diff options
93 files changed, 2876 insertions, 435 deletions
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c index 51f430cc2fbf..2786f7c34b3f 100644 --- a/arch/arm/common/locomo.c +++ b/arch/arm/common/locomo.c | |||
@@ -541,6 +541,103 @@ locomo_init_one_child(struct locomo *lchip, struct locomo_dev_info *info) | |||
541 | return ret; | 541 | return ret; |
542 | } | 542 | } |
543 | 543 | ||
544 | #ifdef CONFIG_PM | ||
545 | |||
546 | struct locomo_save_data { | ||
547 | u16 LCM_GPO; | ||
548 | u16 LCM_SPICT; | ||
549 | u16 LCM_GPE; | ||
550 | u16 LCM_ASD; | ||
551 | u16 LCM_SPIMD; | ||
552 | }; | ||
553 | |||
554 | static int locomo_suspend(struct device *dev, u32 pm_message_t, u32 level) | ||
555 | { | ||
556 | struct locomo *lchip = dev_get_drvdata(dev); | ||
557 | struct locomo_save_data *save; | ||
558 | unsigned long flags; | ||
559 | |||
560 | if (level != SUSPEND_DISABLE) | ||
561 | return 0; | ||
562 | |||
563 | save = kmalloc(sizeof(struct locomo_save_data), GFP_KERNEL); | ||
564 | if (!save) | ||
565 | return -ENOMEM; | ||
566 | |||
567 | dev->power.saved_state = (void *) save; | ||
568 | |||
569 | spin_lock_irqsave(&lchip->lock, flags); | ||
570 | |||
571 | save->LCM_GPO = locomo_readl(lchip->base + LOCOMO_GPO); /* GPIO */ | ||
572 | locomo_writel(0x00, lchip->base + LOCOMO_GPO); | ||
573 | save->LCM_SPICT = locomo_readl(lchip->base + LOCOMO_SPICT); /* SPI */ | ||
574 | locomo_writel(0x40, lchip->base + LOCOMO_SPICT); | ||
575 | save->LCM_GPE = locomo_readl(lchip->base + LOCOMO_GPE); /* GPIO */ | ||
576 | locomo_writel(0x00, lchip->base + LOCOMO_GPE); | ||
577 | save->LCM_ASD = locomo_readl(lchip->base + LOCOMO_ASD); /* ADSTART */ | ||
578 | locomo_writel(0x00, lchip->base + LOCOMO_ASD); | ||
579 | save->LCM_SPIMD = locomo_readl(lchip->base + LOCOMO_SPIMD); /* SPI */ | ||
580 | locomo_writel(0x3C14, lchip->base + LOCOMO_SPIMD); | ||
581 | |||
582 | locomo_writel(0x00, lchip->base + LOCOMO_PAIF); | ||
583 | locomo_writel(0x00, lchip->base + LOCOMO_DAC); | ||
584 | locomo_writel(0x00, lchip->base + LOCOMO_BACKLIGHT + LOCOMO_TC); | ||
585 | |||
586 | if ( (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT0) & 0x88) && (locomo_readl(lchip->base + LOCOMO_LED + LOCOMO_LPT1) & 0x88) ) | ||
587 | locomo_writel(0x00, lchip->base + LOCOMO_C32K); /* CLK32 off */ | ||
588 | else | ||
589 | /* 18MHz already enabled, so no wait */ | ||
590 | locomo_writel(0xc1, lchip->base + LOCOMO_C32K); /* CLK32 on */ | ||
591 | |||
592 | locomo_writel(0x00, lchip->base + LOCOMO_TADC); /* 18MHz clock off*/ | ||
593 | locomo_writel(0x00, lchip->base + LOCOMO_AUDIO + LOCOMO_ACC); /* 22MHz/24MHz clock off */ | ||
594 | locomo_writel(0x00, lchip->base + LOCOMO_FRONTLIGHT + LOCOMO_ALS); /* FL */ | ||
595 | |||
596 | spin_unlock_irqrestore(&lchip->lock, flags); | ||
597 | |||
598 | return 0; | ||
599 | } | ||
600 | |||
601 | static int locomo_resume(struct device *dev, u32 level) | ||
602 | { | ||
603 | struct locomo *lchip = dev_get_drvdata(dev); | ||
604 | struct locomo_save_data *save; | ||
605 | unsigned long r; | ||
606 | unsigned long flags; | ||
607 | |||
608 | if (level != RESUME_ENABLE) | ||
609 | return 0; | ||
610 | |||
611 | save = (struct locomo_save_data *) dev->power.saved_state; | ||
612 | if (!save) | ||
613 | return 0; | ||
614 | |||
615 | spin_lock_irqsave(&lchip->lock, flags); | ||
616 | |||
617 | locomo_writel(save->LCM_GPO, lchip->base + LOCOMO_GPO); | ||
618 | locomo_writel(save->LCM_SPICT, lchip->base + LOCOMO_SPICT); | ||
619 | locomo_writel(save->LCM_GPE, lchip->base + LOCOMO_GPE); | ||
620 | locomo_writel(save->LCM_ASD, lchip->base + LOCOMO_ASD); | ||
621 | locomo_writel(save->LCM_SPIMD, lchip->base + LOCOMO_SPIMD); | ||
622 | |||
623 | locomo_writel(0x00, lchip->base + LOCOMO_C32K); | ||
624 | locomo_writel(0x90, lchip->base + LOCOMO_TADC); | ||
625 | |||
626 | locomo_writel(0, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KSC); | ||
627 | r = locomo_readl(lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
628 | r &= 0xFEFF; | ||
629 | locomo_writel(r, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KIC); | ||
630 | locomo_writel(0x1, lchip->base + LOCOMO_KEYBOARD + LOCOMO_KCMD); | ||
631 | |||
632 | spin_unlock_irqrestore(&lchip->lock, flags); | ||
633 | |||
634 | dev->power.saved_state = NULL; | ||
635 | kfree(save); | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | #endif | ||
640 | |||
544 | /** | 641 | /** |
545 | * locomo_probe - probe for a single LoCoMo chip. | 642 | * locomo_probe - probe for a single LoCoMo chip. |
546 | * @phys_addr: physical address of device. | 643 | * @phys_addr: physical address of device. |
@@ -707,6 +804,10 @@ static struct device_driver locomo_device_driver = { | |||
707 | .bus = &platform_bus_type, | 804 | .bus = &platform_bus_type, |
708 | .probe = locomo_probe, | 805 | .probe = locomo_probe, |
709 | .remove = locomo_remove, | 806 | .remove = locomo_remove, |
807 | #ifdef CONFIG_PM | ||
808 | .suspend = locomo_suspend, | ||
809 | .resume = locomo_resume, | ||
810 | #endif | ||
710 | }; | 811 | }; |
711 | 812 | ||
712 | /* | 813 | /* |
diff --git a/arch/arm/configs/s3c2410_defconfig b/arch/arm/configs/s3c2410_defconfig index 96a794d8de84..756348bf5170 100644 --- a/arch/arm/configs/s3c2410_defconfig +++ b/arch/arm/configs/s3c2410_defconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | # | 1 | # |
2 | # Automatically generated make config: don't edit | 2 | # Automatically generated make config: don't edit |
3 | # Linux kernel version: 2.6.12-git4 | 3 | # Linux kernel version: 2.6.13-git8 |
4 | # Wed Jun 22 15:56:42 2005 | 4 | # Thu Sep 8 19:24:02 2005 |
5 | # | 5 | # |
6 | CONFIG_ARM=y | 6 | CONFIG_ARM=y |
7 | CONFIG_MMU=y | 7 | CONFIG_MMU=y |
@@ -22,6 +22,7 @@ CONFIG_INIT_ENV_ARG_LIMIT=32 | |||
22 | # General setup | 22 | # General setup |
23 | # | 23 | # |
24 | CONFIG_LOCALVERSION="" | 24 | CONFIG_LOCALVERSION="" |
25 | CONFIG_LOCALVERSION_AUTO=y | ||
25 | CONFIG_SWAP=y | 26 | CONFIG_SWAP=y |
26 | CONFIG_SYSVIPC=y | 27 | CONFIG_SYSVIPC=y |
27 | # CONFIG_POSIX_MQUEUE is not set | 28 | # CONFIG_POSIX_MQUEUE is not set |
@@ -31,6 +32,7 @@ CONFIG_SYSCTL=y | |||
31 | # CONFIG_HOTPLUG is not set | 32 | # CONFIG_HOTPLUG is not set |
32 | CONFIG_KOBJECT_UEVENT=y | 33 | CONFIG_KOBJECT_UEVENT=y |
33 | # CONFIG_IKCONFIG is not set | 34 | # CONFIG_IKCONFIG is not set |
35 | CONFIG_INITRAMFS_SOURCE="" | ||
34 | # CONFIG_EMBEDDED is not set | 36 | # CONFIG_EMBEDDED is not set |
35 | CONFIG_KALLSYMS=y | 37 | CONFIG_KALLSYMS=y |
36 | # CONFIG_KALLSYMS_ALL is not set | 38 | # CONFIG_KALLSYMS_ALL is not set |
@@ -88,7 +90,9 @@ CONFIG_ARCH_S3C2410=y | |||
88 | # | 90 | # |
89 | # S3C24XX Implementations | 91 | # S3C24XX Implementations |
90 | # | 92 | # |
93 | CONFIG_MACH_ANUBIS=y | ||
91 | CONFIG_ARCH_BAST=y | 94 | CONFIG_ARCH_BAST=y |
95 | CONFIG_BAST_PC104_IRQ=y | ||
92 | CONFIG_ARCH_H1940=y | 96 | CONFIG_ARCH_H1940=y |
93 | CONFIG_MACH_N30=y | 97 | CONFIG_MACH_N30=y |
94 | CONFIG_ARCH_SMDK2410=y | 98 | CONFIG_ARCH_SMDK2410=y |
@@ -112,6 +116,7 @@ CONFIG_S3C2410_DMA=y | |||
112 | # CONFIG_S3C2410_DMA_DEBUG is not set | 116 | # CONFIG_S3C2410_DMA_DEBUG is not set |
113 | # CONFIG_S3C2410_PM_DEBUG is not set | 117 | # CONFIG_S3C2410_PM_DEBUG is not set |
114 | # CONFIG_S3C2410_PM_CHECK is not set | 118 | # CONFIG_S3C2410_PM_CHECK is not set |
119 | CONFIG_PM_SIMTEC=y | ||
115 | CONFIG_S3C2410_LOWLEVEL_UART_PORT=0 | 120 | CONFIG_S3C2410_LOWLEVEL_UART_PORT=0 |
116 | 121 | ||
117 | # | 122 | # |
@@ -149,7 +154,15 @@ CONFIG_ISA_DMA_API=y | |||
149 | # | 154 | # |
150 | # CONFIG_SMP is not set | 155 | # CONFIG_SMP is not set |
151 | # CONFIG_PREEMPT is not set | 156 | # CONFIG_PREEMPT is not set |
152 | # CONFIG_DISCONTIGMEM is not set | 157 | # CONFIG_NO_IDLE_HZ is not set |
158 | # CONFIG_ARCH_DISCONTIGMEM_ENABLE is not set | ||
159 | CONFIG_SELECT_MEMORY_MODEL=y | ||
160 | CONFIG_FLATMEM_MANUAL=y | ||
161 | # CONFIG_DISCONTIGMEM_MANUAL is not set | ||
162 | # CONFIG_SPARSEMEM_MANUAL is not set | ||
163 | CONFIG_FLATMEM=y | ||
164 | CONFIG_FLAT_NODE_MEM_MAP=y | ||
165 | # CONFIG_SPARSEMEM_STATIC is not set | ||
153 | CONFIG_ALIGNMENT_TRAP=y | 166 | CONFIG_ALIGNMENT_TRAP=y |
154 | 167 | ||
155 | # | 168 | # |
@@ -186,6 +199,74 @@ CONFIG_PM=y | |||
186 | CONFIG_APM=y | 199 | CONFIG_APM=y |
187 | 200 | ||
188 | # | 201 | # |
202 | # Networking | ||
203 | # | ||
204 | CONFIG_NET=y | ||
205 | |||
206 | # | ||
207 | # Networking options | ||
208 | # | ||
209 | # CONFIG_PACKET is not set | ||
210 | CONFIG_UNIX=y | ||
211 | # CONFIG_NET_KEY is not set | ||
212 | CONFIG_INET=y | ||
213 | # CONFIG_IP_MULTICAST is not set | ||
214 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
215 | CONFIG_IP_FIB_HASH=y | ||
216 | CONFIG_IP_PNP=y | ||
217 | # CONFIG_IP_PNP_DHCP is not set | ||
218 | CONFIG_IP_PNP_BOOTP=y | ||
219 | # CONFIG_IP_PNP_RARP is not set | ||
220 | # CONFIG_NET_IPIP is not set | ||
221 | # CONFIG_NET_IPGRE is not set | ||
222 | # CONFIG_ARPD is not set | ||
223 | # CONFIG_SYN_COOKIES is not set | ||
224 | # CONFIG_INET_AH is not set | ||
225 | # CONFIG_INET_ESP is not set | ||
226 | # CONFIG_INET_IPCOMP is not set | ||
227 | # CONFIG_INET_TUNNEL is not set | ||
228 | CONFIG_INET_DIAG=y | ||
229 | CONFIG_INET_TCP_DIAG=y | ||
230 | # CONFIG_TCP_CONG_ADVANCED is not set | ||
231 | CONFIG_TCP_CONG_BIC=y | ||
232 | # CONFIG_IPV6 is not set | ||
233 | # CONFIG_NETFILTER is not set | ||
234 | |||
235 | # | ||
236 | # DCCP Configuration (EXPERIMENTAL) | ||
237 | # | ||
238 | # CONFIG_IP_DCCP is not set | ||
239 | |||
240 | # | ||
241 | # SCTP Configuration (EXPERIMENTAL) | ||
242 | # | ||
243 | # CONFIG_IP_SCTP is not set | ||
244 | # CONFIG_ATM is not set | ||
245 | # CONFIG_BRIDGE is not set | ||
246 | # CONFIG_VLAN_8021Q is not set | ||
247 | # CONFIG_DECNET is not set | ||
248 | # CONFIG_LLC2 is not set | ||
249 | # CONFIG_IPX is not set | ||
250 | # CONFIG_ATALK is not set | ||
251 | # CONFIG_X25 is not set | ||
252 | # CONFIG_LAPB is not set | ||
253 | # CONFIG_NET_DIVERT is not set | ||
254 | # CONFIG_ECONET is not set | ||
255 | # CONFIG_WAN_ROUTER is not set | ||
256 | # CONFIG_NET_SCHED is not set | ||
257 | # CONFIG_NET_CLS_ROUTE is not set | ||
258 | |||
259 | # | ||
260 | # Network testing | ||
261 | # | ||
262 | # CONFIG_NET_PKTGEN is not set | ||
263 | # CONFIG_NETFILTER_NETLINK is not set | ||
264 | # CONFIG_HAMRADIO is not set | ||
265 | # CONFIG_IRDA is not set | ||
266 | # CONFIG_BT is not set | ||
267 | # CONFIG_IEEE80211 is not set | ||
268 | |||
269 | # | ||
189 | # Device Drivers | 270 | # Device Drivers |
190 | # | 271 | # |
191 | 272 | ||
@@ -258,6 +339,7 @@ CONFIG_MTD_ROM=y | |||
258 | # CONFIG_MTD_IMPA7 is not set | 339 | # CONFIG_MTD_IMPA7 is not set |
259 | CONFIG_MTD_BAST=y | 340 | CONFIG_MTD_BAST=y |
260 | CONFIG_MTD_BAST_MAXSIZE=4 | 341 | CONFIG_MTD_BAST_MAXSIZE=4 |
342 | # CONFIG_MTD_PLATRAM is not set | ||
261 | 343 | ||
262 | # | 344 | # |
263 | # Self-contained MTD device drivers | 345 | # Self-contained MTD device drivers |
@@ -312,7 +394,6 @@ CONFIG_BLK_DEV_RAM=y | |||
312 | CONFIG_BLK_DEV_RAM_COUNT=16 | 394 | CONFIG_BLK_DEV_RAM_COUNT=16 |
313 | CONFIG_BLK_DEV_RAM_SIZE=4096 | 395 | CONFIG_BLK_DEV_RAM_SIZE=4096 |
314 | CONFIG_BLK_DEV_INITRD=y | 396 | CONFIG_BLK_DEV_INITRD=y |
315 | CONFIG_INITRAMFS_SOURCE="" | ||
316 | # CONFIG_CDROM_PKTCDVD is not set | 397 | # CONFIG_CDROM_PKTCDVD is not set |
317 | 398 | ||
318 | # | 399 | # |
@@ -354,6 +435,7 @@ CONFIG_BLK_DEV_IDE_BAST=y | |||
354 | # | 435 | # |
355 | # SCSI device support | 436 | # SCSI device support |
356 | # | 437 | # |
438 | # CONFIG_RAID_ATTRS is not set | ||
357 | # CONFIG_SCSI is not set | 439 | # CONFIG_SCSI is not set |
358 | 440 | ||
359 | # | 441 | # |
@@ -376,70 +458,8 @@ CONFIG_BLK_DEV_IDE_BAST=y | |||
376 | # | 458 | # |
377 | 459 | ||
378 | # | 460 | # |
379 | # Networking support | 461 | # Network device support |
380 | # | ||
381 | CONFIG_NET=y | ||
382 | |||
383 | # | ||
384 | # Networking options | ||
385 | # | 462 | # |
386 | # CONFIG_PACKET is not set | ||
387 | CONFIG_UNIX=y | ||
388 | # CONFIG_NET_KEY is not set | ||
389 | CONFIG_INET=y | ||
390 | CONFIG_IP_FIB_HASH=y | ||
391 | # CONFIG_IP_FIB_TRIE is not set | ||
392 | # CONFIG_IP_MULTICAST is not set | ||
393 | # CONFIG_IP_ADVANCED_ROUTER is not set | ||
394 | CONFIG_IP_PNP=y | ||
395 | # CONFIG_IP_PNP_DHCP is not set | ||
396 | CONFIG_IP_PNP_BOOTP=y | ||
397 | # CONFIG_IP_PNP_RARP is not set | ||
398 | # CONFIG_NET_IPIP is not set | ||
399 | # CONFIG_NET_IPGRE is not set | ||
400 | # CONFIG_ARPD is not set | ||
401 | # CONFIG_SYN_COOKIES is not set | ||
402 | # CONFIG_INET_AH is not set | ||
403 | # CONFIG_INET_ESP is not set | ||
404 | # CONFIG_INET_IPCOMP is not set | ||
405 | # CONFIG_INET_TUNNEL is not set | ||
406 | CONFIG_IP_TCPDIAG=y | ||
407 | # CONFIG_IP_TCPDIAG_IPV6 is not set | ||
408 | # CONFIG_IPV6 is not set | ||
409 | # CONFIG_NETFILTER is not set | ||
410 | |||
411 | # | ||
412 | # SCTP Configuration (EXPERIMENTAL) | ||
413 | # | ||
414 | # CONFIG_IP_SCTP is not set | ||
415 | # CONFIG_ATM is not set | ||
416 | # CONFIG_BRIDGE is not set | ||
417 | # CONFIG_VLAN_8021Q is not set | ||
418 | # CONFIG_DECNET is not set | ||
419 | # CONFIG_LLC2 is not set | ||
420 | # CONFIG_IPX is not set | ||
421 | # CONFIG_ATALK is not set | ||
422 | # CONFIG_X25 is not set | ||
423 | # CONFIG_LAPB is not set | ||
424 | # CONFIG_NET_DIVERT is not set | ||
425 | # CONFIG_ECONET is not set | ||
426 | # CONFIG_WAN_ROUTER is not set | ||
427 | |||
428 | # | ||
429 | # QoS and/or fair queueing | ||
430 | # | ||
431 | # CONFIG_NET_SCHED is not set | ||
432 | # CONFIG_NET_CLS_ROUTE is not set | ||
433 | |||
434 | # | ||
435 | # Network testing | ||
436 | # | ||
437 | # CONFIG_NET_PKTGEN is not set | ||
438 | # CONFIG_NETPOLL is not set | ||
439 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
440 | # CONFIG_HAMRADIO is not set | ||
441 | # CONFIG_IRDA is not set | ||
442 | # CONFIG_BT is not set | ||
443 | CONFIG_NETDEVICES=y | 463 | CONFIG_NETDEVICES=y |
444 | # CONFIG_DUMMY is not set | 464 | # CONFIG_DUMMY is not set |
445 | # CONFIG_BONDING is not set | 465 | # CONFIG_BONDING is not set |
@@ -447,6 +467,11 @@ CONFIG_NETDEVICES=y | |||
447 | # CONFIG_TUN is not set | 467 | # CONFIG_TUN is not set |
448 | 468 | ||
449 | # | 469 | # |
470 | # PHY device support | ||
471 | # | ||
472 | # CONFIG_PHYLIB is not set | ||
473 | |||
474 | # | ||
450 | # Ethernet (10 or 100Mbit) | 475 | # Ethernet (10 or 100Mbit) |
451 | # | 476 | # |
452 | CONFIG_NET_ETHERNET=y | 477 | CONFIG_NET_ETHERNET=y |
@@ -480,6 +505,8 @@ CONFIG_DM9000=m | |||
480 | # CONFIG_SLIP is not set | 505 | # CONFIG_SLIP is not set |
481 | # CONFIG_SHAPER is not set | 506 | # CONFIG_SHAPER is not set |
482 | # CONFIG_NETCONSOLE is not set | 507 | # CONFIG_NETCONSOLE is not set |
508 | # CONFIG_NETPOLL is not set | ||
509 | # CONFIG_NET_POLL_CONTROLLER is not set | ||
483 | 510 | ||
484 | # | 511 | # |
485 | # ISDN subsystem | 512 | # ISDN subsystem |
@@ -562,7 +589,6 @@ CONFIG_SERIAL_8250_EXTENDED=y | |||
562 | CONFIG_SERIAL_8250_MANY_PORTS=y | 589 | CONFIG_SERIAL_8250_MANY_PORTS=y |
563 | CONFIG_SERIAL_8250_SHARE_IRQ=y | 590 | CONFIG_SERIAL_8250_SHARE_IRQ=y |
564 | # CONFIG_SERIAL_8250_DETECT_IRQ is not set | 591 | # CONFIG_SERIAL_8250_DETECT_IRQ is not set |
565 | # CONFIG_SERIAL_8250_MULTIPORT is not set | ||
566 | # CONFIG_SERIAL_8250_RSA is not set | 592 | # CONFIG_SERIAL_8250_RSA is not set |
567 | 593 | ||
568 | # | 594 | # |
@@ -605,7 +631,6 @@ CONFIG_S3C2410_RTC=y | |||
605 | # | 631 | # |
606 | # Ftape, the floppy tape device driver | 632 | # Ftape, the floppy tape device driver |
607 | # | 633 | # |
608 | # CONFIG_DRM is not set | ||
609 | # CONFIG_RAW_DRIVER is not set | 634 | # CONFIG_RAW_DRIVER is not set |
610 | 635 | ||
611 | # | 636 | # |
@@ -628,7 +653,7 @@ CONFIG_I2C_ALGOBIT=m | |||
628 | # | 653 | # |
629 | # I2C Hardware Bus support | 654 | # I2C Hardware Bus support |
630 | # | 655 | # |
631 | # CONFIG_I2C_ISA is not set | 656 | CONFIG_I2C_ISA=m |
632 | # CONFIG_I2C_PARPORT is not set | 657 | # CONFIG_I2C_PARPORT is not set |
633 | # CONFIG_I2C_PARPORT_LIGHT is not set | 658 | # CONFIG_I2C_PARPORT_LIGHT is not set |
634 | CONFIG_I2C_S3C2410=y | 659 | CONFIG_I2C_S3C2410=y |
@@ -636,14 +661,33 @@ CONFIG_I2C_S3C2410=y | |||
636 | # CONFIG_I2C_PCA_ISA is not set | 661 | # CONFIG_I2C_PCA_ISA is not set |
637 | 662 | ||
638 | # | 663 | # |
639 | # Hardware Sensors Chip support | 664 | # Miscellaneous I2C Chip support |
640 | # | 665 | # |
641 | CONFIG_I2C_SENSOR=m | 666 | # CONFIG_SENSORS_DS1337 is not set |
667 | # CONFIG_SENSORS_DS1374 is not set | ||
668 | CONFIG_SENSORS_EEPROM=m | ||
669 | # CONFIG_SENSORS_PCF8574 is not set | ||
670 | # CONFIG_SENSORS_PCA9539 is not set | ||
671 | # CONFIG_SENSORS_PCF8591 is not set | ||
672 | # CONFIG_SENSORS_RTC8564 is not set | ||
673 | # CONFIG_SENSORS_MAX6875 is not set | ||
674 | # CONFIG_I2C_DEBUG_CORE is not set | ||
675 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
676 | # CONFIG_I2C_DEBUG_BUS is not set | ||
677 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
678 | |||
679 | # | ||
680 | # Hardware Monitoring support | ||
681 | # | ||
682 | CONFIG_HWMON=y | ||
683 | CONFIG_HWMON_VID=m | ||
642 | # CONFIG_SENSORS_ADM1021 is not set | 684 | # CONFIG_SENSORS_ADM1021 is not set |
643 | # CONFIG_SENSORS_ADM1025 is not set | 685 | # CONFIG_SENSORS_ADM1025 is not set |
644 | # CONFIG_SENSORS_ADM1026 is not set | 686 | # CONFIG_SENSORS_ADM1026 is not set |
645 | # CONFIG_SENSORS_ADM1031 is not set | 687 | # CONFIG_SENSORS_ADM1031 is not set |
688 | # CONFIG_SENSORS_ADM9240 is not set | ||
646 | # CONFIG_SENSORS_ASB100 is not set | 689 | # CONFIG_SENSORS_ASB100 is not set |
690 | # CONFIG_SENSORS_ATXP1 is not set | ||
647 | # CONFIG_SENSORS_DS1621 is not set | 691 | # CONFIG_SENSORS_DS1621 is not set |
648 | # CONFIG_SENSORS_FSCHER is not set | 692 | # CONFIG_SENSORS_FSCHER is not set |
649 | # CONFIG_SENSORS_FSCPOS is not set | 693 | # CONFIG_SENSORS_FSCPOS is not set |
@@ -662,27 +706,21 @@ CONFIG_SENSORS_LM85=m | |||
662 | # CONFIG_SENSORS_LM92 is not set | 706 | # CONFIG_SENSORS_LM92 is not set |
663 | # CONFIG_SENSORS_MAX1619 is not set | 707 | # CONFIG_SENSORS_MAX1619 is not set |
664 | # CONFIG_SENSORS_PC87360 is not set | 708 | # CONFIG_SENSORS_PC87360 is not set |
665 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
666 | # CONFIG_SENSORS_SMSC47M1 is not set | 709 | # CONFIG_SENSORS_SMSC47M1 is not set |
710 | # CONFIG_SENSORS_SMSC47B397 is not set | ||
667 | # CONFIG_SENSORS_W83781D is not set | 711 | # CONFIG_SENSORS_W83781D is not set |
712 | # CONFIG_SENSORS_W83792D is not set | ||
668 | # CONFIG_SENSORS_W83L785TS is not set | 713 | # CONFIG_SENSORS_W83L785TS is not set |
669 | # CONFIG_SENSORS_W83627HF is not set | 714 | # CONFIG_SENSORS_W83627HF is not set |
715 | # CONFIG_SENSORS_W83627EHF is not set | ||
716 | # CONFIG_HWMON_DEBUG_CHIP is not set | ||
670 | 717 | ||
671 | # | 718 | # |
672 | # Other I2C Chip support | 719 | # Misc devices |
673 | # | 720 | # |
674 | # CONFIG_SENSORS_DS1337 is not set | ||
675 | CONFIG_SENSORS_EEPROM=m | ||
676 | # CONFIG_SENSORS_PCF8574 is not set | ||
677 | # CONFIG_SENSORS_PCF8591 is not set | ||
678 | # CONFIG_SENSORS_RTC8564 is not set | ||
679 | # CONFIG_I2C_DEBUG_CORE is not set | ||
680 | # CONFIG_I2C_DEBUG_ALGO is not set | ||
681 | # CONFIG_I2C_DEBUG_BUS is not set | ||
682 | # CONFIG_I2C_DEBUG_CHIP is not set | ||
683 | 721 | ||
684 | # | 722 | # |
685 | # Misc devices | 723 | # Multimedia Capabilities Port drivers |
686 | # | 724 | # |
687 | 725 | ||
688 | # | 726 | # |
@@ -731,7 +769,7 @@ CONFIG_DUMMY_CONSOLE=y | |||
731 | # USB support | 769 | # USB support |
732 | # | 770 | # |
733 | CONFIG_USB_ARCH_HAS_HCD=y | 771 | CONFIG_USB_ARCH_HAS_HCD=y |
734 | # CONFIG_USB_ARCH_HAS_OHCI is not set | 772 | CONFIG_USB_ARCH_HAS_OHCI=y |
735 | # CONFIG_USB is not set | 773 | # CONFIG_USB is not set |
736 | 774 | ||
737 | # | 775 | # |
@@ -749,6 +787,7 @@ CONFIG_USB_ARCH_HAS_HCD=y | |||
749 | # | 787 | # |
750 | CONFIG_EXT2_FS=y | 788 | CONFIG_EXT2_FS=y |
751 | # CONFIG_EXT2_FS_XATTR is not set | 789 | # CONFIG_EXT2_FS_XATTR is not set |
790 | # CONFIG_EXT2_FS_XIP is not set | ||
752 | CONFIG_EXT3_FS=y | 791 | CONFIG_EXT3_FS=y |
753 | CONFIG_EXT3_FS_XATTR=y | 792 | CONFIG_EXT3_FS_XATTR=y |
754 | # CONFIG_EXT3_FS_POSIX_ACL is not set | 793 | # CONFIG_EXT3_FS_POSIX_ACL is not set |
@@ -758,6 +797,7 @@ CONFIG_JBD=y | |||
758 | CONFIG_FS_MBCACHE=y | 797 | CONFIG_FS_MBCACHE=y |
759 | # CONFIG_REISERFS_FS is not set | 798 | # CONFIG_REISERFS_FS is not set |
760 | # CONFIG_JFS_FS is not set | 799 | # CONFIG_JFS_FS is not set |
800 | # CONFIG_FS_POSIX_ACL is not set | ||
761 | 801 | ||
762 | # | 802 | # |
763 | # XFS support | 803 | # XFS support |
@@ -765,6 +805,7 @@ CONFIG_FS_MBCACHE=y | |||
765 | # CONFIG_XFS_FS is not set | 805 | # CONFIG_XFS_FS is not set |
766 | # CONFIG_MINIX_FS is not set | 806 | # CONFIG_MINIX_FS is not set |
767 | CONFIG_ROMFS_FS=y | 807 | CONFIG_ROMFS_FS=y |
808 | CONFIG_INOTIFY=y | ||
768 | # CONFIG_QUOTA is not set | 809 | # CONFIG_QUOTA is not set |
769 | CONFIG_DNOTIFY=y | 810 | CONFIG_DNOTIFY=y |
770 | # CONFIG_AUTOFS_FS is not set | 811 | # CONFIG_AUTOFS_FS is not set |
@@ -791,11 +832,11 @@ CONFIG_FAT_DEFAULT_IOCHARSET="iso8859-1" | |||
791 | # | 832 | # |
792 | CONFIG_PROC_FS=y | 833 | CONFIG_PROC_FS=y |
793 | CONFIG_SYSFS=y | 834 | CONFIG_SYSFS=y |
794 | # CONFIG_DEVPTS_FS_XATTR is not set | ||
795 | # CONFIG_TMPFS is not set | 835 | # CONFIG_TMPFS is not set |
796 | # CONFIG_HUGETLBFS is not set | 836 | # CONFIG_HUGETLBFS is not set |
797 | # CONFIG_HUGETLB_PAGE is not set | 837 | # CONFIG_HUGETLB_PAGE is not set |
798 | CONFIG_RAMFS=y | 838 | CONFIG_RAMFS=y |
839 | # CONFIG_RELAYFS_FS is not set | ||
799 | 840 | ||
800 | # | 841 | # |
801 | # Miscellaneous filesystems | 842 | # Miscellaneous filesystems |
@@ -812,8 +853,7 @@ CONFIG_JFFS_FS_VERBOSE=0 | |||
812 | # CONFIG_JFFS_PROC_FS is not set | 853 | # CONFIG_JFFS_PROC_FS is not set |
813 | CONFIG_JFFS2_FS=y | 854 | CONFIG_JFFS2_FS=y |
814 | CONFIG_JFFS2_FS_DEBUG=0 | 855 | CONFIG_JFFS2_FS_DEBUG=0 |
815 | # CONFIG_JFFS2_FS_NAND is not set | 856 | CONFIG_JFFS2_FS_WRITEBUFFER=y |
816 | # CONFIG_JFFS2_FS_NOR_ECC is not set | ||
817 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set | 857 | # CONFIG_JFFS2_COMPRESSION_OPTIONS is not set |
818 | CONFIG_JFFS2_ZLIB=y | 858 | CONFIG_JFFS2_ZLIB=y |
819 | CONFIG_JFFS2_RTIME=y | 859 | CONFIG_JFFS2_RTIME=y |
@@ -835,6 +875,7 @@ CONFIG_NFS_FS=y | |||
835 | # CONFIG_NFSD is not set | 875 | # CONFIG_NFSD is not set |
836 | CONFIG_ROOT_NFS=y | 876 | CONFIG_ROOT_NFS=y |
837 | CONFIG_LOCKD=y | 877 | CONFIG_LOCKD=y |
878 | CONFIG_NFS_COMMON=y | ||
838 | CONFIG_SUNRPC=y | 879 | CONFIG_SUNRPC=y |
839 | # CONFIG_RPCSEC_GSS_KRB5 is not set | 880 | # CONFIG_RPCSEC_GSS_KRB5 is not set |
840 | # CONFIG_RPCSEC_GSS_SPKM3 is not set | 881 | # CONFIG_RPCSEC_GSS_SPKM3 is not set |
@@ -920,6 +961,7 @@ CONFIG_NLS_DEFAULT="iso8859-1" | |||
920 | CONFIG_DEBUG_KERNEL=y | 961 | CONFIG_DEBUG_KERNEL=y |
921 | # CONFIG_MAGIC_SYSRQ is not set | 962 | # CONFIG_MAGIC_SYSRQ is not set |
922 | CONFIG_LOG_BUF_SHIFT=16 | 963 | CONFIG_LOG_BUF_SHIFT=16 |
964 | CONFIG_DETECT_SOFTLOCKUP=y | ||
923 | # CONFIG_SCHEDSTATS is not set | 965 | # CONFIG_SCHEDSTATS is not set |
924 | # CONFIG_DEBUG_SLAB is not set | 966 | # CONFIG_DEBUG_SLAB is not set |
925 | # CONFIG_DEBUG_SPINLOCK is not set | 967 | # CONFIG_DEBUG_SPINLOCK is not set |
diff --git a/arch/arm/mach-clps7500/core.c b/arch/arm/mach-clps7500/core.c index 112f1d68fb2b..e216ab8b9e8f 100644 --- a/arch/arm/mach-clps7500/core.c +++ b/arch/arm/mach-clps7500/core.c | |||
@@ -354,7 +354,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
354 | 354 | ||
355 | static struct platform_device serial_device = { | 355 | static struct platform_device serial_device = { |
356 | .name = "serial8250", | 356 | .name = "serial8250", |
357 | .id = 0, | 357 | .id = PLAT8250_DEV_PLATFORM, |
358 | .dev = { | 358 | .dev = { |
359 | .platform_data = serial_platform_data, | 359 | .platform_data = serial_platform_data, |
360 | }, | 360 | }, |
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c index 23c4da10101b..5aeadfd72143 100644 --- a/arch/arm/mach-ebsa110/core.c +++ b/arch/arm/mach-ebsa110/core.c | |||
@@ -219,7 +219,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
219 | 219 | ||
220 | static struct platform_device serial_device = { | 220 | static struct platform_device serial_device = { |
221 | .name = "serial8250", | 221 | .name = "serial8250", |
222 | .id = 0, | 222 | .id = PLAT8250_DEV_PLATFORM, |
223 | .dev = { | 223 | .dev = { |
224 | .platform_data = serial_platform_data, | 224 | .platform_data = serial_platform_data, |
225 | }, | 225 | }, |
diff --git a/arch/arm/mach-epxa10db/arch.c b/arch/arm/mach-epxa10db/arch.c index 7daa021676d0..44c56571d183 100644 --- a/arch/arm/mach-epxa10db/arch.c +++ b/arch/arm/mach-epxa10db/arch.c | |||
@@ -52,7 +52,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
52 | 52 | ||
53 | static struct platform_device serial_device = { | 53 | static struct platform_device serial_device = { |
54 | .name = "serial8250", | 54 | .name = "serial8250", |
55 | .id = 0, | 55 | .id = PLAT8250_DEV_PLATFORM, |
56 | .dev = { | 56 | .dev = { |
57 | .platform_data = serial_platform_data, | 57 | .platform_data = serial_platform_data, |
58 | }, | 58 | }, |
diff --git a/arch/arm/mach-footbridge/isa.c b/arch/arm/mach-footbridge/isa.c index aa3a1fef563e..28846c7edaaf 100644 --- a/arch/arm/mach-footbridge/isa.c +++ b/arch/arm/mach-footbridge/isa.c | |||
@@ -34,7 +34,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
34 | 34 | ||
35 | static struct platform_device serial_device = { | 35 | static struct platform_device serial_device = { |
36 | .name = "serial8250", | 36 | .name = "serial8250", |
37 | .id = 0, | 37 | .id = PLAT8250_DEV_PLATFORM, |
38 | .dev = { | 38 | .dev = { |
39 | .platform_data = serial_platform_data, | 39 | .platform_data = serial_platform_data, |
40 | }, | 40 | }, |
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c index 4b3199319e68..a4a7c0125d03 100644 --- a/arch/arm/mach-h720x/cpu-h7202.c +++ b/arch/arm/mach-h720x/cpu-h7202.c | |||
@@ -90,7 +90,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
90 | 90 | ||
91 | static struct platform_device serial_device = { | 91 | static struct platform_device serial_device = { |
92 | .name = "serial8250", | 92 | .name = "serial8250", |
93 | .id = 0, | 93 | .id = PLAT8250_DEV_PLATFORM, |
94 | .dev = { | 94 | .dev = { |
95 | .platform_data = serial_platform_data, | 95 | .platform_data = serial_platform_data, |
96 | }, | 96 | }, |
diff --git a/arch/arm/mach-ixp2000/core.c b/arch/arm/mach-ixp2000/core.c index 098c817a7fb8..74bd2fd602d4 100644 --- a/arch/arm/mach-ixp2000/core.c +++ b/arch/arm/mach-ixp2000/core.c | |||
@@ -174,7 +174,7 @@ static struct resource ixp2000_uart_resource = { | |||
174 | 174 | ||
175 | static struct platform_device ixp2000_serial_device = { | 175 | static struct platform_device ixp2000_serial_device = { |
176 | .name = "serial8250", | 176 | .name = "serial8250", |
177 | .id = 0, | 177 | .id = PLAT8250_DEV_PLATFORM, |
178 | .dev = { | 178 | .dev = { |
179 | .platform_data = ixp2000_serial_port, | 179 | .platform_data = ixp2000_serial_port, |
180 | }, | 180 | }, |
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c index 8b2f25322452..050c92768913 100644 --- a/arch/arm/mach-ixp4xx/coyote-setup.c +++ b/arch/arm/mach-ixp4xx/coyote-setup.c | |||
@@ -66,7 +66,7 @@ static struct plat_serial8250_port coyote_uart_data[] = { | |||
66 | 66 | ||
67 | static struct platform_device coyote_uart = { | 67 | static struct platform_device coyote_uart = { |
68 | .name = "serial8250", | 68 | .name = "serial8250", |
69 | .id = 0, | 69 | .id = PLAT8250_DEV_PLATFORM, |
70 | .dev = { | 70 | .dev = { |
71 | .platform_data = coyote_uart_data, | 71 | .platform_data = coyote_uart_data, |
72 | }, | 72 | }, |
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c index 3fd92c5cbaa8..29a6d02fa851 100644 --- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c +++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c | |||
@@ -93,7 +93,7 @@ static struct plat_serial8250_port gtwx5715_uart_platform_data[] = { | |||
93 | 93 | ||
94 | static struct platform_device gtwx5715_uart_device = { | 94 | static struct platform_device gtwx5715_uart_device = { |
95 | .name = "serial8250", | 95 | .name = "serial8250", |
96 | .id = 0, | 96 | .id = PLAT8250_DEV_PLATFORM, |
97 | .dev = { | 97 | .dev = { |
98 | .platform_data = gtwx5715_uart_platform_data, | 98 | .platform_data = gtwx5715_uart_platform_data, |
99 | }, | 99 | }, |
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c index 6c14ff3c23a0..ae1fa099d5fa 100644 --- a/arch/arm/mach-ixp4xx/ixdp425-setup.c +++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c | |||
@@ -96,7 +96,7 @@ static struct plat_serial8250_port ixdp425_uart_data[] = { | |||
96 | 96 | ||
97 | static struct platform_device ixdp425_uart = { | 97 | static struct platform_device ixdp425_uart = { |
98 | .name = "serial8250", | 98 | .name = "serial8250", |
99 | .id = 0, | 99 | .id = PLAT8250_DEV_PLATFORM, |
100 | .dev.platform_data = ixdp425_uart_data, | 100 | .dev.platform_data = ixdp425_uart_data, |
101 | .num_resources = 2, | 101 | .num_resources = 2, |
102 | .resource = ixdp425_uart_resources | 102 | .resource = ixdp425_uart_resources |
diff --git a/arch/arm/mach-omap1/Kconfig b/arch/arm/mach-omap1/Kconfig index 7408ac94f771..27fc2e8e5fca 100644 --- a/arch/arm/mach-omap1/Kconfig +++ b/arch/arm/mach-omap1/Kconfig | |||
@@ -47,6 +47,14 @@ config MACH_OMAP_OSK | |||
47 | TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here | 47 | TI OMAP 5912 OSK (OMAP Starter Kit) board support. Say Y here |
48 | if you have such a board. | 48 | if you have such a board. |
49 | 49 | ||
50 | config OMAP_OSK_MISTRAL | ||
51 | bool "Mistral QVGA board Support" | ||
52 | depends on MACH_OMAP_OSK | ||
53 | help | ||
54 | The OSK supports an optional add-on board with a Quarter-VGA | ||
55 | touchscreen, PDA-ish buttons, a resume button, bicolor LED, | ||
56 | and camera connector. Say Y here if you have this board. | ||
57 | |||
50 | config MACH_OMAP_PERSEUS2 | 58 | config MACH_OMAP_PERSEUS2 |
51 | bool "TI Perseus2" | 59 | bool "TI Perseus2" |
52 | depends on ARCH_OMAP1 && ARCH_OMAP730 | 60 | depends on ARCH_OMAP1 && ARCH_OMAP730 |
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile index d386fd913f0c..181a93deaaee 100644 --- a/arch/arm/mach-omap1/Makefile +++ b/arch/arm/mach-omap1/Makefile | |||
@@ -3,7 +3,7 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | # Common support | 5 | # Common support |
6 | obj-y := io.o id.o irq.o time.o serial.o | 6 | obj-y := io.o id.o irq.o time.o serial.o devices.o |
7 | led-y := leds.o | 7 | led-y := leds.o |
8 | 8 | ||
9 | # Specific board support | 9 | # Specific board support |
@@ -23,6 +23,7 @@ endif | |||
23 | 23 | ||
24 | # LEDs support | 24 | # LEDs support |
25 | led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o | 25 | led-$(CONFIG_MACH_OMAP_H2) += leds-h2p2-debug.o |
26 | led-$(CONFIG_MACH_OMAP_H3) += leds-h2p2-debug.o | ||
26 | led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o | 27 | led-$(CONFIG_MACH_OMAP_INNOVATOR) += leds-innovator.o |
27 | led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o | 28 | led-$(CONFIG_MACH_OMAP_PERSEUS2) += leds-h2p2-debug.o |
28 | led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o | 29 | led-$(CONFIG_MACH_OMAP_OSK) += leds-osk.o |
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c index 122796ebe8f5..c209c7172a9a 100644 --- a/arch/arm/mach-omap1/board-generic.c +++ b/arch/arm/mach-omap1/board-generic.c | |||
@@ -48,19 +48,43 @@ static struct omap_usb_config generic1510_usb_config __initdata = { | |||
48 | 48 | ||
49 | #if defined(CONFIG_ARCH_OMAP16XX) | 49 | #if defined(CONFIG_ARCH_OMAP16XX) |
50 | static struct omap_usb_config generic1610_usb_config __initdata = { | 50 | static struct omap_usb_config generic1610_usb_config __initdata = { |
51 | #ifdef CONFIG_USB_OTG | ||
52 | .otg = 1, | ||
53 | #endif | ||
51 | .register_host = 1, | 54 | .register_host = 1, |
52 | .register_dev = 1, | 55 | .register_dev = 1, |
53 | .hmc_mode = 16, | 56 | .hmc_mode = 16, |
54 | .pins[0] = 6, | 57 | .pins[0] = 6, |
55 | }; | 58 | }; |
59 | |||
60 | static struct omap_mmc_config generic_mmc_config __initdata = { | ||
61 | .mmc [0] = { | ||
62 | .enabled = 0, | ||
63 | .wire4 = 0, | ||
64 | .wp_pin = -1, | ||
65 | .power_pin = -1, | ||
66 | .switch_pin = -1, | ||
67 | }, | ||
68 | .mmc [1] = { | ||
69 | .enabled = 0, | ||
70 | .wire4 = 0, | ||
71 | .wp_pin = -1, | ||
72 | .power_pin = -1, | ||
73 | .switch_pin = -1, | ||
74 | }, | ||
75 | }; | ||
76 | |||
56 | #endif | 77 | #endif |
57 | 78 | ||
58 | static struct omap_board_config_kernel generic_config[] = { | 79 | static struct omap_board_config_kernel generic_config[] = { |
59 | { OMAP_TAG_USB, NULL }, | 80 | { OMAP_TAG_USB, NULL }, |
81 | { OMAP_TAG_MMC, &generic_mmc_config }, | ||
60 | }; | 82 | }; |
61 | 83 | ||
62 | static void __init omap_generic_init(void) | 84 | static void __init omap_generic_init(void) |
63 | { | 85 | { |
86 | const struct omap_uart_config *uart_conf; | ||
87 | |||
64 | /* | 88 | /* |
65 | * Make sure the serial ports are muxed on at this point. | 89 | * Make sure the serial ports are muxed on at this point. |
66 | * You have to mux them off in device drivers later on | 90 | * You have to mux them off in device drivers later on |
@@ -76,6 +100,18 @@ static void __init omap_generic_init(void) | |||
76 | generic_config[0].data = &generic1610_usb_config; | 100 | generic_config[0].data = &generic1610_usb_config; |
77 | } | 101 | } |
78 | #endif | 102 | #endif |
103 | |||
104 | uart_conf = omap_get_config(OMAP_TAG_UART, struct omap_uart_config); | ||
105 | if (uart_conf != NULL) { | ||
106 | unsigned int enabled_ports, i; | ||
107 | |||
108 | enabled_ports = uart_conf->enabled_uarts; | ||
109 | for (i = 0; i < 3; i++) { | ||
110 | if (!(enabled_ports & (1 << i))) | ||
111 | generic_serial_ports[i] = 0; | ||
112 | } | ||
113 | } | ||
114 | |||
79 | omap_board_config = generic_config; | 115 | omap_board_config = generic_config; |
80 | omap_board_config_size = ARRAY_SIZE(generic_config); | 116 | omap_board_config_size = ARRAY_SIZE(generic_config); |
81 | omap_serial_init(generic_serial_ports); | 117 | omap_serial_init(generic_serial_ports); |
@@ -83,7 +119,7 @@ static void __init omap_generic_init(void) | |||
83 | 119 | ||
84 | static void __init omap_generic_map_io(void) | 120 | static void __init omap_generic_map_io(void) |
85 | { | 121 | { |
86 | omap_map_common_io() | 122 | omap_map_common_io(); |
87 | } | 123 | } |
88 | 124 | ||
89 | MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") | 125 | MACHINE_START(OMAP_GENERIC, "Generic OMAP1510/1610/1710") |
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c index f4983ee95ab4..d46a70063b0c 100644 --- a/arch/arm/mach-omap1/board-h2.c +++ b/arch/arm/mach-omap1/board-h2.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <asm/mach/map.h> | 33 | #include <asm/mach/map.h> |
34 | 34 | ||
35 | #include <asm/arch/gpio.h> | 35 | #include <asm/arch/gpio.h> |
36 | #include <asm/arch/mux.h> | ||
36 | #include <asm/arch/tc.h> | 37 | #include <asm/arch/tc.h> |
37 | #include <asm/arch/usb.h> | 38 | #include <asm/arch/usb.h> |
38 | #include <asm/arch/common.h> | 39 | #include <asm/arch/common.h> |
@@ -80,8 +81,7 @@ static struct flash_platform_data h2_flash_data = { | |||
80 | }; | 81 | }; |
81 | 82 | ||
82 | static struct resource h2_flash_resource = { | 83 | static struct resource h2_flash_resource = { |
83 | .start = OMAP_CS2B_PHYS, | 84 | /* This is on CS3, wherever it's mapped */ |
84 | .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1, | ||
85 | .flags = IORESOURCE_MEM, | 85 | .flags = IORESOURCE_MEM, |
86 | }; | 86 | }; |
87 | 87 | ||
@@ -126,10 +126,9 @@ static void __init h2_init_smc91x(void) | |||
126 | printk("Error requesting gpio 0 for smc91x irq\n"); | 126 | printk("Error requesting gpio 0 for smc91x irq\n"); |
127 | return; | 127 | return; |
128 | } | 128 | } |
129 | omap_set_gpio_edge_ctrl(0, OMAP_GPIO_FALLING_EDGE); | ||
130 | } | 129 | } |
131 | 130 | ||
132 | void h2_init_irq(void) | 131 | static void __init h2_init_irq(void) |
133 | { | 132 | { |
134 | omap_init_irq(); | 133 | omap_init_irq(); |
135 | omap_gpio_init(); | 134 | omap_gpio_init(); |
@@ -152,9 +151,13 @@ static struct omap_usb_config h2_usb_config __initdata = { | |||
152 | }; | 151 | }; |
153 | 152 | ||
154 | static struct omap_mmc_config h2_mmc_config __initdata = { | 153 | static struct omap_mmc_config h2_mmc_config __initdata = { |
155 | .mmc_blocks = 1, | 154 | .mmc [0] = { |
156 | .mmc1_power_pin = -1, /* tps65010 gpio3 */ | 155 | .enabled = 1, |
157 | .mmc1_switch_pin = OMAP_MPUIO(1), | 156 | .wire4 = 1, |
157 | .wp_pin = OMAP_MPUIO(3), | ||
158 | .power_pin = -1, /* tps65010 gpio3 */ | ||
159 | .switch_pin = OMAP_MPUIO(1), | ||
160 | }, | ||
158 | }; | 161 | }; |
159 | 162 | ||
160 | static struct omap_board_config_kernel h2_config[] = { | 163 | static struct omap_board_config_kernel h2_config[] = { |
@@ -164,6 +167,16 @@ static struct omap_board_config_kernel h2_config[] = { | |||
164 | 167 | ||
165 | static void __init h2_init(void) | 168 | static void __init h2_init(void) |
166 | { | 169 | { |
170 | /* NOTE: revC boards support NAND-boot, which can put NOR on CS2B | ||
171 | * and NAND (either 16bit or 8bit) on CS3. | ||
172 | */ | ||
173 | h2_flash_resource.end = h2_flash_resource.start = omap_cs3_phys(); | ||
174 | h2_flash_resource.end += SZ_32M - 1; | ||
175 | |||
176 | /* MMC: card detect and WP */ | ||
177 | // omap_cfg_reg(U19_ARMIO1); /* CD */ | ||
178 | omap_cfg_reg(BALLOUT_V8_ARMIO3); /* WP */ | ||
179 | |||
167 | platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); | 180 | platform_add_devices(h2_devices, ARRAY_SIZE(h2_devices)); |
168 | omap_board_config = h2_config; | 181 | omap_board_config = h2_config; |
169 | omap_board_config_size = ARRAY_SIZE(h2_config); | 182 | omap_board_config_size = ARRAY_SIZE(h2_config); |
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c index 7cd419d61b40..2798613696fa 100644 --- a/arch/arm/mach-omap1/board-h3.c +++ b/arch/arm/mach-omap1/board-h3.c | |||
@@ -82,8 +82,7 @@ static struct flash_platform_data h3_flash_data = { | |||
82 | }; | 82 | }; |
83 | 83 | ||
84 | static struct resource h3_flash_resource = { | 84 | static struct resource h3_flash_resource = { |
85 | .start = OMAP_CS2B_PHYS, | 85 | /* This is on CS3, wherever it's mapped */ |
86 | .end = OMAP_CS2B_PHYS + OMAP_CS2B_SIZE - 1, | ||
87 | .flags = IORESOURCE_MEM, | 86 | .flags = IORESOURCE_MEM, |
88 | }; | 87 | }; |
89 | 88 | ||
@@ -161,13 +160,26 @@ static struct omap_usb_config h3_usb_config __initdata = { | |||
161 | .pins[1] = 3, | 160 | .pins[1] = 3, |
162 | }; | 161 | }; |
163 | 162 | ||
163 | static struct omap_mmc_config h3_mmc_config __initdata = { | ||
164 | .mmc[0] = { | ||
165 | .enabled = 1, | ||
166 | .power_pin = -1, /* tps65010 GPIO4 */ | ||
167 | .switch_pin = OMAP_MPUIO(1), | ||
168 | }, | ||
169 | }; | ||
170 | |||
164 | static struct omap_board_config_kernel h3_config[] = { | 171 | static struct omap_board_config_kernel h3_config[] = { |
165 | { OMAP_TAG_USB, &h3_usb_config }, | 172 | { OMAP_TAG_USB, &h3_usb_config }, |
173 | { OMAP_TAG_MMC, &h3_mmc_config }, | ||
166 | }; | 174 | }; |
167 | 175 | ||
168 | static void __init h3_init(void) | 176 | static void __init h3_init(void) |
169 | { | 177 | { |
178 | h3_flash_resource.end = h3_flash_resource.start = omap_cs3_phys(); | ||
179 | h3_flash_resource.end += OMAP_CS3_SIZE - 1; | ||
170 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); | 180 | (void) platform_add_devices(devices, ARRAY_SIZE(devices)); |
181 | omap_board_config = h3_config; | ||
182 | omap_board_config_size = ARRAY_SIZE(h3_config); | ||
171 | } | 183 | } |
172 | 184 | ||
173 | static void __init h3_init_smc91x(void) | 185 | static void __init h3_init_smc91x(void) |
@@ -177,7 +189,6 @@ static void __init h3_init_smc91x(void) | |||
177 | printk("Error requesting gpio 40 for smc91x irq\n"); | 189 | printk("Error requesting gpio 40 for smc91x irq\n"); |
178 | return; | 190 | return; |
179 | } | 191 | } |
180 | omap_set_gpio_edge_ctrl(40, OMAP_GPIO_FALLING_EDGE); | ||
181 | } | 192 | } |
182 | 193 | ||
183 | void h3_init_irq(void) | 194 | void h3_init_irq(void) |
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c index 91de60a91ef8..df0312b596e4 100644 --- a/arch/arm/mach-omap1/board-innovator.c +++ b/arch/arm/mach-omap1/board-innovator.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <asm/mach/flash.h> | 29 | #include <asm/mach/flash.h> |
30 | #include <asm/mach/map.h> | 30 | #include <asm/mach/map.h> |
31 | 31 | ||
32 | #include <asm/arch/mux.h> | ||
32 | #include <asm/arch/fpga.h> | 33 | #include <asm/arch/fpga.h> |
33 | #include <asm/arch/gpio.h> | 34 | #include <asm/arch/gpio.h> |
34 | #include <asm/arch/tc.h> | 35 | #include <asm/arch/tc.h> |
@@ -173,7 +174,6 @@ static void __init innovator_init_smc91x(void) | |||
173 | printk("Error requesting gpio 0 for smc91x irq\n"); | 174 | printk("Error requesting gpio 0 for smc91x irq\n"); |
174 | return; | 175 | return; |
175 | } | 176 | } |
176 | omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE); | ||
177 | } | 177 | } |
178 | } | 178 | } |
179 | 179 | ||
@@ -220,8 +220,19 @@ static struct omap_usb_config h2_usb_config __initdata = { | |||
220 | }; | 220 | }; |
221 | #endif | 221 | #endif |
222 | 222 | ||
223 | static struct omap_mmc_config innovator_mmc_config __initdata = { | ||
224 | .mmc [0] = { | ||
225 | .enabled = 1, | ||
226 | .wire4 = 1, | ||
227 | .wp_pin = OMAP_MPUIO(3), | ||
228 | .power_pin = -1, /* FPGA F3 UIO42 */ | ||
229 | .switch_pin = -1, /* FPGA F4 UIO43 */ | ||
230 | }, | ||
231 | }; | ||
232 | |||
223 | static struct omap_board_config_kernel innovator_config[] = { | 233 | static struct omap_board_config_kernel innovator_config[] = { |
224 | { OMAP_TAG_USB, NULL }, | 234 | { OMAP_TAG_USB, NULL }, |
235 | { OMAP_TAG_MMC, &innovator_mmc_config }, | ||
225 | }; | 236 | }; |
226 | 237 | ||
227 | static void __init innovator_init(void) | 238 | static void __init innovator_init(void) |
diff --git a/arch/arm/mach-omap1/board-netstar.c b/arch/arm/mach-omap1/board-netstar.c index 6750b2014092..d904e643f5ec 100644 --- a/arch/arm/mach-omap1/board-netstar.c +++ b/arch/arm/mach-omap1/board-netstar.c | |||
@@ -75,16 +75,15 @@ static void __init netstar_init(void) | |||
75 | mdelay(50); /* 50ms until PHY ready */ | 75 | mdelay(50); /* 50ms until PHY ready */ |
76 | /* smc91x interrupt pin */ | 76 | /* smc91x interrupt pin */ |
77 | omap_request_gpio(8); | 77 | omap_request_gpio(8); |
78 | omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE); | ||
79 | 78 | ||
80 | omap_request_gpio(12); | 79 | omap_request_gpio(12); |
81 | omap_request_gpio(13); | 80 | omap_request_gpio(13); |
82 | omap_request_gpio(14); | 81 | omap_request_gpio(14); |
83 | omap_request_gpio(15); | 82 | omap_request_gpio(15); |
84 | omap_set_gpio_edge_ctrl(12, OMAP_GPIO_FALLING_EDGE); | 83 | set_irq_type(OMAP_GPIO_IRQ(12), IRQT_FALLING); |
85 | omap_set_gpio_edge_ctrl(13, OMAP_GPIO_FALLING_EDGE); | 84 | set_irq_type(OMAP_GPIO_IRQ(13), IRQT_FALLING); |
86 | omap_set_gpio_edge_ctrl(14, OMAP_GPIO_FALLING_EDGE); | 85 | set_irq_type(OMAP_GPIO_IRQ(14), IRQT_FALLING); |
87 | omap_set_gpio_edge_ctrl(15, OMAP_GPIO_FALLING_EDGE); | 86 | set_irq_type(OMAP_GPIO_IRQ(15), IRQT_FALLING); |
88 | 87 | ||
89 | platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices)); | 88 | platform_add_devices(netstar_devices, ARRAY_SIZE(netstar_devices)); |
90 | 89 | ||
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c index 6844e536c698..21103df50415 100644 --- a/arch/arm/mach-omap1/board-osk.c +++ b/arch/arm/mach-omap1/board-osk.c | |||
@@ -29,11 +29,16 @@ | |||
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/device.h> | 31 | #include <linux/device.h> |
32 | #include <linux/interrupt.h> | ||
33 | |||
34 | #include <linux/mtd/mtd.h> | ||
35 | #include <linux/mtd/partitions.h> | ||
32 | 36 | ||
33 | #include <asm/hardware.h> | 37 | #include <asm/hardware.h> |
34 | #include <asm/mach-types.h> | 38 | #include <asm/mach-types.h> |
35 | #include <asm/mach/arch.h> | 39 | #include <asm/mach/arch.h> |
36 | #include <asm/mach/map.h> | 40 | #include <asm/mach/map.h> |
41 | #include <asm/mach/flash.h> | ||
37 | 42 | ||
38 | #include <asm/arch/gpio.h> | 43 | #include <asm/arch/gpio.h> |
39 | #include <asm/arch/usb.h> | 44 | #include <asm/arch/usb.h> |
@@ -41,12 +46,56 @@ | |||
41 | #include <asm/arch/tc.h> | 46 | #include <asm/arch/tc.h> |
42 | #include <asm/arch/common.h> | 47 | #include <asm/arch/common.h> |
43 | 48 | ||
44 | static struct map_desc osk5912_io_desc[] __initdata = { | 49 | static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0}; |
45 | { OMAP_OSK_NOR_FLASH_BASE, OMAP_OSK_NOR_FLASH_START, OMAP_OSK_NOR_FLASH_SIZE, | 50 | |
46 | MT_DEVICE }, | 51 | static struct mtd_partition osk_partitions[] = { |
52 | /* bootloader (U-Boot, etc) in first sector */ | ||
53 | { | ||
54 | .name = "bootloader", | ||
55 | .offset = 0, | ||
56 | .size = SZ_128K, | ||
57 | .mask_flags = MTD_WRITEABLE, /* force read-only */ | ||
58 | }, | ||
59 | /* bootloader params in the next sector */ | ||
60 | { | ||
61 | .name = "params", | ||
62 | .offset = MTDPART_OFS_APPEND, | ||
63 | .size = SZ_128K, | ||
64 | .mask_flags = 0, | ||
65 | }, { | ||
66 | .name = "kernel", | ||
67 | .offset = MTDPART_OFS_APPEND, | ||
68 | .size = SZ_2M, | ||
69 | .mask_flags = 0 | ||
70 | }, { | ||
71 | .name = "filesystem", | ||
72 | .offset = MTDPART_OFS_APPEND, | ||
73 | .size = MTDPART_SIZ_FULL, | ||
74 | .mask_flags = 0 | ||
75 | } | ||
47 | }; | 76 | }; |
48 | 77 | ||
49 | static int __initdata osk_serial_ports[OMAP_MAX_NR_PORTS] = {1, 0, 0}; | 78 | static struct flash_platform_data osk_flash_data = { |
79 | .map_name = "cfi_probe", | ||
80 | .width = 2, | ||
81 | .parts = osk_partitions, | ||
82 | .nr_parts = ARRAY_SIZE(osk_partitions), | ||
83 | }; | ||
84 | |||
85 | static struct resource osk_flash_resource = { | ||
86 | /* this is on CS3, wherever it's mapped */ | ||
87 | .flags = IORESOURCE_MEM, | ||
88 | }; | ||
89 | |||
90 | static struct platform_device osk5912_flash_device = { | ||
91 | .name = "omapflash", | ||
92 | .id = 0, | ||
93 | .dev = { | ||
94 | .platform_data = &osk_flash_data, | ||
95 | }, | ||
96 | .num_resources = 1, | ||
97 | .resource = &osk_flash_resource, | ||
98 | }; | ||
50 | 99 | ||
51 | static struct resource osk5912_smc91x_resources[] = { | 100 | static struct resource osk5912_smc91x_resources[] = { |
52 | [0] = { | 101 | [0] = { |
@@ -86,9 +135,16 @@ static struct platform_device osk5912_cf_device = { | |||
86 | .resource = osk5912_cf_resources, | 135 | .resource = osk5912_cf_resources, |
87 | }; | 136 | }; |
88 | 137 | ||
138 | static struct platform_device osk5912_mcbsp1_device = { | ||
139 | .name = "omap_mcbsp", | ||
140 | .id = 1, | ||
141 | }; | ||
142 | |||
89 | static struct platform_device *osk5912_devices[] __initdata = { | 143 | static struct platform_device *osk5912_devices[] __initdata = { |
144 | &osk5912_flash_device, | ||
90 | &osk5912_smc91x_device, | 145 | &osk5912_smc91x_device, |
91 | &osk5912_cf_device, | 146 | &osk5912_cf_device, |
147 | &osk5912_mcbsp1_device, | ||
92 | }; | 148 | }; |
93 | 149 | ||
94 | static void __init osk_init_smc91x(void) | 150 | static void __init osk_init_smc91x(void) |
@@ -97,7 +153,6 @@ static void __init osk_init_smc91x(void) | |||
97 | printk("Error requesting gpio 0 for smc91x irq\n"); | 153 | printk("Error requesting gpio 0 for smc91x irq\n"); |
98 | return; | 154 | return; |
99 | } | 155 | } |
100 | omap_set_gpio_edge_ctrl(0, OMAP_GPIO_RISING_EDGE); | ||
101 | 156 | ||
102 | /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ | 157 | /* Check EMIFS wait states to fix errors with SMC_GET_PKT_HDR */ |
103 | EMIFS_CCS(1) |= 0x2; | 158 | EMIFS_CCS(1) |= 0x2; |
@@ -110,11 +165,11 @@ static void __init osk_init_cf(void) | |||
110 | printk("Error requesting gpio 62 for CF irq\n"); | 165 | printk("Error requesting gpio 62 for CF irq\n"); |
111 | return; | 166 | return; |
112 | } | 167 | } |
113 | /* it's really active-low */ | 168 | /* the CF I/O IRQ is really active-low */ |
114 | omap_set_gpio_edge_ctrl(62, OMAP_GPIO_FALLING_EDGE); | 169 | set_irq_type(OMAP_GPIO_IRQ(62), IRQT_FALLING); |
115 | } | 170 | } |
116 | 171 | ||
117 | void osk_init_irq(void) | 172 | static void __init osk_init_irq(void) |
118 | { | 173 | { |
119 | omap_init_irq(); | 174 | omap_init_irq(); |
120 | omap_gpio_init(); | 175 | omap_gpio_init(); |
@@ -142,18 +197,69 @@ static struct omap_board_config_kernel osk_config[] = { | |||
142 | { OMAP_TAG_USB, &osk_usb_config }, | 197 | { OMAP_TAG_USB, &osk_usb_config }, |
143 | }; | 198 | }; |
144 | 199 | ||
200 | #ifdef CONFIG_OMAP_OSK_MISTRAL | ||
201 | |||
202 | #ifdef CONFIG_PM | ||
203 | static irqreturn_t | ||
204 | osk_mistral_wake_interrupt(int irq, void *ignored, struct pt_regs *regs) | ||
205 | { | ||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | #endif | ||
209 | |||
210 | static void __init osk_mistral_init(void) | ||
211 | { | ||
212 | /* FIXME here's where to feed in framebuffer, touchpad, and | ||
213 | * keyboard setup ... not in the drivers for those devices! | ||
214 | * | ||
215 | * NOTE: we could actually tell if there's a Mistral board | ||
216 | * attached, e.g. by trying to read something from the ads7846. | ||
217 | * But this is too early for that... | ||
218 | */ | ||
219 | |||
220 | /* the sideways button (SW1) is for use as a "wakeup" button */ | ||
221 | omap_cfg_reg(N15_1610_MPUIO2); | ||
222 | if (omap_request_gpio(OMAP_MPUIO(2)) == 0) { | ||
223 | int ret = 0; | ||
224 | omap_set_gpio_direction(OMAP_MPUIO(2), 1); | ||
225 | set_irq_type(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), IRQT_RISING); | ||
226 | #ifdef CONFIG_PM | ||
227 | /* share the IRQ in case someone wants to use the | ||
228 | * button for more than wakeup from system sleep. | ||
229 | */ | ||
230 | ret = request_irq(OMAP_GPIO_IRQ(OMAP_MPUIO(2)), | ||
231 | &osk_mistral_wake_interrupt, | ||
232 | SA_SHIRQ, "mistral_wakeup", | ||
233 | &osk_mistral_wake_interrupt); | ||
234 | if (ret != 0) { | ||
235 | omap_free_gpio(OMAP_MPUIO(2)); | ||
236 | printk(KERN_ERR "OSK+Mistral: no wakeup irq, %d?\n", | ||
237 | ret); | ||
238 | } else | ||
239 | enable_irq_wake(OMAP_GPIO_IRQ(OMAP_MPUIO(2))); | ||
240 | #endif | ||
241 | } else | ||
242 | printk(KERN_ERR "OSK+Mistral: wakeup button is awol\n"); | ||
243 | } | ||
244 | #else | ||
245 | static void __init osk_mistral_init(void) { } | ||
246 | #endif | ||
247 | |||
145 | static void __init osk_init(void) | 248 | static void __init osk_init(void) |
146 | { | 249 | { |
250 | osk_flash_resource.end = osk_flash_resource.start = omap_cs3_phys(); | ||
251 | osk_flash_resource.end += SZ_32M - 1; | ||
147 | platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); | 252 | platform_add_devices(osk5912_devices, ARRAY_SIZE(osk5912_devices)); |
148 | omap_board_config = osk_config; | 253 | omap_board_config = osk_config; |
149 | omap_board_config_size = ARRAY_SIZE(osk_config); | 254 | omap_board_config_size = ARRAY_SIZE(osk_config); |
150 | USB_TRANSCEIVER_CTRL_REG |= (3 << 1); | 255 | USB_TRANSCEIVER_CTRL_REG |= (3 << 1); |
256 | |||
257 | osk_mistral_init(); | ||
151 | } | 258 | } |
152 | 259 | ||
153 | static void __init osk_map_io(void) | 260 | static void __init osk_map_io(void) |
154 | { | 261 | { |
155 | omap_map_common_io(); | 262 | omap_map_common_io(); |
156 | iotable_init(osk5912_io_desc, ARRAY_SIZE(osk5912_io_desc)); | ||
157 | omap_serial_init(osk_serial_ports); | 263 | omap_serial_init(osk_serial_ports); |
158 | } | 264 | } |
159 | 265 | ||
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c index 213317392d9b..107c68c8ab54 100644 --- a/arch/arm/mach-omap1/board-perseus2.c +++ b/arch/arm/mach-omap1/board-perseus2.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/mach/flash.h> | 24 | #include <asm/mach/flash.h> |
25 | #include <asm/mach/map.h> | 25 | #include <asm/mach/map.h> |
26 | 26 | ||
27 | #include <asm/arch/tc.h> | ||
27 | #include <asm/arch/gpio.h> | 28 | #include <asm/arch/gpio.h> |
28 | #include <asm/arch/mux.h> | 29 | #include <asm/arch/mux.h> |
29 | #include <asm/arch/fpga.h> | 30 | #include <asm/arch/fpga.h> |
@@ -83,8 +84,8 @@ static struct flash_platform_data p2_flash_data = { | |||
83 | }; | 84 | }; |
84 | 85 | ||
85 | static struct resource p2_flash_resource = { | 86 | static struct resource p2_flash_resource = { |
86 | .start = OMAP_FLASH_0_START, | 87 | .start = OMAP_CS0_PHYS, |
87 | .end = OMAP_FLASH_0_START + OMAP_FLASH_0_SIZE - 1, | 88 | .end = OMAP_CS0_PHYS + SZ_32M - 1, |
88 | .flags = IORESOURCE_MEM, | 89 | .flags = IORESOURCE_MEM, |
89 | }; | 90 | }; |
90 | 91 | ||
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c index e42281988990..bf30b1acda0b 100644 --- a/arch/arm/mach-omap1/board-voiceblue.c +++ b/arch/arm/mach-omap1/board-voiceblue.c | |||
@@ -25,13 +25,14 @@ | |||
25 | #include <asm/hardware.h> | 25 | #include <asm/hardware.h> |
26 | #include <asm/mach-types.h> | 26 | #include <asm/mach-types.h> |
27 | #include <asm/mach/arch.h> | 27 | #include <asm/mach/arch.h> |
28 | #include <asm/mach/flash.h> | ||
28 | #include <asm/mach/map.h> | 29 | #include <asm/mach/map.h> |
29 | 30 | ||
31 | #include <asm/arch/common.h> | ||
30 | #include <asm/arch/gpio.h> | 32 | #include <asm/arch/gpio.h> |
31 | #include <asm/arch/tc.h> | ||
32 | #include <asm/arch/mux.h> | 33 | #include <asm/arch/mux.h> |
34 | #include <asm/arch/tc.h> | ||
33 | #include <asm/arch/usb.h> | 35 | #include <asm/arch/usb.h> |
34 | #include <asm/arch/common.h> | ||
35 | 36 | ||
36 | extern void omap_init_time(void); | 37 | extern void omap_init_time(void); |
37 | extern int omap_gpio_init(void); | 38 | extern int omap_gpio_init(void); |
@@ -74,7 +75,7 @@ static struct plat_serial8250_port voiceblue_ports[] = { | |||
74 | 75 | ||
75 | static struct platform_device serial_device = { | 76 | static struct platform_device serial_device = { |
76 | .name = "serial8250", | 77 | .name = "serial8250", |
77 | .id = 1, | 78 | .id = PLAT8250_DEV_PLATFORM1, |
78 | .dev = { | 79 | .dev = { |
79 | .platform_data = voiceblue_ports, | 80 | .platform_data = voiceblue_ports, |
80 | }, | 81 | }, |
@@ -86,6 +87,27 @@ static int __init ext_uart_init(void) | |||
86 | } | 87 | } |
87 | arch_initcall(ext_uart_init); | 88 | arch_initcall(ext_uart_init); |
88 | 89 | ||
90 | static struct flash_platform_data voiceblue_flash_data = { | ||
91 | .map_name = "cfi_probe", | ||
92 | .width = 2, | ||
93 | }; | ||
94 | |||
95 | static struct resource voiceblue_flash_resource = { | ||
96 | .start = OMAP_CS0_PHYS, | ||
97 | .end = OMAP_CS0_PHYS + SZ_32M - 1, | ||
98 | .flags = IORESOURCE_MEM, | ||
99 | }; | ||
100 | |||
101 | static struct platform_device voiceblue_flash_device = { | ||
102 | .name = "omapflash", | ||
103 | .id = 0, | ||
104 | .dev = { | ||
105 | .platform_data = &voiceblue_flash_data, | ||
106 | }, | ||
107 | .num_resources = 1, | ||
108 | .resource = &voiceblue_flash_resource, | ||
109 | }; | ||
110 | |||
89 | static struct resource voiceblue_smc91x_resources[] = { | 111 | static struct resource voiceblue_smc91x_resources[] = { |
90 | [0] = { | 112 | [0] = { |
91 | .start = OMAP_CS2_PHYS + 0x300, | 113 | .start = OMAP_CS2_PHYS + 0x300, |
@@ -107,6 +129,7 @@ static struct platform_device voiceblue_smc91x_device = { | |||
107 | }; | 129 | }; |
108 | 130 | ||
109 | static struct platform_device *voiceblue_devices[] __initdata = { | 131 | static struct platform_device *voiceblue_devices[] __initdata = { |
132 | &voiceblue_flash_device, | ||
110 | &voiceblue_smc91x_device, | 133 | &voiceblue_smc91x_device, |
111 | }; | 134 | }; |
112 | 135 | ||
@@ -119,8 +142,17 @@ static struct omap_usb_config voiceblue_usb_config __initdata = { | |||
119 | .pins[2] = 6, | 142 | .pins[2] = 6, |
120 | }; | 143 | }; |
121 | 144 | ||
145 | static struct omap_mmc_config voiceblue_mmc_config __initdata = { | ||
146 | .mmc[0] = { | ||
147 | .enabled = 1, | ||
148 | .power_pin = 2, | ||
149 | .switch_pin = -1, | ||
150 | }, | ||
151 | }; | ||
152 | |||
122 | static struct omap_board_config_kernel voiceblue_config[] = { | 153 | static struct omap_board_config_kernel voiceblue_config[] = { |
123 | { OMAP_TAG_USB, &voiceblue_usb_config }, | 154 | { OMAP_TAG_USB, &voiceblue_usb_config }, |
155 | { OMAP_TAG_MMC, &voiceblue_mmc_config }, | ||
124 | }; | 156 | }; |
125 | 157 | ||
126 | static void __init voiceblue_init_irq(void) | 158 | static void __init voiceblue_init_irq(void) |
@@ -131,9 +163,6 @@ static void __init voiceblue_init_irq(void) | |||
131 | 163 | ||
132 | static void __init voiceblue_init(void) | 164 | static void __init voiceblue_init(void) |
133 | { | 165 | { |
134 | /* There is a good chance board is going up, so enable Power LED | ||
135 | * (it is connected through invertor) */ | ||
136 | omap_writeb(0x00, OMAP_LPG1_LCR); | ||
137 | /* Watchdog */ | 166 | /* Watchdog */ |
138 | omap_request_gpio(0); | 167 | omap_request_gpio(0); |
139 | /* smc91x reset */ | 168 | /* smc91x reset */ |
@@ -145,7 +174,6 @@ static void __init voiceblue_init(void) | |||
145 | mdelay(50); /* 50ms until PHY ready */ | 174 | mdelay(50); /* 50ms until PHY ready */ |
146 | /* smc91x interrupt pin */ | 175 | /* smc91x interrupt pin */ |
147 | omap_request_gpio(8); | 176 | omap_request_gpio(8); |
148 | omap_set_gpio_edge_ctrl(8, OMAP_GPIO_RISING_EDGE); | ||
149 | /* 16C554 reset*/ | 177 | /* 16C554 reset*/ |
150 | omap_request_gpio(6); | 178 | omap_request_gpio(6); |
151 | omap_set_gpio_direction(6, 0); | 179 | omap_set_gpio_direction(6, 0); |
@@ -155,14 +183,19 @@ static void __init voiceblue_init(void) | |||
155 | omap_request_gpio(13); | 183 | omap_request_gpio(13); |
156 | omap_request_gpio(14); | 184 | omap_request_gpio(14); |
157 | omap_request_gpio(15); | 185 | omap_request_gpio(15); |
158 | omap_set_gpio_edge_ctrl(12, OMAP_GPIO_RISING_EDGE); | 186 | set_irq_type(OMAP_GPIO_IRQ(12), IRQT_RISING); |
159 | omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE); | 187 | set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING); |
160 | omap_set_gpio_edge_ctrl(14, OMAP_GPIO_RISING_EDGE); | 188 | set_irq_type(OMAP_GPIO_IRQ(14), IRQT_RISING); |
161 | omap_set_gpio_edge_ctrl(15, OMAP_GPIO_RISING_EDGE); | 189 | set_irq_type(OMAP_GPIO_IRQ(15), IRQT_RISING); |
162 | 190 | ||
163 | platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices)); | 191 | platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices)); |
164 | omap_board_config = voiceblue_config; | 192 | omap_board_config = voiceblue_config; |
165 | omap_board_config_size = ARRAY_SIZE(voiceblue_config); | 193 | omap_board_config_size = ARRAY_SIZE(voiceblue_config); |
194 | |||
195 | /* There is a good chance board is going up, so enable power LED | ||
196 | * (it is connected through invertor) */ | ||
197 | omap_writeb(0x00, OMAP_LPG1_LCR); | ||
198 | omap_writeb(0x00, OMAP_LPG1_PMR); /* Disable clock */ | ||
166 | } | 199 | } |
167 | 200 | ||
168 | static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; | 201 | static int __initdata omap_serial_ports[OMAP_MAX_NR_PORTS] = {1, 1, 1}; |
@@ -184,9 +217,9 @@ static int panic_event(struct notifier_block *this, unsigned long event, | |||
184 | if (test_and_set_bit(MACHINE_PANICED, &machine_state)) | 217 | if (test_and_set_bit(MACHINE_PANICED, &machine_state)) |
185 | return NOTIFY_DONE; | 218 | return NOTIFY_DONE; |
186 | 219 | ||
187 | /* Flash Power LED | 220 | /* Flash power LED */ |
188 | * (TODO: Enable clock right way (enabled in bootloader already)) */ | ||
189 | omap_writeb(0x78, OMAP_LPG1_LCR); | 221 | omap_writeb(0x78, OMAP_LPG1_LCR); |
222 | omap_writeb(0x01, OMAP_LPG1_PMR); /* Enable clock */ | ||
190 | 223 | ||
191 | return NOTIFY_DONE; | 224 | return NOTIFY_DONE; |
192 | } | 225 | } |
@@ -195,15 +228,14 @@ static struct notifier_block panic_block = { | |||
195 | .notifier_call = panic_event, | 228 | .notifier_call = panic_event, |
196 | }; | 229 | }; |
197 | 230 | ||
198 | static int __init setup_notifier(void) | 231 | static int __init voiceblue_setup(void) |
199 | { | 232 | { |
200 | /* Setup panic notifier */ | 233 | /* Setup panic notifier */ |
201 | notifier_chain_register(&panic_notifier_list, &panic_block); | 234 | notifier_chain_register(&panic_notifier_list, &panic_block); |
202 | 235 | ||
203 | return 0; | 236 | return 0; |
204 | } | 237 | } |
205 | 238 | postcore_initcall(voiceblue_setup); | |
206 | postcore_initcall(setup_notifier); | ||
207 | 239 | ||
208 | static int wdt_gpio_state; | 240 | static int wdt_gpio_state; |
209 | 241 | ||
diff --git a/arch/arm/mach-omap1/devices.c b/arch/arm/mach-omap1/devices.c new file mode 100644 index 000000000000..e8b3981444cd --- /dev/null +++ b/arch/arm/mach-omap1/devices.c | |||
@@ -0,0 +1,351 @@ | |||
1 | /* | ||
2 | * linux/arch/arm/mach-omap1/devices.c | ||
3 | * | ||
4 | * OMAP1 platform device setup/initialization | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <linux/config.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/init.h> | ||
16 | #include <linux/device.h> | ||
17 | |||
18 | #include <asm/hardware.h> | ||
19 | #include <asm/io.h> | ||
20 | #include <asm/mach-types.h> | ||
21 | #include <asm/mach/map.h> | ||
22 | |||
23 | #include <asm/arch/tc.h> | ||
24 | #include <asm/arch/board.h> | ||
25 | #include <asm/arch/mux.h> | ||
26 | #include <asm/arch/gpio.h> | ||
27 | |||
28 | |||
29 | static void omap_nop_release(struct device *dev) | ||
30 | { | ||
31 | /* Nothing */ | ||
32 | } | ||
33 | |||
34 | /*-------------------------------------------------------------------------*/ | ||
35 | |||
36 | #if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE) | ||
37 | |||
38 | #define OMAP_I2C_BASE 0xfffb3800 | ||
39 | |||
40 | static struct resource i2c_resources[] = { | ||
41 | { | ||
42 | .start = OMAP_I2C_BASE, | ||
43 | .end = OMAP_I2C_BASE + 0x3f, | ||
44 | .flags = IORESOURCE_MEM, | ||
45 | }, | ||
46 | { | ||
47 | .start = INT_I2C, | ||
48 | .flags = IORESOURCE_IRQ, | ||
49 | }, | ||
50 | }; | ||
51 | |||
52 | /* DMA not used; works around erratum writing to non-empty i2c fifo */ | ||
53 | |||
54 | static struct platform_device omap_i2c_device = { | ||
55 | .name = "i2c_omap", | ||
56 | .id = -1, | ||
57 | .dev = { | ||
58 | .release = omap_nop_release, | ||
59 | }, | ||
60 | .num_resources = ARRAY_SIZE(i2c_resources), | ||
61 | .resource = i2c_resources, | ||
62 | }; | ||
63 | |||
64 | static void omap_init_i2c(void) | ||
65 | { | ||
66 | /* FIXME define and use a boot tag, in case of boards that | ||
67 | * either don't wire up I2C, or chips that mux it differently... | ||
68 | * it can include clocking and address info, maybe more. | ||
69 | */ | ||
70 | omap_cfg_reg(I2C_SCL); | ||
71 | omap_cfg_reg(I2C_SDA); | ||
72 | |||
73 | (void) platform_device_register(&omap_i2c_device); | ||
74 | } | ||
75 | #else | ||
76 | static inline void omap_init_i2c(void) {} | ||
77 | #endif | ||
78 | |||
79 | /*-------------------------------------------------------------------------*/ | ||
80 | |||
81 | #if defined(CONFIG_OMAP1610_IR) || defined(CONFIG_OMAP161O_IR_MODULE) | ||
82 | |||
83 | static u64 irda_dmamask = 0xffffffff; | ||
84 | |||
85 | static struct platform_device omap1610ir_device = { | ||
86 | .name = "omap1610-ir", | ||
87 | .id = -1, | ||
88 | .dev = { | ||
89 | .release = omap_nop_release, | ||
90 | .dma_mask = &irda_dmamask, | ||
91 | }, | ||
92 | }; | ||
93 | |||
94 | static void omap_init_irda(void) | ||
95 | { | ||
96 | /* FIXME define and use a boot tag, members something like: | ||
97 | * u8 uart; // uart1, or uart3 | ||
98 | * ... but driver only handles uart3 for now | ||
99 | * s16 fir_sel; // gpio for SIR vs FIR | ||
100 | * ... may prefer a callback for SIR/MIR/FIR mode select; | ||
101 | * while h2 uses a GPIO, H3 uses a gpio expander | ||
102 | */ | ||
103 | if (machine_is_omap_h2() | ||
104 | || machine_is_omap_h3()) | ||
105 | (void) platform_device_register(&omap1610ir_device); | ||
106 | } | ||
107 | #else | ||
108 | static inline void omap_init_irda(void) {} | ||
109 | #endif | ||
110 | |||
111 | /*-------------------------------------------------------------------------*/ | ||
112 | |||
113 | #if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) | ||
114 | |||
115 | #define OMAP_MMC1_BASE 0xfffb7800 | ||
116 | #define OMAP_MMC2_BASE 0xfffb7c00 /* omap16xx only */ | ||
117 | |||
118 | static struct omap_mmc_conf mmc1_conf; | ||
119 | |||
120 | static u64 mmc1_dmamask = 0xffffffff; | ||
121 | |||
122 | static struct resource mmc1_resources[] = { | ||
123 | { | ||
124 | .start = IO_ADDRESS(OMAP_MMC1_BASE), | ||
125 | .end = IO_ADDRESS(OMAP_MMC1_BASE) + 0x7f, | ||
126 | .flags = IORESOURCE_MEM, | ||
127 | }, | ||
128 | { | ||
129 | .start = INT_MMC, | ||
130 | .flags = IORESOURCE_IRQ, | ||
131 | }, | ||
132 | }; | ||
133 | |||
134 | static struct platform_device mmc_omap_device1 = { | ||
135 | .name = "mmci-omap", | ||
136 | .id = 1, | ||
137 | .dev = { | ||
138 | .release = omap_nop_release, | ||
139 | .dma_mask = &mmc1_dmamask, | ||
140 | .platform_data = &mmc1_conf, | ||
141 | }, | ||
142 | .num_resources = ARRAY_SIZE(mmc1_resources), | ||
143 | .resource = mmc1_resources, | ||
144 | }; | ||
145 | |||
146 | #ifdef CONFIG_ARCH_OMAP16XX | ||
147 | |||
148 | static struct omap_mmc_conf mmc2_conf; | ||
149 | |||
150 | static u64 mmc2_dmamask = 0xffffffff; | ||
151 | |||
152 | static struct resource mmc2_resources[] = { | ||
153 | { | ||
154 | .start = IO_ADDRESS(OMAP_MMC2_BASE), | ||
155 | .end = IO_ADDRESS(OMAP_MMC2_BASE) + 0x7f, | ||
156 | .flags = IORESOURCE_MEM, | ||
157 | }, | ||
158 | { | ||
159 | .start = INT_1610_MMC2, | ||
160 | .flags = IORESOURCE_IRQ, | ||
161 | }, | ||
162 | }; | ||
163 | |||
164 | static struct platform_device mmc_omap_device2 = { | ||
165 | .name = "mmci-omap", | ||
166 | .id = 2, | ||
167 | .dev = { | ||
168 | .release = omap_nop_release, | ||
169 | .dma_mask = &mmc2_dmamask, | ||
170 | .platform_data = &mmc2_conf, | ||
171 | }, | ||
172 | .num_resources = ARRAY_SIZE(mmc2_resources), | ||
173 | .resource = mmc2_resources, | ||
174 | }; | ||
175 | #endif | ||
176 | |||
177 | static void __init omap_init_mmc(void) | ||
178 | { | ||
179 | const struct omap_mmc_config *mmc_conf; | ||
180 | const struct omap_mmc_conf *mmc; | ||
181 | |||
182 | /* NOTE: assumes MMC was never (wrongly) enabled */ | ||
183 | mmc_conf = omap_get_config(OMAP_TAG_MMC, struct omap_mmc_config); | ||
184 | if (!mmc_conf) | ||
185 | return; | ||
186 | |||
187 | /* block 1 is always available and has just one pinout option */ | ||
188 | mmc = &mmc_conf->mmc[0]; | ||
189 | if (mmc->enabled) { | ||
190 | omap_cfg_reg(MMC_CMD); | ||
191 | omap_cfg_reg(MMC_CLK); | ||
192 | omap_cfg_reg(MMC_DAT0); | ||
193 | if (cpu_is_omap1710()) { | ||
194 | omap_cfg_reg(M15_1710_MMC_CLKI); | ||
195 | omap_cfg_reg(P19_1710_MMC_CMDDIR); | ||
196 | omap_cfg_reg(P20_1710_MMC_DATDIR0); | ||
197 | } | ||
198 | if (mmc->wire4) { | ||
199 | omap_cfg_reg(MMC_DAT1); | ||
200 | /* NOTE: DAT2 can be on W10 (here) or M15 */ | ||
201 | if (!mmc->nomux) | ||
202 | omap_cfg_reg(MMC_DAT2); | ||
203 | omap_cfg_reg(MMC_DAT3); | ||
204 | } | ||
205 | mmc1_conf = *mmc; | ||
206 | (void) platform_device_register(&mmc_omap_device1); | ||
207 | } | ||
208 | |||
209 | #ifdef CONFIG_ARCH_OMAP16XX | ||
210 | /* block 2 is on newer chips, and has many pinout options */ | ||
211 | mmc = &mmc_conf->mmc[1]; | ||
212 | if (mmc->enabled) { | ||
213 | if (!mmc->nomux) { | ||
214 | omap_cfg_reg(Y8_1610_MMC2_CMD); | ||
215 | omap_cfg_reg(Y10_1610_MMC2_CLK); | ||
216 | omap_cfg_reg(R18_1610_MMC2_CLKIN); | ||
217 | omap_cfg_reg(W8_1610_MMC2_DAT0); | ||
218 | if (mmc->wire4) { | ||
219 | omap_cfg_reg(V8_1610_MMC2_DAT1); | ||
220 | omap_cfg_reg(W15_1610_MMC2_DAT2); | ||
221 | omap_cfg_reg(R10_1610_MMC2_DAT3); | ||
222 | } | ||
223 | |||
224 | /* These are needed for the level shifter */ | ||
225 | omap_cfg_reg(V9_1610_MMC2_CMDDIR); | ||
226 | omap_cfg_reg(V5_1610_MMC2_DATDIR0); | ||
227 | omap_cfg_reg(W19_1610_MMC2_DATDIR1); | ||
228 | } | ||
229 | |||
230 | /* Feedback clock must be set on OMAP-1710 MMC2 */ | ||
231 | if (cpu_is_omap1710()) | ||
232 | omap_writel(omap_readl(MOD_CONF_CTRL_1) | (1 << 24), | ||
233 | MOD_CONF_CTRL_1); | ||
234 | mmc2_conf = *mmc; | ||
235 | (void) platform_device_register(&mmc_omap_device2); | ||
236 | } | ||
237 | #endif | ||
238 | return; | ||
239 | } | ||
240 | #else | ||
241 | static inline void omap_init_mmc(void) {} | ||
242 | #endif | ||
243 | |||
244 | #if defined(CONFIG_OMAP_RTC) || defined(CONFIG_OMAP_RTC) | ||
245 | |||
246 | #define OMAP_RTC_BASE 0xfffb4800 | ||
247 | |||
248 | static struct resource rtc_resources[] = { | ||
249 | { | ||
250 | .start = OMAP_RTC_BASE, | ||
251 | .end = OMAP_RTC_BASE + 0x5f, | ||
252 | .flags = IORESOURCE_MEM, | ||
253 | }, | ||
254 | { | ||
255 | .start = INT_RTC_TIMER, | ||
256 | .flags = IORESOURCE_IRQ, | ||
257 | }, | ||
258 | { | ||
259 | .start = INT_RTC_ALARM, | ||
260 | .flags = IORESOURCE_IRQ, | ||
261 | }, | ||
262 | }; | ||
263 | |||
264 | static struct platform_device omap_rtc_device = { | ||
265 | .name = "omap_rtc", | ||
266 | .id = -1, | ||
267 | .dev = { | ||
268 | .release = omap_nop_release, | ||
269 | }, | ||
270 | .num_resources = ARRAY_SIZE(rtc_resources), | ||
271 | .resource = rtc_resources, | ||
272 | }; | ||
273 | |||
274 | static void omap_init_rtc(void) | ||
275 | { | ||
276 | (void) platform_device_register(&omap_rtc_device); | ||
277 | } | ||
278 | #else | ||
279 | static inline void omap_init_rtc(void) {} | ||
280 | #endif | ||
281 | |||
282 | /*-------------------------------------------------------------------------*/ | ||
283 | |||
284 | #if defined(CONFIG_OMAP16XX_WATCHDOG) || defined(CONFIG_OMAP16XX_WATCHDOG_MODULE) | ||
285 | |||
286 | #define OMAP_WDT_BASE 0xfffeb000 | ||
287 | |||
288 | static struct resource wdt_resources[] = { | ||
289 | { | ||
290 | .start = OMAP_WDT_BASE, | ||
291 | .end = OMAP_WDT_BASE + 0x4f, | ||
292 | .flags = IORESOURCE_MEM, | ||
293 | }, | ||
294 | }; | ||
295 | |||
296 | static struct platform_device omap_wdt_device = { | ||
297 | .name = "omap1610_wdt", | ||
298 | .id = -1, | ||
299 | .dev = { | ||
300 | .release = omap_nop_release, | ||
301 | }, | ||
302 | .num_resources = ARRAY_SIZE(wdt_resources), | ||
303 | .resource = wdt_resources, | ||
304 | }; | ||
305 | |||
306 | static void omap_init_wdt(void) | ||
307 | { | ||
308 | (void) platform_device_register(&omap_wdt_device); | ||
309 | } | ||
310 | #else | ||
311 | static inline void omap_init_wdt(void) {} | ||
312 | #endif | ||
313 | |||
314 | |||
315 | /*-------------------------------------------------------------------------*/ | ||
316 | |||
317 | /* | ||
318 | * This gets called after board-specific INIT_MACHINE, and initializes most | ||
319 | * on-chip peripherals accessible on this board (except for few like USB): | ||
320 | * | ||
321 | * (a) Does any "standard config" pin muxing needed. Board-specific | ||
322 | * code will have muxed GPIO pins and done "nonstandard" setup; | ||
323 | * that code could live in the boot loader. | ||
324 | * (b) Populating board-specific platform_data with the data drivers | ||
325 | * rely on to handle wiring variations. | ||
326 | * (c) Creating platform devices as meaningful on this board and | ||
327 | * with this kernel configuration. | ||
328 | * | ||
329 | * Claiming GPIOs, and setting their direction and initial values, is the | ||
330 | * responsibility of the device drivers. So is responding to probe(). | ||
331 | * | ||
332 | * Board-specific knowlege like creating devices or pin setup is to be | ||
333 | * kept out of drivers as much as possible. In particular, pin setup | ||
334 | * may be handled by the boot loader, and drivers should expect it will | ||
335 | * normally have been done by the time they're probed. | ||
336 | */ | ||
337 | static int __init omap_init_devices(void) | ||
338 | { | ||
339 | /* please keep these calls, and their implementations above, | ||
340 | * in alphabetical order so they're easier to sort through. | ||
341 | */ | ||
342 | omap_init_i2c(); | ||
343 | omap_init_irda(); | ||
344 | omap_init_mmc(); | ||
345 | omap_init_rtc(); | ||
346 | omap_init_wdt(); | ||
347 | |||
348 | return 0; | ||
349 | } | ||
350 | arch_initcall(omap_init_devices); | ||
351 | |||
diff --git a/arch/arm/mach-omap1/fpga.c b/arch/arm/mach-omap1/fpga.c index c12a78335625..aca2a120813a 100644 --- a/arch/arm/mach-omap1/fpga.c +++ b/arch/arm/mach-omap1/fpga.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap/fpga.c | 2 | * linux/arch/arm/mach-omap1/fpga.c |
3 | * | 3 | * |
4 | * Interrupt handler for OMAP-1510 Innovator FPGA | 4 | * Interrupt handler for OMAP-1510 Innovator FPGA |
5 | * | 5 | * |
@@ -181,7 +181,7 @@ void omap1510_fpga_init_irq(void) | |||
181 | */ | 181 | */ |
182 | omap_request_gpio(13); | 182 | omap_request_gpio(13); |
183 | omap_set_gpio_direction(13, 1); | 183 | omap_set_gpio_direction(13, 1); |
184 | omap_set_gpio_edge_ctrl(13, OMAP_GPIO_RISING_EDGE); | 184 | set_irq_type(OMAP_GPIO_IRQ(13), IRQT_RISING); |
185 | set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux); | 185 | set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux); |
186 | } | 186 | } |
187 | 187 | ||
diff --git a/arch/arm/mach-omap1/io.c b/arch/arm/mach-omap1/io.c index 207df0fe934d..eb8261d7dead 100644 --- a/arch/arm/mach-omap1/io.c +++ b/arch/arm/mach-omap1/io.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | extern int clk_init(void); | 20 | extern int clk_init(void); |
21 | extern void omap_check_revision(void); | 21 | extern void omap_check_revision(void); |
22 | extern void omap_sram_init(void); | ||
22 | 23 | ||
23 | /* | 24 | /* |
24 | * The machine specific code may provide the extra mapping besides the | 25 | * The machine specific code may provide the extra mapping besides the |
@@ -32,7 +33,6 @@ static struct map_desc omap_io_desc[] __initdata = { | |||
32 | static struct map_desc omap730_io_desc[] __initdata = { | 33 | static struct map_desc omap730_io_desc[] __initdata = { |
33 | { OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE }, | 34 | { OMAP730_DSP_BASE, OMAP730_DSP_START, OMAP730_DSP_SIZE, MT_DEVICE }, |
34 | { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE }, | 35 | { OMAP730_DSPREG_BASE, OMAP730_DSPREG_START, OMAP730_DSPREG_SIZE, MT_DEVICE }, |
35 | { OMAP730_SRAM_BASE, OMAP730_SRAM_START, OMAP730_SRAM_SIZE, MT_DEVICE } | ||
36 | }; | 36 | }; |
37 | #endif | 37 | #endif |
38 | 38 | ||
@@ -40,27 +40,13 @@ static struct map_desc omap730_io_desc[] __initdata = { | |||
40 | static struct map_desc omap1510_io_desc[] __initdata = { | 40 | static struct map_desc omap1510_io_desc[] __initdata = { |
41 | { OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE }, | 41 | { OMAP1510_DSP_BASE, OMAP1510_DSP_START, OMAP1510_DSP_SIZE, MT_DEVICE }, |
42 | { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE }, | 42 | { OMAP1510_DSPREG_BASE, OMAP1510_DSPREG_START, OMAP1510_DSPREG_SIZE, MT_DEVICE }, |
43 | { OMAP1510_SRAM_BASE, OMAP1510_SRAM_START, OMAP1510_SRAM_SIZE, MT_DEVICE } | ||
44 | }; | 43 | }; |
45 | #endif | 44 | #endif |
46 | 45 | ||
47 | #if defined(CONFIG_ARCH_OMAP16XX) | 46 | #if defined(CONFIG_ARCH_OMAP16XX) |
48 | static struct map_desc omap1610_io_desc[] __initdata = { | 47 | static struct map_desc omap16xx_io_desc[] __initdata = { |
49 | { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE }, | 48 | { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE }, |
50 | { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE }, | 49 | { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE }, |
51 | { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP1610_SRAM_SIZE, MT_DEVICE } | ||
52 | }; | ||
53 | |||
54 | static struct map_desc omap5912_io_desc[] __initdata = { | ||
55 | { OMAP16XX_DSP_BASE, OMAP16XX_DSP_START, OMAP16XX_DSP_SIZE, MT_DEVICE }, | ||
56 | { OMAP16XX_DSPREG_BASE, OMAP16XX_DSPREG_START, OMAP16XX_DSPREG_SIZE, MT_DEVICE }, | ||
57 | /* | ||
58 | * The OMAP5912 has 250kByte internal SRAM. Because the mapping is baseed on page | ||
59 | * size (4kByte), it seems that the last 2kByte (=0x800) of the 250kByte are not mapped. | ||
60 | * Add additional 2kByte (0x800) so that the last page is mapped and the last 2kByte | ||
61 | * can be used. | ||
62 | */ | ||
63 | { OMAP16XX_SRAM_BASE, OMAP16XX_SRAM_START, OMAP5912_SRAM_SIZE + 0x800, MT_DEVICE } | ||
64 | }; | 50 | }; |
65 | #endif | 51 | #endif |
66 | 52 | ||
@@ -86,14 +72,13 @@ static void __init _omap_map_io(void) | |||
86 | } | 72 | } |
87 | #endif | 73 | #endif |
88 | #if defined(CONFIG_ARCH_OMAP16XX) | 74 | #if defined(CONFIG_ARCH_OMAP16XX) |
89 | if (cpu_is_omap1610() || cpu_is_omap1710()) { | 75 | if (cpu_is_omap16xx()) { |
90 | iotable_init(omap1610_io_desc, ARRAY_SIZE(omap1610_io_desc)); | 76 | iotable_init(omap16xx_io_desc, ARRAY_SIZE(omap16xx_io_desc)); |
91 | } | ||
92 | if (cpu_is_omap5912()) { | ||
93 | iotable_init(omap5912_io_desc, ARRAY_SIZE(omap5912_io_desc)); | ||
94 | } | 77 | } |
95 | #endif | 78 | #endif |
96 | 79 | ||
80 | omap_sram_init(); | ||
81 | |||
97 | /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort | 82 | /* REVISIT: Refer to OMAP5910 Errata, Advisory SYS_1: "Timeout Abort |
98 | * on a Posted Write in the TIPB Bridge". | 83 | * on a Posted Write in the TIPB Bridge". |
99 | */ | 84 | */ |
@@ -108,8 +93,9 @@ static void __init _omap_map_io(void) | |||
108 | /* | 93 | /* |
109 | * This should only get called from board specific init | 94 | * This should only get called from board specific init |
110 | */ | 95 | */ |
111 | void omap_map_common_io(void) | 96 | void __init omap_map_common_io(void) |
112 | { | 97 | { |
113 | if (!initialized) | 98 | if (!initialized) |
114 | _omap_map_io(); | 99 | _omap_map_io(); |
115 | } | 100 | } |
101 | |||
diff --git a/arch/arm/mach-omap1/irq.c b/arch/arm/mach-omap1/irq.c index afd5d67e4ae7..192ce6055faa 100644 --- a/arch/arm/mach-omap1/irq.c +++ b/arch/arm/mach-omap1/irq.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap/irq.c | 2 | * linux/arch/arm/mach-omap1/irq.c |
3 | * | 3 | * |
4 | * Interrupt handler for all OMAP boards | 4 | * Interrupt handler for all OMAP boards |
5 | * | 5 | * |
diff --git a/arch/arm/mach-omap1/leds-h2p2-debug.c b/arch/arm/mach-omap1/leds-h2p2-debug.c index ec0d8285f243..be283cda63dd 100644 --- a/arch/arm/mach-omap1/leds-h2p2-debug.c +++ b/arch/arm/mach-omap1/leds-h2p2-debug.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap/leds-h2p2-debug.c | 2 | * linux/arch/arm/mach-omap1/leds-h2p2-debug.c |
3 | * | 3 | * |
4 | * Copyright 2003 by Texas Instruments Incorporated | 4 | * Copyright 2003 by Texas Instruments Incorporated |
5 | * | 5 | * |
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/kernel_stat.h> | 14 | #include <linux/kernel_stat.h> |
15 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
16 | #include <linux/version.h> | ||
16 | 17 | ||
17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
18 | #include <asm/hardware.h> | 19 | #include <asm/hardware.h> |
diff --git a/arch/arm/mach-omap1/leds-innovator.c b/arch/arm/mach-omap1/leds-innovator.c index 8043b7d0f66e..c8ffd1ddcded 100644 --- a/arch/arm/mach-omap1/leds-innovator.c +++ b/arch/arm/mach-omap1/leds-innovator.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap/leds-innovator.c | 2 | * linux/arch/arm/mach-omap1/leds-innovator.c |
3 | */ | 3 | */ |
4 | #include <linux/config.h> | 4 | #include <linux/config.h> |
5 | #include <linux/init.h> | 5 | #include <linux/init.h> |
diff --git a/arch/arm/mach-omap1/leds-osk.c b/arch/arm/mach-omap1/leds-osk.c index 4a0e8b9d4fc3..2c8bda847c18 100644 --- a/arch/arm/mach-omap1/leds-osk.c +++ b/arch/arm/mach-omap1/leds-osk.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap/leds-osk.c | 2 | * linux/arch/arm/mach-omap1/leds-osk.c |
3 | * | 3 | * |
4 | * LED driver for OSK, and optionally Mistral QVGA, boards | 4 | * LED driver for OSK, and optionally Mistral QVGA, boards |
5 | */ | 5 | */ |
@@ -64,7 +64,7 @@ static void tps_work(void *unused) | |||
64 | 64 | ||
65 | static DECLARE_WORK(work, tps_work, NULL); | 65 | static DECLARE_WORK(work, tps_work, NULL); |
66 | 66 | ||
67 | #ifdef CONFIG_FB_OMAP | 67 | #ifdef CONFIG_OMAP_OSK_MISTRAL |
68 | 68 | ||
69 | /* For now, all system indicators require the Mistral board, since that | 69 | /* For now, all system indicators require the Mistral board, since that |
70 | * LED can be manipulated without a task context. This LED is either red, | 70 | * LED can be manipulated without a task context. This LED is either red, |
@@ -127,7 +127,7 @@ void osk_leds_event(led_event_t evt) | |||
127 | hw_led_state = 0; | 127 | hw_led_state = 0; |
128 | break; | 128 | break; |
129 | 129 | ||
130 | #ifdef CONFIG_FB_OMAP | 130 | #ifdef CONFIG_OMAP_OSK_MISTRAL |
131 | 131 | ||
132 | case led_timer: | 132 | case led_timer: |
133 | hw_led_state ^= TIMER_LED; | 133 | hw_led_state ^= TIMER_LED; |
@@ -144,7 +144,7 @@ void osk_leds_event(led_event_t evt) | |||
144 | mistral_setled(); | 144 | mistral_setled(); |
145 | break; | 145 | break; |
146 | 146 | ||
147 | #endif /* CONFIG_FB_OMAP */ | 147 | #endif /* CONFIG_OMAP_OSK_MISTRAL */ |
148 | 148 | ||
149 | /* "green" == tps LED1 (leftmost, normally power-good) | 149 | /* "green" == tps LED1 (leftmost, normally power-good) |
150 | * works only with DC adapter, not on battery power! | 150 | * works only with DC adapter, not on battery power! |
diff --git a/arch/arm/mach-omap1/leds.c b/arch/arm/mach-omap1/leds.c index 8ab21fe98e1b..5c6b1bb6e722 100644 --- a/arch/arm/mach-omap1/leds.c +++ b/arch/arm/mach-omap1/leds.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * linux/arch/arm/mach-omap/leds.c | 2 | * linux/arch/arm/mach-omap1/leds.c |
3 | * | 3 | * |
4 | * OMAP LEDs dispatcher | 4 | * OMAP LEDs dispatcher |
5 | */ | 5 | */ |
@@ -20,7 +20,9 @@ omap_leds_init(void) | |||
20 | if (machine_is_omap_innovator()) | 20 | if (machine_is_omap_innovator()) |
21 | leds_event = innovator_leds_event; | 21 | leds_event = innovator_leds_event; |
22 | 22 | ||
23 | else if (machine_is_omap_h2() || machine_is_omap_perseus2()) | 23 | else if (machine_is_omap_h2() |
24 | || machine_is_omap_h3() | ||
25 | || machine_is_omap_perseus2()) | ||
24 | leds_event = h2p2_dbg_leds_event; | 26 | leds_event = h2p2_dbg_leds_event; |
25 | 27 | ||
26 | else if (machine_is_omap_osk()) | 28 | else if (machine_is_omap_osk()) |
@@ -30,8 +32,12 @@ omap_leds_init(void) | |||
30 | return -1; | 32 | return -1; |
31 | 33 | ||
32 | if (machine_is_omap_h2() | 34 | if (machine_is_omap_h2() |
35 | || machine_is_omap_h3() | ||
33 | || machine_is_omap_perseus2() | 36 | || machine_is_omap_perseus2() |
34 | || machine_is_omap_osk()) { | 37 | #ifdef CONFIG_OMAP_OSK_MISTRAL |
38 | || machine_is_omap_osk() | ||
39 | #endif | ||
40 | ) { | ||
35 | 41 | ||
36 | /* LED1/LED2 pins can be used as GPIO (as done here), or by | 42 | /* LED1/LED2 pins can be used as GPIO (as done here), or by |
37 | * the LPG (works even in deep sleep!), to drive a bicolor | 43 | * the LPG (works even in deep sleep!), to drive a bicolor |
diff --git a/arch/arm/mach-omap1/serial.c b/arch/arm/mach-omap1/serial.c index 214e5d17c8b5..40c4f7c40e73 100644 --- a/arch/arm/mach-omap1/serial.c +++ b/arch/arm/mach-omap1/serial.c | |||
@@ -24,7 +24,11 @@ | |||
24 | 24 | ||
25 | #include <asm/arch/board.h> | 25 | #include <asm/arch/board.h> |
26 | #include <asm/arch/mux.h> | 26 | #include <asm/arch/mux.h> |
27 | #include <asm/arch/gpio.h> | ||
27 | #include <asm/arch/fpga.h> | 28 | #include <asm/arch/fpga.h> |
29 | #ifdef CONFIG_PM | ||
30 | #include <asm/arch/pm.h> | ||
31 | #endif | ||
28 | 32 | ||
29 | static struct clk * uart1_ck = NULL; | 33 | static struct clk * uart1_ck = NULL; |
30 | static struct clk * uart2_ck = NULL; | 34 | static struct clk * uart2_ck = NULL; |
@@ -94,7 +98,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
94 | 98 | ||
95 | static struct platform_device serial_device = { | 99 | static struct platform_device serial_device = { |
96 | .name = "serial8250", | 100 | .name = "serial8250", |
97 | .id = 0, | 101 | .id = PLAT8250_DEV_PLATFORM, |
98 | .dev = { | 102 | .dev = { |
99 | .platform_data = serial_platform_data, | 103 | .platform_data = serial_platform_data, |
100 | }, | 104 | }, |
@@ -193,6 +197,86 @@ void __init omap_serial_init(int ports[OMAP_MAX_NR_PORTS]) | |||
193 | } | 197 | } |
194 | } | 198 | } |
195 | 199 | ||
200 | #ifdef CONFIG_OMAP_SERIAL_WAKE | ||
201 | |||
202 | static irqreturn_t omap_serial_wake_interrupt(int irq, void *dev_id, | ||
203 | struct pt_regs *regs) | ||
204 | { | ||
205 | /* Need to do something with serial port right after wake-up? */ | ||
206 | return IRQ_HANDLED; | ||
207 | } | ||
208 | |||
209 | /* | ||
210 | * Reroutes serial RX lines to GPIO lines for the duration of | ||
211 | * sleep to allow waking up the device from serial port even | ||
212 | * in deep sleep. | ||
213 | */ | ||
214 | void omap_serial_wake_trigger(int enable) | ||
215 | { | ||
216 | if (!cpu_is_omap16xx()) | ||
217 | return; | ||
218 | |||
219 | if (uart1_ck != NULL) { | ||
220 | if (enable) | ||
221 | omap_cfg_reg(V14_16XX_GPIO37); | ||
222 | else | ||
223 | omap_cfg_reg(V14_16XX_UART1_RX); | ||
224 | } | ||
225 | if (uart2_ck != NULL) { | ||
226 | if (enable) | ||
227 | omap_cfg_reg(R9_16XX_GPIO18); | ||
228 | else | ||
229 | omap_cfg_reg(R9_16XX_UART2_RX); | ||
230 | } | ||
231 | if (uart3_ck != NULL) { | ||
232 | if (enable) | ||
233 | omap_cfg_reg(L14_16XX_GPIO49); | ||
234 | else | ||
235 | omap_cfg_reg(L14_16XX_UART3_RX); | ||
236 | } | ||
237 | } | ||
238 | |||
239 | static void __init omap_serial_set_port_wakeup(int gpio_nr) | ||
240 | { | ||
241 | int ret; | ||
242 | |||
243 | ret = omap_request_gpio(gpio_nr); | ||
244 | if (ret < 0) { | ||
245 | printk(KERN_ERR "Could not request UART wake GPIO: %i\n", | ||
246 | gpio_nr); | ||
247 | return; | ||
248 | } | ||
249 | omap_set_gpio_direction(gpio_nr, 1); | ||
250 | set_irq_type(OMAP_GPIO_IRQ(gpio_nr), IRQT_RISING); | ||
251 | ret = request_irq(OMAP_GPIO_IRQ(gpio_nr), &omap_serial_wake_interrupt, | ||
252 | 0, "serial wakeup", NULL); | ||
253 | if (ret) { | ||
254 | omap_free_gpio(gpio_nr); | ||
255 | printk(KERN_ERR "No interrupt for UART wake GPIO: %i\n", | ||
256 | gpio_nr); | ||
257 | return; | ||
258 | } | ||
259 | enable_irq_wake(OMAP_GPIO_IRQ(gpio_nr)); | ||
260 | } | ||
261 | |||
262 | static int __init omap_serial_wakeup_init(void) | ||
263 | { | ||
264 | if (!cpu_is_omap16xx()) | ||
265 | return 0; | ||
266 | |||
267 | if (uart1_ck != NULL) | ||
268 | omap_serial_set_port_wakeup(37); | ||
269 | if (uart2_ck != NULL) | ||
270 | omap_serial_set_port_wakeup(18); | ||
271 | if (uart3_ck != NULL) | ||
272 | omap_serial_set_port_wakeup(49); | ||
273 | |||
274 | return 0; | ||
275 | } | ||
276 | late_initcall(omap_serial_wakeup_init); | ||
277 | |||
278 | #endif /* CONFIG_OMAP_SERIAL_WAKE */ | ||
279 | |||
196 | static int __init omap_init(void) | 280 | static int __init omap_init(void) |
197 | { | 281 | { |
198 | return platform_device_register(&serial_device); | 282 | return platform_device_register(&serial_device); |
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c index d540539c9bbb..191a9b1ee9b7 100644 --- a/arch/arm/mach-omap1/time.c +++ b/arch/arm/mach-omap1/time.c | |||
@@ -247,13 +247,6 @@ unsigned long long sched_clock(void) | |||
247 | #define OMAP_32K_TIMER_TCR 0x04 | 247 | #define OMAP_32K_TIMER_TCR 0x04 |
248 | 248 | ||
249 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) | 249 | #define OMAP_32K_TICKS_PER_HZ (32768 / HZ) |
250 | #if (32768 % HZ) != 0 | ||
251 | /* We cannot ignore modulo. | ||
252 | * Potential error can be as high as several percent. | ||
253 | */ | ||
254 | #define OMAP_32K_TICK_MODULO (32768 % HZ) | ||
255 | static unsigned modulo_count = 0; /* Counts 1/HZ units */ | ||
256 | #endif | ||
257 | 250 | ||
258 | /* | 251 | /* |
259 | * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1 | 252 | * TRM says 1 / HZ = ( TVR + 1) / 32768, so TRV = (32768 / HZ) - 1 |
@@ -296,13 +289,22 @@ static inline void omap_32k_timer_stop(void) | |||
296 | } | 289 | } |
297 | 290 | ||
298 | /* | 291 | /* |
299 | * Rounds down to nearest usec | 292 | * Rounds down to nearest usec. Note that this will overflow for larger values. |
300 | */ | 293 | */ |
301 | static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k) | 294 | static inline unsigned long omap_32k_ticks_to_usecs(unsigned long ticks_32k) |
302 | { | 295 | { |
303 | return (ticks_32k * 5*5*5*5*5*5) >> 9; | 296 | return (ticks_32k * 5*5*5*5*5*5) >> 9; |
304 | } | 297 | } |
305 | 298 | ||
299 | /* | ||
300 | * Rounds down to nearest nsec. | ||
301 | */ | ||
302 | static inline unsigned long long | ||
303 | omap_32k_ticks_to_nsecs(unsigned long ticks_32k) | ||
304 | { | ||
305 | return (unsigned long long) ticks_32k * 1000 * 5*5*5*5*5*5 >> 9; | ||
306 | } | ||
307 | |||
306 | static unsigned long omap_32k_last_tick = 0; | 308 | static unsigned long omap_32k_last_tick = 0; |
307 | 309 | ||
308 | /* | 310 | /* |
@@ -315,6 +317,15 @@ static unsigned long omap_32k_timer_gettimeoffset(void) | |||
315 | } | 317 | } |
316 | 318 | ||
317 | /* | 319 | /* |
320 | * Returns current time from boot in nsecs. It's OK for this to wrap | ||
321 | * around for now, as it's just a relative time stamp. | ||
322 | */ | ||
323 | unsigned long long sched_clock(void) | ||
324 | { | ||
325 | return omap_32k_ticks_to_nsecs(omap_32k_sync_timer_read()); | ||
326 | } | ||
327 | |||
328 | /* | ||
318 | * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this | 329 | * Timer interrupt for 32KHz timer. When dynamic tick is enabled, this |
319 | * function is also called from other interrupts to remove latency | 330 | * function is also called from other interrupts to remove latency |
320 | * issues with dynamic tick. In the dynamic tick case, we need to lock | 331 | * issues with dynamic tick. In the dynamic tick case, we need to lock |
@@ -330,19 +341,6 @@ static irqreturn_t omap_32k_timer_interrupt(int irq, void *dev_id, | |||
330 | now = omap_32k_sync_timer_read(); | 341 | now = omap_32k_sync_timer_read(); |
331 | 342 | ||
332 | while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { | 343 | while (now - omap_32k_last_tick >= OMAP_32K_TICKS_PER_HZ) { |
333 | #ifdef OMAP_32K_TICK_MODULO | ||
334 | /* Modulo addition may put omap_32k_last_tick ahead of now | ||
335 | * and cause unwanted repetition of the while loop. | ||
336 | */ | ||
337 | if (unlikely(now - omap_32k_last_tick == ~0)) | ||
338 | break; | ||
339 | |||
340 | modulo_count += OMAP_32K_TICK_MODULO; | ||
341 | if (modulo_count > HZ) { | ||
342 | ++omap_32k_last_tick; | ||
343 | modulo_count -= HZ; | ||
344 | } | ||
345 | #endif | ||
346 | omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; | 344 | omap_32k_last_tick += OMAP_32K_TICKS_PER_HZ; |
347 | timer_tick(regs); | 345 | timer_tick(regs); |
348 | } | 346 | } |
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c index a10268618f74..e3587efec4bf 100644 --- a/arch/arm/mach-rpc/riscpc.c +++ b/arch/arm/mach-rpc/riscpc.c | |||
@@ -140,7 +140,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
140 | 140 | ||
141 | static struct platform_device serial_device = { | 141 | static struct platform_device serial_device = { |
142 | .name = "serial8250", | 142 | .name = "serial8250", |
143 | .id = 0, | 143 | .id = PLAT8250_DEV_PLATFORM, |
144 | .dev = { | 144 | .dev = { |
145 | .platform_data = serial_platform_data, | 145 | .platform_data = serial_platform_data, |
146 | }, | 146 | }, |
diff --git a/arch/arm/mach-s3c2410/mach-bast.c b/arch/arm/mach-s3c2410/mach-bast.c index e9182242da95..1a3367da6408 100644 --- a/arch/arm/mach-s3c2410/mach-bast.c +++ b/arch/arm/mach-s3c2410/mach-bast.c | |||
@@ -381,7 +381,7 @@ static struct plat_serial8250_port bast_sio_data[] = { | |||
381 | 381 | ||
382 | static struct platform_device bast_sio = { | 382 | static struct platform_device bast_sio = { |
383 | .name = "serial8250", | 383 | .name = "serial8250", |
384 | .id = 0, | 384 | .id = PLAT8250_DEV_PLATFORM, |
385 | .dev = { | 385 | .dev = { |
386 | .platform_data = &bast_sio_data, | 386 | .platform_data = &bast_sio_data, |
387 | }, | 387 | }, |
diff --git a/arch/arm/mach-s3c2410/mach-vr1000.c b/arch/arm/mach-s3c2410/mach-vr1000.c index 924e8464c212..8f9ab2893df4 100644 --- a/arch/arm/mach-s3c2410/mach-vr1000.c +++ b/arch/arm/mach-s3c2410/mach-vr1000.c | |||
@@ -221,7 +221,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
221 | 221 | ||
222 | static struct platform_device serial_device = { | 222 | static struct platform_device serial_device = { |
223 | .name = "serial8250", | 223 | .name = "serial8250", |
224 | .id = 0, | 224 | .id = PLAT8250_DEV_PLATFORM, |
225 | .dev = { | 225 | .dev = { |
226 | .platform_data = serial_platform_data, | 226 | .platform_data = serial_platform_data, |
227 | }, | 227 | }, |
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c index e737eae4521f..946c0d11c73b 100644 --- a/arch/arm/mach-shark/core.c +++ b/arch/arm/mach-shark/core.c | |||
@@ -41,7 +41,7 @@ static struct plat_serial8250_port serial_platform_data[] = { | |||
41 | 41 | ||
42 | static struct platform_device serial_device = { | 42 | static struct platform_device serial_device = { |
43 | .name = "serial8250", | 43 | .name = "serial8250", |
44 | .id = 0, | 44 | .id = PLAT8250_DEV_PLATFORM, |
45 | .dev = { | 45 | .dev = { |
46 | .platform_data = serial_platform_data, | 46 | .platform_data = serial_platform_data, |
47 | }, | 47 | }, |
diff --git a/arch/arm/mm/flush.c b/arch/arm/mm/flush.c index 191788fb18d1..b0208c992576 100644 --- a/arch/arm/mm/flush.c +++ b/arch/arm/mm/flush.c | |||
@@ -16,6 +16,58 @@ | |||
16 | #include <asm/tlbflush.h> | 16 | #include <asm/tlbflush.h> |
17 | 17 | ||
18 | #ifdef CONFIG_CPU_CACHE_VIPT | 18 | #ifdef CONFIG_CPU_CACHE_VIPT |
19 | |||
20 | void flush_cache_mm(struct mm_struct *mm) | ||
21 | { | ||
22 | if (cache_is_vivt()) { | ||
23 | if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) | ||
24 | __cpuc_flush_user_all(); | ||
25 | return; | ||
26 | } | ||
27 | |||
28 | if (cache_is_vipt_aliasing()) { | ||
29 | asm( "mcr p15, 0, %0, c7, c14, 0\n" | ||
30 | " mcr p15, 0, %0, c7, c5, 0\n" | ||
31 | " mcr p15, 0, %0, c7, c10, 4" | ||
32 | : | ||
33 | : "r" (0) | ||
34 | : "cc"); | ||
35 | } | ||
36 | } | ||
37 | |||
38 | void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end) | ||
39 | { | ||
40 | if (cache_is_vivt()) { | ||
41 | if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) | ||
42 | __cpuc_flush_user_range(start & PAGE_MASK, PAGE_ALIGN(end), | ||
43 | vma->vm_flags); | ||
44 | return; | ||
45 | } | ||
46 | |||
47 | if (cache_is_vipt_aliasing()) { | ||
48 | asm( "mcr p15, 0, %0, c7, c14, 0\n" | ||
49 | " mcr p15, 0, %0, c7, c5, 0\n" | ||
50 | " mcr p15, 0, %0, c7, c10, 4" | ||
51 | : | ||
52 | : "r" (0) | ||
53 | : "cc"); | ||
54 | } | ||
55 | } | ||
56 | |||
57 | void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn) | ||
58 | { | ||
59 | if (cache_is_vivt()) { | ||
60 | if (cpu_isset(smp_processor_id(), vma->vm_mm->cpu_vm_mask)) { | ||
61 | unsigned long addr = user_addr & PAGE_MASK; | ||
62 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); | ||
63 | } | ||
64 | return; | ||
65 | } | ||
66 | |||
67 | if (cache_is_vipt_aliasing()) | ||
68 | flush_pfn_alias(pfn, user_addr); | ||
69 | } | ||
70 | |||
19 | #define ALIAS_FLUSH_START 0xffff4000 | 71 | #define ALIAS_FLUSH_START 0xffff4000 |
20 | 72 | ||
21 | #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) | 73 | #define TOP_PTE(x) pte_offset_kernel(top_pmd, x) |
diff --git a/arch/ppc/syslib/mpc10x_common.c b/arch/ppc/syslib/mpc10x_common.c index 87065e2e4c5f..3e039706bdbc 100644 --- a/arch/ppc/syslib/mpc10x_common.c +++ b/arch/ppc/syslib/mpc10x_common.c | |||
@@ -140,12 +140,12 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
140 | }, | 140 | }, |
141 | [MPC10X_UART0] = { | 141 | [MPC10X_UART0] = { |
142 | .name = "serial8250", | 142 | .name = "serial8250", |
143 | .id = 0, | 143 | .id = PLAT8250_DEV_PLATFORM, |
144 | .dev.platform_data = serial_plat_uart0, | 144 | .dev.platform_data = serial_plat_uart0, |
145 | }, | 145 | }, |
146 | [MPC10X_UART1] = { | 146 | [MPC10X_UART1] = { |
147 | .name = "serial8250", | 147 | .name = "serial8250", |
148 | .id = 1, | 148 | .id = PLAT8250_DEV_PLATFORM1, |
149 | .dev.platform_data = serial_plat_uart1, | 149 | .dev.platform_data = serial_plat_uart1, |
150 | }, | 150 | }, |
151 | 151 | ||
diff --git a/arch/ppc/syslib/mpc83xx_devices.c b/arch/ppc/syslib/mpc83xx_devices.c index 5aaf0e58e1f9..95b3b8a7f0ba 100644 --- a/arch/ppc/syslib/mpc83xx_devices.c +++ b/arch/ppc/syslib/mpc83xx_devices.c | |||
@@ -165,7 +165,7 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
165 | }, | 165 | }, |
166 | [MPC83xx_DUART] = { | 166 | [MPC83xx_DUART] = { |
167 | .name = "serial8250", | 167 | .name = "serial8250", |
168 | .id = 0, | 168 | .id = PLAT8250_DEV_PLATFORM, |
169 | .dev.platform_data = serial_platform_data, | 169 | .dev.platform_data = serial_platform_data, |
170 | }, | 170 | }, |
171 | [MPC83xx_SEC2] = { | 171 | [MPC83xx_SEC2] = { |
diff --git a/arch/ppc/syslib/mpc85xx_devices.c b/arch/ppc/syslib/mpc85xx_devices.c index 8af322dd476a..bbc5ac0de878 100644 --- a/arch/ppc/syslib/mpc85xx_devices.c +++ b/arch/ppc/syslib/mpc85xx_devices.c | |||
@@ -282,7 +282,7 @@ struct platform_device ppc_sys_platform_devices[] = { | |||
282 | }, | 282 | }, |
283 | [MPC85xx_DUART] = { | 283 | [MPC85xx_DUART] = { |
284 | .name = "serial8250", | 284 | .name = "serial8250", |
285 | .id = 0, | 285 | .id = PLAT8250_DEV_PLATFORM, |
286 | .dev.platform_data = serial_platform_data, | 286 | .dev.platform_data = serial_platform_data, |
287 | }, | 287 | }, |
288 | [MPC85xx_PERFMON] = { | 288 | [MPC85xx_PERFMON] = { |
diff --git a/arch/ppc64/kernel/setup.c b/arch/ppc64/kernel/setup.c index d0bb68af0ea4..bfa8791c9807 100644 --- a/arch/ppc64/kernel/setup.c +++ b/arch/ppc64/kernel/setup.c | |||
@@ -1283,7 +1283,7 @@ void __init generic_find_legacy_serial_ports(u64 *physport, | |||
1283 | 1283 | ||
1284 | static struct platform_device serial_device = { | 1284 | static struct platform_device serial_device = { |
1285 | .name = "serial8250", | 1285 | .name = "serial8250", |
1286 | .id = 0, | 1286 | .id = PLAT8250_DEV_PLATFORM, |
1287 | .dev = { | 1287 | .dev = { |
1288 | .platform_data = serial_ports, | 1288 | .platform_data = serial_ports, |
1289 | }, | 1289 | }, |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 6e9da1372225..8334496a7e0a 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -144,6 +144,22 @@ config I2C_I810 | |||
144 | This driver can also be built as a module. If so, the module | 144 | This driver can also be built as a module. If so, the module |
145 | will be called i2c-i810. | 145 | will be called i2c-i810. |
146 | 146 | ||
147 | config I2C_PXA | ||
148 | tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)" | ||
149 | depends on I2C && EXPERIMENTAL && ARCH_PXA | ||
150 | help | ||
151 | If you have devices in the PXA I2C bus, say yes to this option. | ||
152 | This driver can also be built as a module. If so, the module | ||
153 | will be called i2c-pxa. | ||
154 | |||
155 | config I2C_PXA_SLAVE | ||
156 | bool "Intel PXA2XX I2C Slave comms support" | ||
157 | depends on I2C_PXA | ||
158 | help | ||
159 | Support I2C slave mode communications on the PXA I2C bus. This | ||
160 | is necessary for systems where the PXA may be a target on the | ||
161 | I2C bus. | ||
162 | |||
147 | config I2C_PIIX4 | 163 | config I2C_PIIX4 |
148 | tristate "Intel PIIX4" | 164 | tristate "Intel PIIX4" |
149 | depends on I2C && PCI | 165 | depends on I2C && PCI |
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 42d6d814da72..980b3e983670 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile | |||
@@ -28,6 +28,7 @@ obj-$(CONFIG_I2C_PARPORT_LIGHT) += i2c-parport-light.o | |||
28 | obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o | 28 | obj-$(CONFIG_I2C_PCA_ISA) += i2c-pca-isa.o |
29 | obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o | 29 | obj-$(CONFIG_I2C_PIIX4) += i2c-piix4.o |
30 | obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o | 30 | obj-$(CONFIG_I2C_PROSAVAGE) += i2c-prosavage.o |
31 | obj-$(CONFIG_I2C_PXA) += i2c-pxa.o | ||
31 | obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o | 32 | obj-$(CONFIG_I2C_RPXLITE) += i2c-rpx.o |
32 | obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o | 33 | obj-$(CONFIG_I2C_S3C2410) += i2c-s3c2410.o |
33 | obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o | 34 | obj-$(CONFIG_I2C_SAVAGE4) += i2c-savage4.o |
diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c new file mode 100644 index 000000000000..fdf53ce04248 --- /dev/null +++ b/drivers/i2c/busses/i2c-pxa.c | |||
@@ -0,0 +1,1022 @@ | |||
1 | /* | ||
2 | * i2c_adap_pxa.c | ||
3 | * | ||
4 | * I2C adapter for the PXA I2C bus access. | ||
5 | * | ||
6 | * Copyright (C) 2002 Intrinsyc Software Inc. | ||
7 | * Copyright (C) 2004-2005 Deep Blue Solutions Ltd. | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * History: | ||
14 | * Apr 2002: Initial version [CS] | ||
15 | * Jun 2002: Properly seperated algo/adap [FB] | ||
16 | * Jan 2003: Fixed several bugs concerning interrupt handling [Kai-Uwe Bloem] | ||
17 | * Jan 2003: added limited signal handling [Kai-Uwe Bloem] | ||
18 | * Sep 2004: Major rework to ensure efficient bus handling [RMK] | ||
19 | * Dec 2004: Added support for PXA27x and slave device probing [Liam Girdwood] | ||
20 | * Feb 2005: Rework slave mode handling [RMK] | ||
21 | */ | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/i2c.h> | ||
25 | #include <linux/i2c-id.h> | ||
26 | #include <linux/init.h> | ||
27 | #include <linux/time.h> | ||
28 | #include <linux/sched.h> | ||
29 | #include <linux/delay.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/interrupt.h> | ||
32 | #include <linux/i2c-pxa.h> | ||
33 | |||
34 | #include <asm/hardware.h> | ||
35 | #include <asm/irq.h> | ||
36 | #include <asm/arch/i2c.h> | ||
37 | #include <asm/arch/pxa-regs.h> | ||
38 | |||
39 | struct pxa_i2c { | ||
40 | spinlock_t lock; | ||
41 | wait_queue_head_t wait; | ||
42 | struct i2c_msg *msg; | ||
43 | unsigned int msg_num; | ||
44 | unsigned int msg_idx; | ||
45 | unsigned int msg_ptr; | ||
46 | unsigned int slave_addr; | ||
47 | |||
48 | struct i2c_adapter adap; | ||
49 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
50 | struct i2c_slave_client *slave; | ||
51 | #endif | ||
52 | |||
53 | unsigned int irqlogidx; | ||
54 | u32 isrlog[32]; | ||
55 | u32 icrlog[32]; | ||
56 | }; | ||
57 | |||
58 | /* | ||
59 | * I2C Slave mode address | ||
60 | */ | ||
61 | #define I2C_PXA_SLAVE_ADDR 0x1 | ||
62 | |||
63 | #ifdef DEBUG | ||
64 | |||
65 | struct bits { | ||
66 | u32 mask; | ||
67 | const char *set; | ||
68 | const char *unset; | ||
69 | }; | ||
70 | #define BIT(m, s, u) { .mask = m, .set = s, .unset = u } | ||
71 | |||
72 | static inline void | ||
73 | decode_bits(const char *prefix, const struct bits *bits, int num, u32 val) | ||
74 | { | ||
75 | printk("%s %08x: ", prefix, val); | ||
76 | while (num--) { | ||
77 | const char *str = val & bits->mask ? bits->set : bits->unset; | ||
78 | if (str) | ||
79 | printk("%s ", str); | ||
80 | bits++; | ||
81 | } | ||
82 | } | ||
83 | |||
84 | static const struct bits isr_bits[] = { | ||
85 | BIT(ISR_RWM, "RX", "TX"), | ||
86 | BIT(ISR_ACKNAK, "NAK", "ACK"), | ||
87 | BIT(ISR_UB, "Bsy", "Rdy"), | ||
88 | BIT(ISR_IBB, "BusBsy", "BusRdy"), | ||
89 | BIT(ISR_SSD, "SlaveStop", NULL), | ||
90 | BIT(ISR_ALD, "ALD", NULL), | ||
91 | BIT(ISR_ITE, "TxEmpty", NULL), | ||
92 | BIT(ISR_IRF, "RxFull", NULL), | ||
93 | BIT(ISR_GCAD, "GenCall", NULL), | ||
94 | BIT(ISR_SAD, "SlaveAddr", NULL), | ||
95 | BIT(ISR_BED, "BusErr", NULL), | ||
96 | }; | ||
97 | |||
98 | static void decode_ISR(unsigned int val) | ||
99 | { | ||
100 | decode_bits(KERN_DEBUG "ISR", isr_bits, ARRAY_SIZE(isr_bits), val); | ||
101 | printk("\n"); | ||
102 | } | ||
103 | |||
104 | static const struct bits icr_bits[] = { | ||
105 | BIT(ICR_START, "START", NULL), | ||
106 | BIT(ICR_STOP, "STOP", NULL), | ||
107 | BIT(ICR_ACKNAK, "ACKNAK", NULL), | ||
108 | BIT(ICR_TB, "TB", NULL), | ||
109 | BIT(ICR_MA, "MA", NULL), | ||
110 | BIT(ICR_SCLE, "SCLE", "scle"), | ||
111 | BIT(ICR_IUE, "IUE", "iue"), | ||
112 | BIT(ICR_GCD, "GCD", NULL), | ||
113 | BIT(ICR_ITEIE, "ITEIE", NULL), | ||
114 | BIT(ICR_IRFIE, "IRFIE", NULL), | ||
115 | BIT(ICR_BEIE, "BEIE", NULL), | ||
116 | BIT(ICR_SSDIE, "SSDIE", NULL), | ||
117 | BIT(ICR_ALDIE, "ALDIE", NULL), | ||
118 | BIT(ICR_SADIE, "SADIE", NULL), | ||
119 | BIT(ICR_UR, "UR", "ur"), | ||
120 | }; | ||
121 | |||
122 | static void decode_ICR(unsigned int val) | ||
123 | { | ||
124 | decode_bits(KERN_DEBUG "ICR", icr_bits, ARRAY_SIZE(icr_bits), val); | ||
125 | printk("\n"); | ||
126 | } | ||
127 | |||
128 | static unsigned int i2c_debug = DEBUG; | ||
129 | |||
130 | static void i2c_pxa_show_state(struct pxa_i2c *i2c, int lno, const char *fname) | ||
131 | { | ||
132 | dev_dbg(&i2c->adap.dev, "state:%s:%d: ISR=%08x, ICR=%08x, IBMR=%02x\n", fname, lno, ISR, ICR, IBMR); | ||
133 | } | ||
134 | |||
135 | #define show_state(i2c) i2c_pxa_show_state(i2c, __LINE__, __FUNCTION__) | ||
136 | #else | ||
137 | #define i2c_debug 0 | ||
138 | |||
139 | #define show_state(i2c) do { } while (0) | ||
140 | #define decode_ISR(val) do { } while (0) | ||
141 | #define decode_ICR(val) do { } while (0) | ||
142 | #endif | ||
143 | |||
144 | #define eedbg(lvl, x...) do { if ((lvl) < 1) { printk(KERN_DEBUG "" x); } } while(0) | ||
145 | |||
146 | static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret); | ||
147 | |||
148 | static void i2c_pxa_scream_blue_murder(struct pxa_i2c *i2c, const char *why) | ||
149 | { | ||
150 | unsigned int i; | ||
151 | printk("i2c: error: %s\n", why); | ||
152 | printk("i2c: msg_num: %d msg_idx: %d msg_ptr: %d\n", | ||
153 | i2c->msg_num, i2c->msg_idx, i2c->msg_ptr); | ||
154 | printk("i2c: ICR: %08x ISR: %08x\n" | ||
155 | "i2c: log: ", ICR, ISR); | ||
156 | for (i = 0; i < i2c->irqlogidx; i++) | ||
157 | printk("[%08x:%08x] ", i2c->isrlog[i], i2c->icrlog[i]); | ||
158 | printk("\n"); | ||
159 | } | ||
160 | |||
161 | static inline int i2c_pxa_is_slavemode(struct pxa_i2c *i2c) | ||
162 | { | ||
163 | return !(ICR & ICR_SCLE); | ||
164 | } | ||
165 | |||
166 | static void i2c_pxa_abort(struct pxa_i2c *i2c) | ||
167 | { | ||
168 | unsigned long timeout = jiffies + HZ/4; | ||
169 | |||
170 | if (i2c_pxa_is_slavemode(i2c)) { | ||
171 | dev_dbg(&i2c->adap.dev, "%s: called in slave mode\n", __func__); | ||
172 | return; | ||
173 | } | ||
174 | |||
175 | while (time_before(jiffies, timeout) && (IBMR & 0x1) == 0) { | ||
176 | unsigned long icr = ICR; | ||
177 | |||
178 | icr &= ~ICR_START; | ||
179 | icr |= ICR_ACKNAK | ICR_STOP | ICR_TB; | ||
180 | |||
181 | ICR = icr; | ||
182 | |||
183 | show_state(i2c); | ||
184 | |||
185 | msleep(1); | ||
186 | } | ||
187 | |||
188 | ICR &= ~(ICR_MA | ICR_START | ICR_STOP); | ||
189 | } | ||
190 | |||
191 | static int i2c_pxa_wait_bus_not_busy(struct pxa_i2c *i2c) | ||
192 | { | ||
193 | int timeout = DEF_TIMEOUT; | ||
194 | |||
195 | while (timeout-- && ISR & (ISR_IBB | ISR_UB)) { | ||
196 | if ((ISR & ISR_SAD) != 0) | ||
197 | timeout += 4; | ||
198 | |||
199 | msleep(2); | ||
200 | show_state(i2c); | ||
201 | } | ||
202 | |||
203 | if (timeout <= 0) | ||
204 | show_state(i2c); | ||
205 | |||
206 | return timeout <= 0 ? I2C_RETRY : 0; | ||
207 | } | ||
208 | |||
209 | static int i2c_pxa_wait_master(struct pxa_i2c *i2c) | ||
210 | { | ||
211 | unsigned long timeout = jiffies + HZ*4; | ||
212 | |||
213 | while (time_before(jiffies, timeout)) { | ||
214 | if (i2c_debug > 1) | ||
215 | dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", | ||
216 | __func__, (long)jiffies, ISR, ICR, IBMR); | ||
217 | |||
218 | if (ISR & ISR_SAD) { | ||
219 | if (i2c_debug > 0) | ||
220 | dev_dbg(&i2c->adap.dev, "%s: Slave detected\n", __func__); | ||
221 | goto out; | ||
222 | } | ||
223 | |||
224 | /* wait for unit and bus being not busy, and we also do a | ||
225 | * quick check of the i2c lines themselves to ensure they've | ||
226 | * gone high... | ||
227 | */ | ||
228 | if ((ISR & (ISR_UB | ISR_IBB)) == 0 && IBMR == 3) { | ||
229 | if (i2c_debug > 0) | ||
230 | dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); | ||
231 | return 1; | ||
232 | } | ||
233 | |||
234 | msleep(1); | ||
235 | } | ||
236 | |||
237 | if (i2c_debug > 0) | ||
238 | dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__); | ||
239 | out: | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int i2c_pxa_set_master(struct pxa_i2c *i2c) | ||
244 | { | ||
245 | if (i2c_debug) | ||
246 | dev_dbg(&i2c->adap.dev, "setting to bus master\n"); | ||
247 | |||
248 | if ((ISR & (ISR_UB | ISR_IBB)) != 0) { | ||
249 | dev_dbg(&i2c->adap.dev, "%s: unit is busy\n", __func__); | ||
250 | if (!i2c_pxa_wait_master(i2c)) { | ||
251 | dev_dbg(&i2c->adap.dev, "%s: error: unit busy\n", __func__); | ||
252 | return I2C_RETRY; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | ICR |= ICR_SCLE; | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
261 | static int i2c_pxa_wait_slave(struct pxa_i2c *i2c) | ||
262 | { | ||
263 | unsigned long timeout = jiffies + HZ*1; | ||
264 | |||
265 | /* wait for stop */ | ||
266 | |||
267 | show_state(i2c); | ||
268 | |||
269 | while (time_before(jiffies, timeout)) { | ||
270 | if (i2c_debug > 1) | ||
271 | dev_dbg(&i2c->adap.dev, "%s: %ld: ISR=%08x, ICR=%08x, IBMR=%02x\n", | ||
272 | __func__, (long)jiffies, ISR, ICR, IBMR); | ||
273 | |||
274 | if ((ISR & (ISR_UB|ISR_IBB|ISR_SAD)) == ISR_SAD || | ||
275 | (ICR & ICR_SCLE) == 0) { | ||
276 | if (i2c_debug > 1) | ||
277 | dev_dbg(&i2c->adap.dev, "%s: done\n", __func__); | ||
278 | return 1; | ||
279 | } | ||
280 | |||
281 | msleep(1); | ||
282 | } | ||
283 | |||
284 | if (i2c_debug > 0) | ||
285 | dev_dbg(&i2c->adap.dev, "%s: did not free\n", __func__); | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * clear the hold on the bus, and take of anything else | ||
291 | * that has been configured | ||
292 | */ | ||
293 | static void i2c_pxa_set_slave(struct pxa_i2c *i2c, int errcode) | ||
294 | { | ||
295 | show_state(i2c); | ||
296 | |||
297 | if (errcode < 0) { | ||
298 | udelay(100); /* simple delay */ | ||
299 | } else { | ||
300 | /* we need to wait for the stop condition to end */ | ||
301 | |||
302 | /* if we where in stop, then clear... */ | ||
303 | if (ICR & ICR_STOP) { | ||
304 | udelay(100); | ||
305 | ICR &= ~ICR_STOP; | ||
306 | } | ||
307 | |||
308 | if (!i2c_pxa_wait_slave(i2c)) { | ||
309 | dev_err(&i2c->adap.dev, "%s: wait timedout\n", | ||
310 | __func__); | ||
311 | return; | ||
312 | } | ||
313 | } | ||
314 | |||
315 | ICR &= ~(ICR_STOP|ICR_ACKNAK|ICR_MA); | ||
316 | ICR &= ~ICR_SCLE; | ||
317 | |||
318 | if (i2c_debug) { | ||
319 | dev_dbg(&i2c->adap.dev, "ICR now %08x, ISR %08x\n", ICR, ISR); | ||
320 | decode_ICR(ICR); | ||
321 | } | ||
322 | } | ||
323 | #else | ||
324 | #define i2c_pxa_set_slave(i2c, err) do { } while (0) | ||
325 | #endif | ||
326 | |||
327 | static void i2c_pxa_reset(struct pxa_i2c *i2c) | ||
328 | { | ||
329 | pr_debug("Resetting I2C Controller Unit\n"); | ||
330 | |||
331 | /* abort any transfer currently under way */ | ||
332 | i2c_pxa_abort(i2c); | ||
333 | |||
334 | /* reset according to 9.8 */ | ||
335 | ICR = ICR_UR; | ||
336 | ISR = I2C_ISR_INIT; | ||
337 | ICR &= ~ICR_UR; | ||
338 | |||
339 | ISAR = i2c->slave_addr; | ||
340 | |||
341 | /* set control register values */ | ||
342 | ICR = I2C_ICR_INIT; | ||
343 | |||
344 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
345 | dev_info(&i2c->adap.dev, "Enabling slave mode\n"); | ||
346 | ICR |= ICR_SADIE | ICR_ALDIE | ICR_SSDIE; | ||
347 | #endif | ||
348 | |||
349 | i2c_pxa_set_slave(i2c, 0); | ||
350 | |||
351 | /* enable unit */ | ||
352 | ICR |= ICR_IUE; | ||
353 | udelay(100); | ||
354 | } | ||
355 | |||
356 | |||
357 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
358 | /* | ||
359 | * I2C EEPROM emulation. | ||
360 | */ | ||
361 | static struct i2c_eeprom_emu eeprom = { | ||
362 | .size = I2C_EEPROM_EMU_SIZE, | ||
363 | .watch = LIST_HEAD_INIT(eeprom.watch), | ||
364 | }; | ||
365 | |||
366 | struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void) | ||
367 | { | ||
368 | return &eeprom; | ||
369 | } | ||
370 | |||
371 | int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *emu, void *data, | ||
372 | unsigned int addr, unsigned int size, | ||
373 | struct i2c_eeprom_emu_watcher *watcher) | ||
374 | { | ||
375 | struct i2c_eeprom_emu_watch *watch; | ||
376 | unsigned long flags; | ||
377 | |||
378 | if (addr + size > emu->size) | ||
379 | return -EINVAL; | ||
380 | |||
381 | watch = kmalloc(sizeof(struct i2c_eeprom_emu_watch), GFP_KERNEL); | ||
382 | if (watch) { | ||
383 | watch->start = addr; | ||
384 | watch->end = addr + size - 1; | ||
385 | watch->ops = watcher; | ||
386 | watch->data = data; | ||
387 | |||
388 | local_irq_save(flags); | ||
389 | list_add(&watch->node, &emu->watch); | ||
390 | local_irq_restore(flags); | ||
391 | } | ||
392 | |||
393 | return watch ? 0 : -ENOMEM; | ||
394 | } | ||
395 | |||
396 | void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *emu, void *data, | ||
397 | struct i2c_eeprom_emu_watcher *watcher) | ||
398 | { | ||
399 | struct i2c_eeprom_emu_watch *watch, *n; | ||
400 | unsigned long flags; | ||
401 | |||
402 | list_for_each_entry_safe(watch, n, &emu->watch, node) { | ||
403 | if (watch->ops == watcher && watch->data == data) { | ||
404 | local_irq_save(flags); | ||
405 | list_del(&watch->node); | ||
406 | local_irq_restore(flags); | ||
407 | kfree(watch); | ||
408 | } | ||
409 | } | ||
410 | } | ||
411 | |||
412 | static void i2c_eeprom_emu_event(void *ptr, i2c_slave_event_t event) | ||
413 | { | ||
414 | struct i2c_eeprom_emu *emu = ptr; | ||
415 | |||
416 | eedbg(3, "i2c_eeprom_emu_event: %d\n", event); | ||
417 | |||
418 | switch (event) { | ||
419 | case I2C_SLAVE_EVENT_START_WRITE: | ||
420 | emu->seen_start = 1; | ||
421 | eedbg(2, "i2c_eeprom: write initiated\n"); | ||
422 | break; | ||
423 | |||
424 | case I2C_SLAVE_EVENT_START_READ: | ||
425 | emu->seen_start = 0; | ||
426 | eedbg(2, "i2c_eeprom: read initiated\n"); | ||
427 | break; | ||
428 | |||
429 | case I2C_SLAVE_EVENT_STOP: | ||
430 | emu->seen_start = 0; | ||
431 | eedbg(2, "i2c_eeprom: received stop\n"); | ||
432 | break; | ||
433 | |||
434 | default: | ||
435 | eedbg(0, "i2c_eeprom: unhandled event\n"); | ||
436 | break; | ||
437 | } | ||
438 | } | ||
439 | |||
440 | static int i2c_eeprom_emu_read(void *ptr) | ||
441 | { | ||
442 | struct i2c_eeprom_emu *emu = ptr; | ||
443 | int ret; | ||
444 | |||
445 | ret = emu->bytes[emu->ptr]; | ||
446 | emu->ptr = (emu->ptr + 1) % emu->size; | ||
447 | |||
448 | return ret; | ||
449 | } | ||
450 | |||
451 | static void i2c_eeprom_emu_write(void *ptr, unsigned int val) | ||
452 | { | ||
453 | struct i2c_eeprom_emu *emu = ptr; | ||
454 | struct i2c_eeprom_emu_watch *watch; | ||
455 | |||
456 | if (emu->seen_start != 0) { | ||
457 | eedbg(2, "i2c_eeprom_emu_write: setting ptr %02x\n", val); | ||
458 | emu->ptr = val; | ||
459 | emu->seen_start = 0; | ||
460 | return; | ||
461 | } | ||
462 | |||
463 | emu->bytes[emu->ptr] = val; | ||
464 | |||
465 | eedbg(1, "i2c_eeprom_emu_write: ptr=0x%02x, val=0x%02x\n", | ||
466 | emu->ptr, val); | ||
467 | |||
468 | list_for_each_entry(watch, &emu->watch, node) { | ||
469 | if (!watch->ops || !watch->ops->write) | ||
470 | continue; | ||
471 | if (watch->start <= emu->ptr && watch->end >= emu->ptr) | ||
472 | watch->ops->write(watch->data, emu->ptr, val); | ||
473 | } | ||
474 | |||
475 | emu->ptr = (emu->ptr + 1) % emu->size; | ||
476 | } | ||
477 | |||
478 | struct i2c_slave_client eeprom_client = { | ||
479 | .data = &eeprom, | ||
480 | .event = i2c_eeprom_emu_event, | ||
481 | .read = i2c_eeprom_emu_read, | ||
482 | .write = i2c_eeprom_emu_write | ||
483 | }; | ||
484 | |||
485 | /* | ||
486 | * PXA I2C Slave mode | ||
487 | */ | ||
488 | |||
489 | static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) | ||
490 | { | ||
491 | if (isr & ISR_BED) { | ||
492 | /* what should we do here? */ | ||
493 | } else { | ||
494 | int ret = i2c->slave->read(i2c->slave->data); | ||
495 | |||
496 | IDBR = ret; | ||
497 | ICR |= ICR_TB; /* allow next byte */ | ||
498 | } | ||
499 | } | ||
500 | |||
501 | static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) | ||
502 | { | ||
503 | unsigned int byte = IDBR; | ||
504 | |||
505 | if (i2c->slave != NULL) | ||
506 | i2c->slave->write(i2c->slave->data, byte); | ||
507 | |||
508 | ICR |= ICR_TB; | ||
509 | } | ||
510 | |||
511 | static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) | ||
512 | { | ||
513 | int timeout; | ||
514 | |||
515 | if (i2c_debug > 0) | ||
516 | dev_dbg(&i2c->adap.dev, "SAD, mode is slave-%cx\n", | ||
517 | (isr & ISR_RWM) ? 'r' : 't'); | ||
518 | |||
519 | if (i2c->slave != NULL) | ||
520 | i2c->slave->event(i2c->slave->data, | ||
521 | (isr & ISR_RWM) ? I2C_SLAVE_EVENT_START_READ : I2C_SLAVE_EVENT_START_WRITE); | ||
522 | |||
523 | /* | ||
524 | * slave could interrupt in the middle of us generating a | ||
525 | * start condition... if this happens, we'd better back off | ||
526 | * and stop holding the poor thing up | ||
527 | */ | ||
528 | ICR &= ~(ICR_START|ICR_STOP); | ||
529 | ICR |= ICR_TB; | ||
530 | |||
531 | timeout = 0x10000; | ||
532 | |||
533 | while (1) { | ||
534 | if ((IBMR & 2) == 2) | ||
535 | break; | ||
536 | |||
537 | timeout--; | ||
538 | |||
539 | if (timeout <= 0) { | ||
540 | dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n"); | ||
541 | break; | ||
542 | } | ||
543 | } | ||
544 | |||
545 | ICR &= ~ICR_SCLE; | ||
546 | } | ||
547 | |||
548 | static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) | ||
549 | { | ||
550 | if (i2c_debug > 2) | ||
551 | dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop)\n"); | ||
552 | |||
553 | if (i2c->slave != NULL) | ||
554 | i2c->slave->event(i2c->slave->data, I2C_SLAVE_EVENT_STOP); | ||
555 | |||
556 | if (i2c_debug > 2) | ||
557 | dev_dbg(&i2c->adap.dev, "ISR: SSD (Slave Stop) acked\n"); | ||
558 | |||
559 | /* | ||
560 | * If we have a master-mode message waiting, | ||
561 | * kick it off now that the slave has completed. | ||
562 | */ | ||
563 | if (i2c->msg) | ||
564 | i2c_pxa_master_complete(i2c, I2C_RETRY); | ||
565 | } | ||
566 | #else | ||
567 | static void i2c_pxa_slave_txempty(struct pxa_i2c *i2c, u32 isr) | ||
568 | { | ||
569 | if (isr & ISR_BED) { | ||
570 | /* what should we do here? */ | ||
571 | } else { | ||
572 | IDBR = 0; | ||
573 | ICR |= ICR_TB; | ||
574 | } | ||
575 | } | ||
576 | |||
577 | static void i2c_pxa_slave_rxfull(struct pxa_i2c *i2c, u32 isr) | ||
578 | { | ||
579 | ICR |= ICR_TB | ICR_ACKNAK; | ||
580 | } | ||
581 | |||
582 | static void i2c_pxa_slave_start(struct pxa_i2c *i2c, u32 isr) | ||
583 | { | ||
584 | int timeout; | ||
585 | |||
586 | /* | ||
587 | * slave could interrupt in the middle of us generating a | ||
588 | * start condition... if this happens, we'd better back off | ||
589 | * and stop holding the poor thing up | ||
590 | */ | ||
591 | ICR &= ~(ICR_START|ICR_STOP); | ||
592 | ICR |= ICR_TB | ICR_ACKNAK; | ||
593 | |||
594 | timeout = 0x10000; | ||
595 | |||
596 | while (1) { | ||
597 | if ((IBMR & 2) == 2) | ||
598 | break; | ||
599 | |||
600 | timeout--; | ||
601 | |||
602 | if (timeout <= 0) { | ||
603 | dev_err(&i2c->adap.dev, "timeout waiting for SCL high\n"); | ||
604 | break; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | ICR &= ~ICR_SCLE; | ||
609 | } | ||
610 | |||
611 | static void i2c_pxa_slave_stop(struct pxa_i2c *i2c) | ||
612 | { | ||
613 | if (i2c->msg) | ||
614 | i2c_pxa_master_complete(i2c, I2C_RETRY); | ||
615 | } | ||
616 | #endif | ||
617 | |||
618 | /* | ||
619 | * PXA I2C Master mode | ||
620 | */ | ||
621 | |||
622 | static inline unsigned int i2c_pxa_addr_byte(struct i2c_msg *msg) | ||
623 | { | ||
624 | unsigned int addr = (msg->addr & 0x7f) << 1; | ||
625 | |||
626 | if (msg->flags & I2C_M_RD) | ||
627 | addr |= 1; | ||
628 | |||
629 | return addr; | ||
630 | } | ||
631 | |||
632 | static inline void i2c_pxa_start_message(struct pxa_i2c *i2c) | ||
633 | { | ||
634 | u32 icr; | ||
635 | |||
636 | /* | ||
637 | * Step 1: target slave address into IDBR | ||
638 | */ | ||
639 | IDBR = i2c_pxa_addr_byte(i2c->msg); | ||
640 | |||
641 | /* | ||
642 | * Step 2: initiate the write. | ||
643 | */ | ||
644 | icr = ICR & ~(ICR_STOP | ICR_ALDIE); | ||
645 | ICR = icr | ICR_START | ICR_TB; | ||
646 | } | ||
647 | |||
648 | /* | ||
649 | * We are protected by the adapter bus semaphore. | ||
650 | */ | ||
651 | static int i2c_pxa_do_xfer(struct pxa_i2c *i2c, struct i2c_msg *msg, int num) | ||
652 | { | ||
653 | long timeout; | ||
654 | int ret; | ||
655 | |||
656 | /* | ||
657 | * Wait for the bus to become free. | ||
658 | */ | ||
659 | ret = i2c_pxa_wait_bus_not_busy(i2c); | ||
660 | if (ret) { | ||
661 | dev_err(&i2c->adap.dev, "i2c_pxa: timeout waiting for bus free\n"); | ||
662 | goto out; | ||
663 | } | ||
664 | |||
665 | /* | ||
666 | * Set master mode. | ||
667 | */ | ||
668 | ret = i2c_pxa_set_master(i2c); | ||
669 | if (ret) { | ||
670 | dev_err(&i2c->adap.dev, "i2c_pxa_set_master: error %d\n", ret); | ||
671 | goto out; | ||
672 | } | ||
673 | |||
674 | spin_lock_irq(&i2c->lock); | ||
675 | |||
676 | i2c->msg = msg; | ||
677 | i2c->msg_num = num; | ||
678 | i2c->msg_idx = 0; | ||
679 | i2c->msg_ptr = 0; | ||
680 | i2c->irqlogidx = 0; | ||
681 | |||
682 | i2c_pxa_start_message(i2c); | ||
683 | |||
684 | spin_unlock_irq(&i2c->lock); | ||
685 | |||
686 | /* | ||
687 | * The rest of the processing occurs in the interrupt handler. | ||
688 | */ | ||
689 | timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, HZ * 5); | ||
690 | |||
691 | /* | ||
692 | * We place the return code in i2c->msg_idx. | ||
693 | */ | ||
694 | ret = i2c->msg_idx; | ||
695 | |||
696 | if (timeout == 0) | ||
697 | i2c_pxa_scream_blue_murder(i2c, "timeout"); | ||
698 | |||
699 | out: | ||
700 | return ret; | ||
701 | } | ||
702 | |||
703 | /* | ||
704 | * i2c_pxa_master_complete - complete the message and wake up. | ||
705 | */ | ||
706 | static void i2c_pxa_master_complete(struct pxa_i2c *i2c, int ret) | ||
707 | { | ||
708 | i2c->msg_ptr = 0; | ||
709 | i2c->msg = NULL; | ||
710 | i2c->msg_idx ++; | ||
711 | i2c->msg_num = 0; | ||
712 | if (ret) | ||
713 | i2c->msg_idx = ret; | ||
714 | wake_up(&i2c->wait); | ||
715 | } | ||
716 | |||
717 | static void i2c_pxa_irq_txempty(struct pxa_i2c *i2c, u32 isr) | ||
718 | { | ||
719 | u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); | ||
720 | |||
721 | again: | ||
722 | /* | ||
723 | * If ISR_ALD is set, we lost arbitration. | ||
724 | */ | ||
725 | if (isr & ISR_ALD) { | ||
726 | /* | ||
727 | * Do we need to do anything here? The PXA docs | ||
728 | * are vague about what happens. | ||
729 | */ | ||
730 | i2c_pxa_scream_blue_murder(i2c, "ALD set"); | ||
731 | |||
732 | /* | ||
733 | * We ignore this error. We seem to see spurious ALDs | ||
734 | * for seemingly no reason. If we handle them as I think | ||
735 | * they should, we end up causing an I2C error, which | ||
736 | * is painful for some systems. | ||
737 | */ | ||
738 | return; /* ignore */ | ||
739 | } | ||
740 | |||
741 | if (isr & ISR_BED) { | ||
742 | int ret = BUS_ERROR; | ||
743 | |||
744 | /* | ||
745 | * I2C bus error - either the device NAK'd us, or | ||
746 | * something more serious happened. If we were NAK'd | ||
747 | * on the initial address phase, we can retry. | ||
748 | */ | ||
749 | if (isr & ISR_ACKNAK) { | ||
750 | if (i2c->msg_ptr == 0 && i2c->msg_idx == 0) | ||
751 | ret = I2C_RETRY; | ||
752 | else | ||
753 | ret = XFER_NAKED; | ||
754 | } | ||
755 | i2c_pxa_master_complete(i2c, ret); | ||
756 | } else if (isr & ISR_RWM) { | ||
757 | /* | ||
758 | * Read mode. We have just sent the address byte, and | ||
759 | * now we must initiate the transfer. | ||
760 | */ | ||
761 | if (i2c->msg_ptr == i2c->msg->len - 1 && | ||
762 | i2c->msg_idx == i2c->msg_num - 1) | ||
763 | icr |= ICR_STOP | ICR_ACKNAK; | ||
764 | |||
765 | icr |= ICR_ALDIE | ICR_TB; | ||
766 | } else if (i2c->msg_ptr < i2c->msg->len) { | ||
767 | /* | ||
768 | * Write mode. Write the next data byte. | ||
769 | */ | ||
770 | IDBR = i2c->msg->buf[i2c->msg_ptr++]; | ||
771 | |||
772 | icr |= ICR_ALDIE | ICR_TB; | ||
773 | |||
774 | /* | ||
775 | * If this is the last byte of the last message, send | ||
776 | * a STOP. | ||
777 | */ | ||
778 | if (i2c->msg_ptr == i2c->msg->len && | ||
779 | i2c->msg_idx == i2c->msg_num - 1) | ||
780 | icr |= ICR_STOP; | ||
781 | } else if (i2c->msg_idx < i2c->msg_num - 1) { | ||
782 | /* | ||
783 | * Next segment of the message. | ||
784 | */ | ||
785 | i2c->msg_ptr = 0; | ||
786 | i2c->msg_idx ++; | ||
787 | i2c->msg++; | ||
788 | |||
789 | /* | ||
790 | * If we aren't doing a repeated start and address, | ||
791 | * go back and try to send the next byte. Note that | ||
792 | * we do not support switching the R/W direction here. | ||
793 | */ | ||
794 | if (i2c->msg->flags & I2C_M_NOSTART) | ||
795 | goto again; | ||
796 | |||
797 | /* | ||
798 | * Write the next address. | ||
799 | */ | ||
800 | IDBR = i2c_pxa_addr_byte(i2c->msg); | ||
801 | |||
802 | /* | ||
803 | * And trigger a repeated start, and send the byte. | ||
804 | */ | ||
805 | icr &= ~ICR_ALDIE; | ||
806 | icr |= ICR_START | ICR_TB; | ||
807 | } else { | ||
808 | if (i2c->msg->len == 0) { | ||
809 | /* | ||
810 | * Device probes have a message length of zero | ||
811 | * and need the bus to be reset before it can | ||
812 | * be used again. | ||
813 | */ | ||
814 | i2c_pxa_reset(i2c); | ||
815 | } | ||
816 | i2c_pxa_master_complete(i2c, 0); | ||
817 | } | ||
818 | |||
819 | i2c->icrlog[i2c->irqlogidx-1] = icr; | ||
820 | |||
821 | ICR = icr; | ||
822 | show_state(i2c); | ||
823 | } | ||
824 | |||
825 | static void i2c_pxa_irq_rxfull(struct pxa_i2c *i2c, u32 isr) | ||
826 | { | ||
827 | u32 icr = ICR & ~(ICR_START|ICR_STOP|ICR_ACKNAK|ICR_TB); | ||
828 | |||
829 | /* | ||
830 | * Read the byte. | ||
831 | */ | ||
832 | i2c->msg->buf[i2c->msg_ptr++] = IDBR; | ||
833 | |||
834 | if (i2c->msg_ptr < i2c->msg->len) { | ||
835 | /* | ||
836 | * If this is the last byte of the last | ||
837 | * message, send a STOP. | ||
838 | */ | ||
839 | if (i2c->msg_ptr == i2c->msg->len - 1) | ||
840 | icr |= ICR_STOP | ICR_ACKNAK; | ||
841 | |||
842 | icr |= ICR_ALDIE | ICR_TB; | ||
843 | } else { | ||
844 | i2c_pxa_master_complete(i2c, 0); | ||
845 | } | ||
846 | |||
847 | i2c->icrlog[i2c->irqlogidx-1] = icr; | ||
848 | |||
849 | ICR = icr; | ||
850 | } | ||
851 | |||
852 | static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id, struct pt_regs *regs) | ||
853 | { | ||
854 | struct pxa_i2c *i2c = dev_id; | ||
855 | u32 isr = ISR; | ||
856 | |||
857 | if (i2c_debug > 2 && 0) { | ||
858 | dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n", | ||
859 | __func__, isr, ICR, IBMR); | ||
860 | decode_ISR(isr); | ||
861 | } | ||
862 | |||
863 | if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32)) | ||
864 | i2c->isrlog[i2c->irqlogidx++] = isr; | ||
865 | |||
866 | show_state(i2c); | ||
867 | |||
868 | /* | ||
869 | * Always clear all pending IRQs. | ||
870 | */ | ||
871 | ISR = isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED); | ||
872 | |||
873 | if (isr & ISR_SAD) | ||
874 | i2c_pxa_slave_start(i2c, isr); | ||
875 | if (isr & ISR_SSD) | ||
876 | i2c_pxa_slave_stop(i2c); | ||
877 | |||
878 | if (i2c_pxa_is_slavemode(i2c)) { | ||
879 | if (isr & ISR_ITE) | ||
880 | i2c_pxa_slave_txempty(i2c, isr); | ||
881 | if (isr & ISR_IRF) | ||
882 | i2c_pxa_slave_rxfull(i2c, isr); | ||
883 | } else if (i2c->msg) { | ||
884 | if (isr & ISR_ITE) | ||
885 | i2c_pxa_irq_txempty(i2c, isr); | ||
886 | if (isr & ISR_IRF) | ||
887 | i2c_pxa_irq_rxfull(i2c, isr); | ||
888 | } else { | ||
889 | i2c_pxa_scream_blue_murder(i2c, "spurious irq"); | ||
890 | } | ||
891 | |||
892 | return IRQ_HANDLED; | ||
893 | } | ||
894 | |||
895 | |||
896 | static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num) | ||
897 | { | ||
898 | struct pxa_i2c *i2c = adap->algo_data; | ||
899 | int ret, i; | ||
900 | |||
901 | for (i = adap->retries; i >= 0; i--) { | ||
902 | ret = i2c_pxa_do_xfer(i2c, msgs, num); | ||
903 | if (ret != I2C_RETRY) | ||
904 | goto out; | ||
905 | |||
906 | if (i2c_debug) | ||
907 | dev_dbg(&adap->dev, "Retrying transmission\n"); | ||
908 | udelay(100); | ||
909 | } | ||
910 | i2c_pxa_scream_blue_murder(i2c, "exhausted retries"); | ||
911 | ret = -EREMOTEIO; | ||
912 | out: | ||
913 | i2c_pxa_set_slave(i2c, ret); | ||
914 | return ret; | ||
915 | } | ||
916 | |||
917 | static struct i2c_algorithm i2c_pxa_algorithm = { | ||
918 | .name = "PXA-I2C-Algorithm", | ||
919 | .id = I2C_ALGO_PXA, | ||
920 | .master_xfer = i2c_pxa_xfer, | ||
921 | }; | ||
922 | |||
923 | static struct pxa_i2c i2c_pxa = { | ||
924 | .lock = SPIN_LOCK_UNLOCKED, | ||
925 | .wait = __WAIT_QUEUE_HEAD_INITIALIZER(i2c_pxa.wait), | ||
926 | .adap = { | ||
927 | .name = "pxa2xx-i2c", | ||
928 | .id = I2C_ALGO_PXA, | ||
929 | .algo = &i2c_pxa_algorithm, | ||
930 | .retries = 5, | ||
931 | }, | ||
932 | }; | ||
933 | |||
934 | static int i2c_pxa_probe(struct device *dev) | ||
935 | { | ||
936 | struct pxa_i2c *i2c = &i2c_pxa; | ||
937 | struct i2c_pxa_platform_data *plat = dev->platform_data; | ||
938 | int ret; | ||
939 | |||
940 | #ifdef CONFIG_PXA27x | ||
941 | pxa_gpio_mode(GPIO117_I2CSCL_MD); | ||
942 | pxa_gpio_mode(GPIO118_I2CSDA_MD); | ||
943 | udelay(100); | ||
944 | #endif | ||
945 | |||
946 | i2c->slave_addr = I2C_PXA_SLAVE_ADDR; | ||
947 | |||
948 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
949 | i2c->slave = &eeprom_client; | ||
950 | if (plat) { | ||
951 | i2c->slave_addr = plat->slave_addr; | ||
952 | if (plat->slave) | ||
953 | i2c->slave = plat->slave; | ||
954 | } | ||
955 | #endif | ||
956 | |||
957 | pxa_set_cken(CKEN14_I2C, 1); | ||
958 | ret = request_irq(IRQ_I2C, i2c_pxa_handler, SA_INTERRUPT, | ||
959 | "pxa2xx-i2c", i2c); | ||
960 | if (ret) | ||
961 | goto out; | ||
962 | |||
963 | i2c_pxa_reset(i2c); | ||
964 | |||
965 | i2c->adap.algo_data = i2c; | ||
966 | i2c->adap.dev.parent = dev; | ||
967 | |||
968 | ret = i2c_add_adapter(&i2c->adap); | ||
969 | if (ret < 0) { | ||
970 | printk(KERN_INFO "I2C: Failed to add bus\n"); | ||
971 | goto err_irq; | ||
972 | } | ||
973 | |||
974 | dev_set_drvdata(dev, i2c); | ||
975 | |||
976 | #ifdef CONFIG_I2C_PXA_SLAVE | ||
977 | printk(KERN_INFO "I2C: %s: PXA I2C adapter, slave address %d\n", | ||
978 | i2c->adap.dev.bus_id, i2c->slave_addr); | ||
979 | #else | ||
980 | printk(KERN_INFO "I2C: %s: PXA I2C adapter\n", | ||
981 | i2c->adap.dev.bus_id); | ||
982 | #endif | ||
983 | return 0; | ||
984 | |||
985 | err_irq: | ||
986 | free_irq(IRQ_I2C, i2c); | ||
987 | out: | ||
988 | return ret; | ||
989 | } | ||
990 | |||
991 | static int i2c_pxa_remove(struct device *dev) | ||
992 | { | ||
993 | struct pxa_i2c *i2c = dev_get_drvdata(dev); | ||
994 | |||
995 | dev_set_drvdata(dev, NULL); | ||
996 | |||
997 | i2c_del_adapter(&i2c->adap); | ||
998 | free_irq(IRQ_I2C, i2c); | ||
999 | pxa_set_cken(CKEN14_I2C, 0); | ||
1000 | |||
1001 | return 0; | ||
1002 | } | ||
1003 | |||
1004 | static struct device_driver i2c_pxa_driver = { | ||
1005 | .name = "pxa2xx-i2c", | ||
1006 | .bus = &platform_bus_type, | ||
1007 | .probe = i2c_pxa_probe, | ||
1008 | .remove = i2c_pxa_remove, | ||
1009 | }; | ||
1010 | |||
1011 | static int __init i2c_adap_pxa_init(void) | ||
1012 | { | ||
1013 | return driver_register(&i2c_pxa_driver); | ||
1014 | } | ||
1015 | |||
1016 | static void i2c_adap_pxa_exit(void) | ||
1017 | { | ||
1018 | return driver_unregister(&i2c_pxa_driver); | ||
1019 | } | ||
1020 | |||
1021 | module_init(i2c_adap_pxa_init); | ||
1022 | module_exit(i2c_adap_pxa_exit); | ||
diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 0a117c61cd18..ceae379a4d4c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c | |||
@@ -1079,13 +1079,17 @@ static void mmc_setup(struct mmc_host *host) | |||
1079 | /** | 1079 | /** |
1080 | * mmc_detect_change - process change of state on a MMC socket | 1080 | * mmc_detect_change - process change of state on a MMC socket |
1081 | * @host: host which changed state. | 1081 | * @host: host which changed state. |
1082 | * @delay: optional delay to wait before detection (jiffies) | ||
1082 | * | 1083 | * |
1083 | * All we know is that card(s) have been inserted or removed | 1084 | * All we know is that card(s) have been inserted or removed |
1084 | * from the socket(s). We don't know which socket or cards. | 1085 | * from the socket(s). We don't know which socket or cards. |
1085 | */ | 1086 | */ |
1086 | void mmc_detect_change(struct mmc_host *host) | 1087 | void mmc_detect_change(struct mmc_host *host, unsigned long delay) |
1087 | { | 1088 | { |
1088 | schedule_work(&host->detect); | 1089 | if (delay) |
1090 | schedule_delayed_work(&host->detect, delay); | ||
1091 | else | ||
1092 | schedule_work(&host->detect); | ||
1089 | } | 1093 | } |
1090 | 1094 | ||
1091 | EXPORT_SYMBOL(mmc_detect_change); | 1095 | EXPORT_SYMBOL(mmc_detect_change); |
@@ -1189,7 +1193,7 @@ int mmc_add_host(struct mmc_host *host) | |||
1189 | ret = mmc_add_host_sysfs(host); | 1193 | ret = mmc_add_host_sysfs(host); |
1190 | if (ret == 0) { | 1194 | if (ret == 0) { |
1191 | mmc_power_off(host); | 1195 | mmc_power_off(host); |
1192 | mmc_detect_change(host); | 1196 | mmc_detect_change(host, 0); |
1193 | } | 1197 | } |
1194 | 1198 | ||
1195 | return ret; | 1199 | return ret; |
@@ -1259,7 +1263,7 @@ EXPORT_SYMBOL(mmc_suspend_host); | |||
1259 | */ | 1263 | */ |
1260 | int mmc_resume_host(struct mmc_host *host) | 1264 | int mmc_resume_host(struct mmc_host *host) |
1261 | { | 1265 | { |
1262 | mmc_detect_change(host); | 1266 | mmc_detect_change(host, 0); |
1263 | 1267 | ||
1264 | return 0; | 1268 | return 0; |
1265 | } | 1269 | } |
diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 716c4ef4faf6..91c74843dc0d 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c | |||
@@ -442,7 +442,7 @@ static void mmci_check_status(unsigned long data) | |||
442 | 442 | ||
443 | status = host->plat->status(mmc_dev(host->mmc)); | 443 | status = host->plat->status(mmc_dev(host->mmc)); |
444 | if (status ^ host->oldstat) | 444 | if (status ^ host->oldstat) |
445 | mmc_detect_change(host->mmc); | 445 | mmc_detect_change(host->mmc, 0); |
446 | 446 | ||
447 | host->oldstat = status; | 447 | host->oldstat = status; |
448 | mod_timer(&host->timer, jiffies + HZ); | 448 | mod_timer(&host->timer, jiffies + HZ); |
diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index e99a53b09e32..b53af57074e3 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c | |||
@@ -423,7 +423,9 @@ static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs) | |||
423 | 423 | ||
424 | static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs) | 424 | static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs) |
425 | { | 425 | { |
426 | mmc_detect_change(devid); | 426 | struct pxamci_host *host = mmc_priv(devid); |
427 | |||
428 | mmc_detect_change(devid, host->pdata->detect_delay); | ||
427 | return IRQ_HANDLED; | 429 | return IRQ_HANDLED; |
428 | } | 430 | } |
429 | 431 | ||
diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index dec01d38c782..a62c86fef5cc 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c | |||
@@ -1122,7 +1122,7 @@ static void wbsd_detect_card(unsigned long data) | |||
1122 | 1122 | ||
1123 | DBG("Executing card detection\n"); | 1123 | DBG("Executing card detection\n"); |
1124 | 1124 | ||
1125 | mmc_detect_change(host->mmc); | 1125 | mmc_detect_change(host->mmc, 0); |
1126 | } | 1126 | } |
1127 | 1127 | ||
1128 | /* | 1128 | /* |
@@ -1198,7 +1198,7 @@ static void wbsd_tasklet_card(unsigned long param) | |||
1198 | */ | 1198 | */ |
1199 | spin_unlock(&host->lock); | 1199 | spin_unlock(&host->lock); |
1200 | 1200 | ||
1201 | mmc_detect_change(host->mmc); | 1201 | mmc_detect_change(host->mmc, 0); |
1202 | } | 1202 | } |
1203 | else | 1203 | else |
1204 | spin_unlock(&host->lock); | 1204 | spin_unlock(&host->lock); |
diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index 55a72c7ad001..83598e32179c 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c | |||
@@ -14,8 +14,8 @@ | |||
14 | 14 | ||
15 | #define DRV_MODULE_NAME "bnx2" | 15 | #define DRV_MODULE_NAME "bnx2" |
16 | #define PFX DRV_MODULE_NAME ": " | 16 | #define PFX DRV_MODULE_NAME ": " |
17 | #define DRV_MODULE_VERSION "1.2.20" | 17 | #define DRV_MODULE_VERSION "1.2.21" |
18 | #define DRV_MODULE_RELDATE "August 22, 2005" | 18 | #define DRV_MODULE_RELDATE "September 7, 2005" |
19 | 19 | ||
20 | #define RUN_AT(x) (jiffies + (x)) | 20 | #define RUN_AT(x) (jiffies + (x)) |
21 | 21 | ||
@@ -1533,6 +1533,7 @@ bnx2_msi(int irq, void *dev_instance, struct pt_regs *regs) | |||
1533 | struct net_device *dev = dev_instance; | 1533 | struct net_device *dev = dev_instance; |
1534 | struct bnx2 *bp = dev->priv; | 1534 | struct bnx2 *bp = dev->priv; |
1535 | 1535 | ||
1536 | prefetch(bp->status_blk); | ||
1536 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, | 1537 | REG_WR(bp, BNX2_PCICFG_INT_ACK_CMD, |
1537 | BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | | 1538 | BNX2_PCICFG_INT_ACK_CMD_USE_INT_HC_PARAM | |
1538 | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); | 1539 | BNX2_PCICFG_INT_ACK_CMD_MASK_INT); |
@@ -1558,7 +1559,7 @@ bnx2_interrupt(int irq, void *dev_instance, struct pt_regs *regs) | |||
1558 | * When using MSI, the MSI message will always complete after | 1559 | * When using MSI, the MSI message will always complete after |
1559 | * the status block write. | 1560 | * the status block write. |
1560 | */ | 1561 | */ |
1561 | if ((bp->status_blk->status_idx == bp->last_status_idx) || | 1562 | if ((bp->status_blk->status_idx == bp->last_status_idx) && |
1562 | (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & | 1563 | (REG_RD(bp, BNX2_PCICFG_MISC_STATUS) & |
1563 | BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) | 1564 | BNX2_PCICFG_MISC_STATUS_INTA_VALUE)) |
1564 | return IRQ_NONE; | 1565 | return IRQ_NONE; |
diff --git a/drivers/net/bnx2.h b/drivers/net/bnx2.h index 9ad3f5740cd8..62857b6a6ee4 100644 --- a/drivers/net/bnx2.h +++ b/drivers/net/bnx2.h | |||
@@ -50,6 +50,7 @@ | |||
50 | #endif | 50 | #endif |
51 | #include <linux/workqueue.h> | 51 | #include <linux/workqueue.h> |
52 | #include <linux/crc32.h> | 52 | #include <linux/crc32.h> |
53 | #include <linux/prefetch.h> | ||
53 | 54 | ||
54 | /* Hardware data structures and register definitions automatically | 55 | /* Hardware data structures and register definitions automatically |
55 | * generated from RTL code. Do not modify. | 56 | * generated from RTL code. Do not modify. |
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index 30a0a3d10145..5b65e208893b 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
@@ -2536,7 +2536,7 @@ static int __init serial8250_init(void) | |||
2536 | goto out; | 2536 | goto out; |
2537 | 2537 | ||
2538 | serial8250_isa_devs = platform_device_register_simple("serial8250", | 2538 | serial8250_isa_devs = platform_device_register_simple("serial8250", |
2539 | -1, NULL, 0); | 2539 | PLAT8250_DEV_LEGACY, NULL, 0); |
2540 | if (IS_ERR(serial8250_isa_devs)) { | 2540 | if (IS_ERR(serial8250_isa_devs)) { |
2541 | ret = PTR_ERR(serial8250_isa_devs); | 2541 | ret = PTR_ERR(serial8250_isa_devs); |
2542 | goto unreg; | 2542 | goto unreg; |
diff --git a/drivers/serial/8250_accent.c b/drivers/serial/8250_accent.c index 1f2c276063ef..9c10262f2469 100644 --- a/drivers/serial/8250_accent.c +++ b/drivers/serial/8250_accent.c | |||
@@ -29,7 +29,7 @@ static struct plat_serial8250_port accent_data[] = { | |||
29 | 29 | ||
30 | static struct platform_device accent_device = { | 30 | static struct platform_device accent_device = { |
31 | .name = "serial8250", | 31 | .name = "serial8250", |
32 | .id = 2, | 32 | .id = PLAT8250_DEV_ACCENT, |
33 | .dev = { | 33 | .dev = { |
34 | .platform_data = accent_data, | 34 | .platform_data = accent_data, |
35 | }, | 35 | }, |
diff --git a/drivers/serial/8250_boca.c b/drivers/serial/8250_boca.c index 465c9ea1e7a3..3bfe0f7b26fb 100644 --- a/drivers/serial/8250_boca.c +++ b/drivers/serial/8250_boca.c | |||
@@ -43,7 +43,7 @@ static struct plat_serial8250_port boca_data[] = { | |||
43 | 43 | ||
44 | static struct platform_device boca_device = { | 44 | static struct platform_device boca_device = { |
45 | .name = "serial8250", | 45 | .name = "serial8250", |
46 | .id = 3, | 46 | .id = PLAT8250_DEV_BOCA, |
47 | .dev = { | 47 | .dev = { |
48 | .platform_data = boca_data, | 48 | .platform_data = boca_data, |
49 | }, | 49 | }, |
diff --git a/drivers/serial/8250_fourport.c b/drivers/serial/8250_fourport.c index e9b4d908ef42..6375d68b7913 100644 --- a/drivers/serial/8250_fourport.c +++ b/drivers/serial/8250_fourport.c | |||
@@ -35,7 +35,7 @@ static struct plat_serial8250_port fourport_data[] = { | |||
35 | 35 | ||
36 | static struct platform_device fourport_device = { | 36 | static struct platform_device fourport_device = { |
37 | .name = "serial8250", | 37 | .name = "serial8250", |
38 | .id = 1, | 38 | .id = PLAT8250_DEV_FOURPORT, |
39 | .dev = { | 39 | .dev = { |
40 | .platform_data = fourport_data, | 40 | .platform_data = fourport_data, |
41 | }, | 41 | }, |
diff --git a/drivers/serial/8250_hub6.c b/drivers/serial/8250_hub6.c index 77f396f84b4c..daf569cd3c8f 100644 --- a/drivers/serial/8250_hub6.c +++ b/drivers/serial/8250_hub6.c | |||
@@ -40,7 +40,7 @@ static struct plat_serial8250_port hub6_data[] = { | |||
40 | 40 | ||
41 | static struct platform_device hub6_device = { | 41 | static struct platform_device hub6_device = { |
42 | .name = "serial8250", | 42 | .name = "serial8250", |
43 | .id = 4, | 43 | .id = PLAT8250_DEV_HUB6, |
44 | .dev = { | 44 | .dev = { |
45 | .platform_data = hub6_data, | 45 | .platform_data = hub6_data, |
46 | }, | 46 | }, |
diff --git a/drivers/serial/8250_mca.c b/drivers/serial/8250_mca.c index f0c40d68b8c1..ac205256d5f3 100644 --- a/drivers/serial/8250_mca.c +++ b/drivers/serial/8250_mca.c | |||
@@ -44,7 +44,7 @@ static struct plat_serial8250_port mca_data[] = { | |||
44 | 44 | ||
45 | static struct platform_device mca_device = { | 45 | static struct platform_device mca_device = { |
46 | .name = "serial8250", | 46 | .name = "serial8250", |
47 | .id = 5, | 47 | .id = PLAT8250_DEV_MCA, |
48 | .dev = { | 48 | .dev = { |
49 | .platform_data = mca_data, | 49 | .platform_data = mca_data, |
50 | }, | 50 | }, |
diff --git a/include/asm-arm/arch-pxa/hardware.h b/include/asm-arm/arch-pxa/hardware.h index 72b04d846a23..cf35721cfa45 100644 --- a/include/asm-arm/arch-pxa/hardware.h +++ b/include/asm-arm/arch-pxa/hardware.h | |||
@@ -44,24 +44,12 @@ | |||
44 | 44 | ||
45 | #ifndef __ASSEMBLY__ | 45 | #ifndef __ASSEMBLY__ |
46 | 46 | ||
47 | #if 0 | 47 | # define __REG(x) (*((volatile unsigned long *)io_p2v(x))) |
48 | # define __REG(x) (*((volatile u32 *)io_p2v(x))) | ||
49 | #else | ||
50 | /* | ||
51 | * This __REG() version gives the same results as the one above, except | ||
52 | * that we are fooling gcc somehow so it generates far better and smaller | ||
53 | * assembly code for access to contigous registers. It's a shame that gcc | ||
54 | * doesn't guess this by itself. | ||
55 | */ | ||
56 | #include <asm/types.h> | ||
57 | typedef struct { volatile u32 offset[4096]; } __regbase; | ||
58 | # define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2] | ||
59 | # define __REG(x) __REGP(io_p2v(x)) | ||
60 | #endif | ||
61 | 48 | ||
62 | /* With indexed regs we don't want to feed the index through io_p2v() | 49 | /* With indexed regs we don't want to feed the index through io_p2v() |
63 | especially if it is a variable, otherwise horrible code will result. */ | 50 | especially if it is a variable, otherwise horrible code will result. */ |
64 | # define __REG2(x,y) (*(volatile u32 *)((u32)&__REG(x) + (y))) | 51 | # define __REG2(x,y) \ |
52 | (*(volatile unsigned long *)((unsigned long)&__REG(x) + (y))) | ||
65 | 53 | ||
66 | # define __PREG(x) (io_v2p((u32)&(x))) | 54 | # define __PREG(x) (io_v2p((u32)&(x))) |
67 | 55 | ||
diff --git a/include/asm-arm/arch-pxa/i2c.h b/include/asm-arm/arch-pxa/i2c.h new file mode 100644 index 000000000000..46ec2243974a --- /dev/null +++ b/include/asm-arm/arch-pxa/i2c.h | |||
@@ -0,0 +1,70 @@ | |||
1 | /* | ||
2 | * i2c_pxa.h | ||
3 | * | ||
4 | * Copyright (C) 2002 Intrinsyc Software Inc. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | #ifndef _I2C_PXA_H_ | ||
12 | #define _I2C_PXA_H_ | ||
13 | |||
14 | #if 0 | ||
15 | #define DEF_TIMEOUT 3 | ||
16 | #else | ||
17 | /* need a longer timeout if we're dealing with the fact we may well be | ||
18 | * looking at a multi-master environment | ||
19 | */ | ||
20 | #define DEF_TIMEOUT 32 | ||
21 | #endif | ||
22 | |||
23 | #define BUS_ERROR (-EREMOTEIO) | ||
24 | #define XFER_NAKED (-ECONNREFUSED) | ||
25 | #define I2C_RETRY (-2000) /* an error has occurred retry transmit */ | ||
26 | |||
27 | /* ICR initialize bit values | ||
28 | * | ||
29 | * 15. FM 0 (100 Khz operation) | ||
30 | * 14. UR 0 (No unit reset) | ||
31 | * 13. SADIE 0 (Disables the unit from interrupting on slave addresses | ||
32 | * matching its slave address) | ||
33 | * 12. ALDIE 0 (Disables the unit from interrupt when it loses arbitration | ||
34 | * in master mode) | ||
35 | * 11. SSDIE 0 (Disables interrupts from a slave stop detected, in slave mode) | ||
36 | * 10. BEIE 1 (Enable interrupts from detected bus errors, no ACK sent) | ||
37 | * 9. IRFIE 1 (Enable interrupts from full buffer received) | ||
38 | * 8. ITEIE 1 (Enables the I2C unit to interrupt when transmit buffer empty) | ||
39 | * 7. GCD 1 (Disables i2c unit response to general call messages as a slave) | ||
40 | * 6. IUE 0 (Disable unit until we change settings) | ||
41 | * 5. SCLE 1 (Enables the i2c clock output for master mode (drives SCL) | ||
42 | * 4. MA 0 (Only send stop with the ICR stop bit) | ||
43 | * 3. TB 0 (We are not transmitting a byte initially) | ||
44 | * 2. ACKNAK 0 (Send an ACK after the unit receives a byte) | ||
45 | * 1. STOP 0 (Do not send a STOP) | ||
46 | * 0. START 0 (Do not send a START) | ||
47 | * | ||
48 | */ | ||
49 | #define I2C_ICR_INIT (ICR_BEIE | ICR_IRFIE | ICR_ITEIE | ICR_GCD | ICR_SCLE) | ||
50 | |||
51 | /* I2C status register init values | ||
52 | * | ||
53 | * 10. BED 1 (Clear bus error detected) | ||
54 | * 9. SAD 1 (Clear slave address detected) | ||
55 | * 7. IRF 1 (Clear IDBR Receive Full) | ||
56 | * 6. ITE 1 (Clear IDBR Transmit Empty) | ||
57 | * 5. ALD 1 (Clear Arbitration Loss Detected) | ||
58 | * 4. SSD 1 (Clear Slave Stop Detected) | ||
59 | */ | ||
60 | #define I2C_ISR_INIT 0x7FF /* status register init */ | ||
61 | |||
62 | struct i2c_slave_client; | ||
63 | |||
64 | struct i2c_pxa_platform_data { | ||
65 | unsigned int slave_addr; | ||
66 | struct i2c_slave_client *slave; | ||
67 | }; | ||
68 | |||
69 | extern void pxa_set_i2c_info(struct i2c_pxa_platform_data *info); | ||
70 | #endif | ||
diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h index 9718063a2119..88c17dd02ed2 100644 --- a/include/asm-arm/arch-pxa/mmc.h +++ b/include/asm-arm/arch-pxa/mmc.h | |||
@@ -9,6 +9,7 @@ struct mmc_host; | |||
9 | 9 | ||
10 | struct pxamci_platform_data { | 10 | struct pxamci_platform_data { |
11 | unsigned int ocr_mask; /* available voltages */ | 11 | unsigned int ocr_mask; /* available voltages */ |
12 | unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ | ||
12 | int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *); | 13 | int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *); |
13 | int (*get_ro)(struct device *); | 14 | int (*get_ro)(struct device *); |
14 | void (*setpower)(struct device *, unsigned int); | 15 | void (*setpower)(struct device *, unsigned int); |
diff --git a/include/asm-arm/arch-sa1100/hardware.h b/include/asm-arm/arch-sa1100/hardware.h index 10c62db34362..19c3b1e186bb 100644 --- a/include/asm-arm/arch-sa1100/hardware.h +++ b/include/asm-arm/arch-sa1100/hardware.h | |||
@@ -49,23 +49,9 @@ | |||
49 | ( (((x)&0x00ffffff) | (((x)&(0x30000000>>VIO_SHIFT))<<VIO_SHIFT)) + PIO_START ) | 49 | ( (((x)&0x00ffffff) | (((x)&(0x30000000>>VIO_SHIFT))<<VIO_SHIFT)) + PIO_START ) |
50 | 50 | ||
51 | #ifndef __ASSEMBLY__ | 51 | #ifndef __ASSEMBLY__ |
52 | #include <asm/types.h> | ||
53 | 52 | ||
54 | #if 0 | 53 | # define __REG(x) (*((volatile unsigned long *)io_p2v(x))) |
55 | # define __REG(x) (*((volatile u32 *)io_p2v(x))) | 54 | # define __PREG(x) (io_v2p((unsigned long)&(x))) |
56 | #else | ||
57 | /* | ||
58 | * This __REG() version gives the same results as the one above, except | ||
59 | * that we are fooling gcc somehow so it generates far better and smaller | ||
60 | * assembly code for access to contigous registers. It's a shame that gcc | ||
61 | * doesn't guess this by itself. | ||
62 | */ | ||
63 | typedef struct { volatile u32 offset[4096]; } __regbase; | ||
64 | # define __REGP(x) ((__regbase *)((x)&~4095))->offset[((x)&4095)>>2] | ||
65 | # define __REG(x) __REGP(io_p2v(x)) | ||
66 | #endif | ||
67 | |||
68 | # define __PREG(x) (io_v2p((u32)&(x))) | ||
69 | 55 | ||
70 | #else | 56 | #else |
71 | 57 | ||
diff --git a/include/asm-arm/cacheflush.h b/include/asm-arm/cacheflush.h index 035cdcff43d2..e81baff4f54b 100644 --- a/include/asm-arm/cacheflush.h +++ b/include/asm-arm/cacheflush.h | |||
@@ -256,7 +256,7 @@ extern void dmac_flush_range(unsigned long, unsigned long); | |||
256 | * Convert calls to our calling convention. | 256 | * Convert calls to our calling convention. |
257 | */ | 257 | */ |
258 | #define flush_cache_all() __cpuc_flush_kern_all() | 258 | #define flush_cache_all() __cpuc_flush_kern_all() |
259 | 259 | #ifndef CONFIG_CPU_CACHE_VIPT | |
260 | static inline void flush_cache_mm(struct mm_struct *mm) | 260 | static inline void flush_cache_mm(struct mm_struct *mm) |
261 | { | 261 | { |
262 | if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) | 262 | if (cpu_isset(smp_processor_id(), mm->cpu_vm_mask)) |
@@ -279,6 +279,11 @@ flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned l | |||
279 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); | 279 | __cpuc_flush_user_range(addr, addr + PAGE_SIZE, vma->vm_flags); |
280 | } | 280 | } |
281 | } | 281 | } |
282 | #else | ||
283 | extern void flush_cache_mm(struct mm_struct *mm); | ||
284 | extern void flush_cache_range(struct vm_area_struct *vma, unsigned long start, unsigned long end); | ||
285 | extern void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr, unsigned long pfn); | ||
286 | #endif | ||
282 | 287 | ||
283 | /* | 288 | /* |
284 | * flush_cache_user_range is used when we want to ensure that the | 289 | * flush_cache_user_range is used when we want to ensure that the |
diff --git a/include/linux/i2c-pxa.h b/include/linux/i2c-pxa.h new file mode 100644 index 000000000000..5f3eaf802223 --- /dev/null +++ b/include/linux/i2c-pxa.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #ifndef _LINUX_I2C_ALGO_PXA_H | ||
2 | #define _LINUX_I2C_ALGO_PXA_H | ||
3 | |||
4 | struct i2c_eeprom_emu_watcher { | ||
5 | void (*write)(void *, unsigned int addr, unsigned char newval); | ||
6 | }; | ||
7 | |||
8 | struct i2c_eeprom_emu_watch { | ||
9 | struct list_head node; | ||
10 | unsigned int start; | ||
11 | unsigned int end; | ||
12 | struct i2c_eeprom_emu_watcher *ops; | ||
13 | void *data; | ||
14 | }; | ||
15 | |||
16 | #define I2C_EEPROM_EMU_SIZE (256) | ||
17 | |||
18 | struct i2c_eeprom_emu { | ||
19 | unsigned int size; | ||
20 | unsigned int ptr; | ||
21 | unsigned int seen_start; | ||
22 | struct list_head watch; | ||
23 | |||
24 | unsigned char bytes[I2C_EEPROM_EMU_SIZE]; | ||
25 | }; | ||
26 | |||
27 | typedef enum i2c_slave_event_e { | ||
28 | I2C_SLAVE_EVENT_START_READ, | ||
29 | I2C_SLAVE_EVENT_START_WRITE, | ||
30 | I2C_SLAVE_EVENT_STOP | ||
31 | } i2c_slave_event_t; | ||
32 | |||
33 | struct i2c_slave_client { | ||
34 | void *data; | ||
35 | void (*event)(void *ptr, i2c_slave_event_t event); | ||
36 | int (*read) (void *ptr); | ||
37 | void (*write)(void *ptr, unsigned int val); | ||
38 | }; | ||
39 | |||
40 | extern int i2c_eeprom_emu_addwatcher(struct i2c_eeprom_emu *, void *data, | ||
41 | unsigned int addr, unsigned int size, | ||
42 | struct i2c_eeprom_emu_watcher *); | ||
43 | |||
44 | extern void i2c_eeprom_emu_delwatcher(struct i2c_eeprom_emu *, void *data, struct i2c_eeprom_emu_watcher *watcher); | ||
45 | |||
46 | extern struct i2c_eeprom_emu *i2c_pxa_get_eeprom(void); | ||
47 | |||
48 | #endif /* _LINUX_I2C_ALGO_PXA_H */ | ||
diff --git a/include/linux/in6.h b/include/linux/in6.h index dcf5720ffcbb..bd32b79d6295 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h | |||
@@ -148,13 +148,13 @@ struct in6_flowlabel_req | |||
148 | */ | 148 | */ |
149 | 149 | ||
150 | #define IPV6_ADDRFORM 1 | 150 | #define IPV6_ADDRFORM 1 |
151 | #define IPV6_PKTINFO 2 | 151 | #define IPV6_2292PKTINFO 2 |
152 | #define IPV6_HOPOPTS 3 | 152 | #define IPV6_2292HOPOPTS 3 |
153 | #define IPV6_DSTOPTS 4 | 153 | #define IPV6_2292DSTOPTS 4 |
154 | #define IPV6_RTHDR 5 | 154 | #define IPV6_2292RTHDR 5 |
155 | #define IPV6_PKTOPTIONS 6 | 155 | #define IPV6_2292PKTOPTIONS 6 |
156 | #define IPV6_CHECKSUM 7 | 156 | #define IPV6_CHECKSUM 7 |
157 | #define IPV6_HOPLIMIT 8 | 157 | #define IPV6_2292HOPLIMIT 8 |
158 | #define IPV6_NEXTHOP 9 | 158 | #define IPV6_NEXTHOP 9 |
159 | #define IPV6_AUTHHDR 10 /* obsolete */ | 159 | #define IPV6_AUTHHDR 10 /* obsolete */ |
160 | #define IPV6_FLOWINFO 11 | 160 | #define IPV6_FLOWINFO 11 |
@@ -198,4 +198,28 @@ struct in6_flowlabel_req | |||
198 | * MCAST_MSFILTER 48 | 198 | * MCAST_MSFILTER 48 |
199 | */ | 199 | */ |
200 | 200 | ||
201 | /* RFC3542 advanced socket options (50-67) */ | ||
202 | #define IPV6_RECVPKTINFO 50 | ||
203 | #define IPV6_PKTINFO 51 | ||
204 | #if 0 | ||
205 | #define IPV6_RECVPATHMTU 52 | ||
206 | #define IPV6_PATHMTU 53 | ||
207 | #define IPV6_DONTFRAG 54 | ||
208 | #define IPV6_USE_MIN_MTU 55 | ||
209 | #endif | ||
210 | #define IPV6_RECVHOPOPTS 56 | ||
211 | #define IPV6_HOPOPTS 57 | ||
212 | #if 0 | ||
213 | #define IPV6_RECVRTHDRDSTOPTS 58 /* Unused, see net/ipv6/datagram.c */ | ||
214 | #endif | ||
215 | #define IPV6_RTHDRDSTOPTS 59 | ||
216 | #define IPV6_RECVRTHDR 60 | ||
217 | #define IPV6_RTHDR 61 | ||
218 | #define IPV6_RECVDSTOPTS 62 | ||
219 | #define IPV6_DSTOPTS 63 | ||
220 | #define IPV6_RECVHOPLIMIT 64 | ||
221 | #define IPV6_HOPLIMIT 65 | ||
222 | #define IPV6_RECVTCLASS 66 | ||
223 | #define IPV6_TCLASS 67 | ||
224 | |||
201 | #endif | 225 | #endif |
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index 3c7dbc6a0a70..6c5f7b39a4b0 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h | |||
@@ -189,6 +189,7 @@ struct inet6_skb_parm { | |||
189 | __u16 dst0; | 189 | __u16 dst0; |
190 | __u16 srcrt; | 190 | __u16 srcrt; |
191 | __u16 dst1; | 191 | __u16 dst1; |
192 | __u16 lastopt; | ||
192 | }; | 193 | }; |
193 | 194 | ||
194 | #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) | 195 | #define IP6CB(skb) ((struct inet6_skb_parm*)((skb)->cb)) |
@@ -234,14 +235,20 @@ struct ipv6_pinfo { | |||
234 | /* pktoption flags */ | 235 | /* pktoption flags */ |
235 | union { | 236 | union { |
236 | struct { | 237 | struct { |
237 | __u8 srcrt:2, | 238 | __u16 srcrt:2, |
239 | osrcrt:2, | ||
238 | rxinfo:1, | 240 | rxinfo:1, |
241 | rxoinfo:1, | ||
239 | rxhlim:1, | 242 | rxhlim:1, |
243 | rxohlim:1, | ||
240 | hopopts:1, | 244 | hopopts:1, |
245 | ohopopts:1, | ||
241 | dstopts:1, | 246 | dstopts:1, |
242 | rxflow:1; | 247 | odstopts:1, |
248 | rxflow:1, | ||
249 | rxtclass:1; | ||
243 | } bits; | 250 | } bits; |
244 | __u8 all; | 251 | __u16 all; |
245 | } rxopt; | 252 | } rxopt; |
246 | 253 | ||
247 | /* sockopt flags */ | 254 | /* sockopt flags */ |
@@ -250,6 +257,7 @@ struct ipv6_pinfo { | |||
250 | sndflow:1, | 257 | sndflow:1, |
251 | pmtudisc:2, | 258 | pmtudisc:2, |
252 | ipv6only:1; | 259 | ipv6only:1; |
260 | __u8 tclass; | ||
253 | 261 | ||
254 | __u32 dst_cookie; | 262 | __u32 dst_cookie; |
255 | 263 | ||
@@ -263,6 +271,7 @@ struct ipv6_pinfo { | |||
263 | struct ipv6_txoptions *opt; | 271 | struct ipv6_txoptions *opt; |
264 | struct rt6_info *rt; | 272 | struct rt6_info *rt; |
265 | int hop_limit; | 273 | int hop_limit; |
274 | int tclass; | ||
266 | } cork; | 275 | } cork; |
267 | }; | 276 | }; |
268 | 277 | ||
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 6014160d9c06..c1f021eddffa 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -109,6 +109,8 @@ struct mmc_host { | |||
109 | struct mmc_card *card_selected; /* the selected MMC card */ | 109 | struct mmc_card *card_selected; /* the selected MMC card */ |
110 | 110 | ||
111 | struct work_struct detect; | 111 | struct work_struct detect; |
112 | |||
113 | unsigned long private[0] ____cacheline_aligned; | ||
112 | }; | 114 | }; |
113 | 115 | ||
114 | extern struct mmc_host *mmc_alloc_host(int extra, struct device *); | 116 | extern struct mmc_host *mmc_alloc_host(int extra, struct device *); |
@@ -116,14 +118,18 @@ extern int mmc_add_host(struct mmc_host *); | |||
116 | extern void mmc_remove_host(struct mmc_host *); | 118 | extern void mmc_remove_host(struct mmc_host *); |
117 | extern void mmc_free_host(struct mmc_host *); | 119 | extern void mmc_free_host(struct mmc_host *); |
118 | 120 | ||
119 | #define mmc_priv(x) ((void *)((x) + 1)) | 121 | static inline void *mmc_priv(struct mmc_host *host) |
122 | { | ||
123 | return (void *)host->private; | ||
124 | } | ||
125 | |||
120 | #define mmc_dev(x) ((x)->dev) | 126 | #define mmc_dev(x) ((x)->dev) |
121 | #define mmc_hostname(x) ((x)->class_dev.class_id) | 127 | #define mmc_hostname(x) ((x)->class_dev.class_id) |
122 | 128 | ||
123 | extern int mmc_suspend_host(struct mmc_host *, pm_message_t); | 129 | extern int mmc_suspend_host(struct mmc_host *, pm_message_t); |
124 | extern int mmc_resume_host(struct mmc_host *); | 130 | extern int mmc_resume_host(struct mmc_host *); |
125 | 131 | ||
126 | extern void mmc_detect_change(struct mmc_host *); | 132 | extern void mmc_detect_change(struct mmc_host *, unsigned long delay); |
127 | extern void mmc_request_done(struct mmc_host *, struct mmc_request *); | 133 | extern void mmc_request_done(struct mmc_host *, struct mmc_request *); |
128 | 134 | ||
129 | #endif | 135 | #endif |
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h index d8a023d804d4..317a979b24de 100644 --- a/include/linux/serial_8250.h +++ b/include/linux/serial_8250.h | |||
@@ -30,6 +30,21 @@ struct plat_serial8250_port { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | /* | 32 | /* |
33 | * Allocate 8250 platform device IDs. Nothing is implied by | ||
34 | * the numbering here, except for the legacy entry being -1. | ||
35 | */ | ||
36 | enum { | ||
37 | PLAT8250_DEV_LEGACY = -1, | ||
38 | PLAT8250_DEV_PLATFORM, | ||
39 | PLAT8250_DEV_PLATFORM1, | ||
40 | PLAT8250_DEV_FOURPORT, | ||
41 | PLAT8250_DEV_ACCENT, | ||
42 | PLAT8250_DEV_BOCA, | ||
43 | PLAT8250_DEV_HUB6, | ||
44 | PLAT8250_DEV_MCA, | ||
45 | }; | ||
46 | |||
47 | /* | ||
33 | * This should be used by drivers which want to register | 48 | * This should be used by drivers which want to register |
34 | * their own 8250 ports without registering their own | 49 | * their own 8250 ports without registering their own |
35 | * platform device. Using these will make your driver | 50 | * platform device. Using these will make your driver |
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 9b12fe731612..27db8da43aa4 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h | |||
@@ -401,6 +401,9 @@ uart_handle_sysrq_char(struct uart_port *port, unsigned int ch, | |||
401 | #endif | 401 | #endif |
402 | return 0; | 402 | return 0; |
403 | } | 403 | } |
404 | #ifndef SUPPORT_SYSRQ | ||
405 | #define uart_handle_sysrq_char(port,ch,regs) uart_handle_sysrq_char(port, 0, NULL) | ||
406 | #endif | ||
404 | 407 | ||
405 | /* | 408 | /* |
406 | * We do the SysRQ and SAK checking like this... | 409 | * We do the SysRQ and SAK checking like this... |
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h index da7da9c0ed1b..2741c0c55e83 100644 --- a/include/linux/skbuff.h +++ b/include/linux/skbuff.h | |||
@@ -1167,7 +1167,7 @@ static inline void skb_postpull_rcsum(struct sk_buff *skb, | |||
1167 | 1167 | ||
1168 | static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) | 1168 | static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len) |
1169 | { | 1169 | { |
1170 | if (len >= skb->len) | 1170 | if (likely(len >= skb->len)) |
1171 | return 0; | 1171 | return 0; |
1172 | if (skb->ip_summed == CHECKSUM_HW) | 1172 | if (skb->ip_summed == CHECKSUM_HW) |
1173 | skb->ip_summed = CHECKSUM_NONE; | 1173 | skb->ip_summed = CHECKSUM_NONE; |
diff --git a/include/net/ax25.h b/include/net/ax25.h index 364b046e9f47..227d3378decd 100644 --- a/include/net/ax25.h +++ b/include/net/ax25.h | |||
@@ -258,7 +258,7 @@ extern struct sock *ax25_make_new(struct sock *, struct ax25_dev *); | |||
258 | /* ax25_addr.c */ | 258 | /* ax25_addr.c */ |
259 | extern ax25_address null_ax25_address; | 259 | extern ax25_address null_ax25_address; |
260 | extern char *ax2asc(char *buf, ax25_address *); | 260 | extern char *ax2asc(char *buf, ax25_address *); |
261 | extern ax25_address *asc2ax(char *); | 261 | extern void asc2ax(ax25_address *addr, char *callsign); |
262 | extern int ax25cmp(ax25_address *, ax25_address *); | 262 | extern int ax25cmp(ax25_address *, ax25_address *); |
263 | extern int ax25digicmp(ax25_digi *, ax25_digi *); | 263 | extern int ax25digicmp(ax25_digi *, ax25_digi *); |
264 | extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *); | 264 | extern unsigned char *ax25_addr_parse(unsigned char *, int, ax25_address *, ax25_address *, ax25_digi *, int *, int *); |
diff --git a/include/net/compat.h b/include/net/compat.h index 482eb820f13a..290bab46d457 100644 --- a/include/net/compat.h +++ b/include/net/compat.h | |||
@@ -33,7 +33,8 @@ extern asmlinkage long compat_sys_sendmsg(int,struct compat_msghdr __user *,unsi | |||
33 | extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); | 33 | extern asmlinkage long compat_sys_recvmsg(int,struct compat_msghdr __user *,unsigned); |
34 | extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); | 34 | extern asmlinkage long compat_sys_getsockopt(int, int, int, char __user *, int __user *); |
35 | extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); | 35 | extern int put_cmsg_compat(struct msghdr*, int, int, int, void *); |
36 | extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, | 36 | |
37 | int); | 37 | struct sock; |
38 | extern int cmsghdr_from_user_compat_to_kern(struct msghdr *, struct sock *, unsigned char *, int); | ||
38 | 39 | ||
39 | #endif /* NET_COMPAT_H */ | 40 | #endif /* NET_COMPAT_H */ |
diff --git a/include/net/ipv6.h b/include/net/ipv6.h index 3203eaff4bd4..65ec86678a08 100644 --- a/include/net/ipv6.h +++ b/include/net/ipv6.h | |||
@@ -233,6 +233,10 @@ extern int ip6_ra_control(struct sock *sk, int sel, | |||
233 | extern int ipv6_parse_hopopts(struct sk_buff *skb, int); | 233 | extern int ipv6_parse_hopopts(struct sk_buff *skb, int); |
234 | 234 | ||
235 | extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); | 235 | extern struct ipv6_txoptions * ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt); |
236 | extern struct ipv6_txoptions * ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, | ||
237 | int newtype, | ||
238 | struct ipv6_opt_hdr __user *newopt, | ||
239 | int newoptlen); | ||
236 | 240 | ||
237 | extern int ip6_frag_nqueues; | 241 | extern int ip6_frag_nqueues; |
238 | extern atomic_t ip6_frag_mem; | 242 | extern atomic_t ip6_frag_mem; |
@@ -373,6 +377,7 @@ extern int ip6_append_data(struct sock *sk, | |||
373 | int length, | 377 | int length, |
374 | int transhdrlen, | 378 | int transhdrlen, |
375 | int hlimit, | 379 | int hlimit, |
380 | int tclass, | ||
376 | struct ipv6_txoptions *opt, | 381 | struct ipv6_txoptions *opt, |
377 | struct flowi *fl, | 382 | struct flowi *fl, |
378 | struct rt6_info *rt, | 383 | struct rt6_info *rt, |
diff --git a/include/net/transp_v6.h b/include/net/transp_v6.h index 8b075ab7a26c..4e86f2de6638 100644 --- a/include/net/transp_v6.h +++ b/include/net/transp_v6.h | |||
@@ -37,7 +37,7 @@ extern int datagram_recv_ctl(struct sock *sk, | |||
37 | extern int datagram_send_ctl(struct msghdr *msg, | 37 | extern int datagram_send_ctl(struct msghdr *msg, |
38 | struct flowi *fl, | 38 | struct flowi *fl, |
39 | struct ipv6_txoptions *opt, | 39 | struct ipv6_txoptions *opt, |
40 | int *hlimit); | 40 | int *hlimit, int *tclass); |
41 | 41 | ||
42 | #define LOOPBACK4_IPV6 __constant_htonl(0x7f000006) | 42 | #define LOOPBACK4_IPV6 __constant_htonl(0x7f000006) |
43 | 43 | ||
diff --git a/net/ax25/ax25_addr.c b/net/ax25/ax25_addr.c index dca179daf415..0164a155b8c4 100644 --- a/net/ax25/ax25_addr.c +++ b/net/ax25/ax25_addr.c | |||
@@ -67,37 +67,34 @@ char *ax2asc(char *buf, ax25_address *a) | |||
67 | /* | 67 | /* |
68 | * ascii -> ax25 conversion | 68 | * ascii -> ax25 conversion |
69 | */ | 69 | */ |
70 | ax25_address *asc2ax(char *callsign) | 70 | void asc2ax(ax25_address *addr, char *callsign) |
71 | { | 71 | { |
72 | static ax25_address addr; | ||
73 | char *s; | 72 | char *s; |
74 | int n; | 73 | int n; |
75 | 74 | ||
76 | for (s = callsign, n = 0; n < 6; n++) { | 75 | for (s = callsign, n = 0; n < 6; n++) { |
77 | if (*s != '\0' && *s != '-') | 76 | if (*s != '\0' && *s != '-') |
78 | addr.ax25_call[n] = *s++; | 77 | addr->ax25_call[n] = *s++; |
79 | else | 78 | else |
80 | addr.ax25_call[n] = ' '; | 79 | addr->ax25_call[n] = ' '; |
81 | addr.ax25_call[n] <<= 1; | 80 | addr->ax25_call[n] <<= 1; |
82 | addr.ax25_call[n] &= 0xFE; | 81 | addr->ax25_call[n] &= 0xFE; |
83 | } | 82 | } |
84 | 83 | ||
85 | if (*s++ == '\0') { | 84 | if (*s++ == '\0') { |
86 | addr.ax25_call[6] = 0x00; | 85 | addr->ax25_call[6] = 0x00; |
87 | return &addr; | 86 | return; |
88 | } | 87 | } |
89 | 88 | ||
90 | addr.ax25_call[6] = *s++ - '0'; | 89 | addr->ax25_call[6] = *s++ - '0'; |
91 | 90 | ||
92 | if (*s != '\0') { | 91 | if (*s != '\0') { |
93 | addr.ax25_call[6] *= 10; | 92 | addr->ax25_call[6] *= 10; |
94 | addr.ax25_call[6] += *s++ - '0'; | 93 | addr->ax25_call[6] += *s++ - '0'; |
95 | } | 94 | } |
96 | 95 | ||
97 | addr.ax25_call[6] <<= 1; | 96 | addr->ax25_call[6] <<= 1; |
98 | addr.ax25_call[6] &= 0x1E; | 97 | addr->ax25_call[6] &= 0x1E; |
99 | |||
100 | return &addr; | ||
101 | } | 98 | } |
102 | 99 | ||
103 | /* | 100 | /* |
diff --git a/net/ieee80211/Kconfig b/net/ieee80211/Kconfig index 58ed4319e693..91b16fbf91f0 100644 --- a/net/ieee80211/Kconfig +++ b/net/ieee80211/Kconfig | |||
@@ -1,6 +1,5 @@ | |||
1 | config IEEE80211 | 1 | config IEEE80211 |
2 | tristate "Generic IEEE 802.11 Networking Stack" | 2 | tristate "Generic IEEE 802.11 Networking Stack" |
3 | select NET_RADIO | ||
4 | ---help--- | 3 | ---help--- |
5 | This option enables the hardware independent IEEE 802.11 | 4 | This option enables the hardware independent IEEE 802.11 |
6 | networking stack. | 5 | networking stack. |
diff --git a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c index 2b5cf9c51309..bb7246683b74 100644 --- a/net/ipv4/netfilter/ip_conntrack_netbios_ns.c +++ b/net/ipv4/netfilter/ip_conntrack_netbios_ns.c | |||
@@ -104,12 +104,28 @@ out: | |||
104 | static struct ip_conntrack_helper helper = { | 104 | static struct ip_conntrack_helper helper = { |
105 | .name = "netbios-ns", | 105 | .name = "netbios-ns", |
106 | .tuple = { | 106 | .tuple = { |
107 | .src.u.udp.port = __constant_htons(137), | 107 | .src = { |
108 | .dst.protonum = IPPROTO_UDP, | 108 | .u = { |
109 | .udp = { | ||
110 | .port = __constant_htons(137), | ||
111 | } | ||
112 | } | ||
113 | }, | ||
114 | .dst = { | ||
115 | .protonum = IPPROTO_UDP, | ||
116 | }, | ||
109 | }, | 117 | }, |
110 | .mask = { | 118 | .mask = { |
111 | .src.u.udp.port = 0xFFFF, | 119 | .src = { |
112 | .dst.protonum = 0xFF, | 120 | .u = { |
121 | .udp = { | ||
122 | .port = 0xFFFF, | ||
123 | } | ||
124 | } | ||
125 | }, | ||
126 | .dst = { | ||
127 | .protonum = 0xFF, | ||
128 | }, | ||
113 | }, | 129 | }, |
114 | .max_expected = 1, | 130 | .max_expected = 1, |
115 | .me = THIS_MODULE, | 131 | .me = THIS_MODULE, |
diff --git a/net/ipv4/netfilter/ipt_REJECT.c b/net/ipv4/netfilter/ipt_REJECT.c index f115a84a4ac6..f057025a719e 100644 --- a/net/ipv4/netfilter/ipt_REJECT.c +++ b/net/ipv4/netfilter/ipt_REJECT.c | |||
@@ -92,10 +92,7 @@ static inline struct rtable *route_reverse(struct sk_buff *skb, | |||
92 | fl.fl_ip_sport = tcph->dest; | 92 | fl.fl_ip_sport = tcph->dest; |
93 | fl.fl_ip_dport = tcph->source; | 93 | fl.fl_ip_dport = tcph->source; |
94 | 94 | ||
95 | if (xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0)) { | 95 | xfrm_lookup((struct dst_entry **)&rt, &fl, NULL, 0); |
96 | dst_release(&rt->u.dst); | ||
97 | rt = NULL; | ||
98 | } | ||
99 | 96 | ||
100 | return rt; | 97 | return rt; |
101 | } | 98 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 8c0b14e3beec..8549f26e2495 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1760,6 +1760,7 @@ static inline int __mkroute_input(struct sk_buff *skb, | |||
1760 | goto cleanup; | 1760 | goto cleanup; |
1761 | } | 1761 | } |
1762 | 1762 | ||
1763 | atomic_set(&rth->u.dst.__refcnt, 1); | ||
1763 | rth->u.dst.flags= DST_HOST; | 1764 | rth->u.dst.flags= DST_HOST; |
1764 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | 1765 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED |
1765 | if (res->fi->fib_nhs > 1) | 1766 | if (res->fi->fib_nhs > 1) |
@@ -1820,7 +1821,6 @@ static inline int ip_mkroute_input_def(struct sk_buff *skb, | |||
1820 | err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth); | 1821 | err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, &rth); |
1821 | if (err) | 1822 | if (err) |
1822 | return err; | 1823 | return err; |
1823 | atomic_set(&rth->u.dst.__refcnt, 1); | ||
1824 | 1824 | ||
1825 | /* put it into the cache */ | 1825 | /* put it into the cache */ |
1826 | hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos); | 1826 | hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos); |
@@ -1834,8 +1834,8 @@ static inline int ip_mkroute_input(struct sk_buff *skb, | |||
1834 | u32 daddr, u32 saddr, u32 tos) | 1834 | u32 daddr, u32 saddr, u32 tos) |
1835 | { | 1835 | { |
1836 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | 1836 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED |
1837 | struct rtable* rth = NULL; | 1837 | struct rtable* rth = NULL, *rtres; |
1838 | unsigned char hop, hopcount, lasthop; | 1838 | unsigned char hop, hopcount; |
1839 | int err = -EINVAL; | 1839 | int err = -EINVAL; |
1840 | unsigned int hash; | 1840 | unsigned int hash; |
1841 | 1841 | ||
@@ -1844,8 +1844,6 @@ static inline int ip_mkroute_input(struct sk_buff *skb, | |||
1844 | else | 1844 | else |
1845 | hopcount = 1; | 1845 | hopcount = 1; |
1846 | 1846 | ||
1847 | lasthop = hopcount - 1; | ||
1848 | |||
1849 | /* distinguish between multipath and singlepath */ | 1847 | /* distinguish between multipath and singlepath */ |
1850 | if (hopcount < 2) | 1848 | if (hopcount < 2) |
1851 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, | 1849 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, |
@@ -1855,6 +1853,10 @@ static inline int ip_mkroute_input(struct sk_buff *skb, | |||
1855 | for (hop = 0; hop < hopcount; hop++) { | 1853 | for (hop = 0; hop < hopcount; hop++) { |
1856 | res->nh_sel = hop; | 1854 | res->nh_sel = hop; |
1857 | 1855 | ||
1856 | /* put reference to previous result */ | ||
1857 | if (hop) | ||
1858 | ip_rt_put(rtres); | ||
1859 | |||
1858 | /* create a routing cache entry */ | 1860 | /* create a routing cache entry */ |
1859 | err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, | 1861 | err = __mkroute_input(skb, res, in_dev, daddr, saddr, tos, |
1860 | &rth); | 1862 | &rth); |
@@ -1863,7 +1865,7 @@ static inline int ip_mkroute_input(struct sk_buff *skb, | |||
1863 | 1865 | ||
1864 | /* put it into the cache */ | 1866 | /* put it into the cache */ |
1865 | hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos); | 1867 | hash = rt_hash_code(daddr, saddr ^ (fl->iif << 5), tos); |
1866 | err = rt_intern_hash(hash, rth, (struct rtable**)&skb->dst); | 1868 | err = rt_intern_hash(hash, rth, &rtres); |
1867 | if (err) | 1869 | if (err) |
1868 | return err; | 1870 | return err; |
1869 | 1871 | ||
@@ -1873,13 +1875,8 @@ static inline int ip_mkroute_input(struct sk_buff *skb, | |||
1873 | FIB_RES_NETMASK(*res), | 1875 | FIB_RES_NETMASK(*res), |
1874 | res->prefixlen, | 1876 | res->prefixlen, |
1875 | &FIB_RES_NH(*res)); | 1877 | &FIB_RES_NH(*res)); |
1876 | |||
1877 | /* only for the last hop the reference count is handled | ||
1878 | * outside | ||
1879 | */ | ||
1880 | if (hop == lasthop) | ||
1881 | atomic_set(&(skb->dst->__refcnt), 1); | ||
1882 | } | 1878 | } |
1879 | skb->dst = &rtres->u.dst; | ||
1883 | return err; | 1880 | return err; |
1884 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ | 1881 | #else /* CONFIG_IP_ROUTE_MULTIPATH_CACHED */ |
1885 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos); | 1882 | return ip_mkroute_input_def(skb, res, fl, in_dev, daddr, saddr, tos); |
@@ -2208,6 +2205,7 @@ static inline int __mkroute_output(struct rtable **result, | |||
2208 | goto cleanup; | 2205 | goto cleanup; |
2209 | } | 2206 | } |
2210 | 2207 | ||
2208 | atomic_set(&rth->u.dst.__refcnt, 1); | ||
2211 | rth->u.dst.flags= DST_HOST; | 2209 | rth->u.dst.flags= DST_HOST; |
2212 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED | 2210 | #ifdef CONFIG_IP_ROUTE_MULTIPATH_CACHED |
2213 | if (res->fi) { | 2211 | if (res->fi) { |
@@ -2290,8 +2288,6 @@ static inline int ip_mkroute_output_def(struct rtable **rp, | |||
2290 | if (err == 0) { | 2288 | if (err == 0) { |
2291 | u32 tos = RT_FL_TOS(oldflp); | 2289 | u32 tos = RT_FL_TOS(oldflp); |
2292 | 2290 | ||
2293 | atomic_set(&rth->u.dst.__refcnt, 1); | ||
2294 | |||
2295 | hash = rt_hash_code(oldflp->fl4_dst, | 2291 | hash = rt_hash_code(oldflp->fl4_dst, |
2296 | oldflp->fl4_src ^ (oldflp->oif << 5), tos); | 2292 | oldflp->fl4_src ^ (oldflp->oif << 5), tos); |
2297 | err = rt_intern_hash(hash, rth, rp); | 2293 | err = rt_intern_hash(hash, rth, rp); |
@@ -2326,6 +2322,10 @@ static inline int ip_mkroute_output(struct rtable** rp, | |||
2326 | dev2nexthop = FIB_RES_DEV(*res); | 2322 | dev2nexthop = FIB_RES_DEV(*res); |
2327 | dev_hold(dev2nexthop); | 2323 | dev_hold(dev2nexthop); |
2328 | 2324 | ||
2325 | /* put reference to previous result */ | ||
2326 | if (hop) | ||
2327 | ip_rt_put(*rp); | ||
2328 | |||
2329 | err = __mkroute_output(&rth, res, fl, oldflp, | 2329 | err = __mkroute_output(&rth, res, fl, oldflp, |
2330 | dev2nexthop, flags); | 2330 | dev2nexthop, flags); |
2331 | 2331 | ||
@@ -2350,7 +2350,6 @@ static inline int ip_mkroute_output(struct rtable** rp, | |||
2350 | if (err != 0) | 2350 | if (err != 0) |
2351 | return err; | 2351 | return err; |
2352 | } | 2352 | } |
2353 | atomic_set(&(*rp)->u.dst.__refcnt, 1); | ||
2354 | return err; | 2353 | return err; |
2355 | } else { | 2354 | } else { |
2356 | return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, | 2355 | return ip_mkroute_output_def(rp, res, fl, oldflp, dev_out, |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 6094db5e11be..15e1134da1b2 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -499,7 +499,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, unsigned int mss | |||
499 | /* If this packet has been sent out already, we must | 499 | /* If this packet has been sent out already, we must |
500 | * adjust the various packet counters. | 500 | * adjust the various packet counters. |
501 | */ | 501 | */ |
502 | if (after(tp->snd_nxt, TCP_SKB_CB(buff)->end_seq)) { | 502 | if (!before(tp->snd_nxt, TCP_SKB_CB(buff)->end_seq)) { |
503 | int diff = old_factor - tcp_skb_pcount(skb) - | 503 | int diff = old_factor - tcp_skb_pcount(skb) - |
504 | tcp_skb_pcount(buff); | 504 | tcp_skb_pcount(buff); |
505 | 505 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index e5beca7de86c..e0bd1013cb0d 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -1141,7 +1141,7 @@ int udp_rcv(struct sk_buff *skb) | |||
1141 | if (ulen > len || ulen < sizeof(*uh)) | 1141 | if (ulen > len || ulen < sizeof(*uh)) |
1142 | goto short_packet; | 1142 | goto short_packet; |
1143 | 1143 | ||
1144 | if (pskb_trim(skb, ulen)) | 1144 | if (pskb_trim_rcsum(skb, ulen)) |
1145 | goto short_packet; | 1145 | goto short_packet; |
1146 | 1146 | ||
1147 | if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0) | 1147 | if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0) |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index 01468fab3d3d..cc518405b3e1 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -175,10 +175,8 @@ ipv4_connected: | |||
175 | if (final_p) | 175 | if (final_p) |
176 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 176 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
177 | 177 | ||
178 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { | 178 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
179 | dst_release(dst); | ||
180 | goto out; | 179 | goto out; |
181 | } | ||
182 | 180 | ||
183 | /* source address lookup done in ip6_dst_lookup */ | 181 | /* source address lookup done in ip6_dst_lookup */ |
184 | 182 | ||
@@ -390,32 +388,101 @@ int datagram_recv_ctl(struct sock *sk, struct msghdr *msg, struct sk_buff *skb) | |||
390 | put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); | 388 | put_cmsg(msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); |
391 | } | 389 | } |
392 | 390 | ||
391 | if (np->rxopt.bits.rxtclass) { | ||
392 | int tclass = (ntohl(*(u32 *)skb->nh.ipv6h) >> 20) & 0xff; | ||
393 | put_cmsg(msg, SOL_IPV6, IPV6_TCLASS, sizeof(tclass), &tclass); | ||
394 | } | ||
395 | |||
393 | if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { | 396 | if (np->rxopt.bits.rxflow && (*(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK)) { |
394 | u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK; | 397 | u32 flowinfo = *(u32*)skb->nh.raw & IPV6_FLOWINFO_MASK; |
395 | put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); | 398 | put_cmsg(msg, SOL_IPV6, IPV6_FLOWINFO, sizeof(flowinfo), &flowinfo); |
396 | } | 399 | } |
400 | |||
401 | /* HbH is allowed only once */ | ||
397 | if (np->rxopt.bits.hopopts && opt->hop) { | 402 | if (np->rxopt.bits.hopopts && opt->hop) { |
398 | u8 *ptr = skb->nh.raw + opt->hop; | 403 | u8 *ptr = skb->nh.raw + opt->hop; |
399 | put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); | 404 | put_cmsg(msg, SOL_IPV6, IPV6_HOPOPTS, (ptr[1]+1)<<3, ptr); |
400 | } | 405 | } |
401 | if (np->rxopt.bits.dstopts && opt->dst0) { | 406 | |
407 | if (opt->lastopt && | ||
408 | (np->rxopt.bits.dstopts || np->rxopt.bits.srcrt)) { | ||
409 | /* | ||
410 | * Silly enough, but we need to reparse in order to | ||
411 | * report extension headers (except for HbH) | ||
412 | * in order. | ||
413 | * | ||
414 | * Also note that IPV6_RECVRTHDRDSTOPTS is NOT | ||
415 | * (and WILL NOT be) defined because | ||
416 | * IPV6_RECVDSTOPTS is more generic. --yoshfuji | ||
417 | */ | ||
418 | unsigned int off = sizeof(struct ipv6hdr); | ||
419 | u8 nexthdr = skb->nh.ipv6h->nexthdr; | ||
420 | |||
421 | while (off <= opt->lastopt) { | ||
422 | unsigned len; | ||
423 | u8 *ptr = skb->nh.raw + off; | ||
424 | |||
425 | switch(nexthdr) { | ||
426 | case IPPROTO_DSTOPTS: | ||
427 | nexthdr = ptr[0]; | ||
428 | len = (ptr[1] + 1) << 3; | ||
429 | if (np->rxopt.bits.dstopts) | ||
430 | put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, len, ptr); | ||
431 | break; | ||
432 | case IPPROTO_ROUTING: | ||
433 | nexthdr = ptr[0]; | ||
434 | len = (ptr[1] + 1) << 3; | ||
435 | if (np->rxopt.bits.srcrt) | ||
436 | put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, len, ptr); | ||
437 | break; | ||
438 | case IPPROTO_AH: | ||
439 | nexthdr = ptr[0]; | ||
440 | len = (ptr[1] + 1) << 2; | ||
441 | break; | ||
442 | default: | ||
443 | nexthdr = ptr[0]; | ||
444 | len = (ptr[1] + 1) << 3; | ||
445 | break; | ||
446 | } | ||
447 | |||
448 | off += len; | ||
449 | } | ||
450 | } | ||
451 | |||
452 | /* socket options in old style */ | ||
453 | if (np->rxopt.bits.rxoinfo) { | ||
454 | struct in6_pktinfo src_info; | ||
455 | |||
456 | src_info.ipi6_ifindex = opt->iif; | ||
457 | ipv6_addr_copy(&src_info.ipi6_addr, &skb->nh.ipv6h->daddr); | ||
458 | put_cmsg(msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); | ||
459 | } | ||
460 | if (np->rxopt.bits.rxohlim) { | ||
461 | int hlim = skb->nh.ipv6h->hop_limit; | ||
462 | put_cmsg(msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); | ||
463 | } | ||
464 | if (np->rxopt.bits.ohopopts && opt->hop) { | ||
465 | u8 *ptr = skb->nh.raw + opt->hop; | ||
466 | put_cmsg(msg, SOL_IPV6, IPV6_2292HOPOPTS, (ptr[1]+1)<<3, ptr); | ||
467 | } | ||
468 | if (np->rxopt.bits.odstopts && opt->dst0) { | ||
402 | u8 *ptr = skb->nh.raw + opt->dst0; | 469 | u8 *ptr = skb->nh.raw + opt->dst0; |
403 | put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr); | 470 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); |
404 | } | 471 | } |
405 | if (np->rxopt.bits.srcrt && opt->srcrt) { | 472 | if (np->rxopt.bits.osrcrt && opt->srcrt) { |
406 | struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(skb->nh.raw + opt->srcrt); | 473 | struct ipv6_rt_hdr *rthdr = (struct ipv6_rt_hdr *)(skb->nh.raw + opt->srcrt); |
407 | put_cmsg(msg, SOL_IPV6, IPV6_RTHDR, (rthdr->hdrlen+1) << 3, rthdr); | 474 | put_cmsg(msg, SOL_IPV6, IPV6_2292RTHDR, (rthdr->hdrlen+1) << 3, rthdr); |
408 | } | 475 | } |
409 | if (np->rxopt.bits.dstopts && opt->dst1) { | 476 | if (np->rxopt.bits.odstopts && opt->dst1) { |
410 | u8 *ptr = skb->nh.raw + opt->dst1; | 477 | u8 *ptr = skb->nh.raw + opt->dst1; |
411 | put_cmsg(msg, SOL_IPV6, IPV6_DSTOPTS, (ptr[1]+1)<<3, ptr); | 478 | put_cmsg(msg, SOL_IPV6, IPV6_2292DSTOPTS, (ptr[1]+1)<<3, ptr); |
412 | } | 479 | } |
413 | return 0; | 480 | return 0; |
414 | } | 481 | } |
415 | 482 | ||
416 | int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | 483 | int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, |
417 | struct ipv6_txoptions *opt, | 484 | struct ipv6_txoptions *opt, |
418 | int *hlimit) | 485 | int *hlimit, int *tclass) |
419 | { | 486 | { |
420 | struct in6_pktinfo *src_info; | 487 | struct in6_pktinfo *src_info; |
421 | struct cmsghdr *cmsg; | 488 | struct cmsghdr *cmsg; |
@@ -438,6 +505,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
438 | 505 | ||
439 | switch (cmsg->cmsg_type) { | 506 | switch (cmsg->cmsg_type) { |
440 | case IPV6_PKTINFO: | 507 | case IPV6_PKTINFO: |
508 | case IPV6_2292PKTINFO: | ||
441 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { | 509 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct in6_pktinfo))) { |
442 | err = -EINVAL; | 510 | err = -EINVAL; |
443 | goto exit_f; | 511 | goto exit_f; |
@@ -492,6 +560,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
492 | fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg); | 560 | fl->fl6_flowlabel = IPV6_FLOWINFO_MASK & *(u32 *)CMSG_DATA(cmsg); |
493 | break; | 561 | break; |
494 | 562 | ||
563 | case IPV6_2292HOPOPTS: | ||
495 | case IPV6_HOPOPTS: | 564 | case IPV6_HOPOPTS: |
496 | if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { | 565 | if (opt->hopopt || cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { |
497 | err = -EINVAL; | 566 | err = -EINVAL; |
@@ -512,7 +581,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
512 | opt->hopopt = hdr; | 581 | opt->hopopt = hdr; |
513 | break; | 582 | break; |
514 | 583 | ||
515 | case IPV6_DSTOPTS: | 584 | case IPV6_2292DSTOPTS: |
516 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { | 585 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { |
517 | err = -EINVAL; | 586 | err = -EINVAL; |
518 | goto exit_f; | 587 | goto exit_f; |
@@ -536,6 +605,33 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
536 | opt->dst1opt = hdr; | 605 | opt->dst1opt = hdr; |
537 | break; | 606 | break; |
538 | 607 | ||
608 | case IPV6_DSTOPTS: | ||
609 | case IPV6_RTHDRDSTOPTS: | ||
610 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_opt_hdr))) { | ||
611 | err = -EINVAL; | ||
612 | goto exit_f; | ||
613 | } | ||
614 | |||
615 | hdr = (struct ipv6_opt_hdr *)CMSG_DATA(cmsg); | ||
616 | len = ((hdr->hdrlen + 1) << 3); | ||
617 | if (cmsg->cmsg_len < CMSG_LEN(len)) { | ||
618 | err = -EINVAL; | ||
619 | goto exit_f; | ||
620 | } | ||
621 | if (!capable(CAP_NET_RAW)) { | ||
622 | err = -EPERM; | ||
623 | goto exit_f; | ||
624 | } | ||
625 | if (cmsg->cmsg_type == IPV6_DSTOPTS) { | ||
626 | opt->opt_flen += len; | ||
627 | opt->dst1opt = hdr; | ||
628 | } else { | ||
629 | opt->opt_nflen += len; | ||
630 | opt->dst0opt = hdr; | ||
631 | } | ||
632 | break; | ||
633 | |||
634 | case IPV6_2292RTHDR: | ||
539 | case IPV6_RTHDR: | 635 | case IPV6_RTHDR: |
540 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) { | 636 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct ipv6_rt_hdr))) { |
541 | err = -EINVAL; | 637 | err = -EINVAL; |
@@ -568,7 +664,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
568 | opt->opt_nflen += len; | 664 | opt->opt_nflen += len; |
569 | opt->srcrt = rthdr; | 665 | opt->srcrt = rthdr; |
570 | 666 | ||
571 | if (opt->dst1opt) { | 667 | if (cmsg->cmsg_type == IPV6_2292RTHDR && opt->dst1opt) { |
572 | int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3); | 668 | int dsthdrlen = ((opt->dst1opt->hdrlen+1)<<3); |
573 | 669 | ||
574 | opt->opt_nflen += dsthdrlen; | 670 | opt->opt_nflen += dsthdrlen; |
@@ -579,6 +675,7 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
579 | 675 | ||
580 | break; | 676 | break; |
581 | 677 | ||
678 | case IPV6_2292HOPLIMIT: | ||
582 | case IPV6_HOPLIMIT: | 679 | case IPV6_HOPLIMIT: |
583 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { | 680 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { |
584 | err = -EINVAL; | 681 | err = -EINVAL; |
@@ -588,6 +685,24 @@ int datagram_send_ctl(struct msghdr *msg, struct flowi *fl, | |||
588 | *hlimit = *(int *)CMSG_DATA(cmsg); | 685 | *hlimit = *(int *)CMSG_DATA(cmsg); |
589 | break; | 686 | break; |
590 | 687 | ||
688 | case IPV6_TCLASS: | ||
689 | { | ||
690 | int tc; | ||
691 | |||
692 | err = -EINVAL; | ||
693 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(int))) { | ||
694 | goto exit_f; | ||
695 | } | ||
696 | |||
697 | tc = *(int *)CMSG_DATA(cmsg); | ||
698 | if (tc < 0 || tc > 0xff) | ||
699 | goto exit_f; | ||
700 | |||
701 | err = 0; | ||
702 | *tclass = tc; | ||
703 | |||
704 | break; | ||
705 | } | ||
591 | default: | 706 | default: |
592 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", | 707 | LIMIT_NETDEBUG(KERN_DEBUG "invalid cmsg type: %d\n", |
593 | cmsg->cmsg_type); | 708 | cmsg->cmsg_type); |
diff --git a/net/ipv6/exthdrs.c b/net/ipv6/exthdrs.c index 5be6da2584ee..47122728212a 100644 --- a/net/ipv6/exthdrs.c +++ b/net/ipv6/exthdrs.c | |||
@@ -164,6 +164,7 @@ static int ipv6_destopt_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | |||
164 | return -1; | 164 | return -1; |
165 | } | 165 | } |
166 | 166 | ||
167 | opt->lastopt = skb->h.raw - skb->nh.raw; | ||
167 | opt->dst1 = skb->h.raw - skb->nh.raw; | 168 | opt->dst1 = skb->h.raw - skb->nh.raw; |
168 | 169 | ||
169 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { | 170 | if (ip6_parse_tlv(tlvprocdestopt_lst, skb)) { |
@@ -243,6 +244,7 @@ static int ipv6_rthdr_rcv(struct sk_buff **skbp, unsigned int *nhoffp) | |||
243 | 244 | ||
244 | looped_back: | 245 | looped_back: |
245 | if (hdr->segments_left == 0) { | 246 | if (hdr->segments_left == 0) { |
247 | opt->lastopt = skb->h.raw - skb->nh.raw; | ||
246 | opt->srcrt = skb->h.raw - skb->nh.raw; | 248 | opt->srcrt = skb->h.raw - skb->nh.raw; |
247 | skb->h.raw += (hdr->hdrlen + 1) << 3; | 249 | skb->h.raw += (hdr->hdrlen + 1) << 3; |
248 | opt->dst0 = opt->dst1; | 250 | opt->dst0 = opt->dst1; |
@@ -459,11 +461,10 @@ static int ipv6_hop_jumbo(struct sk_buff *skb, int optoff) | |||
459 | IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); | 461 | IP6_INC_STATS_BH(IPSTATS_MIB_INTRUNCATEDPKTS); |
460 | goto drop; | 462 | goto drop; |
461 | } | 463 | } |
462 | if (pkt_len + sizeof(struct ipv6hdr) < skb->len) { | 464 | |
463 | __pskb_trim(skb, pkt_len + sizeof(struct ipv6hdr)); | 465 | if (pskb_trim_rcsum(skb, pkt_len + sizeof(struct ipv6hdr))) |
464 | if (skb->ip_summed == CHECKSUM_HW) | 466 | goto drop; |
465 | skb->ip_summed = CHECKSUM_NONE; | 467 | |
466 | } | ||
467 | return 1; | 468 | return 1; |
468 | 469 | ||
469 | drop: | 470 | drop: |
@@ -539,10 +540,15 @@ void ipv6_push_nfrag_opts(struct sk_buff *skb, struct ipv6_txoptions *opt, | |||
539 | u8 *proto, | 540 | u8 *proto, |
540 | struct in6_addr **daddr) | 541 | struct in6_addr **daddr) |
541 | { | 542 | { |
542 | if (opt->srcrt) | 543 | if (opt->srcrt) { |
543 | ipv6_push_rthdr(skb, proto, opt->srcrt, daddr); | 544 | ipv6_push_rthdr(skb, proto, opt->srcrt, daddr); |
544 | if (opt->dst0opt) | 545 | /* |
545 | ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt); | 546 | * IPV6_RTHDRDSTOPTS is ignored |
547 | * unless IPV6_RTHDR is set (RFC3542). | ||
548 | */ | ||
549 | if (opt->dst0opt) | ||
550 | ipv6_push_exthdr(skb, proto, NEXTHDR_DEST, opt->dst0opt); | ||
551 | } | ||
546 | if (opt->hopopt) | 552 | if (opt->hopopt) |
547 | ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt); | 553 | ipv6_push_exthdr(skb, proto, NEXTHDR_HOP, opt->hopopt); |
548 | } | 554 | } |
@@ -573,3 +579,97 @@ ipv6_dup_options(struct sock *sk, struct ipv6_txoptions *opt) | |||
573 | } | 579 | } |
574 | return opt2; | 580 | return opt2; |
575 | } | 581 | } |
582 | |||
583 | static int ipv6_renew_option(void *ohdr, | ||
584 | struct ipv6_opt_hdr __user *newopt, int newoptlen, | ||
585 | int inherit, | ||
586 | struct ipv6_opt_hdr **hdr, | ||
587 | char **p) | ||
588 | { | ||
589 | if (inherit) { | ||
590 | if (ohdr) { | ||
591 | memcpy(*p, ohdr, ipv6_optlen((struct ipv6_opt_hdr *)ohdr)); | ||
592 | *hdr = (struct ipv6_opt_hdr *)*p; | ||
593 | *p += CMSG_ALIGN(ipv6_optlen(*(struct ipv6_opt_hdr **)hdr)); | ||
594 | } | ||
595 | } else { | ||
596 | if (newopt) { | ||
597 | if (copy_from_user(*p, newopt, newoptlen)) | ||
598 | return -EFAULT; | ||
599 | *hdr = (struct ipv6_opt_hdr *)*p; | ||
600 | if (ipv6_optlen(*(struct ipv6_opt_hdr **)hdr) > newoptlen) | ||
601 | return -EINVAL; | ||
602 | *p += CMSG_ALIGN(newoptlen); | ||
603 | } | ||
604 | } | ||
605 | return 0; | ||
606 | } | ||
607 | |||
608 | struct ipv6_txoptions * | ||
609 | ipv6_renew_options(struct sock *sk, struct ipv6_txoptions *opt, | ||
610 | int newtype, | ||
611 | struct ipv6_opt_hdr __user *newopt, int newoptlen) | ||
612 | { | ||
613 | int tot_len = 0; | ||
614 | char *p; | ||
615 | struct ipv6_txoptions *opt2; | ||
616 | int err; | ||
617 | |||
618 | if (newtype != IPV6_HOPOPTS && opt->hopopt) | ||
619 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->hopopt)); | ||
620 | if (newtype != IPV6_RTHDRDSTOPTS && opt->dst0opt) | ||
621 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst0opt)); | ||
622 | if (newtype != IPV6_RTHDR && opt->srcrt) | ||
623 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->srcrt)); | ||
624 | if (newtype != IPV6_DSTOPTS && opt->dst1opt) | ||
625 | tot_len += CMSG_ALIGN(ipv6_optlen(opt->dst1opt)); | ||
626 | if (newopt && newoptlen) | ||
627 | tot_len += CMSG_ALIGN(newoptlen); | ||
628 | |||
629 | if (!tot_len) | ||
630 | return NULL; | ||
631 | |||
632 | opt2 = sock_kmalloc(sk, tot_len, GFP_ATOMIC); | ||
633 | if (!opt2) | ||
634 | return ERR_PTR(-ENOBUFS); | ||
635 | |||
636 | memset(opt2, 0, tot_len); | ||
637 | |||
638 | opt2->tot_len = tot_len; | ||
639 | p = (char *)(opt2 + 1); | ||
640 | |||
641 | err = ipv6_renew_option(opt->hopopt, newopt, newoptlen, | ||
642 | newtype != IPV6_HOPOPTS, | ||
643 | &opt2->hopopt, &p); | ||
644 | if (err) | ||
645 | goto out; | ||
646 | |||
647 | err = ipv6_renew_option(opt->dst0opt, newopt, newoptlen, | ||
648 | newtype != IPV6_RTHDRDSTOPTS, | ||
649 | &opt2->dst0opt, &p); | ||
650 | if (err) | ||
651 | goto out; | ||
652 | |||
653 | err = ipv6_renew_option(opt->srcrt, newopt, newoptlen, | ||
654 | newtype != IPV6_RTHDR, | ||
655 | (struct ipv6_opt_hdr **)opt2->srcrt, &p); | ||
656 | if (err) | ||
657 | goto out; | ||
658 | |||
659 | err = ipv6_renew_option(opt->dst1opt, newopt, newoptlen, | ||
660 | newtype != IPV6_DSTOPTS, | ||
661 | &opt2->dst1opt, &p); | ||
662 | if (err) | ||
663 | goto out; | ||
664 | |||
665 | opt2->opt_nflen = (opt2->hopopt ? ipv6_optlen(opt2->hopopt) : 0) + | ||
666 | (opt2->dst0opt ? ipv6_optlen(opt2->dst0opt) : 0) + | ||
667 | (opt2->srcrt ? ipv6_optlen(opt2->srcrt) : 0); | ||
668 | opt2->opt_flen = (opt2->dst1opt ? ipv6_optlen(opt2->dst1opt) : 0); | ||
669 | |||
670 | return opt2; | ||
671 | out: | ||
672 | sock_kfree_s(sk, p, tot_len); | ||
673 | return ERR_PTR(err); | ||
674 | } | ||
675 | |||
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index fa8f1bb0aa52..b7185fb3377c 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -287,7 +287,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
287 | int iif = 0; | 287 | int iif = 0; |
288 | int addr_type = 0; | 288 | int addr_type = 0; |
289 | int len; | 289 | int len; |
290 | int hlimit; | 290 | int hlimit, tclass; |
291 | int err = 0; | 291 | int err = 0; |
292 | 292 | ||
293 | if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail) | 293 | if ((u8*)hdr < skb->head || (u8*)(hdr+1) > skb->tail) |
@@ -374,7 +374,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
374 | if (err) | 374 | if (err) |
375 | goto out; | 375 | goto out; |
376 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | 376 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
377 | goto out_dst_release; | 377 | goto out; |
378 | 378 | ||
379 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 379 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
380 | hlimit = np->mcast_hops; | 380 | hlimit = np->mcast_hops; |
@@ -385,6 +385,10 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
385 | if (hlimit < 0) | 385 | if (hlimit < 0) |
386 | hlimit = ipv6_get_hoplimit(dst->dev); | 386 | hlimit = ipv6_get_hoplimit(dst->dev); |
387 | 387 | ||
388 | tclass = np->cork.tclass; | ||
389 | if (tclass < 0) | ||
390 | tclass = 0; | ||
391 | |||
388 | msg.skb = skb; | 392 | msg.skb = skb; |
389 | msg.offset = skb->nh.raw - skb->data; | 393 | msg.offset = skb->nh.raw - skb->data; |
390 | 394 | ||
@@ -400,7 +404,7 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info, | |||
400 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, | 404 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, |
401 | len + sizeof(struct icmp6hdr), | 405 | len + sizeof(struct icmp6hdr), |
402 | sizeof(struct icmp6hdr), | 406 | sizeof(struct icmp6hdr), |
403 | hlimit, NULL, &fl, (struct rt6_info*)dst, | 407 | hlimit, tclass, NULL, &fl, (struct rt6_info*)dst, |
404 | MSG_DONTWAIT); | 408 | MSG_DONTWAIT); |
405 | if (err) { | 409 | if (err) { |
406 | ip6_flush_pending_frames(sk); | 410 | ip6_flush_pending_frames(sk); |
@@ -434,6 +438,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
434 | struct dst_entry *dst; | 438 | struct dst_entry *dst; |
435 | int err = 0; | 439 | int err = 0; |
436 | int hlimit; | 440 | int hlimit; |
441 | int tclass; | ||
437 | 442 | ||
438 | saddr = &skb->nh.ipv6h->daddr; | 443 | saddr = &skb->nh.ipv6h->daddr; |
439 | 444 | ||
@@ -464,7 +469,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
464 | if (err) | 469 | if (err) |
465 | goto out; | 470 | goto out; |
466 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) | 471 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
467 | goto out_dst_release; | 472 | goto out; |
468 | 473 | ||
469 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 474 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
470 | hlimit = np->mcast_hops; | 475 | hlimit = np->mcast_hops; |
@@ -475,13 +480,17 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
475 | if (hlimit < 0) | 480 | if (hlimit < 0) |
476 | hlimit = ipv6_get_hoplimit(dst->dev); | 481 | hlimit = ipv6_get_hoplimit(dst->dev); |
477 | 482 | ||
483 | tclass = np->cork.tclass; | ||
484 | if (tclass < 0) | ||
485 | tclass = 0; | ||
486 | |||
478 | idev = in6_dev_get(skb->dev); | 487 | idev = in6_dev_get(skb->dev); |
479 | 488 | ||
480 | msg.skb = skb; | 489 | msg.skb = skb; |
481 | msg.offset = 0; | 490 | msg.offset = 0; |
482 | 491 | ||
483 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), | 492 | err = ip6_append_data(sk, icmpv6_getfrag, &msg, skb->len + sizeof(struct icmp6hdr), |
484 | sizeof(struct icmp6hdr), hlimit, NULL, &fl, | 493 | sizeof(struct icmp6hdr), hlimit, tclass, NULL, &fl, |
485 | (struct rt6_info*)dst, MSG_DONTWAIT); | 494 | (struct rt6_info*)dst, MSG_DONTWAIT); |
486 | 495 | ||
487 | if (err) { | 496 | if (err) { |
@@ -496,7 +505,6 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
496 | out_put: | 505 | out_put: |
497 | if (likely(idev != NULL)) | 506 | if (likely(idev != NULL)) |
498 | in6_dev_put(idev); | 507 | in6_dev_put(idev); |
499 | out_dst_release: | ||
500 | dst_release(dst); | 508 | dst_release(dst); |
501 | out: | 509 | out: |
502 | icmpv6_xmit_unlock(); | 510 | icmpv6_xmit_unlock(); |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index b6c73da5ff35..a7db762de14a 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -225,16 +225,20 @@ struct ipv6_txoptions *fl6_merge_options(struct ipv6_txoptions * opt_space, | |||
225 | struct ip6_flowlabel * fl, | 225 | struct ip6_flowlabel * fl, |
226 | struct ipv6_txoptions * fopt) | 226 | struct ipv6_txoptions * fopt) |
227 | { | 227 | { |
228 | struct ipv6_txoptions * fl_opt = fl->opt; | 228 | struct ipv6_txoptions * fl_opt = fl ? fl->opt : NULL; |
229 | 229 | ||
230 | if (fopt == NULL || fopt->opt_flen == 0) | 230 | if (fopt == NULL || fopt->opt_flen == 0) { |
231 | return fl_opt; | 231 | if (!fl_opt || !fl_opt->dst0opt || fl_opt->srcrt) |
232 | return fl_opt; | ||
233 | } | ||
232 | 234 | ||
233 | if (fl_opt != NULL) { | 235 | if (fl_opt != NULL) { |
234 | opt_space->hopopt = fl_opt->hopopt; | 236 | opt_space->hopopt = fl_opt->hopopt; |
235 | opt_space->dst0opt = fl_opt->dst0opt; | 237 | opt_space->dst0opt = fl_opt->srcrt ? fl_opt->dst0opt : NULL; |
236 | opt_space->srcrt = fl_opt->srcrt; | 238 | opt_space->srcrt = fl_opt->srcrt; |
237 | opt_space->opt_nflen = fl_opt->opt_nflen; | 239 | opt_space->opt_nflen = fl_opt->opt_nflen; |
240 | if (fl_opt->dst0opt && !fl_opt->srcrt) | ||
241 | opt_space->opt_nflen -= ipv6_optlen(fl_opt->dst0opt); | ||
238 | } else { | 242 | } else { |
239 | if (fopt->opt_nflen == 0) | 243 | if (fopt->opt_nflen == 0) |
240 | return fopt; | 244 | return fopt; |
@@ -310,7 +314,7 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int * | |||
310 | msg.msg_control = (void*)(fl->opt+1); | 314 | msg.msg_control = (void*)(fl->opt+1); |
311 | flowi.oif = 0; | 315 | flowi.oif = 0; |
312 | 316 | ||
313 | err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk); | 317 | err = datagram_send_ctl(&msg, &flowi, fl->opt, &junk, &junk); |
314 | if (err) | 318 | if (err) |
315 | goto done; | 319 | goto done; |
316 | err = -EINVAL; | 320 | err = -EINVAL; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 01ef94f7c7f1..2f589f24c093 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -166,7 +166,7 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
166 | struct ipv6hdr *hdr; | 166 | struct ipv6hdr *hdr; |
167 | u8 proto = fl->proto; | 167 | u8 proto = fl->proto; |
168 | int seg_len = skb->len; | 168 | int seg_len = skb->len; |
169 | int hlimit; | 169 | int hlimit, tclass; |
170 | u32 mtu; | 170 | u32 mtu; |
171 | 171 | ||
172 | if (opt) { | 172 | if (opt) { |
@@ -202,7 +202,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
202 | * Fill in the IPv6 header | 202 | * Fill in the IPv6 header |
203 | */ | 203 | */ |
204 | 204 | ||
205 | *(u32*)hdr = htonl(0x60000000) | fl->fl6_flowlabel; | ||
206 | hlimit = -1; | 205 | hlimit = -1; |
207 | if (np) | 206 | if (np) |
208 | hlimit = np->hop_limit; | 207 | hlimit = np->hop_limit; |
@@ -211,6 +210,14 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl, | |||
211 | if (hlimit < 0) | 210 | if (hlimit < 0) |
212 | hlimit = ipv6_get_hoplimit(dst->dev); | 211 | hlimit = ipv6_get_hoplimit(dst->dev); |
213 | 212 | ||
213 | tclass = -1; | ||
214 | if (np) | ||
215 | tclass = np->tclass; | ||
216 | if (tclass < 0) | ||
217 | tclass = 0; | ||
218 | |||
219 | *(u32 *)hdr = htonl(0x60000000 | (tclass << 20)) | fl->fl6_flowlabel; | ||
220 | |||
214 | hdr->payload_len = htons(seg_len); | 221 | hdr->payload_len = htons(seg_len); |
215 | hdr->nexthdr = proto; | 222 | hdr->nexthdr = proto; |
216 | hdr->hop_limit = hlimit; | 223 | hdr->hop_limit = hlimit; |
@@ -762,10 +769,11 @@ out_err_release: | |||
762 | return err; | 769 | return err; |
763 | } | 770 | } |
764 | 771 | ||
765 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb), | 772 | int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, |
766 | void *from, int length, int transhdrlen, | 773 | int offset, int len, int odd, struct sk_buff *skb), |
767 | int hlimit, struct ipv6_txoptions *opt, struct flowi *fl, struct rt6_info *rt, | 774 | void *from, int length, int transhdrlen, |
768 | unsigned int flags) | 775 | int hlimit, int tclass, struct ipv6_txoptions *opt, struct flowi *fl, |
776 | struct rt6_info *rt, unsigned int flags) | ||
769 | { | 777 | { |
770 | struct inet_sock *inet = inet_sk(sk); | 778 | struct inet_sock *inet = inet_sk(sk); |
771 | struct ipv6_pinfo *np = inet6_sk(sk); | 779 | struct ipv6_pinfo *np = inet6_sk(sk); |
@@ -803,6 +811,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offse | |||
803 | np->cork.rt = rt; | 811 | np->cork.rt = rt; |
804 | inet->cork.fl = *fl; | 812 | inet->cork.fl = *fl; |
805 | np->cork.hop_limit = hlimit; | 813 | np->cork.hop_limit = hlimit; |
814 | np->cork.tclass = tclass; | ||
806 | inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path); | 815 | inet->cork.fragsize = mtu = dst_mtu(rt->u.dst.path); |
807 | if (dst_allfrag(rt->u.dst.path)) | 816 | if (dst_allfrag(rt->u.dst.path)) |
808 | inet->cork.flags |= IPCORK_ALLFRAG; | 817 | inet->cork.flags |= IPCORK_ALLFRAG; |
@@ -1084,7 +1093,8 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1084 | 1093 | ||
1085 | skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); | 1094 | skb->nh.ipv6h = hdr = (struct ipv6hdr*) skb_push(skb, sizeof(struct ipv6hdr)); |
1086 | 1095 | ||
1087 | *(u32*)hdr = fl->fl6_flowlabel | htonl(0x60000000); | 1096 | *(u32*)hdr = fl->fl6_flowlabel | |
1097 | htonl(0x60000000 | ((int)np->cork.tclass << 20)); | ||
1088 | 1098 | ||
1089 | if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) | 1099 | if (skb->len <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) |
1090 | hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); | 1100 | hdr->payload_len = htons(skb->len - sizeof(struct ipv6hdr)); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 09613729404c..cf94372d1af3 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -673,11 +673,12 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
673 | 673 | ||
674 | if ((dst = ip6_tnl_dst_check(t)) != NULL) | 674 | if ((dst = ip6_tnl_dst_check(t)) != NULL) |
675 | dst_hold(dst); | 675 | dst_hold(dst); |
676 | else | 676 | else { |
677 | dst = ip6_route_output(NULL, &fl); | 677 | dst = ip6_route_output(NULL, &fl); |
678 | 678 | ||
679 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0) < 0) | 679 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0) < 0) |
680 | goto tx_err_link_failure; | 680 | goto tx_err_link_failure; |
681 | } | ||
681 | 682 | ||
682 | tdev = dst->dev; | 683 | tdev = dst->dev; |
683 | 684 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 76466af8331e..8567873d0dd8 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -210,39 +210,139 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
210 | retv = 0; | 210 | retv = 0; |
211 | break; | 211 | break; |
212 | 212 | ||
213 | case IPV6_PKTINFO: | 213 | case IPV6_RECVPKTINFO: |
214 | np->rxopt.bits.rxinfo = valbool; | 214 | np->rxopt.bits.rxinfo = valbool; |
215 | retv = 0; | 215 | retv = 0; |
216 | break; | 216 | break; |
217 | |||
218 | case IPV6_2292PKTINFO: | ||
219 | np->rxopt.bits.rxoinfo = valbool; | ||
220 | retv = 0; | ||
221 | break; | ||
217 | 222 | ||
218 | case IPV6_HOPLIMIT: | 223 | case IPV6_RECVHOPLIMIT: |
219 | np->rxopt.bits.rxhlim = valbool; | 224 | np->rxopt.bits.rxhlim = valbool; |
220 | retv = 0; | 225 | retv = 0; |
221 | break; | 226 | break; |
222 | 227 | ||
223 | case IPV6_RTHDR: | 228 | case IPV6_2292HOPLIMIT: |
229 | np->rxopt.bits.rxohlim = valbool; | ||
230 | retv = 0; | ||
231 | break; | ||
232 | |||
233 | case IPV6_RECVRTHDR: | ||
224 | if (val < 0 || val > 2) | 234 | if (val < 0 || val > 2) |
225 | goto e_inval; | 235 | goto e_inval; |
226 | np->rxopt.bits.srcrt = val; | 236 | np->rxopt.bits.srcrt = val; |
227 | retv = 0; | 237 | retv = 0; |
228 | break; | 238 | break; |
229 | 239 | ||
230 | case IPV6_HOPOPTS: | 240 | case IPV6_2292RTHDR: |
241 | if (val < 0 || val > 2) | ||
242 | goto e_inval; | ||
243 | np->rxopt.bits.osrcrt = val; | ||
244 | retv = 0; | ||
245 | break; | ||
246 | |||
247 | case IPV6_RECVHOPOPTS: | ||
231 | np->rxopt.bits.hopopts = valbool; | 248 | np->rxopt.bits.hopopts = valbool; |
232 | retv = 0; | 249 | retv = 0; |
233 | break; | 250 | break; |
234 | 251 | ||
235 | case IPV6_DSTOPTS: | 252 | case IPV6_2292HOPOPTS: |
253 | np->rxopt.bits.ohopopts = valbool; | ||
254 | retv = 0; | ||
255 | break; | ||
256 | |||
257 | case IPV6_RECVDSTOPTS: | ||
236 | np->rxopt.bits.dstopts = valbool; | 258 | np->rxopt.bits.dstopts = valbool; |
237 | retv = 0; | 259 | retv = 0; |
238 | break; | 260 | break; |
239 | 261 | ||
262 | case IPV6_2292DSTOPTS: | ||
263 | np->rxopt.bits.odstopts = valbool; | ||
264 | retv = 0; | ||
265 | break; | ||
266 | |||
267 | case IPV6_TCLASS: | ||
268 | if (val < 0 || val > 0xff) | ||
269 | goto e_inval; | ||
270 | np->tclass = val; | ||
271 | retv = 0; | ||
272 | break; | ||
273 | |||
274 | case IPV6_RECVTCLASS: | ||
275 | np->rxopt.bits.rxtclass = valbool; | ||
276 | retv = 0; | ||
277 | break; | ||
278 | |||
240 | case IPV6_FLOWINFO: | 279 | case IPV6_FLOWINFO: |
241 | np->rxopt.bits.rxflow = valbool; | 280 | np->rxopt.bits.rxflow = valbool; |
242 | retv = 0; | 281 | retv = 0; |
243 | break; | 282 | break; |
244 | 283 | ||
245 | case IPV6_PKTOPTIONS: | 284 | case IPV6_HOPOPTS: |
285 | case IPV6_RTHDRDSTOPTS: | ||
286 | case IPV6_RTHDR: | ||
287 | case IPV6_DSTOPTS: | ||
288 | { | ||
289 | struct ipv6_txoptions *opt; | ||
290 | if (optlen == 0) | ||
291 | optval = 0; | ||
292 | |||
293 | /* hop-by-hop / destination options are privileged option */ | ||
294 | retv = -EPERM; | ||
295 | if (optname != IPV6_RTHDR && !capable(CAP_NET_RAW)) | ||
296 | break; | ||
297 | |||
298 | retv = -EINVAL; | ||
299 | if (optlen & 0x7 || optlen > 8 * 255) | ||
300 | break; | ||
301 | |||
302 | opt = ipv6_renew_options(sk, np->opt, optname, | ||
303 | (struct ipv6_opt_hdr __user *)optval, | ||
304 | optlen); | ||
305 | if (IS_ERR(opt)) { | ||
306 | retv = PTR_ERR(opt); | ||
307 | break; | ||
308 | } | ||
309 | |||
310 | /* routing header option needs extra check */ | ||
311 | if (optname == IPV6_RTHDR && opt->srcrt) { | ||
312 | struct ipv6_rt_hdr *rthdr = opt->srcrt; | ||
313 | if (rthdr->type) | ||
314 | goto sticky_done; | ||
315 | if ((rthdr->hdrlen & 1) || | ||
316 | (rthdr->hdrlen >> 1) != rthdr->segments_left) | ||
317 | goto sticky_done; | ||
318 | } | ||
319 | |||
320 | retv = 0; | ||
321 | if (sk->sk_type == SOCK_STREAM) { | ||
322 | if (opt) { | ||
323 | struct tcp_sock *tp = tcp_sk(sk); | ||
324 | if (!((1 << sk->sk_state) & | ||
325 | (TCPF_LISTEN | TCPF_CLOSE)) | ||
326 | && inet_sk(sk)->daddr != LOOPBACK4_IPV6) { | ||
327 | tp->ext_header_len = opt->opt_flen + opt->opt_nflen; | ||
328 | tcp_sync_mss(sk, tp->pmtu_cookie); | ||
329 | } | ||
330 | } | ||
331 | opt = xchg(&np->opt, opt); | ||
332 | sk_dst_reset(sk); | ||
333 | } else { | ||
334 | write_lock(&sk->sk_dst_lock); | ||
335 | opt = xchg(&np->opt, opt); | ||
336 | write_unlock(&sk->sk_dst_lock); | ||
337 | sk_dst_reset(sk); | ||
338 | } | ||
339 | sticky_done: | ||
340 | if (opt) | ||
341 | sock_kfree_s(sk, opt, opt->tot_len); | ||
342 | break; | ||
343 | } | ||
344 | |||
345 | case IPV6_2292PKTOPTIONS: | ||
246 | { | 346 | { |
247 | struct ipv6_txoptions *opt = NULL; | 347 | struct ipv6_txoptions *opt = NULL; |
248 | struct msghdr msg; | 348 | struct msghdr msg; |
@@ -276,7 +376,7 @@ int ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
276 | msg.msg_controllen = optlen; | 376 | msg.msg_controllen = optlen; |
277 | msg.msg_control = (void*)(opt+1); | 377 | msg.msg_control = (void*)(opt+1); |
278 | 378 | ||
279 | retv = datagram_send_ctl(&msg, &fl, opt, &junk); | 379 | retv = datagram_send_ctl(&msg, &fl, opt, &junk, &junk); |
280 | if (retv) | 380 | if (retv) |
281 | goto done; | 381 | goto done; |
282 | update: | 382 | update: |
@@ -529,6 +629,17 @@ e_inval: | |||
529 | return -EINVAL; | 629 | return -EINVAL; |
530 | } | 630 | } |
531 | 631 | ||
632 | int ipv6_getsockopt_sticky(struct sock *sk, struct ipv6_opt_hdr *hdr, | ||
633 | char __user *optval, int len) | ||
634 | { | ||
635 | if (!hdr) | ||
636 | return 0; | ||
637 | len = min_t(int, len, ipv6_optlen(hdr)); | ||
638 | if (copy_to_user(optval, hdr, ipv6_optlen(hdr))) | ||
639 | return -EFAULT; | ||
640 | return len; | ||
641 | } | ||
642 | |||
532 | int ipv6_getsockopt(struct sock *sk, int level, int optname, | 643 | int ipv6_getsockopt(struct sock *sk, int level, int optname, |
533 | char __user *optval, int __user *optlen) | 644 | char __user *optval, int __user *optlen) |
534 | { | 645 | { |
@@ -567,7 +678,7 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
567 | return err; | 678 | return err; |
568 | } | 679 | } |
569 | 680 | ||
570 | case IPV6_PKTOPTIONS: | 681 | case IPV6_2292PKTOPTIONS: |
571 | { | 682 | { |
572 | struct msghdr msg; | 683 | struct msghdr msg; |
573 | struct sk_buff *skb; | 684 | struct sk_buff *skb; |
@@ -601,6 +712,16 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
601 | int hlim = np->mcast_hops; | 712 | int hlim = np->mcast_hops; |
602 | put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); | 713 | put_cmsg(&msg, SOL_IPV6, IPV6_HOPLIMIT, sizeof(hlim), &hlim); |
603 | } | 714 | } |
715 | if (np->rxopt.bits.rxoinfo) { | ||
716 | struct in6_pktinfo src_info; | ||
717 | src_info.ipi6_ifindex = np->mcast_oif; | ||
718 | ipv6_addr_copy(&src_info.ipi6_addr, &np->daddr); | ||
719 | put_cmsg(&msg, SOL_IPV6, IPV6_2292PKTINFO, sizeof(src_info), &src_info); | ||
720 | } | ||
721 | if (np->rxopt.bits.rxohlim) { | ||
722 | int hlim = np->mcast_hops; | ||
723 | put_cmsg(&msg, SOL_IPV6, IPV6_2292HOPLIMIT, sizeof(hlim), &hlim); | ||
724 | } | ||
604 | } | 725 | } |
605 | len -= msg.msg_controllen; | 726 | len -= msg.msg_controllen; |
606 | return put_user(len, optlen); | 727 | return put_user(len, optlen); |
@@ -625,26 +746,67 @@ int ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
625 | val = np->ipv6only; | 746 | val = np->ipv6only; |
626 | break; | 747 | break; |
627 | 748 | ||
628 | case IPV6_PKTINFO: | 749 | case IPV6_RECVPKTINFO: |
629 | val = np->rxopt.bits.rxinfo; | 750 | val = np->rxopt.bits.rxinfo; |
630 | break; | 751 | break; |
631 | 752 | ||
632 | case IPV6_HOPLIMIT: | 753 | case IPV6_2292PKTINFO: |
754 | val = np->rxopt.bits.rxoinfo; | ||
755 | break; | ||
756 | |||
757 | case IPV6_RECVHOPLIMIT: | ||
633 | val = np->rxopt.bits.rxhlim; | 758 | val = np->rxopt.bits.rxhlim; |
634 | break; | 759 | break; |
635 | 760 | ||
636 | case IPV6_RTHDR: | 761 | case IPV6_2292HOPLIMIT: |
762 | val = np->rxopt.bits.rxohlim; | ||
763 | break; | ||
764 | |||
765 | case IPV6_RECVRTHDR: | ||
637 | val = np->rxopt.bits.srcrt; | 766 | val = np->rxopt.bits.srcrt; |
638 | break; | 767 | break; |
639 | 768 | ||
769 | case IPV6_2292RTHDR: | ||
770 | val = np->rxopt.bits.osrcrt; | ||
771 | break; | ||
772 | |||
640 | case IPV6_HOPOPTS: | 773 | case IPV6_HOPOPTS: |
774 | case IPV6_RTHDRDSTOPTS: | ||
775 | case IPV6_RTHDR: | ||
776 | case IPV6_DSTOPTS: | ||
777 | { | ||
778 | |||
779 | lock_sock(sk); | ||
780 | len = ipv6_getsockopt_sticky(sk, np->opt->hopopt, | ||
781 | optval, len); | ||
782 | release_sock(sk); | ||
783 | return put_user(len, optlen); | ||
784 | } | ||
785 | |||
786 | case IPV6_RECVHOPOPTS: | ||
641 | val = np->rxopt.bits.hopopts; | 787 | val = np->rxopt.bits.hopopts; |
642 | break; | 788 | break; |
643 | 789 | ||
644 | case IPV6_DSTOPTS: | 790 | case IPV6_2292HOPOPTS: |
791 | val = np->rxopt.bits.ohopopts; | ||
792 | break; | ||
793 | |||
794 | case IPV6_RECVDSTOPTS: | ||
645 | val = np->rxopt.bits.dstopts; | 795 | val = np->rxopt.bits.dstopts; |
646 | break; | 796 | break; |
647 | 797 | ||
798 | case IPV6_2292DSTOPTS: | ||
799 | val = np->rxopt.bits.odstopts; | ||
800 | break; | ||
801 | |||
802 | case IPV6_TCLASS: | ||
803 | val = np->tclass; | ||
804 | break; | ||
805 | |||
806 | case IPV6_RECVTCLASS: | ||
807 | val = np->rxopt.bits.rxtclass; | ||
808 | break; | ||
809 | |||
648 | case IPV6_FLOWINFO: | 810 | case IPV6_FLOWINFO: |
649 | val = np->rxopt.bits.rxflow; | 811 | val = np->rxopt.bits.rxflow; |
650 | break; | 812 | break; |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index a7eae30f4554..555a31347eda 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -447,10 +447,8 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
447 | return; | 447 | return; |
448 | 448 | ||
449 | err = xfrm_lookup(&dst, &fl, NULL, 0); | 449 | err = xfrm_lookup(&dst, &fl, NULL, 0); |
450 | if (err < 0) { | 450 | if (err < 0) |
451 | dst_release(dst); | ||
452 | return; | 451 | return; |
453 | } | ||
454 | 452 | ||
455 | if (inc_opt) { | 453 | if (inc_opt) { |
456 | if (dev->addr_len) | 454 | if (dev->addr_len) |
@@ -539,10 +537,8 @@ void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | |||
539 | return; | 537 | return; |
540 | 538 | ||
541 | err = xfrm_lookup(&dst, &fl, NULL, 0); | 539 | err = xfrm_lookup(&dst, &fl, NULL, 0); |
542 | if (err < 0) { | 540 | if (err < 0) |
543 | dst_release(dst); | ||
544 | return; | 541 | return; |
545 | } | ||
546 | 542 | ||
547 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); | 543 | len = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); |
548 | send_llinfo = dev->addr_len && !ipv6_addr_any(saddr); | 544 | send_llinfo = dev->addr_len && !ipv6_addr_any(saddr); |
@@ -616,10 +612,8 @@ void ndisc_send_rs(struct net_device *dev, struct in6_addr *saddr, | |||
616 | return; | 612 | return; |
617 | 613 | ||
618 | err = xfrm_lookup(&dst, &fl, NULL, 0); | 614 | err = xfrm_lookup(&dst, &fl, NULL, 0); |
619 | if (err < 0) { | 615 | if (err < 0) |
620 | dst_release(dst); | ||
621 | return; | 616 | return; |
622 | } | ||
623 | 617 | ||
624 | len = sizeof(struct icmp6hdr); | 618 | len = sizeof(struct icmp6hdr); |
625 | if (dev->addr_len) | 619 | if (dev->addr_len) |
@@ -1353,10 +1347,8 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, | |||
1353 | return; | 1347 | return; |
1354 | 1348 | ||
1355 | err = xfrm_lookup(&dst, &fl, NULL, 0); | 1349 | err = xfrm_lookup(&dst, &fl, NULL, 0); |
1356 | if (err) { | 1350 | if (err) |
1357 | dst_release(dst); | ||
1358 | return; | 1351 | return; |
1359 | } | ||
1360 | 1352 | ||
1361 | rt = (struct rt6_info *) dst; | 1353 | rt = (struct rt6_info *) dst; |
1362 | 1354 | ||
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 14316c3ebde4..b03e87adca93 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -100,11 +100,8 @@ static void send_reset(struct sk_buff *oldskb) | |||
100 | dst = ip6_route_output(NULL, &fl); | 100 | dst = ip6_route_output(NULL, &fl); |
101 | if (dst == NULL) | 101 | if (dst == NULL) |
102 | return; | 102 | return; |
103 | if (dst->error || | 103 | if (dst->error || xfrm_lookup(&dst, &fl, NULL, 0)) |
104 | xfrm_lookup(&dst, &fl, NULL, 0)) { | ||
105 | dst_release(dst); | ||
106 | return; | 104 | return; |
107 | } | ||
108 | 105 | ||
109 | hh_len = (dst->dev->hard_header_len + 15)&~15; | 106 | hh_len = (dst->dev->hard_header_len + 15)&~15; |
110 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) | 107 | nskb = alloc_skb(hh_len + 15 + dst->header_len + sizeof(struct ipv6hdr) |
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ed3a76b30fd9..5aa3691c578d 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -655,6 +655,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
655 | struct flowi fl; | 655 | struct flowi fl; |
656 | int addr_len = msg->msg_namelen; | 656 | int addr_len = msg->msg_namelen; |
657 | int hlimit = -1; | 657 | int hlimit = -1; |
658 | int tclass = -1; | ||
658 | u16 proto; | 659 | u16 proto; |
659 | int err; | 660 | int err; |
660 | 661 | ||
@@ -740,7 +741,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
740 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 741 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
741 | opt->tot_len = sizeof(struct ipv6_txoptions); | 742 | opt->tot_len = sizeof(struct ipv6_txoptions); |
742 | 743 | ||
743 | err = datagram_send_ctl(msg, &fl, opt, &hlimit); | 744 | err = datagram_send_ctl(msg, &fl, opt, &hlimit, &tclass); |
744 | if (err < 0) { | 745 | if (err < 0) { |
745 | fl6_sock_release(flowlabel); | 746 | fl6_sock_release(flowlabel); |
746 | return err; | 747 | return err; |
@@ -755,8 +756,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
755 | } | 756 | } |
756 | if (opt == NULL) | 757 | if (opt == NULL) |
757 | opt = np->opt; | 758 | opt = np->opt; |
758 | if (flowlabel) | 759 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
759 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | ||
760 | 760 | ||
761 | fl.proto = proto; | 761 | fl.proto = proto; |
762 | rawv6_probe_proto_opt(&fl, msg); | 762 | rawv6_probe_proto_opt(&fl, msg); |
@@ -782,10 +782,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
782 | if (final_p) | 782 | if (final_p) |
783 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 783 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
784 | 784 | ||
785 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { | 785 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
786 | dst_release(dst); | ||
787 | goto out; | 786 | goto out; |
788 | } | ||
789 | 787 | ||
790 | if (hlimit < 0) { | 788 | if (hlimit < 0) { |
791 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) | 789 | if (ipv6_addr_is_multicast(&fl.fl6_dst)) |
@@ -798,6 +796,12 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
798 | hlimit = ipv6_get_hoplimit(dst->dev); | 796 | hlimit = ipv6_get_hoplimit(dst->dev); |
799 | } | 797 | } |
800 | 798 | ||
799 | if (tclass < 0) { | ||
800 | tclass = np->cork.tclass; | ||
801 | if (tclass < 0) | ||
802 | tclass = 0; | ||
803 | } | ||
804 | |||
801 | if (msg->msg_flags&MSG_CONFIRM) | 805 | if (msg->msg_flags&MSG_CONFIRM) |
802 | goto do_confirm; | 806 | goto do_confirm; |
803 | 807 | ||
@@ -806,8 +810,9 @@ back_from_confirm: | |||
806 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags); | 810 | err = rawv6_send_hdrinc(sk, msg->msg_iov, len, &fl, (struct rt6_info*)dst, msg->msg_flags); |
807 | } else { | 811 | } else { |
808 | lock_sock(sk); | 812 | lock_sock(sk); |
809 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0, | 813 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, |
810 | hlimit, opt, &fl, (struct rt6_info*)dst, msg->msg_flags); | 814 | len, 0, hlimit, tclass, opt, &fl, (struct rt6_info*)dst, |
815 | msg->msg_flags); | ||
811 | 816 | ||
812 | if (err) | 817 | if (err) |
813 | ip6_flush_pending_frames(sk); | 818 | ip6_flush_pending_frames(sk); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 9d9e04344c77..e4fe9ee484dd 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -479,12 +479,9 @@ static void ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
479 | /* Point into the IP datagram 'data' part. */ | 479 | /* Point into the IP datagram 'data' part. */ |
480 | if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) | 480 | if (!pskb_pull(skb, (u8 *) (fhdr + 1) - skb->data)) |
481 | goto err; | 481 | goto err; |
482 | if (end-offset < skb->len) { | 482 | |
483 | if (pskb_trim(skb, end - offset)) | 483 | if (pskb_trim_rcsum(skb, end - offset)) |
484 | goto err; | 484 | goto err; |
485 | if (skb->ip_summed != CHECKSUM_UNNECESSARY) | ||
486 | skb->ip_summed = CHECKSUM_NONE; | ||
487 | } | ||
488 | 485 | ||
489 | /* Find out which fragments are in front and at the back of us | 486 | /* Find out which fragments are in front and at the back of us |
490 | * in the chain of fragments so far. We must know where to put | 487 | * in the chain of fragments so far. We must know where to put |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 794734f1d230..80643e6b346b 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -632,10 +632,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
632 | if (final_p) | 632 | if (final_p) |
633 | ipv6_addr_copy(&fl.fl6_dst, final_p); | 633 | ipv6_addr_copy(&fl.fl6_dst, final_p); |
634 | 634 | ||
635 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { | 635 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) |
636 | dst_release(dst); | ||
637 | goto failure; | 636 | goto failure; |
638 | } | ||
639 | 637 | ||
640 | if (saddr == NULL) { | 638 | if (saddr == NULL) { |
641 | saddr = &fl.fl6_src; | 639 | saddr = &fl.fl6_src; |
@@ -849,7 +847,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
849 | if (dst == NULL) { | 847 | if (dst == NULL) { |
850 | opt = np->opt; | 848 | opt = np->opt; |
851 | if (opt == NULL && | 849 | if (opt == NULL && |
852 | np->rxopt.bits.srcrt == 2 && | 850 | np->rxopt.bits.osrcrt == 2 && |
853 | treq->pktopts) { | 851 | treq->pktopts) { |
854 | struct sk_buff *pktopts = treq->pktopts; | 852 | struct sk_buff *pktopts = treq->pktopts; |
855 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); | 853 | struct inet6_skb_parm *rxopt = IP6CB(pktopts); |
@@ -888,7 +886,6 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
888 | } | 886 | } |
889 | 887 | ||
890 | done: | 888 | done: |
891 | dst_release(dst); | ||
892 | if (opt && opt != np->opt) | 889 | if (opt && opt != np->opt) |
893 | sock_kfree_s(sk, opt, opt->tot_len); | 890 | sock_kfree_s(sk, opt, opt->tot_len); |
894 | return err; | 891 | return err; |
@@ -915,11 +912,10 @@ static int ipv6_opt_accepted(struct sock *sk, struct sk_buff *skb) | |||
915 | struct inet6_skb_parm *opt = IP6CB(skb); | 912 | struct inet6_skb_parm *opt = IP6CB(skb); |
916 | 913 | ||
917 | if (np->rxopt.all) { | 914 | if (np->rxopt.all) { |
918 | if ((opt->hop && np->rxopt.bits.hopopts) || | 915 | if ((opt->hop && (np->rxopt.bits.hopopts || np->rxopt.bits.ohopopts)) || |
919 | ((IPV6_FLOWINFO_MASK&*(u32*)skb->nh.raw) && | 916 | ((IPV6_FLOWINFO_MASK & *(u32*)skb->nh.raw) && np->rxopt.bits.rxflow) || |
920 | np->rxopt.bits.rxflow) || | 917 | (opt->srcrt && (np->rxopt.bits.srcrt || np->rxopt.bits.osrcrt)) || |
921 | (opt->srcrt && np->rxopt.bits.srcrt) || | 918 | ((opt->dst1 || opt->dst0) && (np->rxopt.bits.dstopts || np->rxopt.bits.odstopts))) |
922 | ((opt->dst1 || opt->dst0) && np->rxopt.bits.dstopts)) | ||
923 | return 1; | 919 | return 1; |
924 | } | 920 | } |
925 | return 0; | 921 | return 0; |
@@ -1001,10 +997,8 @@ static void tcp_v6_send_reset(struct sk_buff *skb) | |||
1001 | /* sk = NULL, but it is safe for now. RST socket required. */ | 997 | /* sk = NULL, but it is safe for now. RST socket required. */ |
1002 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 998 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { |
1003 | 999 | ||
1004 | if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) { | 1000 | if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) |
1005 | dst_release(buff->dst); | ||
1006 | return; | 1001 | return; |
1007 | } | ||
1008 | 1002 | ||
1009 | ip6_xmit(NULL, buff, &fl, NULL, 0); | 1003 | ip6_xmit(NULL, buff, &fl, NULL, 0); |
1010 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1004 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
@@ -1068,10 +1062,8 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32 | |||
1068 | fl.fl_ip_sport = t1->source; | 1062 | fl.fl_ip_sport = t1->source; |
1069 | 1063 | ||
1070 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { | 1064 | if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) { |
1071 | if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) { | 1065 | if ((xfrm_lookup(&buff->dst, &fl, NULL, 0)) < 0) |
1072 | dst_release(buff->dst); | ||
1073 | return; | 1066 | return; |
1074 | } | ||
1075 | ip6_xmit(NULL, buff, &fl, NULL, 0); | 1067 | ip6_xmit(NULL, buff, &fl, NULL, 0); |
1076 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); | 1068 | TCP_INC_STATS_BH(TCP_MIB_OUTSEGS); |
1077 | return; | 1069 | return; |
@@ -1190,8 +1182,8 @@ static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1190 | TCP_ECN_create_request(req, skb->h.th); | 1182 | TCP_ECN_create_request(req, skb->h.th); |
1191 | treq->pktopts = NULL; | 1183 | treq->pktopts = NULL; |
1192 | if (ipv6_opt_accepted(sk, skb) || | 1184 | if (ipv6_opt_accepted(sk, skb) || |
1193 | np->rxopt.bits.rxinfo || | 1185 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || |
1194 | np->rxopt.bits.rxhlim) { | 1186 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) { |
1195 | atomic_inc(&skb->users); | 1187 | atomic_inc(&skb->users); |
1196 | treq->pktopts = skb; | 1188 | treq->pktopts = skb; |
1197 | } | 1189 | } |
@@ -1288,7 +1280,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1288 | if (sk_acceptq_is_full(sk)) | 1280 | if (sk_acceptq_is_full(sk)) |
1289 | goto out_overflow; | 1281 | goto out_overflow; |
1290 | 1282 | ||
1291 | if (np->rxopt.bits.srcrt == 2 && | 1283 | if (np->rxopt.bits.osrcrt == 2 && |
1292 | opt == NULL && treq->pktopts) { | 1284 | opt == NULL && treq->pktopts) { |
1293 | struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts); | 1285 | struct inet6_skb_parm *rxopt = IP6CB(treq->pktopts); |
1294 | if (rxopt->srcrt) | 1286 | if (rxopt->srcrt) |
@@ -1544,9 +1536,9 @@ ipv6_pktoptions: | |||
1544 | tp = tcp_sk(sk); | 1536 | tp = tcp_sk(sk); |
1545 | if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt && | 1537 | if (TCP_SKB_CB(opt_skb)->end_seq == tp->rcv_nxt && |
1546 | !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { | 1538 | !((1 << sk->sk_state) & (TCPF_CLOSE | TCPF_LISTEN))) { |
1547 | if (np->rxopt.bits.rxinfo) | 1539 | if (np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo) |
1548 | np->mcast_oif = inet6_iif(opt_skb); | 1540 | np->mcast_oif = inet6_iif(opt_skb); |
1549 | if (np->rxopt.bits.rxhlim) | 1541 | if (np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim) |
1550 | np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; | 1542 | np->mcast_hops = opt_skb->nh.ipv6h->hop_limit; |
1551 | if (ipv6_opt_accepted(sk, opt_skb)) { | 1543 | if (ipv6_opt_accepted(sk, opt_skb)) { |
1552 | skb_set_owner_r(opt_skb, sk); | 1544 | skb_set_owner_r(opt_skb, sk); |
@@ -1734,7 +1726,6 @@ static int tcp_v6_rebuild_header(struct sock *sk) | |||
1734 | 1726 | ||
1735 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { | 1727 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { |
1736 | sk->sk_err_soft = -err; | 1728 | sk->sk_err_soft = -err; |
1737 | dst_release(dst); | ||
1738 | return err; | 1729 | return err; |
1739 | } | 1730 | } |
1740 | 1731 | ||
@@ -1787,7 +1778,6 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok) | |||
1787 | 1778 | ||
1788 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { | 1779 | if ((err = xfrm_lookup(&dst, &fl, sk, 0)) < 0) { |
1789 | sk->sk_route_caps = 0; | 1780 | sk->sk_route_caps = 0; |
1790 | dst_release(dst); | ||
1791 | return err; | 1781 | return err; |
1792 | } | 1782 | } |
1793 | 1783 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 390d750449ce..69b146843a20 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -483,7 +483,7 @@ static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) | |||
483 | } | 483 | } |
484 | 484 | ||
485 | if (ulen < skb->len) { | 485 | if (ulen < skb->len) { |
486 | if (__pskb_trim(skb, ulen)) | 486 | if (pskb_trim_rcsum(skb, ulen)) |
487 | goto discard; | 487 | goto discard; |
488 | saddr = &skb->nh.ipv6h->saddr; | 488 | saddr = &skb->nh.ipv6h->saddr; |
489 | daddr = &skb->nh.ipv6h->daddr; | 489 | daddr = &skb->nh.ipv6h->daddr; |
@@ -637,6 +637,7 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
637 | int addr_len = msg->msg_namelen; | 637 | int addr_len = msg->msg_namelen; |
638 | int ulen = len; | 638 | int ulen = len; |
639 | int hlimit = -1; | 639 | int hlimit = -1; |
640 | int tclass = -1; | ||
640 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 641 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
641 | int err; | 642 | int err; |
642 | 643 | ||
@@ -758,7 +759,7 @@ do_udp_sendmsg: | |||
758 | memset(opt, 0, sizeof(struct ipv6_txoptions)); | 759 | memset(opt, 0, sizeof(struct ipv6_txoptions)); |
759 | opt->tot_len = sizeof(*opt); | 760 | opt->tot_len = sizeof(*opt); |
760 | 761 | ||
761 | err = datagram_send_ctl(msg, fl, opt, &hlimit); | 762 | err = datagram_send_ctl(msg, fl, opt, &hlimit, &tclass); |
762 | if (err < 0) { | 763 | if (err < 0) { |
763 | fl6_sock_release(flowlabel); | 764 | fl6_sock_release(flowlabel); |
764 | return err; | 765 | return err; |
@@ -773,8 +774,7 @@ do_udp_sendmsg: | |||
773 | } | 774 | } |
774 | if (opt == NULL) | 775 | if (opt == NULL) |
775 | opt = np->opt; | 776 | opt = np->opt; |
776 | if (flowlabel) | 777 | opt = fl6_merge_options(&opt_space, flowlabel, opt); |
777 | opt = fl6_merge_options(&opt_space, flowlabel, opt); | ||
778 | 778 | ||
779 | fl->proto = IPPROTO_UDP; | 779 | fl->proto = IPPROTO_UDP; |
780 | ipv6_addr_copy(&fl->fl6_dst, daddr); | 780 | ipv6_addr_copy(&fl->fl6_dst, daddr); |
@@ -799,10 +799,8 @@ do_udp_sendmsg: | |||
799 | if (final_p) | 799 | if (final_p) |
800 | ipv6_addr_copy(&fl->fl6_dst, final_p); | 800 | ipv6_addr_copy(&fl->fl6_dst, final_p); |
801 | 801 | ||
802 | if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) { | 802 | if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) |
803 | dst_release(dst); | ||
804 | goto out; | 803 | goto out; |
805 | } | ||
806 | 804 | ||
807 | if (hlimit < 0) { | 805 | if (hlimit < 0) { |
808 | if (ipv6_addr_is_multicast(&fl->fl6_dst)) | 806 | if (ipv6_addr_is_multicast(&fl->fl6_dst)) |
@@ -815,6 +813,12 @@ do_udp_sendmsg: | |||
815 | hlimit = ipv6_get_hoplimit(dst->dev); | 813 | hlimit = ipv6_get_hoplimit(dst->dev); |
816 | } | 814 | } |
817 | 815 | ||
816 | if (tclass < 0) { | ||
817 | tclass = np->tclass; | ||
818 | if (tclass < 0) | ||
819 | tclass = 0; | ||
820 | } | ||
821 | |||
818 | if (msg->msg_flags&MSG_CONFIRM) | 822 | if (msg->msg_flags&MSG_CONFIRM) |
819 | goto do_confirm; | 823 | goto do_confirm; |
820 | back_from_confirm: | 824 | back_from_confirm: |
@@ -834,9 +838,10 @@ back_from_confirm: | |||
834 | 838 | ||
835 | do_append_data: | 839 | do_append_data: |
836 | up->len += ulen; | 840 | up->len += ulen; |
837 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, sizeof(struct udphdr), | 841 | err = ip6_append_data(sk, ip_generic_getfrag, msg->msg_iov, ulen, |
838 | hlimit, opt, fl, (struct rt6_info*)dst, | 842 | sizeof(struct udphdr), hlimit, tclass, opt, fl, |
839 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 843 | (struct rt6_info*)dst, |
844 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | ||
840 | if (err) | 845 | if (err) |
841 | udp_v6_flush_pending_frames(sk); | 846 | udp_v6_flush_pending_frames(sk); |
842 | else if (!corkreq) | 847 | else if (!corkreq) |
diff --git a/net/rose/rose_subr.c b/net/rose/rose_subr.c index 02891ce2db37..36a77944622b 100644 --- a/net/rose/rose_subr.c +++ b/net/rose/rose_subr.c | |||
@@ -337,13 +337,13 @@ static int rose_parse_ccitt(unsigned char *p, struct rose_facilities_struct *fac | |||
337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); | 337 | memcpy(&facilities->source_addr, p + 7, ROSE_ADDR_LEN); |
338 | memcpy(callsign, p + 12, l - 10); | 338 | memcpy(callsign, p + 12, l - 10); |
339 | callsign[l - 10] = '\0'; | 339 | callsign[l - 10] = '\0'; |
340 | facilities->source_call = *asc2ax(callsign); | 340 | asc2ax(&facilities->source_call, callsign); |
341 | } | 341 | } |
342 | if (*p == FAC_CCITT_SRC_NSAP) { | 342 | if (*p == FAC_CCITT_SRC_NSAP) { |
343 | memcpy(&facilities->dest_addr, p + 7, ROSE_ADDR_LEN); | 343 | memcpy(&facilities->dest_addr, p + 7, ROSE_ADDR_LEN); |
344 | memcpy(callsign, p + 12, l - 10); | 344 | memcpy(callsign, p + 12, l - 10); |
345 | callsign[l - 10] = '\0'; | 345 | callsign[l - 10] = '\0'; |
346 | facilities->dest_call = *asc2ax(callsign); | 346 | asc2ax(&facilities->dest_call, callsign); |
347 | } | 347 | } |
348 | p += l + 2; | 348 | p += l + 2; |
349 | n += l + 2; | 349 | n += l + 2; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 83c8135e1764..fda737d77edc 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -765,8 +765,8 @@ restart: | |||
765 | switch (policy->action) { | 765 | switch (policy->action) { |
766 | case XFRM_POLICY_BLOCK: | 766 | case XFRM_POLICY_BLOCK: |
767 | /* Prohibit the flow */ | 767 | /* Prohibit the flow */ |
768 | xfrm_pol_put(policy); | 768 | err = -EPERM; |
769 | return -EPERM; | 769 | goto error; |
770 | 770 | ||
771 | case XFRM_POLICY_ALLOW: | 771 | case XFRM_POLICY_ALLOW: |
772 | if (policy->xfrm_nr == 0) { | 772 | if (policy->xfrm_nr == 0) { |
@@ -782,8 +782,8 @@ restart: | |||
782 | */ | 782 | */ |
783 | dst = xfrm_find_bundle(fl, policy, family); | 783 | dst = xfrm_find_bundle(fl, policy, family); |
784 | if (IS_ERR(dst)) { | 784 | if (IS_ERR(dst)) { |
785 | xfrm_pol_put(policy); | 785 | err = PTR_ERR(dst); |
786 | return PTR_ERR(dst); | 786 | goto error; |
787 | } | 787 | } |
788 | 788 | ||
789 | if (dst) | 789 | if (dst) |