diff options
| author | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
|---|---|---|
| committer | Jonathan Herman <hermanjl@cs.unc.edu> | 2013-01-17 16:15:55 -0500 |
| commit | 8dea78da5cee153b8af9c07a2745f6c55057fe12 (patch) | |
| tree | a8f4d49d63b1ecc92f2fddceba0655b2472c5bd9 /drivers/char | |
| parent | 406089d01562f1e2bf9f089fd7637009ebaad589 (diff) | |
Patched in Tegra support.
Diffstat (limited to 'drivers/char')
95 files changed, 1662 insertions, 5518 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 72bedad6bf8..b2aec046996 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -6,6 +6,19 @@ menu "Character devices" | |||
| 6 | 6 | ||
| 7 | source "drivers/tty/Kconfig" | 7 | source "drivers/tty/Kconfig" |
| 8 | 8 | ||
| 9 | config DEVMEM | ||
| 10 | bool "Memory device driver" | ||
| 11 | default y | ||
| 12 | help | ||
| 13 | The memory driver provides two character devices, mem and kmem, which | ||
| 14 | provide access to the system's memory. The mem device is a view of | ||
| 15 | physical memory, and each byte in the device corresponds to the | ||
| 16 | matching physical address. The kmem device is the same as mem, but | ||
| 17 | the addresses correspond to the kernel's virtual address space rather | ||
| 18 | than physical memory. These devices are standard parts of a Linux | ||
| 19 | system and most users should say Y here. You might say N if very | ||
| 20 | security conscience or memory is tight. | ||
| 21 | |||
| 9 | config DEVKMEM | 22 | config DEVKMEM |
| 10 | bool "/dev/kmem virtual device support" | 23 | bool "/dev/kmem virtual device support" |
| 11 | default y | 24 | default y |
| @@ -66,6 +79,21 @@ config TTY_PRINTK | |||
| 66 | 79 | ||
| 67 | If unsure, say N. | 80 | If unsure, say N. |
| 68 | 81 | ||
| 82 | config BRIQ_PANEL | ||
| 83 | tristate 'Total Impact briQ front panel driver' | ||
| 84 | depends on PPC_CHRP | ||
| 85 | ---help--- | ||
| 86 | The briQ is a small footprint CHRP computer with a frontpanel VFD, a | ||
| 87 | tristate led and two switches. It is the size of a CDROM drive. | ||
| 88 | |||
| 89 | If you have such one and want anything showing on the VFD then you | ||
| 90 | must answer Y here. | ||
| 91 | |||
| 92 | To compile this driver as a module, choose M here: the | ||
| 93 | module will be called briq_panel. | ||
| 94 | |||
| 95 | It's safe to say N here. | ||
| 96 | |||
| 69 | config BFIN_OTP | 97 | config BFIN_OTP |
| 70 | tristate "Blackfin On-Chip OTP Memory Support" | 98 | tristate "Blackfin On-Chip OTP Memory Support" |
| 71 | depends on BLACKFIN && (BF51x || BF52x || BF54x) | 99 | depends on BLACKFIN && (BF51x || BF52x || BF54x) |
| @@ -283,7 +311,7 @@ if RTC_LIB=n | |||
| 283 | config RTC | 311 | config RTC |
| 284 | tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" | 312 | tristate "Enhanced Real Time Clock Support (legacy PC RTC driver)" |
| 285 | depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \ | 313 | depends on !PPC && !PARISC && !IA64 && !M68K && !SPARC && !FRV \ |
| 286 | && !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN && !UML | 314 | && !ARM && !SUPERH && !S390 && !AVR32 && !BLACKFIN |
| 287 | ---help--- | 315 | ---help--- |
| 288 | If you say Y here and create a character special file /dev/rtc with | 316 | If you say Y here and create a character special file /dev/rtc with |
| 289 | major number 10 and minor number 135 using mknod ("man mknod"), you | 317 | major number 10 and minor number 135 using mknod ("man mknod"), you |
| @@ -331,7 +359,7 @@ config JS_RTC | |||
| 331 | 359 | ||
| 332 | config GEN_RTC | 360 | config GEN_RTC |
| 333 | tristate "Generic /dev/rtc emulation" | 361 | tristate "Generic /dev/rtc emulation" |
| 334 | depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN && !UML | 362 | depends on RTC!=y && !IA64 && !ARM && !M32R && !MIPS && !SPARC && !FRV && !S390 && !SUPERH && !AVR32 && !BLACKFIN |
| 335 | ---help--- | 363 | ---help--- |
| 336 | If you say Y here and create a character special file /dev/rtc with | 364 | If you say Y here and create a character special file /dev/rtc with |
| 337 | major number 10 and minor number 135 using mknod ("man mknod"), you | 365 | major number 10 and minor number 135 using mknod ("man mknod"), you |
| @@ -418,8 +446,8 @@ config APPLICOM | |||
| 418 | If unsure, say N. | 446 | If unsure, say N. |
| 419 | 447 | ||
| 420 | config SONYPI | 448 | config SONYPI |
| 421 | tristate "Sony Vaio Programmable I/O Control Device support" | 449 | tristate "Sony Vaio Programmable I/O Control Device support (EXPERIMENTAL)" |
| 422 | depends on X86 && PCI && INPUT && !64BIT | 450 | depends on EXPERIMENTAL && X86 && PCI && INPUT && !64BIT |
| 423 | ---help--- | 451 | ---help--- |
| 424 | This driver enables access to the Sony Programmable I/O Control | 452 | This driver enables access to the Sony Programmable I/O Control |
| 425 | Device which can be found in many (all ?) Sony Vaio laptops. | 453 | Device which can be found in many (all ?) Sony Vaio laptops. |
| @@ -475,7 +503,7 @@ config SCx200_GPIO | |||
| 475 | 503 | ||
| 476 | config PC8736x_GPIO | 504 | config PC8736x_GPIO |
| 477 | tristate "NatSemi PC8736x GPIO Support" | 505 | tristate "NatSemi PC8736x GPIO Support" |
| 478 | depends on X86_32 && !UML | 506 | depends on X86_32 |
| 479 | default SCx200_GPIO # mostly N | 507 | default SCx200_GPIO # mostly N |
| 480 | select NSC_GPIO # needed for support routines | 508 | select NSC_GPIO # needed for support routines |
| 481 | help | 509 | help |
| @@ -566,7 +594,7 @@ source "drivers/char/tpm/Kconfig" | |||
| 566 | 594 | ||
| 567 | config TELCLOCK | 595 | config TELCLOCK |
| 568 | tristate "Telecom clock driver for ATCA SBC" | 596 | tristate "Telecom clock driver for ATCA SBC" |
| 569 | depends on X86 | 597 | depends on EXPERIMENTAL && X86 |
| 570 | default n | 598 | default n |
| 571 | help | 599 | help |
| 572 | The telecom clock device is specific to the MPCBL0010 and MPCBL0050 | 600 | The telecom clock device is specific to the MPCBL0010 and MPCBL0050 |
| @@ -583,8 +611,20 @@ config DEVPORT | |||
| 583 | depends on ISA || PCI | 611 | depends on ISA || PCI |
| 584 | default y | 612 | default y |
| 585 | 613 | ||
| 614 | config DCC_TTY | ||
| 615 | tristate "DCC tty driver" | ||
| 616 | depends on ARM | ||
| 617 | |||
| 586 | source "drivers/s390/char/Kconfig" | 618 | source "drivers/s390/char/Kconfig" |
| 587 | 619 | ||
| 620 | config RAMOOPS | ||
| 621 | tristate "Log panic/oops to a RAM buffer" | ||
| 622 | depends on HAS_IOMEM | ||
| 623 | default n | ||
| 624 | help | ||
| 625 | This enables panic and oops messages to be logged to a circular | ||
| 626 | buffer in RAM where it can be read back at some later point. | ||
| 627 | |||
| 588 | config MSM_SMD_PKT | 628 | config MSM_SMD_PKT |
| 589 | bool "Enable device interface for some SMD packet ports" | 629 | bool "Enable device interface for some SMD packet ports" |
| 590 | default n | 630 | default n |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 7ff1d0d208a..5e2fd709702 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
| @@ -16,6 +16,7 @@ obj-$(CONFIG_UV_MMTIMER) += uv_mmtimer.o | |||
| 16 | obj-$(CONFIG_VIOTAPE) += viotape.o | 16 | obj-$(CONFIG_VIOTAPE) += viotape.o |
| 17 | obj-$(CONFIG_IBM_BSR) += bsr.o | 17 | obj-$(CONFIG_IBM_BSR) += bsr.o |
| 18 | obj-$(CONFIG_SGI_MBCS) += mbcs.o | 18 | obj-$(CONFIG_SGI_MBCS) += mbcs.o |
| 19 | obj-$(CONFIG_BRIQ_PANEL) += briq_panel.o | ||
| 19 | obj-$(CONFIG_BFIN_OTP) += bfin-otp.o | 20 | obj-$(CONFIG_BFIN_OTP) += bfin-otp.o |
| 20 | 21 | ||
| 21 | obj-$(CONFIG_PRINTER) += lp.o | 22 | obj-$(CONFIG_PRINTER) += lp.o |
| @@ -52,11 +53,14 @@ obj-$(CONFIG_TELCLOCK) += tlclk.o | |||
| 52 | obj-$(CONFIG_MWAVE) += mwave/ | 53 | obj-$(CONFIG_MWAVE) += mwave/ |
| 53 | obj-$(CONFIG_AGP) += agp/ | 54 | obj-$(CONFIG_AGP) += agp/ |
| 54 | obj-$(CONFIG_PCMCIA) += pcmcia/ | 55 | obj-$(CONFIG_PCMCIA) += pcmcia/ |
| 56 | obj-$(CONFIG_IPMI_HANDLER) += ipmi/ | ||
| 55 | 57 | ||
| 56 | obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o | 58 | obj-$(CONFIG_HANGCHECK_TIMER) += hangcheck-timer.o |
| 57 | obj-$(CONFIG_TCG_TPM) += tpm/ | 59 | obj-$(CONFIG_TCG_TPM) += tpm/ |
| 58 | 60 | ||
| 61 | obj-$(CONFIG_DCC_TTY) += dcc_tty.o | ||
| 59 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o | 62 | obj-$(CONFIG_PS3_FLASH) += ps3flash.o |
| 63 | obj-$(CONFIG_RAMOOPS) += ramoops.o | ||
| 60 | 64 | ||
| 61 | obj-$(CONFIG_JS_RTC) += js-rtc.o | 65 | obj-$(CONFIG_JS_RTC) += js-rtc.o |
| 62 | js-rtc-y = rtc.o | 66 | js-rtc-y = rtc.o |
diff --git a/drivers/char/agp/ali-agp.c b/drivers/char/agp/ali-agp.c index 443cd6751ca..fd793519ea2 100644 --- a/drivers/char/agp/ali-agp.c +++ b/drivers/char/agp/ali-agp.c | |||
| @@ -249,7 +249,7 @@ static const struct agp_bridge_driver ali_m1541_bridge = { | |||
| 249 | }; | 249 | }; |
| 250 | 250 | ||
| 251 | 251 | ||
| 252 | static struct agp_device_ids ali_agp_device_ids[] = | 252 | static struct agp_device_ids ali_agp_device_ids[] __devinitdata = |
| 253 | { | 253 | { |
| 254 | { | 254 | { |
| 255 | .device_id = PCI_DEVICE_ID_AL_M1541, | 255 | .device_id = PCI_DEVICE_ID_AL_M1541, |
| @@ -299,7 +299,8 @@ static struct agp_device_ids ali_agp_device_ids[] = | |||
| 299 | { }, /* dummy final entry, always present */ | 299 | { }, /* dummy final entry, always present */ |
| 300 | }; | 300 | }; |
| 301 | 301 | ||
| 302 | static int agp_ali_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 302 | static int __devinit agp_ali_probe(struct pci_dev *pdev, |
| 303 | const struct pci_device_id *ent) | ||
| 303 | { | 304 | { |
| 304 | struct agp_device_ids *devs = ali_agp_device_ids; | 305 | struct agp_device_ids *devs = ali_agp_device_ids; |
| 305 | struct agp_bridge_data *bridge; | 306 | struct agp_bridge_data *bridge; |
| @@ -373,7 +374,7 @@ found: | |||
| 373 | return agp_add_bridge(bridge); | 374 | return agp_add_bridge(bridge); |
| 374 | } | 375 | } |
| 375 | 376 | ||
| 376 | static void agp_ali_remove(struct pci_dev *pdev) | 377 | static void __devexit agp_ali_remove(struct pci_dev *pdev) |
| 377 | { | 378 | { |
| 378 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 379 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 379 | 380 | ||
diff --git a/drivers/char/agp/amd-k7-agp.c b/drivers/char/agp/amd-k7-agp.c index 779f0ab845a..f7e88787af9 100644 --- a/drivers/char/agp/amd-k7-agp.c +++ b/drivers/char/agp/amd-k7-agp.c | |||
| @@ -388,7 +388,7 @@ static const struct agp_bridge_driver amd_irongate_driver = { | |||
| 388 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 388 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
| 389 | }; | 389 | }; |
| 390 | 390 | ||
| 391 | static struct agp_device_ids amd_agp_device_ids[] = | 391 | static struct agp_device_ids amd_agp_device_ids[] __devinitdata = |
| 392 | { | 392 | { |
| 393 | { | 393 | { |
| 394 | .device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006, | 394 | .device_id = PCI_DEVICE_ID_AMD_FE_GATE_7006, |
| @@ -405,8 +405,8 @@ static struct agp_device_ids amd_agp_device_ids[] = | |||
| 405 | { }, /* dummy final entry, always present */ | 405 | { }, /* dummy final entry, always present */ |
| 406 | }; | 406 | }; |
| 407 | 407 | ||
| 408 | static int agp_amdk7_probe(struct pci_dev *pdev, | 408 | static int __devinit agp_amdk7_probe(struct pci_dev *pdev, |
| 409 | const struct pci_device_id *ent) | 409 | const struct pci_device_id *ent) |
| 410 | { | 410 | { |
| 411 | struct agp_bridge_data *bridge; | 411 | struct agp_bridge_data *bridge; |
| 412 | u8 cap_ptr; | 412 | u8 cap_ptr; |
| @@ -480,7 +480,7 @@ static int agp_amdk7_probe(struct pci_dev *pdev, | |||
| 480 | return agp_add_bridge(bridge); | 480 | return agp_add_bridge(bridge); |
| 481 | } | 481 | } |
| 482 | 482 | ||
| 483 | static void agp_amdk7_remove(struct pci_dev *pdev) | 483 | static void __devexit agp_amdk7_remove(struct pci_dev *pdev) |
| 484 | { | 484 | { |
| 485 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 485 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 486 | 486 | ||
diff --git a/drivers/char/agp/amd64-agp.c b/drivers/char/agp/amd64-agp.c index d79d692d05b..780498d7658 100644 --- a/drivers/char/agp/amd64-agp.c +++ b/drivers/char/agp/amd64-agp.c | |||
| @@ -33,7 +33,7 @@ | |||
| 33 | #define ULI_X86_64_ENU_SCR_REG 0x54 | 33 | #define ULI_X86_64_ENU_SCR_REG 0x54 |
| 34 | 34 | ||
| 35 | static struct resource *aperture_resource; | 35 | static struct resource *aperture_resource; |
| 36 | static bool __initdata agp_try_unsupported = 1; | 36 | static int __initdata agp_try_unsupported = 1; |
| 37 | static int agp_bridges_found; | 37 | static int agp_bridges_found; |
| 38 | 38 | ||
| 39 | static void amd64_tlbflush(struct agp_memory *temp) | 39 | static void amd64_tlbflush(struct agp_memory *temp) |
| @@ -240,7 +240,7 @@ static const struct agp_bridge_driver amd_8151_driver = { | |||
| 240 | }; | 240 | }; |
| 241 | 241 | ||
| 242 | /* Some basic sanity checks for the aperture. */ | 242 | /* Some basic sanity checks for the aperture. */ |
| 243 | static int agp_aperture_valid(u64 aper, u32 size) | 243 | static int __devinit agp_aperture_valid(u64 aper, u32 size) |
| 244 | { | 244 | { |
| 245 | if (!aperture_valid(aper, size, 32*1024*1024)) | 245 | if (!aperture_valid(aper, size, 32*1024*1024)) |
| 246 | return 0; | 246 | return 0; |
| @@ -267,7 +267,8 @@ static int agp_aperture_valid(u64 aper, u32 size) | |||
| 267 | * to allocate that much memory. But at least error out cleanly instead of | 267 | * to allocate that much memory. But at least error out cleanly instead of |
| 268 | * crashing. | 268 | * crashing. |
| 269 | */ | 269 | */ |
| 270 | static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap) | 270 | static __devinit int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, |
| 271 | u16 cap) | ||
| 271 | { | 272 | { |
| 272 | u32 aper_low, aper_hi; | 273 | u32 aper_low, aper_hi; |
| 273 | u64 aper, nb_aper; | 274 | u64 aper, nb_aper; |
| @@ -325,7 +326,7 @@ static int fix_northbridge(struct pci_dev *nb, struct pci_dev *agp, u16 cap) | |||
| 325 | return 0; | 326 | return 0; |
| 326 | } | 327 | } |
| 327 | 328 | ||
| 328 | static int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) | 329 | static __devinit int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) |
| 329 | { | 330 | { |
| 330 | int i; | 331 | int i; |
| 331 | 332 | ||
| @@ -351,7 +352,7 @@ static int cache_nbs(struct pci_dev *pdev, u32 cap_ptr) | |||
| 351 | } | 352 | } |
| 352 | 353 | ||
| 353 | /* Handle AMD 8151 quirks */ | 354 | /* Handle AMD 8151 quirks */ |
| 354 | static void amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) | 355 | static void __devinit amd8151_init(struct pci_dev *pdev, struct agp_bridge_data *bridge) |
| 355 | { | 356 | { |
| 356 | char *revstring; | 357 | char *revstring; |
| 357 | 358 | ||
| @@ -389,7 +390,7 @@ static const struct aper_size_info_32 uli_sizes[7] = | |||
| 389 | {8, 2048, 1, 4}, | 390 | {8, 2048, 1, 4}, |
| 390 | {4, 1024, 0, 3} | 391 | {4, 1024, 0, 3} |
| 391 | }; | 392 | }; |
| 392 | static int uli_agp_init(struct pci_dev *pdev) | 393 | static int __devinit uli_agp_init(struct pci_dev *pdev) |
| 393 | { | 394 | { |
| 394 | u32 httfea,baseaddr,enuscr; | 395 | u32 httfea,baseaddr,enuscr; |
| 395 | struct pci_dev *dev1; | 396 | struct pci_dev *dev1; |
| @@ -512,8 +513,8 @@ put: | |||
| 512 | return ret; | 513 | return ret; |
| 513 | } | 514 | } |
| 514 | 515 | ||
| 515 | static int agp_amd64_probe(struct pci_dev *pdev, | 516 | static int __devinit agp_amd64_probe(struct pci_dev *pdev, |
| 516 | const struct pci_device_id *ent) | 517 | const struct pci_device_id *ent) |
| 517 | { | 518 | { |
| 518 | struct agp_bridge_data *bridge; | 519 | struct agp_bridge_data *bridge; |
| 519 | u8 cap_ptr; | 520 | u8 cap_ptr; |
| @@ -578,7 +579,7 @@ static int agp_amd64_probe(struct pci_dev *pdev, | |||
| 578 | return 0; | 579 | return 0; |
| 579 | } | 580 | } |
| 580 | 581 | ||
| 581 | static void agp_amd64_remove(struct pci_dev *pdev) | 582 | static void __devexit agp_amd64_remove(struct pci_dev *pdev) |
| 582 | { | 583 | { |
| 583 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 584 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 584 | 585 | ||
diff --git a/drivers/char/agp/ati-agp.c b/drivers/char/agp/ati-agp.c index 0628d7b65c7..dc30e224349 100644 --- a/drivers/char/agp/ati-agp.c +++ b/drivers/char/agp/ati-agp.c | |||
| @@ -445,7 +445,7 @@ static const struct agp_bridge_driver ati_generic_bridge = { | |||
| 445 | }; | 445 | }; |
| 446 | 446 | ||
| 447 | 447 | ||
| 448 | static struct agp_device_ids ati_agp_device_ids[] = | 448 | static struct agp_device_ids ati_agp_device_ids[] __devinitdata = |
| 449 | { | 449 | { |
| 450 | { | 450 | { |
| 451 | .device_id = PCI_DEVICE_ID_ATI_RS100, | 451 | .device_id = PCI_DEVICE_ID_ATI_RS100, |
| @@ -490,7 +490,8 @@ static struct agp_device_ids ati_agp_device_ids[] = | |||
| 490 | { }, /* dummy final entry, always present */ | 490 | { }, /* dummy final entry, always present */ |
| 491 | }; | 491 | }; |
| 492 | 492 | ||
| 493 | static int agp_ati_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 493 | static int __devinit agp_ati_probe(struct pci_dev *pdev, |
| 494 | const struct pci_device_id *ent) | ||
| 494 | { | 495 | { |
| 495 | struct agp_device_ids *devs = ati_agp_device_ids; | 496 | struct agp_device_ids *devs = ati_agp_device_ids; |
| 496 | struct agp_bridge_data *bridge; | 497 | struct agp_bridge_data *bridge; |
| @@ -532,7 +533,7 @@ found: | |||
| 532 | return agp_add_bridge(bridge); | 533 | return agp_add_bridge(bridge); |
| 533 | } | 534 | } |
| 534 | 535 | ||
| 535 | static void agp_ati_remove(struct pci_dev *pdev) | 536 | static void __devexit agp_ati_remove(struct pci_dev *pdev) |
| 536 | { | 537 | { |
| 537 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 538 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 538 | 539 | ||
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c index 317c28ce832..f27d0d0816d 100644 --- a/drivers/char/agp/backend.c +++ b/drivers/char/agp/backend.c | |||
| @@ -171,7 +171,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
| 171 | } | 171 | } |
| 172 | got_gatt = 1; | 172 | got_gatt = 1; |
| 173 | 173 | ||
| 174 | bridge->key_list = vzalloc(PAGE_SIZE * 4); | 174 | bridge->key_list = vmalloc(PAGE_SIZE * 4); |
| 175 | if (bridge->key_list == NULL) { | 175 | if (bridge->key_list == NULL) { |
| 176 | dev_err(&bridge->dev->dev, | 176 | dev_err(&bridge->dev->dev, |
| 177 | "can't allocate memory for key lists\n"); | 177 | "can't allocate memory for key lists\n"); |
| @@ -181,6 +181,7 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
| 181 | got_keylist = 1; | 181 | got_keylist = 1; |
| 182 | 182 | ||
| 183 | /* FIXME vmalloc'd memory not guaranteed contiguous */ | 183 | /* FIXME vmalloc'd memory not guaranteed contiguous */ |
| 184 | memset(bridge->key_list, 0, PAGE_SIZE * 4); | ||
| 184 | 185 | ||
| 185 | if (bridge->driver->configure()) { | 186 | if (bridge->driver->configure()) { |
| 186 | dev_err(&bridge->dev->dev, "error configuring host chipset\n"); | 187 | dev_err(&bridge->dev->dev, "error configuring host chipset\n"); |
| @@ -194,10 +195,10 @@ static int agp_backend_initialize(struct agp_bridge_data *bridge) | |||
| 194 | 195 | ||
| 195 | err_out: | 196 | err_out: |
| 196 | if (bridge->driver->needs_scratch_page) { | 197 | if (bridge->driver->needs_scratch_page) { |
| 197 | struct page *page = bridge->scratch_page_page; | 198 | void *va = page_address(bridge->scratch_page_page); |
| 198 | 199 | ||
| 199 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); | 200 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); |
| 200 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); | 201 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); |
| 201 | } | 202 | } |
| 202 | if (got_gatt) | 203 | if (got_gatt) |
| 203 | bridge->driver->free_gatt_table(bridge); | 204 | bridge->driver->free_gatt_table(bridge); |
| @@ -221,10 +222,10 @@ static void agp_backend_cleanup(struct agp_bridge_data *bridge) | |||
| 221 | 222 | ||
| 222 | if (bridge->driver->agp_destroy_page && | 223 | if (bridge->driver->agp_destroy_page && |
| 223 | bridge->driver->needs_scratch_page) { | 224 | bridge->driver->needs_scratch_page) { |
| 224 | struct page *page = bridge->scratch_page_page; | 225 | void *va = page_address(bridge->scratch_page_page); |
| 225 | 226 | ||
| 226 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_UNMAP); | 227 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_UNMAP); |
| 227 | bridge->driver->agp_destroy_page(page, AGP_PAGE_DESTROY_FREE); | 228 | bridge->driver->agp_destroy_page(va, AGP_PAGE_DESTROY_FREE); |
| 228 | } | 229 | } |
| 229 | } | 230 | } |
| 230 | 231 | ||
diff --git a/drivers/char/agp/efficeon-agp.c b/drivers/char/agp/efficeon-agp.c index 6974d503205..d607f53d8af 100644 --- a/drivers/char/agp/efficeon-agp.c +++ b/drivers/char/agp/efficeon-agp.c | |||
| @@ -343,8 +343,8 @@ static const struct agp_bridge_driver efficeon_driver = { | |||
| 343 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 343 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
| 344 | }; | 344 | }; |
| 345 | 345 | ||
| 346 | static int agp_efficeon_probe(struct pci_dev *pdev, | 346 | static int __devinit agp_efficeon_probe(struct pci_dev *pdev, |
| 347 | const struct pci_device_id *ent) | 347 | const struct pci_device_id *ent) |
| 348 | { | 348 | { |
| 349 | struct agp_bridge_data *bridge; | 349 | struct agp_bridge_data *bridge; |
| 350 | u8 cap_ptr; | 350 | u8 cap_ptr; |
| @@ -407,7 +407,7 @@ static int agp_efficeon_probe(struct pci_dev *pdev, | |||
| 407 | return agp_add_bridge(bridge); | 407 | return agp_add_bridge(bridge); |
| 408 | } | 408 | } |
| 409 | 409 | ||
| 410 | static void agp_efficeon_remove(struct pci_dev *pdev) | 410 | static void __devexit agp_efficeon_remove(struct pci_dev *pdev) |
| 411 | { | 411 | { |
| 412 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 412 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 413 | 413 | ||
diff --git a/drivers/char/agp/generic.c b/drivers/char/agp/generic.c index a0df182f6f7..b072648dc3f 100644 --- a/drivers/char/agp/generic.c +++ b/drivers/char/agp/generic.c | |||
| @@ -514,12 +514,12 @@ static void agp_v2_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ | |||
| 514 | switch (*bridge_agpstat & 7) { | 514 | switch (*bridge_agpstat & 7) { |
| 515 | case 4: | 515 | case 4: |
| 516 | *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X); | 516 | *bridge_agpstat |= (AGPSTAT2_2X | AGPSTAT2_1X); |
| 517 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate. " | 517 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x4 rate" |
| 518 | "Fixing up support for x2 & x1\n"); | 518 | "Fixing up support for x2 & x1\n"); |
| 519 | break; | 519 | break; |
| 520 | case 2: | 520 | case 2: |
| 521 | *bridge_agpstat |= AGPSTAT2_1X; | 521 | *bridge_agpstat |= AGPSTAT2_1X; |
| 522 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate. " | 522 | printk(KERN_INFO PFX "BIOS bug. AGP bridge claims to only support x2 rate" |
| 523 | "Fixing up support for x1\n"); | 523 | "Fixing up support for x1\n"); |
| 524 | break; | 524 | break; |
| 525 | default: | 525 | default: |
| @@ -693,7 +693,7 @@ static void agp_v3_parse_one(u32 *requested_mode, u32 *bridge_agpstat, u32 *vga_ | |||
| 693 | *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); | 693 | *bridge_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); |
| 694 | *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); | 694 | *vga_agpstat &= ~(AGPSTAT3_4X | AGPSTAT3_RSVD); |
| 695 | } else { | 695 | } else { |
| 696 | printk(KERN_INFO PFX "Fell back to AGPx4 mode because "); | 696 | printk(KERN_INFO PFX "Fell back to AGPx4 mode because"); |
| 697 | if (!(*bridge_agpstat & AGPSTAT3_8X)) { | 697 | if (!(*bridge_agpstat & AGPSTAT3_8X)) { |
| 698 | printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n", | 698 | printk(KERN_INFO PFX "bridge couldn't do x8. bridge_agpstat:%x (orig=%x)\n", |
| 699 | *bridge_agpstat, origbridge); | 699 | *bridge_agpstat, origbridge); |
| @@ -956,9 +956,9 @@ int agp_generic_create_gatt_table(struct agp_bridge_data *bridge) | |||
| 956 | bridge->driver->cache_flush(); | 956 | bridge->driver->cache_flush(); |
| 957 | #ifdef CONFIG_X86 | 957 | #ifdef CONFIG_X86 |
| 958 | if (set_memory_uc((unsigned long)table, 1 << page_order)) | 958 | if (set_memory_uc((unsigned long)table, 1 << page_order)) |
| 959 | printk(KERN_WARNING "Could not set GATT table memory to UC!\n"); | 959 | printk(KERN_WARNING "Could not set GATT table memory to UC!"); |
| 960 | 960 | ||
| 961 | bridge->gatt_table = (u32 __iomem *)table; | 961 | bridge->gatt_table = (void *)table; |
| 962 | #else | 962 | #else |
| 963 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), | 963 | bridge->gatt_table = ioremap_nocache(virt_to_phys(table), |
| 964 | (PAGE_SIZE * (1 << page_order))); | 964 | (PAGE_SIZE * (1 << page_order))); |
| @@ -1010,6 +1010,7 @@ int agp_generic_free_gatt_table(struct agp_bridge_data *bridge) | |||
| 1010 | case LVL2_APER_SIZE: | 1010 | case LVL2_APER_SIZE: |
| 1011 | /* The generic routines can't deal with 2 level gatt's */ | 1011 | /* The generic routines can't deal with 2 level gatt's */ |
| 1012 | return -EINVAL; | 1012 | return -EINVAL; |
| 1013 | break; | ||
| 1013 | default: | 1014 | default: |
| 1014 | page_order = 0; | 1015 | page_order = 0; |
| 1015 | break; | 1016 | break; |
| @@ -1076,6 +1077,7 @@ int agp_generic_insert_memory(struct agp_memory * mem, off_t pg_start, int type) | |||
| 1076 | case LVL2_APER_SIZE: | 1077 | case LVL2_APER_SIZE: |
| 1077 | /* The generic routines can't deal with 2 level gatt's */ | 1078 | /* The generic routines can't deal with 2 level gatt's */ |
| 1078 | return -EINVAL; | 1079 | return -EINVAL; |
| 1080 | break; | ||
| 1079 | default: | 1081 | default: |
| 1080 | num_entries = 0; | 1082 | num_entries = 0; |
| 1081 | break; | 1083 | break; |
diff --git a/drivers/char/agp/hp-agp.c b/drivers/char/agp/hp-agp.c index 3695773ce7c..056b289a1e8 100644 --- a/drivers/char/agp/hp-agp.c +++ b/drivers/char/agp/hp-agp.c | |||
| @@ -336,8 +336,7 @@ hp_zx1_insert_memory (struct agp_memory *mem, off_t pg_start, int type) | |||
| 336 | off_t j, io_pg_start; | 336 | off_t j, io_pg_start; |
| 337 | int io_pg_count; | 337 | int io_pg_count; |
| 338 | 338 | ||
| 339 | if (type != mem->type || | 339 | if (type != 0 || mem->type != 0) { |
| 340 | agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) { | ||
| 341 | return -EINVAL; | 340 | return -EINVAL; |
| 342 | } | 341 | } |
| 343 | 342 | ||
| @@ -381,8 +380,7 @@ hp_zx1_remove_memory (struct agp_memory *mem, off_t pg_start, int type) | |||
| 381 | struct _hp_private *hp = &hp_private; | 380 | struct _hp_private *hp = &hp_private; |
| 382 | int i, io_pg_start, io_pg_count; | 381 | int i, io_pg_start, io_pg_count; |
| 383 | 382 | ||
| 384 | if (type != mem->type || | 383 | if (type != 0 || mem->type != 0) { |
| 385 | agp_bridge->driver->agp_type_to_mask_type(agp_bridge, type)) { | ||
| 386 | return -EINVAL; | 384 | return -EINVAL; |
| 387 | } | 385 | } |
| 388 | 386 | ||
diff --git a/drivers/char/agp/i460-agp.c b/drivers/char/agp/i460-agp.c index 15b240ea484..75b763cb3ea 100644 --- a/drivers/char/agp/i460-agp.c +++ b/drivers/char/agp/i460-agp.c | |||
| @@ -587,8 +587,8 @@ const struct agp_bridge_driver intel_i460_driver = { | |||
| 587 | .cant_use_aperture = true, | 587 | .cant_use_aperture = true, |
| 588 | }; | 588 | }; |
| 589 | 589 | ||
| 590 | static int agp_intel_i460_probe(struct pci_dev *pdev, | 590 | static int __devinit agp_intel_i460_probe(struct pci_dev *pdev, |
| 591 | const struct pci_device_id *ent) | 591 | const struct pci_device_id *ent) |
| 592 | { | 592 | { |
| 593 | struct agp_bridge_data *bridge; | 593 | struct agp_bridge_data *bridge; |
| 594 | u8 cap_ptr; | 594 | u8 cap_ptr; |
| @@ -611,7 +611,7 @@ static int agp_intel_i460_probe(struct pci_dev *pdev, | |||
| 611 | return agp_add_bridge(bridge); | 611 | return agp_add_bridge(bridge); |
| 612 | } | 612 | } |
| 613 | 613 | ||
| 614 | static void agp_intel_i460_remove(struct pci_dev *pdev) | 614 | static void __devexit agp_intel_i460_remove(struct pci_dev *pdev) |
| 615 | { | 615 | { |
| 616 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 616 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 617 | 617 | ||
| @@ -637,7 +637,7 @@ static struct pci_driver agp_intel_i460_pci_driver = { | |||
| 637 | .name = "agpgart-intel-i460", | 637 | .name = "agpgart-intel-i460", |
| 638 | .id_table = agp_intel_i460_pci_table, | 638 | .id_table = agp_intel_i460_pci_table, |
| 639 | .probe = agp_intel_i460_probe, | 639 | .probe = agp_intel_i460_probe, |
| 640 | .remove = agp_intel_i460_remove, | 640 | .remove = __devexit_p(agp_intel_i460_remove), |
| 641 | }; | 641 | }; |
| 642 | 642 | ||
| 643 | static int __init agp_intel_i460_init(void) | 643 | static int __init agp_intel_i460_init(void) |
diff --git a/drivers/char/agp/intel-agp.c b/drivers/char/agp/intel-agp.c index a426ee1f57a..b427711be4b 100644 --- a/drivers/char/agp/intel-agp.c +++ b/drivers/char/agp/intel-agp.c | |||
| @@ -12,7 +12,6 @@ | |||
| 12 | #include <asm/smp.h> | 12 | #include <asm/smp.h> |
| 13 | #include "agp.h" | 13 | #include "agp.h" |
| 14 | #include "intel-agp.h" | 14 | #include "intel-agp.h" |
| 15 | #include <drm/intel-gtt.h> | ||
| 16 | 15 | ||
| 17 | int intel_agp_enabled; | 16 | int intel_agp_enabled; |
| 18 | EXPORT_SYMBOL(intel_agp_enabled); | 17 | EXPORT_SYMBOL(intel_agp_enabled); |
| @@ -732,8 +731,8 @@ static const struct intel_agp_driver_description { | |||
| 732 | { 0, NULL, NULL } | 731 | { 0, NULL, NULL } |
| 733 | }; | 732 | }; |
| 734 | 733 | ||
| 735 | static int agp_intel_probe(struct pci_dev *pdev, | 734 | static int __devinit agp_intel_probe(struct pci_dev *pdev, |
| 736 | const struct pci_device_id *ent) | 735 | const struct pci_device_id *ent) |
| 737 | { | 736 | { |
| 738 | struct agp_bridge_data *bridge; | 737 | struct agp_bridge_data *bridge; |
| 739 | u8 cap_ptr = 0; | 738 | u8 cap_ptr = 0; |
| @@ -748,7 +747,7 @@ static int agp_intel_probe(struct pci_dev *pdev, | |||
| 748 | 747 | ||
| 749 | bridge->capndx = cap_ptr; | 748 | bridge->capndx = cap_ptr; |
| 750 | 749 | ||
| 751 | if (intel_gmch_probe(pdev, NULL, bridge)) | 750 | if (intel_gmch_probe(pdev, bridge)) |
| 752 | goto found_gmch; | 751 | goto found_gmch; |
| 753 | 752 | ||
| 754 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { | 753 | for (i = 0; intel_agp_chipsets[i].name != NULL; i++) { |
| @@ -819,13 +818,13 @@ found_gmch: | |||
| 819 | return err; | 818 | return err; |
| 820 | } | 819 | } |
| 821 | 820 | ||
| 822 | static void agp_intel_remove(struct pci_dev *pdev) | 821 | static void __devexit agp_intel_remove(struct pci_dev *pdev) |
| 823 | { | 822 | { |
| 824 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 823 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 825 | 824 | ||
| 826 | agp_remove_bridge(bridge); | 825 | agp_remove_bridge(bridge); |
| 827 | 826 | ||
| 828 | intel_gmch_remove(); | 827 | intel_gmch_remove(pdev); |
| 829 | 828 | ||
| 830 | agp_put_bridge(bridge); | 829 | agp_put_bridge(bridge); |
| 831 | } | 830 | } |
| @@ -851,7 +850,6 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
| 851 | .subvendor = PCI_ANY_ID, \ | 850 | .subvendor = PCI_ANY_ID, \ |
| 852 | .subdevice = PCI_ANY_ID, \ | 851 | .subdevice = PCI_ANY_ID, \ |
| 853 | } | 852 | } |
| 854 | ID(PCI_DEVICE_ID_INTEL_82441), /* for HAS2 support */ | ||
| 855 | ID(PCI_DEVICE_ID_INTEL_82443LX_0), | 853 | ID(PCI_DEVICE_ID_INTEL_82443LX_0), |
| 856 | ID(PCI_DEVICE_ID_INTEL_82443BX_0), | 854 | ID(PCI_DEVICE_ID_INTEL_82443BX_0), |
| 857 | ID(PCI_DEVICE_ID_INTEL_82443GX_0), | 855 | ID(PCI_DEVICE_ID_INTEL_82443GX_0), |
| @@ -899,10 +897,15 @@ static struct pci_device_id agp_intel_pci_table[] = { | |||
| 899 | ID(PCI_DEVICE_ID_INTEL_B43_HB), | 897 | ID(PCI_DEVICE_ID_INTEL_B43_HB), |
| 900 | ID(PCI_DEVICE_ID_INTEL_B43_1_HB), | 898 | ID(PCI_DEVICE_ID_INTEL_B43_1_HB), |
| 901 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), | 899 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB), |
| 902 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB), | ||
| 903 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), | 900 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB), |
| 904 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), | 901 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB), |
| 905 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), | 902 | ID(PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB), |
| 903 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB), | ||
| 904 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB), | ||
| 905 | ID(PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB), | ||
| 906 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB), | ||
| 907 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB), | ||
| 908 | ID(PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB), | ||
| 906 | { } | 909 | { } |
| 907 | }; | 910 | }; |
| 908 | 911 | ||
| @@ -912,7 +915,7 @@ static struct pci_driver agp_intel_pci_driver = { | |||
| 912 | .name = "agpgart-intel", | 915 | .name = "agpgart-intel", |
| 913 | .id_table = agp_intel_pci_table, | 916 | .id_table = agp_intel_pci_table, |
| 914 | .probe = agp_intel_probe, | 917 | .probe = agp_intel_probe, |
| 915 | .remove = agp_intel_remove, | 918 | .remove = __devexit_p(agp_intel_remove), |
| 916 | #ifdef CONFIG_PM | 919 | #ifdef CONFIG_PM |
| 917 | .resume = agp_intel_resume, | 920 | .resume = agp_intel_resume, |
| 918 | #endif | 921 | #endif |
diff --git a/drivers/char/agp/intel-agp.h b/drivers/char/agp/intel-agp.h index 1042c1b9037..5da67f165af 100644 --- a/drivers/char/agp/intel-agp.h +++ b/drivers/char/agp/intel-agp.h | |||
| @@ -62,6 +62,11 @@ | |||
| 62 | #define I810_PTE_LOCAL 0x00000002 | 62 | #define I810_PTE_LOCAL 0x00000002 |
| 63 | #define I810_PTE_VALID 0x00000001 | 63 | #define I810_PTE_VALID 0x00000001 |
| 64 | #define I830_PTE_SYSTEM_CACHED 0x00000006 | 64 | #define I830_PTE_SYSTEM_CACHED 0x00000006 |
| 65 | /* GT PTE cache control fields */ | ||
| 66 | #define GEN6_PTE_UNCACHED 0x00000002 | ||
| 67 | #define GEN6_PTE_LLC 0x00000004 | ||
| 68 | #define GEN6_PTE_LLC_MLC 0x00000006 | ||
| 69 | #define GEN6_PTE_GFDT 0x00000008 | ||
| 65 | 70 | ||
| 66 | #define I810_SMRAM_MISCC 0x70 | 71 | #define I810_SMRAM_MISCC 0x70 |
| 67 | #define I810_GFX_MEM_WIN_SIZE 0x00010000 | 72 | #define I810_GFX_MEM_WIN_SIZE 0x00010000 |
| @@ -141,6 +146,29 @@ | |||
| 141 | #define INTEL_I7505_AGPCTRL 0x70 | 146 | #define INTEL_I7505_AGPCTRL 0x70 |
| 142 | #define INTEL_I7505_MCHCFG 0x50 | 147 | #define INTEL_I7505_MCHCFG 0x50 |
| 143 | 148 | ||
| 149 | #define SNB_GMCH_CTRL 0x50 | ||
| 150 | #define SNB_GMCH_GMS_STOLEN_MASK 0xF8 | ||
| 151 | #define SNB_GMCH_GMS_STOLEN_32M (1 << 3) | ||
| 152 | #define SNB_GMCH_GMS_STOLEN_64M (2 << 3) | ||
| 153 | #define SNB_GMCH_GMS_STOLEN_96M (3 << 3) | ||
| 154 | #define SNB_GMCH_GMS_STOLEN_128M (4 << 3) | ||
| 155 | #define SNB_GMCH_GMS_STOLEN_160M (5 << 3) | ||
| 156 | #define SNB_GMCH_GMS_STOLEN_192M (6 << 3) | ||
| 157 | #define SNB_GMCH_GMS_STOLEN_224M (7 << 3) | ||
| 158 | #define SNB_GMCH_GMS_STOLEN_256M (8 << 3) | ||
| 159 | #define SNB_GMCH_GMS_STOLEN_288M (9 << 3) | ||
| 160 | #define SNB_GMCH_GMS_STOLEN_320M (0xa << 3) | ||
| 161 | #define SNB_GMCH_GMS_STOLEN_352M (0xb << 3) | ||
| 162 | #define SNB_GMCH_GMS_STOLEN_384M (0xc << 3) | ||
| 163 | #define SNB_GMCH_GMS_STOLEN_416M (0xd << 3) | ||
| 164 | #define SNB_GMCH_GMS_STOLEN_448M (0xe << 3) | ||
| 165 | #define SNB_GMCH_GMS_STOLEN_480M (0xf << 3) | ||
| 166 | #define SNB_GMCH_GMS_STOLEN_512M (0x10 << 3) | ||
| 167 | #define SNB_GTT_SIZE_0M (0 << 8) | ||
| 168 | #define SNB_GTT_SIZE_1M (1 << 8) | ||
| 169 | #define SNB_GTT_SIZE_2M (2 << 8) | ||
| 170 | #define SNB_GTT_SIZE_MASK (3 << 8) | ||
| 171 | |||
| 144 | /* pci devices ids */ | 172 | /* pci devices ids */ |
| 145 | #define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588 | 173 | #define PCI_DEVICE_ID_INTEL_E7221_HB 0x2588 |
| 146 | #define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a | 174 | #define PCI_DEVICE_ID_INTEL_E7221_IG 0x258a |
| @@ -183,11 +211,31 @@ | |||
| 183 | #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 | 211 | #define PCI_DEVICE_ID_INTEL_G41_HB 0x2E30 |
| 184 | #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 | 212 | #define PCI_DEVICE_ID_INTEL_G41_IG 0x2E32 |
| 185 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 | 213 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_HB 0x0040 |
| 186 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D2_HB 0x0069 | ||
| 187 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 | 214 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_D_IG 0x0042 |
| 188 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 | 215 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB 0x0044 |
| 189 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 | 216 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MA_HB 0x0062 |
| 190 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a | 217 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_MC2_HB 0x006a |
| 191 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 | 218 | #define PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG 0x0046 |
| 192 | 219 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_HB 0x0100 /* Desktop */ | |
| 220 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG 0x0102 | ||
| 221 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG 0x0112 | ||
| 222 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG 0x0122 | ||
| 223 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_HB 0x0104 /* Mobile */ | ||
| 224 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG 0x0106 | ||
| 225 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG 0x0116 | ||
| 226 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG 0x0126 | ||
| 227 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_HB 0x0108 /* Server */ | ||
| 228 | #define PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG 0x010A | ||
| 229 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_HB 0x0150 /* Desktop */ | ||
| 230 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG 0x0152 | ||
| 231 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG 0x0162 | ||
| 232 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_HB 0x0154 /* Mobile */ | ||
| 233 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG 0x0156 | ||
| 234 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG 0x0166 | ||
| 235 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_HB 0x0158 /* Server */ | ||
| 236 | #define PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG 0x015A | ||
| 237 | |||
| 238 | int intel_gmch_probe(struct pci_dev *pdev, | ||
| 239 | struct agp_bridge_data *bridge); | ||
| 240 | void intel_gmch_remove(struct pci_dev *pdev); | ||
| 193 | #endif | 241 | #endif |
diff --git a/drivers/char/agp/intel-gtt.c b/drivers/char/agp/intel-gtt.c index dbd901e94ea..2774ac1086d 100644 --- a/drivers/char/agp/intel-gtt.c +++ b/drivers/char/agp/intel-gtt.c | |||
| @@ -66,6 +66,7 @@ static struct _intel_private { | |||
| 66 | struct pci_dev *bridge_dev; | 66 | struct pci_dev *bridge_dev; |
| 67 | u8 __iomem *registers; | 67 | u8 __iomem *registers; |
| 68 | phys_addr_t gtt_bus_addr; | 68 | phys_addr_t gtt_bus_addr; |
| 69 | phys_addr_t gma_bus_addr; | ||
| 69 | u32 PGETBL_save; | 70 | u32 PGETBL_save; |
| 70 | u32 __iomem *gtt; /* I915G */ | 71 | u32 __iomem *gtt; /* I915G */ |
| 71 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ | 72 | bool clear_fake_agp; /* on first access via agp, fill with scratch */ |
| @@ -75,7 +76,7 @@ static struct _intel_private { | |||
| 75 | struct resource ifp_resource; | 76 | struct resource ifp_resource; |
| 76 | int resource_valid; | 77 | int resource_valid; |
| 77 | struct page *scratch_page; | 78 | struct page *scratch_page; |
| 78 | int refcount; | 79 | dma_addr_t scratch_page_dma; |
| 79 | } intel_private; | 80 | } intel_private; |
| 80 | 81 | ||
| 81 | #define INTEL_GTT_GEN intel_private.driver->gen | 82 | #define INTEL_GTT_GEN intel_private.driver->gen |
| @@ -84,33 +85,40 @@ static struct _intel_private { | |||
| 84 | #define IS_IRONLAKE intel_private.driver->is_ironlake | 85 | #define IS_IRONLAKE intel_private.driver->is_ironlake |
| 85 | #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable | 86 | #define HAS_PGTBL_EN intel_private.driver->has_pgtbl_enable |
| 86 | 87 | ||
| 87 | static int intel_gtt_map_memory(struct page **pages, | 88 | int intel_gtt_map_memory(struct page **pages, unsigned int num_entries, |
| 88 | unsigned int num_entries, | 89 | struct scatterlist **sg_list, int *num_sg) |
| 89 | struct sg_table *st) | ||
| 90 | { | 90 | { |
| 91 | struct sg_table st; | ||
| 91 | struct scatterlist *sg; | 92 | struct scatterlist *sg; |
| 92 | int i; | 93 | int i; |
| 93 | 94 | ||
| 95 | if (*sg_list) | ||
| 96 | return 0; /* already mapped (for e.g. resume */ | ||
| 97 | |||
| 94 | DBG("try mapping %lu pages\n", (unsigned long)num_entries); | 98 | DBG("try mapping %lu pages\n", (unsigned long)num_entries); |
| 95 | 99 | ||
| 96 | if (sg_alloc_table(st, num_entries, GFP_KERNEL)) | 100 | if (sg_alloc_table(&st, num_entries, GFP_KERNEL)) |
| 97 | goto err; | 101 | goto err; |
| 98 | 102 | ||
| 99 | for_each_sg(st->sgl, sg, num_entries, i) | 103 | *sg_list = sg = st.sgl; |
| 104 | |||
| 105 | for (i = 0 ; i < num_entries; i++, sg = sg_next(sg)) | ||
| 100 | sg_set_page(sg, pages[i], PAGE_SIZE, 0); | 106 | sg_set_page(sg, pages[i], PAGE_SIZE, 0); |
| 101 | 107 | ||
| 102 | if (!pci_map_sg(intel_private.pcidev, | 108 | *num_sg = pci_map_sg(intel_private.pcidev, *sg_list, |
| 103 | st->sgl, st->nents, PCI_DMA_BIDIRECTIONAL)) | 109 | num_entries, PCI_DMA_BIDIRECTIONAL); |
| 110 | if (unlikely(!*num_sg)) | ||
| 104 | goto err; | 111 | goto err; |
| 105 | 112 | ||
| 106 | return 0; | 113 | return 0; |
| 107 | 114 | ||
| 108 | err: | 115 | err: |
| 109 | sg_free_table(st); | 116 | sg_free_table(&st); |
| 110 | return -ENOMEM; | 117 | return -ENOMEM; |
| 111 | } | 118 | } |
| 119 | EXPORT_SYMBOL(intel_gtt_map_memory); | ||
| 112 | 120 | ||
| 113 | static void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) | 121 | void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) |
| 114 | { | 122 | { |
| 115 | struct sg_table st; | 123 | struct sg_table st; |
| 116 | DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); | 124 | DBG("try unmapping %lu pages\n", (unsigned long)mem->page_count); |
| @@ -123,6 +131,7 @@ static void intel_gtt_unmap_memory(struct scatterlist *sg_list, int num_sg) | |||
| 123 | 131 | ||
| 124 | sg_free_table(&st); | 132 | sg_free_table(&st); |
| 125 | } | 133 | } |
| 134 | EXPORT_SYMBOL(intel_gtt_unmap_memory); | ||
| 126 | 135 | ||
| 127 | static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) | 136 | static void intel_fake_agp_enable(struct agp_bridge_data *bridge, u32 mode) |
| 128 | { | 137 | { |
| @@ -297,9 +306,9 @@ static int intel_gtt_setup_scratch_page(void) | |||
| 297 | if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) | 306 | if (pci_dma_mapping_error(intel_private.pcidev, dma_addr)) |
| 298 | return -EINVAL; | 307 | return -EINVAL; |
| 299 | 308 | ||
| 300 | intel_private.base.scratch_page_dma = dma_addr; | 309 | intel_private.scratch_page_dma = dma_addr; |
| 301 | } else | 310 | } else |
| 302 | intel_private.base.scratch_page_dma = page_to_phys(page); | 311 | intel_private.scratch_page_dma = page_to_phys(page); |
| 303 | 312 | ||
| 304 | intel_private.scratch_page = page; | 313 | intel_private.scratch_page = page; |
| 305 | 314 | ||
| @@ -367,6 +376,62 @@ static unsigned int intel_gtt_stolen_size(void) | |||
| 367 | stolen_size = 0; | 376 | stolen_size = 0; |
| 368 | break; | 377 | break; |
| 369 | } | 378 | } |
| 379 | } else if (INTEL_GTT_GEN == 6) { | ||
| 380 | /* | ||
| 381 | * SandyBridge has new memory control reg at 0x50.w | ||
| 382 | */ | ||
| 383 | u16 snb_gmch_ctl; | ||
| 384 | pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); | ||
| 385 | switch (snb_gmch_ctl & SNB_GMCH_GMS_STOLEN_MASK) { | ||
| 386 | case SNB_GMCH_GMS_STOLEN_32M: | ||
| 387 | stolen_size = MB(32); | ||
| 388 | break; | ||
| 389 | case SNB_GMCH_GMS_STOLEN_64M: | ||
| 390 | stolen_size = MB(64); | ||
| 391 | break; | ||
| 392 | case SNB_GMCH_GMS_STOLEN_96M: | ||
| 393 | stolen_size = MB(96); | ||
| 394 | break; | ||
| 395 | case SNB_GMCH_GMS_STOLEN_128M: | ||
| 396 | stolen_size = MB(128); | ||
| 397 | break; | ||
| 398 | case SNB_GMCH_GMS_STOLEN_160M: | ||
| 399 | stolen_size = MB(160); | ||
| 400 | break; | ||
| 401 | case SNB_GMCH_GMS_STOLEN_192M: | ||
| 402 | stolen_size = MB(192); | ||
| 403 | break; | ||
| 404 | case SNB_GMCH_GMS_STOLEN_224M: | ||
| 405 | stolen_size = MB(224); | ||
| 406 | break; | ||
| 407 | case SNB_GMCH_GMS_STOLEN_256M: | ||
| 408 | stolen_size = MB(256); | ||
| 409 | break; | ||
| 410 | case SNB_GMCH_GMS_STOLEN_288M: | ||
| 411 | stolen_size = MB(288); | ||
| 412 | break; | ||
| 413 | case SNB_GMCH_GMS_STOLEN_320M: | ||
| 414 | stolen_size = MB(320); | ||
| 415 | break; | ||
| 416 | case SNB_GMCH_GMS_STOLEN_352M: | ||
| 417 | stolen_size = MB(352); | ||
| 418 | break; | ||
| 419 | case SNB_GMCH_GMS_STOLEN_384M: | ||
| 420 | stolen_size = MB(384); | ||
| 421 | break; | ||
| 422 | case SNB_GMCH_GMS_STOLEN_416M: | ||
| 423 | stolen_size = MB(416); | ||
| 424 | break; | ||
| 425 | case SNB_GMCH_GMS_STOLEN_448M: | ||
| 426 | stolen_size = MB(448); | ||
| 427 | break; | ||
| 428 | case SNB_GMCH_GMS_STOLEN_480M: | ||
| 429 | stolen_size = MB(480); | ||
| 430 | break; | ||
| 431 | case SNB_GMCH_GMS_STOLEN_512M: | ||
| 432 | stolen_size = MB(512); | ||
| 433 | break; | ||
| 434 | } | ||
| 370 | } else { | 435 | } else { |
| 371 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { | 436 | switch (gmch_ctrl & I855_GMCH_GMS_MASK) { |
| 372 | case I855_GMCH_GMS_STOLEN_1M: | 437 | case I855_GMCH_GMS_STOLEN_1M: |
| @@ -500,9 +565,29 @@ static unsigned int i965_gtt_total_entries(void) | |||
| 500 | 565 | ||
| 501 | static unsigned int intel_gtt_total_entries(void) | 566 | static unsigned int intel_gtt_total_entries(void) |
| 502 | { | 567 | { |
| 568 | int size; | ||
| 569 | |||
| 503 | if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) | 570 | if (IS_G33 || INTEL_GTT_GEN == 4 || INTEL_GTT_GEN == 5) |
| 504 | return i965_gtt_total_entries(); | 571 | return i965_gtt_total_entries(); |
| 505 | else { | 572 | else if (INTEL_GTT_GEN == 6) { |
| 573 | u16 snb_gmch_ctl; | ||
| 574 | |||
| 575 | pci_read_config_word(intel_private.pcidev, SNB_GMCH_CTRL, &snb_gmch_ctl); | ||
| 576 | switch (snb_gmch_ctl & SNB_GTT_SIZE_MASK) { | ||
| 577 | default: | ||
| 578 | case SNB_GTT_SIZE_0M: | ||
| 579 | printk(KERN_ERR "Bad GTT size mask: 0x%04x.\n", snb_gmch_ctl); | ||
| 580 | size = MB(0); | ||
| 581 | break; | ||
| 582 | case SNB_GTT_SIZE_1M: | ||
| 583 | size = MB(1); | ||
| 584 | break; | ||
| 585 | case SNB_GTT_SIZE_2M: | ||
| 586 | size = MB(2); | ||
| 587 | break; | ||
| 588 | } | ||
| 589 | return size/4; | ||
| 590 | } else { | ||
| 506 | /* On previous hardware, the GTT size was just what was | 591 | /* On previous hardware, the GTT size was just what was |
| 507 | * required to map the aperture. | 592 | * required to map the aperture. |
| 508 | */ | 593 | */ |
| @@ -546,7 +631,7 @@ static unsigned int intel_gtt_mappable_entries(void) | |||
| 546 | static void intel_gtt_teardown_scratch_page(void) | 631 | static void intel_gtt_teardown_scratch_page(void) |
| 547 | { | 632 | { |
| 548 | set_pages_wb(intel_private.scratch_page, 1); | 633 | set_pages_wb(intel_private.scratch_page, 1); |
| 549 | pci_unmap_page(intel_private.pcidev, intel_private.base.scratch_page_dma, | 634 | pci_unmap_page(intel_private.pcidev, intel_private.scratch_page_dma, |
| 550 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); | 635 | PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); |
| 551 | put_page(intel_private.scratch_page); | 636 | put_page(intel_private.scratch_page); |
| 552 | __free_page(intel_private.scratch_page); | 637 | __free_page(intel_private.scratch_page); |
| @@ -564,7 +649,6 @@ static void intel_gtt_cleanup(void) | |||
| 564 | 649 | ||
| 565 | static int intel_gtt_init(void) | 650 | static int intel_gtt_init(void) |
| 566 | { | 651 | { |
| 567 | u32 gma_addr; | ||
| 568 | u32 gtt_map_size; | 652 | u32 gtt_map_size; |
| 569 | int ret; | 653 | int ret; |
| 570 | 654 | ||
| @@ -590,19 +674,13 @@ static int intel_gtt_init(void) | |||
| 590 | 674 | ||
| 591 | gtt_map_size = intel_private.base.gtt_total_entries * 4; | 675 | gtt_map_size = intel_private.base.gtt_total_entries * 4; |
| 592 | 676 | ||
| 593 | intel_private.gtt = NULL; | 677 | intel_private.gtt = ioremap(intel_private.gtt_bus_addr, |
| 594 | if (INTEL_GTT_GEN < 6 && INTEL_GTT_GEN > 2) | 678 | gtt_map_size); |
| 595 | intel_private.gtt = ioremap_wc(intel_private.gtt_bus_addr, | 679 | if (!intel_private.gtt) { |
| 596 | gtt_map_size); | ||
| 597 | if (intel_private.gtt == NULL) | ||
| 598 | intel_private.gtt = ioremap(intel_private.gtt_bus_addr, | ||
| 599 | gtt_map_size); | ||
| 600 | if (intel_private.gtt == NULL) { | ||
| 601 | intel_private.driver->cleanup(); | 680 | intel_private.driver->cleanup(); |
| 602 | iounmap(intel_private.registers); | 681 | iounmap(intel_private.registers); |
| 603 | return -ENOMEM; | 682 | return -ENOMEM; |
| 604 | } | 683 | } |
| 605 | intel_private.base.gtt = intel_private.gtt; | ||
| 606 | 684 | ||
| 607 | global_cache_flush(); /* FIXME: ? */ | 685 | global_cache_flush(); /* FIXME: ? */ |
| 608 | 686 | ||
| @@ -616,15 +694,6 @@ static int intel_gtt_init(void) | |||
| 616 | return ret; | 694 | return ret; |
| 617 | } | 695 | } |
| 618 | 696 | ||
| 619 | if (INTEL_GTT_GEN <= 2) | ||
| 620 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, | ||
| 621 | &gma_addr); | ||
| 622 | else | ||
| 623 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, | ||
| 624 | &gma_addr); | ||
| 625 | |||
| 626 | intel_private.base.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); | ||
| 627 | |||
| 628 | return 0; | 697 | return 0; |
| 629 | } | 698 | } |
| 630 | 699 | ||
| @@ -698,10 +767,23 @@ static void i830_write_entry(dma_addr_t addr, unsigned int entry, | |||
| 698 | writel(addr | pte_flags, intel_private.gtt + entry); | 767 | writel(addr | pte_flags, intel_private.gtt + entry); |
| 699 | } | 768 | } |
| 700 | 769 | ||
| 701 | bool intel_enable_gtt(void) | 770 | static bool intel_enable_gtt(void) |
| 702 | { | 771 | { |
| 772 | u32 gma_addr; | ||
| 703 | u8 __iomem *reg; | 773 | u8 __iomem *reg; |
| 704 | 774 | ||
| 775 | if (INTEL_GTT_GEN <= 2) | ||
| 776 | pci_read_config_dword(intel_private.pcidev, I810_GMADDR, | ||
| 777 | &gma_addr); | ||
| 778 | else | ||
| 779 | pci_read_config_dword(intel_private.pcidev, I915_GMADDR, | ||
| 780 | &gma_addr); | ||
| 781 | |||
| 782 | intel_private.gma_bus_addr = (gma_addr & PCI_BASE_ADDRESS_MEM_MASK); | ||
| 783 | |||
| 784 | if (INTEL_GTT_GEN >= 6) | ||
| 785 | return true; | ||
| 786 | |||
| 705 | if (INTEL_GTT_GEN == 2) { | 787 | if (INTEL_GTT_GEN == 2) { |
| 706 | u16 gmch_ctrl; | 788 | u16 gmch_ctrl; |
| 707 | 789 | ||
| @@ -741,7 +823,6 @@ bool intel_enable_gtt(void) | |||
| 741 | 823 | ||
| 742 | return true; | 824 | return true; |
| 743 | } | 825 | } |
| 744 | EXPORT_SYMBOL(intel_enable_gtt); | ||
| 745 | 826 | ||
| 746 | static int i830_setup(void) | 827 | static int i830_setup(void) |
| 747 | { | 828 | { |
| @@ -779,7 +860,7 @@ static int intel_fake_agp_configure(void) | |||
| 779 | return -EIO; | 860 | return -EIO; |
| 780 | 861 | ||
| 781 | intel_private.clear_fake_agp = true; | 862 | intel_private.clear_fake_agp = true; |
| 782 | agp_bridge->gart_bus_addr = intel_private.base.gma_bus_addr; | 863 | agp_bridge->gart_bus_addr = intel_private.gma_bus_addr; |
| 783 | 864 | ||
| 784 | return 0; | 865 | return 0; |
| 785 | } | 866 | } |
| @@ -797,7 +878,8 @@ static bool i830_check_flags(unsigned int flags) | |||
| 797 | return false; | 878 | return false; |
| 798 | } | 879 | } |
| 799 | 880 | ||
| 800 | void intel_gtt_insert_sg_entries(struct sg_table *st, | 881 | void intel_gtt_insert_sg_entries(struct scatterlist *sg_list, |
| 882 | unsigned int sg_len, | ||
| 801 | unsigned int pg_start, | 883 | unsigned int pg_start, |
| 802 | unsigned int flags) | 884 | unsigned int flags) |
| 803 | { | 885 | { |
| @@ -809,11 +891,12 @@ void intel_gtt_insert_sg_entries(struct sg_table *st, | |||
| 809 | 891 | ||
| 810 | /* sg may merge pages, but we have to separate | 892 | /* sg may merge pages, but we have to separate |
| 811 | * per-page addr for GTT */ | 893 | * per-page addr for GTT */ |
| 812 | for_each_sg(st->sgl, sg, st->nents, i) { | 894 | for_each_sg(sg_list, sg, sg_len, i) { |
| 813 | len = sg_dma_len(sg) >> PAGE_SHIFT; | 895 | len = sg_dma_len(sg) >> PAGE_SHIFT; |
| 814 | for (m = 0; m < len; m++) { | 896 | for (m = 0; m < len; m++) { |
| 815 | dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); | 897 | dma_addr_t addr = sg_dma_address(sg) + (m << PAGE_SHIFT); |
| 816 | intel_private.driver->write_entry(addr, j, flags); | 898 | intel_private.driver->write_entry(addr, |
| 899 | j, flags); | ||
| 817 | j++; | 900 | j++; |
| 818 | } | 901 | } |
| 819 | } | 902 | } |
| @@ -821,10 +904,8 @@ void intel_gtt_insert_sg_entries(struct sg_table *st, | |||
| 821 | } | 904 | } |
| 822 | EXPORT_SYMBOL(intel_gtt_insert_sg_entries); | 905 | EXPORT_SYMBOL(intel_gtt_insert_sg_entries); |
| 823 | 906 | ||
| 824 | static void intel_gtt_insert_pages(unsigned int first_entry, | 907 | void intel_gtt_insert_pages(unsigned int first_entry, unsigned int num_entries, |
| 825 | unsigned int num_entries, | 908 | struct page **pages, unsigned int flags) |
| 826 | struct page **pages, | ||
| 827 | unsigned int flags) | ||
| 828 | { | 909 | { |
| 829 | int i, j; | 910 | int i, j; |
| 830 | 911 | ||
| @@ -835,15 +916,13 @@ static void intel_gtt_insert_pages(unsigned int first_entry, | |||
| 835 | } | 916 | } |
| 836 | readl(intel_private.gtt+j-1); | 917 | readl(intel_private.gtt+j-1); |
| 837 | } | 918 | } |
| 919 | EXPORT_SYMBOL(intel_gtt_insert_pages); | ||
| 838 | 920 | ||
| 839 | static int intel_fake_agp_insert_entries(struct agp_memory *mem, | 921 | static int intel_fake_agp_insert_entries(struct agp_memory *mem, |
| 840 | off_t pg_start, int type) | 922 | off_t pg_start, int type) |
| 841 | { | 923 | { |
| 842 | int ret = -EINVAL; | 924 | int ret = -EINVAL; |
| 843 | 925 | ||
| 844 | if (intel_private.base.do_idle_maps) | ||
| 845 | return -ENODEV; | ||
| 846 | |||
| 847 | if (intel_private.clear_fake_agp) { | 926 | if (intel_private.clear_fake_agp) { |
| 848 | int start = intel_private.base.stolen_size / PAGE_SIZE; | 927 | int start = intel_private.base.stolen_size / PAGE_SIZE; |
| 849 | int end = intel_private.base.gtt_mappable_entries; | 928 | int end = intel_private.base.gtt_mappable_entries; |
| @@ -870,15 +949,13 @@ static int intel_fake_agp_insert_entries(struct agp_memory *mem, | |||
| 870 | global_cache_flush(); | 949 | global_cache_flush(); |
| 871 | 950 | ||
| 872 | if (intel_private.base.needs_dmar) { | 951 | if (intel_private.base.needs_dmar) { |
| 873 | struct sg_table st; | 952 | ret = intel_gtt_map_memory(mem->pages, mem->page_count, |
| 874 | 953 | &mem->sg_list, &mem->num_sg); | |
| 875 | ret = intel_gtt_map_memory(mem->pages, mem->page_count, &st); | ||
| 876 | if (ret != 0) | 954 | if (ret != 0) |
| 877 | return ret; | 955 | return ret; |
| 878 | 956 | ||
| 879 | intel_gtt_insert_sg_entries(&st, pg_start, type); | 957 | intel_gtt_insert_sg_entries(mem->sg_list, mem->num_sg, |
| 880 | mem->sg_list = st.sgl; | 958 | pg_start, type); |
| 881 | mem->num_sg = st.nents; | ||
| 882 | } else | 959 | } else |
| 883 | intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages, | 960 | intel_gtt_insert_pages(pg_start, mem->page_count, mem->pages, |
| 884 | type); | 961 | type); |
| @@ -895,7 +972,7 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned int num_entries) | |||
| 895 | unsigned int i; | 972 | unsigned int i; |
| 896 | 973 | ||
| 897 | for (i = first_entry; i < (first_entry + num_entries); i++) { | 974 | for (i = first_entry; i < (first_entry + num_entries); i++) { |
| 898 | intel_private.driver->write_entry(intel_private.base.scratch_page_dma, | 975 | intel_private.driver->write_entry(intel_private.scratch_page_dma, |
| 899 | i, 0); | 976 | i, 0); |
| 900 | } | 977 | } |
| 901 | readl(intel_private.gtt+i-1); | 978 | readl(intel_private.gtt+i-1); |
| @@ -908,9 +985,6 @@ static int intel_fake_agp_remove_entries(struct agp_memory *mem, | |||
| 908 | if (mem->page_count == 0) | 985 | if (mem->page_count == 0) |
| 909 | return 0; | 986 | return 0; |
| 910 | 987 | ||
| 911 | if (intel_private.base.do_idle_maps) | ||
| 912 | return -ENODEV; | ||
| 913 | |||
| 914 | intel_gtt_clear_range(pg_start, mem->page_count); | 988 | intel_gtt_clear_range(pg_start, mem->page_count); |
| 915 | 989 | ||
| 916 | if (intel_private.base.needs_dmar) { | 990 | if (intel_private.base.needs_dmar) { |
| @@ -1070,54 +1144,72 @@ static void i965_write_entry(dma_addr_t addr, | |||
| 1070 | writel(addr | pte_flags, intel_private.gtt + entry); | 1144 | writel(addr | pte_flags, intel_private.gtt + entry); |
| 1071 | } | 1145 | } |
| 1072 | 1146 | ||
| 1073 | /* Certain Gen5 chipsets require require idling the GPU before | 1147 | static bool gen6_check_flags(unsigned int flags) |
| 1074 | * unmapping anything from the GTT when VT-d is enabled. | ||
| 1075 | */ | ||
| 1076 | static inline int needs_idle_maps(void) | ||
| 1077 | { | 1148 | { |
| 1078 | #ifdef CONFIG_INTEL_IOMMU | 1149 | return true; |
| 1079 | const unsigned short gpu_devid = intel_private.pcidev->device; | 1150 | } |
| 1080 | 1151 | ||
| 1081 | /* Query intel_iommu to see if we need the workaround. Presumably that | 1152 | static void gen6_write_entry(dma_addr_t addr, unsigned int entry, |
| 1082 | * was loaded first. | 1153 | unsigned int flags) |
| 1083 | */ | 1154 | { |
| 1084 | if ((gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_HB || | 1155 | unsigned int type_mask = flags & ~AGP_USER_CACHED_MEMORY_GFDT; |
| 1085 | gpu_devid == PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG) && | 1156 | unsigned int gfdt = flags & AGP_USER_CACHED_MEMORY_GFDT; |
| 1086 | intel_iommu_gfx_mapped) | 1157 | u32 pte_flags; |
| 1087 | return 1; | 1158 | |
| 1088 | #endif | 1159 | if (type_mask == AGP_USER_MEMORY) |
| 1089 | return 0; | 1160 | pte_flags = GEN6_PTE_UNCACHED | I810_PTE_VALID; |
| 1161 | else if (type_mask == AGP_USER_CACHED_MEMORY_LLC_MLC) { | ||
| 1162 | pte_flags = GEN6_PTE_LLC_MLC | I810_PTE_VALID; | ||
| 1163 | if (gfdt) | ||
| 1164 | pte_flags |= GEN6_PTE_GFDT; | ||
| 1165 | } else { /* set 'normal'/'cached' to LLC by default */ | ||
| 1166 | pte_flags = GEN6_PTE_LLC | I810_PTE_VALID; | ||
| 1167 | if (gfdt) | ||
| 1168 | pte_flags |= GEN6_PTE_GFDT; | ||
| 1169 | } | ||
| 1170 | |||
| 1171 | /* gen6 has bit11-4 for physical addr bit39-32 */ | ||
| 1172 | addr |= (addr >> 28) & 0xff0; | ||
| 1173 | writel(addr | pte_flags, intel_private.gtt + entry); | ||
| 1174 | } | ||
| 1175 | |||
| 1176 | static void gen6_cleanup(void) | ||
| 1177 | { | ||
| 1090 | } | 1178 | } |
| 1091 | 1179 | ||
| 1092 | static int i9xx_setup(void) | 1180 | static int i9xx_setup(void) |
| 1093 | { | 1181 | { |
| 1094 | u32 reg_addr, gtt_addr; | 1182 | u32 reg_addr; |
| 1095 | int size = KB(512); | ||
| 1096 | 1183 | ||
| 1097 | pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); | 1184 | pci_read_config_dword(intel_private.pcidev, I915_MMADDR, ®_addr); |
| 1098 | 1185 | ||
| 1099 | reg_addr &= 0xfff80000; | 1186 | reg_addr &= 0xfff80000; |
| 1100 | 1187 | ||
| 1101 | intel_private.registers = ioremap(reg_addr, size); | 1188 | intel_private.registers = ioremap(reg_addr, 128 * 4096); |
| 1102 | if (!intel_private.registers) | 1189 | if (!intel_private.registers) |
| 1103 | return -ENOMEM; | 1190 | return -ENOMEM; |
| 1104 | 1191 | ||
| 1105 | switch (INTEL_GTT_GEN) { | 1192 | if (INTEL_GTT_GEN == 3) { |
| 1106 | case 3: | 1193 | u32 gtt_addr; |
| 1194 | |||
| 1107 | pci_read_config_dword(intel_private.pcidev, | 1195 | pci_read_config_dword(intel_private.pcidev, |
| 1108 | I915_PTEADDR, >t_addr); | 1196 | I915_PTEADDR, >t_addr); |
| 1109 | intel_private.gtt_bus_addr = gtt_addr; | 1197 | intel_private.gtt_bus_addr = gtt_addr; |
| 1110 | break; | 1198 | } else { |
| 1111 | case 5: | 1199 | u32 gtt_offset; |
| 1112 | intel_private.gtt_bus_addr = reg_addr + MB(2); | ||
| 1113 | break; | ||
| 1114 | default: | ||
| 1115 | intel_private.gtt_bus_addr = reg_addr + KB(512); | ||
| 1116 | break; | ||
| 1117 | } | ||
| 1118 | 1200 | ||
| 1119 | if (needs_idle_maps()) | 1201 | switch (INTEL_GTT_GEN) { |
| 1120 | intel_private.base.do_idle_maps = 1; | 1202 | case 5: |
| 1203 | case 6: | ||
| 1204 | gtt_offset = MB(2); | ||
| 1205 | break; | ||
| 1206 | case 4: | ||
| 1207 | default: | ||
| 1208 | gtt_offset = KB(512); | ||
| 1209 | break; | ||
| 1210 | } | ||
| 1211 | intel_private.gtt_bus_addr = reg_addr + gtt_offset; | ||
| 1212 | } | ||
| 1121 | 1213 | ||
| 1122 | intel_i9xx_setup_flush(); | 1214 | intel_i9xx_setup_flush(); |
| 1123 | 1215 | ||
| @@ -1225,6 +1317,15 @@ static const struct intel_gtt_driver ironlake_gtt_driver = { | |||
| 1225 | .check_flags = i830_check_flags, | 1317 | .check_flags = i830_check_flags, |
| 1226 | .chipset_flush = i9xx_chipset_flush, | 1318 | .chipset_flush = i9xx_chipset_flush, |
| 1227 | }; | 1319 | }; |
| 1320 | static const struct intel_gtt_driver sandybridge_gtt_driver = { | ||
| 1321 | .gen = 6, | ||
| 1322 | .setup = i9xx_setup, | ||
| 1323 | .cleanup = gen6_cleanup, | ||
| 1324 | .write_entry = gen6_write_entry, | ||
| 1325 | .dma_mask_size = 40, | ||
| 1326 | .check_flags = gen6_check_flags, | ||
| 1327 | .chipset_flush = i9xx_chipset_flush, | ||
| 1328 | }; | ||
| 1228 | 1329 | ||
| 1229 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of | 1330 | /* Table to describe Intel GMCH and AGP/PCIE GART drivers. At least one of |
| 1230 | * driver and gmch_driver must be non-null, and find_gmch will determine | 1331 | * driver and gmch_driver must be non-null, and find_gmch will determine |
| @@ -1305,6 +1406,30 @@ static const struct intel_gtt_driver_description { | |||
| 1305 | "HD Graphics", &ironlake_gtt_driver }, | 1406 | "HD Graphics", &ironlake_gtt_driver }, |
| 1306 | { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, | 1407 | { PCI_DEVICE_ID_INTEL_IRONLAKE_M_IG, |
| 1307 | "HD Graphics", &ironlake_gtt_driver }, | 1408 | "HD Graphics", &ironlake_gtt_driver }, |
| 1409 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT1_IG, | ||
| 1410 | "Sandybridge", &sandybridge_gtt_driver }, | ||
| 1411 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_IG, | ||
| 1412 | "Sandybridge", &sandybridge_gtt_driver }, | ||
| 1413 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_GT2_PLUS_IG, | ||
| 1414 | "Sandybridge", &sandybridge_gtt_driver }, | ||
| 1415 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT1_IG, | ||
| 1416 | "Sandybridge", &sandybridge_gtt_driver }, | ||
| 1417 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_IG, | ||
| 1418 | "Sandybridge", &sandybridge_gtt_driver }, | ||
| 1419 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_M_GT2_PLUS_IG, | ||
| 1420 | "Sandybridge", &sandybridge_gtt_driver }, | ||
| 1421 | { PCI_DEVICE_ID_INTEL_SANDYBRIDGE_S_IG, | ||
| 1422 | "Sandybridge", &sandybridge_gtt_driver }, | ||
| 1423 | { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT1_IG, | ||
| 1424 | "Ivybridge", &sandybridge_gtt_driver }, | ||
| 1425 | { PCI_DEVICE_ID_INTEL_IVYBRIDGE_GT2_IG, | ||
| 1426 | "Ivybridge", &sandybridge_gtt_driver }, | ||
| 1427 | { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT1_IG, | ||
| 1428 | "Ivybridge", &sandybridge_gtt_driver }, | ||
| 1429 | { PCI_DEVICE_ID_INTEL_IVYBRIDGE_M_GT2_IG, | ||
| 1430 | "Ivybridge", &sandybridge_gtt_driver }, | ||
| 1431 | { PCI_DEVICE_ID_INTEL_IVYBRIDGE_S_GT1_IG, | ||
| 1432 | "Ivybridge", &sandybridge_gtt_driver }, | ||
| 1308 | { 0, NULL, NULL } | 1433 | { 0, NULL, NULL } |
| 1309 | }; | 1434 | }; |
| 1310 | 1435 | ||
| @@ -1325,32 +1450,14 @@ static int find_gmch(u16 device) | |||
| 1325 | return 1; | 1450 | return 1; |
| 1326 | } | 1451 | } |
| 1327 | 1452 | ||
| 1328 | int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, | 1453 | int intel_gmch_probe(struct pci_dev *pdev, |
| 1329 | struct agp_bridge_data *bridge) | 1454 | struct agp_bridge_data *bridge) |
| 1330 | { | 1455 | { |
| 1331 | int i, mask; | 1456 | int i, mask; |
| 1332 | 1457 | intel_private.driver = NULL; | |
| 1333 | /* | ||
| 1334 | * Can be called from the fake agp driver but also directly from | ||
| 1335 | * drm/i915.ko. Hence we need to check whether everything is set up | ||
| 1336 | * already. | ||
| 1337 | */ | ||
| 1338 | if (intel_private.driver) { | ||
| 1339 | intel_private.refcount++; | ||
| 1340 | return 1; | ||
| 1341 | } | ||
| 1342 | 1458 | ||
| 1343 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { | 1459 | for (i = 0; intel_gtt_chipsets[i].name != NULL; i++) { |
| 1344 | if (gpu_pdev) { | 1460 | if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { |
| 1345 | if (gpu_pdev->device == | ||
| 1346 | intel_gtt_chipsets[i].gmch_chip_id) { | ||
| 1347 | intel_private.pcidev = pci_dev_get(gpu_pdev); | ||
| 1348 | intel_private.driver = | ||
| 1349 | intel_gtt_chipsets[i].gtt_driver; | ||
| 1350 | |||
| 1351 | break; | ||
| 1352 | } | ||
| 1353 | } else if (find_gmch(intel_gtt_chipsets[i].gmch_chip_id)) { | ||
| 1354 | intel_private.driver = | 1461 | intel_private.driver = |
| 1355 | intel_gtt_chipsets[i].gtt_driver; | 1462 | intel_gtt_chipsets[i].gtt_driver; |
| 1356 | break; | 1463 | break; |
| @@ -1360,17 +1467,13 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, | |||
| 1360 | if (!intel_private.driver) | 1467 | if (!intel_private.driver) |
| 1361 | return 0; | 1468 | return 0; |
| 1362 | 1469 | ||
| 1363 | intel_private.refcount++; | 1470 | bridge->driver = &intel_fake_agp_driver; |
| 1471 | bridge->dev_private_data = &intel_private; | ||
| 1472 | bridge->dev = pdev; | ||
| 1364 | 1473 | ||
| 1365 | if (bridge) { | 1474 | intel_private.bridge_dev = pci_dev_get(pdev); |
| 1366 | bridge->driver = &intel_fake_agp_driver; | ||
| 1367 | bridge->dev_private_data = &intel_private; | ||
| 1368 | bridge->dev = bridge_pdev; | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | intel_private.bridge_dev = pci_dev_get(bridge_pdev); | ||
| 1372 | 1475 | ||
| 1373 | dev_info(&bridge_pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); | 1476 | dev_info(&pdev->dev, "Intel %s Chipset\n", intel_gtt_chipsets[i].name); |
| 1374 | 1477 | ||
| 1375 | mask = intel_private.driver->dma_mask_size; | 1478 | mask = intel_private.driver->dma_mask_size; |
| 1376 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) | 1479 | if (pci_set_dma_mask(intel_private.pcidev, DMA_BIT_MASK(mask))) |
| @@ -1380,17 +1483,17 @@ int intel_gmch_probe(struct pci_dev *bridge_pdev, struct pci_dev *gpu_pdev, | |||
| 1380 | pci_set_consistent_dma_mask(intel_private.pcidev, | 1483 | pci_set_consistent_dma_mask(intel_private.pcidev, |
| 1381 | DMA_BIT_MASK(mask)); | 1484 | DMA_BIT_MASK(mask)); |
| 1382 | 1485 | ||
| 1383 | if (intel_gtt_init() != 0) { | 1486 | /*if (bridge->driver == &intel_810_driver) |
| 1384 | intel_gmch_remove(); | 1487 | return 1;*/ |
| 1385 | 1488 | ||
| 1489 | if (intel_gtt_init() != 0) | ||
| 1386 | return 0; | 1490 | return 0; |
| 1387 | } | ||
| 1388 | 1491 | ||
| 1389 | return 1; | 1492 | return 1; |
| 1390 | } | 1493 | } |
| 1391 | EXPORT_SYMBOL(intel_gmch_probe); | 1494 | EXPORT_SYMBOL(intel_gmch_probe); |
| 1392 | 1495 | ||
| 1393 | struct intel_gtt *intel_gtt_get(void) | 1496 | const struct intel_gtt *intel_gtt_get(void) |
| 1394 | { | 1497 | { |
| 1395 | return &intel_private.base; | 1498 | return &intel_private.base; |
| 1396 | } | 1499 | } |
| @@ -1403,16 +1506,12 @@ void intel_gtt_chipset_flush(void) | |||
| 1403 | } | 1506 | } |
| 1404 | EXPORT_SYMBOL(intel_gtt_chipset_flush); | 1507 | EXPORT_SYMBOL(intel_gtt_chipset_flush); |
| 1405 | 1508 | ||
| 1406 | void intel_gmch_remove(void) | 1509 | void intel_gmch_remove(struct pci_dev *pdev) |
| 1407 | { | 1510 | { |
| 1408 | if (--intel_private.refcount) | ||
| 1409 | return; | ||
| 1410 | |||
| 1411 | if (intel_private.pcidev) | 1511 | if (intel_private.pcidev) |
| 1412 | pci_dev_put(intel_private.pcidev); | 1512 | pci_dev_put(intel_private.pcidev); |
| 1413 | if (intel_private.bridge_dev) | 1513 | if (intel_private.bridge_dev) |
| 1414 | pci_dev_put(intel_private.bridge_dev); | 1514 | pci_dev_put(intel_private.bridge_dev); |
| 1415 | intel_private.driver = NULL; | ||
| 1416 | } | 1515 | } |
| 1417 | EXPORT_SYMBOL(intel_gmch_remove); | 1516 | EXPORT_SYMBOL(intel_gmch_remove); |
| 1418 | 1517 | ||
diff --git a/drivers/char/agp/nvidia-agp.c b/drivers/char/agp/nvidia-agp.c index 62be3ec0da4..b9734a97818 100644 --- a/drivers/char/agp/nvidia-agp.c +++ b/drivers/char/agp/nvidia-agp.c | |||
| @@ -332,8 +332,8 @@ static const struct agp_bridge_driver nvidia_driver = { | |||
| 332 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 332 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
| 333 | }; | 333 | }; |
| 334 | 334 | ||
| 335 | static int agp_nvidia_probe(struct pci_dev *pdev, | 335 | static int __devinit agp_nvidia_probe(struct pci_dev *pdev, |
| 336 | const struct pci_device_id *ent) | 336 | const struct pci_device_id *ent) |
| 337 | { | 337 | { |
| 338 | struct agp_bridge_data *bridge; | 338 | struct agp_bridge_data *bridge; |
| 339 | u8 cap_ptr; | 339 | u8 cap_ptr; |
| @@ -388,7 +388,7 @@ static int agp_nvidia_probe(struct pci_dev *pdev, | |||
| 388 | return agp_add_bridge(bridge); | 388 | return agp_add_bridge(bridge); |
| 389 | } | 389 | } |
| 390 | 390 | ||
| 391 | static void agp_nvidia_remove(struct pci_dev *pdev) | 391 | static void __devexit agp_nvidia_remove(struct pci_dev *pdev) |
| 392 | { | 392 | { |
| 393 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 393 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 394 | 394 | ||
diff --git a/drivers/char/agp/sgi-agp.c b/drivers/char/agp/sgi-agp.c index 05b8d0241bd..ffa888cd1c8 100644 --- a/drivers/char/agp/sgi-agp.c +++ b/drivers/char/agp/sgi-agp.c | |||
| @@ -158,6 +158,7 @@ static int sgi_tioca_insert_memory(struct agp_memory *mem, off_t pg_start, | |||
| 158 | break; | 158 | break; |
| 159 | case LVL2_APER_SIZE: | 159 | case LVL2_APER_SIZE: |
| 160 | return -EINVAL; | 160 | return -EINVAL; |
| 161 | break; | ||
| 161 | default: | 162 | default: |
| 162 | num_entries = 0; | 163 | num_entries = 0; |
| 163 | break; | 164 | break; |
| @@ -270,7 +271,7 @@ const struct agp_bridge_driver sgi_tioca_driver = { | |||
| 270 | .num_aperture_sizes = 1, | 271 | .num_aperture_sizes = 1, |
| 271 | }; | 272 | }; |
| 272 | 273 | ||
| 273 | static int agp_sgi_init(void) | 274 | static int __devinit agp_sgi_init(void) |
| 274 | { | 275 | { |
| 275 | unsigned int j; | 276 | unsigned int j; |
| 276 | struct tioca_kernel *info; | 277 | struct tioca_kernel *info; |
| @@ -289,11 +290,12 @@ static int agp_sgi_init(void) | |||
| 289 | 290 | ||
| 290 | j = 0; | 291 | j = 0; |
| 291 | list_for_each_entry(info, &tioca_list, ca_list) { | 292 | list_for_each_entry(info, &tioca_list, ca_list) { |
| 293 | struct list_head *tmp; | ||
| 292 | if (list_empty(info->ca_devices)) | 294 | if (list_empty(info->ca_devices)) |
| 293 | continue; | 295 | continue; |
| 294 | list_for_each_entry(pdev, info->ca_devices, bus_list) { | 296 | list_for_each(tmp, info->ca_devices) { |
| 295 | u8 cap_ptr; | 297 | u8 cap_ptr; |
| 296 | 298 | pdev = pci_dev_b(tmp); | |
| 297 | if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8)) | 299 | if (pdev->class != (PCI_CLASS_DISPLAY_VGA << 8)) |
| 298 | continue; | 300 | continue; |
| 299 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); | 301 | cap_ptr = pci_find_capability(pdev, PCI_CAP_ID_AGP); |
| @@ -327,7 +329,7 @@ static int agp_sgi_init(void) | |||
| 327 | return 0; | 329 | return 0; |
| 328 | } | 330 | } |
| 329 | 331 | ||
| 330 | static void agp_sgi_cleanup(void) | 332 | static void __devexit agp_sgi_cleanup(void) |
| 331 | { | 333 | { |
| 332 | kfree(sgi_tioca_agp_bridges); | 334 | kfree(sgi_tioca_agp_bridges); |
| 333 | sgi_tioca_agp_bridges = NULL; | 335 | sgi_tioca_agp_bridges = NULL; |
diff --git a/drivers/char/agp/sis-agp.c b/drivers/char/agp/sis-agp.c index 79c838c434b..29aacd81de7 100644 --- a/drivers/char/agp/sis-agp.c +++ b/drivers/char/agp/sis-agp.c | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #define PCI_DEVICE_ID_SI_662 0x0662 | 17 | #define PCI_DEVICE_ID_SI_662 0x0662 |
| 18 | #define PCI_DEVICE_ID_SI_671 0x0671 | 18 | #define PCI_DEVICE_ID_SI_671 0x0671 |
| 19 | 19 | ||
| 20 | static bool agp_sis_force_delay = 0; | 20 | static int __devinitdata agp_sis_force_delay = 0; |
| 21 | static int agp_sis_agp_spec = -1; | 21 | static int __devinitdata agp_sis_agp_spec = -1; |
| 22 | 22 | ||
| 23 | static int sis_fetch_size(void) | 23 | static int sis_fetch_size(void) |
| 24 | { | 24 | { |
| @@ -148,13 +148,13 @@ static struct agp_bridge_driver sis_driver = { | |||
| 148 | }; | 148 | }; |
| 149 | 149 | ||
| 150 | // chipsets that require the 'delay hack' | 150 | // chipsets that require the 'delay hack' |
| 151 | static int sis_broken_chipsets[] = { | 151 | static int sis_broken_chipsets[] __devinitdata = { |
| 152 | PCI_DEVICE_ID_SI_648, | 152 | PCI_DEVICE_ID_SI_648, |
| 153 | PCI_DEVICE_ID_SI_746, | 153 | PCI_DEVICE_ID_SI_746, |
| 154 | 0 // terminator | 154 | 0 // terminator |
| 155 | }; | 155 | }; |
| 156 | 156 | ||
| 157 | static void sis_get_driver(struct agp_bridge_data *bridge) | 157 | static void __devinit sis_get_driver(struct agp_bridge_data *bridge) |
| 158 | { | 158 | { |
| 159 | int i; | 159 | int i; |
| 160 | 160 | ||
| @@ -180,7 +180,8 @@ static void sis_get_driver(struct agp_bridge_data *bridge) | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | 182 | ||
| 183 | static int agp_sis_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 183 | static int __devinit agp_sis_probe(struct pci_dev *pdev, |
| 184 | const struct pci_device_id *ent) | ||
| 184 | { | 185 | { |
| 185 | struct agp_bridge_data *bridge; | 186 | struct agp_bridge_data *bridge; |
| 186 | u8 cap_ptr; | 187 | u8 cap_ptr; |
| @@ -210,7 +211,7 @@ static int agp_sis_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 210 | return agp_add_bridge(bridge); | 211 | return agp_add_bridge(bridge); |
| 211 | } | 212 | } |
| 212 | 213 | ||
| 213 | static void agp_sis_remove(struct pci_dev *pdev) | 214 | static void __devexit agp_sis_remove(struct pci_dev *pdev) |
| 214 | { | 215 | { |
| 215 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 216 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 216 | 217 | ||
diff --git a/drivers/char/agp/sworks-agp.c b/drivers/char/agp/sworks-agp.c index 9b163b49d97..f02f9b07fd4 100644 --- a/drivers/char/agp/sworks-agp.c +++ b/drivers/char/agp/sworks-agp.c | |||
| @@ -445,8 +445,8 @@ static const struct agp_bridge_driver sworks_driver = { | |||
| 445 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 445 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
| 446 | }; | 446 | }; |
| 447 | 447 | ||
| 448 | static int agp_serverworks_probe(struct pci_dev *pdev, | 448 | static int __devinit agp_serverworks_probe(struct pci_dev *pdev, |
| 449 | const struct pci_device_id *ent) | 449 | const struct pci_device_id *ent) |
| 450 | { | 450 | { |
| 451 | struct agp_bridge_data *bridge; | 451 | struct agp_bridge_data *bridge; |
| 452 | struct pci_dev *bridge_dev; | 452 | struct pci_dev *bridge_dev; |
| @@ -518,7 +518,7 @@ static int agp_serverworks_probe(struct pci_dev *pdev, | |||
| 518 | return agp_add_bridge(bridge); | 518 | return agp_add_bridge(bridge); |
| 519 | } | 519 | } |
| 520 | 520 | ||
| 521 | static void agp_serverworks_remove(struct pci_dev *pdev) | 521 | static void __devexit agp_serverworks_remove(struct pci_dev *pdev) |
| 522 | { | 522 | { |
| 523 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 523 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 524 | 524 | ||
diff --git a/drivers/char/agp/uninorth-agp.c b/drivers/char/agp/uninorth-agp.c index a56ee9bedd1..a32c492baf5 100644 --- a/drivers/char/agp/uninorth-agp.c +++ b/drivers/char/agp/uninorth-agp.c | |||
| @@ -557,7 +557,7 @@ const struct agp_bridge_driver u3_agp_driver = { | |||
| 557 | .needs_scratch_page = true, | 557 | .needs_scratch_page = true, |
| 558 | }; | 558 | }; |
| 559 | 559 | ||
| 560 | static struct agp_device_ids uninorth_agp_device_ids[] = { | 560 | static struct agp_device_ids uninorth_agp_device_ids[] __devinitdata = { |
| 561 | { | 561 | { |
| 562 | .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP, | 562 | .device_id = PCI_DEVICE_ID_APPLE_UNI_N_AGP, |
| 563 | .chipset_name = "UniNorth", | 563 | .chipset_name = "UniNorth", |
| @@ -592,8 +592,8 @@ static struct agp_device_ids uninorth_agp_device_ids[] = { | |||
| 592 | }, | 592 | }, |
| 593 | }; | 593 | }; |
| 594 | 594 | ||
| 595 | static int agp_uninorth_probe(struct pci_dev *pdev, | 595 | static int __devinit agp_uninorth_probe(struct pci_dev *pdev, |
| 596 | const struct pci_device_id *ent) | 596 | const struct pci_device_id *ent) |
| 597 | { | 597 | { |
| 598 | struct agp_device_ids *devs = uninorth_agp_device_ids; | 598 | struct agp_device_ids *devs = uninorth_agp_device_ids; |
| 599 | struct agp_bridge_data *bridge; | 599 | struct agp_bridge_data *bridge; |
| @@ -663,7 +663,7 @@ static int agp_uninorth_probe(struct pci_dev *pdev, | |||
| 663 | return agp_add_bridge(bridge); | 663 | return agp_add_bridge(bridge); |
| 664 | } | 664 | } |
| 665 | 665 | ||
| 666 | static void agp_uninorth_remove(struct pci_dev *pdev) | 666 | static void __devexit agp_uninorth_remove(struct pci_dev *pdev) |
| 667 | { | 667 | { |
| 668 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 668 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 669 | 669 | ||
diff --git a/drivers/char/agp/via-agp.c b/drivers/char/agp/via-agp.c index 74d3aa3773b..8bc38493740 100644 --- a/drivers/char/agp/via-agp.c +++ b/drivers/char/agp/via-agp.c | |||
| @@ -224,7 +224,7 @@ static const struct agp_bridge_driver via_driver = { | |||
| 224 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, | 224 | .agp_type_to_mask_type = agp_generic_type_to_mask_type, |
| 225 | }; | 225 | }; |
| 226 | 226 | ||
| 227 | static struct agp_device_ids via_agp_device_ids[] = | 227 | static struct agp_device_ids via_agp_device_ids[] __devinitdata = |
| 228 | { | 228 | { |
| 229 | { | 229 | { |
| 230 | .device_id = PCI_DEVICE_ID_VIA_82C597_0, | 230 | .device_id = PCI_DEVICE_ID_VIA_82C597_0, |
| @@ -438,7 +438,8 @@ static void check_via_agp3 (struct agp_bridge_data *bridge) | |||
| 438 | } | 438 | } |
| 439 | 439 | ||
| 440 | 440 | ||
| 441 | static int agp_via_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | 441 | static int __devinit agp_via_probe(struct pci_dev *pdev, |
| 442 | const struct pci_device_id *ent) | ||
| 442 | { | 443 | { |
| 443 | struct agp_device_ids *devs = via_agp_device_ids; | 444 | struct agp_device_ids *devs = via_agp_device_ids; |
| 444 | struct agp_bridge_data *bridge; | 445 | struct agp_bridge_data *bridge; |
| @@ -484,7 +485,7 @@ static int agp_via_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 484 | return agp_add_bridge(bridge); | 485 | return agp_add_bridge(bridge); |
| 485 | } | 486 | } |
| 486 | 487 | ||
| 487 | static void agp_via_remove(struct pci_dev *pdev) | 488 | static void __devexit agp_via_remove(struct pci_dev *pdev) |
| 488 | { | 489 | { |
| 489 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); | 490 | struct agp_bridge_data *bridge = pci_get_drvdata(pdev); |
| 490 | 491 | ||
diff --git a/drivers/char/apm-emulation.c b/drivers/char/apm-emulation.c index 46118f84594..a7346ab97a3 100644 --- a/drivers/char/apm-emulation.c +++ b/drivers/char/apm-emulation.c | |||
| @@ -31,6 +31,7 @@ | |||
| 31 | #include <linux/kthread.h> | 31 | #include <linux/kthread.h> |
| 32 | #include <linux/delay.h> | 32 | #include <linux/delay.h> |
| 33 | 33 | ||
| 34 | #include <asm/system.h> | ||
| 34 | 35 | ||
| 35 | /* | 36 | /* |
| 36 | * The apm_bios device is one of the misc char devices. | 37 | * The apm_bios device is one of the misc char devices. |
| @@ -39,7 +40,10 @@ | |||
| 39 | #define APM_MINOR_DEV 134 | 40 | #define APM_MINOR_DEV 134 |
| 40 | 41 | ||
| 41 | /* | 42 | /* |
| 42 | * One option can be changed at boot time as follows: | 43 | * See Documentation/Config.help for the configuration options. |
| 44 | * | ||
| 45 | * Various options can be changed at boot time as follows: | ||
| 46 | * (We allow underscores for compatibility with the modules code) | ||
| 43 | * apm=on/off enable/disable APM | 47 | * apm=on/off enable/disable APM |
| 44 | */ | 48 | */ |
| 45 | 49 | ||
| @@ -296,13 +300,17 @@ apm_ioctl(struct file *filp, u_int cmd, u_long arg) | |||
| 296 | /* | 300 | /* |
| 297 | * Wait for the suspend/resume to complete. If there | 301 | * Wait for the suspend/resume to complete. If there |
| 298 | * are pending acknowledges, we wait here for them. | 302 | * are pending acknowledges, we wait here for them. |
| 299 | * wait_event_freezable() is interruptible and pending | ||
| 300 | * signal can cause busy looping. We aren't doing | ||
| 301 | * anything critical, chill a bit on each iteration. | ||
| 302 | */ | 303 | */ |
| 303 | while (wait_event_freezable(apm_suspend_waitqueue, | 304 | freezer_do_not_count(); |
| 304 | as->suspend_state != SUSPEND_ACKED)) | 305 | |
| 305 | msleep(10); | 306 | wait_event(apm_suspend_waitqueue, |
| 307 | as->suspend_state == SUSPEND_DONE); | ||
| 308 | |||
| 309 | /* | ||
| 310 | * Since we are waiting until the suspend is done, the | ||
| 311 | * try_to_freeze() in freezer_count() will not trigger | ||
| 312 | */ | ||
| 313 | freezer_count(); | ||
| 306 | break; | 314 | break; |
| 307 | case SUSPEND_ACKTO: | 315 | case SUSPEND_ACKTO: |
| 308 | as->suspend_result = -ETIMEDOUT; | 316 | as->suspend_result = -ETIMEDOUT; |
diff --git a/drivers/char/bsr.c b/drivers/char/bsr.c index 97467053a01..0c688232aab 100644 --- a/drivers/char/bsr.c +++ b/drivers/char/bsr.c | |||
| @@ -297,6 +297,7 @@ static int __init bsr_init(void) | |||
| 297 | struct device_node *np; | 297 | struct device_node *np; |
| 298 | dev_t bsr_dev; | 298 | dev_t bsr_dev; |
| 299 | int ret = -ENODEV; | 299 | int ret = -ENODEV; |
| 300 | int result; | ||
| 300 | 301 | ||
| 301 | np = of_find_compatible_node(NULL, NULL, "ibm,bsr"); | 302 | np = of_find_compatible_node(NULL, NULL, "ibm,bsr"); |
| 302 | if (!np) | 303 | if (!np) |
| @@ -305,14 +306,13 @@ static int __init bsr_init(void) | |||
| 305 | bsr_class = class_create(THIS_MODULE, "bsr"); | 306 | bsr_class = class_create(THIS_MODULE, "bsr"); |
| 306 | if (IS_ERR(bsr_class)) { | 307 | if (IS_ERR(bsr_class)) { |
| 307 | printk(KERN_ERR "class_create() failed for bsr_class\n"); | 308 | printk(KERN_ERR "class_create() failed for bsr_class\n"); |
| 308 | ret = PTR_ERR(bsr_class); | ||
| 309 | goto out_err_1; | 309 | goto out_err_1; |
| 310 | } | 310 | } |
| 311 | bsr_class->dev_attrs = bsr_dev_attrs; | 311 | bsr_class->dev_attrs = bsr_dev_attrs; |
| 312 | 312 | ||
| 313 | ret = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr"); | 313 | result = alloc_chrdev_region(&bsr_dev, 0, BSR_MAX_DEVS, "bsr"); |
| 314 | bsr_major = MAJOR(bsr_dev); | 314 | bsr_major = MAJOR(bsr_dev); |
| 315 | if (ret < 0) { | 315 | if (result < 0) { |
| 316 | printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n"); | 316 | printk(KERN_ERR "alloc_chrdev_region() failed for bsr\n"); |
| 317 | goto out_err_2; | 317 | goto out_err_2; |
| 318 | } | 318 | } |
diff --git a/drivers/char/ds1302.c b/drivers/char/ds1302.c index 7d34b203718..ed8303f9890 100644 --- a/drivers/char/ds1302.c +++ b/drivers/char/ds1302.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
| 25 | #include <linux/io.h> | 25 | #include <linux/io.h> |
| 26 | 26 | ||
| 27 | #include <asm/system.h> | ||
| 27 | #include <asm/rtc.h> | 28 | #include <asm/rtc.h> |
| 28 | #if defined(CONFIG_M32R) | 29 | #if defined(CONFIG_M32R) |
| 29 | #include <asm/m32r.h> | 30 | #include <asm/m32r.h> |
diff --git a/drivers/char/ds1620.c b/drivers/char/ds1620.c index 24ffd8cec51..aab9605f0b4 100644 --- a/drivers/char/ds1620.c +++ b/drivers/char/ds1620.c | |||
| @@ -74,21 +74,21 @@ static inline void netwinder_ds1620_reset(void) | |||
| 74 | 74 | ||
| 75 | static inline void netwinder_lock(unsigned long *flags) | 75 | static inline void netwinder_lock(unsigned long *flags) |
| 76 | { | 76 | { |
| 77 | raw_spin_lock_irqsave(&nw_gpio_lock, *flags); | 77 | spin_lock_irqsave(&nw_gpio_lock, *flags); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| 80 | static inline void netwinder_unlock(unsigned long *flags) | 80 | static inline void netwinder_unlock(unsigned long *flags) |
| 81 | { | 81 | { |
| 82 | raw_spin_unlock_irqrestore(&nw_gpio_lock, *flags); | 82 | spin_unlock_irqrestore(&nw_gpio_lock, *flags); |
| 83 | } | 83 | } |
| 84 | 84 | ||
| 85 | static inline void netwinder_set_fan(int i) | 85 | static inline void netwinder_set_fan(int i) |
| 86 | { | 86 | { |
| 87 | unsigned long flags; | 87 | unsigned long flags; |
| 88 | 88 | ||
| 89 | raw_spin_lock_irqsave(&nw_gpio_lock, flags); | 89 | spin_lock_irqsave(&nw_gpio_lock, flags); |
| 90 | nw_gpio_modify_op(GPIO_FAN, i ? GPIO_FAN : 0); | 90 | nw_gpio_modify_op(GPIO_FAN, i ? GPIO_FAN : 0); |
| 91 | raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); | 91 | spin_unlock_irqrestore(&nw_gpio_lock, flags); |
| 92 | } | 92 | } |
| 93 | 93 | ||
| 94 | static inline int netwinder_get_fan(void) | 94 | static inline int netwinder_get_fan(void) |
diff --git a/drivers/char/efirtc.c b/drivers/char/efirtc.c index a082d00b0f1..53c524e7b82 100644 --- a/drivers/char/efirtc.c +++ b/drivers/char/efirtc.c | |||
| @@ -37,6 +37,7 @@ | |||
| 37 | #include <linux/efi.h> | 37 | #include <linux/efi.h> |
| 38 | #include <linux/uaccess.h> | 38 | #include <linux/uaccess.h> |
| 39 | 39 | ||
| 40 | #include <asm/system.h> | ||
| 40 | 41 | ||
| 41 | #define EFI_RTC_VERSION "0.4" | 42 | #define EFI_RTC_VERSION "0.4" |
| 42 | 43 | ||
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c index 21cb980f115..f773a9dd14f 100644 --- a/drivers/char/genrtc.c +++ b/drivers/char/genrtc.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | #include <linux/workqueue.h> | 56 | #include <linux/workqueue.h> |
| 57 | 57 | ||
| 58 | #include <asm/uaccess.h> | 58 | #include <asm/uaccess.h> |
| 59 | #include <asm/system.h> | ||
| 59 | #include <asm/rtc.h> | 60 | #include <asm/rtc.h> |
| 60 | 61 | ||
| 61 | /* | 62 | /* |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index fe6d4be4829..0833896cf6f 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
| @@ -36,6 +36,7 @@ | |||
| 36 | #include <linux/io.h> | 36 | #include <linux/io.h> |
| 37 | 37 | ||
| 38 | #include <asm/current.h> | 38 | #include <asm/current.h> |
| 39 | #include <asm/system.h> | ||
| 39 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
| 40 | #include <asm/div64.h> | 41 | #include <asm/div64.h> |
| 41 | 42 | ||
| @@ -816,7 +817,7 @@ static unsigned long __hpet_calibrate(struct hpets *hpetp) | |||
| 816 | 817 | ||
| 817 | static unsigned long hpet_calibrate(struct hpets *hpetp) | 818 | static unsigned long hpet_calibrate(struct hpets *hpetp) |
| 818 | { | 819 | { |
| 819 | unsigned long ret = ~0UL; | 820 | unsigned long ret = -1; |
| 820 | unsigned long tmp; | 821 | unsigned long tmp; |
| 821 | 822 | ||
| 822 | /* | 823 | /* |
| @@ -906,8 +907,8 @@ int hpet_alloc(struct hpet_data *hdp) | |||
| 906 | hpetp->hp_which, hdp->hd_phys_address, | 907 | hpetp->hp_which, hdp->hd_phys_address, |
| 907 | hpetp->hp_ntimer > 1 ? "s" : ""); | 908 | hpetp->hp_ntimer > 1 ? "s" : ""); |
| 908 | for (i = 0; i < hpetp->hp_ntimer; i++) | 909 | for (i = 0; i < hpetp->hp_ntimer; i++) |
| 909 | printk(KERN_CONT "%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); | 910 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); |
| 910 | printk(KERN_CONT "\n"); | 911 | printk("\n"); |
| 911 | 912 | ||
| 912 | temp = hpetp->hp_tick_freq; | 913 | temp = hpetp->hp_tick_freq; |
| 913 | remainder = do_div(temp, 1000000); | 914 | remainder = do_div(temp, 1000000); |
| @@ -1001,9 +1002,6 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
| 1001 | irqp = &res->data.extended_irq; | 1002 | irqp = &res->data.extended_irq; |
| 1002 | 1003 | ||
| 1003 | for (i = 0; i < irqp->interrupt_count; i++) { | 1004 | for (i = 0; i < irqp->interrupt_count; i++) { |
| 1004 | if (hdp->hd_nirqs >= HPET_MAX_TIMERS) | ||
| 1005 | break; | ||
| 1006 | |||
| 1007 | irq = acpi_register_gsi(NULL, irqp->interrupts[i], | 1005 | irq = acpi_register_gsi(NULL, irqp->interrupts[i], |
| 1008 | irqp->triggering, irqp->polarity); | 1006 | irqp->triggering, irqp->polarity); |
| 1009 | if (irq < 0) | 1007 | if (irq < 0) |
diff --git a/drivers/char/hw_random/Kconfig b/drivers/char/hw_random/Kconfig index c5a0262251b..1d2ebc7a494 100644 --- a/drivers/char/hw_random/Kconfig +++ b/drivers/char/hw_random/Kconfig | |||
| @@ -60,33 +60,6 @@ config HW_RANDOM_AMD | |||
| 60 | 60 | ||
| 61 | If unsure, say Y. | 61 | If unsure, say Y. |
| 62 | 62 | ||
| 63 | config HW_RANDOM_ATMEL | ||
| 64 | tristate "Atmel Random Number Generator support" | ||
| 65 | depends on HW_RANDOM && HAVE_CLK | ||
| 66 | default (HW_RANDOM && ARCH_AT91) | ||
| 67 | ---help--- | ||
| 68 | This driver provides kernel-side support for the Random Number | ||
| 69 | Generator hardware found on Atmel AT91 devices. | ||
| 70 | |||
| 71 | To compile this driver as a module, choose M here: the | ||
| 72 | module will be called atmel-rng. | ||
| 73 | |||
| 74 | If unsure, say Y. | ||
| 75 | |||
| 76 | config HW_RANDOM_BCM63XX | ||
| 77 | tristate "Broadcom BCM63xx Random Number Generator support" | ||
| 78 | depends on HW_RANDOM && BCM63XX | ||
| 79 | default HW_RANDOM | ||
| 80 | ---help--- | ||
| 81 | This driver provides kernel-side support for the Random Number | ||
| 82 | Generator hardware found on the Broadcom BCM63xx SoCs. | ||
| 83 | |||
| 84 | To compile this driver as a module, choose M here: the | ||
| 85 | module will be called bcm63xx-rng | ||
| 86 | |||
| 87 | If unusure, say Y. | ||
| 88 | |||
| 89 | |||
| 90 | config HW_RANDOM_GEODE | 63 | config HW_RANDOM_GEODE |
| 91 | tristate "AMD Geode HW Random Number Generator support" | 64 | tristate "AMD Geode HW Random Number Generator support" |
| 92 | depends on HW_RANDOM && X86_32 && PCI | 65 | depends on HW_RANDOM && X86_32 && PCI |
| @@ -127,12 +100,12 @@ config HW_RANDOM_VIA | |||
| 127 | If unsure, say Y. | 100 | If unsure, say Y. |
| 128 | 101 | ||
| 129 | config HW_RANDOM_IXP4XX | 102 | config HW_RANDOM_IXP4XX |
| 130 | tristate "Intel IXP4xx NPU HW Pseudo-Random Number Generator support" | 103 | tristate "Intel IXP4xx NPU HW Random Number Generator support" |
| 131 | depends on HW_RANDOM && ARCH_IXP4XX | 104 | depends on HW_RANDOM && ARCH_IXP4XX |
| 132 | default HW_RANDOM | 105 | default HW_RANDOM |
| 133 | ---help--- | 106 | ---help--- |
| 134 | This driver provides kernel-side support for the Pseudo-Random | 107 | This driver provides kernel-side support for the Random |
| 135 | Number Generator hardware found on the Intel IXP45x/46x NPU. | 108 | Number Generator hardware found on the Intel IXP4xx NPU. |
| 136 | 109 | ||
| 137 | To compile this driver as a module, choose M here: the | 110 | To compile this driver as a module, choose M here: the |
| 138 | module will be called ixp4xx-rng. | 111 | module will be called ixp4xx-rng. |
| @@ -216,7 +189,7 @@ config HW_RANDOM_MXC_RNGA | |||
| 216 | 189 | ||
| 217 | config HW_RANDOM_NOMADIK | 190 | config HW_RANDOM_NOMADIK |
| 218 | tristate "ST-Ericsson Nomadik Random Number Generator support" | 191 | tristate "ST-Ericsson Nomadik Random Number Generator support" |
| 219 | depends on HW_RANDOM && ARCH_NOMADIK | 192 | depends on HW_RANDOM && PLAT_NOMADIK |
| 220 | ---help--- | 193 | ---help--- |
| 221 | This driver provides kernel-side support for the Random Number | 194 | This driver provides kernel-side support for the Random Number |
| 222 | Generator hardware found on ST-Ericsson SoCs (8815 and 8500). | 195 | Generator hardware found on ST-Ericsson SoCs (8815 and 8500). |
| @@ -249,56 +222,3 @@ config HW_RANDOM_PPC4XX | |||
| 249 | module will be called ppc4xx-rng. | 222 | module will be called ppc4xx-rng. |
| 250 | 223 | ||
| 251 | If unsure, say N. | 224 | If unsure, say N. |
| 252 | |||
| 253 | config UML_RANDOM | ||
| 254 | depends on UML | ||
| 255 | tristate "Hardware random number generator" | ||
| 256 | help | ||
| 257 | This option enables UML's "hardware" random number generator. It | ||
| 258 | attaches itself to the host's /dev/random, supplying as much entropy | ||
| 259 | as the host has, rather than the small amount the UML gets from its | ||
| 260 | own drivers. It registers itself as a standard hardware random number | ||
| 261 | generator, major 10, minor 183, and the canonical device name is | ||
| 262 | /dev/hwrng. | ||
| 263 | The way to make use of this is to install the rng-tools package | ||
| 264 | (check your distro, or download from | ||
| 265 | http://sourceforge.net/projects/gkernel/). rngd periodically reads | ||
| 266 | /dev/hwrng and injects the entropy into /dev/random. | ||
| 267 | |||
| 268 | config HW_RANDOM_PSERIES | ||
| 269 | tristate "pSeries HW Random Number Generator support" | ||
| 270 | depends on HW_RANDOM && PPC64 && IBMVIO | ||
| 271 | default HW_RANDOM | ||
| 272 | ---help--- | ||
| 273 | This driver provides kernel-side support for the Random Number | ||
| 274 | Generator hardware found on POWER7+ machines and above | ||
| 275 | |||
| 276 | To compile this driver as a module, choose M here: the | ||
| 277 | module will be called pseries-rng. | ||
| 278 | |||
| 279 | If unsure, say Y. | ||
| 280 | |||
| 281 | config HW_RANDOM_EXYNOS | ||
| 282 | tristate "EXYNOS HW random number generator support" | ||
| 283 | depends on HW_RANDOM && HAS_IOMEM && HAVE_CLK | ||
| 284 | ---help--- | ||
| 285 | This driver provides kernel-side support for the Random Number | ||
| 286 | Generator hardware found on EXYNOS SOCs. | ||
| 287 | |||
| 288 | To compile this driver as a module, choose M here: the | ||
| 289 | module will be called exynos-rng. | ||
| 290 | |||
| 291 | If unsure, say Y. | ||
| 292 | |||
| 293 | config HW_RANDOM_TPM | ||
| 294 | tristate "TPM HW Random Number Generator support" | ||
| 295 | depends on HW_RANDOM && TCG_TPM | ||
| 296 | default HW_RANDOM | ||
| 297 | ---help--- | ||
| 298 | This driver provides kernel-side support for the Random Number | ||
| 299 | Generator in the Trusted Platform Module | ||
| 300 | |||
| 301 | To compile this driver as a module, choose M here: the | ||
| 302 | module will be called tpm-rng. | ||
| 303 | |||
| 304 | If unsure, say Y. | ||
diff --git a/drivers/char/hw_random/Makefile b/drivers/char/hw_random/Makefile index 1fd7eec9fbf..c88f244c8a7 100644 --- a/drivers/char/hw_random/Makefile +++ b/drivers/char/hw_random/Makefile | |||
| @@ -7,8 +7,6 @@ rng-core-y := core.o | |||
| 7 | obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o | 7 | obj-$(CONFIG_HW_RANDOM_TIMERIOMEM) += timeriomem-rng.o |
| 8 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o | 8 | obj-$(CONFIG_HW_RANDOM_INTEL) += intel-rng.o |
| 9 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o | 9 | obj-$(CONFIG_HW_RANDOM_AMD) += amd-rng.o |
| 10 | obj-$(CONFIG_HW_RANDOM_ATMEL) += atmel-rng.o | ||
| 11 | obj-$(CONFIG_HW_RANDOM_BCM63XX) += bcm63xx-rng.o | ||
| 12 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o | 10 | obj-$(CONFIG_HW_RANDOM_GEODE) += geode-rng.o |
| 13 | obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o | 11 | obj-$(CONFIG_HW_RANDOM_N2RNG) += n2-rng.o |
| 14 | n2-rng-y := n2-drv.o n2-asm.o | 12 | n2-rng-y := n2-drv.o n2-asm.o |
| @@ -23,6 +21,3 @@ obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o | |||
| 23 | obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o | 21 | obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o |
| 24 | obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o | 22 | obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o |
| 25 | obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o | 23 | obj-$(CONFIG_HW_RANDOM_PPC4XX) += ppc4xx-rng.o |
| 26 | obj-$(CONFIG_HW_RANDOM_PSERIES) += pseries-rng.o | ||
| 27 | obj-$(CONFIG_HW_RANDOM_EXYNOS) += exynos-rng.o | ||
| 28 | obj-$(CONFIG_HW_RANDOM_TPM) += tpm-rng.o | ||
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c deleted file mode 100644 index 7c73d4aca36..00000000000 --- a/drivers/char/hw_random/atmel-rng.c +++ /dev/null | |||
| @@ -1,155 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2011 Peter Korsgaard <jacmet@sunsite.dk> | ||
| 3 | * | ||
| 4 | * This file is licensed under the terms of the GNU General Public | ||
| 5 | * License version 2. This program is licensed "as is" without any | ||
| 6 | * warranty of any kind, whether express or implied. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/slab.h> | ||
| 12 | #include <linux/err.h> | ||
| 13 | #include <linux/clk.h> | ||
| 14 | #include <linux/io.h> | ||
| 15 | #include <linux/hw_random.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | |||
| 18 | #define TRNG_CR 0x00 | ||
| 19 | #define TRNG_ISR 0x1c | ||
| 20 | #define TRNG_ODATA 0x50 | ||
| 21 | |||
| 22 | #define TRNG_KEY 0x524e4700 /* RNG */ | ||
| 23 | |||
| 24 | struct atmel_trng { | ||
| 25 | struct clk *clk; | ||
| 26 | void __iomem *base; | ||
| 27 | struct hwrng rng; | ||
| 28 | }; | ||
| 29 | |||
| 30 | static int atmel_trng_read(struct hwrng *rng, void *buf, size_t max, | ||
| 31 | bool wait) | ||
| 32 | { | ||
| 33 | struct atmel_trng *trng = container_of(rng, struct atmel_trng, rng); | ||
| 34 | u32 *data = buf; | ||
| 35 | |||
| 36 | /* data ready? */ | ||
| 37 | if (readl(trng->base + TRNG_ISR) & 1) { | ||
| 38 | *data = readl(trng->base + TRNG_ODATA); | ||
| 39 | /* | ||
| 40 | ensure data ready is only set again AFTER the next data | ||
| 41 | word is ready in case it got set between checking ISR | ||
| 42 | and reading ODATA, so we don't risk re-reading the | ||
| 43 | same word | ||
| 44 | */ | ||
| 45 | readl(trng->base + TRNG_ISR); | ||
| 46 | return 4; | ||
| 47 | } else | ||
| 48 | return 0; | ||
| 49 | } | ||
| 50 | |||
| 51 | static int atmel_trng_probe(struct platform_device *pdev) | ||
| 52 | { | ||
| 53 | struct atmel_trng *trng; | ||
| 54 | struct resource *res; | ||
| 55 | int ret; | ||
| 56 | |||
| 57 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 58 | if (!res) | ||
| 59 | return -EINVAL; | ||
| 60 | |||
| 61 | trng = devm_kzalloc(&pdev->dev, sizeof(*trng), GFP_KERNEL); | ||
| 62 | if (!trng) | ||
| 63 | return -ENOMEM; | ||
| 64 | |||
| 65 | if (!devm_request_mem_region(&pdev->dev, res->start, | ||
| 66 | resource_size(res), pdev->name)) | ||
| 67 | return -EBUSY; | ||
| 68 | |||
| 69 | trng->base = devm_ioremap(&pdev->dev, res->start, resource_size(res)); | ||
| 70 | if (!trng->base) | ||
| 71 | return -EBUSY; | ||
| 72 | |||
| 73 | trng->clk = clk_get(&pdev->dev, NULL); | ||
| 74 | if (IS_ERR(trng->clk)) | ||
| 75 | return PTR_ERR(trng->clk); | ||
| 76 | |||
| 77 | ret = clk_enable(trng->clk); | ||
| 78 | if (ret) | ||
| 79 | goto err_enable; | ||
| 80 | |||
| 81 | writel(TRNG_KEY | 1, trng->base + TRNG_CR); | ||
| 82 | trng->rng.name = pdev->name; | ||
| 83 | trng->rng.read = atmel_trng_read; | ||
| 84 | |||
| 85 | ret = hwrng_register(&trng->rng); | ||
| 86 | if (ret) | ||
| 87 | goto err_register; | ||
| 88 | |||
| 89 | platform_set_drvdata(pdev, trng); | ||
| 90 | |||
| 91 | return 0; | ||
| 92 | |||
| 93 | err_register: | ||
| 94 | clk_disable(trng->clk); | ||
| 95 | err_enable: | ||
| 96 | clk_put(trng->clk); | ||
| 97 | |||
| 98 | return ret; | ||
| 99 | } | ||
| 100 | |||
| 101 | static int atmel_trng_remove(struct platform_device *pdev) | ||
| 102 | { | ||
| 103 | struct atmel_trng *trng = platform_get_drvdata(pdev); | ||
| 104 | |||
| 105 | hwrng_unregister(&trng->rng); | ||
| 106 | |||
| 107 | writel(TRNG_KEY, trng->base + TRNG_CR); | ||
| 108 | clk_disable(trng->clk); | ||
| 109 | clk_put(trng->clk); | ||
| 110 | |||
| 111 | platform_set_drvdata(pdev, NULL); | ||
| 112 | |||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | #ifdef CONFIG_PM | ||
| 117 | static int atmel_trng_suspend(struct device *dev) | ||
| 118 | { | ||
| 119 | struct atmel_trng *trng = dev_get_drvdata(dev); | ||
| 120 | |||
| 121 | clk_disable(trng->clk); | ||
| 122 | |||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static int atmel_trng_resume(struct device *dev) | ||
| 127 | { | ||
| 128 | struct atmel_trng *trng = dev_get_drvdata(dev); | ||
| 129 | |||
| 130 | return clk_enable(trng->clk); | ||
| 131 | } | ||
| 132 | |||
| 133 | static const struct dev_pm_ops atmel_trng_pm_ops = { | ||
| 134 | .suspend = atmel_trng_suspend, | ||
| 135 | .resume = atmel_trng_resume, | ||
| 136 | }; | ||
| 137 | #endif /* CONFIG_PM */ | ||
| 138 | |||
| 139 | static struct platform_driver atmel_trng_driver = { | ||
| 140 | .probe = atmel_trng_probe, | ||
| 141 | .remove = atmel_trng_remove, | ||
| 142 | .driver = { | ||
| 143 | .name = "atmel-trng", | ||
| 144 | .owner = THIS_MODULE, | ||
| 145 | #ifdef CONFIG_PM | ||
| 146 | .pm = &atmel_trng_pm_ops, | ||
| 147 | #endif /* CONFIG_PM */ | ||
| 148 | }, | ||
| 149 | }; | ||
| 150 | |||
| 151 | module_platform_driver(atmel_trng_driver); | ||
| 152 | |||
| 153 | MODULE_LICENSE("GPL"); | ||
| 154 | MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>"); | ||
| 155 | MODULE_DESCRIPTION("Atmel true random number generator driver"); | ||
diff --git a/drivers/char/hw_random/bcm63xx-rng.c b/drivers/char/hw_random/bcm63xx-rng.c deleted file mode 100644 index f343b7d0dfa..00000000000 --- a/drivers/char/hw_random/bcm63xx-rng.c +++ /dev/null | |||
| @@ -1,175 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Broadcom BCM63xx Random Number Generator support | ||
| 3 | * | ||
| 4 | * Copyright (C) 2011, Florian Fainelli <florian@openwrt.org> | ||
| 5 | * Copyright (C) 2009, Broadcom Corporation | ||
| 6 | * | ||
| 7 | */ | ||
| 8 | #include <linux/module.h> | ||
| 9 | #include <linux/slab.h> | ||
| 10 | #include <linux/io.h> | ||
| 11 | #include <linux/err.h> | ||
| 12 | #include <linux/clk.h> | ||
| 13 | #include <linux/platform_device.h> | ||
| 14 | #include <linux/hw_random.h> | ||
| 15 | |||
| 16 | #include <bcm63xx_io.h> | ||
| 17 | #include <bcm63xx_regs.h> | ||
| 18 | |||
| 19 | struct bcm63xx_rng_priv { | ||
| 20 | struct clk *clk; | ||
| 21 | void __iomem *regs; | ||
| 22 | }; | ||
| 23 | |||
| 24 | #define to_rng_priv(rng) ((struct bcm63xx_rng_priv *)rng->priv) | ||
| 25 | |||
| 26 | static int bcm63xx_rng_init(struct hwrng *rng) | ||
| 27 | { | ||
| 28 | struct bcm63xx_rng_priv *priv = to_rng_priv(rng); | ||
| 29 | u32 val; | ||
| 30 | |||
| 31 | val = bcm_readl(priv->regs + RNG_CTRL); | ||
| 32 | val |= RNG_EN; | ||
| 33 | bcm_writel(val, priv->regs + RNG_CTRL); | ||
| 34 | |||
| 35 | return 0; | ||
| 36 | } | ||
| 37 | |||
| 38 | static void bcm63xx_rng_cleanup(struct hwrng *rng) | ||
| 39 | { | ||
| 40 | struct bcm63xx_rng_priv *priv = to_rng_priv(rng); | ||
| 41 | u32 val; | ||
| 42 | |||
| 43 | val = bcm_readl(priv->regs + RNG_CTRL); | ||
| 44 | val &= ~RNG_EN; | ||
| 45 | bcm_writel(val, priv->regs + RNG_CTRL); | ||
| 46 | } | ||
| 47 | |||
| 48 | static int bcm63xx_rng_data_present(struct hwrng *rng, int wait) | ||
| 49 | { | ||
| 50 | struct bcm63xx_rng_priv *priv = to_rng_priv(rng); | ||
| 51 | |||
| 52 | return bcm_readl(priv->regs + RNG_STAT) & RNG_AVAIL_MASK; | ||
| 53 | } | ||
| 54 | |||
| 55 | static int bcm63xx_rng_data_read(struct hwrng *rng, u32 *data) | ||
| 56 | { | ||
| 57 | struct bcm63xx_rng_priv *priv = to_rng_priv(rng); | ||
| 58 | |||
| 59 | *data = bcm_readl(priv->regs + RNG_DATA); | ||
| 60 | |||
| 61 | return 4; | ||
| 62 | } | ||
| 63 | |||
| 64 | static int bcm63xx_rng_probe(struct platform_device *pdev) | ||
| 65 | { | ||
| 66 | struct resource *r; | ||
| 67 | struct clk *clk; | ||
| 68 | int ret; | ||
| 69 | struct bcm63xx_rng_priv *priv; | ||
| 70 | struct hwrng *rng; | ||
| 71 | |||
| 72 | r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 73 | if (!r) { | ||
| 74 | dev_err(&pdev->dev, "no iomem resource\n"); | ||
| 75 | ret = -ENXIO; | ||
| 76 | goto out; | ||
| 77 | } | ||
| 78 | |||
| 79 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | ||
| 80 | if (!priv) { | ||
| 81 | dev_err(&pdev->dev, "no memory for private structure\n"); | ||
| 82 | ret = -ENOMEM; | ||
| 83 | goto out; | ||
| 84 | } | ||
| 85 | |||
| 86 | rng = kzalloc(sizeof(*rng), GFP_KERNEL); | ||
| 87 | if (!rng) { | ||
| 88 | dev_err(&pdev->dev, "no memory for rng structure\n"); | ||
| 89 | ret = -ENOMEM; | ||
| 90 | goto out_free_priv; | ||
| 91 | } | ||
| 92 | |||
| 93 | platform_set_drvdata(pdev, rng); | ||
| 94 | rng->priv = (unsigned long)priv; | ||
| 95 | rng->name = pdev->name; | ||
| 96 | rng->init = bcm63xx_rng_init; | ||
| 97 | rng->cleanup = bcm63xx_rng_cleanup; | ||
| 98 | rng->data_present = bcm63xx_rng_data_present; | ||
| 99 | rng->data_read = bcm63xx_rng_data_read; | ||
| 100 | |||
| 101 | clk = clk_get(&pdev->dev, "ipsec"); | ||
| 102 | if (IS_ERR(clk)) { | ||
| 103 | dev_err(&pdev->dev, "no clock for device\n"); | ||
| 104 | ret = PTR_ERR(clk); | ||
| 105 | goto out_free_rng; | ||
| 106 | } | ||
| 107 | |||
| 108 | priv->clk = clk; | ||
| 109 | |||
| 110 | if (!devm_request_mem_region(&pdev->dev, r->start, | ||
| 111 | resource_size(r), pdev->name)) { | ||
| 112 | dev_err(&pdev->dev, "request mem failed"); | ||
| 113 | ret = -ENOMEM; | ||
| 114 | goto out_free_rng; | ||
| 115 | } | ||
| 116 | |||
| 117 | priv->regs = devm_ioremap_nocache(&pdev->dev, r->start, | ||
| 118 | resource_size(r)); | ||
| 119 | if (!priv->regs) { | ||
| 120 | dev_err(&pdev->dev, "ioremap failed"); | ||
| 121 | ret = -ENOMEM; | ||
| 122 | goto out_free_rng; | ||
| 123 | } | ||
| 124 | |||
| 125 | clk_enable(clk); | ||
| 126 | |||
| 127 | ret = hwrng_register(rng); | ||
| 128 | if (ret) { | ||
| 129 | dev_err(&pdev->dev, "failed to register rng device\n"); | ||
| 130 | goto out_clk_disable; | ||
| 131 | } | ||
| 132 | |||
| 133 | dev_info(&pdev->dev, "registered RNG driver\n"); | ||
| 134 | |||
| 135 | return 0; | ||
| 136 | |||
| 137 | out_clk_disable: | ||
| 138 | clk_disable(clk); | ||
| 139 | out_free_rng: | ||
| 140 | platform_set_drvdata(pdev, NULL); | ||
| 141 | kfree(rng); | ||
| 142 | out_free_priv: | ||
| 143 | kfree(priv); | ||
| 144 | out: | ||
| 145 | return ret; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int bcm63xx_rng_remove(struct platform_device *pdev) | ||
| 149 | { | ||
| 150 | struct hwrng *rng = platform_get_drvdata(pdev); | ||
| 151 | struct bcm63xx_rng_priv *priv = to_rng_priv(rng); | ||
| 152 | |||
| 153 | hwrng_unregister(rng); | ||
| 154 | clk_disable(priv->clk); | ||
| 155 | kfree(priv); | ||
| 156 | kfree(rng); | ||
| 157 | platform_set_drvdata(pdev, NULL); | ||
| 158 | |||
| 159 | return 0; | ||
| 160 | } | ||
| 161 | |||
| 162 | static struct platform_driver bcm63xx_rng_driver = { | ||
| 163 | .probe = bcm63xx_rng_probe, | ||
| 164 | .remove = bcm63xx_rng_remove, | ||
| 165 | .driver = { | ||
| 166 | .name = "bcm63xx-rng", | ||
| 167 | .owner = THIS_MODULE, | ||
| 168 | }, | ||
| 169 | }; | ||
| 170 | |||
| 171 | module_platform_driver(bcm63xx_rng_driver); | ||
| 172 | |||
| 173 | MODULE_AUTHOR("Florian Fainelli <florian@openwrt.org>"); | ||
| 174 | MODULE_DESCRIPTION("Broadcom BCM63xx RNG driver"); | ||
| 175 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/hw_random/exynos-rng.c b/drivers/char/hw_random/exynos-rng.c deleted file mode 100644 index 48bbfeca4b5..00000000000 --- a/drivers/char/hw_random/exynos-rng.c +++ /dev/null | |||
| @@ -1,182 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * exynos-rng.c - Random Number Generator driver for the exynos | ||
| 3 | * | ||
| 4 | * Copyright (C) 2012 Samsung Electronics | ||
| 5 | * Jonghwa Lee <jonghwa3.lee@smasung.com> | ||
| 6 | * | ||
| 7 | * This program is free software; you can redistribute it and/or modify | ||
| 8 | * it under the terms of the GNU General Public License as published by | ||
| 9 | * the Free Software Foundation; | ||
| 10 | * | ||
| 11 | * This program is distributed in the hope that it will be useful, | ||
| 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | * GNU General Public License for more details. | ||
| 15 | * | ||
| 16 | * You should have received a copy of the GNU General Public License | ||
| 17 | * along with this program; if not, write to the Free Software | ||
| 18 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/hw_random.h> | ||
| 23 | #include <linux/kernel.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/platform_device.h> | ||
| 28 | #include <linux/clk.h> | ||
| 29 | #include <linux/pm_runtime.h> | ||
| 30 | #include <linux/err.h> | ||
| 31 | |||
| 32 | #define EXYNOS_PRNG_STATUS_OFFSET 0x10 | ||
| 33 | #define EXYNOS_PRNG_SEED_OFFSET 0x140 | ||
| 34 | #define EXYNOS_PRNG_OUT1_OFFSET 0x160 | ||
| 35 | #define SEED_SETTING_DONE BIT(1) | ||
| 36 | #define PRNG_START 0x18 | ||
| 37 | #define PRNG_DONE BIT(5) | ||
| 38 | #define EXYNOS_AUTOSUSPEND_DELAY 100 | ||
| 39 | |||
| 40 | struct exynos_rng { | ||
| 41 | struct device *dev; | ||
| 42 | struct hwrng rng; | ||
| 43 | void __iomem *mem; | ||
| 44 | struct clk *clk; | ||
| 45 | }; | ||
| 46 | |||
| 47 | static u32 exynos_rng_readl(struct exynos_rng *rng, u32 offset) | ||
| 48 | { | ||
| 49 | return __raw_readl(rng->mem + offset); | ||
| 50 | } | ||
| 51 | |||
| 52 | static void exynos_rng_writel(struct exynos_rng *rng, u32 val, u32 offset) | ||
| 53 | { | ||
| 54 | __raw_writel(val, rng->mem + offset); | ||
| 55 | } | ||
| 56 | |||
| 57 | static int exynos_init(struct hwrng *rng) | ||
| 58 | { | ||
| 59 | struct exynos_rng *exynos_rng = container_of(rng, | ||
| 60 | struct exynos_rng, rng); | ||
| 61 | int i; | ||
| 62 | int ret = 0; | ||
| 63 | |||
| 64 | pm_runtime_get_sync(exynos_rng->dev); | ||
| 65 | |||
| 66 | for (i = 0 ; i < 5 ; i++) | ||
| 67 | exynos_rng_writel(exynos_rng, jiffies, | ||
| 68 | EXYNOS_PRNG_SEED_OFFSET + 4*i); | ||
| 69 | |||
| 70 | if (!(exynos_rng_readl(exynos_rng, EXYNOS_PRNG_STATUS_OFFSET) | ||
| 71 | & SEED_SETTING_DONE)) | ||
| 72 | ret = -EIO; | ||
| 73 | |||
| 74 | pm_runtime_put_noidle(exynos_rng->dev); | ||
| 75 | |||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | |||
| 79 | static int exynos_read(struct hwrng *rng, void *buf, | ||
| 80 | size_t max, bool wait) | ||
| 81 | { | ||
| 82 | struct exynos_rng *exynos_rng = container_of(rng, | ||
| 83 | struct exynos_rng, rng); | ||
| 84 | u32 *data = buf; | ||
| 85 | |||
| 86 | pm_runtime_get_sync(exynos_rng->dev); | ||
| 87 | |||
| 88 | exynos_rng_writel(exynos_rng, PRNG_START, 0); | ||
| 89 | |||
| 90 | while (!(exynos_rng_readl(exynos_rng, | ||
| 91 | EXYNOS_PRNG_STATUS_OFFSET) & PRNG_DONE)) | ||
| 92 | cpu_relax(); | ||
| 93 | |||
| 94 | exynos_rng_writel(exynos_rng, PRNG_DONE, EXYNOS_PRNG_STATUS_OFFSET); | ||
| 95 | |||
| 96 | *data = exynos_rng_readl(exynos_rng, EXYNOS_PRNG_OUT1_OFFSET); | ||
| 97 | |||
| 98 | pm_runtime_mark_last_busy(exynos_rng->dev); | ||
| 99 | pm_runtime_autosuspend(exynos_rng->dev); | ||
| 100 | |||
| 101 | return 4; | ||
| 102 | } | ||
| 103 | |||
| 104 | static int exynos_rng_probe(struct platform_device *pdev) | ||
| 105 | { | ||
| 106 | struct exynos_rng *exynos_rng; | ||
| 107 | |||
| 108 | exynos_rng = devm_kzalloc(&pdev->dev, sizeof(struct exynos_rng), | ||
| 109 | GFP_KERNEL); | ||
| 110 | if (!exynos_rng) | ||
| 111 | return -ENOMEM; | ||
| 112 | |||
| 113 | exynos_rng->dev = &pdev->dev; | ||
| 114 | exynos_rng->rng.name = "exynos"; | ||
| 115 | exynos_rng->rng.init = exynos_init; | ||
| 116 | exynos_rng->rng.read = exynos_read; | ||
| 117 | exynos_rng->clk = devm_clk_get(&pdev->dev, "secss"); | ||
| 118 | if (IS_ERR(exynos_rng->clk)) { | ||
| 119 | dev_err(&pdev->dev, "Couldn't get clock.\n"); | ||
| 120 | return -ENOENT; | ||
| 121 | } | ||
| 122 | |||
| 123 | exynos_rng->mem = devm_request_and_ioremap(&pdev->dev, | ||
| 124 | platform_get_resource(pdev, IORESOURCE_MEM, 0)); | ||
| 125 | if (!exynos_rng->mem) | ||
| 126 | return -EBUSY; | ||
| 127 | |||
| 128 | platform_set_drvdata(pdev, exynos_rng); | ||
| 129 | |||
| 130 | pm_runtime_set_autosuspend_delay(&pdev->dev, EXYNOS_AUTOSUSPEND_DELAY); | ||
| 131 | pm_runtime_use_autosuspend(&pdev->dev); | ||
| 132 | pm_runtime_enable(&pdev->dev); | ||
| 133 | |||
| 134 | return hwrng_register(&exynos_rng->rng); | ||
| 135 | } | ||
| 136 | |||
| 137 | static int exynos_rng_remove(struct platform_device *pdev) | ||
| 138 | { | ||
| 139 | struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); | ||
| 140 | |||
| 141 | hwrng_unregister(&exynos_rng->rng); | ||
| 142 | |||
| 143 | return 0; | ||
| 144 | } | ||
| 145 | |||
| 146 | static int exynos_rng_runtime_suspend(struct device *dev) | ||
| 147 | { | ||
| 148 | struct platform_device *pdev = to_platform_device(dev); | ||
| 149 | struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); | ||
| 150 | |||
| 151 | clk_disable_unprepare(exynos_rng->clk); | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | |||
| 156 | static int exynos_rng_runtime_resume(struct device *dev) | ||
| 157 | { | ||
| 158 | struct platform_device *pdev = to_platform_device(dev); | ||
| 159 | struct exynos_rng *exynos_rng = platform_get_drvdata(pdev); | ||
| 160 | |||
| 161 | return clk_prepare_enable(exynos_rng->clk); | ||
| 162 | } | ||
| 163 | |||
| 164 | |||
| 165 | UNIVERSAL_DEV_PM_OPS(exynos_rng_pm_ops, exynos_rng_runtime_suspend, | ||
| 166 | exynos_rng_runtime_resume, NULL); | ||
| 167 | |||
| 168 | static struct platform_driver exynos_rng_driver = { | ||
| 169 | .driver = { | ||
| 170 | .name = "exynos-rng", | ||
| 171 | .owner = THIS_MODULE, | ||
| 172 | .pm = &exynos_rng_pm_ops, | ||
| 173 | }, | ||
| 174 | .probe = exynos_rng_probe, | ||
| 175 | .remove = exynos_rng_remove, | ||
| 176 | }; | ||
| 177 | |||
| 178 | module_platform_driver(exynos_rng_driver); | ||
| 179 | |||
| 180 | MODULE_DESCRIPTION("EXYNOS 4 H/W Random Number Generator driver"); | ||
| 181 | MODULE_AUTHOR("Jonghwa Lee <jonghwa3.lee@samsung.com>"); | ||
| 182 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/hw_random/ixp4xx-rng.c b/drivers/char/hw_random/ixp4xx-rng.c index beec1627db3..263567f5f39 100644 --- a/drivers/char/hw_random/ixp4xx-rng.c +++ b/drivers/char/hw_random/ixp4xx-rng.c | |||
| @@ -45,9 +45,6 @@ static int __init ixp4xx_rng_init(void) | |||
| 45 | void __iomem * rng_base; | 45 | void __iomem * rng_base; |
| 46 | int err; | 46 | int err; |
| 47 | 47 | ||
| 48 | if (!cpu_is_ixp46x()) /* includes IXP455 */ | ||
| 49 | return -ENOSYS; | ||
| 50 | |||
| 51 | rng_base = ioremap(0x70002100, 4); | 48 | rng_base = ioremap(0x70002100, 4); |
| 52 | if (!rng_base) | 49 | if (!rng_base) |
| 53 | return -ENOMEM; | 50 | return -ENOMEM; |
| @@ -71,5 +68,5 @@ module_init(ixp4xx_rng_init); | |||
| 71 | module_exit(ixp4xx_rng_exit); | 68 | module_exit(ixp4xx_rng_exit); |
| 72 | 69 | ||
| 73 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); | 70 | MODULE_AUTHOR("Deepak Saxena <dsaxena@plexity.net>"); |
| 74 | MODULE_DESCRIPTION("H/W Pseudo-Random Number Generator (RNG) driver for IXP45x/46x"); | 71 | MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver for IXP4xx"); |
| 75 | MODULE_LICENSE("GPL"); | 72 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/hw_random/mxc-rnga.c b/drivers/char/hw_random/mxc-rnga.c index f05d85713fd..187c6be80f4 100644 --- a/drivers/char/hw_random/mxc-rnga.c +++ b/drivers/char/hw_random/mxc-rnga.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | #include <linux/ioport.h> | 24 | #include <linux/ioport.h> |
| 25 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
| 26 | #include <linux/hw_random.h> | 26 | #include <linux/hw_random.h> |
| 27 | #include <linux/delay.h> | ||
| 28 | #include <linux/io.h> | 27 | #include <linux/io.h> |
| 29 | 28 | ||
| 30 | /* RNGA Registers */ | 29 | /* RNGA Registers */ |
| @@ -59,47 +58,38 @@ | |||
| 59 | #define RNGA_STATUS_LAST_READ_STATUS 0x00000002 | 58 | #define RNGA_STATUS_LAST_READ_STATUS 0x00000002 |
| 60 | #define RNGA_STATUS_SECURITY_VIOLATION 0x00000001 | 59 | #define RNGA_STATUS_SECURITY_VIOLATION 0x00000001 |
| 61 | 60 | ||
| 62 | struct mxc_rng { | 61 | static struct platform_device *rng_dev; |
| 63 | struct device *dev; | ||
| 64 | struct hwrng rng; | ||
| 65 | void __iomem *mem; | ||
| 66 | struct clk *clk; | ||
| 67 | }; | ||
| 68 | 62 | ||
| 69 | static int mxc_rnga_data_present(struct hwrng *rng, int wait) | 63 | static int mxc_rnga_data_present(struct hwrng *rng) |
| 70 | { | 64 | { |
| 71 | int i; | 65 | int level; |
| 72 | struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng); | 66 | void __iomem *rng_base = (void __iomem *)rng->priv; |
| 73 | 67 | ||
| 74 | for (i = 0; i < 20; i++) { | 68 | /* how many random numbers is in FIFO? [0-16] */ |
| 75 | /* how many random numbers are in FIFO? [0-16] */ | 69 | level = ((__raw_readl(rng_base + RNGA_STATUS) & |
| 76 | int level = (__raw_readl(mxc_rng->mem + RNGA_STATUS) & | 70 | RNGA_STATUS_LEVEL_MASK) >> 8); |
| 77 | RNGA_STATUS_LEVEL_MASK) >> 8; | 71 | |
| 78 | if (level || !wait) | 72 | return level > 0 ? 1 : 0; |
| 79 | return !!level; | ||
| 80 | udelay(10); | ||
| 81 | } | ||
| 82 | return 0; | ||
| 83 | } | 73 | } |
| 84 | 74 | ||
| 85 | static int mxc_rnga_data_read(struct hwrng *rng, u32 * data) | 75 | static int mxc_rnga_data_read(struct hwrng *rng, u32 * data) |
| 86 | { | 76 | { |
| 87 | int err; | 77 | int err; |
| 88 | u32 ctrl; | 78 | u32 ctrl; |
| 89 | struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng); | 79 | void __iomem *rng_base = (void __iomem *)rng->priv; |
| 90 | 80 | ||
| 91 | /* retrieve a random number from FIFO */ | 81 | /* retrieve a random number from FIFO */ |
| 92 | *data = __raw_readl(mxc_rng->mem + RNGA_OUTPUT_FIFO); | 82 | *data = __raw_readl(rng_base + RNGA_OUTPUT_FIFO); |
| 93 | 83 | ||
| 94 | /* some error while reading this random number? */ | 84 | /* some error while reading this random number? */ |
| 95 | err = __raw_readl(mxc_rng->mem + RNGA_STATUS) & RNGA_STATUS_ERROR_INT; | 85 | err = __raw_readl(rng_base + RNGA_STATUS) & RNGA_STATUS_ERROR_INT; |
| 96 | 86 | ||
| 97 | /* if error: clear error interrupt, but doesn't return random number */ | 87 | /* if error: clear error interrupt, but doesn't return random number */ |
| 98 | if (err) { | 88 | if (err) { |
| 99 | dev_dbg(mxc_rng->dev, "Error while reading random number!\n"); | 89 | dev_dbg(&rng_dev->dev, "Error while reading random number!\n"); |
| 100 | ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL); | 90 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); |
| 101 | __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT, | 91 | __raw_writel(ctrl | RNGA_CONTROL_CLEAR_INT, |
| 102 | mxc_rng->mem + RNGA_CONTROL); | 92 | rng_base + RNGA_CONTROL); |
| 103 | return 0; | 93 | return 0; |
| 104 | } else | 94 | } else |
| 105 | return 4; | 95 | return 4; |
| @@ -108,22 +98,22 @@ static int mxc_rnga_data_read(struct hwrng *rng, u32 * data) | |||
| 108 | static int mxc_rnga_init(struct hwrng *rng) | 98 | static int mxc_rnga_init(struct hwrng *rng) |
| 109 | { | 99 | { |
| 110 | u32 ctrl, osc; | 100 | u32 ctrl, osc; |
| 111 | struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng); | 101 | void __iomem *rng_base = (void __iomem *)rng->priv; |
| 112 | 102 | ||
| 113 | /* wake up */ | 103 | /* wake up */ |
| 114 | ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL); | 104 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); |
| 115 | __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, mxc_rng->mem + RNGA_CONTROL); | 105 | __raw_writel(ctrl & ~RNGA_CONTROL_SLEEP, rng_base + RNGA_CONTROL); |
| 116 | 106 | ||
| 117 | /* verify if oscillator is working */ | 107 | /* verify if oscillator is working */ |
| 118 | osc = __raw_readl(mxc_rng->mem + RNGA_STATUS); | 108 | osc = __raw_readl(rng_base + RNGA_STATUS); |
| 119 | if (osc & RNGA_STATUS_OSC_DEAD) { | 109 | if (osc & RNGA_STATUS_OSC_DEAD) { |
| 120 | dev_err(mxc_rng->dev, "RNGA Oscillator is dead!\n"); | 110 | dev_err(&rng_dev->dev, "RNGA Oscillator is dead!\n"); |
| 121 | return -ENODEV; | 111 | return -ENODEV; |
| 122 | } | 112 | } |
| 123 | 113 | ||
| 124 | /* go running */ | 114 | /* go running */ |
| 125 | ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL); | 115 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); |
| 126 | __raw_writel(ctrl | RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL); | 116 | __raw_writel(ctrl | RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); |
| 127 | 117 | ||
| 128 | return 0; | 118 | return 0; |
| 129 | } | 119 | } |
| @@ -131,40 +121,40 @@ static int mxc_rnga_init(struct hwrng *rng) | |||
| 131 | static void mxc_rnga_cleanup(struct hwrng *rng) | 121 | static void mxc_rnga_cleanup(struct hwrng *rng) |
| 132 | { | 122 | { |
| 133 | u32 ctrl; | 123 | u32 ctrl; |
| 134 | struct mxc_rng *mxc_rng = container_of(rng, struct mxc_rng, rng); | 124 | void __iomem *rng_base = (void __iomem *)rng->priv; |
| 135 | 125 | ||
| 136 | ctrl = __raw_readl(mxc_rng->mem + RNGA_CONTROL); | 126 | ctrl = __raw_readl(rng_base + RNGA_CONTROL); |
| 137 | 127 | ||
| 138 | /* stop rnga */ | 128 | /* stop rnga */ |
| 139 | __raw_writel(ctrl & ~RNGA_CONTROL_GO, mxc_rng->mem + RNGA_CONTROL); | 129 | __raw_writel(ctrl & ~RNGA_CONTROL_GO, rng_base + RNGA_CONTROL); |
| 140 | } | 130 | } |
| 141 | 131 | ||
| 132 | static struct hwrng mxc_rnga = { | ||
| 133 | .name = "mxc-rnga", | ||
| 134 | .init = mxc_rnga_init, | ||
| 135 | .cleanup = mxc_rnga_cleanup, | ||
| 136 | .data_present = mxc_rnga_data_present, | ||
| 137 | .data_read = mxc_rnga_data_read | ||
| 138 | }; | ||
| 139 | |||
| 142 | static int __init mxc_rnga_probe(struct platform_device *pdev) | 140 | static int __init mxc_rnga_probe(struct platform_device *pdev) |
| 143 | { | 141 | { |
| 144 | int err = -ENODEV; | 142 | int err = -ENODEV; |
| 143 | struct clk *clk; | ||
| 145 | struct resource *res, *mem; | 144 | struct resource *res, *mem; |
| 146 | struct mxc_rng *mxc_rng; | 145 | void __iomem *rng_base = NULL; |
| 147 | 146 | ||
| 148 | mxc_rng = devm_kzalloc(&pdev->dev, sizeof(struct mxc_rng), | 147 | if (rng_dev) |
| 149 | GFP_KERNEL); | 148 | return -EBUSY; |
| 150 | if (!mxc_rng) | 149 | |
| 151 | return -ENOMEM; | 150 | clk = clk_get(&pdev->dev, "rng"); |
| 152 | 151 | if (IS_ERR(clk)) { | |
| 153 | mxc_rng->dev = &pdev->dev; | ||
| 154 | mxc_rng->rng.name = "mxc-rnga"; | ||
| 155 | mxc_rng->rng.init = mxc_rnga_init; | ||
| 156 | mxc_rng->rng.cleanup = mxc_rnga_cleanup, | ||
| 157 | mxc_rng->rng.data_present = mxc_rnga_data_present, | ||
| 158 | mxc_rng->rng.data_read = mxc_rnga_data_read, | ||
| 159 | |||
| 160 | mxc_rng->clk = devm_clk_get(&pdev->dev, NULL); | ||
| 161 | if (IS_ERR(mxc_rng->clk)) { | ||
| 162 | dev_err(&pdev->dev, "Could not get rng_clk!\n"); | 152 | dev_err(&pdev->dev, "Could not get rng_clk!\n"); |
| 163 | err = PTR_ERR(mxc_rng->clk); | 153 | err = PTR_ERR(clk); |
| 164 | goto out; | 154 | goto out; |
| 165 | } | 155 | } |
| 166 | 156 | ||
| 167 | clk_prepare_enable(mxc_rng->clk); | 157 | clk_enable(clk); |
| 168 | 158 | ||
| 169 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 159 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 170 | if (!res) { | 160 | if (!res) { |
| @@ -178,27 +168,36 @@ static int __init mxc_rnga_probe(struct platform_device *pdev) | |||
| 178 | goto err_region; | 168 | goto err_region; |
| 179 | } | 169 | } |
| 180 | 170 | ||
| 181 | mxc_rng->mem = ioremap(res->start, resource_size(res)); | 171 | rng_base = ioremap(res->start, resource_size(res)); |
| 182 | if (!mxc_rng->mem) { | 172 | if (!rng_base) { |
| 183 | err = -ENOMEM; | 173 | err = -ENOMEM; |
| 184 | goto err_ioremap; | 174 | goto err_ioremap; |
| 185 | } | 175 | } |
| 186 | 176 | ||
| 187 | err = hwrng_register(&mxc_rng->rng); | 177 | mxc_rnga.priv = (unsigned long)rng_base; |
| 178 | |||
| 179 | err = hwrng_register(&mxc_rnga); | ||
| 188 | if (err) { | 180 | if (err) { |
| 189 | dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err); | 181 | dev_err(&pdev->dev, "MXC RNGA registering failed (%d)\n", err); |
| 190 | goto err_ioremap; | 182 | goto err_register; |
| 191 | } | 183 | } |
| 192 | 184 | ||
| 185 | rng_dev = pdev; | ||
| 186 | |||
| 193 | dev_info(&pdev->dev, "MXC RNGA Registered.\n"); | 187 | dev_info(&pdev->dev, "MXC RNGA Registered.\n"); |
| 194 | 188 | ||
| 195 | return 0; | 189 | return 0; |
| 196 | 190 | ||
| 191 | err_register: | ||
| 192 | iounmap(rng_base); | ||
| 193 | rng_base = NULL; | ||
| 194 | |||
| 197 | err_ioremap: | 195 | err_ioremap: |
| 198 | release_mem_region(res->start, resource_size(res)); | 196 | release_mem_region(res->start, resource_size(res)); |
| 199 | 197 | ||
| 200 | err_region: | 198 | err_region: |
| 201 | clk_disable_unprepare(mxc_rng->clk); | 199 | clk_disable(clk); |
| 200 | clk_put(clk); | ||
| 202 | 201 | ||
| 203 | out: | 202 | out: |
| 204 | return err; | 203 | return err; |
| @@ -207,15 +206,17 @@ out: | |||
| 207 | static int __exit mxc_rnga_remove(struct platform_device *pdev) | 206 | static int __exit mxc_rnga_remove(struct platform_device *pdev) |
| 208 | { | 207 | { |
| 209 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 208 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 210 | struct mxc_rng *mxc_rng = platform_get_drvdata(pdev); | 209 | void __iomem *rng_base = (void __iomem *)mxc_rnga.priv; |
| 210 | struct clk *clk = clk_get(&pdev->dev, "rng"); | ||
| 211 | 211 | ||
| 212 | hwrng_unregister(&mxc_rng->rng); | 212 | hwrng_unregister(&mxc_rnga); |
| 213 | 213 | ||
| 214 | iounmap(mxc_rng->mem); | 214 | iounmap(rng_base); |
| 215 | 215 | ||
| 216 | release_mem_region(res->start, resource_size(res)); | 216 | release_mem_region(res->start, resource_size(res)); |
| 217 | 217 | ||
| 218 | clk_disable_unprepare(mxc_rng->clk); | 218 | clk_disable(clk); |
| 219 | clk_put(clk); | ||
| 219 | 220 | ||
| 220 | return 0; | 221 | return 0; |
| 221 | } | 222 | } |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 20b962e1d83..c3de70de00d 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
| @@ -25,7 +25,7 @@ | |||
| 25 | #define DRV_MODULE_VERSION "0.2" | 25 | #define DRV_MODULE_VERSION "0.2" |
| 26 | #define DRV_MODULE_RELDATE "July 27, 2011" | 26 | #define DRV_MODULE_RELDATE "July 27, 2011" |
| 27 | 27 | ||
| 28 | static char version[] = | 28 | static char version[] __devinitdata = |
| 29 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; | 29 | DRV_MODULE_NAME ".c:v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n"; |
| 30 | 30 | ||
| 31 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | 31 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); |
| @@ -611,7 +611,7 @@ static void n2rng_work(struct work_struct *work) | |||
| 611 | schedule_delayed_work(&np->work, HZ * 2); | 611 | schedule_delayed_work(&np->work, HZ * 2); |
| 612 | } | 612 | } |
| 613 | 613 | ||
| 614 | static void n2rng_driver_version(void) | 614 | static void __devinit n2rng_driver_version(void) |
| 615 | { | 615 | { |
| 616 | static int n2rng_version_printed; | 616 | static int n2rng_version_printed; |
| 617 | 617 | ||
| @@ -620,7 +620,7 @@ static void n2rng_driver_version(void) | |||
| 620 | } | 620 | } |
| 621 | 621 | ||
| 622 | static const struct of_device_id n2rng_match[]; | 622 | static const struct of_device_id n2rng_match[]; |
| 623 | static int n2rng_probe(struct platform_device *op) | 623 | static int __devinit n2rng_probe(struct platform_device *op) |
| 624 | { | 624 | { |
| 625 | const struct of_device_id *match; | 625 | const struct of_device_id *match; |
| 626 | int multi_capable; | 626 | int multi_capable; |
| @@ -719,7 +719,7 @@ out: | |||
| 719 | return err; | 719 | return err; |
| 720 | } | 720 | } |
| 721 | 721 | ||
| 722 | static int n2rng_remove(struct platform_device *op) | 722 | static int __devexit n2rng_remove(struct platform_device *op) |
| 723 | { | 723 | { |
| 724 | struct n2rng *np = dev_get_drvdata(&op->dev); | 724 | struct n2rng *np = dev_get_drvdata(&op->dev); |
| 725 | 725 | ||
| @@ -767,7 +767,18 @@ static struct platform_driver n2rng_driver = { | |||
| 767 | .of_match_table = n2rng_match, | 767 | .of_match_table = n2rng_match, |
| 768 | }, | 768 | }, |
| 769 | .probe = n2rng_probe, | 769 | .probe = n2rng_probe, |
| 770 | .remove = n2rng_remove, | 770 | .remove = __devexit_p(n2rng_remove), |
| 771 | }; | 771 | }; |
| 772 | 772 | ||
| 773 | module_platform_driver(n2rng_driver); | 773 | static int __init n2rng_init(void) |
| 774 | { | ||
| 775 | return platform_driver_register(&n2rng_driver); | ||
| 776 | } | ||
| 777 | |||
| 778 | static void __exit n2rng_exit(void) | ||
| 779 | { | ||
| 780 | platform_driver_unregister(&n2rng_driver); | ||
| 781 | } | ||
| 782 | |||
| 783 | module_init(n2rng_init); | ||
| 784 | module_exit(n2rng_exit); | ||
diff --git a/drivers/char/hw_random/nomadik-rng.c b/drivers/char/hw_random/nomadik-rng.c index 96de0249e59..52e08ca3ccd 100644 --- a/drivers/char/hw_random/nomadik-rng.c +++ b/drivers/char/hw_random/nomadik-rng.c | |||
| @@ -95,8 +95,6 @@ static struct amba_id nmk_rng_ids[] = { | |||
| 95 | {0, 0}, | 95 | {0, 0}, |
| 96 | }; | 96 | }; |
| 97 | 97 | ||
| 98 | MODULE_DEVICE_TABLE(amba, nmk_rng_ids); | ||
| 99 | |||
| 100 | static struct amba_driver nmk_rng_driver = { | 98 | static struct amba_driver nmk_rng_driver = { |
| 101 | .drv = { | 99 | .drv = { |
| 102 | .owner = THIS_MODULE, | 100 | .owner = THIS_MODULE, |
| @@ -107,6 +105,17 @@ static struct amba_driver nmk_rng_driver = { | |||
| 107 | .id_table = nmk_rng_ids, | 105 | .id_table = nmk_rng_ids, |
| 108 | }; | 106 | }; |
| 109 | 107 | ||
| 110 | module_amba_driver(nmk_rng_driver); | 108 | static int __init nmk_rng_init(void) |
| 109 | { | ||
| 110 | return amba_driver_register(&nmk_rng_driver); | ||
| 111 | } | ||
| 112 | |||
| 113 | static void __devexit nmk_rng_exit(void) | ||
| 114 | { | ||
| 115 | amba_driver_unregister(&nmk_rng_driver); | ||
| 116 | } | ||
| 117 | |||
| 118 | module_init(nmk_rng_init); | ||
| 119 | module_exit(nmk_rng_exit); | ||
| 111 | 120 | ||
| 112 | MODULE_LICENSE("GPL"); | 121 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c index 1eada566ca7..9cd0feca318 100644 --- a/drivers/char/hw_random/octeon-rng.c +++ b/drivers/char/hw_random/octeon-rng.c | |||
| @@ -56,7 +56,7 @@ static int octeon_rng_data_read(struct hwrng *rng, u32 *data) | |||
| 56 | return sizeof(u32); | 56 | return sizeof(u32); |
| 57 | } | 57 | } |
| 58 | 58 | ||
| 59 | static int octeon_rng_probe(struct platform_device *pdev) | 59 | static int __devinit octeon_rng_probe(struct platform_device *pdev) |
| 60 | { | 60 | { |
| 61 | struct resource *res_ports; | 61 | struct resource *res_ports; |
| 62 | struct resource *res_result; | 62 | struct resource *res_result; |
| @@ -75,35 +75,42 @@ static int octeon_rng_probe(struct platform_device *pdev) | |||
| 75 | 75 | ||
| 76 | res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 76 | res_ports = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 77 | if (!res_ports) | 77 | if (!res_ports) |
| 78 | return -ENOENT; | 78 | goto err_ports; |
| 79 | 79 | ||
| 80 | res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 80 | res_result = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
| 81 | if (!res_result) | 81 | if (!res_result) |
| 82 | return -ENOENT; | 82 | goto err_ports; |
| 83 | 83 | ||
| 84 | 84 | ||
| 85 | rng->control_status = devm_ioremap_nocache(&pdev->dev, | 85 | rng->control_status = devm_ioremap_nocache(&pdev->dev, |
| 86 | res_ports->start, | 86 | res_ports->start, |
| 87 | sizeof(u64)); | 87 | sizeof(u64)); |
| 88 | if (!rng->control_status) | 88 | if (!rng->control_status) |
| 89 | return -ENOENT; | 89 | goto err_ports; |
| 90 | 90 | ||
| 91 | rng->result = devm_ioremap_nocache(&pdev->dev, | 91 | rng->result = devm_ioremap_nocache(&pdev->dev, |
| 92 | res_result->start, | 92 | res_result->start, |
| 93 | sizeof(u64)); | 93 | sizeof(u64)); |
| 94 | if (!rng->result) | 94 | if (!rng->result) |
| 95 | return -ENOENT; | 95 | goto err_r; |
| 96 | 96 | ||
| 97 | rng->ops = ops; | 97 | rng->ops = ops; |
| 98 | 98 | ||
| 99 | dev_set_drvdata(&pdev->dev, &rng->ops); | 99 | dev_set_drvdata(&pdev->dev, &rng->ops); |
| 100 | ret = hwrng_register(&rng->ops); | 100 | ret = hwrng_register(&rng->ops); |
| 101 | if (ret) | 101 | if (ret) |
| 102 | return -ENOENT; | 102 | goto err; |
| 103 | 103 | ||
| 104 | dev_info(&pdev->dev, "Octeon Random Number Generator\n"); | 104 | dev_info(&pdev->dev, "Octeon Random Number Generator\n"); |
| 105 | 105 | ||
| 106 | return 0; | 106 | return 0; |
| 107 | err: | ||
| 108 | devm_iounmap(&pdev->dev, rng->control_status); | ||
| 109 | err_r: | ||
| 110 | devm_iounmap(&pdev->dev, rng->result); | ||
| 111 | err_ports: | ||
| 112 | devm_kfree(&pdev->dev, rng); | ||
| 113 | return -ENOENT; | ||
| 107 | } | 114 | } |
| 108 | 115 | ||
| 109 | static int __exit octeon_rng_remove(struct platform_device *pdev) | 116 | static int __exit octeon_rng_remove(struct platform_device *pdev) |
| @@ -124,7 +131,18 @@ static struct platform_driver octeon_rng_driver = { | |||
| 124 | .remove = __exit_p(octeon_rng_remove), | 131 | .remove = __exit_p(octeon_rng_remove), |
| 125 | }; | 132 | }; |
| 126 | 133 | ||
| 127 | module_platform_driver(octeon_rng_driver); | 134 | static int __init octeon_rng_mod_init(void) |
| 135 | { | ||
| 136 | return platform_driver_register(&octeon_rng_driver); | ||
| 137 | } | ||
| 138 | |||
| 139 | static void __exit octeon_rng_mod_exit(void) | ||
| 140 | { | ||
| 141 | platform_driver_unregister(&octeon_rng_driver); | ||
| 142 | } | ||
| 143 | |||
| 144 | module_init(octeon_rng_mod_init); | ||
| 145 | module_exit(octeon_rng_mod_exit); | ||
| 128 | 146 | ||
| 129 | MODULE_AUTHOR("David Daney"); | 147 | MODULE_AUTHOR("David Daney"); |
| 130 | MODULE_LICENSE("GPL"); | 148 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c index d8c54e25376..b757fac3cd1 100644 --- a/drivers/char/hw_random/omap-rng.c +++ b/drivers/char/hw_random/omap-rng.c | |||
| @@ -18,12 +18,11 @@ | |||
| 18 | #include <linux/module.h> | 18 | #include <linux/module.h> |
| 19 | #include <linux/init.h> | 19 | #include <linux/init.h> |
| 20 | #include <linux/random.h> | 20 | #include <linux/random.h> |
| 21 | #include <linux/clk.h> | ||
| 21 | #include <linux/err.h> | 22 | #include <linux/err.h> |
| 22 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 23 | #include <linux/hw_random.h> | 24 | #include <linux/hw_random.h> |
| 24 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
| 25 | #include <linux/slab.h> | ||
| 26 | #include <linux/pm_runtime.h> | ||
| 27 | 26 | ||
| 28 | #include <asm/io.h> | 27 | #include <asm/io.h> |
| 29 | 28 | ||
| @@ -45,36 +44,26 @@ | |||
| 45 | #define RNG_SYSSTATUS 0x44 /* System status | 44 | #define RNG_SYSSTATUS 0x44 /* System status |
| 46 | [0] = RESETDONE */ | 45 | [0] = RESETDONE */ |
| 47 | 46 | ||
| 48 | /** | 47 | static void __iomem *rng_base; |
| 49 | * struct omap_rng_private_data - RNG IP block-specific data | 48 | static struct clk *rng_ick; |
| 50 | * @base: virtual address of the beginning of the RNG IP block registers | 49 | static struct platform_device *rng_dev; |
| 51 | * @mem_res: struct resource * for the IP block registers physical memory | ||
| 52 | */ | ||
| 53 | struct omap_rng_private_data { | ||
| 54 | void __iomem *base; | ||
| 55 | struct resource *mem_res; | ||
| 56 | }; | ||
| 57 | 50 | ||
| 58 | static inline u32 omap_rng_read_reg(struct omap_rng_private_data *priv, int reg) | 51 | static inline u32 omap_rng_read_reg(int reg) |
| 59 | { | 52 | { |
| 60 | return __raw_readl(priv->base + reg); | 53 | return __raw_readl(rng_base + reg); |
| 61 | } | 54 | } |
| 62 | 55 | ||
| 63 | static inline void omap_rng_write_reg(struct omap_rng_private_data *priv, | 56 | static inline void omap_rng_write_reg(int reg, u32 val) |
| 64 | int reg, u32 val) | ||
| 65 | { | 57 | { |
| 66 | __raw_writel(val, priv->base + reg); | 58 | __raw_writel(val, rng_base + reg); |
| 67 | } | 59 | } |
| 68 | 60 | ||
| 69 | static int omap_rng_data_present(struct hwrng *rng, int wait) | 61 | static int omap_rng_data_present(struct hwrng *rng, int wait) |
| 70 | { | 62 | { |
| 71 | struct omap_rng_private_data *priv; | ||
| 72 | int data, i; | 63 | int data, i; |
| 73 | 64 | ||
| 74 | priv = (struct omap_rng_private_data *)rng->priv; | ||
| 75 | |||
| 76 | for (i = 0; i < 20; i++) { | 65 | for (i = 0; i < 20; i++) { |
| 77 | data = omap_rng_read_reg(priv, RNG_STAT_REG) ? 0 : 1; | 66 | data = omap_rng_read_reg(RNG_STAT_REG) ? 0 : 1; |
| 78 | if (data || !wait) | 67 | if (data || !wait) |
| 79 | break; | 68 | break; |
| 80 | /* RNG produces data fast enough (2+ MBit/sec, even | 69 | /* RNG produces data fast enough (2+ MBit/sec, even |
| @@ -89,13 +78,9 @@ static int omap_rng_data_present(struct hwrng *rng, int wait) | |||
| 89 | 78 | ||
| 90 | static int omap_rng_data_read(struct hwrng *rng, u32 *data) | 79 | static int omap_rng_data_read(struct hwrng *rng, u32 *data) |
| 91 | { | 80 | { |
| 92 | struct omap_rng_private_data *priv; | 81 | *data = omap_rng_read_reg(RNG_OUT_REG); |
| 93 | |||
| 94 | priv = (struct omap_rng_private_data *)rng->priv; | ||
| 95 | |||
| 96 | *data = omap_rng_read_reg(priv, RNG_OUT_REG); | ||
| 97 | 82 | ||
| 98 | return sizeof(u32); | 83 | return 4; |
| 99 | } | 84 | } |
| 100 | 85 | ||
| 101 | static struct hwrng omap_rng_ops = { | 86 | static struct hwrng omap_rng_ops = { |
| @@ -104,102 +89,111 @@ static struct hwrng omap_rng_ops = { | |||
| 104 | .data_read = omap_rng_data_read, | 89 | .data_read = omap_rng_data_read, |
| 105 | }; | 90 | }; |
| 106 | 91 | ||
| 107 | static int omap_rng_probe(struct platform_device *pdev) | 92 | static int __devinit omap_rng_probe(struct platform_device *pdev) |
| 108 | { | 93 | { |
| 109 | struct omap_rng_private_data *priv; | 94 | struct resource *res; |
| 110 | int ret; | 95 | int ret; |
| 111 | 96 | ||
| 112 | priv = kzalloc(sizeof(struct omap_rng_private_data), GFP_KERNEL); | 97 | /* |
| 113 | if (!priv) { | 98 | * A bit ugly, and it will never actually happen but there can |
| 114 | dev_err(&pdev->dev, "could not allocate memory\n"); | 99 | * be only one RNG and this catches any bork |
| 115 | return -ENOMEM; | 100 | */ |
| 116 | }; | 101 | if (rng_dev) |
| 102 | return -EBUSY; | ||
| 103 | |||
| 104 | if (cpu_is_omap24xx()) { | ||
| 105 | rng_ick = clk_get(&pdev->dev, "ick"); | ||
| 106 | if (IS_ERR(rng_ick)) { | ||
| 107 | dev_err(&pdev->dev, "Could not get rng_ick\n"); | ||
| 108 | ret = PTR_ERR(rng_ick); | ||
| 109 | return ret; | ||
| 110 | } else | ||
| 111 | clk_enable(rng_ick); | ||
| 112 | } | ||
| 117 | 113 | ||
| 118 | omap_rng_ops.priv = (unsigned long)priv; | 114 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 119 | dev_set_drvdata(&pdev->dev, priv); | ||
| 120 | 115 | ||
| 121 | priv->mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 116 | if (!res) { |
| 122 | if (!priv->mem_res) { | ||
| 123 | ret = -ENOENT; | 117 | ret = -ENOENT; |
| 124 | goto err_ioremap; | 118 | goto err_region; |
| 125 | } | 119 | } |
| 126 | 120 | ||
| 127 | priv->base = devm_request_and_ioremap(&pdev->dev, priv->mem_res); | 121 | if (!request_mem_region(res->start, resource_size(res), pdev->name)) { |
| 128 | if (!priv->base) { | 122 | ret = -EBUSY; |
| 123 | goto err_region; | ||
| 124 | } | ||
| 125 | |||
| 126 | dev_set_drvdata(&pdev->dev, res); | ||
| 127 | rng_base = ioremap(res->start, resource_size(res)); | ||
| 128 | if (!rng_base) { | ||
| 129 | ret = -ENOMEM; | 129 | ret = -ENOMEM; |
| 130 | goto err_ioremap; | 130 | goto err_ioremap; |
| 131 | } | 131 | } |
| 132 | dev_set_drvdata(&pdev->dev, priv); | ||
| 133 | |||
| 134 | pm_runtime_enable(&pdev->dev); | ||
| 135 | pm_runtime_get_sync(&pdev->dev); | ||
| 136 | 132 | ||
| 137 | ret = hwrng_register(&omap_rng_ops); | 133 | ret = hwrng_register(&omap_rng_ops); |
| 138 | if (ret) | 134 | if (ret) |
| 139 | goto err_register; | 135 | goto err_register; |
| 140 | 136 | ||
| 141 | dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", | 137 | dev_info(&pdev->dev, "OMAP Random Number Generator ver. %02x\n", |
| 142 | omap_rng_read_reg(priv, RNG_REV_REG)); | 138 | omap_rng_read_reg(RNG_REV_REG)); |
| 139 | omap_rng_write_reg(RNG_MASK_REG, 0x1); | ||
| 143 | 140 | ||
| 144 | omap_rng_write_reg(priv, RNG_MASK_REG, 0x1); | 141 | rng_dev = pdev; |
| 145 | 142 | ||
| 146 | return 0; | 143 | return 0; |
| 147 | 144 | ||
| 148 | err_register: | 145 | err_register: |
| 149 | priv->base = NULL; | 146 | iounmap(rng_base); |
| 150 | pm_runtime_disable(&pdev->dev); | 147 | rng_base = NULL; |
| 151 | err_ioremap: | 148 | err_ioremap: |
| 152 | kfree(priv); | 149 | release_mem_region(res->start, resource_size(res)); |
| 153 | 150 | err_region: | |
| 151 | if (cpu_is_omap24xx()) { | ||
| 152 | clk_disable(rng_ick); | ||
| 153 | clk_put(rng_ick); | ||
| 154 | } | ||
| 154 | return ret; | 155 | return ret; |
| 155 | } | 156 | } |
| 156 | 157 | ||
| 157 | static int __exit omap_rng_remove(struct platform_device *pdev) | 158 | static int __exit omap_rng_remove(struct platform_device *pdev) |
| 158 | { | 159 | { |
| 159 | struct omap_rng_private_data *priv = dev_get_drvdata(&pdev->dev); | 160 | struct resource *res = dev_get_drvdata(&pdev->dev); |
| 160 | 161 | ||
| 161 | hwrng_unregister(&omap_rng_ops); | 162 | hwrng_unregister(&omap_rng_ops); |
| 162 | 163 | ||
| 163 | omap_rng_write_reg(priv, RNG_MASK_REG, 0x0); | 164 | omap_rng_write_reg(RNG_MASK_REG, 0x0); |
| 164 | 165 | ||
| 165 | pm_runtime_put_sync(&pdev->dev); | 166 | iounmap(rng_base); |
| 166 | pm_runtime_disable(&pdev->dev); | ||
| 167 | 167 | ||
| 168 | release_mem_region(priv->mem_res->start, resource_size(priv->mem_res)); | 168 | if (cpu_is_omap24xx()) { |
| 169 | clk_disable(rng_ick); | ||
| 170 | clk_put(rng_ick); | ||
| 171 | } | ||
| 169 | 172 | ||
| 170 | kfree(priv); | 173 | release_mem_region(res->start, resource_size(res)); |
| 174 | rng_base = NULL; | ||
| 171 | 175 | ||
| 172 | return 0; | 176 | return 0; |
| 173 | } | 177 | } |
| 174 | 178 | ||
| 175 | #ifdef CONFIG_PM_SLEEP | 179 | #ifdef CONFIG_PM |
| 176 | 180 | ||
| 177 | static int omap_rng_suspend(struct device *dev) | 181 | static int omap_rng_suspend(struct platform_device *pdev, pm_message_t message) |
| 178 | { | 182 | { |
| 179 | struct omap_rng_private_data *priv = dev_get_drvdata(dev); | 183 | omap_rng_write_reg(RNG_MASK_REG, 0x0); |
| 180 | |||
| 181 | omap_rng_write_reg(priv, RNG_MASK_REG, 0x0); | ||
| 182 | pm_runtime_put_sync(dev); | ||
| 183 | |||
| 184 | return 0; | 184 | return 0; |
| 185 | } | 185 | } |
| 186 | 186 | ||
| 187 | static int omap_rng_resume(struct device *dev) | 187 | static int omap_rng_resume(struct platform_device *pdev) |
| 188 | { | 188 | { |
| 189 | struct omap_rng_private_data *priv = dev_get_drvdata(dev); | 189 | omap_rng_write_reg(RNG_MASK_REG, 0x1); |
| 190 | |||
| 191 | pm_runtime_get_sync(dev); | ||
| 192 | omap_rng_write_reg(priv, RNG_MASK_REG, 0x1); | ||
| 193 | |||
| 194 | return 0; | 190 | return 0; |
| 195 | } | 191 | } |
| 196 | 192 | ||
| 197 | static SIMPLE_DEV_PM_OPS(omap_rng_pm, omap_rng_suspend, omap_rng_resume); | ||
| 198 | #define OMAP_RNG_PM (&omap_rng_pm) | ||
| 199 | |||
| 200 | #else | 193 | #else |
| 201 | 194 | ||
| 202 | #define OMAP_RNG_PM NULL | 195 | #define omap_rng_suspend NULL |
| 196 | #define omap_rng_resume NULL | ||
| 203 | 197 | ||
| 204 | #endif | 198 | #endif |
| 205 | 199 | ||
| @@ -210,14 +204,18 @@ static struct platform_driver omap_rng_driver = { | |||
| 210 | .driver = { | 204 | .driver = { |
| 211 | .name = "omap_rng", | 205 | .name = "omap_rng", |
| 212 | .owner = THIS_MODULE, | 206 | .owner = THIS_MODULE, |
| 213 | .pm = OMAP_RNG_PM, | ||
| 214 | }, | 207 | }, |
| 215 | .probe = omap_rng_probe, | 208 | .probe = omap_rng_probe, |
| 216 | .remove = __exit_p(omap_rng_remove), | 209 | .remove = __exit_p(omap_rng_remove), |
| 210 | .suspend = omap_rng_suspend, | ||
| 211 | .resume = omap_rng_resume | ||
| 217 | }; | 212 | }; |
| 218 | 213 | ||
| 219 | static int __init omap_rng_init(void) | 214 | static int __init omap_rng_init(void) |
| 220 | { | 215 | { |
| 216 | if (!cpu_is_omap16xx() && !cpu_is_omap24xx()) | ||
| 217 | return -ENODEV; | ||
| 218 | |||
| 221 | return platform_driver_register(&omap_rng_driver); | 219 | return platform_driver_register(&omap_rng_driver); |
| 222 | } | 220 | } |
| 223 | 221 | ||
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c index c6df5b29af0..1d504815e6d 100644 --- a/drivers/char/hw_random/pasemi-rng.c +++ b/drivers/char/hw_random/pasemi-rng.c | |||
| @@ -94,7 +94,7 @@ static struct hwrng pasemi_rng = { | |||
| 94 | .data_read = pasemi_rng_data_read, | 94 | .data_read = pasemi_rng_data_read, |
| 95 | }; | 95 | }; |
| 96 | 96 | ||
| 97 | static int rng_probe(struct platform_device *ofdev) | 97 | static int __devinit rng_probe(struct platform_device *ofdev) |
| 98 | { | 98 | { |
| 99 | void __iomem *rng_regs; | 99 | void __iomem *rng_regs; |
| 100 | struct device_node *rng_np = ofdev->dev.of_node; | 100 | struct device_node *rng_np = ofdev->dev.of_node; |
| @@ -122,7 +122,7 @@ static int rng_probe(struct platform_device *ofdev) | |||
| 122 | return err; | 122 | return err; |
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | static int rng_remove(struct platform_device *dev) | 125 | static int __devexit rng_remove(struct platform_device *dev) |
| 126 | { | 126 | { |
| 127 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; | 127 | void __iomem *rng_regs = (void __iomem *)pasemi_rng.priv; |
| 128 | 128 | ||
| @@ -148,7 +148,17 @@ static struct platform_driver rng_driver = { | |||
| 148 | .remove = rng_remove, | 148 | .remove = rng_remove, |
| 149 | }; | 149 | }; |
| 150 | 150 | ||
| 151 | module_platform_driver(rng_driver); | 151 | static int __init rng_init(void) |
| 152 | { | ||
| 153 | return platform_driver_register(&rng_driver); | ||
| 154 | } | ||
| 155 | module_init(rng_init); | ||
| 156 | |||
| 157 | static void __exit rng_exit(void) | ||
| 158 | { | ||
| 159 | platform_driver_unregister(&rng_driver); | ||
| 160 | } | ||
| 161 | module_exit(rng_exit); | ||
| 152 | 162 | ||
| 153 | MODULE_LICENSE("GPL"); | 163 | MODULE_LICENSE("GPL"); |
| 154 | MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); | 164 | MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>"); |
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c index 973b95113ed..990d55a5e3e 100644 --- a/drivers/char/hw_random/picoxcell-rng.c +++ b/drivers/char/hw_random/picoxcell-rng.c | |||
| @@ -151,7 +151,7 @@ err_enable: | |||
| 151 | return ret; | 151 | return ret; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | static int picoxcell_trng_remove(struct platform_device *pdev) | 154 | static int __devexit picoxcell_trng_remove(struct platform_device *pdev) |
| 155 | { | 155 | { |
| 156 | hwrng_unregister(&picoxcell_trng); | 156 | hwrng_unregister(&picoxcell_trng); |
| 157 | clk_disable(rng_clk); | 157 | clk_disable(rng_clk); |
| @@ -181,7 +181,7 @@ static const struct dev_pm_ops picoxcell_trng_pm_ops = { | |||
| 181 | 181 | ||
| 182 | static struct platform_driver picoxcell_trng_driver = { | 182 | static struct platform_driver picoxcell_trng_driver = { |
| 183 | .probe = picoxcell_trng_probe, | 183 | .probe = picoxcell_trng_probe, |
| 184 | .remove = picoxcell_trng_remove, | 184 | .remove = __devexit_p(picoxcell_trng_remove), |
| 185 | .driver = { | 185 | .driver = { |
| 186 | .name = "picoxcell-trng", | 186 | .name = "picoxcell-trng", |
| 187 | .owner = THIS_MODULE, | 187 | .owner = THIS_MODULE, |
| @@ -191,7 +191,17 @@ static struct platform_driver picoxcell_trng_driver = { | |||
| 191 | }, | 191 | }, |
| 192 | }; | 192 | }; |
| 193 | 193 | ||
| 194 | module_platform_driver(picoxcell_trng_driver); | 194 | static int __init picoxcell_trng_init(void) |
| 195 | { | ||
| 196 | return platform_driver_register(&picoxcell_trng_driver); | ||
| 197 | } | ||
| 198 | module_init(picoxcell_trng_init); | ||
| 199 | |||
| 200 | static void __exit picoxcell_trng_exit(void) | ||
| 201 | { | ||
| 202 | platform_driver_unregister(&picoxcell_trng_driver); | ||
| 203 | } | ||
| 204 | module_exit(picoxcell_trng_exit); | ||
| 195 | 205 | ||
| 196 | MODULE_LICENSE("GPL"); | 206 | MODULE_LICENSE("GPL"); |
| 197 | MODULE_AUTHOR("Jamie Iles"); | 207 | MODULE_AUTHOR("Jamie Iles"); |
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c index 732c330805f..b8afa6a4ff6 100644 --- a/drivers/char/hw_random/ppc4xx-rng.c +++ b/drivers/char/hw_random/ppc4xx-rng.c | |||
| @@ -90,7 +90,7 @@ static struct hwrng ppc4xx_rng = { | |||
| 90 | .data_read = ppc4xx_rng_data_read, | 90 | .data_read = ppc4xx_rng_data_read, |
| 91 | }; | 91 | }; |
| 92 | 92 | ||
| 93 | static int ppc4xx_rng_probe(struct platform_device *dev) | 93 | static int __devinit ppc4xx_rng_probe(struct platform_device *dev) |
| 94 | { | 94 | { |
| 95 | void __iomem *rng_regs; | 95 | void __iomem *rng_regs; |
| 96 | int err = 0; | 96 | int err = 0; |
| @@ -111,7 +111,7 @@ static int ppc4xx_rng_probe(struct platform_device *dev) | |||
| 111 | return err; | 111 | return err; |
| 112 | } | 112 | } |
| 113 | 113 | ||
| 114 | static int ppc4xx_rng_remove(struct platform_device *dev) | 114 | static int __devexit ppc4xx_rng_remove(struct platform_device *dev) |
| 115 | { | 115 | { |
| 116 | void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv; | 116 | void __iomem *rng_regs = (void __iomem *) ppc4xx_rng.priv; |
| 117 | 117 | ||
| @@ -139,7 +139,17 @@ static struct platform_driver ppc4xx_rng_driver = { | |||
| 139 | .remove = ppc4xx_rng_remove, | 139 | .remove = ppc4xx_rng_remove, |
| 140 | }; | 140 | }; |
| 141 | 141 | ||
| 142 | module_platform_driver(ppc4xx_rng_driver); | 142 | static int __init ppc4xx_rng_init(void) |
| 143 | { | ||
| 144 | return platform_driver_register(&ppc4xx_rng_driver); | ||
| 145 | } | ||
| 146 | module_init(ppc4xx_rng_init); | ||
| 147 | |||
| 148 | static void __exit ppc4xx_rng_exit(void) | ||
| 149 | { | ||
| 150 | platform_driver_unregister(&ppc4xx_rng_driver); | ||
| 151 | } | ||
| 152 | module_exit(ppc4xx_rng_exit); | ||
| 143 | 153 | ||
| 144 | MODULE_LICENSE("GPL"); | 154 | MODULE_LICENSE("GPL"); |
| 145 | MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>"); | 155 | MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>"); |
diff --git a/drivers/char/hw_random/pseries-rng.c b/drivers/char/hw_random/pseries-rng.c deleted file mode 100644 index 5f1197929f0..00000000000 --- a/drivers/char/hw_random/pseries-rng.c +++ /dev/null | |||
| @@ -1,96 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2010 Michael Neuling IBM Corporation | ||
| 3 | * | ||
| 4 | * Driver for the pseries hardware RNG for POWER7+ and above | ||
| 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 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/hw_random.h> | ||
| 22 | #include <asm/vio.h> | ||
| 23 | |||
| 24 | #define MODULE_NAME "pseries-rng" | ||
| 25 | |||
| 26 | static int pseries_rng_data_read(struct hwrng *rng, u32 *data) | ||
| 27 | { | ||
| 28 | if (plpar_hcall(H_RANDOM, (unsigned long *)data) != H_SUCCESS) { | ||
| 29 | printk(KERN_ERR "pseries rng hcall error\n"); | ||
| 30 | return 0; | ||
| 31 | } | ||
| 32 | return 8; | ||
| 33 | } | ||
| 34 | |||
| 35 | /** | ||
| 36 | * pseries_rng_get_desired_dma - Return desired DMA allocate for CMO operations | ||
| 37 | * | ||
| 38 | * This is a required function for a driver to operate in a CMO environment | ||
| 39 | * but this device does not make use of DMA allocations, return 0. | ||
| 40 | * | ||
| 41 | * Return value: | ||
| 42 | * Number of bytes of IO data the driver will need to perform well -> 0 | ||
| 43 | */ | ||
| 44 | static unsigned long pseries_rng_get_desired_dma(struct vio_dev *vdev) | ||
| 45 | { | ||
| 46 | return 0; | ||
| 47 | }; | ||
| 48 | |||
| 49 | static struct hwrng pseries_rng = { | ||
| 50 | .name = MODULE_NAME, | ||
| 51 | .data_read = pseries_rng_data_read, | ||
| 52 | }; | ||
| 53 | |||
| 54 | static int __init pseries_rng_probe(struct vio_dev *dev, | ||
| 55 | const struct vio_device_id *id) | ||
| 56 | { | ||
| 57 | return hwrng_register(&pseries_rng); | ||
| 58 | } | ||
| 59 | |||
| 60 | static int __exit pseries_rng_remove(struct vio_dev *dev) | ||
| 61 | { | ||
| 62 | hwrng_unregister(&pseries_rng); | ||
| 63 | return 0; | ||
| 64 | } | ||
| 65 | |||
| 66 | static struct vio_device_id pseries_rng_driver_ids[] = { | ||
| 67 | { "ibm,random-v1", "ibm,random"}, | ||
| 68 | { "", "" } | ||
| 69 | }; | ||
| 70 | MODULE_DEVICE_TABLE(vio, pseries_rng_driver_ids); | ||
| 71 | |||
| 72 | static struct vio_driver pseries_rng_driver = { | ||
| 73 | .name = MODULE_NAME, | ||
| 74 | .probe = pseries_rng_probe, | ||
| 75 | .remove = pseries_rng_remove, | ||
| 76 | .get_desired_dma = pseries_rng_get_desired_dma, | ||
| 77 | .id_table = pseries_rng_driver_ids | ||
| 78 | }; | ||
| 79 | |||
| 80 | static int __init rng_init(void) | ||
| 81 | { | ||
| 82 | printk(KERN_INFO "Registering IBM pSeries RNG driver\n"); | ||
| 83 | return vio_register_driver(&pseries_rng_driver); | ||
| 84 | } | ||
| 85 | |||
| 86 | module_init(rng_init); | ||
| 87 | |||
| 88 | static void __exit rng_exit(void) | ||
| 89 | { | ||
| 90 | vio_unregister_driver(&pseries_rng_driver); | ||
| 91 | } | ||
| 92 | module_exit(rng_exit); | ||
| 93 | |||
| 94 | MODULE_LICENSE("GPL"); | ||
| 95 | MODULE_AUTHOR("Michael Neuling <mikey@neuling.org>"); | ||
| 96 | MODULE_DESCRIPTION("H/W RNG driver for IBM pSeries processors"); | ||
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c index 849db199c02..a8428e6f64a 100644 --- a/drivers/char/hw_random/timeriomem-rng.c +++ b/drivers/char/hw_random/timeriomem-rng.c | |||
| @@ -88,7 +88,7 @@ static struct hwrng timeriomem_rng_ops = { | |||
| 88 | .priv = 0, | 88 | .priv = 0, |
| 89 | }; | 89 | }; |
| 90 | 90 | ||
| 91 | static int timeriomem_rng_probe(struct platform_device *pdev) | 91 | static int __devinit timeriomem_rng_probe(struct platform_device *pdev) |
| 92 | { | 92 | { |
| 93 | struct resource *res; | 93 | struct resource *res; |
| 94 | int ret; | 94 | int ret; |
| @@ -130,7 +130,7 @@ failed: | |||
| 130 | return ret; | 130 | return ret; |
| 131 | } | 131 | } |
| 132 | 132 | ||
| 133 | static int timeriomem_rng_remove(struct platform_device *pdev) | 133 | static int __devexit timeriomem_rng_remove(struct platform_device *pdev) |
| 134 | { | 134 | { |
| 135 | del_timer_sync(&timeriomem_rng_timer); | 135 | del_timer_sync(&timeriomem_rng_timer); |
| 136 | hwrng_unregister(&timeriomem_rng_ops); | 136 | hwrng_unregister(&timeriomem_rng_ops); |
| @@ -146,10 +146,21 @@ static struct platform_driver timeriomem_rng_driver = { | |||
| 146 | .owner = THIS_MODULE, | 146 | .owner = THIS_MODULE, |
| 147 | }, | 147 | }, |
| 148 | .probe = timeriomem_rng_probe, | 148 | .probe = timeriomem_rng_probe, |
| 149 | .remove = timeriomem_rng_remove, | 149 | .remove = __devexit_p(timeriomem_rng_remove), |
| 150 | }; | 150 | }; |
| 151 | 151 | ||
| 152 | module_platform_driver(timeriomem_rng_driver); | 152 | static int __init timeriomem_rng_init(void) |
| 153 | { | ||
| 154 | return platform_driver_register(&timeriomem_rng_driver); | ||
| 155 | } | ||
| 156 | |||
| 157 | static void __exit timeriomem_rng_exit(void) | ||
| 158 | { | ||
| 159 | platform_driver_unregister(&timeriomem_rng_driver); | ||
| 160 | } | ||
| 161 | |||
| 162 | module_init(timeriomem_rng_init); | ||
| 163 | module_exit(timeriomem_rng_exit); | ||
| 153 | 164 | ||
| 154 | MODULE_LICENSE("GPL"); | 165 | MODULE_LICENSE("GPL"); |
| 155 | MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); | 166 | MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>"); |
diff --git a/drivers/char/hw_random/tpm-rng.c b/drivers/char/hw_random/tpm-rng.c deleted file mode 100644 index d6d448266f0..00000000000 --- a/drivers/char/hw_random/tpm-rng.c +++ /dev/null | |||
| @@ -1,50 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012 Kent Yoder IBM Corporation | ||
| 3 | * | ||
| 4 | * HWRNG interfaces to pull RNG data from a TPM | ||
| 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 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/hw_random.h> | ||
| 22 | #include <linux/tpm.h> | ||
| 23 | |||
| 24 | #define MODULE_NAME "tpm-rng" | ||
| 25 | |||
| 26 | static int tpm_rng_read(struct hwrng *rng, void *data, size_t max, bool wait) | ||
| 27 | { | ||
| 28 | return tpm_get_random(TPM_ANY_NUM, data, max); | ||
| 29 | } | ||
| 30 | |||
| 31 | static struct hwrng tpm_rng = { | ||
| 32 | .name = MODULE_NAME, | ||
| 33 | .read = tpm_rng_read, | ||
| 34 | }; | ||
| 35 | |||
| 36 | static int __init rng_init(void) | ||
| 37 | { | ||
| 38 | return hwrng_register(&tpm_rng); | ||
| 39 | } | ||
| 40 | module_init(rng_init); | ||
| 41 | |||
| 42 | static void __exit rng_exit(void) | ||
| 43 | { | ||
| 44 | hwrng_unregister(&tpm_rng); | ||
| 45 | } | ||
| 46 | module_exit(rng_exit); | ||
| 47 | |||
| 48 | MODULE_LICENSE("GPL v2"); | ||
| 49 | MODULE_AUTHOR("Kent Yoder <key@linux.vnet.ibm.com>"); | ||
| 50 | MODULE_DESCRIPTION("RNG driver for TPM devices"); | ||
diff --git a/drivers/char/hw_random/tx4939-rng.c b/drivers/char/hw_random/tx4939-rng.c index de473ef3882..0bc0cb70210 100644 --- a/drivers/char/hw_random/tx4939-rng.c +++ b/drivers/char/hw_random/tx4939-rng.c | |||
| @@ -115,7 +115,10 @@ static int __init tx4939_rng_probe(struct platform_device *dev) | |||
| 115 | rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL); | 115 | rngdev = devm_kzalloc(&dev->dev, sizeof(*rngdev), GFP_KERNEL); |
| 116 | if (!rngdev) | 116 | if (!rngdev) |
| 117 | return -ENOMEM; | 117 | return -ENOMEM; |
| 118 | rngdev->base = devm_request_and_ioremap(&dev->dev, r); | 118 | if (!devm_request_mem_region(&dev->dev, r->start, resource_size(r), |
| 119 | dev_name(&dev->dev))) | ||
| 120 | return -EBUSY; | ||
| 121 | rngdev->base = devm_ioremap(&dev->dev, r->start, resource_size(r)); | ||
| 119 | if (!rngdev->base) | 122 | if (!rngdev->base) |
| 120 | return -EBUSY; | 123 | return -EBUSY; |
| 121 | 124 | ||
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index b65c1039595..75f1cbd61c1 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
| @@ -23,7 +23,6 @@ | |||
| 23 | #include <linux/spinlock.h> | 23 | #include <linux/spinlock.h> |
| 24 | #include <linux/virtio.h> | 24 | #include <linux/virtio.h> |
| 25 | #include <linux/virtio_rng.h> | 25 | #include <linux/virtio_rng.h> |
| 26 | #include <linux/module.h> | ||
| 27 | 26 | ||
| 28 | static struct virtqueue *vq; | 27 | static struct virtqueue *vq; |
| 29 | static unsigned int data_avail; | 28 | static unsigned int data_avail; |
| @@ -47,7 +46,7 @@ static void register_buffer(u8 *buf, size_t size) | |||
| 47 | sg_init_one(&sg, buf, size); | 46 | sg_init_one(&sg, buf, size); |
| 48 | 47 | ||
| 49 | /* There should always be room for one buffer. */ | 48 | /* There should always be room for one buffer. */ |
| 50 | if (virtqueue_add_buf(vq, &sg, 0, 1, buf, GFP_KERNEL) < 0) | 49 | if (virtqueue_add_buf(vq, &sg, 0, 1, buf) < 0) |
| 51 | BUG(); | 50 | BUG(); |
| 52 | 51 | ||
| 53 | virtqueue_kick(vq); | 52 | virtqueue_kick(vq); |
| @@ -55,7 +54,6 @@ static void register_buffer(u8 *buf, size_t size) | |||
| 55 | 54 | ||
| 56 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) | 55 | static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) |
| 57 | { | 56 | { |
| 58 | int ret; | ||
| 59 | 57 | ||
| 60 | if (!busy) { | 58 | if (!busy) { |
| 61 | busy = true; | 59 | busy = true; |
| @@ -66,9 +64,7 @@ static int virtio_read(struct hwrng *rng, void *buf, size_t size, bool wait) | |||
| 66 | if (!wait) | 64 | if (!wait) |
| 67 | return 0; | 65 | return 0; |
| 68 | 66 | ||
| 69 | ret = wait_for_completion_killable(&have_data); | 67 | wait_for_completion(&have_data); |
| 70 | if (ret < 0) | ||
| 71 | return ret; | ||
| 72 | 68 | ||
| 73 | busy = false; | 69 | busy = false; |
| 74 | 70 | ||
| @@ -88,7 +84,7 @@ static struct hwrng virtio_hwrng = { | |||
| 88 | .read = virtio_read, | 84 | .read = virtio_read, |
| 89 | }; | 85 | }; |
| 90 | 86 | ||
| 91 | static int probe_common(struct virtio_device *vdev) | 87 | static int virtrng_probe(struct virtio_device *vdev) |
| 92 | { | 88 | { |
| 93 | int err; | 89 | int err; |
| 94 | 90 | ||
| @@ -106,37 +102,13 @@ static int probe_common(struct virtio_device *vdev) | |||
| 106 | return 0; | 102 | return 0; |
| 107 | } | 103 | } |
| 108 | 104 | ||
| 109 | static void remove_common(struct virtio_device *vdev) | 105 | static void __devexit virtrng_remove(struct virtio_device *vdev) |
| 110 | { | 106 | { |
| 111 | vdev->config->reset(vdev); | 107 | vdev->config->reset(vdev); |
| 112 | busy = false; | ||
| 113 | hwrng_unregister(&virtio_hwrng); | 108 | hwrng_unregister(&virtio_hwrng); |
| 114 | vdev->config->del_vqs(vdev); | 109 | vdev->config->del_vqs(vdev); |
| 115 | } | 110 | } |
| 116 | 111 | ||
| 117 | static int virtrng_probe(struct virtio_device *vdev) | ||
| 118 | { | ||
| 119 | return probe_common(vdev); | ||
| 120 | } | ||
| 121 | |||
| 122 | static void virtrng_remove(struct virtio_device *vdev) | ||
| 123 | { | ||
| 124 | remove_common(vdev); | ||
| 125 | } | ||
| 126 | |||
| 127 | #ifdef CONFIG_PM | ||
| 128 | static int virtrng_freeze(struct virtio_device *vdev) | ||
| 129 | { | ||
| 130 | remove_common(vdev); | ||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int virtrng_restore(struct virtio_device *vdev) | ||
| 135 | { | ||
| 136 | return probe_common(vdev); | ||
| 137 | } | ||
| 138 | #endif | ||
| 139 | |||
| 140 | static struct virtio_device_id id_table[] = { | 112 | static struct virtio_device_id id_table[] = { |
| 141 | { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID }, | 113 | { VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID }, |
| 142 | { 0 }, | 114 | { 0 }, |
| @@ -147,11 +119,7 @@ static struct virtio_driver virtio_rng_driver = { | |||
| 147 | .driver.owner = THIS_MODULE, | 119 | .driver.owner = THIS_MODULE, |
| 148 | .id_table = id_table, | 120 | .id_table = id_table, |
| 149 | .probe = virtrng_probe, | 121 | .probe = virtrng_probe, |
| 150 | .remove = virtrng_remove, | 122 | .remove = __devexit_p(virtrng_remove), |
| 151 | #ifdef CONFIG_PM | ||
| 152 | .freeze = virtrng_freeze, | ||
| 153 | .restore = virtrng_restore, | ||
| 154 | #endif | ||
| 155 | }; | 123 | }; |
| 156 | 124 | ||
| 157 | static int __init init(void) | 125 | static int __init init(void) |
diff --git a/drivers/char/i8k.c b/drivers/char/i8k.c index 40cc0cf2ded..6e40072fbf6 100644 --- a/drivers/char/i8k.c +++ b/drivers/char/i8k.c | |||
| @@ -69,19 +69,19 @@ MODULE_AUTHOR("Massimo Dal Zotto (dz@debian.org)"); | |||
| 69 | MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); | 69 | MODULE_DESCRIPTION("Driver for accessing SMM BIOS on Dell laptops"); |
| 70 | MODULE_LICENSE("GPL"); | 70 | MODULE_LICENSE("GPL"); |
| 71 | 71 | ||
| 72 | static bool force; | 72 | static int force; |
| 73 | module_param(force, bool, 0); | 73 | module_param(force, bool, 0); |
| 74 | MODULE_PARM_DESC(force, "Force loading without checking for supported models"); | 74 | MODULE_PARM_DESC(force, "Force loading without checking for supported models"); |
| 75 | 75 | ||
| 76 | static bool ignore_dmi; | 76 | static int ignore_dmi; |
| 77 | module_param(ignore_dmi, bool, 0); | 77 | module_param(ignore_dmi, bool, 0); |
| 78 | MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); | 78 | MODULE_PARM_DESC(ignore_dmi, "Continue probing hardware even if DMI data does not match"); |
| 79 | 79 | ||
| 80 | static bool restricted; | 80 | static int restricted; |
| 81 | module_param(restricted, bool, 0); | 81 | module_param(restricted, bool, 0); |
| 82 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); | 82 | MODULE_PARM_DESC(restricted, "Allow fan control if SYS_ADMIN capability set"); |
| 83 | 83 | ||
| 84 | static bool power_status; | 84 | static int power_status; |
| 85 | module_param(power_status, bool, 0600); | 85 | module_param(power_status, bool, 0600); |
| 86 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); | 86 | MODULE_PARM_DESC(power_status, "Report power status in /proc/i8k"); |
| 87 | 87 | ||
diff --git a/drivers/char/ipmi/ipmi_bt_sm.c b/drivers/char/ipmi/ipmi_bt_sm.c index cdd4c09fda9..3ed20e8abc0 100644 --- a/drivers/char/ipmi/ipmi_bt_sm.c +++ b/drivers/char/ipmi/ipmi_bt_sm.c | |||
| @@ -560,7 +560,7 @@ static enum si_sm_result bt_event(struct si_sm_data *bt, long time) | |||
| 560 | BT_CONTROL(BT_H_BUSY); /* set */ | 560 | BT_CONTROL(BT_H_BUSY); /* set */ |
| 561 | 561 | ||
| 562 | /* | 562 | /* |
| 563 | * Uncached, ordered writes should just proceed serially but | 563 | * Uncached, ordered writes should just proceeed serially but |
| 564 | * some BMCs don't clear B2H_ATN with one hit. Fast-path a | 564 | * some BMCs don't clear B2H_ATN with one hit. Fast-path a |
| 565 | * workaround without too much penalty to the general case. | 565 | * workaround without too much penalty to the general case. |
| 566 | */ | 566 | */ |
diff --git a/drivers/char/ipmi/ipmi_devintf.c b/drivers/char/ipmi/ipmi_devintf.c index 9eb360ff8ca..2aa3977aae5 100644 --- a/drivers/char/ipmi/ipmi_devintf.c +++ b/drivers/char/ipmi/ipmi_devintf.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
| 35 | #include <linux/moduleparam.h> | 35 | #include <linux/moduleparam.h> |
| 36 | #include <linux/errno.h> | 36 | #include <linux/errno.h> |
| 37 | #include <asm/system.h> | ||
| 37 | #include <linux/poll.h> | 38 | #include <linux/poll.h> |
| 38 | #include <linux/sched.h> | 39 | #include <linux/sched.h> |
| 39 | #include <linux/spinlock.h> | 40 | #include <linux/spinlock.h> |
diff --git a/drivers/char/ipmi/ipmi_kcs_sm.c b/drivers/char/ipmi/ipmi_kcs_sm.c index e53fc24c6af..cf82fedae09 100644 --- a/drivers/char/ipmi/ipmi_kcs_sm.c +++ b/drivers/char/ipmi/ipmi_kcs_sm.c | |||
| @@ -118,8 +118,8 @@ enum kcs_states { | |||
| 118 | #define MAX_KCS_WRITE_SIZE IPMI_MAX_MSG_LENGTH | 118 | #define MAX_KCS_WRITE_SIZE IPMI_MAX_MSG_LENGTH |
| 119 | 119 | ||
| 120 | /* Timeouts in microseconds. */ | 120 | /* Timeouts in microseconds. */ |
| 121 | #define IBF_RETRY_TIMEOUT 5000000 | 121 | #define IBF_RETRY_TIMEOUT 1000000 |
| 122 | #define OBF_RETRY_TIMEOUT 5000000 | 122 | #define OBF_RETRY_TIMEOUT 1000000 |
| 123 | #define MAX_ERROR_RETRIES 10 | 123 | #define MAX_ERROR_RETRIES 10 |
| 124 | #define ERROR0_OBF_WAIT_JIFFIES (2*HZ) | 124 | #define ERROR0_OBF_WAIT_JIFFIES (2*HZ) |
| 125 | 125 | ||
diff --git a/drivers/char/ipmi/ipmi_msghandler.c b/drivers/char/ipmi/ipmi_msghandler.c index 053201b062a..58c0e6387cf 100644 --- a/drivers/char/ipmi/ipmi_msghandler.c +++ b/drivers/char/ipmi/ipmi_msghandler.c | |||
| @@ -33,6 +33,7 @@ | |||
| 33 | 33 | ||
| 34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
| 35 | #include <linux/errno.h> | 35 | #include <linux/errno.h> |
| 36 | #include <asm/system.h> | ||
| 36 | #include <linux/poll.h> | 37 | #include <linux/poll.h> |
| 37 | #include <linux/sched.h> | 38 | #include <linux/sched.h> |
| 38 | #include <linux/seq_file.h> | 39 | #include <linux/seq_file.h> |
| @@ -45,7 +46,6 @@ | |||
| 45 | #include <linux/init.h> | 46 | #include <linux/init.h> |
| 46 | #include <linux/proc_fs.h> | 47 | #include <linux/proc_fs.h> |
| 47 | #include <linux/rcupdate.h> | 48 | #include <linux/rcupdate.h> |
| 48 | #include <linux/interrupt.h> | ||
| 49 | 49 | ||
| 50 | #define PFX "IPMI message handler: " | 50 | #define PFX "IPMI message handler: " |
| 51 | 51 | ||
| @@ -53,8 +53,6 @@ | |||
| 53 | 53 | ||
| 54 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); | 54 | static struct ipmi_recv_msg *ipmi_alloc_recv_msg(void); |
| 55 | static int ipmi_init_msghandler(void); | 55 | static int ipmi_init_msghandler(void); |
| 56 | static void smi_recv_tasklet(unsigned long); | ||
| 57 | static void handle_new_recv_msgs(ipmi_smi_t intf); | ||
| 58 | 56 | ||
| 59 | static int initialized; | 57 | static int initialized; |
| 60 | 58 | ||
| @@ -357,15 +355,12 @@ struct ipmi_smi { | |||
| 357 | int curr_seq; | 355 | int curr_seq; |
| 358 | 356 | ||
| 359 | /* | 357 | /* |
| 360 | * Messages queued for delivery. If delivery fails (out of memory | 358 | * Messages that were delayed for some reason (out of memory, |
| 361 | * for instance), They will stay in here to be processed later in a | 359 | * for instance), will go in here to be processed later in a |
| 362 | * periodic timer interrupt. The tasklet is for handling received | 360 | * periodic timer interrupt. |
| 363 | * messages directly from the handler. | ||
| 364 | */ | 361 | */ |
| 365 | spinlock_t waiting_msgs_lock; | 362 | spinlock_t waiting_msgs_lock; |
| 366 | struct list_head waiting_msgs; | 363 | struct list_head waiting_msgs; |
| 367 | atomic_t watchdog_pretimeouts_to_deliver; | ||
| 368 | struct tasklet_struct recv_tasklet; | ||
| 369 | 364 | ||
| 370 | /* | 365 | /* |
| 371 | * The list of command receivers that are registered for commands | 366 | * The list of command receivers that are registered for commands |
| @@ -498,8 +493,6 @@ static void clean_up_interface_data(ipmi_smi_t intf) | |||
| 498 | struct cmd_rcvr *rcvr, *rcvr2; | 493 | struct cmd_rcvr *rcvr, *rcvr2; |
| 499 | struct list_head list; | 494 | struct list_head list; |
| 500 | 495 | ||
| 501 | tasklet_kill(&intf->recv_tasklet); | ||
| 502 | |||
| 503 | free_smi_msg_list(&intf->waiting_msgs); | 496 | free_smi_msg_list(&intf->waiting_msgs); |
| 504 | free_recv_msg_list(&intf->waiting_events); | 497 | free_recv_msg_list(&intf->waiting_events); |
| 505 | 498 | ||
| @@ -1880,7 +1873,7 @@ int ipmi_request_supply_msgs(ipmi_user_t user, | |||
| 1880 | struct ipmi_recv_msg *supplied_recv, | 1873 | struct ipmi_recv_msg *supplied_recv, |
| 1881 | int priority) | 1874 | int priority) |
| 1882 | { | 1875 | { |
| 1883 | unsigned char saddr = 0, lun = 0; | 1876 | unsigned char saddr, lun; |
| 1884 | int rv; | 1877 | int rv; |
| 1885 | 1878 | ||
| 1886 | if (!user) | 1879 | if (!user) |
| @@ -2793,17 +2786,12 @@ channel_handler(ipmi_smi_t intf, struct ipmi_recv_msg *msg) | |||
| 2793 | return; | 2786 | return; |
| 2794 | } | 2787 | } |
| 2795 | 2788 | ||
| 2796 | static void ipmi_poll(ipmi_smi_t intf) | 2789 | void ipmi_poll_interface(ipmi_user_t user) |
| 2797 | { | 2790 | { |
| 2791 | ipmi_smi_t intf = user->intf; | ||
| 2792 | |||
| 2798 | if (intf->handlers->poll) | 2793 | if (intf->handlers->poll) |
| 2799 | intf->handlers->poll(intf->send_info); | 2794 | intf->handlers->poll(intf->send_info); |
| 2800 | /* In case something came in */ | ||
| 2801 | handle_new_recv_msgs(intf); | ||
| 2802 | } | ||
| 2803 | |||
| 2804 | void ipmi_poll_interface(ipmi_user_t user) | ||
| 2805 | { | ||
| 2806 | ipmi_poll(user->intf); | ||
| 2807 | } | 2795 | } |
| 2808 | EXPORT_SYMBOL(ipmi_poll_interface); | 2796 | EXPORT_SYMBOL(ipmi_poll_interface); |
| 2809 | 2797 | ||
| @@ -2872,10 +2860,6 @@ int ipmi_register_smi(struct ipmi_smi_handlers *handlers, | |||
| 2872 | #endif | 2860 | #endif |
| 2873 | spin_lock_init(&intf->waiting_msgs_lock); | 2861 | spin_lock_init(&intf->waiting_msgs_lock); |
| 2874 | INIT_LIST_HEAD(&intf->waiting_msgs); | 2862 | INIT_LIST_HEAD(&intf->waiting_msgs); |
| 2875 | tasklet_init(&intf->recv_tasklet, | ||
| 2876 | smi_recv_tasklet, | ||
| 2877 | (unsigned long) intf); | ||
| 2878 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 0); | ||
| 2879 | spin_lock_init(&intf->events_lock); | 2863 | spin_lock_init(&intf->events_lock); |
| 2880 | INIT_LIST_HEAD(&intf->waiting_events); | 2864 | INIT_LIST_HEAD(&intf->waiting_events); |
| 2881 | intf->waiting_events_count = 0; | 2865 | intf->waiting_events_count = 0; |
| @@ -3638,11 +3622,11 @@ static int handle_bmc_rsp(ipmi_smi_t intf, | |||
| 3638 | } | 3622 | } |
| 3639 | 3623 | ||
| 3640 | /* | 3624 | /* |
| 3641 | * Handle a received message. Return 1 if the message should be requeued, | 3625 | * Handle a new message. Return 1 if the message should be requeued, |
| 3642 | * 0 if the message should be freed, or -1 if the message should not | 3626 | * 0 if the message should be freed, or -1 if the message should not |
| 3643 | * be freed or requeued. | 3627 | * be freed or requeued. |
| 3644 | */ | 3628 | */ |
| 3645 | static int handle_one_recv_msg(ipmi_smi_t intf, | 3629 | static int handle_new_recv_msg(ipmi_smi_t intf, |
| 3646 | struct ipmi_smi_msg *msg) | 3630 | struct ipmi_smi_msg *msg) |
| 3647 | { | 3631 | { |
| 3648 | int requeue; | 3632 | int requeue; |
| @@ -3789,7 +3773,7 @@ static int handle_one_recv_msg(ipmi_smi_t intf, | |||
| 3789 | 3773 | ||
| 3790 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) | 3774 | } else if ((msg->rsp[0] == ((IPMI_NETFN_APP_REQUEST|1) << 2)) |
| 3791 | && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) { | 3775 | && (msg->rsp[1] == IPMI_READ_EVENT_MSG_BUFFER_CMD)) { |
| 3792 | /* It's an asynchronous event. */ | 3776 | /* It's an asyncronous event. */ |
| 3793 | requeue = handle_read_event_rsp(intf, msg); | 3777 | requeue = handle_read_event_rsp(intf, msg); |
| 3794 | } else { | 3778 | } else { |
| 3795 | /* It's a response from the local BMC. */ | 3779 | /* It's a response from the local BMC. */ |
| @@ -3800,72 +3784,12 @@ static int handle_one_recv_msg(ipmi_smi_t intf, | |||
| 3800 | return requeue; | 3784 | return requeue; |
| 3801 | } | 3785 | } |
| 3802 | 3786 | ||
| 3803 | /* | ||
| 3804 | * If there are messages in the queue or pretimeouts, handle them. | ||
| 3805 | */ | ||
| 3806 | static void handle_new_recv_msgs(ipmi_smi_t intf) | ||
| 3807 | { | ||
| 3808 | struct ipmi_smi_msg *smi_msg; | ||
| 3809 | unsigned long flags = 0; | ||
| 3810 | int rv; | ||
| 3811 | int run_to_completion = intf->run_to_completion; | ||
| 3812 | |||
| 3813 | /* See if any waiting messages need to be processed. */ | ||
| 3814 | if (!run_to_completion) | ||
| 3815 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | ||
| 3816 | while (!list_empty(&intf->waiting_msgs)) { | ||
| 3817 | smi_msg = list_entry(intf->waiting_msgs.next, | ||
| 3818 | struct ipmi_smi_msg, link); | ||
| 3819 | list_del(&smi_msg->link); | ||
| 3820 | if (!run_to_completion) | ||
| 3821 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | ||
| 3822 | rv = handle_one_recv_msg(intf, smi_msg); | ||
| 3823 | if (!run_to_completion) | ||
| 3824 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | ||
| 3825 | if (rv == 0) { | ||
| 3826 | /* Message handled */ | ||
| 3827 | ipmi_free_smi_msg(smi_msg); | ||
| 3828 | } else if (rv < 0) { | ||
| 3829 | /* Fatal error on the message, del but don't free. */ | ||
| 3830 | } else { | ||
| 3831 | /* | ||
| 3832 | * To preserve message order, quit if we | ||
| 3833 | * can't handle a message. | ||
| 3834 | */ | ||
| 3835 | list_add(&smi_msg->link, &intf->waiting_msgs); | ||
| 3836 | break; | ||
| 3837 | } | ||
| 3838 | } | ||
| 3839 | if (!run_to_completion) | ||
| 3840 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | ||
| 3841 | |||
| 3842 | /* | ||
| 3843 | * If the pretimout count is non-zero, decrement one from it and | ||
| 3844 | * deliver pretimeouts to all the users. | ||
| 3845 | */ | ||
| 3846 | if (atomic_add_unless(&intf->watchdog_pretimeouts_to_deliver, -1, 0)) { | ||
| 3847 | ipmi_user_t user; | ||
| 3848 | |||
| 3849 | rcu_read_lock(); | ||
| 3850 | list_for_each_entry_rcu(user, &intf->users, link) { | ||
| 3851 | if (user->handler->ipmi_watchdog_pretimeout) | ||
| 3852 | user->handler->ipmi_watchdog_pretimeout( | ||
| 3853 | user->handler_data); | ||
| 3854 | } | ||
| 3855 | rcu_read_unlock(); | ||
| 3856 | } | ||
| 3857 | } | ||
| 3858 | |||
| 3859 | static void smi_recv_tasklet(unsigned long val) | ||
| 3860 | { | ||
| 3861 | handle_new_recv_msgs((ipmi_smi_t) val); | ||
| 3862 | } | ||
| 3863 | |||
| 3864 | /* Handle a new message from the lower layer. */ | 3787 | /* Handle a new message from the lower layer. */ |
| 3865 | void ipmi_smi_msg_received(ipmi_smi_t intf, | 3788 | void ipmi_smi_msg_received(ipmi_smi_t intf, |
| 3866 | struct ipmi_smi_msg *msg) | 3789 | struct ipmi_smi_msg *msg) |
| 3867 | { | 3790 | { |
| 3868 | unsigned long flags = 0; /* keep us warning-free. */ | 3791 | unsigned long flags = 0; /* keep us warning-free. */ |
| 3792 | int rv; | ||
| 3869 | int run_to_completion; | 3793 | int run_to_completion; |
| 3870 | 3794 | ||
| 3871 | 3795 | ||
| @@ -3919,11 +3843,31 @@ void ipmi_smi_msg_received(ipmi_smi_t intf, | |||
| 3919 | run_to_completion = intf->run_to_completion; | 3843 | run_to_completion = intf->run_to_completion; |
| 3920 | if (!run_to_completion) | 3844 | if (!run_to_completion) |
| 3921 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | 3845 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); |
| 3922 | list_add_tail(&msg->link, &intf->waiting_msgs); | 3846 | if (!list_empty(&intf->waiting_msgs)) { |
| 3847 | list_add_tail(&msg->link, &intf->waiting_msgs); | ||
| 3848 | if (!run_to_completion) | ||
| 3849 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | ||
| 3850 | goto out; | ||
| 3851 | } | ||
| 3923 | if (!run_to_completion) | 3852 | if (!run_to_completion) |
| 3924 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | 3853 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); |
| 3925 | 3854 | ||
| 3926 | tasklet_schedule(&intf->recv_tasklet); | 3855 | rv = handle_new_recv_msg(intf, msg); |
| 3856 | if (rv > 0) { | ||
| 3857 | /* | ||
| 3858 | * Could not handle the message now, just add it to a | ||
| 3859 | * list to handle later. | ||
| 3860 | */ | ||
| 3861 | run_to_completion = intf->run_to_completion; | ||
| 3862 | if (!run_to_completion) | ||
| 3863 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | ||
| 3864 | list_add_tail(&msg->link, &intf->waiting_msgs); | ||
| 3865 | if (!run_to_completion) | ||
| 3866 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | ||
| 3867 | } else if (rv == 0) { | ||
| 3868 | ipmi_free_smi_msg(msg); | ||
| 3869 | } | ||
| 3870 | |||
| 3927 | out: | 3871 | out: |
| 3928 | return; | 3872 | return; |
| 3929 | } | 3873 | } |
| @@ -3931,8 +3875,16 @@ EXPORT_SYMBOL(ipmi_smi_msg_received); | |||
| 3931 | 3875 | ||
| 3932 | void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) | 3876 | void ipmi_smi_watchdog_pretimeout(ipmi_smi_t intf) |
| 3933 | { | 3877 | { |
| 3934 | atomic_set(&intf->watchdog_pretimeouts_to_deliver, 1); | 3878 | ipmi_user_t user; |
| 3935 | tasklet_schedule(&intf->recv_tasklet); | 3879 | |
| 3880 | rcu_read_lock(); | ||
| 3881 | list_for_each_entry_rcu(user, &intf->users, link) { | ||
| 3882 | if (!user->handler->ipmi_watchdog_pretimeout) | ||
| 3883 | continue; | ||
| 3884 | |||
| 3885 | user->handler->ipmi_watchdog_pretimeout(user->handler_data); | ||
| 3886 | } | ||
| 3887 | rcu_read_unlock(); | ||
| 3936 | } | 3888 | } |
| 3937 | EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout); | 3889 | EXPORT_SYMBOL(ipmi_smi_watchdog_pretimeout); |
| 3938 | 3890 | ||
| @@ -4046,12 +3998,28 @@ static void ipmi_timeout_handler(long timeout_period) | |||
| 4046 | ipmi_smi_t intf; | 3998 | ipmi_smi_t intf; |
| 4047 | struct list_head timeouts; | 3999 | struct list_head timeouts; |
| 4048 | struct ipmi_recv_msg *msg, *msg2; | 4000 | struct ipmi_recv_msg *msg, *msg2; |
| 4001 | struct ipmi_smi_msg *smi_msg, *smi_msg2; | ||
| 4049 | unsigned long flags; | 4002 | unsigned long flags; |
| 4050 | int i; | 4003 | int i; |
| 4051 | 4004 | ||
| 4052 | rcu_read_lock(); | 4005 | rcu_read_lock(); |
| 4053 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { | 4006 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
| 4054 | tasklet_schedule(&intf->recv_tasklet); | 4007 | /* See if any waiting messages need to be processed. */ |
| 4008 | spin_lock_irqsave(&intf->waiting_msgs_lock, flags); | ||
| 4009 | list_for_each_entry_safe(smi_msg, smi_msg2, | ||
| 4010 | &intf->waiting_msgs, link) { | ||
| 4011 | if (!handle_new_recv_msg(intf, smi_msg)) { | ||
| 4012 | list_del(&smi_msg->link); | ||
| 4013 | ipmi_free_smi_msg(smi_msg); | ||
| 4014 | } else { | ||
| 4015 | /* | ||
| 4016 | * To preserve message order, quit if we | ||
| 4017 | * can't handle a message. | ||
| 4018 | */ | ||
| 4019 | break; | ||
| 4020 | } | ||
| 4021 | } | ||
| 4022 | spin_unlock_irqrestore(&intf->waiting_msgs_lock, flags); | ||
| 4055 | 4023 | ||
| 4056 | /* | 4024 | /* |
| 4057 | * Go through the seq table and find any messages that | 4025 | * Go through the seq table and find any messages that |
| @@ -4205,48 +4173,12 @@ EXPORT_SYMBOL(ipmi_free_recv_msg); | |||
| 4205 | 4173 | ||
| 4206 | #ifdef CONFIG_IPMI_PANIC_EVENT | 4174 | #ifdef CONFIG_IPMI_PANIC_EVENT |
| 4207 | 4175 | ||
| 4208 | static atomic_t panic_done_count = ATOMIC_INIT(0); | ||
| 4209 | |||
| 4210 | static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) | 4176 | static void dummy_smi_done_handler(struct ipmi_smi_msg *msg) |
| 4211 | { | 4177 | { |
| 4212 | atomic_dec(&panic_done_count); | ||
| 4213 | } | 4178 | } |
| 4214 | 4179 | ||
| 4215 | static void dummy_recv_done_handler(struct ipmi_recv_msg *msg) | 4180 | static void dummy_recv_done_handler(struct ipmi_recv_msg *msg) |
| 4216 | { | 4181 | { |
| 4217 | atomic_dec(&panic_done_count); | ||
| 4218 | } | ||
| 4219 | |||
| 4220 | /* | ||
| 4221 | * Inside a panic, send a message and wait for a response. | ||
| 4222 | */ | ||
| 4223 | static void ipmi_panic_request_and_wait(ipmi_smi_t intf, | ||
| 4224 | struct ipmi_addr *addr, | ||
| 4225 | struct kernel_ipmi_msg *msg) | ||
| 4226 | { | ||
| 4227 | struct ipmi_smi_msg smi_msg; | ||
| 4228 | struct ipmi_recv_msg recv_msg; | ||
| 4229 | int rv; | ||
| 4230 | |||
| 4231 | smi_msg.done = dummy_smi_done_handler; | ||
| 4232 | recv_msg.done = dummy_recv_done_handler; | ||
| 4233 | atomic_add(2, &panic_done_count); | ||
| 4234 | rv = i_ipmi_request(NULL, | ||
| 4235 | intf, | ||
| 4236 | addr, | ||
| 4237 | 0, | ||
| 4238 | msg, | ||
| 4239 | intf, | ||
| 4240 | &smi_msg, | ||
| 4241 | &recv_msg, | ||
| 4242 | 0, | ||
| 4243 | intf->channels[0].address, | ||
| 4244 | intf->channels[0].lun, | ||
| 4245 | 0, 1); /* Don't retry, and don't wait. */ | ||
| 4246 | if (rv) | ||
| 4247 | atomic_sub(2, &panic_done_count); | ||
| 4248 | while (atomic_read(&panic_done_count) != 0) | ||
| 4249 | ipmi_poll(intf); | ||
| 4250 | } | 4182 | } |
| 4251 | 4183 | ||
| 4252 | #ifdef CONFIG_IPMI_PANIC_STRING | 4184 | #ifdef CONFIG_IPMI_PANIC_STRING |
| @@ -4285,6 +4217,8 @@ static void send_panic_events(char *str) | |||
| 4285 | unsigned char data[16]; | 4217 | unsigned char data[16]; |
| 4286 | struct ipmi_system_interface_addr *si; | 4218 | struct ipmi_system_interface_addr *si; |
| 4287 | struct ipmi_addr addr; | 4219 | struct ipmi_addr addr; |
| 4220 | struct ipmi_smi_msg smi_msg; | ||
| 4221 | struct ipmi_recv_msg recv_msg; | ||
| 4288 | 4222 | ||
| 4289 | si = (struct ipmi_system_interface_addr *) &addr; | 4223 | si = (struct ipmi_system_interface_addr *) &addr; |
| 4290 | si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; | 4224 | si->addr_type = IPMI_SYSTEM_INTERFACE_ADDR_TYPE; |
| @@ -4312,6 +4246,9 @@ static void send_panic_events(char *str) | |||
| 4312 | data[7] = str[2]; | 4246 | data[7] = str[2]; |
| 4313 | } | 4247 | } |
| 4314 | 4248 | ||
| 4249 | smi_msg.done = dummy_smi_done_handler; | ||
| 4250 | recv_msg.done = dummy_recv_done_handler; | ||
| 4251 | |||
| 4315 | /* For every registered interface, send the event. */ | 4252 | /* For every registered interface, send the event. */ |
| 4316 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { | 4253 | list_for_each_entry_rcu(intf, &ipmi_interfaces, link) { |
| 4317 | if (!intf->handlers) | 4254 | if (!intf->handlers) |
| @@ -4321,7 +4258,18 @@ static void send_panic_events(char *str) | |||
| 4321 | intf->run_to_completion = 1; | 4258 | intf->run_to_completion = 1; |
| 4322 | /* Send the event announcing the panic. */ | 4259 | /* Send the event announcing the panic. */ |
| 4323 | intf->handlers->set_run_to_completion(intf->send_info, 1); | 4260 | intf->handlers->set_run_to_completion(intf->send_info, 1); |
| 4324 | ipmi_panic_request_and_wait(intf, &addr, &msg); | 4261 | i_ipmi_request(NULL, |
| 4262 | intf, | ||
| 4263 | &addr, | ||
| 4264 | 0, | ||
| 4265 | &msg, | ||
| 4266 | intf, | ||
| 4267 | &smi_msg, | ||
| 4268 | &recv_msg, | ||
| 4269 | 0, | ||
| 4270 | intf->channels[0].address, | ||
| 4271 | intf->channels[0].lun, | ||
| 4272 | 0, 1); /* Don't retry, and don't wait. */ | ||
| 4325 | } | 4273 | } |
| 4326 | 4274 | ||
| 4327 | #ifdef CONFIG_IPMI_PANIC_STRING | 4275 | #ifdef CONFIG_IPMI_PANIC_STRING |
| @@ -4369,7 +4317,18 @@ static void send_panic_events(char *str) | |||
| 4369 | msg.data = NULL; | 4317 | msg.data = NULL; |
| 4370 | msg.data_len = 0; | 4318 | msg.data_len = 0; |
| 4371 | intf->null_user_handler = device_id_fetcher; | 4319 | intf->null_user_handler = device_id_fetcher; |
| 4372 | ipmi_panic_request_and_wait(intf, &addr, &msg); | 4320 | i_ipmi_request(NULL, |
| 4321 | intf, | ||
| 4322 | &addr, | ||
| 4323 | 0, | ||
| 4324 | &msg, | ||
| 4325 | intf, | ||
| 4326 | &smi_msg, | ||
| 4327 | &recv_msg, | ||
| 4328 | 0, | ||
| 4329 | intf->channels[0].address, | ||
| 4330 | intf->channels[0].lun, | ||
| 4331 | 0, 1); /* Don't retry, and don't wait. */ | ||
| 4373 | 4332 | ||
| 4374 | if (intf->local_event_generator) { | 4333 | if (intf->local_event_generator) { |
| 4375 | /* Request the event receiver from the local MC. */ | 4334 | /* Request the event receiver from the local MC. */ |
| @@ -4378,7 +4337,18 @@ static void send_panic_events(char *str) | |||
| 4378 | msg.data = NULL; | 4337 | msg.data = NULL; |
| 4379 | msg.data_len = 0; | 4338 | msg.data_len = 0; |
| 4380 | intf->null_user_handler = event_receiver_fetcher; | 4339 | intf->null_user_handler = event_receiver_fetcher; |
| 4381 | ipmi_panic_request_and_wait(intf, &addr, &msg); | 4340 | i_ipmi_request(NULL, |
| 4341 | intf, | ||
| 4342 | &addr, | ||
| 4343 | 0, | ||
| 4344 | &msg, | ||
| 4345 | intf, | ||
| 4346 | &smi_msg, | ||
| 4347 | &recv_msg, | ||
| 4348 | 0, | ||
| 4349 | intf->channels[0].address, | ||
| 4350 | intf->channels[0].lun, | ||
| 4351 | 0, 1); /* no retry, and no wait. */ | ||
| 4382 | } | 4352 | } |
| 4383 | intf->null_user_handler = NULL; | 4353 | intf->null_user_handler = NULL; |
| 4384 | 4354 | ||
| @@ -4435,7 +4405,18 @@ static void send_panic_events(char *str) | |||
| 4435 | strncpy(data+5, p, 11); | 4405 | strncpy(data+5, p, 11); |
| 4436 | p += size; | 4406 | p += size; |
| 4437 | 4407 | ||
| 4438 | ipmi_panic_request_and_wait(intf, &addr, &msg); | 4408 | i_ipmi_request(NULL, |
| 4409 | intf, | ||
| 4410 | &addr, | ||
| 4411 | 0, | ||
| 4412 | &msg, | ||
| 4413 | intf, | ||
| 4414 | &smi_msg, | ||
| 4415 | &recv_msg, | ||
| 4416 | 0, | ||
| 4417 | intf->channels[0].address, | ||
| 4418 | intf->channels[0].lun, | ||
| 4419 | 0, 1); /* no retry, and no wait. */ | ||
| 4439 | } | 4420 | } |
| 4440 | } | 4421 | } |
| 4441 | #endif /* CONFIG_IPMI_PANIC_STRING */ | 4422 | #endif /* CONFIG_IPMI_PANIC_STRING */ |
diff --git a/drivers/char/ipmi/ipmi_si_intf.c b/drivers/char/ipmi/ipmi_si_intf.c index 1c7fdcd22a9..9397ab49b72 100644 --- a/drivers/char/ipmi/ipmi_si_intf.c +++ b/drivers/char/ipmi/ipmi_si_intf.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | 41 | ||
| 42 | #include <linux/module.h> | 42 | #include <linux/module.h> |
| 43 | #include <linux/moduleparam.h> | 43 | #include <linux/moduleparam.h> |
| 44 | #include <asm/system.h> | ||
| 44 | #include <linux/sched.h> | 45 | #include <linux/sched.h> |
| 45 | #include <linux/seq_file.h> | 46 | #include <linux/seq_file.h> |
| 46 | #include <linux/timer.h> | 47 | #include <linux/timer.h> |
| @@ -155,7 +156,7 @@ enum si_stat_indexes { | |||
| 155 | /* Number of watchdog pretimeouts. */ | 156 | /* Number of watchdog pretimeouts. */ |
| 156 | SI_STAT_watchdog_pretimeouts, | 157 | SI_STAT_watchdog_pretimeouts, |
| 157 | 158 | ||
| 158 | /* Number of asynchronous messages received. */ | 159 | /* Number of asyncronous messages received. */ |
| 159 | SI_STAT_incoming_messages, | 160 | SI_STAT_incoming_messages, |
| 160 | 161 | ||
| 161 | 162 | ||
| @@ -170,6 +171,7 @@ struct smi_info { | |||
| 170 | struct si_sm_handlers *handlers; | 171 | struct si_sm_handlers *handlers; |
| 171 | enum si_type si_type; | 172 | enum si_type si_type; |
| 172 | spinlock_t si_lock; | 173 | spinlock_t si_lock; |
| 174 | spinlock_t msg_lock; | ||
| 173 | struct list_head xmit_msgs; | 175 | struct list_head xmit_msgs; |
| 174 | struct list_head hp_xmit_msgs; | 176 | struct list_head hp_xmit_msgs; |
| 175 | struct ipmi_smi_msg *curr_msg; | 177 | struct ipmi_smi_msg *curr_msg; |
| @@ -318,8 +320,16 @@ static int register_xaction_notifier(struct notifier_block *nb) | |||
| 318 | static void deliver_recv_msg(struct smi_info *smi_info, | 320 | static void deliver_recv_msg(struct smi_info *smi_info, |
| 319 | struct ipmi_smi_msg *msg) | 321 | struct ipmi_smi_msg *msg) |
| 320 | { | 322 | { |
| 321 | /* Deliver the message to the upper layer. */ | 323 | /* Deliver the message to the upper layer with the lock |
| 322 | ipmi_smi_msg_received(smi_info->intf, msg); | 324 | released. */ |
| 325 | |||
| 326 | if (smi_info->run_to_completion) { | ||
| 327 | ipmi_smi_msg_received(smi_info->intf, msg); | ||
| 328 | } else { | ||
| 329 | spin_unlock(&(smi_info->si_lock)); | ||
| 330 | ipmi_smi_msg_received(smi_info->intf, msg); | ||
| 331 | spin_lock(&(smi_info->si_lock)); | ||
| 332 | } | ||
| 323 | } | 333 | } |
| 324 | 334 | ||
| 325 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) | 335 | static void return_hosed_msg(struct smi_info *smi_info, int cCode) |
| @@ -348,6 +358,13 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
| 348 | struct timeval t; | 358 | struct timeval t; |
| 349 | #endif | 359 | #endif |
| 350 | 360 | ||
| 361 | /* | ||
| 362 | * No need to save flags, we aleady have interrupts off and we | ||
| 363 | * already hold the SMI lock. | ||
| 364 | */ | ||
| 365 | if (!smi_info->run_to_completion) | ||
| 366 | spin_lock(&(smi_info->msg_lock)); | ||
| 367 | |||
| 351 | /* Pick the high priority queue first. */ | 368 | /* Pick the high priority queue first. */ |
| 352 | if (!list_empty(&(smi_info->hp_xmit_msgs))) { | 369 | if (!list_empty(&(smi_info->hp_xmit_msgs))) { |
| 353 | entry = smi_info->hp_xmit_msgs.next; | 370 | entry = smi_info->hp_xmit_msgs.next; |
| @@ -385,6 +402,9 @@ static enum si_sm_result start_next_msg(struct smi_info *smi_info) | |||
| 385 | rv = SI_SM_CALL_WITHOUT_DELAY; | 402 | rv = SI_SM_CALL_WITHOUT_DELAY; |
| 386 | } | 403 | } |
| 387 | out: | 404 | out: |
| 405 | if (!smi_info->run_to_completion) | ||
| 406 | spin_unlock(&(smi_info->msg_lock)); | ||
| 407 | |||
| 388 | return rv; | 408 | return rv; |
| 389 | } | 409 | } |
| 390 | 410 | ||
| @@ -461,7 +481,9 @@ static void handle_flags(struct smi_info *smi_info) | |||
| 461 | 481 | ||
| 462 | start_clear_flags(smi_info); | 482 | start_clear_flags(smi_info); |
| 463 | smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; | 483 | smi_info->msg_flags &= ~WDT_PRE_TIMEOUT_INT; |
| 484 | spin_unlock(&(smi_info->si_lock)); | ||
| 464 | ipmi_smi_watchdog_pretimeout(smi_info->intf); | 485 | ipmi_smi_watchdog_pretimeout(smi_info->intf); |
| 486 | spin_lock(&(smi_info->si_lock)); | ||
| 465 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { | 487 | } else if (smi_info->msg_flags & RECEIVE_MSG_AVAIL) { |
| 466 | /* Messages available. */ | 488 | /* Messages available. */ |
| 467 | smi_info->curr_msg = ipmi_alloc_smi_msg(); | 489 | smi_info->curr_msg = ipmi_alloc_smi_msg(); |
| @@ -867,6 +889,19 @@ static void sender(void *send_info, | |||
| 867 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); | 889 | printk("**Enqueue: %d.%9.9d\n", t.tv_sec, t.tv_usec); |
| 868 | #endif | 890 | #endif |
| 869 | 891 | ||
| 892 | /* | ||
| 893 | * last_timeout_jiffies is updated here to avoid | ||
| 894 | * smi_timeout() handler passing very large time_diff | ||
| 895 | * value to smi_event_handler() that causes | ||
| 896 | * the send command to abort. | ||
| 897 | */ | ||
| 898 | smi_info->last_timeout_jiffies = jiffies; | ||
| 899 | |||
| 900 | mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); | ||
| 901 | |||
| 902 | if (smi_info->thread) | ||
| 903 | wake_up_process(smi_info->thread); | ||
| 904 | |||
| 870 | if (smi_info->run_to_completion) { | 905 | if (smi_info->run_to_completion) { |
| 871 | /* | 906 | /* |
| 872 | * If we are running to completion, then throw it in | 907 | * If we are running to completion, then throw it in |
| @@ -889,29 +924,16 @@ static void sender(void *send_info, | |||
| 889 | return; | 924 | return; |
| 890 | } | 925 | } |
| 891 | 926 | ||
| 892 | spin_lock_irqsave(&smi_info->si_lock, flags); | 927 | spin_lock_irqsave(&smi_info->msg_lock, flags); |
| 893 | if (priority > 0) | 928 | if (priority > 0) |
| 894 | list_add_tail(&msg->link, &smi_info->hp_xmit_msgs); | 929 | list_add_tail(&msg->link, &smi_info->hp_xmit_msgs); |
| 895 | else | 930 | else |
| 896 | list_add_tail(&msg->link, &smi_info->xmit_msgs); | 931 | list_add_tail(&msg->link, &smi_info->xmit_msgs); |
| 932 | spin_unlock_irqrestore(&smi_info->msg_lock, flags); | ||
| 897 | 933 | ||
| 898 | if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) { | 934 | spin_lock_irqsave(&smi_info->si_lock, flags); |
| 899 | /* | 935 | if (smi_info->si_state == SI_NORMAL && smi_info->curr_msg == NULL) |
| 900 | * last_timeout_jiffies is updated here to avoid | ||
| 901 | * smi_timeout() handler passing very large time_diff | ||
| 902 | * value to smi_event_handler() that causes | ||
| 903 | * the send command to abort. | ||
| 904 | */ | ||
| 905 | smi_info->last_timeout_jiffies = jiffies; | ||
| 906 | |||
| 907 | mod_timer(&smi_info->si_timer, jiffies + SI_TIMEOUT_JIFFIES); | ||
| 908 | |||
| 909 | if (smi_info->thread) | ||
| 910 | wake_up_process(smi_info->thread); | ||
| 911 | |||
| 912 | start_next_msg(smi_info); | 936 | start_next_msg(smi_info); |
| 913 | smi_event_handler(smi_info, 0); | ||
| 914 | } | ||
| 915 | spin_unlock_irqrestore(&smi_info->si_lock, flags); | 937 | spin_unlock_irqrestore(&smi_info->si_lock, flags); |
| 916 | } | 938 | } |
| 917 | 939 | ||
| @@ -1012,19 +1034,16 @@ static int ipmi_thread(void *data) | |||
| 1012 | static void poll(void *send_info) | 1034 | static void poll(void *send_info) |
| 1013 | { | 1035 | { |
| 1014 | struct smi_info *smi_info = send_info; | 1036 | struct smi_info *smi_info = send_info; |
| 1015 | unsigned long flags = 0; | 1037 | unsigned long flags; |
| 1016 | int run_to_completion = smi_info->run_to_completion; | ||
| 1017 | 1038 | ||
| 1018 | /* | 1039 | /* |
| 1019 | * Make sure there is some delay in the poll loop so we can | 1040 | * Make sure there is some delay in the poll loop so we can |
| 1020 | * drive time forward and timeout things. | 1041 | * drive time forward and timeout things. |
| 1021 | */ | 1042 | */ |
| 1022 | udelay(10); | 1043 | udelay(10); |
| 1023 | if (!run_to_completion) | 1044 | spin_lock_irqsave(&smi_info->si_lock, flags); |
| 1024 | spin_lock_irqsave(&smi_info->si_lock, flags); | ||
| 1025 | smi_event_handler(smi_info, 10); | 1045 | smi_event_handler(smi_info, 10); |
| 1026 | if (!run_to_completion) | 1046 | spin_unlock_irqrestore(&smi_info->si_lock, flags); |
| 1027 | spin_unlock_irqrestore(&smi_info->si_lock, flags); | ||
| 1028 | } | 1047 | } |
| 1029 | 1048 | ||
| 1030 | static void request_events(void *send_info) | 1049 | static void request_events(void *send_info) |
| @@ -1208,7 +1227,7 @@ static int smi_num; /* Used to sequence the SMIs */ | |||
| 1208 | #define DEFAULT_REGSPACING 1 | 1227 | #define DEFAULT_REGSPACING 1 |
| 1209 | #define DEFAULT_REGSIZE 1 | 1228 | #define DEFAULT_REGSIZE 1 |
| 1210 | 1229 | ||
| 1211 | static bool si_trydefaults = 1; | 1230 | static int si_trydefaults = 1; |
| 1212 | static char *si_type[SI_MAX_PARMS]; | 1231 | static char *si_type[SI_MAX_PARMS]; |
| 1213 | #define MAX_SI_TYPE_STR 30 | 1232 | #define MAX_SI_TYPE_STR 30 |
| 1214 | static char si_type_str[MAX_SI_TYPE_STR]; | 1233 | static char si_type_str[MAX_SI_TYPE_STR]; |
| @@ -1661,8 +1680,10 @@ static struct smi_info *smi_info_alloc(void) | |||
| 1661 | { | 1680 | { |
| 1662 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); | 1681 | struct smi_info *info = kzalloc(sizeof(*info), GFP_KERNEL); |
| 1663 | 1682 | ||
| 1664 | if (info) | 1683 | if (info) { |
| 1665 | spin_lock_init(&info->si_lock); | 1684 | spin_lock_init(&info->si_lock); |
| 1685 | spin_lock_init(&info->msg_lock); | ||
| 1686 | } | ||
| 1666 | return info; | 1687 | return info; |
| 1667 | } | 1688 | } |
| 1668 | 1689 | ||
| @@ -1836,7 +1857,7 @@ static int hotmod_handler(const char *val, struct kernel_param *kp) | |||
| 1836 | return rv; | 1857 | return rv; |
| 1837 | } | 1858 | } |
| 1838 | 1859 | ||
| 1839 | static int hardcode_find_bmc(void) | 1860 | static int __devinit hardcode_find_bmc(void) |
| 1840 | { | 1861 | { |
| 1841 | int ret = -ENODEV; | 1862 | int ret = -ENODEV; |
| 1842 | int i; | 1863 | int i; |
| @@ -2023,7 +2044,7 @@ struct SPMITable { | |||
| 2023 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ | 2044 | s8 spmi_id[1]; /* A '\0' terminated array starts here. */ |
| 2024 | }; | 2045 | }; |
| 2025 | 2046 | ||
| 2026 | static int try_init_spmi(struct SPMITable *spmi) | 2047 | static int __devinit try_init_spmi(struct SPMITable *spmi) |
| 2027 | { | 2048 | { |
| 2028 | struct smi_info *info; | 2049 | struct smi_info *info; |
| 2029 | 2050 | ||
| @@ -2106,7 +2127,7 @@ static int try_init_spmi(struct SPMITable *spmi) | |||
| 2106 | return 0; | 2127 | return 0; |
| 2107 | } | 2128 | } |
| 2108 | 2129 | ||
| 2109 | static void spmi_find_bmc(void) | 2130 | static void __devinit spmi_find_bmc(void) |
| 2110 | { | 2131 | { |
| 2111 | acpi_status status; | 2132 | acpi_status status; |
| 2112 | struct SPMITable *spmi; | 2133 | struct SPMITable *spmi; |
| @@ -2128,7 +2149,7 @@ static void spmi_find_bmc(void) | |||
| 2128 | } | 2149 | } |
| 2129 | } | 2150 | } |
| 2130 | 2151 | ||
| 2131 | static int ipmi_pnp_probe(struct pnp_dev *dev, | 2152 | static int __devinit ipmi_pnp_probe(struct pnp_dev *dev, |
| 2132 | const struct pnp_device_id *dev_id) | 2153 | const struct pnp_device_id *dev_id) |
| 2133 | { | 2154 | { |
| 2134 | struct acpi_device *acpi_dev; | 2155 | struct acpi_device *acpi_dev; |
| @@ -2228,7 +2249,7 @@ err_free: | |||
| 2228 | return -EINVAL; | 2249 | return -EINVAL; |
| 2229 | } | 2250 | } |
| 2230 | 2251 | ||
| 2231 | static void ipmi_pnp_remove(struct pnp_dev *dev) | 2252 | static void __devexit ipmi_pnp_remove(struct pnp_dev *dev) |
| 2232 | { | 2253 | { |
| 2233 | struct smi_info *info = pnp_get_drvdata(dev); | 2254 | struct smi_info *info = pnp_get_drvdata(dev); |
| 2234 | 2255 | ||
| @@ -2243,7 +2264,7 @@ static const struct pnp_device_id pnp_dev_table[] = { | |||
| 2243 | static struct pnp_driver ipmi_pnp_driver = { | 2264 | static struct pnp_driver ipmi_pnp_driver = { |
| 2244 | .name = DEVICE_NAME, | 2265 | .name = DEVICE_NAME, |
| 2245 | .probe = ipmi_pnp_probe, | 2266 | .probe = ipmi_pnp_probe, |
| 2246 | .remove = ipmi_pnp_remove, | 2267 | .remove = __devexit_p(ipmi_pnp_remove), |
| 2247 | .id_table = pnp_dev_table, | 2268 | .id_table = pnp_dev_table, |
| 2248 | }; | 2269 | }; |
| 2249 | #endif | 2270 | #endif |
| @@ -2258,7 +2279,7 @@ struct dmi_ipmi_data { | |||
| 2258 | u8 slave_addr; | 2279 | u8 slave_addr; |
| 2259 | }; | 2280 | }; |
| 2260 | 2281 | ||
| 2261 | static int decode_dmi(const struct dmi_header *dm, | 2282 | static int __devinit decode_dmi(const struct dmi_header *dm, |
| 2262 | struct dmi_ipmi_data *dmi) | 2283 | struct dmi_ipmi_data *dmi) |
| 2263 | { | 2284 | { |
| 2264 | const u8 *data = (const u8 *)dm; | 2285 | const u8 *data = (const u8 *)dm; |
| @@ -2320,7 +2341,7 @@ static int decode_dmi(const struct dmi_header *dm, | |||
| 2320 | return 0; | 2341 | return 0; |
| 2321 | } | 2342 | } |
| 2322 | 2343 | ||
| 2323 | static void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | 2344 | static void __devinit try_init_dmi(struct dmi_ipmi_data *ipmi_data) |
| 2324 | { | 2345 | { |
| 2325 | struct smi_info *info; | 2346 | struct smi_info *info; |
| 2326 | 2347 | ||
| @@ -2388,7 +2409,7 @@ static void try_init_dmi(struct dmi_ipmi_data *ipmi_data) | |||
| 2388 | kfree(info); | 2409 | kfree(info); |
| 2389 | } | 2410 | } |
| 2390 | 2411 | ||
| 2391 | static void dmi_find_bmc(void) | 2412 | static void __devinit dmi_find_bmc(void) |
| 2392 | { | 2413 | { |
| 2393 | const struct dmi_device *dev = NULL; | 2414 | const struct dmi_device *dev = NULL; |
| 2394 | struct dmi_ipmi_data data; | 2415 | struct dmi_ipmi_data data; |
| @@ -2424,39 +2445,7 @@ static void ipmi_pci_cleanup(struct smi_info *info) | |||
| 2424 | pci_disable_device(pdev); | 2445 | pci_disable_device(pdev); |
| 2425 | } | 2446 | } |
| 2426 | 2447 | ||
| 2427 | static int ipmi_pci_probe_regspacing(struct smi_info *info) | 2448 | static int __devinit ipmi_pci_probe(struct pci_dev *pdev, |
| 2428 | { | ||
| 2429 | if (info->si_type == SI_KCS) { | ||
| 2430 | unsigned char status; | ||
| 2431 | int regspacing; | ||
| 2432 | |||
| 2433 | info->io.regsize = DEFAULT_REGSIZE; | ||
| 2434 | info->io.regshift = 0; | ||
| 2435 | info->io_size = 2; | ||
| 2436 | info->handlers = &kcs_smi_handlers; | ||
| 2437 | |||
| 2438 | /* detect 1, 4, 16byte spacing */ | ||
| 2439 | for (regspacing = DEFAULT_REGSPACING; regspacing <= 16;) { | ||
| 2440 | info->io.regspacing = regspacing; | ||
| 2441 | if (info->io_setup(info)) { | ||
| 2442 | dev_err(info->dev, | ||
| 2443 | "Could not setup I/O space\n"); | ||
| 2444 | return DEFAULT_REGSPACING; | ||
| 2445 | } | ||
| 2446 | /* write invalid cmd */ | ||
| 2447 | info->io.outputb(&info->io, 1, 0x10); | ||
| 2448 | /* read status back */ | ||
| 2449 | status = info->io.inputb(&info->io, 1); | ||
| 2450 | info->io_cleanup(info); | ||
| 2451 | if (status) | ||
| 2452 | return regspacing; | ||
| 2453 | regspacing *= 4; | ||
| 2454 | } | ||
| 2455 | } | ||
| 2456 | return DEFAULT_REGSPACING; | ||
| 2457 | } | ||
| 2458 | |||
| 2459 | static int ipmi_pci_probe(struct pci_dev *pdev, | ||
| 2460 | const struct pci_device_id *ent) | 2449 | const struct pci_device_id *ent) |
| 2461 | { | 2450 | { |
| 2462 | int rv; | 2451 | int rv; |
| @@ -2508,8 +2497,8 @@ static int ipmi_pci_probe(struct pci_dev *pdev, | |||
| 2508 | } | 2497 | } |
| 2509 | info->io.addr_data = pci_resource_start(pdev, 0); | 2498 | info->io.addr_data = pci_resource_start(pdev, 0); |
| 2510 | 2499 | ||
| 2511 | info->io.regspacing = ipmi_pci_probe_regspacing(info); | 2500 | info->io.regspacing = DEFAULT_REGSPACING; |
| 2512 | info->io.regsize = DEFAULT_REGSIZE; | 2501 | info->io.regsize = DEFAULT_REGSPACING; |
| 2513 | info->io.regshift = 0; | 2502 | info->io.regshift = 0; |
| 2514 | 2503 | ||
| 2515 | info->irq = pdev->irq; | 2504 | info->irq = pdev->irq; |
| @@ -2529,12 +2518,24 @@ static int ipmi_pci_probe(struct pci_dev *pdev, | |||
| 2529 | return 0; | 2518 | return 0; |
| 2530 | } | 2519 | } |
| 2531 | 2520 | ||
| 2532 | static void ipmi_pci_remove(struct pci_dev *pdev) | 2521 | static void __devexit ipmi_pci_remove(struct pci_dev *pdev) |
| 2533 | { | 2522 | { |
| 2534 | struct smi_info *info = pci_get_drvdata(pdev); | 2523 | struct smi_info *info = pci_get_drvdata(pdev); |
| 2535 | cleanup_one_si(info); | 2524 | cleanup_one_si(info); |
| 2536 | } | 2525 | } |
| 2537 | 2526 | ||
| 2527 | #ifdef CONFIG_PM | ||
| 2528 | static int ipmi_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
| 2529 | { | ||
| 2530 | return 0; | ||
| 2531 | } | ||
| 2532 | |||
| 2533 | static int ipmi_pci_resume(struct pci_dev *pdev) | ||
| 2534 | { | ||
| 2535 | return 0; | ||
| 2536 | } | ||
| 2537 | #endif | ||
| 2538 | |||
| 2538 | static struct pci_device_id ipmi_pci_devices[] = { | 2539 | static struct pci_device_id ipmi_pci_devices[] = { |
| 2539 | { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, | 2540 | { PCI_DEVICE(PCI_HP_VENDOR_ID, PCI_MMC_DEVICE_ID) }, |
| 2540 | { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }, | 2541 | { PCI_DEVICE_CLASS(PCI_ERMC_CLASSCODE, PCI_ERMC_CLASSCODE_MASK) }, |
| @@ -2546,12 +2547,16 @@ static struct pci_driver ipmi_pci_driver = { | |||
| 2546 | .name = DEVICE_NAME, | 2547 | .name = DEVICE_NAME, |
| 2547 | .id_table = ipmi_pci_devices, | 2548 | .id_table = ipmi_pci_devices, |
| 2548 | .probe = ipmi_pci_probe, | 2549 | .probe = ipmi_pci_probe, |
| 2549 | .remove = ipmi_pci_remove, | 2550 | .remove = __devexit_p(ipmi_pci_remove), |
| 2551 | #ifdef CONFIG_PM | ||
| 2552 | .suspend = ipmi_pci_suspend, | ||
| 2553 | .resume = ipmi_pci_resume, | ||
| 2554 | #endif | ||
| 2550 | }; | 2555 | }; |
| 2551 | #endif /* CONFIG_PCI */ | 2556 | #endif /* CONFIG_PCI */ |
| 2552 | 2557 | ||
| 2553 | static struct of_device_id ipmi_match[]; | 2558 | static struct of_device_id ipmi_match[]; |
| 2554 | static int ipmi_probe(struct platform_device *dev) | 2559 | static int __devinit ipmi_probe(struct platform_device *dev) |
| 2555 | { | 2560 | { |
| 2556 | #ifdef CONFIG_OF | 2561 | #ifdef CONFIG_OF |
| 2557 | const struct of_device_id *match; | 2562 | const struct of_device_id *match; |
| @@ -2635,7 +2640,7 @@ static int ipmi_probe(struct platform_device *dev) | |||
| 2635 | return 0; | 2640 | return 0; |
| 2636 | } | 2641 | } |
| 2637 | 2642 | ||
| 2638 | static int ipmi_remove(struct platform_device *dev) | 2643 | static int __devexit ipmi_remove(struct platform_device *dev) |
| 2639 | { | 2644 | { |
| 2640 | #ifdef CONFIG_OF | 2645 | #ifdef CONFIG_OF |
| 2641 | cleanup_one_si(dev_get_drvdata(&dev->dev)); | 2646 | cleanup_one_si(dev_get_drvdata(&dev->dev)); |
| @@ -2661,7 +2666,7 @@ static struct platform_driver ipmi_driver = { | |||
| 2661 | .of_match_table = ipmi_match, | 2666 | .of_match_table = ipmi_match, |
| 2662 | }, | 2667 | }, |
| 2663 | .probe = ipmi_probe, | 2668 | .probe = ipmi_probe, |
| 2664 | .remove = ipmi_remove, | 2669 | .remove = __devexit_p(ipmi_remove), |
| 2665 | }; | 2670 | }; |
| 2666 | 2671 | ||
| 2667 | static int wait_for_msg_done(struct smi_info *smi_info) | 2672 | static int wait_for_msg_done(struct smi_info *smi_info) |
| @@ -3047,7 +3052,7 @@ static inline void wait_for_timer_and_thread(struct smi_info *smi_info) | |||
| 3047 | } | 3052 | } |
| 3048 | } | 3053 | } |
| 3049 | 3054 | ||
| 3050 | static struct ipmi_default_vals | 3055 | static __devinitdata struct ipmi_default_vals |
| 3051 | { | 3056 | { |
| 3052 | int type; | 3057 | int type; |
| 3053 | int port; | 3058 | int port; |
| @@ -3059,7 +3064,7 @@ static struct ipmi_default_vals | |||
| 3059 | { .port = 0 } | 3064 | { .port = 0 } |
| 3060 | }; | 3065 | }; |
| 3061 | 3066 | ||
| 3062 | static void default_find_bmc(void) | 3067 | static void __devinit default_find_bmc(void) |
| 3063 | { | 3068 | { |
| 3064 | struct smi_info *info; | 3069 | struct smi_info *info; |
| 3065 | int i; | 3070 | int i; |
| @@ -3359,7 +3364,7 @@ static int try_smi_init(struct smi_info *new_smi) | |||
| 3359 | return rv; | 3364 | return rv; |
| 3360 | } | 3365 | } |
| 3361 | 3366 | ||
| 3362 | static int init_ipmi_si(void) | 3367 | static int __devinit init_ipmi_si(void) |
| 3363 | { | 3368 | { |
| 3364 | int i; | 3369 | int i; |
| 3365 | char *str; | 3370 | char *str; |
diff --git a/drivers/char/ipmi/ipmi_watchdog.c b/drivers/char/ipmi/ipmi_watchdog.c index 37b8be7cba9..3302586655c 100644 --- a/drivers/char/ipmi/ipmi_watchdog.c +++ b/drivers/char/ipmi/ipmi_watchdog.c | |||
| @@ -65,7 +65,6 @@ | |||
| 65 | * mechanism for it at that time. | 65 | * mechanism for it at that time. |
| 66 | */ | 66 | */ |
| 67 | #include <asm/kdebug.h> | 67 | #include <asm/kdebug.h> |
| 68 | #include <asm/nmi.h> | ||
| 69 | #define HAVE_DIE_NMI | 68 | #define HAVE_DIE_NMI |
| 70 | #endif | 69 | #endif |
| 71 | 70 | ||
| @@ -139,10 +138,19 @@ | |||
| 139 | #define IPMI_WDOG_SET_TIMER 0x24 | 138 | #define IPMI_WDOG_SET_TIMER 0x24 |
| 140 | #define IPMI_WDOG_GET_TIMER 0x25 | 139 | #define IPMI_WDOG_GET_TIMER 0x25 |
| 141 | 140 | ||
| 142 | #define IPMI_WDOG_TIMER_NOT_INIT_RESP 0x80 | 141 | /* These are here until the real ones get into the watchdog.h interface. */ |
| 142 | #ifndef WDIOC_GETTIMEOUT | ||
| 143 | #define WDIOC_GETTIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 20, int) | ||
| 144 | #endif | ||
| 145 | #ifndef WDIOC_SET_PRETIMEOUT | ||
| 146 | #define WDIOC_SET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 21, int) | ||
| 147 | #endif | ||
| 148 | #ifndef WDIOC_GET_PRETIMEOUT | ||
| 149 | #define WDIOC_GET_PRETIMEOUT _IOW(WATCHDOG_IOCTL_BASE, 22, int) | ||
| 150 | #endif | ||
| 143 | 151 | ||
| 144 | static DEFINE_MUTEX(ipmi_watchdog_mutex); | 152 | static DEFINE_MUTEX(ipmi_watchdog_mutex); |
| 145 | static bool nowayout = WATCHDOG_NOWAYOUT; | 153 | static int nowayout = WATCHDOG_NOWAYOUT; |
| 146 | 154 | ||
| 147 | static ipmi_user_t watchdog_user; | 155 | static ipmi_user_t watchdog_user; |
| 148 | static int watchdog_ifnum; | 156 | static int watchdog_ifnum; |
| @@ -309,7 +317,7 @@ module_param(start_now, int, 0444); | |||
| 309 | MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as" | 317 | MODULE_PARM_DESC(start_now, "Set to 1 to start the watchdog as" |
| 310 | "soon as the driver is loaded."); | 318 | "soon as the driver is loaded."); |
| 311 | 319 | ||
| 312 | module_param(nowayout, bool, 0644); | 320 | module_param(nowayout, int, 0644); |
| 313 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | 321 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " |
| 314 | "(default=CONFIG_WATCHDOG_NOWAYOUT)"); | 322 | "(default=CONFIG_WATCHDOG_NOWAYOUT)"); |
| 315 | 323 | ||
| @@ -509,7 +517,6 @@ static void panic_halt_ipmi_heartbeat(void) | |||
| 509 | msg.cmd = IPMI_WDOG_RESET_TIMER; | 517 | msg.cmd = IPMI_WDOG_RESET_TIMER; |
| 510 | msg.data = NULL; | 518 | msg.data = NULL; |
| 511 | msg.data_len = 0; | 519 | msg.data_len = 0; |
| 512 | atomic_add(2, &panic_done_count); | ||
| 513 | rv = ipmi_request_supply_msgs(watchdog_user, | 520 | rv = ipmi_request_supply_msgs(watchdog_user, |
| 514 | (struct ipmi_addr *) &addr, | 521 | (struct ipmi_addr *) &addr, |
| 515 | 0, | 522 | 0, |
| @@ -518,8 +525,8 @@ static void panic_halt_ipmi_heartbeat(void) | |||
| 518 | &panic_halt_heartbeat_smi_msg, | 525 | &panic_halt_heartbeat_smi_msg, |
| 519 | &panic_halt_heartbeat_recv_msg, | 526 | &panic_halt_heartbeat_recv_msg, |
| 520 | 1); | 527 | 1); |
| 521 | if (rv) | 528 | if (!rv) |
| 522 | atomic_sub(2, &panic_done_count); | 529 | atomic_add(2, &panic_done_count); |
| 523 | } | 530 | } |
| 524 | 531 | ||
| 525 | static struct ipmi_smi_msg panic_halt_smi_msg = { | 532 | static struct ipmi_smi_msg panic_halt_smi_msg = { |
| @@ -543,18 +550,16 @@ static void panic_halt_ipmi_set_timeout(void) | |||
| 543 | /* Wait for the messages to be free. */ | 550 | /* Wait for the messages to be free. */ |
| 544 | while (atomic_read(&panic_done_count) != 0) | 551 | while (atomic_read(&panic_done_count) != 0) |
| 545 | ipmi_poll_interface(watchdog_user); | 552 | ipmi_poll_interface(watchdog_user); |
| 546 | atomic_add(2, &panic_done_count); | ||
| 547 | rv = i_ipmi_set_timeout(&panic_halt_smi_msg, | 553 | rv = i_ipmi_set_timeout(&panic_halt_smi_msg, |
| 548 | &panic_halt_recv_msg, | 554 | &panic_halt_recv_msg, |
| 549 | &send_heartbeat_now); | 555 | &send_heartbeat_now); |
| 550 | if (rv) { | 556 | if (!rv) { |
| 551 | atomic_sub(2, &panic_done_count); | 557 | atomic_add(2, &panic_done_count); |
| 552 | printk(KERN_WARNING PFX | ||
| 553 | "Unable to extend the watchdog timeout."); | ||
| 554 | } else { | ||
| 555 | if (send_heartbeat_now) | 558 | if (send_heartbeat_now) |
| 556 | panic_halt_ipmi_heartbeat(); | 559 | panic_halt_ipmi_heartbeat(); |
| 557 | } | 560 | } else |
| 561 | printk(KERN_WARNING PFX | ||
| 562 | "Unable to extend the watchdog timeout."); | ||
| 558 | while (atomic_read(&panic_done_count) != 0) | 563 | while (atomic_read(&panic_done_count) != 0) |
| 559 | ipmi_poll_interface(watchdog_user); | 564 | ipmi_poll_interface(watchdog_user); |
| 560 | } | 565 | } |
| @@ -590,7 +595,6 @@ static int ipmi_heartbeat(void) | |||
| 590 | struct kernel_ipmi_msg msg; | 595 | struct kernel_ipmi_msg msg; |
| 591 | int rv; | 596 | int rv; |
| 592 | struct ipmi_system_interface_addr addr; | 597 | struct ipmi_system_interface_addr addr; |
| 593 | int timeout_retries = 0; | ||
| 594 | 598 | ||
| 595 | if (ipmi_ignore_heartbeat) | 599 | if (ipmi_ignore_heartbeat) |
| 596 | return 0; | 600 | return 0; |
| @@ -611,7 +615,6 @@ static int ipmi_heartbeat(void) | |||
| 611 | 615 | ||
| 612 | mutex_lock(&heartbeat_lock); | 616 | mutex_lock(&heartbeat_lock); |
| 613 | 617 | ||
| 614 | restart: | ||
| 615 | atomic_set(&heartbeat_tofree, 2); | 618 | atomic_set(&heartbeat_tofree, 2); |
| 616 | 619 | ||
| 617 | /* | 620 | /* |
| @@ -649,33 +652,7 @@ restart: | |||
| 649 | /* Wait for the heartbeat to be sent. */ | 652 | /* Wait for the heartbeat to be sent. */ |
| 650 | wait_for_completion(&heartbeat_wait); | 653 | wait_for_completion(&heartbeat_wait); |
| 651 | 654 | ||
| 652 | if (heartbeat_recv_msg.msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP) { | 655 | if (heartbeat_recv_msg.msg.data[0] != 0) { |
| 653 | timeout_retries++; | ||
| 654 | if (timeout_retries > 3) { | ||
| 655 | printk(KERN_ERR PFX ": Unable to restore the IPMI" | ||
| 656 | " watchdog's settings, giving up.\n"); | ||
| 657 | rv = -EIO; | ||
| 658 | goto out_unlock; | ||
| 659 | } | ||
| 660 | |||
| 661 | /* | ||
| 662 | * The timer was not initialized, that means the BMC was | ||
| 663 | * probably reset and lost the watchdog information. Attempt | ||
| 664 | * to restore the timer's info. Note that we still hold | ||
| 665 | * the heartbeat lock, to keep a heartbeat from happening | ||
| 666 | * in this process, so must say no heartbeat to avoid a | ||
| 667 | * deadlock on this mutex. | ||
| 668 | */ | ||
| 669 | rv = ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); | ||
| 670 | if (rv) { | ||
| 671 | printk(KERN_ERR PFX ": Unable to send the command to" | ||
| 672 | " set the watchdog's settings, giving up.\n"); | ||
| 673 | goto out_unlock; | ||
| 674 | } | ||
| 675 | |||
| 676 | /* We might need a new heartbeat, so do it now */ | ||
| 677 | goto restart; | ||
| 678 | } else if (heartbeat_recv_msg.msg.data[0] != 0) { | ||
| 679 | /* | 656 | /* |
| 680 | * Got an error in the heartbeat response. It was already | 657 | * Got an error in the heartbeat response. It was already |
| 681 | * reported in ipmi_wdog_msg_handler, but we should return | 658 | * reported in ipmi_wdog_msg_handler, but we should return |
| @@ -684,7 +661,6 @@ restart: | |||
| 684 | rv = -EINVAL; | 661 | rv = -EINVAL; |
| 685 | } | 662 | } |
| 686 | 663 | ||
| 687 | out_unlock: | ||
| 688 | mutex_unlock(&heartbeat_lock); | 664 | mutex_unlock(&heartbeat_lock); |
| 689 | 665 | ||
| 690 | return rv; | 666 | return rv; |
| @@ -721,6 +697,7 @@ static int ipmi_ioctl(struct file *file, | |||
| 721 | return -EFAULT; | 697 | return -EFAULT; |
| 722 | return 0; | 698 | return 0; |
| 723 | 699 | ||
| 700 | case WDIOC_SET_PRETIMEOUT: | ||
| 724 | case WDIOC_SETPRETIMEOUT: | 701 | case WDIOC_SETPRETIMEOUT: |
| 725 | i = copy_from_user(&val, argp, sizeof(int)); | 702 | i = copy_from_user(&val, argp, sizeof(int)); |
| 726 | if (i) | 703 | if (i) |
| @@ -728,6 +705,7 @@ static int ipmi_ioctl(struct file *file, | |||
| 728 | pretimeout = val; | 705 | pretimeout = val; |
| 729 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); | 706 | return ipmi_set_timeout(IPMI_SET_TIMEOUT_HB_IF_NECESSARY); |
| 730 | 707 | ||
| 708 | case WDIOC_GET_PRETIMEOUT: | ||
| 731 | case WDIOC_GETPRETIMEOUT: | 709 | case WDIOC_GETPRETIMEOUT: |
| 732 | i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); | 710 | i = copy_to_user(argp, &pretimeout, sizeof(pretimeout)); |
| 733 | if (i) | 711 | if (i) |
| @@ -943,15 +921,11 @@ static struct miscdevice ipmi_wdog_miscdev = { | |||
| 943 | static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, | 921 | static void ipmi_wdog_msg_handler(struct ipmi_recv_msg *msg, |
| 944 | void *handler_data) | 922 | void *handler_data) |
| 945 | { | 923 | { |
| 946 | if (msg->msg.cmd == IPMI_WDOG_RESET_TIMER && | 924 | if (msg->msg.data[0] != 0) { |
| 947 | msg->msg.data[0] == IPMI_WDOG_TIMER_NOT_INIT_RESP) | ||
| 948 | printk(KERN_INFO PFX "response: The IPMI controller appears" | ||
| 949 | " to have been reset, will attempt to reinitialize" | ||
| 950 | " the watchdog timer\n"); | ||
| 951 | else if (msg->msg.data[0] != 0) | ||
| 952 | printk(KERN_ERR PFX "response: Error %x on cmd %x\n", | 925 | printk(KERN_ERR PFX "response: Error %x on cmd %x\n", |
| 953 | msg->msg.data[0], | 926 | msg->msg.data[0], |
| 954 | msg->msg.cmd); | 927 | msg->msg.cmd); |
| 928 | } | ||
| 955 | 929 | ||
| 956 | ipmi_free_recv_msg(msg); | 930 | ipmi_free_recv_msg(msg); |
| 957 | } | 931 | } |
| @@ -1103,8 +1077,17 @@ static void ipmi_unregister_watchdog(int ipmi_intf) | |||
| 1103 | 1077 | ||
| 1104 | #ifdef HAVE_DIE_NMI | 1078 | #ifdef HAVE_DIE_NMI |
| 1105 | static int | 1079 | static int |
| 1106 | ipmi_nmi(unsigned int val, struct pt_regs *regs) | 1080 | ipmi_nmi(struct notifier_block *self, unsigned long val, void *data) |
| 1107 | { | 1081 | { |
| 1082 | struct die_args *args = data; | ||
| 1083 | |||
| 1084 | if (val != DIE_NMIUNKNOWN) | ||
| 1085 | return NOTIFY_OK; | ||
| 1086 | |||
| 1087 | /* Hack, if it's a memory or I/O error, ignore it. */ | ||
| 1088 | if (args->err & 0xc0) | ||
| 1089 | return NOTIFY_OK; | ||
| 1090 | |||
| 1108 | /* | 1091 | /* |
| 1109 | * If we get here, it's an NMI that's not a memory or I/O | 1092 | * If we get here, it's an NMI that's not a memory or I/O |
| 1110 | * error. We can't truly tell if it's from IPMI or not | 1093 | * error. We can't truly tell if it's from IPMI or not |
| @@ -1114,15 +1097,15 @@ ipmi_nmi(unsigned int val, struct pt_regs *regs) | |||
| 1114 | 1097 | ||
| 1115 | if (testing_nmi) { | 1098 | if (testing_nmi) { |
| 1116 | testing_nmi = 2; | 1099 | testing_nmi = 2; |
| 1117 | return NMI_HANDLED; | 1100 | return NOTIFY_STOP; |
| 1118 | } | 1101 | } |
| 1119 | 1102 | ||
| 1120 | /* If we are not expecting a timeout, ignore it. */ | 1103 | /* If we are not expecting a timeout, ignore it. */ |
| 1121 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) | 1104 | if (ipmi_watchdog_state == WDOG_TIMEOUT_NONE) |
| 1122 | return NMI_DONE; | 1105 | return NOTIFY_OK; |
| 1123 | 1106 | ||
| 1124 | if (preaction_val != WDOG_PRETIMEOUT_NMI) | 1107 | if (preaction_val != WDOG_PRETIMEOUT_NMI) |
| 1125 | return NMI_DONE; | 1108 | return NOTIFY_OK; |
| 1126 | 1109 | ||
| 1127 | /* | 1110 | /* |
| 1128 | * If no one else handled the NMI, we assume it was the IPMI | 1111 | * If no one else handled the NMI, we assume it was the IPMI |
| @@ -1137,8 +1120,12 @@ ipmi_nmi(unsigned int val, struct pt_regs *regs) | |||
| 1137 | panic(PFX "pre-timeout"); | 1120 | panic(PFX "pre-timeout"); |
| 1138 | } | 1121 | } |
| 1139 | 1122 | ||
| 1140 | return NMI_HANDLED; | 1123 | return NOTIFY_STOP; |
| 1141 | } | 1124 | } |
| 1125 | |||
| 1126 | static struct notifier_block ipmi_nmi_handler = { | ||
| 1127 | .notifier_call = ipmi_nmi | ||
| 1128 | }; | ||
| 1142 | #endif | 1129 | #endif |
| 1143 | 1130 | ||
| 1144 | static int wdog_reboot_handler(struct notifier_block *this, | 1131 | static int wdog_reboot_handler(struct notifier_block *this, |
| @@ -1154,7 +1141,7 @@ static int wdog_reboot_handler(struct notifier_block *this, | |||
| 1154 | if (code == SYS_POWER_OFF || code == SYS_HALT) { | 1141 | if (code == SYS_POWER_OFF || code == SYS_HALT) { |
| 1155 | /* Disable the WDT if we are shutting down. */ | 1142 | /* Disable the WDT if we are shutting down. */ |
| 1156 | ipmi_watchdog_state = WDOG_TIMEOUT_NONE; | 1143 | ipmi_watchdog_state = WDOG_TIMEOUT_NONE; |
| 1157 | ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); | 1144 | panic_halt_ipmi_set_timeout(); |
| 1158 | } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { | 1145 | } else if (ipmi_watchdog_state != WDOG_TIMEOUT_NONE) { |
| 1159 | /* Set a long timer to let the reboot happens, but | 1146 | /* Set a long timer to let the reboot happens, but |
| 1160 | reboot if it hangs, but only if the watchdog | 1147 | reboot if it hangs, but only if the watchdog |
| @@ -1162,7 +1149,7 @@ static int wdog_reboot_handler(struct notifier_block *this, | |||
| 1162 | timeout = 120; | 1149 | timeout = 120; |
| 1163 | pretimeout = 0; | 1150 | pretimeout = 0; |
| 1164 | ipmi_watchdog_state = WDOG_TIMEOUT_RESET; | 1151 | ipmi_watchdog_state = WDOG_TIMEOUT_RESET; |
| 1165 | ipmi_set_timeout(IPMI_SET_TIMEOUT_NO_HB); | 1152 | panic_halt_ipmi_set_timeout(); |
| 1166 | } | 1153 | } |
| 1167 | } | 1154 | } |
| 1168 | return NOTIFY_OK; | 1155 | return NOTIFY_OK; |
| @@ -1303,8 +1290,7 @@ static void check_parms(void) | |||
| 1303 | } | 1290 | } |
| 1304 | } | 1291 | } |
| 1305 | if (do_nmi && !nmi_handler_registered) { | 1292 | if (do_nmi && !nmi_handler_registered) { |
| 1306 | rv = register_nmi_handler(NMI_UNKNOWN, ipmi_nmi, 0, | 1293 | rv = register_die_notifier(&ipmi_nmi_handler); |
| 1307 | "ipmi"); | ||
| 1308 | if (rv) { | 1294 | if (rv) { |
| 1309 | printk(KERN_WARNING PFX | 1295 | printk(KERN_WARNING PFX |
| 1310 | "Can't register nmi handler\n"); | 1296 | "Can't register nmi handler\n"); |
| @@ -1312,7 +1298,7 @@ static void check_parms(void) | |||
| 1312 | } else | 1298 | } else |
| 1313 | nmi_handler_registered = 1; | 1299 | nmi_handler_registered = 1; |
| 1314 | } else if (!do_nmi && nmi_handler_registered) { | 1300 | } else if (!do_nmi && nmi_handler_registered) { |
| 1315 | unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); | 1301 | unregister_die_notifier(&ipmi_nmi_handler); |
| 1316 | nmi_handler_registered = 0; | 1302 | nmi_handler_registered = 0; |
| 1317 | } | 1303 | } |
| 1318 | #endif | 1304 | #endif |
| @@ -1350,7 +1336,7 @@ static int __init ipmi_wdog_init(void) | |||
| 1350 | if (rv) { | 1336 | if (rv) { |
| 1351 | #ifdef HAVE_DIE_NMI | 1337 | #ifdef HAVE_DIE_NMI |
| 1352 | if (nmi_handler_registered) | 1338 | if (nmi_handler_registered) |
| 1353 | unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); | 1339 | unregister_die_notifier(&ipmi_nmi_handler); |
| 1354 | #endif | 1340 | #endif |
| 1355 | atomic_notifier_chain_unregister(&panic_notifier_list, | 1341 | atomic_notifier_chain_unregister(&panic_notifier_list, |
| 1356 | &wdog_panic_notifier); | 1342 | &wdog_panic_notifier); |
| @@ -1371,7 +1357,7 @@ static void __exit ipmi_wdog_exit(void) | |||
| 1371 | 1357 | ||
| 1372 | #ifdef HAVE_DIE_NMI | 1358 | #ifdef HAVE_DIE_NMI |
| 1373 | if (nmi_handler_registered) | 1359 | if (nmi_handler_registered) |
| 1374 | unregister_nmi_handler(NMI_UNKNOWN, "ipmi"); | 1360 | unregister_die_notifier(&ipmi_nmi_handler); |
| 1375 | #endif | 1361 | #endif |
| 1376 | 1362 | ||
| 1377 | atomic_notifier_chain_unregister(&panic_notifier_list, | 1363 | atomic_notifier_chain_unregister(&panic_notifier_list, |
diff --git a/drivers/char/lp.c b/drivers/char/lp.c index a741e418b45..97c3edb95ae 100644 --- a/drivers/char/lp.c +++ b/drivers/char/lp.c | |||
| @@ -135,6 +135,7 @@ | |||
| 135 | 135 | ||
| 136 | #include <asm/irq.h> | 136 | #include <asm/irq.h> |
| 137 | #include <asm/uaccess.h> | 137 | #include <asm/uaccess.h> |
| 138 | #include <asm/system.h> | ||
| 138 | 139 | ||
| 139 | /* if you have more than 8 printers, remember to increase LP_NO */ | 140 | /* if you have more than 8 printers, remember to increase LP_NO */ |
| 140 | #define LP_NO 8 | 141 | #define LP_NO 8 |
| @@ -705,13 +706,16 @@ static long lp_compat_ioctl(struct file *file, unsigned int cmd, | |||
| 705 | { | 706 | { |
| 706 | unsigned int minor; | 707 | unsigned int minor; |
| 707 | struct timeval par_timeout; | 708 | struct timeval par_timeout; |
| 709 | struct compat_timeval __user *tc; | ||
| 708 | int ret; | 710 | int ret; |
| 709 | 711 | ||
| 710 | minor = iminor(file->f_path.dentry->d_inode); | 712 | minor = iminor(file->f_path.dentry->d_inode); |
| 711 | mutex_lock(&lp_mutex); | 713 | mutex_lock(&lp_mutex); |
| 712 | switch (cmd) { | 714 | switch (cmd) { |
| 713 | case LPSETTIMEOUT: | 715 | case LPSETTIMEOUT: |
| 714 | if (compat_get_timeval(&par_timeout, compat_ptr(arg))) { | 716 | tc = compat_ptr(arg); |
| 717 | if (get_user(par_timeout.tv_sec, &tc->tv_sec) || | ||
| 718 | get_user(par_timeout.tv_usec, &tc->tv_usec)) { | ||
| 715 | ret = -EFAULT; | 719 | ret = -EFAULT; |
| 716 | break; | 720 | break; |
| 717 | } | 721 | } |
| @@ -825,7 +829,7 @@ static struct console lpcons = { | |||
| 825 | 829 | ||
| 826 | static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC }; | 830 | static int parport_nr[LP_NO] = { [0 ... LP_NO-1] = LP_PARPORT_UNSPEC }; |
| 827 | static char *parport[LP_NO]; | 831 | static char *parport[LP_NO]; |
| 828 | static bool reset; | 832 | static int reset; |
| 829 | 833 | ||
| 830 | module_param_array(parport, charp, NULL, 0); | 834 | module_param_array(parport, charp, NULL, 0); |
| 831 | module_param(reset, bool, 0); | 835 | module_param(reset, bool, 0); |
diff --git a/drivers/char/mbcs.c b/drivers/char/mbcs.c index e5d3e3f7a49..1aeaaba680d 100644 --- a/drivers/char/mbcs.c +++ b/drivers/char/mbcs.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <asm/io.h> | 29 | #include <asm/io.h> |
| 30 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
| 31 | #include <asm/system.h> | ||
| 31 | #include <asm/pgtable.h> | 32 | #include <asm/pgtable.h> |
| 32 | #include <asm/sn/addrs.h> | 33 | #include <asm/sn/addrs.h> |
| 33 | #include <asm/sn/intr.h> | 34 | #include <asm/sn/intr.h> |
| @@ -507,7 +508,7 @@ static int mbcs_gscr_mmap(struct file *fp, struct vm_area_struct *vma) | |||
| 507 | 508 | ||
| 508 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 509 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 509 | 510 | ||
| 510 | /* Remap-pfn-range will mark the range VM_IO */ | 511 | /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ |
| 511 | if (remap_pfn_range(vma, | 512 | if (remap_pfn_range(vma, |
| 512 | vma->vm_start, | 513 | vma->vm_start, |
| 513 | __pa(soft->gscr_addr) >> PAGE_SHIFT, | 514 | __pa(soft->gscr_addr) >> PAGE_SHIFT, |
| @@ -799,7 +800,7 @@ static int mbcs_remove(struct cx_dev *dev) | |||
| 799 | return 0; | 800 | return 0; |
| 800 | } | 801 | } |
| 801 | 802 | ||
| 802 | static const struct cx_device_id mbcs_id_table[] = { | 803 | static const struct cx_device_id __devinitdata mbcs_id_table[] = { |
| 803 | { | 804 | { |
| 804 | .part_num = MBCS_PART_NUM, | 805 | .part_num = MBCS_PART_NUM, |
| 805 | .mfg_num = MBCS_MFG_NUM, | 806 | .mfg_num = MBCS_MFG_NUM, |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index c6fa3bc2baa..9b1eb188acd 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -26,17 +26,14 @@ | |||
| 26 | #include <linux/bootmem.h> | 26 | #include <linux/bootmem.h> |
| 27 | #include <linux/splice.h> | 27 | #include <linux/splice.h> |
| 28 | #include <linux/pfn.h> | 28 | #include <linux/pfn.h> |
| 29 | #include <linux/export.h> | ||
| 30 | #include <linux/io.h> | ||
| 31 | 29 | ||
| 32 | #include <asm/uaccess.h> | 30 | #include <asm/uaccess.h> |
| 31 | #include <asm/io.h> | ||
| 33 | 32 | ||
| 34 | #ifdef CONFIG_IA64 | 33 | #ifdef CONFIG_IA64 |
| 35 | # include <linux/efi.h> | 34 | # include <linux/efi.h> |
| 36 | #endif | 35 | #endif |
| 37 | 36 | ||
| 38 | #define DEVPORT_MINOR 4 | ||
| 39 | |||
| 40 | static inline unsigned long size_inside_page(unsigned long start, | 37 | static inline unsigned long size_inside_page(unsigned long start, |
| 41 | unsigned long size) | 38 | unsigned long size) |
| 42 | { | 39 | { |
| @@ -48,7 +45,7 @@ static inline unsigned long size_inside_page(unsigned long start, | |||
| 48 | } | 45 | } |
| 49 | 46 | ||
| 50 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE | 47 | #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE |
| 51 | static inline int valid_phys_addr_range(phys_addr_t addr, size_t count) | 48 | static inline int valid_phys_addr_range(unsigned long addr, size_t count) |
| 52 | { | 49 | { |
| 53 | return addr + count <= __pa(high_memory); | 50 | return addr + count <= __pa(high_memory); |
| 54 | } | 51 | } |
| @@ -59,6 +56,7 @@ static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size) | |||
| 59 | } | 56 | } |
| 60 | #endif | 57 | #endif |
| 61 | 58 | ||
| 59 | #if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) | ||
| 62 | #ifdef CONFIG_STRICT_DEVMEM | 60 | #ifdef CONFIG_STRICT_DEVMEM |
| 63 | static inline int range_is_allowed(unsigned long pfn, unsigned long size) | 61 | static inline int range_is_allowed(unsigned long pfn, unsigned long size) |
| 64 | { | 62 | { |
| @@ -84,7 +82,9 @@ static inline int range_is_allowed(unsigned long pfn, unsigned long size) | |||
| 84 | return 1; | 82 | return 1; |
| 85 | } | 83 | } |
| 86 | #endif | 84 | #endif |
| 85 | #endif | ||
| 87 | 86 | ||
| 87 | #ifdef CONFIG_DEVMEM | ||
| 88 | void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) | 88 | void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) |
| 89 | { | 89 | { |
| 90 | } | 90 | } |
| @@ -96,7 +96,7 @@ void __weak unxlate_dev_mem_ptr(unsigned long phys, void *addr) | |||
| 96 | static ssize_t read_mem(struct file *file, char __user *buf, | 96 | static ssize_t read_mem(struct file *file, char __user *buf, |
| 97 | size_t count, loff_t *ppos) | 97 | size_t count, loff_t *ppos) |
| 98 | { | 98 | { |
| 99 | phys_addr_t p = *ppos; | 99 | unsigned long p = *ppos; |
| 100 | ssize_t read, sz; | 100 | ssize_t read, sz; |
| 101 | char *ptr; | 101 | char *ptr; |
| 102 | 102 | ||
| @@ -153,7 +153,7 @@ static ssize_t read_mem(struct file *file, char __user *buf, | |||
| 153 | static ssize_t write_mem(struct file *file, const char __user *buf, | 153 | static ssize_t write_mem(struct file *file, const char __user *buf, |
| 154 | size_t count, loff_t *ppos) | 154 | size_t count, loff_t *ppos) |
| 155 | { | 155 | { |
| 156 | phys_addr_t p = *ppos; | 156 | unsigned long p = *ppos; |
| 157 | ssize_t written, sz; | 157 | ssize_t written, sz; |
| 158 | unsigned long copied; | 158 | unsigned long copied; |
| 159 | void *ptr; | 159 | void *ptr; |
| @@ -211,6 +211,9 @@ static ssize_t write_mem(struct file *file, const char __user *buf, | |||
| 211 | *ppos += written; | 211 | *ppos += written; |
| 212 | return written; | 212 | return written; |
| 213 | } | 213 | } |
| 214 | #endif /* CONFIG_DEVMEM */ | ||
| 215 | |||
| 216 | #if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) | ||
| 214 | 217 | ||
| 215 | int __weak phys_mem_access_prot_allowed(struct file *file, | 218 | int __weak phys_mem_access_prot_allowed(struct file *file, |
| 216 | unsigned long pfn, unsigned long size, pgprot_t *vma_prot) | 219 | unsigned long pfn, unsigned long size, pgprot_t *vma_prot) |
| @@ -226,7 +229,7 @@ int __weak phys_mem_access_prot_allowed(struct file *file, | |||
| 226 | * | 229 | * |
| 227 | */ | 230 | */ |
| 228 | #ifdef pgprot_noncached | 231 | #ifdef pgprot_noncached |
| 229 | static int uncached_access(struct file *file, phys_addr_t addr) | 232 | static int uncached_access(struct file *file, unsigned long addr) |
| 230 | { | 233 | { |
| 231 | #if defined(CONFIG_IA64) | 234 | #if defined(CONFIG_IA64) |
| 232 | /* | 235 | /* |
| @@ -258,7 +261,7 @@ static pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn, | |||
| 258 | unsigned long size, pgprot_t vma_prot) | 261 | unsigned long size, pgprot_t vma_prot) |
| 259 | { | 262 | { |
| 260 | #ifdef pgprot_noncached | 263 | #ifdef pgprot_noncached |
| 261 | phys_addr_t offset = pfn << PAGE_SHIFT; | 264 | unsigned long offset = pfn << PAGE_SHIFT; |
| 262 | 265 | ||
| 263 | if (uncached_access(file, offset)) | 266 | if (uncached_access(file, offset)) |
| 264 | return pgprot_noncached(vma_prot); | 267 | return pgprot_noncached(vma_prot); |
| @@ -322,7 +325,7 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) | |||
| 322 | 325 | ||
| 323 | vma->vm_ops = &mmap_mem_ops; | 326 | vma->vm_ops = &mmap_mem_ops; |
| 324 | 327 | ||
| 325 | /* Remap-pfn-range will mark the range VM_IO */ | 328 | /* Remap-pfn-range will mark the range VM_IO and VM_RESERVED */ |
| 326 | if (remap_pfn_range(vma, | 329 | if (remap_pfn_range(vma, |
| 327 | vma->vm_start, | 330 | vma->vm_start, |
| 328 | vma->vm_pgoff, | 331 | vma->vm_pgoff, |
| @@ -332,6 +335,7 @@ static int mmap_mem(struct file *file, struct vm_area_struct *vma) | |||
| 332 | } | 335 | } |
| 333 | return 0; | 336 | return 0; |
| 334 | } | 337 | } |
| 338 | #endif /* CONFIG_DEVMEM */ | ||
| 335 | 339 | ||
| 336 | #ifdef CONFIG_DEVKMEM | 340 | #ifdef CONFIG_DEVKMEM |
| 337 | static int mmap_kmem(struct file *file, struct vm_area_struct *vma) | 341 | static int mmap_kmem(struct file *file, struct vm_area_struct *vma) |
| @@ -696,6 +700,8 @@ static loff_t null_lseek(struct file *file, loff_t offset, int orig) | |||
| 696 | return file->f_pos = 0; | 700 | return file->f_pos = 0; |
| 697 | } | 701 | } |
| 698 | 702 | ||
| 703 | #if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) || defined(CONFIG_DEVPORT) | ||
| 704 | |||
| 699 | /* | 705 | /* |
| 700 | * The memory devices use the full 32/64 bits of the offset, and so we cannot | 706 | * The memory devices use the full 32/64 bits of the offset, and so we cannot |
| 701 | * check against negative addresses: they are ok. The return value is weird, | 707 | * check against negative addresses: they are ok. The return value is weird, |
| @@ -729,10 +735,14 @@ static loff_t memory_lseek(struct file *file, loff_t offset, int orig) | |||
| 729 | return ret; | 735 | return ret; |
| 730 | } | 736 | } |
| 731 | 737 | ||
| 738 | #endif | ||
| 739 | |||
| 740 | #if defined(CONFIG_DEVMEM) || defined(CONFIG_DEVKMEM) || defined(CONFIG_DEVPORT) | ||
| 732 | static int open_port(struct inode * inode, struct file * filp) | 741 | static int open_port(struct inode * inode, struct file * filp) |
| 733 | { | 742 | { |
| 734 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; | 743 | return capable(CAP_SYS_RAWIO) ? 0 : -EPERM; |
| 735 | } | 744 | } |
| 745 | #endif | ||
| 736 | 746 | ||
| 737 | #define zero_lseek null_lseek | 747 | #define zero_lseek null_lseek |
| 738 | #define full_lseek null_lseek | 748 | #define full_lseek null_lseek |
| @@ -742,6 +752,7 @@ static int open_port(struct inode * inode, struct file * filp) | |||
| 742 | #define open_kmem open_mem | 752 | #define open_kmem open_mem |
| 743 | #define open_oldmem open_mem | 753 | #define open_oldmem open_mem |
| 744 | 754 | ||
| 755 | #ifdef CONFIG_DEVMEM | ||
| 745 | static const struct file_operations mem_fops = { | 756 | static const struct file_operations mem_fops = { |
| 746 | .llseek = memory_lseek, | 757 | .llseek = memory_lseek, |
| 747 | .read = read_mem, | 758 | .read = read_mem, |
| @@ -750,6 +761,7 @@ static const struct file_operations mem_fops = { | |||
| 750 | .open = open_mem, | 761 | .open = open_mem, |
| 751 | .get_unmapped_area = get_unmapped_area_mem, | 762 | .get_unmapped_area = get_unmapped_area_mem, |
| 752 | }; | 763 | }; |
| 764 | #endif | ||
| 753 | 765 | ||
| 754 | #ifdef CONFIG_DEVKMEM | 766 | #ifdef CONFIG_DEVKMEM |
| 755 | static const struct file_operations kmem_fops = { | 767 | static const struct file_operations kmem_fops = { |
| @@ -809,13 +821,53 @@ static const struct file_operations oldmem_fops = { | |||
| 809 | }; | 821 | }; |
| 810 | #endif | 822 | #endif |
| 811 | 823 | ||
| 824 | static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv, | ||
| 825 | unsigned long count, loff_t pos) | ||
| 826 | { | ||
| 827 | char *line, *p; | ||
| 828 | int i; | ||
| 829 | ssize_t ret = -EFAULT; | ||
| 830 | size_t len = iov_length(iv, count); | ||
| 831 | |||
| 832 | line = kmalloc(len + 1, GFP_KERNEL); | ||
| 833 | if (line == NULL) | ||
| 834 | return -ENOMEM; | ||
| 835 | |||
| 836 | /* | ||
| 837 | * copy all vectors into a single string, to ensure we do | ||
| 838 | * not interleave our log line with other printk calls | ||
| 839 | */ | ||
| 840 | p = line; | ||
| 841 | for (i = 0; i < count; i++) { | ||
| 842 | if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len)) | ||
| 843 | goto out; | ||
| 844 | p += iv[i].iov_len; | ||
| 845 | } | ||
| 846 | p[0] = '\0'; | ||
| 847 | |||
| 848 | ret = printk("%s", line); | ||
| 849 | /* printk can add a prefix */ | ||
| 850 | if (ret > len) | ||
| 851 | ret = len; | ||
| 852 | out: | ||
| 853 | kfree(line); | ||
| 854 | return ret; | ||
| 855 | } | ||
| 856 | |||
| 857 | static const struct file_operations kmsg_fops = { | ||
| 858 | .aio_write = kmsg_writev, | ||
| 859 | .llseek = noop_llseek, | ||
| 860 | }; | ||
| 861 | |||
| 812 | static const struct memdev { | 862 | static const struct memdev { |
| 813 | const char *name; | 863 | const char *name; |
| 814 | umode_t mode; | 864 | mode_t mode; |
| 815 | const struct file_operations *fops; | 865 | const struct file_operations *fops; |
| 816 | struct backing_dev_info *dev_info; | 866 | struct backing_dev_info *dev_info; |
| 817 | } devlist[] = { | 867 | } devlist[] = { |
| 868 | #ifdef CONFIG_DEVMEM | ||
| 818 | [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi }, | 869 | [1] = { "mem", 0, &mem_fops, &directly_mappable_cdev_bdi }, |
| 870 | #endif | ||
| 819 | #ifdef CONFIG_DEVKMEM | 871 | #ifdef CONFIG_DEVKMEM |
| 820 | [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi }, | 872 | [2] = { "kmem", 0, &kmem_fops, &directly_mappable_cdev_bdi }, |
| 821 | #endif | 873 | #endif |
| @@ -827,9 +879,7 @@ static const struct memdev { | |||
| 827 | [7] = { "full", 0666, &full_fops, NULL }, | 879 | [7] = { "full", 0666, &full_fops, NULL }, |
| 828 | [8] = { "random", 0666, &random_fops, NULL }, | 880 | [8] = { "random", 0666, &random_fops, NULL }, |
| 829 | [9] = { "urandom", 0666, &urandom_fops, NULL }, | 881 | [9] = { "urandom", 0666, &urandom_fops, NULL }, |
| 830 | #ifdef CONFIG_PRINTK | 882 | [11] = { "kmsg", 0, &kmsg_fops, NULL }, |
| 831 | [11] = { "kmsg", 0644, &kmsg_fops, NULL }, | ||
| 832 | #endif | ||
| 833 | #ifdef CONFIG_CRASH_DUMP | 883 | #ifdef CONFIG_CRASH_DUMP |
| 834 | [12] = { "oldmem", 0, &oldmem_fops, NULL }, | 884 | [12] = { "oldmem", 0, &oldmem_fops, NULL }, |
| 835 | #endif | 885 | #endif |
| @@ -867,7 +917,7 @@ static const struct file_operations memory_fops = { | |||
| 867 | .llseek = noop_llseek, | 917 | .llseek = noop_llseek, |
| 868 | }; | 918 | }; |
| 869 | 919 | ||
| 870 | static char *mem_devnode(struct device *dev, umode_t *mode) | 920 | static char *mem_devnode(struct device *dev, mode_t *mode) |
| 871 | { | 921 | { |
| 872 | if (mode && devlist[MINOR(dev->devt)].mode) | 922 | if (mode && devlist[MINOR(dev->devt)].mode) |
| 873 | *mode = devlist[MINOR(dev->devt)].mode; | 923 | *mode = devlist[MINOR(dev->devt)].mode; |
| @@ -896,13 +946,6 @@ static int __init chr_dev_init(void) | |||
| 896 | for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { | 946 | for (minor = 1; minor < ARRAY_SIZE(devlist); minor++) { |
| 897 | if (!devlist[minor].name) | 947 | if (!devlist[minor].name) |
| 898 | continue; | 948 | continue; |
| 899 | |||
| 900 | /* | ||
| 901 | * Create /dev/port? | ||
| 902 | */ | ||
| 903 | if ((minor == DEVPORT_MINOR) && !arch_has_dev_port()) | ||
| 904 | continue; | ||
| 905 | |||
| 906 | device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor), | 949 | device_create(mem_class, NULL, MKDEV(MEM_MAJOR, minor), |
| 907 | NULL, devlist[minor].name); | 950 | NULL, devlist[minor].name); |
| 908 | } | 951 | } |
diff --git a/drivers/char/misc.c b/drivers/char/misc.c index 522136d4084..778273c9324 100644 --- a/drivers/char/misc.c +++ b/drivers/char/misc.c | |||
| @@ -258,7 +258,7 @@ int misc_deregister(struct miscdevice *misc) | |||
| 258 | EXPORT_SYMBOL(misc_register); | 258 | EXPORT_SYMBOL(misc_register); |
| 259 | EXPORT_SYMBOL(misc_deregister); | 259 | EXPORT_SYMBOL(misc_deregister); |
| 260 | 260 | ||
| 261 | static char *misc_devnode(struct device *dev, umode_t *mode) | 261 | static char *misc_devnode(struct device *dev, mode_t *mode) |
| 262 | { | 262 | { |
| 263 | struct miscdevice *c = dev_get_drvdata(dev); | 263 | struct miscdevice *c = dev_get_drvdata(dev); |
| 264 | 264 | ||
diff --git a/drivers/char/mmtimer.c b/drivers/char/mmtimer.c index 3d6c0671e99..33dc2298af7 100644 --- a/drivers/char/mmtimer.c +++ b/drivers/char/mmtimer.c | |||
| @@ -826,7 +826,7 @@ static int __init mmtimer_init(void) | |||
| 826 | 826 | ||
| 827 | /* Allocate list of node ptrs to mmtimer_t's */ | 827 | /* Allocate list of node ptrs to mmtimer_t's */ |
| 828 | timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL); | 828 | timers = kzalloc(sizeof(struct mmtimer_node)*maxn, GFP_KERNEL); |
| 829 | if (!timers) { | 829 | if (timers == NULL) { |
| 830 | printk(KERN_ERR "%s: failed to allocate memory for device\n", | 830 | printk(KERN_ERR "%s: failed to allocate memory for device\n", |
| 831 | MMTIMER_NAME); | 831 | MMTIMER_NAME); |
| 832 | goto out3; | 832 | goto out3; |
| @@ -848,6 +848,7 @@ static int __init mmtimer_init(void) | |||
| 848 | return 0; | 848 | return 0; |
| 849 | 849 | ||
| 850 | out3: | 850 | out3: |
| 851 | kfree(timers); | ||
| 851 | misc_deregister(&mmtimer_miscdev); | 852 | misc_deregister(&mmtimer_miscdev); |
| 852 | out2: | 853 | out2: |
| 853 | free_irq(SGI_MMTIMER_VECTOR, NULL); | 854 | free_irq(SGI_MMTIMER_VECTOR, NULL); |
diff --git a/drivers/char/mspec.c b/drivers/char/mspec.c index e1f60f968fd..5c0d96a820f 100644 --- a/drivers/char/mspec.c +++ b/drivers/char/mspec.c | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
| 45 | #include <linux/numa.h> | 45 | #include <linux/numa.h> |
| 46 | #include <asm/page.h> | 46 | #include <asm/page.h> |
| 47 | #include <asm/system.h> | ||
| 47 | #include <asm/pgtable.h> | 48 | #include <asm/pgtable.h> |
| 48 | #include <linux/atomic.h> | 49 | #include <linux/atomic.h> |
| 49 | #include <asm/tlbflush.h> | 50 | #include <asm/tlbflush.h> |
| @@ -283,10 +284,10 @@ mspec_mmap(struct file *file, struct vm_area_struct *vma, | |||
| 283 | vdata->flags = flags; | 284 | vdata->flags = flags; |
| 284 | vdata->type = type; | 285 | vdata->type = type; |
| 285 | spin_lock_init(&vdata->lock); | 286 | spin_lock_init(&vdata->lock); |
| 286 | atomic_set(&vdata->refcnt, 1); | 287 | vdata->refcnt = ATOMIC_INIT(1); |
| 287 | vma->vm_private_data = vdata; | 288 | vma->vm_private_data = vdata; |
| 288 | 289 | ||
| 289 | vma->vm_flags |= VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP; | 290 | vma->vm_flags |= (VM_IO | VM_RESERVED | VM_PFNMAP | VM_DONTEXPAND); |
| 290 | if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED) | 291 | if (vdata->type == MSPEC_FETCHOP || vdata->type == MSPEC_UNCACHED) |
| 291 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | 292 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); |
| 292 | vma->vm_ops = &mspec_vm_ops; | 293 | vma->vm_ops = &mspec_vm_ops; |
diff --git a/drivers/char/mwave/3780i.c b/drivers/char/mwave/3780i.c index 881c9e59593..492dbfb2efd 100644 --- a/drivers/char/mwave/3780i.c +++ b/drivers/char/mwave/3780i.c | |||
| @@ -56,6 +56,7 @@ | |||
| 56 | 56 | ||
| 57 | #include <asm/io.h> | 57 | #include <asm/io.h> |
| 58 | #include <asm/uaccess.h> | 58 | #include <asm/uaccess.h> |
| 59 | #include <asm/system.h> | ||
| 59 | #include <asm/irq.h> | 60 | #include <asm/irq.h> |
| 60 | #include "smapi.h" | 61 | #include "smapi.h" |
| 61 | #include "mwavedd.h" | 62 | #include "mwavedd.h" |
diff --git a/drivers/char/mwave/mwavedd.c b/drivers/char/mwave/mwavedd.c index 164544afd68..1d82d5838f0 100644 --- a/drivers/char/mwave/mwavedd.c +++ b/drivers/char/mwave/mwavedd.c | |||
| @@ -430,7 +430,7 @@ static ssize_t mwave_write(struct file *file, const char __user *buf, | |||
| 430 | 430 | ||
| 431 | static int register_serial_portandirq(unsigned int port, int irq) | 431 | static int register_serial_portandirq(unsigned int port, int irq) |
| 432 | { | 432 | { |
| 433 | struct uart_8250_port uart; | 433 | struct uart_port uart; |
| 434 | 434 | ||
| 435 | switch ( port ) { | 435 | switch ( port ) { |
| 436 | case 0x3f8: | 436 | case 0x3f8: |
| @@ -462,14 +462,14 @@ static int register_serial_portandirq(unsigned int port, int irq) | |||
| 462 | } /* switch */ | 462 | } /* switch */ |
| 463 | /* irq is okay */ | 463 | /* irq is okay */ |
| 464 | 464 | ||
| 465 | memset(&uart, 0, sizeof(uart)); | 465 | memset(&uart, 0, sizeof(struct uart_port)); |
| 466 | 466 | ||
| 467 | uart.port.uartclk = 1843200; | 467 | uart.uartclk = 1843200; |
| 468 | uart.port.iobase = port; | 468 | uart.iobase = port; |
| 469 | uart.port.irq = irq; | 469 | uart.irq = irq; |
| 470 | uart.port.iotype = UPIO_PORT; | 470 | uart.iotype = UPIO_PORT; |
| 471 | uart.port.flags = UPF_SHARE_IRQ; | 471 | uart.flags = UPF_SHARE_IRQ; |
| 472 | return serial8250_register_8250_port(&uart); | 472 | return serial8250_register_port(&uart); |
| 473 | } | 473 | } |
| 474 | 474 | ||
| 475 | 475 | ||
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c index 9df78e2cc45..da3cfee782d 100644 --- a/drivers/char/nvram.c +++ b/drivers/char/nvram.c | |||
| @@ -94,7 +94,7 @@ | |||
| 94 | /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with | 94 | /* Note that *all* calls to CMOS_READ and CMOS_WRITE must be done with |
| 95 | * rtc_lock held. Due to the index-port/data-port design of the RTC, we | 95 | * rtc_lock held. Due to the index-port/data-port design of the RTC, we |
| 96 | * don't want two different things trying to get to it at once. (e.g. the | 96 | * don't want two different things trying to get to it at once. (e.g. the |
| 97 | * periodic 11 min sync from kernel/time/ntp.c vs. this driver.) | 97 | * periodic 11 min sync from time.c vs. this driver.) |
| 98 | */ | 98 | */ |
| 99 | 99 | ||
| 100 | #include <linux/types.h> | 100 | #include <linux/types.h> |
| @@ -111,6 +111,7 @@ | |||
| 111 | #include <linux/uaccess.h> | 111 | #include <linux/uaccess.h> |
| 112 | #include <linux/mutex.h> | 112 | #include <linux/mutex.h> |
| 113 | 113 | ||
| 114 | #include <asm/system.h> | ||
| 114 | 115 | ||
| 115 | static DEFINE_MUTEX(nvram_mutex); | 116 | static DEFINE_MUTEX(nvram_mutex); |
| 116 | static DEFINE_SPINLOCK(nvram_state_lock); | 117 | static DEFINE_SPINLOCK(nvram_state_lock); |
diff --git a/drivers/char/nwbutton.c b/drivers/char/nwbutton.c index cfdfe493c6a..04a480f86c6 100644 --- a/drivers/char/nwbutton.c +++ b/drivers/char/nwbutton.c | |||
| @@ -93,9 +93,9 @@ int button_del_callback (void (*callback) (void)) | |||
| 93 | button_callback_list [lp].count = 0; | 93 | button_callback_list [lp].count = 0; |
| 94 | callback_count--; | 94 | callback_count--; |
| 95 | return 0; | 95 | return 0; |
| 96 | } | 96 | }; |
| 97 | lp--; | 97 | lp--; |
| 98 | } | 98 | }; |
| 99 | return -EINVAL; | 99 | return -EINVAL; |
| 100 | } | 100 | } |
| 101 | 101 | ||
diff --git a/drivers/char/nwflash.c b/drivers/char/nwflash.c index e371480d363..a12f52400db 100644 --- a/drivers/char/nwflash.c +++ b/drivers/char/nwflash.c | |||
| @@ -30,7 +30,9 @@ | |||
| 30 | 30 | ||
| 31 | #include <asm/hardware/dec21285.h> | 31 | #include <asm/hardware/dec21285.h> |
| 32 | #include <asm/io.h> | 32 | #include <asm/io.h> |
| 33 | #include <asm/leds.h> | ||
| 33 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
| 35 | #include <asm/system.h> | ||
| 34 | #include <asm/uaccess.h> | 36 | #include <asm/uaccess.h> |
| 35 | 37 | ||
| 36 | /*****************************************************************************/ | 38 | /*****************************************************************************/ |
| @@ -49,7 +51,7 @@ static int write_block(unsigned long p, const char __user *buf, int count); | |||
| 49 | #define KFLASH_ID 0x89A6 //Intel flash | 51 | #define KFLASH_ID 0x89A6 //Intel flash |
| 50 | #define KFLASH_ID4 0xB0D4 //Intel flash 4Meg | 52 | #define KFLASH_ID4 0xB0D4 //Intel flash 4Meg |
| 51 | 53 | ||
| 52 | static bool flashdebug; //if set - we will display progress msgs | 54 | static int flashdebug; //if set - we will display progress msgs |
| 53 | 55 | ||
| 54 | static int gbWriteEnable; | 56 | static int gbWriteEnable; |
| 55 | static int gbWriteBase64Enable; | 57 | static int gbWriteBase64Enable; |
| @@ -178,6 +180,9 @@ static ssize_t flash_write(struct file *file, const char __user *buf, | |||
| 178 | 180 | ||
| 179 | written = 0; | 181 | written = 0; |
| 180 | 182 | ||
| 183 | leds_event(led_claim); | ||
| 184 | leds_event(led_green_on); | ||
| 185 | |||
| 181 | nBlock = (int) p >> 16; //block # of 64K bytes | 186 | nBlock = (int) p >> 16; //block # of 64K bytes |
| 182 | 187 | ||
| 183 | /* | 188 | /* |
| @@ -254,6 +259,11 @@ static ssize_t flash_write(struct file *file, const char __user *buf, | |||
| 254 | printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written); | 259 | printk(KERN_DEBUG "flash_write: written 0x%X bytes OK.\n", written); |
| 255 | } | 260 | } |
| 256 | 261 | ||
| 262 | /* | ||
| 263 | * restore reg on exit | ||
| 264 | */ | ||
| 265 | leds_event(led_release); | ||
| 266 | |||
| 257 | mutex_unlock(&nwflash_mutex); | 267 | mutex_unlock(&nwflash_mutex); |
| 258 | 268 | ||
| 259 | return written; | 269 | return written; |
| @@ -325,6 +335,11 @@ static int erase_block(int nBlock) | |||
| 325 | int temp, temp1; | 335 | int temp, temp1; |
| 326 | 336 | ||
| 327 | /* | 337 | /* |
| 338 | * orange LED == erase | ||
| 339 | */ | ||
| 340 | leds_event(led_amber_on); | ||
| 341 | |||
| 342 | /* | ||
| 328 | * reset footbridge to the correct offset 0 (...0..3) | 343 | * reset footbridge to the correct offset 0 (...0..3) |
| 329 | */ | 344 | */ |
| 330 | *CSR_ROMWRITEREG = 0; | 345 | *CSR_ROMWRITEREG = 0; |
| @@ -432,6 +447,12 @@ static int write_block(unsigned long p, const char __user *buf, int count) | |||
| 432 | unsigned long timeout; | 447 | unsigned long timeout; |
| 433 | unsigned long timeout1; | 448 | unsigned long timeout1; |
| 434 | 449 | ||
| 450 | /* | ||
| 451 | * red LED == write | ||
| 452 | */ | ||
| 453 | leds_event(led_amber_off); | ||
| 454 | leds_event(led_red_on); | ||
| 455 | |||
| 435 | pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p)); | 456 | pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p)); |
| 436 | 457 | ||
| 437 | /* | 458 | /* |
| @@ -538,9 +559,17 @@ static int write_block(unsigned long p, const char __user *buf, int count) | |||
| 538 | pWritePtr - FLASH_BASE); | 559 | pWritePtr - FLASH_BASE); |
| 539 | 560 | ||
| 540 | /* | 561 | /* |
| 562 | * no LED == waiting | ||
| 563 | */ | ||
| 564 | leds_event(led_amber_off); | ||
| 565 | /* | ||
| 541 | * wait couple ms | 566 | * wait couple ms |
| 542 | */ | 567 | */ |
| 543 | msleep(10); | 568 | msleep(10); |
| 569 | /* | ||
| 570 | * red LED == write | ||
| 571 | */ | ||
| 572 | leds_event(led_red_on); | ||
| 544 | 573 | ||
| 545 | goto WriteRetry; | 574 | goto WriteRetry; |
| 546 | } else { | 575 | } else { |
| @@ -555,6 +584,12 @@ static int write_block(unsigned long p, const char __user *buf, int count) | |||
| 555 | } | 584 | } |
| 556 | } | 585 | } |
| 557 | 586 | ||
| 587 | /* | ||
| 588 | * green LED == read/verify | ||
| 589 | */ | ||
| 590 | leds_event(led_amber_off); | ||
| 591 | leds_event(led_green_on); | ||
| 592 | |||
| 558 | msleep(10); | 593 | msleep(10); |
| 559 | 594 | ||
| 560 | pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p)); | 595 | pWritePtr = (unsigned char *) ((unsigned int) (FLASH_BASE + p)); |
| @@ -583,9 +618,9 @@ static void kick_open(void) | |||
| 583 | * we want to write a bit pattern XXX1 to Xilinx to enable | 618 | * we want to write a bit pattern XXX1 to Xilinx to enable |
| 584 | * the write gate, which will be open for about the next 2ms. | 619 | * the write gate, which will be open for about the next 2ms. |
| 585 | */ | 620 | */ |
| 586 | raw_spin_lock_irqsave(&nw_gpio_lock, flags); | 621 | spin_lock_irqsave(&nw_gpio_lock, flags); |
| 587 | nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); | 622 | nw_cpld_modify(CPLD_FLASH_WR_ENABLE, CPLD_FLASH_WR_ENABLE); |
| 588 | raw_spin_unlock_irqrestore(&nw_gpio_lock, flags); | 623 | spin_unlock_irqrestore(&nw_gpio_lock, flags); |
| 589 | 624 | ||
| 590 | /* | 625 | /* |
| 591 | * let the ISA bus to catch on... | 626 | * let the ISA bus to catch on... |
diff --git a/drivers/char/pc8736x_gpio.c b/drivers/char/pc8736x_gpio.c index 3f79a9fb6b1..b304ec05250 100644 --- a/drivers/char/pc8736x_gpio.c +++ b/drivers/char/pc8736x_gpio.c | |||
| @@ -345,7 +345,8 @@ static void __exit pc8736x_gpio_cleanup(void) | |||
| 345 | unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT); | 345 | unregister_chrdev_region(MKDEV(major,0), PC8736X_GPIO_CT); |
| 346 | release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE); | 346 | release_region(pc8736x_gpio_base, PC8736X_GPIO_RANGE); |
| 347 | 347 | ||
| 348 | platform_device_unregister(pdev); | 348 | platform_device_del(pdev); |
| 349 | platform_device_put(pdev); | ||
| 349 | } | 350 | } |
| 350 | 351 | ||
| 351 | module_init(pc8736x_gpio_init); | 352 | module_init(pc8736x_gpio_init); |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index b66eaa04f8c..15781396af2 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | #include <linux/ioctl.h> | 60 | #include <linux/ioctl.h> |
| 61 | #include <linux/synclink.h> | 61 | #include <linux/synclink.h> |
| 62 | 62 | ||
| 63 | #include <asm/system.h> | ||
| 63 | #include <asm/io.h> | 64 | #include <asm/io.h> |
| 64 | #include <asm/irq.h> | 65 | #include <asm/irq.h> |
| 65 | #include <asm/dma.h> | 66 | #include <asm/dma.h> |
| @@ -438,7 +439,7 @@ static int mgslpc_device_count = 0; | |||
| 438 | * .text section address and breakpoint on module load. | 439 | * .text section address and breakpoint on module load. |
| 439 | * This is useful for use with gdb and add-symbol-file command. | 440 | * This is useful for use with gdb and add-symbol-file command. |
| 440 | */ | 441 | */ |
| 441 | static bool break_on_load=0; | 442 | static int break_on_load=0; |
| 442 | 443 | ||
| 443 | /* | 444 | /* |
| 444 | * Driver major number, defaults to zero to get auto | 445 | * Driver major number, defaults to zero to get auto |
| @@ -549,10 +550,8 @@ static int mgslpc_probe(struct pcmcia_device *link) | |||
| 549 | /* Initialize the struct pcmcia_device structure */ | 550 | /* Initialize the struct pcmcia_device structure */ |
| 550 | 551 | ||
| 551 | ret = mgslpc_config(link); | 552 | ret = mgslpc_config(link); |
| 552 | if (ret) { | 553 | if (ret) |
| 553 | tty_port_destroy(&info->port); | ||
| 554 | return ret; | 554 | return ret; |
| 555 | } | ||
| 556 | 555 | ||
| 557 | mgslpc_add_device(info); | 556 | mgslpc_add_device(info); |
| 558 | 557 | ||
| @@ -893,14 +892,6 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty) | |||
| 893 | int work = 0; | 892 | int work = 0; |
| 894 | struct mgsl_icount *icount = &info->icount; | 893 | struct mgsl_icount *icount = &info->icount; |
| 895 | 894 | ||
| 896 | if (!tty) { | ||
| 897 | /* tty is not available anymore */ | ||
| 898 | issue_command(info, CHA, CMD_RXRESET); | ||
| 899 | if (debug_level >= DEBUG_LEVEL_ISR) | ||
| 900 | printk("%s(%d):rx_ready_async(tty=NULL)\n",__FILE__,__LINE__); | ||
| 901 | return; | ||
| 902 | } | ||
| 903 | |||
| 904 | if (tcd) { | 895 | if (tcd) { |
| 905 | /* early termination, get FIFO count from RBCL register */ | 896 | /* early termination, get FIFO count from RBCL register */ |
| 906 | fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f); | 897 | fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f); |
| @@ -990,7 +981,7 @@ static void tx_done(MGSLPC_INFO *info, struct tty_struct *tty) | |||
| 990 | else | 981 | else |
| 991 | #endif | 982 | #endif |
| 992 | { | 983 | { |
| 993 | if (tty && (tty->stopped || tty->hw_stopped)) { | 984 | if (tty->stopped || tty->hw_stopped) { |
| 994 | tx_stop(info); | 985 | tx_stop(info); |
| 995 | return; | 986 | return; |
| 996 | } | 987 | } |
| @@ -1010,7 +1001,7 @@ static void tx_ready(MGSLPC_INFO *info, struct tty_struct *tty) | |||
| 1010 | if (!info->tx_active) | 1001 | if (!info->tx_active) |
| 1011 | return; | 1002 | return; |
| 1012 | } else { | 1003 | } else { |
| 1013 | if (tty && (tty->stopped || tty->hw_stopped)) { | 1004 | if (tty->stopped || tty->hw_stopped) { |
| 1014 | tx_stop(info); | 1005 | tx_stop(info); |
| 1015 | return; | 1006 | return; |
| 1016 | } | 1007 | } |
| @@ -1060,12 +1051,13 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) | |||
| 1060 | wake_up_interruptible(&info->status_event_wait_q); | 1051 | wake_up_interruptible(&info->status_event_wait_q); |
| 1061 | wake_up_interruptible(&info->event_wait_q); | 1052 | wake_up_interruptible(&info->event_wait_q); |
| 1062 | 1053 | ||
| 1063 | if (tty && tty_port_cts_enabled(&info->port)) { | 1054 | if (info->port.flags & ASYNC_CTS_FLOW) { |
| 1064 | if (tty->hw_stopped) { | 1055 | if (tty->hw_stopped) { |
| 1065 | if (info->serial_signals & SerialSignal_CTS) { | 1056 | if (info->serial_signals & SerialSignal_CTS) { |
| 1066 | if (debug_level >= DEBUG_LEVEL_ISR) | 1057 | if (debug_level >= DEBUG_LEVEL_ISR) |
| 1067 | printk("CTS tx start..."); | 1058 | printk("CTS tx start..."); |
| 1068 | tty->hw_stopped = 0; | 1059 | if (tty) |
| 1060 | tty->hw_stopped = 0; | ||
| 1069 | tx_start(info, tty); | 1061 | tx_start(info, tty); |
| 1070 | info->pending_bh |= BH_TRANSMIT; | 1062 | info->pending_bh |= BH_TRANSMIT; |
| 1071 | return; | 1063 | return; |
| @@ -1074,7 +1066,8 @@ static void cts_change(MGSLPC_INFO *info, struct tty_struct *tty) | |||
| 1074 | if (!(info->serial_signals & SerialSignal_CTS)) { | 1066 | if (!(info->serial_signals & SerialSignal_CTS)) { |
| 1075 | if (debug_level >= DEBUG_LEVEL_ISR) | 1067 | if (debug_level >= DEBUG_LEVEL_ISR) |
| 1076 | printk("CTS tx stop..."); | 1068 | printk("CTS tx stop..."); |
| 1077 | tty->hw_stopped = 1; | 1069 | if (tty) |
| 1070 | tty->hw_stopped = 1; | ||
| 1078 | tx_stop(info); | 1071 | tx_stop(info); |
| 1079 | } | 1072 | } |
| 1080 | } | 1073 | } |
| @@ -1352,7 +1345,7 @@ static void shutdown(MGSLPC_INFO * info, struct tty_struct *tty) | |||
| 1352 | /* TODO:disable interrupts instead of reset to preserve signal states */ | 1345 | /* TODO:disable interrupts instead of reset to preserve signal states */ |
| 1353 | reset_device(info); | 1346 | reset_device(info); |
| 1354 | 1347 | ||
| 1355 | if (!tty || tty->termios.c_cflag & HUPCL) { | 1348 | if (!tty || tty->termios->c_cflag & HUPCL) { |
| 1356 | info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); | 1349 | info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS); |
| 1357 | set_signals(info); | 1350 | set_signals(info); |
| 1358 | } | 1351 | } |
| @@ -1393,7 +1386,7 @@ static void mgslpc_program_hw(MGSLPC_INFO *info, struct tty_struct *tty) | |||
| 1393 | port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); | 1386 | port_irq_enable(info, (unsigned char) PVR_DSR | PVR_RI); |
| 1394 | get_signals(info); | 1387 | get_signals(info); |
| 1395 | 1388 | ||
| 1396 | if (info->netcount || (tty && (tty->termios.c_cflag & CREAD))) | 1389 | if (info->netcount || (tty && (tty->termios->c_cflag & CREAD))) |
| 1397 | rx_start(info); | 1390 | rx_start(info); |
| 1398 | 1391 | ||
| 1399 | spin_unlock_irqrestore(&info->lock,flags); | 1392 | spin_unlock_irqrestore(&info->lock,flags); |
| @@ -1406,14 +1399,14 @@ static void mgslpc_change_params(MGSLPC_INFO *info, struct tty_struct *tty) | |||
| 1406 | unsigned cflag; | 1399 | unsigned cflag; |
| 1407 | int bits_per_char; | 1400 | int bits_per_char; |
| 1408 | 1401 | ||
| 1409 | if (!tty) | 1402 | if (!tty || !tty->termios) |
| 1410 | return; | 1403 | return; |
| 1411 | 1404 | ||
| 1412 | if (debug_level >= DEBUG_LEVEL_INFO) | 1405 | if (debug_level >= DEBUG_LEVEL_INFO) |
| 1413 | printk("%s(%d):mgslpc_change_params(%s)\n", | 1406 | printk("%s(%d):mgslpc_change_params(%s)\n", |
| 1414 | __FILE__,__LINE__, info->device_name ); | 1407 | __FILE__,__LINE__, info->device_name ); |
| 1415 | 1408 | ||
| 1416 | cflag = tty->termios.c_cflag; | 1409 | cflag = tty->termios->c_cflag; |
| 1417 | 1410 | ||
| 1418 | /* if B0 rate (hangup) specified then negate DTR and RTS */ | 1411 | /* if B0 rate (hangup) specified then negate DTR and RTS */ |
| 1419 | /* otherwise assert DTR and RTS */ | 1412 | /* otherwise assert DTR and RTS */ |
| @@ -1736,7 +1729,7 @@ static void mgslpc_throttle(struct tty_struct * tty) | |||
| 1736 | if (I_IXOFF(tty)) | 1729 | if (I_IXOFF(tty)) |
| 1737 | mgslpc_send_xchar(tty, STOP_CHAR(tty)); | 1730 | mgslpc_send_xchar(tty, STOP_CHAR(tty)); |
| 1738 | 1731 | ||
| 1739 | if (tty->termios.c_cflag & CRTSCTS) { | 1732 | if (tty->termios->c_cflag & CRTSCTS) { |
| 1740 | spin_lock_irqsave(&info->lock,flags); | 1733 | spin_lock_irqsave(&info->lock,flags); |
| 1741 | info->serial_signals &= ~SerialSignal_RTS; | 1734 | info->serial_signals &= ~SerialSignal_RTS; |
| 1742 | set_signals(info); | 1735 | set_signals(info); |
| @@ -1765,7 +1758,7 @@ static void mgslpc_unthrottle(struct tty_struct * tty) | |||
| 1765 | mgslpc_send_xchar(tty, START_CHAR(tty)); | 1758 | mgslpc_send_xchar(tty, START_CHAR(tty)); |
| 1766 | } | 1759 | } |
| 1767 | 1760 | ||
| 1768 | if (tty->termios.c_cflag & CRTSCTS) { | 1761 | if (tty->termios->c_cflag & CRTSCTS) { |
| 1769 | spin_lock_irqsave(&info->lock,flags); | 1762 | spin_lock_irqsave(&info->lock,flags); |
| 1770 | info->serial_signals |= SerialSignal_RTS; | 1763 | info->serial_signals |= SerialSignal_RTS; |
| 1771 | set_signals(info); | 1764 | set_signals(info); |
| @@ -2301,8 +2294,8 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
| 2301 | tty->driver->name ); | 2294 | tty->driver->name ); |
| 2302 | 2295 | ||
| 2303 | /* just return if nothing has changed */ | 2296 | /* just return if nothing has changed */ |
| 2304 | if ((tty->termios.c_cflag == old_termios->c_cflag) | 2297 | if ((tty->termios->c_cflag == old_termios->c_cflag) |
| 2305 | && (RELEVANT_IFLAG(tty->termios.c_iflag) | 2298 | && (RELEVANT_IFLAG(tty->termios->c_iflag) |
| 2306 | == RELEVANT_IFLAG(old_termios->c_iflag))) | 2299 | == RELEVANT_IFLAG(old_termios->c_iflag))) |
| 2307 | return; | 2300 | return; |
| 2308 | 2301 | ||
| @@ -2310,7 +2303,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
| 2310 | 2303 | ||
| 2311 | /* Handle transition to B0 status */ | 2304 | /* Handle transition to B0 status */ |
| 2312 | if (old_termios->c_cflag & CBAUD && | 2305 | if (old_termios->c_cflag & CBAUD && |
| 2313 | !(tty->termios.c_cflag & CBAUD)) { | 2306 | !(tty->termios->c_cflag & CBAUD)) { |
| 2314 | info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | 2307 | info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); |
| 2315 | spin_lock_irqsave(&info->lock,flags); | 2308 | spin_lock_irqsave(&info->lock,flags); |
| 2316 | set_signals(info); | 2309 | set_signals(info); |
| @@ -2319,9 +2312,9 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
| 2319 | 2312 | ||
| 2320 | /* Handle transition away from B0 status */ | 2313 | /* Handle transition away from B0 status */ |
| 2321 | if (!(old_termios->c_cflag & CBAUD) && | 2314 | if (!(old_termios->c_cflag & CBAUD) && |
| 2322 | tty->termios.c_cflag & CBAUD) { | 2315 | tty->termios->c_cflag & CBAUD) { |
| 2323 | info->serial_signals |= SerialSignal_DTR; | 2316 | info->serial_signals |= SerialSignal_DTR; |
| 2324 | if (!(tty->termios.c_cflag & CRTSCTS) || | 2317 | if (!(tty->termios->c_cflag & CRTSCTS) || |
| 2325 | !test_bit(TTY_THROTTLED, &tty->flags)) { | 2318 | !test_bit(TTY_THROTTLED, &tty->flags)) { |
| 2326 | info->serial_signals |= SerialSignal_RTS; | 2319 | info->serial_signals |= SerialSignal_RTS; |
| 2327 | } | 2320 | } |
| @@ -2332,7 +2325,7 @@ static void mgslpc_set_termios(struct tty_struct *tty, struct ktermios *old_term | |||
| 2332 | 2325 | ||
| 2333 | /* Handle turning off CRTSCTS */ | 2326 | /* Handle turning off CRTSCTS */ |
| 2334 | if (old_termios->c_cflag & CRTSCTS && | 2327 | if (old_termios->c_cflag & CRTSCTS && |
| 2335 | !(tty->termios.c_cflag & CRTSCTS)) { | 2328 | !(tty->termios->c_cflag & CRTSCTS)) { |
| 2336 | tty->hw_stopped = 0; | 2329 | tty->hw_stopped = 0; |
| 2337 | tx_release(tty); | 2330 | tx_release(tty); |
| 2338 | } | 2331 | } |
| @@ -2491,7 +2484,7 @@ static int mgslpc_open(struct tty_struct *tty, struct file * filp) | |||
| 2491 | 2484 | ||
| 2492 | /* verify range of specified line number */ | 2485 | /* verify range of specified line number */ |
| 2493 | line = tty->index; | 2486 | line = tty->index; |
| 2494 | if (line >= mgslpc_device_count) { | 2487 | if ((line < 0) || (line >= mgslpc_device_count)) { |
| 2495 | printk("%s(%d):mgslpc_open with invalid line #%d.\n", | 2488 | printk("%s(%d):mgslpc_open with invalid line #%d.\n", |
| 2496 | __FILE__,__LINE__,line); | 2489 | __FILE__,__LINE__,line); |
| 2497 | return -ENODEV; | 2490 | return -ENODEV; |
| @@ -2739,8 +2732,6 @@ static void mgslpc_add_device(MGSLPC_INFO *info) | |||
| 2739 | #if SYNCLINK_GENERIC_HDLC | 2732 | #if SYNCLINK_GENERIC_HDLC |
| 2740 | hdlcdev_init(info); | 2733 | hdlcdev_init(info); |
| 2741 | #endif | 2734 | #endif |
| 2742 | tty_port_register_device(&info->port, serial_driver, info->line, | ||
| 2743 | &info->p_dev->dev); | ||
| 2744 | } | 2735 | } |
| 2745 | 2736 | ||
| 2746 | static void mgslpc_remove_device(MGSLPC_INFO *remove_info) | 2737 | static void mgslpc_remove_device(MGSLPC_INFO *remove_info) |
| @@ -2754,12 +2745,10 @@ static void mgslpc_remove_device(MGSLPC_INFO *remove_info) | |||
| 2754 | last->next_device = info->next_device; | 2745 | last->next_device = info->next_device; |
| 2755 | else | 2746 | else |
| 2756 | mgslpc_device_list = info->next_device; | 2747 | mgslpc_device_list = info->next_device; |
| 2757 | tty_unregister_device(serial_driver, info->line); | ||
| 2758 | #if SYNCLINK_GENERIC_HDLC | 2748 | #if SYNCLINK_GENERIC_HDLC |
| 2759 | hdlcdev_exit(info); | 2749 | hdlcdev_exit(info); |
| 2760 | #endif | 2750 | #endif |
| 2761 | release_resources(info); | 2751 | release_resources(info); |
| 2762 | tty_port_destroy(&info->port); | ||
| 2763 | kfree(info); | 2752 | kfree(info); |
| 2764 | mgslpc_device_count--; | 2753 | mgslpc_device_count--; |
| 2765 | return; | 2754 | return; |
| @@ -2810,63 +2799,78 @@ static const struct tty_operations mgslpc_ops = { | |||
| 2810 | .proc_fops = &mgslpc_proc_fops, | 2799 | .proc_fops = &mgslpc_proc_fops, |
| 2811 | }; | 2800 | }; |
| 2812 | 2801 | ||
| 2813 | static int __init synclink_cs_init(void) | 2802 | static void synclink_cs_cleanup(void) |
| 2814 | { | 2803 | { |
| 2815 | int rc; | 2804 | int rc; |
| 2816 | 2805 | ||
| 2817 | if (break_on_load) { | 2806 | while(mgslpc_device_list) |
| 2818 | mgslpc_get_text_ptr(); | 2807 | mgslpc_remove_device(mgslpc_device_list); |
| 2819 | BREAKPOINT(); | ||
| 2820 | } | ||
| 2821 | 2808 | ||
| 2822 | serial_driver = tty_alloc_driver(MAX_DEVICE_COUNT, | 2809 | if (serial_driver) { |
| 2823 | TTY_DRIVER_REAL_RAW | | 2810 | if ((rc = tty_unregister_driver(serial_driver))) |
| 2824 | TTY_DRIVER_DYNAMIC_DEV); | 2811 | printk("%s(%d) failed to unregister tty driver err=%d\n", |
| 2825 | if (IS_ERR(serial_driver)) { | 2812 | __FILE__,__LINE__,rc); |
| 2826 | rc = PTR_ERR(serial_driver); | 2813 | put_tty_driver(serial_driver); |
| 2827 | goto err; | ||
| 2828 | } | 2814 | } |
| 2829 | 2815 | ||
| 2830 | /* Initialize the tty_driver structure */ | 2816 | pcmcia_unregister_driver(&mgslpc_driver); |
| 2831 | serial_driver->driver_name = "synclink_cs"; | 2817 | } |
| 2832 | serial_driver->name = "ttySLP"; | ||
| 2833 | serial_driver->major = ttymajor; | ||
| 2834 | serial_driver->minor_start = 64; | ||
| 2835 | serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
| 2836 | serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
| 2837 | serial_driver->init_termios = tty_std_termios; | ||
| 2838 | serial_driver->init_termios.c_cflag = | ||
| 2839 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
| 2840 | tty_set_operations(serial_driver, &mgslpc_ops); | ||
| 2841 | |||
| 2842 | rc = tty_register_driver(serial_driver); | ||
| 2843 | if (rc < 0) { | ||
| 2844 | printk(KERN_ERR "%s(%d):Couldn't register serial driver\n", | ||
| 2845 | __FILE__, __LINE__); | ||
| 2846 | goto err_put_tty; | ||
| 2847 | } | ||
| 2848 | 2818 | ||
| 2849 | rc = pcmcia_register_driver(&mgslpc_driver); | 2819 | static int __init synclink_cs_init(void) |
| 2850 | if (rc < 0) | 2820 | { |
| 2851 | goto err_unreg_tty; | 2821 | int rc; |
| 2852 | 2822 | ||
| 2853 | printk(KERN_INFO "%s %s, tty major#%d\n", driver_name, driver_version, | 2823 | if (break_on_load) { |
| 2854 | serial_driver->major); | 2824 | mgslpc_get_text_ptr(); |
| 2825 | BREAKPOINT(); | ||
| 2826 | } | ||
| 2855 | 2827 | ||
| 2856 | return 0; | 2828 | if ((rc = pcmcia_register_driver(&mgslpc_driver)) < 0) |
| 2857 | err_unreg_tty: | 2829 | return rc; |
| 2858 | tty_unregister_driver(serial_driver); | 2830 | |
| 2859 | err_put_tty: | 2831 | serial_driver = alloc_tty_driver(MAX_DEVICE_COUNT); |
| 2860 | put_tty_driver(serial_driver); | 2832 | if (!serial_driver) { |
| 2861 | err: | 2833 | rc = -ENOMEM; |
| 2862 | return rc; | 2834 | goto error; |
| 2835 | } | ||
| 2836 | |||
| 2837 | /* Initialize the tty_driver structure */ | ||
| 2838 | |||
| 2839 | serial_driver->owner = THIS_MODULE; | ||
| 2840 | serial_driver->driver_name = "synclink_cs"; | ||
| 2841 | serial_driver->name = "ttySLP"; | ||
| 2842 | serial_driver->major = ttymajor; | ||
| 2843 | serial_driver->minor_start = 64; | ||
| 2844 | serial_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
| 2845 | serial_driver->subtype = SERIAL_TYPE_NORMAL; | ||
| 2846 | serial_driver->init_termios = tty_std_termios; | ||
| 2847 | serial_driver->init_termios.c_cflag = | ||
| 2848 | B9600 | CS8 | CREAD | HUPCL | CLOCAL; | ||
| 2849 | serial_driver->flags = TTY_DRIVER_REAL_RAW; | ||
| 2850 | tty_set_operations(serial_driver, &mgslpc_ops); | ||
| 2851 | |||
| 2852 | if ((rc = tty_register_driver(serial_driver)) < 0) { | ||
| 2853 | printk("%s(%d):Couldn't register serial driver\n", | ||
| 2854 | __FILE__,__LINE__); | ||
| 2855 | put_tty_driver(serial_driver); | ||
| 2856 | serial_driver = NULL; | ||
| 2857 | goto error; | ||
| 2858 | } | ||
| 2859 | |||
| 2860 | printk("%s %s, tty major#%d\n", | ||
| 2861 | driver_name, driver_version, | ||
| 2862 | serial_driver->major); | ||
| 2863 | |||
| 2864 | return 0; | ||
| 2865 | |||
| 2866 | error: | ||
| 2867 | synclink_cs_cleanup(); | ||
| 2868 | return rc; | ||
| 2863 | } | 2869 | } |
| 2864 | 2870 | ||
| 2865 | static void __exit synclink_cs_exit(void) | 2871 | static void __exit synclink_cs_exit(void) |
| 2866 | { | 2872 | { |
| 2867 | pcmcia_unregister_driver(&mgslpc_driver); | 2873 | synclink_cs_cleanup(); |
| 2868 | tty_unregister_driver(serial_driver); | ||
| 2869 | put_tty_driver(serial_driver); | ||
| 2870 | } | 2874 | } |
| 2871 | 2875 | ||
| 2872 | module_init(synclink_cs_init); | 2876 | module_init(synclink_cs_init); |
diff --git a/drivers/char/ppdev.c b/drivers/char/ppdev.c index 1cd49241e60..3fcf80ff12f 100644 --- a/drivers/char/ppdev.c +++ b/drivers/char/ppdev.c | |||
| @@ -251,8 +251,12 @@ static ssize_t pp_write (struct file * file, const char __user * buf, | |||
| 251 | break; | 251 | break; |
| 252 | } | 252 | } |
| 253 | 253 | ||
| 254 | if (signal_pending (current)) | 254 | if (signal_pending (current)) { |
| 255 | if (!bytes_written) { | ||
| 256 | bytes_written = -EINTR; | ||
| 257 | } | ||
| 255 | break; | 258 | break; |
| 259 | } | ||
| 256 | 260 | ||
| 257 | cond_resched(); | 261 | cond_resched(); |
| 258 | } | 262 | } |
| @@ -779,8 +783,7 @@ static int __init ppdev_init (void) | |||
| 779 | err = PTR_ERR(ppdev_class); | 783 | err = PTR_ERR(ppdev_class); |
| 780 | goto out_chrdev; | 784 | goto out_chrdev; |
| 781 | } | 785 | } |
| 782 | err = parport_register_driver(&pp_driver); | 786 | if (parport_register_driver(&pp_driver)) { |
| 783 | if (err < 0) { | ||
| 784 | printk (KERN_WARNING CHRDEV ": unable to register with parport\n"); | 787 | printk (KERN_WARNING CHRDEV ": unable to register with parport\n"); |
| 785 | goto out_class; | 788 | goto out_class; |
| 786 | } | 789 | } |
diff --git a/drivers/char/ps3flash.c b/drivers/char/ps3flash.c index 588063ac951..d0c57c2e290 100644 --- a/drivers/char/ps3flash.c +++ b/drivers/char/ps3flash.c | |||
| @@ -22,7 +22,6 @@ | |||
| 22 | #include <linux/miscdevice.h> | 22 | #include <linux/miscdevice.h> |
| 23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
| 24 | #include <linux/uaccess.h> | 24 | #include <linux/uaccess.h> |
| 25 | #include <linux/module.h> | ||
| 26 | 25 | ||
| 27 | #include <asm/lv1call.h> | 26 | #include <asm/lv1call.h> |
| 28 | #include <asm/ps3stor.h> | 27 | #include <asm/ps3stor.h> |
| @@ -363,7 +362,7 @@ static struct miscdevice ps3flash_misc = { | |||
| 363 | .fops = &ps3flash_fops, | 362 | .fops = &ps3flash_fops, |
| 364 | }; | 363 | }; |
| 365 | 364 | ||
| 366 | static int ps3flash_probe(struct ps3_system_bus_device *_dev) | 365 | static int __devinit ps3flash_probe(struct ps3_system_bus_device *_dev) |
| 367 | { | 366 | { |
| 368 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); | 367 | struct ps3_storage_device *dev = to_ps3_storage_device(&_dev->core); |
| 369 | struct ps3flash_private *priv; | 368 | struct ps3flash_private *priv; |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 85e81ec1451..c35a785005b 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
| @@ -125,26 +125,21 @@ | |||
| 125 | * The current exported interfaces for gathering environmental noise | 125 | * The current exported interfaces for gathering environmental noise |
| 126 | * from the devices are: | 126 | * from the devices are: |
| 127 | * | 127 | * |
| 128 | * void add_device_randomness(const void *buf, unsigned int size); | ||
| 129 | * void add_input_randomness(unsigned int type, unsigned int code, | 128 | * void add_input_randomness(unsigned int type, unsigned int code, |
| 130 | * unsigned int value); | 129 | * unsigned int value); |
| 131 | * void add_interrupt_randomness(int irq, int irq_flags); | 130 | * void add_interrupt_randomness(int irq); |
| 132 | * void add_disk_randomness(struct gendisk *disk); | 131 | * void add_disk_randomness(struct gendisk *disk); |
| 133 | * | 132 | * |
| 134 | * add_device_randomness() is for adding data to the random pool that | ||
| 135 | * is likely to differ between two devices (or possibly even per boot). | ||
| 136 | * This would be things like MAC addresses or serial numbers, or the | ||
| 137 | * read-out of the RTC. This does *not* add any actual entropy to the | ||
| 138 | * pool, but it initializes the pool to different values for devices | ||
| 139 | * that might otherwise be identical and have very little entropy | ||
| 140 | * available to them (particularly common in the embedded world). | ||
| 141 | * | ||
| 142 | * add_input_randomness() uses the input layer interrupt timing, as well as | 133 | * add_input_randomness() uses the input layer interrupt timing, as well as |
| 143 | * the event type information from the hardware. | 134 | * the event type information from the hardware. |
| 144 | * | 135 | * |
| 145 | * add_interrupt_randomness() uses the interrupt timing as random | 136 | * add_interrupt_randomness() uses the inter-interrupt timing as random |
| 146 | * inputs to the entropy pool. Using the cycle counters and the irq source | 137 | * inputs to the entropy pool. Note that not all interrupts are good |
| 147 | * as inputs, it feeds the randomness roughly once a second. | 138 | * sources of randomness! For example, the timer interrupts is not a |
| 139 | * good choice, because the periodicity of the interrupts is too | ||
| 140 | * regular, and hence predictable to an attacker. Network Interface | ||
| 141 | * Controller interrupts are a better measure, since the timing of the | ||
| 142 | * NIC interrupts are more unpredictable. | ||
| 148 | * | 143 | * |
| 149 | * add_disk_randomness() uses what amounts to the seek time of block | 144 | * add_disk_randomness() uses what amounts to the seek time of block |
| 150 | * layer request events, on a per-disk_devt basis, as input to the | 145 | * layer request events, on a per-disk_devt basis, as input to the |
| @@ -253,8 +248,6 @@ | |||
| 253 | #include <linux/percpu.h> | 248 | #include <linux/percpu.h> |
| 254 | #include <linux/cryptohash.h> | 249 | #include <linux/cryptohash.h> |
| 255 | #include <linux/fips.h> | 250 | #include <linux/fips.h> |
| 256 | #include <linux/ptrace.h> | ||
| 257 | #include <linux/kmemcheck.h> | ||
| 258 | 251 | ||
| 259 | #ifdef CONFIG_GENERIC_HARDIRQS | 252 | #ifdef CONFIG_GENERIC_HARDIRQS |
| 260 | # include <linux/irq.h> | 253 | # include <linux/irq.h> |
| @@ -263,12 +256,8 @@ | |||
| 263 | #include <asm/processor.h> | 256 | #include <asm/processor.h> |
| 264 | #include <asm/uaccess.h> | 257 | #include <asm/uaccess.h> |
| 265 | #include <asm/irq.h> | 258 | #include <asm/irq.h> |
| 266 | #include <asm/irq_regs.h> | ||
| 267 | #include <asm/io.h> | 259 | #include <asm/io.h> |
| 268 | 260 | ||
| 269 | #define CREATE_TRACE_POINTS | ||
| 270 | #include <trace/events/random.h> | ||
| 271 | |||
| 272 | /* | 261 | /* |
| 273 | * Configuration information | 262 | * Configuration information |
| 274 | */ | 263 | */ |
| @@ -277,8 +266,6 @@ | |||
| 277 | #define SEC_XFER_SIZE 512 | 266 | #define SEC_XFER_SIZE 512 |
| 278 | #define EXTRACT_SIZE 10 | 267 | #define EXTRACT_SIZE 10 |
| 279 | 268 | ||
| 280 | #define LONGS(x) (((x) + sizeof(unsigned long) - 1)/sizeof(unsigned long)) | ||
| 281 | |||
| 282 | /* | 269 | /* |
| 283 | * The minimum number of bits of entropy before we wake up a read on | 270 | * The minimum number of bits of entropy before we wake up a read on |
| 284 | * /dev/random. Should be enough to do a significant reseed. | 271 | * /dev/random. Should be enough to do a significant reseed. |
| @@ -399,7 +386,8 @@ static DECLARE_WAIT_QUEUE_HEAD(random_read_wait); | |||
| 399 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); | 386 | static DECLARE_WAIT_QUEUE_HEAD(random_write_wait); |
| 400 | static struct fasync_struct *fasync; | 387 | static struct fasync_struct *fasync; |
| 401 | 388 | ||
| 402 | static bool debug; | 389 | #if 0 |
| 390 | static int debug; | ||
| 403 | module_param(debug, bool, 0644); | 391 | module_param(debug, bool, 0644); |
| 404 | #define DEBUG_ENT(fmt, arg...) do { \ | 392 | #define DEBUG_ENT(fmt, arg...) do { \ |
| 405 | if (debug) \ | 393 | if (debug) \ |
| @@ -409,6 +397,9 @@ module_param(debug, bool, 0644); | |||
| 409 | blocking_pool.entropy_count,\ | 397 | blocking_pool.entropy_count,\ |
| 410 | nonblocking_pool.entropy_count,\ | 398 | nonblocking_pool.entropy_count,\ |
| 411 | ## arg); } while (0) | 399 | ## arg); } while (0) |
| 400 | #else | ||
| 401 | #define DEBUG_ENT(fmt, arg...) do {} while (0) | ||
| 402 | #endif | ||
| 412 | 403 | ||
| 413 | /********************************************************************** | 404 | /********************************************************************** |
| 414 | * | 405 | * |
| @@ -429,11 +420,8 @@ struct entropy_store { | |||
| 429 | /* read-write data: */ | 420 | /* read-write data: */ |
| 430 | spinlock_t lock; | 421 | spinlock_t lock; |
| 431 | unsigned add_ptr; | 422 | unsigned add_ptr; |
| 432 | unsigned input_rotate; | ||
| 433 | int entropy_count; | 423 | int entropy_count; |
| 434 | int entropy_total; | 424 | int input_rotate; |
| 435 | unsigned int initialized:1; | ||
| 436 | bool last_data_init; | ||
| 437 | __u8 last_data[EXTRACT_SIZE]; | 425 | __u8 last_data[EXTRACT_SIZE]; |
| 438 | }; | 426 | }; |
| 439 | 427 | ||
| @@ -466,10 +454,6 @@ static struct entropy_store nonblocking_pool = { | |||
| 466 | .pool = nonblocking_pool_data | 454 | .pool = nonblocking_pool_data |
| 467 | }; | 455 | }; |
| 468 | 456 | ||
| 469 | static __u32 const twist_table[8] = { | ||
| 470 | 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, | ||
| 471 | 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; | ||
| 472 | |||
| 473 | /* | 457 | /* |
| 474 | * This function adds bytes into the entropy "pool". It does not | 458 | * This function adds bytes into the entropy "pool". It does not |
| 475 | * update the entropy estimate. The caller should call | 459 | * update the entropy estimate. The caller should call |
| @@ -480,24 +464,29 @@ static __u32 const twist_table[8] = { | |||
| 480 | * it's cheap to do so and helps slightly in the expected case where | 464 | * it's cheap to do so and helps slightly in the expected case where |
| 481 | * the entropy is concentrated in the low-order bits. | 465 | * the entropy is concentrated in the low-order bits. |
| 482 | */ | 466 | */ |
| 483 | static void _mix_pool_bytes(struct entropy_store *r, const void *in, | 467 | static void mix_pool_bytes_extract(struct entropy_store *r, const void *in, |
| 484 | int nbytes, __u8 out[64]) | 468 | int nbytes, __u8 out[64]) |
| 485 | { | 469 | { |
| 470 | static __u32 const twist_table[8] = { | ||
| 471 | 0x00000000, 0x3b6e20c8, 0x76dc4190, 0x4db26158, | ||
| 472 | 0xedb88320, 0xd6d6a3e8, 0x9b64c2b0, 0xa00ae278 }; | ||
| 486 | unsigned long i, j, tap1, tap2, tap3, tap4, tap5; | 473 | unsigned long i, j, tap1, tap2, tap3, tap4, tap5; |
| 487 | int input_rotate; | 474 | int input_rotate; |
| 488 | int wordmask = r->poolinfo->poolwords - 1; | 475 | int wordmask = r->poolinfo->poolwords - 1; |
| 489 | const char *bytes = in; | 476 | const char *bytes = in; |
| 490 | __u32 w; | 477 | __u32 w; |
| 478 | unsigned long flags; | ||
| 491 | 479 | ||
| 480 | /* Taps are constant, so we can load them without holding r->lock. */ | ||
| 492 | tap1 = r->poolinfo->tap1; | 481 | tap1 = r->poolinfo->tap1; |
| 493 | tap2 = r->poolinfo->tap2; | 482 | tap2 = r->poolinfo->tap2; |
| 494 | tap3 = r->poolinfo->tap3; | 483 | tap3 = r->poolinfo->tap3; |
| 495 | tap4 = r->poolinfo->tap4; | 484 | tap4 = r->poolinfo->tap4; |
| 496 | tap5 = r->poolinfo->tap5; | 485 | tap5 = r->poolinfo->tap5; |
| 497 | 486 | ||
| 498 | smp_rmb(); | 487 | spin_lock_irqsave(&r->lock, flags); |
| 499 | input_rotate = ACCESS_ONCE(r->input_rotate); | 488 | input_rotate = r->input_rotate; |
| 500 | i = ACCESS_ONCE(r->add_ptr); | 489 | i = r->add_ptr; |
| 501 | 490 | ||
| 502 | /* mix one byte at a time to simplify size handling and churn faster */ | 491 | /* mix one byte at a time to simplify size handling and churn faster */ |
| 503 | while (nbytes--) { | 492 | while (nbytes--) { |
| @@ -524,61 +513,19 @@ static void _mix_pool_bytes(struct entropy_store *r, const void *in, | |||
| 524 | input_rotate += i ? 7 : 14; | 513 | input_rotate += i ? 7 : 14; |
| 525 | } | 514 | } |
| 526 | 515 | ||
| 527 | ACCESS_ONCE(r->input_rotate) = input_rotate; | 516 | r->input_rotate = input_rotate; |
| 528 | ACCESS_ONCE(r->add_ptr) = i; | 517 | r->add_ptr = i; |
| 529 | smp_wmb(); | ||
| 530 | 518 | ||
| 531 | if (out) | 519 | if (out) |
| 532 | for (j = 0; j < 16; j++) | 520 | for (j = 0; j < 16; j++) |
| 533 | ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; | 521 | ((__u32 *)out)[j] = r->pool[(i - j) & wordmask]; |
| 534 | } | ||
| 535 | |||
| 536 | static void __mix_pool_bytes(struct entropy_store *r, const void *in, | ||
| 537 | int nbytes, __u8 out[64]) | ||
| 538 | { | ||
| 539 | trace_mix_pool_bytes_nolock(r->name, nbytes, _RET_IP_); | ||
| 540 | _mix_pool_bytes(r, in, nbytes, out); | ||
| 541 | } | ||
| 542 | |||
| 543 | static void mix_pool_bytes(struct entropy_store *r, const void *in, | ||
| 544 | int nbytes, __u8 out[64]) | ||
| 545 | { | ||
| 546 | unsigned long flags; | ||
| 547 | 522 | ||
| 548 | trace_mix_pool_bytes(r->name, nbytes, _RET_IP_); | ||
| 549 | spin_lock_irqsave(&r->lock, flags); | ||
| 550 | _mix_pool_bytes(r, in, nbytes, out); | ||
| 551 | spin_unlock_irqrestore(&r->lock, flags); | 523 | spin_unlock_irqrestore(&r->lock, flags); |
| 552 | } | 524 | } |
| 553 | 525 | ||
| 554 | struct fast_pool { | 526 | static void mix_pool_bytes(struct entropy_store *r, const void *in, int bytes) |
| 555 | __u32 pool[4]; | ||
| 556 | unsigned long last; | ||
| 557 | unsigned short count; | ||
| 558 | unsigned char rotate; | ||
| 559 | unsigned char last_timer_intr; | ||
| 560 | }; | ||
| 561 | |||
| 562 | /* | ||
| 563 | * This is a fast mixing routine used by the interrupt randomness | ||
| 564 | * collector. It's hardcoded for an 128 bit pool and assumes that any | ||
| 565 | * locks that might be needed are taken by the caller. | ||
| 566 | */ | ||
| 567 | static void fast_mix(struct fast_pool *f, const void *in, int nbytes) | ||
| 568 | { | 527 | { |
| 569 | const char *bytes = in; | 528 | mix_pool_bytes_extract(r, in, bytes, NULL); |
| 570 | __u32 w; | ||
| 571 | unsigned i = f->count; | ||
| 572 | unsigned input_rotate = f->rotate; | ||
| 573 | |||
| 574 | while (nbytes--) { | ||
| 575 | w = rol32(*bytes++, input_rotate & 31) ^ f->pool[i & 3] ^ | ||
| 576 | f->pool[(i + 1) & 3]; | ||
| 577 | f->pool[i & 3] = (w >> 3) ^ twist_table[w & 7]; | ||
| 578 | input_rotate += (i++ & 3) ? 7 : 14; | ||
| 579 | } | ||
| 580 | f->count = i; | ||
| 581 | f->rotate = input_rotate; | ||
| 582 | } | 529 | } |
| 583 | 530 | ||
| 584 | /* | 531 | /* |
| @@ -586,38 +533,30 @@ static void fast_mix(struct fast_pool *f, const void *in, int nbytes) | |||
| 586 | */ | 533 | */ |
| 587 | static void credit_entropy_bits(struct entropy_store *r, int nbits) | 534 | static void credit_entropy_bits(struct entropy_store *r, int nbits) |
| 588 | { | 535 | { |
| 589 | int entropy_count, orig; | 536 | unsigned long flags; |
| 537 | int entropy_count; | ||
| 590 | 538 | ||
| 591 | if (!nbits) | 539 | if (!nbits) |
| 592 | return; | 540 | return; |
| 593 | 541 | ||
| 542 | spin_lock_irqsave(&r->lock, flags); | ||
| 543 | |||
| 594 | DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name); | 544 | DEBUG_ENT("added %d entropy credits to %s\n", nbits, r->name); |
| 595 | retry: | 545 | entropy_count = r->entropy_count; |
| 596 | entropy_count = orig = ACCESS_ONCE(r->entropy_count); | ||
| 597 | entropy_count += nbits; | 546 | entropy_count += nbits; |
| 598 | |||
| 599 | if (entropy_count < 0) { | 547 | if (entropy_count < 0) { |
| 600 | DEBUG_ENT("negative entropy/overflow\n"); | 548 | DEBUG_ENT("negative entropy/overflow\n"); |
| 601 | entropy_count = 0; | 549 | entropy_count = 0; |
| 602 | } else if (entropy_count > r->poolinfo->POOLBITS) | 550 | } else if (entropy_count > r->poolinfo->POOLBITS) |
| 603 | entropy_count = r->poolinfo->POOLBITS; | 551 | entropy_count = r->poolinfo->POOLBITS; |
| 604 | if (cmpxchg(&r->entropy_count, orig, entropy_count) != orig) | 552 | r->entropy_count = entropy_count; |
| 605 | goto retry; | ||
| 606 | |||
| 607 | if (!r->initialized && nbits > 0) { | ||
| 608 | r->entropy_total += nbits; | ||
| 609 | if (r->entropy_total > 128) | ||
| 610 | r->initialized = 1; | ||
| 611 | } | ||
| 612 | |||
| 613 | trace_credit_entropy_bits(r->name, nbits, entropy_count, | ||
| 614 | r->entropy_total, _RET_IP_); | ||
| 615 | 553 | ||
| 616 | /* should we wake readers? */ | 554 | /* should we wake readers? */ |
| 617 | if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) { | 555 | if (r == &input_pool && entropy_count >= random_read_wakeup_thresh) { |
| 618 | wake_up_interruptible(&random_read_wait); | 556 | wake_up_interruptible(&random_read_wait); |
| 619 | kill_fasync(&fasync, SIGIO, POLL_IN); | 557 | kill_fasync(&fasync, SIGIO, POLL_IN); |
| 620 | } | 558 | } |
| 559 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 621 | } | 560 | } |
| 622 | 561 | ||
| 623 | /********************************************************************* | 562 | /********************************************************************* |
| @@ -633,24 +572,42 @@ struct timer_rand_state { | |||
| 633 | unsigned dont_count_entropy:1; | 572 | unsigned dont_count_entropy:1; |
| 634 | }; | 573 | }; |
| 635 | 574 | ||
| 636 | /* | 575 | #ifndef CONFIG_GENERIC_HARDIRQS |
| 637 | * Add device- or boot-specific data to the input and nonblocking | 576 | |
| 638 | * pools to help initialize them to unique values. | 577 | static struct timer_rand_state *irq_timer_state[NR_IRQS]; |
| 639 | * | 578 | |
| 640 | * None of this adds any entropy, it is meant to avoid the | 579 | static struct timer_rand_state *get_timer_rand_state(unsigned int irq) |
| 641 | * problem of the nonblocking pool having similar initial state | 580 | { |
| 642 | * across largely identical devices. | 581 | return irq_timer_state[irq]; |
| 643 | */ | 582 | } |
| 644 | void add_device_randomness(const void *buf, unsigned int size) | 583 | |
| 584 | static void set_timer_rand_state(unsigned int irq, | ||
| 585 | struct timer_rand_state *state) | ||
| 586 | { | ||
| 587 | irq_timer_state[irq] = state; | ||
| 588 | } | ||
| 589 | |||
| 590 | #else | ||
| 591 | |||
| 592 | static struct timer_rand_state *get_timer_rand_state(unsigned int irq) | ||
| 645 | { | 593 | { |
| 646 | unsigned long time = get_cycles() ^ jiffies; | 594 | struct irq_desc *desc; |
| 595 | |||
| 596 | desc = irq_to_desc(irq); | ||
| 647 | 597 | ||
| 648 | mix_pool_bytes(&input_pool, buf, size, NULL); | 598 | return desc->timer_rand_state; |
| 649 | mix_pool_bytes(&input_pool, &time, sizeof(time), NULL); | ||
| 650 | mix_pool_bytes(&nonblocking_pool, buf, size, NULL); | ||
| 651 | mix_pool_bytes(&nonblocking_pool, &time, sizeof(time), NULL); | ||
| 652 | } | 599 | } |
| 653 | EXPORT_SYMBOL(add_device_randomness); | 600 | |
| 601 | static void set_timer_rand_state(unsigned int irq, | ||
| 602 | struct timer_rand_state *state) | ||
| 603 | { | ||
| 604 | struct irq_desc *desc; | ||
| 605 | |||
| 606 | desc = irq_to_desc(irq); | ||
| 607 | |||
| 608 | desc->timer_rand_state = state; | ||
| 609 | } | ||
| 610 | #endif | ||
| 654 | 611 | ||
| 655 | static struct timer_rand_state input_timer_state; | 612 | static struct timer_rand_state input_timer_state; |
| 656 | 613 | ||
| @@ -667,8 +624,8 @@ static struct timer_rand_state input_timer_state; | |||
| 667 | static void add_timer_randomness(struct timer_rand_state *state, unsigned num) | 624 | static void add_timer_randomness(struct timer_rand_state *state, unsigned num) |
| 668 | { | 625 | { |
| 669 | struct { | 626 | struct { |
| 627 | cycles_t cycles; | ||
| 670 | long jiffies; | 628 | long jiffies; |
| 671 | unsigned cycles; | ||
| 672 | unsigned num; | 629 | unsigned num; |
| 673 | } sample; | 630 | } sample; |
| 674 | long delta, delta2, delta3; | 631 | long delta, delta2, delta3; |
| @@ -682,7 +639,7 @@ static void add_timer_randomness(struct timer_rand_state *state, unsigned num) | |||
| 682 | sample.jiffies = jiffies; | 639 | sample.jiffies = jiffies; |
| 683 | sample.cycles = get_cycles(); | 640 | sample.cycles = get_cycles(); |
| 684 | sample.num = num; | 641 | sample.num = num; |
| 685 | mix_pool_bytes(&input_pool, &sample, sizeof(sample), NULL); | 642 | mix_pool_bytes(&input_pool, &sample, sizeof(sample)); |
| 686 | 643 | ||
| 687 | /* | 644 | /* |
| 688 | * Calculate number of bits of randomness we probably added. | 645 | * Calculate number of bits of randomness we probably added. |
| @@ -739,48 +696,17 @@ void add_input_randomness(unsigned int type, unsigned int code, | |||
| 739 | } | 696 | } |
| 740 | EXPORT_SYMBOL_GPL(add_input_randomness); | 697 | EXPORT_SYMBOL_GPL(add_input_randomness); |
| 741 | 698 | ||
| 742 | static DEFINE_PER_CPU(struct fast_pool, irq_randomness); | 699 | void add_interrupt_randomness(int irq) |
| 743 | |||
| 744 | void add_interrupt_randomness(int irq, int irq_flags) | ||
| 745 | { | 700 | { |
| 746 | struct entropy_store *r; | 701 | struct timer_rand_state *state; |
| 747 | struct fast_pool *fast_pool = &__get_cpu_var(irq_randomness); | ||
| 748 | struct pt_regs *regs = get_irq_regs(); | ||
| 749 | unsigned long now = jiffies; | ||
| 750 | __u32 input[4], cycles = get_cycles(); | ||
| 751 | |||
| 752 | input[0] = cycles ^ jiffies; | ||
| 753 | input[1] = irq; | ||
| 754 | if (regs) { | ||
| 755 | __u64 ip = instruction_pointer(regs); | ||
| 756 | input[2] = ip; | ||
| 757 | input[3] = ip >> 32; | ||
| 758 | } | ||
| 759 | 702 | ||
| 760 | fast_mix(fast_pool, input, sizeof(input)); | 703 | state = get_timer_rand_state(irq); |
| 761 | 704 | ||
| 762 | if ((fast_pool->count & 1023) && | 705 | if (state == NULL) |
| 763 | !time_after(now, fast_pool->last + HZ)) | ||
| 764 | return; | 706 | return; |
| 765 | 707 | ||
| 766 | fast_pool->last = now; | 708 | DEBUG_ENT("irq event %d\n", irq); |
| 767 | 709 | add_timer_randomness(state, 0x100 + irq); | |
| 768 | r = nonblocking_pool.initialized ? &input_pool : &nonblocking_pool; | ||
| 769 | __mix_pool_bytes(r, &fast_pool->pool, sizeof(fast_pool->pool), NULL); | ||
| 770 | /* | ||
| 771 | * If we don't have a valid cycle counter, and we see | ||
| 772 | * back-to-back timer interrupts, then skip giving credit for | ||
| 773 | * any entropy. | ||
| 774 | */ | ||
| 775 | if (cycles == 0) { | ||
| 776 | if (irq_flags & __IRQF_TIMER) { | ||
| 777 | if (fast_pool->last_timer_intr) | ||
| 778 | return; | ||
| 779 | fast_pool->last_timer_intr = 1; | ||
| 780 | } else | ||
| 781 | fast_pool->last_timer_intr = 0; | ||
| 782 | } | ||
| 783 | credit_entropy_bits(r, 1); | ||
| 784 | } | 710 | } |
| 785 | 711 | ||
| 786 | #ifdef CONFIG_BLOCK | 712 | #ifdef CONFIG_BLOCK |
| @@ -812,7 +738,7 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 812 | */ | 738 | */ |
| 813 | static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) | 739 | static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) |
| 814 | { | 740 | { |
| 815 | __u32 tmp[OUTPUT_POOL_WORDS]; | 741 | __u32 tmp[OUTPUT_POOL_WORDS]; |
| 816 | 742 | ||
| 817 | if (r->pull && r->entropy_count < nbytes * 8 && | 743 | if (r->pull && r->entropy_count < nbytes * 8 && |
| 818 | r->entropy_count < r->poolinfo->POOLBITS) { | 744 | r->entropy_count < r->poolinfo->POOLBITS) { |
| @@ -826,12 +752,12 @@ static void xfer_secondary_pool(struct entropy_store *r, size_t nbytes) | |||
| 826 | bytes = min_t(int, bytes, sizeof(tmp)); | 752 | bytes = min_t(int, bytes, sizeof(tmp)); |
| 827 | 753 | ||
| 828 | DEBUG_ENT("going to reseed %s with %d bits " | 754 | DEBUG_ENT("going to reseed %s with %d bits " |
| 829 | "(%zu of %d requested)\n", | 755 | "(%d of %d requested)\n", |
| 830 | r->name, bytes * 8, nbytes * 8, r->entropy_count); | 756 | r->name, bytes * 8, nbytes * 8, r->entropy_count); |
| 831 | 757 | ||
| 832 | bytes = extract_entropy(r->pull, tmp, bytes, | 758 | bytes = extract_entropy(r->pull, tmp, bytes, |
| 833 | random_read_wakeup_thresh / 8, rsvd); | 759 | random_read_wakeup_thresh / 8, rsvd); |
| 834 | mix_pool_bytes(r, tmp, bytes, NULL); | 760 | mix_pool_bytes(r, tmp, bytes); |
| 835 | credit_entropy_bits(r, bytes*8); | 761 | credit_entropy_bits(r, bytes*8); |
| 836 | } | 762 | } |
| 837 | } | 763 | } |
| @@ -857,7 +783,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 857 | spin_lock_irqsave(&r->lock, flags); | 783 | spin_lock_irqsave(&r->lock, flags); |
| 858 | 784 | ||
| 859 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); | 785 | BUG_ON(r->entropy_count > r->poolinfo->POOLBITS); |
| 860 | DEBUG_ENT("trying to extract %zu bits from %s\n", | 786 | DEBUG_ENT("trying to extract %d bits from %s\n", |
| 861 | nbytes * 8, r->name); | 787 | nbytes * 8, r->name); |
| 862 | 788 | ||
| 863 | /* Can we pull enough? */ | 789 | /* Can we pull enough? */ |
| @@ -879,7 +805,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 879 | } | 805 | } |
| 880 | } | 806 | } |
| 881 | 807 | ||
| 882 | DEBUG_ENT("debiting %zu entropy credits from %s%s\n", | 808 | DEBUG_ENT("debiting %d entropy credits from %s%s\n", |
| 883 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); | 809 | nbytes * 8, r->name, r->limit ? "" : " (unlimited)"); |
| 884 | 810 | ||
| 885 | spin_unlock_irqrestore(&r->lock, flags); | 811 | spin_unlock_irqrestore(&r->lock, flags); |
| @@ -890,19 +816,13 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
| 890 | static void extract_buf(struct entropy_store *r, __u8 *out) | 816 | static void extract_buf(struct entropy_store *r, __u8 *out) |
| 891 | { | 817 | { |
| 892 | int i; | 818 | int i; |
| 893 | union { | 819 | __u32 hash[5], workspace[SHA_WORKSPACE_WORDS]; |
| 894 | __u32 w[5]; | ||
| 895 | unsigned long l[LONGS(EXTRACT_SIZE)]; | ||
| 896 | } hash; | ||
| 897 | __u32 workspace[SHA_WORKSPACE_WORDS]; | ||
| 898 | __u8 extract[64]; | 820 | __u8 extract[64]; |
| 899 | unsigned long flags; | ||
| 900 | 821 | ||
| 901 | /* Generate a hash across the pool, 16 words (512 bits) at a time */ | 822 | /* Generate a hash across the pool, 16 words (512 bits) at a time */ |
| 902 | sha_init(hash.w); | 823 | sha_init(hash); |
| 903 | spin_lock_irqsave(&r->lock, flags); | ||
| 904 | for (i = 0; i < r->poolinfo->poolwords; i += 16) | 824 | for (i = 0; i < r->poolinfo->poolwords; i += 16) |
| 905 | sha_transform(hash.w, (__u8 *)(r->pool + i), workspace); | 825 | sha_transform(hash, (__u8 *)(r->pool + i), workspace); |
| 906 | 826 | ||
| 907 | /* | 827 | /* |
| 908 | * We mix the hash back into the pool to prevent backtracking | 828 | * We mix the hash back into the pool to prevent backtracking |
| @@ -913,14 +833,13 @@ static void extract_buf(struct entropy_store *r, __u8 *out) | |||
| 913 | * brute-forcing the feedback as hard as brute-forcing the | 833 | * brute-forcing the feedback as hard as brute-forcing the |
| 914 | * hash. | 834 | * hash. |
| 915 | */ | 835 | */ |
| 916 | __mix_pool_bytes(r, hash.w, sizeof(hash.w), extract); | 836 | mix_pool_bytes_extract(r, hash, sizeof(hash), extract); |
| 917 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 918 | 837 | ||
| 919 | /* | 838 | /* |
| 920 | * To avoid duplicates, we atomically extract a portion of the | 839 | * To avoid duplicates, we atomically extract a portion of the |
| 921 | * pool while mixing, and hash one final time. | 840 | * pool while mixing, and hash one final time. |
| 922 | */ | 841 | */ |
| 923 | sha_transform(hash.w, extract, workspace); | 842 | sha_transform(hash, extract, workspace); |
| 924 | memset(extract, 0, sizeof(extract)); | 843 | memset(extract, 0, sizeof(extract)); |
| 925 | memset(workspace, 0, sizeof(workspace)); | 844 | memset(workspace, 0, sizeof(workspace)); |
| 926 | 845 | ||
| @@ -929,36 +848,20 @@ static void extract_buf(struct entropy_store *r, __u8 *out) | |||
| 929 | * pattern, we fold it in half. Thus, we always feed back | 848 | * pattern, we fold it in half. Thus, we always feed back |
| 930 | * twice as much data as we output. | 849 | * twice as much data as we output. |
| 931 | */ | 850 | */ |
| 932 | hash.w[0] ^= hash.w[3]; | 851 | hash[0] ^= hash[3]; |
| 933 | hash.w[1] ^= hash.w[4]; | 852 | hash[1] ^= hash[4]; |
| 934 | hash.w[2] ^= rol32(hash.w[2], 16); | 853 | hash[2] ^= rol32(hash[2], 16); |
| 935 | 854 | memcpy(out, hash, EXTRACT_SIZE); | |
| 936 | /* | 855 | memset(hash, 0, sizeof(hash)); |
| 937 | * If we have a architectural hardware random number | ||
| 938 | * generator, mix that in, too. | ||
| 939 | */ | ||
| 940 | for (i = 0; i < LONGS(EXTRACT_SIZE); i++) { | ||
| 941 | unsigned long v; | ||
| 942 | if (!arch_get_random_long(&v)) | ||
| 943 | break; | ||
| 944 | hash.l[i] ^= v; | ||
| 945 | } | ||
| 946 | |||
| 947 | memcpy(out, &hash, EXTRACT_SIZE); | ||
| 948 | memset(&hash, 0, sizeof(hash)); | ||
| 949 | } | 856 | } |
| 950 | 857 | ||
| 951 | static ssize_t extract_entropy(struct entropy_store *r, void *buf, | 858 | static ssize_t extract_entropy(struct entropy_store *r, void *buf, |
| 952 | size_t nbytes, int min, int reserved) | 859 | size_t nbytes, int min, int reserved) |
| 953 | { | 860 | { |
| 954 | ssize_t ret = 0, i; | 861 | ssize_t ret = 0, i; |
| 955 | __u8 tmp[EXTRACT_SIZE]; | 862 | __u8 tmp[EXTRACT_SIZE]; |
| 863 | unsigned long flags; | ||
| 956 | 864 | ||
| 957 | /* if last_data isn't primed, we need EXTRACT_SIZE extra bytes */ | ||
| 958 | if (fips_enabled && !r->last_data_init) | ||
| 959 | nbytes += EXTRACT_SIZE; | ||
| 960 | |||
| 961 | trace_extract_entropy(r->name, nbytes, r->entropy_count, _RET_IP_); | ||
| 962 | xfer_secondary_pool(r, nbytes); | 865 | xfer_secondary_pool(r, nbytes); |
| 963 | nbytes = account(r, nbytes, min, reserved); | 866 | nbytes = account(r, nbytes, min, reserved); |
| 964 | 867 | ||
| @@ -966,19 +869,6 @@ static ssize_t extract_entropy(struct entropy_store *r, void *buf, | |||
| 966 | extract_buf(r, tmp); | 869 | extract_buf(r, tmp); |
| 967 | 870 | ||
| 968 | if (fips_enabled) { | 871 | if (fips_enabled) { |
| 969 | unsigned long flags; | ||
| 970 | |||
| 971 | |||
| 972 | /* prime last_data value if need be, per fips 140-2 */ | ||
| 973 | if (!r->last_data_init) { | ||
| 974 | spin_lock_irqsave(&r->lock, flags); | ||
| 975 | memcpy(r->last_data, tmp, EXTRACT_SIZE); | ||
| 976 | r->last_data_init = true; | ||
| 977 | nbytes -= EXTRACT_SIZE; | ||
| 978 | spin_unlock_irqrestore(&r->lock, flags); | ||
| 979 | extract_buf(r, tmp); | ||
| 980 | } | ||
| 981 | |||
| 982 | spin_lock_irqsave(&r->lock, flags); | 872 | spin_lock_irqsave(&r->lock, flags); |
| 983 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) | 873 | if (!memcmp(tmp, r->last_data, EXTRACT_SIZE)) |
| 984 | panic("Hardware RNG duplicated output!\n"); | 874 | panic("Hardware RNG duplicated output!\n"); |
| @@ -1004,7 +894,6 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, | |||
| 1004 | ssize_t ret = 0, i; | 894 | ssize_t ret = 0, i; |
| 1005 | __u8 tmp[EXTRACT_SIZE]; | 895 | __u8 tmp[EXTRACT_SIZE]; |
| 1006 | 896 | ||
| 1007 | trace_extract_entropy_user(r->name, nbytes, r->entropy_count, _RET_IP_); | ||
| 1008 | xfer_secondary_pool(r, nbytes); | 897 | xfer_secondary_pool(r, nbytes); |
| 1009 | nbytes = account(r, nbytes, 0, 0); | 898 | nbytes = account(r, nbytes, 0, 0); |
| 1010 | 899 | ||
| @@ -1038,9 +927,8 @@ static ssize_t extract_entropy_user(struct entropy_store *r, void __user *buf, | |||
| 1038 | 927 | ||
| 1039 | /* | 928 | /* |
| 1040 | * This function is the exported kernel interface. It returns some | 929 | * This function is the exported kernel interface. It returns some |
| 1041 | * number of good random numbers, suitable for key generation, seeding | 930 | * number of good random numbers, suitable for seeding TCP sequence |
| 1042 | * TCP sequence numbers, etc. It does not use the hw random number | 931 | * numbers, etc. |
| 1043 | * generator, if available; use get_random_bytes_arch() for that. | ||
| 1044 | */ | 932 | */ |
| 1045 | void get_random_bytes(void *buf, int nbytes) | 933 | void get_random_bytes(void *buf, int nbytes) |
| 1046 | { | 934 | { |
| @@ -1049,39 +937,6 @@ void get_random_bytes(void *buf, int nbytes) | |||
| 1049 | EXPORT_SYMBOL(get_random_bytes); | 937 | EXPORT_SYMBOL(get_random_bytes); |
| 1050 | 938 | ||
| 1051 | /* | 939 | /* |
| 1052 | * This function will use the architecture-specific hardware random | ||
| 1053 | * number generator if it is available. The arch-specific hw RNG will | ||
| 1054 | * almost certainly be faster than what we can do in software, but it | ||
| 1055 | * is impossible to verify that it is implemented securely (as | ||
| 1056 | * opposed, to, say, the AES encryption of a sequence number using a | ||
| 1057 | * key known by the NSA). So it's useful if we need the speed, but | ||
| 1058 | * only if we're willing to trust the hardware manufacturer not to | ||
| 1059 | * have put in a back door. | ||
| 1060 | */ | ||
| 1061 | void get_random_bytes_arch(void *buf, int nbytes) | ||
| 1062 | { | ||
| 1063 | char *p = buf; | ||
| 1064 | |||
| 1065 | trace_get_random_bytes(nbytes, _RET_IP_); | ||
| 1066 | while (nbytes) { | ||
| 1067 | unsigned long v; | ||
| 1068 | int chunk = min(nbytes, (int)sizeof(unsigned long)); | ||
| 1069 | |||
| 1070 | if (!arch_get_random_long(&v)) | ||
| 1071 | break; | ||
| 1072 | |||
| 1073 | memcpy(p, &v, chunk); | ||
| 1074 | p += chunk; | ||
| 1075 | nbytes -= chunk; | ||
| 1076 | } | ||
| 1077 | |||
| 1078 | if (nbytes) | ||
| 1079 | extract_entropy(&nonblocking_pool, p, nbytes, 0, 0); | ||
| 1080 | } | ||
| 1081 | EXPORT_SYMBOL(get_random_bytes_arch); | ||
| 1082 | |||
| 1083 | |||
| 1084 | /* | ||
| 1085 | * init_std_data - initialize pool with system data | 940 | * init_std_data - initialize pool with system data |
| 1086 | * | 941 | * |
| 1087 | * @r: pool to initialize | 942 | * @r: pool to initialize |
| @@ -1092,32 +947,18 @@ EXPORT_SYMBOL(get_random_bytes_arch); | |||
| 1092 | */ | 947 | */ |
| 1093 | static void init_std_data(struct entropy_store *r) | 948 | static void init_std_data(struct entropy_store *r) |
| 1094 | { | 949 | { |
| 1095 | int i; | 950 | ktime_t now; |
| 1096 | ktime_t now = ktime_get_real(); | 951 | unsigned long flags; |
| 1097 | unsigned long rv; | ||
| 1098 | 952 | ||
| 953 | spin_lock_irqsave(&r->lock, flags); | ||
| 1099 | r->entropy_count = 0; | 954 | r->entropy_count = 0; |
| 1100 | r->entropy_total = 0; | 955 | spin_unlock_irqrestore(&r->lock, flags); |
| 1101 | r->last_data_init = false; | 956 | |
| 1102 | mix_pool_bytes(r, &now, sizeof(now), NULL); | 957 | now = ktime_get_real(); |
| 1103 | for (i = r->poolinfo->POOLBYTES; i > 0; i -= sizeof(rv)) { | 958 | mix_pool_bytes(r, &now, sizeof(now)); |
| 1104 | if (!arch_get_random_long(&rv)) | 959 | mix_pool_bytes(r, utsname(), sizeof(*(utsname()))); |
| 1105 | break; | ||
| 1106 | mix_pool_bytes(r, &rv, sizeof(rv), NULL); | ||
| 1107 | } | ||
| 1108 | mix_pool_bytes(r, utsname(), sizeof(*(utsname())), NULL); | ||
| 1109 | } | 960 | } |
| 1110 | 961 | ||
| 1111 | /* | ||
| 1112 | * Note that setup_arch() may call add_device_randomness() | ||
| 1113 | * long before we get here. This allows seeding of the pools | ||
| 1114 | * with some platform dependent data very early in the boot | ||
| 1115 | * process. But it limits our options here. We must use | ||
| 1116 | * statically allocated structures that already have all | ||
| 1117 | * initializations complete at compile time. We should also | ||
| 1118 | * take care not to overwrite the precious per platform data | ||
| 1119 | * we were given. | ||
| 1120 | */ | ||
| 1121 | static int rand_initialize(void) | 962 | static int rand_initialize(void) |
| 1122 | { | 963 | { |
| 1123 | init_std_data(&input_pool); | 964 | init_std_data(&input_pool); |
| @@ -1127,6 +968,24 @@ static int rand_initialize(void) | |||
| 1127 | } | 968 | } |
| 1128 | module_init(rand_initialize); | 969 | module_init(rand_initialize); |
| 1129 | 970 | ||
| 971 | void rand_initialize_irq(int irq) | ||
| 972 | { | ||
| 973 | struct timer_rand_state *state; | ||
| 974 | |||
| 975 | state = get_timer_rand_state(irq); | ||
| 976 | |||
| 977 | if (state) | ||
| 978 | return; | ||
| 979 | |||
| 980 | /* | ||
| 981 | * If kzalloc returns null, we just won't use that entropy | ||
| 982 | * source. | ||
| 983 | */ | ||
| 984 | state = kzalloc(sizeof(struct timer_rand_state), GFP_KERNEL); | ||
| 985 | if (state) | ||
| 986 | set_timer_rand_state(irq, state); | ||
| 987 | } | ||
| 988 | |||
| 1130 | #ifdef CONFIG_BLOCK | 989 | #ifdef CONFIG_BLOCK |
| 1131 | void rand_initialize_disk(struct gendisk *disk) | 990 | void rand_initialize_disk(struct gendisk *disk) |
| 1132 | { | 991 | { |
| @@ -1155,16 +1014,11 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
| 1155 | if (n > SEC_XFER_SIZE) | 1014 | if (n > SEC_XFER_SIZE) |
| 1156 | n = SEC_XFER_SIZE; | 1015 | n = SEC_XFER_SIZE; |
| 1157 | 1016 | ||
| 1158 | DEBUG_ENT("reading %zu bits\n", n*8); | 1017 | DEBUG_ENT("reading %d bits\n", n*8); |
| 1159 | 1018 | ||
| 1160 | n = extract_entropy_user(&blocking_pool, buf, n); | 1019 | n = extract_entropy_user(&blocking_pool, buf, n); |
| 1161 | 1020 | ||
| 1162 | if (n < 0) { | 1021 | DEBUG_ENT("read got %d bits (%d still needed)\n", |
| 1163 | retval = n; | ||
| 1164 | break; | ||
| 1165 | } | ||
| 1166 | |||
| 1167 | DEBUG_ENT("read got %zd bits (%zd still needed)\n", | ||
| 1168 | n*8, (nbytes-n)*8); | 1022 | n*8, (nbytes-n)*8); |
| 1169 | 1023 | ||
| 1170 | if (n == 0) { | 1024 | if (n == 0) { |
| @@ -1189,6 +1043,10 @@ random_read(struct file *file, char __user *buf, size_t nbytes, loff_t *ppos) | |||
| 1189 | continue; | 1043 | continue; |
| 1190 | } | 1044 | } |
| 1191 | 1045 | ||
| 1046 | if (n < 0) { | ||
| 1047 | retval = n; | ||
| 1048 | break; | ||
| 1049 | } | ||
| 1192 | count += n; | 1050 | count += n; |
| 1193 | buf += n; | 1051 | buf += n; |
| 1194 | nbytes -= n; | 1052 | nbytes -= n; |
| @@ -1235,7 +1093,7 @@ write_pool(struct entropy_store *r, const char __user *buffer, size_t count) | |||
| 1235 | count -= bytes; | 1093 | count -= bytes; |
| 1236 | p += bytes; | 1094 | p += bytes; |
| 1237 | 1095 | ||
| 1238 | mix_pool_bytes(r, buf, bytes, NULL); | 1096 | mix_pool_bytes(r, buf, bytes); |
| 1239 | cond_resched(); | 1097 | cond_resched(); |
| 1240 | } | 1098 | } |
| 1241 | 1099 | ||
| @@ -1378,15 +1236,10 @@ static int proc_do_uuid(ctl_table *table, int write, | |||
| 1378 | uuid = table->data; | 1236 | uuid = table->data; |
| 1379 | if (!uuid) { | 1237 | if (!uuid) { |
| 1380 | uuid = tmp_uuid; | 1238 | uuid = tmp_uuid; |
| 1381 | generate_random_uuid(uuid); | 1239 | uuid[8] = 0; |
| 1382 | } else { | ||
| 1383 | static DEFINE_SPINLOCK(bootid_spinlock); | ||
| 1384 | |||
| 1385 | spin_lock(&bootid_spinlock); | ||
| 1386 | if (!uuid[8]) | ||
| 1387 | generate_random_uuid(uuid); | ||
| 1388 | spin_unlock(&bootid_spinlock); | ||
| 1389 | } | 1240 | } |
| 1241 | if (uuid[8] == 0) | ||
| 1242 | generate_random_uuid(uuid); | ||
| 1390 | 1243 | ||
| 1391 | sprintf(buf, "%pU", uuid); | 1244 | sprintf(buf, "%pU", uuid); |
| 1392 | 1245 | ||
| @@ -1397,7 +1250,6 @@ static int proc_do_uuid(ctl_table *table, int write, | |||
| 1397 | } | 1250 | } |
| 1398 | 1251 | ||
| 1399 | static int sysctl_poolsize = INPUT_POOL_WORDS * 32; | 1252 | static int sysctl_poolsize = INPUT_POOL_WORDS * 32; |
| 1400 | extern ctl_table random_table[]; | ||
| 1401 | ctl_table random_table[] = { | 1253 | ctl_table random_table[] = { |
| 1402 | { | 1254 | { |
| 1403 | .procname = "poolsize", | 1255 | .procname = "poolsize", |
| @@ -1463,17 +1315,12 @@ late_initcall(random_int_secret_init); | |||
| 1463 | * value is not cryptographically secure but for several uses the cost of | 1315 | * value is not cryptographically secure but for several uses the cost of |
| 1464 | * depleting entropy is too high | 1316 | * depleting entropy is too high |
| 1465 | */ | 1317 | */ |
| 1466 | static DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); | 1318 | DEFINE_PER_CPU(__u32 [MD5_DIGEST_WORDS], get_random_int_hash); |
| 1467 | unsigned int get_random_int(void) | 1319 | unsigned int get_random_int(void) |
| 1468 | { | 1320 | { |
| 1469 | __u32 *hash; | 1321 | __u32 *hash = get_cpu_var(get_random_int_hash); |
| 1470 | unsigned int ret; | 1322 | unsigned int ret; |
| 1471 | 1323 | ||
| 1472 | if (arch_get_random_int(&ret)) | ||
| 1473 | return ret; | ||
| 1474 | |||
| 1475 | hash = get_cpu_var(get_random_int_hash); | ||
| 1476 | |||
| 1477 | hash[0] += current->pid + jiffies + get_cycles(); | 1324 | hash[0] += current->pid + jiffies + get_cycles(); |
| 1478 | md5_transform(hash, random_int_secret); | 1325 | md5_transform(hash, random_int_secret); |
| 1479 | ret = hash[0]; | 1326 | ret = hash[0]; |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 54a3a6d0981..b33e8ea314e 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
| @@ -308,7 +308,7 @@ static const struct file_operations raw_ctl_fops = { | |||
| 308 | 308 | ||
| 309 | static struct cdev raw_cdev; | 309 | static struct cdev raw_cdev; |
| 310 | 310 | ||
| 311 | static char *raw_devnode(struct device *dev, umode_t *mode) | 311 | static char *raw_devnode(struct device *dev, mode_t *mode) |
| 312 | { | 312 | { |
| 313 | return kasprintf(GFP_KERNEL, "raw/%s", dev_name(dev)); | 313 | return kasprintf(GFP_KERNEL, "raw/%s", dev_name(dev)); |
| 314 | } | 314 | } |
| @@ -324,12 +324,13 @@ static int __init raw_init(void) | |||
| 324 | max_raw_minors = MAX_RAW_MINORS; | 324 | max_raw_minors = MAX_RAW_MINORS; |
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | raw_devices = vzalloc(sizeof(struct raw_device_data) * max_raw_minors); | 327 | raw_devices = vmalloc(sizeof(struct raw_device_data) * max_raw_minors); |
| 328 | if (!raw_devices) { | 328 | if (!raw_devices) { |
| 329 | printk(KERN_ERR "Not enough memory for raw device structures\n"); | 329 | printk(KERN_ERR "Not enough memory for raw device structures\n"); |
| 330 | ret = -ENOMEM; | 330 | ret = -ENOMEM; |
| 331 | goto error; | 331 | goto error; |
| 332 | } | 332 | } |
| 333 | memset(raw_devices, 0, sizeof(struct raw_device_data) * max_raw_minors); | ||
| 333 | 334 | ||
| 334 | ret = register_chrdev_region(dev, max_raw_minors, "raw"); | 335 | ret = register_chrdev_region(dev, max_raw_minors, "raw"); |
| 335 | if (ret) | 336 | if (ret) |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index 91470fdbab2..dfa8b3062fd 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
| @@ -57,8 +57,8 @@ | |||
| 57 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with | 57 | * Note that *all* calls to CMOS_READ and CMOS_WRITE are done with |
| 58 | * interrupts disabled. Due to the index-port/data-port (0x70/0x71) | 58 | * interrupts disabled. Due to the index-port/data-port (0x70/0x71) |
| 59 | * design of the RTC, we don't want two different things trying to | 59 | * design of the RTC, we don't want two different things trying to |
| 60 | * get to it at once. (e.g. the periodic 11 min sync from | 60 | * get to it at once. (e.g. the periodic 11 min sync from time.c vs. |
| 61 | * kernel/time/ntp.c vs. this driver.) | 61 | * this driver.) |
| 62 | */ | 62 | */ |
| 63 | 63 | ||
| 64 | #include <linux/interrupt.h> | 64 | #include <linux/interrupt.h> |
| @@ -80,9 +80,9 @@ | |||
| 80 | #include <linux/bcd.h> | 80 | #include <linux/bcd.h> |
| 81 | #include <linux/delay.h> | 81 | #include <linux/delay.h> |
| 82 | #include <linux/uaccess.h> | 82 | #include <linux/uaccess.h> |
| 83 | #include <linux/ratelimit.h> | ||
| 84 | 83 | ||
| 85 | #include <asm/current.h> | 84 | #include <asm/current.h> |
| 85 | #include <asm/system.h> | ||
| 86 | 86 | ||
| 87 | #ifdef CONFIG_X86 | 87 | #ifdef CONFIG_X86 |
| 88 | #include <asm/hpet.h> | 88 | #include <asm/hpet.h> |
| @@ -411,7 +411,7 @@ static int rtc_do_ioctl(unsigned int cmd, unsigned long arg, int kernel) | |||
| 411 | case RTC_IRQP_READ: | 411 | case RTC_IRQP_READ: |
| 412 | case RTC_IRQP_SET: | 412 | case RTC_IRQP_SET: |
| 413 | return -EINVAL; | 413 | return -EINVAL; |
| 414 | } | 414 | }; |
| 415 | } | 415 | } |
| 416 | #endif | 416 | #endif |
| 417 | 417 | ||
| @@ -1195,8 +1195,10 @@ static void rtc_dropped_irq(unsigned long data) | |||
| 1195 | 1195 | ||
| 1196 | spin_unlock_irq(&rtc_lock); | 1196 | spin_unlock_irq(&rtc_lock); |
| 1197 | 1197 | ||
| 1198 | printk_ratelimited(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", | 1198 | if (printk_ratelimit()) { |
| 1199 | freq); | 1199 | printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n", |
| 1200 | freq); | ||
| 1201 | } | ||
| 1200 | 1202 | ||
| 1201 | /* Now we have new data */ | 1203 | /* Now we have new data */ |
| 1202 | wake_up_interruptible(&rtc_wait); | 1204 | wake_up_interruptible(&rtc_wait); |
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c index d780295a147..1ee8ce7d276 100644 --- a/drivers/char/sonypi.c +++ b/drivers/char/sonypi.c | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | 54 | ||
| 55 | #include <asm/uaccess.h> | 55 | #include <asm/uaccess.h> |
| 56 | #include <asm/io.h> | 56 | #include <asm/io.h> |
| 57 | #include <asm/system.h> | ||
| 57 | 58 | ||
| 58 | #include <linux/sonypi.h> | 59 | #include <linux/sonypi.h> |
| 59 | 60 | ||
| @@ -1164,7 +1165,7 @@ static struct acpi_driver sonypi_acpi_driver = { | |||
| 1164 | }; | 1165 | }; |
| 1165 | #endif | 1166 | #endif |
| 1166 | 1167 | ||
| 1167 | static int sonypi_create_input_devices(struct platform_device *pdev) | 1168 | static int __devinit sonypi_create_input_devices(struct platform_device *pdev) |
| 1168 | { | 1169 | { |
| 1169 | struct input_dev *jog_dev; | 1170 | struct input_dev *jog_dev; |
| 1170 | struct input_dev *key_dev; | 1171 | struct input_dev *key_dev; |
| @@ -1225,7 +1226,7 @@ static int sonypi_create_input_devices(struct platform_device *pdev) | |||
| 1225 | return error; | 1226 | return error; |
| 1226 | } | 1227 | } |
| 1227 | 1228 | ||
| 1228 | static int sonypi_setup_ioports(struct sonypi_device *dev, | 1229 | static int __devinit sonypi_setup_ioports(struct sonypi_device *dev, |
| 1229 | const struct sonypi_ioport_list *ioport_list) | 1230 | const struct sonypi_ioport_list *ioport_list) |
| 1230 | { | 1231 | { |
| 1231 | /* try to detect if sony-laptop is being used and thus | 1232 | /* try to detect if sony-laptop is being used and thus |
| @@ -1265,7 +1266,7 @@ static int sonypi_setup_ioports(struct sonypi_device *dev, | |||
| 1265 | return -EBUSY; | 1266 | return -EBUSY; |
| 1266 | } | 1267 | } |
| 1267 | 1268 | ||
| 1268 | static int sonypi_setup_irq(struct sonypi_device *dev, | 1269 | static int __devinit sonypi_setup_irq(struct sonypi_device *dev, |
| 1269 | const struct sonypi_irq_list *irq_list) | 1270 | const struct sonypi_irq_list *irq_list) |
| 1270 | { | 1271 | { |
| 1271 | while (irq_list->irq) { | 1272 | while (irq_list->irq) { |
| @@ -1282,7 +1283,7 @@ static int sonypi_setup_irq(struct sonypi_device *dev, | |||
| 1282 | return -EBUSY; | 1283 | return -EBUSY; |
| 1283 | } | 1284 | } |
| 1284 | 1285 | ||
| 1285 | static void sonypi_display_info(void) | 1286 | static void __devinit sonypi_display_info(void) |
| 1286 | { | 1287 | { |
| 1287 | printk(KERN_INFO "sonypi: detected type%d model, " | 1288 | printk(KERN_INFO "sonypi: detected type%d model, " |
| 1288 | "verbose = %d, fnkeyinit = %s, camera = %s, " | 1289 | "verbose = %d, fnkeyinit = %s, camera = %s, " |
| @@ -1304,7 +1305,7 @@ static void sonypi_display_info(void) | |||
| 1304 | sonypi_misc_device.minor); | 1305 | sonypi_misc_device.minor); |
| 1305 | } | 1306 | } |
| 1306 | 1307 | ||
| 1307 | static int sonypi_probe(struct platform_device *dev) | 1308 | static int __devinit sonypi_probe(struct platform_device *dev) |
| 1308 | { | 1309 | { |
| 1309 | const struct sonypi_ioport_list *ioport_list; | 1310 | const struct sonypi_ioport_list *ioport_list; |
| 1310 | const struct sonypi_irq_list *irq_list; | 1311 | const struct sonypi_irq_list *irq_list; |
| @@ -1428,12 +1429,12 @@ static int sonypi_probe(struct platform_device *dev) | |||
| 1428 | return error; | 1429 | return error; |
| 1429 | } | 1430 | } |
| 1430 | 1431 | ||
| 1431 | static int sonypi_remove(struct platform_device *dev) | 1432 | static int __devexit sonypi_remove(struct platform_device *dev) |
| 1432 | { | 1433 | { |
| 1433 | sonypi_disable(); | 1434 | sonypi_disable(); |
| 1434 | 1435 | ||
| 1435 | synchronize_irq(sonypi_device.irq); | 1436 | synchronize_irq(sonypi_device.irq); |
| 1436 | flush_work(&sonypi_device.input_work); | 1437 | flush_work_sync(&sonypi_device.input_work); |
| 1437 | 1438 | ||
| 1438 | if (useinput) { | 1439 | if (useinput) { |
| 1439 | input_unregister_device(sonypi_device.input_key_dev); | 1440 | input_unregister_device(sonypi_device.input_key_dev); |
| @@ -1456,10 +1457,10 @@ static int sonypi_remove(struct platform_device *dev) | |||
| 1456 | return 0; | 1457 | return 0; |
| 1457 | } | 1458 | } |
| 1458 | 1459 | ||
| 1459 | #ifdef CONFIG_PM_SLEEP | 1460 | #ifdef CONFIG_PM |
| 1460 | static int old_camera_power; | 1461 | static int old_camera_power; |
| 1461 | 1462 | ||
| 1462 | static int sonypi_suspend(struct device *dev) | 1463 | static int sonypi_suspend(struct platform_device *dev, pm_message_t state) |
| 1463 | { | 1464 | { |
| 1464 | old_camera_power = sonypi_device.camera_power; | 1465 | old_camera_power = sonypi_device.camera_power; |
| 1465 | sonypi_disable(); | 1466 | sonypi_disable(); |
| @@ -1467,16 +1468,14 @@ static int sonypi_suspend(struct device *dev) | |||
| 1467 | return 0; | 1468 | return 0; |
| 1468 | } | 1469 | } |
| 1469 | 1470 | ||
| 1470 | static int sonypi_resume(struct device *dev) | 1471 | static int sonypi_resume(struct platform_device *dev) |
| 1471 | { | 1472 | { |
| 1472 | sonypi_enable(old_camera_power); | 1473 | sonypi_enable(old_camera_power); |
| 1473 | return 0; | 1474 | return 0; |
| 1474 | } | 1475 | } |
| 1475 | |||
| 1476 | static SIMPLE_DEV_PM_OPS(sonypi_pm, sonypi_suspend, sonypi_resume); | ||
| 1477 | #define SONYPI_PM (&sonypi_pm) | ||
| 1478 | #else | 1476 | #else |
| 1479 | #define SONYPI_PM NULL | 1477 | #define sonypi_suspend NULL |
| 1478 | #define sonypi_resume NULL | ||
| 1480 | #endif | 1479 | #endif |
| 1481 | 1480 | ||
| 1482 | static void sonypi_shutdown(struct platform_device *dev) | 1481 | static void sonypi_shutdown(struct platform_device *dev) |
| @@ -1488,11 +1487,12 @@ static struct platform_driver sonypi_driver = { | |||
| 1488 | .driver = { | 1487 | .driver = { |
| 1489 | .name = "sonypi", | 1488 | .name = "sonypi", |
| 1490 | .owner = THIS_MODULE, | 1489 | .owner = THIS_MODULE, |
| 1491 | .pm = SONYPI_PM, | ||
| 1492 | }, | 1490 | }, |
| 1493 | .probe = sonypi_probe, | 1491 | .probe = sonypi_probe, |
| 1494 | .remove = sonypi_remove, | 1492 | .remove = __devexit_p(sonypi_remove), |
| 1495 | .shutdown = sonypi_shutdown, | 1493 | .shutdown = sonypi_shutdown, |
| 1494 | .suspend = sonypi_suspend, | ||
| 1495 | .resume = sonypi_resume, | ||
| 1496 | }; | 1496 | }; |
| 1497 | 1497 | ||
| 1498 | static struct platform_device *sonypi_platform_device; | 1498 | static struct platform_device *sonypi_platform_device; |
diff --git a/drivers/char/tb0219.c b/drivers/char/tb0219.c index 34c63f85104..ad264185eb1 100644 --- a/drivers/char/tb0219.c +++ b/drivers/char/tb0219.c | |||
| @@ -284,7 +284,7 @@ static void tb0219_pci_irq_init(void) | |||
| 284 | vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW); | 284 | vr41xx_set_irq_level(TB0219_PCI_SLOT3_PIN, IRQ_LEVEL_LOW); |
| 285 | } | 285 | } |
| 286 | 286 | ||
| 287 | static int tb0219_probe(struct platform_device *dev) | 287 | static int __devinit tb0219_probe(struct platform_device *dev) |
| 288 | { | 288 | { |
| 289 | int retval; | 289 | int retval; |
| 290 | 290 | ||
| @@ -318,7 +318,7 @@ static int tb0219_probe(struct platform_device *dev) | |||
| 318 | return 0; | 318 | return 0; |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | static int tb0219_remove(struct platform_device *dev) | 321 | static int __devexit tb0219_remove(struct platform_device *dev) |
| 322 | { | 322 | { |
| 323 | _machine_restart = old_machine_restart; | 323 | _machine_restart = old_machine_restart; |
| 324 | 324 | ||
| @@ -334,7 +334,7 @@ static struct platform_device *tb0219_platform_device; | |||
| 334 | 334 | ||
| 335 | static struct platform_driver tb0219_device_driver = { | 335 | static struct platform_driver tb0219_device_driver = { |
| 336 | .probe = tb0219_probe, | 336 | .probe = tb0219_probe, |
| 337 | .remove = tb0219_remove, | 337 | .remove = __devexit_p(tb0219_remove), |
| 338 | .driver = { | 338 | .driver = { |
| 339 | .name = "TB0219", | 339 | .name = "TB0219", |
| 340 | .owner = THIS_MODULE, | 340 | .owner = THIS_MODULE, |
diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c index 3b22a606f79..cf3ee008dca 100644 --- a/drivers/char/tile-srom.c +++ b/drivers/char/tile-srom.c | |||
| @@ -194,17 +194,17 @@ static ssize_t srom_read(struct file *filp, char __user *buf, | |||
| 194 | 194 | ||
| 195 | hv_retval = _srom_read(srom->hv_devhdl, kernbuf, | 195 | hv_retval = _srom_read(srom->hv_devhdl, kernbuf, |
| 196 | *f_pos, bytes_this_pass); | 196 | *f_pos, bytes_this_pass); |
| 197 | if (hv_retval <= 0) { | 197 | if (hv_retval > 0) { |
| 198 | if (copy_to_user(buf, kernbuf, hv_retval) != 0) { | ||
| 199 | retval = -EFAULT; | ||
| 200 | break; | ||
| 201 | } | ||
| 202 | } else if (hv_retval <= 0) { | ||
| 198 | if (retval == 0) | 203 | if (retval == 0) |
| 199 | retval = hv_retval; | 204 | retval = hv_retval; |
| 200 | break; | 205 | break; |
| 201 | } | 206 | } |
| 202 | 207 | ||
| 203 | if (copy_to_user(buf, kernbuf, hv_retval) != 0) { | ||
| 204 | retval = -EFAULT; | ||
| 205 | break; | ||
| 206 | } | ||
| 207 | |||
| 208 | retval += hv_retval; | 208 | retval += hv_retval; |
| 209 | *f_pos += hv_retval; | 209 | *f_pos += hv_retval; |
| 210 | buf += hv_retval; | 210 | buf += hv_retval; |
| @@ -329,7 +329,7 @@ static struct device_attribute srom_dev_attrs[] = { | |||
| 329 | __ATTR_NULL | 329 | __ATTR_NULL |
| 330 | }; | 330 | }; |
| 331 | 331 | ||
| 332 | static char *srom_devnode(struct device *dev, umode_t *mode) | 332 | static char *srom_devnode(struct device *dev, mode_t *mode) |
| 333 | { | 333 | { |
| 334 | *mode = S_IRUGO | S_IWUSR; | 334 | *mode = S_IRUGO | S_IWUSR; |
| 335 | return kasprintf(GFP_KERNEL, "srom/%s", dev_name(dev)); | 335 | return kasprintf(GFP_KERNEL, "srom/%s", dev_name(dev)); |
diff --git a/drivers/char/tlclk.c b/drivers/char/tlclk.c index e95e0ab0bd8..0c964cdcc22 100644 --- a/drivers/char/tlclk.c +++ b/drivers/char/tlclk.c | |||
| @@ -784,10 +784,8 @@ static int __init tlclk_init(void) | |||
| 784 | } | 784 | } |
| 785 | tlclk_major = ret; | 785 | tlclk_major = ret; |
| 786 | alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL); | 786 | alarm_events = kzalloc( sizeof(struct tlclk_alarms), GFP_KERNEL); |
| 787 | if (!alarm_events) { | 787 | if (!alarm_events) |
| 788 | ret = -ENOMEM; | ||
| 789 | goto out1; | 788 | goto out1; |
| 790 | } | ||
| 791 | 789 | ||
| 792 | /* Read telecom clock IRQ number (Set by BIOS) */ | 790 | /* Read telecom clock IRQ number (Set by BIOS) */ |
| 793 | if (!request_region(TLCLK_BASE, 8, "telco_clock")) { | 791 | if (!request_region(TLCLK_BASE, 8, "telco_clock")) { |
| @@ -799,7 +797,7 @@ static int __init tlclk_init(void) | |||
| 799 | telclk_interrupt = (inb(TLCLK_REG7) & 0x0f); | 797 | telclk_interrupt = (inb(TLCLK_REG7) & 0x0f); |
| 800 | 798 | ||
| 801 | if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */ | 799 | if (0x0F == telclk_interrupt ) { /* not MCPBL0010 ? */ |
| 802 | printk(KERN_ERR "telclk_interrupt = 0x%x non-mcpbl0010 hw.\n", | 800 | printk(KERN_ERR "telclk_interrup = 0x%x non-mcpbl0010 hw.\n", |
| 803 | telclk_interrupt); | 801 | telclk_interrupt); |
| 804 | ret = -ENXIO; | 802 | ret = -ENXIO; |
| 805 | goto out3; | 803 | goto out3; |
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig index 915875e431d..fa567f1158c 100644 --- a/drivers/char/tpm/Kconfig +++ b/drivers/char/tpm/Kconfig | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | menuconfig TCG_TPM | 5 | menuconfig TCG_TPM |
| 6 | tristate "TPM Hardware Support" | 6 | tristate "TPM Hardware Support" |
| 7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
| 8 | depends on EXPERIMENTAL | ||
| 8 | select SECURITYFS | 9 | select SECURITYFS |
| 9 | ---help--- | 10 | ---help--- |
| 10 | If you have a TPM security chip in your system, which | 11 | If you have a TPM security chip in your system, which |
| @@ -26,27 +27,14 @@ if TCG_TPM | |||
| 26 | 27 | ||
| 27 | config TCG_TIS | 28 | config TCG_TIS |
| 28 | tristate "TPM Interface Specification 1.2 Interface" | 29 | tristate "TPM Interface Specification 1.2 Interface" |
| 29 | depends on X86 | ||
| 30 | ---help--- | 30 | ---help--- |
| 31 | If you have a TPM security chip that is compliant with the | 31 | If you have a TPM security chip that is compliant with the |
| 32 | TCG TIS 1.2 TPM specification say Yes and it will be accessible | 32 | TCG TIS 1.2 TPM specification say Yes and it will be accessible |
| 33 | from within Linux. To compile this driver as a module, choose | 33 | from within Linux. To compile this driver as a module, choose |
| 34 | M here; the module will be called tpm_tis. | 34 | M here; the module will be called tpm_tis. |
| 35 | 35 | ||
| 36 | config TCG_TIS_I2C_INFINEON | ||
| 37 | tristate "TPM Interface Specification 1.2 Interface (I2C - Infineon)" | ||
| 38 | depends on I2C | ||
| 39 | ---help--- | ||
| 40 | If you have a TPM security chip that is compliant with the | ||
| 41 | TCG TIS 1.2 TPM specification and Infineon's I2C Protocol Stack | ||
| 42 | Specification 0.20 say Yes and it will be accessible from within | ||
| 43 | Linux. | ||
| 44 | To compile this driver as a module, choose M here; the module | ||
| 45 | will be called tpm_tis_i2c_infineon. | ||
| 46 | |||
| 47 | config TCG_NSC | 36 | config TCG_NSC |
| 48 | tristate "National Semiconductor TPM Interface" | 37 | tristate "National Semiconductor TPM Interface" |
| 49 | depends on X86 | ||
| 50 | ---help--- | 38 | ---help--- |
| 51 | If you have a TPM security chip from National Semiconductor | 39 | If you have a TPM security chip from National Semiconductor |
| 52 | say Yes and it will be accessible from within Linux. To | 40 | say Yes and it will be accessible from within Linux. To |
| @@ -73,12 +61,4 @@ config TCG_INFINEON | |||
| 73 | Further information on this driver and the supported hardware | 61 | Further information on this driver and the supported hardware |
| 74 | can be found at http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ | 62 | can be found at http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ |
| 75 | 63 | ||
| 76 | config TCG_IBMVTPM | ||
| 77 | tristate "IBM VTPM Interface" | ||
| 78 | depends on PPC64 | ||
| 79 | ---help--- | ||
| 80 | If you have IBM virtual TPM (VTPM) support say Yes and it | ||
| 81 | will be accessible from within Linux. To compile this driver | ||
| 82 | as a module, choose M here; the module will be called tpm_ibmvtpm. | ||
| 83 | |||
| 84 | endif # TCG_TPM | 64 | endif # TCG_TPM |
diff --git a/drivers/char/tpm/Makefile b/drivers/char/tpm/Makefile index 5b3fc8bc6c1..ea3a1e02a82 100644 --- a/drivers/char/tpm/Makefile +++ b/drivers/char/tpm/Makefile | |||
| @@ -4,16 +4,8 @@ | |||
| 4 | obj-$(CONFIG_TCG_TPM) += tpm.o | 4 | obj-$(CONFIG_TCG_TPM) += tpm.o |
| 5 | ifdef CONFIG_ACPI | 5 | ifdef CONFIG_ACPI |
| 6 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o | 6 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o |
| 7 | tpm_bios-objs += tpm_eventlog.o tpm_acpi.o tpm_ppi.o | ||
| 8 | else | ||
| 9 | ifdef CONFIG_TCG_IBMVTPM | ||
| 10 | obj-$(CONFIG_TCG_TPM) += tpm_bios.o | ||
| 11 | tpm_bios-objs += tpm_eventlog.o tpm_of.o | ||
| 12 | endif | ||
| 13 | endif | 7 | endif |
| 14 | obj-$(CONFIG_TCG_TIS) += tpm_tis.o | 8 | obj-$(CONFIG_TCG_TIS) += tpm_tis.o |
| 15 | obj-$(CONFIG_TCG_TIS_I2C_INFINEON) += tpm_i2c_infineon.o | ||
| 16 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o | 9 | obj-$(CONFIG_TCG_NSC) += tpm_nsc.o |
| 17 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o | 10 | obj-$(CONFIG_TCG_ATMEL) += tpm_atmel.o |
| 18 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o | 11 | obj-$(CONFIG_TCG_INFINEON) += tpm_infineon.o |
| 19 | obj-$(CONFIG_TCG_IBMVTPM) += tpm_ibmvtpm.o | ||
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c index 93211df52aa..9ca5c021d0b 100644 --- a/drivers/char/tpm/tpm.c +++ b/drivers/char/tpm/tpm.c | |||
| @@ -27,10 +27,14 @@ | |||
| 27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
| 28 | #include <linux/mutex.h> | 28 | #include <linux/mutex.h> |
| 29 | #include <linux/spinlock.h> | 29 | #include <linux/spinlock.h> |
| 30 | #include <linux/freezer.h> | ||
| 31 | 30 | ||
| 32 | #include "tpm.h" | 31 | #include "tpm.h" |
| 33 | #include "tpm_eventlog.h" | 32 | |
| 33 | enum tpm_const { | ||
| 34 | TPM_MINOR = 224, /* officially assigned */ | ||
| 35 | TPM_BUFSIZE = 4096, | ||
| 36 | TPM_NUM_DEVICES = 256, | ||
| 37 | }; | ||
| 34 | 38 | ||
| 35 | enum tpm_duration { | 39 | enum tpm_duration { |
| 36 | TPM_SHORT = 0, | 40 | TPM_SHORT = 0, |
| @@ -436,6 +440,7 @@ out: | |||
| 436 | } | 440 | } |
| 437 | 441 | ||
| 438 | #define TPM_DIGEST_SIZE 20 | 442 | #define TPM_DIGEST_SIZE 20 |
| 443 | #define TPM_ERROR_SIZE 10 | ||
| 439 | #define TPM_RET_CODE_IDX 6 | 444 | #define TPM_RET_CODE_IDX 6 |
| 440 | 445 | ||
| 441 | enum tpm_capabilities { | 446 | enum tpm_capabilities { |
| @@ -464,20 +469,17 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd, | |||
| 464 | len = tpm_transmit(chip,(u8 *) cmd, len); | 469 | len = tpm_transmit(chip,(u8 *) cmd, len); |
| 465 | if (len < 0) | 470 | if (len < 0) |
| 466 | return len; | 471 | return len; |
| 467 | else if (len < TPM_HEADER_SIZE) | 472 | if (len == TPM_ERROR_SIZE) { |
| 468 | return -EFAULT; | 473 | err = be32_to_cpu(cmd->header.out.return_code); |
| 469 | 474 | dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | |
| 470 | err = be32_to_cpu(cmd->header.out.return_code); | 475 | return err; |
| 471 | if (err != 0) | 476 | } |
| 472 | dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc); | 477 | return 0; |
| 473 | |||
| 474 | return err; | ||
| 475 | } | 478 | } |
| 476 | 479 | ||
| 477 | #define TPM_INTERNAL_RESULT_SIZE 200 | 480 | #define TPM_INTERNAL_RESULT_SIZE 200 |
| 478 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) | 481 | #define TPM_TAG_RQU_COMMAND cpu_to_be16(193) |
| 479 | #define TPM_ORD_GET_CAP cpu_to_be32(101) | 482 | #define TPM_ORD_GET_CAP cpu_to_be32(101) |
| 480 | #define TPM_ORD_GET_RANDOM cpu_to_be32(70) | ||
| 481 | 483 | ||
| 482 | static const struct tpm_input_header tpm_getcap_header = { | 484 | static const struct tpm_input_header tpm_getcap_header = { |
| 483 | .tag = TPM_TAG_RQU_COMMAND, | 485 | .tag = TPM_TAG_RQU_COMMAND, |
| @@ -528,7 +530,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip) | |||
| 528 | } | 530 | } |
| 529 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); | 531 | EXPORT_SYMBOL_GPL(tpm_gen_interrupt); |
| 530 | 532 | ||
| 531 | int tpm_get_timeouts(struct tpm_chip *chip) | 533 | void tpm_get_timeouts(struct tpm_chip *chip) |
| 532 | { | 534 | { |
| 533 | struct tpm_cmd_t tpm_cmd; | 535 | struct tpm_cmd_t tpm_cmd; |
| 534 | struct timeout_t *timeout_cap; | 536 | struct timeout_t *timeout_cap; |
| @@ -550,7 +552,7 @@ int tpm_get_timeouts(struct tpm_chip *chip) | |||
| 550 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || | 552 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
| 551 | be32_to_cpu(tpm_cmd.header.out.length) | 553 | be32_to_cpu(tpm_cmd.header.out.length) |
| 552 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) | 554 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32)) |
| 553 | return -EINVAL; | 555 | return; |
| 554 | 556 | ||
| 555 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; | 557 | timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout; |
| 556 | /* Don't overwrite default if value is 0 */ | 558 | /* Don't overwrite default if value is 0 */ |
| @@ -581,12 +583,12 @@ duration: | |||
| 581 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, | 583 | rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE, |
| 582 | "attempting to determine the durations"); | 584 | "attempting to determine the durations"); |
| 583 | if (rc) | 585 | if (rc) |
| 584 | return rc; | 586 | return; |
| 585 | 587 | ||
| 586 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || | 588 | if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 || |
| 587 | be32_to_cpu(tpm_cmd.header.out.length) | 589 | be32_to_cpu(tpm_cmd.header.out.length) |
| 588 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) | 590 | != sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32)) |
| 589 | return -EINVAL; | 591 | return; |
| 590 | 592 | ||
| 591 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; | 593 | duration_cap = &tpm_cmd.params.getcap_out.cap.duration; |
| 592 | chip->vendor.duration[TPM_SHORT] = | 594 | chip->vendor.duration[TPM_SHORT] = |
| @@ -608,36 +610,20 @@ duration: | |||
| 608 | chip->vendor.duration_adjusted = true; | 610 | chip->vendor.duration_adjusted = true; |
| 609 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); | 611 | dev_info(chip->dev, "Adjusting TPM timeout parameters."); |
| 610 | } | 612 | } |
| 611 | return 0; | ||
| 612 | } | 613 | } |
| 613 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); | 614 | EXPORT_SYMBOL_GPL(tpm_get_timeouts); |
| 614 | 615 | ||
| 615 | #define TPM_ORD_CONTINUE_SELFTEST 83 | 616 | void tpm_continue_selftest(struct tpm_chip *chip) |
| 616 | #define CONTINUE_SELFTEST_RESULT_SIZE 10 | ||
| 617 | |||
| 618 | static struct tpm_input_header continue_selftest_header = { | ||
| 619 | .tag = TPM_TAG_RQU_COMMAND, | ||
| 620 | .length = cpu_to_be32(10), | ||
| 621 | .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST), | ||
| 622 | }; | ||
| 623 | |||
| 624 | /** | ||
| 625 | * tpm_continue_selftest -- run TPM's selftest | ||
| 626 | * @chip: TPM chip to use | ||
| 627 | * | ||
| 628 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | ||
| 629 | * a TPM error code. | ||
| 630 | */ | ||
| 631 | static int tpm_continue_selftest(struct tpm_chip *chip) | ||
| 632 | { | 617 | { |
| 633 | int rc; | 618 | u8 data[] = { |
| 634 | struct tpm_cmd_t cmd; | 619 | 0, 193, /* TPM_TAG_RQU_COMMAND */ |
| 620 | 0, 0, 0, 10, /* length */ | ||
| 621 | 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */ | ||
| 622 | }; | ||
| 635 | 623 | ||
| 636 | cmd.header.in = continue_selftest_header; | 624 | tpm_transmit(chip, data, sizeof(data)); |
| 637 | rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE, | ||
| 638 | "continue selftest"); | ||
| 639 | return rc; | ||
| 640 | } | 625 | } |
| 626 | EXPORT_SYMBOL_GPL(tpm_continue_selftest); | ||
| 641 | 627 | ||
| 642 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, | 628 | ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr, |
| 643 | char *buf) | 629 | char *buf) |
| @@ -732,7 +718,7 @@ static struct tpm_input_header pcrread_header = { | |||
| 732 | .ordinal = TPM_ORDINAL_PCRREAD | 718 | .ordinal = TPM_ORDINAL_PCRREAD |
| 733 | }; | 719 | }; |
| 734 | 720 | ||
| 735 | static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) | 721 | int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf) |
| 736 | { | 722 | { |
| 737 | int rc; | 723 | int rc; |
| 738 | struct tpm_cmd_t cmd; | 724 | struct tpm_cmd_t cmd; |
| @@ -812,62 +798,6 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash) | |||
| 812 | } | 798 | } |
| 813 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); | 799 | EXPORT_SYMBOL_GPL(tpm_pcr_extend); |
| 814 | 800 | ||
| 815 | /** | ||
| 816 | * tpm_do_selftest - have the TPM continue its selftest and wait until it | ||
| 817 | * can receive further commands | ||
| 818 | * @chip: TPM chip to use | ||
| 819 | * | ||
| 820 | * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing | ||
| 821 | * a TPM error code. | ||
| 822 | */ | ||
| 823 | int tpm_do_selftest(struct tpm_chip *chip) | ||
| 824 | { | ||
| 825 | int rc; | ||
| 826 | unsigned int loops; | ||
| 827 | unsigned int delay_msec = 1000; | ||
| 828 | unsigned long duration; | ||
| 829 | struct tpm_cmd_t cmd; | ||
| 830 | |||
| 831 | duration = tpm_calc_ordinal_duration(chip, | ||
| 832 | TPM_ORD_CONTINUE_SELFTEST); | ||
| 833 | |||
| 834 | loops = jiffies_to_msecs(duration) / delay_msec; | ||
| 835 | |||
| 836 | rc = tpm_continue_selftest(chip); | ||
| 837 | /* This may fail if there was no TPM driver during a suspend/resume | ||
| 838 | * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST) | ||
| 839 | */ | ||
| 840 | if (rc) | ||
| 841 | return rc; | ||
| 842 | |||
| 843 | do { | ||
| 844 | /* Attempt to read a PCR value */ | ||
| 845 | cmd.header.in = pcrread_header; | ||
| 846 | cmd.params.pcrread_in.pcr_idx = cpu_to_be32(0); | ||
| 847 | rc = tpm_transmit(chip, (u8 *) &cmd, READ_PCR_RESULT_SIZE); | ||
| 848 | |||
| 849 | if (rc < TPM_HEADER_SIZE) | ||
| 850 | return -EFAULT; | ||
| 851 | |||
| 852 | rc = be32_to_cpu(cmd.header.out.return_code); | ||
| 853 | if (rc == TPM_ERR_DISABLED || rc == TPM_ERR_DEACTIVATED) { | ||
| 854 | dev_info(chip->dev, | ||
| 855 | "TPM is disabled/deactivated (0x%X)\n", rc); | ||
| 856 | /* TPM is disabled and/or deactivated; driver can | ||
| 857 | * proceed and TPM does handle commands for | ||
| 858 | * suspend/resume correctly | ||
| 859 | */ | ||
| 860 | return 0; | ||
| 861 | } | ||
| 862 | if (rc != TPM_WARN_DOING_SELFTEST) | ||
| 863 | return rc; | ||
| 864 | msleep(delay_msec); | ||
| 865 | } while (--loops > 0); | ||
| 866 | |||
| 867 | return rc; | ||
| 868 | } | ||
| 869 | EXPORT_SYMBOL_GPL(tpm_do_selftest); | ||
| 870 | |||
| 871 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) | 801 | int tpm_send(u32 chip_num, void *cmd, size_t buflen) |
| 872 | { | 802 | { |
| 873 | struct tpm_chip *chip; | 803 | struct tpm_chip *chip; |
| @@ -915,7 +845,7 @@ EXPORT_SYMBOL_GPL(tpm_show_pcrs); | |||
| 915 | 845 | ||
| 916 | #define READ_PUBEK_RESULT_SIZE 314 | 846 | #define READ_PUBEK_RESULT_SIZE 314 |
| 917 | #define TPM_ORD_READPUBEK cpu_to_be32(124) | 847 | #define TPM_ORD_READPUBEK cpu_to_be32(124) |
| 918 | static struct tpm_input_header tpm_readpubek_header = { | 848 | struct tpm_input_header tpm_readpubek_header = { |
| 919 | .tag = TPM_TAG_RQU_COMMAND, | 849 | .tag = TPM_TAG_RQU_COMMAND, |
| 920 | .length = cpu_to_be32(30), | 850 | .length = cpu_to_be32(30), |
| 921 | .ordinal = TPM_ORD_READPUBEK | 851 | .ordinal = TPM_ORD_READPUBEK |
| @@ -1036,9 +966,6 @@ ssize_t tpm_show_durations(struct device *dev, struct device_attribute *attr, | |||
| 1036 | { | 966 | { |
| 1037 | struct tpm_chip *chip = dev_get_drvdata(dev); | 967 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 1038 | 968 | ||
| 1039 | if (chip->vendor.duration[TPM_LONG] == 0) | ||
| 1040 | return 0; | ||
| 1041 | |||
| 1042 | return sprintf(buf, "%d %d %d [%s]\n", | 969 | return sprintf(buf, "%d %d %d [%s]\n", |
| 1043 | jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), | 970 | jiffies_to_usecs(chip->vendor.duration[TPM_SHORT]), |
| 1044 | jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), | 971 | jiffies_to_usecs(chip->vendor.duration[TPM_MEDIUM]), |
| @@ -1075,46 +1002,6 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr, | |||
| 1075 | } | 1002 | } |
| 1076 | EXPORT_SYMBOL_GPL(tpm_store_cancel); | 1003 | EXPORT_SYMBOL_GPL(tpm_store_cancel); |
| 1077 | 1004 | ||
| 1078 | int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
| 1079 | wait_queue_head_t *queue) | ||
| 1080 | { | ||
| 1081 | unsigned long stop; | ||
| 1082 | long rc; | ||
| 1083 | u8 status; | ||
| 1084 | |||
| 1085 | /* check current status */ | ||
| 1086 | status = chip->vendor.status(chip); | ||
| 1087 | if ((status & mask) == mask) | ||
| 1088 | return 0; | ||
| 1089 | |||
| 1090 | stop = jiffies + timeout; | ||
| 1091 | |||
| 1092 | if (chip->vendor.irq) { | ||
| 1093 | again: | ||
| 1094 | timeout = stop - jiffies; | ||
| 1095 | if ((long)timeout <= 0) | ||
| 1096 | return -ETIME; | ||
| 1097 | rc = wait_event_interruptible_timeout(*queue, | ||
| 1098 | ((chip->vendor.status(chip) | ||
| 1099 | & mask) == mask), | ||
| 1100 | timeout); | ||
| 1101 | if (rc > 0) | ||
| 1102 | return 0; | ||
| 1103 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
| 1104 | clear_thread_flag(TIF_SIGPENDING); | ||
| 1105 | goto again; | ||
| 1106 | } | ||
| 1107 | } else { | ||
| 1108 | do { | ||
| 1109 | msleep(TPM_TIMEOUT); | ||
| 1110 | status = chip->vendor.status(chip); | ||
| 1111 | if ((status & mask) == mask) | ||
| 1112 | return 0; | ||
| 1113 | } while (time_before(jiffies, stop)); | ||
| 1114 | } | ||
| 1115 | return -ETIME; | ||
| 1116 | } | ||
| 1117 | EXPORT_SYMBOL_GPL(wait_for_tpm_stat); | ||
| 1118 | /* | 1005 | /* |
| 1119 | * Device file system interface to the TPM | 1006 | * Device file system interface to the TPM |
| 1120 | * | 1007 | * |
| @@ -1168,10 +1055,10 @@ int tpm_release(struct inode *inode, struct file *file) | |||
| 1168 | struct tpm_chip *chip = file->private_data; | 1055 | struct tpm_chip *chip = file->private_data; |
| 1169 | 1056 | ||
| 1170 | del_singleshot_timer_sync(&chip->user_read_timer); | 1057 | del_singleshot_timer_sync(&chip->user_read_timer); |
| 1171 | flush_work(&chip->work); | 1058 | flush_work_sync(&chip->work); |
| 1172 | file->private_data = NULL; | 1059 | file->private_data = NULL; |
| 1173 | atomic_set(&chip->data_pending, 0); | 1060 | atomic_set(&chip->data_pending, 0); |
| 1174 | kzfree(chip->data_buffer); | 1061 | kfree(chip->data_buffer); |
| 1175 | clear_bit(0, &chip->is_open); | 1062 | clear_bit(0, &chip->is_open); |
| 1176 | put_device(chip->dev); | 1063 | put_device(chip->dev); |
| 1177 | return 0; | 1064 | return 0; |
| @@ -1182,21 +1069,18 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
| 1182 | size_t size, loff_t *off) | 1069 | size_t size, loff_t *off) |
| 1183 | { | 1070 | { |
| 1184 | struct tpm_chip *chip = file->private_data; | 1071 | struct tpm_chip *chip = file->private_data; |
| 1185 | size_t in_size = size; | 1072 | size_t in_size = size, out_size; |
| 1186 | ssize_t out_size; | ||
| 1187 | 1073 | ||
| 1188 | /* cannot perform a write until the read has cleared | 1074 | /* cannot perform a write until the read has cleared |
| 1189 | either via tpm_read or a user_read_timer timeout. | 1075 | either via tpm_read or a user_read_timer timeout */ |
| 1190 | This also prevents splitted buffered writes from blocking here. | 1076 | while (atomic_read(&chip->data_pending) != 0) |
| 1191 | */ | 1077 | msleep(TPM_TIMEOUT); |
| 1192 | if (atomic_read(&chip->data_pending) != 0) | ||
| 1193 | return -EBUSY; | ||
| 1194 | |||
| 1195 | if (in_size > TPM_BUFSIZE) | ||
| 1196 | return -E2BIG; | ||
| 1197 | 1078 | ||
| 1198 | mutex_lock(&chip->buffer_mutex); | 1079 | mutex_lock(&chip->buffer_mutex); |
| 1199 | 1080 | ||
| 1081 | if (in_size > TPM_BUFSIZE) | ||
| 1082 | in_size = TPM_BUFSIZE; | ||
| 1083 | |||
| 1200 | if (copy_from_user | 1084 | if (copy_from_user |
| 1201 | (chip->data_buffer, (void __user *) buf, in_size)) { | 1085 | (chip->data_buffer, (void __user *) buf, in_size)) { |
| 1202 | mutex_unlock(&chip->buffer_mutex); | 1086 | mutex_unlock(&chip->buffer_mutex); |
| @@ -1205,10 +1089,6 @@ ssize_t tpm_write(struct file *file, const char __user *buf, | |||
| 1205 | 1089 | ||
| 1206 | /* atomic tpm command send and result receive */ | 1090 | /* atomic tpm command send and result receive */ |
| 1207 | out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); | 1091 | out_size = tpm_transmit(chip, chip->data_buffer, TPM_BUFSIZE); |
| 1208 | if (out_size < 0) { | ||
| 1209 | mutex_unlock(&chip->buffer_mutex); | ||
| 1210 | return out_size; | ||
| 1211 | } | ||
| 1212 | 1092 | ||
| 1213 | atomic_set(&chip->data_pending, out_size); | 1093 | atomic_set(&chip->data_pending, out_size); |
| 1214 | mutex_unlock(&chip->buffer_mutex); | 1094 | mutex_unlock(&chip->buffer_mutex); |
| @@ -1228,24 +1108,22 @@ ssize_t tpm_read(struct file *file, char __user *buf, | |||
| 1228 | int rc; | 1108 | int rc; |
| 1229 | 1109 | ||
| 1230 | del_singleshot_timer_sync(&chip->user_read_timer); | 1110 | del_singleshot_timer_sync(&chip->user_read_timer); |
| 1231 | flush_work(&chip->work); | 1111 | flush_work_sync(&chip->work); |
| 1232 | ret_size = atomic_read(&chip->data_pending); | 1112 | ret_size = atomic_read(&chip->data_pending); |
| 1113 | atomic_set(&chip->data_pending, 0); | ||
| 1233 | if (ret_size > 0) { /* relay data */ | 1114 | if (ret_size > 0) { /* relay data */ |
| 1234 | ssize_t orig_ret_size = ret_size; | ||
| 1235 | if (size < ret_size) | 1115 | if (size < ret_size) |
| 1236 | ret_size = size; | 1116 | ret_size = size; |
| 1237 | 1117 | ||
| 1238 | mutex_lock(&chip->buffer_mutex); | 1118 | mutex_lock(&chip->buffer_mutex); |
| 1239 | rc = copy_to_user(buf, chip->data_buffer, ret_size); | 1119 | rc = copy_to_user(buf, chip->data_buffer, ret_size); |
| 1240 | memset(chip->data_buffer, 0, orig_ret_size); | 1120 | memset(chip->data_buffer, 0, ret_size); |
| 1241 | if (rc) | 1121 | if (rc) |
| 1242 | ret_size = -EFAULT; | 1122 | ret_size = -EFAULT; |
| 1243 | 1123 | ||
| 1244 | mutex_unlock(&chip->buffer_mutex); | 1124 | mutex_unlock(&chip->buffer_mutex); |
| 1245 | } | 1125 | } |
| 1246 | 1126 | ||
| 1247 | atomic_set(&chip->data_pending, 0); | ||
| 1248 | |||
| 1249 | return ret_size; | 1127 | return ret_size; |
| 1250 | } | 1128 | } |
| 1251 | EXPORT_SYMBOL_GPL(tpm_read); | 1129 | EXPORT_SYMBOL_GPL(tpm_read); |
| @@ -1266,7 +1144,6 @@ void tpm_remove_hardware(struct device *dev) | |||
| 1266 | 1144 | ||
| 1267 | misc_deregister(&chip->vendor.miscdev); | 1145 | misc_deregister(&chip->vendor.miscdev); |
| 1268 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); | 1146 | sysfs_remove_group(&dev->kobj, chip->vendor.attr_group); |
| 1269 | tpm_remove_ppi(&dev->kobj); | ||
| 1270 | tpm_bios_log_teardown(chip->bios_dir); | 1147 | tpm_bios_log_teardown(chip->bios_dir); |
| 1271 | 1148 | ||
| 1272 | /* write it this way to be explicit (chip->dev == dev) */ | 1149 | /* write it this way to be explicit (chip->dev == dev) */ |
| @@ -1287,7 +1164,7 @@ static struct tpm_input_header savestate_header = { | |||
| 1287 | * We are about to suspend. Save the TPM state | 1164 | * We are about to suspend. Save the TPM state |
| 1288 | * so that it can be restored. | 1165 | * so that it can be restored. |
| 1289 | */ | 1166 | */ |
| 1290 | int tpm_pm_suspend(struct device *dev) | 1167 | int tpm_pm_suspend(struct device *dev, pm_message_t pm_state) |
| 1291 | { | 1168 | { |
| 1292 | struct tpm_chip *chip = dev_get_drvdata(dev); | 1169 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 1293 | struct tpm_cmd_t cmd; | 1170 | struct tpm_cmd_t cmd; |
| @@ -1331,65 +1208,10 @@ int tpm_pm_resume(struct device *dev) | |||
| 1331 | } | 1208 | } |
| 1332 | EXPORT_SYMBOL_GPL(tpm_pm_resume); | 1209 | EXPORT_SYMBOL_GPL(tpm_pm_resume); |
| 1333 | 1210 | ||
| 1334 | #define TPM_GETRANDOM_RESULT_SIZE 18 | ||
| 1335 | static struct tpm_input_header tpm_getrandom_header = { | ||
| 1336 | .tag = TPM_TAG_RQU_COMMAND, | ||
| 1337 | .length = cpu_to_be32(14), | ||
| 1338 | .ordinal = TPM_ORD_GET_RANDOM | ||
| 1339 | }; | ||
| 1340 | |||
| 1341 | /** | ||
| 1342 | * tpm_get_random() - Get random bytes from the tpm's RNG | ||
| 1343 | * @chip_num: A specific chip number for the request or TPM_ANY_NUM | ||
| 1344 | * @out: destination buffer for the random bytes | ||
| 1345 | * @max: the max number of bytes to write to @out | ||
| 1346 | * | ||
| 1347 | * Returns < 0 on error and the number of bytes read on success | ||
| 1348 | */ | ||
| 1349 | int tpm_get_random(u32 chip_num, u8 *out, size_t max) | ||
| 1350 | { | ||
| 1351 | struct tpm_chip *chip; | ||
| 1352 | struct tpm_cmd_t tpm_cmd; | ||
| 1353 | u32 recd, num_bytes = min_t(u32, max, TPM_MAX_RNG_DATA); | ||
| 1354 | int err, total = 0, retries = 5; | ||
| 1355 | u8 *dest = out; | ||
| 1356 | |||
| 1357 | chip = tpm_chip_find_get(chip_num); | ||
| 1358 | if (chip == NULL) | ||
| 1359 | return -ENODEV; | ||
| 1360 | |||
| 1361 | if (!out || !num_bytes || max > TPM_MAX_RNG_DATA) | ||
| 1362 | return -EINVAL; | ||
| 1363 | |||
| 1364 | do { | ||
| 1365 | tpm_cmd.header.in = tpm_getrandom_header; | ||
| 1366 | tpm_cmd.params.getrandom_in.num_bytes = cpu_to_be32(num_bytes); | ||
| 1367 | |||
| 1368 | err = transmit_cmd(chip, &tpm_cmd, | ||
| 1369 | TPM_GETRANDOM_RESULT_SIZE + num_bytes, | ||
| 1370 | "attempting get random"); | ||
| 1371 | if (err) | ||
| 1372 | break; | ||
| 1373 | |||
| 1374 | recd = be32_to_cpu(tpm_cmd.params.getrandom_out.rng_data_len); | ||
| 1375 | memcpy(dest, tpm_cmd.params.getrandom_out.rng_data, recd); | ||
| 1376 | |||
| 1377 | dest += recd; | ||
| 1378 | total += recd; | ||
| 1379 | num_bytes -= recd; | ||
| 1380 | } while (retries-- && total < max); | ||
| 1381 | |||
| 1382 | return total ? total : -EIO; | ||
| 1383 | } | ||
| 1384 | EXPORT_SYMBOL_GPL(tpm_get_random); | ||
| 1385 | |||
| 1386 | /* In case vendor provided release function, call it too.*/ | 1211 | /* In case vendor provided release function, call it too.*/ |
| 1387 | 1212 | ||
| 1388 | void tpm_dev_vendor_release(struct tpm_chip *chip) | 1213 | void tpm_dev_vendor_release(struct tpm_chip *chip) |
| 1389 | { | 1214 | { |
| 1390 | if (!chip) | ||
| 1391 | return; | ||
| 1392 | |||
| 1393 | if (chip->vendor.release) | 1215 | if (chip->vendor.release) |
| 1394 | chip->vendor.release(chip->dev); | 1216 | chip->vendor.release(chip->dev); |
| 1395 | 1217 | ||
| @@ -1403,13 +1225,10 @@ EXPORT_SYMBOL_GPL(tpm_dev_vendor_release); | |||
| 1403 | * Once all references to platform device are down to 0, | 1225 | * Once all references to platform device are down to 0, |
| 1404 | * release all allocated structures. | 1226 | * release all allocated structures. |
| 1405 | */ | 1227 | */ |
| 1406 | static void tpm_dev_release(struct device *dev) | 1228 | void tpm_dev_release(struct device *dev) |
| 1407 | { | 1229 | { |
| 1408 | struct tpm_chip *chip = dev_get_drvdata(dev); | 1230 | struct tpm_chip *chip = dev_get_drvdata(dev); |
| 1409 | 1231 | ||
| 1410 | if (!chip) | ||
| 1411 | return; | ||
| 1412 | |||
| 1413 | tpm_dev_vendor_release(chip); | 1232 | tpm_dev_vendor_release(chip); |
| 1414 | 1233 | ||
| 1415 | chip->release(dev); | 1234 | chip->release(dev); |
| @@ -1476,17 +1295,15 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | |||
| 1476 | "unable to misc_register %s, minor %d\n", | 1295 | "unable to misc_register %s, minor %d\n", |
| 1477 | chip->vendor.miscdev.name, | 1296 | chip->vendor.miscdev.name, |
| 1478 | chip->vendor.miscdev.minor); | 1297 | chip->vendor.miscdev.minor); |
| 1479 | goto put_device; | 1298 | put_device(chip->dev); |
| 1299 | return NULL; | ||
| 1480 | } | 1300 | } |
| 1481 | 1301 | ||
| 1482 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { | 1302 | if (sysfs_create_group(&dev->kobj, chip->vendor.attr_group)) { |
| 1483 | misc_deregister(&chip->vendor.miscdev); | 1303 | misc_deregister(&chip->vendor.miscdev); |
| 1484 | goto put_device; | 1304 | put_device(chip->dev); |
| 1485 | } | ||
| 1486 | 1305 | ||
| 1487 | if (tpm_add_ppi(&dev->kobj)) { | 1306 | return NULL; |
| 1488 | misc_deregister(&chip->vendor.miscdev); | ||
| 1489 | goto put_device; | ||
| 1490 | } | 1307 | } |
| 1491 | 1308 | ||
| 1492 | chip->bios_dir = tpm_bios_log_setup(devname); | 1309 | chip->bios_dir = tpm_bios_log_setup(devname); |
| @@ -1498,8 +1315,6 @@ struct tpm_chip *tpm_register_hardware(struct device *dev, | |||
| 1498 | 1315 | ||
| 1499 | return chip; | 1316 | return chip; |
| 1500 | 1317 | ||
| 1501 | put_device: | ||
| 1502 | put_device(chip->dev); | ||
| 1503 | out_free: | 1318 | out_free: |
| 1504 | kfree(chip); | 1319 | kfree(chip); |
| 1505 | kfree(devname); | 1320 | kfree(devname); |
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h index 8ef7649a50a..9c4163cfa3c 100644 --- a/drivers/char/tpm/tpm.h +++ b/drivers/char/tpm/tpm.h | |||
| @@ -28,12 +28,6 @@ | |||
| 28 | #include <linux/io.h> | 28 | #include <linux/io.h> |
| 29 | #include <linux/tpm.h> | 29 | #include <linux/tpm.h> |
| 30 | 30 | ||
| 31 | enum tpm_const { | ||
| 32 | TPM_MINOR = 224, /* officially assigned */ | ||
| 33 | TPM_BUFSIZE = 4096, | ||
| 34 | TPM_NUM_DEVICES = 256, | ||
| 35 | }; | ||
| 36 | |||
| 37 | enum tpm_timeout { | 31 | enum tpm_timeout { |
| 38 | TPM_TIMEOUT = 5, /* msecs */ | 32 | TPM_TIMEOUT = 5, /* msecs */ |
| 39 | }; | 33 | }; |
| @@ -44,11 +38,6 @@ enum tpm_addr { | |||
| 44 | TPM_ADDR = 0x4E, | 38 | TPM_ADDR = 0x4E, |
| 45 | }; | 39 | }; |
| 46 | 40 | ||
| 47 | #define TPM_WARN_DOING_SELFTEST 0x802 | ||
| 48 | #define TPM_ERR_DEACTIVATED 0x6 | ||
| 49 | #define TPM_ERR_DISABLED 0x7 | ||
| 50 | |||
| 51 | #define TPM_HEADER_SIZE 10 | ||
| 52 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, | 41 | extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr, |
| 53 | char *); | 42 | char *); |
| 54 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, | 43 | extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr, |
| @@ -100,14 +89,11 @@ struct tpm_vendor_specific { | |||
| 100 | bool timeout_adjusted; | 89 | bool timeout_adjusted; |
| 101 | unsigned long duration[3]; /* jiffies */ | 90 | unsigned long duration[3]; /* jiffies */ |
| 102 | bool duration_adjusted; | 91 | bool duration_adjusted; |
| 103 | void *data; | ||
| 104 | 92 | ||
| 105 | wait_queue_head_t read_queue; | 93 | wait_queue_head_t read_queue; |
| 106 | wait_queue_head_t int_queue; | 94 | wait_queue_head_t int_queue; |
| 107 | }; | 95 | }; |
| 108 | 96 | ||
| 109 | #define TPM_VID_INTEL 0x8086 | ||
| 110 | |||
| 111 | struct tpm_chip { | 97 | struct tpm_chip { |
| 112 | struct device *dev; /* Device stuff */ | 98 | struct device *dev; /* Device stuff */ |
| 113 | 99 | ||
| @@ -276,21 +262,6 @@ struct tpm_pcrextend_in { | |||
| 276 | u8 hash[TPM_DIGEST_SIZE]; | 262 | u8 hash[TPM_DIGEST_SIZE]; |
| 277 | }__attribute__((packed)); | 263 | }__attribute__((packed)); |
| 278 | 264 | ||
| 279 | /* 128 bytes is an arbitrary cap. This could be as large as TPM_BUFSIZE - 18 | ||
| 280 | * bytes, but 128 is still a relatively large number of random bytes and | ||
| 281 | * anything much bigger causes users of struct tpm_cmd_t to start getting | ||
| 282 | * compiler warnings about stack frame size. */ | ||
| 283 | #define TPM_MAX_RNG_DATA 128 | ||
| 284 | |||
| 285 | struct tpm_getrandom_out { | ||
| 286 | __be32 rng_data_len; | ||
| 287 | u8 rng_data[TPM_MAX_RNG_DATA]; | ||
| 288 | }__attribute__((packed)); | ||
| 289 | |||
| 290 | struct tpm_getrandom_in { | ||
| 291 | __be32 num_bytes; | ||
| 292 | }__attribute__((packed)); | ||
| 293 | |||
| 294 | typedef union { | 265 | typedef union { |
| 295 | struct tpm_getcap_params_out getcap_out; | 266 | struct tpm_getcap_params_out getcap_out; |
| 296 | struct tpm_readpubek_params_out readpubek_out; | 267 | struct tpm_readpubek_params_out readpubek_out; |
| @@ -299,8 +270,6 @@ typedef union { | |||
| 299 | struct tpm_pcrread_in pcrread_in; | 270 | struct tpm_pcrread_in pcrread_in; |
| 300 | struct tpm_pcrread_out pcrread_out; | 271 | struct tpm_pcrread_out pcrread_out; |
| 301 | struct tpm_pcrextend_in pcrextend_in; | 272 | struct tpm_pcrextend_in pcrextend_in; |
| 302 | struct tpm_getrandom_in getrandom_in; | ||
| 303 | struct tpm_getrandom_out getrandom_out; | ||
| 304 | } tpm_cmd_params; | 273 | } tpm_cmd_params; |
| 305 | 274 | ||
| 306 | struct tpm_cmd_t { | 275 | struct tpm_cmd_t { |
| @@ -310,9 +279,9 @@ struct tpm_cmd_t { | |||
| 310 | 279 | ||
| 311 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); | 280 | ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *); |
| 312 | 281 | ||
| 313 | extern int tpm_get_timeouts(struct tpm_chip *); | 282 | extern void tpm_get_timeouts(struct tpm_chip *); |
| 314 | extern void tpm_gen_interrupt(struct tpm_chip *); | 283 | extern void tpm_gen_interrupt(struct tpm_chip *); |
| 315 | extern int tpm_do_selftest(struct tpm_chip *); | 284 | extern void tpm_continue_selftest(struct tpm_chip *); |
| 316 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); | 285 | extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32); |
| 317 | extern struct tpm_chip* tpm_register_hardware(struct device *, | 286 | extern struct tpm_chip* tpm_register_hardware(struct device *, |
| 318 | const struct tpm_vendor_specific *); | 287 | const struct tpm_vendor_specific *); |
| @@ -323,21 +292,18 @@ extern ssize_t tpm_write(struct file *, const char __user *, size_t, | |||
| 323 | loff_t *); | 292 | loff_t *); |
| 324 | extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); | 293 | extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *); |
| 325 | extern void tpm_remove_hardware(struct device *); | 294 | extern void tpm_remove_hardware(struct device *); |
| 326 | extern int tpm_pm_suspend(struct device *); | 295 | extern int tpm_pm_suspend(struct device *, pm_message_t); |
| 327 | extern int tpm_pm_resume(struct device *); | 296 | extern int tpm_pm_resume(struct device *); |
| 328 | extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long, | ||
| 329 | wait_queue_head_t *); | ||
| 330 | 297 | ||
| 331 | #ifdef CONFIG_ACPI | 298 | #ifdef CONFIG_ACPI |
| 332 | extern int tpm_add_ppi(struct kobject *); | 299 | extern struct dentry ** tpm_bios_log_setup(char *); |
| 333 | extern void tpm_remove_ppi(struct kobject *); | 300 | extern void tpm_bios_log_teardown(struct dentry **); |
| 334 | #else | 301 | #else |
| 335 | static inline int tpm_add_ppi(struct kobject *parent) | 302 | static inline struct dentry ** tpm_bios_log_setup(char *name) |
| 336 | { | 303 | { |
| 337 | return 0; | 304 | return NULL; |
| 338 | } | 305 | } |
| 339 | 306 | static inline void tpm_bios_log_teardown(struct dentry **dir) | |
| 340 | static inline void tpm_remove_ppi(struct kobject *parent) | ||
| 341 | { | 307 | { |
| 342 | } | 308 | } |
| 343 | #endif | 309 | #endif |
diff --git a/drivers/char/tpm/tpm_acpi.c b/drivers/char/tpm/tpm_acpi.c deleted file mode 100644 index 56051d0c97a..00000000000 --- a/drivers/char/tpm/tpm_acpi.c +++ /dev/null | |||
| @@ -1,109 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005 IBM Corporation | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Seiji Munetoh <munetoh@jp.ibm.com> | ||
| 6 | * Stefan Berger <stefanb@us.ibm.com> | ||
| 7 | * Reiner Sailer <sailer@watson.ibm.com> | ||
| 8 | * Kylene Hall <kjhall@us.ibm.com> | ||
| 9 | * | ||
| 10 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
| 11 | * | ||
| 12 | * Access to the eventlog extended by the TCG BIOS of PC platform | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or | ||
| 15 | * modify it under the terms of the GNU General Public License | ||
| 16 | * as published by the Free Software Foundation; either version | ||
| 17 | * 2 of the License, or (at your option) any later version. | ||
| 18 | * | ||
| 19 | */ | ||
| 20 | |||
| 21 | #include <linux/seq_file.h> | ||
| 22 | #include <linux/fs.h> | ||
| 23 | #include <linux/security.h> | ||
| 24 | #include <linux/module.h> | ||
| 25 | #include <linux/slab.h> | ||
| 26 | #include <acpi/acpi.h> | ||
| 27 | |||
| 28 | #include "tpm.h" | ||
| 29 | #include "tpm_eventlog.h" | ||
| 30 | |||
| 31 | struct acpi_tcpa { | ||
| 32 | struct acpi_table_header hdr; | ||
| 33 | u16 platform_class; | ||
| 34 | union { | ||
| 35 | struct client_hdr { | ||
| 36 | u32 log_max_len __attribute__ ((packed)); | ||
| 37 | u64 log_start_addr __attribute__ ((packed)); | ||
| 38 | } client; | ||
| 39 | struct server_hdr { | ||
| 40 | u16 reserved; | ||
| 41 | u64 log_max_len __attribute__ ((packed)); | ||
| 42 | u64 log_start_addr __attribute__ ((packed)); | ||
| 43 | } server; | ||
| 44 | }; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* read binary bios log */ | ||
| 48 | int read_log(struct tpm_bios_log *log) | ||
| 49 | { | ||
| 50 | struct acpi_tcpa *buff; | ||
| 51 | acpi_status status; | ||
| 52 | void __iomem *virt; | ||
| 53 | u64 len, start; | ||
| 54 | |||
| 55 | if (log->bios_event_log != NULL) { | ||
| 56 | printk(KERN_ERR | ||
| 57 | "%s: ERROR - Eventlog already initialized\n", | ||
| 58 | __func__); | ||
| 59 | return -EFAULT; | ||
| 60 | } | ||
| 61 | |||
| 62 | /* Find TCPA entry in RSDT (ACPI_LOGICAL_ADDRESSING) */ | ||
| 63 | status = acpi_get_table(ACPI_SIG_TCPA, 1, | ||
| 64 | (struct acpi_table_header **)&buff); | ||
| 65 | |||
| 66 | if (ACPI_FAILURE(status)) { | ||
| 67 | printk(KERN_ERR "%s: ERROR - Could not get TCPA table\n", | ||
| 68 | __func__); | ||
| 69 | return -EIO; | ||
| 70 | } | ||
| 71 | |||
| 72 | switch(buff->platform_class) { | ||
| 73 | case BIOS_SERVER: | ||
| 74 | len = buff->server.log_max_len; | ||
| 75 | start = buff->server.log_start_addr; | ||
| 76 | break; | ||
| 77 | case BIOS_CLIENT: | ||
| 78 | default: | ||
| 79 | len = buff->client.log_max_len; | ||
| 80 | start = buff->client.log_start_addr; | ||
| 81 | break; | ||
| 82 | } | ||
| 83 | if (!len) { | ||
| 84 | printk(KERN_ERR "%s: ERROR - TCPA log area empty\n", __func__); | ||
| 85 | return -EIO; | ||
| 86 | } | ||
| 87 | |||
| 88 | /* malloc EventLog space */ | ||
| 89 | log->bios_event_log = kmalloc(len, GFP_KERNEL); | ||
| 90 | if (!log->bios_event_log) { | ||
| 91 | printk("%s: ERROR - Not enough Memory for BIOS measurements\n", | ||
| 92 | __func__); | ||
| 93 | return -ENOMEM; | ||
| 94 | } | ||
| 95 | |||
| 96 | log->bios_event_log_end = log->bios_event_log + len; | ||
| 97 | |||
| 98 | virt = acpi_os_map_memory(start, len); | ||
| 99 | if (!virt) { | ||
| 100 | kfree(log->bios_event_log); | ||
| 101 | printk("%s: ERROR - Unable to map memory\n", __func__); | ||
| 102 | return -EIO; | ||
| 103 | } | ||
| 104 | |||
| 105 | memcpy_fromio(log->bios_event_log, virt, len); | ||
| 106 | |||
| 107 | acpi_os_unmap_memory(virt, len); | ||
| 108 | return 0; | ||
| 109 | } | ||
diff --git a/drivers/char/tpm/tpm_atmel.c b/drivers/char/tpm/tpm_atmel.c index 678d57019dc..c64a1bc6534 100644 --- a/drivers/char/tpm/tpm_atmel.c +++ b/drivers/char/tpm/tpm_atmel.c | |||
| @@ -168,14 +168,22 @@ static void atml_plat_remove(void) | |||
| 168 | } | 168 | } |
| 169 | } | 169 | } |
| 170 | 170 | ||
| 171 | static SIMPLE_DEV_PM_OPS(tpm_atml_pm, tpm_pm_suspend, tpm_pm_resume); | 171 | static int tpm_atml_suspend(struct platform_device *dev, pm_message_t msg) |
| 172 | { | ||
| 173 | return tpm_pm_suspend(&dev->dev, msg); | ||
| 174 | } | ||
| 172 | 175 | ||
| 176 | static int tpm_atml_resume(struct platform_device *dev) | ||
| 177 | { | ||
| 178 | return tpm_pm_resume(&dev->dev); | ||
| 179 | } | ||
| 173 | static struct platform_driver atml_drv = { | 180 | static struct platform_driver atml_drv = { |
| 174 | .driver = { | 181 | .driver = { |
| 175 | .name = "tpm_atmel", | 182 | .name = "tpm_atmel", |
| 176 | .owner = THIS_MODULE, | 183 | .owner = THIS_MODULE, |
| 177 | .pm = &tpm_atml_pm, | ||
| 178 | }, | 184 | }, |
| 185 | .suspend = tpm_atml_suspend, | ||
| 186 | .resume = tpm_atml_resume, | ||
| 179 | }; | 187 | }; |
| 180 | 188 | ||
| 181 | static int __init init_atmel(void) | 189 | static int __init init_atmel(void) |
diff --git a/drivers/char/tpm/tpm_eventlog.c b/drivers/char/tpm/tpm_eventlog.c deleted file mode 100644 index 84ddc557b8f..00000000000 --- a/drivers/char/tpm/tpm_eventlog.c +++ /dev/null | |||
| @@ -1,419 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2005, 2012 IBM Corporation | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Kent Yoder <key@linux.vnet.ibm.com> | ||
| 6 | * Seiji Munetoh <munetoh@jp.ibm.com> | ||
| 7 | * Stefan Berger <stefanb@us.ibm.com> | ||
| 8 | * Reiner Sailer <sailer@watson.ibm.com> | ||
| 9 | * Kylene Hall <kjhall@us.ibm.com> | ||
| 10 | * | ||
| 11 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
| 12 | * | ||
| 13 | * Access to the eventlog created by a system's firmware / BIOS | ||
| 14 | * | ||
| 15 | * This program is free software; you can redistribute it and/or | ||
| 16 | * modify it under the terms of the GNU General Public License | ||
| 17 | * as published by the Free Software Foundation; either version | ||
| 18 | * 2 of the License, or (at your option) any later version. | ||
| 19 | * | ||
| 20 | */ | ||
| 21 | |||
| 22 | #include <linux/seq_file.h> | ||
| 23 | #include <linux/fs.h> | ||
| 24 | #include <linux/security.h> | ||
| 25 | #include <linux/module.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | |||
| 28 | #include "tpm.h" | ||
| 29 | #include "tpm_eventlog.h" | ||
| 30 | |||
| 31 | |||
| 32 | static const char* tcpa_event_type_strings[] = { | ||
| 33 | "PREBOOT", | ||
| 34 | "POST CODE", | ||
| 35 | "", | ||
| 36 | "NO ACTION", | ||
| 37 | "SEPARATOR", | ||
| 38 | "ACTION", | ||
| 39 | "EVENT TAG", | ||
| 40 | "S-CRTM Contents", | ||
| 41 | "S-CRTM Version", | ||
| 42 | "CPU Microcode", | ||
| 43 | "Platform Config Flags", | ||
| 44 | "Table of Devices", | ||
| 45 | "Compact Hash", | ||
| 46 | "IPL", | ||
| 47 | "IPL Partition Data", | ||
| 48 | "Non-Host Code", | ||
| 49 | "Non-Host Config", | ||
| 50 | "Non-Host Info" | ||
| 51 | }; | ||
| 52 | |||
| 53 | static const char* tcpa_pc_event_id_strings[] = { | ||
| 54 | "", | ||
| 55 | "SMBIOS", | ||
| 56 | "BIS Certificate", | ||
| 57 | "POST BIOS ", | ||
| 58 | "ESCD ", | ||
| 59 | "CMOS", | ||
| 60 | "NVRAM", | ||
| 61 | "Option ROM", | ||
| 62 | "Option ROM config", | ||
| 63 | "", | ||
| 64 | "Option ROM microcode ", | ||
| 65 | "S-CRTM Version", | ||
| 66 | "S-CRTM Contents ", | ||
| 67 | "POST Contents ", | ||
| 68 | "Table of Devices", | ||
| 69 | }; | ||
| 70 | |||
| 71 | /* returns pointer to start of pos. entry of tcg log */ | ||
| 72 | static void *tpm_bios_measurements_start(struct seq_file *m, loff_t *pos) | ||
| 73 | { | ||
| 74 | loff_t i; | ||
| 75 | struct tpm_bios_log *log = m->private; | ||
| 76 | void *addr = log->bios_event_log; | ||
| 77 | void *limit = log->bios_event_log_end; | ||
| 78 | struct tcpa_event *event; | ||
| 79 | |||
| 80 | /* read over *pos measurements */ | ||
| 81 | for (i = 0; i < *pos; i++) { | ||
| 82 | event = addr; | ||
| 83 | |||
| 84 | if ((addr + sizeof(struct tcpa_event)) < limit) { | ||
| 85 | if (event->event_type == 0 && event->event_size == 0) | ||
| 86 | return NULL; | ||
| 87 | addr += sizeof(struct tcpa_event) + event->event_size; | ||
| 88 | } | ||
| 89 | } | ||
| 90 | |||
| 91 | /* now check if current entry is valid */ | ||
| 92 | if ((addr + sizeof(struct tcpa_event)) >= limit) | ||
| 93 | return NULL; | ||
| 94 | |||
| 95 | event = addr; | ||
| 96 | |||
| 97 | if ((event->event_type == 0 && event->event_size == 0) || | ||
| 98 | ((addr + sizeof(struct tcpa_event) + event->event_size) >= limit)) | ||
| 99 | return NULL; | ||
| 100 | |||
| 101 | return addr; | ||
| 102 | } | ||
| 103 | |||
| 104 | static void *tpm_bios_measurements_next(struct seq_file *m, void *v, | ||
| 105 | loff_t *pos) | ||
| 106 | { | ||
| 107 | struct tcpa_event *event = v; | ||
| 108 | struct tpm_bios_log *log = m->private; | ||
| 109 | void *limit = log->bios_event_log_end; | ||
| 110 | |||
| 111 | v += sizeof(struct tcpa_event) + event->event_size; | ||
| 112 | |||
| 113 | /* now check if current entry is valid */ | ||
| 114 | if ((v + sizeof(struct tcpa_event)) >= limit) | ||
| 115 | return NULL; | ||
| 116 | |||
| 117 | event = v; | ||
| 118 | |||
| 119 | if (event->event_type == 0 && event->event_size == 0) | ||
| 120 | return NULL; | ||
| 121 | |||
| 122 | if ((event->event_type == 0 && event->event_size == 0) || | ||
| 123 | ((v + sizeof(struct tcpa_event) + event->event_size) >= limit)) | ||
| 124 | return NULL; | ||
| 125 | |||
| 126 | (*pos)++; | ||
| 127 | return v; | ||
| 128 | } | ||
| 129 | |||
| 130 | static void tpm_bios_measurements_stop(struct seq_file *m, void *v) | ||
| 131 | { | ||
| 132 | } | ||
| 133 | |||
| 134 | static int get_event_name(char *dest, struct tcpa_event *event, | ||
| 135 | unsigned char * event_entry) | ||
| 136 | { | ||
| 137 | const char *name = ""; | ||
| 138 | /* 41 so there is room for 40 data and 1 nul */ | ||
| 139 | char data[41] = ""; | ||
| 140 | int i, n_len = 0, d_len = 0; | ||
| 141 | struct tcpa_pc_event *pc_event; | ||
| 142 | |||
| 143 | switch(event->event_type) { | ||
| 144 | case PREBOOT: | ||
| 145 | case POST_CODE: | ||
| 146 | case UNUSED: | ||
| 147 | case NO_ACTION: | ||
| 148 | case SCRTM_CONTENTS: | ||
| 149 | case SCRTM_VERSION: | ||
| 150 | case CPU_MICROCODE: | ||
| 151 | case PLATFORM_CONFIG_FLAGS: | ||
| 152 | case TABLE_OF_DEVICES: | ||
| 153 | case COMPACT_HASH: | ||
| 154 | case IPL: | ||
| 155 | case IPL_PARTITION_DATA: | ||
| 156 | case NONHOST_CODE: | ||
| 157 | case NONHOST_CONFIG: | ||
| 158 | case NONHOST_INFO: | ||
| 159 | name = tcpa_event_type_strings[event->event_type]; | ||
| 160 | n_len = strlen(name); | ||
| 161 | break; | ||
| 162 | case SEPARATOR: | ||
| 163 | case ACTION: | ||
| 164 | if (MAX_TEXT_EVENT > event->event_size) { | ||
| 165 | name = event_entry; | ||
| 166 | n_len = event->event_size; | ||
| 167 | } | ||
| 168 | break; | ||
| 169 | case EVENT_TAG: | ||
| 170 | pc_event = (struct tcpa_pc_event *)event_entry; | ||
| 171 | |||
| 172 | /* ToDo Row data -> Base64 */ | ||
| 173 | |||
| 174 | switch (pc_event->event_id) { | ||
| 175 | case SMBIOS: | ||
| 176 | case BIS_CERT: | ||
| 177 | case CMOS: | ||
| 178 | case NVRAM: | ||
| 179 | case OPTION_ROM_EXEC: | ||
| 180 | case OPTION_ROM_CONFIG: | ||
| 181 | case S_CRTM_VERSION: | ||
| 182 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | ||
| 183 | n_len = strlen(name); | ||
| 184 | break; | ||
| 185 | /* hash data */ | ||
| 186 | case POST_BIOS_ROM: | ||
| 187 | case ESCD: | ||
| 188 | case OPTION_ROM_MICROCODE: | ||
| 189 | case S_CRTM_CONTENTS: | ||
| 190 | case POST_CONTENTS: | ||
| 191 | name = tcpa_pc_event_id_strings[pc_event->event_id]; | ||
| 192 | n_len = strlen(name); | ||
| 193 | for (i = 0; i < 20; i++) | ||
| 194 | d_len += sprintf(&data[2*i], "%02x", | ||
| 195 | pc_event->event_data[i]); | ||
| 196 | break; | ||
| 197 | default: | ||
| 198 | break; | ||
| 199 | } | ||
| 200 | default: | ||
| 201 | break; | ||
| 202 | } | ||
| 203 | |||
| 204 | return snprintf(dest, MAX_TEXT_EVENT, "[%.*s%.*s]", | ||
| 205 | n_len, name, d_len, data); | ||
| 206 | |||
| 207 | } | ||
| 208 | |||
| 209 | static int tpm_binary_bios_measurements_show(struct seq_file *m, void *v) | ||
| 210 | { | ||
| 211 | struct tcpa_event *event = v; | ||
| 212 | char *data = v; | ||
| 213 | int i; | ||
| 214 | |||
| 215 | for (i = 0; i < sizeof(struct tcpa_event) + event->event_size; i++) | ||
| 216 | seq_putc(m, data[i]); | ||
| 217 | |||
| 218 | return 0; | ||
| 219 | } | ||
| 220 | |||
| 221 | static int tpm_bios_measurements_release(struct inode *inode, | ||
| 222 | struct file *file) | ||
| 223 | { | ||
| 224 | struct seq_file *seq = file->private_data; | ||
| 225 | struct tpm_bios_log *log = seq->private; | ||
| 226 | |||
| 227 | if (log) { | ||
| 228 | kfree(log->bios_event_log); | ||
| 229 | kfree(log); | ||
| 230 | } | ||
| 231 | |||
| 232 | return seq_release(inode, file); | ||
| 233 | } | ||
| 234 | |||
| 235 | static int tpm_ascii_bios_measurements_show(struct seq_file *m, void *v) | ||
| 236 | { | ||
| 237 | int len = 0; | ||
| 238 | int i; | ||
| 239 | char *eventname; | ||
| 240 | struct tcpa_event *event = v; | ||
| 241 | unsigned char *event_entry = | ||
| 242 | (unsigned char *) (v + sizeof(struct tcpa_event)); | ||
| 243 | |||
| 244 | eventname = kmalloc(MAX_TEXT_EVENT, GFP_KERNEL); | ||
| 245 | if (!eventname) { | ||
| 246 | printk(KERN_ERR "%s: ERROR - No Memory for event name\n ", | ||
| 247 | __func__); | ||
| 248 | return -EFAULT; | ||
| 249 | } | ||
| 250 | |||
| 251 | seq_printf(m, "%2d ", event->pcr_index); | ||
| 252 | |||
| 253 | /* 2nd: SHA1 */ | ||
| 254 | for (i = 0; i < 20; i++) | ||
| 255 | seq_printf(m, "%02x", event->pcr_value[i]); | ||
| 256 | |||
| 257 | /* 3rd: event type identifier */ | ||
| 258 | seq_printf(m, " %02x", event->event_type); | ||
| 259 | |||
| 260 | len += get_event_name(eventname, event, event_entry); | ||
| 261 | |||
| 262 | /* 4th: eventname <= max + \'0' delimiter */ | ||
| 263 | seq_printf(m, " %s\n", eventname); | ||
| 264 | |||
| 265 | kfree(eventname); | ||
| 266 | return 0; | ||
| 267 | } | ||
| 268 | |||
| 269 | static const struct seq_operations tpm_ascii_b_measurments_seqops = { | ||
| 270 | .start = tpm_bios_measurements_start, | ||
| 271 | .next = tpm_bios_measurements_next, | ||
| 272 | .stop = tpm_bios_measurements_stop, | ||
| 273 | .show = tpm_ascii_bios_measurements_show, | ||
| 274 | }; | ||
| 275 | |||
| 276 | static const struct seq_operations tpm_binary_b_measurments_seqops = { | ||
| 277 | .start = tpm_bios_measurements_start, | ||
| 278 | .next = tpm_bios_measurements_next, | ||
| 279 | .stop = tpm_bios_measurements_stop, | ||
| 280 | .show = tpm_binary_bios_measurements_show, | ||
| 281 | }; | ||
| 282 | |||
| 283 | static int tpm_ascii_bios_measurements_open(struct inode *inode, | ||
| 284 | struct file *file) | ||
| 285 | { | ||
| 286 | int err; | ||
| 287 | struct tpm_bios_log *log; | ||
| 288 | struct seq_file *seq; | ||
| 289 | |||
| 290 | log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL); | ||
| 291 | if (!log) | ||
| 292 | return -ENOMEM; | ||
| 293 | |||
| 294 | if ((err = read_log(log))) | ||
| 295 | goto out_free; | ||
| 296 | |||
| 297 | /* now register seq file */ | ||
| 298 | err = seq_open(file, &tpm_ascii_b_measurments_seqops); | ||
| 299 | if (!err) { | ||
| 300 | seq = file->private_data; | ||
| 301 | seq->private = log; | ||
| 302 | } else { | ||
| 303 | goto out_free; | ||
| 304 | } | ||
| 305 | |||
| 306 | out: | ||
| 307 | return err; | ||
| 308 | out_free: | ||
| 309 | kfree(log->bios_event_log); | ||
| 310 | kfree(log); | ||
| 311 | goto out; | ||
| 312 | } | ||
| 313 | |||
| 314 | static const struct file_operations tpm_ascii_bios_measurements_ops = { | ||
| 315 | .open = tpm_ascii_bios_measurements_open, | ||
| 316 | .read = seq_read, | ||
| 317 | .llseek = seq_lseek, | ||
| 318 | .release = tpm_bios_measurements_release, | ||
| 319 | }; | ||
| 320 | |||
| 321 | static int tpm_binary_bios_measurements_open(struct inode *inode, | ||
| 322 | struct file *file) | ||
| 323 | { | ||
| 324 | int err; | ||
| 325 | struct tpm_bios_log *log; | ||
| 326 | struct seq_file *seq; | ||
| 327 | |||
| 328 | log = kzalloc(sizeof(struct tpm_bios_log), GFP_KERNEL); | ||
| 329 | if (!log) | ||
| 330 | return -ENOMEM; | ||
| 331 | |||
| 332 | if ((err = read_log(log))) | ||
| 333 | goto out_free; | ||
| 334 | |||
| 335 | /* now register seq file */ | ||
| 336 | err = seq_open(file, &tpm_binary_b_measurments_seqops); | ||
| 337 | if (!err) { | ||
| 338 | seq = file->private_data; | ||
| 339 | seq->private = log; | ||
| 340 | } else { | ||
| 341 | goto out_free; | ||
| 342 | } | ||
| 343 | |||
| 344 | out: | ||
| 345 | return err; | ||
| 346 | out_free: | ||
| 347 | kfree(log->bios_event_log); | ||
| 348 | kfree(log); | ||
| 349 | goto out; | ||
| 350 | } | ||
| 351 | |||
| 352 | static const struct file_operations tpm_binary_bios_measurements_ops = { | ||
| 353 | .open = tpm_binary_bios_measurements_open, | ||
| 354 | .read = seq_read, | ||
| 355 | .llseek = seq_lseek, | ||
| 356 | .release = tpm_bios_measurements_release, | ||
| 357 | }; | ||
| 358 | |||
| 359 | static int is_bad(void *p) | ||
| 360 | { | ||
| 361 | if (!p) | ||
| 362 | return 1; | ||
| 363 | if (IS_ERR(p) && (PTR_ERR(p) != -ENODEV)) | ||
| 364 | return 1; | ||
| 365 | return 0; | ||
| 366 | } | ||
| 367 | |||
| 368 | struct dentry **tpm_bios_log_setup(char *name) | ||
| 369 | { | ||
| 370 | struct dentry **ret = NULL, *tpm_dir, *bin_file, *ascii_file; | ||
| 371 | |||
| 372 | tpm_dir = securityfs_create_dir(name, NULL); | ||
| 373 | if (is_bad(tpm_dir)) | ||
| 374 | goto out; | ||
| 375 | |||
| 376 | bin_file = | ||
| 377 | securityfs_create_file("binary_bios_measurements", | ||
| 378 | S_IRUSR | S_IRGRP, tpm_dir, NULL, | ||
| 379 | &tpm_binary_bios_measurements_ops); | ||
| 380 | if (is_bad(bin_file)) | ||
| 381 | goto out_tpm; | ||
| 382 | |||
| 383 | ascii_file = | ||
| 384 | securityfs_create_file("ascii_bios_measurements", | ||
| 385 | S_IRUSR | S_IRGRP, tpm_dir, NULL, | ||
| 386 | &tpm_ascii_bios_measurements_ops); | ||
| 387 | if (is_bad(ascii_file)) | ||
| 388 | goto out_bin; | ||
| 389 | |||
| 390 | ret = kmalloc(3 * sizeof(struct dentry *), GFP_KERNEL); | ||
| 391 | if (!ret) | ||
| 392 | goto out_ascii; | ||
| 393 | |||
| 394 | ret[0] = ascii_file; | ||
| 395 | ret[1] = bin_file; | ||
| 396 | ret[2] = tpm_dir; | ||
| 397 | |||
| 398 | return ret; | ||
| 399 | |||
| 400 | out_ascii: | ||
| 401 | securityfs_remove(ascii_file); | ||
| 402 | out_bin: | ||
| 403 | securityfs_remove(bin_file); | ||
| 404 | out_tpm: | ||
| 405 | securityfs_remove(tpm_dir); | ||
| 406 | out: | ||
| 407 | return NULL; | ||
| 408 | } | ||
| 409 | EXPORT_SYMBOL_GPL(tpm_bios_log_setup); | ||
| 410 | |||
| 411 | void tpm_bios_log_teardown(struct dentry **lst) | ||
| 412 | { | ||
| 413 | int i; | ||
| 414 | |||
| 415 | for (i = 0; i < 3; i++) | ||
| 416 | securityfs_remove(lst[i]); | ||
| 417 | } | ||
| 418 | EXPORT_SYMBOL_GPL(tpm_bios_log_teardown); | ||
| 419 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/tpm/tpm_eventlog.h b/drivers/char/tpm/tpm_eventlog.h deleted file mode 100644 index e7da086d692..00000000000 --- a/drivers/char/tpm/tpm_eventlog.h +++ /dev/null | |||
| @@ -1,86 +0,0 @@ | |||
| 1 | |||
| 2 | #ifndef __TPM_EVENTLOG_H__ | ||
| 3 | #define __TPM_EVENTLOG_H__ | ||
| 4 | |||
| 5 | #define TCG_EVENT_NAME_LEN_MAX 255 | ||
| 6 | #define MAX_TEXT_EVENT 1000 /* Max event string length */ | ||
| 7 | #define ACPI_TCPA_SIG "TCPA" /* 0x41504354 /'TCPA' */ | ||
| 8 | |||
| 9 | enum bios_platform_class { | ||
| 10 | BIOS_CLIENT = 0x00, | ||
| 11 | BIOS_SERVER = 0x01, | ||
| 12 | }; | ||
| 13 | |||
| 14 | struct tpm_bios_log { | ||
| 15 | void *bios_event_log; | ||
| 16 | void *bios_event_log_end; | ||
| 17 | }; | ||
| 18 | |||
| 19 | struct tcpa_event { | ||
| 20 | u32 pcr_index; | ||
| 21 | u32 event_type; | ||
| 22 | u8 pcr_value[20]; /* SHA1 */ | ||
| 23 | u32 event_size; | ||
| 24 | u8 event_data[0]; | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum tcpa_event_types { | ||
| 28 | PREBOOT = 0, | ||
| 29 | POST_CODE, | ||
| 30 | UNUSED, | ||
| 31 | NO_ACTION, | ||
| 32 | SEPARATOR, | ||
| 33 | ACTION, | ||
| 34 | EVENT_TAG, | ||
| 35 | SCRTM_CONTENTS, | ||
| 36 | SCRTM_VERSION, | ||
| 37 | CPU_MICROCODE, | ||
| 38 | PLATFORM_CONFIG_FLAGS, | ||
| 39 | TABLE_OF_DEVICES, | ||
| 40 | COMPACT_HASH, | ||
| 41 | IPL, | ||
| 42 | IPL_PARTITION_DATA, | ||
| 43 | NONHOST_CODE, | ||
| 44 | NONHOST_CONFIG, | ||
| 45 | NONHOST_INFO, | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct tcpa_pc_event { | ||
| 49 | u32 event_id; | ||
| 50 | u32 event_size; | ||
| 51 | u8 event_data[0]; | ||
| 52 | }; | ||
| 53 | |||
| 54 | enum tcpa_pc_event_ids { | ||
| 55 | SMBIOS = 1, | ||
| 56 | BIS_CERT, | ||
| 57 | POST_BIOS_ROM, | ||
| 58 | ESCD, | ||
| 59 | CMOS, | ||
| 60 | NVRAM, | ||
| 61 | OPTION_ROM_EXEC, | ||
| 62 | OPTION_ROM_CONFIG, | ||
| 63 | OPTION_ROM_MICROCODE = 10, | ||
| 64 | S_CRTM_VERSION, | ||
| 65 | S_CRTM_CONTENTS, | ||
| 66 | POST_CONTENTS, | ||
| 67 | HOST_TABLE_OF_DEVICES, | ||
| 68 | }; | ||
| 69 | |||
| 70 | int read_log(struct tpm_bios_log *log); | ||
| 71 | |||
| 72 | #if defined(CONFIG_TCG_IBMVTPM) || defined(CONFIG_TCG_IBMVTPM_MODULE) || \ | ||
| 73 | defined(CONFIG_ACPI) | ||
| 74 | extern struct dentry **tpm_bios_log_setup(char *); | ||
| 75 | extern void tpm_bios_log_teardown(struct dentry **); | ||
| 76 | #else | ||
| 77 | static inline struct dentry **tpm_bios_log_setup(char *name) | ||
| 78 | { | ||
| 79 | return NULL; | ||
| 80 | } | ||
| 81 | static inline void tpm_bios_log_teardown(struct dentry **dir) | ||
| 82 | { | ||
| 83 | } | ||
| 84 | #endif | ||
| 85 | |||
| 86 | #endif | ||
diff --git a/drivers/char/tpm/tpm_i2c_infineon.c b/drivers/char/tpm/tpm_i2c_infineon.c deleted file mode 100644 index fb447bd0cb6..00000000000 --- a/drivers/char/tpm/tpm_i2c_infineon.c +++ /dev/null | |||
| @@ -1,695 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012 Infineon Technologies | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Peter Huewe <peter.huewe@infineon.com> | ||
| 6 | * | ||
| 7 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
| 8 | * Specifications at www.trustedcomputinggroup.org | ||
| 9 | * | ||
| 10 | * This device driver implements the TPM interface as defined in | ||
| 11 | * the TCG TPM Interface Spec version 1.2, revision 1.0 and the | ||
| 12 | * Infineon I2C Protocol Stack Specification v0.20. | ||
| 13 | * | ||
| 14 | * It is based on the original tpm_tis device driver from Leendert van | ||
| 15 | * Dorn and Kyleen Hall. | ||
| 16 | * | ||
| 17 | * This program is free software; you can redistribute it and/or | ||
| 18 | * modify it under the terms of the GNU General Public License as | ||
| 19 | * published by the Free Software Foundation, version 2 of the | ||
| 20 | * License. | ||
| 21 | * | ||
| 22 | * | ||
| 23 | */ | ||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/i2c.h> | ||
| 26 | #include <linux/module.h> | ||
| 27 | #include <linux/moduleparam.h> | ||
| 28 | #include <linux/wait.h> | ||
| 29 | #include "tpm.h" | ||
| 30 | |||
| 31 | /* max. buffer size supported by our TPM */ | ||
| 32 | #define TPM_BUFSIZE 1260 | ||
| 33 | |||
| 34 | /* max. number of iterations after I2C NAK */ | ||
| 35 | #define MAX_COUNT 3 | ||
| 36 | |||
| 37 | #define SLEEP_DURATION_LOW 55 | ||
| 38 | #define SLEEP_DURATION_HI 65 | ||
| 39 | |||
| 40 | /* max. number of iterations after I2C NAK for 'long' commands | ||
| 41 | * we need this especially for sending TPM_READY, since the cleanup after the | ||
| 42 | * transtion to the ready state may take some time, but it is unpredictable | ||
| 43 | * how long it will take. | ||
| 44 | */ | ||
| 45 | #define MAX_COUNT_LONG 50 | ||
| 46 | |||
| 47 | #define SLEEP_DURATION_LONG_LOW 200 | ||
| 48 | #define SLEEP_DURATION_LONG_HI 220 | ||
| 49 | |||
| 50 | /* After sending TPM_READY to 'reset' the TPM we have to sleep even longer */ | ||
| 51 | #define SLEEP_DURATION_RESET_LOW 2400 | ||
| 52 | #define SLEEP_DURATION_RESET_HI 2600 | ||
| 53 | |||
| 54 | /* we want to use usleep_range instead of msleep for the 5ms TPM_TIMEOUT */ | ||
| 55 | #define TPM_TIMEOUT_US_LOW (TPM_TIMEOUT * 1000) | ||
| 56 | #define TPM_TIMEOUT_US_HI (TPM_TIMEOUT_US_LOW + 2000) | ||
| 57 | |||
| 58 | /* expected value for DIDVID register */ | ||
| 59 | #define TPM_TIS_I2C_DID_VID 0x000b15d1L | ||
| 60 | |||
| 61 | /* Structure to store I2C TPM specific stuff */ | ||
| 62 | struct tpm_inf_dev { | ||
| 63 | struct i2c_client *client; | ||
| 64 | u8 buf[TPM_BUFSIZE + sizeof(u8)]; /* max. buffer size + addr */ | ||
| 65 | struct tpm_chip *chip; | ||
| 66 | }; | ||
| 67 | |||
| 68 | static struct tpm_inf_dev tpm_dev; | ||
| 69 | static struct i2c_driver tpm_tis_i2c_driver; | ||
| 70 | |||
| 71 | /* | ||
| 72 | * iic_tpm_read() - read from TPM register | ||
| 73 | * @addr: register address to read from | ||
| 74 | * @buffer: provided by caller | ||
| 75 | * @len: number of bytes to read | ||
| 76 | * | ||
| 77 | * Read len bytes from TPM register and put them into | ||
| 78 | * buffer (little-endian format, i.e. first byte is put into buffer[0]). | ||
| 79 | * | ||
| 80 | * NOTE: TPM is big-endian for multi-byte values. Multi-byte | ||
| 81 | * values have to be swapped. | ||
| 82 | * | ||
| 83 | * NOTE: We can't unfortunately use the combined read/write functions | ||
| 84 | * provided by the i2c core as the TPM currently does not support the | ||
| 85 | * repeated start condition and due to it's special requirements. | ||
| 86 | * The i2c_smbus* functions do not work for this chip. | ||
| 87 | * | ||
| 88 | * Return -EIO on error, 0 on success. | ||
| 89 | */ | ||
| 90 | static int iic_tpm_read(u8 addr, u8 *buffer, size_t len) | ||
| 91 | { | ||
| 92 | |||
| 93 | struct i2c_msg msg1 = { tpm_dev.client->addr, 0, 1, &addr }; | ||
| 94 | struct i2c_msg msg2 = { tpm_dev.client->addr, I2C_M_RD, len, buffer }; | ||
| 95 | |||
| 96 | int rc; | ||
| 97 | int count; | ||
| 98 | |||
| 99 | /* Lock the adapter for the duration of the whole sequence. */ | ||
| 100 | if (!tpm_dev.client->adapter->algo->master_xfer) | ||
| 101 | return -EOPNOTSUPP; | ||
| 102 | i2c_lock_adapter(tpm_dev.client->adapter); | ||
| 103 | |||
| 104 | for (count = 0; count < MAX_COUNT; count++) { | ||
| 105 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); | ||
| 106 | if (rc > 0) | ||
| 107 | break; /* break here to skip sleep */ | ||
| 108 | |||
| 109 | usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | ||
| 110 | } | ||
| 111 | |||
| 112 | if (rc <= 0) | ||
| 113 | goto out; | ||
| 114 | |||
| 115 | /* After the TPM has successfully received the register address it needs | ||
| 116 | * some time, thus we're sleeping here again, before retrieving the data | ||
| 117 | */ | ||
| 118 | for (count = 0; count < MAX_COUNT; count++) { | ||
| 119 | usleep_range(SLEEP_DURATION_LOW, SLEEP_DURATION_HI); | ||
| 120 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg2, 1); | ||
| 121 | if (rc > 0) | ||
| 122 | break; | ||
| 123 | |||
| 124 | } | ||
| 125 | |||
| 126 | out: | ||
| 127 | i2c_unlock_adapter(tpm_dev.client->adapter); | ||
| 128 | if (rc <= 0) | ||
| 129 | return -EIO; | ||
| 130 | |||
| 131 | return 0; | ||
| 132 | } | ||
| 133 | |||
| 134 | static int iic_tpm_write_generic(u8 addr, u8 *buffer, size_t len, | ||
| 135 | unsigned int sleep_low, | ||
| 136 | unsigned int sleep_hi, u8 max_count) | ||
| 137 | { | ||
| 138 | int rc = -EIO; | ||
| 139 | int count; | ||
| 140 | |||
| 141 | struct i2c_msg msg1 = { tpm_dev.client->addr, 0, len + 1, tpm_dev.buf }; | ||
| 142 | |||
| 143 | if (len > TPM_BUFSIZE) | ||
| 144 | return -EINVAL; | ||
| 145 | |||
| 146 | if (!tpm_dev.client->adapter->algo->master_xfer) | ||
| 147 | return -EOPNOTSUPP; | ||
| 148 | i2c_lock_adapter(tpm_dev.client->adapter); | ||
| 149 | |||
| 150 | /* prepend the 'register address' to the buffer */ | ||
| 151 | tpm_dev.buf[0] = addr; | ||
| 152 | memcpy(&(tpm_dev.buf[1]), buffer, len); | ||
| 153 | |||
| 154 | /* | ||
| 155 | * NOTE: We have to use these special mechanisms here and unfortunately | ||
| 156 | * cannot rely on the standard behavior of i2c_transfer. | ||
| 157 | */ | ||
| 158 | for (count = 0; count < max_count; count++) { | ||
| 159 | rc = __i2c_transfer(tpm_dev.client->adapter, &msg1, 1); | ||
| 160 | if (rc > 0) | ||
| 161 | break; | ||
| 162 | |||
| 163 | usleep_range(sleep_low, sleep_hi); | ||
| 164 | } | ||
| 165 | |||
| 166 | i2c_unlock_adapter(tpm_dev.client->adapter); | ||
| 167 | if (rc <= 0) | ||
| 168 | return -EIO; | ||
| 169 | |||
| 170 | return 0; | ||
| 171 | } | ||
| 172 | |||
| 173 | /* | ||
| 174 | * iic_tpm_write() - write to TPM register | ||
| 175 | * @addr: register address to write to | ||
| 176 | * @buffer: containing data to be written | ||
| 177 | * @len: number of bytes to write | ||
| 178 | * | ||
| 179 | * Write len bytes from provided buffer to TPM register (little | ||
| 180 | * endian format, i.e. buffer[0] is written as first byte). | ||
| 181 | * | ||
| 182 | * NOTE: TPM is big-endian for multi-byte values. Multi-byte | ||
| 183 | * values have to be swapped. | ||
| 184 | * | ||
| 185 | * NOTE: use this function instead of the iic_tpm_write_generic function. | ||
| 186 | * | ||
| 187 | * Return -EIO on error, 0 on success | ||
| 188 | */ | ||
| 189 | static int iic_tpm_write(u8 addr, u8 *buffer, size_t len) | ||
| 190 | { | ||
| 191 | return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LOW, | ||
| 192 | SLEEP_DURATION_HI, MAX_COUNT); | ||
| 193 | } | ||
| 194 | |||
| 195 | /* | ||
| 196 | * This function is needed especially for the cleanup situation after | ||
| 197 | * sending TPM_READY | ||
| 198 | * */ | ||
| 199 | static int iic_tpm_write_long(u8 addr, u8 *buffer, size_t len) | ||
| 200 | { | ||
| 201 | return iic_tpm_write_generic(addr, buffer, len, SLEEP_DURATION_LONG_LOW, | ||
| 202 | SLEEP_DURATION_LONG_HI, MAX_COUNT_LONG); | ||
| 203 | } | ||
| 204 | |||
| 205 | enum tis_access { | ||
| 206 | TPM_ACCESS_VALID = 0x80, | ||
| 207 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, | ||
| 208 | TPM_ACCESS_REQUEST_PENDING = 0x04, | ||
| 209 | TPM_ACCESS_REQUEST_USE = 0x02, | ||
| 210 | }; | ||
| 211 | |||
| 212 | enum tis_status { | ||
| 213 | TPM_STS_VALID = 0x80, | ||
| 214 | TPM_STS_COMMAND_READY = 0x40, | ||
| 215 | TPM_STS_GO = 0x20, | ||
| 216 | TPM_STS_DATA_AVAIL = 0x10, | ||
| 217 | TPM_STS_DATA_EXPECT = 0x08, | ||
| 218 | }; | ||
| 219 | |||
| 220 | enum tis_defaults { | ||
| 221 | TIS_SHORT_TIMEOUT = 750, /* ms */ | ||
| 222 | TIS_LONG_TIMEOUT = 2000, /* 2 sec */ | ||
| 223 | }; | ||
| 224 | |||
| 225 | #define TPM_ACCESS(l) (0x0000 | ((l) << 4)) | ||
| 226 | #define TPM_STS(l) (0x0001 | ((l) << 4)) | ||
| 227 | #define TPM_DATA_FIFO(l) (0x0005 | ((l) << 4)) | ||
| 228 | #define TPM_DID_VID(l) (0x0006 | ((l) << 4)) | ||
| 229 | |||
| 230 | static int check_locality(struct tpm_chip *chip, int loc) | ||
| 231 | { | ||
| 232 | u8 buf; | ||
| 233 | int rc; | ||
| 234 | |||
| 235 | rc = iic_tpm_read(TPM_ACCESS(loc), &buf, 1); | ||
| 236 | if (rc < 0) | ||
| 237 | return rc; | ||
| 238 | |||
| 239 | if ((buf & (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) == | ||
| 240 | (TPM_ACCESS_ACTIVE_LOCALITY | TPM_ACCESS_VALID)) { | ||
| 241 | chip->vendor.locality = loc; | ||
| 242 | return loc; | ||
| 243 | } | ||
| 244 | |||
| 245 | return -EIO; | ||
| 246 | } | ||
| 247 | |||
| 248 | /* implementation similar to tpm_tis */ | ||
| 249 | static void release_locality(struct tpm_chip *chip, int loc, int force) | ||
| 250 | { | ||
| 251 | u8 buf; | ||
| 252 | if (iic_tpm_read(TPM_ACCESS(loc), &buf, 1) < 0) | ||
| 253 | return; | ||
| 254 | |||
| 255 | if (force || (buf & (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) == | ||
| 256 | (TPM_ACCESS_REQUEST_PENDING | TPM_ACCESS_VALID)) { | ||
| 257 | buf = TPM_ACCESS_ACTIVE_LOCALITY; | ||
| 258 | iic_tpm_write(TPM_ACCESS(loc), &buf, 1); | ||
| 259 | } | ||
| 260 | } | ||
| 261 | |||
| 262 | static int request_locality(struct tpm_chip *chip, int loc) | ||
| 263 | { | ||
| 264 | unsigned long stop; | ||
| 265 | u8 buf = TPM_ACCESS_REQUEST_USE; | ||
| 266 | |||
| 267 | if (check_locality(chip, loc) >= 0) | ||
| 268 | return loc; | ||
| 269 | |||
| 270 | iic_tpm_write(TPM_ACCESS(loc), &buf, 1); | ||
| 271 | |||
| 272 | /* wait for burstcount */ | ||
| 273 | stop = jiffies + chip->vendor.timeout_a; | ||
| 274 | do { | ||
| 275 | if (check_locality(chip, loc) >= 0) | ||
| 276 | return loc; | ||
| 277 | usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); | ||
| 278 | } while (time_before(jiffies, stop)); | ||
| 279 | |||
| 280 | return -ETIME; | ||
| 281 | } | ||
| 282 | |||
| 283 | static u8 tpm_tis_i2c_status(struct tpm_chip *chip) | ||
| 284 | { | ||
| 285 | /* NOTE: since I2C read may fail, return 0 in this case --> time-out */ | ||
| 286 | u8 buf; | ||
| 287 | if (iic_tpm_read(TPM_STS(chip->vendor.locality), &buf, 1) < 0) | ||
| 288 | return 0; | ||
| 289 | else | ||
| 290 | return buf; | ||
| 291 | } | ||
| 292 | |||
| 293 | static void tpm_tis_i2c_ready(struct tpm_chip *chip) | ||
| 294 | { | ||
| 295 | /* this causes the current command to be aborted */ | ||
| 296 | u8 buf = TPM_STS_COMMAND_READY; | ||
| 297 | iic_tpm_write_long(TPM_STS(chip->vendor.locality), &buf, 1); | ||
| 298 | } | ||
| 299 | |||
| 300 | static ssize_t get_burstcount(struct tpm_chip *chip) | ||
| 301 | { | ||
| 302 | unsigned long stop; | ||
| 303 | ssize_t burstcnt; | ||
| 304 | u8 buf[3]; | ||
| 305 | |||
| 306 | /* wait for burstcount */ | ||
| 307 | /* which timeout value, spec has 2 answers (c & d) */ | ||
| 308 | stop = jiffies + chip->vendor.timeout_d; | ||
| 309 | do { | ||
| 310 | /* Note: STS is little endian */ | ||
| 311 | if (iic_tpm_read(TPM_STS(chip->vendor.locality)+1, buf, 3) < 0) | ||
| 312 | burstcnt = 0; | ||
| 313 | else | ||
| 314 | burstcnt = (buf[2] << 16) + (buf[1] << 8) + buf[0]; | ||
| 315 | |||
| 316 | if (burstcnt) | ||
| 317 | return burstcnt; | ||
| 318 | |||
| 319 | usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); | ||
| 320 | } while (time_before(jiffies, stop)); | ||
| 321 | return -EBUSY; | ||
| 322 | } | ||
| 323 | |||
| 324 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
| 325 | int *status) | ||
| 326 | { | ||
| 327 | unsigned long stop; | ||
| 328 | |||
| 329 | /* check current status */ | ||
| 330 | *status = tpm_tis_i2c_status(chip); | ||
| 331 | if ((*status & mask) == mask) | ||
| 332 | return 0; | ||
| 333 | |||
| 334 | stop = jiffies + timeout; | ||
| 335 | do { | ||
| 336 | /* since we just checked the status, give the TPM some time */ | ||
| 337 | usleep_range(TPM_TIMEOUT_US_LOW, TPM_TIMEOUT_US_HI); | ||
| 338 | *status = tpm_tis_i2c_status(chip); | ||
| 339 | if ((*status & mask) == mask) | ||
| 340 | return 0; | ||
| 341 | |||
| 342 | } while (time_before(jiffies, stop)); | ||
| 343 | |||
| 344 | return -ETIME; | ||
| 345 | } | ||
| 346 | |||
| 347 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | ||
| 348 | { | ||
| 349 | size_t size = 0; | ||
| 350 | ssize_t burstcnt; | ||
| 351 | u8 retries = 0; | ||
| 352 | int rc; | ||
| 353 | |||
| 354 | while (size < count) { | ||
| 355 | burstcnt = get_burstcount(chip); | ||
| 356 | |||
| 357 | /* burstcnt < 0 = TPM is busy */ | ||
| 358 | if (burstcnt < 0) | ||
| 359 | return burstcnt; | ||
| 360 | |||
| 361 | /* limit received data to max. left */ | ||
| 362 | if (burstcnt > (count - size)) | ||
| 363 | burstcnt = count - size; | ||
| 364 | |||
| 365 | rc = iic_tpm_read(TPM_DATA_FIFO(chip->vendor.locality), | ||
| 366 | &(buf[size]), burstcnt); | ||
| 367 | if (rc == 0) | ||
| 368 | size += burstcnt; | ||
| 369 | else if (rc < 0) | ||
| 370 | retries++; | ||
| 371 | |||
| 372 | /* avoid endless loop in case of broken HW */ | ||
| 373 | if (retries > MAX_COUNT_LONG) | ||
| 374 | return -EIO; | ||
| 375 | |||
| 376 | } | ||
| 377 | return size; | ||
| 378 | } | ||
| 379 | |||
| 380 | static int tpm_tis_i2c_recv(struct tpm_chip *chip, u8 *buf, size_t count) | ||
| 381 | { | ||
| 382 | int size = 0; | ||
| 383 | int expected, status; | ||
| 384 | |||
| 385 | if (count < TPM_HEADER_SIZE) { | ||
| 386 | size = -EIO; | ||
| 387 | goto out; | ||
| 388 | } | ||
| 389 | |||
| 390 | /* read first 10 bytes, including tag, paramsize, and result */ | ||
| 391 | size = recv_data(chip, buf, TPM_HEADER_SIZE); | ||
| 392 | if (size < TPM_HEADER_SIZE) { | ||
| 393 | dev_err(chip->dev, "Unable to read header\n"); | ||
| 394 | goto out; | ||
| 395 | } | ||
| 396 | |||
| 397 | expected = be32_to_cpu(*(__be32 *)(buf + 2)); | ||
| 398 | if ((size_t) expected > count) { | ||
| 399 | size = -EIO; | ||
| 400 | goto out; | ||
| 401 | } | ||
| 402 | |||
| 403 | size += recv_data(chip, &buf[TPM_HEADER_SIZE], | ||
| 404 | expected - TPM_HEADER_SIZE); | ||
| 405 | if (size < expected) { | ||
| 406 | dev_err(chip->dev, "Unable to read remainder of result\n"); | ||
| 407 | size = -ETIME; | ||
| 408 | goto out; | ||
| 409 | } | ||
| 410 | |||
| 411 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); | ||
| 412 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | ||
| 413 | dev_err(chip->dev, "Error left over data\n"); | ||
| 414 | size = -EIO; | ||
| 415 | goto out; | ||
| 416 | } | ||
| 417 | |||
| 418 | out: | ||
| 419 | tpm_tis_i2c_ready(chip); | ||
| 420 | /* The TPM needs some time to clean up here, | ||
| 421 | * so we sleep rather than keeping the bus busy | ||
| 422 | */ | ||
| 423 | usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI); | ||
| 424 | release_locality(chip, chip->vendor.locality, 0); | ||
| 425 | return size; | ||
| 426 | } | ||
| 427 | |||
| 428 | static int tpm_tis_i2c_send(struct tpm_chip *chip, u8 *buf, size_t len) | ||
| 429 | { | ||
| 430 | int rc, status; | ||
| 431 | ssize_t burstcnt; | ||
| 432 | size_t count = 0; | ||
| 433 | u8 retries = 0; | ||
| 434 | u8 sts = TPM_STS_GO; | ||
| 435 | |||
| 436 | if (len > TPM_BUFSIZE) | ||
| 437 | return -E2BIG; /* command is too long for our tpm, sorry */ | ||
| 438 | |||
| 439 | if (request_locality(chip, 0) < 0) | ||
| 440 | return -EBUSY; | ||
| 441 | |||
| 442 | status = tpm_tis_i2c_status(chip); | ||
| 443 | if ((status & TPM_STS_COMMAND_READY) == 0) { | ||
| 444 | tpm_tis_i2c_ready(chip); | ||
| 445 | if (wait_for_stat | ||
| 446 | (chip, TPM_STS_COMMAND_READY, | ||
| 447 | chip->vendor.timeout_b, &status) < 0) { | ||
| 448 | rc = -ETIME; | ||
| 449 | goto out_err; | ||
| 450 | } | ||
| 451 | } | ||
| 452 | |||
| 453 | while (count < len - 1) { | ||
| 454 | burstcnt = get_burstcount(chip); | ||
| 455 | |||
| 456 | /* burstcnt < 0 = TPM is busy */ | ||
| 457 | if (burstcnt < 0) | ||
| 458 | return burstcnt; | ||
| 459 | |||
| 460 | if (burstcnt > (len - 1 - count)) | ||
| 461 | burstcnt = len - 1 - count; | ||
| 462 | |||
| 463 | rc = iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), | ||
| 464 | &(buf[count]), burstcnt); | ||
| 465 | if (rc == 0) | ||
| 466 | count += burstcnt; | ||
| 467 | else if (rc < 0) | ||
| 468 | retries++; | ||
| 469 | |||
| 470 | /* avoid endless loop in case of broken HW */ | ||
| 471 | if (retries > MAX_COUNT_LONG) { | ||
| 472 | rc = -EIO; | ||
| 473 | goto out_err; | ||
| 474 | } | ||
| 475 | |||
| 476 | wait_for_stat(chip, TPM_STS_VALID, | ||
| 477 | chip->vendor.timeout_c, &status); | ||
| 478 | |||
| 479 | if ((status & TPM_STS_DATA_EXPECT) == 0) { | ||
| 480 | rc = -EIO; | ||
| 481 | goto out_err; | ||
| 482 | } | ||
| 483 | |||
| 484 | } | ||
| 485 | |||
| 486 | /* write last byte */ | ||
| 487 | iic_tpm_write(TPM_DATA_FIFO(chip->vendor.locality), &(buf[count]), 1); | ||
| 488 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, &status); | ||
| 489 | if ((status & TPM_STS_DATA_EXPECT) != 0) { | ||
| 490 | rc = -EIO; | ||
| 491 | goto out_err; | ||
| 492 | } | ||
| 493 | |||
| 494 | /* go and do it */ | ||
| 495 | iic_tpm_write(TPM_STS(chip->vendor.locality), &sts, 1); | ||
| 496 | |||
| 497 | return len; | ||
| 498 | out_err: | ||
| 499 | tpm_tis_i2c_ready(chip); | ||
| 500 | /* The TPM needs some time to clean up here, | ||
| 501 | * so we sleep rather than keeping the bus busy | ||
| 502 | */ | ||
| 503 | usleep_range(SLEEP_DURATION_RESET_LOW, SLEEP_DURATION_RESET_HI); | ||
| 504 | release_locality(chip, chip->vendor.locality, 0); | ||
| 505 | return rc; | ||
| 506 | } | ||
| 507 | |||
| 508 | static const struct file_operations tis_ops = { | ||
| 509 | .owner = THIS_MODULE, | ||
| 510 | .llseek = no_llseek, | ||
| 511 | .open = tpm_open, | ||
| 512 | .read = tpm_read, | ||
| 513 | .write = tpm_write, | ||
| 514 | .release = tpm_release, | ||
| 515 | }; | ||
| 516 | |||
| 517 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
| 518 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
| 519 | static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); | ||
| 520 | static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); | ||
| 521 | static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); | ||
| 522 | static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, NULL); | ||
| 523 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); | ||
| 524 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); | ||
| 525 | static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); | ||
| 526 | static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); | ||
| 527 | |||
| 528 | static struct attribute *tis_attrs[] = { | ||
| 529 | &dev_attr_pubek.attr, | ||
| 530 | &dev_attr_pcrs.attr, | ||
| 531 | &dev_attr_enabled.attr, | ||
| 532 | &dev_attr_active.attr, | ||
| 533 | &dev_attr_owned.attr, | ||
| 534 | &dev_attr_temp_deactivated.attr, | ||
| 535 | &dev_attr_caps.attr, | ||
| 536 | &dev_attr_cancel.attr, | ||
| 537 | &dev_attr_durations.attr, | ||
| 538 | &dev_attr_timeouts.attr, | ||
| 539 | NULL, | ||
| 540 | }; | ||
| 541 | |||
| 542 | static struct attribute_group tis_attr_grp = { | ||
| 543 | .attrs = tis_attrs | ||
| 544 | }; | ||
| 545 | |||
| 546 | static struct tpm_vendor_specific tpm_tis_i2c = { | ||
| 547 | .status = tpm_tis_i2c_status, | ||
| 548 | .recv = tpm_tis_i2c_recv, | ||
| 549 | .send = tpm_tis_i2c_send, | ||
| 550 | .cancel = tpm_tis_i2c_ready, | ||
| 551 | .req_complete_mask = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
| 552 | .req_complete_val = TPM_STS_DATA_AVAIL | TPM_STS_VALID, | ||
| 553 | .req_canceled = TPM_STS_COMMAND_READY, | ||
| 554 | .attr_group = &tis_attr_grp, | ||
| 555 | .miscdev.fops = &tis_ops, | ||
| 556 | }; | ||
| 557 | |||
| 558 | static int tpm_tis_i2c_init(struct device *dev) | ||
| 559 | { | ||
| 560 | u32 vendor; | ||
| 561 | int rc = 0; | ||
| 562 | struct tpm_chip *chip; | ||
| 563 | |||
| 564 | chip = tpm_register_hardware(dev, &tpm_tis_i2c); | ||
| 565 | if (!chip) { | ||
| 566 | rc = -ENODEV; | ||
| 567 | goto out_err; | ||
| 568 | } | ||
| 569 | |||
| 570 | /* Disable interrupts */ | ||
| 571 | chip->vendor.irq = 0; | ||
| 572 | |||
| 573 | /* Default timeouts */ | ||
| 574 | chip->vendor.timeout_a = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
| 575 | chip->vendor.timeout_b = msecs_to_jiffies(TIS_LONG_TIMEOUT); | ||
| 576 | chip->vendor.timeout_c = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
| 577 | chip->vendor.timeout_d = msecs_to_jiffies(TIS_SHORT_TIMEOUT); | ||
| 578 | |||
| 579 | if (request_locality(chip, 0) != 0) { | ||
| 580 | rc = -ENODEV; | ||
| 581 | goto out_vendor; | ||
| 582 | } | ||
| 583 | |||
| 584 | /* read four bytes from DID_VID register */ | ||
| 585 | if (iic_tpm_read(TPM_DID_VID(0), (u8 *)&vendor, 4) < 0) { | ||
| 586 | rc = -EIO; | ||
| 587 | goto out_release; | ||
| 588 | } | ||
| 589 | |||
| 590 | /* create DID_VID register value, after swapping to little-endian */ | ||
| 591 | vendor = be32_to_cpu((__be32) vendor); | ||
| 592 | |||
| 593 | if (vendor != TPM_TIS_I2C_DID_VID) { | ||
| 594 | rc = -ENODEV; | ||
| 595 | goto out_release; | ||
| 596 | } | ||
| 597 | |||
| 598 | dev_info(dev, "1.2 TPM (device-id 0x%X)\n", vendor >> 16); | ||
| 599 | |||
| 600 | INIT_LIST_HEAD(&chip->vendor.list); | ||
| 601 | tpm_dev.chip = chip; | ||
| 602 | |||
| 603 | tpm_get_timeouts(chip); | ||
| 604 | tpm_do_selftest(chip); | ||
| 605 | |||
| 606 | return 0; | ||
| 607 | |||
| 608 | out_release: | ||
| 609 | release_locality(chip, chip->vendor.locality, 1); | ||
| 610 | |||
| 611 | out_vendor: | ||
| 612 | /* close file handles */ | ||
| 613 | tpm_dev_vendor_release(chip); | ||
| 614 | |||
| 615 | /* remove hardware */ | ||
| 616 | tpm_remove_hardware(chip->dev); | ||
| 617 | |||
| 618 | /* reset these pointers, otherwise we oops */ | ||
| 619 | chip->dev->release = NULL; | ||
| 620 | chip->release = NULL; | ||
| 621 | tpm_dev.client = NULL; | ||
| 622 | dev_set_drvdata(chip->dev, chip); | ||
| 623 | out_err: | ||
| 624 | return rc; | ||
| 625 | } | ||
| 626 | |||
| 627 | static const struct i2c_device_id tpm_tis_i2c_table[] = { | ||
| 628 | {"tpm_i2c_infineon", 0}, | ||
| 629 | {}, | ||
| 630 | }; | ||
| 631 | |||
| 632 | MODULE_DEVICE_TABLE(i2c, tpm_tis_i2c_table); | ||
| 633 | static SIMPLE_DEV_PM_OPS(tpm_tis_i2c_ops, tpm_pm_suspend, tpm_pm_resume); | ||
| 634 | |||
| 635 | static int tpm_tis_i2c_probe(struct i2c_client *client, | ||
| 636 | const struct i2c_device_id *id) | ||
| 637 | { | ||
| 638 | int rc; | ||
| 639 | if (tpm_dev.client != NULL) | ||
| 640 | return -EBUSY; /* We only support one client */ | ||
| 641 | |||
| 642 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
| 643 | dev_err(&client->dev, | ||
| 644 | "no algorithms associated to the i2c bus\n"); | ||
| 645 | return -ENODEV; | ||
| 646 | } | ||
| 647 | |||
| 648 | client->driver = &tpm_tis_i2c_driver; | ||
| 649 | tpm_dev.client = client; | ||
| 650 | rc = tpm_tis_i2c_init(&client->dev); | ||
| 651 | if (rc != 0) { | ||
| 652 | client->driver = NULL; | ||
| 653 | tpm_dev.client = NULL; | ||
| 654 | rc = -ENODEV; | ||
| 655 | } | ||
| 656 | return rc; | ||
| 657 | } | ||
| 658 | |||
| 659 | static int tpm_tis_i2c_remove(struct i2c_client *client) | ||
| 660 | { | ||
| 661 | struct tpm_chip *chip = tpm_dev.chip; | ||
| 662 | release_locality(chip, chip->vendor.locality, 1); | ||
| 663 | |||
| 664 | /* close file handles */ | ||
| 665 | tpm_dev_vendor_release(chip); | ||
| 666 | |||
| 667 | /* remove hardware */ | ||
| 668 | tpm_remove_hardware(chip->dev); | ||
| 669 | |||
| 670 | /* reset these pointers, otherwise we oops */ | ||
| 671 | chip->dev->release = NULL; | ||
| 672 | chip->release = NULL; | ||
| 673 | tpm_dev.client = NULL; | ||
| 674 | dev_set_drvdata(chip->dev, chip); | ||
| 675 | |||
| 676 | return 0; | ||
| 677 | } | ||
| 678 | |||
| 679 | static struct i2c_driver tpm_tis_i2c_driver = { | ||
| 680 | |||
| 681 | .id_table = tpm_tis_i2c_table, | ||
| 682 | .probe = tpm_tis_i2c_probe, | ||
| 683 | .remove = tpm_tis_i2c_remove, | ||
| 684 | .driver = { | ||
| 685 | .name = "tpm_i2c_infineon", | ||
| 686 | .owner = THIS_MODULE, | ||
| 687 | .pm = &tpm_tis_i2c_ops, | ||
| 688 | }, | ||
| 689 | }; | ||
| 690 | |||
| 691 | module_i2c_driver(tpm_tis_i2c_driver); | ||
| 692 | MODULE_AUTHOR("Peter Huewe <peter.huewe@infineon.com>"); | ||
| 693 | MODULE_DESCRIPTION("TPM TIS I2C Infineon Driver"); | ||
| 694 | MODULE_VERSION("2.1.5"); | ||
| 695 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/tpm/tpm_ibmvtpm.c b/drivers/char/tpm/tpm_ibmvtpm.c deleted file mode 100644 index 9978609d93b..00000000000 --- a/drivers/char/tpm/tpm_ibmvtpm.c +++ /dev/null | |||
| @@ -1,724 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012 IBM Corporation | ||
| 3 | * | ||
| 4 | * Author: Ashley Lai <adlai@us.ibm.com> | ||
| 5 | * | ||
| 6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
| 7 | * | ||
| 8 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
| 9 | * Specifications at www.trustedcomputinggroup.org | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License as | ||
| 13 | * published by the Free Software Foundation, version 2 of the | ||
| 14 | * License. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/dma-mapping.h> | ||
| 19 | #include <linux/dmapool.h> | ||
| 20 | #include <linux/slab.h> | ||
| 21 | #include <asm/vio.h> | ||
| 22 | #include <asm/irq.h> | ||
| 23 | #include <linux/types.h> | ||
| 24 | #include <linux/list.h> | ||
| 25 | #include <linux/spinlock.h> | ||
| 26 | #include <linux/interrupt.h> | ||
| 27 | #include <linux/wait.h> | ||
| 28 | #include <asm/prom.h> | ||
| 29 | |||
| 30 | #include "tpm.h" | ||
| 31 | #include "tpm_ibmvtpm.h" | ||
| 32 | |||
| 33 | static const char tpm_ibmvtpm_driver_name[] = "tpm_ibmvtpm"; | ||
| 34 | |||
| 35 | static struct vio_device_id tpm_ibmvtpm_device_table[] = { | ||
| 36 | { "IBM,vtpm", "IBM,vtpm"}, | ||
| 37 | { "", "" } | ||
| 38 | }; | ||
| 39 | MODULE_DEVICE_TABLE(vio, tpm_ibmvtpm_device_table); | ||
| 40 | |||
| 41 | /** | ||
| 42 | * ibmvtpm_send_crq - Send a CRQ request | ||
| 43 | * @vdev: vio device struct | ||
| 44 | * @w1: first word | ||
| 45 | * @w2: second word | ||
| 46 | * | ||
| 47 | * Return value: | ||
| 48 | * 0 -Sucess | ||
| 49 | * Non-zero - Failure | ||
| 50 | */ | ||
| 51 | static int ibmvtpm_send_crq(struct vio_dev *vdev, u64 w1, u64 w2) | ||
| 52 | { | ||
| 53 | return plpar_hcall_norets(H_SEND_CRQ, vdev->unit_address, w1, w2); | ||
| 54 | } | ||
| 55 | |||
| 56 | /** | ||
| 57 | * ibmvtpm_get_data - Retrieve ibm vtpm data | ||
| 58 | * @dev: device struct | ||
| 59 | * | ||
| 60 | * Return value: | ||
| 61 | * vtpm device struct | ||
| 62 | */ | ||
| 63 | static struct ibmvtpm_dev *ibmvtpm_get_data(const struct device *dev) | ||
| 64 | { | ||
| 65 | struct tpm_chip *chip = dev_get_drvdata(dev); | ||
| 66 | if (chip) | ||
| 67 | return (struct ibmvtpm_dev *)chip->vendor.data; | ||
| 68 | return NULL; | ||
| 69 | } | ||
| 70 | |||
| 71 | /** | ||
| 72 | * tpm_ibmvtpm_recv - Receive data after send | ||
| 73 | * @chip: tpm chip struct | ||
| 74 | * @buf: buffer to read | ||
| 75 | * count: size of buffer | ||
| 76 | * | ||
| 77 | * Return value: | ||
| 78 | * Number of bytes read | ||
| 79 | */ | ||
| 80 | static int tpm_ibmvtpm_recv(struct tpm_chip *chip, u8 *buf, size_t count) | ||
| 81 | { | ||
| 82 | struct ibmvtpm_dev *ibmvtpm; | ||
| 83 | u16 len; | ||
| 84 | int sig; | ||
| 85 | |||
| 86 | ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; | ||
| 87 | |||
| 88 | if (!ibmvtpm->rtce_buf) { | ||
| 89 | dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); | ||
| 90 | return 0; | ||
| 91 | } | ||
| 92 | |||
| 93 | sig = wait_event_interruptible(ibmvtpm->wq, ibmvtpm->res_len != 0); | ||
| 94 | if (sig) | ||
| 95 | return -EINTR; | ||
| 96 | |||
| 97 | len = ibmvtpm->res_len; | ||
| 98 | |||
| 99 | if (count < len) { | ||
| 100 | dev_err(ibmvtpm->dev, | ||
| 101 | "Invalid size in recv: count=%ld, crq_size=%d\n", | ||
| 102 | count, len); | ||
| 103 | return -EIO; | ||
| 104 | } | ||
| 105 | |||
| 106 | spin_lock(&ibmvtpm->rtce_lock); | ||
| 107 | memcpy((void *)buf, (void *)ibmvtpm->rtce_buf, len); | ||
| 108 | memset(ibmvtpm->rtce_buf, 0, len); | ||
| 109 | ibmvtpm->res_len = 0; | ||
| 110 | spin_unlock(&ibmvtpm->rtce_lock); | ||
| 111 | return len; | ||
| 112 | } | ||
| 113 | |||
| 114 | /** | ||
| 115 | * tpm_ibmvtpm_send - Send tpm request | ||
| 116 | * @chip: tpm chip struct | ||
| 117 | * @buf: buffer contains data to send | ||
| 118 | * count: size of buffer | ||
| 119 | * | ||
| 120 | * Return value: | ||
| 121 | * Number of bytes sent | ||
| 122 | */ | ||
| 123 | static int tpm_ibmvtpm_send(struct tpm_chip *chip, u8 *buf, size_t count) | ||
| 124 | { | ||
| 125 | struct ibmvtpm_dev *ibmvtpm; | ||
| 126 | struct ibmvtpm_crq crq; | ||
| 127 | u64 *word = (u64 *) &crq; | ||
| 128 | int rc; | ||
| 129 | |||
| 130 | ibmvtpm = (struct ibmvtpm_dev *)chip->vendor.data; | ||
| 131 | |||
| 132 | if (!ibmvtpm->rtce_buf) { | ||
| 133 | dev_err(ibmvtpm->dev, "ibmvtpm device is not ready\n"); | ||
| 134 | return 0; | ||
| 135 | } | ||
| 136 | |||
| 137 | if (count > ibmvtpm->rtce_size) { | ||
| 138 | dev_err(ibmvtpm->dev, | ||
| 139 | "Invalid size in send: count=%ld, rtce_size=%d\n", | ||
| 140 | count, ibmvtpm->rtce_size); | ||
| 141 | return -EIO; | ||
| 142 | } | ||
| 143 | |||
| 144 | spin_lock(&ibmvtpm->rtce_lock); | ||
| 145 | memcpy((void *)ibmvtpm->rtce_buf, (void *)buf, count); | ||
| 146 | crq.valid = (u8)IBMVTPM_VALID_CMD; | ||
| 147 | crq.msg = (u8)VTPM_TPM_COMMAND; | ||
| 148 | crq.len = (u16)count; | ||
| 149 | crq.data = ibmvtpm->rtce_dma_handle; | ||
| 150 | |||
| 151 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, word[0], word[1]); | ||
| 152 | if (rc != H_SUCCESS) { | ||
| 153 | dev_err(ibmvtpm->dev, "tpm_ibmvtpm_send failed rc=%d\n", rc); | ||
| 154 | rc = 0; | ||
| 155 | } else | ||
| 156 | rc = count; | ||
| 157 | |||
| 158 | spin_unlock(&ibmvtpm->rtce_lock); | ||
| 159 | return rc; | ||
| 160 | } | ||
| 161 | |||
| 162 | static void tpm_ibmvtpm_cancel(struct tpm_chip *chip) | ||
| 163 | { | ||
| 164 | return; | ||
| 165 | } | ||
| 166 | |||
| 167 | static u8 tpm_ibmvtpm_status(struct tpm_chip *chip) | ||
| 168 | { | ||
| 169 | return 0; | ||
| 170 | } | ||
| 171 | |||
| 172 | /** | ||
| 173 | * ibmvtpm_crq_get_rtce_size - Send a CRQ request to get rtce size | ||
| 174 | * @ibmvtpm: vtpm device struct | ||
| 175 | * | ||
| 176 | * Return value: | ||
| 177 | * 0 - Success | ||
| 178 | * Non-zero - Failure | ||
| 179 | */ | ||
| 180 | static int ibmvtpm_crq_get_rtce_size(struct ibmvtpm_dev *ibmvtpm) | ||
| 181 | { | ||
| 182 | struct ibmvtpm_crq crq; | ||
| 183 | u64 *buf = (u64 *) &crq; | ||
| 184 | int rc; | ||
| 185 | |||
| 186 | crq.valid = (u8)IBMVTPM_VALID_CMD; | ||
| 187 | crq.msg = (u8)VTPM_GET_RTCE_BUFFER_SIZE; | ||
| 188 | |||
| 189 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | ||
| 190 | if (rc != H_SUCCESS) | ||
| 191 | dev_err(ibmvtpm->dev, | ||
| 192 | "ibmvtpm_crq_get_rtce_size failed rc=%d\n", rc); | ||
| 193 | |||
| 194 | return rc; | ||
| 195 | } | ||
| 196 | |||
| 197 | /** | ||
| 198 | * ibmvtpm_crq_get_version - Send a CRQ request to get vtpm version | ||
| 199 | * - Note that this is vtpm version and not tpm version | ||
| 200 | * @ibmvtpm: vtpm device struct | ||
| 201 | * | ||
| 202 | * Return value: | ||
| 203 | * 0 - Success | ||
| 204 | * Non-zero - Failure | ||
| 205 | */ | ||
| 206 | static int ibmvtpm_crq_get_version(struct ibmvtpm_dev *ibmvtpm) | ||
| 207 | { | ||
| 208 | struct ibmvtpm_crq crq; | ||
| 209 | u64 *buf = (u64 *) &crq; | ||
| 210 | int rc; | ||
| 211 | |||
| 212 | crq.valid = (u8)IBMVTPM_VALID_CMD; | ||
| 213 | crq.msg = (u8)VTPM_GET_VERSION; | ||
| 214 | |||
| 215 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | ||
| 216 | if (rc != H_SUCCESS) | ||
| 217 | dev_err(ibmvtpm->dev, | ||
| 218 | "ibmvtpm_crq_get_version failed rc=%d\n", rc); | ||
| 219 | |||
| 220 | return rc; | ||
| 221 | } | ||
| 222 | |||
| 223 | /** | ||
| 224 | * ibmvtpm_crq_send_init_complete - Send a CRQ initialize complete message | ||
| 225 | * @ibmvtpm: vtpm device struct | ||
| 226 | * | ||
| 227 | * Return value: | ||
| 228 | * 0 - Success | ||
| 229 | * Non-zero - Failure | ||
| 230 | */ | ||
| 231 | static int ibmvtpm_crq_send_init_complete(struct ibmvtpm_dev *ibmvtpm) | ||
| 232 | { | ||
| 233 | int rc; | ||
| 234 | |||
| 235 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_COMP_CMD, 0); | ||
| 236 | if (rc != H_SUCCESS) | ||
| 237 | dev_err(ibmvtpm->dev, | ||
| 238 | "ibmvtpm_crq_send_init_complete failed rc=%d\n", rc); | ||
| 239 | |||
| 240 | return rc; | ||
| 241 | } | ||
| 242 | |||
| 243 | /** | ||
| 244 | * ibmvtpm_crq_send_init - Send a CRQ initialize message | ||
| 245 | * @ibmvtpm: vtpm device struct | ||
| 246 | * | ||
| 247 | * Return value: | ||
| 248 | * 0 - Success | ||
| 249 | * Non-zero - Failure | ||
| 250 | */ | ||
| 251 | static int ibmvtpm_crq_send_init(struct ibmvtpm_dev *ibmvtpm) | ||
| 252 | { | ||
| 253 | int rc; | ||
| 254 | |||
| 255 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, INIT_CRQ_CMD, 0); | ||
| 256 | if (rc != H_SUCCESS) | ||
| 257 | dev_err(ibmvtpm->dev, | ||
| 258 | "ibmvtpm_crq_send_init failed rc=%d\n", rc); | ||
| 259 | |||
| 260 | return rc; | ||
| 261 | } | ||
| 262 | |||
| 263 | /** | ||
| 264 | * tpm_ibmvtpm_remove - ibm vtpm remove entry point | ||
| 265 | * @vdev: vio device struct | ||
| 266 | * | ||
| 267 | * Return value: | ||
| 268 | * 0 | ||
| 269 | */ | ||
| 270 | static int tpm_ibmvtpm_remove(struct vio_dev *vdev) | ||
| 271 | { | ||
| 272 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); | ||
| 273 | int rc = 0; | ||
| 274 | |||
| 275 | free_irq(vdev->irq, ibmvtpm); | ||
| 276 | |||
| 277 | do { | ||
| 278 | if (rc) | ||
| 279 | msleep(100); | ||
| 280 | rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address); | ||
| 281 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); | ||
| 282 | |||
| 283 | dma_unmap_single(ibmvtpm->dev, ibmvtpm->crq_dma_handle, | ||
| 284 | CRQ_RES_BUF_SIZE, DMA_BIDIRECTIONAL); | ||
| 285 | free_page((unsigned long)ibmvtpm->crq_queue.crq_addr); | ||
| 286 | |||
| 287 | if (ibmvtpm->rtce_buf) { | ||
| 288 | dma_unmap_single(ibmvtpm->dev, ibmvtpm->rtce_dma_handle, | ||
| 289 | ibmvtpm->rtce_size, DMA_BIDIRECTIONAL); | ||
| 290 | kfree(ibmvtpm->rtce_buf); | ||
| 291 | } | ||
| 292 | |||
| 293 | tpm_remove_hardware(ibmvtpm->dev); | ||
| 294 | |||
| 295 | kfree(ibmvtpm); | ||
| 296 | |||
| 297 | return 0; | ||
| 298 | } | ||
| 299 | |||
| 300 | /** | ||
| 301 | * tpm_ibmvtpm_get_desired_dma - Get DMA size needed by this driver | ||
| 302 | * @vdev: vio device struct | ||
| 303 | * | ||
| 304 | * Return value: | ||
| 305 | * Number of bytes the driver needs to DMA map | ||
| 306 | */ | ||
| 307 | static unsigned long tpm_ibmvtpm_get_desired_dma(struct vio_dev *vdev) | ||
| 308 | { | ||
| 309 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(&vdev->dev); | ||
| 310 | return CRQ_RES_BUF_SIZE + ibmvtpm->rtce_size; | ||
| 311 | } | ||
| 312 | |||
| 313 | /** | ||
| 314 | * tpm_ibmvtpm_suspend - Suspend | ||
| 315 | * @dev: device struct | ||
| 316 | * | ||
| 317 | * Return value: | ||
| 318 | * 0 | ||
| 319 | */ | ||
| 320 | static int tpm_ibmvtpm_suspend(struct device *dev) | ||
| 321 | { | ||
| 322 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev); | ||
| 323 | struct ibmvtpm_crq crq; | ||
| 324 | u64 *buf = (u64 *) &crq; | ||
| 325 | int rc = 0; | ||
| 326 | |||
| 327 | crq.valid = (u8)IBMVTPM_VALID_CMD; | ||
| 328 | crq.msg = (u8)VTPM_PREPARE_TO_SUSPEND; | ||
| 329 | |||
| 330 | rc = ibmvtpm_send_crq(ibmvtpm->vdev, buf[0], buf[1]); | ||
| 331 | if (rc != H_SUCCESS) | ||
| 332 | dev_err(ibmvtpm->dev, | ||
| 333 | "tpm_ibmvtpm_suspend failed rc=%d\n", rc); | ||
| 334 | |||
| 335 | return rc; | ||
| 336 | } | ||
| 337 | |||
| 338 | /** | ||
| 339 | * ibmvtpm_reset_crq - Reset CRQ | ||
| 340 | * @ibmvtpm: ibm vtpm struct | ||
| 341 | * | ||
| 342 | * Return value: | ||
| 343 | * 0 - Success | ||
| 344 | * Non-zero - Failure | ||
| 345 | */ | ||
| 346 | static int ibmvtpm_reset_crq(struct ibmvtpm_dev *ibmvtpm) | ||
| 347 | { | ||
| 348 | int rc = 0; | ||
| 349 | |||
| 350 | do { | ||
| 351 | if (rc) | ||
| 352 | msleep(100); | ||
| 353 | rc = plpar_hcall_norets(H_FREE_CRQ, | ||
| 354 | ibmvtpm->vdev->unit_address); | ||
| 355 | } while (rc == H_BUSY || H_IS_LONG_BUSY(rc)); | ||
| 356 | |||
| 357 | memset(ibmvtpm->crq_queue.crq_addr, 0, CRQ_RES_BUF_SIZE); | ||
| 358 | ibmvtpm->crq_queue.index = 0; | ||
| 359 | |||
| 360 | return plpar_hcall_norets(H_REG_CRQ, ibmvtpm->vdev->unit_address, | ||
| 361 | ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE); | ||
| 362 | } | ||
| 363 | |||
| 364 | /** | ||
| 365 | * tpm_ibmvtpm_resume - Resume from suspend | ||
| 366 | * @dev: device struct | ||
| 367 | * | ||
| 368 | * Return value: | ||
| 369 | * 0 | ||
| 370 | */ | ||
| 371 | static int tpm_ibmvtpm_resume(struct device *dev) | ||
| 372 | { | ||
| 373 | struct ibmvtpm_dev *ibmvtpm = ibmvtpm_get_data(dev); | ||
| 374 | int rc = 0; | ||
| 375 | |||
| 376 | do { | ||
| 377 | if (rc) | ||
| 378 | msleep(100); | ||
| 379 | rc = plpar_hcall_norets(H_ENABLE_CRQ, | ||
| 380 | ibmvtpm->vdev->unit_address); | ||
| 381 | } while (rc == H_IN_PROGRESS || rc == H_BUSY || H_IS_LONG_BUSY(rc)); | ||
| 382 | |||
| 383 | if (rc) { | ||
| 384 | dev_err(dev, "Error enabling ibmvtpm rc=%d\n", rc); | ||
| 385 | return rc; | ||
| 386 | } | ||
| 387 | |||
| 388 | rc = vio_enable_interrupts(ibmvtpm->vdev); | ||
| 389 | if (rc) { | ||
| 390 | dev_err(dev, "Error vio_enable_interrupts rc=%d\n", rc); | ||
| 391 | return rc; | ||
| 392 | } | ||
| 393 | |||
| 394 | rc = ibmvtpm_crq_send_init(ibmvtpm); | ||
| 395 | if (rc) | ||
| 396 | dev_err(dev, "Error send_init rc=%d\n", rc); | ||
| 397 | |||
| 398 | return rc; | ||
| 399 | } | ||
| 400 | |||
| 401 | static const struct file_operations ibmvtpm_ops = { | ||
| 402 | .owner = THIS_MODULE, | ||
| 403 | .llseek = no_llseek, | ||
| 404 | .open = tpm_open, | ||
| 405 | .read = tpm_read, | ||
| 406 | .write = tpm_write, | ||
| 407 | .release = tpm_release, | ||
| 408 | }; | ||
| 409 | |||
| 410 | static DEVICE_ATTR(pubek, S_IRUGO, tpm_show_pubek, NULL); | ||
| 411 | static DEVICE_ATTR(pcrs, S_IRUGO, tpm_show_pcrs, NULL); | ||
| 412 | static DEVICE_ATTR(enabled, S_IRUGO, tpm_show_enabled, NULL); | ||
| 413 | static DEVICE_ATTR(active, S_IRUGO, tpm_show_active, NULL); | ||
| 414 | static DEVICE_ATTR(owned, S_IRUGO, tpm_show_owned, NULL); | ||
| 415 | static DEVICE_ATTR(temp_deactivated, S_IRUGO, tpm_show_temp_deactivated, | ||
| 416 | NULL); | ||
| 417 | static DEVICE_ATTR(caps, S_IRUGO, tpm_show_caps_1_2, NULL); | ||
| 418 | static DEVICE_ATTR(cancel, S_IWUSR | S_IWGRP, NULL, tpm_store_cancel); | ||
| 419 | static DEVICE_ATTR(durations, S_IRUGO, tpm_show_durations, NULL); | ||
| 420 | static DEVICE_ATTR(timeouts, S_IRUGO, tpm_show_timeouts, NULL); | ||
| 421 | |||
| 422 | static struct attribute *ibmvtpm_attrs[] = { | ||
| 423 | &dev_attr_pubek.attr, | ||
| 424 | &dev_attr_pcrs.attr, | ||
| 425 | &dev_attr_enabled.attr, | ||
| 426 | &dev_attr_active.attr, | ||
| 427 | &dev_attr_owned.attr, | ||
| 428 | &dev_attr_temp_deactivated.attr, | ||
| 429 | &dev_attr_caps.attr, | ||
| 430 | &dev_attr_cancel.attr, | ||
| 431 | &dev_attr_durations.attr, | ||
| 432 | &dev_attr_timeouts.attr, NULL, | ||
| 433 | }; | ||
| 434 | |||
| 435 | static struct attribute_group ibmvtpm_attr_grp = { .attrs = ibmvtpm_attrs }; | ||
| 436 | |||
| 437 | static const struct tpm_vendor_specific tpm_ibmvtpm = { | ||
| 438 | .recv = tpm_ibmvtpm_recv, | ||
| 439 | .send = tpm_ibmvtpm_send, | ||
| 440 | .cancel = tpm_ibmvtpm_cancel, | ||
| 441 | .status = tpm_ibmvtpm_status, | ||
| 442 | .req_complete_mask = 0, | ||
| 443 | .req_complete_val = 0, | ||
| 444 | .req_canceled = 0, | ||
| 445 | .attr_group = &ibmvtpm_attr_grp, | ||
| 446 | .miscdev = { .fops = &ibmvtpm_ops, }, | ||
| 447 | }; | ||
| 448 | |||
| 449 | static const struct dev_pm_ops tpm_ibmvtpm_pm_ops = { | ||
| 450 | .suspend = tpm_ibmvtpm_suspend, | ||
| 451 | .resume = tpm_ibmvtpm_resume, | ||
| 452 | }; | ||
| 453 | |||
| 454 | /** | ||
| 455 | * ibmvtpm_crq_get_next - Get next responded crq | ||
| 456 | * @ibmvtpm vtpm device struct | ||
| 457 | * | ||
| 458 | * Return value: | ||
| 459 | * vtpm crq pointer | ||
| 460 | */ | ||
| 461 | static struct ibmvtpm_crq *ibmvtpm_crq_get_next(struct ibmvtpm_dev *ibmvtpm) | ||
| 462 | { | ||
| 463 | struct ibmvtpm_crq_queue *crq_q = &ibmvtpm->crq_queue; | ||
| 464 | struct ibmvtpm_crq *crq = &crq_q->crq_addr[crq_q->index]; | ||
| 465 | |||
| 466 | if (crq->valid & VTPM_MSG_RES) { | ||
| 467 | if (++crq_q->index == crq_q->num_entry) | ||
| 468 | crq_q->index = 0; | ||
| 469 | smp_rmb(); | ||
| 470 | } else | ||
| 471 | crq = NULL; | ||
| 472 | return crq; | ||
| 473 | } | ||
| 474 | |||
| 475 | /** | ||
| 476 | * ibmvtpm_crq_process - Process responded crq | ||
| 477 | * @crq crq to be processed | ||
| 478 | * @ibmvtpm vtpm device struct | ||
| 479 | * | ||
| 480 | * Return value: | ||
| 481 | * Nothing | ||
| 482 | */ | ||
| 483 | static void ibmvtpm_crq_process(struct ibmvtpm_crq *crq, | ||
| 484 | struct ibmvtpm_dev *ibmvtpm) | ||
| 485 | { | ||
| 486 | int rc = 0; | ||
| 487 | |||
| 488 | switch (crq->valid) { | ||
| 489 | case VALID_INIT_CRQ: | ||
| 490 | switch (crq->msg) { | ||
| 491 | case INIT_CRQ_RES: | ||
| 492 | dev_info(ibmvtpm->dev, "CRQ initialized\n"); | ||
| 493 | rc = ibmvtpm_crq_send_init_complete(ibmvtpm); | ||
| 494 | if (rc) | ||
| 495 | dev_err(ibmvtpm->dev, "Unable to send CRQ init complete rc=%d\n", rc); | ||
| 496 | return; | ||
| 497 | case INIT_CRQ_COMP_RES: | ||
| 498 | dev_info(ibmvtpm->dev, | ||
| 499 | "CRQ initialization completed\n"); | ||
| 500 | return; | ||
| 501 | default: | ||
| 502 | dev_err(ibmvtpm->dev, "Unknown crq message type: %d\n", crq->msg); | ||
| 503 | return; | ||
| 504 | } | ||
| 505 | return; | ||
| 506 | case IBMVTPM_VALID_CMD: | ||
| 507 | switch (crq->msg) { | ||
| 508 | case VTPM_GET_RTCE_BUFFER_SIZE_RES: | ||
| 509 | if (crq->len <= 0) { | ||
| 510 | dev_err(ibmvtpm->dev, "Invalid rtce size\n"); | ||
| 511 | return; | ||
| 512 | } | ||
| 513 | ibmvtpm->rtce_size = crq->len; | ||
| 514 | ibmvtpm->rtce_buf = kmalloc(ibmvtpm->rtce_size, | ||
| 515 | GFP_KERNEL); | ||
| 516 | if (!ibmvtpm->rtce_buf) { | ||
| 517 | dev_err(ibmvtpm->dev, "Failed to allocate memory for rtce buffer\n"); | ||
| 518 | return; | ||
| 519 | } | ||
| 520 | |||
| 521 | ibmvtpm->rtce_dma_handle = dma_map_single(ibmvtpm->dev, | ||
| 522 | ibmvtpm->rtce_buf, ibmvtpm->rtce_size, | ||
| 523 | DMA_BIDIRECTIONAL); | ||
| 524 | |||
| 525 | if (dma_mapping_error(ibmvtpm->dev, | ||
| 526 | ibmvtpm->rtce_dma_handle)) { | ||
| 527 | kfree(ibmvtpm->rtce_buf); | ||
| 528 | ibmvtpm->rtce_buf = NULL; | ||
| 529 | dev_err(ibmvtpm->dev, "Failed to dma map rtce buffer\n"); | ||
| 530 | } | ||
| 531 | |||
| 532 | return; | ||
| 533 | case VTPM_GET_VERSION_RES: | ||
| 534 | ibmvtpm->vtpm_version = crq->data; | ||
| 535 | return; | ||
| 536 | case VTPM_TPM_COMMAND_RES: | ||
| 537 | /* len of the data in rtce buffer */ | ||
| 538 | ibmvtpm->res_len = crq->len; | ||
| 539 | wake_up_interruptible(&ibmvtpm->wq); | ||
| 540 | return; | ||
| 541 | default: | ||
| 542 | return; | ||
| 543 | } | ||
| 544 | } | ||
| 545 | return; | ||
| 546 | } | ||
| 547 | |||
| 548 | /** | ||
| 549 | * ibmvtpm_interrupt - Interrupt handler | ||
| 550 | * @irq: irq number to handle | ||
| 551 | * @vtpm_instance: vtpm that received interrupt | ||
| 552 | * | ||
| 553 | * Returns: | ||
| 554 | * IRQ_HANDLED | ||
| 555 | **/ | ||
| 556 | static irqreturn_t ibmvtpm_interrupt(int irq, void *vtpm_instance) | ||
| 557 | { | ||
| 558 | struct ibmvtpm_dev *ibmvtpm = (struct ibmvtpm_dev *) vtpm_instance; | ||
| 559 | struct ibmvtpm_crq *crq; | ||
| 560 | |||
| 561 | /* while loop is needed for initial setup (get version and | ||
| 562 | * get rtce_size). There should be only one tpm request at any | ||
| 563 | * given time. | ||
| 564 | */ | ||
| 565 | while ((crq = ibmvtpm_crq_get_next(ibmvtpm)) != NULL) { | ||
| 566 | ibmvtpm_crq_process(crq, ibmvtpm); | ||
| 567 | crq->valid = 0; | ||
| 568 | smp_wmb(); | ||
| 569 | } | ||
| 570 | |||
| 571 | return IRQ_HANDLED; | ||
| 572 | } | ||
| 573 | |||
| 574 | /** | ||
| 575 | * tpm_ibmvtpm_probe - ibm vtpm initialize entry point | ||
| 576 | * @vio_dev: vio device struct | ||
| 577 | * @id: vio device id struct | ||
| 578 | * | ||
| 579 | * Return value: | ||
| 580 | * 0 - Success | ||
| 581 | * Non-zero - Failure | ||
| 582 | */ | ||
| 583 | static int tpm_ibmvtpm_probe(struct vio_dev *vio_dev, | ||
| 584 | const struct vio_device_id *id) | ||
| 585 | { | ||
| 586 | struct ibmvtpm_dev *ibmvtpm; | ||
| 587 | struct device *dev = &vio_dev->dev; | ||
| 588 | struct ibmvtpm_crq_queue *crq_q; | ||
| 589 | struct tpm_chip *chip; | ||
| 590 | int rc = -ENOMEM, rc1; | ||
| 591 | |||
| 592 | chip = tpm_register_hardware(dev, &tpm_ibmvtpm); | ||
| 593 | if (!chip) { | ||
| 594 | dev_err(dev, "tpm_register_hardware failed\n"); | ||
| 595 | return -ENODEV; | ||
| 596 | } | ||
| 597 | |||
| 598 | ibmvtpm = kzalloc(sizeof(struct ibmvtpm_dev), GFP_KERNEL); | ||
| 599 | if (!ibmvtpm) { | ||
| 600 | dev_err(dev, "kzalloc for ibmvtpm failed\n"); | ||
| 601 | goto cleanup; | ||
| 602 | } | ||
| 603 | |||
| 604 | crq_q = &ibmvtpm->crq_queue; | ||
| 605 | crq_q->crq_addr = (struct ibmvtpm_crq *)get_zeroed_page(GFP_KERNEL); | ||
| 606 | if (!crq_q->crq_addr) { | ||
| 607 | dev_err(dev, "Unable to allocate memory for crq_addr\n"); | ||
| 608 | goto cleanup; | ||
| 609 | } | ||
| 610 | |||
| 611 | crq_q->num_entry = CRQ_RES_BUF_SIZE / sizeof(*crq_q->crq_addr); | ||
| 612 | ibmvtpm->crq_dma_handle = dma_map_single(dev, crq_q->crq_addr, | ||
| 613 | CRQ_RES_BUF_SIZE, | ||
| 614 | DMA_BIDIRECTIONAL); | ||
| 615 | |||
| 616 | if (dma_mapping_error(dev, ibmvtpm->crq_dma_handle)) { | ||
| 617 | dev_err(dev, "dma mapping failed\n"); | ||
| 618 | goto cleanup; | ||
| 619 | } | ||
| 620 | |||
| 621 | rc = plpar_hcall_norets(H_REG_CRQ, vio_dev->unit_address, | ||
| 622 | ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE); | ||
| 623 | if (rc == H_RESOURCE) | ||
| 624 | rc = ibmvtpm_reset_crq(ibmvtpm); | ||
| 625 | |||
| 626 | if (rc) { | ||
| 627 | dev_err(dev, "Unable to register CRQ rc=%d\n", rc); | ||
| 628 | goto reg_crq_cleanup; | ||
| 629 | } | ||
| 630 | |||
| 631 | rc = request_irq(vio_dev->irq, ibmvtpm_interrupt, 0, | ||
| 632 | tpm_ibmvtpm_driver_name, ibmvtpm); | ||
| 633 | if (rc) { | ||
| 634 | dev_err(dev, "Error %d register irq 0x%x\n", rc, vio_dev->irq); | ||
| 635 | goto init_irq_cleanup; | ||
| 636 | } | ||
| 637 | |||
| 638 | rc = vio_enable_interrupts(vio_dev); | ||
| 639 | if (rc) { | ||
| 640 | dev_err(dev, "Error %d enabling interrupts\n", rc); | ||
| 641 | goto init_irq_cleanup; | ||
| 642 | } | ||
| 643 | |||
| 644 | init_waitqueue_head(&ibmvtpm->wq); | ||
| 645 | |||
| 646 | crq_q->index = 0; | ||
| 647 | |||
| 648 | ibmvtpm->dev = dev; | ||
| 649 | ibmvtpm->vdev = vio_dev; | ||
| 650 | chip->vendor.data = (void *)ibmvtpm; | ||
| 651 | |||
| 652 | spin_lock_init(&ibmvtpm->rtce_lock); | ||
| 653 | |||
| 654 | rc = ibmvtpm_crq_send_init(ibmvtpm); | ||
| 655 | if (rc) | ||
| 656 | goto init_irq_cleanup; | ||
| 657 | |||
| 658 | rc = ibmvtpm_crq_get_version(ibmvtpm); | ||
| 659 | if (rc) | ||
| 660 | goto init_irq_cleanup; | ||
| 661 | |||
| 662 | rc = ibmvtpm_crq_get_rtce_size(ibmvtpm); | ||
| 663 | if (rc) | ||
| 664 | goto init_irq_cleanup; | ||
| 665 | |||
| 666 | return rc; | ||
| 667 | init_irq_cleanup: | ||
| 668 | do { | ||
| 669 | rc1 = plpar_hcall_norets(H_FREE_CRQ, vio_dev->unit_address); | ||
| 670 | } while (rc1 == H_BUSY || H_IS_LONG_BUSY(rc1)); | ||
| 671 | reg_crq_cleanup: | ||
| 672 | dma_unmap_single(dev, ibmvtpm->crq_dma_handle, CRQ_RES_BUF_SIZE, | ||
| 673 | DMA_BIDIRECTIONAL); | ||
| 674 | cleanup: | ||
| 675 | if (ibmvtpm) { | ||
| 676 | if (crq_q->crq_addr) | ||
| 677 | free_page((unsigned long)crq_q->crq_addr); | ||
| 678 | kfree(ibmvtpm); | ||
| 679 | } | ||
| 680 | |||
| 681 | tpm_remove_hardware(dev); | ||
| 682 | |||
| 683 | return rc; | ||
| 684 | } | ||
| 685 | |||
| 686 | static struct vio_driver ibmvtpm_driver = { | ||
| 687 | .id_table = tpm_ibmvtpm_device_table, | ||
| 688 | .probe = tpm_ibmvtpm_probe, | ||
| 689 | .remove = tpm_ibmvtpm_remove, | ||
| 690 | .get_desired_dma = tpm_ibmvtpm_get_desired_dma, | ||
| 691 | .name = tpm_ibmvtpm_driver_name, | ||
| 692 | .pm = &tpm_ibmvtpm_pm_ops, | ||
| 693 | }; | ||
| 694 | |||
| 695 | /** | ||
| 696 | * ibmvtpm_module_init - Initialize ibm vtpm module | ||
| 697 | * | ||
| 698 | * Return value: | ||
| 699 | * 0 -Success | ||
| 700 | * Non-zero - Failure | ||
| 701 | */ | ||
| 702 | static int __init ibmvtpm_module_init(void) | ||
| 703 | { | ||
| 704 | return vio_register_driver(&ibmvtpm_driver); | ||
| 705 | } | ||
| 706 | |||
| 707 | /** | ||
| 708 | * ibmvtpm_module_exit - Teardown ibm vtpm module | ||
| 709 | * | ||
| 710 | * Return value: | ||
| 711 | * Nothing | ||
| 712 | */ | ||
| 713 | static void __exit ibmvtpm_module_exit(void) | ||
| 714 | { | ||
| 715 | vio_unregister_driver(&ibmvtpm_driver); | ||
| 716 | } | ||
| 717 | |||
| 718 | module_init(ibmvtpm_module_init); | ||
| 719 | module_exit(ibmvtpm_module_exit); | ||
| 720 | |||
| 721 | MODULE_AUTHOR("adlai@us.ibm.com"); | ||
| 722 | MODULE_DESCRIPTION("IBM vTPM Driver"); | ||
| 723 | MODULE_VERSION("1.0"); | ||
| 724 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/tpm/tpm_ibmvtpm.h b/drivers/char/tpm/tpm_ibmvtpm.h deleted file mode 100644 index bd82a791f99..00000000000 --- a/drivers/char/tpm/tpm_ibmvtpm.h +++ /dev/null | |||
| @@ -1,76 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2012 IBM Corporation | ||
| 3 | * | ||
| 4 | * Author: Ashley Lai <adlai@us.ibm.com> | ||
| 5 | * | ||
| 6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
| 7 | * | ||
| 8 | * Device driver for TCG/TCPA TPM (trusted platform module). | ||
| 9 | * Specifications at www.trustedcomputinggroup.org | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License as | ||
| 13 | * published by the Free Software Foundation, version 2 of the | ||
| 14 | * License. | ||
| 15 | * | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef __TPM_IBMVTPM_H__ | ||
| 19 | #define __TPM_IBMVTPM_H__ | ||
| 20 | |||
| 21 | /* vTPM Message Format 1 */ | ||
| 22 | struct ibmvtpm_crq { | ||
| 23 | u8 valid; | ||
| 24 | u8 msg; | ||
| 25 | u16 len; | ||
| 26 | u32 data; | ||
| 27 | u64 reserved; | ||
| 28 | } __attribute__((packed, aligned(8))); | ||
| 29 | |||
| 30 | struct ibmvtpm_crq_queue { | ||
| 31 | struct ibmvtpm_crq *crq_addr; | ||
| 32 | u32 index; | ||
| 33 | u32 num_entry; | ||
| 34 | }; | ||
| 35 | |||
| 36 | struct ibmvtpm_dev { | ||
| 37 | struct device *dev; | ||
| 38 | struct vio_dev *vdev; | ||
| 39 | struct ibmvtpm_crq_queue crq_queue; | ||
| 40 | dma_addr_t crq_dma_handle; | ||
| 41 | u32 rtce_size; | ||
| 42 | void __iomem *rtce_buf; | ||
| 43 | dma_addr_t rtce_dma_handle; | ||
| 44 | spinlock_t rtce_lock; | ||
| 45 | wait_queue_head_t wq; | ||
| 46 | u16 res_len; | ||
| 47 | u32 vtpm_version; | ||
| 48 | }; | ||
| 49 | |||
| 50 | #define CRQ_RES_BUF_SIZE PAGE_SIZE | ||
| 51 | |||
| 52 | /* Initialize CRQ */ | ||
| 53 | #define INIT_CRQ_CMD 0xC001000000000000LL /* Init cmd */ | ||
| 54 | #define INIT_CRQ_COMP_CMD 0xC002000000000000LL /* Init complete cmd */ | ||
| 55 | #define INIT_CRQ_RES 0x01 /* Init respond */ | ||
| 56 | #define INIT_CRQ_COMP_RES 0x02 /* Init complete respond */ | ||
| 57 | #define VALID_INIT_CRQ 0xC0 /* Valid command for init crq */ | ||
| 58 | |||
| 59 | /* vTPM CRQ response is the message type | 0x80 */ | ||
| 60 | #define VTPM_MSG_RES 0x80 | ||
| 61 | #define IBMVTPM_VALID_CMD 0x80 | ||
| 62 | |||
| 63 | /* vTPM CRQ message types */ | ||
| 64 | #define VTPM_GET_VERSION 0x01 | ||
| 65 | #define VTPM_GET_VERSION_RES (0x01 | VTPM_MSG_RES) | ||
| 66 | |||
| 67 | #define VTPM_TPM_COMMAND 0x02 | ||
| 68 | #define VTPM_TPM_COMMAND_RES (0x02 | VTPM_MSG_RES) | ||
| 69 | |||
| 70 | #define VTPM_GET_RTCE_BUFFER_SIZE 0x03 | ||
| 71 | #define VTPM_GET_RTCE_BUFFER_SIZE_RES (0x03 | VTPM_MSG_RES) | ||
| 72 | |||
| 73 | #define VTPM_PREPARE_TO_SUSPEND 0x04 | ||
| 74 | #define VTPM_PREPARE_TO_SUSPEND_RES (0x04 | VTPM_MSG_RES) | ||
| 75 | |||
| 76 | #endif | ||
diff --git a/drivers/char/tpm/tpm_infineon.c b/drivers/char/tpm/tpm_infineon.c index 2b480c2960b..76da32e11f1 100644 --- a/drivers/char/tpm/tpm_infineon.c +++ b/drivers/char/tpm/tpm_infineon.c | |||
| @@ -4,8 +4,8 @@ | |||
| 4 | * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module | 4 | * SLD 9630 TT 1.1 and SLB 9635 TT 1.2 Trusted Platform Module |
| 5 | * Specifications at www.trustedcomputinggroup.org | 5 | * Specifications at www.trustedcomputinggroup.org |
| 6 | * | 6 | * |
| 7 | * Copyright (C) 2005, Marcel Selhorst <tpmdd@selhorst.net> | 7 | * Copyright (C) 2005, Marcel Selhorst <m.selhorst@sirrix.com> |
| 8 | * Sirrix AG - security technologies <tpmdd@sirrix.com> and | 8 | * Sirrix AG - security technologies, http://www.sirrix.com and |
| 9 | * Applied Data Security Group, Ruhr-University Bochum, Germany | 9 | * Applied Data Security Group, Ruhr-University Bochum, Germany |
| 10 | * Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ | 10 | * Project-Homepage: http://www.trust.rub.de/projects/linux-device-driver-infineon-tpm/ |
| 11 | * | 11 | * |
| @@ -415,7 +415,7 @@ static const struct pnp_device_id tpm_inf_pnp_tbl[] = { | |||
| 415 | 415 | ||
| 416 | MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl); | 416 | MODULE_DEVICE_TABLE(pnp, tpm_inf_pnp_tbl); |
| 417 | 417 | ||
| 418 | static int tpm_inf_pnp_probe(struct pnp_dev *dev, | 418 | static int __devinit tpm_inf_pnp_probe(struct pnp_dev *dev, |
| 419 | const struct pnp_device_id *dev_id) | 419 | const struct pnp_device_id *dev_id) |
| 420 | { | 420 | { |
| 421 | int rc = 0; | 421 | int rc = 0; |
| @@ -594,7 +594,7 @@ err_last: | |||
| 594 | return rc; | 594 | return rc; |
| 595 | } | 595 | } |
| 596 | 596 | ||
| 597 | static void tpm_inf_pnp_remove(struct pnp_dev *dev) | 597 | static __devexit void tpm_inf_pnp_remove(struct pnp_dev *dev) |
| 598 | { | 598 | { |
| 599 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 599 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
| 600 | 600 | ||
| @@ -655,7 +655,7 @@ static struct pnp_driver tpm_inf_pnp_driver = { | |||
| 655 | .probe = tpm_inf_pnp_probe, | 655 | .probe = tpm_inf_pnp_probe, |
| 656 | .suspend = tpm_inf_pnp_suspend, | 656 | .suspend = tpm_inf_pnp_suspend, |
| 657 | .resume = tpm_inf_pnp_resume, | 657 | .resume = tpm_inf_pnp_resume, |
| 658 | .remove = tpm_inf_pnp_remove | 658 | .remove = __devexit_p(tpm_inf_pnp_remove) |
| 659 | }; | 659 | }; |
| 660 | 660 | ||
| 661 | static int __init init_inf(void) | 661 | static int __init init_inf(void) |
| @@ -671,7 +671,7 @@ static void __exit cleanup_inf(void) | |||
| 671 | module_init(init_inf); | 671 | module_init(init_inf); |
| 672 | module_exit(cleanup_inf); | 672 | module_exit(cleanup_inf); |
| 673 | 673 | ||
| 674 | MODULE_AUTHOR("Marcel Selhorst <tpmdd@sirrix.com>"); | 674 | MODULE_AUTHOR("Marcel Selhorst <m.selhorst@sirrix.com>"); |
| 675 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); | 675 | MODULE_DESCRIPTION("Driver for Infineon TPM SLD 9630 TT 1.1 / SLB 9635 TT 1.2"); |
| 676 | MODULE_VERSION("1.9.2"); | 676 | MODULE_VERSION("1.9.2"); |
| 677 | MODULE_LICENSE("GPL"); | 677 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/char/tpm/tpm_nsc.c b/drivers/char/tpm/tpm_nsc.c index 640c9a427b5..4d2464871ad 100644 --- a/drivers/char/tpm/tpm_nsc.c +++ b/drivers/char/tpm/tpm_nsc.c | |||
| @@ -274,13 +274,22 @@ static void tpm_nsc_remove(struct device *dev) | |||
| 274 | } | 274 | } |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | static SIMPLE_DEV_PM_OPS(tpm_nsc_pm, tpm_pm_suspend, tpm_pm_resume); | 277 | static int tpm_nsc_suspend(struct platform_device *dev, pm_message_t msg) |
| 278 | { | ||
| 279 | return tpm_pm_suspend(&dev->dev, msg); | ||
| 280 | } | ||
| 281 | |||
| 282 | static int tpm_nsc_resume(struct platform_device *dev) | ||
| 283 | { | ||
| 284 | return tpm_pm_resume(&dev->dev); | ||
| 285 | } | ||
| 278 | 286 | ||
| 279 | static struct platform_driver nsc_drv = { | 287 | static struct platform_driver nsc_drv = { |
| 288 | .suspend = tpm_nsc_suspend, | ||
| 289 | .resume = tpm_nsc_resume, | ||
| 280 | .driver = { | 290 | .driver = { |
| 281 | .name = "tpm_nsc", | 291 | .name = "tpm_nsc", |
| 282 | .owner = THIS_MODULE, | 292 | .owner = THIS_MODULE, |
| 283 | .pm = &tpm_nsc_pm, | ||
| 284 | }, | 293 | }, |
| 285 | }; | 294 | }; |
| 286 | 295 | ||
diff --git a/drivers/char/tpm/tpm_of.c b/drivers/char/tpm/tpm_of.c deleted file mode 100644 index 98ba2bd1a35..00000000000 --- a/drivers/char/tpm/tpm_of.c +++ /dev/null | |||
| @@ -1,73 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2012 IBM Corporation | ||
| 3 | * | ||
| 4 | * Author: Ashley Lai <adlai@us.ibm.com> | ||
| 5 | * | ||
| 6 | * Maintained by: <tpmdd-devel@lists.sourceforge.net> | ||
| 7 | * | ||
| 8 | * Read the event log created by the firmware on PPC64 | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or | ||
| 11 | * modify it under the terms of the GNU General Public License | ||
| 12 | * as published by the Free Software Foundation; either version | ||
| 13 | * 2 of the License, or (at your option) any later version. | ||
| 14 | * | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/slab.h> | ||
| 18 | #include <linux/of.h> | ||
| 19 | |||
| 20 | #include "tpm.h" | ||
| 21 | #include "tpm_eventlog.h" | ||
| 22 | |||
| 23 | int read_log(struct tpm_bios_log *log) | ||
| 24 | { | ||
| 25 | struct device_node *np; | ||
| 26 | const u32 *sizep; | ||
| 27 | const __be64 *basep; | ||
| 28 | |||
| 29 | if (log->bios_event_log != NULL) { | ||
| 30 | pr_err("%s: ERROR - Eventlog already initialized\n", __func__); | ||
| 31 | return -EFAULT; | ||
| 32 | } | ||
| 33 | |||
| 34 | np = of_find_node_by_name(NULL, "ibm,vtpm"); | ||
| 35 | if (!np) { | ||
| 36 | pr_err("%s: ERROR - IBMVTPM not supported\n", __func__); | ||
| 37 | return -ENODEV; | ||
| 38 | } | ||
| 39 | |||
| 40 | sizep = of_get_property(np, "linux,sml-size", NULL); | ||
| 41 | if (sizep == NULL) { | ||
| 42 | pr_err("%s: ERROR - SML size not found\n", __func__); | ||
| 43 | goto cleanup_eio; | ||
| 44 | } | ||
| 45 | if (*sizep == 0) { | ||
| 46 | pr_err("%s: ERROR - event log area empty\n", __func__); | ||
| 47 | goto cleanup_eio; | ||
| 48 | } | ||
| 49 | |||
| 50 | basep = of_get_property(np, "linux,sml-base", NULL); | ||
| 51 | if (basep == NULL) { | ||
| 52 | pr_err(KERN_ERR "%s: ERROR - SML not found\n", __func__); | ||
| 53 | goto cleanup_eio; | ||
| 54 | } | ||
| 55 | |||
| 56 | of_node_put(np); | ||
| 57 | log->bios_event_log = kmalloc(*sizep, GFP_KERNEL); | ||
| 58 | if (!log->bios_event_log) { | ||
| 59 | pr_err("%s: ERROR - Not enough memory for BIOS measurements\n", | ||
| 60 | __func__); | ||
| 61 | return -ENOMEM; | ||
| 62 | } | ||
| 63 | |||
| 64 | log->bios_event_log_end = log->bios_event_log + *sizep; | ||
| 65 | |||
| 66 | memcpy(log->bios_event_log, __va(be64_to_cpup(basep)), *sizep); | ||
| 67 | |||
| 68 | return 0; | ||
| 69 | |||
| 70 | cleanup_eio: | ||
| 71 | of_node_put(np); | ||
| 72 | return -EIO; | ||
| 73 | } | ||
diff --git a/drivers/char/tpm/tpm_ppi.c b/drivers/char/tpm/tpm_ppi.c deleted file mode 100644 index 720ebcf29fd..00000000000 --- a/drivers/char/tpm/tpm_ppi.c +++ /dev/null | |||
| @@ -1,463 +0,0 @@ | |||
| 1 | #include <linux/acpi.h> | ||
| 2 | #include <acpi/acpi_drivers.h> | ||
| 3 | #include "tpm.h" | ||
| 4 | |||
| 5 | static const u8 tpm_ppi_uuid[] = { | ||
| 6 | 0xA6, 0xFA, 0xDD, 0x3D, | ||
| 7 | 0x1B, 0x36, | ||
| 8 | 0xB4, 0x4E, | ||
| 9 | 0xA4, 0x24, | ||
| 10 | 0x8D, 0x10, 0x08, 0x9D, 0x16, 0x53 | ||
| 11 | }; | ||
| 12 | static char *tpm_device_name = "TPM"; | ||
| 13 | |||
| 14 | #define TPM_PPI_REVISION_ID 1 | ||
| 15 | #define TPM_PPI_FN_VERSION 1 | ||
| 16 | #define TPM_PPI_FN_SUBREQ 2 | ||
| 17 | #define TPM_PPI_FN_GETREQ 3 | ||
| 18 | #define TPM_PPI_FN_GETACT 4 | ||
| 19 | #define TPM_PPI_FN_GETRSP 5 | ||
| 20 | #define TPM_PPI_FN_SUBREQ2 7 | ||
| 21 | #define TPM_PPI_FN_GETOPR 8 | ||
| 22 | #define PPI_TPM_REQ_MAX 22 | ||
| 23 | #define PPI_VS_REQ_START 128 | ||
| 24 | #define PPI_VS_REQ_END 255 | ||
| 25 | #define PPI_VERSION_LEN 3 | ||
| 26 | |||
| 27 | static acpi_status ppi_callback(acpi_handle handle, u32 level, void *context, | ||
| 28 | void **return_value) | ||
| 29 | { | ||
| 30 | acpi_status status; | ||
| 31 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 32 | status = acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | ||
| 33 | if (strstr(buffer.pointer, context) != NULL) { | ||
| 34 | *return_value = handle; | ||
| 35 | kfree(buffer.pointer); | ||
| 36 | return AE_CTRL_TERMINATE; | ||
| 37 | } | ||
| 38 | return AE_OK; | ||
| 39 | } | ||
| 40 | |||
| 41 | static inline void ppi_assign_params(union acpi_object params[4], | ||
| 42 | u64 function_num) | ||
| 43 | { | ||
| 44 | params[0].type = ACPI_TYPE_BUFFER; | ||
| 45 | params[0].buffer.length = sizeof(tpm_ppi_uuid); | ||
| 46 | params[0].buffer.pointer = (char *)tpm_ppi_uuid; | ||
| 47 | params[1].type = ACPI_TYPE_INTEGER; | ||
| 48 | params[1].integer.value = TPM_PPI_REVISION_ID; | ||
| 49 | params[2].type = ACPI_TYPE_INTEGER; | ||
| 50 | params[2].integer.value = function_num; | ||
| 51 | params[3].type = ACPI_TYPE_PACKAGE; | ||
| 52 | params[3].package.count = 0; | ||
| 53 | params[3].package.elements = NULL; | ||
| 54 | } | ||
| 55 | |||
| 56 | static ssize_t tpm_show_ppi_version(struct device *dev, | ||
| 57 | struct device_attribute *attr, char *buf) | ||
| 58 | { | ||
| 59 | acpi_handle handle; | ||
| 60 | acpi_status status; | ||
| 61 | struct acpi_object_list input; | ||
| 62 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 63 | union acpi_object params[4]; | ||
| 64 | union acpi_object *obj; | ||
| 65 | |||
| 66 | input.count = 4; | ||
| 67 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
| 68 | input.pointer = params; | ||
| 69 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 70 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
| 71 | tpm_device_name, &handle); | ||
| 72 | if (ACPI_FAILURE(status)) | ||
| 73 | return -ENXIO; | ||
| 74 | |||
| 75 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 76 | ACPI_TYPE_STRING); | ||
| 77 | if (ACPI_FAILURE(status)) | ||
| 78 | return -ENOMEM; | ||
| 79 | obj = (union acpi_object *)output.pointer; | ||
| 80 | status = scnprintf(buf, PAGE_SIZE, "%s\n", obj->string.pointer); | ||
| 81 | kfree(output.pointer); | ||
| 82 | return status; | ||
| 83 | } | ||
| 84 | |||
| 85 | static ssize_t tpm_show_ppi_request(struct device *dev, | ||
| 86 | struct device_attribute *attr, char *buf) | ||
| 87 | { | ||
| 88 | acpi_handle handle; | ||
| 89 | acpi_status status; | ||
| 90 | struct acpi_object_list input; | ||
| 91 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 92 | union acpi_object params[4]; | ||
| 93 | union acpi_object *ret_obj; | ||
| 94 | |||
| 95 | input.count = 4; | ||
| 96 | ppi_assign_params(params, TPM_PPI_FN_GETREQ); | ||
| 97 | input.pointer = params; | ||
| 98 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 99 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
| 100 | tpm_device_name, &handle); | ||
| 101 | if (ACPI_FAILURE(status)) | ||
| 102 | return -ENXIO; | ||
| 103 | |||
| 104 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 105 | ACPI_TYPE_PACKAGE); | ||
| 106 | if (ACPI_FAILURE(status)) | ||
| 107 | return -ENOMEM; | ||
| 108 | /* | ||
| 109 | * output.pointer should be of package type, including two integers. | ||
| 110 | * The first is function return code, 0 means success and 1 means | ||
| 111 | * error. The second is pending TPM operation requested by the OS, 0 | ||
| 112 | * means none and >0 means operation value. | ||
| 113 | */ | ||
| 114 | ret_obj = ((union acpi_object *)output.pointer)->package.elements; | ||
| 115 | if (ret_obj->type == ACPI_TYPE_INTEGER) { | ||
| 116 | if (ret_obj->integer.value) { | ||
| 117 | status = -EFAULT; | ||
| 118 | goto cleanup; | ||
| 119 | } | ||
| 120 | ret_obj++; | ||
| 121 | if (ret_obj->type == ACPI_TYPE_INTEGER) | ||
| 122 | status = scnprintf(buf, PAGE_SIZE, "%llu\n", | ||
| 123 | ret_obj->integer.value); | ||
| 124 | else | ||
| 125 | status = -EINVAL; | ||
| 126 | } else { | ||
| 127 | status = -EINVAL; | ||
| 128 | } | ||
| 129 | cleanup: | ||
| 130 | kfree(output.pointer); | ||
| 131 | return status; | ||
| 132 | } | ||
| 133 | |||
| 134 | static ssize_t tpm_store_ppi_request(struct device *dev, | ||
| 135 | struct device_attribute *attr, | ||
| 136 | const char *buf, size_t count) | ||
| 137 | { | ||
| 138 | char version[PPI_VERSION_LEN + 1]; | ||
| 139 | acpi_handle handle; | ||
| 140 | acpi_status status; | ||
| 141 | struct acpi_object_list input; | ||
| 142 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 143 | union acpi_object params[4]; | ||
| 144 | union acpi_object obj; | ||
| 145 | u32 req; | ||
| 146 | u64 ret; | ||
| 147 | |||
| 148 | input.count = 4; | ||
| 149 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
| 150 | input.pointer = params; | ||
| 151 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 152 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
| 153 | tpm_device_name, &handle); | ||
| 154 | if (ACPI_FAILURE(status)) | ||
| 155 | return -ENXIO; | ||
| 156 | |||
| 157 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 158 | ACPI_TYPE_STRING); | ||
| 159 | if (ACPI_FAILURE(status)) | ||
| 160 | return -ENOMEM; | ||
| 161 | strncpy(version, | ||
| 162 | ((union acpi_object *)output.pointer)->string.pointer, | ||
| 163 | PPI_VERSION_LEN); | ||
| 164 | kfree(output.pointer); | ||
| 165 | output.length = ACPI_ALLOCATE_BUFFER; | ||
| 166 | output.pointer = NULL; | ||
| 167 | /* | ||
| 168 | * the function to submit TPM operation request to pre-os environment | ||
| 169 | * is updated with function index from SUBREQ to SUBREQ2 since PPI | ||
| 170 | * version 1.1 | ||
| 171 | */ | ||
| 172 | if (strcmp(version, "1.1") == -1) | ||
| 173 | params[2].integer.value = TPM_PPI_FN_SUBREQ; | ||
| 174 | else | ||
| 175 | params[2].integer.value = TPM_PPI_FN_SUBREQ2; | ||
| 176 | /* | ||
| 177 | * PPI spec defines params[3].type as ACPI_TYPE_PACKAGE. Some BIOS | ||
| 178 | * accept buffer/string/integer type, but some BIOS accept buffer/ | ||
| 179 | * string/package type. For PPI version 1.0 and 1.1, use buffer type | ||
| 180 | * for compatibility, and use package type since 1.2 according to spec. | ||
| 181 | */ | ||
| 182 | if (strcmp(version, "1.2") == -1) { | ||
| 183 | params[3].type = ACPI_TYPE_BUFFER; | ||
| 184 | params[3].buffer.length = sizeof(req); | ||
| 185 | sscanf(buf, "%d", &req); | ||
| 186 | params[3].buffer.pointer = (char *)&req; | ||
| 187 | } else { | ||
| 188 | params[3].package.count = 1; | ||
| 189 | obj.type = ACPI_TYPE_INTEGER; | ||
| 190 | sscanf(buf, "%llu", &obj.integer.value); | ||
| 191 | params[3].package.elements = &obj; | ||
| 192 | } | ||
| 193 | |||
| 194 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 195 | ACPI_TYPE_INTEGER); | ||
| 196 | if (ACPI_FAILURE(status)) | ||
| 197 | return -ENOMEM; | ||
| 198 | ret = ((union acpi_object *)output.pointer)->integer.value; | ||
| 199 | if (ret == 0) | ||
| 200 | status = (acpi_status)count; | ||
| 201 | else if (ret == 1) | ||
| 202 | status = -EPERM; | ||
| 203 | else | ||
| 204 | status = -EFAULT; | ||
| 205 | kfree(output.pointer); | ||
| 206 | return status; | ||
| 207 | } | ||
| 208 | |||
| 209 | static ssize_t tpm_show_ppi_transition_action(struct device *dev, | ||
| 210 | struct device_attribute *attr, | ||
| 211 | char *buf) | ||
| 212 | { | ||
| 213 | char version[PPI_VERSION_LEN + 1]; | ||
| 214 | acpi_handle handle; | ||
| 215 | acpi_status status; | ||
| 216 | struct acpi_object_list input; | ||
| 217 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 218 | union acpi_object params[4]; | ||
| 219 | u32 ret; | ||
| 220 | char *info[] = { | ||
| 221 | "None", | ||
| 222 | "Shutdown", | ||
| 223 | "Reboot", | ||
| 224 | "OS Vendor-specific", | ||
| 225 | "Error", | ||
| 226 | }; | ||
| 227 | input.count = 4; | ||
| 228 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
| 229 | input.pointer = params; | ||
| 230 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 231 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
| 232 | tpm_device_name, &handle); | ||
| 233 | if (ACPI_FAILURE(status)) | ||
| 234 | return -ENXIO; | ||
| 235 | |||
| 236 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 237 | ACPI_TYPE_STRING); | ||
| 238 | if (ACPI_FAILURE(status)) | ||
| 239 | return -ENOMEM; | ||
| 240 | strncpy(version, | ||
| 241 | ((union acpi_object *)output.pointer)->string.pointer, | ||
| 242 | PPI_VERSION_LEN); | ||
| 243 | /* | ||
| 244 | * PPI spec defines params[3].type as empty package, but some platforms | ||
| 245 | * (e.g. Capella with PPI 1.0) need integer/string/buffer type, so for | ||
| 246 | * compatibility, define params[3].type as buffer, if PPI version < 1.2 | ||
| 247 | */ | ||
| 248 | if (strcmp(version, "1.2") == -1) { | ||
| 249 | params[3].type = ACPI_TYPE_BUFFER; | ||
| 250 | params[3].buffer.length = 0; | ||
| 251 | params[3].buffer.pointer = NULL; | ||
| 252 | } | ||
| 253 | params[2].integer.value = TPM_PPI_FN_GETACT; | ||
| 254 | kfree(output.pointer); | ||
| 255 | output.length = ACPI_ALLOCATE_BUFFER; | ||
| 256 | output.pointer = NULL; | ||
| 257 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 258 | ACPI_TYPE_INTEGER); | ||
| 259 | if (ACPI_FAILURE(status)) | ||
| 260 | return -ENOMEM; | ||
| 261 | ret = ((union acpi_object *)output.pointer)->integer.value; | ||
| 262 | if (ret < ARRAY_SIZE(info) - 1) | ||
| 263 | status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, info[ret]); | ||
| 264 | else | ||
| 265 | status = scnprintf(buf, PAGE_SIZE, "%d: %s\n", ret, | ||
| 266 | info[ARRAY_SIZE(info)-1]); | ||
| 267 | kfree(output.pointer); | ||
| 268 | return status; | ||
| 269 | } | ||
| 270 | |||
| 271 | static ssize_t tpm_show_ppi_response(struct device *dev, | ||
| 272 | struct device_attribute *attr, | ||
| 273 | char *buf) | ||
| 274 | { | ||
| 275 | acpi_handle handle; | ||
| 276 | acpi_status status; | ||
| 277 | struct acpi_object_list input; | ||
| 278 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 279 | union acpi_object params[4]; | ||
| 280 | union acpi_object *ret_obj; | ||
| 281 | u64 req; | ||
| 282 | |||
| 283 | input.count = 4; | ||
| 284 | ppi_assign_params(params, TPM_PPI_FN_GETRSP); | ||
| 285 | input.pointer = params; | ||
| 286 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 287 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
| 288 | tpm_device_name, &handle); | ||
| 289 | if (ACPI_FAILURE(status)) | ||
| 290 | return -ENXIO; | ||
| 291 | |||
| 292 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 293 | ACPI_TYPE_PACKAGE); | ||
| 294 | if (ACPI_FAILURE(status)) | ||
| 295 | return -ENOMEM; | ||
| 296 | /* | ||
| 297 | * parameter output.pointer should be of package type, including | ||
| 298 | * 3 integers. The first means function return code, the second means | ||
| 299 | * most recent TPM operation request, and the last means response to | ||
| 300 | * the most recent TPM operation request. Only if the first is 0, and | ||
| 301 | * the second integer is not 0, the response makes sense. | ||
| 302 | */ | ||
| 303 | ret_obj = ((union acpi_object *)output.pointer)->package.elements; | ||
| 304 | if (ret_obj->type != ACPI_TYPE_INTEGER) { | ||
| 305 | status = -EINVAL; | ||
| 306 | goto cleanup; | ||
| 307 | } | ||
| 308 | if (ret_obj->integer.value) { | ||
| 309 | status = -EFAULT; | ||
| 310 | goto cleanup; | ||
| 311 | } | ||
| 312 | ret_obj++; | ||
| 313 | if (ret_obj->type != ACPI_TYPE_INTEGER) { | ||
| 314 | status = -EINVAL; | ||
| 315 | goto cleanup; | ||
| 316 | } | ||
| 317 | if (ret_obj->integer.value) { | ||
| 318 | req = ret_obj->integer.value; | ||
| 319 | ret_obj++; | ||
| 320 | if (ret_obj->type != ACPI_TYPE_INTEGER) { | ||
| 321 | status = -EINVAL; | ||
| 322 | goto cleanup; | ||
| 323 | } | ||
| 324 | if (ret_obj->integer.value == 0) | ||
| 325 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, | ||
| 326 | "0: Success"); | ||
| 327 | else if (ret_obj->integer.value == 0xFFFFFFF0) | ||
| 328 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, | ||
| 329 | "0xFFFFFFF0: User Abort"); | ||
| 330 | else if (ret_obj->integer.value == 0xFFFFFFF1) | ||
| 331 | status = scnprintf(buf, PAGE_SIZE, "%llu %s\n", req, | ||
| 332 | "0xFFFFFFF1: BIOS Failure"); | ||
| 333 | else if (ret_obj->integer.value >= 1 && | ||
| 334 | ret_obj->integer.value <= 0x00000FFF) | ||
| 335 | status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n", | ||
| 336 | req, ret_obj->integer.value, | ||
| 337 | "Corresponding TPM error"); | ||
| 338 | else | ||
| 339 | status = scnprintf(buf, PAGE_SIZE, "%llu %llu: %s\n", | ||
| 340 | req, ret_obj->integer.value, | ||
| 341 | "Error"); | ||
| 342 | } else { | ||
| 343 | status = scnprintf(buf, PAGE_SIZE, "%llu: %s\n", | ||
| 344 | ret_obj->integer.value, "No Recent Request"); | ||
| 345 | } | ||
| 346 | cleanup: | ||
| 347 | kfree(output.pointer); | ||
| 348 | return status; | ||
| 349 | } | ||
| 350 | |||
| 351 | static ssize_t show_ppi_operations(char *buf, u32 start, u32 end) | ||
| 352 | { | ||
| 353 | char *str = buf; | ||
| 354 | char version[PPI_VERSION_LEN]; | ||
| 355 | acpi_handle handle; | ||
| 356 | acpi_status status; | ||
| 357 | struct acpi_object_list input; | ||
| 358 | struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; | ||
| 359 | union acpi_object params[4]; | ||
| 360 | union acpi_object obj; | ||
| 361 | int i; | ||
| 362 | u32 ret; | ||
| 363 | char *info[] = { | ||
| 364 | "Not implemented", | ||
| 365 | "BIOS only", | ||
| 366 | "Blocked for OS by BIOS", | ||
| 367 | "User required", | ||
| 368 | "User not required", | ||
| 369 | }; | ||
| 370 | input.count = 4; | ||
| 371 | ppi_assign_params(params, TPM_PPI_FN_VERSION); | ||
| 372 | input.pointer = params; | ||
| 373 | status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | ||
| 374 | ACPI_UINT32_MAX, ppi_callback, NULL, | ||
| 375 | tpm_device_name, &handle); | ||
| 376 | if (ACPI_FAILURE(status)) | ||
| 377 | return -ENXIO; | ||
| 378 | |||
| 379 | status = acpi_evaluate_object_typed(handle, "_DSM", &input, &output, | ||
| 380 | ACPI_TYPE_STRING); | ||
| 381 | if (ACPI_FAILURE(status)) | ||
| 382 | return -ENOMEM; | ||
| 383 | |||
| 384 | strncpy(version, | ||
| 385 | ((union acpi_object *)output.pointer)->string.pointer, | ||
| 386 | PPI_VERSION_LEN); | ||
| 387 | kfree(output.pointer); | ||
| 388 | output.length = ACPI_ALLOCATE_BUFFER; | ||
| 389 | output.pointer = NULL; | ||
| 390 | if (strcmp(version, "1.2") == -1) | ||
| 391 | return -EPERM; | ||
| 392 | |||
| 393 | params[2].integer.value = TPM_PPI_FN_GETOPR; | ||
| 394 | params[3].package.count = 1; | ||
| 395 | obj.type = ACPI_TYPE_INTEGER; | ||
| 396 | params[3].package.elements = &obj; | ||
| 397 | for (i = start; i <= end; i++) { | ||
| 398 | obj.integer.value = i; | ||
| 399 | status = acpi_evaluate_object_typed(handle, "_DSM", | ||
| 400 | &input, &output, ACPI_TYPE_INTEGER); | ||
| 401 | if (ACPI_FAILURE(status)) | ||
| 402 | return -ENOMEM; | ||
| 403 | |||
| 404 | ret = ((union acpi_object *)output.pointer)->integer.value; | ||
| 405 | if (ret > 0 && ret < ARRAY_SIZE(info)) | ||
| 406 | str += scnprintf(str, PAGE_SIZE, "%d %d: %s\n", | ||
| 407 | i, ret, info[ret]); | ||
| 408 | kfree(output.pointer); | ||
| 409 | output.length = ACPI_ALLOCATE_BUFFER; | ||
| 410 | output.pointer = NULL; | ||
| 411 | } | ||
| 412 | return str - buf; | ||
| 413 | } | ||
| 414 | |||
| 415 | static ssize_t tpm_show_ppi_tcg_operations(struct device *dev, | ||
| 416 | struct device_attribute *attr, | ||
| 417 | char *buf) | ||
| 418 | { | ||
| 419 | return show_ppi_operations(buf, 0, PPI_TPM_REQ_MAX); | ||
| 420 | } | ||
| 421 | |||
| 422 | static ssize_t tpm_show_ppi_vs_operations(struct device *dev, | ||
| 423 | struct device_attribute *attr, | ||
| 424 | char *buf) | ||
| 425 | { | ||
| 426 | return show_ppi_operations(buf, PPI_VS_REQ_START, PPI_VS_REQ_END); | ||
| 427 | } | ||
| 428 | |||
| 429 | static DEVICE_ATTR(version, S_IRUGO, tpm_show_ppi_version, NULL); | ||
| 430 | static DEVICE_ATTR(request, S_IRUGO | S_IWUSR | S_IWGRP, | ||
| 431 | tpm_show_ppi_request, tpm_store_ppi_request); | ||
| 432 | static DEVICE_ATTR(transition_action, S_IRUGO, | ||
| 433 | tpm_show_ppi_transition_action, NULL); | ||
| 434 | static DEVICE_ATTR(response, S_IRUGO, tpm_show_ppi_response, NULL); | ||
| 435 | static DEVICE_ATTR(tcg_operations, S_IRUGO, tpm_show_ppi_tcg_operations, NULL); | ||
| 436 | static DEVICE_ATTR(vs_operations, S_IRUGO, tpm_show_ppi_vs_operations, NULL); | ||
| 437 | |||
| 438 | static struct attribute *ppi_attrs[] = { | ||
| 439 | &dev_attr_version.attr, | ||
| 440 | &dev_attr_request.attr, | ||
| 441 | &dev_attr_transition_action.attr, | ||
| 442 | &dev_attr_response.attr, | ||
| 443 | &dev_attr_tcg_operations.attr, | ||
| 444 | &dev_attr_vs_operations.attr, NULL, | ||
| 445 | }; | ||
| 446 | static struct attribute_group ppi_attr_grp = { | ||
| 447 | .name = "ppi", | ||
| 448 | .attrs = ppi_attrs | ||
| 449 | }; | ||
| 450 | |||
| 451 | int tpm_add_ppi(struct kobject *parent) | ||
| 452 | { | ||
| 453 | return sysfs_create_group(parent, &ppi_attr_grp); | ||
| 454 | } | ||
| 455 | EXPORT_SYMBOL_GPL(tpm_add_ppi); | ||
| 456 | |||
| 457 | void tpm_remove_ppi(struct kobject *parent) | ||
| 458 | { | ||
| 459 | sysfs_remove_group(parent, &ppi_attr_grp); | ||
| 460 | } | ||
| 461 | EXPORT_SYMBOL_GPL(tpm_remove_ppi); | ||
| 462 | |||
| 463 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c index ea31dafbcac..3f4051a7c5a 100644 --- a/drivers/char/tpm/tpm_tis.c +++ b/drivers/char/tpm/tpm_tis.c | |||
| @@ -29,6 +29,8 @@ | |||
| 29 | #include <linux/freezer.h> | 29 | #include <linux/freezer.h> |
| 30 | #include "tpm.h" | 30 | #include "tpm.h" |
| 31 | 31 | ||
| 32 | #define TPM_HEADER_SIZE 10 | ||
| 33 | |||
| 32 | enum tis_access { | 34 | enum tis_access { |
| 33 | TPM_ACCESS_VALID = 0x80, | 35 | TPM_ACCESS_VALID = 0x80, |
| 34 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, | 36 | TPM_ACCESS_ACTIVE_LOCALITY = 0x20, |
| @@ -76,7 +78,7 @@ enum tis_defaults { | |||
| 76 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) | 78 | #define TPM_RID(l) (0x0F04 | ((l) << 12)) |
| 77 | 79 | ||
| 78 | static LIST_HEAD(tis_chips); | 80 | static LIST_HEAD(tis_chips); |
| 79 | static DEFINE_MUTEX(tis_lock); | 81 | static DEFINE_SPINLOCK(tis_lock); |
| 80 | 82 | ||
| 81 | #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) | 83 | #if defined(CONFIG_PNP) && defined(CONFIG_ACPI) |
| 82 | static int is_itpm(struct pnp_dev *dev) | 84 | static int is_itpm(struct pnp_dev *dev) |
| @@ -191,14 +193,54 @@ static int get_burstcount(struct tpm_chip *chip) | |||
| 191 | return -EBUSY; | 193 | return -EBUSY; |
| 192 | } | 194 | } |
| 193 | 195 | ||
| 196 | static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout, | ||
| 197 | wait_queue_head_t *queue) | ||
| 198 | { | ||
| 199 | unsigned long stop; | ||
| 200 | long rc; | ||
| 201 | u8 status; | ||
| 202 | |||
| 203 | /* check current status */ | ||
| 204 | status = tpm_tis_status(chip); | ||
| 205 | if ((status & mask) == mask) | ||
| 206 | return 0; | ||
| 207 | |||
| 208 | stop = jiffies + timeout; | ||
| 209 | |||
| 210 | if (chip->vendor.irq) { | ||
| 211 | again: | ||
| 212 | timeout = stop - jiffies; | ||
| 213 | if ((long)timeout <= 0) | ||
| 214 | return -ETIME; | ||
| 215 | rc = wait_event_interruptible_timeout(*queue, | ||
| 216 | ((tpm_tis_status | ||
| 217 | (chip) & mask) == | ||
| 218 | mask), timeout); | ||
| 219 | if (rc > 0) | ||
| 220 | return 0; | ||
| 221 | if (rc == -ERESTARTSYS && freezing(current)) { | ||
| 222 | clear_thread_flag(TIF_SIGPENDING); | ||
| 223 | goto again; | ||
| 224 | } | ||
| 225 | } else { | ||
| 226 | do { | ||
| 227 | msleep(TPM_TIMEOUT); | ||
| 228 | status = tpm_tis_status(chip); | ||
| 229 | if ((status & mask) == mask) | ||
| 230 | return 0; | ||
| 231 | } while (time_before(jiffies, stop)); | ||
| 232 | } | ||
| 233 | return -ETIME; | ||
| 234 | } | ||
| 235 | |||
| 194 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) | 236 | static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count) |
| 195 | { | 237 | { |
| 196 | int size = 0, burstcnt; | 238 | int size = 0, burstcnt; |
| 197 | while (size < count && | 239 | while (size < count && |
| 198 | wait_for_tpm_stat(chip, | 240 | wait_for_stat(chip, |
| 199 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 241 | TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
| 200 | chip->vendor.timeout_c, | 242 | chip->vendor.timeout_c, |
| 201 | &chip->vendor.read_queue) | 243 | &chip->vendor.read_queue) |
| 202 | == 0) { | 244 | == 0) { |
| 203 | burstcnt = get_burstcount(chip); | 245 | burstcnt = get_burstcount(chip); |
| 204 | for (; burstcnt > 0 && size < count; burstcnt--) | 246 | for (; burstcnt > 0 && size < count; burstcnt--) |
| @@ -240,8 +282,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count) | |||
| 240 | goto out; | 282 | goto out; |
| 241 | } | 283 | } |
| 242 | 284 | ||
| 243 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 285 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
| 244 | &chip->vendor.int_queue); | 286 | &chip->vendor.int_queue); |
| 245 | status = tpm_tis_status(chip); | 287 | status = tpm_tis_status(chip); |
| 246 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ | 288 | if (status & TPM_STS_DATA_AVAIL) { /* retry? */ |
| 247 | dev_err(chip->dev, "Error left over data\n"); | 289 | dev_err(chip->dev, "Error left over data\n"); |
| @@ -255,7 +297,7 @@ out: | |||
| 255 | return size; | 297 | return size; |
| 256 | } | 298 | } |
| 257 | 299 | ||
| 258 | static bool itpm; | 300 | static int itpm; |
| 259 | module_param(itpm, bool, 0444); | 301 | module_param(itpm, bool, 0444); |
| 260 | MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); | 302 | MODULE_PARM_DESC(itpm, "Force iTPM workarounds (found on some Lenovo laptops)"); |
| 261 | 303 | ||
| @@ -275,7 +317,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 275 | status = tpm_tis_status(chip); | 317 | status = tpm_tis_status(chip); |
| 276 | if ((status & TPM_STS_COMMAND_READY) == 0) { | 318 | if ((status & TPM_STS_COMMAND_READY) == 0) { |
| 277 | tpm_tis_ready(chip); | 319 | tpm_tis_ready(chip); |
| 278 | if (wait_for_tpm_stat | 320 | if (wait_for_stat |
| 279 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, | 321 | (chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b, |
| 280 | &chip->vendor.int_queue) < 0) { | 322 | &chip->vendor.int_queue) < 0) { |
| 281 | rc = -ETIME; | 323 | rc = -ETIME; |
| @@ -291,8 +333,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 291 | count++; | 333 | count++; |
| 292 | } | 334 | } |
| 293 | 335 | ||
| 294 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 336 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
| 295 | &chip->vendor.int_queue); | 337 | &chip->vendor.int_queue); |
| 296 | status = tpm_tis_status(chip); | 338 | status = tpm_tis_status(chip); |
| 297 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { | 339 | if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) { |
| 298 | rc = -EIO; | 340 | rc = -EIO; |
| @@ -303,8 +345,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 303 | /* write last byte */ | 345 | /* write last byte */ |
| 304 | iowrite8(buf[count], | 346 | iowrite8(buf[count], |
| 305 | chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); | 347 | chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality)); |
| 306 | wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, | 348 | wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c, |
| 307 | &chip->vendor.int_queue); | 349 | &chip->vendor.int_queue); |
| 308 | status = tpm_tis_status(chip); | 350 | status = tpm_tis_status(chip); |
| 309 | if ((status & TPM_STS_DATA_EXPECT) != 0) { | 351 | if ((status & TPM_STS_DATA_EXPECT) != 0) { |
| 310 | rc = -EIO; | 352 | rc = -EIO; |
| @@ -339,7 +381,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len) | |||
| 339 | 381 | ||
| 340 | if (chip->vendor.irq) { | 382 | if (chip->vendor.irq) { |
| 341 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); | 383 | ordinal = be32_to_cpu(*((__be32 *) (buf + 6))); |
| 342 | if (wait_for_tpm_stat | 384 | if (wait_for_stat |
| 343 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, | 385 | (chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID, |
| 344 | tpm_calc_ordinal_duration(chip, ordinal), | 386 | tpm_calc_ordinal_duration(chip, ordinal), |
| 345 | &chip->vendor.read_queue) < 0) { | 387 | &chip->vendor.read_queue) < 0) { |
| @@ -367,12 +409,7 @@ static int probe_itpm(struct tpm_chip *chip) | |||
| 367 | 0x00, 0x00, 0x00, 0xf1 | 409 | 0x00, 0x00, 0x00, 0xf1 |
| 368 | }; | 410 | }; |
| 369 | size_t len = sizeof(cmd_getticks); | 411 | size_t len = sizeof(cmd_getticks); |
| 370 | bool rem_itpm = itpm; | 412 | int rem_itpm = itpm; |
| 371 | u16 vendor = ioread16(chip->vendor.iobase + TPM_DID_VID(0)); | ||
| 372 | |||
| 373 | /* probe only iTPMS */ | ||
| 374 | if (vendor != TPM_VID_INTEL) | ||
| 375 | return 0; | ||
| 376 | 413 | ||
| 377 | itpm = 0; | 414 | itpm = 0; |
| 378 | 415 | ||
| @@ -502,7 +539,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id) | |||
| 502 | return IRQ_HANDLED; | 539 | return IRQ_HANDLED; |
| 503 | } | 540 | } |
| 504 | 541 | ||
| 505 | static bool interrupts = 1; | 542 | static int interrupts = 1; |
| 506 | module_param(interrupts, bool, 0444); | 543 | module_param(interrupts, bool, 0444); |
| 507 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); | 544 | MODULE_PARM_DESC(interrupts, "Enable interrupts"); |
| 508 | 545 | ||
| @@ -510,7 +547,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
| 510 | resource_size_t len, unsigned int irq) | 547 | resource_size_t len, unsigned int irq) |
| 511 | { | 548 | { |
| 512 | u32 vendor, intfcaps, intmask; | 549 | u32 vendor, intfcaps, intmask; |
| 513 | int rc, i, irq_s, irq_e, probe; | 550 | int rc, i, irq_s, irq_e; |
| 514 | struct tpm_chip *chip; | 551 | struct tpm_chip *chip; |
| 515 | 552 | ||
| 516 | if (!(chip = tpm_register_hardware(dev, &tpm_tis))) | 553 | if (!(chip = tpm_register_hardware(dev, &tpm_tis))) |
| @@ -540,12 +577,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
| 540 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); | 577 | vendor >> 16, ioread8(chip->vendor.iobase + TPM_RID(0))); |
| 541 | 578 | ||
| 542 | if (!itpm) { | 579 | if (!itpm) { |
| 543 | probe = probe_itpm(chip); | 580 | itpm = probe_itpm(chip); |
| 544 | if (probe < 0) { | 581 | if (itpm < 0) { |
| 545 | rc = -ENODEV; | 582 | rc = -ENODEV; |
| 546 | goto out_err; | 583 | goto out_err; |
| 547 | } | 584 | } |
| 548 | itpm = (probe == 0) ? 0 : 1; | ||
| 549 | } | 585 | } |
| 550 | 586 | ||
| 551 | if (itpm) | 587 | if (itpm) |
| @@ -578,17 +614,7 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
| 578 | dev_dbg(dev, "\tData Avail Int Support\n"); | 614 | dev_dbg(dev, "\tData Avail Int Support\n"); |
| 579 | 615 | ||
| 580 | /* get the timeouts before testing for irqs */ | 616 | /* get the timeouts before testing for irqs */ |
| 581 | if (tpm_get_timeouts(chip)) { | 617 | tpm_get_timeouts(chip); |
| 582 | dev_err(dev, "Could not get TPM timeouts and durations\n"); | ||
| 583 | rc = -ENODEV; | ||
| 584 | goto out_err; | ||
| 585 | } | ||
| 586 | |||
| 587 | if (tpm_do_selftest(chip)) { | ||
| 588 | dev_err(dev, "TPM self test failed\n"); | ||
| 589 | rc = -ENODEV; | ||
| 590 | goto out_err; | ||
| 591 | } | ||
| 592 | 618 | ||
| 593 | /* INTERRUPT Setup */ | 619 | /* INTERRUPT Setup */ |
| 594 | init_waitqueue_head(&chip->vendor.read_queue); | 620 | init_waitqueue_head(&chip->vendor.read_queue); |
| @@ -692,10 +718,11 @@ static int tpm_tis_init(struct device *dev, resource_size_t start, | |||
| 692 | } | 718 | } |
| 693 | 719 | ||
| 694 | INIT_LIST_HEAD(&chip->vendor.list); | 720 | INIT_LIST_HEAD(&chip->vendor.list); |
| 695 | mutex_lock(&tis_lock); | 721 | spin_lock(&tis_lock); |
| 696 | list_add(&chip->vendor.list, &tis_chips); | 722 | list_add(&chip->vendor.list, &tis_chips); |
| 697 | mutex_unlock(&tis_lock); | 723 | spin_unlock(&tis_lock); |
| 698 | 724 | ||
| 725 | tpm_continue_selftest(chip); | ||
| 699 | 726 | ||
| 700 | return 0; | 727 | return 0; |
| 701 | out_err: | 728 | out_err: |
| @@ -705,7 +732,6 @@ out_err: | |||
| 705 | return rc; | 732 | return rc; |
| 706 | } | 733 | } |
| 707 | 734 | ||
| 708 | #if defined(CONFIG_PNP) || defined(CONFIG_PM_SLEEP) | ||
| 709 | static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | 735 | static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) |
| 710 | { | 736 | { |
| 711 | u32 intmask; | 737 | u32 intmask; |
| @@ -726,10 +752,10 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip) | |||
| 726 | iowrite32(intmask, | 752 | iowrite32(intmask, |
| 727 | chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); | 753 | chip->vendor.iobase + TPM_INT_ENABLE(chip->vendor.locality)); |
| 728 | } | 754 | } |
| 729 | #endif | 755 | |
| 730 | 756 | ||
| 731 | #ifdef CONFIG_PNP | 757 | #ifdef CONFIG_PNP |
| 732 | static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | 758 | static int __devinit tpm_tis_pnp_init(struct pnp_dev *pnp_dev, |
| 733 | const struct pnp_device_id *pnp_id) | 759 | const struct pnp_device_id *pnp_id) |
| 734 | { | 760 | { |
| 735 | resource_size_t start, len; | 761 | resource_size_t start, len; |
| @@ -751,7 +777,7 @@ static int tpm_tis_pnp_init(struct pnp_dev *pnp_dev, | |||
| 751 | 777 | ||
| 752 | static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) | 778 | static int tpm_tis_pnp_suspend(struct pnp_dev *dev, pm_message_t msg) |
| 753 | { | 779 | { |
| 754 | return tpm_pm_suspend(&dev->dev); | 780 | return tpm_pm_suspend(&dev->dev, msg); |
| 755 | } | 781 | } |
| 756 | 782 | ||
| 757 | static int tpm_tis_pnp_resume(struct pnp_dev *dev) | 783 | static int tpm_tis_pnp_resume(struct pnp_dev *dev) |
| @@ -764,12 +790,12 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev) | |||
| 764 | 790 | ||
| 765 | ret = tpm_pm_resume(&dev->dev); | 791 | ret = tpm_pm_resume(&dev->dev); |
| 766 | if (!ret) | 792 | if (!ret) |
| 767 | tpm_do_selftest(chip); | 793 | tpm_continue_selftest(chip); |
| 768 | 794 | ||
| 769 | return ret; | 795 | return ret; |
| 770 | } | 796 | } |
| 771 | 797 | ||
| 772 | static struct pnp_device_id tpm_pnp_tbl[] = { | 798 | static struct pnp_device_id tpm_pnp_tbl[] __devinitdata = { |
| 773 | {"PNP0C31", 0}, /* TPM */ | 799 | {"PNP0C31", 0}, /* TPM */ |
| 774 | {"ATM1200", 0}, /* Atmel */ | 800 | {"ATM1200", 0}, /* Atmel */ |
| 775 | {"IFX0102", 0}, /* Infineon */ | 801 | {"IFX0102", 0}, /* Infineon */ |
| @@ -783,7 +809,7 @@ static struct pnp_device_id tpm_pnp_tbl[] = { | |||
| 783 | }; | 809 | }; |
| 784 | MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); | 810 | MODULE_DEVICE_TABLE(pnp, tpm_pnp_tbl); |
| 785 | 811 | ||
| 786 | static void tpm_tis_pnp_remove(struct pnp_dev *dev) | 812 | static __devexit void tpm_tis_pnp_remove(struct pnp_dev *dev) |
| 787 | { | 813 | { |
| 788 | struct tpm_chip *chip = pnp_get_drvdata(dev); | 814 | struct tpm_chip *chip = pnp_get_drvdata(dev); |
| 789 | 815 | ||
| @@ -807,32 +833,32 @@ module_param_string(hid, tpm_pnp_tbl[TIS_HID_USR_IDX].id, | |||
| 807 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); | 833 | sizeof(tpm_pnp_tbl[TIS_HID_USR_IDX].id), 0444); |
| 808 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); | 834 | MODULE_PARM_DESC(hid, "Set additional specific HID for this driver to probe"); |
| 809 | #endif | 835 | #endif |
| 836 | static int tpm_tis_suspend(struct platform_device *dev, pm_message_t msg) | ||
| 837 | { | ||
| 838 | return tpm_pm_suspend(&dev->dev, msg); | ||
| 839 | } | ||
| 810 | 840 | ||
| 811 | #ifdef CONFIG_PM_SLEEP | 841 | static int tpm_tis_resume(struct platform_device *dev) |
| 812 | static int tpm_tis_resume(struct device *dev) | ||
| 813 | { | 842 | { |
| 814 | struct tpm_chip *chip = dev_get_drvdata(dev); | 843 | struct tpm_chip *chip = dev_get_drvdata(&dev->dev); |
| 815 | 844 | ||
| 816 | if (chip->vendor.irq) | 845 | if (chip->vendor.irq) |
| 817 | tpm_tis_reenable_interrupts(chip); | 846 | tpm_tis_reenable_interrupts(chip); |
| 818 | 847 | ||
| 819 | return tpm_pm_resume(dev); | 848 | return tpm_pm_resume(&dev->dev); |
| 820 | } | 849 | } |
| 821 | #endif | ||
| 822 | |||
| 823 | static SIMPLE_DEV_PM_OPS(tpm_tis_pm, tpm_pm_suspend, tpm_tis_resume); | ||
| 824 | |||
| 825 | static struct platform_driver tis_drv = { | 850 | static struct platform_driver tis_drv = { |
| 826 | .driver = { | 851 | .driver = { |
| 827 | .name = "tpm_tis", | 852 | .name = "tpm_tis", |
| 828 | .owner = THIS_MODULE, | 853 | .owner = THIS_MODULE, |
| 829 | .pm = &tpm_tis_pm, | ||
| 830 | }, | 854 | }, |
| 855 | .suspend = tpm_tis_suspend, | ||
| 856 | .resume = tpm_tis_resume, | ||
| 831 | }; | 857 | }; |
| 832 | 858 | ||
| 833 | static struct platform_device *pdev; | 859 | static struct platform_device *pdev; |
| 834 | 860 | ||
| 835 | static bool force; | 861 | static int force; |
| 836 | module_param(force, bool, 0444); | 862 | module_param(force, bool, 0444); |
| 837 | MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); | 863 | MODULE_PARM_DESC(force, "Force device probe rather than using ACPI entry"); |
| 838 | static int __init init_tis(void) | 864 | static int __init init_tis(void) |
| @@ -859,7 +885,7 @@ static void __exit cleanup_tis(void) | |||
| 859 | { | 885 | { |
| 860 | struct tpm_vendor_specific *i, *j; | 886 | struct tpm_vendor_specific *i, *j; |
| 861 | struct tpm_chip *chip; | 887 | struct tpm_chip *chip; |
| 862 | mutex_lock(&tis_lock); | 888 | spin_lock(&tis_lock); |
| 863 | list_for_each_entry_safe(i, j, &tis_chips, list) { | 889 | list_for_each_entry_safe(i, j, &tis_chips, list) { |
| 864 | chip = to_tpm_chip(i); | 890 | chip = to_tpm_chip(i); |
| 865 | tpm_remove_hardware(chip->dev); | 891 | tpm_remove_hardware(chip->dev); |
| @@ -875,7 +901,7 @@ static void __exit cleanup_tis(void) | |||
| 875 | iounmap(i->iobase); | 901 | iounmap(i->iobase); |
| 876 | list_del(&i->list); | 902 | list_del(&i->list); |
| 877 | } | 903 | } |
| 878 | mutex_unlock(&tis_lock); | 904 | spin_unlock(&tis_lock); |
| 879 | #ifdef CONFIG_PNP | 905 | #ifdef CONFIG_PNP |
| 880 | if (!force) { | 906 | if (!force) { |
| 881 | pnp_unregister_driver(&tis_pnp_driver); | 907 | pnp_unregister_driver(&tis_pnp_driver); |
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c index 4945bd3d18d..a1f68af4ccf 100644 --- a/drivers/char/ttyprintk.c +++ b/drivers/char/ttyprintk.c | |||
| @@ -17,7 +17,6 @@ | |||
| 17 | #include <linux/device.h> | 17 | #include <linux/device.h> |
| 18 | #include <linux/serial.h> | 18 | #include <linux/serial.h> |
| 19 | #include <linux/tty.h> | 19 | #include <linux/tty.h> |
| 20 | #include <linux/export.h> | ||
| 21 | 20 | ||
| 22 | struct ttyprintk_port { | 21 | struct ttyprintk_port { |
| 23 | struct tty_port port; | 22 | struct tty_port port; |
| @@ -67,7 +66,7 @@ static int tpk_printk(const unsigned char *buf, int count) | |||
| 67 | tmp[tpk_curr + 1] = '\0'; | 66 | tmp[tpk_curr + 1] = '\0'; |
| 68 | printk(KERN_INFO "%s%s", tpk_tag, tmp); | 67 | printk(KERN_INFO "%s%s", tpk_tag, tmp); |
| 69 | tpk_curr = 0; | 68 | tpk_curr = 0; |
| 70 | if ((i + 1) < count && buf[i + 1] == '\n') | 69 | if (buf[i + 1] == '\n') |
| 71 | i++; | 70 | i++; |
| 72 | break; | 71 | break; |
| 73 | case '\n': | 72 | case '\n': |
| @@ -171,35 +170,31 @@ static const struct tty_operations ttyprintk_ops = { | |||
| 171 | .ioctl = tpk_ioctl, | 170 | .ioctl = tpk_ioctl, |
| 172 | }; | 171 | }; |
| 173 | 172 | ||
| 174 | static struct tty_port_operations null_ops = { }; | 173 | struct tty_port_operations null_ops = { }; |
| 175 | 174 | ||
| 176 | static struct tty_driver *ttyprintk_driver; | 175 | static struct tty_driver *ttyprintk_driver; |
| 177 | 176 | ||
| 178 | static int __init ttyprintk_init(void) | 177 | static int __init ttyprintk_init(void) |
| 179 | { | 178 | { |
| 180 | int ret = -ENOMEM; | 179 | int ret = -ENOMEM; |
| 180 | void *rp; | ||
| 181 | 181 | ||
| 182 | tpk_port.port.ops = &null_ops; | 182 | ttyprintk_driver = alloc_tty_driver(1); |
| 183 | mutex_init(&tpk_port.port_write_mutex); | 183 | if (!ttyprintk_driver) |
| 184 | 184 | return ret; | |
| 185 | ttyprintk_driver = tty_alloc_driver(1, | ||
| 186 | TTY_DRIVER_RESET_TERMIOS | | ||
| 187 | TTY_DRIVER_REAL_RAW | | ||
| 188 | TTY_DRIVER_UNNUMBERED_NODE); | ||
| 189 | if (IS_ERR(ttyprintk_driver)) | ||
| 190 | return PTR_ERR(ttyprintk_driver); | ||
| 191 | |||
| 192 | tty_port_init(&tpk_port.port); | ||
| 193 | 185 | ||
| 186 | ttyprintk_driver->owner = THIS_MODULE; | ||
| 194 | ttyprintk_driver->driver_name = "ttyprintk"; | 187 | ttyprintk_driver->driver_name = "ttyprintk"; |
| 195 | ttyprintk_driver->name = "ttyprintk"; | 188 | ttyprintk_driver->name = "ttyprintk"; |
| 196 | ttyprintk_driver->major = TTYAUX_MAJOR; | 189 | ttyprintk_driver->major = TTYAUX_MAJOR; |
| 197 | ttyprintk_driver->minor_start = 3; | 190 | ttyprintk_driver->minor_start = 3; |
| 191 | ttyprintk_driver->num = 1; | ||
| 198 | ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE; | 192 | ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE; |
| 199 | ttyprintk_driver->init_termios = tty_std_termios; | 193 | ttyprintk_driver->init_termios = tty_std_termios; |
| 200 | ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET; | 194 | ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET; |
| 195 | ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS | | ||
| 196 | TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | ||
| 201 | tty_set_operations(ttyprintk_driver, &ttyprintk_ops); | 197 | tty_set_operations(ttyprintk_driver, &ttyprintk_ops); |
| 202 | tty_port_link_device(&tpk_port.port, ttyprintk_driver, 0); | ||
| 203 | 198 | ||
| 204 | ret = tty_register_driver(ttyprintk_driver); | 199 | ret = tty_register_driver(ttyprintk_driver); |
| 205 | if (ret < 0) { | 200 | if (ret < 0) { |
| @@ -207,12 +202,23 @@ static int __init ttyprintk_init(void) | |||
| 207 | goto error; | 202 | goto error; |
| 208 | } | 203 | } |
| 209 | 204 | ||
| 205 | /* create our unnumbered device */ | ||
| 206 | rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL, | ||
| 207 | ttyprintk_driver->name); | ||
| 208 | if (IS_ERR(rp)) { | ||
| 209 | printk(KERN_ERR "Couldn't create ttyprintk device\n"); | ||
| 210 | ret = PTR_ERR(rp); | ||
| 211 | goto error; | ||
| 212 | } | ||
| 213 | |||
| 214 | tty_port_init(&tpk_port.port); | ||
| 215 | tpk_port.port.ops = &null_ops; | ||
| 216 | mutex_init(&tpk_port.port_write_mutex); | ||
| 217 | |||
| 210 | return 0; | 218 | return 0; |
| 211 | 219 | ||
| 212 | error: | 220 | error: |
| 213 | tty_unregister_driver(ttyprintk_driver); | ||
| 214 | put_tty_driver(ttyprintk_driver); | 221 | put_tty_driver(ttyprintk_driver); |
| 215 | tty_port_destroy(&tpk_port.port); | ||
| 216 | ttyprintk_driver = NULL; | 222 | ttyprintk_driver = NULL; |
| 217 | return ret; | 223 | return ret; |
| 218 | } | 224 | } |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 684b0d53764..fb68b129537 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
| @@ -19,13 +19,9 @@ | |||
| 19 | */ | 19 | */ |
| 20 | #include <linux/cdev.h> | 20 | #include <linux/cdev.h> |
| 21 | #include <linux/debugfs.h> | 21 | #include <linux/debugfs.h> |
| 22 | #include <linux/completion.h> | ||
| 23 | #include <linux/device.h> | 22 | #include <linux/device.h> |
| 24 | #include <linux/err.h> | 23 | #include <linux/err.h> |
| 25 | #include <linux/freezer.h> | ||
| 26 | #include <linux/fs.h> | 24 | #include <linux/fs.h> |
| 27 | #include <linux/splice.h> | ||
| 28 | #include <linux/pagemap.h> | ||
| 29 | #include <linux/init.h> | 25 | #include <linux/init.h> |
| 30 | #include <linux/list.h> | 26 | #include <linux/list.h> |
| 31 | #include <linux/poll.h> | 27 | #include <linux/poll.h> |
| @@ -36,13 +32,8 @@ | |||
| 36 | #include <linux/virtio_console.h> | 32 | #include <linux/virtio_console.h> |
| 37 | #include <linux/wait.h> | 33 | #include <linux/wait.h> |
| 38 | #include <linux/workqueue.h> | 34 | #include <linux/workqueue.h> |
| 39 | #include <linux/module.h> | ||
| 40 | #include <linux/dma-mapping.h> | ||
| 41 | #include <linux/kconfig.h> | ||
| 42 | #include "../tty/hvc/hvc_console.h" | 35 | #include "../tty/hvc/hvc_console.h" |
| 43 | 36 | ||
| 44 | #define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC) | ||
| 45 | |||
| 46 | /* | 37 | /* |
| 47 | * This is a global struct for storing common data for all the devices | 38 | * This is a global struct for storing common data for all the devices |
| 48 | * this driver handles. | 39 | * this driver handles. |
| @@ -82,7 +73,6 @@ struct ports_driver_data { | |||
| 82 | static struct ports_driver_data pdrvdata; | 73 | static struct ports_driver_data pdrvdata; |
| 83 | 74 | ||
| 84 | DEFINE_SPINLOCK(pdrvdata_lock); | 75 | DEFINE_SPINLOCK(pdrvdata_lock); |
| 85 | DECLARE_COMPLETION(early_console_added); | ||
| 86 | 76 | ||
| 87 | /* This struct holds information that's relevant only for console ports */ | 77 | /* This struct holds information that's relevant only for console ports */ |
| 88 | struct console { | 78 | struct console { |
| @@ -115,21 +105,6 @@ struct port_buffer { | |||
| 115 | size_t len; | 105 | size_t len; |
| 116 | /* offset in the buf from which to consume data */ | 106 | /* offset in the buf from which to consume data */ |
| 117 | size_t offset; | 107 | size_t offset; |
| 118 | |||
| 119 | /* DMA address of buffer */ | ||
| 120 | dma_addr_t dma; | ||
| 121 | |||
| 122 | /* Device we got DMA memory from */ | ||
| 123 | struct device *dev; | ||
| 124 | |||
| 125 | /* List of pending dma buffers to free */ | ||
| 126 | struct list_head list; | ||
| 127 | |||
| 128 | /* If sgpages == 0 then buf is used */ | ||
| 129 | unsigned int sgpages; | ||
| 130 | |||
| 131 | /* sg is used if spages > 0. sg must be the last in is struct */ | ||
| 132 | struct scatterlist sg[0]; | ||
| 133 | }; | 108 | }; |
| 134 | 109 | ||
| 135 | /* | 110 | /* |
| @@ -176,10 +151,6 @@ struct ports_device { | |||
| 176 | int chr_major; | 151 | int chr_major; |
| 177 | }; | 152 | }; |
| 178 | 153 | ||
| 179 | struct port_stats { | ||
| 180 | unsigned long bytes_sent, bytes_received, bytes_discarded; | ||
| 181 | }; | ||
| 182 | |||
| 183 | /* This struct holds the per-port data */ | 154 | /* This struct holds the per-port data */ |
| 184 | struct port { | 155 | struct port { |
| 185 | /* Next port in the list, head is in the ports_device */ | 156 | /* Next port in the list, head is in the ports_device */ |
| @@ -208,13 +179,6 @@ struct port { | |||
| 208 | struct dentry *debugfs_file; | 179 | struct dentry *debugfs_file; |
| 209 | 180 | ||
| 210 | /* | 181 | /* |
| 211 | * Keep count of the bytes sent, received and discarded for | ||
| 212 | * this port for accounting and debugging purposes. These | ||
| 213 | * counts are not reset across port open / close events. | ||
| 214 | */ | ||
| 215 | struct port_stats stats; | ||
| 216 | |||
| 217 | /* | ||
| 218 | * The entries in this struct will be valid if this port is | 182 | * The entries in this struct will be valid if this port is |
| 219 | * hooked up to an hvc console | 183 | * hooked up to an hvc console |
| 220 | */ | 184 | */ |
| @@ -344,11 +308,6 @@ static bool is_console_port(struct port *port) | |||
| 344 | return false; | 308 | return false; |
| 345 | } | 309 | } |
| 346 | 310 | ||
| 347 | static bool is_rproc_serial(const struct virtio_device *vdev) | ||
| 348 | { | ||
| 349 | return is_rproc_enabled && vdev->id.device == VIRTIO_ID_RPROC_SERIAL; | ||
| 350 | } | ||
| 351 | |||
| 352 | static inline bool use_multiport(struct ports_device *portdev) | 311 | static inline bool use_multiport(struct ports_device *portdev) |
| 353 | { | 312 | { |
| 354 | /* | 313 | /* |
| @@ -360,110 +319,20 @@ static inline bool use_multiport(struct ports_device *portdev) | |||
| 360 | return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT); | 319 | return portdev->vdev->features[0] & (1 << VIRTIO_CONSOLE_F_MULTIPORT); |
| 361 | } | 320 | } |
| 362 | 321 | ||
| 363 | static DEFINE_SPINLOCK(dma_bufs_lock); | 322 | static void free_buf(struct port_buffer *buf) |
| 364 | static LIST_HEAD(pending_free_dma_bufs); | ||
| 365 | |||
| 366 | static void free_buf(struct port_buffer *buf, bool can_sleep) | ||
| 367 | { | 323 | { |
| 368 | unsigned int i; | 324 | kfree(buf->buf); |
| 369 | |||
| 370 | for (i = 0; i < buf->sgpages; i++) { | ||
| 371 | struct page *page = sg_page(&buf->sg[i]); | ||
| 372 | if (!page) | ||
| 373 | break; | ||
| 374 | put_page(page); | ||
| 375 | } | ||
| 376 | |||
| 377 | if (!buf->dev) { | ||
| 378 | kfree(buf->buf); | ||
| 379 | } else if (is_rproc_enabled) { | ||
| 380 | unsigned long flags; | ||
| 381 | |||
| 382 | /* dma_free_coherent requires interrupts to be enabled. */ | ||
| 383 | if (!can_sleep) { | ||
| 384 | /* queue up dma-buffers to be freed later */ | ||
| 385 | spin_lock_irqsave(&dma_bufs_lock, flags); | ||
| 386 | list_add_tail(&buf->list, &pending_free_dma_bufs); | ||
| 387 | spin_unlock_irqrestore(&dma_bufs_lock, flags); | ||
| 388 | return; | ||
| 389 | } | ||
| 390 | dma_free_coherent(buf->dev, buf->size, buf->buf, buf->dma); | ||
| 391 | |||
| 392 | /* Release device refcnt and allow it to be freed */ | ||
| 393 | put_device(buf->dev); | ||
| 394 | } | ||
| 395 | |||
| 396 | kfree(buf); | 325 | kfree(buf); |
| 397 | } | 326 | } |
| 398 | 327 | ||
| 399 | static void reclaim_dma_bufs(void) | 328 | static struct port_buffer *alloc_buf(size_t buf_size) |
| 400 | { | ||
| 401 | unsigned long flags; | ||
| 402 | struct port_buffer *buf, *tmp; | ||
| 403 | LIST_HEAD(tmp_list); | ||
| 404 | |||
| 405 | if (list_empty(&pending_free_dma_bufs)) | ||
| 406 | return; | ||
| 407 | |||
| 408 | /* Create a copy of the pending_free_dma_bufs while holding the lock */ | ||
| 409 | spin_lock_irqsave(&dma_bufs_lock, flags); | ||
| 410 | list_cut_position(&tmp_list, &pending_free_dma_bufs, | ||
| 411 | pending_free_dma_bufs.prev); | ||
| 412 | spin_unlock_irqrestore(&dma_bufs_lock, flags); | ||
| 413 | |||
| 414 | /* Release the dma buffers, without irqs enabled */ | ||
| 415 | list_for_each_entry_safe(buf, tmp, &tmp_list, list) { | ||
| 416 | list_del(&buf->list); | ||
| 417 | free_buf(buf, true); | ||
| 418 | } | ||
| 419 | } | ||
| 420 | |||
| 421 | static struct port_buffer *alloc_buf(struct virtqueue *vq, size_t buf_size, | ||
| 422 | int pages) | ||
| 423 | { | 329 | { |
| 424 | struct port_buffer *buf; | 330 | struct port_buffer *buf; |
| 425 | 331 | ||
| 426 | reclaim_dma_bufs(); | 332 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); |
| 427 | |||
| 428 | /* | ||
| 429 | * Allocate buffer and the sg list. The sg list array is allocated | ||
| 430 | * directly after the port_buffer struct. | ||
| 431 | */ | ||
| 432 | buf = kmalloc(sizeof(*buf) + sizeof(struct scatterlist) * pages, | ||
| 433 | GFP_KERNEL); | ||
| 434 | if (!buf) | 333 | if (!buf) |
| 435 | goto fail; | 334 | goto fail; |
| 436 | 335 | buf->buf = kzalloc(buf_size, GFP_KERNEL); | |
| 437 | buf->sgpages = pages; | ||
| 438 | if (pages > 0) { | ||
| 439 | buf->dev = NULL; | ||
| 440 | buf->buf = NULL; | ||
| 441 | return buf; | ||
| 442 | } | ||
| 443 | |||
| 444 | if (is_rproc_serial(vq->vdev)) { | ||
| 445 | /* | ||
| 446 | * Allocate DMA memory from ancestor. When a virtio | ||
| 447 | * device is created by remoteproc, the DMA memory is | ||
| 448 | * associated with the grandparent device: | ||
| 449 | * vdev => rproc => platform-dev. | ||
| 450 | * The code here would have been less quirky if | ||
| 451 | * DMA_MEMORY_INCLUDES_CHILDREN had been supported | ||
| 452 | * in dma-coherent.c | ||
| 453 | */ | ||
| 454 | if (!vq->vdev->dev.parent || !vq->vdev->dev.parent->parent) | ||
| 455 | goto free_buf; | ||
| 456 | buf->dev = vq->vdev->dev.parent->parent; | ||
| 457 | |||
| 458 | /* Increase device refcnt to avoid freeing it */ | ||
| 459 | get_device(buf->dev); | ||
| 460 | buf->buf = dma_alloc_coherent(buf->dev, buf_size, &buf->dma, | ||
| 461 | GFP_KERNEL); | ||
| 462 | } else { | ||
| 463 | buf->dev = NULL; | ||
| 464 | buf->buf = kmalloc(buf_size, GFP_KERNEL); | ||
| 465 | } | ||
| 466 | |||
| 467 | if (!buf->buf) | 336 | if (!buf->buf) |
| 468 | goto free_buf; | 337 | goto free_buf; |
| 469 | buf->len = 0; | 338 | buf->len = 0; |
| @@ -478,19 +347,17 @@ fail: | |||
| 478 | } | 347 | } |
| 479 | 348 | ||
| 480 | /* Callers should take appropriate locks */ | 349 | /* Callers should take appropriate locks */ |
| 481 | static struct port_buffer *get_inbuf(struct port *port) | 350 | static void *get_inbuf(struct port *port) |
| 482 | { | 351 | { |
| 483 | struct port_buffer *buf; | 352 | struct port_buffer *buf; |
| 353 | struct virtqueue *vq; | ||
| 484 | unsigned int len; | 354 | unsigned int len; |
| 485 | 355 | ||
| 486 | if (port->inbuf) | 356 | vq = port->in_vq; |
| 487 | return port->inbuf; | 357 | buf = virtqueue_get_buf(vq, &len); |
| 488 | |||
| 489 | buf = virtqueue_get_buf(port->in_vq, &len); | ||
| 490 | if (buf) { | 358 | if (buf) { |
| 491 | buf->len = len; | 359 | buf->len = len; |
| 492 | buf->offset = 0; | 360 | buf->offset = 0; |
| 493 | port->stats.bytes_received += len; | ||
| 494 | } | 361 | } |
| 495 | return buf; | 362 | return buf; |
| 496 | } | 363 | } |
| @@ -508,10 +375,8 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) | |||
| 508 | 375 | ||
| 509 | sg_init_one(sg, buf->buf, buf->size); | 376 | sg_init_one(sg, buf->buf, buf->size); |
| 510 | 377 | ||
| 511 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf, GFP_ATOMIC); | 378 | ret = virtqueue_add_buf(vq, sg, 0, 1, buf); |
| 512 | virtqueue_kick(vq); | 379 | virtqueue_kick(vq); |
| 513 | if (!ret) | ||
| 514 | ret = vq->num_free; | ||
| 515 | return ret; | 380 | return ret; |
| 516 | } | 381 | } |
| 517 | 382 | ||
| @@ -519,27 +384,32 @@ static int add_inbuf(struct virtqueue *vq, struct port_buffer *buf) | |||
| 519 | static void discard_port_data(struct port *port) | 384 | static void discard_port_data(struct port *port) |
| 520 | { | 385 | { |
| 521 | struct port_buffer *buf; | 386 | struct port_buffer *buf; |
| 522 | unsigned int err; | 387 | struct virtqueue *vq; |
| 388 | unsigned int len; | ||
| 389 | int ret; | ||
| 523 | 390 | ||
| 524 | if (!port->portdev) { | 391 | if (!port->portdev) { |
| 525 | /* Device has been unplugged. vqs are already gone. */ | 392 | /* Device has been unplugged. vqs are already gone. */ |
| 526 | return; | 393 | return; |
| 527 | } | 394 | } |
| 528 | buf = get_inbuf(port); | 395 | vq = port->in_vq; |
| 396 | if (port->inbuf) | ||
| 397 | buf = port->inbuf; | ||
| 398 | else | ||
| 399 | buf = virtqueue_get_buf(vq, &len); | ||
| 529 | 400 | ||
| 530 | err = 0; | 401 | ret = 0; |
| 531 | while (buf) { | 402 | while (buf) { |
| 532 | port->stats.bytes_discarded += buf->len - buf->offset; | 403 | if (add_inbuf(vq, buf) < 0) { |
| 533 | if (add_inbuf(port->in_vq, buf) < 0) { | 404 | ret++; |
| 534 | err++; | 405 | free_buf(buf); |
| 535 | free_buf(buf, false); | ||
| 536 | } | 406 | } |
| 537 | port->inbuf = NULL; | 407 | buf = virtqueue_get_buf(vq, &len); |
| 538 | buf = get_inbuf(port); | ||
| 539 | } | 408 | } |
| 540 | if (err) | 409 | port->inbuf = NULL; |
| 410 | if (ret) | ||
| 541 | dev_warn(port->dev, "Errors adding %d buffers back to vq\n", | 411 | dev_warn(port->dev, "Errors adding %d buffers back to vq\n", |
| 542 | err); | 412 | ret); |
| 543 | } | 413 | } |
| 544 | 414 | ||
| 545 | static bool port_has_data(struct port *port) | 415 | static bool port_has_data(struct port *port) |
| @@ -547,12 +417,18 @@ static bool port_has_data(struct port *port) | |||
| 547 | unsigned long flags; | 417 | unsigned long flags; |
| 548 | bool ret; | 418 | bool ret; |
| 549 | 419 | ||
| 550 | ret = false; | ||
| 551 | spin_lock_irqsave(&port->inbuf_lock, flags); | 420 | spin_lock_irqsave(&port->inbuf_lock, flags); |
| 421 | if (port->inbuf) { | ||
| 422 | ret = true; | ||
| 423 | goto out; | ||
| 424 | } | ||
| 552 | port->inbuf = get_inbuf(port); | 425 | port->inbuf = get_inbuf(port); |
| 553 | if (port->inbuf) | 426 | if (port->inbuf) { |
| 554 | ret = true; | 427 | ret = true; |
| 555 | 428 | goto out; | |
| 429 | } | ||
| 430 | ret = false; | ||
| 431 | out: | ||
| 556 | spin_unlock_irqrestore(&port->inbuf_lock, flags); | 432 | spin_unlock_irqrestore(&port->inbuf_lock, flags); |
| 557 | return ret; | 433 | return ret; |
| 558 | } | 434 | } |
| @@ -575,7 +451,7 @@ static ssize_t __send_control_msg(struct ports_device *portdev, u32 port_id, | |||
| 575 | vq = portdev->c_ovq; | 451 | vq = portdev->c_ovq; |
| 576 | 452 | ||
| 577 | sg_init_one(sg, &cpkt, sizeof(cpkt)); | 453 | sg_init_one(sg, &cpkt, sizeof(cpkt)); |
| 578 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt, GFP_ATOMIC) == 0) { | 454 | if (virtqueue_add_buf(vq, sg, 1, 0, &cpkt) >= 0) { |
| 579 | virtqueue_kick(vq); | 455 | virtqueue_kick(vq); |
| 580 | while (!virtqueue_get_buf(vq, &len)) | 456 | while (!virtqueue_get_buf(vq, &len)) |
| 581 | cpu_relax(); | 457 | cpu_relax(); |
| @@ -592,11 +468,10 @@ static ssize_t send_control_msg(struct port *port, unsigned int event, | |||
| 592 | return 0; | 468 | return 0; |
| 593 | } | 469 | } |
| 594 | 470 | ||
| 595 | |||
| 596 | /* Callers must take the port->outvq_lock */ | 471 | /* Callers must take the port->outvq_lock */ |
| 597 | static void reclaim_consumed_buffers(struct port *port) | 472 | static void reclaim_consumed_buffers(struct port *port) |
| 598 | { | 473 | { |
| 599 | struct port_buffer *buf; | 474 | void *buf; |
| 600 | unsigned int len; | 475 | unsigned int len; |
| 601 | 476 | ||
| 602 | if (!port->portdev) { | 477 | if (!port->portdev) { |
| @@ -604,17 +479,17 @@ static void reclaim_consumed_buffers(struct port *port) | |||
| 604 | return; | 479 | return; |
| 605 | } | 480 | } |
| 606 | while ((buf = virtqueue_get_buf(port->out_vq, &len))) { | 481 | while ((buf = virtqueue_get_buf(port->out_vq, &len))) { |
| 607 | free_buf(buf, false); | 482 | kfree(buf); |
| 608 | port->outvq_full = false; | 483 | port->outvq_full = false; |
| 609 | } | 484 | } |
| 610 | } | 485 | } |
| 611 | 486 | ||
| 612 | static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, | 487 | static ssize_t send_buf(struct port *port, void *in_buf, size_t in_count, |
| 613 | int nents, size_t in_count, | 488 | bool nonblock) |
| 614 | void *data, bool nonblock) | ||
| 615 | { | 489 | { |
| 490 | struct scatterlist sg[1]; | ||
| 616 | struct virtqueue *out_vq; | 491 | struct virtqueue *out_vq; |
| 617 | int err; | 492 | ssize_t ret; |
| 618 | unsigned long flags; | 493 | unsigned long flags; |
| 619 | unsigned int len; | 494 | unsigned int len; |
| 620 | 495 | ||
| @@ -624,17 +499,18 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, | |||
| 624 | 499 | ||
| 625 | reclaim_consumed_buffers(port); | 500 | reclaim_consumed_buffers(port); |
| 626 | 501 | ||
| 627 | err = virtqueue_add_buf(out_vq, sg, nents, 0, data, GFP_ATOMIC); | 502 | sg_init_one(sg, in_buf, in_count); |
| 503 | ret = virtqueue_add_buf(out_vq, sg, 1, 0, in_buf); | ||
| 628 | 504 | ||
| 629 | /* Tell Host to go! */ | 505 | /* Tell Host to go! */ |
| 630 | virtqueue_kick(out_vq); | 506 | virtqueue_kick(out_vq); |
| 631 | 507 | ||
| 632 | if (err) { | 508 | if (ret < 0) { |
| 633 | in_count = 0; | 509 | in_count = 0; |
| 634 | goto done; | 510 | goto done; |
| 635 | } | 511 | } |
| 636 | 512 | ||
| 637 | if (out_vq->num_free == 0) | 513 | if (ret == 0) |
| 638 | port->outvq_full = true; | 514 | port->outvq_full = true; |
| 639 | 515 | ||
| 640 | if (nonblock) | 516 | if (nonblock) |
| @@ -653,8 +529,6 @@ static ssize_t __send_to_port(struct port *port, struct scatterlist *sg, | |||
| 653 | cpu_relax(); | 529 | cpu_relax(); |
| 654 | done: | 530 | done: |
| 655 | spin_unlock_irqrestore(&port->outvq_lock, flags); | 531 | spin_unlock_irqrestore(&port->outvq_lock, flags); |
| 656 | |||
| 657 | port->stats.bytes_sent += in_count; | ||
| 658 | /* | 532 | /* |
| 659 | * We're expected to return the amount of data we wrote -- all | 533 | * We're expected to return the amount of data we wrote -- all |
| 660 | * of it | 534 | * of it |
| @@ -759,8 +633,8 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
| 759 | if (filp->f_flags & O_NONBLOCK) | 633 | if (filp->f_flags & O_NONBLOCK) |
| 760 | return -EAGAIN; | 634 | return -EAGAIN; |
| 761 | 635 | ||
| 762 | ret = wait_event_freezable(port->waitqueue, | 636 | ret = wait_event_interruptible(port->waitqueue, |
| 763 | !will_read_block(port)); | 637 | !will_read_block(port)); |
| 764 | if (ret < 0) | 638 | if (ret < 0) |
| 765 | return ret; | 639 | return ret; |
| 766 | } | 640 | } |
| @@ -783,34 +657,13 @@ static ssize_t port_fops_read(struct file *filp, char __user *ubuf, | |||
| 783 | return fill_readbuf(port, ubuf, count, true); | 657 | return fill_readbuf(port, ubuf, count, true); |
| 784 | } | 658 | } |
| 785 | 659 | ||
| 786 | static int wait_port_writable(struct port *port, bool nonblock) | ||
| 787 | { | ||
| 788 | int ret; | ||
| 789 | |||
| 790 | if (will_write_block(port)) { | ||
| 791 | if (nonblock) | ||
| 792 | return -EAGAIN; | ||
| 793 | |||
| 794 | ret = wait_event_freezable(port->waitqueue, | ||
| 795 | !will_write_block(port)); | ||
| 796 | if (ret < 0) | ||
| 797 | return ret; | ||
| 798 | } | ||
| 799 | /* Port got hot-unplugged. */ | ||
| 800 | if (!port->guest_connected) | ||
| 801 | return -ENODEV; | ||
| 802 | |||
| 803 | return 0; | ||
| 804 | } | ||
| 805 | |||
| 806 | static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | 660 | static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, |
| 807 | size_t count, loff_t *offp) | 661 | size_t count, loff_t *offp) |
| 808 | { | 662 | { |
| 809 | struct port *port; | 663 | struct port *port; |
| 810 | struct port_buffer *buf; | 664 | char *buf; |
| 811 | ssize_t ret; | 665 | ssize_t ret; |
| 812 | bool nonblock; | 666 | bool nonblock; |
| 813 | struct scatterlist sg[1]; | ||
| 814 | 667 | ||
| 815 | /* Userspace could be out to fool us */ | 668 | /* Userspace could be out to fool us */ |
| 816 | if (!count) | 669 | if (!count) |
| @@ -820,17 +673,26 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
| 820 | 673 | ||
| 821 | nonblock = filp->f_flags & O_NONBLOCK; | 674 | nonblock = filp->f_flags & O_NONBLOCK; |
| 822 | 675 | ||
| 823 | ret = wait_port_writable(port, nonblock); | 676 | if (will_write_block(port)) { |
| 824 | if (ret < 0) | 677 | if (nonblock) |
| 825 | return ret; | 678 | return -EAGAIN; |
| 679 | |||
| 680 | ret = wait_event_interruptible(port->waitqueue, | ||
| 681 | !will_write_block(port)); | ||
| 682 | if (ret < 0) | ||
| 683 | return ret; | ||
| 684 | } | ||
| 685 | /* Port got hot-unplugged. */ | ||
| 686 | if (!port->guest_connected) | ||
| 687 | return -ENODEV; | ||
| 826 | 688 | ||
| 827 | count = min((size_t)(32 * 1024), count); | 689 | count = min((size_t)(32 * 1024), count); |
| 828 | 690 | ||
| 829 | buf = alloc_buf(port->out_vq, count, 0); | 691 | buf = kmalloc(count, GFP_KERNEL); |
| 830 | if (!buf) | 692 | if (!buf) |
| 831 | return -ENOMEM; | 693 | return -ENOMEM; |
| 832 | 694 | ||
| 833 | ret = copy_from_user(buf->buf, ubuf, count); | 695 | ret = copy_from_user(buf, ubuf, count); |
| 834 | if (ret) { | 696 | if (ret) { |
| 835 | ret = -EFAULT; | 697 | ret = -EFAULT; |
| 836 | goto free_buf; | 698 | goto free_buf; |
| @@ -844,118 +706,17 @@ static ssize_t port_fops_write(struct file *filp, const char __user *ubuf, | |||
| 844 | * through to the host. | 706 | * through to the host. |
| 845 | */ | 707 | */ |
| 846 | nonblock = true; | 708 | nonblock = true; |
| 847 | sg_init_one(sg, buf->buf, count); | 709 | ret = send_buf(port, buf, count, nonblock); |
| 848 | ret = __send_to_port(port, sg, 1, count, buf, nonblock); | ||
| 849 | 710 | ||
| 850 | if (nonblock && ret > 0) | 711 | if (nonblock && ret > 0) |
| 851 | goto out; | 712 | goto out; |
| 852 | 713 | ||
| 853 | free_buf: | 714 | free_buf: |
| 854 | free_buf(buf, true); | 715 | kfree(buf); |
| 855 | out: | 716 | out: |
| 856 | return ret; | 717 | return ret; |
| 857 | } | 718 | } |
| 858 | 719 | ||
| 859 | struct sg_list { | ||
| 860 | unsigned int n; | ||
| 861 | unsigned int size; | ||
| 862 | size_t len; | ||
| 863 | struct scatterlist *sg; | ||
| 864 | }; | ||
| 865 | |||
| 866 | static int pipe_to_sg(struct pipe_inode_info *pipe, struct pipe_buffer *buf, | ||
| 867 | struct splice_desc *sd) | ||
| 868 | { | ||
| 869 | struct sg_list *sgl = sd->u.data; | ||
| 870 | unsigned int offset, len; | ||
| 871 | |||
| 872 | if (sgl->n == sgl->size) | ||
| 873 | return 0; | ||
| 874 | |||
| 875 | /* Try lock this page */ | ||
| 876 | if (buf->ops->steal(pipe, buf) == 0) { | ||
| 877 | /* Get reference and unlock page for moving */ | ||
| 878 | get_page(buf->page); | ||
| 879 | unlock_page(buf->page); | ||
| 880 | |||
| 881 | len = min(buf->len, sd->len); | ||
| 882 | sg_set_page(&(sgl->sg[sgl->n]), buf->page, len, buf->offset); | ||
| 883 | } else { | ||
| 884 | /* Failback to copying a page */ | ||
| 885 | struct page *page = alloc_page(GFP_KERNEL); | ||
| 886 | char *src = buf->ops->map(pipe, buf, 1); | ||
| 887 | char *dst; | ||
| 888 | |||
| 889 | if (!page) | ||
| 890 | return -ENOMEM; | ||
| 891 | dst = kmap(page); | ||
| 892 | |||
| 893 | offset = sd->pos & ~PAGE_MASK; | ||
| 894 | |||
| 895 | len = sd->len; | ||
| 896 | if (len + offset > PAGE_SIZE) | ||
| 897 | len = PAGE_SIZE - offset; | ||
| 898 | |||
| 899 | memcpy(dst + offset, src + buf->offset, len); | ||
| 900 | |||
| 901 | kunmap(page); | ||
| 902 | buf->ops->unmap(pipe, buf, src); | ||
| 903 | |||
| 904 | sg_set_page(&(sgl->sg[sgl->n]), page, len, offset); | ||
| 905 | } | ||
| 906 | sgl->n++; | ||
| 907 | sgl->len += len; | ||
| 908 | |||
| 909 | return len; | ||
| 910 | } | ||
| 911 | |||
| 912 | /* Faster zero-copy write by splicing */ | ||
| 913 | static ssize_t port_fops_splice_write(struct pipe_inode_info *pipe, | ||
| 914 | struct file *filp, loff_t *ppos, | ||
| 915 | size_t len, unsigned int flags) | ||
| 916 | { | ||
| 917 | struct port *port = filp->private_data; | ||
| 918 | struct sg_list sgl; | ||
| 919 | ssize_t ret; | ||
| 920 | struct port_buffer *buf; | ||
| 921 | struct splice_desc sd = { | ||
| 922 | .total_len = len, | ||
| 923 | .flags = flags, | ||
| 924 | .pos = *ppos, | ||
| 925 | .u.data = &sgl, | ||
| 926 | }; | ||
| 927 | |||
| 928 | /* | ||
| 929 | * Rproc_serial does not yet support splice. To support splice | ||
| 930 | * pipe_to_sg() must allocate dma-buffers and copy content from | ||
| 931 | * regular pages to dma pages. And alloc_buf and free_buf must | ||
| 932 | * support allocating and freeing such a list of dma-buffers. | ||
| 933 | */ | ||
| 934 | if (is_rproc_serial(port->out_vq->vdev)) | ||
| 935 | return -EINVAL; | ||
| 936 | |||
| 937 | ret = wait_port_writable(port, filp->f_flags & O_NONBLOCK); | ||
| 938 | if (ret < 0) | ||
| 939 | return ret; | ||
| 940 | |||
| 941 | buf = alloc_buf(port->out_vq, 0, pipe->nrbufs); | ||
| 942 | if (!buf) | ||
| 943 | return -ENOMEM; | ||
| 944 | |||
| 945 | sgl.n = 0; | ||
| 946 | sgl.len = 0; | ||
| 947 | sgl.size = pipe->nrbufs; | ||
| 948 | sgl.sg = buf->sg; | ||
| 949 | sg_init_table(sgl.sg, sgl.size); | ||
| 950 | ret = __splice_from_pipe(pipe, &sd, pipe_to_sg); | ||
| 951 | if (likely(ret > 0)) | ||
| 952 | ret = __send_to_port(port, buf->sg, sgl.n, sgl.len, buf, true); | ||
| 953 | |||
| 954 | if (unlikely(ret <= 0)) | ||
| 955 | free_buf(buf, true); | ||
| 956 | return ret; | ||
| 957 | } | ||
| 958 | |||
| 959 | static unsigned int port_fops_poll(struct file *filp, poll_table *wait) | 720 | static unsigned int port_fops_poll(struct file *filp, poll_table *wait) |
| 960 | { | 721 | { |
| 961 | struct port *port; | 722 | struct port *port; |
| @@ -1001,7 +762,6 @@ static int port_fops_release(struct inode *inode, struct file *filp) | |||
| 1001 | reclaim_consumed_buffers(port); | 762 | reclaim_consumed_buffers(port); |
| 1002 | spin_unlock_irq(&port->outvq_lock); | 763 | spin_unlock_irq(&port->outvq_lock); |
| 1003 | 764 | ||
| 1004 | reclaim_dma_bufs(); | ||
| 1005 | /* | 765 | /* |
| 1006 | * Locks aren't necessary here as a port can't be opened after | 766 | * Locks aren't necessary here as a port can't be opened after |
| 1007 | * unplug, and if a port isn't unplugged, a kref would already | 767 | * unplug, and if a port isn't unplugged, a kref would already |
| @@ -1088,7 +848,6 @@ static const struct file_operations port_fops = { | |||
| 1088 | .open = port_fops_open, | 848 | .open = port_fops_open, |
| 1089 | .read = port_fops_read, | 849 | .read = port_fops_read, |
| 1090 | .write = port_fops_write, | 850 | .write = port_fops_write, |
| 1091 | .splice_write = port_fops_splice_write, | ||
| 1092 | .poll = port_fops_poll, | 851 | .poll = port_fops_poll, |
| 1093 | .release = port_fops_release, | 852 | .release = port_fops_release, |
| 1094 | .fasync = port_fops_fasync, | 853 | .fasync = port_fops_fasync, |
| @@ -1106,7 +865,6 @@ static const struct file_operations port_fops = { | |||
| 1106 | static int put_chars(u32 vtermno, const char *buf, int count) | 865 | static int put_chars(u32 vtermno, const char *buf, int count) |
| 1107 | { | 866 | { |
| 1108 | struct port *port; | 867 | struct port *port; |
| 1109 | struct scatterlist sg[1]; | ||
| 1110 | 868 | ||
| 1111 | if (unlikely(early_put_chars)) | 869 | if (unlikely(early_put_chars)) |
| 1112 | return early_put_chars(vtermno, buf, count); | 870 | return early_put_chars(vtermno, buf, count); |
| @@ -1115,8 +873,7 @@ static int put_chars(u32 vtermno, const char *buf, int count) | |||
| 1115 | if (!port) | 873 | if (!port) |
| 1116 | return -EPIPE; | 874 | return -EPIPE; |
| 1117 | 875 | ||
| 1118 | sg_init_one(sg, buf, count); | 876 | return send_buf(port, (void *)buf, count, false); |
| 1119 | return __send_to_port(port, sg, 1, count, (void *)buf, false); | ||
| 1120 | } | 877 | } |
| 1121 | 878 | ||
| 1122 | /* | 879 | /* |
| @@ -1153,10 +910,7 @@ static void resize_console(struct port *port) | |||
| 1153 | return; | 910 | return; |
| 1154 | 911 | ||
| 1155 | vdev = port->portdev->vdev; | 912 | vdev = port->portdev->vdev; |
| 1156 | 913 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) | |
| 1157 | /* Don't test F_SIZE at all if we're rproc: not a valid feature! */ | ||
| 1158 | if (!is_rproc_serial(vdev) && | ||
| 1159 | virtio_has_feature(vdev, VIRTIO_CONSOLE_F_SIZE)) | ||
| 1160 | hvc_resize(port->cons.hvc, port->cons.ws); | 914 | hvc_resize(port->cons.hvc, port->cons.ws); |
| 1161 | } | 915 | } |
| 1162 | 916 | ||
| @@ -1276,6 +1030,12 @@ static struct attribute_group port_attribute_group = { | |||
| 1276 | .attrs = port_sysfs_entries, | 1030 | .attrs = port_sysfs_entries, |
| 1277 | }; | 1031 | }; |
| 1278 | 1032 | ||
| 1033 | static int debugfs_open(struct inode *inode, struct file *filp) | ||
| 1034 | { | ||
| 1035 | filp->private_data = inode->i_private; | ||
| 1036 | return 0; | ||
| 1037 | } | ||
| 1038 | |||
| 1279 | static ssize_t debugfs_read(struct file *filp, char __user *ubuf, | 1039 | static ssize_t debugfs_read(struct file *filp, char __user *ubuf, |
| 1280 | size_t count, loff_t *offp) | 1040 | size_t count, loff_t *offp) |
| 1281 | { | 1041 | { |
| @@ -1299,14 +1059,6 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, | |||
| 1299 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | 1059 | out_offset += snprintf(buf + out_offset, out_count - out_offset, |
| 1300 | "outvq_full: %d\n", port->outvq_full); | 1060 | "outvq_full: %d\n", port->outvq_full); |
| 1301 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | 1061 | out_offset += snprintf(buf + out_offset, out_count - out_offset, |
| 1302 | "bytes_sent: %lu\n", port->stats.bytes_sent); | ||
| 1303 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
| 1304 | "bytes_received: %lu\n", | ||
| 1305 | port->stats.bytes_received); | ||
| 1306 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
| 1307 | "bytes_discarded: %lu\n", | ||
| 1308 | port->stats.bytes_discarded); | ||
| 1309 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | ||
| 1310 | "is_console: %s\n", | 1062 | "is_console: %s\n", |
| 1311 | is_console_port(port) ? "yes" : "no"); | 1063 | is_console_port(port) ? "yes" : "no"); |
| 1312 | out_offset += snprintf(buf + out_offset, out_count - out_offset, | 1064 | out_offset += snprintf(buf + out_offset, out_count - out_offset, |
| @@ -1319,7 +1071,7 @@ static ssize_t debugfs_read(struct file *filp, char __user *ubuf, | |||
| 1319 | 1071 | ||
| 1320 | static const struct file_operations port_debugfs_ops = { | 1072 | static const struct file_operations port_debugfs_ops = { |
| 1321 | .owner = THIS_MODULE, | 1073 | .owner = THIS_MODULE, |
| 1322 | .open = simple_open, | 1074 | .open = debugfs_open, |
| 1323 | .read = debugfs_read, | 1075 | .read = debugfs_read, |
| 1324 | }; | 1076 | }; |
| 1325 | 1077 | ||
| @@ -1340,7 +1092,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
| 1340 | 1092 | ||
| 1341 | nr_added_bufs = 0; | 1093 | nr_added_bufs = 0; |
| 1342 | do { | 1094 | do { |
| 1343 | buf = alloc_buf(vq, PAGE_SIZE, 0); | 1095 | buf = alloc_buf(PAGE_SIZE); |
| 1344 | if (!buf) | 1096 | if (!buf) |
| 1345 | break; | 1097 | break; |
| 1346 | 1098 | ||
| @@ -1348,7 +1100,7 @@ static unsigned int fill_queue(struct virtqueue *vq, spinlock_t *lock) | |||
| 1348 | ret = add_inbuf(vq, buf); | 1100 | ret = add_inbuf(vq, buf); |
| 1349 | if (ret < 0) { | 1101 | if (ret < 0) { |
| 1350 | spin_unlock_irq(lock); | 1102 | spin_unlock_irq(lock); |
| 1351 | free_buf(buf, true); | 1103 | free_buf(buf); |
| 1352 | break; | 1104 | break; |
| 1353 | } | 1105 | } |
| 1354 | nr_added_bufs++; | 1106 | nr_added_bufs++; |
| @@ -1391,7 +1143,6 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
| 1391 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; | 1143 | port->cons.ws.ws_row = port->cons.ws.ws_col = 0; |
| 1392 | 1144 | ||
| 1393 | port->host_connected = port->guest_connected = false; | 1145 | port->host_connected = port->guest_connected = false; |
| 1394 | port->stats = (struct port_stats) { 0 }; | ||
| 1395 | 1146 | ||
| 1396 | port->outvq_full = false; | 1147 | port->outvq_full = false; |
| 1397 | 1148 | ||
| @@ -1436,18 +1187,10 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
| 1436 | goto free_device; | 1187 | goto free_device; |
| 1437 | } | 1188 | } |
| 1438 | 1189 | ||
| 1439 | if (is_rproc_serial(port->portdev->vdev)) | 1190 | /* |
| 1440 | /* | 1191 | * If we're not using multiport support, this has to be a console port |
| 1441 | * For rproc_serial assume remote processor is connected. | 1192 | */ |
| 1442 | * rproc_serial does not want the console port, only | 1193 | if (!use_multiport(port->portdev)) { |
| 1443 | * the generic port implementation. | ||
| 1444 | */ | ||
| 1445 | port->host_connected = true; | ||
| 1446 | else if (!use_multiport(port->portdev)) { | ||
| 1447 | /* | ||
| 1448 | * If we're not using multiport support, | ||
| 1449 | * this has to be a console port. | ||
| 1450 | */ | ||
| 1451 | err = init_port_console(port); | 1194 | err = init_port_console(port); |
| 1452 | if (err) | 1195 | if (err) |
| 1453 | goto free_inbufs; | 1196 | goto free_inbufs; |
| @@ -1480,7 +1223,7 @@ static int add_port(struct ports_device *portdev, u32 id) | |||
| 1480 | 1223 | ||
| 1481 | free_inbufs: | 1224 | free_inbufs: |
| 1482 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | 1225 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) |
| 1483 | free_buf(buf, true); | 1226 | free_buf(buf); |
| 1484 | free_device: | 1227 | free_device: |
| 1485 | device_destroy(pdrvdata.class, port->dev->devt); | 1228 | device_destroy(pdrvdata.class, port->dev->devt); |
| 1486 | free_cdev: | 1229 | free_cdev: |
| @@ -1511,24 +1254,6 @@ static void remove_port(struct kref *kref) | |||
| 1511 | kfree(port); | 1254 | kfree(port); |
| 1512 | } | 1255 | } |
| 1513 | 1256 | ||
| 1514 | static void remove_port_data(struct port *port) | ||
| 1515 | { | ||
| 1516 | struct port_buffer *buf; | ||
| 1517 | |||
| 1518 | /* Remove unused data this port might have received. */ | ||
| 1519 | discard_port_data(port); | ||
| 1520 | |||
| 1521 | reclaim_consumed_buffers(port); | ||
| 1522 | |||
| 1523 | /* Remove buffers we queued up for the Host to send us data in. */ | ||
| 1524 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
| 1525 | free_buf(buf, true); | ||
| 1526 | |||
| 1527 | /* Free pending buffers from the out-queue. */ | ||
| 1528 | while ((buf = virtqueue_detach_unused_buf(port->out_vq))) | ||
| 1529 | free_buf(buf, true); | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | /* | 1257 | /* |
| 1533 | * Port got unplugged. Remove port from portdev's list and drop the | 1258 | * Port got unplugged. Remove port from portdev's list and drop the |
| 1534 | * kref reference. If no userspace has this port opened, it will | 1259 | * kref reference. If no userspace has this port opened, it will |
| @@ -1536,6 +1261,8 @@ static void remove_port_data(struct port *port) | |||
| 1536 | */ | 1261 | */ |
| 1537 | static void unplug_port(struct port *port) | 1262 | static void unplug_port(struct port *port) |
| 1538 | { | 1263 | { |
| 1264 | struct port_buffer *buf; | ||
| 1265 | |||
| 1539 | spin_lock_irq(&port->portdev->ports_lock); | 1266 | spin_lock_irq(&port->portdev->ports_lock); |
| 1540 | list_del(&port->list); | 1267 | list_del(&port->list); |
| 1541 | spin_unlock_irq(&port->portdev->ports_lock); | 1268 | spin_unlock_irq(&port->portdev->ports_lock); |
| @@ -1556,7 +1283,14 @@ static void unplug_port(struct port *port) | |||
| 1556 | hvc_remove(port->cons.hvc); | 1283 | hvc_remove(port->cons.hvc); |
| 1557 | } | 1284 | } |
| 1558 | 1285 | ||
| 1559 | remove_port_data(port); | 1286 | /* Remove unused data this port might have received. */ |
| 1287 | discard_port_data(port); | ||
| 1288 | |||
| 1289 | reclaim_consumed_buffers(port); | ||
| 1290 | |||
| 1291 | /* Remove buffers we queued up for the Host to send us data in. */ | ||
| 1292 | while ((buf = virtqueue_detach_unused_buf(port->in_vq))) | ||
| 1293 | free_buf(buf); | ||
| 1560 | 1294 | ||
| 1561 | /* | 1295 | /* |
| 1562 | * We should just assume the device itself has gone off -- | 1296 | * We should just assume the device itself has gone off -- |
| @@ -1618,7 +1352,6 @@ static void handle_control_message(struct ports_device *portdev, | |||
| 1618 | break; | 1352 | break; |
| 1619 | 1353 | ||
| 1620 | init_port_console(port); | 1354 | init_port_console(port); |
| 1621 | complete(&early_console_added); | ||
| 1622 | /* | 1355 | /* |
| 1623 | * Could remove the port here in case init fails - but | 1356 | * Could remove the port here in case init fails - but |
| 1624 | * have to notify the host first. | 1357 | * have to notify the host first. |
| @@ -1661,13 +1394,6 @@ static void handle_control_message(struct ports_device *portdev, | |||
| 1661 | break; | 1394 | break; |
| 1662 | case VIRTIO_CONSOLE_PORT_NAME: | 1395 | case VIRTIO_CONSOLE_PORT_NAME: |
| 1663 | /* | 1396 | /* |
| 1664 | * If we woke up after hibernation, we can get this | ||
| 1665 | * again. Skip it in that case. | ||
| 1666 | */ | ||
| 1667 | if (port->name) | ||
| 1668 | break; | ||
| 1669 | |||
| 1670 | /* | ||
| 1671 | * Skip the size of the header and the cpkt to get the size | 1397 | * Skip the size of the header and the cpkt to get the size |
| 1672 | * of the name that was sent | 1398 | * of the name that was sent |
| 1673 | */ | 1399 | */ |
| @@ -1728,7 +1454,7 @@ static void control_work_handler(struct work_struct *work) | |||
| 1728 | if (add_inbuf(portdev->c_ivq, buf) < 0) { | 1454 | if (add_inbuf(portdev->c_ivq, buf) < 0) { |
| 1729 | dev_warn(&portdev->vdev->dev, | 1455 | dev_warn(&portdev->vdev->dev, |
| 1730 | "Error adding buffer to queue\n"); | 1456 | "Error adding buffer to queue\n"); |
| 1731 | free_buf(buf, false); | 1457 | free_buf(buf); |
| 1732 | } | 1458 | } |
| 1733 | } | 1459 | } |
| 1734 | spin_unlock(&portdev->cvq_lock); | 1460 | spin_unlock(&portdev->cvq_lock); |
| @@ -1755,7 +1481,8 @@ static void in_intr(struct virtqueue *vq) | |||
| 1755 | return; | 1481 | return; |
| 1756 | 1482 | ||
| 1757 | spin_lock_irqsave(&port->inbuf_lock, flags); | 1483 | spin_lock_irqsave(&port->inbuf_lock, flags); |
| 1758 | port->inbuf = get_inbuf(port); | 1484 | if (!port->inbuf) |
| 1485 | port->inbuf = get_inbuf(port); | ||
| 1759 | 1486 | ||
| 1760 | /* | 1487 | /* |
| 1761 | * Don't queue up data when port is closed. This condition | 1488 | * Don't queue up data when port is closed. This condition |
| @@ -1836,7 +1563,7 @@ static int init_vqs(struct ports_device *portdev) | |||
| 1836 | portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), | 1563 | portdev->out_vqs = kmalloc(nr_ports * sizeof(struct virtqueue *), |
| 1837 | GFP_KERNEL); | 1564 | GFP_KERNEL); |
| 1838 | if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs || | 1565 | if (!vqs || !io_callbacks || !io_names || !portdev->in_vqs || |
| 1839 | !portdev->out_vqs) { | 1566 | !portdev->out_vqs) { |
| 1840 | err = -ENOMEM; | 1567 | err = -ENOMEM; |
| 1841 | goto free; | 1568 | goto free; |
| 1842 | } | 1569 | } |
| @@ -1908,28 +1635,6 @@ static const struct file_operations portdev_fops = { | |||
| 1908 | .owner = THIS_MODULE, | 1635 | .owner = THIS_MODULE, |
| 1909 | }; | 1636 | }; |
| 1910 | 1637 | ||
| 1911 | static void remove_vqs(struct ports_device *portdev) | ||
| 1912 | { | ||
| 1913 | portdev->vdev->config->del_vqs(portdev->vdev); | ||
| 1914 | kfree(portdev->in_vqs); | ||
| 1915 | kfree(portdev->out_vqs); | ||
| 1916 | } | ||
| 1917 | |||
| 1918 | static void remove_controlq_data(struct ports_device *portdev) | ||
| 1919 | { | ||
| 1920 | struct port_buffer *buf; | ||
| 1921 | unsigned int len; | ||
| 1922 | |||
| 1923 | if (!use_multiport(portdev)) | ||
| 1924 | return; | ||
| 1925 | |||
| 1926 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | ||
| 1927 | free_buf(buf, true); | ||
| 1928 | |||
| 1929 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | ||
| 1930 | free_buf(buf, true); | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | /* | 1638 | /* |
| 1934 | * Once we're further in boot, we get probed like any other virtio | 1639 | * Once we're further in boot, we get probed like any other virtio |
| 1935 | * device. | 1640 | * device. |
| @@ -1938,15 +1643,11 @@ static void remove_controlq_data(struct ports_device *portdev) | |||
| 1938 | * config space to see how many ports the host has spawned. We | 1643 | * config space to see how many ports the host has spawned. We |
| 1939 | * initialize each port found. | 1644 | * initialize each port found. |
| 1940 | */ | 1645 | */ |
| 1941 | static int virtcons_probe(struct virtio_device *vdev) | 1646 | static int __devinit virtcons_probe(struct virtio_device *vdev) |
| 1942 | { | 1647 | { |
| 1943 | struct ports_device *portdev; | 1648 | struct ports_device *portdev; |
| 1944 | int err; | 1649 | int err; |
| 1945 | bool multiport; | 1650 | bool multiport; |
| 1946 | bool early = early_put_chars != NULL; | ||
| 1947 | |||
| 1948 | /* Ensure to read early_put_chars now */ | ||
| 1949 | barrier(); | ||
| 1950 | 1651 | ||
| 1951 | portdev = kmalloc(sizeof(*portdev), GFP_KERNEL); | 1652 | portdev = kmalloc(sizeof(*portdev), GFP_KERNEL); |
| 1952 | if (!portdev) { | 1653 | if (!portdev) { |
| @@ -1974,14 +1675,12 @@ static int virtcons_probe(struct virtio_device *vdev) | |||
| 1974 | 1675 | ||
| 1975 | multiport = false; | 1676 | multiport = false; |
| 1976 | portdev->config.max_nr_ports = 1; | 1677 | portdev->config.max_nr_ports = 1; |
| 1977 | 1678 | if (virtio_has_feature(vdev, VIRTIO_CONSOLE_F_MULTIPORT)) { | |
| 1978 | /* Don't test MULTIPORT at all if we're rproc: not a valid feature! */ | ||
| 1979 | if (!is_rproc_serial(vdev) && | ||
| 1980 | virtio_config_val(vdev, VIRTIO_CONSOLE_F_MULTIPORT, | ||
| 1981 | offsetof(struct virtio_console_config, | ||
| 1982 | max_nr_ports), | ||
| 1983 | &portdev->config.max_nr_ports) == 0) { | ||
| 1984 | multiport = true; | 1679 | multiport = true; |
| 1680 | vdev->config->get(vdev, offsetof(struct virtio_console_config, | ||
| 1681 | max_nr_ports), | ||
| 1682 | &portdev->config.max_nr_ports, | ||
| 1683 | sizeof(portdev->config.max_nr_ports)); | ||
| 1985 | } | 1684 | } |
| 1986 | 1685 | ||
| 1987 | err = init_vqs(portdev); | 1686 | err = init_vqs(portdev); |
| @@ -2020,26 +1719,15 @@ static int virtcons_probe(struct virtio_device *vdev) | |||
| 2020 | 1719 | ||
| 2021 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | 1720 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
| 2022 | VIRTIO_CONSOLE_DEVICE_READY, 1); | 1721 | VIRTIO_CONSOLE_DEVICE_READY, 1); |
| 2023 | |||
| 2024 | /* | ||
| 2025 | * If there was an early virtio console, assume that there are no | ||
| 2026 | * other consoles. We need to wait until the hvc_alloc matches the | ||
| 2027 | * hvc_instantiate, otherwise tty_open will complain, resulting in | ||
| 2028 | * a "Warning: unable to open an initial console" boot failure. | ||
| 2029 | * Without multiport this is done in add_port above. With multiport | ||
| 2030 | * this might take some host<->guest communication - thus we have to | ||
| 2031 | * wait. | ||
| 2032 | */ | ||
| 2033 | if (multiport && early) | ||
| 2034 | wait_for_completion(&early_console_added); | ||
| 2035 | |||
| 2036 | return 0; | 1722 | return 0; |
| 2037 | 1723 | ||
| 2038 | free_vqs: | 1724 | free_vqs: |
| 2039 | /* The host might want to notify mgmt sw about device add failure */ | 1725 | /* The host might want to notify mgmt sw about device add failure */ |
| 2040 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, | 1726 | __send_control_msg(portdev, VIRTIO_CONSOLE_BAD_ID, |
| 2041 | VIRTIO_CONSOLE_DEVICE_READY, 0); | 1727 | VIRTIO_CONSOLE_DEVICE_READY, 0); |
| 2042 | remove_vqs(portdev); | 1728 | vdev->config->del_vqs(vdev); |
| 1729 | kfree(portdev->in_vqs); | ||
| 1730 | kfree(portdev->out_vqs); | ||
| 2043 | free_chrdev: | 1731 | free_chrdev: |
| 2044 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); | 1732 | unregister_chrdev(portdev->chr_major, "virtio-portsdev"); |
| 2045 | free: | 1733 | free: |
| @@ -2077,8 +1765,21 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
| 2077 | * have to just stop using the port, as the vqs are going | 1765 | * have to just stop using the port, as the vqs are going |
| 2078 | * away. | 1766 | * away. |
| 2079 | */ | 1767 | */ |
| 2080 | remove_controlq_data(portdev); | 1768 | if (use_multiport(portdev)) { |
| 2081 | remove_vqs(portdev); | 1769 | struct port_buffer *buf; |
| 1770 | unsigned int len; | ||
| 1771 | |||
| 1772 | while ((buf = virtqueue_get_buf(portdev->c_ivq, &len))) | ||
| 1773 | free_buf(buf); | ||
| 1774 | |||
| 1775 | while ((buf = virtqueue_detach_unused_buf(portdev->c_ivq))) | ||
| 1776 | free_buf(buf); | ||
| 1777 | } | ||
| 1778 | |||
| 1779 | vdev->config->del_vqs(vdev); | ||
| 1780 | kfree(portdev->in_vqs); | ||
| 1781 | kfree(portdev->out_vqs); | ||
| 1782 | |||
| 2082 | kfree(portdev); | 1783 | kfree(portdev); |
| 2083 | } | 1784 | } |
| 2084 | 1785 | ||
| @@ -2092,85 +1793,6 @@ static unsigned int features[] = { | |||
| 2092 | VIRTIO_CONSOLE_F_MULTIPORT, | 1793 | VIRTIO_CONSOLE_F_MULTIPORT, |
| 2093 | }; | 1794 | }; |
| 2094 | 1795 | ||
| 2095 | static struct virtio_device_id rproc_serial_id_table[] = { | ||
| 2096 | #if IS_ENABLED(CONFIG_REMOTEPROC) | ||
| 2097 | { VIRTIO_ID_RPROC_SERIAL, VIRTIO_DEV_ANY_ID }, | ||
| 2098 | #endif | ||
| 2099 | { 0 }, | ||
| 2100 | }; | ||
| 2101 | |||
| 2102 | static unsigned int rproc_serial_features[] = { | ||
| 2103 | }; | ||
| 2104 | |||
| 2105 | #ifdef CONFIG_PM | ||
| 2106 | static int virtcons_freeze(struct virtio_device *vdev) | ||
| 2107 | { | ||
| 2108 | struct ports_device *portdev; | ||
| 2109 | struct port *port; | ||
| 2110 | |||
| 2111 | portdev = vdev->priv; | ||
| 2112 | |||
| 2113 | vdev->config->reset(vdev); | ||
| 2114 | |||
| 2115 | virtqueue_disable_cb(portdev->c_ivq); | ||
| 2116 | cancel_work_sync(&portdev->control_work); | ||
| 2117 | /* | ||
| 2118 | * Once more: if control_work_handler() was running, it would | ||
| 2119 | * enable the cb as the last step. | ||
| 2120 | */ | ||
| 2121 | virtqueue_disable_cb(portdev->c_ivq); | ||
| 2122 | remove_controlq_data(portdev); | ||
| 2123 | |||
| 2124 | list_for_each_entry(port, &portdev->ports, list) { | ||
| 2125 | virtqueue_disable_cb(port->in_vq); | ||
| 2126 | virtqueue_disable_cb(port->out_vq); | ||
| 2127 | /* | ||
| 2128 | * We'll ask the host later if the new invocation has | ||
| 2129 | * the port opened or closed. | ||
| 2130 | */ | ||
| 2131 | port->host_connected = false; | ||
| 2132 | remove_port_data(port); | ||
| 2133 | } | ||
| 2134 | remove_vqs(portdev); | ||
| 2135 | |||
| 2136 | return 0; | ||
| 2137 | } | ||
| 2138 | |||
| 2139 | static int virtcons_restore(struct virtio_device *vdev) | ||
| 2140 | { | ||
| 2141 | struct ports_device *portdev; | ||
| 2142 | struct port *port; | ||
| 2143 | int ret; | ||
| 2144 | |||
| 2145 | portdev = vdev->priv; | ||
| 2146 | |||
| 2147 | ret = init_vqs(portdev); | ||
| 2148 | if (ret) | ||
| 2149 | return ret; | ||
| 2150 | |||
| 2151 | if (use_multiport(portdev)) | ||
| 2152 | fill_queue(portdev->c_ivq, &portdev->cvq_lock); | ||
| 2153 | |||
| 2154 | list_for_each_entry(port, &portdev->ports, list) { | ||
| 2155 | port->in_vq = portdev->in_vqs[port->id]; | ||
| 2156 | port->out_vq = portdev->out_vqs[port->id]; | ||
| 2157 | |||
| 2158 | fill_queue(port->in_vq, &port->inbuf_lock); | ||
| 2159 | |||
| 2160 | /* Get port open/close status on the host */ | ||
| 2161 | send_control_msg(port, VIRTIO_CONSOLE_PORT_READY, 1); | ||
| 2162 | |||
| 2163 | /* | ||
| 2164 | * If a port was open at the time of suspending, we | ||
| 2165 | * have to let the host know that it's still open. | ||
| 2166 | */ | ||
| 2167 | if (port->guest_connected) | ||
| 2168 | send_control_msg(port, VIRTIO_CONSOLE_PORT_OPEN, 1); | ||
| 2169 | } | ||
| 2170 | return 0; | ||
| 2171 | } | ||
| 2172 | #endif | ||
| 2173 | |||
| 2174 | static struct virtio_driver virtio_console = { | 1796 | static struct virtio_driver virtio_console = { |
| 2175 | .feature_table = features, | 1797 | .feature_table = features, |
| 2176 | .feature_table_size = ARRAY_SIZE(features), | 1798 | .feature_table_size = ARRAY_SIZE(features), |
| @@ -2180,20 +1802,6 @@ static struct virtio_driver virtio_console = { | |||
| 2180 | .probe = virtcons_probe, | 1802 | .probe = virtcons_probe, |
| 2181 | .remove = virtcons_remove, | 1803 | .remove = virtcons_remove, |
| 2182 | .config_changed = config_intr, | 1804 | .config_changed = config_intr, |
| 2183 | #ifdef CONFIG_PM | ||
| 2184 | .freeze = virtcons_freeze, | ||
| 2185 | .restore = virtcons_restore, | ||
| 2186 | #endif | ||
| 2187 | }; | ||
| 2188 | |||
| 2189 | static struct virtio_driver virtio_rproc_serial = { | ||
| 2190 | .feature_table = rproc_serial_features, | ||
| 2191 | .feature_table_size = ARRAY_SIZE(rproc_serial_features), | ||
| 2192 | .driver.name = "virtio_rproc_serial", | ||
| 2193 | .driver.owner = THIS_MODULE, | ||
| 2194 | .id_table = rproc_serial_id_table, | ||
| 2195 | .probe = virtcons_probe, | ||
| 2196 | .remove = virtcons_remove, | ||
| 2197 | }; | 1805 | }; |
| 2198 | 1806 | ||
| 2199 | static int __init init(void) | 1807 | static int __init init(void) |
| @@ -2215,33 +1823,12 @@ static int __init init(void) | |||
| 2215 | INIT_LIST_HEAD(&pdrvdata.consoles); | 1823 | INIT_LIST_HEAD(&pdrvdata.consoles); |
| 2216 | INIT_LIST_HEAD(&pdrvdata.portdevs); | 1824 | INIT_LIST_HEAD(&pdrvdata.portdevs); |
| 2217 | 1825 | ||
| 2218 | err = register_virtio_driver(&virtio_console); | 1826 | return register_virtio_driver(&virtio_console); |
| 2219 | if (err < 0) { | ||
| 2220 | pr_err("Error %d registering virtio driver\n", err); | ||
| 2221 | goto free; | ||
| 2222 | } | ||
| 2223 | err = register_virtio_driver(&virtio_rproc_serial); | ||
| 2224 | if (err < 0) { | ||
| 2225 | pr_err("Error %d registering virtio rproc serial driver\n", | ||
| 2226 | err); | ||
| 2227 | goto unregister; | ||
| 2228 | } | ||
| 2229 | return 0; | ||
| 2230 | unregister: | ||
| 2231 | unregister_virtio_driver(&virtio_console); | ||
| 2232 | free: | ||
| 2233 | if (pdrvdata.debugfs_dir) | ||
| 2234 | debugfs_remove_recursive(pdrvdata.debugfs_dir); | ||
| 2235 | class_destroy(pdrvdata.class); | ||
| 2236 | return err; | ||
| 2237 | } | 1827 | } |
| 2238 | 1828 | ||
| 2239 | static void __exit fini(void) | 1829 | static void __exit fini(void) |
| 2240 | { | 1830 | { |
| 2241 | reclaim_dma_bufs(); | ||
| 2242 | |||
| 2243 | unregister_virtio_driver(&virtio_console); | 1831 | unregister_virtio_driver(&virtio_console); |
| 2244 | unregister_virtio_driver(&virtio_rproc_serial); | ||
| 2245 | 1832 | ||
| 2246 | class_destroy(pdrvdata.class); | 1833 | class_destroy(pdrvdata.class); |
| 2247 | if (pdrvdata.debugfs_dir) | 1834 | if (pdrvdata.debugfs_dir) |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c index 5224da5202d..e90e1c74fd4 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c | |||
| @@ -89,6 +89,7 @@ | |||
| 89 | 89 | ||
| 90 | #include <asm/io.h> | 90 | #include <asm/io.h> |
| 91 | #include <asm/uaccess.h> | 91 | #include <asm/uaccess.h> |
| 92 | #include <asm/system.h> | ||
| 92 | 93 | ||
| 93 | #ifdef CONFIG_OF | 94 | #ifdef CONFIG_OF |
| 94 | /* For open firmware. */ | 95 | /* For open firmware. */ |
| @@ -167,7 +168,6 @@ static const struct config_registers v4_config_registers = { | |||
| 167 | .BOOTSTS = UNIMPLEMENTED, | 168 | .BOOTSTS = UNIMPLEMENTED, |
| 168 | .CTL_1 = UNIMPLEMENTED, | 169 | .CTL_1 = UNIMPLEMENTED, |
| 169 | }; | 170 | }; |
| 170 | |||
| 171 | static const struct config_registers v5_config_registers = { | 171 | static const struct config_registers v5_config_registers = { |
| 172 | .CRC = 0, | 172 | .CRC = 0, |
| 173 | .FAR = 1, | 173 | .FAR = 1, |
| @@ -193,31 +193,6 @@ static const struct config_registers v5_config_registers = { | |||
| 193 | .CTL_1 = 19, | 193 | .CTL_1 = 19, |
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| 196 | static const struct config_registers v6_config_registers = { | ||
| 197 | .CRC = 0, | ||
| 198 | .FAR = 1, | ||
| 199 | .FDRI = 2, | ||
| 200 | .FDRO = 3, | ||
| 201 | .CMD = 4, | ||
| 202 | .CTL = 5, | ||
| 203 | .MASK = 6, | ||
| 204 | .STAT = 7, | ||
| 205 | .LOUT = 8, | ||
| 206 | .COR = 9, | ||
| 207 | .MFWR = 10, | ||
| 208 | .FLR = UNIMPLEMENTED, | ||
| 209 | .KEY = UNIMPLEMENTED, | ||
| 210 | .CBC = 11, | ||
| 211 | .IDCODE = 12, | ||
| 212 | .AXSS = 13, | ||
| 213 | .C0R_1 = 14, | ||
| 214 | .CSOB = 15, | ||
| 215 | .WBSTAR = 16, | ||
| 216 | .TIMER = 17, | ||
| 217 | .BOOTSTS = 22, | ||
| 218 | .CTL_1 = 24, | ||
| 219 | }; | ||
| 220 | |||
| 221 | /** | 196 | /** |
| 222 | * hwicap_command_desync - Send a DESYNC command to the ICAP port. | 197 | * hwicap_command_desync - Send a DESYNC command to the ICAP port. |
| 223 | * @drvdata: a pointer to the drvdata. | 198 | * @drvdata: a pointer to the drvdata. |
| @@ -595,7 +570,7 @@ static const struct file_operations hwicap_fops = { | |||
| 595 | .llseek = noop_llseek, | 570 | .llseek = noop_llseek, |
| 596 | }; | 571 | }; |
| 597 | 572 | ||
| 598 | static int hwicap_setup(struct device *dev, int id, | 573 | static int __devinit hwicap_setup(struct device *dev, int id, |
| 599 | const struct resource *regs_res, | 574 | const struct resource *regs_res, |
| 600 | const struct hwicap_driver_config *config, | 575 | const struct hwicap_driver_config *config, |
| 601 | const struct config_registers *config_regs) | 576 | const struct config_registers *config_regs) |
| @@ -717,7 +692,7 @@ static struct hwicap_driver_config fifo_icap_config = { | |||
| 717 | .reset = fifo_icap_reset, | 692 | .reset = fifo_icap_reset, |
| 718 | }; | 693 | }; |
| 719 | 694 | ||
| 720 | static int hwicap_remove(struct device *dev) | 695 | static int __devexit hwicap_remove(struct device *dev) |
| 721 | { | 696 | { |
| 722 | struct hwicap_drvdata *drvdata; | 697 | struct hwicap_drvdata *drvdata; |
| 723 | 698 | ||
| @@ -740,7 +715,7 @@ static int hwicap_remove(struct device *dev) | |||
| 740 | } | 715 | } |
| 741 | 716 | ||
| 742 | #ifdef CONFIG_OF | 717 | #ifdef CONFIG_OF |
| 743 | static int hwicap_of_probe(struct platform_device *op, | 718 | static int __devinit hwicap_of_probe(struct platform_device *op, |
| 744 | const struct hwicap_driver_config *config) | 719 | const struct hwicap_driver_config *config) |
| 745 | { | 720 | { |
| 746 | struct resource res; | 721 | struct resource res; |
| @@ -770,8 +745,6 @@ static int hwicap_of_probe(struct platform_device *op, | |||
| 770 | regs = &v4_config_registers; | 745 | regs = &v4_config_registers; |
| 771 | } else if (!strcmp(family, "virtex5")) { | 746 | } else if (!strcmp(family, "virtex5")) { |
| 772 | regs = &v5_config_registers; | 747 | regs = &v5_config_registers; |
| 773 | } else if (!strcmp(family, "virtex6")) { | ||
| 774 | regs = &v6_config_registers; | ||
| 775 | } | 748 | } |
| 776 | } | 749 | } |
| 777 | return hwicap_setup(&op->dev, id ? *id : -1, &res, config, | 750 | return hwicap_setup(&op->dev, id ? *id : -1, &res, config, |
| @@ -785,8 +758,8 @@ static inline int hwicap_of_probe(struct platform_device *op, | |||
| 785 | } | 758 | } |
| 786 | #endif /* CONFIG_OF */ | 759 | #endif /* CONFIG_OF */ |
| 787 | 760 | ||
| 788 | static const struct of_device_id hwicap_of_match[]; | 761 | static const struct of_device_id __devinitconst hwicap_of_match[]; |
| 789 | static int hwicap_drv_probe(struct platform_device *pdev) | 762 | static int __devinit hwicap_drv_probe(struct platform_device *pdev) |
| 790 | { | 763 | { |
| 791 | const struct of_device_id *match; | 764 | const struct of_device_id *match; |
| 792 | struct resource *res; | 765 | struct resource *res; |
| @@ -813,8 +786,6 @@ static int hwicap_drv_probe(struct platform_device *pdev) | |||
| 813 | regs = &v4_config_registers; | 786 | regs = &v4_config_registers; |
| 814 | } else if (!strcmp(family, "virtex5")) { | 787 | } else if (!strcmp(family, "virtex5")) { |
| 815 | regs = &v5_config_registers; | 788 | regs = &v5_config_registers; |
| 816 | } else if (!strcmp(family, "virtex6")) { | ||
| 817 | regs = &v6_config_registers; | ||
| 818 | } | 789 | } |
| 819 | } | 790 | } |
| 820 | 791 | ||
| @@ -822,14 +793,14 @@ static int hwicap_drv_probe(struct platform_device *pdev) | |||
| 822 | &buffer_icap_config, regs); | 793 | &buffer_icap_config, regs); |
| 823 | } | 794 | } |
| 824 | 795 | ||
| 825 | static int hwicap_drv_remove(struct platform_device *pdev) | 796 | static int __devexit hwicap_drv_remove(struct platform_device *pdev) |
| 826 | { | 797 | { |
| 827 | return hwicap_remove(&pdev->dev); | 798 | return hwicap_remove(&pdev->dev); |
| 828 | } | 799 | } |
| 829 | 800 | ||
| 830 | #ifdef CONFIG_OF | 801 | #ifdef CONFIG_OF |
| 831 | /* Match table for device tree binding */ | 802 | /* Match table for device tree binding */ |
| 832 | static const struct of_device_id hwicap_of_match[] = { | 803 | static const struct of_device_id __devinitconst hwicap_of_match[] = { |
| 833 | { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config}, | 804 | { .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config}, |
| 834 | { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config}, | 805 | { .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config}, |
| 835 | {}, | 806 | {}, |
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.h b/drivers/char/xilinx_hwicap/xilinx_hwicap.h index d31ee23c9f1..8cca11981c5 100644 --- a/drivers/char/xilinx_hwicap/xilinx_hwicap.h +++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.h | |||
| @@ -86,7 +86,7 @@ struct hwicap_driver_config { | |||
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | /* Number of times to poll the done regsiter */ | 88 | /* Number of times to poll the done regsiter */ |
| 89 | #define XHI_MAX_RETRIES 5000 | 89 | #define XHI_MAX_RETRIES 10 |
| 90 | 90 | ||
| 91 | /************ Constant Definitions *************/ | 91 | /************ Constant Definitions *************/ |
| 92 | 92 | ||
