diff --git a/[refs] b/[refs] index ccffbd3ad2f7..1cf9bc680ea2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: b09a75fc5e77b7c58d097236f89b1ff72dcdb562 +refs/heads/master: 7c329288d72e025db4feac65f0fed95fb3e3ef1c diff --git a/trunk/Documentation/ABI/stable/sysfs-class-backlight b/trunk/Documentation/ABI/stable/sysfs-class-backlight deleted file mode 100644 index 4d637e1c4ff7..000000000000 --- a/trunk/Documentation/ABI/stable/sysfs-class-backlight +++ /dev/null @@ -1,36 +0,0 @@ -What: /sys/class/backlight//bl_power -Date: April 2005 -KernelVersion: 2.6.12 -Contact: Richard Purdie -Description: - Control BACKLIGHT power, values are FB_BLANK_* from fb.h - - FB_BLANK_UNBLANK (0) : power on. - - FB_BLANK_POWERDOWN (4) : power off -Users: HAL - -What: /sys/class/backlight//brightness -Date: April 2005 -KernelVersion: 2.6.12 -Contact: Richard Purdie -Description: - Control the brightness for this . Values - are between 0 and max_brightness. This file will also - show the brightness level stored in the driver, which - may not be the actual brightness (see actual_brightness). -Users: HAL - -What: /sys/class/backlight//actual_brightness -Date: March 2006 -KernelVersion: 2.6.17 -Contact: Richard Purdie -Description: - Show the actual brightness by querying the hardware. -Users: HAL - -What: /sys/class/backlight//max_brightness -Date: April 2005 -KernelVersion: 2.6.12 -Contact: Richard Purdie -Description: - Maximum brightness for . -Users: HAL diff --git a/trunk/Documentation/ABI/testing/sysfs-class-lcd b/trunk/Documentation/ABI/testing/sysfs-class-lcd deleted file mode 100644 index 35906bf7aa70..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-class-lcd +++ /dev/null @@ -1,23 +0,0 @@ -What: /sys/class/lcd//lcd_power -Date: April 2005 -KernelVersion: 2.6.12 -Contact: Richard Purdie -Description: - Control LCD power, values are FB_BLANK_* from fb.h - - FB_BLANK_UNBLANK (0) : power on. - - FB_BLANK_POWERDOWN (4) : power off - -What: /sys/class/lcd//contrast -Date: April 2005 -KernelVersion: 2.6.12 -Contact: Richard Purdie -Description: - Current contrast of this LCD device. Value is between 0 and - /sys/class/lcd//max_contrast. - -What: /sys/class/lcd//max_contrast -Date: April 2005 -KernelVersion: 2.6.12 -Contact: Richard Purdie -Description: - Maximum contrast for this LCD device. diff --git a/trunk/Documentation/ABI/testing/sysfs-class-led b/trunk/Documentation/ABI/testing/sysfs-class-led deleted file mode 100644 index 9e4541d71cb6..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-class-led +++ /dev/null @@ -1,28 +0,0 @@ -What: /sys/class/leds//brightness -Date: March 2006 -KernelVersion: 2.6.17 -Contact: Richard Purdie -Description: - Set the brightness of the LED. Most LEDs don't - have hardware brightness support so will just be turned on for - non-zero brightness settings. The value is between 0 and - /sys/class/leds//max_brightness. - -What: /sys/class/leds//max_brightness -Date: March 2006 -KernelVersion: 2.6.17 -Contact: Richard Purdie -Description: - Maximum brightness level for this led, default is 255 (LED_FULL). - -What: /sys/class/leds//trigger -Date: March 2006 -KernelVersion: 2.6.17 -Contact: Richard Purdie -Description: - Set the trigger for this LED. A trigger is a kernel based source - of led events. - You can change triggers in a similar manner to the way an IO - scheduler is chosen. Trigger specific parameters can appear in - /sys/class/leds/ once a given trigger is selected. - diff --git a/trunk/Documentation/ABI/testing/sysfs-gpio b/trunk/Documentation/ABI/testing/sysfs-gpio index 80f4c94c7bef..8aab8092ad35 100644 --- a/trunk/Documentation/ABI/testing/sysfs-gpio +++ b/trunk/Documentation/ABI/testing/sysfs-gpio @@ -19,7 +19,6 @@ Description: /gpioN ... for each exported GPIO #N /value ... always readable, writes fail for input GPIOs /direction ... r/w as: in, out (default low); write: high, low - /edge ... r/w as: none, falling, rising, both /gpiochipN ... for each gpiochip; #N is its first GPIO /base ... (r/o) same as N /label ... (r/o) descriptive, not necessarily unique diff --git a/trunk/Documentation/ABI/testing/sysfs-platform-asus-laptop b/trunk/Documentation/ABI/testing/sysfs-platform-asus-laptop deleted file mode 100644 index a1cb660c50cf..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-platform-asus-laptop +++ /dev/null @@ -1,52 +0,0 @@ -What: /sys/devices/platform/asus-laptop/display -Date: January 2007 -KernelVersion: 2.6.20 -Contact: "Corentin Chary" -Description: - This file allows display switching. The value - is composed by 4 bits and defined as follow: - 4321 - |||`- LCD - ||`-- CRT - |`--- TV - `---- DVI - Ex: - 0 (0000b) means no display - - 3 (0011b) CRT+LCD. - -What: /sys/devices/platform/asus-laptop/gps -Date: January 2007 -KernelVersion: 2.6.20 -Contact: "Corentin Chary" -Description: - Control the gps device. 1 means on, 0 means off. -Users: Lapsus - -What: /sys/devices/platform/asus-laptop/ledd -Date: January 2007 -KernelVersion: 2.6.20 -Contact: "Corentin Chary" -Description: - Some models like the W1N have a LED display that can be - used to display several informations. - To control the LED display, use the following : - echo 0x0T000DDD > /sys/devices/platform/asus-laptop/ - where T control the 3 letters display, and DDD the 3 digits display. - The DDD table can be found in Documentation/laptops/asus-laptop.txt - -What: /sys/devices/platform/asus-laptop/bluetooth -Date: January 2007 -KernelVersion: 2.6.20 -Contact: "Corentin Chary" -Description: - Control the bluetooth device. 1 means on, 0 means off. - This may control the led, the device or both. -Users: Lapsus - -What: /sys/devices/platform/asus-laptop/wlan -Date: January 2007 -KernelVersion: 2.6.20 -Contact: "Corentin Chary" -Description: - Control the bluetooth device. 1 means on, 0 means off. - This may control the led, the device or both. -Users: Lapsus diff --git a/trunk/Documentation/ABI/testing/sysfs-platform-eeepc-laptop b/trunk/Documentation/ABI/testing/sysfs-platform-eeepc-laptop deleted file mode 100644 index 7445dfb321b5..000000000000 --- a/trunk/Documentation/ABI/testing/sysfs-platform-eeepc-laptop +++ /dev/null @@ -1,50 +0,0 @@ -What: /sys/devices/platform/eeepc-laptop/disp -Date: May 2008 -KernelVersion: 2.6.26 -Contact: "Corentin Chary" -Description: - This file allows display switching. - - 1 = LCD - - 2 = CRT - - 3 = LCD+CRT - If you run X11, you should use xrandr instead. - -What: /sys/devices/platform/eeepc-laptop/camera -Date: May 2008 -KernelVersion: 2.6.26 -Contact: "Corentin Chary" -Description: - Control the camera. 1 means on, 0 means off. - -What: /sys/devices/platform/eeepc-laptop/cardr -Date: May 2008 -KernelVersion: 2.6.26 -Contact: "Corentin Chary" -Description: - Control the card reader. 1 means on, 0 means off. - -What: /sys/devices/platform/eeepc-laptop/cpufv -Date: Jun 2009 -KernelVersion: 2.6.31 -Contact: "Corentin Chary" -Description: - Change CPU clock configuration. - On the Eee PC 1000H there are three available clock configuration: - * 0 -> Super Performance Mode - * 1 -> High Performance Mode - * 2 -> Power Saving Mode - On Eee PC 701 there is only 2 available clock configurations. - Available configuration are listed in available_cpufv file. - Reading this file will show the raw hexadecimal value which - is defined as follow: - | 8 bit | 8 bit | - | `---- Current mode - `------------ Availables modes - For example, 0x301 means: mode 1 selected, 3 available modes. - -What: /sys/devices/platform/eeepc-laptop/available_cpufv -Date: Jun 2009 -KernelVersion: 2.6.31 -Contact: "Corentin Chary" -Description: - List available cpufv modes. diff --git a/trunk/Documentation/Intel-IOMMU.txt b/trunk/Documentation/Intel-IOMMU.txt index cf9431db8731..21bc416d887e 100644 --- a/trunk/Documentation/Intel-IOMMU.txt +++ b/trunk/Documentation/Intel-IOMMU.txt @@ -56,7 +56,11 @@ Graphics Problems? ------------------ If you encounter issues with graphics devices, you can try adding option intel_iommu=igfx_off to turn off the integrated graphics engine. -If this fixes anything, please ensure you file a bug reporting the problem. + +If it happens to be a PCI device included in the INCLUDE_ALL Engine, +then try enabling CONFIG_DMAR_GFX_WA to setup a 1-1 map. We hear +graphics drivers may be in process of using DMA api's in the near +future and at that time this option can be yanked out. Some exceptions to IOVA ----------------------- diff --git a/trunk/Documentation/accounting/getdelays.c b/trunk/Documentation/accounting/getdelays.c index 6e25c2659e0a..aa73e72fd793 100644 --- a/trunk/Documentation/accounting/getdelays.c +++ b/trunk/Documentation/accounting/getdelays.c @@ -116,7 +116,7 @@ static int create_nl_socket(int protocol) } -static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, +int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, __u8 genl_cmd, __u16 nla_type, void *nla_data, int nla_len) { @@ -160,7 +160,7 @@ static int send_cmd(int sd, __u16 nlmsg_type, __u32 nlmsg_pid, * Probe the controller in genetlink to find the family id * for the TASKSTATS family */ -static int get_family_id(int sd) +int get_family_id(int sd) { struct { struct nlmsghdr n; @@ -190,7 +190,7 @@ static int get_family_id(int sd) return id; } -static void print_delayacct(struct taskstats *t) +void print_delayacct(struct taskstats *t) { printf("\n\nCPU %15s%15s%15s%15s\n" " %15llu%15llu%15llu%15llu\n" @@ -216,7 +216,7 @@ static void print_delayacct(struct taskstats *t) (unsigned long long)t->freepages_delay_total); } -static void task_context_switch_counts(struct taskstats *t) +void task_context_switch_counts(struct taskstats *t) { printf("\n\nTask %15s%15s\n" " %15llu%15llu\n", @@ -224,7 +224,7 @@ static void task_context_switch_counts(struct taskstats *t) (unsigned long long)t->nvcsw, (unsigned long long)t->nivcsw); } -static void print_cgroupstats(struct cgroupstats *c) +void print_cgroupstats(struct cgroupstats *c) { printf("sleeping %llu, blocked %llu, running %llu, stopped %llu, " "uninterruptible %llu\n", (unsigned long long)c->nr_sleeping, @@ -235,7 +235,7 @@ static void print_cgroupstats(struct cgroupstats *c) } -static void print_ioacct(struct taskstats *t) +void print_ioacct(struct taskstats *t) { printf("%s: read=%llu, write=%llu, cancelled_write=%llu\n", t->ac_comm, diff --git a/trunk/Documentation/auxdisplay/cfag12864b-example.c b/trunk/Documentation/auxdisplay/cfag12864b-example.c index 1d2c010bae12..2caeea5e4993 100644 --- a/trunk/Documentation/auxdisplay/cfag12864b-example.c +++ b/trunk/Documentation/auxdisplay/cfag12864b-example.c @@ -62,7 +62,7 @@ unsigned char cfag12864b_buffer[CFAG12864B_SIZE]; * Unable to open: return = -1 * Unable to mmap: return = -2 */ -static int cfag12864b_init(char *path) +int cfag12864b_init(char *path) { cfag12864b_fd = open(path, O_RDWR); if (cfag12864b_fd == -1) @@ -81,7 +81,7 @@ static int cfag12864b_init(char *path) /* * exit a cfag12864b framebuffer device */ -static void cfag12864b_exit(void) +void cfag12864b_exit(void) { munmap(cfag12864b_mem, CFAG12864B_SIZE); close(cfag12864b_fd); @@ -90,7 +90,7 @@ static void cfag12864b_exit(void) /* * set (x, y) pixel */ -static void cfag12864b_set(unsigned char x, unsigned char y) +void cfag12864b_set(unsigned char x, unsigned char y) { if (CFAG12864B_CHECK(x, y)) cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] |= @@ -100,7 +100,7 @@ static void cfag12864b_set(unsigned char x, unsigned char y) /* * unset (x, y) pixel */ -static void cfag12864b_unset(unsigned char x, unsigned char y) +void cfag12864b_unset(unsigned char x, unsigned char y) { if (CFAG12864B_CHECK(x, y)) cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] &= @@ -113,7 +113,7 @@ static void cfag12864b_unset(unsigned char x, unsigned char y) * Pixel off: return = 0 * Pixel on: return = 1 */ -static unsigned char cfag12864b_isset(unsigned char x, unsigned char y) +unsigned char cfag12864b_isset(unsigned char x, unsigned char y) { if (CFAG12864B_CHECK(x, y)) if (cfag12864b_buffer[CFAG12864B_ADDRESS(x, y)] & @@ -126,7 +126,7 @@ static unsigned char cfag12864b_isset(unsigned char x, unsigned char y) /* * not (x, y) pixel */ -static void cfag12864b_not(unsigned char x, unsigned char y) +void cfag12864b_not(unsigned char x, unsigned char y) { if (cfag12864b_isset(x, y)) cfag12864b_unset(x, y); @@ -137,7 +137,7 @@ static void cfag12864b_not(unsigned char x, unsigned char y) /* * fill (set all pixels) */ -static void cfag12864b_fill(void) +void cfag12864b_fill(void) { unsigned short i; @@ -148,7 +148,7 @@ static void cfag12864b_fill(void) /* * clear (unset all pixels) */ -static void cfag12864b_clear(void) +void cfag12864b_clear(void) { unsigned short i; @@ -162,7 +162,7 @@ static void cfag12864b_clear(void) * Pixel off: src[i] = 0 * Pixel on: src[i] > 0 */ -static void cfag12864b_format(unsigned char * matrix) +void cfag12864b_format(unsigned char * matrix) { unsigned char i, j, n; @@ -182,7 +182,7 @@ static void cfag12864b_format(unsigned char * matrix) /* * blit buffer to lcd */ -static void cfag12864b_blit(void) +void cfag12864b_blit(void) { memcpy(cfag12864b_mem, cfag12864b_buffer, CFAG12864B_SIZE); } @@ -198,7 +198,7 @@ static void cfag12864b_blit(void) #define EXAMPLES 6 -static void example(unsigned char n) +void example(unsigned char n) { unsigned short i, j; unsigned char matrix[CFAG12864B_WIDTH * CFAG12864B_HEIGHT]; diff --git a/trunk/Documentation/fb/ep93xx-fb.txt b/trunk/Documentation/fb/ep93xx-fb.txt deleted file mode 100644 index 5af1bd9effae..000000000000 --- a/trunk/Documentation/fb/ep93xx-fb.txt +++ /dev/null @@ -1,135 +0,0 @@ -================================ -Driver for EP93xx LCD controller -================================ - -The EP93xx LCD controller can drive both standard desktop monitors and -embedded LCD displays. If you have a standard desktop monitor then you -can use the standard Linux video mode database. In your board file: - - static struct ep93xxfb_mach_info some_board_fb_info = { - .num_modes = EP93XXFB_USE_MODEDB, - .bpp = 16, - }; - -If you have an embedded LCD display then you need to define a video -mode for it as follows: - - static struct fb_videomode some_board_video_modes[] = { - { - .name = "some_lcd_name", - /* Pixel clock, porches, etc */ - }, - }; - -Note that the pixel clock value is in pico-seconds. You can use the -KHZ2PICOS macro to convert the pixel clock value. Most other values -are in pixel clocks. See Documentation/fb/framebuffer.txt for further -details. - -The ep93xxfb_mach_info structure for your board should look like the -following: - - static struct ep93xxfb_mach_info some_board_fb_info = { - .num_modes = ARRAY_SIZE(some_board_video_modes), - .modes = some_board_video_modes, - .default_mode = &some_board_video_modes[0], - .bpp = 16, - }; - -The framebuffer device can be registered by adding the following to -your board initialisation function: - - ep93xx_register_fb(&some_board_fb_info); - -===================== -Video Attribute Flags -===================== - -The ep93xxfb_mach_info structure has a flags field which can be used -to configure the controller. The video attributes flags are fully -documented in section 7 of the EP93xx users' guide. The following -flags are available: - -EP93XXFB_PCLK_FALLING Clock data on the falling edge of the - pixel clock. The default is to clock - data on the rising edge. - -EP93XXFB_SYNC_BLANK_HIGH Blank signal is active high. By - default the blank signal is active low. - -EP93XXFB_SYNC_HORIZ_HIGH Horizontal sync is active high. By - default the horizontal sync is active low. - -EP93XXFB_SYNC_VERT_HIGH Vertical sync is active high. By - default the vertical sync is active high. - -The physical address of the framebuffer can be controlled using the -following flags: - -EP93XXFB_USE_SDCSN0 Use SDCSn[0] for the framebuffer. This - is the default setting. - -EP93XXFB_USE_SDCSN1 Use SDCSn[1] for the framebuffer. - -EP93XXFB_USE_SDCSN2 Use SDCSn[2] for the framebuffer. - -EP93XXFB_USE_SDCSN3 Use SDCSn[3] for the framebuffer. - -================== -Platform callbacks -================== - -The EP93xx framebuffer driver supports three optional platform -callbacks: setup, teardown and blank. The setup and teardown functions -are called when the framebuffer driver is installed and removed -respectively. The blank function is called whenever the display is -blanked or unblanked. - -The setup and teardown devices pass the platform_device structure as -an argument. The fb_info and ep93xxfb_mach_info structures can be -obtained as follows: - - static int some_board_fb_setup(struct platform_device *pdev) - { - struct ep93xxfb_mach_info *mach_info = pdev->dev.platform_data; - struct fb_info *fb_info = platform_get_drvdata(pdev); - - /* Board specific framebuffer setup */ - } - -====================== -Setting the video mode -====================== - -The video mode is set using the following syntax: - - video=XRESxYRES[-BPP][@REFRESH] - -If the EP93xx video driver is built-in then the video mode is set on -the Linux kernel command line, for example: - - video=ep93xx-fb:800x600-16@60 - -If the EP93xx video driver is built as a module then the video mode is -set when the module is installed: - - modprobe ep93xx-fb video=320x240 - -============== -Screenpage bug -============== - -At least on the EP9315 there is a silicon bug which causes bit 27 of -the VIDSCRNPAGE (framebuffer physical offset) to be tied low. There is -an unofficial errata for this bug at: - http://marc.info/?l=linux-arm-kernel&m=110061245502000&w=2 - -By default the EP93xx framebuffer driver checks if the allocated physical -address has bit 27 set. If it does, then the memory is freed and an -error is returned. The check can be disabled by adding the following -option when loading the driver: - - ep93xx-fb.check_screenpage_bug=0 - -In some cases it may be possible to reconfigure your SDRAM layout to -avoid this bug. See section 13 of the EP93xx users' guide for details. diff --git a/trunk/Documentation/fb/matroxfb.txt b/trunk/Documentation/fb/matroxfb.txt index e5ce8a1a978b..ad7a67707d62 100644 --- a/trunk/Documentation/fb/matroxfb.txt +++ b/trunk/Documentation/fb/matroxfb.txt @@ -186,7 +186,9 @@ noinverse - show true colors on screen. It is default. dev:X - bind driver to device X. Driver numbers device from 0 up to N, where device 0 is first `known' device found, 1 second and so on. lspci lists devices in this order. - Default is `every' known device. + Default is `every' known device for driver with multihead support + and first working device (usually dev:0) for driver without + multihead support. nohwcursor - disables hardware cursor (use software cursor instead). hwcursor - enables hardware cursor. It is default. If you are using non-accelerated mode (`noaccel' or `fbset -accel false'), software diff --git a/trunk/Documentation/filesystems/ncpfs.txt b/trunk/Documentation/filesystems/ncpfs.txt index 5af164f4b37b..f12c30c93f2f 100644 --- a/trunk/Documentation/filesystems/ncpfs.txt +++ b/trunk/Documentation/filesystems/ncpfs.txt @@ -7,6 +7,6 @@ ftp.gwdg.de/pub/linux/misc/ncpfs, but sunsite and its many mirrors will have it as well. Related products are linware and mars_nwe, which will give Linux partial -NetWare server functionality. - -mars_nwe can be found on ftp.gwdg.de/pub/linux/misc/ncpfs. +NetWare server functionality. Linware's home site is +klokan.sh.cvut.cz/pub/linux/linware; mars_nwe can be found on +ftp.gwdg.de/pub/linux/misc/ncpfs. diff --git a/trunk/Documentation/filesystems/proc.txt b/trunk/Documentation/filesystems/proc.txt index b5aee7838a00..75988ba26a51 100644 --- a/trunk/Documentation/filesystems/proc.txt +++ b/trunk/Documentation/filesystems/proc.txt @@ -176,7 +176,6 @@ read the file /proc/PID/status: CapBnd: ffffffffffffffff voluntary_ctxt_switches: 0 nonvoluntary_ctxt_switches: 1 - Stack usage: 12 kB This shows you nearly the same information you would get if you viewed it with the ps command. In fact, ps uses the proc file system to obtain its @@ -230,7 +229,6 @@ Table 1-2: Contents of the statm files (as of 2.6.30-rc7) Mems_allowed_list Same as previous, but in "list format" voluntary_ctxt_switches number of voluntary context switches nonvoluntary_ctxt_switches number of non voluntary context switches - Stack usage: stack usage high water mark (round up to page size) .............................................................................. Table 1-3: Contents of the statm files (as of 2.6.8-rc3) @@ -309,7 +307,7 @@ address perms offset dev inode pathname 08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test 0804a000-0806b000 rw-p 00000000 00:00 0 [heap] a7cb1000-a7cb2000 ---p 00000000 00:00 0 -a7cb2000-a7eb2000 rw-p 00000000 00:00 0 [threadstack:001ff4b4] +a7cb2000-a7eb2000 rw-p 00000000 00:00 0 a7eb2000-a7eb3000 ---p 00000000 00:00 0 a7eb3000-a7ed5000 rw-p 00000000 00:00 0 a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 @@ -345,7 +343,6 @@ is not associated with a file: [stack] = the stack of the main process [vdso] = the "virtual dynamic shared object", the kernel system call handler - [threadstack:xxxxxxxx] = the stack of the thread, xxxxxxxx is the stack size or if empty, the mapping is anonymous. diff --git a/trunk/Documentation/gpio.txt b/trunk/Documentation/gpio.txt index fa4dc077ae0e..e4b6985044a2 100644 --- a/trunk/Documentation/gpio.txt +++ b/trunk/Documentation/gpio.txt @@ -524,13 +524,6 @@ and have the following read/write attributes: is configured as an output, this value may be written; any nonzero value is treated as high. - "edge" ... reads as either "none", "rising", "falling", or - "both". Write these strings to select the signal edge(s) - that will make poll(2) on the "value" file return. - - This file exists only if the pin can be configured as an - interrupt generating input pin. - GPIO controllers have paths like /sys/class/gpio/chipchip42/ (for the controller implementing GPIOs starting at #42) and have the following read-only attributes: @@ -562,11 +555,6 @@ requested using gpio_request(): /* reverse gpio_export() */ void gpio_unexport(); - /* create a sysfs link to an exported GPIO node */ - int gpio_export_link(struct device *dev, const char *name, - unsigned gpio) - - After a kernel driver requests a GPIO, it may only be made available in the sysfs interface by gpio_export(). The driver can control whether the signal direction may change. This helps drivers prevent userspace code @@ -575,8 +563,3 @@ from accidentally clobbering important system state. This explicit exporting can help with debugging (by making some kinds of experiments easier), or can provide an always-there interface that's suitable for documenting as part of a board support package. - -After the GPIO has been exported, gpio_export_link() allows creating -symlinks from elsewhere in sysfs to the GPIO sysfs node. Drivers can -use this to provide the interface under their own device in sysfs with -a descriptive name. diff --git a/trunk/Documentation/hwmon/acpi_power_meter b/trunk/Documentation/hwmon/acpi_power_meter deleted file mode 100644 index c80399a00c50..000000000000 --- a/trunk/Documentation/hwmon/acpi_power_meter +++ /dev/null @@ -1,51 +0,0 @@ -Kernel driver power_meter -========================= - -This driver talks to ACPI 4.0 power meters. - -Supported systems: - * Any recent system with ACPI 4.0. - Prefix: 'power_meter' - Datasheet: http://acpi.info/, section 10.4. - -Author: Darrick J. Wong - -Description ------------ - -This driver implements sensor reading support for the power meters exposed in -the ACPI 4.0 spec (Chapter 10.4). These devices have a simple set of -features--a power meter that returns average power use over a configurable -interval, an optional capping mechanism, and a couple of trip points. The -sysfs interface conforms with the specification outlined in the "Power" section -of Documentation/hwmon/sysfs-interface. - -Special Features ----------------- - -The power[1-*]_is_battery knob indicates if the power supply is a battery. -Both power[1-*]_average_{min,max} must be set before the trip points will work. -When both of them are set, an ACPI event will be broadcast on the ACPI netlink -socket and a poll notification will be sent to the appropriate -power[1-*]_average sysfs file. - -The power[1-*]_{model_number, serial_number, oem_info} fields display arbitrary -strings that ACPI provides with the meter. The measures/ directory contains -symlinks to the devices that this meter measures. - -Some computers have the ability to enforce a power cap in hardware. If this is -the case, the power[1-*]_cap and related sysfs files will appear. When the -average power consumption exceeds the cap, an ACPI event will be broadcast on -the netlink event socket and a poll notification will be sent to the -appropriate power[1-*]_alarm file to indicate that capping has begun, and the -hardware has taken action to reduce power consumption. Most likely this will -result in reduced performance. - -There are a few other ACPI notifications that can be sent by the firmware. In -all cases the ACPI event will be broadcast on the ACPI netlink event socket as -well as sent as a poll notification to a sysfs file. The events are as -follows: - -power[1-*]_cap will be notified if the firmware changes the power cap. -power[1-*]_interval will be notified if the firmware changes the averaging -interval. diff --git a/trunk/Documentation/i2c/busses/i2c-piix4 b/trunk/Documentation/i2c/busses/i2c-piix4 index c5b37c570554..f889481762b5 100644 --- a/trunk/Documentation/i2c/busses/i2c-piix4 +++ b/trunk/Documentation/i2c/busses/i2c-piix4 @@ -8,8 +8,6 @@ Supported adapters: Datasheet: Only available via NDA from ServerWorks * ATI IXP200, IXP300, IXP400, SB600, SB700 and SB800 southbridges Datasheet: Not publicly available - * AMD SB900 - Datasheet: Not publicly available * Standard Microsystems (SMSC) SLC90E66 (Victory66) southbridge Datasheet: Publicly available at the SMSC website http://www.smsc.com diff --git a/trunk/Documentation/i2c/chips/pca9539 b/trunk/Documentation/i2c/chips/pca9539 new file mode 100644 index 000000000000..6aff890088b1 --- /dev/null +++ b/trunk/Documentation/i2c/chips/pca9539 @@ -0,0 +1,58 @@ +Kernel driver pca9539 +===================== + +NOTE: this driver is deprecated and will be dropped soon, use +drivers/gpio/pca9539.c instead. + +Supported chips: + * Philips PCA9539 + Prefix: 'pca9539' + Addresses scanned: none + Datasheet: + http://www.semiconductors.philips.com/acrobat/datasheets/PCA9539_2.pdf + +Author: Ben Gardner + + +Description +----------- + +The Philips PCA9539 is a 16 bit low power I/O device. +All 16 lines can be individually configured as an input or output. +The input sense can also be inverted. +The 16 lines are split between two bytes. + + +Detection +--------- + +The PCA9539 is difficult to detect and not commonly found in PC machines, +so you have to pass the I2C bus and address of the installed PCA9539 +devices explicitly to the driver at load time via the force=... parameter. + + +Sysfs entries +------------- + +Each is a byte that maps to the 8 I/O bits. +A '0' suffix is for bits 0-7, while '1' is for bits 8-15. + +input[01] - read the current value +output[01] - sets the output value +direction[01] - direction of each bit: 1=input, 0=output +invert[01] - toggle the input bit sense + +input reads the actual state of the line and is always available. +The direction defaults to input for all channels. + + +General Remarks +--------------- + +Note that each output, direction, and invert entry controls 8 lines. +You should use the read, modify, write sequence. +For example. to set output bit 0 of 1. + val=$(cat output0) + val=$(( $val | 1 )) + echo $val > output0 + diff --git a/trunk/Documentation/i2c/chips/pcf8574 b/trunk/Documentation/i2c/chips/pcf8574 new file mode 100644 index 000000000000..235815c075ff --- /dev/null +++ b/trunk/Documentation/i2c/chips/pcf8574 @@ -0,0 +1,65 @@ +Kernel driver pcf8574 +===================== + +Supported chips: + * Philips PCF8574 + Prefix: 'pcf8574' + Addresses scanned: none + Datasheet: Publicly available at the Philips Semiconductors website + http://www.semiconductors.philips.com/pip/PCF8574P.html + + * Philips PCF8574A + Prefix: 'pcf8574a' + Addresses scanned: none + Datasheet: Publicly available at the Philips Semiconductors website + http://www.semiconductors.philips.com/pip/PCF8574P.html + +Authors: + Frodo Looijaard , + Philip Edelbrock , + Dan Eaton , + Aurelien Jarno , + Jean Delvare , + + +Description +----------- +The PCF8574(A) is an 8-bit I/O expander for the I2C bus produced by Philips +Semiconductors. It is designed to provide a byte I2C interface to up to 16 +separate devices (8 x PCF8574 and 8 x PCF8574A). + +This device consists of a quasi-bidirectional port. Each of the eight I/Os +can be independently used as an input or output. To setup an I/O as an +input, you have to write a 1 to the corresponding output. + +For more informations see the datasheet. + + +Accessing PCF8574(A) via /sys interface +------------------------------------- + +The PCF8574(A) is plainly impossible to detect ! Stupid chip. +So, you have to pass the I2C bus and address of the installed PCF857A +and PCF8574A devices explicitly to the driver at load time via the +force=... parameter. + +On detection (i.e. insmod, modprobe et al.), directories are being +created for each detected PCF8574(A): + +/sys/bus/i2c/devices/<0>-<1>/ +where <0> is the bus the chip was detected on (e. g. i2c-0) +and <1> the chip address ([20..27] or [38..3f]): + +(example: /sys/bus/i2c/devices/1-0020/) + +Inside these directories, there are two files each: +read and write (and one file with chip name). + +The read file is read-only. Reading gives you the current I/O input +if the corresponding output is set as 1, otherwise the current output +value, that is to say 0. + +The write file is read/write. Writing a value outputs it on the I/O +port. Reading returns the last written value. As it is not possible +to read this value from the chip, you need to write at least once to +this file before you can read back from it. diff --git a/trunk/Documentation/i2c/chips/pcf8575 b/trunk/Documentation/i2c/chips/pcf8575 new file mode 100644 index 000000000000..40b268eb276f --- /dev/null +++ b/trunk/Documentation/i2c/chips/pcf8575 @@ -0,0 +1,69 @@ +About the PCF8575 chip and the pcf8575 kernel driver +==================================================== + +The PCF8575 chip is produced by the following manufacturers: + + * Philips NXP + http://www.nxp.com/#/pip/cb=[type=product,path=50807/41735/41850,final=PCF8575_3]|pip=[pip=PCF8575_3][0] + + * Texas Instruments + http://focus.ti.com/docs/prod/folders/print/pcf8575.html + + +Some vendors sell small PCB's with the PCF8575 mounted on it. You can connect +such a board to a Linux host via e.g. an USB to I2C interface. Examples of +PCB boards with a PCF8575: + + * SFE Breakout Board for PCF8575 I2C Expander by RobotShop + http://www.robotshop.ca/home/products/robot-parts/electronics/adapters-converters/sfe-pcf8575-i2c-expander-board.html + + * Breakout Board for PCF8575 I2C Expander by Spark Fun Electronics + http://www.sparkfun.com/commerce/product_info.php?products_id=8130 + + +Description +----------- +The PCF8575 chip is a 16-bit I/O expander for the I2C bus. Up to eight of +these chips can be connected to the same I2C bus. You can find this +chip on some custom designed hardware, but you won't find it on PC +motherboards. + +The PCF8575 chip consists of a 16-bit quasi-bidirectional port and an I2C-bus +interface. Each of the sixteen I/O's can be independently used as an input or +an output. To set up an I/O pin as an input, you have to write a 1 to the +corresponding output. + +For more information please see the datasheet. + + +Detection +--------- + +There is no method known to detect whether a chip on a given I2C address is +a PCF8575 or whether it is any other I2C device, so you have to pass the I2C +bus and address of the installed PCF8575 devices explicitly to the driver at +load time via the force=... parameter. + +/sys interface +-------------- + +For each address on which a PCF8575 chip was found or forced the following +files will be created under /sys: +* /sys/bus/i2c/devices/-
/read +* /sys/bus/i2c/devices/-
/write +where bus is the I2C bus number (0, 1, ...) and address is the four-digit +hexadecimal representation of the 7-bit I2C address of the PCF8575 +(0020 .. 0027). + +The read file is read-only. Reading it will trigger an I2C read and will hence +report the current input state for the pins configured as inputs, and the +current output value for the pins configured as outputs. + +The write file is read-write. Writing a value to it will configure all pins +as output for which the corresponding bit is zero. Reading the write file will +return the value last written, or -EAGAIN if no value has yet been written to +the write file. + +On module initialization the configuration of the chip is not changed -- the +chip is left in the state it was already configured in through either power-up +or through previous I2C write actions. diff --git a/trunk/Documentation/ia64/aliasing-test.c b/trunk/Documentation/ia64/aliasing-test.c index 3dfb76ca6931..d23610fb2ff9 100644 --- a/trunk/Documentation/ia64/aliasing-test.c +++ b/trunk/Documentation/ia64/aliasing-test.c @@ -24,7 +24,7 @@ int sum; -static int map_mem(char *path, off_t offset, size_t length, int touch) +int map_mem(char *path, off_t offset, size_t length, int touch) { int fd, rc; void *addr; @@ -62,7 +62,7 @@ static int map_mem(char *path, off_t offset, size_t length, int touch) return 0; } -static int scan_tree(char *path, char *file, off_t offset, size_t length, int touch) +int scan_tree(char *path, char *file, off_t offset, size_t length, int touch) { struct dirent **namelist; char *name, *path2; @@ -119,7 +119,7 @@ static int scan_tree(char *path, char *file, off_t offset, size_t length, int to char buf[1024]; -static int read_rom(char *path) +int read_rom(char *path) { int fd, rc; size_t size = 0; @@ -146,7 +146,7 @@ static int read_rom(char *path) return size; } -static int scan_rom(char *path, char *file) +int scan_rom(char *path, char *file) { struct dirent **namelist; char *name, *path2; diff --git a/trunk/Documentation/kernel-parameters.txt b/trunk/Documentation/kernel-parameters.txt index 6fa7292947e5..c363840cdcea 100644 --- a/trunk/Documentation/kernel-parameters.txt +++ b/trunk/Documentation/kernel-parameters.txt @@ -671,7 +671,7 @@ and is between 256 and 4096 characters. It is defined in the file earlyprintk= [X86,SH,BLACKFIN] earlyprintk=vga earlyprintk=serial[,ttySn[,baudrate]] - earlyprintk=dbgp[debugController#] + earlyprintk=dbgp Append ",keep" to not disable it when the real console takes over. diff --git a/trunk/Documentation/laptops/asus-laptop.txt b/trunk/Documentation/laptops/asus-laptop.txt deleted file mode 100644 index c1c5be84e4b1..000000000000 --- a/trunk/Documentation/laptops/asus-laptop.txt +++ /dev/null @@ -1,258 +0,0 @@ -Asus Laptop Extras - -Version 0.1 -August 6, 2009 - -Corentin Chary -http://acpi4asus.sf.net/ - - This driver provides support for extra features of ACPI-compatible ASUS laptops. - It may also support some MEDION, JVC or VICTOR laptops (such as MEDION 9675 or - VICTOR XP7210 for example). It makes all the extra buttons generate standard - ACPI events that go through /proc/acpi/events and input events (like keyboards). - On some models adds support for changing the display brightness and output, - switching the LCD backlight on and off, and most importantly, allows you to - blink those fancy LEDs intended for reporting mail and wireless status. - -This driver supercedes the old asus_acpi driver. - -Requirements ------------- - - Kernel 2.6.X sources, configured for your computer, with ACPI support. - You also need CONFIG_INPUT and CONFIG_ACPI. - -Status ------- - - The features currently supported are the following (see below for - detailed description): - - - Fn key combinations - - Bluetooth enable and disable - - Wlan enable and disable - - GPS enable and disable - - Video output switching - - Ambient Light Sensor on and off - - LED control - - LED Display control - - LCD brightness control - - LCD on and off - - A compatibility table by model and feature is maintained on the web - site, http://acpi4asus.sf.net/. - -Usage ------ - - Try "modprobe asus_acpi". Check your dmesg (simply type dmesg). You should - see some lines like this : - - Asus Laptop Extras version 0.42 - L2D model detected. - - If it is not the output you have on your laptop, send it (and the laptop's - DSDT) to me. - - That's all, now, all the events generated by the hotkeys of your laptop - should be reported in your /proc/acpi/event entry. You can check with - "acpi_listen". - - Hotkeys are also reported as input keys (like keyboards) you can check - which key are supported using "xev" under X11. - - You can get informations on the version of your DSDT table by reading the - /sys/devices/platform/asus-laptop/infos entry. If you have a question or a - bug report to do, please include the output of this entry. - -LEDs ----- - - You can modify LEDs be echoing values to /sys/class/leds/asus::*/brightness : - echo 1 > /sys/class/leds/asus::mail/brightness - will switch the mail LED on. - You can also know if they are on/off by reading their content and use - kernel triggers like ide-disk or heartbeat. - -Backlight ---------- - - You can control lcd backlight power and brightness with - /sys/class/backlight/asus-laptop/. Brightness Values are between 0 and 15. - -Wireless devices ---------------- - - You can turn the internal Bluetooth adapter on/off with the bluetooth entry - (only on models with Bluetooth). This usually controls the associated LED. - Same for Wlan adapter. - -Display switching ------------------ - - Note: the display switching code is currently considered EXPERIMENTAL. - - Switching works for the following models: - L3800C - A2500H - L5800C - M5200N - W1000N (albeit with some glitches) - M6700R - A6JC - F3J - - Switching doesn't work for the following: - M3700N - L2X00D (locks the laptop under certain conditions) - - To switch the displays, echo values from 0 to 15 to - /sys/devices/platform/asus-laptop/display. The significance of those values - is as follows: - - +-------+-----+-----+-----+-----+-----+ - | Bin | Val | DVI | TV | CRT | LCD | - +-------+-----+-----+-----+-----+-----+ - + 0000 + 0 + + + + + - +-------+-----+-----+-----+-----+-----+ - + 0001 + 1 + + + + X + - +-------+-----+-----+-----+-----+-----+ - + 0010 + 2 + + + X + + - +-------+-----+-----+-----+-----+-----+ - + 0011 + 3 + + + X + X + - +-------+-----+-----+-----+-----+-----+ - + 0100 + 4 + + X + + + - +-------+-----+-----+-----+-----+-----+ - + 0101 + 5 + + X + + X + - +-------+-----+-----+-----+-----+-----+ - + 0110 + 6 + + X + X + + - +-------+-----+-----+-----+-----+-----+ - + 0111 + 7 + + X + X + X + - +-------+-----+-----+-----+-----+-----+ - + 1000 + 8 + X + + + + - +-------+-----+-----+-----+-----+-----+ - + 1001 + 9 + X + + + X + - +-------+-----+-----+-----+-----+-----+ - + 1010 + 10 + X + + X + + - +-------+-----+-----+-----+-----+-----+ - + 1011 + 11 + X + + X + X + - +-------+-----+-----+-----+-----+-----+ - + 1100 + 12 + X + X + + + - +-------+-----+-----+-----+-----+-----+ - + 1101 + 13 + X + X + + X + - +-------+-----+-----+-----+-----+-----+ - + 1110 + 14 + X + X + X + + - +-------+-----+-----+-----+-----+-----+ - + 1111 + 15 + X + X + X + X + - +-------+-----+-----+-----+-----+-----+ - - In most cases, the appropriate displays must be plugged in for the above - combinations to work. TV-Out may need to be initialized at boot time. - - Debugging: - 1) Check whether the Fn+F8 key: - a) does not lock the laptop (try disabling CONFIG_X86_UP_APIC or boot with - noapic / nolapic if it does) - b) generates events (0x6n, where n is the value corresponding to the - configuration above) - c) actually works - Record the disp value at every configuration. - 2) Echo values from 0 to 15 to /sys/devices/platform/asus-laptop/display. - Record its value, note any change. If nothing changes, try a broader range, - up to 65535. - 3) Send ANY output (both positive and negative reports are needed, unless your - machine is already listed above) to the acpi4asus-user mailing list. - - Note: on some machines (e.g. L3C), after the module has been loaded, only 0x6n - events are generated and no actual switching occurs. In such a case, a line - like: - - echo $((10#$arg-60)) > /sys/devices/platform/asus-laptop/display - - will usually do the trick ($arg is the 0000006n-like event passed to acpid). - - Note: there is currently no reliable way to read display status on xxN - (Centrino) models. - -LED display ------------ - - Some models like the W1N have a LED display that can be used to display - several informations. - - LED display works for the following models: - W1000N - W1J - - To control the LED display, use the following : - - echo 0x0T000DDD > /sys/devices/platform/asus-laptop/ - - where T control the 3 letters display, and DDD the 3 digits display, - according to the tables below. - - DDD (digits) - 000 to 999 = display digits - AAA = --- - BBB to FFF = turn-off - - T (type) - 0 = off - 1 = dvd - 2 = vcd - 3 = mp3 - 4 = cd - 5 = tv - 6 = cpu - 7 = vol - - For example "echo 0x01000001 >/sys/devices/platform/asus-laptop/ledd" - would display "DVD001". - -Driver options: ---------------- - - Options can be passed to the asus-laptop driver using the standard - module argument syntax (= when passing the option to the - module or asus-laptop.= on the kernel boot line when - asus-laptop is statically linked into the kernel). - - wapf: WAPF defines the behavior of the Fn+Fx wlan key - The significance of values is yet to be found, but - most of the time: - - 0x0 should do nothing - - 0x1 should allow to control the device with Fn+Fx key. - - 0x4 should send an ACPI event (0x88) while pressing the Fn+Fx key - - 0x5 like 0x1 or 0x4 - - The default value is 0x1. - -Unsupported models ------------------- - - These models will never be supported by this module, as they use a completely - different mechanism to handle LEDs and extra stuff (meaning we have no clue - how it works): - - - ASUS A1300 (A1B), A1370D - - ASUS L7300G - - ASUS L8400 - -Patches, Errors, Questions: --------------------------- - - I appreciate any success or failure - reports, especially if they add to or correct the compatibility table. - Please include the following information in your report: - - - Asus model name - - a copy of your ACPI tables, using the "acpidump" utility - - a copy of /sys/devices/platform/asus-laptop/infos - - which driver features work and which don't - - the observed behavior of non-working features - - Any other comments or patches are also more than welcome. - - acpi4asus-user@lists.sourceforge.net - http://sourceforge.net/projects/acpi4asus - diff --git a/trunk/Documentation/laptops/thinkpad-acpi.txt b/trunk/Documentation/laptops/thinkpad-acpi.txt index 6d03487ef1c7..e2ddcdeb61b6 100644 --- a/trunk/Documentation/laptops/thinkpad-acpi.txt +++ b/trunk/Documentation/laptops/thinkpad-acpi.txt @@ -219,7 +219,7 @@ The following commands can be written to the /proc/acpi/ibm/hotkey file: echo 0xffffffff > /proc/acpi/ibm/hotkey -- enable all hot keys echo 0 > /proc/acpi/ibm/hotkey -- disable all possible hot keys ... any other 8-hex-digit mask ... - echo reset > /proc/acpi/ibm/hotkey -- restore the recommended mask + echo reset > /proc/acpi/ibm/hotkey -- restore the original mask The following commands have been deprecated and will cause the kernel to log a warning: @@ -240,13 +240,9 @@ sysfs notes: Returns 0. hotkey_bios_mask: - DEPRECATED, DON'T USE, WILL BE REMOVED IN THE FUTURE. - Returns the hot keys mask when thinkpad-acpi was loaded. Upon module unload, the hot keys mask will be restored - to this value. This is always 0x80c, because those are - the hotkeys that were supported by ancient firmware - without mask support. + to this value. hotkey_enable: DEPRECATED, WILL BE REMOVED SOON. diff --git a/trunk/Documentation/leds-class.txt b/trunk/Documentation/leds-class.txt index 8fd5ca2ae32d..6399557cdab3 100644 --- a/trunk/Documentation/leds-class.txt +++ b/trunk/Documentation/leds-class.txt @@ -1,4 +1,3 @@ - LED handling under Linux ======================== @@ -6,10 +5,10 @@ If you're reading this and thinking about keyboard leds, these are handled by the input subsystem and the led class is *not* needed. In its simplest form, the LED class just allows control of LEDs from -userspace. LEDs appear in /sys/class/leds/. The maximum brightness of the -LED is defined in max_brightness file. The brightness file will set the brightness -of the LED (taking a value 0-max_brightness). Most LEDs don't have hardware -brightness support so will just be turned on for non-zero brightness settings. +userspace. LEDs appear in /sys/class/leds/. The brightness file will +set the brightness of the LED (taking a value 0-255). Most LEDs don't +have hardware brightness support so will just be turned on for non-zero +brightness settings. The class also introduces the optional concept of an LED trigger. A trigger is a kernel based source of led events. Triggers can either be simple or diff --git a/trunk/Documentation/lguest/lguest.c b/trunk/Documentation/lguest/lguest.c index ba9373f82ab5..950cde6d6e58 100644 --- a/trunk/Documentation/lguest/lguest.c +++ b/trunk/Documentation/lguest/lguest.c @@ -42,7 +42,6 @@ #include #include "linux/lguest_launcher.h" #include "linux/virtio_config.h" -#include #include "linux/virtio_net.h" #include "linux/virtio_blk.h" #include "linux/virtio_console.h" @@ -134,9 +133,6 @@ struct device { /* Is it operational */ bool running; - /* Does Guest want an intrrupt on empty? */ - bool irq_on_empty; - /* Device-specific data. */ void *priv; }; @@ -627,13 +623,10 @@ static void trigger_irq(struct virtqueue *vq) return; vq->pending_used = 0; - /* If they don't want an interrupt, don't send one... */ - if (vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) { - /* ... unless they've asked us to force one on empty. */ - if (!vq->dev->irq_on_empty - || lg_last_avail(vq) != vq->vring.avail->idx) - return; - } + /* If they don't want an interrupt, don't send one, unless empty. */ + if ((vq->vring.avail->flags & VRING_AVAIL_F_NO_INTERRUPT) + && lg_last_avail(vq) != vq->vring.avail->idx) + return; /* Send the Guest an interrupt tell them we used something up. */ if (write(lguest_fd, buf, sizeof(buf)) != 0) @@ -1049,15 +1042,6 @@ static void create_thread(struct virtqueue *vq) close(vq->eventfd); } -static bool accepted_feature(struct device *dev, unsigned int bit) -{ - const u8 *features = get_feature_bits(dev) + dev->feature_len; - - if (dev->feature_len < bit / CHAR_BIT) - return false; - return features[bit / CHAR_BIT] & (1 << (bit % CHAR_BIT)); -} - static void start_device(struct device *dev) { unsigned int i; @@ -1071,8 +1055,6 @@ static void start_device(struct device *dev) verbose(" %02x", get_feature_bits(dev) [dev->feature_len+i]); - dev->irq_on_empty = accepted_feature(dev, VIRTIO_F_NOTIFY_ON_EMPTY); - for (vq = dev->vq; vq; vq = vq->next) { if (vq->service) create_thread(vq); diff --git a/trunk/Documentation/pcmcia/crc32hash.c b/trunk/Documentation/pcmcia/crc32hash.c index 44f8beea7260..4210e5abab8a 100644 --- a/trunk/Documentation/pcmcia/crc32hash.c +++ b/trunk/Documentation/pcmcia/crc32hash.c @@ -8,7 +8,7 @@ #include #include -static unsigned int crc32(unsigned char const *p, unsigned int len) +unsigned int crc32(unsigned char const *p, unsigned int len) { int i; unsigned int crc = 0; diff --git a/trunk/Documentation/power/regulator/design.txt b/trunk/Documentation/power/regulator/design.txt deleted file mode 100644 index f9b56b72b782..000000000000 --- a/trunk/Documentation/power/regulator/design.txt +++ /dev/null @@ -1,33 +0,0 @@ -Regulator API design notes -========================== - -This document provides a brief, partially structured, overview of some -of the design considerations which impact the regulator API design. - -Safety ------- - - - Errors in regulator configuration can have very serious consequences - for the system, potentially including lasting hardware damage. - - It is not possible to automatically determine the power confugration - of the system - software-equivalent variants of the same chip may - have different power requirments, and not all components with power - requirements are visible to software. - - => The API should make no changes to the hardware state unless it has - specific knowledge that these changes are safe to do perform on - this particular system. - -Consumer use cases ------------------- - - - The overwhelming majority of devices in a system will have no - requirement to do any runtime configuration of their power beyond - being able to turn it on or off. - - - Many of the power supplies in the system will be shared between many - different consumers. - - => The consumer API should be structured so that these use cases are - very easy to handle and so that consumers will work with shared - supplies without any additional effort. diff --git a/trunk/Documentation/power/regulator/machine.txt b/trunk/Documentation/power/regulator/machine.txt index 63728fed620b..ce3487d99abe 100644 --- a/trunk/Documentation/power/regulator/machine.txt +++ b/trunk/Documentation/power/regulator/machine.txt @@ -87,7 +87,7 @@ static struct platform_device regulator_devices[] = { }, }; /* register regulator 1 device */ -platform_device_register(®ulator_devices[0]); +platform_device_register(&wm8350_regulator_devices[0]); /* register regulator 2 device */ -platform_device_register(®ulator_devices[1]); +platform_device_register(&wm8350_regulator_devices[1]); diff --git a/trunk/Documentation/power/regulator/overview.txt b/trunk/Documentation/power/regulator/overview.txt index ffd185bb6054..0cded696ca01 100644 --- a/trunk/Documentation/power/regulator/overview.txt +++ b/trunk/Documentation/power/regulator/overview.txt @@ -29,7 +29,7 @@ Some terms used in this document:- o PMIC - Power Management IC. An IC that contains numerous regulators - and often contains other subsystems. + and often contains other susbsystems. o Consumer - Electronic device that is supplied power by a regulator. @@ -168,4 +168,4 @@ relevant to non SoC devices and is split into the following four interfaces:- userspace via sysfs. This could be used to help monitor device power consumption and status. - See Documentation/ABI/testing/sysfs-class-regulator + See Documentation/ABI/testing/regulator-sysfs.txt diff --git a/trunk/Documentation/power/regulator/regulator.txt b/trunk/Documentation/power/regulator/regulator.txt index 3f8b528f237e..4200accb9bba 100644 --- a/trunk/Documentation/power/regulator/regulator.txt +++ b/trunk/Documentation/power/regulator/regulator.txt @@ -10,9 +10,8 @@ Registration Drivers can register a regulator by calling :- -struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, - struct device *dev, struct regulator_init_data *init_data, - void *driver_data); +struct regulator_dev *regulator_register(struct device *dev, + struct regulator_desc *regulator_desc); This will register the regulators capabilities and operations to the regulator core. diff --git a/trunk/Documentation/powerpc/dts-bindings/fsl/esdhc.txt b/trunk/Documentation/powerpc/dts-bindings/fsl/esdhc.txt index 8a0040738969..3ed3797b5086 100644 --- a/trunk/Documentation/powerpc/dts-bindings/fsl/esdhc.txt +++ b/trunk/Documentation/powerpc/dts-bindings/fsl/esdhc.txt @@ -10,8 +10,6 @@ Required properties: - interrupts : should contain eSDHC interrupt. - interrupt-parent : interrupt source phandle. - clock-frequency : specifies eSDHC base clock frequency. - - sdhci,wp-inverted : (optional) specifies that eSDHC controller - reports inverted write-protect state; - sdhci,1-bit-only : (optional) specifies that a controller can only handle 1-bit data transfers. diff --git a/trunk/Documentation/rtc.txt b/trunk/Documentation/rtc.txt index 9104c1062084..8deffcd68cb8 100644 --- a/trunk/Documentation/rtc.txt +++ b/trunk/Documentation/rtc.txt @@ -135,30 +135,6 @@ a high functionality RTC is integrated into the SOC. That system might read the system clock from the discrete RTC, but use the integrated one for all other tasks, because of its greater functionality. -SYSFS INTERFACE ---------------- - -The sysfs interface under /sys/class/rtc/rtcN provides access to various -rtc attributes without requiring the use of ioctls. All dates and times -are in the RTC's timezone, rather than in system time. - -date: RTC-provided date -hctosys: 1 if the RTC provided the system time at boot via the - CONFIG_RTC_HCTOSYS kernel option, 0 otherwise -max_user_freq: The maximum interrupt rate an unprivileged user may request - from this RTC. -name: The name of the RTC corresponding to this sysfs directory -since_epoch: The number of seconds since the epoch according to the RTC -time: RTC-provided time -wakealarm: The time at which the clock will generate a system wakeup - event. This is a one shot wakeup event, so must be reset - after wake if a daily wakeup is required. Format is either - seconds since the epoch or, if there's a leading +, seconds - in the future. - -IOCTL INTERFACE ---------------- - The ioctl() calls supported by /dev/rtc are also supported by the RTC class framework. However, because the chips and systems are not standardized, some PC/AT functionality might not be provided. And in the same way, some @@ -209,8 +185,6 @@ driver returns ENOIOCTLCMD. Some common examples: hardware in the irq_set_freq function. If it isn't, return -EINVAL. If you cannot actually change the frequency, do not define irq_set_freq. - * RTC_PIE_ON, RTC_PIE_OFF: the irq_set_state function will be called. - If all else fails, check out the rtc-test.c driver! diff --git a/trunk/Documentation/spi/spi-summary b/trunk/Documentation/spi/spi-summary index deab51ddc33e..4a02d2508bc8 100644 --- a/trunk/Documentation/spi/spi-summary +++ b/trunk/Documentation/spi/spi-summary @@ -350,7 +350,7 @@ SPI protocol drivers somewhat resemble platform device drivers: .resume = CHIP_resume, }; -The driver core will automatically attempt to bind this driver to any SPI +The driver core will autmatically attempt to bind this driver to any SPI device whose board_info gave a modalias of "CHIP". Your probe() code might look like this unless you're creating a device which is managing a bus (appearing under /sys/class/spi_master). diff --git a/trunk/Documentation/spi/spidev_test.c b/trunk/Documentation/spi/spidev_test.c index 10abd3773e49..c1a5aad3c75a 100644 --- a/trunk/Documentation/spi/spidev_test.c +++ b/trunk/Documentation/spi/spidev_test.c @@ -69,7 +69,7 @@ static void transfer(int fd) puts(""); } -static void print_usage(const char *prog) +void print_usage(const char *prog) { printf("Usage: %s [-DsbdlHOLC3]\n", prog); puts(" -D --device device to use (default /dev/spidev1.1)\n" @@ -85,7 +85,7 @@ static void print_usage(const char *prog) exit(1); } -static void parse_opts(int argc, char *argv[]) +void parse_opts(int argc, char *argv[]) { while (1) { static const struct option lopts[] = { diff --git a/trunk/Documentation/sysctl/kernel.txt b/trunk/Documentation/sysctl/kernel.txt index b3d8b4922740..3e5b63ebb821 100644 --- a/trunk/Documentation/sysctl/kernel.txt +++ b/trunk/Documentation/sysctl/kernel.txt @@ -313,14 +313,6 @@ send before ratelimiting kicks in. ============================================================== -printk_delay: - -Delay each printk message in printk_delay milliseconds - -Value from 0 - 10000 is allowed. - -============================================================== - randomize-va-space: This option can be used to select the type of process address diff --git a/trunk/Documentation/usb/authorization.txt b/trunk/Documentation/usb/authorization.txt index c069b6884c77..381b22ee7834 100644 --- a/trunk/Documentation/usb/authorization.txt +++ b/trunk/Documentation/usb/authorization.txt @@ -16,20 +16,20 @@ Usage: Authorize a device to connect: -$ echo 1 > /sys/bus/usb/devices/DEVICE/authorized +$ echo 1 > /sys/usb/devices/DEVICE/authorized Deauthorize a device: -$ echo 0 > /sys/bus/usb/devices/DEVICE/authorized +$ echo 0 > /sys/usb/devices/DEVICE/authorized Set new devices connected to hostX to be deauthorized by default (ie: lock down): -$ echo 0 > /sys/bus/usb/devices/usbX/authorized_default +$ echo 0 > /sys/bus/devices/usbX/authorized_default Remove the lock down: -$ echo 1 > /sys/bus/usb/devices/usbX/authorized_default +$ echo 1 > /sys/bus/devices/usbX/authorized_default By default, Wired USB devices are authorized by default to connect. Wireless USB hosts deauthorize by default all new connected @@ -47,7 +47,7 @@ USB port): boot up rc.local -> - for host in /sys/bus/usb/devices/usb* + for host in /sys/bus/devices/usb* do echo 0 > $host/authorized_default done diff --git a/trunk/Documentation/usb/usbmon.txt b/trunk/Documentation/usb/usbmon.txt index 66f92d1194c1..6c3c625b7f30 100644 --- a/trunk/Documentation/usb/usbmon.txt +++ b/trunk/Documentation/usb/usbmon.txt @@ -33,7 +33,7 @@ if usbmon is built into the kernel. Verify that bus sockets are present. -# ls /sys/kernel/debug/usb/usbmon +# ls /sys/kernel/debug/usbmon 0s 0u 1s 1t 1u 2s 2t 2u 3s 3t 3u 4s 4t 4u # @@ -58,11 +58,11 @@ Bus=03 means it's bus 3. 3. Start 'cat' -# cat /sys/kernel/debug/usb/usbmon/3u > /tmp/1.mon.out +# cat /sys/kernel/debug/usbmon/3u > /tmp/1.mon.out to listen on a single bus, otherwise, to listen on all buses, type: -# cat /sys/kernel/debug/usb/usbmon/0u > /tmp/1.mon.out +# cat /sys/kernel/debug/usbmon/0u > /tmp/1.mon.out This process will be reading until killed. Naturally, the output can be redirected to a desirable location. This is preferred, because it is going @@ -305,7 +305,7 @@ Before the call, hdr, data, and alloc should be filled. Upon return, the area pointed by hdr contains the next event structure, and the data buffer contains the data, if any. The event is removed from the kernel buffer. -The MON_IOCX_GET copies 48 bytes to hdr area, MON_IOCX_GETX copies 64 bytes. +The MON_IOCX_GET copies 48 bytes, MON_IOCX_GETX copies 64 bytes. MON_IOCX_MFETCH, defined as _IOWR(MON_IOC_MAGIC, 7, struct mon_mfetch_arg) diff --git a/trunk/Documentation/video4linux/v4lgrab.c b/trunk/Documentation/video4linux/v4lgrab.c index c8ded175796e..05769cff1009 100644 --- a/trunk/Documentation/video4linux/v4lgrab.c +++ b/trunk/Documentation/video4linux/v4lgrab.c @@ -89,7 +89,7 @@ } \ } -static int get_brightness_adj(unsigned char *image, long size, int *brightness) { +int get_brightness_adj(unsigned char *image, long size, int *brightness) { long i, tot = 0; for (i=0;i> 20; } -static void fatal(const char *x, ...) +void fatal(const char *x, ...) { va_list ap; @@ -178,7 +178,7 @@ static void fatal(const char *x, ...) * page flag names */ -static char *page_flag_name(uint64_t flags) +char *page_flag_name(uint64_t flags) { static char buf[65]; int present; @@ -197,7 +197,7 @@ static char *page_flag_name(uint64_t flags) return buf; } -static char *page_flag_longname(uint64_t flags) +char *page_flag_longname(uint64_t flags) { static char buf[1024]; int i, n; @@ -221,7 +221,7 @@ static char *page_flag_longname(uint64_t flags) * page list and summary */ -static void show_page_range(unsigned long offset, uint64_t flags) +void show_page_range(unsigned long offset, uint64_t flags) { static uint64_t flags0; static unsigned long index; @@ -241,12 +241,12 @@ static void show_page_range(unsigned long offset, uint64_t flags) count = 1; } -static void show_page(unsigned long offset, uint64_t flags) +void show_page(unsigned long offset, uint64_t flags) { printf("%lu\t%s\n", offset, page_flag_name(flags)); } -static void show_summary(void) +void show_summary(void) { int i; @@ -272,7 +272,7 @@ static void show_summary(void) * page flag filters */ -static int bit_mask_ok(uint64_t flags) +int bit_mask_ok(uint64_t flags) { int i; @@ -289,7 +289,7 @@ static int bit_mask_ok(uint64_t flags) return 1; } -static uint64_t expand_overloaded_flags(uint64_t flags) +uint64_t expand_overloaded_flags(uint64_t flags) { /* SLOB/SLUB overload several page flags */ if (flags & BIT(SLAB)) { @@ -308,7 +308,7 @@ static uint64_t expand_overloaded_flags(uint64_t flags) return flags; } -static uint64_t well_known_flags(uint64_t flags) +uint64_t well_known_flags(uint64_t flags) { /* hide flags intended only for kernel hacker */ flags &= ~KPF_HACKERS_BITS; @@ -325,7 +325,7 @@ static uint64_t well_known_flags(uint64_t flags) * page frame walker */ -static int hash_slot(uint64_t flags) +int hash_slot(uint64_t flags) { int k = HASH_KEY(flags); int i; @@ -352,7 +352,7 @@ static int hash_slot(uint64_t flags) exit(EXIT_FAILURE); } -static void add_page(unsigned long offset, uint64_t flags) +void add_page(unsigned long offset, uint64_t flags) { flags = expand_overloaded_flags(flags); @@ -371,7 +371,7 @@ static void add_page(unsigned long offset, uint64_t flags) total_pages++; } -static void walk_pfn(unsigned long index, unsigned long count) +void walk_pfn(unsigned long index, unsigned long count) { unsigned long batch; unsigned long n; @@ -404,7 +404,7 @@ static void walk_pfn(unsigned long index, unsigned long count) } } -static void walk_addr_ranges(void) +void walk_addr_ranges(void) { int i; @@ -428,7 +428,7 @@ static void walk_addr_ranges(void) * user interface */ -static const char *page_flag_type(uint64_t flag) +const char *page_flag_type(uint64_t flag) { if (flag & KPF_HACKERS_BITS) return "(r)"; @@ -437,7 +437,7 @@ static const char *page_flag_type(uint64_t flag) return " "; } -static void usage(void) +void usage(void) { int i, j; @@ -482,7 +482,7 @@ static void usage(void) "(r) raw mode bits (o) overloaded bits\n"); } -static unsigned long long parse_number(const char *str) +unsigned long long parse_number(const char *str) { unsigned long long n; @@ -494,16 +494,16 @@ static unsigned long long parse_number(const char *str) return n; } -static void parse_pid(const char *str) +void parse_pid(const char *str) { opt_pid = parse_number(str); } -static void parse_file(const char *name) +void parse_file(const char *name) { } -static void add_addr_range(unsigned long offset, unsigned long size) +void add_addr_range(unsigned long offset, unsigned long size) { if (nr_addr_ranges >= MAX_ADDR_RANGES) fatal("too much addr ranges\n"); @@ -513,7 +513,7 @@ static void add_addr_range(unsigned long offset, unsigned long size) nr_addr_ranges++; } -static void parse_addr_range(const char *optarg) +void parse_addr_range(const char *optarg) { unsigned long offset; unsigned long size; @@ -547,7 +547,7 @@ static void parse_addr_range(const char *optarg) add_addr_range(offset, size); } -static void add_bits_filter(uint64_t mask, uint64_t bits) +void add_bits_filter(uint64_t mask, uint64_t bits) { if (nr_bit_filters >= MAX_BIT_FILTERS) fatal("too much bit filters\n"); @@ -557,7 +557,7 @@ static void add_bits_filter(uint64_t mask, uint64_t bits) nr_bit_filters++; } -static uint64_t parse_flag_name(const char *str, int len) +uint64_t parse_flag_name(const char *str, int len) { int i; @@ -577,7 +577,7 @@ static uint64_t parse_flag_name(const char *str, int len) return parse_number(str); } -static uint64_t parse_flag_names(const char *str, int all) +uint64_t parse_flag_names(const char *str, int all) { const char *p = str; uint64_t flags = 0; @@ -596,7 +596,7 @@ static uint64_t parse_flag_names(const char *str, int all) return flags; } -static void parse_bits_mask(const char *optarg) +void parse_bits_mask(const char *optarg) { uint64_t mask; uint64_t bits; @@ -621,7 +621,7 @@ static void parse_bits_mask(const char *optarg) } -static struct option opts[] = { +struct option opts[] = { { "raw" , 0, NULL, 'r' }, { "pid" , 1, NULL, 'p' }, { "file" , 1, NULL, 'f' }, diff --git a/trunk/Documentation/vm/slabinfo.c b/trunk/Documentation/vm/slabinfo.c index 92e729f4b676..df3227605d59 100644 --- a/trunk/Documentation/vm/slabinfo.c +++ b/trunk/Documentation/vm/slabinfo.c @@ -87,7 +87,7 @@ int page_size; regex_t pattern; -static void fatal(const char *x, ...) +void fatal(const char *x, ...) { va_list ap; @@ -97,7 +97,7 @@ static void fatal(const char *x, ...) exit(EXIT_FAILURE); } -static void usage(void) +void usage(void) { printf("slabinfo 5/7/2007. (c) 2007 sgi.\n\n" "slabinfo [-ahnpvtsz] [-d debugopts] [slab-regexp]\n" @@ -131,7 +131,7 @@ static void usage(void) ); } -static unsigned long read_obj(const char *name) +unsigned long read_obj(const char *name) { FILE *f = fopen(name, "r"); @@ -151,7 +151,7 @@ static unsigned long read_obj(const char *name) /* * Get the contents of an attribute */ -static unsigned long get_obj(const char *name) +unsigned long get_obj(const char *name) { if (!read_obj(name)) return 0; @@ -159,7 +159,7 @@ static unsigned long get_obj(const char *name) return atol(buffer); } -static unsigned long get_obj_and_str(const char *name, char **x) +unsigned long get_obj_and_str(const char *name, char **x) { unsigned long result = 0; char *p; @@ -178,7 +178,7 @@ static unsigned long get_obj_and_str(const char *name, char **x) return result; } -static void set_obj(struct slabinfo *s, const char *name, int n) +void set_obj(struct slabinfo *s, const char *name, int n) { char x[100]; FILE *f; @@ -192,7 +192,7 @@ static void set_obj(struct slabinfo *s, const char *name, int n) fclose(f); } -static unsigned long read_slab_obj(struct slabinfo *s, const char *name) +unsigned long read_slab_obj(struct slabinfo *s, const char *name) { char x[100]; FILE *f; @@ -215,7 +215,7 @@ static unsigned long read_slab_obj(struct slabinfo *s, const char *name) /* * Put a size string together */ -static int store_size(char *buffer, unsigned long value) +int store_size(char *buffer, unsigned long value) { unsigned long divisor = 1; char trailer = 0; @@ -247,7 +247,7 @@ static int store_size(char *buffer, unsigned long value) return n; } -static void decode_numa_list(int *numa, char *t) +void decode_numa_list(int *numa, char *t) { int node; int nr; @@ -272,7 +272,7 @@ static void decode_numa_list(int *numa, char *t) } } -static void slab_validate(struct slabinfo *s) +void slab_validate(struct slabinfo *s) { if (strcmp(s->name, "*") == 0) return; @@ -280,7 +280,7 @@ static void slab_validate(struct slabinfo *s) set_obj(s, "validate", 1); } -static void slab_shrink(struct slabinfo *s) +void slab_shrink(struct slabinfo *s) { if (strcmp(s->name, "*") == 0) return; @@ -290,7 +290,7 @@ static void slab_shrink(struct slabinfo *s) int line = 0; -static void first_line(void) +void first_line(void) { if (show_activity) printf("Name Objects Alloc Free %%Fast Fallb O\n"); @@ -302,7 +302,7 @@ static void first_line(void) /* * Find the shortest alias of a slab */ -static struct aliasinfo *find_one_alias(struct slabinfo *find) +struct aliasinfo *find_one_alias(struct slabinfo *find) { struct aliasinfo *a; struct aliasinfo *best = NULL; @@ -318,18 +318,18 @@ static struct aliasinfo *find_one_alias(struct slabinfo *find) return best; } -static unsigned long slab_size(struct slabinfo *s) +unsigned long slab_size(struct slabinfo *s) { return s->slabs * (page_size << s->order); } -static unsigned long slab_activity(struct slabinfo *s) +unsigned long slab_activity(struct slabinfo *s) { return s->alloc_fastpath + s->free_fastpath + s->alloc_slowpath + s->free_slowpath; } -static void slab_numa(struct slabinfo *s, int mode) +void slab_numa(struct slabinfo *s, int mode) { int node; @@ -374,7 +374,7 @@ static void slab_numa(struct slabinfo *s, int mode) line++; } -static void show_tracking(struct slabinfo *s) +void show_tracking(struct slabinfo *s) { printf("\n%s: Kernel object allocation\n", s->name); printf("-----------------------------------------------------------------------\n"); @@ -392,7 +392,7 @@ static void show_tracking(struct slabinfo *s) } -static void ops(struct slabinfo *s) +void ops(struct slabinfo *s) { if (strcmp(s->name, "*") == 0) return; @@ -405,14 +405,14 @@ static void ops(struct slabinfo *s) printf("\n%s has no kmem_cache operations\n", s->name); } -static const char *onoff(int x) +const char *onoff(int x) { if (x) return "On "; return "Off"; } -static void slab_stats(struct slabinfo *s) +void slab_stats(struct slabinfo *s) { unsigned long total_alloc; unsigned long total_free; @@ -477,7 +477,7 @@ static void slab_stats(struct slabinfo *s) s->deactivate_to_tail, (s->deactivate_to_tail * 100) / total); } -static void report(struct slabinfo *s) +void report(struct slabinfo *s) { if (strcmp(s->name, "*") == 0) return; @@ -518,7 +518,7 @@ static void report(struct slabinfo *s) slab_stats(s); } -static void slabcache(struct slabinfo *s) +void slabcache(struct slabinfo *s) { char size_str[20]; char dist_str[40]; @@ -593,7 +593,7 @@ static void slabcache(struct slabinfo *s) /* * Analyze debug options. Return false if something is amiss. */ -static int debug_opt_scan(char *opt) +int debug_opt_scan(char *opt) { if (!opt || !opt[0] || strcmp(opt, "-") == 0) return 1; @@ -642,7 +642,7 @@ static int debug_opt_scan(char *opt) return 1; } -static int slab_empty(struct slabinfo *s) +int slab_empty(struct slabinfo *s) { if (s->objects > 0) return 0; @@ -657,7 +657,7 @@ static int slab_empty(struct slabinfo *s) return 1; } -static void slab_debug(struct slabinfo *s) +void slab_debug(struct slabinfo *s) { if (strcmp(s->name, "*") == 0) return; @@ -717,7 +717,7 @@ static void slab_debug(struct slabinfo *s) set_obj(s, "trace", 1); } -static void totals(void) +void totals(void) { struct slabinfo *s; @@ -976,7 +976,7 @@ static void totals(void) b1, b2, b3); } -static void sort_slabs(void) +void sort_slabs(void) { struct slabinfo *s1,*s2; @@ -1005,7 +1005,7 @@ static void sort_slabs(void) } } -static void sort_aliases(void) +void sort_aliases(void) { struct aliasinfo *a1,*a2; @@ -1030,7 +1030,7 @@ static void sort_aliases(void) } } -static void link_slabs(void) +void link_slabs(void) { struct aliasinfo *a; struct slabinfo *s; @@ -1048,7 +1048,7 @@ static void link_slabs(void) } } -static void alias(void) +void alias(void) { struct aliasinfo *a; char *active = NULL; @@ -1079,7 +1079,7 @@ static void alias(void) } -static void rename_slabs(void) +void rename_slabs(void) { struct slabinfo *s; struct aliasinfo *a; @@ -1102,12 +1102,12 @@ static void rename_slabs(void) } } -static int slab_mismatch(char *slab) +int slab_mismatch(char *slab) { return regexec(&pattern, slab, 0, NULL, 0); } -static void read_slab_dir(void) +void read_slab_dir(void) { DIR *dir; struct dirent *de; @@ -1209,7 +1209,7 @@ static void read_slab_dir(void) fatal("Too many aliases\n"); } -static void output_slabs(void) +void output_slabs(void) { struct slabinfo *slab; diff --git a/trunk/Documentation/watchdog/src/watchdog-test.c b/trunk/Documentation/watchdog/src/watchdog-test.c index a750532ffcf8..65f6c19cb865 100644 --- a/trunk/Documentation/watchdog/src/watchdog-test.c +++ b/trunk/Documentation/watchdog/src/watchdog-test.c @@ -18,7 +18,7 @@ int fd; * the PC Watchdog card to reset its internal timer so it doesn't trigger * a computer reset. */ -static void keep_alive(void) +void keep_alive(void) { int dummy; diff --git a/trunk/Documentation/x86/earlyprintk.txt b/trunk/Documentation/x86/earlyprintk.txt index f19802c0f485..607b1a016064 100644 --- a/trunk/Documentation/x86/earlyprintk.txt +++ b/trunk/Documentation/x86/earlyprintk.txt @@ -7,7 +7,7 @@ and two USB cables, connected like this: [host/target] <-------> [USB debug key] <-------> [client/console] -1. There are a number of specific hardware requirements: +1. There are three specific hardware requirements: a.) Host/target system needs to have USB debug port capability. @@ -42,35 +42,7 @@ and two USB cables, connected like this: This is a small blue plastic connector with two USB connections, it draws power from its USB connections. - c.) You need a second client/console system with a high speed USB 2.0 - port. - - d.) The Netchip device must be plugged directly into the physical - debug port on the "host/target" system. You cannot use a USB hub in - between the physical debug port and the "host/target" system. - - The EHCI debug controller is bound to a specific physical USB - port and the Netchip device will only work as an early printk - device in this port. The EHCI host controllers are electrically - wired such that the EHCI debug controller is hooked up to the - first physical and there is no way to change this via software. - You can find the physical port through experimentation by trying - each physical port on the system and rebooting. Or you can try - and use lsusb or look at the kernel info messages emitted by the - usb stack when you plug a usb device into various ports on the - "host/target" system. - - Some hardware vendors do not expose the usb debug port with a - physical connector and if you find such a device send a complaint - to the hardware vendor, because there is no reason not to wire - this port into one of the physically accessible ports. - - e.) It is also important to note, that many versions of the Netchip - device require the "client/console" system to be plugged into the - right and side of the device (with the product logo facing up and - readable left to right). The reason being is that the 5 volt - power supply is taken from only one side of the device and it - must be the side that does not get rebooted. + c.) Thirdly, you need a second client/console system with a regular USB port. 2. Software requirements: @@ -84,13 +56,6 @@ and two USB cables, connected like this: (If you are using Grub, append it to the 'kernel' line in /etc/grub.conf) - On systems with more than one EHCI debug controller you must - specify the correct EHCI debug controller number. The ordering - comes from the PCI bus enumeration of the EHCI controllers. The - default with no number argument is "0" the first EHCI debug - controller. To use the second EHCI debug controller, you would - use the command line: "earlyprintk=dbgp1" - NOTE: normally earlyprintk console gets turned off once the regular console is alive - use "earlyprintk=dbgp,keep" to keep this channel open beyond early bootup. This can be useful for diff --git a/trunk/MAINTAINERS b/trunk/MAINTAINERS index 8f6297881077..d24c8823a8cb 100644 --- a/trunk/MAINTAINERS +++ b/trunk/MAINTAINERS @@ -895,13 +895,6 @@ F: drivers/dma/ F: include/linux/dmaengine.h F: include/linux/async_tx.h -AT24 EEPROM DRIVER -M: Wolfram Sang -L: linux-i2c@vger.kernel.org -S: Maintained -F: drivers/misc/eeprom/at24.c -F: include/linux/i2c/at24.h - ATA OVER ETHERNET (AOE) DRIVER M: "Ed L. Cashin" W: http://www.coraid.com/support/linux @@ -2114,12 +2107,12 @@ S: Supported F: arch/powerpc/sysdev/qe_lib/ F: arch/powerpc/include/asm/*qe.h -FREESCALE USB PERIPHERIAL DRIVERS +FREESCALE HIGHSPEED USB DEVICE DRIVER M: Li Yang L: linux-usb@vger.kernel.org L: linuxppc-dev@ozlabs.org S: Maintained -F: drivers/usb/gadget/fsl* +F: drivers/usb/gadget/fsl_usb2_udc.c FREESCALE QUICC ENGINE UCC ETHERNET DRIVER M: Li Yang @@ -3534,6 +3527,7 @@ F: drivers/net/natsemi.c NCP FILESYSTEM M: Petr Vandrovec +L: linware@sh.cvut.cz S: Maintained F: fs/ncpfs/ @@ -3775,13 +3769,7 @@ OMAP MMC SUPPORT M: Jarkko Lavinen L: linux-omap@vger.kernel.org S: Maintained -F: drivers/mmc/host/omap.c - -OMAP HS MMC SUPPORT -M: Madhusudhan Chikkature -L: linux-omap@vger.kernel.org -S: Maintained -F: drivers/mmc/host/omap_hsmmc.c +F: drivers/mmc/host/*omap* OMAP RANDOM NUMBER GENERATOR SUPPORT M: Deepak Saxena @@ -3971,15 +3959,6 @@ S: Maintained F: drivers/leds/leds-pca9532.c F: include/linux/leds-pca9532.h -PCA9564/PCA9665 I2C BUS DRIVER -M: Wolfram Sang -L: linux-i2c@vger.kernel.org -S: Maintained -F: drivers/i2c/algos/i2c-algo-pca.c -F: drivers/i2c/busses/i2c-pca-* -F: include/linux/i2c-algo-pca.h -F: include/linux/i2c-pca-platform.h - PCI ERROR RECOVERY M: Linas Vepstas L: linux-pci@vger.kernel.org @@ -4481,7 +4460,7 @@ SCORE ARCHITECTURE P: Chen Liqin M: liqin.chen@sunplusct.com P: Lennox Wu -M: lennox.wu@gmail.com +M: lennox.wu@sunplusct.com W: http://www.sunplusct.com S: Supported @@ -4669,18 +4648,6 @@ L: linux-pci@vger.kernel.org S: Supported F: drivers/pci/hotplug/shpchp* -SIMPLE FIRMWARE INTERFACE (SFI) -P: Len Brown -M: lenb@kernel.org -L: sfi-devel@simplefirmware.org -W: http://simplefirmware.org/ -T: git git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux-sfi-2.6.git -S: Supported -F: arch/x86/kernel/*sfi* -F: drivers/sfi/ -F: include/linux/sfi*.h - - SIMTEC EB110ATX (Chalice CATS) P: Ben Dooks M: Vincent Sanders @@ -5081,11 +5048,6 @@ T: quilt http://svn.sourceforge.jp/svnroot/tomoyo/trunk/2.2.x/tomoyo-lsm/patches S: Maintained F: security/tomoyo/ -TOPSTAR LAPTOP EXTRAS DRIVER -M: Herton Ronaldo Krzesinski -S: Maintained -F: drivers/platform/x86/topstar-laptop.c - TOSHIBA ACPI EXTRAS DRIVER S: Orphan F: drivers/platform/x86/toshiba_acpi.c diff --git a/trunk/arch/arm/configs/n770_defconfig b/trunk/arch/arm/configs/n770_defconfig index a1657b73683f..672f6db06a52 100644 --- a/trunk/arch/arm/configs/n770_defconfig +++ b/trunk/arch/arm/configs/n770_defconfig @@ -875,7 +875,7 @@ CONFIG_FB_OMAP_LCDC_EXTERNAL=y CONFIG_FB_OMAP_LCDC_HWA742=y # CONFIG_FB_OMAP_LCDC_BLIZZARD is not set CONFIG_FB_OMAP_MANUAL_UPDATE=y -CONFIG_FB_OMAP_LCD_MIPID=y +# CONFIG_FB_OMAP_LCD_MIPID is not set # CONFIG_FB_OMAP_BOOTLOADER_INIT is not set CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 # CONFIG_FB_OMAP_DMA_TUNE is not set diff --git a/trunk/arch/arm/configs/omap3_beagle_defconfig b/trunk/arch/arm/configs/omap3_beagle_defconfig index 357d4021e2d0..51c0fa8897cd 100644 --- a/trunk/arch/arm/configs/omap3_beagle_defconfig +++ b/trunk/arch/arm/configs/omap3_beagle_defconfig @@ -778,33 +778,7 @@ CONFIG_DAB=y # # CONFIG_VGASTATE is not set # CONFIG_VIDEO_OUTPUT_CONTROL is not set -CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB_DDC is not set -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# 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_S1D13XXX is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FB_OMAP=y -# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set -# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 +# CONFIG_FB is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -817,25 +791,6 @@ CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y -CONFIG_FONTS=y -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -# CONFIG_FONT_6x11 is not set -# CONFIG_FONT_7x14 is not set -# CONFIG_FONT_PEARL_8x8 is not set -# CONFIG_FONT_ACORN_8x8 is not set -# CONFIG_FONT_MINI_4x6 is not set -# CONFIG_FONT_SUN8x16 is not set -# CONFIG_FONT_SUN12x22 is not set -# CONFIG_FONT_10x18 is not set -# CONFIG_LOGO is not set - -# -# Sound -# # CONFIG_SOUND is not set # CONFIG_HID_SUPPORT is not set CONFIG_USB_SUPPORT=y diff --git a/trunk/arch/arm/configs/omap_3430sdp_defconfig b/trunk/arch/arm/configs/omap_3430sdp_defconfig index 8a4a7e2ba87b..9a510eab75a6 100644 --- a/trunk/arch/arm/configs/omap_3430sdp_defconfig +++ b/trunk/arch/arm/configs/omap_3430sdp_defconfig @@ -1313,33 +1313,8 @@ CONFIG_DVB_ISL6421=m # Graphics support # # CONFIG_VGASTATE is not set -CONFIG_FB=y -# CONFIG_FIRMWARE_EDID is not set -# CONFIG_FB_DDC is not set -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# 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_S1D13XXX is not set -# CONFIG_FB_VIRTUAL is not set -CONFIG_FB_OMAP=y -# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set -# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=2 +# CONFIG_VIDEO_OUTPUT_CONTROL is not set +# CONFIG_FB is not set # CONFIG_BACKLIGHT_LCD_SUPPORT is not set # @@ -1356,16 +1331,6 @@ CONFIG_DISPLAY_SUPPORT=y # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y CONFIG_SOUND=y CONFIG_SOUND_OSS_CORE=y CONFIG_SND=y diff --git a/trunk/arch/arm/configs/omap_ldp_defconfig b/trunk/arch/arm/configs/omap_ldp_defconfig index b9c48919a68c..679a4a3e265e 100644 --- a/trunk/arch/arm/configs/omap_ldp_defconfig +++ b/trunk/arch/arm/configs/omap_ldp_defconfig @@ -690,7 +690,6 @@ CONFIG_GPIOLIB=y # CONFIG_GPIO_MAX732X is not set # CONFIG_GPIO_PCA953X is not set # CONFIG_GPIO_PCF857X is not set -CONFIG_GPIO_TWL4030=y # # PCI GPIO expanders: @@ -743,7 +742,6 @@ CONFIG_SSB_POSSIBLE=y # CONFIG_MFD_SM501 is not set # CONFIG_HTC_EGPIO is not set # CONFIG_HTC_PASIC3 is not set -CONFIG_TWL4030_CORE=y # CONFIG_MFD_TMIO is not set # CONFIG_MFD_T7L66XB is not set # CONFIG_MFD_TC6387XB is not set @@ -769,46 +767,8 @@ CONFIG_DAB=y # # CONFIG_VGASTATE is not set CONFIG_VIDEO_OUTPUT_CONTROL=m -CONFIG_FB=y -CONFIG_FIRMWARE_EDID=y -# CONFIG_FB_DDC is not set -# CONFIG_FB_BOOT_VESA_SUPPORT is not set -CONFIG_FB_CFB_FILLRECT=y -CONFIG_FB_CFB_COPYAREA=y -CONFIG_FB_CFB_IMAGEBLIT=y -# CONFIG_FB_CFB_REV_PIXELS_IN_BYTE is not set -# CONFIG_FB_SYS_FILLRECT is not set -# CONFIG_FB_SYS_COPYAREA is not set -# CONFIG_FB_SYS_IMAGEBLIT is not set -# CONFIG_FB_FOREIGN_ENDIAN is not set -# CONFIG_FB_SYS_FOPS is not set -# CONFIG_FB_SVGALIB is not set -# CONFIG_FB_MACMODES is not set -# CONFIG_FB_BACKLIGHT is not set -CONFIG_FB_MODE_HELPERS=y -CONFIG_FB_TILEBLITTING=y - -# -# Frame buffer hardware drivers -# -# CONFIG_FB_S1D13XXX is not set -# CONFIG_FB_VIRTUAL is not set -# CONFIG_FB_METRONOME is not set -CONFIG_FB_OMAP=y -CONFIG_FB_OMAP_LCD_VGA=y -# CONFIG_FB_OMAP_LCDC_EXTERNAL is not set -# CONFIG_FB_OMAP_BOOTLOADER_INIT is not set -CONFIG_FB_OMAP_CONSISTENT_DMA_SIZE=4 -CONFIG_BACKLIGHT_LCD_SUPPORT=y -CONFIG_LCD_CLASS_DEVICE=y -# CONFIG_LCD_LTV350QV is not set -# CONFIG_LCD_ILI9320 is not set -# CONFIG_LCD_TDO24M is not set -# CONFIG_LCD_VGG2432A4 is not set -CONFIG_LCD_PLATFORM=y -CONFIG_BACKLIGHT_CLASS_DEVICE=y -# CONFIG_BACKLIGHT_CORGI is not set -# CONFIG_BACKLIGHT_GENERIC is not set +# CONFIG_FB is not set +# CONFIG_BACKLIGHT_LCD_SUPPORT is not set # # Display device support @@ -820,16 +780,6 @@ CONFIG_BACKLIGHT_CLASS_DEVICE=y # # CONFIG_VGA_CONSOLE is not set CONFIG_DUMMY_CONSOLE=y -CONFIG_FRAMEBUFFER_CONSOLE=y -# CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY is not set -# CONFIG_FRAMEBUFFER_CONSOLE_ROTATION is not set -# CONFIG_FONTS is not set -CONFIG_FONT_8x8=y -CONFIG_FONT_8x16=y -CONFIG_LOGO=y -CONFIG_LOGO_LINUX_MONO=y -CONFIG_LOGO_LINUX_VGA16=y -CONFIG_LOGO_LINUX_CLUT224=y CONFIG_SOUND=y CONFIG_SND=y # CONFIG_SND_SEQUENCER is not set diff --git a/trunk/arch/arm/mach-at91/Kconfig b/trunk/arch/arm/mach-at91/Kconfig index e35d54d43e70..a24d824c428b 100644 --- a/trunk/arch/arm/mach-at91/Kconfig +++ b/trunk/arch/arm/mach-at91/Kconfig @@ -289,13 +289,6 @@ config MACH_NEOCORE926 help Select this if you are using the Adeneo Neocore 926 board. -config MACH_AT91SAM9G20EK_2MMC - bool "Atmel AT91SAM9G20-EK Evaluation Kit modified for 2 MMC Slots" - depends on ARCH_AT91SAM9G20 - help - Select this if you are using an Atmel AT91SAM9G20-EK Evaluation Kit - Rev A or B modified for 2 MMC Slots. - endif # ---------------------------------------------------------- diff --git a/trunk/arch/arm/mach-at91/Makefile b/trunk/arch/arm/mach-at91/Makefile index ada440aab0c5..a6ed015d82ed 100644 --- a/trunk/arch/arm/mach-at91/Makefile +++ b/trunk/arch/arm/mach-at91/Makefile @@ -59,7 +59,6 @@ obj-$(CONFIG_MACH_AT91SAM9RLEK) += board-sam9rlek.o # AT91SAM9G20 board-specific support obj-$(CONFIG_MACH_AT91SAM9G20EK) += board-sam9g20ek.o -obj-$(CONFIG_MACH_AT91SAM9G20EK_2MMC) += board-sam9g20ek-2slot-mmc.o obj-$(CONFIG_MACH_CPU9G20) += board-cpu9krea.o # AT91SAM9G45 board-specific support diff --git a/trunk/arch/arm/mach-at91/at91sam9260_devices.c b/trunk/arch/arm/mach-at91/at91sam9260_devices.c index 07eb7b07e442..ee4ea0e720cf 100644 --- a/trunk/arch/arm/mach-at91/at91sam9260_devices.c +++ b/trunk/arch/arm/mach-at91/at91sam9260_devices.c @@ -278,102 +278,6 @@ void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data) {} #endif -/* -------------------------------------------------------------------- - * MMC / SD Slot for Atmel MCI Driver - * -------------------------------------------------------------------- */ - -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -static u64 mmc_dmamask = DMA_BIT_MASK(32); -static struct mci_platform_data mmc_data; - -static struct resource mmc_resources[] = { - [0] = { - .start = AT91SAM9260_BASE_MCI, - .end = AT91SAM9260_BASE_MCI + SZ_16K - 1, - .flags = IORESOURCE_MEM, - }, - [1] = { - .start = AT91SAM9260_ID_MCI, - .end = AT91SAM9260_ID_MCI, - .flags = IORESOURCE_IRQ, - }, -}; - -static struct platform_device at91sam9260_mmc_device = { - .name = "atmel_mci", - .id = -1, - .dev = { - .dma_mask = &mmc_dmamask, - .coherent_dma_mask = DMA_BIT_MASK(32), - .platform_data = &mmc_data, - }, - .resource = mmc_resources, - .num_resources = ARRAY_SIZE(mmc_resources), -}; - -void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) -{ - unsigned int i; - unsigned int slot_count = 0; - - if (!data) - return; - - for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { - if (data->slot[i].bus_width) { - /* input/irq */ - if (data->slot[i].detect_pin) { - at91_set_gpio_input(data->slot[i].detect_pin, 1); - at91_set_deglitch(data->slot[i].detect_pin, 1); - } - if (data->slot[i].wp_pin) - at91_set_gpio_input(data->slot[i].wp_pin, 1); - - switch (i) { - case 0: - /* CMD */ - at91_set_A_periph(AT91_PIN_PA7, 1); - /* DAT0, maybe DAT1..DAT3 */ - at91_set_A_periph(AT91_PIN_PA6, 1); - if (data->slot[i].bus_width == 4) { - at91_set_A_periph(AT91_PIN_PA9, 1); - at91_set_A_periph(AT91_PIN_PA10, 1); - at91_set_A_periph(AT91_PIN_PA11, 1); - } - slot_count++; - break; - case 1: - /* CMD */ - at91_set_B_periph(AT91_PIN_PA1, 1); - /* DAT0, maybe DAT1..DAT3 */ - at91_set_B_periph(AT91_PIN_PA0, 1); - if (data->slot[i].bus_width == 4) { - at91_set_B_periph(AT91_PIN_PA5, 1); - at91_set_B_periph(AT91_PIN_PA4, 1); - at91_set_B_periph(AT91_PIN_PA3, 1); - } - slot_count++; - break; - default: - printk(KERN_ERR - "AT91: SD/MMC slot %d not available\n", i); - break; - } - } - } - - if (slot_count) { - /* CLK */ - at91_set_A_periph(AT91_PIN_PA8, 0); - - mmc_data = *data; - platform_device_register(&at91sam9260_mmc_device); - } -} -#else -void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data) {} -#endif - /* -------------------------------------------------------------------- * NAND / SmartMedia diff --git a/trunk/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c b/trunk/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c deleted file mode 100644 index a28e53faf71d..000000000000 --- a/trunk/arch/arm/mach-at91/board-sam9g20ek-2slot-mmc.c +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (C) 2005 SAN People - * Copyright (C) 2008 Atmel - * Copyright (C) 2009 Rob Emanuele - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include "sam9_smc.h" -#include "generic.h" - - -static void __init ek_map_io(void) -{ - /* Initialize processor: 18.432 MHz crystal */ - at91sam9260_initialize(18432000); - - /* DGBU on ttyS0. (Rx & Tx only) */ - at91_register_uart(0, 0, 0); - - /* USART0 on ttyS1. (Rx, Tx, CTS, RTS, DTR, DSR, DCD, RI) */ - at91_register_uart(AT91SAM9260_ID_US0, 1, ATMEL_UART_CTS | ATMEL_UART_RTS - | ATMEL_UART_DTR | ATMEL_UART_DSR | ATMEL_UART_DCD - | ATMEL_UART_RI); - - /* USART1 on ttyS2. (Rx, Tx, RTS, CTS) */ - at91_register_uart(AT91SAM9260_ID_US1, 2, ATMEL_UART_CTS | ATMEL_UART_RTS); - - /* set serial console to ttyS0 (ie, DBGU) */ - at91_set_serial_console(0); -} - -static void __init ek_init_irq(void) -{ - at91sam9260_init_interrupts(NULL); -} - - -/* - * USB Host port - */ -static struct at91_usbh_data __initdata ek_usbh_data = { - .ports = 2, -}; - -/* - * USB Device port - */ -static struct at91_udc_data __initdata ek_udc_data = { - .vbus_pin = AT91_PIN_PC5, - .pullup_pin = 0, /* pull-up driven by UDC */ -}; - - -/* - * SPI devices. - */ -static struct spi_board_info ek_spi_devices[] = { -#if !defined(CONFIG_MMC_ATMELMCI) - { /* DataFlash chip */ - .modalias = "mtd_dataflash", - .chip_select = 1, - .max_speed_hz = 15 * 1000 * 1000, - .bus_num = 0, - }, -#if defined(CONFIG_MTD_AT91_DATAFLASH_CARD) - { /* DataFlash card */ - .modalias = "mtd_dataflash", - .chip_select = 0, - .max_speed_hz = 15 * 1000 * 1000, - .bus_num = 0, - }, -#endif -#endif -}; - - -/* - * MACB Ethernet device - */ -static struct at91_eth_data __initdata ek_macb_data = { - .phy_irq_pin = AT91_PIN_PC12, - .is_rmii = 1, -}; - - -/* - * NAND flash - */ -static struct mtd_partition __initdata ek_nand_partition[] = { - { - .name = "Bootstrap", - .offset = 0, - .size = 4 * SZ_1M, - }, - { - .name = "Partition 1", - .offset = MTDPART_OFS_NXTBLK, - .size = 60 * SZ_1M, - }, - { - .name = "Partition 2", - .offset = MTDPART_OFS_NXTBLK, - .size = MTDPART_SIZ_FULL, - }, -}; - -static struct mtd_partition * __init nand_partitions(int size, int *num_partitions) -{ - *num_partitions = ARRAY_SIZE(ek_nand_partition); - return ek_nand_partition; -} - -/* det_pin is not connected */ -static struct atmel_nand_data __initdata ek_nand_data = { - .ale = 21, - .cle = 22, - .rdy_pin = AT91_PIN_PC13, - .enable_pin = AT91_PIN_PC14, - .partition_info = nand_partitions, -#if defined(CONFIG_MTD_NAND_ATMEL_BUSWIDTH_16) - .bus_width_16 = 1, -#else - .bus_width_16 = 0, -#endif -}; - -static struct sam9_smc_config __initdata ek_nand_smc_config = { - .ncs_read_setup = 0, - .nrd_setup = 2, - .ncs_write_setup = 0, - .nwe_setup = 2, - - .ncs_read_pulse = 4, - .nrd_pulse = 4, - .ncs_write_pulse = 4, - .nwe_pulse = 4, - - .read_cycle = 7, - .write_cycle = 7, - - .mode = AT91_SMC_READMODE | AT91_SMC_WRITEMODE | AT91_SMC_EXNWMODE_DISABLE, - .tdf_cycles = 3, -}; - -static void __init ek_add_device_nand(void) -{ - /* setup bus-width (8 or 16) */ - if (ek_nand_data.bus_width_16) - ek_nand_smc_config.mode |= AT91_SMC_DBW_16; - else - ek_nand_smc_config.mode |= AT91_SMC_DBW_8; - - /* configure chip-select 3 (NAND) */ - sam9_smc_configure(3, &ek_nand_smc_config); - - at91_add_device_nand(&ek_nand_data); -} - - -/* - * MCI (SD/MMC) - * det_pin and wp_pin are not connected - */ -#if defined(CONFIG_MMC_ATMELMCI) || defined(CONFIG_MMC_ATMELMCI_MODULE) -static struct mci_platform_data __initdata ek_mmc_data = { - .slot[0] = { - .bus_width = 4, - .detect_pin = -ENODEV, - .wp_pin = -ENODEV, - }, - .slot[1] = { - .bus_width = 4, - .detect_pin = -ENODEV, - .wp_pin = -ENODEV, - }, - -}; -#else -static struct amci_platform_data __initdata ek_mmc_data = { -}; -#endif - -/* - * LEDs - */ -static struct gpio_led ek_leds[] = { - { /* "bottom" led, green, userled1 to be defined */ - .name = "ds5", - .gpio = AT91_PIN_PB12, - .active_low = 1, - .default_trigger = "none", - }, - { /* "power" led, yellow */ - .name = "ds1", - .gpio = AT91_PIN_PB13, - .default_trigger = "heartbeat", - } -}; - -static struct i2c_board_info __initdata ek_i2c_devices[] = { - { - I2C_BOARD_INFO("24c512", 0x50), - }, -}; - - -static void __init ek_board_init(void) -{ - /* Serial */ - at91_add_device_serial(); - /* USB Host */ - at91_add_device_usbh(&ek_usbh_data); - /* USB Device */ - at91_add_device_udc(&ek_udc_data); - /* SPI */ - at91_add_device_spi(ek_spi_devices, ARRAY_SIZE(ek_spi_devices)); - /* NAND */ - ek_add_device_nand(); - /* Ethernet */ - at91_add_device_eth(&ek_macb_data); - /* MMC */ - at91_add_device_mci(0, &ek_mmc_data); - /* I2C */ - at91_add_device_i2c(ek_i2c_devices, ARRAY_SIZE(ek_i2c_devices)); - /* LEDs */ - at91_gpio_leds(ek_leds, ARRAY_SIZE(ek_leds)); - /* PCK0 provides MCLK to the WM8731 */ - at91_set_B_periph(AT91_PIN_PC1, 0); - /* SSC (for WM8731) */ - at91_add_device_ssc(AT91SAM9260_ID_SSC, ATMEL_SSC_TX); -} - -MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod") - /* Maintainer: Rob Emanuele */ - .phys_io = AT91_BASE_SYS, - .io_pg_offst = (AT91_VA_BASE_SYS >> 18) & 0xfffc, - .boot_params = AT91_SDRAM_BASE + 0x100, - .timer = &at91sam926x_timer, - .map_io = ek_map_io, - .init_irq = ek_init_irq, - .init_machine = ek_board_init, -MACHINE_END diff --git a/trunk/arch/arm/mach-at91/include/mach/board.h b/trunk/arch/arm/mach-at91/include/mach/board.h index 583f38a38df7..13f27a4b882d 100644 --- a/trunk/arch/arm/mach-at91/include/mach/board.h +++ b/trunk/arch/arm/mach-at91/include/mach/board.h @@ -37,7 +37,6 @@ #include #include #include -#include #include /* USB Device */ @@ -65,7 +64,6 @@ struct at91_cf_data { extern void __init at91_add_device_cf(struct at91_cf_data *data); /* MMC / SD */ - /* at91_mci platform config */ struct at91_mmc_data { u8 det_pin; /* card detect IRQ */ unsigned slot_b:1; /* uses Slot B */ @@ -75,9 +73,6 @@ struct at91_mmc_data { }; extern void __init at91_add_device_mmc(short mmc_id, struct at91_mmc_data *data); - /* atmel-mci platform config */ -extern void __init at91_add_device_mci(short mmc_id, struct mci_platform_data *data); - /* Ethernet (EMAC & MACB) */ struct at91_eth_data { u32 phy_mask; diff --git a/trunk/arch/arm/mach-ep93xx/clock.c b/trunk/arch/arm/mach-ep93xx/clock.c index dda19cd76194..3dd0e2a23095 100644 --- a/trunk/arch/arm/mach-ep93xx/clock.c +++ b/trunk/arch/arm/mach-ep93xx/clock.c @@ -37,7 +37,7 @@ struct clk { static unsigned long get_uart_rate(struct clk *clk); static int set_keytchclk_rate(struct clk *clk, unsigned long rate); -static int set_div_rate(struct clk *clk, unsigned long rate); + static struct clk clk_uart1 = { .sw_locked = 1, @@ -76,13 +76,6 @@ static struct clk clk_pwm = { .rate = EP93XX_EXT_CLK_RATE, }; -static struct clk clk_video = { - .sw_locked = 1, - .enable_reg = EP93XX_SYSCON_VIDCLKDIV, - .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE, - .set_rate = set_div_rate, -}; - /* DMA Clocks */ static struct clk clk_m2p0 = { .enable_reg = EP93XX_SYSCON_PWRCNT, @@ -147,7 +140,6 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "pll2", &clk_pll2), INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), INIT_CK("ep93xx-keypad", NULL, &clk_keypad), - INIT_CK("ep93xx-fb", NULL, &clk_video), INIT_CK(NULL, "pwm_clk", &clk_pwm), INIT_CK(NULL, "m2p0", &clk_m2p0), INIT_CK(NULL, "m2p1", &clk_m2p1), @@ -244,84 +236,6 @@ static int set_keytchclk_rate(struct clk *clk, unsigned long rate) return 0; } -static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel, - int *pdiv, int *div) -{ - unsigned long max_rate, best_rate = 0, - actual_rate = 0, mclk_rate = 0, rate_err = -1; - int i, found = 0, __div = 0, __pdiv = 0; - - /* Don't exceed the maximum rate */ - max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4), - (unsigned long)EP93XX_EXT_CLK_RATE / 4); - rate = min(rate, max_rate); - - /* - * Try the two pll's and the external clock - * Because the valid predividers are 2, 2.5 and 3, we multiply - * all the clocks by 2 to avoid floating point math. - * - * This is based on the algorithm in the ep93xx raster guide: - * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf - * - */ - for (i = 0; i < 3; i++) { - if (i == 0) - mclk_rate = EP93XX_EXT_CLK_RATE * 2; - else if (i == 1) - mclk_rate = clk_pll1.rate * 2; - else if (i == 2) - mclk_rate = clk_pll2.rate * 2; - - /* Try each predivider value */ - for (__pdiv = 4; __pdiv <= 6; __pdiv++) { - __div = mclk_rate / (rate * __pdiv); - if (__div < 2 || __div > 127) - continue; - - actual_rate = mclk_rate / (__pdiv * __div); - - if (!found || abs(actual_rate - rate) < rate_err) { - *pdiv = __pdiv - 3; - *div = __div; - *psel = (i == 2); - *esel = (i != 0); - best_rate = actual_rate; - rate_err = abs(actual_rate - rate); - found = 1; - } - } - } - - if (!found) - return 0; - - return best_rate; -} - -static int set_div_rate(struct clk *clk, unsigned long rate) -{ - unsigned long actual_rate; - int psel = 0, esel = 0, pdiv = 0, div = 0; - u32 val; - - actual_rate = calc_clk_div(rate, &psel, &esel, &pdiv, &div); - if (actual_rate == 0) - return -EINVAL; - clk->rate = actual_rate; - - /* Clear the esel, psel, pdiv and div bits */ - val = __raw_readl(clk->enable_reg); - val &= ~0x7fff; - - /* Set the new esel, psel, pdiv and div bits for the new clock rate */ - val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) | - (psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) | - (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div; - ep93xx_syscon_swlocked_write(val, clk->enable_reg); - return 0; -} - int clk_set_rate(struct clk *clk, unsigned long rate) { if (clk->set_rate) diff --git a/trunk/arch/arm/mach-ep93xx/core.c b/trunk/arch/arm/mach-ep93xx/core.c index f7ebed942f66..16b92c37ec99 100644 --- a/trunk/arch/arm/mach-ep93xx/core.c +++ b/trunk/arch/arm/mach-ep93xx/core.c @@ -30,7 +30,6 @@ #include #include -#include #include #include @@ -683,37 +682,6 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev) EXPORT_SYMBOL(ep93xx_pwm_release_gpio); -/************************************************************************* - * EP93xx video peripheral handling - *************************************************************************/ -static struct ep93xxfb_mach_info ep93xxfb_data; - -static struct resource ep93xx_fb_resource[] = { - { - .start = EP93XX_RASTER_PHYS_BASE, - .end = EP93XX_RASTER_PHYS_BASE + 0x800 - 1, - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device ep93xx_fb_device = { - .name = "ep93xx-fb", - .id = -1, - .dev = { - .platform_data = &ep93xxfb_data, - .coherent_dma_mask = DMA_BIT_MASK(32), - .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask, - }, - .num_resources = ARRAY_SIZE(ep93xx_fb_resource), - .resource = ep93xx_fb_resource, -}; - -void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) -{ - ep93xxfb_data = *data; - platform_device_register(&ep93xx_fb_device); -} - extern void ep93xx_gpio_init(void); void __init ep93xx_init_devices(void) diff --git a/trunk/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/trunk/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index 0fbf87b16338..ea78e908fc82 100644 --- a/trunk/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/trunk/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -70,7 +70,6 @@ #define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000) #define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000) -#define EP93XX_RASTER_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00030000) #define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000) #define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000) @@ -208,11 +207,6 @@ #define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2) #define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) #define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) -#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84) -#define EP93XX_SYSCON_CLKDIV_ENABLE (1<<15) -#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) -#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) -#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 #define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) #define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) #define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) diff --git a/trunk/arch/arm/mach-ep93xx/include/mach/fb.h b/trunk/arch/arm/mach-ep93xx/include/mach/fb.h deleted file mode 100644 index d5ae11d7c453..000000000000 --- a/trunk/arch/arm/mach-ep93xx/include/mach/fb.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * arch/arm/mach-ep93xx/include/mach/fb.h - */ - -#ifndef __ASM_ARCH_EP93XXFB_H -#define __ASM_ARCH_EP93XXFB_H - -struct platform_device; -struct fb_videomode; -struct fb_info; - -#define EP93XXFB_USE_MODEDB 0 - -/* VideoAttributes flags */ -#define EP93XXFB_STATE_MACHINE_ENABLE (1 << 0) -#define EP93XXFB_PIXEL_CLOCK_ENABLE (1 << 1) -#define EP93XXFB_VSYNC_ENABLE (1 << 2) -#define EP93XXFB_PIXEL_DATA_ENABLE (1 << 3) -#define EP93XXFB_COMPOSITE_SYNC (1 << 4) -#define EP93XXFB_SYNC_VERT_HIGH (1 << 5) -#define EP93XXFB_SYNC_HORIZ_HIGH (1 << 6) -#define EP93XXFB_SYNC_BLANK_HIGH (1 << 7) -#define EP93XXFB_PCLK_FALLING (1 << 8) -#define EP93XXFB_ENABLE_AC (1 << 9) -#define EP93XXFB_ENABLE_LCD (1 << 10) -#define EP93XXFB_ENABLE_CCIR (1 << 12) -#define EP93XXFB_USE_PARALLEL_INTERFACE (1 << 13) -#define EP93XXFB_ENABLE_INTERRUPT (1 << 14) -#define EP93XXFB_USB_INTERLACE (1 << 16) -#define EP93XXFB_USE_EQUALIZATION (1 << 17) -#define EP93XXFB_USE_DOUBLE_HORZ (1 << 18) -#define EP93XXFB_USE_DOUBLE_VERT (1 << 19) -#define EP93XXFB_USE_BLANK_PIXEL (1 << 20) -#define EP93XXFB_USE_SDCSN0 (0 << 21) -#define EP93XXFB_USE_SDCSN1 (1 << 21) -#define EP93XXFB_USE_SDCSN2 (2 << 21) -#define EP93XXFB_USE_SDCSN3 (3 << 21) - -#define EP93XXFB_ENABLE (EP93XXFB_STATE_MACHINE_ENABLE | \ - EP93XXFB_PIXEL_CLOCK_ENABLE | \ - EP93XXFB_VSYNC_ENABLE | \ - EP93XXFB_PIXEL_DATA_ENABLE) - -struct ep93xxfb_mach_info { - unsigned int num_modes; - const struct fb_videomode *modes; - const struct fb_videomode *default_mode; - int bpp; - unsigned int flags; - - int (*setup)(struct platform_device *pdev); - void (*teardown)(struct platform_device *pdev); - void (*blank)(int blank_mode, struct fb_info *info); -}; - -#endif /* __ASM_ARCH_EP93XXFB_H */ diff --git a/trunk/arch/arm/mach-ep93xx/include/mach/platform.h b/trunk/arch/arm/mach-ep93xx/include/mach/platform.h index 01a0f0838e5b..5f5fa6574d34 100644 --- a/trunk/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/trunk/arch/arm/mach-ep93xx/include/mach/platform.h @@ -6,7 +6,6 @@ struct i2c_board_info; struct platform_device; -struct ep93xxfb_mach_info; struct ep93xx_eth_data { @@ -34,7 +33,6 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits) void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); void ep93xx_register_i2c(struct i2c_board_info *devices, int num); -void ep93xx_register_fb(struct ep93xxfb_mach_info *data); void ep93xx_register_pwm(int pwm0, int pwm1); int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); void ep93xx_pwm_release_gpio(struct platform_device *pdev); diff --git a/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c b/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c index e6e8290b7828..e70baa799018 100644 --- a/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c +++ b/trunk/arch/arm/mach-omap2/board-rx51-peripherals.c @@ -19,7 +19,6 @@ #include #include #include -#include #include #include @@ -103,7 +102,6 @@ static struct twl4030_hsmmc_info mmc[] = { .cover_only = true, .gpio_cd = 160, .gpio_wp = -EINVAL, - .power_saving = true, }, { .name = "internal", @@ -111,8 +109,6 @@ static struct twl4030_hsmmc_info mmc[] = { .wires = 8, .gpio_cd = -EINVAL, .gpio_wp = -EINVAL, - .nonremovable = true, - .power_saving = true, }, {} /* Terminator */ }; diff --git a/trunk/arch/arm/mach-omap2/devices.c b/trunk/arch/arm/mach-omap2/devices.c index bcfcfc7fdb9b..a2e915639b72 100644 --- a/trunk/arch/arm/mach-omap2/devices.c +++ b/trunk/arch/arm/mach-omap2/devices.c @@ -257,11 +257,6 @@ static inline void omap_init_sti(void) {} #define OMAP2_MCSPI3_BASE 0x480b8000 #define OMAP2_MCSPI4_BASE 0x480ba000 -#define OMAP4_MCSPI1_BASE 0x48098100 -#define OMAP4_MCSPI2_BASE 0x4809a100 -#define OMAP4_MCSPI3_BASE 0x480b8100 -#define OMAP4_MCSPI4_BASE 0x480ba100 - static struct omap2_mcspi_platform_config omap2_mcspi1_config = { .num_cs = 4, }; @@ -306,8 +301,7 @@ static struct platform_device omap2_mcspi2 = { }, }; -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ - defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) static struct omap2_mcspi_platform_config omap2_mcspi3_config = { .num_cs = 2, }; @@ -331,7 +325,7 @@ static struct platform_device omap2_mcspi3 = { }; #endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) +#ifdef CONFIG_ARCH_OMAP3 static struct omap2_mcspi_platform_config omap2_mcspi4_config = { .num_cs = 1, }; @@ -357,25 +351,14 @@ static struct platform_device omap2_mcspi4 = { static void omap_init_mcspi(void) { - if (cpu_is_omap44xx()) { - omap2_mcspi1_resources[0].start = OMAP4_MCSPI1_BASE; - omap2_mcspi1_resources[0].end = OMAP4_MCSPI1_BASE + 0xff; - omap2_mcspi2_resources[0].start = OMAP4_MCSPI2_BASE; - omap2_mcspi2_resources[0].end = OMAP4_MCSPI2_BASE + 0xff; - omap2_mcspi3_resources[0].start = OMAP4_MCSPI3_BASE; - omap2_mcspi3_resources[0].end = OMAP4_MCSPI3_BASE + 0xff; - omap2_mcspi4_resources[0].start = OMAP4_MCSPI4_BASE; - omap2_mcspi4_resources[0].end = OMAP4_MCSPI4_BASE + 0xff; - } platform_device_register(&omap2_mcspi1); platform_device_register(&omap2_mcspi2); -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \ - defined(CONFIG_ARCH_OMAP4) - if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx()) +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) + if (cpu_is_omap2430() || cpu_is_omap343x()) platform_device_register(&omap2_mcspi3); #endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) - if (cpu_is_omap343x() || cpu_is_omap44xx()) +#ifdef CONFIG_ARCH_OMAP3 + if (cpu_is_omap343x()) platform_device_register(&omap2_mcspi4); #endif } @@ -414,7 +397,7 @@ static inline void omap_init_sha1_md5(void) { } /*-------------------------------------------------------------------------*/ -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) +#ifdef CONFIG_ARCH_OMAP3 #define MMCHS_SYSCONFIG 0x0010 #define MMCHS_SYSCONFIG_SWRESET (1 << 1) @@ -441,8 +424,8 @@ static struct platform_device dummy_pdev = { **/ static void __init omap_hsmmc_reset(void) { - u32 i, nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC : - (cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC); + u32 i, nr_controllers = cpu_is_omap34xx() ? OMAP34XX_NR_MMC : + OMAP24XX_NR_MMC; for (i = 0; i < nr_controllers; i++) { u32 v, base = 0; @@ -459,21 +442,8 @@ static void __init omap_hsmmc_reset(void) case 2: base = OMAP3_MMC3_BASE; break; - case 3: - if (!cpu_is_omap44xx()) - return; - base = OMAP4_MMC4_BASE; - break; - case 4: - if (!cpu_is_omap44xx()) - return; - base = OMAP4_MMC5_BASE; - break; } - if (cpu_is_omap44xx()) - base += OMAP4_MMC_REG_OFFSET; - dummy_pdev.id = i; dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i); iclk = clk_get(dev, "ick"); @@ -611,23 +581,11 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, irq = INT_24XX_MMC2_IRQ; break; case 2: - if (!cpu_is_omap44xx() && !cpu_is_omap34xx()) + if (!cpu_is_omap34xx()) return; base = OMAP3_MMC3_BASE; irq = INT_34XX_MMC3_IRQ; break; - case 3: - if (!cpu_is_omap44xx()) - return; - base = OMAP4_MMC4_BASE + OMAP4_MMC_REG_OFFSET; - irq = INT_44XX_MMC4_IRQ; - break; - case 4: - if (!cpu_is_omap44xx()) - return; - base = OMAP4_MMC5_BASE + OMAP4_MMC_REG_OFFSET; - irq = INT_44XX_MMC5_IRQ; - break; default: continue; } @@ -635,15 +593,8 @@ void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data, if (cpu_is_omap2420()) { size = OMAP2420_MMC_SIZE; name = "mmci-omap"; - } else if (cpu_is_omap44xx()) { - if (i < 3) { - base += OMAP4_MMC_REG_OFFSET; - irq += IRQ_GIC_START; - } - size = OMAP4_HSMMC_SIZE; - name = "mmci-omap-hs"; } else { - size = OMAP3_HSMMC_SIZE; + size = HSMMC_SIZE; name = "mmci-omap-hs"; } omap_mmc_add(name, i, base, size, irq, mmc_data[i]); diff --git a/trunk/arch/arm/mach-omap2/mmc-twl4030.c b/trunk/arch/arm/mach-omap2/mmc-twl4030.c index c9c59a2db4e2..3c04c2f1b23f 100644 --- a/trunk/arch/arm/mach-omap2/mmc-twl4030.c +++ b/trunk/arch/arm/mach-omap2/mmc-twl4030.c @@ -198,18 +198,6 @@ static int twl_mmc_resume(struct device *dev, int slot) #define twl_mmc_resume NULL #endif -#if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM) - -static int twl4030_mmc_get_context_loss(struct device *dev) -{ - /* FIXME: PM DPS not implemented yet */ - return 0; -} - -#else -#define twl4030_mmc_get_context_loss NULL -#endif - static int twl_mmc1_set_power(struct device *dev, int slot, int power_on, int vdd) { @@ -340,61 +328,6 @@ static int twl_mmc23_set_power(struct device *dev, int slot, int power_on, int v return ret; } -static int twl_mmc1_set_sleep(struct device *dev, int slot, int sleep, int vdd, - int cardsleep) -{ - struct twl_mmc_controller *c = &hsmmc[0]; - int mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; - - return regulator_set_mode(c->vcc, mode); -} - -static int twl_mmc23_set_sleep(struct device *dev, int slot, int sleep, int vdd, - int cardsleep) -{ - struct twl_mmc_controller *c = NULL; - struct omap_mmc_platform_data *mmc = dev->platform_data; - int i, err, mode; - - for (i = 1; i < ARRAY_SIZE(hsmmc); i++) { - if (mmc == hsmmc[i].mmc) { - c = &hsmmc[i]; - break; - } - } - - if (c == NULL) - return -ENODEV; - - /* - * If we don't see a Vcc regulator, assume it's a fixed - * voltage always-on regulator. - */ - if (!c->vcc) - return 0; - - mode = sleep ? REGULATOR_MODE_STANDBY : REGULATOR_MODE_NORMAL; - - if (!c->vcc_aux) - return regulator_set_mode(c->vcc, mode); - - if (cardsleep) { - /* VCC can be turned off if card is asleep */ - struct regulator *vcc_aux = c->vcc_aux; - - c->vcc_aux = NULL; - if (sleep) - err = twl_mmc23_set_power(dev, slot, 0, 0); - else - err = twl_mmc23_set_power(dev, slot, 1, vdd); - c->vcc_aux = vcc_aux; - } else - err = regulator_set_mode(c->vcc, mode); - if (err) - return err; - return regulator_set_mode(c->vcc_aux, mode); -} - static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata; void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) @@ -457,9 +390,6 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) } else mmc->slots[0].switch_pin = -EINVAL; - mmc->get_context_loss_count = - twl4030_mmc_get_context_loss; - /* write protect normally uses an OMAP gpio */ if (gpio_is_valid(c->gpio_wp)) { gpio_request(c->gpio_wp, "mmc_wp"); @@ -470,12 +400,6 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) } else mmc->slots[0].gpio_wp = -EINVAL; - if (c->nonremovable) - mmc->slots[0].nonremovable = 1; - - if (c->power_saving) - mmc->slots[0].power_saving = 1; - /* NOTE: MMC slots should have a Vcc regulator set up. * This may be from a TWL4030-family chip, another * controllable regulator, or a fixed supply. @@ -488,7 +412,6 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) case 1: /* on-chip level shifting via PBIAS0/PBIAS1 */ mmc->slots[0].set_power = twl_mmc1_set_power; - mmc->slots[0].set_sleep = twl_mmc1_set_sleep; break; case 2: if (c->ext_clock) @@ -499,7 +422,6 @@ void __init twl4030_mmc_init(struct twl4030_hsmmc_info *controllers) case 3: /* off-chip level shifting, or none */ mmc->slots[0].set_power = twl_mmc23_set_power; - mmc->slots[0].set_sleep = twl_mmc23_set_sleep; break; default: pr_err("MMC%d configuration not supported!\n", c->mmc); diff --git a/trunk/arch/arm/mach-omap2/mmc-twl4030.h b/trunk/arch/arm/mach-omap2/mmc-twl4030.h index a47e68563fb6..3807c45c9a6c 100644 --- a/trunk/arch/arm/mach-omap2/mmc-twl4030.h +++ b/trunk/arch/arm/mach-omap2/mmc-twl4030.h @@ -12,8 +12,6 @@ struct twl4030_hsmmc_info { bool transceiver; /* MMC-2 option */ bool ext_clock; /* use external pin for input clock */ bool cover_only; /* No card detect - just cover switch */ - bool nonremovable; /* Nonremovable e.g. eMMC */ - bool power_saving; /* Try to sleep or power off when possible */ int gpio_cd; /* or -EINVAL */ int gpio_wp; /* or -EINVAL */ char *name; /* or NULL for default */ diff --git a/trunk/arch/arm/plat-mxc/include/mach/spi.h b/trunk/arch/arm/plat-mxc/include/mach/spi.h deleted file mode 100644 index 08be445e8eb8..000000000000 --- a/trunk/arch/arm/plat-mxc/include/mach/spi.h +++ /dev/null @@ -1,27 +0,0 @@ - -#ifndef __MACH_SPI_H_ -#define __MACH_SPI_H_ - -/* - * struct spi_imx_master - device.platform_data for SPI controller devices. - * @chipselect: Array of chipselects for this master. Numbers >= 0 mean gpio - * pins, numbers < 0 mean internal CSPI chipselects according - * to MXC_SPI_CS(). Normally you want to use gpio based chip - * selects as the CSPI module tries to be intelligent about - * when to assert the chipselect: The CSPI module deasserts the - * chipselect once it runs out of input data. The other problem - * is that it is not possible to mix between high active and low - * active chipselects on one single bus using the internal - * chipselects. Unfortunately Freescale decided to put some - * chipselects on dedicated pins which are not usable as gpios, - * so we have to support the internal chipselects. - * @num_chipselect: ARRAY_SIZE(chipselect) - */ -struct spi_imx_master { - int *chipselect; - int num_chipselect; -}; - -#define MXC_SPI_CS(no) ((no) - 32) - -#endif /* __MACH_SPI_H_*/ diff --git a/trunk/arch/arm/plat-omap/include/mach/irqs.h b/trunk/arch/arm/plat-omap/include/mach/irqs.h index 28a165058b61..fb7cb7723990 100644 --- a/trunk/arch/arm/plat-omap/include/mach/irqs.h +++ b/trunk/arch/arm/plat-omap/include/mach/irqs.h @@ -503,7 +503,6 @@ #define INT_44XX_FPKA_READY_IRQ (50 + IRQ_GIC_START) #define INT_44XX_SHA1MD51_IRQ (51 + IRQ_GIC_START) #define INT_44XX_RNG_IRQ (52 + IRQ_GIC_START) -#define INT_44XX_MMC5_IRQ (59 + IRQ_GIC_START) #define INT_44XX_I2C3_IRQ (61 + IRQ_GIC_START) #define INT_44XX_FPKA_ERROR_IRQ (64 + IRQ_GIC_START) #define INT_44XX_PBIAS_IRQ (75 + IRQ_GIC_START) @@ -512,7 +511,6 @@ #define INT_44XX_TLL_IRQ (78 + IRQ_GIC_START) #define INT_44XX_PARTHASH_IRQ (79 + IRQ_GIC_START) #define INT_44XX_MMC3_IRQ (94 + IRQ_GIC_START) -#define INT_44XX_MMC4_IRQ (96 + IRQ_GIC_START) /* Max. 128 level 2 IRQs (OMAP1610), 192 GPIOs (OMAP730/850) and diff --git a/trunk/arch/arm/plat-omap/include/mach/lcd_mipid.h b/trunk/arch/arm/plat-omap/include/mach/lcd_mipid.h index 8e52c6572281..f8fbc4801e52 100644 --- a/trunk/arch/arm/plat-omap/include/mach/lcd_mipid.h +++ b/trunk/arch/arm/plat-omap/include/mach/lcd_mipid.h @@ -16,12 +16,7 @@ enum mipid_test_result { struct mipid_platform_data { int nreset_gpio; int data_lines; - void (*shutdown)(struct mipid_platform_data *pdata); - void (*set_bklight_level)(struct mipid_platform_data *pdata, - int level); - int (*get_bklight_level)(struct mipid_platform_data *pdata); - int (*get_bklight_max)(struct mipid_platform_data *pdata); }; #endif diff --git a/trunk/arch/arm/plat-omap/include/mach/mmc.h b/trunk/arch/arm/plat-omap/include/mach/mmc.h index 7229b9593301..81d5b36534b3 100644 --- a/trunk/arch/arm/plat-omap/include/mach/mmc.h +++ b/trunk/arch/arm/plat-omap/include/mach/mmc.h @@ -25,18 +25,11 @@ #define OMAP24XX_NR_MMC 2 #define OMAP34XX_NR_MMC 3 -#define OMAP44XX_NR_MMC 5 #define OMAP2420_MMC_SIZE OMAP1_MMC_SIZE -#define OMAP3_HSMMC_SIZE 0x200 -#define OMAP4_HSMMC_SIZE 0x1000 +#define HSMMC_SIZE 0x200 #define OMAP2_MMC1_BASE 0x4809c000 #define OMAP2_MMC2_BASE 0x480b4000 #define OMAP3_MMC3_BASE 0x480ad000 -#define OMAP4_MMC4_BASE 0x480d1000 -#define OMAP4_MMC5_BASE 0x480d5000 -#define OMAP4_MMC_REG_OFFSET 0x100 -#define HSMMC5 (1 << 4) -#define HSMMC4 (1 << 3) #define HSMMC3 (1 << 2) #define HSMMC2 (1 << 1) #define HSMMC1 (1 << 0) @@ -66,9 +59,6 @@ struct omap_mmc_platform_data { int (*suspend)(struct device *dev, int slot); int (*resume)(struct device *dev, int slot); - /* Return context loss count due to PM states changing */ - int (*get_context_loss_count)(struct device *dev); - u64 dma_mask; struct omap_mmc_slot_data { @@ -90,20 +80,12 @@ struct omap_mmc_platform_data { /* use the internal clock */ unsigned internal_clock:1; - /* nonremovable e.g. eMMC */ - unsigned nonremovable:1; - - /* Try to sleep or power off when possible */ - unsigned power_saving:1; - int switch_pin; /* gpio (card detect) */ int gpio_wp; /* gpio (write protect) */ int (* set_bus_mode)(struct device *dev, int slot, int bus_mode); int (* set_power)(struct device *dev, int slot, int power_on, int vdd); int (* get_ro)(struct device *dev, int slot); - int (*set_sleep)(struct device *dev, int slot, int sleep, - int vdd, int cardsleep); /* return MMC cover switch state, can be NULL if not supported. * diff --git a/trunk/arch/arm/plat-omap/include/mach/omapfb.h b/trunk/arch/arm/plat-omap/include/mach/omapfb.h index b226bdf45739..7b74d1255e0b 100644 --- a/trunk/arch/arm/plat-omap/include/mach/omapfb.h +++ b/trunk/arch/arm/plat-omap/include/mach/omapfb.h @@ -276,8 +276,8 @@ typedef int (*omapfb_notifier_callback_t)(struct notifier_block *, void *fbi); struct omapfb_mem_region { - u32 paddr; - void __iomem *vaddr; + dma_addr_t paddr; + void *vaddr; unsigned long size; u8 type; /* OMAPFB_PLANE_MEM_* */ unsigned alloc:1; /* allocated by the driver */ diff --git a/trunk/arch/blackfin/include/asm/sections.h b/trunk/arch/blackfin/include/asm/sections.h index ae4dae1e370b..e7fd0ecd73f7 100644 --- a/trunk/arch/blackfin/include/asm/sections.h +++ b/trunk/arch/blackfin/include/asm/sections.h @@ -1,6 +1,9 @@ #ifndef _BLACKFIN_SECTIONS_H #define _BLACKFIN_SECTIONS_H +/* nothing to see, move along */ +#include + /* only used when MTD_UCLINUX */ extern unsigned long memory_mtd_start, memory_mtd_end, mtd_size; @@ -12,39 +15,4 @@ extern char _stext_l1[], _etext_l1[], _sdata_l1[], _edata_l1[], _sbss_l1[], _stext_l2[], _etext_l2[], _sdata_l2[], _edata_l2[], _sbss_l2[], _ebss_l2[], _l2_lma_start[]; -#include - -/* Blackfin systems have discontinuous memory map and no virtualized memory */ -static inline int arch_is_kernel_text(unsigned long addr) -{ - return - (L1_CODE_LENGTH && - addr >= (unsigned long)_stext_l1 && - addr < (unsigned long)_etext_l1) - || - (L2_LENGTH && - addr >= (unsigned long)_stext_l2 && - addr < (unsigned long)_etext_l2); -} -#define arch_is_kernel_text(addr) arch_is_kernel_text(addr) - -static inline int arch_is_kernel_data(unsigned long addr) -{ - return - (L1_DATA_A_LENGTH && - addr >= (unsigned long)_sdata_l1 && - addr < (unsigned long)_ebss_l1) - || - (L1_DATA_B_LENGTH && - addr >= (unsigned long)_sdata_b_l1 && - addr < (unsigned long)_ebss_b_l1) - || - (L2_LENGTH && - addr >= (unsigned long)_sdata_l2 && - addr < (unsigned long)_ebss_l2); -} -#define arch_is_kernel_data(addr) arch_is_kernel_data(addr) - -#include - #endif diff --git a/trunk/arch/frv/include/asm/gdb-stub.h b/trunk/arch/frv/include/asm/gdb-stub.h index 2da716407ff2..24f9738670bd 100644 --- a/trunk/arch/frv/include/asm/gdb-stub.h +++ b/trunk/arch/frv/include/asm/gdb-stub.h @@ -90,6 +90,7 @@ extern void gdbstub_do_rx(void); extern asmlinkage void __debug_stub_init_break(void); extern asmlinkage void __break_hijack_kernel_event(void); extern asmlinkage void __break_hijack_kernel_event_breaks_here(void); +extern asmlinkage void start_kernel(void); extern asmlinkage void gdbstub_rx_handler(void); extern asmlinkage void gdbstub_rx_irq(void); diff --git a/trunk/arch/frv/kernel/debug-stub.c b/trunk/arch/frv/kernel/debug-stub.c index 2845139c8077..2f6c60c921e0 100644 --- a/trunk/arch/frv/kernel/debug-stub.c +++ b/trunk/arch/frv/kernel/debug-stub.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include diff --git a/trunk/arch/ia64/Kconfig b/trunk/arch/ia64/Kconfig index 6851e52ed5a2..011a1cdf0eb5 100644 --- a/trunk/arch/ia64/Kconfig +++ b/trunk/arch/ia64/Kconfig @@ -500,10 +500,6 @@ config HAVE_ARCH_NODEDATA_EXTENSION def_bool y depends on NUMA -config ARCH_PROC_KCORE_TEXT - def_bool y - depends on PROC_KCORE - config IA32_SUPPORT bool "Support for Linux/x86 binaries" help diff --git a/trunk/arch/ia64/hp/common/sba_iommu.c b/trunk/arch/ia64/hp/common/sba_iommu.c index 674a8374c6d9..8cfb001092ab 100644 --- a/trunk/arch/ia64/hp/common/sba_iommu.c +++ b/trunk/arch/ia64/hp/common/sba_iommu.c @@ -2026,21 +2026,24 @@ acpi_sba_ioc_add(struct acpi_device *device) struct ioc *ioc; acpi_status status; u64 hpa, length; + struct acpi_buffer buffer; struct acpi_device_info *dev_info; status = hp_acpi_csr_space(device->handle, &hpa, &length); if (ACPI_FAILURE(status)) return 1; - status = acpi_get_object_info(device->handle, &dev_info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(device->handle, &buffer); if (ACPI_FAILURE(status)) return 1; + dev_info = buffer.pointer; /* * For HWP0001, only SBA appears in ACPI namespace. It encloses the PCI * root bridges, and its CSR space includes the IOC function. */ - if (strncmp("HWP0001", dev_info->hardware_id.string, 7) == 0) { + if (strncmp("HWP0001", dev_info->hardware_id.value, 7) == 0) { hpa += ZX1_IOC_OFFSET; /* zx1 based systems default to kernel page size iommu pages */ if (!iovp_shift) diff --git a/trunk/arch/ia64/include/asm/cputime.h b/trunk/arch/ia64/include/asm/cputime.h index 7fa8a8594660..d20b998cb91d 100644 --- a/trunk/arch/ia64/include/asm/cputime.h +++ b/trunk/arch/ia64/include/asm/cputime.h @@ -30,7 +30,6 @@ typedef u64 cputime_t; typedef u64 cputime64_t; #define cputime_zero ((cputime_t)0) -#define cputime_one_jiffy jiffies_to_cputime(1) #define cputime_max ((~((cputime_t)0) >> 1) - 1) #define cputime_add(__a, __b) ((__a) + (__b)) #define cputime_sub(__a, __b) ((__a) - (__b)) diff --git a/trunk/arch/ia64/kernel/pci-swiotlb.c b/trunk/arch/ia64/kernel/pci-swiotlb.c index 285aae8431c6..223abb134105 100644 --- a/trunk/arch/ia64/kernel/pci-swiotlb.c +++ b/trunk/arch/ia64/kernel/pci-swiotlb.c @@ -46,7 +46,7 @@ void __init swiotlb_dma_init(void) void __init pci_swiotlb_init(void) { - if (!iommu_detected) { + if (!iommu_detected || iommu_pass_through) { #ifdef CONFIG_IA64_GENERIC swiotlb = 1; printk(KERN_INFO "PCI-DMA: Re-initialize machine vector.\n"); diff --git a/trunk/arch/ia64/mm/init.c b/trunk/arch/ia64/mm/init.c index 1857766a63c1..1d286244a562 100644 --- a/trunk/arch/ia64/mm/init.c +++ b/trunk/arch/ia64/mm/init.c @@ -617,6 +617,7 @@ mem_init (void) long reserved_pages, codesize, datasize, initsize; pg_data_t *pgdat; int i; + static struct kcore_list kcore_mem, kcore_vmem, kcore_kernel; BUG_ON(PTRS_PER_PGD * sizeof(pgd_t) != PAGE_SIZE); BUG_ON(PTRS_PER_PMD * sizeof(pmd_t) != PAGE_SIZE); @@ -638,6 +639,10 @@ mem_init (void) high_memory = __va(max_low_pfn * PAGE_SIZE); + kclist_add(&kcore_mem, __va(0), max_low_pfn * PAGE_SIZE); + kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); + kclist_add(&kcore_kernel, _stext, _end - _stext); + for_each_online_pgdat(pgdat) if (pgdat->bdata->node_bootmem_map) totalram_pages += free_all_bootmem_node(pgdat); diff --git a/trunk/arch/mips/mm/init.c b/trunk/arch/mips/mm/init.c index 15aa1902a788..1f4ee4797a6e 100644 --- a/trunk/arch/mips/mm/init.c +++ b/trunk/arch/mips/mm/init.c @@ -352,6 +352,7 @@ void __init paging_init(void) free_area_init_nodes(max_zone_pfns); } +static struct kcore_list kcore_mem, kcore_vmalloc; #ifdef CONFIG_64BIT static struct kcore_list kcore_kseg0; #endif @@ -408,9 +409,11 @@ void __init mem_init(void) if ((unsigned long) &_text > (unsigned long) CKSEG0) /* The -4 is a hack so that user tools don't have to handle the overflow. */ - kclist_add(&kcore_kseg0, (void *) CKSEG0, - 0x80000000 - 4, KCORE_TEXT); + kclist_add(&kcore_kseg0, (void *) CKSEG0, 0x80000000 - 4); #endif + kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); + kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, + VMALLOC_END-VMALLOC_START); printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " "%ldk reserved, %ldk data, %ldk init, %ldk highmem)\n", diff --git a/trunk/arch/mn10300/include/asm/gdb-stub.h b/trunk/arch/mn10300/include/asm/gdb-stub.h index 556cce992548..e5a6368559af 100644 --- a/trunk/arch/mn10300/include/asm/gdb-stub.h +++ b/trunk/arch/mn10300/include/asm/gdb-stub.h @@ -109,6 +109,7 @@ extern asmlinkage int gdbstub_intercept(struct pt_regs *, enum exception_code); extern asmlinkage void gdbstub_exception(struct pt_regs *, enum exception_code); extern asmlinkage void __gdbstub_bug_trap(void); extern asmlinkage void __gdbstub_pause(void); +extern asmlinkage void start_kernel(void); #ifndef CONFIG_MN10300_CACHE_DISABLED extern asmlinkage void gdbstub_purge_cache(void); diff --git a/trunk/arch/mn10300/kernel/setup.c b/trunk/arch/mn10300/kernel/setup.c index 3f24c298a3af..79890edfd67a 100644 --- a/trunk/arch/mn10300/kernel/setup.c +++ b/trunk/arch/mn10300/kernel/setup.c @@ -285,7 +285,7 @@ static void c_stop(struct seq_file *m, void *v) { } -const struct seq_operations cpuinfo_op = { +struct seq_operations cpuinfo_op = { .start = c_start, .next = c_next, .stop = c_stop, diff --git a/trunk/arch/powerpc/boot/dts/mpc8377_mds.dts b/trunk/arch/powerpc/boot/dts/mpc8377_mds.dts index 855782c5e5ec..f32c2811c6d9 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8377_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8377_mds.dts @@ -159,7 +159,6 @@ reg = <0x2e000 0x1000>; interrupts = <42 0x8>; interrupt-parent = <&ipic>; - sdhci,wp-inverted; /* Filled in by U-Boot */ clock-frequency = <0>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts b/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts index 9e2264b10008..28e022ac4179 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8377_rdb.dts @@ -173,7 +173,6 @@ reg = <0x2e000 0x1000>; interrupts = <42 0x8>; interrupt-parent = <&ipic>; - sdhci,wp-inverted; /* Filled in by U-Boot */ clock-frequency = <111111111>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8377_wlan.dts b/trunk/arch/powerpc/boot/dts/mpc8377_wlan.dts index 9a603695723b..3febc4e91b10 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8377_wlan.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8377_wlan.dts @@ -150,7 +150,6 @@ reg = <0x2e000 0x1000>; interrupts = <42 0x8>; interrupt-parent = <&ipic>; - sdhci,wp-inverted; clock-frequency = <133333333>; }; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8378_mds.dts b/trunk/arch/powerpc/boot/dts/mpc8378_mds.dts index f70cf6000839..f720ab9af30d 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8378_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8378_mds.dts @@ -159,7 +159,6 @@ reg = <0x2e000 0x1000>; interrupts = <42 0x8>; interrupt-parent = <&ipic>; - sdhci,wp-inverted; /* Filled in by U-Boot */ clock-frequency = <0>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts b/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts index 4e6a1a407bbd..a11ead8214b4 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8378_rdb.dts @@ -173,7 +173,6 @@ reg = <0x2e000 0x1000>; interrupts = <42 0x8>; interrupt-parent = <&ipic>; - sdhci,wp-inverted; /* Filled in by U-Boot */ clock-frequency = <111111111>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8379_mds.dts b/trunk/arch/powerpc/boot/dts/mpc8379_mds.dts index 645ec51cc6e1..4fa221fd9bdc 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8379_mds.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8379_mds.dts @@ -157,7 +157,6 @@ reg = <0x2e000 0x1000>; interrupts = <42 0x8>; interrupt-parent = <&ipic>; - sdhci,wp-inverted; /* Filled in by U-Boot */ clock-frequency = <0>; }; diff --git a/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts b/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts index 72336d504528..e35dfba587c8 100644 --- a/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts +++ b/trunk/arch/powerpc/boot/dts/mpc8379_rdb.dts @@ -171,7 +171,6 @@ reg = <0x2e000 0x1000>; interrupts = <42 0x8>; interrupt-parent = <&ipic>; - sdhci,wp-inverted; /* Filled in by U-Boot */ clock-frequency = <111111111>; }; diff --git a/trunk/arch/powerpc/include/asm/cputime.h b/trunk/arch/powerpc/include/asm/cputime.h index fa19f3fe05ff..f42e623030ee 100644 --- a/trunk/arch/powerpc/include/asm/cputime.h +++ b/trunk/arch/powerpc/include/asm/cputime.h @@ -18,9 +18,6 @@ #ifndef CONFIG_VIRT_CPU_ACCOUNTING #include -#ifdef __KERNEL__ -static inline void setup_cputime_one_jiffy(void) { } -#endif #else #include @@ -51,11 +48,6 @@ typedef u64 cputime64_t; #ifdef __KERNEL__ -/* - * One jiffy in timebase units computed during initialization - */ -extern cputime_t cputime_one_jiffy; - /* * Convert cputime <-> jiffies */ @@ -97,11 +89,6 @@ static inline cputime_t jiffies_to_cputime(const unsigned long jif) return ct; } -static inline void setup_cputime_one_jiffy(void) -{ - cputime_one_jiffy = jiffies_to_cputime(1); -} - static inline cputime64_t jiffies64_to_cputime64(const u64 jif) { cputime_t ct; diff --git a/trunk/arch/powerpc/kernel/setup-common.c b/trunk/arch/powerpc/kernel/setup-common.c index 1d5570a1e456..02fed27af7f6 100644 --- a/trunk/arch/powerpc/kernel/setup-common.c +++ b/trunk/arch/powerpc/kernel/setup-common.c @@ -328,7 +328,7 @@ static void c_stop(struct seq_file *m, void *v) { } -const struct seq_operations cpuinfo_op = { +struct seq_operations cpuinfo_op = { .start =c_start, .next = c_next, .stop = c_stop, diff --git a/trunk/arch/powerpc/kernel/time.c b/trunk/arch/powerpc/kernel/time.c index 92dc844299b6..df45a7449a66 100644 --- a/trunk/arch/powerpc/kernel/time.c +++ b/trunk/arch/powerpc/kernel/time.c @@ -193,8 +193,6 @@ EXPORT_SYMBOL(__cputime_clockt_factor); DEFINE_PER_CPU(unsigned long, cputime_last_delta); DEFINE_PER_CPU(unsigned long, cputime_scaled_last_delta); -cputime_t cputime_one_jiffy; - static void calc_cputime_factors(void) { struct div_result res; @@ -503,7 +501,6 @@ static int __init iSeries_tb_recal(void) tb_to_xs = divres.result_low; vdso_data->tb_ticks_per_sec = tb_ticks_per_sec; vdso_data->tb_to_xs = tb_to_xs; - setup_cputime_one_jiffy(); } else { printk( "Titan recalibrate: FAILED (difference > 4 percent)\n" @@ -963,7 +960,6 @@ void __init time_init(void) tb_ticks_per_usec = ppc_tb_freq / 1000000; tb_to_us = mulhwu_scale_factor(ppc_tb_freq, 1000000); calc_cputime_factors(); - setup_cputime_one_jiffy(); /* * Calculate the length of each tick in ns. It will not be diff --git a/trunk/arch/powerpc/mm/init_32.c b/trunk/arch/powerpc/mm/init_32.c index 9ddcfb4dc139..3ef5084b90ca 100644 --- a/trunk/arch/powerpc/mm/init_32.c +++ b/trunk/arch/powerpc/mm/init_32.c @@ -242,3 +242,39 @@ void free_initrd_mem(unsigned long start, unsigned long end) } #endif +#ifdef CONFIG_PROC_KCORE +static struct kcore_list kcore_vmem; + +static int __init setup_kcore(void) +{ + int i; + + for (i = 0; i < lmb.memory.cnt; i++) { + unsigned long base; + unsigned long size; + struct kcore_list *kcore_mem; + + base = lmb.memory.region[i].base; + size = lmb.memory.region[i].size; + + kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC); + if (!kcore_mem) + panic("%s: kmalloc failed\n", __func__); + + /* must stay under 32 bits */ + if ( 0xfffffffful - (unsigned long)__va(base) < size) { + size = 0xfffffffful - (unsigned long)(__va(base)); + printk(KERN_DEBUG "setup_kcore: restrict size=%lx\n", + size); + } + + kclist_add(kcore_mem, __va(base), size); + } + + kclist_add(&kcore_vmem, (void *)VMALLOC_START, + VMALLOC_END-VMALLOC_START); + + return 0; +} +module_init(setup_kcore); +#endif diff --git a/trunk/arch/powerpc/mm/init_64.c b/trunk/arch/powerpc/mm/init_64.c index 335c578b9cc3..31582329cd67 100644 --- a/trunk/arch/powerpc/mm/init_64.c +++ b/trunk/arch/powerpc/mm/init_64.c @@ -109,6 +109,35 @@ void free_initrd_mem(unsigned long start, unsigned long end) } #endif +#ifdef CONFIG_PROC_KCORE +static struct kcore_list kcore_vmem; + +static int __init setup_kcore(void) +{ + int i; + + for (i=0; i < lmb.memory.cnt; i++) { + unsigned long base, size; + struct kcore_list *kcore_mem; + + base = lmb.memory.region[i].base; + size = lmb.memory.region[i].size; + + /* GFP_ATOMIC to avoid might_sleep warnings during boot */ + kcore_mem = kmalloc(sizeof(struct kcore_list), GFP_ATOMIC); + if (!kcore_mem) + panic("%s: kmalloc failed\n", __func__); + + kclist_add(kcore_mem, __va(base), size); + } + + kclist_add(&kcore_vmem, (void *)VMALLOC_START, VMALLOC_END-VMALLOC_START); + + return 0; +} +module_init(setup_kcore); +#endif + static void pgd_ctor(void *addr) { memset(addr, 0, PGD_TABLE_SIZE); diff --git a/trunk/arch/powerpc/mm/mem.c b/trunk/arch/powerpc/mm/mem.c index 59736317bf0e..0e5c59b995ef 100644 --- a/trunk/arch/powerpc/mm/mem.c +++ b/trunk/arch/powerpc/mm/mem.c @@ -143,8 +143,8 @@ int arch_add_memory(int nid, u64 start, u64 size) * memory regions, find holes and callback for contiguous regions. */ int -walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, - void *arg, int (*func)(unsigned long, unsigned long, void *)) +walk_memory_resource(unsigned long start_pfn, unsigned long nr_pages, void *arg, + int (*func)(unsigned long, unsigned long, void *)) { struct lmb_property res; unsigned long pfn, len; @@ -166,7 +166,7 @@ walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages, } return ret; } -EXPORT_SYMBOL_GPL(walk_system_ram_range); +EXPORT_SYMBOL_GPL(walk_memory_resource); /* * Initialize the bootmem system and give it all the memory we diff --git a/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c b/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c index 3631a4f277eb..eae51ef9af24 100644 --- a/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c +++ b/trunk/arch/powerpc/platforms/pseries/hvCall_inst.c @@ -71,7 +71,7 @@ static int hc_show(struct seq_file *m, void *p) return 0; } -static const struct seq_operations hcall_inst_seq_ops = { +static struct seq_operations hcall_inst_seq_ops = { .start = hc_start, .next = hc_next, .stop = hc_stop, diff --git a/trunk/arch/s390/defconfig b/trunk/arch/s390/defconfig index ab4464486b7a..4e91a2573cc4 100644 --- a/trunk/arch/s390/defconfig +++ b/trunk/arch/s390/defconfig @@ -1,7 +1,7 @@ # # Automatically generated make config: don't edit -# Linux kernel version: 2.6.31 -# Tue Sep 22 17:43:13 2009 +# Linux kernel version: 2.6.30 +# Mon Jun 22 11:08:16 2009 # CONFIG_SCHED_MC=y CONFIG_MMU=y @@ -24,7 +24,6 @@ CONFIG_PGSTE=y CONFIG_VIRT_CPU_ACCOUNTING=y CONFIG_ARCH_SUPPORTS_DEBUG_PAGEALLOC=y CONFIG_S390=y -CONFIG_SCHED_OMIT_FRAME_POINTER=y CONFIG_DEFCONFIG_LIST="/lib/modules/$UNAME_RELEASE/.config" CONFIG_CONSTRUCTORS=y @@ -49,12 +48,11 @@ CONFIG_AUDIT=y # # RCU Subsystem # -CONFIG_TREE_RCU=y -# CONFIG_TREE_PREEMPT_RCU is not set -# CONFIG_RCU_TRACE is not set -CONFIG_RCU_FANOUT=64 -# CONFIG_RCU_FANOUT_EXACT is not set +CONFIG_CLASSIC_RCU=y +# CONFIG_TREE_RCU is not set +# CONFIG_PREEMPT_RCU is not set # CONFIG_TREE_RCU_TRACE is not set +# CONFIG_PREEMPT_RCU_TRACE is not set CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=17 @@ -105,12 +103,11 @@ CONFIG_TIMERFD=y CONFIG_EVENTFD=y CONFIG_SHMEM=y CONFIG_AIO=y -CONFIG_HAVE_PERF_EVENTS=y +CONFIG_HAVE_PERF_COUNTERS=y # -# Kernel Performance Events And Counters +# Performance Counters # -# CONFIG_PERF_EVENTS is not set # CONFIG_PERF_COUNTERS is not set CONFIG_VM_EVENT_COUNTERS=y # CONFIG_STRIP_ASM_SYMS is not set @@ -119,6 +116,7 @@ CONFIG_SLAB=y # CONFIG_SLUB is not set # CONFIG_SLOB is not set # CONFIG_PROFILING is not set +# CONFIG_MARKERS is not set CONFIG_HAVE_OPROFILE=y CONFIG_KPROBES=y CONFIG_HAVE_SYSCALL_WRAPPERS=y @@ -178,7 +176,6 @@ CONFIG_NO_HZ=y CONFIG_HIGH_RES_TIMERS=y CONFIG_GENERIC_CLOCKEVENTS_BUILD=y CONFIG_64BIT=y -# CONFIG_KTIME_SCALAR is not set CONFIG_SMP=y CONFIG_NR_CPUS=32 CONFIG_HOTPLUG_CPU=y @@ -260,6 +257,7 @@ CONFIG_FORCE_MAX_ZONEORDER=9 CONFIG_PFAULT=y # CONFIG_SHARED_KERNEL is not set # CONFIG_CMM is not set +# CONFIG_PAGE_STATES is not set # CONFIG_APPLDATA_BASE is not set CONFIG_HZ_100=y # CONFIG_HZ_250 is not set @@ -282,7 +280,6 @@ CONFIG_PM_SLEEP_SMP=y CONFIG_PM_SLEEP=y CONFIG_HIBERNATION=y CONFIG_PM_STD_PARTITION="" -# CONFIG_PM_RUNTIME is not set CONFIG_NET=y # @@ -397,7 +394,6 @@ CONFIG_IP_SCTP=m # CONFIG_SCTP_HMAC_NONE is not set # CONFIG_SCTP_HMAC_SHA1 is not set CONFIG_SCTP_HMAC_MD5=y -# CONFIG_RDS is not set # CONFIG_TIPC is not set # CONFIG_ATM is not set # CONFIG_BRIDGE is not set @@ -491,7 +487,6 @@ CONFIG_CCW=y # Generic Driver Options # CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" -# CONFIG_DEVTMPFS is not set CONFIG_STANDALONE=y CONFIG_PREVENT_FIRMWARE_BUILD=y CONFIG_FW_LOADER=y @@ -506,7 +501,6 @@ CONFIG_BLK_DEV=y CONFIG_BLK_DEV_LOOP=m # CONFIG_BLK_DEV_CRYPTOLOOP is not set CONFIG_BLK_DEV_NBD=m -# CONFIG_BLK_DEV_OSD is not set CONFIG_BLK_DEV_RAM=y CONFIG_BLK_DEV_RAM_COUNT=16 CONFIG_BLK_DEV_RAM_SIZE=4096 @@ -600,11 +594,8 @@ CONFIG_BLK_DEV_DM=y CONFIG_DM_CRYPT=y CONFIG_DM_SNAPSHOT=y CONFIG_DM_MIRROR=y -# CONFIG_DM_LOG_USERSPACE is not set CONFIG_DM_ZERO=y CONFIG_DM_MULTIPATH=m -# CONFIG_DM_MULTIPATH_QL is not set -# CONFIG_DM_MULTIPATH_ST is not set # CONFIG_DM_DELAY is not set # CONFIG_DM_UEVENT is not set CONFIG_NETDEVICES=y @@ -624,6 +615,7 @@ CONFIG_NET_ETHERNET=y # CONFIG_IBM_NEW_EMAC_NO_FLOW_CTRL is not set # CONFIG_IBM_NEW_EMAC_MAL_CLR_ICINTSTAT is not set # CONFIG_IBM_NEW_EMAC_MAL_COMMON_ERR is not set +# CONFIG_KS8842 is not set CONFIG_NETDEV_1000=y CONFIG_NETDEV_10000=y # CONFIG_TR is not set @@ -686,7 +678,6 @@ CONFIG_SCLP_CONSOLE=y CONFIG_SCLP_VT220_TTY=y CONFIG_SCLP_VT220_CONSOLE=y CONFIG_SCLP_CPI=m -CONFIG_SCLP_ASYNC=m CONFIG_S390_TAPE=m # @@ -746,7 +737,6 @@ CONFIG_FS_POSIX_ACL=y # CONFIG_GFS2_FS is not set # CONFIG_OCFS2_FS is not set # CONFIG_BTRFS_FS is not set -# CONFIG_NILFS2_FS is not set CONFIG_FILE_LOCKING=y CONFIG_FSNOTIFY=y CONFIG_DNOTIFY=y @@ -808,6 +798,7 @@ CONFIG_MISC_FILESYSTEMS=y # CONFIG_SYSV_FS is not set # CONFIG_UFS_FS is not set # CONFIG_EXOFS_FS is not set +# CONFIG_NILFS2_FS is not set CONFIG_NETWORK_FILESYSTEMS=y CONFIG_NFS_FS=y CONFIG_NFS_V3=y @@ -894,13 +885,11 @@ CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_DEBUG_LIST is not set # CONFIG_DEBUG_SG is not set # CONFIG_DEBUG_NOTIFIERS is not set -# CONFIG_DEBUG_CREDENTIALS is not set # CONFIG_RCU_TORTURE_TEST is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set # CONFIG_KPROBES_SANITY_TEST is not set # CONFIG_BACKTRACE_SELF_TEST is not set # CONFIG_DEBUG_BLOCK_EXT_DEVT is not set -CONFIG_DEBUG_FORCE_WEAK_PER_CPU=y # CONFIG_LKDTM is not set # CONFIG_FAULT_INJECTION is not set # CONFIG_LATENCYTOP is not set @@ -990,13 +979,11 @@ CONFIG_CRYPTO_PCBC=m # CONFIG_CRYPTO_HMAC=m # CONFIG_CRYPTO_XCBC is not set -CONFIG_CRYPTO_VMAC=m # # Digest # CONFIG_CRYPTO_CRC32C=m -CONFIG_CRYPTO_GHASH=m # CONFIG_CRYPTO_MD4 is not set CONFIG_CRYPTO_MD5=m # CONFIG_CRYPTO_MICHAEL_MIC is not set diff --git a/trunk/arch/s390/include/asm/cputime.h b/trunk/arch/s390/include/asm/cputime.h index 24b1244aadb9..7a3817a656df 100644 --- a/trunk/arch/s390/include/asm/cputime.h +++ b/trunk/arch/s390/include/asm/cputime.h @@ -42,7 +42,6 @@ __div(unsigned long long n, unsigned int base) #endif /* __s390x__ */ #define cputime_zero (0ULL) -#define cputime_one_jiffy jiffies_to_cputime(1) #define cputime_max ((~0UL >> 1) - 1) #define cputime_add(__a, __b) ((__a) + (__b)) #define cputime_sub(__a, __b) ((__a) - (__b)) diff --git a/trunk/arch/s390/include/asm/lowcore.h b/trunk/arch/s390/include/asm/lowcore.h index f2ef4b619ce1..6bc9426a6fbf 100644 --- a/trunk/arch/s390/include/asm/lowcore.h +++ b/trunk/arch/s390/include/asm/lowcore.h @@ -86,7 +86,6 @@ #define __LC_PGM_OLD_PSW 0x0150 #define __LC_MCK_OLD_PSW 0x0160 #define __LC_IO_OLD_PSW 0x0170 -#define __LC_RESTART_PSW 0x01a0 #define __LC_EXT_NEW_PSW 0x01b0 #define __LC_SVC_NEW_PSW 0x01c0 #define __LC_PGM_NEW_PSW 0x01d0 @@ -190,14 +189,6 @@ union save_area { #define SAVE_AREA_BASE SAVE_AREA_BASE_S390X #endif -#ifndef __s390x__ -#define LC_ORDER 0 -#else -#define LC_ORDER 1 -#endif - -#define LC_PAGES (1UL << LC_ORDER) - struct _lowcore { #ifndef __s390x__ diff --git a/trunk/arch/s390/include/asm/processor.h b/trunk/arch/s390/include/asm/processor.h index b42715458312..cf8eed3fa779 100644 --- a/trunk/arch/s390/include/asm/processor.h +++ b/trunk/arch/s390/include/asm/processor.h @@ -295,7 +295,7 @@ static inline void ATTRIB_NORET disabled_wait(unsigned long code) " oi 0x384(1),0x10\n"/* fake protection bit */ " lpswe 0(%1)" : "=m" (ctl_buf) - : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0", "1"); + : "a" (&dw_psw), "a" (&ctl_buf), "m" (dw_psw) : "cc", "0"); #endif /* __s390x__ */ while (1); } diff --git a/trunk/arch/s390/kernel/asm-offsets.c b/trunk/arch/s390/kernel/asm-offsets.c index 63e46433e81d..fa9905ce7d0b 100644 --- a/trunk/arch/s390/kernel/asm-offsets.c +++ b/trunk/arch/s390/kernel/asm-offsets.c @@ -7,7 +7,6 @@ #include #include #include -#include int main(void) { @@ -60,10 +59,6 @@ int main(void) DEFINE(CLOCK_REALTIME, CLOCK_REALTIME); DEFINE(CLOCK_MONOTONIC, CLOCK_MONOTONIC); DEFINE(CLOCK_REALTIME_RES, MONOTONIC_RES_NSEC); - /* constants for SIGP */ - DEFINE(__SIGP_STOP, sigp_stop); - DEFINE(__SIGP_RESTART, sigp_restart); - DEFINE(__SIGP_SENSE, sigp_sense); - DEFINE(__SIGP_INITIAL_CPU_RESET, sigp_initial_cpu_reset); + return 0; } diff --git a/trunk/arch/s390/kernel/compat_linux.c b/trunk/arch/s390/kernel/compat_linux.c index 5519cb745106..9ab188d67a3d 100644 --- a/trunk/arch/s390/kernel/compat_linux.c +++ b/trunk/arch/s390/kernel/compat_linux.c @@ -443,28 +443,66 @@ sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo) * sys32_execve() executes a new program after the asm stub has set * things up for us. This should basically do what I want it to. */ -asmlinkage long sys32_execve(char __user *name, compat_uptr_t __user *argv, - compat_uptr_t __user *envp) +asmlinkage long sys32_execve(void) { struct pt_regs *regs = task_pt_regs(current); char *filename; - long rc; - - filename = getname(name); - rc = PTR_ERR(filename); - if (IS_ERR(filename)) - return rc; - rc = compat_do_execve(filename, argv, envp, regs); - if (rc) - goto out; + unsigned long result; + int rc; + + filename = getname(compat_ptr(regs->orig_gpr2)); + if (IS_ERR(filename)) { + result = PTR_ERR(filename); + goto out; + } + rc = compat_do_execve(filename, compat_ptr(regs->gprs[3]), + compat_ptr(regs->gprs[4]), regs); + if (rc) { + result = rc; + goto out_putname; + } current->thread.fp_regs.fpc=0; asm volatile("sfpc %0,0" : : "d" (0)); - rc = regs->gprs[2]; + result = regs->gprs[2]; +out_putname: + putname(filename); out: - putname(filename); - return rc; + return result; +} + + +#ifdef CONFIG_MODULES + +asmlinkage long +sys32_init_module(void __user *umod, unsigned long len, + const char __user *uargs) +{ + return sys_init_module(umod, len, uargs); +} + +asmlinkage long +sys32_delete_module(const char __user *name_user, unsigned int flags) +{ + return sys_delete_module(name_user, flags); +} + +#else /* CONFIG_MODULES */ + +asmlinkage long +sys32_init_module(void __user *umod, unsigned long len, + const char __user *uargs) +{ + return -ENOSYS; } +asmlinkage long +sys32_delete_module(const char __user *name_user, unsigned int flags) +{ + return -ENOSYS; +} + +#endif /* CONFIG_MODULES */ + asmlinkage long sys32_pread64(unsigned int fd, char __user *ubuf, size_t count, u32 poshi, u32 poslo) { @@ -763,6 +801,23 @@ asmlinkage long sys32_write(unsigned int fd, char __user * buf, size_t count) return sys_write(fd, buf, count); } +asmlinkage long sys32_clone(void) +{ + struct pt_regs *regs = task_pt_regs(current); + unsigned long clone_flags; + unsigned long newsp; + int __user *parent_tidptr, *child_tidptr; + + clone_flags = regs->gprs[3] & 0xffffffffUL; + newsp = regs->orig_gpr2 & 0x7fffffffUL; + parent_tidptr = compat_ptr(regs->gprs[4]); + child_tidptr = compat_ptr(regs->gprs[5]); + if (!newsp) + newsp = regs->gprs[15]; + return do_fork(clone_flags, newsp, regs, 0, + parent_tidptr, child_tidptr); +} + /* * 31 bit emulation wrapper functions for sys_fadvise64/fadvise64_64. * These need to rewrite the advise values for POSIX_FADV_{DONTNEED,NOREUSE} diff --git a/trunk/arch/s390/kernel/compat_linux.h b/trunk/arch/s390/kernel/compat_linux.h index c07f9ca05ade..836a28842900 100644 --- a/trunk/arch/s390/kernel/compat_linux.h +++ b/trunk/arch/s390/kernel/compat_linux.h @@ -198,8 +198,7 @@ long sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset, size_t sigsetsize); long sys32_rt_sigpending(compat_sigset_t __user *set, size_t sigsetsize); long sys32_rt_sigqueueinfo(int pid, int sig, compat_siginfo_t __user *uinfo); -long sys32_execve(char __user *name, compat_uptr_t __user *argv, - compat_uptr_t __user *envp); +long sys32_execve(void); long sys32_init_module(void __user *umod, unsigned long len, const char __user *uargs); long sys32_delete_module(const char __user *name_user, unsigned int flags); @@ -223,6 +222,7 @@ unsigned long old32_mmap(struct mmap_arg_struct_emu31 __user *arg); long sys32_mmap2(struct mmap_arg_struct_emu31 __user *arg); long sys32_read(unsigned int fd, char __user * buf, size_t count); long sys32_write(unsigned int fd, char __user * buf, size_t count); +long sys32_clone(void); long sys32_fadvise64(int fd, loff_t offset, size_t len, int advise); long sys32_fadvise64_64(struct fadvise64_64_args __user *args); long sys32_sigaction(int sig, const struct old_sigaction32 __user *act, diff --git a/trunk/arch/s390/kernel/compat_wrapper.S b/trunk/arch/s390/kernel/compat_wrapper.S index 682fb69dba21..624790042d41 100644 --- a/trunk/arch/s390/kernel/compat_wrapper.S +++ b/trunk/arch/s390/kernel/compat_wrapper.S @@ -568,18 +568,18 @@ compat_sys_sigprocmask_wrapper: llgtr %r4,%r4 # compat_old_sigset_t * jg compat_sys_sigprocmask # branch to system call - .globl sys_init_module_wrapper -sys_init_module_wrapper: + .globl sys32_init_module_wrapper +sys32_init_module_wrapper: llgtr %r2,%r2 # void * llgfr %r3,%r3 # unsigned long llgtr %r4,%r4 # char * - jg sys_init_module # branch to system call + jg sys32_init_module # branch to system call - .globl sys_delete_module_wrapper -sys_delete_module_wrapper: + .globl sys32_delete_module_wrapper +sys32_delete_module_wrapper: llgtr %r2,%r2 # const char * llgfr %r3,%r3 # unsigned int - jg sys_delete_module # branch to system call + jg sys32_delete_module # branch to system call .globl sys32_quotactl_wrapper sys32_quotactl_wrapper: @@ -1840,18 +1840,3 @@ sys_perf_event_open_wrapper: lgfr %r5,%r5 # int llgfr %r6,%r6 # unsigned long jg sys_perf_event_open # branch to system call - - .globl sys_clone_wrapper -sys_clone_wrapper: - llgfr %r2,%r2 # unsigned long - llgfr %r3,%r3 # unsigned long - llgtr %r4,%r4 # int * - llgtr %r5,%r5 # int * - jg sys_clone # branch to system call - - .globl sys32_execve_wrapper -sys32_execve_wrapper: - llgtr %r2,%r2 # char * - llgtr %r3,%r3 # compat_uptr_t * - llgtr %r4,%r4 # compat_uptr_t * - jg sys32_execve # branch to system call diff --git a/trunk/arch/s390/kernel/entry.h b/trunk/arch/s390/kernel/entry.h index e1e5e767ab56..950c59c6688b 100644 --- a/trunk/arch/s390/kernel/entry.h +++ b/trunk/arch/s390/kernel/entry.h @@ -42,12 +42,10 @@ long sys_s390_fadvise64_64(struct fadvise64_64_args __user *args); long sys_s390_fallocate(int fd, int mode, loff_t offset, u32 len_high, u32 len_low); long sys_fork(void); -long sys_clone(unsigned long newsp, unsigned long clone_flags, - int __user *parent_tidptr, int __user *child_tidptr); +long sys_clone(void); long sys_vfork(void); void execve_tail(void); -long sys_execve(char __user *name, char __user * __user *argv, - char __user * __user *envp); +long sys_execve(void); long sys_sigsuspend(int history0, int history1, old_sigset_t mask); long sys_sigaction(int sig, const struct old_sigaction __user *act, struct old_sigaction __user *oact); diff --git a/trunk/arch/s390/kernel/process.c b/trunk/arch/s390/kernel/process.c index 59fe6ecc6ed3..5a43f27eec13 100644 --- a/trunk/arch/s390/kernel/process.c +++ b/trunk/arch/s390/kernel/process.c @@ -32,7 +32,6 @@ #include #include #include -#include #include #include #include @@ -231,11 +230,17 @@ SYSCALL_DEFINE0(fork) return do_fork(SIGCHLD, regs->gprs[15], regs, 0, NULL, NULL); } -SYSCALL_DEFINE4(clone, unsigned long, newsp, unsigned long, clone_flags, - int __user *, parent_tidptr, int __user *, child_tidptr) +SYSCALL_DEFINE0(clone) { struct pt_regs *regs = task_pt_regs(current); + unsigned long clone_flags; + unsigned long newsp; + int __user *parent_tidptr, *child_tidptr; + clone_flags = regs->gprs[3]; + newsp = regs->orig_gpr2; + parent_tidptr = (int __user *) regs->gprs[4]; + child_tidptr = (int __user *) regs->gprs[5]; if (!newsp) newsp = regs->gprs[15]; return do_fork(clone_flags, newsp, regs, 0, @@ -269,25 +274,30 @@ asmlinkage void execve_tail(void) /* * sys_execve() executes a new program. */ -SYSCALL_DEFINE3(execve, char __user *, name, char __user * __user *, argv, - char __user * __user *, envp) +SYSCALL_DEFINE0(execve) { struct pt_regs *regs = task_pt_regs(current); char *filename; - long rc; + unsigned long result; + int rc; - filename = getname(name); - rc = PTR_ERR(filename); - if (IS_ERR(filename)) - return rc; - rc = do_execve(filename, argv, envp, regs); - if (rc) + filename = getname((char __user *) regs->orig_gpr2); + if (IS_ERR(filename)) { + result = PTR_ERR(filename); goto out; + } + rc = do_execve(filename, (char __user * __user *) regs->gprs[3], + (char __user * __user *) regs->gprs[4], regs); + if (rc) { + result = rc; + goto out_putname; + } execve_tail(); - rc = regs->gprs[2]; -out: + result = regs->gprs[2]; +out_putname: putname(filename); - return rc; +out: + return result; } /* diff --git a/trunk/arch/s390/kernel/ptrace.c b/trunk/arch/s390/kernel/ptrace.c index a8738676b26c..f3ddd7ac06c5 100644 --- a/trunk/arch/s390/kernel/ptrace.c +++ b/trunk/arch/s390/kernel/ptrace.c @@ -339,10 +339,24 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) int copied, ret; switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + /* Remove high order bit from address (only for 31 bit). */ + addr &= PSW_ADDR_INSN; + /* read word at location addr. */ + return generic_ptrace_peekdata(child, addr, data); + case PTRACE_PEEKUSR: /* read the word at location addr in the USER area. */ return peek_user(child, addr, data); + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + /* Remove high order bit from address (only for 31 bit). */ + addr &= PSW_ADDR_INSN; + /* write the word at location addr. */ + return generic_ptrace_pokedata(child, addr, data); + case PTRACE_POKEUSR: /* write the word at location addr in the USER area */ return poke_user(child, addr, data); @@ -372,11 +386,8 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) copied += sizeof(unsigned long); } return 0; - default: - /* Removing high order bit from addr (only for 31 bit). */ - addr &= PSW_ADDR_INSN; - return ptrace_request(child, request, addr, data); } + return ptrace_request(child, request, addr, data); } #ifdef CONFIG_COMPAT diff --git a/trunk/arch/s390/kernel/sclp.S b/trunk/arch/s390/kernel/sclp.S index e27ca63076d1..20639dfe0c42 100644 --- a/trunk/arch/s390/kernel/sclp.S +++ b/trunk/arch/s390/kernel/sclp.S @@ -24,6 +24,8 @@ LC_EXT_INT_CODE = 0x86 # addr of ext int code # R3 = external interruption parameter if R2=0 # +.section ".init.text","ax" + _sclp_wait_int: stm %r6,%r15,24(%r15) # save registers basr %r13,0 # get base register @@ -316,8 +318,9 @@ _sclp_print_early: .long _sclp_work_area .Lascebc: .long _ascebc +.previous -.section .data,"aw",@progbits +.section ".init.data","a" .balign 4096 _sclp_work_area: .fill 4096 diff --git a/trunk/arch/s390/kernel/smp.c b/trunk/arch/s390/kernel/smp.c index b4b6396e6cf0..56c16876b919 100644 --- a/trunk/arch/s390/kernel/smp.c +++ b/trunk/arch/s390/kernel/smp.c @@ -475,8 +475,10 @@ static int __cpuinit smp_alloc_lowcore(int cpu) { unsigned long async_stack, panic_stack; struct _lowcore *lowcore; + int lc_order; - lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); + lc_order = sizeof(long) == 8 ? 1 : 0; + lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); if (!lowcore) return -ENOMEM; async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); @@ -507,14 +509,16 @@ static int __cpuinit smp_alloc_lowcore(int cpu) out: free_page(panic_stack); free_pages(async_stack, ASYNC_ORDER); - free_pages((unsigned long) lowcore, LC_ORDER); + free_pages((unsigned long) lowcore, lc_order); return -ENOMEM; } static void smp_free_lowcore(int cpu) { struct _lowcore *lowcore; + int lc_order; + lc_order = sizeof(long) == 8 ? 1 : 0; lowcore = lowcore_ptr[cpu]; #ifndef CONFIG_64BIT if (MACHINE_HAS_IEEE) @@ -524,7 +528,7 @@ static void smp_free_lowcore(int cpu) #endif free_page(lowcore->panic_stack - PAGE_SIZE); free_pages(lowcore->async_stack - ASYNC_SIZE, ASYNC_ORDER); - free_pages((unsigned long) lowcore, LC_ORDER); + free_pages((unsigned long) lowcore, lc_order); lowcore_ptr[cpu] = NULL; } @@ -660,6 +664,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus) unsigned long async_stack, panic_stack; struct _lowcore *lowcore; unsigned int cpu; + int lc_order; smp_detect_cpus(); @@ -669,7 +674,8 @@ void __init smp_prepare_cpus(unsigned int max_cpus) print_cpu_info(); /* Reallocate current lowcore, but keep its contents. */ - lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, LC_ORDER); + lc_order = sizeof(long) == 8 ? 1 : 0; + lowcore = (void *) __get_free_pages(GFP_KERNEL | GFP_DMA, lc_order); panic_stack = __get_free_page(GFP_KERNEL); async_stack = __get_free_pages(GFP_KERNEL, ASYNC_ORDER); BUG_ON(!lowcore || !panic_stack || !async_stack); @@ -1041,6 +1047,42 @@ static ssize_t dispatching_store(struct sysdev_class *dev, const char *buf, static SYSDEV_CLASS_ATTR(dispatching, 0644, dispatching_show, dispatching_store); +/* + * If the resume kernel runs on another cpu than the suspended kernel, + * we have to switch the cpu IDs in the logical map. + */ +void smp_switch_boot_cpu_in_resume(u32 resume_phys_cpu_id, + struct _lowcore *suspend_lowcore) +{ + int cpu, suspend_cpu_id, resume_cpu_id; + u32 suspend_phys_cpu_id; + + suspend_phys_cpu_id = __cpu_logical_map[suspend_lowcore->cpu_nr]; + suspend_cpu_id = suspend_lowcore->cpu_nr; + + for_each_present_cpu(cpu) { + if (__cpu_logical_map[cpu] == resume_phys_cpu_id) { + resume_cpu_id = cpu; + goto found; + } + } + panic("Could not find resume cpu in logical map.\n"); + +found: + printk("Resume cpu ID: %i/%i\n", resume_phys_cpu_id, resume_cpu_id); + printk("Suspend cpu ID: %i/%i\n", suspend_phys_cpu_id, suspend_cpu_id); + + __cpu_logical_map[resume_cpu_id] = suspend_phys_cpu_id; + __cpu_logical_map[suspend_cpu_id] = resume_phys_cpu_id; + + lowcore_ptr[suspend_cpu_id]->cpu_addr = resume_phys_cpu_id; +} + +u32 smp_get_phys_cpu_id(void) +{ + return __cpu_logical_map[smp_processor_id()]; +} + static int __init topology_init(void) { int cpu; diff --git a/trunk/arch/s390/kernel/suspend.c b/trunk/arch/s390/kernel/suspend.c index cf9e5c6d5527..086bee970cae 100644 --- a/trunk/arch/s390/kernel/suspend.c +++ b/trunk/arch/s390/kernel/suspend.c @@ -6,26 +6,36 @@ * Author(s): Hans-Joachim Picht */ +#include +#include #include +#include +#include #include +#include /* * References to section boundaries */ extern const void __nosave_begin, __nosave_end; +/* + * check if given pfn is in the 'nosave' or in the read only NSS section + */ int pfn_is_nosave(unsigned long pfn) { - unsigned long nosave_begin_pfn = PFN_DOWN(__pa(&__nosave_begin)); - unsigned long nosave_end_pfn = PFN_DOWN(__pa(&__nosave_end)); + unsigned long nosave_begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT; + unsigned long nosave_end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) + >> PAGE_SHIFT; + unsigned long eshared_pfn = PFN_DOWN(__pa(&_eshared)) - 1; + unsigned long stext_pfn = PFN_DOWN(__pa(&_stext)); - /* Always save lowcore pages (LC protection might be enabled). */ - if (pfn <= LC_PAGES) - return 0; if (pfn >= nosave_begin_pfn && pfn < nosave_end_pfn) return 1; - /* Skip memory holes and read-only pages (NSS, DCSS, ...). */ - if (tprot(PFN_PHYS(pfn))) + if (pfn >= stext_pfn && pfn <= eshared_pfn) { + if (ipl_info.type == IPL_TYPE_NSS) + return 1; + } else if ((tprot(pfn * PAGE_SIZE) && pfn > 0)) return 1; return 0; } diff --git a/trunk/arch/s390/kernel/swsusp_asm64.S b/trunk/arch/s390/kernel/swsusp_asm64.S index fe927d0bc20b..7cd6b096f0d1 100644 --- a/trunk/arch/s390/kernel/swsusp_asm64.S +++ b/trunk/arch/s390/kernel/swsusp_asm64.S @@ -9,7 +9,6 @@ #include #include -#include #include /* @@ -42,9 +41,6 @@ swsusp_arch_suspend: /* Get pointer to save area */ lghi %r1,0x1000 - /* Save CPU address */ - stap __LC_CPU_ADDRESS(%r1) - /* Store registers */ mvc 0x318(4,%r1),__SF_EMPTY(%r15) /* move prefix to lowcore */ stfpc 0x31c(%r1) /* store fpu control */ @@ -106,10 +102,11 @@ swsusp_arch_resume: aghi %r15,-STACK_FRAME_OVERHEAD stg %r1,__SF_BACKCHAIN(%r15) - /* Make all free pages stable */ - lghi %r2,1 - brasl %r14,arch_set_page_states - +#ifdef CONFIG_SMP + /* Save boot cpu number */ + brasl %r14,smp_get_phys_cpu_id + lgr %r10,%r2 +#endif /* Deactivate DAT */ stnsm __SF_EMPTY(%r15),0xfb @@ -136,69 +133,6 @@ swsusp_arch_resume: 2: ptlb /* flush tlb */ - /* Reset System */ - larl %r1,restart_entry - larl %r2,.Lrestart_diag308_psw - og %r1,0(%r2) - stg %r1,0(%r0) - larl %r1,.Lnew_pgm_check_psw - epsw %r2,%r3 - stm %r2,%r3,0(%r1) - mvc __LC_PGM_NEW_PSW(16,%r0),0(%r1) - lghi %r0,0 - diag %r0,%r0,0x308 -restart_entry: - lhi %r1,1 - sigp %r1,%r0,0x12 - sam64 - larl %r1,.Lnew_pgm_check_psw - lpswe 0(%r1) -pgm_check_entry: - - /* Switch to original suspend CPU */ - larl %r1,.Lresume_cpu /* Resume CPU address: r2 */ - stap 0(%r1) - llgh %r2,0(%r1) - lghi %r3,0x1000 - llgh %r1,__LC_CPU_ADDRESS(%r3) /* Suspend CPU address: r1 */ - cgr %r1,%r2 - je restore_registers /* r1 = r2 -> nothing to do */ - larl %r4,.Lrestart_suspend_psw /* Set new restart PSW */ - mvc __LC_RESTART_PSW(16,%r0),0(%r4) -3: - sigp %r9,%r1,__SIGP_INITIAL_CPU_RESET - brc 8,4f /* accepted */ - brc 2,3b /* busy, try again */ - - /* Suspend CPU not available -> panic */ - larl %r15,init_thread_union - ahi %r15,1<<(PAGE_SHIFT+THREAD_ORDER) - larl %r2,.Lpanic_string - larl %r3,_sclp_print_early - lghi %r1,0 - sam31 - sigp %r1,%r0,0x12 - basr %r14,%r3 - larl %r3,.Ldisabled_wait_31 - lpsw 0(%r3) -4: - /* Switch to suspend CPU */ - sigp %r9,%r1,__SIGP_RESTART /* start suspend CPU */ - brc 2,4b /* busy, try again */ -5: - sigp %r9,%r2,__SIGP_STOP /* stop resume (current) CPU */ -6: j 6b - -restart_suspend: - larl %r1,.Lresume_cpu - llgh %r2,0(%r1) -7: - sigp %r9,%r2,__SIGP_SENSE /* Wait for resume CPU */ - brc 2,7b /* busy, try again */ - tmll %r9,0x40 /* Test if resume CPU is stopped */ - jz 7b - -restore_registers: /* Restore registers */ lghi %r13,0x1000 /* %r1 = pointer to save arae */ @@ -232,33 +166,19 @@ restore_registers: /* Pointer to save area */ lghi %r13,0x1000 +#ifdef CONFIG_SMP + /* Switch CPUs */ + lgr %r2,%r10 /* get cpu id */ + llgf %r3,0x318(%r13) + brasl %r14,smp_switch_boot_cpu_in_resume +#endif /* Restore prefix register */ spx 0x318(%r13) /* Activate DAT */ stosm __SF_EMPTY(%r15),0x04 - /* Make all free pages unstable */ - lghi %r2,0 - brasl %r14,arch_set_page_states - /* Return 0 */ lmg %r6,%r15,STACK_FRAME_OVERHEAD + __SF_GPRS(%r15) lghi %r2,0 br %r14 - - .section .data.nosave,"aw",@progbits - .align 8 -.Ldisabled_wait_31: - .long 0x000a0000,0x00000000 -.Lpanic_string: - .asciz "Resume not possible because suspend CPU is no longer available" - .align 8 -.Lrestart_diag308_psw: - .long 0x00080000,0x80000000 -.Lrestart_suspend_psw: - .quad 0x0000000180000000,restart_suspend -.Lnew_pgm_check_psw: - .quad 0,pgm_check_entry -.Lresume_cpu: - .byte 0,0 diff --git a/trunk/arch/s390/kernel/syscalls.S b/trunk/arch/s390/kernel/syscalls.S index 30eca070d426..0b5083681e77 100644 --- a/trunk/arch/s390/kernel/syscalls.S +++ b/trunk/arch/s390/kernel/syscalls.S @@ -19,7 +19,7 @@ SYSCALL(sys_restart_syscall,sys_restart_syscall,sys_restart_syscall) SYSCALL(sys_creat,sys_creat,sys32_creat_wrapper) SYSCALL(sys_link,sys_link,sys32_link_wrapper) SYSCALL(sys_unlink,sys_unlink,sys32_unlink_wrapper) /* 10 */ -SYSCALL(sys_execve,sys_execve,sys32_execve_wrapper) +SYSCALL(sys_execve,sys_execve,sys32_execve) SYSCALL(sys_chdir,sys_chdir,sys32_chdir_wrapper) SYSCALL(sys_time,sys_ni_syscall,sys32_time_wrapper) /* old time syscall */ SYSCALL(sys_mknod,sys_mknod,sys32_mknod_wrapper) @@ -128,7 +128,7 @@ SYSCALL(sys_sysinfo,sys_sysinfo,compat_sys_sysinfo_wrapper) SYSCALL(sys_ipc,sys_ipc,sys32_ipc_wrapper) SYSCALL(sys_fsync,sys_fsync,sys32_fsync_wrapper) SYSCALL(sys_sigreturn,sys_sigreturn,sys32_sigreturn) -SYSCALL(sys_clone,sys_clone,sys_clone_wrapper) /* 120 */ +SYSCALL(sys_clone,sys_clone,sys32_clone) /* 120 */ SYSCALL(sys_setdomainname,sys_setdomainname,sys32_setdomainname_wrapper) SYSCALL(sys_newuname,sys_s390_newuname,sys32_newuname_wrapper) NI_SYSCALL /* modify_ldt for i386 */ @@ -136,8 +136,8 @@ SYSCALL(sys_adjtimex,sys_adjtimex,compat_sys_adjtimex_wrapper) SYSCALL(sys_mprotect,sys_mprotect,sys32_mprotect_wrapper) /* 125 */ SYSCALL(sys_sigprocmask,sys_sigprocmask,compat_sys_sigprocmask_wrapper) NI_SYSCALL /* old "create module" */ -SYSCALL(sys_init_module,sys_init_module,sys_init_module_wrapper) -SYSCALL(sys_delete_module,sys_delete_module,sys_delete_module_wrapper) +SYSCALL(sys_init_module,sys_init_module,sys32_init_module_wrapper) +SYSCALL(sys_delete_module,sys_delete_module,sys32_delete_module_wrapper) NI_SYSCALL /* 130: old get_kernel_syms */ SYSCALL(sys_quotactl,sys_quotactl,sys32_quotactl_wrapper) SYSCALL(sys_getpgid,sys_getpgid,sys32_getpgid_wrapper) diff --git a/trunk/arch/s390/mm/page-states.c b/trunk/arch/s390/mm/page-states.c index 098923ae458f..f92ec203ad92 100644 --- a/trunk/arch/s390/mm/page-states.c +++ b/trunk/arch/s390/mm/page-states.c @@ -50,64 +50,28 @@ void __init cmma_init(void) cmma_flag = 0; } -static inline void set_page_unstable(struct page *page, int order) +void arch_free_page(struct page *page, int order) { int i, rc; + if (!cmma_flag) + return; for (i = 0; i < (1 << order); i++) asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" : "=&d" (rc) - : "a" (page_to_phys(page + i)), + : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), "i" (ESSA_SET_UNUSED)); } -void arch_free_page(struct page *page, int order) -{ - if (!cmma_flag) - return; - set_page_unstable(page, order); -} - -static inline void set_page_stable(struct page *page, int order) +void arch_alloc_page(struct page *page, int order) { int i, rc; + if (!cmma_flag) + return; for (i = 0; i < (1 << order); i++) asm volatile(".insn rrf,0xb9ab0000,%0,%1,%2,0" : "=&d" (rc) - : "a" (page_to_phys(page + i)), + : "a" ((page_to_pfn(page) + i) << PAGE_SHIFT), "i" (ESSA_SET_STABLE)); } - -void arch_alloc_page(struct page *page, int order) -{ - if (!cmma_flag) - return; - set_page_stable(page, order); -} - -void arch_set_page_states(int make_stable) -{ - unsigned long flags, order, t; - struct list_head *l; - struct page *page; - struct zone *zone; - - if (!cmma_flag) - return; - if (make_stable) - drain_local_pages(NULL); - for_each_populated_zone(zone) { - spin_lock_irqsave(&zone->lock, flags); - for_each_migratetype_order(order, t) { - list_for_each(l, &zone->free_area[order].free_list[t]) { - page = list_entry(l, struct page, lru); - if (make_stable) - set_page_stable(page, order); - else - set_page_unstable(page, order); - } - } - spin_unlock_irqrestore(&zone->lock, flags); - } -} diff --git a/trunk/arch/s390/mm/pgtable.c b/trunk/arch/s390/mm/pgtable.c index c60bfb309ce6..c70215247071 100644 --- a/trunk/arch/s390/mm/pgtable.c +++ b/trunk/arch/s390/mm/pgtable.c @@ -314,18 +314,21 @@ int s390_enable_sie(void) } EXPORT_SYMBOL_GPL(s390_enable_sie); -#if defined(CONFIG_DEBUG_PAGEALLOC) && defined(CONFIG_HIBERNATION) +#ifdef CONFIG_DEBUG_PAGEALLOC +#ifdef CONFIG_HIBERNATION bool kernel_page_present(struct page *page) { unsigned long addr; int cc; addr = page_to_phys(page); - asm volatile( - " lra %1,0(%1)\n" - " ipm %0\n" - " srl %0,28" - : "=d" (cc), "+a" (addr) : : "cc"); + asm("lra %1,0(%1)\n" + "ipm %0\n" + "srl %0,28" + :"=d"(cc),"+a"(addr)::"cc"); return cc == 0; } -#endif /* CONFIG_HIBERNATION && CONFIG_DEBUG_PAGEALLOC */ + +#endif /* CONFIG_HIBERNATION */ +#endif /* CONFIG_DEBUG_PAGEALLOC */ + diff --git a/trunk/arch/score/include/asm/page.h b/trunk/arch/score/include/asm/page.h index d92a5a2d36d4..ee5821042fcc 100644 --- a/trunk/arch/score/include/asm/page.h +++ b/trunk/arch/score/include/asm/page.h @@ -2,11 +2,10 @@ #define _ASM_SCORE_PAGE_H #include -#include /* PAGE_SHIFT determines the page size */ #define PAGE_SHIFT (12) -#define PAGE_SIZE (_AC(1,UL) << PAGE_SHIFT) +#define PAGE_SIZE (1UL << PAGE_SHIFT) #define PAGE_MASK (~(PAGE_SIZE-1)) #ifdef __KERNEL__ diff --git a/trunk/arch/score/include/asm/thread_info.h b/trunk/arch/score/include/asm/thread_info.h index 55939992c27d..3a1122885528 100644 --- a/trunk/arch/score/include/asm/thread_info.h +++ b/trunk/arch/score/include/asm/thread_info.h @@ -7,15 +7,6 @@ #define KU_USER 0x08 #define KU_KERN 0x00 -#include -#include - -/* thread information allocation */ -#define THREAD_SIZE_ORDER (1) -#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) -#define THREAD_MASK (THREAD_SIZE - _AC(1,UL)) -#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR - #ifndef __ASSEMBLY__ #include @@ -71,6 +62,12 @@ struct thread_info { register struct thread_info *__current_thread_info __asm__("r28"); #define current_thread_info() __current_thread_info +/* thread information allocation */ +#define THREAD_SIZE_ORDER (1) +#define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER) +#define THREAD_MASK (THREAD_SIZE - 1UL) +#define __HAVE_ARCH_THREAD_INFO_ALLOCATOR + #define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL) #define free_thread_info(info) kfree(info) diff --git a/trunk/arch/score/kernel/vmlinux.lds.S b/trunk/arch/score/kernel/vmlinux.lds.S index eebcbaa4e978..f85569831d5c 100644 --- a/trunk/arch/score/kernel/vmlinux.lds.S +++ b/trunk/arch/score/kernel/vmlinux.lds.S @@ -24,8 +24,6 @@ */ #include -#include -#include OUTPUT_ARCH(score) ENTRY(_stext) @@ -51,9 +49,21 @@ SECTIONS . = ALIGN(16); RODATA - EXCEPTION_TABLE(16) + /* Exception table */ + . = ALIGN(16); + __ex_table : { + __start___ex_table = .; + *(__ex_table) + __stop___ex_table = .; + } - RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE) + /* writeable */ + .data ALIGN (4096): { + *(.data.init_task) + + DATA_DATA + CONSTRUCTORS + } /* We want the small data sections together, so single-instruction offsets can access them all, and initialized data all before uninitialized, so @@ -62,14 +72,45 @@ SECTIONS .sdata : { *(.sdata) } + + . = ALIGN(32); + .data.cacheline_aligned : { + *(.data.cacheline_aligned) + } _edata = .; /* End of data section */ /* will be freed after init */ - . = ALIGN(PAGE_SIZE); /* Init code and data */ + . = ALIGN(4096); /* Init code and data */ __init_begin = .; - INIT_TEXT_SECTION(PAGE_SIZE) - INIT_DATA_SECTION(16) + . = ALIGN(4096); + .init.text : { + _sinittext = .; + INIT_TEXT + _einittext = .; + } + .init.data : { + INIT_DATA + } + . = ALIGN(16); + .init.setup : { + __setup_start = .; + *(.init.setup) + __setup_end = .; + } + + .initcall.init : { + __initcall_start = .; + INITCALLS + __initcall_end = .; + } + + .con_initcall.init : { + __con_initcall_start = .; + *(.con_initcall.init) + __con_initcall_end = .; + } + SECURITY_INIT /* .exit.text is discarded at runtime, not link time, to deal with * references from .rodata @@ -80,10 +121,28 @@ SECTIONS .exit.data : { EXIT_DATA } - . = ALIGN(PAGE_SIZE); +#if defined(CONFIG_BLK_DEV_INITRD) + .init.ramfs ALIGN(4096): { + __initramfs_start = .; + *(.init.ramfs) + __initramfs_end = .; + . = ALIGN(4); + LONG(0); + } +#endif + . = ALIGN(4096); __init_end = .; /* freed after init ends here */ - BSS_SECTION(0, 0, 0) + __bss_start = .; /* BSS */ + .sbss : { + *(.sbss) + *(.scommon) + } + .bss : { + *(.bss) + *(COMMON) + } + __bss_stop = .; _end = .; } diff --git a/trunk/arch/sh/mm/init.c b/trunk/arch/sh/mm/init.c index 8173e38afd38..fabb7c6f48d2 100644 --- a/trunk/arch/sh/mm/init.c +++ b/trunk/arch/sh/mm/init.c @@ -186,6 +186,8 @@ void __init paging_init(void) set_fixmap_nocache(FIX_UNCACHED, __pa(&__uncached_start)); } +static struct kcore_list kcore_mem, kcore_vmalloc; + void __init mem_init(void) { int codesize, datasize, initsize; @@ -224,6 +226,10 @@ void __init mem_init(void) datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); + kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, + VMALLOC_END - VMALLOC_START); + printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, " "%dk data, %dk init)\n", nr_free_pages() << (PAGE_SHIFT-10), diff --git a/trunk/arch/sparc/include/asm/vio.h b/trunk/arch/sparc/include/asm/vio.h index 6cdbf7e7351d..d4de32f0f8af 100644 --- a/trunk/arch/sparc/include/asm/vio.h +++ b/trunk/arch/sparc/include/asm/vio.h @@ -258,7 +258,7 @@ static inline void *vio_dring_entry(struct vio_dring_state *dr, static inline u32 vio_dring_avail(struct vio_dring_state *dr, unsigned int ring_size) { - MAYBE_BUILD_BUG_ON(!is_power_of_2(ring_size)); + BUILD_BUG_ON(!is_power_of_2(ring_size)); return (dr->pending - ((dr->prod - dr->cons) & (ring_size - 1))); diff --git a/trunk/arch/x86/Kconfig b/trunk/arch/x86/Kconfig index 93698794aa3a..e4ff5d1280ca 100644 --- a/trunk/arch/x86/Kconfig +++ b/trunk/arch/x86/Kconfig @@ -1204,10 +1204,6 @@ config ARCH_DISCONTIGMEM_DEFAULT def_bool y depends on NUMA && X86_32 -config ARCH_PROC_KCORE_TEXT - def_bool y - depends on X86_64 && PROC_KCORE - config ARCH_SPARSEMEM_DEFAULT def_bool y depends on X86_64 @@ -1666,8 +1662,6 @@ source "kernel/power/Kconfig" source "drivers/acpi/Kconfig" -source "drivers/sfi/Kconfig" - config X86_APM_BOOT bool default y @@ -1863,7 +1857,7 @@ config PCI_DIRECT config PCI_MMCONFIG def_bool y - depends on X86_32 && PCI && (ACPI || SFI) && (PCI_GOMMCONFIG || PCI_GOANY) + depends on X86_32 && PCI && ACPI && (PCI_GOMMCONFIG || PCI_GOANY) config PCI_OLPC def_bool y @@ -1901,7 +1895,7 @@ config DMAR_DEFAULT_ON config DMAR_BROKEN_GFX_WA def_bool n prompt "Workaround broken graphics drivers (going away soon)" - depends on DMAR && BROKEN + depends on DMAR ---help--- Current Graphics drivers tend to use physical address for DMA and avoid using DMA APIs. Setting this config diff --git a/trunk/arch/x86/include/asm/acpi.h b/trunk/arch/x86/include/asm/acpi.h index 4518dc500903..20d1465a2ab0 100644 --- a/trunk/arch/x86/include/asm/acpi.h +++ b/trunk/arch/x86/include/asm/acpi.h @@ -144,6 +144,7 @@ static inline unsigned int acpi_processor_cstate_check(unsigned int max_cstate) #else /* !CONFIG_ACPI */ +#define acpi_disabled 1 #define acpi_lapic 0 #define acpi_ioapic 0 static inline void acpi_noirq_set(void) { } diff --git a/trunk/arch/x86/include/asm/syscall.h b/trunk/arch/x86/include/asm/syscall.h index 8d33bc5462d1..d82f39bb7905 100644 --- a/trunk/arch/x86/include/asm/syscall.h +++ b/trunk/arch/x86/include/asm/syscall.h @@ -1,7 +1,7 @@ /* * Access to user system call parameters and results * - * Copyright (C) 2008-2009 Red Hat, Inc. All rights reserved. + * Copyright (C) 2008 Red Hat, Inc. All rights reserved. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions @@ -16,13 +16,13 @@ #include #include -/* - * Only the low 32 bits of orig_ax are meaningful, so we return int. - * This importantly ignores the high bits on 64-bit, so comparisons - * sign-extend the low 32 bits. - */ -static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) +static inline long syscall_get_nr(struct task_struct *task, + struct pt_regs *regs) { + /* + * We always sign-extend a -1 value being set here, + * so this is always either -1L or a syscall number. + */ return regs->orig_ax; } diff --git a/trunk/arch/x86/kernel/Makefile b/trunk/arch/x86/kernel/Makefile index d8e5d0cdd678..4ba419b668a5 100644 --- a/trunk/arch/x86/kernel/Makefile +++ b/trunk/arch/x86/kernel/Makefile @@ -56,7 +56,6 @@ obj-$(CONFIG_INTEL_TXT) += tboot.o obj-$(CONFIG_STACKTRACE) += stacktrace.o obj-y += cpu/ obj-y += acpi/ -obj-$(CONFIG_SFI) += sfi.o obj-y += reboot.o obj-$(CONFIG_MCA) += mca_32.o obj-$(CONFIG_X86_MSR) += msr.o diff --git a/trunk/arch/x86/kernel/early_printk.c b/trunk/arch/x86/kernel/early_printk.c index 2acfd3fdc0cc..b11cab3c323a 100644 --- a/trunk/arch/x86/kernel/early_printk.c +++ b/trunk/arch/x86/kernel/early_printk.c @@ -160,6 +160,721 @@ static struct console early_serial_console = { .index = -1, }; +#ifdef CONFIG_EARLY_PRINTK_DBGP + +static struct ehci_caps __iomem *ehci_caps; +static struct ehci_regs __iomem *ehci_regs; +static struct ehci_dbg_port __iomem *ehci_debug; +static unsigned int dbgp_endpoint_out; + +struct ehci_dev { + u32 bus; + u32 slot; + u32 func; +}; + +static struct ehci_dev ehci_dev; + +#define USB_DEBUG_DEVNUM 127 + +#define DBGP_DATA_TOGGLE 0x8800 + +static inline u32 dbgp_pid_update(u32 x, u32 tok) +{ + return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff); +} + +static inline u32 dbgp_len_update(u32 x, u32 len) +{ + return (x & ~0x0f) | (len & 0x0f); +} + +/* + * USB Packet IDs (PIDs) + */ + +/* token */ +#define USB_PID_OUT 0xe1 +#define USB_PID_IN 0x69 +#define USB_PID_SOF 0xa5 +#define USB_PID_SETUP 0x2d +/* handshake */ +#define USB_PID_ACK 0xd2 +#define USB_PID_NAK 0x5a +#define USB_PID_STALL 0x1e +#define USB_PID_NYET 0x96 +/* data */ +#define USB_PID_DATA0 0xc3 +#define USB_PID_DATA1 0x4b +#define USB_PID_DATA2 0x87 +#define USB_PID_MDATA 0x0f +/* Special */ +#define USB_PID_PREAMBLE 0x3c +#define USB_PID_ERR 0x3c +#define USB_PID_SPLIT 0x78 +#define USB_PID_PING 0xb4 +#define USB_PID_UNDEF_0 0xf0 + +#define USB_PID_DATA_TOGGLE 0x88 +#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE) + +#define PCI_CAP_ID_EHCI_DEBUG 0xa + +#define HUB_ROOT_RESET_TIME 50 /* times are in msec */ +#define HUB_SHORT_RESET_TIME 10 +#define HUB_LONG_RESET_TIME 200 +#define HUB_RESET_TIMEOUT 500 + +#define DBGP_MAX_PACKET 8 + +static int dbgp_wait_until_complete(void) +{ + u32 ctrl; + int loop = 0x100000; + + do { + ctrl = readl(&ehci_debug->control); + /* Stop when the transaction is finished */ + if (ctrl & DBGP_DONE) + break; + } while (--loop > 0); + + if (!loop) + return -1; + + /* + * Now that we have observed the completed transaction, + * clear the done bit. + */ + writel(ctrl | DBGP_DONE, &ehci_debug->control); + return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl); +} + +static void __init dbgp_mdelay(int ms) +{ + int i; + + while (ms--) { + for (i = 0; i < 1000; i++) + outb(0x1, 0x80); + } +} + +static void dbgp_breath(void) +{ + /* Sleep to give the debug port a chance to breathe */ +} + +static int dbgp_wait_until_done(unsigned ctrl) +{ + u32 pids, lpid; + int ret; + int loop = 3; + +retry: + writel(ctrl | DBGP_GO, &ehci_debug->control); + ret = dbgp_wait_until_complete(); + pids = readl(&ehci_debug->pids); + lpid = DBGP_PID_GET(pids); + + if (ret < 0) + return ret; + + /* + * If the port is getting full or it has dropped data + * start pacing ourselves, not necessary but it's friendly. + */ + if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET)) + dbgp_breath(); + + /* If I get a NACK reissue the transmission */ + if (lpid == USB_PID_NAK) { + if (--loop > 0) + goto retry; + } + + return ret; +} + +static void dbgp_set_data(const void *buf, int size) +{ + const unsigned char *bytes = buf; + u32 lo, hi; + int i; + + lo = hi = 0; + for (i = 0; i < 4 && i < size; i++) + lo |= bytes[i] << (8*i); + for (; i < 8 && i < size; i++) + hi |= bytes[i] << (8*(i - 4)); + writel(lo, &ehci_debug->data03); + writel(hi, &ehci_debug->data47); +} + +static void __init dbgp_get_data(void *buf, int size) +{ + unsigned char *bytes = buf; + u32 lo, hi; + int i; + + lo = readl(&ehci_debug->data03); + hi = readl(&ehci_debug->data47); + for (i = 0; i < 4 && i < size; i++) + bytes[i] = (lo >> (8*i)) & 0xff; + for (; i < 8 && i < size; i++) + bytes[i] = (hi >> (8*(i - 4))) & 0xff; +} + +static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, + const char *bytes, int size) +{ + u32 pids, addr, ctrl; + int ret; + + if (size > DBGP_MAX_PACKET) + return -1; + + addr = DBGP_EPADDR(devnum, endpoint); + + pids = readl(&ehci_debug->pids); + pids = dbgp_pid_update(pids, USB_PID_OUT); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, size); + ctrl |= DBGP_OUT; + ctrl |= DBGP_GO; + + dbgp_set_data(bytes, size); + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + return ret; +} + +static int __init dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, + int size) +{ + u32 pids, addr, ctrl; + int ret; + + if (size > DBGP_MAX_PACKET) + return -1; + + addr = DBGP_EPADDR(devnum, endpoint); + + pids = readl(&ehci_debug->pids); + pids = dbgp_pid_update(pids, USB_PID_IN); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, size); + ctrl &= ~DBGP_OUT; + ctrl |= DBGP_GO; + + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + if (size > ret) + size = ret; + dbgp_get_data(data, size); + return ret; +} + +static int __init dbgp_control_msg(unsigned devnum, int requesttype, + int request, int value, int index, void *data, int size) +{ + u32 pids, addr, ctrl; + struct usb_ctrlrequest req; + int read; + int ret; + + read = (requesttype & USB_DIR_IN) != 0; + if (size > (read ? DBGP_MAX_PACKET:0)) + return -1; + + /* Compute the control message */ + req.bRequestType = requesttype; + req.bRequest = request; + req.wValue = cpu_to_le16(value); + req.wIndex = cpu_to_le16(index); + req.wLength = cpu_to_le16(size); + + pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP); + addr = DBGP_EPADDR(devnum, 0); + + ctrl = readl(&ehci_debug->control); + ctrl = dbgp_len_update(ctrl, sizeof(req)); + ctrl |= DBGP_OUT; + ctrl |= DBGP_GO; + + /* Send the setup message */ + dbgp_set_data(&req, sizeof(req)); + writel(addr, &ehci_debug->address); + writel(pids, &ehci_debug->pids); + ret = dbgp_wait_until_done(ctrl); + if (ret < 0) + return ret; + + /* Read the result */ + return dbgp_bulk_read(devnum, 0, data, size); +} + + +/* Find a PCI capability */ +static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap) +{ + u8 pos; + int bytes; + + if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & + PCI_STATUS_CAP_LIST)) + return 0; + + pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); + for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { + u8 id; + + pos &= ~3; + id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); + if (id == 0xff) + break; + if (id == cap) + return pos; + + pos = read_pci_config_byte(num, slot, func, + pos+PCI_CAP_LIST_NEXT); + } + return 0; +} + +static u32 __init __find_dbgp(u32 bus, u32 slot, u32 func) +{ + u32 class; + + class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION); + if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI) + return 0; + + return find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG); +} + +static u32 __init find_dbgp(int ehci_num, u32 *rbus, u32 *rslot, u32 *rfunc) +{ + u32 bus, slot, func; + + for (bus = 0; bus < 256; bus++) { + for (slot = 0; slot < 32; slot++) { + for (func = 0; func < 8; func++) { + unsigned cap; + + cap = __find_dbgp(bus, slot, func); + + if (!cap) + continue; + if (ehci_num-- != 0) + continue; + *rbus = bus; + *rslot = slot; + *rfunc = func; + return cap; + } + } + } + return 0; +} + +static int __init ehci_reset_port(int port) +{ + u32 portsc; + u32 delay_time, delay; + int loop; + + /* Reset the usb debug port */ + portsc = readl(&ehci_regs->port_status[port - 1]); + portsc &= ~PORT_PE; + portsc |= PORT_RESET; + writel(portsc, &ehci_regs->port_status[port - 1]); + + delay = HUB_ROOT_RESET_TIME; + for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; + delay_time += delay) { + dbgp_mdelay(delay); + + portsc = readl(&ehci_regs->port_status[port - 1]); + if (portsc & PORT_RESET) { + /* force reset to complete */ + loop = 2; + writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), + &ehci_regs->port_status[port - 1]); + do { + portsc = readl(&ehci_regs->port_status[port-1]); + } while ((portsc & PORT_RESET) && (--loop > 0)); + } + + /* Device went away? */ + if (!(portsc & PORT_CONNECT)) + return -ENOTCONN; + + /* bomb out completely if something weird happend */ + if ((portsc & PORT_CSC)) + return -EINVAL; + + /* If we've finished resetting, then break out of the loop */ + if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) + return 0; + } + return -EBUSY; +} + +static int __init ehci_wait_for_port(int port) +{ + u32 status; + int ret, reps; + + for (reps = 0; reps < 3; reps++) { + dbgp_mdelay(100); + status = readl(&ehci_regs->status); + if (status & STS_PCD) { + ret = ehci_reset_port(port); + if (ret == 0) + return 0; + } + } + return -ENOTCONN; +} + +#ifdef DBGP_DEBUG +# define dbgp_printk early_printk +#else +static inline void dbgp_printk(const char *fmt, ...) { } +#endif + +typedef void (*set_debug_port_t)(int port); + +static void __init default_set_debug_port(int port) +{ +} + +static set_debug_port_t __initdata set_debug_port = default_set_debug_port; + +static void __init nvidia_set_debug_port(int port) +{ + u32 dword; + dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, + 0x74); + dword &= ~(0x0f<<12); + dword |= ((port & 0x0f)<<12); + write_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, 0x74, + dword); + dbgp_printk("set debug port to %d\n", port); +} + +static void __init detect_set_debug_port(void) +{ + u32 vendorid; + + vendorid = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, + 0x00); + + if ((vendorid & 0xffff) == 0x10de) { + dbgp_printk("using nvidia set_debug_port\n"); + set_debug_port = nvidia_set_debug_port; + } +} + +static int __init ehci_setup(void) +{ + struct usb_debug_descriptor dbgp_desc; + u32 cmd, ctrl, status, portsc, hcs_params; + u32 debug_port, new_debug_port = 0, n_ports; + u32 devnum; + int ret, i; + int loop; + int port_map_tried; + int playtimes = 3; + +try_next_time: + port_map_tried = 0; + +try_next_port: + + hcs_params = readl(&ehci_caps->hcs_params); + debug_port = HCS_DEBUG_PORT(hcs_params); + n_ports = HCS_N_PORTS(hcs_params); + + dbgp_printk("debug_port: %d\n", debug_port); + dbgp_printk("n_ports: %d\n", n_ports); + + for (i = 1; i <= n_ports; i++) { + portsc = readl(&ehci_regs->port_status[i-1]); + dbgp_printk("portstatus%d: %08x\n", i, portsc); + } + + if (port_map_tried && (new_debug_port != debug_port)) { + if (--playtimes) { + set_debug_port(new_debug_port); + goto try_next_time; + } + return -1; + } + + loop = 100000; + /* Reset the EHCI controller */ + cmd = readl(&ehci_regs->command); + cmd |= CMD_RESET; + writel(cmd, &ehci_regs->command); + do { + cmd = readl(&ehci_regs->command); + } while ((cmd & CMD_RESET) && (--loop > 0)); + + if (!loop) { + dbgp_printk("can not reset ehci\n"); + return -1; + } + dbgp_printk("ehci reset done\n"); + + /* Claim ownership, but do not enable yet */ + ctrl = readl(&ehci_debug->control); + ctrl |= DBGP_OWNER; + ctrl &= ~(DBGP_ENABLED | DBGP_INUSE); + writel(ctrl, &ehci_debug->control); + + /* Start the ehci running */ + cmd = readl(&ehci_regs->command); + cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET); + cmd |= CMD_RUN; + writel(cmd, &ehci_regs->command); + + /* Ensure everything is routed to the EHCI */ + writel(FLAG_CF, &ehci_regs->configured_flag); + + /* Wait until the controller is no longer halted */ + loop = 10; + do { + status = readl(&ehci_regs->status); + } while ((status & STS_HALT) && (--loop > 0)); + + if (!loop) { + dbgp_printk("ehci can be started\n"); + return -1; + } + dbgp_printk("ehci started\n"); + + /* Wait for a device to show up in the debug port */ + ret = ehci_wait_for_port(debug_port); + if (ret < 0) { + dbgp_printk("No device found in debug port\n"); + goto next_debug_port; + } + dbgp_printk("ehci wait for port done\n"); + + /* Enable the debug port */ + ctrl = readl(&ehci_debug->control); + ctrl |= DBGP_CLAIM; + writel(ctrl, &ehci_debug->control); + ctrl = readl(&ehci_debug->control); + if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) { + dbgp_printk("No device in debug port\n"); + writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control); + goto err; + } + dbgp_printk("debug ported enabled\n"); + + /* Completely transfer the debug device to the debug controller */ + portsc = readl(&ehci_regs->port_status[debug_port - 1]); + portsc &= ~PORT_PE; + writel(portsc, &ehci_regs->port_status[debug_port - 1]); + + dbgp_mdelay(100); + + /* Find the debug device and make it device number 127 */ + for (devnum = 0; devnum <= 127; devnum++) { + ret = dbgp_control_msg(devnum, + USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0, + &dbgp_desc, sizeof(dbgp_desc)); + if (ret > 0) + break; + } + if (devnum > 127) { + dbgp_printk("Could not find attached debug device\n"); + goto err; + } + if (ret < 0) { + dbgp_printk("Attached device is not a debug device\n"); + goto err; + } + dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint; + + /* Move the device to 127 if it isn't already there */ + if (devnum != USB_DEBUG_DEVNUM) { + ret = dbgp_control_msg(devnum, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0); + if (ret < 0) { + dbgp_printk("Could not move attached device to %d\n", + USB_DEBUG_DEVNUM); + goto err; + } + devnum = USB_DEBUG_DEVNUM; + dbgp_printk("debug device renamed to 127\n"); + } + + /* Enable the debug interface */ + ret = dbgp_control_msg(USB_DEBUG_DEVNUM, + USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, + USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0); + if (ret < 0) { + dbgp_printk(" Could not enable the debug device\n"); + goto err; + } + dbgp_printk("debug interface enabled\n"); + + /* Perform a small write to get the even/odd data state in sync + */ + ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ", 1); + if (ret < 0) { + dbgp_printk("dbgp_bulk_write failed: %d\n", ret); + goto err; + } + dbgp_printk("small write doned\n"); + + return 0; +err: + /* Things didn't work so remove my claim */ + ctrl = readl(&ehci_debug->control); + ctrl &= ~(DBGP_CLAIM | DBGP_OUT); + writel(ctrl, &ehci_debug->control); + return -1; + +next_debug_port: + port_map_tried |= (1<<(debug_port - 1)); + new_debug_port = ((debug_port-1+1)%n_ports) + 1; + if (port_map_tried != ((1<> 29) & 0x7; + bar = (bar * 4) + 0xc; + offset = (debug_port >> 16) & 0xfff; + dbgp_printk("bar: %02x offset: %03x\n", bar, offset); + if (bar != PCI_BASE_ADDRESS_0) { + dbgp_printk("only debug ports on bar 1 handled.\n"); + + return -1; + } + + bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); + dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset); + if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) { + dbgp_printk("only simple 32bit mmio bars supported\n"); + + return -1; + } + + /* double check if the mem space is enabled */ + byte = read_pci_config_byte(bus, slot, func, 0x04); + if (!(byte & 0x2)) { + byte |= 0x02; + write_pci_config_byte(bus, slot, func, 0x04, byte); + dbgp_printk("mmio for ehci enabled\n"); + } + + /* + * FIXME I don't have the bar size so just guess PAGE_SIZE is more + * than enough. 1K is the biggest I have seen. + */ + set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); + ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); + ehci_bar += bar_val & ~PAGE_MASK; + dbgp_printk("ehci_bar: %p\n", ehci_bar); + + ehci_caps = ehci_bar; + ehci_regs = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase)); + ehci_debug = ehci_bar + offset; + ehci_dev.bus = bus; + ehci_dev.slot = slot; + ehci_dev.func = func; + + detect_set_debug_port(); + + ret = ehci_setup(); + if (ret < 0) { + dbgp_printk("ehci_setup failed\n"); + ehci_debug = NULL; + + return -1; + } + + return 0; +} + +static void early_dbgp_write(struct console *con, const char *str, u32 n) +{ + int chunk, ret; + + if (!ehci_debug) + return; + while (n > 0) { + chunk = n; + if (chunk > DBGP_MAX_PACKET) + chunk = DBGP_MAX_PACKET; + ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, + dbgp_endpoint_out, str, chunk); + str += chunk; + n -= chunk; + } +} + +static struct console early_dbgp_console = { + .name = "earlydbg", + .write = early_dbgp_write, + .flags = CON_PRINTBUFFER, + .index = -1, +}; +#endif + /* Direct interface for emergencies */ static struct console *early_console = &early_vga_console; static int __initdata early_console_initialized; @@ -176,19 +891,10 @@ asmlinkage void early_printk(const char *fmt, ...) va_end(ap); } -static inline void early_console_register(struct console *con, int keep_early) -{ - early_console = con; - if (keep_early) - early_console->flags &= ~CON_BOOT; - else - early_console->flags |= CON_BOOT; - register_console(early_console); -} static int __init setup_early_printk(char *buf) { - int keep; + int keep_early; if (!buf) return 0; @@ -197,34 +903,42 @@ static int __init setup_early_printk(char *buf) return 0; early_console_initialized = 1; - keep = (strstr(buf, "keep") != NULL); - - while (*buf != '\0') { - if (!strncmp(buf, "serial", 6)) { - early_serial_init(buf + 6); - early_console_register(&early_serial_console, keep); - } - if (!strncmp(buf, "ttyS", 4)) { - early_serial_init(buf + 4); - early_console_register(&early_serial_console, keep); - } - if (!strncmp(buf, "vga", 3) && - boot_params.screen_info.orig_video_isVGA == 1) { - max_xpos = boot_params.screen_info.orig_video_cols; - max_ypos = boot_params.screen_info.orig_video_lines; - current_ypos = boot_params.screen_info.orig_y; - early_console_register(&early_vga_console, keep); - } + keep_early = (strstr(buf, "keep") != NULL); + + if (!strncmp(buf, "serial", 6)) { + early_serial_init(buf + 6); + early_console = &early_serial_console; + } else if (!strncmp(buf, "ttyS", 4)) { + early_serial_init(buf); + early_console = &early_serial_console; + } else if (!strncmp(buf, "vga", 3) + && boot_params.screen_info.orig_video_isVGA == 1) { + max_xpos = boot_params.screen_info.orig_video_cols; + max_ypos = boot_params.screen_info.orig_video_lines; + current_ypos = boot_params.screen_info.orig_y; + early_console = &early_vga_console; #ifdef CONFIG_EARLY_PRINTK_DBGP - if (!strncmp(buf, "dbgp", 4) && !early_dbgp_init(buf + 4)) - early_console_register(&early_dbgp_console, keep); + } else if (!strncmp(buf, "dbgp", 4)) { + if (early_dbgp_init(buf+4) < 0) + return 0; + early_console = &early_dbgp_console; + /* + * usb subsys will reset ehci controller, so don't keep + * that early console + */ + keep_early = 0; #endif #ifdef CONFIG_HVC_XEN - if (!strncmp(buf, "xen", 3)) - early_console_register(&xenboot_console, keep); + } else if (!strncmp(buf, "xen", 3)) { + early_console = &xenboot_console; #endif - buf++; } + + if (keep_early) + early_console->flags &= ~CON_BOOT; + else + early_console->flags |= CON_BOOT; + register_console(early_console); return 0; } diff --git a/trunk/arch/x86/kernel/pci-swiotlb.c b/trunk/arch/x86/kernel/pci-swiotlb.c index aaa6b7839f1e..e8a35016115f 100644 --- a/trunk/arch/x86/kernel/pci-swiotlb.c +++ b/trunk/arch/x86/kernel/pci-swiotlb.c @@ -46,8 +46,9 @@ void __init pci_swiotlb_init(void) { /* don't initialize swiotlb if iommu=off (no_iommu=1) */ #ifdef CONFIG_X86_64 - if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN)) - swiotlb = 1; + if ((!iommu_detected && !no_iommu && max_pfn > MAX_DMA32_PFN) || + iommu_pass_through) + swiotlb = 1; #endif if (swiotlb_force) swiotlb = 1; diff --git a/trunk/arch/x86/kernel/ptrace.c b/trunk/arch/x86/kernel/ptrace.c index 7b058a2dc66a..8d7d5c9c1be3 100644 --- a/trunk/arch/x86/kernel/ptrace.c +++ b/trunk/arch/x86/kernel/ptrace.c @@ -325,6 +325,16 @@ static int putreg(struct task_struct *child, return set_flags(child, value); #ifdef CONFIG_X86_64 + /* + * Orig_ax is really just a flag with small positive and + * negative values, so make sure to always sign-extend it + * from 32 bits so that it works correctly regardless of + * whether we come from a 32-bit environment or not. + */ + case offsetof(struct user_regs_struct, orig_ax): + value = (long) (s32) value; + break; + case offsetof(struct user_regs_struct,fs_base): if (value >= TASK_SIZE_OF(child)) return -EIO; @@ -1116,15 +1126,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value) case offsetof(struct user32, regs.orig_eax): /* - * A 32-bit debugger setting orig_eax means to restore - * the state of the task restarting a 32-bit syscall. - * Make sure we interpret the -ERESTART* codes correctly - * in case the task is not actually still sitting at the - * exit from a 32-bit syscall with TS_COMPAT still set. + * Sign-extend the value so that orig_eax = -1 + * causes (long)orig_ax < 0 tests to fire correctly. */ - regs->orig_ax = value; - if (syscall_get_nr(child, regs) >= 0) - task_thread_info(child)->status |= TS_COMPAT; + regs->orig_ax = (long) (s32) value; break; case offsetof(struct user32, regs.eflags): diff --git a/trunk/arch/x86/kernel/setup.c b/trunk/arch/x86/kernel/setup.c index e09f0e2c14b5..f327bccf5089 100644 --- a/trunk/arch/x86/kernel/setup.c +++ b/trunk/arch/x86/kernel/setup.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include @@ -986,8 +985,6 @@ void __init setup_arch(char **cmdline_p) */ acpi_boot_init(); - sfi_init(); - /* * get boot-time SMP configuration: */ diff --git a/trunk/arch/x86/kernel/sfi.c b/trunk/arch/x86/kernel/sfi.c deleted file mode 100644 index 34e099382651..000000000000 --- a/trunk/arch/x86/kernel/sfi.c +++ /dev/null @@ -1,122 +0,0 @@ -/* - * sfi.c - x86 architecture SFI support. - * - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - * - */ - -#define KMSG_COMPONENT "SFI" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include - -#include -#include -#include -#include - -#ifdef CONFIG_X86_LOCAL_APIC -static unsigned long sfi_lapic_addr __initdata = APIC_DEFAULT_PHYS_BASE; - -void __init mp_sfi_register_lapic_address(unsigned long address) -{ - mp_lapic_addr = address; - - set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr); - if (boot_cpu_physical_apicid == -1U) - boot_cpu_physical_apicid = read_apic_id(); - - pr_info("Boot CPU = %d\n", boot_cpu_physical_apicid); -} - -/* All CPUs enumerated by SFI must be present and enabled */ -void __cpuinit mp_sfi_register_lapic(u8 id) -{ - if (MAX_APICS - id <= 0) { - pr_warning("Processor #%d invalid (max %d)\n", - id, MAX_APICS); - return; - } - - pr_info("registering lapic[%d]\n", id); - - generic_processor_info(id, GET_APIC_VERSION(apic_read(APIC_LVR))); -} - -static int __init sfi_parse_cpus(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_cpu_table_entry *pentry; - int i; - int cpu_num; - - sb = (struct sfi_table_simple *)table; - cpu_num = SFI_GET_NUM_ENTRIES(sb, struct sfi_cpu_table_entry); - pentry = (struct sfi_cpu_table_entry *)sb->pentry; - - for (i = 0; i < cpu_num; i++) { - mp_sfi_register_lapic(pentry->apic_id); - pentry++; - } - - smp_found_config = 1; - return 0; -} -#endif /* CONFIG_X86_LOCAL_APIC */ - -#ifdef CONFIG_X86_IO_APIC -static u32 gsi_base; - -static int __init sfi_parse_ioapic(struct sfi_table_header *table) -{ - struct sfi_table_simple *sb; - struct sfi_apic_table_entry *pentry; - int i, num; - - sb = (struct sfi_table_simple *)table; - num = SFI_GET_NUM_ENTRIES(sb, struct sfi_apic_table_entry); - pentry = (struct sfi_apic_table_entry *)sb->pentry; - - for (i = 0; i < num; i++) { - mp_register_ioapic(i, pentry->phys_addr, gsi_base); - gsi_base += io_apic_get_redir_entries(i); - pentry++; - } - - WARN(pic_mode, KERN_WARNING - "SFI: pic_mod shouldn't be 1 when IOAPIC table is present\n"); - pic_mode = 0; - return 0; -} -#endif /* CONFIG_X86_IO_APIC */ - -/* - * sfi_platform_init(): register lapics & io-apics - */ -int __init sfi_platform_init(void) -{ -#ifdef CONFIG_X86_LOCAL_APIC - mp_sfi_register_lapic_address(sfi_lapic_addr); - sfi_table_parse(SFI_SIG_CPUS, NULL, NULL, sfi_parse_cpus); -#endif -#ifdef CONFIG_X86_IO_APIC - sfi_table_parse(SFI_SIG_APIC, NULL, NULL, sfi_parse_ioapic); -#endif - return 0; -} diff --git a/trunk/arch/x86/lguest/boot.c b/trunk/arch/x86/lguest/boot.c index 7e59dc1d3fc2..4cb7d5d18b8e 100644 --- a/trunk/arch/x86/lguest/boot.c +++ b/trunk/arch/x86/lguest/boot.c @@ -1135,6 +1135,11 @@ static struct notifier_block paniced = { /* Setting up memory is fairly easy. */ static __init char *lguest_memory_setup(void) { + /* We do this here and not earlier because lockcheck used to barf if we + * did it before start_kernel(). I think we fixed that, so it'd be + * nice to move it back to lguest_init. Patch welcome... */ + atomic_notifier_chain_register(&panic_notifier_list, &paniced); + /* *The Linux bootloader header contains an "e820" memory map: the * Launcher populated the first entry with our memory limit. @@ -1359,13 +1364,10 @@ __init void lguest_init(void) /* * If we don't initialize the lock dependency checker now, it crashes - * atomic_notifier_chain_register, then paravirt_disable_iospace. + * paravirt_disable_iospace. */ lockdep_init(); - /* Hook in our special panic hypercall code. */ - atomic_notifier_chain_register(&panic_notifier_list, &paniced); - /* * The IDE code spends about 3 seconds probing for disks: if we reserve * all the I/O ports up front it can't get them and so doesn't probe. diff --git a/trunk/arch/x86/mm/init_32.c b/trunk/arch/x86/mm/init_32.c index 30938c1d8d5d..b49b4f67453d 100644 --- a/trunk/arch/x86/mm/init_32.c +++ b/trunk/arch/x86/mm/init_32.c @@ -857,6 +857,8 @@ static void __init test_wp_bit(void) } } +static struct kcore_list kcore_mem, kcore_vmalloc; + void __init mem_init(void) { int codesize, reservedpages, datasize, initsize; @@ -884,6 +886,10 @@ void __init mem_init(void) datasize = (unsigned long) &_edata - (unsigned long) &_etext; initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; + kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); + kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, + VMALLOC_END-VMALLOC_START); + printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, " "%dk reserved, %dk data, %dk init, %ldk highmem)\n", nr_free_pages() << (PAGE_SHIFT-10), diff --git a/trunk/arch/x86/mm/init_64.c b/trunk/arch/x86/mm/init_64.c index 5a4398a6006b..810bd31e7f5f 100644 --- a/trunk/arch/x86/mm/init_64.c +++ b/trunk/arch/x86/mm/init_64.c @@ -647,7 +647,8 @@ EXPORT_SYMBOL_GPL(memory_add_physaddr_to_nid); #endif /* CONFIG_MEMORY_HOTPLUG */ -static struct kcore_list kcore_vsyscall; +static struct kcore_list kcore_mem, kcore_vmalloc, kcore_kernel, + kcore_modules, kcore_vsyscall; void __init mem_init(void) { @@ -676,8 +677,13 @@ void __init mem_init(void) initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin; /* Register memory areas for /proc/kcore */ + kclist_add(&kcore_mem, __va(0), max_low_pfn << PAGE_SHIFT); + kclist_add(&kcore_vmalloc, (void *)VMALLOC_START, + VMALLOC_END-VMALLOC_START); + kclist_add(&kcore_kernel, &_stext, _end - _stext); + kclist_add(&kcore_modules, (void *)MODULES_VADDR, MODULES_LEN); kclist_add(&kcore_vsyscall, (void *)VSYSCALL_START, - VSYSCALL_END - VSYSCALL_START, KCORE_OTHER); + VSYSCALL_END - VSYSCALL_START); printk(KERN_INFO "Memory: %luk/%luk available (%ldk kernel code, " "%ldk absent, %ldk reserved, %ldk data, %ldk init)\n", diff --git a/trunk/arch/x86/pci/mmconfig-shared.c b/trunk/arch/x86/pci/mmconfig-shared.c index 602c172d3bd5..712443ec6d43 100644 --- a/trunk/arch/x86/pci/mmconfig-shared.c +++ b/trunk/arch/x86/pci/mmconfig-shared.c @@ -13,14 +13,10 @@ #include #include #include -#include #include #include #include #include -#include - -#define PREFIX "PCI: " /* aperture is up to 256MB but BIOS may reserve less */ #define MMCONFIG_APER_MIN (2 * 1024*1024) @@ -495,7 +491,7 @@ static void __init pci_mmcfg_reject_broken(int early) (unsigned int)cfg->start_bus_number, (unsigned int)cfg->end_bus_number); - if (!early && !acpi_disabled) + if (!early) valid = is_mmconf_reserved(is_acpi_reserved, addr, size, i, cfg, 0); if (valid) @@ -610,7 +606,7 @@ static void __init __pci_mmcfg_init(int early) } if (!known_bridge) - acpi_sfi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); + acpi_table_parse(ACPI_SIG_MCFG, pci_parse_mcfg); pci_mmcfg_reject_broken(early); diff --git a/trunk/arch/x86/pci/mmconfig_32.c b/trunk/arch/x86/pci/mmconfig_32.c index f10a7e94a84c..8b2d561046a3 100644 --- a/trunk/arch/x86/pci/mmconfig_32.c +++ b/trunk/arch/x86/pci/mmconfig_32.c @@ -11,9 +11,9 @@ #include #include +#include #include #include -#include /* Assume systems with more busses have correct MCFG */ #define mmcfg_virt_addr ((void __iomem *) fix_to_virt(FIX_PCIE_MCFG)) diff --git a/trunk/drivers/Makefile b/trunk/drivers/Makefile index ccfa259fa848..bc4205d2fc3c 100644 --- a/trunk/drivers/Makefile +++ b/trunk/drivers/Makefile @@ -11,7 +11,6 @@ obj-$(CONFIG_PARISC) += parisc/ obj-$(CONFIG_RAPIDIO) += rapidio/ obj-y += video/ obj-$(CONFIG_ACPI) += acpi/ -obj-$(CONFIG_SFI) += sfi/ # PnP must come after ACPI since it will eventually need to check if acpi # was used and do nothing if so obj-$(CONFIG_PNP) += pnp/ diff --git a/trunk/drivers/acpi/Kconfig b/trunk/drivers/acpi/Kconfig index dd8729d674e5..7ec7d88c5999 100644 --- a/trunk/drivers/acpi/Kconfig +++ b/trunk/drivers/acpi/Kconfig @@ -60,11 +60,7 @@ config ACPI_PROCFS /proc/acpi/fadt (/sys/firmware/acpi/tables/FACP) /proc/acpi/debug_layer (/sys/module/acpi/parameters/debug_layer) /proc/acpi/debug_level (/sys/module/acpi/parameters/debug_level) - /proc/acpi/processor/*/power (/sys/devices/system/cpu/*/cpuidle/*) - /proc/acpi/processor/*/performance (/sys/devices/system/cpu/*/ - cpufreq/*) - /proc/acpi/processor/*/throttling (/sys/class/thermal/ - cooling_device*/*) + This option has no effect on /proc/acpi/ files and functions which do not yet exist in /sys. @@ -86,17 +82,6 @@ config ACPI_PROCFS_POWER Say N to delete power /proc/acpi/ directories that have moved to /sys/ -config ACPI_POWER_METER - tristate "ACPI 4.0 power meter" - depends on HWMON - help - This driver exposes ACPI 4.0 power meters as hardware monitoring - devices. Say Y (or M) if you have a computer with ACPI 4.0 firmware - and a power meter. - - To compile this driver as a module, choose M here: - the module will be called power-meter. - config ACPI_SYSFS_POWER bool "Future power /sys interface" select POWER_SUPPLY diff --git a/trunk/drivers/acpi/Makefile b/trunk/drivers/acpi/Makefile index 82cd49dc603b..03a985be3fe3 100644 --- a/trunk/drivers/acpi/Makefile +++ b/trunk/drivers/acpi/Makefile @@ -56,7 +56,6 @@ obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o obj-$(CONFIG_ACPI_BATTERY) += battery.o obj-$(CONFIG_ACPI_SBS) += sbshc.o obj-$(CONFIG_ACPI_SBS) += sbs.o -obj-$(CONFIG_ACPI_POWER_METER) += power_meter.o # processor has its own "processor." module_param namespace processor-y := processor_core.o processor_throttling.o diff --git a/trunk/drivers/acpi/ac.c b/trunk/drivers/acpi/ac.c index 98b9690b0159..0df8fcb687d6 100644 --- a/trunk/drivers/acpi/ac.c +++ b/trunk/drivers/acpi/ac.c @@ -37,8 +37,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_AC_CLASS "ac_adapter" #define ACPI_AC_DEVICE_NAME "AC Adapter" #define ACPI_AC_FILE_STATE "state" diff --git a/trunk/drivers/acpi/acpi_memhotplug.c b/trunk/drivers/acpi/acpi_memhotplug.c index 28ccdbc05ac8..9a62224cc278 100644 --- a/trunk/drivers/acpi/acpi_memhotplug.c +++ b/trunk/drivers/acpi/acpi_memhotplug.c @@ -53,6 +53,7 @@ MODULE_LICENSE("GPL"); static int acpi_memory_device_add(struct acpi_device *device); static int acpi_memory_device_remove(struct acpi_device *device, int type); +static int acpi_memory_device_start(struct acpi_device *device); static const struct acpi_device_id memory_device_ids[] = { {ACPI_MEMORY_DEVICE_HID, 0}, @@ -67,6 +68,7 @@ static struct acpi_driver acpi_memory_device_driver = { .ops = { .add = acpi_memory_device_add, .remove = acpi_memory_device_remove, + .start = acpi_memory_device_start, }, }; @@ -429,6 +431,28 @@ static int acpi_memory_device_add(struct acpi_device *device) printk(KERN_DEBUG "%s \n", acpi_device_name(device)); + return result; +} + +static int acpi_memory_device_remove(struct acpi_device *device, int type) +{ + struct acpi_memory_device *mem_device = NULL; + + + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + mem_device = acpi_driver_data(device); + kfree(mem_device); + + return 0; +} + +static int acpi_memory_device_start (struct acpi_device *device) +{ + struct acpi_memory_device *mem_device; + int result = 0; + /* * Early boot code has recognized memory area by EFI/E820. * If DSDT shows these memory devices on boot, hotplug is not necessary @@ -438,6 +462,8 @@ static int acpi_memory_device_add(struct acpi_device *device) if (!acpi_hotmem_initialized) return 0; + mem_device = acpi_driver_data(device); + if (!acpi_memory_check_device(mem_device)) { /* call add_memory func */ result = acpi_memory_enable_device(mem_device); @@ -448,20 +474,6 @@ static int acpi_memory_device_add(struct acpi_device *device) return result; } -static int acpi_memory_device_remove(struct acpi_device *device, int type) -{ - struct acpi_memory_device *mem_device = NULL; - - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - mem_device = acpi_driver_data(device); - kfree(mem_device); - - return 0; -} - /* * Helper function to check for memory device */ @@ -469,23 +481,26 @@ static acpi_status is_memory_device(acpi_handle handle) { char *hardware_id; acpi_status status; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_device_info *info; - status = acpi_get_object_info(handle, &info); + + status = acpi_get_object_info(handle, &buffer); if (ACPI_FAILURE(status)) return status; + info = buffer.pointer; if (!(info->valid & ACPI_VALID_HID)) { - kfree(info); + kfree(buffer.pointer); return AE_ERROR; } - hardware_id = info->hardware_id.string; + hardware_id = info->hardware_id.value; if ((hardware_id == NULL) || (strcmp(hardware_id, ACPI_MEMORY_DEVICE_HID))) status = AE_ERROR; - kfree(info); + kfree(buffer.pointer); return status; } diff --git a/trunk/drivers/acpi/acpica/Makefile b/trunk/drivers/acpi/acpica/Makefile index e7973bc16846..72ac28da14e3 100644 --- a/trunk/drivers/acpi/acpica/Makefile +++ b/trunk/drivers/acpi/acpica/Makefile @@ -28,7 +28,7 @@ acpi-$(ACPI_FUTURE_USAGE) += hwtimer.o acpi-y += nsaccess.o nsload.o nssearch.o nsxfeval.o \ nsalloc.o nseval.o nsnames.o nsutils.o nsxfname.o \ nsdump.o nsinit.o nsobject.o nswalk.o nsxfobj.o \ - nsparse.o nspredef.o nsrepair.o + nsparse.o nspredef.o acpi-$(ACPI_FUTURE_USAGE) += nsdumpdv.o @@ -44,4 +44,4 @@ acpi-y += tbxface.o tbinstal.o tbutils.o tbfind.o tbfadt.o tbxfroot.o acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \ utcopy.o utdelete.o utglobal.o utmath.o utobject.o \ - utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o + utstate.o utmutex.o utobject.o utresrc.o utlock.o diff --git a/trunk/drivers/acpi/acpica/acconfig.h b/trunk/drivers/acpi/acpica/acconfig.h index 8e679ef5b231..e6777fb883d2 100644 --- a/trunk/drivers/acpi/acpica/acconfig.h +++ b/trunk/drivers/acpi/acpica/acconfig.h @@ -183,7 +183,7 @@ /* Operation regions */ -#define ACPI_NUM_PREDEFINED_REGIONS 9 +#define ACPI_NUM_PREDEFINED_REGIONS 8 #define ACPI_USER_REGION_BEGIN 0x80 /* Maximum space_ids for Operation Regions */ @@ -199,15 +199,9 @@ #define ACPI_RSDP_CHECKSUM_LENGTH 20 #define ACPI_RSDP_XCHECKSUM_LENGTH 36 -/* SMBus and IPMI bidirectional buffer size */ +/* SMBus bidirectional buffer size */ #define ACPI_SMBUS_BUFFER_SIZE 34 -#define ACPI_IPMI_BUFFER_SIZE 66 - -/* _sx_d and _sx_w control methods */ - -#define ACPI_NUM_sx_d_METHODS 4 -#define ACPI_NUM_sx_w_METHODS 5 /****************************************************************************** * diff --git a/trunk/drivers/acpi/acpica/acdebug.h b/trunk/drivers/acpi/acpica/acdebug.h index a4fb001d96f1..62c59df3b86c 100644 --- a/trunk/drivers/acpi/acpica/acdebug.h +++ b/trunk/drivers/acpi/acpica/acdebug.h @@ -154,6 +154,10 @@ void acpi_db_display_argument_object(union acpi_operand_object *obj_desc, struct acpi_walk_state *walk_state); +void acpi_db_check_predefined_names(void); + +void acpi_db_batch_execute(void); + /* * dbexec - debugger control method execution */ diff --git a/trunk/drivers/acpi/acpica/acglobal.h b/trunk/drivers/acpi/acpica/acglobal.h index 29ba66d5a790..3d87362d17ed 100644 --- a/trunk/drivers/acpi/acpica/acglobal.h +++ b/trunk/drivers/acpi/acpica/acglobal.h @@ -58,10 +58,6 @@ #define ACPI_INIT_GLOBAL(a,b) a #endif -#ifdef DEFINE_ACPI_GLOBALS - -/* Public globals, available from outside ACPICA subsystem */ - /***************************************************************************** * * Runtime configuration (static defaults that can be overriden at runtime) @@ -82,7 +78,7 @@ * 5) Allow unresolved references (invalid target name) in package objects * 6) Enable warning messages for behavior that is not ACPI spec compliant */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); +ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); /* * Automatically serialize ALL control methods? Default is FALSE, meaning @@ -90,36 +86,27 @@ u8 ACPI_INIT_GLOBAL(acpi_gbl_enable_interpreter_slack, FALSE); * Only change this if the ASL code is poorly written and cannot handle * reentrancy even though methods are marked "NotSerialized". */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE); +ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_all_methods_serialized, FALSE); /* * Create the predefined _OSI method in the namespace? Default is TRUE * because ACPI CA is fully compatible with other ACPI implementations. * Changing this will revert ACPI CA (and machine ASL) to pre-OSI behavior. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE); +ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_create_osi_method, TRUE); /* * Disable wakeup GPEs during runtime? Default is TRUE because WAKE and * RUNTIME GPEs should never be shared, and WAKE GPEs should typically only * be enabled just before going to sleep. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE); +ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_leave_wake_gpes_disabled, TRUE); /* * Optionally use default values for the ACPI register widths. Set this to * TRUE to use the defaults, if an FADT contains incorrect widths/lengths. */ -u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); - -/* acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ - -struct acpi_table_fadt acpi_gbl_FADT; -u32 acpi_current_gpe_count; -u32 acpi_gbl_trace_flags; -acpi_name acpi_gbl_trace_method_name; - -#endif +ACPI_EXTERN u8 ACPI_INIT_GLOBAL(acpi_gbl_use_default_register_widths, TRUE); /***************************************************************************** * @@ -127,6 +114,11 @@ acpi_name acpi_gbl_trace_method_name; * ****************************************************************************/ +/* Runtime configuration of debug print levels */ + +extern u32 acpi_dbg_level; +extern u32 acpi_dbg_layer; + /* Procedure nesting level for debug output */ extern u32 acpi_gbl_nesting_level; @@ -135,8 +127,10 @@ extern u32 acpi_gbl_nesting_level; ACPI_EXTERN u32 acpi_gbl_original_dbg_level; ACPI_EXTERN u32 acpi_gbl_original_dbg_layer; +ACPI_EXTERN acpi_name acpi_gbl_trace_method_name; ACPI_EXTERN u32 acpi_gbl_trace_dbg_level; ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; +ACPI_EXTERN u32 acpi_gbl_trace_flags; /***************************************************************************** * @@ -148,8 +142,10 @@ ACPI_EXTERN u32 acpi_gbl_trace_dbg_layer; * acpi_gbl_root_table_list is the master list of ACPI tables found in the * RSDT/XSDT. * + * acpi_gbl_FADT is a local copy of the FADT, converted to a common format. */ ACPI_EXTERN struct acpi_internal_rsdt acpi_gbl_root_table_list; +ACPI_EXTERN struct acpi_table_fadt acpi_gbl_FADT; ACPI_EXTERN struct acpi_table_facs *acpi_gbl_FACS; /* These addresses are calculated from the FADT Event Block addresses */ @@ -265,8 +261,7 @@ ACPI_EXTERN u8 acpi_gbl_osi_data; extern u8 acpi_gbl_shutdown; extern u32 acpi_gbl_startup_flags; extern const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT]; -extern const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS]; -extern const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS]; +extern const char *acpi_gbl_highest_dstate_names[4]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; @@ -295,7 +290,6 @@ extern char const *acpi_gbl_exception_names_ctrl[]; ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; -ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list; extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; extern const struct acpi_predefined_names @@ -346,6 +340,7 @@ ACPI_EXTERN struct acpi_fixed_event_handler ACPI_EXTERN struct acpi_gpe_xrupt_info *acpi_gbl_gpe_xrupt_list_head; ACPI_EXTERN struct acpi_gpe_block_info *acpi_gbl_gpe_fadt_blocks[ACPI_MAX_GPE_BLOCKS]; +ACPI_EXTERN u32 acpi_current_gpe_count; /***************************************************************************** * diff --git a/trunk/drivers/acpi/acpica/achware.h b/trunk/drivers/acpi/acpica/achware.h index 36192f142fbb..4afa3d8e0efb 100644 --- a/trunk/drivers/acpi/acpica/achware.h +++ b/trunk/drivers/acpi/acpica/achware.h @@ -62,14 +62,6 @@ u32 acpi_hw_get_mode(void); /* * hwregs - ACPI Register I/O */ -acpi_status -acpi_hw_validate_register(struct acpi_generic_address *reg, - u8 max_bit_width, u64 *address); - -acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg); - -acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg); - struct acpi_bit_register_info *acpi_hw_get_bit_register_info(u32 register_id); acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control); diff --git a/trunk/drivers/acpi/acpica/acinterp.h b/trunk/drivers/acpi/acpica/acinterp.h index 5db9f2916f7c..e8db7a3143a5 100644 --- a/trunk/drivers/acpi/acpica/acinterp.h +++ b/trunk/drivers/acpi/acpica/acinterp.h @@ -461,9 +461,9 @@ void acpi_ex_acquire_global_lock(u32 rule); void acpi_ex_release_global_lock(u32 rule); -void acpi_ex_eisa_id_to_string(char *dest, acpi_integer compressed_id); +void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string); -void acpi_ex_integer_to_string(char *dest, acpi_integer value); +void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string); /* * exregion - default op_region handlers diff --git a/trunk/drivers/acpi/acpica/aclocal.h b/trunk/drivers/acpi/acpica/aclocal.h index 81e64f478679..ee986edfa0da 100644 --- a/trunk/drivers/acpi/acpica/aclocal.h +++ b/trunk/drivers/acpi/acpica/aclocal.h @@ -369,19 +369,6 @@ union acpi_predefined_info { struct acpi_package_info3 ret_info3; }; -/* Data block used during object validation */ - -struct acpi_predefined_data { - char *pathname; - const union acpi_predefined_info *predefined; - u32 flags; - u8 node_flags; -}; - -/* Defines for Flags field above */ - -#define ACPI_OBJECT_REPAIRED 1 - /* * Bitmapped return value types * Note: the actual data types must be contiguous, a loop in nspredef.c @@ -898,9 +885,6 @@ struct acpi_bit_register_info { #define ACPI_OSI_WIN_XP_SP2 0x05 #define ACPI_OSI_WINSRV_2003_SP1 0x06 #define ACPI_OSI_WIN_VISTA 0x07 -#define ACPI_OSI_WINSRV_2008 0x08 -#define ACPI_OSI_WIN_VISTA_SP1 0x09 -#define ACPI_OSI_WIN_7 0x0A #define ACPI_ALWAYS_ILLEGAL 0x00 diff --git a/trunk/drivers/acpi/acpica/acmacros.h b/trunk/drivers/acpi/acpica/acmacros.h index 3acd9c6760ea..91ac7d7b4402 100644 --- a/trunk/drivers/acpi/acpica/acmacros.h +++ b/trunk/drivers/acpi/acpica/acmacros.h @@ -340,7 +340,6 @@ */ #define ACPI_ERROR_NAMESPACE(s, e) acpi_ns_report_error (AE_INFO, s, e); #define ACPI_ERROR_METHOD(s, n, p, e) acpi_ns_report_method_error (AE_INFO, s, n, p, e); -#define ACPI_WARN_PREDEFINED(plist) acpi_ut_predefined_warning plist #else @@ -348,7 +347,6 @@ #define ACPI_ERROR_NAMESPACE(s, e) #define ACPI_ERROR_METHOD(s, n, p, e) -#define ACPI_WARN_PREDEFINED(plist) #endif /* ACPI_NO_ERROR_MESSAGES */ /* diff --git a/trunk/drivers/acpi/acpica/acnamesp.h b/trunk/drivers/acpi/acpica/acnamesp.h index 09a2764c734b..94cdc2b8cb93 100644 --- a/trunk/drivers/acpi/acpica/acnamesp.h +++ b/trunk/drivers/acpi/acpica/acnamesp.h @@ -73,14 +73,6 @@ #define ACPI_NS_WALK_UNLOCK 0x01 #define ACPI_NS_WALK_TEMP_NODES 0x02 -/* Object is not a package element */ - -#define ACPI_NOT_PACKAGE_ELEMENT ACPI_UINT32_MAX - -/* Always emit warning message, not dependent on node flags */ - -#define ACPI_WARN_ALWAYS 0 - /* * nsinit - Namespace initialization */ @@ -152,8 +144,6 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name); void acpi_ns_delete_node(struct acpi_namespace_node *node); -void acpi_ns_remove_node(struct acpi_namespace_node *node); - void acpi_ns_delete_namespace_subtree(struct acpi_namespace_node *parent_handle); @@ -196,8 +186,6 @@ acpi_ns_dump_objects(acpi_object_type type, */ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); -void acpi_ns_exec_module_code_list(void); - /* * nspredef - Support for predefined/reserved names */ @@ -271,19 +259,6 @@ acpi_status acpi_ns_get_attached_data(struct acpi_namespace_node *node, acpi_object_handler handler, void **data); -/* - * nsrepair - return object repair for predefined methods/objects - */ -acpi_status -acpi_ns_repair_object(struct acpi_predefined_data *data, - u32 expected_btypes, - u32 package_index, - union acpi_operand_object **return_object_ptr); - -acpi_status -acpi_ns_repair_package_list(struct acpi_predefined_data *data, - union acpi_operand_object **obj_desc_ptr); - /* * nssearch - Namespace searching and entry */ diff --git a/trunk/drivers/acpi/acpica/acobject.h b/trunk/drivers/acpi/acpica/acobject.h index b39d682a2140..eb6f038b03d9 100644 --- a/trunk/drivers/acpi/acpica/acobject.h +++ b/trunk/drivers/acpi/acpica/acobject.h @@ -98,7 +98,6 @@ #define AOPOBJ_SETUP_COMPLETE 0x10 #define AOPOBJ_SINGLE_DATUM 0x20 #define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ -#define AOPOBJ_MODULE_LEVEL 0x80 /****************************************************************************** * diff --git a/trunk/drivers/acpi/acpica/acparser.h b/trunk/drivers/acpi/acpica/acparser.h index 22881e8ce229..23ee0fbf5619 100644 --- a/trunk/drivers/acpi/acpica/acparser.h +++ b/trunk/drivers/acpi/acpica/acparser.h @@ -62,8 +62,6 @@ #define ACPI_PARSE_DEFERRED_OP 0x0100 #define ACPI_PARSE_DISASSEMBLE 0x0200 -#define ACPI_PARSE_MODULE_LEVEL 0x0400 - /****************************************************************************** * * Parser interfaces diff --git a/trunk/drivers/acpi/acpica/acpredef.h b/trunk/drivers/acpi/acpica/acpredef.h index cd80d1dd1950..63f656ae3604 100644 --- a/trunk/drivers/acpi/acpica/acpredef.h +++ b/trunk/drivers/acpi/acpica/acpredef.h @@ -64,8 +64,8 @@ * (Used for _PRW) * * - * 2) PTYPE2 packages contain a Variable-length number of sub-packages. Each - * of the different types describe the contents of each of the sub-packages. + * 2) PTYPE2 packages contain a variable number of sub-packages. Each of the + * different types describe the contents of each of the sub-packages. * * ACPI_PTYPE2: Each subpackage contains 1 or 2 object types: * object type @@ -91,9 +91,6 @@ * ACPI_PTYPE2_MIN: Each subpackage has a variable but minimum length * (Used for _HPX) * - * ACPI_PTYPE2_REV_FIXED: Revision at start, each subpackage is Fixed-length - * (Used for _ART, _FPS) - * *****************************************************************************/ enum acpi_return_package_types { @@ -104,11 +101,9 @@ enum acpi_return_package_types { ACPI_PTYPE2_COUNT = 5, ACPI_PTYPE2_PKG_COUNT = 6, ACPI_PTYPE2_FIXED = 7, - ACPI_PTYPE2_MIN = 8, - ACPI_PTYPE2_REV_FIXED = 9 + ACPI_PTYPE2_MIN = 8 }; -#ifdef ACPI_CREATE_PREDEFINED_TABLE /* * Predefined method/object information table. * @@ -141,384 +136,239 @@ enum acpi_return_package_types { * is saved here (rather than in a separate table) in order to minimize the * overall size of the stored data. */ -static const union acpi_predefined_info predefined_names[] = -{ - {{"_AC0", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC1", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC2", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC3", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC4", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC5", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC6", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC7", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC8", 0, ACPI_RTYPE_INTEGER}}, - {{"_AC9", 0, ACPI_RTYPE_INTEGER}}, - {{"_ADR", 0, ACPI_RTYPE_INTEGER}}, - {{"_AL0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL4", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL5", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL6", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL7", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL8", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_AL9", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_ALC", 0, ACPI_RTYPE_INTEGER}}, - {{"_ALI", 0, ACPI_RTYPE_INTEGER}}, - {{"_ALP", 0, ACPI_RTYPE_INTEGER}}, - {{"_ALR", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2 (Ints) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, - - {{"_ALT", 0, ACPI_RTYPE_INTEGER}}, - {{"_ART", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (2 Ref/11 Int) */ - {{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, - 11, 0}}, - - {{"_BBN", 0, ACPI_RTYPE_INTEGER}}, - {{"_BCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_BCM", 1, 0}}, - {{"_BCT", 1, ACPI_RTYPE_INTEGER}}, - {{"_BDN", 0, ACPI_RTYPE_INTEGER}}, - {{"_BFS", 1, 0}}, - {{"_BIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (9 Int),(4 Str) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 9, ACPI_RTYPE_STRING}, 4,0}}, - - {{"_BIX", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int),(4 Str) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, ACPI_RTYPE_STRING}, 4, - 0}}, - - {{"_BLT", 3, 0}}, - {{"_BMA", 1, ACPI_RTYPE_INTEGER}}, - {{"_BMC", 1, 0}}, - {{"_BMD", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (5 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_BMS", 1, ACPI_RTYPE_INTEGER}}, - {{"_BQC", 0, ACPI_RTYPE_INTEGER}}, - {{"_BST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, - - {{"_BTM", 1, ACPI_RTYPE_INTEGER}}, - {{"_BTP", 1, 0}}, - {{"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* See PCI firmware spec 3.0 */ - {{"_CDM", 0, ACPI_RTYPE_INTEGER}}, - {{"_CID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints/Strs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0,0}, 0,0}}, - - {{"_CRS", 0, ACPI_RTYPE_BUFFER}}, - {{"_CRT", 0, ACPI_RTYPE_INTEGER}}, - {{"_CSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n-1 Int) */ - {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_CST", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(n), n Pkg (1 Buf/3 Int) */ - {{{ACPI_PTYPE2_PKG_COUNT,ACPI_RTYPE_BUFFER, 1, ACPI_RTYPE_INTEGER}, 3,0}}, - - {{"_DCK", 1, ACPI_RTYPE_INTEGER}}, - {{"_DCS", 0, ACPI_RTYPE_INTEGER}}, - {{"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}}, - {{"_DDN", 0, ACPI_RTYPE_STRING}}, - {{"_DGS", 0, ACPI_RTYPE_INTEGER}}, - {{"_DIS", 0, 0}}, - {{"_DMA", 0, ACPI_RTYPE_BUFFER}}, - {{"_DOD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_DOS", 1, 0}}, - {{"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */ - {{"_DSS", 1, 0}}, - {{"_DSW", 3, 0}}, - {{"_DTI", 1, 0}}, - {{"_EC_", 0, ACPI_RTYPE_INTEGER}}, - {{"_EDL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs)*/ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_EJ0", 1, 0}}, - {{"_EJ1", 1, 0}}, - {{"_EJ2", 1, 0}}, - {{"_EJ3", 1, 0}}, - {{"_EJ4", 1, 0}}, - {{"_EJD", 0, ACPI_RTYPE_STRING}}, - {{"_FDE", 0, ACPI_RTYPE_BUFFER}}, - {{"_FDI", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (16 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16,0}, 0,0}}, - - {{"_FDM", 1, 0}}, - {{"_FIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0}, 0, 0}}, - - {{"_FIX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Ints) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0,0}, 0,0}}, - - {{"_FPS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (1 Int(rev), n Pkg (5 Int) */ - {{{ACPI_PTYPE2_REV_FIXED, ACPI_RTYPE_INTEGER, 5, 0}, 0, 0}}, - - {{"_FSL", 1, 0}}, - {{"_FST", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, 0}, 0, 0}}, - - {{"_GAI", 0, ACPI_RTYPE_INTEGER}}, - {{"_GHL", 0, ACPI_RTYPE_INTEGER}}, - {{"_GLK", 0, ACPI_RTYPE_INTEGER}}, - {{"_GPD", 0, ACPI_RTYPE_INTEGER}}, - {{"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */ - {{"_GSB", 0, ACPI_RTYPE_INTEGER}}, - {{"_GTF", 0, ACPI_RTYPE_BUFFER}}, - {{"_GTM", 0, ACPI_RTYPE_BUFFER}}, - {{"_GTS", 1, 0}}, - {{"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, - {{"_HOT", 0, ACPI_RTYPE_INTEGER}}, - {{"_HPP", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, +static const union acpi_predefined_info predefined_names[] = { + {.info = {"_AC0", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC1", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC2", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC3", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC4", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC5", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC6", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC7", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC8", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AC9", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_ADR", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_AL0", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL1", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL2", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL3", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL4", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL5", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL6", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL7", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL8", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_AL9", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_ALC", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_ALI", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_ALP", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_ALR", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* variable (Pkgs) each 2 (Ints) */ + {.info = {"_ALT", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_BBN", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_BCL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */ + {.info = {"_BCM", 1, 0}}, + {.info = {"_BDN", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_BFS", 1, 0}}, + {.info = {"_BIF", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, + 9, + ACPI_RTYPE_STRING | ACPI_RTYPE_BUFFER, 4, 0}}, /* fixed (9 Int),(4 Str) */ + {.info = {"_BLT", 3, 0}}, + {.info = {"_BMC", 1, 0}}, + {.info = {"_BMD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* fixed (5 Int) */ + {.info = {"_BQC", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_BST", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */ + {.info = {"_BTM", 1, ACPI_RTYPE_INTEGER}}, + {.info = {"_BTP", 1, 0}}, + {.info = {"_CBA", 0, ACPI_RTYPE_INTEGER}}, /* see PCI firmware spec 3.0 */ + {.info = {"_CID", 0, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING | ACPI_RTYPE_PACKAGE}}, + {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING, 0, 0, 0, 0}}, /* variable (Ints/Strs) */ + {.info = {"_CRS", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_CRT", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_CSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (1 Int(n), n-1 Int) */ + {.info = {"_CST", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_PKG_COUNT, + ACPI_RTYPE_BUFFER, 1, + ACPI_RTYPE_INTEGER, 3, 0}}, /* variable (1 Int(n), n Pkg (1 Buf/3 Int) */ + {.info = {"_DCK", 1, ACPI_RTYPE_INTEGER}}, + {.info = {"_DCS", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_DDC", 1, ACPI_RTYPE_INTEGER | ACPI_RTYPE_BUFFER}}, + {.info = {"_DDN", 0, ACPI_RTYPE_STRING}}, + {.info = {"_DGS", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_DIS", 0, 0}}, + {.info = {"_DMA", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_DOD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */ + {.info = {"_DOS", 1, 0}}, + {.info = {"_DSM", 4, ACPI_RTYPE_ALL}}, /* Must return a type, but it can be of any type */ + {.info = {"_DSS", 1, 0}}, + {.info = {"_DSW", 3, 0}}, + {.info = {"_EC_", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_EDL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_EJ0", 1, 0}}, + {.info = {"_EJ1", 1, 0}}, + {.info = {"_EJ2", 1, 0}}, + {.info = {"_EJ3", 1, 0}}, + {.info = {"_EJ4", 1, 0}}, + {.info = {"_EJD", 0, ACPI_RTYPE_STRING}}, + {.info = {"_FDE", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_FDI", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 16, 0, 0, 0}}, /* fixed (16 Int) */ + {.info = {"_FDM", 1, 0}}, + {.info = {"_FIX", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Ints) */ + {.info = {"_GLK", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_GPD", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_GPE", 0, ACPI_RTYPE_INTEGER}}, /* _GPE method, not _GPE scope */ + {.info = {"_GSB", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_GTF", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_GTM", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_GTS", 1, 0}}, + {.info = {"_HID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, + {.info = {"_HOT", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_HPP", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */ /* - * For _HPX, a single package is returned, containing a Variable-length number - * of sub-packages. Each sub-package contains a PCI record setting. - * There are several different type of record settings, of different - * lengths, but all elements of all settings are Integers. + * For _HPX, a single package is returned, containing a variable number of sub-packages. + * Each sub-package contains a PCI record setting. There are several different type of + * record settings, of different lengths, but all elements of all settings are Integers. */ - {{"_HPX", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (var Ints) */ - {{{ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ - {{"_INI", 0, 0}}, - {{"_IRC", 0, 0}}, - {{"_LCK", 1, 0}}, - {{"_LID", 0, ACPI_RTYPE_INTEGER}}, - {{"_MAT", 0, ACPI_RTYPE_BUFFER}}, - {{"_MBM", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (8 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 8, 0}, 0, 0}}, - - {{"_MLS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (2 Str) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_STRING, 2,0}, 0,0}}, - - {{"_MSG", 1, 0}}, - {{"_MSM", 4, ACPI_RTYPE_INTEGER}}, - {{"_NTT", 0, ACPI_RTYPE_INTEGER}}, - {{"_OFF", 0, 0}}, - {{"_ON_", 0, 0}}, - {{"_OS_", 0, ACPI_RTYPE_STRING}}, - {{"_OSC", 4, ACPI_RTYPE_BUFFER}}, - {{"_OST", 3, 0}}, - {{"_PAI", 1, ACPI_RTYPE_INTEGER}}, - {{"_PCL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PCT", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, - - {{"_PDC", 1, 0}}, - {{"_PDL", 0, ACPI_RTYPE_INTEGER}}, - {{"_PIC", 1, 0}}, - {{"_PIF", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (3 Int),(3 Str) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 3, ACPI_RTYPE_STRING}, 3, 0}}, - - {{"_PLD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Bufs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0,0}, 0,0}}, - - {{"_PMC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (11 Int),(3 Str) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 11, ACPI_RTYPE_STRING}, 3, - 0}}, - - {{"_PMD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_PMM", 0, ACPI_RTYPE_INTEGER}}, - {{"_PPC", 0, ACPI_RTYPE_INTEGER}}, - {{"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* See dig64 spec */ - {{"_PR0", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PR1", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PR2", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PR3", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_PRL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0}, 0, 0}}, - - {{"_PRS", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_HPX", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_MIN, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each (var Ints) */ + {.info = {"_IFT", 0, ACPI_RTYPE_INTEGER}}, /* see IPMI spec */ + {.info = {"_INI", 0, 0}}, + {.info = {"_IRC", 0, 0}}, + {.info = {"_LCK", 1, 0}}, + {.info = {"_LID", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_MAT", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_MLS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_STRING, 2, 0, 0, 0}}, /* variable (Pkgs) each (2 Str) */ + {.info = {"_MSG", 1, 0}}, + {.info = {"_OFF", 0, 0}}, + {.info = {"_ON_", 0, 0}}, + {.info = {"_OS_", 0, ACPI_RTYPE_STRING}}, + {.info = {"_OSC", 4, ACPI_RTYPE_BUFFER}}, + {.info = {"_OST", 3, 0}}, + {.info = {"_PCL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_PCT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0}}, /* fixed (2 Buf) */ + {.info = {"_PDC", 1, 0}}, + {.info = {"_PIC", 1, 0}}, + {.info = {"_PLD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_BUFFER, 0, 0, 0, 0}}, /* variable (Bufs) */ + {.info = {"_PPC", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_PPE", 0, ACPI_RTYPE_INTEGER}}, /* see dig64 spec */ + {.info = {"_PR0", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_PR1", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_PR2", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_PRS", 0, ACPI_RTYPE_BUFFER}}, /* - * For _PRT, many BIOSs reverse the 3rd and 4th Package elements (Source - * and source_index). This bug is so prevalent that there is code in the - * ACPICA Resource Manager to detect this and switch them back. For now, - * do not allow and issue a warning. To allow this and eliminate the - * warning, add the ACPI_RTYPE_REFERENCE type to the 4th element (index 3) - * in the statement below. + * For _PRT, many BIOSs reverse the 2nd and 3rd Package elements. This bug is so prevalent that there + * is code in the ACPICA Resource Manager to detect this and switch them back. For now, do not allow + * and issue a warning. To allow this and eliminate the warning, add the ACPI_RTYPE_REFERENCE + * type to the 2nd element (index 1) in the statement below. */ - {{"_PRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (4): Int,Int,Int/Ref,Int */ - {{{ACPI_PTYPE2_FIXED, 4, ACPI_RTYPE_INTEGER,ACPI_RTYPE_INTEGER}, - ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, - ACPI_RTYPE_INTEGER}}, - - {{"_PRW", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each: Pkg/Int,Int,[Variable-length Refs] (Pkg is Ref/Int) */ - {{{ACPI_PTYPE1_OPTION, 2, ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE, - ACPI_RTYPE_INTEGER}, ACPI_RTYPE_REFERENCE,0}}, - - {{"_PS0", 0, 0}}, - {{"_PS1", 0, 0}}, - {{"_PS2", 0, 0}}, - {{"_PS3", 0, 0}}, - {{"_PSC", 0, ACPI_RTYPE_INTEGER}}, - {{"_PSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (5 Int) with count */ - {{{ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER,0,0}, 0,0}}, - - {{"_PSL", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_PSR", 0, ACPI_RTYPE_INTEGER}}, - {{"_PSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each (6 Int) */ - {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6,0}, 0,0}}, - - {{"_PSV", 0, ACPI_RTYPE_INTEGER}}, - {{"_PSW", 1, 0}}, - {{"_PTC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Buf) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2,0}, 0,0}}, - - {{"_PTP", 2, ACPI_RTYPE_INTEGER}}, - {{"_PTS", 1, 0}}, - {{"_PUR", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (2 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0}, 0, 0}}, - - {{"_PXM", 0, ACPI_RTYPE_INTEGER}}, - {{"_REG", 2, 0}}, - {{"_REV", 0, ACPI_RTYPE_INTEGER}}, - {{"_RMV", 0, ACPI_RTYPE_INTEGER}}, - {{"_ROM", 2, ACPI_RTYPE_BUFFER}}, - {{"_RTV", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_PRT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_FIXED, 4, + ACPI_RTYPE_INTEGER, + ACPI_RTYPE_INTEGER, + ACPI_RTYPE_INTEGER | ACPI_RTYPE_REFERENCE, ACPI_RTYPE_INTEGER}}, /* variable (Pkgs) each (4): Int,Int,Int/Ref,Int */ + + {.info = {"_PRW", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_OPTION, 2, + ACPI_RTYPE_INTEGER | + ACPI_RTYPE_PACKAGE, + ACPI_RTYPE_INTEGER, ACPI_RTYPE_REFERENCE, 0}}, /* variable (Pkgs) each: Pkg/Int,Int,[variable Refs] (Pkg is Ref/Int) */ + + {.info = {"_PS0", 0, 0}}, + {.info = {"_PS1", 0, 0}}, + {.info = {"_PS2", 0, 0}}, + {.info = {"_PS3", 0, 0}}, + {.info = {"_PSC", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_PSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 0, 0, 0, 0}}, /* variable (Pkgs) each (5 Int) with count */ + {.info = {"_PSL", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_PSR", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_PSS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 6, 0, 0, 0}}, /* variable (Pkgs) each (6 Int) */ + {.info = {"_PSV", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_PSW", 1, 0}}, + {.info = {"_PTC", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_BUFFER, 2, 0, 0, 0}}, /* fixed (2 Buf) */ + {.info = {"_PTS", 1, 0}}, + {.info = {"_PXM", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_REG", 2, 0}}, + {.info = {"_REV", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_RMV", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_ROM", 2, ACPI_RTYPE_BUFFER}}, + {.info = {"_RTV", 0, ACPI_RTYPE_INTEGER}}, /* - * For _S0_ through _S5_, the ACPI spec defines a return Package - * containing 1 Integer, but most DSDTs have it wrong - 2,3, or 4 integers. - * Allow this by making the objects "Variable-length length", but all elements - * must be Integers. + * For _S0_ through _S5_, the ACPI spec defines a return Package containing 1 Integer, + * but most DSDTs have it wrong - 2,3, or 4 integers. Allow this by making the objects "variable length", + * but all elements must be Integers. */ - {{"_S0_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S1_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S2_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S3_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S4_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S5_", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (1 Int) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1,0}, 0,0}}, - - {{"_S1D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S2D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S3D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S4D", 0, ACPI_RTYPE_INTEGER}}, - {{"_S0W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S1W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S2W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S3W", 0, ACPI_RTYPE_INTEGER}}, - {{"_S4W", 0, ACPI_RTYPE_INTEGER}}, - {{"_SBS", 0, ACPI_RTYPE_INTEGER}}, - {{"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */ - /* Note: the 3-arg definition may be removed for ACPI 4.0 */ - {{"_SDD", 1, 0}}, - {{"_SEG", 0, ACPI_RTYPE_INTEGER}}, - {{"_SHL", 1, ACPI_RTYPE_INTEGER}}, - {{"_SLI", 0, ACPI_RTYPE_BUFFER}}, - {{"_SPD", 1, ACPI_RTYPE_INTEGER}}, - {{"_SRS", 1, 0}}, - {{"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* See IPMI spec */ - {{"_SST", 1, 0}}, - {{"_STA", 0, ACPI_RTYPE_INTEGER}}, - {{"_STM", 3, 0}}, - {{"_STP", 2, ACPI_RTYPE_INTEGER}}, - {{"_STR", 0, ACPI_RTYPE_BUFFER}}, - {{"_STV", 2, ACPI_RTYPE_INTEGER}}, - {{"_SUN", 0, ACPI_RTYPE_INTEGER}}, - {{"_SWS", 0, ACPI_RTYPE_INTEGER}}, - {{"_TC1", 0, ACPI_RTYPE_INTEGER}}, - {{"_TC2", 0, ACPI_RTYPE_INTEGER}}, - {{"_TIP", 1, ACPI_RTYPE_INTEGER}}, - {{"_TIV", 1, ACPI_RTYPE_INTEGER}}, - {{"_TMP", 0, ACPI_RTYPE_INTEGER}}, - {{"_TPC", 0, ACPI_RTYPE_INTEGER}}, - {{"_TPT", 1, 0}}, - {{"_TRT", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 2_ref/6_int */ - {{{ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, ACPI_RTYPE_INTEGER}, 6, 0}}, - - {{"_TSD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int with count */ - {{{ACPI_PTYPE2_COUNT,ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_TSP", 0, ACPI_RTYPE_INTEGER}}, - {{"_TSS", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Pkgs) each 5_int */ - {{{ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5,0}, 0,0}}, - - {{"_TST", 0, ACPI_RTYPE_INTEGER}}, - {{"_TTS", 1, 0}}, - {{"_TZD", 0, ACPI_RTYPE_PACKAGE}}, /* Variable-length (Refs) */ - {{{ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0,0}, 0,0}}, - - {{"_TZM", 0, ACPI_RTYPE_REFERENCE}}, - {{"_TZP", 0, ACPI_RTYPE_INTEGER}}, - {{"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, - {{"_UPC", 0, ACPI_RTYPE_PACKAGE}}, /* Fixed-length (4 Int) */ - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4,0}, 0,0}}, - - {{"_UPD", 0, ACPI_RTYPE_INTEGER}}, - {{"_UPP", 0, ACPI_RTYPE_INTEGER}}, - {{"_VPO", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S0_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ + {.info = {"_S1_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ + {.info = {"_S2_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ + {.info = {"_S3_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ + {.info = {"_S4_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ + {.info = {"_S5_", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_INTEGER, 1, 0, 0, 0}}, /* fixed (1 Int) */ + + {.info = {"_S1D", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S2D", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S3D", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S4D", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S0W", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S1W", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S2W", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S3W", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_S4W", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_SBS", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_SCP", 0x13, 0}}, /* Acpi 1.0 allowed 1 arg. Acpi 3.0 expanded to 3 args. Allow both. */ + /* Note: the 3-arg definition may be removed for ACPI 4.0 */ + {.info = {"_SDD", 1, 0}}, + {.info = {"_SEG", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_SLI", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_SPD", 1, ACPI_RTYPE_INTEGER}}, + {.info = {"_SRS", 1, 0}}, + {.info = {"_SRV", 0, ACPI_RTYPE_INTEGER}}, /* see IPMI spec */ + {.info = {"_SST", 1, 0}}, + {.info = {"_STA", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_STM", 3, 0}}, + {.info = {"_STR", 0, ACPI_RTYPE_BUFFER}}, + {.info = {"_SUN", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_SWS", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_TC1", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_TC2", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_TMP", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_TPC", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_TPT", 1, 0}}, + {.info = {"_TRT", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_REFERENCE, 2, + ACPI_RTYPE_INTEGER, 6, 0}}, /* variable (Pkgs) each 2_ref/6_int */ + {.info = {"_TSD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2_COUNT, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each 5_int with count */ + {.info = {"_TSP", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_TSS", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE2, ACPI_RTYPE_INTEGER, 5, 0, 0, 0}}, /* variable (Pkgs) each 5_int */ + {.info = {"_TST", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_TTS", 1, 0}}, + {.info = {"_TZD", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_VAR, ACPI_RTYPE_REFERENCE, 0, 0, 0, 0}}, /* variable (Refs) */ + {.info = {"_TZM", 0, ACPI_RTYPE_REFERENCE}}, + {.info = {"_TZP", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_UID", 0, ACPI_RTYPE_INTEGER | ACPI_RTYPE_STRING}}, + {.info = {"_UPC", 0, ACPI_RTYPE_PACKAGE}}, {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 4, 0, 0, 0}}, /* fixed (4 Int) */ + {.info = {"_UPD", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_UPP", 0, ACPI_RTYPE_INTEGER}}, + {.info = {"_VPO", 0, ACPI_RTYPE_INTEGER}}, /* Acpi 1.0 defined _WAK with no return value. Later, it was changed to return a package */ - {{"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, - {{{ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2,0}, 0,0}}, /* Fixed-length (2 Int), but is optional */ - - {{{0,0,0,0}, 0,0}} /* Table terminator */ + {.info = {"_WAK", 1, ACPI_RTYPE_NONE | ACPI_RTYPE_INTEGER | ACPI_RTYPE_PACKAGE}}, + {.ret_info = {ACPI_PTYPE1_FIXED, ACPI_RTYPE_INTEGER, 2, 0, 0, 0}}, /* fixed (2 Int), but is optional */ + {.ret_info = {0, 0, 0, 0, 0, 0}} /* Table terminator */ }; #if 0 /* Not implemented */ - {{"_WDG", 0, ACPI_RTYPE_BUFFER}}, /* MS Extension */ - {{"_WED", 1, ACPI_RTYPE_PACKAGE}}, /* MS Extension */ - - /* This is an internally implemented control method, no need to check */ - {{"_OSI", 1, ACPI_RTYPE_INTEGER}}, +{ +"_WDG", 0, ACPI_RTYPE_BUFFER}, /* MS Extension */ - /* TBD: */ +{ +"_WED", 1, ACPI_RTYPE_PACKAGE}, /* MS Extension */ - _PRT - currently ignore reversed entries. attempt to fix here? - think about possibly fixing package elements like _BIF, etc. -#endif + /* This is an internally implemented control method, no need to check */ +{ +"_OSI", 1, ACPI_RTYPE_INTEGER}, + /* TBD: */ + _PRT - currently ignore reversed entries.attempt to fix here ? + think about code that attempts to fix package elements like _BIF, etc. #endif #endif diff --git a/trunk/drivers/acpi/acpica/acutils.h b/trunk/drivers/acpi/acpica/acutils.h index 863a264b829e..897810ba0ccc 100644 --- a/trunk/drivers/acpi/acpica/acutils.h +++ b/trunk/drivers/acpi/acpica/acutils.h @@ -324,30 +324,26 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, acpi_status acpi_ut_evaluate_numeric_object(char *object_name, struct acpi_namespace_node *device_node, - acpi_integer *value); + acpi_integer * address); acpi_status -acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 *status_flags); +acpi_ut_execute_HID(struct acpi_namespace_node *device_node, + struct acpica_device_id *hid); acpi_status -acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, - const char **method_names, - u8 method_count, u8 *out_values); +acpi_ut_execute_CID(struct acpi_namespace_node *device_node, + struct acpi_compatible_id_list **return_cid_list); -/* - * utids - device ID support - */ acpi_status -acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id); +acpi_ut_execute_STA(struct acpi_namespace_node *device_node, + u32 * status_flags); acpi_status acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id); + struct acpica_device_id *uid); acpi_status -acpi_ut_execute_CID(struct acpi_namespace_node *device_node, - struct acpica_device_id_list **return_cid_list); +acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest); /* * utlock - reader/writer locks @@ -449,8 +445,6 @@ acpi_ut_short_divide(acpi_integer in_dividend, */ const char *acpi_ut_validate_exception(acpi_status status); -u8 acpi_ut_is_pci_root_bridge(char *id); - u8 acpi_ut_is_aml_table(struct acpi_table_header *table); acpi_status acpi_ut_allocate_owner_id(acpi_owner_id * owner_id); @@ -475,12 +469,6 @@ u8 acpi_ut_valid_acpi_char(char character, u32 position); acpi_status acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer); -void ACPI_INTERNAL_VAR_XFACE -acpi_ut_predefined_warning(const char *module_name, - u32 line_number, - char *pathname, - u8 node_flags, const char *format, ...); - /* Values for Base above (16=Hex, 10=Decimal) */ #define ACPI_ANY_BASE 0 diff --git a/trunk/drivers/acpi/acpica/amlcode.h b/trunk/drivers/acpi/acpica/amlcode.h index 4940249f2524..067f967eb389 100644 --- a/trunk/drivers/acpi/acpica/amlcode.h +++ b/trunk/drivers/acpi/acpica/amlcode.h @@ -404,7 +404,6 @@ typedef enum { REGION_SMBUS, REGION_CMOS, REGION_PCI_BAR, - REGION_IPMI, REGION_DATA_TABLE, /* Internal use only */ REGION_FIXED_HW = 0x7F } AML_REGION_TYPES; diff --git a/trunk/drivers/acpi/acpica/dsfield.c b/trunk/drivers/acpi/acpica/dsfield.c index 54a225e56a64..53e27bc5a734 100644 --- a/trunk/drivers/acpi/acpica/dsfield.c +++ b/trunk/drivers/acpi/acpica/dsfield.c @@ -123,12 +123,9 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op, flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND; - /* - * Mark node temporary if we are executing a normal control - * method. (Don't mark if this is a module-level code method) - */ - if (walk_state->method_node && - !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { + /* Mark node temporary if we are executing a method */ + + if (walk_state->method_node) { flags |= ACPI_NS_TEMPORARY; } @@ -459,12 +456,9 @@ acpi_ds_init_field_objects(union acpi_parse_object *op, flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND; - /* - * Mark node(s) temporary if we are executing a normal control - * method. (Don't mark if this is a module-level code method) - */ - if (walk_state->method_node && - !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) { + /* Mark node(s) temporary if we are executing a method */ + + if (walk_state->method_node) { flags |= ACPI_NS_TEMPORARY; } diff --git a/trunk/drivers/acpi/acpica/dsmethod.c b/trunk/drivers/acpi/acpica/dsmethod.c index 567a4899a018..14b8b8ed8023 100644 --- a/trunk/drivers/acpi/acpica/dsmethod.c +++ b/trunk/drivers/acpi/acpica/dsmethod.c @@ -578,15 +578,10 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, } /* - * Delete any namespace objects created anywhere within the - * namespace by the execution of this method. Unless this method - * is a module-level executable code method, in which case we - * want make the objects permanent. + * Delete any namespace objects created anywhere within + * the namespace by the execution of this method */ - if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { - acpi_ns_delete_namespace_by_owner(method_desc->method. - owner_id); - } + acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); } /* Decrement the thread count on the method */ @@ -627,9 +622,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, /* No more threads, we can free the owner_id */ - if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) { - acpi_ut_release_owner_id(&method_desc->method.owner_id); - } + acpi_ut_release_owner_id(&method_desc->method.owner_id); } return_VOID; diff --git a/trunk/drivers/acpi/acpica/dsmthdat.c b/trunk/drivers/acpi/acpica/dsmthdat.c index 7d077bb2f525..22b1a3ce2c94 100644 --- a/trunk/drivers/acpi/acpica/dsmthdat.c +++ b/trunk/drivers/acpi/acpica/dsmthdat.c @@ -433,10 +433,10 @@ acpi_ds_method_data_get_value(u8 type, case ACPI_REFCLASS_LOCAL: - /* - * No error message for this case, will be trapped again later to - * detect and ignore cases of Store(local_x,local_x) - */ + ACPI_ERROR((AE_INFO, + "Uninitialized Local[%d] at node %p", + index, node)); + return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); default: diff --git a/trunk/drivers/acpi/acpica/dsobject.c b/trunk/drivers/acpi/acpica/dsobject.c index 507e1f0bbdfd..02e6caad4a76 100644 --- a/trunk/drivers/acpi/acpica/dsobject.c +++ b/trunk/drivers/acpi/acpica/dsobject.c @@ -482,27 +482,14 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, if (arg) { /* * num_elements was exhausted, but there are remaining elements in the - * package_list. Truncate the package to num_elements. + * package_list. * * Note: technically, this is an error, from ACPI spec: "It is an error * for NumElements to be less than the number of elements in the - * PackageList". However, we just print an error message and - * no exception is returned. This provides Windows compatibility. Some - * BIOSs will alter the num_elements on the fly, creating this type - * of ill-formed package object. + * PackageList". However, for now, we just print an error message and + * no exception is returned. */ while (arg) { - /* - * We must delete any package elements that were created earlier - * and are not going to be used because of the package truncation. - */ - if (arg->common.node) { - acpi_ut_remove_reference(ACPI_CAST_PTR - (union - acpi_operand_object, - arg->common.node)); - arg->common.node = NULL; - } /* Find out how many elements there really are */ @@ -511,7 +498,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, } ACPI_WARNING((AE_INFO, - "Package List length (0x%X) larger than NumElements count (0x%X), truncated\n", + "Package List length (%X) larger than NumElements count (%X), truncated\n", i, element_count)); } else if (i < element_count) { /* @@ -519,7 +506,7 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, * Note: this is not an error, the package is padded out with NULLs. */ ACPI_DEBUG_PRINT((ACPI_DB_INFO, - "Package List length (0x%X) smaller than NumElements count (0x%X), padded with null elements\n", + "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", i, element_count)); } diff --git a/trunk/drivers/acpi/acpica/dswload.c b/trunk/drivers/acpi/acpica/dswload.c index 6de3a99d4cd4..3023ceaa8d54 100644 --- a/trunk/drivers/acpi/acpica/dswload.c +++ b/trunk/drivers/acpi/acpica/dswload.c @@ -581,6 +581,21 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, if ((!(walk_state->op_info->flags & AML_NSOPCODE) && (walk_state->opcode != AML_INT_NAMEPATH_OP)) || (!(walk_state->op_info->flags & AML_NAMED))) { +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || + (walk_state->op_info->class == AML_CLASS_CONTROL)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "Begin/EXEC: %s (fl %8.8X)\n", + walk_state->op_info->name, + walk_state->op_info->flags)); + + /* Executing a type1 or type2 opcode outside of a method */ + + status = + acpi_ds_exec_begin_op(walk_state, out_op); + return_ACPI_STATUS(status); + } +#endif return_ACPI_STATUS(AE_OK); } @@ -753,13 +768,7 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, /* Execution mode, node cannot already exist, node is temporary */ - flags |= ACPI_NS_ERROR_IF_FOUND; - - if (! - (walk_state-> - parse_flags & ACPI_PARSE_MODULE_LEVEL)) { - flags |= ACPI_NS_TEMPORARY; - } + flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY); } /* Add new entry or lookup existing entry */ @@ -842,6 +851,24 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) /* Check if opcode had an associated namespace object */ if (!(walk_state->op_info->flags & AML_NSOBJECT)) { +#ifndef ACPI_NO_METHOD_EXECUTION +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + /* No namespace object. Executable opcode? */ + + if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || + (walk_state->op_info->class == AML_CLASS_CONTROL)) { + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "End/EXEC: %s (fl %8.8X)\n", + walk_state->op_info->name, + walk_state->op_info->flags)); + + /* Executing a type1 or type2 opcode outside of a method */ + + status = acpi_ds_exec_end_op(walk_state); + return_ACPI_STATUS(status); + } +#endif +#endif return_ACPI_STATUS(AE_OK); } diff --git a/trunk/drivers/acpi/acpica/evgpe.c b/trunk/drivers/acpi/acpica/evgpe.c index afacf4416c73..b9d8ee69ca6c 100644 --- a/trunk/drivers/acpi/acpica/evgpe.c +++ b/trunk/drivers/acpi/acpica/evgpe.c @@ -424,8 +424,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) /* Read the Status Register */ status = - acpi_hw_read(&status_reg, - &gpe_register_info->status_address); + acpi_read(&status_reg, + &gpe_register_info->status_address); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -433,8 +433,8 @@ u32 acpi_ev_gpe_detect(struct acpi_gpe_xrupt_info * gpe_xrupt_list) /* Read the Enable Register */ status = - acpi_hw_read(&enable_reg, - &gpe_register_info->enable_address); + acpi_read(&enable_reg, + &gpe_register_info->enable_address); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } diff --git a/trunk/drivers/acpi/acpica/evgpeblk.c b/trunk/drivers/acpi/acpica/evgpeblk.c index a60aaa7635f3..7b3463639422 100644 --- a/trunk/drivers/acpi/acpica/evgpeblk.c +++ b/trunk/drivers/acpi/acpica/evgpeblk.c @@ -843,14 +843,14 @@ acpi_ev_create_gpe_info_blocks(struct acpi_gpe_block_info *gpe_block) /* Disable all GPEs within this register */ - status = acpi_hw_write(0x00, &this_register->enable_address); + status = acpi_write(0x00, &this_register->enable_address); if (ACPI_FAILURE(status)) { goto error_exit; } /* Clear any pending GPE events within this register */ - status = acpi_hw_write(0xFF, &this_register->status_address); + status = acpi_write(0xFF, &this_register->status_address); if (ACPI_FAILURE(status)) { goto error_exit; } diff --git a/trunk/drivers/acpi/acpica/evrgnini.c b/trunk/drivers/acpi/acpica/evrgnini.c index cf29c4953028..284a7becbe96 100644 --- a/trunk/drivers/acpi/acpica/evrgnini.c +++ b/trunk/drivers/acpi/acpica/evrgnini.c @@ -50,6 +50,8 @@ ACPI_MODULE_NAME("evrgnini") /* Local prototypes */ +static u8 acpi_ev_match_pci_root_bridge(char *id); + static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node); /******************************************************************************* @@ -328,6 +330,37 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, return_ACPI_STATUS(AE_OK); } +/******************************************************************************* + * + * FUNCTION: acpi_ev_match_pci_root_bridge + * + * PARAMETERS: Id - The HID/CID in string format + * + * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge + * + * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. + * + ******************************************************************************/ + +static u8 acpi_ev_match_pci_root_bridge(char *id) +{ + + /* + * Check if this is a PCI root. + * ACPI 3.0+: check for a PCI Express root also. + */ + if (!(ACPI_STRNCMP(id, + PCI_ROOT_HID_STRING, + sizeof(PCI_ROOT_HID_STRING))) || + !(ACPI_STRNCMP(id, + PCI_EXPRESS_ROOT_HID_STRING, + sizeof(PCI_EXPRESS_ROOT_HID_STRING)))) { + return (TRUE); + } + + return (FALSE); +} + /******************************************************************************* * * FUNCTION: acpi_ev_is_pci_root_bridge @@ -344,10 +377,9 @@ acpi_ev_pci_config_region_setup(acpi_handle handle, static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) { acpi_status status; - struct acpica_device_id *hid; - struct acpica_device_id_list *cid; + struct acpica_device_id hid; + struct acpi_compatible_id_list *cid; u32 i; - u8 match; /* Get the _HID and check for a PCI Root Bridge */ @@ -356,10 +388,7 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) return (FALSE); } - match = acpi_ut_is_pci_root_bridge(hid->string); - ACPI_FREE(hid); - - if (match) { + if (acpi_ev_match_pci_root_bridge(hid.value)) { return (TRUE); } @@ -373,7 +402,7 @@ static u8 acpi_ev_is_pci_root_bridge(struct acpi_namespace_node *node) /* Check all _CIDs in the returned list */ for (i = 0; i < cid->count; i++) { - if (acpi_ut_is_pci_root_bridge(cid->ids[i].string)) { + if (acpi_ev_match_pci_root_bridge(cid->id[i].value)) { ACPI_FREE(cid); return (TRUE); } diff --git a/trunk/drivers/acpi/acpica/exconfig.c b/trunk/drivers/acpi/acpica/exconfig.c index 24afef81af39..277fd609611a 100644 --- a/trunk/drivers/acpi/acpica/exconfig.c +++ b/trunk/drivers/acpi/acpica/exconfig.c @@ -110,15 +110,8 @@ acpi_ex_add_table(u32 table_index, if (ACPI_FAILURE(status)) { acpi_ut_remove_reference(obj_desc); *ddb_handle = NULL; - return_ACPI_STATUS(status); } - /* Execute any module-level code that was found in the table */ - - acpi_ex_exit_interpreter(); - acpi_ns_exec_module_code_list(); - acpi_ex_enter_interpreter(); - return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/acpica/exdump.c b/trunk/drivers/acpi/acpica/exdump.c index de3446372ddc..ec524614e708 100644 --- a/trunk/drivers/acpi/acpica/exdump.c +++ b/trunk/drivers/acpi/acpica/exdump.c @@ -418,9 +418,9 @@ acpi_ex_dump_object(union acpi_operand_object *obj_desc, case ACPI_EXD_REFERENCE: acpi_ex_out_string("Class Name", - ACPI_CAST_PTR(char, - acpi_ut_get_reference_name - (obj_desc))); + (char *) + acpi_ut_get_reference_name + (obj_desc)); acpi_ex_dump_reference_obj(obj_desc); break; diff --git a/trunk/drivers/acpi/acpica/exfield.c b/trunk/drivers/acpi/acpica/exfield.c index 0b33d6c887b9..546dcdd86785 100644 --- a/trunk/drivers/acpi/acpica/exfield.c +++ b/trunk/drivers/acpi/acpica/exfield.c @@ -72,7 +72,6 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, union acpi_operand_object *buffer_desc; acpi_size length; void *buffer; - u32 function; ACPI_FUNCTION_TRACE_PTR(ex_read_data_from_field, obj_desc); @@ -98,27 +97,13 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, } } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS - || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_IPMI)) { + ACPI_ADR_SPACE_SMBUS)) { /* - * This is an SMBus or IPMI read. We must create a buffer to hold - * the data and then directly access the region handler. - * - * Note: Smbus protocol value is passed in upper 16-bits of Function + * This is an SMBus read. We must create a buffer to hold the data + * and directly access the region handler. */ - if (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS) { - length = ACPI_SMBUS_BUFFER_SIZE; - function = - ACPI_READ | (obj_desc->field.attribute << 16); - } else { /* IPMI */ - - length = ACPI_IPMI_BUFFER_SIZE; - function = ACPI_READ; - } - - buffer_desc = acpi_ut_create_buffer_object(length); + buffer_desc = + acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); if (!buffer_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -127,13 +112,16 @@ acpi_ex_read_data_from_field(struct acpi_walk_state *walk_state, acpi_ex_acquire_global_lock(obj_desc->common_field.field_flags); - /* Call the region handler for the read */ - + /* + * Perform the read. + * Note: Smbus protocol value is passed in upper 16-bits of Function + */ status = acpi_ex_access_region(obj_desc, 0, ACPI_CAST_PTR(acpi_integer, buffer_desc-> buffer.pointer), - function); + ACPI_READ | (obj_desc->field. + attribute << 16)); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); goto exit; } @@ -224,7 +212,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, u32 length; void *buffer; union acpi_operand_object *buffer_desc; - u32 function; ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); @@ -247,56 +234,39 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, } } else if ((obj_desc->common.type == ACPI_TYPE_LOCAL_REGION_FIELD) && (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS - || obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_IPMI)) { + ACPI_ADR_SPACE_SMBUS)) { /* - * This is an SMBus or IPMI write. We will bypass the entire field - * mechanism and handoff the buffer directly to the handler. For - * these address spaces, the buffer is bi-directional; on a write, - * return data is returned in the same buffer. - * - * Source must be a buffer of sufficient size: - * ACPI_SMBUS_BUFFER_SIZE or ACPI_IPMI_BUFFER_SIZE. + * This is an SMBus write. We will bypass the entire field mechanism + * and handoff the buffer directly to the handler. * - * Note: SMBus protocol type is passed in upper 16-bits of Function + * Source must be a buffer of sufficient size (ACPI_SMBUS_BUFFER_SIZE). */ if (source_desc->common.type != ACPI_TYPE_BUFFER) { ACPI_ERROR((AE_INFO, - "SMBus or IPMI write requires Buffer, found type %s", + "SMBus write requires Buffer, found type %s", acpi_ut_get_object_type_name(source_desc))); return_ACPI_STATUS(AE_AML_OPERAND_TYPE); } - if (obj_desc->field.region_obj->region.space_id == - ACPI_ADR_SPACE_SMBUS) { - length = ACPI_SMBUS_BUFFER_SIZE; - function = - ACPI_WRITE | (obj_desc->field.attribute << 16); - } else { /* IPMI */ - - length = ACPI_IPMI_BUFFER_SIZE; - function = ACPI_WRITE; - } - - if (source_desc->buffer.length < length) { + if (source_desc->buffer.length < ACPI_SMBUS_BUFFER_SIZE) { ACPI_ERROR((AE_INFO, - "SMBus or IPMI write requires Buffer of length %X, found length %X", - length, source_desc->buffer.length)); + "SMBus write requires Buffer of length %X, found length %X", + ACPI_SMBUS_BUFFER_SIZE, + source_desc->buffer.length)); return_ACPI_STATUS(AE_AML_BUFFER_LIMIT); } - /* Create the bi-directional buffer */ - - buffer_desc = acpi_ut_create_buffer_object(length); + buffer_desc = + acpi_ut_create_buffer_object(ACPI_SMBUS_BUFFER_SIZE); if (!buffer_desc) { return_ACPI_STATUS(AE_NO_MEMORY); } buffer = buffer_desc->buffer.pointer; - ACPI_MEMCPY(buffer, source_desc->buffer.pointer, length); + ACPI_MEMCPY(buffer, source_desc->buffer.pointer, + ACPI_SMBUS_BUFFER_SIZE); /* Lock entire transaction if requested */ @@ -305,10 +275,12 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, /* * Perform the write (returns status and perhaps data in the * same buffer) + * Note: SMBus protocol type is passed in upper 16-bits of Function. */ status = acpi_ex_access_region(obj_desc, 0, (acpi_integer *) buffer, - function); + ACPI_WRITE | (obj_desc->field. + attribute << 16)); acpi_ex_release_global_lock(obj_desc->common_field.field_flags); *result_desc = buffer_desc; diff --git a/trunk/drivers/acpi/acpica/exfldio.c b/trunk/drivers/acpi/acpica/exfldio.c index d7b3b418fb45..6687be167f5f 100644 --- a/trunk/drivers/acpi/acpica/exfldio.c +++ b/trunk/drivers/acpi/acpica/exfldio.c @@ -120,13 +120,12 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, } /* - * Exit now for SMBus or IPMI address space, it has a non-linear address space + * Exit now for SMBus address space, it has a non-linear address space * and the request cannot be directly validated */ - if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS || - rgn_desc->region.space_id == ACPI_ADR_SPACE_IPMI) { + if (rgn_desc->region.space_id == ACPI_ADR_SPACE_SMBUS) { - /* SMBus or IPMI has a non-linear address space */ + /* SMBus has a non-linear address space */ return_ACPI_STATUS(AE_OK); } diff --git a/trunk/drivers/acpi/acpica/exutils.c b/trunk/drivers/acpi/acpica/exutils.c index 7d41f99f7052..87730e944132 100644 --- a/trunk/drivers/acpi/acpica/exutils.c +++ b/trunk/drivers/acpi/acpica/exutils.c @@ -358,67 +358,50 @@ static u32 acpi_ex_digits_needed(acpi_integer value, u32 base) * * FUNCTION: acpi_ex_eisa_id_to_string * - * PARAMETERS: compressed_id - EISAID to be converted + * PARAMETERS: numeric_id - EISA ID to be converted * out_string - Where to put the converted string (8 bytes) * * RETURN: None * - * DESCRIPTION: Convert a numeric EISAID to string representation. Return - * buffer must be large enough to hold the string. The string - * returned is always exactly of length ACPI_EISAID_STRING_SIZE - * (includes null terminator). The EISAID is always 32 bits. + * DESCRIPTION: Convert a numeric EISA ID to string representation * ******************************************************************************/ -void acpi_ex_eisa_id_to_string(char *out_string, acpi_integer compressed_id) +void acpi_ex_eisa_id_to_string(u32 numeric_id, char *out_string) { - u32 swapped_id; + u32 eisa_id; ACPI_FUNCTION_ENTRY(); - /* The EISAID should be a 32-bit integer */ - - if (compressed_id > ACPI_UINT32_MAX) { - ACPI_WARNING((AE_INFO, - "Expected EISAID is larger than 32 bits: 0x%8.8X%8.8X, truncating", - ACPI_FORMAT_UINT64(compressed_id))); - } - /* Swap ID to big-endian to get contiguous bits */ - swapped_id = acpi_ut_dword_byte_swap((u32)compressed_id); + eisa_id = acpi_ut_dword_byte_swap(numeric_id); - /* First 3 bytes are uppercase letters. Next 4 bytes are hexadecimal */ - - out_string[0] = - (char)(0x40 + (((unsigned long)swapped_id >> 26) & 0x1F)); - out_string[1] = (char)(0x40 + ((swapped_id >> 21) & 0x1F)); - out_string[2] = (char)(0x40 + ((swapped_id >> 16) & 0x1F)); - out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 12); - out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 8); - out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 4); - out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer)swapped_id, 0); + out_string[0] = (char)('@' + (((unsigned long)eisa_id >> 26) & 0x1f)); + out_string[1] = (char)('@' + ((eisa_id >> 21) & 0x1f)); + out_string[2] = (char)('@' + ((eisa_id >> 16) & 0x1f)); + out_string[3] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 12); + out_string[4] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 8); + out_string[5] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 4); + out_string[6] = acpi_ut_hex_to_ascii_char((acpi_integer) eisa_id, 0); out_string[7] = 0; } /******************************************************************************* * - * FUNCTION: acpi_ex_integer_to_string + * FUNCTION: acpi_ex_unsigned_integer_to_string * - * PARAMETERS: out_string - Where to put the converted string. At least - * 21 bytes are needed to hold the largest - * possible 64-bit integer. - * Value - Value to be converted + * PARAMETERS: Value - Value to be converted + * out_string - Where to put the converted string (8 bytes) * * RETURN: None, string * - * DESCRIPTION: Convert a 64-bit integer to decimal string representation. - * Assumes string buffer is large enough to hold the string. The - * largest string is (ACPI_MAX64_DECIMAL_DIGITS + 1). + * DESCRIPTION: Convert a number to string representation. Assumes string + * buffer is large enough to hold the string. * ******************************************************************************/ -void acpi_ex_integer_to_string(char *out_string, acpi_integer value) +void acpi_ex_unsigned_integer_to_string(acpi_integer value, char *out_string) { u32 count; u32 digits_needed; diff --git a/trunk/drivers/acpi/acpica/hwgpe.c b/trunk/drivers/acpi/acpica/hwgpe.c index c28c41b3180b..d3b7e37c9eed 100644 --- a/trunk/drivers/acpi/acpica/hwgpe.c +++ b/trunk/drivers/acpi/acpica/hwgpe.c @@ -82,7 +82,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) /* Get current value of the enable register that contains this GPE */ - status = acpi_hw_read(&enable_mask, &gpe_register_info->enable_address); + status = acpi_read(&enable_mask, &gpe_register_info->enable_address); if (ACPI_FAILURE(status)) { return (status); } @@ -95,7 +95,7 @@ acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info) /* Write the updated enable mask */ - status = acpi_hw_write(enable_mask, &gpe_register_info->enable_address); + status = acpi_write(enable_mask, &gpe_register_info->enable_address); return (status); } @@ -130,8 +130,8 @@ acpi_hw_write_gpe_enable_reg(struct acpi_gpe_event_info * gpe_event_info) /* Write the entire GPE (runtime) enable register */ - status = acpi_hw_write(gpe_register_info->enable_for_run, - &gpe_register_info->enable_address); + status = acpi_write(gpe_register_info->enable_for_run, + &gpe_register_info->enable_address); return (status); } @@ -163,8 +163,8 @@ acpi_status acpi_hw_clear_gpe(struct acpi_gpe_event_info * gpe_event_info) * Write a one to the appropriate bit in the status register to * clear this GPE. */ - status = acpi_hw_write(register_bit, - &gpe_event_info->register_info->status_address); + status = acpi_write(register_bit, + &gpe_event_info->register_info->status_address); return (status); } @@ -222,7 +222,7 @@ acpi_hw_get_gpe_status(struct acpi_gpe_event_info * gpe_event_info, /* GPE currently active (status bit == 1)? */ - status = acpi_hw_read(&in_byte, &gpe_register_info->status_address); + status = acpi_read(&in_byte, &gpe_register_info->status_address); if (ACPI_FAILURE(status)) { goto unlock_and_exit; } @@ -266,8 +266,8 @@ acpi_hw_disable_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Disable all GPEs in this register */ status = - acpi_hw_write(0x00, - &gpe_block->register_info[i].enable_address); + acpi_write(0x00, + &gpe_block->register_info[i].enable_address); if (ACPI_FAILURE(status)) { return (status); } @@ -303,8 +303,8 @@ acpi_hw_clear_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Clear status on all GPEs in this register */ status = - acpi_hw_write(0xFF, - &gpe_block->register_info[i].status_address); + acpi_write(0xFF, + &gpe_block->register_info[i].status_address); if (ACPI_FAILURE(status)) { return (status); } @@ -345,9 +345,9 @@ acpi_hw_enable_runtime_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Enable all "runtime" GPEs in this register */ - status = - acpi_hw_write(gpe_block->register_info[i].enable_for_run, - &gpe_block->register_info[i].enable_address); + status = acpi_write(gpe_block->register_info[i].enable_for_run, + &gpe_block->register_info[i]. + enable_address); if (ACPI_FAILURE(status)) { return (status); } @@ -387,9 +387,9 @@ acpi_hw_enable_wakeup_gpe_block(struct acpi_gpe_xrupt_info *gpe_xrupt_info, /* Enable all "wake" GPEs in this register */ - status = - acpi_hw_write(gpe_block->register_info[i].enable_for_wake, - &gpe_block->register_info[i].enable_address); + status = acpi_write(gpe_block->register_info[i].enable_for_wake, + &gpe_block->register_info[i]. + enable_address); if (ACPI_FAILURE(status)) { return (status); } diff --git a/trunk/drivers/acpi/acpica/hwregs.c b/trunk/drivers/acpi/acpica/hwregs.c index 15c9ed2be853..23d5505cb1f7 100644 --- a/trunk/drivers/acpi/acpica/hwregs.c +++ b/trunk/drivers/acpi/acpica/hwregs.c @@ -62,184 +62,6 @@ acpi_hw_write_multiple(u32 value, struct acpi_generic_address *register_a, struct acpi_generic_address *register_b); -/****************************************************************************** - * - * FUNCTION: acpi_hw_validate_register - * - * PARAMETERS: Reg - GAS register structure - * max_bit_width - Max bit_width supported (32 or 64) - * Address - Pointer to where the gas->address - * is returned - * - * RETURN: Status - * - * DESCRIPTION: Validate the contents of a GAS register. Checks the GAS - * pointer, Address, space_id, bit_width, and bit_offset. - * - ******************************************************************************/ - -acpi_status -acpi_hw_validate_register(struct acpi_generic_address *reg, - u8 max_bit_width, u64 *address) -{ - - /* Must have a valid pointer to a GAS structure */ - - if (!reg) { - return (AE_BAD_PARAMETER); - } - - /* - * Copy the target address. This handles possible alignment issues. - * Address must not be null. A null address also indicates an optional - * ACPI register that is not supported, so no error message. - */ - ACPI_MOVE_64_TO_64(address, ®->address); - if (!(*address)) { - return (AE_BAD_ADDRESS); - } - - /* Validate the space_iD */ - - if ((reg->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && - (reg->space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { - ACPI_ERROR((AE_INFO, - "Unsupported address space: 0x%X", reg->space_id)); - return (AE_SUPPORT); - } - - /* Validate the bit_width */ - - if ((reg->bit_width != 8) && - (reg->bit_width != 16) && - (reg->bit_width != 32) && (reg->bit_width != max_bit_width)) { - ACPI_ERROR((AE_INFO, - "Unsupported register bit width: 0x%X", - reg->bit_width)); - return (AE_SUPPORT); - } - - /* Validate the bit_offset. Just a warning for now. */ - - if (reg->bit_offset != 0) { - ACPI_WARNING((AE_INFO, - "Unsupported register bit offset: 0x%X", - reg->bit_offset)); - } - - return (AE_OK); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_read - * - * PARAMETERS: Value - Where the value is returned - * Reg - GAS register structure - * - * RETURN: Status - * - * DESCRIPTION: Read from either memory or IO space. This is a 32-bit max - * version of acpi_read, used internally since the overhead of - * 64-bit values is not needed. - * - * LIMITATIONS: - * bit_width must be exactly 8, 16, or 32. - * space_iD must be system_memory or system_iO. - * bit_offset and access_width are currently ignored, as there has - * not been a need to implement these. - * - ******************************************************************************/ - -acpi_status acpi_hw_read(u32 *value, struct acpi_generic_address *reg) -{ - u64 address; - acpi_status status; - - ACPI_FUNCTION_NAME(hw_read); - - /* Validate contents of the GAS register */ - - status = acpi_hw_validate_register(reg, 32, &address); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* Initialize entire 32-bit return value to zero */ - - *value = 0; - - /* - * Two address spaces supported: Memory or IO. PCI_Config is - * not supported here because the GAS structure is insufficient - */ - if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - status = acpi_os_read_memory((acpi_physical_address) - address, value, reg->bit_width); - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ - - status = acpi_hw_read_port((acpi_io_address) - address, value, reg->bit_width); - } - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", - *value, reg->bit_width, ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); - - return (status); -} - -/****************************************************************************** - * - * FUNCTION: acpi_hw_write - * - * PARAMETERS: Value - Value to be written - * Reg - GAS register structure - * - * RETURN: Status - * - * DESCRIPTION: Write to either memory or IO space. This is a 32-bit max - * version of acpi_write, used internally since the overhead of - * 64-bit values is not needed. - * - ******************************************************************************/ - -acpi_status acpi_hw_write(u32 value, struct acpi_generic_address *reg) -{ - u64 address; - acpi_status status; - - ACPI_FUNCTION_NAME(hw_write); - - /* Validate contents of the GAS register */ - - status = acpi_hw_validate_register(reg, 32, &address); - if (ACPI_FAILURE(status)) { - return (status); - } - - /* - * Two address spaces supported: Memory or IO. PCI_Config is - * not supported here because the GAS structure is insufficient - */ - if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - status = acpi_os_write_memory((acpi_physical_address) - address, value, reg->bit_width); - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ - - status = acpi_hw_write_port((acpi_io_address) - address, value, reg->bit_width); - } - - ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", - value, reg->bit_width, ACPI_FORMAT_UINT64(address), - acpi_ut_get_region_name(reg->space_id))); - - return (status); -} - /******************************************************************************* * * FUNCTION: acpi_hw_clear_acpi_status @@ -330,16 +152,15 @@ acpi_status acpi_hw_write_pm1_control(u32 pm1a_control, u32 pm1b_control) ACPI_FUNCTION_TRACE(hw_write_pm1_control); - status = - acpi_hw_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); + status = acpi_write(pm1a_control, &acpi_gbl_FADT.xpm1a_control_block); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } if (acpi_gbl_FADT.xpm1b_control_block.address) { status = - acpi_hw_write(pm1b_control, - &acpi_gbl_FADT.xpm1b_control_block); + acpi_write(pm1b_control, + &acpi_gbl_FADT.xpm1b_control_block); } return_ACPI_STATUS(status); } @@ -397,13 +218,12 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) case ACPI_REGISTER_PM2_CONTROL: /* 8-bit access */ - status = - acpi_hw_read(&value, &acpi_gbl_FADT.xpm2_control_block); + status = acpi_read(&value, &acpi_gbl_FADT.xpm2_control_block); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_hw_read(&value, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_read(&value, &acpi_gbl_FADT.xpm_timer_block); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ @@ -520,8 +340,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) * as per the ACPI spec. */ status = - acpi_hw_read(&read_value, - &acpi_gbl_FADT.xpm2_control_block); + acpi_read(&read_value, &acpi_gbl_FADT.xpm2_control_block); if (ACPI_FAILURE(status)) { goto exit; } @@ -531,13 +350,12 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) ACPI_INSERT_BITS(value, ACPI_PM2_CONTROL_PRESERVED_BITS, read_value); - status = - acpi_hw_write(value, &acpi_gbl_FADT.xpm2_control_block); + status = acpi_write(value, &acpi_gbl_FADT.xpm2_control_block); break; case ACPI_REGISTER_PM_TIMER: /* 32-bit access */ - status = acpi_hw_write(value, &acpi_gbl_FADT.xpm_timer_block); + status = acpi_write(value, &acpi_gbl_FADT.xpm_timer_block); break; case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ @@ -583,7 +401,7 @@ acpi_hw_read_multiple(u32 *value, /* The first register is always required */ - status = acpi_hw_read(&value_a, register_a); + status = acpi_read(&value_a, register_a); if (ACPI_FAILURE(status)) { return (status); } @@ -591,7 +409,7 @@ acpi_hw_read_multiple(u32 *value, /* Second register is optional */ if (register_b->address) { - status = acpi_hw_read(&value_b, register_b); + status = acpi_read(&value_b, register_b); if (ACPI_FAILURE(status)) { return (status); } @@ -634,7 +452,7 @@ acpi_hw_write_multiple(u32 value, /* The first register is always required */ - status = acpi_hw_write(value, register_a); + status = acpi_write(value, register_a); if (ACPI_FAILURE(status)) { return (status); } @@ -652,7 +470,7 @@ acpi_hw_write_multiple(u32 value, * and writes have no side effects" */ if (register_b->address) { - status = acpi_hw_write(value, register_b); + status = acpi_write(value, register_b); } return (status); diff --git a/trunk/drivers/acpi/acpica/hwtimer.c b/trunk/drivers/acpi/acpica/hwtimer.c index 6b282e85d039..b7f522c8f023 100644 --- a/trunk/drivers/acpi/acpica/hwtimer.c +++ b/trunk/drivers/acpi/acpica/hwtimer.c @@ -100,7 +100,7 @@ acpi_status acpi_get_timer(u32 * ticks) } status = - acpi_hw_read(ticks, &acpi_gbl_FADT.xpm_timer_block); + acpi_hw_low_level_read(32, ticks, &acpi_gbl_FADT.xpm_timer_block); return_ACPI_STATUS(status); } diff --git a/trunk/drivers/acpi/acpica/hwxface.c b/trunk/drivers/acpi/acpica/hwxface.c index 647c7b6e6756..9829979f2bdd 100644 --- a/trunk/drivers/acpi/acpica/hwxface.c +++ b/trunk/drivers/acpi/acpica/hwxface.c @@ -78,22 +78,9 @@ acpi_status acpi_reset(void) return_ACPI_STATUS(AE_NOT_EXIST); } - if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) { - /* - * For I/O space, write directly to the OSL. This bypasses the port - * validation mechanism, which may block a valid write to the reset - * register. - */ - status = - acpi_os_write_port((acpi_io_address) reset_reg->address, - acpi_gbl_FADT.reset_value, - reset_reg->bit_width); - } else { - /* Write the reset value to the reset register */ - - status = acpi_hw_write(acpi_gbl_FADT.reset_value, reset_reg); - } + /* Write the reset value to the reset register */ + status = acpi_write(acpi_gbl_FADT.reset_value, reset_reg); return_ACPI_STATUS(status); } @@ -110,92 +97,67 @@ ACPI_EXPORT_SYMBOL(acpi_reset) * * DESCRIPTION: Read from either memory or IO space. * - * LIMITATIONS: - * bit_width must be exactly 8, 16, 32, or 64. - * space_iD must be system_memory or system_iO. - * bit_offset and access_width are currently ignored, as there has - * not been a need to implement these. - * ******************************************************************************/ -acpi_status acpi_read(u64 *return_value, struct acpi_generic_address *reg) +acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) { - u32 value; u32 width; u64 address; acpi_status status; ACPI_FUNCTION_NAME(acpi_read); - if (!return_value) { + /* + * Must have a valid pointer to a GAS structure, and a non-zero address + * within. + */ + if (!reg) { return (AE_BAD_PARAMETER); } - /* Validate contents of the GAS register. Allow 64-bit transfers */ + /* Get a local copy of the address. Handles possible alignment issues */ - status = acpi_hw_validate_register(reg, 64, &address); - if (ACPI_FAILURE(status)) { - return (status); + ACPI_MOVE_64_TO_64(&address, ®->address); + if (!address) { + return (AE_BAD_ADDRESS); } + /* Supported widths are 8/16/32 */ + width = reg->bit_width; - if (width == 64) { - width = 32; /* Break into two 32-bit transfers */ + if ((width != 8) && (width != 16) && (width != 32)) { + return (AE_SUPPORT); } - /* Initialize entire 64-bit return value to zero */ + /* Initialize entire 32-bit return value to zero */ - *return_value = 0; - value = 0; + *value = 0; /* * Two address spaces supported: Memory or IO. PCI_Config is * not supported here because the GAS structure is insufficient */ - if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - status = acpi_os_read_memory((acpi_physical_address) - address, &value, width); - if (ACPI_FAILURE(status)) { - return (status); - } - *return_value = value; - - if (reg->bit_width == 64) { - - /* Read the top 32 bits */ + switch (reg->space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: - status = acpi_os_read_memory((acpi_physical_address) - (address + 4), &value, 32); - if (ACPI_FAILURE(status)) { - return (status); - } - *return_value |= ((u64)value << 32); - } - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + status = acpi_os_read_memory((acpi_physical_address) address, + value, width); + break; - status = acpi_hw_read_port((acpi_io_address) - address, &value, width); - if (ACPI_FAILURE(status)) { - return (status); - } - *return_value = value; + case ACPI_ADR_SPACE_SYSTEM_IO: - if (reg->bit_width == 64) { - - /* Read the top 32 bits */ + status = + acpi_hw_read_port((acpi_io_address) address, value, width); + break; - status = acpi_hw_read_port((acpi_io_address) - (address + 4), &value, 32); - if (ACPI_FAILURE(status)) { - return (status); - } - *return_value |= ((u64)value << 32); - } + default: + ACPI_ERROR((AE_INFO, + "Unsupported address space: %X", reg->space_id)); + return (AE_BAD_PARAMETER); } ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Read: %8.8X%8.8X width %2d from %8.8X%8.8X (%s)\n", - ACPI_FORMAT_UINT64(*return_value), reg->bit_width, - ACPI_FORMAT_UINT64(address), + "Read: %8.8X width %2d from %8.8X%8.8X (%s)\n", + *value, width, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); @@ -207,7 +169,7 @@ ACPI_EXPORT_SYMBOL(acpi_read) * * FUNCTION: acpi_write * - * PARAMETERS: Value - Value to be written + * PARAMETERS: Value - To be written * Reg - GAS register structure * * RETURN: Status @@ -215,7 +177,7 @@ ACPI_EXPORT_SYMBOL(acpi_read) * DESCRIPTION: Write to either memory or IO space. * ******************************************************************************/ -acpi_status acpi_write(u64 value, struct acpi_generic_address *reg) +acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) { u32 width; u64 address; @@ -223,61 +185,54 @@ acpi_status acpi_write(u64 value, struct acpi_generic_address *reg) ACPI_FUNCTION_NAME(acpi_write); - /* Validate contents of the GAS register. Allow 64-bit transfers */ + /* + * Must have a valid pointer to a GAS structure, and a non-zero address + * within. + */ + if (!reg) { + return (AE_BAD_PARAMETER); + } - status = acpi_hw_validate_register(reg, 64, &address); - if (ACPI_FAILURE(status)) { - return (status); + /* Get a local copy of the address. Handles possible alignment issues */ + + ACPI_MOVE_64_TO_64(&address, ®->address); + if (!address) { + return (AE_BAD_ADDRESS); } + /* Supported widths are 8/16/32 */ + width = reg->bit_width; - if (width == 64) { - width = 32; /* Break into two 32-bit transfers */ + if ((width != 8) && (width != 16) && (width != 32)) { + return (AE_SUPPORT); } /* - * Two address spaces supported: Memory or IO. PCI_Config is - * not supported here because the GAS structure is insufficient + * Two address spaces supported: Memory or IO. + * PCI_Config is not supported here because the GAS struct is insufficient */ - if (reg->space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { - status = acpi_os_write_memory((acpi_physical_address) - address, ACPI_LODWORD(value), - width); - if (ACPI_FAILURE(status)) { - return (status); - } + switch (reg->space_id) { + case ACPI_ADR_SPACE_SYSTEM_MEMORY: - if (reg->bit_width == 64) { - status = acpi_os_write_memory((acpi_physical_address) - (address + 4), - ACPI_HIDWORD(value), 32); - if (ACPI_FAILURE(status)) { - return (status); - } - } - } else { /* ACPI_ADR_SPACE_SYSTEM_IO, validated earlier */ + status = acpi_os_write_memory((acpi_physical_address) address, + value, width); + break; + + case ACPI_ADR_SPACE_SYSTEM_IO: - status = acpi_hw_write_port((acpi_io_address) - address, ACPI_LODWORD(value), + status = acpi_hw_write_port((acpi_io_address) address, value, width); - if (ACPI_FAILURE(status)) { - return (status); - } + break; - if (reg->bit_width == 64) { - status = acpi_hw_write_port((acpi_io_address) - (address + 4), - ACPI_HIDWORD(value), 32); - if (ACPI_FAILURE(status)) { - return (status); - } - } + default: + ACPI_ERROR((AE_INFO, + "Unsupported address space: %X", reg->space_id)); + return (AE_BAD_PARAMETER); } ACPI_DEBUG_PRINT((ACPI_DB_IO, - "Wrote: %8.8X%8.8X width %2d to %8.8X%8.8X (%s)\n", - ACPI_FORMAT_UINT64(value), reg->bit_width, - ACPI_FORMAT_UINT64(address), + "Wrote: %8.8X width %2d to %8.8X%8.8X (%s)\n", + value, width, ACPI_FORMAT_UINT64(address), acpi_ut_get_region_name(reg->space_id))); return (status); diff --git a/trunk/drivers/acpi/acpica/nsalloc.c b/trunk/drivers/acpi/acpica/nsalloc.c index 8a58a1b85aa0..efc971ab7d65 100644 --- a/trunk/drivers/acpi/acpica/nsalloc.c +++ b/trunk/drivers/acpi/acpica/nsalloc.c @@ -96,68 +96,17 @@ struct acpi_namespace_node *acpi_ns_create_node(u32 name) * * RETURN: None * - * DESCRIPTION: Delete a namespace node. All node deletions must come through - * here. Detaches any attached objects, including any attached - * data. If a handler is associated with attached data, it is - * invoked before the node is deleted. + * DESCRIPTION: Delete a namespace node * ******************************************************************************/ void acpi_ns_delete_node(struct acpi_namespace_node *node) -{ - union acpi_operand_object *obj_desc; - - ACPI_FUNCTION_NAME(ns_delete_node); - - /* Detach an object if there is one */ - - acpi_ns_detach_object(node); - - /* - * Delete an attached data object if present (an object that was created - * and attached via acpi_attach_data). Note: After any normal object is - * detached above, the only possible remaining object is a data object. - */ - obj_desc = node->object; - if (obj_desc && (obj_desc->common.type == ACPI_TYPE_LOCAL_DATA)) { - - /* Invoke the attached data deletion handler if present */ - - if (obj_desc->data.handler) { - obj_desc->data.handler(node, obj_desc->data.pointer); - } - - acpi_ut_remove_reference(obj_desc); - } - - /* Now we can delete the node */ - - (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); - - ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); - ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "Node %p, Remaining %X\n", - node, acpi_gbl_current_node_count)); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_remove_node - * - * PARAMETERS: Node - Node to be removed/deleted - * - * RETURN: None - * - * DESCRIPTION: Remove (unlink) and delete a namespace node - * - ******************************************************************************/ - -void acpi_ns_remove_node(struct acpi_namespace_node *node) { struct acpi_namespace_node *parent_node; struct acpi_namespace_node *prev_node; struct acpi_namespace_node *next_node; - ACPI_FUNCTION_TRACE_PTR(ns_remove_node, node); + ACPI_FUNCTION_TRACE_PTR(ns_delete_node, node); parent_node = acpi_ns_get_parent_node(node); @@ -193,9 +142,12 @@ void acpi_ns_remove_node(struct acpi_namespace_node *node) } } - /* Delete the node and any attached objects */ + ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); + + /* Detach an object if there is one, then delete the node */ - acpi_ns_delete_node(node); + acpi_ns_detach_object(node); + (void)acpi_os_release_object(acpi_gbl_namespace_cache, node); return_VOID; } @@ -321,11 +273,25 @@ void acpi_ns_delete_children(struct acpi_namespace_node *parent_node) parent_node, child_node)); } - /* - * Delete this child node and move on to the next child in the list. - * No need to unlink the node since we are deleting the entire branch. - */ - acpi_ns_delete_node(child_node); + /* Now we can free this child object */ + + ACPI_MEM_TRACKING(acpi_gbl_ns_node_list->total_freed++); + + ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, + "Object %p, Remaining %X\n", child_node, + acpi_gbl_current_node_count)); + + /* Detach an object if there is one, then free the child node */ + + acpi_ns_detach_object(child_node); + + /* Now we can delete the node */ + + (void)acpi_os_release_object(acpi_gbl_namespace_cache, + child_node); + + /* And move on to the next child in the list */ + child_node = next_node; } while (!(flags & ANOBJ_END_OF_PEER_LIST)); @@ -467,7 +433,7 @@ void acpi_ns_delete_namespace_by_owner(acpi_owner_id owner_id) if (deletion_node) { acpi_ns_delete_children(deletion_node); - acpi_ns_remove_node(deletion_node); + acpi_ns_delete_node(deletion_node); deletion_node = NULL; } diff --git a/trunk/drivers/acpi/acpica/nsdumpdv.c b/trunk/drivers/acpi/acpica/nsdumpdv.c index 0fe87f1aef16..41994fe7fbb8 100644 --- a/trunk/drivers/acpi/acpica/nsdumpdv.c +++ b/trunk/drivers/acpi/acpica/nsdumpdv.c @@ -70,6 +70,7 @@ static acpi_status acpi_ns_dump_one_device(acpi_handle obj_handle, u32 level, void *context, void **return_value) { + struct acpi_buffer buffer; struct acpi_device_info *info; acpi_status status; u32 i; @@ -79,15 +80,17 @@ acpi_ns_dump_one_device(acpi_handle obj_handle, status = acpi_ns_dump_one_object(obj_handle, level, context, return_value); - status = acpi_get_object_info(obj_handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(obj_handle, &buffer); if (ACPI_SUCCESS(status)) { + info = buffer.pointer; for (i = 0; i < level; i++) { ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " ")); } ACPI_DEBUG_PRINT_RAW((ACPI_DB_TABLES, " HID: %s, ADR: %8.8X%8.8X, Status: %X\n", - info->hardware_id.string, + info->hardware_id.value, ACPI_FORMAT_UINT64(info->address), info->current_status)); ACPI_FREE(info); diff --git a/trunk/drivers/acpi/acpica/nseval.c b/trunk/drivers/acpi/acpica/nseval.c index 846d1132feb1..8e7dec1176c9 100644 --- a/trunk/drivers/acpi/acpica/nseval.c +++ b/trunk/drivers/acpi/acpica/nseval.c @@ -50,11 +50,6 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nseval") -/* Local prototypes */ -static void -acpi_ns_exec_module_code(union acpi_operand_object *method_obj, - struct acpi_evaluate_info *info); - /******************************************************************************* * * FUNCTION: acpi_ns_evaluate @@ -81,7 +76,6 @@ acpi_ns_exec_module_code(union acpi_operand_object *method_obj, * MUTEX: Locks interpreter * ******************************************************************************/ - acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) { acpi_status status; @@ -282,134 +276,3 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) */ return_ACPI_STATUS(status); } - -/******************************************************************************* - * - * FUNCTION: acpi_ns_exec_module_code_list - * - * PARAMETERS: None - * - * RETURN: None. Exceptions during method execution are ignored, since - * we cannot abort a table load. - * - * DESCRIPTION: Execute all elements of the global module-level code list. - * Each element is executed as a single control method. - * - ******************************************************************************/ - -void acpi_ns_exec_module_code_list(void) -{ - union acpi_operand_object *prev; - union acpi_operand_object *next; - struct acpi_evaluate_info *info; - u32 method_count = 0; - - ACPI_FUNCTION_TRACE(ns_exec_module_code_list); - - /* Exit now if the list is empty */ - - next = acpi_gbl_module_code_list; - if (!next) { - return_VOID; - } - - /* Allocate the evaluation information block */ - - info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info)); - if (!info) { - return_VOID; - } - - /* Walk the list, executing each "method" */ - - while (next) { - prev = next; - next = next->method.mutex; - - /* Clear the link field and execute the method */ - - prev->method.mutex = NULL; - acpi_ns_exec_module_code(prev, info); - method_count++; - - /* Delete the (temporary) method object */ - - acpi_ut_remove_reference(prev); - } - - ACPI_INFO((AE_INFO, - "Executed %u blocks of module-level executable AML code", - method_count)); - - ACPI_FREE(info); - acpi_gbl_module_code_list = NULL; - return_VOID; -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_exec_module_code - * - * PARAMETERS: method_obj - Object container for the module-level code - * Info - Info block for method evaluation - * - * RETURN: None. Exceptions during method execution are ignored, since - * we cannot abort a table load. - * - * DESCRIPTION: Execute a control method containing a block of module-level - * executable AML code. The control method is temporarily - * installed to the root node, then evaluated. - * - ******************************************************************************/ - -static void -acpi_ns_exec_module_code(union acpi_operand_object *method_obj, - struct acpi_evaluate_info *info) -{ - union acpi_operand_object *root_obj; - acpi_status status; - - ACPI_FUNCTION_TRACE(ns_exec_module_code); - - /* Initialize the evaluation information block */ - - ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info)); - info->prefix_node = acpi_gbl_root_node; - - /* - * Get the currently attached root object. Add a reference, because the - * ref count will be decreased when the method object is installed to - * the root node. - */ - root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node); - acpi_ut_add_reference(root_obj); - - /* Install the method (module-level code) in the root node */ - - status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj, - ACPI_TYPE_METHOD); - if (ACPI_FAILURE(status)) { - goto exit; - } - - /* Execute the root node as a control method */ - - status = acpi_ns_evaluate(info); - - ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n", - method_obj->method.aml_start)); - - /* Detach the temporary method object */ - - acpi_ns_detach_object(acpi_gbl_root_node); - - /* Restore the original root object */ - - status = - acpi_ns_attach_object(acpi_gbl_root_node, root_obj, - ACPI_TYPE_DEVICE); - - exit: - acpi_ut_remove_reference(root_obj); - return_VOID; -} diff --git a/trunk/drivers/acpi/acpica/nsinit.c b/trunk/drivers/acpi/acpica/nsinit.c index 1d5b360eb25b..2adfcf329e15 100644 --- a/trunk/drivers/acpi/acpica/nsinit.c +++ b/trunk/drivers/acpi/acpica/nsinit.c @@ -170,21 +170,6 @@ acpi_status acpi_ns_initialize_devices(void) goto error_exit; } - /* - * Execute the "global" _INI method that may appear at the root. This - * support is provided for Windows compatibility (Vista+) and is not - * part of the ACPI specification. - */ - info.evaluate_info->prefix_node = acpi_gbl_root_node; - info.evaluate_info->pathname = METHOD_NAME__INI; - info.evaluate_info->parameters = NULL; - info.evaluate_info->flags = ACPI_IGNORE_RETURN_VALUE; - - status = acpi_ns_evaluate(info.evaluate_info); - if (ACPI_SUCCESS(status)) { - info.num_INI++; - } - /* Walk namespace to execute all _INIs on present devices */ status = acpi_ns_walk_namespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, diff --git a/trunk/drivers/acpi/acpica/nsload.c b/trunk/drivers/acpi/acpica/nsload.c index a7234e60e985..dcd7a6adbbbc 100644 --- a/trunk/drivers/acpi/acpica/nsload.c +++ b/trunk/drivers/acpi/acpica/nsload.c @@ -270,7 +270,8 @@ static acpi_status acpi_ns_delete_subtree(acpi_handle start_handle) /* Now delete the starting object, and we are done */ - acpi_ns_remove_node(child_handle); + acpi_ns_delete_node(child_handle); + return_ACPI_STATUS(AE_OK); } diff --git a/trunk/drivers/acpi/acpica/nspredef.c b/trunk/drivers/acpi/acpica/nspredef.c index f8427afeebdf..7f8e066b12a3 100644 --- a/trunk/drivers/acpi/acpica/nspredef.c +++ b/trunk/drivers/acpi/acpica/nspredef.c @@ -42,8 +42,6 @@ * POSSIBILITY OF SUCH DAMAGES. */ -#define ACPI_CREATE_PREDEFINED_TABLE - #include #include "accommon.h" #include "acnamesp.h" @@ -74,31 +72,30 @@ ACPI_MODULE_NAME("nspredef") ******************************************************************************/ /* Local prototypes */ static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr); - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count); +acpi_ns_check_package(char *pathname, + union acpi_operand_object **return_object_ptr, + const union acpi_predefined_info *predefined); static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, +acpi_ns_check_package_elements(char *pathname, union acpi_operand_object **elements, u8 type1, u32 count1, u8 type2, u32 count2, u32 start_index); static acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, +acpi_ns_check_object_type(char *pathname, union acpi_operand_object **return_object_ptr, u32 expected_btypes, u32 package_index); static acpi_status -acpi_ns_check_reference(struct acpi_predefined_data *data, +acpi_ns_check_reference(char *pathname, union acpi_operand_object *return_object); -static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes); +static acpi_status +acpi_ns_repair_object(u32 expected_btypes, + u32 package_index, + union acpi_operand_object **return_object_ptr); /* * Names for the types that can be returned by the predefined objects. @@ -112,13 +109,13 @@ static const char *acpi_rtype_names[] = { "/Reference", }; +#define ACPI_NOT_PACKAGE ACPI_UINT32_MAX + /******************************************************************************* * * FUNCTION: acpi_ns_check_predefined_names * * PARAMETERS: Node - Namespace node for the method/object - * user_param_count - Number of parameters actually passed - * return_status - Status from the object evaluation * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * @@ -138,13 +135,12 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, acpi_status status = AE_OK; const union acpi_predefined_info *predefined; char *pathname; - struct acpi_predefined_data *data; /* Match the name for this method/object against the predefined list */ predefined = acpi_ns_check_for_predefined_name(node); - /* Get the full pathname to the object, for use in warning messages */ + /* Get the full pathname to the object, for use in error messages */ pathname = acpi_ns_get_external_pathname(node); if (!pathname) { @@ -162,17 +158,28 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, /* If not a predefined name, we cannot validate the return object */ if (!predefined) { - goto cleanup; + goto exit; + } + + /* If the method failed, we cannot validate the return object */ + + if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { + goto exit; } /* - * If the method failed or did not actually return an object, we cannot - * validate the return object + * Only validate the return value on the first successful evaluation of + * the method. This ensures that any warnings will only be emitted during + * the very first evaluation of the method/object. */ - if ((return_status != AE_OK) && (return_status != AE_CTRL_RETURN_VALUE)) { - goto cleanup; + if (node->flags & ANOBJ_EVALUATED) { + goto exit; } + /* Mark the node as having been successfully evaluated */ + + node->flags |= ANOBJ_EVALUATED; + /* * If there is no return value, check if we require a return value for * this predefined name. Either one return value is expected, or none, @@ -183,67 +190,46 @@ acpi_ns_check_predefined_names(struct acpi_namespace_node *node, if (!return_object) { if ((predefined->info.expected_btypes) && (!(predefined->info.expected_btypes & ACPI_RTYPE_NONE))) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Missing expected return value")); + ACPI_ERROR((AE_INFO, + "%s: Missing expected return value", + pathname)); status = AE_AML_NO_RETURN_VALUE; } - goto cleanup; + goto exit; } /* - * 1) We have a return value, but if one wasn't expected, just exit, this is - * not a problem. For example, if the "Implicit Return" feature is - * enabled, methods will always return a value. + * We have a return value, but if one wasn't expected, just exit, this is + * not a problem * - * 2) If the return value can be of any type, then we cannot perform any - * validation, exit. + * For example, if the "Implicit Return" feature is enabled, methods will + * always return a value */ - if ((!predefined->info.expected_btypes) || - (predefined->info.expected_btypes == ACPI_RTYPE_ALL)) { - goto cleanup; + if (!predefined->info.expected_btypes) { + goto exit; } - /* Create the parameter data block for object validation */ - - data = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_predefined_data)); - if (!data) { - goto cleanup; - } - data->predefined = predefined; - data->node_flags = node->flags; - data->pathname = pathname; - /* * Check that the type of the return object is what is expected for * this predefined name */ - status = acpi_ns_check_object_type(data, return_object_ptr, + status = acpi_ns_check_object_type(pathname, return_object_ptr, predefined->info.expected_btypes, - ACPI_NOT_PACKAGE_ELEMENT); + ACPI_NOT_PACKAGE); if (ACPI_FAILURE(status)) { - goto check_validation_status; + goto exit; } /* For returned Package objects, check the type of all sub-objects */ if (return_object->common.type == ACPI_TYPE_PACKAGE) { - status = acpi_ns_check_package(data, return_object_ptr); - } - -check_validation_status: - /* - * If the object validation failed or if we successfully repaired one - * or more objects, mark the parent node to suppress further warning - * messages during the next evaluation of the same method/object. - */ - if (ACPI_FAILURE(status) || (data->flags & ACPI_OBJECT_REPAIRED)) { - node->flags |= ANOBJ_EVALUATED; + status = + acpi_ns_check_package(pathname, return_object_ptr, + predefined); } - ACPI_FREE(data); -cleanup: + exit: ACPI_FREE(pathname); return (status); } @@ -282,58 +268,64 @@ acpi_ns_check_parameter_count(char *pathname, param_count = node->object->method.param_count; } + /* Argument count check for non-predefined methods/objects */ + if (!predefined) { /* - * Check the parameter count for non-predefined methods/objects. - * * Warning if too few or too many arguments have been passed by the * caller. An incorrect number of arguments may not cause the method * to fail. However, the method will fail if there are too few * arguments and the method attempts to use one of the missing ones. */ if (user_param_count < param_count) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Insufficient arguments - needs %u, found %u", - param_count, user_param_count)); + ACPI_WARNING((AE_INFO, + "%s: Insufficient arguments - needs %d, found %d", + pathname, param_count, user_param_count)); } else if (user_param_count > param_count) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Excess arguments - needs %u, found %u", - param_count, user_param_count)); + ACPI_WARNING((AE_INFO, + "%s: Excess arguments - needs %d, found %d", + pathname, param_count, user_param_count)); } return; } - /* - * Validate the user-supplied parameter count. - * Allow two different legal argument counts (_SCP, etc.) - */ + /* Allow two different legal argument counts (_SCP, etc.) */ + required_params_current = predefined->info.param_count & 0x0F; required_params_old = predefined->info.param_count >> 4; if (user_param_count != ACPI_UINT32_MAX) { + + /* Validate the user-supplied parameter count */ + if ((user_param_count != required_params_current) && (user_param_count != required_params_old)) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, - ACPI_WARN_ALWAYS, - "Parameter count mismatch - " - "caller passed %u, ACPI requires %u", - user_param_count, - required_params_current)); + ACPI_WARNING((AE_INFO, + "%s: Parameter count mismatch - " + "caller passed %d, ACPI requires %d", + pathname, user_param_count, + required_params_current)); } } + /* + * Only validate the argument count on the first successful evaluation of + * the method. This ensures that any warnings will only be emitted during + * the very first evaluation of the method/object. + */ + if (node->flags & ANOBJ_EVALUATED) { + return; + } + /* * Check that the ASL-defined parameter count is what is expected for - * this predefined name (parameter count as defined by the ACPI - * specification) + * this predefined name. */ if ((param_count != required_params_current) && (param_count != required_params_old)) { - ACPI_WARN_PREDEFINED((AE_INFO, pathname, node->flags, - "Parameter count mismatch - ASL declared %u, ACPI requires %u", - param_count, required_params_current)); + ACPI_WARNING((AE_INFO, + "%s: Parameter count mismatch - ASL declared %d, ACPI requires %d", + pathname, param_count, required_params_current)); } } @@ -366,6 +358,9 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct this_name = predefined_names; while (this_name->info.name[0]) { if (ACPI_COMPARE_NAME(node->name.ascii, this_name->info.name)) { + + /* Return pointer to this table entry */ + return (this_name); } @@ -380,16 +375,17 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct this_name++; } - return (NULL); /* Not found */ + return (NULL); } /******************************************************************************* * * FUNCTION: acpi_ns_check_package * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object + * Predefined - Pointer to entry in predefined name table * * RETURN: Status * @@ -399,26 +395,30 @@ const union acpi_predefined_info *acpi_ns_check_for_predefined_name(struct ******************************************************************************/ static acpi_status -acpi_ns_check_package(struct acpi_predefined_data *data, - union acpi_operand_object **return_object_ptr) +acpi_ns_check_package(char *pathname, + union acpi_operand_object **return_object_ptr, + const union acpi_predefined_info *predefined) { union acpi_operand_object *return_object = *return_object_ptr; const union acpi_predefined_info *package; + union acpi_operand_object *sub_package; union acpi_operand_object **elements; - acpi_status status = AE_OK; + union acpi_operand_object **sub_elements; + acpi_status status; u32 expected_count; u32 count; u32 i; + u32 j; ACPI_FUNCTION_NAME(ns_check_package); /* The package info for this name is in the next table entry */ - package = data->predefined + 1; + package = predefined + 1; ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s Validating return Package of Type %X, Count %X\n", - data->pathname, package->ret_info.type, + pathname, package->ret_info.type, return_object->package.count)); /* Extract package count and elements array */ @@ -429,8 +429,9 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* The package must have at least one element, else invalid */ if (!count) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package has no elements (empty)")); + ACPI_WARNING((AE_INFO, + "%s: Return Package has no elements (empty)", + pathname)); return (AE_AML_OPERAND_VALUE); } @@ -455,16 +456,15 @@ acpi_ns_check_package(struct acpi_predefined_data *data, if (count < expected_count) { goto package_too_small; } else if (count > expected_count) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Return Package is larger than needed - " - "found %u, expected %u", count, - expected_count)); + ACPI_WARNING((AE_INFO, + "%s: Return Package is larger than needed - " + "found %u, expected %u", pathname, count, + expected_count)); } /* Validate all elements of the returned package */ - status = acpi_ns_check_package_elements(data, elements, + status = acpi_ns_check_package_elements(pathname, elements, package->ret_info. object_type1, package->ret_info. @@ -473,6 +473,9 @@ acpi_ns_check_package(struct acpi_predefined_data *data, object_type2, package->ret_info. count2, 0); + if (ACPI_FAILURE(status)) { + return (status); + } break; case ACPI_PTYPE1_VAR: @@ -482,7 +485,7 @@ acpi_ns_check_package(struct acpi_predefined_data *data, * elements must be of the same type */ for (i = 0; i < count; i++) { - status = acpi_ns_check_object_type(data, elements, + status = acpi_ns_check_object_type(pathname, elements, package->ret_info. object_type1, i); if (ACPI_FAILURE(status)) { @@ -514,7 +517,8 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* These are the required package elements (0, 1, or 2) */ status = - acpi_ns_check_object_type(data, elements, + acpi_ns_check_object_type(pathname, + elements, package-> ret_info3. object_type[i], @@ -526,7 +530,8 @@ acpi_ns_check_package(struct acpi_predefined_data *data, /* These are the optional package elements */ status = - acpi_ns_check_object_type(data, elements, + acpi_ns_check_object_type(pathname, + elements, package-> ret_info3. tail_object_type, @@ -539,30 +544,11 @@ acpi_ns_check_package(struct acpi_predefined_data *data, } break; - case ACPI_PTYPE2_REV_FIXED: - - /* First element is the (Integer) revision */ - - status = acpi_ns_check_object_type(data, elements, - ACPI_RTYPE_INTEGER, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - - elements++; - count--; - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - case ACPI_PTYPE2_PKG_COUNT: /* First element is the (Integer) count of sub-packages to follow */ - status = acpi_ns_check_object_type(data, elements, + status = acpi_ns_check_object_type(pathname, elements, ACPI_RTYPE_INTEGER, 0); if (ACPI_FAILURE(status)) { return (status); @@ -580,11 +566,9 @@ acpi_ns_check_package(struct acpi_predefined_data *data, count = expected_count; elements++; - /* Examine the sub-packages */ + /* Now we can walk the sub-packages */ - status = - acpi_ns_check_package_list(data, package, elements, count); - break; + /*lint -fallthrough */ case ACPI_PTYPE2: case ACPI_PTYPE2_FIXED: @@ -592,240 +576,176 @@ acpi_ns_check_package(struct acpi_predefined_data *data, case ACPI_PTYPE2_COUNT: /* - * These types all return a single Package that consists of a - * variable number of sub-Packages. - * - * First, ensure that the first element is a sub-Package. If not, - * the BIOS may have incorrectly returned the object as a single - * package instead of a Package of Packages (a common error if - * there is only one entry). We may be able to repair this by - * wrapping the returned Package with a new outer Package. + * These types all return a single package that consists of a variable + * number of sub-packages */ - if ((*elements)->common.type != ACPI_TYPE_PACKAGE) { + for (i = 0; i < count; i++) { + sub_package = *elements; + sub_elements = sub_package->package.elements; - /* Create the new outer package and populate it */ + /* Each sub-object must be of type Package */ status = - acpi_ns_repair_package_list(data, - return_object_ptr); + acpi_ns_check_object_type(pathname, &sub_package, + ACPI_RTYPE_PACKAGE, i); if (ACPI_FAILURE(status)) { return (status); } - /* Update locals to point to the new package (of 1 element) */ - - return_object = *return_object_ptr; - elements = return_object->package.elements; - count = 1; - } - - /* Examine the sub-packages */ - - status = - acpi_ns_check_package_list(data, package, elements, count); - break; - - default: - - /* Should not get here if predefined info table is correct */ - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Invalid internal return type in table entry: %X", - package->ret_info.type)); - - return (AE_AML_INTERNAL); - } - - return (status); + /* Examine the different types of sub-packages */ -package_too_small: + switch (package->ret_info.type) { + case ACPI_PTYPE2: + case ACPI_PTYPE2_PKG_COUNT: - /* Error exit for the case with an incorrect package count */ + /* Each subpackage has a fixed number of elements */ - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package is too small - found %u elements, expected %u", - count, expected_count)); - - return (AE_AML_OPERAND_VALUE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_check_package_list - * - * PARAMETERS: Data - Pointer to validation data structure - * Package - Pointer to package-specific info for method - * Elements - Element list of parent package. All elements - * of this list should be of type Package. - * Count - Count of subpackages - * - * RETURN: Status - * - * DESCRIPTION: Examine a list of subpackages - * - ******************************************************************************/ - -static acpi_status -acpi_ns_check_package_list(struct acpi_predefined_data *data, - const union acpi_predefined_info *package, - union acpi_operand_object **elements, u32 count) -{ - union acpi_operand_object *sub_package; - union acpi_operand_object **sub_elements; - acpi_status status; - u32 expected_count; - u32 i; - u32 j; - - /* Validate each sub-Package in the parent Package */ - - for (i = 0; i < count; i++) { - sub_package = *elements; - sub_elements = sub_package->package.elements; - - /* Each sub-object must be of type Package */ + expected_count = + package->ret_info.count1 + + package->ret_info.count2; + if (sub_package->package.count != + expected_count) { + count = sub_package->package.count; + goto package_too_small; + } - status = acpi_ns_check_object_type(data, &sub_package, - ACPI_RTYPE_PACKAGE, i); - if (ACPI_FAILURE(status)) { - return (status); - } + status = + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + package-> + ret_info. + count1, + package-> + ret_info. + object_type2, + package-> + ret_info. + count2, 0); + if (ACPI_FAILURE(status)) { + return (status); + } + break; - /* Examine the different types of expected sub-packages */ + case ACPI_PTYPE2_FIXED: - switch (package->ret_info.type) { - case ACPI_PTYPE2: - case ACPI_PTYPE2_PKG_COUNT: - case ACPI_PTYPE2_REV_FIXED: + /* Each sub-package has a fixed length */ - /* Each subpackage has a fixed number of elements */ + expected_count = package->ret_info2.count; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } - expected_count = - package->ret_info.count1 + package->ret_info.count2; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } + /* Check the type of each sub-package element */ - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - package->ret_info. - count1, - package->ret_info. - object_type2, - package->ret_info. - count2, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; + for (j = 0; j < expected_count; j++) { + status = + acpi_ns_check_object_type(pathname, + &sub_elements[j], + package->ret_info2.object_type[j], j); + if (ACPI_FAILURE(status)) { + return (status); + } + } + break; - case ACPI_PTYPE2_FIXED: + case ACPI_PTYPE2_MIN: - /* Each sub-package has a fixed length */ + /* Each sub-package has a variable but minimum length */ - expected_count = package->ret_info2.count; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } + expected_count = package->ret_info.count1; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } - /* Check the type of each sub-package element */ + /* Check the type of each sub-package element */ - for (j = 0; j < expected_count; j++) { status = - acpi_ns_check_object_type(data, - &sub_elements[j], - package-> - ret_info2. - object_type[j], - j); + acpi_ns_check_package_elements(pathname, + sub_elements, + package-> + ret_info. + object_type1, + sub_package-> + package. + count, 0, 0, + 0); if (ACPI_FAILURE(status)) { return (status); } - } - break; + break; - case ACPI_PTYPE2_MIN: + case ACPI_PTYPE2_COUNT: - /* Each sub-package has a variable but minimum length */ + /* First element is the (Integer) count of elements to follow */ - expected_count = package->ret_info.count1; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } + status = + acpi_ns_check_object_type(pathname, + sub_elements, + ACPI_RTYPE_INTEGER, + 0); + if (ACPI_FAILURE(status)) { + return (status); + } - /* Check the type of each sub-package element */ + /* Make sure package is large enough for the Count */ - status = - acpi_ns_check_package_elements(data, sub_elements, - package->ret_info. - object_type1, - sub_package->package. - count, 0, 0, 0); - if (ACPI_FAILURE(status)) { - return (status); - } - break; + expected_count = + (u32) (*sub_elements)->integer.value; + if (sub_package->package.count < expected_count) { + count = sub_package->package.count; + goto package_too_small; + } - case ACPI_PTYPE2_COUNT: + /* Check the type of each sub-package element */ - /* - * First element is the (Integer) count of elements, including - * the count field. - */ - status = acpi_ns_check_object_type(data, sub_elements, - ACPI_RTYPE_INTEGER, - 0); - if (ACPI_FAILURE(status)) { - return (status); - } + status = + acpi_ns_check_package_elements(pathname, + (sub_elements + + 1), + package-> + ret_info. + object_type1, + (expected_count + - 1), 0, 0, + 1); + if (ACPI_FAILURE(status)) { + return (status); + } + break; - /* - * Make sure package is large enough for the Count and is - * is as large as the minimum size - */ - expected_count = (u32)(*sub_elements)->integer.value; - if (sub_package->package.count < expected_count) { - goto package_too_small; - } - if (sub_package->package.count < - package->ret_info.count1) { - expected_count = package->ret_info.count1; - goto package_too_small; + default: + break; } - /* Check the type of each sub-package element */ + elements++; + } + break; - status = - acpi_ns_check_package_elements(data, - (sub_elements + 1), - package->ret_info. - object_type1, - (expected_count - 1), - 0, 0, 1); - if (ACPI_FAILURE(status)) { - return (status); - } - break; + default: - default: /* Should not get here, type was validated by caller */ + /* Should not get here if predefined info table is correct */ - return (AE_AML_INTERNAL); - } + ACPI_WARNING((AE_INFO, + "%s: Invalid internal return type in table entry: %X", + pathname, package->ret_info.type)); - elements++; + return (AE_AML_INTERNAL); } return (AE_OK); -package_too_small: + package_too_small: - /* The sub-package count was smaller than required */ + /* Error exit for the case with an incorrect package count */ - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Sub-Package[%u] is too small - found %u elements, expected %u", - i, sub_package->package.count, expected_count)); + ACPI_WARNING((AE_INFO, "%s: Return Package is too small - " + "found %u, expected %u", pathname, count, + expected_count)); return (AE_AML_OPERAND_VALUE); } @@ -834,7 +754,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_package_elements * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) * Elements - Pointer to the package elements array * Type1 - Object type for first group * Count1 - Count for first group @@ -850,7 +770,7 @@ acpi_ns_check_package_list(struct acpi_predefined_data *data, ******************************************************************************/ static acpi_status -acpi_ns_check_package_elements(struct acpi_predefined_data *data, +acpi_ns_check_package_elements(char *pathname, union acpi_operand_object **elements, u8 type1, u32 count1, @@ -866,7 +786,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, * The second group can have a count of zero. */ for (i = 0; i < count1; i++) { - status = acpi_ns_check_object_type(data, this_element, + status = acpi_ns_check_object_type(pathname, this_element, type1, i + start_index); if (ACPI_FAILURE(status)) { return (status); @@ -875,7 +795,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, } for (i = 0; i < count2; i++) { - status = acpi_ns_check_object_type(data, this_element, + status = acpi_ns_check_object_type(pathname, this_element, type2, (i + count1 + start_index)); if (ACPI_FAILURE(status)) { @@ -891,13 +811,12 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_object_type * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) * return_object_ptr - Pointer to the object returned from the * evaluation of a method or object * expected_btypes - Bitmap of expected return type(s) * package_index - Index of object within parent package (if - * applicable - ACPI_NOT_PACKAGE_ELEMENT - * otherwise) + * applicable - ACPI_NOT_PACKAGE otherwise) * * RETURN: Status * @@ -907,7 +826,7 @@ acpi_ns_check_package_elements(struct acpi_predefined_data *data, ******************************************************************************/ static acpi_status -acpi_ns_check_object_type(struct acpi_predefined_data *data, +acpi_ns_check_object_type(char *pathname, union acpi_operand_object **return_object_ptr, u32 expected_btypes, u32 package_index) { @@ -915,6 +834,9 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, acpi_status status = AE_OK; u32 return_btype; char type_buffer[48]; /* Room for 5 types */ + u32 this_rtype; + u32 i; + u32 j; /* * If we get a NULL return_object here, it is a NULL package element, @@ -927,11 +849,10 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, /* A Namespace node should not get here, but make sure */ if (ACPI_GET_DESCRIPTOR_TYPE(return_object) == ACPI_DESC_TYPE_NAMED) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Invalid return type - Found a Namespace node [%4.4s] type %s", - return_object->node.name.ascii, - acpi_ut_get_type_name(return_object->node. - type))); + ACPI_WARNING((AE_INFO, + "%s: Invalid return type - Found a Namespace node [%4.4s] type %s", + pathname, return_object->node.name.ascii, + acpi_ut_get_type_name(return_object->node.type))); return (AE_AML_OPERAND_TYPE); } @@ -976,11 +897,10 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, /* Type mismatch -- attempt repair of the returned object */ - status = acpi_ns_repair_object(data, expected_btypes, - package_index, + status = acpi_ns_repair_object(expected_btypes, package_index, return_object_ptr); if (ACPI_SUCCESS(status)) { - return (AE_OK); /* Repair was successful */ + return (status); } goto type_error_exit; } @@ -988,7 +908,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, /* For reference objects, check that the reference type is correct */ if (return_object->common.type == ACPI_TYPE_LOCAL_REFERENCE) { - status = acpi_ns_check_reference(data, return_object); + status = acpi_ns_check_reference(pathname, return_object); } return (status); @@ -997,19 +917,33 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, /* Create a string with all expected types for this predefined object */ - acpi_ns_get_expected_types(type_buffer, expected_btypes); + j = 1; + type_buffer[0] = 0; + this_rtype = ACPI_RTYPE_INTEGER; + + for (i = 0; i < ACPI_NUM_RTYPES; i++) { + + /* If one of the expected types, concatenate the name of this type */ + + if (expected_btypes & this_rtype) { + ACPI_STRCAT(type_buffer, &acpi_rtype_names[i][j]); + j = 0; /* Use name separator from now on */ + } + this_rtype <<= 1; /* Next Rtype */ + } - if (package_index == ACPI_NOT_PACKAGE_ELEMENT) { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return type mismatch - found %s, expected %s", - acpi_ut_get_object_type_name - (return_object), type_buffer)); + if (package_index == ACPI_NOT_PACKAGE) { + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - found %s, expected %s", + pathname, + acpi_ut_get_object_type_name(return_object), + type_buffer)); } else { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return Package type mismatch at index %u - " - "found %s, expected %s", package_index, - acpi_ut_get_object_type_name - (return_object), type_buffer)); + ACPI_WARNING((AE_INFO, + "%s: Return Package type mismatch at index %u - " + "found %s, expected %s", pathname, package_index, + acpi_ut_get_object_type_name(return_object), + type_buffer)); } return (AE_AML_OPERAND_TYPE); @@ -1019,7 +953,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, * * FUNCTION: acpi_ns_check_reference * - * PARAMETERS: Data - Pointer to validation data structure + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) * return_object - Object returned from the evaluation of a * method or object * @@ -1032,7 +966,7 @@ acpi_ns_check_object_type(struct acpi_predefined_data *data, ******************************************************************************/ static acpi_status -acpi_ns_check_reference(struct acpi_predefined_data *data, +acpi_ns_check_reference(char *pathname, union acpi_operand_object *return_object) { @@ -1045,46 +979,94 @@ acpi_ns_check_reference(struct acpi_predefined_data *data, return (AE_OK); } - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Return type mismatch - unexpected reference object type [%s] %2.2X", - acpi_ut_get_reference_name(return_object), - return_object->reference.class)); + ACPI_WARNING((AE_INFO, + "%s: Return type mismatch - " + "unexpected reference object type [%s] %2.2X", + pathname, acpi_ut_get_reference_name(return_object), + return_object->reference.class)); return (AE_AML_OPERAND_TYPE); } /******************************************************************************* * - * FUNCTION: acpi_ns_get_expected_types + * FUNCTION: acpi_ns_repair_object * - * PARAMETERS: Buffer - Pointer to where the string is returned - * expected_btypes - Bitmap of expected return type(s) + * PARAMETERS: Pathname - Full pathname to the node (for error msgs) + * package_index - Used to determine if target is in a package + * return_object_ptr - Pointer to the object returned from the + * evaluation of a method or object * - * RETURN: Buffer is populated with type names. + * RETURN: Status. AE_OK if repair was successful. * - * DESCRIPTION: Translate the expected types bitmap into a string of ascii - * names of expected types, for use in warning messages. + * DESCRIPTION: Attempt to repair/convert a return object of a type that was + * not expected. * ******************************************************************************/ -static void acpi_ns_get_expected_types(char *buffer, u32 expected_btypes) +static acpi_status +acpi_ns_repair_object(u32 expected_btypes, + u32 package_index, + union acpi_operand_object **return_object_ptr) { - u32 this_rtype; - u32 i; - u32 j; + union acpi_operand_object *return_object = *return_object_ptr; + union acpi_operand_object *new_object; + acpi_size length; - j = 1; - buffer[0] = 0; - this_rtype = ACPI_RTYPE_INTEGER; + switch (return_object->common.type) { + case ACPI_TYPE_BUFFER: - for (i = 0; i < ACPI_NUM_RTYPES; i++) { + if (!(expected_btypes & ACPI_RTYPE_STRING)) { + return (AE_AML_OPERAND_TYPE); + } - /* If one of the expected types, concatenate the name of this type */ + /* + * Have a Buffer, expected a String, convert. Use a to_string + * conversion, no transform performed on the buffer data. The best + * example of this is the _BIF method, where the string data from + * the battery is often (incorrectly) returned as buffer object(s). + */ + length = 0; + while ((length < return_object->buffer.length) && + (return_object->buffer.pointer[length])) { + length++; + } - if (expected_btypes & this_rtype) { - ACPI_STRCAT(buffer, &acpi_rtype_names[i][j]); - j = 0; /* Use name separator from now on */ + /* Allocate a new string object */ + + new_object = acpi_ut_create_string_object(length); + if (!new_object) { + return (AE_NO_MEMORY); } - this_rtype <<= 1; /* Next Rtype */ + + /* + * Copy the raw buffer data with no transform. String is already NULL + * terminated at Length+1. + */ + ACPI_MEMCPY(new_object->string.pointer, + return_object->buffer.pointer, length); + + /* Install the new return object */ + + acpi_ut_remove_reference(return_object); + *return_object_ptr = new_object; + + /* + * If the object is a package element, we need to: + * 1. Decrement the reference count of the orignal object, it was + * incremented when building the package + * 2. Increment the reference count of the new object, it will be + * decremented when releasing the package + */ + if (package_index != ACPI_NOT_PACKAGE) { + acpi_ut_remove_reference(return_object); + acpi_ut_add_reference(new_object); + } + return (AE_OK); + + default: + break; } + + return (AE_AML_OPERAND_TYPE); } diff --git a/trunk/drivers/acpi/acpica/nsrepair.c b/trunk/drivers/acpi/acpica/nsrepair.c deleted file mode 100644 index db2b2a99c3a8..000000000000 --- a/trunk/drivers/acpi/acpica/nsrepair.c +++ /dev/null @@ -1,203 +0,0 @@ -/****************************************************************************** - * - * Module Name: nsrepair - Repair for objects returned by predefined methods - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2009, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include "accommon.h" -#include "acnamesp.h" -#include "acpredef.h" - -#define _COMPONENT ACPI_NAMESPACE -ACPI_MODULE_NAME("nsrepair") - -/******************************************************************************* - * - * FUNCTION: acpi_ns_repair_object - * - * PARAMETERS: Data - Pointer to validation data structure - * expected_btypes - Object types expected - * package_index - Index of object within parent package (if - * applicable - ACPI_NOT_PACKAGE_ELEMENT - * otherwise) - * return_object_ptr - Pointer to the object returned from the - * evaluation of a method or object - * - * RETURN: Status. AE_OK if repair was successful. - * - * DESCRIPTION: Attempt to repair/convert a return object of a type that was - * not expected. - * - ******************************************************************************/ -acpi_status -acpi_ns_repair_object(struct acpi_predefined_data *data, - u32 expected_btypes, - u32 package_index, - union acpi_operand_object **return_object_ptr) -{ - union acpi_operand_object *return_object = *return_object_ptr; - union acpi_operand_object *new_object; - acpi_size length; - - switch (return_object->common.type) { - case ACPI_TYPE_BUFFER: - - /* Does the method/object legally return a string? */ - - if (!(expected_btypes & ACPI_RTYPE_STRING)) { - return (AE_AML_OPERAND_TYPE); - } - - /* - * Have a Buffer, expected a String, convert. Use a to_string - * conversion, no transform performed on the buffer data. The best - * example of this is the _BIF method, where the string data from - * the battery is often (incorrectly) returned as buffer object(s). - */ - length = 0; - while ((length < return_object->buffer.length) && - (return_object->buffer.pointer[length])) { - length++; - } - - /* Allocate a new string object */ - - new_object = acpi_ut_create_string_object(length); - if (!new_object) { - return (AE_NO_MEMORY); - } - - /* - * Copy the raw buffer data with no transform. String is already NULL - * terminated at Length+1. - */ - ACPI_MEMCPY(new_object->string.pointer, - return_object->buffer.pointer, length); - - /* - * If the original object is a package element, we need to: - * 1. Set the reference count of the new object to match the - * reference count of the old object. - * 2. Decrement the reference count of the original object. - */ - if (package_index != ACPI_NOT_PACKAGE_ELEMENT) { - new_object->common.reference_count = - return_object->common.reference_count; - - if (return_object->common.reference_count > 1) { - return_object->common.reference_count--; - } - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Converted Buffer to expected String at index %u", - package_index)); - } else { - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, - data->node_flags, - "Converted Buffer to expected String")); - } - - /* Delete old object, install the new return object */ - - acpi_ut_remove_reference(return_object); - *return_object_ptr = new_object; - data->flags |= ACPI_OBJECT_REPAIRED; - return (AE_OK); - - default: - break; - } - - return (AE_AML_OPERAND_TYPE); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ns_repair_package_list - * - * PARAMETERS: Data - Pointer to validation data structure - * obj_desc_ptr - Pointer to the object to repair. The new - * package object is returned here, - * overwriting the old object. - * - * RETURN: Status, new object in *obj_desc_ptr - * - * DESCRIPTION: Repair a common problem with objects that are defined to return - * a variable-length Package of Packages. If the variable-length - * is one, some BIOS code mistakenly simply declares a single - * Package instead of a Package with one sub-Package. This - * function attempts to repair this error by wrapping a Package - * object around the original Package, creating the correct - * Package with one sub-Package. - * - * Names that can be repaired in this manner include: - * _ALR, _CSD, _HPX, _MLS, _PRT, _PSS, _TRT, TSS - * - ******************************************************************************/ - -acpi_status -acpi_ns_repair_package_list(struct acpi_predefined_data *data, - union acpi_operand_object **obj_desc_ptr) -{ - union acpi_operand_object *pkg_obj_desc; - - /* - * Create the new outer package and populate it. The new package will - * have a single element, the lone subpackage. - */ - pkg_obj_desc = acpi_ut_create_package_object(1); - if (!pkg_obj_desc) { - return (AE_NO_MEMORY); - } - - pkg_obj_desc->package.elements[0] = *obj_desc_ptr; - - /* Return the new object in the object pointer */ - - *obj_desc_ptr = pkg_obj_desc; - data->flags |= ACPI_OBJECT_REPAIRED; - - ACPI_WARN_PREDEFINED((AE_INFO, data->pathname, data->node_flags, - "Incorrectly formed Package, attempting repair")); - - return (AE_OK); -} diff --git a/trunk/drivers/acpi/acpica/nsutils.c b/trunk/drivers/acpi/acpica/nsutils.c index ea55ab4f9849..78277ed08339 100644 --- a/trunk/drivers/acpi/acpica/nsutils.c +++ b/trunk/drivers/acpi/acpica/nsutils.c @@ -88,8 +88,7 @@ acpi_ns_report_error(const char *module_name, /* There is a non-ascii character in the name */ - ACPI_MOVE_32_TO_32(&bad_name, - ACPI_CAST_PTR(u32, internal_name)); + ACPI_MOVE_32_TO_32(&bad_name, internal_name); acpi_os_printf("[0x%4.4X] (NON-ASCII)", bad_name); } else { /* Convert path to external format */ @@ -837,7 +836,7 @@ acpi_ns_get_node(struct acpi_namespace_node *prefix_node, acpi_status status; char *internal_path; - ACPI_FUNCTION_TRACE_PTR(ns_get_node, ACPI_CAST_PTR(char, pathname)); + ACPI_FUNCTION_TRACE_PTR(ns_get_node, pathname); if (!pathname) { *return_node = prefix_node; diff --git a/trunk/drivers/acpi/acpica/nsxfeval.c b/trunk/drivers/acpi/acpica/nsxfeval.c index 4929dbdbc8f0..daf4ad37896d 100644 --- a/trunk/drivers/acpi/acpica/nsxfeval.c +++ b/trunk/drivers/acpi/acpica/nsxfeval.c @@ -535,11 +535,10 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, acpi_status status; struct acpi_namespace_node *node; u32 flags; - struct acpica_device_id *hid; - struct acpica_device_id_list *cid; + struct acpica_device_id hid; + struct acpi_compatible_id_list *cid; u32 i; - u8 found; - int no_match; + int found; status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { @@ -583,14 +582,10 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, return (AE_CTRL_DEPTH); } - no_match = ACPI_STRCMP(hid->string, info->hid); - ACPI_FREE(hid); + if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { + + /* Get the list of Compatible IDs */ - if (no_match) { - /* - * HID does not match, attempt match within the - * list of Compatible IDs (CIDs) - */ status = acpi_ut_execute_CID(node, &cid); if (status == AE_NOT_FOUND) { return (AE_OK); @@ -602,8 +597,10 @@ acpi_ns_get_device_callback(acpi_handle obj_handle, found = 0; for (i = 0; i < cid->count; i++) { - if (ACPI_STRCMP(cid->ids[i].string, info->hid) - == 0) { + if (ACPI_STRNCMP(cid->id[i].value, info->hid, + sizeof(struct + acpi_compatible_id)) == + 0) { found = 1; break; } diff --git a/trunk/drivers/acpi/acpica/nsxfname.c b/trunk/drivers/acpi/acpica/nsxfname.c index ddc84af6336e..f23593d6add4 100644 --- a/trunk/drivers/acpi/acpica/nsxfname.c +++ b/trunk/drivers/acpi/acpica/nsxfname.c @@ -51,11 +51,6 @@ #define _COMPONENT ACPI_NAMESPACE ACPI_MODULE_NAME("nsxfname") -/* Local prototypes */ -static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, - struct acpica_device_id *source, - char *string_area); - /****************************************************************************** * * FUNCTION: acpi_get_handle @@ -73,7 +68,6 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, * namespace handle. * ******************************************************************************/ - acpi_status acpi_get_handle(acpi_handle parent, acpi_string pathname, acpi_handle * ret_handle) @@ -214,40 +208,12 @@ acpi_get_name(acpi_handle handle, u32 name_type, struct acpi_buffer * buffer) ACPI_EXPORT_SYMBOL(acpi_get_name) -/****************************************************************************** - * - * FUNCTION: acpi_ns_copy_device_id - * - * PARAMETERS: Dest - Pointer to the destination DEVICE_ID - * Source - Pointer to the source DEVICE_ID - * string_area - Pointer to where to copy the dest string - * - * RETURN: Pointer to the next string area - * - * DESCRIPTION: Copy a single DEVICE_ID, including the string data. - * - ******************************************************************************/ -static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, - struct acpica_device_id *source, - char *string_area) -{ - /* Create the destination DEVICE_ID */ - - dest->string = string_area; - dest->length = source->length; - - /* Copy actual string and return a pointer to the next string area */ - - ACPI_MEMCPY(string_area, source->string, source->length); - return (string_area + source->length); -} - /****************************************************************************** * * FUNCTION: acpi_get_object_info * - * PARAMETERS: Handle - Object Handle - * return_buffer - Where the info is returned + * PARAMETERS: Handle - Object Handle + * Buffer - Where the info is returned * * RETURN: Status * @@ -255,37 +221,33 @@ static char *acpi_ns_copy_device_id(struct acpica_device_id *dest, * namespace node and possibly by running several standard * control methods (Such as in the case of a device.) * - * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA, - * _ADR, _sx_w, and _sx_d methods. - * - * Note: Allocates the return buffer, must be freed by the caller. - * ******************************************************************************/ - acpi_status -acpi_get_object_info(acpi_handle handle, - struct acpi_device_info **return_buffer) +acpi_get_object_info(acpi_handle handle, struct acpi_buffer * buffer) { + acpi_status status; struct acpi_namespace_node *node; struct acpi_device_info *info; - struct acpica_device_id_list *cid_list = NULL; - struct acpica_device_id *hid = NULL; - struct acpica_device_id *uid = NULL; - char *next_id_string; - acpi_object_type type; - acpi_name name; - u8 param_count = 0; - u8 valid = 0; - u32 info_size; - u32 i; - acpi_status status; + struct acpi_device_info *return_info; + struct acpi_compatible_id_list *cid_list = NULL; + acpi_size size; /* Parameter validation */ - if (!handle || !return_buffer) { + if (!handle || !buffer) { return (AE_BAD_PARAMETER); } + status = acpi_ut_validate_buffer(buffer); + if (ACPI_FAILURE(status)) { + return (status); + } + + info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_device_info)); + if (!info) { + return (AE_NO_MEMORY); + } + status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { goto cleanup; @@ -294,91 +256,66 @@ acpi_get_object_info(acpi_handle handle, node = acpi_ns_map_handle_to_node(handle); if (!node) { (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); - return (AE_BAD_PARAMETER); + status = AE_BAD_PARAMETER; + goto cleanup; } - /* Get the namespace node data while the namespace is locked */ + /* Init return structure */ + + size = sizeof(struct acpi_device_info); - info_size = sizeof(struct acpi_device_info); - type = node->type; - name = node->name.integer; + info->type = node->type; + info->name = node->name.integer; + info->valid = 0; if (node->type == ACPI_TYPE_METHOD) { - param_count = node->object->method.param_count; + info->param_count = node->object->method.param_count; } status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); if (ACPI_FAILURE(status)) { - return (status); + goto cleanup; } - if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { + /* If not a device, we are all done */ + + if (info->type == ACPI_TYPE_DEVICE) { /* - * Get extra info for ACPI Device/Processor objects only: - * Run the Device _HID, _UID, and _CID methods. + * Get extra info for ACPI Devices objects only: + * Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods. * * Note: none of these methods are required, so they may or may - * not be present for this device. The Info->Valid bitfield is used - * to indicate which methods were found and run successfully. + * not be present for this device. The Info->Valid bitfield is used + * to indicate which methods were found and ran successfully. */ /* Execute the Device._HID method */ - status = acpi_ut_execute_HID(node, &hid); + status = acpi_ut_execute_HID(node, &info->hardware_id); if (ACPI_SUCCESS(status)) { - info_size += hid->length; - valid |= ACPI_VALID_HID; + info->valid |= ACPI_VALID_HID; } /* Execute the Device._UID method */ - status = acpi_ut_execute_UID(node, &uid); + status = acpi_ut_execute_UID(node, &info->unique_id); if (ACPI_SUCCESS(status)) { - info_size += uid->length; - valid |= ACPI_VALID_UID; + info->valid |= ACPI_VALID_UID; } /* Execute the Device._CID method */ status = acpi_ut_execute_CID(node, &cid_list); if (ACPI_SUCCESS(status)) { - - /* Add size of CID strings and CID pointer array */ - - info_size += - (cid_list->list_size - - sizeof(struct acpica_device_id_list)); - valid |= ACPI_VALID_CID; + size += cid_list->size; + info->valid |= ACPI_VALID_CID; } - } - - /* - * Now that we have the variable-length data, we can allocate the - * return buffer - */ - info = ACPI_ALLOCATE_ZEROED(info_size); - if (!info) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Get the fixed-length data */ - - if ((type == ACPI_TYPE_DEVICE) || (type == ACPI_TYPE_PROCESSOR)) { - /* - * Get extra info for ACPI Device/Processor objects only: - * Run the _STA, _ADR and, sx_w, and _sx_d methods. - * - * Note: none of these methods are required, so they may or may - * not be present for this device. The Info->Valid bitfield is used - * to indicate which methods were found and run successfully. - */ /* Execute the Device._STA method */ status = acpi_ut_execute_STA(node, &info->current_status); if (ACPI_SUCCESS(status)) { - valid |= ACPI_VALID_STA; + info->valid |= ACPI_VALID_STA; } /* Execute the Device._ADR method */ @@ -386,100 +323,36 @@ acpi_get_object_info(acpi_handle handle, status = acpi_ut_evaluate_numeric_object(METHOD_NAME__ADR, node, &info->address); if (ACPI_SUCCESS(status)) { - valid |= ACPI_VALID_ADR; - } - - /* Execute the Device._sx_w methods */ - - status = acpi_ut_execute_power_methods(node, - acpi_gbl_lowest_dstate_names, - ACPI_NUM_sx_w_METHODS, - info->lowest_dstates); - if (ACPI_SUCCESS(status)) { - valid |= ACPI_VALID_SXWS; + info->valid |= ACPI_VALID_ADR; } /* Execute the Device._sx_d methods */ - status = acpi_ut_execute_power_methods(node, - acpi_gbl_highest_dstate_names, - ACPI_NUM_sx_d_METHODS, - info->highest_dstates); + status = acpi_ut_execute_sxds(node, info->highest_dstates); if (ACPI_SUCCESS(status)) { - valid |= ACPI_VALID_SXDS; + info->valid |= ACPI_VALID_SXDS; } } - /* - * Create a pointer to the string area of the return buffer. - * Point to the end of the base struct acpi_device_info structure. - */ - next_id_string = ACPI_CAST_PTR(char, info->compatible_id_list.ids); - if (cid_list) { - - /* Point past the CID DEVICE_ID array */ + /* Validate/Allocate/Clear caller buffer */ - next_id_string += - ((acpi_size) cid_list->count * - sizeof(struct acpica_device_id)); + status = acpi_ut_initialize_buffer(buffer, size); + if (ACPI_FAILURE(status)) { + goto cleanup; } - /* - * Copy the HID, UID, and CIDs to the return buffer. The variable-length - * strings are copied to the reserved area at the end of the buffer. - * - * For HID and CID, check if the ID is a PCI Root Bridge. - */ - if (hid) { - next_id_string = acpi_ns_copy_device_id(&info->hardware_id, - hid, next_id_string); - - if (acpi_ut_is_pci_root_bridge(hid->string)) { - info->flags |= ACPI_PCI_ROOT_BRIDGE; - } - } + /* Populate the return buffer */ - if (uid) { - next_id_string = acpi_ns_copy_device_id(&info->unique_id, - uid, next_id_string); - } + return_info = buffer->pointer; + ACPI_MEMCPY(return_info, info, sizeof(struct acpi_device_info)); if (cid_list) { - info->compatible_id_list.count = cid_list->count; - info->compatible_id_list.list_size = cid_list->list_size; - - /* Copy each CID */ - - for (i = 0; i < cid_list->count; i++) { - next_id_string = - acpi_ns_copy_device_id(&info->compatible_id_list. - ids[i], &cid_list->ids[i], - next_id_string); - - if (acpi_ut_is_pci_root_bridge(cid_list->ids[i].string)) { - info->flags |= ACPI_PCI_ROOT_BRIDGE; - } - } + ACPI_MEMCPY(&return_info->compatibility_id, cid_list, + cid_list->size); } - /* Copy the fixed-length data */ - - info->info_size = info_size; - info->type = type; - info->name = name; - info->param_count = param_count; - info->valid = valid; - - *return_buffer = info; - status = AE_OK; - cleanup: - if (hid) { - ACPI_FREE(hid); - } - if (uid) { - ACPI_FREE(uid); - } + ACPI_FREE(info); if (cid_list) { ACPI_FREE(cid_list); } diff --git a/trunk/drivers/acpi/acpica/psloop.c b/trunk/drivers/acpi/acpica/psloop.c index cd7995b3aed4..c5f6ce19a401 100644 --- a/trunk/drivers/acpi/acpica/psloop.c +++ b/trunk/drivers/acpi/acpica/psloop.c @@ -86,9 +86,6 @@ static acpi_status acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, union acpi_parse_object *op, acpi_status status); -static void -acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); - /******************************************************************************* * * FUNCTION: acpi_ps_get_aml_opcode @@ -393,7 +390,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, { acpi_status status = AE_OK; union acpi_parse_object *arg = NULL; - const struct acpi_opcode_info *op_info; ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); @@ -453,11 +449,13 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, INCREMENT_ARG_LIST(walk_state->arg_types); } - /* - * Handle executable code at "module-level". This refers to - * executable opcodes that appear outside of any control method. - */ - if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) && + /* Special processing for certain opcodes */ + + /* TBD (remove): Temporary mechanism to disable this code if needed */ + +#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE + + if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { /* * We want to skip If/Else/While constructs during Pass1 because we @@ -471,23 +469,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, case AML_ELSE_OP: case AML_WHILE_OP: - /* - * Currently supported module-level opcodes are: - * IF/ELSE/WHILE. These appear to be the most common, - * and easiest to support since they open an AML - * package. - */ - if (walk_state->pass_number == - ACPI_IMODE_LOAD_PASS1) { - acpi_ps_link_module_code(aml_op_start, - walk_state-> - parser_state. - pkg_end - - aml_op_start, - walk_state-> - owner_id); - } - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Pass1: Skipping an If/Else/While body\n")); @@ -499,34 +480,10 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, break; default: - /* - * Check for an unsupported executable opcode at module - * level. We must be in PASS1, the parent must be a SCOPE, - * The opcode class must be EXECUTE, and the opcode must - * not be an argument to another opcode. - */ - if ((walk_state->pass_number == - ACPI_IMODE_LOAD_PASS1) - && (op->common.parent->common.aml_opcode == - AML_SCOPE_OP)) { - op_info = - acpi_ps_get_opcode_info(op->common. - aml_opcode); - if ((op_info->class == - AML_CLASS_EXECUTE) && (!arg)) { - ACPI_WARNING((AE_INFO, - "Detected an unsupported executable opcode " - "at module-level: [0x%.4X] at table offset 0x%.4X", - op->common.aml_opcode, - (u32)((aml_op_start - walk_state->parser_state.aml_start) - + sizeof(struct acpi_table_header)))); - } - } break; } } - - /* Special processing for certain opcodes */ +#endif switch (op->common.aml_opcode) { case AML_METHOD_OP: @@ -594,66 +551,6 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state, return_ACPI_STATUS(AE_OK); } -/******************************************************************************* - * - * FUNCTION: acpi_ps_link_module_code - * - * PARAMETERS: aml_start - Pointer to the AML - * aml_length - Length of executable AML - * owner_id - owner_id of module level code - * - * RETURN: None. - * - * DESCRIPTION: Wrap the module-level code with a method object and link the - * object to the global list. Note, the mutex field of the method - * object is used to link multiple module-level code objects. - * - ******************************************************************************/ - -static void -acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) -{ - union acpi_operand_object *prev; - union acpi_operand_object *next; - union acpi_operand_object *method_obj; - - /* Get the tail of the list */ - - prev = next = acpi_gbl_module_code_list; - while (next) { - prev = next; - next = next->method.mutex; - } - - /* - * Insert the module level code into the list. Merge it if it is - * adjacent to the previous element. - */ - if (!prev || - ((prev->method.aml_start + prev->method.aml_length) != aml_start)) { - - /* Create, initialize, and link a new temporary method object */ - - method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); - if (!method_obj) { - return; - } - - method_obj->method.aml_start = aml_start; - method_obj->method.aml_length = aml_length; - method_obj->method.owner_id = owner_id; - method_obj->method.flags |= AOPOBJ_MODULE_LEVEL; - - if (!prev) { - acpi_gbl_module_code_list = method_obj; - } else { - prev->method.mutex = method_obj; - } - } else { - prev->method.aml_length += aml_length; - } -} - /******************************************************************************* * * FUNCTION: acpi_ps_complete_op diff --git a/trunk/drivers/acpi/acpica/psxface.c b/trunk/drivers/acpi/acpica/psxface.c index dd9731c29a79..ff06032c0f06 100644 --- a/trunk/drivers/acpi/acpica/psxface.c +++ b/trunk/drivers/acpi/acpica/psxface.c @@ -280,10 +280,6 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info) goto cleanup; } - if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) { - walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL; - } - /* Invoke an internal method if necessary */ if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { diff --git a/trunk/drivers/acpi/acpica/tbutils.c b/trunk/drivers/acpi/acpica/tbutils.c index 1f15497f00d1..ef7d2c2d8f0b 100644 --- a/trunk/drivers/acpi/acpica/tbutils.c +++ b/trunk/drivers/acpi/acpica/tbutils.c @@ -49,12 +49,6 @@ ACPI_MODULE_NAME("tbutils") /* Local prototypes */ -static void acpi_tb_fix_string(char *string, acpi_size length); - -static void -acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, - struct acpi_table_header *header); - static acpi_physical_address acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); @@ -165,59 +159,6 @@ u8 acpi_tb_tables_loaded(void) return (FALSE); } -/******************************************************************************* - * - * FUNCTION: acpi_tb_fix_string - * - * PARAMETERS: String - String to be repaired - * Length - Maximum length - * - * RETURN: None - * - * DESCRIPTION: Replace every non-printable or non-ascii byte in the string - * with a question mark '?'. - * - ******************************************************************************/ - -static void acpi_tb_fix_string(char *string, acpi_size length) -{ - - while (length && *string) { - if (!ACPI_IS_PRINT(*string)) { - *string = '?'; - } - string++; - length--; - } -} - -/******************************************************************************* - * - * FUNCTION: acpi_tb_cleanup_table_header - * - * PARAMETERS: out_header - Where the cleaned header is returned - * Header - Input ACPI table header - * - * RETURN: Returns the cleaned header in out_header - * - * DESCRIPTION: Copy the table header and ensure that all "string" fields in - * the header consist of printable characters. - * - ******************************************************************************/ - -static void -acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, - struct acpi_table_header *header) -{ - - ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header)); - - acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); - acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); - acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); - acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE); -} - /******************************************************************************* * * FUNCTION: acpi_tb_print_table_header @@ -235,7 +176,6 @@ void acpi_tb_print_table_header(acpi_physical_address address, struct acpi_table_header *header) { - struct acpi_table_header local_header; /* * The reason that the Address is cast to a void pointer is so that we @@ -252,11 +192,6 @@ acpi_tb_print_table_header(acpi_physical_address address, /* RSDP has no common fields */ - ACPI_MEMCPY(local_header.oem_id, - ACPI_CAST_PTR(struct acpi_table_rsdp, - header)->oem_id, ACPI_OEM_ID_SIZE); - acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); - ACPI_INFO((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", ACPI_CAST_PTR (void, address), (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> @@ -265,21 +200,18 @@ acpi_tb_print_table_header(acpi_physical_address address, header)->length : 20, ACPI_CAST_PTR(struct acpi_table_rsdp, header)->revision, - local_header.oem_id)); + ACPI_CAST_PTR(struct acpi_table_rsdp, + header)->oem_id)); } else { /* Standard ACPI table with full common header */ - acpi_tb_cleanup_table_header(&local_header, header); - ACPI_INFO((AE_INFO, "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", - local_header.signature, ACPI_CAST_PTR(void, address), - local_header.length, local_header.revision, - local_header.oem_id, local_header.oem_table_id, - local_header.oem_revision, - local_header.asl_compiler_id, - local_header.asl_compiler_revision)); - + header->signature, ACPI_CAST_PTR (void, address), + header->length, header->revision, header->oem_id, + header->oem_table_id, header->oem_revision, + header->asl_compiler_id, + header->asl_compiler_revision)); } } diff --git a/trunk/drivers/acpi/acpica/utdelete.c b/trunk/drivers/acpi/acpica/utdelete.c index 96e26e70c63d..bc1710315088 100644 --- a/trunk/drivers/acpi/acpica/utdelete.c +++ b/trunk/drivers/acpi/acpica/utdelete.c @@ -215,12 +215,6 @@ static void acpi_ut_delete_internal_obj(union acpi_operand_object *object) ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, "***** Region %p\n", object)); - /* Invalidate the region address/length via the host OS */ - - acpi_os_invalidate_address(object->region.space_id, - object->region.address, - (acpi_size) object->region.length); - second_desc = acpi_ns_get_secondary_object(object); if (second_desc) { /* diff --git a/trunk/drivers/acpi/acpica/uteval.c b/trunk/drivers/acpi/acpica/uteval.c index 5d54e36ab453..006b16c26017 100644 --- a/trunk/drivers/acpi/acpica/uteval.c +++ b/trunk/drivers/acpi/acpica/uteval.c @@ -44,10 +44,19 @@ #include #include "accommon.h" #include "acnamesp.h" +#include "acinterp.h" #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("uteval") +/* Local prototypes */ +static void +acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length); + +static acpi_status +acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, + struct acpi_compatible_id *one_cid); + /* * Strings supported by the _OSI predefined (internal) method. * @@ -69,9 +78,6 @@ static struct acpi_interface_info acpi_interfaces_supported[] = { {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ - {"Windows 2006.1", ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ - {"Windows 2006 SP1", ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ - {"Windows 2009", ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ /* Feature Group Strings */ @@ -207,7 +213,7 @@ acpi_status acpi_osi_invalidate(char *interface) * RETURN: Status * * DESCRIPTION: Evaluates a namespace object and verifies the type of the - * return object. Common code that simplifies accessing objects + * return object. Common code that simplifies accessing objects * that have required return objects of fixed types. * * NOTE: Internal function, no parameter validation @@ -292,7 +298,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, if ((acpi_gbl_enable_interpreter_slack) && (!expected_return_btypes)) { /* - * We received a return object, but one was not expected. This can + * We received a return object, but one was not expected. This can * happen frequently if the "implicit return" feature is enabled. * Just delete the return object and return AE_OK. */ @@ -334,12 +340,12 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, * * PARAMETERS: object_name - Object name to be evaluated * device_node - Node for the device - * Value - Where the value is returned + * Address - Where the value is returned * * RETURN: Status * * DESCRIPTION: Evaluates a numeric namespace object for a selected device - * and stores result in *Value. + * and stores result in *Address. * * NOTE: Internal function, no parameter validation * @@ -348,7 +354,7 @@ acpi_ut_evaluate_object(struct acpi_namespace_node *prefix_node, acpi_status acpi_ut_evaluate_numeric_object(char *object_name, struct acpi_namespace_node *device_node, - acpi_integer *value) + acpi_integer * address) { union acpi_operand_object *obj_desc; acpi_status status; @@ -363,7 +369,295 @@ acpi_ut_evaluate_numeric_object(char *object_name, /* Get the returned Integer */ - *value = obj_desc->integer.value; + *address = obj_desc->integer.value; + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_copy_id_string + * + * PARAMETERS: Destination - Where to copy the string + * Source - Source string + * max_length - Length of the destination buffer + * + * RETURN: None + * + * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. + * Performs removal of a leading asterisk if present -- workaround + * for a known issue on a bunch of machines. + * + ******************************************************************************/ + +static void +acpi_ut_copy_id_string(char *destination, char *source, acpi_size max_length) +{ + + /* + * Workaround for ID strings that have a leading asterisk. This construct + * is not allowed by the ACPI specification (ID strings must be + * alphanumeric), but enough existing machines have this embedded in their + * ID strings that the following code is useful. + */ + if (*source == '*') { + source++; + } + + /* Do the actual copy */ + + ACPI_STRNCPY(destination, source, max_length); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_HID + * + * PARAMETERS: device_node - Node for the device + * Hid - Where the HID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _HID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_HID(struct acpi_namespace_node *device_node, + struct acpica_device_id *hid) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_execute_HID); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, + &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { + + /* Convert the Numeric HID to string */ + + acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, + hid->value); + } else { + /* Copy the String HID from the returned object */ + + acpi_ut_copy_id_string(hid->value, obj_desc->string.pointer, + sizeof(hid->value)); + } + + /* On exit, we must delete the return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_translate_one_cid + * + * PARAMETERS: obj_desc - _CID object, must be integer or string + * one_cid - Where the CID string is returned + * + * RETURN: Status + * + * DESCRIPTION: Return a numeric or string _CID value as a string. + * (Compatible ID) + * + * NOTE: Assumes a maximum _CID string length of + * ACPI_MAX_CID_LENGTH. + * + ******************************************************************************/ + +static acpi_status +acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, + struct acpi_compatible_id *one_cid) +{ + + switch (obj_desc->common.type) { + case ACPI_TYPE_INTEGER: + + /* Convert the Numeric CID to string */ + + acpi_ex_eisa_id_to_string((u32) obj_desc->integer.value, + one_cid->value); + return (AE_OK); + + case ACPI_TYPE_STRING: + + if (obj_desc->string.length > ACPI_MAX_CID_LENGTH) { + return (AE_AML_STRING_LIMIT); + } + + /* Copy the String CID from the returned object */ + + acpi_ut_copy_id_string(one_cid->value, obj_desc->string.pointer, + ACPI_MAX_CID_LENGTH); + return (AE_OK); + + default: + + return (AE_TYPE); + } +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_CID + * + * PARAMETERS: device_node - Node for the device + * return_cid_list - Where the CID list is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _CID control method that returns one or more + * compatible hardware IDs for the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_CID(struct acpi_namespace_node * device_node, + struct acpi_compatible_id_list ** return_cid_list) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + u32 count; + u32 size; + struct acpi_compatible_id_list *cid_list; + u32 i; + + ACPI_FUNCTION_TRACE(ut_execute_CID); + + /* Evaluate the _CID method for this device */ + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING + | ACPI_BTYPE_PACKAGE, &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* Get the number of _CIDs returned */ + + count = 1; + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + count = obj_desc->package.count; + } + + /* Allocate a worst-case buffer for the _CIDs */ + + size = (((count - 1) * sizeof(struct acpi_compatible_id)) + + sizeof(struct acpi_compatible_id_list)); + + cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); + if (!cid_list) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* Init CID list */ + + cid_list->count = count; + cid_list->size = size; + + /* + * A _CID can return either a single compatible ID or a package of + * compatible IDs. Each compatible ID can be one of the following: + * 1) Integer (32 bit compressed EISA ID) or + * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") + */ + + /* The _CID object can be either a single CID or a package (list) of CIDs */ + + if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { + + /* Translate each package element */ + + for (i = 0; i < count; i++) { + status = + acpi_ut_translate_one_cid(obj_desc->package. + elements[i], + &cid_list->id[i]); + if (ACPI_FAILURE(status)) { + break; + } + } + } else { + /* Only one CID, translate to a string */ + + status = acpi_ut_translate_one_cid(obj_desc, cid_list->id); + } + + /* Cleanup on error */ + + if (ACPI_FAILURE(status)) { + ACPI_FREE(cid_list); + } else { + *return_cid_list = cid_list; + } + + /* On exit, we must delete the _CID return object */ + + acpi_ut_remove_reference(obj_desc); + return_ACPI_STATUS(status); +} + +/******************************************************************************* + * + * FUNCTION: acpi_ut_execute_UID + * + * PARAMETERS: device_node - Node for the device + * Uid - Where the UID is returned + * + * RETURN: Status + * + * DESCRIPTION: Executes the _UID control method that returns the hardware + * ID of the device. + * + * NOTE: Internal function, no parameter validation + * + ******************************************************************************/ + +acpi_status +acpi_ut_execute_UID(struct acpi_namespace_node *device_node, + struct acpica_device_id *uid) +{ + union acpi_operand_object *obj_desc; + acpi_status status; + + ACPI_FUNCTION_TRACE(ut_execute_UID); + + status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, + ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, + &obj_desc); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + if (obj_desc->common.type == ACPI_TYPE_INTEGER) { + + /* Convert the Numeric UID to string */ + + acpi_ex_unsigned_integer_to_string(obj_desc->integer.value, + uid->value); + } else { + /* Copy the String UID from the returned object */ + + acpi_ut_copy_id_string(uid->value, obj_desc->string.pointer, + sizeof(uid->value)); + } /* On exit, we must delete the return object */ @@ -422,64 +716,60 @@ acpi_ut_execute_STA(struct acpi_namespace_node *device_node, u32 * flags) /******************************************************************************* * - * FUNCTION: acpi_ut_execute_power_methods + * FUNCTION: acpi_ut_execute_Sxds * * PARAMETERS: device_node - Node for the device - * method_names - Array of power method names - * method_count - Number of methods to execute - * out_values - Where the power method values are returned + * Flags - Where the status flags are returned * - * RETURN: Status, out_values + * RETURN: Status * - * DESCRIPTION: Executes the specified power methods for the device and returns - * the result(s). + * DESCRIPTION: Executes _STA for selected device and stores results in + * *Flags. * * NOTE: Internal function, no parameter validation * -******************************************************************************/ + ******************************************************************************/ acpi_status -acpi_ut_execute_power_methods(struct acpi_namespace_node *device_node, - const char **method_names, - u8 method_count, u8 *out_values) +acpi_ut_execute_sxds(struct acpi_namespace_node *device_node, u8 * highest) { union acpi_operand_object *obj_desc; acpi_status status; - acpi_status final_status = AE_NOT_FOUND; u32 i; - ACPI_FUNCTION_TRACE(ut_execute_power_methods); + ACPI_FUNCTION_TRACE(ut_execute_sxds); - for (i = 0; i < method_count; i++) { - /* - * Execute the power method (_sx_d or _sx_w). The only allowable - * return type is an Integer. - */ + for (i = 0; i < 4; i++) { + highest[i] = 0xFF; status = acpi_ut_evaluate_object(device_node, ACPI_CAST_PTR(char, - method_names[i]), + acpi_gbl_highest_dstate_names + [i]), ACPI_BTYPE_INTEGER, &obj_desc); - if (ACPI_SUCCESS(status)) { - out_values[i] = (u8)obj_desc->integer.value; + if (ACPI_FAILURE(status)) { + if (status != AE_NOT_FOUND) { + ACPI_DEBUG_PRINT((ACPI_DB_EXEC, + "%s on Device %4.4s, %s\n", + ACPI_CAST_PTR(char, + acpi_gbl_highest_dstate_names + [i]), + acpi_ut_get_node_name + (device_node), + acpi_format_exception + (status))); + + return_ACPI_STATUS(status); + } + } else { + /* Extract the Dstate value */ + + highest[i] = (u8) obj_desc->integer.value; /* Delete the return object */ acpi_ut_remove_reference(obj_desc); - final_status = AE_OK; /* At least one value is valid */ - continue; } - - out_values[i] = ACPI_UINT8_MAX; - if (status == AE_NOT_FOUND) { - continue; /* Ignore if not found */ - } - - ACPI_DEBUG_PRINT((ACPI_DB_EXEC, - "Failed %s on Device %4.4s, %s\n", - ACPI_CAST_PTR(char, method_names[i]), - acpi_ut_get_node_name(device_node), - acpi_format_exception(status))); } - return_ACPI_STATUS(final_status); + return_ACPI_STATUS(AE_OK); } diff --git a/trunk/drivers/acpi/acpica/utglobal.c b/trunk/drivers/acpi/acpica/utglobal.c index 3f2c68f4e959..59e46f257c02 100644 --- a/trunk/drivers/acpi/acpica/utglobal.c +++ b/trunk/drivers/acpi/acpica/utglobal.c @@ -90,15 +90,7 @@ const char *acpi_gbl_sleep_state_names[ACPI_S_STATE_COUNT] = { "\\_S5_" }; -const char *acpi_gbl_lowest_dstate_names[ACPI_NUM_sx_w_METHODS] = { - "_S0W", - "_S1W", - "_S2W", - "_S3W", - "_S4W" -}; - -const char *acpi_gbl_highest_dstate_names[ACPI_NUM_sx_d_METHODS] = { +const char *acpi_gbl_highest_dstate_names[4] = { "_S1D", "_S2D", "_S3D", @@ -359,7 +351,6 @@ const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = { "SMBus", "SystemCMOS", "PCIBARTarget", - "IPMI", "DataTable" }; @@ -807,7 +798,6 @@ acpi_status acpi_ut_init_globals(void) /* Namespace */ - acpi_gbl_module_code_list = NULL; acpi_gbl_root_node = NULL; acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; diff --git a/trunk/drivers/acpi/acpica/utids.c b/trunk/drivers/acpi/acpica/utids.c deleted file mode 100644 index 52eaae404554..000000000000 --- a/trunk/drivers/acpi/acpica/utids.c +++ /dev/null @@ -1,382 +0,0 @@ -/****************************************************************************** - * - * Module Name: utids - support for device IDs - HID, UID, CID - * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2009, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ - -#include -#include "accommon.h" -#include "acinterp.h" - -#define _COMPONENT ACPI_UTILITIES -ACPI_MODULE_NAME("utids") - -/* Local prototypes */ -static void acpi_ut_copy_id_string(char *destination, char *source); - -/******************************************************************************* - * - * FUNCTION: acpi_ut_copy_id_string - * - * PARAMETERS: Destination - Where to copy the string - * Source - Source string - * - * RETURN: None - * - * DESCRIPTION: Copies an ID string for the _HID, _CID, and _UID methods. - * Performs removal of a leading asterisk if present -- workaround - * for a known issue on a bunch of machines. - * - ******************************************************************************/ - -static void acpi_ut_copy_id_string(char *destination, char *source) -{ - - /* - * Workaround for ID strings that have a leading asterisk. This construct - * is not allowed by the ACPI specification (ID strings must be - * alphanumeric), but enough existing machines have this embedded in their - * ID strings that the following code is useful. - */ - if (*source == '*') { - source++; - } - - /* Do the actual copy */ - - ACPI_STRCPY(destination, source); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_HID - * - * PARAMETERS: device_node - Node for the device - * return_id - Where the string HID is returned - * - * RETURN: Status - * - * DESCRIPTION: Executes the _HID control method that returns the hardware - * ID of the device. The HID is either an 32-bit encoded EISAID - * Integer or a String. A string is always returned. An EISAID - * is converted to a string. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_HID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id) -{ - union acpi_operand_object *obj_desc; - struct acpica_device_id *hid; - u32 length; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_execute_HID); - - status = acpi_ut_evaluate_object(device_node, METHOD_NAME__HID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, - &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the size of the String to be returned, includes null terminator */ - - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - length = ACPI_EISAID_STRING_SIZE; - } else { - length = obj_desc->string.length + 1; - } - - /* Allocate a buffer for the HID */ - - hid = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + - (acpi_size) length); - if (!hid) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Area for the string starts after DEVICE_ID struct */ - - hid->string = ACPI_ADD_PTR(char, hid, sizeof(struct acpica_device_id)); - - /* Convert EISAID to a string or simply copy existing string */ - - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - acpi_ex_eisa_id_to_string(hid->string, obj_desc->integer.value); - } else { - acpi_ut_copy_id_string(hid->string, obj_desc->string.pointer); - } - - hid->length = length; - *return_id = hid; - -cleanup: - - /* On exit, we must delete the return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_UID - * - * PARAMETERS: device_node - Node for the device - * return_id - Where the string UID is returned - * - * RETURN: Status - * - * DESCRIPTION: Executes the _UID control method that returns the unique - * ID of the device. The UID is either a 64-bit Integer (NOT an - * EISAID) or a string. Always returns a string. A 64-bit integer - * is converted to a decimal string. - * - * NOTE: Internal function, no parameter validation - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_UID(struct acpi_namespace_node *device_node, - struct acpica_device_id **return_id) -{ - union acpi_operand_object *obj_desc; - struct acpica_device_id *uid; - u32 length; - acpi_status status; - - ACPI_FUNCTION_TRACE(ut_execute_UID); - - status = acpi_ut_evaluate_object(device_node, METHOD_NAME__UID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING, - &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* Get the size of the String to be returned, includes null terminator */ - - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - length = ACPI_MAX64_DECIMAL_DIGITS + 1; - } else { - length = obj_desc->string.length + 1; - } - - /* Allocate a buffer for the UID */ - - uid = - ACPI_ALLOCATE_ZEROED(sizeof(struct acpica_device_id) + - (acpi_size) length); - if (!uid) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Area for the string starts after DEVICE_ID struct */ - - uid->string = ACPI_ADD_PTR(char, uid, sizeof(struct acpica_device_id)); - - /* Convert an Integer to string, or just copy an existing string */ - - if (obj_desc->common.type == ACPI_TYPE_INTEGER) { - acpi_ex_integer_to_string(uid->string, obj_desc->integer.value); - } else { - acpi_ut_copy_id_string(uid->string, obj_desc->string.pointer); - } - - uid->length = length; - *return_id = uid; - -cleanup: - - /* On exit, we must delete the return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} - -/******************************************************************************* - * - * FUNCTION: acpi_ut_execute_CID - * - * PARAMETERS: device_node - Node for the device - * return_cid_list - Where the CID list is returned - * - * RETURN: Status, list of CID strings - * - * DESCRIPTION: Executes the _CID control method that returns one or more - * compatible hardware IDs for the device. - * - * NOTE: Internal function, no parameter validation - * - * A _CID method can return either a single compatible ID or a package of - * compatible IDs. Each compatible ID can be one of the following: - * 1) Integer (32 bit compressed EISA ID) or - * 2) String (PCI ID format, e.g. "PCI\VEN_vvvv&DEV_dddd&SUBSYS_ssssssss") - * - * The Integer CIDs are converted to string format by this function. - * - ******************************************************************************/ - -acpi_status -acpi_ut_execute_CID(struct acpi_namespace_node *device_node, - struct acpica_device_id_list **return_cid_list) -{ - union acpi_operand_object **cid_objects; - union acpi_operand_object *obj_desc; - struct acpica_device_id_list *cid_list; - char *next_id_string; - u32 string_area_size; - u32 length; - u32 cid_list_size; - acpi_status status; - u32 count; - u32 i; - - ACPI_FUNCTION_TRACE(ut_execute_CID); - - /* Evaluate the _CID method for this device */ - - status = acpi_ut_evaluate_object(device_node, METHOD_NAME__CID, - ACPI_BTYPE_INTEGER | ACPI_BTYPE_STRING - | ACPI_BTYPE_PACKAGE, &obj_desc); - if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); - } - - /* - * Get the count and size of the returned _CIDs. _CID can return either - * a Package of Integers/Strings or a single Integer or String. - * Note: This section also validates that all CID elements are of the - * correct type (Integer or String). - */ - if (obj_desc->common.type == ACPI_TYPE_PACKAGE) { - count = obj_desc->package.count; - cid_objects = obj_desc->package.elements; - } else { /* Single Integer or String CID */ - - count = 1; - cid_objects = &obj_desc; - } - - string_area_size = 0; - for (i = 0; i < count; i++) { - - /* String lengths include null terminator */ - - switch (cid_objects[i]->common.type) { - case ACPI_TYPE_INTEGER: - string_area_size += ACPI_EISAID_STRING_SIZE; - break; - - case ACPI_TYPE_STRING: - string_area_size += cid_objects[i]->string.length + 1; - break; - - default: - status = AE_TYPE; - goto cleanup; - } - } - - /* - * Now that we know the length of the CIDs, allocate return buffer: - * 1) Size of the base structure + - * 2) Size of the CID DEVICE_ID array + - * 3) Size of the actual CID strings - */ - cid_list_size = sizeof(struct acpica_device_id_list) + - ((count - 1) * sizeof(struct acpica_device_id)) + string_area_size; - - cid_list = ACPI_ALLOCATE_ZEROED(cid_list_size); - if (!cid_list) { - status = AE_NO_MEMORY; - goto cleanup; - } - - /* Area for CID strings starts after the CID DEVICE_ID array */ - - next_id_string = ACPI_CAST_PTR(char, cid_list->ids) + - ((acpi_size) count * sizeof(struct acpica_device_id)); - - /* Copy/convert the CIDs to the return buffer */ - - for (i = 0; i < count; i++) { - if (cid_objects[i]->common.type == ACPI_TYPE_INTEGER) { - - /* Convert the Integer (EISAID) CID to a string */ - - acpi_ex_eisa_id_to_string(next_id_string, - cid_objects[i]->integer. - value); - length = ACPI_EISAID_STRING_SIZE; - } else { /* ACPI_TYPE_STRING */ - - /* Copy the String CID from the returned object */ - - acpi_ut_copy_id_string(next_id_string, - cid_objects[i]->string.pointer); - length = cid_objects[i]->string.length + 1; - } - - cid_list->ids[i].string = next_id_string; - cid_list->ids[i].length = length; - next_id_string += length; - } - - /* Finish the CID list */ - - cid_list->count = count; - cid_list->list_size = cid_list_size; - *return_cid_list = cid_list; - -cleanup: - - /* On exit, we must delete the _CID return object */ - - acpi_ut_remove_reference(obj_desc); - return_ACPI_STATUS(status); -} diff --git a/trunk/drivers/acpi/acpica/utinit.c b/trunk/drivers/acpi/acpica/utinit.c index 9d0919ebf7b0..a54ca84eb362 100644 --- a/trunk/drivers/acpi/acpica/utinit.c +++ b/trunk/drivers/acpi/acpica/utinit.c @@ -99,19 +99,33 @@ static void acpi_ut_terminate(void) * * FUNCTION: acpi_ut_subsystem_shutdown * - * PARAMETERS: None + * PARAMETERS: none * - * RETURN: None + * RETURN: none * - * DESCRIPTION: Shutdown the various components. Do not delete the mutex - * objects here, because the AML debugger may be still running. + * DESCRIPTION: Shutdown the various subsystems. Don't delete the mutex + * objects here -- because the AML debugger may be still running. * ******************************************************************************/ void acpi_ut_subsystem_shutdown(void) { + ACPI_FUNCTION_TRACE(ut_subsystem_shutdown); + /* Just exit if subsystem is already shutdown */ + + if (acpi_gbl_shutdown) { + ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); + return_VOID; + } + + /* Subsystem appears active, go ahead and shut it down */ + + acpi_gbl_shutdown = TRUE; + acpi_gbl_startup_flags = 0; + ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); + #ifndef ACPI_ASL_COMPILER /* Close the acpi_event Handling */ diff --git a/trunk/drivers/acpi/acpica/utmisc.c b/trunk/drivers/acpi/acpica/utmisc.c index 61f6315fce9f..fbe782348b0b 100644 --- a/trunk/drivers/acpi/acpica/utmisc.c +++ b/trunk/drivers/acpi/acpica/utmisc.c @@ -50,11 +50,6 @@ #define _COMPONENT ACPI_UTILITIES ACPI_MODULE_NAME("utmisc") -/* - * Common suffix for messages - */ -#define ACPI_COMMON_MSG_SUFFIX \ - acpi_os_printf(" (%8.8X/%s-%u)\n", ACPI_CA_VERSION, module_name, line_number) /******************************************************************************* * * FUNCTION: acpi_ut_validate_exception @@ -123,34 +118,6 @@ const char *acpi_ut_validate_exception(acpi_status status) return (ACPI_CAST_PTR(const char, exception)); } -/******************************************************************************* - * - * FUNCTION: acpi_ut_is_pci_root_bridge - * - * PARAMETERS: Id - The HID/CID in string format - * - * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge - * - * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID. - * - ******************************************************************************/ - -u8 acpi_ut_is_pci_root_bridge(char *id) -{ - - /* - * Check if this is a PCI root bridge. - * ACPI 3.0+: check for a PCI Express root also. - */ - if (!(ACPI_STRCMP(id, - PCI_ROOT_HID_STRING)) || - !(ACPI_STRCMP(id, PCI_EXPRESS_ROOT_HID_STRING))) { - return (TRUE); - } - - return (FALSE); -} - /******************************************************************************* * * FUNCTION: acpi_ut_is_aml_table @@ -1070,7 +1037,8 @@ acpi_error(const char *module_name, u32 line_number, const char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); - ACPI_COMMON_MSG_SUFFIX; + acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name, + line_number); va_end(args); } @@ -1084,7 +1052,8 @@ acpi_exception(const char *module_name, va_start(args, format); acpi_os_vprintf(format, args); - ACPI_COMMON_MSG_SUFFIX; + acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name, + line_number); va_end(args); } @@ -1097,7 +1066,8 @@ acpi_warning(const char *module_name, u32 line_number, const char *format, ...) va_start(args, format); acpi_os_vprintf(format, args); - ACPI_COMMON_MSG_SUFFIX; + acpi_os_printf(" %8.8X %s-%u\n", ACPI_CA_VERSION, module_name, + line_number); va_end(args); } @@ -1118,46 +1088,3 @@ ACPI_EXPORT_SYMBOL(acpi_error) ACPI_EXPORT_SYMBOL(acpi_exception) ACPI_EXPORT_SYMBOL(acpi_warning) ACPI_EXPORT_SYMBOL(acpi_info) - -/******************************************************************************* - * - * FUNCTION: acpi_ut_predefined_warning - * - * PARAMETERS: module_name - Caller's module name (for error output) - * line_number - Caller's line number (for error output) - * Pathname - Full pathname to the node - * node_flags - From Namespace node for the method/object - * Format - Printf format string + additional args - * - * RETURN: None - * - * DESCRIPTION: Warnings for the predefined validation module. Messages are - * only emitted the first time a problem with a particular - * method/object is detected. This prevents a flood of error - * messages for methods that are repeatedly evaluated. - * -******************************************************************************/ - -void ACPI_INTERNAL_VAR_XFACE -acpi_ut_predefined_warning(const char *module_name, - u32 line_number, - char *pathname, - u8 node_flags, const char *format, ...) -{ - va_list args; - - /* - * Warning messages for this method/object will be disabled after the - * first time a validation fails or an object is successfully repaired. - */ - if (node_flags & ANOBJ_EVALUATED) { - return; - } - - acpi_os_printf("ACPI Warning for %s: ", pathname); - - va_start(args, format); - acpi_os_vprintf(format, args); - ACPI_COMMON_MSG_SUFFIX; - va_end(args); -} diff --git a/trunk/drivers/acpi/acpica/utxface.c b/trunk/drivers/acpi/acpica/utxface.c index b1f5f680bc78..078a22728c6b 100644 --- a/trunk/drivers/acpi/acpica/utxface.c +++ b/trunk/drivers/acpi/acpica/utxface.c @@ -250,16 +250,6 @@ acpi_status acpi_initialize_objects(u32 flags) } } - /* - * Execute any module-level code that was detected during the table load - * phase. Although illegal since ACPI 2.0, there are many machines that - * contain this type of code. Each block of detected executable AML code - * outside of any control method is wrapped with a temporary control - * method object and placed on a global list. The methods on this list - * are executed below. - */ - acpi_ns_exec_module_code_list(); - /* * Initialize the objects that remain uninitialized. This runs the * executable AML that may be part of the declaration of these objects: @@ -328,7 +318,7 @@ ACPI_EXPORT_SYMBOL(acpi_initialize_objects) * * RETURN: Status * - * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources. + * DESCRIPTION: Shutdown the ACPI subsystem. Release all resources. * ******************************************************************************/ acpi_status acpi_terminate(void) @@ -337,19 +327,6 @@ acpi_status acpi_terminate(void) ACPI_FUNCTION_TRACE(acpi_terminate); - /* Just exit if subsystem is already shutdown */ - - if (acpi_gbl_shutdown) { - ACPI_ERROR((AE_INFO, "ACPI Subsystem is already terminated")); - return_ACPI_STATUS(AE_OK); - } - - /* Subsystem appears active, go ahead and shut it down */ - - acpi_gbl_shutdown = TRUE; - acpi_gbl_startup_flags = 0; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Shutting down ACPI Subsystem\n")); - /* Terminate the AML Debugger if present */ ACPI_DEBUGGER_EXEC(acpi_gbl_db_terminate_threads = TRUE); @@ -376,7 +353,6 @@ acpi_status acpi_terminate(void) } ACPI_EXPORT_SYMBOL(acpi_terminate) - #ifndef ACPI_ASL_COMPILER #ifdef ACPI_FUTURE_USAGE /******************************************************************************* diff --git a/trunk/drivers/acpi/battery.c b/trunk/drivers/acpi/battery.c index 3f4602b8f287..58b4517ce712 100644 --- a/trunk/drivers/acpi/battery.c +++ b/trunk/drivers/acpi/battery.c @@ -31,7 +31,6 @@ #include #include #include -#include #ifdef CONFIG_ACPI_PROCFS_POWER #include @@ -46,8 +45,6 @@ #include #endif -#define PREFIX "ACPI: " - #define ACPI_BATTERY_VALUE_UNKNOWN 0xFFFFFFFF #define ACPI_BATTERY_CLASS "battery" @@ -88,10 +85,6 @@ static const struct acpi_device_id battery_device_ids[] = { MODULE_DEVICE_TABLE(acpi, battery_device_ids); -/* For buggy DSDTs that report negative 16-bit values for either charging - * or discharging current and/or report 0 as 65536 due to bad math. - */ -#define QUIRK_SIGNED16_CURRENT 0x0001 struct acpi_battery { struct mutex lock; @@ -119,7 +112,6 @@ struct acpi_battery { int state; int power_unit; u8 alarm_present; - long quirks; }; #define to_acpi_battery(x) container_of(x, struct acpi_battery, bat); @@ -398,11 +390,6 @@ static int acpi_battery_get_state(struct acpi_battery *battery) state_offsets, ARRAY_SIZE(state_offsets)); battery->update_time = jiffies; kfree(buffer.pointer); - - if ((battery->quirks & QUIRK_SIGNED16_CURRENT) && - battery->rate_now != -1) - battery->rate_now = abs((s16)battery->rate_now); - return result; } @@ -508,14 +495,6 @@ static void sysfs_remove_battery(struct acpi_battery *battery) } #endif -static void acpi_battery_quirks(struct acpi_battery *battery) -{ - battery->quirks = 0; - if (dmi_name_in_vendors("Acer") && battery->power_unit) { - battery->quirks |= QUIRK_SIGNED16_CURRENT; - } -} - static int acpi_battery_update(struct acpi_battery *battery) { int result, old_present = acpi_battery_present(battery); @@ -534,7 +513,6 @@ static int acpi_battery_update(struct acpi_battery *battery) result = acpi_battery_get_info(battery); if (result) return result; - acpi_battery_quirks(battery); acpi_battery_init_alarm(battery); } #ifdef CONFIG_ACPI_SYSFS_POWER diff --git a/trunk/drivers/acpi/blacklist.c b/trunk/drivers/acpi/blacklist.c index e56b2a7b53db..0c4ca4d318b3 100644 --- a/trunk/drivers/acpi/blacklist.c +++ b/trunk/drivers/acpi/blacklist.c @@ -34,8 +34,6 @@ #include #include -#include "internal.h" - enum acpi_blacklist_predicates { all_versions, less_than_or_equal, diff --git a/trunk/drivers/acpi/bus.c b/trunk/drivers/acpi/bus.c index 135fbfe1825c..2876fc70c3a9 100644 --- a/trunk/drivers/acpi/bus.c +++ b/trunk/drivers/acpi/bus.c @@ -38,7 +38,6 @@ #include #include #include -#include #include "internal.h" @@ -142,7 +141,7 @@ int acpi_bus_get_status(struct acpi_device *device) EXPORT_SYMBOL(acpi_bus_get_status); void acpi_bus_private_data_handler(acpi_handle handle, - void *context) + u32 function, void *context) { return; } diff --git a/trunk/drivers/acpi/button.c b/trunk/drivers/acpi/button.c index d295bdccc09c..9195deba9d94 100644 --- a/trunk/drivers/acpi/button.c +++ b/trunk/drivers/acpi/button.c @@ -33,8 +33,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_BUTTON_CLASS "button" #define ACPI_BUTTON_FILE_INFO "info" #define ACPI_BUTTON_FILE_STATE "state" diff --git a/trunk/drivers/acpi/cm_sbs.c b/trunk/drivers/acpi/cm_sbs.c index 6c9ee68e46fb..332fe4b21708 100644 --- a/trunk/drivers/acpi/cm_sbs.c +++ b/trunk/drivers/acpi/cm_sbs.c @@ -28,8 +28,6 @@ #include #include -#define PREFIX "ACPI: " - ACPI_MODULE_NAME("cm_sbs"); #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" diff --git a/trunk/drivers/acpi/container.c b/trunk/drivers/acpi/container.c index 642bb305cb65..fe0cdf83641a 100644 --- a/trunk/drivers/acpi/container.c +++ b/trunk/drivers/acpi/container.c @@ -35,8 +35,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_CONTAINER_DEVICE_NAME "ACPI container device" #define ACPI_CONTAINER_CLASS "container" @@ -202,17 +200,20 @@ container_walk_namespace_cb(acpi_handle handle, u32 lvl, void *context, void **rv) { char *hid = NULL; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_device_info *info; acpi_status status; int *action = context; - status = acpi_get_object_info(handle, &info); - if (ACPI_FAILURE(status)) { + + status = acpi_get_object_info(handle, &buffer); + if (ACPI_FAILURE(status) || !buffer.pointer) { return AE_OK; } + info = buffer.pointer; if (info->valid & ACPI_VALID_HID) - hid = info->hardware_id.string; + hid = info->hardware_id.value; if (hid == NULL) { goto end; @@ -239,7 +240,7 @@ container_walk_namespace_cb(acpi_handle handle, } end: - kfree(info); + kfree(buffer.pointer); return AE_OK; } diff --git a/trunk/drivers/acpi/debug.c b/trunk/drivers/acpi/debug.c index 8a690c3b8e23..a8287be0870e 100644 --- a/trunk/drivers/acpi/debug.c +++ b/trunk/drivers/acpi/debug.c @@ -3,7 +3,6 @@ */ #include -#include #include #include #include @@ -202,54 +201,72 @@ module_param_call(trace_state, param_set_trace_state, param_get_trace_state, #define ACPI_SYSTEM_FILE_DEBUG_LAYER "debug_layer" #define ACPI_SYSTEM_FILE_DEBUG_LEVEL "debug_level" -static int acpi_system_debug_proc_show(struct seq_file *m, void *v) +static int +acpi_system_read_debug(char *page, + char **start, off_t off, int count, int *eof, void *data) { + char *p = page; + int size = 0; unsigned int i; - seq_printf(m, "%-25s\tHex SET\n", "Description"); + if (off != 0) + goto end; - switch ((unsigned long)m->private) { + p += sprintf(p, "%-25s\tHex SET\n", "Description"); + + switch ((unsigned long)data) { case 0: for (i = 0; i < ARRAY_SIZE(acpi_debug_layers); i++) { - seq_printf(m, "%-25s\t0x%08lX [%c]\n", + p += sprintf(p, "%-25s\t0x%08lX [%c]\n", acpi_debug_layers[i].name, acpi_debug_layers[i].value, (acpi_dbg_layer & acpi_debug_layers[i]. value) ? '*' : ' '); } - seq_printf(m, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", + p += sprintf(p, "%-25s\t0x%08X [%c]\n", "ACPI_ALL_DRIVERS", ACPI_ALL_DRIVERS, (acpi_dbg_layer & ACPI_ALL_DRIVERS) == ACPI_ALL_DRIVERS ? '*' : (acpi_dbg_layer & ACPI_ALL_DRIVERS) == 0 ? ' ' : '-'); - seq_printf(m, + p += sprintf(p, "--\ndebug_layer = 0x%08X (* = enabled, - = partial)\n", acpi_dbg_layer); break; case 1: for (i = 0; i < ARRAY_SIZE(acpi_debug_levels); i++) { - seq_printf(m, "%-25s\t0x%08lX [%c]\n", + p += sprintf(p, "%-25s\t0x%08lX [%c]\n", acpi_debug_levels[i].name, acpi_debug_levels[i].value, (acpi_dbg_level & acpi_debug_levels[i]. value) ? '*' : ' '); } - seq_printf(m, "--\ndebug_level = 0x%08X (* = enabled)\n", + p += sprintf(p, "--\ndebug_level = 0x%08X (* = enabled)\n", acpi_dbg_level); break; + default: + p += sprintf(p, "Invalid debug option\n"); + break; } - return 0; -} -static int acpi_system_debug_proc_open(struct inode *inode, struct file *file) -{ - return single_open(file, acpi_system_debug_proc_show, PDE(inode)->data); + end: + size = (p - page); + if (size <= off + count) + *eof = 1; + *start = page + off; + size -= off; + if (size > count) + size = count; + if (size < 0) + size = 0; + + return size; } -static ssize_t acpi_system_debug_proc_write(struct file *file, +static int +acpi_system_write_debug(struct file *file, const char __user * buffer, - size_t count, loff_t *pos) + unsigned long count, void *data) { char debug_string[12] = { '\0' }; @@ -262,7 +279,7 @@ static ssize_t acpi_system_debug_proc_write(struct file *file, debug_string[count] = '\0'; - switch ((unsigned long)PDE(file->f_path.dentry->d_inode)->data) { + switch ((unsigned long)data) { case 0: acpi_dbg_layer = simple_strtoul(debug_string, NULL, 0); break; @@ -275,15 +292,6 @@ static ssize_t acpi_system_debug_proc_write(struct file *file, return count; } - -static const struct file_operations acpi_system_debug_proc_fops = { - .owner = THIS_MODULE, - .open = acpi_system_debug_proc_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, - .write = acpi_system_debug_proc_write, -}; #endif int __init acpi_debug_init(void) @@ -295,18 +303,24 @@ int __init acpi_debug_init(void) /* 'debug_layer' [R/W] */ name = ACPI_SYSTEM_FILE_DEBUG_LAYER; - entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_debug_proc_fops, - (void *)0); - if (!entry) + entry = + create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, + acpi_root_dir, acpi_system_read_debug, + (void *)0); + if (entry) + entry->write_proc = acpi_system_write_debug; + else goto Error; /* 'debug_level' [R/W] */ name = ACPI_SYSTEM_FILE_DEBUG_LEVEL; - entry = proc_create_data(name, S_IFREG | S_IRUGO | S_IWUSR, - acpi_root_dir, &acpi_system_debug_proc_fops, - (void *)1); - if (!entry) + entry = + create_proc_read_entry(name, S_IFREG | S_IRUGO | S_IWUSR, + acpi_root_dir, acpi_system_read_debug, + (void *)1); + if (entry) + entry->write_proc = acpi_system_write_debug; + else goto Error; Done: diff --git a/trunk/drivers/acpi/dock.c b/trunk/drivers/acpi/dock.c index 3a2cfefc71ab..efb959d6c8a9 100644 --- a/trunk/drivers/acpi/dock.c +++ b/trunk/drivers/acpi/dock.c @@ -33,8 +33,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_DOCK_DRIVER_DESCRIPTION "ACPI Dock Station Driver" ACPI_MODULE_NAME("dock"); @@ -233,16 +231,18 @@ static int is_ata(acpi_handle handle) static int is_battery(acpi_handle handle) { struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; int ret = 1; - if (!ACPI_SUCCESS(acpi_get_object_info(handle, &info))) + if (!ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) return 0; + info = buffer.pointer; if (!(info->valid & ACPI_VALID_HID)) ret = 0; else - ret = !strcmp("PNP0C0A", info->hardware_id.string); + ret = !strcmp("PNP0C0A", info->hardware_id.value); - kfree(info); + kfree(buffer.pointer); return ret; } diff --git a/trunk/drivers/acpi/ec.c b/trunk/drivers/acpi/ec.c index f70796081c4c..391f331674c7 100644 --- a/trunk/drivers/acpi/ec.c +++ b/trunk/drivers/acpi/ec.c @@ -42,12 +42,12 @@ #include #include #include -#include #define ACPI_EC_CLASS "embedded_controller" #define ACPI_EC_DEVICE_NAME "Embedded Controller" #define ACPI_EC_FILE_INFO "info" +#undef PREFIX #define PREFIX "ACPI: EC: " /* EC status register */ @@ -68,13 +68,15 @@ enum ec_command { #define ACPI_EC_DELAY 500 /* Wait 500ms max. during EC ops */ #define ACPI_EC_UDELAY_GLK 1000 /* Wait 1ms max. to get global lock */ #define ACPI_EC_CDELAY 10 /* Wait 10us before polling EC */ -#define ACPI_EC_MSI_UDELAY 550 /* Wait 550us for MSI EC */ #define ACPI_EC_STORM_THRESHOLD 8 /* number of false interrupts per one transaction */ enum { EC_FLAGS_QUERY_PENDING, /* Query is pending */ + EC_FLAGS_GPE_MODE, /* Expect GPE to be sent + * for status change */ + EC_FLAGS_NO_GPE, /* Don't use GPE mode */ EC_FLAGS_GPE_STORM, /* GPE storm detected */ EC_FLAGS_HANDLERS_INSTALLED /* Handlers for GPE and * OpReg are installed */ @@ -168,7 +170,7 @@ static void start_transaction(struct acpi_ec *ec) acpi_ec_write_cmd(ec, ec->curr->command); } -static void advance_transaction(struct acpi_ec *ec, u8 status) +static void gpe_transaction(struct acpi_ec *ec, u8 status) { unsigned long flags; spin_lock_irqsave(&ec->curr_lock, flags); @@ -199,6 +201,29 @@ static void advance_transaction(struct acpi_ec *ec, u8 status) spin_unlock_irqrestore(&ec->curr_lock, flags); } +static int acpi_ec_wait(struct acpi_ec *ec) +{ + if (wait_event_timeout(ec->wait, ec_transaction_done(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + /* try restart command if we get any false interrupts */ + if (ec->curr->irq_count && + (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF) == 0) { + pr_debug(PREFIX "controller reset, restart transaction\n"); + start_transaction(ec); + if (wait_event_timeout(ec->wait, ec_transaction_done(ec), + msecs_to_jiffies(ACPI_EC_DELAY))) + return 0; + } + /* missing GPEs, switch back to poll mode */ + if (printk_ratelimit()) + pr_info(PREFIX "missing confirmations, " + "switch off interrupt mode.\n"); + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); + return 1; +} + static void acpi_ec_gpe_query(void *ec_cxt); static int ec_check_sci(struct acpi_ec *ec, u8 state) @@ -211,51 +236,43 @@ static int ec_check_sci(struct acpi_ec *ec, u8 state) return 0; } +static void ec_delay(void) +{ + /* EC in MSI notebooks don't tolerate delays other than 550 usec */ + if (EC_FLAGS_MSI) + udelay(ACPI_EC_DELAY); + else + /* Use shortest sleep available */ + msleep(1); +} + static int ec_poll(struct acpi_ec *ec) { - unsigned long flags; - int repeat = 2; /* number of command restarts */ - while (repeat--) { - unsigned long delay = jiffies + - msecs_to_jiffies(ACPI_EC_DELAY); - do { - /* don't sleep with disabled interrupts */ - if (EC_FLAGS_MSI || irqs_disabled()) { - udelay(ACPI_EC_MSI_UDELAY); - if (ec_transaction_done(ec)) - return 0; - } else { - if (wait_event_timeout(ec->wait, - ec_transaction_done(ec), - msecs_to_jiffies(1))) - return 0; - } - advance_transaction(ec, acpi_ec_read_status(ec)); - } while (time_before(jiffies, delay)); - if (!ec->curr->irq_count || - (acpi_ec_read_status(ec) & ACPI_EC_FLAG_IBF)) - break; - /* try restart command if we get any false interrupts */ - pr_debug(PREFIX "controller reset, restart transaction\n"); - spin_lock_irqsave(&ec->curr_lock, flags); - start_transaction(ec); - spin_unlock_irqrestore(&ec->curr_lock, flags); + unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); + udelay(ACPI_EC_CDELAY); + while (time_before(jiffies, delay)) { + gpe_transaction(ec, acpi_ec_read_status(ec)); + ec_delay(); + if (ec_transaction_done(ec)) + return 0; } return -ETIME; } static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, - struct transaction *t) + struct transaction *t, + int force_poll) { unsigned long tmp; int ret = 0; pr_debug(PREFIX "transaction start\n"); /* disable GPE during transaction if storm is detected */ if (test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); acpi_disable_gpe(NULL, ec->gpe); } if (EC_FLAGS_MSI) - udelay(ACPI_EC_MSI_UDELAY); + udelay(ACPI_EC_DELAY); /* start transaction */ spin_lock_irqsave(&ec->curr_lock, tmp); /* following two actions should be kept atomic */ @@ -264,7 +281,11 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, if (ec->curr->command == ACPI_EC_COMMAND_QUERY) clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); spin_unlock_irqrestore(&ec->curr_lock, tmp); - ret = ec_poll(ec); + /* if we selected poll mode or failed in GPE-mode do a poll loop */ + if (force_poll || + !test_bit(EC_FLAGS_GPE_MODE, &ec->flags) || + acpi_ec_wait(ec)) + ret = ec_poll(ec); pr_debug(PREFIX "transaction end\n"); spin_lock_irqsave(&ec->curr_lock, tmp); ec->curr = NULL; @@ -274,7 +295,8 @@ static int acpi_ec_transaction_unlocked(struct acpi_ec *ec, ec_check_sci(ec, acpi_ec_read_status(ec)); /* it is safe to enable GPE outside of transaction */ acpi_enable_gpe(NULL, ec->gpe); - } else if (t->irq_count > ACPI_EC_STORM_THRESHOLD) { + } else if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + t->irq_count > ACPI_EC_STORM_THRESHOLD) { pr_info(PREFIX "GPE storm detected, " "transactions will use polling mode\n"); set_bit(EC_FLAGS_GPE_STORM, &ec->flags); @@ -292,14 +314,16 @@ static int ec_wait_ibf0(struct acpi_ec *ec) { unsigned long delay = jiffies + msecs_to_jiffies(ACPI_EC_DELAY); /* interrupt wait manually if GPE mode is not active */ + unsigned long timeout = test_bit(EC_FLAGS_GPE_MODE, &ec->flags) ? + msecs_to_jiffies(ACPI_EC_DELAY) : msecs_to_jiffies(1); while (time_before(jiffies, delay)) - if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), - msecs_to_jiffies(1))) + if (wait_event_timeout(ec->wait, ec_check_ibf0(ec), timeout)) return 0; return -ETIME; } -static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) +static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t, + int force_poll) { int status; u32 glk; @@ -321,7 +345,7 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) status = -ETIME; goto end; } - status = acpi_ec_transaction_unlocked(ec, t); + status = acpi_ec_transaction_unlocked(ec, t, force_poll); end: if (ec->global_lock) acpi_release_global_lock(glk); @@ -330,6 +354,10 @@ static int acpi_ec_transaction(struct acpi_ec *ec, struct transaction *t) return status; } +/* + * Note: samsung nv5000 doesn't work with ec burst mode. + * http://bugzilla.kernel.org/show_bug.cgi?id=4980 + */ static int acpi_ec_burst_enable(struct acpi_ec *ec) { u8 d; @@ -337,7 +365,7 @@ static int acpi_ec_burst_enable(struct acpi_ec *ec) .wdata = NULL, .rdata = &d, .wlen = 0, .rlen = 1}; - return acpi_ec_transaction(ec, &t); + return acpi_ec_transaction(ec, &t, 0); } static int acpi_ec_burst_disable(struct acpi_ec *ec) @@ -347,7 +375,7 @@ static int acpi_ec_burst_disable(struct acpi_ec *ec) .wlen = 0, .rlen = 0}; return (acpi_ec_read_status(ec) & ACPI_EC_FLAG_BURST) ? - acpi_ec_transaction(ec, &t) : 0; + acpi_ec_transaction(ec, &t, 0) : 0; } static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) @@ -358,7 +386,7 @@ static int acpi_ec_read(struct acpi_ec *ec, u8 address, u8 * data) .wdata = &address, .rdata = &d, .wlen = 1, .rlen = 1}; - result = acpi_ec_transaction(ec, &t); + result = acpi_ec_transaction(ec, &t, 0); *data = d; return result; } @@ -370,7 +398,7 @@ static int acpi_ec_write(struct acpi_ec *ec, u8 address, u8 data) .wdata = wdata, .rdata = NULL, .wlen = 2, .rlen = 0}; - return acpi_ec_transaction(ec, &t); + return acpi_ec_transaction(ec, &t, 0); } /* @@ -438,7 +466,7 @@ int ec_transaction(u8 command, if (!first_ec) return -ENODEV; - return acpi_ec_transaction(first_ec, &t); + return acpi_ec_transaction(first_ec, &t, force_poll); } EXPORT_SYMBOL(ec_transaction); @@ -459,7 +487,7 @@ static int acpi_ec_query(struct acpi_ec *ec, u8 * data) * bit to be cleared (and thus clearing the interrupt source). */ - result = acpi_ec_transaction(ec, &t); + result = acpi_ec_transaction(ec, &t, 0); if (result) return result; @@ -542,10 +570,28 @@ static u32 acpi_ec_gpe_handler(void *data) pr_debug(PREFIX "~~~> interrupt\n"); status = acpi_ec_read_status(ec); - advance_transaction(ec, status); - if (ec_transaction_done(ec) && (status & ACPI_EC_FLAG_IBF) == 0) - wake_up(&ec->wait); + if (test_bit(EC_FLAGS_GPE_MODE, &ec->flags)) { + gpe_transaction(ec, status); + if (ec_transaction_done(ec) && + (status & ACPI_EC_FLAG_IBF) == 0) + wake_up(&ec->wait); + } + ec_check_sci(ec, status); + if (!test_bit(EC_FLAGS_GPE_MODE, &ec->flags) && + !test_bit(EC_FLAGS_NO_GPE, &ec->flags)) { + /* this is non-query, must be confirmation */ + if (!test_bit(EC_FLAGS_GPE_STORM, &ec->flags)) { + if (printk_ratelimit()) + pr_info(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); + } else { + /* hush, STORM switches the mode every transaction */ + pr_debug(PREFIX "non-query interrupt received," + " switching to interrupt mode\n"); + } + set_bit(EC_FLAGS_GPE_MODE, &ec->flags); + } return ACPI_INTERRUPT_HANDLED; } @@ -571,8 +617,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, if (bits != 8 && acpi_strict) return AE_BAD_PARAMETER; - if (EC_FLAGS_MSI) - acpi_ec_burst_enable(ec); + acpi_ec_burst_enable(ec); if (function == ACPI_READ) { result = acpi_ec_read(ec, address, &temp); @@ -593,8 +638,7 @@ acpi_ec_space_handler(u32 function, acpi_physical_address address, } } - if (EC_FLAGS_MSI) - acpi_ec_burst_disable(ec); + acpi_ec_burst_disable(ec); switch (result) { case -EINVAL: @@ -744,42 +788,6 @@ ec_parse_device(acpi_handle handle, u32 Level, void *context, void **retval) return AE_CTRL_TERMINATE; } -static int ec_install_handlers(struct acpi_ec *ec) -{ - acpi_status status; - if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) - return 0; - status = acpi_install_gpe_handler(NULL, ec->gpe, - ACPI_GPE_EDGE_TRIGGERED, - &acpi_ec_gpe_handler, ec); - if (ACPI_FAILURE(status)) - return -ENODEV; - acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); - acpi_enable_gpe(NULL, ec->gpe); - status = acpi_install_address_space_handler(ec->handle, - ACPI_ADR_SPACE_EC, - &acpi_ec_space_handler, - NULL, ec); - if (ACPI_FAILURE(status)) { - if (status == AE_NOT_FOUND) { - /* - * Maybe OS fails in evaluating the _REG object. - * The AE_NOT_FOUND error will be ignored and OS - * continue to initialize EC. - */ - printk(KERN_ERR "Fail in evaluating the _REG object" - " of EC device. Broken bios is suspected.\n"); - } else { - acpi_remove_gpe_handler(NULL, ec->gpe, - &acpi_ec_gpe_handler); - return -ENODEV; - } - } - - set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); - return 0; -} - static void ec_remove_handlers(struct acpi_ec *ec) { if (ACPI_FAILURE(acpi_remove_address_space_handler(ec->handle, @@ -794,8 +802,9 @@ static void ec_remove_handlers(struct acpi_ec *ec) static int acpi_ec_add(struct acpi_device *device) { struct acpi_ec *ec = NULL; - int ret; + if (!device) + return -EINVAL; strcpy(acpi_device_name(device), ACPI_EC_DEVICE_NAME); strcpy(acpi_device_class(device), ACPI_EC_CLASS); @@ -828,12 +837,9 @@ static int acpi_ec_add(struct acpi_device *device) acpi_ec_add_fs(device); pr_info(PREFIX "GPE = 0x%lx, I/O: command/status = 0x%lx, data = 0x%lx\n", ec->gpe, ec->command_addr, ec->data_addr); - - ret = ec_install_handlers(ec); - - /* EC is fully operational, allow queries */ - clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); - return ret; + pr_info(PREFIX "driver started in %s mode\n", + (test_bit(EC_FLAGS_GPE_MODE, &ec->flags))?"interrupt":"poll"); + return 0; } static int acpi_ec_remove(struct acpi_device *device, int type) @@ -845,7 +851,6 @@ static int acpi_ec_remove(struct acpi_device *device, int type) return -EINVAL; ec = acpi_driver_data(device); - ec_remove_handlers(ec); mutex_lock(&ec->lock); list_for_each_entry_safe(handler, tmp, &ec->list, node) { list_del(&handler->node); @@ -883,6 +888,75 @@ ec_parse_io_ports(struct acpi_resource *resource, void *context) return AE_OK; } +static int ec_install_handlers(struct acpi_ec *ec) +{ + acpi_status status; + if (test_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags)) + return 0; + status = acpi_install_gpe_handler(NULL, ec->gpe, + ACPI_GPE_EDGE_TRIGGERED, + &acpi_ec_gpe_handler, ec); + if (ACPI_FAILURE(status)) + return -ENODEV; + acpi_set_gpe_type(NULL, ec->gpe, ACPI_GPE_TYPE_RUNTIME); + acpi_enable_gpe(NULL, ec->gpe); + status = acpi_install_address_space_handler(ec->handle, + ACPI_ADR_SPACE_EC, + &acpi_ec_space_handler, + NULL, ec); + if (ACPI_FAILURE(status)) { + if (status == AE_NOT_FOUND) { + /* + * Maybe OS fails in evaluating the _REG object. + * The AE_NOT_FOUND error will be ignored and OS + * continue to initialize EC. + */ + printk(KERN_ERR "Fail in evaluating the _REG object" + " of EC device. Broken bios is suspected.\n"); + } else { + acpi_remove_gpe_handler(NULL, ec->gpe, + &acpi_ec_gpe_handler); + return -ENODEV; + } + } + + set_bit(EC_FLAGS_HANDLERS_INSTALLED, &ec->flags); + return 0; +} + +static int acpi_ec_start(struct acpi_device *device) +{ + struct acpi_ec *ec; + int ret = 0; + + if (!device) + return -EINVAL; + + ec = acpi_driver_data(device); + + if (!ec) + return -EINVAL; + + ret = ec_install_handlers(ec); + + /* EC is fully operational, allow queries */ + clear_bit(EC_FLAGS_QUERY_PENDING, &ec->flags); + return ret; +} + +static int acpi_ec_stop(struct acpi_device *device, int type) +{ + struct acpi_ec *ec; + if (!device) + return -EINVAL; + ec = acpi_driver_data(device); + if (!ec) + return -EINVAL; + ec_remove_handlers(ec); + + return 0; +} + int __init acpi_boot_ec_enable(void) { if (!boot_ec || test_bit(EC_FLAGS_HANDLERS_INSTALLED, &boot_ec->flags)) @@ -980,6 +1054,8 @@ static int acpi_ec_suspend(struct acpi_device *device, pm_message_t state) { struct acpi_ec *ec = acpi_driver_data(device); /* Stop using GPE */ + set_bit(EC_FLAGS_NO_GPE, &ec->flags); + clear_bit(EC_FLAGS_GPE_MODE, &ec->flags); acpi_disable_gpe(NULL, ec->gpe); return 0; } @@ -988,6 +1064,8 @@ static int acpi_ec_resume(struct acpi_device *device) { struct acpi_ec *ec = acpi_driver_data(device); /* Enable use of GPE back */ + clear_bit(EC_FLAGS_NO_GPE, &ec->flags); + set_bit(EC_FLAGS_GPE_MODE, &ec->flags); acpi_enable_gpe(NULL, ec->gpe); return 0; } @@ -999,6 +1077,8 @@ static struct acpi_driver acpi_ec_driver = { .ops = { .add = acpi_ec_add, .remove = acpi_ec_remove, + .start = acpi_ec_start, + .stop = acpi_ec_stop, .suspend = acpi_ec_suspend, .resume = acpi_ec_resume, }, diff --git a/trunk/drivers/acpi/event.c b/trunk/drivers/acpi/event.c index c511071bfd79..aeb7e5fb4a04 100644 --- a/trunk/drivers/acpi/event.c +++ b/trunk/drivers/acpi/event.c @@ -14,8 +14,6 @@ #include #include -#include "internal.h" - #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("event"); diff --git a/trunk/drivers/acpi/fan.c b/trunk/drivers/acpi/fan.c index f419849a0d3f..53698ea08371 100644 --- a/trunk/drivers/acpi/fan.c +++ b/trunk/drivers/acpi/fan.c @@ -34,8 +34,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_FAN_CLASS "fan" #define ACPI_FAN_FILE_STATE "state" diff --git a/trunk/drivers/acpi/glue.c b/trunk/drivers/acpi/glue.c index c6645f26224b..a8a5c29958c8 100644 --- a/trunk/drivers/acpi/glue.c +++ b/trunk/drivers/acpi/glue.c @@ -12,8 +12,6 @@ #include #include -#include "internal.h" - #define ACPI_GLUE_DEBUG 0 #if ACPI_GLUE_DEBUG #define DBG(x...) printk(PREFIX x) @@ -95,13 +93,15 @@ do_acpi_find_child(acpi_handle handle, u32 lvl, void *context, void **rv) { acpi_status status; struct acpi_device_info *info; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; struct acpi_find_child *find = context; - status = acpi_get_object_info(handle, &info); + status = acpi_get_object_info(handle, &buffer); if (ACPI_SUCCESS(status)) { + info = buffer.pointer; if (info->address == find->address) find->handle = handle; - kfree(info); + kfree(buffer.pointer); } return AE_OK; } @@ -121,7 +121,7 @@ EXPORT_SYMBOL(acpi_get_child); /* Link ACPI devices with physical devices */ static void acpi_glue_data_handler(acpi_handle handle, - void *context) + u32 function, void *context) { /* we provide an empty handler */ } diff --git a/trunk/drivers/acpi/internal.h b/trunk/drivers/acpi/internal.h index 074cf8682d52..11a69b53004e 100644 --- a/trunk/drivers/acpi/internal.h +++ b/trunk/drivers/acpi/internal.h @@ -1,24 +1,4 @@ -/* - * acpi/internal.h - * For use by Linux/ACPI infrastructure, not drivers - * - * Copyright (c) 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope 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. - */ - -#define PREFIX "ACPI: " +/* For use by Linux/ACPI infrastructure, not drivers */ int init_acpi_device_notify(void); int acpi_scan_init(void); diff --git a/trunk/drivers/acpi/numa.c b/trunk/drivers/acpi/numa.c index 202dd0c976a3..d440ccd27d91 100644 --- a/trunk/drivers/acpi/numa.c +++ b/trunk/drivers/acpi/numa.c @@ -30,8 +30,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_NUMA 0x80000000 #define _COMPONENT ACPI_NUMA ACPI_MODULE_NAME("numa"); diff --git a/trunk/drivers/acpi/osl.c b/trunk/drivers/acpi/osl.c index 56071b67bed5..5691f165a952 100644 --- a/trunk/drivers/acpi/osl.c +++ b/trunk/drivers/acpi/osl.c @@ -58,7 +58,6 @@ struct acpi_os_dpc { acpi_osd_exec_callback function; void *context; struct work_struct work; - int wait; }; #ifdef CONFIG_ACPI_CUSTOM_DSDT @@ -89,7 +88,6 @@ struct acpi_res_list { char name[5]; /* only can have a length of 4 chars, make use of this one instead of res->name, no need to kalloc then */ struct list_head resource_list; - int count; }; static LIST_HEAD(resource_list_head); @@ -699,12 +697,31 @@ void acpi_os_derive_pci_id(acpi_handle rhandle, /* upper bound */ static void acpi_os_execute_deferred(struct work_struct *work) { struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); + if (!dpc) { + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; + } + + dpc->function(dpc->context); + kfree(dpc); + + return; +} + +static void acpi_os_execute_hp_deferred(struct work_struct *work) +{ + struct acpi_os_dpc *dpc = container_of(work, struct acpi_os_dpc, work); + if (!dpc) { + printk(KERN_ERR PREFIX "Invalid (NULL) context\n"); + return; + } - if (dpc->wait) - acpi_os_wait_events_complete(NULL); + acpi_os_wait_events_complete(NULL); dpc->function(dpc->context); kfree(dpc); + + return; } /******************************************************************************* @@ -728,11 +745,15 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, acpi_status status = AE_OK; struct acpi_os_dpc *dpc; struct workqueue_struct *queue; + work_func_t func; int ret; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Scheduling function [%p(%p)] for deferred execution.\n", function, context)); + if (!function) + return AE_BAD_PARAMETER; + /* * Allocate/initialize DPC structure. Note that this memory will be * freed by the callee. The kernel handles the work_struct list in a @@ -757,8 +778,8 @@ static acpi_status __acpi_os_execute(acpi_execute_type type, */ queue = hp ? kacpi_hotplug_wq : (type == OSL_NOTIFY_HANDLER ? kacpi_notify_wq : kacpid_wq); - dpc->wait = hp ? 1 : 0; - INIT_WORK(&dpc->work, acpi_os_execute_deferred); + func = hp ? acpi_os_execute_hp_deferred : acpi_os_execute_deferred; + INIT_WORK(&dpc->work, func); ret = queue_work(queue, &dpc->work); if (!ret) { @@ -1337,89 +1358,6 @@ acpi_os_validate_interface (char *interface) return AE_SUPPORT; } -static inline int acpi_res_list_add(struct acpi_res_list *res) -{ - struct acpi_res_list *res_list_elem; - - list_for_each_entry(res_list_elem, &resource_list_head, - resource_list) { - - if (res->resource_type == res_list_elem->resource_type && - res->start == res_list_elem->start && - res->end == res_list_elem->end) { - - /* - * The Region(addr,len) already exist in the list, - * just increase the count - */ - - res_list_elem->count++; - return 0; - } - } - - res->count = 1; - list_add(&res->resource_list, &resource_list_head); - return 1; -} - -static inline void acpi_res_list_del(struct acpi_res_list *res) -{ - struct acpi_res_list *res_list_elem; - - list_for_each_entry(res_list_elem, &resource_list_head, - resource_list) { - - if (res->resource_type == res_list_elem->resource_type && - res->start == res_list_elem->start && - res->end == res_list_elem->end) { - - /* - * If the res count is decreased to 0, - * remove and free it - */ - - if (--res_list_elem->count == 0) { - list_del(&res_list_elem->resource_list); - kfree(res_list_elem); - } - return; - } - } -} - -acpi_status -acpi_os_invalidate_address( - u8 space_id, - acpi_physical_address address, - acpi_size length) -{ - struct acpi_res_list res; - - switch (space_id) { - case ACPI_ADR_SPACE_SYSTEM_IO: - case ACPI_ADR_SPACE_SYSTEM_MEMORY: - /* Only interference checks against SystemIO and SytemMemory - are needed */ - res.start = address; - res.end = address + length - 1; - res.resource_type = space_id; - spin_lock(&acpi_res_lock); - acpi_res_list_del(&res); - spin_unlock(&acpi_res_lock); - break; - case ACPI_ADR_SPACE_PCI_CONFIG: - case ACPI_ADR_SPACE_EC: - case ACPI_ADR_SPACE_SMBUS: - case ACPI_ADR_SPACE_CMOS: - case ACPI_ADR_SPACE_PCI_BAR_TARGET: - case ACPI_ADR_SPACE_DATA_TABLE: - case ACPI_ADR_SPACE_FIXED_HARDWARE: - break; - } - return AE_OK; -} - /****************************************************************************** * * FUNCTION: acpi_os_validate_address @@ -1444,7 +1382,6 @@ acpi_os_validate_address ( char *name) { struct acpi_res_list *res; - int added; if (acpi_enforce_resources == ENFORCE_RESOURCES_NO) return AE_OK; @@ -1462,17 +1399,14 @@ acpi_os_validate_address ( res->end = address + length - 1; res->resource_type = space_id; spin_lock(&acpi_res_lock); - added = acpi_res_list_add(res); + list_add(&res->resource_list, &resource_list_head); spin_unlock(&acpi_res_lock); - pr_debug("%s %s resource: start: 0x%llx, end: 0x%llx, " - "name: %s\n", added ? "Added" : "Already exist", - (space_id == ACPI_ADR_SPACE_SYSTEM_IO) + pr_debug("Added %s resource: start: 0x%llx, end: 0x%llx, " + "name: %s\n", (space_id == ACPI_ADR_SPACE_SYSTEM_IO) ? "SystemIO" : "System Memory", (unsigned long long)res->start, (unsigned long long)res->end, res->name); - if (!added) - kfree(res); break; case ACPI_ADR_SPACE_PCI_CONFIG: case ACPI_ADR_SPACE_EC: diff --git a/trunk/drivers/acpi/pci_irq.c b/trunk/drivers/acpi/pci_irq.c index 843699ed93f2..b794eb88ab90 100644 --- a/trunk/drivers/acpi/pci_irq.c +++ b/trunk/drivers/acpi/pci_irq.c @@ -40,8 +40,6 @@ #include #include -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_irq"); diff --git a/trunk/drivers/acpi/pci_link.c b/trunk/drivers/acpi/pci_link.c index 394ae89409c2..16e0f9d3d17c 100644 --- a/trunk/drivers/acpi/pci_link.c +++ b/trunk/drivers/acpi/pci_link.c @@ -43,8 +43,6 @@ #include #include -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_link"); #define ACPI_PCI_LINK_CLASS "pci_irq_routing" diff --git a/trunk/drivers/acpi/pci_root.c b/trunk/drivers/acpi/pci_root.c index 31122214e0ec..31b961c2f22f 100644 --- a/trunk/drivers/acpi/pci_root.c +++ b/trunk/drivers/acpi/pci_root.c @@ -36,8 +36,6 @@ #include #include -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_PCI_COMPONENT ACPI_MODULE_NAME("pci_root"); #define ACPI_PCI_ROOT_CLASS "pci_bridge" diff --git a/trunk/drivers/acpi/pci_slot.c b/trunk/drivers/acpi/pci_slot.c index 45da2bae36c8..12158e0d009b 100644 --- a/trunk/drivers/acpi/pci_slot.c +++ b/trunk/drivers/acpi/pci_slot.c @@ -31,7 +31,6 @@ #include #include #include -#include static int debug; static int check_sta_before_sun; @@ -58,7 +57,7 @@ ACPI_MODULE_NAME("pci_slot"); MY_NAME , ## arg); \ } while (0) -#define SLOT_NAME_SIZE 21 /* Inspired by #define in acpiphp.h */ +#define SLOT_NAME_SIZE 20 /* Inspired by #define in acpiphp.h */ struct acpi_pci_slot { acpi_handle root_handle; /* handle of the root bridge */ @@ -150,7 +149,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) return AE_OK; } - snprintf(name, sizeof(name), "%llu", sun); + snprintf(name, sizeof(name), "%u", (u32)sun); pci_slot = pci_create_slot(pci_bus, device, name, NULL); if (IS_ERR(pci_slot)) { err("pci_create_slot returned %ld\n", PTR_ERR(pci_slot)); diff --git a/trunk/drivers/acpi/power.c b/trunk/drivers/acpi/power.c index 22b297916519..5a09bf392ec1 100644 --- a/trunk/drivers/acpi/power.c +++ b/trunk/drivers/acpi/power.c @@ -43,9 +43,8 @@ #include #include #include -#include "sleep.h" -#define PREFIX "ACPI: " +#include "sleep.h" #define _COMPONENT ACPI_POWER_COMPONENT ACPI_MODULE_NAME("power"); diff --git a/trunk/drivers/acpi/power_meter.c b/trunk/drivers/acpi/power_meter.c deleted file mode 100644 index e6bfd77986b8..000000000000 --- a/trunk/drivers/acpi/power_meter.c +++ /dev/null @@ -1,1018 +0,0 @@ -/* - * A hwmon driver for ACPI 4.0 power meters - * Copyright (C) 2009 IBM - * - * Author: Darrick J. Wong - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define ACPI_POWER_METER_NAME "power_meter" -ACPI_MODULE_NAME(ACPI_POWER_METER_NAME); -#define ACPI_POWER_METER_DEVICE_NAME "Power Meter" -#define ACPI_POWER_METER_CLASS "power_meter_resource" - -#define NUM_SENSORS 17 - -#define POWER_METER_CAN_MEASURE (1 << 0) -#define POWER_METER_CAN_TRIP (1 << 1) -#define POWER_METER_CAN_CAP (1 << 2) -#define POWER_METER_CAN_NOTIFY (1 << 3) -#define POWER_METER_IS_BATTERY (1 << 8) -#define UNKNOWN_HYSTERESIS 0xFFFFFFFF - -#define METER_NOTIFY_CONFIG 0x80 -#define METER_NOTIFY_TRIP 0x81 -#define METER_NOTIFY_CAP 0x82 -#define METER_NOTIFY_CAPPING 0x83 -#define METER_NOTIFY_INTERVAL 0x84 - -#define POWER_AVERAGE_NAME "power1_average" -#define POWER_CAP_NAME "power1_cap" -#define POWER_AVG_INTERVAL_NAME "power1_average_interval" -#define POWER_ALARM_NAME "power1_alarm" - -static int cap_in_hardware; -static int force_cap_on; - -static int can_cap_in_hardware(void) -{ - return force_cap_on || cap_in_hardware; -} - -static struct acpi_device_id power_meter_ids[] = { - {"ACPI000D", 0}, - {"", 0}, -}; -MODULE_DEVICE_TABLE(acpi, power_meter_ids); - -struct acpi_power_meter_capabilities { - acpi_integer flags; - acpi_integer units; - acpi_integer type; - acpi_integer accuracy; - acpi_integer sampling_time; - acpi_integer min_avg_interval; - acpi_integer max_avg_interval; - acpi_integer hysteresis; - acpi_integer configurable_cap; - acpi_integer min_cap; - acpi_integer max_cap; -}; - -struct acpi_power_meter_resource { - struct acpi_device *acpi_dev; - acpi_bus_id name; - struct mutex lock; - struct device *hwmon_dev; - struct acpi_power_meter_capabilities caps; - acpi_string model_number; - acpi_string serial_number; - acpi_string oem_info; - acpi_integer power; - acpi_integer cap; - acpi_integer avg_interval; - int sensors_valid; - unsigned long sensors_last_updated; - struct sensor_device_attribute sensors[NUM_SENSORS]; - int num_sensors; - int trip[2]; - int num_domain_devices; - struct acpi_device **domain_devices; - struct kobject *holders_dir; -}; - -struct ro_sensor_template { - char *label; - ssize_t (*show)(struct device *dev, - struct device_attribute *devattr, - char *buf); - int index; -}; - -struct rw_sensor_template { - char *label; - ssize_t (*show)(struct device *dev, - struct device_attribute *devattr, - char *buf); - ssize_t (*set)(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count); - int index; -}; - -/* Averaging interval */ -static int update_avg_interval(struct acpi_power_meter_resource *resource) -{ - unsigned long long data; - acpi_status status; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GAI", - NULL, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GAI")); - return -ENODEV; - } - - resource->avg_interval = data; - return 0; -} - -static ssize_t show_avg_interval(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - - mutex_lock(&resource->lock); - update_avg_interval(resource); - mutex_unlock(&resource->lock); - - return sprintf(buf, "%llu\n", resource->avg_interval); -} - -static ssize_t set_avg_interval(struct device *dev, - struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; - int res; - unsigned long temp; - unsigned long long data; - acpi_status status; - - res = strict_strtoul(buf, 10, &temp); - if (res) - return res; - - if (temp > resource->caps.max_avg_interval || - temp < resource->caps.min_avg_interval) - return -EINVAL; - arg0.integer.value = temp; - - mutex_lock(&resource->lock); - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PAI", - &args, &data); - if (!ACPI_FAILURE(status)) - resource->avg_interval = temp; - mutex_unlock(&resource->lock); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PAI")); - return -EINVAL; - } - - /* _PAI returns 0 on success, nonzero otherwise */ - if (data) - return -EINVAL; - - return count; -} - -/* Cap functions */ -static int update_cap(struct acpi_power_meter_resource *resource) -{ - unsigned long long data; - acpi_status status; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_GHL", - NULL, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _GHL")); - return -ENODEV; - } - - resource->cap = data; - return 0; -} - -static ssize_t show_cap(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - - mutex_lock(&resource->lock); - update_cap(resource); - mutex_unlock(&resource->lock); - - return sprintf(buf, "%llu\n", resource->cap * 1000); -} - -static ssize_t set_cap(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - union acpi_object arg0 = { ACPI_TYPE_INTEGER }; - struct acpi_object_list args = { 1, &arg0 }; - int res; - unsigned long temp; - unsigned long long data; - acpi_status status; - - res = strict_strtoul(buf, 10, &temp); - if (res) - return res; - - temp /= 1000; - if (temp > resource->caps.max_cap || temp < resource->caps.min_cap) - return -EINVAL; - arg0.integer.value = temp; - - mutex_lock(&resource->lock); - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_SHL", - &args, &data); - if (!ACPI_FAILURE(status)) - resource->cap = temp; - mutex_unlock(&resource->lock); - - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _SHL")); - return -EINVAL; - } - - /* _SHL returns 0 on success, nonzero otherwise */ - if (data) - return -EINVAL; - - return count; -} - -/* Power meter trip points */ -static int set_acpi_trip(struct acpi_power_meter_resource *resource) -{ - union acpi_object arg_objs[] = { - {ACPI_TYPE_INTEGER}, - {ACPI_TYPE_INTEGER} - }; - struct acpi_object_list args = { 2, arg_objs }; - unsigned long long data; - acpi_status status; - - /* Both trip levels must be set */ - if (resource->trip[0] < 0 || resource->trip[1] < 0) - return 0; - - /* This driver stores min, max; ACPI wants max, min. */ - arg_objs[0].integer.value = resource->trip[1]; - arg_objs[1].integer.value = resource->trip[0]; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PTP", - &args, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTP")); - return -EINVAL; - } - - return data; -} - -static ssize_t set_trip(struct device *dev, struct device_attribute *devattr, - const char *buf, size_t count) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - int res; - unsigned long temp; - - res = strict_strtoul(buf, 10, &temp); - if (res) - return res; - - temp /= 1000; - if (temp < 0) - return -EINVAL; - - mutex_lock(&resource->lock); - resource->trip[attr->index - 7] = temp; - res = set_acpi_trip(resource); - mutex_unlock(&resource->lock); - - if (res) - return res; - - return count; -} - -/* Power meter */ -static int update_meter(struct acpi_power_meter_resource *resource) -{ - unsigned long long data; - acpi_status status; - unsigned long local_jiffies = jiffies; - - if (time_before(local_jiffies, resource->sensors_last_updated + - msecs_to_jiffies(resource->caps.sampling_time)) && - resource->sensors_valid) - return 0; - - status = acpi_evaluate_integer(resource->acpi_dev->handle, "_PMM", - NULL, &data); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMM")); - return -ENODEV; - } - - resource->power = data; - resource->sensors_valid = 1; - resource->sensors_last_updated = jiffies; - return 0; -} - -static ssize_t show_power(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - - mutex_lock(&resource->lock); - update_meter(resource); - mutex_unlock(&resource->lock); - - return sprintf(buf, "%llu\n", resource->power * 1000); -} - -/* Miscellaneous */ -static ssize_t show_str(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - acpi_string val; - - switch (attr->index) { - case 0: - val = resource->model_number; - break; - case 1: - val = resource->serial_number; - break; - case 2: - val = resource->oem_info; - break; - default: - BUG(); - } - - return sprintf(buf, "%s\n", val); -} - -static ssize_t show_val(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr); - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - acpi_integer val = 0; - - switch (attr->index) { - case 0: - val = resource->caps.min_avg_interval; - break; - case 1: - val = resource->caps.max_avg_interval; - break; - case 2: - val = resource->caps.min_cap * 1000; - break; - case 3: - val = resource->caps.max_cap * 1000; - break; - case 4: - if (resource->caps.hysteresis == UNKNOWN_HYSTERESIS) - return sprintf(buf, "unknown\n"); - - val = resource->caps.hysteresis * 1000; - break; - case 5: - if (resource->caps.flags & POWER_METER_IS_BATTERY) - val = 1; - else - val = 0; - break; - case 6: - if (resource->power > resource->cap) - val = 1; - else - val = 0; - break; - case 7: - case 8: - if (resource->trip[attr->index - 7] < 0) - return sprintf(buf, "unknown\n"); - - val = resource->trip[attr->index - 7] * 1000; - break; - default: - BUG(); - } - - return sprintf(buf, "%llu\n", val); -} - -static ssize_t show_accuracy(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - struct acpi_device *acpi_dev = to_acpi_device(dev); - struct acpi_power_meter_resource *resource = acpi_dev->driver_data; - unsigned int acc = resource->caps.accuracy; - - return sprintf(buf, "%u.%u%%\n", acc / 1000, acc % 1000); -} - -static ssize_t show_name(struct device *dev, - struct device_attribute *devattr, - char *buf) -{ - return sprintf(buf, "%s\n", ACPI_POWER_METER_NAME); -} - -/* Sensor descriptions. If you add a sensor, update NUM_SENSORS above! */ -static struct ro_sensor_template meter_ro_attrs[] = { -{POWER_AVERAGE_NAME, show_power, 0}, -{"power1_accuracy", show_accuracy, 0}, -{"power1_average_interval_min", show_val, 0}, -{"power1_average_interval_max", show_val, 1}, -{"power1_is_battery", show_val, 5}, -{NULL, NULL, 0}, -}; - -static struct rw_sensor_template meter_rw_attrs[] = { -{POWER_AVG_INTERVAL_NAME, show_avg_interval, set_avg_interval, 0}, -{NULL, NULL, NULL, 0}, -}; - -static struct ro_sensor_template misc_cap_attrs[] = { -{"power1_cap_min", show_val, 2}, -{"power1_cap_max", show_val, 3}, -{"power1_cap_hyst", show_val, 4}, -{POWER_ALARM_NAME, show_val, 6}, -{NULL, NULL, 0}, -}; - -static struct ro_sensor_template ro_cap_attrs[] = { -{POWER_CAP_NAME, show_cap, 0}, -{NULL, NULL, 0}, -}; - -static struct rw_sensor_template rw_cap_attrs[] = { -{POWER_CAP_NAME, show_cap, set_cap, 0}, -{NULL, NULL, NULL, 0}, -}; - -static struct rw_sensor_template trip_attrs[] = { -{"power1_average_min", show_val, set_trip, 7}, -{"power1_average_max", show_val, set_trip, 8}, -{NULL, NULL, NULL, 0}, -}; - -static struct ro_sensor_template misc_attrs[] = { -{"name", show_name, 0}, -{"power1_model_number", show_str, 0}, -{"power1_oem_info", show_str, 2}, -{"power1_serial_number", show_str, 1}, -{NULL, NULL, 0}, -}; - -/* Read power domain data */ -static void remove_domain_devices(struct acpi_power_meter_resource *resource) -{ - int i; - - if (!resource->num_domain_devices) - return; - - for (i = 0; i < resource->num_domain_devices; i++) { - struct acpi_device *obj = resource->domain_devices[i]; - if (!obj) - continue; - - sysfs_remove_link(resource->holders_dir, - kobject_name(&obj->dev.kobj)); - put_device(&obj->dev); - } - - kfree(resource->domain_devices); - kobject_put(resource->holders_dir); -} - -static int read_domain_devices(struct acpi_power_meter_resource *resource) -{ - int res = 0; - int i; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *pss; - acpi_status status; - - status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMD", NULL, - &buffer); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMD")); - return -ENODEV; - } - - pss = buffer.pointer; - if (!pss || - pss->type != ACPI_TYPE_PACKAGE) { - dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME - "Invalid _PMD data\n"); - res = -EFAULT; - goto end; - } - - if (!pss->package.count) - goto end; - - resource->domain_devices = kzalloc(sizeof(struct acpi_device *) * - pss->package.count, GFP_KERNEL); - if (!resource->domain_devices) { - res = -ENOMEM; - goto end; - } - - resource->holders_dir = kobject_create_and_add("measures", - &resource->acpi_dev->dev.kobj); - if (!resource->holders_dir) { - res = -ENOMEM; - goto exit_free; - } - - resource->num_domain_devices = pss->package.count; - - for (i = 0; i < pss->package.count; i++) { - struct acpi_device *obj; - union acpi_object *element = &(pss->package.elements[i]); - - /* Refuse non-references */ - if (element->type != ACPI_TYPE_LOCAL_REFERENCE) - continue; - - /* Create a symlink to domain objects */ - resource->domain_devices[i] = NULL; - status = acpi_bus_get_device(element->reference.handle, - &resource->domain_devices[i]); - if (ACPI_FAILURE(status)) - continue; - - obj = resource->domain_devices[i]; - get_device(&obj->dev); - - res = sysfs_create_link(resource->holders_dir, &obj->dev.kobj, - kobject_name(&obj->dev.kobj)); - if (res) { - put_device(&obj->dev); - resource->domain_devices[i] = NULL; - } - } - - res = 0; - goto end; - -exit_free: - kfree(resource->domain_devices); -end: - kfree(buffer.pointer); - return res; -} - -/* Registration and deregistration */ -static int register_ro_attrs(struct acpi_power_meter_resource *resource, - struct ro_sensor_template *ro) -{ - struct device *dev = &resource->acpi_dev->dev; - struct sensor_device_attribute *sensors = - &resource->sensors[resource->num_sensors]; - int res = 0; - - while (ro->label) { - sensors->dev_attr.attr.name = ro->label; - sensors->dev_attr.attr.mode = S_IRUGO; - sensors->dev_attr.show = ro->show; - sensors->index = ro->index; - - res = device_create_file(dev, &sensors->dev_attr); - if (res) { - sensors->dev_attr.attr.name = NULL; - goto error; - } - sensors++; - resource->num_sensors++; - ro++; - } - -error: - return res; -} - -static int register_rw_attrs(struct acpi_power_meter_resource *resource, - struct rw_sensor_template *rw) -{ - struct device *dev = &resource->acpi_dev->dev; - struct sensor_device_attribute *sensors = - &resource->sensors[resource->num_sensors]; - int res = 0; - - while (rw->label) { - sensors->dev_attr.attr.name = rw->label; - sensors->dev_attr.attr.mode = S_IRUGO | S_IWUSR; - sensors->dev_attr.show = rw->show; - sensors->dev_attr.store = rw->set; - sensors->index = rw->index; - - res = device_create_file(dev, &sensors->dev_attr); - if (res) { - sensors->dev_attr.attr.name = NULL; - goto error; - } - sensors++; - resource->num_sensors++; - rw++; - } - -error: - return res; -} - -static void remove_attrs(struct acpi_power_meter_resource *resource) -{ - int i; - - for (i = 0; i < resource->num_sensors; i++) { - if (!resource->sensors[i].dev_attr.attr.name) - continue; - device_remove_file(&resource->acpi_dev->dev, - &resource->sensors[i].dev_attr); - } - - remove_domain_devices(resource); - - resource->num_sensors = 0; -} - -static int setup_attrs(struct acpi_power_meter_resource *resource) -{ - int res = 0; - - res = read_domain_devices(resource); - if (res) - return res; - - if (resource->caps.flags & POWER_METER_CAN_MEASURE) { - res = register_ro_attrs(resource, meter_ro_attrs); - if (res) - goto error; - res = register_rw_attrs(resource, meter_rw_attrs); - if (res) - goto error; - } - - if (resource->caps.flags & POWER_METER_CAN_CAP) { - if (!can_cap_in_hardware()) { - dev_err(&resource->acpi_dev->dev, - "Ignoring unsafe software power cap!\n"); - goto skip_unsafe_cap; - } - - if (resource->caps.configurable_cap) { - res = register_rw_attrs(resource, rw_cap_attrs); - if (res) - goto error; - } else { - res = register_ro_attrs(resource, ro_cap_attrs); - if (res) - goto error; - } - res = register_ro_attrs(resource, misc_cap_attrs); - if (res) - goto error; - } -skip_unsafe_cap: - - if (resource->caps.flags & POWER_METER_CAN_TRIP) { - res = register_rw_attrs(resource, trip_attrs); - if (res) - goto error; - } - - res = register_ro_attrs(resource, misc_attrs); - if (res) - goto error; - - return res; -error: - remove_domain_devices(resource); - remove_attrs(resource); - return res; -} - -static void free_capabilities(struct acpi_power_meter_resource *resource) -{ - acpi_string *str; - int i; - - str = &resource->model_number; - for (i = 0; i < 3; i++, str++) - kfree(*str); -} - -static int read_capabilities(struct acpi_power_meter_resource *resource) -{ - int res = 0; - int i; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - struct acpi_buffer state = { 0, NULL }; - struct acpi_buffer format = { sizeof("NNNNNNNNNNN"), "NNNNNNNNNNN" }; - union acpi_object *pss; - acpi_string *str; - acpi_status status; - - status = acpi_evaluate_object(resource->acpi_dev->handle, "_PMC", NULL, - &buffer); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PMC")); - return -ENODEV; - } - - pss = buffer.pointer; - if (!pss || - pss->type != ACPI_TYPE_PACKAGE || - pss->package.count != 14) { - dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME - "Invalid _PMC data\n"); - res = -EFAULT; - goto end; - } - - /* Grab all the integer data at once */ - state.length = sizeof(struct acpi_power_meter_capabilities); - state.pointer = &resource->caps; - - status = acpi_extract_package(pss, &format, &state); - if (ACPI_FAILURE(status)) { - ACPI_EXCEPTION((AE_INFO, status, "Invalid data")); - res = -EFAULT; - goto end; - } - - if (resource->caps.units) { - dev_err(&resource->acpi_dev->dev, ACPI_POWER_METER_NAME - "Unknown units %llu.\n", - resource->caps.units); - res = -EINVAL; - goto end; - } - - /* Grab the string data */ - str = &resource->model_number; - - for (i = 11; i < 14; i++) { - union acpi_object *element = &(pss->package.elements[i]); - - if (element->type != ACPI_TYPE_STRING) { - res = -EINVAL; - goto error; - } - - *str = kzalloc(sizeof(u8) * (element->string.length + 1), - GFP_KERNEL); - if (!*str) { - res = -ENOMEM; - goto error; - } - - strncpy(*str, element->string.pointer, element->string.length); - str++; - } - - dev_info(&resource->acpi_dev->dev, "Found ACPI power meter.\n"); - goto end; -error: - str = &resource->model_number; - for (i = 0; i < 3; i++, str++) - kfree(*str); -end: - kfree(buffer.pointer); - return res; -} - -/* Handle ACPI event notifications */ -static void acpi_power_meter_notify(struct acpi_device *device, u32 event) -{ - struct acpi_power_meter_resource *resource; - int res; - - if (!device || !acpi_driver_data(device)) - return; - - resource = acpi_driver_data(device); - - mutex_lock(&resource->lock); - switch (event) { - case METER_NOTIFY_CONFIG: - free_capabilities(resource); - res = read_capabilities(resource); - if (res) - break; - - remove_attrs(resource); - setup_attrs(resource); - break; - case METER_NOTIFY_TRIP: - sysfs_notify(&device->dev.kobj, NULL, POWER_AVERAGE_NAME); - update_meter(resource); - break; - case METER_NOTIFY_CAP: - sysfs_notify(&device->dev.kobj, NULL, POWER_CAP_NAME); - update_cap(resource); - break; - case METER_NOTIFY_INTERVAL: - sysfs_notify(&device->dev.kobj, NULL, POWER_AVG_INTERVAL_NAME); - update_avg_interval(resource); - break; - case METER_NOTIFY_CAPPING: - sysfs_notify(&device->dev.kobj, NULL, POWER_ALARM_NAME); - dev_info(&device->dev, "Capping in progress.\n"); - break; - default: - BUG(); - } - mutex_unlock(&resource->lock); - - acpi_bus_generate_netlink_event(ACPI_POWER_METER_CLASS, - dev_name(&device->dev), event, 0); -} - -static int acpi_power_meter_add(struct acpi_device *device) -{ - int res; - struct acpi_power_meter_resource *resource; - - if (!device) - return -EINVAL; - - resource = kzalloc(sizeof(struct acpi_power_meter_resource), - GFP_KERNEL); - if (!resource) - return -ENOMEM; - - resource->sensors_valid = 0; - resource->acpi_dev = device; - mutex_init(&resource->lock); - strcpy(acpi_device_name(device), ACPI_POWER_METER_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_POWER_METER_CLASS); - device->driver_data = resource; - - free_capabilities(resource); - res = read_capabilities(resource); - if (res) - goto exit_free; - - resource->trip[0] = resource->trip[1] = -1; - - res = setup_attrs(resource); - if (res) - goto exit_free; - - resource->hwmon_dev = hwmon_device_register(&device->dev); - if (IS_ERR(resource->hwmon_dev)) { - res = PTR_ERR(resource->hwmon_dev); - goto exit_remove; - } - - res = 0; - goto exit; - -exit_remove: - remove_attrs(resource); -exit_free: - kfree(resource); -exit: - return res; -} - -static int acpi_power_meter_remove(struct acpi_device *device, int type) -{ - struct acpi_power_meter_resource *resource; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - resource = acpi_driver_data(device); - hwmon_device_unregister(resource->hwmon_dev); - - free_capabilities(resource); - remove_attrs(resource); - - kfree(resource); - return 0; -} - -static int acpi_power_meter_resume(struct acpi_device *device) -{ - struct acpi_power_meter_resource *resource; - - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - resource = acpi_driver_data(device); - free_capabilities(resource); - read_capabilities(resource); - - return 0; -} - -static struct acpi_driver acpi_power_meter_driver = { - .name = "power_meter", - .class = ACPI_POWER_METER_CLASS, - .ids = power_meter_ids, - .ops = { - .add = acpi_power_meter_add, - .remove = acpi_power_meter_remove, - .resume = acpi_power_meter_resume, - .notify = acpi_power_meter_notify, - }, -}; - -/* Module init/exit routines */ -static int __init enable_cap_knobs(const struct dmi_system_id *d) -{ - cap_in_hardware = 1; - return 0; -} - -static struct dmi_system_id __initdata pm_dmi_table[] = { - { - enable_cap_knobs, "IBM Active Energy Manager", - { - DMI_MATCH(DMI_SYS_VENDOR, "IBM") - }, - }, - {} -}; - -static int __init acpi_power_meter_init(void) -{ - int result; - - if (acpi_disabled) - return -ENODEV; - - dmi_check_system(pm_dmi_table); - - result = acpi_bus_register_driver(&acpi_power_meter_driver); - if (result < 0) - return -ENODEV; - - return 0; -} - -static void __exit acpi_power_meter_exit(void) -{ - acpi_bus_unregister_driver(&acpi_power_meter_driver); -} - -MODULE_AUTHOR("Darrick J. Wong "); -MODULE_DESCRIPTION("ACPI 4.0 power meter driver"); -MODULE_LICENSE("GPL"); - -module_param(force_cap_on, bool, 0644); -MODULE_PARM_DESC(force_cap_on, "Enable power cap even it is unsafe to do so."); - -module_init(acpi_power_meter_init); -module_exit(acpi_power_meter_exit); diff --git a/trunk/drivers/acpi/processor_core.c b/trunk/drivers/acpi/processor_core.c index c2d4d6e09364..2cc4b3033872 100644 --- a/trunk/drivers/acpi/processor_core.c +++ b/trunk/drivers/acpi/processor_core.c @@ -59,8 +59,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_DEVICE_NAME "Processor" #define ACPI_PROCESSOR_FILE_INFO "info" @@ -81,10 +79,9 @@ MODULE_DESCRIPTION("ACPI Processor Driver"); MODULE_LICENSE("GPL"); static int acpi_processor_add(struct acpi_device *device); +static int acpi_processor_start(struct acpi_device *device); static int acpi_processor_remove(struct acpi_device *device, int type); -#ifdef CONFIG_ACPI_PROCFS static int acpi_processor_info_open_fs(struct inode *inode, struct file *file); -#endif static void acpi_processor_notify(struct acpi_device *device, u32 event); static acpi_status acpi_processor_hotadd_init(acpi_handle handle, int *p_cpu); static int acpi_processor_handle_eject(struct acpi_processor *pr); @@ -104,6 +101,7 @@ static struct acpi_driver acpi_processor_driver = { .ops = { .add = acpi_processor_add, .remove = acpi_processor_remove, + .start = acpi_processor_start, .suspend = acpi_processor_suspend, .resume = acpi_processor_resume, .notify = acpi_processor_notify, @@ -112,7 +110,7 @@ static struct acpi_driver acpi_processor_driver = { #define INSTALL_NOTIFY_HANDLER 1 #define UNINSTALL_NOTIFY_HANDLER 2 -#ifdef CONFIG_ACPI_PROCFS + static const struct file_operations acpi_processor_info_fops = { .owner = THIS_MODULE, .open = acpi_processor_info_open_fs, @@ -120,7 +118,6 @@ static const struct file_operations acpi_processor_info_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif DEFINE_PER_CPU(struct acpi_processor *, processors); struct acpi_processor_errata errata __read_mostly; @@ -319,7 +316,6 @@ static int acpi_processor_set_pdc(struct acpi_processor *pr) FS Interface (/proc) -------------------------------------------------------------------------- */ -#ifdef CONFIG_ACPI_PROCFS static struct proc_dir_entry *acpi_processor_dir = NULL; static int acpi_processor_info_seq_show(struct seq_file *seq, void *offset) @@ -392,6 +388,7 @@ static int acpi_processor_add_fs(struct acpi_device *device) return -EIO; return 0; } + static int acpi_processor_remove_fs(struct acpi_device *device) { @@ -408,16 +405,6 @@ static int acpi_processor_remove_fs(struct acpi_device *device) return 0; } -#else -static inline int acpi_processor_add_fs(struct acpi_device *device) -{ - return 0; -} -static inline int acpi_processor_remove_fs(struct acpi_device *device) -{ - return 0; -} -#endif /* Use the acpiid in MADT to map cpus in case of SMP */ @@ -711,6 +698,92 @@ static int acpi_processor_get_info(struct acpi_device *device) static DEFINE_PER_CPU(void *, processor_device_array); +static int __cpuinit acpi_processor_start(struct acpi_device *device) +{ + int result = 0; + struct acpi_processor *pr; + struct sys_device *sysdev; + + pr = acpi_driver_data(device); + + result = acpi_processor_get_info(device); + if (result) { + /* Processor is physically not present */ + return 0; + } + + BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); + + /* + * Buggy BIOS check + * ACPI id of processors can be reported wrongly by the BIOS. + * Don't trust it blindly + */ + if (per_cpu(processor_device_array, pr->id) != NULL && + per_cpu(processor_device_array, pr->id) != device) { + printk(KERN_WARNING "BIOS reported wrong ACPI id " + "for the processor\n"); + return -ENODEV; + } + per_cpu(processor_device_array, pr->id) = device; + + per_cpu(processors, pr->id) = pr; + + result = acpi_processor_add_fs(device); + if (result) + goto end; + + sysdev = get_cpu_sysdev(pr->id); + if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) + return -EFAULT; + + /* _PDC call should be done before doing anything else (if reqd.). */ + arch_acpi_processor_init_pdc(pr); + acpi_processor_set_pdc(pr); + arch_acpi_processor_cleanup_pdc(pr); + +#ifdef CONFIG_CPU_FREQ + acpi_processor_ppc_has_changed(pr); +#endif + acpi_processor_get_throttling_info(pr); + acpi_processor_get_limit_info(pr); + + + acpi_processor_power_init(pr, device); + + pr->cdev = thermal_cooling_device_register("Processor", device, + &processor_cooling_ops); + if (IS_ERR(pr->cdev)) { + result = PTR_ERR(pr->cdev); + goto end; + } + + dev_info(&device->dev, "registered as cooling_device%d\n", + pr->cdev->id); + + result = sysfs_create_link(&device->dev.kobj, + &pr->cdev->device.kobj, + "thermal_cooling"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + result = sysfs_create_link(&pr->cdev->device.kobj, + &device->dev.kobj, + "device"); + if (result) + printk(KERN_ERR PREFIX "Create sysfs link\n"); + + if (pr->flags.throttling) { + printk(KERN_INFO PREFIX "%s [%s] (supports", + acpi_device_name(device), acpi_device_bid(device)); + printk(" %d throttling states", pr->throttling.state_count); + printk(")\n"); + } + + end: + + return result; +} + static void acpi_processor_notify(struct acpi_device *device, u32 event) { struct acpi_processor *pr = acpi_driver_data(device); @@ -773,8 +846,10 @@ static struct notifier_block acpi_cpu_notifier = static int acpi_processor_add(struct acpi_device *device) { struct acpi_processor *pr = NULL; - int result = 0; - struct sys_device *sysdev; + + + if (!device) + return -EINVAL; pr = kzalloc(sizeof(struct acpi_processor), GFP_KERNEL); if (!pr) @@ -790,100 +865,7 @@ static int acpi_processor_add(struct acpi_device *device) strcpy(acpi_device_class(device), ACPI_PROCESSOR_CLASS); device->driver_data = pr; - result = acpi_processor_get_info(device); - if (result) { - /* Processor is physically not present */ - return 0; - } - - BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); - - /* - * Buggy BIOS check - * ACPI id of processors can be reported wrongly by the BIOS. - * Don't trust it blindly - */ - if (per_cpu(processor_device_array, pr->id) != NULL && - per_cpu(processor_device_array, pr->id) != device) { - printk(KERN_WARNING "BIOS reported wrong ACPI id " - "for the processor\n"); - result = -ENODEV; - goto err_free_cpumask; - } - per_cpu(processor_device_array, pr->id) = device; - - per_cpu(processors, pr->id) = pr; - - result = acpi_processor_add_fs(device); - if (result) - goto err_free_cpumask; - - sysdev = get_cpu_sysdev(pr->id); - if (sysfs_create_link(&device->dev.kobj, &sysdev->kobj, "sysdev")) { - result = -EFAULT; - goto err_remove_fs; - } - - /* _PDC call should be done before doing anything else (if reqd.). */ - arch_acpi_processor_init_pdc(pr); - acpi_processor_set_pdc(pr); - arch_acpi_processor_cleanup_pdc(pr); - -#ifdef CONFIG_CPU_FREQ - acpi_processor_ppc_has_changed(pr); -#endif - acpi_processor_get_throttling_info(pr); - acpi_processor_get_limit_info(pr); - - - acpi_processor_power_init(pr, device); - - pr->cdev = thermal_cooling_device_register("Processor", device, - &processor_cooling_ops); - if (IS_ERR(pr->cdev)) { - result = PTR_ERR(pr->cdev); - goto err_power_exit; - } - - dev_info(&device->dev, "registered as cooling_device%d\n", - pr->cdev->id); - - result = sysfs_create_link(&device->dev.kobj, - &pr->cdev->device.kobj, - "thermal_cooling"); - if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); - goto err_thermal_unregister; - } - result = sysfs_create_link(&pr->cdev->device.kobj, - &device->dev.kobj, - "device"); - if (result) { - printk(KERN_ERR PREFIX "Create sysfs link\n"); - goto err_remove_sysfs; - } - - if (pr->flags.throttling) { - printk(KERN_INFO PREFIX "%s [%s] (supports", - acpi_device_name(device), acpi_device_bid(device)); - printk(" %d throttling states", pr->throttling.state_count); - printk(")\n"); - } - return 0; - -err_remove_sysfs: - sysfs_remove_link(&device->dev.kobj, "thermal_cooling"); -err_thermal_unregister: - thermal_cooling_device_unregister(pr->cdev); -err_power_exit: - acpi_processor_power_exit(pr, device); -err_remove_fs: - acpi_processor_remove_fs(device); -err_free_cpumask: - free_cpumask_var(pr->throttling.shared_cpu_map); - - return result; } static int acpi_processor_remove(struct acpi_device *device, int type) @@ -960,6 +942,7 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) { acpi_handle phandle; struct acpi_device *pdev; + struct acpi_processor *pr; if (acpi_get_parent(handle, &phandle)) { @@ -974,6 +957,15 @@ int acpi_processor_device_add(acpi_handle handle, struct acpi_device **device) return -ENODEV; } + acpi_bus_start(*device); + + pr = acpi_driver_data(*device); + if (!pr) + return -ENODEV; + + if ((pr->id >= 0) && (pr->id < nr_cpu_ids)) { + kobject_uevent(&(*device)->dev.kobj, KOBJ_ONLINE); + } return 0; } @@ -1003,6 +995,25 @@ static void __ref acpi_processor_hotplug_notify(acpi_handle handle, "Unable to add the device\n"); break; } + + pr = acpi_driver_data(device); + if (!pr) { + printk(KERN_ERR PREFIX "Driver data is NULL\n"); + break; + } + + if (pr->id >= 0 && (pr->id < nr_cpu_ids)) { + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); + break; + } + + result = acpi_processor_start(device); + if ((!result) && ((pr->id >= 0) && (pr->id < nr_cpu_ids))) { + kobject_uevent(&device->dev.kobj, KOBJ_ONLINE); + } else { + printk(KERN_ERR PREFIX "Device [%s] failed to start\n", + acpi_device_bid(device)); + } break; case ACPI_NOTIFY_EJECT_REQUEST: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -1019,6 +1030,9 @@ static void __ref acpi_processor_hotplug_notify(acpi_handle handle, "Driver data is NULL, dropping EJECT\n"); return; } + + if ((pr->id < nr_cpu_ids) && (cpu_present(pr->id))) + kobject_uevent(&device->dev.kobj, KOBJ_OFFLINE); break; default: ACPI_DEBUG_PRINT((ACPI_DB_INFO, @@ -1147,11 +1161,11 @@ static int __init acpi_processor_init(void) (struct acpi_table_header **)&madt))) madt = NULL; #endif -#ifdef CONFIG_ACPI_PROCFS + acpi_processor_dir = proc_mkdir(ACPI_PROCESSOR_CLASS, acpi_root_dir); if (!acpi_processor_dir) return -ENOMEM; -#endif + /* * Check whether the system is DMI table. If yes, OSPM * should not use mwait for CPU-states. @@ -1179,9 +1193,7 @@ static int __init acpi_processor_init(void) cpuidle_unregister_driver(&acpi_idle_driver); out_proc: -#ifdef CONFIG_ACPI_PROCFS remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); -#endif return result; } @@ -1201,9 +1213,7 @@ static void __exit acpi_processor_exit(void) cpuidle_unregister_driver(&acpi_idle_driver); -#ifdef CONFIG_ACPI_PROCFS remove_proc_entry(ACPI_PROCESSOR_CLASS, acpi_root_dir); -#endif return; } diff --git a/trunk/drivers/acpi/processor_idle.c b/trunk/drivers/acpi/processor_idle.c index cc61a6220102..66393d5c4c7c 100644 --- a/trunk/drivers/acpi/processor_idle.c +++ b/trunk/drivers/acpi/processor_idle.c @@ -60,8 +60,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_idle"); @@ -682,7 +680,6 @@ static int acpi_processor_get_power_info(struct acpi_processor *pr) return 0; } -#ifdef CONFIG_ACPI_PROCFS static int acpi_processor_power_seq_show(struct seq_file *seq, void *offset) { struct acpi_processor *pr = seq->private; @@ -762,7 +759,7 @@ static const struct file_operations acpi_processor_power_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif + /** * acpi_idle_bm_check - checks if bus master activity was detected @@ -1163,9 +1160,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, { acpi_status status = 0; static int first_run; -#ifdef CONFIG_ACPI_PROCFS struct proc_dir_entry *entry = NULL; -#endif unsigned int i; if (boot_option_idle_override) @@ -1222,7 +1217,7 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, pr->power.states[i].type); printk(")\n"); } -#ifdef CONFIG_ACPI_PROCFS + /* 'power' [R] */ entry = proc_create_data(ACPI_PROCESSOR_FILE_POWER, S_IRUGO, acpi_device_dir(device), @@ -1230,7 +1225,6 @@ int __cpuinit acpi_processor_power_init(struct acpi_processor *pr, acpi_driver_data(device)); if (!entry) return -EIO; -#endif return 0; } @@ -1243,11 +1237,9 @@ int acpi_processor_power_exit(struct acpi_processor *pr, cpuidle_unregister_device(&pr->power.dev); pr->flags.power_setup_done = 0; -#ifdef CONFIG_ACPI_PROCFS if (acpi_device_dir(device)) remove_proc_entry(ACPI_PROCESSOR_FILE_POWER, acpi_device_dir(device)); -#endif return 0; } diff --git a/trunk/drivers/acpi/processor_perflib.c b/trunk/drivers/acpi/processor_perflib.c index 11088cf10319..60e543d3234e 100644 --- a/trunk/drivers/acpi/processor_perflib.c +++ b/trunk/drivers/acpi/processor_perflib.c @@ -39,8 +39,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_PROCESSOR_CLASS "processor" #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" #define _COMPONENT ACPI_PROCESSOR_COMPONENT diff --git a/trunk/drivers/acpi/processor_thermal.c b/trunk/drivers/acpi/processor_thermal.c index 140c5c5b423c..31adda1099e0 100644 --- a/trunk/drivers/acpi/processor_thermal.c +++ b/trunk/drivers/acpi/processor_thermal.c @@ -40,8 +40,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_thermal"); @@ -440,7 +438,7 @@ struct thermal_cooling_device_ops processor_cooling_ops = { }; /* /proc interface */ -#ifdef CONFIG_ACPI_PROCFS + static int acpi_processor_limit_seq_show(struct seq_file *seq, void *offset) { struct acpi_processor *pr = (struct acpi_processor *)seq->private; @@ -519,4 +517,3 @@ const struct file_operations acpi_processor_limit_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif diff --git a/trunk/drivers/acpi/processor_throttling.c b/trunk/drivers/acpi/processor_throttling.c index ce7cf3bc5101..ae39797aab55 100644 --- a/trunk/drivers/acpi/processor_throttling.c +++ b/trunk/drivers/acpi/processor_throttling.c @@ -41,8 +41,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_PROCESSOR_CLASS "processor" #define _COMPONENT ACPI_PROCESSOR_COMPONENT ACPI_MODULE_NAME("processor_throttling"); @@ -1218,7 +1216,7 @@ int acpi_processor_get_throttling_info(struct acpi_processor *pr) } /* proc interface */ -#ifdef CONFIG_ACPI_PROCFS + static int acpi_processor_throttling_seq_show(struct seq_file *seq, void *offset) { @@ -1326,4 +1324,3 @@ const struct file_operations acpi_processor_throttling_fops = { .llseek = seq_lseek, .release = single_release, }; -#endif diff --git a/trunk/drivers/acpi/sbs.c b/trunk/drivers/acpi/sbs.c index 52b9db8afc20..4b214b74ebaa 100644 --- a/trunk/drivers/acpi/sbs.c +++ b/trunk/drivers/acpi/sbs.c @@ -46,8 +46,6 @@ #include "sbshc.h" -#define PREFIX "ACPI: " - #define ACPI_SBS_CLASS "sbs" #define ACPI_AC_CLASS "ac_adapter" #define ACPI_BATTERY_CLASS "battery" diff --git a/trunk/drivers/acpi/sbshc.c b/trunk/drivers/acpi/sbshc.c index d9339806df45..0619734895b2 100644 --- a/trunk/drivers/acpi/sbshc.c +++ b/trunk/drivers/acpi/sbshc.c @@ -15,8 +15,6 @@ #include #include "sbshc.h" -#define PREFIX "ACPI: " - #define ACPI_SMB_HC_CLASS "smbus_host_controller" #define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC" diff --git a/trunk/drivers/acpi/scan.c b/trunk/drivers/acpi/scan.c index 408ebde18986..318b1ea7a5bf 100644 --- a/trunk/drivers/acpi/scan.c +++ b/trunk/drivers/acpi/scan.c @@ -60,13 +60,13 @@ static int create_modalias(struct acpi_device *acpi_dev, char *modalias, } if (acpi_dev->flags.compatible_ids) { - struct acpica_device_id_list *cid_list; + struct acpi_compatible_id_list *cid_list; int i; cid_list = acpi_dev->pnp.cid_list; for (i = 0; i < cid_list->count; i++) { count = snprintf(&modalias[len], size, "%s:", - cid_list->ids[i].string); + cid_list->id[i].value); if (count < 0 || count >= size) { printk(KERN_ERR PREFIX "%s cid[%i] exceeds event buffer size", acpi_dev->pnp.device_name, i); @@ -287,14 +287,14 @@ int acpi_match_device_ids(struct acpi_device *device, } if (device->flags.compatible_ids) { - struct acpica_device_id_list *cid_list = device->pnp.cid_list; + struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; int i; for (id = ids; id->id[0]; id++) { /* compare multiple _CID entries against driver ids */ for (i = 0; i < cid_list->count; i++) { if (!strcmp((char*)id->id, - cid_list->ids[i].string)) + cid_list->id[i].value)) return 0; } } @@ -309,10 +309,6 @@ static void acpi_device_release(struct device *dev) struct acpi_device *acpi_dev = to_acpi_device(dev); kfree(acpi_dev->pnp.cid_list); - if (acpi_dev->flags.hardware_id) - kfree(acpi_dev->pnp.hardware_id); - if (acpi_dev->flags.unique_id) - kfree(acpi_dev->pnp.unique_id); kfree(acpi_dev); } @@ -370,8 +366,7 @@ static acpi_status acpi_device_notify_fixed(void *data) { struct acpi_device *device = data; - /* Fixed hardware devices have no handles */ - acpi_device_notify(NULL, ACPI_FIXED_HARDWARE_EVENT, device); + acpi_device_notify(device->handle, ACPI_FIXED_HARDWARE_EVENT, device); return AE_OK; } @@ -431,6 +426,9 @@ static int acpi_device_probe(struct device * dev) if (acpi_drv->ops.notify) { ret = acpi_device_install_notify_handler(acpi_dev); if (ret) { + if (acpi_drv->ops.stop) + acpi_drv->ops.stop(acpi_dev, + acpi_dev->removal_type); if (acpi_drv->ops.remove) acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); @@ -454,6 +452,8 @@ static int acpi_device_remove(struct device * dev) if (acpi_drv) { if (acpi_drv->ops.notify) acpi_device_remove_notify_handler(acpi_dev); + if (acpi_drv->ops.stop) + acpi_drv->ops.stop(acpi_dev, acpi_dev->removal_type); if (acpi_drv->ops.remove) acpi_drv->ops.remove(acpi_dev, acpi_dev->removal_type); } @@ -687,7 +687,7 @@ acpi_bus_get_ejd(acpi_handle handle, acpi_handle *ejd) } EXPORT_SYMBOL_GPL(acpi_bus_get_ejd); -void acpi_bus_data_handler(acpi_handle handle, void *context) +void acpi_bus_data_handler(acpi_handle handle, u32 function, void *context) { /* TBD */ @@ -1000,89 +1000,33 @@ static int acpi_dock_match(struct acpi_device *device) return acpi_get_handle(device->handle, "_DCK", &tmp); } -static struct acpica_device_id_list* -acpi_add_cid( - struct acpi_device_info *info, - struct acpica_device_id *new_cid) -{ - struct acpica_device_id_list *cid; - char *next_id_string; - acpi_size cid_length; - acpi_size new_cid_length; - u32 i; - - - /* Allocate new CID list with room for the new CID */ - - if (!new_cid) - new_cid_length = info->compatible_id_list.list_size; - else if (info->compatible_id_list.list_size) - new_cid_length = info->compatible_id_list.list_size + - new_cid->length + sizeof(struct acpica_device_id); - else - new_cid_length = sizeof(struct acpica_device_id_list) + new_cid->length; - - cid = ACPI_ALLOCATE_ZEROED(new_cid_length); - if (!cid) { - return NULL; - } - - cid->list_size = new_cid_length; - cid->count = info->compatible_id_list.count; - if (new_cid) - cid->count++; - next_id_string = (char *) cid->ids + (cid->count * sizeof(struct acpica_device_id)); - - /* Copy all existing CIDs */ - - for (i = 0; i < info->compatible_id_list.count; i++) { - cid_length = info->compatible_id_list.ids[i].length; - cid->ids[i].string = next_id_string; - cid->ids[i].length = cid_length; - - ACPI_MEMCPY(next_id_string, info->compatible_id_list.ids[i].string, - cid_length); - - next_id_string += cid_length; - } - - /* Append the new CID */ - - if (new_cid) { - cid->ids[i].string = next_id_string; - cid->ids[i].length = new_cid->length; - - ACPI_MEMCPY(next_id_string, new_cid->string, new_cid->length); - } - - return cid; -} - static void acpi_device_set_id(struct acpi_device *device, struct acpi_device *parent, acpi_handle handle, int type) { - struct acpi_device_info *info = NULL; + struct acpi_device_info *info; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; char *hid = NULL; char *uid = NULL; - struct acpica_device_id_list *cid_list = NULL; - char *cid_add = NULL; + struct acpi_compatible_id_list *cid_list = NULL; + const char *cid_add = NULL; acpi_status status; switch (type) { case ACPI_BUS_TYPE_DEVICE: - status = acpi_get_object_info(handle, &info); + status = acpi_get_object_info(handle, &buffer); if (ACPI_FAILURE(status)) { printk(KERN_ERR PREFIX "%s: Error reading device info\n", __func__); return; } + info = buffer.pointer; if (info->valid & ACPI_VALID_HID) - hid = info->hardware_id.string; + hid = info->hardware_id.value; if (info->valid & ACPI_VALID_UID) - uid = info->unique_id.string; + uid = info->unique_id.value; if (info->valid & ACPI_VALID_CID) - cid_list = &info->compatible_id_list; + cid_list = &info->compatibility_id; if (info->valid & ACPI_VALID_ADR) { device->pnp.bus_address = info->address; device->flags.bus_address = 1; @@ -1133,46 +1077,55 @@ static void acpi_device_set_id(struct acpi_device *device, } if (hid) { - device->pnp.hardware_id = ACPI_ALLOCATE_ZEROED(strlen (hid) + 1); - if (device->pnp.hardware_id) { - strcpy(device->pnp.hardware_id, hid); - device->flags.hardware_id = 1; - } + strcpy(device->pnp.hardware_id, hid); + device->flags.hardware_id = 1; } - if (!device->flags.hardware_id) - device->pnp.hardware_id = ""; - if (uid) { - device->pnp.unique_id = ACPI_ALLOCATE_ZEROED(strlen (uid) + 1); - if (device->pnp.unique_id) { - strcpy(device->pnp.unique_id, uid); - device->flags.unique_id = 1; - } + strcpy(device->pnp.unique_id, uid); + device->flags.unique_id = 1; } - if (!device->flags.unique_id) - device->pnp.unique_id = ""; - if (cid_list || cid_add) { - struct acpica_device_id_list *list; - - if (cid_add) { - struct acpica_device_id cid; - cid.length = strlen (cid_add) + 1; - cid.string = cid_add; - - list = acpi_add_cid(info, &cid); - } else { - list = acpi_add_cid(info, NULL); + struct acpi_compatible_id_list *list; + int size = 0; + int count = 0; + + if (cid_list) { + size = cid_list->size; + } else if (cid_add) { + size = sizeof(struct acpi_compatible_id_list); + cid_list = ACPI_ALLOCATE_ZEROED((acpi_size) size); + if (!cid_list) { + printk(KERN_ERR "Memory allocation error\n"); + kfree(buffer.pointer); + return; + } else { + cid_list->count = 0; + cid_list->size = size; + } } + if (cid_add) + size += sizeof(struct acpi_compatible_id); + list = kmalloc(size, GFP_KERNEL); if (list) { - device->pnp.cid_list = list; - if (cid_add) + if (cid_list) { + memcpy(list, cid_list, cid_list->size); + count = cid_list->count; + } + if (cid_add) { + strncpy(list->id[count].value, cid_add, + ACPI_MAX_CID_LENGTH); + count++; device->flags.compatible_ids = 1; - } + } + list->size = size; + list->count = count; + device->pnp.cid_list = list; + } else + printk(KERN_ERR PREFIX "Memory allocation error\n"); } - kfree(info); + kfree(buffer.pointer); } static int acpi_device_set_context(struct acpi_device *device, int type) @@ -1311,6 +1264,16 @@ acpi_add_single_object(struct acpi_device **child, */ acpi_device_set_id(device, parent, handle, type); + /* + * The ACPI device is attached to acpi handle before getting + * the power/wakeup/peformance flags. Otherwise OS can't get + * the corresponding ACPI device by the acpi handle in the course + * of getting the power/wakeup/performance flags. + */ + result = acpi_device_set_context(device, type); + if (result) + goto end; + /* * Power Management * ---------------- @@ -1341,8 +1304,6 @@ acpi_add_single_object(struct acpi_device **child, goto end; } - if ((result = acpi_device_set_context(device, type))) - goto end; result = acpi_device_register(device, parent); @@ -1357,8 +1318,10 @@ acpi_add_single_object(struct acpi_device **child, end: if (!result) *child = device; - else - acpi_device_release(&device->dev); + else { + kfree(device->pnp.cid_list); + kfree(device); + } return result; } diff --git a/trunk/drivers/acpi/sleep.c b/trunk/drivers/acpi/sleep.c index a90afcc723ab..feece693d773 100644 --- a/trunk/drivers/acpi/sleep.c +++ b/trunk/drivers/acpi/sleep.c @@ -405,14 +405,6 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { }, }, { - .callback = init_set_sci_en_on_resume, - .ident = "Hewlett-Packard HP Pavilion dv3 Notebook PC", - .matches = { - DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), - DMI_MATCH(DMI_PRODUCT_NAME, "HP Pavilion dv3 Notebook PC"), - }, - }, - { .callback = init_old_suspend_ordering, .ident = "Panasonic CF51-2L", .matches = { diff --git a/trunk/drivers/acpi/system.c b/trunk/drivers/acpi/system.c index d11282975f35..9c61ab2177cf 100644 --- a/trunk/drivers/acpi/system.c +++ b/trunk/drivers/acpi/system.c @@ -31,8 +31,6 @@ #include -#define PREFIX "ACPI: " - #define _COMPONENT ACPI_SYSTEM_COMPONENT ACPI_MODULE_NAME("system"); diff --git a/trunk/drivers/acpi/tables.c b/trunk/drivers/acpi/tables.c index f336bca7c450..646d39c031ca 100644 --- a/trunk/drivers/acpi/tables.c +++ b/trunk/drivers/acpi/tables.c @@ -213,9 +213,6 @@ acpi_table_parse_entries(char *id, unsigned long table_end; acpi_size tbl_size; - if (acpi_disabled) - return -ENODEV; - if (!handler) return -EINVAL; @@ -280,9 +277,6 @@ int __init acpi_table_parse(char *id, acpi_table_handler handler) struct acpi_table_header *table = NULL; acpi_size tbl_size; - if (acpi_disabled) - return -ENODEV; - if (!handler) return -EINVAL; diff --git a/trunk/drivers/acpi/thermal.c b/trunk/drivers/acpi/thermal.c index 65f67815902a..564ea1424288 100644 --- a/trunk/drivers/acpi/thermal.c +++ b/trunk/drivers/acpi/thermal.c @@ -47,8 +47,6 @@ #include #include -#define PREFIX "ACPI: " - #define ACPI_THERMAL_CLASS "thermal_zone" #define ACPI_THERMAL_DEVICE_NAME "Thermal Zone" #define ACPI_THERMAL_FILE_STATE "state" diff --git a/trunk/drivers/acpi/utils.c b/trunk/drivers/acpi/utils.c index 811fec10462b..f844941089bb 100644 --- a/trunk/drivers/acpi/utils.c +++ b/trunk/drivers/acpi/utils.c @@ -30,8 +30,6 @@ #include #include -#include "internal.h" - #define _COMPONENT ACPI_BUS_COMPONENT ACPI_MODULE_NAME("utils"); diff --git a/trunk/drivers/acpi/video.c b/trunk/drivers/acpi/video.c index 94b1a4c5abab..60ea984c84a0 100644 --- a/trunk/drivers/acpi/video.c +++ b/trunk/drivers/acpi/video.c @@ -40,12 +40,10 @@ #include #include #include -#include + #include #include -#define PREFIX "ACPI: " - #define ACPI_VIDEO_CLASS "video" #define ACPI_VIDEO_BUS_NAME "Video Bus" #define ACPI_VIDEO_DEVICE_NAME "Video Device" @@ -200,7 +198,7 @@ struct acpi_video_device { struct acpi_device *dev; struct acpi_video_device_brightness *brightness; struct backlight_device *backlight; - struct thermal_cooling_device *cooling_dev; + struct thermal_cooling_device *cdev; struct output_device *output_dev; }; @@ -389,20 +387,20 @@ static struct output_properties acpi_output_properties = { /* thermal cooling device callbacks */ -static int video_get_max_state(struct thermal_cooling_device *cooling_dev, unsigned +static int video_get_max_state(struct thermal_cooling_device *cdev, unsigned long *state) { - struct acpi_device *device = cooling_dev->devdata; + struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); *state = video->brightness->count - 3; return 0; } -static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsigned +static int video_get_cur_state(struct thermal_cooling_device *cdev, unsigned long *state) { - struct acpi_device *device = cooling_dev->devdata; + struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); unsigned long long level; int offset; @@ -419,9 +417,9 @@ static int video_get_cur_state(struct thermal_cooling_device *cooling_dev, unsig } static int -video_set_cur_state(struct thermal_cooling_device *cooling_dev, unsigned long state) +video_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state) { - struct acpi_device *device = cooling_dev->devdata; + struct acpi_device *device = cdev->devdata; struct acpi_video_device *video = acpi_driver_data(device); int level; @@ -605,7 +603,6 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, unsigned long long *level) { acpi_status status = AE_OK; - int i; if (device->cap._BQC || device->cap._BCQ) { char *buf = device->cap._BQC ? "_BQC" : "_BCQ"; @@ -621,15 +618,8 @@ acpi_video_device_lcd_get_level_current(struct acpi_video_device *device, } *level += bqc_offset_aml_bug_workaround; - for (i = 2; i < device->brightness->count; i++) - if (device->brightness->levels[i] == *level) { - device->brightness->curr = *level; - return 0; - } - /* BQC returned an invalid level. Stop using it. */ - ACPI_WARNING((AE_INFO, "%s returned an invalid level", - buf)); - device->cap._BQC = device->cap._BCQ = 0; + device->brightness->curr = *level; + return 0; } else { /* Fixme: * should we return an error or ignore this failure? @@ -880,7 +870,7 @@ acpi_video_init_brightness(struct acpi_video_device *device) br->flags._BCM_use_index = br->flags._BCL_use_index; /* _BQC uses INDEX while _BCL uses VALUE in some laptops */ - br->curr = level = max_level; + br->curr = level_old = max_level; if (!device->cap._BQC) goto set_level; @@ -902,25 +892,15 @@ acpi_video_init_brightness(struct acpi_video_device *device) br->flags._BQC_use_index = (level == max_level ? 0 : 1); - if (!br->flags._BQC_use_index) { - /* - * Set the backlight to the initial state. - * On some buggy laptops, _BQC returns an uninitialized value - * when invoked for the first time, i.e. level_old is invalid. - * set the backlight to max_level in this case - */ - for (i = 2; i < br->count; i++) - if (level_old == br->levels[i]) - level = level_old; + if (!br->flags._BQC_use_index) goto set_level; - } if (br->flags._BCL_reversed) level_old = (br->count - 1) - level_old; - level = br->levels[level_old]; + level_old = br->levels[level_old]; set_level: - result = acpi_video_device_lcd_set_level(device, level); + result = acpi_video_device_lcd_set_level(device, level_old); if (result) goto out_free_levels; @@ -954,6 +934,9 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) { acpi_handle h_dummy1; + + memset(&device->cap, 0, sizeof(device->cap)); + if (ACPI_SUCCESS(acpi_get_handle(device->dev->handle, "_ADR", &h_dummy1))) { device->cap._ADR = 1; } @@ -1007,29 +990,19 @@ static void acpi_video_device_find_cap(struct acpi_video_device *device) if (result) printk(KERN_ERR PREFIX "Create sysfs link\n"); - device->cooling_dev = thermal_cooling_device_register("LCD", + device->cdev = thermal_cooling_device_register("LCD", device->dev, &video_cooling_ops); - if (IS_ERR(device->cooling_dev)) { - /* - * Set cooling_dev to NULL so we don't crash trying to - * free it. - * Also, why the hell we are returning early and - * not attempt to register video output if cooling - * device registration failed? - * -- dtor - */ - device->cooling_dev = NULL; + if (IS_ERR(device->cdev)) return; - } dev_info(&device->dev->dev, "registered as cooling_device%d\n", - device->cooling_dev->id); + device->cdev->id); result = sysfs_create_link(&device->dev->dev.kobj, - &device->cooling_dev->device.kobj, + &device->cdev->device.kobj, "thermal_cooling"); if (result) printk(KERN_ERR PREFIX "Create sysfs link\n"); - result = sysfs_create_link(&device->cooling_dev->device.kobj, + result = sysfs_create_link(&device->cdev->device.kobj, &device->dev->dev.kobj, "device"); if (result) printk(KERN_ERR PREFIX "Create sysfs link\n"); @@ -1066,6 +1039,7 @@ static void acpi_video_bus_find_cap(struct acpi_video_bus *video) { acpi_handle h_dummy1; + memset(&video->cap, 0, sizeof(video->cap)); if (ACPI_SUCCESS(acpi_get_handle(video->device->handle, "_DOS", &h_dummy1))) { video->cap._DOS = 1; } @@ -2035,13 +2009,13 @@ static int acpi_video_bus_put_one_device(struct acpi_video_device *device) backlight_device_unregister(device->backlight); device->backlight = NULL; } - if (device->cooling_dev) { + if (device->cdev) { sysfs_remove_link(&device->dev->dev.kobj, "thermal_cooling"); - sysfs_remove_link(&device->cooling_dev->device.kobj, + sysfs_remove_link(&device->cdev->device.kobj, "device"); - thermal_cooling_device_unregister(device->cooling_dev); - device->cooling_dev = NULL; + thermal_cooling_device_unregister(device->cdev); + device->cdev = NULL; } video_output_unregister(device->output_dev); diff --git a/trunk/drivers/acpi/video_detect.c b/trunk/drivers/acpi/video_detect.c index 7032f25da9b5..7cd2b63435ea 100644 --- a/trunk/drivers/acpi/video_detect.c +++ b/trunk/drivers/acpi/video_detect.c @@ -38,8 +38,6 @@ #include #include -#define PREFIX "ACPI: " - ACPI_MODULE_NAME("video"); #define _COMPONENT ACPI_VIDEO_COMPONENT diff --git a/trunk/drivers/block/DAC960.c b/trunk/drivers/block/DAC960.c index 6fa7b0fdbdfd..c77b6f3c28ea 100644 --- a/trunk/drivers/block/DAC960.c +++ b/trunk/drivers/block/DAC960.c @@ -6562,7 +6562,7 @@ static int DAC960_ProcWriteUserCommand(struct file *file, if (copy_from_user(CommandBuffer, Buffer, Count)) return -EFAULT; CommandBuffer[Count] = '\0'; Length = strlen(CommandBuffer); - if (Length > 0 && CommandBuffer[Length-1] == '\n') + if (CommandBuffer[Length-1] == '\n') CommandBuffer[--Length] = '\0'; if (Controller->FirmwareType == DAC960_V1_Controller) return (DAC960_V1_ExecuteUserCommand(Controller, CommandBuffer) diff --git a/trunk/drivers/block/cciss.c b/trunk/drivers/block/cciss.c index 24c3e21ab263..4f19105f755c 100644 --- a/trunk/drivers/block/cciss.c +++ b/trunk/drivers/block/cciss.c @@ -363,7 +363,7 @@ static void cciss_seq_stop(struct seq_file *seq, void *v) h->busy_configuring = 0; } -static const struct seq_operations cciss_seq_ops = { +static struct seq_operations cciss_seq_ops = { .start = cciss_seq_start, .show = cciss_seq_show, .next = cciss_seq_next, diff --git a/trunk/drivers/block/virtio_blk.c b/trunk/drivers/block/virtio_blk.c index 43f19389647a..aa89fe45237d 100644 --- a/trunk/drivers/block/virtio_blk.c +++ b/trunk/drivers/block/virtio_blk.c @@ -3,7 +3,6 @@ #include #include #include -#include #include #include @@ -92,26 +91,15 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, return false; vbr->req = req; - switch (req->cmd_type) { - case REQ_TYPE_FS: + if (blk_fs_request(vbr->req)) { vbr->out_hdr.type = 0; vbr->out_hdr.sector = blk_rq_pos(vbr->req); vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); - break; - case REQ_TYPE_BLOCK_PC: + } else if (blk_pc_request(vbr->req)) { vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; vbr->out_hdr.sector = 0; vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); - break; - case REQ_TYPE_LINUX_BLOCK: - if (req->cmd[0] == REQ_LB_OP_FLUSH) { - vbr->out_hdr.type = VIRTIO_BLK_T_FLUSH; - vbr->out_hdr.sector = 0; - vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); - break; - } - /*FALLTHRU*/ - default: + } else { /* We don't put anything else in the queue. */ BUG(); } @@ -151,7 +139,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, } } - if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr) < 0) { + if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) { mempool_free(vbr, vblk->pool); return false; } @@ -211,12 +199,6 @@ static int virtblk_identify(struct gendisk *disk, void *argp) return err; } -static void virtblk_prepare_flush(struct request_queue *q, struct request *req) -{ - req->cmd_type = REQ_TYPE_LINUX_BLOCK; - req->cmd[0] = REQ_LB_OP_FLUSH; -} - static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd, unsigned long data) { @@ -355,10 +337,7 @@ static int __devinit virtblk_probe(struct virtio_device *vdev) index++; /* If barriers are supported, tell block layer that queue is ordered */ - if (virtio_has_feature(vdev, VIRTIO_BLK_F_FLUSH)) - blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_DRAIN_FLUSH, - virtblk_prepare_flush); - else if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) + if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER)) blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL); /* If disk is read-only in the host, the guest should obey */ @@ -445,7 +424,7 @@ static struct virtio_device_id id_table[] = { static unsigned int features[] = { VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, - VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY, VIRTIO_BLK_F_FLUSH + VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY }; /* diff --git a/trunk/drivers/char/agp/hp-agp.c b/trunk/drivers/char/agp/hp-agp.c index 9047b2714653..501e293e5ad0 100644 --- a/trunk/drivers/char/agp/hp-agp.c +++ b/trunk/drivers/char/agp/hp-agp.c @@ -476,6 +476,7 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) { acpi_handle handle, parent; acpi_status status; + struct acpi_buffer buffer; struct acpi_device_info *info; u64 lba_hpa, sba_hpa, length; int match; @@ -487,11 +488,13 @@ zx1_gart_probe (acpi_handle obj, u32 depth, void *context, void **ret) /* Look for an enclosing IOC scope and find its CSR space */ handle = obj; do { - status = acpi_get_object_info(handle, &info); + buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER; + status = acpi_get_object_info(handle, &buffer); if (ACPI_SUCCESS(status)) { /* TBD check _CID also */ - info->hardware_id.string[sizeof(info->hardware_id.length)-1] = '\0'; - match = (strcmp(info->hardware_id.string, "HWP0001") == 0); + info = buffer.pointer; + info->hardware_id.value[sizeof(info->hardware_id)-1] = '\0'; + match = (strcmp(info->hardware_id.value, "HWP0001") == 0); kfree(info); if (match) { status = hp_acpi_csr_space(handle, &sba_hpa, &length); diff --git a/trunk/drivers/char/hw_random/virtio-rng.c b/trunk/drivers/char/hw_random/virtio-rng.c index 962968f05b94..32216b623248 100644 --- a/trunk/drivers/char/hw_random/virtio-rng.c +++ b/trunk/drivers/char/hw_random/virtio-rng.c @@ -21,7 +21,6 @@ #include #include #include -#include #include /* The host will fill any buffer we give it with sweet, sweet randomness. We @@ -52,7 +51,7 @@ static void register_buffer(void) sg_init_one(&sg, random_data+data_left, RANDOM_DATA_SIZE-data_left); /* There should always be room for one buffer. */ - if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) < 0) + if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0) BUG(); vq->vq_ops->kick(vq); } diff --git a/trunk/drivers/char/misc.c b/trunk/drivers/char/misc.c index 07fa612a58d5..1ee27cc23426 100644 --- a/trunk/drivers/char/misc.c +++ b/trunk/drivers/char/misc.c @@ -91,7 +91,7 @@ static int misc_seq_show(struct seq_file *seq, void *v) } -static const struct seq_operations misc_seq_ops = { +static struct seq_operations misc_seq_ops = { .start = misc_seq_start, .next = misc_seq_next, .stop = misc_seq_stop, diff --git a/trunk/drivers/char/tpm/tpm.c b/trunk/drivers/char/tpm/tpm.c index 32b957efa420..b0603b2e5684 100644 --- a/trunk/drivers/char/tpm/tpm.c +++ b/trunk/drivers/char/tpm/tpm.c @@ -696,7 +696,7 @@ int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) cmd.header.in = pcrread_header; cmd.params.pcrread_in.pcr_idx = cpu_to_be32(pcr_idx); - BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); + BUILD_BUG_ON(cmd.header.in.length > READ_PCR_RESULT_SIZE); rc = transmit_cmd(chip, &cmd, cmd.header.in.length, "attempting to read a pcr value"); @@ -760,7 +760,7 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) return -ENODEV; cmd.header.in = pcrextend_header; - BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); + BUILD_BUG_ON(be32_to_cpu(cmd.header.in.length) > EXTEND_PCR_SIZE); cmd.params.pcrextend_in.pcr_idx = cpu_to_be32(pcr_idx); memcpy(cmd.params.pcrextend_in.hash, hash, TPM_DIGEST_SIZE); rc = transmit_cmd(chip, &cmd, cmd.header.in.length, diff --git a/trunk/drivers/char/tpm/tpm_bios.c b/trunk/drivers/char/tpm/tpm_bios.c index bf2170fb1cdd..0c2f55a38b95 100644 --- a/trunk/drivers/char/tpm/tpm_bios.c +++ b/trunk/drivers/char/tpm/tpm_bios.c @@ -343,14 +343,14 @@ static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) return 0; } -static const struct seq_operations tpm_ascii_b_measurments_seqops = { +static struct seq_operations tpm_ascii_b_measurments_seqops = { .start = tpm_bios_measurements_start, .next = tpm_bios_measurements_next, .stop = tpm_bios_measurements_stop, .show = tpm_ascii_bios_measurements_show, }; -static const struct seq_operations tpm_binary_b_measurments_seqops = { +static struct seq_operations tpm_binary_b_measurments_seqops = { .start = tpm_bios_measurements_start, .next = tpm_bios_measurements_next, .stop = tpm_bios_measurements_stop, diff --git a/trunk/drivers/char/virtio_console.c b/trunk/drivers/char/virtio_console.c index 0d328b59568d..c74dacfa6795 100644 --- a/trunk/drivers/char/virtio_console.c +++ b/trunk/drivers/char/virtio_console.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "hvc_console.h" @@ -66,7 +65,7 @@ static int put_chars(u32 vtermno, const char *buf, int count) /* add_buf wants a token to identify this buffer: we hand it any * non-NULL pointer, since there's only ever one buffer. */ - if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) >= 0) { + if (out_vq->vq_ops->add_buf(out_vq, sg, 1, 0, (void *)1) == 0) { /* Tell Host to go! */ out_vq->vq_ops->kick(out_vq); /* Chill out until it's done with the buffer. */ @@ -86,7 +85,7 @@ static void add_inbuf(void) sg_init_one(sg, inbuf, PAGE_SIZE); /* We should always be able to add one buffer to an empty queue. */ - if (in_vq->vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) < 0) + if (in_vq->vq_ops->add_buf(in_vq, sg, 0, 1, inbuf) != 0) BUG(); in_vq->vq_ops->kick(in_vq); } diff --git a/trunk/drivers/connector/cn_proc.c b/trunk/drivers/connector/cn_proc.c index abf4a2529f80..85e5dc0431fe 100644 --- a/trunk/drivers/connector/cn_proc.c +++ b/trunk/drivers/connector/cn_proc.c @@ -139,31 +139,6 @@ void proc_id_connector(struct task_struct *task, int which_id) cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); } -void proc_sid_connector(struct task_struct *task) -{ - struct cn_msg *msg; - struct proc_event *ev; - struct timespec ts; - __u8 buffer[CN_PROC_MSG_SIZE]; - - if (atomic_read(&proc_event_num_listeners) < 1) - return; - - msg = (struct cn_msg *)buffer; - ev = (struct proc_event *)msg->data; - get_seq(&msg->seq, &ev->cpu); - ktime_get_ts(&ts); /* get high res monotonic timestamp */ - put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns); - ev->what = PROC_EVENT_SID; - ev->event_data.sid.process_pid = task->pid; - ev->event_data.sid.process_tgid = task->tgid; - - memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id)); - msg->ack = 0; /* not used */ - msg->len = sizeof(*ev); - cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL); -} - void proc_exit_connector(struct task_struct *task) { struct cn_msg *msg; diff --git a/trunk/drivers/firewire/core-card.c b/trunk/drivers/firewire/core-card.c index e4864e894e4f..f74edae5cb4c 100644 --- a/trunk/drivers/firewire/core-card.c +++ b/trunk/drivers/firewire/core-card.c @@ -444,14 +444,17 @@ int fw_card_add(struct fw_card *card, card->guid = guid; mutex_lock(&card_mutex); - config_rom = generate_config_rom(card, &length); - ret = card->driver->enable(card, config_rom, length); - if (ret == 0) - list_add_tail(&card->link, &card_list); - + list_add_tail(&card->link, &card_list); mutex_unlock(&card_mutex); + ret = card->driver->enable(card, config_rom, length); + if (ret < 0) { + mutex_lock(&card_mutex); + list_del(&card->link); + mutex_unlock(&card_mutex); + } + return ret; } EXPORT_SYMBOL(fw_card_add); diff --git a/trunk/drivers/firewire/core-transaction.c b/trunk/drivers/firewire/core-transaction.c index da628c72a462..479b22f5a1eb 100644 --- a/trunk/drivers/firewire/core-transaction.c +++ b/trunk/drivers/firewire/core-transaction.c @@ -834,7 +834,7 @@ static void handle_topology_map(struct fw_card *card, struct fw_request *request } static struct fw_address_handler topology_map = { - .length = 0x400, + .length = 0x200, .address_callback = handle_topology_map, }; diff --git a/trunk/drivers/firewire/core.h b/trunk/drivers/firewire/core.h index 7ff6e7585152..6052816be353 100644 --- a/trunk/drivers/firewire/core.h +++ b/trunk/drivers/firewire/core.h @@ -96,20 +96,6 @@ int fw_core_initiate_bus_reset(struct fw_card *card, int short_reset); int fw_compute_block_crc(u32 *block); void fw_schedule_bm_work(struct fw_card *card, unsigned long delay); -static inline struct fw_card *fw_card_get(struct fw_card *card) -{ - kref_get(&card->kref); - - return card; -} - -void fw_card_release(struct kref *kref); - -static inline void fw_card_put(struct fw_card *card) -{ - kref_put(&card->kref, fw_card_release); -} - /* -cdev */ diff --git a/trunk/drivers/firewire/ohci.c b/trunk/drivers/firewire/ohci.c index 5d524254499e..76b321bb73f9 100644 --- a/trunk/drivers/firewire/ohci.c +++ b/trunk/drivers/firewire/ohci.c @@ -1279,8 +1279,8 @@ static void bus_reset_tasklet(unsigned long data) * the inverted quadlets and a header quadlet, we shift one * bit extra to get the actual number of self IDs. */ - self_id_count = (reg >> 3) & 0xff; - if (self_id_count == 0 || self_id_count > 252) { + self_id_count = (reg >> 3) & 0x3ff; + if (self_id_count == 0) { fw_notify("inconsistent self IDs\n"); return; } diff --git a/trunk/drivers/firewire/sbp2.c b/trunk/drivers/firewire/sbp2.c index 50f0176de615..e5df822a8130 100644 --- a/trunk/drivers/firewire/sbp2.c +++ b/trunk/drivers/firewire/sbp2.c @@ -354,7 +354,8 @@ static const struct { /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { .firmware_revision = 0x002800, .model = 0x000000, - .workarounds = SBP2_WORKAROUND_POWER_CONDITION, + .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY | + SBP2_WORKAROUND_POWER_CONDITION, }, /* Initio bridges, actually only needed for some older ones */ { .firmware_revision = 0x000200, @@ -424,20 +425,19 @@ static void sbp2_status_write(struct fw_card *card, struct fw_request *request, struct sbp2_logical_unit *lu = callback_data; struct sbp2_orb *orb; struct sbp2_status status; + size_t header_size; unsigned long flags; if (tcode != TCODE_WRITE_BLOCK_REQUEST || - length < 8 || length > sizeof(status)) { + length == 0 || length > sizeof(status)) { fw_send_response(card, request, RCODE_TYPE_ERROR); return; } - status.status = be32_to_cpup(payload); - status.orb_low = be32_to_cpup(payload + 4); - memset(status.data, 0, sizeof(status.data)); - if (length > 8) - memcpy(status.data, payload + 8, length - 8); - + header_size = min(length, 2 * sizeof(u32)); + fw_memcpy_from_be32(&status, payload, header_size); + if (length > header_size) + memcpy(status.data, payload + 8, length - header_size); if (STATUS_GET_SOURCE(status) == 2 || STATUS_GET_SOURCE(status) == 3) { fw_notify("non-orb related status write, not handled\n"); fw_send_response(card, request, RCODE_COMPLETE); diff --git a/trunk/drivers/gpio/Kconfig b/trunk/drivers/gpio/Kconfig index 2ad0128c63c6..6b4c484a699a 100644 --- a/trunk/drivers/gpio/Kconfig +++ b/trunk/drivers/gpio/Kconfig @@ -162,16 +162,6 @@ config GPIO_WM831X Say yes here to access the GPIO signals of WM831x power management chips from Wolfson Microelectronics. -config GPIO_ADP5520 - tristate "GPIO Support for ADP5520 PMIC" - depends on PMIC_ADP5520 - help - This option enables support for on-chip GPIO found - on Analog Devices ADP5520 PMICs. - - To compile this driver as a module, choose M here: the module will - be called adp5520-gpio. - comment "PCI GPIO expanders:" config GPIO_BT8XX @@ -190,12 +180,6 @@ config GPIO_BT8XX If unsure, say N. -config GPIO_LANGWELL - bool "Intel Moorestown Platform Langwell GPIO support" - depends on PCI - help - Say Y here to support Intel Moorestown platform GPIO. - comment "SPI GPIO expanders:" config GPIO_MAX7301 @@ -211,23 +195,4 @@ config GPIO_MCP23S08 SPI driver for Microchip MCP23S08 I/O expander. This provides a GPIO interface supporting inputs and outputs. -config GPIO_MC33880 - tristate "Freescale MC33880 high-side/low-side switch" - depends on SPI_MASTER - help - SPI driver for Freescale MC33880 high-side/low-side switch. - This provides GPIO interface supporting inputs and outputs. - -comment "AC97 GPIO expanders:" - -config GPIO_UCB1400 - bool "Philips UCB1400 GPIO" - depends on UCB1400_CORE - help - This enables support for the Philips UCB1400 GPIO pins. - The UCB1400 is an AC97 audio codec. - - To compile this driver as a module, choose M here: the - module will be called ucb1400_gpio. - endif diff --git a/trunk/drivers/gpio/Makefile b/trunk/drivers/gpio/Makefile index 00a532c9a1e2..ea7c745f26a8 100644 --- a/trunk/drivers/gpio/Makefile +++ b/trunk/drivers/gpio/Makefile @@ -4,17 +4,13 @@ ccflags-$(CONFIG_DEBUG_GPIO) += -DDEBUG obj-$(CONFIG_GPIOLIB) += gpiolib.o -obj-$(CONFIG_GPIO_ADP5520) += adp5520-gpio.o -obj-$(CONFIG_GPIO_LANGWELL) += langwell_gpio.o obj-$(CONFIG_GPIO_MAX7301) += max7301.o obj-$(CONFIG_GPIO_MAX732X) += max732x.o -obj-$(CONFIG_GPIO_MC33880) += mc33880.o obj-$(CONFIG_GPIO_MCP23S08) += mcp23s08.o obj-$(CONFIG_GPIO_PCA953X) += pca953x.o obj-$(CONFIG_GPIO_PCF857X) += pcf857x.o obj-$(CONFIG_GPIO_PL061) += pl061.o obj-$(CONFIG_GPIO_TWL4030) += twl4030-gpio.o -obj-$(CONFIG_GPIO_UCB1400) += ucb1400_gpio.o obj-$(CONFIG_GPIO_XILINX) += xilinx_gpio.o obj-$(CONFIG_GPIO_BT8XX) += bt8xxgpio.o obj-$(CONFIG_GPIO_VR41XX) += vr41xx_giu.o diff --git a/trunk/drivers/gpio/adp5520-gpio.c b/trunk/drivers/gpio/adp5520-gpio.c deleted file mode 100644 index ad05bbc7ffd5..000000000000 --- a/trunk/drivers/gpio/adp5520-gpio.c +++ /dev/null @@ -1,206 +0,0 @@ -/* - * GPIO driver for Analog Devices ADP5520 MFD PMICs - * - * Copyright 2009 Analog Devices Inc. - * - * Licensed under the GPL-2 or later. - */ - -#include -#include -#include -#include -#include - -#include - -struct adp5520_gpio { - struct device *master; - struct gpio_chip gpio_chip; - unsigned char lut[ADP5520_MAXGPIOS]; - unsigned long output; -}; - -static int adp5520_gpio_get_value(struct gpio_chip *chip, unsigned off) -{ - struct adp5520_gpio *dev; - uint8_t reg_val; - - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - /* - * There are dedicated registers for GPIO IN/OUT. - * Make sure we return the right value, even when configured as output - */ - - if (test_bit(off, &dev->output)) - adp5520_read(dev->master, GPIO_OUT, ®_val); - else - adp5520_read(dev->master, GPIO_IN, ®_val); - - return !!(reg_val & dev->lut[off]); -} - -static void adp5520_gpio_set_value(struct gpio_chip *chip, - unsigned off, int val) -{ - struct adp5520_gpio *dev; - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - if (val) - adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); - else - adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); -} - -static int adp5520_gpio_direction_input(struct gpio_chip *chip, unsigned off) -{ - struct adp5520_gpio *dev; - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - clear_bit(off, &dev->output); - - return adp5520_clr_bits(dev->master, GPIO_CFG_2, dev->lut[off]); -} - -static int adp5520_gpio_direction_output(struct gpio_chip *chip, - unsigned off, int val) -{ - struct adp5520_gpio *dev; - int ret = 0; - dev = container_of(chip, struct adp5520_gpio, gpio_chip); - - set_bit(off, &dev->output); - - if (val) - ret |= adp5520_set_bits(dev->master, GPIO_OUT, dev->lut[off]); - else - ret |= adp5520_clr_bits(dev->master, GPIO_OUT, dev->lut[off]); - - ret |= adp5520_set_bits(dev->master, GPIO_CFG_2, dev->lut[off]); - - return ret; -} - -static int __devinit adp5520_gpio_probe(struct platform_device *pdev) -{ - struct adp5520_gpio_platfrom_data *pdata = pdev->dev.platform_data; - struct adp5520_gpio *dev; - struct gpio_chip *gc; - int ret, i, gpios; - unsigned char ctl_mask = 0; - - if (pdata == NULL) { - dev_err(&pdev->dev, "missing platform data\n"); - return -ENODEV; - } - - if (pdev->id != ID_ADP5520) { - dev_err(&pdev->dev, "only ADP5520 supports GPIO\n"); - return -ENODEV; - } - - dev = kzalloc(sizeof(*dev), GFP_KERNEL); - if (dev == NULL) { - dev_err(&pdev->dev, "failed to alloc memory\n"); - return -ENOMEM; - } - - dev->master = pdev->dev.parent; - - for (gpios = 0, i = 0; i < ADP5520_MAXGPIOS; i++) - if (pdata->gpio_en_mask & (1 << i)) - dev->lut[gpios++] = 1 << i; - - if (gpios < 1) { - ret = -EINVAL; - goto err; - } - - gc = &dev->gpio_chip; - gc->direction_input = adp5520_gpio_direction_input; - gc->direction_output = adp5520_gpio_direction_output; - gc->get = adp5520_gpio_get_value; - gc->set = adp5520_gpio_set_value; - gc->can_sleep = 1; - - gc->base = pdata->gpio_start; - gc->ngpio = gpios; - gc->label = pdev->name; - gc->owner = THIS_MODULE; - - ret = adp5520_clr_bits(dev->master, GPIO_CFG_1, - pdata->gpio_en_mask); - - if (pdata->gpio_en_mask & GPIO_C3) - ctl_mask |= C3_MODE; - - if (pdata->gpio_en_mask & GPIO_R3) - ctl_mask |= R3_MODE; - - if (ctl_mask) - ret = adp5520_set_bits(dev->master, LED_CONTROL, - ctl_mask); - - ret |= adp5520_set_bits(dev->master, GPIO_PULLUP, - pdata->gpio_pullup_mask); - - if (ret) { - dev_err(&pdev->dev, "failed to write\n"); - goto err; - } - - ret = gpiochip_add(&dev->gpio_chip); - if (ret) - goto err; - - platform_set_drvdata(pdev, dev); - return 0; - -err: - kfree(dev); - return ret; -} - -static int __devexit adp5520_gpio_remove(struct platform_device *pdev) -{ - struct adp5520_gpio *dev; - int ret; - - dev = platform_get_drvdata(pdev); - ret = gpiochip_remove(&dev->gpio_chip); - if (ret) { - dev_err(&pdev->dev, "%s failed, %d\n", - "gpiochip_remove()", ret); - return ret; - } - - kfree(dev); - return 0; -} - -static struct platform_driver adp5520_gpio_driver = { - .driver = { - .name = "adp5520-gpio", - .owner = THIS_MODULE, - }, - .probe = adp5520_gpio_probe, - .remove = __devexit_p(adp5520_gpio_remove), -}; - -static int __init adp5520_gpio_init(void) -{ - return platform_driver_register(&adp5520_gpio_driver); -} -module_init(adp5520_gpio_init); - -static void __exit adp5520_gpio_exit(void) -{ - platform_driver_unregister(&adp5520_gpio_driver); -} -module_exit(adp5520_gpio_exit); - -MODULE_AUTHOR("Michael Hennerich "); -MODULE_DESCRIPTION("GPIO ADP5520 Driver"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:adp5520-gpio"); diff --git a/trunk/drivers/gpio/bt8xxgpio.c b/trunk/drivers/gpio/bt8xxgpio.c index 2559f2289409..55904140213b 100644 --- a/trunk/drivers/gpio/bt8xxgpio.c +++ b/trunk/drivers/gpio/bt8xxgpio.c @@ -46,7 +46,8 @@ #include #include #include -#include + +#include /* Steal the hardware definitions from the bttv driver. */ #include "../media/video/bt8xx/bt848.h" diff --git a/trunk/drivers/gpio/gpiolib.c b/trunk/drivers/gpio/gpiolib.c index bb11a429394a..51a8d4103be5 100644 --- a/trunk/drivers/gpio/gpiolib.c +++ b/trunk/drivers/gpio/gpiolib.c @@ -1,6 +1,5 @@ #include #include -#include #include #include #include @@ -8,7 +7,6 @@ #include #include #include -#include /* Optional implementation infrastructure for GPIO interfaces. @@ -51,13 +49,6 @@ struct gpio_desc { #define FLAG_RESERVED 2 #define FLAG_EXPORT 3 /* protected by sysfs_lock */ #define FLAG_SYSFS 4 /* exported via /sys/class/gpio/control */ -#define FLAG_TRIG_FALL 5 /* trigger on falling edge */ -#define FLAG_TRIG_RISE 6 /* trigger on rising edge */ - -#define PDESC_ID_SHIFT 16 /* add new flags before this one */ - -#define GPIO_FLAGS_MASK ((1 << PDESC_ID_SHIFT) - 1) -#define GPIO_TRIGGER_MASK (BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE)) #ifdef CONFIG_DEBUG_FS const char *label; @@ -65,15 +56,6 @@ struct gpio_desc { }; static struct gpio_desc gpio_desc[ARCH_NR_GPIOS]; -#ifdef CONFIG_GPIO_SYSFS -struct poll_desc { - struct work_struct work; - struct sysfs_dirent *value_sd; -}; - -static struct idr pdesc_idr; -#endif - static inline void desc_set_label(struct gpio_desc *d, const char *label) { #ifdef CONFIG_DEBUG_FS @@ -206,10 +188,10 @@ static DEFINE_MUTEX(sysfs_lock); * /value * * always readable, subject to hardware behavior * * may be writable, as zero/nonzero - * /edge - * * configures behavior of poll(2) on /value - * * available only if pin can generate IRQs on input - * * is read/write as "none", "falling", "rising", or "both" + * + * REVISIT there will likely be an attribute for configuring async + * notifications, e.g. to specify polling interval or IRQ trigger type + * that would for example trigger a poll() on the "value". */ static ssize_t gpio_direction_show(struct device *dev, @@ -306,175 +288,6 @@ static ssize_t gpio_value_store(struct device *dev, static /*const*/ DEVICE_ATTR(value, 0644, gpio_value_show, gpio_value_store); -static irqreturn_t gpio_sysfs_irq(int irq, void *priv) -{ - struct work_struct *work = priv; - - schedule_work(work); - return IRQ_HANDLED; -} - -static void gpio_notify_sysfs(struct work_struct *work) -{ - struct poll_desc *pdesc; - - pdesc = container_of(work, struct poll_desc, work); - sysfs_notify_dirent(pdesc->value_sd); -} - -static int gpio_setup_irq(struct gpio_desc *desc, struct device *dev, - unsigned long gpio_flags) -{ - struct poll_desc *pdesc; - unsigned long irq_flags; - int ret, irq, id; - - if ((desc->flags & GPIO_TRIGGER_MASK) == gpio_flags) - return 0; - - irq = gpio_to_irq(desc - gpio_desc); - if (irq < 0) - return -EIO; - - id = desc->flags >> PDESC_ID_SHIFT; - pdesc = idr_find(&pdesc_idr, id); - if (pdesc) { - free_irq(irq, &pdesc->work); - cancel_work_sync(&pdesc->work); - } - - desc->flags &= ~GPIO_TRIGGER_MASK; - - if (!gpio_flags) { - ret = 0; - goto free_sd; - } - - irq_flags = IRQF_SHARED; - if (test_bit(FLAG_TRIG_FALL, &gpio_flags)) - irq_flags |= IRQF_TRIGGER_FALLING; - if (test_bit(FLAG_TRIG_RISE, &gpio_flags)) - irq_flags |= IRQF_TRIGGER_RISING; - - if (!pdesc) { - pdesc = kmalloc(sizeof(*pdesc), GFP_KERNEL); - if (!pdesc) { - ret = -ENOMEM; - goto err_out; - } - - do { - ret = -ENOMEM; - if (idr_pre_get(&pdesc_idr, GFP_KERNEL)) - ret = idr_get_new_above(&pdesc_idr, - pdesc, 1, &id); - } while (ret == -EAGAIN); - - if (ret) - goto free_mem; - - desc->flags &= GPIO_FLAGS_MASK; - desc->flags |= (unsigned long)id << PDESC_ID_SHIFT; - - if (desc->flags >> PDESC_ID_SHIFT != id) { - ret = -ERANGE; - goto free_id; - } - - pdesc->value_sd = sysfs_get_dirent(dev->kobj.sd, "value"); - if (!pdesc->value_sd) { - ret = -ENODEV; - goto free_id; - } - INIT_WORK(&pdesc->work, gpio_notify_sysfs); - } - - ret = request_irq(irq, gpio_sysfs_irq, irq_flags, - "gpiolib", &pdesc->work); - if (ret) - goto free_sd; - - desc->flags |= gpio_flags; - return 0; - -free_sd: - sysfs_put(pdesc->value_sd); -free_id: - idr_remove(&pdesc_idr, id); - desc->flags &= GPIO_FLAGS_MASK; -free_mem: - kfree(pdesc); -err_out: - return ret; -} - -static const struct { - const char *name; - unsigned long flags; -} trigger_types[] = { - { "none", 0 }, - { "falling", BIT(FLAG_TRIG_FALL) }, - { "rising", BIT(FLAG_TRIG_RISE) }, - { "both", BIT(FLAG_TRIG_FALL) | BIT(FLAG_TRIG_RISE) }, -}; - -static ssize_t gpio_edge_show(struct device *dev, - struct device_attribute *attr, char *buf) -{ - const struct gpio_desc *desc = dev_get_drvdata(dev); - ssize_t status; - - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else { - int i; - - status = 0; - for (i = 0; i < ARRAY_SIZE(trigger_types); i++) - if ((desc->flags & GPIO_TRIGGER_MASK) - == trigger_types[i].flags) { - status = sprintf(buf, "%s\n", - trigger_types[i].name); - break; - } - } - - mutex_unlock(&sysfs_lock); - return status; -} - -static ssize_t gpio_edge_store(struct device *dev, - struct device_attribute *attr, const char *buf, size_t size) -{ - struct gpio_desc *desc = dev_get_drvdata(dev); - ssize_t status; - int i; - - for (i = 0; i < ARRAY_SIZE(trigger_types); i++) - if (sysfs_streq(trigger_types[i].name, buf)) - goto found; - return -EINVAL; - -found: - mutex_lock(&sysfs_lock); - - if (!test_bit(FLAG_EXPORT, &desc->flags)) - status = -EIO; - else { - status = gpio_setup_irq(desc, dev, trigger_types[i].flags); - if (!status) - status = size; - } - - mutex_unlock(&sysfs_lock); - - return status; -} - -static DEVICE_ATTR(edge, 0644, gpio_edge_show, gpio_edge_store); - static const struct attribute *gpio_attrs[] = { &dev_attr_direction.attr, &dev_attr_value.attr, @@ -660,7 +473,7 @@ int gpio_export(unsigned gpio, bool direction_may_change) struct device *dev; dev = device_create(&gpio_class, desc->chip->dev, MKDEV(0, 0), - desc, ioname ? ioname : "gpio%d", gpio); + desc, ioname ? ioname : "gpio%d", gpio); if (dev) { if (direction_may_change) status = sysfs_create_group(&dev->kobj, @@ -668,14 +481,6 @@ int gpio_export(unsigned gpio, bool direction_may_change) else status = device_create_file(dev, &dev_attr_value); - - if (!status && gpio_to_irq(gpio) >= 0 - && (direction_may_change - || !test_bit(FLAG_IS_OUT, - &desc->flags))) - status = device_create_file(dev, - &dev_attr_edge); - if (status != 0) device_unregister(dev); } else @@ -699,51 +504,6 @@ static int match_export(struct device *dev, void *data) return dev_get_drvdata(dev) == data; } -/** - * gpio_export_link - create a sysfs link to an exported GPIO node - * @dev: device under which to create symlink - * @name: name of the symlink - * @gpio: gpio to create symlink to, already exported - * - * Set up a symlink from /sys/.../dev/name to /sys/class/gpio/gpioN - * node. Caller is responsible for unlinking. - * - * Returns zero on success, else an error. - */ -int gpio_export_link(struct device *dev, const char *name, unsigned gpio) -{ - struct gpio_desc *desc; - int status = -EINVAL; - - if (!gpio_is_valid(gpio)) - goto done; - - mutex_lock(&sysfs_lock); - - desc = &gpio_desc[gpio]; - - if (test_bit(FLAG_EXPORT, &desc->flags)) { - struct device *tdev; - - tdev = class_find_device(&gpio_class, NULL, desc, match_export); - if (tdev != NULL) { - status = sysfs_create_link(&dev->kobj, &tdev->kobj, - name); - } else { - status = -ENODEV; - } - } - - mutex_unlock(&sysfs_lock); - -done: - if (status) - pr_debug("%s: gpio%d status %d\n", __func__, gpio, status); - - return status; -} -EXPORT_SYMBOL_GPL(gpio_export_link); - /** * gpio_unexport - reverse effect of gpio_export() * @gpio: gpio to make unavailable @@ -767,7 +527,6 @@ void gpio_unexport(unsigned gpio) dev = class_find_device(&gpio_class, NULL, desc, match_export); if (dev) { - gpio_setup_irq(desc, dev, 0); clear_bit(FLAG_EXPORT, &desc->flags); put_device(dev); device_unregister(dev); @@ -852,8 +611,6 @@ static int __init gpiolib_sysfs_init(void) unsigned long flags; unsigned gpio; - idr_init(&pdesc_idr); - status = class_register(&gpio_class); if (status < 0) return status; diff --git a/trunk/drivers/gpio/langwell_gpio.c b/trunk/drivers/gpio/langwell_gpio.c deleted file mode 100644 index 5711ce5353c6..000000000000 --- a/trunk/drivers/gpio/langwell_gpio.c +++ /dev/null @@ -1,297 +0,0 @@ -/* langwell_gpio.c Moorestown platform Langwell chip GPIO driver - * Copyright (c) 2008 - 2009, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Moorestown platform Langwell chip. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -struct lnw_gpio_register { - u32 GPLR[2]; - u32 GPDR[2]; - u32 GPSR[2]; - u32 GPCR[2]; - u32 GRER[2]; - u32 GFER[2]; - u32 GEDR[2]; -}; - -struct lnw_gpio { - struct gpio_chip chip; - struct lnw_gpio_register *reg_base; - spinlock_t lock; - unsigned irq_base; -}; - -static int lnw_gpio_get(struct gpio_chip *chip, unsigned offset) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - u8 reg = offset / 32; - void __iomem *gplr; - - gplr = (void __iomem *)(&lnw->reg_base->GPLR[reg]); - return readl(gplr) & BIT(offset % 32); -} - -static void lnw_gpio_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - u8 reg = offset / 32; - void __iomem *gpsr, *gpcr; - - if (value) { - gpsr = (void __iomem *)(&lnw->reg_base->GPSR[reg]); - writel(BIT(offset % 32), gpsr); - } else { - gpcr = (void __iomem *)(&lnw->reg_base->GPCR[reg]); - writel(BIT(offset % 32), gpcr); - } -} - -static int lnw_gpio_direction_input(struct gpio_chip *chip, unsigned offset) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - u8 reg = offset / 32; - u32 value; - unsigned long flags; - void __iomem *gpdr; - - gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]); - spin_lock_irqsave(&lnw->lock, flags); - value = readl(gpdr); - value &= ~BIT(offset % 32); - writel(value, gpdr); - spin_unlock_irqrestore(&lnw->lock, flags); - return 0; -} - -static int lnw_gpio_direction_output(struct gpio_chip *chip, - unsigned offset, int value) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - u8 reg = offset / 32; - unsigned long flags; - void __iomem *gpdr; - - lnw_gpio_set(chip, offset, value); - gpdr = (void __iomem *)(&lnw->reg_base->GPDR[reg]); - spin_lock_irqsave(&lnw->lock, flags); - value = readl(gpdr); - value |= BIT(offset % 32);; - writel(value, gpdr); - spin_unlock_irqrestore(&lnw->lock, flags); - return 0; -} - -static int lnw_gpio_to_irq(struct gpio_chip *chip, unsigned offset) -{ - struct lnw_gpio *lnw = container_of(chip, struct lnw_gpio, chip); - return lnw->irq_base + offset; -} - -static int lnw_irq_type(unsigned irq, unsigned type) -{ - struct lnw_gpio *lnw = get_irq_chip_data(irq); - u32 gpio = irq - lnw->irq_base; - u8 reg = gpio / 32; - unsigned long flags; - u32 value; - void __iomem *grer = (void __iomem *)(&lnw->reg_base->GRER[reg]); - void __iomem *gfer = (void __iomem *)(&lnw->reg_base->GFER[reg]); - - if (gpio < 0 || gpio > lnw->chip.ngpio) - return -EINVAL; - spin_lock_irqsave(&lnw->lock, flags); - if (type & IRQ_TYPE_EDGE_RISING) - value = readl(grer) | BIT(gpio % 32); - else - value = readl(grer) & (~BIT(gpio % 32)); - writel(value, grer); - - if (type & IRQ_TYPE_EDGE_FALLING) - value = readl(gfer) | BIT(gpio % 32); - else - value = readl(gfer) & (~BIT(gpio % 32)); - writel(value, gfer); - spin_unlock_irqrestore(&lnw->lock, flags); - - return 0; -}; - -static void lnw_irq_unmask(unsigned irq) -{ - struct lnw_gpio *lnw = get_irq_chip_data(irq); - u32 gpio = irq - lnw->irq_base; - u8 reg = gpio / 32; - void __iomem *gedr; - - gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]); - writel(BIT(gpio % 32), gedr); -}; - -static void lnw_irq_mask(unsigned irq) -{ -}; - -static struct irq_chip lnw_irqchip = { - .name = "LNW-GPIO", - .mask = lnw_irq_mask, - .unmask = lnw_irq_unmask, - .set_type = lnw_irq_type, -}; - -static struct pci_device_id lnw_gpio_ids[] = { - { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080f) }, - { 0, } -}; -MODULE_DEVICE_TABLE(pci, lnw_gpio_ids); - -static void lnw_irq_handler(unsigned irq, struct irq_desc *desc) -{ - struct lnw_gpio *lnw = (struct lnw_gpio *)get_irq_data(irq); - u32 reg, gpio; - void __iomem *gedr; - u32 gedr_v; - - /* check GPIO controller to check which pin triggered the interrupt */ - for (reg = 0; reg < lnw->chip.ngpio / 32; reg++) { - gedr = (void __iomem *)(&lnw->reg_base->GEDR[reg]); - gedr_v = readl(gedr); - if (!gedr_v) - continue; - for (gpio = reg*32; gpio < reg*32+32; gpio++) { - gedr_v = readl(gedr); - if (gedr_v & BIT(gpio % 32)) { - pr_debug("pin %d triggered\n", gpio); - generic_handle_irq(lnw->irq_base + gpio); - } - } - /* clear the edge detect status bit */ - writel(gedr_v, gedr); - } - desc->chip->eoi(irq); -} - -static int __devinit lnw_gpio_probe(struct pci_dev *pdev, - const struct pci_device_id *id) -{ - void *base; - int i; - resource_size_t start, len; - struct lnw_gpio *lnw; - u32 irq_base; - u32 gpio_base; - int retval = 0; - - retval = pci_enable_device(pdev); - if (retval) - goto done; - - retval = pci_request_regions(pdev, "langwell_gpio"); - if (retval) { - dev_err(&pdev->dev, "error requesting resources\n"); - goto err2; - } - /* get the irq_base from bar1 */ - start = pci_resource_start(pdev, 1); - len = pci_resource_len(pdev, 1); - base = ioremap_nocache(start, len); - if (!base) { - dev_err(&pdev->dev, "error mapping bar1\n"); - goto err3; - } - irq_base = *(u32 *)base; - gpio_base = *((u32 *)base + 1); - /* release the IO mapping, since we already get the info from bar1 */ - iounmap(base); - /* get the register base from bar0 */ - start = pci_resource_start(pdev, 0); - len = pci_resource_len(pdev, 0); - base = ioremap_nocache(start, len); - if (!base) { - dev_err(&pdev->dev, "error mapping bar0\n"); - retval = -EFAULT; - goto err3; - } - - lnw = kzalloc(sizeof(struct lnw_gpio), GFP_KERNEL); - if (!lnw) { - dev_err(&pdev->dev, "can't allocate langwell_gpio chip data\n"); - retval = -ENOMEM; - goto err4; - } - lnw->reg_base = base; - lnw->irq_base = irq_base; - lnw->chip.label = dev_name(&pdev->dev); - lnw->chip.direction_input = lnw_gpio_direction_input; - lnw->chip.direction_output = lnw_gpio_direction_output; - lnw->chip.get = lnw_gpio_get; - lnw->chip.set = lnw_gpio_set; - lnw->chip.to_irq = lnw_gpio_to_irq; - lnw->chip.base = gpio_base; - lnw->chip.ngpio = 64; - lnw->chip.can_sleep = 0; - pci_set_drvdata(pdev, lnw); - retval = gpiochip_add(&lnw->chip); - if (retval) { - dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval); - goto err5; - } - set_irq_data(pdev->irq, lnw); - set_irq_chained_handler(pdev->irq, lnw_irq_handler); - for (i = 0; i < lnw->chip.ngpio; i++) { - set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip, - handle_simple_irq, "demux"); - set_irq_chip_data(i + lnw->irq_base, lnw); - } - - spin_lock_init(&lnw->lock); - goto done; -err5: - kfree(lnw); -err4: - iounmap(base); -err3: - pci_release_regions(pdev); -err2: - pci_disable_device(pdev); -done: - return retval; -} - -static struct pci_driver lnw_gpio_driver = { - .name = "langwell_gpio", - .id_table = lnw_gpio_ids, - .probe = lnw_gpio_probe, -}; - -static int __init lnw_gpio_init(void) -{ - return pci_register_driver(&lnw_gpio_driver); -} - -device_initcall(lnw_gpio_init); diff --git a/trunk/drivers/gpio/max7301.c b/trunk/drivers/gpio/max7301.c index 480956f1ca50..7b82eaae2621 100644 --- a/trunk/drivers/gpio/max7301.c +++ b/trunk/drivers/gpio/max7301.c @@ -339,4 +339,3 @@ module_exit(max7301_exit); MODULE_AUTHOR("Juergen Beisert"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("MAX7301 SPI based GPIO-Expander"); -MODULE_ALIAS("spi:" DRIVER_NAME); diff --git a/trunk/drivers/gpio/mc33880.c b/trunk/drivers/gpio/mc33880.c deleted file mode 100644 index e7d01bd8fdb3..000000000000 --- a/trunk/drivers/gpio/mc33880.c +++ /dev/null @@ -1,196 +0,0 @@ -/* - * mc33880.c MC33880 high-side/low-side switch GPIO driver - * Copyright (c) 2009 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - -/* Supports: - * Freescale MC33880 high-side/low-side switch - */ - -#include -#include -#include -#include -#include - -#define DRIVER_NAME "mc33880" - -/* - * Pin configurations, see MAX7301 datasheet page 6 - */ -#define PIN_CONFIG_MASK 0x03 -#define PIN_CONFIG_IN_PULLUP 0x03 -#define PIN_CONFIG_IN_WO_PULLUP 0x02 -#define PIN_CONFIG_OUT 0x01 - -#define PIN_NUMBER 8 - - -/* - * Some registers must be read back to modify. - * To save time we cache them here in memory - */ -struct mc33880 { - struct mutex lock; /* protect from simultanous accesses */ - u8 port_config; - struct gpio_chip chip; - struct spi_device *spi; -}; - -static int mc33880_write_config(struct mc33880 *mc) -{ - return spi_write(mc->spi, &mc->port_config, sizeof(mc->port_config)); -} - - -static int __mc33880_set(struct mc33880 *mc, unsigned offset, int value) -{ - if (value) - mc->port_config |= 1 << offset; - else - mc->port_config &= ~(1 << offset); - - return mc33880_write_config(mc); -} - - -static void mc33880_set(struct gpio_chip *chip, unsigned offset, int value) -{ - struct mc33880 *mc = container_of(chip, struct mc33880, chip); - - mutex_lock(&mc->lock); - - __mc33880_set(mc, offset, value); - - mutex_unlock(&mc->lock); -} - -static int __devinit mc33880_probe(struct spi_device *spi) -{ - struct mc33880 *mc; - struct mc33880_platform_data *pdata; - int ret; - - pdata = spi->dev.platform_data; - if (!pdata || !pdata->base) { - dev_dbg(&spi->dev, "incorrect or missing platform data\n"); - return -EINVAL; - } - - /* - * bits_per_word cannot be configured in platform data - */ - spi->bits_per_word = 8; - - ret = spi_setup(spi); - if (ret < 0) - return ret; - - mc = kzalloc(sizeof(struct mc33880), GFP_KERNEL); - if (!mc) - return -ENOMEM; - - mutex_init(&mc->lock); - - dev_set_drvdata(&spi->dev, mc); - - mc->spi = spi; - - mc->chip.label = DRIVER_NAME, - mc->chip.set = mc33880_set; - mc->chip.base = pdata->base; - mc->chip.ngpio = PIN_NUMBER; - mc->chip.can_sleep = 1; - mc->chip.dev = &spi->dev; - mc->chip.owner = THIS_MODULE; - - mc->port_config = 0x00; - /* write twice, because during initialisation the first setting - * is just for testing SPI communication, and the second is the - * "real" configuration - */ - ret = mc33880_write_config(mc); - mc->port_config = 0x00; - if (!ret) - ret = mc33880_write_config(mc); - - if (ret) { - printk(KERN_ERR "Failed writing to " DRIVER_NAME ": %d\n", ret); - goto exit_destroy; - } - - ret = gpiochip_add(&mc->chip); - if (ret) - goto exit_destroy; - - return ret; - -exit_destroy: - dev_set_drvdata(&spi->dev, NULL); - mutex_destroy(&mc->lock); - kfree(mc); - return ret; -} - -static int mc33880_remove(struct spi_device *spi) -{ - struct mc33880 *mc; - int ret; - - mc = dev_get_drvdata(&spi->dev); - if (mc == NULL) - return -ENODEV; - - dev_set_drvdata(&spi->dev, NULL); - - ret = gpiochip_remove(&mc->chip); - if (!ret) { - mutex_destroy(&mc->lock); - kfree(mc); - } else - dev_err(&spi->dev, "Failed to remove the GPIO controller: %d\n", - ret); - - return ret; -} - -static struct spi_driver mc33880_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = mc33880_probe, - .remove = __devexit_p(mc33880_remove), -}; - -static int __init mc33880_init(void) -{ - return spi_register_driver(&mc33880_driver); -} -/* register after spi postcore initcall and before - * subsys initcalls that may rely on these GPIOs - */ -subsys_initcall(mc33880_init); - -static void __exit mc33880_exit(void) -{ - spi_unregister_driver(&mc33880_driver); -} -module_exit(mc33880_exit); - -MODULE_AUTHOR("Mocean Laboratories "); -MODULE_LICENSE("GPL v2"); - diff --git a/trunk/drivers/gpio/mcp23s08.c b/trunk/drivers/gpio/mcp23s08.c index cd651ec8d034..f6fae0e50e65 100644 --- a/trunk/drivers/gpio/mcp23s08.c +++ b/trunk/drivers/gpio/mcp23s08.c @@ -6,10 +6,12 @@ #include #include #include -#include + #include #include +#include + /* Registers are all 8 bits wide. * @@ -431,4 +433,3 @@ static void __exit mcp23s08_exit(void) module_exit(mcp23s08_exit); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:mcp23s08"); diff --git a/trunk/drivers/gpio/pca953x.c b/trunk/drivers/gpio/pca953x.c index 6a2fb3fbb3d9..cdb6574d25a6 100644 --- a/trunk/drivers/gpio/pca953x.c +++ b/trunk/drivers/gpio/pca953x.c @@ -13,7 +13,6 @@ #include #include -#include #include #include #ifdef CONFIG_OF_GPIO @@ -21,6 +20,8 @@ #include #endif +#include + #define PCA953X_INPUT 0 #define PCA953X_OUTPUT 1 #define PCA953X_INVERT 2 @@ -39,7 +40,6 @@ static const struct i2c_device_id pca953x_id[] = { { "pca9557", 8, }, { "max7310", 8, }, - { "max7315", 8, }, { "pca6107", 8, }, { "tca6408", 8, }, { "tca6416", 16, }, diff --git a/trunk/drivers/gpio/pcf857x.c b/trunk/drivers/gpio/pcf857x.c index 29f19ce3e80f..9525724be731 100644 --- a/trunk/drivers/gpio/pcf857x.c +++ b/trunk/drivers/gpio/pcf857x.c @@ -20,14 +20,14 @@ #include #include -#include #include #include +#include + static const struct i2c_device_id pcf857x_id[] = { { "pcf8574", 8 }, - { "pcf8574a", 8 }, { "pca8574", 8 }, { "pca9670", 8 }, { "pca9672", 8 }, diff --git a/trunk/drivers/gpio/ucb1400_gpio.c b/trunk/drivers/gpio/ucb1400_gpio.c deleted file mode 100644 index 50e6bd1392ce..000000000000 --- a/trunk/drivers/gpio/ucb1400_gpio.c +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Philips UCB1400 GPIO driver - * - * Author: Marek Vasut - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include - -struct ucb1400_gpio_data *ucbdata; - -static int ucb1400_gpio_dir_in(struct gpio_chip *gc, unsigned off) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - ucb1400_gpio_set_direction(gpio->ac97, off, 0); - return 0; -} - -static int ucb1400_gpio_dir_out(struct gpio_chip *gc, unsigned off, int val) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - ucb1400_gpio_set_direction(gpio->ac97, off, 1); - ucb1400_gpio_set_value(gpio->ac97, off, val); - return 0; -} - -static int ucb1400_gpio_get(struct gpio_chip *gc, unsigned off) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - return ucb1400_gpio_get_value(gpio->ac97, off); -} - -static void ucb1400_gpio_set(struct gpio_chip *gc, unsigned off, int val) -{ - struct ucb1400_gpio *gpio; - gpio = container_of(gc, struct ucb1400_gpio, gc); - ucb1400_gpio_set_value(gpio->ac97, off, val); -} - -static int ucb1400_gpio_probe(struct platform_device *dev) -{ - struct ucb1400_gpio *ucb = dev->dev.platform_data; - int err = 0; - - if (!(ucbdata && ucbdata->gpio_offset)) { - err = -EINVAL; - goto err; - } - - platform_set_drvdata(dev, ucb); - - ucb->gc.label = "ucb1400_gpio"; - ucb->gc.base = ucbdata->gpio_offset; - ucb->gc.ngpio = 10; - ucb->gc.owner = THIS_MODULE; - - ucb->gc.direction_input = ucb1400_gpio_dir_in; - ucb->gc.direction_output = ucb1400_gpio_dir_out; - ucb->gc.get = ucb1400_gpio_get; - ucb->gc.set = ucb1400_gpio_set; - ucb->gc.can_sleep = 1; - - err = gpiochip_add(&ucb->gc); - if (err) - goto err; - - if (ucbdata && ucbdata->gpio_setup) - err = ucbdata->gpio_setup(&dev->dev, ucb->gc.ngpio); - -err: - return err; - -} - -static int ucb1400_gpio_remove(struct platform_device *dev) -{ - int err = 0; - struct ucb1400_gpio *ucb = platform_get_drvdata(dev); - - if (ucbdata && ucbdata->gpio_teardown) { - err = ucbdata->gpio_teardown(&dev->dev, ucb->gc.ngpio); - if (err) - return err; - } - - err = gpiochip_remove(&ucb->gc); - return err; -} - -static struct platform_driver ucb1400_gpio_driver = { - .probe = ucb1400_gpio_probe, - .remove = ucb1400_gpio_remove, - .driver = { - .name = "ucb1400_gpio" - }, -}; - -static int __init ucb1400_gpio_init(void) -{ - return platform_driver_register(&ucb1400_gpio_driver); -} - -static void __exit ucb1400_gpio_exit(void) -{ - platform_driver_unregister(&ucb1400_gpio_driver); -} - -void __init ucb1400_gpio_set_data(struct ucb1400_gpio_data *data) -{ - ucbdata = data; -} - -module_init(ucb1400_gpio_init); -module_exit(ucb1400_gpio_exit); - -MODULE_DESCRIPTION("Philips UCB1400 GPIO driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/hwmon/adcxx.c b/trunk/drivers/hwmon/adcxx.c index 5e9e095f1136..242294db3db6 100644 --- a/trunk/drivers/hwmon/adcxx.c +++ b/trunk/drivers/hwmon/adcxx.c @@ -43,7 +43,6 @@ #include #include #include -#include #include #define DRVNAME "adcxx" @@ -158,9 +157,8 @@ static struct sensor_device_attribute ad_input[] = { /*----------------------------------------------------------------------*/ -static int __devinit adcxx_probe(struct spi_device *spi) +static int __devinit adcxx_probe(struct spi_device *spi, int channels) { - int channels = spi_get_device_id(spi)->driver_data; struct adcxx *adc; int status; int i; @@ -206,6 +204,26 @@ static int __devinit adcxx_probe(struct spi_device *spi) return status; } +static int __devinit adcxx1s_probe(struct spi_device *spi) +{ + return adcxx_probe(spi, 1); +} + +static int __devinit adcxx2s_probe(struct spi_device *spi) +{ + return adcxx_probe(spi, 2); +} + +static int __devinit adcxx4s_probe(struct spi_device *spi) +{ + return adcxx_probe(spi, 4); +} + +static int __devinit adcxx8s_probe(struct spi_device *spi) +{ + return adcxx_probe(spi, 8); +} + static int __devexit adcxx_remove(struct spi_device *spi) { struct adcxx *adc = dev_get_drvdata(&spi->dev); @@ -223,33 +241,79 @@ static int __devexit adcxx_remove(struct spi_device *spi) return 0; } -static const struct spi_device_id adcxx_ids[] = { - { "adcxx1s", 1 }, - { "adcxx2s", 2 }, - { "adcxx4s", 4 }, - { "adcxx8s", 8 }, - { }, +static struct spi_driver adcxx1s_driver = { + .driver = { + .name = "adcxx1s", + .owner = THIS_MODULE, + }, + .probe = adcxx1s_probe, + .remove = __devexit_p(adcxx_remove), }; -MODULE_DEVICE_TABLE(spi, adcxx_ids); -static struct spi_driver adcxx_driver = { +static struct spi_driver adcxx2s_driver = { .driver = { - .name = "adcxx", + .name = "adcxx2s", .owner = THIS_MODULE, }, - .id_table = adcxx_ids, - .probe = adcxx_probe, + .probe = adcxx2s_probe, + .remove = __devexit_p(adcxx_remove), +}; + +static struct spi_driver adcxx4s_driver = { + .driver = { + .name = "adcxx4s", + .owner = THIS_MODULE, + }, + .probe = adcxx4s_probe, + .remove = __devexit_p(adcxx_remove), +}; + +static struct spi_driver adcxx8s_driver = { + .driver = { + .name = "adcxx8s", + .owner = THIS_MODULE, + }, + .probe = adcxx8s_probe, .remove = __devexit_p(adcxx_remove), }; static int __init init_adcxx(void) { - return spi_register_driver(&adcxx_driver); + int status; + status = spi_register_driver(&adcxx1s_driver); + if (status) + goto reg_1_failed; + + status = spi_register_driver(&adcxx2s_driver); + if (status) + goto reg_2_failed; + + status = spi_register_driver(&adcxx4s_driver); + if (status) + goto reg_4_failed; + + status = spi_register_driver(&adcxx8s_driver); + if (status) + goto reg_8_failed; + + return status; + +reg_8_failed: + spi_unregister_driver(&adcxx4s_driver); +reg_4_failed: + spi_unregister_driver(&adcxx2s_driver); +reg_2_failed: + spi_unregister_driver(&adcxx1s_driver); +reg_1_failed: + return status; } static void __exit exit_adcxx(void) { - spi_unregister_driver(&adcxx_driver); + spi_unregister_driver(&adcxx1s_driver); + spi_unregister_driver(&adcxx2s_driver); + spi_unregister_driver(&adcxx4s_driver); + spi_unregister_driver(&adcxx8s_driver); } module_init(init_adcxx); @@ -258,3 +322,8 @@ module_exit(exit_adcxx); MODULE_AUTHOR("Marc Pignat"); MODULE_DESCRIPTION("National Semiconductor adcxx8sxxx Linux driver"); MODULE_LICENSE("GPL"); + +MODULE_ALIAS("adcxx1s"); +MODULE_ALIAS("adcxx2s"); +MODULE_ALIAS("adcxx4s"); +MODULE_ALIAS("adcxx8s"); diff --git a/trunk/drivers/hwmon/dme1737.c b/trunk/drivers/hwmon/dme1737.c index 2c2cb1ec94c5..9814d51b3af4 100644 --- a/trunk/drivers/hwmon/dme1737.c +++ b/trunk/drivers/hwmon/dme1737.c @@ -1134,7 +1134,7 @@ static ssize_t show_pwm(struct device *dev, struct device_attribute *attr, res = PWM_FREQ_FROM_REG(data->pwm_freq[ix]); break; case SYS_PWM_ENABLE: - if (ix >= 3) { + if (ix > 3) { res = 1; /* pwm[5-6] hard-wired to manual mode */ } else { res = PWM_EN_FROM_REG(data->pwm_config[ix]); diff --git a/trunk/drivers/hwmon/lis3lv02d_spi.c b/trunk/drivers/hwmon/lis3lv02d_spi.c index ecd739534f6a..82ebca5a699c 100644 --- a/trunk/drivers/hwmon/lis3lv02d_spi.c +++ b/trunk/drivers/hwmon/lis3lv02d_spi.c @@ -139,4 +139,4 @@ module_exit(lis302dl_exit); MODULE_AUTHOR("Daniel Mack "); MODULE_DESCRIPTION("lis3lv02d SPI glue layer"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:" DRV_NAME); + diff --git a/trunk/drivers/hwmon/lm70.c b/trunk/drivers/hwmon/lm70.c index ab8a5d3c7690..ae6204f33214 100644 --- a/trunk/drivers/hwmon/lm70.c +++ b/trunk/drivers/hwmon/lm70.c @@ -32,7 +32,6 @@ #include #include #include -#include #include @@ -131,20 +130,11 @@ static DEVICE_ATTR(name, S_IRUGO, lm70_show_name, NULL); /*----------------------------------------------------------------------*/ -static int __devinit lm70_probe(struct spi_device *spi) +static int __devinit common_probe(struct spi_device *spi, int chip) { - int chip = spi_get_device_id(spi)->driver_data; struct lm70 *p_lm70; int status; - /* signaling is SPI_MODE_0 for both LM70 and TMP121 */ - if (spi->mode & (SPI_CPOL | SPI_CPHA)) - return -EINVAL; - - /* 3-wire link (shared SI/SO) for LM70 */ - if (chip == LM70_CHIP_LM70 && !(spi->mode & SPI_3WIRE)) - return -EINVAL; - /* NOTE: we assume 8-bit words, and convert to 16 bits manually */ p_lm70 = kzalloc(sizeof *p_lm70, GFP_KERNEL); @@ -180,6 +170,24 @@ static int __devinit lm70_probe(struct spi_device *spi) return status; } +static int __devinit lm70_probe(struct spi_device *spi) +{ + /* signaling is SPI_MODE_0 on a 3-wire link (shared SI/SO) */ + if ((spi->mode & (SPI_CPOL | SPI_CPHA)) || !(spi->mode & SPI_3WIRE)) + return -EINVAL; + + return common_probe(spi, LM70_CHIP_LM70); +} + +static int __devinit tmp121_probe(struct spi_device *spi) +{ + /* signaling is SPI_MODE_0 with only MISO connected */ + if (spi->mode & (SPI_CPOL | SPI_CPHA)) + return -EINVAL; + + return common_probe(spi, LM70_CHIP_TMP121); +} + static int __devexit lm70_remove(struct spi_device *spi) { struct lm70 *p_lm70 = dev_get_drvdata(&spi->dev); @@ -193,32 +201,41 @@ static int __devexit lm70_remove(struct spi_device *spi) return 0; } - -static const struct spi_device_id lm70_ids[] = { - { "lm70", LM70_CHIP_LM70 }, - { "tmp121", LM70_CHIP_TMP121 }, - { }, +static struct spi_driver tmp121_driver = { + .driver = { + .name = "tmp121", + .owner = THIS_MODULE, + }, + .probe = tmp121_probe, + .remove = __devexit_p(lm70_remove), }; -MODULE_DEVICE_TABLE(spi, lm70_ids); static struct spi_driver lm70_driver = { .driver = { .name = "lm70", .owner = THIS_MODULE, }, - .id_table = lm70_ids, .probe = lm70_probe, .remove = __devexit_p(lm70_remove), }; static int __init init_lm70(void) { - return spi_register_driver(&lm70_driver); + int ret = spi_register_driver(&lm70_driver); + if (ret) + return ret; + + ret = spi_register_driver(&tmp121_driver); + if (ret) + spi_unregister_driver(&lm70_driver); + + return ret; } static void __exit cleanup_lm70(void) { spi_unregister_driver(&lm70_driver); + spi_unregister_driver(&tmp121_driver); } module_init(init_lm70); diff --git a/trunk/drivers/hwmon/max1111.c b/trunk/drivers/hwmon/max1111.c index 9ac497271adf..bfaa665ccf32 100644 --- a/trunk/drivers/hwmon/max1111.c +++ b/trunk/drivers/hwmon/max1111.c @@ -242,4 +242,3 @@ module_exit(max1111_exit); MODULE_AUTHOR("Eric Miao "); MODULE_DESCRIPTION("MAX1111 ADC Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:max1111"); diff --git a/trunk/drivers/i2c/Kconfig b/trunk/drivers/i2c/Kconfig index d7ece131b4f4..711ca08ab776 100644 --- a/trunk/drivers/i2c/Kconfig +++ b/trunk/drivers/i2c/Kconfig @@ -27,14 +27,6 @@ config I2C_BOARDINFO boolean default y -config I2C_COMPAT - boolean "Enable compatibility bits for old user-space" - default y - help - Say Y here if you intend to run lm-sensors 3.1.1 or older, or any - other user-space package which expects i2c adapters to be class - devices. If you don't know, say Y. - config I2C_CHARDEV tristate "I2C device interface" help diff --git a/trunk/drivers/i2c/busses/Kconfig b/trunk/drivers/i2c/busses/Kconfig index 6bedd2fcfc15..8206442fbabd 100644 --- a/trunk/drivers/i2c/busses/Kconfig +++ b/trunk/drivers/i2c/busses/Kconfig @@ -113,7 +113,7 @@ config I2C_ISCH will be called i2c-isch. config I2C_PIIX4 - tristate "Intel PIIX4 and compatible (ATI/AMD/Serverworks/Broadcom/SMSC)" + tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)" depends on PCI help If you say yes to this option, support will be included for the Intel @@ -128,7 +128,6 @@ config I2C_PIIX4 ATI SB600 ATI SB700 ATI SB800 - AMD SB900 Serverworks OSB4 Serverworks CSB5 Serverworks CSB6 @@ -232,22 +231,6 @@ config I2C_VIAPRO This driver can also be built as a module. If so, the module will be called i2c-viapro. -if ACPI - -comment "ACPI drivers" - -config I2C_SCMI - tristate "SMBus Control Method Interface" - help - This driver supports the SMBus Control Method Interface. It needs the - BIOS to declare ACPI control methods as described in the SMBus Control - Method Interface specification. - - To compile this driver as a module, choose M here: - the module will be called i2c-scmi. - -endif # ACPI - comment "Mac SMBus host controller drivers" depends on PPC_CHRP || PPC_PMAC diff --git a/trunk/drivers/i2c/busses/Makefile b/trunk/drivers/i2c/busses/Makefile index ff937ac69f5b..e654263bfc01 100644 --- a/trunk/drivers/i2c/busses/Makefile +++ b/trunk/drivers/i2c/busses/Makefile @@ -2,9 +2,6 @@ # Makefile for the i2c bus drivers. # -# ACPI drivers -obj-$(CONFIG_I2C_SCMI) += i2c-scmi.o - # PC SMBus host controller drivers obj-$(CONFIG_I2C_ALI1535) += i2c-ali1535.o obj-$(CONFIG_I2C_ALI1563) += i2c-ali1563.o diff --git a/trunk/drivers/i2c/busses/i2c-piix4.c b/trunk/drivers/i2c/busses/i2c-piix4.c index a782c7a08f9e..0249a7d762b9 100644 --- a/trunk/drivers/i2c/busses/i2c-piix4.c +++ b/trunk/drivers/i2c/busses/i2c-piix4.c @@ -22,7 +22,6 @@ Intel PIIX4, 440MX Serverworks OSB4, CSB5, CSB6, HT-1000, HT-1100 ATI IXP200, IXP300, IXP400, SB600, SB700, SB800 - AMD SB900 SMSC Victory66 Note: we assume there can only be one device, with one SMBus interface. @@ -480,7 +479,6 @@ static struct pci_device_id piix4_ids[] = { { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP300_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_IXP400_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_DEVICE_ID_ATI_SBX00_SMBUS) }, - { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SB900_SMBUS) }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4) }, { PCI_DEVICE(PCI_VENDOR_ID_SERVERWORKS, @@ -501,10 +499,9 @@ static int __devinit piix4_probe(struct pci_dev *dev, { int retval; - if ((dev->vendor == PCI_VENDOR_ID_ATI && - dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS && - dev->revision >= 0x40) || - dev->vendor == PCI_VENDOR_ID_AMD) + if ((dev->vendor == PCI_VENDOR_ID_ATI) && + (dev->device == PCI_DEVICE_ID_ATI_SBX00_SMBUS) && + (dev->revision >= 0x40)) /* base address location etc changed in SB800 */ retval = piix4_setup_sb800(dev, id); else diff --git a/trunk/drivers/i2c/busses/i2c-pnx.c b/trunk/drivers/i2c/busses/i2c-pnx.c index 6ff6c20f1e78..ec15cff556b9 100644 --- a/trunk/drivers/i2c/busses/i2c-pnx.c +++ b/trunk/drivers/i2c/busses/i2c-pnx.c @@ -586,8 +586,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) alg_data->mif.timer.data = (unsigned long)i2c_pnx->adapter; /* Register I/O resource */ - if (!request_mem_region(alg_data->base, I2C_PNX_REGION_SIZE, - pdev->name)) { + if (!request_region(alg_data->base, I2C_PNX_REGION_SIZE, pdev->name)) { dev_err(&pdev->dev, "I/O region 0x%08x for I2C already in use.\n", alg_data->base); @@ -651,7 +650,7 @@ static int __devinit i2c_pnx_probe(struct platform_device *pdev) out_unmap: iounmap((void *)alg_data->ioaddr); out_release: - release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); + release_region(alg_data->base, I2C_PNX_REGION_SIZE); out_drvdata: platform_set_drvdata(pdev, NULL); out: @@ -668,7 +667,7 @@ static int __devexit i2c_pnx_remove(struct platform_device *pdev) i2c_del_adapter(adap); i2c_pnx->set_clock_stop(pdev); iounmap((void *)alg_data->ioaddr); - release_mem_region(alg_data->base, I2C_PNX_REGION_SIZE); + release_region(alg_data->base, I2C_PNX_REGION_SIZE); platform_set_drvdata(pdev, NULL); return 0; diff --git a/trunk/drivers/i2c/busses/i2c-scmi.c b/trunk/drivers/i2c/busses/i2c-scmi.c deleted file mode 100644 index 276a046ac93f..000000000000 --- a/trunk/drivers/i2c/busses/i2c-scmi.c +++ /dev/null @@ -1,430 +0,0 @@ -/* - * SMBus driver for ACPI SMBus CMI - * - * Copyright (C) 2009 Crane Cai - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation version 2. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define ACPI_SMBUS_HC_CLASS "smbus" -#define ACPI_SMBUS_HC_DEVICE_NAME "cmi" - -ACPI_MODULE_NAME("smbus_cmi"); - -struct smbus_methods_t { - char *mt_info; - char *mt_sbr; - char *mt_sbw; -}; - -struct acpi_smbus_cmi { - acpi_handle handle; - struct i2c_adapter adapter; - u8 cap_info:1; - u8 cap_read:1; - u8 cap_write:1; -}; - -static const struct smbus_methods_t smbus_methods = { - .mt_info = "_SBI", - .mt_sbr = "_SBR", - .mt_sbw = "_SBW", -}; - -static const struct acpi_device_id acpi_smbus_cmi_ids[] = { - {"SMBUS01", 0}, - {"", 0} -}; - -#define ACPI_SMBUS_STATUS_OK 0x00 -#define ACPI_SMBUS_STATUS_FAIL 0x07 -#define ACPI_SMBUS_STATUS_DNAK 0x10 -#define ACPI_SMBUS_STATUS_DERR 0x11 -#define ACPI_SMBUS_STATUS_CMD_DENY 0x12 -#define ACPI_SMBUS_STATUS_UNKNOWN 0x13 -#define ACPI_SMBUS_STATUS_ACC_DENY 0x17 -#define ACPI_SMBUS_STATUS_TIMEOUT 0x18 -#define ACPI_SMBUS_STATUS_NOTSUP 0x19 -#define ACPI_SMBUS_STATUS_BUSY 0x1a -#define ACPI_SMBUS_STATUS_PEC 0x1f - -#define ACPI_SMBUS_PRTCL_WRITE 0x00 -#define ACPI_SMBUS_PRTCL_READ 0x01 -#define ACPI_SMBUS_PRTCL_QUICK 0x02 -#define ACPI_SMBUS_PRTCL_BYTE 0x04 -#define ACPI_SMBUS_PRTCL_BYTE_DATA 0x06 -#define ACPI_SMBUS_PRTCL_WORD_DATA 0x08 -#define ACPI_SMBUS_PRTCL_BLOCK_DATA 0x0a - - -static int -acpi_smbus_cmi_access(struct i2c_adapter *adap, u16 addr, unsigned short flags, - char read_write, u8 command, int size, - union i2c_smbus_data *data) -{ - int result = 0; - struct acpi_smbus_cmi *smbus_cmi = adap->algo_data; - unsigned char protocol; - acpi_status status = 0; - struct acpi_object_list input; - union acpi_object mt_params[5]; - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - union acpi_object *pkg; - char *method; - int len = 0; - - dev_dbg(&adap->dev, "access size: %d %s\n", size, - (read_write) ? "READ" : "WRITE"); - switch (size) { - case I2C_SMBUS_QUICK: - protocol = ACPI_SMBUS_PRTCL_QUICK; - command = 0; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 0; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = 0; - } - break; - - case I2C_SMBUS_BYTE: - protocol = ACPI_SMBUS_PRTCL_BYTE; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 0; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = 0; - } else { - command = 0; - } - break; - - case I2C_SMBUS_BYTE_DATA: - protocol = ACPI_SMBUS_PRTCL_BYTE_DATA; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 1; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = data->byte; - } - break; - - case I2C_SMBUS_WORD_DATA: - protocol = ACPI_SMBUS_PRTCL_WORD_DATA; - if (read_write == I2C_SMBUS_WRITE) { - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = 2; - mt_params[4].type = ACPI_TYPE_INTEGER; - mt_params[4].integer.value = data->word; - } - break; - - case I2C_SMBUS_BLOCK_DATA: - protocol = ACPI_SMBUS_PRTCL_BLOCK_DATA; - if (read_write == I2C_SMBUS_WRITE) { - len = data->block[0]; - if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) - return -EINVAL; - mt_params[3].type = ACPI_TYPE_INTEGER; - mt_params[3].integer.value = len; - mt_params[4].type = ACPI_TYPE_BUFFER; - mt_params[4].buffer.pointer = data->block + 1; - } - break; - - default: - dev_warn(&adap->dev, "Unsupported transaction %d\n", size); - return -EOPNOTSUPP; - } - - if (read_write == I2C_SMBUS_READ) { - protocol |= ACPI_SMBUS_PRTCL_READ; - method = smbus_methods.mt_sbr; - input.count = 3; - } else { - protocol |= ACPI_SMBUS_PRTCL_WRITE; - method = smbus_methods.mt_sbw; - input.count = 5; - } - - input.pointer = mt_params; - mt_params[0].type = ACPI_TYPE_INTEGER; - mt_params[0].integer.value = protocol; - mt_params[1].type = ACPI_TYPE_INTEGER; - mt_params[1].integer.value = addr; - mt_params[2].type = ACPI_TYPE_INTEGER; - mt_params[2].integer.value = command; - - status = acpi_evaluate_object(smbus_cmi->handle, method, &input, - &buffer); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Evaluating %s: %i", method, status)); - return -EIO; - } - - pkg = buffer.pointer; - if (pkg && pkg->type == ACPI_TYPE_PACKAGE) - obj = pkg->package.elements; - else { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - - result = obj->integer.value; - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s return status: %i\n", - method, result)); - - switch (result) { - case ACPI_SMBUS_STATUS_OK: - result = 0; - break; - case ACPI_SMBUS_STATUS_BUSY: - result = -EBUSY; - goto out; - case ACPI_SMBUS_STATUS_TIMEOUT: - result = -ETIMEDOUT; - goto out; - case ACPI_SMBUS_STATUS_DNAK: - result = -ENXIO; - goto out; - default: - result = -EIO; - goto out; - } - - if (read_write == I2C_SMBUS_WRITE || size == I2C_SMBUS_QUICK) - goto out; - - obj = pkg->package.elements + 1; - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - - len = obj->integer.value; - obj = pkg->package.elements + 2; - switch (size) { - case I2C_SMBUS_BYTE: - case I2C_SMBUS_BYTE_DATA: - case I2C_SMBUS_WORD_DATA: - if (obj == NULL || obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - if (len == 2) - data->word = obj->integer.value; - else - data->byte = obj->integer.value; - break; - case I2C_SMBUS_BLOCK_DATA: - if (obj == NULL || obj->type != ACPI_TYPE_BUFFER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - result = -EIO; - goto out; - } - if (len == 0 || len > I2C_SMBUS_BLOCK_MAX) - return -EPROTO; - data->block[0] = len; - memcpy(data->block + 1, obj->buffer.pointer, len); - break; - } - -out: - kfree(buffer.pointer); - dev_dbg(&adap->dev, "Transaction status: %i\n", result); - return result; -} - -static u32 acpi_smbus_cmi_func(struct i2c_adapter *adapter) -{ - struct acpi_smbus_cmi *smbus_cmi = adapter->algo_data; - u32 ret; - - ret = smbus_cmi->cap_read | smbus_cmi->cap_write ? - I2C_FUNC_SMBUS_QUICK : 0; - - ret |= smbus_cmi->cap_read ? - (I2C_FUNC_SMBUS_READ_BYTE | - I2C_FUNC_SMBUS_READ_BYTE_DATA | - I2C_FUNC_SMBUS_READ_WORD_DATA | - I2C_FUNC_SMBUS_READ_BLOCK_DATA) : 0; - - ret |= smbus_cmi->cap_write ? - (I2C_FUNC_SMBUS_WRITE_BYTE | - I2C_FUNC_SMBUS_WRITE_BYTE_DATA | - I2C_FUNC_SMBUS_WRITE_WORD_DATA | - I2C_FUNC_SMBUS_WRITE_BLOCK_DATA) : 0; - - return ret; -} - -static const struct i2c_algorithm acpi_smbus_cmi_algorithm = { - .smbus_xfer = acpi_smbus_cmi_access, - .functionality = acpi_smbus_cmi_func, -}; - - -static int acpi_smbus_cmi_add_cap(struct acpi_smbus_cmi *smbus_cmi, - const char *name) -{ - struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; - union acpi_object *obj; - acpi_status status; - - if (!strcmp(name, smbus_methods.mt_info)) { - status = acpi_evaluate_object(smbus_cmi->handle, - smbus_methods.mt_info, - NULL, &buffer); - if (ACPI_FAILURE(status)) { - ACPI_ERROR((AE_INFO, "Evaluating %s: %i", - smbus_methods.mt_info, status)); - return -EIO; - } - - obj = buffer.pointer; - if (obj && obj->type == ACPI_TYPE_PACKAGE) - obj = obj->package.elements; - else { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - kfree(buffer.pointer); - return -EIO; - } - - if (obj->type != ACPI_TYPE_INTEGER) { - ACPI_ERROR((AE_INFO, "Invalid argument type")); - kfree(buffer.pointer); - return -EIO; - } else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "SMBus CMI Version %x" - "\n", (int)obj->integer.value)); - - kfree(buffer.pointer); - smbus_cmi->cap_info = 1; - } else if (!strcmp(name, smbus_methods.mt_sbr)) - smbus_cmi->cap_read = 1; - else if (!strcmp(name, smbus_methods.mt_sbw)) - smbus_cmi->cap_write = 1; - else - ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Unsupported CMI method: %s\n", - name)); - - return 0; -} - -static acpi_status acpi_smbus_cmi_query_methods(acpi_handle handle, u32 level, - void *context, void **return_value) -{ - char node_name[5]; - struct acpi_buffer buffer = { sizeof(node_name), node_name }; - struct acpi_smbus_cmi *smbus_cmi = context; - acpi_status status; - - status = acpi_get_name(handle, ACPI_SINGLE_NAME, &buffer); - - if (ACPI_SUCCESS(status)) - acpi_smbus_cmi_add_cap(smbus_cmi, node_name); - - return AE_OK; -} - -static int acpi_smbus_cmi_add(struct acpi_device *device) -{ - struct acpi_smbus_cmi *smbus_cmi; - - smbus_cmi = kzalloc(sizeof(struct acpi_smbus_cmi), GFP_KERNEL); - if (!smbus_cmi) - return -ENOMEM; - - smbus_cmi->handle = device->handle; - strcpy(acpi_device_name(device), ACPI_SMBUS_HC_DEVICE_NAME); - strcpy(acpi_device_class(device), ACPI_SMBUS_HC_CLASS); - device->driver_data = smbus_cmi; - smbus_cmi->cap_info = 0; - smbus_cmi->cap_read = 0; - smbus_cmi->cap_write = 0; - - acpi_walk_namespace(ACPI_TYPE_METHOD, smbus_cmi->handle, 1, - acpi_smbus_cmi_query_methods, smbus_cmi, NULL); - - if (smbus_cmi->cap_info == 0) - goto err; - - snprintf(smbus_cmi->adapter.name, sizeof(smbus_cmi->adapter.name), - "SMBus CMI adapter %s (%s)", - acpi_device_name(device), - acpi_device_uid(device)); - smbus_cmi->adapter.owner = THIS_MODULE; - smbus_cmi->adapter.algo = &acpi_smbus_cmi_algorithm; - smbus_cmi->adapter.algo_data = smbus_cmi; - smbus_cmi->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - smbus_cmi->adapter.dev.parent = &device->dev; - - if (i2c_add_adapter(&smbus_cmi->adapter)) { - dev_err(&device->dev, "Couldn't register adapter!\n"); - goto err; - } - - return 0; - -err: - kfree(smbus_cmi); - device->driver_data = NULL; - return -EIO; -} - -static int acpi_smbus_cmi_remove(struct acpi_device *device, int type) -{ - struct acpi_smbus_cmi *smbus_cmi = acpi_driver_data(device); - - i2c_del_adapter(&smbus_cmi->adapter); - kfree(smbus_cmi); - device->driver_data = NULL; - - return 0; -} - -static struct acpi_driver acpi_smbus_cmi_driver = { - .name = ACPI_SMBUS_HC_DEVICE_NAME, - .class = ACPI_SMBUS_HC_CLASS, - .ids = acpi_smbus_cmi_ids, - .ops = { - .add = acpi_smbus_cmi_add, - .remove = acpi_smbus_cmi_remove, - }, -}; - -static int __init acpi_smbus_cmi_init(void) -{ - return acpi_bus_register_driver(&acpi_smbus_cmi_driver); -} - -static void __exit acpi_smbus_cmi_exit(void) -{ - acpi_bus_unregister_driver(&acpi_smbus_cmi_driver); -} - -module_init(acpi_smbus_cmi_init); -module_exit(acpi_smbus_cmi_exit); - -MODULE_LICENSE("GPL"); -MODULE_AUTHOR("Crane Cai "); -MODULE_DESCRIPTION("ACPI SMBus CMI driver"); diff --git a/trunk/drivers/i2c/busses/i2c-taos-evm.c b/trunk/drivers/i2c/busses/i2c-taos-evm.c index dd39c1eb03ed..224aa12ee7c8 100644 --- a/trunk/drivers/i2c/busses/i2c-taos-evm.c +++ b/trunk/drivers/i2c/busses/i2c-taos-evm.c @@ -32,12 +32,10 @@ #define TAOS_STATE_INIT 0 #define TAOS_STATE_IDLE 1 -#define TAOS_STATE_EOFF 2 +#define TAOS_STATE_SEND 2 #define TAOS_STATE_RECV 3 #define TAOS_CMD_RESET 0x12 -#define TAOS_CMD_ECHO_ON '+' -#define TAOS_CMD_ECHO_OFF '-' static DECLARE_WAIT_QUEUE_HEAD(wq); @@ -104,9 +102,17 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, /* Send the transaction to the TAOS EVM */ dev_dbg(&adapter->dev, "Command buffer: %s\n", taos->buffer); - for (p = taos->buffer; *p; p++) - serio_write(serio, *p); - + taos->pos = 0; + taos->state = TAOS_STATE_SEND; + serio_write(serio, taos->buffer[0]); + wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, + msecs_to_jiffies(250)); + if (taos->state != TAOS_STATE_IDLE) { + dev_err(&adapter->dev, "Transaction failed " + "(state=%d, pos=%d)\n", taos->state, taos->pos); + taos->addr = 0; + return -EIO; + } taos->addr = addr; /* Start the transaction and read the answer */ @@ -116,7 +122,7 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, msecs_to_jiffies(150)); if (taos->state != TAOS_STATE_IDLE - || taos->pos != 5) { + || taos->pos != 6) { dev_err(&adapter->dev, "Transaction timeout (pos=%d)\n", taos->pos); return -EIO; @@ -124,7 +130,7 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr, dev_dbg(&adapter->dev, "Answer buffer: %s\n", taos->buffer); /* Interpret the returned string */ - p = taos->buffer + 1; + p = taos->buffer + 2; p[3] = '\0'; if (!strcmp(p, "NAK")) return -ENODEV; @@ -167,9 +173,13 @@ static irqreturn_t taos_interrupt(struct serio *serio, unsigned char data, wake_up_interruptible(&wq); } break; - case TAOS_STATE_EOFF: - taos->state = TAOS_STATE_IDLE; - wake_up_interruptible(&wq); + case TAOS_STATE_SEND: + if (taos->buffer[++taos->pos]) + serio_write(serio, taos->buffer[taos->pos]); + else { + taos->state = TAOS_STATE_IDLE; + wake_up_interruptible(&wq); + } break; case TAOS_STATE_RECV: taos->buffer[taos->pos++] = data; @@ -247,19 +257,6 @@ static int taos_connect(struct serio *serio, struct serio_driver *drv) } strlcpy(adapter->name, name, sizeof(adapter->name)); - /* Turn echo off for better performance */ - taos->state = TAOS_STATE_EOFF; - serio_write(serio, TAOS_CMD_ECHO_OFF); - - wait_event_interruptible_timeout(wq, taos->state == TAOS_STATE_IDLE, - msecs_to_jiffies(250)); - if (taos->state != TAOS_STATE_IDLE) { - err = -ENODEV; - dev_err(&adapter->dev, "Echo off failed " - "(state=%d)\n", taos->state); - goto exit_close; - } - err = i2c_add_adapter(adapter); if (err) goto exit_close; diff --git a/trunk/drivers/i2c/busses/scx200_acb.c b/trunk/drivers/i2c/busses/scx200_acb.c index cf994bd01d9c..648ecc6f60e6 100644 --- a/trunk/drivers/i2c/busses/scx200_acb.c +++ b/trunk/drivers/i2c/busses/scx200_acb.c @@ -217,10 +217,8 @@ static void scx200_acb_machine(struct scx200_acb_iface *iface, u8 status) return; error: - dev_err(&iface->adapter.dev, - "%s in state %s (addr=0x%02x, len=%d, status=0x%02x)\n", errmsg, - scx200_acb_state_name[iface->state], iface->address_byte, - iface->len, status); + dev_err(&iface->adapter.dev, "%s in state %s\n", errmsg, + scx200_acb_state_name[iface->state]); iface->state = state_idle; iface->result = -EIO; diff --git a/trunk/drivers/i2c/chips/Kconfig b/trunk/drivers/i2c/chips/Kconfig index f9618f4d4e47..02d746c9c474 100644 --- a/trunk/drivers/i2c/chips/Kconfig +++ b/trunk/drivers/i2c/chips/Kconfig @@ -16,6 +16,54 @@ config DS1682 This driver can also be built as a module. If so, the module will be called ds1682. +config SENSORS_PCF8574 + tristate "Philips PCF8574 and PCF8574A (DEPRECATED)" + depends on EXPERIMENTAL && GPIO_PCF857X = "n" + default n + help + If you say yes here you get support for Philips PCF8574 and + PCF8574A chips. These chips are 8-bit I/O expanders for the I2C bus. + + This driver can also be built as a module. If so, the module + will be called pcf8574. + + This driver is deprecated and will be dropped soon. Use + drivers/gpio/pcf857x.c instead. + + These devices are hard to detect and rarely found on mainstream + hardware. If unsure, say N. + +config PCF8575 + tristate "Philips PCF8575 (DEPRECATED)" + default n + depends on GPIO_PCF857X = "n" + help + If you say yes here you get support for Philips PCF8575 chip. + This chip is a 16-bit I/O expander for the I2C bus. Several other + chip manufacturers sell equivalent chips, e.g. Texas Instruments. + + This driver can also be built as a module. If so, the module + will be called pcf8575. + + This driver is deprecated and will be dropped soon. Use + drivers/gpio/pcf857x.c instead. + + This device is hard to detect and is rarely found on mainstream + hardware. If unsure, say N. + +config SENSORS_PCA9539 + tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)" + depends on EXPERIMENTAL && GPIO_PCA953X = "n" + help + If you say yes here you get support for the Philips PCA9539 + 16-bit I/O port. + + This driver can also be built as a module. If so, the module + will be called pca9539. + + This driver is deprecated and will be dropped soon. Use + drivers/gpio/pca953x.c instead. + config SENSORS_TSL2550 tristate "Taos TSL2550 ambient light sensor" depends on EXPERIMENTAL diff --git a/trunk/drivers/i2c/chips/Makefile b/trunk/drivers/i2c/chips/Makefile index 749cf3606294..f4680d16ee34 100644 --- a/trunk/drivers/i2c/chips/Makefile +++ b/trunk/drivers/i2c/chips/Makefile @@ -11,6 +11,9 @@ # obj-$(CONFIG_DS1682) += ds1682.o +obj-$(CONFIG_SENSORS_PCA9539) += pca9539.o +obj-$(CONFIG_SENSORS_PCF8574) += pcf8574.o +obj-$(CONFIG_PCF8575) += pcf8575.o obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o ifeq ($(CONFIG_I2C_DEBUG_CHIP),y) diff --git a/trunk/drivers/i2c/chips/pca9539.c b/trunk/drivers/i2c/chips/pca9539.c new file mode 100644 index 000000000000..270de4e56a81 --- /dev/null +++ b/trunk/drivers/i2c/chips/pca9539.c @@ -0,0 +1,152 @@ +/* + pca9539.c - 16-bit I/O port with interrupt and reset + + Copyright (C) 2005 Ben Gardner + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. +*/ + +#include +#include +#include +#include +#include + +/* Addresses to scan: none, device is not autodetected */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_1(pca9539); + +enum pca9539_cmd +{ + PCA9539_INPUT_0 = 0, + PCA9539_INPUT_1 = 1, + PCA9539_OUTPUT_0 = 2, + PCA9539_OUTPUT_1 = 3, + PCA9539_INVERT_0 = 4, + PCA9539_INVERT_1 = 5, + PCA9539_DIRECTION_0 = 6, + PCA9539_DIRECTION_1 = 7, +}; + +/* following are the sysfs callback functions */ +static ssize_t pca9539_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + return sprintf(buf, "%d\n", i2c_smbus_read_byte_data(client, + psa->index)); +} + +static ssize_t pca9539_store(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct sensor_device_attribute *psa = to_sensor_dev_attr(attr); + struct i2c_client *client = to_i2c_client(dev); + unsigned long val = simple_strtoul(buf, NULL, 0); + if (val > 0xff) + return -EINVAL; + i2c_smbus_write_byte_data(client, psa->index, val); + return count; +} + +/* Define the device attributes */ + +#define PCA9539_ENTRY_RO(name, cmd_idx) \ + static SENSOR_DEVICE_ATTR(name, S_IRUGO, pca9539_show, NULL, cmd_idx) + +#define PCA9539_ENTRY_RW(name, cmd_idx) \ + static SENSOR_DEVICE_ATTR(name, S_IRUGO | S_IWUSR, pca9539_show, \ + pca9539_store, cmd_idx) + +PCA9539_ENTRY_RO(input0, PCA9539_INPUT_0); +PCA9539_ENTRY_RO(input1, PCA9539_INPUT_1); +PCA9539_ENTRY_RW(output0, PCA9539_OUTPUT_0); +PCA9539_ENTRY_RW(output1, PCA9539_OUTPUT_1); +PCA9539_ENTRY_RW(invert0, PCA9539_INVERT_0); +PCA9539_ENTRY_RW(invert1, PCA9539_INVERT_1); +PCA9539_ENTRY_RW(direction0, PCA9539_DIRECTION_0); +PCA9539_ENTRY_RW(direction1, PCA9539_DIRECTION_1); + +static struct attribute *pca9539_attributes[] = { + &sensor_dev_attr_input0.dev_attr.attr, + &sensor_dev_attr_input1.dev_attr.attr, + &sensor_dev_attr_output0.dev_attr.attr, + &sensor_dev_attr_output1.dev_attr.attr, + &sensor_dev_attr_invert0.dev_attr.attr, + &sensor_dev_attr_invert1.dev_attr.attr, + &sensor_dev_attr_direction0.dev_attr.attr, + &sensor_dev_attr_direction1.dev_attr.attr, + NULL +}; + +static struct attribute_group pca9539_defattr_group = { + .attrs = pca9539_attributes, +}; + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pca9539_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) + return -ENODEV; + + strlcpy(info->type, "pca9539", I2C_NAME_SIZE); + + return 0; +} + +static int pca9539_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + /* Register sysfs hooks */ + return sysfs_create_group(&client->dev.kobj, + &pca9539_defattr_group); +} + +static int pca9539_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group); + return 0; +} + +static const struct i2c_device_id pca9539_id[] = { + { "pca9539", 0 }, + { } +}; + +static struct i2c_driver pca9539_driver = { + .driver = { + .name = "pca9539", + }, + .probe = pca9539_probe, + .remove = pca9539_remove, + .id_table = pca9539_id, + + .detect = pca9539_detect, + .address_data = &addr_data, +}; + +static int __init pca9539_init(void) +{ + return i2c_add_driver(&pca9539_driver); +} + +static void __exit pca9539_exit(void) +{ + i2c_del_driver(&pca9539_driver); +} + +MODULE_AUTHOR("Ben Gardner "); +MODULE_DESCRIPTION("PCA9539 driver"); +MODULE_LICENSE("GPL"); + +module_init(pca9539_init); +module_exit(pca9539_exit); + diff --git a/trunk/drivers/i2c/chips/pcf8574.c b/trunk/drivers/i2c/chips/pcf8574.c new file mode 100644 index 000000000000..6ec309894c88 --- /dev/null +++ b/trunk/drivers/i2c/chips/pcf8574.c @@ -0,0 +1,215 @@ +/* + Copyright (c) 2000 Frodo Looijaard , + Philip Edelbrock , + Dan Eaton + Ported to Linux 2.6 by Aurelien Jarno with + the help of Jean Delvare + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +/* A few notes about the PCF8574: + +* The PCF8574 is an 8-bit I/O expander for the I2C bus produced by + Philips Semiconductors. It is designed to provide a byte I2C + interface to up to 8 separate devices. + +* The PCF8574 appears as a very simple SMBus device which can be + read from or written to with SMBUS byte read/write accesses. + + --Dan + +*/ + +#include +#include +#include +#include + +/* Addresses to scan: none, device can't be detected */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD_2(pcf8574, pcf8574a); + +/* Each client has this additional data */ +struct pcf8574_data { + int write; /* Remember last written value */ +}; + +static void pcf8574_init_client(struct i2c_client *client); + +/* following are the sysfs callback functions */ +static ssize_t show_read(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + return sprintf(buf, "%u\n", i2c_smbus_read_byte(client)); +} + +static DEVICE_ATTR(read, S_IRUGO, show_read, NULL); + +static ssize_t show_write(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct pcf8574_data *data = i2c_get_clientdata(to_i2c_client(dev)); + + if (data->write < 0) + return data->write; + + return sprintf(buf, "%d\n", data->write); +} + +static ssize_t set_write(struct device *dev, struct device_attribute *attr, const char *buf, + size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct pcf8574_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + + if (val > 0xff) + return -EINVAL; + + data->write = val; + i2c_smbus_write_byte(client, data->write); + return count; +} + +static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); + +static struct attribute *pcf8574_attributes[] = { + &dev_attr_read.attr, + &dev_attr_write.attr, + NULL +}; + +static const struct attribute_group pcf8574_attr_group = { + .attrs = pcf8574_attributes, +}; + +/* + * Real code + */ + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pcf8574_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + const char *client_name; + + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) + return -ENODEV; + + /* Now, we would do the remaining detection. But the PCF8574 is plainly + impossible to detect! Stupid chip. */ + + /* Determine the chip type */ + if (kind <= 0) { + if (client->addr >= 0x38 && client->addr <= 0x3f) + kind = pcf8574a; + else + kind = pcf8574; + } + + if (kind == pcf8574a) + client_name = "pcf8574a"; + else + client_name = "pcf8574"; + strlcpy(info->type, client_name, I2C_NAME_SIZE); + + return 0; +} + +static int pcf8574_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pcf8574_data *data; + int err; + + data = kzalloc(sizeof(struct pcf8574_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + + /* Initialize the PCF8574 chip */ + pcf8574_init_client(client); + + /* Register sysfs hooks */ + err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group); + if (err) + goto exit_free; + return 0; + + exit_free: + kfree(data); + exit: + return err; +} + +static int pcf8574_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group); + kfree(i2c_get_clientdata(client)); + return 0; +} + +/* Called when we have found a new PCF8574. */ +static void pcf8574_init_client(struct i2c_client *client) +{ + struct pcf8574_data *data = i2c_get_clientdata(client); + data->write = -EAGAIN; +} + +static const struct i2c_device_id pcf8574_id[] = { + { "pcf8574", 0 }, + { "pcf8574a", 0 }, + { } +}; + +static struct i2c_driver pcf8574_driver = { + .driver = { + .name = "pcf8574", + }, + .probe = pcf8574_probe, + .remove = pcf8574_remove, + .id_table = pcf8574_id, + + .detect = pcf8574_detect, + .address_data = &addr_data, +}; + +static int __init pcf8574_init(void) +{ + return i2c_add_driver(&pcf8574_driver); +} + +static void __exit pcf8574_exit(void) +{ + i2c_del_driver(&pcf8574_driver); +} + + +MODULE_AUTHOR + ("Frodo Looijaard , " + "Philip Edelbrock , " + "Dan Eaton " + "and Aurelien Jarno "); +MODULE_DESCRIPTION("PCF8574 driver"); +MODULE_LICENSE("GPL"); + +module_init(pcf8574_init); +module_exit(pcf8574_exit); diff --git a/trunk/drivers/i2c/chips/pcf8575.c b/trunk/drivers/i2c/chips/pcf8575.c new file mode 100644 index 000000000000..07fd7cb3c57d --- /dev/null +++ b/trunk/drivers/i2c/chips/pcf8575.c @@ -0,0 +1,198 @@ +/* + pcf8575.c + + About the PCF8575 chip: the PCF8575 is a 16-bit I/O expander for the I2C bus + produced by a.o. Philips Semiconductors. + + Copyright (C) 2006 Michael Hennerich, Analog Devices Inc. + + Based on pcf8574.c. + + Copyright (c) 2007 Bart Van Assche . + Ported this driver from ucLinux to the mainstream Linux kernel. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include +#include +#include +#include /* kzalloc() */ +#include /* sysfs_create_group() */ + +/* Addresses to scan: none, device can't be detected */ +static const unsigned short normal_i2c[] = { I2C_CLIENT_END }; + +/* Insmod parameters */ +I2C_CLIENT_INSMOD; + + +/* Each client has this additional data */ +struct pcf8575_data { + int write; /* last written value, or error code */ +}; + +/* following are the sysfs callback functions */ +static ssize_t show_read(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct i2c_client *client = to_i2c_client(dev); + u16 val; + u8 iopin_state[2]; + + i2c_master_recv(client, iopin_state, 2); + + val = iopin_state[0]; + val |= iopin_state[1] << 8; + + return sprintf(buf, "%u\n", val); +} + +static DEVICE_ATTR(read, S_IRUGO, show_read, NULL); + +static ssize_t show_write(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct pcf8575_data *data = dev_get_drvdata(dev); + if (data->write < 0) + return data->write; + return sprintf(buf, "%d\n", data->write); +} + +static ssize_t set_write(struct device *dev, struct device_attribute *attr, + const char *buf, size_t count) +{ + struct i2c_client *client = to_i2c_client(dev); + struct pcf8575_data *data = i2c_get_clientdata(client); + unsigned long val = simple_strtoul(buf, NULL, 10); + u8 iopin_state[2]; + + if (val > 0xffff) + return -EINVAL; + + data->write = val; + + iopin_state[0] = val & 0xFF; + iopin_state[1] = val >> 8; + + i2c_master_send(client, iopin_state, 2); + + return count; +} + +static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write); + +static struct attribute *pcf8575_attributes[] = { + &dev_attr_read.attr, + &dev_attr_write.attr, + NULL +}; + +static const struct attribute_group pcf8575_attr_group = { + .attrs = pcf8575_attributes, +}; + +/* + * Real code + */ + +/* Return 0 if detection is successful, -ENODEV otherwise */ +static int pcf8575_detect(struct i2c_client *client, int kind, + struct i2c_board_info *info) +{ + struct i2c_adapter *adapter = client->adapter; + + if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) + return -ENODEV; + + /* This is the place to detect whether the chip at the specified + address really is a PCF8575 chip. However, there is no method known + to detect whether an I2C chip is a PCF8575 or any other I2C chip. */ + + strlcpy(info->type, "pcf8575", I2C_NAME_SIZE); + + return 0; +} + +static int pcf8575_probe(struct i2c_client *client, + const struct i2c_device_id *id) +{ + struct pcf8575_data *data; + int err; + + data = kzalloc(sizeof(struct pcf8575_data), GFP_KERNEL); + if (!data) { + err = -ENOMEM; + goto exit; + } + + i2c_set_clientdata(client, data); + data->write = -EAGAIN; + + /* Register sysfs hooks */ + err = sysfs_create_group(&client->dev.kobj, &pcf8575_attr_group); + if (err) + goto exit_free; + + return 0; + +exit_free: + kfree(data); +exit: + return err; +} + +static int pcf8575_remove(struct i2c_client *client) +{ + sysfs_remove_group(&client->dev.kobj, &pcf8575_attr_group); + kfree(i2c_get_clientdata(client)); + return 0; +} + +static const struct i2c_device_id pcf8575_id[] = { + { "pcf8575", 0 }, + { } +}; + +static struct i2c_driver pcf8575_driver = { + .driver = { + .owner = THIS_MODULE, + .name = "pcf8575", + }, + .probe = pcf8575_probe, + .remove = pcf8575_remove, + .id_table = pcf8575_id, + + .detect = pcf8575_detect, + .address_data = &addr_data, +}; + +static int __init pcf8575_init(void) +{ + return i2c_add_driver(&pcf8575_driver); +} + +static void __exit pcf8575_exit(void) +{ + i2c_del_driver(&pcf8575_driver); +} + +MODULE_AUTHOR("Michael Hennerich , " + "Bart Van Assche "); +MODULE_DESCRIPTION("pcf8575 driver"); +MODULE_LICENSE("GPL"); + +module_init(pcf8575_init); +module_exit(pcf8575_exit); diff --git a/trunk/drivers/i2c/chips/tsl2550.c b/trunk/drivers/i2c/chips/tsl2550.c index aa96bd2d27ea..b96f3025e588 100644 --- a/trunk/drivers/i2c/chips/tsl2550.c +++ b/trunk/drivers/i2c/chips/tsl2550.c @@ -24,9 +24,10 @@ #include #include #include +#include #define TSL2550_DRV_NAME "tsl2550" -#define DRIVER_VERSION "1.2" +#define DRIVER_VERSION "1.1.2" /* * Defines @@ -95,13 +96,32 @@ static int tsl2550_set_power_state(struct i2c_client *client, int state) static int tsl2550_get_adc_value(struct i2c_client *client, u8 cmd) { - int ret; + unsigned long end; + int loop = 0, ret = 0; - ret = i2c_smbus_read_byte_data(client, cmd); - if (ret < 0) - return ret; + /* + * Read ADC channel waiting at most 400ms (see data sheet for further + * info). + * To avoid long busy wait we spin for few milliseconds then + * start sleeping. + */ + end = jiffies + msecs_to_jiffies(400); + while (time_before(jiffies, end)) { + i2c_smbus_write_byte(client, cmd); + + if (loop++ < 5) + mdelay(1); + else + msleep(1); + + ret = i2c_smbus_read_byte(client); + if (ret < 0) + return ret; + else if (ret & 0x0080) + break; + } if (!(ret & 0x80)) - return -EAGAIN; + return -EIO; return ret & 0x7f; /* remove the "valid" bit */ } @@ -265,6 +285,8 @@ static ssize_t __tsl2550_show_lux(struct i2c_client *client, char *buf) return ret; ch0 = ret; + mdelay(1); + ret = tsl2550_get_adc_value(client, TSL2550_READ_ADC1); if (ret < 0) return ret; @@ -323,10 +345,11 @@ static int tsl2550_init_client(struct i2c_client *client) * Probe the chip. To do so we try to power up the device and then to * read back the 0x03 code */ - err = i2c_smbus_read_byte_data(client, TSL2550_POWER_UP); + err = i2c_smbus_write_byte(client, TSL2550_POWER_UP); if (err < 0) return err; - if (err != TSL2550_POWER_UP) + mdelay(1); + if (i2c_smbus_read_byte(client) != TSL2550_POWER_UP) return -ENODEV; data->power_state = 1; @@ -351,8 +374,7 @@ static int __devinit tsl2550_probe(struct i2c_client *client, struct tsl2550_data *data; int *opmode, err = 0; - if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE - | I2C_FUNC_SMBUS_READ_BYTE_DATA)) { + if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) { err = -EIO; goto exit; } diff --git a/trunk/drivers/i2c/i2c-core.c b/trunk/drivers/i2c/i2c-core.c index 8d80fceca6a4..0e45c296d3d2 100644 --- a/trunk/drivers/i2c/i2c-core.c +++ b/trunk/drivers/i2c/i2c-core.c @@ -46,7 +46,6 @@ static DEFINE_MUTEX(core_lock); static DEFINE_IDR(i2c_adapter_idr); static LIST_HEAD(userspace_devices); -static struct device_type i2c_client_type; static int i2c_check_addr(struct i2c_adapter *adapter, int addr); static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); @@ -65,13 +64,9 @@ static const struct i2c_device_id *i2c_match_id(const struct i2c_device_id *id, static int i2c_device_match(struct device *dev, struct device_driver *drv) { - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; - - if (!client) - return 0; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_driver *driver = to_i2c_driver(drv); - driver = to_i2c_driver(drv); /* match on an id table if there is one */ if (driver->id_table) return i2c_match_id(driver->id_table, client) != NULL; @@ -99,14 +94,10 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) static int i2c_device_probe(struct device *dev) { - struct i2c_client *client = i2c_verify_client(dev); - struct i2c_driver *driver; + struct i2c_client *client = to_i2c_client(dev); + struct i2c_driver *driver = to_i2c_driver(dev->driver); int status; - if (!client) - return 0; - - driver = to_i2c_driver(dev->driver); if (!driver->probe || !driver->id_table) return -ENODEV; client->driver = driver; @@ -123,11 +114,11 @@ static int i2c_device_probe(struct device *dev) static int i2c_device_remove(struct device *dev) { - struct i2c_client *client = i2c_verify_client(dev); + struct i2c_client *client = to_i2c_client(dev); struct i2c_driver *driver; int status; - if (!client || !dev->driver) + if (!dev->driver) return 0; driver = to_i2c_driver(dev->driver); @@ -145,40 +136,37 @@ static int i2c_device_remove(struct device *dev) static void i2c_device_shutdown(struct device *dev) { - struct i2c_client *client = i2c_verify_client(dev); struct i2c_driver *driver; - if (!client || !dev->driver) + if (!dev->driver) return; driver = to_i2c_driver(dev->driver); if (driver->shutdown) - driver->shutdown(client); + driver->shutdown(to_i2c_client(dev)); } static int i2c_device_suspend(struct device *dev, pm_message_t mesg) { - struct i2c_client *client = i2c_verify_client(dev); struct i2c_driver *driver; - if (!client || !dev->driver) + if (!dev->driver) return 0; driver = to_i2c_driver(dev->driver); if (!driver->suspend) return 0; - return driver->suspend(client, mesg); + return driver->suspend(to_i2c_client(dev), mesg); } static int i2c_device_resume(struct device *dev) { - struct i2c_client *client = i2c_verify_client(dev); struct i2c_driver *driver; - if (!client || !dev->driver) + if (!dev->driver) return 0; driver = to_i2c_driver(dev->driver); if (!driver->resume) return 0; - return driver->resume(client); + return driver->resume(to_i2c_client(dev)); } static void i2c_client_dev_release(struct device *dev) @@ -187,10 +175,10 @@ static void i2c_client_dev_release(struct device *dev) } static ssize_t -show_name(struct device *dev, struct device_attribute *attr, char *buf) +show_client_name(struct device *dev, struct device_attribute *attr, char *buf) { - return sprintf(buf, "%s\n", dev->type == &i2c_client_type ? - to_i2c_client(dev)->name : to_i2c_adapter(dev)->name); + struct i2c_client *client = to_i2c_client(dev); + return sprintf(buf, "%s\n", client->name); } static ssize_t @@ -200,28 +188,18 @@ show_modalias(struct device *dev, struct device_attribute *attr, char *buf) return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name); } -static DEVICE_ATTR(name, S_IRUGO, show_name, NULL); -static DEVICE_ATTR(modalias, S_IRUGO, show_modalias, NULL); - -static struct attribute *i2c_dev_attrs[] = { - &dev_attr_name.attr, +static struct device_attribute i2c_dev_attrs[] = { + __ATTR(name, S_IRUGO, show_client_name, NULL), /* modalias helps coldplug: modprobe $(cat .../modalias) */ - &dev_attr_modalias.attr, - NULL -}; - -static struct attribute_group i2c_dev_attr_group = { - .attrs = i2c_dev_attrs, -}; - -static const struct attribute_group *i2c_dev_attr_groups[] = { - &i2c_dev_attr_group, - NULL + __ATTR(modalias, S_IRUGO, show_modalias, NULL), + { }, }; struct bus_type i2c_bus_type = { .name = "i2c", + .dev_attrs = i2c_dev_attrs, .match = i2c_device_match, + .uevent = i2c_device_uevent, .probe = i2c_device_probe, .remove = i2c_device_remove, .shutdown = i2c_device_shutdown, @@ -230,12 +208,6 @@ struct bus_type i2c_bus_type = { }; EXPORT_SYMBOL_GPL(i2c_bus_type); -static struct device_type i2c_client_type = { - .groups = i2c_dev_attr_groups, - .uevent = i2c_device_uevent, - .release = i2c_client_dev_release, -}; - /** * i2c_verify_client - return parameter as i2c_client, or NULL @@ -248,7 +220,7 @@ static struct device_type i2c_client_type = { */ struct i2c_client *i2c_verify_client(struct device *dev) { - return (dev->type == &i2c_client_type) + return (dev->bus == &i2c_bus_type) ? to_i2c_client(dev) : NULL; } @@ -301,7 +273,7 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info) client->dev.parent = &client->adapter->dev; client->dev.bus = &i2c_bus_type; - client->dev.type = &i2c_client_type; + client->dev.release = i2c_client_dev_release; dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap), client->addr); @@ -396,6 +368,13 @@ static void i2c_adapter_dev_release(struct device *dev) complete(&adap->dev_released); } +static ssize_t +show_adapter_name(struct device *dev, struct device_attribute *attr, char *buf) +{ + struct i2c_adapter *adap = to_i2c_adapter(dev); + return sprintf(buf, "%s\n", adap->name); +} + /* * Let users instantiate I2C devices through sysfs. This can be used when * platform initialization code doesn't contain the proper data for @@ -514,34 +493,19 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr, return res; } -static DEVICE_ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device); -static DEVICE_ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device); - -static struct attribute *i2c_adapter_attrs[] = { - &dev_attr_name.attr, - &dev_attr_new_device.attr, - &dev_attr_delete_device.attr, - NULL -}; - -static struct attribute_group i2c_adapter_attr_group = { - .attrs = i2c_adapter_attrs, -}; - -static const struct attribute_group *i2c_adapter_attr_groups[] = { - &i2c_adapter_attr_group, - NULL +static struct device_attribute i2c_adapter_attrs[] = { + __ATTR(name, S_IRUGO, show_adapter_name, NULL), + __ATTR(new_device, S_IWUSR, NULL, i2c_sysfs_new_device), + __ATTR(delete_device, S_IWUSR, NULL, i2c_sysfs_delete_device), + { }, }; -static struct device_type i2c_adapter_type = { - .groups = i2c_adapter_attr_groups, - .release = i2c_adapter_dev_release, +static struct class i2c_adapter_class = { + .owner = THIS_MODULE, + .name = "i2c-adapter", + .dev_attrs = i2c_adapter_attrs, }; -#ifdef CONFIG_I2C_COMPAT -static struct class_compat *i2c_adapter_compat_class; -#endif - static void i2c_scan_static_board_info(struct i2c_adapter *adapter) { struct i2c_devinfo *devinfo; @@ -591,22 +555,14 @@ static int i2c_register_adapter(struct i2c_adapter *adap) adap->timeout = HZ; dev_set_name(&adap->dev, "i2c-%d", adap->nr); - adap->dev.bus = &i2c_bus_type; - adap->dev.type = &i2c_adapter_type; + adap->dev.release = &i2c_adapter_dev_release; + adap->dev.class = &i2c_adapter_class; res = device_register(&adap->dev); if (res) goto out_list; dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name); -#ifdef CONFIG_I2C_COMPAT - res = class_compat_create_link(i2c_adapter_compat_class, &adap->dev, - adap->dev.parent); - if (res) - dev_warn(&adap->dev, - "Failed to create compatibility class link\n"); -#endif - /* create pre-declared device nodes */ if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); @@ -785,11 +741,6 @@ int i2c_del_adapter(struct i2c_adapter *adap) checking the returned value. */ res = device_for_each_child(&adap->dev, NULL, __unregister_client); -#ifdef CONFIG_I2C_COMPAT - class_compat_remove_link(i2c_adapter_compat_class, &adap->dev, - adap->dev.parent); -#endif - /* clean up the sysfs representation */ init_completion(&adap->dev_released); device_unregister(&adap->dev); @@ -817,13 +768,9 @@ EXPORT_SYMBOL(i2c_del_adapter); static int __attach_adapter(struct device *dev, void *data) { - struct i2c_adapter *adapter; + struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; - if (dev->type != &i2c_adapter_type) - return 0; - adapter = to_i2c_adapter(dev); - i2c_detect(adapter, driver); /* Legacy drivers scan i2c busses directly */ @@ -862,7 +809,8 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) INIT_LIST_HEAD(&driver->clients); /* Walk the adapters that are already present */ mutex_lock(&core_lock); - bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter); + class_for_each_device(&i2c_adapter_class, NULL, driver, + __attach_adapter); mutex_unlock(&core_lock); return 0; @@ -871,14 +819,10 @@ EXPORT_SYMBOL(i2c_register_driver); static int __detach_adapter(struct device *dev, void *data) { - struct i2c_adapter *adapter; + struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; struct i2c_client *client, *_n; - if (dev->type != &i2c_adapter_type) - return 0; - adapter = to_i2c_adapter(dev); - /* Remove the devices we created ourselves as the result of hardware * probing (using a driver's detect method) */ list_for_each_entry_safe(client, _n, &driver->clients, detected) { @@ -906,7 +850,8 @@ static int __detach_adapter(struct device *dev, void *data) void i2c_del_driver(struct i2c_driver *driver) { mutex_lock(&core_lock); - bus_for_each_dev(&i2c_bus_type, NULL, driver, __detach_adapter); + class_for_each_device(&i2c_adapter_class, NULL, driver, + __detach_adapter); mutex_unlock(&core_lock); driver_unregister(&driver->driver); @@ -995,23 +940,17 @@ static int __init i2c_init(void) retval = bus_register(&i2c_bus_type); if (retval) return retval; -#ifdef CONFIG_I2C_COMPAT - i2c_adapter_compat_class = class_compat_register("i2c-adapter"); - if (!i2c_adapter_compat_class) { - retval = -ENOMEM; + retval = class_register(&i2c_adapter_class); + if (retval) goto bus_err; - } -#endif retval = i2c_add_driver(&dummy_driver); if (retval) goto class_err; return 0; class_err: -#ifdef CONFIG_I2C_COMPAT - class_compat_unregister(i2c_adapter_compat_class); + class_unregister(&i2c_adapter_class); bus_err: -#endif bus_unregister(&i2c_bus_type); return retval; } @@ -1019,9 +958,7 @@ static int __init i2c_init(void) static void __exit i2c_exit(void) { i2c_del_driver(&dummy_driver); -#ifdef CONFIG_I2C_COMPAT - class_compat_unregister(i2c_adapter_compat_class); -#endif + class_unregister(&i2c_adapter_class); bus_unregister(&i2c_bus_type); } diff --git a/trunk/drivers/ide/ide-acpi.c b/trunk/drivers/ide/ide-acpi.c index c0cf45a11b93..c509c9916464 100644 --- a/trunk/drivers/ide/ide-acpi.c +++ b/trunk/drivers/ide/ide-acpi.c @@ -114,6 +114,8 @@ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, unsigned int bus, devnum, func; acpi_integer addr; acpi_handle dev_handle; + struct acpi_buffer buffer = {.length = ACPI_ALLOCATE_BUFFER, + .pointer = NULL}; acpi_status status; struct acpi_device_info *dinfo = NULL; int ret = -ENODEV; @@ -132,11 +134,12 @@ static int ide_get_dev_handle(struct device *dev, acpi_handle *handle, goto err; } - status = acpi_get_object_info(dev_handle, &dinfo); + status = acpi_get_object_info(dev_handle, &buffer); if (ACPI_FAILURE(status)) { DEBPRINT("get_object_info for device failed\n"); goto err; } + dinfo = buffer.pointer; if (dinfo && (dinfo->valid & ACPI_VALID_ADR) && dinfo->address == addr) { *pcidevfn = addr; diff --git a/trunk/drivers/ieee1394/raw1394.c b/trunk/drivers/ieee1394/raw1394.c index 0bc3d78ce7b1..da5f8829b503 100644 --- a/trunk/drivers/ieee1394/raw1394.c +++ b/trunk/drivers/ieee1394/raw1394.c @@ -2272,10 +2272,8 @@ static ssize_t raw1394_write(struct file *file, const char __user * buffer, return -EFAULT; } - if (!mutex_trylock(&fi->state_mutex)) { - free_pending_request(req); + if (!mutex_trylock(&fi->state_mutex)) return -EAGAIN; - } switch (fi->state) { case opened: diff --git a/trunk/drivers/ieee1394/sbp2.c b/trunk/drivers/ieee1394/sbp2.c index f199896c4113..52b25f8b111d 100644 --- a/trunk/drivers/ieee1394/sbp2.c +++ b/trunk/drivers/ieee1394/sbp2.c @@ -372,7 +372,8 @@ static const struct { /* DViCO Momobay FX-3A with TSB42AA9A bridge */ { .firmware_revision = 0x002800, .model = 0x000000, - .workarounds = SBP2_WORKAROUND_POWER_CONDITION, + .workarounds = SBP2_WORKAROUND_DELAY_INQUIRY | + SBP2_WORKAROUND_POWER_CONDITION, }, /* Initio bridges, actually only needed for some older ones */ { .firmware_revision = 0x000200, diff --git a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c index 7550a534005c..7663a2a9f130 100644 --- a/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c +++ b/trunk/drivers/infiniband/hw/ehca/ehca_mrmw.c @@ -2463,7 +2463,7 @@ int ehca_create_busmap(void) int ret; ehca_mr_len = 0; - ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL, + ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL, ehca_create_busmap_callback); return ret; } diff --git a/trunk/drivers/input/touchscreen/ad7877.c b/trunk/drivers/input/touchscreen/ad7877.c index eb83939c705e..ecaeb7e8e75e 100644 --- a/trunk/drivers/input/touchscreen/ad7877.c +++ b/trunk/drivers/input/touchscreen/ad7877.c @@ -842,4 +842,3 @@ module_exit(ad7877_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("AD7877 touchscreen Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:ad7877"); diff --git a/trunk/drivers/input/touchscreen/ad7879.c b/trunk/drivers/input/touchscreen/ad7879.c index 19b4db7e974d..5d8a70398807 100644 --- a/trunk/drivers/input/touchscreen/ad7879.c +++ b/trunk/drivers/input/touchscreen/ad7879.c @@ -779,4 +779,3 @@ module_exit(ad7879_exit); MODULE_AUTHOR("Michael Hennerich "); MODULE_DESCRIPTION("AD7879(-1) touchscreen Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:ad7879"); diff --git a/trunk/drivers/input/touchscreen/ads7846.c b/trunk/drivers/input/touchscreen/ads7846.c index 09c810999b92..ba9d38c3f412 100644 --- a/trunk/drivers/input/touchscreen/ads7846.c +++ b/trunk/drivers/input/touchscreen/ads7846.c @@ -1256,4 +1256,3 @@ module_exit(ads7846_exit); MODULE_DESCRIPTION("ADS7846 TouchScreen Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:ads7846"); diff --git a/trunk/drivers/isdn/capi/kcapi_proc.c b/trunk/drivers/isdn/capi/kcapi_proc.c index 09d4db764d22..50ed778f63fc 100644 --- a/trunk/drivers/isdn/capi/kcapi_proc.c +++ b/trunk/drivers/isdn/capi/kcapi_proc.c @@ -89,14 +89,14 @@ static int contrstats_show(struct seq_file *seq, void *v) return 0; } -static const struct seq_operations seq_controller_ops = { +static struct seq_operations seq_controller_ops = { .start = controller_start, .next = controller_next, .stop = controller_stop, .show = controller_show, }; -static const struct seq_operations seq_contrstats_ops = { +static struct seq_operations seq_contrstats_ops = { .start = controller_start, .next = controller_next, .stop = controller_stop, @@ -194,14 +194,14 @@ applstats_show(struct seq_file *seq, void *v) return 0; } -static const struct seq_operations seq_applications_ops = { +static struct seq_operations seq_applications_ops = { .start = applications_start, .next = applications_next, .stop = applications_stop, .show = applications_show, }; -static const struct seq_operations seq_applstats_ops = { +static struct seq_operations seq_applstats_ops = { .start = applications_start, .next = applications_next, .stop = applications_stop, @@ -264,7 +264,7 @@ static int capi_driver_show(struct seq_file *seq, void *v) return 0; } -static const struct seq_operations seq_capi_driver_ops = { +static struct seq_operations seq_capi_driver_ops = { .start = capi_driver_start, .next = capi_driver_next, .stop = capi_driver_stop, diff --git a/trunk/drivers/leds/leds-dac124s085.c b/trunk/drivers/leds/leds-dac124s085.c index 2913d76ad3d2..098d9aae7259 100644 --- a/trunk/drivers/leds/leds-dac124s085.c +++ b/trunk/drivers/leds/leds-dac124s085.c @@ -148,4 +148,3 @@ module_exit(dac124s085_leds_exit); MODULE_AUTHOR("Guennadi Liakhovetski "); MODULE_DESCRIPTION("DAC124S085 LED driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:dac124s085"); diff --git a/trunk/drivers/lguest/core.c b/trunk/drivers/lguest/core.c index 8744d24ac6e6..1e2cb846b3c9 100644 --- a/trunk/drivers/lguest/core.c +++ b/trunk/drivers/lguest/core.c @@ -67,11 +67,12 @@ static __init int map_switcher(void) * so we make sure they're zeroed. */ for (i = 0; i < TOTAL_SWITCHER_PAGES; i++) { - switcher_page[i] = alloc_page(GFP_KERNEL|__GFP_ZERO); - if (!switcher_page[i]) { + unsigned long addr = get_zeroed_page(GFP_KERNEL); + if (!addr) { err = -ENOMEM; goto free_some_pages; } + switcher_page[i] = virt_to_page(addr); } /* diff --git a/trunk/drivers/lguest/page_tables.c b/trunk/drivers/lguest/page_tables.c index cf94326f1b59..8aaad65c3bb5 100644 --- a/trunk/drivers/lguest/page_tables.c +++ b/trunk/drivers/lguest/page_tables.c @@ -380,7 +380,7 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) * And we copy the flags to the shadow PMD entry. The page * number in the shadow PMD is the page we just allocated. */ - set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd))); + native_set_pmd(spmd, __pmd(__pa(ptepage) | pmd_flags(gpmd))); } /* @@ -447,7 +447,7 @@ bool demand_page(struct lg_cpu *cpu, unsigned long vaddr, int errcode) * we will come back here when a write does actually occur, so * we can update the Guest's _PAGE_DIRTY flag. */ - set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0)); + native_set_pte(spte, gpte_to_spte(cpu, pte_wrprotect(gpte), 0)); /* * Finally, we write the Guest PTE entry back: we've set the @@ -528,7 +528,7 @@ static void release_pmd(pmd_t *spmd) /* Now we can free the page of PTEs */ free_page((long)ptepage); /* And zero out the PMD entry so we never release it twice. */ - set_pmd(spmd, __pmd(0)); + native_set_pmd(spmd, __pmd(0)); } } @@ -833,15 +833,15 @@ static void do_set_pte(struct lg_cpu *cpu, int idx, */ if (pte_flags(gpte) & (_PAGE_DIRTY | _PAGE_ACCESSED)) { check_gpte(cpu, gpte); - set_pte(spte, - gpte_to_spte(cpu, gpte, + native_set_pte(spte, + gpte_to_spte(cpu, gpte, pte_flags(gpte) & _PAGE_DIRTY)); } else { /* * Otherwise kill it and we can demand_page() * it in later. */ - set_pte(spte, __pte(0)); + native_set_pte(spte, __pte(0)); } #ifdef CONFIG_X86_PAE } @@ -983,22 +983,25 @@ static unsigned long setup_pagetables(struct lguest *lg, */ for (i = j = 0; i < mapped_pages && j < PTRS_PER_PMD; i += PTRS_PER_PTE, j++) { - pmd = pfn_pmd(((unsigned long)&linear[i] - mem_base)/PAGE_SIZE, - __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); + /* FIXME: native_set_pmd is overkill here. */ + native_set_pmd(&pmd, __pmd(((unsigned long)(linear + i) + - mem_base) | _PAGE_PRESENT | _PAGE_RW | _PAGE_USER)); if (copy_to_user(&pmds[j], &pmd, sizeof(pmd)) != 0) return -EFAULT; } /* One PGD entry, pointing to that PMD page. */ - pgd = __pgd(((unsigned long)pmds - mem_base) | _PAGE_PRESENT); + set_pgd(&pgd, __pgd(((u32)pmds - mem_base) | _PAGE_PRESENT)); /* Copy it in as the first PGD entry (ie. addresses 0-1G). */ if (copy_to_user(&pgdir[0], &pgd, sizeof(pgd)) != 0) return -EFAULT; /* - * And the other PGD entry to make the linear mapping at PAGE_OFFSET + * And the third PGD entry (ie. addresses 3G-4G). + * + * FIXME: This assumes that PAGE_OFFSET for the Guest is 0xC0000000. */ - if (copy_to_user(&pgdir[KERNEL_PGD_BOUNDARY], &pgd, sizeof(pgd))) + if (copy_to_user(&pgdir[3], &pgd, sizeof(pgd)) != 0) return -EFAULT; #else /* @@ -1138,13 +1141,15 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) { pte_t *switcher_pte_page = __get_cpu_var(switcher_pte_pages); pte_t regs_pte; + unsigned long pfn; #ifdef CONFIG_X86_PAE pmd_t switcher_pmd; pmd_t *pmd_table; - switcher_pmd = pfn_pmd(__pa(switcher_pte_page) >> PAGE_SHIFT, - PAGE_KERNEL_EXEC); + /* FIXME: native_set_pmd is overkill here. */ + native_set_pmd(&switcher_pmd, pfn_pmd(__pa(switcher_pte_page) >> + PAGE_SHIFT, PAGE_KERNEL_EXEC)); /* Figure out where the pmd page is, by reading the PGD, and converting * it to a virtual address. */ @@ -1152,7 +1157,7 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) pgdirs[cpu->cpu_pgd].pgdir[SWITCHER_PGD_INDEX]) << PAGE_SHIFT); /* Now write it into the shadow page table. */ - set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd); + native_set_pmd(&pmd_table[SWITCHER_PMD_INDEX], switcher_pmd); #else pgd_t switcher_pgd; @@ -1174,8 +1179,10 @@ void map_switcher_in_guest(struct lg_cpu *cpu, struct lguest_pages *pages) * page is already mapped there, we don't have to copy them out * again. */ - regs_pte = pfn_pte(__pa(cpu->regs_page) >> PAGE_SHIFT, PAGE_KERNEL); - set_pte(&switcher_pte_page[pte_index((unsigned long)pages)], regs_pte); + pfn = __pa(cpu->regs_page) >> PAGE_SHIFT; + native_set_pte(®s_pte, pfn_pte(pfn, PAGE_KERNEL)); + native_set_pte(&switcher_pte_page[pte_index((unsigned long)pages)], + regs_pte); } /*:*/ @@ -1202,7 +1209,7 @@ static __init void populate_switcher_pte_page(unsigned int cpu, /* The first entries are easy: they map the Switcher code. */ for (i = 0; i < pages; i++) { - set_pte(&pte[i], mk_pte(switcher_page[i], + native_set_pte(&pte[i], mk_pte(switcher_page[i], __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); } @@ -1210,14 +1217,14 @@ static __init void populate_switcher_pte_page(unsigned int cpu, i = pages + cpu*2; /* First page (Guest registers) is writable from the Guest */ - set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]), + native_set_pte(&pte[i], pfn_pte(page_to_pfn(switcher_page[i]), __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED|_PAGE_RW))); /* * The second page contains the "struct lguest_ro_state", and is * read-only. */ - set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]), + native_set_pte(&pte[i+1], pfn_pte(page_to_pfn(switcher_page[i+1]), __pgprot(_PAGE_PRESENT|_PAGE_ACCESSED))); } diff --git a/trunk/drivers/mfd/ezx-pcap.c b/trunk/drivers/mfd/ezx-pcap.c index 876288917976..016be4938e4c 100644 --- a/trunk/drivers/mfd/ezx-pcap.c +++ b/trunk/drivers/mfd/ezx-pcap.c @@ -548,4 +548,3 @@ module_exit(ezx_pcap_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Daniel Ribeiro / Harald Welte"); MODULE_DESCRIPTION("Motorola PCAP2 ASIC Driver"); -MODULE_ALIAS("spi:ezx-pcap"); diff --git a/trunk/drivers/mfd/ucb1400_core.c b/trunk/drivers/mfd/ucb1400_core.c index 2afc08006e6d..78c2135c5de6 100644 --- a/trunk/drivers/mfd/ucb1400_core.c +++ b/trunk/drivers/mfd/ucb1400_core.c @@ -48,11 +48,9 @@ static int ucb1400_core_probe(struct device *dev) int err; struct ucb1400 *ucb; struct ucb1400_ts ucb_ts; - struct ucb1400_gpio ucb_gpio; struct snd_ac97 *ac97; memset(&ucb_ts, 0, sizeof(ucb_ts)); - memset(&ucb_gpio, 0, sizeof(ucb_gpio)); ucb = kzalloc(sizeof(struct ucb1400), GFP_KERNEL); if (!ucb) { @@ -70,44 +68,25 @@ static int ucb1400_core_probe(struct device *dev) goto err0; } - /* GPIO */ - ucb_gpio.ac97 = ac97; - ucb->ucb1400_gpio = platform_device_alloc("ucb1400_gpio", -1); - if (!ucb->ucb1400_gpio) { - err = -ENOMEM; - goto err0; - } - err = platform_device_add_data(ucb->ucb1400_gpio, &ucb_gpio, - sizeof(ucb_gpio)); - if (err) - goto err1; - err = platform_device_add(ucb->ucb1400_gpio); - if (err) - goto err1; - /* TOUCHSCREEN */ ucb_ts.ac97 = ac97; ucb->ucb1400_ts = platform_device_alloc("ucb1400_ts", -1); if (!ucb->ucb1400_ts) { err = -ENOMEM; - goto err2; + goto err0; } err = platform_device_add_data(ucb->ucb1400_ts, &ucb_ts, sizeof(ucb_ts)); if (err) - goto err3; + goto err1; err = platform_device_add(ucb->ucb1400_ts); if (err) - goto err3; + goto err1; return 0; -err3: - platform_device_put(ucb->ucb1400_ts); -err2: - platform_device_unregister(ucb->ucb1400_gpio); err1: - platform_device_put(ucb->ucb1400_gpio); + platform_device_put(ucb->ucb1400_ts); err0: kfree(ucb); err: @@ -119,8 +98,6 @@ static int ucb1400_core_remove(struct device *dev) struct ucb1400 *ucb = dev_get_drvdata(dev); platform_device_unregister(ucb->ucb1400_ts); - platform_device_unregister(ucb->ucb1400_gpio); - kfree(ucb); return 0; } diff --git a/trunk/drivers/misc/eeprom/at25.c b/trunk/drivers/misc/eeprom/at25.c index d902d81dde39..2e535a0ccd5e 100644 --- a/trunk/drivers/misc/eeprom/at25.c +++ b/trunk/drivers/misc/eeprom/at25.c @@ -417,4 +417,4 @@ module_exit(at25_exit); MODULE_DESCRIPTION("Driver for most SPI EEPROMs"); MODULE_AUTHOR("David Brownell"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:at25"); + diff --git a/trunk/drivers/misc/lkdtm.c b/trunk/drivers/misc/lkdtm.c index 3648b23d5c92..1bfe5d16963b 100644 --- a/trunk/drivers/misc/lkdtm.c +++ b/trunk/drivers/misc/lkdtm.c @@ -283,7 +283,7 @@ static int __init lkdtm_module_init(void) switch (cpoint) { case INT_HARDWARE_ENTRY: - lkdtm.kp.symbol_name = "do_IRQ"; + lkdtm.kp.symbol_name = "__do_IRQ"; lkdtm.entry = (kprobe_opcode_t*) jp_do_irq; break; case INT_HW_IRQ_EN: diff --git a/trunk/drivers/mmc/core/core.c b/trunk/drivers/mmc/core/core.c index 7dab2e5f4bc9..d84c880fac84 100644 --- a/trunk/drivers/mmc/core/core.c +++ b/trunk/drivers/mmc/core/core.c @@ -343,101 +343,6 @@ unsigned int mmc_align_data_size(struct mmc_card *card, unsigned int sz) } EXPORT_SYMBOL(mmc_align_data_size); -/** - * mmc_host_enable - enable a host. - * @host: mmc host to enable - * - * Hosts that support power saving can use the 'enable' and 'disable' - * methods to exit and enter power saving states. For more information - * see comments for struct mmc_host_ops. - */ -int mmc_host_enable(struct mmc_host *host) -{ - if (!(host->caps & MMC_CAP_DISABLE)) - return 0; - - if (host->en_dis_recurs) - return 0; - - if (host->nesting_cnt++) - return 0; - - cancel_delayed_work_sync(&host->disable); - - if (host->enabled) - return 0; - - if (host->ops->enable) { - int err; - - host->en_dis_recurs = 1; - err = host->ops->enable(host); - host->en_dis_recurs = 0; - - if (err) { - pr_debug("%s: enable error %d\n", - mmc_hostname(host), err); - return err; - } - } - host->enabled = 1; - return 0; -} -EXPORT_SYMBOL(mmc_host_enable); - -static int mmc_host_do_disable(struct mmc_host *host, int lazy) -{ - if (host->ops->disable) { - int err; - - host->en_dis_recurs = 1; - err = host->ops->disable(host, lazy); - host->en_dis_recurs = 0; - - if (err < 0) { - pr_debug("%s: disable error %d\n", - mmc_hostname(host), err); - return err; - } - if (err > 0) { - unsigned long delay = msecs_to_jiffies(err); - - mmc_schedule_delayed_work(&host->disable, delay); - } - } - host->enabled = 0; - return 0; -} - -/** - * mmc_host_disable - disable a host. - * @host: mmc host to disable - * - * Hosts that support power saving can use the 'enable' and 'disable' - * methods to exit and enter power saving states. For more information - * see comments for struct mmc_host_ops. - */ -int mmc_host_disable(struct mmc_host *host) -{ - int err; - - if (!(host->caps & MMC_CAP_DISABLE)) - return 0; - - if (host->en_dis_recurs) - return 0; - - if (--host->nesting_cnt) - return 0; - - if (!host->enabled) - return 0; - - err = mmc_host_do_disable(host, 0); - return err; -} -EXPORT_SYMBOL(mmc_host_disable); - /** * __mmc_claim_host - exclusively claim a host * @host: mmc host to claim @@ -461,110 +366,24 @@ int __mmc_claim_host(struct mmc_host *host, atomic_t *abort) while (1) { set_current_state(TASK_UNINTERRUPTIBLE); stop = abort ? atomic_read(abort) : 0; - if (stop || !host->claimed || host->claimer == current) + if (stop || !host->claimed) break; spin_unlock_irqrestore(&host->lock, flags); schedule(); spin_lock_irqsave(&host->lock, flags); } set_current_state(TASK_RUNNING); - if (!stop) { + if (!stop) host->claimed = 1; - host->claimer = current; - host->claim_cnt += 1; - } else + else wake_up(&host->wq); spin_unlock_irqrestore(&host->lock, flags); remove_wait_queue(&host->wq, &wait); - if (!stop) - mmc_host_enable(host); return stop; } EXPORT_SYMBOL(__mmc_claim_host); -/** - * mmc_try_claim_host - try exclusively to claim a host - * @host: mmc host to claim - * - * Returns %1 if the host is claimed, %0 otherwise. - */ -int mmc_try_claim_host(struct mmc_host *host) -{ - int claimed_host = 0; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - if (!host->claimed || host->claimer == current) { - host->claimed = 1; - host->claimer = current; - host->claim_cnt += 1; - claimed_host = 1; - } - spin_unlock_irqrestore(&host->lock, flags); - return claimed_host; -} -EXPORT_SYMBOL(mmc_try_claim_host); - -static void mmc_do_release_host(struct mmc_host *host) -{ - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - if (--host->claim_cnt) { - /* Release for nested claim */ - spin_unlock_irqrestore(&host->lock, flags); - } else { - host->claimed = 0; - host->claimer = NULL; - spin_unlock_irqrestore(&host->lock, flags); - wake_up(&host->wq); - } -} - -void mmc_host_deeper_disable(struct work_struct *work) -{ - struct mmc_host *host = - container_of(work, struct mmc_host, disable.work); - - /* If the host is claimed then we do not want to disable it anymore */ - if (!mmc_try_claim_host(host)) - return; - mmc_host_do_disable(host, 1); - mmc_do_release_host(host); -} - -/** - * mmc_host_lazy_disable - lazily disable a host. - * @host: mmc host to disable - * - * Hosts that support power saving can use the 'enable' and 'disable' - * methods to exit and enter power saving states. For more information - * see comments for struct mmc_host_ops. - */ -int mmc_host_lazy_disable(struct mmc_host *host) -{ - if (!(host->caps & MMC_CAP_DISABLE)) - return 0; - - if (host->en_dis_recurs) - return 0; - - if (--host->nesting_cnt) - return 0; - - if (!host->enabled) - return 0; - - if (host->disable_delay) { - mmc_schedule_delayed_work(&host->disable, - msecs_to_jiffies(host->disable_delay)); - return 0; - } else - return mmc_host_do_disable(host, 1); -} -EXPORT_SYMBOL(mmc_host_lazy_disable); - /** * mmc_release_host - release a host * @host: mmc host to release @@ -574,11 +393,15 @@ EXPORT_SYMBOL(mmc_host_lazy_disable); */ void mmc_release_host(struct mmc_host *host) { + unsigned long flags; + WARN_ON(!host->claimed); - mmc_host_lazy_disable(host); + spin_lock_irqsave(&host->lock, flags); + host->claimed = 0; + spin_unlock_irqrestore(&host->lock, flags); - mmc_do_release_host(host); + wake_up(&host->wq); } EXPORT_SYMBOL(mmc_release_host); @@ -864,13 +687,7 @@ void mmc_set_timing(struct mmc_host *host, unsigned int timing) */ static void mmc_power_up(struct mmc_host *host) { - int bit; - - /* If ocr is set, we use it */ - if (host->ocr) - bit = ffs(host->ocr) - 1; - else - bit = fls(host->ocr_avail) - 1; + int bit = fls(host->ocr_avail) - 1; host->ios.vdd = bit; if (mmc_host_is_spi(host)) { @@ -1130,8 +947,6 @@ void mmc_stop_host(struct mmc_host *host) spin_unlock_irqrestore(&host->lock, flags); #endif - if (host->caps & MMC_CAP_DISABLE) - cancel_delayed_work(&host->disable); cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); @@ -1143,8 +958,6 @@ void mmc_stop_host(struct mmc_host *host) mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); - mmc_bus_put(host); - return; } mmc_bus_put(host); @@ -1153,80 +966,6 @@ void mmc_stop_host(struct mmc_host *host) mmc_power_off(host); } -void mmc_power_save_host(struct mmc_host *host) -{ - mmc_bus_get(host); - - if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { - mmc_bus_put(host); - return; - } - - if (host->bus_ops->power_save) - host->bus_ops->power_save(host); - - mmc_bus_put(host); - - mmc_power_off(host); -} -EXPORT_SYMBOL(mmc_power_save_host); - -void mmc_power_restore_host(struct mmc_host *host) -{ - mmc_bus_get(host); - - if (!host->bus_ops || host->bus_dead || !host->bus_ops->power_restore) { - mmc_bus_put(host); - return; - } - - mmc_power_up(host); - host->bus_ops->power_restore(host); - - mmc_bus_put(host); -} -EXPORT_SYMBOL(mmc_power_restore_host); - -int mmc_card_awake(struct mmc_host *host) -{ - int err = -ENOSYS; - - mmc_bus_get(host); - - if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) - err = host->bus_ops->awake(host); - - mmc_bus_put(host); - - return err; -} -EXPORT_SYMBOL(mmc_card_awake); - -int mmc_card_sleep(struct mmc_host *host) -{ - int err = -ENOSYS; - - mmc_bus_get(host); - - if (host->bus_ops && !host->bus_dead && host->bus_ops->awake) - err = host->bus_ops->sleep(host); - - mmc_bus_put(host); - - return err; -} -EXPORT_SYMBOL(mmc_card_sleep); - -int mmc_card_can_sleep(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - - if (card && mmc_card_mmc(card) && card->ext_csd.rev >= 3) - return 1; - return 0; -} -EXPORT_SYMBOL(mmc_card_can_sleep); - #ifdef CONFIG_PM /** @@ -1236,36 +975,27 @@ EXPORT_SYMBOL(mmc_card_can_sleep); */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { - int err = 0; - - if (host->caps & MMC_CAP_DISABLE) - cancel_delayed_work(&host->disable); cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) - err = host->bus_ops->suspend(host); - if (err == -ENOSYS || !host->bus_ops->resume) { - /* - * We simply "remove" the card in this case. - * It will be redetected on resume. - */ + host->bus_ops->suspend(host); + if (!host->bus_ops->resume) { if (host->bus_ops->remove) host->bus_ops->remove(host); + mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); - err = 0; } } mmc_bus_put(host); - if (!err) - mmc_power_off(host); + mmc_power_off(host); - return err; + return 0; } EXPORT_SYMBOL(mmc_suspend_host); @@ -1276,26 +1006,12 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - int err = 0; - mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { mmc_power_up(host); mmc_select_voltage(host, host->ocr); BUG_ON(!host->bus_ops->resume); - err = host->bus_ops->resume(host); - if (err) { - printk(KERN_WARNING "%s: error %d during resume " - "(card was removed?)\n", - mmc_hostname(host), err); - if (host->bus_ops->remove) - host->bus_ops->remove(host); - mmc_claim_host(host); - mmc_detach_bus(host); - mmc_release_host(host); - /* no need to bother upper layers */ - err = 0; - } + host->bus_ops->resume(host); } mmc_bus_put(host); @@ -1305,7 +1021,7 @@ int mmc_resume_host(struct mmc_host *host) */ mmc_detect_change(host, 1); - return err; + return 0; } EXPORT_SYMBOL(mmc_resume_host); diff --git a/trunk/drivers/mmc/core/core.h b/trunk/drivers/mmc/core/core.h index 67ae6abc4230..c819effa1032 100644 --- a/trunk/drivers/mmc/core/core.h +++ b/trunk/drivers/mmc/core/core.h @@ -16,14 +16,10 @@ #define MMC_CMD_RETRIES 3 struct mmc_bus_ops { - int (*awake)(struct mmc_host *); - int (*sleep)(struct mmc_host *); void (*remove)(struct mmc_host *); void (*detect)(struct mmc_host *); - int (*suspend)(struct mmc_host *); - int (*resume)(struct mmc_host *); - void (*power_save)(struct mmc_host *); - void (*power_restore)(struct mmc_host *); + void (*suspend)(struct mmc_host *); + void (*resume)(struct mmc_host *); }; void mmc_attach_bus(struct mmc_host *host, const struct mmc_bus_ops *ops); diff --git a/trunk/drivers/mmc/core/host.c b/trunk/drivers/mmc/core/host.c index a268d12f1af0..5e945e64ead7 100644 --- a/trunk/drivers/mmc/core/host.c +++ b/trunk/drivers/mmc/core/host.c @@ -83,7 +83,6 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) spin_lock_init(&host->lock); init_waitqueue_head(&host->wq); INIT_DELAYED_WORK(&host->detect, mmc_rescan); - INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable); /* * By default, hosts do not support SGIO or large requests. diff --git a/trunk/drivers/mmc/core/host.h b/trunk/drivers/mmc/core/host.h index 8c87e1109a34..c2dc3d2d9f9a 100644 --- a/trunk/drivers/mmc/core/host.h +++ b/trunk/drivers/mmc/core/host.h @@ -14,7 +14,5 @@ int mmc_register_host_class(void); void mmc_unregister_host_class(void); -void mmc_host_deeper_disable(struct work_struct *work); - #endif diff --git a/trunk/drivers/mmc/core/mmc.c b/trunk/drivers/mmc/core/mmc.c index bfefce365ae7..2fb9d5f271ea 100644 --- a/trunk/drivers/mmc/core/mmc.c +++ b/trunk/drivers/mmc/core/mmc.c @@ -160,6 +160,7 @@ static int mmc_read_ext_csd(struct mmc_card *card) { int err; u8 *ext_csd; + unsigned int ext_csd_struct; BUG_ON(!card); @@ -179,11 +180,11 @@ static int mmc_read_ext_csd(struct mmc_card *card) err = mmc_send_ext_csd(card, ext_csd); if (err) { - /* If the host or the card can't do the switch, - * fail more gracefully. */ - if ((err != -EINVAL) - && (err != -ENOSYS) - && (err != -EFAULT)) + /* + * We all hosts that cannot perform the command + * to fail more gracefully + */ + if (err != -EINVAL) goto out; /* @@ -206,16 +207,16 @@ static int mmc_read_ext_csd(struct mmc_card *card) goto out; } - card->ext_csd.rev = ext_csd[EXT_CSD_REV]; - if (card->ext_csd.rev > 3) { + ext_csd_struct = ext_csd[EXT_CSD_REV]; + if (ext_csd_struct > 3) { printk(KERN_ERR "%s: unrecognised EXT_CSD structure " "version %d\n", mmc_hostname(card->host), - card->ext_csd.rev); + ext_csd_struct); err = -EINVAL; goto out; } - if (card->ext_csd.rev >= 2) { + if (ext_csd_struct >= 2) { card->ext_csd.sectors = ext_csd[EXT_CSD_SEC_CNT + 0] << 0 | ext_csd[EXT_CSD_SEC_CNT + 1] << 8 | @@ -240,15 +241,6 @@ static int mmc_read_ext_csd(struct mmc_card *card) goto out; } - if (card->ext_csd.rev >= 3) { - u8 sa_shift = ext_csd[EXT_CSD_S_A_TIMEOUT]; - - /* Sleep / awake timeout in 100ns units */ - if (sa_shift > 0 && sa_shift <= 0x17) - card->ext_csd.sa_timeout = - 1 << ext_csd[EXT_CSD_S_A_TIMEOUT]; - } - out: kfree(ext_csd); @@ -416,17 +408,12 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, (host->caps & MMC_CAP_MMC_HIGHSPEED)) { err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_HS_TIMING, 1); - if (err && err != -EBADMSG) + if (err) goto free_card; - if (err) { - printk(KERN_WARNING "%s: switch to highspeed failed\n", - mmc_hostname(card->host)); - err = 0; - } else { - mmc_card_set_highspeed(card); - mmc_set_timing(card->host, MMC_TIMING_MMC_HS); - } + mmc_card_set_highspeed(card); + + mmc_set_timing(card->host, MMC_TIMING_MMC_HS); } /* @@ -461,17 +448,10 @@ static int mmc_init_card(struct mmc_host *host, u32 ocr, err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL, EXT_CSD_BUS_WIDTH, ext_csd_bit); - if (err && err != -EBADMSG) + if (err) goto free_card; - if (err) { - printk(KERN_WARNING "%s: switch to bus width %d " - "failed\n", mmc_hostname(card->host), - 1 << bus_width); - err = 0; - } else { - mmc_set_bus_width(card->host, bus_width); - } + mmc_set_bus_width(card->host, bus_width); } if (!oldcard) @@ -527,10 +507,12 @@ static void mmc_detect(struct mmc_host *host) } } +#ifdef CONFIG_MMC_UNSAFE_RESUME + /* * Suspend callback from host. */ -static int mmc_suspend(struct mmc_host *host) +static void mmc_suspend(struct mmc_host *host) { BUG_ON(!host); BUG_ON(!host->card); @@ -540,8 +522,6 @@ static int mmc_suspend(struct mmc_host *host) mmc_deselect_cards(host); host->card->state &= ~MMC_STATE_HIGHSPEED; mmc_release_host(host); - - return 0; } /* @@ -550,7 +530,7 @@ static int mmc_suspend(struct mmc_host *host) * This function tries to determine if the same card is still present * and, if so, restore all state to it. */ -static int mmc_resume(struct mmc_host *host) +static void mmc_resume(struct mmc_host *host) { int err; @@ -561,99 +541,30 @@ static int mmc_resume(struct mmc_host *host) err = mmc_init_card(host, host->ocr, host->card); mmc_release_host(host); - return err; -} - -static void mmc_power_restore(struct mmc_host *host) -{ - host->card->state &= ~MMC_STATE_HIGHSPEED; - mmc_claim_host(host); - mmc_init_card(host, host->ocr, host->card); - mmc_release_host(host); -} - -static int mmc_sleep(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - int err = -ENOSYS; - - if (card && card->ext_csd.rev >= 3) { - err = mmc_card_sleepawake(host, 1); - if (err < 0) - pr_debug("%s: Error %d while putting card into sleep", - mmc_hostname(host), err); - } - - return err; -} + if (err) { + mmc_remove(host); -static int mmc_awake(struct mmc_host *host) -{ - struct mmc_card *card = host->card; - int err = -ENOSYS; - - if (card && card->ext_csd.rev >= 3) { - err = mmc_card_sleepawake(host, 0); - if (err < 0) - pr_debug("%s: Error %d while awaking sleeping card", - mmc_hostname(host), err); + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_release_host(host); } - return err; } -#ifdef CONFIG_MMC_UNSAFE_RESUME - -static const struct mmc_bus_ops mmc_ops = { - .awake = mmc_awake, - .sleep = mmc_sleep, - .remove = mmc_remove, - .detect = mmc_detect, - .suspend = mmc_suspend, - .resume = mmc_resume, - .power_restore = mmc_power_restore, -}; +#else -static void mmc_attach_bus_ops(struct mmc_host *host) -{ - mmc_attach_bus(host, &mmc_ops); -} +#define mmc_suspend NULL +#define mmc_resume NULL -#else +#endif static const struct mmc_bus_ops mmc_ops = { - .awake = mmc_awake, - .sleep = mmc_sleep, - .remove = mmc_remove, - .detect = mmc_detect, - .suspend = NULL, - .resume = NULL, - .power_restore = mmc_power_restore, -}; - -static const struct mmc_bus_ops mmc_ops_unsafe = { - .awake = mmc_awake, - .sleep = mmc_sleep, .remove = mmc_remove, .detect = mmc_detect, .suspend = mmc_suspend, .resume = mmc_resume, - .power_restore = mmc_power_restore, }; -static void mmc_attach_bus_ops(struct mmc_host *host) -{ - const struct mmc_bus_ops *bus_ops; - - if (host->caps & MMC_CAP_NONREMOVABLE) - bus_ops = &mmc_ops_unsafe; - else - bus_ops = &mmc_ops; - mmc_attach_bus(host, bus_ops); -} - -#endif - /* * Starting point for MMC card init. */ @@ -664,7 +575,7 @@ int mmc_attach_mmc(struct mmc_host *host, u32 ocr) BUG_ON(!host); WARN_ON(!host->claimed); - mmc_attach_bus_ops(host); + mmc_attach_bus(host, &mmc_ops); /* * We need to get OCR a different way for SPI. diff --git a/trunk/drivers/mmc/core/mmc_ops.c b/trunk/drivers/mmc/core/mmc_ops.c index d2cb5c634392..34ce2703d29a 100644 --- a/trunk/drivers/mmc/core/mmc_ops.c +++ b/trunk/drivers/mmc/core/mmc_ops.c @@ -57,42 +57,6 @@ int mmc_deselect_cards(struct mmc_host *host) return _mmc_select_card(host, NULL); } -int mmc_card_sleepawake(struct mmc_host *host, int sleep) -{ - struct mmc_command cmd; - struct mmc_card *card = host->card; - int err; - - if (sleep) - mmc_deselect_cards(host); - - memset(&cmd, 0, sizeof(struct mmc_command)); - - cmd.opcode = MMC_SLEEP_AWAKE; - cmd.arg = card->rca << 16; - if (sleep) - cmd.arg |= 1 << 15; - - cmd.flags = MMC_RSP_R1B | MMC_CMD_AC; - err = mmc_wait_for_cmd(host, &cmd, 0); - if (err) - return err; - - /* - * If the host does not wait while the card signals busy, then we will - * will have to wait the sleep/awake timeout. Note, we cannot use the - * SEND_STATUS command to poll the status because that command (and most - * others) is invalid while the card sleeps. - */ - if (!(host->caps & MMC_CAP_WAIT_WHILE_BUSY)) - mmc_delay(DIV_ROUND_UP(card->ext_csd.sa_timeout, 10000)); - - if (!sleep) - err = mmc_select_card(card); - - return err; -} - int mmc_go_idle(struct mmc_host *host) { int err; @@ -390,7 +354,6 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) { int err; struct mmc_command cmd; - u32 status; BUG_ON(!card); BUG_ON(!card->host); @@ -408,28 +371,6 @@ int mmc_switch(struct mmc_card *card, u8 set, u8 index, u8 value) if (err) return err; - /* Must check status to be sure of no errors */ - do { - err = mmc_send_status(card, &status); - if (err) - return err; - if (card->host->caps & MMC_CAP_WAIT_WHILE_BUSY) - break; - if (mmc_host_is_spi(card->host)) - break; - } while (R1_CURRENT_STATE(status) == 7); - - if (mmc_host_is_spi(card->host)) { - if (status & R1_SPI_ILLEGAL_COMMAND) - return -EBADMSG; - } else { - if (status & 0xFDFFA000) - printk(KERN_WARNING "%s: unexpected status %#x after " - "switch", mmc_hostname(card->host), status); - if (status & R1_SWITCH_ERROR) - return -EBADMSG; - } - return 0; } diff --git a/trunk/drivers/mmc/core/mmc_ops.h b/trunk/drivers/mmc/core/mmc_ops.h index 653eb8e84178..17854bf7cf0d 100644 --- a/trunk/drivers/mmc/core/mmc_ops.h +++ b/trunk/drivers/mmc/core/mmc_ops.h @@ -25,7 +25,6 @@ int mmc_send_status(struct mmc_card *card, u32 *status); int mmc_send_cid(struct mmc_host *host, u32 *cid); int mmc_spi_read_ocr(struct mmc_host *host, int highcap, u32 *ocrp); int mmc_spi_set_crc(struct mmc_host *host, int use_crc); -int mmc_card_sleepawake(struct mmc_host *host, int sleep); #endif diff --git a/trunk/drivers/mmc/core/sd.c b/trunk/drivers/mmc/core/sd.c index 10b2a4d20f5a..7ad646fe077e 100644 --- a/trunk/drivers/mmc/core/sd.c +++ b/trunk/drivers/mmc/core/sd.c @@ -210,11 +210,11 @@ static int mmc_read_switch(struct mmc_card *card) err = mmc_sd_switch(card, 0, 0, 1, status); if (err) { - /* If the host or the card can't do the switch, - * fail more gracefully. */ - if ((err != -EINVAL) - && (err != -ENOSYS) - && (err != -EFAULT)) + /* + * We all hosts that cannot perform the command + * to fail more gracefully + */ + if (err != -EINVAL) goto out; printk(KERN_WARNING "%s: problem reading switch " @@ -561,10 +561,12 @@ static void mmc_sd_detect(struct mmc_host *host) } } +#ifdef CONFIG_MMC_UNSAFE_RESUME + /* * Suspend callback from host. */ -static int mmc_sd_suspend(struct mmc_host *host) +static void mmc_sd_suspend(struct mmc_host *host) { BUG_ON(!host); BUG_ON(!host->card); @@ -574,8 +576,6 @@ static int mmc_sd_suspend(struct mmc_host *host) mmc_deselect_cards(host); host->card->state &= ~MMC_STATE_HIGHSPEED; mmc_release_host(host); - - return 0; } /* @@ -584,7 +584,7 @@ static int mmc_sd_suspend(struct mmc_host *host) * This function tries to determine if the same card is still present * and, if so, restore all state to it. */ -static int mmc_sd_resume(struct mmc_host *host) +static void mmc_sd_resume(struct mmc_host *host) { int err; @@ -595,63 +595,30 @@ static int mmc_sd_resume(struct mmc_host *host) err = mmc_sd_init_card(host, host->ocr, host->card); mmc_release_host(host); - return err; -} - -static void mmc_sd_power_restore(struct mmc_host *host) -{ - host->card->state &= ~MMC_STATE_HIGHSPEED; - mmc_claim_host(host); - mmc_sd_init_card(host, host->ocr, host->card); - mmc_release_host(host); -} - -#ifdef CONFIG_MMC_UNSAFE_RESUME + if (err) { + mmc_sd_remove(host); -static const struct mmc_bus_ops mmc_sd_ops = { - .remove = mmc_sd_remove, - .detect = mmc_sd_detect, - .suspend = mmc_sd_suspend, - .resume = mmc_sd_resume, - .power_restore = mmc_sd_power_restore, -}; + mmc_claim_host(host); + mmc_detach_bus(host); + mmc_release_host(host); + } -static void mmc_sd_attach_bus_ops(struct mmc_host *host) -{ - mmc_attach_bus(host, &mmc_sd_ops); } #else -static const struct mmc_bus_ops mmc_sd_ops = { - .remove = mmc_sd_remove, - .detect = mmc_sd_detect, - .suspend = NULL, - .resume = NULL, - .power_restore = mmc_sd_power_restore, -}; +#define mmc_sd_suspend NULL +#define mmc_sd_resume NULL -static const struct mmc_bus_ops mmc_sd_ops_unsafe = { +#endif + +static const struct mmc_bus_ops mmc_sd_ops = { .remove = mmc_sd_remove, .detect = mmc_sd_detect, .suspend = mmc_sd_suspend, .resume = mmc_sd_resume, - .power_restore = mmc_sd_power_restore, }; -static void mmc_sd_attach_bus_ops(struct mmc_host *host) -{ - const struct mmc_bus_ops *bus_ops; - - if (host->caps & MMC_CAP_NONREMOVABLE) - bus_ops = &mmc_sd_ops_unsafe; - else - bus_ops = &mmc_sd_ops; - mmc_attach_bus(host, bus_ops); -} - -#endif - /* * Starting point for SD card init. */ @@ -662,7 +629,7 @@ int mmc_attach_sd(struct mmc_host *host, u32 ocr) BUG_ON(!host); WARN_ON(!host->claimed); - mmc_sd_attach_bus_ops(host); + mmc_attach_bus(host, &mmc_sd_ops); /* * We need to get OCR a different way for SPI. diff --git a/trunk/drivers/mmc/core/sdio.c b/trunk/drivers/mmc/core/sdio.c index cdb845b68ab5..fb99ccff9080 100644 --- a/trunk/drivers/mmc/core/sdio.c +++ b/trunk/drivers/mmc/core/sdio.c @@ -164,29 +164,6 @@ static int sdio_enable_wide(struct mmc_card *card) return 0; } -/* - * If desired, disconnect the pull-up resistor on CD/DAT[3] (pin 1) - * of the card. This may be required on certain setups of boards, - * controllers and embedded sdio device which do not need the card's - * pull-up. As a result, card detection is disabled and power is saved. - */ -static int sdio_disable_cd(struct mmc_card *card) -{ - int ret; - u8 ctrl; - - if (!card->cccr.disable_cd) - return 0; - - ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_IF, 0, &ctrl); - if (ret) - return ret; - - ctrl |= SDIO_BUS_CD_DISABLE; - - return mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_IF, ctrl, NULL); -} - /* * Test if the card supports high-speed mode and, if so, switch to it. */ @@ -217,135 +194,6 @@ static int sdio_enable_hs(struct mmc_card *card) return 0; } -/* - * Handle the detection and initialisation of a card. - * - * In the case of a resume, "oldcard" will contain the card - * we're trying to reinitialise. - */ -static int mmc_sdio_init_card(struct mmc_host *host, u32 ocr, - struct mmc_card *oldcard) -{ - struct mmc_card *card; - int err; - - BUG_ON(!host); - WARN_ON(!host->claimed); - - /* - * Inform the card of the voltage - */ - err = mmc_send_io_op_cond(host, host->ocr, &ocr); - if (err) - goto err; - - /* - * For SPI, enable CRC as appropriate. - */ - if (mmc_host_is_spi(host)) { - err = mmc_spi_set_crc(host, use_spi_crc); - if (err) - goto err; - } - - /* - * Allocate card structure. - */ - card = mmc_alloc_card(host, NULL); - if (IS_ERR(card)) { - err = PTR_ERR(card); - goto err; - } - - card->type = MMC_TYPE_SDIO; - - /* - * For native busses: set card RCA and quit open drain mode. - */ - if (!mmc_host_is_spi(host)) { - err = mmc_send_relative_addr(host, &card->rca); - if (err) - goto remove; - - mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); - } - - /* - * Select card, as all following commands rely on that. - */ - if (!mmc_host_is_spi(host)) { - err = mmc_select_card(card); - if (err) - goto remove; - } - - /* - * Read the common registers. - */ - err = sdio_read_cccr(card); - if (err) - goto remove; - - /* - * Read the common CIS tuples. - */ - err = sdio_read_common_cis(card); - if (err) - goto remove; - - if (oldcard) { - int same = (card->cis.vendor == oldcard->cis.vendor && - card->cis.device == oldcard->cis.device); - mmc_remove_card(card); - if (!same) { - err = -ENOENT; - goto err; - } - card = oldcard; - return 0; - } - - /* - * Switch to high-speed (if supported). - */ - err = sdio_enable_hs(card); - if (err) - goto remove; - - /* - * Change to the card's maximum speed. - */ - if (mmc_card_highspeed(card)) { - /* - * The SDIO specification doesn't mention how - * the CIS transfer speed register relates to - * high-speed, but it seems that 50 MHz is - * mandatory. - */ - mmc_set_clock(host, 50000000); - } else { - mmc_set_clock(host, card->cis.max_dtr); - } - - /* - * Switch to wider bus (if supported). - */ - err = sdio_enable_wide(card); - if (err) - goto remove; - - if (!oldcard) - host->card = card; - return 0; - -remove: - if (!oldcard) - mmc_remove_card(card); - -err: - return err; -} - /* * Host is being removed. Free up the current card. */ @@ -395,77 +243,10 @@ static void mmc_sdio_detect(struct mmc_host *host) } } -/* - * SDIO suspend. We need to suspend all functions separately. - * Therefore all registered functions must have drivers with suspend - * and resume methods. Failing that we simply remove the whole card. - */ -static int mmc_sdio_suspend(struct mmc_host *host) -{ - int i, err = 0; - - for (i = 0; i < host->card->sdio_funcs; i++) { - struct sdio_func *func = host->card->sdio_func[i]; - if (func && sdio_func_present(func) && func->dev.driver) { - const struct dev_pm_ops *pmops = func->dev.driver->pm; - if (!pmops || !pmops->suspend || !pmops->resume) { - /* force removal of entire card in that case */ - err = -ENOSYS; - } else - err = pmops->suspend(&func->dev); - if (err) - break; - } - } - while (err && --i >= 0) { - struct sdio_func *func = host->card->sdio_func[i]; - if (func && sdio_func_present(func) && func->dev.driver) { - const struct dev_pm_ops *pmops = func->dev.driver->pm; - pmops->resume(&func->dev); - } - } - - return err; -} - -static int mmc_sdio_resume(struct mmc_host *host) -{ - int i, err; - - BUG_ON(!host); - BUG_ON(!host->card); - - /* Basic card reinitialization. */ - mmc_claim_host(host); - err = mmc_sdio_init_card(host, host->ocr, host->card); - mmc_release_host(host); - - /* - * If the card looked to be the same as before suspending, then - * we proceed to resume all card functions. If one of them returns - * an error then we simply return that error to the core and the - * card will be redetected as new. It is the responsibility of - * the function driver to perform further tests with the extra - * knowledge it has of the card to confirm the card is indeed the - * same as before suspending (same MAC address for network cards, - * etc.) and return an error otherwise. - */ - for (i = 0; !err && i < host->card->sdio_funcs; i++) { - struct sdio_func *func = host->card->sdio_func[i]; - if (func && sdio_func_present(func) && func->dev.driver) { - const struct dev_pm_ops *pmops = func->dev.driver->pm; - err = pmops->resume(&func->dev); - } - } - - return err; -} static const struct mmc_bus_ops mmc_sdio_ops = { .remove = mmc_sdio_remove, .detect = mmc_sdio_detect, - .suspend = mmc_sdio_suspend, - .resume = mmc_sdio_resume, }; @@ -494,6 +275,13 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) ocr &= ~0x7F; } + if (ocr & MMC_VDD_165_195) { + printk(KERN_WARNING "%s: SDIO card claims to support the " + "incompletely defined 'low voltage range'. This " + "will be ignored.\n", mmc_hostname(host)); + ocr &= ~MMC_VDD_165_195; + } + host->ocr = mmc_select_voltage(host, ocr); /* @@ -505,23 +293,101 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) } /* - * Detect and init the card. + * Inform the card of the voltage */ - err = mmc_sdio_init_card(host, host->ocr, NULL); + err = mmc_send_io_op_cond(host, host->ocr, &ocr); if (err) goto err; - card = host->card; + + /* + * For SPI, enable CRC as appropriate. + */ + if (mmc_host_is_spi(host)) { + err = mmc_spi_set_crc(host, use_spi_crc); + if (err) + goto err; + } /* * The number of functions on the card is encoded inside * the ocr. */ - card->sdio_funcs = funcs = (ocr & 0x70000000) >> 28; + funcs = (ocr & 0x70000000) >> 28; + + /* + * Allocate card structure. + */ + card = mmc_alloc_card(host, NULL); + if (IS_ERR(card)) { + err = PTR_ERR(card); + goto err; + } + + card->type = MMC_TYPE_SDIO; + card->sdio_funcs = funcs; + + host->card = card; + + /* + * For native busses: set card RCA and quit open drain mode. + */ + if (!mmc_host_is_spi(host)) { + err = mmc_send_relative_addr(host, &card->rca); + if (err) + goto remove; + + mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL); + } + + /* + * Select card, as all following commands rely on that. + */ + if (!mmc_host_is_spi(host)) { + err = mmc_select_card(card); + if (err) + goto remove; + } /* - * If needed, disconnect card detection pull-up resistor. + * Read the common registers. */ - err = sdio_disable_cd(card); + err = sdio_read_cccr(card); + if (err) + goto remove; + + /* + * Read the common CIS tuples. + */ + err = sdio_read_common_cis(card); + if (err) + goto remove; + + /* + * Switch to high-speed (if supported). + */ + err = sdio_enable_hs(card); + if (err) + goto remove; + + /* + * Change to the card's maximum speed. + */ + if (mmc_card_highspeed(card)) { + /* + * The SDIO specification doesn't mention how + * the CIS transfer speed register relates to + * high-speed, but it seems that 50 MHz is + * mandatory. + */ + mmc_set_clock(host, 50000000); + } else { + mmc_set_clock(host, card->cis.max_dtr); + } + + /* + * Switch to wider bus (if supported). + */ + err = sdio_enable_wide(card); if (err) goto remove; diff --git a/trunk/drivers/mmc/core/sdio_bus.c b/trunk/drivers/mmc/core/sdio_bus.c index d37464e296a5..46284b527397 100644 --- a/trunk/drivers/mmc/core/sdio_bus.c +++ b/trunk/drivers/mmc/core/sdio_bus.c @@ -20,6 +20,9 @@ #include "sdio_cis.h" #include "sdio_bus.h" +#define dev_to_sdio_func(d) container_of(d, struct sdio_func, dev) +#define to_sdio_driver(d) container_of(d, struct sdio_driver, drv) + /* show configuration fields */ #define sdio_config_attr(field, format_string) \ static ssize_t \ diff --git a/trunk/drivers/mmc/core/sdio_cis.c b/trunk/drivers/mmc/core/sdio_cis.c index 6636354b48ce..963f2937c5e3 100644 --- a/trunk/drivers/mmc/core/sdio_cis.c +++ b/trunk/drivers/mmc/core/sdio_cis.c @@ -40,7 +40,7 @@ static int cistpl_vers_1(struct mmc_card *card, struct sdio_func *func, nr_strings++; } - if (nr_strings < 4) { + if (buf[i-1] != '\0') { printk(KERN_WARNING "SDIO: ignoring broken CISTPL_VERS_1\n"); return 0; } diff --git a/trunk/drivers/mmc/core/sdio_io.c b/trunk/drivers/mmc/core/sdio_io.c index f9aa8a7deffa..f61fc2d4cd0a 100644 --- a/trunk/drivers/mmc/core/sdio_io.c +++ b/trunk/drivers/mmc/core/sdio_io.c @@ -624,7 +624,7 @@ void sdio_f0_writeb(struct sdio_func *func, unsigned char b, unsigned int addr, BUG_ON(!func); - if ((addr < 0xF0 || addr > 0xFF) && (!mmc_card_lenient_fn0(func->card))) { + if (addr < 0xF0 || addr > 0xFF) { if (err_ret) *err_ret = -EINVAL; return; diff --git a/trunk/drivers/mmc/host/Kconfig b/trunk/drivers/mmc/host/Kconfig index 7cb057f3f883..891ef18bd77b 100644 --- a/trunk/drivers/mmc/host/Kconfig +++ b/trunk/drivers/mmc/host/Kconfig @@ -132,11 +132,11 @@ config MMC_OMAP config MMC_OMAP_HS tristate "TI OMAP High Speed Multimedia Card Interface support" - depends on ARCH_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4 + depends on ARCH_OMAP2430 || ARCH_OMAP3 help This selects the TI OMAP High Speed Multimedia card Interface. - If you have an OMAP2430 or OMAP3 board or OMAP4 board with a - Multimedia Card slot, say Y or M here. + If you have an OMAP2430 or OMAP3 board with a Multimedia Card slot, + say Y or M here. If unsure, say N. @@ -160,12 +160,6 @@ config MMC_AU1X If unsure, say N. -choice - prompt "Atmel SD/MMC Driver" - default MMC_ATMELMCI if AVR32 - help - Choose which driver to use for the Atmel MCI Silicon - config MMC_AT91 tristate "AT91 SD/MMC Card Interface support" depends on ARCH_AT91 @@ -176,19 +170,17 @@ config MMC_AT91 config MMC_ATMELMCI tristate "Atmel Multimedia Card Interface support" - depends on AVR32 || ARCH_AT91 + depends on AVR32 help This selects the Atmel Multimedia Card Interface driver. If - you have an AT32 (AVR32) or AT91 platform with a Multimedia - Card slot, say Y or M here. + you have an AT32 (AVR32) platform with a Multimedia Card + slot, say Y or M here. If unsure, say N. -endchoice - config MMC_ATMELMCI_DMA bool "Atmel MCI DMA support (EXPERIMENTAL)" - depends on MMC_ATMELMCI && AVR32 && DMA_ENGINE && EXPERIMENTAL + depends on MMC_ATMELMCI && DMA_ENGINE && EXPERIMENTAL help Say Y here to have the Atmel MCI driver use a DMA engine to do data transfers and thus increase the throughput and @@ -207,13 +199,6 @@ config MMC_IMX If unsure, say N. -config MMC_MSM7X00A - tristate "Qualcomm MSM 7X00A SDCC Controller Support" - depends on MMC && ARCH_MSM - help - This provides support for the SD/MMC cell found in the - MSM 7X00A controllers from Qualcomm. - config MMC_MXC tristate "Freescale i.MX2/3 Multimedia Card Interface support" depends on ARCH_MXC diff --git a/trunk/drivers/mmc/host/Makefile b/trunk/drivers/mmc/host/Makefile index abcb0400e06d..cf153f628457 100644 --- a/trunk/drivers/mmc/host/Makefile +++ b/trunk/drivers/mmc/host/Makefile @@ -23,7 +23,6 @@ obj-$(CONFIG_MMC_OMAP_HS) += omap_hsmmc.o obj-$(CONFIG_MMC_AT91) += at91_mci.o obj-$(CONFIG_MMC_ATMELMCI) += atmel-mci.o obj-$(CONFIG_MMC_TIFM_SD) += tifm_sd.o -obj-$(CONFIG_MMC_MSM7X00A) += msm_sdcc.o obj-$(CONFIG_MMC_MVSDIO) += mvsdio.o obj-$(CONFIG_MMC_SPI) += mmc_spi.o ifeq ($(CONFIG_OF),y) diff --git a/trunk/drivers/mmc/host/atmel-mci.c b/trunk/drivers/mmc/host/atmel-mci.c index 065fa818be57..7b603e4b41db 100644 --- a/trunk/drivers/mmc/host/atmel-mci.c +++ b/trunk/drivers/mmc/host/atmel-mci.c @@ -30,7 +30,6 @@ #include #include -#include #include #include "atmel-mci-regs.h" @@ -210,18 +209,6 @@ struct atmel_mci_slot { #define atmci_set_pending(host, event) \ set_bit(event, &host->pending_events) -/* - * Enable or disable features/registers based on - * whether the processor supports them - */ -static bool mci_has_rwproof(void) -{ - if (cpu_is_at91sam9261() || cpu_is_at91rm9200()) - return false; - else - return true; -} - /* * The debugfs stuff below is mostly optimized away when * CONFIG_DEBUG_FS is not set. @@ -289,13 +276,8 @@ static void atmci_show_status_reg(struct seq_file *s, [3] = "BLKE", [4] = "DTIP", [5] = "NOTBUSY", - [6] = "ENDRX", - [7] = "ENDTX", [8] = "SDIOIRQA", [9] = "SDIOIRQB", - [12] = "SDIOWAIT", - [14] = "RXBUFF", - [15] = "TXBUFE", [16] = "RINDE", [17] = "RDIRE", [18] = "RCRCE", @@ -303,11 +285,6 @@ static void atmci_show_status_reg(struct seq_file *s, [20] = "RTOE", [21] = "DCRCE", [22] = "DTOE", - [23] = "CSTOE", - [24] = "BLKOVRE", - [25] = "DMADONE", - [26] = "FIFOEMPTY", - [27] = "XFRDONE", [30] = "OVRE", [31] = "UNRE", }; @@ -872,15 +849,13 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) clkdiv = 255; } - host->mode_reg = MCI_MR_CLKDIV(clkdiv); - /* * WRPROOF and RDPROOF prevent overruns/underruns by * stopping the clock when the FIFO is full/empty. * This state is not expected to last for long. */ - if (mci_has_rwproof()) - host->mode_reg |= (MCI_MR_WRPROOF | MCI_MR_RDPROOF); + host->mode_reg = MCI_MR_CLKDIV(clkdiv) | MCI_MR_WRPROOF + | MCI_MR_RDPROOF; if (list_empty(&host->queue)) mci_writel(host, MR, host->mode_reg); @@ -1673,10 +1648,8 @@ static int __init atmci_probe(struct platform_device *pdev) nr_slots++; } - if (!nr_slots) { - dev_err(&pdev->dev, "init failed: no slot defined\n"); + if (!nr_slots) goto err_init_slot; - } dev_info(&pdev->dev, "Atmel MCI controller at 0x%08lx irq %d, %u slots\n", diff --git a/trunk/drivers/mmc/host/mmc_spi.c b/trunk/drivers/mmc/host/mmc_spi.c index d55fe4fb7935..a461017ce5ce 100644 --- a/trunk/drivers/mmc/host/mmc_spi.c +++ b/trunk/drivers/mmc/host/mmc_spi.c @@ -1562,4 +1562,3 @@ MODULE_AUTHOR("Mike Lavender, David Brownell, " "Hans-Peter Nilsson, Jan Nikitenko"); MODULE_DESCRIPTION("SPI SD/MMC host driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:mmc_spi"); diff --git a/trunk/drivers/mmc/host/msm_sdcc.c b/trunk/drivers/mmc/host/msm_sdcc.c deleted file mode 100644 index dba4600bcdb4..000000000000 --- a/trunk/drivers/mmc/host/msm_sdcc.c +++ /dev/null @@ -1,1287 +0,0 @@ -/* - * linux/drivers/mmc/host/msm_sdcc.c - Qualcomm MSM 7X00A SDCC Driver - * - * Copyright (C) 2007 Google Inc, - * Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Based on mmci.c - * - * Author: San Mehat (san@android.com) - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include - -#include "msm_sdcc.h" - -#define DRIVER_NAME "msm-sdcc" - -static unsigned int msmsdcc_fmin = 144000; -static unsigned int msmsdcc_fmax = 50000000; -static unsigned int msmsdcc_4bit = 1; -static unsigned int msmsdcc_pwrsave = 1; -static unsigned int msmsdcc_piopoll = 1; -static unsigned int msmsdcc_sdioirq; - -#define PIO_SPINMAX 30 -#define CMD_SPINMAX 20 - -static void -msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, - u32 c); - -static void -msmsdcc_request_end(struct msmsdcc_host *host, struct mmc_request *mrq) -{ - writel(0, host->base + MMCICOMMAND); - - BUG_ON(host->curr.data); - - host->curr.mrq = NULL; - host->curr.cmd = NULL; - - if (mrq->data) - mrq->data->bytes_xfered = host->curr.data_xfered; - if (mrq->cmd->error == -ETIMEDOUT) - mdelay(5); - - /* - * Need to drop the host lock here; mmc_request_done may call - * back into the driver... - */ - spin_unlock(&host->lock); - mmc_request_done(host->mmc, mrq); - spin_lock(&host->lock); -} - -static void -msmsdcc_stop_data(struct msmsdcc_host *host) -{ - writel(0, host->base + MMCIDATACTRL); - host->curr.data = NULL; - host->curr.got_dataend = host->curr.got_datablkend = 0; -} - -uint32_t msmsdcc_fifo_addr(struct msmsdcc_host *host) -{ - switch (host->pdev_id) { - case 1: - return MSM_SDC1_PHYS + MMCIFIFO; - case 2: - return MSM_SDC2_PHYS + MMCIFIFO; - case 3: - return MSM_SDC3_PHYS + MMCIFIFO; - case 4: - return MSM_SDC4_PHYS + MMCIFIFO; - } - BUG(); - return 0; -} - -static void -msmsdcc_dma_complete_func(struct msm_dmov_cmd *cmd, - unsigned int result, - struct msm_dmov_errdata *err) -{ - struct msmsdcc_dma_data *dma_data = - container_of(cmd, struct msmsdcc_dma_data, hdr); - struct msmsdcc_host *host = dma_data->host; - unsigned long flags; - struct mmc_request *mrq; - - spin_lock_irqsave(&host->lock, flags); - mrq = host->curr.mrq; - BUG_ON(!mrq); - - if (!(result & DMOV_RSLT_VALID)) { - pr_err("msmsdcc: Invalid DataMover result\n"); - goto out; - } - - if (result & DMOV_RSLT_DONE) { - host->curr.data_xfered = host->curr.xfer_size; - } else { - /* Error or flush */ - if (result & DMOV_RSLT_ERROR) - pr_err("%s: DMA error (0x%.8x)\n", - mmc_hostname(host->mmc), result); - if (result & DMOV_RSLT_FLUSH) - pr_err("%s: DMA channel flushed (0x%.8x)\n", - mmc_hostname(host->mmc), result); - if (err) - pr_err("Flush data: %.8x %.8x %.8x %.8x %.8x %.8x\n", - err->flush[0], err->flush[1], err->flush[2], - err->flush[3], err->flush[4], err->flush[5]); - if (!mrq->data->error) - mrq->data->error = -EIO; - } - host->dma.busy = 0; - dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents, - host->dma.dir); - - if (host->curr.user_pages) { - struct scatterlist *sg = host->dma.sg; - int i; - - for (i = 0; i < host->dma.num_ents; i++) - flush_dcache_page(sg_page(sg++)); - } - - host->dma.sg = NULL; - - if ((host->curr.got_dataend && host->curr.got_datablkend) - || mrq->data->error) { - - /* - * If we've already gotten our DATAEND / DATABLKEND - * for this request, then complete it through here. - */ - msmsdcc_stop_data(host); - - if (!mrq->data->error) - host->curr.data_xfered = host->curr.xfer_size; - if (!mrq->data->stop || mrq->cmd->error) { - writel(0, host->base + MMCICOMMAND); - host->curr.mrq = NULL; - host->curr.cmd = NULL; - mrq->data->bytes_xfered = host->curr.data_xfered; - - spin_unlock_irqrestore(&host->lock, flags); - mmc_request_done(host->mmc, mrq); - return; - } else - msmsdcc_start_command(host, mrq->data->stop, 0); - } - -out: - spin_unlock_irqrestore(&host->lock, flags); - return; -} - -static int validate_dma(struct msmsdcc_host *host, struct mmc_data *data) -{ - if (host->dma.channel == -1) - return -ENOENT; - - if ((data->blksz * data->blocks) < MCI_FIFOSIZE) - return -EINVAL; - if ((data->blksz * data->blocks) % MCI_FIFOSIZE) - return -EINVAL; - return 0; -} - -static int msmsdcc_config_dma(struct msmsdcc_host *host, struct mmc_data *data) -{ - struct msmsdcc_nc_dmadata *nc; - dmov_box *box; - uint32_t rows; - uint32_t crci; - unsigned int n; - int i, rc; - struct scatterlist *sg = data->sg; - - rc = validate_dma(host, data); - if (rc) - return rc; - - host->dma.sg = data->sg; - host->dma.num_ents = data->sg_len; - - nc = host->dma.nc; - - switch (host->pdev_id) { - case 1: - crci = MSMSDCC_CRCI_SDC1; - break; - case 2: - crci = MSMSDCC_CRCI_SDC2; - break; - case 3: - crci = MSMSDCC_CRCI_SDC3; - break; - case 4: - crci = MSMSDCC_CRCI_SDC4; - break; - default: - host->dma.sg = NULL; - host->dma.num_ents = 0; - return -ENOENT; - } - - if (data->flags & MMC_DATA_READ) - host->dma.dir = DMA_FROM_DEVICE; - else - host->dma.dir = DMA_TO_DEVICE; - - host->curr.user_pages = 0; - - n = dma_map_sg(mmc_dev(host->mmc), host->dma.sg, - host->dma.num_ents, host->dma.dir); - - if (n != host->dma.num_ents) { - pr_err("%s: Unable to map in all sg elements\n", - mmc_hostname(host->mmc)); - host->dma.sg = NULL; - host->dma.num_ents = 0; - return -ENOMEM; - } - - box = &nc->cmd[0]; - for (i = 0; i < host->dma.num_ents; i++) { - box->cmd = CMD_MODE_BOX; - - if (i == (host->dma.num_ents - 1)) - box->cmd |= CMD_LC; - rows = (sg_dma_len(sg) % MCI_FIFOSIZE) ? - (sg_dma_len(sg) / MCI_FIFOSIZE) + 1 : - (sg_dma_len(sg) / MCI_FIFOSIZE) ; - - if (data->flags & MMC_DATA_READ) { - box->src_row_addr = msmsdcc_fifo_addr(host); - box->dst_row_addr = sg_dma_address(sg); - - box->src_dst_len = (MCI_FIFOSIZE << 16) | - (MCI_FIFOSIZE); - box->row_offset = MCI_FIFOSIZE; - - box->num_rows = rows * ((1 << 16) + 1); - box->cmd |= CMD_SRC_CRCI(crci); - } else { - box->src_row_addr = sg_dma_address(sg); - box->dst_row_addr = msmsdcc_fifo_addr(host); - - box->src_dst_len = (MCI_FIFOSIZE << 16) | - (MCI_FIFOSIZE); - box->row_offset = (MCI_FIFOSIZE << 16); - - box->num_rows = rows * ((1 << 16) + 1); - box->cmd |= CMD_DST_CRCI(crci); - } - box++; - sg++; - } - - /* location of command block must be 64 bit aligned */ - BUG_ON(host->dma.cmd_busaddr & 0x07); - - nc->cmdptr = (host->dma.cmd_busaddr >> 3) | CMD_PTR_LP; - host->dma.hdr.cmdptr = DMOV_CMD_PTR_LIST | - DMOV_CMD_ADDR(host->dma.cmdptr_busaddr); - host->dma.hdr.complete_func = msmsdcc_dma_complete_func; - - return 0; -} - -static void -msmsdcc_start_data(struct msmsdcc_host *host, struct mmc_data *data) -{ - unsigned int datactrl, timeout; - unsigned long long clks; - void __iomem *base = host->base; - unsigned int pio_irqmask = 0; - - host->curr.data = data; - host->curr.xfer_size = data->blksz * data->blocks; - host->curr.xfer_remain = host->curr.xfer_size; - host->curr.data_xfered = 0; - host->curr.got_dataend = 0; - host->curr.got_datablkend = 0; - - memset(&host->pio, 0, sizeof(host->pio)); - - clks = (unsigned long long)data->timeout_ns * host->clk_rate; - do_div(clks, NSEC_PER_SEC); - timeout = data->timeout_clks + (unsigned int)clks; - writel(timeout, base + MMCIDATATIMER); - - writel(host->curr.xfer_size, base + MMCIDATALENGTH); - - datactrl = MCI_DPSM_ENABLE | (data->blksz << 4); - - if (!msmsdcc_config_dma(host, data)) - datactrl |= MCI_DPSM_DMAENABLE; - else { - host->pio.sg = data->sg; - host->pio.sg_len = data->sg_len; - host->pio.sg_off = 0; - - if (data->flags & MMC_DATA_READ) { - pio_irqmask = MCI_RXFIFOHALFFULLMASK; - if (host->curr.xfer_remain < MCI_FIFOSIZE) - pio_irqmask |= MCI_RXDATAAVLBLMASK; - } else - pio_irqmask = MCI_TXFIFOHALFEMPTYMASK; - } - - if (data->flags & MMC_DATA_READ) - datactrl |= MCI_DPSM_DIRECTION; - - writel(pio_irqmask, base + MMCIMASK1); - writel(datactrl, base + MMCIDATACTRL); - - if (datactrl & MCI_DPSM_DMAENABLE) { - host->dma.busy = 1; - msm_dmov_enqueue_cmd(host->dma.channel, &host->dma.hdr); - } -} - -static void -msmsdcc_start_command(struct msmsdcc_host *host, struct mmc_command *cmd, u32 c) -{ - void __iomem *base = host->base; - - if (readl(base + MMCICOMMAND) & MCI_CPSM_ENABLE) { - writel(0, base + MMCICOMMAND); - udelay(2 + ((5 * 1000000) / host->clk_rate)); - } - - c |= cmd->opcode | MCI_CPSM_ENABLE; - - if (cmd->flags & MMC_RSP_PRESENT) { - if (cmd->flags & MMC_RSP_136) - c |= MCI_CPSM_LONGRSP; - c |= MCI_CPSM_RESPONSE; - } - - if (cmd->opcode == 17 || cmd->opcode == 18 || - cmd->opcode == 24 || cmd->opcode == 25 || - cmd->opcode == 53) - c |= MCI_CSPM_DATCMD; - - if (cmd == cmd->mrq->stop) - c |= MCI_CSPM_MCIABORT; - - host->curr.cmd = cmd; - - host->stats.cmds++; - - writel(cmd->arg, base + MMCIARGUMENT); - writel(c, base + MMCICOMMAND); -} - -static void -msmsdcc_data_err(struct msmsdcc_host *host, struct mmc_data *data, - unsigned int status) -{ - if (status & MCI_DATACRCFAIL) { - pr_err("%s: Data CRC error\n", mmc_hostname(host->mmc)); - pr_err("%s: opcode 0x%.8x\n", __func__, - data->mrq->cmd->opcode); - pr_err("%s: blksz %d, blocks %d\n", __func__, - data->blksz, data->blocks); - data->error = -EILSEQ; - } else if (status & MCI_DATATIMEOUT) { - pr_err("%s: Data timeout\n", mmc_hostname(host->mmc)); - data->error = -ETIMEDOUT; - } else if (status & MCI_RXOVERRUN) { - pr_err("%s: RX overrun\n", mmc_hostname(host->mmc)); - data->error = -EIO; - } else if (status & MCI_TXUNDERRUN) { - pr_err("%s: TX underrun\n", mmc_hostname(host->mmc)); - data->error = -EIO; - } else { - pr_err("%s: Unknown error (0x%.8x)\n", - mmc_hostname(host->mmc), status); - data->error = -EIO; - } -} - - -static int -msmsdcc_pio_read(struct msmsdcc_host *host, char *buffer, unsigned int remain) -{ - void __iomem *base = host->base; - uint32_t *ptr = (uint32_t *) buffer; - int count = 0; - - while (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL) { - - *ptr = readl(base + MMCIFIFO + (count % MCI_FIFOSIZE)); - ptr++; - count += sizeof(uint32_t); - - remain -= sizeof(uint32_t); - if (remain == 0) - break; - } - return count; -} - -static int -msmsdcc_pio_write(struct msmsdcc_host *host, char *buffer, - unsigned int remain, u32 status) -{ - void __iomem *base = host->base; - char *ptr = buffer; - - do { - unsigned int count, maxcnt; - - maxcnt = status & MCI_TXFIFOEMPTY ? MCI_FIFOSIZE : - MCI_FIFOHALFSIZE; - count = min(remain, maxcnt); - - writesl(base + MMCIFIFO, ptr, count >> 2); - ptr += count; - remain -= count; - - if (remain == 0) - break; - - status = readl(base + MMCISTATUS); - } while (status & MCI_TXFIFOHALFEMPTY); - - return ptr - buffer; -} - -static int -msmsdcc_spin_on_status(struct msmsdcc_host *host, uint32_t mask, int maxspin) -{ - while (maxspin) { - if ((readl(host->base + MMCISTATUS) & mask)) - return 0; - udelay(1); - --maxspin; - } - return -ETIMEDOUT; -} - -static int -msmsdcc_pio_irq(int irq, void *dev_id) -{ - struct msmsdcc_host *host = dev_id; - void __iomem *base = host->base; - uint32_t status; - - status = readl(base + MMCISTATUS); - - do { - unsigned long flags; - unsigned int remain, len; - char *buffer; - - if (!(status & (MCI_TXFIFOHALFEMPTY | MCI_RXDATAAVLBL))) { - if (host->curr.xfer_remain == 0 || !msmsdcc_piopoll) - break; - - if (msmsdcc_spin_on_status(host, - (MCI_TXFIFOHALFEMPTY | - MCI_RXDATAAVLBL), - PIO_SPINMAX)) { - break; - } - } - - /* Map the current scatter buffer */ - local_irq_save(flags); - buffer = kmap_atomic(sg_page(host->pio.sg), - KM_BIO_SRC_IRQ) + host->pio.sg->offset; - buffer += host->pio.sg_off; - remain = host->pio.sg->length - host->pio.sg_off; - len = 0; - if (status & MCI_RXACTIVE) - len = msmsdcc_pio_read(host, buffer, remain); - if (status & MCI_TXACTIVE) - len = msmsdcc_pio_write(host, buffer, remain, status); - - /* Unmap the buffer */ - kunmap_atomic(buffer, KM_BIO_SRC_IRQ); - local_irq_restore(flags); - - host->pio.sg_off += len; - host->curr.xfer_remain -= len; - host->curr.data_xfered += len; - remain -= len; - - if (remain == 0) { - /* This sg page is full - do some housekeeping */ - if (status & MCI_RXACTIVE && host->curr.user_pages) - flush_dcache_page(sg_page(host->pio.sg)); - - if (!--host->pio.sg_len) { - memset(&host->pio, 0, sizeof(host->pio)); - break; - } - - /* Advance to next sg */ - host->pio.sg++; - host->pio.sg_off = 0; - } - - status = readl(base + MMCISTATUS); - } while (1); - - if (status & MCI_RXACTIVE && host->curr.xfer_remain < MCI_FIFOSIZE) - writel(MCI_RXDATAAVLBLMASK, base + MMCIMASK1); - - if (!host->curr.xfer_remain) - writel(0, base + MMCIMASK1); - - return IRQ_HANDLED; -} - -static void msmsdcc_do_cmdirq(struct msmsdcc_host *host, uint32_t status) -{ - struct mmc_command *cmd = host->curr.cmd; - void __iomem *base = host->base; - - host->curr.cmd = NULL; - cmd->resp[0] = readl(base + MMCIRESPONSE0); - cmd->resp[1] = readl(base + MMCIRESPONSE1); - cmd->resp[2] = readl(base + MMCIRESPONSE2); - cmd->resp[3] = readl(base + MMCIRESPONSE3); - - del_timer(&host->command_timer); - if (status & MCI_CMDTIMEOUT) { - cmd->error = -ETIMEDOUT; - } else if (status & MCI_CMDCRCFAIL && - cmd->flags & MMC_RSP_CRC) { - pr_err("%s: Command CRC error\n", mmc_hostname(host->mmc)); - cmd->error = -EILSEQ; - } - - if (!cmd->data || cmd->error) { - if (host->curr.data && host->dma.sg) - msm_dmov_stop_cmd(host->dma.channel, - &host->dma.hdr, 0); - else if (host->curr.data) { /* Non DMA */ - msmsdcc_stop_data(host); - msmsdcc_request_end(host, cmd->mrq); - } else /* host->data == NULL */ - msmsdcc_request_end(host, cmd->mrq); - } else if (!(cmd->data->flags & MMC_DATA_READ)) - msmsdcc_start_data(host, cmd->data); -} - -static void -msmsdcc_handle_irq_data(struct msmsdcc_host *host, u32 status, - void __iomem *base) -{ - struct mmc_data *data = host->curr.data; - - if (!data) - return; - - /* Check for data errors */ - if (status & (MCI_DATACRCFAIL | MCI_DATATIMEOUT | - MCI_TXUNDERRUN | MCI_RXOVERRUN)) { - msmsdcc_data_err(host, data, status); - host->curr.data_xfered = 0; - if (host->dma.sg) - msm_dmov_stop_cmd(host->dma.channel, - &host->dma.hdr, 0); - else { - msmsdcc_stop_data(host); - if (!data->stop) - msmsdcc_request_end(host, data->mrq); - else - msmsdcc_start_command(host, data->stop, 0); - } - } - - /* Check for data done */ - if (!host->curr.got_dataend && (status & MCI_DATAEND)) - host->curr.got_dataend = 1; - - if (!host->curr.got_datablkend && (status & MCI_DATABLOCKEND)) - host->curr.got_datablkend = 1; - - /* - * If DMA is still in progress, we complete via the completion handler - */ - if (host->curr.got_dataend && host->curr.got_datablkend && - !host->dma.busy) { - /* - * There appears to be an issue in the controller where - * if you request a small block transfer (< fifo size), - * you may get your DATAEND/DATABLKEND irq without the - * PIO data irq. - * - * Check to see if there is still data to be read, - * and simulate a PIO irq. - */ - if (readl(base + MMCISTATUS) & MCI_RXDATAAVLBL) - msmsdcc_pio_irq(1, host); - - msmsdcc_stop_data(host); - if (!data->error) - host->curr.data_xfered = host->curr.xfer_size; - - if (!data->stop) - msmsdcc_request_end(host, data->mrq); - else - msmsdcc_start_command(host, data->stop, 0); - } -} - -static irqreturn_t -msmsdcc_irq(int irq, void *dev_id) -{ - struct msmsdcc_host *host = dev_id; - void __iomem *base = host->base; - u32 status; - int ret = 0; - int cardint = 0; - - spin_lock(&host->lock); - - do { - status = readl(base + MMCISTATUS); - - status &= (readl(base + MMCIMASK0) | MCI_DATABLOCKENDMASK); - writel(status, base + MMCICLEAR); - - msmsdcc_handle_irq_data(host, status, base); - - if (status & (MCI_CMDSENT | MCI_CMDRESPEND | MCI_CMDCRCFAIL | - MCI_CMDTIMEOUT) && host->curr.cmd) { - msmsdcc_do_cmdirq(host, status); - } - - if (status & MCI_SDIOINTOPER) { - cardint = 1; - status &= ~MCI_SDIOINTOPER; - } - ret = 1; - } while (status); - - spin_unlock(&host->lock); - - /* - * We have to delay handling the card interrupt as it calls - * back into the driver. - */ - if (cardint) - mmc_signal_sdio_irq(host->mmc); - - return IRQ_RETVAL(ret); -} - -static void -msmsdcc_request(struct mmc_host *mmc, struct mmc_request *mrq) -{ - struct msmsdcc_host *host = mmc_priv(mmc); - unsigned long flags; - - WARN_ON(host->curr.mrq != NULL); - WARN_ON(host->pwr == 0); - - spin_lock_irqsave(&host->lock, flags); - - host->stats.reqs++; - - if (host->eject) { - if (mrq->data && !(mrq->data->flags & MMC_DATA_READ)) { - mrq->cmd->error = 0; - mrq->data->bytes_xfered = mrq->data->blksz * - mrq->data->blocks; - } else - mrq->cmd->error = -ENOMEDIUM; - - spin_unlock_irqrestore(&host->lock, flags); - mmc_request_done(mmc, mrq); - return; - } - - host->curr.mrq = mrq; - - if (mrq->data && mrq->data->flags & MMC_DATA_READ) - msmsdcc_start_data(host, mrq->data); - - msmsdcc_start_command(host, mrq->cmd, 0); - - if (host->cmdpoll && !msmsdcc_spin_on_status(host, - MCI_CMDRESPEND|MCI_CMDCRCFAIL|MCI_CMDTIMEOUT, - CMD_SPINMAX)) { - uint32_t status = readl(host->base + MMCISTATUS); - msmsdcc_do_cmdirq(host, status); - writel(MCI_CMDRESPEND | MCI_CMDCRCFAIL | MCI_CMDTIMEOUT, - host->base + MMCICLEAR); - host->stats.cmdpoll_hits++; - } else { - host->stats.cmdpoll_misses++; - mod_timer(&host->command_timer, jiffies + HZ); - } - spin_unlock_irqrestore(&host->lock, flags); -} - -static void -msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) -{ - struct msmsdcc_host *host = mmc_priv(mmc); - u32 clk = 0, pwr = 0; - int rc; - - if (ios->clock) { - - if (!host->clks_on) { - clk_enable(host->pclk); - clk_enable(host->clk); - host->clks_on = 1; - } - if (ios->clock != host->clk_rate) { - rc = clk_set_rate(host->clk, ios->clock); - if (rc < 0) - pr_err("%s: Error setting clock rate (%d)\n", - mmc_hostname(host->mmc), rc); - else - host->clk_rate = ios->clock; - } - clk |= MCI_CLK_ENABLE; - } - - if (ios->bus_width == MMC_BUS_WIDTH_4) - clk |= (2 << 10); /* Set WIDEBUS */ - - if (ios->clock > 400000 && msmsdcc_pwrsave) - clk |= (1 << 9); /* PWRSAVE */ - - clk |= (1 << 12); /* FLOW_ENA */ - clk |= (1 << 15); /* feedback clock */ - - if (host->plat->translate_vdd) - pwr |= host->plat->translate_vdd(mmc_dev(mmc), ios->vdd); - - switch (ios->power_mode) { - case MMC_POWER_OFF: - htc_pwrsink_set(PWRSINK_SDCARD, 0); - break; - case MMC_POWER_UP: - pwr |= MCI_PWR_UP; - break; - case MMC_POWER_ON: - htc_pwrsink_set(PWRSINK_SDCARD, 100); - pwr |= MCI_PWR_ON; - break; - } - - if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) - pwr |= MCI_OD; - - writel(clk, host->base + MMCICLOCK); - - if (host->pwr != pwr) { - host->pwr = pwr; - writel(pwr, host->base + MMCIPOWER); - } - - if (!(clk & MCI_CLK_ENABLE) && host->clks_on) { - clk_disable(host->clk); - clk_disable(host->pclk); - host->clks_on = 0; - } -} - -static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable) -{ - struct msmsdcc_host *host = mmc_priv(mmc); - unsigned long flags; - u32 status; - - spin_lock_irqsave(&host->lock, flags); - if (msmsdcc_sdioirq == 1) { - status = readl(host->base + MMCIMASK0); - if (enable) - status |= MCI_SDIOINTOPERMASK; - else - status &= ~MCI_SDIOINTOPERMASK; - host->saved_irq0mask = status; - writel(status, host->base + MMCIMASK0); - } - spin_unlock_irqrestore(&host->lock, flags); -} - -static const struct mmc_host_ops msmsdcc_ops = { - .request = msmsdcc_request, - .set_ios = msmsdcc_set_ios, - .enable_sdio_irq = msmsdcc_enable_sdio_irq, -}; - -static void -msmsdcc_check_status(unsigned long data) -{ - struct msmsdcc_host *host = (struct msmsdcc_host *)data; - unsigned int status; - - if (!host->plat->status) { - mmc_detect_change(host->mmc, 0); - goto out; - } - - status = host->plat->status(mmc_dev(host->mmc)); - host->eject = !status; - if (status ^ host->oldstat) { - pr_info("%s: Slot status change detected (%d -> %d)\n", - mmc_hostname(host->mmc), host->oldstat, status); - if (status) - mmc_detect_change(host->mmc, (5 * HZ) / 2); - else - mmc_detect_change(host->mmc, 0); - } - - host->oldstat = status; - -out: - if (host->timer.function) - mod_timer(&host->timer, jiffies + HZ); -} - -static irqreturn_t -msmsdcc_platform_status_irq(int irq, void *dev_id) -{ - struct msmsdcc_host *host = dev_id; - - printk(KERN_DEBUG "%s: %d\n", __func__, irq); - msmsdcc_check_status((unsigned long) host); - return IRQ_HANDLED; -} - -static void -msmsdcc_status_notify_cb(int card_present, void *dev_id) -{ - struct msmsdcc_host *host = dev_id; - - printk(KERN_DEBUG "%s: card_present %d\n", mmc_hostname(host->mmc), - card_present); - msmsdcc_check_status((unsigned long) host); -} - -/* - * called when a command expires. - * Dump some debugging, and then error - * out the transaction. - */ -static void -msmsdcc_command_expired(unsigned long _data) -{ - struct msmsdcc_host *host = (struct msmsdcc_host *) _data; - struct mmc_request *mrq; - unsigned long flags; - - spin_lock_irqsave(&host->lock, flags); - mrq = host->curr.mrq; - - if (!mrq) { - pr_info("%s: Command expiry misfire\n", - mmc_hostname(host->mmc)); - spin_unlock_irqrestore(&host->lock, flags); - return; - } - - pr_err("%s: Command timeout (%p %p %p %p)\n", - mmc_hostname(host->mmc), mrq, mrq->cmd, - mrq->data, host->dma.sg); - - mrq->cmd->error = -ETIMEDOUT; - msmsdcc_stop_data(host); - - writel(0, host->base + MMCICOMMAND); - - host->curr.mrq = NULL; - host->curr.cmd = NULL; - - spin_unlock_irqrestore(&host->lock, flags); - mmc_request_done(host->mmc, mrq); -} - -static int -msmsdcc_init_dma(struct msmsdcc_host *host) -{ - memset(&host->dma, 0, sizeof(struct msmsdcc_dma_data)); - host->dma.host = host; - host->dma.channel = -1; - - if (!host->dmares) - return -ENODEV; - - host->dma.nc = dma_alloc_coherent(NULL, - sizeof(struct msmsdcc_nc_dmadata), - &host->dma.nc_busaddr, - GFP_KERNEL); - if (host->dma.nc == NULL) { - pr_err("Unable to allocate DMA buffer\n"); - return -ENOMEM; - } - memset(host->dma.nc, 0x00, sizeof(struct msmsdcc_nc_dmadata)); - host->dma.cmd_busaddr = host->dma.nc_busaddr; - host->dma.cmdptr_busaddr = host->dma.nc_busaddr + - offsetof(struct msmsdcc_nc_dmadata, cmdptr); - host->dma.channel = host->dmares->start; - - return 0; -} - -#ifdef CONFIG_MMC_MSM7X00A_RESUME_IN_WQ -static void -do_resume_work(struct work_struct *work) -{ - struct msmsdcc_host *host = - container_of(work, struct msmsdcc_host, resume_task); - struct mmc_host *mmc = host->mmc; - - if (mmc) { - mmc_resume_host(mmc); - if (host->stat_irq) - enable_irq(host->stat_irq); - } -} -#endif - -static int -msmsdcc_probe(struct platform_device *pdev) -{ - struct mmc_platform_data *plat = pdev->dev.platform_data; - struct msmsdcc_host *host; - struct mmc_host *mmc; - struct resource *cmd_irqres = NULL; - struct resource *pio_irqres = NULL; - struct resource *stat_irqres = NULL; - struct resource *memres = NULL; - struct resource *dmares = NULL; - int ret; - - /* must have platform data */ - if (!plat) { - pr_err("%s: Platform data not available\n", __func__); - ret = -EINVAL; - goto out; - } - - if (pdev->id < 1 || pdev->id > 4) - return -EINVAL; - - if (pdev->resource == NULL || pdev->num_resources < 2) { - pr_err("%s: Invalid resource\n", __func__); - return -ENXIO; - } - - memres = platform_get_resource(pdev, IORESOURCE_MEM, 0); - dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); - cmd_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - "cmd_irq"); - pio_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - "pio_irq"); - stat_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, - "status_irq"); - - if (!cmd_irqres || !pio_irqres || !memres) { - pr_err("%s: Invalid resource\n", __func__); - return -ENXIO; - } - - /* - * Setup our host structure - */ - - mmc = mmc_alloc_host(sizeof(struct msmsdcc_host), &pdev->dev); - if (!mmc) { - ret = -ENOMEM; - goto out; - } - - host = mmc_priv(mmc); - host->pdev_id = pdev->id; - host->plat = plat; - host->mmc = mmc; - - host->cmdpoll = 1; - - host->base = ioremap(memres->start, PAGE_SIZE); - if (!host->base) { - ret = -ENOMEM; - goto out; - } - - host->cmd_irqres = cmd_irqres; - host->pio_irqres = pio_irqres; - host->memres = memres; - host->dmares = dmares; - spin_lock_init(&host->lock); - - /* - * Setup DMA - */ - msmsdcc_init_dma(host); - - /* - * Setup main peripheral bus clock - */ - host->pclk = clk_get(&pdev->dev, "sdc_pclk"); - if (IS_ERR(host->pclk)) { - ret = PTR_ERR(host->pclk); - goto host_free; - } - - ret = clk_enable(host->pclk); - if (ret) - goto pclk_put; - - host->pclk_rate = clk_get_rate(host->pclk); - - /* - * Setup SDC MMC clock - */ - host->clk = clk_get(&pdev->dev, "sdc_clk"); - if (IS_ERR(host->clk)) { - ret = PTR_ERR(host->clk); - goto pclk_disable; - } - - ret = clk_enable(host->clk); - if (ret) - goto clk_put; - - ret = clk_set_rate(host->clk, msmsdcc_fmin); - if (ret) { - pr_err("%s: Clock rate set failed (%d)\n", __func__, ret); - goto clk_disable; - } - - host->clk_rate = clk_get_rate(host->clk); - - host->clks_on = 1; - - /* - * Setup MMC host structure - */ - mmc->ops = &msmsdcc_ops; - mmc->f_min = msmsdcc_fmin; - mmc->f_max = msmsdcc_fmax; - mmc->ocr_avail = plat->ocr_mask; - - if (msmsdcc_4bit) - mmc->caps |= MMC_CAP_4_BIT_DATA; - if (msmsdcc_sdioirq) - mmc->caps |= MMC_CAP_SDIO_IRQ; - mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; - - mmc->max_phys_segs = NR_SG; - mmc->max_hw_segs = NR_SG; - mmc->max_blk_size = 4096; /* MCI_DATA_CTL BLOCKSIZE up to 4096 */ - mmc->max_blk_count = 65536; - - mmc->max_req_size = 33554432; /* MCI_DATA_LENGTH is 25 bits */ - mmc->max_seg_size = mmc->max_req_size; - - writel(0, host->base + MMCIMASK0); - writel(0x5e007ff, host->base + MMCICLEAR); /* Add: 1 << 25 */ - - writel(MCI_IRQENABLE, host->base + MMCIMASK0); - host->saved_irq0mask = MCI_IRQENABLE; - - /* - * Setup card detect change - */ - - memset(&host->timer, 0, sizeof(host->timer)); - - if (stat_irqres && !(stat_irqres->flags & IORESOURCE_DISABLED)) { - unsigned long irqflags = IRQF_SHARED | - (stat_irqres->flags & IRQF_TRIGGER_MASK); - - host->stat_irq = stat_irqres->start; - ret = request_irq(host->stat_irq, - msmsdcc_platform_status_irq, - irqflags, - DRIVER_NAME " (slot)", - host); - if (ret) { - pr_err("%s: Unable to get slot IRQ %d (%d)\n", - mmc_hostname(mmc), host->stat_irq, ret); - goto clk_disable; - } - } else if (plat->register_status_notify) { - plat->register_status_notify(msmsdcc_status_notify_cb, host); - } else if (!plat->status) - pr_err("%s: No card detect facilities available\n", - mmc_hostname(mmc)); - else { - init_timer(&host->timer); - host->timer.data = (unsigned long)host; - host->timer.function = msmsdcc_check_status; - host->timer.expires = jiffies + HZ; - add_timer(&host->timer); - } - - if (plat->status) { - host->oldstat = host->plat->status(mmc_dev(host->mmc)); - host->eject = !host->oldstat; - } - - /* - * Setup a command timer. We currently need this due to - * some 'strange' timeout / error handling situations. - */ - init_timer(&host->command_timer); - host->command_timer.data = (unsigned long) host; - host->command_timer.function = msmsdcc_command_expired; - - ret = request_irq(cmd_irqres->start, msmsdcc_irq, IRQF_SHARED, - DRIVER_NAME " (cmd)", host); - if (ret) - goto stat_irq_free; - - ret = request_irq(pio_irqres->start, msmsdcc_pio_irq, IRQF_SHARED, - DRIVER_NAME " (pio)", host); - if (ret) - goto cmd_irq_free; - - mmc_set_drvdata(pdev, mmc); - mmc_add_host(mmc); - - pr_info("%s: Qualcomm MSM SDCC at 0x%016llx irq %d,%d dma %d\n", - mmc_hostname(mmc), (unsigned long long)memres->start, - (unsigned int) cmd_irqres->start, - (unsigned int) host->stat_irq, host->dma.channel); - pr_info("%s: 4 bit data mode %s\n", mmc_hostname(mmc), - (mmc->caps & MMC_CAP_4_BIT_DATA ? "enabled" : "disabled")); - pr_info("%s: MMC clock %u -> %u Hz, PCLK %u Hz\n", - mmc_hostname(mmc), msmsdcc_fmin, msmsdcc_fmax, host->pclk_rate); - pr_info("%s: Slot eject status = %d\n", mmc_hostname(mmc), host->eject); - pr_info("%s: Power save feature enable = %d\n", - mmc_hostname(mmc), msmsdcc_pwrsave); - - if (host->dma.channel != -1) { - pr_info("%s: DM non-cached buffer at %p, dma_addr 0x%.8x\n", - mmc_hostname(mmc), host->dma.nc, host->dma.nc_busaddr); - pr_info("%s: DM cmd busaddr 0x%.8x, cmdptr busaddr 0x%.8x\n", - mmc_hostname(mmc), host->dma.cmd_busaddr, - host->dma.cmdptr_busaddr); - } else - pr_info("%s: PIO transfer enabled\n", mmc_hostname(mmc)); - if (host->timer.function) - pr_info("%s: Polling status mode enabled\n", mmc_hostname(mmc)); - - return 0; - cmd_irq_free: - free_irq(cmd_irqres->start, host); - stat_irq_free: - if (host->stat_irq) - free_irq(host->stat_irq, host); - clk_disable: - clk_disable(host->clk); - clk_put: - clk_put(host->clk); - pclk_disable: - clk_disable(host->pclk); - pclk_put: - clk_put(host->pclk); - host_free: - mmc_free_host(mmc); - out: - return ret; -} - -static int -msmsdcc_suspend(struct platform_device *dev, pm_message_t state) -{ - struct mmc_host *mmc = mmc_get_drvdata(dev); - int rc = 0; - - if (mmc) { - struct msmsdcc_host *host = mmc_priv(mmc); - - if (host->stat_irq) - disable_irq(host->stat_irq); - - if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) - rc = mmc_suspend_host(mmc, state); - if (!rc) { - writel(0, host->base + MMCIMASK0); - - if (host->clks_on) { - clk_disable(host->clk); - clk_disable(host->pclk); - host->clks_on = 0; - } - } - } - return rc; -} - -static int -msmsdcc_resume(struct platform_device *dev) -{ - struct mmc_host *mmc = mmc_get_drvdata(dev); - unsigned long flags; - - if (mmc) { - struct msmsdcc_host *host = mmc_priv(mmc); - - spin_lock_irqsave(&host->lock, flags); - - if (!host->clks_on) { - clk_enable(host->pclk); - clk_enable(host->clk); - host->clks_on = 1; - } - - writel(host->saved_irq0mask, host->base + MMCIMASK0); - - spin_unlock_irqrestore(&host->lock, flags); - - if (mmc->card && mmc->card->type != MMC_TYPE_SDIO) - mmc_resume_host(mmc); - if (host->stat_irq) - enable_irq(host->stat_irq); - else if (host->stat_irq) - enable_irq(host->stat_irq); - } - return 0; -} - -static struct platform_driver msmsdcc_driver = { - .probe = msmsdcc_probe, - .suspend = msmsdcc_suspend, - .resume = msmsdcc_resume, - .driver = { - .name = "msm_sdcc", - }, -}; - -static int __init msmsdcc_init(void) -{ - return platform_driver_register(&msmsdcc_driver); -} - -static void __exit msmsdcc_exit(void) -{ - platform_driver_unregister(&msmsdcc_driver); -} - -module_init(msmsdcc_init); -module_exit(msmsdcc_exit); - -MODULE_DESCRIPTION("Qualcomm MSM 7X00A Multimedia Card Interface driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/mmc/host/msm_sdcc.h b/trunk/drivers/mmc/host/msm_sdcc.h deleted file mode 100644 index 8c8448469811..000000000000 --- a/trunk/drivers/mmc/host/msm_sdcc.h +++ /dev/null @@ -1,238 +0,0 @@ -/* - * linux/drivers/mmc/host/msmsdcc.h - QCT MSM7K SDC Controller - * - * Copyright (C) 2008 Google, All Rights Reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * - Based on mmci.h - */ - -#ifndef _MSM_SDCC_H -#define _MSM_SDCC_H - -#define MSMSDCC_CRCI_SDC1 6 -#define MSMSDCC_CRCI_SDC2 7 -#define MSMSDCC_CRCI_SDC3 12 -#define MSMSDCC_CRCI_SDC4 13 - -#define MMCIPOWER 0x000 -#define MCI_PWR_OFF 0x00 -#define MCI_PWR_UP 0x02 -#define MCI_PWR_ON 0x03 -#define MCI_OD (1 << 6) - -#define MMCICLOCK 0x004 -#define MCI_CLK_ENABLE (1 << 8) -#define MCI_CLK_PWRSAVE (1 << 9) -#define MCI_CLK_WIDEBUS (1 << 10) -#define MCI_CLK_FLOWENA (1 << 12) -#define MCI_CLK_INVERTOUT (1 << 13) -#define MCI_CLK_SELECTIN (1 << 14) - -#define MMCIARGUMENT 0x008 -#define MMCICOMMAND 0x00c -#define MCI_CPSM_RESPONSE (1 << 6) -#define MCI_CPSM_LONGRSP (1 << 7) -#define MCI_CPSM_INTERRUPT (1 << 8) -#define MCI_CPSM_PENDING (1 << 9) -#define MCI_CPSM_ENABLE (1 << 10) -#define MCI_CPSM_PROGENA (1 << 11) -#define MCI_CSPM_DATCMD (1 << 12) -#define MCI_CSPM_MCIABORT (1 << 13) -#define MCI_CSPM_CCSENABLE (1 << 14) -#define MCI_CSPM_CCSDISABLE (1 << 15) - - -#define MMCIRESPCMD 0x010 -#define MMCIRESPONSE0 0x014 -#define MMCIRESPONSE1 0x018 -#define MMCIRESPONSE2 0x01c -#define MMCIRESPONSE3 0x020 -#define MMCIDATATIMER 0x024 -#define MMCIDATALENGTH 0x028 - -#define MMCIDATACTRL 0x02c -#define MCI_DPSM_ENABLE (1 << 0) -#define MCI_DPSM_DIRECTION (1 << 1) -#define MCI_DPSM_MODE (1 << 2) -#define MCI_DPSM_DMAENABLE (1 << 3) - -#define MMCIDATACNT 0x030 -#define MMCISTATUS 0x034 -#define MCI_CMDCRCFAIL (1 << 0) -#define MCI_DATACRCFAIL (1 << 1) -#define MCI_CMDTIMEOUT (1 << 2) -#define MCI_DATATIMEOUT (1 << 3) -#define MCI_TXUNDERRUN (1 << 4) -#define MCI_RXOVERRUN (1 << 5) -#define MCI_CMDRESPEND (1 << 6) -#define MCI_CMDSENT (1 << 7) -#define MCI_DATAEND (1 << 8) -#define MCI_DATABLOCKEND (1 << 10) -#define MCI_CMDACTIVE (1 << 11) -#define MCI_TXACTIVE (1 << 12) -#define MCI_RXACTIVE (1 << 13) -#define MCI_TXFIFOHALFEMPTY (1 << 14) -#define MCI_RXFIFOHALFFULL (1 << 15) -#define MCI_TXFIFOFULL (1 << 16) -#define MCI_RXFIFOFULL (1 << 17) -#define MCI_TXFIFOEMPTY (1 << 18) -#define MCI_RXFIFOEMPTY (1 << 19) -#define MCI_TXDATAAVLBL (1 << 20) -#define MCI_RXDATAAVLBL (1 << 21) -#define MCI_SDIOINTR (1 << 22) -#define MCI_PROGDONE (1 << 23) -#define MCI_ATACMDCOMPL (1 << 24) -#define MCI_SDIOINTOPER (1 << 25) -#define MCI_CCSTIMEOUT (1 << 26) - -#define MMCICLEAR 0x038 -#define MCI_CMDCRCFAILCLR (1 << 0) -#define MCI_DATACRCFAILCLR (1 << 1) -#define MCI_CMDTIMEOUTCLR (1 << 2) -#define MCI_DATATIMEOUTCLR (1 << 3) -#define MCI_TXUNDERRUNCLR (1 << 4) -#define MCI_RXOVERRUNCLR (1 << 5) -#define MCI_CMDRESPENDCLR (1 << 6) -#define MCI_CMDSENTCLR (1 << 7) -#define MCI_DATAENDCLR (1 << 8) -#define MCI_DATABLOCKENDCLR (1 << 10) - -#define MMCIMASK0 0x03c -#define MCI_CMDCRCFAILMASK (1 << 0) -#define MCI_DATACRCFAILMASK (1 << 1) -#define MCI_CMDTIMEOUTMASK (1 << 2) -#define MCI_DATATIMEOUTMASK (1 << 3) -#define MCI_TXUNDERRUNMASK (1 << 4) -#define MCI_RXOVERRUNMASK (1 << 5) -#define MCI_CMDRESPENDMASK (1 << 6) -#define MCI_CMDSENTMASK (1 << 7) -#define MCI_DATAENDMASK (1 << 8) -#define MCI_DATABLOCKENDMASK (1 << 10) -#define MCI_CMDACTIVEMASK (1 << 11) -#define MCI_TXACTIVEMASK (1 << 12) -#define MCI_RXACTIVEMASK (1 << 13) -#define MCI_TXFIFOHALFEMPTYMASK (1 << 14) -#define MCI_RXFIFOHALFFULLMASK (1 << 15) -#define MCI_TXFIFOFULLMASK (1 << 16) -#define MCI_RXFIFOFULLMASK (1 << 17) -#define MCI_TXFIFOEMPTYMASK (1 << 18) -#define MCI_RXFIFOEMPTYMASK (1 << 19) -#define MCI_TXDATAAVLBLMASK (1 << 20) -#define MCI_RXDATAAVLBLMASK (1 << 21) -#define MCI_SDIOINTMASK (1 << 22) -#define MCI_PROGDONEMASK (1 << 23) -#define MCI_ATACMDCOMPLMASK (1 << 24) -#define MCI_SDIOINTOPERMASK (1 << 25) -#define MCI_CCSTIMEOUTMASK (1 << 26) - -#define MMCIMASK1 0x040 -#define MMCIFIFOCNT 0x044 -#define MCICCSTIMER 0x058 - -#define MMCIFIFO 0x080 /* to 0x0bc */ - -#define MCI_IRQENABLE \ - (MCI_CMDCRCFAILMASK|MCI_DATACRCFAILMASK|MCI_CMDTIMEOUTMASK| \ - MCI_DATATIMEOUTMASK|MCI_TXUNDERRUNMASK|MCI_RXOVERRUNMASK| \ - MCI_CMDRESPENDMASK|MCI_CMDSENTMASK|MCI_DATAENDMASK) - -/* - * The size of the FIFO in bytes. - */ -#define MCI_FIFOSIZE (16*4) - -#define MCI_FIFOHALFSIZE (MCI_FIFOSIZE / 2) - -#define NR_SG 32 - -struct clk; - -struct msmsdcc_nc_dmadata { - dmov_box cmd[NR_SG]; - uint32_t cmdptr; -}; - -struct msmsdcc_dma_data { - struct msmsdcc_nc_dmadata *nc; - dma_addr_t nc_busaddr; - dma_addr_t cmd_busaddr; - dma_addr_t cmdptr_busaddr; - - struct msm_dmov_cmd hdr; - enum dma_data_direction dir; - - struct scatterlist *sg; - int num_ents; - - int channel; - struct msmsdcc_host *host; - int busy; /* Set if DM is busy */ -}; - -struct msmsdcc_pio_data { - struct scatterlist *sg; - unsigned int sg_len; - unsigned int sg_off; -}; - -struct msmsdcc_curr_req { - struct mmc_request *mrq; - struct mmc_command *cmd; - struct mmc_data *data; - unsigned int xfer_size; /* Total data size */ - unsigned int xfer_remain; /* Bytes remaining to send */ - unsigned int data_xfered; /* Bytes acked by BLKEND irq */ - int got_dataend; - int got_datablkend; - int user_pages; -}; - -struct msmsdcc_stats { - unsigned int reqs; - unsigned int cmds; - unsigned int cmdpoll_hits; - unsigned int cmdpoll_misses; -}; - -struct msmsdcc_host { - struct resource *cmd_irqres; - struct resource *pio_irqres; - struct resource *memres; - struct resource *dmares; - void __iomem *base; - int pdev_id; - unsigned int stat_irq; - - struct msmsdcc_curr_req curr; - - struct mmc_host *mmc; - struct clk *clk; /* main MMC bus clock */ - struct clk *pclk; /* SDCC peripheral bus clock */ - unsigned int clks_on; /* set if clocks are enabled */ - struct timer_list command_timer; - - unsigned int eject; /* eject state */ - - spinlock_t lock; - - unsigned int clk_rate; /* Current clock rate */ - unsigned int pclk_rate; - - u32 pwr; - u32 saved_irq0mask; /* MMCIMASK0 reg value */ - struct mmc_platform_data *plat; - - struct timer_list timer; - unsigned int oldstat; - - struct msmsdcc_dma_data dma; - struct msmsdcc_pio_data pio; - int cmdpoll; - struct msmsdcc_stats stats; -}; - -#endif diff --git a/trunk/drivers/mmc/host/omap_hsmmc.c b/trunk/drivers/mmc/host/omap_hsmmc.c index 4487cc097911..1cf9cfb3b64f 100644 --- a/trunk/drivers/mmc/host/omap_hsmmc.c +++ b/trunk/drivers/mmc/host/omap_hsmmc.c @@ -17,8 +17,6 @@ #include #include -#include -#include #include #include #include @@ -27,7 +25,6 @@ #include #include #include -#include #include #include #include @@ -38,7 +35,6 @@ /* OMAP HSMMC Host Controller Registers */ #define OMAP_HSMMC_SYSCONFIG 0x0010 -#define OMAP_HSMMC_SYSSTATUS 0x0014 #define OMAP_HSMMC_CON 0x002C #define OMAP_HSMMC_BLK 0x0104 #define OMAP_HSMMC_ARG 0x0108 @@ -74,8 +70,6 @@ #define DTO_MASK 0x000F0000 #define DTO_SHIFT 16 #define INT_EN_MASK 0x307F0033 -#define BWR_ENABLE (1 << 4) -#define BRR_ENABLE (1 << 5) #define INIT_STREAM (1 << 1) #define DP_SELECT (1 << 21) #define DDIR (1 << 4) @@ -98,8 +92,6 @@ #define DUAL_VOLT_OCR_BIT 7 #define SRC (1 << 25) #define SRD (1 << 26) -#define SOFTRESET (1 << 1) -#define RESETDONE (1 << 0) /* * FIXME: Most likely all the data using these _DEVID defines should come @@ -109,18 +101,11 @@ #define OMAP_MMC1_DEVID 0 #define OMAP_MMC2_DEVID 1 #define OMAP_MMC3_DEVID 2 -#define OMAP_MMC4_DEVID 3 -#define OMAP_MMC5_DEVID 4 #define MMC_TIMEOUT_MS 20 #define OMAP_MMC_MASTER_CLOCK 96000000 #define DRIVER_NAME "mmci-omap-hs" -/* Timeouts for entering power saving states on inactivity, msec */ -#define OMAP_MMC_DISABLED_TIMEOUT 100 -#define OMAP_MMC_SLEEP_TIMEOUT 1000 -#define OMAP_MMC_OFF_TIMEOUT 8000 - /* * One controller can have multiple slots, like on some omap boards using * omap.c controller driver. Luckily this is not currently done on any known @@ -137,7 +122,7 @@ #define OMAP_HSMMC_WRITE(base, reg, val) \ __raw_writel((val), (base) + OMAP_HSMMC_##reg) -struct omap_hsmmc_host { +struct mmc_omap_host { struct device *dev; struct mmc_host *mmc; struct mmc_request *mrq; @@ -150,35 +135,27 @@ struct omap_hsmmc_host { struct work_struct mmc_carddetect_work; void __iomem *base; resource_size_t mapbase; - spinlock_t irq_lock; /* Prevent races with irq handler */ - unsigned long flags; unsigned int id; unsigned int dma_len; unsigned int dma_sg_idx; unsigned char bus_mode; - unsigned char power_mode; u32 *buffer; u32 bytesleft; int suspended; int irq; + int carddetect; int use_dma, dma_ch; int dma_line_tx, dma_line_rx; int slot_id; - int got_dbclk; + int dbclk_enabled; int response_busy; - int context_loss; - int dpm_state; - int vdd; - int protect_card; - int reqs_blocked; - struct omap_mmc_platform_data *pdata; }; /* * Stop clock to the card */ -static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) +static void omap_mmc_stop_clock(struct mmc_omap_host *host) { OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN); @@ -186,178 +163,15 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host) dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n"); } -#ifdef CONFIG_PM - -/* - * Restore the MMC host context, if it was lost as result of a - * power state change. - */ -static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) -{ - struct mmc_ios *ios = &host->mmc->ios; - struct omap_mmc_platform_data *pdata = host->pdata; - int context_loss = 0; - u32 hctl, capa, con; - u16 dsor = 0; - unsigned long timeout; - - if (pdata->get_context_loss_count) { - context_loss = pdata->get_context_loss_count(host->dev); - if (context_loss < 0) - return 1; - } - - dev_dbg(mmc_dev(host->mmc), "context was %slost\n", - context_loss == host->context_loss ? "not " : ""); - if (host->context_loss == context_loss) - return 1; - - /* Wait for hardware reset */ - timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); - while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE - && time_before(jiffies, timeout)) - ; - - /* Do software reset */ - OMAP_HSMMC_WRITE(host->base, SYSCONFIG, SOFTRESET); - timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); - while ((OMAP_HSMMC_READ(host->base, SYSSTATUS) & RESETDONE) != RESETDONE - && time_before(jiffies, timeout)) - ; - - OMAP_HSMMC_WRITE(host->base, SYSCONFIG, - OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE); - - if (host->id == OMAP_MMC1_DEVID) { - if (host->power_mode != MMC_POWER_OFF && - (1 << ios->vdd) <= MMC_VDD_23_24) - hctl = SDVS18; - else - hctl = SDVS30; - capa = VS30 | VS18; - } else { - hctl = SDVS18; - capa = VS18; - } - - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) | hctl); - - OMAP_HSMMC_WRITE(host->base, CAPA, - OMAP_HSMMC_READ(host->base, CAPA) | capa); - - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) | SDBP); - - timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); - while ((OMAP_HSMMC_READ(host->base, HCTL) & SDBP) != SDBP - && time_before(jiffies, timeout)) - ; - - OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); - OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); - OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); - - /* Do not initialize card-specific things if the power is off */ - if (host->power_mode == MMC_POWER_OFF) - goto out; - - con = OMAP_HSMMC_READ(host->base, CON); - switch (ios->bus_width) { - case MMC_BUS_WIDTH_8: - OMAP_HSMMC_WRITE(host->base, CON, con | DW8); - break; - case MMC_BUS_WIDTH_4: - OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) | FOUR_BIT); - break; - case MMC_BUS_WIDTH_1: - OMAP_HSMMC_WRITE(host->base, CON, con & ~DW8); - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) & ~FOUR_BIT); - break; - } - - if (ios->clock) { - dsor = OMAP_MMC_MASTER_CLOCK / ios->clock; - if (dsor < 1) - dsor = 1; - - if (OMAP_MMC_MASTER_CLOCK / dsor > ios->clock) - dsor++; - - if (dsor > 250) - dsor = 250; - } - - OMAP_HSMMC_WRITE(host->base, SYSCTL, - OMAP_HSMMC_READ(host->base, SYSCTL) & ~CEN); - OMAP_HSMMC_WRITE(host->base, SYSCTL, (dsor << 6) | (DTO << 16)); - OMAP_HSMMC_WRITE(host->base, SYSCTL, - OMAP_HSMMC_READ(host->base, SYSCTL) | ICE); - - timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); - while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS - && time_before(jiffies, timeout)) - ; - - OMAP_HSMMC_WRITE(host->base, SYSCTL, - OMAP_HSMMC_READ(host->base, SYSCTL) | CEN); - - con = OMAP_HSMMC_READ(host->base, CON); - if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) - OMAP_HSMMC_WRITE(host->base, CON, con | OD); - else - OMAP_HSMMC_WRITE(host->base, CON, con & ~OD); -out: - host->context_loss = context_loss; - - dev_dbg(mmc_dev(host->mmc), "context is restored\n"); - return 0; -} - -/* - * Save the MMC host context (store the number of power state changes so far). - */ -static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) -{ - struct omap_mmc_platform_data *pdata = host->pdata; - int context_loss; - - if (pdata->get_context_loss_count) { - context_loss = pdata->get_context_loss_count(host->dev); - if (context_loss < 0) - return; - host->context_loss = context_loss; - } -} - -#else - -static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host) -{ - return 0; -} - -static void omap_hsmmc_context_save(struct omap_hsmmc_host *host) -{ -} - -#endif - /* * Send init stream sequence to card * before sending IDLE command */ -static void send_init_stream(struct omap_hsmmc_host *host) +static void send_init_stream(struct mmc_omap_host *host) { int reg = 0; unsigned long timeout; - if (host->protect_card) - return; - disable_irq(host->irq); OMAP_HSMMC_WRITE(host->base, CON, OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM); @@ -369,53 +183,51 @@ static void send_init_stream(struct omap_hsmmc_host *host) OMAP_HSMMC_WRITE(host->base, CON, OMAP_HSMMC_READ(host->base, CON) & ~INIT_STREAM); - - OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); - OMAP_HSMMC_READ(host->base, STAT); - enable_irq(host->irq); } static inline -int omap_hsmmc_cover_is_closed(struct omap_hsmmc_host *host) +int mmc_omap_cover_is_closed(struct mmc_omap_host *host) { int r = 1; - if (mmc_slot(host).get_cover_state) - r = mmc_slot(host).get_cover_state(host->dev, host->slot_id); + if (host->pdata->slots[host->slot_id].get_cover_state) + r = host->pdata->slots[host->slot_id].get_cover_state(host->dev, + host->slot_id); return r; } static ssize_t -omap_hsmmc_show_cover_switch(struct device *dev, struct device_attribute *attr, +mmc_omap_show_cover_switch(struct device *dev, struct device_attribute *attr, char *buf) { struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); - struct omap_hsmmc_host *host = mmc_priv(mmc); + struct mmc_omap_host *host = mmc_priv(mmc); - return sprintf(buf, "%s\n", - omap_hsmmc_cover_is_closed(host) ? "closed" : "open"); + return sprintf(buf, "%s\n", mmc_omap_cover_is_closed(host) ? "closed" : + "open"); } -static DEVICE_ATTR(cover_switch, S_IRUGO, omap_hsmmc_show_cover_switch, NULL); +static DEVICE_ATTR(cover_switch, S_IRUGO, mmc_omap_show_cover_switch, NULL); static ssize_t -omap_hsmmc_show_slot_name(struct device *dev, struct device_attribute *attr, +mmc_omap_show_slot_name(struct device *dev, struct device_attribute *attr, char *buf) { struct mmc_host *mmc = container_of(dev, struct mmc_host, class_dev); - struct omap_hsmmc_host *host = mmc_priv(mmc); + struct mmc_omap_host *host = mmc_priv(mmc); + struct omap_mmc_slot_data slot = host->pdata->slots[host->slot_id]; - return sprintf(buf, "%s\n", mmc_slot(host).name); + return sprintf(buf, "%s\n", slot.name); } -static DEVICE_ATTR(slot_name, S_IRUGO, omap_hsmmc_show_slot_name, NULL); +static DEVICE_ATTR(slot_name, S_IRUGO, mmc_omap_show_slot_name, NULL); /* * Configure the response type and send the cmd. */ static void -omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, +mmc_omap_start_command(struct mmc_omap_host *host, struct mmc_command *cmd, struct mmc_data *data) { int cmdreg = 0, resptype = 0, cmdtype = 0; @@ -429,12 +241,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, */ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR); OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); - - if (host->use_dma) - OMAP_HSMMC_WRITE(host->base, IE, - INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE)); - else - OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); + OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); host->response_busy = 0; if (cmd->flags & MMC_RSP_PRESENT) { @@ -468,20 +275,12 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, if (host->use_dma) cmdreg |= DMA_EN; - /* - * In an interrupt context (i.e. STOP command), the spinlock is unlocked - * by the interrupt handler, otherwise (i.e. for a new request) it is - * unlocked here. - */ - if (!in_interrupt()) - spin_unlock_irqrestore(&host->irq_lock, host->flags); - OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); } static int -omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data) +mmc_omap_get_dma_dir(struct mmc_omap_host *host, struct mmc_data *data) { if (data->flags & MMC_DATA_WRITE) return DMA_TO_DEVICE; @@ -493,18 +292,11 @@ omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data) * Notify the transfer complete to MMC core */ static void -omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) +mmc_omap_xfer_done(struct mmc_omap_host *host, struct mmc_data *data) { if (!data) { struct mmc_request *mrq = host->mrq; - /* TC before CC from CMD6 - don't know why, but it happens */ - if (host->cmd && host->cmd->opcode == 6 && - host->response_busy) { - host->response_busy = 0; - return; - } - host->mrq = NULL; mmc_request_done(host->mmc, mrq); return; @@ -514,7 +306,7 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) if (host->use_dma && host->dma_ch != -1) dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len, - omap_hsmmc_get_dma_dir(host, data)); + mmc_omap_get_dma_dir(host, data)); if (!data->error) data->bytes_xfered += data->blocks * (data->blksz); @@ -526,14 +318,14 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) mmc_request_done(host->mmc, data->mrq); return; } - omap_hsmmc_start_command(host, data->stop, NULL); + mmc_omap_start_command(host, data->stop, NULL); } /* * Notify the core about command completion */ static void -omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) +mmc_omap_cmd_done(struct mmc_omap_host *host, struct mmc_command *cmd) { host->cmd = NULL; @@ -558,13 +350,13 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) /* * DMA clean up for command errors */ -static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) +static void mmc_dma_cleanup(struct mmc_omap_host *host, int errno) { host->data->error = errno; if (host->use_dma && host->dma_ch != -1) { dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len, - omap_hsmmc_get_dma_dir(host, host->data)); + mmc_omap_get_dma_dir(host, host->data)); omap_free_dma(host->dma_ch); host->dma_ch = -1; up(&host->sem); @@ -576,10 +368,10 @@ static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) * Readable error output */ #ifdef CONFIG_MMC_DEBUG -static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status) +static void mmc_omap_report_irq(struct mmc_omap_host *host, u32 status) { /* --- means reserved bit without definition at documentation */ - static const char *omap_hsmmc_status_bits[] = { + static const char *mmc_omap_status_bits[] = { "CC", "TC", "BGE", "---", "BWR", "BRR", "---", "---", "CIRQ", "OBI", "---", "---", "---", "---", "---", "ERRI", "CTO", "CCRC", "CEB", "CIE", "DTO", "DCRC", "DEB", "---", "ACE", "---", @@ -592,9 +384,9 @@ static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status) len = sprintf(buf, "MMC IRQ 0x%x :", status); buf += len; - for (i = 0; i < ARRAY_SIZE(omap_hsmmc_status_bits); i++) + for (i = 0; i < ARRAY_SIZE(mmc_omap_status_bits); i++) if (status & (1 << i)) { - len = sprintf(buf, " %s", omap_hsmmc_status_bits[i]); + len = sprintf(buf, " %s", mmc_omap_status_bits[i]); buf += len; } @@ -609,8 +401,8 @@ static void omap_hsmmc_report_irq(struct omap_hsmmc_host *host, u32 status) * SRC or SRD bit of SYSCTL register * Can be called from interrupt context */ -static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, - unsigned long bit) +static inline void mmc_omap_reset_controller_fsm(struct mmc_omap_host *host, + unsigned long bit) { unsigned long i = 0; unsigned long limit = (loops_per_jiffy * @@ -632,20 +424,17 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host, /* * MMC controller IRQ handler */ -static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) +static irqreturn_t mmc_omap_irq(int irq, void *dev_id) { - struct omap_hsmmc_host *host = dev_id; + struct mmc_omap_host *host = dev_id; struct mmc_data *data; int end_cmd = 0, end_trans = 0, status; - spin_lock(&host->irq_lock); - if (host->mrq == NULL) { OMAP_HSMMC_WRITE(host->base, STAT, OMAP_HSMMC_READ(host->base, STAT)); /* Flush posted write */ OMAP_HSMMC_READ(host->base, STAT); - spin_unlock(&host->irq_lock); return IRQ_HANDLED; } @@ -655,14 +444,13 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) if (status & ERR) { #ifdef CONFIG_MMC_DEBUG - omap_hsmmc_report_irq(host, status); + mmc_omap_report_irq(host, status); #endif if ((status & CMD_TIMEOUT) || (status & CMD_CRC)) { if (host->cmd) { if (status & CMD_TIMEOUT) { - omap_hsmmc_reset_controller_fsm(host, - SRC); + mmc_omap_reset_controller_fsm(host, SRC); host->cmd->error = -ETIMEDOUT; } else { host->cmd->error = -EILSEQ; @@ -671,10 +459,9 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) } if (host->data || host->response_busy) { if (host->data) - omap_hsmmc_dma_cleanup(host, - -ETIMEDOUT); + mmc_dma_cleanup(host, -ETIMEDOUT); host->response_busy = 0; - omap_hsmmc_reset_controller_fsm(host, SRD); + mmc_omap_reset_controller_fsm(host, SRD); } } if ((status & DATA_TIMEOUT) || @@ -684,11 +471,11 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) -ETIMEDOUT : -EILSEQ; if (host->data) - omap_hsmmc_dma_cleanup(host, err); + mmc_dma_cleanup(host, err); else host->mrq->cmd->error = err; host->response_busy = 0; - omap_hsmmc_reset_controller_fsm(host, SRD); + mmc_omap_reset_controller_fsm(host, SRD); end_trans = 1; } } @@ -707,16 +494,14 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) OMAP_HSMMC_READ(host->base, STAT); if (end_cmd || ((status & CC) && host->cmd)) - omap_hsmmc_cmd_done(host, host->cmd); - if ((end_trans || (status & TC)) && host->mrq) - omap_hsmmc_xfer_done(host, data); - - spin_unlock(&host->irq_lock); + mmc_omap_cmd_done(host, host->cmd); + if (end_trans || (status & TC)) + mmc_omap_xfer_done(host, data); return IRQ_HANDLED; } -static void set_sd_bus_power(struct omap_hsmmc_host *host) +static void set_sd_bus_power(struct mmc_omap_host *host) { unsigned long i; @@ -736,7 +521,7 @@ static void set_sd_bus_power(struct omap_hsmmc_host *host) * The MMC2 transceiver controls are used instead of DAT4..DAT7. * Some chips, like eMMC ones, use internal transceivers. */ -static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) +static int omap_mmc_switch_opcond(struct mmc_omap_host *host, int vdd) { u32 reg_val = 0; int ret; @@ -744,24 +529,22 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) /* Disable the clocks */ clk_disable(host->fclk); clk_disable(host->iclk); - if (host->got_dbclk) - clk_disable(host->dbclk); + clk_disable(host->dbclk); /* Turn the power off */ ret = mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); + if (ret != 0) + goto err; /* Turn the power ON with given VDD 1.8 or 3.0v */ - if (!ret) - ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, - vdd); - clk_enable(host->iclk); - clk_enable(host->fclk); - if (host->got_dbclk) - clk_enable(host->dbclk); - + ret = mmc_slot(host).set_power(host->dev, host->slot_id, 1, vdd); if (ret != 0) goto err; + clk_enable(host->fclk); + clk_enable(host->iclk); + clk_enable(host->dbclk); + OMAP_HSMMC_WRITE(host->base, HCTL, OMAP_HSMMC_READ(host->base, HCTL) & SDVSCLR); reg_val = OMAP_HSMMC_READ(host->base, HCTL); @@ -769,7 +552,7 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) /* * If a MMC dual voltage card is detected, the set_ios fn calls * this fn with VDD bit set for 1.8V. Upon card removal from the - * slot, omap_hsmmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF. + * slot, omap_mmc_set_ios sets the VDD back to 3V on MMC_POWER_OFF. * * Cope with a bit of slop in the range ... per data sheets: * - "1.8V" for vdds_mmc1/vdds_mmc1a can be up to 2.45V max, @@ -795,59 +578,25 @@ static int omap_hsmmc_switch_opcond(struct omap_hsmmc_host *host, int vdd) return ret; } -/* Protect the card while the cover is open */ -static void omap_hsmmc_protect_card(struct omap_hsmmc_host *host) -{ - if (!mmc_slot(host).get_cover_state) - return; - - host->reqs_blocked = 0; - if (mmc_slot(host).get_cover_state(host->dev, host->slot_id)) { - if (host->protect_card) { - printk(KERN_INFO "%s: cover is closed, " - "card is now accessible\n", - mmc_hostname(host->mmc)); - host->protect_card = 0; - } - } else { - if (!host->protect_card) { - printk(KERN_INFO "%s: cover is open, " - "card is now inaccessible\n", - mmc_hostname(host->mmc)); - host->protect_card = 1; - } - } -} - /* * Work Item to notify the core about card insertion/removal */ -static void omap_hsmmc_detect(struct work_struct *work) +static void mmc_omap_detect(struct work_struct *work) { - struct omap_hsmmc_host *host = - container_of(work, struct omap_hsmmc_host, mmc_carddetect_work); + struct mmc_omap_host *host = container_of(work, struct mmc_omap_host, + mmc_carddetect_work); struct omap_mmc_slot_data *slot = &mmc_slot(host); - int carddetect; - if (host->suspended) - return; + if (mmc_slot(host).card_detect) + host->carddetect = slot->card_detect(slot->card_detect_irq); + else + host->carddetect = -ENOSYS; sysfs_notify(&host->mmc->class_dev.kobj, NULL, "cover_switch"); - - if (slot->card_detect) - carddetect = slot->card_detect(slot->card_detect_irq); - else { - omap_hsmmc_protect_card(host); - carddetect = -ENOSYS; - } - - if (carddetect) { + if (host->carddetect) { mmc_detect_change(host->mmc, (HZ * 200) / 1000); } else { - mmc_host_enable(host->mmc); - omap_hsmmc_reset_controller_fsm(host, SRD); - mmc_host_lazy_disable(host->mmc); - + mmc_omap_reset_controller_fsm(host, SRD); mmc_detect_change(host->mmc, (HZ * 50) / 1000); } } @@ -855,18 +604,16 @@ static void omap_hsmmc_detect(struct work_struct *work) /* * ISR for handling card insertion and removal */ -static irqreturn_t omap_hsmmc_cd_handler(int irq, void *dev_id) +static irqreturn_t omap_mmc_cd_handler(int irq, void *dev_id) { - struct omap_hsmmc_host *host = (struct omap_hsmmc_host *)dev_id; + struct mmc_omap_host *host = (struct mmc_omap_host *)dev_id; - if (host->suspended) - return IRQ_HANDLED; schedule_work(&host->mmc_carddetect_work); return IRQ_HANDLED; } -static int omap_hsmmc_get_dma_sync_dev(struct omap_hsmmc_host *host, +static int mmc_omap_get_dma_sync_dev(struct mmc_omap_host *host, struct mmc_data *data) { int sync_dev; @@ -878,7 +625,7 @@ static int omap_hsmmc_get_dma_sync_dev(struct omap_hsmmc_host *host, return sync_dev; } -static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, +static void mmc_omap_config_dma_params(struct mmc_omap_host *host, struct mmc_data *data, struct scatterlist *sgl) { @@ -892,7 +639,7 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, sg_dma_address(sgl), 0, 0); } else { omap_set_dma_src_params(dma_ch, 0, OMAP_DMA_AMODE_CONSTANT, - (host->mapbase + OMAP_HSMMC_DATA), 0, 0); + (host->mapbase + OMAP_HSMMC_DATA), 0, 0); omap_set_dma_dest_params(dma_ch, 0, OMAP_DMA_AMODE_POST_INC, sg_dma_address(sgl), 0, 0); } @@ -902,7 +649,7 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, omap_set_dma_transfer_params(dma_ch, OMAP_DMA_DATA_TYPE_S32, blksz / 4, nblk, OMAP_DMA_SYNC_FRAME, - omap_hsmmc_get_dma_sync_dev(host, data), + mmc_omap_get_dma_sync_dev(host, data), !(data->flags & MMC_DATA_WRITE)); omap_start_dma(dma_ch); @@ -911,9 +658,9 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host, /* * DMA call back function */ -static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data) +static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) { - struct omap_hsmmc_host *host = data; + struct mmc_omap_host *host = data; if (ch_status & OMAP2_DMA_MISALIGNED_ERR_IRQ) dev_dbg(mmc_dev(host->mmc), "MISALIGNED_ADRS_ERR\n"); @@ -924,7 +671,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data) host->dma_sg_idx++; if (host->dma_sg_idx < host->dma_len) { /* Fire up the next transfer. */ - omap_hsmmc_config_dma_params(host, host->data, + mmc_omap_config_dma_params(host, host->data, host->data->sg + host->dma_sg_idx); return; } @@ -941,14 +688,14 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data) /* * Routine to configure and start DMA for the MMC card */ -static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, - struct mmc_request *req) +static int +mmc_omap_start_dma_transfer(struct mmc_omap_host *host, struct mmc_request *req) { int dma_ch = 0, ret = 0, err = 1, i; struct mmc_data *data = req->data; /* Sanity check: all the SG entries must be aligned by block size. */ - for (i = 0; i < data->sg_len; i++) { + for (i = 0; i < host->dma_len; i++) { struct scatterlist *sgl; sgl = data->sg + i; @@ -979,8 +726,8 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, return err; } - ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data), - "MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch); + ret = omap_request_dma(mmc_omap_get_dma_sync_dev(host, data), "MMC/SD", + mmc_omap_dma_cb,host, &dma_ch); if (ret != 0) { dev_err(mmc_dev(host->mmc), "%s: omap_request_dma() failed with %d\n", @@ -989,18 +736,17 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, } host->dma_len = dma_map_sg(mmc_dev(host->mmc), data->sg, - data->sg_len, omap_hsmmc_get_dma_dir(host, data)); + data->sg_len, mmc_omap_get_dma_dir(host, data)); host->dma_ch = dma_ch; host->dma_sg_idx = 0; - omap_hsmmc_config_dma_params(host, data, data->sg); + mmc_omap_config_dma_params(host, data, data->sg); return 0; } -static void set_data_timeout(struct omap_hsmmc_host *host, - unsigned int timeout_ns, - unsigned int timeout_clks) +static void set_data_timeout(struct mmc_omap_host *host, + struct mmc_request *req) { unsigned int timeout, cycle_ns; uint32_t reg, clkd, dto = 0; @@ -1011,8 +757,8 @@ static void set_data_timeout(struct omap_hsmmc_host *host, clkd = 1; cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd); - timeout = timeout_ns / cycle_ns; - timeout += timeout_clks; + timeout = req->data->timeout_ns / cycle_ns; + timeout += req->data->timeout_clks; if (timeout) { while ((timeout & 0x80000000) == 0) { dto += 1; @@ -1039,28 +785,22 @@ static void set_data_timeout(struct omap_hsmmc_host *host, * Configure block length for MMC/SD cards and initiate the transfer. */ static int -omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req) +mmc_omap_prepare_data(struct mmc_omap_host *host, struct mmc_request *req) { int ret; host->data = req->data; if (req->data == NULL) { OMAP_HSMMC_WRITE(host->base, BLK, 0); - /* - * Set an arbitrary 100ms data timeout for commands with - * busy signal. - */ - if (req->cmd->flags & MMC_RSP_BUSY) - set_data_timeout(host, 100000000U, 0); return 0; } OMAP_HSMMC_WRITE(host->base, BLK, (req->data->blksz) | (req->data->blocks << 16)); - set_data_timeout(host, req->data->timeout_ns, req->data->timeout_clks); + set_data_timeout(host, req); if (host->use_dma) { - ret = omap_hsmmc_start_dma_transfer(host, req); + ret = mmc_omap_start_dma_transfer(host, req); if (ret != 0) { dev_dbg(mmc_dev(host->mmc), "MMC start dma failure\n"); return ret; @@ -1072,92 +812,35 @@ omap_hsmmc_prepare_data(struct omap_hsmmc_host *host, struct mmc_request *req) /* * Request function. for read/write operation */ -static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) +static void omap_mmc_request(struct mmc_host *mmc, struct mmc_request *req) { - struct omap_hsmmc_host *host = mmc_priv(mmc); - int err; + struct mmc_omap_host *host = mmc_priv(mmc); - /* - * Prevent races with the interrupt handler because of unexpected - * interrupts, but not if we are already in interrupt context i.e. - * retries. - */ - if (!in_interrupt()) { - spin_lock_irqsave(&host->irq_lock, host->flags); - /* - * Protect the card from I/O if there is a possibility - * it can be removed. - */ - if (host->protect_card) { - if (host->reqs_blocked < 3) { - /* - * Ensure the controller is left in a consistent - * state by resetting the command and data state - * machines. - */ - omap_hsmmc_reset_controller_fsm(host, SRD); - omap_hsmmc_reset_controller_fsm(host, SRC); - host->reqs_blocked += 1; - } - req->cmd->error = -EBADF; - if (req->data) - req->data->error = -EBADF; - spin_unlock_irqrestore(&host->irq_lock, host->flags); - mmc_request_done(mmc, req); - return; - } else if (host->reqs_blocked) - host->reqs_blocked = 0; - } WARN_ON(host->mrq != NULL); host->mrq = req; - err = omap_hsmmc_prepare_data(host, req); - if (err) { - req->cmd->error = err; - if (req->data) - req->data->error = err; - host->mrq = NULL; - if (!in_interrupt()) - spin_unlock_irqrestore(&host->irq_lock, host->flags); - mmc_request_done(mmc, req); - return; - } - - omap_hsmmc_start_command(host, req->cmd, req->data); + mmc_omap_prepare_data(host, req); + mmc_omap_start_command(host, req->cmd, req->data); } + /* Routine to configure clock values. Exposed API to core */ -static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) +static void omap_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) { - struct omap_hsmmc_host *host = mmc_priv(mmc); + struct mmc_omap_host *host = mmc_priv(mmc); u16 dsor = 0; unsigned long regval; unsigned long timeout; u32 con; - int do_send_init_stream = 0; - - mmc_host_enable(host->mmc); - if (ios->power_mode != host->power_mode) { - switch (ios->power_mode) { - case MMC_POWER_OFF: - mmc_slot(host).set_power(host->dev, host->slot_id, - 0, 0); - host->vdd = 0; - break; - case MMC_POWER_UP: - mmc_slot(host).set_power(host->dev, host->slot_id, - 1, ios->vdd); - host->vdd = ios->vdd; - break; - case MMC_POWER_ON: - do_send_init_stream = 1; - break; - } - host->power_mode = ios->power_mode; + switch (ios->power_mode) { + case MMC_POWER_OFF: + mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); + break; + case MMC_POWER_UP: + mmc_slot(host).set_power(host->dev, host->slot_id, 1, ios->vdd); + break; } - /* FIXME: set registers based only on changes to ios */ - con = OMAP_HSMMC_READ(host->base, CON); switch (mmc->ios.bus_width) { case MMC_BUS_WIDTH_8: @@ -1187,8 +870,8 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) * MMC_POWER_UP upon recalculating the voltage. * vdd 1.8v. */ - if (omap_hsmmc_switch_opcond(host, ios->vdd) != 0) - dev_dbg(mmc_dev(host->mmc), + if (omap_mmc_switch_opcond(host, ios->vdd) != 0) + dev_dbg(mmc_dev(host->mmc), "Switch operation failed\n"); } } @@ -1204,7 +887,7 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) if (dsor > 250) dsor = 250; } - omap_hsmmc_stop_clock(host); + omap_mmc_stop_clock(host); regval = OMAP_HSMMC_READ(host->base, SYSCTL); regval = regval & ~(CLKD_MASK); regval = regval | (dsor << 6) | (DTO << 16); @@ -1214,47 +897,42 @@ static void omap_hsmmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) /* Wait till the ICS bit is set */ timeout = jiffies + msecs_to_jiffies(MMC_TIMEOUT_MS); - while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != ICS + while ((OMAP_HSMMC_READ(host->base, SYSCTL) & ICS) != 0x2 && time_before(jiffies, timeout)) msleep(1); OMAP_HSMMC_WRITE(host->base, SYSCTL, OMAP_HSMMC_READ(host->base, SYSCTL) | CEN); - if (do_send_init_stream) + if (ios->power_mode == MMC_POWER_ON) send_init_stream(host); - con = OMAP_HSMMC_READ(host->base, CON); if (ios->bus_mode == MMC_BUSMODE_OPENDRAIN) - OMAP_HSMMC_WRITE(host->base, CON, con | OD); - else - OMAP_HSMMC_WRITE(host->base, CON, con & ~OD); - - if (host->power_mode == MMC_POWER_OFF) - mmc_host_disable(host->mmc); - else - mmc_host_lazy_disable(host->mmc); + OMAP_HSMMC_WRITE(host->base, CON, + OMAP_HSMMC_READ(host->base, CON) | OD); } static int omap_hsmmc_get_cd(struct mmc_host *mmc) { - struct omap_hsmmc_host *host = mmc_priv(mmc); + struct mmc_omap_host *host = mmc_priv(mmc); + struct omap_mmc_platform_data *pdata = host->pdata; - if (!mmc_slot(host).card_detect) + if (!pdata->slots[0].card_detect) return -ENOSYS; - return mmc_slot(host).card_detect(mmc_slot(host).card_detect_irq); + return pdata->slots[0].card_detect(pdata->slots[0].card_detect_irq); } static int omap_hsmmc_get_ro(struct mmc_host *mmc) { - struct omap_hsmmc_host *host = mmc_priv(mmc); + struct mmc_omap_host *host = mmc_priv(mmc); + struct omap_mmc_platform_data *pdata = host->pdata; - if (!mmc_slot(host).get_ro) + if (!pdata->slots[0].get_ro) return -ENOSYS; - return mmc_slot(host).get_ro(host->dev, 0); + return pdata->slots[0].get_ro(host->dev, 0); } -static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) +static void omap_hsmmc_init(struct mmc_omap_host *host) { u32 hctl, capa, value; @@ -1281,340 +959,19 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host) set_sd_bus_power(host); } -/* - * Dynamic power saving handling, FSM: - * ENABLED -> DISABLED -> CARDSLEEP / REGSLEEP -> OFF - * ^___________| | | - * |______________________|______________________| - * - * ENABLED: mmc host is fully functional - * DISABLED: fclk is off - * CARDSLEEP: fclk is off, card is asleep, voltage regulator is asleep - * REGSLEEP: fclk is off, voltage regulator is asleep - * OFF: fclk is off, voltage regulator is off - * - * Transition handlers return the timeout for the next state transition - * or negative error. - */ - -enum {ENABLED = 0, DISABLED, CARDSLEEP, REGSLEEP, OFF}; - -/* Handler for [ENABLED -> DISABLED] transition */ -static int omap_hsmmc_enabled_to_disabled(struct omap_hsmmc_host *host) -{ - omap_hsmmc_context_save(host); - clk_disable(host->fclk); - host->dpm_state = DISABLED; - - dev_dbg(mmc_dev(host->mmc), "ENABLED -> DISABLED\n"); - - if (host->power_mode == MMC_POWER_OFF) - return 0; - - return msecs_to_jiffies(OMAP_MMC_SLEEP_TIMEOUT); -} - -/* Handler for [DISABLED -> REGSLEEP / CARDSLEEP] transition */ -static int omap_hsmmc_disabled_to_sleep(struct omap_hsmmc_host *host) -{ - int err, new_state; - - if (!mmc_try_claim_host(host->mmc)) - return 0; - - clk_enable(host->fclk); - omap_hsmmc_context_restore(host); - if (mmc_card_can_sleep(host->mmc)) { - err = mmc_card_sleep(host->mmc); - if (err < 0) { - clk_disable(host->fclk); - mmc_release_host(host->mmc); - return err; - } - new_state = CARDSLEEP; - } else { - new_state = REGSLEEP; - } - if (mmc_slot(host).set_sleep) - mmc_slot(host).set_sleep(host->dev, host->slot_id, 1, 0, - new_state == CARDSLEEP); - /* FIXME: turn off bus power and perhaps interrupts too */ - clk_disable(host->fclk); - host->dpm_state = new_state; - - mmc_release_host(host->mmc); - - dev_dbg(mmc_dev(host->mmc), "DISABLED -> %s\n", - host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP"); - - if ((host->mmc->caps & MMC_CAP_NONREMOVABLE) || - mmc_slot(host).card_detect || - (mmc_slot(host).get_cover_state && - mmc_slot(host).get_cover_state(host->dev, host->slot_id))) - return msecs_to_jiffies(OMAP_MMC_OFF_TIMEOUT); - - return 0; -} - -/* Handler for [REGSLEEP / CARDSLEEP -> OFF] transition */ -static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host) -{ - if (!mmc_try_claim_host(host->mmc)) - return 0; - - if (!((host->mmc->caps & MMC_CAP_NONREMOVABLE) || - mmc_slot(host).card_detect || - (mmc_slot(host).get_cover_state && - mmc_slot(host).get_cover_state(host->dev, host->slot_id)))) { - mmc_release_host(host->mmc); - return 0; - } - - mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0); - host->vdd = 0; - host->power_mode = MMC_POWER_OFF; - - dev_dbg(mmc_dev(host->mmc), "%s -> OFF\n", - host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP"); - - host->dpm_state = OFF; - - mmc_release_host(host->mmc); - - return 0; -} - -/* Handler for [DISABLED -> ENABLED] transition */ -static int omap_hsmmc_disabled_to_enabled(struct omap_hsmmc_host *host) -{ - int err; - - err = clk_enable(host->fclk); - if (err < 0) - return err; - - omap_hsmmc_context_restore(host); - host->dpm_state = ENABLED; - - dev_dbg(mmc_dev(host->mmc), "DISABLED -> ENABLED\n"); - - return 0; -} - -/* Handler for [SLEEP -> ENABLED] transition */ -static int omap_hsmmc_sleep_to_enabled(struct omap_hsmmc_host *host) -{ - if (!mmc_try_claim_host(host->mmc)) - return 0; - - clk_enable(host->fclk); - omap_hsmmc_context_restore(host); - if (mmc_slot(host).set_sleep) - mmc_slot(host).set_sleep(host->dev, host->slot_id, 0, - host->vdd, host->dpm_state == CARDSLEEP); - if (mmc_card_can_sleep(host->mmc)) - mmc_card_awake(host->mmc); - - dev_dbg(mmc_dev(host->mmc), "%s -> ENABLED\n", - host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP"); - - host->dpm_state = ENABLED; - - mmc_release_host(host->mmc); - - return 0; -} - -/* Handler for [OFF -> ENABLED] transition */ -static int omap_hsmmc_off_to_enabled(struct omap_hsmmc_host *host) -{ - clk_enable(host->fclk); - - omap_hsmmc_context_restore(host); - omap_hsmmc_conf_bus_power(host); - mmc_power_restore_host(host->mmc); - - host->dpm_state = ENABLED; - - dev_dbg(mmc_dev(host->mmc), "OFF -> ENABLED\n"); - - return 0; -} - -/* - * Bring MMC host to ENABLED from any other PM state. - */ -static int omap_hsmmc_enable(struct mmc_host *mmc) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - switch (host->dpm_state) { - case DISABLED: - return omap_hsmmc_disabled_to_enabled(host); - case CARDSLEEP: - case REGSLEEP: - return omap_hsmmc_sleep_to_enabled(host); - case OFF: - return omap_hsmmc_off_to_enabled(host); - default: - dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n"); - return -EINVAL; - } -} - -/* - * Bring MMC host in PM state (one level deeper). - */ -static int omap_hsmmc_disable(struct mmc_host *mmc, int lazy) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - switch (host->dpm_state) { - case ENABLED: { - int delay; - - delay = omap_hsmmc_enabled_to_disabled(host); - if (lazy || delay < 0) - return delay; - return 0; - } - case DISABLED: - return omap_hsmmc_disabled_to_sleep(host); - case CARDSLEEP: - case REGSLEEP: - return omap_hsmmc_sleep_to_off(host); - default: - dev_dbg(mmc_dev(host->mmc), "UNKNOWN state\n"); - return -EINVAL; - } -} - -static int omap_hsmmc_enable_fclk(struct mmc_host *mmc) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - int err; - - err = clk_enable(host->fclk); - if (err) - return err; - dev_dbg(mmc_dev(host->mmc), "mmc_fclk: enabled\n"); - omap_hsmmc_context_restore(host); - return 0; -} - -static int omap_hsmmc_disable_fclk(struct mmc_host *mmc, int lazy) -{ - struct omap_hsmmc_host *host = mmc_priv(mmc); - - omap_hsmmc_context_save(host); - clk_disable(host->fclk); - dev_dbg(mmc_dev(host->mmc), "mmc_fclk: disabled\n"); - return 0; -} - -static const struct mmc_host_ops omap_hsmmc_ops = { - .enable = omap_hsmmc_enable_fclk, - .disable = omap_hsmmc_disable_fclk, - .request = omap_hsmmc_request, - .set_ios = omap_hsmmc_set_ios, +static struct mmc_host_ops mmc_omap_ops = { + .request = omap_mmc_request, + .set_ios = omap_mmc_set_ios, .get_cd = omap_hsmmc_get_cd, .get_ro = omap_hsmmc_get_ro, /* NYET -- enable_sdio_irq */ }; -static const struct mmc_host_ops omap_hsmmc_ps_ops = { - .enable = omap_hsmmc_enable, - .disable = omap_hsmmc_disable, - .request = omap_hsmmc_request, - .set_ios = omap_hsmmc_set_ios, - .get_cd = omap_hsmmc_get_cd, - .get_ro = omap_hsmmc_get_ro, - /* NYET -- enable_sdio_irq */ -}; - -#ifdef CONFIG_DEBUG_FS - -static int omap_hsmmc_regs_show(struct seq_file *s, void *data) -{ - struct mmc_host *mmc = s->private; - struct omap_hsmmc_host *host = mmc_priv(mmc); - int context_loss = 0; - - if (host->pdata->get_context_loss_count) - context_loss = host->pdata->get_context_loss_count(host->dev); - - seq_printf(s, "mmc%d:\n" - " enabled:\t%d\n" - " dpm_state:\t%d\n" - " nesting_cnt:\t%d\n" - " ctx_loss:\t%d:%d\n" - "\nregs:\n", - mmc->index, mmc->enabled ? 1 : 0, - host->dpm_state, mmc->nesting_cnt, - host->context_loss, context_loss); - - if (host->suspended || host->dpm_state == OFF) { - seq_printf(s, "host suspended, can't read registers\n"); - return 0; - } - - if (clk_enable(host->fclk) != 0) { - seq_printf(s, "can't read the regs\n"); - return 0; - } - - seq_printf(s, "SYSCONFIG:\t0x%08x\n", - OMAP_HSMMC_READ(host->base, SYSCONFIG)); - seq_printf(s, "CON:\t\t0x%08x\n", - OMAP_HSMMC_READ(host->base, CON)); - seq_printf(s, "HCTL:\t\t0x%08x\n", - OMAP_HSMMC_READ(host->base, HCTL)); - seq_printf(s, "SYSCTL:\t\t0x%08x\n", - OMAP_HSMMC_READ(host->base, SYSCTL)); - seq_printf(s, "IE:\t\t0x%08x\n", - OMAP_HSMMC_READ(host->base, IE)); - seq_printf(s, "ISE:\t\t0x%08x\n", - OMAP_HSMMC_READ(host->base, ISE)); - seq_printf(s, "CAPA:\t\t0x%08x\n", - OMAP_HSMMC_READ(host->base, CAPA)); - - clk_disable(host->fclk); - - return 0; -} - -static int omap_hsmmc_regs_open(struct inode *inode, struct file *file) -{ - return single_open(file, omap_hsmmc_regs_show, inode->i_private); -} - -static const struct file_operations mmc_regs_fops = { - .open = omap_hsmmc_regs_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -static void omap_hsmmc_debugfs(struct mmc_host *mmc) -{ - if (mmc->debugfs_root) - debugfs_create_file("regs", S_IRUSR, mmc->debugfs_root, - mmc, &mmc_regs_fops); -} - -#else - -static void omap_hsmmc_debugfs(struct mmc_host *mmc) -{ -} - -#endif - -static int __init omap_hsmmc_probe(struct platform_device *pdev) +static int __init omap_mmc_probe(struct platform_device *pdev) { struct omap_mmc_platform_data *pdata = pdev->dev.platform_data; struct mmc_host *mmc; - struct omap_hsmmc_host *host = NULL; + struct mmc_omap_host *host = NULL; struct resource *res; int ret = 0, irq; @@ -1638,7 +995,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) if (res == NULL) return -EBUSY; - mmc = mmc_alloc_host(sizeof(struct omap_hsmmc_host), &pdev->dev); + mmc = mmc_alloc_host(sizeof(struct mmc_omap_host), &pdev->dev); if (!mmc) { ret = -ENOMEM; goto err; @@ -1656,21 +1013,15 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) host->slot_id = 0; host->mapbase = res->start; host->base = ioremap(host->mapbase, SZ_4K); - host->power_mode = -1; platform_set_drvdata(pdev, host); - INIT_WORK(&host->mmc_carddetect_work, omap_hsmmc_detect); - - if (mmc_slot(host).power_saving) - mmc->ops = &omap_hsmmc_ps_ops; - else - mmc->ops = &omap_hsmmc_ops; + INIT_WORK(&host->mmc_carddetect_work, mmc_omap_detect); + mmc->ops = &mmc_omap_ops; mmc->f_min = 400000; mmc->f_max = 52000000; sema_init(&host->sem, 1); - spin_lock_init(&host->irq_lock); host->iclk = clk_get(&pdev->dev, "ick"); if (IS_ERR(host->iclk)) { @@ -1686,42 +1037,31 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) goto err1; } - omap_hsmmc_context_save(host); - - mmc->caps |= MMC_CAP_DISABLE; - mmc_set_disable_delay(mmc, OMAP_MMC_DISABLED_TIMEOUT); - /* we start off in DISABLED state */ - host->dpm_state = DISABLED; - - if (mmc_host_enable(host->mmc) != 0) { + if (clk_enable(host->fclk) != 0) { clk_put(host->iclk); clk_put(host->fclk); goto err1; } if (clk_enable(host->iclk) != 0) { - mmc_host_disable(host->mmc); + clk_disable(host->fclk); clk_put(host->iclk); clk_put(host->fclk); goto err1; } - if (cpu_is_omap2430()) { - host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); - /* - * MMC can still work without debounce clock. - */ - if (IS_ERR(host->dbclk)) - dev_warn(mmc_dev(host->mmc), - "Failed to get debounce clock\n"); - else - host->got_dbclk = 1; - - if (host->got_dbclk) - if (clk_enable(host->dbclk) != 0) - dev_dbg(mmc_dev(host->mmc), "Enabling debounce" + host->dbclk = clk_get(&pdev->dev, "mmchsdb_fck"); + /* + * MMC can still work without debounce clock. + */ + if (IS_ERR(host->dbclk)) + dev_warn(mmc_dev(host->mmc), "Failed to get debounce clock\n"); + else + if (clk_enable(host->dbclk) != 0) + dev_dbg(mmc_dev(host->mmc), "Enabling debounce" " clk failed\n"); - } + else + host->dbclk_enabled = 1; /* Since we do only SG emulation, we can have as many segs * as we want. */ @@ -1733,18 +1073,14 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; mmc->max_seg_size = mmc->max_req_size; - mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED | - MMC_CAP_WAIT_WHILE_BUSY; + mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED; - if (mmc_slot(host).wires >= 8) + if (pdata->slots[host->slot_id].wires >= 8) mmc->caps |= MMC_CAP_8_BIT_DATA; - else if (mmc_slot(host).wires >= 4) + else if (pdata->slots[host->slot_id].wires >= 4) mmc->caps |= MMC_CAP_4_BIT_DATA; - if (mmc_slot(host).nonremovable) - mmc->caps |= MMC_CAP_NONREMOVABLE; - - omap_hsmmc_conf_bus_power(host); + omap_hsmmc_init(host); /* Select DMA lines */ switch (host->id) { @@ -1760,21 +1096,13 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) host->dma_line_tx = OMAP34XX_DMA_MMC3_TX; host->dma_line_rx = OMAP34XX_DMA_MMC3_RX; break; - case OMAP_MMC4_DEVID: - host->dma_line_tx = OMAP44XX_DMA_MMC4_TX; - host->dma_line_rx = OMAP44XX_DMA_MMC4_RX; - break; - case OMAP_MMC5_DEVID: - host->dma_line_tx = OMAP44XX_DMA_MMC5_TX; - host->dma_line_rx = OMAP44XX_DMA_MMC5_RX; - break; default: dev_err(mmc_dev(host->mmc), "Invalid MMC id\n"); goto err_irq; } /* Request IRQ for MMC operations */ - ret = request_irq(host->irq, omap_hsmmc_irq, IRQF_DISABLED, + ret = request_irq(host->irq, mmc_omap_irq, IRQF_DISABLED, mmc_hostname(mmc), host); if (ret) { dev_dbg(mmc_dev(host->mmc), "Unable to grab HSMMC IRQ\n"); @@ -1784,8 +1112,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) /* initialize power supplies, gpios, etc */ if (pdata->init != NULL) { if (pdata->init(&pdev->dev) != 0) { - dev_dbg(mmc_dev(host->mmc), - "Unable to configure MMC IRQs\n"); + dev_dbg(mmc_dev(host->mmc), "late init error\n"); goto err_irq_cd_init; } } @@ -1794,7 +1121,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) /* Request IRQ for card detect */ if ((mmc_slot(host).card_detect_irq)) { ret = request_irq(mmc_slot(host).card_detect_irq, - omap_hsmmc_cd_handler, + omap_mmc_cd_handler, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_DISABLED, mmc_hostname(mmc), host); @@ -1808,26 +1135,21 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK); OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK); - mmc_host_lazy_disable(host->mmc); - - omap_hsmmc_protect_card(host); - mmc_add_host(mmc); - if (mmc_slot(host).name != NULL) { + if (host->pdata->slots[host->slot_id].name != NULL) { ret = device_create_file(&mmc->class_dev, &dev_attr_slot_name); if (ret < 0) goto err_slot_name; } - if (mmc_slot(host).card_detect_irq && mmc_slot(host).get_cover_state) { + if (mmc_slot(host).card_detect_irq && + host->pdata->slots[host->slot_id].get_cover_state) { ret = device_create_file(&mmc->class_dev, &dev_attr_cover_switch); if (ret < 0) goto err_cover_switch; } - omap_hsmmc_debugfs(mmc); - return 0; err_cover_switch: @@ -1839,11 +1161,11 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) err_irq_cd_init: free_irq(host->irq, host); err_irq: - mmc_host_disable(host->mmc); + clk_disable(host->fclk); clk_disable(host->iclk); clk_put(host->fclk); clk_put(host->iclk); - if (host->got_dbclk) { + if (host->dbclk_enabled) { clk_disable(host->dbclk); clk_put(host->dbclk); } @@ -1858,13 +1180,12 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev) return ret; } -static int omap_hsmmc_remove(struct platform_device *pdev) +static int omap_mmc_remove(struct platform_device *pdev) { - struct omap_hsmmc_host *host = platform_get_drvdata(pdev); + struct mmc_omap_host *host = platform_get_drvdata(pdev); struct resource *res; if (host) { - mmc_host_enable(host->mmc); mmc_remove_host(host->mmc); if (host->pdata->cleanup) host->pdata->cleanup(&pdev->dev); @@ -1873,11 +1194,11 @@ static int omap_hsmmc_remove(struct platform_device *pdev) free_irq(mmc_slot(host).card_detect_irq, host); flush_scheduled_work(); - mmc_host_disable(host->mmc); + clk_disable(host->fclk); clk_disable(host->iclk); clk_put(host->fclk); clk_put(host->iclk); - if (host->got_dbclk) { + if (host->dbclk_enabled) { clk_disable(host->dbclk); clk_put(host->dbclk); } @@ -1895,51 +1216,36 @@ static int omap_hsmmc_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state) +static int omap_mmc_suspend(struct platform_device *pdev, pm_message_t state) { int ret = 0; - struct omap_hsmmc_host *host = platform_get_drvdata(pdev); + struct mmc_omap_host *host = platform_get_drvdata(pdev); if (host && host->suspended) return 0; if (host) { - host->suspended = 1; - if (host->pdata->suspend) { - ret = host->pdata->suspend(&pdev->dev, - host->slot_id); - if (ret) { - dev_dbg(mmc_dev(host->mmc), - "Unable to handle MMC board" - " level suspend\n"); - host->suspended = 0; - return ret; - } - } - cancel_work_sync(&host->mmc_carddetect_work); - mmc_host_enable(host->mmc); ret = mmc_suspend_host(host->mmc, state); if (ret == 0) { + host->suspended = 1; + OMAP_HSMMC_WRITE(host->base, ISE, 0); OMAP_HSMMC_WRITE(host->base, IE, 0); - - OMAP_HSMMC_WRITE(host->base, HCTL, - OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); - mmc_host_disable(host->mmc); - clk_disable(host->iclk); - if (host->got_dbclk) - clk_disable(host->dbclk); - } else { - host->suspended = 0; - if (host->pdata->resume) { - ret = host->pdata->resume(&pdev->dev, - host->slot_id); + if (host->pdata->suspend) { + ret = host->pdata->suspend(&pdev->dev, + host->slot_id); if (ret) dev_dbg(mmc_dev(host->mmc), - "Unmask interrupt failed\n"); + "Unable to handle MMC board" + " level suspend\n"); } - mmc_host_disable(host->mmc); + + OMAP_HSMMC_WRITE(host->base, HCTL, + OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP); + clk_disable(host->fclk); + clk_disable(host->iclk); + clk_disable(host->dbclk); } } @@ -1947,28 +1253,32 @@ static int omap_hsmmc_suspend(struct platform_device *pdev, pm_message_t state) } /* Routine to resume the MMC device */ -static int omap_hsmmc_resume(struct platform_device *pdev) +static int omap_mmc_resume(struct platform_device *pdev) { int ret = 0; - struct omap_hsmmc_host *host = platform_get_drvdata(pdev); + struct mmc_omap_host *host = platform_get_drvdata(pdev); if (host && !host->suspended) return 0; if (host) { - ret = clk_enable(host->iclk); + + ret = clk_enable(host->fclk); if (ret) goto clk_en_err; - if (mmc_host_enable(host->mmc) != 0) { - clk_disable(host->iclk); + ret = clk_enable(host->iclk); + if (ret) { + clk_disable(host->fclk); + clk_put(host->fclk); goto clk_en_err; } - if (host->got_dbclk) - clk_enable(host->dbclk); + if (clk_enable(host->dbclk) != 0) + dev_dbg(mmc_dev(host->mmc), + "Enabling debounce clk failed\n"); - omap_hsmmc_conf_bus_power(host); + omap_hsmmc_init(host); if (host->pdata->resume) { ret = host->pdata->resume(&pdev->dev, host->slot_id); @@ -1977,14 +1287,10 @@ static int omap_hsmmc_resume(struct platform_device *pdev) "Unmask interrupt failed\n"); } - omap_hsmmc_protect_card(host); - /* Notify the core to resume the host */ ret = mmc_resume_host(host->mmc); if (ret == 0) host->suspended = 0; - - mmc_host_lazy_disable(host->mmc); } return ret; @@ -1996,34 +1302,35 @@ static int omap_hsmmc_resume(struct platform_device *pdev) } #else -#define omap_hsmmc_suspend NULL -#define omap_hsmmc_resume NULL +#define omap_mmc_suspend NULL +#define omap_mmc_resume NULL #endif -static struct platform_driver omap_hsmmc_driver = { - .remove = omap_hsmmc_remove, - .suspend = omap_hsmmc_suspend, - .resume = omap_hsmmc_resume, +static struct platform_driver omap_mmc_driver = { + .probe = omap_mmc_probe, + .remove = omap_mmc_remove, + .suspend = omap_mmc_suspend, + .resume = omap_mmc_resume, .driver = { .name = DRIVER_NAME, .owner = THIS_MODULE, }, }; -static int __init omap_hsmmc_init(void) +static int __init omap_mmc_init(void) { /* Register the MMC driver */ - return platform_driver_register(&omap_hsmmc_driver); + return platform_driver_register(&omap_mmc_driver); } -static void __exit omap_hsmmc_cleanup(void) +static void __exit omap_mmc_cleanup(void) { /* Unregister MMC driver */ - platform_driver_unregister(&omap_hsmmc_driver); + platform_driver_unregister(&omap_mmc_driver); } -module_init(omap_hsmmc_init); -module_exit(omap_hsmmc_cleanup); +module_init(omap_mmc_init); +module_exit(omap_mmc_cleanup); MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver"); MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/mmc/host/sdhci-of.c b/trunk/drivers/mmc/host/sdhci-of.c index 01ab916c2802..1e8aa590bb39 100644 --- a/trunk/drivers/mmc/host/sdhci-of.c +++ b/trunk/drivers/mmc/host/sdhci-of.c @@ -21,7 +21,6 @@ #include #include #include -#include #include "sdhci.h" struct sdhci_of_data { @@ -49,8 +48,6 @@ struct sdhci_of_host { #define ESDHC_CLOCK_HCKEN 0x00000002 #define ESDHC_CLOCK_IPGEN 0x00000001 -#define ESDHC_HOST_CONTROL_RES 0x05 - static u32 esdhc_readl(struct sdhci_host *host, int reg) { return in_be32(host->ioaddr + reg); @@ -112,17 +109,13 @@ static void esdhc_writeb(struct sdhci_host *host, u8 val, int reg) int base = reg & ~0x3; int shift = (reg & 0x3) * 8; - /* Prevent SDHCI core from writing reserved bits (e.g. HISPD). */ - if (reg == SDHCI_HOST_CONTROL) - val &= ~ESDHC_HOST_CONTROL_RES; - clrsetbits_be32(host->ioaddr + base , 0xff << shift, val << shift); } static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) { + int div; int pre_div = 2; - int div = 1; clrbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | ESDHC_CLOCK_MASK); @@ -130,17 +123,19 @@ static void esdhc_set_clock(struct sdhci_host *host, unsigned int clock) if (clock == 0) goto out; - while (host->max_clk / pre_div / 16 > clock && pre_div < 256) - pre_div *= 2; - - while (host->max_clk / pre_div / div > clock && div < 16) - div++; + if (host->max_clk / 16 > clock) { + for (; pre_div < 256; pre_div *= 2) { + if (host->max_clk / pre_div < clock * 16) + break; + } + } - dev_dbg(mmc_dev(host->mmc), "desired SD clock: %d, actual: %d\n", - clock, host->max_clk / pre_div / div); + for (div = 1; div <= 16; div++) { + if (host->max_clk / (div * pre_div) <= clock) + break; + } pre_div >>= 1; - div--; setbits32(host->ioaddr + ESDHC_SYSTEM_CONTROL, ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN | @@ -170,12 +165,19 @@ static unsigned int esdhc_get_min_clock(struct sdhci_host *host) return of_host->clock / 256 / 16; } +static unsigned int esdhc_get_timeout_clock(struct sdhci_host *host) +{ + struct sdhci_of_host *of_host = sdhci_priv(host); + + return of_host->clock / 1000; +} + static struct sdhci_of_data sdhci_esdhc = { .quirks = SDHCI_QUIRK_FORCE_BLK_SZ_2048 | SDHCI_QUIRK_BROKEN_CARD_DETECTION | + SDHCI_QUIRK_INVERTED_WRITE_PROTECT | SDHCI_QUIRK_NO_BUSY_IRQ | SDHCI_QUIRK_NONSTANDARD_CLOCK | - SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | SDHCI_QUIRK_PIO_NEEDS_DELAY | SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | SDHCI_QUIRK_NO_CARD_NO_RESET, @@ -190,6 +192,7 @@ static struct sdhci_of_data sdhci_esdhc = { .enable_dma = esdhc_enable_dma, .get_max_clock = esdhc_get_max_clock, .get_min_clock = esdhc_get_min_clock, + .get_timeout_clock = esdhc_get_timeout_clock, }, }; @@ -216,15 +219,6 @@ static int sdhci_of_resume(struct of_device *ofdev) #endif -static bool __devinit sdhci_of_wp_inverted(struct device_node *np) -{ - if (of_get_property(np, "sdhci,wp-inverted", NULL)) - return true; - - /* Old device trees don't have the wp-inverted property. */ - return machine_is(mpc837x_rdb) || machine_is(mpc837x_mds); -} - static int __devinit sdhci_of_probe(struct of_device *ofdev, const struct of_device_id *match) { @@ -267,9 +261,6 @@ static int __devinit sdhci_of_probe(struct of_device *ofdev, if (of_get_property(np, "sdhci,1-bit-only", NULL)) host->quirks |= SDHCI_QUIRK_FORCE_1_BIT_DATA; - if (sdhci_of_wp_inverted(np)) - host->quirks |= SDHCI_QUIRK_INVERTED_WRITE_PROTECT; - clk = of_get_property(np, "clock-frequency", &size); if (clk && size == sizeof(*clk) && *clk) of_host->clock = *clk; diff --git a/trunk/drivers/mmc/host/sdhci-pci.c b/trunk/drivers/mmc/host/sdhci-pci.c index e0356644d1aa..2f15cc17d887 100644 --- a/trunk/drivers/mmc/host/sdhci-pci.c +++ b/trunk/drivers/mmc/host/sdhci-pci.c @@ -83,8 +83,7 @@ static int ricoh_probe(struct sdhci_pci_chip *chip) if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_IBM) chip->quirks |= SDHCI_QUIRK_CLOCK_BEFORE_RESET; - if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG || - chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SONY) + if (chip->pdev->subsystem_vendor == PCI_VENDOR_ID_SAMSUNG) chip->quirks |= SDHCI_QUIRK_NO_CARD_NO_RESET; return 0; @@ -396,7 +395,7 @@ static int sdhci_pci_enable_dma(struct sdhci_host *host) if (((pdev->class & 0xFFFF00) == (PCI_CLASS_SYSTEM_SDHCI << 8)) && ((pdev->class & 0x0000FF) != PCI_SDHCI_IFDMA) && - (host->flags & SDHCI_USE_SDMA)) { + (host->flags & SDHCI_USE_DMA)) { dev_warn(&pdev->dev, "Will use DMA mode even though HW " "doesn't fully claim to support it.\n"); } diff --git a/trunk/drivers/mmc/host/sdhci.c b/trunk/drivers/mmc/host/sdhci.c index c279fbc4c2e5..fc96f8cb9c0b 100644 --- a/trunk/drivers/mmc/host/sdhci.c +++ b/trunk/drivers/mmc/host/sdhci.c @@ -591,9 +591,6 @@ static u8 sdhci_calc_timeout(struct sdhci_host *host, struct mmc_data *data) target_timeout = data->timeout_ns / 1000 + data->timeout_clks / host->clock; - if (host->quirks & SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK) - host->timeout_clk = host->clock / 1000; - /* * Figure out needed cycles. * We do this in steps in order to fit inside a 32 bit int. @@ -655,7 +652,7 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data) count = sdhci_calc_timeout(host, data); sdhci_writeb(host, count, SDHCI_TIMEOUT_CONTROL); - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) + if (host->flags & SDHCI_USE_DMA) host->flags |= SDHCI_REQ_USE_DMA; /* @@ -994,8 +991,8 @@ static void sdhci_set_clock(struct sdhci_host *host, unsigned int clock) clk |= SDHCI_CLOCK_INT_EN; sdhci_writew(host, clk, SDHCI_CLOCK_CONTROL); - /* Wait max 20 ms */ - timeout = 20; + /* Wait max 10 ms */ + timeout = 10; while (!((clk = sdhci_readw(host, SDHCI_CLOCK_CONTROL)) & SDHCI_CLOCK_INT_STABLE)) { if (timeout == 0) { @@ -1600,7 +1597,7 @@ int sdhci_resume_host(struct sdhci_host *host) { int ret; - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { + if (host->flags & SDHCI_USE_DMA) { if (host->ops->enable_dma) host->ops->enable_dma(host); } @@ -1681,20 +1678,23 @@ int sdhci_add_host(struct sdhci_host *host) caps = sdhci_readl(host, SDHCI_CAPABILITIES); if (host->quirks & SDHCI_QUIRK_FORCE_DMA) - host->flags |= SDHCI_USE_SDMA; - else if (!(caps & SDHCI_CAN_DO_SDMA)) - DBG("Controller doesn't have SDMA capability\n"); + host->flags |= SDHCI_USE_DMA; + else if (!(caps & SDHCI_CAN_DO_DMA)) + DBG("Controller doesn't have DMA capability\n"); else - host->flags |= SDHCI_USE_SDMA; + host->flags |= SDHCI_USE_DMA; if ((host->quirks & SDHCI_QUIRK_BROKEN_DMA) && - (host->flags & SDHCI_USE_SDMA)) { + (host->flags & SDHCI_USE_DMA)) { DBG("Disabling DMA as it is marked broken\n"); - host->flags &= ~SDHCI_USE_SDMA; + host->flags &= ~SDHCI_USE_DMA; } - if ((host->version >= SDHCI_SPEC_200) && (caps & SDHCI_CAN_DO_ADMA2)) - host->flags |= SDHCI_USE_ADMA; + if (host->flags & SDHCI_USE_DMA) { + if ((host->version >= SDHCI_SPEC_200) && + (caps & SDHCI_CAN_DO_ADMA2)) + host->flags |= SDHCI_USE_ADMA; + } if ((host->quirks & SDHCI_QUIRK_BROKEN_ADMA) && (host->flags & SDHCI_USE_ADMA)) { @@ -1702,14 +1702,13 @@ int sdhci_add_host(struct sdhci_host *host) host->flags &= ~SDHCI_USE_ADMA; } - if (host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA)) { + if (host->flags & SDHCI_USE_DMA) { if (host->ops->enable_dma) { if (host->ops->enable_dma(host)) { printk(KERN_WARNING "%s: No suitable DMA " "available. Falling back to PIO.\n", mmc_hostname(mmc)); - host->flags &= - ~(SDHCI_USE_SDMA | SDHCI_USE_ADMA); + host->flags &= ~(SDHCI_USE_DMA | SDHCI_USE_ADMA); } } } @@ -1737,7 +1736,7 @@ int sdhci_add_host(struct sdhci_host *host) * mask, but PIO does not need the hw shim so we set a new * mask here in that case. */ - if (!(host->flags & (SDHCI_USE_SDMA | SDHCI_USE_ADMA))) { + if (!(host->flags & SDHCI_USE_DMA)) { host->dma_mask = DMA_BIT_MASK(64); mmc_dev(host->mmc)->dma_mask = &host->dma_mask; } @@ -1758,15 +1757,13 @@ int sdhci_add_host(struct sdhci_host *host) host->timeout_clk = (caps & SDHCI_TIMEOUT_CLK_MASK) >> SDHCI_TIMEOUT_CLK_SHIFT; if (host->timeout_clk == 0) { - if (host->ops->get_timeout_clock) { - host->timeout_clk = host->ops->get_timeout_clock(host); - } else if (!(host->quirks & - SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK)) { + if (!host->ops->get_timeout_clock) { printk(KERN_ERR "%s: Hardware doesn't specify timeout clock " "frequency.\n", mmc_hostname(mmc)); return -ENODEV; } + host->timeout_clk = host->ops->get_timeout_clock(host); } if (caps & SDHCI_TIMEOUT_CLK_UNIT) host->timeout_clk *= 1000; @@ -1775,8 +1772,7 @@ int sdhci_add_host(struct sdhci_host *host) * Set host parameters. */ mmc->ops = &sdhci_ops; - if (host->quirks & SDHCI_QUIRK_NONSTANDARD_CLOCK && - host->ops->set_clock && host->ops->get_min_clock) + if (host->ops->get_min_clock) mmc->f_min = host->ops->get_min_clock(host); else mmc->f_min = host->max_clk / 256; @@ -1814,7 +1810,7 @@ int sdhci_add_host(struct sdhci_host *host) */ if (host->flags & SDHCI_USE_ADMA) mmc->max_hw_segs = 128; - else if (host->flags & SDHCI_USE_SDMA) + else if (host->flags & SDHCI_USE_DMA) mmc->max_hw_segs = 1; else /* PIO */ mmc->max_hw_segs = 128; @@ -1897,10 +1893,10 @@ int sdhci_add_host(struct sdhci_host *host) mmc_add_host(mmc); - printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s\n", + printk(KERN_INFO "%s: SDHCI controller on %s [%s] using %s%s\n", mmc_hostname(mmc), host->hw_name, dev_name(mmc_dev(mmc)), - (host->flags & SDHCI_USE_ADMA) ? "ADMA" : - (host->flags & SDHCI_USE_SDMA) ? "DMA" : "PIO"); + (host->flags & SDHCI_USE_ADMA)?"A":"", + (host->flags & SDHCI_USE_DMA)?"DMA":"PIO"); sdhci_enable_card_detection(host); diff --git a/trunk/drivers/mmc/host/sdhci.h b/trunk/drivers/mmc/host/sdhci.h index ce5f1d73dc04..c77e9ff30223 100644 --- a/trunk/drivers/mmc/host/sdhci.h +++ b/trunk/drivers/mmc/host/sdhci.h @@ -143,7 +143,7 @@ #define SDHCI_CAN_DO_ADMA2 0x00080000 #define SDHCI_CAN_DO_ADMA1 0x00100000 #define SDHCI_CAN_DO_HISPD 0x00200000 -#define SDHCI_CAN_DO_SDMA 0x00400000 +#define SDHCI_CAN_DO_DMA 0x00400000 #define SDHCI_CAN_VDD_330 0x01000000 #define SDHCI_CAN_VDD_300 0x02000000 #define SDHCI_CAN_VDD_180 0x04000000 @@ -232,8 +232,6 @@ struct sdhci_host { #define SDHCI_QUIRK_FORCE_1_BIT_DATA (1<<22) /* Controller needs 10ms delay between applying power and clock */ #define SDHCI_QUIRK_DELAY_AFTER_POWER (1<<23) -/* Controller uses SDCLK instead of TMCLK for data timeouts */ -#define SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK (1<<24) int irq; /* Device IRQ */ void __iomem * ioaddr; /* Mapped address */ @@ -252,7 +250,7 @@ struct sdhci_host { spinlock_t lock; /* Mutex */ int flags; /* Host attributes */ -#define SDHCI_USE_SDMA (1<<0) /* Host is SDMA capable */ +#define SDHCI_USE_DMA (1<<0) /* Host is DMA capable */ #define SDHCI_USE_ADMA (1<<1) /* Host is ADMA capable */ #define SDHCI_REQ_USE_DMA (1<<2) /* Use DMA for this req. */ #define SDHCI_DEVICE_DEAD (1<<3) /* Device unresponsive */ diff --git a/trunk/drivers/mtd/devices/mtd_dataflash.c b/trunk/drivers/mtd/devices/mtd_dataflash.c index 211c27acd01e..43976aa4dbb1 100644 --- a/trunk/drivers/mtd/devices/mtd_dataflash.c +++ b/trunk/drivers/mtd/devices/mtd_dataflash.c @@ -966,4 +966,3 @@ module_exit(dataflash_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Andrew Victor, David Brownell"); MODULE_DESCRIPTION("MTD DataFlash driver"); -MODULE_ALIAS("spi:mtd_dataflash"); diff --git a/trunk/drivers/net/ehea/ehea_qmr.c b/trunk/drivers/net/ehea/ehea_qmr.c index bc7c5b7abb88..3747457f5e69 100644 --- a/trunk/drivers/net/ehea/ehea_qmr.c +++ b/trunk/drivers/net/ehea/ehea_qmr.c @@ -751,7 +751,7 @@ int ehea_create_busmap(void) mutex_lock(&ehea_busmap_mutex); ehea_mr_len = 0; - ret = walk_system_ram_range(0, 1ULL << MAX_PHYSMEM_BITS, NULL, + ret = walk_memory_resource(0, 1ULL << MAX_PHYSMEM_BITS, NULL, ehea_create_busmap_callback); mutex_unlock(&ehea_busmap_mutex); return ret; diff --git a/trunk/drivers/net/enc28j60.c b/trunk/drivers/net/enc28j60.c index 66813c91a720..117fc6c12e34 100644 --- a/trunk/drivers/net/enc28j60.c +++ b/trunk/drivers/net/enc28j60.c @@ -1666,4 +1666,3 @@ MODULE_AUTHOR("Claudio Lanconelli "); MODULE_LICENSE("GPL"); module_param_named(debug, debug.msg_enable, int, 0); MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., ffff=all)"); -MODULE_ALIAS("spi:" DRV_NAME); diff --git a/trunk/drivers/net/ks8851.c b/trunk/drivers/net/ks8851.c index 237835864357..547ac7c7479c 100644 --- a/trunk/drivers/net/ks8851.c +++ b/trunk/drivers/net/ks8851.c @@ -1321,4 +1321,3 @@ MODULE_LICENSE("GPL"); module_param_named(message, msg_enable, int, 0); MODULE_PARM_DESC(message, "Message verbosity level (0=none, 31=all)"); -MODULE_ALIAS("spi:ks8851"); diff --git a/trunk/drivers/net/niu.c b/trunk/drivers/net/niu.c index f9364d0678f2..76cc2614f480 100644 --- a/trunk/drivers/net/niu.c +++ b/trunk/drivers/net/niu.c @@ -5615,7 +5615,7 @@ static void niu_init_tx_mac(struct niu *np) /* The XMAC_MIN register only accepts values for TX min which * have the low 3 bits cleared. */ - BUG_ON(min & 0x7); + BUILD_BUG_ON(min & 0x7); if (np->flags & NIU_FLAGS_XMAC) niu_init_tx_xmac(np, min, max); diff --git a/trunk/drivers/net/usb/cdc_eem.c b/trunk/drivers/net/usb/cdc_eem.c index 23300656c266..45cebfb302cf 100644 --- a/trunk/drivers/net/usb/cdc_eem.c +++ b/trunk/drivers/net/usb/cdc_eem.c @@ -300,23 +300,20 @@ static int eem_rx_fixup(struct usbnet *dev, struct sk_buff *skb) return 0; } + crc = get_unaligned_le32(skb2->data + + len - ETH_FCS_LEN); + skb_trim(skb2, len - ETH_FCS_LEN); + /* * The bmCRC helps to denote when the CRC field in * the Ethernet frame contains a calculated CRC: * bmCRC = 1 : CRC is calculated * bmCRC = 0 : CRC = 0xDEADBEEF */ - if (header & BIT(14)) { - crc = get_unaligned_le32(skb2->data - + len - ETH_FCS_LEN); - crc2 = ~crc32_le(~0, skb2->data, skb2->len - - ETH_FCS_LEN); - } else { - crc = get_unaligned_be32(skb2->data - + len - ETH_FCS_LEN); + if (header & BIT(14)) + crc2 = ~crc32_le(~0, skb2->data, skb2->len); + else crc2 = 0xdeadbeef; - } - skb_trim(skb2, len - ETH_FCS_LEN); if (is_last) return crc == crc2; diff --git a/trunk/drivers/net/virtio_net.c b/trunk/drivers/net/virtio_net.c index 5c498d2b043f..32266fb89c20 100644 --- a/trunk/drivers/net/virtio_net.c +++ b/trunk/drivers/net/virtio_net.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -321,7 +320,7 @@ static bool try_fill_recv_maxbufs(struct virtnet_info *vi, gfp_t gfp) skb_queue_head(&vi->recv, skb); err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, num, skb); - if (err < 0) { + if (err) { skb_unlink(skb, &vi->recv); trim_pages(vi, skb); kfree_skb(skb); @@ -374,7 +373,7 @@ static bool try_fill_recv(struct virtnet_info *vi, gfp_t gfp) skb_queue_head(&vi->recv, skb); err = vi->rvq->vq_ops->add_buf(vi->rvq, sg, 0, 1, skb); - if (err < 0) { + if (err) { skb_unlink(skb, &vi->recv); kfree_skb(skb); break; @@ -528,7 +527,7 @@ static int xmit_skb(struct virtnet_info *vi, struct sk_buff *skb) num = skb_to_sgvec(skb, sg+1, 0, skb->len) + 1; err = vi->svq->vq_ops->add_buf(vi->svq, sg, num, 0, skb); - if (err >= 0 && !vi->free_in_tasklet) + if (!err && !vi->free_in_tasklet) mod_timer(&vi->xmit_free_timer, jiffies + (HZ/10)); return err; @@ -539,7 +538,7 @@ static void xmit_tasklet(unsigned long data) struct virtnet_info *vi = (void *)data; netif_tx_lock_bh(vi->dev); - if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) >= 0) { + if (vi->last_xmit_skb && xmit_skb(vi, vi->last_xmit_skb) == 0) { vi->svq->vq_ops->kick(vi->svq); vi->last_xmit_skb = NULL; } @@ -558,7 +557,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) /* If we has a buffer left over from last time, send it now. */ if (unlikely(vi->last_xmit_skb) && - xmit_skb(vi, vi->last_xmit_skb) < 0) + xmit_skb(vi, vi->last_xmit_skb) != 0) goto stop_queue; vi->last_xmit_skb = NULL; @@ -566,7 +565,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev) /* Put new one in send queue and do transmit */ if (likely(skb)) { __skb_queue_head(&vi->send, skb); - if (xmit_skb(vi, skb) < 0) { + if (xmit_skb(vi, skb) != 0) { vi->last_xmit_skb = skb; skb = NULL; goto stop_queue; @@ -669,7 +668,7 @@ static bool virtnet_send_command(struct virtnet_info *vi, u8 class, u8 cmd, sg_set_buf(&sg[i + 1], sg_virt(s), s->length); sg_set_buf(&sg[out + in - 1], &status, sizeof(status)); - BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi) < 0); + BUG_ON(vi->cvq->vq_ops->add_buf(vi->cvq, sg, out, in, vi)); vi->cvq->vq_ops->kick(vi->cvq); diff --git a/trunk/drivers/net/wireless/libertas/if_spi.c b/trunk/drivers/net/wireless/libertas/if_spi.c index cb8be8d7abc1..446e327180f8 100644 --- a/trunk/drivers/net/wireless/libertas/if_spi.c +++ b/trunk/drivers/net/wireless/libertas/if_spi.c @@ -1222,4 +1222,3 @@ MODULE_DESCRIPTION("Libertas SPI WLAN Driver"); MODULE_AUTHOR("Andrey Yurovsky , " "Colin McCabe "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:libertas_spi"); diff --git a/trunk/drivers/net/wireless/p54/p54spi.c b/trunk/drivers/net/wireless/p54/p54spi.c index afd26bf06649..05458d9249ce 100644 --- a/trunk/drivers/net/wireless/p54/p54spi.c +++ b/trunk/drivers/net/wireless/p54/p54spi.c @@ -731,4 +731,3 @@ module_exit(p54spi_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Christian Lamparter "); -MODULE_ALIAS("spi:cx3110x"); diff --git a/trunk/drivers/net/wireless/wl12xx/wl1251_main.c b/trunk/drivers/net/wireless/wl12xx/wl1251_main.c index 1103256ad989..5809ef5b18f8 100644 --- a/trunk/drivers/net/wireless/wl12xx/wl1251_main.c +++ b/trunk/drivers/net/wireless/wl12xx/wl1251_main.c @@ -1426,4 +1426,3 @@ EXPORT_SYMBOL_GPL(wl1251_free_hw); MODULE_DESCRIPTION("TI wl1251 Wireles LAN Driver Core"); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kalle Valo "); -MODULE_ALIAS("spi:wl12xx"); diff --git a/trunk/drivers/of/base.c b/trunk/drivers/of/base.c index ddf224d456b2..69f85c07d17f 100644 --- a/trunk/drivers/of/base.c +++ b/trunk/drivers/of/base.c @@ -447,6 +447,7 @@ struct of_modalias_table { static struct of_modalias_table of_modalias_table[] = { { "fsl,mcu-mpc8349emitx", "mcu-mpc8349emitx" }, { "mmc-spi-slot", "mmc_spi" }, + { "stm,m25p40", "m25p80" }, }; /** diff --git a/trunk/drivers/pci/dmar.c b/trunk/drivers/pci/dmar.c index 14bbaa17e2ca..ab99783dccec 100644 --- a/trunk/drivers/pci/dmar.c +++ b/trunk/drivers/pci/dmar.c @@ -34,9 +34,9 @@ #include #include #include -#include -#define PREFIX "DMAR: " +#undef PREFIX +#define PREFIX "DMAR:" /* No locks are needed as DMA remapping hardware unit * list is constructed at boot time and hotplug of @@ -577,6 +577,9 @@ int __init dmar_table_init(void) printk(KERN_INFO PREFIX "No ATSR found\n"); #endif +#ifdef CONFIG_INTR_REMAP + parse_ioapics_under_ir(); +#endif return 0; } @@ -636,31 +639,20 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) iommu->cap = dmar_readq(iommu->reg + DMAR_CAP_REG); iommu->ecap = dmar_readq(iommu->reg + DMAR_ECAP_REG); - if (iommu->cap == (uint64_t)-1 && iommu->ecap == (uint64_t)-1) { - /* Promote an attitude of violence to a BIOS engineer today */ - WARN(1, "Your BIOS is broken; DMAR reported at address %llx returns all ones!\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - drhd->reg_base_addr, - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); - goto err_unmap; - } - #ifdef CONFIG_DMAR agaw = iommu_calculate_agaw(iommu); if (agaw < 0) { printk(KERN_ERR "Cannot get a valid agaw for iommu (seq_id = %d)\n", iommu->seq_id); - goto err_unmap; + goto error; } msagaw = iommu_calculate_max_sagaw(iommu); if (msagaw < 0) { printk(KERN_ERR "Cannot get a valid max agaw for iommu (seq_id = %d)\n", iommu->seq_id); - goto err_unmap; + goto error; } #endif iommu->agaw = agaw; @@ -680,7 +672,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) } ver = readl(iommu->reg + DMAR_VER_REG); - pr_info("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", + pr_debug("IOMMU %llx: ver %d:%d cap %llx ecap %llx\n", (unsigned long long)drhd->reg_base_addr, DMAR_VER_MAJOR(ver), DMAR_VER_MINOR(ver), (unsigned long long)iommu->cap, @@ -690,10 +682,7 @@ int alloc_iommu(struct dmar_drhd_unit *drhd) drhd->iommu = iommu; return 0; - - err_unmap: - iounmap(iommu->reg); - error: +error: kfree(iommu); return -1; } @@ -1230,7 +1219,7 @@ irqreturn_t dmar_fault(int irq, void *dev_id) source_id, guest_addr); fault_index++; - if (fault_index >= cap_num_fault_regs(iommu->cap)) + if (fault_index > cap_num_fault_regs(iommu->cap)) fault_index = 0; spin_lock_irqsave(&iommu->register_lock, flag); } @@ -1323,13 +1312,3 @@ int dmar_reenable_qi(struct intel_iommu *iommu) return 0; } - -/* - * Check interrupt remapping support in DMAR table description. - */ -int dmar_ir_support(void) -{ - struct acpi_table_dmar *dmar; - dmar = (struct acpi_table_dmar *)dmar_tbl; - return dmar->flags & 0x1; -} diff --git a/trunk/drivers/pci/hotplug/acpiphp_ibm.c b/trunk/drivers/pci/hotplug/acpiphp_ibm.c index a9d926b7d805..5befa7e379b7 100644 --- a/trunk/drivers/pci/hotplug/acpiphp_ibm.c +++ b/trunk/drivers/pci/hotplug/acpiphp_ibm.c @@ -398,21 +398,23 @@ static acpi_status __init ibm_find_acpi_device(acpi_handle handle, acpi_handle *phandle = (acpi_handle *)context; acpi_status status; struct acpi_device_info *info; + struct acpi_buffer info_buffer = { ACPI_ALLOCATE_BUFFER, NULL }; int retval = 0; - status = acpi_get_object_info(handle, &info); + status = acpi_get_object_info(handle, &info_buffer); if (ACPI_FAILURE(status)) { err("%s: Failed to get device information status=0x%x\n", __func__, status); return retval; } - info->hardware_id.string[sizeof(info->hardware_id.length) - 1] = '\0'; + info = info_buffer.pointer; + info->hardware_id.value[sizeof(info->hardware_id.value) - 1] = '\0'; if (info->current_status && (info->valid & ACPI_VALID_HID) && - (!strcmp(info->hardware_id.string, IBM_HARDWARE_ID1) || - !strcmp(info->hardware_id.string, IBM_HARDWARE_ID2))) { + (!strcmp(info->hardware_id.value, IBM_HARDWARE_ID1) || + !strcmp(info->hardware_id.value, IBM_HARDWARE_ID2))) { dbg("found hardware: %s, handle: %p\n", - info->hardware_id.string, handle); + info->hardware_id.value, handle); *phandle = handle; /* returning non-zero causes the search to stop * and returns this value to the caller of diff --git a/trunk/drivers/pci/intel-iommu.c b/trunk/drivers/pci/intel-iommu.c index 855dd7ca47f3..562221e11917 100644 --- a/trunk/drivers/pci/intel-iommu.c +++ b/trunk/drivers/pci/intel-iommu.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include "pci.h" @@ -57,14 +56,8 @@ #define MAX_AGAW_WIDTH 64 -#define __DOMAIN_MAX_PFN(gaw) ((((uint64_t)1) << (gaw-VTD_PAGE_SHIFT)) - 1) -#define __DOMAIN_MAX_ADDR(gaw) ((((uint64_t)1) << gaw) - 1) - -/* We limit DOMAIN_MAX_PFN to fit in an unsigned long, and DOMAIN_MAX_ADDR - to match. That way, we can use 'unsigned long' for PFNs with impunity. */ -#define DOMAIN_MAX_PFN(gaw) ((unsigned long) min_t(uint64_t, \ - __DOMAIN_MAX_PFN(gaw), (unsigned long)-1)) -#define DOMAIN_MAX_ADDR(gaw) (((uint64_t)__DOMAIN_MAX_PFN(gaw)) << VTD_PAGE_SHIFT) +#define DOMAIN_MAX_ADDR(gaw) ((((u64)1) << gaw) - 1) +#define DOMAIN_MAX_PFN(gaw) ((((u64)1) << (gaw-VTD_PAGE_SHIFT)) - 1) #define IOVA_PFN(addr) ((addr) >> PAGE_SHIFT) #define DMA_32BIT_PFN IOVA_PFN(DMA_BIT_MASK(32)) @@ -259,8 +252,7 @@ static inline int first_pte_in_page(struct dma_pte *pte) * 2. It maps to each iommu if successful. * 3. Each iommu mapps to this domain if successful. */ -static struct dmar_domain *si_domain; -static int hw_pass_through = 1; +struct dmar_domain *si_domain; /* devices under the same p2p bridge are owned in one domain */ #define DOMAIN_FLAG_P2P_MULTIPLE_DEVICES (1 << 0) @@ -736,7 +728,7 @@ static struct dma_pte *pfn_to_dma_pte(struct dmar_domain *domain, return NULL; domain_flush_cache(domain, tmp_page, VTD_PAGE_SIZE); - pteval = ((uint64_t)virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; + pteval = (virt_to_dma_pfn(tmp_page) << VTD_PAGE_SHIFT) | DMA_PTE_READ | DMA_PTE_WRITE; if (cmpxchg64(&pte->val, 0ULL, pteval)) { /* Someone else set it while we were thinking; use theirs. */ free_pgtable_page(tmp_page); @@ -786,10 +778,9 @@ static void dma_pte_clear_range(struct dmar_domain *domain, BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); - BUG_ON(start_pfn > last_pfn); /* we don't need lock here; nobody else touches the iova range */ - do { + while (start_pfn <= last_pfn) { first_pte = pte = dma_pfn_level_pte(domain, start_pfn, 1); if (!pte) { start_pfn = align_to_level(start_pfn + 1, 2); @@ -803,8 +794,7 @@ static void dma_pte_clear_range(struct dmar_domain *domain, domain_flush_cache(domain, first_pte, (void *)pte - (void *)first_pte); - - } while (start_pfn && start_pfn <= last_pfn); + } } /* free page table pages. last level pte should already be cleared */ @@ -820,7 +810,6 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, BUG_ON(addr_width < BITS_PER_LONG && start_pfn >> addr_width); BUG_ON(addr_width < BITS_PER_LONG && last_pfn >> addr_width); - BUG_ON(start_pfn > last_pfn); /* We don't need lock here; nobody else touches the iova range */ level = 2; @@ -831,7 +820,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, if (tmp + level_size(level) - 1 > last_pfn) return; - do { + while (tmp + level_size(level) - 1 <= last_pfn) { first_pte = pte = dma_pfn_level_pte(domain, tmp, level); if (!pte) { tmp = align_to_level(tmp + 1, level + 1); @@ -850,7 +839,7 @@ static void dma_pte_free_pagetable(struct dmar_domain *domain, domain_flush_cache(domain, first_pte, (void *)pte - (void *)first_pte); - } while (tmp && tmp + level_size(level) - 1 <= last_pfn); + } level++; } /* free pgd */ @@ -1169,8 +1158,6 @@ static int iommu_init_domains(struct intel_iommu *iommu) pr_debug("Number of Domains supportd <%ld>\n", ndomains); nlongs = BITS_TO_LONGS(ndomains); - spin_lock_init(&iommu->lock); - /* TBD: there might be 64K domains, * consider other allocation for future chip */ @@ -1183,9 +1170,12 @@ static int iommu_init_domains(struct intel_iommu *iommu) GFP_KERNEL); if (!iommu->domains) { printk(KERN_ERR "Allocating domain array failed\n"); + kfree(iommu->domain_ids); return -ENOMEM; } + spin_lock_init(&iommu->lock); + /* * if Caching mode is set, then invalid translations are tagged * with domainid 0. Hence we need to pre-allocate it. @@ -1205,24 +1195,22 @@ void free_dmar_iommu(struct intel_iommu *iommu) int i; unsigned long flags; - if ((iommu->domains) && (iommu->domain_ids)) { - i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); - for (; i < cap_ndoms(iommu->cap); ) { - domain = iommu->domains[i]; - clear_bit(i, iommu->domain_ids); - - spin_lock_irqsave(&domain->iommu_lock, flags); - if (--domain->iommu_count == 0) { - if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) - vm_domain_exit(domain); - else - domain_exit(domain); - } - spin_unlock_irqrestore(&domain->iommu_lock, flags); + i = find_first_bit(iommu->domain_ids, cap_ndoms(iommu->cap)); + for (; i < cap_ndoms(iommu->cap); ) { + domain = iommu->domains[i]; + clear_bit(i, iommu->domain_ids); - i = find_next_bit(iommu->domain_ids, - cap_ndoms(iommu->cap), i+1); + spin_lock_irqsave(&domain->iommu_lock, flags); + if (--domain->iommu_count == 0) { + if (domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) + vm_domain_exit(domain); + else + domain_exit(domain); } + spin_unlock_irqrestore(&domain->iommu_lock, flags); + + i = find_next_bit(iommu->domain_ids, + cap_ndoms(iommu->cap), i+1); } if (iommu->gcmd & DMA_GCMD_TE) @@ -1322,6 +1310,7 @@ static void iommu_detach_domain(struct dmar_domain *domain, } static struct iova_domain reserved_iova_list; +static struct lock_class_key reserved_alloc_key; static struct lock_class_key reserved_rbtree_key; static void dmar_init_reserved_ranges(void) @@ -1332,6 +1321,8 @@ static void dmar_init_reserved_ranges(void) init_iova_domain(&reserved_iova_list, DMA_32BIT_PFN); + lockdep_set_class(&reserved_iova_list.iova_alloc_lock, + &reserved_alloc_key); lockdep_set_class(&reserved_iova_list.iova_rbtree_lock, &reserved_rbtree_key); @@ -1968,34 +1959,13 @@ static int iommu_prepare_identity_map(struct pci_dev *pdev, struct dmar_domain *domain; int ret; - domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); - if (!domain) - return -ENOMEM; - - /* For _hardware_ passthrough, don't bother. But for software - passthrough, we do it anyway -- it may indicate a memory - range which is reserved in E820, so which didn't get set - up to start with in si_domain */ - if (domain == si_domain && hw_pass_through) { - printk("Ignoring identity map for HW passthrough device %s [0x%Lx - 0x%Lx]\n", - pci_name(pdev), start, end); - return 0; - } - printk(KERN_INFO "IOMMU: Setting identity map for device %s [0x%Lx - 0x%Lx]\n", pci_name(pdev), start, end); - - if (end >> agaw_to_width(domain->agaw)) { - WARN(1, "Your BIOS is broken; RMRR exceeds permitted address width (%d bits)\n" - "BIOS vendor: %s; Ver: %s; Product Version: %s\n", - agaw_to_width(domain->agaw), - dmi_get_system_info(DMI_BIOS_VENDOR), - dmi_get_system_info(DMI_BIOS_VERSION), - dmi_get_system_info(DMI_PRODUCT_VERSION)); - ret = -EIO; - goto error; - } + + domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); + if (!domain) + return -ENOMEM; ret = iommu_domain_identity_map(domain, start, end); if (ret) @@ -2047,6 +2017,23 @@ static inline void iommu_prepare_isa(void) } #endif /* !CONFIG_DMAR_FLPY_WA */ +/* Initialize each context entry as pass through.*/ +static int __init init_context_pass_through(void) +{ + struct pci_dev *pdev = NULL; + struct dmar_domain *domain; + int ret; + + for_each_pci_dev(pdev) { + domain = get_domain_for_dev(pdev, DEFAULT_DOMAIN_ADDRESS_WIDTH); + ret = domain_context_mapping(domain, pdev, + CONTEXT_TT_PASS_THROUGH); + if (ret) + return ret; + } + return 0; +} + static int md_domain_init(struct dmar_domain *domain, int guest_width); static int __init si_domain_work_fn(unsigned long start_pfn, @@ -2061,7 +2048,7 @@ static int __init si_domain_work_fn(unsigned long start_pfn, } -static int __init si_domain_init(int hw) +static int si_domain_init(void) { struct dmar_drhd_unit *drhd; struct intel_iommu *iommu; @@ -2088,9 +2075,6 @@ static int __init si_domain_init(int hw) si_domain->flags = DOMAIN_FLAG_STATIC_IDENTITY; - if (hw) - return 0; - for_each_online_node(nid) { work_with_active_regions(nid, si_domain_work_fn, &ret); if (ret) @@ -2117,23 +2101,15 @@ static int identity_mapping(struct pci_dev *pdev) } static int domain_add_dev_info(struct dmar_domain *domain, - struct pci_dev *pdev, - int translation) + struct pci_dev *pdev) { struct device_domain_info *info; unsigned long flags; - int ret; info = alloc_devinfo_mem(); if (!info) return -ENOMEM; - ret = domain_context_mapping(domain, pdev, translation); - if (ret) { - free_devinfo_mem(info); - return ret; - } - info->segment = pci_domain_nr(pdev->bus); info->bus = pdev->bus->number; info->devfn = pdev->devfn; @@ -2190,25 +2166,27 @@ static int iommu_should_identity_map(struct pci_dev *pdev, int startup) return 1; } -static int __init iommu_prepare_static_identity_mapping(int hw) +static int iommu_prepare_static_identity_mapping(void) { struct pci_dev *pdev = NULL; int ret; - ret = si_domain_init(hw); + ret = si_domain_init(); if (ret) return -EFAULT; for_each_pci_dev(pdev) { if (iommu_should_identity_map(pdev, 1)) { - printk(KERN_INFO "IOMMU: %s identity mapping for device %s\n", - hw ? "hardware" : "software", pci_name(pdev)); + printk(KERN_INFO "IOMMU: identity mapping for device %s\n", + pci_name(pdev)); - ret = domain_add_dev_info(si_domain, pdev, - hw ? CONTEXT_TT_PASS_THROUGH : + ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL); if (ret) return ret; + ret = domain_add_dev_info(si_domain, pdev); + if (ret) + return ret; } } @@ -2222,6 +2200,14 @@ int __init init_dmars(void) struct pci_dev *pdev; struct intel_iommu *iommu; int i, ret; + int pass_through = 1; + + /* + * In case pass through can not be enabled, iommu tries to use identity + * mapping. + */ + if (iommu_pass_through) + iommu_identity_mapping = 1; /* * for each drhd @@ -2249,6 +2235,7 @@ int __init init_dmars(void) deferred_flush = kzalloc(g_num_of_iommus * sizeof(struct deferred_flush_tables), GFP_KERNEL); if (!deferred_flush) { + kfree(g_iommus); ret = -ENOMEM; goto error; } @@ -2275,8 +2262,14 @@ int __init init_dmars(void) goto error; } if (!ecap_pass_through(iommu->ecap)) - hw_pass_through = 0; + pass_through = 0; } + if (iommu_pass_through) + if (!pass_through) { + printk(KERN_INFO + "Pass Through is not supported by hardware.\n"); + iommu_pass_through = 0; + } /* * Start from the sane iommu hardware state. @@ -2331,56 +2324,63 @@ int __init init_dmars(void) } } - if (iommu_pass_through) - iommu_identity_mapping = 1; -#ifdef CONFIG_DMAR_BROKEN_GFX_WA - else - iommu_identity_mapping = 2; -#endif /* - * If pass through is not set or not enabled, setup context entries for - * identity mappings for rmrr, gfx, and isa and may fall back to static - * identity mapping if iommu_identity_mapping is set. + * If pass through is set and enabled, context entries of all pci + * devices are intialized by pass through translation type. */ - if (iommu_identity_mapping) { - ret = iommu_prepare_static_identity_mapping(hw_pass_through); + if (iommu_pass_through) { + ret = init_context_pass_through(); if (ret) { - printk(KERN_CRIT "Failed to setup IOMMU pass-through\n"); - goto error; + printk(KERN_ERR "IOMMU: Pass through init failed.\n"); + iommu_pass_through = 0; } } + /* - * For each rmrr - * for each dev attached to rmrr - * do - * locate drhd for dev, alloc domain for dev - * allocate free domain - * allocate page table entries for rmrr - * if context not allocated for bus - * allocate and init context - * set present in root table for this bus - * init context with domain, translation etc - * endfor - * endfor + * If pass through is not set or not enabled, setup context entries for + * identity mappings for rmrr, gfx, and isa and may fall back to static + * identity mapping if iommu_identity_mapping is set. */ - printk(KERN_INFO "IOMMU: Setting RMRR:\n"); - for_each_rmrr_units(rmrr) { - for (i = 0; i < rmrr->devices_cnt; i++) { - pdev = rmrr->devices[i]; - /* - * some BIOS lists non-exist devices in DMAR - * table. - */ - if (!pdev) - continue; - ret = iommu_prepare_rmrr_dev(rmrr, pdev); - if (ret) - printk(KERN_ERR - "IOMMU: mapping reserved region failed\n"); + if (!iommu_pass_through) { +#ifdef CONFIG_DMAR_BROKEN_GFX_WA + if (!iommu_identity_mapping) + iommu_identity_mapping = 2; +#endif + if (iommu_identity_mapping) + iommu_prepare_static_identity_mapping(); + /* + * For each rmrr + * for each dev attached to rmrr + * do + * locate drhd for dev, alloc domain for dev + * allocate free domain + * allocate page table entries for rmrr + * if context not allocated for bus + * allocate and init context + * set present in root table for this bus + * init context with domain, translation etc + * endfor + * endfor + */ + printk(KERN_INFO "IOMMU: Setting RMRR:\n"); + for_each_rmrr_units(rmrr) { + for (i = 0; i < rmrr->devices_cnt; i++) { + pdev = rmrr->devices[i]; + /* + * some BIOS lists non-exist devices in DMAR + * table. + */ + if (!pdev) + continue; + ret = iommu_prepare_rmrr_dev(rmrr, pdev); + if (ret) + printk(KERN_ERR + "IOMMU: mapping reserved region failed\n"); + } } - } - iommu_prepare_isa(); + iommu_prepare_isa(); + } /* * for each drhd @@ -2404,12 +2404,11 @@ int __init init_dmars(void) iommu->flush.flush_context(iommu, 0, 0, 0, DMA_CCMD_GLOBAL_INVL); iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH); + iommu_disable_protect_mem_regions(iommu); ret = iommu_enable_translation(iommu); if (ret) goto error; - - iommu_disable_protect_mem_regions(iommu); } return 0; @@ -2456,7 +2455,8 @@ static struct iova *intel_alloc_iova(struct device *dev, return iova; } -static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev) +static struct dmar_domain * +get_valid_domain_for_dev(struct pci_dev *pdev) { struct dmar_domain *domain; int ret; @@ -2484,18 +2484,6 @@ static struct dmar_domain *__get_valid_domain_for_dev(struct pci_dev *pdev) return domain; } -static inline struct dmar_domain *get_valid_domain_for_dev(struct pci_dev *dev) -{ - struct device_domain_info *info; - - /* No lock here, assumes no domain exit in normal case */ - info = dev->dev.archdata.iommu; - if (likely(info)) - return info->domain; - - return __get_valid_domain_for_dev(dev); -} - static int iommu_dummy(struct pci_dev *pdev) { return pdev->dev.archdata.iommu == DUMMY_DEVICE_DOMAIN_INFO; @@ -2538,10 +2526,10 @@ static int iommu_no_mapping(struct device *dev) */ if (iommu_should_identity_map(pdev, 0)) { int ret; - ret = domain_add_dev_info(si_domain, pdev, - hw_pass_through ? - CONTEXT_TT_PASS_THROUGH : - CONTEXT_TT_MULTI_LEVEL); + ret = domain_add_dev_info(si_domain, pdev); + if (ret) + return 0; + ret = domain_context_mapping(si_domain, pdev, CONTEXT_TT_MULTI_LEVEL); if (!ret) { printk(KERN_INFO "64bit %s uses identity mapping\n", pci_name(pdev)); @@ -2650,9 +2638,10 @@ static void flush_unmaps(void) unsigned long mask; struct iova *iova = deferred_flush[i].iova[j]; - mask = ilog2(mm_to_dma_pfn(iova->pfn_hi - iova->pfn_lo + 1)); + mask = (iova->pfn_hi - iova->pfn_lo + 1) << PAGE_SHIFT; + mask = ilog2(mask >> VTD_PAGE_SHIFT); iommu_flush_dev_iotlb(deferred_flush[i].domain[j], - (uint64_t)iova->pfn_lo << PAGE_SHIFT, mask); + iova->pfn_lo << PAGE_SHIFT, mask); __free_iova(&deferred_flush[i].domain[j]->iovad, iova); } deferred_flush[i].next = 0; @@ -2745,6 +2734,12 @@ static void intel_unmap_page(struct device *dev, dma_addr_t dev_addr, } } +static void intel_unmap_single(struct device *dev, dma_addr_t dev_addr, size_t size, + int dir) +{ + intel_unmap_page(dev, dev_addr, size, dir, NULL); +} + static void *intel_alloc_coherent(struct device *hwdev, size_t size, dma_addr_t *dma_handle, gfp_t flags) { @@ -2777,7 +2772,7 @@ static void intel_free_coherent(struct device *hwdev, size_t size, void *vaddr, size = PAGE_ALIGN(size); order = get_order(size); - intel_unmap_page(hwdev, dma_handle, size, DMA_BIDIRECTIONAL, NULL); + intel_unmap_single(hwdev, dma_handle, size, DMA_BIDIRECTIONAL); free_pages((unsigned long)vaddr, order); } @@ -2813,18 +2808,11 @@ static void intel_unmap_sg(struct device *hwdev, struct scatterlist *sglist, /* free page tables */ dma_pte_free_pagetable(domain, start_pfn, last_pfn); - if (intel_iommu_strict) { - iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, - last_pfn - start_pfn + 1); - /* free iova */ - __free_iova(&domain->iovad, iova); - } else { - add_unmap(domain, iova); - /* - * queue up the release of the unmap to save the 1/6th of the - * cpu used up by the iotlb flush operation... - */ - } + iommu_flush_iotlb_psi(iommu, domain->id, start_pfn, + (last_pfn - start_pfn + 1)); + + /* free iova */ + __free_iova(&domain->iovad, iova); } static int intel_nontranslate_map_sg(struct device *hddev, @@ -3068,8 +3056,8 @@ static int init_iommu_hw(void) DMA_CCMD_GLOBAL_INVL); iommu->flush.flush_iotlb(iommu, 0, 0, 0, DMA_TLB_GLOBAL_FLUSH); - iommu_enable_translation(iommu); iommu_disable_protect_mem_regions(iommu); + iommu_enable_translation(iommu); } return 0; @@ -3217,7 +3205,7 @@ int __init intel_iommu_init(void) * Check the need for DMA-remapping initialization now. * Above initialization will also be used by Interrupt-remapping. */ - if (no_iommu || swiotlb || dmar_disabled) + if (no_iommu || (swiotlb && !iommu_pass_through) || dmar_disabled) return -ENODEV; iommu_init_mempool(); @@ -3239,7 +3227,14 @@ int __init intel_iommu_init(void) init_timer(&unmap_timer); force_iommu = 1; - dma_ops = &intel_dma_ops; + + if (!iommu_pass_through) { + printk(KERN_INFO + "Multi-level page-table translation for DMAR.\n"); + dma_ops = &intel_dma_ops; + } else + printk(KERN_INFO + "DMAR: Pass through translation for DMAR.\n"); init_iommu_sysfs(); @@ -3522,6 +3517,7 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, struct intel_iommu *iommu; int addr_width; u64 end; + int ret; /* normally pdev is not mapped */ if (unlikely(domain_context_mapped(pdev))) { @@ -3553,7 +3549,12 @@ static int intel_iommu_attach_device(struct iommu_domain *domain, return -EFAULT; } - return domain_add_dev_info(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL); + ret = domain_add_dev_info(dmar_domain, pdev); + if (ret) + return ret; + + ret = domain_context_mapping(dmar_domain, pdev, CONTEXT_TT_MULTI_LEVEL); + return ret; } static void intel_iommu_detach_device(struct iommu_domain *domain, diff --git a/trunk/drivers/pci/intr_remapping.c b/trunk/drivers/pci/intr_remapping.c index 0ed78a764ded..44803644ca05 100644 --- a/trunk/drivers/pci/intr_remapping.c +++ b/trunk/drivers/pci/intr_remapping.c @@ -603,9 +603,6 @@ int __init intr_remapping_supported(void) if (disable_intremap) return 0; - if (!dmar_ir_support()) - return 0; - for_each_drhd_unit(drhd) { struct intel_iommu *iommu = drhd->iommu; @@ -621,11 +618,6 @@ int __init enable_intr_remapping(int eim) struct dmar_drhd_unit *drhd; int setup = 0; - if (parse_ioapics_under_ir() != 1) { - printk(KERN_INFO "Not enable interrupt remapping\n"); - return -1; - } - for_each_drhd_unit(drhd) { struct intel_iommu *iommu = drhd->iommu; diff --git a/trunk/drivers/pci/iova.c b/trunk/drivers/pci/iova.c index 7914951ef29a..46dd440e2315 100644 --- a/trunk/drivers/pci/iova.c +++ b/trunk/drivers/pci/iova.c @@ -22,6 +22,7 @@ void init_iova_domain(struct iova_domain *iovad, unsigned long pfn_32bit) { + spin_lock_init(&iovad->iova_alloc_lock); spin_lock_init(&iovad->iova_rbtree_lock); iovad->rbroot = RB_ROOT; iovad->cached32_node = NULL; @@ -204,6 +205,7 @@ alloc_iova(struct iova_domain *iovad, unsigned long size, unsigned long limit_pfn, bool size_aligned) { + unsigned long flags; struct iova *new_iova; int ret; @@ -217,9 +219,11 @@ alloc_iova(struct iova_domain *iovad, unsigned long size, if (size_aligned) size = __roundup_pow_of_two(size); + spin_lock_irqsave(&iovad->iova_alloc_lock, flags); ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn, new_iova, size_aligned); + spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags); if (ret) { free_iova_mem(new_iova); return NULL; @@ -377,7 +381,8 @@ reserve_iova(struct iova_domain *iovad, struct iova *iova; unsigned int overlap = 0; - spin_lock_irqsave(&iovad->iova_rbtree_lock, flags); + spin_lock_irqsave(&iovad->iova_alloc_lock, flags); + spin_lock(&iovad->iova_rbtree_lock); for (node = rb_first(&iovad->rbroot); node; node = rb_next(node)) { if (__is_range_overlap(node, pfn_lo, pfn_hi)) { iova = container_of(node, struct iova, node); @@ -397,7 +402,8 @@ reserve_iova(struct iova_domain *iovad, iova = __insert_new_range(iovad, pfn_lo, pfn_hi); finish: - spin_unlock_irqrestore(&iovad->iova_rbtree_lock, flags); + spin_unlock(&iovad->iova_rbtree_lock); + spin_unlock_irqrestore(&iovad->iova_alloc_lock, flags); return iova; } @@ -414,7 +420,8 @@ copy_reserved_iova(struct iova_domain *from, struct iova_domain *to) unsigned long flags; struct rb_node *node; - spin_lock_irqsave(&from->iova_rbtree_lock, flags); + spin_lock_irqsave(&from->iova_alloc_lock, flags); + spin_lock(&from->iova_rbtree_lock); for (node = rb_first(&from->rbroot); node; node = rb_next(node)) { struct iova *iova = container_of(node, struct iova, node); struct iova *new_iova; @@ -423,5 +430,6 @@ copy_reserved_iova(struct iova_domain *from, struct iova_domain *to) printk(KERN_ERR "Reserve iova range %lx@%lx failed\n", iova->pfn_lo, iova->pfn_lo); } - spin_unlock_irqrestore(&from->iova_rbtree_lock, flags); + spin_unlock(&from->iova_rbtree_lock); + spin_unlock_irqrestore(&from->iova_alloc_lock, flags); } diff --git a/trunk/drivers/platform/x86/Kconfig b/trunk/drivers/platform/x86/Kconfig index 55ca39dea42e..77c6097ced80 100644 --- a/trunk/drivers/platform/x86/Kconfig +++ b/trunk/drivers/platform/x86/Kconfig @@ -99,7 +99,6 @@ config FUJITSU_LAPTOP depends on ACPI depends on INPUT depends on BACKLIGHT_CLASS_DEVICE - depends on LEDS_CLASS || LEDS_CLASS=n ---help--- This is a driver for laptops built by Fujitsu: @@ -397,15 +396,6 @@ config ACPI_ASUS NOTE: This driver is deprecated and will probably be removed soon, use asus-laptop instead. -config TOPSTAR_LAPTOP - tristate "Topstar Laptop Extras" - depends on ACPI - depends on INPUT - ---help--- - This driver adds support for hotkeys found on Topstar laptops. - - If you have a Topstar laptop, say Y or M here. - config ACPI_TOSHIBA tristate "Toshiba Laptop Extras" depends on ACPI diff --git a/trunk/drivers/platform/x86/Makefile b/trunk/drivers/platform/x86/Makefile index d1c16210a512..641b8bfa5538 100644 --- a/trunk/drivers/platform/x86/Makefile +++ b/trunk/drivers/platform/x86/Makefile @@ -19,5 +19,4 @@ obj-$(CONFIG_PANASONIC_LAPTOP) += panasonic-laptop.o obj-$(CONFIG_INTEL_MENLOW) += intel_menlow.o obj-$(CONFIG_ACPI_WMI) += wmi.o obj-$(CONFIG_ACPI_ASUS) += asus_acpi.o -obj-$(CONFIG_TOPSTAR_LAPTOP) += topstar-laptop.o obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o diff --git a/trunk/drivers/platform/x86/acerhdf.c b/trunk/drivers/platform/x86/acerhdf.c index 0a8f735f6c4a..bdfee177eefb 100644 --- a/trunk/drivers/platform/x86/acerhdf.c +++ b/trunk/drivers/platform/x86/acerhdf.c @@ -52,7 +52,7 @@ */ #undef START_IN_KERNEL_MODE -#define DRV_VER "0.5.17" +#define DRV_VER "0.5.13" /* * According to the Atom N270 datasheet, @@ -90,7 +90,6 @@ static unsigned int fanoff = 58; static unsigned int verbose; static unsigned int fanstate = ACERHDF_FAN_AUTO; static char force_bios[16]; -static char force_product[16]; static unsigned int prev_interval; struct thermal_zone_device *thz_dev; struct thermal_cooling_device *cl_dev; @@ -108,62 +107,34 @@ module_param(verbose, uint, 0600); MODULE_PARM_DESC(verbose, "Enable verbose dmesg output"); module_param_string(force_bios, force_bios, 16, 0); MODULE_PARM_DESC(force_bios, "Force BIOS version and omit BIOS check"); -module_param_string(force_product, force_product, 16, 0); -MODULE_PARM_DESC(force_product, "Force BIOS product and omit BIOS check"); - -/* - * cmd_off: to switch the fan completely off / to check if the fan is off - * cmd_auto: to set the BIOS in control of the fan. The BIOS regulates then - * the fan speed depending on the temperature - */ -struct fancmd { - u8 cmd_off; - u8 cmd_auto; -}; /* BIOS settings */ struct bios_settings_t { const char *vendor; - const char *product; const char *version; unsigned char fanreg; unsigned char tempreg; - struct fancmd cmd; + unsigned char fancmd[2]; /* fan off and auto commands */ }; /* Register addresses and values for different BIOS versions */ static const struct bios_settings_t bios_tbl[] = { - /* AOA110 */ - {"Acer", "AOA110", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, - {"Acer", "AOA110", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, - {"Acer", "AOA110", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3307", 0x55, 0x58, {0xaf, 0x00} }, - {"Acer", "AOA110", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, - {"Acer", "AOA110", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, - {"Acer", "AOA110", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, - /* AOA150 */ - {"Acer", "AOA150", "v0.3114", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3301", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3304", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3305", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3307", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3308", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3309", 0x55, 0x58, {0x20, 0x00} }, - {"Acer", "AOA150", "v0.3310", 0x55, 0x58, {0x20, 0x00} }, - /* special BIOS / other */ - {"Gateway", "AOA110", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, - {"Gateway", "AOA150", "v0.3103", 0x55, 0x58, {0x20, 0x00} }, - {"Packard Bell", "DOA150", "v0.3104", 0x55, 0x58, {0x21, 0x00} }, - {"Packard Bell", "AOA110", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, - {"Packard Bell", "AOA150", "v0.3105", 0x55, 0x58, {0x20, 0x00} }, - /* pewpew-terminator */ - {"", "", "", 0, 0, {0, 0} } + {"Acer", "v0.3109", 0x55, 0x58, {0x1f, 0x00} }, + {"Acer", "v0.3114", 0x55, 0x58, {0x1f, 0x00} }, + {"Acer", "v0.3301", 0x55, 0x58, {0xaf, 0x00} }, + {"Acer", "v0.3304", 0x55, 0x58, {0xaf, 0x00} }, + {"Acer", "v0.3305", 0x55, 0x58, {0xaf, 0x00} }, + {"Acer", "v0.3308", 0x55, 0x58, {0x21, 0x00} }, + {"Acer", "v0.3309", 0x55, 0x58, {0x21, 0x00} }, + {"Acer", "v0.3310", 0x55, 0x58, {0x21, 0x00} }, + {"Gateway", "v0.3103", 0x55, 0x58, {0x21, 0x00} }, + {"Packard Bell", "v0.3105", 0x55, 0x58, {0x21, 0x00} }, + {"", "", 0, 0, {0, 0} } }; static const struct bios_settings_t *bios_cfg __read_mostly; + static int acerhdf_get_temp(int *temp) { u8 read_temp; @@ -179,14 +150,13 @@ static int acerhdf_get_temp(int *temp) static int acerhdf_get_fanstate(int *state) { u8 fan; + bool tmp; if (ec_read(bios_cfg->fanreg, &fan)) return -EINVAL; - if (fan != bios_cfg->cmd.cmd_off) - *state = ACERHDF_FAN_AUTO; - else - *state = ACERHDF_FAN_OFF; + tmp = (fan == bios_cfg->fancmd[ACERHDF_FAN_OFF]); + *state = tmp ? ACERHDF_FAN_OFF : ACERHDF_FAN_AUTO; return 0; } @@ -205,8 +175,7 @@ static void acerhdf_change_fanstate(int state) state = ACERHDF_FAN_AUTO; } - cmd = (state == ACERHDF_FAN_OFF) ? bios_cfg->cmd.cmd_off - : bios_cfg->cmd.cmd_auto; + cmd = bios_cfg->fancmd[state]; fanstate = state; ec_write(bios_cfg->fanreg, cmd); @@ -439,7 +408,7 @@ struct thermal_cooling_device_ops acerhdf_cooling_ops = { }; /* suspend / resume functionality */ -static int acerhdf_suspend(struct device *dev) +static int acerhdf_suspend(struct platform_device *dev, pm_message_t state) { if (kernelmode) acerhdf_change_fanstate(ACERHDF_FAN_AUTO); @@ -450,6 +419,14 @@ static int acerhdf_suspend(struct device *dev) return 0; } +static int acerhdf_resume(struct platform_device *device) +{ + if (verbose) + pr_notice("resuming\n"); + + return 0; +} + static int __devinit acerhdf_probe(struct platform_device *device) { return 0; @@ -460,19 +437,15 @@ static int acerhdf_remove(struct platform_device *device) return 0; } -static struct dev_pm_ops acerhdf_pm_ops = { - .suspend = acerhdf_suspend, - .freeze = acerhdf_suspend, -}; - -static struct platform_driver acerhdf_driver = { +struct platform_driver acerhdf_drv = { .driver = { - .name = "acerhdf", + .name = "acerhdf", .owner = THIS_MODULE, - .pm = &acerhdf_pm_ops, }, .probe = acerhdf_probe, .remove = acerhdf_remove, + .suspend = acerhdf_suspend, + .resume = acerhdf_resume, }; @@ -481,40 +454,32 @@ static int acerhdf_check_hardware(void) { char const *vendor, *version, *product; int i; - unsigned long prod_len = 0; /* get BIOS data */ vendor = dmi_get_system_info(DMI_SYS_VENDOR); version = dmi_get_system_info(DMI_BIOS_VERSION); product = dmi_get_system_info(DMI_PRODUCT_NAME); - pr_info("Acer Aspire One Fan driver, v.%s\n", DRV_VER); - if (force_bios[0]) { - version = force_bios; + if (!force_bios[0]) { + if (strncmp(product, "AO", 2)) { + pr_err("no Aspire One hardware found\n"); + return -EINVAL; + } + } else { pr_info("forcing BIOS version: %s\n", version); + version = force_bios; kernelmode = 0; } - if (force_product[0]) { - product = force_product; - pr_info("forcing BIOS product: %s\n", product); - kernelmode = 0; - } - - prod_len = strlen(product); - if (verbose) pr_info("BIOS info: %s %s, product: %s\n", vendor, version, product); /* search BIOS version and vendor in BIOS settings table */ for (i = 0; bios_tbl[i].version[0]; i++) { - if (strlen(bios_tbl[i].product) >= prod_len && - !strncmp(bios_tbl[i].product, product, - strlen(bios_tbl[i].product)) && - !strcmp(bios_tbl[i].vendor, vendor) && + if (!strcmp(bios_tbl[i].vendor, vendor) && !strcmp(bios_tbl[i].version, version)) { bios_cfg = &bios_tbl[i]; break; @@ -522,8 +487,8 @@ static int acerhdf_check_hardware(void) } if (!bios_cfg) { - pr_err("unknown (unsupported) BIOS version %s/%s/%s, " - "please report, aborting!\n", vendor, product, version); + pr_err("unknown (unsupported) BIOS version %s/%s, " + "please report, aborting!\n", vendor, version); return -EINVAL; } @@ -544,7 +509,7 @@ static int acerhdf_register_platform(void) { int err = 0; - err = platform_driver_register(&acerhdf_driver); + err = platform_driver_register(&acerhdf_drv); if (err) return err; @@ -560,7 +525,7 @@ static void acerhdf_unregister_platform(void) return; platform_device_del(acerhdf_dev); - platform_driver_unregister(&acerhdf_driver); + platform_driver_unregister(&acerhdf_drv); } static int acerhdf_register_thermal(void) diff --git a/trunk/drivers/platform/x86/asus-laptop.c b/trunk/drivers/platform/x86/asus-laptop.c index b39d2bb3e75b..db657bbeec90 100644 --- a/trunk/drivers/platform/x86/asus-laptop.c +++ b/trunk/drivers/platform/x86/asus-laptop.c @@ -77,16 +77,15 @@ * Flags for hotk status * WL_ON and BT_ON are also used for wireless_status() */ -#define WL_ON 0x01 /* internal Wifi */ -#define BT_ON 0x02 /* internal Bluetooth */ -#define MLED_ON 0x04 /* mail LED */ -#define TLED_ON 0x08 /* touchpad LED */ -#define RLED_ON 0x10 /* Record LED */ -#define PLED_ON 0x20 /* Phone LED */ -#define GLED_ON 0x40 /* Gaming LED */ -#define LCD_ON 0x80 /* LCD backlight */ -#define GPS_ON 0x100 /* GPS */ -#define KEY_ON 0x200 /* Keyboard backlight */ +#define WL_ON 0x01 //internal Wifi +#define BT_ON 0x02 //internal Bluetooth +#define MLED_ON 0x04 //mail LED +#define TLED_ON 0x08 //touchpad LED +#define RLED_ON 0x10 //Record LED +#define PLED_ON 0x20 //Phone LED +#define GLED_ON 0x40 //Gaming LED +#define LCD_ON 0x80 //LCD backlight +#define GPS_ON 0x100 //GPS #define ASUS_LOG ASUS_HOTK_FILE ": " #define ASUS_ERR KERN_ERR ASUS_LOG @@ -99,8 +98,7 @@ MODULE_AUTHOR("Julien Lerouge, Karol Kozimor, Corentin Chary"); MODULE_DESCRIPTION(ASUS_HOTK_NAME); MODULE_LICENSE("GPL"); -/* - * WAPF defines the behavior of the Fn+Fx wlan key +/* WAPF defines the behavior of the Fn+Fx wlan key * The significance of values is yet to be found, but * most of the time: * 0x0 will do nothing @@ -127,8 +125,7 @@ ASUS_HANDLE(gled_set, ASUS_HOTK_PREFIX "GLED"); /* G1, G2 (probably) */ /* LEDD */ ASUS_HANDLE(ledd_set, ASUS_HOTK_PREFIX "SLCM"); -/* - * Bluetooth and WLAN +/* Bluetooth and WLAN * WLED and BLED are not handled like other XLED, because in some dsdt * they also control the WLAN/Bluetooth device. */ @@ -152,32 +149,22 @@ ASUS_HANDLE(lcd_switch, "\\_SB.PCI0.SBRG.EC0._Q10", /* All new models */ /* Display */ ASUS_HANDLE(display_set, ASUS_HOTK_PREFIX "SDSP"); -ASUS_HANDLE(display_get, - /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */ - "\\_SB.PCI0.P0P1.VGA.GETD", - /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */ - "\\_SB.PCI0.P0P2.VGA.GETD", - /* A6V A6Q */ - "\\_SB.PCI0.P0P3.VGA.GETD", - /* A6T, A6M */ - "\\_SB.PCI0.P0PA.VGA.GETD", - /* L3C */ - "\\_SB.PCI0.PCI1.VGAC.NMAP", - /* Z96F */ - "\\_SB.PCI0.VGA.GETD", - /* A2D */ - "\\ACTD", - /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ - "\\ADVG", - /* P30 */ - "\\DNXT", - /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ - "\\INFB", - /* A3F A6F A3N A3L M6N W3N W6A */ - "\\SSTE"); - -ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ -ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ +ASUS_HANDLE(display_get, "\\_SB.PCI0.P0P1.VGA.GETD", /* A6B, A6K A6R A7D F3JM L4R M6R A3G + M6A M6V VX-1 V6J V6V W3Z */ + "\\_SB.PCI0.P0P2.VGA.GETD", /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V + S5A M5A z33A W1Jc W2V G1 */ + "\\_SB.PCI0.P0P3.VGA.GETD", /* A6V A6Q */ + "\\_SB.PCI0.P0PA.VGA.GETD", /* A6T, A6M */ + "\\_SB.PCI0.PCI1.VGAC.NMAP", /* L3C */ + "\\_SB.PCI0.VGA.GETD", /* Z96F */ + "\\ACTD", /* A2D */ + "\\ADVG", /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */ + "\\DNXT", /* P30 */ + "\\INFB", /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */ + "\\SSTE"); /* A3F A6F A3N A3L M6N W3N W6A */ + +ASUS_HANDLE(ls_switch, ASUS_HOTK_PREFIX "ALSC"); /* Z71A Z71V */ +ASUS_HANDLE(ls_level, ASUS_HOTK_PREFIX "ALSL"); /* Z71A Z71V */ /* GPS */ /* R2H use different handle for GPS on/off */ @@ -185,23 +172,19 @@ ASUS_HANDLE(gps_on, ASUS_HOTK_PREFIX "SDON"); /* R2H */ ASUS_HANDLE(gps_off, ASUS_HOTK_PREFIX "SDOF"); /* R2H */ ASUS_HANDLE(gps_status, ASUS_HOTK_PREFIX "GPST"); -/* Keyboard light */ -ASUS_HANDLE(kled_set, ASUS_HOTK_PREFIX "SLKB"); -ASUS_HANDLE(kled_get, ASUS_HOTK_PREFIX "GLKB"); - /* * This is the main structure, we can use it to store anything interesting * about the hotk device */ struct asus_hotk { - char *name; /* laptop name */ - struct acpi_device *device; /* the device we are in */ - acpi_handle handle; /* the handle of the hotk device */ - char status; /* status of the hotk, for LEDs, ... */ - u32 ledd_status; /* status of the LED display */ - u8 light_level; /* light sensor level */ - u8 light_switch; /* light sensor switch value */ - u16 event_count[128]; /* count for each event TODO make this better */ + char *name; //laptop name + struct acpi_device *device; //the device we are in + acpi_handle handle; //the handle of the hotk device + char status; //status of the hotk, for LEDs, ... + u32 ledd_status; //status of the LED display + u8 light_level; //light sensor level + u8 light_switch; //light sensor switch value + u16 event_count[128]; //count for each event TODO make this better struct input_dev *inputdev; u16 *keycode_map; }; @@ -254,35 +237,28 @@ static struct backlight_ops asusbl_ops = { .update_status = update_bl_status, }; -/* - * These functions actually update the LED's, and are called from a +/* These functions actually update the LED's, and are called from a * workqueue. By doing this as separate work rather than when the LED * subsystem asks, we avoid messing with the Asus ACPI stuff during a - * potentially bad time, such as a timer interrupt. - */ + * potentially bad time, such as a timer interrupt. */ static struct workqueue_struct *led_workqueue; -#define ASUS_LED(object, ledname, max) \ +#define ASUS_LED(object, ledname) \ static void object##_led_set(struct led_classdev *led_cdev, \ enum led_brightness value); \ - static enum led_brightness object##_led_get( \ - struct led_classdev *led_cdev); \ static void object##_led_update(struct work_struct *ignored); \ static int object##_led_wk; \ static DECLARE_WORK(object##_led_work, object##_led_update); \ static struct led_classdev object##_led = { \ .name = "asus::" ledname, \ .brightness_set = object##_led_set, \ - .brightness_get = object##_led_get, \ - .max_brightness = max \ } -ASUS_LED(mled, "mail", 1); -ASUS_LED(tled, "touchpad", 1); -ASUS_LED(rled, "record", 1); -ASUS_LED(pled, "phone", 1); -ASUS_LED(gled, "gaming", 1); -ASUS_LED(kled, "kbd_backlight", 3); +ASUS_LED(mled, "mail"); +ASUS_LED(tled, "touchpad"); +ASUS_LED(rled, "record"); +ASUS_LED(pled, "phone"); +ASUS_LED(gled, "gaming"); struct key_entry { char type; @@ -302,23 +278,16 @@ static struct key_entry asus_keymap[] = { {KE_KEY, 0x41, KEY_NEXTSONG}, {KE_KEY, 0x43, KEY_STOPCD}, {KE_KEY, 0x45, KEY_PLAYPAUSE}, - {KE_KEY, 0x4c, KEY_MEDIA}, {KE_KEY, 0x50, KEY_EMAIL}, {KE_KEY, 0x51, KEY_WWW}, - {KE_KEY, 0x55, KEY_CALC}, {KE_KEY, 0x5C, KEY_SCREENLOCK}, /* Screenlock */ {KE_KEY, 0x5D, KEY_WLAN}, - {KE_KEY, 0x5E, KEY_WLAN}, - {KE_KEY, 0x5F, KEY_WLAN}, - {KE_KEY, 0x60, KEY_SWITCHVIDEOMODE}, {KE_KEY, 0x61, KEY_SWITCHVIDEOMODE}, {KE_KEY, 0x6B, BTN_TOUCH}, /* Lock Mouse */ {KE_KEY, 0x82, KEY_CAMERA}, {KE_KEY, 0x8A, KEY_PROG1}, {KE_KEY, 0x95, KEY_MEDIA}, {KE_KEY, 0x99, KEY_PHONE}, - {KE_KEY, 0xc4, KEY_KBDILLUMUP}, - {KE_KEY, 0xc5, KEY_KBDILLUMDOWN}, {KE_END, 0}, }; @@ -332,8 +301,8 @@ static struct key_entry asus_keymap[] = { static int write_acpi_int(acpi_handle handle, const char *method, int val, struct acpi_buffer *output) { - struct acpi_object_list params; /* list of input parameters (an int) */ - union acpi_object in_obj; /* the only param we use */ + struct acpi_object_list params; //list of input parameters (an int here) + union acpi_object in_obj; //the only param we use acpi_status status; if (!handle) @@ -430,11 +399,6 @@ static void write_status(acpi_handle handle, int out, int mask) { \ int value = object##_led_wk; \ write_status(object##_set_handle, value, (mask)); \ - } \ - static enum led_brightness object##_led_get( \ - struct led_classdev *led_cdev) \ - { \ - return led_cdev->brightness; \ } ASUS_LED_HANDLER(mled, MLED_ON); @@ -443,60 +407,6 @@ ASUS_LED_HANDLER(rled, RLED_ON); ASUS_LED_HANDLER(tled, TLED_ON); ASUS_LED_HANDLER(gled, GLED_ON); -/* - * Keyboard backlight - */ -static int get_kled_lvl(void) -{ - unsigned long long kblv; - struct acpi_object_list params; - union acpi_object in_obj; - acpi_status rv; - - params.count = 1; - params.pointer = &in_obj; - in_obj.type = ACPI_TYPE_INTEGER; - in_obj.integer.value = 2; - - rv = acpi_evaluate_integer(kled_get_handle, NULL, ¶ms, &kblv); - if (ACPI_FAILURE(rv)) { - pr_warning("Error reading kled level\n"); - return 0; - } - return kblv; -} - -static int set_kled_lvl(int kblv) -{ - if (kblv > 0) - kblv = (1 << 7) | (kblv & 0x7F); - else - kblv = 0; - - if (write_acpi_int(kled_set_handle, NULL, kblv, NULL)) { - pr_warning("Keyboard LED display write failed\n"); - return -EINVAL; - } - return 0; -} - -static void kled_led_set(struct led_classdev *led_cdev, - enum led_brightness value) -{ - kled_led_wk = value; - queue_work(led_workqueue, &kled_led_work); -} - -static void kled_led_update(struct work_struct *ignored) -{ - set_kled_lvl(kled_led_wk); -} - -static enum led_brightness kled_led_get(struct led_classdev *led_cdev) -{ - return get_kled_lvl(); -} - static int get_lcd_state(void) { return read_status(LCD_ON); @@ -588,7 +498,7 @@ static ssize_t show_infos(struct device *dev, { int len = 0; unsigned long long temp; - char buf[16]; /* enough for all info */ + char buf[16]; //enough for all info acpi_status rv = AE_OK; /* @@ -606,17 +516,7 @@ static ssize_t show_infos(struct device *dev, */ rv = acpi_evaluate_integer(hotk->handle, "SFUN", NULL, &temp); if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "SFUN value : %#x\n", - (uint) temp); - /* - * The HWRS method return informations about the hardware. - * 0x80 bit is for WLAN, 0x100 for Bluetooth. - * The significance of others is yet to be found. - * If we don't find the method, we assume the device are present. - */ - rv = acpi_evaluate_integer(hotk->handle, "HRWS", NULL, &temp); - if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "HRWS value : %#x\n", + len += sprintf(page + len, "SFUN value : 0x%04x\n", (uint) temp); /* * Another value for userspace: the ASYM method returns 0x02 for @@ -627,7 +527,7 @@ static ssize_t show_infos(struct device *dev, */ rv = acpi_evaluate_integer(hotk->handle, "ASYM", NULL, &temp); if (!ACPI_FAILURE(rv)) - len += sprintf(page + len, "ASYM value : %#x\n", + len += sprintf(page + len, "ASYM value : 0x%04x\n", (uint) temp); if (asus_info) { snprintf(buf, 16, "%d", asus_info->length); @@ -748,10 +648,8 @@ static int read_display(void) unsigned long long value = 0; acpi_status rv = AE_OK; - /* - * In most of the case, we know how to set the display, but sometime - * we can't read it - */ + /* In most of the case, we know how to set the display, but sometime + we can't read it */ if (display_get_handle) { rv = acpi_evaluate_integer(display_get_handle, NULL, NULL, &value); @@ -1139,9 +1037,6 @@ static int asus_hotk_get_info(void) ASUS_HANDLE_INIT(ledd_set); - ASUS_HANDLE_INIT(kled_set); - ASUS_HANDLE_INIT(kled_get); - /* * The HWRS method return informations about the hardware. * 0x80 bit is for WLAN, 0x100 for Bluetooth. @@ -1168,10 +1063,8 @@ static int asus_hotk_get_info(void) ASUS_HANDLE_INIT(display_set); ASUS_HANDLE_INIT(display_get); - /* - * There is a lot of models with "ALSL", but a few get - * a real light sens, so we need to check it. - */ + /* There is a lot of models with "ALSL", but a few get + a real light sens, so we need to check it. */ if (!ASUS_HANDLE_INIT(ls_switch)) ASUS_HANDLE_INIT(ls_level); @@ -1275,10 +1168,6 @@ static int asus_hotk_add(struct acpi_device *device) /* LCD Backlight is on by default */ write_status(NULL, 1, LCD_ON); - /* Keyboard Backlight is on by default */ - if (kled_set_handle) - set_kled_lvl(1); - /* LED display is off by default */ hotk->ledd_status = 0xFFF; @@ -1333,7 +1222,6 @@ static void asus_led_exit(void) ASUS_LED_UNREGISTER(pled); ASUS_LED_UNREGISTER(rled); ASUS_LED_UNREGISTER(gled); - ASUS_LED_UNREGISTER(kled); } static void asus_input_exit(void) @@ -1413,20 +1301,13 @@ static int asus_led_init(struct device *dev) if (rv) goto out4; - if (kled_set_handle && kled_get_handle) - rv = ASUS_LED_REGISTER(kled, dev); - if (rv) - goto out5; - led_workqueue = create_singlethread_workqueue("led_workqueue"); if (!led_workqueue) - goto out6; + goto out5; return 0; -out6: - rv = -ENOMEM; - ASUS_LED_UNREGISTER(kled); out5: + rv = -ENOMEM; ASUS_LED_UNREGISTER(gled); out4: ASUS_LED_UNREGISTER(pled); diff --git a/trunk/drivers/platform/x86/eeepc-laptop.c b/trunk/drivers/platform/x86/eeepc-laptop.c index da3c08b3dcc1..222ffb892f22 100644 --- a/trunk/drivers/platform/x86/eeepc-laptop.c +++ b/trunk/drivers/platform/x86/eeepc-laptop.c @@ -142,28 +142,18 @@ struct eeepc_hotk { struct rfkill *wlan_rfkill; struct rfkill *bluetooth_rfkill; struct rfkill *wwan3g_rfkill; - struct rfkill *wimax_rfkill; struct hotplug_slot *hotplug_slot; - struct mutex hotplug_lock; + struct work_struct hotplug_work; }; /* The actual device the driver binds to */ static struct eeepc_hotk *ehotk; /* Platform device/driver */ -static int eeepc_hotk_thaw(struct device *device); -static int eeepc_hotk_restore(struct device *device); - -static struct dev_pm_ops eeepc_pm_ops = { - .thaw = eeepc_hotk_thaw, - .restore = eeepc_hotk_restore, -}; - static struct platform_driver platform_driver = { .driver = { .name = EEEPC_HOTK_FILE, .owner = THIS_MODULE, - .pm = &eeepc_pm_ops, } }; @@ -202,6 +192,7 @@ static struct key_entry eeepc_keymap[] = { */ static int eeepc_hotk_add(struct acpi_device *device); static int eeepc_hotk_remove(struct acpi_device *device, int type); +static int eeepc_hotk_resume(struct acpi_device *device); static void eeepc_hotk_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id eeepc_device_ids[] = { @@ -218,6 +209,7 @@ static struct acpi_driver eeepc_hotk_driver = { .ops = { .add = eeepc_hotk_add, .remove = eeepc_hotk_remove, + .resume = eeepc_hotk_resume, .notify = eeepc_hotk_notify, }, }; @@ -587,6 +579,7 @@ static void cmsg_quirks(void) static int eeepc_hotk_check(void) { + const struct key_entry *key; struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; int result; @@ -611,6 +604,31 @@ static int eeepc_hotk_check(void) pr_info("Get control methods supported: 0x%x\n", ehotk->cm_supported); } + ehotk->inputdev = input_allocate_device(); + if (!ehotk->inputdev) { + pr_info("Unable to allocate input device\n"); + return 0; + } + ehotk->inputdev->name = "Asus EeePC extra buttons"; + ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; + ehotk->inputdev->id.bustype = BUS_HOST; + ehotk->inputdev->getkeycode = eeepc_getkeycode; + ehotk->inputdev->setkeycode = eeepc_setkeycode; + + for (key = eeepc_keymap; key->type != KE_END; key++) { + switch (key->type) { + case KE_KEY: + set_bit(EV_KEY, ehotk->inputdev->evbit); + set_bit(key->keycode, ehotk->inputdev->keybit); + break; + } + } + result = input_register_device(ehotk->inputdev); + if (result) { + pr_info("Unable to register input device\n"); + input_free_device(ehotk->inputdev); + return 0; + } } else { pr_err("Hotkey device not present, aborting\n"); return -EINVAL; @@ -643,48 +661,40 @@ static int eeepc_get_adapter_status(struct hotplug_slot *hotplug_slot, return 0; } -static void eeepc_rfkill_hotplug(void) +static void eeepc_hotplug_work(struct work_struct *work) { struct pci_dev *dev; - struct pci_bus *bus; - bool blocked = eeepc_wlan_rfkill_blocked(); - - if (ehotk->wlan_rfkill) - rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); + struct pci_bus *bus = pci_find_bus(0, 1); + bool blocked; - mutex_lock(&ehotk->hotplug_lock); + if (!bus) { + pr_warning("Unable to find PCI bus 1?\n"); + return; + } - if (ehotk->hotplug_slot) { - bus = pci_find_bus(0, 1); - if (!bus) { - pr_warning("Unable to find PCI bus 1?\n"); - goto out_unlock; + blocked = eeepc_wlan_rfkill_blocked(); + if (!blocked) { + dev = pci_get_slot(bus, 0); + if (dev) { + /* Device already present */ + pci_dev_put(dev); + return; } - - if (!blocked) { - dev = pci_get_slot(bus, 0); - if (dev) { - /* Device already present */ - pci_dev_put(dev); - goto out_unlock; - } - dev = pci_scan_single_device(bus, 0); - if (dev) { - pci_bus_assign_resources(bus); - if (pci_bus_add_device(dev)) - pr_err("Unable to hotplug wifi\n"); - } - } else { - dev = pci_get_slot(bus, 0); - if (dev) { - pci_remove_bus_device(dev); - pci_dev_put(dev); - } + dev = pci_scan_single_device(bus, 0); + if (dev) { + pci_bus_assign_resources(bus); + if (pci_bus_add_device(dev)) + pr_err("Unable to hotplug wifi\n"); + } + } else { + dev = pci_get_slot(bus, 0); + if (dev) { + pci_remove_bus_device(dev); + pci_dev_put(dev); } } -out_unlock: - mutex_unlock(&ehotk->hotplug_lock); + rfkill_set_sw_state(ehotk->wlan_rfkill, blocked); } static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) @@ -692,7 +702,7 @@ static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data) if (event != ACPI_NOTIFY_BUS_CHECK) return; - eeepc_rfkill_hotplug(); + schedule_work(&ehotk->hotplug_work); } static void eeepc_hotk_notify(struct acpi_device *device, u32 event) @@ -829,38 +839,66 @@ static int eeepc_setup_pci_hotplug(void) return ret; } -static int eeepc_hotk_thaw(struct device *device) +static int eeepc_hotk_add(struct acpi_device *device) +{ + int result; + + if (!device) + return -EINVAL; + pr_notice(EEEPC_HOTK_NAME "\n"); + ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); + if (!ehotk) + return -ENOMEM; + ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; + ehotk->handle = device->handle; + strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); + strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); + device->driver_data = ehotk; + ehotk->device = device; + result = eeepc_hotk_check(); + if (result) + goto ehotk_fail; + + return 0; + + ehotk_fail: + kfree(ehotk); + ehotk = NULL; + + return result; +} + +static int eeepc_hotk_remove(struct acpi_device *device, int type) +{ + if (!device || !acpi_driver_data(device)) + return -EINVAL; + + kfree(ehotk); + return 0; +} + +static int eeepc_hotk_resume(struct acpi_device *device) { if (ehotk->wlan_rfkill) { bool wlan; - /* - * Work around bios bug - acpi _PTS turns off the wireless led - * during suspend. Normally it restores it on resume, but - * we should kick it ourselves in case hibernation is aborted. + /* Workaround - it seems that _PTS disables the wireless + without notification or changing the value read by WLAN. + Normally this is fine because the correct value is restored + from the non-volatile storage on resume, but we need to do + it ourself if case suspend is aborted, or we lose wireless. */ wlan = get_acpi(CM_ASL_WLAN); set_acpi(CM_ASL_WLAN, wlan); - } - return 0; -} + rfkill_set_sw_state(ehotk->wlan_rfkill, wlan != 1); -static int eeepc_hotk_restore(struct device *device) -{ - /* Refresh both wlan rfkill state and pci hotplug */ - if (ehotk->wlan_rfkill) - eeepc_rfkill_hotplug(); + schedule_work(&ehotk->hotplug_work); + } if (ehotk->bluetooth_rfkill) rfkill_set_sw_state(ehotk->bluetooth_rfkill, get_acpi(CM_ASL_BLUETOOTH) != 1); - if (ehotk->wwan3g_rfkill) - rfkill_set_sw_state(ehotk->wwan3g_rfkill, - get_acpi(CM_ASL_3G) != 1); - if (ehotk->wimax_rfkill) - rfkill_set_sw_state(ehotk->wimax_rfkill, - get_acpi(CM_ASL_WIMAX) != 1); return 0; } @@ -981,37 +1019,16 @@ static void eeepc_backlight_exit(void) static void eeepc_rfkill_exit(void) { - eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P5"); eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P6"); eeepc_unregister_rfkill_notifier("\\_SB.PCI0.P0P7"); - if (ehotk->wlan_rfkill) { + if (ehotk->wlan_rfkill) rfkill_unregister(ehotk->wlan_rfkill); - rfkill_destroy(ehotk->wlan_rfkill); - ehotk->wlan_rfkill = NULL; - } - /* - * Refresh pci hotplug in case the rfkill state was changed after - * eeepc_unregister_rfkill_notifier() - */ - eeepc_rfkill_hotplug(); - if (ehotk->hotplug_slot) - pci_hp_deregister(ehotk->hotplug_slot); - - if (ehotk->bluetooth_rfkill) { + if (ehotk->bluetooth_rfkill) rfkill_unregister(ehotk->bluetooth_rfkill); - rfkill_destroy(ehotk->bluetooth_rfkill); - ehotk->bluetooth_rfkill = NULL; - } - if (ehotk->wwan3g_rfkill) { + if (ehotk->wwan3g_rfkill) rfkill_unregister(ehotk->wwan3g_rfkill); - rfkill_destroy(ehotk->wwan3g_rfkill); - ehotk->wwan3g_rfkill = NULL; - } - if (ehotk->wimax_rfkill) { - rfkill_unregister(ehotk->wimax_rfkill); - rfkill_destroy(ehotk->wimax_rfkill); - ehotk->wimax_rfkill = NULL; - } + if (ehotk->hotplug_slot) + pci_hp_deregister(ehotk->hotplug_slot); } static void eeepc_input_exit(void) @@ -1033,6 +1050,19 @@ static void eeepc_hwmon_exit(void) eeepc_hwmon_device = NULL; } +static void __exit eeepc_laptop_exit(void) +{ + eeepc_backlight_exit(); + eeepc_rfkill_exit(); + eeepc_input_exit(); + eeepc_hwmon_exit(); + acpi_bus_unregister_driver(&eeepc_hotk_driver); + sysfs_remove_group(&platform_device->dev.kobj, + &platform_attribute_group); + platform_device_unregister(platform_device); + platform_driver_unregister(&platform_driver); +} + static int eeepc_new_rfkill(struct rfkill **rfkill, const char *name, struct device *dev, enum rfkill_type type, int cm) @@ -1064,7 +1094,10 @@ static int eeepc_rfkill_init(struct device *dev) { int result = 0; - mutex_init(&ehotk->hotplug_lock); + INIT_WORK(&ehotk->hotplug_work, eeepc_hotplug_work); + + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); + eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); result = eeepc_new_rfkill(&ehotk->wlan_rfkill, "eeepc-wlan", dev, @@ -1087,13 +1120,6 @@ static int eeepc_rfkill_init(struct device *dev) if (result && result != -ENODEV) goto exit; - result = eeepc_new_rfkill(&ehotk->wimax_rfkill, - "eeepc-wimax", dev, - RFKILL_TYPE_WIMAX, CM_ASL_WIMAX); - - if (result && result != -ENODEV) - goto exit; - result = eeepc_setup_pci_hotplug(); /* * If we get -EBUSY then something else is handling the PCI hotplug - @@ -1102,15 +1128,6 @@ static int eeepc_rfkill_init(struct device *dev) if (result == -EBUSY) result = 0; - eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P5"); - eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P6"); - eeepc_register_rfkill_notifier("\\_SB.PCI0.P0P7"); - /* - * Refresh pci hotplug in case the rfkill state was changed during - * setup. - */ - eeepc_rfkill_hotplug(); - exit: if (result && result != -ENODEV) eeepc_rfkill_exit(); @@ -1155,61 +1172,21 @@ static int eeepc_hwmon_init(struct device *dev) return result; } -static int eeepc_input_init(struct device *dev) +static int __init eeepc_laptop_init(void) { - const struct key_entry *key; + struct device *dev; int result; - ehotk->inputdev = input_allocate_device(); - if (!ehotk->inputdev) { - pr_info("Unable to allocate input device\n"); - return -ENOMEM; - } - ehotk->inputdev->name = "Asus EeePC extra buttons"; - ehotk->inputdev->dev.parent = dev; - ehotk->inputdev->phys = EEEPC_HOTK_FILE "/input0"; - ehotk->inputdev->id.bustype = BUS_HOST; - ehotk->inputdev->getkeycode = eeepc_getkeycode; - ehotk->inputdev->setkeycode = eeepc_setkeycode; - - for (key = eeepc_keymap; key->type != KE_END; key++) { - switch (key->type) { - case KE_KEY: - set_bit(EV_KEY, ehotk->inputdev->evbit); - set_bit(key->keycode, ehotk->inputdev->keybit); - break; - } - } - result = input_register_device(ehotk->inputdev); - if (result) { - pr_info("Unable to register input device\n"); - input_free_device(ehotk->inputdev); + if (acpi_disabled) + return -ENODEV; + result = acpi_bus_register_driver(&eeepc_hotk_driver); + if (result < 0) return result; + if (!ehotk) { + acpi_bus_unregister_driver(&eeepc_hotk_driver); + return -ENODEV; } - return 0; -} - -static int eeepc_hotk_add(struct acpi_device *device) -{ - struct device *dev; - int result; - if (!device) - return -EINVAL; - pr_notice(EEEPC_HOTK_NAME "\n"); - ehotk = kzalloc(sizeof(struct eeepc_hotk), GFP_KERNEL); - if (!ehotk) - return -ENOMEM; - ehotk->init_flag = DISABLE_ASL_WLAN | DISABLE_ASL_DISPLAYSWITCH; - ehotk->handle = device->handle; - strcpy(acpi_device_name(device), EEEPC_HOTK_DEVICE_NAME); - strcpy(acpi_device_class(device), EEEPC_HOTK_CLASS); - device->driver_data = ehotk; - ehotk->device = device; - - result = eeepc_hotk_check(); - if (result) - goto fail_platform_driver; eeepc_enable_camera(); /* Register platform stuff */ @@ -1239,10 +1216,6 @@ static int eeepc_hotk_add(struct acpi_device *device) pr_info("Backlight controlled by ACPI video " "driver\n"); - result = eeepc_input_init(dev); - if (result) - goto fail_input; - result = eeepc_hwmon_init(dev); if (result) goto fail_hwmon; @@ -1252,12 +1225,9 @@ static int eeepc_hotk_add(struct acpi_device *device) goto fail_rfkill; return 0; - fail_rfkill: eeepc_hwmon_exit(); fail_hwmon: - eeepc_input_exit(); -fail_input: eeepc_backlight_exit(); fail_backlight: sysfs_remove_group(&platform_device->dev.kobj, @@ -1269,48 +1239,8 @@ static int eeepc_hotk_add(struct acpi_device *device) fail_platform_device1: platform_driver_unregister(&platform_driver); fail_platform_driver: - kfree(ehotk); - - return result; -} - -static int eeepc_hotk_remove(struct acpi_device *device, int type) -{ - if (!device || !acpi_driver_data(device)) - return -EINVAL; - - eeepc_backlight_exit(); - eeepc_rfkill_exit(); eeepc_input_exit(); - eeepc_hwmon_exit(); - sysfs_remove_group(&platform_device->dev.kobj, - &platform_attribute_group); - platform_device_unregister(platform_device); - platform_driver_unregister(&platform_driver); - - kfree(ehotk); - return 0; -} - -static int __init eeepc_laptop_init(void) -{ - int result; - - if (acpi_disabled) - return -ENODEV; - result = acpi_bus_register_driver(&eeepc_hotk_driver); - if (result < 0) - return result; - if (!ehotk) { - acpi_bus_unregister_driver(&eeepc_hotk_driver); - return -ENODEV; - } - return 0; -} - -static void __exit eeepc_laptop_exit(void) -{ - acpi_bus_unregister_driver(&eeepc_hotk_driver); + return result; } module_init(eeepc_laptop_init); diff --git a/trunk/drivers/platform/x86/fujitsu-laptop.c b/trunk/drivers/platform/x86/fujitsu-laptop.c index f35aee5c2149..218b9a16ac3f 100644 --- a/trunk/drivers/platform/x86/fujitsu-laptop.c +++ b/trunk/drivers/platform/x86/fujitsu-laptop.c @@ -66,11 +66,11 @@ #include #include #include -#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +#ifdef CONFIG_LEDS_CLASS #include #endif -#define FUJITSU_DRIVER_VERSION "0.6.0" +#define FUJITSU_DRIVER_VERSION "0.5.0" #define FUJITSU_LCD_N_LEVELS 8 @@ -96,7 +96,7 @@ /* FUNC interface - responses */ #define UNSUPPORTED_CMD 0x80000000 -#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +#ifdef CONFIG_LEDS_CLASS /* FUNC interface - LED control */ #define FUNC_LED_OFF 0x1 #define FUNC_LED_ON 0x30001 @@ -176,7 +176,7 @@ static struct fujitsu_hotkey_t *fujitsu_hotkey; static void acpi_fujitsu_hotkey_notify(struct acpi_device *device, u32 event); -#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +#ifdef CONFIG_LEDS_CLASS static enum led_brightness logolamp_get(struct led_classdev *cdev); static void logolamp_set(struct led_classdev *cdev, enum led_brightness brightness); @@ -257,7 +257,7 @@ static int call_fext_func(int cmd, int arg0, int arg1, int arg2) return out_obj.integer.value; } -#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) +#ifdef CONFIG_LEDS_CLASS /* LED class callbacks */ static void logolamp_set(struct led_classdev *cdev, @@ -324,6 +324,9 @@ static int set_lcd_level(int level) if (level < 0 || level >= fujitsu->max_brightness) return -EINVAL; + if (!fujitsu) + return -EINVAL; + status = acpi_get_handle(fujitsu->acpi_handle, "SBLL", &handle); if (ACPI_FAILURE(status)) { vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBLL not present\n"); @@ -352,6 +355,9 @@ static int set_lcd_level_alt(int level) if (level < 0 || level >= fujitsu->max_brightness) return -EINVAL; + if (!fujitsu) + return -EINVAL; + status = acpi_get_handle(fujitsu->acpi_handle, "SBL2", &handle); if (ACPI_FAILURE(status)) { vdbg_printk(FUJLAPTOP_DBG_ERROR, "SBL2 not present\n"); @@ -691,10 +697,10 @@ static int acpi_fujitsu_add(struct acpi_device *device) result = acpi_bus_get_power(fujitsu->acpi_handle, &state); if (result) { printk(KERN_ERR "Error reading power state\n"); - goto err_unregister_input_dev; + goto end; } - printk(KERN_INFO "ACPI: %s [%s] (%s)\n", + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), acpi_device_bid(device), !device->power.state ? "on" : "off"); @@ -722,22 +728,25 @@ static int acpi_fujitsu_add(struct acpi_device *device) return result; -err_unregister_input_dev: - input_unregister_device(input); +end: err_free_input_dev: input_free_device(input); err_stop: + return result; } static int acpi_fujitsu_remove(struct acpi_device *device, int type) { - struct fujitsu_t *fujitsu = acpi_driver_data(device); - struct input_dev *input = fujitsu->input; + struct fujitsu_t *fujitsu = NULL; - input_unregister_device(input); + if (!device || !acpi_driver_data(device)) + return -EINVAL; - input_free_device(input); + fujitsu = acpi_driver_data(device); + + if (!device || !acpi_driver_data(device)) + return -EINVAL; fujitsu->acpi_handle = NULL; @@ -862,10 +871,10 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) result = acpi_bus_get_power(fujitsu_hotkey->acpi_handle, &state); if (result) { printk(KERN_ERR "Error reading power state\n"); - goto err_unregister_input_dev; + goto end; } - printk(KERN_INFO "ACPI: %s [%s] (%s)\n", + printk(KERN_INFO PREFIX "%s [%s] (%s)\n", acpi_device_name(device), acpi_device_bid(device), !device->power.state ? "on" : "off"); @@ -902,7 +911,7 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) printk(KERN_INFO "fujitsu-laptop: BTNI: [0x%x]\n", call_fext_func(FUNC_BUTTONS, 0x0, 0x0, 0x0)); -#if defined(CONFIG_LEDS_CLASS) || defined(CONFIG_LEDS_CLASS_MODULE) + #ifdef CONFIG_LEDS_CLASS if (call_fext_func(FUNC_LEDS, 0x0, 0x0, 0x0) & LOGOLAMP_POWERON) { result = led_classdev_register(&fujitsu->pf_device->dev, &logolamp_led); @@ -925,41 +934,33 @@ static int acpi_fujitsu_hotkey_add(struct acpi_device *device) "LED handler for keyboard lamps, error %i\n", result); } } -#endif + #endif return result; -err_unregister_input_dev: - input_unregister_device(input); +end: err_free_input_dev: input_free_device(input); err_free_fifo: kfifo_free(fujitsu_hotkey->fifo); err_stop: + return result; } static int acpi_fujitsu_hotkey_remove(struct acpi_device *device, int type) { - struct fujitsu_hotkey_t *fujitsu_hotkey = acpi_driver_data(device); - struct input_dev *input = fujitsu_hotkey->input; - -#ifdef CONFIG_LEDS_CLASS - if (fujitsu_hotkey->logolamp_registered) - led_classdev_unregister(&logolamp_led); + struct fujitsu_hotkey_t *fujitsu_hotkey = NULL; - if (fujitsu_hotkey->kblamps_registered) - led_classdev_unregister(&kblamps_led); -#endif + if (!device || !acpi_driver_data(device)) + return -EINVAL; - input_unregister_device(input); + fujitsu_hotkey = acpi_driver_data(device); - input_free_device(input); + fujitsu_hotkey->acpi_handle = NULL; kfifo_free(fujitsu_hotkey->fifo); - fujitsu_hotkey->acpi_handle = NULL; - return 0; } @@ -1129,11 +1130,8 @@ static int __init fujitsu_init(void) fujitsu->bl_device = backlight_device_register("fujitsu-laptop", NULL, NULL, &fujitsubl_ops); - if (IS_ERR(fujitsu->bl_device)) { - ret = PTR_ERR(fujitsu->bl_device); - fujitsu->bl_device = NULL; - goto fail_sysfs_group; - } + if (IS_ERR(fujitsu->bl_device)) + return PTR_ERR(fujitsu->bl_device); max_brightness = fujitsu->max_brightness; fujitsu->bl_device->props.max_brightness = max_brightness - 1; fujitsu->bl_device->props.brightness = fujitsu->brightness_level; @@ -1173,22 +1171,32 @@ static int __init fujitsu_init(void) return 0; fail_hotkey1: + kfree(fujitsu_hotkey); + fail_hotkey: + platform_driver_unregister(&fujitsupf_driver); + fail_backlight: + if (fujitsu->bl_device) backlight_device_unregister(fujitsu->bl_device); -fail_sysfs_group: - sysfs_remove_group(&fujitsu->pf_device->dev.kobj, - &fujitsupf_attribute_group); + fail_platform_device2: + platform_device_del(fujitsu->pf_device); + fail_platform_device1: + platform_device_put(fujitsu->pf_device); + fail_platform_driver: + acpi_bus_unregister_driver(&acpi_fujitsu_driver); + fail_acpi: + kfree(fujitsu); return ret; @@ -1196,24 +1204,29 @@ static int __init fujitsu_init(void) static void __exit fujitsu_cleanup(void) { - acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver); - - kfree(fujitsu_hotkey); - - platform_driver_unregister(&fujitsupf_driver); + #ifdef CONFIG_LEDS_CLASS + if (fujitsu_hotkey->logolamp_registered != 0) + led_classdev_unregister(&logolamp_led); - if (fujitsu->bl_device) - backlight_device_unregister(fujitsu->bl_device); + if (fujitsu_hotkey->kblamps_registered != 0) + led_classdev_unregister(&kblamps_led); + #endif sysfs_remove_group(&fujitsu->pf_device->dev.kobj, &fujitsupf_attribute_group); - platform_device_unregister(fujitsu->pf_device); + platform_driver_unregister(&fujitsupf_driver); + if (fujitsu->bl_device) + backlight_device_unregister(fujitsu->bl_device); acpi_bus_unregister_driver(&acpi_fujitsu_driver); kfree(fujitsu); + acpi_bus_unregister_driver(&acpi_fujitsu_hotkey_driver); + + kfree(fujitsu_hotkey); + printk(KERN_INFO "fujitsu-laptop: driver unloaded.\n"); } diff --git a/trunk/drivers/platform/x86/hp-wmi.c b/trunk/drivers/platform/x86/hp-wmi.c index c2842171cec6..af04f5b049db 100644 --- a/trunk/drivers/platform/x86/hp-wmi.c +++ b/trunk/drivers/platform/x86/hp-wmi.c @@ -507,7 +507,7 @@ static int __exit hp_wmi_bios_remove(struct platform_device *device) } if (bluetooth_rfkill) { rfkill_unregister(bluetooth_rfkill); - rfkill_destroy(bluetooth_rfkill); + rfkill_destroy(wifi_rfkill); } if (wwan_rfkill) { rfkill_unregister(wwan_rfkill); diff --git a/trunk/drivers/platform/x86/sony-laptop.c b/trunk/drivers/platform/x86/sony-laptop.c index f9f68e0e7344..dafaa4a92df5 100644 --- a/trunk/drivers/platform/x86/sony-laptop.c +++ b/trunk/drivers/platform/x86/sony-laptop.c @@ -976,12 +976,15 @@ static acpi_status sony_walk_callback(acpi_handle handle, u32 level, void *context, void **return_value) { struct acpi_device_info *info; + struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; + + if (ACPI_SUCCESS(acpi_get_object_info(handle, &buffer))) { + info = buffer.pointer; - if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) { printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n", (char *)&info->name, info->param_count); - kfree(info); + kfree(buffer.pointer); } return AE_OK; diff --git a/trunk/drivers/platform/x86/thinkpad_acpi.c b/trunk/drivers/platform/x86/thinkpad_acpi.c index f78d27503925..e85600852502 100644 --- a/trunk/drivers/platform/x86/thinkpad_acpi.c +++ b/trunk/drivers/platform/x86/thinkpad_acpi.c @@ -1278,7 +1278,6 @@ static void tpacpi_destroy_rfkill(const enum tpacpi_rfk_id id) tp_rfk = tpacpi_rfkill_switches[id]; if (tp_rfk) { rfkill_unregister(tp_rfk->rfkill); - rfkill_destroy(tp_rfk->rfkill); tpacpi_rfkill_switches[id] = NULL; kfree(tp_rfk); } @@ -1602,196 +1601,6 @@ static void tpacpi_remove_driver_attributes(struct device_driver *drv) #endif } -/************************************************************************* - * Firmware Data - */ - -/* - * Table of recommended minimum BIOS versions - * - * Reasons for listing: - * 1. Stable BIOS, listed because the unknown ammount of - * bugs and bad ACPI behaviour on older versions - * - * 2. BIOS or EC fw with known bugs that trigger on Linux - * - * 3. BIOS with known reduced functionality in older versions - * - * We recommend the latest BIOS and EC version. - * We only support the latest BIOS and EC fw version as a rule. - * - * Sources: IBM ThinkPad Public Web Documents (update changelogs), - * Information from users in ThinkWiki - * - * WARNING: we use this table also to detect that the machine is - * a ThinkPad in some cases, so don't remove entries lightly. - */ - -#define TPV_Q(__v, __id1, __id2, __bv1, __bv2) \ - { .vendor = (__v), \ - .bios = TPID(__id1, __id2), \ - .ec = TPACPI_MATCH_ANY, \ - .quirks = TPACPI_MATCH_ANY << 16 \ - | (__bv1) << 8 | (__bv2) } - -#define TPV_Q_X(__v, __bid1, __bid2, __bv1, __bv2, \ - __eid1, __eid2, __ev1, __ev2) \ - { .vendor = (__v), \ - .bios = TPID(__bid1, __bid2), \ - .ec = TPID(__eid1, __eid2), \ - .quirks = (__ev1) << 24 | (__ev2) << 16 \ - | (__bv1) << 8 | (__bv2) } - -#define TPV_QI0(__id1, __id2, __bv1, __bv2) \ - TPV_Q(PCI_VENDOR_ID_IBM, __id1, __id2, __bv1, __bv2) - -#define TPV_QI1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ - TPV_Q_X(PCI_VENDOR_ID_IBM, __id1, __id2, \ - __bv1, __bv2, __id1, __id2, __ev1, __ev2) - -#define TPV_QI2(__bid1, __bid2, __bv1, __bv2, \ - __eid1, __eid2, __ev1, __ev2) \ - TPV_Q_X(PCI_VENDOR_ID_IBM, __bid1, __bid2, \ - __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) - -#define TPV_QL0(__id1, __id2, __bv1, __bv2) \ - TPV_Q(PCI_VENDOR_ID_LENOVO, __id1, __id2, __bv1, __bv2) - -#define TPV_QL1(__id1, __id2, __bv1, __bv2, __ev1, __ev2) \ - TPV_Q_X(PCI_VENDOR_ID_LENOVO, __id1, __id2, \ - __bv1, __bv2, __id1, __id2, __ev1, __ev2) - -#define TPV_QL2(__bid1, __bid2, __bv1, __bv2, \ - __eid1, __eid2, __ev1, __ev2) \ - TPV_Q_X(PCI_VENDOR_ID_LENOVO, __bid1, __bid2, \ - __bv1, __bv2, __eid1, __eid2, __ev1, __ev2) - -static const struct tpacpi_quirk tpacpi_bios_version_qtable[] __initconst = { - /* Numeric models ------------------ */ - /* FW MODEL BIOS VERS */ - TPV_QI0('I', 'M', '6', '5'), /* 570 */ - TPV_QI0('I', 'U', '2', '6'), /* 570E */ - TPV_QI0('I', 'B', '5', '4'), /* 600 */ - TPV_QI0('I', 'H', '4', '7'), /* 600E */ - TPV_QI0('I', 'N', '3', '6'), /* 600E */ - TPV_QI0('I', 'T', '5', '5'), /* 600X */ - TPV_QI0('I', 'D', '4', '8'), /* 770, 770E, 770ED */ - TPV_QI0('I', 'I', '4', '2'), /* 770X */ - TPV_QI0('I', 'O', '2', '3'), /* 770Z */ - - /* A-series ------------------------- */ - /* FW MODEL BIOS VERS EC VERS */ - TPV_QI0('I', 'W', '5', '9'), /* A20m */ - TPV_QI0('I', 'V', '6', '9'), /* A20p */ - TPV_QI0('1', '0', '2', '6'), /* A21e, A22e */ - TPV_QI0('K', 'U', '3', '6'), /* A21e */ - TPV_QI0('K', 'X', '3', '6'), /* A21m, A22m */ - TPV_QI0('K', 'Y', '3', '8'), /* A21p, A22p */ - TPV_QI0('1', 'B', '1', '7'), /* A22e */ - TPV_QI0('1', '3', '2', '0'), /* A22m */ - TPV_QI0('1', 'E', '7', '3'), /* A30/p (0) */ - TPV_QI1('1', 'G', '4', '1', '1', '7'), /* A31/p (0) */ - TPV_QI1('1', 'N', '1', '6', '0', '7'), /* A31/p (0) */ - - /* G-series ------------------------- */ - /* FW MODEL BIOS VERS */ - TPV_QI0('1', 'T', 'A', '6'), /* G40 */ - TPV_QI0('1', 'X', '5', '7'), /* G41 */ - - /* R-series, T-series --------------- */ - /* FW MODEL BIOS VERS EC VERS */ - TPV_QI0('1', 'C', 'F', '0'), /* R30 */ - TPV_QI0('1', 'F', 'F', '1'), /* R31 */ - TPV_QI0('1', 'M', '9', '7'), /* R32 */ - TPV_QI0('1', 'O', '6', '1'), /* R40 */ - TPV_QI0('1', 'P', '6', '5'), /* R40 */ - TPV_QI0('1', 'S', '7', '0'), /* R40e */ - TPV_QI1('1', 'R', 'D', 'R', '7', '1'), /* R50/p, R51, - T40/p, T41/p, T42/p (1) */ - TPV_QI1('1', 'V', '7', '1', '2', '8'), /* R50e, R51 (1) */ - TPV_QI1('7', '8', '7', '1', '0', '6'), /* R51e (1) */ - TPV_QI1('7', '6', '6', '9', '1', '6'), /* R52 (1) */ - TPV_QI1('7', '0', '6', '9', '2', '8'), /* R52, T43 (1) */ - - TPV_QI0('I', 'Y', '6', '1'), /* T20 */ - TPV_QI0('K', 'Z', '3', '4'), /* T21 */ - TPV_QI0('1', '6', '3', '2'), /* T22 */ - TPV_QI1('1', 'A', '6', '4', '2', '3'), /* T23 (0) */ - TPV_QI1('1', 'I', '7', '1', '2', '0'), /* T30 (0) */ - TPV_QI1('1', 'Y', '6', '5', '2', '9'), /* T43/p (1) */ - - TPV_QL1('7', '9', 'E', '3', '5', '0'), /* T60/p */ - TPV_QL1('7', 'C', 'D', '2', '2', '2'), /* R60, R60i */ - TPV_QL0('7', 'E', 'D', '0'), /* R60e, R60i */ - - /* BIOS FW BIOS VERS EC FW EC VERS */ - TPV_QI2('1', 'W', '9', '0', '1', 'V', '2', '8'), /* R50e (1) */ - TPV_QL2('7', 'I', '3', '4', '7', '9', '5', '0'), /* T60/p wide */ - - /* X-series ------------------------- */ - /* FW MODEL BIOS VERS EC VERS */ - TPV_QI0('I', 'Z', '9', 'D'), /* X20, X21 */ - TPV_QI0('1', 'D', '7', '0'), /* X22, X23, X24 */ - TPV_QI1('1', 'K', '4', '8', '1', '8'), /* X30 (0) */ - TPV_QI1('1', 'Q', '9', '7', '2', '3'), /* X31, X32 (0) */ - TPV_QI1('1', 'U', 'D', '3', 'B', '2'), /* X40 (0) */ - TPV_QI1('7', '4', '6', '4', '2', '7'), /* X41 (0) */ - TPV_QI1('7', '5', '6', '0', '2', '0'), /* X41t (0) */ - - TPV_QL0('7', 'B', 'D', '7'), /* X60/s */ - TPV_QL0('7', 'J', '3', '0'), /* X60t */ - - /* (0) - older versions lack DMI EC fw string and functionality */ - /* (1) - older versions known to lack functionality */ -}; - -#undef TPV_QL1 -#undef TPV_QL0 -#undef TPV_QI2 -#undef TPV_QI1 -#undef TPV_QI0 -#undef TPV_Q_X -#undef TPV_Q - -static void __init tpacpi_check_outdated_fw(void) -{ - unsigned long fwvers; - u16 ec_version, bios_version; - - fwvers = tpacpi_check_quirks(tpacpi_bios_version_qtable, - ARRAY_SIZE(tpacpi_bios_version_qtable)); - - if (!fwvers) - return; - - bios_version = fwvers & 0xffffU; - ec_version = (fwvers >> 16) & 0xffffU; - - /* note that unknown versions are set to 0x0000 and we use that */ - if ((bios_version > thinkpad_id.bios_release) || - (ec_version > thinkpad_id.ec_release && - ec_version != TPACPI_MATCH_ANY)) { - /* - * The changelogs would let us track down the exact - * reason, but it is just too much of a pain to track - * it. We only list BIOSes that are either really - * broken, or really stable to begin with, so it is - * best if the user upgrades the firmware anyway. - */ - printk(TPACPI_WARN - "WARNING: Outdated ThinkPad BIOS/EC firmware\n"); - printk(TPACPI_WARN - "WARNING: This firmware may be missing critical bug " - "fixes and/or important features\n"); - } -} - -static bool __init tpacpi_is_fw_known(void) -{ - return tpacpi_check_quirks(tpacpi_bios_version_qtable, - ARRAY_SIZE(tpacpi_bios_version_qtable)) != 0; -} - /**************************************************************************** **************************************************************************** * @@ -1825,7 +1634,6 @@ static int __init thinkpad_acpi_driver_init(struct ibm_init_struct *iibm) (thinkpad_id.nummodel_str) ? thinkpad_id.nummodel_str : "unknown"); - tpacpi_check_outdated_fw(); return 0; } @@ -1923,42 +1731,16 @@ struct tp_nvram_state { u8 volume_level; }; -/* kthread for the hotkey poller */ static struct task_struct *tpacpi_hotkey_task; - -/* Acquired while the poller kthread is running, use to sync start/stop */ +static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */ +static int hotkey_poll_freq = 10; /* Hz */ static struct mutex hotkey_thread_mutex; - -/* - * Acquire mutex to write poller control variables. - * Increment hotkey_config_change when changing them. - * - * See HOTKEY_CONFIG_CRITICAL_START/HOTKEY_CONFIG_CRITICAL_END - */ static struct mutex hotkey_thread_data_mutex; static unsigned int hotkey_config_change; -/* - * hotkey poller control variables - * - * Must be atomic or readers will also need to acquire mutex - */ -static u32 hotkey_source_mask; /* bit mask 0=ACPI,1=NVRAM */ -static unsigned int hotkey_poll_freq = 10; /* Hz */ - -#define HOTKEY_CONFIG_CRITICAL_START \ - do { \ - mutex_lock(&hotkey_thread_data_mutex); \ - hotkey_config_change++; \ - } while (0); -#define HOTKEY_CONFIG_CRITICAL_END \ - mutex_unlock(&hotkey_thread_data_mutex); - #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ #define hotkey_source_mask 0U -#define HOTKEY_CONFIG_CRITICAL_START -#define HOTKEY_CONFIG_CRITICAL_END #endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ @@ -1983,6 +1765,19 @@ static u16 *hotkey_keycode_map; static struct attribute_set *hotkey_dev_attributes; +#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL +#define HOTKEY_CONFIG_CRITICAL_START \ + do { \ + mutex_lock(&hotkey_thread_data_mutex); \ + hotkey_config_change++; \ + } while (0); +#define HOTKEY_CONFIG_CRITICAL_END \ + mutex_unlock(&hotkey_thread_data_mutex); +#else +#define HOTKEY_CONFIG_CRITICAL_START +#define HOTKEY_CONFIG_CRITICAL_END +#endif /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ + /* HKEY.MHKG() return bits */ #define TP_HOTKEY_TABLET_MASK (1 << 3) @@ -2027,9 +1822,7 @@ static int hotkey_mask_get(void) if (!acpi_evalf(hkey_handle, &m, "DHKN", "d")) return -EIO; } - HOTKEY_CONFIG_CRITICAL_START hotkey_mask = m | (hotkey_source_mask & hotkey_mask); - HOTKEY_CONFIG_CRITICAL_END return 0; } @@ -2282,7 +2075,6 @@ static int hotkey_kthread(void *data) unsigned int si, so; unsigned long t; unsigned int change_detector, must_reset; - unsigned int poll_freq; mutex_lock(&hotkey_thread_mutex); @@ -2299,17 +2091,12 @@ static int hotkey_kthread(void *data) mutex_lock(&hotkey_thread_data_mutex); change_detector = hotkey_config_change; mask = hotkey_source_mask & hotkey_mask; - poll_freq = hotkey_poll_freq; mutex_unlock(&hotkey_thread_data_mutex); hotkey_read_nvram(&s[so], mask); - while (!kthread_should_stop()) { - if (t == 0) { - if (likely(poll_freq)) - t = 1000/poll_freq; - else - t = 100; /* should never happen... */ - } + while (!kthread_should_stop() && hotkey_poll_freq) { + if (t == 0) + t = 1000/hotkey_poll_freq; t = msleep_interruptible(t); if (unlikely(kthread_should_stop())) break; @@ -2325,7 +2112,6 @@ static int hotkey_kthread(void *data) change_detector = hotkey_config_change; } mask = hotkey_source_mask & hotkey_mask; - poll_freq = hotkey_poll_freq; mutex_unlock(&hotkey_thread_data_mutex); if (likely(mask)) { @@ -2345,7 +2131,6 @@ static int hotkey_kthread(void *data) return 0; } -/* call with hotkey_mutex held */ static void hotkey_poll_stop_sync(void) { if (tpacpi_hotkey_task) { @@ -2362,11 +2147,10 @@ static void hotkey_poll_stop_sync(void) } /* call with hotkey_mutex held */ -static void hotkey_poll_setup(bool may_warn) +static void hotkey_poll_setup(int may_warn) { - u32 hotkeys_to_poll = hotkey_source_mask & hotkey_mask; - - if (hotkeys_to_poll != 0 && hotkey_poll_freq > 0 && + if ((hotkey_source_mask & hotkey_mask) != 0 && + hotkey_poll_freq > 0 && (tpacpi_inputdev->users > 0 || hotkey_report_mode < 2)) { if (!tpacpi_hotkey_task) { tpacpi_hotkey_task = kthread_run(hotkey_kthread, @@ -2380,37 +2164,26 @@ static void hotkey_poll_setup(bool may_warn) } } else { hotkey_poll_stop_sync(); - if (may_warn && hotkeys_to_poll != 0 && - hotkey_poll_freq == 0) { + if (may_warn && + hotkey_source_mask != 0 && hotkey_poll_freq == 0) { printk(TPACPI_NOTICE "hot keys 0x%08x require polling, " "which is currently disabled\n", - hotkeys_to_poll); + hotkey_source_mask); } } } -static void hotkey_poll_setup_safe(bool may_warn) +static void hotkey_poll_setup_safe(int may_warn) { mutex_lock(&hotkey_mutex); hotkey_poll_setup(may_warn); mutex_unlock(&hotkey_mutex); } -/* call with hotkey_mutex held */ -static void hotkey_poll_set_freq(unsigned int freq) -{ - if (!freq) - hotkey_poll_stop_sync(); - - HOTKEY_CONFIG_CRITICAL_START - hotkey_poll_freq = freq; - HOTKEY_CONFIG_CRITICAL_END -} - #else /* CONFIG_THINKPAD_ACPI_HOTKEY_POLL */ -static void hotkey_poll_setup_safe(bool __unused) +static void hotkey_poll_setup_safe(int __unused) { } @@ -2428,7 +2201,7 @@ static int hotkey_inputdev_open(struct input_dev *dev) case TPACPI_LIFE_EXITING: return -EBUSY; case TPACPI_LIFE_RUNNING: - hotkey_poll_setup_safe(false); + hotkey_poll_setup_safe(0); return 0; } @@ -2441,7 +2214,7 @@ static void hotkey_inputdev_close(struct input_dev *dev) { /* disable hotkey polling when possible */ if (tpacpi_lifecycle == TPACPI_LIFE_RUNNING) - hotkey_poll_setup_safe(false); + hotkey_poll_setup_safe(0); } /* sysfs hotkey enable ------------------------------------------------- */ @@ -2515,7 +2288,7 @@ static ssize_t hotkey_mask_store(struct device *dev, res = hotkey_mask_set(t); #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - hotkey_poll_setup(true); + hotkey_poll_setup(1); #endif mutex_unlock(&hotkey_mutex); @@ -2545,8 +2318,6 @@ static ssize_t hotkey_bios_mask_show(struct device *dev, struct device_attribute *attr, char *buf) { - printk_deprecated_attribute("hotkey_bios_mask", - "This attribute is useless."); return snprintf(buf, PAGE_SIZE, "0x%08x\n", hotkey_orig_mask); } @@ -2606,8 +2377,7 @@ static ssize_t hotkey_source_mask_store(struct device *dev, hotkey_source_mask = t; HOTKEY_CONFIG_CRITICAL_END - hotkey_poll_setup(true); - hotkey_mask_set(hotkey_mask); + hotkey_poll_setup(1); mutex_unlock(&hotkey_mutex); @@ -2640,9 +2410,9 @@ static ssize_t hotkey_poll_freq_store(struct device *dev, if (mutex_lock_killable(&hotkey_mutex)) return -ERESTARTSYS; - hotkey_poll_set_freq(t); - hotkey_poll_setup(true); + hotkey_poll_freq = t; + hotkey_poll_setup(1); mutex_unlock(&hotkey_mutex); tpacpi_disclose_usertask("hotkey_poll_freq", "set to %lu\n", t); @@ -2833,9 +2603,7 @@ static void tpacpi_send_radiosw_update(void) static void hotkey_exit(void) { #ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - mutex_lock(&hotkey_mutex); hotkey_poll_stop_sync(); - mutex_unlock(&hotkey_mutex); #endif if (hotkey_dev_attributes) @@ -2855,15 +2623,6 @@ static void hotkey_exit(void) } } -static void __init hotkey_unmap(const unsigned int scancode) -{ - if (hotkey_keycode_map[scancode] != KEY_RESERVED) { - clear_bit(hotkey_keycode_map[scancode], - tpacpi_inputdev->keybit); - hotkey_keycode_map[scancode] = KEY_RESERVED; - } -} - static int __init hotkey_init(struct ibm_init_struct *iibm) { /* Requirements for changing the default keymaps: @@ -2942,11 +2701,11 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) KEY_UNKNOWN, /* 0x0D: FN+INSERT */ KEY_UNKNOWN, /* 0x0E: FN+DELETE */ - /* These should be enabled --only-- when ACPI video - * is disabled (i.e. in "vendor" mode), and are handled - * in a special way by the init code */ - KEY_BRIGHTNESSUP, /* 0x0F: FN+HOME (brightness up) */ - KEY_BRIGHTNESSDOWN, /* 0x10: FN+END (brightness down) */ + /* These either have to go through ACPI video, or + * act like in the IBM ThinkPads, so don't ever + * enable them by default */ + KEY_RESERVED, /* 0x0F: FN+HOME (brightness up) */ + KEY_RESERVED, /* 0x10: FN+END (brightness down) */ KEY_RESERVED, /* 0x11: FN+PGUP (thinklight toggle) */ @@ -3072,6 +2831,19 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) goto err_exit; } +#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL + if (tp_features.hotkey_mask) { + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK + & ~hotkey_all_mask; + } else { + hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK; + } + + vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, + "hotkey source mask 0x%08x, polling freq %d\n", + hotkey_source_mask, hotkey_poll_freq); +#endif + #ifdef CONFIG_THINKPAD_ACPI_DEBUGFACILITIES if (dbg_wlswemul) { tp_features.hotkey_wlsw = 1; @@ -3172,31 +2944,17 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) "Disabling thinkpad-acpi brightness events " "by default...\n"); - /* Disable brightness up/down on Lenovo thinkpads when - * ACPI is handling them, otherwise it is plain impossible - * for userspace to do something even remotely sane */ + /* The hotkey_reserved_mask change below is not + * necessary while the keys are at KEY_RESERVED in the + * default map, but better safe than sorry, leave it + * here as a marker of what we have to do, especially + * when we finally become able to set this at runtime + * on response to X.org requests */ hotkey_reserved_mask |= (1 << TP_ACPI_HOTKEYSCAN_FNHOME) | (1 << TP_ACPI_HOTKEYSCAN_FNEND); - hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNHOME); - hotkey_unmap(TP_ACPI_HOTKEYSCAN_FNEND); } -#ifdef CONFIG_THINKPAD_ACPI_HOTKEY_POLL - if (tp_features.hotkey_mask) { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK - & ~hotkey_all_mask - & ~hotkey_reserved_mask; - } else { - hotkey_source_mask = TPACPI_HKEY_NVRAM_GOOD_MASK - & ~hotkey_reserved_mask; - } - - vdbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, - "hotkey source mask 0x%08x, polling freq %u\n", - hotkey_source_mask, hotkey_poll_freq); -#endif - dbg_printk(TPACPI_DBG_INIT | TPACPI_DBG_HKEY, "enabling firmware HKEY event interface...\n"); res = hotkey_status_set(true); @@ -3220,7 +2978,7 @@ static int __init hotkey_init(struct ibm_init_struct *iibm) tpacpi_inputdev->open = &hotkey_inputdev_open; tpacpi_inputdev->close = &hotkey_inputdev_close; - hotkey_poll_setup_safe(true); + hotkey_poll_setup_safe(1); tpacpi_send_radiosw_update(); tpacpi_input_send_tabletsw(); @@ -3508,7 +3266,7 @@ static void hotkey_resume(void) hotkey_tablet_mode_notify_change(); hotkey_wakeup_reason_notify_change(); hotkey_wakeup_hotunplug_complete_notify_change(); - hotkey_poll_setup_safe(false); + hotkey_poll_setup_safe(0); } /* procfs -------------------------------------------------------------- */ @@ -3580,8 +3338,7 @@ static int hotkey_write(char *buf) hotkey_enabledisable_warn(0); res = -EPERM; } else if (strlencmp(cmd, "reset") == 0) { - mask = (hotkey_all_mask | hotkey_source_mask) - & ~hotkey_reserved_mask; + mask = hotkey_orig_mask; } else if (sscanf(cmd, "0x%x", &mask) == 1) { /* mask set */ } else if (sscanf(cmd, "%x", &mask) == 1) { @@ -5898,16 +5655,16 @@ static const struct tpacpi_quirk brightness_quirk_table[] __initconst = { /* Models with ATI GPUs known to require ECNVRAM mode */ TPACPI_Q_IBM('1', 'Y', TPACPI_BRGHT_Q_EC), /* T43/p ATI */ - /* Models with ATI GPUs that can use ECNVRAM */ - TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_EC), + /* Models with ATI GPUs (waiting confirmation) */ + TPACPI_Q_IBM('1', 'R', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), TPACPI_Q_IBM('1', 'Q', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), TPACPI_Q_IBM('7', '6', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), TPACPI_Q_IBM('7', '8', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_EC), - /* Models with Intel Extreme Graphics 2 */ - TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_NOEC), + /* Models with Intel Extreme Graphics 2 (waiting confirmation) */ TPACPI_Q_IBM('1', 'V', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), TPACPI_Q_IBM('1', 'W', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), + TPACPI_Q_IBM('1', 'U', TPACPI_BRGHT_Q_ASK|TPACPI_BRGHT_Q_NOEC), /* Models with Intel GMA900 */ TPACPI_Q_IBM('7', '0', TPACPI_BRGHT_Q_NOEC), /* T43, R52 */ @@ -7767,11 +7524,9 @@ static int __init probe_for_thinkpad(void) /* * Non-ancient models have better DMI tagging, but very old models - * don't. tpacpi_is_fw_known() is a cheat to help in that case. + * don't. */ - is_thinkpad = (thinkpad_id.model_str != NULL) || - (thinkpad_id.ec_model != 0) || - tpacpi_is_fw_known(); + is_thinkpad = (thinkpad_id.model_str != NULL); /* ec is required because many other handles are relative to it */ TPACPI_ACPIHANDLE_INIT(ec); @@ -7782,6 +7537,13 @@ static int __init probe_for_thinkpad(void) return -ENODEV; } + /* + * Risks a regression on very old machines, but reduces potential + * false positives a damn great deal + */ + if (!is_thinkpad) + is_thinkpad = (thinkpad_id.vendor == PCI_VENDOR_ID_IBM); + if (!is_thinkpad && !force_load) return -ENODEV; diff --git a/trunk/drivers/platform/x86/topstar-laptop.c b/trunk/drivers/platform/x86/topstar-laptop.c deleted file mode 100644 index 02f3d4e9e666..000000000000 --- a/trunk/drivers/platform/x86/topstar-laptop.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * ACPI driver for Topstar notebooks (hotkeys support only) - * - * Copyright (c) 2009 Herton Ronaldo Krzesinski - * - * Implementation inspired by existing x86 platform drivers, in special - * asus/eepc/fujitsu-laptop, thanks to their authors - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - */ - -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include -#include -#include -#include -#include - -#define ACPI_TOPSTAR_CLASS "topstar" - -struct topstar_hkey { - struct input_dev *inputdev; -}; - -struct tps_key_entry { - u8 code; - u16 keycode; -}; - -static struct tps_key_entry topstar_keymap[] = { - { 0x80, KEY_BRIGHTNESSUP }, - { 0x81, KEY_BRIGHTNESSDOWN }, - { 0x83, KEY_VOLUMEUP }, - { 0x84, KEY_VOLUMEDOWN }, - { 0x85, KEY_MUTE }, - { 0x86, KEY_SWITCHVIDEOMODE }, - { 0x87, KEY_F13 }, /* touchpad enable/disable key */ - { 0x88, KEY_WLAN }, - { 0x8a, KEY_WWW }, - { 0x8b, KEY_MAIL }, - { 0x8c, KEY_MEDIA }, - { 0x96, KEY_F14 }, /* G key? */ - { } -}; - -static struct tps_key_entry *tps_get_key_by_scancode(int code) -{ - struct tps_key_entry *key; - - for (key = topstar_keymap; key->code; key++) - if (code == key->code) - return key; - - return NULL; -} - -static struct tps_key_entry *tps_get_key_by_keycode(int code) -{ - struct tps_key_entry *key; - - for (key = topstar_keymap; key->code; key++) - if (code == key->keycode) - return key; - - return NULL; -} - -static void acpi_topstar_notify(struct acpi_device *device, u32 event) -{ - struct tps_key_entry *key; - static bool dup_evnt[2]; - bool *dup; - struct topstar_hkey *hkey = acpi_driver_data(device); - - /* 0x83 and 0x84 key events comes duplicated... */ - if (event == 0x83 || event == 0x84) { - dup = &dup_evnt[event - 0x83]; - if (*dup) { - *dup = false; - return; - } - *dup = true; - } - - /* - * 'G key' generate two event codes, convert to only - * one event/key code for now (3G switch?) - */ - if (event == 0x97) - event = 0x96; - - key = tps_get_key_by_scancode(event); - if (key) { - input_report_key(hkey->inputdev, key->keycode, 1); - input_sync(hkey->inputdev); - input_report_key(hkey->inputdev, key->keycode, 0); - input_sync(hkey->inputdev); - return; - } - - /* Known non hotkey events don't handled or that we don't care yet */ - if (event == 0x8e || event == 0x8f || event == 0x90) - return; - - pr_info("unknown event = 0x%02x\n", event); -} - -static int acpi_topstar_fncx_switch(struct acpi_device *device, bool state) -{ - acpi_status status; - union acpi_object fncx_params[1] = { - { .type = ACPI_TYPE_INTEGER } - }; - struct acpi_object_list fncx_arg_list = { 1, &fncx_params[0] }; - - fncx_params[0].integer.value = state ? 0x86 : 0x87; - status = acpi_evaluate_object(device->handle, "FNCX", &fncx_arg_list, NULL); - if (ACPI_FAILURE(status)) { - pr_err("Unable to switch FNCX notifications\n"); - return -ENODEV; - } - - return 0; -} - -static int topstar_getkeycode(struct input_dev *dev, int scancode, int *keycode) -{ - struct tps_key_entry *key = tps_get_key_by_scancode(scancode); - - if (!key) - return -EINVAL; - - *keycode = key->keycode; - return 0; -} - -static int topstar_setkeycode(struct input_dev *dev, int scancode, int keycode) -{ - struct tps_key_entry *key; - int old_keycode; - - if (keycode < 0 || keycode > KEY_MAX) - return -EINVAL; - - key = tps_get_key_by_scancode(scancode); - - if (!key) - return -EINVAL; - - old_keycode = key->keycode; - key->keycode = keycode; - set_bit(keycode, dev->keybit); - if (!tps_get_key_by_keycode(old_keycode)) - clear_bit(old_keycode, dev->keybit); - return 0; -} - -static int acpi_topstar_init_hkey(struct topstar_hkey *hkey) -{ - struct tps_key_entry *key; - - hkey->inputdev = input_allocate_device(); - if (!hkey->inputdev) { - pr_err("Unable to allocate input device\n"); - return -ENODEV; - } - hkey->inputdev->name = "Topstar Laptop extra buttons"; - hkey->inputdev->phys = "topstar/input0"; - hkey->inputdev->id.bustype = BUS_HOST; - hkey->inputdev->getkeycode = topstar_getkeycode; - hkey->inputdev->setkeycode = topstar_setkeycode; - for (key = topstar_keymap; key->code; key++) { - set_bit(EV_KEY, hkey->inputdev->evbit); - set_bit(key->keycode, hkey->inputdev->keybit); - } - if (input_register_device(hkey->inputdev)) { - pr_err("Unable to register input device\n"); - input_free_device(hkey->inputdev); - return -ENODEV; - } - - return 0; -} - -static int acpi_topstar_add(struct acpi_device *device) -{ - struct topstar_hkey *tps_hkey; - - tps_hkey = kzalloc(sizeof(struct topstar_hkey), GFP_KERNEL); - if (!tps_hkey) - return -ENOMEM; - - strcpy(acpi_device_name(device), "Topstar TPSACPI"); - strcpy(acpi_device_class(device), ACPI_TOPSTAR_CLASS); - - if (acpi_topstar_fncx_switch(device, true)) - goto add_err; - - if (acpi_topstar_init_hkey(tps_hkey)) - goto add_err; - - device->driver_data = tps_hkey; - return 0; - -add_err: - kfree(tps_hkey); - return -ENODEV; -} - -static int acpi_topstar_remove(struct acpi_device *device, int type) -{ - struct topstar_hkey *tps_hkey = acpi_driver_data(device); - - acpi_topstar_fncx_switch(device, false); - - input_unregister_device(tps_hkey->inputdev); - kfree(tps_hkey); - - return 0; -} - -static const struct acpi_device_id topstar_device_ids[] = { - { "TPSACPI01", 0 }, - { "", 0 }, -}; -MODULE_DEVICE_TABLE(acpi, topstar_device_ids); - -static struct acpi_driver acpi_topstar_driver = { - .name = "Topstar laptop ACPI driver", - .class = ACPI_TOPSTAR_CLASS, - .ids = topstar_device_ids, - .ops = { - .add = acpi_topstar_add, - .remove = acpi_topstar_remove, - .notify = acpi_topstar_notify, - }, -}; - -static int __init topstar_laptop_init(void) -{ - int ret; - - ret = acpi_bus_register_driver(&acpi_topstar_driver); - if (ret < 0) - return ret; - - printk(KERN_INFO "Topstar Laptop ACPI extras driver loaded\n"); - - return 0; -} - -static void __exit topstar_laptop_exit(void) -{ - acpi_bus_unregister_driver(&acpi_topstar_driver); -} - -module_init(topstar_laptop_init); -module_exit(topstar_laptop_exit); - -MODULE_AUTHOR("Herton Ronaldo Krzesinski"); -MODULE_DESCRIPTION("Topstar Laptop ACPI Extras driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/platform/x86/wmi.c b/trunk/drivers/platform/x86/wmi.c index 177f8d767df4..f215a5919192 100644 --- a/trunk/drivers/platform/x86/wmi.c +++ b/trunk/drivers/platform/x86/wmi.c @@ -42,6 +42,7 @@ MODULE_LICENSE("GPL"); #define ACPI_WMI_CLASS "wmi" +#undef PREFIX #define PREFIX "ACPI: WMI: " static DEFINE_MUTEX(wmi_data_lock); diff --git a/trunk/drivers/pnp/pnpacpi/core.c b/trunk/drivers/pnp/pnpacpi/core.c index c07fdb94d665..9496494f340e 100644 --- a/trunk/drivers/pnp/pnpacpi/core.c +++ b/trunk/drivers/pnp/pnpacpi/core.c @@ -194,13 +194,13 @@ static int __init pnpacpi_add_device(struct acpi_device *device) pnpacpi_parse_resource_option_data(dev); if (device->flags.compatible_ids) { - struct acpica_device_id_list *cid_list = device->pnp.cid_list; + struct acpi_compatible_id_list *cid_list = device->pnp.cid_list; int i; for (i = 0; i < cid_list->count; i++) { - if (!ispnpidacpi(cid_list->ids[i].string)) + if (!ispnpidacpi(cid_list->id[i].value)) continue; - pnp_add_id(dev, cid_list->ids[i].string); + pnp_add_id(dev, cid_list->id[i].value); } } diff --git a/trunk/drivers/regulator/Kconfig b/trunk/drivers/regulator/Kconfig index bcbb161bde0b..2dc42bbf6fe9 100644 --- a/trunk/drivers/regulator/Kconfig +++ b/trunk/drivers/regulator/Kconfig @@ -1,5 +1,6 @@ menuconfig REGULATOR bool "Voltage and Current Regulator Support" + default n help Generic Voltage and Current Regulator support. @@ -29,6 +30,7 @@ config REGULATOR_DEBUG config REGULATOR_FIXED_VOLTAGE tristate "Fixed voltage regulator support" + default n help This driver provides support for fixed voltage regulators, useful for systems which use a combination of software @@ -36,6 +38,7 @@ config REGULATOR_FIXED_VOLTAGE config REGULATOR_VIRTUAL_CONSUMER tristate "Virtual regulator consumer support" + default n help This driver provides a virtual consumer for the voltage and current regulator API which provides sysfs controls for @@ -46,15 +49,17 @@ config REGULATOR_VIRTUAL_CONSUMER config REGULATOR_USERSPACE_CONSUMER tristate "Userspace regulator consumer support" + default n help There are some classes of devices that are controlled entirely - from user space. Userspace consumer driver provides ability to + from user space. Usersapce consumer driver provides ability to control power supplies for such devices. If unsure, say no. config REGULATOR_BQ24022 tristate "TI bq24022 Dual Input 1-Cell Li-Ion Charger IC" + default n help This driver controls a TI bq24022 Charger attached via GPIOs. The provided current regulator can enable/disable @@ -64,6 +69,7 @@ config REGULATOR_BQ24022 config REGULATOR_MAX1586 tristate "Maxim 1586/1587 voltage regulator" depends on I2C + default n help This driver controls a Maxim 1586 or 1587 voltage output regulator via I2C bus. The provided regulator is suitable @@ -141,21 +147,5 @@ config REGULATOR_AB3100 AB3100 analog baseband dealing with power regulators for the system. -config REGULATOR_TPS65023 - tristate "TI TPS65023 Power regulators" - depends on I2C - help - This driver supports TPS65023 voltage regulator chips. TPS65023 provides - three step-down converters and two general-purpose LDO voltage regulators. - It supports TI's software based Class-2 SmartReflex implementation. - -config REGULATOR_TPS6507X - tristate "TI TPS6507X Power regulators" - depends on I2C - help - This driver supports TPS6507X voltage regulator chips. TPS6507X provides - three step-down converters and two general-purpose LDO voltage regulators. - It supports TI's software based Class-2 SmartReflex implementation. - endif diff --git a/trunk/drivers/regulator/Makefile b/trunk/drivers/regulator/Makefile index 4257a8683778..768b3316d6eb 100644 --- a/trunk/drivers/regulator/Makefile +++ b/trunk/drivers/regulator/Makefile @@ -23,7 +23,4 @@ obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o obj-$(CONFIG_REGULATOR_MC13783) += mc13783.o obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o -obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o -obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o - ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG diff --git a/trunk/drivers/regulator/core.c b/trunk/drivers/regulator/core.c index 744ea1d0b59b..91ba9bfaa706 100644 --- a/trunk/drivers/regulator/core.c +++ b/trunk/drivers/regulator/core.c @@ -37,7 +37,7 @@ static int has_full_constraints; */ struct regulator_map { struct list_head list; - const char *dev_name; /* The dev_name() for the consumer */ + struct device *dev; const char *supply; struct regulator_dev *regulator; }; @@ -232,7 +232,7 @@ static ssize_t regulator_name_show(struct device *dev, struct regulator_dev *rdev = dev_get_drvdata(dev); const char *name; - if (rdev->constraints && rdev->constraints->name) + if (rdev->constraints->name) name = rdev->constraints->name; else if (rdev->desc->name) name = rdev->desc->name; @@ -280,13 +280,8 @@ static ssize_t regulator_state_show(struct device *dev, struct device_attribute *attr, char *buf) { struct regulator_dev *rdev = dev_get_drvdata(dev); - ssize_t ret; - - mutex_lock(&rdev->mutex); - ret = regulator_print_state(buf, _regulator_is_enabled(rdev)); - mutex_unlock(&rdev->mutex); - return ret; + return regulator_print_state(buf, _regulator_is_enabled(rdev)); } static DEVICE_ATTR(state, 0444, regulator_state_show, NULL); @@ -862,39 +857,23 @@ static int set_supply(struct regulator_dev *rdev, * set_consumer_device_supply: Bind a regulator to a symbolic supply * @rdev: regulator source * @consumer_dev: device the supply applies to - * @consumer_dev_name: dev_name() string for device supply applies to * @supply: symbolic name for supply * * Allows platform initialisation code to map physical regulator * sources to symbolic names for supplies for use by devices. Devices * should use these symbolic names to request regulators, avoiding the * need to provide board-specific regulator names as platform data. - * - * Only one of consumer_dev and consumer_dev_name may be specified. */ static int set_consumer_device_supply(struct regulator_dev *rdev, - struct device *consumer_dev, const char *consumer_dev_name, - const char *supply) + struct device *consumer_dev, const char *supply) { struct regulator_map *node; - int has_dev; - - if (consumer_dev && consumer_dev_name) - return -EINVAL; - - if (!consumer_dev_name && consumer_dev) - consumer_dev_name = dev_name(consumer_dev); if (supply == NULL) return -EINVAL; - if (consumer_dev_name != NULL) - has_dev = 1; - else - has_dev = 0; - list_for_each_entry(node, ®ulator_map_list, list) { - if (consumer_dev_name != node->dev_name) + if (consumer_dev != node->dev) continue; if (strcmp(node->supply, supply) != 0) continue; @@ -907,45 +886,30 @@ static int set_consumer_device_supply(struct regulator_dev *rdev, return -EBUSY; } - node = kzalloc(sizeof(struct regulator_map), GFP_KERNEL); + node = kmalloc(sizeof(struct regulator_map), GFP_KERNEL); if (node == NULL) return -ENOMEM; node->regulator = rdev; + node->dev = consumer_dev; node->supply = supply; - if (has_dev) { - node->dev_name = kstrdup(consumer_dev_name, GFP_KERNEL); - if (node->dev_name == NULL) { - kfree(node); - return -ENOMEM; - } - } - list_add(&node->list, ®ulator_map_list); return 0; } static void unset_consumer_device_supply(struct regulator_dev *rdev, - const char *consumer_dev_name, struct device *consumer_dev) + struct device *consumer_dev) { struct regulator_map *node, *n; - if (consumer_dev && !consumer_dev_name) - consumer_dev_name = dev_name(consumer_dev); - list_for_each_entry_safe(node, n, ®ulator_map_list, list) { - if (rdev != node->regulator) - continue; - - if (consumer_dev_name && node->dev_name && - strcmp(consumer_dev_name, node->dev_name)) - continue; - - list_del(&node->list); - kfree(node->dev_name); - kfree(node); - return; + if (rdev == node->regulator && + consumer_dev == node->dev) { + list_del(&node->list); + kfree(node); + return; + } } } @@ -956,7 +920,6 @@ static void unset_regulator_supplies(struct regulator_dev *rdev) list_for_each_entry_safe(node, n, ®ulator_map_list, list) { if (rdev == node->regulator) { list_del(&node->list); - kfree(node->dev_name); kfree(node); return; } @@ -1038,33 +1001,35 @@ static struct regulator *create_regulator(struct regulator_dev *rdev, return NULL; } -/* Internal regulator request function */ -static struct regulator *_regulator_get(struct device *dev, const char *id, - int exclusive) +/** + * regulator_get - lookup and obtain a reference to a regulator. + * @dev: device for regulator "consumer" + * @id: Supply name or regulator ID. + * + * Returns a struct regulator corresponding to the regulator producer, + * or IS_ERR() condition containing errno. + * + * Use of supply names configured via regulator_set_device_supply() is + * strongly encouraged. It is recommended that the supply name used + * should match the name used for the supply and/or the relevant + * device pins in the datasheet. + */ +struct regulator *regulator_get(struct device *dev, const char *id) { struct regulator_dev *rdev; struct regulator_map *map; struct regulator *regulator = ERR_PTR(-ENODEV); - const char *devname = NULL; - int ret; if (id == NULL) { printk(KERN_ERR "regulator: get() with no identifier\n"); return regulator; } - if (dev) - devname = dev_name(dev); - mutex_lock(®ulator_list_mutex); list_for_each_entry(map, ®ulator_map_list, list) { - /* If the mapping has a device set up it must match */ - if (map->dev_name && - (!devname || strcmp(map->dev_name, devname))) - continue; - - if (strcmp(map->supply, id) == 0) { + if (dev == map->dev && + strcmp(map->supply, id) == 0) { rdev = map->regulator; goto found; } @@ -1073,16 +1038,6 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, return regulator; found: - if (rdev->exclusive) { - regulator = ERR_PTR(-EPERM); - goto out; - } - - if (exclusive && rdev->open_count) { - regulator = ERR_PTR(-EBUSY); - goto out; - } - if (!try_module_get(rdev->owner)) goto out; @@ -1092,69 +1047,12 @@ static struct regulator *_regulator_get(struct device *dev, const char *id, module_put(rdev->owner); } - rdev->open_count++; - if (exclusive) { - rdev->exclusive = 1; - - ret = _regulator_is_enabled(rdev); - if (ret > 0) - rdev->use_count = 1; - else - rdev->use_count = 0; - } - out: mutex_unlock(®ulator_list_mutex); - return regulator; } - -/** - * regulator_get - lookup and obtain a reference to a regulator. - * @dev: device for regulator "consumer" - * @id: Supply name or regulator ID. - * - * Returns a struct regulator corresponding to the regulator producer, - * or IS_ERR() condition containing errno. - * - * Use of supply names configured via regulator_set_device_supply() is - * strongly encouraged. It is recommended that the supply name used - * should match the name used for the supply and/or the relevant - * device pins in the datasheet. - */ -struct regulator *regulator_get(struct device *dev, const char *id) -{ - return _regulator_get(dev, id, 0); -} EXPORT_SYMBOL_GPL(regulator_get); -/** - * regulator_get_exclusive - obtain exclusive access to a regulator. - * @dev: device for regulator "consumer" - * @id: Supply name or regulator ID. - * - * Returns a struct regulator corresponding to the regulator producer, - * or IS_ERR() condition containing errno. Other consumers will be - * unable to obtain this reference is held and the use count for the - * regulator will be initialised to reflect the current state of the - * regulator. - * - * This is intended for use by consumers which cannot tolerate shared - * use of the regulator such as those which need to force the - * regulator off for correct operation of the hardware they are - * controlling. - * - * Use of supply names configured via regulator_set_device_supply() is - * strongly encouraged. It is recommended that the supply name used - * should match the name used for the supply and/or the relevant - * device pins in the datasheet. - */ -struct regulator *regulator_get_exclusive(struct device *dev, const char *id) -{ - return _regulator_get(dev, id, 1); -} -EXPORT_SYMBOL_GPL(regulator_get_exclusive); - /** * regulator_put - "free" the regulator source * @regulator: regulator source @@ -1183,29 +1081,21 @@ void regulator_put(struct regulator *regulator) list_del(®ulator->list); kfree(regulator); - rdev->open_count--; - rdev->exclusive = 0; - module_put(rdev->owner); mutex_unlock(®ulator_list_mutex); } EXPORT_SYMBOL_GPL(regulator_put); -static int _regulator_can_change_status(struct regulator_dev *rdev) -{ - if (!rdev->constraints) - return 0; - - if (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_STATUS) - return 1; - else - return 0; -} - /* locks held by regulator_enable() */ static int _regulator_enable(struct regulator_dev *rdev) { - int ret; + int ret = -EINVAL; + + if (!rdev->constraints) { + printk(KERN_ERR "%s: %s has no constraints\n", + __func__, rdev->desc->name); + return ret; + } /* do we need to enable the supply regulator first */ if (rdev->supply) { @@ -1218,35 +1108,24 @@ static int _regulator_enable(struct regulator_dev *rdev) } /* check voltage and requested load before enabling */ - if (rdev->constraints && - (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_DRMS)) - drms_uA_update(rdev); - - if (rdev->use_count == 0) { - /* The regulator may on if it's not switchable or left on */ - ret = _regulator_is_enabled(rdev); - if (ret == -EINVAL || ret == 0) { - if (!_regulator_can_change_status(rdev)) - return -EPERM; - - if (rdev->desc->ops->enable) { - ret = rdev->desc->ops->enable(rdev); - if (ret < 0) - return ret; - } else { - return -EINVAL; - } - } else if (ret < 0) { - printk(KERN_ERR "%s: is_enabled() failed for %s: %d\n", + if (rdev->desc->ops->enable) { + + if (rdev->constraints && + (rdev->constraints->valid_ops_mask & + REGULATOR_CHANGE_DRMS)) + drms_uA_update(rdev); + + ret = rdev->desc->ops->enable(rdev); + if (ret < 0) { + printk(KERN_ERR "%s: failed to enable %s: %d\n", __func__, rdev->desc->name, ret); return ret; } - /* Fallthrough on positive return values - already enabled */ + rdev->use_count++; + return ret; } - rdev->use_count++; - - return 0; + return ret; } /** @@ -1286,8 +1165,7 @@ static int _regulator_disable(struct regulator_dev *rdev) if (rdev->use_count == 1 && !rdev->constraints->always_on) { /* we are last user */ - if (_regulator_can_change_status(rdev) && - rdev->desc->ops->disable) { + if (rdev->desc->ops->disable) { ret = rdev->desc->ops->disable(rdev); if (ret < 0) { printk(KERN_ERR "%s: failed to disable %s\n", @@ -1387,11 +1265,20 @@ EXPORT_SYMBOL_GPL(regulator_force_disable); static int _regulator_is_enabled(struct regulator_dev *rdev) { + int ret; + + mutex_lock(&rdev->mutex); + /* sanity check */ - if (!rdev->desc->ops->is_enabled) - return -EINVAL; + if (!rdev->desc->ops->is_enabled) { + ret = -EINVAL; + goto out; + } - return rdev->desc->ops->is_enabled(rdev); + ret = rdev->desc->ops->is_enabled(rdev); +out: + mutex_unlock(&rdev->mutex); + return ret; } /** @@ -1408,13 +1295,7 @@ static int _regulator_is_enabled(struct regulator_dev *rdev) */ int regulator_is_enabled(struct regulator *regulator) { - int ret; - - mutex_lock(®ulator->rdev->mutex); - ret = _regulator_is_enabled(regulator->rdev); - mutex_unlock(®ulator->rdev->mutex); - - return ret; + return _regulator_is_enabled(regulator->rdev); } EXPORT_SYMBOL_GPL(regulator_is_enabled); @@ -1468,35 +1349,6 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector) } EXPORT_SYMBOL_GPL(regulator_list_voltage); -/** - * regulator_is_supported_voltage - check if a voltage range can be supported - * - * @regulator: Regulator to check. - * @min_uV: Minimum required voltage in uV. - * @max_uV: Maximum required voltage in uV. - * - * Returns a boolean or a negative error code. - */ -int regulator_is_supported_voltage(struct regulator *regulator, - int min_uV, int max_uV) -{ - int i, voltages, ret; - - ret = regulator_count_voltages(regulator); - if (ret < 0) - return ret; - voltages = ret; - - for (i = 0; i < voltages; i++) { - ret = regulator_list_voltage(regulator, i); - - if (ret >= min_uV && ret <= max_uV) - return 1; - } - - return 0; -} - /** * regulator_set_voltage - set regulator output voltage * @regulator: regulator source @@ -2239,13 +2091,11 @@ struct regulator_dev *regulator_register(struct regulator_desc *regulator_desc, for (i = 0; i < init_data->num_consumer_supplies; i++) { ret = set_consumer_device_supply(rdev, init_data->consumer_supplies[i].dev, - init_data->consumer_supplies[i].dev_name, init_data->consumer_supplies[i].supply); if (ret < 0) { for (--i; i >= 0; i--) unset_consumer_device_supply(rdev, - init_data->consumer_supplies[i].dev_name, - init_data->consumer_supplies[i].dev); + init_data->consumer_supplies[i].dev); goto scrub; } } @@ -2280,7 +2130,6 @@ void regulator_unregister(struct regulator_dev *rdev) return; mutex_lock(®ulator_list_mutex); - WARN_ON(rdev->open_count); unset_regulator_supplies(rdev); list_del(&rdev->list); if (rdev->supply) @@ -2428,14 +2277,14 @@ static int __init regulator_init_complete(void) ops = rdev->desc->ops; c = rdev->constraints; - if (c && c->name) + if (c->name) name = c->name; else if (rdev->desc->name) name = rdev->desc->name; else name = "regulator"; - if (!ops->disable || (c && c->always_on)) + if (!ops->disable || c->always_on) continue; mutex_lock(&rdev->mutex); diff --git a/trunk/drivers/regulator/da903x.c b/trunk/drivers/regulator/da903x.c index aa224d936e0d..b8b89ef10a84 100644 --- a/trunk/drivers/regulator/da903x.c +++ b/trunk/drivers/regulator/da903x.c @@ -64,14 +64,6 @@ #define DA9034_MDTV2 (0x33) #define DA9034_MVRC (0x34) -/* DA9035 Registers. DA9034 Registers are comptabile to DA9035. */ -#define DA9035_OVER3 (0x12) -#define DA9035_VCC2 (0x1f) -#define DA9035_3DTV1 (0x2c) -#define DA9035_3DTV2 (0x2d) -#define DA9035_3VRC (0x2e) -#define DA9035_AUTOSKIP (0x2f) - struct da903x_regulator_info { struct regulator_desc desc; @@ -87,10 +79,6 @@ struct da903x_regulator_info { int enable_bit; }; -static int da9034_ldo12_data[] = { 1700, 1750, 1800, 1850, 1900, 1950, - 2000, 2050, 2700, 2750, 2800, 2850, - 2900, 2950, 3000, 3050 }; - static inline struct device *to_da903x_dev(struct regulator_dev *rdev) { return rdev_get_dev(rdev)->parent->parent; @@ -174,17 +162,6 @@ static int da903x_is_enabled(struct regulator_dev *rdev) return !!(reg_val & (1 << info->enable_bit)); } -static int da903x_list_voltage(struct regulator_dev *rdev, unsigned selector) -{ - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); - int ret; - - ret = info->min_uV + info->step_uV * selector; - if (ret > info->max_uV) - return -EINVAL; - return ret; -} - /* DA9030 specific operations */ static int da9030_set_ldo1_15_voltage(struct regulator_dev *rdev, int min_uV, int max_uV) @@ -301,7 +278,7 @@ static int da9034_set_ldo12_voltage(struct regulator_dev *rdev, } val = (min_uV - info->min_uV + info->step_uV - 1) / info->step_uV; - val = (val >= 20) ? val - 12 : ((val > 7) ? 8 : val); + val = (val > 7 || val < 20) ? 8 : val - 12; val <<= info->vol_shift; mask = ((1 << info->vol_nbits) - 1) << info->vol_shift; @@ -328,18 +305,9 @@ static int da9034_get_ldo12_voltage(struct regulator_dev *rdev) return info->min_uV + info->step_uV * val; } -static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, - unsigned selector) -{ - if (selector > ARRAY_SIZE(da9034_ldo12_data)) - return -EINVAL; - return da9034_ldo12_data[selector] * 1000; -} - static struct regulator_ops da903x_regulator_ldo_ops = { .set_voltage = da903x_set_ldo_voltage, .get_voltage = da903x_get_voltage, - .list_voltage = da903x_list_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -349,7 +317,6 @@ static struct regulator_ops da903x_regulator_ldo_ops = { static struct regulator_ops da9030_regulator_ldo14_ops = { .set_voltage = da9030_set_ldo14_voltage, .get_voltage = da9030_get_ldo14_voltage, - .list_voltage = da903x_list_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -359,7 +326,6 @@ static struct regulator_ops da9030_regulator_ldo14_ops = { static struct regulator_ops da9030_regulator_ldo1_15_ops = { .set_voltage = da9030_set_ldo1_15_voltage, .get_voltage = da903x_get_voltage, - .list_voltage = da903x_list_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -368,7 +334,6 @@ static struct regulator_ops da9030_regulator_ldo1_15_ops = { static struct regulator_ops da9034_regulator_dvc_ops = { .set_voltage = da9034_set_dvc_voltage, .get_voltage = da903x_get_voltage, - .list_voltage = da903x_list_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -378,7 +343,6 @@ static struct regulator_ops da9034_regulator_dvc_ops = { static struct regulator_ops da9034_regulator_ldo12_ops = { .set_voltage = da9034_set_ldo12_voltage, .get_voltage = da9034_get_ldo12_voltage, - .list_voltage = da9034_list_ldo12_voltage, .enable = da903x_enable, .disable = da903x_disable, .is_enabled = da903x_is_enabled, @@ -391,7 +355,6 @@ static struct regulator_ops da9034_regulator_ldo12_ops = { .ops = &da903x_regulator_ldo_ops, \ .type = REGULATOR_VOLTAGE, \ .id = _pmic##_ID_LDO##_id, \ - .n_voltages = (step) ? ((max - min) / step + 1) : 1, \ .owner = THIS_MODULE, \ }, \ .min_uV = (min) * 1000, \ @@ -404,25 +367,24 @@ static struct regulator_ops da9034_regulator_ldo12_ops = { .enable_bit = (ebit), \ } -#define DA903x_DVC(_pmic, _id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \ +#define DA9034_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \ { \ .desc = { \ .name = #_id, \ .ops = &da9034_regulator_dvc_ops, \ .type = REGULATOR_VOLTAGE, \ - .id = _pmic##_ID_##_id, \ - .n_voltages = (step) ? ((max - min) / step + 1) : 1, \ + .id = DA9034_ID_##_id, \ .owner = THIS_MODULE, \ }, \ .min_uV = (min) * 1000, \ .max_uV = (max) * 1000, \ .step_uV = (step) * 1000, \ - .vol_reg = _pmic##_##vreg, \ + .vol_reg = DA9034_##vreg, \ .vol_shift = (0), \ .vol_nbits = (nbits), \ - .update_reg = _pmic##_##ureg, \ + .update_reg = DA9034_##ureg, \ .update_bit = (ubit), \ - .enable_reg = _pmic##_##ereg, \ + .enable_reg = DA9034_##ereg, \ .enable_bit = (ebit), \ } @@ -432,22 +394,8 @@ static struct regulator_ops da9034_regulator_ldo12_ops = { #define DA9030_LDO(_id, min, max, step, vreg, shift, nbits, ereg, ebit) \ DA903x_LDO(DA9030, _id, min, max, step, vreg, shift, nbits, ereg, ebit) -#define DA9030_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \ - DA903x_DVC(DA9030, _id, min, max, step, vreg, nbits, ureg, ubit, \ - ereg, ebit) - -#define DA9034_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \ - DA903x_DVC(DA9034, _id, min, max, step, vreg, nbits, ureg, ubit, \ - ereg, ebit) - -#define DA9035_DVC(_id, min, max, step, vreg, nbits, ureg, ubit, ereg, ebit) \ - DA903x_DVC(DA9035, _id, min, max, step, vreg, nbits, ureg, ubit, \ - ereg, ebit) - static struct da903x_regulator_info da903x_regulator_info[] = { /* DA9030 */ - DA9030_DVC(BUCK2, 850, 1625, 25, BUCK2DVM1, 5, BUCK2DVM1, 7, RCTL11, 0), - DA9030_LDO( 1, 1200, 3200, 100, LDO1, 0, 5, RCTL12, 1), DA9030_LDO( 2, 1800, 3200, 100, LDO23, 0, 4, RCTL12, 2), DA9030_LDO( 3, 1800, 3200, 100, LDO23, 4, 4, RCTL12, 3), @@ -469,9 +417,9 @@ static struct da903x_regulator_info da903x_regulator_info[] = { DA9030_LDO(13, 2100, 2100, 0, INVAL, 0, 0, RCTL11, 3), /* fixed @2.1V */ /* DA9034 */ - DA9034_DVC(BUCK1, 725, 1500, 25, ADTV2, 5, VCC1, 0, OVER1, 0), - DA9034_DVC(BUCK2, 725, 1500, 25, CDTV2, 5, VCC1, 2, OVER1, 1), - DA9034_DVC(LDO2, 725, 1500, 25, SDTV2, 5, VCC1, 4, OVER1, 2), + DA9034_DVC(BUCK1, 725, 1500, 25, ADTV1, 5, VCC1, 0, OVER1, 0), + DA9034_DVC(BUCK2, 725, 1500, 25, CDTV1, 5, VCC1, 2, OVER1, 1), + DA9034_DVC(LDO2, 725, 1500, 25, SDTV1, 5, VCC1, 4, OVER1, 2), DA9034_DVC(LDO1, 1700, 2075, 25, MDTV1, 4, VCC1, 6, OVER3, 4), DA9034_LDO( 3, 1800, 3300, 100, LDO643, 0, 4, OVER3, 5), @@ -487,9 +435,6 @@ static struct da903x_regulator_info da903x_regulator_info[] = { DA9034_LDO(14, 1800, 3300, 100, LDO1514, 0, 4, OVER3, 0), DA9034_LDO(15, 1800, 3300, 100, LDO1514, 4, 4, OVER3, 1), DA9034_LDO(5, 3100, 3100, 0, INVAL, 0, 0, OVER3, 7), /* fixed @3.1V */ - - /* DA9035 */ - DA9035_DVC(BUCK3, 1800, 2200, 100, 3DTV1, 3, VCC2, 0, OVER3, 3), }; static inline struct da903x_regulator_info *find_regulator_info(int id) @@ -517,10 +462,8 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev) } /* Workaround for the weird LDO12 voltage setting */ - if (ri->desc.id == DA9034_ID_LDO12) { + if (ri->desc.id == DA9034_ID_LDO12) ri->desc.ops = &da9034_regulator_ldo12_ops; - ri->desc.n_voltages = ARRAY_SIZE(da9034_ldo12_data); - } if (ri->desc.id == DA9030_ID_LDO14) ri->desc.ops = &da9030_regulator_ldo14_ops; diff --git a/trunk/drivers/regulator/fixed.c b/trunk/drivers/regulator/fixed.c index f8b295700d7d..cdc674fb46c3 100644 --- a/trunk/drivers/regulator/fixed.c +++ b/trunk/drivers/regulator/fixed.c @@ -5,9 +5,6 @@ * * Author: Mark Brown * - * Copyright (c) 2009 Nokia Corporation - * Roger Quadros - * * 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 @@ -23,45 +20,20 @@ #include #include #include -#include struct fixed_voltage_data { struct regulator_desc desc; struct regulator_dev *dev; int microvolts; - int gpio; - unsigned enable_high:1; - unsigned is_enabled:1; }; static int fixed_voltage_is_enabled(struct regulator_dev *dev) { - struct fixed_voltage_data *data = rdev_get_drvdata(dev); - - return data->is_enabled; + return 1; } static int fixed_voltage_enable(struct regulator_dev *dev) { - struct fixed_voltage_data *data = rdev_get_drvdata(dev); - - if (gpio_is_valid(data->gpio)) { - gpio_set_value_cansleep(data->gpio, data->enable_high); - data->is_enabled = 1; - } - - return 0; -} - -static int fixed_voltage_disable(struct regulator_dev *dev) -{ - struct fixed_voltage_data *data = rdev_get_drvdata(dev); - - if (gpio_is_valid(data->gpio)) { - gpio_set_value_cansleep(data->gpio, !data->enable_high); - data->is_enabled = 0; - } - return 0; } @@ -86,7 +58,6 @@ static int fixed_voltage_list_voltage(struct regulator_dev *dev, static struct regulator_ops fixed_voltage_ops = { .is_enabled = fixed_voltage_is_enabled, .enable = fixed_voltage_enable, - .disable = fixed_voltage_disable, .get_voltage = fixed_voltage_get_voltage, .list_voltage = fixed_voltage_list_voltage, }; @@ -99,14 +70,12 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev) drvdata = kzalloc(sizeof(struct fixed_voltage_data), GFP_KERNEL); if (drvdata == NULL) { - dev_err(&pdev->dev, "Failed to allocate device data\n"); ret = -ENOMEM; goto err; } drvdata->desc.name = kstrdup(config->supply_name, GFP_KERNEL); if (drvdata->desc.name == NULL) { - dev_err(&pdev->dev, "Failed to allocate supply name\n"); ret = -ENOMEM; goto err; } @@ -116,62 +85,12 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev) drvdata->desc.n_voltages = 1; drvdata->microvolts = config->microvolts; - drvdata->gpio = config->gpio; - - if (gpio_is_valid(config->gpio)) { - drvdata->enable_high = config->enable_high; - - /* FIXME: Remove below print warning - * - * config->gpio must be set to -EINVAL by platform code if - * GPIO control is not required. However, early adopters - * not requiring GPIO control may forget to initialize - * config->gpio to -EINVAL. This will cause GPIO 0 to be used - * for GPIO control. - * - * This warning will be removed once there are a couple of users - * for this driver. - */ - if (!config->gpio) - dev_warn(&pdev->dev, - "using GPIO 0 for regulator enable control\n"); - - ret = gpio_request(config->gpio, config->supply_name); - if (ret) { - dev_err(&pdev->dev, - "Could not obtain regulator enable GPIO %d: %d\n", - config->gpio, ret); - goto err_name; - } - - /* set output direction without changing state - * to prevent glitch - */ - drvdata->is_enabled = config->enabled_at_boot; - ret = drvdata->is_enabled ? - config->enable_high : !config->enable_high; - - ret = gpio_direction_output(config->gpio, ret); - if (ret) { - dev_err(&pdev->dev, - "Could not configure regulator enable GPIO %d direction: %d\n", - config->gpio, ret); - goto err_gpio; - } - - } else { - /* Regulator without GPIO control is considered - * always enabled - */ - drvdata->is_enabled = 1; - } drvdata->dev = regulator_register(&drvdata->desc, &pdev->dev, config->init_data, drvdata); if (IS_ERR(drvdata->dev)) { ret = PTR_ERR(drvdata->dev); - dev_err(&pdev->dev, "Failed to register regulator: %d\n", ret); - goto err_gpio; + goto err_name; } platform_set_drvdata(pdev, drvdata); @@ -181,9 +100,6 @@ static int regulator_fixed_voltage_probe(struct platform_device *pdev) return 0; -err_gpio: - if (gpio_is_valid(config->gpio)) - gpio_free(config->gpio); err_name: kfree(drvdata->desc.name); err: @@ -199,9 +115,6 @@ static int regulator_fixed_voltage_remove(struct platform_device *pdev) kfree(drvdata->desc.name); kfree(drvdata); - if (gpio_is_valid(drvdata->gpio)) - gpio_free(drvdata->gpio); - return 0; } diff --git a/trunk/drivers/regulator/lp3971.c b/trunk/drivers/regulator/lp3971.c index 7803a320543b..a61018a27698 100644 --- a/trunk/drivers/regulator/lp3971.c +++ b/trunk/drivers/regulator/lp3971.c @@ -541,7 +541,7 @@ static struct i2c_driver lp3971_i2c_driver = { static int __init lp3971_module_init(void) { - int ret; + int ret = -ENODEV; ret = i2c_add_driver(&lp3971_i2c_driver); if (ret != 0) diff --git a/trunk/drivers/regulator/pcf50633-regulator.c b/trunk/drivers/regulator/pcf50633-regulator.c index 0803ffe6236d..8e14900eb686 100644 --- a/trunk/drivers/regulator/pcf50633-regulator.c +++ b/trunk/drivers/regulator/pcf50633-regulator.c @@ -24,12 +24,11 @@ #include #include -#define PCF50633_REGULATOR(_name, _id, _n) \ +#define PCF50633_REGULATOR(_name, _id) \ { \ .name = _name, \ .id = _id, \ .ops = &pcf50633_regulator_ops, \ - .n_voltages = _n, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ } @@ -150,44 +149,13 @@ static int pcf50633_regulator_set_voltage(struct regulator_dev *rdev, return pcf50633_reg_write(pcf, regnr, volt_bits); } -static int pcf50633_regulator_voltage_value(enum pcf50633_regulator_id id, - u8 bits) -{ - int millivolts; - - switch (id) { - case PCF50633_REGULATOR_AUTO: - millivolts = auto_voltage_value(bits); - break; - case PCF50633_REGULATOR_DOWN1: - millivolts = down_voltage_value(bits); - break; - case PCF50633_REGULATOR_DOWN2: - millivolts = down_voltage_value(bits); - break; - case PCF50633_REGULATOR_LDO1: - case PCF50633_REGULATOR_LDO2: - case PCF50633_REGULATOR_LDO3: - case PCF50633_REGULATOR_LDO4: - case PCF50633_REGULATOR_LDO5: - case PCF50633_REGULATOR_LDO6: - case PCF50633_REGULATOR_HCLDO: - millivolts = ldo_voltage_value(bits); - break; - default: - return -EINVAL; - } - - return millivolts * 1000; -} - static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev) { struct pcf50633 *pcf; - int regulator_id; - u8 volt_bits, regnr; + int regulator_id, millivolts, volt_bits; + u8 regnr; - pcf = rdev_get_drvdata(rdev); + pcf = rdev_get_drvdata(rdev);; regulator_id = rdev_get_id(rdev); if (regulator_id >= PCF50633_NUM_REGULATORS) @@ -196,32 +164,33 @@ static int pcf50633_regulator_get_voltage(struct regulator_dev *rdev) regnr = pcf50633_regulator_registers[regulator_id]; volt_bits = pcf50633_reg_read(pcf, regnr); - - return pcf50633_regulator_voltage_value(regulator_id, volt_bits); -} - -static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, - unsigned int index) -{ - struct pcf50633 *pcf; - int regulator_id; - - pcf = rdev_get_drvdata(rdev); - - regulator_id = rdev_get_id(rdev); + if (volt_bits < 0) + return -1; switch (regulator_id) { case PCF50633_REGULATOR_AUTO: - index += 0x2f; + millivolts = auto_voltage_value(volt_bits); break; + case PCF50633_REGULATOR_DOWN1: + millivolts = down_voltage_value(volt_bits); + break; + case PCF50633_REGULATOR_DOWN2: + millivolts = down_voltage_value(volt_bits); + break; + case PCF50633_REGULATOR_LDO1: + case PCF50633_REGULATOR_LDO2: + case PCF50633_REGULATOR_LDO3: + case PCF50633_REGULATOR_LDO4: + case PCF50633_REGULATOR_LDO5: + case PCF50633_REGULATOR_LDO6: case PCF50633_REGULATOR_HCLDO: - index += 0x01; + millivolts = ldo_voltage_value(volt_bits); break; default: - break; + return -EINVAL; } - return pcf50633_regulator_voltage_value(regulator_id, index); + return millivolts * 1000; } static int pcf50633_regulator_enable(struct regulator_dev *rdev) @@ -277,7 +246,6 @@ static int pcf50633_regulator_is_enabled(struct regulator_dev *rdev) static struct regulator_ops pcf50633_regulator_ops = { .set_voltage = pcf50633_regulator_set_voltage, .get_voltage = pcf50633_regulator_get_voltage, - .list_voltage = pcf50633_regulator_list_voltage, .enable = pcf50633_regulator_enable, .disable = pcf50633_regulator_disable, .is_enabled = pcf50633_regulator_is_enabled, @@ -285,27 +253,27 @@ static struct regulator_ops pcf50633_regulator_ops = { static struct regulator_desc regulators[] = { [PCF50633_REGULATOR_AUTO] = - PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO, 80), + PCF50633_REGULATOR("auto", PCF50633_REGULATOR_AUTO), [PCF50633_REGULATOR_DOWN1] = - PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1, 95), + PCF50633_REGULATOR("down1", PCF50633_REGULATOR_DOWN1), [PCF50633_REGULATOR_DOWN2] = - PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2, 95), + PCF50633_REGULATOR("down2", PCF50633_REGULATOR_DOWN2), [PCF50633_REGULATOR_LDO1] = - PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1, 27), + PCF50633_REGULATOR("ldo1", PCF50633_REGULATOR_LDO1), [PCF50633_REGULATOR_LDO2] = - PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2, 27), + PCF50633_REGULATOR("ldo2", PCF50633_REGULATOR_LDO2), [PCF50633_REGULATOR_LDO3] = - PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3, 27), + PCF50633_REGULATOR("ldo3", PCF50633_REGULATOR_LDO3), [PCF50633_REGULATOR_LDO4] = - PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4, 27), + PCF50633_REGULATOR("ldo4", PCF50633_REGULATOR_LDO4), [PCF50633_REGULATOR_LDO5] = - PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5, 27), + PCF50633_REGULATOR("ldo5", PCF50633_REGULATOR_LDO5), [PCF50633_REGULATOR_LDO6] = - PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6, 27), + PCF50633_REGULATOR("ldo6", PCF50633_REGULATOR_LDO6), [PCF50633_REGULATOR_HCLDO] = - PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO, 26), + PCF50633_REGULATOR("hcldo", PCF50633_REGULATOR_HCLDO), [PCF50633_REGULATOR_MEMLDO] = - PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO, 0), + PCF50633_REGULATOR("memldo", PCF50633_REGULATOR_MEMLDO), }; static int __devinit pcf50633_regulator_probe(struct platform_device *pdev) diff --git a/trunk/drivers/regulator/tps65023-regulator.c b/trunk/drivers/regulator/tps65023-regulator.c deleted file mode 100644 index 07fda0a75adf..000000000000 --- a/trunk/drivers/regulator/tps65023-regulator.c +++ /dev/null @@ -1,632 +0,0 @@ -/* - * tps65023-regulator.c - * - * Supports TPS65023 Regulator - * - * Copyright (C) 2009 Texas Instrument Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Register definitions */ -#define TPS65023_REG_VERSION 0 -#define TPS65023_REG_PGOODZ 1 -#define TPS65023_REG_MASK 2 -#define TPS65023_REG_REG_CTRL 3 -#define TPS65023_REG_CON_CTRL 4 -#define TPS65023_REG_CON_CTRL2 5 -#define TPS65023_REG_DEF_CORE 6 -#define TPS65023_REG_DEFSLEW 7 -#define TPS65023_REG_LDO_CTRL 8 - -/* PGOODZ bitfields */ -#define TPS65023_PGOODZ_PWRFAILZ BIT(7) -#define TPS65023_PGOODZ_LOWBATTZ BIT(6) -#define TPS65023_PGOODZ_VDCDC1 BIT(5) -#define TPS65023_PGOODZ_VDCDC2 BIT(4) -#define TPS65023_PGOODZ_VDCDC3 BIT(3) -#define TPS65023_PGOODZ_LDO2 BIT(2) -#define TPS65023_PGOODZ_LDO1 BIT(1) - -/* MASK bitfields */ -#define TPS65023_MASK_PWRFAILZ BIT(7) -#define TPS65023_MASK_LOWBATTZ BIT(6) -#define TPS65023_MASK_VDCDC1 BIT(5) -#define TPS65023_MASK_VDCDC2 BIT(4) -#define TPS65023_MASK_VDCDC3 BIT(3) -#define TPS65023_MASK_LDO2 BIT(2) -#define TPS65023_MASK_LDO1 BIT(1) - -/* REG_CTRL bitfields */ -#define TPS65023_REG_CTRL_VDCDC1_EN BIT(5) -#define TPS65023_REG_CTRL_VDCDC2_EN BIT(4) -#define TPS65023_REG_CTRL_VDCDC3_EN BIT(3) -#define TPS65023_REG_CTRL_LDO2_EN BIT(2) -#define TPS65023_REG_CTRL_LDO1_EN BIT(1) - -/* LDO_CTRL bitfields */ -#define TPS65023_LDO_CTRL_LDOx_SHIFT(ldo_id) ((ldo_id)*4) -#define TPS65023_LDO_CTRL_LDOx_MASK(ldo_id) (0xF0 >> ((ldo_id)*4)) - -/* Number of step-down converters available */ -#define TPS65023_NUM_DCDC 3 -/* Number of LDO voltage regulators available */ -#define TPS65023_NUM_LDO 2 -/* Number of total regulators available */ -#define TPS65023_NUM_REGULATOR (TPS65023_NUM_DCDC + TPS65023_NUM_LDO) - -/* DCDCs */ -#define TPS65023_DCDC_1 0 -#define TPS65023_DCDC_2 1 -#define TPS65023_DCDC_3 2 -/* LDOs */ -#define TPS65023_LDO_1 3 -#define TPS65023_LDO_2 4 - -#define TPS65023_MAX_REG_ID TPS65023_LDO_2 - -/* Supported voltage values for regulators */ -static const u16 VDCDC1_VSEL_table[] = { - 800, 825, 850, 875, - 900, 925, 950, 975, - 1000, 1025, 1050, 1075, - 1100, 1125, 1150, 1175, - 1200, 1225, 1250, 1275, - 1300, 1325, 1350, 1375, - 1400, 1425, 1450, 1475, - 1500, 1525, 1550, 1600, -}; - -static const u16 LDO1_VSEL_table[] = { - 1000, 1100, 1300, 1800, - 2200, 2600, 2800, 3150, -}; - -static const u16 LDO2_VSEL_table[] = { - 1050, 1200, 1300, 1800, - 2500, 2800, 3000, 3300, -}; - -static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDC1_VSEL_table), - 0, 0, ARRAY_SIZE(LDO1_VSEL_table), - ARRAY_SIZE(LDO2_VSEL_table)}; - -/* Regulator specific details */ -struct tps_info { - const char *name; - unsigned min_uV; - unsigned max_uV; - bool fixed; - u8 table_len; - const u16 *table; -}; - -/* PMIC details */ -struct tps_pmic { - struct regulator_desc desc[TPS65023_NUM_REGULATOR]; - struct i2c_client *client; - struct regulator_dev *rdev[TPS65023_NUM_REGULATOR]; - const struct tps_info *info[TPS65023_NUM_REGULATOR]; - struct mutex io_lock; -}; - -static inline int tps_65023_read(struct tps_pmic *tps, u8 reg) -{ - return i2c_smbus_read_byte_data(tps->client, reg); -} - -static inline int tps_65023_write(struct tps_pmic *tps, u8 reg, u8 val) -{ - return i2c_smbus_write_byte_data(tps->client, reg, val); -} - -static int tps_65023_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) -{ - int err, data; - - mutex_lock(&tps->io_lock); - - data = tps_65023_read(tps, reg); - if (data < 0) { - dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); - err = data; - goto out; - } - - data |= mask; - err = tps_65023_write(tps, reg, data); - if (err) - dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); - -out: - mutex_unlock(&tps->io_lock); - return err; -} - -static int tps_65023_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask) -{ - int err, data; - - mutex_lock(&tps->io_lock); - - data = tps_65023_read(tps, reg); - if (data < 0) { - dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); - err = data; - goto out; - } - - data &= ~mask; - - err = tps_65023_write(tps, reg, data); - if (err) - dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); - -out: - mutex_unlock(&tps->io_lock); - return err; - -} - -static int tps_65023_reg_read(struct tps_pmic *tps, u8 reg) -{ - int data; - - mutex_lock(&tps->io_lock); - - data = tps_65023_read(tps, reg); - if (data < 0) - dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); - - mutex_unlock(&tps->io_lock); - return data; -} - -static int tps_65023_reg_write(struct tps_pmic *tps, u8 reg, u8 val) -{ - int err; - - mutex_lock(&tps->io_lock); - - err = tps_65023_write(tps, reg, val); - if (err < 0) - dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); - - mutex_unlock(&tps->io_lock); - return err; -} - -static int tps65023_dcdc_is_enabled(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, dcdc = rdev_get_id(dev); - u8 shift; - - if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) - return -EINVAL; - - shift = TPS65023_NUM_REGULATOR - dcdc; - data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL); - - if (data < 0) - return data; - else - return (data & 1< TPS65023_LDO_2) - return -EINVAL; - - shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - data = tps_65023_reg_read(tps, TPS65023_REG_REG_CTRL); - - if (data < 0) - return data; - else - return (data & 1< TPS65023_DCDC_3) - return -EINVAL; - - shift = TPS65023_NUM_REGULATOR - dcdc; - return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift); -} - -static int tps65023_dcdc_disable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int dcdc = rdev_get_id(dev); - u8 shift; - - if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) - return -EINVAL; - - shift = TPS65023_NUM_REGULATOR - dcdc; - return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift); -} - -static int tps65023_ldo_enable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - u8 shift; - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - return tps_65023_set_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift); -} - -static int tps65023_ldo_disable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - u8 shift; - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - shift = (ldo == TPS65023_LDO_1 ? 1 : 2); - return tps_65023_clear_bits(tps, TPS65023_REG_REG_CTRL, 1 << shift); -} - -static int tps65023_dcdc_get_voltage(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, dcdc = rdev_get_id(dev); - - if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) - return -EINVAL; - - if (dcdc == TPS65023_DCDC_1) { - data = tps_65023_reg_read(tps, TPS65023_REG_DEF_CORE); - if (data < 0) - return data; - data &= (tps->info[dcdc]->table_len - 1); - return tps->info[dcdc]->table[data] * 1000; - } else - return tps->info[dcdc]->min_uV; -} - -static int tps65023_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int dcdc = rdev_get_id(dev); - int vsel; - - if (dcdc != TPS65023_DCDC_1) - return -EINVAL; - - if (min_uV < tps->info[dcdc]->min_uV - || min_uV > tps->info[dcdc]->max_uV) - return -EINVAL; - if (max_uV < tps->info[dcdc]->min_uV - || max_uV > tps->info[dcdc]->max_uV) - return -EINVAL; - - for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) { - int mV = tps->info[dcdc]->table[vsel]; - int uV = mV * 1000; - - /* Break at the first in-range value */ - if (min_uV <= uV && uV <= max_uV) - break; - } - - /* write to the register in case we found a match */ - if (vsel == tps->info[dcdc]->table_len) - return -EINVAL; - else - return tps_65023_reg_write(tps, TPS65023_REG_DEF_CORE, vsel); -} - -static int tps65023_ldo_get_voltage(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, ldo = rdev_get_id(dev); - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL); - if (data < 0) - return data; - - data >>= (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1)); - data &= (tps->info[ldo]->table_len - 1); - return tps->info[ldo]->table[data] * 1000; -} - -static int tps65023_ldo_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, vsel, ldo = rdev_get_id(dev); - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV) - return -EINVAL; - if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV) - return -EINVAL; - - for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) { - int mV = tps->info[ldo]->table[vsel]; - int uV = mV * 1000; - - /* Break at the first in-range value */ - if (min_uV <= uV && uV <= max_uV) - break; - } - - if (vsel == tps->info[ldo]->table_len) - return -EINVAL; - - data = tps_65023_reg_read(tps, TPS65023_REG_LDO_CTRL); - if (data < 0) - return data; - - data &= TPS65023_LDO_CTRL_LDOx_MASK(ldo - TPS65023_LDO_1); - data |= (vsel << (TPS65023_LDO_CTRL_LDOx_SHIFT(ldo - TPS65023_LDO_1))); - return tps_65023_reg_write(tps, TPS65023_REG_LDO_CTRL, data); -} - -static int tps65023_dcdc_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int dcdc = rdev_get_id(dev); - - if (dcdc < TPS65023_DCDC_1 || dcdc > TPS65023_DCDC_3) - return -EINVAL; - - if (dcdc == TPS65023_DCDC_1) { - if (selector >= tps->info[dcdc]->table_len) - return -EINVAL; - else - return tps->info[dcdc]->table[selector] * 1000; - } else - return tps->info[dcdc]->min_uV; -} - -static int tps65023_ldo_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - - if (ldo < TPS65023_LDO_1 || ldo > TPS65023_LDO_2) - return -EINVAL; - - if (selector >= tps->info[ldo]->table_len) - return -EINVAL; - else - return tps->info[ldo]->table[selector] * 1000; -} - -/* Operations permitted on VDCDCx */ -static struct regulator_ops tps65023_dcdc_ops = { - .is_enabled = tps65023_dcdc_is_enabled, - .enable = tps65023_dcdc_enable, - .disable = tps65023_dcdc_disable, - .get_voltage = tps65023_dcdc_get_voltage, - .set_voltage = tps65023_dcdc_set_voltage, - .list_voltage = tps65023_dcdc_list_voltage, -}; - -/* Operations permitted on LDOx */ -static struct regulator_ops tps65023_ldo_ops = { - .is_enabled = tps65023_ldo_is_enabled, - .enable = tps65023_ldo_enable, - .disable = tps65023_ldo_disable, - .get_voltage = tps65023_ldo_get_voltage, - .set_voltage = tps65023_ldo_set_voltage, - .list_voltage = tps65023_ldo_list_voltage, -}; - -static -int tps_65023_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - static int desc_id; - const struct tps_info *info = (void *)id->driver_data; - struct regulator_init_data *init_data; - struct regulator_dev *rdev; - struct tps_pmic *tps; - int i; - - if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - /** - * init_data points to array of regulator_init structures - * coming from the board-evm file. - */ - init_data = client->dev.platform_data; - - if (!init_data) - return -EIO; - - tps = kzalloc(sizeof(*tps), GFP_KERNEL); - if (!tps) - return -ENOMEM; - - mutex_init(&tps->io_lock); - - /* common for all regulators */ - tps->client = client; - - for (i = 0; i < TPS65023_NUM_REGULATOR; i++, info++, init_data++) { - /* Store regulator specific information */ - tps->info[i] = info; - - tps->desc[i].name = info->name; - tps->desc[i].id = desc_id++; - tps->desc[i].n_voltages = num_voltages[i]; - tps->desc[i].ops = (i > TPS65023_DCDC_3 ? - &tps65023_ldo_ops : &tps65023_dcdc_ops); - tps->desc[i].type = REGULATOR_VOLTAGE; - tps->desc[i].owner = THIS_MODULE; - - /* Register the regulators */ - rdev = regulator_register(&tps->desc[i], &client->dev, - init_data, tps); - if (IS_ERR(rdev)) { - dev_err(&client->dev, "failed to register %s\n", - id->name); - - /* Unregister */ - while (i) - regulator_unregister(tps->rdev[--i]); - - tps->client = NULL; - - /* clear the client data in i2c */ - i2c_set_clientdata(client, NULL); - kfree(tps); - return PTR_ERR(rdev); - } - - /* Save regulator for cleanup */ - tps->rdev[i] = rdev; - } - - i2c_set_clientdata(client, tps); - - return 0; -} - -/** - * tps_65023_remove - TPS65023 driver i2c remove handler - * @client: i2c driver client device structure - * - * Unregister TPS driver as an i2c client device driver - */ -static int __devexit tps_65023_remove(struct i2c_client *client) -{ - struct tps_pmic *tps = i2c_get_clientdata(client); - int i; - - for (i = 0; i < TPS65023_NUM_REGULATOR; i++) - regulator_unregister(tps->rdev[i]); - - tps->client = NULL; - - /* clear the client data in i2c */ - i2c_set_clientdata(client, NULL); - kfree(tps); - - return 0; -} - -static const struct tps_info tps65023_regs[] = { - { - .name = "VDCDC1", - .min_uV = 800000, - .max_uV = 1600000, - .table_len = ARRAY_SIZE(VDCDC1_VSEL_table), - .table = VDCDC1_VSEL_table, - }, - { - .name = "VDCDC2", - .min_uV = 3300000, - .max_uV = 3300000, - .fixed = 1, - }, - { - .name = "VDCDC3", - .min_uV = 1800000, - .max_uV = 1800000, - .fixed = 1, - }, - { - .name = "LDO1", - .min_uV = 1000000, - .max_uV = 3150000, - .table_len = ARRAY_SIZE(LDO1_VSEL_table), - .table = LDO1_VSEL_table, - }, - { - .name = "LDO2", - .min_uV = 1050000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(LDO2_VSEL_table), - .table = LDO2_VSEL_table, - }, -}; - -static const struct i2c_device_id tps_65023_id[] = { - {.name = "tps65023", - .driver_data = (unsigned long) tps65023_regs,}, - { }, -}; - -MODULE_DEVICE_TABLE(i2c, tps_65023_id); - -static struct i2c_driver tps_65023_i2c_driver = { - .driver = { - .name = "tps65023", - .owner = THIS_MODULE, - }, - .probe = tps_65023_probe, - .remove = __devexit_p(tps_65023_remove), - .id_table = tps_65023_id, -}; - -/** - * tps_65023_init - * - * Module init function - */ -static int __init tps_65023_init(void) -{ - return i2c_add_driver(&tps_65023_i2c_driver); -} -subsys_initcall(tps_65023_init); - -/** - * tps_65023_cleanup - * - * Module exit function - */ -static void __exit tps_65023_cleanup(void) -{ - i2c_del_driver(&tps_65023_i2c_driver); -} -module_exit(tps_65023_cleanup); - -MODULE_AUTHOR("Texas Instruments"); -MODULE_DESCRIPTION("TPS65023 voltage regulator driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/regulator/tps6507x-regulator.c b/trunk/drivers/regulator/tps6507x-regulator.c deleted file mode 100644 index f8a6dfbef751..000000000000 --- a/trunk/drivers/regulator/tps6507x-regulator.c +++ /dev/null @@ -1,714 +0,0 @@ -/* - * tps6507x-regulator.c - * - * Regulator driver for TPS65073 PMIC - * - * Copyright (C) 2009 Texas Instrument Incorporated - http://www.ti.com/ - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation version 2. - * - * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind, - * whether express or implied; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Register definitions */ -#define TPS6507X_REG_PPATH1 0X01 -#define TPS6507X_REG_INT 0X02 -#define TPS6507X_REG_CHGCONFIG0 0X03 -#define TPS6507X_REG_CHGCONFIG1 0X04 -#define TPS6507X_REG_CHGCONFIG2 0X05 -#define TPS6507X_REG_CHGCONFIG3 0X06 -#define TPS6507X_REG_REG_ADCONFIG 0X07 -#define TPS6507X_REG_TSCMODE 0X08 -#define TPS6507X_REG_ADRESULT_1 0X09 -#define TPS6507X_REG_ADRESULT_2 0X0A -#define TPS6507X_REG_PGOOD 0X0B -#define TPS6507X_REG_PGOODMASK 0X0C -#define TPS6507X_REG_CON_CTRL1 0X0D -#define TPS6507X_REG_CON_CTRL2 0X0E -#define TPS6507X_REG_CON_CTRL3 0X0F -#define TPS6507X_REG_DEFDCDC1 0X10 -#define TPS6507X_REG_DEFDCDC2_LOW 0X11 -#define TPS6507X_REG_DEFDCDC2_HIGH 0X12 -#define TPS6507X_REG_DEFDCDC3_LOW 0X13 -#define TPS6507X_REG_DEFDCDC3_HIGH 0X14 -#define TPS6507X_REG_DEFSLEW 0X15 -#define TPS6507X_REG_LDO_CTRL1 0X16 -#define TPS6507X_REG_DEFLDO2 0X17 -#define TPS6507X_REG_WLED_CTRL1 0X18 -#define TPS6507X_REG_WLED_CTRL2 0X19 - -/* CON_CTRL1 bitfields */ -#define TPS6507X_CON_CTRL1_DCDC1_ENABLE BIT(4) -#define TPS6507X_CON_CTRL1_DCDC2_ENABLE BIT(3) -#define TPS6507X_CON_CTRL1_DCDC3_ENABLE BIT(2) -#define TPS6507X_CON_CTRL1_LDO1_ENABLE BIT(1) -#define TPS6507X_CON_CTRL1_LDO2_ENABLE BIT(0) - -/* DEFDCDC1 bitfields */ -#define TPS6507X_DEFDCDC1_DCDC1_EXT_ADJ_EN BIT(7) -#define TPS6507X_DEFDCDC1_DCDC1_MASK 0X3F - -/* DEFDCDC2_LOW bitfields */ -#define TPS6507X_DEFDCDC2_LOW_DCDC2_MASK 0X3F - -/* DEFDCDC2_HIGH bitfields */ -#define TPS6507X_DEFDCDC2_HIGH_DCDC2_MASK 0X3F - -/* DEFDCDC3_LOW bitfields */ -#define TPS6507X_DEFDCDC3_LOW_DCDC3_MASK 0X3F - -/* DEFDCDC3_HIGH bitfields */ -#define TPS6507X_DEFDCDC3_HIGH_DCDC3_MASK 0X3F - -/* TPS6507X_REG_LDO_CTRL1 bitfields */ -#define TPS6507X_REG_LDO_CTRL1_LDO1_MASK 0X0F - -/* TPS6507X_REG_DEFLDO2 bitfields */ -#define TPS6507X_REG_DEFLDO2_LDO2_MASK 0X3F - -/* VDCDC MASK */ -#define TPS6507X_DEFDCDCX_DCDC_MASK 0X3F - -/* DCDC's */ -#define TPS6507X_DCDC_1 0 -#define TPS6507X_DCDC_2 1 -#define TPS6507X_DCDC_3 2 -/* LDOs */ -#define TPS6507X_LDO_1 3 -#define TPS6507X_LDO_2 4 - -#define TPS6507X_MAX_REG_ID TPS6507X_LDO_2 - -/* Number of step-down converters available */ -#define TPS6507X_NUM_DCDC 3 -/* Number of LDO voltage regulators available */ -#define TPS6507X_NUM_LDO 2 -/* Number of total regulators available */ -#define TPS6507X_NUM_REGULATOR (TPS6507X_NUM_DCDC + TPS6507X_NUM_LDO) - -/* Supported voltage values for regulators (in milliVolts) */ -static const u16 VDCDCx_VSEL_table[] = { - 725, 750, 775, 800, - 825, 850, 875, 900, - 925, 950, 975, 1000, - 1025, 1050, 1075, 1100, - 1125, 1150, 1175, 1200, - 1225, 1250, 1275, 1300, - 1325, 1350, 1375, 1400, - 1425, 1450, 1475, 1500, - 1550, 1600, 1650, 1700, - 1750, 1800, 1850, 1900, - 1950, 2000, 2050, 2100, - 2150, 2200, 2250, 2300, - 2350, 2400, 2450, 2500, - 2550, 2600, 2650, 2700, - 2750, 2800, 2850, 2900, - 3000, 3100, 3200, 3300, -}; - -static const u16 LDO1_VSEL_table[] = { - 1000, 1100, 1200, 1250, - 1300, 1350, 1400, 1500, - 1600, 1800, 2500, 2750, - 2800, 3000, 3100, 3300, -}; - -static const u16 LDO2_VSEL_table[] = { - 725, 750, 775, 800, - 825, 850, 875, 900, - 925, 950, 975, 1000, - 1025, 1050, 1075, 1100, - 1125, 1150, 1175, 1200, - 1225, 1250, 1275, 1300, - 1325, 1350, 1375, 1400, - 1425, 1450, 1475, 1500, - 1550, 1600, 1650, 1700, - 1750, 1800, 1850, 1900, - 1950, 2000, 2050, 2100, - 2150, 2200, 2250, 2300, - 2350, 2400, 2450, 2500, - 2550, 2600, 2650, 2700, - 2750, 2800, 2850, 2900, - 3000, 3100, 3200, 3300, -}; - -static unsigned int num_voltages[] = {ARRAY_SIZE(VDCDCx_VSEL_table), - ARRAY_SIZE(VDCDCx_VSEL_table), - ARRAY_SIZE(VDCDCx_VSEL_table), - ARRAY_SIZE(LDO1_VSEL_table), - ARRAY_SIZE(LDO2_VSEL_table)}; - -struct tps_info { - const char *name; - unsigned min_uV; - unsigned max_uV; - u8 table_len; - const u16 *table; -}; - -struct tps_pmic { - struct regulator_desc desc[TPS6507X_NUM_REGULATOR]; - struct i2c_client *client; - struct regulator_dev *rdev[TPS6507X_NUM_REGULATOR]; - const struct tps_info *info[TPS6507X_NUM_REGULATOR]; - struct mutex io_lock; -}; - -static inline int tps_6507x_read(struct tps_pmic *tps, u8 reg) -{ - return i2c_smbus_read_byte_data(tps->client, reg); -} - -static inline int tps_6507x_write(struct tps_pmic *tps, u8 reg, u8 val) -{ - return i2c_smbus_write_byte_data(tps->client, reg, val); -} - -static int tps_6507x_set_bits(struct tps_pmic *tps, u8 reg, u8 mask) -{ - int err, data; - - mutex_lock(&tps->io_lock); - - data = tps_6507x_read(tps, reg); - if (data < 0) { - dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); - err = data; - goto out; - } - - data |= mask; - err = tps_6507x_write(tps, reg, data); - if (err) - dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); - -out: - mutex_unlock(&tps->io_lock); - return err; -} - -static int tps_6507x_clear_bits(struct tps_pmic *tps, u8 reg, u8 mask) -{ - int err, data; - - mutex_lock(&tps->io_lock); - - data = tps_6507x_read(tps, reg); - if (data < 0) { - dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); - err = data; - goto out; - } - - data &= ~mask; - err = tps_6507x_write(tps, reg, data); - if (err) - dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); - -out: - mutex_unlock(&tps->io_lock); - return err; -} - -static int tps_6507x_reg_read(struct tps_pmic *tps, u8 reg) -{ - int data; - - mutex_lock(&tps->io_lock); - - data = tps_6507x_read(tps, reg); - if (data < 0) - dev_err(&tps->client->dev, "Read from reg 0x%x failed\n", reg); - - mutex_unlock(&tps->io_lock); - return data; -} - -static int tps_6507x_reg_write(struct tps_pmic *tps, u8 reg, u8 val) -{ - int err; - - mutex_lock(&tps->io_lock); - - err = tps_6507x_write(tps, reg, val); - if (err < 0) - dev_err(&tps->client->dev, "Write for reg 0x%x failed\n", reg); - - mutex_unlock(&tps->io_lock); - return err; -} - -static int tps6507x_dcdc_is_enabled(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, dcdc = rdev_get_id(dev); - u8 shift; - - if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) - return -EINVAL; - - shift = TPS6507X_MAX_REG_ID - dcdc; - data = tps_6507x_reg_read(tps, TPS6507X_REG_CON_CTRL1); - - if (data < 0) - return data; - else - return (data & 1< TPS6507X_LDO_2) - return -EINVAL; - - shift = TPS6507X_MAX_REG_ID - ldo; - data = tps_6507x_reg_read(tps, TPS6507X_REG_CON_CTRL1); - - if (data < 0) - return data; - else - return (data & 1< TPS6507X_DCDC_3) - return -EINVAL; - - shift = TPS6507X_MAX_REG_ID - dcdc; - return tps_6507x_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); -} - -static int tps6507x_dcdc_disable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int dcdc = rdev_get_id(dev); - u8 shift; - - if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) - return -EINVAL; - - shift = TPS6507X_MAX_REG_ID - dcdc; - return tps_6507x_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); -} - -static int tps6507x_ldo_enable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - u8 shift; - - if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) - return -EINVAL; - - shift = TPS6507X_MAX_REG_ID - ldo; - return tps_6507x_set_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); -} - -static int tps6507x_ldo_disable(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - u8 shift; - - if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) - return -EINVAL; - - shift = TPS6507X_MAX_REG_ID - ldo; - return tps_6507x_clear_bits(tps, TPS6507X_REG_CON_CTRL1, 1 << shift); -} - -static int tps6507x_dcdc_get_voltage(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, dcdc = rdev_get_id(dev); - u8 reg; - - switch (dcdc) { - case TPS6507X_DCDC_1: - reg = TPS6507X_REG_DEFDCDC1; - break; - case TPS6507X_DCDC_2: - reg = TPS6507X_REG_DEFDCDC2_LOW; - break; - case TPS6507X_DCDC_3: - reg = TPS6507X_REG_DEFDCDC3_LOW; - break; - default: - return -EINVAL; - } - - data = tps_6507x_reg_read(tps, reg); - if (data < 0) - return data; - - data &= TPS6507X_DEFDCDCX_DCDC_MASK; - return tps->info[dcdc]->table[data] * 1000; -} - -static int tps6507x_dcdc_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, vsel, dcdc = rdev_get_id(dev); - u8 reg; - - switch (dcdc) { - case TPS6507X_DCDC_1: - reg = TPS6507X_REG_DEFDCDC1; - break; - case TPS6507X_DCDC_2: - reg = TPS6507X_REG_DEFDCDC2_LOW; - break; - case TPS6507X_DCDC_3: - reg = TPS6507X_REG_DEFDCDC3_LOW; - break; - default: - return -EINVAL; - } - - if (min_uV < tps->info[dcdc]->min_uV - || min_uV > tps->info[dcdc]->max_uV) - return -EINVAL; - if (max_uV < tps->info[dcdc]->min_uV - || max_uV > tps->info[dcdc]->max_uV) - return -EINVAL; - - for (vsel = 0; vsel < tps->info[dcdc]->table_len; vsel++) { - int mV = tps->info[dcdc]->table[vsel]; - int uV = mV * 1000; - - /* Break at the first in-range value */ - if (min_uV <= uV && uV <= max_uV) - break; - } - - /* write to the register in case we found a match */ - if (vsel == tps->info[dcdc]->table_len) - return -EINVAL; - - data = tps_6507x_reg_read(tps, reg); - if (data < 0) - return data; - - data &= ~TPS6507X_DEFDCDCX_DCDC_MASK; - data |= vsel; - - return tps_6507x_reg_write(tps, reg, data); -} - -static int tps6507x_ldo_get_voltage(struct regulator_dev *dev) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, ldo = rdev_get_id(dev); - u8 reg, mask; - - if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) - return -EINVAL; - else { - reg = (ldo == TPS6507X_LDO_1 ? - TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2); - mask = (ldo == TPS6507X_LDO_1 ? - TPS6507X_REG_LDO_CTRL1_LDO1_MASK : - TPS6507X_REG_DEFLDO2_LDO2_MASK); - } - - data = tps_6507x_reg_read(tps, reg); - if (data < 0) - return data; - - data &= mask; - return tps->info[ldo]->table[data] * 1000; -} - -static int tps6507x_ldo_set_voltage(struct regulator_dev *dev, - int min_uV, int max_uV) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int data, vsel, ldo = rdev_get_id(dev); - u8 reg, mask; - - if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) - return -EINVAL; - else { - reg = (ldo == TPS6507X_LDO_1 ? - TPS6507X_REG_LDO_CTRL1 : TPS6507X_REG_DEFLDO2); - mask = (ldo == TPS6507X_LDO_1 ? - TPS6507X_REG_LDO_CTRL1_LDO1_MASK : - TPS6507X_REG_DEFLDO2_LDO2_MASK); - } - - if (min_uV < tps->info[ldo]->min_uV || min_uV > tps->info[ldo]->max_uV) - return -EINVAL; - if (max_uV < tps->info[ldo]->min_uV || max_uV > tps->info[ldo]->max_uV) - return -EINVAL; - - for (vsel = 0; vsel < tps->info[ldo]->table_len; vsel++) { - int mV = tps->info[ldo]->table[vsel]; - int uV = mV * 1000; - - /* Break at the first in-range value */ - if (min_uV <= uV && uV <= max_uV) - break; - } - - if (vsel == tps->info[ldo]->table_len) - return -EINVAL; - - data = tps_6507x_reg_read(tps, reg); - if (data < 0) - return data; - - data &= ~mask; - data |= vsel; - - return tps_6507x_reg_write(tps, reg, data); -} - -static int tps6507x_dcdc_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int dcdc = rdev_get_id(dev); - - if (dcdc < TPS6507X_DCDC_1 || dcdc > TPS6507X_DCDC_3) - return -EINVAL; - - if (selector >= tps->info[dcdc]->table_len) - return -EINVAL; - else - return tps->info[dcdc]->table[selector] * 1000; -} - -static int tps6507x_ldo_list_voltage(struct regulator_dev *dev, - unsigned selector) -{ - struct tps_pmic *tps = rdev_get_drvdata(dev); - int ldo = rdev_get_id(dev); - - if (ldo < TPS6507X_LDO_1 || ldo > TPS6507X_LDO_2) - return -EINVAL; - - if (selector >= tps->info[ldo]->table_len) - return -EINVAL; - else - return tps->info[ldo]->table[selector] * 1000; -} - -/* Operations permitted on VDCDCx */ -static struct regulator_ops tps6507x_dcdc_ops = { - .is_enabled = tps6507x_dcdc_is_enabled, - .enable = tps6507x_dcdc_enable, - .disable = tps6507x_dcdc_disable, - .get_voltage = tps6507x_dcdc_get_voltage, - .set_voltage = tps6507x_dcdc_set_voltage, - .list_voltage = tps6507x_dcdc_list_voltage, -}; - -/* Operations permitted on LDOx */ -static struct regulator_ops tps6507x_ldo_ops = { - .is_enabled = tps6507x_ldo_is_enabled, - .enable = tps6507x_ldo_enable, - .disable = tps6507x_ldo_disable, - .get_voltage = tps6507x_ldo_get_voltage, - .set_voltage = tps6507x_ldo_set_voltage, - .list_voltage = tps6507x_ldo_list_voltage, -}; - -static -int tps_6507x_probe(struct i2c_client *client, const struct i2c_device_id *id) -{ - static int desc_id; - const struct tps_info *info = (void *)id->driver_data; - struct regulator_init_data *init_data; - struct regulator_dev *rdev; - struct tps_pmic *tps; - int i; - - if (!i2c_check_functionality(client->adapter, - I2C_FUNC_SMBUS_BYTE_DATA)) - return -EIO; - - /** - * init_data points to array of regulator_init structures - * coming from the board-evm file. - */ - init_data = client->dev.platform_data; - - if (!init_data) - return -EIO; - - tps = kzalloc(sizeof(*tps), GFP_KERNEL); - if (!tps) - return -ENOMEM; - - mutex_init(&tps->io_lock); - - /* common for all regulators */ - tps->client = client; - - for (i = 0; i < TPS6507X_NUM_REGULATOR; i++, info++, init_data++) { - /* Register the regulators */ - tps->info[i] = info; - tps->desc[i].name = info->name; - tps->desc[i].id = desc_id++; - tps->desc[i].n_voltages = num_voltages[i]; - tps->desc[i].ops = (i > TPS6507X_DCDC_3 ? - &tps6507x_ldo_ops : &tps6507x_dcdc_ops); - tps->desc[i].type = REGULATOR_VOLTAGE; - tps->desc[i].owner = THIS_MODULE; - - rdev = regulator_register(&tps->desc[i], - &client->dev, init_data, tps); - if (IS_ERR(rdev)) { - dev_err(&client->dev, "failed to register %s\n", - id->name); - - /* Unregister */ - while (i) - regulator_unregister(tps->rdev[--i]); - - tps->client = NULL; - - /* clear the client data in i2c */ - i2c_set_clientdata(client, NULL); - - kfree(tps); - return PTR_ERR(rdev); - } - - /* Save regulator for cleanup */ - tps->rdev[i] = rdev; - } - - i2c_set_clientdata(client, tps); - - return 0; -} - -/** - * tps_6507x_remove - TPS6507x driver i2c remove handler - * @client: i2c driver client device structure - * - * Unregister TPS driver as an i2c client device driver - */ -static int __devexit tps_6507x_remove(struct i2c_client *client) -{ - struct tps_pmic *tps = i2c_get_clientdata(client); - int i; - - for (i = 0; i < TPS6507X_NUM_REGULATOR; i++) - regulator_unregister(tps->rdev[i]); - - tps->client = NULL; - - /* clear the client data in i2c */ - i2c_set_clientdata(client, NULL); - kfree(tps); - - return 0; -} - -static const struct tps_info tps6507x_regs[] = { - { - .name = "VDCDC1", - .min_uV = 725000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), - .table = VDCDCx_VSEL_table, - }, - { - .name = "VDCDC2", - .min_uV = 725000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), - .table = VDCDCx_VSEL_table, - }, - { - .name = "VDCDC3", - .min_uV = 725000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(VDCDCx_VSEL_table), - .table = VDCDCx_VSEL_table, - }, - { - .name = "LDO1", - .min_uV = 1000000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(LDO1_VSEL_table), - .table = LDO1_VSEL_table, - }, - { - .name = "LDO2", - .min_uV = 725000, - .max_uV = 3300000, - .table_len = ARRAY_SIZE(LDO2_VSEL_table), - .table = LDO2_VSEL_table, - }, -}; - -static const struct i2c_device_id tps_6507x_id[] = { - {.name = "tps6507x", - .driver_data = (unsigned long) tps6507x_regs,}, - { }, -}; -MODULE_DEVICE_TABLE(i2c, tps_6507x_id); - -static struct i2c_driver tps_6507x_i2c_driver = { - .driver = { - .name = "tps6507x", - .owner = THIS_MODULE, - }, - .probe = tps_6507x_probe, - .remove = __devexit_p(tps_6507x_remove), - .id_table = tps_6507x_id, -}; - -/** - * tps_6507x_init - * - * Module init function - */ -static int __init tps_6507x_init(void) -{ - return i2c_add_driver(&tps_6507x_i2c_driver); -} -subsys_initcall(tps_6507x_init); - -/** - * tps_6507x_cleanup - * - * Module exit function - */ -static void __exit tps_6507x_cleanup(void) -{ - i2c_del_driver(&tps_6507x_i2c_driver); -} -module_exit(tps_6507x_cleanup); - -MODULE_AUTHOR("Texas Instruments"); -MODULE_DESCRIPTION("TPS6507x voltage regulator driver"); -MODULE_LICENSE("GPL v2"); diff --git a/trunk/drivers/regulator/userspace-consumer.c b/trunk/drivers/regulator/userspace-consumer.c index 44917da4ac97..06d2fa96a8b4 100644 --- a/trunk/drivers/regulator/userspace-consumer.c +++ b/trunk/drivers/regulator/userspace-consumer.c @@ -93,21 +93,16 @@ static ssize_t reg_set_state(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(name, 0444, reg_show_name, NULL); static DEVICE_ATTR(state, 0644, reg_show_state, reg_set_state); -static struct attribute *attributes[] = { - &dev_attr_name.attr, - &dev_attr_state.attr, - NULL, -}; - -static const struct attribute_group attr_group = { - .attrs = attributes, +static struct device_attribute *attributes[] = { + &dev_attr_name, + &dev_attr_state, }; static int regulator_userspace_consumer_probe(struct platform_device *pdev) { struct regulator_userspace_consumer_data *pdata; struct userspace_consumer_data *drvdata; - int ret; + int ret, i; pdata = pdev->dev.platform_data; if (!pdata) @@ -130,29 +125,31 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) goto err_alloc_supplies; } - ret = sysfs_create_group(&pdev->dev.kobj, &attr_group); - if (ret != 0) - goto err_create_attrs; + for (i = 0; i < ARRAY_SIZE(attributes); i++) { + ret = device_create_file(&pdev->dev, attributes[i]); + if (ret != 0) + goto err_create_attrs; + } - if (pdata->init_on) { + if (pdata->init_on) ret = regulator_bulk_enable(drvdata->num_supplies, drvdata->supplies); - if (ret) { - dev_err(&pdev->dev, - "Failed to set initial state: %d\n", ret); - goto err_enable; - } - } drvdata->enabled = pdata->init_on; + + if (ret) { + dev_err(&pdev->dev, "Failed to set initial state: %d\n", ret); + goto err_create_attrs; + } + platform_set_drvdata(pdev, drvdata); return 0; -err_enable: - sysfs_remove_group(&pdev->dev.kobj, &attr_group); - err_create_attrs: + for (i = 0; i < ARRAY_SIZE(attributes); i++) + device_remove_file(&pdev->dev, attributes[i]); + regulator_bulk_free(drvdata->num_supplies, drvdata->supplies); err_alloc_supplies: @@ -163,8 +160,10 @@ static int regulator_userspace_consumer_probe(struct platform_device *pdev) static int regulator_userspace_consumer_remove(struct platform_device *pdev) { struct userspace_consumer_data *data = platform_get_drvdata(pdev); + int i; - sysfs_remove_group(&pdev->dev.kobj, &attr_group); + for (i = 0; i < ARRAY_SIZE(attributes); i++) + device_remove_file(&pdev->dev, attributes[i]); if (data->enabled) regulator_bulk_disable(data->num_supplies, data->supplies); diff --git a/trunk/drivers/regulator/virtual.c b/trunk/drivers/regulator/virtual.c index addc032c84bf..e7db5664722e 100644 --- a/trunk/drivers/regulator/virtual.c +++ b/trunk/drivers/regulator/virtual.c @@ -27,81 +27,71 @@ struct virtual_consumer_data { unsigned int mode; }; -static void update_voltage_constraints(struct device *dev, - struct virtual_consumer_data *data) +static void update_voltage_constraints(struct virtual_consumer_data *data) { int ret; if (data->min_uV && data->max_uV && data->min_uV <= data->max_uV) { - dev_dbg(dev, "Requesting %d-%duV\n", - data->min_uV, data->max_uV); ret = regulator_set_voltage(data->regulator, - data->min_uV, data->max_uV); + data->min_uV, data->max_uV); if (ret != 0) { - dev_err(dev, - "regulator_set_voltage() failed: %d\n", ret); + printk(KERN_ERR "regulator_set_voltage() failed: %d\n", + ret); return; } } if (data->min_uV && data->max_uV && !data->enabled) { - dev_dbg(dev, "Enabling regulator\n"); ret = regulator_enable(data->regulator); if (ret == 0) data->enabled = 1; else - dev_err(dev, "regulator_enable() failed: %d\n", + printk(KERN_ERR "regulator_enable() failed: %d\n", ret); } if (!(data->min_uV && data->max_uV) && data->enabled) { - dev_dbg(dev, "Disabling regulator\n"); ret = regulator_disable(data->regulator); if (ret == 0) data->enabled = 0; else - dev_err(dev, "regulator_disable() failed: %d\n", + printk(KERN_ERR "regulator_disable() failed: %d\n", ret); } } -static void update_current_limit_constraints(struct device *dev, - struct virtual_consumer_data *data) +static void update_current_limit_constraints(struct virtual_consumer_data + *data) { int ret; if (data->max_uA && data->min_uA <= data->max_uA) { - dev_dbg(dev, "Requesting %d-%duA\n", - data->min_uA, data->max_uA); ret = regulator_set_current_limit(data->regulator, data->min_uA, data->max_uA); if (ret != 0) { - dev_err(dev, - "regulator_set_current_limit() failed: %d\n", - ret); + pr_err("regulator_set_current_limit() failed: %d\n", + ret); return; } } if (data->max_uA && !data->enabled) { - dev_dbg(dev, "Enabling regulator\n"); ret = regulator_enable(data->regulator); if (ret == 0) data->enabled = 1; else - dev_err(dev, "regulator_enable() failed: %d\n", + printk(KERN_ERR "regulator_enable() failed: %d\n", ret); } if (!(data->min_uA && data->max_uA) && data->enabled) { - dev_dbg(dev, "Disabling regulator\n"); ret = regulator_disable(data->regulator); if (ret == 0) data->enabled = 0; else - dev_err(dev, "regulator_disable() failed: %d\n", + printk(KERN_ERR "regulator_disable() failed: %d\n", ret); } } @@ -125,7 +115,7 @@ static ssize_t set_min_uV(struct device *dev, struct device_attribute *attr, mutex_lock(&data->lock); data->min_uV = val; - update_voltage_constraints(dev, data); + update_voltage_constraints(data); mutex_unlock(&data->lock); @@ -151,7 +141,7 @@ static ssize_t set_max_uV(struct device *dev, struct device_attribute *attr, mutex_lock(&data->lock); data->max_uV = val; - update_voltage_constraints(dev, data); + update_voltage_constraints(data); mutex_unlock(&data->lock); @@ -177,7 +167,7 @@ static ssize_t set_min_uA(struct device *dev, struct device_attribute *attr, mutex_lock(&data->lock); data->min_uA = val; - update_current_limit_constraints(dev, data); + update_current_limit_constraints(data); mutex_unlock(&data->lock); @@ -203,7 +193,7 @@ static ssize_t set_max_uA(struct device *dev, struct device_attribute *attr, mutex_lock(&data->lock); data->max_uA = val; - update_current_limit_constraints(dev, data); + update_current_limit_constraints(data); mutex_unlock(&data->lock); @@ -286,7 +276,8 @@ static int regulator_virtual_consumer_probe(struct platform_device *pdev) drvdata = kzalloc(sizeof(struct virtual_consumer_data), GFP_KERNEL); if (drvdata == NULL) { - return -ENOMEM; + ret = -ENOMEM; + goto err; } mutex_init(&drvdata->lock); @@ -294,18 +285,13 @@ static int regulator_virtual_consumer_probe(struct platform_device *pdev) drvdata->regulator = regulator_get(&pdev->dev, reg_id); if (IS_ERR(drvdata->regulator)) { ret = PTR_ERR(drvdata->regulator); - dev_err(&pdev->dev, "Failed to obtain supply '%s': %d\n", - reg_id, ret); goto err; } for (i = 0; i < ARRAY_SIZE(attributes); i++) { ret = device_create_file(&pdev->dev, attributes[i]); - if (ret != 0) { - dev_err(&pdev->dev, "Failed to create attr %d: %d\n", - i, ret); - goto err_regulator; - } + if (ret != 0) + goto err; } drvdata->mode = regulator_get_mode(drvdata->regulator); @@ -314,8 +300,6 @@ static int regulator_virtual_consumer_probe(struct platform_device *pdev) return 0; -err_regulator: - regulator_put(drvdata->regulator); err: for (i = 0; i < ARRAY_SIZE(attributes); i++) device_remove_file(&pdev->dev, attributes[i]); diff --git a/trunk/drivers/regulator/wm8350-regulator.c b/trunk/drivers/regulator/wm8350-regulator.c index 768bd0e5b48b..17a00b0fafd1 100644 --- a/trunk/drivers/regulator/wm8350-regulator.c +++ b/trunk/drivers/regulator/wm8350-regulator.c @@ -1419,8 +1419,6 @@ int wm8350_register_regulator(struct wm8350 *wm8350, int reg, { struct platform_device *pdev; int ret; - if (reg < 0 || reg >= NUM_WM8350_REGULATORS) - return -EINVAL; if (wm8350->pmic.pdev[reg]) return -EBUSY; diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index 3c20dae43ce2..73771b09fbd3 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -378,15 +378,6 @@ config RTC_DRV_DS3234 This driver can also be built as a module. If so, the module will be called rtc-ds3234. -config RTC_DRV_PCF2123 - tristate "NXP PCF2123" - help - If you say yes here you get support for the NXP PCF2123 - RTC chip. - - This driver can also be built as a module. If so, the module - will be called rtc-pcf2123. - endif # SPI_MASTER comment "Platform RTC drivers" @@ -509,17 +500,6 @@ config RTC_DRV_M48T59 This driver can also be built as a module, if so, the module will be called "rtc-m48t59". -config RTC_MXC - tristate "Freescale MXC Real Time Clock" - depends on ARCH_MXC - depends on RTC_CLASS - help - If you say yes here you get support for the Freescale MXC - RTC module. - - This driver can also be built as a module, if so, the module - will be called "rtc-mxc". - config RTC_DRV_BQ4802 tristate "TI BQ4802" help @@ -798,33 +778,4 @@ config RTC_DRV_PS3 This driver can also be built as a module. If so, the module will be called rtc-ps3. -config RTC_DRV_COH901331 - tristate "ST-Ericsson COH 901 331 RTC" - depends on ARCH_U300 - help - If you say Y here you will get access to ST-Ericsson - COH 901 331 RTC clock found in some ST-Ericsson Mobile - Platforms. - - This driver can also be built as a module. If so, the module - will be called "rtc-coh901331". - - -config RTC_DRV_STMP - tristate "Freescale STMP3xxx RTC" - depends on ARCH_STMP3XXX - help - If you say yes here you will get support for the onboard - STMP3xxx RTC. - - This driver can also be built as a module. If so, the module - will be called rtc-stmp3xxx. - -config RTC_DRV_PCAP - tristate "PCAP RTC" - depends on EZX_PCAP - help - If you say Y here you will get support for the RTC found on - the PCAP2 ASIC used on some Motorola phones. - endif # RTC_CLASS diff --git a/trunk/drivers/rtc/Makefile b/trunk/drivers/rtc/Makefile index aa3fbd5517a1..5e152ffe5058 100644 --- a/trunk/drivers/rtc/Makefile +++ b/trunk/drivers/rtc/Makefile @@ -23,9 +23,7 @@ obj-$(CONFIG_RTC_DRV_AT91RM9200)+= rtc-at91rm9200.o obj-$(CONFIG_RTC_DRV_AT91SAM9) += rtc-at91sam9.o obj-$(CONFIG_RTC_DRV_AU1XXX) += rtc-au1xxx.o obj-$(CONFIG_RTC_DRV_BFIN) += rtc-bfin.o -obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o obj-$(CONFIG_RTC_DRV_CMOS) += rtc-cmos.o -obj-$(CONFIG_RTC_DRV_COH901331) += rtc-coh901331.o obj-$(CONFIG_RTC_DRV_DM355EVM) += rtc-dm355evm.o obj-$(CONFIG_RTC_DRV_DS1216) += rtc-ds1216.o obj-$(CONFIG_RTC_DRV_DS1286) += rtc-ds1286.o @@ -42,26 +40,24 @@ obj-$(CONFIG_RTC_DRV_DS3234) += rtc-ds3234.o obj-$(CONFIG_RTC_DRV_EFI) += rtc-efi.o obj-$(CONFIG_RTC_DRV_EP93XX) += rtc-ep93xx.o obj-$(CONFIG_RTC_DRV_FM3130) += rtc-fm3130.o -obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o obj-$(CONFIG_RTC_DRV_ISL1208) += rtc-isl1208.o obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o obj-$(CONFIG_RTC_DRV_M48T35) += rtc-m48t35.o obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o -obj-$(CONFIG_RTC_MXC) += rtc-mxc.o +obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o +obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o +obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o obj-$(CONFIG_RTC_DRV_MV) += rtc-mv.o obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o -obj-$(CONFIG_RTC_DRV_PCAP) += rtc-pcap.o obj-$(CONFIG_RTC_DRV_PCF8563) += rtc-pcf8563.o obj-$(CONFIG_RTC_DRV_PCF8583) += rtc-pcf8583.o -obj-$(CONFIG_RTC_DRV_PCF2123) += rtc-pcf2123.o -obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o obj-$(CONFIG_RTC_DRV_PL030) += rtc-pl030.o obj-$(CONFIG_RTC_DRV_PL031) += rtc-pl031.o -obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o +obj-$(CONFIG_RTC_DRV_GENERIC) += rtc-generic.o obj-$(CONFIG_RTC_DRV_PXA) += rtc-pxa.o obj-$(CONFIG_RTC_DRV_R9701) += rtc-r9701.o obj-$(CONFIG_RTC_DRV_RS5C313) += rtc-rs5c313.o @@ -73,10 +69,7 @@ obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o -obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o obj-$(CONFIG_RTC_DRV_STK17TA8) += rtc-stk17ta8.o -obj-$(CONFIG_RTC_DRV_STMP) += rtc-stmp3xxx.o -obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o obj-$(CONFIG_RTC_DRV_TEST) += rtc-test.o obj-$(CONFIG_RTC_DRV_TWL4030) += rtc-twl4030.o obj-$(CONFIG_RTC_DRV_TX4939) += rtc-tx4939.o @@ -85,3 +78,5 @@ obj-$(CONFIG_RTC_DRV_VR41XX) += rtc-vr41xx.o obj-$(CONFIG_RTC_DRV_WM831X) += rtc-wm831x.o obj-$(CONFIG_RTC_DRV_WM8350) += rtc-wm8350.o obj-$(CONFIG_RTC_DRV_X1205) += rtc-x1205.o +obj-$(CONFIG_RTC_DRV_PCF50633) += rtc-pcf50633.o +obj-$(CONFIG_RTC_DRV_PS3) += rtc-ps3.o diff --git a/trunk/drivers/rtc/rtc-at91rm9200.c b/trunk/drivers/rtc/rtc-at91rm9200.c index bc8bbca9a2e2..b5bf93706913 100644 --- a/trunk/drivers/rtc/rtc-at91rm9200.c +++ b/trunk/drivers/rtc/rtc-at91rm9200.c @@ -289,7 +289,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) AT91_RTC_CALEV); ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt, - IRQF_SHARED, + IRQF_DISABLED | IRQF_SHARED, "at91_rtc", pdev); if (ret) { printk(KERN_ERR "at91_rtc: IRQ %d already in use.\n", @@ -340,7 +340,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) static u32 at91_rtc_imr; -static int at91_rtc_suspend(struct device *dev) +static int at91_rtc_suspend(struct platform_device *pdev, pm_message_t state) { /* this IRQ is shared with DBGU and other hardware which isn't * necessarily doing PM like we are... @@ -348,7 +348,7 @@ static int at91_rtc_suspend(struct device *dev) at91_rtc_imr = at91_sys_read(AT91_RTC_IMR) & (AT91_RTC_ALARM|AT91_RTC_SECEV); if (at91_rtc_imr) { - if (device_may_wakeup(dev)) + if (device_may_wakeup(&pdev->dev)) enable_irq_wake(AT91_ID_SYS); else at91_sys_write(AT91_RTC_IDR, at91_rtc_imr); @@ -356,34 +356,28 @@ static int at91_rtc_suspend(struct device *dev) return 0; } -static int at91_rtc_resume(struct device *dev) +static int at91_rtc_resume(struct platform_device *pdev) { if (at91_rtc_imr) { - if (device_may_wakeup(dev)) + if (device_may_wakeup(&pdev->dev)) disable_irq_wake(AT91_ID_SYS); else at91_sys_write(AT91_RTC_IER, at91_rtc_imr); } return 0; } - -static const struct dev_pm_ops at91_rtc_pm = { - .suspend = at91_rtc_suspend, - .resume = at91_rtc_resume, -}; - -#define at91_rtc_pm_ptr &at91_rtc_pm - #else -#define at91_rtc_pm_ptr NULL +#define at91_rtc_suspend NULL +#define at91_rtc_resume NULL #endif static struct platform_driver at91_rtc_driver = { .remove = __exit_p(at91_rtc_remove), + .suspend = at91_rtc_suspend, + .resume = at91_rtc_resume, .driver = { .name = "at91_rtc", .owner = THIS_MODULE, - .pm = at91_rtc_pm_ptr, }, }; diff --git a/trunk/drivers/rtc/rtc-bfin.c b/trunk/drivers/rtc/rtc-bfin.c index b11485b9f21c..a118eb0f1e67 100644 --- a/trunk/drivers/rtc/rtc-bfin.c +++ b/trunk/drivers/rtc/rtc-bfin.c @@ -383,7 +383,7 @@ static int __devinit bfin_rtc_probe(struct platform_device *pdev) } /* Grab the IRQ and init the hardware */ - ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, 0, pdev->name, dev); + ret = request_irq(IRQ_RTC, bfin_rtc_interrupt, IRQF_SHARED, pdev->name, dev); if (unlikely(ret)) goto err_reg; /* sometimes the bootloader touched things, but the write complete was not diff --git a/trunk/drivers/rtc/rtc-coh901331.c b/trunk/drivers/rtc/rtc-coh901331.c deleted file mode 100644 index 7fe1fa26c52c..000000000000 --- a/trunk/drivers/rtc/rtc-coh901331.c +++ /dev/null @@ -1,311 +0,0 @@ -/* - * Copyright (C) 2007-2009 ST-Ericsson AB - * License terms: GNU General Public License (GPL) version 2 - * Real Time Clock interface for ST-Ericsson AB COH 901 331 RTC. - * Author: Linus Walleij - * Based on rtc-pl031.c by Deepak Saxena - * Copyright 2006 (c) MontaVista Software, Inc. - */ -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * Registers in the COH 901 331 - */ -/* Alarm value 32bit (R/W) */ -#define COH901331_ALARM 0x00U -/* Used to set current time 32bit (R/W) */ -#define COH901331_SET_TIME 0x04U -/* Indication if current time is valid 32bit (R/-) */ -#define COH901331_VALID 0x08U -/* Read the current time 32bit (R/-) */ -#define COH901331_CUR_TIME 0x0cU -/* Event register for the "alarm" interrupt */ -#define COH901331_IRQ_EVENT 0x10U -/* Mask register for the "alarm" interrupt */ -#define COH901331_IRQ_MASK 0x14U -/* Force register for the "alarm" interrupt */ -#define COH901331_IRQ_FORCE 0x18U - -/* - * Reference to RTC block clock - * Notice that the frequent clk_enable()/clk_disable() on this - * clock is mainly to be able to turn on/off other clocks in the - * hierarchy as needed, the RTC clock is always on anyway. - */ -struct coh901331_port { - struct rtc_device *rtc; - struct clk *clk; - u32 phybase; - u32 physize; - void __iomem *virtbase; - int irq; -#ifdef CONFIG_PM - u32 irqmaskstore; -#endif -}; - -static irqreturn_t coh901331_interrupt(int irq, void *data) -{ - struct coh901331_port *rtap = data; - - clk_enable(rtap->clk); - /* Ack IRQ */ - writel(1, rtap->virtbase + COH901331_IRQ_EVENT); - clk_disable(rtap->clk); - /* Set alarm flag */ - rtc_update_irq(rtap->rtc, 1, RTC_AF); - - return IRQ_HANDLED; -} - -static int coh901331_read_time(struct device *dev, struct rtc_time *tm) -{ - struct coh901331_port *rtap = dev_get_drvdata(dev); - - clk_enable(rtap->clk); - /* Check if the time is valid */ - if (readl(rtap->virtbase + COH901331_VALID)) { - rtc_time_to_tm(readl(rtap->virtbase + COH901331_CUR_TIME), tm); - clk_disable(rtap->clk); - return rtc_valid_tm(tm); - } - clk_disable(rtap->clk); - return -EINVAL; -} - -static int coh901331_set_mmss(struct device *dev, unsigned long secs) -{ - struct coh901331_port *rtap = dev_get_drvdata(dev); - - clk_enable(rtap->clk); - writel(secs, rtap->virtbase + COH901331_SET_TIME); - clk_disable(rtap->clk); - - return 0; -} - -static int coh901331_read_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - struct coh901331_port *rtap = dev_get_drvdata(dev); - - clk_enable(rtap->clk); - rtc_time_to_tm(readl(rtap->virtbase + COH901331_ALARM), &alarm->time); - alarm->pending = readl(rtap->virtbase + COH901331_IRQ_EVENT) & 1U; - alarm->enabled = readl(rtap->virtbase + COH901331_IRQ_MASK) & 1U; - clk_disable(rtap->clk); - - return 0; -} - -static int coh901331_set_alarm(struct device *dev, struct rtc_wkalrm *alarm) -{ - struct coh901331_port *rtap = dev_get_drvdata(dev); - unsigned long time; - - rtc_tm_to_time(&alarm->time, &time); - clk_enable(rtap->clk); - writel(time, rtap->virtbase + COH901331_ALARM); - writel(alarm->enabled, rtap->virtbase + COH901331_IRQ_MASK); - clk_disable(rtap->clk); - - return 0; -} - -static int coh901331_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct coh901331_port *rtap = dev_get_drvdata(dev); - - clk_enable(rtap->clk); - if (enabled) - writel(1, rtap->virtbase + COH901331_IRQ_MASK); - else - writel(0, rtap->virtbase + COH901331_IRQ_MASK); - clk_disable(rtap->clk); -} - -static struct rtc_class_ops coh901331_ops = { - .read_time = coh901331_read_time, - .set_mmss = coh901331_set_mmss, - .read_alarm = coh901331_read_alarm, - .set_alarm = coh901331_set_alarm, - .alarm_irq_enable = coh901331_alarm_irq_enable, -}; - -static int __exit coh901331_remove(struct platform_device *pdev) -{ - struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); - - if (rtap) { - free_irq(rtap->irq, rtap); - rtc_device_unregister(rtap->rtc); - clk_put(rtap->clk); - iounmap(rtap->virtbase); - release_mem_region(rtap->phybase, rtap->physize); - platform_set_drvdata(pdev, NULL); - kfree(rtap); - } - - return 0; -} - - -static int __init coh901331_probe(struct platform_device *pdev) -{ - int ret; - struct coh901331_port *rtap; - struct resource *res; - - rtap = kzalloc(sizeof(struct coh901331_port), GFP_KERNEL); - if (!rtap) - return -ENOMEM; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - ret = -ENOENT; - goto out_no_resource; - } - rtap->phybase = res->start; - rtap->physize = resource_size(res); - - if (request_mem_region(rtap->phybase, rtap->physize, - "rtc-coh901331") == NULL) { - ret = -EBUSY; - goto out_no_memregion; - } - - rtap->virtbase = ioremap(rtap->phybase, rtap->physize); - if (!rtap->virtbase) { - ret = -ENOMEM; - goto out_no_remap; - } - - rtap->irq = platform_get_irq(pdev, 0); - if (request_irq(rtap->irq, coh901331_interrupt, IRQF_DISABLED, - "RTC COH 901 331 Alarm", rtap)) { - ret = -EIO; - goto out_no_irq; - } - - rtap->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(rtap->clk)) { - ret = PTR_ERR(rtap->clk); - dev_err(&pdev->dev, "could not get clock\n"); - goto out_no_clk; - } - - /* We enable/disable the clock only to assure it works */ - ret = clk_enable(rtap->clk); - if (ret) { - dev_err(&pdev->dev, "could not enable clock\n"); - goto out_no_clk_enable; - } - clk_disable(rtap->clk); - - rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops, - THIS_MODULE); - if (IS_ERR(rtap->rtc)) { - ret = PTR_ERR(rtap->rtc); - goto out_no_rtc; - } - - platform_set_drvdata(pdev, rtap); - - return 0; - - out_no_rtc: - out_no_clk_enable: - clk_put(rtap->clk); - out_no_clk: - free_irq(rtap->irq, rtap); - out_no_irq: - iounmap(rtap->virtbase); - out_no_remap: - platform_set_drvdata(pdev, NULL); - out_no_memregion: - release_mem_region(rtap->phybase, SZ_4K); - out_no_resource: - kfree(rtap); - return ret; -} - -#ifdef CONFIG_PM -static int coh901331_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); - - /* - * If this RTC alarm will be used for waking the system up, - * don't disable it of course. Else we just disable the alarm - * and await suspension. - */ - if (device_may_wakeup(&pdev->dev)) { - enable_irq_wake(rtap->irq); - } else { - clk_enable(rtap->clk); - rtap->irqmaskstore = readl(rtap->virtbase + COH901331_IRQ_MASK); - writel(0, rtap->virtbase + COH901331_IRQ_MASK); - clk_disable(rtap->clk); - } - return 0; -} - -static int coh901331_resume(struct platform_device *pdev) -{ - struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); - - if (device_may_wakeup(&pdev->dev)) - disable_irq_wake(rtap->irq); - else - clk_enable(rtap->clk); - writel(rtap->irqmaskstore, rtap->virtbase + COH901331_IRQ_MASK); - clk_disable(rtap->clk); - return 0; -} -#else -#define coh901331_suspend NULL -#define coh901331_resume NULL -#endif - -static void coh901331_shutdown(struct platform_device *pdev) -{ - struct coh901331_port *rtap = dev_get_drvdata(&pdev->dev); - - clk_enable(rtap->clk); - writel(0, rtap->virtbase + COH901331_IRQ_MASK); - clk_disable(rtap->clk); -} - -static struct platform_driver coh901331_driver = { - .driver = { - .name = "rtc-coh901331", - .owner = THIS_MODULE, - }, - .remove = __exit_p(coh901331_remove), - .suspend = coh901331_suspend, - .resume = coh901331_resume, - .shutdown = coh901331_shutdown, -}; - -static int __init coh901331_init(void) -{ - return platform_driver_probe(&coh901331_driver, coh901331_probe); -} - -static void __exit coh901331_exit(void) -{ - platform_driver_unregister(&coh901331_driver); -} - -module_init(coh901331_init); -module_exit(coh901331_exit); - -MODULE_AUTHOR("Linus Walleij "); -MODULE_DESCRIPTION("ST-Ericsson AB COH 901 331 RTC Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-ds1305.c b/trunk/drivers/rtc/rtc-ds1305.c index 2736b11a1b1e..8f410e59d9f5 100644 --- a/trunk/drivers/rtc/rtc-ds1305.c +++ b/trunk/drivers/rtc/rtc-ds1305.c @@ -841,4 +841,3 @@ module_exit(ds1305_exit); MODULE_DESCRIPTION("RTC driver for DS1305 and DS1306 chips"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:rtc-ds1305"); diff --git a/trunk/drivers/rtc/rtc-ds1307.c b/trunk/drivers/rtc/rtc-ds1307.c index eb99ee4fa0f5..47a93c022d91 100644 --- a/trunk/drivers/rtc/rtc-ds1307.c +++ b/trunk/drivers/rtc/rtc-ds1307.c @@ -896,7 +896,8 @@ static int __devinit ds1307_probe(struct i2c_client *client, return 0; exit_irq: - rtc_device_unregister(ds1307->rtc); + if (ds1307->rtc) + rtc_device_unregister(ds1307->rtc); exit_free: kfree(ds1307); return err; diff --git a/trunk/drivers/rtc/rtc-ds1390.c b/trunk/drivers/rtc/rtc-ds1390.c index cdb705057091..e01b955db077 100644 --- a/trunk/drivers/rtc/rtc-ds1390.c +++ b/trunk/drivers/rtc/rtc-ds1390.c @@ -189,4 +189,3 @@ module_exit(ds1390_exit); MODULE_DESCRIPTION("Dallas/Maxim DS1390/93/94 SPI RTC driver"); MODULE_AUTHOR("Mark Jackson "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:rtc-ds1390"); diff --git a/trunk/drivers/rtc/rtc-ds3234.c b/trunk/drivers/rtc/rtc-ds3234.c index a774ca35b5f7..c51589ede5b7 100644 --- a/trunk/drivers/rtc/rtc-ds3234.c +++ b/trunk/drivers/rtc/rtc-ds3234.c @@ -188,4 +188,3 @@ module_exit(ds3234_exit); MODULE_DESCRIPTION("DS3234 SPI RTC driver"); MODULE_AUTHOR("Dennis Aberilla "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:ds3234"); diff --git a/trunk/drivers/rtc/rtc-ep93xx.c b/trunk/drivers/rtc/rtc-ep93xx.c index 9da02d108b73..551332e4ed02 100644 --- a/trunk/drivers/rtc/rtc-ep93xx.c +++ b/trunk/drivers/rtc/rtc-ep93xx.c @@ -128,16 +128,12 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - err = -ENXIO; - goto fail_free; - } + if (res == NULL) + return -ENXIO; res = request_mem_region(res->start, resource_size(res), pdev->name); - if (res == NULL) { - err = -EBUSY; - goto fail_free; - } + if (res == NULL) + return -EBUSY; ep93xx_rtc->mmio_base = ioremap(res->start, resource_size(res)); if (ep93xx_rtc->mmio_base == NULL) { @@ -173,8 +169,6 @@ static int __init ep93xx_rtc_probe(struct platform_device *pdev) pdev->dev.platform_data = NULL; } release_mem_region(res->start, resource_size(res)); -fail_free: - kfree(ep93xx_rtc); return err; } diff --git a/trunk/drivers/rtc/rtc-m41t94.c b/trunk/drivers/rtc/rtc-m41t94.c index c8c97a4169d4..c3a18c58daf6 100644 --- a/trunk/drivers/rtc/rtc-m41t94.c +++ b/trunk/drivers/rtc/rtc-m41t94.c @@ -171,4 +171,3 @@ module_exit(m41t94_exit); MODULE_AUTHOR("Kim B. Heino "); MODULE_DESCRIPTION("Driver for ST M41T94 SPI RTC"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:rtc-m41t94"); diff --git a/trunk/drivers/rtc/rtc-max6902.c b/trunk/drivers/rtc/rtc-max6902.c index 657403ebd54a..36a8ea9ed8ba 100644 --- a/trunk/drivers/rtc/rtc-max6902.c +++ b/trunk/drivers/rtc/rtc-max6902.c @@ -175,4 +175,3 @@ module_exit(max6902_exit); MODULE_DESCRIPTION ("max6902 spi RTC driver"); MODULE_AUTHOR ("Raphael Assenat"); MODULE_LICENSE ("GPL"); -MODULE_ALIAS("spi:rtc-max6902"); diff --git a/trunk/drivers/rtc/rtc-mxc.c b/trunk/drivers/rtc/rtc-mxc.c deleted file mode 100644 index 6bd5072d4eb7..000000000000 --- a/trunk/drivers/rtc/rtc-mxc.c +++ /dev/null @@ -1,507 +0,0 @@ -/* - * Copyright 2004-2008 Freescale Semiconductor, Inc. All Rights Reserved. - * - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ - -#include -#include -#include -#include -#include -#include - -#include - -#define RTC_INPUT_CLK_32768HZ (0x00 << 5) -#define RTC_INPUT_CLK_32000HZ (0x01 << 5) -#define RTC_INPUT_CLK_38400HZ (0x02 << 5) - -#define RTC_SW_BIT (1 << 0) -#define RTC_ALM_BIT (1 << 2) -#define RTC_1HZ_BIT (1 << 4) -#define RTC_2HZ_BIT (1 << 7) -#define RTC_SAM0_BIT (1 << 8) -#define RTC_SAM1_BIT (1 << 9) -#define RTC_SAM2_BIT (1 << 10) -#define RTC_SAM3_BIT (1 << 11) -#define RTC_SAM4_BIT (1 << 12) -#define RTC_SAM5_BIT (1 << 13) -#define RTC_SAM6_BIT (1 << 14) -#define RTC_SAM7_BIT (1 << 15) -#define PIT_ALL_ON (RTC_2HZ_BIT | RTC_SAM0_BIT | RTC_SAM1_BIT | \ - RTC_SAM2_BIT | RTC_SAM3_BIT | RTC_SAM4_BIT | \ - RTC_SAM5_BIT | RTC_SAM6_BIT | RTC_SAM7_BIT) - -#define RTC_ENABLE_BIT (1 << 7) - -#define MAX_PIE_NUM 9 -#define MAX_PIE_FREQ 512 -static const u32 PIE_BIT_DEF[MAX_PIE_NUM][2] = { - { 2, RTC_2HZ_BIT }, - { 4, RTC_SAM0_BIT }, - { 8, RTC_SAM1_BIT }, - { 16, RTC_SAM2_BIT }, - { 32, RTC_SAM3_BIT }, - { 64, RTC_SAM4_BIT }, - { 128, RTC_SAM5_BIT }, - { 256, RTC_SAM6_BIT }, - { MAX_PIE_FREQ, RTC_SAM7_BIT }, -}; - -/* Those are the bits from a classic RTC we want to mimic */ -#define RTC_IRQF 0x80 /* any of the following 3 is active */ -#define RTC_PF 0x40 /* Periodic interrupt */ -#define RTC_AF 0x20 /* Alarm interrupt */ -#define RTC_UF 0x10 /* Update interrupt for 1Hz RTC */ - -#define MXC_RTC_TIME 0 -#define MXC_RTC_ALARM 1 - -#define RTC_HOURMIN 0x00 /* 32bit rtc hour/min counter reg */ -#define RTC_SECOND 0x04 /* 32bit rtc seconds counter reg */ -#define RTC_ALRM_HM 0x08 /* 32bit rtc alarm hour/min reg */ -#define RTC_ALRM_SEC 0x0C /* 32bit rtc alarm seconds reg */ -#define RTC_RTCCTL 0x10 /* 32bit rtc control reg */ -#define RTC_RTCISR 0x14 /* 32bit rtc interrupt status reg */ -#define RTC_RTCIENR 0x18 /* 32bit rtc interrupt enable reg */ -#define RTC_STPWCH 0x1C /* 32bit rtc stopwatch min reg */ -#define RTC_DAYR 0x20 /* 32bit rtc days counter reg */ -#define RTC_DAYALARM 0x24 /* 32bit rtc day alarm reg */ -#define RTC_TEST1 0x28 /* 32bit rtc test reg 1 */ -#define RTC_TEST2 0x2C /* 32bit rtc test reg 2 */ -#define RTC_TEST3 0x30 /* 32bit rtc test reg 3 */ - -struct rtc_plat_data { - struct rtc_device *rtc; - void __iomem *ioaddr; - int irq; - struct clk *clk; - unsigned int irqen; - int alrm_sec; - int alrm_min; - int alrm_hour; - int alrm_mday; - struct timespec mxc_rtc_delta; - struct rtc_time g_rtc_alarm; -}; - -/* - * This function is used to obtain the RTC time or the alarm value in - * second. - */ -static u32 get_alarm_or_time(struct device *dev, int time_alarm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - u32 day = 0, hr = 0, min = 0, sec = 0, hr_min = 0; - - switch (time_alarm) { - case MXC_RTC_TIME: - day = readw(ioaddr + RTC_DAYR); - hr_min = readw(ioaddr + RTC_HOURMIN); - sec = readw(ioaddr + RTC_SECOND); - break; - case MXC_RTC_ALARM: - day = readw(ioaddr + RTC_DAYALARM); - hr_min = readw(ioaddr + RTC_ALRM_HM) & 0xffff; - sec = readw(ioaddr + RTC_ALRM_SEC); - break; - } - - hr = hr_min >> 8; - min = hr_min & 0xff; - - return (((day * 24 + hr) * 60) + min) * 60 + sec; -} - -/* - * This function sets the RTC alarm value or the time value. - */ -static void set_alarm_or_time(struct device *dev, int time_alarm, u32 time) -{ - u32 day, hr, min, sec, temp; - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - - day = time / 86400; - time -= day * 86400; - - /* time is within a day now */ - hr = time / 3600; - time -= hr * 3600; - - /* time is within an hour now */ - min = time / 60; - sec = time - min * 60; - - temp = (hr << 8) + min; - - switch (time_alarm) { - case MXC_RTC_TIME: - writew(day, ioaddr + RTC_DAYR); - writew(sec, ioaddr + RTC_SECOND); - writew(temp, ioaddr + RTC_HOURMIN); - break; - case MXC_RTC_ALARM: - writew(day, ioaddr + RTC_DAYALARM); - writew(sec, ioaddr + RTC_ALRM_SEC); - writew(temp, ioaddr + RTC_ALRM_HM); - break; - } -} - -/* - * This function updates the RTC alarm registers and then clears all the - * interrupt status bits. - */ -static int rtc_update_alarm(struct device *dev, struct rtc_time *alrm) -{ - struct rtc_time alarm_tm, now_tm; - unsigned long now, time; - int ret; - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - - now = get_alarm_or_time(dev, MXC_RTC_TIME); - rtc_time_to_tm(now, &now_tm); - alarm_tm.tm_year = now_tm.tm_year; - alarm_tm.tm_mon = now_tm.tm_mon; - alarm_tm.tm_mday = now_tm.tm_mday; - alarm_tm.tm_hour = alrm->tm_hour; - alarm_tm.tm_min = alrm->tm_min; - alarm_tm.tm_sec = alrm->tm_sec; - rtc_tm_to_time(&now_tm, &now); - rtc_tm_to_time(&alarm_tm, &time); - - if (time < now) { - time += 60 * 60 * 24; - rtc_time_to_tm(time, &alarm_tm); - } - - ret = rtc_tm_to_time(&alarm_tm, &time); - - /* clear all the interrupt status bits */ - writew(readw(ioaddr + RTC_RTCISR), ioaddr + RTC_RTCISR); - set_alarm_or_time(dev, MXC_RTC_ALARM, time); - - return ret; -} - -/* This function is the RTC interrupt service routine. */ -static irqreturn_t mxc_rtc_interrupt(int irq, void *dev_id) -{ - struct platform_device *pdev = dev_id; - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - u32 status; - u32 events = 0; - - spin_lock_irq(&pdata->rtc->irq_lock); - status = readw(ioaddr + RTC_RTCISR) & readw(ioaddr + RTC_RTCIENR); - /* clear interrupt sources */ - writew(status, ioaddr + RTC_RTCISR); - - /* clear alarm interrupt if it has occurred */ - if (status & RTC_ALM_BIT) - status &= ~RTC_ALM_BIT; - - /* update irq data & counter */ - if (status & RTC_ALM_BIT) - events |= (RTC_AF | RTC_IRQF); - - if (status & RTC_1HZ_BIT) - events |= (RTC_UF | RTC_IRQF); - - if (status & PIT_ALL_ON) - events |= (RTC_PF | RTC_IRQF); - - if ((status & RTC_ALM_BIT) && rtc_valid_tm(&pdata->g_rtc_alarm)) - rtc_update_alarm(&pdev->dev, &pdata->g_rtc_alarm); - - rtc_update_irq(pdata->rtc, 1, events); - spin_unlock_irq(&pdata->rtc->irq_lock); - - return IRQ_HANDLED; -} - -/* - * Clear all interrupts and release the IRQ - */ -static void mxc_rtc_release(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - - spin_lock_irq(&pdata->rtc->irq_lock); - - /* Disable all rtc interrupts */ - writew(0, ioaddr + RTC_RTCIENR); - - /* Clear all interrupt status */ - writew(0xffffffff, ioaddr + RTC_RTCISR); - - spin_unlock_irq(&pdata->rtc->irq_lock); -} - -static void mxc_rtc_irq_enable(struct device *dev, unsigned int bit, - unsigned int enabled) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - u32 reg; - - spin_lock_irq(&pdata->rtc->irq_lock); - reg = readw(ioaddr + RTC_RTCIENR); - - if (enabled) - reg |= bit; - else - reg &= ~bit; - - writew(reg, ioaddr + RTC_RTCIENR); - spin_unlock_irq(&pdata->rtc->irq_lock); -} - -static int mxc_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - mxc_rtc_irq_enable(dev, RTC_ALM_BIT, enabled); - return 0; -} - -static int mxc_rtc_update_irq_enable(struct device *dev, unsigned int enabled) -{ - mxc_rtc_irq_enable(dev, RTC_1HZ_BIT, enabled); - return 0; -} - -/* - * This function reads the current RTC time into tm in Gregorian date. - */ -static int mxc_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - u32 val; - - /* Avoid roll-over from reading the different registers */ - do { - val = get_alarm_or_time(dev, MXC_RTC_TIME); - } while (val != get_alarm_or_time(dev, MXC_RTC_TIME)); - - rtc_time_to_tm(val, tm); - - return 0; -} - -/* - * This function sets the internal RTC time based on tm in Gregorian date. - */ -static int mxc_rtc_set_mmss(struct device *dev, unsigned long time) -{ - /* Avoid roll-over from reading the different registers */ - do { - set_alarm_or_time(dev, MXC_RTC_TIME, time); - } while (time != get_alarm_or_time(dev, MXC_RTC_TIME)); - - return 0; -} - -/* - * This function reads the current alarm value into the passed in 'alrm' - * argument. It updates the alrm's pending field value based on the whether - * an alarm interrupt occurs or not. - */ -static int mxc_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - void __iomem *ioaddr = pdata->ioaddr; - - rtc_time_to_tm(get_alarm_or_time(dev, MXC_RTC_ALARM), &alrm->time); - alrm->pending = ((readw(ioaddr + RTC_RTCISR) & RTC_ALM_BIT)) ? 1 : 0; - - return 0; -} - -/* - * This function sets the RTC alarm based on passed in alrm. - */ -static int mxc_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - int ret; - - if (rtc_valid_tm(&alrm->time)) { - if (alrm->time.tm_sec > 59 || - alrm->time.tm_hour > 23 || - alrm->time.tm_min > 59) - return -EINVAL; - - ret = rtc_update_alarm(dev, &alrm->time); - } else { - ret = rtc_valid_tm(&alrm->time); - if (ret) - return ret; - - ret = rtc_update_alarm(dev, &alrm->time); - } - - if (ret) - return ret; - - memcpy(&pdata->g_rtc_alarm, &alrm->time, sizeof(struct rtc_time)); - mxc_rtc_irq_enable(dev, RTC_ALM_BIT, alrm->enabled); - - return 0; -} - -/* RTC layer */ -static struct rtc_class_ops mxc_rtc_ops = { - .release = mxc_rtc_release, - .read_time = mxc_rtc_read_time, - .set_mmss = mxc_rtc_set_mmss, - .read_alarm = mxc_rtc_read_alarm, - .set_alarm = mxc_rtc_set_alarm, - .alarm_irq_enable = mxc_rtc_alarm_irq_enable, - .update_irq_enable = mxc_rtc_update_irq_enable, -}; - -static int __init mxc_rtc_probe(struct platform_device *pdev) -{ - struct clk *clk; - struct resource *res; - struct rtc_device *rtc; - struct rtc_plat_data *pdata = NULL; - u32 reg; - int ret, rate; - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) - return -ENODEV; - - pdata = kzalloc(sizeof(*pdata), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - - pdata->ioaddr = ioremap(res->start, resource_size(res)); - - clk = clk_get(&pdev->dev, "ckil"); - if (IS_ERR(clk)) - return PTR_ERR(clk); - - rate = clk_get_rate(clk); - clk_put(clk); - - if (rate == 32768) - reg = RTC_INPUT_CLK_32768HZ; - else if (rate == 32000) - reg = RTC_INPUT_CLK_32000HZ; - else if (rate == 38400) - reg = RTC_INPUT_CLK_38400HZ; - else { - dev_err(&pdev->dev, "rtc clock is not valid (%lu)\n", - clk_get_rate(clk)); - ret = -EINVAL; - goto exit_free_pdata; - } - - reg |= RTC_ENABLE_BIT; - writew(reg, (pdata->ioaddr + RTC_RTCCTL)); - if (((readw(pdata->ioaddr + RTC_RTCCTL)) & RTC_ENABLE_BIT) == 0) { - dev_err(&pdev->dev, "hardware module can't be enabled!\n"); - ret = -EIO; - goto exit_free_pdata; - } - - pdata->clk = clk_get(&pdev->dev, "rtc"); - if (IS_ERR(pdata->clk)) { - dev_err(&pdev->dev, "unable to get clock!\n"); - ret = PTR_ERR(pdata->clk); - goto exit_free_pdata; - } - - clk_enable(pdata->clk); - - rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops, - THIS_MODULE); - if (IS_ERR(rtc)) { - ret = PTR_ERR(rtc); - goto exit_put_clk; - } - - pdata->rtc = rtc; - platform_set_drvdata(pdev, pdata); - - /* Configure and enable the RTC */ - pdata->irq = platform_get_irq(pdev, 0); - - if (pdata->irq >= 0 && - request_irq(pdata->irq, mxc_rtc_interrupt, IRQF_SHARED, - pdev->name, pdev) < 0) { - dev_warn(&pdev->dev, "interrupt not available.\n"); - pdata->irq = -1; - } - - return 0; - -exit_put_clk: - clk_put(pdata->clk); - -exit_free_pdata: - kfree(pdata); - - return ret; -} - -static int __exit mxc_rtc_remove(struct platform_device *pdev) -{ - struct rtc_plat_data *pdata = platform_get_drvdata(pdev); - - rtc_device_unregister(pdata->rtc); - - if (pdata->irq >= 0) - free_irq(pdata->irq, pdev); - - clk_disable(pdata->clk); - clk_put(pdata->clk); - kfree(pdata); - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver mxc_rtc_driver = { - .driver = { - .name = "mxc_rtc", - .owner = THIS_MODULE, - }, - .remove = __exit_p(mxc_rtc_remove), -}; - -static int __init mxc_rtc_init(void) -{ - return platform_driver_probe(&mxc_rtc_driver, mxc_rtc_probe); -} - -static void __exit mxc_rtc_exit(void) -{ - platform_driver_unregister(&mxc_rtc_driver); -} - -module_init(mxc_rtc_init); -module_exit(mxc_rtc_exit); - -MODULE_AUTHOR("Daniel Mack "); -MODULE_DESCRIPTION("RTC driver for Freescale MXC"); -MODULE_LICENSE("GPL"); - diff --git a/trunk/drivers/rtc/rtc-pcap.c b/trunk/drivers/rtc/rtc-pcap.c deleted file mode 100644 index a99c28992d21..000000000000 --- a/trunk/drivers/rtc/rtc-pcap.c +++ /dev/null @@ -1,224 +0,0 @@ -/* - * pcap rtc code for Motorola EZX phones - * - * Copyright (c) 2008 guiming zhuo - * Copyright (c) 2009 Daniel Ribeiro - * - * Based on Motorola's rtc.c Copyright (c) 2003-2005 Motorola - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include -#include -#include -#include -#include -#include - -struct pcap_rtc { - struct pcap_chip *pcap; - struct rtc_device *rtc; -}; - -static irqreturn_t pcap_rtc_irq(int irq, void *_pcap_rtc) -{ - struct pcap_rtc *pcap_rtc = _pcap_rtc; - unsigned long rtc_events; - - if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ)) - rtc_events = RTC_IRQF | RTC_UF; - else if (irq == pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA)) - rtc_events = RTC_IRQF | RTC_AF; - else - rtc_events = 0; - - rtc_update_irq(pcap_rtc->rtc, 1, rtc_events); - return IRQ_HANDLED; -} - -static int pcap_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); - struct rtc_time *tm = &alrm->time; - unsigned long secs; - u32 tod; /* time of day, seconds since midnight */ - u32 days; /* days since 1/1/1970 */ - - ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TODA, &tod); - secs = tod & PCAP_RTC_TOD_MASK; - - ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, &days); - secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY; - - rtc_time_to_tm(secs, tm); - - return 0; -} - -static int pcap_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); - struct rtc_time *tm = &alrm->time; - unsigned long secs; - u32 tod, days; - - rtc_tm_to_time(tm, &secs); - - tod = secs % SEC_PER_DAY; - ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TODA, tod); - - days = secs / SEC_PER_DAY; - ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAYA, days); - - return 0; -} - -static int pcap_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); - unsigned long secs; - u32 tod, days; - - ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_TOD, &tod); - secs = tod & PCAP_RTC_TOD_MASK; - - ezx_pcap_read(pcap_rtc->pcap, PCAP_REG_RTC_DAY, &days); - secs += (days & PCAP_RTC_DAY_MASK) * SEC_PER_DAY; - - rtc_time_to_tm(secs, tm); - - return rtc_valid_tm(tm); -} - -static int pcap_rtc_set_mmss(struct device *dev, unsigned long secs) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); - u32 tod, days; - - tod = secs % SEC_PER_DAY; - ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_TOD, tod); - - days = secs / SEC_PER_DAY; - ezx_pcap_write(pcap_rtc->pcap, PCAP_REG_RTC_DAY, days); - - return 0; -} - -static int pcap_rtc_irq_enable(struct device *dev, int pirq, unsigned int en) -{ - struct platform_device *pdev = to_platform_device(dev); - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); - - if (en) - enable_irq(pcap_to_irq(pcap_rtc->pcap, pirq)); - else - disable_irq(pcap_to_irq(pcap_rtc->pcap, pirq)); - - return 0; -} - -static int pcap_rtc_alarm_irq_enable(struct device *dev, unsigned int en) -{ - return pcap_rtc_irq_enable(dev, PCAP_IRQ_TODA, en); -} - -static int pcap_rtc_update_irq_enable(struct device *dev, unsigned int en) -{ - return pcap_rtc_irq_enable(dev, PCAP_IRQ_1HZ, en); -} - -static const struct rtc_class_ops pcap_rtc_ops = { - .read_time = pcap_rtc_read_time, - .read_alarm = pcap_rtc_read_alarm, - .set_alarm = pcap_rtc_set_alarm, - .set_mmss = pcap_rtc_set_mmss, - .alarm_irq_enable = pcap_rtc_alarm_irq_enable, - .update_irq_enable = pcap_rtc_update_irq_enable, -}; - -static int __devinit pcap_rtc_probe(struct platform_device *pdev) -{ - struct pcap_rtc *pcap_rtc; - int timer_irq, alarm_irq; - int err = -ENOMEM; - - pcap_rtc = kmalloc(sizeof(struct pcap_rtc), GFP_KERNEL); - if (!pcap_rtc) - return err; - - pcap_rtc->pcap = dev_get_drvdata(pdev->dev.parent); - - pcap_rtc->rtc = rtc_device_register("pcap", &pdev->dev, - &pcap_rtc_ops, THIS_MODULE); - if (IS_ERR(pcap_rtc->rtc)) { - err = PTR_ERR(pcap_rtc->rtc); - goto fail_rtc; - } - - platform_set_drvdata(pdev, pcap_rtc); - - timer_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ); - alarm_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA); - - err = request_irq(timer_irq, pcap_rtc_irq, 0, "RTC Timer", pcap_rtc); - if (err) - goto fail_timer; - - err = request_irq(alarm_irq, pcap_rtc_irq, 0, "RTC Alarm", pcap_rtc); - if (err) - goto fail_alarm; - - return 0; -fail_alarm: - free_irq(timer_irq, pcap_rtc); -fail_timer: - rtc_device_unregister(pcap_rtc->rtc); -fail_rtc: - kfree(pcap_rtc); - return err; -} - -static int __devexit pcap_rtc_remove(struct platform_device *pdev) -{ - struct pcap_rtc *pcap_rtc = platform_get_drvdata(pdev); - - free_irq(pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ), pcap_rtc); - free_irq(pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA), pcap_rtc); - rtc_device_unregister(pcap_rtc->rtc); - kfree(pcap_rtc); - - return 0; -} - -static struct platform_driver pcap_rtc_driver = { - .remove = __devexit_p(pcap_rtc_remove), - .driver = { - .name = "pcap-rtc", - .owner = THIS_MODULE, - }, -}; - -static int __init rtc_pcap_init(void) -{ - return platform_driver_probe(&pcap_rtc_driver, pcap_rtc_probe); -} - -static void __exit rtc_pcap_exit(void) -{ - platform_driver_unregister(&pcap_rtc_driver); -} - -module_init(rtc_pcap_init); -module_exit(rtc_pcap_exit); - -MODULE_DESCRIPTION("Motorola pcap rtc driver"); -MODULE_AUTHOR("guiming zhuo "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-pcf2123.c b/trunk/drivers/rtc/rtc-pcf2123.c deleted file mode 100644 index e75df9d50e27..000000000000 --- a/trunk/drivers/rtc/rtc-pcf2123.c +++ /dev/null @@ -1,364 +0,0 @@ -/* - * An SPI driver for the Philips PCF2123 RTC - * Copyright 2009 Cyber Switching, Inc. - * - * Author: Chris Verges - * Maintainers: http://www.cyberswitching.com - * - * based on the RS5C348 driver in this same directory. - * - * Thanks to Christian Pellegrin for - * the sysfs contributions to this driver. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - * Please note that the CS is active high, so platform data - * should look something like: - * - * static struct spi_board_info ek_spi_devices[] = { - * ... - * { - * .modalias = "rtc-pcf2123", - * .chip_select = 1, - * .controller_data = (void *)AT91_PIN_PA10, - * .max_speed_hz = 1000 * 1000, - * .mode = SPI_CS_HIGH, - * .bus_num = 0, - * }, - * ... - *}; - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define DRV_VERSION "0.6" - -#define PCF2123_REG_CTRL1 (0x00) /* Control Register 1 */ -#define PCF2123_REG_CTRL2 (0x01) /* Control Register 2 */ -#define PCF2123_REG_SC (0x02) /* datetime */ -#define PCF2123_REG_MN (0x03) -#define PCF2123_REG_HR (0x04) -#define PCF2123_REG_DM (0x05) -#define PCF2123_REG_DW (0x06) -#define PCF2123_REG_MO (0x07) -#define PCF2123_REG_YR (0x08) - -#define PCF2123_SUBADDR (1 << 4) -#define PCF2123_WRITE ((0 << 7) | PCF2123_SUBADDR) -#define PCF2123_READ ((1 << 7) | PCF2123_SUBADDR) - -static struct spi_driver pcf2123_driver; - -struct pcf2123_sysfs_reg { - struct device_attribute attr; - char name[2]; -}; - -struct pcf2123_plat_data { - struct rtc_device *rtc; - struct pcf2123_sysfs_reg regs[16]; -}; - -/* - * Causes a 30 nanosecond delay to ensure that the PCF2123 chip select - * is released properly after an SPI write. This function should be - * called after EVERY read/write call over SPI. - */ -static inline void pcf2123_delay_trec(void) -{ - ndelay(30); -} - -static ssize_t pcf2123_show(struct device *dev, struct device_attribute *attr, - char *buffer) -{ - struct spi_device *spi = to_spi_device(dev); - struct pcf2123_sysfs_reg *r; - u8 txbuf[1], rxbuf[1]; - unsigned long reg; - int ret; - - r = container_of(attr, struct pcf2123_sysfs_reg, attr); - - if (strict_strtoul(r->name, 16, ®)) - return -EINVAL; - - txbuf[0] = PCF2123_READ | reg; - ret = spi_write_then_read(spi, txbuf, 1, rxbuf, 1); - if (ret < 0) - return -EIO; - pcf2123_delay_trec(); - return sprintf(buffer, "0x%x\n", rxbuf[0]); -} - -static ssize_t pcf2123_store(struct device *dev, struct device_attribute *attr, - const char *buffer, size_t count) { - struct spi_device *spi = to_spi_device(dev); - struct pcf2123_sysfs_reg *r; - u8 txbuf[2]; - unsigned long reg; - unsigned long val; - - int ret; - - r = container_of(attr, struct pcf2123_sysfs_reg, attr); - - if (strict_strtoul(r->name, 16, ®) - || strict_strtoul(buffer, 10, &val)) - return -EINVAL; - - txbuf[0] = PCF2123_WRITE | reg; - txbuf[1] = val; - ret = spi_write(spi, txbuf, sizeof(txbuf)); - if (ret < 0) - return -EIO; - pcf2123_delay_trec(); - return count; -} - -static int pcf2123_rtc_read_time(struct device *dev, struct rtc_time *tm) -{ - struct spi_device *spi = to_spi_device(dev); - u8 txbuf[1], rxbuf[7]; - int ret; - - txbuf[0] = PCF2123_READ | PCF2123_REG_SC; - ret = spi_write_then_read(spi, txbuf, sizeof(txbuf), - rxbuf, sizeof(rxbuf)); - if (ret < 0) - return ret; - pcf2123_delay_trec(); - - tm->tm_sec = bcd2bin(rxbuf[0] & 0x7F); - tm->tm_min = bcd2bin(rxbuf[1] & 0x7F); - tm->tm_hour = bcd2bin(rxbuf[2] & 0x3F); /* rtc hr 0-23 */ - tm->tm_mday = bcd2bin(rxbuf[3] & 0x3F); - tm->tm_wday = rxbuf[4] & 0x07; - tm->tm_mon = bcd2bin(rxbuf[5] & 0x1F) - 1; /* rtc mn 1-12 */ - tm->tm_year = bcd2bin(rxbuf[6]); - if (tm->tm_year < 70) - tm->tm_year += 100; /* assume we are in 1970...2069 */ - - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __func__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - - /* the clock can give out invalid datetime, but we cannot return - * -EINVAL otherwise hwclock will refuse to set the time on bootup. - */ - if (rtc_valid_tm(tm) < 0) - dev_err(dev, "retrieved date/time is not valid.\n"); - - return 0; -} - -static int pcf2123_rtc_set_time(struct device *dev, struct rtc_time *tm) -{ - struct spi_device *spi = to_spi_device(dev); - u8 txbuf[8]; - int ret; - - dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, " - "mday=%d, mon=%d, year=%d, wday=%d\n", - __func__, - tm->tm_sec, tm->tm_min, tm->tm_hour, - tm->tm_mday, tm->tm_mon, tm->tm_year, tm->tm_wday); - - /* Stop the counter first */ - txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; - txbuf[1] = 0x20; - ret = spi_write(spi, txbuf, 2); - if (ret < 0) - return ret; - pcf2123_delay_trec(); - - /* Set the new time */ - txbuf[0] = PCF2123_WRITE | PCF2123_REG_SC; - txbuf[1] = bin2bcd(tm->tm_sec & 0x7F); - txbuf[2] = bin2bcd(tm->tm_min & 0x7F); - txbuf[3] = bin2bcd(tm->tm_hour & 0x3F); - txbuf[4] = bin2bcd(tm->tm_mday & 0x3F); - txbuf[5] = tm->tm_wday & 0x07; - txbuf[6] = bin2bcd((tm->tm_mon + 1) & 0x1F); /* rtc mn 1-12 */ - txbuf[7] = bin2bcd(tm->tm_year < 100 ? tm->tm_year : tm->tm_year - 100); - - ret = spi_write(spi, txbuf, sizeof(txbuf)); - if (ret < 0) - return ret; - pcf2123_delay_trec(); - - /* Start the counter */ - txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; - txbuf[1] = 0x00; - ret = spi_write(spi, txbuf, 2); - if (ret < 0) - return ret; - pcf2123_delay_trec(); - - return 0; -} - -static const struct rtc_class_ops pcf2123_rtc_ops = { - .read_time = pcf2123_rtc_read_time, - .set_time = pcf2123_rtc_set_time, -}; - -static int __devinit pcf2123_probe(struct spi_device *spi) -{ - struct rtc_device *rtc; - struct pcf2123_plat_data *pdata; - u8 txbuf[2], rxbuf[2]; - int ret, i; - - pdata = kzalloc(sizeof(struct pcf2123_plat_data), GFP_KERNEL); - if (!pdata) - return -ENOMEM; - spi->dev.platform_data = pdata; - - /* Send a software reset command */ - txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; - txbuf[1] = 0x58; - dev_dbg(&spi->dev, "resetting RTC (0x%02X 0x%02X)\n", - txbuf[0], txbuf[1]); - ret = spi_write(spi, txbuf, 2 * sizeof(u8)); - if (ret < 0) - goto kfree_exit; - pcf2123_delay_trec(); - - /* Stop the counter */ - txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; - txbuf[1] = 0x20; - dev_dbg(&spi->dev, "stopping RTC (0x%02X 0x%02X)\n", - txbuf[0], txbuf[1]); - ret = spi_write(spi, txbuf, 2 * sizeof(u8)); - if (ret < 0) - goto kfree_exit; - pcf2123_delay_trec(); - - /* See if the counter was actually stopped */ - txbuf[0] = PCF2123_READ | PCF2123_REG_CTRL1; - dev_dbg(&spi->dev, "checking for presence of RTC (0x%02X)\n", - txbuf[0]); - ret = spi_write_then_read(spi, txbuf, 1 * sizeof(u8), - rxbuf, 2 * sizeof(u8)); - dev_dbg(&spi->dev, "received data from RTC (0x%02X 0x%02X)\n", - rxbuf[0], rxbuf[1]); - if (ret < 0) - goto kfree_exit; - pcf2123_delay_trec(); - - if (!(rxbuf[0] & 0x20)) { - dev_err(&spi->dev, "chip not found\n"); - goto kfree_exit; - } - - dev_info(&spi->dev, "chip found, driver version " DRV_VERSION "\n"); - dev_info(&spi->dev, "spiclk %u KHz.\n", - (spi->max_speed_hz + 500) / 1000); - - /* Start the counter */ - txbuf[0] = PCF2123_WRITE | PCF2123_REG_CTRL1; - txbuf[1] = 0x00; - ret = spi_write(spi, txbuf, sizeof(txbuf)); - if (ret < 0) - goto kfree_exit; - pcf2123_delay_trec(); - - /* Finalize the initialization */ - rtc = rtc_device_register(pcf2123_driver.driver.name, &spi->dev, - &pcf2123_rtc_ops, THIS_MODULE); - - if (IS_ERR(rtc)) { - dev_err(&spi->dev, "failed to register.\n"); - ret = PTR_ERR(rtc); - goto kfree_exit; - } - - pdata->rtc = rtc; - - for (i = 0; i < 16; i++) { - sprintf(pdata->regs[i].name, "%1x", i); - pdata->regs[i].attr.attr.mode = S_IRUGO | S_IWUSR; - pdata->regs[i].attr.attr.name = pdata->regs[i].name; - pdata->regs[i].attr.show = pcf2123_show; - pdata->regs[i].attr.store = pcf2123_store; - ret = device_create_file(&spi->dev, &pdata->regs[i].attr); - if (ret) { - dev_err(&spi->dev, "Unable to create sysfs %s\n", - pdata->regs[i].name); - goto sysfs_exit; - } - } - - return 0; - -sysfs_exit: - for (i--; i >= 0; i--) - device_remove_file(&spi->dev, &pdata->regs[i].attr); - -kfree_exit: - kfree(pdata); - spi->dev.platform_data = NULL; - return ret; -} - -static int pcf2123_remove(struct spi_device *spi) -{ - struct pcf2123_plat_data *pdata = spi->dev.platform_data; - int i; - - if (pdata) { - struct rtc_device *rtc = pdata->rtc; - - if (rtc) - rtc_device_unregister(rtc); - for (i = 0; i < 16; i++) - if (pdata->regs[i].name[0]) - device_remove_file(&spi->dev, - &pdata->regs[i].attr); - kfree(pdata); - } - - return 0; -} - -static struct spi_driver pcf2123_driver = { - .driver = { - .name = "rtc-pcf2123", - .bus = &spi_bus_type, - .owner = THIS_MODULE, - }, - .probe = pcf2123_probe, - .remove = __devexit_p(pcf2123_remove), -}; - -static int __init pcf2123_init(void) -{ - return spi_register_driver(&pcf2123_driver); -} - -static void __exit pcf2123_exit(void) -{ - spi_unregister_driver(&pcf2123_driver); -} - -MODULE_AUTHOR("Chris Verges "); -MODULE_DESCRIPTION("NXP PCF2123 RTC driver"); -MODULE_LICENSE("GPL"); -MODULE_VERSION(DRV_VERSION); - -module_init(pcf2123_init); -module_exit(pcf2123_exit); diff --git a/trunk/drivers/rtc/rtc-r9701.c b/trunk/drivers/rtc/rtc-r9701.c index 9beba49c3c5b..42028f233bef 100644 --- a/trunk/drivers/rtc/rtc-r9701.c +++ b/trunk/drivers/rtc/rtc-r9701.c @@ -174,4 +174,3 @@ module_exit(r9701_exit); MODULE_DESCRIPTION("r9701 spi RTC driver"); MODULE_AUTHOR("Magnus Damm "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:rtc-r9701"); diff --git a/trunk/drivers/rtc/rtc-rs5c348.c b/trunk/drivers/rtc/rtc-rs5c348.c index 2099037cb3ea..dd1e2bc7a472 100644 --- a/trunk/drivers/rtc/rtc-rs5c348.c +++ b/trunk/drivers/rtc/rtc-rs5c348.c @@ -251,4 +251,3 @@ MODULE_AUTHOR("Atsushi Nemoto "); MODULE_DESCRIPTION("Ricoh RS5C348 RTC driver"); MODULE_LICENSE("GPL"); MODULE_VERSION(DRV_VERSION); -MODULE_ALIAS("spi:rtc-rs5c348"); diff --git a/trunk/drivers/rtc/rtc-stmp3xxx.c b/trunk/drivers/rtc/rtc-stmp3xxx.c deleted file mode 100644 index d7ce1a5c857d..000000000000 --- a/trunk/drivers/rtc/rtc-stmp3xxx.c +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Freescale STMP37XX/STMP378X Real Time Clock driver - * - * Copyright (c) 2007 Sigmatel, Inc. - * Peter Hartley, - * - * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -struct stmp3xxx_rtc_data { - struct rtc_device *rtc; - unsigned irq_count; - void __iomem *io; - int irq_alarm, irq_1msec; -}; - -static void stmp3xxx_wait_time(struct stmp3xxx_rtc_data *rtc_data) -{ - /* - * The datasheet doesn't say which way round the - * NEW_REGS/STALE_REGS bitfields go. In fact it's 0x1=P0, - * 0x2=P1, .., 0x20=P5, 0x40=ALARM, 0x80=SECONDS - */ - while (__raw_readl(rtc_data->io + HW_RTC_STAT) & - BF(0x80, RTC_STAT_STALE_REGS)) - cpu_relax(); -} - -/* Time read/write */ -static int stmp3xxx_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm) -{ - struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); - - stmp3xxx_wait_time(rtc_data); - rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_SECONDS), rtc_tm); - return 0; -} - -static int stmp3xxx_rtc_set_mmss(struct device *dev, unsigned long t) -{ - struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); - - __raw_writel(t, rtc_data->io + HW_RTC_SECONDS); - stmp3xxx_wait_time(rtc_data); - return 0; -} - -/* interrupt(s) handler */ -static irqreturn_t stmp3xxx_rtc_interrupt(int irq, void *dev_id) -{ - struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev_id); - u32 status; - u32 events = 0; - - status = __raw_readl(rtc_data->io + HW_RTC_CTRL) & - (BM_RTC_CTRL_ALARM_IRQ | BM_RTC_CTRL_ONEMSEC_IRQ); - - if (status & BM_RTC_CTRL_ALARM_IRQ) { - stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ, - rtc_data->io + HW_RTC_CTRL); - events |= RTC_AF | RTC_IRQF; - } - - if (status & BM_RTC_CTRL_ONEMSEC_IRQ) { - stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ, - rtc_data->io + HW_RTC_CTRL); - if (++rtc_data->irq_count % 1000 == 0) { - events |= RTC_UF | RTC_IRQF; - rtc_data->irq_count = 0; - } - } - - if (events) - rtc_update_irq(rtc_data->rtc, 1, events); - - return IRQ_HANDLED; -} - -static int stmp3xxx_alarm_irq_enable(struct device *dev, unsigned int enabled) -{ - struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); - void __iomem *p = rtc_data->io + HW_RTC_PERSISTENT0, - *ctl = rtc_data->io + HW_RTC_CTRL; - - if (enabled) { - stmp3xxx_setl(BM_RTC_PERSISTENT0_ALARM_EN | - BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); - stmp3xxx_setl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); - } else { - stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | - BM_RTC_PERSISTENT0_ALARM_WAKE_EN, p); - stmp3xxx_clearl(BM_RTC_CTRL_ALARM_IRQ_EN, ctl); - } - return 0; -} - -static int stmp3xxx_update_irq_enable(struct device *dev, unsigned int enabled) -{ - struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); - - if (enabled) - stmp3xxx_setl(BM_RTC_CTRL_ONEMSEC_IRQ_EN, - rtc_data->io + HW_RTC_CTRL); - else - stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN, - rtc_data->io + HW_RTC_CTRL); - return 0; -} - -static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); - - rtc_time_to_tm(__raw_readl(rtc_data->io + HW_RTC_ALARM), &alm->time); - return 0; -} - -static int stmp3xxx_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm) -{ - unsigned long t; - struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev); - - rtc_tm_to_time(&alm->time, &t); - __raw_writel(t, rtc_data->io + HW_RTC_ALARM); - return 0; -} - -static struct rtc_class_ops stmp3xxx_rtc_ops = { - .alarm_irq_enable = - stmp3xxx_alarm_irq_enable, - .update_irq_enable = - stmp3xxx_update_irq_enable, - .read_time = stmp3xxx_rtc_gettime, - .set_mmss = stmp3xxx_rtc_set_mmss, - .read_alarm = stmp3xxx_rtc_read_alarm, - .set_alarm = stmp3xxx_rtc_set_alarm, -}; - -static int stmp3xxx_rtc_remove(struct platform_device *pdev) -{ - struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(pdev); - - if (!rtc_data) - return 0; - - stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + HW_RTC_CTRL); - free_irq(rtc_data->irq_alarm, &pdev->dev); - free_irq(rtc_data->irq_1msec, &pdev->dev); - rtc_device_unregister(rtc_data->rtc); - iounmap(rtc_data->io); - kfree(rtc_data); - - return 0; -} - -static int stmp3xxx_rtc_probe(struct platform_device *pdev) -{ - struct stmp3xxx_rtc_data *rtc_data; - struct resource *r; - int err; - - rtc_data = kzalloc(sizeof *rtc_data, GFP_KERNEL); - if (!rtc_data) - return -ENOMEM; - - r = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!r) { - dev_err(&pdev->dev, "failed to get resource\n"); - err = -ENXIO; - goto out_free; - } - - rtc_data->io = ioremap(r->start, resource_size(r)); - if (!rtc_data->io) { - dev_err(&pdev->dev, "ioremap failed\n"); - err = -EIO; - goto out_free; - } - - rtc_data->irq_alarm = platform_get_irq(pdev, 0); - rtc_data->irq_1msec = platform_get_irq(pdev, 1); - - if (!(__raw_readl(HW_RTC_STAT + rtc_data->io) & - BM_RTC_STAT_RTC_PRESENT)) { - dev_err(&pdev->dev, "no device onboard\n"); - err = -ENODEV; - goto out_remap; - } - - stmp3xxx_reset_block(rtc_data->io, true); - stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | - BM_RTC_PERSISTENT0_ALARM_WAKE_EN | - BM_RTC_PERSISTENT0_ALARM_WAKE, - rtc_data->io + HW_RTC_PERSISTENT0); - rtc_data->rtc = rtc_device_register(pdev->name, &pdev->dev, - &stmp3xxx_rtc_ops, THIS_MODULE); - if (IS_ERR(rtc_data->rtc)) { - err = PTR_ERR(rtc_data->rtc); - goto out_remap; - } - - rtc_data->irq_count = 0; - err = request_irq(rtc_data->irq_alarm, stmp3xxx_rtc_interrupt, - IRQF_DISABLED, "RTC alarm", &pdev->dev); - if (err) { - dev_err(&pdev->dev, "Cannot claim IRQ%d\n", - rtc_data->irq_alarm); - goto out_irq_alarm; - } - err = request_irq(rtc_data->irq_1msec, stmp3xxx_rtc_interrupt, - IRQF_DISABLED, "RTC tick", &pdev->dev); - if (err) { - dev_err(&pdev->dev, "Cannot claim IRQ%d\n", - rtc_data->irq_1msec); - goto out_irq1; - } - - platform_set_drvdata(pdev, rtc_data); - - return 0; - -out_irq1: - free_irq(rtc_data->irq_alarm, &pdev->dev); -out_irq_alarm: - stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN | BM_RTC_CTRL_ALARM_IRQ_EN, - rtc_data->io + HW_RTC_CTRL); - rtc_device_unregister(rtc_data->rtc); -out_remap: - iounmap(rtc_data->io); -out_free: - kfree(rtc_data); - return err; -} - -#ifdef CONFIG_PM -static int stmp3xxx_rtc_suspend(struct platform_device *dev, pm_message_t state) -{ - return 0; -} - -static int stmp3xxx_rtc_resume(struct platform_device *dev) -{ - struct stmp3xxx_rtc_data *rtc_data = platform_get_drvdata(dev); - - stmp3xxx_reset_block(rtc_data->io, true); - stmp3xxx_clearl(BM_RTC_PERSISTENT0_ALARM_EN | - BM_RTC_PERSISTENT0_ALARM_WAKE_EN | - BM_RTC_PERSISTENT0_ALARM_WAKE, - rtc_data->io + HW_RTC_PERSISTENT0); - return 0; -} -#else -#define stmp3xxx_rtc_suspend NULL -#define stmp3xxx_rtc_resume NULL -#endif - -static struct platform_driver stmp3xxx_rtcdrv = { - .probe = stmp3xxx_rtc_probe, - .remove = stmp3xxx_rtc_remove, - .suspend = stmp3xxx_rtc_suspend, - .resume = stmp3xxx_rtc_resume, - .driver = { - .name = "stmp3xxx-rtc", - .owner = THIS_MODULE, - }, -}; - -static int __init stmp3xxx_rtc_init(void) -{ - return platform_driver_register(&stmp3xxx_rtcdrv); -} - -static void __exit stmp3xxx_rtc_exit(void) -{ - platform_driver_unregister(&stmp3xxx_rtcdrv); -} - -module_init(stmp3xxx_rtc_init); -module_exit(stmp3xxx_rtc_exit); - -MODULE_DESCRIPTION("STMP3xxx RTC Driver"); -MODULE_AUTHOR("dmitry pervushin "); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/rtc/rtc-sysfs.c b/trunk/drivers/rtc/rtc-sysfs.c index 7dd23a6fc825..2531ce4c9db0 100644 --- a/trunk/drivers/rtc/rtc-sysfs.c +++ b/trunk/drivers/rtc/rtc-sysfs.c @@ -102,19 +102,6 @@ rtc_sysfs_set_max_user_freq(struct device *dev, struct device_attribute *attr, return n; } -static ssize_t -rtc_sysfs_show_hctosys(struct device *dev, struct device_attribute *attr, - char *buf) -{ -#ifdef CONFIG_RTC_HCTOSYS_DEVICE - if (strcmp(dev_name(&to_rtc_device(dev)->dev), - CONFIG_RTC_HCTOSYS_DEVICE) == 0) - return sprintf(buf, "1\n"); - else -#endif - return sprintf(buf, "0\n"); -} - static struct device_attribute rtc_attrs[] = { __ATTR(name, S_IRUGO, rtc_sysfs_show_name, NULL), __ATTR(date, S_IRUGO, rtc_sysfs_show_date, NULL), @@ -122,7 +109,6 @@ static struct device_attribute rtc_attrs[] = { __ATTR(since_epoch, S_IRUGO, rtc_sysfs_show_since_epoch, NULL), __ATTR(max_user_freq, S_IRUGO | S_IWUSR, rtc_sysfs_show_max_user_freq, rtc_sysfs_set_max_user_freq), - __ATTR(hctosys, S_IRUGO, rtc_sysfs_show_hctosys, NULL), { }, }; diff --git a/trunk/drivers/s390/block/dasd_eckd.c b/trunk/drivers/s390/block/dasd_eckd.c index ab3521755588..bd9fe2e36dce 100644 --- a/trunk/drivers/s390/block/dasd_eckd.c +++ b/trunk/drivers/s390/block/dasd_eckd.c @@ -935,7 +935,6 @@ static int dasd_eckd_read_features(struct dasd_device *device) struct dasd_eckd_private *private; private = (struct dasd_eckd_private *) device->private; - memset(&private->features, 0, sizeof(struct dasd_rssd_features)); cqr = dasd_smalloc_request(DASD_ECKD_MAGIC, 1 /* PSF */ + 1 /* RSSD */, (sizeof(struct dasd_psf_prssd_data) + sizeof(struct dasd_rssd_features)), @@ -983,9 +982,7 @@ static int dasd_eckd_read_features(struct dasd_device *device) features = (struct dasd_rssd_features *) (prssdp + 1); memcpy(&private->features, features, sizeof(struct dasd_rssd_features)); - } else - dev_warn(&device->cdev->dev, "Reading device feature codes" - " failed with rc=%d\n", rc); + } dasd_sfree_request(cqr, cqr->memdev); return rc; } @@ -1147,7 +1144,9 @@ dasd_eckd_check_characteristics(struct dasd_device *device) } /* Read Feature Codes */ - dasd_eckd_read_features(device); + rc = dasd_eckd_read_features(device); + if (rc) + goto out_err3; /* Read Device Characteristics */ rc = dasd_generic_read_dev_chars(device, DASD_ECKD_MAGIC, @@ -3242,7 +3241,9 @@ int dasd_eckd_restore_device(struct dasd_device *device) } /* Read Feature Codes */ - dasd_eckd_read_features(device); + rc = dasd_eckd_read_features(device); + if (rc) + goto out_err; /* Read Device Characteristics */ memset(&private->rdc_data, 0, sizeof(private->rdc_data)); diff --git a/trunk/drivers/s390/cio/css.c b/trunk/drivers/s390/cio/css.c index 91c25706fa83..393c73c47f87 100644 --- a/trunk/drivers/s390/cio/css.c +++ b/trunk/drivers/s390/cio/css.c @@ -31,7 +31,8 @@ #include "chp.h" int css_init_done = 0; -int max_ssid; +static int need_reprobe = 0; +static int max_ssid = 0; struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1]; @@ -314,18 +315,12 @@ int css_probe_device(struct subchannel_id schid) int ret; struct subchannel *sch; - if (cio_is_console(schid)) - sch = cio_get_console_subchannel(); - else { - sch = css_alloc_subchannel(schid); - if (IS_ERR(sch)) - return PTR_ERR(sch); - } + sch = css_alloc_subchannel(schid); + if (IS_ERR(sch)) + return PTR_ERR(sch); ret = css_register_subchannel(sch); - if (ret) { - if (!cio_is_console(schid)) - put_device(&sch->dev); - } + if (ret) + put_device(&sch->dev); return ret; } @@ -414,14 +409,10 @@ static void css_evaluate_subchannel(struct subchannel_id schid, int slow) static struct idset *slow_subchannel_set; static spinlock_t slow_subchannel_lock; -static wait_queue_head_t css_eval_wq; -static atomic_t css_eval_scheduled; static int __init slow_subchannel_init(void) { spin_lock_init(&slow_subchannel_lock); - atomic_set(&css_eval_scheduled, 0); - init_waitqueue_head(&css_eval_wq); slow_subchannel_set = idset_sch_new(); if (!slow_subchannel_set) { CIO_MSG_EVENT(0, "could not allocate slow subchannel set\n"); @@ -477,17 +468,9 @@ static int slow_eval_unknown_fn(struct subchannel_id schid, void *data) static void css_slow_path_func(struct work_struct *unused) { - unsigned long flags; - CIO_TRACE_EVENT(4, "slowpath"); for_each_subchannel_staged(slow_eval_known_fn, slow_eval_unknown_fn, NULL); - spin_lock_irqsave(&slow_subchannel_lock, flags); - if (idset_is_empty(slow_subchannel_set)) { - atomic_set(&css_eval_scheduled, 0); - wake_up(&css_eval_wq); - } - spin_unlock_irqrestore(&slow_subchannel_lock, flags); } static DECLARE_WORK(slow_path_work, css_slow_path_func); @@ -499,7 +482,6 @@ void css_schedule_eval(struct subchannel_id schid) spin_lock_irqsave(&slow_subchannel_lock, flags); idset_sch_add(slow_subchannel_set, schid); - atomic_set(&css_eval_scheduled, 1); queue_work(slow_path_wq, &slow_path_work); spin_unlock_irqrestore(&slow_subchannel_lock, flags); } @@ -510,53 +492,80 @@ void css_schedule_eval_all(void) spin_lock_irqsave(&slow_subchannel_lock, flags); idset_fill(slow_subchannel_set); - atomic_set(&css_eval_scheduled, 1); queue_work(slow_path_wq, &slow_path_work); spin_unlock_irqrestore(&slow_subchannel_lock, flags); } -static int __unset_registered(struct device *dev, void *data) +void css_wait_for_slow_path(void) { - struct idset *set = data; - struct subchannel *sch = to_subchannel(dev); - - idset_sch_del(set, sch->schid); - return 0; + flush_workqueue(slow_path_wq); } -void css_schedule_eval_all_unreg(void) +/* Reprobe subchannel if unregistered. */ +static int reprobe_subchannel(struct subchannel_id schid, void *data) { - unsigned long flags; - struct idset *unreg_set; + int ret; - /* Find unregistered subchannels. */ - unreg_set = idset_sch_new(); - if (!unreg_set) { - /* Fallback. */ - css_schedule_eval_all(); - return; + CIO_MSG_EVENT(6, "cio: reprobe 0.%x.%04x\n", + schid.ssid, schid.sch_no); + if (need_reprobe) + return -EAGAIN; + + ret = css_probe_device(schid); + switch (ret) { + case 0: + break; + case -ENXIO: + case -ENOMEM: + case -EIO: + /* These should abort looping */ + break; + default: + ret = 0; } - idset_fill(unreg_set); - bus_for_each_dev(&css_bus_type, NULL, unreg_set, __unset_registered); - /* Apply to slow_subchannel_set. */ - spin_lock_irqsave(&slow_subchannel_lock, flags); - idset_add_set(slow_subchannel_set, unreg_set); - atomic_set(&css_eval_scheduled, 1); - queue_work(slow_path_wq, &slow_path_work); - spin_unlock_irqrestore(&slow_subchannel_lock, flags); - idset_free(unreg_set); + + return ret; } -void css_wait_for_slow_path(void) +static void reprobe_after_idle(struct work_struct *unused) { - flush_workqueue(slow_path_wq); + /* Make sure initial subchannel scan is done. */ + wait_event(ccw_device_init_wq, + atomic_read(&ccw_device_init_count) == 0); + if (need_reprobe) + css_schedule_reprobe(); +} + +static DECLARE_WORK(reprobe_idle_work, reprobe_after_idle); + +/* Work function used to reprobe all unregistered subchannels. */ +static void reprobe_all(struct work_struct *unused) +{ + int ret; + + CIO_MSG_EVENT(4, "reprobe start\n"); + + /* Make sure initial subchannel scan is done. */ + if (atomic_read(&ccw_device_init_count) != 0) { + queue_work(ccw_device_work, &reprobe_idle_work); + return; + } + need_reprobe = 0; + ret = for_each_subchannel_staged(NULL, reprobe_subchannel, NULL); + + CIO_MSG_EVENT(4, "reprobe done (rc=%d, need_reprobe=%d)\n", ret, + need_reprobe); } +static DECLARE_WORK(css_reprobe_work, reprobe_all); + /* Schedule reprobing of all unregistered subchannels. */ void css_schedule_reprobe(void) { - css_schedule_eval_all_unreg(); + need_reprobe = 1; + queue_work(slow_path_wq, &css_reprobe_work); } + EXPORT_SYMBOL_GPL(css_schedule_reprobe); /* @@ -592,6 +601,49 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) css_evaluate_subchannel(mchk_schid, 0); } +static int __init +__init_channel_subsystem(struct subchannel_id schid, void *data) +{ + struct subchannel *sch; + int ret; + + if (cio_is_console(schid)) + sch = cio_get_console_subchannel(); + else { + sch = css_alloc_subchannel(schid); + if (IS_ERR(sch)) + ret = PTR_ERR(sch); + else + ret = 0; + switch (ret) { + case 0: + break; + case -ENOMEM: + panic("Out of memory in init_channel_subsystem\n"); + /* -ENXIO: no more subchannels. */ + case -ENXIO: + return ret; + /* -EIO: this subchannel set not supported. */ + case -EIO: + return ret; + default: + return 0; + } + } + /* + * We register ALL valid subchannels in ioinfo, even those + * that have been present before init_channel_subsystem. + * These subchannels can't have been registered yet (kmalloc + * not working) so we do it now. This is true e.g. for the + * console subchannel. + */ + if (css_register_subchannel(sch)) { + if (!cio_is_console(schid)) + put_device(&sch->dev); + } + return 0; +} + static void __init css_generate_pgid(struct channel_subsystem *css, u32 tod_high) { @@ -802,30 +854,19 @@ static struct notifier_block css_power_notifier = { * The struct subchannel's are created during probing (except for the * static console subchannel). */ -static int __init css_bus_init(void) +static int __init +init_channel_subsystem (void) { int ret, i; ret = chsc_determine_css_characteristics(); if (ret == -ENOMEM) - goto out; + goto out; /* No need to continue. */ ret = chsc_alloc_sei_area(); if (ret) goto out; - /* Try to enable MSS. */ - ret = chsc_enable_facility(CHSC_SDA_OC_MSS); - switch (ret) { - case 0: /* Success. */ - max_ssid = __MAX_SSID; - break; - case -ENOMEM: - goto out; - default: - max_ssid = 0; - } - ret = slow_subchannel_init(); if (ret) goto out; @@ -837,6 +878,17 @@ static int __init css_bus_init(void) if ((ret = bus_register(&css_bus_type))) goto out; + /* Try to enable MSS. */ + ret = chsc_enable_facility(CHSC_SDA_OC_MSS); + switch (ret) { + case 0: /* Success. */ + max_ssid = __MAX_SSID; + break; + case -ENOMEM: + goto out_bus; + default: + max_ssid = 0; + } /* Setup css structure. */ for (i = 0; i <= __MAX_CSSID; i++) { struct channel_subsystem *css; @@ -882,6 +934,7 @@ static int __init css_bus_init(void) /* Enable default isc for I/O subchannels. */ isc_register(IO_SCH_ISC); + for_each_subchannel(__init_channel_subsystem, NULL); return 0; out_file: if (css_chsc_characteristics.secm) @@ -902,76 +955,17 @@ static int __init css_bus_init(void) &dev_attr_cm_enable); device_unregister(&css->device); } +out_bus: bus_unregister(&css_bus_type); out: crw_unregister_handler(CRW_RSC_CSS); chsc_free_sei_area(); - idset_free(slow_subchannel_set); + kfree(slow_subchannel_set); pr_alert("The CSS device driver initialization failed with " "errno=%d\n", ret); return ret; } -static void __init css_bus_cleanup(void) -{ - struct channel_subsystem *css; - int i; - - for (i = 0; i <= __MAX_CSSID; i++) { - css = channel_subsystems[i]; - device_unregister(&css->pseudo_subchannel->dev); - css->pseudo_subchannel = NULL; - if (css_chsc_characteristics.secm) - device_remove_file(&css->device, &dev_attr_cm_enable); - device_unregister(&css->device); - } - bus_unregister(&css_bus_type); - crw_unregister_handler(CRW_RSC_CSS); - chsc_free_sei_area(); - idset_free(slow_subchannel_set); - isc_unregister(IO_SCH_ISC); -} - -static int __init channel_subsystem_init(void) -{ - int ret; - - ret = css_bus_init(); - if (ret) - return ret; - - ret = io_subchannel_init(); - if (ret) - css_bus_cleanup(); - - return ret; -} -subsys_initcall(channel_subsystem_init); - -static int css_settle(struct device_driver *drv, void *unused) -{ - struct css_driver *cssdrv = to_cssdriver(drv); - - if (cssdrv->settle) - cssdrv->settle(); - return 0; -} - -/* - * Wait for the initialization of devices to finish, to make sure we are - * done with our setup if the search for the root device starts. - */ -static int __init channel_subsystem_init_sync(void) -{ - /* Start initial subchannel evaluation. */ - css_schedule_eval_all(); - /* Wait for the evaluation of subchannels to finish. */ - wait_event(css_eval_wq, atomic_read(&css_eval_scheduled) == 0); - /* Wait for the subchannel type specific initialization to finish */ - return bus_for_each_drv(&css_bus_type, NULL, NULL, css_settle); -} -subsys_initcall_sync(channel_subsystem_init_sync); - int sch_is_pseudo_sch(struct subchannel *sch) { return sch == to_css(sch->dev.parent)->pseudo_subchannel; @@ -1141,5 +1135,7 @@ void css_driver_unregister(struct css_driver *cdrv) } EXPORT_SYMBOL_GPL(css_driver_unregister); +subsys_initcall(init_channel_subsystem); + MODULE_LICENSE("GPL"); EXPORT_SYMBOL(css_bus_type); diff --git a/trunk/drivers/s390/cio/css.h b/trunk/drivers/s390/cio/css.h index 68d6b0bf151c..9763eeec7458 100644 --- a/trunk/drivers/s390/cio/css.h +++ b/trunk/drivers/s390/cio/css.h @@ -75,7 +75,6 @@ struct chp_link; * @freeze: callback for freezing during hibernation snapshotting * @thaw: undo work done in @freeze * @restore: callback for restoring after hibernation - * @settle: wait for asynchronous work to finish * @name: name of the device driver */ struct css_driver { @@ -93,7 +92,6 @@ struct css_driver { int (*freeze)(struct subchannel *); int (*thaw) (struct subchannel *); int (*restore)(struct subchannel *); - void (*settle)(void); const char *name; }; @@ -111,7 +109,6 @@ extern void css_sch_device_unregister(struct subchannel *); extern int css_probe_device(struct subchannel_id); extern struct subchannel *get_subchannel_by_schid(struct subchannel_id); extern int css_init_done; -extern int max_ssid; int for_each_subchannel_staged(int (*fn_known)(struct subchannel *, void *), int (*fn_unknown)(struct subchannel_id, void *), void *data); diff --git a/trunk/drivers/s390/cio/device.c b/trunk/drivers/s390/cio/device.c index f780bdd3a04e..6527f3f34493 100644 --- a/trunk/drivers/s390/cio/device.c +++ b/trunk/drivers/s390/cio/device.c @@ -131,10 +131,6 @@ static void io_subchannel_shutdown(struct subchannel *); static int io_subchannel_sch_event(struct subchannel *, int); static int io_subchannel_chp_event(struct subchannel *, struct chp_link *, int); -static void recovery_func(unsigned long data); -struct workqueue_struct *ccw_device_work; -wait_queue_head_t ccw_device_init_wq; -atomic_t ccw_device_init_count; static struct css_device_id io_subchannel_ids[] = { { .match_flags = 0x1, .type = SUBCHANNEL_TYPE_IO, }, @@ -155,13 +151,6 @@ static int io_subchannel_prepare(struct subchannel *sch) return 0; } -static void io_subchannel_settle(void) -{ - wait_event(ccw_device_init_wq, - atomic_read(&ccw_device_init_count) == 0); - flush_workqueue(ccw_device_work); -} - static struct css_driver io_subchannel_driver = { .owner = THIS_MODULE, .subchannel_type = io_subchannel_ids, @@ -173,10 +162,16 @@ static struct css_driver io_subchannel_driver = { .remove = io_subchannel_remove, .shutdown = io_subchannel_shutdown, .prepare = io_subchannel_prepare, - .settle = io_subchannel_settle, }; -int __init io_subchannel_init(void) +struct workqueue_struct *ccw_device_work; +wait_queue_head_t ccw_device_init_wq; +atomic_t ccw_device_init_count; + +static void recovery_func(unsigned long data); + +static int __init +init_ccw_bus_type (void) { int ret; @@ -186,10 +181,10 @@ int __init io_subchannel_init(void) ccw_device_work = create_singlethread_workqueue("cio"); if (!ccw_device_work) - return -ENOMEM; + return -ENOMEM; /* FIXME: better errno ? */ slow_path_wq = create_singlethread_workqueue("kslowcrw"); if (!slow_path_wq) { - ret = -ENOMEM; + ret = -ENOMEM; /* FIXME: better errno ? */ goto out_err; } if ((ret = bus_register (&ccw_bus_type))) @@ -199,6 +194,9 @@ int __init io_subchannel_init(void) if (ret) goto out_err; + wait_event(ccw_device_init_wq, + atomic_read(&ccw_device_init_count) == 0); + flush_workqueue(ccw_device_work); return 0; out_err: if (ccw_device_work) @@ -208,6 +206,16 @@ int __init io_subchannel_init(void) return ret; } +static void __exit +cleanup_ccw_bus_type (void) +{ + css_driver_unregister(&io_subchannel_driver); + bus_unregister(&ccw_bus_type); + destroy_workqueue(ccw_device_work); +} + +subsys_initcall(init_ccw_bus_type); +module_exit(cleanup_ccw_bus_type); /************************ device handling **************************/ diff --git a/trunk/drivers/s390/cio/device.h b/trunk/drivers/s390/cio/device.h index ed39a2caaf47..e3975107a578 100644 --- a/trunk/drivers/s390/cio/device.h +++ b/trunk/drivers/s390/cio/device.h @@ -74,7 +74,6 @@ dev_fsm_final_state(struct ccw_device *cdev) extern struct workqueue_struct *ccw_device_work; extern wait_queue_head_t ccw_device_init_wq; extern atomic_t ccw_device_init_count; -int __init io_subchannel_init(void); void io_subchannel_recog_done(struct ccw_device *cdev); void io_subchannel_init_config(struct subchannel *sch); diff --git a/trunk/drivers/s390/cio/idset.c b/trunk/drivers/s390/cio/idset.c index 4d10981c7cc1..cf8f24a4b5eb 100644 --- a/trunk/drivers/s390/cio/idset.c +++ b/trunk/drivers/s390/cio/idset.c @@ -78,7 +78,7 @@ static inline int idset_get_first(struct idset *set, int *ssid, int *id) struct idset *idset_sch_new(void) { - return idset_new(max_ssid + 1, __MAX_SUBCHANNEL + 1); + return idset_new(__MAX_SSID + 1, __MAX_SUBCHANNEL + 1); } void idset_sch_add(struct idset *set, struct subchannel_id schid) @@ -110,23 +110,3 @@ int idset_sch_get_first(struct idset *set, struct subchannel_id *schid) } return rc; } - -int idset_is_empty(struct idset *set) -{ - int bitnum; - - bitnum = find_first_bit(set->bitmap, set->num_ssid * set->num_id); - if (bitnum >= set->num_ssid * set->num_id) - return 1; - return 0; -} - -void idset_add_set(struct idset *to, struct idset *from) -{ - unsigned long i, len; - - len = min(__BITOPS_WORDS(to->num_ssid * to->num_id), - __BITOPS_WORDS(from->num_ssid * from->num_id)); - for (i = 0; i < len ; i++) - to->bitmap[i] |= from->bitmap[i]; -} diff --git a/trunk/drivers/s390/cio/idset.h b/trunk/drivers/s390/cio/idset.h index 7543da4529f9..528065cb5021 100644 --- a/trunk/drivers/s390/cio/idset.h +++ b/trunk/drivers/s390/cio/idset.h @@ -21,7 +21,5 @@ void idset_sch_add(struct idset *set, struct subchannel_id id); void idset_sch_del(struct idset *set, struct subchannel_id id); int idset_sch_contains(struct idset *set, struct subchannel_id id); int idset_sch_get_first(struct idset *set, struct subchannel_id *id); -int idset_is_empty(struct idset *set); -void idset_add_set(struct idset *to, struct idset *from); #endif /* S390_IDSET_H */ diff --git a/trunk/drivers/s390/cio/qdio_main.c b/trunk/drivers/s390/cio/qdio_main.c index 4be6e84b9599..9aef402a5f1b 100644 --- a/trunk/drivers/s390/cio/qdio_main.c +++ b/trunk/drivers/s390/cio/qdio_main.c @@ -401,7 +401,7 @@ static void announce_buffer_error(struct qdio_q *q, int count) if ((!q->is_input_q && (q->sbal[q->first_to_check]->element[15].flags & 0xff) == 0x10)) { qdio_perf_stat_inc(&perf_stats.outbound_target_full); - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%02x", + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "OUTFULL FTC:%3d", q->first_to_check); return; } @@ -418,7 +418,7 @@ static inline void inbound_primed(struct qdio_q *q, int count) { int new; - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %02x", count); + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in prim: %3d", count); /* for QEBSM the ACK was already set by EQBS */ if (is_qebsm(q)) { @@ -455,8 +455,6 @@ static inline void inbound_primed(struct qdio_q *q, int count) count--; if (!count) return; - /* need to change ALL buffers to get more interrupts */ - set_buf_states(q, q->first_to_check, SLSB_P_INPUT_NOT_INIT, count); } static int get_inbound_buffer_frontier(struct qdio_q *q) @@ -547,7 +545,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) * has (probably) not moved (see qdio_inbound_processing). */ if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%3d", q->first_to_check); return 1; } else @@ -567,10 +565,11 @@ static void qdio_kick_handler(struct qdio_q *q) if (q->is_input_q) { qdio_perf_stat_inc(&perf_stats.inbound_handler); - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%02x c:%02x", start, count); - } else - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: s:%02x c:%02x", - start, count); + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "kih s:%3d c:%3d", start, count); + } else { + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "koh: nr:%1d", q->nr); + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "s:%3d c:%3d", start, count); + } q->handler(q->irq_ptr->cdev, q->qdio_error, q->nr, start, count, q->irq_ptr->int_parm); @@ -634,7 +633,7 @@ static int get_outbound_buffer_frontier(struct qdio_q *q) switch (state) { case SLSB_P_OUTPUT_EMPTY: /* the adapter got it */ - DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %02x", q->nr, count); + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "out empty:%1d %3d", q->nr, count); atomic_sub(count, &q->nr_buf_used); q->first_to_check = add_buf(q->first_to_check, count); @@ -1482,9 +1481,10 @@ static int handle_outbound(struct qdio_q *q, unsigned int callflags, get_buf_state(q, prev_buf(bufnr), &state, 0); if (state != SLSB_CU_OUTPUT_PRIMED) rc = qdio_kick_outbound_q(q); - else + else { + DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "fast-req"); qdio_perf_stat_inc(&perf_stats.fast_requeue); - + } out: tasklet_schedule(&q->tasklet); return rc; @@ -1510,8 +1510,12 @@ int do_QDIO(struct ccw_device *cdev, unsigned int callflags, if (!irq_ptr) return -ENODEV; - DBF_DEV_EVENT(DBF_INFO, irq_ptr, - "do%02x b:%02x c:%02x", callflags, bufnr, count); + if (callflags & QDIO_FLAG_SYNC_INPUT) + DBF_DEV_EVENT(DBF_INFO, irq_ptr, "doQDIO input"); + else + DBF_DEV_EVENT(DBF_INFO, irq_ptr, "doQDIO output"); + DBF_DEV_EVENT(DBF_INFO, irq_ptr, "q:%1d flag:%4x", q_nr, callflags); + DBF_DEV_EVENT(DBF_INFO, irq_ptr, "buf:%2d cnt:%3d", bufnr, count); if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE) return -EBUSY; diff --git a/trunk/drivers/s390/crypto/ap_bus.c b/trunk/drivers/s390/crypto/ap_bus.c index 1294876bf7b4..090b32a339c6 100644 --- a/trunk/drivers/s390/crypto/ap_bus.c +++ b/trunk/drivers/s390/crypto/ap_bus.c @@ -60,7 +60,6 @@ static int ap_device_probe(struct device *dev); static void ap_interrupt_handler(void *unused1, void *unused2); static void ap_reset(struct ap_device *ap_dev); static void ap_config_timeout(unsigned long ptr); -static int ap_select_domain(void); /* * Module description. @@ -110,10 +109,6 @@ static unsigned long long poll_timeout = 250000; /* Suspend flag */ static int ap_suspend_flag; -/* Flag to check if domain was set through module parameter domain=. This is - * important when supsend and resume is done in a z/VM environment where the - * domain might change. */ -static int user_set_domain = 0; static struct bus_type ap_bus_type; /** @@ -648,7 +643,6 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state) destroy_workqueue(ap_work_queue); ap_work_queue = NULL; } - tasklet_disable(&ap_tasklet); } /* Poll on the device until all requests are finished. */ @@ -659,10 +653,7 @@ static int ap_bus_suspend(struct device *dev, pm_message_t state) spin_unlock_bh(&ap_dev->lock); } while ((flags & 1) || (flags & 2)); - spin_lock_bh(&ap_dev->lock); - ap_dev->unregistered = 1; - spin_unlock_bh(&ap_dev->lock); - + ap_device_remove(dev); return 0; } @@ -675,10 +666,11 @@ static int ap_bus_resume(struct device *dev) ap_suspend_flag = 0; if (!ap_interrupts_available()) ap_interrupt_indicator = NULL; - if (!user_set_domain) { - ap_domain_index = -1; - ap_select_domain(); - } + ap_device_probe(dev); + ap_reset(ap_dev); + setup_timer(&ap_dev->timeout, ap_request_timeout, + (unsigned long) ap_dev); + ap_scan_bus(NULL); init_timer(&ap_config_timer); ap_config_timer.function = ap_config_timeout; ap_config_timer.data = 0; @@ -694,14 +686,12 @@ static int ap_bus_resume(struct device *dev) tasklet_schedule(&ap_tasklet); if (ap_thread_flag) rc = ap_poll_thread_start(); + } else { + ap_device_probe(dev); + ap_reset(ap_dev); + setup_timer(&ap_dev->timeout, ap_request_timeout, + (unsigned long) ap_dev); } - if (AP_QID_QUEUE(ap_dev->qid) != ap_domain_index) { - spin_lock_bh(&ap_dev->lock); - ap_dev->qid = AP_MKQID(AP_QID_DEVICE(ap_dev->qid), - ap_domain_index); - spin_unlock_bh(&ap_dev->lock); - } - queue_work(ap_work_queue, &ap_config_work); return rc; } @@ -1089,8 +1079,6 @@ static void ap_scan_bus(struct work_struct *unused) spin_lock_bh(&ap_dev->lock); if (rc || ap_dev->unregistered) { spin_unlock_bh(&ap_dev->lock); - if (ap_dev->unregistered) - i--; device_unregister(dev); put_device(dev); continue; @@ -1598,12 +1586,6 @@ int __init ap_module_init(void) ap_domain_index); return -EINVAL; } - /* In resume callback we need to know if the user had set the domain. - * If so, we can not just reset it. - */ - if (ap_domain_index >= 0) - user_set_domain = 1; - if (ap_instructions_available() != 0) { pr_warning("The hardware system does not support " "AP instructions\n"); diff --git a/trunk/drivers/scsi/sg.c b/trunk/drivers/scsi/sg.c index 848b59466850..4968c4ced385 100644 --- a/trunk/drivers/scsi/sg.c +++ b/trunk/drivers/scsi/sg.c @@ -2233,7 +2233,7 @@ static struct file_operations dev_fops = { .open = sg_proc_open_dev, .release = seq_release, }; -static const struct seq_operations dev_seq_ops = { +static struct seq_operations dev_seq_ops = { .start = dev_seq_start, .next = dev_seq_next, .stop = dev_seq_stop, @@ -2246,7 +2246,7 @@ static struct file_operations devstrs_fops = { .open = sg_proc_open_devstrs, .release = seq_release, }; -static const struct seq_operations devstrs_seq_ops = { +static struct seq_operations devstrs_seq_ops = { .start = dev_seq_start, .next = dev_seq_next, .stop = dev_seq_stop, @@ -2259,7 +2259,7 @@ static struct file_operations debug_fops = { .open = sg_proc_open_debug, .release = seq_release, }; -static const struct seq_operations debug_seq_ops = { +static struct seq_operations debug_seq_ops = { .start = dev_seq_start, .next = dev_seq_next, .stop = dev_seq_stop, diff --git a/trunk/drivers/serial/max3100.c b/trunk/drivers/serial/max3100.c index 3c30c56aa2e1..75ab00631c41 100644 --- a/trunk/drivers/serial/max3100.c +++ b/trunk/drivers/serial/max3100.c @@ -925,4 +925,3 @@ module_exit(max3100_exit); MODULE_DESCRIPTION("MAX3100 driver"); MODULE_AUTHOR("Christian Pellegrin "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:max3100"); diff --git a/trunk/drivers/sfi/Kconfig b/trunk/drivers/sfi/Kconfig deleted file mode 100644 index dd115121e0b6..000000000000 --- a/trunk/drivers/sfi/Kconfig +++ /dev/null @@ -1,17 +0,0 @@ -# -# SFI Configuration -# - -menuconfig SFI - bool "SFI (Simple Firmware Interface) Support" - ---help--- - The Simple Firmware Interface (SFI) provides a lightweight method - for platform firmware to pass information to the operating system - via static tables in memory. Kernel SFI support is required to - boot on SFI-only platforms. Currently, all SFI-only platforms are - based on the 2nd generation Intel Atom processor platform, - code-named Moorestown. - - For more information, see http://simplefirmware.org - - Say 'Y' here to enable the kernel to boot on SFI-only platforms. diff --git a/trunk/drivers/sfi/Makefile b/trunk/drivers/sfi/Makefile deleted file mode 100644 index 2343732aefeb..000000000000 --- a/trunk/drivers/sfi/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -obj-y += sfi_acpi.o -obj-y += sfi_core.o - diff --git a/trunk/drivers/sfi/sfi_acpi.c b/trunk/drivers/sfi/sfi_acpi.c deleted file mode 100644 index 34aba30eb84b..000000000000 --- a/trunk/drivers/sfi/sfi_acpi.c +++ /dev/null @@ -1,175 +0,0 @@ -/* sfi_acpi.c Simple Firmware Interface - ACPI extensions */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#define KMSG_COMPONENT "SFI" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include - -#include -#include "sfi_core.h" - -/* - * SFI can access ACPI-defined tables via an optional ACPI XSDT. - * - * This allows re-use, and avoids re-definition, of standard tables. - * For example, the "MCFG" table is defined by PCI, reserved by ACPI, - * and is expected to be present many SFI-only systems. - */ - -static struct acpi_table_xsdt *xsdt_va __read_mostly; - -#define XSDT_GET_NUM_ENTRIES(ptable, entry_type) \ - ((ptable->header.length - sizeof(struct acpi_table_header)) / \ - (sizeof(entry_type))) - -static inline struct sfi_table_header *acpi_to_sfi_th( - struct acpi_table_header *th) -{ - return (struct sfi_table_header *)th; -} - -static inline struct acpi_table_header *sfi_to_acpi_th( - struct sfi_table_header *th) -{ - return (struct acpi_table_header *)th; -} - -/* - * sfi_acpi_parse_xsdt() - * - * Parse the ACPI XSDT for later access by sfi_acpi_table_parse(). - */ -static int __init sfi_acpi_parse_xsdt(struct sfi_table_header *th) -{ - struct sfi_table_key key = SFI_ANY_KEY; - int tbl_cnt, i; - void *ret; - - xsdt_va = (struct acpi_table_xsdt *)th; - tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); - for (i = 0; i < tbl_cnt; i++) { - ret = sfi_check_table(xsdt_va->table_offset_entry[i], &key); - if (IS_ERR(ret)) { - disable_sfi(); - return -1; - } - } - - return 0; -} - -int __init sfi_acpi_init(void) -{ - struct sfi_table_key xsdt_key = { .sig = SFI_SIG_XSDT }; - - sfi_table_parse(SFI_SIG_XSDT, NULL, NULL, sfi_acpi_parse_xsdt); - - /* Only call the get_table to keep the table mapped */ - xsdt_va = (struct acpi_table_xsdt *)sfi_get_table(&xsdt_key); - return 0; -} - -static struct acpi_table_header *sfi_acpi_get_table(struct sfi_table_key *key) -{ - u32 tbl_cnt, i; - void *ret; - - tbl_cnt = XSDT_GET_NUM_ENTRIES(xsdt_va, u64); - for (i = 0; i < tbl_cnt; i++) { - ret = sfi_check_table(xsdt_va->table_offset_entry[i], key); - if (!IS_ERR(ret) && ret) - return sfi_to_acpi_th(ret); - } - - return NULL; -} - -static void sfi_acpi_put_table(struct acpi_table_header *table) -{ - sfi_put_table(acpi_to_sfi_th(table)); -} - -/* - * sfi_acpi_table_parse() - * - * Find specified table in XSDT, run handler on it and return its return value - */ -int sfi_acpi_table_parse(char *signature, char *oem_id, char *oem_table_id, - int(*handler)(struct acpi_table_header *)) -{ - struct acpi_table_header *table = NULL; - struct sfi_table_key key; - int ret = 0; - - if (sfi_disabled) - return -1; - - key.sig = signature; - key.oem_id = oem_id; - key.oem_table_id = oem_table_id; - - table = sfi_acpi_get_table(&key); - if (!table) - return -EINVAL; - - ret = handler(table); - sfi_acpi_put_table(table); - return ret; -} diff --git a/trunk/drivers/sfi/sfi_core.c b/trunk/drivers/sfi/sfi_core.c deleted file mode 100644 index d3b496800477..000000000000 --- a/trunk/drivers/sfi/sfi_core.c +++ /dev/null @@ -1,407 +0,0 @@ -/* sfi_core.c Simple Firmware Interface - core internals */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ - -#define KMSG_COMPONENT "SFI" -#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "sfi_core.h" - -#define ON_SAME_PAGE(addr1, addr2) \ - (((unsigned long)(addr1) & PAGE_MASK) == \ - ((unsigned long)(addr2) & PAGE_MASK)) -#define TABLE_ON_PAGE(page, table, size) (ON_SAME_PAGE(page, table) && \ - ON_SAME_PAGE(page, table + size)) - -int sfi_disabled __read_mostly; -EXPORT_SYMBOL(sfi_disabled); - -static u64 syst_pa __read_mostly; -static struct sfi_table_simple *syst_va __read_mostly; - -/* - * FW creates and saves the SFI tables in memory. When these tables get - * used, they may need to be mapped to virtual address space, and the mapping - * can happen before or after the ioremap() is ready, so a flag is needed - * to indicating this - */ -static u32 sfi_use_ioremap __read_mostly; - -static void __iomem *sfi_map_memory(u64 phys, u32 size) -{ - if (!phys || !size) - return NULL; - - if (sfi_use_ioremap) - return ioremap(phys, size); - else - return early_ioremap(phys, size); -} - -static void sfi_unmap_memory(void __iomem *virt, u32 size) -{ - if (!virt || !size) - return; - - if (sfi_use_ioremap) - iounmap(virt); - else - early_iounmap(virt, size); -} - -static void sfi_print_table_header(unsigned long long pa, - struct sfi_table_header *header) -{ - pr_info("%4.4s %llX, %04X (v%d %6.6s %8.8s)\n", - header->sig, pa, - header->len, header->rev, header->oem_id, - header->oem_table_id); -} - -/* - * sfi_verify_table() - * Sanity check table lengh, calculate checksum - */ -static __init int sfi_verify_table(struct sfi_table_header *table) -{ - - u8 checksum = 0; - u8 *puchar = (u8 *)table; - u32 length = table->len; - - /* Sanity check table length against arbitrary 1MB limit */ - if (length > 0x100000) { - pr_err("Invalid table length 0x%x\n", length); - return -1; - } - - while (length--) - checksum += *puchar++; - - if (checksum) { - pr_err("Checksum %2.2X should be %2.2X\n", - table->csum, table->csum - checksum); - return -1; - } - return 0; -} - -/* - * sfi_map_table() - * - * Return address of mapped table - * Check for common case that we can re-use mapping to SYST, - * which requires syst_pa, syst_va to be initialized. - */ -struct sfi_table_header *sfi_map_table(u64 pa) -{ - struct sfi_table_header *th; - u32 length; - - if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) - th = sfi_map_memory(pa, sizeof(struct sfi_table_header)); - else - th = (void *)syst_va + (pa - syst_pa); - - /* If table fits on same page as its header, we are done */ - if (TABLE_ON_PAGE(th, th, th->len)) - return th; - - /* Entire table does not fit on same page as SYST */ - length = th->len; - if (!TABLE_ON_PAGE(syst_pa, pa, sizeof(struct sfi_table_header))) - sfi_unmap_memory(th, sizeof(struct sfi_table_header)); - - return sfi_map_memory(pa, length); -} - -/* - * sfi_unmap_table() - * - * Undoes effect of sfi_map_table() by unmapping table - * if it did not completely fit on same page as SYST. - */ -void sfi_unmap_table(struct sfi_table_header *th) -{ - if (!TABLE_ON_PAGE(syst_va, th, th->len)) - sfi_unmap_memory(th, TABLE_ON_PAGE(th, th, th->len) ? - sizeof(*th) : th->len); -} - -static int sfi_table_check_key(struct sfi_table_header *th, - struct sfi_table_key *key) -{ - - if (strncmp(th->sig, key->sig, SFI_SIGNATURE_SIZE) - || (key->oem_id && strncmp(th->oem_id, - key->oem_id, SFI_OEM_ID_SIZE)) - || (key->oem_table_id && strncmp(th->oem_table_id, - key->oem_table_id, SFI_OEM_TABLE_ID_SIZE))) - return -1; - - return 0; -} - -/* - * This function will be used in 2 cases: - * 1. used to enumerate and verify the tables addressed by SYST/XSDT, - * thus no signature will be given (in kernel boot phase) - * 2. used to parse one specific table, signature must exist, and - * the mapped virt address will be returned, and the virt space - * will be released by call sfi_put_table() later - * - * Return value: - * NULL: when can't find a table matching the key - * ERR_PTR(error): error value - * virt table address: when a matched table is found - */ -struct sfi_table_header *sfi_check_table(u64 pa, struct sfi_table_key *key) -{ - struct sfi_table_header *th; - void *ret = NULL; - - th = sfi_map_table(pa); - if (!th) - return ERR_PTR(-ENOMEM); - - if (!key->sig) { - sfi_print_table_header(pa, th); - if (sfi_verify_table(th)) - ret = ERR_PTR(-EINVAL); - } else { - if (!sfi_table_check_key(th, key)) - return th; /* Success */ - } - - sfi_unmap_table(th); - return ret; -} - -/* - * sfi_get_table() - * - * Search SYST for the specified table with the signature in - * the key, and return the mapped table - */ -struct sfi_table_header *sfi_get_table(struct sfi_table_key *key) -{ - struct sfi_table_header *th; - u32 tbl_cnt, i; - - tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); - for (i = 0; i < tbl_cnt; i++) { - th = sfi_check_table(syst_va->pentry[i], key); - if (!IS_ERR(th) && th) - return th; - } - - return NULL; -} - -void sfi_put_table(struct sfi_table_header *th) -{ - sfi_unmap_table(th); -} - -/* Find table with signature, run handler on it */ -int sfi_table_parse(char *signature, char *oem_id, char *oem_table_id, - sfi_table_handler handler) -{ - struct sfi_table_header *table = NULL; - struct sfi_table_key key; - int ret = -EINVAL; - - if (sfi_disabled || !handler || !signature) - goto exit; - - key.sig = signature; - key.oem_id = oem_id; - key.oem_table_id = oem_table_id; - - table = sfi_get_table(&key); - if (!table) - goto exit; - - ret = handler(table); - sfi_put_table(table); -exit: - return ret; -} -EXPORT_SYMBOL_GPL(sfi_table_parse); - -/* - * sfi_parse_syst() - * Checksum all the tables in SYST and print their headers - * - * success: set syst_va, return 0 - */ -static int __init sfi_parse_syst(void) -{ - struct sfi_table_key key = SFI_ANY_KEY; - int tbl_cnt, i; - void *ret; - - syst_va = sfi_map_memory(syst_pa, sizeof(struct sfi_table_simple)); - if (!syst_va) - return -ENOMEM; - - tbl_cnt = SFI_GET_NUM_ENTRIES(syst_va, u64); - for (i = 0; i < tbl_cnt; i++) { - ret = sfi_check_table(syst_va->pentry[i], &key); - if (IS_ERR(ret)) - return PTR_ERR(ret); - } - - return 0; -} - -/* - * The OS finds the System Table by searching 16-byte boundaries between - * physical address 0x000E0000 and 0x000FFFFF. The OS shall search this region - * starting at the low address and shall stop searching when the 1st valid SFI - * System Table is found. - * - * success: set syst_pa, return 0 - * fail: return -1 - */ -static __init int sfi_find_syst(void) -{ - unsigned long offset, len; - void *start; - - len = SFI_SYST_SEARCH_END - SFI_SYST_SEARCH_BEGIN; - start = sfi_map_memory(SFI_SYST_SEARCH_BEGIN, len); - if (!start) - return -1; - - for (offset = 0; offset < len; offset += 16) { - struct sfi_table_header *syst_hdr; - - syst_hdr = start + offset; - if (strncmp(syst_hdr->sig, SFI_SIG_SYST, - SFI_SIGNATURE_SIZE)) - continue; - - if (syst_hdr->len > PAGE_SIZE) - continue; - - sfi_print_table_header(SFI_SYST_SEARCH_BEGIN + offset, - syst_hdr); - - if (sfi_verify_table(syst_hdr)) - continue; - - /* - * Enforce SFI spec mandate that SYST reside within a page. - */ - if (!ON_SAME_PAGE(syst_pa, syst_pa + syst_hdr->len)) { - pr_info("SYST 0x%llx + 0x%x crosses page\n", - syst_pa, syst_hdr->len); - continue; - } - - /* Success */ - syst_pa = SFI_SYST_SEARCH_BEGIN + offset; - sfi_unmap_memory(start, len); - return 0; - } - - sfi_unmap_memory(start, len); - return -1; -} - -void __init sfi_init(void) -{ - if (!acpi_disabled) - disable_sfi(); - - if (sfi_disabled) - return; - - pr_info("Simple Firmware Interface v0.7 http://simplefirmware.org\n"); - - if (sfi_find_syst() || sfi_parse_syst() || sfi_platform_init()) - disable_sfi(); - - return; -} - -void __init sfi_init_late(void) -{ - int length; - - if (sfi_disabled) - return; - - length = syst_va->header.len; - sfi_unmap_memory(syst_va, sizeof(struct sfi_table_simple)); - - /* Use ioremap now after it is ready */ - sfi_use_ioremap = 1; - syst_va = sfi_map_memory(syst_pa, length); - - sfi_acpi_init(); -} diff --git a/trunk/drivers/sfi/sfi_core.h b/trunk/drivers/sfi/sfi_core.h deleted file mode 100644 index da82d39e104d..000000000000 --- a/trunk/drivers/sfi/sfi_core.h +++ /dev/null @@ -1,70 +0,0 @@ -/* sfi_core.h Simple Firmware Interface, internal header */ - -/* - - This file is provided under a dual BSD/GPLv2 license. When using or - redistributing this file, you may do so under either license. - - GPL LICENSE SUMMARY - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - This program is free software; you can redistribute it and/or modify - it under the terms of version 2 of the GNU General Public License as - published by the Free Software Foundation. - - This program is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - The full GNU General Public License is included in this distribution - in the file called LICENSE.GPL. - - BSD LICENSE - - Copyright(c) 2009 Intel Corporation. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions - are met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name of Intel Corporation nor the names of its - contributors may be used to endorse or promote products derived - from this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -*/ -struct sfi_table_key{ - char *sig; - char *oem_id; - char *oem_table_id; -}; - -#define SFI_ANY_KEY { .sig = NULL, .oem_id = NULL, .oem_table_id = NULL } - -extern int __init sfi_acpi_init(void); -extern struct sfi_table_header *sfi_check_table(u64 paddr, - struct sfi_table_key *key); -struct sfi_table_header *sfi_get_table(struct sfi_table_key *key); -extern void sfi_put_table(struct sfi_table_header *table); diff --git a/trunk/drivers/spi/Kconfig b/trunk/drivers/spi/Kconfig index 4b6f7cba3b3d..2c733c27db2f 100644 --- a/trunk/drivers/spi/Kconfig +++ b/trunk/drivers/spi/Kconfig @@ -117,11 +117,10 @@ config SPI_GPIO speed with a custom version of this driver; see the source code. config SPI_IMX - tristate "Freescale i.MX SPI controllers" - depends on ARCH_MXC - select SPI_BITBANG + tristate "Freescale iMX SPI controller" + depends on ARCH_MX1 && EXPERIMENTAL help - This enables using the Freescale i.MX SPI controllers in master + This enables using the Freescale iMX SPI controller in master mode. config SPI_LM70_LLP @@ -174,21 +173,11 @@ config SPI_PL022 tristate "ARM AMBA PL022 SSP controller (EXPERIMENTAL)" depends on ARM_AMBA && EXPERIMENTAL default y if MACH_U300 - default y if ARCH_REALVIEW - default y if INTEGRATOR_IMPD1 - default y if ARCH_VERSATILE help This selects the ARM(R) AMBA(R) PrimeCell PL022 SSP controller. If you have an embedded system with an AMBA(R) bus and a PL022 controller, say Y or M here. -config SPI_PPC4xx - tristate "PPC4xx SPI Controller" - depends on PPC32 && 4xx && SPI_MASTER - select SPI_BITBANG - help - This selects a driver for the PPC4xx SPI Controller. - config SPI_PXA2XX tristate "PXA2xx SSP SPI master" depends on ARCH_PXA && EXPERIMENTAL @@ -222,12 +211,6 @@ config SPI_SH_SCI help SPI driver for SuperH SCI blocks. -config SPI_STMP3XXX - tristate "Freescale STMP37xx/378x SPI/SSP controller" - depends on ARCH_STMP3XXX && SPI_MASTER - help - SPI driver for Freescale STMP37xx/378x SoC SSP interface - config SPI_TXX9 tristate "Toshiba TXx9 SPI controller" depends on GENERIC_GPIO && CPU_TX49XX diff --git a/trunk/drivers/spi/Makefile b/trunk/drivers/spi/Makefile index 6d7a3f82c54b..3de408d294ba 100644 --- a/trunk/drivers/spi/Makefile +++ b/trunk/drivers/spi/Makefile @@ -17,7 +17,7 @@ obj-$(CONFIG_SPI_BITBANG) += spi_bitbang.o obj-$(CONFIG_SPI_AU1550) += au1550_spi.o obj-$(CONFIG_SPI_BUTTERFLY) += spi_butterfly.o obj-$(CONFIG_SPI_GPIO) += spi_gpio.o -obj-$(CONFIG_SPI_IMX) += mxc_spi.o +obj-$(CONFIG_SPI_IMX) += spi_imx.o obj-$(CONFIG_SPI_LM70_LLP) += spi_lm70llp.o obj-$(CONFIG_SPI_PXA2XX) += pxa2xx_spi.o obj-$(CONFIG_SPI_OMAP_UWIRE) += omap_uwire.o @@ -26,13 +26,11 @@ obj-$(CONFIG_SPI_ORION) += orion_spi.o obj-$(CONFIG_SPI_PL022) += amba-pl022.o obj-$(CONFIG_SPI_MPC52xx_PSC) += mpc52xx_psc_spi.o obj-$(CONFIG_SPI_MPC8xxx) += spi_mpc8xxx.o -obj-$(CONFIG_SPI_PPC4xx) += spi_ppc4xx.o obj-$(CONFIG_SPI_S3C24XX_GPIO) += spi_s3c24xx_gpio.o obj-$(CONFIG_SPI_S3C24XX) += spi_s3c24xx.o obj-$(CONFIG_SPI_TXX9) += spi_txx9.o obj-$(CONFIG_SPI_XILINX) += xilinx_spi.o obj-$(CONFIG_SPI_SH_SCI) += spi_sh_sci.o -obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o # ... add above this line ... # SPI protocol drivers (device/link on bus) diff --git a/trunk/drivers/spi/mxc_spi.c b/trunk/drivers/spi/mxc_spi.c deleted file mode 100644 index b1447236ae81..000000000000 --- a/trunk/drivers/spi/mxc_spi.c +++ /dev/null @@ -1,685 +0,0 @@ -/* - * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright (C) 2008 Juergen Beisert - * - * 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 - * 51 Franklin Street, Fifth Floor - * Boston, MA 02110-1301, USA. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#define DRIVER_NAME "spi_imx" - -#define MXC_CSPIRXDATA 0x00 -#define MXC_CSPITXDATA 0x04 -#define MXC_CSPICTRL 0x08 -#define MXC_CSPIINT 0x0c -#define MXC_RESET 0x1c - -/* generic defines to abstract from the different register layouts */ -#define MXC_INT_RR (1 << 0) /* Receive data ready interrupt */ -#define MXC_INT_TE (1 << 1) /* Transmit FIFO empty interrupt */ - -struct mxc_spi_config { - unsigned int speed_hz; - unsigned int bpw; - unsigned int mode; - int cs; -}; - -struct mxc_spi_data { - struct spi_bitbang bitbang; - - struct completion xfer_done; - void *base; - int irq; - struct clk *clk; - unsigned long spi_clk; - int *chipselect; - - unsigned int count; - void (*tx)(struct mxc_spi_data *); - void (*rx)(struct mxc_spi_data *); - void *rx_buf; - const void *tx_buf; - unsigned int txfifo; /* number of words pushed in tx FIFO */ - - /* SoC specific functions */ - void (*intctrl)(struct mxc_spi_data *, int); - int (*config)(struct mxc_spi_data *, struct mxc_spi_config *); - void (*trigger)(struct mxc_spi_data *); - int (*rx_available)(struct mxc_spi_data *); -}; - -#define MXC_SPI_BUF_RX(type) \ -static void mxc_spi_buf_rx_##type(struct mxc_spi_data *mxc_spi) \ -{ \ - unsigned int val = readl(mxc_spi->base + MXC_CSPIRXDATA); \ - \ - if (mxc_spi->rx_buf) { \ - *(type *)mxc_spi->rx_buf = val; \ - mxc_spi->rx_buf += sizeof(type); \ - } \ -} - -#define MXC_SPI_BUF_TX(type) \ -static void mxc_spi_buf_tx_##type(struct mxc_spi_data *mxc_spi) \ -{ \ - type val = 0; \ - \ - if (mxc_spi->tx_buf) { \ - val = *(type *)mxc_spi->tx_buf; \ - mxc_spi->tx_buf += sizeof(type); \ - } \ - \ - mxc_spi->count -= sizeof(type); \ - \ - writel(val, mxc_spi->base + MXC_CSPITXDATA); \ -} - -MXC_SPI_BUF_RX(u8) -MXC_SPI_BUF_TX(u8) -MXC_SPI_BUF_RX(u16) -MXC_SPI_BUF_TX(u16) -MXC_SPI_BUF_RX(u32) -MXC_SPI_BUF_TX(u32) - -/* First entry is reserved, second entry is valid only if SDHC_SPIEN is set - * (which is currently not the case in this driver) - */ -static int mxc_clkdivs[] = {0, 3, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128, 192, - 256, 384, 512, 768, 1024}; - -/* MX21, MX27 */ -static unsigned int mxc_spi_clkdiv_1(unsigned int fin, - unsigned int fspi) -{ - int i, max; - - if (cpu_is_mx21()) - max = 18; - else - max = 16; - - for (i = 2; i < max; i++) - if (fspi * mxc_clkdivs[i] >= fin) - return i; - - return max; -} - -/* MX1, MX31, MX35 */ -static unsigned int mxc_spi_clkdiv_2(unsigned int fin, - unsigned int fspi) -{ - int i, div = 4; - - for (i = 0; i < 7; i++) { - if (fspi * div >= fin) - return i; - div <<= 1; - } - - return 7; -} - -#define MX31_INTREG_TEEN (1 << 0) -#define MX31_INTREG_RREN (1 << 3) - -#define MX31_CSPICTRL_ENABLE (1 << 0) -#define MX31_CSPICTRL_MASTER (1 << 1) -#define MX31_CSPICTRL_XCH (1 << 2) -#define MX31_CSPICTRL_POL (1 << 4) -#define MX31_CSPICTRL_PHA (1 << 5) -#define MX31_CSPICTRL_SSCTL (1 << 6) -#define MX31_CSPICTRL_SSPOL (1 << 7) -#define MX31_CSPICTRL_BC_SHIFT 8 -#define MX35_CSPICTRL_BL_SHIFT 20 -#define MX31_CSPICTRL_CS_SHIFT 24 -#define MX35_CSPICTRL_CS_SHIFT 12 -#define MX31_CSPICTRL_DR_SHIFT 16 - -#define MX31_CSPISTATUS 0x14 -#define MX31_STATUS_RR (1 << 3) - -/* These functions also work for the i.MX35, but be aware that - * the i.MX35 has a slightly different register layout for bits - * we do not use here. - */ -static void mx31_intctrl(struct mxc_spi_data *mxc_spi, int enable) -{ - unsigned int val = 0; - - if (enable & MXC_INT_TE) - val |= MX31_INTREG_TEEN; - if (enable & MXC_INT_RR) - val |= MX31_INTREG_RREN; - - writel(val, mxc_spi->base + MXC_CSPIINT); -} - -static void mx31_trigger(struct mxc_spi_data *mxc_spi) -{ - unsigned int reg; - - reg = readl(mxc_spi->base + MXC_CSPICTRL); - reg |= MX31_CSPICTRL_XCH; - writel(reg, mxc_spi->base + MXC_CSPICTRL); -} - -static int mx31_config(struct mxc_spi_data *mxc_spi, - struct mxc_spi_config *config) -{ - unsigned int reg = MX31_CSPICTRL_ENABLE | MX31_CSPICTRL_MASTER; - - reg |= mxc_spi_clkdiv_2(mxc_spi->spi_clk, config->speed_hz) << - MX31_CSPICTRL_DR_SHIFT; - - if (cpu_is_mx31()) - reg |= (config->bpw - 1) << MX31_CSPICTRL_BC_SHIFT; - else if (cpu_is_mx35()) { - reg |= (config->bpw - 1) << MX35_CSPICTRL_BL_SHIFT; - reg |= MX31_CSPICTRL_SSCTL; - } - - if (config->mode & SPI_CPHA) - reg |= MX31_CSPICTRL_PHA; - if (config->mode & SPI_CPOL) - reg |= MX31_CSPICTRL_POL; - if (config->mode & SPI_CS_HIGH) - reg |= MX31_CSPICTRL_SSPOL; - if (config->cs < 0) { - if (cpu_is_mx31()) - reg |= (config->cs + 32) << MX31_CSPICTRL_CS_SHIFT; - else if (cpu_is_mx35()) - reg |= (config->cs + 32) << MX35_CSPICTRL_CS_SHIFT; - } - - writel(reg, mxc_spi->base + MXC_CSPICTRL); - - return 0; -} - -static int mx31_rx_available(struct mxc_spi_data *mxc_spi) -{ - return readl(mxc_spi->base + MX31_CSPISTATUS) & MX31_STATUS_RR; -} - -#define MX27_INTREG_RR (1 << 4) -#define MX27_INTREG_TEEN (1 << 9) -#define MX27_INTREG_RREN (1 << 13) - -#define MX27_CSPICTRL_POL (1 << 5) -#define MX27_CSPICTRL_PHA (1 << 6) -#define MX27_CSPICTRL_SSPOL (1 << 8) -#define MX27_CSPICTRL_XCH (1 << 9) -#define MX27_CSPICTRL_ENABLE (1 << 10) -#define MX27_CSPICTRL_MASTER (1 << 11) -#define MX27_CSPICTRL_DR_SHIFT 14 -#define MX27_CSPICTRL_CS_SHIFT 19 - -static void mx27_intctrl(struct mxc_spi_data *mxc_spi, int enable) -{ - unsigned int val = 0; - - if (enable & MXC_INT_TE) - val |= MX27_INTREG_TEEN; - if (enable & MXC_INT_RR) - val |= MX27_INTREG_RREN; - - writel(val, mxc_spi->base + MXC_CSPIINT); -} - -static void mx27_trigger(struct mxc_spi_data *mxc_spi) -{ - unsigned int reg; - - reg = readl(mxc_spi->base + MXC_CSPICTRL); - reg |= MX27_CSPICTRL_XCH; - writel(reg, mxc_spi->base + MXC_CSPICTRL); -} - -static int mx27_config(struct mxc_spi_data *mxc_spi, - struct mxc_spi_config *config) -{ - unsigned int reg = MX27_CSPICTRL_ENABLE | MX27_CSPICTRL_MASTER; - - reg |= mxc_spi_clkdiv_1(mxc_spi->spi_clk, config->speed_hz) << - MX27_CSPICTRL_DR_SHIFT; - reg |= config->bpw - 1; - - if (config->mode & SPI_CPHA) - reg |= MX27_CSPICTRL_PHA; - if (config->mode & SPI_CPOL) - reg |= MX27_CSPICTRL_POL; - if (config->mode & SPI_CS_HIGH) - reg |= MX27_CSPICTRL_SSPOL; - if (config->cs < 0) - reg |= (config->cs + 32) << MX27_CSPICTRL_CS_SHIFT; - - writel(reg, mxc_spi->base + MXC_CSPICTRL); - - return 0; -} - -static int mx27_rx_available(struct mxc_spi_data *mxc_spi) -{ - return readl(mxc_spi->base + MXC_CSPIINT) & MX27_INTREG_RR; -} - -#define MX1_INTREG_RR (1 << 3) -#define MX1_INTREG_TEEN (1 << 8) -#define MX1_INTREG_RREN (1 << 11) - -#define MX1_CSPICTRL_POL (1 << 4) -#define MX1_CSPICTRL_PHA (1 << 5) -#define MX1_CSPICTRL_XCH (1 << 8) -#define MX1_CSPICTRL_ENABLE (1 << 9) -#define MX1_CSPICTRL_MASTER (1 << 10) -#define MX1_CSPICTRL_DR_SHIFT 13 - -static void mx1_intctrl(struct mxc_spi_data *mxc_spi, int enable) -{ - unsigned int val = 0; - - if (enable & MXC_INT_TE) - val |= MX1_INTREG_TEEN; - if (enable & MXC_INT_RR) - val |= MX1_INTREG_RREN; - - writel(val, mxc_spi->base + MXC_CSPIINT); -} - -static void mx1_trigger(struct mxc_spi_data *mxc_spi) -{ - unsigned int reg; - - reg = readl(mxc_spi->base + MXC_CSPICTRL); - reg |= MX1_CSPICTRL_XCH; - writel(reg, mxc_spi->base + MXC_CSPICTRL); -} - -static int mx1_config(struct mxc_spi_data *mxc_spi, - struct mxc_spi_config *config) -{ - unsigned int reg = MX1_CSPICTRL_ENABLE | MX1_CSPICTRL_MASTER; - - reg |= mxc_spi_clkdiv_2(mxc_spi->spi_clk, config->speed_hz) << - MX1_CSPICTRL_DR_SHIFT; - reg |= config->bpw - 1; - - if (config->mode & SPI_CPHA) - reg |= MX1_CSPICTRL_PHA; - if (config->mode & SPI_CPOL) - reg |= MX1_CSPICTRL_POL; - - writel(reg, mxc_spi->base + MXC_CSPICTRL); - - return 0; -} - -static int mx1_rx_available(struct mxc_spi_data *mxc_spi) -{ - return readl(mxc_spi->base + MXC_CSPIINT) & MX1_INTREG_RR; -} - -static void mxc_spi_chipselect(struct spi_device *spi, int is_active) -{ - struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master); - unsigned int cs = 0; - int gpio = mxc_spi->chipselect[spi->chip_select]; - struct mxc_spi_config config; - - if (spi->mode & SPI_CS_HIGH) - cs = 1; - - if (is_active == BITBANG_CS_INACTIVE) { - if (gpio >= 0) - gpio_set_value(gpio, !cs); - return; - } - - config.bpw = spi->bits_per_word; - config.speed_hz = spi->max_speed_hz; - config.mode = spi->mode; - config.cs = mxc_spi->chipselect[spi->chip_select]; - - mxc_spi->config(mxc_spi, &config); - - /* Initialize the functions for transfer */ - if (config.bpw <= 8) { - mxc_spi->rx = mxc_spi_buf_rx_u8; - mxc_spi->tx = mxc_spi_buf_tx_u8; - } else if (config.bpw <= 16) { - mxc_spi->rx = mxc_spi_buf_rx_u16; - mxc_spi->tx = mxc_spi_buf_tx_u16; - } else if (config.bpw <= 32) { - mxc_spi->rx = mxc_spi_buf_rx_u32; - mxc_spi->tx = mxc_spi_buf_tx_u32; - } else - BUG(); - - if (gpio >= 0) - gpio_set_value(gpio, cs); - - return; -} - -static void mxc_spi_push(struct mxc_spi_data *mxc_spi) -{ - while (mxc_spi->txfifo < 8) { - if (!mxc_spi->count) - break; - mxc_spi->tx(mxc_spi); - mxc_spi->txfifo++; - } - - mxc_spi->trigger(mxc_spi); -} - -static irqreturn_t mxc_spi_isr(int irq, void *dev_id) -{ - struct mxc_spi_data *mxc_spi = dev_id; - - while (mxc_spi->rx_available(mxc_spi)) { - mxc_spi->rx(mxc_spi); - mxc_spi->txfifo--; - } - - if (mxc_spi->count) { - mxc_spi_push(mxc_spi); - return IRQ_HANDLED; - } - - if (mxc_spi->txfifo) { - /* No data left to push, but still waiting for rx data, - * enable receive data available interrupt. - */ - mxc_spi->intctrl(mxc_spi, MXC_INT_RR); - return IRQ_HANDLED; - } - - mxc_spi->intctrl(mxc_spi, 0); - complete(&mxc_spi->xfer_done); - - return IRQ_HANDLED; -} - -static int mxc_spi_setupxfer(struct spi_device *spi, - struct spi_transfer *t) -{ - struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master); - struct mxc_spi_config config; - - config.bpw = t ? t->bits_per_word : spi->bits_per_word; - config.speed_hz = t ? t->speed_hz : spi->max_speed_hz; - config.mode = spi->mode; - - mxc_spi->config(mxc_spi, &config); - - return 0; -} - -static int mxc_spi_transfer(struct spi_device *spi, - struct spi_transfer *transfer) -{ - struct mxc_spi_data *mxc_spi = spi_master_get_devdata(spi->master); - - mxc_spi->tx_buf = transfer->tx_buf; - mxc_spi->rx_buf = transfer->rx_buf; - mxc_spi->count = transfer->len; - mxc_spi->txfifo = 0; - - init_completion(&mxc_spi->xfer_done); - - mxc_spi_push(mxc_spi); - - mxc_spi->intctrl(mxc_spi, MXC_INT_TE); - - wait_for_completion(&mxc_spi->xfer_done); - - return transfer->len; -} - -static int mxc_spi_setup(struct spi_device *spi) -{ - if (!spi->bits_per_word) - spi->bits_per_word = 8; - - pr_debug("%s: mode %d, %u bpw, %d hz\n", __func__, - spi->mode, spi->bits_per_word, spi->max_speed_hz); - - mxc_spi_chipselect(spi, BITBANG_CS_INACTIVE); - - return 0; -} - -static void mxc_spi_cleanup(struct spi_device *spi) -{ -} - -static int __init mxc_spi_probe(struct platform_device *pdev) -{ - struct spi_imx_master *mxc_platform_info; - struct spi_master *master; - struct mxc_spi_data *mxc_spi; - struct resource *res; - int i, ret; - - mxc_platform_info = (struct spi_imx_master *)pdev->dev.platform_data; - if (!mxc_platform_info) { - dev_err(&pdev->dev, "can't get the platform data\n"); - return -EINVAL; - } - - master = spi_alloc_master(&pdev->dev, sizeof(struct mxc_spi_data)); - if (!master) - return -ENOMEM; - - platform_set_drvdata(pdev, master); - - master->bus_num = pdev->id; - master->num_chipselect = mxc_platform_info->num_chipselect; - - mxc_spi = spi_master_get_devdata(master); - mxc_spi->bitbang.master = spi_master_get(master); - mxc_spi->chipselect = mxc_platform_info->chipselect; - - for (i = 0; i < master->num_chipselect; i++) { - if (mxc_spi->chipselect[i] < 0) - continue; - ret = gpio_request(mxc_spi->chipselect[i], DRIVER_NAME); - if (ret) { - i--; - while (i > 0) - if (mxc_spi->chipselect[i] >= 0) - gpio_free(mxc_spi->chipselect[i--]); - dev_err(&pdev->dev, "can't get cs gpios"); - goto out_master_put; - } - gpio_direction_output(mxc_spi->chipselect[i], 1); - } - - mxc_spi->bitbang.chipselect = mxc_spi_chipselect; - mxc_spi->bitbang.setup_transfer = mxc_spi_setupxfer; - mxc_spi->bitbang.txrx_bufs = mxc_spi_transfer; - mxc_spi->bitbang.master->setup = mxc_spi_setup; - mxc_spi->bitbang.master->cleanup = mxc_spi_cleanup; - - init_completion(&mxc_spi->xfer_done); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, "can't get platform resource\n"); - ret = -ENOMEM; - goto out_gpio_free; - } - - if (!request_mem_region(res->start, resource_size(res), pdev->name)) { - dev_err(&pdev->dev, "request_mem_region failed\n"); - ret = -EBUSY; - goto out_gpio_free; - } - - mxc_spi->base = ioremap(res->start, resource_size(res)); - if (!mxc_spi->base) { - ret = -EINVAL; - goto out_release_mem; - } - - mxc_spi->irq = platform_get_irq(pdev, 0); - if (!mxc_spi->irq) { - ret = -EINVAL; - goto out_iounmap; - } - - ret = request_irq(mxc_spi->irq, mxc_spi_isr, 0, DRIVER_NAME, mxc_spi); - if (ret) { - dev_err(&pdev->dev, "can't get irq%d: %d\n", mxc_spi->irq, ret); - goto out_iounmap; - } - - if (cpu_is_mx31() || cpu_is_mx35()) { - mxc_spi->intctrl = mx31_intctrl; - mxc_spi->config = mx31_config; - mxc_spi->trigger = mx31_trigger; - mxc_spi->rx_available = mx31_rx_available; - } else if (cpu_is_mx27() || cpu_is_mx21()) { - mxc_spi->intctrl = mx27_intctrl; - mxc_spi->config = mx27_config; - mxc_spi->trigger = mx27_trigger; - mxc_spi->rx_available = mx27_rx_available; - } else if (cpu_is_mx1()) { - mxc_spi->intctrl = mx1_intctrl; - mxc_spi->config = mx1_config; - mxc_spi->trigger = mx1_trigger; - mxc_spi->rx_available = mx1_rx_available; - } else - BUG(); - - mxc_spi->clk = clk_get(&pdev->dev, NULL); - if (IS_ERR(mxc_spi->clk)) { - dev_err(&pdev->dev, "unable to get clock\n"); - ret = PTR_ERR(mxc_spi->clk); - goto out_free_irq; - } - - clk_enable(mxc_spi->clk); - mxc_spi->spi_clk = clk_get_rate(mxc_spi->clk); - - if (!cpu_is_mx31() || !cpu_is_mx35()) - writel(1, mxc_spi->base + MXC_RESET); - - mxc_spi->intctrl(mxc_spi, 0); - - ret = spi_bitbang_start(&mxc_spi->bitbang); - if (ret) { - dev_err(&pdev->dev, "bitbang start failed with %d\n", ret); - goto out_clk_put; - } - - dev_info(&pdev->dev, "probed\n"); - - return ret; - -out_clk_put: - clk_disable(mxc_spi->clk); - clk_put(mxc_spi->clk); -out_free_irq: - free_irq(mxc_spi->irq, mxc_spi); -out_iounmap: - iounmap(mxc_spi->base); -out_release_mem: - release_mem_region(res->start, resource_size(res)); -out_gpio_free: - for (i = 0; i < master->num_chipselect; i++) - if (mxc_spi->chipselect[i] >= 0) - gpio_free(mxc_spi->chipselect[i]); -out_master_put: - spi_master_put(master); - kfree(master); - platform_set_drvdata(pdev, NULL); - return ret; -} - -static int __exit mxc_spi_remove(struct platform_device *pdev) -{ - struct spi_master *master = platform_get_drvdata(pdev); - struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - struct mxc_spi_data *mxc_spi = spi_master_get_devdata(master); - int i; - - spi_bitbang_stop(&mxc_spi->bitbang); - - writel(0, mxc_spi->base + MXC_CSPICTRL); - clk_disable(mxc_spi->clk); - clk_put(mxc_spi->clk); - free_irq(mxc_spi->irq, mxc_spi); - iounmap(mxc_spi->base); - - for (i = 0; i < master->num_chipselect; i++) - if (mxc_spi->chipselect[i] >= 0) - gpio_free(mxc_spi->chipselect[i]); - - spi_master_put(master); - - release_mem_region(res->start, resource_size(res)); - - platform_set_drvdata(pdev, NULL); - - return 0; -} - -static struct platform_driver mxc_spi_driver = { - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, - .probe = mxc_spi_probe, - .remove = __exit_p(mxc_spi_remove), -}; - -static int __init mxc_spi_init(void) -{ - return platform_driver_register(&mxc_spi_driver); -} - -static void __exit mxc_spi_exit(void) -{ - platform_driver_unregister(&mxc_spi_driver); -} - -module_init(mxc_spi_init); -module_exit(mxc_spi_exit); - -MODULE_DESCRIPTION("SPI Master Controller driver"); -MODULE_AUTHOR("Sascha Hauer, Pengutronix"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/spi/omap2_mcspi.c b/trunk/drivers/spi/omap2_mcspi.c index ba1a872b221e..9b80ad36dbba 100644 --- a/trunk/drivers/spi/omap2_mcspi.c +++ b/trunk/drivers/spi/omap2_mcspi.c @@ -41,9 +41,6 @@ #define OMAP2_MCSPI_MAX_FREQ 48000000 -/* OMAP2 has 3 SPI controllers, while OMAP3 has 4 */ -#define OMAP2_MCSPI_MAX_CTRL 4 - #define OMAP2_MCSPI_REVISION 0x00 #define OMAP2_MCSPI_SYSCONFIG 0x10 #define OMAP2_MCSPI_SYSSTATUS 0x14 @@ -62,40 +59,40 @@ /* per-register bitmasks: */ -#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE BIT(4) -#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP BIT(2) -#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE BIT(0) -#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET BIT(1) +#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE (2 << 3) +#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP (1 << 2) +#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE (1 << 0) +#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET (1 << 1) -#define OMAP2_MCSPI_SYSSTATUS_RESETDONE BIT(0) +#define OMAP2_MCSPI_SYSSTATUS_RESETDONE (1 << 0) -#define OMAP2_MCSPI_MODULCTRL_SINGLE BIT(0) -#define OMAP2_MCSPI_MODULCTRL_MS BIT(2) -#define OMAP2_MCSPI_MODULCTRL_STEST BIT(3) +#define OMAP2_MCSPI_MODULCTRL_SINGLE (1 << 0) +#define OMAP2_MCSPI_MODULCTRL_MS (1 << 2) +#define OMAP2_MCSPI_MODULCTRL_STEST (1 << 3) -#define OMAP2_MCSPI_CHCONF_PHA BIT(0) -#define OMAP2_MCSPI_CHCONF_POL BIT(1) +#define OMAP2_MCSPI_CHCONF_PHA (1 << 0) +#define OMAP2_MCSPI_CHCONF_POL (1 << 1) #define OMAP2_MCSPI_CHCONF_CLKD_MASK (0x0f << 2) -#define OMAP2_MCSPI_CHCONF_EPOL BIT(6) +#define OMAP2_MCSPI_CHCONF_EPOL (1 << 6) #define OMAP2_MCSPI_CHCONF_WL_MASK (0x1f << 7) -#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY BIT(12) -#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY BIT(13) +#define OMAP2_MCSPI_CHCONF_TRM_RX_ONLY (0x01 << 12) +#define OMAP2_MCSPI_CHCONF_TRM_TX_ONLY (0x02 << 12) #define OMAP2_MCSPI_CHCONF_TRM_MASK (0x03 << 12) -#define OMAP2_MCSPI_CHCONF_DMAW BIT(14) -#define OMAP2_MCSPI_CHCONF_DMAR BIT(15) -#define OMAP2_MCSPI_CHCONF_DPE0 BIT(16) -#define OMAP2_MCSPI_CHCONF_DPE1 BIT(17) -#define OMAP2_MCSPI_CHCONF_IS BIT(18) -#define OMAP2_MCSPI_CHCONF_TURBO BIT(19) -#define OMAP2_MCSPI_CHCONF_FORCE BIT(20) +#define OMAP2_MCSPI_CHCONF_DMAW (1 << 14) +#define OMAP2_MCSPI_CHCONF_DMAR (1 << 15) +#define OMAP2_MCSPI_CHCONF_DPE0 (1 << 16) +#define OMAP2_MCSPI_CHCONF_DPE1 (1 << 17) +#define OMAP2_MCSPI_CHCONF_IS (1 << 18) +#define OMAP2_MCSPI_CHCONF_TURBO (1 << 19) +#define OMAP2_MCSPI_CHCONF_FORCE (1 << 20) -#define OMAP2_MCSPI_CHSTAT_RXS BIT(0) -#define OMAP2_MCSPI_CHSTAT_TXS BIT(1) -#define OMAP2_MCSPI_CHSTAT_EOT BIT(2) +#define OMAP2_MCSPI_CHSTAT_RXS (1 << 0) +#define OMAP2_MCSPI_CHSTAT_TXS (1 << 1) +#define OMAP2_MCSPI_CHSTAT_EOT (1 << 2) -#define OMAP2_MCSPI_CHCTRL_EN BIT(0) +#define OMAP2_MCSPI_CHCTRL_EN (1 << 0) -#define OMAP2_MCSPI_WAKEUPENABLE_WKEN BIT(0) +#define OMAP2_MCSPI_WAKEUPENABLE_WKEN (1 << 0) /* We have 2 DMA channels per CS, one for RX and one for TX */ struct omap2_mcspi_dma { @@ -134,23 +131,8 @@ struct omap2_mcspi_cs { void __iomem *base; unsigned long phys; int word_len; - struct list_head node; - /* Context save and restore shadow register */ - u32 chconf0; -}; - -/* used for context save and restore, structure members to be updated whenever - * corresponding registers are modified. - */ -struct omap2_mcspi_regs { - u32 sysconfig; - u32 modulctrl; - u32 wakeupenable; - struct list_head cs; }; -static struct omap2_mcspi_regs omap2_mcspi_ctx[OMAP2_MCSPI_MAX_CTRL]; - static struct workqueue_struct *omap2_mcspi_wq; #define MOD_REG_BIT(val, mask, set) do { \ @@ -190,27 +172,12 @@ static inline u32 mcspi_read_cs_reg(const struct spi_device *spi, int idx) return __raw_readl(cs->base + idx); } -static inline u32 mcspi_cached_chconf0(const struct spi_device *spi) -{ - struct omap2_mcspi_cs *cs = spi->controller_state; - - return cs->chconf0; -} - -static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val) -{ - struct omap2_mcspi_cs *cs = spi->controller_state; - - cs->chconf0 = val; - mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val); -} - static void omap2_mcspi_set_dma_req(const struct spi_device *spi, int is_read, int enable) { u32 l, rw; - l = mcspi_cached_chconf0(spi); + l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); if (is_read) /* 1 is read, 0 write */ rw = OMAP2_MCSPI_CHCONF_DMAR; @@ -218,7 +185,7 @@ static void omap2_mcspi_set_dma_req(const struct spi_device *spi, rw = OMAP2_MCSPI_CHCONF_DMAW; MOD_REG_BIT(l, rw, enable); - mcspi_write_chconf0(spi, l); + mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l); } static void omap2_mcspi_set_enable(const struct spi_device *spi, int enable) @@ -233,9 +200,9 @@ static void omap2_mcspi_force_cs(struct spi_device *spi, int cs_active) { u32 l; - l = mcspi_cached_chconf0(spi); + l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); MOD_REG_BIT(l, OMAP2_MCSPI_CHCONF_FORCE, cs_active); - mcspi_write_chconf0(spi, l); + mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l); } static void omap2_mcspi_set_master_mode(struct spi_master *master) @@ -250,46 +217,6 @@ static void omap2_mcspi_set_master_mode(struct spi_master *master) MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_MS, 0); MOD_REG_BIT(l, OMAP2_MCSPI_MODULCTRL_SINGLE, 1); mcspi_write_reg(master, OMAP2_MCSPI_MODULCTRL, l); - - omap2_mcspi_ctx[master->bus_num - 1].modulctrl = l; -} - -static void omap2_mcspi_restore_ctx(struct omap2_mcspi *mcspi) -{ - struct spi_master *spi_cntrl; - struct omap2_mcspi_cs *cs; - spi_cntrl = mcspi->master; - - /* McSPI: context restore */ - mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL, - omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl); - - mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG, - omap2_mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig); - - mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE, - omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable); - - list_for_each_entry(cs, &omap2_mcspi_ctx[spi_cntrl->bus_num - 1].cs, - node) - __raw_writel(cs->chconf0, cs->base + OMAP2_MCSPI_CHCONF0); -} -static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi) -{ - clk_disable(mcspi->ick); - clk_disable(mcspi->fck); -} - -static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi) -{ - if (clk_enable(mcspi->ick)) - return -ENODEV; - if (clk_enable(mcspi->fck)) - return -ENODEV; - - omap2_mcspi_restore_ctx(mcspi); - - return 0; } static unsigned @@ -430,7 +357,7 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) c = count; word_len = cs->word_len; - l = mcspi_cached_chconf0(spi); + l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); l &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; /* We store the pre-calculated register addresses on stack to speed @@ -470,7 +397,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) * more word i/o: switch to rx+tx */ if (c == 0 && tx == NULL) - mcspi_write_chconf0(spi, l); + mcspi_write_cs_reg(spi, + OMAP2_MCSPI_CHCONF0, l); *rx++ = __raw_readl(rx_reg); #ifdef VERBOSE dev_dbg(&spi->dev, "read-%d %02x\n", @@ -508,7 +436,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) * more word i/o: switch to rx+tx */ if (c == 0 && tx == NULL) - mcspi_write_chconf0(spi, l); + mcspi_write_cs_reg(spi, + OMAP2_MCSPI_CHCONF0, l); *rx++ = __raw_readl(rx_reg); #ifdef VERBOSE dev_dbg(&spi->dev, "read-%d %04x\n", @@ -546,7 +475,8 @@ omap2_mcspi_txrx_pio(struct spi_device *spi, struct spi_transfer *xfer) * more word i/o: switch to rx+tx */ if (c == 0 && tx == NULL) - mcspi_write_chconf0(spi, l); + mcspi_write_cs_reg(spi, + OMAP2_MCSPI_CHCONF0, l); *rx++ = __raw_readl(rx_reg); #ifdef VERBOSE dev_dbg(&spi->dev, "read-%d %04x\n", @@ -575,12 +505,10 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, { struct omap2_mcspi_cs *cs = spi->controller_state; struct omap2_mcspi *mcspi; - struct spi_master *spi_cntrl; u32 l = 0, div = 0; u8 word_len = spi->bits_per_word; mcspi = spi_master_get_devdata(spi->master); - spi_cntrl = mcspi->master; if (t != NULL && t->bits_per_word) word_len = t->bits_per_word; @@ -594,7 +522,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, } else div = 15; - l = mcspi_cached_chconf0(spi); + l = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); /* standard 4-wire master mode: SCK, MOSI/out, MISO/in, nCS * REVISIT: this controller could support SPI_3WIRE mode. @@ -626,7 +554,7 @@ static int omap2_mcspi_setup_transfer(struct spi_device *spi, else l &= ~OMAP2_MCSPI_CHCONF_PHA; - mcspi_write_chconf0(spi, l); + mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, l); dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n", OMAP2_MCSPI_MAX_FREQ / (1 << div), @@ -719,11 +647,7 @@ static int omap2_mcspi_setup(struct spi_device *spi) return -ENOMEM; cs->base = mcspi->base + spi->chip_select * 0x14; cs->phys = mcspi->phys + spi->chip_select * 0x14; - cs->chconf0 = 0; spi->controller_state = cs; - /* Link this to context save list */ - list_add_tail(&cs->node, - &omap2_mcspi_ctx[mcspi->master->bus_num - 1].cs); } if (mcspi_dma->dma_rx_channel == -1 @@ -733,11 +657,11 @@ static int omap2_mcspi_setup(struct spi_device *spi) return ret; } - if (omap2_mcspi_enable_clocks(mcspi)) - return -ENODEV; - + clk_enable(mcspi->ick); + clk_enable(mcspi->fck); ret = omap2_mcspi_setup_transfer(spi, NULL); - omap2_mcspi_disable_clocks(mcspi); + clk_disable(mcspi->fck); + clk_disable(mcspi->ick); return ret; } @@ -746,15 +670,10 @@ static void omap2_mcspi_cleanup(struct spi_device *spi) { struct omap2_mcspi *mcspi; struct omap2_mcspi_dma *mcspi_dma; - struct omap2_mcspi_cs *cs; mcspi = spi_master_get_devdata(spi->master); mcspi_dma = &mcspi->dma_channels[spi->chip_select]; - /* Unlink controller state from context save list */ - cs = spi->controller_state; - list_del(&cs->node); - kfree(spi->controller_state); if (mcspi_dma->dma_rx_channel != -1) { @@ -774,8 +693,8 @@ static void omap2_mcspi_work(struct work_struct *work) mcspi = container_of(work, struct omap2_mcspi, work); spin_lock_irq(&mcspi->lock); - if (omap2_mcspi_enable_clocks(mcspi)) - goto out; + clk_enable(mcspi->ick); + clk_enable(mcspi->fck); /* We only enable one channel at a time -- the one whose message is * at the head of the queue -- although this controller would gladly @@ -822,13 +741,13 @@ static void omap2_mcspi_work(struct work_struct *work) cs_active = 1; } - chconf = mcspi_cached_chconf0(spi); + chconf = mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0); chconf &= ~OMAP2_MCSPI_CHCONF_TRM_MASK; if (t->tx_buf == NULL) chconf |= OMAP2_MCSPI_CHCONF_TRM_RX_ONLY; else if (t->rx_buf == NULL) chconf |= OMAP2_MCSPI_CHCONF_TRM_TX_ONLY; - mcspi_write_chconf0(spi, chconf); + mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, chconf); if (t->len) { unsigned count; @@ -877,9 +796,9 @@ static void omap2_mcspi_work(struct work_struct *work) spin_lock_irq(&mcspi->lock); } - omap2_mcspi_disable_clocks(mcspi); + clk_disable(mcspi->fck); + clk_disable(mcspi->ick); -out: spin_unlock_irq(&mcspi->lock); } @@ -966,8 +885,8 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi) struct spi_master *master = mcspi->master; u32 tmp; - if (omap2_mcspi_enable_clocks(mcspi)) - return -1; + clk_enable(mcspi->ick); + clk_enable(mcspi->fck); mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, OMAP2_MCSPI_SYSCONFIG_SOFTRESET); @@ -975,18 +894,18 @@ static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi) tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS); } while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE)); - tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE | - OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP | - OMAP2_MCSPI_SYSCONFIG_SMARTIDLE; - mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, tmp); - omap2_mcspi_ctx[master->bus_num - 1].sysconfig = tmp; + mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, + OMAP2_MCSPI_SYSCONFIG_AUTOIDLE | + OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP | + OMAP2_MCSPI_SYSCONFIG_SMARTIDLE); - tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN; - mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp); - omap2_mcspi_ctx[master->bus_num - 1].wakeupenable = tmp; + mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, + OMAP2_MCSPI_WAKEUPENABLE_WKEN); omap2_mcspi_set_master_mode(master); - omap2_mcspi_disable_clocks(mcspi); + + clk_disable(mcspi->fck); + clk_disable(mcspi->ick); return 0; } @@ -1014,8 +933,7 @@ static u8 __initdata spi2_txdma_id[] = { OMAP24XX_DMA_SPI2_TX1, }; -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) \ - || defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP34XX) static u8 __initdata spi3_rxdma_id[] = { OMAP24XX_DMA_SPI3_RX0, OMAP24XX_DMA_SPI3_RX1, @@ -1027,7 +945,7 @@ static u8 __initdata spi3_txdma_id[] = { }; #endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) +#ifdef CONFIG_ARCH_OMAP3 static u8 __initdata spi4_rxdma_id[] = { OMAP34XX_DMA_SPI4_RX0, }; @@ -1057,15 +975,14 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) txdma_id = spi2_txdma_id; num_chipselect = 2; break; -#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \ - || defined(CONFIG_ARCH_OMAP4) +#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) case 3: rxdma_id = spi3_rxdma_id; txdma_id = spi3_txdma_id; num_chipselect = 2; break; #endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) +#ifdef CONFIG_ARCH_OMAP3 case 4: rxdma_id = spi4_rxdma_id; txdma_id = spi4_txdma_id; @@ -1121,7 +1038,6 @@ static int __init omap2_mcspi_probe(struct platform_device *pdev) spin_lock_init(&mcspi->lock); INIT_LIST_HEAD(&mcspi->msg_queue); - INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs); mcspi->ick = clk_get(&pdev->dev, "ick"); if (IS_ERR(mcspi->ick)) { diff --git a/trunk/drivers/spi/pxa2xx_spi.c b/trunk/drivers/spi/pxa2xx_spi.c index 31dd56f0dae9..d949dbf1141f 100644 --- a/trunk/drivers/spi/pxa2xx_spi.c +++ b/trunk/drivers/spi/pxa2xx_spi.c @@ -1729,7 +1729,7 @@ static int __init pxa2xx_spi_init(void) { return platform_driver_probe(&driver, pxa2xx_spi_probe); } -subsys_initcall(pxa2xx_spi_init); +module_init(pxa2xx_spi_init); static void __exit pxa2xx_spi_exit(void) { diff --git a/trunk/drivers/spi/spi.c b/trunk/drivers/spi/spi.c index b76f2468a84a..70845ccd85c3 100644 --- a/trunk/drivers/spi/spi.c +++ b/trunk/drivers/spi/spi.c @@ -23,7 +23,6 @@ #include #include #include -#include #include @@ -60,32 +59,9 @@ static struct device_attribute spi_dev_attrs[] = { * and the sysfs version makes coldplug work too. */ -static const struct spi_device_id *spi_match_id(const struct spi_device_id *id, - const struct spi_device *sdev) -{ - while (id->name[0]) { - if (!strcmp(sdev->modalias, id->name)) - return id; - id++; - } - return NULL; -} - -const struct spi_device_id *spi_get_device_id(const struct spi_device *sdev) -{ - const struct spi_driver *sdrv = to_spi_driver(sdev->dev.driver); - - return spi_match_id(sdrv->id_table, sdev); -} -EXPORT_SYMBOL_GPL(spi_get_device_id); - static int spi_match_device(struct device *dev, struct device_driver *drv) { const struct spi_device *spi = to_spi_device(dev); - const struct spi_driver *sdrv = to_spi_driver(drv); - - if (sdrv->id_table) - return !!spi_match_id(sdrv->id_table, spi); return strcmp(spi->modalias, drv->name) == 0; } @@ -94,7 +70,7 @@ static int spi_uevent(struct device *dev, struct kobj_uevent_env *env) { const struct spi_device *spi = to_spi_device(dev); - add_uevent_var(env, "MODALIAS=%s%s", SPI_MODULE_PREFIX, spi->modalias); + add_uevent_var(env, "MODALIAS=%s", spi->modalias); return 0; } @@ -663,65 +639,6 @@ int spi_setup(struct spi_device *spi) } EXPORT_SYMBOL_GPL(spi_setup); -/** - * spi_async - asynchronous SPI transfer - * @spi: device with which data will be exchanged - * @message: describes the data transfers, including completion callback - * Context: any (irqs may be blocked, etc) - * - * This call may be used in_irq and other contexts which can't sleep, - * as well as from task contexts which can sleep. - * - * The completion callback is invoked in a context which can't sleep. - * Before that invocation, the value of message->status is undefined. - * When the callback is issued, message->status holds either zero (to - * indicate complete success) or a negative error code. After that - * callback returns, the driver which issued the transfer request may - * deallocate the associated memory; it's no longer in use by any SPI - * core or controller driver code. - * - * Note that although all messages to a spi_device are handled in - * FIFO order, messages may go to different devices in other orders. - * Some device might be higher priority, or have various "hard" access - * time requirements, for example. - * - * On detection of any fault during the transfer, processing of - * the entire message is aborted, and the device is deselected. - * Until returning from the associated message completion callback, - * no other spi_message queued to that device will be processed. - * (This rule applies equally to all the synchronous transfer calls, - * which are wrappers around this core asynchronous primitive.) - */ -int spi_async(struct spi_device *spi, struct spi_message *message) -{ - struct spi_master *master = spi->master; - - /* Half-duplex links include original MicroWire, and ones with - * only one data pin like SPI_3WIRE (switches direction) or where - * either MOSI or MISO is missing. They can also be caused by - * software limitations. - */ - if ((master->flags & SPI_MASTER_HALF_DUPLEX) - || (spi->mode & SPI_3WIRE)) { - struct spi_transfer *xfer; - unsigned flags = master->flags; - - list_for_each_entry(xfer, &message->transfers, transfer_list) { - if (xfer->rx_buf && xfer->tx_buf) - return -EINVAL; - if ((flags & SPI_MASTER_NO_TX) && xfer->tx_buf) - return -EINVAL; - if ((flags & SPI_MASTER_NO_RX) && xfer->rx_buf) - return -EINVAL; - } - } - - message->spi = spi; - message->status = -EINPROGRESS; - return master->transfer(spi, message); -} -EXPORT_SYMBOL_GPL(spi_async); - /*-------------------------------------------------------------------------*/ diff --git a/trunk/drivers/spi/spi_imx.c b/trunk/drivers/spi/spi_imx.c new file mode 100644 index 000000000000..c195e45f7f35 --- /dev/null +++ b/trunk/drivers/spi/spi_imx.c @@ -0,0 +1,1770 @@ +/* + * drivers/spi/spi_imx.c + * + * Copyright (C) 2006 SWAPP + * Andrea Paterniani + * + * Initial version inspired by: + * linux-2.6.17-rc3-mm1/drivers/spi/pxa2xx_spi.c + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +/*-------------------------------------------------------------------------*/ +/* SPI Registers offsets from peripheral base address */ +#define SPI_RXDATA (0x00) +#define SPI_TXDATA (0x04) +#define SPI_CONTROL (0x08) +#define SPI_INT_STATUS (0x0C) +#define SPI_TEST (0x10) +#define SPI_PERIOD (0x14) +#define SPI_DMA (0x18) +#define SPI_RESET (0x1C) + +/* SPI Control Register Bit Fields & Masks */ +#define SPI_CONTROL_BITCOUNT_MASK (0xF) /* Bit Count Mask */ +#define SPI_CONTROL_BITCOUNT(n) (((n) - 1) & SPI_CONTROL_BITCOUNT_MASK) +#define SPI_CONTROL_POL (0x1 << 4) /* Clock Polarity Mask */ +#define SPI_CONTROL_POL_ACT_HIGH (0x0 << 4) /* Active high pol. (0=idle) */ +#define SPI_CONTROL_POL_ACT_LOW (0x1 << 4) /* Active low pol. (1=idle) */ +#define SPI_CONTROL_PHA (0x1 << 5) /* Clock Phase Mask */ +#define SPI_CONTROL_PHA_0 (0x0 << 5) /* Clock Phase 0 */ +#define SPI_CONTROL_PHA_1 (0x1 << 5) /* Clock Phase 1 */ +#define SPI_CONTROL_SSCTL (0x1 << 6) /* /SS Waveform Select Mask */ +#define SPI_CONTROL_SSCTL_0 (0x0 << 6) /* Master: /SS stays low between SPI burst + Slave: RXFIFO advanced by BIT_COUNT */ +#define SPI_CONTROL_SSCTL_1 (0x1 << 6) /* Master: /SS insert pulse between SPI burst + Slave: RXFIFO advanced by /SS rising edge */ +#define SPI_CONTROL_SSPOL (0x1 << 7) /* /SS Polarity Select Mask */ +#define SPI_CONTROL_SSPOL_ACT_LOW (0x0 << 7) /* /SS Active low */ +#define SPI_CONTROL_SSPOL_ACT_HIGH (0x1 << 7) /* /SS Active high */ +#define SPI_CONTROL_XCH (0x1 << 8) /* Exchange */ +#define SPI_CONTROL_SPIEN (0x1 << 9) /* SPI Module Enable */ +#define SPI_CONTROL_MODE (0x1 << 10) /* SPI Mode Select Mask */ +#define SPI_CONTROL_MODE_SLAVE (0x0 << 10) /* SPI Mode Slave */ +#define SPI_CONTROL_MODE_MASTER (0x1 << 10) /* SPI Mode Master */ +#define SPI_CONTROL_DRCTL (0x3 << 11) /* /SPI_RDY Control Mask */ +#define SPI_CONTROL_DRCTL_0 (0x0 << 11) /* Ignore /SPI_RDY */ +#define SPI_CONTROL_DRCTL_1 (0x1 << 11) /* /SPI_RDY falling edge triggers input */ +#define SPI_CONTROL_DRCTL_2 (0x2 << 11) /* /SPI_RDY active low level triggers input */ +#define SPI_CONTROL_DATARATE (0x7 << 13) /* Data Rate Mask */ +#define SPI_PERCLK2_DIV_MIN (0) /* PERCLK2:4 */ +#define SPI_PERCLK2_DIV_MAX (7) /* PERCLK2:512 */ +#define SPI_CONTROL_DATARATE_MIN (SPI_PERCLK2_DIV_MAX << 13) +#define SPI_CONTROL_DATARATE_MAX (SPI_PERCLK2_DIV_MIN << 13) +#define SPI_CONTROL_DATARATE_BAD (SPI_CONTROL_DATARATE_MIN + 1) + +/* SPI Interrupt/Status Register Bit Fields & Masks */ +#define SPI_STATUS_TE (0x1 << 0) /* TXFIFO Empty Status */ +#define SPI_STATUS_TH (0x1 << 1) /* TXFIFO Half Status */ +#define SPI_STATUS_TF (0x1 << 2) /* TXFIFO Full Status */ +#define SPI_STATUS_RR (0x1 << 3) /* RXFIFO Data Ready Status */ +#define SPI_STATUS_RH (0x1 << 4) /* RXFIFO Half Status */ +#define SPI_STATUS_RF (0x1 << 5) /* RXFIFO Full Status */ +#define SPI_STATUS_RO (0x1 << 6) /* RXFIFO Overflow */ +#define SPI_STATUS_BO (0x1 << 7) /* Bit Count Overflow */ +#define SPI_STATUS (0xFF) /* SPI Status Mask */ +#define SPI_INTEN_TE (0x1 << 8) /* TXFIFO Empty Interrupt Enable */ +#define SPI_INTEN_TH (0x1 << 9) /* TXFIFO Half Interrupt Enable */ +#define SPI_INTEN_TF (0x1 << 10) /* TXFIFO Full Interrupt Enable */ +#define SPI_INTEN_RE (0x1 << 11) /* RXFIFO Data Ready Interrupt Enable */ +#define SPI_INTEN_RH (0x1 << 12) /* RXFIFO Half Interrupt Enable */ +#define SPI_INTEN_RF (0x1 << 13) /* RXFIFO Full Interrupt Enable */ +#define SPI_INTEN_RO (0x1 << 14) /* RXFIFO Overflow Interrupt Enable */ +#define SPI_INTEN_BO (0x1 << 15) /* Bit Count Overflow Interrupt Enable */ +#define SPI_INTEN (0xFF << 8) /* SPI Interrupt Enable Mask */ + +/* SPI Test Register Bit Fields & Masks */ +#define SPI_TEST_TXCNT (0xF << 0) /* TXFIFO Counter */ +#define SPI_TEST_RXCNT_LSB (4) /* RXFIFO Counter LSB */ +#define SPI_TEST_RXCNT (0xF << 4) /* RXFIFO Counter */ +#define SPI_TEST_SSTATUS (0xF << 8) /* State Machine Status */ +#define SPI_TEST_LBC (0x1 << 14) /* Loop Back Control */ + +/* SPI Period Register Bit Fields & Masks */ +#define SPI_PERIOD_WAIT (0x7FFF << 0) /* Wait Between Transactions */ +#define SPI_PERIOD_MAX_WAIT (0x7FFF) /* Max Wait Between + Transactions */ +#define SPI_PERIOD_CSRC (0x1 << 15) /* Period Clock Source Mask */ +#define SPI_PERIOD_CSRC_BCLK (0x0 << 15) /* Period Clock Source is + Bit Clock */ +#define SPI_PERIOD_CSRC_32768 (0x1 << 15) /* Period Clock Source is + 32.768 KHz Clock */ + +/* SPI DMA Register Bit Fields & Masks */ +#define SPI_DMA_RHDMA (0x1 << 4) /* RXFIFO Half Status */ +#define SPI_DMA_RFDMA (0x1 << 5) /* RXFIFO Full Status */ +#define SPI_DMA_TEDMA (0x1 << 6) /* TXFIFO Empty Status */ +#define SPI_DMA_THDMA (0x1 << 7) /* TXFIFO Half Status */ +#define SPI_DMA_RHDEN (0x1 << 12) /* RXFIFO Half DMA Request Enable */ +#define SPI_DMA_RFDEN (0x1 << 13) /* RXFIFO Full DMA Request Enable */ +#define SPI_DMA_TEDEN (0x1 << 14) /* TXFIFO Empty DMA Request Enable */ +#define SPI_DMA_THDEN (0x1 << 15) /* TXFIFO Half DMA Request Enable */ + +/* SPI Soft Reset Register Bit Fields & Masks */ +#define SPI_RESET_START (0x1) /* Start */ + +/* Default SPI configuration values */ +#define SPI_DEFAULT_CONTROL \ +( \ + SPI_CONTROL_BITCOUNT(16) | \ + SPI_CONTROL_POL_ACT_HIGH | \ + SPI_CONTROL_PHA_0 | \ + SPI_CONTROL_SPIEN | \ + SPI_CONTROL_SSCTL_1 | \ + SPI_CONTROL_MODE_MASTER | \ + SPI_CONTROL_DRCTL_0 | \ + SPI_CONTROL_DATARATE_MIN \ +) +#define SPI_DEFAULT_ENABLE_LOOPBACK (0) +#define SPI_DEFAULT_ENABLE_DMA (0) +#define SPI_DEFAULT_PERIOD_WAIT (8) +/*-------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------*/ +/* TX/RX SPI FIFO size */ +#define SPI_FIFO_DEPTH (8) +#define SPI_FIFO_BYTE_WIDTH (2) +#define SPI_FIFO_OVERFLOW_MARGIN (2) + +/* DMA burst length for half full/empty request trigger */ +#define SPI_DMA_BLR (SPI_FIFO_DEPTH * SPI_FIFO_BYTE_WIDTH / 2) + +/* Dummy char output to achieve reads. + Choosing something different from all zeroes may help pattern recogition + for oscilloscope analysis, but may break some drivers. */ +#define SPI_DUMMY_u8 0 +#define SPI_DUMMY_u16 ((SPI_DUMMY_u8 << 8) | SPI_DUMMY_u8) +#define SPI_DUMMY_u32 ((SPI_DUMMY_u16 << 16) | SPI_DUMMY_u16) + +/** + * Macro to change a u32 field: + * @r : register to edit + * @m : bit mask + * @v : new value for the field correctly bit-alligned +*/ +#define u32_EDIT(r, m, v) r = (r & ~(m)) | (v) + +/* Message state */ +#define START_STATE ((void*)0) +#define RUNNING_STATE ((void*)1) +#define DONE_STATE ((void*)2) +#define ERROR_STATE ((void*)-1) + +/* Queue state */ +#define QUEUE_RUNNING (0) +#define QUEUE_STOPPED (1) + +#define IS_DMA_ALIGNED(x) (((u32)(x) & 0x03) == 0) +#define DMA_ALIGNMENT 4 +/*-------------------------------------------------------------------------*/ + + +/*-------------------------------------------------------------------------*/ +/* Driver data structs */ + +/* Context */ +struct driver_data { + /* Driver model hookup */ + struct platform_device *pdev; + + /* SPI framework hookup */ + struct spi_master *master; + + /* IMX hookup */ + struct spi_imx_master *master_info; + + /* Memory resources and SPI regs virtual address */ + struct resource *ioarea; + void __iomem *regs; + + /* SPI RX_DATA physical address */ + dma_addr_t rd_data_phys; + + /* Driver message queue */ + struct workqueue_struct *workqueue; + struct work_struct work; + spinlock_t lock; + struct list_head queue; + int busy; + int run; + + /* Message Transfer pump */ + struct tasklet_struct pump_transfers; + + /* Current message, transfer and state */ + struct spi_message *cur_msg; + struct spi_transfer *cur_transfer; + struct chip_data *cur_chip; + + /* Rd / Wr buffers pointers */ + size_t len; + void *tx; + void *tx_end; + void *rx; + void *rx_end; + + u8 rd_only; + u8 n_bytes; + int cs_change; + + /* Function pointers */ + irqreturn_t (*transfer_handler)(struct driver_data *drv_data); + void (*cs_control)(u32 command); + + /* DMA setup */ + int rx_channel; + int tx_channel; + dma_addr_t rx_dma; + dma_addr_t tx_dma; + int rx_dma_needs_unmap; + int tx_dma_needs_unmap; + size_t tx_map_len; + u32 dummy_dma_buf ____cacheline_aligned; + + struct clk *clk; +}; + +/* Runtime state */ +struct chip_data { + u32 control; + u32 period; + u32 test; + + u8 enable_dma:1; + u8 bits_per_word; + u8 n_bytes; + u32 max_speed_hz; + + void (*cs_control)(u32 command); +}; +/*-------------------------------------------------------------------------*/ + + +static void pump_messages(struct work_struct *work); + +static void flush(struct driver_data *drv_data) +{ + void __iomem *regs = drv_data->regs; + u32 control; + + dev_dbg(&drv_data->pdev->dev, "flush\n"); + + /* Wait for end of transaction */ + do { + control = readl(regs + SPI_CONTROL); + } while (control & SPI_CONTROL_XCH); + + /* Release chip select if requested, transfer delays are + handled in pump_transfers */ + if (drv_data->cs_change) + drv_data->cs_control(SPI_CS_DEASSERT); + + /* Disable SPI to flush FIFOs */ + writel(control & ~SPI_CONTROL_SPIEN, regs + SPI_CONTROL); + writel(control, regs + SPI_CONTROL); +} + +static void restore_state(struct driver_data *drv_data) +{ + void __iomem *regs = drv_data->regs; + struct chip_data *chip = drv_data->cur_chip; + + /* Load chip registers */ + dev_dbg(&drv_data->pdev->dev, + "restore_state\n" + " test = 0x%08X\n" + " control = 0x%08X\n", + chip->test, + chip->control); + writel(chip->test, regs + SPI_TEST); + writel(chip->period, regs + SPI_PERIOD); + writel(0, regs + SPI_INT_STATUS); + writel(chip->control, regs + SPI_CONTROL); +} + +static void null_cs_control(u32 command) +{ +} + +static inline u32 data_to_write(struct driver_data *drv_data) +{ + return ((u32)(drv_data->tx_end - drv_data->tx)) / drv_data->n_bytes; +} + +static inline u32 data_to_read(struct driver_data *drv_data) +{ + return ((u32)(drv_data->rx_end - drv_data->rx)) / drv_data->n_bytes; +} + +static int write(struct driver_data *drv_data) +{ + void __iomem *regs = drv_data->regs; + void *tx = drv_data->tx; + void *tx_end = drv_data->tx_end; + u8 n_bytes = drv_data->n_bytes; + u32 remaining_writes; + u32 fifo_avail_space; + u32 n; + u16 d; + + /* Compute how many fifo writes to do */ + remaining_writes = (u32)(tx_end - tx) / n_bytes; + fifo_avail_space = SPI_FIFO_DEPTH - + (readl(regs + SPI_TEST) & SPI_TEST_TXCNT); + if (drv_data->rx && (fifo_avail_space > SPI_FIFO_OVERFLOW_MARGIN)) + /* Fix misunderstood receive overflow */ + fifo_avail_space -= SPI_FIFO_OVERFLOW_MARGIN; + n = min(remaining_writes, fifo_avail_space); + + dev_dbg(&drv_data->pdev->dev, + "write type %s\n" + " remaining writes = %d\n" + " fifo avail space = %d\n" + " fifo writes = %d\n", + (n_bytes == 1) ? "u8" : "u16", + remaining_writes, + fifo_avail_space, + n); + + if (n > 0) { + /* Fill SPI TXFIFO */ + if (drv_data->rd_only) { + tx += n * n_bytes; + while (n--) + writel(SPI_DUMMY_u16, regs + SPI_TXDATA); + } else { + if (n_bytes == 1) { + while (n--) { + d = *(u8*)tx; + writel(d, regs + SPI_TXDATA); + tx += 1; + } + } else { + while (n--) { + d = *(u16*)tx; + writel(d, regs + SPI_TXDATA); + tx += 2; + } + } + } + + /* Trigger transfer */ + writel(readl(regs + SPI_CONTROL) | SPI_CONTROL_XCH, + regs + SPI_CONTROL); + + /* Update tx pointer */ + drv_data->tx = tx; + } + + return (tx >= tx_end); +} + +static int read(struct driver_data *drv_data) +{ + void __iomem *regs = drv_data->regs; + void *rx = drv_data->rx; + void *rx_end = drv_data->rx_end; + u8 n_bytes = drv_data->n_bytes; + u32 remaining_reads; + u32 fifo_rxcnt; + u32 n; + u16 d; + + /* Compute how many fifo reads to do */ + remaining_reads = (u32)(rx_end - rx) / n_bytes; + fifo_rxcnt = (readl(regs + SPI_TEST) & SPI_TEST_RXCNT) >> + SPI_TEST_RXCNT_LSB; + n = min(remaining_reads, fifo_rxcnt); + + dev_dbg(&drv_data->pdev->dev, + "read type %s\n" + " remaining reads = %d\n" + " fifo rx count = %d\n" + " fifo reads = %d\n", + (n_bytes == 1) ? "u8" : "u16", + remaining_reads, + fifo_rxcnt, + n); + + if (n > 0) { + /* Read SPI RXFIFO */ + if (n_bytes == 1) { + while (n--) { + d = readl(regs + SPI_RXDATA); + *((u8*)rx) = d; + rx += 1; + } + } else { + while (n--) { + d = readl(regs + SPI_RXDATA); + *((u16*)rx) = d; + rx += 2; + } + } + + /* Update rx pointer */ + drv_data->rx = rx; + } + + return (rx >= rx_end); +} + +static void *next_transfer(struct driver_data *drv_data) +{ + struct spi_message *msg = drv_data->cur_msg; + struct spi_transfer *trans = drv_data->cur_transfer; + + /* Move to next transfer */ + if (trans->transfer_list.next != &msg->transfers) { + drv_data->cur_transfer = + list_entry(trans->transfer_list.next, + struct spi_transfer, + transfer_list); + return RUNNING_STATE; + } + + return DONE_STATE; +} + +static int map_dma_buffers(struct driver_data *drv_data) +{ + struct spi_message *msg; + struct device *dev; + void *buf; + + drv_data->rx_dma_needs_unmap = 0; + drv_data->tx_dma_needs_unmap = 0; + + if (!drv_data->master_info->enable_dma || + !drv_data->cur_chip->enable_dma) + return -1; + + msg = drv_data->cur_msg; + dev = &msg->spi->dev; + if (msg->is_dma_mapped) { + if (drv_data->tx_dma) + /* The caller provided at least dma and cpu virtual + address for write; pump_transfers() will consider the + transfer as write only if cpu rx virtual address is + NULL */ + return 0; + + if (drv_data->rx_dma) { + /* The caller provided dma and cpu virtual address to + performe read only transfer --> + use drv_data->dummy_dma_buf for dummy writes to + achive reads */ + buf = &drv_data->dummy_dma_buf; + drv_data->tx_map_len = sizeof(drv_data->dummy_dma_buf); + drv_data->tx_dma = dma_map_single(dev, + buf, + drv_data->tx_map_len, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, drv_data->tx_dma)) + return -1; + + drv_data->tx_dma_needs_unmap = 1; + + /* Flags transfer as rd_only for pump_transfers() DMA + regs programming (should be redundant) */ + drv_data->tx = NULL; + + return 0; + } + } + + if (!IS_DMA_ALIGNED(drv_data->rx) || !IS_DMA_ALIGNED(drv_data->tx)) + return -1; + + if (drv_data->tx == NULL) { + /* Read only message --> use drv_data->dummy_dma_buf for dummy + writes to achive reads */ + buf = &drv_data->dummy_dma_buf; + drv_data->tx_map_len = sizeof(drv_data->dummy_dma_buf); + } else { + buf = drv_data->tx; + drv_data->tx_map_len = drv_data->len; + } + drv_data->tx_dma = dma_map_single(dev, + buf, + drv_data->tx_map_len, + DMA_TO_DEVICE); + if (dma_mapping_error(dev, drv_data->tx_dma)) + return -1; + drv_data->tx_dma_needs_unmap = 1; + + /* NULL rx means write-only transfer and no map needed + * since rx DMA will not be used */ + if (drv_data->rx) { + buf = drv_data->rx; + drv_data->rx_dma = dma_map_single(dev, + buf, + drv_data->len, + DMA_FROM_DEVICE); + if (dma_mapping_error(dev, drv_data->rx_dma)) { + if (drv_data->tx_dma) { + dma_unmap_single(dev, + drv_data->tx_dma, + drv_data->tx_map_len, + DMA_TO_DEVICE); + drv_data->tx_dma_needs_unmap = 0; + } + return -1; + } + drv_data->rx_dma_needs_unmap = 1; + } + + return 0; +} + +static void unmap_dma_buffers(struct driver_data *drv_data) +{ + struct spi_message *msg = drv_data->cur_msg; + struct device *dev = &msg->spi->dev; + + if (drv_data->rx_dma_needs_unmap) { + dma_unmap_single(dev, + drv_data->rx_dma, + drv_data->len, + DMA_FROM_DEVICE); + drv_data->rx_dma_needs_unmap = 0; + } + if (drv_data->tx_dma_needs_unmap) { + dma_unmap_single(dev, + drv_data->tx_dma, + drv_data->tx_map_len, + DMA_TO_DEVICE); + drv_data->tx_dma_needs_unmap = 0; + } +} + +/* Caller already set message->status (dma is already blocked) */ +static void giveback(struct spi_message *message, struct driver_data *drv_data) +{ + void __iomem *regs = drv_data->regs; + + /* Bring SPI to sleep; restore_state() and pump_transfer() + will do new setup */ + writel(0, regs + SPI_INT_STATUS); + writel(0, regs + SPI_DMA); + + /* Unconditioned deselct */ + drv_data->cs_control(SPI_CS_DEASSERT); + + message->state = NULL; + if (message->complete) + message->complete(message->context); + + drv_data->cur_msg = NULL; + drv_data->cur_transfer = NULL; + drv_data->cur_chip = NULL; + queue_work(drv_data->workqueue, &drv_data->work); +} + +static void dma_err_handler(int channel, void *data, int errcode) +{ + struct driver_data *drv_data = data; + struct spi_message *msg = drv_data->cur_msg; + + dev_dbg(&drv_data->pdev->dev, "dma_err_handler\n"); + + /* Disable both rx and tx dma channels */ + imx_dma_disable(drv_data->rx_channel); + imx_dma_disable(drv_data->tx_channel); + unmap_dma_buffers(drv_data); + + flush(drv_data); + + msg->state = ERROR_STATE; + tasklet_schedule(&drv_data->pump_transfers); +} + +static void dma_tx_handler(int channel, void *data) +{ + struct driver_data *drv_data = data; + + dev_dbg(&drv_data->pdev->dev, "dma_tx_handler\n"); + + imx_dma_disable(channel); + + /* Now waits for TX FIFO empty */ + writel(SPI_INTEN_TE, drv_data->regs + SPI_INT_STATUS); +} + +static irqreturn_t dma_transfer(struct driver_data *drv_data) +{ + u32 status; + struct spi_message *msg = drv_data->cur_msg; + void __iomem *regs = drv_data->regs; + + status = readl(regs + SPI_INT_STATUS); + + if ((status & (SPI_INTEN_RO | SPI_STATUS_RO)) + == (SPI_INTEN_RO | SPI_STATUS_RO)) { + writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS); + + imx_dma_disable(drv_data->tx_channel); + imx_dma_disable(drv_data->rx_channel); + unmap_dma_buffers(drv_data); + + flush(drv_data); + + dev_warn(&drv_data->pdev->dev, + "dma_transfer - fifo overun\n"); + + msg->state = ERROR_STATE; + tasklet_schedule(&drv_data->pump_transfers); + + return IRQ_HANDLED; + } + + if (status & SPI_STATUS_TE) { + writel(status & ~SPI_INTEN_TE, regs + SPI_INT_STATUS); + + if (drv_data->rx) { + /* Wait end of transfer before read trailing data */ + while (readl(regs + SPI_CONTROL) & SPI_CONTROL_XCH) + cpu_relax(); + + imx_dma_disable(drv_data->rx_channel); + unmap_dma_buffers(drv_data); + + /* Release chip select if requested, transfer delays are + handled in pump_transfers() */ + if (drv_data->cs_change) + drv_data->cs_control(SPI_CS_DEASSERT); + + /* Calculate number of trailing data and read them */ + dev_dbg(&drv_data->pdev->dev, + "dma_transfer - test = 0x%08X\n", + readl(regs + SPI_TEST)); + drv_data->rx = drv_data->rx_end - + ((readl(regs + SPI_TEST) & + SPI_TEST_RXCNT) >> + SPI_TEST_RXCNT_LSB)*drv_data->n_bytes; + read(drv_data); + } else { + /* Write only transfer */ + unmap_dma_buffers(drv_data); + + flush(drv_data); + } + + /* End of transfer, update total byte transfered */ + msg->actual_length += drv_data->len; + + /* Move to next transfer */ + msg->state = next_transfer(drv_data); + + /* Schedule transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); + + return IRQ_HANDLED; + } + + /* Opps problem detected */ + return IRQ_NONE; +} + +static irqreturn_t interrupt_wronly_transfer(struct driver_data *drv_data) +{ + struct spi_message *msg = drv_data->cur_msg; + void __iomem *regs = drv_data->regs; + u32 status; + irqreturn_t handled = IRQ_NONE; + + status = readl(regs + SPI_INT_STATUS); + + if (status & SPI_INTEN_TE) { + /* TXFIFO Empty Interrupt on the last transfered word */ + writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS); + dev_dbg(&drv_data->pdev->dev, + "interrupt_wronly_transfer - end of tx\n"); + + flush(drv_data); + + /* Update total byte transfered */ + msg->actual_length += drv_data->len; + + /* Move to next transfer */ + msg->state = next_transfer(drv_data); + + /* Schedule transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); + + return IRQ_HANDLED; + } else { + while (status & SPI_STATUS_TH) { + dev_dbg(&drv_data->pdev->dev, + "interrupt_wronly_transfer - status = 0x%08X\n", + status); + + /* Pump data */ + if (write(drv_data)) { + /* End of TXFIFO writes, + now wait until TXFIFO is empty */ + writel(SPI_INTEN_TE, regs + SPI_INT_STATUS); + return IRQ_HANDLED; + } + + status = readl(regs + SPI_INT_STATUS); + + /* We did something */ + handled = IRQ_HANDLED; + } + } + + return handled; +} + +static irqreturn_t interrupt_transfer(struct driver_data *drv_data) +{ + struct spi_message *msg = drv_data->cur_msg; + void __iomem *regs = drv_data->regs; + u32 status, control; + irqreturn_t handled = IRQ_NONE; + unsigned long limit; + + status = readl(regs + SPI_INT_STATUS); + + if (status & SPI_INTEN_TE) { + /* TXFIFO Empty Interrupt on the last transfered word */ + writel(status & ~SPI_INTEN, regs + SPI_INT_STATUS); + dev_dbg(&drv_data->pdev->dev, + "interrupt_transfer - end of tx\n"); + + if (msg->state == ERROR_STATE) { + /* RXFIFO overrun was detected and message aborted */ + flush(drv_data); + } else { + /* Wait for end of transaction */ + do { + control = readl(regs + SPI_CONTROL); + } while (control & SPI_CONTROL_XCH); + + /* Release chip select if requested, transfer delays are + handled in pump_transfers */ + if (drv_data->cs_change) + drv_data->cs_control(SPI_CS_DEASSERT); + + /* Read trailing bytes */ + limit = loops_per_jiffy << 1; + while ((read(drv_data) == 0) && --limit) + cpu_relax(); + + if (limit == 0) + dev_err(&drv_data->pdev->dev, + "interrupt_transfer - " + "trailing byte read failed\n"); + else + dev_dbg(&drv_data->pdev->dev, + "interrupt_transfer - end of rx\n"); + + /* Update total byte transfered */ + msg->actual_length += drv_data->len; + + /* Move to next transfer */ + msg->state = next_transfer(drv_data); + } + + /* Schedule transfer tasklet */ + tasklet_schedule(&drv_data->pump_transfers); + + return IRQ_HANDLED; + } else { + while (status & (SPI_STATUS_TH | SPI_STATUS_RO)) { + dev_dbg(&drv_data->pdev->dev, + "interrupt_transfer - status = 0x%08X\n", + status); + + if (status & SPI_STATUS_RO) { + /* RXFIFO overrun, abort message end wait + until TXFIFO is empty */ + writel(SPI_INTEN_TE, regs + SPI_INT_STATUS); + + dev_warn(&drv_data->pdev->dev, + "interrupt_transfer - fifo overun\n" + " data not yet written = %d\n" + " data not yet read = %d\n", + data_to_write(drv_data), + data_to_read(drv_data)); + + msg->state = ERROR_STATE; + + return IRQ_HANDLED; + } + + /* Pump data */ + read(drv_data); + if (write(drv_data)) { + /* End of TXFIFO writes, + now wait until TXFIFO is empty */ + writel(SPI_INTEN_TE, regs + SPI_INT_STATUS); + return IRQ_HANDLED; + } + + status = readl(regs + SPI_INT_STATUS); + + /* We did something */ + handled = IRQ_HANDLED; + } + } + + return handled; +} + +static irqreturn_t spi_int(int irq, void *dev_id) +{ + struct driver_data *drv_data = (struct driver_data *)dev_id; + + if (!drv_data->cur_msg) { + dev_err(&drv_data->pdev->dev, + "spi_int - bad message state\n"); + /* Never fail */ + return IRQ_HANDLED; + } + + return drv_data->transfer_handler(drv_data); +} + +static inline u32 spi_speed_hz(struct driver_data *drv_data, u32 data_rate) +{ + return clk_get_rate(drv_data->clk) / (4 << ((data_rate) >> 13)); +} + +static u32 spi_data_rate(struct driver_data *drv_data, u32 speed_hz) +{ + u32 div; + u32 quantized_hz = clk_get_rate(drv_data->clk) >> 2; + + for (div = SPI_PERCLK2_DIV_MIN; + div <= SPI_PERCLK2_DIV_MAX; + div++, quantized_hz >>= 1) { + if (quantized_hz <= speed_hz) + /* Max available speed LEQ required speed */ + return div << 13; + } + return SPI_CONTROL_DATARATE_BAD; +} + +static void pump_transfers(unsigned long data) +{ + struct driver_data *drv_data = (struct driver_data *)data; + struct spi_message *message; + struct spi_transfer *transfer, *previous; + struct chip_data *chip; + void __iomem *regs; + u32 tmp, control; + + dev_dbg(&drv_data->pdev->dev, "pump_transfer\n"); + + message = drv_data->cur_msg; + + /* Handle for abort */ + if (message->state == ERROR_STATE) { + message->status = -EIO; + giveback(message, drv_data); + return; + } + + /* Handle end of message */ + if (message->state == DONE_STATE) { + message->status = 0; + giveback(message, drv_data); + return; + } + + chip = drv_data->cur_chip; + + /* Delay if requested at end of transfer*/ + transfer = drv_data->cur_transfer; + if (message->state == RUNNING_STATE) { + previous = list_entry(transfer->transfer_list.prev, + struct spi_transfer, + transfer_list); + if (previous->delay_usecs) + udelay(previous->delay_usecs); + } else { + /* START_STATE */ + message->state = RUNNING_STATE; + drv_data->cs_control = chip->cs_control; + } + + transfer = drv_data->cur_transfer; + drv_data->tx = (void *)transfer->tx_buf; + drv_data->tx_end = drv_data->tx + transfer->len; + drv_data->rx = transfer->rx_buf; + drv_data->rx_end = drv_data->rx + transfer->len; + drv_data->rx_dma = transfer->rx_dma; + drv_data->tx_dma = transfer->tx_dma; + drv_data->len = transfer->len; + drv_data->cs_change = transfer->cs_change; + drv_data->rd_only = (drv_data->tx == NULL); + + regs = drv_data->regs; + control = readl(regs + SPI_CONTROL); + + /* Bits per word setup */ + tmp = transfer->bits_per_word; + if (tmp == 0) { + /* Use device setup */ + tmp = chip->bits_per_word; + drv_data->n_bytes = chip->n_bytes; + } else + /* Use per-transfer setup */ + drv_data->n_bytes = (tmp <= 8) ? 1 : 2; + u32_EDIT(control, SPI_CONTROL_BITCOUNT_MASK, tmp - 1); + + /* Speed setup (surely valid because already checked) */ + tmp = transfer->speed_hz; + if (tmp == 0) + tmp = chip->max_speed_hz; + tmp = spi_data_rate(drv_data, tmp); + u32_EDIT(control, SPI_CONTROL_DATARATE, tmp); + + writel(control, regs + SPI_CONTROL); + + /* Assert device chip-select */ + drv_data->cs_control(SPI_CS_ASSERT); + + /* DMA cannot read/write SPI FIFOs other than 16 bits at a time; hence + if bits_per_word is less or equal 8 PIO transfers are performed. + Moreover DMA is convinient for transfer length bigger than FIFOs + byte size. */ + if ((drv_data->n_bytes == 2) && + (drv_data->len > SPI_FIFO_DEPTH*SPI_FIFO_BYTE_WIDTH) && + (map_dma_buffers(drv_data) == 0)) { + dev_dbg(&drv_data->pdev->dev, + "pump dma transfer\n" + " tx = %p\n" + " tx_dma = %08X\n" + " rx = %p\n" + " rx_dma = %08X\n" + " len = %d\n", + drv_data->tx, + (unsigned int)drv_data->tx_dma, + drv_data->rx, + (unsigned int)drv_data->rx_dma, + drv_data->len); + + /* Ensure we have the correct interrupt handler */ + drv_data->transfer_handler = dma_transfer; + + /* Trigger transfer */ + writel(readl(regs + SPI_CONTROL) | SPI_CONTROL_XCH, + regs + SPI_CONTROL); + + /* Setup tx DMA */ + if (drv_data->tx) + /* Linear source address */ + CCR(drv_data->tx_channel) = + CCR_DMOD_FIFO | + CCR_SMOD_LINEAR | + CCR_SSIZ_32 | CCR_DSIZ_16 | + CCR_REN; + else + /* Read only transfer -> fixed source address for + dummy write to achive read */ + CCR(drv_data->tx_channel) = + CCR_DMOD_FIFO | + CCR_SMOD_FIFO | + CCR_SSIZ_32 | CCR_DSIZ_16 | + CCR_REN; + + imx_dma_setup_single( + drv_data->tx_channel, + drv_data->tx_dma, + drv_data->len, + drv_data->rd_data_phys + 4, + DMA_MODE_WRITE); + + if (drv_data->rx) { + /* Setup rx DMA for linear destination address */ + CCR(drv_data->rx_channel) = + CCR_DMOD_LINEAR | + CCR_SMOD_FIFO | + CCR_DSIZ_32 | CCR_SSIZ_16 | + CCR_REN; + imx_dma_setup_single( + drv_data->rx_channel, + drv_data->rx_dma, + drv_data->len, + drv_data->rd_data_phys, + DMA_MODE_READ); + imx_dma_enable(drv_data->rx_channel); + + /* Enable SPI interrupt */ + writel(SPI_INTEN_RO, regs + SPI_INT_STATUS); + + /* Set SPI to request DMA service on both + Rx and Tx half fifo watermark */ + writel(SPI_DMA_RHDEN | SPI_DMA_THDEN, regs + SPI_DMA); + } else + /* Write only access -> set SPI to request DMA + service on Tx half fifo watermark */ + writel(SPI_DMA_THDEN, regs + SPI_DMA); + + imx_dma_enable(drv_data->tx_channel); + } else { + dev_dbg(&drv_data->pdev->dev, + "pump pio transfer\n" + " tx = %p\n" + " rx = %p\n" + " len = %d\n", + drv_data->tx, + drv_data->rx, + drv_data->len); + + /* Ensure we have the correct interrupt handler */ + if (drv_data->rx) + drv_data->transfer_handler = interrupt_transfer; + else + drv_data->transfer_handler = interrupt_wronly_transfer; + + /* Enable SPI interrupt */ + if (drv_data->rx) + writel(SPI_INTEN_TH | SPI_INTEN_RO, + regs + SPI_INT_STATUS); + else + writel(SPI_INTEN_TH, regs + SPI_INT_STATUS); + } +} + +static void pump_messages(struct work_struct *work) +{ + struct driver_data *drv_data = + container_of(work, struct driver_data, work); + unsigned long flags; + + /* Lock queue and check for queue work */ + spin_lock_irqsave(&drv_data->lock, flags); + if (list_empty(&drv_data->queue) || drv_data->run == QUEUE_STOPPED) { + drv_data->busy = 0; + spin_unlock_irqrestore(&drv_data->lock, flags); + return; + } + + /* Make sure we are not already running a message */ + if (drv_data->cur_msg) { + spin_unlock_irqrestore(&drv_data->lock, flags); + return; + } + + /* Extract head of queue */ + drv_data->cur_msg = list_entry(drv_data->queue.next, + struct spi_message, queue); + list_del_init(&drv_data->cur_msg->queue); + drv_data->busy = 1; + spin_unlock_irqrestore(&drv_data->lock, flags); + + /* Initial message state */ + drv_data->cur_msg->state = START_STATE; + drv_data->cur_transfer = list_entry(drv_data->cur_msg->transfers.next, + struct spi_transfer, + transfer_list); + + /* Setup the SPI using the per chip configuration */ + drv_data->cur_chip = spi_get_ctldata(drv_data->cur_msg->spi); + restore_state(drv_data); + + /* Mark as busy and launch transfers */ + tasklet_schedule(&drv_data->pump_transfers); +} + +static int transfer(struct spi_device *spi, struct spi_message *msg) +{ + struct driver_data *drv_data = spi_master_get_devdata(spi->master); + u32 min_speed_hz, max_speed_hz, tmp; + struct spi_transfer *trans; + unsigned long flags; + + msg->actual_length = 0; + + /* Per transfer setup check */ + min_speed_hz = spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN); + max_speed_hz = spi->max_speed_hz; + list_for_each_entry(trans, &msg->transfers, transfer_list) { + tmp = trans->bits_per_word; + if (tmp > 16) { + dev_err(&drv_data->pdev->dev, + "message rejected : " + "invalid transfer bits_per_word (%d bits)\n", + tmp); + goto msg_rejected; + } + tmp = trans->speed_hz; + if (tmp) { + if (tmp < min_speed_hz) { + dev_err(&drv_data->pdev->dev, + "message rejected : " + "device min speed (%d Hz) exceeds " + "required transfer speed (%d Hz)\n", + min_speed_hz, + tmp); + goto msg_rejected; + } else if (tmp > max_speed_hz) { + dev_err(&drv_data->pdev->dev, + "message rejected : " + "transfer speed (%d Hz) exceeds " + "device max speed (%d Hz)\n", + tmp, + max_speed_hz); + goto msg_rejected; + } + } + } + + /* Message accepted */ + msg->status = -EINPROGRESS; + msg->state = START_STATE; + + spin_lock_irqsave(&drv_data->lock, flags); + if (drv_data->run == QUEUE_STOPPED) { + spin_unlock_irqrestore(&drv_data->lock, flags); + return -ESHUTDOWN; + } + + list_add_tail(&msg->queue, &drv_data->queue); + if (drv_data->run == QUEUE_RUNNING && !drv_data->busy) + queue_work(drv_data->workqueue, &drv_data->work); + + spin_unlock_irqrestore(&drv_data->lock, flags); + return 0; + +msg_rejected: + /* Message rejected and not queued */ + msg->status = -EINVAL; + msg->state = ERROR_STATE; + if (msg->complete) + msg->complete(msg->context); + return -EINVAL; +} + +/* On first setup bad values must free chip_data memory since will cause + spi_new_device to fail. Bad value setup from protocol driver are simply not + applied and notified to the calling driver. */ +static int setup(struct spi_device *spi) +{ + struct driver_data *drv_data = spi_master_get_devdata(spi->master); + struct spi_imx_chip *chip_info; + struct chip_data *chip; + int first_setup = 0; + u32 tmp; + int status = 0; + + /* Get controller data */ + chip_info = spi->controller_data; + + /* Get controller_state */ + chip = spi_get_ctldata(spi); + if (chip == NULL) { + first_setup = 1; + + chip = kzalloc(sizeof(struct chip_data), GFP_KERNEL); + if (!chip) { + dev_err(&spi->dev, + "setup - cannot allocate controller state\n"); + return -ENOMEM; + } + chip->control = SPI_DEFAULT_CONTROL; + + if (chip_info == NULL) { + /* spi_board_info.controller_data not is supplied */ + chip_info = kzalloc(sizeof(struct spi_imx_chip), + GFP_KERNEL); + if (!chip_info) { + dev_err(&spi->dev, + "setup - " + "cannot allocate controller data\n"); + status = -ENOMEM; + goto err_first_setup; + } + /* Set controller data default value */ + chip_info->enable_loopback = + SPI_DEFAULT_ENABLE_LOOPBACK; + chip_info->enable_dma = SPI_DEFAULT_ENABLE_DMA; + chip_info->ins_ss_pulse = 1; + chip_info->bclk_wait = SPI_DEFAULT_PERIOD_WAIT; + chip_info->cs_control = null_cs_control; + } + } + + /* Now set controller state based on controller data */ + + if (first_setup) { + /* SPI loopback */ + if (chip_info->enable_loopback) + chip->test = SPI_TEST_LBC; + else + chip->test = 0; + + /* SPI dma driven */ + chip->enable_dma = chip_info->enable_dma; + + /* SPI /SS pulse between spi burst */ + if (chip_info->ins_ss_pulse) + u32_EDIT(chip->control, + SPI_CONTROL_SSCTL, SPI_CONTROL_SSCTL_1); + else + u32_EDIT(chip->control, + SPI_CONTROL_SSCTL, SPI_CONTROL_SSCTL_0); + + /* SPI bclk waits between each bits_per_word spi burst */ + if (chip_info->bclk_wait > SPI_PERIOD_MAX_WAIT) { + dev_err(&spi->dev, + "setup - " + "bclk_wait exceeds max allowed (%d)\n", + SPI_PERIOD_MAX_WAIT); + goto err_first_setup; + } + chip->period = SPI_PERIOD_CSRC_BCLK | + (chip_info->bclk_wait & SPI_PERIOD_WAIT); + } + + /* SPI mode */ + tmp = spi->mode; + if (tmp & SPI_CS_HIGH) { + u32_EDIT(chip->control, + SPI_CONTROL_SSPOL, SPI_CONTROL_SSPOL_ACT_HIGH); + } + switch (tmp & SPI_MODE_3) { + case SPI_MODE_0: + tmp = 0; + break; + case SPI_MODE_1: + tmp = SPI_CONTROL_PHA_1; + break; + case SPI_MODE_2: + tmp = SPI_CONTROL_POL_ACT_LOW; + break; + default: + /* SPI_MODE_3 */ + tmp = SPI_CONTROL_PHA_1 | SPI_CONTROL_POL_ACT_LOW; + break; + } + u32_EDIT(chip->control, SPI_CONTROL_POL | SPI_CONTROL_PHA, tmp); + + /* SPI word width */ + tmp = spi->bits_per_word; + if (tmp > 16) { + status = -EINVAL; + dev_err(&spi->dev, + "setup - " + "invalid bits_per_word (%d)\n", + tmp); + if (first_setup) + goto err_first_setup; + else { + /* Undo setup using chip as backup copy */ + tmp = chip->bits_per_word; + spi->bits_per_word = tmp; + } + } + chip->bits_per_word = tmp; + u32_EDIT(chip->control, SPI_CONTROL_BITCOUNT_MASK, tmp - 1); + chip->n_bytes = (tmp <= 8) ? 1 : 2; + + /* SPI datarate */ + tmp = spi_data_rate(drv_data, spi->max_speed_hz); + if (tmp == SPI_CONTROL_DATARATE_BAD) { + status = -EINVAL; + dev_err(&spi->dev, + "setup - " + "HW min speed (%d Hz) exceeds required " + "max speed (%d Hz)\n", + spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN), + spi->max_speed_hz); + if (first_setup) + goto err_first_setup; + else + /* Undo setup using chip as backup copy */ + spi->max_speed_hz = chip->max_speed_hz; + } else { + u32_EDIT(chip->control, SPI_CONTROL_DATARATE, tmp); + /* Actual rounded max_speed_hz */ + tmp = spi_speed_hz(drv_data, tmp); + spi->max_speed_hz = tmp; + chip->max_speed_hz = tmp; + } + + /* SPI chip-select management */ + if (chip_info->cs_control) + chip->cs_control = chip_info->cs_control; + else + chip->cs_control = null_cs_control; + + /* Save controller_state */ + spi_set_ctldata(spi, chip); + + /* Summary */ + dev_dbg(&spi->dev, + "setup succeded\n" + " loopback enable = %s\n" + " dma enable = %s\n" + " insert /ss pulse = %s\n" + " period wait = %d\n" + " mode = %d\n" + " bits per word = %d\n" + " min speed = %d Hz\n" + " rounded max speed = %d Hz\n", + chip->test & SPI_TEST_LBC ? "Yes" : "No", + chip->enable_dma ? "Yes" : "No", + chip->control & SPI_CONTROL_SSCTL ? "Yes" : "No", + chip->period & SPI_PERIOD_WAIT, + spi->mode, + spi->bits_per_word, + spi_speed_hz(drv_data, SPI_CONTROL_DATARATE_MIN), + spi->max_speed_hz); + return status; + +err_first_setup: + kfree(chip); + return status; +} + +static void cleanup(struct spi_device *spi) +{ + kfree(spi_get_ctldata(spi)); +} + +static int __init init_queue(struct driver_data *drv_data) +{ + INIT_LIST_HEAD(&drv_data->queue); + spin_lock_init(&drv_data->lock); + + drv_data->run = QUEUE_STOPPED; + drv_data->busy = 0; + + tasklet_init(&drv_data->pump_transfers, + pump_transfers, (unsigned long)drv_data); + + INIT_WORK(&drv_data->work, pump_messages); + drv_data->workqueue = create_singlethread_workqueue( + dev_name(drv_data->master->dev.parent)); + if (drv_data->workqueue == NULL) + return -EBUSY; + + return 0; +} + +static int start_queue(struct driver_data *drv_data) +{ + unsigned long flags; + + spin_lock_irqsave(&drv_data->lock, flags); + + if (drv_data->run == QUEUE_RUNNING || drv_data->busy) { + spin_unlock_irqrestore(&drv_data->lock, flags); + return -EBUSY; + } + + drv_data->run = QUEUE_RUNNING; + drv_data->cur_msg = NULL; + drv_data->cur_transfer = NULL; + drv_data->cur_chip = NULL; + spin_unlock_irqrestore(&drv_data->lock, flags); + + queue_work(drv_data->workqueue, &drv_data->work); + + return 0; +} + +static int stop_queue(struct driver_data *drv_data) +{ + unsigned long flags; + unsigned limit = 500; + int status = 0; + + spin_lock_irqsave(&drv_data->lock, flags); + + /* This is a bit lame, but is optimized for the common execution path. + * A wait_queue on the drv_data->busy could be used, but then the common + * execution path (pump_messages) would be required to call wake_up or + * friends on every SPI message. Do this instead */ + drv_data->run = QUEUE_STOPPED; + while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) { + spin_unlock_irqrestore(&drv_data->lock, flags); + msleep(10); + spin_lock_irqsave(&drv_data->lock, flags); + } + + if (!list_empty(&drv_data->queue) || drv_data->busy) + status = -EBUSY; + + spin_unlock_irqrestore(&drv_data->lock, flags); + + return status; +} + +static int destroy_queue(struct driver_data *drv_data) +{ + int status; + + status = stop_queue(drv_data); + if (status != 0) + return status; + + if (drv_data->workqueue) + destroy_workqueue(drv_data->workqueue); + + return 0; +} + +static int __init spi_imx_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct spi_imx_master *platform_info; + struct spi_master *master; + struct driver_data *drv_data; + struct resource *res; + int irq, status = 0; + + platform_info = dev->platform_data; + if (platform_info == NULL) { + dev_err(&pdev->dev, "probe - no platform data supplied\n"); + status = -ENODEV; + goto err_no_pdata; + } + + /* Allocate master with space for drv_data */ + master = spi_alloc_master(dev, sizeof(struct driver_data)); + if (!master) { + dev_err(&pdev->dev, "probe - cannot alloc spi_master\n"); + status = -ENOMEM; + goto err_no_mem; + } + drv_data = spi_master_get_devdata(master); + drv_data->master = master; + drv_data->master_info = platform_info; + drv_data->pdev = pdev; + + /* the spi->mode bits understood by this driver: */ + master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH; + + master->bus_num = pdev->id; + master->num_chipselect = platform_info->num_chipselect; + master->dma_alignment = DMA_ALIGNMENT; + master->cleanup = cleanup; + master->setup = setup; + master->transfer = transfer; + + drv_data->dummy_dma_buf = SPI_DUMMY_u32; + + drv_data->clk = clk_get(&pdev->dev, "perclk2"); + if (IS_ERR(drv_data->clk)) { + dev_err(&pdev->dev, "probe - cannot get clock\n"); + status = PTR_ERR(drv_data->clk); + goto err_no_clk; + } + clk_enable(drv_data->clk); + + /* Find and map resources */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (!res) { + dev_err(&pdev->dev, "probe - MEM resources not defined\n"); + status = -ENODEV; + goto err_no_iores; + } + drv_data->ioarea = request_mem_region(res->start, + res->end - res->start + 1, + pdev->name); + if (drv_data->ioarea == NULL) { + dev_err(&pdev->dev, "probe - cannot reserve region\n"); + status = -ENXIO; + goto err_no_iores; + } + drv_data->regs = ioremap(res->start, res->end - res->start + 1); + if (drv_data->regs == NULL) { + dev_err(&pdev->dev, "probe - cannot map IO\n"); + status = -ENXIO; + goto err_no_iomap; + } + drv_data->rd_data_phys = (dma_addr_t)res->start; + + /* Attach to IRQ */ + irq = platform_get_irq(pdev, 0); + if (irq < 0) { + dev_err(&pdev->dev, "probe - IRQ resource not defined\n"); + status = -ENODEV; + goto err_no_irqres; + } + status = request_irq(irq, spi_int, IRQF_DISABLED, + dev_name(dev), drv_data); + if (status < 0) { + dev_err(&pdev->dev, "probe - cannot get IRQ (%d)\n", status); + goto err_no_irqres; + } + + /* Setup DMA if requested */ + drv_data->tx_channel = -1; + drv_data->rx_channel = -1; + if (platform_info->enable_dma) { + /* Get rx DMA channel */ + drv_data->rx_channel = imx_dma_request_by_prio("spi_imx_rx", + DMA_PRIO_HIGH); + if (drv_data->rx_channel < 0) { + dev_err(dev, + "probe - problem (%d) requesting rx channel\n", + drv_data->rx_channel); + goto err_no_rxdma; + } else + imx_dma_setup_handlers(drv_data->rx_channel, NULL, + dma_err_handler, drv_data); + + /* Get tx DMA channel */ + drv_data->tx_channel = imx_dma_request_by_prio("spi_imx_tx", + DMA_PRIO_MEDIUM); + if (drv_data->tx_channel < 0) { + dev_err(dev, + "probe - problem (%d) requesting tx channel\n", + drv_data->tx_channel); + imx_dma_free(drv_data->rx_channel); + goto err_no_txdma; + } else + imx_dma_setup_handlers(drv_data->tx_channel, + dma_tx_handler, dma_err_handler, + drv_data); + + /* Set request source and burst length for allocated channels */ + switch (drv_data->pdev->id) { + case 1: + /* Using SPI1 */ + RSSR(drv_data->rx_channel) = DMA_REQ_SPI1_R; + RSSR(drv_data->tx_channel) = DMA_REQ_SPI1_T; + break; + case 2: + /* Using SPI2 */ + RSSR(drv_data->rx_channel) = DMA_REQ_SPI2_R; + RSSR(drv_data->tx_channel) = DMA_REQ_SPI2_T; + break; + default: + dev_err(dev, "probe - bad SPI Id\n"); + imx_dma_free(drv_data->rx_channel); + imx_dma_free(drv_data->tx_channel); + status = -ENODEV; + goto err_no_devid; + } + BLR(drv_data->rx_channel) = SPI_DMA_BLR; + BLR(drv_data->tx_channel) = SPI_DMA_BLR; + } + + /* Load default SPI configuration */ + writel(SPI_RESET_START, drv_data->regs + SPI_RESET); + writel(0, drv_data->regs + SPI_RESET); + writel(SPI_DEFAULT_CONTROL, drv_data->regs + SPI_CONTROL); + + /* Initial and start queue */ + status = init_queue(drv_data); + if (status != 0) { + dev_err(&pdev->dev, "probe - problem initializing queue\n"); + goto err_init_queue; + } + status = start_queue(drv_data); + if (status != 0) { + dev_err(&pdev->dev, "probe - problem starting queue\n"); + goto err_start_queue; + } + + /* Register with the SPI framework */ + platform_set_drvdata(pdev, drv_data); + status = spi_register_master(master); + if (status != 0) { + dev_err(&pdev->dev, "probe - problem registering spi master\n"); + goto err_spi_register; + } + + dev_dbg(dev, "probe succeded\n"); + return 0; + +err_init_queue: +err_start_queue: +err_spi_register: + destroy_queue(drv_data); + +err_no_rxdma: +err_no_txdma: +err_no_devid: + free_irq(irq, drv_data); + +err_no_irqres: + iounmap(drv_data->regs); + +err_no_iomap: + release_resource(drv_data->ioarea); + kfree(drv_data->ioarea); + +err_no_iores: + clk_disable(drv_data->clk); + clk_put(drv_data->clk); + +err_no_clk: + spi_master_put(master); + +err_no_pdata: +err_no_mem: + return status; +} + +static int __exit spi_imx_remove(struct platform_device *pdev) +{ + struct driver_data *drv_data = platform_get_drvdata(pdev); + int irq; + int status = 0; + + if (!drv_data) + return 0; + + tasklet_kill(&drv_data->pump_transfers); + + /* Remove the queue */ + status = destroy_queue(drv_data); + if (status != 0) { + dev_err(&pdev->dev, "queue remove failed (%d)\n", status); + return status; + } + + /* Reset SPI */ + writel(SPI_RESET_START, drv_data->regs + SPI_RESET); + writel(0, drv_data->regs + SPI_RESET); + + /* Release DMA */ + if (drv_data->master_info->enable_dma) { + RSSR(drv_data->rx_channel) = 0; + RSSR(drv_data->tx_channel) = 0; + imx_dma_free(drv_data->tx_channel); + imx_dma_free(drv_data->rx_channel); + } + + /* Release IRQ */ + irq = platform_get_irq(pdev, 0); + if (irq >= 0) + free_irq(irq, drv_data); + + clk_disable(drv_data->clk); + clk_put(drv_data->clk); + + /* Release map resources */ + iounmap(drv_data->regs); + release_resource(drv_data->ioarea); + kfree(drv_data->ioarea); + + /* Disconnect from the SPI framework */ + spi_unregister_master(drv_data->master); + spi_master_put(drv_data->master); + + /* Prevent double remove */ + platform_set_drvdata(pdev, NULL); + + dev_dbg(&pdev->dev, "remove succeded\n"); + + return 0; +} + +static void spi_imx_shutdown(struct platform_device *pdev) +{ + struct driver_data *drv_data = platform_get_drvdata(pdev); + + /* Reset SPI */ + writel(SPI_RESET_START, drv_data->regs + SPI_RESET); + writel(0, drv_data->regs + SPI_RESET); + + dev_dbg(&pdev->dev, "shutdown succeded\n"); +} + +#ifdef CONFIG_PM + +static int spi_imx_suspend(struct platform_device *pdev, pm_message_t state) +{ + struct driver_data *drv_data = platform_get_drvdata(pdev); + int status = 0; + + status = stop_queue(drv_data); + if (status != 0) { + dev_warn(&pdev->dev, "suspend cannot stop queue\n"); + return status; + } + + dev_dbg(&pdev->dev, "suspended\n"); + + return 0; +} + +static int spi_imx_resume(struct platform_device *pdev) +{ + struct driver_data *drv_data = platform_get_drvdata(pdev); + int status = 0; + + /* Start the queue running */ + status = start_queue(drv_data); + if (status != 0) + dev_err(&pdev->dev, "problem starting queue (%d)\n", status); + else + dev_dbg(&pdev->dev, "resumed\n"); + + return status; +} +#else +#define spi_imx_suspend NULL +#define spi_imx_resume NULL +#endif /* CONFIG_PM */ + +/* work with hotplug and coldplug */ +MODULE_ALIAS("platform:spi_imx"); + +static struct platform_driver driver = { + .driver = { + .name = "spi_imx", + .owner = THIS_MODULE, + }, + .remove = __exit_p(spi_imx_remove), + .shutdown = spi_imx_shutdown, + .suspend = spi_imx_suspend, + .resume = spi_imx_resume, +}; + +static int __init spi_imx_init(void) +{ + return platform_driver_probe(&driver, spi_imx_probe); +} +module_init(spi_imx_init); + +static void __exit spi_imx_exit(void) +{ + platform_driver_unregister(&driver); +} +module_exit(spi_imx_exit); + +MODULE_AUTHOR("Andrea Paterniani, "); +MODULE_DESCRIPTION("iMX SPI Controller Driver"); +MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/spi/spi_ppc4xx.c b/trunk/drivers/spi/spi_ppc4xx.c deleted file mode 100644 index 140a18d6cf3e..000000000000 --- a/trunk/drivers/spi/spi_ppc4xx.c +++ /dev/null @@ -1,612 +0,0 @@ -/* - * SPI_PPC4XX SPI controller driver. - * - * Copyright (C) 2007 Gary Jennejohn - * Copyright 2008 Stefan Roese , DENX Software Engineering - * Copyright 2009 Harris Corporation, Steven A. Falco - * - * Based in part on drivers/spi/spi_s3c24xx.c - * - * Copyright (c) 2006 Ben Dooks - * Copyright (c) 2006 Simtec Electronics - * Ben Dooks - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. - */ - -/* - * The PPC4xx SPI controller has no FIFO so each sent/received byte will - * generate an interrupt to the CPU. This can cause high CPU utilization. - * This driver allows platforms to reduce the interrupt load on the CPU - * during SPI transfers by setting max_speed_hz via the device tree. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -/* bits in mode register - bit 0 is MSb */ - -/* - * SPI_PPC4XX_MODE_SCP = 0 means "data latched on trailing edge of clock" - * SPI_PPC4XX_MODE_SCP = 1 means "data latched on leading edge of clock" - * Note: This is the inverse of CPHA. - */ -#define SPI_PPC4XX_MODE_SCP (0x80 >> 3) - -/* SPI_PPC4XX_MODE_SPE = 1 means "port enabled" */ -#define SPI_PPC4XX_MODE_SPE (0x80 >> 4) - -/* - * SPI_PPC4XX_MODE_RD = 0 means "MSB first" - this is the normal mode - * SPI_PPC4XX_MODE_RD = 1 means "LSB first" - this is bit-reversed mode - * Note: This is identical to SPI_LSB_FIRST. - */ -#define SPI_PPC4XX_MODE_RD (0x80 >> 5) - -/* - * SPI_PPC4XX_MODE_CI = 0 means "clock idles low" - * SPI_PPC4XX_MODE_CI = 1 means "clock idles high" - * Note: This is identical to CPOL. - */ -#define SPI_PPC4XX_MODE_CI (0x80 >> 6) - -/* - * SPI_PPC4XX_MODE_IL = 0 means "loopback disable" - * SPI_PPC4XX_MODE_IL = 1 means "loopback enable" - */ -#define SPI_PPC4XX_MODE_IL (0x80 >> 7) - -/* bits in control register */ -/* starts a transfer when set */ -#define SPI_PPC4XX_CR_STR (0x80 >> 7) - -/* bits in status register */ -/* port is busy with a transfer */ -#define SPI_PPC4XX_SR_BSY (0x80 >> 6) -/* RxD ready */ -#define SPI_PPC4XX_SR_RBR (0x80 >> 7) - -/* clock settings (SCP and CI) for various SPI modes */ -#define SPI_CLK_MODE0 (SPI_PPC4XX_MODE_SCP | 0) -#define SPI_CLK_MODE1 (0 | 0) -#define SPI_CLK_MODE2 (SPI_PPC4XX_MODE_SCP | SPI_PPC4XX_MODE_CI) -#define SPI_CLK_MODE3 (0 | SPI_PPC4XX_MODE_CI) - -#define DRIVER_NAME "spi_ppc4xx_of" - -struct spi_ppc4xx_regs { - u8 mode; - u8 rxd; - u8 txd; - u8 cr; - u8 sr; - u8 dummy; - /* - * Clock divisor modulus register - * This uses the follwing formula: - * SCPClkOut = OPBCLK/(4(CDM + 1)) - * or - * CDM = (OPBCLK/4*SCPClkOut) - 1 - * bit 0 is the MSb! - */ - u8 cdm; -}; - -/* SPI Controller driver's private data. */ -struct ppc4xx_spi { - /* bitbang has to be first */ - struct spi_bitbang bitbang; - struct completion done; - - u64 mapbase; - u64 mapsize; - int irqnum; - /* need this to set the SPI clock */ - unsigned int opb_freq; - - /* for transfers */ - int len; - int count; - /* data buffers */ - const unsigned char *tx; - unsigned char *rx; - - int *gpios; - - struct spi_ppc4xx_regs __iomem *regs; /* pointer to the registers */ - struct spi_master *master; - struct device *dev; -}; - -/* need this so we can set the clock in the chipselect routine */ -struct spi_ppc4xx_cs { - u8 mode; -}; - -static int spi_ppc4xx_txrx(struct spi_device *spi, struct spi_transfer *t) -{ - struct ppc4xx_spi *hw; - u8 data; - - dev_dbg(&spi->dev, "txrx: tx %p, rx %p, len %d\n", - t->tx_buf, t->rx_buf, t->len); - - hw = spi_master_get_devdata(spi->master); - - hw->tx = t->tx_buf; - hw->rx = t->rx_buf; - hw->len = t->len; - hw->count = 0; - - /* send the first byte */ - data = hw->tx ? hw->tx[0] : 0; - out_8(&hw->regs->txd, data); - out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR); - wait_for_completion(&hw->done); - - return hw->count; -} - -static int spi_ppc4xx_setupxfer(struct spi_device *spi, struct spi_transfer *t) -{ - struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); - struct spi_ppc4xx_cs *cs = spi->controller_state; - int scr; - u8 cdm = 0; - u32 speed; - u8 bits_per_word; - - /* Start with the generic configuration for this device. */ - bits_per_word = spi->bits_per_word; - speed = spi->max_speed_hz; - - /* - * Modify the configuration if the transfer overrides it. Do not allow - * the transfer to overwrite the generic configuration with zeros. - */ - if (t) { - if (t->bits_per_word) - bits_per_word = t->bits_per_word; - - if (t->speed_hz) - speed = min(t->speed_hz, spi->max_speed_hz); - } - - if (bits_per_word != 8) { - dev_err(&spi->dev, "invalid bits-per-word (%d)\n", - bits_per_word); - return -EINVAL; - } - - if (!speed || (speed > spi->max_speed_hz)) { - dev_err(&spi->dev, "invalid speed_hz (%d)\n", speed); - return -EINVAL; - } - - /* Write new configration */ - out_8(&hw->regs->mode, cs->mode); - - /* Set the clock */ - /* opb_freq was already divided by 4 */ - scr = (hw->opb_freq / speed) - 1; - if (scr > 0) - cdm = min(scr, 0xff); - - dev_dbg(&spi->dev, "setting pre-scaler to %d (hz %d)\n", cdm, speed); - - if (in_8(&hw->regs->cdm) != cdm) - out_8(&hw->regs->cdm, cdm); - - spin_lock(&hw->bitbang.lock); - if (!hw->bitbang.busy) { - hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); - /* Need to ndelay here? */ - } - spin_unlock(&hw->bitbang.lock); - - return 0; -} - -static int spi_ppc4xx_setup(struct spi_device *spi) -{ - struct spi_ppc4xx_cs *cs = spi->controller_state; - - if (spi->bits_per_word != 8) { - dev_err(&spi->dev, "invalid bits-per-word (%d)\n", - spi->bits_per_word); - return -EINVAL; - } - - if (!spi->max_speed_hz) { - dev_err(&spi->dev, "invalid max_speed_hz (must be non-zero)\n"); - return -EINVAL; - } - - if (cs == NULL) { - cs = kzalloc(sizeof *cs, GFP_KERNEL); - if (!cs) - return -ENOMEM; - spi->controller_state = cs; - } - - /* - * We set all bits of the SPI0_MODE register, so, - * no need to read-modify-write - */ - cs->mode = SPI_PPC4XX_MODE_SPE; - - switch (spi->mode & (SPI_CPHA | SPI_CPOL)) { - case SPI_MODE_0: - cs->mode |= SPI_CLK_MODE0; - break; - case SPI_MODE_1: - cs->mode |= SPI_CLK_MODE1; - break; - case SPI_MODE_2: - cs->mode |= SPI_CLK_MODE2; - break; - case SPI_MODE_3: - cs->mode |= SPI_CLK_MODE3; - break; - } - - if (spi->mode & SPI_LSB_FIRST) - cs->mode |= SPI_PPC4XX_MODE_RD; - - return 0; -} - -static void spi_ppc4xx_chipsel(struct spi_device *spi, int value) -{ - struct ppc4xx_spi *hw = spi_master_get_devdata(spi->master); - unsigned int cs = spi->chip_select; - unsigned int cspol; - - /* - * If there are no chip selects at all, or if this is the special - * case of a non-existent (dummy) chip select, do nothing. - */ - - if (!hw->master->num_chipselect || hw->gpios[cs] == -EEXIST) - return; - - cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; - if (value == BITBANG_CS_INACTIVE) - cspol = !cspol; - - gpio_set_value(hw->gpios[cs], cspol); -} - -static irqreturn_t spi_ppc4xx_int(int irq, void *dev_id) -{ - struct ppc4xx_spi *hw; - u8 status; - u8 data; - unsigned int count; - - hw = (struct ppc4xx_spi *)dev_id; - - status = in_8(&hw->regs->sr); - if (!status) - return IRQ_NONE; - - /* - * BSY de-asserts one cycle after the transfer is complete. The - * interrupt is asserted after the transfer is complete. The exact - * relationship is not documented, hence this code. - */ - - if (unlikely(status & SPI_PPC4XX_SR_BSY)) { - u8 lstatus; - int cnt = 0; - - dev_dbg(hw->dev, "got interrupt but spi still busy?\n"); - do { - ndelay(10); - lstatus = in_8(&hw->regs->sr); - } while (++cnt < 100 && lstatus & SPI_PPC4XX_SR_BSY); - - if (cnt >= 100) { - dev_err(hw->dev, "busywait: too many loops!\n"); - complete(&hw->done); - return IRQ_HANDLED; - } else { - /* status is always 1 (RBR) here */ - status = in_8(&hw->regs->sr); - dev_dbg(hw->dev, "loops %d status %x\n", cnt, status); - } - } - - count = hw->count; - hw->count++; - - /* RBR triggered this interrupt. Therefore, data must be ready. */ - data = in_8(&hw->regs->rxd); - if (hw->rx) - hw->rx[count] = data; - - count++; - - if (count < hw->len) { - data = hw->tx ? hw->tx[count] : 0; - out_8(&hw->regs->txd, data); - out_8(&hw->regs->cr, SPI_PPC4XX_CR_STR); - } else { - complete(&hw->done); - } - - return IRQ_HANDLED; -} - -static void spi_ppc4xx_cleanup(struct spi_device *spi) -{ - kfree(spi->controller_state); -} - -static void spi_ppc4xx_enable(struct ppc4xx_spi *hw) -{ - /* - * On all 4xx PPC's the SPI bus is shared/multiplexed with - * the 2nd I2C bus. We need to enable the the SPI bus before - * using it. - */ - - /* need to clear bit 14 to enable SPC */ - dcri_clrset(SDR0, SDR0_PFC1, 0x80000000 >> 14, 0); -} - -static void free_gpios(struct ppc4xx_spi *hw) -{ - if (hw->master->num_chipselect) { - int i; - for (i = 0; i < hw->master->num_chipselect; i++) - if (gpio_is_valid(hw->gpios[i])) - gpio_free(hw->gpios[i]); - - kfree(hw->gpios); - hw->gpios = NULL; - } -} - -/* - * of_device layer stuff... - */ -static int __init spi_ppc4xx_of_probe(struct of_device *op, - const struct of_device_id *match) -{ - struct ppc4xx_spi *hw; - struct spi_master *master; - struct spi_bitbang *bbp; - struct resource resource; - struct device_node *np = op->node; - struct device *dev = &op->dev; - struct device_node *opbnp; - int ret; - int num_gpios; - const unsigned int *clk; - - master = spi_alloc_master(dev, sizeof *hw); - if (master == NULL) - return -ENOMEM; - dev_set_drvdata(dev, master); - hw = spi_master_get_devdata(master); - hw->master = spi_master_get(master); - hw->dev = dev; - - init_completion(&hw->done); - - /* - * A count of zero implies a single SPI device without any chip-select. - * Note that of_gpio_count counts all gpios assigned to this spi master. - * This includes both "null" gpio's and real ones. - */ - num_gpios = of_gpio_count(np); - if (num_gpios) { - int i; - - hw->gpios = kzalloc(sizeof(int) * num_gpios, GFP_KERNEL); - if (!hw->gpios) { - ret = -ENOMEM; - goto free_master; - } - - for (i = 0; i < num_gpios; i++) { - int gpio; - enum of_gpio_flags flags; - - gpio = of_get_gpio_flags(np, i, &flags); - hw->gpios[i] = gpio; - - if (gpio_is_valid(gpio)) { - /* Real CS - set the initial state. */ - ret = gpio_request(gpio, np->name); - if (ret < 0) { - dev_err(dev, "can't request gpio " - "#%d: %d\n", i, ret); - goto free_gpios; - } - - gpio_direction_output(gpio, - !!(flags & OF_GPIO_ACTIVE_LOW)); - } else if (gpio == -EEXIST) { - ; /* No CS, but that's OK. */ - } else { - dev_err(dev, "invalid gpio #%d: %d\n", i, gpio); - ret = -EINVAL; - goto free_gpios; - } - } - } - - /* Setup the state for the bitbang driver */ - bbp = &hw->bitbang; - bbp->master = hw->master; - bbp->setup_transfer = spi_ppc4xx_setupxfer; - bbp->chipselect = spi_ppc4xx_chipsel; - bbp->txrx_bufs = spi_ppc4xx_txrx; - bbp->use_dma = 0; - bbp->master->setup = spi_ppc4xx_setup; - bbp->master->cleanup = spi_ppc4xx_cleanup; - - /* Allocate bus num dynamically. */ - bbp->master->bus_num = -1; - - /* the spi->mode bits understood by this driver: */ - bbp->master->mode_bits = - SPI_CPHA | SPI_CPOL | SPI_CS_HIGH | SPI_LSB_FIRST; - - /* this many pins in all GPIO controllers */ - bbp->master->num_chipselect = num_gpios; - - /* Get the clock for the OPB */ - opbnp = of_find_compatible_node(NULL, NULL, "ibm,opb"); - if (opbnp == NULL) { - dev_err(dev, "OPB: cannot find node\n"); - ret = -ENODEV; - goto free_gpios; - } - /* Get the clock (Hz) for the OPB */ - clk = of_get_property(opbnp, "clock-frequency", NULL); - if (clk == NULL) { - dev_err(dev, "OPB: no clock-frequency property set\n"); - of_node_put(opbnp); - ret = -ENODEV; - goto free_gpios; - } - hw->opb_freq = *clk; - hw->opb_freq >>= 2; - of_node_put(opbnp); - - ret = of_address_to_resource(np, 0, &resource); - if (ret) { - dev_err(dev, "error while parsing device node resource\n"); - goto free_gpios; - } - hw->mapbase = resource.start; - hw->mapsize = resource.end - resource.start + 1; - - /* Sanity check */ - if (hw->mapsize < sizeof(struct spi_ppc4xx_regs)) { - dev_err(dev, "too small to map registers\n"); - ret = -EINVAL; - goto free_gpios; - } - - /* Request IRQ */ - hw->irqnum = irq_of_parse_and_map(np, 0); - ret = request_irq(hw->irqnum, spi_ppc4xx_int, - IRQF_DISABLED, "spi_ppc4xx_of", (void *)hw); - if (ret) { - dev_err(dev, "unable to allocate interrupt\n"); - goto free_gpios; - } - - if (!request_mem_region(hw->mapbase, hw->mapsize, DRIVER_NAME)) { - dev_err(dev, "resource unavailable\n"); - ret = -EBUSY; - goto request_mem_error; - } - - hw->regs = ioremap(hw->mapbase, sizeof(struct spi_ppc4xx_regs)); - - if (!hw->regs) { - dev_err(dev, "unable to memory map registers\n"); - ret = -ENXIO; - goto map_io_error; - } - - spi_ppc4xx_enable(hw); - - /* Finally register our spi controller */ - dev->dma_mask = 0; - ret = spi_bitbang_start(bbp); - if (ret) { - dev_err(dev, "failed to register SPI master\n"); - goto unmap_regs; - } - - dev_info(dev, "driver initialized\n"); - of_register_spi_devices(master, np); - - return 0; - -unmap_regs: - iounmap(hw->regs); -map_io_error: - release_mem_region(hw->mapbase, hw->mapsize); -request_mem_error: - free_irq(hw->irqnum, hw); -free_gpios: - free_gpios(hw); -free_master: - dev_set_drvdata(dev, NULL); - spi_master_put(master); - - dev_err(dev, "initialization failed\n"); - return ret; -} - -static int __exit spi_ppc4xx_of_remove(struct of_device *op) -{ - struct spi_master *master = dev_get_drvdata(&op->dev); - struct ppc4xx_spi *hw = spi_master_get_devdata(master); - - spi_bitbang_stop(&hw->bitbang); - dev_set_drvdata(&op->dev, NULL); - release_mem_region(hw->mapbase, hw->mapsize); - free_irq(hw->irqnum, hw); - iounmap(hw->regs); - free_gpios(hw); - return 0; -} - -static struct of_device_id spi_ppc4xx_of_match[] = { - { .compatible = "ibm,ppc4xx-spi", }, - {}, -}; - -MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match); - -static struct of_platform_driver spi_ppc4xx_of_driver = { - .match_table = spi_ppc4xx_of_match, - .probe = spi_ppc4xx_of_probe, - .remove = __exit_p(spi_ppc4xx_of_remove), - .driver = { - .name = DRIVER_NAME, - .owner = THIS_MODULE, - }, -}; - -static int __init spi_ppc4xx_init(void) -{ - return of_register_platform_driver(&spi_ppc4xx_of_driver); -} -module_init(spi_ppc4xx_init); - -static void __exit spi_ppc4xx_exit(void) -{ - of_unregister_platform_driver(&spi_ppc4xx_of_driver); -} -module_exit(spi_ppc4xx_exit); - -MODULE_AUTHOR("Gary Jennejohn & Stefan Roese"); -MODULE_DESCRIPTION("Simple PPC4xx SPI Driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/spi/spi_s3c24xx.c b/trunk/drivers/spi/spi_s3c24xx.c index 33d94f76b9ef..6ba8aece90b5 100644 --- a/trunk/drivers/spi/spi_s3c24xx.c +++ b/trunk/drivers/spi/spi_s3c24xx.c @@ -20,28 +20,17 @@ #include #include #include -#include #include #include +#include +#include +#include + #include #include -/** - * s3c24xx_spi_devstate - per device data - * @hz: Last frequency calculated for @sppre field. - * @mode: Last mode setting for the @spcon field. - * @spcon: Value to write to the SPCON register. - * @sppre: Value to write to the SPPRE register. - */ -struct s3c24xx_spi_devstate { - unsigned int hz; - unsigned int mode; - u8 spcon; - u8 sppre; -}; - struct s3c24xx_spi { /* bitbang has to be first */ struct spi_bitbang bitbang; @@ -82,31 +71,43 @@ static void s3c24xx_spi_gpiocs(struct s3c2410_spi_info *spi, int cs, int pol) static void s3c24xx_spi_chipsel(struct spi_device *spi, int value) { - struct s3c24xx_spi_devstate *cs = spi->controller_state; struct s3c24xx_spi *hw = to_hw(spi); unsigned int cspol = spi->mode & SPI_CS_HIGH ? 1 : 0; - - /* change the chipselect state and the state of the spi engine clock */ + unsigned int spcon; switch (value) { case BITBANG_CS_INACTIVE: hw->set_cs(hw->pdata, spi->chip_select, cspol^1); - writeb(cs->spcon, hw->regs + S3C2410_SPCON); break; case BITBANG_CS_ACTIVE: - writeb(cs->spcon | S3C2410_SPCON_ENSCK, - hw->regs + S3C2410_SPCON); + spcon = readb(hw->regs + S3C2410_SPCON); + + if (spi->mode & SPI_CPHA) + spcon |= S3C2410_SPCON_CPHA_FMTB; + else + spcon &= ~S3C2410_SPCON_CPHA_FMTB; + + if (spi->mode & SPI_CPOL) + spcon |= S3C2410_SPCON_CPOL_HIGH; + else + spcon &= ~S3C2410_SPCON_CPOL_HIGH; + + spcon |= S3C2410_SPCON_ENSCK; + + /* write new configration */ + + writeb(spcon, hw->regs + S3C2410_SPCON); hw->set_cs(hw->pdata, spi->chip_select, cspol); + break; } } -static int s3c24xx_spi_update_state(struct spi_device *spi, - struct spi_transfer *t) +static int s3c24xx_spi_setupxfer(struct spi_device *spi, + struct spi_transfer *t) { struct s3c24xx_spi *hw = to_hw(spi); - struct s3c24xx_spi_devstate *cs = spi->controller_state; unsigned int bpw; unsigned int hz; unsigned int div; @@ -126,89 +127,41 @@ static int s3c24xx_spi_update_state(struct spi_device *spi, return -EINVAL; } - if (spi->mode != cs->mode) { - u8 spcon = SPCON_DEFAULT; - - if (spi->mode & SPI_CPHA) - spcon |= S3C2410_SPCON_CPHA_FMTB; - - if (spi->mode & SPI_CPOL) - spcon |= S3C2410_SPCON_CPOL_HIGH; + clk = clk_get_rate(hw->clk); + div = DIV_ROUND_UP(clk, hz * 2) - 1; - cs->mode = spi->mode; - cs->spcon = spcon; - } + if (div > 255) + div = 255; - if (cs->hz != hz) { - clk = clk_get_rate(hw->clk); - div = DIV_ROUND_UP(clk, hz * 2) - 1; + dev_dbg(&spi->dev, "setting pre-scaler to %d (wanted %d, got %ld)\n", + div, hz, clk / (2 * (div + 1))); - if (div > 255) - div = 255; - dev_dbg(&spi->dev, "pre-scaler=%d (wanted %d, got %ld)\n", - div, hz, clk / (2 * (div + 1))); + writeb(div, hw->regs + S3C2410_SPPRE); - cs->hz = hz; - cs->sppre = div; + spin_lock(&hw->bitbang.lock); + if (!hw->bitbang.busy) { + hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); + /* need to ndelay for 0.5 clocktick ? */ } + spin_unlock(&hw->bitbang.lock); return 0; } -static int s3c24xx_spi_setupxfer(struct spi_device *spi, - struct spi_transfer *t) -{ - struct s3c24xx_spi_devstate *cs = spi->controller_state; - struct s3c24xx_spi *hw = to_hw(spi); - int ret; - - ret = s3c24xx_spi_update_state(spi, t); - if (!ret) - writeb(cs->sppre, hw->regs + S3C2410_SPPRE); - - return ret; -} - static int s3c24xx_spi_setup(struct spi_device *spi) { - struct s3c24xx_spi_devstate *cs = spi->controller_state; - struct s3c24xx_spi *hw = to_hw(spi); int ret; - /* allocate settings on the first call */ - if (!cs) { - cs = kzalloc(sizeof(struct s3c24xx_spi_devstate), GFP_KERNEL); - if (!cs) { - dev_err(&spi->dev, "no memory for controller state\n"); - return -ENOMEM; - } - - cs->spcon = SPCON_DEFAULT; - cs->hz = -1; - spi->controller_state = cs; - } - - /* initialise the state from the device */ - ret = s3c24xx_spi_update_state(spi, NULL); - if (ret) + ret = s3c24xx_spi_setupxfer(spi, NULL); + if (ret < 0) { + dev_err(&spi->dev, "setupxfer returned %d\n", ret); return ret; - - spin_lock(&hw->bitbang.lock); - if (!hw->bitbang.busy) { - hw->bitbang.chipselect(spi, BITBANG_CS_INACTIVE); - /* need to ndelay for 0.5 clocktick ? */ } - spin_unlock(&hw->bitbang.lock); return 0; } -static void s3c24xx_spi_cleanup(struct spi_device *spi) -{ - kfree(spi->controller_state); -} - static inline unsigned int hw_txbyte(struct s3c24xx_spi *hw, int count) { return hw->tx ? hw->tx[count] : 0; @@ -336,9 +289,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) hw->bitbang.setup_transfer = s3c24xx_spi_setupxfer; hw->bitbang.chipselect = s3c24xx_spi_chipsel; hw->bitbang.txrx_bufs = s3c24xx_spi_txrx; - - hw->master->setup = s3c24xx_spi_setup; - hw->master->cleanup = s3c24xx_spi_cleanup; + hw->bitbang.master->setup = s3c24xx_spi_setup; dev_dbg(hw->dev, "bitbang at %p\n", &hw->bitbang); @@ -351,7 +302,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) goto err_no_iores; } - hw->ioarea = request_mem_region(res->start, resource_size(res), + hw->ioarea = request_mem_region(res->start, (res->end - res->start)+1, pdev->name); if (hw->ioarea == NULL) { @@ -360,7 +311,7 @@ static int __init s3c24xx_spi_probe(struct platform_device *pdev) goto err_no_iores; } - hw->regs = ioremap(res->start, resource_size(res)); + hw->regs = ioremap(res->start, (res->end - res->start)+1); if (hw->regs == NULL) { dev_err(&pdev->dev, "Cannot map IO\n"); err = -ENXIO; @@ -470,9 +421,9 @@ static int __exit s3c24xx_spi_remove(struct platform_device *dev) #ifdef CONFIG_PM -static int s3c24xx_spi_suspend(struct device *dev) +static int s3c24xx_spi_suspend(struct platform_device *pdev, pm_message_t msg) { - struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev)); + struct s3c24xx_spi *hw = platform_get_drvdata(pdev); if (hw->pdata && hw->pdata->gpio_setup) hw->pdata->gpio_setup(hw->pdata, 0); @@ -481,31 +432,27 @@ static int s3c24xx_spi_suspend(struct device *dev) return 0; } -static int s3c24xx_spi_resume(struct device *dev) +static int s3c24xx_spi_resume(struct platform_device *pdev) { - struct s3c24xx_spi *hw = platform_get_drvdata(to_platform_device(dev)); + struct s3c24xx_spi *hw = platform_get_drvdata(pdev); s3c24xx_spi_initialsetup(hw); return 0; } -static struct dev_pm_ops s3c24xx_spi_pmops = { - .suspend = s3c24xx_spi_suspend, - .resume = s3c24xx_spi_resume, -}; - -#define S3C24XX_SPI_PMOPS &s3c24xx_spi_pmops #else -#define S3C24XX_SPI_PMOPS NULL -#endif /* CONFIG_PM */ +#define s3c24xx_spi_suspend NULL +#define s3c24xx_spi_resume NULL +#endif MODULE_ALIAS("platform:s3c2410-spi"); static struct platform_driver s3c24xx_spi_driver = { .remove = __exit_p(s3c24xx_spi_remove), + .suspend = s3c24xx_spi_suspend, + .resume = s3c24xx_spi_resume, .driver = { .name = "s3c2410-spi", .owner = THIS_MODULE, - .pm = S3C24XX_SPI_PMOPS, }, }; diff --git a/trunk/drivers/spi/spi_stmp.c b/trunk/drivers/spi/spi_stmp.c deleted file mode 100644 index d871dc23909c..000000000000 --- a/trunk/drivers/spi/spi_stmp.c +++ /dev/null @@ -1,679 +0,0 @@ -/* - * Freescale STMP378X SPI master driver - * - * Author: dmitry pervushin - * - * Copyright 2008 Freescale Semiconductor, Inc. All Rights Reserved. - * Copyright 2008 Embedded Alley Solutions, Inc All Rights Reserved. - */ - -/* - * The code contained herein is licensed under the GNU General Public - * License. You may obtain a copy of the GNU General Public License - * Version 2 or later at the following locations: - * - * http://www.opensource.org/licenses/gpl-license.html - * http://www.gnu.org/copyleft/gpl.html - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - - -/* 0 means DMA mode(recommended, default), !0 - PIO mode */ -static int pio; -static int clock; - -/* default timeout for busy waits is 2 seconds */ -#define STMP_SPI_TIMEOUT (2 * HZ) - -struct stmp_spi { - int id; - - void * __iomem regs; /* vaddr of the control registers */ - - int irq, err_irq; - u32 dma; - struct stmp3xxx_dma_descriptor d; - - u32 speed_khz; - u32 saved_timings; - u32 divider; - - struct clk *clk; - struct device *master_dev; - - struct work_struct work; - struct workqueue_struct *workqueue; - - /* lock protects queue access */ - spinlock_t lock; - struct list_head queue; - - struct completion done; -}; - -#define busy_wait(cond) \ - ({ \ - unsigned long end_jiffies = jiffies + STMP_SPI_TIMEOUT; \ - bool succeeded = false; \ - do { \ - if (cond) { \ - succeeded = true; \ - break; \ - } \ - cpu_relax(); \ - } while (time_before(end_jiffies, jiffies)); \ - succeeded; \ - }) - -/** - * stmp_spi_init_hw - * Initialize the SSP port - */ -static int stmp_spi_init_hw(struct stmp_spi *ss) -{ - int err = 0; - void *pins = ss->master_dev->platform_data; - - err = stmp3xxx_request_pin_group(pins, dev_name(ss->master_dev)); - if (err) - goto out; - - ss->clk = clk_get(NULL, "ssp"); - if (IS_ERR(ss->clk)) { - err = PTR_ERR(ss->clk); - goto out_free_pins; - } - clk_enable(ss->clk); - - stmp3xxx_reset_block(ss->regs, false); - stmp3xxx_dma_reset_channel(ss->dma); - - return 0; - -out_free_pins: - stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev)); -out: - return err; -} - -static void stmp_spi_release_hw(struct stmp_spi *ss) -{ - void *pins = ss->master_dev->platform_data; - - if (ss->clk && !IS_ERR(ss->clk)) { - clk_disable(ss->clk); - clk_put(ss->clk); - } - stmp3xxx_release_pin_group(pins, dev_name(ss->master_dev)); -} - -static int stmp_spi_setup_transfer(struct spi_device *spi, - struct spi_transfer *t) -{ - u8 bits_per_word; - u32 hz; - struct stmp_spi *ss = spi_master_get_devdata(spi->master); - u16 rate; - - bits_per_word = spi->bits_per_word; - if (t && t->bits_per_word) - bits_per_word = t->bits_per_word; - - /* - * Calculate speed: - * - by default, use maximum speed from ssp clk - * - if device overrides it, use it - * - if transfer specifies other speed, use transfer's one - */ - hz = 1000 * ss->speed_khz / ss->divider; - if (spi->max_speed_hz) - hz = min(hz, spi->max_speed_hz); - if (t && t->speed_hz) - hz = min(hz, t->speed_hz); - - if (hz == 0) { - dev_err(&spi->dev, "Cannot continue with zero clock\n"); - return -EINVAL; - } - - if (bits_per_word != 8) { - dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", - __func__, bits_per_word); - return -EINVAL; - } - - dev_dbg(&spi->dev, "Requested clk rate = %uHz, max = %uHz/%d = %uHz\n", - hz, ss->speed_khz, ss->divider, - ss->speed_khz * 1000 / ss->divider); - - if (ss->speed_khz * 1000 / ss->divider < hz) { - dev_err(&spi->dev, "%s, unsupported clock rate %uHz\n", - __func__, hz); - return -EINVAL; - } - - rate = 1000 * ss->speed_khz/ss->divider/hz; - - writel(BF(ss->divider, SSP_TIMING_CLOCK_DIVIDE) | - BF(rate - 1, SSP_TIMING_CLOCK_RATE), - HW_SSP_TIMING + ss->regs); - - writel(BF(1 /* mode SPI */, SSP_CTRL1_SSP_MODE) | - BF(4 /* 8 bits */, SSP_CTRL1_WORD_LENGTH) | - ((spi->mode & SPI_CPOL) ? BM_SSP_CTRL1_POLARITY : 0) | - ((spi->mode & SPI_CPHA) ? BM_SSP_CTRL1_PHASE : 0) | - (pio ? 0 : BM_SSP_CTRL1_DMA_ENABLE), - ss->regs + HW_SSP_CTRL1); - - return 0; -} - -static int stmp_spi_setup(struct spi_device *spi) -{ - /* spi_setup() does basic checks, - * stmp_spi_setup_transfer() does more later - */ - if (spi->bits_per_word != 8) { - dev_err(&spi->dev, "%s, unsupported bits_per_word=%d\n", - __func__, spi->bits_per_word); - return -EINVAL; - } - return 0; -} - -static inline u32 stmp_spi_cs(unsigned cs) -{ - return ((cs & 1) ? BM_SSP_CTRL0_WAIT_FOR_CMD : 0) | - ((cs & 2) ? BM_SSP_CTRL0_WAIT_FOR_IRQ : 0); -} - -static int stmp_spi_txrx_dma(struct stmp_spi *ss, int cs, - unsigned char *buf, dma_addr_t dma_buf, int len, - int first, int last, bool write) -{ - u32 c0 = 0; - dma_addr_t spi_buf_dma = dma_buf; - int status = 0; - enum dma_data_direction dir = write ? DMA_TO_DEVICE : DMA_FROM_DEVICE; - - c0 |= (first ? BM_SSP_CTRL0_LOCK_CS : 0); - c0 |= (last ? BM_SSP_CTRL0_IGNORE_CRC : 0); - c0 |= (write ? 0 : BM_SSP_CTRL0_READ); - c0 |= BM_SSP_CTRL0_DATA_XFER; - - c0 |= stmp_spi_cs(cs); - - c0 |= BF(len, SSP_CTRL0_XFER_COUNT); - - if (!dma_buf) - spi_buf_dma = dma_map_single(ss->master_dev, buf, len, dir); - - ss->d.command->cmd = - BF(len, APBH_CHn_CMD_XFER_COUNT) | - BF(1, APBH_CHn_CMD_CMDWORDS) | - BM_APBH_CHn_CMD_WAIT4ENDCMD | - BM_APBH_CHn_CMD_IRQONCMPLT | - BF(write ? BV_APBH_CHn_CMD_COMMAND__DMA_READ : - BV_APBH_CHn_CMD_COMMAND__DMA_WRITE, - APBH_CHn_CMD_COMMAND); - ss->d.command->pio_words[0] = c0; - ss->d.command->buf_ptr = spi_buf_dma; - - stmp3xxx_dma_reset_channel(ss->dma); - stmp3xxx_dma_clear_interrupt(ss->dma); - stmp3xxx_dma_enable_interrupt(ss->dma); - init_completion(&ss->done); - stmp3xxx_dma_go(ss->dma, &ss->d, 1); - wait_for_completion(&ss->done); - - if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) & BM_SSP_CTRL0_RUN)) - status = ETIMEDOUT; - - if (!dma_buf) - dma_unmap_single(ss->master_dev, spi_buf_dma, len, dir); - - return status; -} - -static inline void stmp_spi_enable(struct stmp_spi *ss) -{ - stmp3xxx_setl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0); - stmp3xxx_clearl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0); -} - -static inline void stmp_spi_disable(struct stmp_spi *ss) -{ - stmp3xxx_clearl(BM_SSP_CTRL0_LOCK_CS, ss->regs + HW_SSP_CTRL0); - stmp3xxx_setl(BM_SSP_CTRL0_IGNORE_CRC, ss->regs + HW_SSP_CTRL0); -} - -static int stmp_spi_txrx_pio(struct stmp_spi *ss, int cs, - unsigned char *buf, int len, - bool first, bool last, bool write) -{ - if (first) - stmp_spi_enable(ss); - - stmp3xxx_setl(stmp_spi_cs(cs), ss->regs + HW_SSP_CTRL0); - - while (len--) { - if (last && len <= 0) - stmp_spi_disable(ss); - - stmp3xxx_clearl(BM_SSP_CTRL0_XFER_COUNT, - ss->regs + HW_SSP_CTRL0); - stmp3xxx_setl(1, ss->regs + HW_SSP_CTRL0); - - if (write) - stmp3xxx_clearl(BM_SSP_CTRL0_READ, - ss->regs + HW_SSP_CTRL0); - else - stmp3xxx_setl(BM_SSP_CTRL0_READ, - ss->regs + HW_SSP_CTRL0); - - /* Run! */ - stmp3xxx_setl(BM_SSP_CTRL0_RUN, ss->regs + HW_SSP_CTRL0); - - if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) & - BM_SSP_CTRL0_RUN)) - break; - - if (write) - writel(*buf, ss->regs + HW_SSP_DATA); - - /* Set TRANSFER */ - stmp3xxx_setl(BM_SSP_CTRL0_DATA_XFER, ss->regs + HW_SSP_CTRL0); - - if (!write) { - if (busy_wait((readl(ss->regs + HW_SSP_STATUS) & - BM_SSP_STATUS_FIFO_EMPTY))) - break; - *buf = readl(ss->regs + HW_SSP_DATA) & 0xFF; - } - - if (!busy_wait(readl(ss->regs + HW_SSP_CTRL0) & - BM_SSP_CTRL0_RUN)) - break; - - /* advance to the next byte */ - buf++; - } - - return len < 0 ? 0 : -ETIMEDOUT; -} - -static int stmp_spi_handle_message(struct stmp_spi *ss, struct spi_message *m) -{ - bool first, last; - struct spi_transfer *t, *tmp_t; - int status = 0; - int cs; - - cs = m->spi->chip_select; - - list_for_each_entry_safe(t, tmp_t, &m->transfers, transfer_list) { - - first = (&t->transfer_list == m->transfers.next); - last = (&t->transfer_list == m->transfers.prev); - - if (first || t->speed_hz || t->bits_per_word) - stmp_spi_setup_transfer(m->spi, t); - - /* reject "not last" transfers which request to change cs */ - if (t->cs_change && !last) { - dev_err(&m->spi->dev, - "Message with t->cs_change has been skipped\n"); - continue; - } - - if (t->tx_buf) { - status = pio ? - stmp_spi_txrx_pio(ss, cs, (void *)t->tx_buf, - t->len, first, last, true) : - stmp_spi_txrx_dma(ss, cs, (void *)t->tx_buf, - t->tx_dma, t->len, first, last, true); -#ifdef DEBUG - if (t->len < 0x10) - print_hex_dump_bytes("Tx ", - DUMP_PREFIX_OFFSET, - t->tx_buf, t->len); - else - pr_debug("Tx: %d bytes\n", t->len); -#endif - } - if (t->rx_buf) { - status = pio ? - stmp_spi_txrx_pio(ss, cs, t->rx_buf, - t->len, first, last, false) : - stmp_spi_txrx_dma(ss, cs, t->rx_buf, - t->rx_dma, t->len, first, last, false); -#ifdef DEBUG - if (t->len < 0x10) - print_hex_dump_bytes("Rx ", - DUMP_PREFIX_OFFSET, - t->rx_buf, t->len); - else - pr_debug("Rx: %d bytes\n", t->len); -#endif - } - - if (t->delay_usecs) - udelay(t->delay_usecs); - - if (status) - break; - - } - return status; -} - -/** - * stmp_spi_handle - handle messages from the queue - */ -static void stmp_spi_handle(struct work_struct *w) -{ - struct stmp_spi *ss = container_of(w, struct stmp_spi, work); - unsigned long flags; - struct spi_message *m; - - spin_lock_irqsave(&ss->lock, flags); - while (!list_empty(&ss->queue)) { - m = list_entry(ss->queue.next, struct spi_message, queue); - list_del_init(&m->queue); - spin_unlock_irqrestore(&ss->lock, flags); - - m->status = stmp_spi_handle_message(ss, m); - m->complete(m->context); - - spin_lock_irqsave(&ss->lock, flags); - } - spin_unlock_irqrestore(&ss->lock, flags); - - return; -} - -/** - * stmp_spi_transfer - perform message transfer. - * Called indirectly from spi_async, queues all the messages to - * spi_handle_message. - * @spi: spi device - * @m: message to be queued - */ -static int stmp_spi_transfer(struct spi_device *spi, struct spi_message *m) -{ - struct stmp_spi *ss = spi_master_get_devdata(spi->master); - unsigned long flags; - - m->status = -EINPROGRESS; - spin_lock_irqsave(&ss->lock, flags); - list_add_tail(&m->queue, &ss->queue); - queue_work(ss->workqueue, &ss->work); - spin_unlock_irqrestore(&ss->lock, flags); - return 0; -} - -static irqreturn_t stmp_spi_irq(int irq, void *dev_id) -{ - struct stmp_spi *ss = dev_id; - - stmp3xxx_dma_clear_interrupt(ss->dma); - complete(&ss->done); - return IRQ_HANDLED; -} - -static irqreturn_t stmp_spi_irq_err(int irq, void *dev_id) -{ - struct stmp_spi *ss = dev_id; - u32 c1, st; - - c1 = readl(ss->regs + HW_SSP_CTRL1); - st = readl(ss->regs + HW_SSP_STATUS); - dev_err(ss->master_dev, "%s: status = 0x%08X, c1 = 0x%08X\n", - __func__, st, c1); - stmp3xxx_clearl(c1 & 0xCCCC0000, ss->regs + HW_SSP_CTRL1); - - return IRQ_HANDLED; -} - -static int __devinit stmp_spi_probe(struct platform_device *dev) -{ - int err = 0; - struct spi_master *master; - struct stmp_spi *ss; - struct resource *r; - - master = spi_alloc_master(&dev->dev, sizeof(struct stmp_spi)); - if (master == NULL) { - err = -ENOMEM; - goto out0; - } - master->flags = SPI_MASTER_HALF_DUPLEX; - - ss = spi_master_get_devdata(master); - platform_set_drvdata(dev, master); - - /* Get resources(memory, IRQ) associated with the device */ - r = platform_get_resource(dev, IORESOURCE_MEM, 0); - if (r == NULL) { - err = -ENODEV; - goto out_put_master; - } - ss->regs = ioremap(r->start, resource_size(r)); - if (!ss->regs) { - err = -EINVAL; - goto out_put_master; - } - - ss->master_dev = &dev->dev; - ss->id = dev->id; - - INIT_WORK(&ss->work, stmp_spi_handle); - INIT_LIST_HEAD(&ss->queue); - spin_lock_init(&ss->lock); - - ss->workqueue = create_singlethread_workqueue(dev_name(&dev->dev)); - if (!ss->workqueue) { - err = -ENXIO; - goto out_put_master; - } - master->transfer = stmp_spi_transfer; - master->setup = stmp_spi_setup; - - /* the spi->mode bits understood by this driver: */ - master->mode_bits = SPI_CPOL | SPI_CPHA; - - ss->irq = platform_get_irq(dev, 0); - if (ss->irq < 0) { - err = ss->irq; - goto out_put_master; - } - ss->err_irq = platform_get_irq(dev, 1); - if (ss->err_irq < 0) { - err = ss->err_irq; - goto out_put_master; - } - - r = platform_get_resource(dev, IORESOURCE_DMA, 0); - if (r == NULL) { - err = -ENODEV; - goto out_put_master; - } - - ss->dma = r->start; - err = stmp3xxx_dma_request(ss->dma, &dev->dev, dev_name(&dev->dev)); - if (err) - goto out_put_master; - - err = stmp3xxx_dma_allocate_command(ss->dma, &ss->d); - if (err) - goto out_free_dma; - - master->bus_num = dev->id; - master->num_chipselect = 1; - - /* SPI controller initializations */ - err = stmp_spi_init_hw(ss); - if (err) { - dev_dbg(&dev->dev, "cannot initialize hardware\n"); - goto out_free_dma_desc; - } - - if (clock) { - dev_info(&dev->dev, "clock rate forced to %d\n", clock); - clk_set_rate(ss->clk, clock); - } - ss->speed_khz = clk_get_rate(ss->clk); - ss->divider = 2; - dev_info(&dev->dev, "max possible speed %d = %ld/%d kHz\n", - ss->speed_khz, clk_get_rate(ss->clk), ss->divider); - - /* Register for SPI interrupt */ - err = request_irq(ss->irq, stmp_spi_irq, 0, - dev_name(&dev->dev), ss); - if (err) { - dev_dbg(&dev->dev, "request_irq failed, %d\n", err); - goto out_release_hw; - } - - /* ..and shared interrupt for all SSP controllers */ - err = request_irq(ss->err_irq, stmp_spi_irq_err, IRQF_SHARED, - dev_name(&dev->dev), ss); - if (err) { - dev_dbg(&dev->dev, "request_irq(error) failed, %d\n", err); - goto out_free_irq; - } - - err = spi_register_master(master); - if (err) { - dev_dbg(&dev->dev, "cannot register spi master, %d\n", err); - goto out_free_irq_2; - } - dev_info(&dev->dev, "at (mapped) 0x%08X, irq=%d, bus %d, %s mode\n", - (u32)ss->regs, ss->irq, master->bus_num, - pio ? "PIO" : "DMA"); - return 0; - -out_free_irq_2: - free_irq(ss->err_irq, ss); -out_free_irq: - free_irq(ss->irq, ss); -out_free_dma_desc: - stmp3xxx_dma_free_command(ss->dma, &ss->d); -out_free_dma: - stmp3xxx_dma_release(ss->dma); -out_release_hw: - stmp_spi_release_hw(ss); -out_put_master: - if (ss->workqueue) - destroy_workqueue(ss->workqueue); - if (ss->regs) - iounmap(ss->regs); - platform_set_drvdata(dev, NULL); - spi_master_put(master); -out0: - return err; -} - -static int __devexit stmp_spi_remove(struct platform_device *dev) -{ - struct stmp_spi *ss; - struct spi_master *master; - - master = platform_get_drvdata(dev); - if (master == NULL) - goto out0; - ss = spi_master_get_devdata(master); - - spi_unregister_master(master); - - free_irq(ss->err_irq, ss); - free_irq(ss->irq, ss); - stmp3xxx_dma_free_command(ss->dma, &ss->d); - stmp3xxx_dma_release(ss->dma); - stmp_spi_release_hw(ss); - destroy_workqueue(ss->workqueue); - iounmap(ss->regs); - spi_master_put(master); - platform_set_drvdata(dev, NULL); -out0: - return 0; -} - -#ifdef CONFIG_PM -static int stmp_spi_suspend(struct platform_device *pdev, pm_message_t pmsg) -{ - struct stmp_spi *ss; - struct spi_master *master; - - master = platform_get_drvdata(pdev); - ss = spi_master_get_devdata(master); - - ss->saved_timings = readl(HW_SSP_TIMING + ss->regs); - clk_disable(ss->clk); - - return 0; -} - -static int stmp_spi_resume(struct platform_device *pdev) -{ - struct stmp_spi *ss; - struct spi_master *master; - - master = platform_get_drvdata(pdev); - ss = spi_master_get_devdata(master); - - clk_enable(ss->clk); - stmp3xxx_reset_block(ss->regs, false); - writel(ss->saved_timings, ss->regs + HW_SSP_TIMING); - - return 0; -} - -#else -#define stmp_spi_suspend NULL -#define stmp_spi_resume NULL -#endif - -static struct platform_driver stmp_spi_driver = { - .probe = stmp_spi_probe, - .remove = __devexit_p(stmp_spi_remove), - .driver = { - .name = "stmp3xxx_ssp", - .owner = THIS_MODULE, - }, - .suspend = stmp_spi_suspend, - .resume = stmp_spi_resume, -}; - -static int __init stmp_spi_init(void) -{ - return platform_driver_register(&stmp_spi_driver); -} - -static void __exit stmp_spi_exit(void) -{ - platform_driver_unregister(&stmp_spi_driver); -} - -module_init(stmp_spi_init); -module_exit(stmp_spi_exit); -module_param(pio, int, S_IRUGO); -module_param(clock, int, S_IRUGO); -MODULE_AUTHOR("dmitry pervushin "); -MODULE_DESCRIPTION("STMP3xxx SPI/SSP driver"); -MODULE_LICENSE("GPL"); diff --git a/trunk/drivers/spi/spidev.c b/trunk/drivers/spi/spidev.c index f921bd1109e1..606e7a40a8da 100644 --- a/trunk/drivers/spi/spidev.c +++ b/trunk/drivers/spi/spidev.c @@ -688,4 +688,3 @@ module_exit(spidev_exit); MODULE_AUTHOR("Andrea Paterniani, "); MODULE_DESCRIPTION("User mode SPI device interface"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:spidev"); diff --git a/trunk/drivers/spi/tle62x0.c b/trunk/drivers/spi/tle62x0.c index bf9540f5fb98..455991fbe28f 100644 --- a/trunk/drivers/spi/tle62x0.c +++ b/trunk/drivers/spi/tle62x0.c @@ -329,4 +329,3 @@ module_exit(tle62x0_exit); MODULE_AUTHOR("Ben Dooks "); MODULE_DESCRIPTION("TLE62x0 SPI driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:tle62x0"); diff --git a/trunk/drivers/staging/stlc45xx/stlc45xx.c b/trunk/drivers/staging/stlc45xx/stlc45xx.c index be99eb33d817..12d414deaad6 100644 --- a/trunk/drivers/staging/stlc45xx/stlc45xx.c +++ b/trunk/drivers/staging/stlc45xx/stlc45xx.c @@ -2591,4 +2591,3 @@ module_exit(stlc45xx_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Kalle Valo "); -MODULE_ALIAS("spi:cx3110x"); diff --git a/trunk/drivers/thermal/Kconfig b/trunk/drivers/thermal/Kconfig index bf7c687519ef..a86e952ed4ca 100644 --- a/trunk/drivers/thermal/Kconfig +++ b/trunk/drivers/thermal/Kconfig @@ -15,7 +15,6 @@ menuconfig THERMAL config THERMAL_HWMON bool "Hardware monitoring support" - depends on THERMAL depends on HWMON=y || HWMON=THERMAL help The generic thermal sysfs driver's hardware monitoring support diff --git a/trunk/drivers/usb/Kconfig b/trunk/drivers/usb/Kconfig index ebd7237230e3..dcd49f1e96d0 100644 --- a/trunk/drivers/usb/Kconfig +++ b/trunk/drivers/usb/Kconfig @@ -39,7 +39,6 @@ config USB_ARCH_HAS_OHCI default y if ARCH_AT91 default y if ARCH_PNX4008 && I2C default y if MFD_TC6393XB - default y if ARCH_W90X900 # PPC: default y if STB03xxx default y if PPC_MPC52xx @@ -59,8 +58,6 @@ config USB_ARCH_HAS_EHCI default y if PPC_83xx default y if SOC_AU1200 default y if ARCH_IXP4XX - default y if ARCH_W90X900 - default y if ARCH_AT91SAM9G45 default PCI # ARM SA1111 chips have a non-PCI based "OHCI-compatible" USB host interface. diff --git a/trunk/drivers/usb/Makefile b/trunk/drivers/usb/Makefile index be3c9b80bc9f..19cb7d5480d7 100644 --- a/trunk/drivers/usb/Makefile +++ b/trunk/drivers/usb/Makefile @@ -16,7 +16,6 @@ obj-$(CONFIG_USB_UHCI_HCD) += host/ obj-$(CONFIG_USB_FHCI_HCD) += host/ obj-$(CONFIG_USB_XHCI_HCD) += host/ obj-$(CONFIG_USB_SL811_HCD) += host/ -obj-$(CONFIG_USB_ISP1362_HCD) += host/ obj-$(CONFIG_USB_U132_HCD) += host/ obj-$(CONFIG_USB_R8A66597_HCD) += host/ obj-$(CONFIG_USB_HWA_HCD) += host/ @@ -40,7 +39,6 @@ obj-$(CONFIG_USB_MICROTEK) += image/ obj-$(CONFIG_USB_SERIAL) += serial/ obj-$(CONFIG_USB) += misc/ -obj-y += early/ obj-$(CONFIG_USB_ATM) += atm/ obj-$(CONFIG_USB_SPEEDTOUCH) += atm/ diff --git a/trunk/drivers/usb/class/cdc-acm.c b/trunk/drivers/usb/class/cdc-acm.c index e3861b21e776..85a1a55815cf 100644 --- a/trunk/drivers/usb/class/cdc-acm.c +++ b/trunk/drivers/usb/class/cdc-acm.c @@ -59,7 +59,6 @@ #include #include #include -#include #include #include #include @@ -610,7 +609,6 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) acm->throttle = 0; tasklet_schedule(&acm->urb_task); - set_bit(ASYNCB_INITIALIZED, &acm->port.flags); rv = tty_port_block_til_ready(&acm->port, tty, filp); done: mutex_unlock(&acm->mutex); diff --git a/trunk/drivers/usb/class/cdc-wdm.c b/trunk/drivers/usb/class/cdc-wdm.c index 3e564bfe17d1..8c64c018b676 100644 --- a/trunk/drivers/usb/class/cdc-wdm.c +++ b/trunk/drivers/usb/class/cdc-wdm.c @@ -313,13 +313,8 @@ static ssize_t wdm_write r = usb_autopm_get_interface(desc->intf); if (r < 0) goto outnp; - - if (!file->f_flags && O_NONBLOCK) - r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, - &desc->flags)); - else - if (test_bit(WDM_IN_USE, &desc->flags)) - r = -EAGAIN; + r = wait_event_interruptible(desc->wait, !test_bit(WDM_IN_USE, + &desc->flags)); if (r < 0) goto out; @@ -382,7 +377,7 @@ static ssize_t wdm_write static ssize_t wdm_read (struct file *file, char __user *buffer, size_t count, loff_t *ppos) { - int rv, cntr = 0; + int rv, cntr; int i = 0; struct wdm_device *desc = file->private_data; @@ -394,23 +389,10 @@ static ssize_t wdm_read if (desc->length == 0) { desc->read = 0; retry: - if (test_bit(WDM_DISCONNECTING, &desc->flags)) { - rv = -ENODEV; - goto err; - } i++; - if (file->f_flags & O_NONBLOCK) { - if (!test_bit(WDM_READ, &desc->flags)) { - rv = cntr ? cntr : -EAGAIN; - goto err; - } - rv = 0; - } else { - rv = wait_event_interruptible(desc->wait, - test_bit(WDM_READ, &desc->flags)); - } + rv = wait_event_interruptible(desc->wait, + test_bit(WDM_READ, &desc->flags)); - /* may have happened while we slept */ if (test_bit(WDM_DISCONNECTING, &desc->flags)) { rv = -ENODEV; goto err; @@ -466,7 +448,7 @@ static ssize_t wdm_read err: mutex_unlock(&desc->rlock); - if (rv < 0 && rv != -EAGAIN) + if (rv < 0) dev_err(&desc->intf->dev, "wdm_read: exit error\n"); return rv; } diff --git a/trunk/drivers/usb/class/usbtmc.c b/trunk/drivers/usb/class/usbtmc.c index 333ee02e7b2b..b09a527f7341 100644 --- a/trunk/drivers/usb/class/usbtmc.c +++ b/trunk/drivers/usb/class/usbtmc.c @@ -57,9 +57,7 @@ MODULE_DEVICE_TABLE(usb, usbtmc_devices); /* * This structure is the capabilities for the device - * See section 4.2.1.8 of the USBTMC specification, - * and section 4.2.2 of the USBTMC usb488 subclass - * specification for details. + * See section 4.2.1.8 of the USBTMC specification for details. */ struct usbtmc_dev_capabilities { __u8 interface_capabilities; @@ -88,8 +86,6 @@ struct usbtmc_device_data { bool TermCharEnabled; bool auto_abort; - bool zombie; /* fd of disconnected device */ - struct usbtmc_dev_capabilities capabilities; struct kref kref; struct mutex io_mutex; /* only one i/o function running at a time */ @@ -371,13 +367,13 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, { struct usbtmc_device_data *data; struct device *dev; - u32 n_characters; + unsigned long int n_characters; u8 *buffer; int actual; - size_t done; - size_t remaining; + int done; + int remaining; int retval; - size_t this_part; + int this_part; /* Get pointer to private data structure */ data = filp->private_data; @@ -388,10 +384,6 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, return -ENOMEM; mutex_lock(&data->io_mutex); - if (data->zombie) { - retval = -ENODEV; - goto exit; - } remaining = count; done = 0; @@ -409,10 +401,10 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, buffer[1] = data->bTag; buffer[2] = ~(data->bTag); buffer[3] = 0; /* Reserved */ - buffer[4] = (this_part) & 255; - buffer[5] = ((this_part) >> 8) & 255; - buffer[6] = ((this_part) >> 16) & 255; - buffer[7] = ((this_part) >> 24) & 255; + buffer[4] = (this_part - 12 - 3) & 255; + buffer[5] = ((this_part - 12 - 3) >> 8) & 255; + buffer[6] = ((this_part - 12 - 3) >> 16) & 255; + buffer[7] = ((this_part - 12 - 3) >> 24) & 255; buffer[8] = data->TermCharEnabled * 2; /* Use term character? */ buffer[9] = data->TermChar; @@ -463,22 +455,6 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, (buffer[6] << 16) + (buffer[7] << 24); - /* Ensure the instrument doesn't lie about it */ - if(n_characters > actual - 12) { - dev_err(dev, "Device lies about message size: %u > %d\n", n_characters, actual - 12); - n_characters = actual - 12; - } - - /* Ensure the instrument doesn't send more back than requested */ - if(n_characters > this_part) { - dev_err(dev, "Device returns more than requested: %zu > %zu\n", done + n_characters, done + this_part); - n_characters = this_part; - } - - /* Bound amount of data received by amount of data requested */ - if (n_characters > this_part) - n_characters = this_part; - /* Copy buffer to user space */ if (copy_to_user(buf + done, &buffer[12], n_characters)) { /* There must have been an addressing problem */ @@ -487,11 +463,8 @@ static ssize_t usbtmc_read(struct file *filp, char __user *buf, } done += n_characters; - /* Terminate if end-of-message bit recieved from device */ - if ((buffer[8] & 0x01) && (actual >= n_characters + 12)) + if (n_characters < USBTMC_SIZE_IOBUFFER) remaining = 0; - else - remaining -= n_characters; } /* Update file position value */ @@ -523,10 +496,6 @@ static ssize_t usbtmc_write(struct file *filp, const char __user *buf, return -ENOMEM; mutex_lock(&data->io_mutex); - if (data->zombie) { - retval = -ENODEV; - goto exit; - } remaining = count; done = 0; @@ -798,21 +767,20 @@ static int get_capabilities(struct usbtmc_device_data *data) } dev_dbg(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); + dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]); + dev_dbg(dev, "Device capabilities are %x\n", buffer[5]); + dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]); + dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); if (buffer[0] != USBTMC_STATUS_SUCCESS) { dev_err(dev, "GET_CAPABILITIES returned %x\n", buffer[0]); rv = -EPERM; goto err_out; } - dev_dbg(dev, "Interface capabilities are %x\n", buffer[4]); - dev_dbg(dev, "Device capabilities are %x\n", buffer[5]); - dev_dbg(dev, "USB488 interface capabilities are %x\n", buffer[14]); - dev_dbg(dev, "USB488 device capabilities are %x\n", buffer[15]); data->capabilities.interface_capabilities = buffer[4]; data->capabilities.device_capabilities = buffer[5]; data->capabilities.usb488_interface_capabilities = buffer[14]; data->capabilities.usb488_device_capabilities = buffer[15]; - rv = 0; err_out: kfree(buffer); @@ -957,10 +925,6 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) data = file->private_data; mutex_lock(&data->io_mutex); - if (data->zombie) { - retval = -ENODEV; - goto skip_io_on_zombie; - } switch (cmd) { case USBTMC_IOCTL_CLEAR_OUT_HALT: @@ -988,7 +952,6 @@ static long usbtmc_ioctl(struct file *file, unsigned int cmd, unsigned long arg) break; } -skip_io_on_zombie: mutex_unlock(&data->io_mutex); return retval; } @@ -1032,7 +995,6 @@ static int usbtmc_probe(struct usb_interface *intf, usb_set_intfdata(intf, data); kref_init(&data->kref); mutex_init(&data->io_mutex); - data->zombie = 0; /* Initialize USBTMC bTag and other fields */ data->bTag = 1; @@ -1103,30 +1065,14 @@ static void usbtmc_disconnect(struct usb_interface *intf) usb_deregister_dev(intf, &usbtmc_class); sysfs_remove_group(&intf->dev.kobj, &capability_attr_grp); sysfs_remove_group(&intf->dev.kobj, &data_attr_grp); - mutex_lock(&data->io_mutex); - data->zombie = 1; - mutex_unlock(&data->io_mutex); kref_put(&data->kref, usbtmc_delete); } -static int usbtmc_suspend (struct usb_interface *intf, pm_message_t message) -{ - /* this driver does not have pending URBs */ - return 0; -} - -static int usbtmc_resume (struct usb_interface *intf) -{ - return 0; -} - static struct usb_driver usbtmc_driver = { .name = "usbtmc", .id_table = usbtmc_devices, .probe = usbtmc_probe, - .disconnect = usbtmc_disconnect, - .suspend = usbtmc_suspend, - .resume = usbtmc_resume, + .disconnect = usbtmc_disconnect }; static int __init usbtmc_init(void) diff --git a/trunk/drivers/usb/core/config.c b/trunk/drivers/usb/core/config.c index 0d3af6a6ee49..a16c538d0132 100644 --- a/trunk/drivers/usb/core/config.c +++ b/trunk/drivers/usb/core/config.c @@ -105,7 +105,7 @@ static int usb_parse_ss_endpoint_companion(struct device *ddev, int cfgno, ep->ss_ep_comp->extralen = i; buffer += i; size -= i; - retval = buffer - buffer_start; + retval = buffer - buffer_start + i; if (num_skipped > 0) dev_dbg(ddev, "skipped %d descriptor%s after %s\n", num_skipped, plural(num_skipped), diff --git a/trunk/drivers/usb/core/devio.c b/trunk/drivers/usb/core/devio.c index 181f78c84105..4247eccf858c 100644 --- a/trunk/drivers/usb/core/devio.c +++ b/trunk/drivers/usb/core/devio.c @@ -52,7 +52,6 @@ #include "hcd.h" /* for usbcore internals */ #include "usb.h" -#include "hub.h" #define USB_MAXBUS 64 #define USB_DEVICE_MAX USB_MAXBUS * 128 @@ -74,7 +73,6 @@ struct dev_state { void __user *disccontext; unsigned long ifclaimed; u32 secid; - u32 disabled_bulk_eps; }; struct async { @@ -89,8 +87,6 @@ struct async { struct urb *urb; int status; u32 secid; - u8 bulk_addr; - u8 bulk_status; }; static int usbfs_snoop; @@ -103,14 +99,10 @@ MODULE_PARM_DESC(usbfs_snoop, "true to log all usbfs traffic"); dev_info(dev , format , ## arg); \ } while (0) -enum snoop_when { - SUBMIT, COMPLETE -}; - #define USB_DEVICE_DEV MKDEV(USB_DEVICE_MAJOR, 0) -#define MAX_USBFS_BUFFER_SIZE 16384 +#define MAX_USBFS_BUFFER_SIZE 16384 static int connected(struct dev_state *ps) { @@ -308,79 +300,24 @@ static struct async *async_getpending(struct dev_state *ps, return NULL; } -static void snoop_urb(struct usb_device *udev, - void __user *userurb, int pipe, unsigned length, - int timeout_or_status, enum snoop_when when) +static void snoop_urb(struct urb *urb, void __user *userurb) { - static const char *types[] = {"isoc", "int", "ctrl", "bulk"}; - static const char *dirs[] = {"out", "in"}; - int ep; - const char *t, *d; + unsigned j; + unsigned char *data = urb->transfer_buffer; if (!usbfs_snoop) return; - ep = usb_pipeendpoint(pipe); - t = types[usb_pipetype(pipe)]; - d = dirs[!!usb_pipein(pipe)]; - - if (userurb) { /* Async */ - if (when == SUBMIT) - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " - "length %u\n", - userurb, ep, t, d, length); - else - dev_info(&udev->dev, "userurb %p, ep%d %s-%s, " - "actual_length %u status %d\n", - userurb, ep, t, d, length, - timeout_or_status); - } else { - if (when == SUBMIT) - dev_info(&udev->dev, "ep%d %s-%s, length %u, " - "timeout %d\n", - ep, t, d, length, timeout_or_status); - else - dev_info(&udev->dev, "ep%d %s-%s, actual_length %u, " - "status %d\n", - ep, t, d, length, timeout_or_status); - } -} - -#define AS_CONTINUATION 1 -#define AS_UNLINK 2 - -static void cancel_bulk_urbs(struct dev_state *ps, unsigned bulk_addr) -__releases(ps->lock) -__acquires(ps->lock) -{ - struct async *as; - - /* Mark all the pending URBs that match bulk_addr, up to but not - * including the first one without AS_CONTINUATION. If such an - * URB is encountered then a new transfer has already started so - * the endpoint doesn't need to be disabled; otherwise it does. - */ - list_for_each_entry(as, &ps->async_pending, asynclist) { - if (as->bulk_addr == bulk_addr) { - if (as->bulk_status != AS_CONTINUATION) - goto rescan; - as->bulk_status = AS_UNLINK; - as->bulk_addr = 0; - } - } - ps->disabled_bulk_eps |= (1 << bulk_addr); - - /* Now carefully unlink all the marked pending URBs */ - rescan: - list_for_each_entry(as, &ps->async_pending, asynclist) { - if (as->bulk_status == AS_UNLINK) { - as->bulk_status = 0; /* Only once */ - spin_unlock(&ps->lock); /* Allow completions */ - usb_unlink_urb(as->urb); - spin_lock(&ps->lock); - goto rescan; - } - } + dev_info(&urb->dev->dev, "direction=%s\n", + usb_urb_dir_in(urb) ? "IN" : "OUT"); + dev_info(&urb->dev->dev, "userurb=%p\n", userurb); + dev_info(&urb->dev->dev, "transfer_buffer_length=%u\n", + urb->transfer_buffer_length); + dev_info(&urb->dev->dev, "actual_length=%u\n", urb->actual_length); + dev_info(&urb->dev->dev, "data: "); + for (j = 0; j < urb->transfer_buffer_length; ++j) + printk("%02x ", data[j]); + printk("\n"); } static void async_completed(struct urb *urb) @@ -409,11 +346,7 @@ static void async_completed(struct urb *urb) secid = as->secid; } snoop(&urb->dev->dev, "urb complete\n"); - snoop_urb(urb->dev, as->userurb, urb->pipe, urb->actual_length, - as->status, COMPLETE); - if (as->status < 0 && as->bulk_addr && as->status != -ECONNRESET && - as->status != -ENOENT) - cancel_bulk_urbs(ps, as->bulk_addr); + snoop_urb(urb, as->userurb); spin_unlock(&ps->lock); if (signr) @@ -722,7 +655,6 @@ static int usbdev_release(struct inode *inode, struct file *file) struct async *as; usb_lock_device(dev); - usb_hub_release_all_ports(dev, ps); /* Protect against simultaneous open */ mutex_lock(&usbfs_mutex); @@ -756,7 +688,7 @@ static int proc_control(struct dev_state *ps, void __user *arg) unsigned int tmo; unsigned char *tbuf; unsigned wLength; - int i, pipe, ret; + int i, j, ret; if (copy_from_user(&ctrl, arg, sizeof(ctrl))) return -EFAULT; @@ -776,17 +708,24 @@ static int proc_control(struct dev_state *ps, void __user *arg) free_page((unsigned long)tbuf); return -EINVAL; } - pipe = usb_rcvctrlpipe(dev, 0); - snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT); + snoop(&dev->dev, "control read: bRequest=%02x " + "bRrequestType=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, + ctrl.wIndex, ctrl.wLength); usb_unlock_device(dev); - i = usb_control_msg(dev, pipe, ctrl.bRequest, + i = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo); usb_lock_device(dev); - snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE); - if ((i > 0) && ctrl.wLength) { + if (usbfs_snoop) { + dev_info(&dev->dev, "control read: data "); + for (j = 0; j < i; ++j) + printk("%02x ", (u8)(tbuf)[j]); + printk("\n"); + } if (copy_to_user(ctrl.data, tbuf, i)) { free_page((unsigned long)tbuf); return -EFAULT; @@ -799,15 +738,22 @@ static int proc_control(struct dev_state *ps, void __user *arg) return -EFAULT; } } - pipe = usb_sndctrlpipe(dev, 0); - snoop_urb(dev, NULL, pipe, ctrl.wLength, tmo, SUBMIT); - + snoop(&dev->dev, "control write: bRequest=%02x " + "bRrequestType=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, + ctrl.wIndex, ctrl.wLength); + if (usbfs_snoop) { + dev_info(&dev->dev, "control write: data: "); + for (j = 0; j < ctrl.wLength; ++j) + printk("%02x ", (unsigned char)(tbuf)[j]); + printk("\n"); + } usb_unlock_device(dev); i = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), ctrl.bRequest, ctrl.bRequestType, ctrl.wValue, ctrl.wIndex, tbuf, ctrl.wLength, tmo); usb_lock_device(dev); - snoop_urb(dev, NULL, pipe, max(i, 0), min(i, 0), COMPLETE); } free_page((unsigned long)tbuf); if (i < 0 && i != -EPIPE) { @@ -826,7 +772,7 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) unsigned int tmo, len1, pipe; int len2; unsigned char *tbuf; - int i, ret; + int i, j, ret; if (copy_from_user(&bulk, arg, sizeof(bulk))) return -EFAULT; @@ -853,14 +799,18 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) kfree(tbuf); return -EINVAL; } - snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT); - + snoop(&dev->dev, "bulk read: len=0x%02x timeout=%04d\n", + bulk.len, bulk.timeout); usb_unlock_device(dev); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); usb_lock_device(dev); - snoop_urb(dev, NULL, pipe, len2, i, COMPLETE); - if (!i && len2) { + if (usbfs_snoop) { + dev_info(&dev->dev, "bulk read: data "); + for (j = 0; j < len2; ++j) + printk("%02x ", (u8)(tbuf)[j]); + printk("\n"); + } if (copy_to_user(bulk.data, tbuf, len2)) { kfree(tbuf); return -EFAULT; @@ -873,12 +823,17 @@ static int proc_bulk(struct dev_state *ps, void __user *arg) return -EFAULT; } } - snoop_urb(dev, NULL, pipe, len1, tmo, SUBMIT); - + snoop(&dev->dev, "bulk write: len=0x%02x timeout=%04d\n", + bulk.len, bulk.timeout); + if (usbfs_snoop) { + dev_info(&dev->dev, "bulk write: data: "); + for (j = 0; j < len1; ++j) + printk("%02x ", (unsigned char)(tbuf)[j]); + printk("\n"); + } usb_unlock_device(dev); i = usb_bulk_msg(dev, pipe, tbuf, len1, &len2, tmo); usb_lock_device(dev); - snoop_urb(dev, NULL, pipe, len2, i, COMPLETE); } kfree(tbuf); if (i < 0) @@ -1036,7 +991,6 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, if (uurb->flags & ~(USBDEVFS_URB_ISO_ASAP | USBDEVFS_URB_SHORT_NOT_OK | - USBDEVFS_URB_BULK_CONTINUATION | USBDEVFS_URB_NO_FSBR | USBDEVFS_URB_ZERO_PACKET | USBDEVFS_URB_NO_INTERRUPT)) @@ -1097,6 +1051,13 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, is_in = 0; uurb->endpoint &= ~USB_DIR_IN; } + snoop(&ps->dev->dev, "control urb: bRequest=%02x " + "bRrequestType=%02x wValue=%04x " + "wIndex=%04x wLength=%04x\n", + dr->bRequest, dr->bRequestType, + __le16_to_cpup(&dr->wValue), + __le16_to_cpup(&dr->wIndex), + __le16_to_cpup(&dr->wLength)); break; case USBDEVFS_URB_TYPE_BULK: @@ -1109,6 +1070,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, uurb->number_of_packets = 0; if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) return -EINVAL; + snoop(&ps->dev->dev, "bulk urb\n"); break; case USBDEVFS_URB_TYPE_ISO: @@ -1135,12 +1097,12 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, } totlen += isopkt[u].length; } - /* 3072 * 64 microframes */ - if (totlen > 196608) { + if (totlen > 32768) { kfree(isopkt); return -EINVAL; } uurb->buffer_length = totlen; + snoop(&ps->dev->dev, "iso urb\n"); break; case USBDEVFS_URB_TYPE_INTERRUPT: @@ -1149,6 +1111,7 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EINVAL; if (uurb->buffer_length > MAX_USBFS_BUFFER_SIZE) return -EINVAL; + snoop(&ps->dev->dev, "interrupt urb\n"); break; default: @@ -1235,46 +1198,11 @@ static int proc_do_submiturb(struct dev_state *ps, struct usbdevfs_urb *uurb, return -EFAULT; } } - snoop_urb(ps->dev, as->userurb, as->urb->pipe, - as->urb->transfer_buffer_length, 0, SUBMIT); + snoop_urb(as->urb, as->userurb); async_newpending(as); - - if (usb_endpoint_xfer_bulk(&ep->desc)) { - spin_lock_irq(&ps->lock); - - /* Not exactly the endpoint address; the direction bit is - * shifted to the 0x10 position so that the value will be - * between 0 and 31. - */ - as->bulk_addr = usb_endpoint_num(&ep->desc) | - ((ep->desc.bEndpointAddress & USB_ENDPOINT_DIR_MASK) - >> 3); - - /* If this bulk URB is the start of a new transfer, re-enable - * the endpoint. Otherwise mark it as a continuation URB. - */ - if (uurb->flags & USBDEVFS_URB_BULK_CONTINUATION) - as->bulk_status = AS_CONTINUATION; - else - ps->disabled_bulk_eps &= ~(1 << as->bulk_addr); - - /* Don't accept continuation URBs if the endpoint is - * disabled because of an earlier error. - */ - if (ps->disabled_bulk_eps & (1 << as->bulk_addr)) - ret = -EREMOTEIO; - else - ret = usb_submit_urb(as->urb, GFP_ATOMIC); - spin_unlock_irq(&ps->lock); - } else { - ret = usb_submit_urb(as->urb, GFP_KERNEL); - } - - if (ret) { + if ((ret = usb_submit_urb(as->urb, GFP_KERNEL))) { dev_printk(KERN_DEBUG, &ps->dev->dev, "usbfs: usb_submit_urb returned %d\n", ret); - snoop_urb(ps->dev, as->userurb, as->urb->pipe, - 0, ret, COMPLETE); async_removepending(as); free_async(as); return ret; @@ -1620,29 +1548,6 @@ static int proc_ioctl_compat(struct dev_state *ps, compat_uptr_t arg) } #endif -static int proc_claim_port(struct dev_state *ps, void __user *arg) -{ - unsigned portnum; - int rc; - - if (get_user(portnum, (unsigned __user *) arg)) - return -EFAULT; - rc = usb_hub_claim_port(ps->dev, portnum, ps); - if (rc == 0) - snoop(&ps->dev->dev, "port %d claimed by process %d: %s\n", - portnum, task_pid_nr(current), current->comm); - return rc; -} - -static int proc_release_port(struct dev_state *ps, void __user *arg) -{ - unsigned portnum; - - if (get_user(portnum, (unsigned __user *) arg)) - return -EFAULT; - return usb_hub_release_port(ps->dev, portnum, ps); -} - /* * NOTE: All requests here that have interface numbers as parameters * are assuming that somehow the configuration has been prevented from @@ -1740,7 +1645,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, break; case USBDEVFS_REAPURBNDELAY32: - snoop(&dev->dev, "%s: REAPURBNDELAY32\n", __func__); + snoop(&dev->dev, "%s: REAPURBDELAY32\n", __func__); ret = proc_reapurbnonblock_compat(ps, p); break; @@ -1761,7 +1666,7 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, break; case USBDEVFS_REAPURBNDELAY: - snoop(&dev->dev, "%s: REAPURBNDELAY\n", __func__); + snoop(&dev->dev, "%s: REAPURBDELAY\n", __func__); ret = proc_reapurbnonblock(ps, p); break; @@ -1784,16 +1689,6 @@ static int usbdev_ioctl(struct inode *inode, struct file *file, snoop(&dev->dev, "%s: IOCTL\n", __func__); ret = proc_ioctl_default(ps, p); break; - - case USBDEVFS_CLAIM_PORT: - snoop(&dev->dev, "%s: CLAIM_PORT\n", __func__); - ret = proc_claim_port(ps, p); - break; - - case USBDEVFS_RELEASE_PORT: - snoop(&dev->dev, "%s: RELEASE_PORT\n", __func__); - ret = proc_release_port(ps, p); - break; } usb_unlock_device(dev); if (ret >= 0) diff --git a/trunk/drivers/usb/core/driver.c b/trunk/drivers/usb/core/driver.c index 4f864472c5c4..69e5773abfce 100644 --- a/trunk/drivers/usb/core/driver.c +++ b/trunk/drivers/usb/core/driver.c @@ -207,9 +207,6 @@ static int usb_probe_interface(struct device *dev) intf->needs_binding = 0; - if (usb_device_is_owned(udev)) - return -ENODEV; - if (udev->authorized == 0) { dev_err(&intf->dev, "Device is not authorized for usage\n"); return -ENODEV; @@ -235,35 +232,28 @@ static int usb_probe_interface(struct device *dev) /* The interface should always appear to be in use * unless the driver suports autosuspend. */ - atomic_set(&intf->pm_usage_cnt, !driver->supports_autosuspend); + intf->pm_usage_cnt = !(driver->supports_autosuspend); /* Carry out a deferred switch to altsetting 0 */ if (intf->needs_altsetting0) { - error = usb_set_interface(udev, intf->altsetting[0]. + usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); - if (error < 0) - goto err; - intf->needs_altsetting0 = 0; } error = driver->probe(intf, id); - if (error) - goto err; + if (error) { + mark_quiesced(intf); + intf->needs_remote_wakeup = 0; + intf->condition = USB_INTERFACE_UNBOUND; + usb_cancel_queued_reset(intf); + } else + intf->condition = USB_INTERFACE_BOUND; - intf->condition = USB_INTERFACE_BOUND; usb_autosuspend_device(udev); } return error; - -err: - mark_quiesced(intf); - intf->needs_remote_wakeup = 0; - intf->condition = USB_INTERFACE_UNBOUND; - usb_cancel_queued_reset(intf); - usb_autosuspend_device(udev); - return error; } /* called from driver core with dev locked */ @@ -272,7 +262,7 @@ static int usb_unbind_interface(struct device *dev) struct usb_driver *driver = to_usb_driver(dev->driver); struct usb_interface *intf = to_usb_interface(dev); struct usb_device *udev; - int error, r; + int error; intf->condition = USB_INTERFACE_UNBINDING; @@ -300,14 +290,11 @@ static int usb_unbind_interface(struct device *dev) * Just re-enable it without affecting the endpoint toggles. */ usb_enable_interface(udev, intf, false); - } else if (!error && intf->dev.power.status == DPM_ON) { - r = usb_set_interface(udev, intf->altsetting[0]. + } else if (!error && intf->dev.power.status == DPM_ON) + usb_set_interface(udev, intf->altsetting[0]. desc.bInterfaceNumber, 0); - if (r < 0) - intf->needs_altsetting0 = 1; - } else { + else intf->needs_altsetting0 = 1; - } usb_set_intfdata(intf, NULL); intf->condition = USB_INTERFACE_UNBOUND; @@ -357,7 +344,7 @@ int usb_driver_claim_interface(struct usb_driver *driver, usb_pm_lock(udev); iface->condition = USB_INTERFACE_BOUND; mark_active(iface); - atomic_set(&iface->pm_usage_cnt, !driver->supports_autosuspend); + iface->pm_usage_cnt = !(driver->supports_autosuspend); usb_pm_unlock(udev); /* if interface was already added, bind now; else let @@ -1078,7 +1065,7 @@ static int autosuspend_check(struct usb_device *udev, int reschedule) intf = udev->actconfig->interface[i]; if (!is_active(intf)) continue; - if (atomic_read(&intf->pm_usage_cnt) > 0) + if (intf->pm_usage_cnt > 0) return -EBUSY; if (intf->needs_remote_wakeup && !udev->do_remote_wakeup) { @@ -1474,19 +1461,17 @@ static int usb_autopm_do_interface(struct usb_interface *intf, status = -ENODEV; else { udev->auto_pm = 1; - atomic_add(inc_usage_cnt, &intf->pm_usage_cnt); + intf->pm_usage_cnt += inc_usage_cnt; udev->last_busy = jiffies; - if (inc_usage_cnt >= 0 && - atomic_read(&intf->pm_usage_cnt) > 0) { + if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) { if (udev->state == USB_STATE_SUSPENDED) status = usb_resume_both(udev, PMSG_AUTO_RESUME); if (status != 0) - atomic_sub(inc_usage_cnt, &intf->pm_usage_cnt); + intf->pm_usage_cnt -= inc_usage_cnt; else udev->last_busy = jiffies; - } else if (inc_usage_cnt <= 0 && - atomic_read(&intf->pm_usage_cnt) <= 0) { + } else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) { status = usb_suspend_both(udev, PMSG_AUTO_SUSPEND); } } @@ -1531,7 +1516,7 @@ void usb_autopm_put_interface(struct usb_interface *intf) status = usb_autopm_do_interface(intf, -1); dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", - __func__, status, atomic_read(&intf->pm_usage_cnt)); + __func__, status, intf->pm_usage_cnt); } EXPORT_SYMBOL_GPL(usb_autopm_put_interface); @@ -1559,10 +1544,10 @@ void usb_autopm_put_interface_async(struct usb_interface *intf) status = -ENODEV; } else { udev->last_busy = jiffies; - atomic_dec(&intf->pm_usage_cnt); + --intf->pm_usage_cnt; if (udev->autosuspend_disabled || udev->autosuspend_delay < 0) status = -EPERM; - else if (atomic_read(&intf->pm_usage_cnt) <= 0 && + else if (intf->pm_usage_cnt <= 0 && !timer_pending(&udev->autosuspend.timer)) { queue_delayed_work(ksuspend_usb_wq, &udev->autosuspend, round_jiffies_up_relative( @@ -1570,7 +1555,7 @@ void usb_autopm_put_interface_async(struct usb_interface *intf) } } dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", - __func__, status, atomic_read(&intf->pm_usage_cnt)); + __func__, status, intf->pm_usage_cnt); } EXPORT_SYMBOL_GPL(usb_autopm_put_interface_async); @@ -1614,7 +1599,7 @@ int usb_autopm_get_interface(struct usb_interface *intf) status = usb_autopm_do_interface(intf, 1); dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", - __func__, status, atomic_read(&intf->pm_usage_cnt)); + __func__, status, intf->pm_usage_cnt); return status; } EXPORT_SYMBOL_GPL(usb_autopm_get_interface); @@ -1642,14 +1627,10 @@ int usb_autopm_get_interface_async(struct usb_interface *intf) status = -ENODEV; else if (udev->autoresume_disabled) status = -EPERM; - else { - atomic_inc(&intf->pm_usage_cnt); - if (atomic_read(&intf->pm_usage_cnt) > 0 && - udev->state == USB_STATE_SUSPENDED) - queue_work(ksuspend_usb_wq, &udev->autoresume); - } + else if (++intf->pm_usage_cnt > 0 && udev->state == USB_STATE_SUSPENDED) + queue_work(ksuspend_usb_wq, &udev->autoresume); dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", - __func__, status, atomic_read(&intf->pm_usage_cnt)); + __func__, status, intf->pm_usage_cnt); return status; } EXPORT_SYMBOL_GPL(usb_autopm_get_interface_async); @@ -1671,7 +1652,7 @@ int usb_autopm_set_interface(struct usb_interface *intf) status = usb_autopm_do_interface(intf, 0); dev_vdbg(&intf->dev, "%s: status %d cnt %d\n", - __func__, status, atomic_read(&intf->pm_usage_cnt)); + __func__, status, intf->pm_usage_cnt); return status; } EXPORT_SYMBOL_GPL(usb_autopm_set_interface); diff --git a/trunk/drivers/usb/core/generic.c b/trunk/drivers/usb/core/generic.c index 05e6d313961e..30ecac3af15a 100644 --- a/trunk/drivers/usb/core/generic.c +++ b/trunk/drivers/usb/core/generic.c @@ -158,9 +158,7 @@ static int generic_probe(struct usb_device *udev) /* Choose and set the configuration. This registers the interfaces * with the driver core and lets interface drivers bind to them. */ - if (usb_device_is_owned(udev)) - ; /* Don't configure if the device is owned */ - else if (udev->authorized == 0) + if (udev->authorized == 0) dev_err(&udev->dev, "Device is not authorized for usage\n"); else { c = usb_choose_configuration(udev); diff --git a/trunk/drivers/usb/core/hcd.c b/trunk/drivers/usb/core/hcd.c index 34de475f016e..95ccfa0b9fc5 100644 --- a/trunk/drivers/usb/core/hcd.c +++ b/trunk/drivers/usb/core/hcd.c @@ -337,89 +337,72 @@ static const u8 ss_rh_config_descriptor[] = { /*-------------------------------------------------------------------------*/ -/** - * ascii2desc() - Helper routine for producing UTF-16LE string descriptors - * @s: Null-terminated ASCII (actually ISO-8859-1) string - * @buf: Buffer for USB string descriptor (header + UTF-16LE) - * @len: Length (in bytes; may be odd) of descriptor buffer. - * - * The return value is the number of bytes filled in: 2 + 2*strlen(s) or - * buflen, whichever is less. - * - * USB String descriptors can contain at most 126 characters; input - * strings longer than that are truncated. +/* + * helper routine for returning string descriptors in UTF-16LE + * input can actually be ISO-8859-1; ASCII is its 7-bit subset */ -static unsigned -ascii2desc(char const *s, u8 *buf, unsigned len) +static unsigned ascii2utf(char *s, u8 *utf, int utfmax) { - unsigned n, t = 2 + 2*strlen(s); + unsigned retval; - if (t > 254) - t = 254; /* Longest possible UTF string descriptor */ - if (len > t) - len = t; - - t += USB_DT_STRING << 8; /* Now t is first 16 bits to store */ - - n = len; - while (n--) { - *buf++ = t; - if (!n--) - break; - *buf++ = t >> 8; - t = (unsigned char)*s++; + for (retval = 0; *s && utfmax > 1; utfmax -= 2, retval += 2) { + *utf++ = *s++; + *utf++ = 0; } - return len; + if (utfmax > 0) { + *utf = *s; + ++retval; + } + return retval; } -/** - * rh_string() - provides string descriptors for root hub - * @id: the string ID number (0: langids, 1: serial #, 2: product, 3: vendor) +/* + * rh_string - provides manufacturer, product and serial strings for root hub + * @id: the string ID number (1: serial number, 2: product, 3: vendor) * @hcd: the host controller for this root hub - * @data: buffer for output packet - * @len: length of the provided buffer + * @data: return packet in UTF-16 LE + * @len: length of the return packet * * Produces either a manufacturer, product or serial number string for the * virtual root hub device. - * Returns the number of bytes filled in: the length of the descriptor or - * of the provided buffer, whichever is less. */ -static unsigned -rh_string(int id, struct usb_hcd const *hcd, u8 *data, unsigned len) +static unsigned rh_string(int id, struct usb_hcd *hcd, u8 *data, unsigned len) { - char buf[100]; - char const *s; - static char const langids[4] = {4, USB_DT_STRING, 0x09, 0x04}; + char buf [100]; // language ids - switch (id) { - case 0: - /* Array of LANGID codes (0x0409 is MSFT-speak for "en-us") */ - /* See http://www.usb.org/developers/docs/USB_LANGIDs.pdf */ - if (len > 4) - len = 4; - memcpy(data, langids, len); + if (id == 0) { + buf[0] = 4; buf[1] = 3; /* 4 bytes string data */ + buf[2] = 0x09; buf[3] = 0x04; /* MSFT-speak for "en-us" */ + len = min_t(unsigned, len, 4); + memcpy (data, buf, len); return len; - case 1: - /* Serial number */ - s = hcd->self.bus_name; - break; - case 2: - /* Product name */ - s = hcd->product_desc; - break; - case 3: - /* Manufacturer */ + + // serial number + } else if (id == 1) { + strlcpy (buf, hcd->self.bus_name, sizeof buf); + + // product description + } else if (id == 2) { + strlcpy (buf, hcd->product_desc, sizeof buf); + + // id 3 == vendor description + } else if (id == 3) { snprintf (buf, sizeof buf, "%s %s %s", init_utsname()->sysname, init_utsname()->release, hcd->driver->description); - s = buf; - break; - default: - /* Can't happen; caller guarantees it */ - return 0; } - return ascii2desc(s, data, len); + switch (len) { /* All cases fall through */ + default: + len = 2 + ascii2utf (buf, data + 2, len - 2); + case 2: + data [1] = 3; /* type == string */ + case 1: + data [0] = 2 * (strlen (buf) + 1); + case 0: + ; /* Compiler wants a statement here */ + } + return len; } diff --git a/trunk/drivers/usb/core/hcd.h b/trunk/drivers/usb/core/hcd.h index 79782a1c43f6..ec5c67ea07b7 100644 --- a/trunk/drivers/usb/core/hcd.h +++ b/trunk/drivers/usb/core/hcd.h @@ -267,11 +267,6 @@ struct hc_driver { void (*reset_bandwidth)(struct usb_hcd *, struct usb_device *); /* Returns the hardware-chosen device address */ int (*address_device)(struct usb_hcd *, struct usb_device *udev); - /* Notifies the HCD after a hub descriptor is fetched. - * Will block. - */ - int (*update_hub_device)(struct usb_hcd *, struct usb_device *hdev, - struct usb_tt *tt, gfp_t mem_flags); }; extern int usb_hcd_link_urb_to_ep(struct usb_hcd *hcd, struct urb *urb); diff --git a/trunk/drivers/usb/core/hub.c b/trunk/drivers/usb/core/hub.c index 5ce839137ad6..71f86c60d83c 100644 --- a/trunk/drivers/usb/core/hub.c +++ b/trunk/drivers/usb/core/hub.c @@ -78,7 +78,6 @@ struct usb_hub { u8 indicator[USB_MAXCHILDREN]; struct delayed_work leds; struct delayed_work init_work; - void **port_owners; }; @@ -163,10 +162,8 @@ static inline char *portspeed(int portstatus) } /* Note that hdev or one of its children must be locked! */ -static struct usb_hub *hdev_to_hub(struct usb_device *hdev) +static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev) { - if (!hdev || !hdev->actconfig) - return NULL; return usb_get_intfdata(hdev->actconfig->interface[0]); } @@ -375,7 +372,7 @@ static void kick_khubd(struct usb_hub *hub) unsigned long flags; /* Suppress autosuspend until khubd runs */ - atomic_set(&to_usb_interface(hub->intfdev)->pm_usage_cnt, 1); + to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; spin_lock_irqsave(&hub_event_lock, flags); if (!hub->disconnected && list_empty(&hub->event_list)) { @@ -387,10 +384,8 @@ static void kick_khubd(struct usb_hub *hub) void usb_kick_khubd(struct usb_device *hdev) { - struct usb_hub *hub = hdev_to_hub(hdev); - - if (hub) - kick_khubd(hub); + /* FIXME: What if hdev isn't bound to the hub driver? */ + kick_khubd(hdev_to_hub(hdev)); } @@ -682,8 +677,7 @@ static void hub_activate(struct usb_hub *hub, enum hub_activation_type type) msecs_to_jiffies(delay)); /* Suppress autosuspend until init is done */ - atomic_set(&to_usb_interface(hub->intfdev)-> - pm_usage_cnt, 1); + to_usb_interface(hub->intfdev)->pm_usage_cnt = 1; return; /* Continues at init2: below */ } else { hub_power_on(hub, true); @@ -860,24 +854,25 @@ static int hub_post_reset(struct usb_interface *intf) static int hub_configure(struct usb_hub *hub, struct usb_endpoint_descriptor *endpoint) { - struct usb_hcd *hcd; struct usb_device *hdev = hub->hdev; struct device *hub_dev = hub->intfdev; u16 hubstatus, hubchange; u16 wHubCharacteristics; unsigned int pipe; int maxp, ret; - char *message = "out of memory"; + char *message; hub->buffer = usb_buffer_alloc(hdev, sizeof(*hub->buffer), GFP_KERNEL, &hub->buffer_dma); if (!hub->buffer) { + message = "can't allocate hub irq buffer"; ret = -ENOMEM; goto fail; } hub->status = kmalloc(sizeof(*hub->status), GFP_KERNEL); if (!hub->status) { + message = "can't kmalloc hub status buffer"; ret = -ENOMEM; goto fail; } @@ -885,6 +880,7 @@ static int hub_configure(struct usb_hub *hub, hub->descriptor = kmalloc(sizeof(*hub->descriptor), GFP_KERNEL); if (!hub->descriptor) { + message = "can't kmalloc hub descriptor"; ret = -ENOMEM; goto fail; } @@ -908,12 +904,6 @@ static int hub_configure(struct usb_hub *hub, dev_info (hub_dev, "%d port%s detected\n", hdev->maxchild, (hdev->maxchild == 1) ? "" : "s"); - hub->port_owners = kzalloc(hdev->maxchild * sizeof(void *), GFP_KERNEL); - if (!hub->port_owners) { - ret = -ENOMEM; - goto fail; - } - wHubCharacteristics = le16_to_cpu(hub->descriptor->wHubCharacteristics); if (wHubCharacteristics & HUB_CHAR_COMPOUND) { @@ -1062,19 +1052,6 @@ static int hub_configure(struct usb_hub *hub, dev_dbg(hub_dev, "%umA bus power budget for each child\n", hub->mA_per_port); - /* Update the HCD's internal representation of this hub before khubd - * starts getting port status changes for devices under the hub. - */ - hcd = bus_to_hcd(hdev->bus); - if (hcd->driver->update_hub_device) { - ret = hcd->driver->update_hub_device(hcd, hdev, - &hub->tt, GFP_KERNEL); - if (ret < 0) { - message = "can't update HCD hub info"; - goto fail; - } - } - ret = hub_hub_status(hub, &hubstatus, &hubchange); if (ret < 0) { message = "can't get hub status"; @@ -1105,6 +1082,7 @@ static int hub_configure(struct usb_hub *hub, hub->urb = usb_alloc_urb(0, GFP_KERNEL); if (!hub->urb) { + message = "couldn't allocate interrupt urb"; ret = -ENOMEM; goto fail; } @@ -1153,13 +1131,11 @@ static void hub_disconnect(struct usb_interface *intf) hub_quiesce(hub, HUB_DISCONNECT); usb_set_intfdata (intf, NULL); - hub->hdev->maxchild = 0; if (hub->hdev->speed == USB_SPEED_HIGH) highspeed_hubs--; usb_free_urb(hub->urb); - kfree(hub->port_owners); kfree(hub->descriptor); kfree(hub->status); usb_buffer_free(hub->hdev, sizeof(*hub->buffer), hub->buffer, @@ -1274,79 +1250,6 @@ hub_ioctl(struct usb_interface *intf, unsigned int code, void *user_data) } } -/* - * Allow user programs to claim ports on a hub. When a device is attached - * to one of these "claimed" ports, the program will "own" the device. - */ -static int find_port_owner(struct usb_device *hdev, unsigned port1, - void ***ppowner) -{ - if (hdev->state == USB_STATE_NOTATTACHED) - return -ENODEV; - if (port1 == 0 || port1 > hdev->maxchild) - return -EINVAL; - - /* This assumes that devices not managed by the hub driver - * will always have maxchild equal to 0. - */ - *ppowner = &(hdev_to_hub(hdev)->port_owners[port1 - 1]); - return 0; -} - -/* In the following three functions, the caller must hold hdev's lock */ -int usb_hub_claim_port(struct usb_device *hdev, unsigned port1, void *owner) -{ - int rc; - void **powner; - - rc = find_port_owner(hdev, port1, &powner); - if (rc) - return rc; - if (*powner) - return -EBUSY; - *powner = owner; - return rc; -} - -int usb_hub_release_port(struct usb_device *hdev, unsigned port1, void *owner) -{ - int rc; - void **powner; - - rc = find_port_owner(hdev, port1, &powner); - if (rc) - return rc; - if (*powner != owner) - return -ENOENT; - *powner = NULL; - return rc; -} - -void usb_hub_release_all_ports(struct usb_device *hdev, void *owner) -{ - int n; - void **powner; - - n = find_port_owner(hdev, 1, &powner); - if (n == 0) { - for (; n < hdev->maxchild; (++n, ++powner)) { - if (*powner == owner) - *powner = NULL; - } - } -} - -/* The caller must hold udev's lock */ -bool usb_device_is_owned(struct usb_device *udev) -{ - struct usb_hub *hub; - - if (udev->state == USB_STATE_NOTATTACHED || !udev->parent) - return false; - hub = hdev_to_hub(udev->parent); - return !!hub->port_owners[udev->portnum - 1]; -} - static void recursively_mark_NOTATTACHED(struct usb_device *udev) { @@ -2946,7 +2849,14 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1, /* For a suspended device, treat this as a * remote wakeup event. */ - status = remote_wakeup(udev); + if (udev->do_remote_wakeup) + status = remote_wakeup(udev); + + /* Otherwise leave it be; devices can't tell the + * difference between suspended and disabled. + */ + else + status = 0; #endif } else { diff --git a/trunk/drivers/usb/core/message.c b/trunk/drivers/usb/core/message.c index da718e84d58d..9720e699f472 100644 --- a/trunk/drivers/usb/core/message.c +++ b/trunk/drivers/usb/core/message.c @@ -459,23 +459,35 @@ int usb_sg_init(struct usb_sg_request *io, struct usb_device *dev, io->urbs[i]->context = io; /* - * Some systems need to revert to PIO when DMA is temporarily - * unavailable. For their sakes, both transfer_buffer and - * transfer_dma are set when possible. + * Some systems need to revert to PIO when DMA is + * temporarily unavailable. For their sakes, both + * transfer_buffer and transfer_dma are set when + * possible. However this can only work on systems + * without: * - * Note that if IOMMU coalescing occurred, we cannot - * trust sg_page anymore, so check if S/G list shrunk. + * - HIGHMEM, since DMA buffers located in high memory + * are not directly addressable by the CPU for PIO; + * + * - IOMMU, since dma_map_sg() is allowed to use an + * IOMMU to make virtually discontiguous buffers be + * "dma-contiguous" so that PIO and DMA need diferent + * numbers of URBs. + * + * So when HIGHMEM or IOMMU are in use, transfer_buffer + * is NULL to prevent stale pointers and to help spot + * bugs. */ - if (io->nents == io->entries && !PageHighMem(sg_page(sg))) - io->urbs[i]->transfer_buffer = sg_virt(sg); - else - io->urbs[i]->transfer_buffer = NULL; - if (dma) { io->urbs[i]->transfer_dma = sg_dma_address(sg); len = sg_dma_len(sg); +#if defined(CONFIG_HIGHMEM) || defined(CONFIG_GART_IOMMU) + io->urbs[i]->transfer_buffer = NULL; +#else + io->urbs[i]->transfer_buffer = sg_virt(sg); +#endif } else { /* hc may use _only_ transfer_buffer */ + io->urbs[i]->transfer_buffer = sg_virt(sg); len = sg->length; } diff --git a/trunk/drivers/usb/core/usb.c b/trunk/drivers/usb/core/usb.c index b1b85abb9a2d..43ee943d757a 100644 --- a/trunk/drivers/usb/core/usb.c +++ b/trunk/drivers/usb/core/usb.c @@ -413,13 +413,8 @@ struct usb_device *usb_alloc_dev(struct usb_device *parent, } else { snprintf(dev->devpath, sizeof dev->devpath, "%s.%d", parent->devpath, port1); - /* Route string assumes hubs have less than 16 ports */ - if (port1 < 15) - dev->route = parent->route + - (port1 << ((parent->level - 1)*4)); - else - dev->route = parent->route + - (15 << ((parent->level - 1)*4)); + dev->route = parent->route + + (port1 << ((parent->level - 1)*4)); } dev->dev.parent = &parent->dev; @@ -919,11 +914,11 @@ int usb_buffer_map_sg(const struct usb_device *dev, int is_in, || !(bus = dev->bus) || !(controller = bus->controller) || !controller->dma_mask) - return -EINVAL; + return -1; /* FIXME generic api broken like pci, can't report errors */ return dma_map_sg(controller, sg, nents, - is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE) ? : -ENOMEM; + is_in ? DMA_FROM_DEVICE : DMA_TO_DEVICE); } EXPORT_SYMBOL_GPL(usb_buffer_map_sg); diff --git a/trunk/drivers/usb/core/usb.h b/trunk/drivers/usb/core/usb.h index 9a8b15e6377a..c0e0ae2bb8e7 100644 --- a/trunk/drivers/usb/core/usb.h +++ b/trunk/drivers/usb/core/usb.h @@ -37,13 +37,6 @@ extern int usb_match_device(struct usb_device *dev, extern void usb_forced_unbind_intf(struct usb_interface *intf); extern void usb_rebind_intf(struct usb_interface *intf); -extern int usb_hub_claim_port(struct usb_device *hdev, unsigned port, - void *owner); -extern int usb_hub_release_port(struct usb_device *hdev, unsigned port, - void *owner); -extern void usb_hub_release_all_ports(struct usb_device *hdev, void *owner); -extern bool usb_device_is_owned(struct usb_device *udev); - extern int usb_hub_init(void); extern void usb_hub_cleanup(void); extern int usb_major_init(void); diff --git a/trunk/drivers/usb/early/Makefile b/trunk/drivers/usb/early/Makefile deleted file mode 100644 index dfedee8c45b6..000000000000 --- a/trunk/drivers/usb/early/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -# -# Makefile for early USB devices -# - -obj-$(CONFIG_EARLY_PRINTK_DBGP) += ehci-dbgp.o diff --git a/trunk/drivers/usb/early/ehci-dbgp.c b/trunk/drivers/usb/early/ehci-dbgp.c deleted file mode 100644 index 1206a26ef893..000000000000 --- a/trunk/drivers/usb/early/ehci-dbgp.c +++ /dev/null @@ -1,996 +0,0 @@ -/* - * Standalone EHCI usb debug driver - * - * Originally written by: - * Eric W. Biederman" and - * Yinghai Lu - * - * Changes for early/late printk and HW errata: - * Jason Wessel - * Copyright (C) 2009 Wind River Systems, Inc. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* The code here is intended to talk directly to the EHCI debug port - * and does not require that you have any kind of USB host controller - * drivers or USB device drivers compiled into the kernel. - * - * If you make a change to anything in here, the following test cases - * need to pass where a USB debug device works in the following - * configurations. - * - * 1. boot args: earlyprintk=dbgp - * o kernel compiled with # CONFIG_USB_EHCI_HCD is not set - * o kernel compiled with CONFIG_USB_EHCI_HCD=y - * 2. boot args: earlyprintk=dbgp,keep - * o kernel compiled with # CONFIG_USB_EHCI_HCD is not set - * o kernel compiled with CONFIG_USB_EHCI_HCD=y - * 3. boot args: earlyprintk=dbgp console=ttyUSB0 - * o kernel has CONFIG_USB_EHCI_HCD=y and - * CONFIG_USB_SERIAL_DEBUG=y - * 4. boot args: earlyprintk=vga,dbgp - * o kernel compiled with # CONFIG_USB_EHCI_HCD is not set - * o kernel compiled with CONFIG_USB_EHCI_HCD=y - * - * For the 4th configuration you can turn on or off the DBGP_DEBUG - * such that you can debug the dbgp device's driver code. - */ - -static int dbgp_phys_port = 1; - -static struct ehci_caps __iomem *ehci_caps; -static struct ehci_regs __iomem *ehci_regs; -static struct ehci_dbg_port __iomem *ehci_debug; -static int dbgp_not_safe; /* Cannot use debug device during ehci reset */ -static unsigned int dbgp_endpoint_out; - -struct ehci_dev { - u32 bus; - u32 slot; - u32 func; -}; - -static struct ehci_dev ehci_dev; - -#define USB_DEBUG_DEVNUM 127 - -#define DBGP_DATA_TOGGLE 0x8800 - -#ifdef DBGP_DEBUG -#define dbgp_printk printk -static void dbgp_ehci_status(char *str) -{ - if (!ehci_debug) - return; - dbgp_printk("dbgp: %s\n", str); - dbgp_printk(" Debug control: %08x", readl(&ehci_debug->control)); - dbgp_printk(" ehci cmd : %08x", readl(&ehci_regs->command)); - dbgp_printk(" ehci conf flg: %08x\n", - readl(&ehci_regs->configured_flag)); - dbgp_printk(" ehci status : %08x", readl(&ehci_regs->status)); - dbgp_printk(" ehci portsc : %08x\n", - readl(&ehci_regs->port_status[dbgp_phys_port - 1])); -} -#else -static inline void dbgp_ehci_status(char *str) { } -static inline void dbgp_printk(const char *fmt, ...) { } -#endif - -static inline u32 dbgp_pid_update(u32 x, u32 tok) -{ - return ((x ^ DBGP_DATA_TOGGLE) & 0xffff00) | (tok & 0xff); -} - -static inline u32 dbgp_len_update(u32 x, u32 len) -{ - return (x & ~0x0f) | (len & 0x0f); -} - -/* - * USB Packet IDs (PIDs) - */ - -/* token */ -#define USB_PID_OUT 0xe1 -#define USB_PID_IN 0x69 -#define USB_PID_SOF 0xa5 -#define USB_PID_SETUP 0x2d -/* handshake */ -#define USB_PID_ACK 0xd2 -#define USB_PID_NAK 0x5a -#define USB_PID_STALL 0x1e -#define USB_PID_NYET 0x96 -/* data */ -#define USB_PID_DATA0 0xc3 -#define USB_PID_DATA1 0x4b -#define USB_PID_DATA2 0x87 -#define USB_PID_MDATA 0x0f -/* Special */ -#define USB_PID_PREAMBLE 0x3c -#define USB_PID_ERR 0x3c -#define USB_PID_SPLIT 0x78 -#define USB_PID_PING 0xb4 -#define USB_PID_UNDEF_0 0xf0 - -#define USB_PID_DATA_TOGGLE 0x88 -#define DBGP_CLAIM (DBGP_OWNER | DBGP_ENABLED | DBGP_INUSE) - -#define PCI_CAP_ID_EHCI_DEBUG 0xa - -#define HUB_ROOT_RESET_TIME 50 /* times are in msec */ -#define HUB_SHORT_RESET_TIME 10 -#define HUB_LONG_RESET_TIME 200 -#define HUB_RESET_TIMEOUT 500 - -#define DBGP_MAX_PACKET 8 -#define DBGP_TIMEOUT (250 * 1000) - -static int dbgp_wait_until_complete(void) -{ - u32 ctrl; - int loop = DBGP_TIMEOUT; - - do { - ctrl = readl(&ehci_debug->control); - /* Stop when the transaction is finished */ - if (ctrl & DBGP_DONE) - break; - udelay(1); - } while (--loop > 0); - - if (!loop) - return -DBGP_TIMEOUT; - - /* - * Now that we have observed the completed transaction, - * clear the done bit. - */ - writel(ctrl | DBGP_DONE, &ehci_debug->control); - return (ctrl & DBGP_ERROR) ? -DBGP_ERRCODE(ctrl) : DBGP_LEN(ctrl); -} - -static inline void dbgp_mdelay(int ms) -{ - int i; - - while (ms--) { - for (i = 0; i < 1000; i++) - outb(0x1, 0x80); - } -} - -static void dbgp_breath(void) -{ - /* Sleep to give the debug port a chance to breathe */ -} - -static int dbgp_wait_until_done(unsigned ctrl) -{ - u32 pids, lpid; - int ret; - int loop = 3; - -retry: - writel(ctrl | DBGP_GO, &ehci_debug->control); - ret = dbgp_wait_until_complete(); - pids = readl(&ehci_debug->pids); - lpid = DBGP_PID_GET(pids); - - if (ret < 0) { - /* A -DBGP_TIMEOUT failure here means the device has - * failed, perhaps because it was unplugged, in which - * case we do not want to hang the system so the dbgp - * will be marked as unsafe to use. EHCI reset is the - * only way to recover if you unplug the dbgp device. - */ - if (ret == -DBGP_TIMEOUT && !dbgp_not_safe) - dbgp_not_safe = 1; - return ret; - } - - /* - * If the port is getting full or it has dropped data - * start pacing ourselves, not necessary but it's friendly. - */ - if ((lpid == USB_PID_NAK) || (lpid == USB_PID_NYET)) - dbgp_breath(); - - /* If I get a NACK reissue the transmission */ - if (lpid == USB_PID_NAK) { - if (--loop > 0) - goto retry; - } - - return ret; -} - -static inline void dbgp_set_data(const void *buf, int size) -{ - const unsigned char *bytes = buf; - u32 lo, hi; - int i; - - lo = hi = 0; - for (i = 0; i < 4 && i < size; i++) - lo |= bytes[i] << (8*i); - for (; i < 8 && i < size; i++) - hi |= bytes[i] << (8*(i - 4)); - writel(lo, &ehci_debug->data03); - writel(hi, &ehci_debug->data47); -} - -static inline void dbgp_get_data(void *buf, int size) -{ - unsigned char *bytes = buf; - u32 lo, hi; - int i; - - lo = readl(&ehci_debug->data03); - hi = readl(&ehci_debug->data47); - for (i = 0; i < 4 && i < size; i++) - bytes[i] = (lo >> (8*i)) & 0xff; - for (; i < 8 && i < size; i++) - bytes[i] = (hi >> (8*(i - 4))) & 0xff; -} - -static int dbgp_out(u32 addr, const char *bytes, int size) -{ - u32 pids, ctrl; - - pids = readl(&ehci_debug->pids); - pids = dbgp_pid_update(pids, USB_PID_OUT); - - ctrl = readl(&ehci_debug->control); - ctrl = dbgp_len_update(ctrl, size); - ctrl |= DBGP_OUT; - ctrl |= DBGP_GO; - - dbgp_set_data(bytes, size); - writel(addr, &ehci_debug->address); - writel(pids, &ehci_debug->pids); - return dbgp_wait_until_done(ctrl); -} - -static int dbgp_bulk_write(unsigned devnum, unsigned endpoint, - const char *bytes, int size) -{ - int ret; - int loops = 5; - u32 addr; - if (size > DBGP_MAX_PACKET) - return -1; - - addr = DBGP_EPADDR(devnum, endpoint); -try_again: - if (loops--) { - ret = dbgp_out(addr, bytes, size); - if (ret == -DBGP_ERR_BAD) { - int try_loops = 3; - do { - /* Emit a dummy packet to re-sync communication - * with the debug device */ - if (dbgp_out(addr, "12345678", 8) >= 0) { - udelay(2); - goto try_again; - } - } while (try_loops--); - } - } - - return ret; -} - -static int dbgp_bulk_read(unsigned devnum, unsigned endpoint, void *data, - int size) -{ - u32 pids, addr, ctrl; - int ret; - - if (size > DBGP_MAX_PACKET) - return -1; - - addr = DBGP_EPADDR(devnum, endpoint); - - pids = readl(&ehci_debug->pids); - pids = dbgp_pid_update(pids, USB_PID_IN); - - ctrl = readl(&ehci_debug->control); - ctrl = dbgp_len_update(ctrl, size); - ctrl &= ~DBGP_OUT; - ctrl |= DBGP_GO; - - writel(addr, &ehci_debug->address); - writel(pids, &ehci_debug->pids); - ret = dbgp_wait_until_done(ctrl); - if (ret < 0) - return ret; - - if (size > ret) - size = ret; - dbgp_get_data(data, size); - return ret; -} - -static int dbgp_control_msg(unsigned devnum, int requesttype, - int request, int value, int index, void *data, int size) -{ - u32 pids, addr, ctrl; - struct usb_ctrlrequest req; - int read; - int ret; - - read = (requesttype & USB_DIR_IN) != 0; - if (size > (read ? DBGP_MAX_PACKET:0)) - return -1; - - /* Compute the control message */ - req.bRequestType = requesttype; - req.bRequest = request; - req.wValue = cpu_to_le16(value); - req.wIndex = cpu_to_le16(index); - req.wLength = cpu_to_le16(size); - - pids = DBGP_PID_SET(USB_PID_DATA0, USB_PID_SETUP); - addr = DBGP_EPADDR(devnum, 0); - - ctrl = readl(&ehci_debug->control); - ctrl = dbgp_len_update(ctrl, sizeof(req)); - ctrl |= DBGP_OUT; - ctrl |= DBGP_GO; - - /* Send the setup message */ - dbgp_set_data(&req, sizeof(req)); - writel(addr, &ehci_debug->address); - writel(pids, &ehci_debug->pids); - ret = dbgp_wait_until_done(ctrl); - if (ret < 0) - return ret; - - /* Read the result */ - return dbgp_bulk_read(devnum, 0, data, size); -} - - -/* Find a PCI capability */ -static u32 __init find_cap(u32 num, u32 slot, u32 func, int cap) -{ - u8 pos; - int bytes; - - if (!(read_pci_config_16(num, slot, func, PCI_STATUS) & - PCI_STATUS_CAP_LIST)) - return 0; - - pos = read_pci_config_byte(num, slot, func, PCI_CAPABILITY_LIST); - for (bytes = 0; bytes < 48 && pos >= 0x40; bytes++) { - u8 id; - - pos &= ~3; - id = read_pci_config_byte(num, slot, func, pos+PCI_CAP_LIST_ID); - if (id == 0xff) - break; - if (id == cap) - return pos; - - pos = read_pci_config_byte(num, slot, func, - pos+PCI_CAP_LIST_NEXT); - } - return 0; -} - -static u32 __init __find_dbgp(u32 bus, u32 slot, u32 func) -{ - u32 class; - - class = read_pci_config(bus, slot, func, PCI_CLASS_REVISION); - if ((class >> 8) != PCI_CLASS_SERIAL_USB_EHCI) - return 0; - - return find_cap(bus, slot, func, PCI_CAP_ID_EHCI_DEBUG); -} - -static u32 __init find_dbgp(int ehci_num, u32 *rbus, u32 *rslot, u32 *rfunc) -{ - u32 bus, slot, func; - - for (bus = 0; bus < 256; bus++) { - for (slot = 0; slot < 32; slot++) { - for (func = 0; func < 8; func++) { - unsigned cap; - - cap = __find_dbgp(bus, slot, func); - - if (!cap) - continue; - if (ehci_num-- != 0) - continue; - *rbus = bus; - *rslot = slot; - *rfunc = func; - return cap; - } - } - } - return 0; -} - -static int dbgp_ehci_startup(void) -{ - u32 ctrl, cmd, status; - int loop; - - /* Claim ownership, but do not enable yet */ - ctrl = readl(&ehci_debug->control); - ctrl |= DBGP_OWNER; - ctrl &= ~(DBGP_ENABLED | DBGP_INUSE); - writel(ctrl, &ehci_debug->control); - udelay(1); - - dbgp_ehci_status("EHCI startup"); - /* Start the ehci running */ - cmd = readl(&ehci_regs->command); - cmd &= ~(CMD_LRESET | CMD_IAAD | CMD_PSE | CMD_ASE | CMD_RESET); - cmd |= CMD_RUN; - writel(cmd, &ehci_regs->command); - - /* Ensure everything is routed to the EHCI */ - writel(FLAG_CF, &ehci_regs->configured_flag); - - /* Wait until the controller is no longer halted */ - loop = 10; - do { - status = readl(&ehci_regs->status); - if (!(status & STS_HALT)) - break; - udelay(1); - } while (--loop > 0); - - if (!loop) { - dbgp_printk("ehci can not be started\n"); - return -ENODEV; - } - dbgp_printk("ehci started\n"); - return 0; -} - -static int dbgp_ehci_controller_reset(void) -{ - int loop = 250 * 1000; - u32 cmd; - - /* Reset the EHCI controller */ - cmd = readl(&ehci_regs->command); - cmd |= CMD_RESET; - writel(cmd, &ehci_regs->command); - do { - cmd = readl(&ehci_regs->command); - } while ((cmd & CMD_RESET) && (--loop > 0)); - - if (!loop) { - dbgp_printk("can not reset ehci\n"); - return -1; - } - dbgp_ehci_status("ehci reset done"); - return 0; -} -static int ehci_wait_for_port(int port); -/* Return 0 on success - * Return -ENODEV for any general failure - * Return -EIO if wait for port fails - */ -int dbgp_external_startup(void) -{ - int devnum; - struct usb_debug_descriptor dbgp_desc; - int ret; - u32 ctrl, portsc, cmd; - int dbg_port = dbgp_phys_port; - int tries = 3; - int reset_port_tries = 1; - int try_hard_once = 1; - -try_port_reset_again: - ret = dbgp_ehci_startup(); - if (ret) - return ret; - - /* Wait for a device to show up in the debug port */ - ret = ehci_wait_for_port(dbg_port); - if (ret < 0) { - portsc = readl(&ehci_regs->port_status[dbg_port - 1]); - if (!(portsc & PORT_CONNECT) && try_hard_once) { - /* Last ditch effort to try to force enable - * the debug device by using the packet test - * ehci command to try and wake it up. */ - try_hard_once = 0; - cmd = readl(&ehci_regs->command); - cmd &= ~CMD_RUN; - writel(cmd, &ehci_regs->command); - portsc = readl(&ehci_regs->port_status[dbg_port - 1]); - portsc |= PORT_TEST_PKT; - writel(portsc, &ehci_regs->port_status[dbg_port - 1]); - dbgp_ehci_status("Trying to force debug port online"); - mdelay(50); - dbgp_ehci_controller_reset(); - goto try_port_reset_again; - } else if (reset_port_tries--) { - goto try_port_reset_again; - } - dbgp_printk("No device found in debug port\n"); - return -EIO; - } - dbgp_ehci_status("wait for port done"); - - /* Enable the debug port */ - ctrl = readl(&ehci_debug->control); - ctrl |= DBGP_CLAIM; - writel(ctrl, &ehci_debug->control); - ctrl = readl(&ehci_debug->control); - if ((ctrl & DBGP_CLAIM) != DBGP_CLAIM) { - dbgp_printk("No device in debug port\n"); - writel(ctrl & ~DBGP_CLAIM, &ehci_debug->control); - return -ENODEV; - } - dbgp_ehci_status("debug ported enabled"); - - /* Completely transfer the debug device to the debug controller */ - portsc = readl(&ehci_regs->port_status[dbg_port - 1]); - portsc &= ~PORT_PE; - writel(portsc, &ehci_regs->port_status[dbg_port - 1]); - - dbgp_mdelay(100); - -try_again: - /* Find the debug device and make it device number 127 */ - for (devnum = 0; devnum <= 127; devnum++) { - ret = dbgp_control_msg(devnum, - USB_DIR_IN | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_REQ_GET_DESCRIPTOR, (USB_DT_DEBUG << 8), 0, - &dbgp_desc, sizeof(dbgp_desc)); - if (ret > 0) - break; - } - if (devnum > 127) { - dbgp_printk("Could not find attached debug device\n"); - goto err; - } - if (ret < 0) { - dbgp_printk("Attached device is not a debug device\n"); - goto err; - } - dbgp_endpoint_out = dbgp_desc.bDebugOutEndpoint; - - /* Move the device to 127 if it isn't already there */ - if (devnum != USB_DEBUG_DEVNUM) { - ret = dbgp_control_msg(devnum, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_REQ_SET_ADDRESS, USB_DEBUG_DEVNUM, 0, NULL, 0); - if (ret < 0) { - dbgp_printk("Could not move attached device to %d\n", - USB_DEBUG_DEVNUM); - goto err; - } - devnum = USB_DEBUG_DEVNUM; - dbgp_printk("debug device renamed to 127\n"); - } - - /* Enable the debug interface */ - ret = dbgp_control_msg(USB_DEBUG_DEVNUM, - USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE, - USB_REQ_SET_FEATURE, USB_DEVICE_DEBUG_MODE, 0, NULL, 0); - if (ret < 0) { - dbgp_printk(" Could not enable the debug device\n"); - goto err; - } - dbgp_printk("debug interface enabled\n"); - /* Perform a small write to get the even/odd data state in sync - */ - ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, dbgp_endpoint_out, " ", 1); - if (ret < 0) { - dbgp_printk("dbgp_bulk_write failed: %d\n", ret); - goto err; - } - dbgp_printk("small write doned\n"); - dbgp_not_safe = 0; - - return 0; -err: - if (tries--) - goto try_again; - return -ENODEV; -} -EXPORT_SYMBOL_GPL(dbgp_external_startup); - -static int __init ehci_reset_port(int port) -{ - u32 portsc; - u32 delay_time, delay; - int loop; - - dbgp_ehci_status("reset port"); - /* Reset the usb debug port */ - portsc = readl(&ehci_regs->port_status[port - 1]); - portsc &= ~PORT_PE; - portsc |= PORT_RESET; - writel(portsc, &ehci_regs->port_status[port - 1]); - - delay = HUB_ROOT_RESET_TIME; - for (delay_time = 0; delay_time < HUB_RESET_TIMEOUT; - delay_time += delay) { - dbgp_mdelay(delay); - portsc = readl(&ehci_regs->port_status[port - 1]); - if (!(portsc & PORT_RESET)) - break; - } - if (portsc & PORT_RESET) { - /* force reset to complete */ - loop = 100 * 1000; - writel(portsc & ~(PORT_RWC_BITS | PORT_RESET), - &ehci_regs->port_status[port - 1]); - do { - udelay(1); - portsc = readl(&ehci_regs->port_status[port-1]); - } while ((portsc & PORT_RESET) && (--loop > 0)); - } - - /* Device went away? */ - if (!(portsc & PORT_CONNECT)) - return -ENOTCONN; - - /* bomb out completely if something weird happend */ - if ((portsc & PORT_CSC)) - return -EINVAL; - - /* If we've finished resetting, then break out of the loop */ - if (!(portsc & PORT_RESET) && (portsc & PORT_PE)) - return 0; - return -EBUSY; -} - -static int ehci_wait_for_port(int port) -{ - u32 status; - int ret, reps; - - for (reps = 0; reps < 300; reps++) { - status = readl(&ehci_regs->status); - if (status & STS_PCD) - break; - dbgp_mdelay(1); - } - ret = ehci_reset_port(port); - if (ret == 0) - return 0; - return -ENOTCONN; -} - -typedef void (*set_debug_port_t)(int port); - -static void __init default_set_debug_port(int port) -{ -} - -static set_debug_port_t __initdata set_debug_port = default_set_debug_port; - -static void __init nvidia_set_debug_port(int port) -{ - u32 dword; - dword = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, - 0x74); - dword &= ~(0x0f<<12); - dword |= ((port & 0x0f)<<12); - write_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, 0x74, - dword); - dbgp_printk("set debug port to %d\n", port); -} - -static void __init detect_set_debug_port(void) -{ - u32 vendorid; - - vendorid = read_pci_config(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, - 0x00); - - if ((vendorid & 0xffff) == 0x10de) { - dbgp_printk("using nvidia set_debug_port\n"); - set_debug_port = nvidia_set_debug_port; - } -} - -/* The code in early_ehci_bios_handoff() is derived from the usb pci - * quirk initialization, but altered so as to use the early PCI - * routines. */ -#define EHCI_USBLEGSUP_BIOS (1 << 16) /* BIOS semaphore */ -#define EHCI_USBLEGCTLSTS 4 /* legacy control/status */ -static void __init early_ehci_bios_handoff(void) -{ - u32 hcc_params = readl(&ehci_caps->hcc_params); - int offset = (hcc_params >> 8) & 0xff; - u32 cap; - int msec; - - if (!offset) - return; - - cap = read_pci_config(ehci_dev.bus, ehci_dev.slot, - ehci_dev.func, offset); - dbgp_printk("dbgp: ehci BIOS state %08x\n", cap); - - if ((cap & 0xff) == 1 && (cap & EHCI_USBLEGSUP_BIOS)) { - dbgp_printk("dbgp: BIOS handoff\n"); - write_pci_config_byte(ehci_dev.bus, ehci_dev.slot, - ehci_dev.func, offset + 3, 1); - } - - /* if boot firmware now owns EHCI, spin till it hands it over. */ - msec = 1000; - while ((cap & EHCI_USBLEGSUP_BIOS) && (msec > 0)) { - mdelay(10); - msec -= 10; - cap = read_pci_config(ehci_dev.bus, ehci_dev.slot, - ehci_dev.func, offset); - } - - if (cap & EHCI_USBLEGSUP_BIOS) { - /* well, possibly buggy BIOS... try to shut it down, - * and hope nothing goes too wrong */ - dbgp_printk("dbgp: BIOS handoff failed: %08x\n", cap); - write_pci_config_byte(ehci_dev.bus, ehci_dev.slot, - ehci_dev.func, offset + 2, 0); - } - - /* just in case, always disable EHCI SMIs */ - write_pci_config_byte(ehci_dev.bus, ehci_dev.slot, ehci_dev.func, - offset + EHCI_USBLEGCTLSTS, 0); -} - -static int __init ehci_setup(void) -{ - u32 ctrl, portsc, hcs_params; - u32 debug_port, new_debug_port = 0, n_ports; - int ret, i; - int port_map_tried; - int playtimes = 3; - - early_ehci_bios_handoff(); - -try_next_time: - port_map_tried = 0; - -try_next_port: - - hcs_params = readl(&ehci_caps->hcs_params); - debug_port = HCS_DEBUG_PORT(hcs_params); - dbgp_phys_port = debug_port; - n_ports = HCS_N_PORTS(hcs_params); - - dbgp_printk("debug_port: %d\n", debug_port); - dbgp_printk("n_ports: %d\n", n_ports); - dbgp_ehci_status(""); - - for (i = 1; i <= n_ports; i++) { - portsc = readl(&ehci_regs->port_status[i-1]); - dbgp_printk("portstatus%d: %08x\n", i, portsc); - } - - if (port_map_tried && (new_debug_port != debug_port)) { - if (--playtimes) { - set_debug_port(new_debug_port); - goto try_next_time; - } - return -1; - } - - /* Only reset the controller if it is not already in the - * configured state */ - if (!(readl(&ehci_regs->configured_flag) & FLAG_CF)) { - if (dbgp_ehci_controller_reset() != 0) - return -1; - } else { - dbgp_ehci_status("ehci skip - already configured"); - } - - ret = dbgp_external_startup(); - if (ret == -EIO) - goto next_debug_port; - - if (ret < 0) { - /* Things didn't work so remove my claim */ - ctrl = readl(&ehci_debug->control); - ctrl &= ~(DBGP_CLAIM | DBGP_OUT); - writel(ctrl, &ehci_debug->control); - return -1; - } - return 0; - -next_debug_port: - port_map_tried |= (1<<(debug_port - 1)); - new_debug_port = ((debug_port-1+1)%n_ports) + 1; - if (port_map_tried != ((1<> 29) & 0x7; - bar = (bar * 4) + 0xc; - offset = (debug_port >> 16) & 0xfff; - dbgp_printk("bar: %02x offset: %03x\n", bar, offset); - if (bar != PCI_BASE_ADDRESS_0) { - dbgp_printk("only debug ports on bar 1 handled.\n"); - - return -1; - } - - bar_val = read_pci_config(bus, slot, func, PCI_BASE_ADDRESS_0); - dbgp_printk("bar_val: %02x offset: %03x\n", bar_val, offset); - if (bar_val & ~PCI_BASE_ADDRESS_MEM_MASK) { - dbgp_printk("only simple 32bit mmio bars supported\n"); - - return -1; - } - - /* double check if the mem space is enabled */ - byte = read_pci_config_byte(bus, slot, func, 0x04); - if (!(byte & 0x2)) { - byte |= 0x02; - write_pci_config_byte(bus, slot, func, 0x04, byte); - dbgp_printk("mmio for ehci enabled\n"); - } - - /* - * FIXME I don't have the bar size so just guess PAGE_SIZE is more - * than enough. 1K is the biggest I have seen. - */ - set_fixmap_nocache(FIX_DBGP_BASE, bar_val & PAGE_MASK); - ehci_bar = (void __iomem *)__fix_to_virt(FIX_DBGP_BASE); - ehci_bar += bar_val & ~PAGE_MASK; - dbgp_printk("ehci_bar: %p\n", ehci_bar); - - ehci_caps = ehci_bar; - ehci_regs = ehci_bar + HC_LENGTH(readl(&ehci_caps->hc_capbase)); - ehci_debug = ehci_bar + offset; - ehci_dev.bus = bus; - ehci_dev.slot = slot; - ehci_dev.func = func; - - detect_set_debug_port(); - - ret = ehci_setup(); - if (ret < 0) { - dbgp_printk("ehci_setup failed\n"); - ehci_debug = NULL; - - return -1; - } - dbgp_ehci_status("early_init_complete"); - - return 0; -} - -static void early_dbgp_write(struct console *con, const char *str, u32 n) -{ - int chunk, ret; - char buf[DBGP_MAX_PACKET]; - int use_cr = 0; - u32 cmd, ctrl; - int reset_run = 0; - - if (!ehci_debug || dbgp_not_safe) - return; - - cmd = readl(&ehci_regs->command); - if (unlikely(!(cmd & CMD_RUN))) { - /* If the ehci controller is not in the run state do extended - * checks to see if the acpi or some other initialization also - * reset the ehci debug port */ - ctrl = readl(&ehci_debug->control); - if (!(ctrl & DBGP_ENABLED)) { - dbgp_not_safe = 1; - dbgp_external_startup(); - } else { - cmd |= CMD_RUN; - writel(cmd, &ehci_regs->command); - reset_run = 1; - } - } - while (n > 0) { - for (chunk = 0; chunk < DBGP_MAX_PACKET && n > 0; - str++, chunk++, n--) { - if (!use_cr && *str == '\n') { - use_cr = 1; - buf[chunk] = '\r'; - str--; - n++; - continue; - } - if (use_cr) - use_cr = 0; - buf[chunk] = *str; - } - if (chunk > 0) { - ret = dbgp_bulk_write(USB_DEBUG_DEVNUM, - dbgp_endpoint_out, buf, chunk); - } - } - if (unlikely(reset_run)) { - cmd = readl(&ehci_regs->command); - cmd &= ~CMD_RUN; - writel(cmd, &ehci_regs->command); - } -} - -struct console early_dbgp_console = { - .name = "earlydbg", - .write = early_dbgp_write, - .flags = CON_PRINTBUFFER, - .index = -1, -}; - -int dbgp_reset_prep(void) -{ - u32 ctrl; - - dbgp_not_safe = 1; - if (!ehci_debug) - return 0; - - if (early_dbgp_console.index != -1 && - !(early_dbgp_console.flags & CON_BOOT)) - return 1; - /* This means the console is not initialized, or should get - * shutdown so as to allow for reuse of the usb device, which - * means it is time to shutdown the usb debug port. */ - ctrl = readl(&ehci_debug->control); - if (ctrl & DBGP_ENABLED) { - ctrl &= ~(DBGP_CLAIM); - writel(ctrl, &ehci_debug->control); - } - return 0; -} -EXPORT_SYMBOL_GPL(dbgp_reset_prep); diff --git a/trunk/drivers/usb/gadget/Kconfig b/trunk/drivers/usb/gadget/Kconfig index 33351312327f..9f986b417c5b 100644 --- a/trunk/drivers/usb/gadget/Kconfig +++ b/trunk/drivers/usb/gadget/Kconfig @@ -124,7 +124,7 @@ choice config USB_GADGET_AT91 boolean "Atmel AT91 USB Device Port" - depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 && !ARCH_AT91SAM9G45 + depends on ARCH_AT91 && !ARCH_AT91SAM9RL && !ARCH_AT91CAP9 select USB_GADGET_SELECTED help Many Atmel AT91 processors (such as the AT91RM2000) have a @@ -143,7 +143,7 @@ config USB_AT91 config USB_GADGET_ATMEL_USBA boolean "Atmel USBA" select USB_GADGET_DUALSPEED - depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL || ARCH_AT91SAM9G45 + depends on AVR32 || ARCH_AT91CAP9 || ARCH_AT91SAM9RL help USBA is the integrated high-speed USB Device controller on the AT32AP700x, some AT91SAM9 and AT91CAP9 processors from Atmel. @@ -627,10 +627,9 @@ config USB_AUDIO config USB_ETH tristate "Ethernet Gadget (with CDC Ethernet support)" depends on NET - select CRC32 help - This driver implements Ethernet style communication, in one of - several ways: + This driver implements Ethernet style communication, in either + of two ways: - The "Communication Device Class" (CDC) Ethernet Control Model. That protocol is often avoided with pure Ethernet adapters, in @@ -640,11 +639,7 @@ config USB_ETH - On hardware can't implement that protocol, a simple CDC subset is used, placing fewer demands on USB. - - CDC Ethernet Emulation Model (EEM) is a newer standard that has - a simpler interface that can be used by more USB hardware. - - RNDIS support is an additional option, more demanding than than - subset. + RNDIS support is a third option, more demanding than that subset. Within the USB device, this gadget driver exposes a network device "usbX", where X depends on what other networking devices you have. @@ -677,22 +672,6 @@ config USB_ETH_RNDIS XP, you'll need to download drivers from Microsoft's website; a URL is given in comments found in that info file. -config USB_ETH_EEM - bool "Ethernet Emulation Model (EEM) support" - depends on USB_ETH - default n - help - CDC EEM is a newer USB standard that is somewhat simpler than CDC ECM - and therefore can be supported by more hardware. Technically ECM and - EEM are designed for different applications. The ECM model extends - the network interface to the target (e.g. a USB cable modem), and the - EEM model is for mobile devices to communicate with hosts using - ethernet over USB. For Linux gadgets, however, the interface with - the host is the same (a usbX device), so the differences are minimal. - - If you say "y" here, the Ethernet gadget driver will use the EEM - protocol rather than ECM. If unsure, say "n". - config USB_GADGETFS tristate "Gadget Filesystem (EXPERIMENTAL)" depends on EXPERIMENTAL diff --git a/trunk/drivers/usb/gadget/amd5536udc.c b/trunk/drivers/usb/gadget/amd5536udc.c index d5b65962dd36..77352ccc245e 100644 --- a/trunk/drivers/usb/gadget/amd5536udc.c +++ b/trunk/drivers/usb/gadget/amd5536udc.c @@ -2378,34 +2378,40 @@ static irqreturn_t udc_data_in_isr(struct udc *dev, int ep_ix) if (!ep->cancel_transfer && !list_empty(&ep->queue)) { req = list_entry(ep->queue.next, struct udc_request, queue); - /* - * length bytes transfered - * check dma done of last desc. in PPBDU mode - */ - if (use_dma_ppb_du) { - td = udc_get_last_dma_desc(req); - if (td) { - dma_done = - AMD_GETBITS(td->status, - UDC_DMA_IN_STS_BS); - /* don't care DMA done */ + if (req) { + /* + * length bytes transfered + * check dma done of last desc. in PPBDU mode + */ + if (use_dma_ppb_du) { + td = udc_get_last_dma_desc(req); + if (td) { + dma_done = + AMD_GETBITS(td->status, + UDC_DMA_IN_STS_BS); + /* don't care DMA done */ + req->req.actual = + req->req.length; + } + } else { + /* assume all bytes transferred */ req->req.actual = req->req.length; } - } else { - /* assume all bytes transferred */ - req->req.actual = req->req.length; - } - if (req->req.actual == req->req.length) { - /* complete req */ - complete_req(ep, req, 0); - req->dma_going = 0; - /* further request available ? */ - if (list_empty(&ep->queue)) { - /* disable interrupt */ - tmp = readl(&dev->regs->ep_irqmsk); - tmp |= AMD_BIT(ep->num); - writel(tmp, &dev->regs->ep_irqmsk); + if (req->req.actual == req->req.length) { + /* complete req */ + complete_req(ep, req, 0); + req->dma_going = 0; + /* further request available ? */ + if (list_empty(&ep->queue)) { + /* disable interrupt */ + tmp = readl( + &dev->regs->ep_irqmsk); + tmp |= AMD_BIT(ep->num); + writel(tmp, + &dev->regs->ep_irqmsk); + } + } } } diff --git a/trunk/drivers/usb/gadget/at91_udc.c b/trunk/drivers/usb/gadget/at91_udc.c index 66450a1abc22..72bae8f39d81 100644 --- a/trunk/drivers/usb/gadget/at91_udc.c +++ b/trunk/drivers/usb/gadget/at91_udc.c @@ -1754,6 +1754,7 @@ static int __init at91udc_probe(struct platform_device *pdev) IRQF_DISABLED, driver_name, udc)) { DBG("request vbus irq %d failed\n", udc->board.vbus_pin); + free_irq(udc->udp_irq, udc); retval = -EBUSY; goto fail3; } diff --git a/trunk/drivers/usb/gadget/audio.c b/trunk/drivers/usb/gadget/audio.c index a3a0f4a27ef0..9f80f4e970bd 100644 --- a/trunk/drivers/usb/gadget/audio.c +++ b/trunk/drivers/usb/gadget/audio.c @@ -106,20 +106,20 @@ static int audio_set_endpoint_req(struct usb_configuration *c, ctrl->bRequest, w_value, len, ep); switch (ctrl->bRequest) { - case UAC_SET_CUR: + case SET_CUR: value = 0; break; - case UAC_SET_MIN: + case SET_MIN: break; - case UAC_SET_MAX: + case SET_MAX: break; - case UAC_SET_RES: + case SET_RES: break; - case UAC_SET_MEM: + case SET_MEM: break; default: @@ -142,13 +142,13 @@ static int audio_get_endpoint_req(struct usb_configuration *c, ctrl->bRequest, w_value, len, ep); switch (ctrl->bRequest) { - case UAC_GET_CUR: - case UAC_GET_MIN: - case UAC_GET_MAX: - case UAC_GET_RES: + case GET_CUR: + case GET_MIN: + case GET_MAX: + case GET_RES: value = 3; break; - case UAC_GET_MEM: + case GET_MEM: break; default: break; @@ -171,11 +171,11 @@ audio_setup(struct usb_configuration *c, const struct usb_ctrlrequest *ctrl) * Audio class messages; interface activation uses set_alt(). */ switch (ctrl->bRequestType) { - case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: + case USB_AUDIO_SET_ENDPOINT: value = audio_set_endpoint_req(c, ctrl); break; - case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_ENDPOINT: + case USB_AUDIO_GET_ENDPOINT: value = audio_get_endpoint_req(c, ctrl); break; diff --git a/trunk/drivers/usb/gadget/composite.c b/trunk/drivers/usb/gadget/composite.c index d05397ec8a18..59e85234fa0a 100644 --- a/trunk/drivers/usb/gadget/composite.c +++ b/trunk/drivers/usb/gadget/composite.c @@ -602,7 +602,7 @@ static int get_string(struct usb_composite_dev *cdev, } } - for (len = 0; len <= 126 && s->wData[len]; len++) + for (len = 0; s->wData[len] && len <= 126; len++) continue; if (!len) return -EINVAL; diff --git a/trunk/drivers/usb/gadget/dummy_hcd.c b/trunk/drivers/usb/gadget/dummy_hcd.c index 5e0966485188..a56b24d305f8 100644 --- a/trunk/drivers/usb/gadget/dummy_hcd.c +++ b/trunk/drivers/usb/gadget/dummy_hcd.c @@ -1306,6 +1306,11 @@ static void dummy_timer (unsigned long _dum) setup = *(struct usb_ctrlrequest*) urb->setup_packet; w_index = le16_to_cpu(setup.wIndex); w_value = le16_to_cpu(setup.wValue); + if (le16_to_cpu(setup.wLength) != + urb->transfer_buffer_length) { + status = -EOVERFLOW; + goto return_urb; + } /* paranoia, in case of stale queued data */ list_for_each_entry (req, &ep->queue, queue) { diff --git a/trunk/drivers/usb/gadget/ether.c b/trunk/drivers/usb/gadget/ether.c index f37de283d0ab..bd102f5052ba 100644 --- a/trunk/drivers/usb/gadget/ether.c +++ b/trunk/drivers/usb/gadget/ether.c @@ -61,11 +61,6 @@ * simpler, Microsoft pushes their own approach: RNDIS. The published * RNDIS specs are ambiguous and appear to be incomplete, and are also * needlessly complex. They borrow more from CDC ACM than CDC ECM. - * - * While CDC ECM, CDC Subset, and RNDIS are designed to extend the ethernet - * interface to the target, CDC EEM was designed to use ethernet over the USB - * link between the host and target. CDC EEM is implemented as an alternative - * to those other protocols when that communication model is more appropriate */ #define DRIVER_DESC "Ethernet Gadget" @@ -119,7 +114,6 @@ static inline bool has_rndis(void) #include "f_rndis.c" #include "rndis.c" #endif -#include "f_eem.c" #include "u_ether.c" /*-------------------------------------------------------------------------*/ @@ -156,10 +150,6 @@ static inline bool has_rndis(void) #define RNDIS_VENDOR_NUM 0x0525 /* NetChip */ #define RNDIS_PRODUCT_NUM 0xa4a2 /* Ethernet/RNDIS Gadget */ -/* For EEM gadgets */ -#define EEM_VENDOR_NUM 0x0525 /* INVALID - NEEDS TO BE ALLOCATED */ -#define EEM_PRODUCT_NUM 0xa4a1 /* INVALID - NEEDS TO BE ALLOCATED */ - /*-------------------------------------------------------------------------*/ static struct usb_device_descriptor device_desc = { @@ -256,16 +246,8 @@ static struct usb_configuration rndis_config_driver = { /*-------------------------------------------------------------------------*/ -#ifdef CONFIG_USB_ETH_EEM -static int use_eem = 1; -#else -static int use_eem; -#endif -module_param(use_eem, bool, 0); -MODULE_PARM_DESC(use_eem, "use CDC EEM mode"); - /* - * We _always_ have an ECM, CDC Subset, or EEM configuration. + * We _always_ have an ECM or CDC Subset configuration. */ static int __init eth_do_config(struct usb_configuration *c) { @@ -276,9 +258,7 @@ static int __init eth_do_config(struct usb_configuration *c) c->bmAttributes |= USB_CONFIG_ATT_WAKEUP; } - if (use_eem) - return eem_bind_config(c); - else if (can_support_ecm(c->cdev->gadget)) + if (can_support_ecm(c->cdev->gadget)) return ecm_bind_config(c, hostaddr); else return geth_bind_config(c, hostaddr); @@ -306,12 +286,7 @@ static int __init eth_bind(struct usb_composite_dev *cdev) return status; /* set up main config label and device descriptor */ - if (use_eem) { - /* EEM */ - eth_config_driver.label = "CDC Ethernet (EEM)"; - device_desc.idVendor = cpu_to_le16(EEM_VENDOR_NUM); - device_desc.idProduct = cpu_to_le16(EEM_PRODUCT_NUM); - } else if (can_support_ecm(cdev->gadget)) { + if (can_support_ecm(cdev->gadget)) { /* ECM */ eth_config_driver.label = "CDC Ethernet (ECM)"; } else { diff --git a/trunk/drivers/usb/gadget/f_audio.c b/trunk/drivers/usb/gadget/f_audio.c index 98e9bb977291..66527ba2d2ea 100644 --- a/trunk/drivers/usb/gadget/f_audio.c +++ b/trunk/drivers/usb/gadget/f_audio.c @@ -28,9 +28,6 @@ static int audio_buf_size = 48000; module_param(audio_buf_size, int, S_IRUGO); MODULE_PARM_DESC(audio_buf_size, "Audio buffer size"); -static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value); -static int generic_get_cmd(struct usb_audio_control *con, u8 cmd); - /* * DESCRIPTORS ... most are static, but strings and full * configuration descriptors are built on demand. @@ -53,16 +50,16 @@ static struct usb_interface_descriptor ac_interface_desc __initdata = { .bInterfaceSubClass = USB_SUBCLASS_AUDIOCONTROL, }; -DECLARE_UAC_AC_HEADER_DESCRIPTOR(2); +DECLARE_USB_AC_HEADER_DESCRIPTOR(2); -#define UAC_DT_AC_HEADER_LENGTH UAC_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES) +#define USB_DT_AC_HEADER_LENGH USB_DT_AC_HEADER_SIZE(F_AUDIO_NUM_INTERFACES) /* B.3.2 Class-Specific AC Interface Descriptor */ -static struct uac_ac_header_descriptor_2 ac_header_desc = { - .bLength = UAC_DT_AC_HEADER_LENGTH, +static struct usb_ac_header_descriptor_2 ac_header_desc = { + .bLength = USB_DT_AC_HEADER_LENGH, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_HEADER, + .bDescriptorSubtype = HEADER, .bcdADC = __constant_cpu_to_le16(0x0100), - .wTotalLength = __constant_cpu_to_le16(UAC_DT_AC_HEADER_LENGTH), + .wTotalLength = __constant_cpu_to_le16(USB_DT_AC_HEADER_LENGH), .bInCollection = F_AUDIO_NUM_INTERFACES, .baInterfaceNr = { [0] = F_AUDIO_AC_INTERFACE, @@ -71,33 +68,33 @@ static struct uac_ac_header_descriptor_2 ac_header_desc = { }; #define INPUT_TERMINAL_ID 1 -static struct uac_input_terminal_descriptor input_terminal_desc = { - .bLength = UAC_DT_INPUT_TERMINAL_SIZE, +static struct usb_input_terminal_descriptor input_terminal_desc = { + .bLength = USB_DT_AC_INPUT_TERMINAL_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_INPUT_TERMINAL, + .bDescriptorSubtype = INPUT_TERMINAL, .bTerminalID = INPUT_TERMINAL_ID, - .wTerminalType = UAC_TERMINAL_STREAMING, + .wTerminalType = USB_AC_TERMINAL_STREAMING, .bAssocTerminal = 0, .wChannelConfig = 0x3, }; -DECLARE_UAC_FEATURE_UNIT_DESCRIPTOR(0); +DECLARE_USB_AC_FEATURE_UNIT_DESCRIPTOR(0); #define FEATURE_UNIT_ID 2 -static struct uac_feature_unit_descriptor_0 feature_unit_desc = { - .bLength = UAC_DT_FEATURE_UNIT_SIZE(0), +static struct usb_ac_feature_unit_descriptor_0 feature_unit_desc = { + .bLength = USB_DT_AC_FEATURE_UNIT_SIZE(0), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_FEATURE_UNIT, + .bDescriptorSubtype = FEATURE_UNIT, .bUnitID = FEATURE_UNIT_ID, .bSourceID = INPUT_TERMINAL_ID, .bControlSize = 2, - .bmaControls[0] = (UAC_FU_MUTE | UAC_FU_VOLUME), + .bmaControls[0] = (FU_MUTE | FU_VOLUME), }; static struct usb_audio_control mute_control = { .list = LIST_HEAD_INIT(mute_control.list), .name = "Mute Control", - .type = UAC_MUTE_CONTROL, + .type = MUTE_CONTROL, /* Todo: add real Mute control code */ .set = generic_set_cmd, .get = generic_get_cmd, @@ -106,7 +103,7 @@ static struct usb_audio_control mute_control = { static struct usb_audio_control volume_control = { .list = LIST_HEAD_INIT(volume_control.list), .name = "Volume Control", - .type = UAC_VOLUME_CONTROL, + .type = VOLUME_CONTROL, /* Todo: add real Volume control code */ .set = generic_set_cmd, .get = generic_get_cmd, @@ -116,17 +113,17 @@ static struct usb_audio_control_selector feature_unit = { .list = LIST_HEAD_INIT(feature_unit.list), .id = FEATURE_UNIT_ID, .name = "Mute & Volume Control", - .type = UAC_FEATURE_UNIT, + .type = FEATURE_UNIT, .desc = (struct usb_descriptor_header *)&feature_unit_desc, }; #define OUTPUT_TERMINAL_ID 3 -static struct uac_output_terminal_descriptor output_terminal_desc = { - .bLength = UAC_DT_OUTPUT_TERMINAL_SIZE, +static struct usb_output_terminal_descriptor output_terminal_desc = { + .bLength = USB_DT_AC_OUTPUT_TERMINAL_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_OUTPUT_TERMINAL, + .bDescriptorSubtype = OUTPUT_TERMINAL, .bTerminalID = OUTPUT_TERMINAL_ID, - .wTerminalType = UAC_OUTPUT_TERMINAL_SPEAKER, + .wTerminalType = USB_AC_OUTPUT_TERMINAL_SPEAKER, .bAssocTerminal = FEATURE_UNIT_ID, .bSourceID = FEATURE_UNIT_ID, }; @@ -151,22 +148,22 @@ static struct usb_interface_descriptor as_interface_alt_1_desc = { }; /* B.4.2 Class-Specific AS Interface Descriptor */ -static struct uac_as_header_descriptor as_header_desc = { - .bLength = UAC_DT_AS_HEADER_SIZE, +static struct usb_as_header_descriptor as_header_desc = { + .bLength = USB_DT_AS_HEADER_SIZE, .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_AS_GENERAL, + .bDescriptorSubtype = AS_GENERAL, .bTerminalLink = INPUT_TERMINAL_ID, .bDelay = 1, - .wFormatTag = UAC_FORMAT_TYPE_I_PCM, + .wFormatTag = USB_AS_AUDIO_FORMAT_TYPE_I_PCM, }; -DECLARE_UAC_FORMAT_TYPE_I_DISCRETE_DESC(1); +DECLARE_USB_AS_FORMAT_TYPE_I_DISCRETE_DESC(1); -static struct uac_format_type_i_discrete_descriptor_1 as_type_i_desc = { - .bLength = UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), +static struct usb_as_formate_type_i_discrete_descriptor_1 as_type_i_desc = { + .bLength = USB_AS_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, - .bDescriptorSubtype = UAC_FORMAT_TYPE, - .bFormatType = UAC_FORMAT_TYPE_I, + .bDescriptorSubtype = FORMAT_TYPE, + .bFormatType = USB_AS_FORMAT_TYPE_I, .bSubframeSize = 2, .bBitResolution = 16, .bSamFreqType = 1, @@ -177,17 +174,17 @@ static struct usb_endpoint_descriptor as_out_ep_desc __initdata = { .bLength = USB_DT_ENDPOINT_AUDIO_SIZE, .bDescriptorType = USB_DT_ENDPOINT, .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_SYNC_ADAPTIVE + .bmAttributes = USB_AS_ENDPOINT_ADAPTIVE | USB_ENDPOINT_XFER_ISOC, .wMaxPacketSize = __constant_cpu_to_le16(OUT_EP_MAX_PACKET_SIZE), .bInterval = 4, }; /* Class-specific AS ISO OUT Endpoint Descriptor */ -static struct uac_iso_endpoint_descriptor as_iso_out_desc __initdata = { - .bLength = UAC_ISO_ENDPOINT_DESC_SIZE, +static struct usb_as_iso_endpoint_descriptor as_iso_out_desc __initdata = { + .bLength = USB_AS_ISO_ENDPOINT_DESC_SIZE, .bDescriptorType = USB_DT_CS_ENDPOINT, - .bDescriptorSubtype = UAC_EP_GENERAL, + .bDescriptorSubtype = EP_GENERAL, .bmAttributes = 1, .bLockDelayUnits = 1, .wLockDelay = __constant_cpu_to_le16(1), @@ -459,11 +456,11 @@ f_audio_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) * Audio class messages; interface activation uses set_alt(). */ switch (ctrl->bRequestType) { - case USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE: + case USB_AUDIO_SET_INTF: value = audio_set_intf_req(f, ctrl); break; - case USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE: + case USB_AUDIO_GET_INTF: value = audio_get_intf_req(f, ctrl); break; @@ -635,18 +632,6 @@ f_audio_unbind(struct usb_configuration *c, struct usb_function *f) /*-------------------------------------------------------------------------*/ -static int generic_set_cmd(struct usb_audio_control *con, u8 cmd, int value) -{ - con->data[cmd] = value; - - return 0; -} - -static int generic_get_cmd(struct usb_audio_control *con, u8 cmd) -{ - return con->data[cmd]; -} - /* Todo: add more control selecotor dynamically */ int __init control_selector_init(struct f_audio *audio) { @@ -657,10 +642,10 @@ int __init control_selector_init(struct f_audio *audio) list_add(&mute_control.list, &feature_unit.control); list_add(&volume_control.list, &feature_unit.control); - volume_control.data[UAC__CUR] = 0xffc0; - volume_control.data[UAC__MIN] = 0xe3a0; - volume_control.data[UAC__MAX] = 0xfff0; - volume_control.data[UAC__RES] = 0x0030; + volume_control.data[_CUR] = 0xffc0; + volume_control.data[_MIN] = 0xe3a0; + volume_control.data[_MAX] = 0xfff0; + volume_control.data[_RES] = 0x0030; return 0; } diff --git a/trunk/drivers/usb/gadget/f_eem.c b/trunk/drivers/usb/gadget/f_eem.c deleted file mode 100644 index 0a577d5694fd..000000000000 --- a/trunk/drivers/usb/gadget/f_eem.c +++ /dev/null @@ -1,562 +0,0 @@ -/* - * f_eem.c -- USB CDC Ethernet (EEM) link function driver - * - * Copyright (C) 2003-2005,2008 David Brownell - * Copyright (C) 2008 Nokia Corporation - * Copyright (C) 2009 EF Johnson Technologies - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include -#include -#include -#include - -#include "u_ether.h" - -#define EEM_HLEN 2 - -/* - * This function is a "CDC Ethernet Emulation Model" (CDC EEM) - * Ethernet link. - */ - -struct eem_ep_descs { - struct usb_endpoint_descriptor *in; - struct usb_endpoint_descriptor *out; -}; - -struct f_eem { - struct gether port; - u8 ctrl_id; - - struct eem_ep_descs fs; - struct eem_ep_descs hs; -}; - -static inline struct f_eem *func_to_eem(struct usb_function *f) -{ - return container_of(f, struct f_eem, port.func); -} - -/*-------------------------------------------------------------------------*/ - -/* interface descriptor: */ - -static struct usb_interface_descriptor eem_intf __initdata = { - .bLength = sizeof eem_intf, - .bDescriptorType = USB_DT_INTERFACE, - - /* .bInterfaceNumber = DYNAMIC */ - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_COMM, - .bInterfaceSubClass = USB_CDC_SUBCLASS_EEM, - .bInterfaceProtocol = USB_CDC_PROTO_EEM, - /* .iInterface = DYNAMIC */ -}; - -/* full speed support: */ - -static struct usb_endpoint_descriptor eem_fs_in_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_endpoint_descriptor eem_fs_out_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, -}; - -static struct usb_descriptor_header *eem_fs_function[] __initdata = { - /* CDC EEM control descriptors */ - (struct usb_descriptor_header *) &eem_intf, - (struct usb_descriptor_header *) &eem_fs_in_desc, - (struct usb_descriptor_header *) &eem_fs_out_desc, - NULL, -}; - -/* high speed support: */ - -static struct usb_endpoint_descriptor eem_hs_in_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_IN, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), -}; - -static struct usb_endpoint_descriptor eem_hs_out_desc __initdata = { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - - .bEndpointAddress = USB_DIR_OUT, - .bmAttributes = USB_ENDPOINT_XFER_BULK, - .wMaxPacketSize = cpu_to_le16(512), -}; - -static struct usb_descriptor_header *eem_hs_function[] __initdata = { - /* CDC EEM control descriptors */ - (struct usb_descriptor_header *) &eem_intf, - (struct usb_descriptor_header *) &eem_hs_in_desc, - (struct usb_descriptor_header *) &eem_hs_out_desc, - NULL, -}; - -/* string descriptors: */ - -static struct usb_string eem_string_defs[] = { - [0].s = "CDC Ethernet Emulation Model (EEM)", - { } /* end of list */ -}; - -static struct usb_gadget_strings eem_string_table = { - .language = 0x0409, /* en-us */ - .strings = eem_string_defs, -}; - -static struct usb_gadget_strings *eem_strings[] = { - &eem_string_table, - NULL, -}; - -/*-------------------------------------------------------------------------*/ - -static int eem_setup(struct usb_function *f, const struct usb_ctrlrequest *ctrl) -{ - struct usb_composite_dev *cdev = f->config->cdev; - int value = -EOPNOTSUPP; - u16 w_index = le16_to_cpu(ctrl->wIndex); - u16 w_value = le16_to_cpu(ctrl->wValue); - u16 w_length = le16_to_cpu(ctrl->wLength); - - DBG(cdev, "invalid control req%02x.%02x v%04x i%04x l%d\n", - ctrl->bRequestType, ctrl->bRequest, - w_value, w_index, w_length); - - /* device either stalls (value < 0) or reports success */ - return value; -} - - -static int eem_set_alt(struct usb_function *f, unsigned intf, unsigned alt) -{ - struct f_eem *eem = func_to_eem(f); - struct usb_composite_dev *cdev = f->config->cdev; - struct net_device *net; - - /* we know alt == 0, so this is an activation or a reset */ - if (alt != 0) - goto fail; - - if (intf == eem->ctrl_id) { - - if (eem->port.in_ep->driver_data) { - DBG(cdev, "reset eem\n"); - gether_disconnect(&eem->port); - } - - if (!eem->port.in) { - DBG(cdev, "init eem\n"); - eem->port.in = ep_choose(cdev->gadget, - eem->hs.in, eem->fs.in); - eem->port.out = ep_choose(cdev->gadget, - eem->hs.out, eem->fs.out); - } - - /* zlps should not occur because zero-length EEM packets - * will be inserted in those cases where they would occur - */ - eem->port.is_zlp_ok = 1; - eem->port.cdc_filter = DEFAULT_FILTER; - DBG(cdev, "activate eem\n"); - net = gether_connect(&eem->port); - if (IS_ERR(net)) - return PTR_ERR(net); - } else - goto fail; - - return 0; -fail: - return -EINVAL; -} - -static void eem_disable(struct usb_function *f) -{ - struct f_eem *eem = func_to_eem(f); - struct usb_composite_dev *cdev = f->config->cdev; - - DBG(cdev, "eem deactivated\n"); - - if (eem->port.in_ep->driver_data) - gether_disconnect(&eem->port); -} - -/*-------------------------------------------------------------------------*/ - -/* EEM function driver setup/binding */ - -static int __init -eem_bind(struct usb_configuration *c, struct usb_function *f) -{ - struct usb_composite_dev *cdev = c->cdev; - struct f_eem *eem = func_to_eem(f); - int status; - struct usb_ep *ep; - - /* allocate instance-specific interface IDs */ - status = usb_interface_id(c, f); - if (status < 0) - goto fail; - eem->ctrl_id = status; - eem_intf.bInterfaceNumber = status; - - status = -ENODEV; - - /* allocate instance-specific endpoints */ - ep = usb_ep_autoconfig(cdev->gadget, &eem_fs_in_desc); - if (!ep) - goto fail; - eem->port.in_ep = ep; - ep->driver_data = cdev; /* claim */ - - ep = usb_ep_autoconfig(cdev->gadget, &eem_fs_out_desc); - if (!ep) - goto fail; - eem->port.out_ep = ep; - ep->driver_data = cdev; /* claim */ - - status = -ENOMEM; - - /* copy descriptors, and track endpoint copies */ - f->descriptors = usb_copy_descriptors(eem_fs_function); - if (!f->descriptors) - goto fail; - - eem->fs.in = usb_find_endpoint(eem_fs_function, - f->descriptors, &eem_fs_in_desc); - eem->fs.out = usb_find_endpoint(eem_fs_function, - f->descriptors, &eem_fs_out_desc); - - /* support all relevant hardware speeds... we expect that when - * hardware is dual speed, all bulk-capable endpoints work at - * both speeds - */ - if (gadget_is_dualspeed(c->cdev->gadget)) { - eem_hs_in_desc.bEndpointAddress = - eem_fs_in_desc.bEndpointAddress; - eem_hs_out_desc.bEndpointAddress = - eem_fs_out_desc.bEndpointAddress; - - /* copy descriptors, and track endpoint copies */ - f->hs_descriptors = usb_copy_descriptors(eem_hs_function); - if (!f->hs_descriptors) - goto fail; - - eem->hs.in = usb_find_endpoint(eem_hs_function, - f->hs_descriptors, &eem_hs_in_desc); - eem->hs.out = usb_find_endpoint(eem_hs_function, - f->hs_descriptors, &eem_hs_out_desc); - } - - DBG(cdev, "CDC Ethernet (EEM): %s speed IN/%s OUT/%s\n", - gadget_is_dualspeed(c->cdev->gadget) ? "dual" : "full", - eem->port.in_ep->name, eem->port.out_ep->name); - return 0; - -fail: - if (f->descriptors) - usb_free_descriptors(f->descriptors); - - /* we might as well release our claims on endpoints */ - if (eem->port.out) - eem->port.out_ep->driver_data = NULL; - if (eem->port.in) - eem->port.in_ep->driver_data = NULL; - - ERROR(cdev, "%s: can't bind, err %d\n", f->name, status); - - return status; -} - -static void -eem_unbind(struct usb_configuration *c, struct usb_function *f) -{ - struct f_eem *eem = func_to_eem(f); - - DBG(c->cdev, "eem unbind\n"); - - if (gadget_is_dualspeed(c->cdev->gadget)) - usb_free_descriptors(f->hs_descriptors); - usb_free_descriptors(f->descriptors); - kfree(eem); -} - -static void eem_cmd_complete(struct usb_ep *ep, struct usb_request *req) -{ -} - -/* - * Add the EEM header and ethernet checksum. - * We currently do not attempt to put multiple ethernet frames - * into a single USB transfer - */ -static struct sk_buff *eem_wrap(struct gether *port, struct sk_buff *skb) -{ - struct sk_buff *skb2 = NULL; - struct usb_ep *in = port->in_ep; - int padlen = 0; - u16 len = skb->len; - - if (!skb_cloned(skb)) { - int headroom = skb_headroom(skb); - int tailroom = skb_tailroom(skb); - - /* When (len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) is 0, - * stick two bytes of zero-length EEM packet on the end. - */ - if (((len + EEM_HLEN + ETH_FCS_LEN) % in->maxpacket) == 0) - padlen += 2; - - if ((tailroom >= (ETH_FCS_LEN + padlen)) && - (headroom >= EEM_HLEN)) - goto done; - } - - skb2 = skb_copy_expand(skb, EEM_HLEN, ETH_FCS_LEN + padlen, GFP_ATOMIC); - dev_kfree_skb_any(skb); - skb = skb2; - if (!skb) - return skb; - -done: - /* use the "no CRC" option */ - put_unaligned_be32(0xdeadbeef, skb_put(skb, 4)); - - /* EEM packet header format: - * b0..13: length of ethernet frame - * b14: bmCRC (0 == sentinel CRC) - * b15: bmType (0 == data) - */ - len = skb->len; - put_unaligned_le16((len & 0x3FFF) | BIT(14), skb_push(skb, 2)); - - /* add a zero-length EEM packet, if needed */ - if (padlen) - put_unaligned_le16(0, skb_put(skb, 2)); - - return skb; -} - -/* - * Remove the EEM header. Note that there can be many EEM packets in a single - * USB transfer, so we need to break them out and handle them independently. - */ -static int eem_unwrap(struct gether *port, - struct sk_buff *skb, - struct sk_buff_head *list) -{ - struct usb_composite_dev *cdev = port->func.config->cdev; - int status = 0; - - do { - struct sk_buff *skb2; - u16 header; - u16 len = 0; - - if (skb->len < EEM_HLEN) { - status = -EINVAL; - DBG(cdev, "invalid EEM header\n"); - goto error; - } - - /* remove the EEM header */ - header = get_unaligned_le16(skb->data); - skb_pull(skb, EEM_HLEN); - - /* EEM packet header format: - * b0..14: EEM type dependent (data or command) - * b15: bmType (0 == data, 1 == command) - */ - if (header & BIT(15)) { - struct usb_request *req = cdev->req; - u16 bmEEMCmd; - - /* EEM command packet format: - * b0..10: bmEEMCmdParam - * b11..13: bmEEMCmd - * b14: reserved (must be zero) - * b15: bmType (1 == command) - */ - if (header & BIT(14)) - continue; - - bmEEMCmd = (header >> 11) & 0x7; - switch (bmEEMCmd) { - case 0: /* echo */ - len = header & 0x7FF; - if (skb->len < len) { - status = -EOVERFLOW; - goto error; - } - - skb2 = skb_clone(skb, GFP_ATOMIC); - if (unlikely(!skb2)) { - DBG(cdev, "EEM echo response error\n"); - goto next; - } - skb_trim(skb2, len); - put_unaligned_le16(BIT(15) | BIT(11) | len, - skb_push(skb2, 2)); - skb_copy_bits(skb, 0, req->buf, skb->len); - req->length = skb->len; - req->complete = eem_cmd_complete; - req->zero = 1; - if (usb_ep_queue(port->in_ep, req, GFP_ATOMIC)) - DBG(cdev, "echo response queue fail\n"); - break; - - case 1: /* echo response */ - case 2: /* suspend hint */ - case 3: /* response hint */ - case 4: /* response complete hint */ - case 5: /* tickle */ - default: /* reserved */ - continue; - } - } else { - u32 crc, crc2; - struct sk_buff *skb3; - - /* check for zero-length EEM packet */ - if (header == 0) - continue; - - /* EEM data packet format: - * b0..13: length of ethernet frame - * b14: bmCRC (0 == sentinel, 1 == calculated) - * b15: bmType (0 == data) - */ - len = header & 0x3FFF; - if ((skb->len < len) - || (len < (ETH_HLEN + ETH_FCS_LEN))) { - status = -EINVAL; - goto error; - } - - /* validate CRC */ - crc = get_unaligned_le32(skb->data + len - ETH_FCS_LEN); - if (header & BIT(14)) { - crc = get_unaligned_le32(skb->data + len - - ETH_FCS_LEN); - crc2 = ~crc32_le(~0, - skb->data, - skb->len - ETH_FCS_LEN); - } else { - crc = get_unaligned_be32(skb->data + len - - ETH_FCS_LEN); - crc2 = 0xdeadbeef; - } - if (crc != crc2) { - DBG(cdev, "invalid EEM CRC\n"); - goto next; - } - - skb2 = skb_clone(skb, GFP_ATOMIC); - if (unlikely(!skb2)) { - DBG(cdev, "unable to unframe EEM packet\n"); - continue; - } - skb_trim(skb2, len - ETH_FCS_LEN); - - skb3 = skb_copy_expand(skb2, - NET_IP_ALIGN, - 0, - GFP_ATOMIC); - if (unlikely(!skb3)) { - DBG(cdev, "unable to realign EEM packet\n"); - dev_kfree_skb_any(skb2); - continue; - } - dev_kfree_skb_any(skb2); - skb_queue_tail(list, skb3); - } -next: - skb_pull(skb, len); - } while (skb->len); - -error: - dev_kfree_skb_any(skb); - return status; -} - -/** - * eem_bind_config - add CDC Ethernet (EEM) network link to a configuration - * @c: the configuration to support the network link - * Context: single threaded during gadget setup - * - * Returns zero on success, else negative errno. - * - * Caller must have called @gether_setup(). Caller is also responsible - * for calling @gether_cleanup() before module unload. - */ -int __init eem_bind_config(struct usb_configuration *c) -{ - struct f_eem *eem; - int status; - - /* maybe allocate device-global string IDs */ - if (eem_string_defs[0].id == 0) { - - /* control interface label */ - status = usb_string_id(c->cdev); - if (status < 0) - return status; - eem_string_defs[0].id = status; - eem_intf.iInterface = status; - } - - /* allocate and initialize one new instance */ - eem = kzalloc(sizeof *eem, GFP_KERNEL); - if (!eem) - return -ENOMEM; - - eem->port.cdc_filter = DEFAULT_FILTER; - - eem->port.func.name = "cdc_eem"; - eem->port.func.strings = eem_strings; - /* descriptors are per-instance copies */ - eem->port.func.bind = eem_bind; - eem->port.func.unbind = eem_unbind; - eem->port.func.set_alt = eem_set_alt; - eem->port.func.setup = eem_setup; - eem->port.func.disable = eem_disable; - eem->port.wrap = eem_wrap; - eem->port.unwrap = eem_unwrap; - eem->port.header_len = EEM_HLEN; - - status = usb_add_function(c, &eem->port.func); - if (status) - kfree(eem); - return status; -} - diff --git a/trunk/drivers/usb/gadget/f_rndis.c b/trunk/drivers/usb/gadget/f_rndis.c index c9966cc07d3a..424a37c5773f 100644 --- a/trunk/drivers/usb/gadget/f_rndis.c +++ b/trunk/drivers/usb/gadget/f_rndis.c @@ -286,17 +286,12 @@ static struct usb_gadget_strings *rndis_strings[] = { /*-------------------------------------------------------------------------*/ -static struct sk_buff *rndis_add_header(struct gether *port, - struct sk_buff *skb) +static struct sk_buff *rndis_add_header(struct sk_buff *skb) { - struct sk_buff *skb2; - - skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); - if (skb2) - rndis_add_hdr(skb2); - - dev_kfree_skb_any(skb); - return skb2; + skb = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type)); + if (skb) + rndis_add_hdr(skb); + return skb; } static void rndis_response_available(void *_rndis) diff --git a/trunk/drivers/usb/gadget/fsl_qe_udc.c b/trunk/drivers/usb/gadget/fsl_qe_udc.c index 7881f12413c4..d701bf4698d2 100644 --- a/trunk/drivers/usb/gadget/fsl_qe_udc.c +++ b/trunk/drivers/usb/gadget/fsl_qe_udc.c @@ -2750,10 +2750,6 @@ static int __devexit qe_udc_remove(struct of_device *ofdev) /*-------------------------------------------------------------------------*/ static struct of_device_id __devinitdata qe_udc_match[] = { - { - .compatible = "fsl,mpc8323-qe-usb", - .data = (void *)PORT_QE, - }, { .compatible = "fsl,mpc8360-qe-usb", .data = (void *)PORT_QE, diff --git a/trunk/drivers/usb/gadget/gmidi.c b/trunk/drivers/usb/gadget/gmidi.c index d0b1e836f0e0..b9312dc6e041 100644 --- a/trunk/drivers/usb/gadget/gmidi.c +++ b/trunk/drivers/usb/gadget/gmidi.c @@ -191,7 +191,7 @@ module_param(qlen, uint, S_IRUGO); #define GMIDI_MS_INTERFACE 1 #define GMIDI_NUM_INTERFACES 2 -DECLARE_UAC_AC_HEADER_DESCRIPTOR(1); +DECLARE_USB_AC_HEADER_DESCRIPTOR(1); DECLARE_USB_MIDI_OUT_JACK_DESCRIPTOR(1); DECLARE_USB_MS_ENDPOINT_DESCRIPTOR(1); @@ -237,12 +237,12 @@ static const struct usb_interface_descriptor ac_interface_desc = { }; /* B.3.2 Class-Specific AC Interface Descriptor */ -static const struct uac_ac_header_descriptor_1 ac_header_desc = { - .bLength = UAC_DT_AC_HEADER_SIZE(1), +static const struct usb_ac_header_descriptor_1 ac_header_desc = { + .bLength = USB_DT_AC_HEADER_SIZE(1), .bDescriptorType = USB_DT_CS_INTERFACE, .bDescriptorSubtype = USB_MS_HEADER, .bcdADC = cpu_to_le16(0x0100), - .wTotalLength = cpu_to_le16(UAC_DT_AC_HEADER_SIZE(1)), + .wTotalLength = cpu_to_le16(USB_DT_AC_HEADER_SIZE(1)), .bInCollection = 1, .baInterfaceNr = { [0] = GMIDI_MS_INTERFACE, diff --git a/trunk/drivers/usb/gadget/pxa25x_udc.c b/trunk/drivers/usb/gadget/pxa25x_udc.c index e6fedbd5a654..ed21e263f832 100644 --- a/trunk/drivers/usb/gadget/pxa25x_udc.c +++ b/trunk/drivers/usb/gadget/pxa25x_udc.c @@ -56,7 +56,6 @@ #include #include -#include /* * This driver is PXA25x only. Grab the right register definitions. @@ -1009,27 +1008,15 @@ static int pxa25x_udc_pullup(struct usb_gadget *_gadget, int is_active) return 0; } -/* boards may consume current from VBUS, up to 100-500mA based on config. - * the 500uA suspend ceiling means that exclusively vbus-powered PXA designs - * violate USB specs. - */ -static int pxa25x_udc_vbus_draw(struct usb_gadget *_gadget, unsigned mA) -{ - struct pxa25x_udc *udc; - - udc = container_of(_gadget, struct pxa25x_udc, gadget); - - if (udc->transceiver) - return otg_set_power(udc->transceiver, mA); - return -EOPNOTSUPP; -} - static const struct usb_gadget_ops pxa25x_udc_ops = { .get_frame = pxa25x_udc_get_frame, .wakeup = pxa25x_udc_wakeup, .vbus_session = pxa25x_udc_vbus_session, .pullup = pxa25x_udc_pullup, - .vbus_draw = pxa25x_udc_vbus_draw, + + // .vbus_draw ... boards may consume current from VBUS, up to + // 100-500mA based on config. the 500uA suspend ceiling means + // that exclusively vbus-powered PXA designs violate USB specs. }; /*-------------------------------------------------------------------------*/ @@ -1316,23 +1303,9 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) * for set_configuration as well as eventual disconnect. */ DMSG("registered gadget driver '%s'\n", driver->driver.name); - - /* connect to bus through transceiver */ - if (dev->transceiver) { - retval = otg_set_peripheral(dev->transceiver, &dev->gadget); - if (retval) { - DMSG("can't bind to transceiver\n"); - if (driver->unbind) - driver->unbind(&dev->gadget); - goto bind_fail; - } - } - pullup(dev); dump_state(dev); return 0; -bind_fail: - return retval; } EXPORT_SYMBOL(usb_gadget_register_driver); @@ -1378,9 +1351,6 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) stop_activity(dev, driver); local_irq_enable(); - if (dev->transceiver) - (void) otg_set_peripheral(dev->transceiver, NULL); - driver->unbind(&dev->gadget); dev->gadget.dev.driver = NULL; dev->driver = NULL; @@ -2192,8 +2162,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) dev->dev = &pdev->dev; dev->mach = pdev->dev.platform_data; - dev->transceiver = otg_get_transceiver(); - if (gpio_is_valid(dev->mach->gpio_vbus)) { if ((retval = gpio_request(dev->mach->gpio_vbus, "pxa25x_udc GPIO VBUS"))) { @@ -2296,10 +2264,6 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) if (gpio_is_valid(dev->mach->gpio_vbus)) gpio_free(dev->mach->gpio_vbus); err_gpio_vbus: - if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); - dev->transceiver = NULL; - } clk_put(dev->clk); err_clk: return retval; @@ -2341,11 +2305,6 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) clk_put(dev->clk); - if (dev->transceiver) { - otg_put_transceiver(dev->transceiver); - dev->transceiver = NULL; - } - platform_set_drvdata(pdev, NULL); the_controller = NULL; return 0; diff --git a/trunk/drivers/usb/gadget/pxa25x_udc.h b/trunk/drivers/usb/gadget/pxa25x_udc.h index f572c5617462..1d51aa21e6eb 100644 --- a/trunk/drivers/usb/gadget/pxa25x_udc.h +++ b/trunk/drivers/usb/gadget/pxa25x_udc.h @@ -128,7 +128,6 @@ struct pxa25x_udc { struct device *dev; struct clk *clk; struct pxa2xx_udc_mach_info *mach; - struct otg_transceiver *transceiver; u64 dma_mask; struct pxa25x_ep ep [PXA_UDC_NUM_ENDPOINTS]; diff --git a/trunk/drivers/usb/gadget/rndis.c b/trunk/drivers/usb/gadget/rndis.c index 48267bc0b2e0..ca41b0b5afb3 100644 --- a/trunk/drivers/usb/gadget/rndis.c +++ b/trunk/drivers/usb/gadget/rndis.c @@ -1022,29 +1022,22 @@ static rndis_resp_t *rndis_add_response (int configNr, u32 length) return r; } -int rndis_rm_hdr(struct gether *port, - struct sk_buff *skb, - struct sk_buff_head *list) +int rndis_rm_hdr(struct sk_buff *skb) { /* tmp points to a struct rndis_packet_msg_type */ __le32 *tmp = (void *) skb->data; /* MessageType, MessageLength */ if (cpu_to_le32(REMOTE_NDIS_PACKET_MSG) - != get_unaligned(tmp++)) { - dev_kfree_skb_any(skb); + != get_unaligned(tmp++)) return -EINVAL; - } tmp++; /* DataOffset, DataLength */ - if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) { - dev_kfree_skb_any(skb); + if (!skb_pull(skb, get_unaligned_le32(tmp++) + 8)) return -EOVERFLOW; - } skb_trim(skb, get_unaligned_le32(tmp++)); - skb_queue_tail(list, skb); return 0; } diff --git a/trunk/drivers/usb/gadget/rndis.h b/trunk/drivers/usb/gadget/rndis.h index c236aaa9dcd1..aac61dfe0f03 100644 --- a/trunk/drivers/usb/gadget/rndis.h +++ b/trunk/drivers/usb/gadget/rndis.h @@ -251,8 +251,7 @@ int rndis_set_param_vendor (u8 configNr, u32 vendorID, const char *vendorDescr); int rndis_set_param_medium (u8 configNr, u32 medium, u32 speed); void rndis_add_hdr (struct sk_buff *skb); -int rndis_rm_hdr(struct gether *port, struct sk_buff *skb, - struct sk_buff_head *list); +int rndis_rm_hdr (struct sk_buff *skb); u8 *rndis_get_next_response (int configNr, u32 *length); void rndis_free_response (int configNr, u8 *buf); diff --git a/trunk/drivers/usb/gadget/s3c-hsotg.c b/trunk/drivers/usb/gadget/s3c-hsotg.c index 4b5dbd0127f5..50c71aae2cc2 100644 --- a/trunk/drivers/usb/gadget/s3c-hsotg.c +++ b/trunk/drivers/usb/gadget/s3c-hsotg.c @@ -2392,7 +2392,7 @@ static int s3c_hsotg_corereset(struct s3c_hsotg *hsotg) grstctl = readl(hsotg->regs + S3C_GRSTCTL); } while (!(grstctl & S3C_GRSTCTL_CSftRst) && timeout-- > 0); - if (!(grstctl & S3C_GRSTCTL_CSftRst)) { + if (!grstctl & S3C_GRSTCTL_CSftRst) { dev_err(hsotg->dev, "Failed to get CSftRst asserted\n"); return -EINVAL; } @@ -2514,8 +2514,8 @@ int usb_gadget_register_driver(struct usb_gadget_driver *driver) * DMA mode we may need this. */ writel(S3C_DOEPMSK_SetupMsk | S3C_DOEPMSK_AHBErrMsk | S3C_DOEPMSK_EPDisbldMsk | - (using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk | - S3C_DIEPMSK_TimeOUTMsk) : 0), + using_dma(hsotg) ? (S3C_DIEPMSK_XferComplMsk | + S3C_DIEPMSK_TimeOUTMsk) : 0, hsotg->regs + S3C_DOEPMSK); writel(0, hsotg->regs + S3C_DAINTMSK); diff --git a/trunk/drivers/usb/gadget/s3c2410_udc.c b/trunk/drivers/usb/gadget/s3c2410_udc.c index d5f4c1d45c97..a9b452fe6221 100644 --- a/trunk/drivers/usb/gadget/s3c2410_udc.c +++ b/trunk/drivers/usb/gadget/s3c2410_udc.c @@ -1703,7 +1703,8 @@ int usb_gadget_unregister_driver(struct usb_gadget_driver *driver) dprintk(DEBUG_NORMAL,"usb_gadget_register_driver() '%s'\n", driver->driver.name); - driver->unbind(&udc->gadget); + if (driver->disconnect) + driver->disconnect(&udc->gadget); device_del(&udc->gadget.dev); udc->driver = NULL; diff --git a/trunk/drivers/usb/gadget/u_audio.c b/trunk/drivers/usb/gadget/u_audio.c index b5200d551458..0f3d22fc030e 100644 --- a/trunk/drivers/usb/gadget/u_audio.c +++ b/trunk/drivers/usb/gadget/u_audio.c @@ -253,13 +253,11 @@ static int gaudio_open_snd_dev(struct gaudio *card) snd->filp = filp_open(fn_cap, O_RDONLY, 0); if (IS_ERR(snd->filp)) { ERROR(card, "No such PCM capture device: %s\n", fn_cap); - snd->substream = NULL; - snd->card = NULL; - } else { - pcm_file = snd->filp->private_data; - snd->substream = pcm_file->substream; - snd->card = card; + snd->filp = NULL; } + pcm_file = snd->filp->private_data; + snd->substream = pcm_file->substream; + snd->card = card; return 0; } diff --git a/trunk/drivers/usb/gadget/u_ether.c b/trunk/drivers/usb/gadget/u_ether.c index f8751ff863cd..c66521953917 100644 --- a/trunk/drivers/usb/gadget/u_ether.c +++ b/trunk/drivers/usb/gadget/u_ether.c @@ -37,9 +37,8 @@ * one (!) network link through the USB gadget stack, normally "usb0". * * The control and data models are handled by the function driver which - * connects to this code; such as CDC Ethernet (ECM or EEM), - * "CDC Subset", or RNDIS. That includes all descriptor and endpoint - * management. + * connects to this code; such as CDC Ethernet, "CDC Subset", or RNDIS. + * That includes all descriptor and endpoint management. * * Link level addressing is handled by this component using module * parameters; if no such parameters are provided, random link level @@ -69,13 +68,9 @@ struct eth_dev { struct list_head tx_reqs, rx_reqs; atomic_t tx_qlen; - struct sk_buff_head rx_frames; - unsigned header_len; - struct sk_buff *(*wrap)(struct gether *, struct sk_buff *skb); - int (*unwrap)(struct gether *, - struct sk_buff *skb, - struct sk_buff_head *list); + struct sk_buff *(*wrap)(struct sk_buff *skb); + int (*unwrap)(struct sk_buff *skb); struct work_struct work; @@ -274,7 +269,7 @@ rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags) static void rx_complete(struct usb_ep *ep, struct usb_request *req) { - struct sk_buff *skb = req->context, *skb2; + struct sk_buff *skb = req->context; struct eth_dev *dev = ep->driver_data; int status = req->status; @@ -283,47 +278,26 @@ static void rx_complete(struct usb_ep *ep, struct usb_request *req) /* normal completion */ case 0: skb_put(skb, req->actual); - - if (dev->unwrap) { - unsigned long flags; - - spin_lock_irqsave(&dev->lock, flags); - if (dev->port_usb) { - status = dev->unwrap(dev->port_usb, - skb, - &dev->rx_frames); - } else { - dev_kfree_skb_any(skb); - status = -ENOTCONN; - } - spin_unlock_irqrestore(&dev->lock, flags); - } else { - skb_queue_tail(&dev->rx_frames, skb); + if (dev->unwrap) + status = dev->unwrap(skb); + if (status < 0 + || ETH_HLEN > skb->len + || skb->len > ETH_FRAME_LEN) { + dev->net->stats.rx_errors++; + dev->net->stats.rx_length_errors++; + DBG(dev, "rx length %d\n", skb->len); + break; } - skb = NULL; - skb2 = skb_dequeue(&dev->rx_frames); - while (skb2) { - if (status < 0 - || ETH_HLEN > skb2->len - || skb2->len > ETH_FRAME_LEN) { - dev->net->stats.rx_errors++; - dev->net->stats.rx_length_errors++; - DBG(dev, "rx length %d\n", skb2->len); - dev_kfree_skb_any(skb2); - goto next_frame; - } - skb2->protocol = eth_type_trans(skb2, dev->net); - dev->net->stats.rx_packets++; - dev->net->stats.rx_bytes += skb2->len; + skb->protocol = eth_type_trans(skb, dev->net); + dev->net->stats.rx_packets++; + dev->net->stats.rx_bytes += skb->len; - /* no buffer copies needed, unless hardware can't - * use skb buffers. - */ - status = netif_rx(skb2); -next_frame: - skb2 = skb_dequeue(&dev->rx_frames); - } + /* no buffer copies needed, unless hardware can't + * use skb buffers. + */ + status = netif_rx(skb); + skb = NULL; break; /* software-driven interface shutdown */ @@ -563,15 +537,14 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, * or there's not enough space for extra headers we need */ if (dev->wrap) { - unsigned long flags; + struct sk_buff *skb_new; - spin_lock_irqsave(&dev->lock, flags); - if (dev->port_usb) - skb = dev->wrap(dev->port_usb, skb); - spin_unlock_irqrestore(&dev->lock, flags); - if (!skb) + skb_new = dev->wrap(skb); + if (!skb_new) goto drop; + dev_kfree_skb_any(skb); + skb = skb_new; length = skb->len; } req->buf = skb->data; @@ -605,9 +578,9 @@ static netdev_tx_t eth_start_xmit(struct sk_buff *skb, } if (retval) { - dev_kfree_skb_any(skb); drop: dev->net->stats.tx_dropped++; + dev_kfree_skb_any(skb); spin_lock_irqsave(&dev->req_lock, flags); if (list_empty(&dev->tx_reqs)) netif_start_queue(net); @@ -780,8 +753,6 @@ int __init gether_setup(struct usb_gadget *g, u8 ethaddr[ETH_ALEN]) INIT_LIST_HEAD(&dev->tx_reqs); INIT_LIST_HEAD(&dev->rx_reqs); - skb_queue_head_init(&dev->rx_frames); - /* network device setup */ dev->net = net; strcpy(net->name, "usb%d"); diff --git a/trunk/drivers/usb/gadget/u_ether.h b/trunk/drivers/usb/gadget/u_ether.h index 91b39ffdf6ea..0d1f7ae3b071 100644 --- a/trunk/drivers/usb/gadget/u_ether.h +++ b/trunk/drivers/usb/gadget/u_ether.h @@ -60,13 +60,12 @@ struct gether { u16 cdc_filter; - /* hooks for added framing, as needed for RNDIS and EEM. */ + /* hooks for added framing, as needed for RNDIS and EEM. + * we currently don't support multiple frames per SKB. + */ u32 header_len; - struct sk_buff *(*wrap)(struct gether *port, - struct sk_buff *skb); - int (*unwrap)(struct gether *port, - struct sk_buff *skb, - struct sk_buff_head *list); + struct sk_buff *(*wrap)(struct sk_buff *skb); + int (*unwrap)(struct sk_buff *skb); /* called on network open/close */ void (*open)(struct gether *); @@ -110,7 +109,6 @@ static inline bool can_support_ecm(struct usb_gadget *gadget) /* each configuration may bind one instance of an ethernet link */ int geth_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); int ecm_bind_config(struct usb_configuration *c, u8 ethaddr[ETH_ALEN]); -int eem_bind_config(struct usb_configuration *c); #ifdef CONFIG_USB_ETH_RNDIS diff --git a/trunk/drivers/usb/gadget/u_serial.c b/trunk/drivers/usb/gadget/u_serial.c index adf8260c3a6a..fc6e709f45b1 100644 --- a/trunk/drivers/usb/gadget/u_serial.c +++ b/trunk/drivers/usb/gadget/u_serial.c @@ -1114,6 +1114,7 @@ int __init gserial_setup(struct usb_gadget *g, unsigned count) /* export the driver ... */ status = tty_register_driver(gs_tty_driver); if (status) { + put_tty_driver(gs_tty_driver); pr_err("%s: cannot register, err %d\n", __func__, status); goto fail; diff --git a/trunk/drivers/usb/host/Kconfig b/trunk/drivers/usb/host/Kconfig index 9b43b226817f..f21ca7d27a43 100644 --- a/trunk/drivers/usb/host/Kconfig +++ b/trunk/drivers/usb/host/Kconfig @@ -113,12 +113,6 @@ config USB_EHCI_HCD_PPC_OF Enables support for the USB controller present on the PowerPC OpenFirmware platform bus. -config USB_W90X900_EHCI - bool "W90X900(W90P910) EHCI support" - depends on USB_EHCI_HCD && ARCH_W90X900 - ---help--- - Enables support for the W90X900 USB controller - config USB_OXU210HP_HCD tristate "OXU210HP HCD support" depends on USB @@ -159,18 +153,6 @@ config USB_ISP1760_HCD To compile this driver as a module, choose M here: the module will be called isp1760. -config USB_ISP1362_HCD - tristate "ISP1362 HCD support" - depends on USB - default N - ---help--- - Supports the Philips ISP1362 chip as a host controller - - This driver does not support isochronous transfers. - - To compile this driver as a module, choose M here: the - module will be called isp1362-hcd. - config USB_OHCI_HCD tristate "OHCI HCD support" depends on USB && USB_ARCH_HAS_OHCI diff --git a/trunk/drivers/usb/host/Makefile b/trunk/drivers/usb/host/Makefile index f58b2494c44a..289d748bb414 100644 --- a/trunk/drivers/usb/host/Makefile +++ b/trunk/drivers/usb/host/Makefile @@ -21,7 +21,6 @@ obj-$(CONFIG_PCI) += pci-quirks.o obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o -obj-$(CONFIG_USB_ISP1362_HCD) += isp1362-hcd.o obj-$(CONFIG_USB_OHCI_HCD) += ohci-hcd.o obj-$(CONFIG_USB_UHCI_HCD) += uhci-hcd.o obj-$(CONFIG_USB_FHCI_HCD) += fhci.o diff --git a/trunk/drivers/usb/host/ehci-atmel.c b/trunk/drivers/usb/host/ehci-atmel.c deleted file mode 100644 index 87c1b7c34c0e..000000000000 --- a/trunk/drivers/usb/host/ehci-atmel.c +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Driver for EHCI UHP on Atmel chips - * - * Copyright (C) 2009 Atmel Corporation, - * Nicolas Ferre - * - * Based on various ehci-*.c drivers - * - * 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. - */ - -#include -#include - -/* interface and function clocks */ -static struct clk *iclk, *fclk; -static int clocked; - -/*-------------------------------------------------------------------------*/ - -static void atmel_start_clock(void) -{ - clk_enable(iclk); - clk_enable(fclk); - clocked = 1; -} - -static void atmel_stop_clock(void) -{ - clk_disable(fclk); - clk_disable(iclk); - clocked = 0; -} - -static void atmel_start_ehci(struct platform_device *pdev) -{ - dev_dbg(&pdev->dev, "start\n"); - atmel_start_clock(); -} - -static void atmel_stop_ehci(struct platform_device *pdev) -{ - dev_dbg(&pdev->dev, "stop\n"); - atmel_stop_clock(); -} - -/*-------------------------------------------------------------------------*/ - -static int ehci_atmel_setup(struct usb_hcd *hcd) -{ - struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval = 0; - - /* registers start at offset 0x0 */ - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); - dbg_hcs_params(ehci, "reset"); - dbg_hcc_params(ehci, "reset"); - - /* cache this readonly data; minimize chip reads */ - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - - retval = ehci_halt(ehci); - if (retval) - return retval; - - /* data structure init */ - retval = ehci_init(hcd); - if (retval) - return retval; - - ehci->sbrn = 0x20; - - ehci_reset(ehci); - ehci_port_power(ehci, 0); - - return retval; -} - -static const struct hc_driver ehci_atmel_hc_driver = { - .description = hcd_name, - .product_desc = "Atmel EHCI UHP HS", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* generic hardware linkage */ - .irq = ehci_irq, - .flags = HCD_MEMORY | HCD_USB2, - - /* basic lifecycle operations */ - .reset = ehci_atmel_setup, - .start = ehci_run, - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* managing i/o requests and associated device resources */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - - /* scheduling support */ - .get_frame_number = ehci_get_frame, - - /* root hub support */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, -}; - -static int __init ehci_atmel_drv_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - const struct hc_driver *driver = &ehci_atmel_hc_driver; - struct resource *res; - int irq; - int retval; - - if (usb_disabled()) - return -ENODEV; - - pr_debug("Initializing Atmel-SoC USB Host Controller\n"); - - irq = platform_get_irq(pdev, 0); - if (irq <= 0) { - dev_err(&pdev->dev, - "Found HC with no IRQ. Check %s setup!\n", - dev_name(&pdev->dev)); - retval = -ENODEV; - goto fail_create_hcd; - } - - hcd = usb_create_hcd(driver, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) { - retval = -ENOMEM; - goto fail_create_hcd; - } - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - dev_err(&pdev->dev, - "Found HC with no register addr. Check %s setup!\n", - dev_name(&pdev->dev)); - retval = -ENODEV; - goto fail_request_resource; - } - hcd->rsrc_start = res->start; - hcd->rsrc_len = res->end - res->start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, - driver->description)) { - dev_dbg(&pdev->dev, "controller already in use\n"); - retval = -EBUSY; - goto fail_request_resource; - } - - hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - dev_dbg(&pdev->dev, "error mapping memory\n"); - retval = -EFAULT; - goto fail_ioremap; - } - - iclk = clk_get(&pdev->dev, "ehci_clk"); - if (IS_ERR(iclk)) { - dev_err(&pdev->dev, "Error getting interface clock\n"); - retval = -ENOENT; - goto fail_get_iclk; - } - fclk = clk_get(&pdev->dev, "uhpck"); - if (IS_ERR(fclk)) { - dev_err(&pdev->dev, "Error getting function clock\n"); - retval = -ENOENT; - goto fail_get_fclk; - } - - atmel_start_ehci(pdev); - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval) - goto fail_add_hcd; - - return retval; - -fail_add_hcd: - atmel_stop_ehci(pdev); - clk_put(fclk); -fail_get_fclk: - clk_put(iclk); -fail_get_iclk: - iounmap(hcd->regs); -fail_ioremap: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -fail_request_resource: - usb_put_hcd(hcd); -fail_create_hcd: - dev_err(&pdev->dev, "init %s fail, %d\n", - dev_name(&pdev->dev), retval); - - return retval; -} - -static int __exit ehci_atmel_drv_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - ehci_shutdown(hcd); - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); - - atmel_stop_ehci(pdev); - clk_put(fclk); - clk_put(iclk); - fclk = iclk = NULL; - - return 0; -} - -static struct platform_driver ehci_atmel_driver = { - .probe = ehci_atmel_drv_probe, - .remove = __exit_p(ehci_atmel_drv_remove), - .shutdown = usb_hcd_platform_shutdown, - .driver.name = "atmel-ehci", -}; diff --git a/trunk/drivers/usb/host/ehci-au1xxx.c b/trunk/drivers/usb/host/ehci-au1xxx.c index ed77be76d6bb..59d208d94d4e 100644 --- a/trunk/drivers/usb/host/ehci-au1xxx.c +++ b/trunk/drivers/usb/host/ehci-au1xxx.c @@ -199,9 +199,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) +static int ehci_hcd_au1xxx_drv_suspend(struct platform_device *pdev, + pm_message_t message) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); unsigned long flags; int rc; @@ -228,6 +229,12 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) ehci_writel(ehci, 0, &ehci->regs->intr_enable); (void)ehci_readl(ehci, &ehci->regs->intr_enable); + /* make sure snapshot being resumed re-enumerates everything */ + if (message.event == PM_EVENT_PRETHAW) { + ehci_halt(ehci); + ehci_reset(ehci); + } + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); au1xxx_stop_ehc(); @@ -241,9 +248,10 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) return rc; } -static int ehci_hcd_au1xxx_drv_resume(struct device *dev) + +static int ehci_hcd_au1xxx_drv_resume(struct platform_device *pdev) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); au1xxx_start_ehc(); @@ -297,25 +305,20 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev) return 0; } -static struct dev_pm_ops au1xxx_ehci_pmops = { - .suspend = ehci_hcd_au1xxx_drv_suspend, - .resume = ehci_hcd_au1xxx_drv_resume, -}; - -#define AU1XXX_EHCI_PMOPS &au1xxx_ehci_pmops - #else -#define AU1XXX_EHCI_PMOPS NULL +#define ehci_hcd_au1xxx_drv_suspend NULL +#define ehci_hcd_au1xxx_drv_resume NULL #endif static struct platform_driver ehci_hcd_au1xxx_driver = { .probe = ehci_hcd_au1xxx_drv_probe, .remove = ehci_hcd_au1xxx_drv_remove, .shutdown = usb_hcd_platform_shutdown, + .suspend = ehci_hcd_au1xxx_drv_suspend, + .resume = ehci_hcd_au1xxx_drv_resume, .driver = { .name = "au1xxx-ehci", .owner = THIS_MODULE, - .pm = AU1XXX_EHCI_PMOPS, } }; diff --git a/trunk/drivers/usb/host/ehci-dbg.c b/trunk/drivers/usb/host/ehci-dbg.c index 874d2000bf92..7f4ace73d44a 100644 --- a/trunk/drivers/usb/host/ehci-dbg.c +++ b/trunk/drivers/usb/host/ehci-dbg.c @@ -134,11 +134,10 @@ dbg_qtd (const char *label, struct ehci_hcd *ehci, struct ehci_qtd *qtd) static void __maybe_unused dbg_qh (const char *label, struct ehci_hcd *ehci, struct ehci_qh *qh) { - struct ehci_qh_hw *hw = qh->hw; - ehci_dbg (ehci, "%s qh %p n%08x info %x %x qtd %x\n", label, - qh, hw->hw_next, hw->hw_info1, hw->hw_info2, hw->hw_current); - dbg_qtd("overlay", ehci, (struct ehci_qtd *) &hw->hw_qtd_next); + qh, qh->hw_next, qh->hw_info1, qh->hw_info2, + qh->hw_current); + dbg_qtd ("overlay", ehci, (struct ehci_qtd *) &qh->hw_qtd_next); } static void __maybe_unused @@ -401,32 +400,31 @@ static void qh_lines ( char *next = *nextp; char mark; __le32 list_end = EHCI_LIST_END(ehci); - struct ehci_qh_hw *hw = qh->hw; - if (hw->hw_qtd_next == list_end) /* NEC does this */ + if (qh->hw_qtd_next == list_end) /* NEC does this */ mark = '@'; else - mark = token_mark(ehci, hw->hw_token); + mark = token_mark(ehci, qh->hw_token); if (mark == '/') { /* qh_alt_next controls qh advance? */ - if ((hw->hw_alt_next & QTD_MASK(ehci)) - == ehci->async->hw->hw_alt_next) + if ((qh->hw_alt_next & QTD_MASK(ehci)) + == ehci->async->hw_alt_next) mark = '#'; /* blocked */ - else if (hw->hw_alt_next == list_end) + else if (qh->hw_alt_next == list_end) mark = '.'; /* use hw_qtd_next */ /* else alt_next points to some other qtd */ } - scratch = hc32_to_cpup(ehci, &hw->hw_info1); - hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &hw->hw_current) : 0; + scratch = hc32_to_cpup(ehci, &qh->hw_info1); + hw_curr = (mark == '*') ? hc32_to_cpup(ehci, &qh->hw_current) : 0; temp = scnprintf (next, size, "qh/%p dev%d %cs ep%d %08x %08x (%08x%c %s nak%d)", qh, scratch & 0x007f, speed_char (scratch), (scratch >> 8) & 0x000f, - scratch, hc32_to_cpup(ehci, &hw->hw_info2), - hc32_to_cpup(ehci, &hw->hw_token), mark, - (cpu_to_hc32(ehci, QTD_TOGGLE) & hw->hw_token) + scratch, hc32_to_cpup(ehci, &qh->hw_info2), + hc32_to_cpup(ehci, &qh->hw_token), mark, + (cpu_to_hc32(ehci, QTD_TOGGLE) & qh->hw_token) ? "data1" : "data0", - (hc32_to_cpup(ehci, &hw->hw_alt_next) >> 1) & 0x0f); + (hc32_to_cpup(ehci, &qh->hw_alt_next) >> 1) & 0x0f); size -= temp; next += temp; @@ -437,10 +435,10 @@ static void qh_lines ( mark = ' '; if (hw_curr == td->qtd_dma) mark = '*'; - else if (hw->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) + else if (qh->hw_qtd_next == cpu_to_hc32(ehci, td->qtd_dma)) mark = '+'; else if (QTD_LENGTH (scratch)) { - if (td->hw_alt_next == ehci->async->hw->hw_alt_next) + if (td->hw_alt_next == ehci->async->hw_alt_next) mark = '#'; else if (td->hw_alt_next != list_end) mark = '/'; @@ -552,15 +550,12 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) next += temp; do { - struct ehci_qh_hw *hw; - switch (hc32_to_cpu(ehci, tag)) { case Q_TYPE_QH: - hw = p.qh->hw; temp = scnprintf (next, size, " qh%d-%04x/%p", p.qh->period, hc32_to_cpup(ehci, - &hw->hw_info2) + &p.qh->hw_info2) /* uframe masks */ & (QH_CMASK | QH_SMASK), p.qh); @@ -581,7 +576,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) /* show more info the first time around */ if (temp == seen_count) { u32 scratch = hc32_to_cpup(ehci, - &hw->hw_info1); + &p.qh->hw_info1); struct ehci_qtd *qtd; char *type = ""; @@ -614,7 +609,7 @@ static ssize_t fill_periodic_buffer(struct debug_buffer *buf) } else temp = 0; if (p.qh) { - tag = Q_NEXT_TYPE(ehci, hw->hw_next); + tag = Q_NEXT_TYPE(ehci, p.qh->hw_next); p = p.qh->qh_next; } break; @@ -884,7 +879,8 @@ static int debug_close(struct inode *inode, struct file *file) struct debug_buffer *buf = file->private_data; if (buf) { - vfree(buf->output_buf); + if (buf->output_buf) + vfree(buf->output_buf); kfree(buf); } diff --git a/trunk/drivers/usb/host/ehci-hcd.c b/trunk/drivers/usb/host/ehci-hcd.c index 9835e0713943..11c627ce6022 100644 --- a/trunk/drivers/usb/host/ehci-hcd.c +++ b/trunk/drivers/usb/host/ehci-hcd.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -126,8 +127,6 @@ timer_action(struct ehci_hcd *ehci, enum ehci_timer_action action) switch (action) { case TIMER_IO_WATCHDOG: - if (!ehci->need_io_watchdog) - return; t = EHCI_IO_JIFFIES; break; case TIMER_ASYNC_OFF: @@ -240,11 +239,6 @@ static int ehci_reset (struct ehci_hcd *ehci) int retval; u32 command = ehci_readl(ehci, &ehci->regs->command); - /* If the EHCI debug controller is active, special care must be - * taken before and after a host controller reset */ - if (ehci->debug && !dbgp_reset_prep()) - ehci->debug = NULL; - command |= CMD_RESET; dbg_cmd (ehci, "reset", command); ehci_writel(ehci, command, &ehci->regs->command); @@ -253,21 +247,12 @@ static int ehci_reset (struct ehci_hcd *ehci) retval = handshake (ehci, &ehci->regs->command, CMD_RESET, 0, 250 * 1000); - if (ehci->has_hostpc) { - ehci_writel(ehci, USBMODE_EX_HC | USBMODE_EX_VBPS, - (u32 __iomem *)(((u8 *)ehci->regs) + USBMODE_EX)); - ehci_writel(ehci, TXFIFO_DEFAULT, - (u32 __iomem *)(((u8 *)ehci->regs) + TXFILLTUNING)); - } if (retval) return retval; if (ehci_is_TDI(ehci)) tdi_reset (ehci); - if (ehci->debug) - dbgp_external_startup(); - return retval; } @@ -520,14 +505,9 @@ static int ehci_init(struct usb_hcd *hcd) u32 temp; int retval; u32 hcc_params; - struct ehci_qh_hw *hw; spin_lock_init(&ehci->lock); - /* - * keep io watchdog by default, those good HCDs could turn off it later - */ - ehci->need_io_watchdog = 1; init_timer(&ehci->watchdog); ehci->watchdog.function = ehci_watchdog; ehci->watchdog.data = (unsigned long) ehci; @@ -564,13 +544,12 @@ static int ehci_init(struct usb_hcd *hcd) * from automatically advancing to the next td after short reads. */ ehci->async->qh_next.qh = NULL; - hw = ehci->async->hw; - hw->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); - hw->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); - hw->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); - hw->hw_qtd_next = EHCI_LIST_END(ehci); + ehci->async->hw_next = QH_NEXT(ehci, ehci->async->qh_dma); + ehci->async->hw_info1 = cpu_to_hc32(ehci, QH_HEAD); + ehci->async->hw_token = cpu_to_hc32(ehci, QTD_STS_HALT); + ehci->async->hw_qtd_next = EHCI_LIST_END(ehci); ehci->async->qh_state = QH_STATE_LINKED; - hw->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); + ehci->async->hw_alt_next = QTD_NEXT(ehci, ehci->async->dummy->qtd_dma); /* clear interrupt enables, set irq latency */ if (log2_irq_thresh < 0 || log2_irq_thresh > 6) @@ -871,18 +850,12 @@ static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) if (!HC_IS_RUNNING(ehci_to_hcd(ehci)->state) && ehci->reclaim) end_unlink_async(ehci); - /* If the QH isn't linked then there's nothing we can do - * unless we were called during a giveback, in which case - * qh_completions() has to deal with it. - */ - if (qh->qh_state != QH_STATE_LINKED) { - if (qh->qh_state == QH_STATE_COMPLETING) - qh->needs_rescan = 1; - return; - } + /* if it's not linked then there's nothing to do */ + if (qh->qh_state != QH_STATE_LINKED) + ; /* defer till later if busy */ - if (ehci->reclaim) { + else if (ehci->reclaim) { struct ehci_qh *last; for (last = ehci->reclaim; @@ -942,9 +915,8 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) break; switch (qh->qh_state) { case QH_STATE_LINKED: - case QH_STATE_COMPLETING: intr_deschedule (ehci, qh); - break; + /* FALL THROUGH */ case QH_STATE_IDLE: qh_completions (ehci, qh); break; @@ -953,6 +925,23 @@ static int ehci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) qh, qh->qh_state); goto done; } + + /* reschedule QH iff another request is queued */ + if (!list_empty (&qh->qtd_list) + && HC_IS_RUNNING (hcd->state)) { + rc = qh_schedule(ehci, qh); + + /* An error here likely indicates handshake failure + * or no space left in the schedule. Neither fault + * should happen often ... + * + * FIXME kill the now-dysfunctional queued urbs + */ + if (rc != 0) + ehci_err(ehci, + "can't reschedule qh %p, err %d", + qh, rc); + } break; case PIPE_ISOCHRONOUS: @@ -990,7 +979,7 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) /* endpoints can be iso streams. for now, we don't * accelerate iso completions ... so spin a while. */ - if (qh->hw->hw_info1 == 0) { + if (qh->hw_info1 == 0) { ehci_vdbg (ehci, "iso delay\n"); goto idle_timeout; } @@ -999,7 +988,6 @@ ehci_endpoint_disable (struct usb_hcd *hcd, struct usb_host_endpoint *ep) qh->qh_state = QH_STATE_IDLE; switch (qh->qh_state) { case QH_STATE_LINKED: - case QH_STATE_COMPLETING: for (tmp = ehci->async->qh_next.qh; tmp && tmp != qh; tmp = tmp->qh_next.qh) @@ -1064,17 +1052,18 @@ ehci_endpoint_reset(struct usb_hcd *hcd, struct usb_host_endpoint *ep) usb_settoggle(qh->dev, epnum, is_out, 0); if (!list_empty(&qh->qtd_list)) { WARN_ONCE(1, "clear_halt for a busy endpoint\n"); - } else if (qh->qh_state == QH_STATE_LINKED || - qh->qh_state == QH_STATE_COMPLETING) { + } else if (qh->qh_state == QH_STATE_LINKED) { /* The toggle value in the QH can't be updated * while the QH is active. Unlink it now; * re-linking will call qh_refresh(). */ - if (eptype == USB_ENDPOINT_XFER_BULK) + if (eptype == USB_ENDPOINT_XFER_BULK) { unlink_async(ehci, qh); - else + } else { intr_deschedule(ehci, qh); + (void) qh_schedule(ehci, qh); + } } } spin_unlock_irqrestore(&ehci->lock, flags); @@ -1128,16 +1117,6 @@ MODULE_LICENSE ("GPL"); #define PLATFORM_DRIVER ixp4xx_ehci_driver #endif -#ifdef CONFIG_USB_W90X900_EHCI -#include "ehci-w90x900.c" -#define PLATFORM_DRIVER ehci_hcd_w90x900_driver -#endif - -#ifdef CONFIG_ARCH_AT91 -#include "ehci-atmel.c" -#define PLATFORM_DRIVER ehci_atmel_driver -#endif - #if !defined(PCI_DRIVER) && !defined(PLATFORM_DRIVER) && \ !defined(PS3_SYSTEM_BUS_DRIVER) && !defined(OF_PLATFORM_DRIVER) #error "missing bus glue for ehci-hcd" diff --git a/trunk/drivers/usb/host/ehci-hub.c b/trunk/drivers/usb/host/ehci-hub.c index 1b6f1c0e5cee..f46ad27c9a90 100644 --- a/trunk/drivers/usb/host/ehci-hub.c +++ b/trunk/drivers/usb/host/ehci-hub.c @@ -111,7 +111,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) struct ehci_hcd *ehci = hcd_to_ehci (hcd); int port; int mask; - u32 __iomem *hostpc_reg = NULL; ehci_dbg(ehci, "suspend root hub\n"); @@ -143,9 +142,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; u32 t2 = t1; - if (ehci->has_hostpc) - hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs - + HOSTPC0 + 4 * (port & 0xff)); /* keep track of which ports we suspend */ if (t1 & PORT_OWNER) set_bit(port, &ehci->owned_ports); @@ -155,37 +151,15 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) } /* enable remote wakeup on all ports */ - if (hcd->self.root_hub->do_remote_wakeup) { - /* only enable appropriate wake bits, otherwise the - * hardware can not go phy low power mode. If a race - * condition happens here(connection change during bits - * set), the port change detection will finally fix it. - */ - if (t1 & PORT_CONNECT) { - t2 |= PORT_WKOC_E | PORT_WKDISC_E; - t2 &= ~PORT_WKCONN_E; - } else { - t2 |= PORT_WKOC_E | PORT_WKCONN_E; - t2 &= ~PORT_WKDISC_E; - } - } else + if (hcd->self.root_hub->do_remote_wakeup) + t2 |= PORT_WAKE_BITS; + else t2 &= ~PORT_WAKE_BITS; if (t1 != t2) { ehci_vdbg (ehci, "port %d, %08x -> %08x\n", port + 1, t1, t2); ehci_writel(ehci, t2, reg); - if (hostpc_reg) { - u32 t3; - - msleep(5);/* 5ms for HCD enter low pwr mode */ - t3 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); - t3 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", - port, (t3 & HOSTPC_PHCD) ? - "succeeded" : "failed"); - } } } @@ -209,11 +183,6 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) ehci->next_statechange = jiffies + msecs_to_jiffies(10); spin_unlock_irq (&ehci->lock); - - /* ehci_work() may have re-enabled the watchdog timer, which we do not - * want, and so we must delete any pending watchdog timer events. - */ - del_timer_sync(&ehci->watchdog); return 0; } @@ -235,13 +204,6 @@ static int ehci_bus_resume (struct usb_hcd *hcd) return -ESHUTDOWN; } - if (unlikely(ehci->debug)) { - if (ehci->debug && !dbgp_reset_prep()) - ehci->debug = NULL; - else - dbgp_external_startup(); - } - /* Ideally and we've got a real resume here, and no port's power * was lost. (For PCI, that means Vaux was maintained.) But we * could instead be restoring a swsusp snapshot -- so that BIOS was @@ -601,8 +563,7 @@ static int ehci_hub_control ( int ports = HCS_N_PORTS (ehci->hcs_params); u32 __iomem *status_reg = &ehci->regs->port_status[ (wIndex & 0xff) - 1]; - u32 __iomem *hostpc_reg = NULL; - u32 temp, temp1, status; + u32 temp, status; unsigned long flags; int retval = 0; unsigned selector; @@ -614,9 +575,6 @@ static int ehci_hub_control ( * power, "this is the one", etc. EHCI spec supports this. */ - if (ehci->has_hostpc) - hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs - + HOSTPC0 + 4 * ((wIndex & 0xff) - 1)); spin_lock_irqsave (&ehci->lock, flags); switch (typeReq) { case ClearHubFeature: @@ -815,11 +773,7 @@ static int ehci_hub_control ( if (temp & PORT_CONNECT) { status |= 1 << USB_PORT_FEAT_CONNECTION; // status may be from integrated TT - if (ehci->has_hostpc) { - temp1 = ehci_readl(ehci, hostpc_reg); - status |= ehci_port_speed(ehci, temp1); - } else - status |= ehci_port_speed(ehci, temp); + status |= ehci_port_speed(ehci, temp); } if (temp & PORT_PE) status |= 1 << USB_PORT_FEAT_ENABLE; @@ -862,15 +816,6 @@ static int ehci_hub_control ( case SetPortFeature: selector = wIndex >> 8; wIndex &= 0xff; - if (unlikely(ehci->debug)) { - /* If the debug port is active any port - * feature requests should get denied */ - if (wIndex == HCS_DEBUG_PORT(ehci->hcs_params) && - (readl(&ehci->debug->control) & DBGP_ENABLED)) { - retval = -ENODEV; - goto error_exit; - } - } if (!wIndex || wIndex > ports) goto error; wIndex--; @@ -887,24 +832,6 @@ static int ehci_hub_control ( || (temp & PORT_RESET) != 0) goto error; ehci_writel(ehci, temp | PORT_SUSPEND, status_reg); - /* After above check the port must be connected. - * Set appropriate bit thus could put phy into low power - * mode if we have hostpc feature - */ - if (hostpc_reg) { - temp &= ~PORT_WKCONN_E; - temp |= (PORT_WKDISC_E | PORT_WKOC_E); - ehci_writel(ehci, temp | PORT_SUSPEND, - status_reg); - msleep(5);/* 5ms for HCD enter low pwr mode */ - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_writel(ehci, temp1 | HOSTPC_PHCD, - hostpc_reg); - temp1 = ehci_readl(ehci, hostpc_reg); - ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", - wIndex, (temp1 & HOSTPC_PHCD) ? - "succeeded" : "failed"); - } set_bit(wIndex, &ehci->suspended_ports); break; case USB_PORT_FEAT_POWER: @@ -967,7 +894,6 @@ static int ehci_hub_control ( /* "stall" on error */ retval = -EPIPE; } -error_exit: spin_unlock_irqrestore (&ehci->lock, flags); return retval; } diff --git a/trunk/drivers/usb/host/ehci-mem.c b/trunk/drivers/usb/host/ehci-mem.c index aeda96e0af67..10d52919abbb 100644 --- a/trunk/drivers/usb/host/ehci-mem.c +++ b/trunk/drivers/usb/host/ehci-mem.c @@ -75,8 +75,7 @@ static void qh_destroy(struct ehci_qh *qh) } if (qh->dummy) ehci_qtd_free (ehci, qh->dummy); - dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); - kfree(qh); + dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); } static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) @@ -84,14 +83,12 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) struct ehci_qh *qh; dma_addr_t dma; - qh = kzalloc(sizeof *qh, GFP_ATOMIC); + qh = (struct ehci_qh *) + dma_pool_alloc (ehci->qh_pool, flags, &dma); if (!qh) - goto done; - qh->hw = (struct ehci_qh_hw *) - dma_pool_alloc(ehci->qh_pool, flags, &dma); - if (!qh->hw) - goto fail; - memset(qh->hw, 0, sizeof *qh->hw); + return qh; + + memset (qh, 0, sizeof *qh); qh->refcount = 1; qh->ehci = ehci; qh->qh_dma = dma; @@ -102,15 +99,10 @@ static struct ehci_qh *ehci_qh_alloc (struct ehci_hcd *ehci, gfp_t flags) qh->dummy = ehci_qtd_alloc (ehci, flags); if (qh->dummy == NULL) { ehci_dbg (ehci, "no dummy td\n"); - goto fail1; + dma_pool_free (ehci->qh_pool, qh, qh->qh_dma); + qh = NULL; } -done: return qh; -fail1: - dma_pool_free(ehci->qh_pool, qh->hw, qh->qh_dma); -fail: - kfree(qh); - return NULL; } /* to share a qh (cpu threads, or hc) */ @@ -188,7 +180,7 @@ static int ehci_mem_init (struct ehci_hcd *ehci, gfp_t flags) /* QHs for control/bulk/intr transfers */ ehci->qh_pool = dma_pool_create ("ehci_qh", ehci_to_hcd(ehci)->self.controller, - sizeof(struct ehci_qh_hw), + sizeof (struct ehci_qh), 32 /* byte alignment (for hw parts) */, 4096 /* can't cross 4K */); if (!ehci->qh_pool) { diff --git a/trunk/drivers/usb/host/ehci-pci.c b/trunk/drivers/usb/host/ehci-pci.c index 378861b9d79a..b5b83c43898a 100644 --- a/trunk/drivers/usb/host/ehci-pci.c +++ b/trunk/drivers/usb/host/ehci-pci.c @@ -27,8 +27,28 @@ /* called after powerup, by probe or system-pm "wakeup" */ static int ehci_pci_reinit(struct ehci_hcd *ehci, struct pci_dev *pdev) { + u32 temp; int retval; + /* optional debug port, normally in the first BAR */ + temp = pci_find_capability(pdev, 0x0a); + if (temp) { + pci_read_config_dword(pdev, temp, &temp); + temp >>= 16; + if ((temp & (3 << 13)) == (1 << 13)) { + temp &= 0x1fff; + ehci->debug = ehci_to_hcd(ehci)->regs + temp; + temp = ehci_readl(ehci, &ehci->debug->control); + ehci_info(ehci, "debug port %d%s\n", + HCS_DEBUG_PORT(ehci->hcs_params), + (temp & DBGP_ENABLED) + ? " IN USE" + : ""); + if (!(temp & DBGP_ENABLED)) + ehci->debug = NULL; + } + } + /* we expect static quirk code to handle the "extended capabilities" * (currently just BIOS handoff) allowed starting with EHCI 0.96 */ @@ -109,9 +129,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) return retval; switch (pdev->vendor) { - case PCI_VENDOR_ID_INTEL: - ehci->need_io_watchdog = 0; - break; case PCI_VENDOR_ID_TDI: if (pdev->device == PCI_DEVICE_ID_TDI_EHCI) { hcd->has_tt = 1; @@ -175,25 +192,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) break; } - /* optional debug port, normally in the first BAR */ - temp = pci_find_capability(pdev, 0x0a); - if (temp) { - pci_read_config_dword(pdev, temp, &temp); - temp >>= 16; - if ((temp & (3 << 13)) == (1 << 13)) { - temp &= 0x1fff; - ehci->debug = ehci_to_hcd(ehci)->regs + temp; - temp = ehci_readl(ehci, &ehci->debug->control); - ehci_info(ehci, "debug port %d%s\n", - HCS_DEBUG_PORT(ehci->hcs_params), - (temp & DBGP_ENABLED) - ? " IN USE" - : ""); - if (!(temp & DBGP_ENABLED)) - ehci->debug = NULL; - } - } - ehci_reset(ehci); /* at least the Genesys GL880S needs fixup here */ diff --git a/trunk/drivers/usb/host/ehci-q.c b/trunk/drivers/usb/host/ehci-q.c index 00ad9ce392ed..7673554fa64d 100644 --- a/trunk/drivers/usb/host/ehci-q.c +++ b/trunk/drivers/usb/host/ehci-q.c @@ -87,33 +87,31 @@ qtd_fill(struct ehci_hcd *ehci, struct ehci_qtd *qtd, dma_addr_t buf, static inline void qh_update (struct ehci_hcd *ehci, struct ehci_qh *qh, struct ehci_qtd *qtd) { - struct ehci_qh_hw *hw = qh->hw; - /* writes to an active overlay are unsafe */ BUG_ON(qh->qh_state != QH_STATE_IDLE); - hw->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); - hw->hw_alt_next = EHCI_LIST_END(ehci); + qh->hw_qtd_next = QTD_NEXT(ehci, qtd->qtd_dma); + qh->hw_alt_next = EHCI_LIST_END(ehci); /* Except for control endpoints, we make hardware maintain data * toggle (like OHCI) ... here (re)initialize the toggle in the QH, * and set the pseudo-toggle in udev. Only usb_clear_halt() will * ever clear it. */ - if (!(hw->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { + if (!(qh->hw_info1 & cpu_to_hc32(ehci, 1 << 14))) { unsigned is_out, epnum; is_out = !(qtd->hw_token & cpu_to_hc32(ehci, 1 << 8)); - epnum = (hc32_to_cpup(ehci, &hw->hw_info1) >> 8) & 0x0f; + epnum = (hc32_to_cpup(ehci, &qh->hw_info1) >> 8) & 0x0f; if (unlikely (!usb_gettoggle (qh->dev, epnum, is_out))) { - hw->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); + qh->hw_token &= ~cpu_to_hc32(ehci, QTD_TOGGLE); usb_settoggle (qh->dev, epnum, is_out, 1); } } /* HC must see latest qtd and qh data before we clear ACTIVE+HALT */ wmb (); - hw->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); + qh->hw_token &= cpu_to_hc32(ehci, QTD_TOGGLE | QTD_STS_PING); } /* if it weren't for a common silicon quirk (writing the dummy into the qh @@ -131,7 +129,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) qtd = list_entry (qh->qtd_list.next, struct ehci_qtd, qtd_list); /* first qtd may already be partially processed */ - if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) + if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw_current) qtd = NULL; } @@ -262,7 +260,7 @@ __acquires(ehci->lock) struct ehci_qh *qh = (struct ehci_qh *) urb->hcpriv; /* S-mask in a QH means it's an interrupt urb */ - if ((qh->hw->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { + if ((qh->hw_info2 & cpu_to_hc32(ehci, QH_SMASK)) != 0) { /* ... update hc-wide periodic stats (for usbfs) */ ehci_to_hcd(ehci)->self.bandwidth_int_reqs--; @@ -299,6 +297,7 @@ __acquires(ehci->lock) static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); static void unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh); +static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh); static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); /* @@ -309,14 +308,13 @@ static int qh_schedule (struct ehci_hcd *ehci, struct ehci_qh *qh); static unsigned qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) { - struct ehci_qtd *last, *end = qh->dummy; + struct ehci_qtd *last = NULL, *end = qh->dummy; struct list_head *entry, *tmp; - int last_status; + int last_status = -EINPROGRESS; int stopped; unsigned count = 0; u8 state; - const __le32 halt = HALT_BIT(ehci); - struct ehci_qh_hw *hw = qh->hw; + __le32 halt = HALT_BIT(ehci); if (unlikely (list_empty (&qh->qtd_list))) return count; @@ -326,20 +324,11 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) * they add urbs to this qh's queue or mark them for unlinking. * * NOTE: unlinking expects to be done in queue order. - * - * It's a bug for qh->qh_state to be anything other than - * QH_STATE_IDLE, unless our caller is scan_async() or - * scan_periodic(). */ state = qh->qh_state; qh->qh_state = QH_STATE_COMPLETING; stopped = (state == QH_STATE_IDLE); - rescan: - last = NULL; - last_status = -EINPROGRESS; - qh->needs_rescan = 0; - /* remove de-activated QTDs from front of queue. * after faults (including short reads), cleanup this urb * then let the queue advance. @@ -403,8 +392,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) qtd->hw_token = cpu_to_hc32(ehci, token); wmb(); - hw->hw_token = cpu_to_hc32(ehci, - token); + qh->hw_token = cpu_to_hc32(ehci, token); goto retry_xacterr; } stopped = 1; @@ -447,8 +435,8 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) /* qh unlinked; token in overlay may be most current */ if (state == QH_STATE_IDLE && cpu_to_hc32(ehci, qtd->qtd_dma) - == hw->hw_current) { - token = hc32_to_cpu(ehci, hw->hw_token); + == qh->hw_current) { + token = hc32_to_cpu(ehci, qh->hw_token); /* An unlink may leave an incomplete * async transaction in the TT buffer. @@ -461,9 +449,9 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) * patch the qh later and so that completions can't * activate it while we "know" it's stopped. */ - if ((halt & hw->hw_token) == 0) { + if ((halt & qh->hw_token) == 0) { halt: - hw->hw_token |= halt; + qh->hw_token |= halt; wmb (); } } @@ -515,21 +503,6 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) ehci_qtd_free (ehci, last); } - /* Do we need to rescan for URBs dequeued during a giveback? */ - if (unlikely(qh->needs_rescan)) { - /* If the QH is already unlinked, do the rescan now. */ - if (state == QH_STATE_IDLE) - goto rescan; - - /* Otherwise we have to wait until the QH is fully unlinked. - * Our caller will start an unlink if qh->needs_rescan is - * set. But if an unlink has already started, nothing needs - * to be done. - */ - if (state != QH_STATE_LINKED) - qh->needs_rescan = 0; - } - /* restore original state; caller must unlink or relink */ qh->qh_state = state; @@ -537,7 +510,7 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) * it after fault cleanup, or recovering from silicon wrongly * overlaying the dummy qtd (which reduces DMA chatter). */ - if (stopped != 0 || hw->hw_qtd_next == EHCI_LIST_END(ehci)) { + if (stopped != 0 || qh->hw_qtd_next == EHCI_LIST_END(ehci)) { switch (state) { case QH_STATE_IDLE: qh_refresh(ehci, qh); @@ -554,9 +527,12 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) * That should be rare for interrupt transfers, * except maybe high bandwidth ... */ - - /* Tell the caller to start an unlink */ - qh->needs_rescan = 1; + if ((cpu_to_hc32(ehci, QH_SMASK) + & qh->hw_info2) != 0) { + intr_deschedule (ehci, qh); + (void) qh_schedule (ehci, qh); + } else + unlink_async (ehci, qh); break; /* otherwise, unlink already started */ } @@ -673,7 +649,7 @@ qh_urb_transaction ( * (this will usually be overridden later.) */ if (is_input) - qtd->hw_alt_next = ehci->async->hw->hw_alt_next; + qtd->hw_alt_next = ehci->async->hw_alt_next; /* qh makes control packets use qtd toggle; maybe switch it */ if ((maxpacket & (this_qtd_len + (maxpacket - 1))) == 0) @@ -768,7 +744,6 @@ qh_make ( int is_input, type; int maxp = 0; struct usb_tt *tt = urb->dev->tt; - struct ehci_qh_hw *hw; if (!qh) return qh; @@ -915,9 +890,8 @@ qh_make ( /* init as live, toggle clear, advance to dummy */ qh->qh_state = QH_STATE_IDLE; - hw = qh->hw; - hw->hw_info1 = cpu_to_hc32(ehci, info1); - hw->hw_info2 = cpu_to_hc32(ehci, info2); + qh->hw_info1 = cpu_to_hc32(ehci, info1); + qh->hw_info2 = cpu_to_hc32(ehci, info2); usb_settoggle (urb->dev, usb_pipeendpoint (urb->pipe), !is_input, 1); qh_refresh (ehci, qh); return qh; @@ -936,8 +910,6 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) if (unlikely(qh->clearing_tt)) return; - WARN_ON(qh->qh_state != QH_STATE_IDLE); - /* (re)start the async schedule? */ head = ehci->async; timer_action_done (ehci, TIMER_ASYNC_OFF); @@ -956,15 +928,16 @@ static void qh_link_async (struct ehci_hcd *ehci, struct ehci_qh *qh) } /* clear halt and/or toggle; and maybe recover from silicon quirk */ - qh_refresh(ehci, qh); + if (qh->qh_state == QH_STATE_IDLE) + qh_refresh (ehci, qh); /* splice right after start */ qh->qh_next = head->qh_next; - qh->hw->hw_next = head->hw->hw_next; + qh->hw_next = head->hw_next; wmb (); head->qh_next.qh = qh; - head->hw->hw_next = dma; + head->hw_next = dma; qh_get(qh); qh->xacterrs = 0; @@ -1011,7 +984,7 @@ static struct ehci_qh *qh_append_tds ( /* usb_reset_device() briefly reverts to address 0 */ if (usb_pipedevice (urb->pipe) == 0) - qh->hw->hw_info1 &= ~qh_addr_mask; + qh->hw_info1 &= ~qh_addr_mask; } /* just one way to queue requests: swap with the dummy qtd. @@ -1196,7 +1169,7 @@ static void start_unlink_async (struct ehci_hcd *ehci, struct ehci_qh *qh) while (prev->qh_next.qh != qh) prev = prev->qh_next.qh; - prev->hw->hw_next = qh->hw->hw_next; + prev->hw_next = qh->hw_next; prev->qh_next = qh->qh_next; wmb (); @@ -1241,8 +1214,6 @@ static void scan_async (struct ehci_hcd *ehci) qh = qh_get (qh); qh->stamp = ehci->stamp; temp = qh_completions (ehci, qh); - if (qh->needs_rescan) - unlink_async(ehci, qh); qh_put (qh); if (temp != 0) { goto rescan; diff --git a/trunk/drivers/usb/host/ehci-sched.c b/trunk/drivers/usb/host/ehci-sched.c index 3ea05936851f..edd61ee90323 100644 --- a/trunk/drivers/usb/host/ehci-sched.c +++ b/trunk/drivers/usb/host/ehci-sched.c @@ -60,20 +60,6 @@ periodic_next_shadow(struct ehci_hcd *ehci, union ehci_shadow *periodic, } } -static __hc32 * -shadow_next_periodic(struct ehci_hcd *ehci, union ehci_shadow *periodic, - __hc32 tag) -{ - switch (hc32_to_cpu(ehci, tag)) { - /* our ehci_shadow.qh is actually software part */ - case Q_TYPE_QH: - return &periodic->qh->hw->hw_next; - /* others are hw parts */ - default: - return periodic->hw_next; - } -} - /* caller must hold ehci->lock */ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) { @@ -85,8 +71,7 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) while (here.ptr && here.ptr != ptr) { prev_p = periodic_next_shadow(ehci, prev_p, Q_NEXT_TYPE(ehci, *hw_p)); - hw_p = shadow_next_periodic(ehci, &here, - Q_NEXT_TYPE(ehci, *hw_p)); + hw_p = here.hw_next; here = *prev_p; } /* an interrupt entry (at list end) could have been shared */ @@ -98,7 +83,7 @@ static void periodic_unlink (struct ehci_hcd *ehci, unsigned frame, void *ptr) */ *prev_p = *periodic_next_shadow(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)); - *hw_p = *shadow_next_periodic(ehci, &here, Q_NEXT_TYPE(ehci, *hw_p)); + *hw_p = *here.hw_next; } /* how many of the uframe's 125 usecs are allocated? */ @@ -108,20 +93,18 @@ periodic_usecs (struct ehci_hcd *ehci, unsigned frame, unsigned uframe) __hc32 *hw_p = &ehci->periodic [frame]; union ehci_shadow *q = &ehci->pshadow [frame]; unsigned usecs = 0; - struct ehci_qh_hw *hw; while (q->ptr) { switch (hc32_to_cpu(ehci, Q_NEXT_TYPE(ehci, *hw_p))) { case Q_TYPE_QH: - hw = q->qh->hw; /* is it in the S-mask? */ - if (hw->hw_info2 & cpu_to_hc32(ehci, 1 << uframe)) + if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << uframe)) usecs += q->qh->usecs; /* ... or C-mask? */ - if (hw->hw_info2 & cpu_to_hc32(ehci, + if (q->qh->hw_info2 & cpu_to_hc32(ehci, 1 << (8 + uframe))) usecs += q->qh->c_usecs; - hw_p = &hw->hw_next; + hw_p = &q->qh->hw_next; q = &q->qh->qh_next; break; // case Q_TYPE_FSTN: @@ -254,10 +237,10 @@ periodic_tt_usecs ( continue; case Q_TYPE_QH: if (same_tt(dev, q->qh->dev)) { - uf = tt_start_uframe(ehci, q->qh->hw->hw_info2); + uf = tt_start_uframe(ehci, q->qh->hw_info2); tt_usecs[uf] += q->qh->tt_usecs; } - hw_p = &q->qh->hw->hw_next; + hw_p = &q->qh->hw_next; q = &q->qh->qh_next; continue; case Q_TYPE_SITD: @@ -392,7 +375,6 @@ static int tt_no_collision ( for (; frame < ehci->periodic_size; frame += period) { union ehci_shadow here; __hc32 type; - struct ehci_qh_hw *hw; here = ehci->pshadow [frame]; type = Q_NEXT_TYPE(ehci, ehci->periodic [frame]); @@ -403,18 +385,17 @@ static int tt_no_collision ( here = here.itd->itd_next; continue; case Q_TYPE_QH: - hw = here.qh->hw; if (same_tt (dev, here.qh->dev)) { u32 mask; mask = hc32_to_cpu(ehci, - hw->hw_info2); + here.qh->hw_info2); /* "knows" no gap is needed */ mask |= mask >> 8; if (mask & uf_mask) break; } - type = Q_NEXT_TYPE(ehci, hw->hw_next); + type = Q_NEXT_TYPE(ehci, here.qh->hw_next); here = here.qh->qh_next; continue; case Q_TYPE_SITD: @@ -517,8 +498,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) dev_dbg (&qh->dev->dev, "link qh%d-%04x/%p start %d [%d/%d us]\n", - period, hc32_to_cpup(ehci, &qh->hw->hw_info2) - & (QH_CMASK | QH_SMASK), + period, hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); /* high bandwidth, or otherwise every microframe */ @@ -537,7 +517,7 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) if (type == cpu_to_hc32(ehci, Q_TYPE_QH)) break; prev = periodic_next_shadow(ehci, prev, type); - hw_p = shadow_next_periodic(ehci, &here, type); + hw_p = &here.qh->hw_next; here = *prev; } @@ -548,14 +528,14 @@ static int qh_link_periodic (struct ehci_hcd *ehci, struct ehci_qh *qh) if (qh->period > here.qh->period) break; prev = &here.qh->qh_next; - hw_p = &here.qh->hw->hw_next; + hw_p = &here.qh->hw_next; here = *prev; } /* link in this qh, unless some earlier pass did that */ if (qh != here.qh) { qh->qh_next = here; if (here.qh) - qh->hw->hw_next = *hw_p; + qh->hw_next = *hw_p; wmb (); prev->qh = qh; *hw_p = QH_NEXT (ehci, qh->qh_dma); @@ -601,7 +581,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) dev_dbg (&qh->dev->dev, "unlink qh%d-%04x/%p start %d [%d/%d us]\n", qh->period, - hc32_to_cpup(ehci, &qh->hw->hw_info2) & (QH_CMASK | QH_SMASK), + hc32_to_cpup(ehci, &qh->hw_info2) & (QH_CMASK | QH_SMASK), qh, qh->start, qh->usecs, qh->c_usecs); /* qh->qh_next still "live" to HC */ @@ -615,19 +595,7 @@ static int qh_unlink_periodic(struct ehci_hcd *ehci, struct ehci_qh *qh) static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) { - unsigned wait; - struct ehci_qh_hw *hw = qh->hw; - int rc; - - /* If the QH isn't linked then there's nothing we can do - * unless we were called during a giveback, in which case - * qh_completions() has to deal with it. - */ - if (qh->qh_state != QH_STATE_LINKED) { - if (qh->qh_state == QH_STATE_COMPLETING) - qh->needs_rescan = 1; - return; - } + unsigned wait; qh_unlink_periodic (ehci, qh); @@ -638,33 +606,15 @@ static void intr_deschedule (struct ehci_hcd *ehci, struct ehci_qh *qh) */ if (list_empty (&qh->qtd_list) || (cpu_to_hc32(ehci, QH_CMASK) - & hw->hw_info2) != 0) + & qh->hw_info2) != 0) wait = 2; else wait = 55; /* worst case: 3 * 1024 */ udelay (wait); qh->qh_state = QH_STATE_IDLE; - hw->hw_next = EHCI_LIST_END(ehci); + qh->hw_next = EHCI_LIST_END(ehci); wmb (); - - qh_completions(ehci, qh); - - /* reschedule QH iff another request is queued */ - if (!list_empty(&qh->qtd_list) && - HC_IS_RUNNING(ehci_to_hcd(ehci)->state)) { - rc = qh_schedule(ehci, qh); - - /* An error here likely indicates handshake failure - * or no space left in the schedule. Neither fault - * should happen often ... - * - * FIXME kill the now-dysfunctional queued urbs - */ - if (rc != 0) - ehci_err(ehci, "can't reschedule qh %p, err %d\n", - qh, rc); - } } /*-------------------------------------------------------------------------*/ @@ -789,15 +739,14 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) unsigned uframe; __hc32 c_mask; unsigned frame; /* 0..(qh->period - 1), or NO_FRAME */ - struct ehci_qh_hw *hw = qh->hw; qh_refresh(ehci, qh); - hw->hw_next = EHCI_LIST_END(ehci); + qh->hw_next = EHCI_LIST_END(ehci); frame = qh->start; /* reuse the previous schedule slots, if we can */ if (frame < qh->period) { - uframe = ffs(hc32_to_cpup(ehci, &hw->hw_info2) & QH_SMASK); + uframe = ffs(hc32_to_cpup(ehci, &qh->hw_info2) & QH_SMASK); status = check_intr_schedule (ehci, frame, --uframe, qh, &c_mask); } else { @@ -835,11 +784,11 @@ static int qh_schedule(struct ehci_hcd *ehci, struct ehci_qh *qh) qh->start = frame; /* reset S-frame and (maybe) C-frame masks */ - hw->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); - hw->hw_info2 |= qh->period + qh->hw_info2 &= cpu_to_hc32(ehci, ~(QH_CMASK | QH_SMASK)); + qh->hw_info2 |= qh->period ? cpu_to_hc32(ehci, 1 << uframe) : cpu_to_hc32(ehci, QH_SMASK); - hw->hw_info2 |= c_mask; + qh->hw_info2 |= c_mask; } else ehci_dbg (ehci, "reused qh %p schedule\n", qh); @@ -2239,11 +2188,10 @@ scan_periodic (struct ehci_hcd *ehci) case Q_TYPE_QH: /* handle any completions */ temp.qh = qh_get (q.qh); - type = Q_NEXT_TYPE(ehci, q.qh->hw->hw_next); + type = Q_NEXT_TYPE(ehci, q.qh->hw_next); q = q.qh->qh_next; modified = qh_completions (ehci, temp.qh); - if (unlikely(list_empty(&temp.qh->qtd_list) || - temp.qh->needs_rescan)) + if (unlikely (list_empty (&temp.qh->qtd_list))) intr_deschedule (ehci, temp.qh); qh_put (temp.qh); break; diff --git a/trunk/drivers/usb/host/ehci-w90x900.c b/trunk/drivers/usb/host/ehci-w90x900.c deleted file mode 100644 index cfa21ea20f82..000000000000 --- a/trunk/drivers/usb/host/ehci-w90x900.c +++ /dev/null @@ -1,181 +0,0 @@ -/* - * linux/driver/usb/host/ehci-w90x900.c - * - * Copyright (c) 2008 Nuvoton technology corporation. - * - * Wan ZongShun - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation;version 2 of the License. - * - */ - -#include - -/*ebable phy0 and phy1 for w90p910*/ -#define ENPHY (0x01<<8) -#define PHY0_CTR (0xA4) -#define PHY1_CTR (0xA8) - -static int __devinit usb_w90x900_probe(const struct hc_driver *driver, - struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct ehci_hcd *ehci; - struct resource *res; - int retval = 0, irq; - unsigned long val; - - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (!res) { - retval = -ENXIO; - goto err1; - } - - hcd = usb_create_hcd(driver, &pdev->dev, "w90x900 EHCI"); - if (!hcd) { - retval = -ENOMEM; - goto err1; - } - - hcd->rsrc_start = res->start; - hcd->rsrc_len = res->end - res->start + 1; - - if (!request_mem_region(hcd->rsrc_start, hcd->rsrc_len, hcd_name)) { - retval = -EBUSY; - goto err2; - } - - hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len); - if (hcd->regs == NULL) { - retval = -EFAULT; - goto err3; - } - - ehci = hcd_to_ehci(hcd); - ehci->caps = hcd->regs; - ehci->regs = hcd->regs + - HC_LENGTH(ehci_readl(ehci, &ehci->caps->hc_capbase)); - - /* enable PHY 0,1,the regs only apply to w90p910 - * 0xA4,0xA8 were offsets of PHY0 and PHY1 controller of - * w90p910 IC relative to ehci->regs. - */ - val = __raw_readl(ehci->regs+PHY0_CTR); - val |= ENPHY; - __raw_writel(val, ehci->regs+PHY0_CTR); - - val = __raw_readl(ehci->regs+PHY1_CTR); - val |= ENPHY; - __raw_writel(val, ehci->regs+PHY1_CTR); - - ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params); - ehci->sbrn = 0x20; - - irq = platform_get_irq(pdev, 0); - if (irq < 0) - goto err4; - - retval = usb_add_hcd(hcd, irq, IRQF_SHARED); - if (retval != 0) - goto err4; - - ehci_writel(ehci, 1, &ehci->regs->configured_flag); - - return retval; -err4: - iounmap(hcd->regs); -err3: - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); -err2: - usb_put_hcd(hcd); -err1: - return retval; -} - -static -void usb_w90x900_remove(struct usb_hcd *hcd, struct platform_device *pdev) -{ - usb_remove_hcd(hcd); - iounmap(hcd->regs); - release_mem_region(hcd->rsrc_start, hcd->rsrc_len); - usb_put_hcd(hcd); -} - -static const struct hc_driver ehci_w90x900_hc_driver = { - .description = hcd_name, - .product_desc = "Nuvoton w90x900 EHCI Host Controller", - .hcd_priv_size = sizeof(struct ehci_hcd), - - /* - * generic hardware linkage - */ - .irq = ehci_irq, - .flags = HCD_USB2|HCD_MEMORY, - - /* - * basic lifecycle operations - */ - .reset = ehci_init, - .start = ehci_run, - - .stop = ehci_stop, - .shutdown = ehci_shutdown, - - /* - * managing i/o requests and associated device resources - */ - .urb_enqueue = ehci_urb_enqueue, - .urb_dequeue = ehci_urb_dequeue, - .endpoint_disable = ehci_endpoint_disable, - - /* - * scheduling support - */ - .get_frame_number = ehci_get_frame, - - /* - * root hub support - */ - .hub_status_data = ehci_hub_status_data, - .hub_control = ehci_hub_control, -#ifdef CONFIG_PM - .bus_suspend = ehci_bus_suspend, - .bus_resume = ehci_bus_resume, -#endif - .relinquish_port = ehci_relinquish_port, - .port_handed_over = ehci_port_handed_over, -}; - -static int __devinit ehci_w90x900_probe(struct platform_device *pdev) -{ - if (usb_disabled()) - return -ENODEV; - - return usb_w90x900_probe(&ehci_w90x900_hc_driver, pdev); -} - -static int __devexit ehci_w90x900_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - - usb_w90x900_remove(hcd, pdev); - - return 0; -} - -static struct platform_driver ehci_hcd_w90x900_driver = { - .probe = ehci_w90x900_probe, - .remove = __devexit_p(ehci_w90x900_remove), - .driver = { - .name = "w90x900-ehci", - .owner = THIS_MODULE, - }, -}; - -MODULE_AUTHOR("Wan ZongShun "); -MODULE_DESCRIPTION("w90p910 usb ehci driver!"); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:w90p910-ehci"); diff --git a/trunk/drivers/usb/host/ehci.h b/trunk/drivers/usb/host/ehci.h index 064e76821ff5..48b9e889a18b 100644 --- a/trunk/drivers/usb/host/ehci.h +++ b/trunk/drivers/usb/host/ehci.h @@ -126,7 +126,6 @@ struct ehci_hcd { /* one per controller */ unsigned big_endian_mmio:1; unsigned big_endian_desc:1; unsigned has_amcc_usb23:1; - unsigned need_io_watchdog:1; /* required for usb32 quirk */ #define OHCI_CTRL_HCFS (3 << 6) @@ -136,7 +135,6 @@ struct ehci_hcd { /* one per controller */ #define OHCI_HCCTRL_OFFSET 0x4 #define OHCI_HCCTRL_LEN 0x4 __hc32 *ohci_hcctrl_reg; - unsigned has_hostpc:1; u8 sbrn; /* packed release number */ @@ -300,8 +298,8 @@ union ehci_shadow { * These appear in both the async and (for interrupt) periodic schedules. */ -/* first part defined by EHCI spec */ -struct ehci_qh_hw { +struct ehci_qh { + /* first part defined by EHCI spec */ __hc32 hw_next; /* see EHCI 3.6.1 */ __hc32 hw_info1; /* see EHCI 3.6.2 */ #define QH_HEAD 0x00008000 @@ -319,10 +317,7 @@ struct ehci_qh_hw { __hc32 hw_token; __hc32 hw_buf [5]; __hc32 hw_buf_hi [5]; -} __attribute__ ((aligned(32))); -struct ehci_qh { - struct ehci_qh_hw *hw; /* the rest is HCD-private */ dma_addr_t qh_dma; /* address of qh */ union ehci_shadow qh_next; /* ptr to qh; or periodic */ @@ -341,7 +336,6 @@ struct ehci_qh { u32 refcount; unsigned stamp; - u8 needs_rescan; /* Dequeue during giveback */ u8 qh_state; #define QH_STATE_LINKED 1 /* HC sees this */ #define QH_STATE_UNLINK 2 /* HC may still see this */ @@ -363,7 +357,7 @@ struct ehci_qh { struct usb_device *dev; /* access to TT */ unsigned clearing_tt:1; /* Clear-TT-Buf in progress */ -}; +} __attribute__ ((aligned (32))); /*-------------------------------------------------------------------------*/ @@ -550,7 +544,7 @@ static inline unsigned int ehci_port_speed(struct ehci_hcd *ehci, unsigned int portsc) { if (ehci_is_TDI(ehci)) { - switch ((portsc >> (ehci->has_hostpc ? 25 : 26)) & 3) { + switch ((portsc>>26)&3) { case 0: return 0; case 1: diff --git a/trunk/drivers/usb/host/isp1362-hcd.c b/trunk/drivers/usb/host/isp1362-hcd.c deleted file mode 100644 index e35d82808bab..000000000000 --- a/trunk/drivers/usb/host/isp1362-hcd.c +++ /dev/null @@ -1,2909 +0,0 @@ -/* - * ISP1362 HCD (Host Controller Driver) for USB. - * - * Copyright (C) 2005 Lothar Wassmann - * - * Derived from the SL811 HCD, rewritten for ISP116x. - * Copyright (C) 2005 Olav Kongas - * - * Portions: - * Copyright (C) 2004 Psion Teklogix (for NetBook PRO) - * Copyright (C) 2004 David Brownell - */ - -/* - * The ISP1362 chip requires a large delay (300ns and 462ns) between - * accesses to the address and data register. - * The following timing options exist: - * - * 1. Configure your memory controller to add such delays if it can (the best) - * 2. Implement platform-specific delay function possibly - * combined with configuring the memory controller; see - * include/linux/usb_isp1362.h for more info. - * 3. Use ndelay (easiest, poorest). - * - * Use the corresponding macros USE_PLATFORM_DELAY and USE_NDELAY in the - * platform specific section of isp1362.h to select the appropriate variant. - * - * Also note that according to the Philips "ISP1362 Errata" document - * Rev 1.00 from 27 May data corruption may occur when the #WR signal - * is reasserted (even with #CS deasserted) within 132ns after a - * write cycle to any controller register. If the hardware doesn't - * implement the recommended fix (gating the #WR with #CS) software - * must ensure that no further write cycle (not necessarily to the chip!) - * is issued by the CPU within this interval. - - * For PXA25x this can be ensured by using VLIO with the maximum - * recovery time (MSCx = 0x7f8c) with a memory clock of 99.53 MHz. - */ - -#ifdef CONFIG_USB_DEBUG -# define ISP1362_DEBUG -#else -# undef ISP1362_DEBUG -#endif - -/* - * The PXA255 UDC apparently doesn't handle GET_STATUS, GET_CONFIG and - * GET_INTERFACE requests correctly when the SETUP and DATA stages of the - * requests are carried out in separate frames. This will delay any SETUP - * packets until the start of the next frame so that this situation is - * unlikely to occur (and makes usbtest happy running with a PXA255 target - * device). - */ -#undef BUGGY_PXA2XX_UDC_USBTEST - -#undef PTD_TRACE -#undef URB_TRACE -#undef VERBOSE -#undef REGISTERS - -/* This enables a memory test on the ISP1362 chip memory to make sure the - * chip access timing is correct. - */ -#undef CHIP_BUFFER_TEST - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -static int dbg_level; -#ifdef ISP1362_DEBUG -module_param(dbg_level, int, 0644); -#else -module_param(dbg_level, int, 0); -#define STUB_DEBUG_FILE -#endif - -#include "../core/hcd.h" -#include "../core/usb.h" -#include "isp1362.h" - - -#define DRIVER_VERSION "2005-04-04" -#define DRIVER_DESC "ISP1362 USB Host Controller Driver" - -MODULE_DESCRIPTION(DRIVER_DESC); -MODULE_LICENSE("GPL"); - -static const char hcd_name[] = "isp1362-hcd"; - -static void isp1362_hc_stop(struct usb_hcd *hcd); -static int isp1362_hc_start(struct usb_hcd *hcd); - -/*-------------------------------------------------------------------------*/ - -/* - * When called from the interrupthandler only isp1362_hcd->irqenb is modified, - * since the interrupt handler will write isp1362_hcd->irqenb to HCuPINT upon - * completion. - * We don't need a 'disable' counterpart, since interrupts will be disabled - * only by the interrupt handler. - */ -static inline void isp1362_enable_int(struct isp1362_hcd *isp1362_hcd, u16 mask) -{ - if ((isp1362_hcd->irqenb | mask) == isp1362_hcd->irqenb) - return; - if (mask & ~isp1362_hcd->irqenb) - isp1362_write_reg16(isp1362_hcd, HCuPINT, mask & ~isp1362_hcd->irqenb); - isp1362_hcd->irqenb |= mask; - if (isp1362_hcd->irq_active) - return; - isp1362_write_reg16(isp1362_hcd, HCuPINTENB, isp1362_hcd->irqenb); -} - -/*-------------------------------------------------------------------------*/ - -static inline struct isp1362_ep_queue *get_ptd_queue(struct isp1362_hcd *isp1362_hcd, - u16 offset) -{ - struct isp1362_ep_queue *epq = NULL; - - if (offset < isp1362_hcd->istl_queue[1].buf_start) - epq = &isp1362_hcd->istl_queue[0]; - else if (offset < isp1362_hcd->intl_queue.buf_start) - epq = &isp1362_hcd->istl_queue[1]; - else if (offset < isp1362_hcd->atl_queue.buf_start) - epq = &isp1362_hcd->intl_queue; - else if (offset < isp1362_hcd->atl_queue.buf_start + - isp1362_hcd->atl_queue.buf_size) - epq = &isp1362_hcd->atl_queue; - - if (epq) - DBG(1, "%s: PTD $%04x is on %s queue\n", __func__, offset, epq->name); - else - pr_warning("%s: invalid PTD $%04x\n", __func__, offset); - - return epq; -} - -static inline int get_ptd_offset(struct isp1362_ep_queue *epq, u8 index) -{ - int offset; - - if (index * epq->blk_size > epq->buf_size) { - pr_warning("%s: Bad %s index %d(%d)\n", __func__, epq->name, index, - epq->buf_size / epq->blk_size); - return -EINVAL; - } - offset = epq->buf_start + index * epq->blk_size; - DBG(3, "%s: %s PTD[%02x] # %04x\n", __func__, epq->name, index, offset); - - return offset; -} - -/*-------------------------------------------------------------------------*/ - -static inline u16 max_transfer_size(struct isp1362_ep_queue *epq, size_t size, - int mps) -{ - u16 xfer_size = min_t(size_t, MAX_XFER_SIZE, size); - - xfer_size = min_t(size_t, xfer_size, epq->buf_avail * epq->blk_size - PTD_HEADER_SIZE); - if (xfer_size < size && xfer_size % mps) - xfer_size -= xfer_size % mps; - - return xfer_size; -} - -static int claim_ptd_buffers(struct isp1362_ep_queue *epq, - struct isp1362_ep *ep, u16 len) -{ - int ptd_offset = -EINVAL; - int index; - int num_ptds = ((len + PTD_HEADER_SIZE - 1) / epq->blk_size) + 1; - int found = -1; - int last = -1; - - BUG_ON(len > epq->buf_size); - - if (!epq->buf_avail) - return -ENOMEM; - - if (ep->num_ptds) - pr_err("%s: %s len %d/%d num_ptds %d buf_map %08lx skip_map %08lx\n", __func__, - epq->name, len, epq->blk_size, num_ptds, epq->buf_map, epq->skip_map); - BUG_ON(ep->num_ptds != 0); - - for (index = 0; index <= epq->buf_count - num_ptds; index++) { - if (test_bit(index, &epq->buf_map)) - continue; - found = index; - for (last = index + 1; last < index + num_ptds; last++) { - if (test_bit(last, &epq->buf_map)) { - found = -1; - break; - } - } - if (found >= 0) - break; - } - if (found < 0) - return -EOVERFLOW; - - DBG(1, "%s: Found %d PTDs[%d] for %d/%d byte\n", __func__, - num_ptds, found, len, (int)(epq->blk_size - PTD_HEADER_SIZE)); - ptd_offset = get_ptd_offset(epq, found); - WARN_ON(ptd_offset < 0); - ep->ptd_offset = ptd_offset; - ep->num_ptds += num_ptds; - epq->buf_avail -= num_ptds; - BUG_ON(epq->buf_avail > epq->buf_count); - ep->ptd_index = found; - for (index = found; index < last; index++) - __set_bit(index, &epq->buf_map); - DBG(1, "%s: Done %s PTD[%d] $%04x, avail %d count %d claimed %d %08lx:%08lx\n", - __func__, epq->name, ep->ptd_index, ep->ptd_offset, - epq->buf_avail, epq->buf_count, num_ptds, epq->buf_map, epq->skip_map); - - return found; -} - -static inline void release_ptd_buffers(struct isp1362_ep_queue *epq, struct isp1362_ep *ep) -{ - int index = ep->ptd_index; - int last = ep->ptd_index + ep->num_ptds; - - if (last > epq->buf_count) - pr_err("%s: ep %p req %d len %d %s PTD[%d] $%04x num_ptds %d buf_count %d buf_avail %d buf_map %08lx skip_map %08lx\n", - __func__, ep, ep->num_req, ep->length, epq->name, ep->ptd_index, - ep->ptd_offset, ep->num_ptds, epq->buf_count, epq->buf_avail, - epq->buf_map, epq->skip_map); - BUG_ON(last > epq->buf_count); - - for (; index < last; index++) { - __clear_bit(index, &epq->buf_map); - __set_bit(index, &epq->skip_map); - } - epq->buf_avail += ep->num_ptds; - epq->ptd_count--; - - BUG_ON(epq->buf_avail > epq->buf_count); - BUG_ON(epq->ptd_count > epq->buf_count); - - DBG(1, "%s: Done %s PTDs $%04x released %d avail %d count %d\n", - __func__, epq->name, - ep->ptd_offset, ep->num_ptds, epq->buf_avail, epq->buf_count); - DBG(1, "%s: buf_map %08lx skip_map %08lx\n", __func__, - epq->buf_map, epq->skip_map); - - ep->num_ptds = 0; - ep->ptd_offset = -EINVAL; - ep->ptd_index = -EINVAL; -} - -/*-------------------------------------------------------------------------*/ - -/* - Set up PTD's. -*/ -static void prepare_ptd(struct isp1362_hcd *isp1362_hcd, struct urb *urb, - struct isp1362_ep *ep, struct isp1362_ep_queue *epq, - u16 fno) -{ - struct ptd *ptd; - int toggle; - int dir; - u16 len; - size_t buf_len = urb->transfer_buffer_length - urb->actual_length; - - DBG(3, "%s: %s ep %p\n", __func__, epq->name, ep); - - ptd = &ep->ptd; - - ep->data = (unsigned char *)urb->transfer_buffer + urb->actual_length; - - switch (ep->nextpid) { - case USB_PID_IN: - toggle = usb_gettoggle(urb->dev, ep->epnum, 0); - dir = PTD_DIR_IN; - if (usb_pipecontrol(urb->pipe)) { - len = min_t(size_t, ep->maxpacket, buf_len); - } else if (usb_pipeisoc(urb->pipe)) { - len = min_t(size_t, urb->iso_frame_desc[fno].length, MAX_XFER_SIZE); - ep->data = urb->transfer_buffer + urb->iso_frame_desc[fno].offset; - } else - len = max_transfer_size(epq, buf_len, ep->maxpacket); - DBG(1, "%s: IN len %d/%d/%d from URB\n", __func__, len, ep->maxpacket, - (int)buf_len); - break; - case USB_PID_OUT: - toggle = usb_gettoggle(urb->dev, ep->epnum, 1); - dir = PTD_DIR_OUT; - if (usb_pipecontrol(urb->pipe)) - len = min_t(size_t, ep->maxpacket, buf_len); - else if (usb_pipeisoc(urb->pipe)) - len = min_t(size_t, urb->iso_frame_desc[0].length, MAX_XFER_SIZE); - else - len = max_transfer_size(epq, buf_len, ep->maxpacket); - if (len == 0) - pr_info("%s: Sending ZERO packet: %d\n", __func__, - urb->transfer_flags & URB_ZERO_PACKET); - DBG(1, "%s: OUT len %d/%d/%d from URB\n", __func__, len, ep->maxpacket, - (int)buf_len); - break; - case USB_PID_SETUP: - toggle = 0; - dir = PTD_DIR_SETUP; - len = sizeof(struct usb_ctrlrequest); - DBG(1, "%s: SETUP len %d\n", __func__, len); - ep->data = urb->setup_packet; - break; - case USB_PID_ACK: - toggle = 1; - len = 0; - dir = (urb->transfer_buffer_length && usb_pipein(urb->pipe)) ? - PTD_DIR_OUT : PTD_DIR_IN; - DBG(1, "%s: ACK len %d\n", __func__, len); - break; - default: - toggle = dir = len = 0; - pr_err("%s@%d: ep->nextpid %02x\n", __func__, __LINE__, ep->nextpid); - BUG_ON(1); - } - - ep->length = len; - if (!len) - ep->data = NULL; - - ptd->count = PTD_CC_MSK | PTD_ACTIVE_MSK | PTD_TOGGLE(toggle); - ptd->mps = PTD_MPS(ep->maxpacket) | PTD_SPD(urb->dev->speed == USB_SPEED_LOW) | - PTD_EP(ep->epnum); - ptd->len = PTD_LEN(len) | PTD_DIR(dir); - ptd->faddr = PTD_FA(usb_pipedevice(urb->pipe)); - - if (usb_pipeint(urb->pipe)) { - ptd->faddr |= PTD_SF_INT(ep->branch); - ptd->faddr |= PTD_PR(ep->interval ? __ffs(ep->interval) : 0); - } - if (usb_pipeisoc(urb->pipe)) - ptd->faddr |= PTD_SF_ISO(fno); - - DBG(1, "%s: Finished\n", __func__); -} - -static void isp1362_write_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep, - struct isp1362_ep_queue *epq) -{ - struct ptd *ptd = &ep->ptd; - int len = PTD_GET_DIR(ptd) == PTD_DIR_IN ? 0 : ep->length; - - _BUG_ON(ep->ptd_offset < 0); - - prefetch(ptd); - isp1362_write_buffer(isp1362_hcd, ptd, ep->ptd_offset, PTD_HEADER_SIZE); - if (len) - isp1362_write_buffer(isp1362_hcd, ep->data, - ep->ptd_offset + PTD_HEADER_SIZE, len); - - dump_ptd(ptd); - dump_ptd_out_data(ptd, ep->data); -} - -static void isp1362_read_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep, - struct isp1362_ep_queue *epq) -{ - struct ptd *ptd = &ep->ptd; - int act_len; - - WARN_ON(list_empty(&ep->active)); - BUG_ON(ep->ptd_offset < 0); - - list_del_init(&ep->active); - DBG(1, "%s: ep %p removed from active list %p\n", __func__, ep, &epq->active); - - prefetchw(ptd); - isp1362_read_buffer(isp1362_hcd, ptd, ep->ptd_offset, PTD_HEADER_SIZE); - dump_ptd(ptd); - act_len = PTD_GET_COUNT(ptd); - if (PTD_GET_DIR(ptd) != PTD_DIR_IN || act_len == 0) - return; - if (act_len > ep->length) - pr_err("%s: ep %p PTD $%04x act_len %d ep->length %d\n", __func__, ep, - ep->ptd_offset, act_len, ep->length); - BUG_ON(act_len > ep->length); - /* Only transfer the amount of data that has actually been overwritten - * in the chip buffer. We don't want any data that doesn't belong to the - * transfer to leak out of the chip to the callers transfer buffer! - */ - prefetchw(ep->data); - isp1362_read_buffer(isp1362_hcd, ep->data, - ep->ptd_offset + PTD_HEADER_SIZE, act_len); - dump_ptd_in_data(ptd, ep->data); -} - -/* - * INT PTDs will stay in the chip until data is available. - * This function will remove a PTD from the chip when the URB is dequeued. - * Must be called with the spinlock held and IRQs disabled - */ -static void remove_ptd(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep) - -{ - int index; - struct isp1362_ep_queue *epq; - - DBG(1, "%s: ep %p PTD[%d] $%04x\n", __func__, ep, ep->ptd_index, ep->ptd_offset); - BUG_ON(ep->ptd_offset < 0); - - epq = get_ptd_queue(isp1362_hcd, ep->ptd_offset); - BUG_ON(!epq); - - /* put ep in remove_list for cleanup */ - WARN_ON(!list_empty(&ep->remove_list)); - list_add_tail(&ep->remove_list, &isp1362_hcd->remove_list); - /* let SOF interrupt handle the cleanup */ - isp1362_enable_int(isp1362_hcd, HCuPINT_SOF); - - index = ep->ptd_index; - if (index < 0) - /* ISO queues don't have SKIP registers */ - return; - - DBG(1, "%s: Disabling PTD[%02x] $%04x %08lx|%08x\n", __func__, - index, ep->ptd_offset, epq->skip_map, 1 << index); - - /* prevent further processing of PTD (will be effective after next SOF) */ - epq->skip_map |= 1 << index; - if (epq == &isp1362_hcd->atl_queue) { - DBG(2, "%s: ATLSKIP = %08x -> %08lx\n", __func__, - isp1362_read_reg32(isp1362_hcd, HCATLSKIP), epq->skip_map); - isp1362_write_reg32(isp1362_hcd, HCATLSKIP, epq->skip_map); - if (~epq->skip_map == 0) - isp1362_clr_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_ATL_ACTIVE); - } else if (epq == &isp1362_hcd->intl_queue) { - DBG(2, "%s: INTLSKIP = %08x -> %08lx\n", __func__, - isp1362_read_reg32(isp1362_hcd, HCINTLSKIP), epq->skip_map); - isp1362_write_reg32(isp1362_hcd, HCINTLSKIP, epq->skip_map); - if (~epq->skip_map == 0) - isp1362_clr_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_INTL_ACTIVE); - } -} - -/* - Take done or failed requests out of schedule. Give back - processed urbs. -*/ -static void finish_request(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep, - struct urb *urb, int status) - __releases(isp1362_hcd->lock) - __acquires(isp1362_hcd->lock) -{ - urb->hcpriv = NULL; - ep->error_count = 0; - - if (usb_pipecontrol(urb->pipe)) - ep->nextpid = USB_PID_SETUP; - - URB_DBG("%s: req %d FA %d ep%d%s %s: len %d/%d %s stat %d\n", __func__, - ep->num_req, usb_pipedevice(urb->pipe), - usb_pipeendpoint(urb->pipe), - !usb_pipein(urb->pipe) ? "out" : "in", - usb_pipecontrol(urb->pipe) ? "ctrl" : - usb_pipeint(urb->pipe) ? "int" : - usb_pipebulk(urb->pipe) ? "bulk" : - "iso", - urb->actual_length, urb->transfer_buffer_length, - !(urb->transfer_flags & URB_SHORT_NOT_OK) ? - "short_ok" : "", urb->status); - - - usb_hcd_unlink_urb_from_ep(isp1362_hcd_to_hcd(isp1362_hcd), urb); - spin_unlock(&isp1362_hcd->lock); - usb_hcd_giveback_urb(isp1362_hcd_to_hcd(isp1362_hcd), urb, status); - spin_lock(&isp1362_hcd->lock); - - /* take idle endpoints out of the schedule right away */ - if (!list_empty(&ep->hep->urb_list)) - return; - - /* async deschedule */ - if (!list_empty(&ep->schedule)) { - list_del_init(&ep->schedule); - return; - } - - - if (ep->interval) { - /* periodic deschedule */ - DBG(1, "deschedule qh%d/%p branch %d load %d bandwidth %d -> %d\n", ep->interval, - ep, ep->branch, ep->load, - isp1362_hcd->load[ep->branch], - isp1362_hcd->load[ep->branch] - ep->load); - isp1362_hcd->load[ep->branch] -= ep->load; - ep->branch = PERIODIC_SIZE; - } -} - -/* - * Analyze transfer results, handle partial transfers and errors -*/ -static void postproc_ep(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep *ep) -{ - struct urb *urb = get_urb(ep); - struct usb_device *udev; - struct ptd *ptd; - int short_ok; - u16 len; - int urbstat = -EINPROGRESS; - u8 cc; - - DBG(2, "%s: ep %p req %d\n", __func__, ep, ep->num_req); - - udev = urb->dev; - ptd = &ep->ptd; - cc = PTD_GET_CC(ptd); - if (cc == PTD_NOTACCESSED) { - pr_err("%s: req %d PTD %p Untouched by ISP1362\n", __func__, - ep->num_req, ptd); - cc = PTD_DEVNOTRESP; - } - - short_ok = !(urb->transfer_flags & URB_SHORT_NOT_OK); - len = urb->transfer_buffer_length - urb->actual_length; - - /* Data underrun is special. For allowed underrun - we clear the error and continue as normal. For - forbidden underrun we finish the DATA stage - immediately while for control transfer, - we do a STATUS stage. - */ - if (cc == PTD_DATAUNDERRUN) { - if (short_ok) { - DBG(1, "%s: req %d Allowed data underrun short_%sok %d/%d/%d byte\n", - __func__, ep->num_req, short_ok ? "" : "not_", - PTD_GET_COUNT(ptd), ep->maxpacket, len); - cc = PTD_CC_NOERROR; - urbstat = 0; - } else { - DBG(1, "%s: req %d Data Underrun %s nextpid %02x short_%sok %d/%d/%d byte\n", - __func__, ep->num_req, - usb_pipein(urb->pipe) ? "IN" : "OUT", ep->nextpid, - short_ok ? "" : "not_", - PTD_GET_COUNT(ptd), ep->maxpacket, len); - if (usb_pipecontrol(urb->pipe)) { - ep->nextpid = USB_PID_ACK; - /* save the data underrun error code for later and - * procede with the status stage - */ - urb->actual_length += PTD_GET_COUNT(ptd); - BUG_ON(urb->actual_length > urb->transfer_buffer_length); - - if (urb->status == -EINPROGRESS) - urb->status = cc_to_error[PTD_DATAUNDERRUN]; - } else { - usb_settoggle(udev, ep->epnum, ep->nextpid == USB_PID_OUT, - PTD_GET_TOGGLE(ptd)); - urbstat = cc_to_error[PTD_DATAUNDERRUN]; - } - goto out; - } - } - - if (cc != PTD_CC_NOERROR) { - if (++ep->error_count >= 3 || cc == PTD_CC_STALL || cc == PTD_DATAOVERRUN) { - urbstat = cc_to_error[cc]; - DBG(1, "%s: req %d nextpid %02x, status %d, error %d, error_count %d\n", - __func__, ep->num_req, ep->nextpid, urbstat, cc, - ep->error_count); - } - goto out; - } - - switch (ep->nextpid) { - case USB_PID_OUT: - if (PTD_GET_COUNT(ptd) != ep->length) - pr_err("%s: count=%d len=%d\n", __func__, - PTD_GET_COUNT(ptd), ep->length); - BUG_ON(PTD_GET_COUNT(ptd) != ep->length); - urb->actual_length += ep->length; - BUG_ON(urb->actual_length > urb->transfer_buffer_length); - usb_settoggle(udev, ep->epnum, 1, PTD_GET_TOGGLE(ptd)); - if (urb->actual_length == urb->transfer_buffer_length) { - DBG(3, "%s: req %d xfer complete %d/%d status %d -> 0\n", __func__, - ep->num_req, len, ep->maxpacket, urbstat); - if (usb_pipecontrol(urb->pipe)) { - DBG(3, "%s: req %d %s Wait for ACK\n", __func__, - ep->num_req, - usb_pipein(urb->pipe) ? "IN" : "OUT"); - ep->nextpid = USB_PID_ACK; - } else { - if (len % ep->maxpacket || - !(urb->transfer_flags & URB_ZERO_PACKET)) { - urbstat = 0; - DBG(3, "%s: req %d URB %s status %d count %d/%d/%d\n", - __func__, ep->num_req, usb_pipein(urb->pipe) ? "IN" : "OUT", - urbstat, len, ep->maxpacket, urb->actual_length); - } - } - } - break; - case USB_PID_IN: - len = PTD_GET_COUNT(ptd); - BUG_ON(len > ep->length); - urb->actual_length += len; - BUG_ON(urb->actual_length > urb->transfer_buffer_length); - usb_settoggle(udev, ep->epnum, 0, PTD_GET_TOGGLE(ptd)); - /* if transfer completed or (allowed) data underrun */ - if ((urb->transfer_buffer_length == urb->actual_length) || - len % ep->maxpacket) { - DBG(3, "%s: req %d xfer complete %d/%d status %d -> 0\n", __func__, - ep->num_req, len, ep->maxpacket, urbstat); - if (usb_pipecontrol(urb->pipe)) { - DBG(3, "%s: req %d %s Wait for ACK\n", __func__, - ep->num_req, - usb_pipein(urb->pipe) ? "IN" : "OUT"); - ep->nextpid = USB_PID_ACK; - } else { - urbstat = 0; - DBG(3, "%s: req %d URB %s status %d count %d/%d/%d\n", - __func__, ep->num_req, usb_pipein(urb->pipe) ? "IN" : "OUT", - urbstat, len, ep->maxpacket, urb->actual_length); - } - } - break; - case USB_PID_SETUP: - if (urb->transfer_buffer_length == urb->actual_length) { - ep->nextpid = USB_PID_ACK; - } else if (usb_pipeout(urb->pipe)) { - usb_settoggle(udev, 0, 1, 1); - ep->nextpid = USB_PID_OUT; - } else { - usb_settoggle(udev, 0, 0, 1); - ep->nextpid = USB_PID_IN; - } - break; - case USB_PID_ACK: - DBG(3, "%s: req %d got ACK %d -> 0\n", __func__, ep->num_req, - urbstat); - WARN_ON(urbstat != -EINPROGRESS); - urbstat = 0; - ep->nextpid = 0; - break; - default: - BUG_ON(1); - } - - out: - if (urbstat != -EINPROGRESS) { - DBG(2, "%s: Finishing ep %p req %d urb %p status %d\n", __func__, - ep, ep->num_req, urb, urbstat); - finish_request(isp1362_hcd, ep, urb, urbstat); - } -} - -static void finish_unlinks(struct isp1362_hcd *isp1362_hcd) -{ - struct isp1362_ep *ep; - struct isp1362_ep *tmp; - - list_for_each_entry_safe(ep, tmp, &isp1362_hcd->remove_list, remove_list) { - struct isp1362_ep_queue *epq = - get_ptd_queue(isp1362_hcd, ep->ptd_offset); - int index = ep->ptd_index; - - BUG_ON(epq == NULL); - if (index >= 0) { - DBG(1, "%s: remove PTD[%d] $%04x\n", __func__, index, ep->ptd_offset); - BUG_ON(ep->num_ptds == 0); - release_ptd_buffers(epq, ep); - } - if (!list_empty(&ep->hep->urb_list)) { - struct urb *urb = get_urb(ep); - - DBG(1, "%s: Finishing req %d ep %p from remove_list\n", __func__, - ep->num_req, ep); - finish_request(isp1362_hcd, ep, urb, -ESHUTDOWN); - } - WARN_ON(list_empty(&ep->active)); - if (!list_empty(&ep->active)) { - list_del_init(&ep->active); - DBG(1, "%s: ep %p removed from active list\n", __func__, ep); - } - list_del_init(&ep->remove_list); - DBG(1, "%s: ep %p removed from remove_list\n", __func__, ep); - } - DBG(1, "%s: Done\n", __func__); -} - -static inline void enable_atl_transfers(struct isp1362_hcd *isp1362_hcd, int count) -{ - if (count > 0) { - if (count < isp1362_hcd->atl_queue.ptd_count) - isp1362_write_reg16(isp1362_hcd, HCATLDTC, count); - isp1362_enable_int(isp1362_hcd, HCuPINT_ATL); - isp1362_write_reg32(isp1362_hcd, HCATLSKIP, isp1362_hcd->atl_queue.skip_map); - isp1362_set_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_ATL_ACTIVE); - } else - isp1362_enable_int(isp1362_hcd, HCuPINT_SOF); -} - -static inline void enable_intl_transfers(struct isp1362_hcd *isp1362_hcd) -{ - isp1362_enable_int(isp1362_hcd, HCuPINT_INTL); - isp1362_set_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_INTL_ACTIVE); - isp1362_write_reg32(isp1362_hcd, HCINTLSKIP, isp1362_hcd->intl_queue.skip_map); -} - -static inline void enable_istl_transfers(struct isp1362_hcd *isp1362_hcd, int flip) -{ - isp1362_enable_int(isp1362_hcd, flip ? HCuPINT_ISTL1 : HCuPINT_ISTL0); - isp1362_set_mask16(isp1362_hcd, HCBUFSTAT, flip ? - HCBUFSTAT_ISTL1_FULL : HCBUFSTAT_ISTL0_FULL); -} - -static int submit_req(struct isp1362_hcd *isp1362_hcd, struct urb *urb, - struct isp1362_ep *ep, struct isp1362_ep_queue *epq) -{ - int index = epq->free_ptd; - - prepare_ptd(isp1362_hcd, urb, ep, epq, 0); - index = claim_ptd_buffers(epq, ep, ep->length); - if (index == -ENOMEM) { - DBG(1, "%s: req %d No free %s PTD available: %d, %08lx:%08lx\n", __func__, - ep->num_req, epq->name, ep->num_ptds, epq->buf_map, epq->skip_map); - return index; - } else if (index == -EOVERFLOW) { - DBG(1, "%s: req %d Not enough space for %d byte %s PTD %d %08lx:%08lx\n", - __func__, ep->num_req, ep->length, epq->name, ep->num_ptds, - epq->buf_map, epq->skip_map); - return index; - } else - BUG_ON(index < 0); - list_add_tail(&ep->active, &epq->active); - DBG(1, "%s: ep %p req %d len %d added to active list %p\n", __func__, - ep, ep->num_req, ep->length, &epq->active); - DBG(1, "%s: Submitting %s PTD $%04x for ep %p req %d\n", __func__, epq->name, - ep->ptd_offset, ep, ep->num_req); - isp1362_write_ptd(isp1362_hcd, ep, epq); - __clear_bit(ep->ptd_index, &epq->skip_map); - - return 0; -} - -static void start_atl_transfers(struct isp1362_hcd *isp1362_hcd) -{ - int ptd_count = 0; - struct isp1362_ep_queue *epq = &isp1362_hcd->atl_queue; - struct isp1362_ep *ep; - int defer = 0; - - if (atomic_read(&epq->finishing)) { - DBG(1, "%s: finish_transfers is active for %s\n", __func__, epq->name); - return; - } - - list_for_each_entry(ep, &isp1362_hcd->async, schedule) { - struct urb *urb = get_urb(ep); - int ret; - - if (!list_empty(&ep->active)) { - DBG(2, "%s: Skipping active %s ep %p\n", __func__, epq->name, ep); - continue; - } - - DBG(1, "%s: Processing %s ep %p req %d\n", __func__, epq->name, - ep, ep->num_req); - - ret = submit_req(isp1362_hcd, urb, ep, epq); - if (ret == -ENOMEM) { - defer = 1; - break; - } else if (ret == -EOVERFLOW) { - defer = 1; - continue; - } -#ifdef BUGGY_PXA2XX_UDC_USBTEST - defer = ep->nextpid == USB_PID_SETUP; -#endif - ptd_count++; - } - - /* Avoid starving of endpoints */ - if (isp1362_hcd->async.next != isp1362_hcd->async.prev) { - DBG(2, "%s: Cycling ASYNC schedule %d\n", __func__, ptd_count); - list_move(&isp1362_hcd->async, isp1362_hcd->async.next); - } - if (ptd_count || defer) - enable_atl_transfers(isp1362_hcd, defer ? 0 : ptd_count); - - epq->ptd_count += ptd_count; - if (epq->ptd_count > epq->stat_maxptds) { - epq->stat_maxptds = epq->ptd_count; - DBG(0, "%s: max_ptds: %d\n", __func__, epq->stat_maxptds); - } -} - -static void start_intl_transfers(struct isp1362_hcd *isp1362_hcd) -{ - int ptd_count = 0; - struct isp1362_ep_queue *epq = &isp1362_hcd->intl_queue; - struct isp1362_ep *ep; - - if (atomic_read(&epq->finishing)) { - DBG(1, "%s: finish_transfers is active for %s\n", __func__, epq->name); - return; - } - - list_for_each_entry(ep, &isp1362_hcd->periodic, schedule) { - struct urb *urb = get_urb(ep); - int ret; - - if (!list_empty(&ep->active)) { - DBG(1, "%s: Skipping active %s ep %p\n", __func__, - epq->name, ep); - continue; - } - - DBG(1, "%s: Processing %s ep %p req %d\n", __func__, - epq->name, ep, ep->num_req); - ret = submit_req(isp1362_hcd, urb, ep, epq); - if (ret == -ENOMEM) - break; - else if (ret == -EOVERFLOW) - continue; - ptd_count++; - } - - if (ptd_count) { - static int last_count; - - if (ptd_count != last_count) { - DBG(0, "%s: ptd_count: %d\n", __func__, ptd_count); - last_count = ptd_count; - } - enable_intl_transfers(isp1362_hcd); - } - - epq->ptd_count += ptd_count; - if (epq->ptd_count > epq->stat_maxptds) - epq->stat_maxptds = epq->ptd_count; -} - -static inline int next_ptd(struct isp1362_ep_queue *epq, struct isp1362_ep *ep) -{ - u16 ptd_offset = ep->ptd_offset; - int num_ptds = (ep->length + PTD_HEADER_SIZE + (epq->blk_size - 1)) / epq->blk_size; - - DBG(2, "%s: PTD offset $%04x + %04x => %d * %04x -> $%04x\n", __func__, ptd_offset, - ep->length, num_ptds, epq->blk_size, ptd_offset + num_ptds * epq->blk_size); - - ptd_offset += num_ptds * epq->blk_size; - if (ptd_offset < epq->buf_start + epq->buf_size) - return ptd_offset; - else - return -ENOMEM; -} - -static void start_iso_transfers(struct isp1362_hcd *isp1362_hcd) -{ - int ptd_count = 0; - int flip = isp1362_hcd->istl_flip; - struct isp1362_ep_queue *epq; - int ptd_offset; - struct isp1362_ep *ep; - struct isp1362_ep *tmp; - u16 fno = isp1362_read_reg32(isp1362_hcd, HCFMNUM); - - fill2: - epq = &isp1362_hcd->istl_queue[flip]; - if (atomic_read(&epq->finishing)) { - DBG(1, "%s: finish_transfers is active for %s\n", __func__, epq->name); - return; - } - - if (!list_empty(&epq->active)) - return; - - ptd_offset = epq->buf_start; - list_for_each_entry_safe(ep, tmp, &isp1362_hcd->isoc, schedule) { - struct urb *urb = get_urb(ep); - s16 diff = fno - (u16)urb->start_frame; - - DBG(1, "%s: Processing %s ep %p\n", __func__, epq->name, ep); - - if (diff > urb->number_of_packets) { - /* time frame for this URB has elapsed */ - finish_request(isp1362_hcd, ep, urb, -EOVERFLOW); - continue; - } else if (diff < -1) { - /* URB is not due in this frame or the next one. - * Comparing with '-1' instead of '0' accounts for double - * buffering in the ISP1362 which enables us to queue the PTD - * one frame ahead of time - */ - } else if (diff == -1) { - /* submit PTD's that are due in the next frame */ - prepare_ptd(isp1362_hcd, urb, ep, epq, fno); - if (ptd_offset + PTD_HEADER_SIZE + ep->length > - epq->buf_start + epq->buf_size) { - pr_err("%s: Not enough ISO buffer space for %d byte PTD\n", - __func__, ep->length); - continue; - } - ep->ptd_offset = ptd_offset; - list_add_tail(&ep->active, &epq->active); - - ptd_offset = next_ptd(epq, ep); - if (ptd_offset < 0) { - pr_warning("%s: req %d No more %s PTD buffers available\n", __func__, - ep->num_req, epq->name); - break; - } - } - } - list_for_each_entry(ep, &epq->active, active) { - if (epq->active.next == &ep->active) - ep->ptd.mps |= PTD_LAST_MSK; - isp1362_write_ptd(isp1362_hcd, ep, epq); - ptd_count++; - } - - if (ptd_count) - enable_istl_transfers(isp1362_hcd, flip); - - epq->ptd_count += ptd_count; - if (epq->ptd_count > epq->stat_maxptds) - epq->stat_maxptds = epq->ptd_count; - - /* check, whether the second ISTL buffer may also be filled */ - if (!(isp1362_read_reg16(isp1362_hcd, HCBUFSTAT) & - (flip ? HCBUFSTAT_ISTL0_FULL : HCBUFSTAT_ISTL1_FULL))) { - fno++; - ptd_count = 0; - flip = 1 - flip; - goto fill2; - } -} - -static void finish_transfers(struct isp1362_hcd *isp1362_hcd, unsigned long done_map, - struct isp1362_ep_queue *epq) -{ - struct isp1362_ep *ep; - struct isp1362_ep *tmp; - - if (list_empty(&epq->active)) { - DBG(1, "%s: Nothing to do for %s queue\n", __func__, epq->name); - return; - } - - DBG(1, "%s: Finishing %s transfers %08lx\n", __func__, epq->name, done_map); - - atomic_inc(&epq->finishing); - list_for_each_entry_safe(ep, tmp, &epq->active, active) { - int index = ep->ptd_index; - - DBG(1, "%s: Checking %s PTD[%02x] $%04x\n", __func__, epq->name, - index, ep->ptd_offset); - - BUG_ON(index < 0); - if (__test_and_clear_bit(index, &done_map)) { - isp1362_read_ptd(isp1362_hcd, ep, epq); - epq->free_ptd = index; - BUG_ON(ep->num_ptds == 0); - release_ptd_buffers(epq, ep); - - DBG(1, "%s: ep %p req %d removed from active list\n", __func__, - ep, ep->num_req); - if (!list_empty(&ep->remove_list)) { - list_del_init(&ep->remove_list); - DBG(1, "%s: ep %p removed from remove list\n", __func__, ep); - } - DBG(1, "%s: Postprocessing %s ep %p req %d\n", __func__, epq->name, - ep, ep->num_req); - postproc_ep(isp1362_hcd, ep); - } - if (!done_map) - break; - } - if (done_map) - pr_warning("%s: done_map not clear: %08lx:%08lx\n", __func__, done_map, - epq->skip_map); - atomic_dec(&epq->finishing); -} - -static void finish_iso_transfers(struct isp1362_hcd *isp1362_hcd, struct isp1362_ep_queue *epq) -{ - struct isp1362_ep *ep; - struct isp1362_ep *tmp; - - if (list_empty(&epq->active)) { - DBG(1, "%s: Nothing to do for %s queue\n", __func__, epq->name); - return; - } - - DBG(1, "%s: Finishing %s transfers\n", __func__, epq->name); - - atomic_inc(&epq->finishing); - list_for_each_entry_safe(ep, tmp, &epq->active, active) { - DBG(1, "%s: Checking PTD $%04x\n", __func__, ep->ptd_offset); - - isp1362_read_ptd(isp1362_hcd, ep, epq); - DBG(1, "%s: Postprocessing %s ep %p\n", __func__, epq->name, ep); - postproc_ep(isp1362_hcd, ep); - } - WARN_ON(epq->blk_size != 0); - atomic_dec(&epq->finishing); -} - -static irqreturn_t isp1362_irq(struct usb_hcd *hcd) -{ - int handled = 0; - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - u16 irqstat; - u16 svc_mask; - - spin_lock(&isp1362_hcd->lock); - - BUG_ON(isp1362_hcd->irq_active++); - - isp1362_write_reg16(isp1362_hcd, HCuPINTENB, 0); - - irqstat = isp1362_read_reg16(isp1362_hcd, HCuPINT); - DBG(3, "%s: got IRQ %04x:%04x\n", __func__, irqstat, isp1362_hcd->irqenb); - - /* only handle interrupts that are currently enabled */ - irqstat &= isp1362_hcd->irqenb; - isp1362_write_reg16(isp1362_hcd, HCuPINT, irqstat); - svc_mask = irqstat; - - if (irqstat & HCuPINT_SOF) { - isp1362_hcd->irqenb &= ~HCuPINT_SOF; - isp1362_hcd->irq_stat[ISP1362_INT_SOF]++; - handled = 1; - svc_mask &= ~HCuPINT_SOF; - DBG(3, "%s: SOF\n", __func__); - isp1362_hcd->fmindex = isp1362_read_reg32(isp1362_hcd, HCFMNUM); - if (!list_empty(&isp1362_hcd->remove_list)) - finish_unlinks(isp1362_hcd); - if (!list_empty(&isp1362_hcd->async) && !(irqstat & HCuPINT_ATL)) { - if (list_empty(&isp1362_hcd->atl_queue.active)) { - start_atl_transfers(isp1362_hcd); - } else { - isp1362_enable_int(isp1362_hcd, HCuPINT_ATL); - isp1362_write_reg32(isp1362_hcd, HCATLSKIP, - isp1362_hcd->atl_queue.skip_map); - isp1362_set_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_ATL_ACTIVE); - } - } - } - - if (irqstat & HCuPINT_ISTL0) { - isp1362_hcd->irq_stat[ISP1362_INT_ISTL0]++; - handled = 1; - svc_mask &= ~HCuPINT_ISTL0; - isp1362_clr_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_ISTL0_FULL); - DBG(1, "%s: ISTL0\n", __func__); - WARN_ON((int)!!isp1362_hcd->istl_flip); - WARN_ON(isp1362_read_reg16(isp1362_hcd, HCBUFSTAT) & - HCBUFSTAT_ISTL0_ACTIVE); - WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCBUFSTAT) & - HCBUFSTAT_ISTL0_DONE)); - isp1362_hcd->irqenb &= ~HCuPINT_ISTL0; - } - - if (irqstat & HCuPINT_ISTL1) { - isp1362_hcd->irq_stat[ISP1362_INT_ISTL1]++; - handled = 1; - svc_mask &= ~HCuPINT_ISTL1; - isp1362_clr_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_ISTL1_FULL); - DBG(1, "%s: ISTL1\n", __func__); - WARN_ON(!(int)isp1362_hcd->istl_flip); - WARN_ON(isp1362_read_reg16(isp1362_hcd, HCBUFSTAT) & - HCBUFSTAT_ISTL1_ACTIVE); - WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCBUFSTAT) & - HCBUFSTAT_ISTL1_DONE)); - isp1362_hcd->irqenb &= ~HCuPINT_ISTL1; - } - - if (irqstat & (HCuPINT_ISTL0 | HCuPINT_ISTL1)) { - WARN_ON((irqstat & (HCuPINT_ISTL0 | HCuPINT_ISTL1)) == - (HCuPINT_ISTL0 | HCuPINT_ISTL1)); - finish_iso_transfers(isp1362_hcd, - &isp1362_hcd->istl_queue[isp1362_hcd->istl_flip]); - start_iso_transfers(isp1362_hcd); - isp1362_hcd->istl_flip = 1 - isp1362_hcd->istl_flip; - } - - if (irqstat & HCuPINT_INTL) { - u32 done_map = isp1362_read_reg32(isp1362_hcd, HCINTLDONE); - u32 skip_map = isp1362_read_reg32(isp1362_hcd, HCINTLSKIP); - isp1362_hcd->irq_stat[ISP1362_INT_INTL]++; - - DBG(2, "%s: INTL\n", __func__); - - svc_mask &= ~HCuPINT_INTL; - - isp1362_write_reg32(isp1362_hcd, HCINTLSKIP, skip_map | done_map); - if (~(done_map | skip_map) == 0) - /* All PTDs are finished, disable INTL processing entirely */ - isp1362_clr_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_INTL_ACTIVE); - - handled = 1; - WARN_ON(!done_map); - if (done_map) { - DBG(3, "%s: INTL done_map %08x\n", __func__, done_map); - finish_transfers(isp1362_hcd, done_map, &isp1362_hcd->intl_queue); - start_intl_transfers(isp1362_hcd); - } - } - - if (irqstat & HCuPINT_ATL) { - u32 done_map = isp1362_read_reg32(isp1362_hcd, HCATLDONE); - u32 skip_map = isp1362_read_reg32(isp1362_hcd, HCATLSKIP); - isp1362_hcd->irq_stat[ISP1362_INT_ATL]++; - - DBG(2, "%s: ATL\n", __func__); - - svc_mask &= ~HCuPINT_ATL; - - isp1362_write_reg32(isp1362_hcd, HCATLSKIP, skip_map | done_map); - if (~(done_map | skip_map) == 0) - isp1362_clr_mask16(isp1362_hcd, HCBUFSTAT, HCBUFSTAT_ATL_ACTIVE); - if (done_map) { - DBG(3, "%s: ATL done_map %08x\n", __func__, done_map); - finish_transfers(isp1362_hcd, done_map, &isp1362_hcd->atl_queue); - start_atl_transfers(isp1362_hcd); - } - handled = 1; - } - - if (irqstat & HCuPINT_OPR) { - u32 intstat = isp1362_read_reg32(isp1362_hcd, HCINTSTAT); - isp1362_hcd->irq_stat[ISP1362_INT_OPR]++; - - svc_mask &= ~HCuPINT_OPR; - DBG(2, "%s: OPR %08x:%08x\n", __func__, intstat, isp1362_hcd->intenb); - intstat &= isp1362_hcd->intenb; - if (intstat & OHCI_INTR_UE) { - pr_err("Unrecoverable error\n"); - /* FIXME: do here reset or cleanup or whatever */ - } - if (intstat & OHCI_INTR_RHSC) { - isp1362_hcd->rhstatus = isp1362_read_reg32(isp1362_hcd, HCRHSTATUS); - isp1362_hcd->rhport[0] = isp1362_read_reg32(isp1362_hcd, HCRHPORT1); - isp1362_hcd->rhport[1] = isp1362_read_reg32(isp1362_hcd, HCRHPORT2); - } - if (intstat & OHCI_INTR_RD) { - pr_info("%s: RESUME DETECTED\n", __func__); - isp1362_show_reg(isp1362_hcd, HCCONTROL); - usb_hcd_resume_root_hub(hcd); - } - isp1362_write_reg32(isp1362_hcd, HCINTSTAT, intstat); - irqstat &= ~HCuPINT_OPR; - handled = 1; - } - - if (irqstat & HCuPINT_SUSP) { - isp1362_hcd->irq_stat[ISP1362_INT_SUSP]++; - handled = 1; - svc_mask &= ~HCuPINT_SUSP; - - pr_info("%s: SUSPEND IRQ\n", __func__); - } - - if (irqstat & HCuPINT_CLKRDY) { - isp1362_hcd->irq_stat[ISP1362_INT_CLKRDY]++; - handled = 1; - isp1362_hcd->irqenb &= ~HCuPINT_CLKRDY; - svc_mask &= ~HCuPINT_CLKRDY; - pr_info("%s: CLKRDY IRQ\n", __func__); - } - - if (svc_mask) - pr_err("%s: Unserviced interrupt(s) %04x\n", __func__, svc_mask); - - isp1362_write_reg16(isp1362_hcd, HCuPINTENB, isp1362_hcd->irqenb); - isp1362_hcd->irq_active--; - spin_unlock(&isp1362_hcd->lock); - - return IRQ_RETVAL(handled); -} - -/*-------------------------------------------------------------------------*/ - -#define MAX_PERIODIC_LOAD 900 /* out of 1000 usec */ -static int balance(struct isp1362_hcd *isp1362_hcd, u16 interval, u16 load) -{ - int i, branch = -ENOSPC; - - /* search for the least loaded schedule branch of that interval - * which has enough bandwidth left unreserved. - */ - for (i = 0; i < interval; i++) { - if (branch < 0 || isp1362_hcd->load[branch] > isp1362_hcd->load[i]) { - int j; - - for (j = i; j < PERIODIC_SIZE; j += interval) { - if ((isp1362_hcd->load[j] + load) > MAX_PERIODIC_LOAD) { - pr_err("%s: new load %d load[%02x] %d max %d\n", __func__, - load, j, isp1362_hcd->load[j], MAX_PERIODIC_LOAD); - break; - } - } - if (j < PERIODIC_SIZE) - continue; - branch = i; - } - } - return branch; -} - -/* NB! ALL the code above this point runs with isp1362_hcd->lock - held, irqs off -*/ - -/*-------------------------------------------------------------------------*/ - -static int isp1362_urb_enqueue(struct usb_hcd *hcd, - struct urb *urb, - gfp_t mem_flags) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - struct usb_device *udev = urb->dev; - unsigned int pipe = urb->pipe; - int is_out = !usb_pipein(pipe); - int type = usb_pipetype(pipe); - int epnum = usb_pipeendpoint(pipe); - struct usb_host_endpoint *hep = urb->ep; - struct isp1362_ep *ep = NULL; - unsigned long flags; - int retval = 0; - - DBG(3, "%s: urb %p\n", __func__, urb); - - if (type == PIPE_ISOCHRONOUS) { - pr_err("Isochronous transfers not supported\n"); - return -ENOSPC; - } - - URB_DBG("%s: FA %d ep%d%s %s: len %d %s%s\n", __func__, - usb_pipedevice(pipe), epnum, - is_out ? "out" : "in", - usb_pipecontrol(pipe) ? "ctrl" : - usb_pipeint(pipe) ? "int" : - usb_pipebulk(pipe) ? "bulk" : - "iso", - urb->transfer_buffer_length, - (urb->transfer_flags & URB_ZERO_PACKET) ? "ZERO_PACKET " : "", - !(urb->transfer_flags & URB_SHORT_NOT_OK) ? - "short_ok" : ""); - - /* avoid all allocations within spinlocks: request or endpoint */ - if (!hep->hcpriv) { - ep = kcalloc(1, sizeof *ep, mem_flags); - if (!ep) - return -ENOMEM; - } - spin_lock_irqsave(&isp1362_hcd->lock, flags); - - /* don't submit to a dead or disabled port */ - if (!((isp1362_hcd->rhport[0] | isp1362_hcd->rhport[1]) & - (1 << USB_PORT_FEAT_ENABLE)) || - !HC_IS_RUNNING(hcd->state)) { - kfree(ep); - retval = -ENODEV; - goto fail_not_linked; - } - - retval = usb_hcd_link_urb_to_ep(hcd, urb); - if (retval) { - kfree(ep); - goto fail_not_linked; - } - - if (hep->hcpriv) { - ep = hep->hcpriv; - } else { - INIT_LIST_HEAD(&ep->schedule); - INIT_LIST_HEAD(&ep->active); - INIT_LIST_HEAD(&ep->remove_list); - ep->udev = usb_get_dev(udev); - ep->hep = hep; - ep->epnum = epnum; - ep->maxpacket = usb_maxpacket(udev, urb->pipe, is_out); - ep->ptd_offset = -EINVAL; - ep->ptd_index = -EINVAL; - usb_settoggle(udev, epnum, is_out, 0); - - if (type == PIPE_CONTROL) - ep->nextpid = USB_PID_SETUP; - else if (is_out) - ep->nextpid = USB_PID_OUT; - else - ep->nextpid = USB_PID_IN; - - switch (type) { - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - if (urb->interval > PERIODIC_SIZE) - urb->interval = PERIODIC_SIZE; - ep->interval = urb->interval; - ep->branch = PERIODIC_SIZE; - ep->load = usb_calc_bus_time(udev->speed, !is_out, - (type == PIPE_ISOCHRONOUS), - usb_maxpacket(udev, pipe, is_out)) / 1000; - break; - } - hep->hcpriv = ep; - } - ep->num_req = isp1362_hcd->req_serial++; - - /* maybe put endpoint into schedule */ - switch (type) { - case PIPE_CONTROL: - case PIPE_BULK: - if (list_empty(&ep->schedule)) { - DBG(1, "%s: Adding ep %p req %d to async schedule\n", - __func__, ep, ep->num_req); - list_add_tail(&ep->schedule, &isp1362_hcd->async); - } - break; - case PIPE_ISOCHRONOUS: - case PIPE_INTERRUPT: - urb->interval = ep->interval; - - /* urb submitted for already existing EP */ - if (ep->branch < PERIODIC_SIZE) - break; - - retval = balance(isp1362_hcd, ep->interval, ep->load); - if (retval < 0) { - pr_err("%s: balance returned %d\n", __func__, retval); - goto fail; - } - ep->branch = retval; - retval = 0; - isp1362_hcd->fmindex = isp1362_read_reg32(isp1362_hcd, HCFMNUM); - DBG(1, "%s: Current frame %04x branch %02x start_frame %04x(%04x)\n", - __func__, isp1362_hcd->fmindex, ep->branch, - ((isp1362_hcd->fmindex + PERIODIC_SIZE - 1) & - ~(PERIODIC_SIZE - 1)) + ep->branch, - (isp1362_hcd->fmindex & (PERIODIC_SIZE - 1)) + ep->branch); - - if (list_empty(&ep->schedule)) { - if (type == PIPE_ISOCHRONOUS) { - u16 frame = isp1362_hcd->fmindex; - - frame += max_t(u16, 8, ep->interval); - frame &= ~(ep->interval - 1); - frame |= ep->branch; - if (frame_before(frame, isp1362_hcd->fmindex)) - frame += ep->interval; - urb->start_frame = frame; - - DBG(1, "%s: Adding ep %p to isoc schedule\n", __func__, ep); - list_add_tail(&ep->schedule, &isp1362_hcd->isoc); - } else { - DBG(1, "%s: Adding ep %p to periodic schedule\n", __func__, ep); - list_add_tail(&ep->schedule, &isp1362_hcd->periodic); - } - } else - DBG(1, "%s: ep %p already scheduled\n", __func__, ep); - - DBG(2, "%s: load %d bandwidth %d -> %d\n", __func__, - ep->load / ep->interval, isp1362_hcd->load[ep->branch], - isp1362_hcd->load[ep->branch] + ep->load); - isp1362_hcd->load[ep->branch] += ep->load; - } - - urb->hcpriv = hep; - ALIGNSTAT(isp1362_hcd, urb->transfer_buffer); - - switch (type) { - case PIPE_CONTROL: - case PIPE_BULK: - start_atl_transfers(isp1362_hcd); - break; - case PIPE_INTERRUPT: - start_intl_transfers(isp1362_hcd); - break; - case PIPE_ISOCHRONOUS: - start_iso_transfers(isp1362_hcd); - break; - default: - BUG(); - } - fail: - if (retval) - usb_hcd_unlink_urb_from_ep(hcd, urb); - - - fail_not_linked: - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - if (retval) - DBG(0, "%s: urb %p failed with %d\n", __func__, urb, retval); - return retval; -} - -static int isp1362_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - struct usb_host_endpoint *hep; - unsigned long flags; - struct isp1362_ep *ep; - int retval = 0; - - DBG(3, "%s: urb %p\n", __func__, urb); - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - retval = usb_hcd_check_unlink_urb(hcd, urb, status); - if (retval) - goto done; - - hep = urb->hcpriv; - - if (!hep) { - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - return -EIDRM; - } - - ep = hep->hcpriv; - if (ep) { - /* In front of queue? */ - if (ep->hep->urb_list.next == &urb->urb_list) { - if (!list_empty(&ep->active)) { - DBG(1, "%s: urb %p ep %p req %d active PTD[%d] $%04x\n", __func__, - urb, ep, ep->num_req, ep->ptd_index, ep->ptd_offset); - /* disable processing and queue PTD for removal */ - remove_ptd(isp1362_hcd, ep); - urb = NULL; - } - } - if (urb) { - DBG(1, "%s: Finishing ep %p req %d\n", __func__, ep, - ep->num_req); - finish_request(isp1362_hcd, ep, urb, status); - } else - DBG(1, "%s: urb %p active; wait4irq\n", __func__, urb); - } else { - pr_warning("%s: No EP in URB %p\n", __func__, urb); - retval = -EINVAL; - } -done: - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - DBG(3, "%s: exit\n", __func__); - - return retval; -} - -static void isp1362_endpoint_disable(struct usb_hcd *hcd, struct usb_host_endpoint *hep) -{ - struct isp1362_ep *ep = hep->hcpriv; - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - unsigned long flags; - - DBG(1, "%s: ep %p\n", __func__, ep); - if (!ep) - return; - spin_lock_irqsave(&isp1362_hcd->lock, flags); - if (!list_empty(&hep->urb_list)) { - if (!list_empty(&ep->active) && list_empty(&ep->remove_list)) { - DBG(1, "%s: Removing ep %p req %d PTD[%d] $%04x\n", __func__, - ep, ep->num_req, ep->ptd_index, ep->ptd_offset); - remove_ptd(isp1362_hcd, ep); - pr_info("%s: Waiting for Interrupt to clean up\n", __func__); - } - } - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - /* Wait for interrupt to clear out active list */ - while (!list_empty(&ep->active)) - msleep(1); - - DBG(1, "%s: Freeing EP %p\n", __func__, ep); - - usb_put_dev(ep->udev); - kfree(ep); - hep->hcpriv = NULL; -} - -static int isp1362_get_frame(struct usb_hcd *hcd) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - u32 fmnum; - unsigned long flags; - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - fmnum = isp1362_read_reg32(isp1362_hcd, HCFMNUM); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - return (int)fmnum; -} - -/*-------------------------------------------------------------------------*/ - -/* Adapted from ohci-hub.c */ -static int isp1362_hub_status_data(struct usb_hcd *hcd, char *buf) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - int ports, i, changed = 0; - unsigned long flags; - - if (!HC_IS_RUNNING(hcd->state)) - return -ESHUTDOWN; - - /* Report no status change now, if we are scheduled to be - called later */ - if (timer_pending(&hcd->rh_timer)) - return 0; - - ports = isp1362_hcd->rhdesca & RH_A_NDP; - BUG_ON(ports > 2); - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - /* init status */ - if (isp1362_hcd->rhstatus & (RH_HS_LPSC | RH_HS_OCIC)) - buf[0] = changed = 1; - else - buf[0] = 0; - - for (i = 0; i < ports; i++) { - u32 status = isp1362_hcd->rhport[i]; - - if (status & (RH_PS_CSC | RH_PS_PESC | RH_PS_PSSC | - RH_PS_OCIC | RH_PS_PRSC)) { - changed = 1; - buf[0] |= 1 << (i + 1); - continue; - } - - if (!(status & RH_PS_CCS)) - continue; - } - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - return changed; -} - -static void isp1362_hub_descriptor(struct isp1362_hcd *isp1362_hcd, - struct usb_hub_descriptor *desc) -{ - u32 reg = isp1362_hcd->rhdesca; - - DBG(3, "%s: enter\n", __func__); - - desc->bDescriptorType = 0x29; - desc->bDescLength = 9; - desc->bHubContrCurrent = 0; - desc->bNbrPorts = reg & 0x3; - /* Power switching, device type, overcurrent. */ - desc->wHubCharacteristics = cpu_to_le16((reg >> 8) & 0x1f); - DBG(0, "%s: hubcharacteristics = %02x\n", __func__, cpu_to_le16((reg >> 8) & 0x1f)); - desc->bPwrOn2PwrGood = (reg >> 24) & 0xff; - /* two bitmaps: ports removable, and legacy PortPwrCtrlMask */ - desc->bitmap[0] = desc->bNbrPorts == 1 ? 1 << 1 : 3 << 1; - desc->bitmap[1] = ~0; - - DBG(3, "%s: exit\n", __func__); -} - -/* Adapted from ohci-hub.c */ -static int isp1362_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, - u16 wIndex, char *buf, u16 wLength) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - int retval = 0; - unsigned long flags; - unsigned long t1; - int ports = isp1362_hcd->rhdesca & RH_A_NDP; - u32 tmp = 0; - - switch (typeReq) { - case ClearHubFeature: - DBG(0, "ClearHubFeature: "); - switch (wValue) { - case C_HUB_OVER_CURRENT: - _DBG(0, "C_HUB_OVER_CURRENT\n"); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_reg32(isp1362_hcd, HCRHSTATUS, RH_HS_OCIC); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - case C_HUB_LOCAL_POWER: - _DBG(0, "C_HUB_LOCAL_POWER\n"); - break; - default: - goto error; - } - break; - case SetHubFeature: - DBG(0, "SetHubFeature: "); - switch (wValue) { - case C_HUB_OVER_CURRENT: - case C_HUB_LOCAL_POWER: - _DBG(0, "C_HUB_OVER_CURRENT or C_HUB_LOCAL_POWER\n"); - break; - default: - goto error; - } - break; - case GetHubDescriptor: - DBG(0, "GetHubDescriptor\n"); - isp1362_hub_descriptor(isp1362_hcd, (struct usb_hub_descriptor *)buf); - break; - case GetHubStatus: - DBG(0, "GetHubStatus\n"); - put_unaligned(cpu_to_le32(0), (__le32 *) buf); - break; - case GetPortStatus: -#ifndef VERBOSE - DBG(0, "GetPortStatus\n"); -#endif - if (!wIndex || wIndex > ports) - goto error; - tmp = isp1362_hcd->rhport[--wIndex]; - put_unaligned(cpu_to_le32(tmp), (__le32 *) buf); - break; - case ClearPortFeature: - DBG(0, "ClearPortFeature: "); - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - - switch (wValue) { - case USB_PORT_FEAT_ENABLE: - _DBG(0, "USB_PORT_FEAT_ENABLE\n"); - tmp = RH_PS_CCS; - break; - case USB_PORT_FEAT_C_ENABLE: - _DBG(0, "USB_PORT_FEAT_C_ENABLE\n"); - tmp = RH_PS_PESC; - break; - case USB_PORT_FEAT_SUSPEND: - _DBG(0, "USB_PORT_FEAT_SUSPEND\n"); - tmp = RH_PS_POCI; - break; - case USB_PORT_FEAT_C_SUSPEND: - _DBG(0, "USB_PORT_FEAT_C_SUSPEND\n"); - tmp = RH_PS_PSSC; - break; - case USB_PORT_FEAT_POWER: - _DBG(0, "USB_PORT_FEAT_POWER\n"); - tmp = RH_PS_LSDA; - - break; - case USB_PORT_FEAT_C_CONNECTION: - _DBG(0, "USB_PORT_FEAT_C_CONNECTION\n"); - tmp = RH_PS_CSC; - break; - case USB_PORT_FEAT_C_OVER_CURRENT: - _DBG(0, "USB_PORT_FEAT_C_OVER_CURRENT\n"); - tmp = RH_PS_OCIC; - break; - case USB_PORT_FEAT_C_RESET: - _DBG(0, "USB_PORT_FEAT_C_RESET\n"); - tmp = RH_PS_PRSC; - break; - default: - goto error; - } - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, tmp); - isp1362_hcd->rhport[wIndex] = - isp1362_read_reg32(isp1362_hcd, HCRHPORT1 + wIndex); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - break; - case SetPortFeature: - DBG(0, "SetPortFeature: "); - if (!wIndex || wIndex > ports) - goto error; - wIndex--; - switch (wValue) { - case USB_PORT_FEAT_SUSPEND: - _DBG(0, "USB_PORT_FEAT_SUSPEND\n"); -#ifdef CONFIG_USB_OTG - if (ohci->hcd.self.otg_port == (wIndex + 1) && - ohci->hcd.self.b_hnp_enable) { - start_hnp(ohci); - break; - } -#endif - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PSS); - isp1362_hcd->rhport[wIndex] = - isp1362_read_reg32(isp1362_hcd, HCRHPORT1 + wIndex); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - break; - case USB_PORT_FEAT_POWER: - _DBG(0, "USB_PORT_FEAT_POWER\n"); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, RH_PS_PPS); - isp1362_hcd->rhport[wIndex] = - isp1362_read_reg32(isp1362_hcd, HCRHPORT1 + wIndex); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - break; - case USB_PORT_FEAT_RESET: - _DBG(0, "USB_PORT_FEAT_RESET\n"); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - - t1 = jiffies + msecs_to_jiffies(USB_RESET_WIDTH); - while (time_before(jiffies, t1)) { - /* spin until any current reset finishes */ - for (;;) { - tmp = isp1362_read_reg32(isp1362_hcd, HCRHPORT1 + wIndex); - if (!(tmp & RH_PS_PRS)) - break; - udelay(500); - } - if (!(tmp & RH_PS_CCS)) - break; - /* Reset lasts 10ms (claims datasheet) */ - isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + wIndex, (RH_PS_PRS)); - - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - msleep(10); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - } - - isp1362_hcd->rhport[wIndex] = isp1362_read_reg32(isp1362_hcd, - HCRHPORT1 + wIndex); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - break; - default: - goto error; - } - break; - - default: - error: - /* "protocol stall" on error */ - _DBG(0, "PROTOCOL STALL\n"); - retval = -EPIPE; - } - - return retval; -} - -#ifdef CONFIG_PM -static int isp1362_bus_suspend(struct usb_hcd *hcd) -{ - int status = 0; - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - unsigned long flags; - - if (time_before(jiffies, isp1362_hcd->next_statechange)) - msleep(5); - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - - isp1362_hcd->hc_control = isp1362_read_reg32(isp1362_hcd, HCCONTROL); - switch (isp1362_hcd->hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_RESUME: - DBG(0, "%s: resume/suspend?\n", __func__); - isp1362_hcd->hc_control &= ~OHCI_CTRL_HCFS; - isp1362_hcd->hc_control |= OHCI_USB_RESET; - isp1362_write_reg32(isp1362_hcd, HCCONTROL, isp1362_hcd->hc_control); - /* FALL THROUGH */ - case OHCI_USB_RESET: - status = -EBUSY; - pr_warning("%s: needs reinit!\n", __func__); - goto done; - case OHCI_USB_SUSPEND: - pr_warning("%s: already suspended?\n", __func__); - goto done; - } - DBG(0, "%s: suspend root hub\n", __func__); - - /* First stop any processing */ - hcd->state = HC_STATE_QUIESCING; - if (!list_empty(&isp1362_hcd->atl_queue.active) || - !list_empty(&isp1362_hcd->intl_queue.active) || - !list_empty(&isp1362_hcd->istl_queue[0] .active) || - !list_empty(&isp1362_hcd->istl_queue[1] .active)) { - int limit; - - isp1362_write_reg32(isp1362_hcd, HCATLSKIP, ~0); - isp1362_write_reg32(isp1362_hcd, HCINTLSKIP, ~0); - isp1362_write_reg16(isp1362_hcd, HCBUFSTAT, 0); - isp1362_write_reg16(isp1362_hcd, HCuPINTENB, 0); - isp1362_write_reg32(isp1362_hcd, HCINTSTAT, OHCI_INTR_SF); - - DBG(0, "%s: stopping schedules ...\n", __func__); - limit = 2000; - while (limit > 0) { - udelay(250); - limit -= 250; - if (isp1362_read_reg32(isp1362_hcd, HCINTSTAT) & OHCI_INTR_SF) - break; - } - mdelay(7); - if (isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_ATL) { - u32 done_map = isp1362_read_reg32(isp1362_hcd, HCATLDONE); - finish_transfers(isp1362_hcd, done_map, &isp1362_hcd->atl_queue); - } - if (isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_INTL) { - u32 done_map = isp1362_read_reg32(isp1362_hcd, HCINTLDONE); - finish_transfers(isp1362_hcd, done_map, &isp1362_hcd->intl_queue); - } - if (isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_ISTL0) - finish_iso_transfers(isp1362_hcd, &isp1362_hcd->istl_queue[0]); - if (isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_ISTL1) - finish_iso_transfers(isp1362_hcd, &isp1362_hcd->istl_queue[1]); - } - DBG(0, "%s: HCINTSTAT: %08x\n", __func__, - isp1362_read_reg32(isp1362_hcd, HCINTSTAT)); - isp1362_write_reg32(isp1362_hcd, HCINTSTAT, - isp1362_read_reg32(isp1362_hcd, HCINTSTAT)); - - /* Suspend hub */ - isp1362_hcd->hc_control = OHCI_USB_SUSPEND; - isp1362_show_reg(isp1362_hcd, HCCONTROL); - isp1362_write_reg32(isp1362_hcd, HCCONTROL, isp1362_hcd->hc_control); - isp1362_show_reg(isp1362_hcd, HCCONTROL); - -#if 1 - isp1362_hcd->hc_control = isp1362_read_reg32(isp1362_hcd, HCCONTROL); - if ((isp1362_hcd->hc_control & OHCI_CTRL_HCFS) != OHCI_USB_SUSPEND) { - pr_err("%s: controller won't suspend %08x\n", __func__, - isp1362_hcd->hc_control); - status = -EBUSY; - } else -#endif - { - /* no resumes until devices finish suspending */ - isp1362_hcd->next_statechange = jiffies + msecs_to_jiffies(5); - } -done: - if (status == 0) { - hcd->state = HC_STATE_SUSPENDED; - DBG(0, "%s: HCD suspended: %08x\n", __func__, - isp1362_read_reg32(isp1362_hcd, HCCONTROL)); - } - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - return status; -} - -static int isp1362_bus_resume(struct usb_hcd *hcd) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - u32 port; - unsigned long flags; - int status = -EINPROGRESS; - - if (time_before(jiffies, isp1362_hcd->next_statechange)) - msleep(5); - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_hcd->hc_control = isp1362_read_reg32(isp1362_hcd, HCCONTROL); - pr_info("%s: HCCONTROL: %08x\n", __func__, isp1362_hcd->hc_control); - if (hcd->state == HC_STATE_RESUMING) { - pr_warning("%s: duplicate resume\n", __func__); - status = 0; - } else - switch (isp1362_hcd->hc_control & OHCI_CTRL_HCFS) { - case OHCI_USB_SUSPEND: - DBG(0, "%s: resume root hub\n", __func__); - isp1362_hcd->hc_control &= ~OHCI_CTRL_HCFS; - isp1362_hcd->hc_control |= OHCI_USB_RESUME; - isp1362_write_reg32(isp1362_hcd, HCCONTROL, isp1362_hcd->hc_control); - break; - case OHCI_USB_RESUME: - /* HCFS changes sometime after INTR_RD */ - DBG(0, "%s: remote wakeup\n", __func__); - break; - case OHCI_USB_OPER: - DBG(0, "%s: odd resume\n", __func__); - status = 0; - hcd->self.root_hub->dev.power.power_state = PMSG_ON; - break; - default: /* RESET, we lost power */ - DBG(0, "%s: root hub hardware reset\n", __func__); - status = -EBUSY; - } - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - if (status == -EBUSY) { - DBG(0, "%s: Restarting HC\n", __func__); - isp1362_hc_stop(hcd); - return isp1362_hc_start(hcd); - } - if (status != -EINPROGRESS) - return status; - spin_lock_irqsave(&isp1362_hcd->lock, flags); - port = isp1362_read_reg32(isp1362_hcd, HCRHDESCA) & RH_A_NDP; - while (port--) { - u32 stat = isp1362_read_reg32(isp1362_hcd, HCRHPORT1 + port); - - /* force global, not selective, resume */ - if (!(stat & RH_PS_PSS)) { - DBG(0, "%s: Not Resuming RH port %d\n", __func__, port); - continue; - } - DBG(0, "%s: Resuming RH port %d\n", __func__, port); - isp1362_write_reg32(isp1362_hcd, HCRHPORT1 + port, RH_PS_POCI); - } - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - /* Some controllers (lucent) need extra-long delays */ - hcd->state = HC_STATE_RESUMING; - mdelay(20 /* usb 11.5.1.10 */ + 15); - - isp1362_hcd->hc_control = OHCI_USB_OPER; - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_show_reg(isp1362_hcd, HCCONTROL); - isp1362_write_reg32(isp1362_hcd, HCCONTROL, isp1362_hcd->hc_control); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - /* TRSMRCY */ - msleep(10); - - /* keep it alive for ~5x suspend + resume costs */ - isp1362_hcd->next_statechange = jiffies + msecs_to_jiffies(250); - - hcd->self.root_hub->dev.power.power_state = PMSG_ON; - hcd->state = HC_STATE_RUNNING; - return 0; -} -#else -#define isp1362_bus_suspend NULL -#define isp1362_bus_resume NULL -#endif - -/*-------------------------------------------------------------------------*/ - -#ifdef STUB_DEBUG_FILE - -static inline void create_debug_file(struct isp1362_hcd *isp1362_hcd) -{ -} -static inline void remove_debug_file(struct isp1362_hcd *isp1362_hcd) -{ -} - -#else - -#include -#include - -static void dump_irq(struct seq_file *s, char *label, u16 mask) -{ - seq_printf(s, "%-15s %04x%s%s%s%s%s%s\n", label, mask, - mask & HCuPINT_CLKRDY ? " clkrdy" : "", - mask & HCuPINT_SUSP ? " susp" : "", - mask & HCuPINT_OPR ? " opr" : "", - mask & HCuPINT_EOT ? " eot" : "", - mask & HCuPINT_ATL ? " atl" : "", - mask & HCuPINT_SOF ? " sof" : ""); -} - -static void dump_int(struct seq_file *s, char *label, u32 mask) -{ - seq_printf(s, "%-15s %08x%s%s%s%s%s%s%s\n", label, mask, - mask & OHCI_INTR_MIE ? " MIE" : "", - mask & OHCI_INTR_RHSC ? " rhsc" : "", - mask & OHCI_INTR_FNO ? " fno" : "", - mask & OHCI_INTR_UE ? " ue" : "", - mask & OHCI_INTR_RD ? " rd" : "", - mask & OHCI_INTR_SF ? " sof" : "", - mask & OHCI_INTR_SO ? " so" : ""); -} - -static void dump_ctrl(struct seq_file *s, char *label, u32 mask) -{ - seq_printf(s, "%-15s %08x%s%s%s\n", label, mask, - mask & OHCI_CTRL_RWC ? " rwc" : "", - mask & OHCI_CTRL_RWE ? " rwe" : "", - ({ - char *hcfs; - switch (mask & OHCI_CTRL_HCFS) { - case OHCI_USB_OPER: - hcfs = " oper"; - break; - case OHCI_USB_RESET: - hcfs = " reset"; - break; - case OHCI_USB_RESUME: - hcfs = " resume"; - break; - case OHCI_USB_SUSPEND: - hcfs = " suspend"; - break; - default: - hcfs = " ?"; - } - hcfs; - })); -} - -static void dump_regs(struct seq_file *s, struct isp1362_hcd *isp1362_hcd) -{ - seq_printf(s, "HCREVISION [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCREVISION), - isp1362_read_reg32(isp1362_hcd, HCREVISION)); - seq_printf(s, "HCCONTROL [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCCONTROL), - isp1362_read_reg32(isp1362_hcd, HCCONTROL)); - seq_printf(s, "HCCMDSTAT [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCCMDSTAT), - isp1362_read_reg32(isp1362_hcd, HCCMDSTAT)); - seq_printf(s, "HCINTSTAT [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCINTSTAT), - isp1362_read_reg32(isp1362_hcd, HCINTSTAT)); - seq_printf(s, "HCINTENB [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCINTENB), - isp1362_read_reg32(isp1362_hcd, HCINTENB)); - seq_printf(s, "HCFMINTVL [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCFMINTVL), - isp1362_read_reg32(isp1362_hcd, HCFMINTVL)); - seq_printf(s, "HCFMREM [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCFMREM), - isp1362_read_reg32(isp1362_hcd, HCFMREM)); - seq_printf(s, "HCFMNUM [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCFMNUM), - isp1362_read_reg32(isp1362_hcd, HCFMNUM)); - seq_printf(s, "HCLSTHRESH [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCLSTHRESH), - isp1362_read_reg32(isp1362_hcd, HCLSTHRESH)); - seq_printf(s, "HCRHDESCA [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCRHDESCA), - isp1362_read_reg32(isp1362_hcd, HCRHDESCA)); - seq_printf(s, "HCRHDESCB [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCRHDESCB), - isp1362_read_reg32(isp1362_hcd, HCRHDESCB)); - seq_printf(s, "HCRHSTATUS [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCRHSTATUS), - isp1362_read_reg32(isp1362_hcd, HCRHSTATUS)); - seq_printf(s, "HCRHPORT1 [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCRHPORT1), - isp1362_read_reg32(isp1362_hcd, HCRHPORT1)); - seq_printf(s, "HCRHPORT2 [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCRHPORT2), - isp1362_read_reg32(isp1362_hcd, HCRHPORT2)); - seq_printf(s, "\n"); - seq_printf(s, "HCHWCFG [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCHWCFG), - isp1362_read_reg16(isp1362_hcd, HCHWCFG)); - seq_printf(s, "HCDMACFG [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCDMACFG), - isp1362_read_reg16(isp1362_hcd, HCDMACFG)); - seq_printf(s, "HCXFERCTR [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCXFERCTR), - isp1362_read_reg16(isp1362_hcd, HCXFERCTR)); - seq_printf(s, "HCuPINT [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCuPINT), - isp1362_read_reg16(isp1362_hcd, HCuPINT)); - seq_printf(s, "HCuPINTENB [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCuPINTENB), - isp1362_read_reg16(isp1362_hcd, HCuPINTENB)); - seq_printf(s, "HCCHIPID [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCCHIPID), - isp1362_read_reg16(isp1362_hcd, HCCHIPID)); - seq_printf(s, "HCSCRATCH [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCSCRATCH), - isp1362_read_reg16(isp1362_hcd, HCSCRATCH)); - seq_printf(s, "HCBUFSTAT [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCBUFSTAT), - isp1362_read_reg16(isp1362_hcd, HCBUFSTAT)); - seq_printf(s, "HCDIRADDR [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCDIRADDR), - isp1362_read_reg32(isp1362_hcd, HCDIRADDR)); -#if 0 - seq_printf(s, "HCDIRDATA [%02x] %04x\n", ISP1362_REG_NO(HCDIRDATA), - isp1362_read_reg16(isp1362_hcd, HCDIRDATA)); -#endif - seq_printf(s, "HCISTLBUFSZ[%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCISTLBUFSZ), - isp1362_read_reg16(isp1362_hcd, HCISTLBUFSZ)); - seq_printf(s, "HCISTLRATE [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCISTLRATE), - isp1362_read_reg16(isp1362_hcd, HCISTLRATE)); - seq_printf(s, "\n"); - seq_printf(s, "HCINTLBUFSZ[%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCINTLBUFSZ), - isp1362_read_reg16(isp1362_hcd, HCINTLBUFSZ)); - seq_printf(s, "HCINTLBLKSZ[%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCINTLBLKSZ), - isp1362_read_reg16(isp1362_hcd, HCINTLBLKSZ)); - seq_printf(s, "HCINTLDONE [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCINTLDONE), - isp1362_read_reg32(isp1362_hcd, HCINTLDONE)); - seq_printf(s, "HCINTLSKIP [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCINTLSKIP), - isp1362_read_reg32(isp1362_hcd, HCINTLSKIP)); - seq_printf(s, "HCINTLLAST [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCINTLLAST), - isp1362_read_reg32(isp1362_hcd, HCINTLLAST)); - seq_printf(s, "HCINTLCURR [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCINTLCURR), - isp1362_read_reg16(isp1362_hcd, HCINTLCURR)); - seq_printf(s, "\n"); - seq_printf(s, "HCATLBUFSZ [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCATLBUFSZ), - isp1362_read_reg16(isp1362_hcd, HCATLBUFSZ)); - seq_printf(s, "HCATLBLKSZ [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCATLBLKSZ), - isp1362_read_reg16(isp1362_hcd, HCATLBLKSZ)); -#if 0 - seq_printf(s, "HCATLDONE [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCATLDONE), - isp1362_read_reg32(isp1362_hcd, HCATLDONE)); -#endif - seq_printf(s, "HCATLSKIP [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCATLSKIP), - isp1362_read_reg32(isp1362_hcd, HCATLSKIP)); - seq_printf(s, "HCATLLAST [%02x] %08x\n", ISP1362_REG_NO(ISP1362_REG_HCATLLAST), - isp1362_read_reg32(isp1362_hcd, HCATLLAST)); - seq_printf(s, "HCATLCURR [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCATLCURR), - isp1362_read_reg16(isp1362_hcd, HCATLCURR)); - seq_printf(s, "\n"); - seq_printf(s, "HCATLDTC [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCATLDTC), - isp1362_read_reg16(isp1362_hcd, HCATLDTC)); - seq_printf(s, "HCATLDTCTO [%02x] %04x\n", ISP1362_REG_NO(ISP1362_REG_HCATLDTCTO), - isp1362_read_reg16(isp1362_hcd, HCATLDTCTO)); -} - -static int proc_isp1362_show(struct seq_file *s, void *unused) -{ - struct isp1362_hcd *isp1362_hcd = s->private; - struct isp1362_ep *ep; - int i; - - seq_printf(s, "%s\n%s version %s\n", - isp1362_hcd_to_hcd(isp1362_hcd)->product_desc, hcd_name, DRIVER_VERSION); - - /* collect statistics to help estimate potential win for - * DMA engines that care about alignment (PXA) - */ - seq_printf(s, "alignment: 16b/%ld 8b/%ld 4b/%ld 2b/%ld 1b/%ld\n", - isp1362_hcd->stat16, isp1362_hcd->stat8, isp1362_hcd->stat4, - isp1362_hcd->stat2, isp1362_hcd->stat1); - seq_printf(s, "max # ptds in ATL fifo: %d\n", isp1362_hcd->atl_queue.stat_maxptds); - seq_printf(s, "max # ptds in INTL fifo: %d\n", isp1362_hcd->intl_queue.stat_maxptds); - seq_printf(s, "max # ptds in ISTL fifo: %d\n", - max(isp1362_hcd->istl_queue[0] .stat_maxptds, - isp1362_hcd->istl_queue[1] .stat_maxptds)); - - /* FIXME: don't show the following in suspended state */ - spin_lock_irq(&isp1362_hcd->lock); - - dump_irq(s, "hc_irq_enable", isp1362_read_reg16(isp1362_hcd, HCuPINTENB)); - dump_irq(s, "hc_irq_status", isp1362_read_reg16(isp1362_hcd, HCuPINT)); - dump_int(s, "ohci_int_enable", isp1362_read_reg32(isp1362_hcd, HCINTENB)); - dump_int(s, "ohci_int_status", isp1362_read_reg32(isp1362_hcd, HCINTSTAT)); - dump_ctrl(s, "ohci_control", isp1362_read_reg32(isp1362_hcd, HCCONTROL)); - - for (i = 0; i < NUM_ISP1362_IRQS; i++) - if (isp1362_hcd->irq_stat[i]) - seq_printf(s, "%-15s: %d\n", - ISP1362_INT_NAME(i), isp1362_hcd->irq_stat[i]); - - dump_regs(s, isp1362_hcd); - list_for_each_entry(ep, &isp1362_hcd->async, schedule) { - struct urb *urb; - - seq_printf(s, "%p, ep%d%s, maxpacket %d:\n", ep, ep->epnum, - ({ - char *s; - switch (ep->nextpid) { - case USB_PID_IN: - s = "in"; - break; - case USB_PID_OUT: - s = "out"; - break; - case USB_PID_SETUP: - s = "setup"; - break; - case USB_PID_ACK: - s = "status"; - break; - default: - s = "?"; - break; - }; - s;}), ep->maxpacket) ; - list_for_each_entry(urb, &ep->hep->urb_list, urb_list) { - seq_printf(s, " urb%p, %d/%d\n", urb, - urb->actual_length, - urb->transfer_buffer_length); - } - } - if (!list_empty(&isp1362_hcd->async)) - seq_printf(s, "\n"); - dump_ptd_queue(&isp1362_hcd->atl_queue); - - seq_printf(s, "periodic size= %d\n", PERIODIC_SIZE); - - list_for_each_entry(ep, &isp1362_hcd->periodic, schedule) { - seq_printf(s, "branch:%2d load:%3d PTD[%d] $%04x:\n", ep->branch, - isp1362_hcd->load[ep->branch], ep->ptd_index, ep->ptd_offset); - - seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n", - ep->interval, ep, - (ep->udev->speed == USB_SPEED_FULL) ? "" : "ls ", - ep->udev->devnum, ep->epnum, - (ep->epnum == 0) ? "" : - ((ep->nextpid == USB_PID_IN) ? - "in" : "out"), ep->maxpacket); - } - dump_ptd_queue(&isp1362_hcd->intl_queue); - - seq_printf(s, "ISO:\n"); - - list_for_each_entry(ep, &isp1362_hcd->isoc, schedule) { - seq_printf(s, " %d/%p (%sdev%d ep%d%s max %d)\n", - ep->interval, ep, - (ep->udev->speed == USB_SPEED_FULL) ? "" : "ls ", - ep->udev->devnum, ep->epnum, - (ep->epnum == 0) ? "" : - ((ep->nextpid == USB_PID_IN) ? - "in" : "out"), ep->maxpacket); - } - - spin_unlock_irq(&isp1362_hcd->lock); - seq_printf(s, "\n"); - - return 0; -} - -static int proc_isp1362_open(struct inode *inode, struct file *file) -{ - return single_open(file, proc_isp1362_show, PDE(inode)->data); -} - -static const struct file_operations proc_ops = { - .open = proc_isp1362_open, - .read = seq_read, - .llseek = seq_lseek, - .release = single_release, -}; - -/* expect just one isp1362_hcd per system */ -static const char proc_filename[] = "driver/isp1362"; - -static void create_debug_file(struct isp1362_hcd *isp1362_hcd) -{ - struct proc_dir_entry *pde; - - pde = create_proc_entry(proc_filename, 0, NULL); - if (pde == NULL) { - pr_warning("%s: Failed to create debug file '%s'\n", __func__, proc_filename); - return; - } - - pde->proc_fops = &proc_ops; - pde->data = isp1362_hcd; - isp1362_hcd->pde = pde; -} - -static void remove_debug_file(struct isp1362_hcd *isp1362_hcd) -{ - if (isp1362_hcd->pde) - remove_proc_entry(proc_filename, 0); -} - -#endif - -/*-------------------------------------------------------------------------*/ - -static void isp1362_sw_reset(struct isp1362_hcd *isp1362_hcd) -{ - int tmp = 20; - unsigned long flags; - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - - isp1362_write_reg16(isp1362_hcd, HCSWRES, HCSWRES_MAGIC); - isp1362_write_reg32(isp1362_hcd, HCCMDSTAT, OHCI_HCR); - while (--tmp) { - mdelay(1); - if (!(isp1362_read_reg32(isp1362_hcd, HCCMDSTAT) & OHCI_HCR)) - break; - } - if (!tmp) - pr_err("Software reset timeout\n"); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); -} - -static int isp1362_mem_config(struct usb_hcd *hcd) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - unsigned long flags; - u32 total; - u16 istl_size = ISP1362_ISTL_BUFSIZE; - u16 intl_blksize = ISP1362_INTL_BLKSIZE + PTD_HEADER_SIZE; - u16 intl_size = ISP1362_INTL_BUFFERS * intl_blksize; - u16 atl_blksize = ISP1362_ATL_BLKSIZE + PTD_HEADER_SIZE; - u16 atl_buffers = (ISP1362_BUF_SIZE - (istl_size + intl_size)) / atl_blksize; - u16 atl_size; - int i; - - WARN_ON(istl_size & 3); - WARN_ON(atl_blksize & 3); - WARN_ON(intl_blksize & 3); - WARN_ON(atl_blksize < PTD_HEADER_SIZE); - WARN_ON(intl_blksize < PTD_HEADER_SIZE); - - BUG_ON((unsigned)ISP1362_INTL_BUFFERS > 32); - if (atl_buffers > 32) - atl_buffers = 32; - atl_size = atl_buffers * atl_blksize; - total = atl_size + intl_size + istl_size; - dev_info(hcd->self.controller, "ISP1362 Memory usage:\n"); - dev_info(hcd->self.controller, " ISTL: 2 * %4d: %4d @ $%04x:$%04x\n", - istl_size / 2, istl_size, 0, istl_size / 2); - dev_info(hcd->self.controller, " INTL: %4d * (%3u+8): %4d @ $%04x\n", - ISP1362_INTL_BUFFERS, intl_blksize - PTD_HEADER_SIZE, - intl_size, istl_size); - dev_info(hcd->self.controller, " ATL : %4d * (%3u+8): %4d @ $%04x\n", - atl_buffers, atl_blksize - PTD_HEADER_SIZE, - atl_size, istl_size + intl_size); - dev_info(hcd->self.controller, " USED/FREE: %4d %4d\n", total, - ISP1362_BUF_SIZE - total); - - if (total > ISP1362_BUF_SIZE) { - dev_err(hcd->self.controller, "%s: Memory requested: %d, available %d\n", - __func__, total, ISP1362_BUF_SIZE); - return -ENOMEM; - } - - total = istl_size + intl_size + atl_size; - spin_lock_irqsave(&isp1362_hcd->lock, flags); - - for (i = 0; i < 2; i++) { - isp1362_hcd->istl_queue[i].buf_start = i * istl_size / 2, - isp1362_hcd->istl_queue[i].buf_size = istl_size / 2; - isp1362_hcd->istl_queue[i].blk_size = 4; - INIT_LIST_HEAD(&isp1362_hcd->istl_queue[i].active); - snprintf(isp1362_hcd->istl_queue[i].name, - sizeof(isp1362_hcd->istl_queue[i].name), "ISTL%d", i); - DBG(3, "%s: %5s buf $%04x %d\n", __func__, - isp1362_hcd->istl_queue[i].name, - isp1362_hcd->istl_queue[i].buf_start, - isp1362_hcd->istl_queue[i].buf_size); - } - isp1362_write_reg16(isp1362_hcd, HCISTLBUFSZ, istl_size / 2); - - isp1362_hcd->intl_queue.buf_start = istl_size; - isp1362_hcd->intl_queue.buf_size = intl_size; - isp1362_hcd->intl_queue.buf_count = ISP1362_INTL_BUFFERS; - isp1362_hcd->intl_queue.blk_size = intl_blksize; - isp1362_hcd->intl_queue.buf_avail = isp1362_hcd->intl_queue.buf_count; - isp1362_hcd->intl_queue.skip_map = ~0; - INIT_LIST_HEAD(&isp1362_hcd->intl_queue.active); - - isp1362_write_reg16(isp1362_hcd, HCINTLBUFSZ, - isp1362_hcd->intl_queue.buf_size); - isp1362_write_reg16(isp1362_hcd, HCINTLBLKSZ, - isp1362_hcd->intl_queue.blk_size - PTD_HEADER_SIZE); - isp1362_write_reg32(isp1362_hcd, HCINTLSKIP, ~0); - isp1362_write_reg32(isp1362_hcd, HCINTLLAST, - 1 << (ISP1362_INTL_BUFFERS - 1)); - - isp1362_hcd->atl_queue.buf_start = istl_size + intl_size; - isp1362_hcd->atl_queue.buf_size = atl_size; - isp1362_hcd->atl_queue.buf_count = atl_buffers; - isp1362_hcd->atl_queue.blk_size = atl_blksize; - isp1362_hcd->atl_queue.buf_avail = isp1362_hcd->atl_queue.buf_count; - isp1362_hcd->atl_queue.skip_map = ~0; - INIT_LIST_HEAD(&isp1362_hcd->atl_queue.active); - - isp1362_write_reg16(isp1362_hcd, HCATLBUFSZ, - isp1362_hcd->atl_queue.buf_size); - isp1362_write_reg16(isp1362_hcd, HCATLBLKSZ, - isp1362_hcd->atl_queue.blk_size - PTD_HEADER_SIZE); - isp1362_write_reg32(isp1362_hcd, HCATLSKIP, ~0); - isp1362_write_reg32(isp1362_hcd, HCATLLAST, - 1 << (atl_buffers - 1)); - - snprintf(isp1362_hcd->atl_queue.name, - sizeof(isp1362_hcd->atl_queue.name), "ATL"); - snprintf(isp1362_hcd->intl_queue.name, - sizeof(isp1362_hcd->intl_queue.name), "INTL"); - DBG(3, "%s: %5s buf $%04x %2d * %4d = %4d\n", __func__, - isp1362_hcd->intl_queue.name, - isp1362_hcd->intl_queue.buf_start, - ISP1362_INTL_BUFFERS, isp1362_hcd->intl_queue.blk_size, - isp1362_hcd->intl_queue.buf_size); - DBG(3, "%s: %5s buf $%04x %2d * %4d = %4d\n", __func__, - isp1362_hcd->atl_queue.name, - isp1362_hcd->atl_queue.buf_start, - atl_buffers, isp1362_hcd->atl_queue.blk_size, - isp1362_hcd->atl_queue.buf_size); - - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - return 0; -} - -static int isp1362_hc_reset(struct usb_hcd *hcd) -{ - int ret = 0; - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - unsigned long t; - unsigned long timeout = 100; - unsigned long flags; - int clkrdy = 0; - - pr_info("%s:\n", __func__); - - if (isp1362_hcd->board && isp1362_hcd->board->reset) { - isp1362_hcd->board->reset(hcd->self.controller, 1); - msleep(20); - if (isp1362_hcd->board->clock) - isp1362_hcd->board->clock(hcd->self.controller, 1); - isp1362_hcd->board->reset(hcd->self.controller, 0); - } else - isp1362_sw_reset(isp1362_hcd); - - /* chip has been reset. First we need to see a clock */ - t = jiffies + msecs_to_jiffies(timeout); - while (!clkrdy && time_before_eq(jiffies, t)) { - spin_lock_irqsave(&isp1362_hcd->lock, flags); - clkrdy = isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_CLKRDY; - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - if (!clkrdy) - msleep(4); - } - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_CLKRDY); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - if (!clkrdy) { - pr_err("Clock not ready after %lums\n", timeout); - ret = -ENODEV; - } - return ret; -} - -static void isp1362_hc_stop(struct usb_hcd *hcd) -{ - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - unsigned long flags; - u32 tmp; - - pr_info("%s:\n", __func__); - - del_timer_sync(&hcd->rh_timer); - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - - isp1362_write_reg16(isp1362_hcd, HCuPINTENB, 0); - - /* Switch off power for all ports */ - tmp = isp1362_read_reg32(isp1362_hcd, HCRHDESCA); - tmp &= ~(RH_A_NPS | RH_A_PSM); - isp1362_write_reg32(isp1362_hcd, HCRHDESCA, tmp); - isp1362_write_reg32(isp1362_hcd, HCRHSTATUS, RH_HS_LPS); - - /* Reset the chip */ - if (isp1362_hcd->board && isp1362_hcd->board->reset) - isp1362_hcd->board->reset(hcd->self.controller, 1); - else - isp1362_sw_reset(isp1362_hcd); - - if (isp1362_hcd->board && isp1362_hcd->board->clock) - isp1362_hcd->board->clock(hcd->self.controller, 0); - - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); -} - -#ifdef CHIP_BUFFER_TEST -static int isp1362_chip_test(struct isp1362_hcd *isp1362_hcd) -{ - int ret = 0; - u16 *ref; - unsigned long flags; - - ref = kmalloc(2 * ISP1362_BUF_SIZE, GFP_KERNEL); - if (ref) { - int offset; - u16 *tst = &ref[ISP1362_BUF_SIZE / 2]; - - for (offset = 0; offset < ISP1362_BUF_SIZE / 2; offset++) { - ref[offset] = ~offset; - tst[offset] = offset; - } - - for (offset = 0; offset < 4; offset++) { - int j; - - for (j = 0; j < 8; j++) { - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_buffer(isp1362_hcd, (u8 *)ref + offset, 0, j); - isp1362_read_buffer(isp1362_hcd, (u8 *)tst + offset, 0, j); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - if (memcmp(ref, tst, j)) { - ret = -ENODEV; - pr_err("%s: memory check with %d byte offset %d failed\n", - __func__, j, offset); - dump_data((u8 *)ref + offset, j); - dump_data((u8 *)tst + offset, j); - } - } - } - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_buffer(isp1362_hcd, ref, 0, ISP1362_BUF_SIZE); - isp1362_read_buffer(isp1362_hcd, tst, 0, ISP1362_BUF_SIZE); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - if (memcmp(ref, tst, ISP1362_BUF_SIZE)) { - ret = -ENODEV; - pr_err("%s: memory check failed\n", __func__); - dump_data((u8 *)tst, ISP1362_BUF_SIZE / 2); - } - - for (offset = 0; offset < 256; offset++) { - int test_size = 0; - - yield(); - - memset(tst, 0, ISP1362_BUF_SIZE); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_buffer(isp1362_hcd, tst, 0, ISP1362_BUF_SIZE); - isp1362_read_buffer(isp1362_hcd, tst, 0, ISP1362_BUF_SIZE); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - if (memcmp(tst, tst + (ISP1362_BUF_SIZE / (2 * sizeof(*tst))), - ISP1362_BUF_SIZE / 2)) { - pr_err("%s: Failed to clear buffer\n", __func__); - dump_data((u8 *)tst, ISP1362_BUF_SIZE); - break; - } - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_buffer(isp1362_hcd, ref, offset * 2, PTD_HEADER_SIZE); - isp1362_write_buffer(isp1362_hcd, ref + PTD_HEADER_SIZE / sizeof(*ref), - offset * 2 + PTD_HEADER_SIZE, test_size); - isp1362_read_buffer(isp1362_hcd, tst, offset * 2, - PTD_HEADER_SIZE + test_size); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - if (memcmp(ref, tst, PTD_HEADER_SIZE + test_size)) { - dump_data(((u8 *)ref) + offset, PTD_HEADER_SIZE + test_size); - dump_data((u8 *)tst, PTD_HEADER_SIZE + test_size); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_read_buffer(isp1362_hcd, tst, offset * 2, - PTD_HEADER_SIZE + test_size); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - if (memcmp(ref, tst, PTD_HEADER_SIZE + test_size)) { - ret = -ENODEV; - pr_err("%s: memory check with offset %02x failed\n", - __func__, offset); - break; - } - pr_warning("%s: memory check with offset %02x ok after second read\n", - __func__, offset); - } - } - kfree(ref); - } - return ret; -} -#endif - -static int isp1362_hc_start(struct usb_hcd *hcd) -{ - int ret; - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - struct isp1362_platform_data *board = isp1362_hcd->board; - u16 hwcfg; - u16 chipid; - unsigned long flags; - - pr_info("%s:\n", __func__); - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - chipid = isp1362_read_reg16(isp1362_hcd, HCCHIPID); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - if ((chipid & HCCHIPID_MASK) != HCCHIPID_MAGIC) { - pr_err("%s: Invalid chip ID %04x\n", __func__, chipid); - return -ENODEV; - } - -#ifdef CHIP_BUFFER_TEST - ret = isp1362_chip_test(isp1362_hcd); - if (ret) - return -ENODEV; -#endif - spin_lock_irqsave(&isp1362_hcd->lock, flags); - /* clear interrupt status and disable all interrupt sources */ - isp1362_write_reg16(isp1362_hcd, HCuPINT, 0xff); - isp1362_write_reg16(isp1362_hcd, HCuPINTENB, 0); - - /* HW conf */ - hwcfg = HCHWCFG_INT_ENABLE | HCHWCFG_DBWIDTH(1); - if (board->sel15Kres) - hwcfg |= HCHWCFG_PULLDOWN_DS2 | - ((MAX_ROOT_PORTS > 1) ? HCHWCFG_PULLDOWN_DS1 : 0); - if (board->clknotstop) - hwcfg |= HCHWCFG_CLKNOTSTOP; - if (board->oc_enable) - hwcfg |= HCHWCFG_ANALOG_OC; - if (board->int_act_high) - hwcfg |= HCHWCFG_INT_POL; - if (board->int_edge_triggered) - hwcfg |= HCHWCFG_INT_TRIGGER; - if (board->dreq_act_high) - hwcfg |= HCHWCFG_DREQ_POL; - if (board->dack_act_high) - hwcfg |= HCHWCFG_DACK_POL; - isp1362_write_reg16(isp1362_hcd, HCHWCFG, hwcfg); - isp1362_show_reg(isp1362_hcd, HCHWCFG); - isp1362_write_reg16(isp1362_hcd, HCDMACFG, 0); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - ret = isp1362_mem_config(hcd); - if (ret) - return ret; - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - - /* Root hub conf */ - isp1362_hcd->rhdesca = 0; - if (board->no_power_switching) - isp1362_hcd->rhdesca |= RH_A_NPS; - if (board->power_switching_mode) - isp1362_hcd->rhdesca |= RH_A_PSM; - if (board->potpg) - isp1362_hcd->rhdesca |= (board->potpg << 24) & RH_A_POTPGT; - else - isp1362_hcd->rhdesca |= (25 << 24) & RH_A_POTPGT; - - isp1362_write_reg32(isp1362_hcd, HCRHDESCA, isp1362_hcd->rhdesca & ~RH_A_OCPM); - isp1362_write_reg32(isp1362_hcd, HCRHDESCA, isp1362_hcd->rhdesca | RH_A_OCPM); - isp1362_hcd->rhdesca = isp1362_read_reg32(isp1362_hcd, HCRHDESCA); - - isp1362_hcd->rhdescb = RH_B_PPCM; - isp1362_write_reg32(isp1362_hcd, HCRHDESCB, isp1362_hcd->rhdescb); - isp1362_hcd->rhdescb = isp1362_read_reg32(isp1362_hcd, HCRHDESCB); - - isp1362_read_reg32(isp1362_hcd, HCFMINTVL); - isp1362_write_reg32(isp1362_hcd, HCFMINTVL, (FSMP(FI) << 16) | FI); - isp1362_write_reg32(isp1362_hcd, HCLSTHRESH, LSTHRESH); - - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - isp1362_hcd->hc_control = OHCI_USB_OPER; - hcd->state = HC_STATE_RUNNING; - - spin_lock_irqsave(&isp1362_hcd->lock, flags); - /* Set up interrupts */ - isp1362_hcd->intenb = OHCI_INTR_MIE | OHCI_INTR_RHSC | OHCI_INTR_UE; - isp1362_hcd->intenb |= OHCI_INTR_RD; - isp1362_hcd->irqenb = HCuPINT_OPR | HCuPINT_SUSP; - isp1362_write_reg32(isp1362_hcd, HCINTENB, isp1362_hcd->intenb); - isp1362_write_reg16(isp1362_hcd, HCuPINTENB, isp1362_hcd->irqenb); - - /* Go operational */ - isp1362_write_reg32(isp1362_hcd, HCCONTROL, isp1362_hcd->hc_control); - /* enable global power */ - isp1362_write_reg32(isp1362_hcd, HCRHSTATUS, RH_HS_LPSC | RH_HS_DRWE); - - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - - return 0; -} - -/*-------------------------------------------------------------------------*/ - -static struct hc_driver isp1362_hc_driver = { - .description = hcd_name, - .product_desc = "ISP1362 Host Controller", - .hcd_priv_size = sizeof(struct isp1362_hcd), - - .irq = isp1362_irq, - .flags = HCD_USB11 | HCD_MEMORY, - - .reset = isp1362_hc_reset, - .start = isp1362_hc_start, - .stop = isp1362_hc_stop, - - .urb_enqueue = isp1362_urb_enqueue, - .urb_dequeue = isp1362_urb_dequeue, - .endpoint_disable = isp1362_endpoint_disable, - - .get_frame_number = isp1362_get_frame, - - .hub_status_data = isp1362_hub_status_data, - .hub_control = isp1362_hub_control, - .bus_suspend = isp1362_bus_suspend, - .bus_resume = isp1362_bus_resume, -}; - -/*-------------------------------------------------------------------------*/ - -#define resource_len(r) (((r)->end - (r)->start) + 1) - -static int __devexit isp1362_remove(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - struct resource *res; - - remove_debug_file(isp1362_hcd); - DBG(0, "%s: Removing HCD\n", __func__); - usb_remove_hcd(hcd); - - DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__, - (u32)isp1362_hcd->data_reg); - iounmap(isp1362_hcd->data_reg); - - DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__, - (u32)isp1362_hcd->addr_reg); - iounmap(isp1362_hcd->addr_reg); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 1); - DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start); - if (res) - release_mem_region(res->start, resource_len(res)); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - DBG(0, "%s: release mem_region: %08lx\n", __func__, (long unsigned int)res->start); - if (res) - release_mem_region(res->start, resource_len(res)); - - DBG(0, "%s: put_hcd\n", __func__); - usb_put_hcd(hcd); - DBG(0, "%s: Done\n", __func__); - - return 0; -} - -static int __init isp1362_probe(struct platform_device *pdev) -{ - struct usb_hcd *hcd; - struct isp1362_hcd *isp1362_hcd; - struct resource *addr, *data; - void __iomem *addr_reg; - void __iomem *data_reg; - int irq; - int retval = 0; - - /* basic sanity checks first. board-specific init logic should - * have initialized this the three resources and probably board - * specific platform_data. we don't probe for IRQs, and do only - * minimal sanity checking. - */ - if (pdev->num_resources < 3) { - retval = -ENODEV; - goto err1; - } - - data = platform_get_resource(pdev, IORESOURCE_MEM, 0); - addr = platform_get_resource(pdev, IORESOURCE_MEM, 1); - irq = platform_get_irq(pdev, 0); - if (!addr || !data || irq < 0) { - retval = -ENODEV; - goto err1; - } - -#ifdef CONFIG_USB_HCD_DMA - if (pdev->dev.dma_mask) { - struct resource *dma_res = platform_get_resource(pdev, IORESOURCE_MEM, 2); - - if (!dma_res) { - retval = -ENODEV; - goto err1; - } - isp1362_hcd->data_dma = dma_res->start; - isp1362_hcd->max_dma_size = resource_len(dma_res); - } -#else - if (pdev->dev.dma_mask) { - DBG(1, "won't do DMA"); - retval = -ENODEV; - goto err1; - } -#endif - - if (!request_mem_region(addr->start, resource_len(addr), hcd_name)) { - retval = -EBUSY; - goto err1; - } - addr_reg = ioremap(addr->start, resource_len(addr)); - if (addr_reg == NULL) { - retval = -ENOMEM; - goto err2; - } - - if (!request_mem_region(data->start, resource_len(data), hcd_name)) { - retval = -EBUSY; - goto err3; - } - data_reg = ioremap(data->start, resource_len(data)); - if (data_reg == NULL) { - retval = -ENOMEM; - goto err4; - } - - /* allocate and initialize hcd */ - hcd = usb_create_hcd(&isp1362_hc_driver, &pdev->dev, dev_name(&pdev->dev)); - if (!hcd) { - retval = -ENOMEM; - goto err5; - } - hcd->rsrc_start = data->start; - isp1362_hcd = hcd_to_isp1362_hcd(hcd); - isp1362_hcd->data_reg = data_reg; - isp1362_hcd->addr_reg = addr_reg; - - isp1362_hcd->next_statechange = jiffies; - spin_lock_init(&isp1362_hcd->lock); - INIT_LIST_HEAD(&isp1362_hcd->async); - INIT_LIST_HEAD(&isp1362_hcd->periodic); - INIT_LIST_HEAD(&isp1362_hcd->isoc); - INIT_LIST_HEAD(&isp1362_hcd->remove_list); - isp1362_hcd->board = pdev->dev.platform_data; -#if USE_PLATFORM_DELAY - if (!isp1362_hcd->board->delay) { - dev_err(hcd->self.controller, "No platform delay function given\n"); - retval = -ENODEV; - goto err6; - } -#endif - -#ifdef CONFIG_ARM - if (isp1362_hcd->board) - set_irq_type(irq, isp1362_hcd->board->int_act_high ? IRQT_RISING : IRQT_FALLING); -#endif - - retval = usb_add_hcd(hcd, irq, IRQF_TRIGGER_LOW | IRQF_DISABLED | IRQF_SHARED); - if (retval != 0) - goto err6; - pr_info("%s, irq %d\n", hcd->product_desc, irq); - - create_debug_file(isp1362_hcd); - - return 0; - - err6: - DBG(0, "%s: Freeing dev %08x\n", __func__, (u32)isp1362_hcd); - usb_put_hcd(hcd); - err5: - DBG(0, "%s: Unmapping data_reg @ %08x\n", __func__, (u32)data_reg); - iounmap(data_reg); - err4: - DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)data->start); - release_mem_region(data->start, resource_len(data)); - err3: - DBG(0, "%s: Unmapping addr_reg @ %08x\n", __func__, (u32)addr_reg); - iounmap(addr_reg); - err2: - DBG(0, "%s: Releasing mem region %08lx\n", __func__, (long unsigned int)addr->start); - release_mem_region(addr->start, resource_len(addr)); - err1: - pr_err("%s: init error, %d\n", __func__, retval); - - return retval; -} - -#ifdef CONFIG_PM -static int isp1362_suspend(struct platform_device *pdev, pm_message_t state) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - unsigned long flags; - int retval = 0; - - DBG(0, "%s: Suspending device\n", __func__); - - if (state.event == PM_EVENT_FREEZE) { - DBG(0, "%s: Suspending root hub\n", __func__); - retval = isp1362_bus_suspend(hcd); - } else { - DBG(0, "%s: Suspending RH ports\n", __func__); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_reg32(isp1362_hcd, HCRHSTATUS, RH_HS_LPS); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - } - if (retval == 0) - pdev->dev.power.power_state = state; - return retval; -} - -static int isp1362_resume(struct platform_device *pdev) -{ - struct usb_hcd *hcd = platform_get_drvdata(pdev); - struct isp1362_hcd *isp1362_hcd = hcd_to_isp1362_hcd(hcd); - unsigned long flags; - - DBG(0, "%s: Resuming\n", __func__); - - if (pdev->dev.power.power_state.event == PM_EVENT_SUSPEND) { - DBG(0, "%s: Resume RH ports\n", __func__); - spin_lock_irqsave(&isp1362_hcd->lock, flags); - isp1362_write_reg32(isp1362_hcd, HCRHSTATUS, RH_HS_LPSC); - spin_unlock_irqrestore(&isp1362_hcd->lock, flags); - return 0; - } - - pdev->dev.power.power_state = PMSG_ON; - - return isp1362_bus_resume(isp1362_hcd_to_hcd(isp1362_hcd)); -} -#else -#define isp1362_suspend NULL -#define isp1362_resume NULL -#endif - -static struct platform_driver isp1362_driver = { - .probe = isp1362_probe, - .remove = __devexit_p(isp1362_remove), - - .suspend = isp1362_suspend, - .resume = isp1362_resume, - .driver = { - .name = (char *)hcd_name, - .owner = THIS_MODULE, - }, -}; - -/*-------------------------------------------------------------------------*/ - -static int __init isp1362_init(void) -{ - if (usb_disabled()) - return -ENODEV; - pr_info("driver %s, %s\n", hcd_name, DRIVER_VERSION); - return platform_driver_register(&isp1362_driver); -} -module_init(isp1362_init); - -static void __exit isp1362_cleanup(void) -{ - platform_driver_unregister(&isp1362_driver); -} -module_exit(isp1362_cleanup); diff --git a/trunk/drivers/usb/host/isp1362.h b/trunk/drivers/usb/host/isp1362.h deleted file mode 100644 index fe60f62a32f3..000000000000 --- a/trunk/drivers/usb/host/isp1362.h +++ /dev/null @@ -1,1079 +0,0 @@ -/* - * ISP1362 HCD (Host Controller Driver) for USB. - * - * COPYRIGHT (C) by L. Wassmann - */ - -/* ------------------------------------------------------------------------- */ -/* - * Platform specific compile time options - */ -#if defined(CONFIG_ARCH_KARO) -#include -#include -#include - -#define USE_32BIT 1 - - -/* These options are mutually eclusive */ -#define USE_PLATFORM_DELAY 1 -#define USE_NDELAY 0 -/* - * MAX_ROOT_PORTS: Number of downstream ports - * - * The chip has two USB ports, one of which can be configured as - * an USB device port, so the value of this constant is implementation - * specific. - */ -#define MAX_ROOT_PORTS 2 -#define DUMMY_DELAY_ACCESS do {} while (0) - -/* insert platform specific definitions for other machines here */ -#elif defined(CONFIG_BLACKFIN) - -#include -#define USE_32BIT 0 -#define MAX_ROOT_PORTS 2 -#define USE_PLATFORM_DELAY 0 -#define USE_NDELAY 1 - -#define DUMMY_DELAY_ACCESS \ - do { \ - bfin_read16(ASYNC_BANK0_BASE); \ - bfin_read16(ASYNC_BANK0_BASE); \ - bfin_read16(ASYNC_BANK0_BASE); \ - } while (0) - -#undef insw -#undef outsw - -#define insw delayed_insw -#define outsw delayed_outsw - -static inline void delayed_outsw(unsigned int addr, void *buf, int len) -{ - unsigned short *bp = (unsigned short *)buf; - while (len--) { - DUMMY_DELAY_ACCESS; - outw(*bp++, addr); - } -} - -static inline void delayed_insw(unsigned int addr, void *buf, int len) -{ - unsigned short *bp = (unsigned short *)buf; - while (len--) { - DUMMY_DELAY_ACCESS; - *bp++ = inw((void *)addr); - } -} - -#else - -#define MAX_ROOT_PORTS 2 - -#define USE_32BIT 0 - -/* These options are mutually eclusive */ -#define USE_PLATFORM_DELAY 0 -#define USE_NDELAY 0 - -#define DUMMY_DELAY_ACCESS do {} while (0) - -#endif - - -/* ------------------------------------------------------------------------- */ - -#define USB_RESET_WIDTH 50 -#define MAX_XFER_SIZE 1023 - -/* Buffer sizes */ -#define ISP1362_BUF_SIZE 4096 -#define ISP1362_ISTL_BUFSIZE 512 -#define ISP1362_INTL_BLKSIZE 64 -#define ISP1362_INTL_BUFFERS 16 -#define ISP1362_ATL_BLKSIZE 64 - -#define ISP1362_REG_WRITE_OFFSET 0x80 - -#ifdef ISP1362_DEBUG -typedef const unsigned int isp1362_reg_t; - -#define REG_WIDTH_16 0x000 -#define REG_WIDTH_32 0x100 -#define REG_WIDTH_MASK 0x100 -#define REG_NO_MASK 0x0ff - -#define REG_ACCESS_R 0x200 -#define REG_ACCESS_W 0x400 -#define REG_ACCESS_RW 0x600 -#define REG_ACCESS_MASK 0x600 - -#define ISP1362_REG_NO(r) ((r) & REG_NO_MASK) - -#define _BUG_ON(x) BUG_ON(x) -#define _WARN_ON(x) WARN_ON(x) - -#define ISP1362_REG(name, addr, width, rw) \ -static isp1362_reg_t ISP1362_REG_##name = ((addr) | (width) | (rw)) - -#define REG_ACCESS_TEST(r) BUG_ON(((r) & ISP1362_REG_WRITE_OFFSET) && !((r) & REG_ACCESS_W)) -#define REG_WIDTH_TEST(r, w) BUG_ON(((r) & REG_WIDTH_MASK) != (w)) -#else -typedef const unsigned char isp1362_reg_t; -#define ISP1362_REG_NO(r) (r) -#define _BUG_ON(x) do {} while (0) -#define _WARN_ON(x) do {} while (0) - -#define ISP1362_REG(name, addr, width, rw) \ -static isp1362_reg_t ISP1362_REG_##name = addr - -#define REG_ACCESS_TEST(r) do {} while (0) -#define REG_WIDTH_TEST(r, w) do {} while (0) -#endif - -/* OHCI compatible registers */ -/* - * Note: Some of the ISP1362 'OHCI' registers implement only - * a subset of the bits defined in the OHCI spec. - * - * Bitmasks for the individual bits of these registers are defined in "ohci.h" - */ -ISP1362_REG(HCREVISION, 0x00, REG_WIDTH_32, REG_ACCESS_R); -ISP1362_REG(HCCONTROL, 0x01, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCCMDSTAT, 0x02, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCINTSTAT, 0x03, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCINTENB, 0x04, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCINTDIS, 0x05, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCFMINTVL, 0x0d, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCFMREM, 0x0e, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCFMNUM, 0x0f, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCLSTHRESH, 0x11, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCRHDESCA, 0x12, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCRHDESCB, 0x13, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCRHSTATUS, 0x14, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCRHPORT1, 0x15, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCRHPORT2, 0x16, REG_WIDTH_32, REG_ACCESS_RW); - -/* Philips ISP1362 specific registers */ -ISP1362_REG(HCHWCFG, 0x20, REG_WIDTH_16, REG_ACCESS_RW); -#define HCHWCFG_DISABLE_SUSPEND (1 << 15) -#define HCHWCFG_GLOBAL_PWRDOWN (1 << 14) -#define HCHWCFG_PULLDOWN_DS2 (1 << 13) -#define HCHWCFG_PULLDOWN_DS1 (1 << 12) -#define HCHWCFG_CLKNOTSTOP (1 << 11) -#define HCHWCFG_ANALOG_OC (1 << 10) -#define HCHWCFG_ONEINT (1 << 9) -#define HCHWCFG_DACK_MODE (1 << 8) -#define HCHWCFG_ONEDMA (1 << 7) -#define HCHWCFG_DACK_POL (1 << 6) -#define HCHWCFG_DREQ_POL (1 << 5) -#define HCHWCFG_DBWIDTH_MASK (0x03 << 3) -#define HCHWCFG_DBWIDTH(n) (((n) << 3) & HCHWCFG_DBWIDTH_MASK) -#define HCHWCFG_INT_POL (1 << 2) -#define HCHWCFG_INT_TRIGGER (1 << 1) -#define HCHWCFG_INT_ENABLE (1 << 0) - -ISP1362_REG(HCDMACFG, 0x21, REG_WIDTH_16, REG_ACCESS_RW); -#define HCDMACFG_CTR_ENABLE (1 << 7) -#define HCDMACFG_BURST_LEN_MASK (0x03 << 5) -#define HCDMACFG_BURST_LEN(n) (((n) << 5) & HCDMACFG_BURST_LEN_MASK) -#define HCDMACFG_BURST_LEN_1 HCDMACFG_BURST_LEN(0) -#define HCDMACFG_BURST_LEN_4 HCDMACFG_BURST_LEN(1) -#define HCDMACFG_BURST_LEN_8 HCDMACFG_BURST_LEN(2) -#define HCDMACFG_DMA_ENABLE (1 << 4) -#define HCDMACFG_BUF_TYPE_MASK (0x07 << 1) -#define HCDMACFG_BUF_TYPE(n) (((n) << 1) & HCDMACFG_BUF_TYPE_MASK) -#define HCDMACFG_BUF_ISTL0 HCDMACFG_BUF_TYPE(0) -#define HCDMACFG_BUF_ISTL1 HCDMACFG_BUF_TYPE(1) -#define HCDMACFG_BUF_INTL HCDMACFG_BUF_TYPE(2) -#define HCDMACFG_BUF_ATL HCDMACFG_BUF_TYPE(3) -#define HCDMACFG_BUF_DIRECT HCDMACFG_BUF_TYPE(4) -#define HCDMACFG_DMA_RW_SELECT (1 << 0) - -ISP1362_REG(HCXFERCTR, 0x22, REG_WIDTH_16, REG_ACCESS_RW); - -ISP1362_REG(HCuPINT, 0x24, REG_WIDTH_16, REG_ACCESS_RW); -#define HCuPINT_SOF (1 << 0) -#define HCuPINT_ISTL0 (1 << 1) -#define HCuPINT_ISTL1 (1 << 2) -#define HCuPINT_EOT (1 << 3) -#define HCuPINT_OPR (1 << 4) -#define HCuPINT_SUSP (1 << 5) -#define HCuPINT_CLKRDY (1 << 6) -#define HCuPINT_INTL (1 << 7) -#define HCuPINT_ATL (1 << 8) -#define HCuPINT_OTG (1 << 9) - -ISP1362_REG(HCuPINTENB, 0x25, REG_WIDTH_16, REG_ACCESS_RW); -/* same bit definitions apply as for HCuPINT */ - -ISP1362_REG(HCCHIPID, 0x27, REG_WIDTH_16, REG_ACCESS_R); -#define HCCHIPID_MASK 0xff00 -#define HCCHIPID_MAGIC 0x3600 - -ISP1362_REG(HCSCRATCH, 0x28, REG_WIDTH_16, REG_ACCESS_RW); - -ISP1362_REG(HCSWRES, 0x29, REG_WIDTH_16, REG_ACCESS_W); -#define HCSWRES_MAGIC 0x00f6 - -ISP1362_REG(HCBUFSTAT, 0x2c, REG_WIDTH_16, REG_ACCESS_RW); -#define HCBUFSTAT_ISTL0_FULL (1 << 0) -#define HCBUFSTAT_ISTL1_FULL (1 << 1) -#define HCBUFSTAT_INTL_ACTIVE (1 << 2) -#define HCBUFSTAT_ATL_ACTIVE (1 << 3) -#define HCBUFSTAT_RESET_HWPP (1 << 4) -#define HCBUFSTAT_ISTL0_ACTIVE (1 << 5) -#define HCBUFSTAT_ISTL1_ACTIVE (1 << 6) -#define HCBUFSTAT_ISTL0_DONE (1 << 8) -#define HCBUFSTAT_ISTL1_DONE (1 << 9) -#define HCBUFSTAT_PAIRED_PTDPP (1 << 10) - -ISP1362_REG(HCDIRADDR, 0x32, REG_WIDTH_32, REG_ACCESS_RW); -#define HCDIRADDR_ADDR_MASK 0x0000ffff -#define HCDIRADDR_ADDR(n) (((n) << 0) & HCDIRADDR_ADDR_MASK) -#define HCDIRADDR_COUNT_MASK 0xffff0000 -#define HCDIRADDR_COUNT(n) (((n) << 16) & HCDIRADDR_COUNT_MASK) -ISP1362_REG(HCDIRDATA, 0x45, REG_WIDTH_16, REG_ACCESS_RW); - -ISP1362_REG(HCISTLBUFSZ, 0x30, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCISTL0PORT, 0x40, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCISTL1PORT, 0x42, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCISTLRATE, 0x47, REG_WIDTH_16, REG_ACCESS_RW); - -ISP1362_REG(HCINTLBUFSZ, 0x33, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCINTLPORT, 0x43, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCINTLBLKSZ, 0x53, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCINTLDONE, 0x17, REG_WIDTH_32, REG_ACCESS_R); -ISP1362_REG(HCINTLSKIP, 0x18, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCINTLLAST, 0x19, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCINTLCURR, 0x1a, REG_WIDTH_16, REG_ACCESS_R); - -ISP1362_REG(HCATLBUFSZ, 0x34, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCATLPORT, 0x44, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCATLBLKSZ, 0x54, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCATLDONE, 0x1b, REG_WIDTH_32, REG_ACCESS_R); -ISP1362_REG(HCATLSKIP, 0x1c, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCATLLAST, 0x1d, REG_WIDTH_32, REG_ACCESS_RW); -ISP1362_REG(HCATLCURR, 0x1e, REG_WIDTH_16, REG_ACCESS_R); - -ISP1362_REG(HCATLDTC, 0x51, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(HCATLDTCTO, 0x52, REG_WIDTH_16, REG_ACCESS_RW); - - -ISP1362_REG(OTGCONTROL, 0x62, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(OTGSTATUS, 0x67, REG_WIDTH_16, REG_ACCESS_R); -ISP1362_REG(OTGINT, 0x68, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(OTGINTENB, 0x69, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(OTGTIMER, 0x6A, REG_WIDTH_16, REG_ACCESS_RW); -ISP1362_REG(OTGALTTMR, 0x6C, REG_WIDTH_16, REG_ACCESS_RW); - -/* Philips transfer descriptor, cpu-endian */ -struct ptd { - u16 count; -#define PTD_COUNT_MSK (0x3ff << 0) -#define PTD_TOGGLE_MSK (1 << 10) -#define PTD_ACTIVE_MSK (1 << 11) -#define PTD_CC_MSK (0xf << 12) - u16 mps; -#define PTD_MPS_MSK (0x3ff << 0) -#define PTD_SPD_MSK (1 << 10) -#define PTD_LAST_MSK (1 << 11) -#define PTD_EP_MSK (0xf << 12) - u16 len; -#define PTD_LEN_MSK (0x3ff << 0) -#define PTD_DIR_MSK (3 << 10) -#define PTD_DIR_SETUP (0) -#define PTD_DIR_OUT (1) -#define PTD_DIR_IN (2) - u16 faddr; -#define PTD_FA_MSK (0x7f << 0) -/* PTD Byte 7: [StartingFrame (if ISO PTD) | StartingFrame[0..4], PollingRate[0..2] (if INT PTD)] */ -#define PTD_SF_ISO_MSK (0xff << 8) -#define PTD_SF_INT_MSK (0x1f << 8) -#define PTD_PR_MSK (0x07 << 13) -} __attribute__ ((packed, aligned(2))); -#define PTD_HEADER_SIZE sizeof(struct ptd) - -/* ------------------------------------------------------------------------- */ -/* Copied from ohci.h: */ -/* - * Hardware transfer status codes -- CC from PTD - */ -#define PTD_CC_NOERROR 0x00 -#define PTD_CC_CRC 0x01 -#define PTD_CC_BITSTUFFING 0x02 -#define PTD_CC_DATATOGGLEM 0x03 -#define PTD_CC_STALL 0x04 -#define PTD_DEVNOTRESP 0x05 -#define PTD_PIDCHECKFAIL 0x06 -#define PTD_UNEXPECTEDPID 0x07 -#define PTD_DATAOVERRUN 0x08 -#define PTD_DATAUNDERRUN 0x09 - /* 0x0A, 0x0B reserved for hardware */ -#define PTD_BUFFEROVERRUN 0x0C -#define PTD_BUFFERUNDERRUN 0x0D - /* 0x0E, 0x0F reserved for HCD */ -#define PTD_NOTACCESSED 0x0F - - -/* map OHCI TD status codes (CC) to errno values */ -static const int cc_to_error[16] = { - /* No Error */ 0, - /* CRC Error */ -EILSEQ, - /* Bit Stuff */ -EPROTO, - /* Data Togg */ -EILSEQ, - /* Stall */ -EPIPE, - /* DevNotResp */ -ETIMEDOUT, - /* PIDCheck */ -EPROTO, - /* UnExpPID */ -EPROTO, - /* DataOver */ -EOVERFLOW, - /* DataUnder */ -EREMOTEIO, - /* (for hw) */ -EIO, - /* (for hw) */ -EIO, - /* BufferOver */ -ECOMM, - /* BuffUnder */ -ENOSR, - /* (for HCD) */ -EALREADY, - /* (for HCD) */ -EALREADY -}; - - -/* - * HcControl (control) register masks - */ -#define OHCI_CTRL_HCFS (3 << 6) /* host controller functional state */ -#define OHCI_CTRL_RWC (1 << 9) /* remote wakeup connected */ -#define OHCI_CTRL_RWE (1 << 10) /* remote wakeup enable */ - -/* pre-shifted values for HCFS */ -# define OHCI_USB_RESET (0 << 6) -# define OHCI_USB_RESUME (1 << 6) -# define OHCI_USB_OPER (2 << 6) -# define OHCI_USB_SUSPEND (3 << 6) - -/* - * HcCommandStatus (cmdstatus) register masks - */ -#define OHCI_HCR (1 << 0) /* host controller reset */ -#define OHCI_SOC (3 << 16) /* scheduling overrun count */ - -/* - * masks used with interrupt registers: - * HcInterruptStatus (intrstatus) - * HcInterruptEnable (intrenable) - * HcInterruptDisable (intrdisable) - */ -#define OHCI_INTR_SO (1 << 0) /* scheduling overrun */ -#define OHCI_INTR_WDH (1 << 1) /* writeback of done_head */ -#define OHCI_INTR_SF (1 << 2) /* start frame */ -#define OHCI_INTR_RD (1 << 3) /* resume detect */ -#define OHCI_INTR_UE (1 << 4) /* unrecoverable error */ -#define OHCI_INTR_FNO (1 << 5) /* frame number overflow */ -#define OHCI_INTR_RHSC (1 << 6) /* root hub status change */ -#define OHCI_INTR_OC (1 << 30) /* ownership change */ -#define OHCI_INTR_MIE (1 << 31) /* master interrupt enable */ - -/* roothub.portstatus [i] bits */ -#define RH_PS_CCS 0x00000001 /* current connect status */ -#define RH_PS_PES 0x00000002 /* port enable status*/ -#define RH_PS_PSS 0x00000004 /* port suspend status */ -#define RH_PS_POCI 0x00000008 /* port over current indicator */ -#define RH_PS_PRS 0x00000010 /* port reset status */ -#define RH_PS_PPS 0x00000100 /* port power status */ -#define RH_PS_LSDA 0x00000200 /* low speed device attached */ -#define RH_PS_CSC 0x00010000 /* connect status change */ -#define RH_PS_PESC 0x00020000 /* port enable status change */ -#define RH_PS_PSSC 0x00040000 /* port suspend status change */ -#define RH_PS_OCIC 0x00080000 /* over current indicator change */ -#define RH_PS_PRSC 0x00100000 /* port reset status change */ - -/* roothub.status bits */ -#define RH_HS_LPS 0x00000001 /* local power status */ -#define RH_HS_OCI 0x00000002 /* over current indicator */ -#define RH_HS_DRWE 0x00008000 /* device remote wakeup enable */ -#define RH_HS_LPSC 0x00010000 /* local power status change */ -#define RH_HS_OCIC 0x00020000 /* over current indicator change */ -#define RH_HS_CRWE 0x80000000 /* clear remote wakeup enable */ - -/* roothub.b masks */ -#define RH_B_DR 0x0000ffff /* device removable flags */ -#define RH_B_PPCM 0xffff0000 /* port power control mask */ - -/* roothub.a masks */ -#define RH_A_NDP (0xff << 0) /* number of downstream ports */ -#define RH_A_PSM (1 << 8) /* power switching mode */ -#define RH_A_NPS (1 << 9) /* no power switching */ -#define RH_A_DT (1 << 10) /* device type (mbz) */ -#define RH_A_OCPM (1 << 11) /* over current protection mode */ -#define RH_A_NOCP (1 << 12) /* no over current protection */ -#define RH_A_POTPGT (0xff << 24) /* power on to power good time */ - -#define FI 0x2edf /* 12000 bits per frame (-1) */ -#define FSMP(fi) (0x7fff & ((6 * ((fi) - 210)) / 7)) -#define LSTHRESH 0x628 /* lowspeed bit threshold */ - -/* ------------------------------------------------------------------------- */ - -/* PTD accessor macros. */ -#define PTD_GET_COUNT(p) (((p)->count & PTD_COUNT_MSK) >> 0) -#define PTD_COUNT(v) (((v) << 0) & PTD_COUNT_MSK) -#define PTD_GET_TOGGLE(p) (((p)->count & PTD_TOGGLE_MSK) >> 10) -#define PTD_TOGGLE(v) (((v) << 10) & PTD_TOGGLE_MSK) -#define PTD_GET_ACTIVE(p) (((p)->count & PTD_ACTIVE_MSK) >> 11) -#define PTD_ACTIVE(v) (((v) << 11) & PTD_ACTIVE_MSK) -#define PTD_GET_CC(p) (((p)->count & PTD_CC_MSK) >> 12) -#define PTD_CC(v) (((v) << 12) & PTD_CC_MSK) -#define PTD_GET_MPS(p) (((p)->mps & PTD_MPS_MSK) >> 0) -#define PTD_MPS(v) (((v) << 0) & PTD_MPS_MSK) -#define PTD_GET_SPD(p) (((p)->mps & PTD_SPD_MSK) >> 10) -#define PTD_SPD(v) (((v) << 10) & PTD_SPD_MSK) -#define PTD_GET_LAST(p) (((p)->mps & PTD_LAST_MSK) >> 11) -#define PTD_LAST(v) (((v) << 11) & PTD_LAST_MSK) -#define PTD_GET_EP(p) (((p)->mps & PTD_EP_MSK) >> 12) -#define PTD_EP(v) (((v) << 12) & PTD_EP_MSK) -#define PTD_GET_LEN(p) (((p)->len & PTD_LEN_MSK) >> 0) -#define PTD_LEN(v) (((v) << 0) & PTD_LEN_MSK) -#define PTD_GET_DIR(p) (((p)->len & PTD_DIR_MSK) >> 10) -#define PTD_DIR(v) (((v) << 10) & PTD_DIR_MSK) -#define PTD_GET_FA(p) (((p)->faddr & PTD_FA_MSK) >> 0) -#define PTD_FA(v) (((v) << 0) & PTD_FA_MSK) -#define PTD_GET_SF_INT(p) (((p)->faddr & PTD_SF_INT_MSK) >> 8) -#define PTD_SF_INT(v) (((v) << 8) & PTD_SF_INT_MSK) -#define PTD_GET_SF_ISO(p) (((p)->faddr & PTD_SF_ISO_MSK) >> 8) -#define PTD_SF_ISO(v) (((v) << 8) & PTD_SF_ISO_MSK) -#define PTD_GET_PR(p) (((p)->faddr & PTD_PR_MSK) >> 13) -#define PTD_PR(v) (((v) << 13) & PTD_PR_MSK) - -#define LOG2_PERIODIC_SIZE 5 /* arbitrary; this matches OHCI */ -#define PERIODIC_SIZE (1 << LOG2_PERIODIC_SIZE) - -struct isp1362_ep { - struct usb_host_endpoint *hep; - struct usb_device *udev; - - /* philips transfer descriptor */ - struct ptd ptd; - - u8 maxpacket; - u8 epnum; - u8 nextpid; - u16 error_count; - u16 length; /* of current packet */ - s16 ptd_offset; /* buffer offset in ISP1362 where - PTD has been stored - (for access thru HCDIRDATA) */ - int ptd_index; - int num_ptds; - void *data; /* to databuf */ - /* queue of active EPs (the ones transmitted to the chip) */ - struct list_head active; - - /* periodic schedule */ - u8 branch; - u16 interval; - u16 load; - u16 last_iso; - - /* async schedule */ - struct list_head schedule; /* list of all EPs that need processing */ - struct list_head remove_list; - int num_req; -}; - -struct isp1362_ep_queue { - struct list_head active; /* list of PTDs currently processed by HC */ - atomic_t finishing; - unsigned long buf_map; - unsigned long skip_map; - int free_ptd; - u16 buf_start; - u16 buf_size; - u16 blk_size; /* PTD buffer block size for ATL and INTL */ - u8 buf_count; - u8 buf_avail; - char name[16]; - - /* for statistical tracking */ - u8 stat_maxptds; /* Max # of ptds seen simultaneously in fifo */ - u8 ptd_count; /* number of ptds submitted to this queue */ -}; - -struct isp1362_hcd { - spinlock_t lock; - void __iomem *addr_reg; - void __iomem *data_reg; - - struct isp1362_platform_data *board; - - struct proc_dir_entry *pde; - unsigned long stat1, stat2, stat4, stat8, stat16; - - /* HC registers */ - u32 intenb; /* "OHCI" interrupts */ - u16 irqenb; /* uP interrupts */ - - /* Root hub registers */ - u32 rhdesca; - u32 rhdescb; - u32 rhstatus; - u32 rhport[MAX_ROOT_PORTS]; - unsigned long next_statechange; - - /* HC control reg shadow copy */ - u32 hc_control; - - /* async schedule: control, bulk */ - struct list_head async; - - /* periodic schedule: int */ - u16 load[PERIODIC_SIZE]; - struct list_head periodic; - u16 fmindex; - - /* periodic schedule: isochronous */ - struct list_head isoc; - int istl_flip:1; - int irq_active:1; - - /* Schedules for the current frame */ - struct isp1362_ep_queue atl_queue; - struct isp1362_ep_queue intl_queue; - struct isp1362_ep_queue istl_queue[2]; - - /* list of PTDs retrieved from HC */ - struct list_head remove_list; - enum { - ISP1362_INT_SOF, - ISP1362_INT_ISTL0, - ISP1362_INT_ISTL1, - ISP1362_INT_EOT, - ISP1362_INT_OPR, - ISP1362_INT_SUSP, - ISP1362_INT_CLKRDY, - ISP1362_INT_INTL, - ISP1362_INT_ATL, - ISP1362_INT_OTG, - NUM_ISP1362_IRQS - } IRQ_NAMES; - unsigned int irq_stat[NUM_ISP1362_IRQS]; - int req_serial; -}; - -static inline const char *ISP1362_INT_NAME(int n) -{ - switch (n) { - case ISP1362_INT_SOF: return "SOF"; - case ISP1362_INT_ISTL0: return "ISTL0"; - case ISP1362_INT_ISTL1: return "ISTL1"; - case ISP1362_INT_EOT: return "EOT"; - case ISP1362_INT_OPR: return "OPR"; - case ISP1362_INT_SUSP: return "SUSP"; - case ISP1362_INT_CLKRDY: return "CLKRDY"; - case ISP1362_INT_INTL: return "INTL"; - case ISP1362_INT_ATL: return "ATL"; - case ISP1362_INT_OTG: return "OTG"; - default: return "unknown"; - } -} - -static inline void ALIGNSTAT(struct isp1362_hcd *isp1362_hcd, void *ptr) -{ - unsigned p = (unsigned)ptr; - if (!(p & 0xf)) - isp1362_hcd->stat16++; - else if (!(p & 0x7)) - isp1362_hcd->stat8++; - else if (!(p & 0x3)) - isp1362_hcd->stat4++; - else if (!(p & 0x1)) - isp1362_hcd->stat2++; - else - isp1362_hcd->stat1++; -} - -static inline struct isp1362_hcd *hcd_to_isp1362_hcd(struct usb_hcd *hcd) -{ - return (struct isp1362_hcd *) (hcd->hcd_priv); -} - -static inline struct usb_hcd *isp1362_hcd_to_hcd(struct isp1362_hcd *isp1362_hcd) -{ - return container_of((void *)isp1362_hcd, struct usb_hcd, hcd_priv); -} - -#define frame_before(f1, f2) ((s16)((u16)f1 - (u16)f2) < 0) - -/* - * ISP1362 HW Interface - */ - -#ifdef ISP1362_DEBUG -#define DBG(level, fmt...) \ - do { \ - if (dbg_level > level) \ - pr_debug(fmt); \ - } while (0) -#define _DBG(level, fmt...) \ - do { \ - if (dbg_level > level) \ - printk(fmt); \ - } while (0) -#else -#define DBG(fmt...) do {} while (0) -#define _DBG DBG -#endif - -#ifdef VERBOSE -# define VDBG(fmt...) DBG(3, fmt) -#else -# define VDBG(fmt...) do {} while (0) -#endif - -#ifdef REGISTERS -# define RDBG(fmt...) DBG(1, fmt) -#else -# define RDBG(fmt...) do {} while (0) -#endif - -#ifdef URB_TRACE -#define URB_DBG(fmt...) DBG(0, fmt) -#else -#define URB_DBG(fmt...) do {} while (0) -#endif - - -#if USE_PLATFORM_DELAY -#if USE_NDELAY -#error USE_PLATFORM_DELAY and USE_NDELAY defined simultaneously. -#endif -#define isp1362_delay(h, d) (h)->board->delay(isp1362_hcd_to_hcd(h)->self.controller, d) -#elif USE_NDELAY -#define isp1362_delay(h, d) ndelay(d) -#else -#define isp1362_delay(h, d) do {} while (0) -#endif - -#define get_urb(ep) ({ \ - BUG_ON(list_empty(&ep->hep->urb_list)); \ - container_of(ep->hep->urb_list.next, struct urb, urb_list); \ -}) - -/* basic access functions for ISP1362 chip registers */ -/* NOTE: The contents of the address pointer register cannot be read back! The driver must ensure, - * that all register accesses are performed with interrupts disabled, since the interrupt - * handler has no way of restoring the previous state. - */ -static void isp1362_write_addr(struct isp1362_hcd *isp1362_hcd, isp1362_reg_t reg) -{ - /*_BUG_ON((reg & ISP1362_REG_WRITE_OFFSET) && !(reg & REG_ACCESS_W));*/ - REG_ACCESS_TEST(reg); - _BUG_ON(!irqs_disabled()); - DUMMY_DELAY_ACCESS; - writew(ISP1362_REG_NO(reg), isp1362_hcd->addr_reg); - DUMMY_DELAY_ACCESS; - isp1362_delay(isp1362_hcd, 1); -} - -static void isp1362_write_data16(struct isp1362_hcd *isp1362_hcd, u16 val) -{ - _BUG_ON(!irqs_disabled()); - DUMMY_DELAY_ACCESS; - writew(val, isp1362_hcd->data_reg); -} - -static u16 isp1362_read_data16(struct isp1362_hcd *isp1362_hcd) -{ - u16 val; - - _BUG_ON(!irqs_disabled()); - DUMMY_DELAY_ACCESS; - val = readw(isp1362_hcd->data_reg); - - return val; -} - -static void isp1362_write_data32(struct isp1362_hcd *isp1362_hcd, u32 val) -{ - _BUG_ON(!irqs_disabled()); -#if USE_32BIT - DUMMY_DELAY_ACCESS; - writel(val, isp1362_hcd->data_reg); -#else - DUMMY_DELAY_ACCESS; - writew((u16)val, isp1362_hcd->data_reg); - DUMMY_DELAY_ACCESS; - writew(val >> 16, isp1362_hcd->data_reg); -#endif -} - -static u32 isp1362_read_data32(struct isp1362_hcd *isp1362_hcd) -{ - u32 val; - - _BUG_ON(!irqs_disabled()); -#if USE_32BIT - DUMMY_DELAY_ACCESS; - val = readl(isp1362_hcd->data_reg); -#else - DUMMY_DELAY_ACCESS; - val = (u32)readw(isp1362_hcd->data_reg); - DUMMY_DELAY_ACCESS; - val |= (u32)readw(isp1362_hcd->data_reg) << 16; -#endif - return val; -} - -/* use readsw/writesw to access the fifo whenever possible */ -/* assume HCDIRDATA or XFERCTR & addr_reg have been set up */ -static void isp1362_read_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 len) -{ - u8 *dp = buf; - u16 data; - - if (!len) - return; - - _BUG_ON(!irqs_disabled()); - - RDBG("%s: Reading %d byte from fifo to mem @ %p\n", __func__, len, buf); -#if USE_32BIT - if (len >= 4) { - RDBG("%s: Using readsl for %d dwords\n", __func__, len >> 2); - readsl(isp1362_hcd->data_reg, dp, len >> 2); - dp += len & ~3; - len &= 3; - } -#endif - if (len >= 2) { - RDBG("%s: Using readsw for %d words\n", __func__, len >> 1); - insw((unsigned long)isp1362_hcd->data_reg, dp, len >> 1); - dp += len & ~1; - len &= 1; - } - - BUG_ON(len & ~1); - if (len > 0) { - data = isp1362_read_data16(isp1362_hcd); - RDBG("%s: Reading trailing byte %02x to mem @ %08x\n", __func__, - (u8)data, (u32)dp); - *dp = (u8)data; - } -} - -static void isp1362_write_fifo(struct isp1362_hcd *isp1362_hcd, void *buf, u16 len) -{ - u8 *dp = buf; - u16 data; - - if (!len) - return; - - if ((unsigned)dp & 0x1) { - /* not aligned */ - for (; len > 1; len -= 2) { - data = *dp++; - data |= *dp++ << 8; - isp1362_write_data16(isp1362_hcd, data); - } - if (len) - isp1362_write_data16(isp1362_hcd, *dp); - return; - } - - _BUG_ON(!irqs_disabled()); - - RDBG("%s: Writing %d byte to fifo from memory @%p\n", __func__, len, buf); -#if USE_32BIT - if (len >= 4) { - RDBG("%s: Using writesl for %d dwords\n", __func__, len >> 2); - writesl(isp1362_hcd->data_reg, dp, len >> 2); - dp += len & ~3; - len &= 3; - } -#endif - if (len >= 2) { - RDBG("%s: Using writesw for %d words\n", __func__, len >> 1); - outsw((unsigned long)isp1362_hcd->data_reg, dp, len >> 1); - dp += len & ~1; - len &= 1; - } - - BUG_ON(len & ~1); - if (len > 0) { - /* finally write any trailing byte; we don't need to care - * about the high byte of the last word written - */ - data = (u16)*dp; - RDBG("%s: Sending trailing byte %02x from mem @ %08x\n", __func__, - data, (u32)dp); - isp1362_write_data16(isp1362_hcd, data); - } -} - -#define isp1362_read_reg16(d, r) ({ \ - u16 __v; \ - REG_WIDTH_TEST(ISP1362_REG_##r, REG_WIDTH_16); \ - isp1362_write_addr(d, ISP1362_REG_##r); \ - __v = isp1362_read_data16(d); \ - RDBG("%s: Read %04x from %s[%02x]\n", __func__, __v, #r, \ - ISP1362_REG_NO(ISP1362_REG_##r)); \ - __v; \ -}) - -#define isp1362_read_reg32(d, r) ({ \ - u32 __v; \ - REG_WIDTH_TEST(ISP1362_REG_##r, REG_WIDTH_32); \ - isp1362_write_addr(d, ISP1362_REG_##r); \ - __v = isp1362_read_data32(d); \ - RDBG("%s: Read %08x from %s[%02x]\n", __func__, __v, #r, \ - ISP1362_REG_NO(ISP1362_REG_##r)); \ - __v; \ -}) - -#define isp1362_write_reg16(d, r, v) { \ - REG_WIDTH_TEST(ISP1362_REG_##r, REG_WIDTH_16); \ - isp1362_write_addr(d, (ISP1362_REG_##r) | ISP1362_REG_WRITE_OFFSET); \ - isp1362_write_data16(d, (u16)(v)); \ - RDBG("%s: Wrote %04x to %s[%02x]\n", __func__, (u16)(v), #r, \ - ISP1362_REG_NO(ISP1362_REG_##r)); \ -} - -#define isp1362_write_reg32(d, r, v) { \ - REG_WIDTH_TEST(ISP1362_REG_##r, REG_WIDTH_32); \ - isp1362_write_addr(d, (ISP1362_REG_##r) | ISP1362_REG_WRITE_OFFSET); \ - isp1362_write_data32(d, (u32)(v)); \ - RDBG("%s: Wrote %08x to %s[%02x]\n", __func__, (u32)(v), #r, \ - ISP1362_REG_NO(ISP1362_REG_##r)); \ -} - -#define isp1362_set_mask16(d, r, m) { \ - u16 __v; \ - __v = isp1362_read_reg16(d, r); \ - if ((__v | m) != __v) \ - isp1362_write_reg16(d, r, __v | m); \ -} - -#define isp1362_clr_mask16(d, r, m) { \ - u16 __v; \ - __v = isp1362_read_reg16(d, r); \ - if ((__v & ~m) != __v) \ - isp1362_write_reg16(d, r, __v & ~m); \ -} - -#define isp1362_set_mask32(d, r, m) { \ - u32 __v; \ - __v = isp1362_read_reg32(d, r); \ - if ((__v | m) != __v) \ - isp1362_write_reg32(d, r, __v | m); \ -} - -#define isp1362_clr_mask32(d, r, m) { \ - u32 __v; \ - __v = isp1362_read_reg32(d, r); \ - if ((__v & ~m) != __v) \ - isp1362_write_reg32(d, r, __v & ~m); \ -} - -#ifdef ISP1362_DEBUG -#define isp1362_show_reg(d, r) { \ - if ((ISP1362_REG_##r & REG_WIDTH_MASK) == REG_WIDTH_32) \ - DBG(0, "%-12s[%02x]: %08x\n", #r, \ - ISP1362_REG_NO(ISP1362_REG_##r), isp1362_read_reg32(d, r)); \ - else \ - DBG(0, "%-12s[%02x]: %04x\n", #r, \ - ISP1362_REG_NO(ISP1362_REG_##r), isp1362_read_reg16(d, r)); \ -} -#else -#define isp1362_show_reg(d, r) do {} while (0) -#endif - -static void __attribute__((__unused__)) isp1362_show_regs(struct isp1362_hcd *isp1362_hcd) -{ - isp1362_show_reg(isp1362_hcd, HCREVISION); - isp1362_show_reg(isp1362_hcd, HCCONTROL); - isp1362_show_reg(isp1362_hcd, HCCMDSTAT); - isp1362_show_reg(isp1362_hcd, HCINTSTAT); - isp1362_show_reg(isp1362_hcd, HCINTENB); - isp1362_show_reg(isp1362_hcd, HCFMINTVL); - isp1362_show_reg(isp1362_hcd, HCFMREM); - isp1362_show_reg(isp1362_hcd, HCFMNUM); - isp1362_show_reg(isp1362_hcd, HCLSTHRESH); - isp1362_show_reg(isp1362_hcd, HCRHDESCA); - isp1362_show_reg(isp1362_hcd, HCRHDESCB); - isp1362_show_reg(isp1362_hcd, HCRHSTATUS); - isp1362_show_reg(isp1362_hcd, HCRHPORT1); - isp1362_show_reg(isp1362_hcd, HCRHPORT2); - - isp1362_show_reg(isp1362_hcd, HCHWCFG); - isp1362_show_reg(isp1362_hcd, HCDMACFG); - isp1362_show_reg(isp1362_hcd, HCXFERCTR); - isp1362_show_reg(isp1362_hcd, HCuPINT); - - if (in_interrupt()) - DBG(0, "%-12s[%02x]: %04x\n", "HCuPINTENB", - ISP1362_REG_NO(ISP1362_REG_HCuPINTENB), isp1362_hcd->irqenb); - else - isp1362_show_reg(isp1362_hcd, HCuPINTENB); - isp1362_show_reg(isp1362_hcd, HCCHIPID); - isp1362_show_reg(isp1362_hcd, HCSCRATCH); - isp1362_show_reg(isp1362_hcd, HCBUFSTAT); - isp1362_show_reg(isp1362_hcd, HCDIRADDR); - /* Access would advance fifo - * isp1362_show_reg(isp1362_hcd, HCDIRDATA); - */ - isp1362_show_reg(isp1362_hcd, HCISTLBUFSZ); - isp1362_show_reg(isp1362_hcd, HCISTLRATE); - isp1362_show_reg(isp1362_hcd, HCINTLBUFSZ); - isp1362_show_reg(isp1362_hcd, HCINTLBLKSZ); - isp1362_show_reg(isp1362_hcd, HCINTLDONE); - isp1362_show_reg(isp1362_hcd, HCINTLSKIP); - isp1362_show_reg(isp1362_hcd, HCINTLLAST); - isp1362_show_reg(isp1362_hcd, HCINTLCURR); - isp1362_show_reg(isp1362_hcd, HCATLBUFSZ); - isp1362_show_reg(isp1362_hcd, HCATLBLKSZ); - /* only valid after ATL_DONE interrupt - * isp1362_show_reg(isp1362_hcd, HCATLDONE); - */ - isp1362_show_reg(isp1362_hcd, HCATLSKIP); - isp1362_show_reg(isp1362_hcd, HCATLLAST); - isp1362_show_reg(isp1362_hcd, HCATLCURR); - isp1362_show_reg(isp1362_hcd, HCATLDTC); - isp1362_show_reg(isp1362_hcd, HCATLDTCTO); -} - -static void isp1362_write_diraddr(struct isp1362_hcd *isp1362_hcd, u16 offset, u16 len) -{ - _BUG_ON(offset & 1); - _BUG_ON(offset >= ISP1362_BUF_SIZE); - _BUG_ON(len > ISP1362_BUF_SIZE); - _BUG_ON(offset + len > ISP1362_BUF_SIZE); - len = (len + 1) & ~1; - - isp1362_clr_mask16(isp1362_hcd, HCDMACFG, HCDMACFG_CTR_ENABLE); - isp1362_write_reg32(isp1362_hcd, HCDIRADDR, - HCDIRADDR_ADDR(offset) | HCDIRADDR_COUNT(len)); -} - -static void isp1362_read_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 offset, int len) -{ - _BUG_ON(offset & 1); - - isp1362_write_diraddr(isp1362_hcd, offset, len); - - DBG(3, "%s: Reading %d byte from buffer @%04x to memory @ %08x\n", __func__, - len, offset, (u32)buf); - - isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); - - isp1362_write_addr(isp1362_hcd, ISP1362_REG_HCDIRDATA); - - isp1362_read_fifo(isp1362_hcd, buf, len); - _WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); - isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); -} - -static void isp1362_write_buffer(struct isp1362_hcd *isp1362_hcd, void *buf, u16 offset, int len) -{ - _BUG_ON(offset & 1); - - isp1362_write_diraddr(isp1362_hcd, offset, len); - - DBG(3, "%s: Writing %d byte to buffer @%04x from memory @ %08x\n", __func__, - len, offset, (u32)buf); - - isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); - - isp1362_write_addr(isp1362_hcd, ISP1362_REG_HCDIRDATA | ISP1362_REG_WRITE_OFFSET); - isp1362_write_fifo(isp1362_hcd, buf, len); - - _WARN_ON(!(isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); - isp1362_write_reg16(isp1362_hcd, HCuPINT, HCuPINT_EOT); - _WARN_ON((isp1362_read_reg16(isp1362_hcd, HCuPINT) & HCuPINT_EOT)); -} - -static void __attribute__((unused)) dump_data(char *buf, int len) -{ - if (dbg_level > 0) { - int k; - int lf = 0; - - for (k = 0; k < len; ++k) { - if (!lf) - DBG(0, "%04x:", k); - printk(" %02x", ((u8 *) buf)[k]); - lf = 1; - if (!k) - continue; - if (k % 16 == 15) { - printk("\n"); - lf = 0; - continue; - } - if (k % 8 == 7) - printk(" "); - if (k % 4 == 3) - printk(" "); - } - if (lf) - printk("\n"); - } -} - -#if defined(ISP1362_DEBUG) && defined(PTD_TRACE) - -static void dump_ptd(struct ptd *ptd) -{ - DBG(0, "EP %p: CC=%x EP=%d DIR=%x CNT=%d LEN=%d MPS=%d TGL=%x ACT=%x FA=%d SPD=%x SF=%x PR=%x LST=%x\n", - container_of(ptd, struct isp1362_ep, ptd), - PTD_GET_CC(ptd), PTD_GET_EP(ptd), PTD_GET_DIR(ptd), - PTD_GET_COUNT(ptd), PTD_GET_LEN(ptd), PTD_GET_MPS(ptd), - PTD_GET_TOGGLE(ptd), PTD_GET_ACTIVE(ptd), PTD_GET_FA(ptd), - PTD_GET_SPD(ptd), PTD_GET_SF_INT(ptd), PTD_GET_PR(ptd), PTD_GET_LAST(ptd)); - DBG(0, " %04x %04x %04x %04x\n", ptd->count, ptd->mps, ptd->len, ptd->faddr); -} - -static void dump_ptd_out_data(struct ptd *ptd, u8 *buf) -{ - if (dbg_level > 0) { - if (PTD_GET_DIR(ptd) != PTD_DIR_IN && PTD_GET_LEN(ptd)) { - DBG(0, "--out->\n"); - dump_data(buf, PTD_GET_LEN(ptd)); - } - } -} - -static void dump_ptd_in_data(struct ptd *ptd, u8 *buf) -{ - if (dbg_level > 0) { - if (PTD_GET_DIR(ptd) == PTD_DIR_IN && PTD_GET_COUNT(ptd)) { - DBG(0, "<--in--\n"); - dump_data(buf, PTD_GET_COUNT(ptd)); - } - DBG(0, "-----\n"); - } -} - -static void dump_ptd_queue(struct isp1362_ep_queue *epq) -{ - struct isp1362_ep *ep; - int dbg = dbg_level; - - dbg_level = 1; - list_for_each_entry(ep, &epq->active, active) { - dump_ptd(&ep->ptd); - dump_data(ep->data, ep->length); - } - dbg_level = dbg; -} -#else -#define dump_ptd(ptd) do {} while (0) -#define dump_ptd_in_data(ptd, buf) do {} while (0) -#define dump_ptd_out_data(ptd, buf) do {} while (0) -#define dump_ptd_data(ptd, buf) do {} while (0) -#define dump_ptd_queue(epq) do {} while (0) -#endif diff --git a/trunk/drivers/usb/host/isp1760-hcd.c b/trunk/drivers/usb/host/isp1760-hcd.c index 9600a58299db..15438469f21a 100644 --- a/trunk/drivers/usb/host/isp1760-hcd.c +++ b/trunk/drivers/usb/host/isp1760-hcd.c @@ -386,10 +386,6 @@ static int isp1760_hc_setup(struct usb_hcd *hcd) hwmode |= HW_DACK_POL_HIGH; if (priv->devflags & ISP1760_FLAG_DREQ_POL_HIGH) hwmode |= HW_DREQ_POL_HIGH; - if (priv->devflags & ISP1760_FLAG_INTR_POL_HIGH) - hwmode |= HW_INTR_HIGH_ACT; - if (priv->devflags & ISP1760_FLAG_INTR_EDGE_TRIG) - hwmode |= HW_INTR_EDGE_TRIG; /* * We have to set this first in case we're in 16-bit mode. diff --git a/trunk/drivers/usb/host/isp1760-hcd.h b/trunk/drivers/usb/host/isp1760-hcd.h index 6931ef5c9650..462f4943cb1b 100644 --- a/trunk/drivers/usb/host/isp1760-hcd.h +++ b/trunk/drivers/usb/host/isp1760-hcd.h @@ -142,8 +142,6 @@ typedef void (packet_enqueue)(struct usb_hcd *hcd, struct isp1760_qh *qh, #define ISP1760_FLAG_DACK_POL_HIGH 0x00000010 /* DACK active high */ #define ISP1760_FLAG_DREQ_POL_HIGH 0x00000020 /* DREQ active high */ #define ISP1760_FLAG_ISP1761 0x00000040 /* Chip is ISP1761 */ -#define ISP1760_FLAG_INTR_POL_HIGH 0x00000080 /* Interrupt polarity active high */ -#define ISP1760_FLAG_INTR_EDGE_TRIG 0x00000100 /* Interrupt edge triggered */ /* chip memory management */ struct memory_chunk { diff --git a/trunk/drivers/usb/host/isp1760-if.c b/trunk/drivers/usb/host/isp1760-if.c index 1c9f977a5c9c..d4feebfc63bd 100644 --- a/trunk/drivers/usb/host/isp1760-if.c +++ b/trunk/drivers/usb/host/isp1760-if.c @@ -3,7 +3,6 @@ * Currently there is support for * - OpenFirmware * - PCI - * - PDEV (generic platform device centralized driver model) * * (c) 2007 Sebastian Siewior * @@ -12,7 +11,6 @@ #include #include #include -#include #include "../core/hcd.h" #include "isp1760-hcd.h" @@ -310,8 +308,6 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev) struct resource *mem_res; struct resource *irq_res; resource_size_t mem_size; - struct isp1760_platform_data *priv = pdev->dev.platform_data; - unsigned int devflags = 0; unsigned long irqflags = IRQF_SHARED | IRQF_DISABLED; mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); @@ -334,23 +330,8 @@ static int __devinit isp1760_plat_probe(struct platform_device *pdev) } irqflags |= irq_res->flags & IRQF_TRIGGER_MASK; - if (priv) { - if (priv->is_isp1761) - devflags |= ISP1760_FLAG_ISP1761; - if (priv->bus_width_16) - devflags |= ISP1760_FLAG_BUS_WIDTH_16; - if (priv->port1_otg) - devflags |= ISP1760_FLAG_OTG_EN; - if (priv->analog_oc) - devflags |= ISP1760_FLAG_ANALOG_OC; - if (priv->dack_polarity_high) - devflags |= ISP1760_FLAG_DACK_POL_HIGH; - if (priv->dreq_polarity_high) - devflags |= ISP1760_FLAG_DREQ_POL_HIGH; - } - hcd = isp1760_register(mem_res->start, mem_size, irq_res->start, - irqflags, &pdev->dev, dev_name(&pdev->dev), devflags); + irqflags, &pdev->dev, dev_name(&pdev->dev), 0); if (IS_ERR(hcd)) { pr_warning("isp1760: Failed to register the HCD device\n"); ret = -ENODEV; diff --git a/trunk/drivers/usb/host/ohci-at91.c b/trunk/drivers/usb/host/ohci-at91.c index 7ccffcbe7b6f..bb5e6f671578 100644 --- a/trunk/drivers/usb/host/ohci-at91.c +++ b/trunk/drivers/usb/host/ohci-at91.c @@ -148,7 +148,7 @@ static int usb_hcd_at91_probe(const struct hc_driver *driver, at91_start_hc(pdev); ohci_hcd_init(hcd_to_ohci(hcd)); - retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_SHARED); + retval = usb_add_hcd(hcd, pdev->resource[1].start, IRQF_DISABLED); if (retval == 0) return retval; diff --git a/trunk/drivers/usb/host/ohci-au1xxx.c b/trunk/drivers/usb/host/ohci-au1xxx.c index e4380082ebb1..2ac4e022a13f 100644 --- a/trunk/drivers/usb/host/ohci-au1xxx.c +++ b/trunk/drivers/usb/host/ohci-au1xxx.c @@ -248,9 +248,10 @@ static int ohci_hcd_au1xxx_drv_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int ohci_hcd_au1xxx_drv_suspend(struct device *dev) +static int ohci_hcd_au1xxx_drv_suspend(struct platform_device *pdev, + pm_message_t message) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); unsigned long flags; int rc; @@ -273,6 +274,10 @@ static int ohci_hcd_au1xxx_drv_suspend(struct device *dev) ohci_writel(ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); (void)ohci_readl(ohci, &ohci->regs->intrdisable); + /* make sure snapshot being resumed re-enumerates everything */ + if (message.event == PM_EVENT_PRETHAW) + ohci_usb_reset(ohci); + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); au1xxx_stop_ohc(); @@ -282,9 +287,9 @@ static int ohci_hcd_au1xxx_drv_suspend(struct device *dev) return rc; } -static int ohci_hcd_au1xxx_drv_resume(struct device *dev) +static int ohci_hcd_au1xxx_drv_resume(struct platform_device *pdev) { - struct usb_hcd *hcd = dev_get_drvdata(dev); + struct usb_hcd *hcd = platform_get_drvdata(pdev); au1xxx_start_ohc(); @@ -293,26 +298,20 @@ static int ohci_hcd_au1xxx_drv_resume(struct device *dev) return 0; } - -static struct dev_pm_ops au1xxx_ohci_pmops = { - .suspend = ohci_hcd_au1xxx_drv_suspend, - .resume = ohci_hcd_au1xxx_drv_resume, -}; - -#define AU1XXX_OHCI_PMOPS &au1xxx_ohci_pmops - #else -#define AU1XXX_OHCI_PMOPS NULL +#define ohci_hcd_au1xxx_drv_suspend NULL +#define ohci_hcd_au1xxx_drv_resume NULL #endif static struct platform_driver ohci_hcd_au1xxx_driver = { .probe = ohci_hcd_au1xxx_drv_probe, .remove = ohci_hcd_au1xxx_drv_remove, .shutdown = usb_hcd_platform_shutdown, + .suspend = ohci_hcd_au1xxx_drv_suspend, + .resume = ohci_hcd_au1xxx_drv_resume, .driver = { .name = "au1xxx-ohci", .owner = THIS_MODULE, - .pm = AU1XXX_OHCI_PMOPS, }, }; diff --git a/trunk/drivers/usb/host/ohci-ep93xx.c b/trunk/drivers/usb/host/ohci-ep93xx.c index 4e681613e7ae..b0dbf4157d29 100644 --- a/trunk/drivers/usb/host/ohci-ep93xx.c +++ b/trunk/drivers/usb/host/ohci-ep93xx.c @@ -188,6 +188,7 @@ static int ohci_hcd_ep93xx_drv_resume(struct platform_device *pdev) { struct usb_hcd *hcd = platform_get_drvdata(pdev); struct ohci_hcd *ohci = hcd_to_ohci(hcd); + int status; if (time_before(jiffies, ohci->next_statechange)) msleep(5); diff --git a/trunk/drivers/usb/host/ohci-hcd.c b/trunk/drivers/usb/host/ohci-hcd.c index 78bb7710f36d..58151687d351 100644 --- a/trunk/drivers/usb/host/ohci-hcd.c +++ b/trunk/drivers/usb/host/ohci-hcd.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include diff --git a/trunk/drivers/usb/host/ohci-pxa27x.c b/trunk/drivers/usb/host/ohci-pxa27x.c index b5294a9344de..e44dc2cbca24 100644 --- a/trunk/drivers/usb/host/ohci-pxa27x.c +++ b/trunk/drivers/usb/host/ohci-pxa27x.c @@ -177,13 +177,9 @@ static inline void pxa27x_setup_hc(struct pxa27x_ohci *ohci, if (inf->flags & NO_OC_PROTECTION) uhcrhda |= UHCRHDA_NOCP; - else - uhcrhda &= ~UHCRHDA_NOCP; if (inf->flags & OC_MODE_PERPORT) uhcrhda |= UHCRHDA_OCPM; - else - uhcrhda &= ~UHCRHDA_OCPM; if (inf->power_on_delay) { uhcrhda &= ~UHCRHDA_POTPGT(0xff); diff --git a/trunk/drivers/usb/host/oxu210hp-hcd.c b/trunk/drivers/usb/host/oxu210hp-hcd.c index 50f57f468836..5ac489ee3dab 100644 --- a/trunk/drivers/usb/host/oxu210hp-hcd.c +++ b/trunk/drivers/usb/host/oxu210hp-hcd.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include #include diff --git a/trunk/drivers/usb/host/pci-quirks.c b/trunk/drivers/usb/host/pci-quirks.c index 23cf3bde4762..83b5f9cea85a 100644 --- a/trunk/drivers/usb/host/pci-quirks.c +++ b/trunk/drivers/usb/host/pci-quirks.c @@ -475,4 +475,4 @@ static void __devinit quirk_usb_early_handoff(struct pci_dev *pdev) else if (pdev->class == PCI_CLASS_SERIAL_USB_XHCI) quirk_usb_handoff_xhci(pdev); } -DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); +DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_usb_early_handoff); diff --git a/trunk/drivers/usb/host/sl811-hcd.c b/trunk/drivers/usb/host/sl811-hcd.c index 5b22a4d1c9e4..a949259f18b9 100644 --- a/trunk/drivers/usb/host/sl811-hcd.c +++ b/trunk/drivers/usb/host/sl811-hcd.c @@ -719,12 +719,8 @@ static irqreturn_t sl811h_irq(struct usb_hcd *hcd) /* port status seems weird until after reset, so * force the reset and make khubd clean up later. */ - if (sl811->stat_insrmv & 1) - sl811->port1 |= 1 << USB_PORT_FEAT_CONNECTION; - else - sl811->port1 &= ~(1 << USB_PORT_FEAT_CONNECTION); - - sl811->port1 |= 1 << USB_PORT_FEAT_C_CONNECTION; + sl811->port1 |= (1 << USB_PORT_FEAT_C_CONNECTION) + | (1 << USB_PORT_FEAT_CONNECTION); } else if (irqstat & SL11H_INTMASK_RD) { if (sl811->port1 & (1 << USB_PORT_FEAT_SUSPEND)) { diff --git a/trunk/drivers/usb/host/uhci-q.c b/trunk/drivers/usb/host/uhci-q.c index acd582c02802..64e57bfe236b 100644 --- a/trunk/drivers/usb/host/uhci-q.c +++ b/trunk/drivers/usb/host/uhci-q.c @@ -1422,6 +1422,7 @@ static int uhci_urb_enqueue(struct usb_hcd *hcd, goto err_submit_failed; /* Add this URB to the QH */ + urbp->qh = qh; list_add_tail(&urbp->node, &qh->queue); /* If the new URB is the first and only one on this QH then either diff --git a/trunk/drivers/usb/host/whci/asl.c b/trunk/drivers/usb/host/whci/asl.c index c632437c7649..c2050785a819 100644 --- a/trunk/drivers/usb/host/whci/asl.c +++ b/trunk/drivers/usb/host/whci/asl.c @@ -227,21 +227,11 @@ void scan_async_work(struct work_struct *work) /* * Now that the ASL is updated, complete the removal of any * removed qsets. - * - * If the qset was to be reset, do so and reinsert it into the - * ASL if it has pending transfers. */ spin_lock_irq(&whc->lock); list_for_each_entry_safe(qset, t, &whc->async_removed_list, list_node) { qset_remove_complete(whc, qset); - if (qset->reset) { - qset_reset(whc, qset); - if (!list_empty(&qset->stds)) { - asl_qset_insert_begin(whc, qset); - queue_work(whc->workqueue, &whc->async_work); - } - } } spin_unlock_irq(&whc->lock); @@ -277,7 +267,7 @@ int asl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) else err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); if (!err) { - if (!qset->in_sw_list && !qset->remove) + if (!qset->in_sw_list) asl_qset_insert_begin(whc, qset); } else usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); diff --git a/trunk/drivers/usb/host/whci/hcd.c b/trunk/drivers/usb/host/whci/hcd.c index 687b622a1612..e019a5058ab8 100644 --- a/trunk/drivers/usb/host/whci/hcd.c +++ b/trunk/drivers/usb/host/whci/hcd.c @@ -192,23 +192,19 @@ static void whc_endpoint_reset(struct usb_hcd *usb_hcd, struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); struct whc *whc = wusbhc_to_whc(wusbhc); struct whc_qset *qset; - unsigned long flags; - - spin_lock_irqsave(&whc->lock, flags); qset = ep->hcpriv; if (qset) { qset->remove = 1; - qset->reset = 1; if (usb_endpoint_xfer_bulk(&ep->desc) || usb_endpoint_xfer_control(&ep->desc)) queue_work(whc->workqueue, &whc->async_work); else queue_work(whc->workqueue, &whc->periodic_work); - } - spin_unlock_irqrestore(&whc->lock, flags); + qset_reset(whc, qset); + } } diff --git a/trunk/drivers/usb/host/whci/pzl.c b/trunk/drivers/usb/host/whci/pzl.c index a9e05bac6646..ff4ef9e910d9 100644 --- a/trunk/drivers/usb/host/whci/pzl.c +++ b/trunk/drivers/usb/host/whci/pzl.c @@ -255,21 +255,11 @@ void scan_periodic_work(struct work_struct *work) /* * Now that the PZL is updated, complete the removal of any * removed qsets. - * - * If the qset was to be reset, do so and reinsert it into the - * PZL if it has pending transfers. */ spin_lock_irq(&whc->lock); list_for_each_entry_safe(qset, t, &whc->periodic_removed_list, list_node) { qset_remove_complete(whc, qset); - if (qset->reset) { - qset_reset(whc, qset); - if (!list_empty(&qset->stds)) { - qset_insert_in_sw_list(whc, qset); - queue_work(whc->workqueue, &whc->periodic_work); - } - } } spin_unlock_irq(&whc->lock); @@ -305,7 +295,7 @@ int pzl_urb_enqueue(struct whc *whc, struct urb *urb, gfp_t mem_flags) else err = qset_add_urb(whc, qset, urb, GFP_ATOMIC); if (!err) { - if (!qset->in_sw_list && !qset->remove) + if (!qset->in_sw_list) qset_insert_in_sw_list(whc, qset); } else usb_hcd_unlink_urb_from_ep(&whc->wusbhc.usb_hcd, urb); diff --git a/trunk/drivers/usb/host/whci/qset.c b/trunk/drivers/usb/host/whci/qset.c index 1b9dc1571570..640b38fbd051 100644 --- a/trunk/drivers/usb/host/whci/qset.c +++ b/trunk/drivers/usb/host/whci/qset.c @@ -103,6 +103,7 @@ static void qset_fill_qh(struct whc_qset *qset, struct urb *urb) void qset_clear(struct whc *whc, struct whc_qset *qset) { qset->td_start = qset->td_end = qset->ntds = 0; + qset->remove = 0; qset->qh.link = cpu_to_le32(QH_LINK_NTDS(8) | QH_LINK_T); qset->qh.status = qset->qh.status & QH_STATUS_SEQ_MASK; @@ -124,7 +125,7 @@ void qset_clear(struct whc *whc, struct whc_qset *qset) */ void qset_reset(struct whc *whc, struct whc_qset *qset) { - qset->reset = 0; + wait_for_completion(&qset->remove_complete); qset->qh.status &= ~QH_STATUS_SEQ_MASK; qset->qh.cur_window = cpu_to_le32((1 << qset->max_burst) - 1); @@ -155,7 +156,6 @@ struct whc_qset *get_qset(struct whc *whc, struct urb *urb, void qset_remove_complete(struct whc *whc, struct whc_qset *qset) { - qset->remove = 0; list_del_init(&qset->list_node); complete(&qset->remove_complete); } diff --git a/trunk/drivers/usb/host/whci/whci-hc.h b/trunk/drivers/usb/host/whci/whci-hc.h index e8d0001605be..794dba0d0f0a 100644 --- a/trunk/drivers/usb/host/whci/whci-hc.h +++ b/trunk/drivers/usb/host/whci/whci-hc.h @@ -264,7 +264,6 @@ struct whc_qset { unsigned in_sw_list:1; unsigned in_hw_list:1; unsigned remove:1; - unsigned reset:1; struct urb *pause_after_urb; struct completion remove_complete; int max_burst; diff --git a/trunk/drivers/usb/host/xhci-dbg.c b/trunk/drivers/usb/host/xhci-dbg.c index 33128d52f212..705e34324156 100644 --- a/trunk/drivers/usb/host/xhci-dbg.c +++ b/trunk/drivers/usb/host/xhci-dbg.c @@ -413,8 +413,7 @@ void xhci_dbg_slot_ctx(struct xhci_hcd *xhci, struct xhci_container_ctx *ctx) int i; struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx); - dma_addr_t dma = ctx->dma + - ((unsigned long)slot_ctx - (unsigned long)ctx->bytes); + dma_addr_t dma = ctx->dma + ((unsigned long)slot_ctx - (unsigned long)ctx); int csz = HCC_64BYTE_CONTEXT(xhci->hcc_params); xhci_dbg(xhci, "Slot Context:\n"); @@ -460,7 +459,7 @@ void xhci_dbg_ep_ctx(struct xhci_hcd *xhci, for (i = 0; i < last_ep_ctx; ++i) { struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, ctx, i); dma_addr_t dma = ctx->dma + - ((unsigned long)ep_ctx - (unsigned long)ctx->bytes); + ((unsigned long)ep_ctx - (unsigned long)ctx); xhci_dbg(xhci, "Endpoint %02d Context:\n", i); xhci_dbg(xhci, "@%p (virt) @%08llx (dma) %#08x - ep_info\n", diff --git a/trunk/drivers/usb/host/xhci-hcd.c b/trunk/drivers/usb/host/xhci-hcd.c index 99911e727e0b..816c39caca1c 100644 --- a/trunk/drivers/usb/host/xhci-hcd.c +++ b/trunk/drivers/usb/host/xhci-hcd.c @@ -22,18 +22,12 @@ #include #include -#include #include "xhci.h" #define DRIVER_AUTHOR "Sarah Sharp" #define DRIVER_DESC "'eXtensible' Host Controller (xHC) Driver" -/* Some 0.95 hardware can't handle the chain bit on a Link TRB being cleared */ -static int link_quirk; -module_param(link_quirk, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(link_quirk, "Don't clear the chain bit on a link TRB"); - /* TODO: copied from ehci-hcd.c - can this be refactored? */ /* * handshake - spin reading hc until handshake completes or fails @@ -220,12 +214,6 @@ int xhci_init(struct usb_hcd *hcd) xhci_dbg(xhci, "xhci_init\n"); spin_lock_init(&xhci->lock); - if (link_quirk) { - xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits.\n"); - xhci->quirks |= XHCI_LINK_TRB_QUIRK; - } else { - xhci_dbg(xhci, "xHCI doesn't need link TRB QUIRK\n"); - } retval = xhci_mem_init(xhci, GFP_KERNEL); xhci_dbg(xhci, "Finished xhci_init\n"); @@ -351,14 +339,13 @@ void xhci_event_ring_work(unsigned long arg) xhci_dbg_ring_ptrs(xhci, xhci->cmd_ring); xhci_dbg_cmd_ptrs(xhci); for (i = 0; i < MAX_HC_SLOTS; ++i) { - if (!xhci->devs[i]) - continue; - for (j = 0; j < 31; ++j) { - struct xhci_ring *ring = xhci->devs[i]->eps[j].ring; - if (!ring) - continue; - xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", i, j); - xhci_debug_segment(xhci, ring->deq_seg); + if (xhci->devs[i]) { + for (j = 0; j < 31; ++j) { + if (xhci->devs[i]->ep_rings[j]) { + xhci_dbg(xhci, "Dev %d endpoint ring %d:\n", i, j); + xhci_debug_segment(xhci, xhci->devs[i]->ep_rings[j]->deq_seg); + } + } } } @@ -568,22 +555,13 @@ unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc) return 1 << (xhci_get_endpoint_index(desc) + 1); } -/* Find the flag for this endpoint (for use in the control context). Use the - * endpoint index to create a bitmask. The slot context is bit 0, endpoint 0 is - * bit 1, etc. - */ -unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index) -{ - return 1 << (ep_index + 1); -} - /* Compute the last valid endpoint context index. Basically, this is the * endpoint index plus one. For slot contexts with more than valid endpoint, * we find the most significant bit set in the added contexts flags. * e.g. ep 1 IN (with epnum 0x81) => added_ctxs = 0b1000 * fls(0b1000) = 4, but the endpoint context index is 3, so subtract one. */ -unsigned int xhci_last_valid_endpoint(u32 added_ctxs) +static inline unsigned int xhci_last_valid_endpoint(u32 added_ctxs) { return fls(added_ctxs) - 1; } @@ -611,71 +589,6 @@ int xhci_check_args(struct usb_hcd *hcd, struct usb_device *udev, return 1; } -static int xhci_configure_endpoint(struct xhci_hcd *xhci, - struct usb_device *udev, struct xhci_command *command, - bool ctx_change, bool must_succeed); - -/* - * Full speed devices may have a max packet size greater than 8 bytes, but the - * USB core doesn't know that until it reads the first 8 bytes of the - * descriptor. If the usb_device's max packet size changes after that point, - * we need to issue an evaluate context command and wait on it. - */ -static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id, - unsigned int ep_index, struct urb *urb) -{ - struct xhci_container_ctx *in_ctx; - struct xhci_container_ctx *out_ctx; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_ep_ctx *ep_ctx; - int max_packet_size; - int hw_max_packet_size; - int ret = 0; - - out_ctx = xhci->devs[slot_id]->out_ctx; - ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); - hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2); - max_packet_size = urb->dev->ep0.desc.wMaxPacketSize; - if (hw_max_packet_size != max_packet_size) { - xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n"); - xhci_dbg(xhci, "Max packet size in usb_device = %d\n", - max_packet_size); - xhci_dbg(xhci, "Max packet size in xHCI HW = %d\n", - hw_max_packet_size); - xhci_dbg(xhci, "Issuing evaluate context command.\n"); - - /* Set up the modified control endpoint 0 */ - xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, - xhci->devs[slot_id]->out_ctx, ep_index); - in_ctx = xhci->devs[slot_id]->in_ctx; - ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); - ep_ctx->ep_info2 &= ~MAX_PACKET_MASK; - ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size); - - /* Set up the input context flags for the command */ - /* FIXME: This won't work if a non-default control endpoint - * changes max packet sizes. - */ - ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); - ctrl_ctx->add_flags = EP0_FLAG; - ctrl_ctx->drop_flags = 0; - - xhci_dbg(xhci, "Slot %d input context\n", slot_id); - xhci_dbg_ctx(xhci, in_ctx, ep_index); - xhci_dbg(xhci, "Slot %d output context\n", slot_id); - xhci_dbg_ctx(xhci, out_ctx, ep_index); - - ret = xhci_configure_endpoint(xhci, urb->dev, NULL, - true, false); - - /* Clean up the input context for later use by bandwidth - * functions. - */ - ctrl_ctx->add_flags = SLOT_FLAG; - } - return ret; -} - /* * non-error returns are a promise to giveback() the urb later * we drop ownership so next owner (or urb unlink) can get it @@ -687,13 +600,13 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) int ret = 0; unsigned int slot_id, ep_index; - if (!urb || xhci_check_args(hcd, urb->dev, urb->ep, true, __func__) <= 0) return -EINVAL; slot_id = urb->dev->slot_id; ep_index = xhci_get_endpoint_index(&urb->ep->desc); + spin_lock_irqsave(&xhci->lock, flags); if (!xhci->devs || !xhci->devs[slot_id]) { if (!in_interrupt()) dev_warn(&urb->dev->dev, "WARN: urb submitted for dev with no Slot ID\n"); @@ -706,38 +619,19 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) ret = -ESHUTDOWN; goto exit; } - if (usb_endpoint_xfer_control(&urb->ep->desc)) { - /* Check to see if the max packet size for the default control - * endpoint changed during FS device enumeration - */ - if (urb->dev->speed == USB_SPEED_FULL) { - ret = xhci_check_maxpacket(xhci, slot_id, - ep_index, urb); - if (ret < 0) - return ret; - } - + if (usb_endpoint_xfer_control(&urb->ep->desc)) /* We have a spinlock and interrupts disabled, so we must pass * atomic context to this function, which may allocate memory. */ - spin_lock_irqsave(&xhci->lock, flags); ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); - spin_unlock_irqrestore(&xhci->lock, flags); - } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) { - spin_lock_irqsave(&xhci->lock, flags); + else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); - spin_unlock_irqrestore(&xhci->lock, flags); - } else if (usb_endpoint_xfer_int(&urb->ep->desc)) { - spin_lock_irqsave(&xhci->lock, flags); - ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb, - slot_id, ep_index); - spin_unlock_irqrestore(&xhci->lock, flags); - } else { + else ret = -EINVAL; - } exit: + spin_unlock_irqrestore(&xhci->lock, flags); return ret; } @@ -780,7 +674,6 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) struct xhci_td *td; unsigned int ep_index; struct xhci_ring *ep_ring; - struct xhci_virt_ep *ep; xhci = hcd_to_xhci(hcd); spin_lock_irqsave(&xhci->lock, flags); @@ -793,18 +686,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) xhci_dbg(xhci, "Event ring:\n"); xhci_debug_ring(xhci, xhci->event_ring); ep_index = xhci_get_endpoint_index(&urb->ep->desc); - ep = &xhci->devs[urb->dev->slot_id]->eps[ep_index]; - ep_ring = ep->ring; + ep_ring = xhci->devs[urb->dev->slot_id]->ep_rings[ep_index]; xhci_dbg(xhci, "Endpoint ring:\n"); xhci_debug_ring(xhci, ep_ring); td = (struct xhci_td *) urb->hcpriv; - ep->cancels_pending++; - list_add_tail(&td->cancelled_td_list, &ep->cancelled_td_list); + ep_ring->cancels_pending++; + list_add_tail(&td->cancelled_td_list, &ep_ring->cancelled_td_list); /* Queue a stop endpoint command, but only if this is * the first cancellation to be handled. */ - if (ep->cancels_pending == 1) { + if (ep_ring->cancels_pending == 1) { xhci_queue_stop_endpoint(xhci, urb->dev->slot_id, ep_index); xhci_ring_cmd_db(xhci); } @@ -1038,141 +930,6 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir } } -static int xhci_configure_endpoint_result(struct xhci_hcd *xhci, - struct usb_device *udev, int *cmd_status) -{ - int ret; - - switch (*cmd_status) { - case COMP_ENOMEM: - dev_warn(&udev->dev, "Not enough host controller resources " - "for new device state.\n"); - ret = -ENOMEM; - /* FIXME: can we allocate more resources for the HC? */ - break; - case COMP_BW_ERR: - dev_warn(&udev->dev, "Not enough bandwidth " - "for new device state.\n"); - ret = -ENOSPC; - /* FIXME: can we go back to the old state? */ - break; - case COMP_TRB_ERR: - /* the HCD set up something wrong */ - dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, " - "add flag = 1, " - "and endpoint is not disabled.\n"); - ret = -EINVAL; - break; - case COMP_SUCCESS: - dev_dbg(&udev->dev, "Successful Endpoint Configure command\n"); - ret = 0; - break; - default: - xhci_err(xhci, "ERROR: unexpected command completion " - "code 0x%x.\n", *cmd_status); - ret = -EINVAL; - break; - } - return ret; -} - -static int xhci_evaluate_context_result(struct xhci_hcd *xhci, - struct usb_device *udev, int *cmd_status) -{ - int ret; - struct xhci_virt_device *virt_dev = xhci->devs[udev->slot_id]; - - switch (*cmd_status) { - case COMP_EINVAL: - dev_warn(&udev->dev, "WARN: xHCI driver setup invalid evaluate " - "context command.\n"); - ret = -EINVAL; - break; - case COMP_EBADSLT: - dev_warn(&udev->dev, "WARN: slot not enabled for" - "evaluate context command.\n"); - case COMP_CTX_STATE: - dev_warn(&udev->dev, "WARN: invalid context state for " - "evaluate context command.\n"); - xhci_dbg_ctx(xhci, virt_dev->out_ctx, 1); - ret = -EINVAL; - break; - case COMP_SUCCESS: - dev_dbg(&udev->dev, "Successful evaluate context command\n"); - ret = 0; - break; - default: - xhci_err(xhci, "ERROR: unexpected command completion " - "code 0x%x.\n", *cmd_status); - ret = -EINVAL; - break; - } - return ret; -} - -/* Issue a configure endpoint command or evaluate context command - * and wait for it to finish. - */ -static int xhci_configure_endpoint(struct xhci_hcd *xhci, - struct usb_device *udev, - struct xhci_command *command, - bool ctx_change, bool must_succeed) -{ - int ret; - int timeleft; - unsigned long flags; - struct xhci_container_ctx *in_ctx; - struct completion *cmd_completion; - int *cmd_status; - struct xhci_virt_device *virt_dev; - - spin_lock_irqsave(&xhci->lock, flags); - virt_dev = xhci->devs[udev->slot_id]; - if (command) { - in_ctx = command->in_ctx; - cmd_completion = command->completion; - cmd_status = &command->status; - command->command_trb = xhci->cmd_ring->enqueue; - list_add_tail(&command->cmd_list, &virt_dev->cmd_list); - } else { - in_ctx = virt_dev->in_ctx; - cmd_completion = &virt_dev->cmd_completion; - cmd_status = &virt_dev->cmd_status; - } - - if (!ctx_change) - ret = xhci_queue_configure_endpoint(xhci, in_ctx->dma, - udev->slot_id, must_succeed); - else - ret = xhci_queue_evaluate_context(xhci, in_ctx->dma, - udev->slot_id); - if (ret < 0) { - spin_unlock_irqrestore(&xhci->lock, flags); - xhci_dbg(xhci, "FIXME allocate a new ring segment\n"); - return -ENOMEM; - } - xhci_ring_cmd_db(xhci); - spin_unlock_irqrestore(&xhci->lock, flags); - - /* Wait for the configure endpoint command to complete */ - timeleft = wait_for_completion_interruptible_timeout( - cmd_completion, - USB_CTRL_SET_TIMEOUT); - if (timeleft <= 0) { - xhci_warn(xhci, "%s while waiting for %s command\n", - timeleft == 0 ? "Timeout" : "Signal", - ctx_change == 0 ? - "configure endpoint" : - "evaluate context"); - /* FIXME cancel the configure endpoint command */ - return -ETIME; - } - - if (!ctx_change) - return xhci_configure_endpoint_result(xhci, udev, cmd_status); - return xhci_evaluate_context_result(xhci, udev, cmd_status); -} - /* Called after one or more calls to xhci_add_endpoint() or * xhci_drop_endpoint(). If this call fails, the USB core is expected * to call xhci_reset_bandwidth(). @@ -1187,6 +944,8 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) { int i; int ret = 0; + int timeleft; + unsigned long flags; struct xhci_hcd *xhci; struct xhci_virt_device *virt_dev; struct xhci_input_control_ctx *ctrl_ctx; @@ -1216,8 +975,56 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) xhci_dbg_ctx(xhci, virt_dev->in_ctx, LAST_CTX_TO_EP_NUM(slot_ctx->dev_info)); - ret = xhci_configure_endpoint(xhci, udev, NULL, - false, false); + spin_lock_irqsave(&xhci->lock, flags); + ret = xhci_queue_configure_endpoint(xhci, virt_dev->in_ctx->dma, + udev->slot_id); + if (ret < 0) { + spin_unlock_irqrestore(&xhci->lock, flags); + xhci_dbg(xhci, "FIXME allocate a new ring segment\n"); + return -ENOMEM; + } + xhci_ring_cmd_db(xhci); + spin_unlock_irqrestore(&xhci->lock, flags); + + /* Wait for the configure endpoint command to complete */ + timeleft = wait_for_completion_interruptible_timeout( + &virt_dev->cmd_completion, + USB_CTRL_SET_TIMEOUT); + if (timeleft <= 0) { + xhci_warn(xhci, "%s while waiting for configure endpoint command\n", + timeleft == 0 ? "Timeout" : "Signal"); + /* FIXME cancel the configure endpoint command */ + return -ETIME; + } + + switch (virt_dev->cmd_status) { + case COMP_ENOMEM: + dev_warn(&udev->dev, "Not enough host controller resources " + "for new device state.\n"); + ret = -ENOMEM; + /* FIXME: can we allocate more resources for the HC? */ + break; + case COMP_BW_ERR: + dev_warn(&udev->dev, "Not enough bandwidth " + "for new device state.\n"); + ret = -ENOSPC; + /* FIXME: can we go back to the old state? */ + break; + case COMP_TRB_ERR: + /* the HCD set up something wrong */ + dev_warn(&udev->dev, "ERROR: Endpoint drop flag = 0, add flag = 1, " + "and endpoint is not disabled.\n"); + ret = -EINVAL; + break; + case COMP_SUCCESS: + dev_dbg(&udev->dev, "Successful Endpoint Configure command\n"); + break; + default: + xhci_err(xhci, "ERROR: unexpected command completion " + "code 0x%x.\n", virt_dev->cmd_status); + ret = -EINVAL; + break; + } if (ret) { /* Callee should call reset_bandwidth() */ return ret; @@ -1230,10 +1037,10 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) xhci_zero_in_ctx(xhci, virt_dev); /* Free any old rings */ for (i = 1; i < 31; ++i) { - if (virt_dev->eps[i].new_ring) { - xhci_ring_free(xhci, virt_dev->eps[i].ring); - virt_dev->eps[i].ring = virt_dev->eps[i].new_ring; - virt_dev->eps[i].new_ring = NULL; + if (virt_dev->new_ep_rings[i]) { + xhci_ring_free(xhci, virt_dev->ep_rings[i]); + virt_dev->ep_rings[i] = virt_dev->new_ep_rings[i]; + virt_dev->new_ep_rings[i] = NULL; } } @@ -1260,93 +1067,14 @@ void xhci_reset_bandwidth(struct usb_hcd *hcd, struct usb_device *udev) virt_dev = xhci->devs[udev->slot_id]; /* Free any rings allocated for added endpoints */ for (i = 0; i < 31; ++i) { - if (virt_dev->eps[i].new_ring) { - xhci_ring_free(xhci, virt_dev->eps[i].new_ring); - virt_dev->eps[i].new_ring = NULL; + if (virt_dev->new_ep_rings[i]) { + xhci_ring_free(xhci, virt_dev->new_ep_rings[i]); + virt_dev->new_ep_rings[i] = NULL; } } xhci_zero_in_ctx(xhci, virt_dev); } -static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx, - u32 add_flags, u32 drop_flags) -{ - struct xhci_input_control_ctx *ctrl_ctx; - ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx); - ctrl_ctx->add_flags = add_flags; - ctrl_ctx->drop_flags = drop_flags; - xhci_slot_copy(xhci, in_ctx, out_ctx); - ctrl_ctx->add_flags |= SLOT_FLAG; - - xhci_dbg(xhci, "Input Context:\n"); - xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags)); -} - -void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci, - unsigned int slot_id, unsigned int ep_index, - struct xhci_dequeue_state *deq_state) -{ - struct xhci_container_ctx *in_ctx; - struct xhci_ep_ctx *ep_ctx; - u32 added_ctxs; - dma_addr_t addr; - - xhci_endpoint_copy(xhci, xhci->devs[slot_id]->in_ctx, - xhci->devs[slot_id]->out_ctx, ep_index); - in_ctx = xhci->devs[slot_id]->in_ctx; - ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); - addr = xhci_trb_virt_to_dma(deq_state->new_deq_seg, - deq_state->new_deq_ptr); - if (addr == 0) { - xhci_warn(xhci, "WARN Cannot submit config ep after " - "reset ep command\n"); - xhci_warn(xhci, "WARN deq seg = %p, deq ptr = %p\n", - deq_state->new_deq_seg, - deq_state->new_deq_ptr); - return; - } - ep_ctx->deq = addr | deq_state->new_cycle_state; - - added_ctxs = xhci_get_endpoint_flag_from_index(ep_index); - xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx, - xhci->devs[slot_id]->out_ctx, added_ctxs, added_ctxs); -} - -void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, - struct usb_device *udev, unsigned int ep_index) -{ - struct xhci_dequeue_state deq_state; - struct xhci_virt_ep *ep; - - xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n"); - ep = &xhci->devs[udev->slot_id]->eps[ep_index]; - /* We need to move the HW's dequeue pointer past this TD, - * or it will attempt to resend it on the next doorbell ring. - */ - xhci_find_new_dequeue_state(xhci, udev->slot_id, - ep_index, ep->stopped_td, - &deq_state); - - /* HW with the reset endpoint quirk will use the saved dequeue state to - * issue a configure endpoint command later. - */ - if (!(xhci->quirks & XHCI_RESET_EP_QUIRK)) { - xhci_dbg(xhci, "Queueing new dequeue state\n"); - xhci_queue_new_dequeue_state(xhci, udev->slot_id, - ep_index, &deq_state); - } else { - /* Better hope no one uses the input context between now and the - * reset endpoint completion! - */ - xhci_dbg(xhci, "Setting up input context for " - "configure endpoint command\n"); - xhci_setup_input_ctx_for_quirk(xhci, udev->slot_id, - ep_index, &deq_state); - } -} - /* Deal with stalled endpoints. The core should have sent the control message * to clear the halt condition. However, we need to make the xHCI hardware * reset its sequence number, since a device will expect a sequence number of @@ -1361,7 +1089,8 @@ void xhci_endpoint_reset(struct usb_hcd *hcd, unsigned int ep_index; unsigned long flags; int ret; - struct xhci_virt_ep *virt_ep; + struct xhci_dequeue_state deq_state; + struct xhci_ring *ep_ring; xhci = hcd_to_xhci(hcd); udev = (struct usb_device *) ep->hcpriv; @@ -1371,16 +1100,12 @@ void xhci_endpoint_reset(struct usb_hcd *hcd, if (!ep->hcpriv) return; ep_index = xhci_get_endpoint_index(&ep->desc); - virt_ep = &xhci->devs[udev->slot_id]->eps[ep_index]; - if (!virt_ep->stopped_td) { + ep_ring = xhci->devs[udev->slot_id]->ep_rings[ep_index]; + if (!ep_ring->stopped_td) { xhci_dbg(xhci, "Endpoint 0x%x not halted, refusing to reset.\n", ep->desc.bEndpointAddress); return; } - if (usb_endpoint_xfer_control(&ep->desc)) { - xhci_dbg(xhci, "Control endpoint stall already handled.\n"); - return; - } xhci_dbg(xhci, "Queueing reset endpoint command\n"); spin_lock_irqsave(&xhci->lock, flags); @@ -1391,8 +1116,17 @@ void xhci_endpoint_reset(struct usb_hcd *hcd, * command. Better hope that last command worked! */ if (!ret) { - xhci_cleanup_stalled_ring(xhci, udev, ep_index); - kfree(virt_ep->stopped_td); + xhci_dbg(xhci, "Cleaning up stalled endpoint ring\n"); + /* We need to move the HW's dequeue pointer past this TD, + * or it will attempt to resend it on the next doorbell ring. + */ + xhci_find_new_dequeue_state(xhci, udev->slot_id, + ep_index, ep_ring->stopped_td, &deq_state); + xhci_dbg(xhci, "Queueing new dequeue state\n"); + xhci_queue_new_dequeue_state(xhci, ep_ring, + udev->slot_id, + ep_index, &deq_state); + kfree(ep_ring->stopped_td); xhci_ring_cmd_db(xhci); } spin_unlock_irqrestore(&xhci->lock, flags); @@ -1594,88 +1328,6 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) return 0; } -/* Once a hub descriptor is fetched for a device, we need to update the xHC's - * internal data structures for the device. - */ -int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, - struct usb_tt *tt, gfp_t mem_flags) -{ - struct xhci_hcd *xhci = hcd_to_xhci(hcd); - struct xhci_virt_device *vdev; - struct xhci_command *config_cmd; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_slot_ctx *slot_ctx; - unsigned long flags; - unsigned think_time; - int ret; - - /* Ignore root hubs */ - if (!hdev->parent) - return 0; - - vdev = xhci->devs[hdev->slot_id]; - if (!vdev) { - xhci_warn(xhci, "Cannot update hub desc for unknown device.\n"); - return -EINVAL; - } - config_cmd = xhci_alloc_command(xhci, true, mem_flags); - if (!config_cmd) { - xhci_dbg(xhci, "Could not allocate xHCI command structure.\n"); - return -ENOMEM; - } - - spin_lock_irqsave(&xhci->lock, flags); - xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx); - ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx); - ctrl_ctx->add_flags |= SLOT_FLAG; - slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx); - slot_ctx->dev_info |= DEV_HUB; - if (tt->multi) - slot_ctx->dev_info |= DEV_MTT; - if (xhci->hci_version > 0x95) { - xhci_dbg(xhci, "xHCI version %x needs hub " - "TT think time and number of ports\n", - (unsigned int) xhci->hci_version); - slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild); - /* Set TT think time - convert from ns to FS bit times. - * 0 = 8 FS bit times, 1 = 16 FS bit times, - * 2 = 24 FS bit times, 3 = 32 FS bit times. - */ - think_time = tt->think_time; - if (think_time != 0) - think_time = (think_time / 666) - 1; - slot_ctx->tt_info |= TT_THINK_TIME(think_time); - } else { - xhci_dbg(xhci, "xHCI version %x doesn't need hub " - "TT think time or number of ports\n", - (unsigned int) xhci->hci_version); - } - slot_ctx->dev_state = 0; - spin_unlock_irqrestore(&xhci->lock, flags); - - xhci_dbg(xhci, "Set up %s for hub device.\n", - (xhci->hci_version > 0x95) ? - "configure endpoint" : "evaluate context"); - xhci_dbg(xhci, "Slot %u Input Context:\n", hdev->slot_id); - xhci_dbg_ctx(xhci, config_cmd->in_ctx, 0); - - /* Issue and wait for the configure endpoint or - * evaluate context command. - */ - if (xhci->hci_version > 0x95) - ret = xhci_configure_endpoint(xhci, hdev, config_cmd, - false, false); - else - ret = xhci_configure_endpoint(xhci, hdev, config_cmd, - true, false); - - xhci_dbg(xhci, "Slot %u Output Context:\n", hdev->slot_id); - xhci_dbg_ctx(xhci, vdev->out_ctx, 0); - - xhci_free_command(xhci, config_cmd); - return ret; -} - int xhci_get_frame(struct usb_hcd *hcd) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); diff --git a/trunk/drivers/usb/host/xhci-mem.c b/trunk/drivers/usb/host/xhci-mem.c index 1db4fea8c170..e6b9a1c6002d 100644 --- a/trunk/drivers/usb/host/xhci-mem.c +++ b/trunk/drivers/usb/host/xhci-mem.c @@ -94,9 +94,6 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev, val = prev->trbs[TRBS_PER_SEGMENT-1].link.control; val &= ~TRB_TYPE_BITMASK; val |= TRB_TYPE(TRB_LINK); - /* Always set the chain bit with 0.95 hardware */ - if (xhci_link_trb_quirk(xhci)) - val |= TRB_CHAIN; prev->trbs[TRBS_PER_SEGMENT-1].link.control = val; } xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n", @@ -144,6 +141,7 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, return 0; INIT_LIST_HEAD(&ring->td_list); + INIT_LIST_HEAD(&ring->cancelled_td_list); if (num_segs == 0) return ring; @@ -264,8 +262,8 @@ void xhci_free_virt_device(struct xhci_hcd *xhci, int slot_id) return; for (i = 0; i < 31; ++i) - if (dev->eps[i].ring) - xhci_ring_free(xhci, dev->eps[i].ring); + if (dev->ep_rings[i]) + xhci_ring_free(xhci, dev->ep_rings[i]); if (dev->in_ctx) xhci_free_container_ctx(xhci, dev->in_ctx); @@ -280,7 +278,6 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device *udev, gfp_t flags) { struct xhci_virt_device *dev; - int i; /* Slot ID 0 is reserved */ if (slot_id == 0 || xhci->devs[slot_id]) { @@ -309,17 +306,12 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, xhci_dbg(xhci, "Slot %d input ctx = 0x%llx (dma)\n", slot_id, (unsigned long long)dev->in_ctx->dma); - /* Initialize the cancellation list for each endpoint */ - for (i = 0; i < 31; i++) - INIT_LIST_HEAD(&dev->eps[i].cancelled_td_list); - /* Allocate endpoint 0 ring */ - dev->eps[0].ring = xhci_ring_alloc(xhci, 1, true, flags); - if (!dev->eps[0].ring) + dev->ep_rings[0] = xhci_ring_alloc(xhci, 1, true, flags); + if (!dev->ep_rings[0]) goto fail; init_completion(&dev->cmd_completion); - INIT_LIST_HEAD(&dev->cmd_list); /* Point to output device context in dcbaa. */ xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma; @@ -360,9 +352,9 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud /* 3) Only the control endpoint is valid - one endpoint context */ slot_ctx->dev_info |= LAST_CTX(1); - slot_ctx->dev_info |= (u32) udev->route; switch (udev->speed) { case USB_SPEED_SUPER: + slot_ctx->dev_info |= (u32) udev->route; slot_ctx->dev_info |= (u32) SLOT_SPEED_SS; break; case USB_SPEED_HIGH: @@ -390,12 +382,14 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud xhci_dbg(xhci, "Set root hub portnum to %d\n", top_dev->portnum); /* Is this a LS/FS device under a HS hub? */ + /* + * FIXME: I don't think this is right, where does the TT info for the + * roothub or parent hub come from? + */ if ((udev->speed == USB_SPEED_LOW || udev->speed == USB_SPEED_FULL) && udev->tt) { slot_ctx->tt_info = udev->tt->hub->slot_id; slot_ctx->tt_info |= udev->ttport << 8; - if (udev->tt->multi) - slot_ctx->dev_info |= DEV_MTT; } xhci_dbg(xhci, "udev->tt = %p\n", udev->tt); xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport); @@ -404,35 +398,22 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud /* Step 5 */ ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP); /* + * See section 4.3 bullet 6: + * The default Max Packet size for ep0 is "8 bytes for a USB2 + * LS/FS/HS device or 512 bytes for a USB3 SS device" * XXX: Not sure about wireless USB devices. */ - switch (udev->speed) { - case USB_SPEED_SUPER: + if (udev->speed == USB_SPEED_SUPER) ep0_ctx->ep_info2 |= MAX_PACKET(512); - break; - case USB_SPEED_HIGH: - /* USB core guesses at a 64-byte max packet first for FS devices */ - case USB_SPEED_FULL: - ep0_ctx->ep_info2 |= MAX_PACKET(64); - break; - case USB_SPEED_LOW: + else ep0_ctx->ep_info2 |= MAX_PACKET(8); - break; - case USB_SPEED_VARIABLE: - xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n"); - return -EINVAL; - break; - default: - /* New speed? */ - BUG(); - } /* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */ ep0_ctx->ep_info2 |= MAX_BURST(0); ep0_ctx->ep_info2 |= ERROR_COUNT(3); ep0_ctx->deq = - dev->eps[0].ring->first_seg->dma; - ep0_ctx->deq |= dev->eps[0].ring->cycle_state; + dev->ep_rings[0]->first_seg->dma; + ep0_ctx->deq |= dev->ep_rings[0]->cycle_state; /* Steps 7 and 8 were done in xhci_alloc_virt_device() */ @@ -542,11 +523,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci, ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, ep_index); /* Set up the endpoint ring */ - virt_dev->eps[ep_index].new_ring = - xhci_ring_alloc(xhci, 1, true, mem_flags); - if (!virt_dev->eps[ep_index].new_ring) + virt_dev->new_ep_rings[ep_index] = xhci_ring_alloc(xhci, 1, true, mem_flags); + if (!virt_dev->new_ep_rings[ep_index]) return -ENOMEM; - ep_ring = virt_dev->eps[ep_index].new_ring; + ep_ring = virt_dev->new_ep_rings[ep_index]; ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state; ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep); @@ -618,48 +598,6 @@ void xhci_endpoint_zero(struct xhci_hcd *xhci, */ } -/* Copy output xhci_ep_ctx to the input xhci_ep_ctx copy. - * Useful when you want to change one particular aspect of the endpoint and then - * issue a configure endpoint command. - */ -void xhci_endpoint_copy(struct xhci_hcd *xhci, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx, - unsigned int ep_index) -{ - struct xhci_ep_ctx *out_ep_ctx; - struct xhci_ep_ctx *in_ep_ctx; - - out_ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index); - in_ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index); - - in_ep_ctx->ep_info = out_ep_ctx->ep_info; - in_ep_ctx->ep_info2 = out_ep_ctx->ep_info2; - in_ep_ctx->deq = out_ep_ctx->deq; - in_ep_ctx->tx_info = out_ep_ctx->tx_info; -} - -/* Copy output xhci_slot_ctx to the input xhci_slot_ctx. - * Useful when you want to change one particular aspect of the endpoint and then - * issue a configure endpoint command. Only the context entries field matters, - * but we'll copy the whole thing anyway. - */ -void xhci_slot_copy(struct xhci_hcd *xhci, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx) -{ - struct xhci_slot_ctx *in_slot_ctx; - struct xhci_slot_ctx *out_slot_ctx; - - in_slot_ctx = xhci_get_slot_ctx(xhci, in_ctx); - out_slot_ctx = xhci_get_slot_ctx(xhci, out_ctx); - - in_slot_ctx->dev_info = out_slot_ctx->dev_info; - in_slot_ctx->dev_info2 = out_slot_ctx->dev_info2; - in_slot_ctx->tt_info = out_slot_ctx->tt_info; - in_slot_ctx->dev_state = out_slot_ctx->dev_state; -} - /* Set up the scratchpad buffer array and scratchpad buffers, if needed. */ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags) { @@ -757,44 +695,6 @@ static void scratchpad_free(struct xhci_hcd *xhci) xhci->scratchpad = NULL; } -struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, - bool allocate_completion, gfp_t mem_flags) -{ - struct xhci_command *command; - - command = kzalloc(sizeof(*command), mem_flags); - if (!command) - return NULL; - - command->in_ctx = - xhci_alloc_container_ctx(xhci, XHCI_CTX_TYPE_INPUT, mem_flags); - if (!command->in_ctx) - return NULL; - - if (allocate_completion) { - command->completion = - kzalloc(sizeof(struct completion), mem_flags); - if (!command->completion) { - xhci_free_container_ctx(xhci, command->in_ctx); - return NULL; - } - init_completion(command->completion); - } - - command->status = 0; - INIT_LIST_HEAD(&command->cmd_list); - return command; -} - -void xhci_free_command(struct xhci_hcd *xhci, - struct xhci_command *command) -{ - xhci_free_container_ctx(xhci, - command->in_ctx); - kfree(command->completion); - kfree(command); -} - void xhci_mem_cleanup(struct xhci_hcd *xhci) { struct pci_dev *pdev = to_pci_dev(xhci_to_hcd(xhci)->self.controller); diff --git a/trunk/drivers/usb/host/xhci-pci.c b/trunk/drivers/usb/host/xhci-pci.c index 06595ec27bb7..592fe7e623f7 100644 --- a/trunk/drivers/usb/host/xhci-pci.c +++ b/trunk/drivers/usb/host/xhci-pci.c @@ -24,10 +24,6 @@ #include "xhci.h" -/* Device for a quirk */ -#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73 -#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000 - static const char hcd_name[] = "xhci_hcd"; /* called after powerup, by probe or system-pm "wakeup" */ @@ -63,20 +59,9 @@ static int xhci_pci_setup(struct usb_hcd *hcd) xhci->hcs_params1 = xhci_readl(xhci, &xhci->cap_regs->hcs_params1); xhci->hcs_params2 = xhci_readl(xhci, &xhci->cap_regs->hcs_params2); xhci->hcs_params3 = xhci_readl(xhci, &xhci->cap_regs->hcs_params3); - xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); - xhci->hci_version = HC_VERSION(xhci->hcc_params); xhci->hcc_params = xhci_readl(xhci, &xhci->cap_regs->hcc_params); xhci_print_registers(xhci); - /* Look for vendor-specific quirks */ - if (pdev->vendor == PCI_VENDOR_ID_FRESCO_LOGIC && - pdev->device == PCI_DEVICE_ID_FRESCO_LOGIC_PDK && - pdev->revision == 0x0) { - xhci->quirks |= XHCI_RESET_EP_QUIRK; - xhci_dbg(xhci, "QUIRK: Fresco Logic xHC needs configure" - " endpoint cmd after reset endpoint\n"); - } - /* Make sure the HC is halted. */ retval = xhci_halt(xhci); if (retval) @@ -136,7 +121,6 @@ static const struct hc_driver xhci_pci_hc_driver = { .check_bandwidth = xhci_check_bandwidth, .reset_bandwidth = xhci_reset_bandwidth, .address_device = xhci_address_device, - .update_hub_device = xhci_update_hub_device, /* * scheduling support diff --git a/trunk/drivers/usb/host/xhci-ring.c b/trunk/drivers/usb/host/xhci-ring.c index 173c39c76489..aa88a067148b 100644 --- a/trunk/drivers/usb/host/xhci-ring.c +++ b/trunk/drivers/usb/host/xhci-ring.c @@ -172,9 +172,8 @@ static void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer * have their chain bit cleared (so that each Link TRB is a separate TD). * * Section 6.4.4.1 of the 0.95 spec says link TRBs cannot have the chain bit - * set, but other sections talk about dealing with the chain bit set. This was - * fixed in the 0.96 specification errata, but we have to assume that all 0.95 - * xHCI hardware can't handle the chain bit being cleared on a link TRB. + * set, but other sections talk about dealing with the chain bit set. + * Assume section 6.4.4.1 is wrong, and the chain bit can be set in a Link TRB. */ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer) { @@ -192,14 +191,8 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring, bool consumer while (last_trb(xhci, ring, ring->enq_seg, next)) { if (!consumer) { if (ring != xhci->event_ring) { - /* If we're not dealing with 0.95 hardware, - * carry over the chain bit of the previous TRB - * (which may mean the chain bit is cleared). - */ - if (!xhci_link_trb_quirk(xhci)) { - next->link.control &= ~TRB_CHAIN; - next->link.control |= chain; - } + next->link.control &= ~TRB_CHAIN; + next->link.control |= chain; /* Give this link TRB to the hardware */ wmb(); if (next->link.control & TRB_CYCLE) @@ -296,18 +289,16 @@ static void ring_ep_doorbell(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index) { - struct xhci_virt_ep *ep; - unsigned int ep_state; + struct xhci_ring *ep_ring; u32 field; __u32 __iomem *db_addr = &xhci->dba->doorbell[slot_id]; - ep = &xhci->devs[slot_id]->eps[ep_index]; - ep_state = ep->ep_state; + ep_ring = xhci->devs[slot_id]->ep_rings[ep_index]; /* Don't ring the doorbell for this endpoint if there are pending * cancellations because the we don't want to interrupt processing. */ - if (!ep->cancels_pending && !(ep_state & SET_DEQ_PENDING) - && !(ep_state & EP_HALTED)) { + if (!ep_ring->cancels_pending && !(ep_ring->state & SET_DEQ_PENDING) + && !(ep_ring->state & EP_HALTED)) { field = xhci_readl(xhci, db_addr) & DB_MASK; xhci_writel(xhci, field | EPI_TO_DB(ep_index), db_addr); /* Flush PCI posted writes - FIXME Matthew Wilcox says this @@ -363,7 +354,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, struct xhci_td *cur_td, struct xhci_dequeue_state *state) { struct xhci_virt_device *dev = xhci->devs[slot_id]; - struct xhci_ring *ep_ring = dev->eps[ep_index].ring; + struct xhci_ring *ep_ring = dev->ep_rings[ep_index]; struct xhci_generic_trb *trb; struct xhci_ep_ctx *ep_ctx; dma_addr_t addr; @@ -371,7 +362,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, state->new_cycle_state = 0; xhci_dbg(xhci, "Finding segment containing stopped TRB.\n"); state->new_deq_seg = find_trb_seg(cur_td->start_seg, - dev->eps[ep_index].stopped_trb, + ep_ring->stopped_trb, &state->new_cycle_state); if (!state->new_deq_seg) BUG(); @@ -451,11 +442,9 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, union xhci_trb *deq_ptr, u32 cycle_state); void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, - unsigned int slot_id, unsigned int ep_index, - struct xhci_dequeue_state *deq_state) + struct xhci_ring *ep_ring, unsigned int slot_id, + unsigned int ep_index, struct xhci_dequeue_state *deq_state) { - struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index]; - xhci_dbg(xhci, "Set TR Deq Ptr cmd, new deq seg = %p (0x%llx dma), " "new deq ptr = %p (0x%llx dma), new cycle = %u\n", deq_state->new_deq_seg, @@ -472,7 +461,8 @@ void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, * if the ring is running, and ringing the doorbell starts the * ring running. */ - ep->ep_state |= SET_DEQ_PENDING; + ep_ring->state |= SET_DEQ_PENDING; + xhci_ring_cmd_db(xhci); } /* @@ -491,7 +481,6 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, unsigned int slot_id; unsigned int ep_index; struct xhci_ring *ep_ring; - struct xhci_virt_ep *ep; struct list_head *entry; struct xhci_td *cur_td = 0; struct xhci_td *last_unlinked_td; @@ -504,10 +493,9 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, memset(&deq_state, 0, sizeof(deq_state)); slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); - ep = &xhci->devs[slot_id]->eps[ep_index]; - ep_ring = ep->ring; + ep_ring = xhci->devs[slot_id]->ep_rings[ep_index]; - if (list_empty(&ep->cancelled_td_list)) + if (list_empty(&ep_ring->cancelled_td_list)) return; /* Fix up the ep ring first, so HW stops executing cancelled TDs. @@ -515,7 +503,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, * it. We're also in the event handler, so we can't get re-interrupted * if another Stop Endpoint command completes */ - list_for_each(entry, &ep->cancelled_td_list) { + list_for_each(entry, &ep_ring->cancelled_td_list) { cur_td = list_entry(entry, struct xhci_td, cancelled_td_list); xhci_dbg(xhci, "Cancelling TD starting at %p, 0x%llx (dma).\n", cur_td->first_trb, @@ -524,7 +512,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, * If we stopped on the TD we need to cancel, then we have to * move the xHC endpoint ring dequeue pointer past this TD. */ - if (cur_td == ep->stopped_td) + if (cur_td == ep_ring->stopped_td) xhci_find_new_dequeue_state(xhci, slot_id, ep_index, cur_td, &deq_state); else @@ -535,15 +523,14 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, * the cancelled TD list for URB completion later. */ list_del(&cur_td->td_list); - ep->cancels_pending--; + ep_ring->cancels_pending--; } last_unlinked_td = cur_td; /* If necessary, queue a Set Transfer Ring Dequeue Pointer command */ if (deq_state.new_deq_ptr && deq_state.new_deq_seg) { - xhci_queue_new_dequeue_state(xhci, + xhci_queue_new_dequeue_state(xhci, ep_ring, slot_id, ep_index, &deq_state); - xhci_ring_cmd_db(xhci); } else { /* Otherwise just ring the doorbell to restart the ring */ ring_ep_doorbell(xhci, slot_id, ep_index); @@ -556,7 +543,7 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci, * So stop when we've completed the URB for the last TD we unlinked. */ do { - cur_td = list_entry(ep->cancelled_td_list.next, + cur_td = list_entry(ep_ring->cancelled_td_list.next, struct xhci_td, cancelled_td_list); list_del(&cur_td->cancelled_td_list); @@ -603,7 +590,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); dev = xhci->devs[slot_id]; - ep_ring = dev->eps[ep_index].ring; + ep_ring = dev->ep_rings[ep_index]; ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index); slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx); @@ -647,7 +634,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci, ep_ctx->deq); } - dev->eps[ep_index].ep_state &= ~SET_DEQ_PENDING; + ep_ring->state &= ~SET_DEQ_PENDING; ring_ep_doorbell(xhci, slot_id, ep_index); } @@ -657,60 +644,18 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci, { int slot_id; unsigned int ep_index; - struct xhci_ring *ep_ring; slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]); ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]); - ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; /* This command will only fail if the endpoint wasn't halted, * but we don't care. */ xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n", (unsigned int) GET_COMP_CODE(event->status)); - /* HW with the reset endpoint quirk needs to have a configure endpoint - * command complete before the endpoint can be used. Queue that here - * because the HW can't handle two commands being queued in a row. - */ - if (xhci->quirks & XHCI_RESET_EP_QUIRK) { - xhci_dbg(xhci, "Queueing configure endpoint command\n"); - xhci_queue_configure_endpoint(xhci, - xhci->devs[slot_id]->in_ctx->dma, slot_id, - false); - xhci_ring_cmd_db(xhci); - } else { - /* Clear our internal halted state and restart the ring */ - xhci->devs[slot_id]->eps[ep_index].ep_state &= ~EP_HALTED; - ring_ep_doorbell(xhci, slot_id, ep_index); - } -} - -/* Check to see if a command in the device's command queue matches this one. - * Signal the completion or free the command, and return 1. Return 0 if the - * completed command isn't at the head of the command list. - */ -static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci, - struct xhci_virt_device *virt_dev, - struct xhci_event_cmd *event) -{ - struct xhci_command *command; - - if (list_empty(&virt_dev->cmd_list)) - return 0; - - command = list_entry(virt_dev->cmd_list.next, - struct xhci_command, cmd_list); - if (xhci->cmd_ring->dequeue != command->command_trb) - return 0; - - command->status = - GET_COMP_CODE(event->status); - list_del(&command->cmd_list); - if (command->completion) - complete(command->completion); - else - xhci_free_command(xhci, command); - return 1; + /* Clear our internal halted state and restart the ring */ + xhci->devs[slot_id]->ep_rings[ep_index]->state &= ~EP_HALTED; + ring_ep_doorbell(xhci, slot_id, ep_index); } static void handle_cmd_completion(struct xhci_hcd *xhci, @@ -719,11 +664,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, int slot_id = TRB_TO_SLOT_ID(event->flags); u64 cmd_dma; dma_addr_t cmd_dequeue_dma; - struct xhci_input_control_ctx *ctrl_ctx; - struct xhci_virt_device *virt_dev; - unsigned int ep_index; - struct xhci_ring *ep_ring; - unsigned int ep_state; cmd_dma = event->cmd_trb; cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg, @@ -751,47 +691,6 @@ static void handle_cmd_completion(struct xhci_hcd *xhci, xhci_free_virt_device(xhci, slot_id); break; case TRB_TYPE(TRB_CONFIG_EP): - virt_dev = xhci->devs[slot_id]; - if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) - break; - /* - * Configure endpoint commands can come from the USB core - * configuration or alt setting changes, or because the HW - * needed an extra configure endpoint command after a reset - * endpoint command. In the latter case, the xHCI driver is - * not waiting on the configure endpoint command. - */ - ctrl_ctx = xhci_get_input_control_ctx(xhci, - virt_dev->in_ctx); - /* Input ctx add_flags are the endpoint index plus one */ - ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1; - ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; - if (!ep_ring) { - /* This must have been an initial configure endpoint */ - xhci->devs[slot_id]->cmd_status = - GET_COMP_CODE(event->status); - complete(&xhci->devs[slot_id]->cmd_completion); - break; - } - ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state; - xhci_dbg(xhci, "Completed config ep cmd - last ep index = %d, " - "state = %d\n", ep_index, ep_state); - if (xhci->quirks & XHCI_RESET_EP_QUIRK && - ep_state & EP_HALTED) { - /* Clear our internal halted state and restart ring */ - xhci->devs[slot_id]->eps[ep_index].ep_state &= - ~EP_HALTED; - ring_ep_doorbell(xhci, slot_id, ep_index); - } else { - xhci->devs[slot_id]->cmd_status = - GET_COMP_CODE(event->status); - complete(&xhci->devs[slot_id]->cmd_completion); - } - break; - case TRB_TYPE(TRB_EVAL_CONTEXT): - virt_dev = xhci->devs[slot_id]; - if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event)) - break; xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status); complete(&xhci->devs[slot_id]->cmd_completion); break; @@ -906,9 +805,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, struct xhci_transfer_event *event) { struct xhci_virt_device *xdev; - struct xhci_virt_ep *ep; struct xhci_ring *ep_ring; - unsigned int slot_id; int ep_index; struct xhci_td *td = 0; dma_addr_t event_dma; @@ -917,11 +814,9 @@ static int handle_tx_event(struct xhci_hcd *xhci, struct urb *urb = 0; int status = -EINPROGRESS; struct xhci_ep_ctx *ep_ctx; - u32 trb_comp_code; xhci_dbg(xhci, "In %s\n", __func__); - slot_id = TRB_TO_SLOT_ID(event->flags); - xdev = xhci->devs[slot_id]; + xdev = xhci->devs[TRB_TO_SLOT_ID(event->flags)]; if (!xdev) { xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n"); return -ENODEV; @@ -930,8 +825,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, /* Endpoint ID is 1 based, our index is zero based */ ep_index = TRB_TO_EP_ID(event->flags) - 1; xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index); - ep = &xdev->eps[ep_index]; - ep_ring = ep->ring; + ep_ring = xdev->ep_rings[ep_index]; ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); if (!ep_ring || (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) { xhci_err(xhci, "ERROR Transfer event pointed to disabled endpoint\n"); @@ -976,8 +870,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, (unsigned int) event->flags); /* Look for common error cases */ - trb_comp_code = GET_COMP_CODE(event->transfer_len); - switch (trb_comp_code) { + switch (GET_COMP_CODE(event->transfer_len)) { /* Skip codes that require special handling depending on * transfer type */ @@ -992,7 +885,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, break; case COMP_STALL: xhci_warn(xhci, "WARN: Stalled endpoint\n"); - ep->ep_state |= EP_HALTED; + ep_ring->state |= EP_HALTED; status = -EPIPE; break; case COMP_TRB_ERR: @@ -1020,7 +913,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, /* Was this a control transfer? */ if (usb_endpoint_xfer_control(&td->urb->ep->desc)) { xhci_debug_trb(xhci, xhci->event_ring->dequeue); - switch (trb_comp_code) { + switch (GET_COMP_CODE(event->transfer_len)) { case COMP_SUCCESS: if (event_trb == ep_ring->dequeue) { xhci_warn(xhci, "WARN: Success on ctrl setup TRB without IOC set??\n"); @@ -1035,37 +928,8 @@ static int handle_tx_event(struct xhci_hcd *xhci, break; case COMP_SHORT_TX: xhci_warn(xhci, "WARN: short transfer on control ep\n"); - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - status = -EREMOTEIO; - else - status = 0; + status = -EREMOTEIO; break; - case COMP_BABBLE: - /* The 0.96 spec says a babbling control endpoint - * is not halted. The 0.96 spec says it is. Some HW - * claims to be 0.95 compliant, but it halts the control - * endpoint anyway. Check if a babble halted the - * endpoint. - */ - if (ep_ctx->ep_info != EP_STATE_HALTED) - break; - /* else fall through */ - case COMP_STALL: - /* Did we transfer part of the data (middle) phase? */ - if (event_trb != ep_ring->dequeue && - event_trb != td->last_trb) - td->urb->actual_length = - td->urb->transfer_buffer_length - - TRB_LEN(event->transfer_len); - else - td->urb->actual_length = 0; - - ep->stopped_td = td; - ep->stopped_trb = event_trb; - xhci_queue_reset_ep(xhci, slot_id, ep_index); - xhci_cleanup_stalled_ring(xhci, td->urb->dev, ep_index); - xhci_ring_cmd_db(xhci); - goto td_cleanup; default: /* Others already handled above */ break; @@ -1079,10 +943,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (event_trb == td->last_trb) { if (td->urb->actual_length != 0) { /* Don't overwrite a previously set error code */ - if ((status == -EINPROGRESS || - status == 0) && - (td->urb->transfer_flags - & URB_SHORT_NOT_OK)) + if (status == -EINPROGRESS || status == 0) /* Did we already see a short data stage? */ status = -EREMOTEIO; } else { @@ -1091,7 +952,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, } } else { /* Maybe the event was for the data stage? */ - if (trb_comp_code != COMP_STOP_INVAL) { + if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) { /* We didn't stop on a link TRB in the middle */ td->urb->actual_length = td->urb->transfer_buffer_length - @@ -1103,7 +964,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, } } } else { - switch (trb_comp_code) { + switch (GET_COMP_CODE(event->transfer_len)) { case COMP_SUCCESS: /* Double check that the HW transferred everything. */ if (event_trb != td->last_trb) { @@ -1114,12 +975,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, else status = 0; } else { - if (usb_endpoint_xfer_bulk(&td->urb->ep->desc)) - xhci_dbg(xhci, "Successful bulk " - "transfer!\n"); - else - xhci_dbg(xhci, "Successful interrupt " - "transfer!\n"); + xhci_dbg(xhci, "Successful bulk transfer!\n"); status = 0; } break; @@ -1145,17 +1001,11 @@ static int handle_tx_event(struct xhci_hcd *xhci, td->urb->actual_length = td->urb->transfer_buffer_length - TRB_LEN(event->transfer_len); - if (td->urb->transfer_buffer_length < - td->urb->actual_length) { + if (td->urb->actual_length < 0) { xhci_warn(xhci, "HC gave bad length " "of %d bytes left\n", TRB_LEN(event->transfer_len)); td->urb->actual_length = 0; - if (td->urb->transfer_flags & - URB_SHORT_NOT_OK) - status = -EREMOTEIO; - else - status = 0; } /* Don't overwrite a previously set error code */ if (status == -EINPROGRESS) { @@ -1191,31 +1041,30 @@ static int handle_tx_event(struct xhci_hcd *xhci, /* If the ring didn't stop on a Link or No-op TRB, add * in the actual bytes transferred from the Normal TRB */ - if (trb_comp_code != COMP_STOP_INVAL) + if (GET_COMP_CODE(event->transfer_len) != COMP_STOP_INVAL) td->urb->actual_length += TRB_LEN(cur_trb->generic.field[2]) - TRB_LEN(event->transfer_len); } } - if (trb_comp_code == COMP_STOP_INVAL || - trb_comp_code == COMP_STOP) { + if (GET_COMP_CODE(event->transfer_len) == COMP_STOP_INVAL || + GET_COMP_CODE(event->transfer_len) == COMP_STOP) { /* The Endpoint Stop Command completion will take care of any * stopped TDs. A stopped TD may be restarted, so don't update * the ring dequeue pointer or take this TD off any lists yet. */ - ep->stopped_td = td; - ep->stopped_trb = event_trb; + ep_ring->stopped_td = td; + ep_ring->stopped_trb = event_trb; } else { - if (trb_comp_code == COMP_STALL || - trb_comp_code == COMP_BABBLE) { + if (GET_COMP_CODE(event->transfer_len) == COMP_STALL) { /* The transfer is completed from the driver's * perspective, but we need to issue a set dequeue * command for this stalled endpoint to move the dequeue * pointer past the TD. We can't do that here because * the halt condition must be cleared first. */ - ep->stopped_td = td; - ep->stopped_trb = event_trb; + ep_ring->stopped_td = td; + ep_ring->stopped_trb = event_trb; } else { /* Update ring dequeue pointer */ while (ep_ring->dequeue != td->last_trb) @@ -1223,41 +1072,16 @@ static int handle_tx_event(struct xhci_hcd *xhci, inc_deq(xhci, ep_ring, false); } -td_cleanup: /* Clean up the endpoint's TD list */ urb = td->urb; - /* Do one last check of the actual transfer length. - * If the host controller said we transferred more data than - * the buffer length, urb->actual_length will be a very big - * number (since it's unsigned). Play it safe and say we didn't - * transfer anything. - */ - if (urb->actual_length > urb->transfer_buffer_length) { - xhci_warn(xhci, "URB transfer length is wrong, " - "xHC issue? req. len = %u, " - "act. len = %u\n", - urb->transfer_buffer_length, - urb->actual_length); - urb->actual_length = 0; - if (td->urb->transfer_flags & URB_SHORT_NOT_OK) - status = -EREMOTEIO; - else - status = 0; - } list_del(&td->td_list); /* Was this TD slated to be cancelled but completed anyway? */ if (!list_empty(&td->cancelled_td_list)) { list_del(&td->cancelled_td_list); - ep->cancels_pending--; + ep_ring->cancels_pending--; } - /* Leave the TD around for the reset endpoint function to use - * (but only if it's not a control endpoint, since we already - * queued the Set TR dequeue pointer command for stalled - * control endpoints). - */ - if (usb_endpoint_xfer_control(&urb->ep->desc) || - (trb_comp_code != COMP_STALL && - trb_comp_code != COMP_BABBLE)) { + /* Leave the TD around for the reset endpoint function to use */ + if (GET_COMP_CODE(event->transfer_len) != COMP_STALL) { kfree(td); } urb->hcpriv = NULL; @@ -1270,7 +1094,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, if (urb) { usb_hcd_unlink_urb_from_ep(xhci_to_hcd(xhci), urb); xhci_dbg(xhci, "Giveback URB %p, len = %d, status = %d\n", - urb, urb->actual_length, status); + urb, td->urb->actual_length, status); spin_unlock(&xhci->lock); usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, status); spin_lock(&xhci->lock); @@ -1411,7 +1235,7 @@ static int prepare_transfer(struct xhci_hcd *xhci, { int ret; struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index); - ret = prepare_ring(xhci, xdev->eps[ep_index].ring, + ret = prepare_ring(xhci, xdev->ep_rings[ep_index], ep_ctx->ep_info & EP_STATE_MASK, num_trbs, mem_flags); if (ret) @@ -1431,9 +1255,9 @@ static int prepare_transfer(struct xhci_hcd *xhci, (*td)->urb = urb; urb->hcpriv = (void *) (*td); /* Add this TD to the tail of the endpoint ring's TD list */ - list_add_tail(&(*td)->td_list, &xdev->eps[ep_index].ring->td_list); - (*td)->start_seg = xdev->eps[ep_index].ring->enq_seg; - (*td)->first_trb = xdev->eps[ep_index].ring->enqueue; + list_add_tail(&(*td)->td_list, &xdev->ep_rings[ep_index]->td_list); + (*td)->start_seg = xdev->ep_rings[ep_index]->enq_seg; + (*td)->first_trb = xdev->ep_rings[ep_index]->enqueue; return 0; } @@ -1511,47 +1335,6 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id, ring_ep_doorbell(xhci, slot_id, ep_index); } -/* - * xHCI uses normal TRBs for both bulk and interrupt. When the interrupt - * endpoint is to be serviced, the xHC will consume (at most) one TD. A TD - * (comprised of sg list entries) can take several service intervals to - * transmit. - */ -int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, - struct urb *urb, int slot_id, unsigned int ep_index) -{ - struct xhci_ep_ctx *ep_ctx = xhci_get_ep_ctx(xhci, - xhci->devs[slot_id]->out_ctx, ep_index); - int xhci_interval; - int ep_interval; - - xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info); - ep_interval = urb->interval; - /* Convert to microframes */ - if (urb->dev->speed == USB_SPEED_LOW || - urb->dev->speed == USB_SPEED_FULL) - ep_interval *= 8; - /* FIXME change this to a warning and a suggestion to use the new API - * to set the polling interval (once the API is added). - */ - if (xhci_interval != ep_interval) { - if (!printk_ratelimit()) - dev_dbg(&urb->dev->dev, "Driver uses different interval" - " (%d microframe%s) than xHCI " - "(%d microframe%s)\n", - ep_interval, - ep_interval == 1 ? "" : "s", - xhci_interval, - xhci_interval == 1 ? "" : "s"); - urb->interval = xhci_interval; - /* Convert back to frames for LS/FS devices */ - if (urb->dev->speed == USB_SPEED_LOW || - urb->dev->speed == USB_SPEED_FULL) - urb->interval /= 8; - } - return xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); -} - static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index) { @@ -1567,7 +1350,7 @@ static int queue_bulk_sg_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct xhci_generic_trb *start_trb; int start_cycle; - ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; + ep_ring = xhci->devs[slot_id]->ep_rings[ep_index]; num_trbs = count_sg_trbs_needed(xhci, urb); num_sgs = urb->num_sgs; @@ -1700,7 +1483,7 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, if (urb->sg) return queue_bulk_sg_tx(xhci, mem_flags, urb, slot_id, ep_index); - ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; + ep_ring = xhci->devs[slot_id]->ep_rings[ep_index]; num_trbs = 0; /* How much data is (potentially) left before the 64KB boundary? */ @@ -1811,7 +1594,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, u32 field, length_field; struct xhci_td *td; - ep_ring = xhci->devs[slot_id]->eps[ep_index].ring; + ep_ring = xhci->devs[slot_id]->ep_rings[ep_index]; /* * Need to copy setup packet into setup TRB, so we can't use the setup @@ -1894,27 +1677,12 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, /**** Command Ring Operations ****/ -/* Generic function for queueing a command TRB on the command ring. - * Check to make sure there's room on the command ring for one command TRB. - * Also check that there's room reserved for commands that must not fail. - * If this is a command that must not fail, meaning command_must_succeed = TRUE, - * then only check for the number of reserved spots. - * Don't decrement xhci->cmd_ring_reserved_trbs after we've queued the TRB - * because the command event handler may want to resubmit a failed command. - */ -static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2, - u32 field3, u32 field4, bool command_must_succeed) +/* Generic function for queueing a command TRB on the command ring */ +static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2, u32 field3, u32 field4) { - int reserved_trbs = xhci->cmd_ring_reserved_trbs; - if (!command_must_succeed) - reserved_trbs++; - - if (!room_on_ring(xhci, xhci->cmd_ring, reserved_trbs)) { + if (!room_on_ring(xhci, xhci->cmd_ring, 1)) { if (!in_interrupt()) xhci_err(xhci, "ERR: No room for command on command ring\n"); - if (command_must_succeed) - xhci_err(xhci, "ERR: Reserved TRB counting for " - "unfailable commands failed.\n"); return -ENOMEM; } queue_trb(xhci, xhci->cmd_ring, false, field1, field2, field3, @@ -1925,7 +1693,7 @@ static int queue_command(struct xhci_hcd *xhci, u32 field1, u32 field2, /* Queue a no-op command on the command ring */ static int queue_cmd_noop(struct xhci_hcd *xhci) { - return queue_command(xhci, 0, 0, 0, TRB_TYPE(TRB_CMD_NOOP), false); + return queue_command(xhci, 0, 0, 0, TRB_TYPE(TRB_CMD_NOOP)); } /* @@ -1944,7 +1712,7 @@ void *xhci_setup_one_noop(struct xhci_hcd *xhci) int xhci_queue_slot_control(struct xhci_hcd *xhci, u32 trb_type, u32 slot_id) { return queue_command(xhci, 0, 0, 0, - TRB_TYPE(trb_type) | SLOT_ID_FOR_TRB(slot_id), false); + TRB_TYPE(trb_type) | SLOT_ID_FOR_TRB(slot_id)); } /* Queue an address device command TRB */ @@ -1953,28 +1721,16 @@ int xhci_queue_address_device(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, { return queue_command(xhci, lower_32_bits(in_ctx_ptr), upper_32_bits(in_ctx_ptr), 0, - TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id), - false); + TRB_TYPE(TRB_ADDR_DEV) | SLOT_ID_FOR_TRB(slot_id)); } /* Queue a configure endpoint command TRB */ int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, - u32 slot_id, bool command_must_succeed) -{ - return queue_command(xhci, lower_32_bits(in_ctx_ptr), - upper_32_bits(in_ctx_ptr), 0, - TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id), - command_must_succeed); -} - -/* Queue an evaluate context command TRB */ -int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id) { return queue_command(xhci, lower_32_bits(in_ctx_ptr), upper_32_bits(in_ctx_ptr), 0, - TRB_TYPE(TRB_EVAL_CONTEXT) | SLOT_ID_FOR_TRB(slot_id), - false); + TRB_TYPE(TRB_CONFIG_EP) | SLOT_ID_FOR_TRB(slot_id)); } int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, @@ -1985,7 +1741,7 @@ int xhci_queue_stop_endpoint(struct xhci_hcd *xhci, int slot_id, u32 type = TRB_TYPE(TRB_STOP_RING); return queue_command(xhci, 0, 0, 0, - trb_slot_id | trb_ep_index | type, false); + trb_slot_id | trb_ep_index | type); } /* Set Transfer Ring Dequeue Pointer command. @@ -2009,7 +1765,7 @@ static int queue_set_tr_deq(struct xhci_hcd *xhci, int slot_id, } return queue_command(xhci, lower_32_bits(addr) | cycle_state, upper_32_bits(addr), 0, - trb_slot_id | trb_ep_index | type, false); + trb_slot_id | trb_ep_index | type); } int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, @@ -2019,6 +1775,5 @@ int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, u32 trb_ep_index = EP_ID_FOR_TRB(ep_index); u32 type = TRB_TYPE(TRB_RESET_EP); - return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type, - false); + return queue_command(xhci, 0, 0, 0, trb_slot_id | trb_ep_index | type); } diff --git a/trunk/drivers/usb/host/xhci.h b/trunk/drivers/usb/host/xhci.h index 4b254b6fa245..ffe1625d4e1b 100644 --- a/trunk/drivers/usb/host/xhci.h +++ b/trunk/drivers/usb/host/xhci.h @@ -509,8 +509,6 @@ struct xhci_slot_ctx { #define MAX_EXIT (0xffff) /* Root hub port number that is needed to access the USB device */ #define ROOT_HUB_PORT(p) (((p) & 0xff) << 16) -/* Maximum number of ports under a hub device */ -#define XHCI_MAX_PORTS(p) (((p) & 0xff) << 24) /* tt_info bitmasks */ /* @@ -524,7 +522,6 @@ struct xhci_slot_ctx { * '0' if the device is not low or full speed. */ #define TT_PORT (0xff << 8) -#define TT_THINK_TIME(p) (((p) & 0x3) << 16) /* dev_state bitmasks */ /* USB device address - assigned by the HC */ @@ -584,7 +581,6 @@ struct xhci_ep_ctx { /* bit 15 is Linear Stream Array */ /* Interval - period between requests to an endpoint - 125u increments. */ #define EP_INTERVAL(p) ((p & 0xff) << 16) -#define EP_INTERVAL_TO_UFRAMES(p) (1 << (((p) >> 16) & 0xff)) /* ep_info2 bitmasks */ /* @@ -593,7 +589,6 @@ struct xhci_ep_ctx { */ #define FORCE_EVENT (0x1) #define ERROR_COUNT(p) (((p) & 0x3) << 1) -#define CTX_TO_EP_TYPE(p) (((p) >> 3) & 0x7) #define EP_TYPE(p) ((p) << 3) #define ISOC_OUT_EP 1 #define BULK_OUT_EP 2 @@ -606,8 +601,6 @@ struct xhci_ep_ctx { /* bit 7 is Host Initiate Disable - for disabling stream selection */ #define MAX_BURST(p) (((p)&0xff) << 8) #define MAX_PACKET(p) (((p)&0xffff) << 16) -#define MAX_PACKET_MASK (0xffff << 16) -#define MAX_PACKET_DECODED(p) (((p) >> 16) & 0xffff) /** @@ -623,44 +616,11 @@ struct xhci_input_control_ctx { u32 rsvd2[6]; }; -/* Represents everything that is needed to issue a command on the command ring. - * It's useful to pre-allocate these for commands that cannot fail due to - * out-of-memory errors, like freeing streams. - */ -struct xhci_command { - /* Input context for changing device state */ - struct xhci_container_ctx *in_ctx; - u32 status; - /* If completion is null, no one is waiting on this command - * and the structure can be freed after the command completes. - */ - struct completion *completion; - union xhci_trb *command_trb; - struct list_head cmd_list; -}; - /* drop context bitmasks */ #define DROP_EP(x) (0x1 << x) /* add context bitmasks */ #define ADD_EP(x) (0x1 << x) -struct xhci_virt_ep { - struct xhci_ring *ring; - /* Temporary storage in case the configure endpoint command fails and we - * have to restore the device state to the previous state - */ - struct xhci_ring *new_ring; - unsigned int ep_state; -#define SET_DEQ_PENDING (1 << 0) -#define EP_HALTED (1 << 1) - /* ---- Related to URB cancellation ---- */ - struct list_head cancelled_td_list; - unsigned int cancels_pending; - /* The TRB that was last reported in a stopped endpoint ring */ - union xhci_trb *stopped_trb; - struct xhci_td *stopped_td; -}; - struct xhci_virt_device { /* * Commands to the hardware are passed an "input context" that @@ -673,11 +633,16 @@ struct xhci_virt_device { struct xhci_container_ctx *out_ctx; /* Used for addressing devices and configuration changes */ struct xhci_container_ctx *in_ctx; - struct xhci_virt_ep eps[31]; + + /* FIXME when stream support is added */ + struct xhci_ring *ep_rings[31]; + /* Temporary storage in case the configure endpoint command fails and we + * have to restore the device state to the previous state + */ + struct xhci_ring *new_ep_rings[31]; struct completion cmd_completion; /* Status of the last command issued for this device */ u32 cmd_status; - struct list_head cmd_list; }; @@ -940,8 +905,6 @@ union xhci_trb { * It must also be greater than 16. */ #define TRBS_PER_SEGMENT 64 -/* Allow two commands + a link TRB, along with any reserved command TRBs */ -#define MAX_RSVD_CMD_TRBS (TRBS_PER_SEGMENT - 3) #define SEGMENT_SIZE (TRBS_PER_SEGMENT*16) /* TRB buffer pointers can't cross 64KB boundaries */ #define TRB_MAX_BUFF_SHIFT 16 @@ -963,12 +926,6 @@ struct xhci_td { union xhci_trb *last_trb; }; -struct xhci_dequeue_state { - struct xhci_segment *new_deq_seg; - union xhci_trb *new_deq_ptr; - int new_cycle_state; -}; - struct xhci_ring { struct xhci_segment *first_seg; union xhci_trb *enqueue; @@ -978,6 +935,15 @@ struct xhci_ring { struct xhci_segment *deq_seg; unsigned int deq_updates; struct list_head td_list; + /* ---- Related to URB cancellation ---- */ + struct list_head cancelled_td_list; + unsigned int cancels_pending; + unsigned int state; +#define SET_DEQ_PENDING (1 << 0) +#define EP_HALTED (1 << 1) + /* The TRB that was last reported in a stopped endpoint ring */ + union xhci_trb *stopped_trb; + struct xhci_td *stopped_td; /* * Write the cycle state into the TRB cycle field to give ownership of * the TRB to the host controller (if we are the producer), or to check @@ -986,6 +952,12 @@ struct xhci_ring { u32 cycle_state; }; +struct xhci_dequeue_state { + struct xhci_segment *new_deq_seg; + union xhci_trb *new_deq_ptr; + int new_cycle_state; +}; + struct xhci_erst_entry { /* 64-bit event ring segment address */ u64 seg_addr; @@ -1062,7 +1034,6 @@ struct xhci_hcd { /* data structures */ struct xhci_device_context_array *dcbaa; struct xhci_ring *cmd_ring; - unsigned int cmd_ring_reserved_trbs; struct xhci_ring *event_ring; struct xhci_erst erst; /* Scratchpad */ @@ -1087,9 +1058,6 @@ struct xhci_hcd { int noops_submitted; int noops_handled; int error_bitmask; - unsigned int quirks; -#define XHCI_LINK_TRB_QUIRK (1 << 0) -#define XHCI_RESET_EP_QUIRK (1 << 1) }; /* For testing purposes */ @@ -1168,13 +1136,6 @@ static inline void xhci_write_64(struct xhci_hcd *xhci, writel(val_hi, ptr + 1); } -static inline int xhci_link_trb_quirk(struct xhci_hcd *xhci) -{ - u32 temp = xhci_readl(xhci, &xhci->cap_regs->hc_capbase); - return ((HC_VERSION(temp) == 0x95) && - (xhci->quirks & XHCI_LINK_TRB_QUIRK)); -} - /* xHCI debugging */ void xhci_print_ir_set(struct xhci_hcd *xhci, struct xhci_intr_reg *ir_set, int set_num); void xhci_print_registers(struct xhci_hcd *xhci); @@ -1197,24 +1158,11 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id, struct usb_device int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *udev); unsigned int xhci_get_endpoint_index(struct usb_endpoint_descriptor *desc); unsigned int xhci_get_endpoint_flag(struct usb_endpoint_descriptor *desc); -unsigned int xhci_get_endpoint_flag_from_index(unsigned int ep_index); -unsigned int xhci_last_valid_endpoint(u32 added_ctxs); void xhci_endpoint_zero(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_host_endpoint *ep); -void xhci_endpoint_copy(struct xhci_hcd *xhci, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx, - unsigned int ep_index); -void xhci_slot_copy(struct xhci_hcd *xhci, - struct xhci_container_ctx *in_ctx, - struct xhci_container_ctx *out_ctx); int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev, struct usb_device *udev, struct usb_host_endpoint *ep, gfp_t mem_flags); void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring); -struct xhci_command *xhci_alloc_command(struct xhci_hcd *xhci, - bool allocate_completion, gfp_t mem_flags); -void xhci_free_command(struct xhci_hcd *xhci, - struct xhci_command *command); #ifdef CONFIG_PCI /* xHCI PCI glue */ @@ -1234,8 +1182,6 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd); int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev); void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev); int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev); -int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev, - struct usb_tt *tt, gfp_t mem_flags); int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags); int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status); int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev, struct usb_host_endpoint *ep); @@ -1259,11 +1205,7 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, int slot_id, unsigned int ep_index); -int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags, struct urb *urb, - int slot_id, unsigned int ep_index); int xhci_queue_configure_endpoint(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, - u32 slot_id, bool command_must_succeed); -int xhci_queue_evaluate_context(struct xhci_hcd *xhci, dma_addr_t in_ctx_ptr, u32 slot_id); int xhci_queue_reset_ep(struct xhci_hcd *xhci, int slot_id, unsigned int ep_index); @@ -1271,13 +1213,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci, unsigned int slot_id, unsigned int ep_index, struct xhci_td *cur_td, struct xhci_dequeue_state *state); void xhci_queue_new_dequeue_state(struct xhci_hcd *xhci, - unsigned int slot_id, unsigned int ep_index, - struct xhci_dequeue_state *deq_state); -void xhci_cleanup_stalled_ring(struct xhci_hcd *xhci, - struct usb_device *udev, unsigned int ep_index); -void xhci_queue_config_ep_quirk(struct xhci_hcd *xhci, - unsigned int slot_id, unsigned int ep_index, - struct xhci_dequeue_state *deq_state); + struct xhci_ring *ep_ring, unsigned int slot_id, + unsigned int ep_index, struct xhci_dequeue_state *deq_state); /* xHCI roothub code */ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, diff --git a/trunk/drivers/usb/image/microtek.c b/trunk/drivers/usb/image/microtek.c index 459a7287fe01..4541dfcea88f 100644 --- a/trunk/drivers/usb/image/microtek.c +++ b/trunk/drivers/usb/image/microtek.c @@ -653,6 +653,33 @@ static struct scsi_host_template mts_scsi_host_template = { .max_sectors= 256, /* 128 K */ }; +struct vendor_product +{ + char* name; + enum + { + mts_sup_unknown=0, + mts_sup_alpha, + mts_sup_full + } + support_status; +} ; + + +/* These are taken from the msmUSB.inf file on the Windows driver CD */ +static const struct vendor_product mts_supported_products[] = +{ + { "Phantom 336CX", mts_sup_unknown}, + { "Phantom 336CX", mts_sup_unknown}, + { "Scanmaker X6", mts_sup_alpha}, + { "Phantom C6", mts_sup_unknown}, + { "Phantom 336CX", mts_sup_unknown}, + { "ScanMaker V6USL", mts_sup_unknown}, + { "ScanMaker V6USL", mts_sup_unknown}, + { "Scanmaker V6UL", mts_sup_unknown}, + { "Scanmaker V6UPL", mts_sup_alpha}, +}; + /* The entries of microtek_table must correspond, line-by-line to the entries of mts_supported_products[]. */ @@ -684,6 +711,7 @@ static int mts_usb_probe(struct usb_interface *intf, int err_retval = -ENOMEM; struct mts_desc * new_desc; + struct vendor_product const* p; struct usb_device *dev = interface_to_usbdev (intf); /* the current altsetting on the interface we're probing */ @@ -698,6 +726,15 @@ static int mts_usb_probe(struct usb_interface *intf, MTS_DEBUG_GOT_HERE(); + p = &mts_supported_products[id - mts_usb_ids]; + + MTS_DEBUG_GOT_HERE(); + + MTS_DEBUG( "found model %s\n", p->name ); + if ( p->support_status != mts_sup_full ) + MTS_MESSAGE( "model %s is not known to be fully supported, reports welcome!\n", + p->name ); + /* the current altsetting on the interface we're probing */ altsetting = intf->cur_altsetting; diff --git a/trunk/drivers/usb/misc/idmouse.c b/trunk/drivers/usb/misc/idmouse.c index 1337a9ce80b9..6da8887538c7 100644 --- a/trunk/drivers/usb/misc/idmouse.c +++ b/trunk/drivers/usb/misc/idmouse.c @@ -96,8 +96,6 @@ static int idmouse_probe(struct usb_interface *interface, const struct usb_device_id *id); static void idmouse_disconnect(struct usb_interface *interface); -static int idmouse_suspend(struct usb_interface *intf, pm_message_t message); -static int idmouse_resume(struct usb_interface *intf); /* file operation pointers */ static const struct file_operations idmouse_fops = { @@ -119,11 +117,7 @@ static struct usb_driver idmouse_driver = { .name = DRIVER_SHORT, .probe = idmouse_probe, .disconnect = idmouse_disconnect, - .suspend = idmouse_suspend, - .resume = idmouse_resume, - .reset_resume = idmouse_resume, .id_table = idmouse_table, - .supports_autosuspend = 1, }; static int idmouse_create_image(struct usb_idmouse *dev) @@ -203,17 +197,6 @@ static int idmouse_create_image(struct usb_idmouse *dev) return result; } -/* PM operations are nops as this driver does IO only during open() */ -static int idmouse_suspend(struct usb_interface *intf, pm_message_t message) -{ - return 0; -} - -static int idmouse_resume(struct usb_interface *intf) -{ - return 0; -} - static inline void idmouse_delete(struct usb_idmouse *dev) { kfree(dev->bulk_in_buffer); @@ -252,13 +235,9 @@ static int idmouse_open(struct inode *inode, struct file *file) } else { /* create a new image and check for success */ - result = usb_autopm_get_interface(interface); - if (result) - goto error; result = idmouse_create_image (dev); if (result) goto error; - usb_autopm_put_interface(interface); /* increment our usage count for the driver */ ++dev->open; diff --git a/trunk/drivers/usb/misc/ldusb.c b/trunk/drivers/usb/misc/ldusb.c index 90f130126c10..ad4fb15b5dcb 100644 --- a/trunk/drivers/usb/misc/ldusb.c +++ b/trunk/drivers/usb/misc/ldusb.c @@ -412,9 +412,6 @@ static unsigned int ld_usb_poll(struct file *file, poll_table *wait) dev = file->private_data; - if (!dev->intf) - return POLLERR | POLLHUP; - poll_wait(file, &dev->read_wait, wait); poll_wait(file, &dev->write_wait, wait); @@ -770,9 +767,6 @@ static void ld_usb_disconnect(struct usb_interface *intf) ld_usb_delete(dev); } else { dev->intf = NULL; - /* wake up pollers */ - wake_up_interruptible_all(&dev->read_wait); - wake_up_interruptible_all(&dev->write_wait); mutex_unlock(&dev->mutex); } diff --git a/trunk/drivers/usb/misc/legousbtower.c b/trunk/drivers/usb/misc/legousbtower.c index faa6d623de78..97efeaec4d52 100644 --- a/trunk/drivers/usb/misc/legousbtower.c +++ b/trunk/drivers/usb/misc/legousbtower.c @@ -552,9 +552,6 @@ static unsigned int tower_poll (struct file *file, poll_table *wait) dev = file->private_data; - if (!dev->udev) - return POLLERR | POLLHUP; - poll_wait(file, &dev->read_wait, wait); poll_wait(file, &dev->write_wait, wait); @@ -1028,9 +1025,6 @@ static void tower_disconnect (struct usb_interface *interface) tower_delete (dev); } else { dev->udev = NULL; - /* wake up pollers */ - wake_up_interruptible_all(&dev->read_wait); - wake_up_interruptible_all(&dev->write_wait); mutex_unlock(&dev->lock); } diff --git a/trunk/drivers/usb/misc/sisusbvga/sisusb.c b/trunk/drivers/usb/misc/sisusbvga/sisusb.c index 0025847743f3..b4ec716de7da 100644 --- a/trunk/drivers/usb/misc/sisusbvga/sisusb.c +++ b/trunk/drivers/usb/misc/sisusbvga/sisusb.c @@ -79,12 +79,14 @@ sisusb_free_buffers(struct sisusb_usb_data *sisusb) for (i = 0; i < NUMOBUFS; i++) { if (sisusb->obuf[i]) { - kfree(sisusb->obuf[i]); + usb_buffer_free(sisusb->sisusb_dev, sisusb->obufsize, + sisusb->obuf[i], sisusb->transfer_dma_out[i]); sisusb->obuf[i] = NULL; } } if (sisusb->ibuf) { - kfree(sisusb->ibuf); + usb_buffer_free(sisusb->sisusb_dev, sisusb->ibufsize, + sisusb->ibuf, sisusb->transfer_dma_in); sisusb->ibuf = NULL; } } @@ -228,7 +230,8 @@ sisusb_bulk_completeout(struct urb *urb) static int sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, void *data, - int len, int *actual_length, int timeout, unsigned int tflags) + int len, int *actual_length, int timeout, unsigned int tflags, + dma_addr_t transfer_dma) { struct urb *urb = sisusb->sisurbout[index]; int retval, byteswritten = 0; @@ -242,6 +245,9 @@ sisusb_bulkout_msg(struct sisusb_usb_data *sisusb, int index, unsigned int pipe, urb->transfer_flags |= tflags; urb->actual_length = 0; + if ((urb->transfer_dma = transfer_dma)) + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + /* Set up context */ sisusb->urbout_context[index].actual_length = (timeout) ? NULL : actual_length; @@ -291,8 +297,8 @@ sisusb_bulk_completein(struct urb *urb) } static int -sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, - int len, int *actual_length, int timeout, unsigned int tflags) +sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, int len, + int *actual_length, int timeout, unsigned int tflags, dma_addr_t transfer_dma) { struct urb *urb = sisusb->sisurbin; int retval, readbytes = 0; @@ -305,6 +311,9 @@ sisusb_bulkin_msg(struct sisusb_usb_data *sisusb, unsigned int pipe, void *data, urb->transfer_flags |= tflags; urb->actual_length = 0; + if ((urb->transfer_dma = transfer_dma)) + urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; + sisusb->completein = 0; retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval == 0) { @@ -413,7 +422,8 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, thispass, &transferred_len, async ? 0 : 5 * HZ, - tflags); + tflags, + sisusb->transfer_dma_out[index]); if (result == -ETIMEDOUT) { @@ -422,16 +432,29 @@ static int sisusb_send_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, return -ETIME; continue; - } - if ((result == 0) && !async && transferred_len) { + } else if ((result == 0) && !async && transferred_len) { thispass -= transferred_len; - buffer += transferred_len; + if (thispass) { + if (sisusb->transfer_dma_out) { + /* If DMA, copy remaining + * to beginning of buffer + */ + memcpy(buffer, + buffer + transferred_len, + thispass); + } else { + /* If not DMA, simply increase + * the pointer + */ + buffer += transferred_len; + } + } } else break; - } + }; if (result) return result; @@ -507,7 +530,8 @@ static int sisusb_recv_bulk_msg(struct sisusb_usb_data *sisusb, int ep, int len, thispass, &transferred_len, 5 * HZ, - tflags); + tflags, + sisusb->transfer_dma_in); if (transferred_len) thispass = transferred_len; @@ -3108,7 +3132,8 @@ static int sisusb_probe(struct usb_interface *intf, /* Allocate buffers */ sisusb->ibufsize = SISUSB_IBUF_SIZE; - if (!(sisusb->ibuf = kmalloc(SISUSB_IBUF_SIZE, GFP_KERNEL))) { + if (!(sisusb->ibuf = usb_buffer_alloc(dev, SISUSB_IBUF_SIZE, + GFP_KERNEL, &sisusb->transfer_dma_in))) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for input buffer"); retval = -ENOMEM; goto error_2; @@ -3117,7 +3142,9 @@ static int sisusb_probe(struct usb_interface *intf, sisusb->numobufs = 0; sisusb->obufsize = SISUSB_OBUF_SIZE; for (i = 0; i < NUMOBUFS; i++) { - if (!(sisusb->obuf[i] = kmalloc(SISUSB_OBUF_SIZE, GFP_KERNEL))) { + if (!(sisusb->obuf[i] = usb_buffer_alloc(dev, SISUSB_OBUF_SIZE, + GFP_KERNEL, + &sisusb->transfer_dma_out[i]))) { if (i == 0) { dev_err(&sisusb->sisusb_dev->dev, "Failed to allocate memory for output buffer\n"); retval = -ENOMEM; diff --git a/trunk/drivers/usb/misc/sisusbvga/sisusb.h b/trunk/drivers/usb/misc/sisusbvga/sisusb.h index 55492a5930bd..cf0b4a5883f6 100644 --- a/trunk/drivers/usb/misc/sisusbvga/sisusb.h +++ b/trunk/drivers/usb/misc/sisusbvga/sisusb.h @@ -123,6 +123,8 @@ struct sisusb_usb_data { int numobufs; /* number of obufs = number of out urbs */ char *obuf[NUMOBUFS], *ibuf; /* transfer buffers */ int obufsize, ibufsize; + dma_addr_t transfer_dma_out[NUMOBUFS]; + dma_addr_t transfer_dma_in; struct urb *sisurbout[NUMOBUFS]; struct urb *sisurbin; unsigned char urbstatus[NUMOBUFS]; diff --git a/trunk/drivers/usb/misc/usbsevseg.c b/trunk/drivers/usb/misc/usbsevseg.c index 3db255537e79..28a6a3a09538 100644 --- a/trunk/drivers/usb/misc/usbsevseg.c +++ b/trunk/drivers/usb/misc/usbsevseg.c @@ -38,7 +38,6 @@ static char *display_textmodes[] = {"raw", "hex", "ascii", NULL}; struct usb_sevsegdev { struct usb_device *udev; - struct usb_interface *intf; u8 powered; u8 mode_msb; @@ -47,8 +46,6 @@ struct usb_sevsegdev { u8 textmode; u8 text[MAXLEN]; u16 textlength; - - u8 shadow_power; /* for PM */ }; /* sysfs_streq can't replace this completely @@ -68,12 +65,6 @@ static void update_display_powered(struct usb_sevsegdev *mydev) { int rc; - if (!mydev->shadow_power && mydev->powered) { - rc = usb_autopm_get_interface(mydev->intf); - if (rc < 0) - return; - } - rc = usb_control_msg(mydev->udev, usb_sndctrlpipe(mydev->udev, 0), 0x12, @@ -85,18 +76,12 @@ static void update_display_powered(struct usb_sevsegdev *mydev) 2000); if (rc < 0) dev_dbg(&mydev->udev->dev, "power retval = %d\n", rc); - - if (mydev->shadow_power && !mydev->powered) - usb_autopm_put_interface(mydev->intf); } static void update_display_mode(struct usb_sevsegdev *mydev) { int rc; - if(mydev->shadow_power != 1) - return; - rc = usb_control_msg(mydev->udev, usb_sndctrlpipe(mydev->udev, 0), 0x12, @@ -111,17 +96,14 @@ static void update_display_mode(struct usb_sevsegdev *mydev) dev_dbg(&mydev->udev->dev, "mode retval = %d\n", rc); } -static void update_display_visual(struct usb_sevsegdev *mydev, gfp_t mf) +static void update_display_visual(struct usb_sevsegdev *mydev) { int rc; int i; unsigned char *buffer; u8 decimals = 0; - if(mydev->shadow_power != 1) - return; - - buffer = kzalloc(MAXLEN, mf); + buffer = kzalloc(MAXLEN, GFP_KERNEL); if (!buffer) { dev_err(&mydev->udev->dev, "out of memory\n"); return; @@ -181,7 +163,7 @@ static ssize_t set_attr_##name(struct device *dev, \ struct usb_sevsegdev *mydev = usb_get_intfdata(intf); \ \ mydev->name = simple_strtoul(buf, NULL, 10); \ - update_fcn(mydev); \ + update_fcn(mydev); \ \ return count; \ } \ @@ -212,7 +194,7 @@ static ssize_t set_attr_text(struct device *dev, if (end > 0) memcpy(mydev->text, buf, end); - update_display_visual(mydev, GFP_KERNEL); + update_display_visual(mydev); return count; } @@ -260,7 +242,7 @@ static ssize_t set_attr_decimals(struct device *dev, if (buf[i] == '1') mydev->decimals[end-1-i] = 1; - update_display_visual(mydev, GFP_KERNEL); + update_display_visual(mydev); return count; } @@ -304,7 +286,7 @@ static ssize_t set_attr_textmode(struct device *dev, for (i = 0; display_textmodes[i]; i++) { if (sysfs_streq(display_textmodes[i], buf)) { mydev->textmode = i; - update_display_visual(mydev, GFP_KERNEL); + update_display_visual(mydev); return count; } } @@ -348,7 +330,6 @@ static int sevseg_probe(struct usb_interface *interface, } mydev->udev = usb_get_dev(udev); - mydev->intf = interface; usb_set_intfdata(interface, mydev); /*set defaults */ @@ -383,49 +364,11 @@ static void sevseg_disconnect(struct usb_interface *interface) dev_info(&interface->dev, "USB 7 Segment now disconnected\n"); } -static int sevseg_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usb_sevsegdev *mydev; - - mydev = usb_get_intfdata(intf); - mydev->shadow_power = 0; - - return 0; -} - -static int sevseg_resume(struct usb_interface *intf) -{ - struct usb_sevsegdev *mydev; - - mydev = usb_get_intfdata(intf); - mydev->shadow_power = 1; - update_display_mode(mydev); - update_display_visual(mydev, GFP_NOIO); - - return 0; -} - -static int sevseg_reset_resume(struct usb_interface *intf) -{ - struct usb_sevsegdev *mydev; - - mydev = usb_get_intfdata(intf); - mydev->shadow_power = 1; - update_display_mode(mydev); - update_display_visual(mydev, GFP_NOIO); - - return 0; -} - static struct usb_driver sevseg_driver = { .name = "usbsevseg", .probe = sevseg_probe, .disconnect = sevseg_disconnect, - .suspend = sevseg_suspend, - .resume = sevseg_resume, - .reset_resume = sevseg_reset_resume, .id_table = id_table, - .supports_autosuspend = 1, }; static int __init usb_sevseg_init(void) diff --git a/trunk/drivers/usb/mon/Kconfig b/trunk/drivers/usb/mon/Kconfig index 635745f57fbd..f28f350cd96a 100644 --- a/trunk/drivers/usb/mon/Kconfig +++ b/trunk/drivers/usb/mon/Kconfig @@ -5,9 +5,11 @@ config USB_MON tristate "USB Monitor" depends on USB + default y if USB=y + default m if USB=m help If you select this option, a component which captures the USB traffic between peripheral-specific drivers and HC drivers will be built. For more information, see . - If unsure, say Y, if allowed, otherwise M. + If unsure, say Y (if allowed), otherwise M. diff --git a/trunk/drivers/usb/mon/Makefile b/trunk/drivers/usb/mon/Makefile index 384b198faa7c..c6516b566731 100644 --- a/trunk/drivers/usb/mon/Makefile +++ b/trunk/drivers/usb/mon/Makefile @@ -2,6 +2,6 @@ # Makefile for USB monitor # -usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o +usbmon-objs := mon_main.o mon_stat.o mon_text.o mon_bin.o mon_dma.o obj-$(CONFIG_USB_MON) += usbmon.o diff --git a/trunk/drivers/usb/mon/mon_bin.c b/trunk/drivers/usb/mon/mon_bin.c index dfdc43e2e00d..0f7a30b7d2d1 100644 --- a/trunk/drivers/usb/mon/mon_bin.c +++ b/trunk/drivers/usb/mon/mon_bin.c @@ -220,8 +220,9 @@ static void mon_free_buff(struct mon_pgmap *map, int npages); /* * This is a "chunked memcpy". It does not manipulate any counters. + * But it returns the new offset for repeated application. */ -static void mon_copy_to_buff(const struct mon_reader_bin *this, +unsigned int mon_copy_to_buff(const struct mon_reader_bin *this, unsigned int off, const unsigned char *from, unsigned int length) { unsigned int step_len; @@ -246,6 +247,7 @@ static void mon_copy_to_buff(const struct mon_reader_bin *this, from += step_len; length -= step_len; } + return off; } /* @@ -398,8 +400,15 @@ static char mon_bin_get_data(const struct mon_reader_bin *rp, unsigned int offset, struct urb *urb, unsigned int length) { + if (urb->dev->bus->uses_dma && + (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { + mon_dmapeek_vec(rp, offset, urb->transfer_dma, length); + return 0; + } + if (urb->transfer_buffer == NULL) return 'Z'; + mon_copy_to_buff(rp, offset, urb->transfer_buffer, length); return 0; } @@ -626,6 +635,7 @@ static int mon_bin_open(struct inode *inode, struct file *file) spin_lock_init(&rp->b_lock); init_waitqueue_head(&rp->b_wait); mutex_init(&rp->fetch_lock); + rp->b_size = BUFF_DFL; size = sizeof(struct mon_pgmap) * (rp->b_size/CHUNK_SIZE); diff --git a/trunk/drivers/usb/mon/mon_dma.c b/trunk/drivers/usb/mon/mon_dma.c new file mode 100644 index 000000000000..140cc80bd2b1 --- /dev/null +++ b/trunk/drivers/usb/mon/mon_dma.c @@ -0,0 +1,95 @@ +/* + * The USB Monitor, inspired by Dave Harding's USBMon. + * + * mon_dma.c: Library which snoops on DMA areas. + * + * Copyright (C) 2005 Pete Zaitcev (zaitcev@redhat.com) + */ +#include +#include +#include +#include + +#include /* Only needed for declarations in usb_mon.h */ +#include "usb_mon.h" + +/* + * PC-compatibles, are, fortunately, sufficiently cache-coherent for this. + */ +#if defined(__i386__) || defined(__x86_64__) /* CONFIG_ARCH_I386 doesn't exit */ +#define MON_HAS_UNMAP 1 + +#define phys_to_page(phys) pfn_to_page((phys) >> PAGE_SHIFT) + +char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len) +{ + struct page *pg; + unsigned long flags; + unsigned char *map; + unsigned char *ptr; + + /* + * On i386, a DMA handle is the "physical" address of a page. + * In other words, the bus address is equal to physical address. + * There is no IOMMU. + */ + pg = phys_to_page(dma_addr); + + /* + * We are called from hardware IRQs in case of callbacks. + * But we can be called from softirq or process context in case + * of submissions. In such case, we need to protect KM_IRQ0. + */ + local_irq_save(flags); + map = kmap_atomic(pg, KM_IRQ0); + ptr = map + (dma_addr & (PAGE_SIZE-1)); + memcpy(dst, ptr, len); + kunmap_atomic(map, KM_IRQ0); + local_irq_restore(flags); + return 0; +} + +void mon_dmapeek_vec(const struct mon_reader_bin *rp, + unsigned int offset, dma_addr_t dma_addr, unsigned int length) +{ + unsigned long flags; + unsigned int step_len; + struct page *pg; + unsigned char *map; + unsigned long page_off, page_len; + + local_irq_save(flags); + while (length) { + /* compute number of bytes we are going to copy in this page */ + step_len = length; + page_off = dma_addr & (PAGE_SIZE-1); + page_len = PAGE_SIZE - page_off; + if (page_len < step_len) + step_len = page_len; + + /* copy data and advance pointers */ + pg = phys_to_page(dma_addr); + map = kmap_atomic(pg, KM_IRQ0); + offset = mon_copy_to_buff(rp, offset, map + page_off, step_len); + kunmap_atomic(map, KM_IRQ0); + dma_addr += step_len; + length -= step_len; + } + local_irq_restore(flags); +} + +#endif /* __i386__ */ + +#ifndef MON_HAS_UNMAP +char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len) +{ + return 'D'; +} + +void mon_dmapeek_vec(const struct mon_reader_bin *rp, + unsigned int offset, dma_addr_t dma_addr, unsigned int length) +{ + ; +} + +#endif /* MON_HAS_UNMAP */ diff --git a/trunk/drivers/usb/mon/mon_main.c b/trunk/drivers/usb/mon/mon_main.c index e0c2db3b767b..5e0ab4201c00 100644 --- a/trunk/drivers/usb/mon/mon_main.c +++ b/trunk/drivers/usb/mon/mon_main.c @@ -361,6 +361,7 @@ static int __init mon_init(void) } // MOD_INC_USE_COUNT(which_module?); + mutex_lock(&usb_bus_list_lock); list_for_each_entry (ubus, &usb_bus_list, bus_list) { mon_bus_init(ubus); diff --git a/trunk/drivers/usb/mon/mon_text.c b/trunk/drivers/usb/mon/mon_text.c index 9f1a9227ebe6..a7eb4c99342c 100644 --- a/trunk/drivers/usb/mon/mon_text.c +++ b/trunk/drivers/usb/mon/mon_text.c @@ -150,6 +150,20 @@ static inline char mon_text_get_data(struct mon_event_text *ep, struct urb *urb, return '>'; } + /* + * The check to see if it's safe to poke at data has an enormous + * number of corner cases, but it seems that the following is + * more or less safe. + * + * We do not even try to look at transfer_buffer, because it can + * contain non-NULL garbage in case the upper level promised to + * set DMA for the HCD. + */ + if (urb->dev->bus->uses_dma && + (urb->transfer_flags & URB_NO_TRANSFER_DMA_MAP)) { + return mon_dmapeek(ep->data, urb->transfer_dma, len); + } + if (urb->transfer_buffer == NULL) return 'Z'; /* '0' would be not as pretty. */ diff --git a/trunk/drivers/usb/mon/usb_mon.h b/trunk/drivers/usb/mon/usb_mon.h index df9a4df342c7..f5d84ff8c101 100644 --- a/trunk/drivers/usb/mon/usb_mon.h +++ b/trunk/drivers/usb/mon/usb_mon.h @@ -64,6 +64,20 @@ void mon_text_exit(void); int __init mon_bin_init(void); void mon_bin_exit(void); +/* + * DMA interface. + * + * XXX The vectored side needs a serious re-thinking. Abstracting vectors, + * like in Paolo's original patch, produces a double pkmap. We need an idea. +*/ +extern char mon_dmapeek(unsigned char *dst, dma_addr_t dma_addr, int len); + +struct mon_reader_bin; +extern void mon_dmapeek_vec(const struct mon_reader_bin *rp, + unsigned int offset, dma_addr_t dma_addr, unsigned int len); +extern unsigned int mon_copy_to_buff(const struct mon_reader_bin *rp, + unsigned int offset, const unsigned char *from, unsigned int len); + /* */ extern struct mutex mon_lock; diff --git a/trunk/drivers/usb/musb/musb_core.c b/trunk/drivers/usb/musb/musb_core.c index 3a61ddb62bd2..1d26beddf2ca 100644 --- a/trunk/drivers/usb/musb/musb_core.c +++ b/trunk/drivers/usb/musb/musb_core.c @@ -1850,10 +1850,6 @@ static void musb_free(struct musb *musb) dma_controller_destroy(c); } -#ifdef CONFIG_USB_MUSB_OTG - put_device(musb->xceiv->dev); -#endif - musb_writeb(musb->mregs, MUSB_DEVCTL, 0); musb_platform_exit(musb); musb_writeb(musb->mregs, MUSB_DEVCTL, 0); @@ -1863,6 +1859,10 @@ static void musb_free(struct musb *musb) clk_put(musb->clock); } +#ifdef CONFIG_USB_MUSB_OTG + put_device(musb->xceiv->dev); +#endif + #ifdef CONFIG_USB_MUSB_HDRC_HCD usb_put_hcd(musb_to_hcd(musb)); #else diff --git a/trunk/drivers/usb/otg/isp1301_omap.c b/trunk/drivers/usb/otg/isp1301_omap.c index 77a5f4188999..e0d56ef2bcb0 100644 --- a/trunk/drivers/usb/otg/isp1301_omap.c +++ b/trunk/drivers/usb/otg/isp1301_omap.c @@ -117,7 +117,24 @@ static void enable_vbus_draw(struct isp1301 *isp, unsigned mA) pr_debug(" VBUS %d mA error %d\n", mA, status); } -#else +static void enable_vbus_source(struct isp1301 *isp) +{ + /* this board won't supply more than 8mA vbus power. + * some boards can switch a 100ma "unit load" (or more). + */ +} + + +/* products will deliver OTG messages with LEDs, GUI, etc */ +static inline void notresponding(struct isp1301 *isp) +{ + printk(KERN_NOTICE "OTG device not responding.\n"); +} + + +#endif + +#if defined(CONFIG_MACH_OMAP_H4) static void enable_vbus_draw(struct isp1301 *isp, unsigned mA) { @@ -127,8 +144,6 @@ static void enable_vbus_draw(struct isp1301 *isp, unsigned mA) */ } -#endif - static void enable_vbus_source(struct isp1301 *isp) { /* this board won't supply more than 8mA vbus power. @@ -144,6 +159,8 @@ static inline void notresponding(struct isp1301 *isp) } +#endif + /*-------------------------------------------------------------------------*/ static struct i2c_driver isp1301_driver; diff --git a/trunk/drivers/usb/serial/ark3116.c b/trunk/drivers/usb/serial/ark3116.c index 131e61adaaf7..5d25d3e52bf6 100644 --- a/trunk/drivers/usb/serial/ark3116.c +++ b/trunk/drivers/usb/serial/ark3116.c @@ -31,20 +31,10 @@ static int debug; static struct usb_device_id id_table [] = { { USB_DEVICE(0x6547, 0x0232) }, - { USB_DEVICE(0x18ec, 0x3118) }, /* USB to IrDA adapter */ { }, }; MODULE_DEVICE_TABLE(usb, id_table); -static int is_irda(struct usb_serial *serial) -{ - struct usb_device *dev = serial->dev; - if (le16_to_cpu(dev->descriptor.idVendor) == 0x18ec && - le16_to_cpu(dev->descriptor.idProduct) == 0x3118) - return 1; - return 0; -} - static inline void ARK3116_SND(struct usb_serial *serial, int seq, __u8 request, __u8 requesttype, __u16 value, __u16 index) @@ -94,21 +84,11 @@ static int ark3116_attach(struct usb_serial *serial) return -ENOMEM; } - if (is_irda(serial)) - dbg("IrDA mode"); - /* 3 */ ARK3116_SND(serial, 3, 0xFE, 0x40, 0x0008, 0x0002); ARK3116_SND(serial, 4, 0xFE, 0x40, 0x0008, 0x0001); ARK3116_SND(serial, 5, 0xFE, 0x40, 0x0000, 0x0008); - ARK3116_SND(serial, 6, 0xFE, 0x40, is_irda(serial) ? 0x0001 : 0x0000, - 0x000B); - - if (is_irda(serial)) { - ARK3116_SND(serial, 1001, 0xFE, 0x40, 0x0000, 0x000C); - ARK3116_SND(serial, 1002, 0xFE, 0x40, 0x0041, 0x000D); - ARK3116_SND(serial, 1003, 0xFE, 0x40, 0x0001, 0x000A); - } + ARK3116_SND(serial, 6, 0xFE, 0x40, 0x0000, 0x000B); /* <-- seq7 */ ARK3116_RCV(serial, 7, 0xFE, 0xC0, 0x0000, 0x0003, 0x00, buf); @@ -145,8 +125,6 @@ static int ark3116_attach(struct usb_serial *serial) ARK3116_SND(serial, 147, 0xFE, 0x40, 0x0083, 0x0003); ARK3116_SND(serial, 148, 0xFE, 0x40, 0x0038, 0x0000); ARK3116_SND(serial, 149, 0xFE, 0x40, 0x0001, 0x0001); - if (is_irda(serial)) - ARK3116_SND(serial, 1004, 0xFE, 0x40, 0x0000, 0x0009); ARK3116_SND(serial, 150, 0xFE, 0x40, 0x0003, 0x0003); ARK3116_RCV(serial, 151, 0xFE, 0xC0, 0x0000, 0x0004, 0x03, buf); ARK3116_SND(serial, 152, 0xFE, 0x40, 0x0000, 0x0003); diff --git a/trunk/drivers/usb/serial/ch341.c b/trunk/drivers/usb/serial/ch341.c index 59eff721fcc5..8c894a7d5dcf 100644 --- a/trunk/drivers/usb/serial/ch341.c +++ b/trunk/drivers/usb/serial/ch341.c @@ -56,18 +56,6 @@ #define CH341_BAUDBASE_FACTOR 1532620800 #define CH341_BAUDBASE_DIVMAX 3 -/* Break support - the information used to implement this was gleaned from - * the Net/FreeBSD uchcom.c driver by Takanori Watanabe. Domo arigato. - */ - -#define CH341_REQ_WRITE_REG 0x9A -#define CH341_REQ_READ_REG 0x95 -#define CH341_REG_BREAK1 0x05 -#define CH341_REG_BREAK2 0x18 -#define CH341_NBREAK_BITS_REG1 0x01 -#define CH341_NBREAK_BITS_REG2 0x40 - - static int debug; static struct usb_device_id id_table [] = { @@ -385,45 +373,6 @@ static void ch341_set_termios(struct tty_struct *tty, */ } -static void ch341_break_ctl(struct tty_struct *tty, int break_state) -{ - const uint16_t ch341_break_reg = - CH341_REG_BREAK1 | ((uint16_t) CH341_REG_BREAK2 << 8); - struct usb_serial_port *port = tty->driver_data; - int r; - uint16_t reg_contents; - uint8_t break_reg[2]; - - dbg("%s()", __func__); - - r = ch341_control_in(port->serial->dev, CH341_REQ_READ_REG, - ch341_break_reg, 0, break_reg, sizeof(break_reg)); - if (r < 0) { - printk(KERN_WARNING "%s: USB control read error whilst getting" - " break register contents.\n", __FILE__); - return; - } - dbg("%s - initial ch341 break register contents - reg1: %x, reg2: %x", - __func__, break_reg[0], break_reg[1]); - if (break_state != 0) { - dbg("%s - Enter break state requested", __func__); - break_reg[0] &= ~CH341_NBREAK_BITS_REG1; - break_reg[1] &= ~CH341_NBREAK_BITS_REG2; - } else { - dbg("%s - Leave break state requested", __func__); - break_reg[0] |= CH341_NBREAK_BITS_REG1; - break_reg[1] |= CH341_NBREAK_BITS_REG2; - } - dbg("%s - New ch341 break register contents - reg1: %x, reg2: %x", - __func__, break_reg[0], break_reg[1]); - reg_contents = (uint16_t)break_reg[0] | ((uint16_t)break_reg[1] << 8); - r = ch341_control_out(port->serial->dev, CH341_REQ_WRITE_REG, - ch341_break_reg, reg_contents); - if (r < 0) - printk(KERN_WARNING "%s: USB control write error whilst setting" - " break register contents.\n", __FILE__); -} - static int ch341_tiocmset(struct tty_struct *tty, struct file *file, unsigned int set, unsigned int clear) { @@ -627,7 +576,6 @@ static struct usb_serial_driver ch341_device = { .close = ch341_close, .ioctl = ch341_ioctl, .set_termios = ch341_set_termios, - .break_ctl = ch341_break_ctl, .tiocmget = ch341_tiocmget, .tiocmset = ch341_tiocmset, .read_int_callback = ch341_read_int_callback, diff --git a/trunk/drivers/usb/serial/ftdi_sio.c b/trunk/drivers/usb/serial/ftdi_sio.c index 4f883b1773d0..76a17f915eef 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.c +++ b/trunk/drivers/usb/serial/ftdi_sio.c @@ -176,9 +176,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(FTDI_VID, FTDI_MICRO_CHAMELEON_PID) }, { USB_DEVICE(FTDI_VID, FTDI_RELAIS_PID) }, { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_SNIFFER_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_THROTTLE_PID) }, - { USB_DEVICE(FTDI_VID, FTDI_OPENDCC_GATEWAY_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_IOBOARD_PID) }, { USB_DEVICE(INTERBIOMETRICS_VID, INTERBIOMETRICS_MINI_IOBOARD_PID) }, { USB_DEVICE(FTDI_VID, FTDI_SPROG_II) }, @@ -697,8 +694,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(DE_VID, WHT_PID) }, { USB_DEVICE(ADI_VID, ADI_GNICE_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID), - .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) }, { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, @@ -707,8 +702,6 @@ static struct usb_device_id id_table_combined [] = { { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) }, { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID), .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, - { USB_DEVICE(FTDI_VID, HAMEG_HO820_PID) }, - { USB_DEVICE(FTDI_VID, HAMEG_HO870_PID) }, { }, /* Optional parameter entry */ { } /* Terminating entry */ }; diff --git a/trunk/drivers/usb/serial/ftdi_sio.h b/trunk/drivers/usb/serial/ftdi_sio.h index 6f31e0d71898..8c92b88166ae 100644 --- a/trunk/drivers/usb/serial/ftdi_sio.h +++ b/trunk/drivers/usb/serial/ftdi_sio.h @@ -81,9 +81,6 @@ /* OpenDCC (www.opendcc.de) product id */ #define FTDI_OPENDCC_PID 0xBFD8 -#define FTDI_OPENDCC_SNIFFER_PID 0xBFD9 -#define FTDI_OPENDCC_THROTTLE_PID 0xBFDA -#define FTDI_OPENDCC_GATEWAY_PID 0xBFDB /* Sprog II (Andrew Crosland's SprogII DCC interface) */ #define FTDI_SPROG_II 0xF0C8 @@ -933,7 +930,6 @@ */ #define ADI_VID 0x0456 #define ADI_GNICE_PID 0xF000 -#define ADI_GNICEPLUS_PID 0xF001 /* * JETI SPECTROMETER SPECBOS 1201 @@ -971,12 +967,6 @@ */ #define MARVELL_OPENRD_PID 0x9e90 -/* - * Hameg HO820 and HO870 interface (using VID 0x0403) - */ -#define HAMEG_HO820_PID 0xed74 -#define HAMEG_HO870_PID 0xed71 - /* * BmRequestType: 1100 0000b * bRequest: FTDI_E2_READ diff --git a/trunk/drivers/usb/serial/generic.c b/trunk/drivers/usb/serial/generic.c index deba08c7a015..d9398e9f30ce 100644 --- a/trunk/drivers/usb/serial/generic.c +++ b/trunk/drivers/usb/serial/generic.c @@ -19,7 +19,7 @@ #include #include #include -#include + static int debug; @@ -166,6 +166,24 @@ static void generic_cleanup(struct usb_serial_port *port) } } +int usb_serial_generic_resume(struct usb_serial *serial) +{ + struct usb_serial_port *port; + int i, c = 0, r; + + for (i = 0; i < serial->num_ports; i++) { + port = serial->port[i]; + if (port->port.count && port->read_urb) { + r = usb_submit_urb(port->read_urb, GFP_NOIO); + if (r < 0) + c++; + } + } + + return c ? -EIO : 0; +} +EXPORT_SYMBOL_GPL(usb_serial_generic_resume); + void usb_serial_generic_close(struct usb_serial_port *port) { dbg("%s - port %d", __func__, port->number); @@ -254,81 +272,12 @@ static int usb_serial_multi_urb_write(struct tty_struct *tty, return bwrite; } -/** - * usb_serial_generic_write_start - kick off an URB write - * @port: Pointer to the &struct usb_serial_port data - * - * Returns the number of bytes queued on success. This will be zero if there - * was nothing to send. Otherwise, it returns a negative errno value - */ -static int usb_serial_generic_write_start(struct usb_serial_port *port) -{ - struct usb_serial *serial = port->serial; - unsigned char *data; - int result; - int count; - unsigned long flags; - bool start_io; - - /* Atomically determine whether we can and need to start a USB - * operation. */ - spin_lock_irqsave(&port->lock, flags); - if (port->write_urb_busy) - start_io = false; - else { - start_io = (__kfifo_len(port->write_fifo) != 0); - port->write_urb_busy = start_io; - } - spin_unlock_irqrestore(&port->lock, flags); - - if (!start_io) - return 0; - - data = port->write_urb->transfer_buffer; - count = kfifo_get(port->write_fifo, data, port->bulk_out_size); - usb_serial_debug_data(debug, &port->dev, __func__, count, data); - - /* set up our urb */ - usb_fill_bulk_urb(port->write_urb, serial->dev, - usb_sndbulkpipe(serial->dev, - port->bulk_out_endpointAddress), - port->write_urb->transfer_buffer, count, - ((serial->type->write_bulk_callback) ? - serial->type->write_bulk_callback : - usb_serial_generic_write_bulk_callback), - port); - - /* send the data out the bulk port */ - result = usb_submit_urb(port->write_urb, GFP_ATOMIC); - if (result) { - dev_err(&port->dev, - "%s - failed submitting write urb, error %d\n", - __func__, result); - /* don't have to grab the lock here, as we will - retry if != 0 */ - port->write_urb_busy = 0; - } else - result = count; - - return result; -} - -/** - * usb_serial_generic_write - generic write function for serial USB devices - * @tty: Pointer to &struct tty_struct for the device - * @port: Pointer to the &usb_serial_port structure for the device - * @buf: Pointer to the data to write - * @count: Number of bytes to write - * - * Returns the number of characters actually written, which may be anything - * from zero to @count. If an error occurs, it returns the negative errno - * value. - */ int usb_serial_generic_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct usb_serial *serial = port->serial; int result; + unsigned char *data; dbg("%s - port %d", __func__, port->number); @@ -338,20 +287,57 @@ int usb_serial_generic_write(struct tty_struct *tty, } /* only do something if we have a bulk out endpoint */ - if (!serial->num_bulk_out) - return 0; + if (serial->num_bulk_out) { + unsigned long flags; + + if (serial->type->max_in_flight_urbs) + return usb_serial_multi_urb_write(tty, port, + buf, count); + + spin_lock_irqsave(&port->lock, flags); + if (port->write_urb_busy) { + spin_unlock_irqrestore(&port->lock, flags); + dbg("%s - already writing", __func__); + return 0; + } + port->write_urb_busy = 1; + spin_unlock_irqrestore(&port->lock, flags); - if (serial->type->max_in_flight_urbs) - return usb_serial_multi_urb_write(tty, port, - buf, count); + count = (count > port->bulk_out_size) ? + port->bulk_out_size : count; - count = kfifo_put(port->write_fifo, buf, count); - result = usb_serial_generic_write_start(port); + memcpy(port->write_urb->transfer_buffer, buf, count); + data = port->write_urb->transfer_buffer; + usb_serial_debug_data(debug, &port->dev, __func__, count, data); - if (result >= 0) - result = count; + /* set up our urb */ + usb_fill_bulk_urb(port->write_urb, serial->dev, + usb_sndbulkpipe(serial->dev, + port->bulk_out_endpointAddress), + port->write_urb->transfer_buffer, count, + ((serial->type->write_bulk_callback) ? + serial->type->write_bulk_callback : + usb_serial_generic_write_bulk_callback), + port); - return result; + /* send the data out the bulk port */ + port->write_urb_busy = 1; + result = usb_submit_urb(port->write_urb, GFP_ATOMIC); + if (result) { + dev_err(&port->dev, + "%s - failed submitting write urb, error %d\n", + __func__, result); + /* don't have to grab the lock here, as we will + retry if != 0 */ + port->write_urb_busy = 0; + } else + result = count; + + return result; + } + + /* no bulk out, so return 0 bytes written */ + return 0; } EXPORT_SYMBOL_GPL(usb_serial_generic_write); @@ -369,8 +355,9 @@ int usb_serial_generic_write_room(struct tty_struct *tty) room = port->bulk_out_size * (serial->type->max_in_flight_urbs - port->urbs_in_flight); - } else if (serial->num_bulk_out) - room = port->write_fifo->size - __kfifo_len(port->write_fifo); + } else if (serial->num_bulk_out && !(port->write_urb_busy)) { + room = port->bulk_out_size; + } spin_unlock_irqrestore(&port->lock, flags); dbg("%s - returns %d", __func__, room); @@ -390,8 +377,11 @@ int usb_serial_generic_chars_in_buffer(struct tty_struct *tty) spin_lock_irqsave(&port->lock, flags); chars = port->tx_bytes_flight; spin_unlock_irqrestore(&port->lock, flags); - } else if (serial->num_bulk_out) - chars = kfifo_len(port->write_fifo); + } else if (serial->num_bulk_out) { + /* FIXME: Locking */ + if (port->write_urb_busy) + chars = port->write_urb->transfer_buffer_length; + } dbg("%s - returns %d", __func__, chars); return chars; @@ -495,23 +485,16 @@ void usb_serial_generic_write_bulk_callback(struct urb *urb) if (port->urbs_in_flight < 0) port->urbs_in_flight = 0; spin_unlock_irqrestore(&port->lock, flags); - - if (status) { - dbg("%s - nonzero multi-urb write bulk status " - "received: %d", __func__, status); - return; - } } else { + /* Handle the case for single urb mode */ port->write_urb_busy = 0; - - if (status) { - dbg("%s - nonzero multi-urb write bulk status " - "received: %d", __func__, status); - kfifo_reset(port->write_fifo); - } else - usb_serial_generic_write_start(port); } + if (status) { + dbg("%s - nonzero write bulk status received: %d", + __func__, status); + return; + } usb_serial_port_softint(port); } EXPORT_SYMBOL_GPL(usb_serial_generic_write_bulk_callback); @@ -576,33 +559,6 @@ int usb_serial_handle_break(struct usb_serial_port *port) } EXPORT_SYMBOL_GPL(usb_serial_handle_break); -int usb_serial_generic_resume(struct usb_serial *serial) -{ - struct usb_serial_port *port; - int i, c = 0, r; - - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - if (!port->port.count) - continue; - - if (port->read_urb) { - r = usb_submit_urb(port->read_urb, GFP_NOIO); - if (r < 0) - c++; - } - - if (port->write_urb) { - r = usb_serial_generic_write_start(port); - if (r < 0) - c++; - } - } - - return c ? -EIO : 0; -} -EXPORT_SYMBOL_GPL(usb_serial_generic_resume); - void usb_serial_generic_disconnect(struct usb_serial *serial) { int i; diff --git a/trunk/drivers/usb/serial/iuu_phoenix.c b/trunk/drivers/usb/serial/iuu_phoenix.c index e6e02b178d2b..6138c1cda35f 100644 --- a/trunk/drivers/usb/serial/iuu_phoenix.c +++ b/trunk/drivers/usb/serial/iuu_phoenix.c @@ -40,7 +40,7 @@ static int debug; /* * Version Information */ -#define DRIVER_VERSION "v0.11" +#define DRIVER_VERSION "v0.10" #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" static struct usb_device_id id_table[] = { @@ -64,7 +64,6 @@ static int cdmode = 1; static int iuu_cardin; static int iuu_cardout; static int xmas; -static int vcc_default = 5; static void read_rxcmd_callback(struct urb *urb); @@ -80,7 +79,6 @@ struct iuu_private { u8 *buf; /* used for initialize speed */ u8 *dbgbuf; /* debug buffer */ u8 len; - int vcc; /* vcc (either 3 or 5 V) */ }; @@ -116,7 +114,6 @@ static int iuu_startup(struct usb_serial *serial) kfree(priv); return -ENOMEM; } - priv->vcc = vcc_default; spin_lock_init(&priv->lock); init_waitqueue_head(&priv->delta_msr_wait); usb_set_serial_port_data(serial->port[0], priv); @@ -1012,7 +1009,11 @@ static void iuu_close(struct usb_serial_port *port) usb_kill_urb(port->write_urb); usb_kill_urb(port->read_urb); usb_kill_urb(port->interrupt_in_urb); + msleep(1000); + /* wait one second to free all buffers */ iuu_led(port, 0, 0, 0xF000, 0xFF); + msleep(1000); + usb_reset_device(port->serial->dev); } } @@ -1181,95 +1182,6 @@ static int iuu_open(struct tty_struct *tty, struct usb_serial_port *port) return result; } -/* how to change VCC */ -static int iuu_vcc_set(struct usb_serial_port *port, unsigned int vcc) -{ - int status; - u8 *buf; - - buf = kmalloc(5, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - dbg("%s - enter", __func__); - - buf[0] = IUU_SET_VCC; - buf[1] = vcc & 0xFF; - buf[2] = (vcc >> 8) & 0xFF; - buf[3] = (vcc >> 16) & 0xFF; - buf[4] = (vcc >> 24) & 0xFF; - - status = bulk_immediate(port, buf, 5); - kfree(buf); - - if (status != IUU_OPERATION_OK) - dbg("%s - vcc error status = %2x", __func__, status); - else - dbg("%s - vcc OK !", __func__); - - return status; -} - -/* - * Sysfs Attributes - */ - -static ssize_t show_vcc_mode(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct usb_serial_port *port = to_usb_serial_port(dev); - struct iuu_private *priv = usb_get_serial_port_data(port); - - return sprintf(buf, "%d\n", priv->vcc); -} - -static ssize_t store_vcc_mode(struct device *dev, - struct device_attribute *attr, const char *buf, size_t count) -{ - struct usb_serial_port *port = to_usb_serial_port(dev); - struct iuu_private *priv = usb_get_serial_port_data(port); - unsigned long v; - - if (strict_strtoul(buf, 10, &v)) { - dev_err(dev, "%s - vcc_mode: %s is not a unsigned long\n", - __func__, buf); - goto fail_store_vcc_mode; - } - - dbg("%s: setting vcc_mode = %ld", __func__, v); - - if ((v != 3) && (v != 5)) { - dev_err(dev, "%s - vcc_mode %ld is invalid\n", __func__, v); - } else { - iuu_vcc_set(port, v); - priv->vcc = v; - } -fail_store_vcc_mode: - return count; -} - -static DEVICE_ATTR(vcc_mode, S_IRUSR | S_IWUSR, show_vcc_mode, - store_vcc_mode); - -static int iuu_create_sysfs_attrs(struct usb_serial_port *port) -{ - dbg("%s", __func__); - - return device_create_file(&port->dev, &dev_attr_vcc_mode); -} - -static int iuu_remove_sysfs_attrs(struct usb_serial_port *port) -{ - dbg("%s", __func__); - - device_remove_file(&port->dev, &dev_attr_vcc_mode); - return 0; -} - -/* - * End Sysfs Attributes - */ - static struct usb_serial_driver iuu_device = { .driver = { .owner = THIS_MODULE, @@ -1277,8 +1189,6 @@ static struct usb_serial_driver iuu_device = { }, .id_table = id_table, .num_ports = 1, - .port_probe = iuu_create_sysfs_attrs, - .port_remove = iuu_remove_sysfs_attrs, .open = iuu_open, .close = iuu_close, .write = iuu_uart_write, @@ -1328,19 +1238,14 @@ module_param(debug, bool, S_IRUGO | S_IWUSR); MODULE_PARM_DESC(debug, "Debug enabled or not"); module_param(xmas, bool, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(xmas, "Xmas colors enabled or not"); +MODULE_PARM_DESC(xmas, "xmas color enabled or not"); module_param(boost, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(boost, "Card overclock boost (in percent 100-500)"); +MODULE_PARM_DESC(boost, "overclock boost percent 100 to 500"); module_param(clockmode, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(clockmode, "Card clock mode (1=3.579 MHz, 2=3.680 MHz, " - "3=6 Mhz)"); +MODULE_PARM_DESC(clockmode, "1=3Mhz579,2=3Mhz680,3=6Mhz"); module_param(cdmode, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(cdmode, "Card detect mode (0=none, 1=CD, 2=!CD, 3=DSR, " - "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING)"); - -module_param(vcc_default, int, S_IRUGO | S_IWUSR); -MODULE_PARM_DESC(vcc_default, "Set default VCC (either 3 for 3.3V or 5 " - "for 5V). Default to 5."); +MODULE_PARM_DESC(cdmode, "Card detect mode 0=none, 1=CD, 2=!CD, 3=DSR, " + "4=!DSR, 5=CTS, 6=!CTS, 7=RING, 8=!RING"); diff --git a/trunk/drivers/usb/serial/moto_modem.c b/trunk/drivers/usb/serial/moto_modem.c index 99bd00f5188a..b66b71ccd12b 100644 --- a/trunk/drivers/usb/serial/moto_modem.c +++ b/trunk/drivers/usb/serial/moto_modem.c @@ -8,7 +8,7 @@ * published by the Free Software Foundation. * * {sigh} - * Motorola should be using the CDC ACM USB spec, but instead + * Mororola should be using the CDC ACM USB spec, but instead * they try to just "do their own thing"... This driver should handle a * few phones in which a basic "dumb serial connection" is needed to be * able to get a connection through to them. diff --git a/trunk/drivers/usb/serial/option.c b/trunk/drivers/usb/serial/option.c index f66e39883218..fe47051dbef2 100644 --- a/trunk/drivers/usb/serial/option.c +++ b/trunk/drivers/usb/serial/option.c @@ -291,7 +291,6 @@ static int option_resume(struct usb_serial *serial); #define TELIT_VENDOR_ID 0x1bc7 #define TELIT_PRODUCT_UC864E 0x1003 -#define TELIT_PRODUCT_UC864G 0x1004 /* ZTE PRODUCTS */ #define ZTE_VENDOR_ID 0x19d2 @@ -300,7 +299,6 @@ static int option_resume(struct usb_serial *serial); #define ZTE_PRODUCT_MF626 0x0031 #define ZTE_PRODUCT_CDMA_TECH 0xfffe #define ZTE_PRODUCT_AC8710 0xfff1 -#define ZTE_PRODUCT_AC2726 0xfff5 #define BENQ_VENDOR_ID 0x04a5 #define BENQ_PRODUCT_H10 0x4068 @@ -504,7 +502,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE(QUALCOMM_VENDOR_ID, 0x6613)}, /* Onda H600/ZTE MF330 */ { USB_DEVICE(MAXON_VENDOR_ID, 0x6280) }, /* BP3-USB & BP3-EXT HSDPA */ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864E) }, - { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UC864G) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0003, 0xff, 0xff, 0xff) }, @@ -574,7 +571,6 @@ static struct usb_device_id option_ids[] = { { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0073, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_CDMA_TECH, 0xff, 0xff, 0xff) }, { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC8710, 0xff, 0xff, 0xff) }, - { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_AC2726, 0xff, 0xff, 0xff) }, { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) }, { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) }, { USB_DEVICE(QISDA_VENDOR_ID, QISDA_PRODUCT_H21_4512) }, @@ -596,7 +592,6 @@ static struct usb_driver option_driver = { #ifdef CONFIG_PM .suspend = usb_serial_suspend, .resume = usb_serial_resume, - .supports_autosuspend = 1, #endif .id_table = option_ids, .no_dynamic_id = 1, @@ -644,12 +639,6 @@ static int debug; #define IN_BUFLEN 4096 #define OUT_BUFLEN 4096 -struct option_intf_private { - spinlock_t susp_lock; - unsigned int suspended:1; - int in_flight; -}; - struct option_port_private { /* Input endpoints and buffer for this port */ struct urb *in_urbs[N_IN_URB]; @@ -658,8 +647,6 @@ struct option_port_private { struct urb *out_urbs[N_OUT_URB]; u8 *out_buffer[N_OUT_URB]; unsigned long out_busy; /* Bit vector of URBs in use */ - int opened; - struct usb_anchor delayed; /* Settings for the port */ int rts_state; /* Handshaking pins (outputs) */ @@ -706,17 +693,12 @@ module_exit(option_exit); static int option_probe(struct usb_serial *serial, const struct usb_device_id *id) { - struct option_intf_private *data; /* D-Link DWM 652 still exposes CD-Rom emulation interface in modem mode */ if (serial->dev->descriptor.idVendor == DLINK_VENDOR_ID && serial->dev->descriptor.idProduct == DLINK_PRODUCT_DWM_652 && serial->interface->cur_altsetting->desc.bInterfaceClass == 0x8) return -ENODEV; - data = serial->private = kzalloc(sizeof(struct option_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); return 0; } @@ -773,15 +755,12 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct option_port_private *portdata; - struct option_intf_private *intfdata; int i; int left, todo; struct urb *this_urb = NULL; /* spurious */ int err; - unsigned long flags; portdata = usb_get_serial_port_data(port); - intfdata = port->serial->private; dbg("%s: write (%d chars)", __func__, count); @@ -803,33 +782,17 @@ static int option_write(struct tty_struct *tty, struct usb_serial_port *port, dbg("%s: endpoint %d buf %d", __func__, usb_pipeendpoint(this_urb->pipe), i); - err = usb_autopm_get_interface_async(port->serial->interface); - if (err < 0) - break; - /* send the data */ memcpy(this_urb->transfer_buffer, buf, todo); this_urb->transfer_buffer_length = todo; - spin_lock_irqsave(&intfdata->susp_lock, flags); - if (intfdata->suspended) { - usb_anchor_urb(this_urb, &portdata->delayed); - spin_unlock_irqrestore(&intfdata->susp_lock, flags); - } else { - intfdata->in_flight++; - spin_unlock_irqrestore(&intfdata->susp_lock, flags); - err = usb_submit_urb(this_urb, GFP_ATOMIC); - if (err) { - dbg("usb_submit_urb %p (write bulk) failed " - "(%d)", this_urb, err); - clear_bit(i, &portdata->out_busy); - spin_lock_irqsave(&intfdata->susp_lock, flags); - intfdata->in_flight--; - spin_unlock_irqrestore(&intfdata->susp_lock, flags); - continue; - } + err = usb_submit_urb(this_urb, GFP_ATOMIC); + if (err) { + dbg("usb_submit_urb %p (write bulk) failed " + "(%d)", this_urb, err); + clear_bit(i, &portdata->out_busy); + continue; } - portdata->tx_start_time[i] = jiffies; buf += todo; left -= todo; @@ -873,10 +836,7 @@ static void option_indat_callback(struct urb *urb) if (err) printk(KERN_ERR "%s: resubmit read urb failed. " "(%d)", __func__, err); - else - usb_mark_last_busy(port->serial->dev); } - } return; } @@ -885,21 +845,15 @@ static void option_outdat_callback(struct urb *urb) { struct usb_serial_port *port; struct option_port_private *portdata; - struct option_intf_private *intfdata; int i; dbg("%s", __func__); port = urb->context; - intfdata = port->serial->private; usb_serial_port_softint(port); - usb_autopm_put_interface_async(port->serial->interface); - portdata = usb_get_serial_port_data(port); - spin_lock(&intfdata->susp_lock); - intfdata->in_flight--; - spin_unlock(&intfdata->susp_lock); + portdata = usb_get_serial_port_data(port); for (i = 0; i < N_OUT_URB; ++i) { if (portdata->out_urbs[i] == urb) { smp_mb__before_clear_bit(); @@ -1009,13 +963,10 @@ static int option_chars_in_buffer(struct tty_struct *tty) static int option_open(struct tty_struct *tty, struct usb_serial_port *port) { struct option_port_private *portdata; - struct option_intf_private *intfdata; - struct usb_serial *serial = port->serial; int i, err; struct urb *urb; portdata = usb_get_serial_port_data(port); - intfdata = serial->private; dbg("%s", __func__); @@ -1034,12 +985,6 @@ static int option_open(struct tty_struct *tty, struct usb_serial_port *port) option_send_setup(port); - serial->interface->needs_remote_wakeup = 1; - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 1; - spin_unlock_irq(&intfdata->susp_lock); - usb_autopm_put_interface(serial->interface); - return 0; } @@ -1064,23 +1009,16 @@ static void option_close(struct usb_serial_port *port) int i; struct usb_serial *serial = port->serial; struct option_port_private *portdata; - struct option_intf_private *intfdata = port->serial->private; dbg("%s", __func__); portdata = usb_get_serial_port_data(port); if (serial->dev) { /* Stop reading/writing urbs */ - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 0; - spin_unlock_irq(&intfdata->susp_lock); - for (i = 0; i < N_IN_URB; i++) usb_kill_urb(portdata->in_urbs[i]); for (i = 0; i < N_OUT_URB; i++) usb_kill_urb(portdata->out_urbs[i]); - usb_autopm_get_interface(serial->interface); - serial->interface->needs_remote_wakeup = 0; } } @@ -1185,7 +1123,6 @@ static int option_startup(struct usb_serial *serial) __func__, i); return 1; } - init_usb_anchor(&portdata->delayed); for (j = 0; j < N_IN_URB; j++) { buffer = (u8 *)__get_free_page(GFP_KERNEL); @@ -1288,52 +1225,18 @@ static void option_release(struct usb_serial *serial) #ifdef CONFIG_PM static int option_suspend(struct usb_serial *serial, pm_message_t message) { - struct option_intf_private *intfdata = serial->private; - int b; - dbg("%s entered", __func__); - - if (serial->dev->auto_pm) { - spin_lock_irq(&intfdata->susp_lock); - b = intfdata->in_flight; - spin_unlock_irq(&intfdata->susp_lock); - - if (b) - return -EBUSY; - } - - spin_lock_irq(&intfdata->susp_lock); - intfdata->suspended = 1; - spin_unlock_irq(&intfdata->susp_lock); stop_read_write_urbs(serial); return 0; } -static void play_delayed(struct usb_serial_port *port) -{ - struct option_intf_private *data; - struct option_port_private *portdata; - struct urb *urb; - int err; - - portdata = usb_get_serial_port_data(port); - data = port->serial->private; - while ((urb = usb_get_from_anchor(&portdata->delayed))) { - err = usb_submit_urb(urb, GFP_ATOMIC); - if (!err) - data->in_flight++; - } -} - static int option_resume(struct usb_serial *serial) { - int i, j; + int err, i, j; struct usb_serial_port *port; - struct option_intf_private *intfdata = serial->private; - struct option_port_private *portdata; struct urb *urb; - int err = 0; + struct option_port_private *portdata; dbg("%s entered", __func__); /* get the interrupt URBs resubmitted unconditionally */ @@ -1348,7 +1251,7 @@ static int option_resume(struct usb_serial *serial) if (err < 0) { err("%s: Error %d for interrupt URB of port%d", __func__, err, i); - goto err_out; + return err; } } @@ -1356,32 +1259,27 @@ static int option_resume(struct usb_serial *serial) /* walk all ports */ port = serial->port[i]; portdata = usb_get_serial_port_data(port); + mutex_lock(&port->mutex); /* skip closed ports */ - spin_lock_irq(&intfdata->susp_lock); - if (!portdata->opened) { - spin_unlock_irq(&intfdata->susp_lock); + if (!port->port.count) { + mutex_unlock(&port->mutex); continue; } for (j = 0; j < N_IN_URB; j++) { urb = portdata->in_urbs[j]; - err = usb_submit_urb(urb, GFP_ATOMIC); + err = usb_submit_urb(urb, GFP_NOIO); if (err < 0) { + mutex_unlock(&port->mutex); err("%s: Error %d for bulk URB %d", __func__, err, i); - spin_unlock_irq(&intfdata->susp_lock); - goto err_out; + return err; } } - play_delayed(port); - spin_unlock_irq(&intfdata->susp_lock); + mutex_unlock(&port->mutex); } - spin_lock_irq(&intfdata->susp_lock); - intfdata->suspended = 0; - spin_unlock_irq(&intfdata->susp_lock); -err_out: - return err; + return 0; } #endif diff --git a/trunk/drivers/usb/serial/pl2303.c b/trunk/drivers/usb/serial/pl2303.c index 1128e01525b1..a63ea99936f7 100644 --- a/trunk/drivers/usb/serial/pl2303.c +++ b/trunk/drivers/usb/serial/pl2303.c @@ -96,7 +96,6 @@ static struct usb_device_id id_table [] = { { USB_DEVICE(HP_VENDOR_ID, HP_LD220_PRODUCT_ID) }, { USB_DEVICE(CRESSI_VENDOR_ID, CRESSI_EDY_PRODUCT_ID) }, { USB_DEVICE(SONY_VENDOR_ID, SONY_QN3USB_PRODUCT_ID) }, - { USB_DEVICE(SANWA_VENDOR_ID, SANWA_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -528,12 +527,6 @@ static void pl2303_set_termios(struct tty_struct *tty, int baud; int i; u8 control; - const int baud_sup[] = { 75, 150, 300, 600, 1200, 1800, 2400, 3600, - 4800, 7200, 9600, 14400, 19200, 28800, 38400, - 57600, 115200, 230400, 460800, 614400, - 921600, 1228800, 2457600, 3000000, 6000000 }; - int baud_floor, baud_ceil; - int k; dbg("%s - port %d", __func__, port->number); @@ -579,39 +572,9 @@ static void pl2303_set_termios(struct tty_struct *tty, dbg("%s - data bits = %d", __func__, buf[6]); } - /* For reference buf[0]:buf[3] baud rate value */ - /* NOTE: Only the values defined in baud_sup are supported ! - * => if unsupported values are set, the PL2303 seems to use - * 9600 baud (at least my PL2303X always does) - */ baud = tty_get_baud_rate(tty); - dbg("%s - baud requested = %d", __func__, baud); + dbg("%s - baud = %d", __func__, baud); if (baud) { - /* Set baudrate to nearest supported value */ - for (k=0; k (baud % baud_floor)) - baud = baud_floor; - else - baud = baud_ceil; - } - break; - } - } - if (baud > 1228800) { - /* type_0, type_1 only support up to 1228800 baud */ - if (priv->type != HX) - baud = 1228800; - else if (baud > 6000000) - baud = 6000000; - } - dbg("%s - baud set = %d", __func__, baud); buf[0] = baud & 0xff; buf[1] = (baud >> 8) & 0xff; buf[2] = (baud >> 16) & 0xff; @@ -622,16 +585,8 @@ static void pl2303_set_termios(struct tty_struct *tty, /* For reference buf[4]=1 is 1.5 stop bits */ /* For reference buf[4]=2 is 2 stop bits */ if (cflag & CSTOPB) { - /* NOTE: Comply with "real" UARTs / RS232: - * use 1.5 instead of 2 stop bits with 5 data bits - */ - if ((cflag & CSIZE) == CS5) { - buf[4] = 1; - dbg("%s - stop bits = 1.5", __func__); - } else { - buf[4] = 2; - dbg("%s - stop bits = 2", __func__); - } + buf[4] = 2; + dbg("%s - stop bits = 2", __func__); } else { buf[4] = 0; dbg("%s - stop bits = 1", __func__); @@ -644,21 +599,11 @@ static void pl2303_set_termios(struct tty_struct *tty, /* For reference buf[5]=3 is mark parity */ /* For reference buf[5]=4 is space parity */ if (cflag & PARODD) { - if (cflag & CMSPAR) { - buf[5] = 3; - dbg("%s - parity = mark", __func__); - } else { - buf[5] = 1; - dbg("%s - parity = odd", __func__); - } + buf[5] = 1; + dbg("%s - parity = odd", __func__); } else { - if (cflag & CMSPAR) { - buf[5] = 4; - dbg("%s - parity = space", __func__); - } else { - buf[5] = 2; - dbg("%s - parity = even", __func__); - } + buf[5] = 2; + dbg("%s - parity = even", __func__); } } else { buf[5] = 0; @@ -702,7 +647,7 @@ static void pl2303_set_termios(struct tty_struct *tty, pl2303_vendor_write(0x0, 0x0, serial); } - /* Save resulting baud rate */ + /* FIXME: Need to read back resulting baud rate */ if (baud) tty_encode_baud_rate(tty, baud, baud); diff --git a/trunk/drivers/usb/serial/pl2303.h b/trunk/drivers/usb/serial/pl2303.h index d640dc951568..ee9505e1dd92 100644 --- a/trunk/drivers/usb/serial/pl2303.h +++ b/trunk/drivers/usb/serial/pl2303.h @@ -130,7 +130,3 @@ /* Sony, USB data cable for CMD-Jxx mobile phones */ #define SONY_VENDOR_ID 0x054c #define SONY_QN3USB_PRODUCT_ID 0x0437 - -/* Sanwa KB-USB2 multimeter cable (ID: 11ad:0001) */ -#define SANWA_VENDOR_ID 0x11ad -#define SANWA_PRODUCT_ID 0x0001 diff --git a/trunk/drivers/usb/serial/sierra.c b/trunk/drivers/usb/serial/sierra.c index 68fa0e43b781..55391bbe1230 100644 --- a/trunk/drivers/usb/serial/sierra.c +++ b/trunk/drivers/usb/serial/sierra.c @@ -51,12 +51,6 @@ struct sierra_iface_info { const u8 *ifaceinfo; /* pointer to the array holding the numbers */ }; -struct sierra_intf_private { - spinlock_t susp_lock; - unsigned int suspended:1; - int in_flight; -}; - static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) { int result; @@ -150,7 +144,6 @@ static int sierra_probe(struct usb_serial *serial, { int result = 0; struct usb_device *udev; - struct sierra_intf_private *data; u8 ifnum; udev = serial->dev; @@ -178,11 +171,6 @@ static int sierra_probe(struct usb_serial *serial, return -ENODEV; } - data = serial->private = kzalloc(sizeof(struct sierra_intf_private), GFP_KERNEL); - if (!data) - return -ENOMEM; - spin_lock_init(&data->susp_lock); - return result; } @@ -273,18 +261,13 @@ static struct usb_driver sierra_driver = { .name = "sierra", .probe = usb_serial_probe, .disconnect = usb_serial_disconnect, - .suspend = usb_serial_suspend, - .resume = usb_serial_resume, .id_table = id_table, .no_dynamic_id = 1, - .supports_autosuspend = 1, }; struct sierra_port_private { spinlock_t lock; /* lock the structure */ int outstanding_urbs; /* number of out urbs in flight */ - struct usb_anchor active; - struct usb_anchor delayed; /* Input endpoints and buffers for this port */ struct urb *in_urbs[N_IN_URB]; @@ -296,8 +279,6 @@ struct sierra_port_private { int dsr_state; int dcd_state; int ri_state; - - unsigned int opened:1; }; static int sierra_send_setup(struct usb_serial_port *port) @@ -409,25 +390,21 @@ static void sierra_outdat_callback(struct urb *urb) { struct usb_serial_port *port = urb->context; struct sierra_port_private *portdata = usb_get_serial_port_data(port); - struct sierra_intf_private *intfdata; int status = urb->status; + unsigned long flags; dev_dbg(&port->dev, "%s - port %d\n", __func__, port->number); - intfdata = port->serial->private; /* free up the transfer buffer, as usb_free_urb() does not do this */ kfree(urb->transfer_buffer); - usb_autopm_put_interface_async(port->serial->interface); + if (status) dev_dbg(&port->dev, "%s - nonzero write bulk status " "received: %d\n", __func__, status); - spin_lock(&portdata->lock); + spin_lock_irqsave(&portdata->lock, flags); --portdata->outstanding_urbs; - spin_unlock(&portdata->lock); - spin_lock(&intfdata->susp_lock); - --intfdata->in_flight; - spin_unlock(&intfdata->susp_lock); + spin_unlock_irqrestore(&portdata->lock, flags); usb_serial_port_softint(port); } @@ -437,7 +414,6 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, const unsigned char *buf, int count) { struct sierra_port_private *portdata = usb_get_serial_port_data(port); - struct sierra_intf_private *intfdata; struct usb_serial *serial = port->serial; unsigned long flags; unsigned char *buffer; @@ -450,9 +426,9 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, return 0; portdata = usb_get_serial_port_data(port); - intfdata = serial->private; dev_dbg(&port->dev, "%s: write (%zd bytes)\n", __func__, writesize); + spin_lock_irqsave(&portdata->lock, flags); dev_dbg(&port->dev, "%s - outstanding_urbs: %d\n", __func__, portdata->outstanding_urbs); @@ -466,14 +442,6 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, portdata->outstanding_urbs); spin_unlock_irqrestore(&portdata->lock, flags); - retval = usb_autopm_get_interface_async(serial->interface); - if (retval < 0) { - spin_lock_irqsave(&portdata->lock, flags); - portdata->outstanding_urbs--; - spin_unlock_irqrestore(&portdata->lock, flags); - goto error_simple; - } - buffer = kmalloc(writesize, GFP_ATOMIC); if (!buffer) { dev_err(&port->dev, "out of memory\n"); @@ -500,29 +468,14 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, /* Handle the need to send a zero length packet */ urb->transfer_flags |= URB_ZERO_PACKET; - spin_lock_irqsave(&intfdata->susp_lock, flags); - - if (intfdata->suspended) { - usb_anchor_urb(urb, &portdata->delayed); - spin_unlock_irqrestore(&intfdata->susp_lock, flags); - goto skip_power; - } else { - usb_anchor_urb(urb, &portdata->active); - } /* send it down the pipe */ retval = usb_submit_urb(urb, GFP_ATOMIC); if (retval) { - usb_unanchor_urb(urb); - spin_unlock_irqrestore(&intfdata->susp_lock, flags); dev_err(&port->dev, "%s - usb_submit_urb(write bulk) failed " "with status = %d\n", __func__, retval); goto error; - } else { - intfdata->in_flight++; - spin_unlock_irqrestore(&intfdata->susp_lock, flags); } -skip_power: /* we are done with this urb, so let the host driver * really free it when it is finished with it */ usb_free_urb(urb); @@ -538,8 +491,6 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port, dev_dbg(&port->dev, "%s - 2. outstanding_urbs: %d\n", __func__, portdata->outstanding_urbs); spin_unlock_irqrestore(&portdata->lock, flags); - usb_autopm_put_interface_async(serial->interface); -error_simple: return retval; } @@ -579,7 +530,6 @@ static void sierra_indat_callback(struct urb *urb) /* Resubmit urb so we continue receiving */ if (port->port.count && status != -ESHUTDOWN && status != -EPERM) { - usb_mark_last_busy(port->serial->dev); err = usb_submit_urb(urb, GFP_ATOMIC); if (err) dev_err(&port->dev, "resubmit read urb failed." @@ -641,7 +591,6 @@ static void sierra_instat_callback(struct urb *urb) /* Resubmit urb so we continue receiving IRQ data */ if (port->port.count && status != -ESHUTDOWN && status != -ENOENT) { - usb_mark_last_busy(serial->dev); urb->dev = serial->dev; err = usb_submit_urb(urb, GFP_ATOMIC); if (err) @@ -762,8 +711,6 @@ static void sierra_close(struct usb_serial_port *port) int i; struct usb_serial *serial = port->serial; struct sierra_port_private *portdata; - struct sierra_intf_private *intfdata = port->serial->private; - dev_dbg(&port->dev, "%s\n", __func__); portdata = usb_get_serial_port_data(port); @@ -776,10 +723,6 @@ static void sierra_close(struct usb_serial_port *port) if (!serial->disconnected) sierra_send_setup(port); mutex_unlock(&serial->disc_mutex); - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 0; - spin_unlock_irq(&intfdata->susp_lock); - /* Stop reading urbs */ sierra_stop_rx_urbs(port); @@ -788,8 +731,6 @@ static void sierra_close(struct usb_serial_port *port) sierra_release_urb(portdata->in_urbs[i]); portdata->in_urbs[i] = NULL; } - usb_autopm_get_interface(serial->interface); - serial->interface->needs_remote_wakeup = 0; } } @@ -797,7 +738,6 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) { struct sierra_port_private *portdata; struct usb_serial *serial = port->serial; - struct sierra_intf_private *intfdata = serial->private; int i; int err; int endpoint; @@ -831,12 +771,6 @@ static int sierra_open(struct tty_struct *tty, struct usb_serial_port *port) } sierra_send_setup(port); - serial->interface->needs_remote_wakeup = 1; - spin_lock_irq(&intfdata->susp_lock); - portdata->opened = 1; - spin_unlock_irq(&intfdata->susp_lock); - usb_autopm_put_interface(serial->interface); - return 0; } @@ -884,8 +818,6 @@ static int sierra_startup(struct usb_serial *serial) return -ENOMEM; } spin_lock_init(&portdata->lock); - init_usb_anchor(&portdata->active); - init_usb_anchor(&portdata->delayed); /* Set the port private data pointer */ usb_set_serial_port_data(port, portdata); } @@ -912,83 +844,6 @@ static void sierra_release(struct usb_serial *serial) } } -static void stop_read_write_urbs(struct usb_serial *serial) -{ - int i, j; - struct usb_serial_port *port; - struct sierra_port_private *portdata; - - /* Stop reading/writing urbs */ - for (i = 0; i < serial->num_ports; ++i) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); - for (j = 0; j < N_IN_URB; j++) - usb_kill_urb(portdata->in_urbs[j]); - usb_kill_anchored_urbs(&portdata->active); - } -} - -static int sierra_suspend(struct usb_serial *serial, pm_message_t message) -{ - struct sierra_intf_private *intfdata; - int b; - - if (serial->dev->auto_pm) { - intfdata = serial->private; - spin_lock_irq(&intfdata->susp_lock); - b = intfdata->in_flight; - - if (b) { - spin_unlock_irq(&intfdata->susp_lock); - return -EBUSY; - } else { - intfdata->suspended = 1; - spin_unlock_irq(&intfdata->susp_lock); - } - } - stop_read_write_urbs(serial); - - return 0; -} - -static int sierra_resume(struct usb_serial *serial) -{ - struct usb_serial_port *port; - struct sierra_intf_private *intfdata = serial->private; - struct sierra_port_private *portdata; - struct urb *urb; - int ec = 0; - int i, err; - - spin_lock_irq(&intfdata->susp_lock); - for (i = 0; i < serial->num_ports; i++) { - port = serial->port[i]; - portdata = usb_get_serial_port_data(port); - - while ((urb = usb_get_from_anchor(&portdata->delayed))) { - usb_anchor_urb(urb, &portdata->active); - intfdata->in_flight++; - err = usb_submit_urb(urb, GFP_ATOMIC); - if (err < 0) { - intfdata->in_flight--; - usb_unanchor_urb(urb); - usb_scuttle_anchored_urbs(&portdata->delayed); - break; - } - } - - if (portdata->opened) { - err = sierra_submit_rx_urbs(port, GFP_ATOMIC); - if (err) - ec++; - } - } - intfdata->suspended = 0; - spin_unlock_irq(&intfdata->susp_lock); - - return ec ? -EIO : 0; -} - static struct usb_serial_driver sierra_device = { .driver = { .owner = THIS_MODULE, @@ -1009,8 +864,6 @@ static struct usb_serial_driver sierra_device = { .tiocmset = sierra_tiocmset, .attach = sierra_startup, .release = sierra_release, - .suspend = sierra_suspend, - .resume = sierra_resume, .read_int_callback = sierra_instat_callback, }; diff --git a/trunk/drivers/usb/serial/usb-serial.c b/trunk/drivers/usb/serial/usb-serial.c index ff75a3589e7e..9d7ca4868d37 100644 --- a/trunk/drivers/usb/serial/usb-serial.c +++ b/trunk/drivers/usb/serial/usb-serial.c @@ -35,7 +35,6 @@ #include #include #include -#include #include "pl2303.h" /* @@ -293,6 +292,8 @@ static int serial_open(struct tty_struct *tty, struct file *filp) static void serial_down(struct usb_serial_port *port) { struct usb_serial_driver *drv = port->serial->type; + struct usb_serial *serial; + struct module *owner; /* * The console is magical. Do not hang up the console hardware @@ -308,8 +309,12 @@ static void serial_down(struct usb_serial_port *port) return; mutex_lock(&port->mutex); + serial = port->serial; + owner = serial->type->driver.owner; + if (drv->close) drv->close(port); + mutex_unlock(&port->mutex); } @@ -626,8 +631,6 @@ static void port_release(struct device *dev) usb_free_urb(port->write_urb); usb_free_urb(port->interrupt_in_urb); usb_free_urb(port->interrupt_out_urb); - if (!IS_ERR(port->write_fifo) && port->write_fifo) - kfifo_free(port->write_fifo); kfree(port->bulk_in_buffer); kfree(port->bulk_out_buffer); kfree(port->interrupt_in_buffer); @@ -967,10 +970,6 @@ int usb_serial_probe(struct usb_interface *interface, dev_err(&interface->dev, "No free urbs available\n"); goto probe_error; } - port->write_fifo = kfifo_alloc(PAGE_SIZE, GFP_KERNEL, - &port->lock); - if (IS_ERR(port->write_fifo)) - goto probe_error; buffer_size = le16_to_cpu(endpoint->wMaxPacketSize); port->bulk_out_size = buffer_size; port->bulk_out_endpointAddress = endpoint->bEndpointAddress; @@ -1164,19 +1163,15 @@ int usb_serial_suspend(struct usb_interface *intf, pm_message_t message) serial->suspending = 1; - if (serial->type->suspend) { - r = serial->type->suspend(serial, message); - if (r < 0) - goto err_out; - } - for (i = 0; i < serial->num_ports; ++i) { port = serial->port[i]; if (port) kill_traffic(port); } -err_out: + if (serial->type->suspend) + r = serial->type->suspend(serial, message); + return r; } EXPORT_SYMBOL(usb_serial_suspend); diff --git a/trunk/drivers/usb/storage/datafab.c b/trunk/drivers/usb/storage/datafab.c index ded836b02d7b..2b6e565262c2 100644 --- a/trunk/drivers/usb/storage/datafab.c +++ b/trunk/drivers/usb/storage/datafab.c @@ -334,7 +334,7 @@ static int datafab_determine_lun(struct us_data *us, unsigned char *buf; int count = 0, rc; - if (!info) + if (!us || !info) return USB_STOR_TRANSPORT_ERROR; memcpy(command, scommand, 8); @@ -399,7 +399,7 @@ static int datafab_id_device(struct us_data *us, unsigned char *reply; int rc; - if (!info) + if (!us || !info) return USB_STOR_TRANSPORT_ERROR; if (info->lun == -1) { diff --git a/trunk/drivers/usb/storage/initializers.c b/trunk/drivers/usb/storage/initializers.c index 105d900150c1..ec17c96371af 100644 --- a/trunk/drivers/usb/storage/initializers.c +++ b/trunk/drivers/usb/storage/initializers.c @@ -102,5 +102,5 @@ int usb_stor_huawei_e220_init(struct us_data *us) USB_TYPE_STANDARD | USB_RECIP_DEVICE, 0x01, 0x0, NULL, 0x0, 1000); US_DEBUGP("Huawei mode set result is %d\n", result); - return 0; + return (result ? 0 : -ENODEV); } diff --git a/trunk/drivers/usb/storage/jumpshot.c b/trunk/drivers/usb/storage/jumpshot.c index 6168596c5ac6..1c69420e3acf 100644 --- a/trunk/drivers/usb/storage/jumpshot.c +++ b/trunk/drivers/usb/storage/jumpshot.c @@ -335,7 +335,7 @@ static int jumpshot_id_device(struct us_data *us, unsigned char *reply; int rc; - if (!info) + if (!us || !info) return USB_STOR_TRANSPORT_ERROR; command[0] = 0xE0; diff --git a/trunk/drivers/usb/storage/onetouch.c b/trunk/drivers/usb/storage/onetouch.c index 80e65f29921c..380233bd6a39 100644 --- a/trunk/drivers/usb/storage/onetouch.c +++ b/trunk/drivers/usb/storage/onetouch.c @@ -163,7 +163,7 @@ static void usb_onetouch_pm_hook(struct us_data *us, int action) usb_kill_urb(onetouch->irq); break; case US_RESUME: - if (usb_submit_urb(onetouch->irq, GFP_NOIO) != 0) + if (usb_submit_urb(onetouch->irq, GFP_KERNEL) != 0) dev_err(&onetouch->irq->dev->dev, "usb_submit_urb failed\n"); break; diff --git a/trunk/drivers/usb/storage/unusual_devs.h b/trunk/drivers/usb/storage/unusual_devs.h index 079ae0f7bec1..7477d411959f 100644 --- a/trunk/drivers/usb/storage/unusual_devs.h +++ b/trunk/drivers/usb/storage/unusual_devs.h @@ -66,6 +66,13 @@ UNUSUAL_DEV( 0x03eb, 0x2002, 0x0100, 0x0100, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_IGNORE_RESIDUE), +/* modified by Tobias Lorenz */ +UNUSUAL_DEV( 0x03ee, 0x6901, 0x0000, 0x0200, + "Mitsumi", + "USB FDD", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + /* Reported by Rodolfo Quesada */ UNUSUAL_DEV( 0x03ee, 0x6906, 0x0003, 0x0003, "VIA Technologies Inc.", @@ -226,6 +233,13 @@ UNUSUAL_DEV( 0x0421, 0x0495, 0x0370, 0x0370, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_MAX_SECTORS_64 ), +/* Reported by Olaf Hering from novell bug #105878 */ +UNUSUAL_DEV( 0x0424, 0x0fdc, 0x0210, 0x0210, + "SMSC", + "FDC GOLD-2.30", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN ), + #ifdef NO_SDDR09 UNUSUAL_DEV( 0x0436, 0x0005, 0x0100, 0x0100, "Microtech", @@ -650,13 +664,19 @@ UNUSUAL_DEV( 0x055d, 0x2020, 0x0000, 0x0210, US_SC_DEVICE, US_PR_DEVICE, NULL, US_FL_SINGLE_LUN ), -/* We keep this entry to force the transport; firmware 3.00 and later is ok. */ + UNUSUAL_DEV( 0x057b, 0x0000, 0x0000, 0x0299, "Y-E Data", "Flashbuster-U", US_SC_DEVICE, US_PR_CB, NULL, US_FL_SINGLE_LUN), +UNUSUAL_DEV( 0x057b, 0x0000, 0x0300, 0x9999, + "Y-E Data", + "Flashbuster-U", + US_SC_DEVICE, US_PR_DEVICE, NULL, + US_FL_SINGLE_LUN), + /* Reported by Johann Cardon * This entry is needed only because the device reports * bInterfaceClass = 0xff (vendor-specific) diff --git a/trunk/drivers/usb/usb-skeleton.c b/trunk/drivers/usb/usb-skeleton.c index b62f2bc064f6..60ba631e99c2 100644 --- a/trunk/drivers/usb/usb-skeleton.c +++ b/trunk/drivers/usb/usb-skeleton.c @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include @@ -28,7 +28,7 @@ #define USB_SKEL_PRODUCT_ID 0xfff0 /* table of devices that work with this driver */ -static struct usb_device_id skel_table[] = { +static struct usb_device_id skel_table [] = { { USB_DEVICE(USB_SKEL_VENDOR_ID, USB_SKEL_PRODUCT_ID) }, { } /* Terminating entry */ }; @@ -52,21 +52,15 @@ struct usb_skel { struct usb_interface *interface; /* the interface for this device */ struct semaphore limit_sem; /* limiting the number of writes in progress */ struct usb_anchor submitted; /* in case we need to retract our submissions */ - struct urb *bulk_in_urb; /* the urb to read data with */ unsigned char *bulk_in_buffer; /* the buffer to receive data */ size_t bulk_in_size; /* the size of the receive buffer */ - size_t bulk_in_filled; /* number of bytes in the buffer */ - size_t bulk_in_copied; /* already copied to user space */ __u8 bulk_in_endpointAddr; /* the address of the bulk in endpoint */ __u8 bulk_out_endpointAddr; /* the address of the bulk out endpoint */ int errors; /* the last request tanked */ int open_count; /* count the number of openers */ - bool ongoing_read; /* a read is going on */ - bool processed_urb; /* indicates we haven't processed the urb */ spinlock_t err_lock; /* lock for errors */ struct kref kref; struct mutex io_mutex; /* synchronize I/O with disconnect */ - struct completion bulk_in_completion; /* to wait for an ongoing read */ }; #define to_skel_dev(d) container_of(d, struct usb_skel, kref) @@ -77,7 +71,6 @@ static void skel_delete(struct kref *kref) { struct usb_skel *dev = to_skel_dev(kref); - usb_free_urb(dev->bulk_in_urb); usb_put_dev(dev->udev); kfree(dev->bulk_in_buffer); kfree(dev); @@ -94,7 +87,7 @@ static int skel_open(struct inode *inode, struct file *file) interface = usb_find_interface(&skel_driver, subminor); if (!interface) { - err("%s - error, can't find device for minor %d", + err ("%s - error, can't find device for minor %d", __func__, subminor); retval = -ENODEV; goto exit; @@ -181,190 +174,38 @@ static int skel_flush(struct file *file, fl_owner_t id) return res; } -static void skel_read_bulk_callback(struct urb *urb) +static ssize_t skel_read(struct file *file, char *buffer, size_t count, loff_t *ppos) { struct usb_skel *dev; - - dev = urb->context; - - spin_lock(&dev->err_lock); - /* sync/async unlink faults aren't errors */ - if (urb->status) { - if (!(urb->status == -ENOENT || - urb->status == -ECONNRESET || - urb->status == -ESHUTDOWN)) - err("%s - nonzero write bulk status received: %d", - __func__, urb->status); - - dev->errors = urb->status; - } else { - dev->bulk_in_filled = urb->actual_length; - } - dev->ongoing_read = 0; - spin_unlock(&dev->err_lock); - - complete(&dev->bulk_in_completion); -} - -static int skel_do_read_io(struct usb_skel *dev, size_t count) -{ - int rv; - - /* prepare a read */ - usb_fill_bulk_urb(dev->bulk_in_urb, - dev->udev, - usb_rcvbulkpipe(dev->udev, - dev->bulk_in_endpointAddr), - dev->bulk_in_buffer, - min(dev->bulk_in_size, count), - skel_read_bulk_callback, - dev); - /* tell everybody to leave the URB alone */ - spin_lock_irq(&dev->err_lock); - dev->ongoing_read = 1; - spin_unlock_irq(&dev->err_lock); - - /* do it */ - rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL); - if (rv < 0) { - err("%s - failed submitting read urb, error %d", - __func__, rv); - dev->bulk_in_filled = 0; - rv = (rv == -ENOMEM) ? rv : -EIO; - spin_lock_irq(&dev->err_lock); - dev->ongoing_read = 0; - spin_unlock_irq(&dev->err_lock); - } - - return rv; -} - -static ssize_t skel_read(struct file *file, char *buffer, size_t count, - loff_t *ppos) -{ - struct usb_skel *dev; - int rv; - bool ongoing_io; + int retval; + int bytes_read; dev = (struct usb_skel *)file->private_data; - /* if we cannot read at all, return EOF */ - if (!dev->bulk_in_urb || !count) - return 0; - - /* no concurrent readers */ - rv = mutex_lock_interruptible(&dev->io_mutex); - if (rv < 0) - return rv; - + mutex_lock(&dev->io_mutex); if (!dev->interface) { /* disconnect() was called */ - rv = -ENODEV; - goto exit; - } - - /* if IO is under way, we must not touch things */ -retry: - spin_lock_irq(&dev->err_lock); - ongoing_io = dev->ongoing_read; - spin_unlock_irq(&dev->err_lock); - - if (ongoing_io) { - /* nonblocking IO shall not wait */ - if (file->f_flags & O_NONBLOCK) { - rv = -EAGAIN; - goto exit; - } - /* - * IO may take forever - * hence wait in an interruptible state - */ - rv = wait_for_completion_interruptible(&dev->bulk_in_completion); - if (rv < 0) - goto exit; - /* - * by waiting we also semiprocessed the urb - * we must finish now - */ - dev->bulk_in_copied = 0; - dev->processed_urb = 1; - } - - if (!dev->processed_urb) { - /* - * the URB hasn't been processed - * do it now - */ - wait_for_completion(&dev->bulk_in_completion); - dev->bulk_in_copied = 0; - dev->processed_urb = 1; - } - - /* errors must be reported */ - rv = dev->errors; - if (rv < 0) { - /* any error is reported once */ - dev->errors = 0; - /* to preserve notifications about reset */ - rv = (rv == -EPIPE) ? rv : -EIO; - /* no data to deliver */ - dev->bulk_in_filled = 0; - /* report it */ + retval = -ENODEV; goto exit; } - /* - * if the buffer is filled we may satisfy the read - * else we need to start IO - */ - - if (dev->bulk_in_filled) { - /* we had read data */ - size_t available = dev->bulk_in_filled - dev->bulk_in_copied; - size_t chunk = min(available, count); - - if (!available) { - /* - * all data has been used - * actual IO needs to be done - */ - rv = skel_do_read_io(dev, count); - if (rv < 0) - goto exit; - else - goto retry; - } - /* - * data is available - * chunk tells us how much shall be copied - */ - - if (copy_to_user(buffer, - dev->bulk_in_buffer + dev->bulk_in_copied, - chunk)) - rv = -EFAULT; + /* do a blocking bulk read to get data from the device */ + retval = usb_bulk_msg(dev->udev, + usb_rcvbulkpipe(dev->udev, dev->bulk_in_endpointAddr), + dev->bulk_in_buffer, + min(dev->bulk_in_size, count), + &bytes_read, 10000); + + /* if the read was successful, copy the data to userspace */ + if (!retval) { + if (copy_to_user(buffer, dev->bulk_in_buffer, bytes_read)) + retval = -EFAULT; else - rv = chunk; - - dev->bulk_in_copied += chunk; - - /* - * if we are asked for more than we have, - * we start IO but don't wait - */ - if (available < count) - skel_do_read_io(dev, count - chunk); - } else { - /* no data in the buffer */ - rv = skel_do_read_io(dev, count); - if (rv < 0) - goto exit; - else if (!file->f_flags & O_NONBLOCK) - goto retry; - rv = -EAGAIN; + retval = bytes_read; } + exit: mutex_unlock(&dev->io_mutex); - return rv; + return retval; } static void skel_write_bulk_callback(struct urb *urb) @@ -375,7 +216,7 @@ static void skel_write_bulk_callback(struct urb *urb) /* sync/async unlink faults aren't errors */ if (urb->status) { - if (!(urb->status == -ENOENT || + if(!(urb->status == -ENOENT || urb->status == -ECONNRESET || urb->status == -ESHUTDOWN)) err("%s - nonzero write bulk status received: %d", @@ -392,8 +233,7 @@ static void skel_write_bulk_callback(struct urb *urb) up(&dev->limit_sem); } -static ssize_t skel_write(struct file *file, const char *user_buffer, - size_t count, loff_t *ppos) +static ssize_t skel_write(struct file *file, const char *user_buffer, size_t count, loff_t *ppos) { struct usb_skel *dev; int retval = 0; @@ -407,25 +247,14 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, if (count == 0) goto exit; - /* - * limit the number of URBs in flight to stop a user from using up all - * RAM - */ - if (!file->f_flags & O_NONBLOCK) { - if (down_interruptible(&dev->limit_sem)) { - retval = -ERESTARTSYS; - goto exit; - } - } else { - if (down_trylock(&dev->limit_sem)) { - retval = -EAGAIN; - goto exit; - } + /* limit the number of URBs in flight to stop a user from using up all RAM */ + if (down_interruptible(&dev->limit_sem)) { + retval = -ERESTARTSYS; + goto exit; } spin_lock_irq(&dev->err_lock); - retval = dev->errors; - if (retval < 0) { + if ((retval = dev->errors) < 0) { /* any error is reported once */ dev->errors = 0; /* to preserve notifications about reset */ @@ -442,8 +271,7 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, goto error; } - buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, - &urb->transfer_dma); + buf = usb_buffer_alloc(dev->udev, writesize, GFP_KERNEL, &urb->transfer_dma); if (!buf) { retval = -ENOMEM; goto error; @@ -473,15 +301,11 @@ static ssize_t skel_write(struct file *file, const char *user_buffer, retval = usb_submit_urb(urb, GFP_KERNEL); mutex_unlock(&dev->io_mutex); if (retval) { - err("%s - failed submitting write urb, error %d", __func__, - retval); + err("%s - failed submitting write urb, error %d", __func__, retval); goto error_unanchor; } - /* - * release our reference to this urb, the USB core will eventually free - * it entirely - */ + /* release our reference to this urb, the USB core will eventually free it entirely */ usb_free_urb(urb); @@ -519,8 +343,7 @@ static struct usb_class_driver skel_class = { .minor_base = USB_SKEL_MINOR_BASE, }; -static int skel_probe(struct usb_interface *interface, - const struct usb_device_id *id) +static int skel_probe(struct usb_interface *interface, const struct usb_device_id *id) { struct usb_skel *dev; struct usb_host_interface *iface_desc; @@ -540,7 +363,6 @@ static int skel_probe(struct usb_interface *interface, mutex_init(&dev->io_mutex); spin_lock_init(&dev->err_lock); init_usb_anchor(&dev->submitted); - init_completion(&dev->bulk_in_completion); dev->udev = usb_get_dev(interface_to_usbdev(interface)); dev->interface = interface; @@ -562,11 +384,6 @@ static int skel_probe(struct usb_interface *interface, err("Could not allocate bulk_in_buffer"); goto error; } - dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL); - if (!dev->bulk_in_urb) { - err("Could not allocate bulk_in_urb"); - goto error; - } } if (!dev->bulk_out_endpointAddr && @@ -636,7 +453,6 @@ static void skel_draw_down(struct usb_skel *dev) time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000); if (!time) usb_kill_anchored_urbs(&dev->submitted); - usb_kill_urb(dev->bulk_in_urb); } static int skel_suspend(struct usb_interface *intf, pm_message_t message) @@ -649,7 +465,7 @@ static int skel_suspend(struct usb_interface *intf, pm_message_t message) return 0; } -static int skel_resume(struct usb_interface *intf) +static int skel_resume (struct usb_interface *intf) { return 0; } diff --git a/trunk/drivers/video/Kconfig b/trunk/drivers/video/Kconfig index 9bbb2855ea91..11af4cb8924e 100644 --- a/trunk/drivers/video/Kconfig +++ b/trunk/drivers/video/Kconfig @@ -1275,6 +1275,26 @@ config FB_MATROX_MAVEN painting procedures (the secondary head does not use acceleration engine). +config FB_MATROX_MULTIHEAD + bool "Multihead support" + depends on FB_MATROX + ---help--- + Say Y here if you have more than one (supported) Matrox device in + your computer and you want to use all of them for different monitors + ("multihead"). If you have only one device, you should say N because + the driver compiled with Y is larger and a bit slower, especially on + ia32 (ix86). + + If you said M to "Matrox unified accelerated driver" and N here, you + will still be able to use several Matrox devices simultaneously: + insert several instances of the module matroxfb into the kernel + with insmod, supplying the parameter "dev=N" where N is 0, 1, etc. + for the different Matrox devices. This method is slightly faster but + uses 40 KB of kernel memory per Matrox card. + + There is no need for enabling 'Matrox multihead support' if you have + only one Matrox card in the box. + config FB_RADEON tristate "ATI Radeon display support" depends on FB && PCI @@ -2021,17 +2041,6 @@ config FB_SH7760 and 8, 15 or 16 bpp color; 90 degrees clockwise display rotation for panels <= 320 pixel horizontal resolution. -config FB_DA8XX - tristate "DA8xx/OMAP-L1xx Framebuffer support" - depends on FB && ARCH_DAVINCI_DA8XX - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - This is the frame buffer device driver for the TI LCD controller - found on DA8xx/OMAP-L1xx SoCs. - If unsure, say N. - config FB_VIRTUAL tristate "Virtual Frame Buffer support (ONLY FOR TESTING!)" depends on FB @@ -2108,17 +2117,6 @@ config FB_MB862XX_LIME ---help--- Framebuffer support for Fujitsu Lime GDC on host CPU bus. -config FB_EP93XX - tristate "EP93XX frame buffer support" - depends on FB && ARCH_EP93XX - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - ---help--- - Framebuffer driver for the Cirrus Logic EP93XX series of processors. - This driver is also available as a module. The module will be called - ep93xx-fb. - config FB_PRE_INIT_FB bool "Don't reinitialize, use bootloader's GDC/Display configuration" depends on FB_MB862XX_LIME @@ -2126,14 +2124,6 @@ config FB_PRE_INIT_FB Select this option if display contents should be inherited as set by the bootloader. -config FB_MSM - tristate - depends on FB && ARCH_MSM - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - default y - config FB_MX3 tristate "MX3 Framebuffer support" depends on FB && MX3_IPU diff --git a/trunk/drivers/video/Makefile b/trunk/drivers/video/Makefile index 80232e124889..01a819f47371 100644 --- a/trunk/drivers/video/Makefile +++ b/trunk/drivers/video/Makefile @@ -85,7 +85,6 @@ obj-$(CONFIG_FB_Q40) += q40fb.o obj-$(CONFIG_FB_TGA) += tgafb.o obj-$(CONFIG_FB_HP300) += hpfb.o obj-$(CONFIG_FB_G364) += g364fb.o -obj-$(CONFIG_FB_EP93XX) += ep93xx-fb.o obj-$(CONFIG_FB_SA1100) += sa1100fb.o obj-$(CONFIG_FB_HIT) += hitfb.o obj-$(CONFIG_FB_EPSON1355) += epson1355fb.o @@ -127,7 +126,6 @@ obj-$(CONFIG_FB_OMAP) += omap/ obj-$(CONFIG_XEN_FBDEV_FRONTEND) += xen-fbfront.o obj-$(CONFIG_FB_CARMINE) += carminefb.o obj-$(CONFIG_FB_MB862XX) += mb862xx/ -obj-$(CONFIG_FB_MSM) += msm/ # Platform or fallback drivers go here obj-$(CONFIG_FB_UVESA) += uvesafb.o @@ -138,7 +136,6 @@ obj-$(CONFIG_FB_OF) += offb.o obj-$(CONFIG_FB_BF54X_LQ043) += bf54x-lq043fb.o obj-$(CONFIG_FB_BFIN_T350MCQB) += bfin-t350mcqb-fb.o obj-$(CONFIG_FB_MX3) += mx3fb.o -obj-$(CONFIG_FB_DA8XX) += da8xx-fb.o # the test framebuffer is last obj-$(CONFIG_FB_VIRTUAL) += vfb.o diff --git a/trunk/drivers/video/aty/atyfb_base.c b/trunk/drivers/video/aty/atyfb_base.c index 913b4a47ae52..63d3739d43a8 100644 --- a/trunk/drivers/video/aty/atyfb_base.c +++ b/trunk/drivers/video/aty/atyfb_base.c @@ -132,7 +132,7 @@ #endif #define PRINTKI(fmt, args...) printk(KERN_INFO "atyfb: " fmt, ## args) -#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) +#define PRINTKE(fmt, args...) printk(KERN_ERR "atyfb: " fmt, ## args) #if defined(CONFIG_PM) || defined(CONFIG_PMAC_BACKLIGHT) || \ defined (CONFIG_FB_ATY_GENERIC_LCD) || defined(CONFIG_FB_ATY_BACKLIGHT) @@ -188,23 +188,24 @@ u32 aty_ld_lcd(int index, const struct atyfb_par *par) */ static void ATIReduceRatio(int *Numerator, int *Denominator) { - int Multiplier, Divider, Remainder; + int Multiplier, Divider, Remainder; - Multiplier = *Numerator; - Divider = *Denominator; + Multiplier = *Numerator; + Divider = *Denominator; - while ((Remainder = Multiplier % Divider)) { - Multiplier = Divider; - Divider = Remainder; - } + while ((Remainder = Multiplier % Divider)) + { + Multiplier = Divider; + Divider = Remainder; + } - *Numerator /= Divider; - *Denominator /= Divider; + *Numerator /= Divider; + *Denominator /= Divider; } #endif -/* - * The Hardware parameters for each card - */ + /* + * The Hardware parameters for each card + */ struct pci_mmap_map { unsigned long voff; @@ -222,19 +223,17 @@ static struct fb_fix_screeninfo atyfb_fix __devinitdata = { .ypanstep = 1, }; -/* - * Frame buffer device API - */ + /* + * Frame buffer device API + */ static int atyfb_open(struct fb_info *info, int user); static int atyfb_release(struct fb_info *info, int user); -static int atyfb_check_var(struct fb_var_screeninfo *var, - struct fb_info *info); +static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info); static int atyfb_set_par(struct fb_info *info); static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info); -static int atyfb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info); + u_int transp, struct fb_info *info); +static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info); static int atyfb_blank(int blank, struct fb_info *info); static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg); #ifdef __sparc__ @@ -242,9 +241,9 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma); #endif static int atyfb_sync(struct fb_info *info); -/* - * Internal routines - */ + /* + * Internal routines + */ static int aty_init(struct fb_info *info); @@ -255,11 +254,8 @@ static int store_video_par(char *videopar, unsigned char m64_num); static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc); static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc); -static int aty_var_to_crtc(const struct fb_info *info, - const struct fb_var_screeninfo *var, - struct crtc *crtc); -static int aty_crtc_to_var(const struct crtc *crtc, - struct fb_var_screeninfo *var); +static int aty_var_to_crtc(const struct fb_info *info, const struct fb_var_screeninfo *var, struct crtc *crtc); +static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var); static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info); #ifdef CONFIG_PPC static int read_aty_sense(const struct atyfb_par *par); @@ -268,9 +264,9 @@ static int read_aty_sense(const struct atyfb_par *par); static DEFINE_MUTEX(reboot_lock); static struct fb_info *reboot_info; -/* - * Interface used by the world - */ + /* + * Interface used by the world + */ static struct fb_var_screeninfo default_var = { /* 640x480, 60 Hz, Non-Interlaced (25.175 MHz dotclock) */ @@ -456,14 +452,14 @@ static int __devinit correct_chipset(struct atyfb_par *par) type = chip_id & CFG_CHIP_TYPE; rev = (chip_id & CFG_CHIP_REV) >> 24; - switch (par->pci_id) { + switch(par->pci_id) { #ifdef CONFIG_FB_ATY_GX case PCI_CHIP_MACH64GX: - if (type != 0x00d7) + if(type != 0x00d7) return -ENODEV; break; case PCI_CHIP_MACH64CX: - if (type != 0x0057) + if(type != 0x0057) return -ENODEV; break; #endif @@ -568,8 +564,7 @@ static char *aty_xl_ram[8] __devinitdata = { }; #endif /* CONFIG_FB_ATY_CT */ -static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, - struct atyfb_par *par) +static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, struct atyfb_par *par) { u32 pixclock = var->pixclock; #ifdef CONFIG_FB_ATY_GENERIC_LCD @@ -577,7 +572,7 @@ static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, par->pll.ct.xres = 0; if (par->lcd_table != 0) { lcd_on_off = aty_ld_lcd(LCD_GEN_CNTL, par); - if (lcd_on_off & LCD_ON) { + if(lcd_on_off & LCD_ON) { par->pll.ct.xres = var->xres; pixclock = par->lcd_pixclock; } @@ -589,7 +584,7 @@ static u32 atyfb_get_pixclock(struct fb_var_screeninfo *var, #if defined(CONFIG_PPC) /* - * Apple monitor sense + * Apple monitor sense */ static int __devinit read_aty_sense(const struct atyfb_par *par) @@ -630,16 +625,16 @@ static int __devinit read_aty_sense(const struct atyfb_par *par) /* ------------------------------------------------------------------------- */ /* - * CRTC programming + * CRTC programming */ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) { #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { - if (!M64_HAS(LT_LCD_REGS)) { - crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); - aty_st_le32(LCD_INDEX, crtc->lcd_index, par); + if(!M64_HAS(LT_LCD_REGS)) { + crtc->lcd_index = aty_ld_le32(LCD_INDEX, par); + aty_st_le32(LCD_INDEX, crtc->lcd_index, par); } crtc->lcd_config_panel = aty_ld_lcd(CNFG_PANEL, par); crtc->lcd_gen_cntl = aty_ld_lcd(LCD_GEN_CNTL, par); @@ -647,7 +642,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) /* switch to non shadow registers */ aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); + ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); /* save stretching */ crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par); @@ -668,7 +663,7 @@ static void aty_get_crtc(const struct atyfb_par *par, struct crtc *crtc) if (par->lcd_table != 0) { /* switch to shadow registers */ aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) | - SHADOW_EN | SHADOW_RW_EN, par); + SHADOW_EN | SHADOW_RW_EN, par); crtc->shadow_h_tot_disp = aty_ld_le32(CRTC_H_TOTAL_DISP, par); crtc->shadow_h_sync_strt_wid = aty_ld_le32(CRTC_H_SYNC_STRT_WID, par); @@ -685,20 +680,21 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { /* stop CRTC */ - aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & - ~(CRTC_EXT_DISP_EN | CRTC_EN), par); + aty_st_le32(CRTC_GEN_CNTL, crtc->gen_cntl & ~(CRTC_EXT_DISP_EN | CRTC_EN), par); /* update non-shadow registers first */ aty_st_lcd(CNFG_PANEL, crtc->lcd_config_panel, par); aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl & - ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); + ~(CRTC_RW_SELECT | SHADOW_EN | SHADOW_RW_EN), par); /* temporarily disable stretching */ - aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching & - ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par); - aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching & - ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | - VERT_STRETCH_USE0 | VERT_STRETCH_EN), par); + aty_st_lcd(HORZ_STRETCHING, + crtc->horz_stretching & + ~(HORZ_STRETCH_MODE | HORZ_STRETCH_EN), par); + aty_st_lcd(VERT_STRETCHING, + crtc->vert_stretching & + ~(VERT_STRETCH_RATIO1 | VERT_STRETCH_RATIO2 | + VERT_STRETCH_USE0 | VERT_STRETCH_EN), par); } #endif /* turn off CRT */ @@ -706,19 +702,17 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) DPRINTK("setting up CRTC\n"); DPRINTK("set primary CRT to %ix%i %c%c composite %c\n", - ((((crtc->h_tot_disp >> 16) & 0xff) + 1) << 3), - (((crtc->v_tot_disp >> 16) & 0x7ff) + 1), - (crtc->h_sync_strt_wid & 0x200000) ? 'N' : 'P', - (crtc->v_sync_strt_wid & 0x200000) ? 'N' : 'P', - (crtc->gen_cntl & CRTC_CSYNC_EN) ? 'P' : 'N'); - - DPRINTK("CRTC_H_TOTAL_DISP: %x\n", crtc->h_tot_disp); - DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n", crtc->h_sync_strt_wid); - DPRINTK("CRTC_V_TOTAL_DISP: %x\n", crtc->v_tot_disp); - DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n", crtc->v_sync_strt_wid); + ((((crtc->h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->v_tot_disp>>16) & 0x7ff) + 1), + (crtc->h_sync_strt_wid & 0x200000)?'N':'P', (crtc->v_sync_strt_wid & 0x200000)?'N':'P', + (crtc->gen_cntl & CRTC_CSYNC_EN)?'P':'N'); + + DPRINTK("CRTC_H_TOTAL_DISP: %x\n",crtc->h_tot_disp); + DPRINTK("CRTC_H_SYNC_STRT_WID: %x\n",crtc->h_sync_strt_wid); + DPRINTK("CRTC_V_TOTAL_DISP: %x\n",crtc->v_tot_disp); + DPRINTK("CRTC_V_SYNC_STRT_WID: %x\n",crtc->v_sync_strt_wid); DPRINTK("CRTC_OFF_PITCH: %x\n", crtc->off_pitch); DPRINTK("CRTC_VLINE_CRNT_VLINE: %x\n", crtc->vline_crnt_vline); - DPRINTK("CRTC_GEN_CNTL: %x\n", crtc->gen_cntl); + DPRINTK("CRTC_GEN_CNTL: %x\n",crtc->gen_cntl); aty_st_le32(CRTC_H_TOTAL_DISP, crtc->h_tot_disp, par); aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->h_sync_strt_wid, par); @@ -738,22 +732,16 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) if (par->lcd_table != 0) { /* switch to shadow registers */ aty_st_lcd(LCD_GEN_CNTL, (crtc->lcd_gen_cntl & ~CRTC_RW_SELECT) | - SHADOW_EN | SHADOW_RW_EN, par); + (SHADOW_EN | SHADOW_RW_EN), par); DPRINTK("set shadow CRT to %ix%i %c%c\n", - ((((crtc->shadow_h_tot_disp >> 16) & 0xff) + 1) << 3), - (((crtc->shadow_v_tot_disp >> 16) & 0x7ff) + 1), - (crtc->shadow_h_sync_strt_wid & 0x200000) ? 'N' : 'P', - (crtc->shadow_v_sync_strt_wid & 0x200000) ? 'N' : 'P'); - - DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", - crtc->shadow_h_tot_disp); - DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", - crtc->shadow_h_sync_strt_wid); - DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", - crtc->shadow_v_tot_disp); - DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", - crtc->shadow_v_sync_strt_wid); + ((((crtc->shadow_h_tot_disp>>16) & 0xff) + 1)<<3), (((crtc->shadow_v_tot_disp>>16) & 0x7ff) + 1), + (crtc->shadow_h_sync_strt_wid & 0x200000)?'N':'P', (crtc->shadow_v_sync_strt_wid & 0x200000)?'N':'P'); + + DPRINTK("SHADOW CRTC_H_TOTAL_DISP: %x\n", crtc->shadow_h_tot_disp); + DPRINTK("SHADOW CRTC_H_SYNC_STRT_WID: %x\n", crtc->shadow_h_sync_strt_wid); + DPRINTK("SHADOW CRTC_V_TOTAL_DISP: %x\n", crtc->shadow_v_tot_disp); + DPRINTK("SHADOW CRTC_V_SYNC_STRT_WID: %x\n", crtc->shadow_v_sync_strt_wid); aty_st_le32(CRTC_H_TOTAL_DISP, crtc->shadow_h_tot_disp, par); aty_st_le32(CRTC_H_SYNC_STRT_WID, crtc->shadow_h_sync_strt_wid, par); @@ -764,16 +752,16 @@ static void aty_set_crtc(const struct atyfb_par *par, const struct crtc *crtc) DPRINTK("LCD_GEN_CNTL: %x\n", crtc->lcd_gen_cntl); DPRINTK("HORZ_STRETCHING: %x\n", crtc->horz_stretching); DPRINTK("VERT_STRETCHING: %x\n", crtc->vert_stretching); - if (!M64_HAS(LT_LCD_REGS)) - DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch); + if(!M64_HAS(LT_LCD_REGS)) + DPRINTK("EXT_VERT_STRETCH: %x\n", crtc->ext_vert_stretch); aty_st_lcd(LCD_GEN_CNTL, crtc->lcd_gen_cntl, par); aty_st_lcd(HORZ_STRETCHING, crtc->horz_stretching, par); aty_st_lcd(VERT_STRETCHING, crtc->vert_stretching, par); - if (!M64_HAS(LT_LCD_REGS)) { - aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par); - aty_ld_le32(LCD_INDEX, par); - aty_st_le32(LCD_INDEX, crtc->lcd_index, par); + if(!M64_HAS(LT_LCD_REGS)) { + aty_st_lcd(EXT_VERT_STRETCH, crtc->ext_vert_stretch, par); + aty_ld_le32(LCD_INDEX, par); + aty_st_le32(LCD_INDEX, crtc->lcd_index, par); } } #endif /* CONFIG_FB_ATY_GENERIC_LCD */ @@ -791,8 +779,7 @@ static u32 calc_line_length(struct atyfb_par *par, u32 vxres, u32 bpp) } static int aty_var_to_crtc(const struct fb_info *info, - const struct fb_var_screeninfo *var, - struct crtc *crtc) + const struct fb_var_screeninfo *var, struct crtc *crtc) { struct atyfb_par *par = (struct atyfb_par *) info->par; u32 xres, yres, vxres, vyres, xoffset, yoffset, bpp; @@ -827,32 +814,34 @@ static int aty_var_to_crtc(const struct fb_info *info, if (bpp <= 8) { bpp = 8; pix_width = CRTC_PIX_WIDTH_8BPP; - dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | - BYTE_ORDER_LSB_TO_MSB; + dp_pix_width = + HOST_8BPP | SRC_8BPP | DST_8BPP | + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_8BPP; } else if (bpp <= 15) { bpp = 16; pix_width = CRTC_PIX_WIDTH_15BPP; dp_pix_width = HOST_15BPP | SRC_15BPP | DST_15BPP | - BYTE_ORDER_LSB_TO_MSB; + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_15BPP; } else if (bpp <= 16) { bpp = 16; pix_width = CRTC_PIX_WIDTH_16BPP; dp_pix_width = HOST_16BPP | SRC_16BPP | DST_16BPP | - BYTE_ORDER_LSB_TO_MSB; + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_16BPP; } else if (bpp <= 24 && M64_HAS(INTEGRATED)) { bpp = 24; pix_width = CRTC_PIX_WIDTH_24BPP; - dp_pix_width = HOST_8BPP | SRC_8BPP | DST_8BPP | - BYTE_ORDER_LSB_TO_MSB; + dp_pix_width = + HOST_8BPP | SRC_8BPP | DST_8BPP | + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_24BPP; } else if (bpp <= 32) { bpp = 32; pix_width = CRTC_PIX_WIDTH_32BPP; dp_pix_width = HOST_32BPP | SRC_32BPP | DST_32BPP | - BYTE_ORDER_LSB_TO_MSB; + BYTE_ORDER_LSB_TO_MSB; dp_chain_mask = DP_CHAIN_32BPP; } else FAIL("invalid bpp"); @@ -865,9 +854,9 @@ static int aty_var_to_crtc(const struct fb_info *info, h_sync_pol = sync & FB_SYNC_HOR_HIGH_ACT ? 0 : 1; v_sync_pol = sync & FB_SYNC_VERT_HIGH_ACT ? 0 : 1; - if ((xres > 1600) || (yres > 1200)) { + if((xres > 1600) || (yres > 1200)) { FAIL("MACH64 chips are designed for max 1600x1200\n" - "select anoter resolution."); + "select anoter resolution."); } h_sync_strt = h_disp + var->right_margin; h_sync_end = h_sync_strt + var->hsync_len; @@ -880,12 +869,11 @@ static int aty_var_to_crtc(const struct fb_info *info, #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { - if (!M64_HAS(LT_LCD_REGS)) { - u32 lcd_index = aty_ld_le32(LCD_INDEX, par); - crtc->lcd_index = lcd_index & - ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | - LCD_SRC_SEL | CRTC2_DISPLAY_DIS); - aty_st_le32(LCD_INDEX, lcd_index, par); + if(!M64_HAS(LT_LCD_REGS)) { + u32 lcd_index = aty_ld_le32(LCD_INDEX, par); + crtc->lcd_index = lcd_index & + ~(LCD_INDEX_MASK | LCD_DISPLAY_DIS | LCD_SRC_SEL | CRTC2_DISPLAY_DIS); + aty_st_le32(LCD_INDEX, lcd_index, par); } if (!M64_HAS(MOBIL_BUS)) @@ -900,14 +888,12 @@ static int aty_var_to_crtc(const struct fb_info *info, USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN); crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR | LOCK_8DOT; - if ((crtc->lcd_gen_cntl & LCD_ON) && - ((xres > par->lcd_width) || (yres > par->lcd_height))) { - /* - * We cannot display the mode on the LCD. If the CRT is - * enabled we can turn off the LCD. - * If the CRT is off, it isn't a good idea to switch it - * on; we don't know if one is connected. So it's better - * to fail then. + if((crtc->lcd_gen_cntl & LCD_ON) && + ((xres > par->lcd_width) || (yres > par->lcd_height))) { + /* We cannot display the mode on the LCD. If the CRT is enabled + we can turn off the LCD. + If the CRT is off, it isn't a good idea to switch it on; we don't + know if one is connected. So it's better to fail then. */ if (crtc->lcd_gen_cntl & CRT_ON) { if (!(var->activate & FB_ACTIVATE_TEST)) @@ -930,18 +916,17 @@ static int aty_var_to_crtc(const struct fb_info *info, vmode &= ~(FB_VMODE_DOUBLE | FB_VMODE_INTERLACED); - /* - * This is horror! When we simulate, say 640x480 on an 800x600 - * LCD monitor, the CRTC should be programmed 800x600 values for - * the non visible part, but 640x480 for the visible part. - * This code has been tested on a laptop with it's 1400x1050 LCD - * monitor and a conventional monitor both switched on. - * Tested modes: 1280x1024, 1152x864, 1024x768, 800x600, - * works with little glitches also with DOUBLESCAN modes + /* This is horror! When we simulate, say 640x480 on an 800x600 + LCD monitor, the CRTC should be programmed 800x600 values for + the non visible part, but 640x480 for the visible part. + This code has been tested on a laptop with it's 1400x1050 LCD + monitor and a conventional monitor both switched on. + Tested modes: 1280x1024, 1152x864, 1024x768, 800x600, + works with little glitches also with DOUBLESCAN modes */ if (yres < par->lcd_height) { VScan = par->lcd_height / yres; - if (VScan > 1) { + if(VScan > 1) { VScan = 2; vmode |= FB_VMODE_DOUBLE; } @@ -967,7 +952,7 @@ static int aty_var_to_crtc(const struct fb_info *info, FAIL_MAX("h_disp too large", h_disp, 0xff); FAIL_MAX("h_sync_strt too large", h_sync_strt, 0x1ff); /*FAIL_MAX("h_sync_wid too large", h_sync_wid, 0x1f);*/ - if (h_sync_wid > 0x1f) + if(h_sync_wid > 0x1f) h_sync_wid = 0x1f; FAIL_MAX("h_total too large", h_total, 0x1ff); @@ -993,7 +978,7 @@ static int aty_var_to_crtc(const struct fb_info *info, FAIL_MAX("v_disp too large", v_disp, 0x7ff); FAIL_MAX("v_sync_stsrt too large", v_sync_strt, 0x7ff); /*FAIL_MAX("v_sync_wid too large", v_sync_wid, 0x1f);*/ - if (v_sync_wid > 0x1f) + if(v_sync_wid > 0x1f) v_sync_wid = 0x1f; FAIL_MAX("v_total too large", v_total, 0x7ff); @@ -1010,13 +995,11 @@ static int aty_var_to_crtc(const struct fb_info *info, ((line_length / bpp) << 22); crtc->vline_crnt_vline = 0; - crtc->h_tot_disp = h_total | (h_disp << 16); - crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly << 8) | - ((h_sync_strt & 0x100) << 4) | (h_sync_wid << 16) | - (h_sync_pol << 21); - crtc->v_tot_disp = v_total | (v_disp << 16); - crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid << 16) | - (v_sync_pol << 21); + crtc->h_tot_disp = h_total | (h_disp<<16); + crtc->h_sync_strt_wid = (h_sync_strt & 0xff) | (h_sync_dly<<8) | + ((h_sync_strt & 0x100)<<4) | (h_sync_wid<<16) | (h_sync_pol<<21); + crtc->v_tot_disp = v_total | (v_disp<<16); + crtc->v_sync_strt_wid = v_sync_strt | (v_sync_wid<<16) | (v_sync_pol<<21); /* crtc->gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_PRESERVED_MASK; */ crtc->gen_cntl = CRTC_EXT_DISP_EN | CRTC_EN | pix_width | c_sync; @@ -1031,15 +1014,13 @@ static int aty_var_to_crtc(const struct fb_info *info, #ifdef CONFIG_FB_ATY_GENERIC_LCD if (par->lcd_table != 0) { vdisplay = yres; - if (vmode & FB_VMODE_DOUBLE) + if(vmode & FB_VMODE_DOUBLE) vdisplay <<= 1; crtc->gen_cntl &= ~(CRTC2_EN | CRTC2_PIX_WIDTH); crtc->lcd_gen_cntl &= ~(HORZ_DIVBY2_EN | DIS_HOR_CRT_DIVBY2 | - /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/ - USE_SHADOWED_VEND | - USE_SHADOWED_ROWCUR | - SHADOW_EN | SHADOW_RW_EN); - crtc->lcd_gen_cntl |= DONT_SHADOW_VPAR/* | LOCK_8DOT*/; + /*TVCLK_PM_EN | VCLK_DAC_PM_EN |*/ + USE_SHADOWED_VEND | USE_SHADOWED_ROWCUR | SHADOW_EN | SHADOW_RW_EN); + crtc->lcd_gen_cntl |= (DONT_SHADOW_VPAR/* | LOCK_8DOT*/); /* MOBILITY M1 tested, FIXME: LT */ crtc->horz_stretching = aty_ld_lcd(HORZ_STRETCHING, par); @@ -1047,32 +1028,28 @@ static int aty_var_to_crtc(const struct fb_info *info, crtc->ext_vert_stretch = aty_ld_lcd(EXT_VERT_STRETCH, par) & ~(AUTO_VERT_RATIO | VERT_STRETCH_MODE | VERT_STRETCH_RATIO3); - crtc->horz_stretching &= ~(HORZ_STRETCH_RATIO | - HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO | - HORZ_STRETCH_MODE | HORZ_STRETCH_EN); + crtc->horz_stretching &= + ~(HORZ_STRETCH_RATIO | HORZ_STRETCH_LOOP | AUTO_HORZ_RATIO | + HORZ_STRETCH_MODE | HORZ_STRETCH_EN); if (xres < par->lcd_width && crtc->lcd_gen_cntl & LCD_ON) { do { /* - * The horizontal blender misbehaves when - * HDisplay is less than a certain threshold - * (440 for a 1024-wide panel). It doesn't - * stretch such modes enough. Use pixel - * replication instead of blending to stretch - * modes that can be made to exactly fit the - * panel width. The undocumented "NoLCDBlend" - * option allows the pixel-replicated mode to - * be slightly wider or narrower than the - * panel width. It also causes a mode that is - * exactly half as wide as the panel to be - * pixel-replicated, rather than blended. - */ + * The horizontal blender misbehaves when HDisplay is less than a + * a certain threshold (440 for a 1024-wide panel). It doesn't + * stretch such modes enough. Use pixel replication instead of + * blending to stretch modes that can be made to exactly fit the + * panel width. The undocumented "NoLCDBlend" option allows the + * pixel-replicated mode to be slightly wider or narrower than the + * panel width. It also causes a mode that is exactly half as wide + * as the panel to be pixel-replicated, rather than blended. + */ int HDisplay = xres & ~7; int nStretch = par->lcd_width / HDisplay; int Remainder = par->lcd_width % HDisplay; if ((!Remainder && ((nStretch > 2))) || - (((HDisplay * 16) / par->lcd_width) < 7)) { - static const char StretchLoops[] = { 10, 12, 13, 15, 16 }; + (((HDisplay * 16) / par->lcd_width) < 7)) { + static const char StretchLoops[] = {10, 12, 13, 15, 16}; int horz_stretch_loop = -1, BestRemainder; int Numerator = HDisplay, Denominator = par->lcd_width; int Index = 5; @@ -1121,12 +1098,12 @@ static int aty_var_to_crtc(const struct fb_info *info, (((vdisplay * (VERT_STRETCH_RATIO0 + 1)) / par->lcd_height) & VERT_STRETCH_RATIO0)); if (!M64_HAS(LT_LCD_REGS) && - xres <= (M64_HAS(MOBIL_BUS) ? 1024 : 800)) + xres <= (M64_HAS(MOBIL_BUS)?1024:800)) crtc->ext_vert_stretch |= VERT_STRETCH_MODE; } else { /* - * Don't use vertical blending if the mode is too wide - * or not vertically stretched. + * Don't use vertical blending if the mode is too wide or not + * vertically stretched. */ crtc->vert_stretching = 0; } @@ -1148,11 +1125,11 @@ static int aty_var_to_crtc(const struct fb_info *info, return 0; } -static int aty_crtc_to_var(const struct crtc *crtc, - struct fb_var_screeninfo *var) +static int aty_crtc_to_var(const struct crtc *crtc, struct fb_var_screeninfo *var) { u32 xres, yres, bpp, left, right, upper, lower, hslen, vslen, sync; - u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, h_sync_pol; + u32 h_total, h_disp, h_sync_strt, h_sync_dly, h_sync_wid, + h_sync_pol; u32 v_total, v_disp, v_sync_strt, v_sync_wid, v_sync_pol, c_sync; u32 pix_width; u32 double_scan, interlace; @@ -1184,8 +1161,8 @@ static int aty_crtc_to_var(const struct crtc *crtc, lower = v_sync_strt - v_disp; vslen = v_sync_wid; sync = (h_sync_pol ? 0 : FB_SYNC_HOR_HIGH_ACT) | - (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | - (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); + (v_sync_pol ? 0 : FB_SYNC_VERT_HIGH_ACT) | + (c_sync ? FB_SYNC_COMP_HIGH_ACT : 0); switch (pix_width) { #if 0 @@ -1275,21 +1252,20 @@ static int aty_crtc_to_var(const struct crtc *crtc, var->vsync_len = vslen; var->sync = sync; var->vmode = FB_VMODE_NONINTERLACED; - /* - * In double scan mode, the vertical parameters are doubled, - * so we need to halve them to get the right values. - * In interlaced mode the values are already correct, - * so no correction is necessary. + /* In double scan mode, the vertical parameters are doubled, so we need to + half them to get the right values. + In interlaced mode the values are already correct, so no correction is + necessary. */ if (interlace) var->vmode = FB_VMODE_INTERLACED; if (double_scan) { var->vmode = FB_VMODE_DOUBLE; - var->yres >>= 1; - var->upper_margin >>= 1; - var->lower_margin >>= 1; - var->vsync_len >>= 1; + var->yres>>=1; + var->upper_margin>>=1; + var->lower_margin>>=1; + var->vsync_len>>=1; } return 0; @@ -1310,8 +1286,7 @@ static int atyfb_set_par(struct fb_info *info) if (par->asleep) return 0; - err = aty_var_to_crtc(info, var, &par->crtc); - if (err) + if ((err = aty_var_to_crtc(info, var, &par->crtc))) return err; pixclock = atyfb_get_pixclock(var, par); @@ -1320,9 +1295,7 @@ static int atyfb_set_par(struct fb_info *info) PRINTKE("Invalid pixclock\n"); return -EINVAL; } else { - err = par->pll_ops->var_to_pll(info, pixclock, - var->bits_per_pixel, &par->pll); - if (err) + if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &par->pll))) return err; } @@ -1340,23 +1313,22 @@ static int atyfb_set_par(struct fb_info *info) wait_for_idle(par); aty_set_crtc(par, &par->crtc); - par->dac_ops->set_dac(info, &par->pll, - var->bits_per_pixel, par->accel_flags); + par->dac_ops->set_dac(info, &par->pll, var->bits_per_pixel, par->accel_flags); par->pll_ops->set_pll(info, &par->pll); #ifdef DEBUG - if (par->pll_ops && par->pll_ops->pll_to_var) - pixclock_in_ps = par->pll_ops->pll_to_var(info, &par->pll); + if(par->pll_ops && par->pll_ops->pll_to_var) + pixclock_in_ps = par->pll_ops->pll_to_var(info, &(par->pll)); else pixclock_in_ps = 0; - if (0 == pixclock_in_ps) { + if(0 == pixclock_in_ps) { PRINTKE("ALERT ops->pll_to_var get 0\n"); pixclock_in_ps = pixclock; } memset(&debug, 0, sizeof(debug)); - if (!aty_crtc_to_var(&par->crtc, &debug)) { + if(!aty_crtc_to_var(&(par->crtc), &debug)) { u32 hSync, vRefresh; u32 h_disp, h_sync_strt, h_sync_end, h_total; u32 v_disp, v_sync_strt, v_sync_end, v_total; @@ -1372,20 +1344,16 @@ static int atyfb_set_par(struct fb_info *info) hSync = 1000000000 / (pixclock_in_ps * h_total); vRefresh = (hSync * 1000) / v_total; - if (par->crtc.gen_cntl & CRTC_INTERLACE_EN) - vRefresh *= 2; - if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) - vRefresh /= 2; + if (par->crtc.gen_cntl & CRTC_INTERLACE_EN) + vRefresh *= 2; + if (par->crtc.gen_cntl & CRTC_DBL_SCAN_EN) + vRefresh /= 2; DPRINTK("atyfb_set_par\n"); - DPRINTK(" Set Visible Mode to %ix%i-%i\n", - var->xres, var->yres, var->bits_per_pixel); - DPRINTK(" Virtual resolution %ix%i, " - "pixclock_in_ps %i (calculated %i)\n", - var->xres_virtual, var->yres_virtual, - pixclock, pixclock_in_ps); - DPRINTK(" Dot clock: %i MHz\n", - 1000000 / pixclock_in_ps); + DPRINTK(" Set Visible Mode to %ix%i-%i\n", var->xres, var->yres, var->bits_per_pixel); + DPRINTK(" Virtual resolution %ix%i, pixclock_in_ps %i (calculated %i)\n", + var->xres_virtual, var->yres_virtual, pixclock, pixclock_in_ps); + DPRINTK(" Dot clock: %i MHz\n", 1000000 / pixclock_in_ps); DPRINTK(" Horizontal sync: %i kHz\n", hSync); DPRINTK(" Vertical refresh: %i Hz\n", vRefresh); DPRINTK(" x style: %i.%03i %i %i %i %i %i %i %i %i\n", @@ -1480,8 +1448,7 @@ static int atyfb_set_par(struct fb_info *info) base = 0x2000; printk("debug atyfb: Mach64 non-shadow register values:"); for (i = 0; i < 256; i = i+4) { - if (i % 16 == 0) - printk("\ndebug atyfb: 0x%04X: ", base + i); + if(i%16 == 0) printk("\ndebug atyfb: 0x%04X: ", base + i); printk(" %08X", aty_ld_le32(i, par)); } printk("\n\n"); @@ -1491,10 +1458,8 @@ static int atyfb_set_par(struct fb_info *info) base = 0x00; printk("debug atyfb: Mach64 PLL register values:"); for (i = 0; i < 64; i++) { - if (i % 16 == 0) - printk("\ndebug atyfb: 0x%02X: ", base + i); - if (i % 4 == 0) - printk(" "); + if(i%16 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i); + if(i%4 == 0) printk(" "); printk("%02X", aty_ld_pll_ct(i, par)); } printk("\n\n"); @@ -1505,21 +1470,19 @@ static int atyfb_set_par(struct fb_info *info) /* LCD registers */ base = 0x00; printk("debug atyfb: LCD register values:"); - if (M64_HAS(LT_LCD_REGS)) { - for (i = 0; i <= POWER_MANAGEMENT; i++) { - if (i == EXT_VERT_STRETCH) - continue; - printk("\ndebug atyfb: 0x%04X: ", - lt_lcd_regs[i]); - printk(" %08X", aty_ld_lcd(i, par)); - } + if(M64_HAS(LT_LCD_REGS)) { + for(i = 0; i <= POWER_MANAGEMENT; i++) { + if(i == EXT_VERT_STRETCH) + continue; + printk("\ndebug atyfb: 0x%04X: ", lt_lcd_regs[i]); + printk(" %08X", aty_ld_lcd(i, par)); + } + } else { - for (i = 0; i < 64; i++) { - if (i % 4 == 0) - printk("\ndebug atyfb: 0x%02X: ", - base + i); - printk(" %08X", aty_ld_lcd(i, par)); - } + for (i = 0; i < 64; i++) { + if(i%4 == 0) printk("\ndebug atyfb: 0x%02X: ", base + i); + printk(" %08X", aty_ld_lcd(i, par)); + } } printk("\n\n"); } @@ -1537,10 +1500,9 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) union aty_pll pll; u32 pixclock; - memcpy(&pll, &par->pll, sizeof(pll)); + memcpy(&pll, &(par->pll), sizeof(pll)); - err = aty_var_to_crtc(info, var, &crtc); - if (err) + if((err = aty_var_to_crtc(info, var, &crtc))) return err; pixclock = atyfb_get_pixclock(var, par); @@ -1550,9 +1512,7 @@ static int atyfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) PRINTKE("Invalid pixclock\n"); return -EINVAL; } else { - err = par->pll_ops->var_to_pll(info, pixclock, - var->bits_per_pixel, &pll); - if (err) + if((err = par->pll_ops->var_to_pll(info, pixclock, var->bits_per_pixel, &pll))) return err; } @@ -1579,9 +1539,9 @@ static void set_off_pitch(struct atyfb_par *par, const struct fb_info *info) } -/* - * Open/Release the frame buffer device - */ + /* + * Open/Release the frame buffer device + */ static int atyfb_open(struct fb_info *info, int user) { @@ -1593,7 +1553,7 @@ static int atyfb_open(struct fb_info *info, int user) par->mmaped = 0; #endif } - return 0; + return (0); } static irqreturn_t aty_irq(int irq, void *dev_id) @@ -1608,8 +1568,7 @@ static irqreturn_t aty_irq(int irq, void *dev_id) if (int_cntl & CRTC_VBLANK_INT) { /* clear interrupt */ - aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | - CRTC_VBLANK_INT_AK, par); + aty_st_le32(CRTC_INT_CNTL, (int_cntl & CRTC_INT_EN_MASK) | CRTC_VBLANK_INT_AK, par); par->vblank.count++; if (par->vblank.pan_display) { par->vblank.pan_display = 0; @@ -1644,11 +1603,9 @@ static int aty_enable_irq(struct atyfb_par *par, int reenable) spin_lock_irq(&par->int_lock); int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK; if (!(int_cntl & CRTC_VBLANK_INT_EN)) { - printk("atyfb: someone disabled IRQ [%08x]\n", - int_cntl); + printk("atyfb: someone disabled IRQ [%08x]\n", int_cntl); /* re-enable interrupt */ - aty_st_le32(CRTC_INT_CNTL, int_cntl | - CRTC_VBLANK_INT_EN, par); + aty_st_le32(CRTC_INT_CNTL, int_cntl | CRTC_VBLANK_INT_EN, par ); } spin_unlock_irq(&par->int_lock); } @@ -1668,7 +1625,7 @@ static int aty_disable_irq(struct atyfb_par *par) spin_lock_irq(&par->int_lock); int_cntl = aty_ld_le32(CRTC_INT_CNTL, par) & CRTC_INT_EN_MASK; /* disable interrupt */ - aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par); + aty_st_le32(CRTC_INT_CNTL, int_cntl & ~CRTC_VBLANK_INT_EN, par ); spin_unlock_irq(&par->int_lock); free_irq(par->irq, par); } @@ -1679,62 +1636,50 @@ static int aty_disable_irq(struct atyfb_par *par) static int atyfb_release(struct fb_info *info, int user) { struct atyfb_par *par = (struct atyfb_par *) info->par; + if (user) { + par->open--; + mdelay(1); + wait_for_idle(par); + if (!par->open) { #ifdef __sparc__ - int was_mmaped; -#endif - - if (!user) - return 0; - - par->open--; - mdelay(1); - wait_for_idle(par); - - if (par->open) - return 0; - -#ifdef __sparc__ - was_mmaped = par->mmaped; + int was_mmaped = par->mmaped; - par->mmaped = 0; + par->mmaped = 0; - if (was_mmaped) { - struct fb_var_screeninfo var; + if (was_mmaped) { + struct fb_var_screeninfo var; - /* - * Now reset the default display config, we have - * no idea what the program(s) which mmap'd the - * chip did to the configuration, nor whether it - * restored it correctly. - */ - var = default_var; - if (noaccel) - var.accel_flags &= ~FB_ACCELF_TEXT; - else - var.accel_flags |= FB_ACCELF_TEXT; - if (var.yres == var.yres_virtual) { - u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2)); - var.yres_virtual = - ((videoram * 8) / var.bits_per_pixel) / - var.xres_virtual; - if (var.yres_virtual < var.yres) - var.yres_virtual = var.yres; + /* Now reset the default display config, we have no + * idea what the program(s) which mmap'd the chip did + * to the configuration, nor whether it restored it + * correctly. + */ + var = default_var; + if (noaccel) + var.accel_flags &= ~FB_ACCELF_TEXT; + else + var.accel_flags |= FB_ACCELF_TEXT; + if (var.yres == var.yres_virtual) { + u32 videoram = (info->fix.smem_len - (PAGE_SIZE << 2)); + var.yres_virtual = ((videoram * 8) / var.bits_per_pixel) / var.xres_virtual; + if (var.yres_virtual < var.yres) + var.yres_virtual = var.yres; + } + } +#endif + aty_disable_irq(par); } } -#endif - aty_disable_irq(par); - - return 0; + return (0); } -/* - * Pan or Wrap the Display - * - * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag - */ + /* + * Pan or Wrap the Display + * + * This call looks only at xoffset, yoffset and the FB_VMODE_YWRAP flag + */ -static int atyfb_pan_display(struct fb_var_screeninfo *var, - struct fb_info *info) +static int atyfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; u32 xres, yres, xoffset, yoffset; @@ -1745,8 +1690,7 @@ static int atyfb_pan_display(struct fb_var_screeninfo *var, yres >>= 1; xoffset = (var->xoffset + 7) & ~7; yoffset = var->yoffset; - if (xoffset + xres > par->crtc.vxres || - yoffset + yres > par->crtc.vyres) + if (xoffset + xres > par->crtc.vxres || yoffset + yres > par->crtc.vyres) return -EINVAL; info->var.xoffset = xoffset; info->var.yoffset = yoffset; @@ -1783,10 +1727,10 @@ static int aty_waitforvblank(struct atyfb_par *par, u32 crtc) return ret; count = vbl->count; - ret = wait_event_interruptible_timeout(vbl->wait, - count != vbl->count, HZ/10); - if (ret < 0) + ret = wait_event_interruptible_timeout(vbl->wait, count != vbl->count, HZ/10); + if (ret < 0) { return ret; + } if (ret == 0) { aty_enable_irq(par, 1); return -ETIMEDOUT; @@ -1840,8 +1784,7 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) fbtyp.fb_depth = info->var.bits_per_pixel; fbtyp.fb_cmsize = info->cmap.len; fbtyp.fb_size = info->fix.smem_len; - if (copy_to_user((struct fbtype __user *) arg, &fbtyp, - sizeof(fbtyp))) + if (copy_to_user((struct fbtype __user *) arg, &fbtyp, sizeof(fbtyp))) return -EFAULT; break; #endif /* __sparc__ */ @@ -1861,7 +1804,7 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) case ATYIO_CLKR: if (M64_HAS(INTEGRATED)) { struct atyclk clk; - union aty_pll *pll = &par->pll; + union aty_pll *pll = &(par->pll); u32 dsp_config = pll->ct.dsp_config; u32 dsp_on_off = pll->ct.dsp_on_off; clk.ref_clk_per = par->ref_clk_per; @@ -1886,9 +1829,8 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) case ATYIO_CLKW: if (M64_HAS(INTEGRATED)) { struct atyclk clk; - union aty_pll *pll = &par->pll; - if (copy_from_user(&clk, (struct atyclk __user *) arg, - sizeof(clk))) + union aty_pll *pll = &(par->pll); + if (copy_from_user(&clk, (struct atyclk __user *) arg, sizeof(clk))) return -EFAULT; par->ref_clk_per = clk.ref_clk_per; pll->ct.pll_ref_div = clk.pll_ref_div; @@ -1899,10 +1841,8 @@ static int atyfb_ioctl(struct fb_info *info, u_int cmd, u_long arg) pll->ct.vclk_fb_div = clk.vclk_fb_div; pll->ct.vclk_post_div_real = clk.vclk_post_div; pll->ct.dsp_config = (clk.dsp_xclks_per_row & 0x3fff) | - ((clk.dsp_loop_latency & 0xf) << 16) | - ((clk.dsp_precision & 7) << 20); - pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | - ((clk.dsp_on & 0x7ff) << 16); + ((clk.dsp_loop_latency & 0xf)<<16)| ((clk.dsp_precision & 7)<<20); + pll->ct.dsp_on_off = (clk.dsp_off & 0x7ff) | ((clk.dsp_on & 0x7ff)<<16); /*aty_calc_pll_ct(info, &pll->ct);*/ aty_set_pll_ct(info, pll); } else @@ -1973,7 +1913,8 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) continue; map_size = par->mmap_map[i].size - (offset - start); - map_offset = par->mmap_map[i].poff + (offset - start); + map_offset = + par->mmap_map[i].poff + (offset - start); break; } if (!map_size) { @@ -1983,7 +1924,8 @@ static int atyfb_mmap(struct fb_info *info, struct vm_area_struct *vma) if (page + map_size > size) map_size = size - page; - pgprot_val(vma->vm_page_prot) &= ~(par->mmap_map[i].prot_mask); + pgprot_val(vma->vm_page_prot) &= + ~(par->mmap_map[i].prot_mask); pgprot_val(vma->vm_page_prot) |= par->mmap_map[i].prot_flag; if (remap_pfn_range(vma, vma->vm_start + page, @@ -2087,8 +2029,7 @@ static int atyfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) par->asleep = 1; par->lock_blank = 1; - /* - * Because we may change PCI D state ourselves, we need to + /* Because we may change PCI D state ourselves, we need to * first save the config space content so the core can * restore it properly on resume. */ @@ -2139,8 +2080,7 @@ static int atyfb_pci_resume(struct pci_dev *pdev) acquire_console_sem(); - /* - * PCI state will have been restored by the core, so + /* PCI state will have been restored by the core, so * we should be in D0 now with our config space fully * restored */ @@ -2252,8 +2192,8 @@ static void aty_bl_init(struct atyfb_par *par) info->bl_dev = bd; fb_bl_default_curve(info, 0, - 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, - 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); + 0x3F * FB_BACKLIGHT_MAX / MAX_LEVEL, + 0xFF * FB_BACKLIGHT_MAX / MAX_LEVEL); bd->props.max_brightness = FB_BACKLIGHT_LEVELS - 1; bd->props.brightness = bd->props.max_brightness; @@ -2296,16 +2236,16 @@ static void __devinit aty_calc_mem_refresh(struct atyfb_par *par, int xclk) size = ARRAY_SIZE(ragepro_tbl); } - for (i = 0; i < size; i++) { + for (i=0; i < size; i++) { if (xclk < refresh_tbl[i]) - break; + break; } par->mem_refresh_rate = i; } -/* - * Initialisation - */ + /* + * Initialisation + */ static struct fb_info *fb_list = NULL; @@ -2435,10 +2375,8 @@ static int __devinit aty_init(struct fb_info *info) } #endif #ifdef CONFIG_PPC_PMAC - /* - * The Apple iBook1 uses non-standard memory frequencies. - * We detect it and set the frequency manually. - */ + /* The Apple iBook1 uses non-standard memory frequencies. We detect it + * and set the frequency manually. */ if (machine_is_compatible("PowerBook2,1")) { par->pll_limits.mclk = 70; par->pll_limits.xclk = 53; @@ -2483,14 +2421,13 @@ static int __devinit aty_init(struct fb_info *info) /* save previous video mode */ aty_get_crtc(par, &par->saved_crtc); - if (par->pll_ops->get_pll) + if(par->pll_ops->get_pll) par->pll_ops->get_pll(info, &par->saved_pll); par->mem_cntl = aty_ld_le32(MEM_CNTL, par); gtb_memsize = M64_HAS(GTB_DSP); if (gtb_memsize) - /* 0xF used instead of MEM_SIZE_ALIAS */ - switch (par->mem_cntl & 0xF) { + switch (par->mem_cntl & 0xF) { /* 0xF used instead of MEM_SIZE_ALIAS */ case MEM_SIZE_512K: info->fix.smem_len = 0x80000; break; @@ -2559,8 +2496,8 @@ static int __devinit aty_init(struct fb_info *info) } /* - * Reg Block 0 (CT-compatible block) is at mmio_start - * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400 + * Reg Block 0 (CT-compatible block) is at mmio_start + * Reg Block 1 (multimedia extensions) is at mmio_start - 0x400 */ if (M64_HAS(GX)) { info->fix.mmio_len = 0x400; @@ -2579,98 +2516,84 @@ static int __devinit aty_init(struct fb_info *info) } PRINTKI("%d%c %s, %s MHz XTAL, %d MHz PLL, %d Mhz MCLK, %d MHz XCLK\n", - info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len>>20), - info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, - par->pll_limits.pll_max, par->pll_limits.mclk, - par->pll_limits.xclk); + info->fix.smem_len == 0x80000 ? 512 : (info->fix.smem_len >> 20), + info->fix.smem_len == 0x80000 ? 'K' : 'M', ramname, xtal, par->pll_limits.pll_max, + par->pll_limits.mclk, par->pll_limits.xclk); #if defined(DEBUG) && defined(CONFIG_FB_ATY_CT) if (M64_HAS(INTEGRATED)) { int i; - printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL " - "EXT_MEM_CNTL CRTC_GEN_CNTL DSP_CONFIG " - "DSP_ON_OFF CLOCK_CNTL\n" - "debug atyfb: %08x %08x %08x " - "%08x %08x %08x " - "%08x %08x\n" + printk("debug atyfb: BUS_CNTL DAC_CNTL MEM_CNTL EXT_MEM_CNTL CRTC_GEN_CNTL " + "DSP_CONFIG DSP_ON_OFF CLOCK_CNTL\n" + "debug atyfb: %08x %08x %08x %08x %08x %08x %08x %08x\n" "debug atyfb: PLL", - aty_ld_le32(BUS_CNTL, par), - aty_ld_le32(DAC_CNTL, par), - aty_ld_le32(MEM_CNTL, par), - aty_ld_le32(EXT_MEM_CNTL, par), - aty_ld_le32(CRTC_GEN_CNTL, par), - aty_ld_le32(DSP_CONFIG, par), - aty_ld_le32(DSP_ON_OFF, par), - aty_ld_le32(CLOCK_CNTL, par)); + aty_ld_le32(BUS_CNTL, par), aty_ld_le32(DAC_CNTL, par), + aty_ld_le32(MEM_CNTL, par), aty_ld_le32(EXT_MEM_CNTL, par), + aty_ld_le32(CRTC_GEN_CNTL, par), aty_ld_le32(DSP_CONFIG, par), + aty_ld_le32(DSP_ON_OFF, par), aty_ld_le32(CLOCK_CNTL, par)); for (i = 0; i < 40; i++) printk(" %02x", aty_ld_pll_ct(i, par)); printk("\n"); } #endif - if (par->pll_ops->init_pll) + if(par->pll_ops->init_pll) par->pll_ops->init_pll(info, &par->pll); if (par->pll_ops->resume_pll) par->pll_ops->resume_pll(info, &par->pll); /* - * Last page of 8 MB (4 MB on ISA) aperture is MMIO, - * unless the auxiliary register aperture is used. + * Last page of 8 MB (4 MB on ISA) aperture is MMIO, + * unless the auxiliary register aperture is used. */ + if (!par->aux_start && - (info->fix.smem_len == 0x800000 || - (par->bus_type == ISA && info->fix.smem_len == 0x400000))) + (info->fix.smem_len == 0x800000 || (par->bus_type == ISA && info->fix.smem_len == 0x400000))) info->fix.smem_len -= GUI_RESERVE; /* - * Disable register access through the linear aperture - * if the auxiliary aperture is used so we can access - * the full 8 MB of video RAM on 8 MB boards. + * Disable register access through the linear aperture + * if the auxiliary aperture is used so we can access + * the full 8 MB of video RAM on 8 MB boards. */ if (par->aux_start) - aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | - BUS_APER_REG_DIS, par); + aty_st_le32(BUS_CNTL, aty_ld_le32(BUS_CNTL, par) | BUS_APER_REG_DIS, par); #ifdef CONFIG_MTRR par->mtrr_aper = -1; par->mtrr_reg = -1; if (!nomtrr) { /* Cover the whole resource. */ - par->mtrr_aper = mtrr_add(par->res_start, par->res_size, - MTRR_TYPE_WRCOMB, 1); - if (par->mtrr_aper >= 0 && !par->aux_start) { + par->mtrr_aper = mtrr_add(par->res_start, par->res_size, MTRR_TYPE_WRCOMB, 1); + if (par->mtrr_aper >= 0 && !par->aux_start) { /* Make a hole for mmio. */ - par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - - GUI_RESERVE, GUI_RESERVE, - MTRR_TYPE_UNCACHABLE, 1); + par->mtrr_reg = mtrr_add(par->res_start + 0x800000 - GUI_RESERVE, + GUI_RESERVE, MTRR_TYPE_UNCACHABLE, 1); if (par->mtrr_reg < 0) { mtrr_del(par->mtrr_aper, 0, 0); par->mtrr_aper = -1; } - } + } } #endif info->fbops = &atyfb_ops; info->pseudo_palette = par->pseudo_palette; info->flags = FBINFO_DEFAULT | - FBINFO_HWACCEL_IMAGEBLIT | - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_COPYAREA | - FBINFO_HWACCEL_YPAN; + FBINFO_HWACCEL_IMAGEBLIT | + FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_COPYAREA | + FBINFO_HWACCEL_YPAN; #ifdef CONFIG_PMAC_BACKLIGHT if (M64_HAS(G3_PB_1_1) && machine_is_compatible("PowerBook1,1")) { - /* - * these bits let the 101 powerbook - * wake up from sleep -- paulus - */ - aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) | - USE_F32KHZ | TRISTATE_MEM_EN, par); + /* these bits let the 101 powerbook wake up from sleep -- paulus */ + aty_st_lcd(POWER_MANAGEMENT, aty_ld_lcd(POWER_MANAGEMENT, par) + | (USE_F32KHZ | TRISTATE_MEM_EN), par); } else #endif if (M64_HAS(MOBIL_BUS) && backlight) { #ifdef CONFIG_FB_ATY_BACKLIGHT - aty_bl_init(par); + aty_bl_init (par); #endif } @@ -2678,8 +2601,8 @@ static int __devinit aty_init(struct fb_info *info) #ifdef CONFIG_PPC if (machine_is(powermac)) { /* - * FIXME: The NVRAM stuff should be put in a Mac-specific file, - * as it applies to all Mac video cards + * FIXME: The NVRAM stuff should be put in a Mac-specific file, as it + * applies to all Mac video cards */ if (mode) { if (mac_find_mode(&var, info, mode, 8)) @@ -2692,7 +2615,8 @@ static int __devinit aty_init(struct fb_info *info) default_vmode = VMODE_1024_768_60; else if (machine_is_compatible("iMac")) default_vmode = VMODE_1024_768_75; - else if (machine_is_compatible("PowerBook2,1")) + else if (machine_is_compatible + ("PowerBook2,1")) /* iBook with 800x600 LCD */ default_vmode = VMODE_800_600_60; else @@ -2706,7 +2630,7 @@ static int __devinit aty_init(struct fb_info *info) if (default_cmode < CMODE_8 || default_cmode > CMODE_32) default_cmode = CMODE_8; if (!mac_vmode_to_var(default_vmode, default_cmode, - &var)) + &var)) has_var = 1; } } @@ -2778,12 +2702,12 @@ static int __devinit aty_init(struct fb_info *info) #ifdef CONFIG_MTRR if (par->mtrr_reg >= 0) { - mtrr_del(par->mtrr_reg, 0, 0); - par->mtrr_reg = -1; + mtrr_del(par->mtrr_reg, 0, 0); + par->mtrr_reg = -1; } if (par->mtrr_aper >= 0) { - mtrr_del(par->mtrr_aper, 0, 0); - par->mtrr_aper = -1; + mtrr_del(par->mtrr_aper, 0, 0); + par->mtrr_aper = -1; } #endif return ret; @@ -2811,18 +2735,18 @@ static int __devinit store_video_par(char *video_str, unsigned char m64_num) phys_size[m64_num] = size; phys_guiregbase[m64_num] = guiregbase; PRINTKI("stored them all: $%08lX $%08lX $%08lX \n", vmembase, size, - guiregbase); + guiregbase); return 0; - mach64_invalid: + mach64_invalid: phys_vmembase[m64_num] = 0; return -1; } #endif /* CONFIG_ATARI */ -/* - * Blank the display. - */ + /* + * Blank the display. + */ static int atyfb_blank(int blank, struct fb_info *info) { @@ -2844,20 +2768,20 @@ static int atyfb_blank(int blank, struct fb_info *info) gen_cntl = aty_ld_le32(CRTC_GEN_CNTL, par); gen_cntl &= ~0x400004c; switch (blank) { - case FB_BLANK_UNBLANK: - break; - case FB_BLANK_NORMAL: - gen_cntl |= 0x4000040; - break; - case FB_BLANK_VSYNC_SUSPEND: - gen_cntl |= 0x4000048; - break; - case FB_BLANK_HSYNC_SUSPEND: - gen_cntl |= 0x4000044; - break; - case FB_BLANK_POWERDOWN: - gen_cntl |= 0x400004c; - break; + case FB_BLANK_UNBLANK: + break; + case FB_BLANK_NORMAL: + gen_cntl |= 0x4000040; + break; + case FB_BLANK_VSYNC_SUSPEND: + gen_cntl |= 0x4000048; + break; + case FB_BLANK_HSYNC_SUSPEND: + gen_cntl |= 0x4000044; + break; + case FB_BLANK_POWERDOWN: + gen_cntl |= 0x400004c; + break; } aty_st_le32(CRTC_GEN_CNTL, gen_cntl, par); @@ -2882,15 +2806,15 @@ static void aty_st_pal(u_int regno, u_int red, u_int green, u_int blue, aty_st_8(DAC_DATA, blue, par); } -/* - * Set a single color register. The values supplied are already - * rounded down to the hardware's capabilities (according to the - * entries in the var structure). Return != 0 for invalid regno. - * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR - */ + /* + * Set a single color register. The values supplied are already + * rounded down to the hardware's capabilities (according to the + * entries in the var structure). Return != 0 for invalid regno. + * !! 4 & 8 = PSEUDO, > 8 = DIRECTCOLOR + */ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, - u_int transp, struct fb_info *info) + u_int transp, struct fb_info *info) { struct atyfb_par *par = (struct atyfb_par *) info->par; int i, depth; @@ -2944,15 +2868,16 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, if (depth == 16) { if (regno < 32) aty_st_pal(regno << 3, red, - par->palette[regno << 1].green, + par->palette[regno<<1].green, blue, par); - red = par->palette[regno >> 1].red; - blue = par->palette[regno >> 1].blue; + red = par->palette[regno>>1].red; + blue = par->palette[regno>>1].blue; regno <<= 2; } else if (depth == 15) { regno <<= 3; - for (i = 0; i < 8; i++) - aty_st_pal(regno + i, red, green, blue, par); + for(i = 0; i < 8; i++) { + aty_st_pal(regno + i, red, green, blue, par); + } } } aty_st_pal(regno, red, green, blue, par); @@ -2965,8 +2890,7 @@ static int atyfb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, #ifdef __sparc__ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, - struct fb_info *info, - unsigned long addr) + struct fb_info *info, unsigned long addr) { struct atyfb_par *par = info->par; struct device_node *dp; @@ -3054,8 +2978,7 @@ static int __devinit atyfb_setup_sparc(struct pci_dev *pdev, j++; } - ret = correct_chipset(par); - if (ret) + if((ret = correct_chipset(par))) return ret; if (IS_XL(pdev->device)) { @@ -3185,28 +3108,28 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) u32 driv_inf_tab, sig; u16 lcd_ofs; - /* - * To support an LCD panel, we should know it's dimensions and + /* To support an LCD panel, we should know it's dimensions and * it's desired pixel clock. * There are two ways to do it: * - Check the startup video mode and calculate the panel * size from it. This is unreliable. * - Read it from the driver information table in the video BIOS. - */ + */ /* Address of driver information table is at offset 0x78. */ driv_inf_tab = bios_base + *((u16 *)(bios_base+0x78)); /* Check for the driver information table signature. */ - sig = *(u32 *)driv_inf_tab; + sig = (*(u32 *)driv_inf_tab); if ((sig == 0x54504c24) || /* Rage LT pro */ - (sig == 0x544d5224) || /* Rage mobility */ - (sig == 0x54435824) || /* Rage XC */ - (sig == 0x544c5824)) { /* Rage XL */ + (sig == 0x544d5224) || /* Rage mobility */ + (sig == 0x54435824) || /* Rage XC */ + (sig == 0x544c5824)) { /* Rage XL */ PRINTKI("BIOS contains driver information table.\n"); - lcd_ofs = *(u16 *)(driv_inf_tab + 10); + lcd_ofs = (*(u16 *)(driv_inf_tab + 10)); par->lcd_table = 0; - if (lcd_ofs != 0) + if (lcd_ofs != 0) { par->lcd_table = bios_base + lcd_ofs; + } } if (par->lcd_table != 0) { @@ -3221,16 +3144,14 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) u16 width, height, panel_type, refresh_rates; u16 *lcdmodeptr; u32 format; - u8 lcd_refresh_rates[16] = { 50, 56, 60, 67, 70, 72, 75, 76, 85, - 90, 100, 120, 140, 150, 160, 200 }; - /* - * The most important information is the panel size at + u8 lcd_refresh_rates[16] = {50,56,60,67,70,72,75,76,85,90,100,120,140,150,160,200}; + /* The most important information is the panel size at * offset 25 and 27, but there's some other nice information * which we print to the screen. */ id = *(u8 *)par->lcd_table; - strncpy(model, (char *)par->lcd_table+1, 24); - model[23] = 0; + strncpy(model,(char *)par->lcd_table+1,24); + model[23]=0; width = par->lcd_width = *(u16 *)(par->lcd_table+25); height = par->lcd_height = *(u16 *)(par->lcd_table+27); @@ -3243,7 +3164,7 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) txtdual = "dual (split) "; else txtdual = ""; - tech = (panel_type >> 2) & 63; + tech = (panel_type>>2) & 63; switch (tech) { case 0: txtmonitor = "passive matrix"; @@ -3303,24 +3224,22 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) } } PRINTKI("%s%s %s monitor detected: %s\n", - txtdual, txtcolour, txtmonitor, model); + txtdual ,txtcolour, txtmonitor, model); PRINTKI(" id=%d, %dx%d pixels, %s\n", id, width, height, txtformat); refresh_rates_buf[0] = 0; refresh_rates = *(u16 *)(par->lcd_table+62); m = 1; f = 0; - for (i = 0; i < 16; i++) { + for (i=0;i<16;i++) { if (refresh_rates & m) { if (f == 0) { - sprintf(strbuf, "%d", - lcd_refresh_rates[i]); + sprintf(strbuf, "%d", lcd_refresh_rates[i]); f++; } else { - sprintf(strbuf, ",%d", - lcd_refresh_rates[i]); + sprintf(strbuf, ",%d", lcd_refresh_rates[i]); } - strcat(refresh_rates_buf, strbuf); + strcat(refresh_rates_buf,strbuf); } m = m << 1; } @@ -3328,8 +3247,7 @@ static void __devinit aty_init_lcd(struct atyfb_par *par, u32 bios_base) PRINTKI(" supports refresh rates [%s], default %d Hz\n", refresh_rates_buf, lcd_refresh_rates[default_refresh_rate]); par->lcd_refreshrate = lcd_refresh_rates[default_refresh_rate]; - /* - * We now need to determine the crtc parameters for the + /* We now need to determine the crtc parameters for the * LCD monitor. This is tricky, because they are not stored * individually in the BIOS. Instead, the BIOS contains a * table of display modes that work for this monitor. @@ -3464,9 +3382,7 @@ static int __devinit init_from_bios(struct atyfb_par *par) } #endif /* __i386__ */ -static int __devinit atyfb_setup_generic(struct pci_dev *pdev, - struct fb_info *info, - unsigned long addr) +static int __devinit atyfb_setup_generic(struct pci_dev *pdev, struct fb_info *info, unsigned long addr) { struct atyfb_par *par = info->par; u16 tmp; @@ -3513,12 +3429,10 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, goto atyfb_setup_generic_fail; } - ret = correct_chipset(par); - if (ret) + if((ret = correct_chipset(par))) goto atyfb_setup_generic_fail; #ifdef __i386__ - ret = init_from_bios(par); - if (ret) + if((ret = init_from_bios(par))) goto atyfb_setup_generic_fail; #endif if (!(aty_ld_le32(CRTC_GEN_CNTL, par) & CRTC_EXT_DISP_EN)) @@ -3543,8 +3457,7 @@ static int __devinit atyfb_setup_generic(struct pci_dev *pdev, #endif /* !__sparc__ */ -static int __devinit atyfb_pci_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) +static int __devinit atyfb_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { unsigned long addr, res_start, res_size; struct fb_info *info; @@ -3569,10 +3482,10 @@ static int __devinit atyfb_pci_probe(struct pci_dev *pdev, /* Reserve space */ res_start = rp->start; res_size = rp->end - rp->start + 1; - if (!request_mem_region(res_start, res_size, "atyfb")) + if (!request_mem_region (res_start, res_size, "atyfb")) return -EBUSY; - /* Allocate framebuffer */ + /* Allocate framebuffer */ info = framebuffer_alloc(sizeof(struct atyfb_par), &pdev->dev); if (!info) { PRINTKE("atyfb_pci_probe() can't alloc fb_info\n"); @@ -3660,8 +3573,7 @@ static int __init atyfb_atari_probe(void) for (m64_num = 0; m64_num < mach64_count; m64_num++) { if (!phys_vmembase[m64_num] || !phys_size[m64_num] || !phys_guiregbase[m64_num]) { - PRINTKI("phys_*[%d] parameters not set => " - "returning early. \n", m64_num); + PRINTKI("phys_*[%d] parameters not set => returning early. \n", m64_num); continue; } @@ -3677,8 +3589,8 @@ static int __init atyfb_atari_probe(void) par->irq = (unsigned int) -1; /* something invalid */ /* - * Map the video memory (physical address given) - * to somewhere in the kernel address space. + * Map the video memory (physical address given) to somewhere in the + * kernel address space. */ info->screen_base = ioremap(phys_vmembase[m64_num], phys_size[m64_num]); info->fix.smem_start = (unsigned long)info->screen_base; /* Fake! */ @@ -3749,12 +3661,12 @@ static void __devexit atyfb_remove(struct fb_info *info) #ifdef CONFIG_MTRR if (par->mtrr_reg >= 0) { - mtrr_del(par->mtrr_reg, 0, 0); - par->mtrr_reg = -1; + mtrr_del(par->mtrr_reg, 0, 0); + par->mtrr_reg = -1; } if (par->mtrr_aper >= 0) { - mtrr_del(par->mtrr_aper, 0, 0); - par->mtrr_aper = -1; + mtrr_del(par->mtrr_aper, 0, 0); + par->mtrr_aper = -1; } #endif #ifndef __sparc__ @@ -3988,29 +3900,29 @@ static const struct dmi_system_id atyfb_reboot_ids[] = { static int __init atyfb_init(void) { - int err1 = 1, err2 = 1; + int err1 = 1, err2 = 1; #ifndef MODULE - char *option = NULL; + char *option = NULL; - if (fb_get_options("atyfb", &option)) - return -ENODEV; - atyfb_setup(option); + if (fb_get_options("atyfb", &option)) + return -ENODEV; + atyfb_setup(option); #endif #ifdef CONFIG_PCI - err1 = pci_register_driver(&atyfb_driver); + err1 = pci_register_driver(&atyfb_driver); #endif #ifdef CONFIG_ATARI - err2 = atyfb_atari_probe(); + err2 = atyfb_atari_probe(); #endif - if (err1 && err2) - return -ENODEV; + if (err1 && err2) + return -ENODEV; - if (dmi_check_system(atyfb_reboot_ids)) - register_reboot_notifier(&atyfb_reboot_notifier); + if (dmi_check_system(atyfb_reboot_ids)) + register_reboot_notifier(&atyfb_reboot_notifier); - return 0; + return 0; } static void __exit atyfb_exit(void) @@ -4039,7 +3951,8 @@ MODULE_PARM_DESC(mclk, "int: override memory clock"); module_param(xclk, int, 0); MODULE_PARM_DESC(xclk, "int: override accelerated engine clock"); module_param(comp_sync, int, 0); -MODULE_PARM_DESC(comp_sync, "Set composite sync signal to low (0) or high (1)"); +MODULE_PARM_DESC(comp_sync, + "Set composite sync signal to low (0) or high (1)"); module_param(mode, charp, 0); MODULE_PARM_DESC(mode, "Specify resolution as \"x[-][@]\" "); #ifdef CONFIG_MTRR diff --git a/trunk/drivers/video/au1100fb.c b/trunk/drivers/video/au1100fb.c index a699aab63820..378f27745a1d 100644 --- a/trunk/drivers/video/au1100fb.c +++ b/trunk/drivers/video/au1100fb.c @@ -715,11 +715,8 @@ int au1100fb_setup(char *options) } /* Mode option (only option that start with digit) */ else if (isdigit(this_opt[0])) { - mode = kstrdup(this_opt, GFP_KERNEL); - if (!mode) { - print_err("memory allocation failed"); - return -ENOMEM; - } + mode = kmalloc(strlen(this_opt) + 1, GFP_KERNEL); + strncpy(mode, this_opt, strlen(this_opt) + 1); } /* Unsupported option */ else { diff --git a/trunk/drivers/video/backlight/corgi_lcd.c b/trunk/drivers/video/backlight/corgi_lcd.c index 2211a852af9c..f8a4bb20f41a 100644 --- a/trunk/drivers/video/backlight/corgi_lcd.c +++ b/trunk/drivers/video/backlight/corgi_lcd.c @@ -639,4 +639,3 @@ module_exit(corgi_lcd_exit); MODULE_DESCRIPTION("LCD and backlight driver for SHARP C7x0/Cxx00"); MODULE_AUTHOR("Eric Miao "); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:corgi-lcd"); diff --git a/trunk/drivers/video/backlight/ltv350qv.c b/trunk/drivers/video/backlight/ltv350qv.c index 4631ca8fa4a4..2eb206bf73e6 100644 --- a/trunk/drivers/video/backlight/ltv350qv.c +++ b/trunk/drivers/video/backlight/ltv350qv.c @@ -328,4 +328,3 @@ module_exit(ltv350qv_exit); MODULE_AUTHOR("Haavard Skinnemoen "); MODULE_DESCRIPTION("Samsung LTV350QV LCD Driver"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:ltv350qv"); diff --git a/trunk/drivers/video/backlight/tdo24m.c b/trunk/drivers/video/backlight/tdo24m.c index bbfb502add67..51422fc4f606 100644 --- a/trunk/drivers/video/backlight/tdo24m.c +++ b/trunk/drivers/video/backlight/tdo24m.c @@ -472,4 +472,3 @@ module_exit(tdo24m_exit); MODULE_AUTHOR("Eric Miao "); MODULE_DESCRIPTION("Driver for Toppoly TDO24M LCD Panel"); MODULE_LICENSE("GPL"); -MODULE_ALIAS("spi:tdo24m"); diff --git a/trunk/drivers/video/backlight/tosa_lcd.c b/trunk/drivers/video/backlight/tosa_lcd.c index 50ec17dfc517..b7fbc75a62fc 100644 --- a/trunk/drivers/video/backlight/tosa_lcd.c +++ b/trunk/drivers/video/backlight/tosa_lcd.c @@ -300,4 +300,4 @@ module_exit(tosa_lcd_exit); MODULE_AUTHOR("Dmitry Baryshkov"); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("LCD/Backlight control for Sharp SL-6000 PDA"); -MODULE_ALIAS("spi:tosa-lcd"); + diff --git a/trunk/drivers/video/backlight/vgg2432a4.c b/trunk/drivers/video/backlight/vgg2432a4.c index b49063c831e7..8e653b8a6f17 100644 --- a/trunk/drivers/video/backlight/vgg2432a4.c +++ b/trunk/drivers/video/backlight/vgg2432a4.c @@ -280,4 +280,5 @@ module_exit(vgg2432a4_exit); MODULE_AUTHOR("Ben Dooks "); MODULE_DESCRIPTION("VGG2432A4 LCD Driver"); MODULE_LICENSE("GPL v2"); -MODULE_ALIAS("spi:VGG2432A4"); + + diff --git a/trunk/drivers/video/console/bitblit.c b/trunk/drivers/video/console/bitblit.c index 6b7c8fbc5495..69864b1b3f9e 100644 --- a/trunk/drivers/video/console/bitblit.c +++ b/trunk/drivers/video/console/bitblit.c @@ -25,7 +25,7 @@ static inline void update_attr(u8 *dst, u8 *src, int attribute, struct vc_data *vc) { int i, offset = (vc->vc_font.height < 10) ? 1 : 2; - int width = DIV_ROUND_UP(vc->vc_font.width, 8); + int width = (vc->vc_font.width + 7) >> 3; unsigned int cellsize = vc->vc_font.height * width; u8 c; @@ -144,7 +144,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, int fg, int bg) { struct fb_image image; - u32 width = DIV_ROUND_UP(vc->vc_font.width, 8); + u32 width = (vc->vc_font.width + 7)/8; u32 cellsize = width * vc->vc_font.height; u32 maxcnt = info->pixmap.size/cellsize; u32 scan_align = info->pixmap.scan_align - 1; @@ -173,7 +173,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info, cnt = count; image.width = vc->vc_font.width * cnt; - pitch = DIV_ROUND_UP(image.width, 8) + scan_align; + pitch = ((image.width + 7) >> 3) + scan_align; pitch &= ~scan_align; size = pitch * image.height + buf_align; size &= ~buf_align; @@ -239,7 +239,7 @@ static void bit_cursor(struct vc_data *vc, struct fb_info *info, int mode, struct fb_cursor cursor; struct fbcon_ops *ops = info->fbcon_par; unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; - int w = DIV_ROUND_UP(vc->vc_font.width, 8), c; + int w = (vc->vc_font.width + 7) >> 3, c; int y = real_y(ops->p, vc->vc_y); int attribute, use_sw = (vc->vc_cursor_type & 0x10); int err = 1; diff --git a/trunk/drivers/video/console/fbcon.c b/trunk/drivers/video/console/fbcon.c index 5a686cea23f4..3a44695b9c09 100644 --- a/trunk/drivers/video/console/fbcon.c +++ b/trunk/drivers/video/console/fbcon.c @@ -114,7 +114,6 @@ static int last_fb_vc = MAX_NR_CONSOLES - 1; static int fbcon_is_default = 1; static int fbcon_has_exited; static int primary_device = -1; -static int fbcon_has_console_bind; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY static int map_override; @@ -545,8 +544,6 @@ static int fbcon_takeover(int show_logo) con2fb_map[i] = -1; } info_idx = -1; - } else { - fbcon_has_console_bind = 1; } return err; @@ -728,7 +725,7 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, int oldidx, int found) { struct fbcon_ops *ops = oldinfo->fbcon_par; - int err = 0, ret; + int err = 0; if (oldinfo->fbops->fb_release && oldinfo->fbops->fb_release(oldinfo, 0)) { @@ -755,14 +752,8 @@ static int con2fb_release_oldinfo(struct vc_data *vc, struct fb_info *oldinfo, newinfo in an undefined state. Thus, a call to fb_set_par() may be needed for the newinfo. */ - if (newinfo->fbops->fb_set_par) { - ret = newinfo->fbops->fb_set_par(newinfo); - - if (ret) - printk(KERN_ERR "con2fb_release_oldinfo: " - "detected unhandled fb_set_par error, " - "error code %d\n", ret); - } + if (newinfo->fbops->fb_set_par) + newinfo->fbops->fb_set_par(newinfo); } return err; @@ -772,18 +763,11 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info, int unit, int show_logo) { struct fbcon_ops *ops = info->fbcon_par; - int ret; ops->currcon = fg_console; - if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) { - ret = info->fbops->fb_set_par(info); - - if (ret) - printk(KERN_ERR "con2fb_init_display: detected " - "unhandled fb_set_par error, " - "error code %d\n", ret); - } + if (info->fbops->fb_set_par && !(ops->flags & FBCON_FLAGS_INIT)) + info->fbops->fb_set_par(info); ops->flags |= FBCON_FLAGS_INIT; ops->graphics = 0; @@ -1022,7 +1006,7 @@ static void fbcon_init(struct vc_data *vc, int init) struct vc_data *svc = *default_mode; struct display *t, *p = &fb_display[vc->vc_num]; int logo = 1, new_rows, new_cols, rows, cols, charcnt = 256; - int cap, ret; + int cap; if (info_idx == -1 || info == NULL) return; @@ -1108,15 +1092,8 @@ static void fbcon_init(struct vc_data *vc, int init) */ if (CON_IS_VISIBLE(vc) && vc->vc_mode == KD_TEXT) { if (info->fbops->fb_set_par && - !(ops->flags & FBCON_FLAGS_INIT)) { - ret = info->fbops->fb_set_par(info); - - if (ret) - printk(KERN_ERR "fbcon_init: detected " - "unhandled fb_set_par error, " - "error code %d\n", ret); - } - + !(ops->flags & FBCON_FLAGS_INIT)) + info->fbops->fb_set_par(info); ops->flags |= FBCON_FLAGS_INIT; } @@ -2142,7 +2119,7 @@ static int fbcon_switch(struct vc_data *vc) struct fbcon_ops *ops; struct display *p = &fb_display[vc->vc_num]; struct fb_var_screeninfo var; - int i, ret, prev_console, charcnt = 256; + int i, prev_console, charcnt = 256; info = registered_fb[con2fb_map[vc->vc_num]]; ops = info->fbcon_par; @@ -2197,14 +2174,8 @@ static int fbcon_switch(struct vc_data *vc) if (old_info != NULL && (old_info != info || info->flags & FBINFO_MISC_ALWAYS_SETPAR)) { - if (info->fbops->fb_set_par) { - ret = info->fbops->fb_set_par(info); - - if (ret) - printk(KERN_ERR "fbcon_switch: detected " - "unhandled fb_set_par error, " - "error code %d\n", ret); - } + if (info->fbops->fb_set_par) + info->fbops->fb_set_par(info); if (old_info != info) fbcon_del_cursor_timer(old_info); @@ -2952,10 +2923,6 @@ static int fbcon_unbind(void) ret = unbind_con_driver(&fb_con, first_fb_vc, last_fb_vc, fbcon_is_default); - - if (!ret) - fbcon_has_console_bind = 0; - return ret; } #else @@ -2969,9 +2936,6 @@ static int fbcon_fb_unbind(int idx) { int i, new_idx = -1, ret = 0; - if (!fbcon_has_console_bind) - return 0; - for (i = first_fb_vc; i <= last_fb_vc; i++) { if (con2fb_map[i] != idx && con2fb_map[i] != -1) { diff --git a/trunk/drivers/video/console/newport_con.c b/trunk/drivers/video/console/newport_con.c index 3772433c49d1..d31b203bf654 100644 --- a/trunk/drivers/video/console/newport_con.c +++ b/trunk/drivers/video/console/newport_con.c @@ -216,7 +216,7 @@ static void newport_get_screensize(void) } newport_xsize = newport_ysize = 0; - for (i = 0; i < ARRAY_SIZE(linetable) - 1 && linetable[i + 1]; i += 2) { + for (i = 0; linetable[i + 1] && (i < sizeof(linetable)); i += 2) { cols = 0; newport_vc2_set(npregs, VC2_IREG_RADDR, linetable[i]); npregs->set.dcbmode = (NPORT_DMODE_AVC2 | VC2_REGADDR_RAM | diff --git a/trunk/drivers/video/console/vgacon.c b/trunk/drivers/video/console/vgacon.c index da55ccaf4d55..74e96cf83b7e 100644 --- a/trunk/drivers/video/console/vgacon.c +++ b/trunk/drivers/video/console/vgacon.c @@ -589,14 +589,12 @@ static void vgacon_init(struct vc_data *c, int init) static void vgacon_deinit(struct vc_data *c) { - /* When closing the active console, reset video origin */ - if (CON_IS_VISIBLE(c)) { + /* When closing the last console, reset video origin */ + if (!--vgacon_uni_pagedir[1]) { c->vc_visible_origin = vga_vram_base; vga_set_mem_top(c); - } - - if (!--vgacon_uni_pagedir[1]) con_free_unimap(c); + } c->vc_uni_pagedir_loc = &c->vc_uni_pagedir; con_set_default_unimap(c); } diff --git a/trunk/drivers/video/da8xx-fb.c b/trunk/drivers/video/da8xx-fb.c deleted file mode 100644 index 42e1005e2916..000000000000 --- a/trunk/drivers/video/da8xx-fb.c +++ /dev/null @@ -1,890 +0,0 @@ -/* - * Copyright (C) 2008-2009 MontaVista Software Inc. - * Copyright (C) 2008-2009 Texas Instruments Inc - * - * Based on the LCD driver for TI Avalanche processors written by - * Ajay Singh and Shalom Hai. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option)any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include