diff options
Diffstat (limited to 'drivers')
191 files changed, 3652 insertions, 3312 deletions
diff --git a/drivers/Makefile b/drivers/Makefile index 34f1e1064dbc..f42a03029b7c 100644 --- a/drivers/Makefile +++ b/drivers/Makefile | |||
| @@ -17,6 +17,7 @@ obj-$(CONFIG_SFI) += sfi/ | |||
| 17 | obj-$(CONFIG_PNP) += pnp/ | 17 | obj-$(CONFIG_PNP) += pnp/ |
| 18 | obj-$(CONFIG_ARM_AMBA) += amba/ | 18 | obj-$(CONFIG_ARM_AMBA) += amba/ |
| 19 | 19 | ||
| 20 | obj-$(CONFIG_VIRTIO) += virtio/ | ||
| 20 | obj-$(CONFIG_XEN) += xen/ | 21 | obj-$(CONFIG_XEN) += xen/ |
| 21 | 22 | ||
| 22 | # regulators early, since some subsystems rely on them to initialize | 23 | # regulators early, since some subsystems rely on them to initialize |
| @@ -108,7 +109,6 @@ obj-$(CONFIG_PPC_PS3) += ps3/ | |||
| 108 | obj-$(CONFIG_OF) += of/ | 109 | obj-$(CONFIG_OF) += of/ |
| 109 | obj-$(CONFIG_SSB) += ssb/ | 110 | obj-$(CONFIG_SSB) += ssb/ |
| 110 | obj-$(CONFIG_VHOST_NET) += vhost/ | 111 | obj-$(CONFIG_VHOST_NET) += vhost/ |
| 111 | obj-$(CONFIG_VIRTIO) += virtio/ | ||
| 112 | obj-$(CONFIG_VLYNQ) += vlynq/ | 112 | obj-$(CONFIG_VLYNQ) += vlynq/ |
| 113 | obj-$(CONFIG_STAGING) += staging/ | 113 | obj-$(CONFIG_STAGING) += staging/ |
| 114 | obj-y += platform/ | 114 | obj-y += platform/ |
diff --git a/drivers/acpi/acpi_pad.c b/drivers/acpi/acpi_pad.c index 19dacfd43163..62122134693b 100644 --- a/drivers/acpi/acpi_pad.c +++ b/drivers/acpi/acpi_pad.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <acpi/acpi_bus.h> | 31 | #include <acpi/acpi_bus.h> |
| 32 | #include <acpi/acpi_drivers.h> | 32 | #include <acpi/acpi_drivers.h> |
| 33 | 33 | ||
| 34 | #define ACPI_PROCESSOR_AGGREGATOR_CLASS "processor_aggregator" | 34 | #define ACPI_PROCESSOR_AGGREGATOR_CLASS "acpi_pad" |
| 35 | #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" | 35 | #define ACPI_PROCESSOR_AGGREGATOR_DEVICE_NAME "Processor Aggregator" |
| 36 | #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 | 36 | #define ACPI_PROCESSOR_AGGREGATOR_NOTIFY 0x80 |
| 37 | static DEFINE_MUTEX(isolated_cpus_lock); | 37 | static DEFINE_MUTEX(isolated_cpus_lock); |
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c index 37132dc2da03..743576bf1bd7 100644 --- a/drivers/acpi/bus.c +++ b/drivers/acpi/bus.c | |||
| @@ -527,7 +527,7 @@ int acpi_bus_generate_proc_event4(const char *device_class, const char *bus_id, | |||
| 527 | if (!event_is_open) | 527 | if (!event_is_open) |
| 528 | return 0; | 528 | return 0; |
| 529 | 529 | ||
| 530 | event = kmalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); | 530 | event = kzalloc(sizeof(struct acpi_bus_event), GFP_ATOMIC); |
| 531 | if (!event) | 531 | if (!event) |
| 532 | return -ENOMEM; | 532 | return -ENOMEM; |
| 533 | 533 | ||
diff --git a/drivers/acpi/hest.c b/drivers/acpi/hest.c index 4bb18c980ac6..1c527a192872 100644 --- a/drivers/acpi/hest.c +++ b/drivers/acpi/hest.c | |||
| @@ -123,6 +123,10 @@ int acpi_hest_firmware_first_pci(struct pci_dev *pci) | |||
| 123 | { | 123 | { |
| 124 | acpi_status status = AE_NOT_FOUND; | 124 | acpi_status status = AE_NOT_FOUND; |
| 125 | struct acpi_table_header *hest = NULL; | 125 | struct acpi_table_header *hest = NULL; |
| 126 | |||
| 127 | if (acpi_disabled) | ||
| 128 | return 0; | ||
| 129 | |||
| 126 | status = acpi_get_table(ACPI_SIG_HEST, 1, &hest); | 130 | status = acpi_get_table(ACPI_SIG_HEST, 1, &hest); |
| 127 | 131 | ||
| 128 | if (ACPI_SUCCESS(status)) { | 132 | if (ACPI_SUCCESS(status)) { |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index b0a71ecee682..e4804fb05e23 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
| @@ -401,11 +401,13 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
| 401 | * driver reported one, then use it. Exit in any case. | 401 | * driver reported one, then use it. Exit in any case. |
| 402 | */ | 402 | */ |
| 403 | if (gsi < 0) { | 403 | if (gsi < 0) { |
| 404 | u32 dev_gsi; | ||
| 404 | dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); | 405 | dev_warn(&dev->dev, "PCI INT %c: no GSI", pin_name(pin)); |
| 405 | /* Interrupt Line values above 0xF are forbidden */ | 406 | /* Interrupt Line values above 0xF are forbidden */ |
| 406 | if (dev->irq > 0 && (dev->irq <= 0xF)) { | 407 | if (dev->irq > 0 && (dev->irq <= 0xF) && |
| 407 | printk(" - using IRQ %d\n", dev->irq); | 408 | (acpi_isa_irq_to_gsi(dev->irq, &dev_gsi) == 0)) { |
| 408 | acpi_register_gsi(&dev->dev, dev->irq, | 409 | printk(" - using ISA IRQ %d\n", dev->irq); |
| 410 | acpi_register_gsi(&dev->dev, dev_gsi, | ||
| 409 | ACPI_LEVEL_SENSITIVE, | 411 | ACPI_LEVEL_SENSITIVE, |
| 410 | ACPI_ACTIVE_LOW); | 412 | ACPI_ACTIVE_LOW); |
| 411 | return 0; | 413 | return 0; |
diff --git a/drivers/acpi/power_meter.c b/drivers/acpi/power_meter.c index e8c32a49f14e..66f67293341e 100644 --- a/drivers/acpi/power_meter.c +++ b/drivers/acpi/power_meter.c | |||
| @@ -35,7 +35,7 @@ | |||
| 35 | #define ACPI_POWER_METER_NAME "power_meter" | 35 | #define ACPI_POWER_METER_NAME "power_meter" |
| 36 | ACPI_MODULE_NAME(ACPI_POWER_METER_NAME); | 36 | ACPI_MODULE_NAME(ACPI_POWER_METER_NAME); |
| 37 | #define ACPI_POWER_METER_DEVICE_NAME "Power Meter" | 37 | #define ACPI_POWER_METER_DEVICE_NAME "Power Meter" |
| 38 | #define ACPI_POWER_METER_CLASS "power_meter_resource" | 38 | #define ACPI_POWER_METER_CLASS "pwr_meter_resource" |
| 39 | 39 | ||
| 40 | #define NUM_SENSORS 17 | 40 | #define NUM_SENSORS 17 |
| 41 | 41 | ||
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c index 36704b887ccf..f8be23b6c129 100644 --- a/drivers/acpi/sbshc.c +++ b/drivers/acpi/sbshc.c | |||
| @@ -18,7 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | #define PREFIX "ACPI: " | 19 | #define PREFIX "ACPI: " |
| 20 | 20 | ||
| 21 | #define ACPI_SMB_HC_CLASS "smbus_host_controller" | 21 | #define ACPI_SMB_HC_CLASS "smbus_host_ctl" |
| 22 | #define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC" | 22 | #define ACPI_SMB_HC_DEVICE_NAME "ACPI SMBus HC" |
| 23 | 23 | ||
| 24 | struct acpi_smb_hc { | 24 | struct acpi_smb_hc { |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index f74834a544fd..baa76bbf244a 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
| @@ -450,6 +450,38 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| 450 | }, | 450 | }, |
| 451 | }, | 451 | }, |
| 452 | { | 452 | { |
| 453 | .callback = init_set_sci_en_on_resume, | ||
| 454 | .ident = "Lenovo ThinkPad T410", | ||
| 455 | .matches = { | ||
| 456 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 457 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T410"), | ||
| 458 | }, | ||
| 459 | }, | ||
| 460 | { | ||
| 461 | .callback = init_set_sci_en_on_resume, | ||
| 462 | .ident = "Lenovo ThinkPad T510", | ||
| 463 | .matches = { | ||
| 464 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 465 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad T510"), | ||
| 466 | }, | ||
| 467 | }, | ||
| 468 | { | ||
| 469 | .callback = init_set_sci_en_on_resume, | ||
| 470 | .ident = "Lenovo ThinkPad W510", | ||
| 471 | .matches = { | ||
| 472 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 473 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad W510"), | ||
| 474 | }, | ||
| 475 | }, | ||
| 476 | { | ||
| 477 | .callback = init_set_sci_en_on_resume, | ||
| 478 | .ident = "Lenovo ThinkPad X201[s]", | ||
| 479 | .matches = { | ||
| 480 | DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), | ||
| 481 | DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad X201"), | ||
| 482 | }, | ||
| 483 | }, | ||
| 484 | { | ||
| 453 | .callback = init_old_suspend_ordering, | 485 | .callback = init_old_suspend_ordering, |
| 454 | .ident = "Panasonic CF51-2L", | 486 | .ident = "Panasonic CF51-2L", |
| 455 | .matches = { | 487 | .matches = { |
| @@ -458,6 +490,30 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
| 458 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), | 490 | DMI_MATCH(DMI_BOARD_NAME, "CF51-2L"), |
| 459 | }, | 491 | }, |
| 460 | }, | 492 | }, |
| 493 | { | ||
| 494 | .callback = init_set_sci_en_on_resume, | ||
| 495 | .ident = "Dell Studio 1558", | ||
| 496 | .matches = { | ||
| 497 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 498 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1558"), | ||
| 499 | }, | ||
| 500 | }, | ||
| 501 | { | ||
| 502 | .callback = init_set_sci_en_on_resume, | ||
| 503 | .ident = "Dell Studio 1557", | ||
| 504 | .matches = { | ||
| 505 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 506 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1557"), | ||
| 507 | }, | ||
| 508 | }, | ||
| 509 | { | ||
| 510 | .callback = init_set_sci_en_on_resume, | ||
| 511 | .ident = "Dell Studio 1555", | ||
| 512 | .matches = { | ||
| 513 | DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), | ||
| 514 | DMI_MATCH(DMI_PRODUCT_NAME, "Studio 1555"), | ||
| 515 | }, | ||
| 516 | }, | ||
| 461 | {}, | 517 | {}, |
| 462 | }; | 518 | }; |
| 463 | #endif /* CONFIG_SUSPEND */ | 519 | #endif /* CONFIG_SUSPEND */ |
diff --git a/drivers/ata/pata_pcmcia.c b/drivers/ata/pata_pcmcia.c index 4164dd244dd0..d94b8f0bd743 100644 --- a/drivers/ata/pata_pcmcia.c +++ b/drivers/ata/pata_pcmcia.c | |||
| @@ -424,7 +424,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { | |||
| 424 | PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), | 424 | PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), |
| 425 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), | 425 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), |
| 426 | PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), | 426 | PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), |
| 427 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x3e520e17), | 427 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb), |
| 428 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10), | 428 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10), |
| 429 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), | 429 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), |
| 430 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), | 430 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), |
| @@ -446,7 +446,7 @@ static struct pcmcia_device_id pcmcia_devices[] = { | |||
| 446 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), | 446 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), |
| 447 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), | 447 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), |
| 448 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), | 448 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), |
| 449 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x9351e59d), | 449 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133), |
| 450 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47), | 450 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47), |
| 451 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), | 451 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), |
| 452 | PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), | 452 | PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), |
diff --git a/drivers/base/iommu.c b/drivers/base/iommu.c index 8ad4ffea6920..6e6b6a11b3ce 100644 --- a/drivers/base/iommu.c +++ b/drivers/base/iommu.c | |||
| @@ -80,20 +80,6 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev) | |||
| 80 | } | 80 | } |
| 81 | EXPORT_SYMBOL_GPL(iommu_detach_device); | 81 | EXPORT_SYMBOL_GPL(iommu_detach_device); |
| 82 | 82 | ||
| 83 | int iommu_map_range(struct iommu_domain *domain, unsigned long iova, | ||
| 84 | phys_addr_t paddr, size_t size, int prot) | ||
| 85 | { | ||
| 86 | return iommu_ops->map(domain, iova, paddr, size, prot); | ||
| 87 | } | ||
| 88 | EXPORT_SYMBOL_GPL(iommu_map_range); | ||
| 89 | |||
| 90 | void iommu_unmap_range(struct iommu_domain *domain, unsigned long iova, | ||
| 91 | size_t size) | ||
| 92 | { | ||
| 93 | iommu_ops->unmap(domain, iova, size); | ||
| 94 | } | ||
| 95 | EXPORT_SYMBOL_GPL(iommu_unmap_range); | ||
| 96 | |||
| 97 | phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, | 83 | phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, |
| 98 | unsigned long iova) | 84 | unsigned long iova) |
| 99 | { | 85 | { |
| @@ -107,3 +93,32 @@ int iommu_domain_has_cap(struct iommu_domain *domain, | |||
| 107 | return iommu_ops->domain_has_cap(domain, cap); | 93 | return iommu_ops->domain_has_cap(domain, cap); |
| 108 | } | 94 | } |
| 109 | EXPORT_SYMBOL_GPL(iommu_domain_has_cap); | 95 | EXPORT_SYMBOL_GPL(iommu_domain_has_cap); |
| 96 | |||
| 97 | int iommu_map(struct iommu_domain *domain, unsigned long iova, | ||
| 98 | phys_addr_t paddr, int gfp_order, int prot) | ||
| 99 | { | ||
| 100 | unsigned long invalid_mask; | ||
| 101 | size_t size; | ||
| 102 | |||
| 103 | size = 0x1000UL << gfp_order; | ||
| 104 | invalid_mask = size - 1; | ||
| 105 | |||
| 106 | BUG_ON((iova | paddr) & invalid_mask); | ||
| 107 | |||
| 108 | return iommu_ops->map(domain, iova, paddr, gfp_order, prot); | ||
| 109 | } | ||
| 110 | EXPORT_SYMBOL_GPL(iommu_map); | ||
| 111 | |||
| 112 | int iommu_unmap(struct iommu_domain *domain, unsigned long iova, int gfp_order) | ||
| 113 | { | ||
| 114 | unsigned long invalid_mask; | ||
| 115 | size_t size; | ||
| 116 | |||
| 117 | size = 0x1000UL << gfp_order; | ||
| 118 | invalid_mask = size - 1; | ||
| 119 | |||
| 120 | BUG_ON(iova & invalid_mask); | ||
| 121 | |||
| 122 | return iommu_ops->unmap(domain, iova, gfp_order); | ||
| 123 | } | ||
| 124 | EXPORT_SYMBOL_GPL(iommu_unmap); | ||
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 4b4b565c835f..765bcf0df3bb 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -187,7 +187,7 @@ EXPORT_SYMBOL_GPL(platform_device_alloc); | |||
| 187 | * released. | 187 | * released. |
| 188 | */ | 188 | */ |
| 189 | int platform_device_add_resources(struct platform_device *pdev, | 189 | int platform_device_add_resources(struct platform_device *pdev, |
| 190 | struct resource *res, unsigned int num) | 190 | const struct resource *res, unsigned int num) |
| 191 | { | 191 | { |
| 192 | struct resource *r; | 192 | struct resource *r; |
| 193 | 193 | ||
| @@ -367,7 +367,7 @@ EXPORT_SYMBOL_GPL(platform_device_unregister); | |||
| 367 | */ | 367 | */ |
| 368 | struct platform_device *platform_device_register_simple(const char *name, | 368 | struct platform_device *platform_device_register_simple(const char *name, |
| 369 | int id, | 369 | int id, |
| 370 | struct resource *res, | 370 | const struct resource *res, |
| 371 | unsigned int num) | 371 | unsigned int num) |
| 372 | { | 372 | { |
| 373 | struct platform_device *pdev; | 373 | struct platform_device *pdev; |
| @@ -1254,6 +1254,26 @@ static int __init early_platform_driver_probe_id(char *class_str, | |||
| 1254 | } | 1254 | } |
| 1255 | 1255 | ||
| 1256 | if (match) { | 1256 | if (match) { |
| 1257 | /* | ||
| 1258 | * Set up a sensible init_name to enable | ||
| 1259 | * dev_name() and others to be used before the | ||
| 1260 | * rest of the driver core is initialized. | ||
| 1261 | */ | ||
| 1262 | if (!match->dev.init_name && slab_is_available()) { | ||
| 1263 | if (match->id != -1) | ||
| 1264 | match->dev.init_name = | ||
| 1265 | kasprintf(GFP_KERNEL, "%s.%d", | ||
| 1266 | match->name, | ||
| 1267 | match->id); | ||
| 1268 | else | ||
| 1269 | match->dev.init_name = | ||
| 1270 | kasprintf(GFP_KERNEL, "%s", | ||
| 1271 | match->name); | ||
| 1272 | |||
| 1273 | if (!match->dev.init_name) | ||
| 1274 | return -ENOMEM; | ||
| 1275 | } | ||
| 1276 | |||
| 1257 | if (epdrv->pdrv->probe(match)) | 1277 | if (epdrv->pdrv->probe(match)) |
| 1258 | pr_warning("%s: unable to probe %s early.\n", | 1278 | pr_warning("%s: unable to probe %s early.\n", |
| 1259 | class_str, match->name); | 1279 | class_str, match->name); |
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 0182a22c423a..832798aa14f6 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
| @@ -66,6 +66,7 @@ | |||
| 66 | #include <linux/blkdev.h> | 66 | #include <linux/blkdev.h> |
| 67 | #include <linux/elevator.h> | 67 | #include <linux/elevator.h> |
| 68 | #include <linux/interrupt.h> | 68 | #include <linux/interrupt.h> |
| 69 | #include <linux/platform_device.h> | ||
| 69 | 70 | ||
| 70 | #include <asm/setup.h> | 71 | #include <asm/setup.h> |
| 71 | #include <asm/uaccess.h> | 72 | #include <asm/uaccess.h> |
| @@ -1696,34 +1697,18 @@ static struct kobject *floppy_find(dev_t dev, int *part, void *data) | |||
| 1696 | return get_disk(unit[drive].gendisk); | 1697 | return get_disk(unit[drive].gendisk); |
| 1697 | } | 1698 | } |
| 1698 | 1699 | ||
| 1699 | static int __init amiga_floppy_init(void) | 1700 | static int __init amiga_floppy_probe(struct platform_device *pdev) |
| 1700 | { | 1701 | { |
| 1701 | int i, ret; | 1702 | int i, ret; |
| 1702 | 1703 | ||
| 1703 | if (!MACH_IS_AMIGA) | ||
| 1704 | return -ENODEV; | ||
| 1705 | |||
| 1706 | if (!AMIGAHW_PRESENT(AMI_FLOPPY)) | ||
| 1707 | return -ENODEV; | ||
| 1708 | |||
| 1709 | if (register_blkdev(FLOPPY_MAJOR,"fd")) | 1704 | if (register_blkdev(FLOPPY_MAJOR,"fd")) |
| 1710 | return -EBUSY; | 1705 | return -EBUSY; |
| 1711 | 1706 | ||
| 1712 | /* | ||
| 1713 | * We request DSKPTR, DSKLEN and DSKDATA only, because the other | ||
| 1714 | * floppy registers are too spreaded over the custom register space | ||
| 1715 | */ | ||
| 1716 | ret = -EBUSY; | ||
| 1717 | if (!request_mem_region(CUSTOM_PHYSADDR+0x20, 8, "amiflop [Paula]")) { | ||
| 1718 | printk("fd: cannot get floppy registers\n"); | ||
| 1719 | goto out_blkdev; | ||
| 1720 | } | ||
| 1721 | |||
| 1722 | ret = -ENOMEM; | 1707 | ret = -ENOMEM; |
| 1723 | if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == | 1708 | if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) == |
| 1724 | NULL) { | 1709 | NULL) { |
| 1725 | printk("fd: cannot get chip mem buffer\n"); | 1710 | printk("fd: cannot get chip mem buffer\n"); |
| 1726 | goto out_memregion; | 1711 | goto out_blkdev; |
| 1727 | } | 1712 | } |
| 1728 | 1713 | ||
| 1729 | ret = -EBUSY; | 1714 | ret = -EBUSY; |
| @@ -1792,18 +1777,13 @@ out_irq2: | |||
| 1792 | free_irq(IRQ_AMIGA_DSKBLK, NULL); | 1777 | free_irq(IRQ_AMIGA_DSKBLK, NULL); |
| 1793 | out_irq: | 1778 | out_irq: |
| 1794 | amiga_chip_free(raw_buf); | 1779 | amiga_chip_free(raw_buf); |
| 1795 | out_memregion: | ||
| 1796 | release_mem_region(CUSTOM_PHYSADDR+0x20, 8); | ||
| 1797 | out_blkdev: | 1780 | out_blkdev: |
| 1798 | unregister_blkdev(FLOPPY_MAJOR,"fd"); | 1781 | unregister_blkdev(FLOPPY_MAJOR,"fd"); |
| 1799 | return ret; | 1782 | return ret; |
| 1800 | } | 1783 | } |
| 1801 | 1784 | ||
| 1802 | module_init(amiga_floppy_init); | ||
| 1803 | #ifdef MODULE | ||
| 1804 | |||
| 1805 | #if 0 /* not safe to unload */ | 1785 | #if 0 /* not safe to unload */ |
| 1806 | void cleanup_module(void) | 1786 | static int __exit amiga_floppy_remove(struct platform_device *pdev) |
| 1807 | { | 1787 | { |
| 1808 | int i; | 1788 | int i; |
| 1809 | 1789 | ||
| @@ -1820,12 +1800,25 @@ void cleanup_module(void) | |||
| 1820 | custom.dmacon = DMAF_DISK; /* disable DMA */ | 1800 | custom.dmacon = DMAF_DISK; /* disable DMA */ |
| 1821 | amiga_chip_free(raw_buf); | 1801 | amiga_chip_free(raw_buf); |
| 1822 | blk_cleanup_queue(floppy_queue); | 1802 | blk_cleanup_queue(floppy_queue); |
| 1823 | release_mem_region(CUSTOM_PHYSADDR+0x20, 8); | ||
| 1824 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 1803 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
| 1825 | } | 1804 | } |
| 1826 | #endif | 1805 | #endif |
| 1827 | 1806 | ||
| 1828 | #else | 1807 | static struct platform_driver amiga_floppy_driver = { |
| 1808 | .driver = { | ||
| 1809 | .name = "amiga-floppy", | ||
| 1810 | .owner = THIS_MODULE, | ||
| 1811 | }, | ||
| 1812 | }; | ||
| 1813 | |||
| 1814 | static int __init amiga_floppy_init(void) | ||
| 1815 | { | ||
| 1816 | return platform_driver_probe(&amiga_floppy_driver, amiga_floppy_probe); | ||
| 1817 | } | ||
| 1818 | |||
| 1819 | module_init(amiga_floppy_init); | ||
| 1820 | |||
| 1821 | #ifndef MODULE | ||
| 1829 | static int __init amiga_floppy_setup (char *str) | 1822 | static int __init amiga_floppy_setup (char *str) |
| 1830 | { | 1823 | { |
| 1831 | int n; | 1824 | int n; |
| @@ -1840,3 +1833,5 @@ static int __init amiga_floppy_setup (char *str) | |||
| 1840 | 1833 | ||
| 1841 | __setup("floppy=", amiga_floppy_setup); | 1834 | __setup("floppy=", amiga_floppy_setup); |
| 1842 | #endif | 1835 | #endif |
| 1836 | |||
| 1837 | MODULE_ALIAS("platform:amiga-floppy"); | ||
diff --git a/drivers/block/drbd/drbd_worker.c b/drivers/block/drbd/drbd_worker.c index 44bf6d11197e..d48a1dfd7b24 100644 --- a/drivers/block/drbd/drbd_worker.c +++ b/drivers/block/drbd/drbd_worker.c | |||
| @@ -235,7 +235,7 @@ void drbd_endio_pri(struct bio *bio, int error) | |||
| 235 | if (unlikely(error)) { | 235 | if (unlikely(error)) { |
| 236 | what = (bio_data_dir(bio) == WRITE) | 236 | what = (bio_data_dir(bio) == WRITE) |
| 237 | ? write_completed_with_error | 237 | ? write_completed_with_error |
| 238 | : (bio_rw(bio) == READA) | 238 | : (bio_rw(bio) == READ) |
| 239 | ? read_completed_with_error | 239 | ? read_completed_with_error |
| 240 | : read_ahead_completed_with_error; | 240 | : read_ahead_completed_with_error; |
| 241 | } else | 241 | } else |
diff --git a/drivers/block/hd.c b/drivers/block/hd.c index 034e6dfc878c..81c78b3ce2df 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c | |||
| @@ -164,12 +164,12 @@ unsigned long read_timer(void) | |||
| 164 | unsigned long t, flags; | 164 | unsigned long t, flags; |
| 165 | int i; | 165 | int i; |
| 166 | 166 | ||
| 167 | spin_lock_irqsave(&i8253_lock, flags); | 167 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 168 | t = jiffies * 11932; | 168 | t = jiffies * 11932; |
| 169 | outb_p(0, 0x43); | 169 | outb_p(0, 0x43); |
| 170 | i = inb_p(0x40); | 170 | i = inb_p(0x40); |
| 171 | i |= inb(0x40) << 8; | 171 | i |= inb(0x40) << 8; |
| 172 | spin_unlock_irqrestore(&i8253_lock, flags); | 172 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 173 | return(t - i); | 173 | return(t - i); |
| 174 | } | 174 | } |
| 175 | #endif | 175 | #endif |
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c index 8dfd24721a82..78a62ebe75c7 100644 --- a/drivers/char/serial167.c +++ b/drivers/char/serial167.c | |||
| @@ -627,7 +627,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) | |||
| 627 | char data; | 627 | char data; |
| 628 | int char_count; | 628 | int char_count; |
| 629 | int save_cnt; | 629 | int save_cnt; |
| 630 | int len; | ||
| 631 | 630 | ||
| 632 | /* determine the channel and change to that context */ | 631 | /* determine the channel and change to that context */ |
| 633 | channel = (u_short) (base_addr[CyLICR] >> 2); | 632 | channel = (u_short) (base_addr[CyLICR] >> 2); |
| @@ -1528,7 +1527,6 @@ static int | |||
| 1528 | cy_ioctl(struct tty_struct *tty, struct file *file, | 1527 | cy_ioctl(struct tty_struct *tty, struct file *file, |
| 1529 | unsigned int cmd, unsigned long arg) | 1528 | unsigned int cmd, unsigned long arg) |
| 1530 | { | 1529 | { |
| 1531 | unsigned long val; | ||
| 1532 | struct cyclades_port *info = tty->driver_data; | 1530 | struct cyclades_port *info = tty->driver_data; |
| 1533 | int ret_val = 0; | 1531 | int ret_val = 0; |
| 1534 | void __user *argp = (void __user *)arg; | 1532 | void __user *argp = (void __user *)arg; |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index 59de2525d303..d4e8b213a462 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
| @@ -289,7 +289,7 @@ static struct sysrq_key_op sysrq_showstate_blocked_op = { | |||
| 289 | 289 | ||
| 290 | static void sysrq_ftrace_dump(int key, struct tty_struct *tty) | 290 | static void sysrq_ftrace_dump(int key, struct tty_struct *tty) |
| 291 | { | 291 | { |
| 292 | ftrace_dump(); | 292 | ftrace_dump(DUMP_ALL); |
| 293 | } | 293 | } |
| 294 | static struct sysrq_key_op sysrq_ftrace_dump_op = { | 294 | static struct sysrq_key_op sysrq_ftrace_dump_op = { |
| 295 | .handler = sysrq_ftrace_dump, | 295 | .handler = sysrq_ftrace_dump, |
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 6da962c9b21c..d71f0fc34b46 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -1875,6 +1875,7 @@ got_driver: | |||
| 1875 | */ | 1875 | */ |
| 1876 | if (filp->f_op == &hung_up_tty_fops) | 1876 | if (filp->f_op == &hung_up_tty_fops) |
| 1877 | filp->f_op = &tty_fops; | 1877 | filp->f_op = &tty_fops; |
| 1878 | unlock_kernel(); | ||
| 1878 | goto retry_open; | 1879 | goto retry_open; |
| 1879 | } | 1880 | } |
| 1880 | unlock_kernel(); | 1881 | unlock_kernel(); |
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 744f748cc84b..f6677cb19789 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
| @@ -150,13 +150,12 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | |||
| 150 | 150 | ||
| 151 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | 151 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) |
| 152 | { | 152 | { |
| 153 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 154 | int ret; | 153 | int ret; |
| 155 | 154 | ||
| 156 | /* enable clock */ | 155 | /* enable clock */ |
| 157 | ret = clk_enable(p->clk); | 156 | ret = clk_enable(p->clk); |
| 158 | if (ret) { | 157 | if (ret) { |
| 159 | pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); | 158 | dev_err(&p->pdev->dev, "cannot enable clock\n"); |
| 160 | return ret; | 159 | return ret; |
| 161 | } | 160 | } |
| 162 | 161 | ||
| @@ -279,7 +278,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, | |||
| 279 | delay = 1; | 278 | delay = 1; |
| 280 | 279 | ||
| 281 | if (!delay) | 280 | if (!delay) |
| 282 | pr_warning("sh_cmt: too long delay\n"); | 281 | dev_warn(&p->pdev->dev, "too long delay\n"); |
| 283 | 282 | ||
| 284 | } while (delay); | 283 | } while (delay); |
| 285 | } | 284 | } |
| @@ -289,7 +288,7 @@ static void sh_cmt_set_next(struct sh_cmt_priv *p, unsigned long delta) | |||
| 289 | unsigned long flags; | 288 | unsigned long flags; |
| 290 | 289 | ||
| 291 | if (delta > p->max_match_value) | 290 | if (delta > p->max_match_value) |
| 292 | pr_warning("sh_cmt: delta out of range\n"); | 291 | dev_warn(&p->pdev->dev, "delta out of range\n"); |
| 293 | 292 | ||
| 294 | spin_lock_irqsave(&p->lock, flags); | 293 | spin_lock_irqsave(&p->lock, flags); |
| 295 | p->next_match_value = delta; | 294 | p->next_match_value = delta; |
| @@ -451,7 +450,7 @@ static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, | |||
| 451 | cs->resume = sh_cmt_clocksource_resume; | 450 | cs->resume = sh_cmt_clocksource_resume; |
| 452 | cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); | 451 | cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); |
| 453 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; | 452 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; |
| 454 | pr_info("sh_cmt: %s used as clock source\n", cs->name); | 453 | dev_info(&p->pdev->dev, "used as clock source\n"); |
| 455 | clocksource_register(cs); | 454 | clocksource_register(cs); |
| 456 | return 0; | 455 | return 0; |
| 457 | } | 456 | } |
| @@ -497,13 +496,11 @@ static void sh_cmt_clock_event_mode(enum clock_event_mode mode, | |||
| 497 | 496 | ||
| 498 | switch (mode) { | 497 | switch (mode) { |
| 499 | case CLOCK_EVT_MODE_PERIODIC: | 498 | case CLOCK_EVT_MODE_PERIODIC: |
| 500 | pr_info("sh_cmt: %s used for periodic clock events\n", | 499 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); |
| 501 | ced->name); | ||
| 502 | sh_cmt_clock_event_start(p, 1); | 500 | sh_cmt_clock_event_start(p, 1); |
| 503 | break; | 501 | break; |
| 504 | case CLOCK_EVT_MODE_ONESHOT: | 502 | case CLOCK_EVT_MODE_ONESHOT: |
| 505 | pr_info("sh_cmt: %s used for oneshot clock events\n", | 503 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); |
| 506 | ced->name); | ||
| 507 | sh_cmt_clock_event_start(p, 0); | 504 | sh_cmt_clock_event_start(p, 0); |
| 508 | break; | 505 | break; |
| 509 | case CLOCK_EVT_MODE_SHUTDOWN: | 506 | case CLOCK_EVT_MODE_SHUTDOWN: |
| @@ -544,7 +541,7 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, | |||
| 544 | ced->set_next_event = sh_cmt_clock_event_next; | 541 | ced->set_next_event = sh_cmt_clock_event_next; |
| 545 | ced->set_mode = sh_cmt_clock_event_mode; | 542 | ced->set_mode = sh_cmt_clock_event_mode; |
| 546 | 543 | ||
| 547 | pr_info("sh_cmt: %s used for clock events\n", ced->name); | 544 | dev_info(&p->pdev->dev, "used for clock events\n"); |
| 548 | clockevents_register_device(ced); | 545 | clockevents_register_device(ced); |
| 549 | } | 546 | } |
| 550 | 547 | ||
| @@ -601,22 +598,27 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
| 601 | /* map memory, let mapbase point to our channel */ | 598 | /* map memory, let mapbase point to our channel */ |
| 602 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | 599 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); |
| 603 | if (p->mapbase == NULL) { | 600 | if (p->mapbase == NULL) { |
| 604 | pr_err("sh_cmt: failed to remap I/O memory\n"); | 601 | dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); |
| 605 | goto err0; | 602 | goto err0; |
| 606 | } | 603 | } |
| 607 | 604 | ||
| 608 | /* request irq using setup_irq() (too early for request_irq()) */ | 605 | /* request irq using setup_irq() (too early for request_irq()) */ |
| 609 | p->irqaction.name = cfg->name; | 606 | p->irqaction.name = dev_name(&p->pdev->dev); |
| 610 | p->irqaction.handler = sh_cmt_interrupt; | 607 | p->irqaction.handler = sh_cmt_interrupt; |
| 611 | p->irqaction.dev_id = p; | 608 | p->irqaction.dev_id = p; |
| 612 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | 609 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ |
| 610 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
| 613 | 611 | ||
| 614 | /* get hold of clock */ | 612 | /* get hold of clock */ |
| 615 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | 613 | p->clk = clk_get(&p->pdev->dev, "cmt_fck"); |
| 616 | if (IS_ERR(p->clk)) { | 614 | if (IS_ERR(p->clk)) { |
| 617 | pr_err("sh_cmt: cannot get clock \"%s\"\n", cfg->clk); | 615 | dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); |
| 618 | ret = PTR_ERR(p->clk); | 616 | p->clk = clk_get(&p->pdev->dev, cfg->clk); |
| 619 | goto err1; | 617 | if (IS_ERR(p->clk)) { |
| 618 | dev_err(&p->pdev->dev, "cannot get clock\n"); | ||
| 619 | ret = PTR_ERR(p->clk); | ||
| 620 | goto err1; | ||
| 621 | } | ||
| 620 | } | 622 | } |
| 621 | 623 | ||
| 622 | if (resource_size(res) == 6) { | 624 | if (resource_size(res) == 6) { |
| @@ -629,17 +631,17 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
| 629 | p->clear_bits = ~0xc000; | 631 | p->clear_bits = ~0xc000; |
| 630 | } | 632 | } |
| 631 | 633 | ||
| 632 | ret = sh_cmt_register(p, cfg->name, | 634 | ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), |
| 633 | cfg->clockevent_rating, | 635 | cfg->clockevent_rating, |
| 634 | cfg->clocksource_rating); | 636 | cfg->clocksource_rating); |
| 635 | if (ret) { | 637 | if (ret) { |
| 636 | pr_err("sh_cmt: registration failed\n"); | 638 | dev_err(&p->pdev->dev, "registration failed\n"); |
| 637 | goto err1; | 639 | goto err1; |
| 638 | } | 640 | } |
| 639 | 641 | ||
| 640 | ret = setup_irq(irq, &p->irqaction); | 642 | ret = setup_irq(irq, &p->irqaction); |
| 641 | if (ret) { | 643 | if (ret) { |
| 642 | pr_err("sh_cmt: failed to request irq %d\n", irq); | 644 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); |
| 643 | goto err1; | 645 | goto err1; |
| 644 | } | 646 | } |
| 645 | 647 | ||
| @@ -654,11 +656,10 @@ err0: | |||
| 654 | static int __devinit sh_cmt_probe(struct platform_device *pdev) | 656 | static int __devinit sh_cmt_probe(struct platform_device *pdev) |
| 655 | { | 657 | { |
| 656 | struct sh_cmt_priv *p = platform_get_drvdata(pdev); | 658 | struct sh_cmt_priv *p = platform_get_drvdata(pdev); |
| 657 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 658 | int ret; | 659 | int ret; |
| 659 | 660 | ||
| 660 | if (p) { | 661 | if (p) { |
| 661 | pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name); | 662 | dev_info(&pdev->dev, "kept as earlytimer\n"); |
| 662 | return 0; | 663 | return 0; |
| 663 | } | 664 | } |
| 664 | 665 | ||
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 5fb78bfd73bb..ef7a5be8a09f 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
| @@ -119,13 +119,12 @@ static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) | |||
| 119 | 119 | ||
| 120 | static int sh_mtu2_enable(struct sh_mtu2_priv *p) | 120 | static int sh_mtu2_enable(struct sh_mtu2_priv *p) |
| 121 | { | 121 | { |
| 122 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 123 | int ret; | 122 | int ret; |
| 124 | 123 | ||
| 125 | /* enable clock */ | 124 | /* enable clock */ |
| 126 | ret = clk_enable(p->clk); | 125 | ret = clk_enable(p->clk); |
| 127 | if (ret) { | 126 | if (ret) { |
| 128 | pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk); | 127 | dev_err(&p->pdev->dev, "cannot enable clock\n"); |
| 129 | return ret; | 128 | return ret; |
| 130 | } | 129 | } |
| 131 | 130 | ||
| @@ -194,8 +193,7 @@ static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, | |||
| 194 | 193 | ||
| 195 | switch (mode) { | 194 | switch (mode) { |
| 196 | case CLOCK_EVT_MODE_PERIODIC: | 195 | case CLOCK_EVT_MODE_PERIODIC: |
| 197 | pr_info("sh_mtu2: %s used for periodic clock events\n", | 196 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); |
| 198 | ced->name); | ||
| 199 | sh_mtu2_enable(p); | 197 | sh_mtu2_enable(p); |
| 200 | break; | 198 | break; |
| 201 | case CLOCK_EVT_MODE_UNUSED: | 199 | case CLOCK_EVT_MODE_UNUSED: |
| @@ -222,13 +220,13 @@ static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, | |||
| 222 | ced->cpumask = cpumask_of(0); | 220 | ced->cpumask = cpumask_of(0); |
| 223 | ced->set_mode = sh_mtu2_clock_event_mode; | 221 | ced->set_mode = sh_mtu2_clock_event_mode; |
| 224 | 222 | ||
| 225 | pr_info("sh_mtu2: %s used for clock events\n", ced->name); | 223 | dev_info(&p->pdev->dev, "used for clock events\n"); |
| 226 | clockevents_register_device(ced); | 224 | clockevents_register_device(ced); |
| 227 | 225 | ||
| 228 | ret = setup_irq(p->irqaction.irq, &p->irqaction); | 226 | ret = setup_irq(p->irqaction.irq, &p->irqaction); |
| 229 | if (ret) { | 227 | if (ret) { |
| 230 | pr_err("sh_mtu2: failed to request irq %d\n", | 228 | dev_err(&p->pdev->dev, "failed to request irq %d\n", |
| 231 | p->irqaction.irq); | 229 | p->irqaction.irq); |
| 232 | return; | 230 | return; |
| 233 | } | 231 | } |
| 234 | } | 232 | } |
| @@ -274,26 +272,32 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) | |||
| 274 | /* map memory, let mapbase point to our channel */ | 272 | /* map memory, let mapbase point to our channel */ |
| 275 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | 273 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); |
| 276 | if (p->mapbase == NULL) { | 274 | if (p->mapbase == NULL) { |
| 277 | pr_err("sh_mtu2: failed to remap I/O memory\n"); | 275 | dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); |
| 278 | goto err0; | 276 | goto err0; |
| 279 | } | 277 | } |
| 280 | 278 | ||
| 281 | /* setup data for setup_irq() (too early for request_irq()) */ | 279 | /* setup data for setup_irq() (too early for request_irq()) */ |
| 282 | p->irqaction.name = cfg->name; | 280 | p->irqaction.name = dev_name(&p->pdev->dev); |
| 283 | p->irqaction.handler = sh_mtu2_interrupt; | 281 | p->irqaction.handler = sh_mtu2_interrupt; |
| 284 | p->irqaction.dev_id = p; | 282 | p->irqaction.dev_id = p; |
| 285 | p->irqaction.irq = irq; | 283 | p->irqaction.irq = irq; |
| 286 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | 284 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ |
| 285 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
| 287 | 286 | ||
| 288 | /* get hold of clock */ | 287 | /* get hold of clock */ |
| 289 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | 288 | p->clk = clk_get(&p->pdev->dev, "mtu2_fck"); |
| 290 | if (IS_ERR(p->clk)) { | 289 | if (IS_ERR(p->clk)) { |
| 291 | pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk); | 290 | dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); |
| 292 | ret = PTR_ERR(p->clk); | 291 | p->clk = clk_get(&p->pdev->dev, cfg->clk); |
| 293 | goto err1; | 292 | if (IS_ERR(p->clk)) { |
| 293 | dev_err(&p->pdev->dev, "cannot get clock\n"); | ||
| 294 | ret = PTR_ERR(p->clk); | ||
| 295 | goto err1; | ||
| 296 | } | ||
| 294 | } | 297 | } |
| 295 | 298 | ||
| 296 | return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating); | 299 | return sh_mtu2_register(p, (char *)dev_name(&p->pdev->dev), |
| 300 | cfg->clockevent_rating); | ||
| 297 | err1: | 301 | err1: |
| 298 | iounmap(p->mapbase); | 302 | iounmap(p->mapbase); |
| 299 | err0: | 303 | err0: |
| @@ -303,11 +307,10 @@ static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) | |||
| 303 | static int __devinit sh_mtu2_probe(struct platform_device *pdev) | 307 | static int __devinit sh_mtu2_probe(struct platform_device *pdev) |
| 304 | { | 308 | { |
| 305 | struct sh_mtu2_priv *p = platform_get_drvdata(pdev); | 309 | struct sh_mtu2_priv *p = platform_get_drvdata(pdev); |
| 306 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 307 | int ret; | 310 | int ret; |
| 308 | 311 | ||
| 309 | if (p) { | 312 | if (p) { |
| 310 | pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name); | 313 | dev_info(&pdev->dev, "kept as earlytimer\n"); |
| 311 | return 0; | 314 | return 0; |
| 312 | } | 315 | } |
| 313 | 316 | ||
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index fc9ff1e5b770..8e44e14ec4c2 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
| @@ -107,13 +107,12 @@ static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) | |||
| 107 | 107 | ||
| 108 | static int sh_tmu_enable(struct sh_tmu_priv *p) | 108 | static int sh_tmu_enable(struct sh_tmu_priv *p) |
| 109 | { | 109 | { |
| 110 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 111 | int ret; | 110 | int ret; |
| 112 | 111 | ||
| 113 | /* enable clock */ | 112 | /* enable clock */ |
| 114 | ret = clk_enable(p->clk); | 113 | ret = clk_enable(p->clk); |
| 115 | if (ret) { | 114 | if (ret) { |
| 116 | pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk); | 115 | dev_err(&p->pdev->dev, "cannot enable clock\n"); |
| 117 | return ret; | 116 | return ret; |
| 118 | } | 117 | } |
| 119 | 118 | ||
| @@ -229,7 +228,7 @@ static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, | |||
| 229 | cs->disable = sh_tmu_clocksource_disable; | 228 | cs->disable = sh_tmu_clocksource_disable; |
| 230 | cs->mask = CLOCKSOURCE_MASK(32); | 229 | cs->mask = CLOCKSOURCE_MASK(32); |
| 231 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; | 230 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; |
| 232 | pr_info("sh_tmu: %s used as clock source\n", cs->name); | 231 | dev_info(&p->pdev->dev, "used as clock source\n"); |
| 233 | clocksource_register(cs); | 232 | clocksource_register(cs); |
| 234 | return 0; | 233 | return 0; |
| 235 | } | 234 | } |
| @@ -277,13 +276,11 @@ static void sh_tmu_clock_event_mode(enum clock_event_mode mode, | |||
| 277 | 276 | ||
| 278 | switch (mode) { | 277 | switch (mode) { |
| 279 | case CLOCK_EVT_MODE_PERIODIC: | 278 | case CLOCK_EVT_MODE_PERIODIC: |
| 280 | pr_info("sh_tmu: %s used for periodic clock events\n", | 279 | dev_info(&p->pdev->dev, "used for periodic clock events\n"); |
| 281 | ced->name); | ||
| 282 | sh_tmu_clock_event_start(p, 1); | 280 | sh_tmu_clock_event_start(p, 1); |
| 283 | break; | 281 | break; |
| 284 | case CLOCK_EVT_MODE_ONESHOT: | 282 | case CLOCK_EVT_MODE_ONESHOT: |
| 285 | pr_info("sh_tmu: %s used for oneshot clock events\n", | 283 | dev_info(&p->pdev->dev, "used for oneshot clock events\n"); |
| 286 | ced->name); | ||
| 287 | sh_tmu_clock_event_start(p, 0); | 284 | sh_tmu_clock_event_start(p, 0); |
| 288 | break; | 285 | break; |
| 289 | case CLOCK_EVT_MODE_UNUSED: | 286 | case CLOCK_EVT_MODE_UNUSED: |
| @@ -324,13 +321,13 @@ static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, | |||
| 324 | ced->set_next_event = sh_tmu_clock_event_next; | 321 | ced->set_next_event = sh_tmu_clock_event_next; |
| 325 | ced->set_mode = sh_tmu_clock_event_mode; | 322 | ced->set_mode = sh_tmu_clock_event_mode; |
| 326 | 323 | ||
| 327 | pr_info("sh_tmu: %s used for clock events\n", ced->name); | 324 | dev_info(&p->pdev->dev, "used for clock events\n"); |
| 328 | clockevents_register_device(ced); | 325 | clockevents_register_device(ced); |
| 329 | 326 | ||
| 330 | ret = setup_irq(p->irqaction.irq, &p->irqaction); | 327 | ret = setup_irq(p->irqaction.irq, &p->irqaction); |
| 331 | if (ret) { | 328 | if (ret) { |
| 332 | pr_err("sh_tmu: failed to request irq %d\n", | 329 | dev_err(&p->pdev->dev, "failed to request irq %d\n", |
| 333 | p->irqaction.irq); | 330 | p->irqaction.irq); |
| 334 | return; | 331 | return; |
| 335 | } | 332 | } |
| 336 | } | 333 | } |
| @@ -379,26 +376,31 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) | |||
| 379 | /* map memory, let mapbase point to our channel */ | 376 | /* map memory, let mapbase point to our channel */ |
| 380 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | 377 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); |
| 381 | if (p->mapbase == NULL) { | 378 | if (p->mapbase == NULL) { |
| 382 | pr_err("sh_tmu: failed to remap I/O memory\n"); | 379 | dev_err(&p->pdev->dev, "failed to remap I/O memory\n"); |
| 383 | goto err0; | 380 | goto err0; |
| 384 | } | 381 | } |
| 385 | 382 | ||
| 386 | /* setup data for setup_irq() (too early for request_irq()) */ | 383 | /* setup data for setup_irq() (too early for request_irq()) */ |
| 387 | p->irqaction.name = cfg->name; | 384 | p->irqaction.name = dev_name(&p->pdev->dev); |
| 388 | p->irqaction.handler = sh_tmu_interrupt; | 385 | p->irqaction.handler = sh_tmu_interrupt; |
| 389 | p->irqaction.dev_id = p; | 386 | p->irqaction.dev_id = p; |
| 390 | p->irqaction.irq = irq; | 387 | p->irqaction.irq = irq; |
| 391 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | 388 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | \ |
| 389 | IRQF_IRQPOLL | IRQF_NOBALANCING; | ||
| 392 | 390 | ||
| 393 | /* get hold of clock */ | 391 | /* get hold of clock */ |
| 394 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | 392 | p->clk = clk_get(&p->pdev->dev, "tmu_fck"); |
| 395 | if (IS_ERR(p->clk)) { | 393 | if (IS_ERR(p->clk)) { |
| 396 | pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk); | 394 | dev_warn(&p->pdev->dev, "using deprecated clock lookup\n"); |
| 397 | ret = PTR_ERR(p->clk); | 395 | p->clk = clk_get(&p->pdev->dev, cfg->clk); |
| 398 | goto err1; | 396 | if (IS_ERR(p->clk)) { |
| 397 | dev_err(&p->pdev->dev, "cannot get clock\n"); | ||
| 398 | ret = PTR_ERR(p->clk); | ||
| 399 | goto err1; | ||
| 400 | } | ||
| 399 | } | 401 | } |
| 400 | 402 | ||
| 401 | return sh_tmu_register(p, cfg->name, | 403 | return sh_tmu_register(p, (char *)dev_name(&p->pdev->dev), |
| 402 | cfg->clockevent_rating, | 404 | cfg->clockevent_rating, |
| 403 | cfg->clocksource_rating); | 405 | cfg->clocksource_rating); |
| 404 | err1: | 406 | err1: |
| @@ -410,11 +412,10 @@ static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) | |||
| 410 | static int __devinit sh_tmu_probe(struct platform_device *pdev) | 412 | static int __devinit sh_tmu_probe(struct platform_device *pdev) |
| 411 | { | 413 | { |
| 412 | struct sh_tmu_priv *p = platform_get_drvdata(pdev); | 414 | struct sh_tmu_priv *p = platform_get_drvdata(pdev); |
| 413 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 414 | int ret; | 415 | int ret; |
| 415 | 416 | ||
| 416 | if (p) { | 417 | if (p) { |
| 417 | pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name); | 418 | dev_info(&pdev->dev, "kept as earlytimer\n"); |
| 418 | return 0; | 419 | return 0; |
| 419 | } | 420 | } |
| 420 | 421 | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 75d293eeb3ee..063b2184caf5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -662,32 +662,20 @@ static ssize_t show_bios_limit(struct cpufreq_policy *policy, char *buf) | |||
| 662 | return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); | 662 | return sprintf(buf, "%u\n", policy->cpuinfo.max_freq); |
| 663 | } | 663 | } |
| 664 | 664 | ||
| 665 | #define define_one_ro(_name) \ | 665 | cpufreq_freq_attr_ro_perm(cpuinfo_cur_freq, 0400); |
| 666 | static struct freq_attr _name = \ | 666 | cpufreq_freq_attr_ro(cpuinfo_min_freq); |
| 667 | __ATTR(_name, 0444, show_##_name, NULL) | 667 | cpufreq_freq_attr_ro(cpuinfo_max_freq); |
| 668 | 668 | cpufreq_freq_attr_ro(cpuinfo_transition_latency); | |
| 669 | #define define_one_ro0400(_name) \ | 669 | cpufreq_freq_attr_ro(scaling_available_governors); |
| 670 | static struct freq_attr _name = \ | 670 | cpufreq_freq_attr_ro(scaling_driver); |
| 671 | __ATTR(_name, 0400, show_##_name, NULL) | 671 | cpufreq_freq_attr_ro(scaling_cur_freq); |
| 672 | 672 | cpufreq_freq_attr_ro(bios_limit); | |
| 673 | #define define_one_rw(_name) \ | 673 | cpufreq_freq_attr_ro(related_cpus); |
| 674 | static struct freq_attr _name = \ | 674 | cpufreq_freq_attr_ro(affected_cpus); |
| 675 | __ATTR(_name, 0644, show_##_name, store_##_name) | 675 | cpufreq_freq_attr_rw(scaling_min_freq); |
| 676 | 676 | cpufreq_freq_attr_rw(scaling_max_freq); | |
| 677 | define_one_ro0400(cpuinfo_cur_freq); | 677 | cpufreq_freq_attr_rw(scaling_governor); |
| 678 | define_one_ro(cpuinfo_min_freq); | 678 | cpufreq_freq_attr_rw(scaling_setspeed); |
| 679 | define_one_ro(cpuinfo_max_freq); | ||
| 680 | define_one_ro(cpuinfo_transition_latency); | ||
| 681 | define_one_ro(scaling_available_governors); | ||
| 682 | define_one_ro(scaling_driver); | ||
| 683 | define_one_ro(scaling_cur_freq); | ||
| 684 | define_one_ro(bios_limit); | ||
| 685 | define_one_ro(related_cpus); | ||
| 686 | define_one_ro(affected_cpus); | ||
| 687 | define_one_rw(scaling_min_freq); | ||
| 688 | define_one_rw(scaling_max_freq); | ||
| 689 | define_one_rw(scaling_governor); | ||
| 690 | define_one_rw(scaling_setspeed); | ||
| 691 | 679 | ||
| 692 | static struct attribute *default_attrs[] = { | 680 | static struct attribute *default_attrs[] = { |
| 693 | &cpuinfo_min_freq.attr, | 681 | &cpuinfo_min_freq.attr, |
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 3a147874a465..526bfbf69611 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c | |||
| @@ -178,12 +178,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, | |||
| 178 | return sprintf(buf, "%u\n", min_sampling_rate); | 178 | return sprintf(buf, "%u\n", min_sampling_rate); |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | #define define_one_ro(_name) \ | 181 | define_one_global_ro(sampling_rate_max); |
| 182 | static struct global_attr _name = \ | 182 | define_one_global_ro(sampling_rate_min); |
| 183 | __ATTR(_name, 0444, show_##_name, NULL) | ||
| 184 | |||
| 185 | define_one_ro(sampling_rate_max); | ||
| 186 | define_one_ro(sampling_rate_min); | ||
| 187 | 183 | ||
| 188 | /* cpufreq_conservative Governor Tunables */ | 184 | /* cpufreq_conservative Governor Tunables */ |
| 189 | #define show_one(file_name, object) \ | 185 | #define show_one(file_name, object) \ |
| @@ -221,12 +217,8 @@ show_one_old(freq_step); | |||
| 221 | show_one_old(sampling_rate_min); | 217 | show_one_old(sampling_rate_min); |
| 222 | show_one_old(sampling_rate_max); | 218 | show_one_old(sampling_rate_max); |
| 223 | 219 | ||
| 224 | #define define_one_ro_old(object, _name) \ | 220 | cpufreq_freq_attr_ro_old(sampling_rate_min); |
| 225 | static struct freq_attr object = \ | 221 | cpufreq_freq_attr_ro_old(sampling_rate_max); |
| 226 | __ATTR(_name, 0444, show_##_name##_old, NULL) | ||
| 227 | |||
| 228 | define_one_ro_old(sampling_rate_min_old, sampling_rate_min); | ||
| 229 | define_one_ro_old(sampling_rate_max_old, sampling_rate_max); | ||
| 230 | 222 | ||
| 231 | /*** delete after deprecation time ***/ | 223 | /*** delete after deprecation time ***/ |
| 232 | 224 | ||
| @@ -364,16 +356,12 @@ static ssize_t store_freq_step(struct kobject *a, struct attribute *b, | |||
| 364 | return count; | 356 | return count; |
| 365 | } | 357 | } |
| 366 | 358 | ||
| 367 | #define define_one_rw(_name) \ | 359 | define_one_global_rw(sampling_rate); |
| 368 | static struct global_attr _name = \ | 360 | define_one_global_rw(sampling_down_factor); |
| 369 | __ATTR(_name, 0644, show_##_name, store_##_name) | 361 | define_one_global_rw(up_threshold); |
| 370 | 362 | define_one_global_rw(down_threshold); | |
| 371 | define_one_rw(sampling_rate); | 363 | define_one_global_rw(ignore_nice_load); |
| 372 | define_one_rw(sampling_down_factor); | 364 | define_one_global_rw(freq_step); |
| 373 | define_one_rw(up_threshold); | ||
| 374 | define_one_rw(down_threshold); | ||
| 375 | define_one_rw(ignore_nice_load); | ||
| 376 | define_one_rw(freq_step); | ||
| 377 | 365 | ||
| 378 | static struct attribute *dbs_attributes[] = { | 366 | static struct attribute *dbs_attributes[] = { |
| 379 | &sampling_rate_max.attr, | 367 | &sampling_rate_max.attr, |
| @@ -409,16 +397,12 @@ write_one_old(down_threshold); | |||
| 409 | write_one_old(ignore_nice_load); | 397 | write_one_old(ignore_nice_load); |
| 410 | write_one_old(freq_step); | 398 | write_one_old(freq_step); |
| 411 | 399 | ||
| 412 | #define define_one_rw_old(object, _name) \ | 400 | cpufreq_freq_attr_rw_old(sampling_rate); |
| 413 | static struct freq_attr object = \ | 401 | cpufreq_freq_attr_rw_old(sampling_down_factor); |
| 414 | __ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) | 402 | cpufreq_freq_attr_rw_old(up_threshold); |
| 415 | 403 | cpufreq_freq_attr_rw_old(down_threshold); | |
| 416 | define_one_rw_old(sampling_rate_old, sampling_rate); | 404 | cpufreq_freq_attr_rw_old(ignore_nice_load); |
| 417 | define_one_rw_old(sampling_down_factor_old, sampling_down_factor); | 405 | cpufreq_freq_attr_rw_old(freq_step); |
| 418 | define_one_rw_old(up_threshold_old, up_threshold); | ||
| 419 | define_one_rw_old(down_threshold_old, down_threshold); | ||
| 420 | define_one_rw_old(ignore_nice_load_old, ignore_nice_load); | ||
| 421 | define_one_rw_old(freq_step_old, freq_step); | ||
| 422 | 406 | ||
| 423 | static struct attribute *dbs_attributes_old[] = { | 407 | static struct attribute *dbs_attributes_old[] = { |
| 424 | &sampling_rate_max_old.attr, | 408 | &sampling_rate_max_old.attr, |
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index bd444dc93cf2..e1314212d8d4 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c | |||
| @@ -73,6 +73,7 @@ enum {DBS_NORMAL_SAMPLE, DBS_SUB_SAMPLE}; | |||
| 73 | 73 | ||
| 74 | struct cpu_dbs_info_s { | 74 | struct cpu_dbs_info_s { |
| 75 | cputime64_t prev_cpu_idle; | 75 | cputime64_t prev_cpu_idle; |
| 76 | cputime64_t prev_cpu_iowait; | ||
| 76 | cputime64_t prev_cpu_wall; | 77 | cputime64_t prev_cpu_wall; |
| 77 | cputime64_t prev_cpu_nice; | 78 | cputime64_t prev_cpu_nice; |
| 78 | struct cpufreq_policy *cur_policy; | 79 | struct cpufreq_policy *cur_policy; |
| @@ -108,6 +109,7 @@ static struct dbs_tuners { | |||
| 108 | unsigned int down_differential; | 109 | unsigned int down_differential; |
| 109 | unsigned int ignore_nice; | 110 | unsigned int ignore_nice; |
| 110 | unsigned int powersave_bias; | 111 | unsigned int powersave_bias; |
| 112 | unsigned int io_is_busy; | ||
| 111 | } dbs_tuners_ins = { | 113 | } dbs_tuners_ins = { |
| 112 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, | 114 | .up_threshold = DEF_FREQUENCY_UP_THRESHOLD, |
| 113 | .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, | 115 | .down_differential = DEF_FREQUENCY_DOWN_DIFFERENTIAL, |
| @@ -148,6 +150,16 @@ static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall) | |||
| 148 | return idle_time; | 150 | return idle_time; |
| 149 | } | 151 | } |
| 150 | 152 | ||
| 153 | static inline cputime64_t get_cpu_iowait_time(unsigned int cpu, cputime64_t *wall) | ||
| 154 | { | ||
| 155 | u64 iowait_time = get_cpu_iowait_time_us(cpu, wall); | ||
| 156 | |||
| 157 | if (iowait_time == -1ULL) | ||
| 158 | return 0; | ||
| 159 | |||
| 160 | return iowait_time; | ||
| 161 | } | ||
| 162 | |||
| 151 | /* | 163 | /* |
| 152 | * Find right freq to be set now with powersave_bias on. | 164 | * Find right freq to be set now with powersave_bias on. |
| 153 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, | 165 | * Returns the freq_hi to be used right now and will set freq_hi_jiffies, |
| @@ -234,12 +246,8 @@ static ssize_t show_sampling_rate_min(struct kobject *kobj, | |||
| 234 | return sprintf(buf, "%u\n", min_sampling_rate); | 246 | return sprintf(buf, "%u\n", min_sampling_rate); |
| 235 | } | 247 | } |
| 236 | 248 | ||
| 237 | #define define_one_ro(_name) \ | 249 | define_one_global_ro(sampling_rate_max); |
| 238 | static struct global_attr _name = \ | 250 | define_one_global_ro(sampling_rate_min); |
| 239 | __ATTR(_name, 0444, show_##_name, NULL) | ||
| 240 | |||
| 241 | define_one_ro(sampling_rate_max); | ||
| 242 | define_one_ro(sampling_rate_min); | ||
| 243 | 251 | ||
| 244 | /* cpufreq_ondemand Governor Tunables */ | 252 | /* cpufreq_ondemand Governor Tunables */ |
| 245 | #define show_one(file_name, object) \ | 253 | #define show_one(file_name, object) \ |
| @@ -249,6 +257,7 @@ static ssize_t show_##file_name \ | |||
| 249 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ | 257 | return sprintf(buf, "%u\n", dbs_tuners_ins.object); \ |
| 250 | } | 258 | } |
| 251 | show_one(sampling_rate, sampling_rate); | 259 | show_one(sampling_rate, sampling_rate); |
| 260 | show_one(io_is_busy, io_is_busy); | ||
| 252 | show_one(up_threshold, up_threshold); | 261 | show_one(up_threshold, up_threshold); |
| 253 | show_one(ignore_nice_load, ignore_nice); | 262 | show_one(ignore_nice_load, ignore_nice); |
| 254 | show_one(powersave_bias, powersave_bias); | 263 | show_one(powersave_bias, powersave_bias); |
| @@ -274,12 +283,8 @@ show_one_old(powersave_bias); | |||
| 274 | show_one_old(sampling_rate_min); | 283 | show_one_old(sampling_rate_min); |
| 275 | show_one_old(sampling_rate_max); | 284 | show_one_old(sampling_rate_max); |
| 276 | 285 | ||
| 277 | #define define_one_ro_old(object, _name) \ | 286 | cpufreq_freq_attr_ro_old(sampling_rate_min); |
| 278 | static struct freq_attr object = \ | 287 | cpufreq_freq_attr_ro_old(sampling_rate_max); |
| 279 | __ATTR(_name, 0444, show_##_name##_old, NULL) | ||
| 280 | |||
| 281 | define_one_ro_old(sampling_rate_min_old, sampling_rate_min); | ||
| 282 | define_one_ro_old(sampling_rate_max_old, sampling_rate_max); | ||
| 283 | 288 | ||
| 284 | /*** delete after deprecation time ***/ | 289 | /*** delete after deprecation time ***/ |
| 285 | 290 | ||
| @@ -299,6 +304,23 @@ static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b, | |||
| 299 | return count; | 304 | return count; |
| 300 | } | 305 | } |
| 301 | 306 | ||
| 307 | static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b, | ||
| 308 | const char *buf, size_t count) | ||
| 309 | { | ||
| 310 | unsigned int input; | ||
| 311 | int ret; | ||
| 312 | |||
| 313 | ret = sscanf(buf, "%u", &input); | ||
| 314 | if (ret != 1) | ||
| 315 | return -EINVAL; | ||
| 316 | |||
| 317 | mutex_lock(&dbs_mutex); | ||
| 318 | dbs_tuners_ins.io_is_busy = !!input; | ||
| 319 | mutex_unlock(&dbs_mutex); | ||
| 320 | |||
| 321 | return count; | ||
| 322 | } | ||
| 323 | |||
| 302 | static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, | 324 | static ssize_t store_up_threshold(struct kobject *a, struct attribute *b, |
| 303 | const char *buf, size_t count) | 325 | const char *buf, size_t count) |
| 304 | { | 326 | { |
| @@ -376,14 +398,11 @@ static ssize_t store_powersave_bias(struct kobject *a, struct attribute *b, | |||
| 376 | return count; | 398 | return count; |
| 377 | } | 399 | } |
| 378 | 400 | ||
| 379 | #define define_one_rw(_name) \ | 401 | define_one_global_rw(sampling_rate); |
| 380 | static struct global_attr _name = \ | 402 | define_one_global_rw(io_is_busy); |
| 381 | __ATTR(_name, 0644, show_##_name, store_##_name) | 403 | define_one_global_rw(up_threshold); |
| 382 | 404 | define_one_global_rw(ignore_nice_load); | |
| 383 | define_one_rw(sampling_rate); | 405 | define_one_global_rw(powersave_bias); |
| 384 | define_one_rw(up_threshold); | ||
| 385 | define_one_rw(ignore_nice_load); | ||
| 386 | define_one_rw(powersave_bias); | ||
| 387 | 406 | ||
| 388 | static struct attribute *dbs_attributes[] = { | 407 | static struct attribute *dbs_attributes[] = { |
| 389 | &sampling_rate_max.attr, | 408 | &sampling_rate_max.attr, |
| @@ -392,6 +411,7 @@ static struct attribute *dbs_attributes[] = { | |||
| 392 | &up_threshold.attr, | 411 | &up_threshold.attr, |
| 393 | &ignore_nice_load.attr, | 412 | &ignore_nice_load.attr, |
| 394 | &powersave_bias.attr, | 413 | &powersave_bias.attr, |
| 414 | &io_is_busy.attr, | ||
| 395 | NULL | 415 | NULL |
| 396 | }; | 416 | }; |
| 397 | 417 | ||
| @@ -415,14 +435,10 @@ write_one_old(up_threshold); | |||
| 415 | write_one_old(ignore_nice_load); | 435 | write_one_old(ignore_nice_load); |
| 416 | write_one_old(powersave_bias); | 436 | write_one_old(powersave_bias); |
| 417 | 437 | ||
| 418 | #define define_one_rw_old(object, _name) \ | 438 | cpufreq_freq_attr_rw_old(sampling_rate); |
| 419 | static struct freq_attr object = \ | 439 | cpufreq_freq_attr_rw_old(up_threshold); |
| 420 | __ATTR(_name, 0644, show_##_name##_old, store_##_name##_old) | 440 | cpufreq_freq_attr_rw_old(ignore_nice_load); |
| 421 | 441 | cpufreq_freq_attr_rw_old(powersave_bias); | |
| 422 | define_one_rw_old(sampling_rate_old, sampling_rate); | ||
| 423 | define_one_rw_old(up_threshold_old, up_threshold); | ||
| 424 | define_one_rw_old(ignore_nice_load_old, ignore_nice_load); | ||
| 425 | define_one_rw_old(powersave_bias_old, powersave_bias); | ||
| 426 | 442 | ||
| 427 | static struct attribute *dbs_attributes_old[] = { | 443 | static struct attribute *dbs_attributes_old[] = { |
| 428 | &sampling_rate_max_old.attr, | 444 | &sampling_rate_max_old.attr, |
| @@ -470,14 +486,15 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 470 | 486 | ||
| 471 | for_each_cpu(j, policy->cpus) { | 487 | for_each_cpu(j, policy->cpus) { |
| 472 | struct cpu_dbs_info_s *j_dbs_info; | 488 | struct cpu_dbs_info_s *j_dbs_info; |
| 473 | cputime64_t cur_wall_time, cur_idle_time; | 489 | cputime64_t cur_wall_time, cur_idle_time, cur_iowait_time; |
| 474 | unsigned int idle_time, wall_time; | 490 | unsigned int idle_time, wall_time, iowait_time; |
| 475 | unsigned int load, load_freq; | 491 | unsigned int load, load_freq; |
| 476 | int freq_avg; | 492 | int freq_avg; |
| 477 | 493 | ||
| 478 | j_dbs_info = &per_cpu(od_cpu_dbs_info, j); | 494 | j_dbs_info = &per_cpu(od_cpu_dbs_info, j); |
| 479 | 495 | ||
| 480 | cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); | 496 | cur_idle_time = get_cpu_idle_time(j, &cur_wall_time); |
| 497 | cur_iowait_time = get_cpu_iowait_time(j, &cur_wall_time); | ||
| 481 | 498 | ||
| 482 | wall_time = (unsigned int) cputime64_sub(cur_wall_time, | 499 | wall_time = (unsigned int) cputime64_sub(cur_wall_time, |
| 483 | j_dbs_info->prev_cpu_wall); | 500 | j_dbs_info->prev_cpu_wall); |
| @@ -487,6 +504,10 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 487 | j_dbs_info->prev_cpu_idle); | 504 | j_dbs_info->prev_cpu_idle); |
| 488 | j_dbs_info->prev_cpu_idle = cur_idle_time; | 505 | j_dbs_info->prev_cpu_idle = cur_idle_time; |
| 489 | 506 | ||
| 507 | iowait_time = (unsigned int) cputime64_sub(cur_iowait_time, | ||
| 508 | j_dbs_info->prev_cpu_iowait); | ||
| 509 | j_dbs_info->prev_cpu_iowait = cur_iowait_time; | ||
| 510 | |||
| 490 | if (dbs_tuners_ins.ignore_nice) { | 511 | if (dbs_tuners_ins.ignore_nice) { |
| 491 | cputime64_t cur_nice; | 512 | cputime64_t cur_nice; |
| 492 | unsigned long cur_nice_jiffies; | 513 | unsigned long cur_nice_jiffies; |
| @@ -504,6 +525,16 @@ static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info) | |||
| 504 | idle_time += jiffies_to_usecs(cur_nice_jiffies); | 525 | idle_time += jiffies_to_usecs(cur_nice_jiffies); |
| 505 | } | 526 | } |
| 506 | 527 | ||
| 528 | /* | ||
| 529 | * For the purpose of ondemand, waiting for disk IO is an | ||
| 530 | * indication that you're performance critical, and not that | ||
| 531 | * the system is actually idle. So subtract the iowait time | ||
| 532 | * from the cpu idle time. | ||
| 533 | */ | ||
| 534 | |||
| 535 | if (dbs_tuners_ins.io_is_busy && idle_time >= iowait_time) | ||
| 536 | idle_time -= iowait_time; | ||
| 537 | |||
| 507 | if (unlikely(!wall_time || wall_time < idle_time)) | 538 | if (unlikely(!wall_time || wall_time < idle_time)) |
| 508 | continue; | 539 | continue; |
| 509 | 540 | ||
| @@ -617,6 +648,29 @@ static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info) | |||
| 617 | cancel_delayed_work_sync(&dbs_info->work); | 648 | cancel_delayed_work_sync(&dbs_info->work); |
| 618 | } | 649 | } |
| 619 | 650 | ||
| 651 | /* | ||
| 652 | * Not all CPUs want IO time to be accounted as busy; this dependson how | ||
| 653 | * efficient idling at a higher frequency/voltage is. | ||
| 654 | * Pavel Machek says this is not so for various generations of AMD and old | ||
| 655 | * Intel systems. | ||
| 656 | * Mike Chan (androidlcom) calis this is also not true for ARM. | ||
| 657 | * Because of this, whitelist specific known (series) of CPUs by default, and | ||
| 658 | * leave all others up to the user. | ||
| 659 | */ | ||
| 660 | static int should_io_be_busy(void) | ||
| 661 | { | ||
| 662 | #if defined(CONFIG_X86) | ||
| 663 | /* | ||
| 664 | * For Intel, Core 2 (model 15) andl later have an efficient idle. | ||
| 665 | */ | ||
| 666 | if (boot_cpu_data.x86_vendor == X86_VENDOR_INTEL && | ||
| 667 | boot_cpu_data.x86 == 6 && | ||
| 668 | boot_cpu_data.x86_model >= 15) | ||
| 669 | return 1; | ||
| 670 | #endif | ||
| 671 | return 0; | ||
| 672 | } | ||
| 673 | |||
| 620 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | 674 | static int cpufreq_governor_dbs(struct cpufreq_policy *policy, |
| 621 | unsigned int event) | 675 | unsigned int event) |
| 622 | { | 676 | { |
| @@ -679,6 +733,7 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy, | |||
| 679 | dbs_tuners_ins.sampling_rate = | 733 | dbs_tuners_ins.sampling_rate = |
| 680 | max(min_sampling_rate, | 734 | max(min_sampling_rate, |
| 681 | latency * LATENCY_MULTIPLIER); | 735 | latency * LATENCY_MULTIPLIER); |
| 736 | dbs_tuners_ins.io_is_busy = should_io_be_busy(); | ||
| 682 | } | 737 | } |
| 683 | mutex_unlock(&dbs_mutex); | 738 | mutex_unlock(&dbs_mutex); |
| 684 | 739 | ||
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 1aea7157d8ff..f8e57c6303f2 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
| @@ -100,7 +100,6 @@ struct menu_device { | |||
| 100 | int needs_update; | 100 | int needs_update; |
| 101 | 101 | ||
| 102 | unsigned int expected_us; | 102 | unsigned int expected_us; |
| 103 | unsigned int measured_us; | ||
| 104 | u64 predicted_us; | 103 | u64 predicted_us; |
| 105 | unsigned int exit_us; | 104 | unsigned int exit_us; |
| 106 | unsigned int bucket; | 105 | unsigned int bucket; |
| @@ -187,14 +186,14 @@ static int menu_select(struct cpuidle_device *dev) | |||
| 187 | int i; | 186 | int i; |
| 188 | int multiplier; | 187 | int multiplier; |
| 189 | 188 | ||
| 190 | data->last_state_idx = 0; | ||
| 191 | data->exit_us = 0; | ||
| 192 | |||
| 193 | if (data->needs_update) { | 189 | if (data->needs_update) { |
| 194 | menu_update(dev); | 190 | menu_update(dev); |
| 195 | data->needs_update = 0; | 191 | data->needs_update = 0; |
| 196 | } | 192 | } |
| 197 | 193 | ||
| 194 | data->last_state_idx = 0; | ||
| 195 | data->exit_us = 0; | ||
| 196 | |||
| 198 | /* Special case when user has set very strict latency requirement */ | 197 | /* Special case when user has set very strict latency requirement */ |
| 199 | if (unlikely(latency_req == 0)) | 198 | if (unlikely(latency_req == 0)) |
| 200 | return 0; | 199 | return 0; |
| @@ -294,7 +293,7 @@ static void menu_update(struct cpuidle_device *dev) | |||
| 294 | new_factor = data->correction_factor[data->bucket] | 293 | new_factor = data->correction_factor[data->bucket] |
| 295 | * (DECAY - 1) / DECAY; | 294 | * (DECAY - 1) / DECAY; |
| 296 | 295 | ||
| 297 | if (data->expected_us > 0 && data->measured_us < MAX_INTERESTING) | 296 | if (data->expected_us > 0 && measured_us < MAX_INTERESTING) |
| 298 | new_factor += RESOLUTION * measured_us / data->expected_us; | 297 | new_factor += RESOLUTION * measured_us / data->expected_us; |
| 299 | else | 298 | else |
| 300 | /* | 299 | /* |
diff --git a/drivers/dma/shdma.c b/drivers/dma/shdma.c index 7cc31b3f40d8..323afef77802 100644 --- a/drivers/dma/shdma.c +++ b/drivers/dma/shdma.c | |||
| @@ -26,8 +26,7 @@ | |||
| 26 | #include <linux/dma-mapping.h> | 26 | #include <linux/dma-mapping.h> |
| 27 | #include <linux/platform_device.h> | 27 | #include <linux/platform_device.h> |
| 28 | #include <linux/pm_runtime.h> | 28 | #include <linux/pm_runtime.h> |
| 29 | 29 | #include <linux/sh_dma.h> | |
| 30 | #include <asm/dmaengine.h> | ||
| 31 | 30 | ||
| 32 | #include "shdma.h" | 31 | #include "shdma.h" |
| 33 | 32 | ||
| @@ -45,7 +44,7 @@ enum sh_dmae_desc_status { | |||
| 45 | #define LOG2_DEFAULT_XFER_SIZE 2 | 44 | #define LOG2_DEFAULT_XFER_SIZE 2 |
| 46 | 45 | ||
| 47 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ | 46 | /* A bitmask with bits enough for enum sh_dmae_slave_chan_id */ |
| 48 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SHDMA_SLAVE_NUMBER)]; | 47 | static unsigned long sh_dmae_slave_used[BITS_TO_LONGS(SH_DMA_SLAVE_NUMBER)]; |
| 49 | 48 | ||
| 50 | static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); | 49 | static void sh_dmae_chan_ld_cleanup(struct sh_dmae_chan *sh_chan, bool all); |
| 51 | 50 | ||
| @@ -190,7 +189,7 @@ static int dmae_set_dmars(struct sh_dmae_chan *sh_chan, u16 val) | |||
| 190 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, | 189 | struct sh_dmae_device *shdev = container_of(sh_chan->common.device, |
| 191 | struct sh_dmae_device, common); | 190 | struct sh_dmae_device, common); |
| 192 | struct sh_dmae_pdata *pdata = shdev->pdata; | 191 | struct sh_dmae_pdata *pdata = shdev->pdata; |
| 193 | struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; | 192 | const struct sh_dmae_channel *chan_pdata = &pdata->channel[sh_chan->id]; |
| 194 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); | 193 | u16 __iomem *addr = shdev->dmars + chan_pdata->dmars / sizeof(u16); |
| 195 | int shift = chan_pdata->dmars_bit; | 194 | int shift = chan_pdata->dmars_bit; |
| 196 | 195 | ||
| @@ -266,8 +265,8 @@ static struct sh_desc *sh_dmae_get_desc(struct sh_dmae_chan *sh_chan) | |||
| 266 | return NULL; | 265 | return NULL; |
| 267 | } | 266 | } |
| 268 | 267 | ||
| 269 | static struct sh_dmae_slave_config *sh_dmae_find_slave( | 268 | static const struct sh_dmae_slave_config *sh_dmae_find_slave( |
| 270 | struct sh_dmae_chan *sh_chan, enum sh_dmae_slave_chan_id slave_id) | 269 | struct sh_dmae_chan *sh_chan, struct sh_dmae_slave *param) |
| 271 | { | 270 | { |
| 272 | struct dma_device *dma_dev = sh_chan->common.device; | 271 | struct dma_device *dma_dev = sh_chan->common.device; |
| 273 | struct sh_dmae_device *shdev = container_of(dma_dev, | 272 | struct sh_dmae_device *shdev = container_of(dma_dev, |
| @@ -275,11 +274,11 @@ static struct sh_dmae_slave_config *sh_dmae_find_slave( | |||
| 275 | struct sh_dmae_pdata *pdata = shdev->pdata; | 274 | struct sh_dmae_pdata *pdata = shdev->pdata; |
| 276 | int i; | 275 | int i; |
| 277 | 276 | ||
| 278 | if ((unsigned)slave_id >= SHDMA_SLAVE_NUMBER) | 277 | if (param->slave_id >= SH_DMA_SLAVE_NUMBER) |
| 279 | return NULL; | 278 | return NULL; |
| 280 | 279 | ||
| 281 | for (i = 0; i < pdata->slave_num; i++) | 280 | for (i = 0; i < pdata->slave_num; i++) |
| 282 | if (pdata->slave[i].slave_id == slave_id) | 281 | if (pdata->slave[i].slave_id == param->slave_id) |
| 283 | return pdata->slave + i; | 282 | return pdata->slave + i; |
| 284 | 283 | ||
| 285 | return NULL; | 284 | return NULL; |
| @@ -290,6 +289,7 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
| 290 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); | 289 | struct sh_dmae_chan *sh_chan = to_sh_chan(chan); |
| 291 | struct sh_desc *desc; | 290 | struct sh_desc *desc; |
| 292 | struct sh_dmae_slave *param = chan->private; | 291 | struct sh_dmae_slave *param = chan->private; |
| 292 | int ret; | ||
| 293 | 293 | ||
| 294 | pm_runtime_get_sync(sh_chan->dev); | 294 | pm_runtime_get_sync(sh_chan->dev); |
| 295 | 295 | ||
| @@ -298,14 +298,18 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
| 298 | * never runs concurrently with itself or free_chan_resources. | 298 | * never runs concurrently with itself or free_chan_resources. |
| 299 | */ | 299 | */ |
| 300 | if (param) { | 300 | if (param) { |
| 301 | struct sh_dmae_slave_config *cfg; | 301 | const struct sh_dmae_slave_config *cfg; |
| 302 | 302 | ||
| 303 | cfg = sh_dmae_find_slave(sh_chan, param->slave_id); | 303 | cfg = sh_dmae_find_slave(sh_chan, param); |
| 304 | if (!cfg) | 304 | if (!cfg) { |
| 305 | return -EINVAL; | 305 | ret = -EINVAL; |
| 306 | goto efindslave; | ||
| 307 | } | ||
| 306 | 308 | ||
| 307 | if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) | 309 | if (test_and_set_bit(param->slave_id, sh_dmae_slave_used)) { |
| 308 | return -EBUSY; | 310 | ret = -EBUSY; |
| 311 | goto etestused; | ||
| 312 | } | ||
| 309 | 313 | ||
| 310 | param->config = cfg; | 314 | param->config = cfg; |
| 311 | 315 | ||
| @@ -334,10 +338,20 @@ static int sh_dmae_alloc_chan_resources(struct dma_chan *chan) | |||
| 334 | } | 338 | } |
| 335 | spin_unlock_bh(&sh_chan->desc_lock); | 339 | spin_unlock_bh(&sh_chan->desc_lock); |
| 336 | 340 | ||
| 337 | if (!sh_chan->descs_allocated) | 341 | if (!sh_chan->descs_allocated) { |
| 338 | pm_runtime_put(sh_chan->dev); | 342 | ret = -ENOMEM; |
| 343 | goto edescalloc; | ||
| 344 | } | ||
| 339 | 345 | ||
| 340 | return sh_chan->descs_allocated; | 346 | return sh_chan->descs_allocated; |
| 347 | |||
| 348 | edescalloc: | ||
| 349 | if (param) | ||
| 350 | clear_bit(param->slave_id, sh_dmae_slave_used); | ||
| 351 | etestused: | ||
| 352 | efindslave: | ||
| 353 | pm_runtime_put(sh_chan->dev); | ||
| 354 | return ret; | ||
| 341 | } | 355 | } |
| 342 | 356 | ||
| 343 | /* | 357 | /* |
| @@ -559,12 +573,14 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
| 559 | { | 573 | { |
| 560 | struct sh_dmae_slave *param; | 574 | struct sh_dmae_slave *param; |
| 561 | struct sh_dmae_chan *sh_chan; | 575 | struct sh_dmae_chan *sh_chan; |
| 576 | dma_addr_t slave_addr; | ||
| 562 | 577 | ||
| 563 | if (!chan) | 578 | if (!chan) |
| 564 | return NULL; | 579 | return NULL; |
| 565 | 580 | ||
| 566 | sh_chan = to_sh_chan(chan); | 581 | sh_chan = to_sh_chan(chan); |
| 567 | param = chan->private; | 582 | param = chan->private; |
| 583 | slave_addr = param->config->addr; | ||
| 568 | 584 | ||
| 569 | /* Someone calling slave DMA on a public channel? */ | 585 | /* Someone calling slave DMA on a public channel? */ |
| 570 | if (!param || !sg_len) { | 586 | if (!param || !sg_len) { |
| @@ -577,7 +593,7 @@ static struct dma_async_tx_descriptor *sh_dmae_prep_slave_sg( | |||
| 577 | * if (param != NULL), this is a successfully requested slave channel, | 593 | * if (param != NULL), this is a successfully requested slave channel, |
| 578 | * therefore param->config != NULL too. | 594 | * therefore param->config != NULL too. |
| 579 | */ | 595 | */ |
| 580 | return sh_dmae_prep_sg(sh_chan, sgl, sg_len, ¶m->config->addr, | 596 | return sh_dmae_prep_sg(sh_chan, sgl, sg_len, &slave_addr, |
| 581 | direction, flags); | 597 | direction, flags); |
| 582 | } | 598 | } |
| 583 | 599 | ||
| @@ -858,7 +874,7 @@ static int __devinit sh_dmae_chan_probe(struct sh_dmae_device *shdev, int id, | |||
| 858 | int irq, unsigned long flags) | 874 | int irq, unsigned long flags) |
| 859 | { | 875 | { |
| 860 | int err; | 876 | int err; |
| 861 | struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; | 877 | const struct sh_dmae_channel *chan_pdata = &shdev->pdata->channel[id]; |
| 862 | struct platform_device *pdev = to_platform_device(shdev->common.dev); | 878 | struct platform_device *pdev = to_platform_device(shdev->common.dev); |
| 863 | struct sh_dmae_chan *new_sh_chan; | 879 | struct sh_dmae_chan *new_sh_chan; |
| 864 | 880 | ||
diff --git a/drivers/dma/shdma.h b/drivers/dma/shdma.h index 153609a1e96c..4021275a0a43 100644 --- a/drivers/dma/shdma.h +++ b/drivers/dma/shdma.h | |||
| @@ -17,8 +17,8 @@ | |||
| 17 | #include <linux/interrupt.h> | 17 | #include <linux/interrupt.h> |
| 18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
| 19 | 19 | ||
| 20 | #include <asm/dmaengine.h> | 20 | #define SH_DMAC_MAX_CHANNELS 6 |
| 21 | 21 | #define SH_DMA_SLAVE_NUMBER 256 | |
| 22 | #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ | 22 | #define SH_DMA_TCR_MAX 0x00FFFFFF /* 16MB */ |
| 23 | 23 | ||
| 24 | struct device; | 24 | struct device; |
diff --git a/drivers/gpio/it8761e_gpio.c b/drivers/gpio/it8761e_gpio.c index 753219cf993a..41a9388f2fde 100644 --- a/drivers/gpio/it8761e_gpio.c +++ b/drivers/gpio/it8761e_gpio.c | |||
| @@ -80,8 +80,8 @@ static int it8761e_gpio_get(struct gpio_chip *gc, unsigned gpio_num) | |||
| 80 | u16 reg; | 80 | u16 reg; |
| 81 | u8 bit; | 81 | u8 bit; |
| 82 | 82 | ||
| 83 | bit = gpio_num % 7; | 83 | bit = gpio_num % 8; |
| 84 | reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; | 84 | reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; |
| 85 | 85 | ||
| 86 | return !!(inb(reg) & (1 << bit)); | 86 | return !!(inb(reg) & (1 << bit)); |
| 87 | } | 87 | } |
| @@ -91,8 +91,8 @@ static int it8761e_gpio_direction_in(struct gpio_chip *gc, unsigned gpio_num) | |||
| 91 | u8 curr_dirs; | 91 | u8 curr_dirs; |
| 92 | u8 io_reg, bit; | 92 | u8 io_reg, bit; |
| 93 | 93 | ||
| 94 | bit = gpio_num % 7; | 94 | bit = gpio_num % 8; |
| 95 | io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; | 95 | io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; |
| 96 | 96 | ||
| 97 | spin_lock(&sio_lock); | 97 | spin_lock(&sio_lock); |
| 98 | 98 | ||
| @@ -116,8 +116,8 @@ static void it8761e_gpio_set(struct gpio_chip *gc, | |||
| 116 | u8 curr_vals, bit; | 116 | u8 curr_vals, bit; |
| 117 | u16 reg; | 117 | u16 reg; |
| 118 | 118 | ||
| 119 | bit = gpio_num % 7; | 119 | bit = gpio_num % 8; |
| 120 | reg = (gpio_num >= 7) ? gpio_ba + 1 : gpio_ba; | 120 | reg = (gpio_num >= 8) ? gpio_ba + 1 : gpio_ba; |
| 121 | 121 | ||
| 122 | spin_lock(&sio_lock); | 122 | spin_lock(&sio_lock); |
| 123 | 123 | ||
| @@ -135,8 +135,8 @@ static int it8761e_gpio_direction_out(struct gpio_chip *gc, | |||
| 135 | { | 135 | { |
| 136 | u8 curr_dirs, io_reg, bit; | 136 | u8 curr_dirs, io_reg, bit; |
| 137 | 137 | ||
| 138 | bit = gpio_num % 7; | 138 | bit = gpio_num % 8; |
| 139 | io_reg = (gpio_num >= 7) ? GPIO2X_IO : GPIO1X_IO; | 139 | io_reg = (gpio_num >= 8) ? GPIO2X_IO : GPIO1X_IO; |
| 140 | 140 | ||
| 141 | it8761e_gpio_set(gc, gpio_num, val); | 141 | it8761e_gpio_set(gc, gpio_num, val); |
| 142 | 142 | ||
| @@ -200,7 +200,7 @@ static int __init it8761e_gpio_init(void) | |||
| 200 | return -EBUSY; | 200 | return -EBUSY; |
| 201 | 201 | ||
| 202 | it8761e_gpio_chip.base = -1; | 202 | it8761e_gpio_chip.base = -1; |
| 203 | it8761e_gpio_chip.ngpio = 14; | 203 | it8761e_gpio_chip.ngpio = 16; |
| 204 | 204 | ||
| 205 | err = gpiochip_add(&it8761e_gpio_chip); | 205 | err = gpiochip_add(&it8761e_gpio_chip); |
| 206 | if (err < 0) | 206 | if (err < 0) |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2b8b969d0c15..df6a9cd82c4d 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -456,11 +456,15 @@ i915_error_object_create(struct drm_device *dev, | |||
| 456 | 456 | ||
| 457 | for (page = 0; page < page_count; page++) { | 457 | for (page = 0; page < page_count; page++) { |
| 458 | void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC); | 458 | void *s, *d = kmalloc(PAGE_SIZE, GFP_ATOMIC); |
| 459 | unsigned long flags; | ||
| 460 | |||
| 459 | if (d == NULL) | 461 | if (d == NULL) |
| 460 | goto unwind; | 462 | goto unwind; |
| 461 | s = kmap_atomic(src_priv->pages[page], KM_USER0); | 463 | local_irq_save(flags); |
| 464 | s = kmap_atomic(src_priv->pages[page], KM_IRQ0); | ||
| 462 | memcpy(d, s, PAGE_SIZE); | 465 | memcpy(d, s, PAGE_SIZE); |
| 463 | kunmap_atomic(s, KM_USER0); | 466 | kunmap_atomic(s, KM_IRQ0); |
| 467 | local_irq_restore(flags); | ||
| 464 | dst->pages[page] = d; | 468 | dst->pages[page] = d; |
| 465 | } | 469 | } |
| 466 | dst->page_count = page_count; | 470 | dst->page_count = page_count; |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 4b05563d99e1..b3749d47be7b 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
| @@ -216,6 +216,7 @@ static struct drm_driver driver_old = { | |||
| 216 | .mmap = drm_mmap, | 216 | .mmap = drm_mmap, |
| 217 | .poll = drm_poll, | 217 | .poll = drm_poll, |
| 218 | .fasync = drm_fasync, | 218 | .fasync = drm_fasync, |
| 219 | .read = drm_read, | ||
| 219 | #ifdef CONFIG_COMPAT | 220 | #ifdef CONFIG_COMPAT |
| 220 | .compat_ioctl = radeon_compat_ioctl, | 221 | .compat_ioctl = radeon_compat_ioctl, |
| 221 | #endif | 222 | #endif |
| @@ -304,6 +305,7 @@ static struct drm_driver kms_driver = { | |||
| 304 | .mmap = radeon_mmap, | 305 | .mmap = radeon_mmap, |
| 305 | .poll = drm_poll, | 306 | .poll = drm_poll, |
| 306 | .fasync = drm_fasync, | 307 | .fasync = drm_fasync, |
| 308 | .read = drm_read, | ||
| 307 | #ifdef CONFIG_COMPAT | 309 | #ifdef CONFIG_COMPAT |
| 308 | .compat_ioctl = radeon_kms_compat_ioctl, | 310 | .compat_ioctl = radeon_kms_compat_ioctl, |
| 309 | #endif | 311 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c index 40ab6d9c3736..cc5316dcf580 100644 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ b/drivers/gpu/drm/radeon/radeon_state.c | |||
| @@ -424,7 +424,7 @@ static __inline__ int radeon_check_and_fixup_packet3(drm_radeon_private_t * | |||
| 424 | if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && | 424 | if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && |
| 425 | (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { | 425 | (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { |
| 426 | u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); | 426 | u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); |
| 427 | offset = *cmd << 10; | 427 | offset = *cmd3 << 10; |
| 428 | if (radeon_check_and_fixup_offset | 428 | if (radeon_check_and_fixup_offset |
| 429 | (dev_priv, file_priv, &offset)) { | 429 | (dev_priv, file_priv, &offset)) { |
| 430 | DRM_ERROR("Invalid second packet offset\n"); | 430 | DRM_ERROR("Invalid second packet offset\n"); |
| @@ -2895,9 +2895,12 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, | |||
| 2895 | return rv; | 2895 | return rv; |
| 2896 | rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer, | 2896 | rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer, |
| 2897 | cmdbuf->bufsz); | 2897 | cmdbuf->bufsz); |
| 2898 | if (rv) | 2898 | if (rv) { |
| 2899 | drm_buffer_free(cmdbuf->buffer); | ||
| 2899 | return rv; | 2900 | return rv; |
| 2900 | } | 2901 | } |
| 2902 | } else | ||
| 2903 | goto done; | ||
| 2901 | 2904 | ||
| 2902 | orig_nbox = cmdbuf->nbox; | 2905 | orig_nbox = cmdbuf->nbox; |
| 2903 | 2906 | ||
| @@ -2905,8 +2908,7 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, | |||
| 2905 | int temp; | 2908 | int temp; |
| 2906 | temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); | 2909 | temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); |
| 2907 | 2910 | ||
| 2908 | if (cmdbuf->bufsz != 0) | 2911 | drm_buffer_free(cmdbuf->buffer); |
| 2909 | drm_buffer_free(cmdbuf->buffer); | ||
| 2910 | 2912 | ||
| 2911 | return temp; | 2913 | return temp; |
| 2912 | } | 2914 | } |
| @@ -3012,16 +3014,15 @@ static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, | |||
| 3012 | } | 3014 | } |
| 3013 | } | 3015 | } |
| 3014 | 3016 | ||
| 3015 | if (cmdbuf->bufsz != 0) | 3017 | drm_buffer_free(cmdbuf->buffer); |
| 3016 | drm_buffer_free(cmdbuf->buffer); | ||
| 3017 | 3018 | ||
| 3019 | done: | ||
| 3018 | DRM_DEBUG("DONE\n"); | 3020 | DRM_DEBUG("DONE\n"); |
| 3019 | COMMIT_RING(); | 3021 | COMMIT_RING(); |
| 3020 | return 0; | 3022 | return 0; |
| 3021 | 3023 | ||
| 3022 | err: | 3024 | err: |
| 3023 | if (cmdbuf->bufsz != 0) | 3025 | drm_buffer_free(cmdbuf->buffer); |
| 3024 | drm_buffer_free(cmdbuf->buffer); | ||
| 3025 | return -EINVAL; | 3026 | return -EINVAL; |
| 3026 | } | 3027 | } |
| 3027 | 3028 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index dd47b2a9a791..0e3754a3a303 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
| @@ -1716,40 +1716,12 @@ int ttm_bo_wait(struct ttm_buffer_object *bo, | |||
| 1716 | } | 1716 | } |
| 1717 | EXPORT_SYMBOL(ttm_bo_wait); | 1717 | EXPORT_SYMBOL(ttm_bo_wait); |
| 1718 | 1718 | ||
| 1719 | void ttm_bo_unblock_reservation(struct ttm_buffer_object *bo) | ||
| 1720 | { | ||
| 1721 | atomic_set(&bo->reserved, 0); | ||
| 1722 | wake_up_all(&bo->event_queue); | ||
| 1723 | } | ||
| 1724 | |||
| 1725 | int ttm_bo_block_reservation(struct ttm_buffer_object *bo, bool interruptible, | ||
| 1726 | bool no_wait) | ||
| 1727 | { | ||
| 1728 | int ret; | ||
| 1729 | |||
| 1730 | while (unlikely(atomic_cmpxchg(&bo->reserved, 0, 1) != 0)) { | ||
| 1731 | if (no_wait) | ||
| 1732 | return -EBUSY; | ||
| 1733 | else if (interruptible) { | ||
| 1734 | ret = wait_event_interruptible | ||
| 1735 | (bo->event_queue, atomic_read(&bo->reserved) == 0); | ||
| 1736 | if (unlikely(ret != 0)) | ||
| 1737 | return ret; | ||
| 1738 | } else { | ||
| 1739 | wait_event(bo->event_queue, | ||
| 1740 | atomic_read(&bo->reserved) == 0); | ||
| 1741 | } | ||
| 1742 | } | ||
| 1743 | return 0; | ||
| 1744 | } | ||
| 1745 | |||
| 1746 | int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait) | 1719 | int ttm_bo_synccpu_write_grab(struct ttm_buffer_object *bo, bool no_wait) |
| 1747 | { | 1720 | { |
| 1748 | int ret = 0; | 1721 | int ret = 0; |
| 1749 | 1722 | ||
| 1750 | /* | 1723 | /* |
| 1751 | * Using ttm_bo_reserve instead of ttm_bo_block_reservation | 1724 | * Using ttm_bo_reserve makes sure the lru lists are updated. |
| 1752 | * makes sure the lru lists are updated. | ||
| 1753 | */ | 1725 | */ |
| 1754 | 1726 | ||
| 1755 | ret = ttm_bo_reserve(bo, true, no_wait, false, 0); | 1727 | ret = ttm_bo_reserve(bo, true, no_wait, false, 0); |
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c index 3d172ef04ee1..de41e55a944a 100644 --- a/drivers/gpu/drm/ttm/ttm_lock.c +++ b/drivers/gpu/drm/ttm/ttm_lock.c | |||
| @@ -204,7 +204,6 @@ static int __ttm_vt_unlock(struct ttm_lock *lock) | |||
| 204 | lock->flags &= ~TTM_VT_LOCK; | 204 | lock->flags &= ~TTM_VT_LOCK; |
| 205 | wake_up_all(&lock->queue); | 205 | wake_up_all(&lock->queue); |
| 206 | spin_unlock(&lock->lock); | 206 | spin_unlock(&lock->lock); |
| 207 | printk(KERN_INFO TTM_PFX "vt unlock.\n"); | ||
| 208 | 207 | ||
| 209 | return ret; | 208 | return ret; |
| 210 | } | 209 | } |
| @@ -265,10 +264,8 @@ int ttm_vt_lock(struct ttm_lock *lock, | |||
| 265 | ttm_lock_type, &ttm_vt_lock_remove, NULL); | 264 | ttm_lock_type, &ttm_vt_lock_remove, NULL); |
| 266 | if (ret) | 265 | if (ret) |
| 267 | (void)__ttm_vt_unlock(lock); | 266 | (void)__ttm_vt_unlock(lock); |
| 268 | else { | 267 | else |
| 269 | lock->vt_holder = tfile; | 268 | lock->vt_holder = tfile; |
| 270 | printk(KERN_INFO TTM_PFX "vt lock.\n"); | ||
| 271 | } | ||
| 272 | 269 | ||
| 273 | return ret; | 270 | return ret; |
| 274 | } | 271 | } |
diff --git a/drivers/hid/hid-cherry.c b/drivers/hid/hid-cherry.c index 7e597d7f770f..24663a8717b1 100644 --- a/drivers/hid/hid-cherry.c +++ b/drivers/hid/hid-cherry.c | |||
| @@ -59,6 +59,7 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi, | |||
| 59 | 59 | ||
| 60 | static const struct hid_device_id ch_devices[] = { | 60 | static const struct hid_device_id ch_devices[] = { |
| 61 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 61 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
| 62 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, | ||
| 62 | { } | 63 | { } |
| 63 | }; | 64 | }; |
| 64 | MODULE_DEVICE_TABLE(hid, ch_devices); | 65 | MODULE_DEVICE_TABLE(hid, ch_devices); |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 2e2aa759d230..143e788b729b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
| @@ -1043,13 +1043,8 @@ void hid_report_raw_event(struct hid_device *hid, int type, u8 *data, int size, | |||
| 1043 | 1043 | ||
| 1044 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) | 1044 | if ((hid->claimed & HID_CLAIMED_HIDDEV) && hid->hiddev_report_event) |
| 1045 | hid->hiddev_report_event(hid, report); | 1045 | hid->hiddev_report_event(hid, report); |
| 1046 | if (hid->claimed & HID_CLAIMED_HIDRAW) { | 1046 | if (hid->claimed & HID_CLAIMED_HIDRAW) |
| 1047 | /* numbered reports need to be passed with the report num */ | 1047 | hidraw_report_event(hid, data, size); |
| 1048 | if (report_enum->numbered) | ||
| 1049 | hidraw_report_event(hid, data - 1, size + 1); | ||
| 1050 | else | ||
| 1051 | hidraw_report_event(hid, data, size); | ||
| 1052 | } | ||
| 1053 | 1048 | ||
| 1054 | for (a = 0; a < report->maxfield; a++) | 1049 | for (a = 0; a < report->maxfield; a++) |
| 1055 | hid_input_field(hid, report->field[a], cdata, interrupt); | 1050 | hid_input_field(hid, report->field[a], cdata, interrupt); |
| @@ -1296,6 +1291,7 @@ static const struct hid_device_id hid_blacklist[] = { | |||
| 1296 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, | 1291 | { HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) }, |
| 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, | 1292 | { HID_USB_DEVICE(USB_VENDOR_ID_BELKIN, USB_DEVICE_ID_FLIP_KVM) }, |
| 1298 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, | 1293 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION) }, |
| 1294 | { HID_USB_DEVICE(USB_VENDOR_ID_CHERRY, USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR) }, | ||
| 1299 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, | 1295 | { HID_USB_DEVICE(USB_VENDOR_ID_CHICONY, USB_DEVICE_ID_CHICONY_TACTICAL_PAD) }, |
| 1300 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, | 1296 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_1) }, |
| 1301 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, | 1297 | { HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_BARCODE_2) }, |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 797e06470356..09d27649a0f7 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
| @@ -131,6 +131,7 @@ | |||
| 131 | 131 | ||
| 132 | #define USB_VENDOR_ID_CHERRY 0x046a | 132 | #define USB_VENDOR_ID_CHERRY 0x046a |
| 133 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 | 133 | #define USB_DEVICE_ID_CHERRY_CYMOTION 0x0023 |
| 134 | #define USB_DEVICE_ID_CHERRY_CYMOTION_SOLAR 0x0027 | ||
| 134 | 135 | ||
| 135 | #define USB_VENDOR_ID_CHIC 0x05fe | 136 | #define USB_VENDOR_ID_CHIC 0x05fe |
| 136 | #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 | 137 | #define USB_DEVICE_ID_CHIC_GAMEPAD 0x0014 |
diff --git a/drivers/hid/hid-ntrig.c b/drivers/hid/hid-ntrig.c index 9b24fc510712..4777bbfa1cc2 100644 --- a/drivers/hid/hid-ntrig.c +++ b/drivers/hid/hid-ntrig.c | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * HID driver for N-Trig touchscreens | 2 | * HID driver for N-Trig touchscreens |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2008 Rafi Rubin | 4 | * Copyright (c) 2008-2010 Rafi Rubin |
| 5 | * Copyright (c) 2009 Stephane Chatty | 5 | * Copyright (c) 2009-2010 Stephane Chatty |
| 6 | * | 6 | * |
| 7 | */ | 7 | */ |
| 8 | 8 | ||
| @@ -15,6 +15,8 @@ | |||
| 15 | 15 | ||
| 16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
| 17 | #include <linux/hid.h> | 17 | #include <linux/hid.h> |
| 18 | #include <linux/usb.h> | ||
| 19 | #include "usbhid/usbhid.h" | ||
| 18 | #include <linux/module.h> | 20 | #include <linux/module.h> |
| 19 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| 20 | 22 | ||
| @@ -22,17 +24,16 @@ | |||
| 22 | 24 | ||
| 23 | #define NTRIG_DUPLICATE_USAGES 0x001 | 25 | #define NTRIG_DUPLICATE_USAGES 0x001 |
| 24 | 26 | ||
| 25 | #define nt_map_key_clear(c) hid_map_usage_clear(hi, usage, bit, max, \ | ||
| 26 | EV_KEY, (c)) | ||
| 27 | |||
| 28 | struct ntrig_data { | 27 | struct ntrig_data { |
| 29 | /* Incoming raw values for a single contact */ | 28 | /* Incoming raw values for a single contact */ |
| 30 | __u16 x, y, w, h; | 29 | __u16 x, y, w, h; |
| 31 | __u16 id; | 30 | __u16 id; |
| 32 | __u8 confidence; | 31 | |
| 32 | bool tipswitch; | ||
| 33 | bool confidence; | ||
| 34 | bool first_contact_touch; | ||
| 33 | 35 | ||
| 34 | bool reading_mt; | 36 | bool reading_mt; |
| 35 | __u8 first_contact_confidence; | ||
| 36 | 37 | ||
| 37 | __u8 mt_footer[4]; | 38 | __u8 mt_footer[4]; |
| 38 | __u8 mt_foot_count; | 39 | __u8 mt_foot_count; |
| @@ -139,9 +140,10 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
| 139 | case 0xff000001: | 140 | case 0xff000001: |
| 140 | /* Tag indicating the start of a multitouch group */ | 141 | /* Tag indicating the start of a multitouch group */ |
| 141 | nd->reading_mt = 1; | 142 | nd->reading_mt = 1; |
| 142 | nd->first_contact_confidence = 0; | 143 | nd->first_contact_touch = 0; |
| 143 | break; | 144 | break; |
| 144 | case HID_DG_TIPSWITCH: | 145 | case HID_DG_TIPSWITCH: |
| 146 | nd->tipswitch = value; | ||
| 145 | /* Prevent emission of touch until validated */ | 147 | /* Prevent emission of touch until validated */ |
| 146 | return 1; | 148 | return 1; |
| 147 | case HID_DG_CONFIDENCE: | 149 | case HID_DG_CONFIDENCE: |
| @@ -169,8 +171,14 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
| 169 | * to emit a normal (X, Y) position | 171 | * to emit a normal (X, Y) position |
| 170 | */ | 172 | */ |
| 171 | if (!nd->reading_mt) { | 173 | if (!nd->reading_mt) { |
| 174 | /* | ||
| 175 | * TipSwitch indicates the presence of a | ||
| 176 | * finger in single touch mode. | ||
| 177 | */ | ||
| 178 | input_report_key(input, BTN_TOUCH, | ||
| 179 | nd->tipswitch); | ||
| 172 | input_report_key(input, BTN_TOOL_DOUBLETAP, | 180 | input_report_key(input, BTN_TOOL_DOUBLETAP, |
| 173 | (nd->confidence != 0)); | 181 | nd->tipswitch); |
| 174 | input_event(input, EV_ABS, ABS_X, nd->x); | 182 | input_event(input, EV_ABS, ABS_X, nd->x); |
| 175 | input_event(input, EV_ABS, ABS_Y, nd->y); | 183 | input_event(input, EV_ABS, ABS_Y, nd->y); |
| 176 | } | 184 | } |
| @@ -209,7 +217,13 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
| 209 | 217 | ||
| 210 | /* emit a normal (X, Y) for the first point only */ | 218 | /* emit a normal (X, Y) for the first point only */ |
| 211 | if (nd->id == 0) { | 219 | if (nd->id == 0) { |
| 212 | nd->first_contact_confidence = nd->confidence; | 220 | /* |
| 221 | * TipSwitch is superfluous in multitouch | ||
| 222 | * mode. The footer events tell us | ||
| 223 | * if there is a finger on the screen or | ||
| 224 | * not. | ||
| 225 | */ | ||
| 226 | nd->first_contact_touch = nd->confidence; | ||
| 213 | input_event(input, EV_ABS, ABS_X, nd->x); | 227 | input_event(input, EV_ABS, ABS_X, nd->x); |
| 214 | input_event(input, EV_ABS, ABS_Y, nd->y); | 228 | input_event(input, EV_ABS, ABS_Y, nd->y); |
| 215 | } | 229 | } |
| @@ -239,30 +253,11 @@ static int ntrig_event (struct hid_device *hid, struct hid_field *field, | |||
| 239 | 253 | ||
| 240 | nd->reading_mt = 0; | 254 | nd->reading_mt = 0; |
| 241 | 255 | ||
| 242 | if (nd->first_contact_confidence) { | 256 | if (nd->first_contact_touch) { |
| 243 | switch (value) { | 257 | input_report_key(input, BTN_TOOL_DOUBLETAP, 1); |
| 244 | case 0: /* for single touch devices */ | ||
| 245 | case 1: | ||
| 246 | input_report_key(input, | ||
| 247 | BTN_TOOL_DOUBLETAP, 1); | ||
| 248 | break; | ||
| 249 | case 2: | ||
| 250 | input_report_key(input, | ||
| 251 | BTN_TOOL_TRIPLETAP, 1); | ||
| 252 | break; | ||
| 253 | case 3: | ||
| 254 | default: | ||
| 255 | input_report_key(input, | ||
| 256 | BTN_TOOL_QUADTAP, 1); | ||
| 257 | } | ||
| 258 | input_report_key(input, BTN_TOUCH, 1); | 258 | input_report_key(input, BTN_TOUCH, 1); |
| 259 | } else { | 259 | } else { |
| 260 | input_report_key(input, | 260 | input_report_key(input, BTN_TOOL_DOUBLETAP, 0); |
| 261 | BTN_TOOL_DOUBLETAP, 0); | ||
| 262 | input_report_key(input, | ||
| 263 | BTN_TOOL_TRIPLETAP, 0); | ||
| 264 | input_report_key(input, | ||
| 265 | BTN_TOOL_QUADTAP, 0); | ||
| 266 | input_report_key(input, BTN_TOUCH, 0); | 261 | input_report_key(input, BTN_TOUCH, 0); |
| 267 | } | 262 | } |
| 268 | break; | 263 | break; |
| @@ -286,6 +281,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 286 | struct ntrig_data *nd; | 281 | struct ntrig_data *nd; |
| 287 | struct hid_input *hidinput; | 282 | struct hid_input *hidinput; |
| 288 | struct input_dev *input; | 283 | struct input_dev *input; |
| 284 | struct hid_report *report; | ||
| 289 | 285 | ||
| 290 | if (id->driver_data) | 286 | if (id->driver_data) |
| 291 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; | 287 | hdev->quirks |= HID_QUIRK_MULTI_INPUT; |
| @@ -327,13 +323,7 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 327 | __clear_bit(BTN_TOOL_PEN, input->keybit); | 323 | __clear_bit(BTN_TOOL_PEN, input->keybit); |
| 328 | __clear_bit(BTN_TOOL_FINGER, input->keybit); | 324 | __clear_bit(BTN_TOOL_FINGER, input->keybit); |
| 329 | __clear_bit(BTN_0, input->keybit); | 325 | __clear_bit(BTN_0, input->keybit); |
| 330 | /* | ||
| 331 | * A little something special to enable | ||
| 332 | * two and three finger taps. | ||
| 333 | */ | ||
| 334 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); | 326 | __set_bit(BTN_TOOL_DOUBLETAP, input->keybit); |
| 335 | __set_bit(BTN_TOOL_TRIPLETAP, input->keybit); | ||
| 336 | __set_bit(BTN_TOOL_QUADTAP, input->keybit); | ||
| 337 | /* | 327 | /* |
| 338 | * The physical touchscreen (single touch) | 328 | * The physical touchscreen (single touch) |
| 339 | * input has a value for physical, whereas | 329 | * input has a value for physical, whereas |
| @@ -349,6 +339,12 @@ static int ntrig_probe(struct hid_device *hdev, const struct hid_device_id *id) | |||
| 349 | } | 339 | } |
| 350 | } | 340 | } |
| 351 | 341 | ||
| 342 | /* This is needed for devices with more recent firmware versions */ | ||
| 343 | report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a]; | ||
| 344 | if (report) | ||
| 345 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | ||
| 346 | |||
| 347 | |||
| 352 | return 0; | 348 | return 0; |
| 353 | err_free: | 349 | err_free: |
| 354 | kfree(nd); | 350 | kfree(nd); |
diff --git a/drivers/hid/hid-sony.c b/drivers/hid/hid-sony.c index 7502a4b2fa86..402d5574b574 100644 --- a/drivers/hid/hid-sony.c +++ b/drivers/hid/hid-sony.c | |||
| @@ -76,7 +76,7 @@ static int sony_set_operational_usb(struct hid_device *hdev) | |||
| 76 | 76 | ||
| 77 | static int sony_set_operational_bt(struct hid_device *hdev) | 77 | static int sony_set_operational_bt(struct hid_device *hdev) |
| 78 | { | 78 | { |
| 79 | unsigned char buf[] = { 0x53, 0xf4, 0x42, 0x03, 0x00, 0x00 }; | 79 | unsigned char buf[] = { 0xf4, 0x42, 0x03, 0x00, 0x00 }; |
| 80 | return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); | 80 | return hdev->hid_output_raw_report(hdev, buf, sizeof(buf), HID_FEATURE_REPORT); |
| 81 | } | 81 | } |
| 82 | 82 | ||
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c index f7700cf49721..f947d8337e21 100644 --- a/drivers/hid/hid-wacom.c +++ b/drivers/hid/hid-wacom.c | |||
| @@ -277,7 +277,6 @@ static int __init wacom_init(void) | |||
| 277 | ret = hid_register_driver(&wacom_driver); | 277 | ret = hid_register_driver(&wacom_driver); |
| 278 | if (ret) | 278 | if (ret) |
| 279 | printk(KERN_ERR "can't register wacom driver\n"); | 279 | printk(KERN_ERR "can't register wacom driver\n"); |
| 280 | printk(KERN_ERR "wacom driver registered\n"); | ||
| 281 | return ret; | 280 | return ret; |
| 282 | } | 281 | } |
| 283 | 282 | ||
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 56d06cd8075b..7b85b696fdab 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
| @@ -999,13 +999,6 @@ static int usbhid_start(struct hid_device *hid) | |||
| 999 | } | 999 | } |
| 1000 | } | 1000 | } |
| 1001 | 1001 | ||
| 1002 | init_waitqueue_head(&usbhid->wait); | ||
| 1003 | INIT_WORK(&usbhid->reset_work, hid_reset); | ||
| 1004 | INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); | ||
| 1005 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | ||
| 1006 | |||
| 1007 | spin_lock_init(&usbhid->lock); | ||
| 1008 | |||
| 1009 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); | 1002 | usbhid->urbctrl = usb_alloc_urb(0, GFP_KERNEL); |
| 1010 | if (!usbhid->urbctrl) { | 1003 | if (!usbhid->urbctrl) { |
| 1011 | ret = -ENOMEM; | 1004 | ret = -ENOMEM; |
| @@ -1179,6 +1172,12 @@ static int usbhid_probe(struct usb_interface *intf, const struct usb_device_id * | |||
| 1179 | usbhid->intf = intf; | 1172 | usbhid->intf = intf; |
| 1180 | usbhid->ifnum = interface->desc.bInterfaceNumber; | 1173 | usbhid->ifnum = interface->desc.bInterfaceNumber; |
| 1181 | 1174 | ||
| 1175 | init_waitqueue_head(&usbhid->wait); | ||
| 1176 | INIT_WORK(&usbhid->reset_work, hid_reset); | ||
| 1177 | INIT_WORK(&usbhid->restart_work, __usbhid_restart_queues); | ||
| 1178 | setup_timer(&usbhid->io_retry, hid_retry_timeout, (unsigned long) hid); | ||
| 1179 | spin_lock_init(&usbhid->lock); | ||
| 1180 | |||
| 1182 | ret = hid_add_device(hid); | 1181 | ret = hid_add_device(hid); |
| 1183 | if (ret) { | 1182 | if (ret) { |
| 1184 | if (ret != -ENODEV) | 1183 | if (ret != -ENODEV) |
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c index 0f28d91f29d8..f085c18d2905 100644 --- a/drivers/hwmon/applesmc.c +++ b/drivers/hwmon/applesmc.c | |||
| @@ -195,6 +195,9 @@ static unsigned int applesmc_accelerometer; | |||
| 195 | /* Indicates whether this computer has light sensors and keyboard backlight. */ | 195 | /* Indicates whether this computer has light sensors and keyboard backlight. */ |
| 196 | static unsigned int applesmc_light; | 196 | static unsigned int applesmc_light; |
| 197 | 197 | ||
| 198 | /* The number of fans handled by the driver */ | ||
| 199 | static unsigned int fans_handled; | ||
| 200 | |||
| 198 | /* Indicates which temperature sensors set to use. */ | 201 | /* Indicates which temperature sensors set to use. */ |
| 199 | static unsigned int applesmc_temperature_set; | 202 | static unsigned int applesmc_temperature_set; |
| 200 | 203 | ||
| @@ -1492,39 +1495,24 @@ static int __init applesmc_init(void) | |||
| 1492 | 1495 | ||
| 1493 | /* create fan files */ | 1496 | /* create fan files */ |
| 1494 | count = applesmc_get_fan_count(); | 1497 | count = applesmc_get_fan_count(); |
| 1495 | if (count < 0) { | 1498 | if (count < 0) |
| 1496 | printk(KERN_ERR "applesmc: Cannot get the number of fans.\n"); | 1499 | printk(KERN_ERR "applesmc: Cannot get the number of fans.\n"); |
| 1497 | } else { | 1500 | else |
| 1498 | printk(KERN_INFO "applesmc: %d fans found.\n", count); | 1501 | printk(KERN_INFO "applesmc: %d fans found.\n", count); |
| 1499 | 1502 | ||
| 1500 | switch (count) { | 1503 | if (count > 4) { |
| 1501 | default: | 1504 | count = 4; |
| 1502 | printk(KERN_WARNING "applesmc: More than 4 fans found," | 1505 | printk(KERN_WARNING "applesmc: More than 4 fans found," |
| 1503 | " but at most 4 fans are supported" | 1506 | " but at most 4 fans are supported" |
| 1504 | " by the driver.\n"); | 1507 | " by the driver.\n"); |
| 1505 | case 4: | 1508 | } |
| 1506 | ret = sysfs_create_group(&pdev->dev.kobj, | 1509 | |
| 1507 | &fan_attribute_groups[3]); | 1510 | while (fans_handled < count) { |
| 1508 | if (ret) | 1511 | ret = sysfs_create_group(&pdev->dev.kobj, |
| 1509 | goto out_key_enumeration; | 1512 | &fan_attribute_groups[fans_handled]); |
| 1510 | case 3: | 1513 | if (ret) |
| 1511 | ret = sysfs_create_group(&pdev->dev.kobj, | 1514 | goto out_fans; |
| 1512 | &fan_attribute_groups[2]); | 1515 | fans_handled++; |
| 1513 | if (ret) | ||
| 1514 | goto out_key_enumeration; | ||
| 1515 | case 2: | ||
| 1516 | ret = sysfs_create_group(&pdev->dev.kobj, | ||
| 1517 | &fan_attribute_groups[1]); | ||
| 1518 | if (ret) | ||
| 1519 | goto out_key_enumeration; | ||
| 1520 | case 1: | ||
| 1521 | ret = sysfs_create_group(&pdev->dev.kobj, | ||
| 1522 | &fan_attribute_groups[0]); | ||
| 1523 | if (ret) | ||
| 1524 | goto out_fan_1; | ||
| 1525 | case 0: | ||
| 1526 | ; | ||
| 1527 | } | ||
| 1528 | } | 1516 | } |
| 1529 | 1517 | ||
| 1530 | for (i = 0; | 1518 | for (i = 0; |
| @@ -1593,10 +1581,10 @@ out_accelerometer: | |||
| 1593 | applesmc_release_accelerometer(); | 1581 | applesmc_release_accelerometer(); |
| 1594 | out_temperature: | 1582 | out_temperature: |
| 1595 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); | 1583 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); |
| 1596 | sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]); | 1584 | out_fans: |
| 1597 | out_fan_1: | 1585 | while (fans_handled) |
| 1598 | sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]); | 1586 | sysfs_remove_group(&pdev->dev.kobj, |
| 1599 | out_key_enumeration: | 1587 | &fan_attribute_groups[--fans_handled]); |
| 1600 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); | 1588 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); |
| 1601 | out_name: | 1589 | out_name: |
| 1602 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); | 1590 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); |
| @@ -1622,8 +1610,9 @@ static void __exit applesmc_exit(void) | |||
| 1622 | if (applesmc_accelerometer) | 1610 | if (applesmc_accelerometer) |
| 1623 | applesmc_release_accelerometer(); | 1611 | applesmc_release_accelerometer(); |
| 1624 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); | 1612 | sysfs_remove_group(&pdev->dev.kobj, &temperature_attributes_group); |
| 1625 | sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[0]); | 1613 | while (fans_handled) |
| 1626 | sysfs_remove_group(&pdev->dev.kobj, &fan_attribute_groups[1]); | 1614 | sysfs_remove_group(&pdev->dev.kobj, |
| 1615 | &fan_attribute_groups[--fans_handled]); | ||
| 1627 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); | 1616 | sysfs_remove_group(&pdev->dev.kobj, &key_enumeration_group); |
| 1628 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); | 1617 | sysfs_remove_file(&pdev->dev.kobj, &dev_attr_name.attr); |
| 1629 | platform_device_unregister(pdev); | 1618 | platform_device_unregister(pdev); |
diff --git a/drivers/hwmon/asc7621.c b/drivers/hwmon/asc7621.c index 7f948105d8ad..0f388adc6187 100644 --- a/drivers/hwmon/asc7621.c +++ b/drivers/hwmon/asc7621.c | |||
| @@ -268,8 +268,11 @@ static ssize_t store_fan16(struct device *dev, | |||
| 268 | if (strict_strtol(buf, 10, &reqval)) | 268 | if (strict_strtol(buf, 10, &reqval)) |
| 269 | return -EINVAL; | 269 | return -EINVAL; |
| 270 | 270 | ||
| 271 | /* If a minimum RPM of zero is requested, then we set the register to | ||
| 272 | 0xffff. This value allows the fan to be stopped completely without | ||
| 273 | generating an alarm. */ | ||
| 271 | reqval = | 274 | reqval = |
| 272 | (SENSORS_LIMIT((reqval) <= 0 ? 0 : 5400000 / (reqval), 0, 65534)); | 275 | (reqval <= 0 ? 0xffff : SENSORS_LIMIT(5400000 / reqval, 0, 0xfffe)); |
| 273 | 276 | ||
| 274 | mutex_lock(&data->update_lock); | 277 | mutex_lock(&data->update_lock); |
| 275 | data->reg[param->msb[0]] = (reqval >> 8) & 0xff; | 278 | data->reg[param->msb[0]] = (reqval >> 8) & 0xff; |
| @@ -285,8 +288,9 @@ static ssize_t store_fan16(struct device *dev, | |||
| 285 | * Voltages are scaled in the device so that the nominal voltage | 288 | * Voltages are scaled in the device so that the nominal voltage |
| 286 | * is 3/4ths of the 0-255 range (i.e. 192). | 289 | * is 3/4ths of the 0-255 range (i.e. 192). |
| 287 | * If all voltages are 'normal' then all voltage registers will | 290 | * If all voltages are 'normal' then all voltage registers will |
| 288 | * read 0xC0. This doesn't help us if we don't have a point of refernce. | 291 | * read 0xC0. |
| 289 | * The data sheet however provides us with the full scale value for each | 292 | * |
| 293 | * The data sheet provides us with the 3/4 scale value for each voltage | ||
| 290 | * which is stored in in_scaling. The sda->index parameter value provides | 294 | * which is stored in in_scaling. The sda->index parameter value provides |
| 291 | * the index into in_scaling. | 295 | * the index into in_scaling. |
| 292 | * | 296 | * |
| @@ -295,7 +299,7 @@ static ssize_t store_fan16(struct device *dev, | |||
| 295 | */ | 299 | */ |
| 296 | 300 | ||
| 297 | static int asc7621_in_scaling[] = { | 301 | static int asc7621_in_scaling[] = { |
| 298 | 3320, 3000, 4380, 6640, 16000 | 302 | 2500, 2250, 3300, 5000, 12000 |
| 299 | }; | 303 | }; |
| 300 | 304 | ||
| 301 | static ssize_t show_in10(struct device *dev, struct device_attribute *attr, | 305 | static ssize_t show_in10(struct device *dev, struct device_attribute *attr, |
| @@ -306,19 +310,12 @@ static ssize_t show_in10(struct device *dev, struct device_attribute *attr, | |||
| 306 | u8 nr = sda->index; | 310 | u8 nr = sda->index; |
| 307 | 311 | ||
| 308 | mutex_lock(&data->update_lock); | 312 | mutex_lock(&data->update_lock); |
| 309 | regval = (data->reg[param->msb[0]] * asc7621_in_scaling[nr]) / 256; | 313 | regval = (data->reg[param->msb[0]] << 8) | (data->reg[param->lsb[0]]); |
| 310 | |||
| 311 | /* The LSB value is a 2-bit scaling of the MSB's LSbit value. | ||
| 312 | * I.E. If the maximim voltage for this input is 6640 millivolts then | ||
| 313 | * a MSB register value of 0 = 0mv and 255 = 6640mv. | ||
| 314 | * A 1 step change therefore represents 25.9mv (6640 / 256). | ||
| 315 | * The extra 2-bits therefore represent increments of 6.48mv. | ||
| 316 | */ | ||
| 317 | regval += ((asc7621_in_scaling[nr] / 256) / 4) * | ||
| 318 | (data->reg[param->lsb[0]] >> 6); | ||
| 319 | |||
| 320 | mutex_unlock(&data->update_lock); | 314 | mutex_unlock(&data->update_lock); |
| 321 | 315 | ||
| 316 | /* The LSB value is a 2-bit scaling of the MSB's LSbit value. */ | ||
| 317 | regval = (regval >> 6) * asc7621_in_scaling[nr] / (0xc0 << 2); | ||
| 318 | |||
| 322 | return sprintf(buf, "%u\n", regval); | 319 | return sprintf(buf, "%u\n", regval); |
| 323 | } | 320 | } |
| 324 | 321 | ||
| @@ -331,7 +328,7 @@ static ssize_t show_in8(struct device *dev, struct device_attribute *attr, | |||
| 331 | 328 | ||
| 332 | return sprintf(buf, "%u\n", | 329 | return sprintf(buf, "%u\n", |
| 333 | ((data->reg[param->msb[0]] * | 330 | ((data->reg[param->msb[0]] * |
| 334 | asc7621_in_scaling[nr]) / 256)); | 331 | asc7621_in_scaling[nr]) / 0xc0)); |
| 335 | } | 332 | } |
| 336 | 333 | ||
| 337 | static ssize_t store_in8(struct device *dev, struct device_attribute *attr, | 334 | static ssize_t store_in8(struct device *dev, struct device_attribute *attr, |
| @@ -344,9 +341,11 @@ static ssize_t store_in8(struct device *dev, struct device_attribute *attr, | |||
| 344 | if (strict_strtol(buf, 10, &reqval)) | 341 | if (strict_strtol(buf, 10, &reqval)) |
| 345 | return -EINVAL; | 342 | return -EINVAL; |
| 346 | 343 | ||
| 347 | reqval = SENSORS_LIMIT(reqval, 0, asc7621_in_scaling[nr]); | 344 | reqval = SENSORS_LIMIT(reqval, 0, 0xffff); |
| 345 | |||
| 346 | reqval = reqval * 0xc0 / asc7621_in_scaling[nr]; | ||
| 348 | 347 | ||
| 349 | reqval = (reqval * 255 + 128) / asc7621_in_scaling[nr]; | 348 | reqval = SENSORS_LIMIT(reqval, 0, 0xff); |
| 350 | 349 | ||
| 351 | mutex_lock(&data->update_lock); | 350 | mutex_lock(&data->update_lock); |
| 352 | data->reg[param->msb[0]] = reqval; | 351 | data->reg[param->msb[0]] = reqval; |
| @@ -846,11 +845,11 @@ static struct asc7621_param asc7621_params[] = { | |||
| 846 | PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8), | 845 | PWRITE(in3_max, 3, PRI_LOW, 0x4b, 0, 0, 0, in8), |
| 847 | PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), | 846 | PWRITE(in4_max, 4, PRI_LOW, 0x4d, 0, 0, 0, in8), |
| 848 | 847 | ||
| 849 | PREAD(in0_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 0, bitmask), | 848 | PREAD(in0_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 0, bitmask), |
| 850 | PREAD(in1_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 1, bitmask), | 849 | PREAD(in1_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 1, bitmask), |
| 851 | PREAD(in2_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 2, bitmask), | 850 | PREAD(in2_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 2, bitmask), |
| 852 | PREAD(in3_alarm, 3, PRI_LOW, 0x41, 0, 0x01, 3, bitmask), | 851 | PREAD(in3_alarm, 3, PRI_HIGH, 0x41, 0, 0x01, 3, bitmask), |
| 853 | PREAD(in4_alarm, 4, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), | 852 | PREAD(in4_alarm, 4, PRI_HIGH, 0x42, 0, 0x01, 0, bitmask), |
| 854 | 853 | ||
| 855 | PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16), | 854 | PREAD(fan1_input, 0, PRI_HIGH, 0x29, 0x28, 0, 0, fan16), |
| 856 | PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), | 855 | PREAD(fan2_input, 1, PRI_HIGH, 0x2b, 0x2a, 0, 0, fan16), |
| @@ -862,10 +861,10 @@ static struct asc7621_param asc7621_params[] = { | |||
| 862 | PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16), | 861 | PWRITE(fan3_min, 2, PRI_LOW, 0x59, 0x58, 0, 0, fan16), |
| 863 | PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), | 862 | PWRITE(fan4_min, 3, PRI_LOW, 0x5b, 0x5a, 0, 0, fan16), |
| 864 | 863 | ||
| 865 | PREAD(fan1_alarm, 0, PRI_LOW, 0x42, 0, 0x01, 0, bitmask), | 864 | PREAD(fan1_alarm, 0, PRI_HIGH, 0x42, 0, 0x01, 2, bitmask), |
| 866 | PREAD(fan2_alarm, 1, PRI_LOW, 0x42, 0, 0x01, 1, bitmask), | 865 | PREAD(fan2_alarm, 1, PRI_HIGH, 0x42, 0, 0x01, 3, bitmask), |
| 867 | PREAD(fan3_alarm, 2, PRI_LOW, 0x42, 0, 0x01, 2, bitmask), | 866 | PREAD(fan3_alarm, 2, PRI_HIGH, 0x42, 0, 0x01, 4, bitmask), |
| 868 | PREAD(fan4_alarm, 3, PRI_LOW, 0x42, 0, 0x01, 3, bitmask), | 867 | PREAD(fan4_alarm, 3, PRI_HIGH, 0x42, 0, 0x01, 5, bitmask), |
| 869 | 868 | ||
| 870 | PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10), | 869 | PREAD(temp1_input, 0, PRI_HIGH, 0x25, 0x10, 0, 0, temp10), |
| 871 | PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), | 870 | PREAD(temp2_input, 1, PRI_HIGH, 0x26, 0x15, 0, 0, temp10), |
| @@ -886,10 +885,10 @@ static struct asc7621_param asc7621_params[] = { | |||
| 886 | PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8), | 885 | PWRITE(temp3_max, 2, PRI_LOW, 0x53, 0, 0, 0, temp8), |
| 887 | PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), | 886 | PWRITE(temp4_max, 3, PRI_LOW, 0x35, 0, 0, 0, temp8), |
| 888 | 887 | ||
| 889 | PREAD(temp1_alarm, 0, PRI_LOW, 0x41, 0, 0x01, 4, bitmask), | 888 | PREAD(temp1_alarm, 0, PRI_HIGH, 0x41, 0, 0x01, 4, bitmask), |
| 890 | PREAD(temp2_alarm, 1, PRI_LOW, 0x41, 0, 0x01, 5, bitmask), | 889 | PREAD(temp2_alarm, 1, PRI_HIGH, 0x41, 0, 0x01, 5, bitmask), |
| 891 | PREAD(temp3_alarm, 2, PRI_LOW, 0x41, 0, 0x01, 6, bitmask), | 890 | PREAD(temp3_alarm, 2, PRI_HIGH, 0x41, 0, 0x01, 6, bitmask), |
| 892 | PREAD(temp4_alarm, 3, PRI_LOW, 0x43, 0, 0x01, 0, bitmask), | 891 | PREAD(temp4_alarm, 3, PRI_HIGH, 0x43, 0, 0x01, 0, bitmask), |
| 893 | 892 | ||
| 894 | PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask), | 893 | PWRITE(temp1_source, 0, PRI_LOW, 0x02, 0, 0x07, 4, bitmask), |
| 895 | PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), | 894 | PWRITE(temp2_source, 1, PRI_LOW, 0x02, 0, 0x07, 0, bitmask), |
| @@ -898,7 +897,7 @@ static struct asc7621_param asc7621_params[] = { | |||
| 898 | 897 | ||
| 899 | PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask), | 898 | PWRITE(temp1_smoothing_enable, 0, PRI_LOW, 0x62, 0, 0x01, 3, bitmask), |
| 900 | PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), | 899 | PWRITE(temp2_smoothing_enable, 1, PRI_LOW, 0x63, 0, 0x01, 7, bitmask), |
| 901 | PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x64, 0, 0x01, 3, bitmask), | 900 | PWRITE(temp3_smoothing_enable, 2, PRI_LOW, 0x63, 0, 0x01, 3, bitmask), |
| 902 | PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask), | 901 | PWRITE(temp4_smoothing_enable, 3, PRI_LOW, 0x3c, 0, 0x01, 3, bitmask), |
| 903 | 902 | ||
| 904 | PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), | 903 | PWRITE(temp1_smoothing_time, 0, PRI_LOW, 0x62, 0, 0x07, 0, temp_st), |
diff --git a/drivers/hwmon/hp_accel.c b/drivers/hwmon/hp_accel.c index c8ab50516672..7580f55e67e3 100644 --- a/drivers/hwmon/hp_accel.c +++ b/drivers/hwmon/hp_accel.c | |||
| @@ -328,8 +328,8 @@ static int lis3lv02d_remove(struct acpi_device *device, int type) | |||
| 328 | lis3lv02d_joystick_disable(); | 328 | lis3lv02d_joystick_disable(); |
| 329 | lis3lv02d_poweroff(&lis3_dev); | 329 | lis3lv02d_poweroff(&lis3_dev); |
| 330 | 330 | ||
| 331 | flush_work(&hpled_led.work); | ||
| 332 | led_classdev_unregister(&hpled_led.led_classdev); | 331 | led_classdev_unregister(&hpled_led.led_classdev); |
| 332 | flush_work(&hpled_led.work); | ||
| 333 | 333 | ||
| 334 | return lis3lv02d_remove_fs(&lis3_dev); | 334 | return lis3lv02d_remove_fs(&lis3_dev); |
| 335 | } | 335 | } |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index 9c6170cd9aac..87ab0568bb0e 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
| @@ -564,7 +564,7 @@ config I2C_STU300 | |||
| 564 | 564 | ||
| 565 | config I2C_VERSATILE | 565 | config I2C_VERSATILE |
| 566 | tristate "ARM Versatile/Realview I2C bus support" | 566 | tristate "ARM Versatile/Realview I2C bus support" |
| 567 | depends on ARCH_VERSATILE || ARCH_REALVIEW | 567 | depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS |
| 568 | select I2C_ALGOBIT | 568 | select I2C_ALGOBIT |
| 569 | help | 569 | help |
| 570 | Say yes if you want to support the I2C serial bus on ARMs Versatile | 570 | Say yes if you want to support the I2C serial bus on ARMs Versatile |
diff --git a/drivers/ide/ide-cs.c b/drivers/ide/ide-cs.c index defce2877eef..b85450865ff0 100644 --- a/drivers/ide/ide-cs.c +++ b/drivers/ide/ide-cs.c | |||
| @@ -409,7 +409,7 @@ static struct pcmcia_device_id ide_ids[] = { | |||
| 409 | PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), | 409 | PCMCIA_DEVICE_PROD_ID12("Hyperstone", "Model1", 0x3d5b9ef5, 0xca6ab420), |
| 410 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), | 410 | PCMCIA_DEVICE_PROD_ID12("IBM", "microdrive", 0xb569a6e5, 0xa6d76178), |
| 411 | PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), | 411 | PCMCIA_DEVICE_PROD_ID12("IBM", "IBM17JSSFP20", 0xb569a6e5, 0xf2508753), |
| 412 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x3e520e17), | 412 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 1GB", 0x2e6d1829, 0x55d5bffb), |
| 413 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10), | 413 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF CARD 4GB", 0x2e6d1829, 0x531e7d10), |
| 414 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), | 414 | PCMCIA_DEVICE_PROD_ID12("KINGSTON", "CF8GB", 0x2e6d1829, 0xacbe682e), |
| 415 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), | 415 | PCMCIA_DEVICE_PROD_ID12("IO DATA", "CBIDE2 ", 0x547e66dc, 0x8671043b), |
| @@ -431,7 +431,7 @@ static struct pcmcia_device_id ide_ids[] = { | |||
| 431 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), | 431 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS1GCF80", 0x709b1bf1, 0x2a54d4b1), |
| 432 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), | 432 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS2GCF120", 0x709b1bf1, 0x969aa4f2), |
| 433 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), | 433 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF120", 0x709b1bf1, 0xf54a91c8), |
| 434 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x9351e59d), | 434 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS4GCF133", 0x709b1bf1, 0x7558f133), |
| 435 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47), | 435 | PCMCIA_DEVICE_PROD_ID12("TRANSCEND", "TS8GCF133", 0x709b1bf1, 0xb2f89b47), |
| 436 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), | 436 | PCMCIA_DEVICE_PROD_ID12("WIT", "IDE16", 0x244e5994, 0x3e232852), |
| 437 | PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), | 437 | PCMCIA_DEVICE_PROD_ID12("WEIDA", "TWTTI", 0xcc7cf69c, 0x212bb918), |
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c index 7e18bcf05a66..46239e47a260 100644 --- a/drivers/input/gameport/gameport.c +++ b/drivers/input/gameport/gameport.c | |||
| @@ -59,11 +59,11 @@ static unsigned int get_time_pit(void) | |||
| 59 | unsigned long flags; | 59 | unsigned long flags; |
| 60 | unsigned int count; | 60 | unsigned int count; |
| 61 | 61 | ||
| 62 | spin_lock_irqsave(&i8253_lock, flags); | 62 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 63 | outb_p(0x00, 0x43); | 63 | outb_p(0x00, 0x43); |
| 64 | count = inb_p(0x40); | 64 | count = inb_p(0x40); |
| 65 | count |= inb_p(0x40) << 8; | 65 | count |= inb_p(0x40) << 8; |
| 66 | spin_unlock_irqrestore(&i8253_lock, flags); | 66 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 67 | 67 | ||
| 68 | return count; | 68 | return count; |
| 69 | } | 69 | } |
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index c52bec4d0530..423e0e6031ab 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
| @@ -929,6 +929,24 @@ static const struct input_device_id joydev_ids[] = { | |||
| 929 | .evbit = { BIT_MASK(EV_ABS) }, | 929 | .evbit = { BIT_MASK(EV_ABS) }, |
| 930 | .absbit = { BIT_MASK(ABS_THROTTLE) }, | 930 | .absbit = { BIT_MASK(ABS_THROTTLE) }, |
| 931 | }, | 931 | }, |
| 932 | { | ||
| 933 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
| 934 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
| 935 | .evbit = { BIT_MASK(EV_KEY) }, | ||
| 936 | .keybit = {[BIT_WORD(BTN_JOYSTICK)] = BIT_MASK(BTN_JOYSTICK) }, | ||
| 937 | }, | ||
| 938 | { | ||
| 939 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
| 940 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
| 941 | .evbit = { BIT_MASK(EV_KEY) }, | ||
| 942 | .keybit = { [BIT_WORD(BTN_GAMEPAD)] = BIT_MASK(BTN_GAMEPAD) }, | ||
| 943 | }, | ||
| 944 | { | ||
| 945 | .flags = INPUT_DEVICE_ID_MATCH_EVBIT | | ||
| 946 | INPUT_DEVICE_ID_MATCH_KEYBIT, | ||
| 947 | .evbit = { BIT_MASK(EV_KEY) }, | ||
| 948 | .keybit = { [BIT_WORD(BTN_TRIGGER_HAPPY)] = BIT_MASK(BTN_TRIGGER_HAPPY) }, | ||
| 949 | }, | ||
| 932 | { } /* Terminating entry */ | 950 | { } /* Terminating entry */ |
| 933 | }; | 951 | }; |
| 934 | 952 | ||
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 1c0b529c06aa..4afe0a3b4884 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
| @@ -146,11 +146,11 @@ static unsigned int get_time_pit(void) | |||
| 146 | unsigned long flags; | 146 | unsigned long flags; |
| 147 | unsigned int count; | 147 | unsigned int count; |
| 148 | 148 | ||
| 149 | spin_lock_irqsave(&i8253_lock, flags); | 149 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 150 | outb_p(0x00, 0x43); | 150 | outb_p(0x00, 0x43); |
| 151 | count = inb_p(0x40); | 151 | count = inb_p(0x40); |
| 152 | count |= inb_p(0x40) << 8; | 152 | count |= inb_p(0x40) << 8; |
| 153 | spin_unlock_irqrestore(&i8253_lock, flags); | 153 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 154 | 154 | ||
| 155 | return count; | 155 | return count; |
| 156 | } | 156 | } |
diff --git a/drivers/input/joystick/iforce/iforce-main.c b/drivers/input/joystick/iforce/iforce-main.c index b1edd778639c..405febd94f24 100644 --- a/drivers/input/joystick/iforce/iforce-main.c +++ b/drivers/input/joystick/iforce/iforce-main.c | |||
| @@ -54,6 +54,9 @@ static signed short btn_avb_wheel[] = | |||
| 54 | static signed short abs_joystick[] = | 54 | static signed short abs_joystick[] = |
| 55 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; | 55 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_HAT0X, ABS_HAT0Y, -1 }; |
| 56 | 56 | ||
| 57 | static signed short abs_joystick_rudder[] = | ||
| 58 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, -1 }; | ||
| 59 | |||
| 57 | static signed short abs_avb_pegasus[] = | 60 | static signed short abs_avb_pegasus[] = |
| 58 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, | 61 | { ABS_X, ABS_Y, ABS_THROTTLE, ABS_RUDDER, ABS_HAT0X, ABS_HAT0Y, |
| 59 | ABS_HAT1X, ABS_HAT1Y, -1 }; | 62 | ABS_HAT1X, ABS_HAT1Y, -1 }; |
| @@ -76,8 +79,9 @@ static struct iforce_device iforce_device[] = { | |||
| 76 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? | 79 | { 0x061c, 0xc0a4, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, //? |
| 77 | { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, | 80 | { 0x061c, 0xc084, "ACT LABS Force RS", btn_wheel, abs_wheel, ff_iforce }, |
| 78 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? | 81 | { 0x06f8, 0x0001, "Guillemot Race Leader Force Feedback", btn_wheel, abs_wheel, ff_iforce }, //? |
| 82 | { 0x06f8, 0x0001, "Guillemot Jet Leader Force Feedback", btn_joystick, abs_joystick_rudder, ff_iforce }, | ||
| 79 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? | 83 | { 0x06f8, 0x0004, "Guillemot Force Feedback Racing Wheel", btn_wheel, abs_wheel, ff_iforce }, //? |
| 80 | { 0x06f8, 0x0004, "Gullemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? | 84 | { 0x06f8, 0xa302, "Guillemot Jet Leader 3D", btn_joystick, abs_joystick, ff_iforce }, //? |
| 81 | { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, | 85 | { 0x06d6, 0x29bc, "Trust Force Feedback Race Master", btn_wheel, abs_wheel, ff_iforce }, |
| 82 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } | 86 | { 0x0000, 0x0000, "Unknown I-Force Device [%04x:%04x]", btn_joystick, abs_joystick, ff_iforce } |
| 83 | }; | 87 | }; |
diff --git a/drivers/input/joystick/iforce/iforce-usb.c b/drivers/input/joystick/iforce/iforce-usb.c index b41303d3ec54..6c96631ae5d9 100644 --- a/drivers/input/joystick/iforce/iforce-usb.c +++ b/drivers/input/joystick/iforce/iforce-usb.c | |||
| @@ -212,6 +212,7 @@ static struct usb_device_id iforce_usb_ids [] = { | |||
| 212 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ | 212 | { USB_DEVICE(0x061c, 0xc0a4) }, /* ACT LABS Force RS */ |
| 213 | { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ | 213 | { USB_DEVICE(0x061c, 0xc084) }, /* ACT LABS Force RS */ |
| 214 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ | 214 | { USB_DEVICE(0x06f8, 0x0001) }, /* Guillemot Race Leader Force Feedback */ |
| 215 | { USB_DEVICE(0x06f8, 0x0003) }, /* Guillemot Jet Leader Force Feedback */ | ||
| 215 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ | 216 | { USB_DEVICE(0x06f8, 0x0004) }, /* Guillemot Force Feedback Racing Wheel */ |
| 216 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ | 217 | { USB_DEVICE(0x06f8, 0xa302) }, /* Guillemot Jet Leader 3D */ |
| 217 | { } /* Terminating entry */ | 218 | { } /* Terminating entry */ |
diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index 64c102355f53..a8293388d019 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig | |||
| @@ -143,19 +143,6 @@ config KEYBOARD_BFIN | |||
| 143 | To compile this driver as a module, choose M here: the | 143 | To compile this driver as a module, choose M here: the |
| 144 | module will be called bf54x-keys. | 144 | module will be called bf54x-keys. |
| 145 | 145 | ||
| 146 | config KEYBOARD_CORGI | ||
| 147 | tristate "Corgi keyboard (deprecated)" | ||
| 148 | depends on PXA_SHARPSL | ||
| 149 | help | ||
| 150 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C7xx | ||
| 151 | series of PDAs. | ||
| 152 | |||
| 153 | This driver is now deprecated, use generic GPIO based matrix | ||
| 154 | keyboard driver instead. | ||
| 155 | |||
| 156 | To compile this driver as a module, choose M here: the | ||
| 157 | module will be called corgikbd. | ||
| 158 | |||
| 159 | config KEYBOARD_LKKBD | 146 | config KEYBOARD_LKKBD |
| 160 | tristate "DECstation/VAXstation LK201/LK401 keyboard" | 147 | tristate "DECstation/VAXstation LK201/LK401 keyboard" |
| 161 | select SERIO | 148 | select SERIO |
| @@ -339,19 +326,6 @@ config KEYBOARD_PXA930_ROTARY | |||
| 339 | To compile this driver as a module, choose M here: the | 326 | To compile this driver as a module, choose M here: the |
| 340 | module will be called pxa930_rotary. | 327 | module will be called pxa930_rotary. |
| 341 | 328 | ||
| 342 | config KEYBOARD_SPITZ | ||
| 343 | tristate "Spitz keyboard (deprecated)" | ||
| 344 | depends on PXA_SHARPSL | ||
| 345 | help | ||
| 346 | Say Y here to enable the keyboard on the Sharp Zaurus SL-C1000, | ||
| 347 | SL-C3000 and Sl-C3100 series of PDAs. | ||
| 348 | |||
| 349 | This driver is now deprecated, use generic GPIO based matrix | ||
| 350 | keyboard driver instead. | ||
| 351 | |||
| 352 | To compile this driver as a module, choose M here: the | ||
| 353 | module will be called spitzkbd. | ||
| 354 | |||
| 355 | config KEYBOARD_STOWAWAY | 329 | config KEYBOARD_STOWAWAY |
| 356 | tristate "Stowaway keyboard" | 330 | tristate "Stowaway keyboard" |
| 357 | select SERIO | 331 | select SERIO |
| @@ -414,28 +388,6 @@ config KEYBOARD_TWL4030 | |||
| 414 | To compile this driver as a module, choose M here: the | 388 | To compile this driver as a module, choose M here: the |
| 415 | module will be called twl4030_keypad. | 389 | module will be called twl4030_keypad. |
| 416 | 390 | ||
| 417 | config KEYBOARD_TOSA | ||
| 418 | tristate "Tosa keyboard (deprecated)" | ||
| 419 | depends on MACH_TOSA | ||
| 420 | help | ||
| 421 | Say Y here to enable the keyboard on the Sharp Zaurus SL-6000x (Tosa) | ||
| 422 | |||
| 423 | This driver is now deprecated, use generic GPIO based matrix | ||
| 424 | keyboard driver instead. | ||
| 425 | |||
| 426 | To compile this driver as a module, choose M here: the | ||
| 427 | module will be called tosakbd. | ||
| 428 | |||
| 429 | config KEYBOARD_TOSA_USE_EXT_KEYCODES | ||
| 430 | bool "Tosa keyboard: use extended keycodes" | ||
| 431 | depends on KEYBOARD_TOSA | ||
| 432 | help | ||
| 433 | Say Y here to enable the tosa keyboard driver to generate extended | ||
| 434 | (>= 127) keycodes. Be aware, that they can't be correctly interpreted | ||
| 435 | by either console keyboard driver or by Kdrive keybd driver. | ||
| 436 | |||
| 437 | Say Y only if you know, what you are doing! | ||
| 438 | |||
| 439 | config KEYBOARD_XTKBD | 391 | config KEYBOARD_XTKBD |
| 440 | tristate "XT keyboard" | 392 | tristate "XT keyboard" |
| 441 | select SERIO | 393 | select SERIO |
diff --git a/drivers/input/keyboard/Makefile b/drivers/input/keyboard/Makefile index 706c6b5ed5f4..9a74127e4d17 100644 --- a/drivers/input/keyboard/Makefile +++ b/drivers/input/keyboard/Makefile | |||
| @@ -11,7 +11,6 @@ obj-$(CONFIG_KEYBOARD_AMIGA) += amikbd.o | |||
| 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o | 11 | obj-$(CONFIG_KEYBOARD_ATARI) += atakbd.o |
| 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o | 12 | obj-$(CONFIG_KEYBOARD_ATKBD) += atkbd.o |
| 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o | 13 | obj-$(CONFIG_KEYBOARD_BFIN) += bf54x-keys.o |
| 14 | obj-$(CONFIG_KEYBOARD_CORGI) += corgikbd.o | ||
| 15 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o | 14 | obj-$(CONFIG_KEYBOARD_DAVINCI) += davinci_keyscan.o |
| 16 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o | 15 | obj-$(CONFIG_KEYBOARD_EP93XX) += ep93xx_keypad.o |
| 17 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o | 16 | obj-$(CONFIG_KEYBOARD_GPIO) += gpio_keys.o |
| @@ -33,10 +32,8 @@ obj-$(CONFIG_KEYBOARD_PXA27x) += pxa27x_keypad.o | |||
| 33 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o | 32 | obj-$(CONFIG_KEYBOARD_PXA930_ROTARY) += pxa930_rotary.o |
| 34 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o | 33 | obj-$(CONFIG_KEYBOARD_QT2160) += qt2160.o |
| 35 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o | 34 | obj-$(CONFIG_KEYBOARD_SH_KEYSC) += sh_keysc.o |
| 36 | obj-$(CONFIG_KEYBOARD_SPITZ) += spitzkbd.o | ||
| 37 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o | 35 | obj-$(CONFIG_KEYBOARD_STOWAWAY) += stowaway.o |
| 38 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o | 36 | obj-$(CONFIG_KEYBOARD_SUNKBD) += sunkbd.o |
| 39 | obj-$(CONFIG_KEYBOARD_TOSA) += tosakbd.o | ||
| 40 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o | 37 | obj-$(CONFIG_KEYBOARD_TWL4030) += twl4030_keypad.o |
| 41 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o | 38 | obj-$(CONFIG_KEYBOARD_XTKBD) += xtkbd.o |
| 42 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o | 39 | obj-$(CONFIG_KEYBOARD_W90P910) += w90p910_keypad.o |
diff --git a/drivers/input/keyboard/corgikbd.c b/drivers/input/keyboard/corgikbd.c deleted file mode 100644 index 634af6a8e6b3..000000000000 --- a/drivers/input/keyboard/corgikbd.c +++ /dev/null | |||
| @@ -1,414 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Keyboard driver for Sharp Corgi models (SL-C7xx) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2004-2005 Richard Purdie | ||
| 5 | * | ||
| 6 | * Based on xtkbd.c/locomkbd.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/input.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/jiffies.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | |||
| 23 | #include <mach/corgi.h> | ||
| 24 | #include <mach/pxa2xx-gpio.h> | ||
| 25 | #include <asm/hardware/scoop.h> | ||
| 26 | |||
| 27 | #define KB_ROWS 8 | ||
| 28 | #define KB_COLS 12 | ||
| 29 | #define KB_ROWMASK(r) (1 << (r)) | ||
| 30 | #define SCANCODE(r,c) ( ((r)<<4) + (c) + 1 ) | ||
| 31 | /* zero code, 124 scancodes */ | ||
| 32 | #define NR_SCANCODES ( SCANCODE(KB_ROWS-1,KB_COLS-1) +1 +1 ) | ||
| 33 | |||
| 34 | #define SCAN_INTERVAL (50) /* ms */ | ||
| 35 | #define HINGE_SCAN_INTERVAL (250) /* ms */ | ||
| 36 | |||
| 37 | #define CORGI_KEY_CALENDER KEY_F1 | ||
| 38 | #define CORGI_KEY_ADDRESS KEY_F2 | ||
| 39 | #define CORGI_KEY_FN KEY_F3 | ||
| 40 | #define CORGI_KEY_CANCEL KEY_F4 | ||
| 41 | #define CORGI_KEY_OFF KEY_SUSPEND | ||
| 42 | #define CORGI_KEY_EXOK KEY_F5 | ||
| 43 | #define CORGI_KEY_EXCANCEL KEY_F6 | ||
| 44 | #define CORGI_KEY_EXJOGDOWN KEY_F7 | ||
| 45 | #define CORGI_KEY_EXJOGUP KEY_F8 | ||
| 46 | #define CORGI_KEY_JAP1 KEY_LEFTCTRL | ||
| 47 | #define CORGI_KEY_JAP2 KEY_LEFTALT | ||
| 48 | #define CORGI_KEY_MAIL KEY_F10 | ||
| 49 | #define CORGI_KEY_OK KEY_F11 | ||
| 50 | #define CORGI_KEY_MENU KEY_F12 | ||
| 51 | |||
| 52 | static unsigned char corgikbd_keycode[NR_SCANCODES] = { | ||
| 53 | 0, /* 0 */ | ||
| 54 | 0, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, 0, 0, 0, 0, 0, 0, 0, /* 1-16 */ | ||
| 55 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, 0, 0, 0, 0, 0, 0, 0, /* 17-32 */ | ||
| 56 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | ||
| 57 | CORGI_KEY_CALENDER, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | ||
| 58 | CORGI_KEY_ADDRESS, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, 0, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, /* 65-80 */ | ||
| 59 | CORGI_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, 0, CORGI_KEY_FN, 0, 0, 0, 0, /* 81-96 */ | ||
| 60 | KEY_SYSRQ, CORGI_KEY_JAP1, CORGI_KEY_JAP2, CORGI_KEY_CANCEL, CORGI_KEY_OK, CORGI_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0, /* 97-112 */ | ||
| 61 | CORGI_KEY_OFF, CORGI_KEY_EXOK, CORGI_KEY_EXCANCEL, CORGI_KEY_EXJOGDOWN, CORGI_KEY_EXJOGUP, 0, 0, 0, 0, 0, 0, 0, /* 113-124 */ | ||
| 62 | }; | ||
| 63 | |||
| 64 | |||
| 65 | struct corgikbd { | ||
| 66 | unsigned char keycode[ARRAY_SIZE(corgikbd_keycode)]; | ||
| 67 | struct input_dev *input; | ||
| 68 | |||
| 69 | spinlock_t lock; | ||
| 70 | struct timer_list timer; | ||
| 71 | struct timer_list htimer; | ||
| 72 | |||
| 73 | unsigned int suspended; | ||
| 74 | unsigned long suspend_jiffies; | ||
| 75 | }; | ||
| 76 | |||
| 77 | #define KB_DISCHARGE_DELAY 10 | ||
| 78 | #define KB_ACTIVATE_DELAY 10 | ||
| 79 | |||
| 80 | /* Helper functions for reading the keyboard matrix | ||
| 81 | * Note: We should really be using the generic gpio functions to alter | ||
| 82 | * GPDR but it requires a function call per GPIO bit which is | ||
| 83 | * excessive when we need to access 12 bits at once, multiple times. | ||
| 84 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
| 85 | * or similar. | ||
| 86 | */ | ||
| 87 | static inline void corgikbd_discharge_all(void) | ||
| 88 | { | ||
| 89 | /* STROBE All HiZ */ | ||
| 90 | GPCR2 = CORGI_GPIO_ALL_STROBE_BIT; | ||
| 91 | GPDR2 &= ~CORGI_GPIO_ALL_STROBE_BIT; | ||
| 92 | } | ||
| 93 | |||
| 94 | static inline void corgikbd_activate_all(void) | ||
| 95 | { | ||
| 96 | /* STROBE ALL -> High */ | ||
| 97 | GPSR2 = CORGI_GPIO_ALL_STROBE_BIT; | ||
| 98 | GPDR2 |= CORGI_GPIO_ALL_STROBE_BIT; | ||
| 99 | |||
| 100 | udelay(KB_DISCHARGE_DELAY); | ||
| 101 | |||
| 102 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ | ||
| 103 | GEDR1 = CORGI_GPIO_HIGH_SENSE_BIT; | ||
| 104 | GEDR2 = CORGI_GPIO_LOW_SENSE_BIT; | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void corgikbd_activate_col(int col) | ||
| 108 | { | ||
| 109 | /* STROBE col -> High, not col -> HiZ */ | ||
| 110 | GPSR2 = CORGI_GPIO_STROBE_BIT(col); | ||
| 111 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | ||
| 112 | } | ||
| 113 | |||
| 114 | static inline void corgikbd_reset_col(int col) | ||
| 115 | { | ||
| 116 | /* STROBE col -> Low */ | ||
| 117 | GPCR2 = CORGI_GPIO_STROBE_BIT(col); | ||
| 118 | /* STROBE col -> out, not col -> HiZ */ | ||
| 119 | GPDR2 = (GPDR2 & ~CORGI_GPIO_ALL_STROBE_BIT) | CORGI_GPIO_STROBE_BIT(col); | ||
| 120 | } | ||
| 121 | |||
| 122 | #define GET_ROWS_STATUS(c) (((GPLR1 & CORGI_GPIO_HIGH_SENSE_BIT) >> CORGI_GPIO_HIGH_SENSE_RSHIFT) | ((GPLR2 & CORGI_GPIO_LOW_SENSE_BIT) << CORGI_GPIO_LOW_SENSE_LSHIFT)) | ||
| 123 | |||
| 124 | /* | ||
| 125 | * The corgi keyboard only generates interrupts when a key is pressed. | ||
| 126 | * When a key is pressed, we enable a timer which then scans the | ||
| 127 | * keyboard to detect when the key is released. | ||
| 128 | */ | ||
| 129 | |||
| 130 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
| 131 | static void corgikbd_scankeyboard(struct corgikbd *corgikbd_data) | ||
| 132 | { | ||
| 133 | unsigned int row, col, rowd; | ||
| 134 | unsigned long flags; | ||
| 135 | unsigned int num_pressed; | ||
| 136 | |||
| 137 | if (corgikbd_data->suspended) | ||
| 138 | return; | ||
| 139 | |||
| 140 | spin_lock_irqsave(&corgikbd_data->lock, flags); | ||
| 141 | |||
| 142 | num_pressed = 0; | ||
| 143 | for (col = 0; col < KB_COLS; col++) { | ||
| 144 | /* | ||
| 145 | * Discharge the output driver capacitatance | ||
| 146 | * in the keyboard matrix. (Yes it is significant..) | ||
| 147 | */ | ||
| 148 | |||
| 149 | corgikbd_discharge_all(); | ||
| 150 | udelay(KB_DISCHARGE_DELAY); | ||
| 151 | |||
| 152 | corgikbd_activate_col(col); | ||
| 153 | udelay(KB_ACTIVATE_DELAY); | ||
| 154 | |||
| 155 | rowd = GET_ROWS_STATUS(col); | ||
| 156 | for (row = 0; row < KB_ROWS; row++) { | ||
| 157 | unsigned int scancode, pressed; | ||
| 158 | |||
| 159 | scancode = SCANCODE(row, col); | ||
| 160 | pressed = rowd & KB_ROWMASK(row); | ||
| 161 | |||
| 162 | input_report_key(corgikbd_data->input, corgikbd_data->keycode[scancode], pressed); | ||
| 163 | |||
| 164 | if (pressed) | ||
| 165 | num_pressed++; | ||
| 166 | |||
| 167 | if (pressed && (corgikbd_data->keycode[scancode] == CORGI_KEY_OFF) | ||
| 168 | && time_after(jiffies, corgikbd_data->suspend_jiffies + HZ)) { | ||
| 169 | input_event(corgikbd_data->input, EV_PWR, CORGI_KEY_OFF, 1); | ||
| 170 | corgikbd_data->suspend_jiffies=jiffies; | ||
| 171 | } | ||
| 172 | } | ||
| 173 | corgikbd_reset_col(col); | ||
| 174 | } | ||
| 175 | |||
| 176 | corgikbd_activate_all(); | ||
| 177 | |||
| 178 | input_sync(corgikbd_data->input); | ||
| 179 | |||
| 180 | /* if any keys are pressed, enable the timer */ | ||
| 181 | if (num_pressed) | ||
| 182 | mod_timer(&corgikbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); | ||
| 183 | |||
| 184 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); | ||
| 185 | } | ||
| 186 | |||
| 187 | /* | ||
| 188 | * corgi keyboard interrupt handler. | ||
| 189 | */ | ||
| 190 | static irqreturn_t corgikbd_interrupt(int irq, void *dev_id) | ||
| 191 | { | ||
| 192 | struct corgikbd *corgikbd_data = dev_id; | ||
| 193 | |||
| 194 | if (!timer_pending(&corgikbd_data->timer)) { | ||
| 195 | /** wait chattering delay **/ | ||
| 196 | udelay(20); | ||
| 197 | corgikbd_scankeyboard(corgikbd_data); | ||
| 198 | } | ||
| 199 | |||
| 200 | return IRQ_HANDLED; | ||
| 201 | } | ||
| 202 | |||
| 203 | /* | ||
| 204 | * corgi timer checking for released keys | ||
| 205 | */ | ||
| 206 | static void corgikbd_timer_callback(unsigned long data) | ||
| 207 | { | ||
| 208 | struct corgikbd *corgikbd_data = (struct corgikbd *) data; | ||
| 209 | corgikbd_scankeyboard(corgikbd_data); | ||
| 210 | } | ||
| 211 | |||
| 212 | /* | ||
| 213 | * The hinge switches generate no interrupt so they need to be | ||
| 214 | * monitored by a timer. | ||
| 215 | * | ||
| 216 | * We debounce the switches and pass them to the input system. | ||
| 217 | * | ||
| 218 | * gprr == 0x00 - Keyboard with Landscape Screen | ||
| 219 | * 0x08 - No Keyboard with Portrait Screen | ||
| 220 | * 0x0c - Keyboard and Screen Closed | ||
| 221 | */ | ||
| 222 | |||
| 223 | #define READ_GPIO_BIT(x) (GPLR(x) & GPIO_bit(x)) | ||
| 224 | #define HINGE_STABLE_COUNT 2 | ||
| 225 | static int sharpsl_hinge_state; | ||
| 226 | static int hinge_count; | ||
| 227 | |||
| 228 | static void corgikbd_hinge_timer(unsigned long data) | ||
| 229 | { | ||
| 230 | struct corgikbd *corgikbd_data = (struct corgikbd *) data; | ||
| 231 | unsigned long gprr; | ||
| 232 | unsigned long flags; | ||
| 233 | |||
| 234 | gprr = read_scoop_reg(&corgiscoop_device.dev, SCOOP_GPRR) & (CORGI_SCP_SWA | CORGI_SCP_SWB); | ||
| 235 | gprr |= (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0); | ||
| 236 | if (gprr != sharpsl_hinge_state) { | ||
| 237 | hinge_count = 0; | ||
| 238 | sharpsl_hinge_state = gprr; | ||
| 239 | } else if (hinge_count < HINGE_STABLE_COUNT) { | ||
| 240 | hinge_count++; | ||
| 241 | if (hinge_count >= HINGE_STABLE_COUNT) { | ||
| 242 | spin_lock_irqsave(&corgikbd_data->lock, flags); | ||
| 243 | |||
| 244 | input_report_switch(corgikbd_data->input, SW_LID, ((sharpsl_hinge_state & CORGI_SCP_SWA) != 0)); | ||
| 245 | input_report_switch(corgikbd_data->input, SW_TABLET_MODE, ((sharpsl_hinge_state & CORGI_SCP_SWB) != 0)); | ||
| 246 | input_report_switch(corgikbd_data->input, SW_HEADPHONE_INSERT, (READ_GPIO_BIT(CORGI_GPIO_AK_INT) != 0)); | ||
| 247 | input_sync(corgikbd_data->input); | ||
| 248 | |||
| 249 | spin_unlock_irqrestore(&corgikbd_data->lock, flags); | ||
| 250 | } | ||
| 251 | } | ||
| 252 | mod_timer(&corgikbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 253 | } | ||
| 254 | |||
| 255 | #ifdef CONFIG_PM | ||
| 256 | static int corgikbd_suspend(struct platform_device *dev, pm_message_t state) | ||
| 257 | { | ||
| 258 | int i; | ||
| 259 | struct corgikbd *corgikbd = platform_get_drvdata(dev); | ||
| 260 | |||
| 261 | corgikbd->suspended = 1; | ||
| 262 | /* strobe 0 is the power key so this can't be made an input for | ||
| 263 | powersaving therefore i = 1 */ | ||
| 264 | for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) | ||
| 265 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_IN); | ||
| 266 | |||
| 267 | return 0; | ||
| 268 | } | ||
| 269 | |||
| 270 | static int corgikbd_resume(struct platform_device *dev) | ||
| 271 | { | ||
| 272 | int i; | ||
| 273 | struct corgikbd *corgikbd = platform_get_drvdata(dev); | ||
| 274 | |||
| 275 | for (i = 1; i < CORGI_KEY_STROBE_NUM; i++) | ||
| 276 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 277 | |||
| 278 | /* Upon resume, ignore the suspend key for a short while */ | ||
| 279 | corgikbd->suspend_jiffies=jiffies; | ||
| 280 | corgikbd->suspended = 0; | ||
| 281 | |||
| 282 | return 0; | ||
| 283 | } | ||
| 284 | #else | ||
| 285 | #define corgikbd_suspend NULL | ||
| 286 | #define corgikbd_resume NULL | ||
| 287 | #endif | ||
| 288 | |||
| 289 | static int __devinit corgikbd_probe(struct platform_device *pdev) | ||
| 290 | { | ||
| 291 | struct corgikbd *corgikbd; | ||
| 292 | struct input_dev *input_dev; | ||
| 293 | int i, err = -ENOMEM; | ||
| 294 | |||
| 295 | corgikbd = kzalloc(sizeof(struct corgikbd), GFP_KERNEL); | ||
| 296 | input_dev = input_allocate_device(); | ||
| 297 | if (!corgikbd || !input_dev) | ||
| 298 | goto fail; | ||
| 299 | |||
| 300 | platform_set_drvdata(pdev, corgikbd); | ||
| 301 | |||
| 302 | corgikbd->input = input_dev; | ||
| 303 | spin_lock_init(&corgikbd->lock); | ||
| 304 | |||
| 305 | /* Init Keyboard rescan timer */ | ||
| 306 | init_timer(&corgikbd->timer); | ||
| 307 | corgikbd->timer.function = corgikbd_timer_callback; | ||
| 308 | corgikbd->timer.data = (unsigned long) corgikbd; | ||
| 309 | |||
| 310 | /* Init Hinge Timer */ | ||
| 311 | init_timer(&corgikbd->htimer); | ||
| 312 | corgikbd->htimer.function = corgikbd_hinge_timer; | ||
| 313 | corgikbd->htimer.data = (unsigned long) corgikbd; | ||
| 314 | |||
| 315 | corgikbd->suspend_jiffies=jiffies; | ||
| 316 | |||
| 317 | memcpy(corgikbd->keycode, corgikbd_keycode, sizeof(corgikbd->keycode)); | ||
| 318 | |||
| 319 | input_dev->name = "Corgi Keyboard"; | ||
| 320 | input_dev->phys = "corgikbd/input0"; | ||
| 321 | input_dev->id.bustype = BUS_HOST; | ||
| 322 | input_dev->id.vendor = 0x0001; | ||
| 323 | input_dev->id.product = 0x0001; | ||
| 324 | input_dev->id.version = 0x0100; | ||
| 325 | input_dev->dev.parent = &pdev->dev; | ||
| 326 | |||
| 327 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
| 328 | BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); | ||
| 329 | input_dev->keycode = corgikbd->keycode; | ||
| 330 | input_dev->keycodesize = sizeof(unsigned char); | ||
| 331 | input_dev->keycodemax = ARRAY_SIZE(corgikbd_keycode); | ||
| 332 | |||
| 333 | for (i = 0; i < ARRAY_SIZE(corgikbd_keycode); i++) | ||
| 334 | set_bit(corgikbd->keycode[i], input_dev->keybit); | ||
| 335 | clear_bit(0, input_dev->keybit); | ||
| 336 | set_bit(SW_LID, input_dev->swbit); | ||
| 337 | set_bit(SW_TABLET_MODE, input_dev->swbit); | ||
| 338 | set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); | ||
| 339 | |||
| 340 | err = input_register_device(corgikbd->input); | ||
| 341 | if (err) | ||
| 342 | goto fail; | ||
| 343 | |||
| 344 | mod_timer(&corgikbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 345 | |||
| 346 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
| 347 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) { | ||
| 348 | pxa_gpio_mode(CORGI_GPIO_KEY_SENSE(i) | GPIO_IN); | ||
| 349 | if (request_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd_interrupt, | ||
| 350 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
| 351 | "corgikbd", corgikbd)) | ||
| 352 | printk(KERN_WARNING "corgikbd: Can't get IRQ: %d!\n", i); | ||
| 353 | } | ||
| 354 | |||
| 355 | /* Set Strobe lines as outputs - set high */ | ||
| 356 | for (i = 0; i < CORGI_KEY_STROBE_NUM; i++) | ||
| 357 | pxa_gpio_mode(CORGI_GPIO_KEY_STROBE(i) | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 358 | |||
| 359 | /* Setup the headphone jack as an input */ | ||
| 360 | pxa_gpio_mode(CORGI_GPIO_AK_INT | GPIO_IN); | ||
| 361 | |||
| 362 | return 0; | ||
| 363 | |||
| 364 | fail: input_free_device(input_dev); | ||
| 365 | kfree(corgikbd); | ||
| 366 | return err; | ||
| 367 | } | ||
| 368 | |||
| 369 | static int __devexit corgikbd_remove(struct platform_device *pdev) | ||
| 370 | { | ||
| 371 | int i; | ||
| 372 | struct corgikbd *corgikbd = platform_get_drvdata(pdev); | ||
| 373 | |||
| 374 | for (i = 0; i < CORGI_KEY_SENSE_NUM; i++) | ||
| 375 | free_irq(CORGI_IRQ_GPIO_KEY_SENSE(i), corgikbd); | ||
| 376 | |||
| 377 | del_timer_sync(&corgikbd->htimer); | ||
| 378 | del_timer_sync(&corgikbd->timer); | ||
| 379 | |||
| 380 | input_unregister_device(corgikbd->input); | ||
| 381 | |||
| 382 | kfree(corgikbd); | ||
| 383 | |||
| 384 | return 0; | ||
| 385 | } | ||
| 386 | |||
| 387 | static struct platform_driver corgikbd_driver = { | ||
| 388 | .probe = corgikbd_probe, | ||
| 389 | .remove = __devexit_p(corgikbd_remove), | ||
| 390 | .suspend = corgikbd_suspend, | ||
| 391 | .resume = corgikbd_resume, | ||
| 392 | .driver = { | ||
| 393 | .name = "corgi-keyboard", | ||
| 394 | .owner = THIS_MODULE, | ||
| 395 | }, | ||
| 396 | }; | ||
| 397 | |||
| 398 | static int __init corgikbd_init(void) | ||
| 399 | { | ||
| 400 | return platform_driver_register(&corgikbd_driver); | ||
| 401 | } | ||
| 402 | |||
| 403 | static void __exit corgikbd_exit(void) | ||
| 404 | { | ||
| 405 | platform_driver_unregister(&corgikbd_driver); | ||
| 406 | } | ||
| 407 | |||
| 408 | module_init(corgikbd_init); | ||
| 409 | module_exit(corgikbd_exit); | ||
| 410 | |||
| 411 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
| 412 | MODULE_DESCRIPTION("Corgi Keyboard Driver"); | ||
| 413 | MODULE_LICENSE("GPL v2"); | ||
| 414 | MODULE_ALIAS("platform:corgi-keyboard"); | ||
diff --git a/drivers/input/keyboard/spitzkbd.c b/drivers/input/keyboard/spitzkbd.c deleted file mode 100644 index 13967422658c..000000000000 --- a/drivers/input/keyboard/spitzkbd.c +++ /dev/null | |||
| @@ -1,496 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Keyboard driver for Sharp Spitz, Borzoi and Akita (SL-Cxx00 series) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Richard Purdie | ||
| 5 | * | ||
| 6 | * Based on corgikbd.c | ||
| 7 | * | ||
| 8 | * This program is free software; you can redistribute it and/or modify | ||
| 9 | * it under the terms of the GNU General Public License version 2 as | ||
| 10 | * published by the Free Software Foundation. | ||
| 11 | * | ||
| 12 | */ | ||
| 13 | |||
| 14 | #include <linux/delay.h> | ||
| 15 | #include <linux/platform_device.h> | ||
| 16 | #include <linux/init.h> | ||
| 17 | #include <linux/input.h> | ||
| 18 | #include <linux/interrupt.h> | ||
| 19 | #include <linux/jiffies.h> | ||
| 20 | #include <linux/module.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | |||
| 23 | #include <mach/spitz.h> | ||
| 24 | #include <mach/pxa2xx-gpio.h> | ||
| 25 | |||
| 26 | #define KB_ROWS 7 | ||
| 27 | #define KB_COLS 11 | ||
| 28 | #define KB_ROWMASK(r) (1 << (r)) | ||
| 29 | #define SCANCODE(r,c) (((r)<<4) + (c) + 1) | ||
| 30 | #define NR_SCANCODES ((KB_ROWS<<4) + 1) | ||
| 31 | |||
| 32 | #define SCAN_INTERVAL (50) /* ms */ | ||
| 33 | #define HINGE_SCAN_INTERVAL (150) /* ms */ | ||
| 34 | |||
| 35 | #define SPITZ_KEY_CALENDER KEY_F1 | ||
| 36 | #define SPITZ_KEY_ADDRESS KEY_F2 | ||
| 37 | #define SPITZ_KEY_FN KEY_F3 | ||
| 38 | #define SPITZ_KEY_CANCEL KEY_F4 | ||
| 39 | #define SPITZ_KEY_EXOK KEY_F5 | ||
| 40 | #define SPITZ_KEY_EXCANCEL KEY_F6 | ||
| 41 | #define SPITZ_KEY_EXJOGDOWN KEY_F7 | ||
| 42 | #define SPITZ_KEY_EXJOGUP KEY_F8 | ||
| 43 | #define SPITZ_KEY_JAP1 KEY_LEFTALT | ||
| 44 | #define SPITZ_KEY_JAP2 KEY_RIGHTCTRL | ||
| 45 | #define SPITZ_KEY_SYNC KEY_F9 | ||
| 46 | #define SPITZ_KEY_MAIL KEY_F10 | ||
| 47 | #define SPITZ_KEY_OK KEY_F11 | ||
| 48 | #define SPITZ_KEY_MENU KEY_F12 | ||
| 49 | |||
| 50 | static unsigned char spitzkbd_keycode[NR_SCANCODES] = { | ||
| 51 | 0, /* 0 */ | ||
| 52 | KEY_LEFTCTRL, KEY_1, KEY_3, KEY_5, KEY_6, KEY_7, KEY_9, KEY_0, KEY_BACKSPACE, SPITZ_KEY_EXOK, SPITZ_KEY_EXCANCEL, 0, 0, 0, 0, 0, /* 1-16 */ | ||
| 53 | 0, KEY_2, KEY_4, KEY_R, KEY_Y, KEY_8, KEY_I, KEY_O, KEY_P, SPITZ_KEY_EXJOGDOWN, SPITZ_KEY_EXJOGUP, 0, 0, 0, 0, 0, /* 17-32 */ | ||
| 54 | KEY_TAB, KEY_Q, KEY_E, KEY_T, KEY_G, KEY_U, KEY_J, KEY_K, 0, 0, 0, 0, 0, 0, 0, 0, /* 33-48 */ | ||
| 55 | SPITZ_KEY_ADDRESS, KEY_W, KEY_S, KEY_F, KEY_V, KEY_H, KEY_M, KEY_L, 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, /* 49-64 */ | ||
| 56 | SPITZ_KEY_CALENDER, KEY_A, KEY_D, KEY_C, KEY_B, KEY_N, KEY_DOT, 0, KEY_ENTER, KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, /* 65-80 */ | ||
| 57 | SPITZ_KEY_MAIL, KEY_Z, KEY_X, KEY_MINUS, KEY_SPACE, KEY_COMMA, 0, KEY_UP, 0, 0, SPITZ_KEY_FN, 0, 0, 0, 0, 0, /* 81-96 */ | ||
| 58 | KEY_SYSRQ, SPITZ_KEY_JAP1, SPITZ_KEY_JAP2, SPITZ_KEY_CANCEL, SPITZ_KEY_OK, SPITZ_KEY_MENU, KEY_LEFT, KEY_DOWN, KEY_RIGHT, 0, 0, 0, 0, 0, 0, 0 /* 97-112 */ | ||
| 59 | }; | ||
| 60 | |||
| 61 | static int spitz_strobes[] = { | ||
| 62 | SPITZ_GPIO_KEY_STROBE0, | ||
| 63 | SPITZ_GPIO_KEY_STROBE1, | ||
| 64 | SPITZ_GPIO_KEY_STROBE2, | ||
| 65 | SPITZ_GPIO_KEY_STROBE3, | ||
| 66 | SPITZ_GPIO_KEY_STROBE4, | ||
| 67 | SPITZ_GPIO_KEY_STROBE5, | ||
| 68 | SPITZ_GPIO_KEY_STROBE6, | ||
| 69 | SPITZ_GPIO_KEY_STROBE7, | ||
| 70 | SPITZ_GPIO_KEY_STROBE8, | ||
| 71 | SPITZ_GPIO_KEY_STROBE9, | ||
| 72 | SPITZ_GPIO_KEY_STROBE10, | ||
| 73 | }; | ||
| 74 | |||
| 75 | static int spitz_senses[] = { | ||
| 76 | SPITZ_GPIO_KEY_SENSE0, | ||
| 77 | SPITZ_GPIO_KEY_SENSE1, | ||
| 78 | SPITZ_GPIO_KEY_SENSE2, | ||
| 79 | SPITZ_GPIO_KEY_SENSE3, | ||
| 80 | SPITZ_GPIO_KEY_SENSE4, | ||
| 81 | SPITZ_GPIO_KEY_SENSE5, | ||
| 82 | SPITZ_GPIO_KEY_SENSE6, | ||
| 83 | }; | ||
| 84 | |||
| 85 | struct spitzkbd { | ||
| 86 | unsigned char keycode[ARRAY_SIZE(spitzkbd_keycode)]; | ||
| 87 | struct input_dev *input; | ||
| 88 | char phys[32]; | ||
| 89 | |||
| 90 | spinlock_t lock; | ||
| 91 | struct timer_list timer; | ||
| 92 | struct timer_list htimer; | ||
| 93 | |||
| 94 | unsigned int suspended; | ||
| 95 | unsigned long suspend_jiffies; | ||
| 96 | }; | ||
| 97 | |||
| 98 | #define KB_DISCHARGE_DELAY 10 | ||
| 99 | #define KB_ACTIVATE_DELAY 10 | ||
| 100 | |||
| 101 | /* Helper functions for reading the keyboard matrix | ||
| 102 | * Note: We should really be using the generic gpio functions to alter | ||
| 103 | * GPDR but it requires a function call per GPIO bit which is | ||
| 104 | * excessive when we need to access 11 bits at once, multiple times. | ||
| 105 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
| 106 | * or similar. | ||
| 107 | */ | ||
| 108 | static inline void spitzkbd_discharge_all(void) | ||
| 109 | { | ||
| 110 | /* STROBE All HiZ */ | ||
| 111 | GPCR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
| 112 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
| 113 | GPCR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
| 114 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
| 115 | GPCR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
| 116 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
| 117 | GPCR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
| 118 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
| 119 | } | ||
| 120 | |||
| 121 | static inline void spitzkbd_activate_all(void) | ||
| 122 | { | ||
| 123 | /* STROBE ALL -> High */ | ||
| 124 | GPSR0 = SPITZ_GPIO_G0_STROBE_BIT; | ||
| 125 | GPDR0 |= SPITZ_GPIO_G0_STROBE_BIT; | ||
| 126 | GPSR1 = SPITZ_GPIO_G1_STROBE_BIT; | ||
| 127 | GPDR1 |= SPITZ_GPIO_G1_STROBE_BIT; | ||
| 128 | GPSR2 = SPITZ_GPIO_G2_STROBE_BIT; | ||
| 129 | GPDR2 |= SPITZ_GPIO_G2_STROBE_BIT; | ||
| 130 | GPSR3 = SPITZ_GPIO_G3_STROBE_BIT; | ||
| 131 | GPDR3 |= SPITZ_GPIO_G3_STROBE_BIT; | ||
| 132 | |||
| 133 | udelay(KB_DISCHARGE_DELAY); | ||
| 134 | |||
| 135 | /* Clear any interrupts we may have triggered when altering the GPIO lines */ | ||
| 136 | GEDR0 = SPITZ_GPIO_G0_SENSE_BIT; | ||
| 137 | GEDR1 = SPITZ_GPIO_G1_SENSE_BIT; | ||
| 138 | GEDR2 = SPITZ_GPIO_G2_SENSE_BIT; | ||
| 139 | GEDR3 = SPITZ_GPIO_G3_SENSE_BIT; | ||
| 140 | } | ||
| 141 | |||
| 142 | static inline void spitzkbd_activate_col(int col) | ||
| 143 | { | ||
| 144 | int gpio = spitz_strobes[col]; | ||
| 145 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
| 146 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
| 147 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
| 148 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
| 149 | GPSR(gpio) = GPIO_bit(gpio); | ||
| 150 | GPDR(gpio) |= GPIO_bit(gpio); | ||
| 151 | } | ||
| 152 | |||
| 153 | static inline void spitzkbd_reset_col(int col) | ||
| 154 | { | ||
| 155 | int gpio = spitz_strobes[col]; | ||
| 156 | GPDR0 &= ~SPITZ_GPIO_G0_STROBE_BIT; | ||
| 157 | GPDR1 &= ~SPITZ_GPIO_G1_STROBE_BIT; | ||
| 158 | GPDR2 &= ~SPITZ_GPIO_G2_STROBE_BIT; | ||
| 159 | GPDR3 &= ~SPITZ_GPIO_G3_STROBE_BIT; | ||
| 160 | GPCR(gpio) = GPIO_bit(gpio); | ||
| 161 | GPDR(gpio) |= GPIO_bit(gpio); | ||
| 162 | } | ||
| 163 | |||
| 164 | static inline int spitzkbd_get_row_status(int col) | ||
| 165 | { | ||
| 166 | return ((GPLR0 >> 12) & 0x01) | ((GPLR0 >> 16) & 0x02) | ||
| 167 | | ((GPLR2 >> 25) & 0x04) | ((GPLR1 << 1) & 0x08) | ||
| 168 | | ((GPLR1 >> 0) & 0x10) | ((GPLR1 >> 1) & 0x60); | ||
| 169 | } | ||
| 170 | |||
| 171 | /* | ||
| 172 | * The spitz keyboard only generates interrupts when a key is pressed. | ||
| 173 | * When a key is pressed, we enable a timer which then scans the | ||
| 174 | * keyboard to detect when the key is released. | ||
| 175 | */ | ||
| 176 | |||
| 177 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
| 178 | static void spitzkbd_scankeyboard(struct spitzkbd *spitzkbd_data) | ||
| 179 | { | ||
| 180 | unsigned int row, col, rowd; | ||
| 181 | unsigned long flags; | ||
| 182 | unsigned int num_pressed, pwrkey = ((GPLR(SPITZ_GPIO_ON_KEY) & GPIO_bit(SPITZ_GPIO_ON_KEY)) != 0); | ||
| 183 | |||
| 184 | if (spitzkbd_data->suspended) | ||
| 185 | return; | ||
| 186 | |||
| 187 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
| 188 | |||
| 189 | num_pressed = 0; | ||
| 190 | for (col = 0; col < KB_COLS; col++) { | ||
| 191 | /* | ||
| 192 | * Discharge the output driver capacitatance | ||
| 193 | * in the keyboard matrix. (Yes it is significant..) | ||
| 194 | */ | ||
| 195 | |||
| 196 | spitzkbd_discharge_all(); | ||
| 197 | udelay(KB_DISCHARGE_DELAY); | ||
| 198 | |||
| 199 | spitzkbd_activate_col(col); | ||
| 200 | udelay(KB_ACTIVATE_DELAY); | ||
| 201 | |||
| 202 | rowd = spitzkbd_get_row_status(col); | ||
| 203 | for (row = 0; row < KB_ROWS; row++) { | ||
| 204 | unsigned int scancode, pressed; | ||
| 205 | |||
| 206 | scancode = SCANCODE(row, col); | ||
| 207 | pressed = rowd & KB_ROWMASK(row); | ||
| 208 | |||
| 209 | input_report_key(spitzkbd_data->input, spitzkbd_data->keycode[scancode], pressed); | ||
| 210 | |||
| 211 | if (pressed) | ||
| 212 | num_pressed++; | ||
| 213 | } | ||
| 214 | spitzkbd_reset_col(col); | ||
| 215 | } | ||
| 216 | |||
| 217 | spitzkbd_activate_all(); | ||
| 218 | |||
| 219 | input_report_key(spitzkbd_data->input, SPITZ_KEY_SYNC, (GPLR(SPITZ_GPIO_SYNC) & GPIO_bit(SPITZ_GPIO_SYNC)) != 0 ); | ||
| 220 | input_report_key(spitzkbd_data->input, KEY_SUSPEND, pwrkey); | ||
| 221 | |||
| 222 | if (pwrkey && time_after(jiffies, spitzkbd_data->suspend_jiffies + msecs_to_jiffies(1000))) { | ||
| 223 | input_event(spitzkbd_data->input, EV_PWR, KEY_SUSPEND, 1); | ||
| 224 | spitzkbd_data->suspend_jiffies = jiffies; | ||
| 225 | } | ||
| 226 | |||
| 227 | input_sync(spitzkbd_data->input); | ||
| 228 | |||
| 229 | /* if any keys are pressed, enable the timer */ | ||
| 230 | if (num_pressed) | ||
| 231 | mod_timer(&spitzkbd_data->timer, jiffies + msecs_to_jiffies(SCAN_INTERVAL)); | ||
| 232 | |||
| 233 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
| 234 | } | ||
| 235 | |||
| 236 | /* | ||
| 237 | * spitz keyboard interrupt handler. | ||
| 238 | */ | ||
| 239 | static irqreturn_t spitzkbd_interrupt(int irq, void *dev_id) | ||
| 240 | { | ||
| 241 | struct spitzkbd *spitzkbd_data = dev_id; | ||
| 242 | |||
| 243 | if (!timer_pending(&spitzkbd_data->timer)) { | ||
| 244 | /** wait chattering delay **/ | ||
| 245 | udelay(20); | ||
| 246 | spitzkbd_scankeyboard(spitzkbd_data); | ||
| 247 | } | ||
| 248 | |||
| 249 | return IRQ_HANDLED; | ||
| 250 | } | ||
| 251 | |||
| 252 | /* | ||
| 253 | * spitz timer checking for released keys | ||
| 254 | */ | ||
| 255 | static void spitzkbd_timer_callback(unsigned long data) | ||
| 256 | { | ||
| 257 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
| 258 | |||
| 259 | spitzkbd_scankeyboard(spitzkbd_data); | ||
| 260 | } | ||
| 261 | |||
| 262 | /* | ||
| 263 | * The hinge switches generate an interrupt. | ||
| 264 | * We debounce the switches and pass them to the input system. | ||
| 265 | */ | ||
| 266 | |||
| 267 | static irqreturn_t spitzkbd_hinge_isr(int irq, void *dev_id) | ||
| 268 | { | ||
| 269 | struct spitzkbd *spitzkbd_data = dev_id; | ||
| 270 | |||
| 271 | if (!timer_pending(&spitzkbd_data->htimer)) | ||
| 272 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 273 | |||
| 274 | return IRQ_HANDLED; | ||
| 275 | } | ||
| 276 | |||
| 277 | #define HINGE_STABLE_COUNT 2 | ||
| 278 | static int sharpsl_hinge_state; | ||
| 279 | static int hinge_count; | ||
| 280 | |||
| 281 | static void spitzkbd_hinge_timer(unsigned long data) | ||
| 282 | { | ||
| 283 | struct spitzkbd *spitzkbd_data = (struct spitzkbd *) data; | ||
| 284 | unsigned long state; | ||
| 285 | unsigned long flags; | ||
| 286 | |||
| 287 | state = GPLR(SPITZ_GPIO_SWA) & (GPIO_bit(SPITZ_GPIO_SWA)|GPIO_bit(SPITZ_GPIO_SWB)); | ||
| 288 | state |= (GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)); | ||
| 289 | if (state != sharpsl_hinge_state) { | ||
| 290 | hinge_count = 0; | ||
| 291 | sharpsl_hinge_state = state; | ||
| 292 | } else if (hinge_count < HINGE_STABLE_COUNT) { | ||
| 293 | hinge_count++; | ||
| 294 | } | ||
| 295 | |||
| 296 | if (hinge_count >= HINGE_STABLE_COUNT) { | ||
| 297 | spin_lock_irqsave(&spitzkbd_data->lock, flags); | ||
| 298 | |||
| 299 | input_report_switch(spitzkbd_data->input, SW_LID, ((GPLR(SPITZ_GPIO_SWA) & GPIO_bit(SPITZ_GPIO_SWA)) != 0)); | ||
| 300 | input_report_switch(spitzkbd_data->input, SW_TABLET_MODE, ((GPLR(SPITZ_GPIO_SWB) & GPIO_bit(SPITZ_GPIO_SWB)) != 0)); | ||
| 301 | input_report_switch(spitzkbd_data->input, SW_HEADPHONE_INSERT, ((GPLR(SPITZ_GPIO_AK_INT) & GPIO_bit(SPITZ_GPIO_AK_INT)) != 0)); | ||
| 302 | input_sync(spitzkbd_data->input); | ||
| 303 | |||
| 304 | spin_unlock_irqrestore(&spitzkbd_data->lock, flags); | ||
| 305 | } else { | ||
| 306 | mod_timer(&spitzkbd_data->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 307 | } | ||
| 308 | } | ||
| 309 | |||
| 310 | #ifdef CONFIG_PM | ||
| 311 | static int spitzkbd_suspend(struct platform_device *dev, pm_message_t state) | ||
| 312 | { | ||
| 313 | int i; | ||
| 314 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
| 315 | spitzkbd->suspended = 1; | ||
| 316 | |||
| 317 | /* Set Strobe lines as inputs - *except* strobe line 0 leave this | ||
| 318 | enabled so we can detect a power button press for resume */ | ||
| 319 | for (i = 1; i < SPITZ_KEY_STROBE_NUM; i++) | ||
| 320 | pxa_gpio_mode(spitz_strobes[i] | GPIO_IN); | ||
| 321 | |||
| 322 | return 0; | ||
| 323 | } | ||
| 324 | |||
| 325 | static int spitzkbd_resume(struct platform_device *dev) | ||
| 326 | { | ||
| 327 | int i; | ||
| 328 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
| 329 | |||
| 330 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
| 331 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 332 | |||
| 333 | /* Upon resume, ignore the suspend key for a short while */ | ||
| 334 | spitzkbd->suspend_jiffies = jiffies; | ||
| 335 | spitzkbd->suspended = 0; | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | #else | ||
| 340 | #define spitzkbd_suspend NULL | ||
| 341 | #define spitzkbd_resume NULL | ||
| 342 | #endif | ||
| 343 | |||
| 344 | static int __devinit spitzkbd_probe(struct platform_device *dev) | ||
| 345 | { | ||
| 346 | struct spitzkbd *spitzkbd; | ||
| 347 | struct input_dev *input_dev; | ||
| 348 | int i, err = -ENOMEM; | ||
| 349 | |||
| 350 | spitzkbd = kzalloc(sizeof(struct spitzkbd), GFP_KERNEL); | ||
| 351 | input_dev = input_allocate_device(); | ||
| 352 | if (!spitzkbd || !input_dev) | ||
| 353 | goto fail; | ||
| 354 | |||
| 355 | platform_set_drvdata(dev, spitzkbd); | ||
| 356 | strcpy(spitzkbd->phys, "spitzkbd/input0"); | ||
| 357 | |||
| 358 | spin_lock_init(&spitzkbd->lock); | ||
| 359 | |||
| 360 | /* Init Keyboard rescan timer */ | ||
| 361 | init_timer(&spitzkbd->timer); | ||
| 362 | spitzkbd->timer.function = spitzkbd_timer_callback; | ||
| 363 | spitzkbd->timer.data = (unsigned long) spitzkbd; | ||
| 364 | |||
| 365 | /* Init Hinge Timer */ | ||
| 366 | init_timer(&spitzkbd->htimer); | ||
| 367 | spitzkbd->htimer.function = spitzkbd_hinge_timer; | ||
| 368 | spitzkbd->htimer.data = (unsigned long) spitzkbd; | ||
| 369 | |||
| 370 | spitzkbd->suspend_jiffies = jiffies; | ||
| 371 | |||
| 372 | spitzkbd->input = input_dev; | ||
| 373 | |||
| 374 | input_dev->name = "Spitz Keyboard"; | ||
| 375 | input_dev->phys = spitzkbd->phys; | ||
| 376 | input_dev->dev.parent = &dev->dev; | ||
| 377 | |||
| 378 | input_dev->id.bustype = BUS_HOST; | ||
| 379 | input_dev->id.vendor = 0x0001; | ||
| 380 | input_dev->id.product = 0x0001; | ||
| 381 | input_dev->id.version = 0x0100; | ||
| 382 | |||
| 383 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) | | ||
| 384 | BIT_MASK(EV_PWR) | BIT_MASK(EV_SW); | ||
| 385 | input_dev->keycode = spitzkbd->keycode; | ||
| 386 | input_dev->keycodesize = sizeof(unsigned char); | ||
| 387 | input_dev->keycodemax = ARRAY_SIZE(spitzkbd_keycode); | ||
| 388 | |||
| 389 | memcpy(spitzkbd->keycode, spitzkbd_keycode, sizeof(spitzkbd->keycode)); | ||
| 390 | for (i = 0; i < ARRAY_SIZE(spitzkbd_keycode); i++) | ||
| 391 | set_bit(spitzkbd->keycode[i], input_dev->keybit); | ||
| 392 | clear_bit(0, input_dev->keybit); | ||
| 393 | set_bit(KEY_SUSPEND, input_dev->keybit); | ||
| 394 | set_bit(SW_LID, input_dev->swbit); | ||
| 395 | set_bit(SW_TABLET_MODE, input_dev->swbit); | ||
| 396 | set_bit(SW_HEADPHONE_INSERT, input_dev->swbit); | ||
| 397 | |||
| 398 | err = input_register_device(input_dev); | ||
| 399 | if (err) | ||
| 400 | goto fail; | ||
| 401 | |||
| 402 | mod_timer(&spitzkbd->htimer, jiffies + msecs_to_jiffies(HINGE_SCAN_INTERVAL)); | ||
| 403 | |||
| 404 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
| 405 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) { | ||
| 406 | pxa_gpio_mode(spitz_senses[i] | GPIO_IN); | ||
| 407 | if (request_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd_interrupt, | ||
| 408 | IRQF_DISABLED|IRQF_TRIGGER_RISING, | ||
| 409 | "Spitzkbd Sense", spitzkbd)) | ||
| 410 | printk(KERN_WARNING "spitzkbd: Can't get Sense IRQ: %d!\n", i); | ||
| 411 | } | ||
| 412 | |||
| 413 | /* Set Strobe lines as outputs - set high */ | ||
| 414 | for (i = 0; i < SPITZ_KEY_STROBE_NUM; i++) | ||
| 415 | pxa_gpio_mode(spitz_strobes[i] | GPIO_OUT | GPIO_DFLT_HIGH); | ||
| 416 | |||
| 417 | pxa_gpio_mode(SPITZ_GPIO_SYNC | GPIO_IN); | ||
| 418 | pxa_gpio_mode(SPITZ_GPIO_ON_KEY | GPIO_IN); | ||
| 419 | pxa_gpio_mode(SPITZ_GPIO_SWA | GPIO_IN); | ||
| 420 | pxa_gpio_mode(SPITZ_GPIO_SWB | GPIO_IN); | ||
| 421 | |||
| 422 | request_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd_interrupt, | ||
| 423 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 424 | "Spitzkbd Sync", spitzkbd); | ||
| 425 | request_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd_interrupt, | ||
| 426 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 427 | "Spitzkbd PwrOn", spitzkbd); | ||
| 428 | request_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd_hinge_isr, | ||
| 429 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 430 | "Spitzkbd SWA", spitzkbd); | ||
| 431 | request_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd_hinge_isr, | ||
| 432 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 433 | "Spitzkbd SWB", spitzkbd); | ||
| 434 | request_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd_hinge_isr, | ||
| 435 | IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, | ||
| 436 | "Spitzkbd HP", spitzkbd); | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | |||
| 440 | fail: input_free_device(input_dev); | ||
| 441 | kfree(spitzkbd); | ||
| 442 | return err; | ||
| 443 | } | ||
| 444 | |||
| 445 | static int __devexit spitzkbd_remove(struct platform_device *dev) | ||
| 446 | { | ||
| 447 | int i; | ||
| 448 | struct spitzkbd *spitzkbd = platform_get_drvdata(dev); | ||
| 449 | |||
| 450 | for (i = 0; i < SPITZ_KEY_SENSE_NUM; i++) | ||
| 451 | free_irq(IRQ_GPIO(spitz_senses[i]), spitzkbd); | ||
| 452 | |||
| 453 | free_irq(SPITZ_IRQ_GPIO_SYNC, spitzkbd); | ||
| 454 | free_irq(SPITZ_IRQ_GPIO_ON_KEY, spitzkbd); | ||
| 455 | free_irq(SPITZ_IRQ_GPIO_SWA, spitzkbd); | ||
| 456 | free_irq(SPITZ_IRQ_GPIO_SWB, spitzkbd); | ||
| 457 | free_irq(SPITZ_IRQ_GPIO_AK_INT, spitzkbd); | ||
| 458 | |||
| 459 | del_timer_sync(&spitzkbd->htimer); | ||
| 460 | del_timer_sync(&spitzkbd->timer); | ||
| 461 | |||
| 462 | input_unregister_device(spitzkbd->input); | ||
| 463 | |||
| 464 | kfree(spitzkbd); | ||
| 465 | |||
| 466 | return 0; | ||
| 467 | } | ||
| 468 | |||
| 469 | static struct platform_driver spitzkbd_driver = { | ||
| 470 | .probe = spitzkbd_probe, | ||
| 471 | .remove = __devexit_p(spitzkbd_remove), | ||
| 472 | .suspend = spitzkbd_suspend, | ||
| 473 | .resume = spitzkbd_resume, | ||
| 474 | .driver = { | ||
| 475 | .name = "spitz-keyboard", | ||
| 476 | .owner = THIS_MODULE, | ||
| 477 | }, | ||
| 478 | }; | ||
| 479 | |||
| 480 | static int __init spitzkbd_init(void) | ||
| 481 | { | ||
| 482 | return platform_driver_register(&spitzkbd_driver); | ||
| 483 | } | ||
| 484 | |||
| 485 | static void __exit spitzkbd_exit(void) | ||
| 486 | { | ||
| 487 | platform_driver_unregister(&spitzkbd_driver); | ||
| 488 | } | ||
| 489 | |||
| 490 | module_init(spitzkbd_init); | ||
| 491 | module_exit(spitzkbd_exit); | ||
| 492 | |||
| 493 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
| 494 | MODULE_DESCRIPTION("Spitz Keyboard Driver"); | ||
| 495 | MODULE_LICENSE("GPL v2"); | ||
| 496 | MODULE_ALIAS("platform:spitz-keyboard"); | ||
diff --git a/drivers/input/keyboard/tosakbd.c b/drivers/input/keyboard/tosakbd.c deleted file mode 100644 index 3910f269cfc8..000000000000 --- a/drivers/input/keyboard/tosakbd.c +++ /dev/null | |||
| @@ -1,431 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Keyboard driver for Sharp Tosa models (SL-6000x) | ||
| 3 | * | ||
| 4 | * Copyright (c) 2005 Dirk Opfer | ||
| 5 | * Copyright (c) 2007 Dmitry Baryshkov | ||
| 6 | * | ||
| 7 | * Based on xtkbd.c/locomkbd.c/corgikbd.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/module.h> | ||
| 17 | #include <linux/platform_device.h> | ||
| 18 | #include <linux/input.h> | ||
| 19 | #include <linux/delay.h> | ||
| 20 | #include <linux/interrupt.h> | ||
| 21 | #include <linux/slab.h> | ||
| 22 | |||
| 23 | #include <mach/gpio.h> | ||
| 24 | #include <mach/tosa.h> | ||
| 25 | |||
| 26 | #define KB_ROWMASK(r) (1 << (r)) | ||
| 27 | #define SCANCODE(r, c) (((r)<<4) + (c) + 1) | ||
| 28 | #define NR_SCANCODES SCANCODE(TOSA_KEY_SENSE_NUM - 1, TOSA_KEY_STROBE_NUM - 1) + 1 | ||
| 29 | |||
| 30 | #define SCAN_INTERVAL (HZ/10) | ||
| 31 | |||
| 32 | #define KB_DISCHARGE_DELAY 10 | ||
| 33 | #define KB_ACTIVATE_DELAY 10 | ||
| 34 | |||
| 35 | static unsigned short tosakbd_keycode[NR_SCANCODES] = { | ||
| 36 | 0, | ||
| 37 | 0, KEY_W, 0, 0, 0, KEY_K, KEY_BACKSPACE, KEY_P, | ||
| 38 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 39 | KEY_Q, KEY_E, KEY_T, KEY_Y, 0, KEY_O, KEY_I, KEY_COMMA, | ||
| 40 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 41 | KEY_A, KEY_D, KEY_G, KEY_U, 0, KEY_L, KEY_ENTER, KEY_DOT, | ||
| 42 | 0, 0, 0, 0, 0, 0, 0, 0, | ||
| 43 | KEY_Z, KEY_C, KEY_V, KEY_J, TOSA_KEY_ADDRESSBOOK, TOSA_KEY_CANCEL, TOSA_KEY_CENTER, TOSA_KEY_OK, | ||
| 44 | KEY_LEFTSHIFT, 0, 0, 0, 0, 0, 0, 0, | ||
| 45 | KEY_S, KEY_R, KEY_B, KEY_N, TOSA_KEY_CALENDAR, TOSA_KEY_HOMEPAGE, KEY_LEFTCTRL, TOSA_KEY_LIGHT, | ||
| 46 | 0, KEY_RIGHTSHIFT, 0, 0, 0, 0, 0, 0, | ||
| 47 | KEY_TAB, KEY_SLASH, KEY_H, KEY_M, TOSA_KEY_MENU, 0, KEY_UP, 0, | ||
| 48 | 0, 0, TOSA_KEY_FN, 0, 0, 0, 0, 0, | ||
| 49 | KEY_X, KEY_F, KEY_SPACE, KEY_APOSTROPHE, TOSA_KEY_MAIL, KEY_LEFT, KEY_DOWN, KEY_RIGHT, | ||
| 50 | 0, 0, 0, | ||
| 51 | }; | ||
| 52 | |||
| 53 | struct tosakbd { | ||
| 54 | unsigned short keycode[ARRAY_SIZE(tosakbd_keycode)]; | ||
| 55 | struct input_dev *input; | ||
| 56 | bool suspended; | ||
| 57 | spinlock_t lock; /* protect kbd scanning */ | ||
| 58 | struct timer_list timer; | ||
| 59 | }; | ||
| 60 | |||
| 61 | |||
| 62 | /* Helper functions for reading the keyboard matrix | ||
| 63 | * Note: We should really be using the generic gpio functions to alter | ||
| 64 | * GPDR but it requires a function call per GPIO bit which is | ||
| 65 | * excessive when we need to access 12 bits at once, multiple times. | ||
| 66 | * These functions must be called within local_irq_save()/local_irq_restore() | ||
| 67 | * or similar. | ||
| 68 | */ | ||
| 69 | #define GET_ROWS_STATUS(c) ((GPLR2 & TOSA_GPIO_ALL_SENSE_BIT) >> TOSA_GPIO_ALL_SENSE_RSHIFT) | ||
| 70 | |||
| 71 | static inline void tosakbd_discharge_all(void) | ||
| 72 | { | ||
| 73 | /* STROBE All HiZ */ | ||
| 74 | GPCR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 75 | GPDR1 &= ~TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 76 | GPCR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
| 77 | GPDR2 &= ~TOSA_GPIO_LOW_STROBE_BIT; | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void tosakbd_activate_all(void) | ||
| 81 | { | ||
| 82 | /* STROBE ALL -> High */ | ||
| 83 | GPSR1 = TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 84 | GPDR1 |= TOSA_GPIO_HIGH_STROBE_BIT; | ||
| 85 | GPSR2 = TOSA_GPIO_LOW_STROBE_BIT; | ||
| 86 | GPDR2 |= TOSA_GPIO_LOW_STROBE_BIT; | ||
| 87 | |||
| 88 | udelay(KB_DISCHARGE_DELAY); | ||
| 89 | |||
| 90 | /* STATE CLEAR */ | ||
| 91 | GEDR2 |= TOSA_GPIO_ALL_SENSE_BIT; | ||
| 92 | } | ||
| 93 | |||
| 94 | static inline void tosakbd_activate_col(int col) | ||
| 95 | { | ||
| 96 | if (col <= 5) { | ||
| 97 | /* STROBE col -> High, not col -> HiZ */ | ||
| 98 | GPSR1 = TOSA_GPIO_STROBE_BIT(col); | ||
| 99 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 100 | } else { | ||
| 101 | /* STROBE col -> High, not col -> HiZ */ | ||
| 102 | GPSR2 = TOSA_GPIO_STROBE_BIT(col); | ||
| 103 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 104 | } | ||
| 105 | } | ||
| 106 | |||
| 107 | static inline void tosakbd_reset_col(int col) | ||
| 108 | { | ||
| 109 | if (col <= 5) { | ||
| 110 | /* STROBE col -> Low */ | ||
| 111 | GPCR1 = TOSA_GPIO_STROBE_BIT(col); | ||
| 112 | /* STROBE col -> out, not col -> HiZ */ | ||
| 113 | GPDR1 = (GPDR1 & ~TOSA_GPIO_HIGH_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 114 | } else { | ||
| 115 | /* STROBE col -> Low */ | ||
| 116 | GPCR2 = TOSA_GPIO_STROBE_BIT(col); | ||
| 117 | /* STROBE col -> out, not col -> HiZ */ | ||
| 118 | GPDR2 = (GPDR2 & ~TOSA_GPIO_LOW_STROBE_BIT) | TOSA_GPIO_STROBE_BIT(col); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | /* | ||
| 122 | * The tosa keyboard only generates interrupts when a key is pressed. | ||
| 123 | * So when a key is pressed, we enable a timer. This timer scans the | ||
| 124 | * keyboard, and this is how we detect when the key is released. | ||
| 125 | */ | ||
| 126 | |||
| 127 | /* Scan the hardware keyboard and push any changes up through the input layer */ | ||
| 128 | static void tosakbd_scankeyboard(struct platform_device *dev) | ||
| 129 | { | ||
| 130 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 131 | unsigned int row, col, rowd; | ||
| 132 | unsigned long flags; | ||
| 133 | unsigned int num_pressed = 0; | ||
| 134 | |||
| 135 | spin_lock_irqsave(&tosakbd->lock, flags); | ||
| 136 | |||
| 137 | if (tosakbd->suspended) | ||
| 138 | goto out; | ||
| 139 | |||
| 140 | for (col = 0; col < TOSA_KEY_STROBE_NUM; col++) { | ||
| 141 | /* | ||
| 142 | * Discharge the output driver capacitatance | ||
| 143 | * in the keyboard matrix. (Yes it is significant..) | ||
| 144 | */ | ||
| 145 | tosakbd_discharge_all(); | ||
| 146 | udelay(KB_DISCHARGE_DELAY); | ||
| 147 | |||
| 148 | tosakbd_activate_col(col); | ||
| 149 | udelay(KB_ACTIVATE_DELAY); | ||
| 150 | |||
| 151 | rowd = GET_ROWS_STATUS(col); | ||
| 152 | |||
| 153 | for (row = 0; row < TOSA_KEY_SENSE_NUM; row++) { | ||
| 154 | unsigned int scancode, pressed; | ||
| 155 | scancode = SCANCODE(row, col); | ||
| 156 | pressed = rowd & KB_ROWMASK(row); | ||
| 157 | |||
| 158 | if (pressed && !tosakbd->keycode[scancode]) | ||
| 159 | dev_warn(&dev->dev, | ||
| 160 | "unhandled scancode: 0x%02x\n", | ||
| 161 | scancode); | ||
| 162 | |||
| 163 | input_report_key(tosakbd->input, | ||
| 164 | tosakbd->keycode[scancode], | ||
| 165 | pressed); | ||
| 166 | if (pressed) | ||
| 167 | num_pressed++; | ||
| 168 | } | ||
| 169 | |||
| 170 | tosakbd_reset_col(col); | ||
| 171 | } | ||
| 172 | |||
| 173 | tosakbd_activate_all(); | ||
| 174 | |||
| 175 | input_sync(tosakbd->input); | ||
| 176 | |||
| 177 | /* if any keys are pressed, enable the timer */ | ||
| 178 | if (num_pressed) | ||
| 179 | mod_timer(&tosakbd->timer, jiffies + SCAN_INTERVAL); | ||
| 180 | |||
| 181 | out: | ||
| 182 | spin_unlock_irqrestore(&tosakbd->lock, flags); | ||
| 183 | } | ||
| 184 | |||
| 185 | /* | ||
| 186 | * tosa keyboard interrupt handler. | ||
| 187 | */ | ||
| 188 | static irqreturn_t tosakbd_interrupt(int irq, void *__dev) | ||
| 189 | { | ||
| 190 | struct platform_device *dev = __dev; | ||
| 191 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 192 | |||
| 193 | if (!timer_pending(&tosakbd->timer)) { | ||
| 194 | /** wait chattering delay **/ | ||
| 195 | udelay(20); | ||
| 196 | tosakbd_scankeyboard(dev); | ||
| 197 | } | ||
| 198 | |||
| 199 | return IRQ_HANDLED; | ||
| 200 | } | ||
| 201 | |||
| 202 | /* | ||
| 203 | * tosa timer checking for released keys | ||
| 204 | */ | ||
| 205 | static void tosakbd_timer_callback(unsigned long __dev) | ||
| 206 | { | ||
| 207 | struct platform_device *dev = (struct platform_device *)__dev; | ||
| 208 | |||
| 209 | tosakbd_scankeyboard(dev); | ||
| 210 | } | ||
| 211 | |||
| 212 | #ifdef CONFIG_PM | ||
| 213 | static int tosakbd_suspend(struct platform_device *dev, pm_message_t state) | ||
| 214 | { | ||
| 215 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 216 | unsigned long flags; | ||
| 217 | |||
| 218 | spin_lock_irqsave(&tosakbd->lock, flags); | ||
| 219 | tosakbd->suspended = true; | ||
| 220 | spin_unlock_irqrestore(&tosakbd->lock, flags); | ||
| 221 | |||
| 222 | del_timer_sync(&tosakbd->timer); | ||
| 223 | |||
| 224 | return 0; | ||
| 225 | } | ||
| 226 | |||
| 227 | static int tosakbd_resume(struct platform_device *dev) | ||
| 228 | { | ||
| 229 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 230 | |||
| 231 | tosakbd->suspended = false; | ||
| 232 | tosakbd_scankeyboard(dev); | ||
| 233 | |||
| 234 | return 0; | ||
| 235 | } | ||
| 236 | #else | ||
| 237 | #define tosakbd_suspend NULL | ||
| 238 | #define tosakbd_resume NULL | ||
| 239 | #endif | ||
| 240 | |||
| 241 | static int __devinit tosakbd_probe(struct platform_device *pdev) { | ||
| 242 | |||
| 243 | int i; | ||
| 244 | struct tosakbd *tosakbd; | ||
| 245 | struct input_dev *input_dev; | ||
| 246 | int error; | ||
| 247 | |||
| 248 | tosakbd = kzalloc(sizeof(struct tosakbd), GFP_KERNEL); | ||
| 249 | if (!tosakbd) | ||
| 250 | return -ENOMEM; | ||
| 251 | |||
| 252 | input_dev = input_allocate_device(); | ||
| 253 | if (!input_dev) { | ||
| 254 | kfree(tosakbd); | ||
| 255 | return -ENOMEM; | ||
| 256 | } | ||
| 257 | |||
| 258 | platform_set_drvdata(pdev, tosakbd); | ||
| 259 | |||
| 260 | spin_lock_init(&tosakbd->lock); | ||
| 261 | |||
| 262 | /* Init Keyboard rescan timer */ | ||
| 263 | init_timer(&tosakbd->timer); | ||
| 264 | tosakbd->timer.function = tosakbd_timer_callback; | ||
| 265 | tosakbd->timer.data = (unsigned long) pdev; | ||
| 266 | |||
| 267 | tosakbd->input = input_dev; | ||
| 268 | |||
| 269 | input_set_drvdata(input_dev, tosakbd); | ||
| 270 | input_dev->name = "Tosa Keyboard"; | ||
| 271 | input_dev->phys = "tosakbd/input0"; | ||
| 272 | input_dev->dev.parent = &pdev->dev; | ||
| 273 | |||
| 274 | input_dev->id.bustype = BUS_HOST; | ||
| 275 | input_dev->id.vendor = 0x0001; | ||
| 276 | input_dev->id.product = 0x0001; | ||
| 277 | input_dev->id.version = 0x0100; | ||
| 278 | |||
| 279 | input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_REP); | ||
| 280 | input_dev->keycode = tosakbd->keycode; | ||
| 281 | input_dev->keycodesize = sizeof(tosakbd->keycode[0]); | ||
| 282 | input_dev->keycodemax = ARRAY_SIZE(tosakbd_keycode); | ||
| 283 | |||
| 284 | memcpy(tosakbd->keycode, tosakbd_keycode, sizeof(tosakbd_keycode)); | ||
| 285 | |||
| 286 | for (i = 0; i < ARRAY_SIZE(tosakbd_keycode); i++) | ||
| 287 | __set_bit(tosakbd->keycode[i], input_dev->keybit); | ||
| 288 | __clear_bit(KEY_RESERVED, input_dev->keybit); | ||
| 289 | |||
| 290 | /* Setup sense interrupts - RisingEdge Detect, sense lines as inputs */ | ||
| 291 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
| 292 | int gpio = TOSA_GPIO_KEY_SENSE(i); | ||
| 293 | int irq; | ||
| 294 | error = gpio_request(gpio, "tosakbd"); | ||
| 295 | if (error < 0) { | ||
| 296 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
| 297 | " error %d\n", gpio, error); | ||
| 298 | goto fail; | ||
| 299 | } | ||
| 300 | |||
| 301 | error = gpio_direction_input(TOSA_GPIO_KEY_SENSE(i)); | ||
| 302 | if (error < 0) { | ||
| 303 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
| 304 | " direction for GPIO %d, error %d\n", | ||
| 305 | gpio, error); | ||
| 306 | gpio_free(gpio); | ||
| 307 | goto fail; | ||
| 308 | } | ||
| 309 | |||
| 310 | irq = gpio_to_irq(gpio); | ||
| 311 | if (irq < 0) { | ||
| 312 | error = irq; | ||
| 313 | printk(KERN_ERR "gpio-keys: Unable to get irq number" | ||
| 314 | " for GPIO %d, error %d\n", | ||
| 315 | gpio, error); | ||
| 316 | gpio_free(gpio); | ||
| 317 | goto fail; | ||
| 318 | } | ||
| 319 | |||
| 320 | error = request_irq(irq, tosakbd_interrupt, | ||
| 321 | IRQF_DISABLED | IRQF_TRIGGER_RISING, | ||
| 322 | "tosakbd", pdev); | ||
| 323 | |||
| 324 | if (error) { | ||
| 325 | printk("tosakbd: Can't get IRQ: %d: error %d!\n", | ||
| 326 | irq, error); | ||
| 327 | gpio_free(gpio); | ||
| 328 | goto fail; | ||
| 329 | } | ||
| 330 | } | ||
| 331 | |||
| 332 | /* Set Strobe lines as outputs - set high */ | ||
| 333 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) { | ||
| 334 | int gpio = TOSA_GPIO_KEY_STROBE(i); | ||
| 335 | error = gpio_request(gpio, "tosakbd"); | ||
| 336 | if (error < 0) { | ||
| 337 | printk(KERN_ERR "tosakbd: failed to request GPIO %d, " | ||
| 338 | " error %d\n", gpio, error); | ||
| 339 | goto fail2; | ||
| 340 | } | ||
| 341 | |||
| 342 | error = gpio_direction_output(gpio, 1); | ||
| 343 | if (error < 0) { | ||
| 344 | printk(KERN_ERR "tosakbd: failed to configure input" | ||
| 345 | " direction for GPIO %d, error %d\n", | ||
| 346 | gpio, error); | ||
| 347 | gpio_free(gpio); | ||
| 348 | goto fail2; | ||
| 349 | } | ||
| 350 | |||
| 351 | } | ||
| 352 | |||
| 353 | error = input_register_device(input_dev); | ||
| 354 | if (error) { | ||
| 355 | printk(KERN_ERR "tosakbd: Unable to register input device, " | ||
| 356 | "error: %d\n", error); | ||
| 357 | goto fail2; | ||
| 358 | } | ||
| 359 | |||
| 360 | printk(KERN_INFO "input: Tosa Keyboard Registered\n"); | ||
| 361 | |||
| 362 | return 0; | ||
| 363 | |||
| 364 | fail2: | ||
| 365 | while (--i >= 0) | ||
| 366 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
| 367 | |||
| 368 | i = TOSA_KEY_SENSE_NUM; | ||
| 369 | fail: | ||
| 370 | while (--i >= 0) { | ||
| 371 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), pdev); | ||
| 372 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
| 373 | } | ||
| 374 | |||
| 375 | platform_set_drvdata(pdev, NULL); | ||
| 376 | input_free_device(input_dev); | ||
| 377 | kfree(tosakbd); | ||
| 378 | |||
| 379 | return error; | ||
| 380 | } | ||
| 381 | |||
| 382 | static int __devexit tosakbd_remove(struct platform_device *dev) | ||
| 383 | { | ||
| 384 | int i; | ||
| 385 | struct tosakbd *tosakbd = platform_get_drvdata(dev); | ||
| 386 | |||
| 387 | for (i = 0; i < TOSA_KEY_STROBE_NUM; i++) | ||
| 388 | gpio_free(TOSA_GPIO_KEY_STROBE(i)); | ||
| 389 | |||
| 390 | for (i = 0; i < TOSA_KEY_SENSE_NUM; i++) { | ||
| 391 | free_irq(gpio_to_irq(TOSA_GPIO_KEY_SENSE(i)), dev); | ||
| 392 | gpio_free(TOSA_GPIO_KEY_SENSE(i)); | ||
| 393 | } | ||
| 394 | |||
| 395 | del_timer_sync(&tosakbd->timer); | ||
| 396 | |||
| 397 | input_unregister_device(tosakbd->input); | ||
| 398 | |||
| 399 | kfree(tosakbd); | ||
| 400 | |||
| 401 | return 0; | ||
| 402 | } | ||
| 403 | |||
| 404 | static struct platform_driver tosakbd_driver = { | ||
| 405 | .probe = tosakbd_probe, | ||
| 406 | .remove = __devexit_p(tosakbd_remove), | ||
| 407 | .suspend = tosakbd_suspend, | ||
| 408 | .resume = tosakbd_resume, | ||
| 409 | .driver = { | ||
| 410 | .name = "tosa-keyboard", | ||
| 411 | .owner = THIS_MODULE, | ||
| 412 | }, | ||
| 413 | }; | ||
| 414 | |||
| 415 | static int __devinit tosakbd_init(void) | ||
| 416 | { | ||
| 417 | return platform_driver_register(&tosakbd_driver); | ||
| 418 | } | ||
| 419 | |||
| 420 | static void __exit tosakbd_exit(void) | ||
| 421 | { | ||
| 422 | platform_driver_unregister(&tosakbd_driver); | ||
| 423 | } | ||
| 424 | |||
| 425 | module_init(tosakbd_init); | ||
| 426 | module_exit(tosakbd_exit); | ||
| 427 | |||
| 428 | MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); | ||
| 429 | MODULE_DESCRIPTION("Tosa Keyboard Driver"); | ||
| 430 | MODULE_LICENSE("GPL v2"); | ||
| 431 | MODULE_ALIAS("platform:tosa-keyboard"); | ||
diff --git a/drivers/input/misc/ati_remote.c b/drivers/input/misc/ati_remote.c index 614b65d78fe9..e8bbc619f6df 100644 --- a/drivers/input/misc/ati_remote.c +++ b/drivers/input/misc/ati_remote.c | |||
| @@ -98,10 +98,12 @@ | |||
| 98 | * Module and Version Information, Module Parameters | 98 | * Module and Version Information, Module Parameters |
| 99 | */ | 99 | */ |
| 100 | 100 | ||
| 101 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 | 101 | #define ATI_REMOTE_VENDOR_ID 0x0bc7 |
| 102 | #define ATI_REMOTE_PRODUCT_ID 0x004 | 102 | #define LOLA_REMOTE_PRODUCT_ID 0x0002 |
| 103 | #define LOLA_REMOTE_PRODUCT_ID 0x002 | 103 | #define LOLA2_REMOTE_PRODUCT_ID 0x0003 |
| 104 | #define MEDION_REMOTE_PRODUCT_ID 0x006 | 104 | #define ATI_REMOTE_PRODUCT_ID 0x0004 |
| 105 | #define NVIDIA_REMOTE_PRODUCT_ID 0x0005 | ||
| 106 | #define MEDION_REMOTE_PRODUCT_ID 0x0006 | ||
| 105 | 107 | ||
| 106 | #define DRIVER_VERSION "2.2.1" | 108 | #define DRIVER_VERSION "2.2.1" |
| 107 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" | 109 | #define DRIVER_AUTHOR "Torrey Hoffman <thoffman@arnor.net>" |
| @@ -142,8 +144,10 @@ MODULE_PARM_DESC(repeat_delay, "Delay before sending repeats, default = 500 msec | |||
| 142 | #define err(format, arg...) printk(KERN_ERR format , ## arg) | 144 | #define err(format, arg...) printk(KERN_ERR format , ## arg) |
| 143 | 145 | ||
| 144 | static struct usb_device_id ati_remote_table[] = { | 146 | static struct usb_device_id ati_remote_table[] = { |
| 145 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | ||
| 146 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, | 147 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA_REMOTE_PRODUCT_ID) }, |
| 148 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, LOLA2_REMOTE_PRODUCT_ID) }, | ||
| 149 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, ATI_REMOTE_PRODUCT_ID) }, | ||
| 150 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, NVIDIA_REMOTE_PRODUCT_ID) }, | ||
| 147 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, | 151 | { USB_DEVICE(ATI_REMOTE_VENDOR_ID, MEDION_REMOTE_PRODUCT_ID) }, |
| 148 | {} /* Terminating entry */ | 152 | {} /* Terminating entry */ |
| 149 | }; | 153 | }; |
diff --git a/drivers/input/misc/pcspkr.c b/drivers/input/misc/pcspkr.c index ea4e1fd12651..f080dd31499b 100644 --- a/drivers/input/misc/pcspkr.c +++ b/drivers/input/misc/pcspkr.c | |||
| @@ -30,7 +30,7 @@ MODULE_ALIAS("platform:pcspkr"); | |||
| 30 | #include <asm/i8253.h> | 30 | #include <asm/i8253.h> |
| 31 | #else | 31 | #else |
| 32 | #include <asm/8253pit.h> | 32 | #include <asm/8253pit.h> |
| 33 | static DEFINE_SPINLOCK(i8253_lock); | 33 | static DEFINE_RAW_SPINLOCK(i8253_lock); |
| 34 | #endif | 34 | #endif |
| 35 | 35 | ||
| 36 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) | 36 | static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) |
| @@ -50,7 +50,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
| 50 | if (value > 20 && value < 32767) | 50 | if (value > 20 && value < 32767) |
| 51 | count = PIT_TICK_RATE / value; | 51 | count = PIT_TICK_RATE / value; |
| 52 | 52 | ||
| 53 | spin_lock_irqsave(&i8253_lock, flags); | 53 | raw_spin_lock_irqsave(&i8253_lock, flags); |
| 54 | 54 | ||
| 55 | if (count) { | 55 | if (count) { |
| 56 | /* set command for counter 2, 2 byte write */ | 56 | /* set command for counter 2, 2 byte write */ |
| @@ -65,7 +65,7 @@ static int pcspkr_event(struct input_dev *dev, unsigned int type, unsigned int c | |||
| 65 | outb(inb_p(0x61) & 0xFC, 0x61); | 65 | outb(inb_p(0x61) & 0xFC, 0x61); |
| 66 | } | 66 | } |
| 67 | 67 | ||
| 68 | spin_unlock_irqrestore(&i8253_lock, flags); | 68 | raw_spin_unlock_irqrestore(&i8253_lock, flags); |
| 69 | 69 | ||
| 70 | return 0; | 70 | return 0; |
| 71 | } | 71 | } |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 0d22cb9ce42e..99d58764ef03 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
| @@ -64,7 +64,6 @@ static const struct alps_model_info alps_model_data[] = { | |||
| 64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, | 64 | { { 0x62, 0x02, 0x14 }, 0xcf, 0xcf, |
| 65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, | 65 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, |
| 66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ | 66 | { { 0x73, 0x02, 0x50 }, 0xcf, 0xcf, ALPS_FOUR_BUTTONS }, /* Dell Vostro 1400 */ |
| 67 | { { 0x73, 0x02, 0x64 }, 0xf8, 0xf8, 0 }, /* HP Pavilion dm3 */ | ||
| 68 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, | 67 | { { 0x52, 0x01, 0x14 }, 0xff, 0xff, |
| 69 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ | 68 | ALPS_PASS | ALPS_DUALPOINT | ALPS_PS2_INTERLEAVED }, /* Toshiba Tecra A11-11L */ |
| 70 | }; | 69 | }; |
diff --git a/drivers/input/mouse/elantech.c b/drivers/input/mouse/elantech.c index a138b5da79f9..112b4ee52ff2 100644 --- a/drivers/input/mouse/elantech.c +++ b/drivers/input/mouse/elantech.c | |||
| @@ -25,6 +25,10 @@ | |||
| 25 | printk(KERN_DEBUG format, ##arg); \ | 25 | printk(KERN_DEBUG format, ##arg); \ |
| 26 | } while (0) | 26 | } while (0) |
| 27 | 27 | ||
| 28 | static bool force_elantech; | ||
| 29 | module_param_named(force_elantech, force_elantech, bool, 0644); | ||
| 30 | MODULE_PARM_DESC(force_elantech, "Force the Elantech PS/2 protocol extension to be used, 1 = enabled, 0 = disabled (default)."); | ||
| 31 | |||
| 28 | /* | 32 | /* |
| 29 | * Send a Synaptics style sliced query command | 33 | * Send a Synaptics style sliced query command |
| 30 | */ | 34 | */ |
| @@ -181,14 +185,18 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
| 181 | int fingers; | 185 | int fingers; |
| 182 | static int old_fingers; | 186 | static int old_fingers; |
| 183 | 187 | ||
| 184 | if (etd->fw_version_maj == 0x01) { | 188 | if (etd->fw_version < 0x020000) { |
| 185 | /* byte 0: D U p1 p2 1 p3 R L | 189 | /* |
| 186 | byte 1: f 0 th tw x9 x8 y9 y8 */ | 190 | * byte 0: D U p1 p2 1 p3 R L |
| 191 | * byte 1: f 0 th tw x9 x8 y9 y8 | ||
| 192 | */ | ||
| 187 | fingers = ((packet[1] & 0x80) >> 7) + | 193 | fingers = ((packet[1] & 0x80) >> 7) + |
| 188 | ((packet[1] & 0x30) >> 4); | 194 | ((packet[1] & 0x30) >> 4); |
| 189 | } else { | 195 | } else { |
| 190 | /* byte 0: n1 n0 p2 p1 1 p3 R L | 196 | /* |
| 191 | byte 1: 0 0 0 0 x9 x8 y9 y8 */ | 197 | * byte 0: n1 n0 p2 p1 1 p3 R L |
| 198 | * byte 1: 0 0 0 0 x9 x8 y9 y8 | ||
| 199 | */ | ||
| 192 | fingers = (packet[0] & 0xc0) >> 6; | 200 | fingers = (packet[0] & 0xc0) >> 6; |
| 193 | } | 201 | } |
| 194 | 202 | ||
| @@ -202,13 +210,15 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
| 202 | 210 | ||
| 203 | input_report_key(dev, BTN_TOUCH, fingers != 0); | 211 | input_report_key(dev, BTN_TOUCH, fingers != 0); |
| 204 | 212 | ||
| 205 | /* byte 2: x7 x6 x5 x4 x3 x2 x1 x0 | 213 | /* |
| 206 | byte 3: y7 y6 y5 y4 y3 y2 y1 y0 */ | 214 | * byte 2: x7 x6 x5 x4 x3 x2 x1 x0 |
| 215 | * byte 3: y7 y6 y5 y4 y3 y2 y1 y0 | ||
| 216 | */ | ||
| 207 | if (fingers) { | 217 | if (fingers) { |
| 208 | input_report_abs(dev, ABS_X, | 218 | input_report_abs(dev, ABS_X, |
| 209 | ((packet[1] & 0x0c) << 6) | packet[2]); | 219 | ((packet[1] & 0x0c) << 6) | packet[2]); |
| 210 | input_report_abs(dev, ABS_Y, ETP_YMAX_V1 - | 220 | input_report_abs(dev, ABS_Y, |
| 211 | (((packet[1] & 0x03) << 8) | packet[3])); | 221 | ETP_YMAX_V1 - (((packet[1] & 0x03) << 8) | packet[3])); |
| 212 | } | 222 | } |
| 213 | 223 | ||
| 214 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); | 224 | input_report_key(dev, BTN_TOOL_FINGER, fingers == 1); |
| @@ -217,7 +227,7 @@ static void elantech_report_absolute_v1(struct psmouse *psmouse) | |||
| 217 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); | 227 | input_report_key(dev, BTN_LEFT, packet[0] & 0x01); |
| 218 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); | 228 | input_report_key(dev, BTN_RIGHT, packet[0] & 0x02); |
| 219 | 229 | ||
| 220 | if ((etd->fw_version_maj == 0x01) && | 230 | if (etd->fw_version < 0x020000 && |
| 221 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 231 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { |
| 222 | /* rocker up */ | 232 | /* rocker up */ |
| 223 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); | 233 | input_report_key(dev, BTN_FORWARD, packet[0] & 0x40); |
| @@ -247,34 +257,47 @@ static void elantech_report_absolute_v2(struct psmouse *psmouse) | |||
| 247 | 257 | ||
| 248 | switch (fingers) { | 258 | switch (fingers) { |
| 249 | case 1: | 259 | case 1: |
| 250 | /* byte 1: x15 x14 x13 x12 x11 x10 x9 x8 | 260 | /* |
| 251 | byte 2: x7 x6 x5 x4 x4 x2 x1 x0 */ | 261 | * byte 1: . . . . . x10 x9 x8 |
| 252 | input_report_abs(dev, ABS_X, (packet[1] << 8) | packet[2]); | 262 | * byte 2: x7 x6 x5 x4 x4 x2 x1 x0 |
| 253 | /* byte 4: y15 y14 y13 y12 y11 y10 y8 y8 | 263 | */ |
| 254 | byte 5: y7 y6 y5 y4 y3 y2 y1 y0 */ | 264 | input_report_abs(dev, ABS_X, |
| 255 | input_report_abs(dev, ABS_Y, ETP_YMAX_V2 - | 265 | ((packet[1] & 0x07) << 8) | packet[2]); |
| 256 | ((packet[4] << 8) | packet[5])); | 266 | /* |
| 267 | * byte 4: . . . . . . y9 y8 | ||
| 268 | * byte 5: y7 y6 y5 y4 y3 y2 y1 y0 | ||
| 269 | */ | ||
| 270 | input_report_abs(dev, ABS_Y, | ||
| 271 | ETP_YMAX_V2 - (((packet[4] & 0x03) << 8) | packet[5])); | ||
| 257 | break; | 272 | break; |
| 258 | 273 | ||
| 259 | case 2: | 274 | case 2: |
| 260 | /* The coordinate of each finger is reported separately with | 275 | /* |
| 261 | a lower resolution for two finger touches */ | 276 | * The coordinate of each finger is reported separately |
| 262 | /* byte 0: . . ay8 ax8 . . . . | 277 | * with a lower resolution for two finger touches: |
| 263 | byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 */ | 278 | * byte 0: . . ay8 ax8 . . . . |
| 279 | * byte 1: ax7 ax6 ax5 ax4 ax3 ax2 ax1 ax0 | ||
| 280 | */ | ||
| 264 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; | 281 | x1 = ((packet[0] & 0x10) << 4) | packet[1]; |
| 265 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ | 282 | /* byte 2: ay7 ay6 ay5 ay4 ay3 ay2 ay1 ay0 */ |
| 266 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); | 283 | y1 = ETP_2FT_YMAX - (((packet[0] & 0x20) << 3) | packet[2]); |
| 267 | /* byte 3: . . by8 bx8 . . . . | 284 | /* |
| 268 | byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 */ | 285 | * byte 3: . . by8 bx8 . . . . |
| 286 | * byte 4: bx7 bx6 bx5 bx4 bx3 bx2 bx1 bx0 | ||
| 287 | */ | ||
| 269 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; | 288 | x2 = ((packet[3] & 0x10) << 4) | packet[4]; |
| 270 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ | 289 | /* byte 5: by7 by8 by5 by4 by3 by2 by1 by0 */ |
| 271 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); | 290 | y2 = ETP_2FT_YMAX - (((packet[3] & 0x20) << 3) | packet[5]); |
| 272 | /* For compatibility with the X Synaptics driver scale up one | 291 | /* |
| 273 | coordinate and report as ordinary mouse movent */ | 292 | * For compatibility with the X Synaptics driver scale up |
| 293 | * one coordinate and report as ordinary mouse movent | ||
| 294 | */ | ||
| 274 | input_report_abs(dev, ABS_X, x1 << 2); | 295 | input_report_abs(dev, ABS_X, x1 << 2); |
| 275 | input_report_abs(dev, ABS_Y, y1 << 2); | 296 | input_report_abs(dev, ABS_Y, y1 << 2); |
| 276 | /* For compatibility with the proprietary X Elantech driver | 297 | /* |
| 277 | report both coordinates as hat coordinates */ | 298 | * For compatibility with the proprietary X Elantech driver |
| 299 | * report both coordinates as hat coordinates | ||
| 300 | */ | ||
| 278 | input_report_abs(dev, ABS_HAT0X, x1); | 301 | input_report_abs(dev, ABS_HAT0X, x1); |
| 279 | input_report_abs(dev, ABS_HAT0Y, y1); | 302 | input_report_abs(dev, ABS_HAT0Y, y1); |
| 280 | input_report_abs(dev, ABS_HAT1X, x2); | 303 | input_report_abs(dev, ABS_HAT1X, x2); |
| @@ -298,7 +321,7 @@ static int elantech_check_parity_v1(struct psmouse *psmouse) | |||
| 298 | unsigned char p1, p2, p3; | 321 | unsigned char p1, p2, p3; |
| 299 | 322 | ||
| 300 | /* Parity bits are placed differently */ | 323 | /* Parity bits are placed differently */ |
| 301 | if (etd->fw_version_maj == 0x01) { | 324 | if (etd->fw_version < 0x020000) { |
| 302 | /* byte 0: D U p1 p2 1 p3 R L */ | 325 | /* byte 0: D U p1 p2 1 p3 R L */ |
| 303 | p1 = (packet[0] & 0x20) >> 5; | 326 | p1 = (packet[0] & 0x20) >> 5; |
| 304 | p2 = (packet[0] & 0x10) >> 4; | 327 | p2 = (packet[0] & 0x10) >> 4; |
| @@ -434,7 +457,7 @@ static void elantech_set_input_params(struct psmouse *psmouse) | |||
| 434 | switch (etd->hw_version) { | 457 | switch (etd->hw_version) { |
| 435 | case 1: | 458 | case 1: |
| 436 | /* Rocker button */ | 459 | /* Rocker button */ |
| 437 | if ((etd->fw_version_maj == 0x01) && | 460 | if (etd->fw_version < 0x020000 && |
| 438 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { | 461 | (etd->capabilities & ETP_CAP_HAS_ROCKER)) { |
| 439 | __set_bit(BTN_FORWARD, dev->keybit); | 462 | __set_bit(BTN_FORWARD, dev->keybit); |
| 440 | __set_bit(BTN_BACK, dev->keybit); | 463 | __set_bit(BTN_BACK, dev->keybit); |
| @@ -596,8 +619,12 @@ int elantech_detect(struct psmouse *psmouse, bool set_properties) | |||
| 596 | param[0], param[1], param[2]); | 619 | param[0], param[1], param[2]); |
| 597 | 620 | ||
| 598 | if (param[0] == 0 || param[1] != 0) { | 621 | if (param[0] == 0 || param[1] != 0) { |
| 599 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); | 622 | if (!force_elantech) { |
| 600 | return -1; | 623 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Aborting.\n"); |
| 624 | return -1; | ||
| 625 | } | ||
| 626 | |||
| 627 | pr_debug("elantech.c: Probably not a real Elantech touchpad. Enabling anyway due to force_elantech.\n"); | ||
| 601 | } | 628 | } |
| 602 | 629 | ||
| 603 | if (set_properties) { | 630 | if (set_properties) { |
| @@ -659,14 +686,14 @@ int elantech_init(struct psmouse *psmouse) | |||
| 659 | pr_err("elantech.c: failed to query firmware version.\n"); | 686 | pr_err("elantech.c: failed to query firmware version.\n"); |
| 660 | goto init_fail; | 687 | goto init_fail; |
| 661 | } | 688 | } |
| 662 | etd->fw_version_maj = param[0]; | 689 | |
| 663 | etd->fw_version_min = param[2]; | 690 | etd->fw_version = (param[0] << 16) | (param[1] << 8) | param[2]; |
| 664 | 691 | ||
| 665 | /* | 692 | /* |
| 666 | * Assume every version greater than this is new EeePC style | 693 | * Assume every version greater than this is new EeePC style |
| 667 | * hardware with 6 byte packets | 694 | * hardware with 6 byte packets |
| 668 | */ | 695 | */ |
| 669 | if (etd->fw_version_maj >= 0x02 && etd->fw_version_min >= 0x30) { | 696 | if (etd->fw_version >= 0x020030) { |
| 670 | etd->hw_version = 2; | 697 | etd->hw_version = 2; |
| 671 | /* For now show extra debug information */ | 698 | /* For now show extra debug information */ |
| 672 | etd->debug = 1; | 699 | etd->debug = 1; |
| @@ -676,8 +703,9 @@ int elantech_init(struct psmouse *psmouse) | |||
| 676 | etd->hw_version = 1; | 703 | etd->hw_version = 1; |
| 677 | etd->paritycheck = 1; | 704 | etd->paritycheck = 1; |
| 678 | } | 705 | } |
| 679 | pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d\n", | 706 | |
| 680 | etd->hw_version, etd->fw_version_maj, etd->fw_version_min); | 707 | pr_info("elantech.c: assuming hardware version %d, firmware version %d.%d.%d\n", |
| 708 | etd->hw_version, param[0], param[1], param[2]); | ||
| 681 | 709 | ||
| 682 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { | 710 | if (synaptics_send_cmd(psmouse, ETP_CAPABILITIES_QUERY, param)) { |
| 683 | pr_err("elantech.c: failed to query capabilities.\n"); | 711 | pr_err("elantech.c: failed to query capabilities.\n"); |
| @@ -692,8 +720,8 @@ int elantech_init(struct psmouse *psmouse) | |||
| 692 | * a touch action starts causing the mouse cursor or scrolled page | 720 | * a touch action starts causing the mouse cursor or scrolled page |
| 693 | * to jump. Enable a workaround. | 721 | * to jump. Enable a workaround. |
| 694 | */ | 722 | */ |
| 695 | if (etd->fw_version_maj == 0x02 && etd->fw_version_min == 0x22) { | 723 | if (etd->fw_version == 0x020022) { |
| 696 | pr_info("elantech.c: firmware version 2.34 detected, " | 724 | pr_info("elantech.c: firmware version 2.0.34 detected, " |
| 697 | "enabling jumpy cursor workaround\n"); | 725 | "enabling jumpy cursor workaround\n"); |
| 698 | etd->jumpy_cursor = 1; | 726 | etd->jumpy_cursor = 1; |
| 699 | } | 727 | } |
diff --git a/drivers/input/mouse/elantech.h b/drivers/input/mouse/elantech.h index feac5f7af966..ac57bde1bb9f 100644 --- a/drivers/input/mouse/elantech.h +++ b/drivers/input/mouse/elantech.h | |||
| @@ -100,11 +100,10 @@ struct elantech_data { | |||
| 100 | unsigned char reg_26; | 100 | unsigned char reg_26; |
| 101 | unsigned char debug; | 101 | unsigned char debug; |
| 102 | unsigned char capabilities; | 102 | unsigned char capabilities; |
| 103 | unsigned char fw_version_maj; | ||
| 104 | unsigned char fw_version_min; | ||
| 105 | unsigned char hw_version; | ||
| 106 | unsigned char paritycheck; | 103 | unsigned char paritycheck; |
| 107 | unsigned char jumpy_cursor; | 104 | unsigned char jumpy_cursor; |
| 105 | unsigned char hw_version; | ||
| 106 | unsigned int fw_version; | ||
| 108 | unsigned char parity[256]; | 107 | unsigned char parity[256]; |
| 109 | }; | 108 | }; |
| 110 | 109 | ||
diff --git a/drivers/input/mouse/psmouse-base.c b/drivers/input/mouse/psmouse-base.c index d8c0c8d6992c..a3c97315a473 100644 --- a/drivers/input/mouse/psmouse-base.c +++ b/drivers/input/mouse/psmouse-base.c | |||
| @@ -110,6 +110,7 @@ static struct workqueue_struct *kpsmoused_wq; | |||
| 110 | struct psmouse_protocol { | 110 | struct psmouse_protocol { |
| 111 | enum psmouse_type type; | 111 | enum psmouse_type type; |
| 112 | bool maxproto; | 112 | bool maxproto; |
| 113 | bool ignore_parity; /* Protocol should ignore parity errors from KBC */ | ||
| 113 | const char *name; | 114 | const char *name; |
| 114 | const char *alias; | 115 | const char *alias; |
| 115 | int (*detect)(struct psmouse *, bool); | 116 | int (*detect)(struct psmouse *, bool); |
| @@ -288,7 +289,9 @@ static irqreturn_t psmouse_interrupt(struct serio *serio, | |||
| 288 | if (psmouse->state == PSMOUSE_IGNORE) | 289 | if (psmouse->state == PSMOUSE_IGNORE) |
| 289 | goto out; | 290 | goto out; |
| 290 | 291 | ||
| 291 | if (flags & (SERIO_PARITY|SERIO_TIMEOUT)) { | 292 | if (unlikely((flags & SERIO_TIMEOUT) || |
| 293 | ((flags & SERIO_PARITY) && !psmouse->ignore_parity))) { | ||
| 294 | |||
| 292 | if (psmouse->state == PSMOUSE_ACTIVATED) | 295 | if (psmouse->state == PSMOUSE_ACTIVATED) |
| 293 | printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", | 296 | printk(KERN_WARNING "psmouse.c: bad data from KBC -%s%s\n", |
| 294 | flags & SERIO_TIMEOUT ? " timeout" : "", | 297 | flags & SERIO_TIMEOUT ? " timeout" : "", |
| @@ -759,6 +762,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
| 759 | .name = "PS/2", | 762 | .name = "PS/2", |
| 760 | .alias = "bare", | 763 | .alias = "bare", |
| 761 | .maxproto = true, | 764 | .maxproto = true, |
| 765 | .ignore_parity = true, | ||
| 762 | .detect = ps2bare_detect, | 766 | .detect = ps2bare_detect, |
| 763 | }, | 767 | }, |
| 764 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP | 768 | #ifdef CONFIG_MOUSE_PS2_LOGIPS2PP |
| @@ -786,6 +790,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
| 786 | .name = "ImPS/2", | 790 | .name = "ImPS/2", |
| 787 | .alias = "imps", | 791 | .alias = "imps", |
| 788 | .maxproto = true, | 792 | .maxproto = true, |
| 793 | .ignore_parity = true, | ||
| 789 | .detect = intellimouse_detect, | 794 | .detect = intellimouse_detect, |
| 790 | }, | 795 | }, |
| 791 | { | 796 | { |
| @@ -793,6 +798,7 @@ static const struct psmouse_protocol psmouse_protocols[] = { | |||
| 793 | .name = "ImExPS/2", | 798 | .name = "ImExPS/2", |
| 794 | .alias = "exps", | 799 | .alias = "exps", |
| 795 | .maxproto = true, | 800 | .maxproto = true, |
| 801 | .ignore_parity = true, | ||
| 796 | .detect = im_explorer_detect, | 802 | .detect = im_explorer_detect, |
| 797 | }, | 803 | }, |
| 798 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS | 804 | #ifdef CONFIG_MOUSE_PS2_SYNAPTICS |
| @@ -1222,6 +1228,7 @@ static void psmouse_disconnect(struct serio *serio) | |||
| 1222 | static int psmouse_switch_protocol(struct psmouse *psmouse, | 1228 | static int psmouse_switch_protocol(struct psmouse *psmouse, |
| 1223 | const struct psmouse_protocol *proto) | 1229 | const struct psmouse_protocol *proto) |
| 1224 | { | 1230 | { |
| 1231 | const struct psmouse_protocol *selected_proto; | ||
| 1225 | struct input_dev *input_dev = psmouse->dev; | 1232 | struct input_dev *input_dev = psmouse->dev; |
| 1226 | 1233 | ||
| 1227 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; | 1234 | input_dev->dev.parent = &psmouse->ps2dev.serio->dev; |
| @@ -1245,9 +1252,14 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, | |||
| 1245 | return -1; | 1252 | return -1; |
| 1246 | 1253 | ||
| 1247 | psmouse->type = proto->type; | 1254 | psmouse->type = proto->type; |
| 1248 | } else | 1255 | selected_proto = proto; |
| 1256 | } else { | ||
| 1249 | psmouse->type = psmouse_extensions(psmouse, | 1257 | psmouse->type = psmouse_extensions(psmouse, |
| 1250 | psmouse_max_proto, true); | 1258 | psmouse_max_proto, true); |
| 1259 | selected_proto = psmouse_protocol_by_type(psmouse->type); | ||
| 1260 | } | ||
| 1261 | |||
| 1262 | psmouse->ignore_parity = selected_proto->ignore_parity; | ||
| 1251 | 1263 | ||
| 1252 | /* | 1264 | /* |
| 1253 | * If mouse's packet size is 3 there is no point in polling the | 1265 | * If mouse's packet size is 3 there is no point in polling the |
| @@ -1267,7 +1279,7 @@ static int psmouse_switch_protocol(struct psmouse *psmouse, | |||
| 1267 | psmouse->resync_time = 0; | 1279 | psmouse->resync_time = 0; |
| 1268 | 1280 | ||
| 1269 | snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", | 1281 | snprintf(psmouse->devname, sizeof(psmouse->devname), "%s %s %s", |
| 1270 | psmouse_protocol_by_type(psmouse->type)->name, psmouse->vendor, psmouse->name); | 1282 | selected_proto->name, psmouse->vendor, psmouse->name); |
| 1271 | 1283 | ||
| 1272 | input_dev->name = psmouse->devname; | 1284 | input_dev->name = psmouse->devname; |
| 1273 | input_dev->phys = psmouse->phys; | 1285 | input_dev->phys = psmouse->phys; |
| @@ -1382,6 +1394,7 @@ static int psmouse_reconnect(struct serio *serio) | |||
| 1382 | struct psmouse *psmouse = serio_get_drvdata(serio); | 1394 | struct psmouse *psmouse = serio_get_drvdata(serio); |
| 1383 | struct psmouse *parent = NULL; | 1395 | struct psmouse *parent = NULL; |
| 1384 | struct serio_driver *drv = serio->drv; | 1396 | struct serio_driver *drv = serio->drv; |
| 1397 | unsigned char type; | ||
| 1385 | int rc = -1; | 1398 | int rc = -1; |
| 1386 | 1399 | ||
| 1387 | if (!drv || !psmouse) { | 1400 | if (!drv || !psmouse) { |
| @@ -1401,10 +1414,15 @@ static int psmouse_reconnect(struct serio *serio) | |||
| 1401 | if (psmouse->reconnect) { | 1414 | if (psmouse->reconnect) { |
| 1402 | if (psmouse->reconnect(psmouse)) | 1415 | if (psmouse->reconnect(psmouse)) |
| 1403 | goto out; | 1416 | goto out; |
| 1404 | } else if (psmouse_probe(psmouse) < 0 || | 1417 | } else { |
| 1405 | psmouse->type != psmouse_extensions(psmouse, | 1418 | psmouse_reset(psmouse); |
| 1406 | psmouse_max_proto, false)) { | 1419 | |
| 1407 | goto out; | 1420 | if (psmouse_probe(psmouse) < 0) |
| 1421 | goto out; | ||
| 1422 | |||
| 1423 | type = psmouse_extensions(psmouse, psmouse_max_proto, false); | ||
| 1424 | if (psmouse->type != type) | ||
| 1425 | goto out; | ||
| 1408 | } | 1426 | } |
| 1409 | 1427 | ||
| 1410 | /* ok, the device type (and capabilities) match the old one, | 1428 | /* ok, the device type (and capabilities) match the old one, |
diff --git a/drivers/input/mouse/psmouse.h b/drivers/input/mouse/psmouse.h index e053bdd137ff..593e910bfc7a 100644 --- a/drivers/input/mouse/psmouse.h +++ b/drivers/input/mouse/psmouse.h | |||
| @@ -47,6 +47,7 @@ struct psmouse { | |||
| 47 | unsigned char pktcnt; | 47 | unsigned char pktcnt; |
| 48 | unsigned char pktsize; | 48 | unsigned char pktsize; |
| 49 | unsigned char type; | 49 | unsigned char type; |
| 50 | bool ignore_parity; | ||
| 50 | bool acks_disable_command; | 51 | bool acks_disable_command; |
| 51 | unsigned int model; | 52 | unsigned int model; |
| 52 | unsigned long last; | 53 | unsigned long last; |
diff --git a/drivers/input/mouse/synaptics.c b/drivers/input/mouse/synaptics.c index 026df6010161..ebd7a99efeae 100644 --- a/drivers/input/mouse/synaptics.c +++ b/drivers/input/mouse/synaptics.c | |||
| @@ -137,7 +137,8 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
| 137 | if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) | 137 | if (synaptics_send_cmd(psmouse, SYN_QUE_CAPABILITIES, cap)) |
| 138 | return -1; | 138 | return -1; |
| 139 | priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 139 | priv->capabilities = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
| 140 | priv->ext_cap = 0; | 140 | priv->ext_cap = priv->ext_cap_0c = 0; |
| 141 | |||
| 141 | if (!SYN_CAP_VALID(priv->capabilities)) | 142 | if (!SYN_CAP_VALID(priv->capabilities)) |
| 142 | return -1; | 143 | return -1; |
| 143 | 144 | ||
| @@ -150,7 +151,7 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
| 150 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { | 151 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 1) { |
| 151 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { | 152 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB, cap)) { |
| 152 | printk(KERN_ERR "Synaptics claims to have extended capabilities," | 153 | printk(KERN_ERR "Synaptics claims to have extended capabilities," |
| 153 | " but I'm not able to read them."); | 154 | " but I'm not able to read them.\n"); |
| 154 | } else { | 155 | } else { |
| 155 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | 156 | priv->ext_cap = (cap[0] << 16) | (cap[1] << 8) | cap[2]; |
| 156 | 157 | ||
| @@ -162,6 +163,16 @@ static int synaptics_capability(struct psmouse *psmouse) | |||
| 162 | priv->ext_cap &= 0xff0fff; | 163 | priv->ext_cap &= 0xff0fff; |
| 163 | } | 164 | } |
| 164 | } | 165 | } |
| 166 | |||
| 167 | if (SYN_EXT_CAP_REQUESTS(priv->capabilities) >= 4) { | ||
| 168 | if (synaptics_send_cmd(psmouse, SYN_QUE_EXT_CAPAB_0C, cap)) { | ||
| 169 | printk(KERN_ERR "Synaptics claims to have extended capability 0x0c," | ||
| 170 | " but I'm not able to read it.\n"); | ||
| 171 | } else { | ||
| 172 | priv->ext_cap_0c = (cap[0] << 16) | (cap[1] << 8) | cap[2]; | ||
| 173 | } | ||
| 174 | } | ||
| 175 | |||
| 165 | return 0; | 176 | return 0; |
| 166 | } | 177 | } |
| 167 | 178 | ||
| @@ -348,7 +359,15 @@ static void synaptics_parse_hw_state(unsigned char buf[], struct synaptics_data | |||
| 348 | hw->left = (buf[0] & 0x01) ? 1 : 0; | 359 | hw->left = (buf[0] & 0x01) ? 1 : 0; |
| 349 | hw->right = (buf[0] & 0x02) ? 1 : 0; | 360 | hw->right = (buf[0] & 0x02) ? 1 : 0; |
| 350 | 361 | ||
| 351 | if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | 362 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { |
| 363 | /* | ||
| 364 | * Clickpad's button is transmitted as middle button, | ||
| 365 | * however, since it is primary button, we will report | ||
| 366 | * it as BTN_LEFT. | ||
| 367 | */ | ||
| 368 | hw->left = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; | ||
| 369 | |||
| 370 | } else if (SYN_CAP_MIDDLE_BUTTON(priv->capabilities)) { | ||
| 352 | hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; | 371 | hw->middle = ((buf[0] ^ buf[3]) & 0x01) ? 1 : 0; |
| 353 | if (hw->w == 2) | 372 | if (hw->w == 2) |
| 354 | hw->scroll = (signed char)(buf[1]); | 373 | hw->scroll = (signed char)(buf[1]); |
| @@ -593,6 +612,12 @@ static void set_input_params(struct input_dev *dev, struct synaptics_data *priv) | |||
| 593 | 612 | ||
| 594 | dev->absres[ABS_X] = priv->x_res; | 613 | dev->absres[ABS_X] = priv->x_res; |
| 595 | dev->absres[ABS_Y] = priv->y_res; | 614 | dev->absres[ABS_Y] = priv->y_res; |
| 615 | |||
| 616 | if (SYN_CAP_CLICKPAD(priv->ext_cap_0c)) { | ||
| 617 | /* Clickpads report only left button */ | ||
| 618 | __clear_bit(BTN_RIGHT, dev->keybit); | ||
| 619 | __clear_bit(BTN_MIDDLE, dev->keybit); | ||
| 620 | } | ||
| 596 | } | 621 | } |
| 597 | 622 | ||
| 598 | static void synaptics_disconnect(struct psmouse *psmouse) | 623 | static void synaptics_disconnect(struct psmouse *psmouse) |
| @@ -697,10 +722,10 @@ int synaptics_init(struct psmouse *psmouse) | |||
| 697 | 722 | ||
| 698 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; | 723 | priv->pkt_type = SYN_MODEL_NEWABS(priv->model_id) ? SYN_NEWABS : SYN_OLDABS; |
| 699 | 724 | ||
| 700 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx\n", | 725 | printk(KERN_INFO "Synaptics Touchpad, model: %ld, fw: %ld.%ld, id: %#lx, caps: %#lx/%#lx/%#lx\n", |
| 701 | SYN_ID_MODEL(priv->identity), | 726 | SYN_ID_MODEL(priv->identity), |
| 702 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), | 727 | SYN_ID_MAJOR(priv->identity), SYN_ID_MINOR(priv->identity), |
| 703 | priv->model_id, priv->capabilities, priv->ext_cap); | 728 | priv->model_id, priv->capabilities, priv->ext_cap, priv->ext_cap_0c); |
| 704 | 729 | ||
| 705 | set_input_params(psmouse->dev, priv); | 730 | set_input_params(psmouse->dev, priv); |
| 706 | 731 | ||
diff --git a/drivers/input/mouse/synaptics.h b/drivers/input/mouse/synaptics.h index f0f40a331dc8..ae37c5d162a4 100644 --- a/drivers/input/mouse/synaptics.h +++ b/drivers/input/mouse/synaptics.h | |||
| @@ -18,6 +18,7 @@ | |||
| 18 | #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 | 18 | #define SYN_QUE_SERIAL_NUMBER_SUFFIX 0x07 |
| 19 | #define SYN_QUE_RESOLUTION 0x08 | 19 | #define SYN_QUE_RESOLUTION 0x08 |
| 20 | #define SYN_QUE_EXT_CAPAB 0x09 | 20 | #define SYN_QUE_EXT_CAPAB 0x09 |
| 21 | #define SYN_QUE_EXT_CAPAB_0C 0x0c | ||
| 21 | 22 | ||
| 22 | /* synatics modes */ | 23 | /* synatics modes */ |
| 23 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) | 24 | #define SYN_BIT_ABSOLUTE_MODE (1 << 7) |
| @@ -48,6 +49,8 @@ | |||
| 48 | #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) | 49 | #define SYN_CAP_VALID(c) ((((c) & 0x00ff00) >> 8) == 0x47) |
| 49 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) | 50 | #define SYN_EXT_CAP_REQUESTS(c) (((c) & 0x700000) >> 20) |
| 50 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) | 51 | #define SYN_CAP_MULTI_BUTTON_NO(ec) (((ec) & 0x00f000) >> 12) |
| 52 | #define SYN_CAP_PRODUCT_ID(ec) (((ec) & 0xff0000) >> 16) | ||
| 53 | #define SYN_CAP_CLICKPAD(ex0c) ((ex0c) & 0x100100) | ||
| 51 | 54 | ||
| 52 | /* synaptics modes query bits */ | 55 | /* synaptics modes query bits */ |
| 53 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) | 56 | #define SYN_MODE_ABSOLUTE(m) ((m) & (1 << 7)) |
| @@ -96,6 +99,7 @@ struct synaptics_data { | |||
| 96 | unsigned long int model_id; /* Model-ID */ | 99 | unsigned long int model_id; /* Model-ID */ |
| 97 | unsigned long int capabilities; /* Capabilities */ | 100 | unsigned long int capabilities; /* Capabilities */ |
| 98 | unsigned long int ext_cap; /* Extended Capabilities */ | 101 | unsigned long int ext_cap; /* Extended Capabilities */ |
| 102 | unsigned long int ext_cap_0c; /* Ext Caps from 0x0c query */ | ||
| 99 | unsigned long int identity; /* Identification */ | 103 | unsigned long int identity; /* Identification */ |
| 100 | int x_res; /* X resolution in units/mm */ | 104 | int x_res; /* X resolution in units/mm */ |
| 101 | int y_res; /* Y resolution in units/mm */ | 105 | int y_res; /* Y resolution in units/mm */ |
diff --git a/drivers/input/touchscreen/Kconfig b/drivers/input/touchscreen/Kconfig index 77a50d9bba17..6c0f1712f55b 100644 --- a/drivers/input/touchscreen/Kconfig +++ b/drivers/input/touchscreen/Kconfig | |||
| @@ -99,22 +99,6 @@ config TOUCHSCREEN_BITSY | |||
| 99 | To compile this driver as a module, choose M here: the | 99 | To compile this driver as a module, choose M here: the |
| 100 | module will be called h3600_ts_input. | 100 | module will be called h3600_ts_input. |
| 101 | 101 | ||
| 102 | config TOUCHSCREEN_CORGI | ||
| 103 | tristate "SharpSL (Corgi and Spitz series) touchscreen driver (DEPRECATED)" | ||
| 104 | depends on PXA_SHARPSL | ||
| 105 | select CORGI_SSP_DEPRECATED | ||
| 106 | help | ||
| 107 | Say Y here to enable the driver for the touchscreen on the | ||
| 108 | Sharp SL-C7xx and SL-Cxx00 series of PDAs. | ||
| 109 | |||
| 110 | If unsure, say N. | ||
| 111 | |||
| 112 | To compile this driver as a module, choose M here: the | ||
| 113 | module will be called corgi_ts. | ||
| 114 | |||
| 115 | NOTE: this driver is deprecated, try enable SPI and generic | ||
| 116 | ADS7846-based touchscreen driver. | ||
| 117 | |||
| 118 | config TOUCHSCREEN_DA9034 | 102 | config TOUCHSCREEN_DA9034 |
| 119 | tristate "Touchscreen support for Dialog Semiconductor DA9034" | 103 | tristate "Touchscreen support for Dialog Semiconductor DA9034" |
| 120 | depends on PMIC_DA903X | 104 | depends on PMIC_DA903X |
diff --git a/drivers/input/touchscreen/Makefile b/drivers/input/touchscreen/Makefile index 7fef7d5cca23..41145d074dec 100644 --- a/drivers/input/touchscreen/Makefile +++ b/drivers/input/touchscreen/Makefile | |||
| @@ -12,7 +12,6 @@ obj-$(CONFIG_TOUCHSCREEN_AD7879) += ad7879.o | |||
| 12 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o | 12 | obj-$(CONFIG_TOUCHSCREEN_ADS7846) += ads7846.o |
| 13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o | 13 | obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC) += atmel_tsadcc.o |
| 14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o | 14 | obj-$(CONFIG_TOUCHSCREEN_BITSY) += h3600_ts_input.o |
| 15 | obj-$(CONFIG_TOUCHSCREEN_CORGI) += corgi_ts.o | ||
| 16 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o | 15 | obj-$(CONFIG_TOUCHSCREEN_DYNAPRO) += dynapro.o |
| 17 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o | 16 | obj-$(CONFIG_TOUCHSCREEN_GUNZE) += gunze.o |
| 18 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o | 17 | obj-$(CONFIG_TOUCHSCREEN_EETI) += eeti_ts.o |
diff --git a/drivers/input/touchscreen/ad7877.c b/drivers/input/touchscreen/ad7877.c index e019d53d1ab4..0d2d7e54b465 100644 --- a/drivers/input/touchscreen/ad7877.c +++ b/drivers/input/touchscreen/ad7877.c | |||
| @@ -156,9 +156,14 @@ struct ser_req { | |||
| 156 | u16 reset; | 156 | u16 reset; |
| 157 | u16 ref_on; | 157 | u16 ref_on; |
| 158 | u16 command; | 158 | u16 command; |
| 159 | u16 sample; | ||
| 160 | struct spi_message msg; | 159 | struct spi_message msg; |
| 161 | struct spi_transfer xfer[6]; | 160 | struct spi_transfer xfer[6]; |
| 161 | |||
| 162 | /* | ||
| 163 | * DMA (thus cache coherency maintenance) requires the | ||
| 164 | * transfer buffers to live in their own cache lines. | ||
| 165 | */ | ||
| 166 | u16 sample ____cacheline_aligned; | ||
| 162 | }; | 167 | }; |
| 163 | 168 | ||
| 164 | struct ad7877 { | 169 | struct ad7877 { |
| @@ -182,8 +187,6 @@ struct ad7877 { | |||
| 182 | u8 averaging; | 187 | u8 averaging; |
| 183 | u8 pen_down_acc_interval; | 188 | u8 pen_down_acc_interval; |
| 184 | 189 | ||
| 185 | u16 conversion_data[AD7877_NR_SENSE]; | ||
| 186 | |||
| 187 | struct spi_transfer xfer[AD7877_NR_SENSE + 2]; | 190 | struct spi_transfer xfer[AD7877_NR_SENSE + 2]; |
| 188 | struct spi_message msg; | 191 | struct spi_message msg; |
| 189 | 192 | ||
| @@ -195,6 +198,12 @@ struct ad7877 { | |||
| 195 | spinlock_t lock; | 198 | spinlock_t lock; |
| 196 | struct timer_list timer; /* P: lock */ | 199 | struct timer_list timer; /* P: lock */ |
| 197 | unsigned pending:1; /* P: lock */ | 200 | unsigned pending:1; /* P: lock */ |
| 201 | |||
| 202 | /* | ||
| 203 | * DMA (thus cache coherency maintenance) requires the | ||
| 204 | * transfer buffers to live in their own cache lines. | ||
| 205 | */ | ||
| 206 | u16 conversion_data[AD7877_NR_SENSE] ____cacheline_aligned; | ||
| 198 | }; | 207 | }; |
| 199 | 208 | ||
| 200 | static int gpio3; | 209 | static int gpio3; |
diff --git a/drivers/input/touchscreen/corgi_ts.c b/drivers/input/touchscreen/corgi_ts.c deleted file mode 100644 index 94a1919d439d..000000000000 --- a/drivers/input/touchscreen/corgi_ts.c +++ /dev/null | |||
| @@ -1,385 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Touchscreen driver for Sharp SL-C7xx and SL-Cxx00 models | ||
| 3 | * | ||
| 4 | * Copyright (c) 2004-2005 Richard Purdie | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License version 2 as | ||
| 8 | * published by the Free Software Foundation. | ||
| 9 | * | ||
| 10 | */ | ||
| 11 | |||
| 12 | |||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/platform_device.h> | ||
| 15 | #include <linux/init.h> | ||
| 16 | #include <linux/input.h> | ||
| 17 | #include <linux/interrupt.h> | ||
| 18 | #include <linux/module.h> | ||
| 19 | #include <linux/slab.h> | ||
| 20 | #include <linux/irq.h> | ||
| 21 | |||
| 22 | #include <mach/sharpsl.h> | ||
| 23 | #include <mach/hardware.h> | ||
| 24 | #include <mach/pxa2xx-gpio.h> | ||
| 25 | |||
| 26 | |||
| 27 | #define PWR_MODE_ACTIVE 0 | ||
| 28 | #define PWR_MODE_SUSPEND 1 | ||
| 29 | |||
| 30 | #define X_AXIS_MAX 3830 | ||
| 31 | #define X_AXIS_MIN 150 | ||
| 32 | #define Y_AXIS_MAX 3830 | ||
| 33 | #define Y_AXIS_MIN 190 | ||
| 34 | #define PRESSURE_MIN 0 | ||
| 35 | #define PRESSURE_MAX 15000 | ||
| 36 | |||
| 37 | struct ts_event { | ||
| 38 | short pressure; | ||
| 39 | short x; | ||
| 40 | short y; | ||
| 41 | }; | ||
| 42 | |||
| 43 | struct corgi_ts { | ||
| 44 | struct input_dev *input; | ||
| 45 | struct timer_list timer; | ||
| 46 | struct ts_event tc; | ||
| 47 | int pendown; | ||
| 48 | int power_mode; | ||
| 49 | int irq_gpio; | ||
| 50 | struct corgits_machinfo *machinfo; | ||
| 51 | }; | ||
| 52 | |||
| 53 | #ifdef CONFIG_PXA25x | ||
| 54 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C0, 0" : "=r"(a)) | ||
| 55 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C0, 0" : "=r"(x)) | ||
| 56 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C0, 0" : : "r"(x)) | ||
| 57 | #endif | ||
| 58 | #ifdef CONFIG_PXA27x | ||
| 59 | #define CCNT(a) asm volatile ("mrc p14, 0, %0, C1, C1, 0" : "=r"(a)) | ||
| 60 | #define PMNC_GET(x) asm volatile ("mrc p14, 0, %0, C0, C1, 0" : "=r"(x)) | ||
| 61 | #define PMNC_SET(x) asm volatile ("mcr p14, 0, %0, C0, C1, 0" : : "r"(x)) | ||
| 62 | #endif | ||
| 63 | |||
| 64 | /* ADS7846 Touch Screen Controller bit definitions */ | ||
| 65 | #define ADSCTRL_PD0 (1u << 0) /* PD0 */ | ||
| 66 | #define ADSCTRL_PD1 (1u << 1) /* PD1 */ | ||
| 67 | #define ADSCTRL_DFR (1u << 2) /* SER/DFR */ | ||
| 68 | #define ADSCTRL_MOD (1u << 3) /* Mode */ | ||
| 69 | #define ADSCTRL_ADR_SH 4 /* Address setting */ | ||
| 70 | #define ADSCTRL_STS (1u << 7) /* Start Bit */ | ||
| 71 | |||
| 72 | /* External Functions */ | ||
| 73 | extern unsigned int get_clk_frequency_khz(int info); | ||
| 74 | |||
| 75 | static unsigned long calc_waittime(struct corgi_ts *corgi_ts) | ||
| 76 | { | ||
| 77 | unsigned long hsync_invperiod = corgi_ts->machinfo->get_hsync_invperiod(); | ||
| 78 | |||
| 79 | if (hsync_invperiod) | ||
| 80 | return get_clk_frequency_khz(0)*1000/hsync_invperiod; | ||
| 81 | else | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | static int sync_receive_data_send_cmd(struct corgi_ts *corgi_ts, int doRecive, int doSend, | ||
| 86 | unsigned int address, unsigned long wait_time) | ||
| 87 | { | ||
| 88 | unsigned long timer1 = 0, timer2, pmnc = 0; | ||
| 89 | int pos = 0; | ||
| 90 | |||
| 91 | if (wait_time && doSend) { | ||
| 92 | PMNC_GET(pmnc); | ||
| 93 | if (!(pmnc & 0x01)) | ||
| 94 | PMNC_SET(0x01); | ||
| 95 | |||
| 96 | /* polling HSync */ | ||
| 97 | corgi_ts->machinfo->wait_hsync(); | ||
| 98 | /* get CCNT */ | ||
| 99 | CCNT(timer1); | ||
| 100 | } | ||
| 101 | |||
| 102 | if (doRecive) | ||
| 103 | pos = corgi_ssp_ads7846_get(); | ||
| 104 | |||
| 105 | if (doSend) { | ||
| 106 | int cmd = ADSCTRL_PD0 | ADSCTRL_PD1 | (address << ADSCTRL_ADR_SH) | ADSCTRL_STS; | ||
| 107 | /* dummy command */ | ||
| 108 | corgi_ssp_ads7846_put(cmd); | ||
| 109 | corgi_ssp_ads7846_get(); | ||
| 110 | |||
| 111 | if (wait_time) { | ||
| 112 | /* Wait after HSync */ | ||
| 113 | CCNT(timer2); | ||
| 114 | if (timer2-timer1 > wait_time) { | ||
| 115 | /* too slow - timeout, try again */ | ||
| 116 | corgi_ts->machinfo->wait_hsync(); | ||
| 117 | /* get CCNT */ | ||
| 118 | CCNT(timer1); | ||
| 119 | /* Wait after HSync */ | ||
| 120 | CCNT(timer2); | ||
| 121 | } | ||
| 122 | while (timer2 - timer1 < wait_time) | ||
| 123 | CCNT(timer2); | ||
| 124 | } | ||
| 125 | corgi_ssp_ads7846_put(cmd); | ||
| 126 | if (wait_time && !(pmnc & 0x01)) | ||
| 127 | PMNC_SET(pmnc); | ||
| 128 | } | ||
| 129 | return pos; | ||
| 130 | } | ||
| 131 | |||
| 132 | static int read_xydata(struct corgi_ts *corgi_ts) | ||
| 133 | { | ||
| 134 | unsigned int x, y, z1, z2; | ||
| 135 | unsigned long flags, wait_time; | ||
| 136 | |||
| 137 | /* critical section */ | ||
| 138 | local_irq_save(flags); | ||
| 139 | corgi_ssp_ads7846_lock(); | ||
| 140 | wait_time = calc_waittime(corgi_ts); | ||
| 141 | |||
| 142 | /* Y-axis */ | ||
| 143 | sync_receive_data_send_cmd(corgi_ts, 0, 1, 1u, wait_time); | ||
| 144 | |||
| 145 | /* Y-axis */ | ||
| 146 | sync_receive_data_send_cmd(corgi_ts, 1, 1, 1u, wait_time); | ||
| 147 | |||
| 148 | /* X-axis */ | ||
| 149 | y = sync_receive_data_send_cmd(corgi_ts, 1, 1, 5u, wait_time); | ||
| 150 | |||
| 151 | /* Z1 */ | ||
| 152 | x = sync_receive_data_send_cmd(corgi_ts, 1, 1, 3u, wait_time); | ||
| 153 | |||
| 154 | /* Z2 */ | ||
| 155 | z1 = sync_receive_data_send_cmd(corgi_ts, 1, 1, 4u, wait_time); | ||
| 156 | z2 = sync_receive_data_send_cmd(corgi_ts, 1, 0, 4u, wait_time); | ||
| 157 | |||
| 158 | /* Power-Down Enable */ | ||
| 159 | corgi_ssp_ads7846_put((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 160 | corgi_ssp_ads7846_get(); | ||
| 161 | |||
| 162 | corgi_ssp_ads7846_unlock(); | ||
| 163 | local_irq_restore(flags); | ||
| 164 | |||
| 165 | if (x== 0 || y == 0 || z1 == 0 || (x * (z2 - z1) / z1) >= 15000) { | ||
| 166 | corgi_ts->tc.pressure = 0; | ||
| 167 | return 0; | ||
| 168 | } | ||
| 169 | |||
| 170 | corgi_ts->tc.x = x; | ||
| 171 | corgi_ts->tc.y = y; | ||
| 172 | corgi_ts->tc.pressure = (x * (z2 - z1)) / z1; | ||
| 173 | return 1; | ||
| 174 | } | ||
| 175 | |||
| 176 | static void new_data(struct corgi_ts *corgi_ts) | ||
| 177 | { | ||
| 178 | struct input_dev *dev = corgi_ts->input; | ||
| 179 | |||
| 180 | if (corgi_ts->power_mode != PWR_MODE_ACTIVE) | ||
| 181 | return; | ||
| 182 | |||
| 183 | if (!corgi_ts->tc.pressure && corgi_ts->pendown == 0) | ||
| 184 | return; | ||
| 185 | |||
| 186 | input_report_abs(dev, ABS_X, corgi_ts->tc.x); | ||
| 187 | input_report_abs(dev, ABS_Y, corgi_ts->tc.y); | ||
| 188 | input_report_abs(dev, ABS_PRESSURE, corgi_ts->tc.pressure); | ||
| 189 | input_report_key(dev, BTN_TOUCH, corgi_ts->pendown); | ||
| 190 | input_sync(dev); | ||
| 191 | } | ||
| 192 | |||
| 193 | static void ts_interrupt_main(struct corgi_ts *corgi_ts, int isTimer) | ||
| 194 | { | ||
| 195 | if ((GPLR(IRQ_TO_GPIO(corgi_ts->irq_gpio)) & GPIO_bit(IRQ_TO_GPIO(corgi_ts->irq_gpio))) == 0) { | ||
| 196 | /* Disable Interrupt */ | ||
| 197 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_NONE); | ||
| 198 | if (read_xydata(corgi_ts)) { | ||
| 199 | corgi_ts->pendown = 1; | ||
| 200 | new_data(corgi_ts); | ||
| 201 | } | ||
| 202 | mod_timer(&corgi_ts->timer, jiffies + HZ / 100); | ||
| 203 | } else { | ||
| 204 | if (corgi_ts->pendown == 1 || corgi_ts->pendown == 2) { | ||
| 205 | mod_timer(&corgi_ts->timer, jiffies + HZ / 100); | ||
| 206 | corgi_ts->pendown++; | ||
| 207 | return; | ||
| 208 | } | ||
| 209 | |||
| 210 | if (corgi_ts->pendown) { | ||
| 211 | corgi_ts->tc.pressure = 0; | ||
| 212 | new_data(corgi_ts); | ||
| 213 | } | ||
| 214 | |||
| 215 | /* Enable Falling Edge */ | ||
| 216 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
| 217 | corgi_ts->pendown = 0; | ||
| 218 | } | ||
| 219 | } | ||
| 220 | |||
| 221 | static void corgi_ts_timer(unsigned long data) | ||
| 222 | { | ||
| 223 | struct corgi_ts *corgits_data = (struct corgi_ts *) data; | ||
| 224 | |||
| 225 | ts_interrupt_main(corgits_data, 1); | ||
| 226 | } | ||
| 227 | |||
| 228 | static irqreturn_t ts_interrupt(int irq, void *dev_id) | ||
| 229 | { | ||
| 230 | struct corgi_ts *corgits_data = dev_id; | ||
| 231 | |||
| 232 | ts_interrupt_main(corgits_data, 0); | ||
| 233 | return IRQ_HANDLED; | ||
| 234 | } | ||
| 235 | |||
| 236 | #ifdef CONFIG_PM | ||
| 237 | static int corgits_suspend(struct platform_device *dev, pm_message_t state) | ||
| 238 | { | ||
| 239 | struct corgi_ts *corgi_ts = platform_get_drvdata(dev); | ||
| 240 | |||
| 241 | if (corgi_ts->pendown) { | ||
| 242 | del_timer_sync(&corgi_ts->timer); | ||
| 243 | corgi_ts->tc.pressure = 0; | ||
| 244 | new_data(corgi_ts); | ||
| 245 | corgi_ts->pendown = 0; | ||
| 246 | } | ||
| 247 | corgi_ts->power_mode = PWR_MODE_SUSPEND; | ||
| 248 | |||
| 249 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 250 | |||
| 251 | return 0; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int corgits_resume(struct platform_device *dev) | ||
| 255 | { | ||
| 256 | struct corgi_ts *corgi_ts = platform_get_drvdata(dev); | ||
| 257 | |||
| 258 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 259 | /* Enable Falling Edge */ | ||
| 260 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
| 261 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | ||
| 262 | |||
| 263 | return 0; | ||
| 264 | } | ||
| 265 | #else | ||
| 266 | #define corgits_suspend NULL | ||
| 267 | #define corgits_resume NULL | ||
| 268 | #endif | ||
| 269 | |||
| 270 | static int __devinit corgits_probe(struct platform_device *pdev) | ||
| 271 | { | ||
| 272 | struct corgi_ts *corgi_ts; | ||
| 273 | struct input_dev *input_dev; | ||
| 274 | int err = -ENOMEM; | ||
| 275 | |||
| 276 | corgi_ts = kzalloc(sizeof(struct corgi_ts), GFP_KERNEL); | ||
| 277 | input_dev = input_allocate_device(); | ||
| 278 | if (!corgi_ts || !input_dev) | ||
| 279 | goto fail1; | ||
| 280 | |||
| 281 | platform_set_drvdata(pdev, corgi_ts); | ||
| 282 | |||
| 283 | corgi_ts->machinfo = pdev->dev.platform_data; | ||
| 284 | corgi_ts->irq_gpio = platform_get_irq(pdev, 0); | ||
| 285 | |||
| 286 | if (corgi_ts->irq_gpio < 0) { | ||
| 287 | err = -ENODEV; | ||
| 288 | goto fail1; | ||
| 289 | } | ||
| 290 | |||
| 291 | corgi_ts->input = input_dev; | ||
| 292 | |||
| 293 | init_timer(&corgi_ts->timer); | ||
| 294 | corgi_ts->timer.data = (unsigned long) corgi_ts; | ||
| 295 | corgi_ts->timer.function = corgi_ts_timer; | ||
| 296 | |||
| 297 | input_dev->name = "Corgi Touchscreen"; | ||
| 298 | input_dev->phys = "corgits/input0"; | ||
| 299 | input_dev->id.bustype = BUS_HOST; | ||
| 300 | input_dev->id.vendor = 0x0001; | ||
| 301 | input_dev->id.product = 0x0002; | ||
| 302 | input_dev->id.version = 0x0100; | ||
| 303 | input_dev->dev.parent = &pdev->dev; | ||
| 304 | |||
| 305 | input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); | ||
| 306 | input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH); | ||
| 307 | input_set_abs_params(input_dev, ABS_X, X_AXIS_MIN, X_AXIS_MAX, 0, 0); | ||
| 308 | input_set_abs_params(input_dev, ABS_Y, Y_AXIS_MIN, Y_AXIS_MAX, 0, 0); | ||
| 309 | input_set_abs_params(input_dev, ABS_PRESSURE, PRESSURE_MIN, PRESSURE_MAX, 0, 0); | ||
| 310 | |||
| 311 | pxa_gpio_mode(IRQ_TO_GPIO(corgi_ts->irq_gpio) | GPIO_IN); | ||
| 312 | |||
| 313 | /* Initiaize ADS7846 Difference Reference mode */ | ||
| 314 | corgi_ssp_ads7846_putget((1u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 315 | mdelay(5); | ||
| 316 | corgi_ssp_ads7846_putget((3u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 317 | mdelay(5); | ||
| 318 | corgi_ssp_ads7846_putget((4u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 319 | mdelay(5); | ||
| 320 | corgi_ssp_ads7846_putget((5u << ADSCTRL_ADR_SH) | ADSCTRL_STS); | ||
| 321 | mdelay(5); | ||
| 322 | |||
| 323 | if (request_irq(corgi_ts->irq_gpio, ts_interrupt, IRQF_DISABLED, "ts", corgi_ts)) { | ||
| 324 | err = -EBUSY; | ||
| 325 | goto fail1; | ||
| 326 | } | ||
| 327 | |||
| 328 | err = input_register_device(corgi_ts->input); | ||
| 329 | if (err) | ||
| 330 | goto fail2; | ||
| 331 | |||
| 332 | corgi_ts->power_mode = PWR_MODE_ACTIVE; | ||
| 333 | |||
| 334 | /* Enable Falling Edge */ | ||
| 335 | set_irq_type(corgi_ts->irq_gpio, IRQ_TYPE_EDGE_FALLING); | ||
| 336 | |||
| 337 | return 0; | ||
| 338 | |||
| 339 | fail2: free_irq(corgi_ts->irq_gpio, corgi_ts); | ||
| 340 | fail1: input_free_device(input_dev); | ||
| 341 | kfree(corgi_ts); | ||
| 342 | return err; | ||
| 343 | } | ||
| 344 | |||
| 345 | static int __devexit corgits_remove(struct platform_device *pdev) | ||
| 346 | { | ||
| 347 | struct corgi_ts *corgi_ts = platform_get_drvdata(pdev); | ||
| 348 | |||
| 349 | free_irq(corgi_ts->irq_gpio, corgi_ts); | ||
| 350 | del_timer_sync(&corgi_ts->timer); | ||
| 351 | corgi_ts->machinfo->put_hsync(); | ||
| 352 | input_unregister_device(corgi_ts->input); | ||
| 353 | kfree(corgi_ts); | ||
| 354 | |||
| 355 | return 0; | ||
| 356 | } | ||
| 357 | |||
| 358 | static struct platform_driver corgits_driver = { | ||
| 359 | .probe = corgits_probe, | ||
| 360 | .remove = __devexit_p(corgits_remove), | ||
| 361 | .suspend = corgits_suspend, | ||
| 362 | .resume = corgits_resume, | ||
| 363 | .driver = { | ||
| 364 | .name = "corgi-ts", | ||
| 365 | .owner = THIS_MODULE, | ||
| 366 | }, | ||
| 367 | }; | ||
| 368 | |||
| 369 | static int __init corgits_init(void) | ||
| 370 | { | ||
| 371 | return platform_driver_register(&corgits_driver); | ||
| 372 | } | ||
| 373 | |||
| 374 | static void __exit corgits_exit(void) | ||
| 375 | { | ||
| 376 | platform_driver_unregister(&corgits_driver); | ||
| 377 | } | ||
| 378 | |||
| 379 | module_init(corgits_init); | ||
| 380 | module_exit(corgits_exit); | ||
| 381 | |||
| 382 | MODULE_AUTHOR("Richard Purdie <rpurdie@rpsys.net>"); | ||
| 383 | MODULE_DESCRIPTION("Corgi TouchScreen Driver"); | ||
| 384 | MODULE_LICENSE("GPL"); | ||
| 385 | MODULE_ALIAS("platform:corgi-ts"); | ||
diff --git a/drivers/input/touchscreen/eeti_ts.c b/drivers/input/touchscreen/eeti_ts.c index 204b8a1a601c..75f8b73010fa 100644 --- a/drivers/input/touchscreen/eeti_ts.c +++ b/drivers/input/touchscreen/eeti_ts.c | |||
| @@ -124,14 +124,25 @@ static irqreturn_t eeti_ts_isr(int irq, void *dev_id) | |||
| 124 | return IRQ_HANDLED; | 124 | return IRQ_HANDLED; |
| 125 | } | 125 | } |
| 126 | 126 | ||
| 127 | static int eeti_ts_open(struct input_dev *dev) | 127 | static void eeti_ts_start(struct eeti_ts_priv *priv) |
| 128 | { | 128 | { |
| 129 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | ||
| 130 | |||
| 131 | enable_irq(priv->irq); | 129 | enable_irq(priv->irq); |
| 132 | 130 | ||
| 133 | /* Read the events once to arm the IRQ */ | 131 | /* Read the events once to arm the IRQ */ |
| 134 | eeti_ts_read(&priv->work); | 132 | eeti_ts_read(&priv->work); |
| 133 | } | ||
| 134 | |||
| 135 | static void eeti_ts_stop(struct eeti_ts_priv *priv) | ||
| 136 | { | ||
| 137 | disable_irq(priv->irq); | ||
| 138 | cancel_work_sync(&priv->work); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int eeti_ts_open(struct input_dev *dev) | ||
| 142 | { | ||
| 143 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | ||
| 144 | |||
| 145 | eeti_ts_start(priv); | ||
| 135 | 146 | ||
| 136 | return 0; | 147 | return 0; |
| 137 | } | 148 | } |
| @@ -140,8 +151,7 @@ static void eeti_ts_close(struct input_dev *dev) | |||
| 140 | { | 151 | { |
| 141 | struct eeti_ts_priv *priv = input_get_drvdata(dev); | 152 | struct eeti_ts_priv *priv = input_get_drvdata(dev); |
| 142 | 153 | ||
| 143 | disable_irq(priv->irq); | 154 | eeti_ts_stop(priv); |
| 144 | cancel_work_sync(&priv->work); | ||
| 145 | } | 155 | } |
| 146 | 156 | ||
| 147 | static int __devinit eeti_ts_probe(struct i2c_client *client, | 157 | static int __devinit eeti_ts_probe(struct i2c_client *client, |
| @@ -153,10 +163,12 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
| 153 | unsigned int irq_flags; | 163 | unsigned int irq_flags; |
| 154 | int err = -ENOMEM; | 164 | int err = -ENOMEM; |
| 155 | 165 | ||
| 156 | /* In contrast to what's described in the datasheet, there seems | 166 | /* |
| 167 | * In contrast to what's described in the datasheet, there seems | ||
| 157 | * to be no way of probing the presence of that device using I2C | 168 | * to be no way of probing the presence of that device using I2C |
| 158 | * commands. So we need to blindly believe it is there, and wait | 169 | * commands. So we need to blindly believe it is there, and wait |
| 159 | * for interrupts to occur. */ | 170 | * for interrupts to occur. |
| 171 | */ | ||
| 160 | 172 | ||
| 161 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 173 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 162 | if (!priv) { | 174 | if (!priv) { |
| @@ -212,9 +224,11 @@ static int __devinit eeti_ts_probe(struct i2c_client *client, | |||
| 212 | goto err2; | 224 | goto err2; |
| 213 | } | 225 | } |
| 214 | 226 | ||
| 215 | /* Disable the irq for now. It will be enabled once the input device | 227 | /* |
| 216 | * is opened. */ | 228 | * Disable the device for now. It will be enabled once the |
| 217 | disable_irq(priv->irq); | 229 | * input device is opened. |
| 230 | */ | ||
| 231 | eeti_ts_stop(priv); | ||
| 218 | 232 | ||
| 219 | device_init_wakeup(&client->dev, 0); | 233 | device_init_wakeup(&client->dev, 0); |
| 220 | return 0; | 234 | return 0; |
| @@ -235,6 +249,12 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) | |||
| 235 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 249 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
| 236 | 250 | ||
| 237 | free_irq(priv->irq, priv); | 251 | free_irq(priv->irq, priv); |
| 252 | /* | ||
| 253 | * eeti_ts_stop() leaves IRQ disabled. We need to re-enable it | ||
| 254 | * so that device still works if we reload the driver. | ||
| 255 | */ | ||
| 256 | enable_irq(priv->irq); | ||
| 257 | |||
| 238 | input_unregister_device(priv->input); | 258 | input_unregister_device(priv->input); |
| 239 | i2c_set_clientdata(client, NULL); | 259 | i2c_set_clientdata(client, NULL); |
| 240 | kfree(priv); | 260 | kfree(priv); |
| @@ -246,6 +266,14 @@ static int __devexit eeti_ts_remove(struct i2c_client *client) | |||
| 246 | static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | 266 | static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) |
| 247 | { | 267 | { |
| 248 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 268 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
| 269 | struct input_dev *input_dev = priv->input; | ||
| 270 | |||
| 271 | mutex_lock(&input_dev->mutex); | ||
| 272 | |||
| 273 | if (input_dev->users) | ||
| 274 | eeti_ts_stop(priv); | ||
| 275 | |||
| 276 | mutex_unlock(&input_dev->mutex); | ||
| 249 | 277 | ||
| 250 | if (device_may_wakeup(&client->dev)) | 278 | if (device_may_wakeup(&client->dev)) |
| 251 | enable_irq_wake(priv->irq); | 279 | enable_irq_wake(priv->irq); |
| @@ -256,10 +284,18 @@ static int eeti_ts_suspend(struct i2c_client *client, pm_message_t mesg) | |||
| 256 | static int eeti_ts_resume(struct i2c_client *client) | 284 | static int eeti_ts_resume(struct i2c_client *client) |
| 257 | { | 285 | { |
| 258 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); | 286 | struct eeti_ts_priv *priv = i2c_get_clientdata(client); |
| 287 | struct input_dev *input_dev = priv->input; | ||
| 259 | 288 | ||
| 260 | if (device_may_wakeup(&client->dev)) | 289 | if (device_may_wakeup(&client->dev)) |
| 261 | disable_irq_wake(priv->irq); | 290 | disable_irq_wake(priv->irq); |
| 262 | 291 | ||
| 292 | mutex_lock(&input_dev->mutex); | ||
| 293 | |||
| 294 | if (input_dev->users) | ||
| 295 | eeti_ts_start(priv); | ||
| 296 | |||
| 297 | mutex_unlock(&input_dev->mutex); | ||
| 298 | |||
| 263 | return 0; | 299 | return 0; |
| 264 | } | 300 | } |
| 265 | #else | 301 | #else |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 9712b2e97be4..cefd63daff31 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -2109,12 +2109,18 @@ repeat: | |||
| 2109 | if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */ | 2109 | if (!mddev->in_sync || mddev->recovery_cp != MaxSector) { /* not clean */ |
| 2110 | /* .. if the array isn't clean, an 'even' event must also go | 2110 | /* .. if the array isn't clean, an 'even' event must also go |
| 2111 | * to spares. */ | 2111 | * to spares. */ |
| 2112 | if ((mddev->events&1)==0) | 2112 | if ((mddev->events&1)==0) { |
| 2113 | nospares = 0; | 2113 | nospares = 0; |
| 2114 | sync_req = 2; /* force a second update to get the | ||
| 2115 | * even/odd in sync */ | ||
| 2116 | } | ||
| 2114 | } else { | 2117 | } else { |
| 2115 | /* otherwise an 'odd' event must go to spares */ | 2118 | /* otherwise an 'odd' event must go to spares */ |
| 2116 | if ((mddev->events&1)) | 2119 | if ((mddev->events&1)) { |
| 2117 | nospares = 0; | 2120 | nospares = 0; |
| 2121 | sync_req = 2; /* force a second update to get the | ||
| 2122 | * even/odd in sync */ | ||
| 2123 | } | ||
| 2118 | } | 2124 | } |
| 2119 | } | 2125 | } |
| 2120 | 2126 | ||
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 58ea0ecae7c3..15348c393b5d 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -1527,7 +1527,7 @@ static void raid5_end_read_request(struct bio * bi, int error) | |||
| 1527 | 1527 | ||
| 1528 | clear_bit(R5_UPTODATE, &sh->dev[i].flags); | 1528 | clear_bit(R5_UPTODATE, &sh->dev[i].flags); |
| 1529 | atomic_inc(&rdev->read_errors); | 1529 | atomic_inc(&rdev->read_errors); |
| 1530 | if (conf->mddev->degraded) | 1530 | if (conf->mddev->degraded >= conf->max_degraded) |
| 1531 | printk_rl(KERN_WARNING | 1531 | printk_rl(KERN_WARNING |
| 1532 | "raid5:%s: read error not correctable " | 1532 | "raid5:%s: read error not correctable " |
| 1533 | "(sector %llu on %s).\n", | 1533 | "(sector %llu on %s).\n", |
diff --git a/drivers/media/common/saa7146_fops.c b/drivers/media/common/saa7146_fops.c index fd8e1f45be36..7364b9642d00 100644 --- a/drivers/media/common/saa7146_fops.c +++ b/drivers/media/common/saa7146_fops.c | |||
| @@ -423,15 +423,14 @@ static void vv_callback(struct saa7146_dev *dev, unsigned long status) | |||
| 423 | } | 423 | } |
| 424 | } | 424 | } |
| 425 | 425 | ||
| 426 | int saa7146_vv_devinit(struct saa7146_dev *dev) | ||
| 427 | { | ||
| 428 | return v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); | ||
| 429 | } | ||
| 430 | EXPORT_SYMBOL_GPL(saa7146_vv_devinit); | ||
| 431 | |||
| 432 | int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) | 426 | int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv) |
| 433 | { | 427 | { |
| 434 | struct saa7146_vv *vv; | 428 | struct saa7146_vv *vv; |
| 429 | int err; | ||
| 430 | |||
| 431 | err = v4l2_device_register(&dev->pci->dev, &dev->v4l2_dev); | ||
| 432 | if (err) | ||
| 433 | return err; | ||
| 435 | 434 | ||
| 436 | vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); | 435 | vv = kzalloc(sizeof(struct saa7146_vv), GFP_KERNEL); |
| 437 | if (vv == NULL) { | 436 | if (vv == NULL) { |
diff --git a/drivers/media/common/saa7146_video.c b/drivers/media/common/saa7146_video.c index 5ed75263340a..b8b2c551a1e2 100644 --- a/drivers/media/common/saa7146_video.c +++ b/drivers/media/common/saa7146_video.c | |||
| @@ -558,9 +558,11 @@ static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f | |||
| 558 | /* ok, accept it */ | 558 | /* ok, accept it */ |
| 559 | vv->ov_fb = *fb; | 559 | vv->ov_fb = *fb; |
| 560 | vv->ov_fmt = fmt; | 560 | vv->ov_fmt = fmt; |
| 561 | if (0 == vv->ov_fb.fmt.bytesperline) | 561 | |
| 562 | vv->ov_fb.fmt.bytesperline = | 562 | if (vv->ov_fb.fmt.bytesperline < vv->ov_fb.fmt.width) { |
| 563 | vv->ov_fb.fmt.width * fmt->depth / 8; | 563 | vv->ov_fb.fmt.bytesperline = vv->ov_fb.fmt.width * fmt->depth / 8; |
| 564 | DEB_D(("setting bytesperline to %d\n", vv->ov_fb.fmt.bytesperline)); | ||
| 565 | } | ||
| 564 | 566 | ||
| 565 | mutex_unlock(&dev->lock); | 567 | mutex_unlock(&dev->lock); |
| 566 | return 0; | 568 | return 0; |
diff --git a/drivers/media/dvb/frontends/stv090x.c b/drivers/media/dvb/frontends/stv090x.c index a3c07fe0e6c4..96972804f4ad 100644 --- a/drivers/media/dvb/frontends/stv090x.c +++ b/drivers/media/dvb/frontends/stv090x.c | |||
| @@ -4470,6 +4470,10 @@ static int stv090x_setup(struct dvb_frontend *fe) | |||
| 4470 | if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) | 4470 | if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0) |
| 4471 | goto err; | 4471 | goto err; |
| 4472 | 4472 | ||
| 4473 | /* workaround for stuck DiSEqC output */ | ||
| 4474 | if (config->diseqc_envelope_mode) | ||
| 4475 | stv090x_send_diseqc_burst(fe, SEC_MINI_A); | ||
| 4476 | |||
| 4473 | return 0; | 4477 | return 0; |
| 4474 | err: | 4478 | err: |
| 4475 | dprintk(FE_ERROR, 1, "I/O error"); | 4479 | dprintk(FE_ERROR, 1, "I/O error"); |
diff --git a/drivers/media/dvb/ttpci/budget.c b/drivers/media/dvb/ttpci/budget.c index 9fdf26cc6998..1500210c06cf 100644 --- a/drivers/media/dvb/ttpci/budget.c +++ b/drivers/media/dvb/ttpci/budget.c | |||
| @@ -643,9 +643,6 @@ static void frontend_init(struct budget *budget) | |||
| 643 | &budget->i2c_adap, | 643 | &budget->i2c_adap, |
| 644 | &tt1600_isl6423_config); | 644 | &tt1600_isl6423_config); |
| 645 | 645 | ||
| 646 | } else { | ||
| 647 | dvb_frontend_detach(budget->dvb_frontend); | ||
| 648 | budget->dvb_frontend = NULL; | ||
| 649 | } | 646 | } |
| 650 | } | 647 | } |
| 651 | break; | 648 | break; |
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig index f8fc8654693d..9644cf760aaa 100644 --- a/drivers/media/video/Kconfig +++ b/drivers/media/video/Kconfig | |||
| @@ -361,7 +361,7 @@ config VIDEO_SAA717X | |||
| 361 | 361 | ||
| 362 | config VIDEO_SAA7191 | 362 | config VIDEO_SAA7191 |
| 363 | tristate "Philips SAA7191 video decoder" | 363 | tristate "Philips SAA7191 video decoder" |
| 364 | depends on VIDEO_V4L1 && I2C | 364 | depends on VIDEO_V4L2 && I2C |
| 365 | ---help--- | 365 | ---help--- |
| 366 | Support for the Philips SAA7191 video decoder. | 366 | Support for the Philips SAA7191 video decoder. |
| 367 | 367 | ||
| @@ -756,7 +756,7 @@ source "drivers/media/video/saa7134/Kconfig" | |||
| 756 | 756 | ||
| 757 | config VIDEO_MXB | 757 | config VIDEO_MXB |
| 758 | tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" | 758 | tristate "Siemens-Nixdorf 'Multimedia eXtension Board'" |
| 759 | depends on PCI && VIDEO_V4L1 && I2C | 759 | depends on PCI && VIDEO_V4L2 && I2C |
| 760 | select VIDEO_SAA7146_VV | 760 | select VIDEO_SAA7146_VV |
| 761 | select VIDEO_TUNER | 761 | select VIDEO_TUNER |
| 762 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO | 762 | select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO |
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile index b88b6174a331..c51c386559f2 100644 --- a/drivers/media/video/Makefile +++ b/drivers/media/video/Makefile | |||
| @@ -160,8 +160,6 @@ obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o | |||
| 160 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o | 160 | obj-$(CONFIG_VIDEO_PXA27x) += pxa_camera.o |
| 161 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o | 161 | obj-$(CONFIG_VIDEO_SH_MOBILE_CEU) += sh_mobile_ceu_camera.o |
| 162 | 162 | ||
| 163 | obj-$(CONFIG_ARCH_DAVINCI) += davinci/ | ||
| 164 | |||
| 165 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ | 163 | obj-$(CONFIG_VIDEO_AU0828) += au0828/ |
| 166 | 164 | ||
| 167 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ | 165 | obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/ |
diff --git a/drivers/media/video/davinci/vpfe_capture.c b/drivers/media/video/davinci/vpfe_capture.c index 7cf042f9b377..398dbe71cb82 100644 --- a/drivers/media/video/davinci/vpfe_capture.c +++ b/drivers/media/video/davinci/vpfe_capture.c | |||
| @@ -223,7 +223,6 @@ int vpfe_register_ccdc_device(struct ccdc_hw_device *dev) | |||
| 223 | BUG_ON(!dev->hw_ops.get_frame_format); | 223 | BUG_ON(!dev->hw_ops.get_frame_format); |
| 224 | BUG_ON(!dev->hw_ops.get_pixel_format); | 224 | BUG_ON(!dev->hw_ops.get_pixel_format); |
| 225 | BUG_ON(!dev->hw_ops.set_pixel_format); | 225 | BUG_ON(!dev->hw_ops.set_pixel_format); |
| 226 | BUG_ON(!dev->hw_ops.set_params); | ||
| 227 | BUG_ON(!dev->hw_ops.set_image_window); | 226 | BUG_ON(!dev->hw_ops.set_image_window); |
| 228 | BUG_ON(!dev->hw_ops.get_image_window); | 227 | BUG_ON(!dev->hw_ops.get_image_window); |
| 229 | BUG_ON(!dev->hw_ops.get_line_length); | 228 | BUG_ON(!dev->hw_ops.get_line_length); |
| @@ -1689,11 +1688,12 @@ static long vpfe_param_handler(struct file *file, void *priv, | |||
| 1689 | struct vpfe_device *vpfe_dev = video_drvdata(file); | 1688 | struct vpfe_device *vpfe_dev = video_drvdata(file); |
| 1690 | int ret = 0; | 1689 | int ret = 0; |
| 1691 | 1690 | ||
| 1692 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); | 1691 | v4l2_dbg(2, debug, &vpfe_dev->v4l2_dev, "vpfe_param_handler\n"); |
| 1693 | 1692 | ||
| 1694 | if (vpfe_dev->started) { | 1693 | if (vpfe_dev->started) { |
| 1695 | /* only allowed if streaming is not started */ | 1694 | /* only allowed if streaming is not started */ |
| 1696 | v4l2_err(&vpfe_dev->v4l2_dev, "device already started\n"); | 1695 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, |
| 1696 | "device already started\n"); | ||
| 1697 | return -EBUSY; | 1697 | return -EBUSY; |
| 1698 | } | 1698 | } |
| 1699 | 1699 | ||
| @@ -1705,16 +1705,23 @@ static long vpfe_param_handler(struct file *file, void *priv, | |||
| 1705 | case VPFE_CMD_S_CCDC_RAW_PARAMS: | 1705 | case VPFE_CMD_S_CCDC_RAW_PARAMS: |
| 1706 | v4l2_warn(&vpfe_dev->v4l2_dev, | 1706 | v4l2_warn(&vpfe_dev->v4l2_dev, |
| 1707 | "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); | 1707 | "VPFE_CMD_S_CCDC_RAW_PARAMS: experimental ioctl\n"); |
| 1708 | ret = ccdc_dev->hw_ops.set_params(param); | 1708 | if (ccdc_dev->hw_ops.set_params) { |
| 1709 | if (ret) { | 1709 | ret = ccdc_dev->hw_ops.set_params(param); |
| 1710 | v4l2_err(&vpfe_dev->v4l2_dev, | 1710 | if (ret) { |
| 1711 | "Error in setting parameters in CCDC\n"); | 1711 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, |
| 1712 | goto unlock_out; | 1712 | "Error setting parameters in CCDC\n"); |
| 1713 | } | 1713 | goto unlock_out; |
| 1714 | if (vpfe_get_ccdc_image_format(vpfe_dev, &vpfe_dev->fmt) < 0) { | 1714 | } |
| 1715 | v4l2_err(&vpfe_dev->v4l2_dev, | 1715 | if (vpfe_get_ccdc_image_format(vpfe_dev, |
| 1716 | "Invalid image format at CCDC\n"); | 1716 | &vpfe_dev->fmt) < 0) { |
| 1717 | goto unlock_out; | 1717 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, |
| 1718 | "Invalid image format at CCDC\n"); | ||
| 1719 | goto unlock_out; | ||
| 1720 | } | ||
| 1721 | } else { | ||
| 1722 | ret = -EINVAL; | ||
| 1723 | v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, | ||
| 1724 | "VPFE_CMD_S_CCDC_RAW_PARAMS not supported\n"); | ||
| 1718 | } | 1725 | } |
| 1719 | break; | 1726 | break; |
| 1720 | default: | 1727 | default: |
| @@ -1830,7 +1837,7 @@ static __init int vpfe_probe(struct platform_device *pdev) | |||
| 1830 | if (NULL == ccdc_cfg) { | 1837 | if (NULL == ccdc_cfg) { |
| 1831 | v4l2_err(pdev->dev.driver, | 1838 | v4l2_err(pdev->dev.driver, |
| 1832 | "Memory allocation failed for ccdc_cfg\n"); | 1839 | "Memory allocation failed for ccdc_cfg\n"); |
| 1833 | goto probe_free_dev_mem; | 1840 | goto probe_free_lock; |
| 1834 | } | 1841 | } |
| 1835 | 1842 | ||
| 1836 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); | 1843 | strncpy(ccdc_cfg->name, vpfe_cfg->ccdc, 32); |
| @@ -1982,8 +1989,9 @@ probe_out_video_release: | |||
| 1982 | probe_out_release_irq: | 1989 | probe_out_release_irq: |
| 1983 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); | 1990 | free_irq(vpfe_dev->ccdc_irq0, vpfe_dev); |
| 1984 | probe_free_ccdc_cfg_mem: | 1991 | probe_free_ccdc_cfg_mem: |
| 1985 | mutex_unlock(&ccdc_lock); | ||
| 1986 | kfree(ccdc_cfg); | 1992 | kfree(ccdc_cfg); |
| 1993 | probe_free_lock: | ||
| 1994 | mutex_unlock(&ccdc_lock); | ||
| 1987 | probe_free_dev_mem: | 1995 | probe_free_dev_mem: |
| 1988 | kfree(vpfe_dev); | 1996 | kfree(vpfe_dev); |
| 1989 | return ret; | 1997 | return ret; |
diff --git a/drivers/media/video/gspca/sn9c20x.c b/drivers/media/video/gspca/sn9c20x.c index 38a6e15e096b..3dee3e5844b6 100644 --- a/drivers/media/video/gspca/sn9c20x.c +++ b/drivers/media/video/gspca/sn9c20x.c | |||
| @@ -1427,7 +1427,7 @@ static int input_kthread(void *data) | |||
| 1427 | struct gspca_dev *gspca_dev = (struct gspca_dev *)data; | 1427 | struct gspca_dev *gspca_dev = (struct gspca_dev *)data; |
| 1428 | struct sd *sd = (struct sd *) gspca_dev; | 1428 | struct sd *sd = (struct sd *) gspca_dev; |
| 1429 | 1429 | ||
| 1430 | DECLARE_WAIT_QUEUE_HEAD(wait); | 1430 | DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wait); |
| 1431 | set_freezable(); | 1431 | set_freezable(); |
| 1432 | for (;;) { | 1432 | for (;;) { |
| 1433 | if (kthread_should_stop()) | 1433 | if (kthread_should_stop()) |
diff --git a/drivers/media/video/gspca/spca508.c b/drivers/media/video/gspca/spca508.c index 15b2eef8a3f6..edf0fe157501 100644 --- a/drivers/media/video/gspca/spca508.c +++ b/drivers/media/video/gspca/spca508.c | |||
| @@ -1513,7 +1513,6 @@ static const struct sd_desc sd_desc = { | |||
| 1513 | static const __devinitdata struct usb_device_id device_table[] = { | 1513 | static const __devinitdata struct usb_device_id device_table[] = { |
| 1514 | {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam}, | 1514 | {USB_DEVICE(0x0130, 0x0130), .driver_info = HamaUSBSightcam}, |
| 1515 | {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista}, | 1515 | {USB_DEVICE(0x041e, 0x4018), .driver_info = CreativeVista}, |
| 1516 | {USB_DEVICE(0x0461, 0x0815), .driver_info = MicroInnovationIC200}, | ||
| 1517 | {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110}, | 1516 | {USB_DEVICE(0x0733, 0x0110), .driver_info = ViewQuestVQ110}, |
| 1518 | {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam}, | 1517 | {USB_DEVICE(0x0af9, 0x0010), .driver_info = HamaUSBSightcam}, |
| 1519 | {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2}, | 1518 | {USB_DEVICE(0x0af9, 0x0011), .driver_info = HamaUSBSightcam2}, |
diff --git a/drivers/media/video/gspca/spca561.c b/drivers/media/video/gspca/spca561.c index dc7f2b0fbc79..b9c80e2103b9 100644 --- a/drivers/media/video/gspca/spca561.c +++ b/drivers/media/video/gspca/spca561.c | |||
| @@ -1053,6 +1053,7 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
| 1053 | {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A}, | 1053 | {USB_DEVICE(0x041e, 0x401a), .driver_info = Rev072A}, |
| 1054 | {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A}, | 1054 | {USB_DEVICE(0x041e, 0x403b), .driver_info = Rev012A}, |
| 1055 | {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A}, | 1055 | {USB_DEVICE(0x0458, 0x7004), .driver_info = Rev072A}, |
| 1056 | {USB_DEVICE(0x0461, 0x0815), .driver_info = Rev072A}, | ||
| 1056 | {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A}, | 1057 | {USB_DEVICE(0x046d, 0x0928), .driver_info = Rev012A}, |
| 1057 | {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A}, | 1058 | {USB_DEVICE(0x046d, 0x0929), .driver_info = Rev012A}, |
| 1058 | {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A}, | 1059 | {USB_DEVICE(0x046d, 0x092a), .driver_info = Rev012A}, |
diff --git a/drivers/media/video/gspca/stv06xx/stv06xx.c b/drivers/media/video/gspca/stv06xx/stv06xx.c index af73da34c83f..14f179a19485 100644 --- a/drivers/media/video/gspca/stv06xx/stv06xx.c +++ b/drivers/media/video/gspca/stv06xx/stv06xx.c | |||
| @@ -524,8 +524,6 @@ static const __devinitdata struct usb_device_id device_table[] = { | |||
| 524 | {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 }, | 524 | {USB_DEVICE(0x046D, 0x08F5), .driver_info = BRIDGE_ST6422 }, |
| 525 | /* QuickCam Messenger (new) */ | 525 | /* QuickCam Messenger (new) */ |
| 526 | {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, | 526 | {USB_DEVICE(0x046D, 0x08F6), .driver_info = BRIDGE_ST6422 }, |
| 527 | /* QuickCam Messenger (new) */ | ||
| 528 | {USB_DEVICE(0x046D, 0x08DA), .driver_info = BRIDGE_ST6422 }, | ||
| 529 | {} | 527 | {} |
| 530 | }; | 528 | }; |
| 531 | MODULE_DEVICE_TABLE(usb, device_table); | 529 | MODULE_DEVICE_TABLE(usb, device_table); |
diff --git a/drivers/media/video/hexium_gemini.c b/drivers/media/video/hexium_gemini.c index e620a3a92f25..ad2c232baa6d 100644 --- a/drivers/media/video/hexium_gemini.c +++ b/drivers/media/video/hexium_gemini.c | |||
| @@ -356,9 +356,6 @@ static int hexium_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_d | |||
| 356 | 356 | ||
| 357 | DEB_EE((".\n")); | 357 | DEB_EE((".\n")); |
| 358 | 358 | ||
| 359 | ret = saa7146_vv_devinit(dev); | ||
| 360 | if (ret) | ||
| 361 | return ret; | ||
| 362 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); | 359 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); |
| 363 | if (NULL == hexium) { | 360 | if (NULL == hexium) { |
| 364 | printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); | 361 | printk("hexium_gemini: not enough kernel memory in hexium_attach().\n"); |
diff --git a/drivers/media/video/hexium_orion.c b/drivers/media/video/hexium_orion.c index fe596a1c12a8..938a1f8f880a 100644 --- a/drivers/media/video/hexium_orion.c +++ b/drivers/media/video/hexium_orion.c | |||
| @@ -216,10 +216,6 @@ static int hexium_probe(struct saa7146_dev *dev) | |||
| 216 | return -EFAULT; | 216 | return -EFAULT; |
| 217 | } | 217 | } |
| 218 | 218 | ||
| 219 | err = saa7146_vv_devinit(dev); | ||
| 220 | if (err) | ||
| 221 | return err; | ||
| 222 | |||
| 223 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); | 219 | hexium = kzalloc(sizeof(struct hexium), GFP_KERNEL); |
| 224 | if (NULL == hexium) { | 220 | if (NULL == hexium) { |
| 225 | printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); | 221 | printk("hexium_orion: hexium_probe: not enough kernel memory.\n"); |
diff --git a/drivers/media/video/mx1_camera.c b/drivers/media/video/mx1_camera.c index 3c8ebfcb742e..34a66019190e 100644 --- a/drivers/media/video/mx1_camera.c +++ b/drivers/media/video/mx1_camera.c | |||
| @@ -49,8 +49,6 @@ | |||
| 49 | /* | 49 | /* |
| 50 | * CSI registers | 50 | * CSI registers |
| 51 | */ | 51 | */ |
| 52 | #define DMA_CCR(x) (0x8c + ((x) << 6)) /* Control Registers */ | ||
| 53 | #define DMA_DIMR 0x08 /* Interrupt mask Register */ | ||
| 54 | #define CSICR1 0x00 /* CSI Control Register 1 */ | 52 | #define CSICR1 0x00 /* CSI Control Register 1 */ |
| 55 | #define CSISR 0x08 /* CSI Status Register */ | 53 | #define CSISR 0x08 /* CSI Status Register */ |
| 56 | #define CSIRXR 0x10 /* CSI RxFIFO Register */ | 54 | #define CSIRXR 0x10 /* CSI RxFIFO Register */ |
| @@ -784,7 +782,7 @@ static int __init mx1_camera_probe(struct platform_device *pdev) | |||
| 784 | pcdev); | 782 | pcdev); |
| 785 | 783 | ||
| 786 | imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO, | 784 | imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO, |
| 787 | IMX_DMA_MEMSIZE_32, DMA_REQ_CSI_R, 0); | 785 | IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0); |
| 788 | /* burst length : 16 words = 64 bytes */ | 786 | /* burst length : 16 words = 64 bytes */ |
| 789 | imx_dma_config_burstlen(pcdev->dma_chan, 0); | 787 | imx_dma_config_burstlen(pcdev->dma_chan, 0); |
| 790 | 788 | ||
| @@ -798,8 +796,8 @@ static int __init mx1_camera_probe(struct platform_device *pdev) | |||
| 798 | set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end - | 796 | set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end - |
| 799 | &mx1_camera_sof_fiq_start); | 797 | &mx1_camera_sof_fiq_start); |
| 800 | 798 | ||
| 801 | regs.ARM_r8 = DMA_BASE + DMA_DIMR; | 799 | regs.ARM_r8 = (long)MX1_DMA_DIMR; |
| 802 | regs.ARM_r9 = DMA_BASE + DMA_CCR(pcdev->dma_chan); | 800 | regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan); |
| 803 | regs.ARM_r10 = (long)pcdev->base + CSICR1; | 801 | regs.ARM_r10 = (long)pcdev->base + CSICR1; |
| 804 | regs.ARM_fp = (long)pcdev->base + CSISR; | 802 | regs.ARM_fp = (long)pcdev->base + CSISR; |
| 805 | regs.ARM_sp = 1 << pcdev->dma_chan; | 803 | regs.ARM_sp = 1 << pcdev->dma_chan; |
diff --git a/drivers/media/video/mxb.c b/drivers/media/video/mxb.c index 9f01f14e4aa2..ef0c8178f255 100644 --- a/drivers/media/video/mxb.c +++ b/drivers/media/video/mxb.c | |||
| @@ -169,11 +169,7 @@ static struct saa7146_extension extension; | |||
| 169 | static int mxb_probe(struct saa7146_dev *dev) | 169 | static int mxb_probe(struct saa7146_dev *dev) |
| 170 | { | 170 | { |
| 171 | struct mxb *mxb = NULL; | 171 | struct mxb *mxb = NULL; |
| 172 | int err; | ||
| 173 | 172 | ||
| 174 | err = saa7146_vv_devinit(dev); | ||
| 175 | if (err) | ||
| 176 | return err; | ||
| 177 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); | 173 | mxb = kzalloc(sizeof(struct mxb), GFP_KERNEL); |
| 178 | if (mxb == NULL) { | 174 | if (mxb == NULL) { |
| 179 | DEB_D(("not enough kernel memory.\n")); | 175 | DEB_D(("not enough kernel memory.\n")); |
| @@ -699,14 +695,17 @@ static struct saa7146_ext_vv vv_data; | |||
| 699 | /* this function only gets called when the probing was successful */ | 695 | /* this function only gets called when the probing was successful */ |
| 700 | static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) | 696 | static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data *info) |
| 701 | { | 697 | { |
| 702 | struct mxb *mxb = (struct mxb *)dev->ext_priv; | 698 | struct mxb *mxb; |
| 703 | 699 | ||
| 704 | DEB_EE(("dev:%p\n", dev)); | 700 | DEB_EE(("dev:%p\n", dev)); |
| 705 | 701 | ||
| 706 | /* checking for i2c-devices can be omitted here, because we | ||
| 707 | already did this in "mxb_vl42_probe" */ | ||
| 708 | |||
| 709 | saa7146_vv_init(dev, &vv_data); | 702 | saa7146_vv_init(dev, &vv_data); |
| 703 | if (mxb_probe(dev)) { | ||
| 704 | saa7146_vv_release(dev); | ||
| 705 | return -1; | ||
| 706 | } | ||
| 707 | mxb = (struct mxb *)dev->ext_priv; | ||
| 708 | |||
| 710 | vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; | 709 | vv_data.ops.vidioc_queryctrl = vidioc_queryctrl; |
| 711 | vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; | 710 | vv_data.ops.vidioc_g_ctrl = vidioc_g_ctrl; |
| 712 | vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; | 711 | vv_data.ops.vidioc_s_ctrl = vidioc_s_ctrl; |
| @@ -726,6 +725,7 @@ static int mxb_attach(struct saa7146_dev *dev, struct saa7146_pci_extension_data | |||
| 726 | vv_data.ops.vidioc_default = vidioc_default; | 725 | vv_data.ops.vidioc_default = vidioc_default; |
| 727 | if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { | 726 | if (saa7146_register_device(&mxb->video_dev, dev, "mxb", VFL_TYPE_GRABBER)) { |
| 728 | ERR(("cannot register capture v4l2 device. skipping.\n")); | 727 | ERR(("cannot register capture v4l2 device. skipping.\n")); |
| 728 | saa7146_vv_release(dev); | ||
| 729 | return -1; | 729 | return -1; |
| 730 | } | 730 | } |
| 731 | 731 | ||
| @@ -846,7 +846,6 @@ static struct saa7146_extension extension = { | |||
| 846 | .pci_tbl = &pci_tbl[0], | 846 | .pci_tbl = &pci_tbl[0], |
| 847 | .module = THIS_MODULE, | 847 | .module = THIS_MODULE, |
| 848 | 848 | ||
| 849 | .probe = mxb_probe, | ||
| 850 | .attach = mxb_attach, | 849 | .attach = mxb_attach, |
| 851 | .detach = mxb_detach, | 850 | .detach = mxb_detach, |
| 852 | 851 | ||
diff --git a/drivers/media/video/omap24xxcam.c b/drivers/media/video/omap24xxcam.c index b189fe63394b..ce76d952e161 100644 --- a/drivers/media/video/omap24xxcam.c +++ b/drivers/media/video/omap24xxcam.c | |||
| @@ -1405,7 +1405,7 @@ static int omap24xxcam_mmap_buffers(struct file *file, | |||
| 1405 | } | 1405 | } |
| 1406 | 1406 | ||
| 1407 | size = 0; | 1407 | size = 0; |
| 1408 | for (i = first; i <= last; i++) { | 1408 | for (i = first; i <= last && i < VIDEO_MAX_FRAME; i++) { |
| 1409 | struct videobuf_dmabuf *dma = videobuf_to_dma(vbq->bufs[i]); | 1409 | struct videobuf_dmabuf *dma = videobuf_to_dma(vbq->bufs[i]); |
| 1410 | 1410 | ||
| 1411 | for (j = 0; j < dma->sglen; j++) { | 1411 | for (j = 0; j < dma->sglen; j++) { |
diff --git a/drivers/media/video/pxa_camera.c b/drivers/media/video/pxa_camera.c index 5ecc30daef2d..04bf5c11308d 100644 --- a/drivers/media/video/pxa_camera.c +++ b/drivers/media/video/pxa_camera.c | |||
| @@ -609,12 +609,9 @@ static void pxa_dma_add_tail_buf(struct pxa_camera_dev *pcdev, | |||
| 609 | */ | 609 | */ |
| 610 | static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) | 610 | static void pxa_camera_start_capture(struct pxa_camera_dev *pcdev) |
| 611 | { | 611 | { |
| 612 | unsigned long cicr0, cifr; | 612 | unsigned long cicr0; |
| 613 | 613 | ||
| 614 | dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); | 614 | dev_dbg(pcdev->soc_host.v4l2_dev.dev, "%s\n", __func__); |
| 615 | /* Reset the FIFOs */ | ||
| 616 | cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; | ||
| 617 | __raw_writel(cifr, pcdev->base + CIFR); | ||
| 618 | /* Enable End-Of-Frame Interrupt */ | 615 | /* Enable End-Of-Frame Interrupt */ |
| 619 | cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; | 616 | cicr0 = __raw_readl(pcdev->base + CICR0) | CICR0_ENB; |
| 620 | cicr0 &= ~CICR0_EOFM; | 617 | cicr0 &= ~CICR0_EOFM; |
| @@ -935,7 +932,7 @@ static void pxa_camera_deactivate(struct pxa_camera_dev *pcdev) | |||
| 935 | static irqreturn_t pxa_camera_irq(int irq, void *data) | 932 | static irqreturn_t pxa_camera_irq(int irq, void *data) |
| 936 | { | 933 | { |
| 937 | struct pxa_camera_dev *pcdev = data; | 934 | struct pxa_camera_dev *pcdev = data; |
| 938 | unsigned long status, cicr0; | 935 | unsigned long status, cifr, cicr0; |
| 939 | struct pxa_buffer *buf; | 936 | struct pxa_buffer *buf; |
| 940 | struct videobuf_buffer *vb; | 937 | struct videobuf_buffer *vb; |
| 941 | 938 | ||
| @@ -949,6 +946,10 @@ static irqreturn_t pxa_camera_irq(int irq, void *data) | |||
| 949 | __raw_writel(status, pcdev->base + CISR); | 946 | __raw_writel(status, pcdev->base + CISR); |
| 950 | 947 | ||
| 951 | if (status & CISR_EOF) { | 948 | if (status & CISR_EOF) { |
| 949 | /* Reset the FIFOs */ | ||
| 950 | cifr = __raw_readl(pcdev->base + CIFR) | CIFR_RESET_F; | ||
| 951 | __raw_writel(cifr, pcdev->base + CIFR); | ||
| 952 | |||
| 952 | pcdev->active = list_first_entry(&pcdev->capture, | 953 | pcdev->active = list_first_entry(&pcdev->capture, |
| 953 | struct pxa_buffer, vb.queue); | 954 | struct pxa_buffer, vb.queue); |
| 954 | vb = &pcdev->active->vb; | 955 | vb = &pcdev->active->vb; |
diff --git a/drivers/media/video/sh_mobile_ceu_camera.c b/drivers/media/video/sh_mobile_ceu_camera.c index 6e16b3979326..1ad980f8e770 100644 --- a/drivers/media/video/sh_mobile_ceu_camera.c +++ b/drivers/media/video/sh_mobile_ceu_camera.c | |||
| @@ -1633,7 +1633,7 @@ static int sh_mobile_ceu_try_fmt(struct soc_camera_device *icd, | |||
| 1633 | height = pix->height; | 1633 | height = pix->height; |
| 1634 | 1634 | ||
| 1635 | pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt); | 1635 | pix->bytesperline = soc_mbus_bytes_per_line(width, xlate->host_fmt); |
| 1636 | if (pix->bytesperline < 0) | 1636 | if ((int)pix->bytesperline < 0) |
| 1637 | return pix->bytesperline; | 1637 | return pix->bytesperline; |
| 1638 | pix->sizeimage = height * pix->bytesperline; | 1638 | pix->sizeimage = height * pix->bytesperline; |
| 1639 | 1639 | ||
diff --git a/drivers/mfd/wm831x-core.c b/drivers/mfd/wm831x-core.c index a3d5728b6449..f2ab025ad97a 100644 --- a/drivers/mfd/wm831x-core.c +++ b/drivers/mfd/wm831x-core.c | |||
| @@ -349,6 +349,9 @@ int wm831x_auxadc_read(struct wm831x *wm831x, enum wm831x_auxadc input) | |||
| 349 | goto disable; | 349 | goto disable; |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | /* If an interrupt arrived late clean up after it */ | ||
| 353 | try_wait_for_completion(&wm831x->auxadc_done); | ||
| 354 | |||
| 352 | /* Ignore the result to allow us to soldier on without IRQ hookup */ | 355 | /* Ignore the result to allow us to soldier on without IRQ hookup */ |
| 353 | wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); | 356 | wait_for_completion_timeout(&wm831x->auxadc_done, msecs_to_jiffies(5)); |
| 354 | 357 | ||
diff --git a/drivers/mfd/wm8350-core.c b/drivers/mfd/wm8350-core.c index e400a3bed063..b5807484b4c9 100644 --- a/drivers/mfd/wm8350-core.c +++ b/drivers/mfd/wm8350-core.c | |||
| @@ -363,6 +363,10 @@ int wm8350_read_auxadc(struct wm8350 *wm8350, int channel, int scale, int vref) | |||
| 363 | reg |= 1 << channel | WM8350_AUXADC_POLL; | 363 | reg |= 1 << channel | WM8350_AUXADC_POLL; |
| 364 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); | 364 | wm8350_reg_write(wm8350, WM8350_DIGITISER_CONTROL_1, reg); |
| 365 | 365 | ||
| 366 | /* If a late IRQ left the completion signalled then consume | ||
| 367 | * the completion. */ | ||
| 368 | try_wait_for_completion(&wm8350->auxadc_done); | ||
| 369 | |||
| 366 | /* We ignore the result of the completion and just check for a | 370 | /* We ignore the result of the completion and just check for a |
| 367 | * conversion result, allowing us to soldier on if the IRQ | 371 | * conversion result, allowing us to soldier on if the IRQ |
| 368 | * infrastructure is not set up for the chip. */ | 372 | * infrastructure is not set up for the chip. */ |
diff --git a/drivers/misc/vmware_balloon.c b/drivers/misc/vmware_balloon.c index e7161c4e3798..db9cd0240c6f 100644 --- a/drivers/misc/vmware_balloon.c +++ b/drivers/misc/vmware_balloon.c | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | #include <linux/workqueue.h> | 41 | #include <linux/workqueue.h> |
| 42 | #include <linux/debugfs.h> | 42 | #include <linux/debugfs.h> |
| 43 | #include <linux/seq_file.h> | 43 | #include <linux/seq_file.h> |
| 44 | #include <asm/vmware.h> | 44 | #include <asm/hypervisor.h> |
| 45 | 45 | ||
| 46 | MODULE_AUTHOR("VMware, Inc."); | 46 | MODULE_AUTHOR("VMware, Inc."); |
| 47 | MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver"); | 47 | MODULE_DESCRIPTION("VMware Memory Control (Balloon) Driver"); |
| @@ -767,7 +767,7 @@ static int __init vmballoon_init(void) | |||
| 767 | * Check if we are running on VMware's hypervisor and bail out | 767 | * Check if we are running on VMware's hypervisor and bail out |
| 768 | * if we are not. | 768 | * if we are not. |
| 769 | */ | 769 | */ |
| 770 | if (!vmware_platform()) | 770 | if (x86_hyper != &x86_hyper_vmware) |
| 771 | return -ENODEV; | 771 | return -ENODEV; |
| 772 | 772 | ||
| 773 | vmballoon_wq = create_freezeable_workqueue("vmmemctl"); | 773 | vmballoon_wq = create_freezeable_workqueue("vmmemctl"); |
diff --git a/drivers/mmc/host/at91_mci.c b/drivers/mmc/host/at91_mci.c index a6dd7da37357..336d9f553f3e 100644 --- a/drivers/mmc/host/at91_mci.c +++ b/drivers/mmc/host/at91_mci.c | |||
| @@ -314,8 +314,8 @@ static void at91_mci_post_dma_read(struct at91mci_host *host) | |||
| 314 | dmabuf = (unsigned *)tmpv; | 314 | dmabuf = (unsigned *)tmpv; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | flush_kernel_dcache_page(sg_page(sg)); | ||
| 317 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); | 318 | kunmap_atomic(sgbuffer, KM_BIO_SRC_IRQ); |
| 318 | dmac_flush_range((void *)sgbuffer, ((void *)sgbuffer) + amount); | ||
| 319 | data->bytes_xfered += amount; | 319 | data->bytes_xfered += amount; |
| 320 | if (size == 0) | 320 | if (size == 0) |
| 321 | break; | 321 | break; |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 88be37d9e9a5..fb279f4ed8b3 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
| @@ -266,7 +266,7 @@ static int atmci_req_show(struct seq_file *s, void *v) | |||
| 266 | "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", | 266 | "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", |
| 267 | cmd->opcode, cmd->arg, cmd->flags, | 267 | cmd->opcode, cmd->arg, cmd->flags, |
| 268 | cmd->resp[0], cmd->resp[1], cmd->resp[2], | 268 | cmd->resp[0], cmd->resp[1], cmd->resp[2], |
| 269 | cmd->resp[2], cmd->error); | 269 | cmd->resp[3], cmd->error); |
| 270 | if (data) | 270 | if (data) |
| 271 | seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", | 271 | seq_printf(s, "DATA %u / %u * %u flg %x err %d\n", |
| 272 | data->bytes_xfered, data->blocks, | 272 | data->bytes_xfered, data->blocks, |
| @@ -276,7 +276,7 @@ static int atmci_req_show(struct seq_file *s, void *v) | |||
| 276 | "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", | 276 | "CMD%u(0x%x) flg %x rsp %x %x %x %x err %d\n", |
| 277 | stop->opcode, stop->arg, stop->flags, | 277 | stop->opcode, stop->arg, stop->flags, |
| 278 | stop->resp[0], stop->resp[1], stop->resp[2], | 278 | stop->resp[0], stop->resp[1], stop->resp[2], |
| 279 | stop->resp[2], stop->error); | 279 | stop->resp[3], stop->error); |
| 280 | } | 280 | } |
| 281 | 281 | ||
| 282 | spin_unlock_bh(&slot->host->lock); | 282 | spin_unlock_bh(&slot->host->lock); |
| @@ -569,9 +569,10 @@ static void atmci_dma_cleanup(struct atmel_mci *host) | |||
| 569 | { | 569 | { |
| 570 | struct mmc_data *data = host->data; | 570 | struct mmc_data *data = host->data; |
| 571 | 571 | ||
| 572 | dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, | 572 | if (data) |
| 573 | ((data->flags & MMC_DATA_WRITE) | 573 | dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, |
| 574 | ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); | 574 | ((data->flags & MMC_DATA_WRITE) |
| 575 | ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); | ||
| 575 | } | 576 | } |
| 576 | 577 | ||
| 577 | static void atmci_stop_dma(struct atmel_mci *host) | 578 | static void atmci_stop_dma(struct atmel_mci *host) |
| @@ -1099,8 +1100,8 @@ static void atmci_command_complete(struct atmel_mci *host, | |||
| 1099 | "command error: status=0x%08x\n", status); | 1100 | "command error: status=0x%08x\n", status); |
| 1100 | 1101 | ||
| 1101 | if (cmd->data) { | 1102 | if (cmd->data) { |
| 1102 | host->data = NULL; | ||
| 1103 | atmci_stop_dma(host); | 1103 | atmci_stop_dma(host); |
| 1104 | host->data = NULL; | ||
| 1104 | mci_writel(host, IDR, MCI_NOTBUSY | 1105 | mci_writel(host, IDR, MCI_NOTBUSY |
| 1105 | | MCI_TXRDY | MCI_RXRDY | 1106 | | MCI_TXRDY | MCI_RXRDY |
| 1106 | | ATMCI_DATA_ERROR_FLAGS); | 1107 | | ATMCI_DATA_ERROR_FLAGS); |
| @@ -1293,6 +1294,7 @@ static void atmci_tasklet_func(unsigned long priv) | |||
| 1293 | } else { | 1294 | } else { |
| 1294 | data->bytes_xfered = data->blocks * data->blksz; | 1295 | data->bytes_xfered = data->blocks * data->blksz; |
| 1295 | data->error = 0; | 1296 | data->error = 0; |
| 1297 | mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS); | ||
| 1296 | } | 1298 | } |
| 1297 | 1299 | ||
| 1298 | if (!data->stop) { | 1300 | if (!data->stop) { |
| @@ -1751,13 +1753,13 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
| 1751 | ret = -ENODEV; | 1753 | ret = -ENODEV; |
| 1752 | if (pdata->slot[0].bus_width) { | 1754 | if (pdata->slot[0].bus_width) { |
| 1753 | ret = atmci_init_slot(host, &pdata->slot[0], | 1755 | ret = atmci_init_slot(host, &pdata->slot[0], |
| 1754 | MCI_SDCSEL_SLOT_A, 0); | 1756 | 0, MCI_SDCSEL_SLOT_A); |
| 1755 | if (!ret) | 1757 | if (!ret) |
| 1756 | nr_slots++; | 1758 | nr_slots++; |
| 1757 | } | 1759 | } |
| 1758 | if (pdata->slot[1].bus_width) { | 1760 | if (pdata->slot[1].bus_width) { |
| 1759 | ret = atmci_init_slot(host, &pdata->slot[1], | 1761 | ret = atmci_init_slot(host, &pdata->slot[1], |
| 1760 | MCI_SDCSEL_SLOT_B, 1); | 1762 | 1, MCI_SDCSEL_SLOT_B); |
| 1761 | if (!ret) | 1763 | if (!ret) |
| 1762 | nr_slots++; | 1764 | nr_slots++; |
| 1763 | } | 1765 | } |
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c index 84c103a7ee13..ff115d920888 100644 --- a/drivers/mmc/host/mmci.c +++ b/drivers/mmc/host/mmci.c | |||
| @@ -55,14 +55,16 @@ static void mmci_set_clkreg(struct mmci_host *host, unsigned int desired) | |||
| 55 | host->cclk = host->mclk / (2 * (clk + 1)); | 55 | host->cclk = host->mclk / (2 * (clk + 1)); |
| 56 | } | 56 | } |
| 57 | if (host->hw_designer == AMBA_VENDOR_ST) | 57 | if (host->hw_designer == AMBA_VENDOR_ST) |
| 58 | clk |= MCI_FCEN; /* Bug fix in ST IP block */ | 58 | clk |= MCI_ST_FCEN; /* Bug fix in ST IP block */ |
| 59 | clk |= MCI_CLK_ENABLE; | 59 | clk |= MCI_CLK_ENABLE; |
| 60 | /* This hasn't proven to be worthwhile */ | 60 | /* This hasn't proven to be worthwhile */ |
| 61 | /* clk |= MCI_CLK_PWRSAVE; */ | 61 | /* clk |= MCI_CLK_PWRSAVE; */ |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) | 64 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) |
| 65 | clk |= MCI_WIDE_BUS; | 65 | clk |= MCI_4BIT_BUS; |
| 66 | if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_8) | ||
| 67 | clk |= MCI_ST_8BIT_BUS; | ||
| 66 | 68 | ||
| 67 | writel(clk, host->base + MMCICLOCK); | 69 | writel(clk, host->base + MMCICLOCK); |
| 68 | } | 70 | } |
| @@ -629,7 +631,18 @@ static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id) | |||
| 629 | 631 | ||
| 630 | mmc->ops = &mmci_ops; | 632 | mmc->ops = &mmci_ops; |
| 631 | mmc->f_min = (host->mclk + 511) / 512; | 633 | mmc->f_min = (host->mclk + 511) / 512; |
| 632 | mmc->f_max = min(host->mclk, fmax); | 634 | /* |
| 635 | * If the platform data supplies a maximum operating | ||
| 636 | * frequency, this takes precedence. Else, we fall back | ||
| 637 | * to using the module parameter, which has a (low) | ||
| 638 | * default value in case it is not specified. Either | ||
| 639 | * value must not exceed the clock rate into the block, | ||
| 640 | * of course. | ||
| 641 | */ | ||
| 642 | if (plat->f_max) | ||
| 643 | mmc->f_max = min(host->mclk, plat->f_max); | ||
| 644 | else | ||
| 645 | mmc->f_max = min(host->mclk, fmax); | ||
| 633 | dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); | 646 | dev_dbg(mmc_dev(mmc), "clocking block at %u Hz\n", mmc->f_max); |
| 634 | 647 | ||
| 635 | #ifdef CONFIG_REGULATOR | 648 | #ifdef CONFIG_REGULATOR |
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h index 1ceb9a90f59b..d77062e5e3af 100644 --- a/drivers/mmc/host/mmci.h +++ b/drivers/mmc/host/mmci.h | |||
| @@ -25,9 +25,11 @@ | |||
| 25 | #define MCI_CLK_ENABLE (1 << 8) | 25 | #define MCI_CLK_ENABLE (1 << 8) |
| 26 | #define MCI_CLK_PWRSAVE (1 << 9) | 26 | #define MCI_CLK_PWRSAVE (1 << 9) |
| 27 | #define MCI_CLK_BYPASS (1 << 10) | 27 | #define MCI_CLK_BYPASS (1 << 10) |
| 28 | #define MCI_WIDE_BUS (1 << 11) | 28 | #define MCI_4BIT_BUS (1 << 11) |
| 29 | /* 8bit wide buses supported in ST Micro versions */ | ||
| 30 | #define MCI_ST_8BIT_BUS (1 << 12) | ||
| 29 | /* HW flow control on the ST Micro version */ | 31 | /* HW flow control on the ST Micro version */ |
| 30 | #define MCI_FCEN (1 << 13) | 32 | #define MCI_ST_FCEN (1 << 13) |
| 31 | 33 | ||
| 32 | #define MMCIARGUMENT 0x008 | 34 | #define MMCIARGUMENT 0x008 |
| 33 | #define MMCICOMMAND 0x00c | 35 | #define MMCICOMMAND 0x00c |
diff --git a/drivers/mmc/host/pxamci.c b/drivers/mmc/host/pxamci.c index 0ed48959b590..e4f00e70a749 100644 --- a/drivers/mmc/host/pxamci.c +++ b/drivers/mmc/host/pxamci.c | |||
| @@ -544,7 +544,7 @@ static irqreturn_t pxamci_detect_irq(int irq, void *devid) | |||
| 544 | { | 544 | { |
| 545 | struct pxamci_host *host = mmc_priv(devid); | 545 | struct pxamci_host *host = mmc_priv(devid); |
| 546 | 546 | ||
| 547 | mmc_detect_change(devid, host->pdata->detect_delay); | 547 | mmc_detect_change(devid, msecs_to_jiffies(host->pdata->detect_delay_ms)); |
| 548 | return IRQ_HANDLED; | 548 | return IRQ_HANDLED; |
| 549 | } | 549 | } |
| 550 | 550 | ||
diff --git a/drivers/mtd/internal.h b/drivers/mtd/internal.h deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/drivers/mtd/internal.h +++ /dev/null | |||
diff --git a/drivers/mtd/mtdbdi.c b/drivers/mtd/mtdbdi.c deleted file mode 100644 index e69de29bb2d1..000000000000 --- a/drivers/mtd/mtdbdi.c +++ /dev/null | |||
diff --git a/drivers/net/a2065.c b/drivers/net/a2065.c index ed5e9742be2c..a8f0512bad38 100644 --- a/drivers/net/a2065.c +++ b/drivers/net/a2065.c | |||
| @@ -674,6 +674,7 @@ static struct zorro_device_id a2065_zorro_tbl[] __devinitdata = { | |||
| 674 | { ZORRO_PROD_AMERISTAR_A2065 }, | 674 | { ZORRO_PROD_AMERISTAR_A2065 }, |
| 675 | { 0 } | 675 | { 0 } |
| 676 | }; | 676 | }; |
| 677 | MODULE_DEVICE_TABLE(zorro, a2065_zorro_tbl); | ||
| 677 | 678 | ||
| 678 | static struct zorro_driver a2065_driver = { | 679 | static struct zorro_driver a2065_driver = { |
| 679 | .name = "a2065", | 680 | .name = "a2065", |
diff --git a/drivers/net/ariadne.c b/drivers/net/ariadne.c index fa1a2354f5f9..4b30a46486e2 100644 --- a/drivers/net/ariadne.c +++ b/drivers/net/ariadne.c | |||
| @@ -145,6 +145,7 @@ static struct zorro_device_id ariadne_zorro_tbl[] __devinitdata = { | |||
| 145 | { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, | 145 | { ZORRO_PROD_VILLAGE_TRONIC_ARIADNE }, |
| 146 | { 0 } | 146 | { 0 } |
| 147 | }; | 147 | }; |
| 148 | MODULE_DEVICE_TABLE(zorro, ariadne_zorro_tbl); | ||
| 148 | 149 | ||
| 149 | static struct zorro_driver ariadne_driver = { | 150 | static struct zorro_driver ariadne_driver = { |
| 150 | .name = "ariadne", | 151 | .name = "ariadne", |
diff --git a/drivers/net/arm/ep93xx_eth.c b/drivers/net/arm/ep93xx_eth.c index 6995169d285a..cd17d09f385c 100644 --- a/drivers/net/arm/ep93xx_eth.c +++ b/drivers/net/arm/ep93xx_eth.c | |||
| @@ -311,11 +311,6 @@ err: | |||
| 311 | processed++; | 311 | processed++; |
| 312 | } | 312 | } |
| 313 | 313 | ||
| 314 | if (processed) { | ||
| 315 | wrw(ep, REG_RXDENQ, processed); | ||
| 316 | wrw(ep, REG_RXSTSENQ, processed); | ||
| 317 | } | ||
| 318 | |||
| 319 | return processed; | 314 | return processed; |
| 320 | } | 315 | } |
| 321 | 316 | ||
| @@ -350,6 +345,11 @@ poll_some_more: | |||
| 350 | goto poll_some_more; | 345 | goto poll_some_more; |
| 351 | } | 346 | } |
| 352 | 347 | ||
| 348 | if (rx) { | ||
| 349 | wrw(ep, REG_RXDENQ, rx); | ||
| 350 | wrw(ep, REG_RXSTSENQ, rx); | ||
| 351 | } | ||
| 352 | |||
| 353 | return rx; | 353 | return rx; |
| 354 | } | 354 | } |
| 355 | 355 | ||
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index fb8fc7d1b50d..dbf81788bb40 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
| @@ -4633,6 +4633,9 @@ static void __e1000e_disable_aspm(struct pci_dev *pdev, u16 state) | |||
| 4633 | reg16 &= ~state; | 4633 | reg16 &= ~state; |
| 4634 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); | 4634 | pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16); |
| 4635 | 4635 | ||
| 4636 | if (!pdev->bus->self) | ||
| 4637 | return; | ||
| 4638 | |||
| 4636 | pos = pci_pcie_cap(pdev->bus->self); | 4639 | pos = pci_pcie_cap(pdev->bus->self); |
| 4637 | pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); | 4640 | pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, ®16); |
| 4638 | reg16 &= ~state; | 4641 | reg16 &= ~state; |
diff --git a/drivers/net/fec.c b/drivers/net/fec.c index 9f98c1c4a344..9b4e8f797a7a 100644 --- a/drivers/net/fec.c +++ b/drivers/net/fec.c | |||
| @@ -1653,7 +1653,7 @@ fec_set_mac_address(struct net_device *dev, void *p) | |||
| 1653 | (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), | 1653 | (dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24), |
| 1654 | fep->hwp + FEC_ADDR_LOW); | 1654 | fep->hwp + FEC_ADDR_LOW); |
| 1655 | writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), | 1655 | writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24), |
| 1656 | fep + FEC_ADDR_HIGH); | 1656 | fep->hwp + FEC_ADDR_HIGH); |
| 1657 | return 0; | 1657 | return 0; |
| 1658 | } | 1658 | } |
| 1659 | 1659 | ||
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index 4e97ca182997..5d3763fb3472 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
| @@ -1649,6 +1649,7 @@ static void free_skb_resources(struct gfar_private *priv) | |||
| 1649 | sizeof(struct rxbd8) * priv->total_rx_ring_size, | 1649 | sizeof(struct rxbd8) * priv->total_rx_ring_size, |
| 1650 | priv->tx_queue[0]->tx_bd_base, | 1650 | priv->tx_queue[0]->tx_bd_base, |
| 1651 | priv->tx_queue[0]->tx_bd_dma_base); | 1651 | priv->tx_queue[0]->tx_bd_dma_base); |
| 1652 | skb_queue_purge(&priv->rx_recycle); | ||
| 1652 | } | 1653 | } |
| 1653 | 1654 | ||
| 1654 | void gfar_start(struct net_device *dev) | 1655 | void gfar_start(struct net_device *dev) |
| @@ -2088,7 +2089,6 @@ static int gfar_close(struct net_device *dev) | |||
| 2088 | 2089 | ||
| 2089 | disable_napi(priv); | 2090 | disable_napi(priv); |
| 2090 | 2091 | ||
| 2091 | skb_queue_purge(&priv->rx_recycle); | ||
| 2092 | cancel_work_sync(&priv->reset_task); | 2092 | cancel_work_sync(&priv->reset_task); |
| 2093 | stop_gfar(dev); | 2093 | stop_gfar(dev); |
| 2094 | 2094 | ||
diff --git a/drivers/net/hydra.c b/drivers/net/hydra.c index 24724b4ad709..07d8e5b634f3 100644 --- a/drivers/net/hydra.c +++ b/drivers/net/hydra.c | |||
| @@ -71,6 +71,7 @@ static struct zorro_device_id hydra_zorro_tbl[] __devinitdata = { | |||
| 71 | { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, | 71 | { ZORRO_PROD_HYDRA_SYSTEMS_AMIGANET }, |
| 72 | { 0 } | 72 | { 0 } |
| 73 | }; | 73 | }; |
| 74 | MODULE_DEVICE_TABLE(zorro, hydra_zorro_tbl); | ||
| 74 | 75 | ||
| 75 | static struct zorro_driver hydra_driver = { | 76 | static struct zorro_driver hydra_driver = { |
| 76 | .name = "hydra", | 77 | .name = "hydra", |
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig index fc5938ba3d78..a527e37728cd 100644 --- a/drivers/net/phy/Kconfig +++ b/drivers/net/phy/Kconfig | |||
| @@ -88,6 +88,11 @@ config LSI_ET1011C_PHY | |||
| 88 | ---help--- | 88 | ---help--- |
| 89 | Supports the LSI ET1011C PHY. | 89 | Supports the LSI ET1011C PHY. |
| 90 | 90 | ||
| 91 | config MICREL_PHY | ||
| 92 | tristate "Driver for Micrel PHYs" | ||
| 93 | ---help--- | ||
| 94 | Supports the KSZ9021, VSC8201, KS8001 PHYs. | ||
| 95 | |||
| 91 | config FIXED_PHY | 96 | config FIXED_PHY |
| 92 | bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" | 97 | bool "Driver for MDIO Bus/PHY emulation with fixed speed/link PHYs" |
| 93 | depends on PHYLIB=y | 98 | depends on PHYLIB=y |
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile index 1342585af381..13bebab65d02 100644 --- a/drivers/net/phy/Makefile +++ b/drivers/net/phy/Makefile | |||
| @@ -20,4 +20,5 @@ obj-$(CONFIG_MDIO_BITBANG) += mdio-bitbang.o | |||
| 20 | obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o | 20 | obj-$(CONFIG_MDIO_GPIO) += mdio-gpio.o |
| 21 | obj-$(CONFIG_NATIONAL_PHY) += national.o | 21 | obj-$(CONFIG_NATIONAL_PHY) += national.o |
| 22 | obj-$(CONFIG_STE10XP) += ste10Xp.o | 22 | obj-$(CONFIG_STE10XP) += ste10Xp.o |
| 23 | obj-$(CONFIG_MICREL_PHY) += micrel.o | ||
| 23 | obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o | 24 | obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o |
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c new file mode 100644 index 000000000000..e67691dca4ab --- /dev/null +++ b/drivers/net/phy/micrel.c | |||
| @@ -0,0 +1,105 @@ | |||
| 1 | /* | ||
| 2 | * drivers/net/phy/micrel.c | ||
| 3 | * | ||
| 4 | * Driver for Micrel PHYs | ||
| 5 | * | ||
| 6 | * Author: David J. Choi | ||
| 7 | * | ||
| 8 | * Copyright (c) 2010 Micrel, Inc. | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify it | ||
| 11 | * under the terms of the GNU General Public License as published by the | ||
| 12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
| 13 | * option) any later version. | ||
| 14 | * | ||
| 15 | * Support : ksz9021 , vsc8201, ks8001 | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include <linux/kernel.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/phy.h> | ||
| 21 | |||
| 22 | #define PHY_ID_KSZ9021 0x00221611 | ||
| 23 | #define PHY_ID_VSC8201 0x000FC413 | ||
| 24 | #define PHY_ID_KS8001 0x0022161A | ||
| 25 | |||
| 26 | |||
| 27 | static int kszphy_config_init(struct phy_device *phydev) | ||
| 28 | { | ||
| 29 | return 0; | ||
| 30 | } | ||
| 31 | |||
| 32 | |||
| 33 | static struct phy_driver ks8001_driver = { | ||
| 34 | .phy_id = PHY_ID_KS8001, | ||
| 35 | .name = "Micrel KS8001", | ||
| 36 | .phy_id_mask = 0x00fffff0, | ||
| 37 | .features = PHY_BASIC_FEATURES, | ||
| 38 | .flags = PHY_POLL, | ||
| 39 | .config_init = kszphy_config_init, | ||
| 40 | .config_aneg = genphy_config_aneg, | ||
| 41 | .read_status = genphy_read_status, | ||
| 42 | .driver = { .owner = THIS_MODULE,}, | ||
| 43 | }; | ||
| 44 | |||
| 45 | static struct phy_driver vsc8201_driver = { | ||
| 46 | .phy_id = PHY_ID_VSC8201, | ||
| 47 | .name = "Micrel VSC8201", | ||
| 48 | .phy_id_mask = 0x00fffff0, | ||
| 49 | .features = PHY_BASIC_FEATURES, | ||
| 50 | .flags = PHY_POLL, | ||
| 51 | .config_init = kszphy_config_init, | ||
| 52 | .config_aneg = genphy_config_aneg, | ||
| 53 | .read_status = genphy_read_status, | ||
| 54 | .driver = { .owner = THIS_MODULE,}, | ||
| 55 | }; | ||
| 56 | |||
| 57 | static struct phy_driver ksz9021_driver = { | ||
| 58 | .phy_id = PHY_ID_KSZ9021, | ||
| 59 | .phy_id_mask = 0x000fff10, | ||
| 60 | .name = "Micrel KSZ9021 Gigabit PHY", | ||
| 61 | .features = PHY_GBIT_FEATURES | SUPPORTED_Pause, | ||
| 62 | .flags = PHY_POLL, | ||
| 63 | .config_init = kszphy_config_init, | ||
| 64 | .config_aneg = genphy_config_aneg, | ||
| 65 | .read_status = genphy_read_status, | ||
| 66 | .driver = { .owner = THIS_MODULE, }, | ||
| 67 | }; | ||
| 68 | |||
| 69 | static int __init ksphy_init(void) | ||
| 70 | { | ||
| 71 | int ret; | ||
| 72 | |||
| 73 | ret = phy_driver_register(&ks8001_driver); | ||
| 74 | if (ret) | ||
| 75 | goto err1; | ||
| 76 | ret = phy_driver_register(&vsc8201_driver); | ||
| 77 | if (ret) | ||
| 78 | goto err2; | ||
| 79 | |||
| 80 | ret = phy_driver_register(&ksz9021_driver); | ||
| 81 | if (ret) | ||
| 82 | goto err3; | ||
| 83 | return 0; | ||
| 84 | |||
| 85 | err3: | ||
| 86 | phy_driver_unregister(&vsc8201_driver); | ||
| 87 | err2: | ||
| 88 | phy_driver_unregister(&ks8001_driver); | ||
| 89 | err1: | ||
| 90 | return ret; | ||
| 91 | } | ||
| 92 | |||
| 93 | static void __exit ksphy_exit(void) | ||
| 94 | { | ||
| 95 | phy_driver_unregister(&ks8001_driver); | ||
| 96 | phy_driver_unregister(&vsc8201_driver); | ||
| 97 | phy_driver_unregister(&ksz9021_driver); | ||
| 98 | } | ||
| 99 | |||
| 100 | module_init(ksphy_init); | ||
| 101 | module_exit(ksphy_exit); | ||
| 102 | |||
| 103 | MODULE_DESCRIPTION("Micrel PHY driver"); | ||
| 104 | MODULE_AUTHOR("David J. Choi"); | ||
| 105 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/ppp_generic.c b/drivers/net/ppp_generic.c index 6e281bc825e5..8518a2e58e53 100644 --- a/drivers/net/ppp_generic.c +++ b/drivers/net/ppp_generic.c | |||
| @@ -405,6 +405,7 @@ static ssize_t ppp_read(struct file *file, char __user *buf, | |||
| 405 | DECLARE_WAITQUEUE(wait, current); | 405 | DECLARE_WAITQUEUE(wait, current); |
| 406 | ssize_t ret; | 406 | ssize_t ret; |
| 407 | struct sk_buff *skb = NULL; | 407 | struct sk_buff *skb = NULL; |
| 408 | struct iovec iov; | ||
| 408 | 409 | ||
| 409 | ret = count; | 410 | ret = count; |
| 410 | 411 | ||
| @@ -448,7 +449,9 @@ static ssize_t ppp_read(struct file *file, char __user *buf, | |||
| 448 | if (skb->len > count) | 449 | if (skb->len > count) |
| 449 | goto outf; | 450 | goto outf; |
| 450 | ret = -EFAULT; | 451 | ret = -EFAULT; |
| 451 | if (copy_to_user(buf, skb->data, skb->len)) | 452 | iov.iov_base = buf; |
| 453 | iov.iov_len = count; | ||
| 454 | if (skb_copy_datagram_iovec(skb, 0, &iov, skb->len)) | ||
| 452 | goto outf; | 455 | goto outf; |
| 453 | ret = skb->len; | 456 | ret = skb->len; |
| 454 | 457 | ||
| @@ -1567,13 +1570,22 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 1567 | struct channel *pch = chan->ppp; | 1570 | struct channel *pch = chan->ppp; |
| 1568 | int proto; | 1571 | int proto; |
| 1569 | 1572 | ||
| 1570 | if (!pch || skb->len == 0) { | 1573 | if (!pch) { |
| 1571 | kfree_skb(skb); | 1574 | kfree_skb(skb); |
| 1572 | return; | 1575 | return; |
| 1573 | } | 1576 | } |
| 1574 | 1577 | ||
| 1575 | proto = PPP_PROTO(skb); | ||
| 1576 | read_lock_bh(&pch->upl); | 1578 | read_lock_bh(&pch->upl); |
| 1579 | if (!pskb_may_pull(skb, 2)) { | ||
| 1580 | kfree_skb(skb); | ||
| 1581 | if (pch->ppp) { | ||
| 1582 | ++pch->ppp->dev->stats.rx_length_errors; | ||
| 1583 | ppp_receive_error(pch->ppp); | ||
| 1584 | } | ||
| 1585 | goto done; | ||
| 1586 | } | ||
| 1587 | |||
| 1588 | proto = PPP_PROTO(skb); | ||
| 1577 | if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { | 1589 | if (!pch->ppp || proto >= 0xc000 || proto == PPP_CCPFRAG) { |
| 1578 | /* put it on the channel queue */ | 1590 | /* put it on the channel queue */ |
| 1579 | skb_queue_tail(&pch->file.rq, skb); | 1591 | skb_queue_tail(&pch->file.rq, skb); |
| @@ -1585,6 +1597,8 @@ ppp_input(struct ppp_channel *chan, struct sk_buff *skb) | |||
| 1585 | } else { | 1597 | } else { |
| 1586 | ppp_do_recv(pch->ppp, skb, pch); | 1598 | ppp_do_recv(pch->ppp, skb, pch); |
| 1587 | } | 1599 | } |
| 1600 | |||
| 1601 | done: | ||
| 1588 | read_unlock_bh(&pch->upl); | 1602 | read_unlock_bh(&pch->upl); |
| 1589 | } | 1603 | } |
| 1590 | 1604 | ||
| @@ -1617,7 +1631,8 @@ ppp_input_error(struct ppp_channel *chan, int code) | |||
| 1617 | static void | 1631 | static void |
| 1618 | ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) | 1632 | ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) |
| 1619 | { | 1633 | { |
| 1620 | if (pskb_may_pull(skb, 2)) { | 1634 | /* note: a 0-length skb is used as an error indication */ |
| 1635 | if (skb->len > 0) { | ||
| 1621 | #ifdef CONFIG_PPP_MULTILINK | 1636 | #ifdef CONFIG_PPP_MULTILINK |
| 1622 | /* XXX do channel-level decompression here */ | 1637 | /* XXX do channel-level decompression here */ |
| 1623 | if (PPP_PROTO(skb) == PPP_MP) | 1638 | if (PPP_PROTO(skb) == PPP_MP) |
| @@ -1625,15 +1640,10 @@ ppp_receive_frame(struct ppp *ppp, struct sk_buff *skb, struct channel *pch) | |||
| 1625 | else | 1640 | else |
| 1626 | #endif /* CONFIG_PPP_MULTILINK */ | 1641 | #endif /* CONFIG_PPP_MULTILINK */ |
| 1627 | ppp_receive_nonmp_frame(ppp, skb); | 1642 | ppp_receive_nonmp_frame(ppp, skb); |
| 1628 | return; | 1643 | } else { |
| 1644 | kfree_skb(skb); | ||
| 1645 | ppp_receive_error(ppp); | ||
| 1629 | } | 1646 | } |
| 1630 | |||
| 1631 | if (skb->len > 0) | ||
| 1632 | /* note: a 0-length skb is used as an error indication */ | ||
| 1633 | ++ppp->dev->stats.rx_length_errors; | ||
| 1634 | |||
| 1635 | kfree_skb(skb); | ||
| 1636 | ppp_receive_error(ppp); | ||
| 1637 | } | 1647 | } |
| 1638 | 1648 | ||
| 1639 | static void | 1649 | static void |
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 4748c21eb72e..dd8106ff35aa 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -1042,14 +1042,14 @@ static void rtl8169_vlan_rx_register(struct net_device *dev, | |||
| 1042 | } | 1042 | } |
| 1043 | 1043 | ||
| 1044 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, | 1044 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, |
| 1045 | struct sk_buff *skb) | 1045 | struct sk_buff *skb, int polling) |
| 1046 | { | 1046 | { |
| 1047 | u32 opts2 = le32_to_cpu(desc->opts2); | 1047 | u32 opts2 = le32_to_cpu(desc->opts2); |
| 1048 | struct vlan_group *vlgrp = tp->vlgrp; | 1048 | struct vlan_group *vlgrp = tp->vlgrp; |
| 1049 | int ret; | 1049 | int ret; |
| 1050 | 1050 | ||
| 1051 | if (vlgrp && (opts2 & RxVlanTag)) { | 1051 | if (vlgrp && (opts2 & RxVlanTag)) { |
| 1052 | vlan_hwaccel_receive_skb(skb, vlgrp, swab16(opts2 & 0xffff)); | 1052 | __vlan_hwaccel_rx(skb, vlgrp, swab16(opts2 & 0xffff), polling); |
| 1053 | ret = 0; | 1053 | ret = 0; |
| 1054 | } else | 1054 | } else |
| 1055 | ret = -1; | 1055 | ret = -1; |
| @@ -1066,7 +1066,7 @@ static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp, | |||
| 1066 | } | 1066 | } |
| 1067 | 1067 | ||
| 1068 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, | 1068 | static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc, |
| 1069 | struct sk_buff *skb) | 1069 | struct sk_buff *skb, int polling) |
| 1070 | { | 1070 | { |
| 1071 | return -1; | 1071 | return -1; |
| 1072 | } | 1072 | } |
| @@ -4445,12 +4445,20 @@ out: | |||
| 4445 | return done; | 4445 | return done; |
| 4446 | } | 4446 | } |
| 4447 | 4447 | ||
| 4448 | /* | ||
| 4449 | * Warning : rtl8169_rx_interrupt() might be called : | ||
| 4450 | * 1) from NAPI (softirq) context | ||
| 4451 | * (polling = 1 : we should call netif_receive_skb()) | ||
| 4452 | * 2) from process context (rtl8169_reset_task()) | ||
| 4453 | * (polling = 0 : we must call netif_rx() instead) | ||
| 4454 | */ | ||
| 4448 | static int rtl8169_rx_interrupt(struct net_device *dev, | 4455 | static int rtl8169_rx_interrupt(struct net_device *dev, |
| 4449 | struct rtl8169_private *tp, | 4456 | struct rtl8169_private *tp, |
| 4450 | void __iomem *ioaddr, u32 budget) | 4457 | void __iomem *ioaddr, u32 budget) |
| 4451 | { | 4458 | { |
| 4452 | unsigned int cur_rx, rx_left; | 4459 | unsigned int cur_rx, rx_left; |
| 4453 | unsigned int delta, count; | 4460 | unsigned int delta, count; |
| 4461 | int polling = (budget != ~(u32)0) ? 1 : 0; | ||
| 4454 | 4462 | ||
| 4455 | cur_rx = tp->cur_rx; | 4463 | cur_rx = tp->cur_rx; |
| 4456 | rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; | 4464 | rx_left = NUM_RX_DESC + tp->dirty_rx - cur_rx; |
| @@ -4512,8 +4520,12 @@ static int rtl8169_rx_interrupt(struct net_device *dev, | |||
| 4512 | skb_put(skb, pkt_size); | 4520 | skb_put(skb, pkt_size); |
| 4513 | skb->protocol = eth_type_trans(skb, dev); | 4521 | skb->protocol = eth_type_trans(skb, dev); |
| 4514 | 4522 | ||
| 4515 | if (rtl8169_rx_vlan_skb(tp, desc, skb) < 0) | 4523 | if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) { |
| 4516 | netif_receive_skb(skb); | 4524 | if (likely(polling)) |
| 4525 | netif_receive_skb(skb); | ||
| 4526 | else | ||
| 4527 | netif_rx(skb); | ||
| 4528 | } | ||
| 4517 | 4529 | ||
| 4518 | dev->stats.rx_bytes += pkt_size; | 4530 | dev->stats.rx_bytes += pkt_size; |
| 4519 | dev->stats.rx_packets++; | 4531 | dev->stats.rx_packets++; |
diff --git a/drivers/net/sb1250-mac.c b/drivers/net/sb1250-mac.c index 9944e5d662c0..04efc0c1bda9 100644 --- a/drivers/net/sb1250-mac.c +++ b/drivers/net/sb1250-mac.c | |||
| @@ -2353,17 +2353,36 @@ static int sbmac_init(struct platform_device *pldev, long long base) | |||
| 2353 | 2353 | ||
| 2354 | sc->mii_bus = mdiobus_alloc(); | 2354 | sc->mii_bus = mdiobus_alloc(); |
| 2355 | if (sc->mii_bus == NULL) { | 2355 | if (sc->mii_bus == NULL) { |
| 2356 | sbmac_uninitctx(sc); | 2356 | err = -ENOMEM; |
| 2357 | return -ENOMEM; | 2357 | goto uninit_ctx; |
| 2358 | } | 2358 | } |
| 2359 | 2359 | ||
| 2360 | sc->mii_bus->name = sbmac_mdio_string; | ||
| 2361 | snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); | ||
| 2362 | sc->mii_bus->priv = sc; | ||
| 2363 | sc->mii_bus->read = sbmac_mii_read; | ||
| 2364 | sc->mii_bus->write = sbmac_mii_write; | ||
| 2365 | sc->mii_bus->irq = sc->phy_irq; | ||
| 2366 | for (i = 0; i < PHY_MAX_ADDR; ++i) | ||
| 2367 | sc->mii_bus->irq[i] = SBMAC_PHY_INT; | ||
| 2368 | |||
| 2369 | sc->mii_bus->parent = &pldev->dev; | ||
| 2370 | /* | ||
| 2371 | * Probe PHY address | ||
| 2372 | */ | ||
| 2373 | err = mdiobus_register(sc->mii_bus); | ||
| 2374 | if (err) { | ||
| 2375 | printk(KERN_ERR "%s: unable to register MDIO bus\n", | ||
| 2376 | dev->name); | ||
| 2377 | goto free_mdio; | ||
| 2378 | } | ||
| 2379 | dev_set_drvdata(&pldev->dev, sc->mii_bus); | ||
| 2380 | |||
| 2360 | err = register_netdev(dev); | 2381 | err = register_netdev(dev); |
| 2361 | if (err) { | 2382 | if (err) { |
| 2362 | printk(KERN_ERR "%s.%d: unable to register netdev\n", | 2383 | printk(KERN_ERR "%s.%d: unable to register netdev\n", |
| 2363 | sbmac_string, idx); | 2384 | sbmac_string, idx); |
| 2364 | mdiobus_free(sc->mii_bus); | 2385 | goto unreg_mdio; |
| 2365 | sbmac_uninitctx(sc); | ||
| 2366 | return err; | ||
| 2367 | } | 2386 | } |
| 2368 | 2387 | ||
| 2369 | pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); | 2388 | pr_info("%s.%d: registered as %s\n", sbmac_string, idx, dev->name); |
| @@ -2379,19 +2398,15 @@ static int sbmac_init(struct platform_device *pldev, long long base) | |||
| 2379 | pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n", | 2398 | pr_info("%s: SiByte Ethernet at 0x%08Lx, address: %pM\n", |
| 2380 | dev->name, base, eaddr); | 2399 | dev->name, base, eaddr); |
| 2381 | 2400 | ||
| 2382 | sc->mii_bus->name = sbmac_mdio_string; | ||
| 2383 | snprintf(sc->mii_bus->id, MII_BUS_ID_SIZE, "%x", idx); | ||
| 2384 | sc->mii_bus->priv = sc; | ||
| 2385 | sc->mii_bus->read = sbmac_mii_read; | ||
| 2386 | sc->mii_bus->write = sbmac_mii_write; | ||
| 2387 | sc->mii_bus->irq = sc->phy_irq; | ||
| 2388 | for (i = 0; i < PHY_MAX_ADDR; ++i) | ||
| 2389 | sc->mii_bus->irq[i] = SBMAC_PHY_INT; | ||
| 2390 | |||
| 2391 | sc->mii_bus->parent = &pldev->dev; | ||
| 2392 | dev_set_drvdata(&pldev->dev, sc->mii_bus); | ||
| 2393 | |||
| 2394 | return 0; | 2401 | return 0; |
| 2402 | unreg_mdio: | ||
| 2403 | mdiobus_unregister(sc->mii_bus); | ||
| 2404 | dev_set_drvdata(&pldev->dev, NULL); | ||
| 2405 | free_mdio: | ||
| 2406 | mdiobus_free(sc->mii_bus); | ||
| 2407 | uninit_ctx: | ||
| 2408 | sbmac_uninitctx(sc); | ||
| 2409 | return err; | ||
| 2395 | } | 2410 | } |
| 2396 | 2411 | ||
| 2397 | 2412 | ||
| @@ -2417,16 +2432,6 @@ static int sbmac_open(struct net_device *dev) | |||
| 2417 | goto out_err; | 2432 | goto out_err; |
| 2418 | } | 2433 | } |
| 2419 | 2434 | ||
| 2420 | /* | ||
| 2421 | * Probe PHY address | ||
| 2422 | */ | ||
| 2423 | err = mdiobus_register(sc->mii_bus); | ||
| 2424 | if (err) { | ||
| 2425 | printk(KERN_ERR "%s: unable to register MDIO bus\n", | ||
| 2426 | dev->name); | ||
| 2427 | goto out_unirq; | ||
| 2428 | } | ||
| 2429 | |||
| 2430 | sc->sbm_speed = sbmac_speed_none; | 2435 | sc->sbm_speed = sbmac_speed_none; |
| 2431 | sc->sbm_duplex = sbmac_duplex_none; | 2436 | sc->sbm_duplex = sbmac_duplex_none; |
| 2432 | sc->sbm_fc = sbmac_fc_none; | 2437 | sc->sbm_fc = sbmac_fc_none; |
| @@ -2457,11 +2462,7 @@ static int sbmac_open(struct net_device *dev) | |||
| 2457 | return 0; | 2462 | return 0; |
| 2458 | 2463 | ||
| 2459 | out_unregister: | 2464 | out_unregister: |
| 2460 | mdiobus_unregister(sc->mii_bus); | ||
| 2461 | |||
| 2462 | out_unirq: | ||
| 2463 | free_irq(dev->irq, dev); | 2465 | free_irq(dev->irq, dev); |
| 2464 | |||
| 2465 | out_err: | 2466 | out_err: |
| 2466 | return err; | 2467 | return err; |
| 2467 | } | 2468 | } |
| @@ -2650,9 +2651,6 @@ static int sbmac_close(struct net_device *dev) | |||
| 2650 | 2651 | ||
| 2651 | phy_disconnect(sc->phy_dev); | 2652 | phy_disconnect(sc->phy_dev); |
| 2652 | sc->phy_dev = NULL; | 2653 | sc->phy_dev = NULL; |
| 2653 | |||
| 2654 | mdiobus_unregister(sc->mii_bus); | ||
| 2655 | |||
| 2656 | free_irq(dev->irq, dev); | 2654 | free_irq(dev->irq, dev); |
| 2657 | 2655 | ||
| 2658 | sbdma_emptyring(&(sc->sbm_txdma)); | 2656 | sbdma_emptyring(&(sc->sbm_txdma)); |
| @@ -2760,6 +2758,7 @@ static int __exit sbmac_remove(struct platform_device *pldev) | |||
| 2760 | 2758 | ||
| 2761 | unregister_netdev(dev); | 2759 | unregister_netdev(dev); |
| 2762 | sbmac_uninitctx(sc); | 2760 | sbmac_uninitctx(sc); |
| 2761 | mdiobus_unregister(sc->mii_bus); | ||
| 2763 | mdiobus_free(sc->mii_bus); | 2762 | mdiobus_free(sc->mii_bus); |
| 2764 | iounmap(sc->sbm_base); | 2763 | iounmap(sc->sbm_base); |
| 2765 | free_netdev(dev); | 2764 | free_netdev(dev); |
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 5d58abc224f4..d7b7018a1de1 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
| @@ -400,7 +400,6 @@ config USB_IPHETH | |||
| 400 | config USB_SIERRA_NET | 400 | config USB_SIERRA_NET |
| 401 | tristate "USB-to-WWAN Driver for Sierra Wireless modems" | 401 | tristate "USB-to-WWAN Driver for Sierra Wireless modems" |
| 402 | depends on USB_USBNET | 402 | depends on USB_USBNET |
| 403 | default y | ||
| 404 | help | 403 | help |
| 405 | Choose this option if you have a Sierra Wireless USB-to-WWAN device. | 404 | Choose this option if you have a Sierra Wireless USB-to-WWAN device. |
| 406 | 405 | ||
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 04b281002a76..5dfed9297b22 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c | |||
| @@ -240,7 +240,7 @@ static int dm_write_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 valu | |||
| 240 | goto out; | 240 | goto out; |
| 241 | 241 | ||
| 242 | dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); | 242 | dm_write_reg(dev, DM_SHARED_ADDR, phy ? (reg | 0x40) : reg); |
| 243 | dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1c : 0x14); | 243 | dm_write_reg(dev, DM_SHARED_CTRL, phy ? 0x1a : 0x12); |
| 244 | 244 | ||
| 245 | for (i = 0; i < DM_TIMEOUT; i++) { | 245 | for (i = 0; i < DM_TIMEOUT; i++) { |
| 246 | u8 tmp; | 246 | u8 tmp; |
diff --git a/drivers/net/usb/sierra_net.c b/drivers/net/usb/sierra_net.c index a44f9e0ea098..f1942d69a0d5 100644 --- a/drivers/net/usb/sierra_net.c +++ b/drivers/net/usb/sierra_net.c | |||
| @@ -789,6 +789,9 @@ static int sierra_net_bind(struct usbnet *dev, struct usb_interface *intf) | |||
| 789 | /* prepare sync message from template */ | 789 | /* prepare sync message from template */ |
| 790 | memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); | 790 | memcpy(priv->sync_msg, sync_tmplate, sizeof(priv->sync_msg)); |
| 791 | 791 | ||
| 792 | /* initiate the sync sequence */ | ||
| 793 | sierra_net_dosync(dev); | ||
| 794 | |||
| 792 | return 0; | 795 | return 0; |
| 793 | } | 796 | } |
| 794 | 797 | ||
diff --git a/drivers/net/veth.c b/drivers/net/veth.c index f9f0730b53d5..5ec542dd5b50 100644 --- a/drivers/net/veth.c +++ b/drivers/net/veth.c | |||
| @@ -187,7 +187,6 @@ tx_drop: | |||
| 187 | return NETDEV_TX_OK; | 187 | return NETDEV_TX_OK; |
| 188 | 188 | ||
| 189 | rx_drop: | 189 | rx_drop: |
| 190 | kfree_skb(skb); | ||
| 191 | rcv_stats->rx_dropped++; | 190 | rcv_stats->rx_dropped++; |
| 192 | return NETDEV_TX_OK; | 191 | return NETDEV_TX_OK; |
| 193 | } | 192 | } |
diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c index 99a6da464bd3..e1c2fcaa8bed 100644 --- a/drivers/net/wireless/ath/ar9170/usb.c +++ b/drivers/net/wireless/ath/ar9170/usb.c | |||
| @@ -727,12 +727,16 @@ static void ar9170_usb_firmware_failed(struct ar9170_usb *aru) | |||
| 727 | { | 727 | { |
| 728 | struct device *parent = aru->udev->dev.parent; | 728 | struct device *parent = aru->udev->dev.parent; |
| 729 | 729 | ||
| 730 | complete(&aru->firmware_loading_complete); | ||
| 731 | |||
| 730 | /* unbind anything failed */ | 732 | /* unbind anything failed */ |
| 731 | if (parent) | 733 | if (parent) |
| 732 | down(&parent->sem); | 734 | down(&parent->sem); |
| 733 | device_release_driver(&aru->udev->dev); | 735 | device_release_driver(&aru->udev->dev); |
| 734 | if (parent) | 736 | if (parent) |
| 735 | up(&parent->sem); | 737 | up(&parent->sem); |
| 738 | |||
| 739 | usb_put_dev(aru->udev); | ||
| 736 | } | 740 | } |
| 737 | 741 | ||
| 738 | static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) | 742 | static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) |
| @@ -761,6 +765,8 @@ static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context) | |||
| 761 | if (err) | 765 | if (err) |
| 762 | goto err_unrx; | 766 | goto err_unrx; |
| 763 | 767 | ||
| 768 | complete(&aru->firmware_loading_complete); | ||
| 769 | usb_put_dev(aru->udev); | ||
| 764 | return; | 770 | return; |
| 765 | 771 | ||
| 766 | err_unrx: | 772 | err_unrx: |
| @@ -858,6 +864,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
| 858 | init_usb_anchor(&aru->tx_pending); | 864 | init_usb_anchor(&aru->tx_pending); |
| 859 | init_usb_anchor(&aru->tx_submitted); | 865 | init_usb_anchor(&aru->tx_submitted); |
| 860 | init_completion(&aru->cmd_wait); | 866 | init_completion(&aru->cmd_wait); |
| 867 | init_completion(&aru->firmware_loading_complete); | ||
| 861 | spin_lock_init(&aru->tx_urb_lock); | 868 | spin_lock_init(&aru->tx_urb_lock); |
| 862 | 869 | ||
| 863 | aru->tx_pending_urbs = 0; | 870 | aru->tx_pending_urbs = 0; |
| @@ -877,6 +884,7 @@ static int ar9170_usb_probe(struct usb_interface *intf, | |||
| 877 | if (err) | 884 | if (err) |
| 878 | goto err_freehw; | 885 | goto err_freehw; |
| 879 | 886 | ||
| 887 | usb_get_dev(aru->udev); | ||
| 880 | return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", | 888 | return request_firmware_nowait(THIS_MODULE, 1, "ar9170.fw", |
| 881 | &aru->udev->dev, GFP_KERNEL, aru, | 889 | &aru->udev->dev, GFP_KERNEL, aru, |
| 882 | ar9170_usb_firmware_step2); | 890 | ar9170_usb_firmware_step2); |
| @@ -896,6 +904,9 @@ static void ar9170_usb_disconnect(struct usb_interface *intf) | |||
| 896 | return; | 904 | return; |
| 897 | 905 | ||
| 898 | aru->common.state = AR9170_IDLE; | 906 | aru->common.state = AR9170_IDLE; |
| 907 | |||
| 908 | wait_for_completion(&aru->firmware_loading_complete); | ||
| 909 | |||
| 899 | ar9170_unregister(&aru->common); | 910 | ar9170_unregister(&aru->common); |
| 900 | ar9170_usb_cancel_urbs(aru); | 911 | ar9170_usb_cancel_urbs(aru); |
| 901 | 912 | ||
diff --git a/drivers/net/wireless/ath/ar9170/usb.h b/drivers/net/wireless/ath/ar9170/usb.h index a2ce3b169ceb..919b06046eb3 100644 --- a/drivers/net/wireless/ath/ar9170/usb.h +++ b/drivers/net/wireless/ath/ar9170/usb.h | |||
| @@ -71,6 +71,7 @@ struct ar9170_usb { | |||
| 71 | unsigned int tx_pending_urbs; | 71 | unsigned int tx_pending_urbs; |
| 72 | 72 | ||
| 73 | struct completion cmd_wait; | 73 | struct completion cmd_wait; |
| 74 | struct completion firmware_loading_complete; | ||
| 74 | int readlen; | 75 | int readlen; |
| 75 | u8 *readbuf; | 76 | u8 *readbuf; |
| 76 | 77 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 6383d9f8c9b3..f4e59ae07f8e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
| @@ -2621,7 +2621,9 @@ struct iwl_ssid_ie { | |||
| 2621 | #define PROBE_OPTION_MAX_3945 4 | 2621 | #define PROBE_OPTION_MAX_3945 4 |
| 2622 | #define PROBE_OPTION_MAX 20 | 2622 | #define PROBE_OPTION_MAX 20 |
| 2623 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) | 2623 | #define TX_CMD_LIFE_TIME_INFINITE cpu_to_le32(0xFFFFFFFF) |
| 2624 | #define IWL_GOOD_CRC_TH cpu_to_le16(1) | 2624 | #define IWL_GOOD_CRC_TH_DISABLED 0 |
| 2625 | #define IWL_GOOD_CRC_TH_DEFAULT cpu_to_le16(1) | ||
| 2626 | #define IWL_GOOD_CRC_TH_NEVER cpu_to_le16(0xffff) | ||
| 2625 | #define IWL_MAX_SCAN_SIZE 1024 | 2627 | #define IWL_MAX_SCAN_SIZE 1024 |
| 2626 | #define IWL_MAX_CMD_SIZE 4096 | 2628 | #define IWL_MAX_CMD_SIZE 4096 |
| 2627 | #define IWL_MAX_PROBE_REQUEST 200 | 2629 | #define IWL_MAX_PROBE_REQUEST 200 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 12e455a4b90e..741e65ec8301 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
| @@ -813,16 +813,29 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
| 813 | rate = IWL_RATE_1M_PLCP; | 813 | rate = IWL_RATE_1M_PLCP; |
| 814 | rate_flags = RATE_MCS_CCK_MSK; | 814 | rate_flags = RATE_MCS_CCK_MSK; |
| 815 | } | 815 | } |
| 816 | scan->good_CRC_th = 0; | 816 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; |
| 817 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { | 817 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { |
| 818 | band = IEEE80211_BAND_5GHZ; | 818 | band = IEEE80211_BAND_5GHZ; |
| 819 | rate = IWL_RATE_6M_PLCP; | 819 | rate = IWL_RATE_6M_PLCP; |
| 820 | /* | 820 | /* |
| 821 | * If active scaning is requested but a certain channel | 821 | * If active scanning is requested but a certain channel is |
| 822 | * is marked passive, we can do active scanning if we | 822 | * marked passive, we can do active scanning if we detect |
| 823 | * detect transmissions. | 823 | * transmissions. |
| 824 | * | ||
| 825 | * There is an issue with some firmware versions that triggers | ||
| 826 | * a sysassert on a "good CRC threshold" of zero (== disabled), | ||
| 827 | * on a radar channel even though this means that we should NOT | ||
| 828 | * send probes. | ||
| 829 | * | ||
| 830 | * The "good CRC threshold" is the number of frames that we | ||
| 831 | * need to receive during our dwell time on a channel before | ||
| 832 | * sending out probes -- setting this to a huge value will | ||
| 833 | * mean we never reach it, but at the same time work around | ||
| 834 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | ||
| 835 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | ||
| 824 | */ | 836 | */ |
| 825 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 837 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : |
| 838 | IWL_GOOD_CRC_TH_NEVER; | ||
| 826 | 839 | ||
| 827 | /* Force use of chains B and C (0x6) for scan Rx for 4965 | 840 | /* Force use of chains B and C (0x6) for scan Rx for 4965 |
| 828 | * Avoid A (0x1) because of its off-channel reception on A-band. | 841 | * Avoid A (0x1) because of its off-channel reception on A-band. |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index b55e4f39a9e1..b74a56c48d26 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
| @@ -2967,7 +2967,8 @@ static void iwl3945_bg_request_scan(struct work_struct *data) | |||
| 2967 | * is marked passive, we can do active scanning if we | 2967 | * is marked passive, we can do active scanning if we |
| 2968 | * detect transmissions. | 2968 | * detect transmissions. |
| 2969 | */ | 2969 | */ |
| 2970 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 2970 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : |
| 2971 | IWL_GOOD_CRC_TH_DISABLED; | ||
| 2971 | band = IEEE80211_BAND_5GHZ; | 2972 | band = IEEE80211_BAND_5GHZ; |
| 2972 | } else { | 2973 | } else { |
| 2973 | IWL_WARN(priv, "Invalid scan band count\n"); | 2974 | IWL_WARN(priv, "Invalid scan band count\n"); |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index 269fda362836..c24067f1a0cb 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
| @@ -246,7 +246,7 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | |||
| 246 | u32 idx, i; | 246 | u32 idx, i; |
| 247 | 247 | ||
| 248 | i = (*index) % ring_limit; | 248 | i = (*index) % ring_limit; |
| 249 | (*index) = idx = le32_to_cpu(ring_control->device_idx[1]); | 249 | (*index) = idx = le32_to_cpu(ring_control->device_idx[ring_index]); |
| 250 | idx %= ring_limit; | 250 | idx %= ring_limit; |
| 251 | 251 | ||
| 252 | while (i != idx) { | 252 | while (i != idx) { |
diff --git a/drivers/net/zorro8390.c b/drivers/net/zorro8390.c index 81c753a617ab..9548cbb5012a 100644 --- a/drivers/net/zorro8390.c +++ b/drivers/net/zorro8390.c | |||
| @@ -102,6 +102,7 @@ static struct zorro_device_id zorro8390_zorro_tbl[] __devinitdata = { | |||
| 102 | { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, | 102 | { ZORRO_PROD_INDIVIDUAL_COMPUTERS_X_SURF, }, |
| 103 | { 0 } | 103 | { 0 } |
| 104 | }; | 104 | }; |
| 105 | MODULE_DEVICE_TABLE(zorro, zorro8390_zorro_tbl); | ||
| 105 | 106 | ||
| 106 | static struct zorro_driver zorro8390_driver = { | 107 | static struct zorro_driver zorro8390_driver = { |
| 107 | .name = "zorro8390", | 108 | .name = "zorro8390", |
diff --git a/drivers/oprofile/cpu_buffer.c b/drivers/oprofile/cpu_buffer.c index 166b67ea622f..219f79e2210a 100644 --- a/drivers/oprofile/cpu_buffer.c +++ b/drivers/oprofile/cpu_buffer.c | |||
| @@ -30,23 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #define OP_BUFFER_FLAGS 0 | 31 | #define OP_BUFFER_FLAGS 0 |
| 32 | 32 | ||
| 33 | /* | 33 | static struct ring_buffer *op_ring_buffer; |
| 34 | * Read and write access is using spin locking. Thus, writing to the | ||
| 35 | * buffer by NMI handler (x86) could occur also during critical | ||
| 36 | * sections when reading the buffer. To avoid this, there are 2 | ||
| 37 | * buffers for independent read and write access. Read access is in | ||
| 38 | * process context only, write access only in the NMI handler. If the | ||
| 39 | * read buffer runs empty, both buffers are swapped atomically. There | ||
| 40 | * is potentially a small window during swapping where the buffers are | ||
| 41 | * disabled and samples could be lost. | ||
| 42 | * | ||
| 43 | * Using 2 buffers is a little bit overhead, but the solution is clear | ||
| 44 | * and does not require changes in the ring buffer implementation. It | ||
| 45 | * can be changed to a single buffer solution when the ring buffer | ||
| 46 | * access is implemented as non-locking atomic code. | ||
| 47 | */ | ||
| 48 | static struct ring_buffer *op_ring_buffer_read; | ||
| 49 | static struct ring_buffer *op_ring_buffer_write; | ||
| 50 | DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); | 34 | DEFINE_PER_CPU(struct oprofile_cpu_buffer, op_cpu_buffer); |
| 51 | 35 | ||
| 52 | static void wq_sync_buffer(struct work_struct *work); | 36 | static void wq_sync_buffer(struct work_struct *work); |
| @@ -68,12 +52,9 @@ void oprofile_cpu_buffer_inc_smpl_lost(void) | |||
| 68 | 52 | ||
| 69 | void free_cpu_buffers(void) | 53 | void free_cpu_buffers(void) |
| 70 | { | 54 | { |
| 71 | if (op_ring_buffer_read) | 55 | if (op_ring_buffer) |
| 72 | ring_buffer_free(op_ring_buffer_read); | 56 | ring_buffer_free(op_ring_buffer); |
| 73 | op_ring_buffer_read = NULL; | 57 | op_ring_buffer = NULL; |
| 74 | if (op_ring_buffer_write) | ||
| 75 | ring_buffer_free(op_ring_buffer_write); | ||
| 76 | op_ring_buffer_write = NULL; | ||
| 77 | } | 58 | } |
| 78 | 59 | ||
| 79 | #define RB_EVENT_HDR_SIZE 4 | 60 | #define RB_EVENT_HDR_SIZE 4 |
| @@ -86,11 +67,8 @@ int alloc_cpu_buffers(void) | |||
| 86 | unsigned long byte_size = buffer_size * (sizeof(struct op_sample) + | 67 | unsigned long byte_size = buffer_size * (sizeof(struct op_sample) + |
| 87 | RB_EVENT_HDR_SIZE); | 68 | RB_EVENT_HDR_SIZE); |
| 88 | 69 | ||
| 89 | op_ring_buffer_read = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); | 70 | op_ring_buffer = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); |
| 90 | if (!op_ring_buffer_read) | 71 | if (!op_ring_buffer) |
| 91 | goto fail; | ||
| 92 | op_ring_buffer_write = ring_buffer_alloc(byte_size, OP_BUFFER_FLAGS); | ||
| 93 | if (!op_ring_buffer_write) | ||
| 94 | goto fail; | 72 | goto fail; |
| 95 | 73 | ||
| 96 | for_each_possible_cpu(i) { | 74 | for_each_possible_cpu(i) { |
| @@ -162,16 +140,11 @@ struct op_sample | |||
| 162 | *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size) | 140 | *op_cpu_buffer_write_reserve(struct op_entry *entry, unsigned long size) |
| 163 | { | 141 | { |
| 164 | entry->event = ring_buffer_lock_reserve | 142 | entry->event = ring_buffer_lock_reserve |
| 165 | (op_ring_buffer_write, sizeof(struct op_sample) + | 143 | (op_ring_buffer, sizeof(struct op_sample) + |
| 166 | size * sizeof(entry->sample->data[0])); | 144 | size * sizeof(entry->sample->data[0])); |
| 167 | if (entry->event) | 145 | if (!entry->event) |
| 168 | entry->sample = ring_buffer_event_data(entry->event); | ||
| 169 | else | ||
| 170 | entry->sample = NULL; | ||
| 171 | |||
| 172 | if (!entry->sample) | ||
| 173 | return NULL; | 146 | return NULL; |
| 174 | 147 | entry->sample = ring_buffer_event_data(entry->event); | |
| 175 | entry->size = size; | 148 | entry->size = size; |
| 176 | entry->data = entry->sample->data; | 149 | entry->data = entry->sample->data; |
| 177 | 150 | ||
| @@ -180,25 +153,16 @@ struct op_sample | |||
| 180 | 153 | ||
| 181 | int op_cpu_buffer_write_commit(struct op_entry *entry) | 154 | int op_cpu_buffer_write_commit(struct op_entry *entry) |
| 182 | { | 155 | { |
| 183 | return ring_buffer_unlock_commit(op_ring_buffer_write, entry->event); | 156 | return ring_buffer_unlock_commit(op_ring_buffer, entry->event); |
| 184 | } | 157 | } |
| 185 | 158 | ||
| 186 | struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu) | 159 | struct op_sample *op_cpu_buffer_read_entry(struct op_entry *entry, int cpu) |
| 187 | { | 160 | { |
| 188 | struct ring_buffer_event *e; | 161 | struct ring_buffer_event *e; |
| 189 | e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); | 162 | e = ring_buffer_consume(op_ring_buffer, cpu, NULL, NULL); |
| 190 | if (e) | 163 | if (!e) |
| 191 | goto event; | ||
| 192 | if (ring_buffer_swap_cpu(op_ring_buffer_read, | ||
| 193 | op_ring_buffer_write, | ||
| 194 | cpu)) | ||
| 195 | return NULL; | 164 | return NULL; |
| 196 | e = ring_buffer_consume(op_ring_buffer_read, cpu, NULL); | ||
| 197 | if (e) | ||
| 198 | goto event; | ||
| 199 | return NULL; | ||
| 200 | 165 | ||
| 201 | event: | ||
| 202 | entry->event = e; | 166 | entry->event = e; |
| 203 | entry->sample = ring_buffer_event_data(e); | 167 | entry->sample = ring_buffer_event_data(e); |
| 204 | entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample)) | 168 | entry->size = (ring_buffer_event_length(e) - sizeof(struct op_sample)) |
| @@ -209,8 +173,7 @@ event: | |||
| 209 | 173 | ||
| 210 | unsigned long op_cpu_buffer_entries(int cpu) | 174 | unsigned long op_cpu_buffer_entries(int cpu) |
| 211 | { | 175 | { |
| 212 | return ring_buffer_entries_cpu(op_ring_buffer_read, cpu) | 176 | return ring_buffer_entries_cpu(op_ring_buffer, cpu); |
| 213 | + ring_buffer_entries_cpu(op_ring_buffer_write, cpu); | ||
| 214 | } | 177 | } |
| 215 | 178 | ||
| 216 | static int | 179 | static int |
| @@ -356,8 +319,16 @@ void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs, | |||
| 356 | 319 | ||
| 357 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) | 320 | void oprofile_add_sample(struct pt_regs * const regs, unsigned long event) |
| 358 | { | 321 | { |
| 359 | int is_kernel = !user_mode(regs); | 322 | int is_kernel; |
| 360 | unsigned long pc = profile_pc(regs); | 323 | unsigned long pc; |
| 324 | |||
| 325 | if (likely(regs)) { | ||
| 326 | is_kernel = !user_mode(regs); | ||
| 327 | pc = profile_pc(regs); | ||
| 328 | } else { | ||
| 329 | is_kernel = 0; /* This value will not be used */ | ||
| 330 | pc = ESCAPE_CODE; /* as this causes an early return. */ | ||
| 331 | } | ||
| 361 | 332 | ||
| 362 | __oprofile_add_ext_sample(pc, regs, event, is_kernel); | 333 | __oprofile_add_ext_sample(pc, regs, event, is_kernel); |
| 363 | } | 334 | } |
diff --git a/drivers/oprofile/oprof.c b/drivers/oprofile/oprof.c index dc8a0428260d..b336cd9ee7a1 100644 --- a/drivers/oprofile/oprof.c +++ b/drivers/oprofile/oprof.c | |||
| @@ -253,22 +253,26 @@ static int __init oprofile_init(void) | |||
| 253 | int err; | 253 | int err; |
| 254 | 254 | ||
| 255 | err = oprofile_arch_init(&oprofile_ops); | 255 | err = oprofile_arch_init(&oprofile_ops); |
| 256 | |||
| 257 | if (err < 0 || timer) { | 256 | if (err < 0 || timer) { |
| 258 | printk(KERN_INFO "oprofile: using timer interrupt.\n"); | 257 | printk(KERN_INFO "oprofile: using timer interrupt.\n"); |
| 259 | oprofile_timer_init(&oprofile_ops); | 258 | err = oprofile_timer_init(&oprofile_ops); |
| 259 | if (err) | ||
| 260 | goto out_arch; | ||
| 260 | } | 261 | } |
| 261 | |||
| 262 | err = oprofilefs_register(); | 262 | err = oprofilefs_register(); |
| 263 | if (err) | 263 | if (err) |
| 264 | oprofile_arch_exit(); | 264 | goto out_arch; |
| 265 | return 0; | ||
| 265 | 266 | ||
| 267 | out_arch: | ||
| 268 | oprofile_arch_exit(); | ||
| 266 | return err; | 269 | return err; |
| 267 | } | 270 | } |
| 268 | 271 | ||
| 269 | 272 | ||
| 270 | static void __exit oprofile_exit(void) | 273 | static void __exit oprofile_exit(void) |
| 271 | { | 274 | { |
| 275 | oprofile_timer_exit(); | ||
| 272 | oprofilefs_unregister(); | 276 | oprofilefs_unregister(); |
| 273 | oprofile_arch_exit(); | 277 | oprofile_arch_exit(); |
| 274 | } | 278 | } |
diff --git a/drivers/oprofile/oprof.h b/drivers/oprofile/oprof.h index cb92f5c98c1a..47e12cb4ee8b 100644 --- a/drivers/oprofile/oprof.h +++ b/drivers/oprofile/oprof.h | |||
| @@ -34,7 +34,8 @@ struct super_block; | |||
| 34 | struct dentry; | 34 | struct dentry; |
| 35 | 35 | ||
| 36 | void oprofile_create_files(struct super_block *sb, struct dentry *root); | 36 | void oprofile_create_files(struct super_block *sb, struct dentry *root); |
| 37 | void oprofile_timer_init(struct oprofile_operations *ops); | 37 | int oprofile_timer_init(struct oprofile_operations *ops); |
| 38 | void oprofile_timer_exit(void); | ||
| 38 | 39 | ||
| 39 | int oprofile_set_backtrace(unsigned long depth); | 40 | int oprofile_set_backtrace(unsigned long depth); |
| 40 | int oprofile_set_timeout(unsigned long time); | 41 | int oprofile_set_timeout(unsigned long time); |
diff --git a/drivers/oprofile/timer_int.c b/drivers/oprofile/timer_int.c index 333f915568c7..dc0ae4d14dff 100644 --- a/drivers/oprofile/timer_int.c +++ b/drivers/oprofile/timer_int.c | |||
| @@ -13,34 +13,94 @@ | |||
| 13 | #include <linux/oprofile.h> | 13 | #include <linux/oprofile.h> |
| 14 | #include <linux/profile.h> | 14 | #include <linux/profile.h> |
| 15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 16 | #include <linux/cpu.h> | ||
| 17 | #include <linux/hrtimer.h> | ||
| 18 | #include <asm/irq_regs.h> | ||
| 16 | #include <asm/ptrace.h> | 19 | #include <asm/ptrace.h> |
| 17 | 20 | ||
| 18 | #include "oprof.h" | 21 | #include "oprof.h" |
| 19 | 22 | ||
| 20 | static int timer_notify(struct pt_regs *regs) | 23 | static DEFINE_PER_CPU(struct hrtimer, oprofile_hrtimer); |
| 24 | |||
| 25 | static enum hrtimer_restart oprofile_hrtimer_notify(struct hrtimer *hrtimer) | ||
| 26 | { | ||
| 27 | oprofile_add_sample(get_irq_regs(), 0); | ||
| 28 | hrtimer_forward_now(hrtimer, ns_to_ktime(TICK_NSEC)); | ||
| 29 | return HRTIMER_RESTART; | ||
| 30 | } | ||
| 31 | |||
| 32 | static void __oprofile_hrtimer_start(void *unused) | ||
| 33 | { | ||
| 34 | struct hrtimer *hrtimer = &__get_cpu_var(oprofile_hrtimer); | ||
| 35 | |||
| 36 | hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | ||
| 37 | hrtimer->function = oprofile_hrtimer_notify; | ||
| 38 | |||
| 39 | hrtimer_start(hrtimer, ns_to_ktime(TICK_NSEC), | ||
| 40 | HRTIMER_MODE_REL_PINNED); | ||
| 41 | } | ||
| 42 | |||
| 43 | static int oprofile_hrtimer_start(void) | ||
| 21 | { | 44 | { |
| 22 | oprofile_add_sample(regs, 0); | 45 | on_each_cpu(__oprofile_hrtimer_start, NULL, 1); |
| 23 | return 0; | 46 | return 0; |
| 24 | } | 47 | } |
| 25 | 48 | ||
| 26 | static int timer_start(void) | 49 | static void __oprofile_hrtimer_stop(int cpu) |
| 27 | { | 50 | { |
| 28 | return register_timer_hook(timer_notify); | 51 | struct hrtimer *hrtimer = &per_cpu(oprofile_hrtimer, cpu); |
| 52 | |||
| 53 | hrtimer_cancel(hrtimer); | ||
| 29 | } | 54 | } |
| 30 | 55 | ||
| 56 | static void oprofile_hrtimer_stop(void) | ||
| 57 | { | ||
| 58 | int cpu; | ||
| 59 | |||
| 60 | for_each_online_cpu(cpu) | ||
| 61 | __oprofile_hrtimer_stop(cpu); | ||
| 62 | } | ||
| 31 | 63 | ||
| 32 | static void timer_stop(void) | 64 | static int __cpuinit oprofile_cpu_notify(struct notifier_block *self, |
| 65 | unsigned long action, void *hcpu) | ||
| 33 | { | 66 | { |
| 34 | unregister_timer_hook(timer_notify); | 67 | long cpu = (long) hcpu; |
| 68 | |||
| 69 | switch (action) { | ||
| 70 | case CPU_ONLINE: | ||
| 71 | case CPU_ONLINE_FROZEN: | ||
| 72 | smp_call_function_single(cpu, __oprofile_hrtimer_start, | ||
| 73 | NULL, 1); | ||
| 74 | break; | ||
| 75 | case CPU_DEAD: | ||
| 76 | case CPU_DEAD_FROZEN: | ||
| 77 | __oprofile_hrtimer_stop(cpu); | ||
| 78 | break; | ||
| 79 | } | ||
| 80 | return NOTIFY_OK; | ||
| 35 | } | 81 | } |
| 36 | 82 | ||
| 83 | static struct notifier_block __refdata oprofile_cpu_notifier = { | ||
| 84 | .notifier_call = oprofile_cpu_notify, | ||
| 85 | }; | ||
| 37 | 86 | ||
| 38 | void __init oprofile_timer_init(struct oprofile_operations *ops) | 87 | int __init oprofile_timer_init(struct oprofile_operations *ops) |
| 39 | { | 88 | { |
| 89 | int rc; | ||
| 90 | |||
| 91 | rc = register_hotcpu_notifier(&oprofile_cpu_notifier); | ||
| 92 | if (rc) | ||
| 93 | return rc; | ||
| 40 | ops->create_files = NULL; | 94 | ops->create_files = NULL; |
| 41 | ops->setup = NULL; | 95 | ops->setup = NULL; |
| 42 | ops->shutdown = NULL; | 96 | ops->shutdown = NULL; |
| 43 | ops->start = timer_start; | 97 | ops->start = oprofile_hrtimer_start; |
| 44 | ops->stop = timer_stop; | 98 | ops->stop = oprofile_hrtimer_stop; |
| 45 | ops->cpu_type = "timer"; | 99 | ops->cpu_type = "timer"; |
| 100 | return 0; | ||
| 101 | } | ||
| 102 | |||
| 103 | void __exit oprofile_timer_exit(void) | ||
| 104 | { | ||
| 105 | unregister_hotcpu_notifier(&oprofile_cpu_notifier); | ||
| 46 | } | 106 | } |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index 417312528ddf..371dc564e2e4 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -3626,14 +3626,15 @@ static void intel_iommu_detach_device(struct iommu_domain *domain, | |||
| 3626 | domain_remove_one_dev_info(dmar_domain, pdev); | 3626 | domain_remove_one_dev_info(dmar_domain, pdev); |
| 3627 | } | 3627 | } |
| 3628 | 3628 | ||
| 3629 | static int intel_iommu_map_range(struct iommu_domain *domain, | 3629 | static int intel_iommu_map(struct iommu_domain *domain, |
| 3630 | unsigned long iova, phys_addr_t hpa, | 3630 | unsigned long iova, phys_addr_t hpa, |
| 3631 | size_t size, int iommu_prot) | 3631 | int gfp_order, int iommu_prot) |
| 3632 | { | 3632 | { |
| 3633 | struct dmar_domain *dmar_domain = domain->priv; | 3633 | struct dmar_domain *dmar_domain = domain->priv; |
| 3634 | u64 max_addr; | 3634 | u64 max_addr; |
| 3635 | int addr_width; | 3635 | int addr_width; |
| 3636 | int prot = 0; | 3636 | int prot = 0; |
| 3637 | size_t size; | ||
| 3637 | int ret; | 3638 | int ret; |
| 3638 | 3639 | ||
| 3639 | if (iommu_prot & IOMMU_READ) | 3640 | if (iommu_prot & IOMMU_READ) |
| @@ -3643,6 +3644,7 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3643 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) | 3644 | if ((iommu_prot & IOMMU_CACHE) && dmar_domain->iommu_snooping) |
| 3644 | prot |= DMA_PTE_SNP; | 3645 | prot |= DMA_PTE_SNP; |
| 3645 | 3646 | ||
| 3647 | size = PAGE_SIZE << gfp_order; | ||
| 3646 | max_addr = iova + size; | 3648 | max_addr = iova + size; |
| 3647 | if (dmar_domain->max_addr < max_addr) { | 3649 | if (dmar_domain->max_addr < max_addr) { |
| 3648 | int min_agaw; | 3650 | int min_agaw; |
| @@ -3669,19 +3671,19 @@ static int intel_iommu_map_range(struct iommu_domain *domain, | |||
| 3669 | return ret; | 3671 | return ret; |
| 3670 | } | 3672 | } |
| 3671 | 3673 | ||
| 3672 | static void intel_iommu_unmap_range(struct iommu_domain *domain, | 3674 | static int intel_iommu_unmap(struct iommu_domain *domain, |
| 3673 | unsigned long iova, size_t size) | 3675 | unsigned long iova, int gfp_order) |
| 3674 | { | 3676 | { |
| 3675 | struct dmar_domain *dmar_domain = domain->priv; | 3677 | struct dmar_domain *dmar_domain = domain->priv; |
| 3676 | 3678 | size_t size = PAGE_SIZE << gfp_order; | |
| 3677 | if (!size) | ||
| 3678 | return; | ||
| 3679 | 3679 | ||
| 3680 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, | 3680 | dma_pte_clear_range(dmar_domain, iova >> VTD_PAGE_SHIFT, |
| 3681 | (iova + size - 1) >> VTD_PAGE_SHIFT); | 3681 | (iova + size - 1) >> VTD_PAGE_SHIFT); |
| 3682 | 3682 | ||
| 3683 | if (dmar_domain->max_addr == iova + size) | 3683 | if (dmar_domain->max_addr == iova + size) |
| 3684 | dmar_domain->max_addr = iova; | 3684 | dmar_domain->max_addr = iova; |
| 3685 | |||
| 3686 | return gfp_order; | ||
| 3685 | } | 3687 | } |
| 3686 | 3688 | ||
| 3687 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, | 3689 | static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain, |
| @@ -3714,8 +3716,8 @@ static struct iommu_ops intel_iommu_ops = { | |||
| 3714 | .domain_destroy = intel_iommu_domain_destroy, | 3716 | .domain_destroy = intel_iommu_domain_destroy, |
| 3715 | .attach_dev = intel_iommu_attach_device, | 3717 | .attach_dev = intel_iommu_attach_device, |
| 3716 | .detach_dev = intel_iommu_detach_device, | 3718 | .detach_dev = intel_iommu_detach_device, |
| 3717 | .map = intel_iommu_map_range, | 3719 | .map = intel_iommu_map, |
| 3718 | .unmap = intel_iommu_unmap_range, | 3720 | .unmap = intel_iommu_unmap, |
| 3719 | .iova_to_phys = intel_iommu_iova_to_phys, | 3721 | .iova_to_phys = intel_iommu_iova_to_phys, |
| 3720 | .domain_has_cap = intel_iommu_domain_has_cap, | 3722 | .domain_has_cap = intel_iommu_domain_has_cap, |
| 3721 | }; | 3723 | }; |
diff --git a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c index 4fe36d2e1049..19b111383f62 100644 --- a/drivers/pci/setup-bus.c +++ b/drivers/pci/setup-bus.c | |||
| @@ -838,65 +838,11 @@ static void pci_bus_dump_resources(struct pci_bus *bus) | |||
| 838 | } | 838 | } |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | static int __init pci_bus_get_depth(struct pci_bus *bus) | ||
| 842 | { | ||
| 843 | int depth = 0; | ||
| 844 | struct pci_dev *dev; | ||
| 845 | |||
| 846 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 847 | int ret; | ||
| 848 | struct pci_bus *b = dev->subordinate; | ||
| 849 | if (!b) | ||
| 850 | continue; | ||
| 851 | |||
| 852 | ret = pci_bus_get_depth(b); | ||
| 853 | if (ret + 1 > depth) | ||
| 854 | depth = ret + 1; | ||
| 855 | } | ||
| 856 | |||
| 857 | return depth; | ||
| 858 | } | ||
| 859 | static int __init pci_get_max_depth(void) | ||
| 860 | { | ||
| 861 | int depth = 0; | ||
| 862 | struct pci_bus *bus; | ||
| 863 | |||
| 864 | list_for_each_entry(bus, &pci_root_buses, node) { | ||
| 865 | int ret; | ||
| 866 | |||
| 867 | ret = pci_bus_get_depth(bus); | ||
| 868 | if (ret > depth) | ||
| 869 | depth = ret; | ||
| 870 | } | ||
| 871 | |||
| 872 | return depth; | ||
| 873 | } | ||
| 874 | |||
| 875 | /* | ||
| 876 | * first try will not touch pci bridge res | ||
| 877 | * second and later try will clear small leaf bridge res | ||
| 878 | * will stop till to the max deepth if can not find good one | ||
| 879 | */ | ||
| 880 | void __init | 841 | void __init |
| 881 | pci_assign_unassigned_resources(void) | 842 | pci_assign_unassigned_resources(void) |
| 882 | { | 843 | { |
| 883 | struct pci_bus *bus; | 844 | struct pci_bus *bus; |
| 884 | int tried_times = 0; | ||
| 885 | enum release_type rel_type = leaf_only; | ||
| 886 | struct resource_list_x head, *list; | ||
| 887 | unsigned long type_mask = IORESOURCE_IO | IORESOURCE_MEM | | ||
| 888 | IORESOURCE_PREFETCH; | ||
| 889 | unsigned long failed_type; | ||
| 890 | int max_depth = pci_get_max_depth(); | ||
| 891 | int pci_try_num; | ||
| 892 | 845 | ||
| 893 | head.next = NULL; | ||
| 894 | |||
| 895 | pci_try_num = max_depth + 1; | ||
| 896 | printk(KERN_DEBUG "PCI: max bus depth: %d pci_try_num: %d\n", | ||
| 897 | max_depth, pci_try_num); | ||
| 898 | |||
| 899 | again: | ||
| 900 | /* Depth first, calculate sizes and alignments of all | 846 | /* Depth first, calculate sizes and alignments of all |
| 901 | subordinate buses. */ | 847 | subordinate buses. */ |
| 902 | list_for_each_entry(bus, &pci_root_buses, node) { | 848 | list_for_each_entry(bus, &pci_root_buses, node) { |
| @@ -904,65 +850,9 @@ again: | |||
| 904 | } | 850 | } |
| 905 | /* Depth last, allocate resources and update the hardware. */ | 851 | /* Depth last, allocate resources and update the hardware. */ |
| 906 | list_for_each_entry(bus, &pci_root_buses, node) { | 852 | list_for_each_entry(bus, &pci_root_buses, node) { |
| 907 | __pci_bus_assign_resources(bus, &head); | 853 | pci_bus_assign_resources(bus); |
| 908 | } | ||
| 909 | tried_times++; | ||
| 910 | |||
| 911 | /* any device complain? */ | ||
| 912 | if (!head.next) | ||
| 913 | goto enable_and_dump; | ||
| 914 | failed_type = 0; | ||
| 915 | for (list = head.next; list;) { | ||
| 916 | failed_type |= list->flags; | ||
| 917 | list = list->next; | ||
| 918 | } | ||
| 919 | /* | ||
| 920 | * io port are tight, don't try extra | ||
| 921 | * or if reach the limit, don't want to try more | ||
| 922 | */ | ||
| 923 | failed_type &= type_mask; | ||
| 924 | if ((failed_type == IORESOURCE_IO) || (tried_times >= pci_try_num)) { | ||
| 925 | free_failed_list(&head); | ||
| 926 | goto enable_and_dump; | ||
| 927 | } | ||
| 928 | |||
| 929 | printk(KERN_DEBUG "PCI: No. %d try to assign unassigned res\n", | ||
| 930 | tried_times + 1); | ||
| 931 | |||
| 932 | /* third times and later will not check if it is leaf */ | ||
| 933 | if ((tried_times + 1) > 2) | ||
| 934 | rel_type = whole_subtree; | ||
| 935 | |||
| 936 | /* | ||
| 937 | * Try to release leaf bridge's resources that doesn't fit resource of | ||
| 938 | * child device under that bridge | ||
| 939 | */ | ||
| 940 | for (list = head.next; list;) { | ||
| 941 | bus = list->dev->bus; | ||
| 942 | pci_bus_release_bridge_resources(bus, list->flags & type_mask, | ||
| 943 | rel_type); | ||
| 944 | list = list->next; | ||
| 945 | } | ||
| 946 | /* restore size and flags */ | ||
| 947 | for (list = head.next; list;) { | ||
| 948 | struct resource *res = list->res; | ||
| 949 | |||
| 950 | res->start = list->start; | ||
| 951 | res->end = list->end; | ||
| 952 | res->flags = list->flags; | ||
| 953 | if (list->dev->subordinate) | ||
| 954 | res->flags = 0; | ||
| 955 | |||
| 956 | list = list->next; | ||
| 957 | } | ||
| 958 | free_failed_list(&head); | ||
| 959 | |||
| 960 | goto again; | ||
| 961 | |||
| 962 | enable_and_dump: | ||
| 963 | /* Depth last, update the hardware. */ | ||
| 964 | list_for_each_entry(bus, &pci_root_buses, node) | ||
| 965 | pci_enable_bridges(bus); | 854 | pci_enable_bridges(bus); |
| 855 | } | ||
| 966 | 856 | ||
| 967 | /* dump the resource on buses */ | 857 | /* dump the resource on buses */ |
| 968 | list_for_each_entry(bus, &pci_root_buses, node) { | 858 | list_for_each_entry(bus, &pci_root_buses, node) { |
diff --git a/drivers/pcmcia/Kconfig b/drivers/pcmcia/Kconfig index d189e4743e69..a44733d44ca1 100644 --- a/drivers/pcmcia/Kconfig +++ b/drivers/pcmcia/Kconfig | |||
| @@ -234,7 +234,8 @@ config PCMCIA_PXA2XX | |||
| 234 | depends on ARM && ARCH_PXA && PCMCIA | 234 | depends on ARM && ARCH_PXA && PCMCIA |
| 235 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ | 235 | depends on (ARCH_LUBBOCK || MACH_MAINSTONE || PXA_SHARPSL \ |
| 236 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ | 236 | || MACH_ARMCORE || ARCH_PXA_PALM || TRIZEPS_PCMCIA \ |
| 237 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2) | 237 | || ARCOM_PCMCIA || ARCH_PXA_ESERIES || MACH_STARGATE2 \ |
| 238 | || MACH_VPAC270) | ||
| 238 | select PCMCIA_SOC_COMMON | 239 | select PCMCIA_SOC_COMMON |
| 239 | help | 240 | help |
| 240 | Say Y here to include support for the PXA2xx PCMCIA controller | 241 | Say Y here to include support for the PXA2xx PCMCIA controller |
diff --git a/drivers/pcmcia/Makefile b/drivers/pcmcia/Makefile index 381b031d9d75..4dae3613c458 100644 --- a/drivers/pcmcia/Makefile +++ b/drivers/pcmcia/Makefile | |||
| @@ -66,6 +66,7 @@ pxa2xx-obj-$(CONFIG_MACH_PALMTC) += pxa2xx_palmtc.o | |||
| 66 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o | 66 | pxa2xx-obj-$(CONFIG_MACH_PALMLD) += pxa2xx_palmld.o |
| 67 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o | 67 | pxa2xx-obj-$(CONFIG_MACH_E740) += pxa2xx_e740.o |
| 68 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o | 68 | pxa2xx-obj-$(CONFIG_MACH_STARGATE2) += pxa2xx_stargate2.o |
| 69 | pxa2xx-obj-$(CONFIG_MACH_VPAC270) += pxa2xx_vpac270.o | ||
| 69 | 70 | ||
| 70 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) | 71 | obj-$(CONFIG_PCMCIA_PXA2XX) += pxa2xx_base.o $(pxa2xx-obj-y) |
| 71 | 72 | ||
diff --git a/drivers/pcmcia/cs.c b/drivers/pcmcia/cs.c index 75ed866e6953..c3383750e333 100644 --- a/drivers/pcmcia/cs.c +++ b/drivers/pcmcia/cs.c | |||
| @@ -671,20 +671,22 @@ static int pccardd(void *__skt) | |||
| 671 | socket_remove(skt); | 671 | socket_remove(skt); |
| 672 | if (sysfs_events & PCMCIA_UEVENT_INSERT) | 672 | if (sysfs_events & PCMCIA_UEVENT_INSERT) |
| 673 | socket_insert(skt); | 673 | socket_insert(skt); |
| 674 | if ((sysfs_events & PCMCIA_UEVENT_RESUME) && | ||
| 675 | !(skt->state & SOCKET_CARDBUS)) { | ||
| 676 | ret = socket_resume(skt); | ||
| 677 | if (!ret && skt->callback) | ||
| 678 | skt->callback->resume(skt); | ||
| 679 | } | ||
| 680 | if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) && | 674 | if ((sysfs_events & PCMCIA_UEVENT_SUSPEND) && |
| 681 | !(skt->state & SOCKET_CARDBUS)) { | 675 | !(skt->state & SOCKET_CARDBUS)) { |
| 682 | if (skt->callback) | 676 | if (skt->callback) |
| 683 | ret = skt->callback->suspend(skt); | 677 | ret = skt->callback->suspend(skt); |
| 684 | else | 678 | else |
| 685 | ret = 0; | 679 | ret = 0; |
| 686 | if (!ret) | 680 | if (!ret) { |
| 687 | socket_suspend(skt); | 681 | socket_suspend(skt); |
| 682 | msleep(100); | ||
| 683 | } | ||
| 684 | } | ||
| 685 | if ((sysfs_events & PCMCIA_UEVENT_RESUME) && | ||
| 686 | !(skt->state & SOCKET_CARDBUS)) { | ||
| 687 | ret = socket_resume(skt); | ||
| 688 | if (!ret && skt->callback) | ||
| 689 | skt->callback->resume(skt); | ||
| 688 | } | 690 | } |
| 689 | if ((sysfs_events & PCMCIA_UEVENT_REQUERY) && | 691 | if ((sysfs_events & PCMCIA_UEVENT_REQUERY) && |
| 690 | !(skt->state & SOCKET_CARDBUS)) { | 692 | !(skt->state & SOCKET_CARDBUS)) { |
diff --git a/drivers/pcmcia/ds.c b/drivers/pcmcia/ds.c index 508f94a2a78d..041eee43fd8d 100644 --- a/drivers/pcmcia/ds.c +++ b/drivers/pcmcia/ds.c | |||
| @@ -1283,6 +1283,7 @@ static int ds_event(struct pcmcia_socket *skt, event_t event, int priority) | |||
| 1283 | destroy_cis_cache(skt); | 1283 | destroy_cis_cache(skt); |
| 1284 | kfree(skt->fake_cis); | 1284 | kfree(skt->fake_cis); |
| 1285 | skt->fake_cis = NULL; | 1285 | skt->fake_cis = NULL; |
| 1286 | s->functions = 0; | ||
| 1286 | mutex_unlock(&s->ops_mutex); | 1287 | mutex_unlock(&s->ops_mutex); |
| 1287 | /* now, add the new card */ | 1288 | /* now, add the new card */ |
| 1288 | ds_event(skt, CS_EVENT_CARD_INSERTION, | 1289 | ds_event(skt, CS_EVENT_CARD_INSERTION, |
diff --git a/drivers/pcmcia/pcmcia_ioctl.c b/drivers/pcmcia/pcmcia_ioctl.c index 104e73d5d86c..7631faa0cadd 100644 --- a/drivers/pcmcia/pcmcia_ioctl.c +++ b/drivers/pcmcia/pcmcia_ioctl.c | |||
| @@ -711,7 +711,7 @@ static int ds_open(struct inode *inode, struct file *file) | |||
| 711 | warning_printed = 1; | 711 | warning_printed = 1; |
| 712 | } | 712 | } |
| 713 | 713 | ||
| 714 | if (s->pcmcia_state.present) | 714 | if (atomic_read(&s->present)) |
| 715 | queue_event(user, CS_EVENT_CARD_INSERTION); | 715 | queue_event(user, CS_EVENT_CARD_INSERTION); |
| 716 | out: | 716 | out: |
| 717 | unlock_kernel(); | 717 | unlock_kernel(); |
| @@ -770,9 +770,6 @@ static ssize_t ds_read(struct file *file, char __user *buf, | |||
| 770 | return -EIO; | 770 | return -EIO; |
| 771 | 771 | ||
| 772 | s = user->socket; | 772 | s = user->socket; |
| 773 | if (s->pcmcia_state.dead) | ||
| 774 | return -EIO; | ||
| 775 | |||
| 776 | ret = wait_event_interruptible(s->queue, !queue_empty(user)); | 773 | ret = wait_event_interruptible(s->queue, !queue_empty(user)); |
| 777 | if (ret == 0) | 774 | if (ret == 0) |
| 778 | ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; | 775 | ret = put_user(get_queued_event(user), (int __user *)buf) ? -EFAULT : 4; |
| @@ -838,8 +835,6 @@ static int ds_ioctl(struct inode *inode, struct file *file, | |||
| 838 | return -EIO; | 835 | return -EIO; |
| 839 | 836 | ||
| 840 | s = user->socket; | 837 | s = user->socket; |
| 841 | if (s->pcmcia_state.dead) | ||
| 842 | return -EIO; | ||
| 843 | 838 | ||
| 844 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; | 839 | size = (cmd & IOCSIZE_MASK) >> IOCSIZE_SHIFT; |
| 845 | if (size > sizeof(ds_ioctl_arg_t)) | 840 | if (size > sizeof(ds_ioctl_arg_t)) |
diff --git a/drivers/pcmcia/pxa2xx_vpac270.c b/drivers/pcmcia/pxa2xx_vpac270.c new file mode 100644 index 000000000000..55627eccee8e --- /dev/null +++ b/drivers/pcmcia/pxa2xx_vpac270.c | |||
| @@ -0,0 +1,229 @@ | |||
| 1 | /* | ||
| 2 | * linux/drivers/pcmcia/pxa2xx_vpac270.c | ||
| 3 | * | ||
| 4 | * Driver for Voipac PXA270 PCMCIA and CF sockets | ||
| 5 | * | ||
| 6 | * Copyright (C) 2010 | ||
| 7 | * Marek Vasut <marek.vasut@gmail.com> | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License version 2 as | ||
| 11 | * published by the Free Software Foundation. | ||
| 12 | * | ||
| 13 | */ | ||
| 14 | |||
| 15 | #include <linux/module.h> | ||
| 16 | #include <linux/platform_device.h> | ||
| 17 | |||
| 18 | #include <asm/mach-types.h> | ||
| 19 | |||
| 20 | #include <mach/gpio.h> | ||
| 21 | #include <mach/vpac270.h> | ||
| 22 | |||
| 23 | #include "soc_common.h" | ||
| 24 | |||
| 25 | static struct pcmcia_irqs cd_irqs[] = { | ||
| 26 | { | ||
| 27 | .sock = 0, | ||
| 28 | .irq = IRQ_GPIO(GPIO84_VPAC270_PCMCIA_CD), | ||
| 29 | .str = "PCMCIA CD" | ||
| 30 | }, | ||
| 31 | { | ||
| 32 | .sock = 1, | ||
| 33 | .irq = IRQ_GPIO(GPIO17_VPAC270_CF_CD), | ||
| 34 | .str = "CF CD" | ||
| 35 | }, | ||
| 36 | }; | ||
| 37 | |||
| 38 | static int vpac270_pcmcia_hw_init(struct soc_pcmcia_socket *skt) | ||
| 39 | { | ||
| 40 | int ret; | ||
| 41 | |||
| 42 | if (skt->nr == 0) { | ||
| 43 | ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD"); | ||
| 44 | if (ret) | ||
| 45 | goto err1; | ||
| 46 | ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD); | ||
| 47 | if (ret) | ||
| 48 | goto err2; | ||
| 49 | |||
| 50 | ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY"); | ||
| 51 | if (ret) | ||
| 52 | goto err2; | ||
| 53 | ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 54 | if (ret) | ||
| 55 | goto err3; | ||
| 56 | |||
| 57 | ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN"); | ||
| 58 | if (ret) | ||
| 59 | goto err3; | ||
| 60 | ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0); | ||
| 61 | if (ret) | ||
| 62 | goto err4; | ||
| 63 | |||
| 64 | ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET"); | ||
| 65 | if (ret) | ||
| 66 | goto err4; | ||
| 67 | ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0); | ||
| 68 | if (ret) | ||
| 69 | goto err5; | ||
| 70 | |||
| 71 | skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 72 | |||
| 73 | return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1); | ||
| 74 | |||
| 75 | err5: | ||
| 76 | gpio_free(GPIO11_VPAC270_PCMCIA_RESET); | ||
| 77 | err4: | ||
| 78 | gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); | ||
| 79 | err3: | ||
| 80 | gpio_free(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 81 | err2: | ||
| 82 | gpio_free(GPIO84_VPAC270_PCMCIA_CD); | ||
| 83 | err1: | ||
| 84 | return ret; | ||
| 85 | |||
| 86 | } else { | ||
| 87 | ret = gpio_request(GPIO17_VPAC270_CF_CD, "CF CD"); | ||
| 88 | if (ret) | ||
| 89 | goto err6; | ||
| 90 | ret = gpio_direction_input(GPIO17_VPAC270_CF_CD); | ||
| 91 | if (ret) | ||
| 92 | goto err7; | ||
| 93 | |||
| 94 | ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY"); | ||
| 95 | if (ret) | ||
| 96 | goto err7; | ||
| 97 | ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY); | ||
| 98 | if (ret) | ||
| 99 | goto err8; | ||
| 100 | |||
| 101 | ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET"); | ||
| 102 | if (ret) | ||
| 103 | goto err8; | ||
| 104 | ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0); | ||
| 105 | if (ret) | ||
| 106 | goto err9; | ||
| 107 | |||
| 108 | skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY); | ||
| 109 | |||
| 110 | return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1); | ||
| 111 | |||
| 112 | err9: | ||
| 113 | gpio_free(GPIO16_VPAC270_CF_RESET); | ||
| 114 | err8: | ||
| 115 | gpio_free(GPIO12_VPAC270_CF_RDY); | ||
| 116 | err7: | ||
| 117 | gpio_free(GPIO17_VPAC270_CF_CD); | ||
| 118 | err6: | ||
| 119 | return ret; | ||
| 120 | |||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 124 | static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt) | ||
| 125 | { | ||
| 126 | gpio_free(GPIO11_VPAC270_PCMCIA_RESET); | ||
| 127 | gpio_free(GPIO107_VPAC270_PCMCIA_PPEN); | ||
| 128 | gpio_free(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 129 | gpio_free(GPIO84_VPAC270_PCMCIA_CD); | ||
| 130 | gpio_free(GPIO16_VPAC270_CF_RESET); | ||
| 131 | gpio_free(GPIO12_VPAC270_CF_RDY); | ||
| 132 | gpio_free(GPIO17_VPAC270_CF_CD); | ||
| 133 | } | ||
| 134 | |||
| 135 | static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt, | ||
| 136 | struct pcmcia_state *state) | ||
| 137 | { | ||
| 138 | if (skt->nr == 0) { | ||
| 139 | state->detect = !gpio_get_value(GPIO84_VPAC270_PCMCIA_CD); | ||
| 140 | state->ready = !!gpio_get_value(GPIO35_VPAC270_PCMCIA_RDY); | ||
| 141 | } else { | ||
| 142 | state->detect = !gpio_get_value(GPIO17_VPAC270_CF_CD); | ||
| 143 | state->ready = !!gpio_get_value(GPIO12_VPAC270_CF_RDY); | ||
| 144 | } | ||
| 145 | state->bvd1 = 1; | ||
| 146 | state->bvd2 = 1; | ||
| 147 | state->wrprot = 0; | ||
| 148 | state->vs_3v = 1; | ||
| 149 | state->vs_Xv = 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static int | ||
| 153 | vpac270_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, | ||
| 154 | const socket_state_t *state) | ||
| 155 | { | ||
| 156 | if (skt->nr == 0) { | ||
| 157 | gpio_set_value(GPIO11_VPAC270_PCMCIA_RESET, | ||
| 158 | (state->flags & SS_RESET)); | ||
| 159 | gpio_set_value(GPIO107_VPAC270_PCMCIA_PPEN, | ||
| 160 | !(state->Vcc == 33 || state->Vcc == 50)); | ||
| 161 | } else { | ||
| 162 | gpio_set_value(GPIO16_VPAC270_CF_RESET, | ||
| 163 | (state->flags & SS_RESET)); | ||
| 164 | } | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | } | ||
| 168 | |||
| 169 | static void vpac270_pcmcia_socket_init(struct soc_pcmcia_socket *skt) | ||
| 170 | { | ||
| 171 | } | ||
| 172 | |||
| 173 | static void vpac270_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt) | ||
| 174 | { | ||
| 175 | } | ||
| 176 | |||
| 177 | static struct pcmcia_low_level vpac270_pcmcia_ops = { | ||
| 178 | .owner = THIS_MODULE, | ||
| 179 | |||
| 180 | .first = 0, | ||
| 181 | .nr = 2, | ||
| 182 | |||
| 183 | .hw_init = vpac270_pcmcia_hw_init, | ||
| 184 | .hw_shutdown = vpac270_pcmcia_hw_shutdown, | ||
| 185 | |||
| 186 | .socket_state = vpac270_pcmcia_socket_state, | ||
| 187 | .configure_socket = vpac270_pcmcia_configure_socket, | ||
| 188 | |||
| 189 | .socket_init = vpac270_pcmcia_socket_init, | ||
| 190 | .socket_suspend = vpac270_pcmcia_socket_suspend, | ||
| 191 | }; | ||
| 192 | |||
| 193 | static struct platform_device *vpac270_pcmcia_device; | ||
| 194 | |||
| 195 | static int __init vpac270_pcmcia_init(void) | ||
| 196 | { | ||
| 197 | int ret; | ||
| 198 | |||
| 199 | if (!machine_is_vpac270()) | ||
| 200 | return -ENODEV; | ||
| 201 | |||
| 202 | vpac270_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1); | ||
| 203 | if (!vpac270_pcmcia_device) | ||
| 204 | return -ENOMEM; | ||
| 205 | |||
| 206 | ret = platform_device_add_data(vpac270_pcmcia_device, | ||
| 207 | &vpac270_pcmcia_ops, sizeof(vpac270_pcmcia_ops)); | ||
| 208 | |||
| 209 | if (!ret) | ||
| 210 | ret = platform_device_add(vpac270_pcmcia_device); | ||
| 211 | |||
| 212 | if (ret) | ||
| 213 | platform_device_put(vpac270_pcmcia_device); | ||
| 214 | |||
| 215 | return ret; | ||
| 216 | } | ||
| 217 | |||
| 218 | static void __exit vpac270_pcmcia_exit(void) | ||
| 219 | { | ||
| 220 | platform_device_unregister(vpac270_pcmcia_device); | ||
| 221 | } | ||
| 222 | |||
| 223 | module_init(vpac270_pcmcia_init); | ||
| 224 | module_exit(vpac270_pcmcia_exit); | ||
| 225 | |||
| 226 | MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>"); | ||
| 227 | MODULE_DESCRIPTION("PCMCIA support for Voipac PXA270"); | ||
| 228 | MODULE_ALIAS("platform:pxa2xx-pcmcia"); | ||
| 229 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index 35bb44af49b3..100e4d9372f1 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
| @@ -274,26 +274,6 @@ static void pnpacpi_parse_allocated_busresource(struct pnp_dev *dev, | |||
| 274 | pnp_add_bus_resource(dev, start, end); | 274 | pnp_add_bus_resource(dev, start, end); |
| 275 | } | 275 | } |
| 276 | 276 | ||
| 277 | static u64 addr_space_length(struct pnp_dev *dev, u64 min, u64 max, u64 len) | ||
| 278 | { | ||
| 279 | u64 max_len; | ||
| 280 | |||
| 281 | max_len = max - min + 1; | ||
| 282 | if (len <= max_len) | ||
| 283 | return len; | ||
| 284 | |||
| 285 | /* | ||
| 286 | * Per 6.4.3.5, _LEN cannot exceed _MAX - _MIN + 1, but some BIOSes | ||
| 287 | * don't do this correctly, e.g., | ||
| 288 | * https://bugzilla.kernel.org/show_bug.cgi?id=15480 | ||
| 289 | */ | ||
| 290 | dev_info(&dev->dev, | ||
| 291 | "resource length %#llx doesn't fit in %#llx-%#llx, trimming\n", | ||
| 292 | (unsigned long long) len, (unsigned long long) min, | ||
| 293 | (unsigned long long) max); | ||
| 294 | return max_len; | ||
| 295 | } | ||
| 296 | |||
| 297 | static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, | 277 | static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, |
| 298 | struct acpi_resource *res) | 278 | struct acpi_resource *res) |
| 299 | { | 279 | { |
| @@ -309,7 +289,8 @@ static void pnpacpi_parse_allocated_address_space(struct pnp_dev *dev, | |||
| 309 | return; | 289 | return; |
| 310 | } | 290 | } |
| 311 | 291 | ||
| 312 | len = addr_space_length(dev, p->minimum, p->maximum, p->address_length); | 292 | /* Windows apparently computes length rather than using _LEN */ |
| 293 | len = p->maximum - p->minimum + 1; | ||
| 313 | window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; | 294 | window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; |
| 314 | 295 | ||
| 315 | if (p->resource_type == ACPI_MEMORY_RANGE) | 296 | if (p->resource_type == ACPI_MEMORY_RANGE) |
| @@ -330,7 +311,8 @@ static void pnpacpi_parse_allocated_ext_address_space(struct pnp_dev *dev, | |||
| 330 | int window; | 311 | int window; |
| 331 | u64 len; | 312 | u64 len; |
| 332 | 313 | ||
| 333 | len = addr_space_length(dev, p->minimum, p->maximum, p->address_length); | 314 | /* Windows apparently computes length rather than using _LEN */ |
| 315 | len = p->maximum - p->minimum + 1; | ||
| 334 | window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; | 316 | window = (p->producer_consumer == ACPI_PRODUCER) ? 1 : 0; |
| 335 | 317 | ||
| 336 | if (p->resource_type == ACPI_MEMORY_RANGE) | 318 | if (p->resource_type == ACPI_MEMORY_RANGE) |
diff --git a/drivers/pnp/resource.c b/drivers/pnp/resource.c index 2e54e6a23c72..e3446ab8b563 100644 --- a/drivers/pnp/resource.c +++ b/drivers/pnp/resource.c | |||
| @@ -211,6 +211,8 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res) | |||
| 211 | if (tres->flags & IORESOURCE_IO) { | 211 | if (tres->flags & IORESOURCE_IO) { |
| 212 | if (cannot_compare(tres->flags)) | 212 | if (cannot_compare(tres->flags)) |
| 213 | continue; | 213 | continue; |
| 214 | if (tres->flags & IORESOURCE_WINDOW) | ||
| 215 | continue; | ||
| 214 | tport = &tres->start; | 216 | tport = &tres->start; |
| 215 | tend = &tres->end; | 217 | tend = &tres->end; |
| 216 | if (ranged_conflict(port, end, tport, tend)) | 218 | if (ranged_conflict(port, end, tport, tend)) |
| @@ -271,6 +273,8 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res) | |||
| 271 | if (tres->flags & IORESOURCE_MEM) { | 273 | if (tres->flags & IORESOURCE_MEM) { |
| 272 | if (cannot_compare(tres->flags)) | 274 | if (cannot_compare(tres->flags)) |
| 273 | continue; | 275 | continue; |
| 276 | if (tres->flags & IORESOURCE_WINDOW) | ||
| 277 | continue; | ||
| 274 | taddr = &tres->start; | 278 | taddr = &tres->start; |
| 275 | tend = &tres->end; | 279 | tend = &tres->end; |
| 276 | if (ranged_conflict(addr, end, taddr, tend)) | 280 | if (ranged_conflict(addr, end, taddr, tend)) |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index acf222f91f5a..0e86247d791e 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -37,6 +37,9 @@ | |||
| 37 | */ | 37 | */ |
| 38 | #define DASD_CHANQ_MAX_SIZE 4 | 38 | #define DASD_CHANQ_MAX_SIZE 4 |
| 39 | 39 | ||
| 40 | #define DASD_SLEEPON_START_TAG (void *) 1 | ||
| 41 | #define DASD_SLEEPON_END_TAG (void *) 2 | ||
| 42 | |||
| 40 | /* | 43 | /* |
| 41 | * SECTION: exported variables of dasd.c | 44 | * SECTION: exported variables of dasd.c |
| 42 | */ | 45 | */ |
| @@ -62,6 +65,7 @@ static void dasd_device_tasklet(struct dasd_device *); | |||
| 62 | static void dasd_block_tasklet(struct dasd_block *); | 65 | static void dasd_block_tasklet(struct dasd_block *); |
| 63 | static void do_kick_device(struct work_struct *); | 66 | static void do_kick_device(struct work_struct *); |
| 64 | static void do_restore_device(struct work_struct *); | 67 | static void do_restore_device(struct work_struct *); |
| 68 | static void do_reload_device(struct work_struct *); | ||
| 65 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); | 69 | static void dasd_return_cqr_cb(struct dasd_ccw_req *, void *); |
| 66 | static void dasd_device_timeout(unsigned long); | 70 | static void dasd_device_timeout(unsigned long); |
| 67 | static void dasd_block_timeout(unsigned long); | 71 | static void dasd_block_timeout(unsigned long); |
| @@ -112,6 +116,7 @@ struct dasd_device *dasd_alloc_device(void) | |||
| 112 | device->timer.data = (unsigned long) device; | 116 | device->timer.data = (unsigned long) device; |
| 113 | INIT_WORK(&device->kick_work, do_kick_device); | 117 | INIT_WORK(&device->kick_work, do_kick_device); |
| 114 | INIT_WORK(&device->restore_device, do_restore_device); | 118 | INIT_WORK(&device->restore_device, do_restore_device); |
| 119 | INIT_WORK(&device->reload_device, do_reload_device); | ||
| 115 | device->state = DASD_STATE_NEW; | 120 | device->state = DASD_STATE_NEW; |
| 116 | device->target = DASD_STATE_NEW; | 121 | device->target = DASD_STATE_NEW; |
| 117 | mutex_init(&device->state_mutex); | 122 | mutex_init(&device->state_mutex); |
| @@ -518,6 +523,26 @@ void dasd_kick_device(struct dasd_device *device) | |||
| 518 | } | 523 | } |
| 519 | 524 | ||
| 520 | /* | 525 | /* |
| 526 | * dasd_reload_device will schedule a call do do_reload_device to the kernel | ||
| 527 | * event daemon. | ||
| 528 | */ | ||
| 529 | static void do_reload_device(struct work_struct *work) | ||
| 530 | { | ||
| 531 | struct dasd_device *device = container_of(work, struct dasd_device, | ||
| 532 | reload_device); | ||
| 533 | device->discipline->reload(device); | ||
| 534 | dasd_put_device(device); | ||
| 535 | } | ||
| 536 | |||
| 537 | void dasd_reload_device(struct dasd_device *device) | ||
| 538 | { | ||
| 539 | dasd_get_device(device); | ||
| 540 | /* queue call to dasd_reload_device to the kernel event daemon. */ | ||
| 541 | schedule_work(&device->reload_device); | ||
| 542 | } | ||
| 543 | EXPORT_SYMBOL(dasd_reload_device); | ||
| 544 | |||
| 545 | /* | ||
| 521 | * dasd_restore_device will schedule a call do do_restore_device to the kernel | 546 | * dasd_restore_device will schedule a call do do_restore_device to the kernel |
| 522 | * event daemon. | 547 | * event daemon. |
| 523 | */ | 548 | */ |
| @@ -1472,7 +1497,10 @@ void dasd_add_request_tail(struct dasd_ccw_req *cqr) | |||
| 1472 | */ | 1497 | */ |
| 1473 | static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data) | 1498 | static void dasd_wakeup_cb(struct dasd_ccw_req *cqr, void *data) |
| 1474 | { | 1499 | { |
| 1475 | wake_up((wait_queue_head_t *) data); | 1500 | spin_lock_irq(get_ccwdev_lock(cqr->startdev->cdev)); |
| 1501 | cqr->callback_data = DASD_SLEEPON_END_TAG; | ||
| 1502 | spin_unlock_irq(get_ccwdev_lock(cqr->startdev->cdev)); | ||
| 1503 | wake_up(&generic_waitq); | ||
| 1476 | } | 1504 | } |
| 1477 | 1505 | ||
| 1478 | static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) | 1506 | static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) |
| @@ -1482,10 +1510,7 @@ static inline int _wait_for_wakeup(struct dasd_ccw_req *cqr) | |||
| 1482 | 1510 | ||
| 1483 | device = cqr->startdev; | 1511 | device = cqr->startdev; |
| 1484 | spin_lock_irq(get_ccwdev_lock(device->cdev)); | 1512 | spin_lock_irq(get_ccwdev_lock(device->cdev)); |
| 1485 | rc = ((cqr->status == DASD_CQR_DONE || | 1513 | rc = (cqr->callback_data == DASD_SLEEPON_END_TAG); |
| 1486 | cqr->status == DASD_CQR_NEED_ERP || | ||
| 1487 | cqr->status == DASD_CQR_TERMINATED) && | ||
| 1488 | list_empty(&cqr->devlist)); | ||
| 1489 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); | 1514 | spin_unlock_irq(get_ccwdev_lock(device->cdev)); |
| 1490 | return rc; | 1515 | return rc; |
| 1491 | } | 1516 | } |
| @@ -1573,7 +1598,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible) | |||
| 1573 | wait_event(generic_waitq, !(device->stopped)); | 1598 | wait_event(generic_waitq, !(device->stopped)); |
| 1574 | 1599 | ||
| 1575 | cqr->callback = dasd_wakeup_cb; | 1600 | cqr->callback = dasd_wakeup_cb; |
| 1576 | cqr->callback_data = (void *) &generic_waitq; | 1601 | cqr->callback_data = DASD_SLEEPON_START_TAG; |
| 1577 | dasd_add_request_tail(cqr); | 1602 | dasd_add_request_tail(cqr); |
| 1578 | if (interruptible) { | 1603 | if (interruptible) { |
| 1579 | rc = wait_event_interruptible( | 1604 | rc = wait_event_interruptible( |
| @@ -1652,7 +1677,7 @@ int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr) | |||
| 1652 | } | 1677 | } |
| 1653 | 1678 | ||
| 1654 | cqr->callback = dasd_wakeup_cb; | 1679 | cqr->callback = dasd_wakeup_cb; |
| 1655 | cqr->callback_data = (void *) &generic_waitq; | 1680 | cqr->callback_data = DASD_SLEEPON_START_TAG; |
| 1656 | cqr->status = DASD_CQR_QUEUED; | 1681 | cqr->status = DASD_CQR_QUEUED; |
| 1657 | list_add(&cqr->devlist, &device->ccw_queue); | 1682 | list_add(&cqr->devlist, &device->ccw_queue); |
| 1658 | 1683 | ||
diff --git a/drivers/s390/block/dasd_3990_erp.c b/drivers/s390/block/dasd_3990_erp.c index 6632649dd6aa..85bfd8794856 100644 --- a/drivers/s390/block/dasd_3990_erp.c +++ b/drivers/s390/block/dasd_3990_erp.c | |||
| @@ -1418,9 +1418,29 @@ static struct dasd_ccw_req *dasd_3990_erp_inspect_alias( | |||
| 1418 | struct dasd_ccw_req *erp) | 1418 | struct dasd_ccw_req *erp) |
| 1419 | { | 1419 | { |
| 1420 | struct dasd_ccw_req *cqr = erp->refers; | 1420 | struct dasd_ccw_req *cqr = erp->refers; |
| 1421 | char *sense; | ||
| 1421 | 1422 | ||
| 1422 | if (cqr->block && | 1423 | if (cqr->block && |
| 1423 | (cqr->block->base != cqr->startdev)) { | 1424 | (cqr->block->base != cqr->startdev)) { |
| 1425 | |||
| 1426 | sense = dasd_get_sense(&erp->refers->irb); | ||
| 1427 | /* | ||
| 1428 | * dynamic pav may have changed base alias mapping | ||
| 1429 | */ | ||
| 1430 | if (!test_bit(DASD_FLAG_OFFLINE, &cqr->startdev->flags) && sense | ||
| 1431 | && (sense[0] == 0x10) && (sense[7] == 0x0F) | ||
| 1432 | && (sense[8] == 0x67)) { | ||
| 1433 | /* | ||
| 1434 | * remove device from alias handling to prevent new | ||
| 1435 | * requests from being scheduled on the | ||
| 1436 | * wrong alias device | ||
| 1437 | */ | ||
| 1438 | dasd_alias_remove_device(cqr->startdev); | ||
| 1439 | |||
| 1440 | /* schedule worker to reload device */ | ||
| 1441 | dasd_reload_device(cqr->startdev); | ||
| 1442 | } | ||
| 1443 | |||
| 1424 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { | 1444 | if (cqr->startdev->features & DASD_FEATURE_ERPLOG) { |
| 1425 | DBF_DEV_EVENT(DBF_ERR, cqr->startdev, | 1445 | DBF_DEV_EVENT(DBF_ERR, cqr->startdev, |
| 1426 | "ERP on alias device for request %p," | 1446 | "ERP on alias device for request %p," |
diff --git a/drivers/s390/block/dasd_alias.c b/drivers/s390/block/dasd_alias.c index 8c4814258e93..4155805dcdff 100644 --- a/drivers/s390/block/dasd_alias.c +++ b/drivers/s390/block/dasd_alias.c | |||
| @@ -190,20 +190,21 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 190 | struct alias_server *server, *newserver; | 190 | struct alias_server *server, *newserver; |
| 191 | struct alias_lcu *lcu, *newlcu; | 191 | struct alias_lcu *lcu, *newlcu; |
| 192 | int is_lcu_known; | 192 | int is_lcu_known; |
| 193 | struct dasd_uid *uid; | 193 | struct dasd_uid uid; |
| 194 | 194 | ||
| 195 | private = (struct dasd_eckd_private *) device->private; | 195 | private = (struct dasd_eckd_private *) device->private; |
| 196 | uid = &private->uid; | 196 | |
| 197 | device->discipline->get_uid(device, &uid); | ||
| 197 | spin_lock_irqsave(&aliastree.lock, flags); | 198 | spin_lock_irqsave(&aliastree.lock, flags); |
| 198 | is_lcu_known = 1; | 199 | is_lcu_known = 1; |
| 199 | server = _find_server(uid); | 200 | server = _find_server(&uid); |
| 200 | if (!server) { | 201 | if (!server) { |
| 201 | spin_unlock_irqrestore(&aliastree.lock, flags); | 202 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 202 | newserver = _allocate_server(uid); | 203 | newserver = _allocate_server(&uid); |
| 203 | if (IS_ERR(newserver)) | 204 | if (IS_ERR(newserver)) |
| 204 | return PTR_ERR(newserver); | 205 | return PTR_ERR(newserver); |
| 205 | spin_lock_irqsave(&aliastree.lock, flags); | 206 | spin_lock_irqsave(&aliastree.lock, flags); |
| 206 | server = _find_server(uid); | 207 | server = _find_server(&uid); |
| 207 | if (!server) { | 208 | if (!server) { |
| 208 | list_add(&newserver->server, &aliastree.serverlist); | 209 | list_add(&newserver->server, &aliastree.serverlist); |
| 209 | server = newserver; | 210 | server = newserver; |
| @@ -214,14 +215,14 @@ int dasd_alias_make_device_known_to_lcu(struct dasd_device *device) | |||
| 214 | } | 215 | } |
| 215 | } | 216 | } |
| 216 | 217 | ||
| 217 | lcu = _find_lcu(server, uid); | 218 | lcu = _find_lcu(server, &uid); |
| 218 | if (!lcu) { | 219 | if (!lcu) { |
| 219 | spin_unlock_irqrestore(&aliastree.lock, flags); | 220 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 220 | newlcu = _allocate_lcu(uid); | 221 | newlcu = _allocate_lcu(&uid); |
| 221 | if (IS_ERR(newlcu)) | 222 | if (IS_ERR(newlcu)) |
| 222 | return PTR_ERR(newlcu); | 223 | return PTR_ERR(newlcu); |
| 223 | spin_lock_irqsave(&aliastree.lock, flags); | 224 | spin_lock_irqsave(&aliastree.lock, flags); |
| 224 | lcu = _find_lcu(server, uid); | 225 | lcu = _find_lcu(server, &uid); |
| 225 | if (!lcu) { | 226 | if (!lcu) { |
| 226 | list_add(&newlcu->lcu, &server->lculist); | 227 | list_add(&newlcu->lcu, &server->lculist); |
| 227 | lcu = newlcu; | 228 | lcu = newlcu; |
| @@ -256,20 +257,20 @@ void dasd_alias_lcu_setup_complete(struct dasd_device *device) | |||
| 256 | unsigned long flags; | 257 | unsigned long flags; |
| 257 | struct alias_server *server; | 258 | struct alias_server *server; |
| 258 | struct alias_lcu *lcu; | 259 | struct alias_lcu *lcu; |
| 259 | struct dasd_uid *uid; | 260 | struct dasd_uid uid; |
| 260 | 261 | ||
| 261 | private = (struct dasd_eckd_private *) device->private; | 262 | private = (struct dasd_eckd_private *) device->private; |
| 262 | uid = &private->uid; | 263 | device->discipline->get_uid(device, &uid); |
| 263 | lcu = NULL; | 264 | lcu = NULL; |
| 264 | spin_lock_irqsave(&aliastree.lock, flags); | 265 | spin_lock_irqsave(&aliastree.lock, flags); |
| 265 | server = _find_server(uid); | 266 | server = _find_server(&uid); |
| 266 | if (server) | 267 | if (server) |
| 267 | lcu = _find_lcu(server, uid); | 268 | lcu = _find_lcu(server, &uid); |
| 268 | spin_unlock_irqrestore(&aliastree.lock, flags); | 269 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 269 | if (!lcu) { | 270 | if (!lcu) { |
| 270 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | 271 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, |
| 271 | "could not find lcu for %04x %02x", | 272 | "could not find lcu for %04x %02x", |
| 272 | uid->ssid, uid->real_unit_addr); | 273 | uid.ssid, uid.real_unit_addr); |
| 273 | WARN_ON(1); | 274 | WARN_ON(1); |
| 274 | return; | 275 | return; |
| 275 | } | 276 | } |
| @@ -282,20 +283,20 @@ void dasd_alias_wait_for_lcu_setup(struct dasd_device *device) | |||
| 282 | unsigned long flags; | 283 | unsigned long flags; |
| 283 | struct alias_server *server; | 284 | struct alias_server *server; |
| 284 | struct alias_lcu *lcu; | 285 | struct alias_lcu *lcu; |
| 285 | struct dasd_uid *uid; | 286 | struct dasd_uid uid; |
| 286 | 287 | ||
| 287 | private = (struct dasd_eckd_private *) device->private; | 288 | private = (struct dasd_eckd_private *) device->private; |
| 288 | uid = &private->uid; | 289 | device->discipline->get_uid(device, &uid); |
| 289 | lcu = NULL; | 290 | lcu = NULL; |
| 290 | spin_lock_irqsave(&aliastree.lock, flags); | 291 | spin_lock_irqsave(&aliastree.lock, flags); |
| 291 | server = _find_server(uid); | 292 | server = _find_server(&uid); |
| 292 | if (server) | 293 | if (server) |
| 293 | lcu = _find_lcu(server, uid); | 294 | lcu = _find_lcu(server, &uid); |
| 294 | spin_unlock_irqrestore(&aliastree.lock, flags); | 295 | spin_unlock_irqrestore(&aliastree.lock, flags); |
| 295 | if (!lcu) { | 296 | if (!lcu) { |
| 296 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, | 297 | DBF_EVENT_DEVID(DBF_ERR, device->cdev, |
| 297 | "could not find lcu for %04x %02x", | 298 | "could not find lcu for %04x %02x", |
| 298 | uid->ssid, uid->real_unit_addr); | 299 | uid.ssid, uid.real_unit_addr); |
| 299 | WARN_ON(1); | 300 | WARN_ON(1); |
| 300 | return; | 301 | return; |
| 301 | } | 302 | } |
| @@ -314,9 +315,11 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 314 | struct alias_lcu *lcu; | 315 | struct alias_lcu *lcu; |
| 315 | struct alias_server *server; | 316 | struct alias_server *server; |
| 316 | int was_pending; | 317 | int was_pending; |
| 318 | struct dasd_uid uid; | ||
| 317 | 319 | ||
| 318 | private = (struct dasd_eckd_private *) device->private; | 320 | private = (struct dasd_eckd_private *) device->private; |
| 319 | lcu = private->lcu; | 321 | lcu = private->lcu; |
| 322 | device->discipline->get_uid(device, &uid); | ||
| 320 | spin_lock_irqsave(&lcu->lock, flags); | 323 | spin_lock_irqsave(&lcu->lock, flags); |
| 321 | list_del_init(&device->alias_list); | 324 | list_del_init(&device->alias_list); |
| 322 | /* make sure that the workers don't use this device */ | 325 | /* make sure that the workers don't use this device */ |
| @@ -353,7 +356,7 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 353 | _schedule_lcu_update(lcu, NULL); | 356 | _schedule_lcu_update(lcu, NULL); |
| 354 | spin_unlock(&lcu->lock); | 357 | spin_unlock(&lcu->lock); |
| 355 | } | 358 | } |
| 356 | server = _find_server(&private->uid); | 359 | server = _find_server(&uid); |
| 357 | if (server && list_empty(&server->lculist)) { | 360 | if (server && list_empty(&server->lculist)) { |
| 358 | list_del(&server->server); | 361 | list_del(&server->server); |
| 359 | _free_server(server); | 362 | _free_server(server); |
| @@ -366,19 +369,30 @@ void dasd_alias_disconnect_device_from_lcu(struct dasd_device *device) | |||
| 366 | * in the lcu is up to date and will update the device uid before | 369 | * in the lcu is up to date and will update the device uid before |
| 367 | * adding it to a pav group. | 370 | * adding it to a pav group. |
| 368 | */ | 371 | */ |
| 372 | |||
| 369 | static int _add_device_to_lcu(struct alias_lcu *lcu, | 373 | static int _add_device_to_lcu(struct alias_lcu *lcu, |
| 370 | struct dasd_device *device) | 374 | struct dasd_device *device, |
| 375 | struct dasd_device *pos) | ||
| 371 | { | 376 | { |
| 372 | 377 | ||
| 373 | struct dasd_eckd_private *private; | 378 | struct dasd_eckd_private *private; |
| 374 | struct alias_pav_group *group; | 379 | struct alias_pav_group *group; |
| 375 | struct dasd_uid *uid; | 380 | struct dasd_uid uid; |
| 381 | unsigned long flags; | ||
| 376 | 382 | ||
| 377 | private = (struct dasd_eckd_private *) device->private; | 383 | private = (struct dasd_eckd_private *) device->private; |
| 378 | uid = &private->uid; | 384 | |
| 379 | uid->type = lcu->uac->unit[uid->real_unit_addr].ua_type; | 385 | /* only lock if not already locked */ |
| 380 | uid->base_unit_addr = lcu->uac->unit[uid->real_unit_addr].base_ua; | 386 | if (device != pos) |
| 381 | dasd_set_uid(device->cdev, &private->uid); | 387 | spin_lock_irqsave_nested(get_ccwdev_lock(device->cdev), flags, |
| 388 | CDEV_NESTED_SECOND); | ||
| 389 | private->uid.type = lcu->uac->unit[private->uid.real_unit_addr].ua_type; | ||
| 390 | private->uid.base_unit_addr = | ||
| 391 | lcu->uac->unit[private->uid.real_unit_addr].base_ua; | ||
| 392 | uid = private->uid; | ||
| 393 | |||
| 394 | if (device != pos) | ||
| 395 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 382 | 396 | ||
| 383 | /* if we have no PAV anyway, we don't need to bother with PAV groups */ | 397 | /* if we have no PAV anyway, we don't need to bother with PAV groups */ |
| 384 | if (lcu->pav == NO_PAV) { | 398 | if (lcu->pav == NO_PAV) { |
| @@ -386,25 +400,25 @@ static int _add_device_to_lcu(struct alias_lcu *lcu, | |||
| 386 | return 0; | 400 | return 0; |
| 387 | } | 401 | } |
| 388 | 402 | ||
| 389 | group = _find_group(lcu, uid); | 403 | group = _find_group(lcu, &uid); |
| 390 | if (!group) { | 404 | if (!group) { |
| 391 | group = kzalloc(sizeof(*group), GFP_ATOMIC); | 405 | group = kzalloc(sizeof(*group), GFP_ATOMIC); |
| 392 | if (!group) | 406 | if (!group) |
| 393 | return -ENOMEM; | 407 | return -ENOMEM; |
| 394 | memcpy(group->uid.vendor, uid->vendor, sizeof(uid->vendor)); | 408 | memcpy(group->uid.vendor, uid.vendor, sizeof(uid.vendor)); |
| 395 | memcpy(group->uid.serial, uid->serial, sizeof(uid->serial)); | 409 | memcpy(group->uid.serial, uid.serial, sizeof(uid.serial)); |
| 396 | group->uid.ssid = uid->ssid; | 410 | group->uid.ssid = uid.ssid; |
| 397 | if (uid->type == UA_BASE_DEVICE) | 411 | if (uid.type == UA_BASE_DEVICE) |
| 398 | group->uid.base_unit_addr = uid->real_unit_addr; | 412 | group->uid.base_unit_addr = uid.real_unit_addr; |
| 399 | else | 413 | else |
| 400 | group->uid.base_unit_addr = uid->base_unit_addr; | 414 | group->uid.base_unit_addr = uid.base_unit_addr; |
| 401 | memcpy(group->uid.vduit, uid->vduit, sizeof(uid->vduit)); | 415 | memcpy(group->uid.vduit, uid.vduit, sizeof(uid.vduit)); |
| 402 | INIT_LIST_HEAD(&group->group); | 416 | INIT_LIST_HEAD(&group->group); |
| 403 | INIT_LIST_HEAD(&group->baselist); | 417 | INIT_LIST_HEAD(&group->baselist); |
| 404 | INIT_LIST_HEAD(&group->aliaslist); | 418 | INIT_LIST_HEAD(&group->aliaslist); |
| 405 | list_add(&group->group, &lcu->grouplist); | 419 | list_add(&group->group, &lcu->grouplist); |
| 406 | } | 420 | } |
| 407 | if (uid->type == UA_BASE_DEVICE) | 421 | if (uid.type == UA_BASE_DEVICE) |
| 408 | list_move(&device->alias_list, &group->baselist); | 422 | list_move(&device->alias_list, &group->baselist); |
| 409 | else | 423 | else |
| 410 | list_move(&device->alias_list, &group->aliaslist); | 424 | list_move(&device->alias_list, &group->aliaslist); |
| @@ -525,7 +539,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) | |||
| 525 | if (rc) | 539 | if (rc) |
| 526 | return rc; | 540 | return rc; |
| 527 | 541 | ||
| 528 | spin_lock_irqsave(&lcu->lock, flags); | 542 | /* need to take cdev lock before lcu lock */ |
| 543 | spin_lock_irqsave_nested(get_ccwdev_lock(refdev->cdev), flags, | ||
| 544 | CDEV_NESTED_FIRST); | ||
| 545 | spin_lock(&lcu->lock); | ||
| 529 | lcu->pav = NO_PAV; | 546 | lcu->pav = NO_PAV; |
| 530 | for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { | 547 | for (i = 0; i < MAX_DEVICES_PER_LCU; ++i) { |
| 531 | switch (lcu->uac->unit[i].ua_type) { | 548 | switch (lcu->uac->unit[i].ua_type) { |
| @@ -542,9 +559,10 @@ static int _lcu_update(struct dasd_device *refdev, struct alias_lcu *lcu) | |||
| 542 | 559 | ||
| 543 | list_for_each_entry_safe(device, tempdev, &lcu->active_devices, | 560 | list_for_each_entry_safe(device, tempdev, &lcu->active_devices, |
| 544 | alias_list) { | 561 | alias_list) { |
| 545 | _add_device_to_lcu(lcu, device); | 562 | _add_device_to_lcu(lcu, device, refdev); |
| 546 | } | 563 | } |
| 547 | spin_unlock_irqrestore(&lcu->lock, flags); | 564 | spin_unlock(&lcu->lock); |
| 565 | spin_unlock_irqrestore(get_ccwdev_lock(refdev->cdev), flags); | ||
| 548 | return 0; | 566 | return 0; |
| 549 | } | 567 | } |
| 550 | 568 | ||
| @@ -628,9 +646,12 @@ int dasd_alias_add_device(struct dasd_device *device) | |||
| 628 | private = (struct dasd_eckd_private *) device->private; | 646 | private = (struct dasd_eckd_private *) device->private; |
| 629 | lcu = private->lcu; | 647 | lcu = private->lcu; |
| 630 | rc = 0; | 648 | rc = 0; |
| 631 | spin_lock_irqsave(&lcu->lock, flags); | 649 | |
| 650 | /* need to take cdev lock before lcu lock */ | ||
| 651 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 652 | spin_lock(&lcu->lock); | ||
| 632 | if (!(lcu->flags & UPDATE_PENDING)) { | 653 | if (!(lcu->flags & UPDATE_PENDING)) { |
| 633 | rc = _add_device_to_lcu(lcu, device); | 654 | rc = _add_device_to_lcu(lcu, device, device); |
| 634 | if (rc) | 655 | if (rc) |
| 635 | lcu->flags |= UPDATE_PENDING; | 656 | lcu->flags |= UPDATE_PENDING; |
| 636 | } | 657 | } |
| @@ -638,10 +659,19 @@ int dasd_alias_add_device(struct dasd_device *device) | |||
| 638 | list_move(&device->alias_list, &lcu->active_devices); | 659 | list_move(&device->alias_list, &lcu->active_devices); |
| 639 | _schedule_lcu_update(lcu, device); | 660 | _schedule_lcu_update(lcu, device); |
| 640 | } | 661 | } |
| 641 | spin_unlock_irqrestore(&lcu->lock, flags); | 662 | spin_unlock(&lcu->lock); |
| 663 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 642 | return rc; | 664 | return rc; |
| 643 | } | 665 | } |
| 644 | 666 | ||
| 667 | int dasd_alias_update_add_device(struct dasd_device *device) | ||
| 668 | { | ||
| 669 | struct dasd_eckd_private *private; | ||
| 670 | private = (struct dasd_eckd_private *) device->private; | ||
| 671 | private->lcu->flags |= UPDATE_PENDING; | ||
| 672 | return dasd_alias_add_device(device); | ||
| 673 | } | ||
| 674 | |||
| 645 | int dasd_alias_remove_device(struct dasd_device *device) | 675 | int dasd_alias_remove_device(struct dasd_device *device) |
| 646 | { | 676 | { |
| 647 | struct dasd_eckd_private *private; | 677 | struct dasd_eckd_private *private; |
| @@ -740,19 +770,30 @@ static void _restart_all_base_devices_on_lcu(struct alias_lcu *lcu) | |||
| 740 | struct alias_pav_group *pavgroup; | 770 | struct alias_pav_group *pavgroup; |
| 741 | struct dasd_device *device; | 771 | struct dasd_device *device; |
| 742 | struct dasd_eckd_private *private; | 772 | struct dasd_eckd_private *private; |
| 773 | unsigned long flags; | ||
| 743 | 774 | ||
| 744 | /* active and inactive list can contain alias as well as base devices */ | 775 | /* active and inactive list can contain alias as well as base devices */ |
| 745 | list_for_each_entry(device, &lcu->active_devices, alias_list) { | 776 | list_for_each_entry(device, &lcu->active_devices, alias_list) { |
| 746 | private = (struct dasd_eckd_private *) device->private; | 777 | private = (struct dasd_eckd_private *) device->private; |
| 747 | if (private->uid.type != UA_BASE_DEVICE) | 778 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
| 779 | if (private->uid.type != UA_BASE_DEVICE) { | ||
| 780 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | ||
| 781 | flags); | ||
| 748 | continue; | 782 | continue; |
| 783 | } | ||
| 784 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 749 | dasd_schedule_block_bh(device->block); | 785 | dasd_schedule_block_bh(device->block); |
| 750 | dasd_schedule_device_bh(device); | 786 | dasd_schedule_device_bh(device); |
| 751 | } | 787 | } |
| 752 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { | 788 | list_for_each_entry(device, &lcu->inactive_devices, alias_list) { |
| 753 | private = (struct dasd_eckd_private *) device->private; | 789 | private = (struct dasd_eckd_private *) device->private; |
| 754 | if (private->uid.type != UA_BASE_DEVICE) | 790 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); |
| 791 | if (private->uid.type != UA_BASE_DEVICE) { | ||
| 792 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), | ||
| 793 | flags); | ||
| 755 | continue; | 794 | continue; |
| 795 | } | ||
| 796 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 756 | dasd_schedule_block_bh(device->block); | 797 | dasd_schedule_block_bh(device->block); |
| 757 | dasd_schedule_device_bh(device); | 798 | dasd_schedule_device_bh(device); |
| 758 | } | 799 | } |
diff --git a/drivers/s390/block/dasd_devmap.c b/drivers/s390/block/dasd_devmap.c index eff9c812c5c2..34d51dd4c539 100644 --- a/drivers/s390/block/dasd_devmap.c +++ b/drivers/s390/block/dasd_devmap.c | |||
| @@ -49,7 +49,6 @@ struct dasd_devmap { | |||
| 49 | unsigned int devindex; | 49 | unsigned int devindex; |
| 50 | unsigned short features; | 50 | unsigned short features; |
| 51 | struct dasd_device *device; | 51 | struct dasd_device *device; |
| 52 | struct dasd_uid uid; | ||
| 53 | }; | 52 | }; |
| 54 | 53 | ||
| 55 | /* | 54 | /* |
| @@ -936,42 +935,46 @@ dasd_device_status_show(struct device *dev, struct device_attribute *attr, | |||
| 936 | 935 | ||
| 937 | static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); | 936 | static DEVICE_ATTR(status, 0444, dasd_device_status_show, NULL); |
| 938 | 937 | ||
| 939 | static ssize_t | 938 | static ssize_t dasd_alias_show(struct device *dev, |
| 940 | dasd_alias_show(struct device *dev, struct device_attribute *attr, char *buf) | 939 | struct device_attribute *attr, char *buf) |
| 941 | { | 940 | { |
| 942 | struct dasd_devmap *devmap; | 941 | struct dasd_device *device; |
| 943 | int alias; | 942 | struct dasd_uid uid; |
| 944 | 943 | ||
| 945 | devmap = dasd_find_busid(dev_name(dev)); | 944 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 946 | spin_lock(&dasd_devmap_lock); | 945 | if (IS_ERR(device)) |
| 947 | if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { | ||
| 948 | spin_unlock(&dasd_devmap_lock); | ||
| 949 | return sprintf(buf, "0\n"); | 946 | return sprintf(buf, "0\n"); |
| 947 | |||
| 948 | if (device->discipline && device->discipline->get_uid && | ||
| 949 | !device->discipline->get_uid(device, &uid)) { | ||
| 950 | if (uid.type == UA_BASE_PAV_ALIAS || | ||
| 951 | uid.type == UA_HYPER_PAV_ALIAS) | ||
| 952 | return sprintf(buf, "1\n"); | ||
| 950 | } | 953 | } |
| 951 | if (devmap->uid.type == UA_BASE_PAV_ALIAS || | 954 | dasd_put_device(device); |
| 952 | devmap->uid.type == UA_HYPER_PAV_ALIAS) | 955 | |
| 953 | alias = 1; | 956 | return sprintf(buf, "0\n"); |
| 954 | else | ||
| 955 | alias = 0; | ||
| 956 | spin_unlock(&dasd_devmap_lock); | ||
| 957 | return sprintf(buf, alias ? "1\n" : "0\n"); | ||
| 958 | } | 957 | } |
| 959 | 958 | ||
| 960 | static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); | 959 | static DEVICE_ATTR(alias, 0444, dasd_alias_show, NULL); |
| 961 | 960 | ||
| 962 | static ssize_t | 961 | static ssize_t dasd_vendor_show(struct device *dev, |
| 963 | dasd_vendor_show(struct device *dev, struct device_attribute *attr, char *buf) | 962 | struct device_attribute *attr, char *buf) |
| 964 | { | 963 | { |
| 965 | struct dasd_devmap *devmap; | 964 | struct dasd_device *device; |
| 965 | struct dasd_uid uid; | ||
| 966 | char *vendor; | 966 | char *vendor; |
| 967 | 967 | ||
| 968 | devmap = dasd_find_busid(dev_name(dev)); | 968 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 969 | spin_lock(&dasd_devmap_lock); | 969 | vendor = ""; |
| 970 | if (!IS_ERR(devmap) && strlen(devmap->uid.vendor) > 0) | 970 | if (IS_ERR(device)) |
| 971 | vendor = devmap->uid.vendor; | 971 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); |
| 972 | else | 972 | |
| 973 | vendor = ""; | 973 | if (device->discipline && device->discipline->get_uid && |
| 974 | spin_unlock(&dasd_devmap_lock); | 974 | !device->discipline->get_uid(device, &uid)) |
| 975 | vendor = uid.vendor; | ||
| 976 | |||
| 977 | dasd_put_device(device); | ||
| 975 | 978 | ||
| 976 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); | 979 | return snprintf(buf, PAGE_SIZE, "%s\n", vendor); |
| 977 | } | 980 | } |
| @@ -985,48 +988,51 @@ static DEVICE_ATTR(vendor, 0444, dasd_vendor_show, NULL); | |||
| 985 | static ssize_t | 988 | static ssize_t |
| 986 | dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) | 989 | dasd_uid_show(struct device *dev, struct device_attribute *attr, char *buf) |
| 987 | { | 990 | { |
| 988 | struct dasd_devmap *devmap; | 991 | struct dasd_device *device; |
| 992 | struct dasd_uid uid; | ||
| 989 | char uid_string[UID_STRLEN]; | 993 | char uid_string[UID_STRLEN]; |
| 990 | char ua_string[3]; | 994 | char ua_string[3]; |
| 991 | struct dasd_uid *uid; | ||
| 992 | 995 | ||
| 993 | devmap = dasd_find_busid(dev_name(dev)); | 996 | device = dasd_device_from_cdev(to_ccwdev(dev)); |
| 994 | spin_lock(&dasd_devmap_lock); | 997 | uid_string[0] = 0; |
| 995 | if (IS_ERR(devmap) || strlen(devmap->uid.vendor) == 0) { | 998 | if (IS_ERR(device)) |
| 996 | spin_unlock(&dasd_devmap_lock); | 999 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); |
| 997 | return sprintf(buf, "\n"); | 1000 | |
| 998 | } | 1001 | if (device->discipline && device->discipline->get_uid && |
| 999 | uid = &devmap->uid; | 1002 | !device->discipline->get_uid(device, &uid)) { |
| 1000 | switch (uid->type) { | 1003 | switch (uid.type) { |
| 1001 | case UA_BASE_DEVICE: | 1004 | case UA_BASE_DEVICE: |
| 1002 | sprintf(ua_string, "%02x", uid->real_unit_addr); | 1005 | snprintf(ua_string, sizeof(ua_string), "%02x", |
| 1003 | break; | 1006 | uid.real_unit_addr); |
| 1004 | case UA_BASE_PAV_ALIAS: | 1007 | break; |
| 1005 | sprintf(ua_string, "%02x", uid->base_unit_addr); | 1008 | case UA_BASE_PAV_ALIAS: |
| 1006 | break; | 1009 | snprintf(ua_string, sizeof(ua_string), "%02x", |
| 1007 | case UA_HYPER_PAV_ALIAS: | 1010 | uid.base_unit_addr); |
| 1008 | sprintf(ua_string, "xx"); | 1011 | break; |
| 1009 | break; | 1012 | case UA_HYPER_PAV_ALIAS: |
| 1010 | default: | 1013 | snprintf(ua_string, sizeof(ua_string), "xx"); |
| 1011 | /* should not happen, treat like base device */ | 1014 | break; |
| 1012 | sprintf(ua_string, "%02x", uid->real_unit_addr); | 1015 | default: |
| 1013 | break; | 1016 | /* should not happen, treat like base device */ |
| 1017 | snprintf(ua_string, sizeof(ua_string), "%02x", | ||
| 1018 | uid.real_unit_addr); | ||
| 1019 | break; | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | if (strlen(uid.vduit) > 0) | ||
| 1023 | snprintf(uid_string, sizeof(uid_string), | ||
| 1024 | "%s.%s.%04x.%s.%s", | ||
| 1025 | uid.vendor, uid.serial, uid.ssid, ua_string, | ||
| 1026 | uid.vduit); | ||
| 1027 | else | ||
| 1028 | snprintf(uid_string, sizeof(uid_string), | ||
| 1029 | "%s.%s.%04x.%s", | ||
| 1030 | uid.vendor, uid.serial, uid.ssid, ua_string); | ||
| 1014 | } | 1031 | } |
| 1015 | if (strlen(uid->vduit) > 0) | 1032 | dasd_put_device(device); |
| 1016 | snprintf(uid_string, sizeof(uid_string), | 1033 | |
| 1017 | "%s.%s.%04x.%s.%s", | ||
| 1018 | uid->vendor, uid->serial, | ||
| 1019 | uid->ssid, ua_string, | ||
| 1020 | uid->vduit); | ||
| 1021 | else | ||
| 1022 | snprintf(uid_string, sizeof(uid_string), | ||
| 1023 | "%s.%s.%04x.%s", | ||
| 1024 | uid->vendor, uid->serial, | ||
| 1025 | uid->ssid, ua_string); | ||
| 1026 | spin_unlock(&dasd_devmap_lock); | ||
| 1027 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); | 1034 | return snprintf(buf, PAGE_SIZE, "%s\n", uid_string); |
| 1028 | } | 1035 | } |
| 1029 | |||
| 1030 | static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); | 1036 | static DEVICE_ATTR(uid, 0444, dasd_uid_show, NULL); |
| 1031 | 1037 | ||
| 1032 | /* | 1038 | /* |
| @@ -1094,50 +1100,6 @@ static struct attribute_group dasd_attr_group = { | |||
| 1094 | }; | 1100 | }; |
| 1095 | 1101 | ||
| 1096 | /* | 1102 | /* |
| 1097 | * Return copy of the device unique identifier. | ||
| 1098 | */ | ||
| 1099 | int | ||
| 1100 | dasd_get_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 1101 | { | ||
| 1102 | struct dasd_devmap *devmap; | ||
| 1103 | |||
| 1104 | devmap = dasd_find_busid(dev_name(&cdev->dev)); | ||
| 1105 | if (IS_ERR(devmap)) | ||
| 1106 | return PTR_ERR(devmap); | ||
| 1107 | spin_lock(&dasd_devmap_lock); | ||
| 1108 | *uid = devmap->uid; | ||
| 1109 | spin_unlock(&dasd_devmap_lock); | ||
| 1110 | return 0; | ||
| 1111 | } | ||
| 1112 | EXPORT_SYMBOL_GPL(dasd_get_uid); | ||
| 1113 | |||
| 1114 | /* | ||
| 1115 | * Register the given device unique identifier into devmap struct. | ||
| 1116 | * In addition check if the related storage server subsystem ID is already | ||
| 1117 | * contained in the dasd_server_ssid_list. If subsystem ID is not contained, | ||
| 1118 | * create new entry. | ||
| 1119 | * Return 0 if server was already in serverlist, | ||
| 1120 | * 1 if the server was added successful | ||
| 1121 | * <0 in case of error. | ||
| 1122 | */ | ||
| 1123 | int | ||
| 1124 | dasd_set_uid(struct ccw_device *cdev, struct dasd_uid *uid) | ||
| 1125 | { | ||
| 1126 | struct dasd_devmap *devmap; | ||
| 1127 | |||
| 1128 | devmap = dasd_find_busid(dev_name(&cdev->dev)); | ||
| 1129 | if (IS_ERR(devmap)) | ||
| 1130 | return PTR_ERR(devmap); | ||
| 1131 | |||
| 1132 | spin_lock(&dasd_devmap_lock); | ||
| 1133 | devmap->uid = *uid; | ||
| 1134 | spin_unlock(&dasd_devmap_lock); | ||
| 1135 | |||
| 1136 | return 0; | ||
| 1137 | } | ||
| 1138 | EXPORT_SYMBOL_GPL(dasd_set_uid); | ||
| 1139 | |||
| 1140 | /* | ||
| 1141 | * Return value of the specified feature. | 1103 | * Return value of the specified feature. |
| 1142 | */ | 1104 | */ |
| 1143 | int | 1105 | int |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 0cb233116855..5b1cd8d6e971 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -692,18 +692,20 @@ dasd_eckd_cdl_reclen(int recid) | |||
| 692 | /* | 692 | /* |
| 693 | * Generate device unique id that specifies the physical device. | 693 | * Generate device unique id that specifies the physical device. |
| 694 | */ | 694 | */ |
| 695 | static int dasd_eckd_generate_uid(struct dasd_device *device, | 695 | static int dasd_eckd_generate_uid(struct dasd_device *device) |
| 696 | struct dasd_uid *uid) | ||
| 697 | { | 696 | { |
| 698 | struct dasd_eckd_private *private; | 697 | struct dasd_eckd_private *private; |
| 698 | struct dasd_uid *uid; | ||
| 699 | int count; | 699 | int count; |
| 700 | unsigned long flags; | ||
| 700 | 701 | ||
| 701 | private = (struct dasd_eckd_private *) device->private; | 702 | private = (struct dasd_eckd_private *) device->private; |
| 702 | if (!private) | 703 | if (!private) |
| 703 | return -ENODEV; | 704 | return -ENODEV; |
| 704 | if (!private->ned || !private->gneq) | 705 | if (!private->ned || !private->gneq) |
| 705 | return -ENODEV; | 706 | return -ENODEV; |
| 706 | 707 | uid = &private->uid; | |
| 708 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 707 | memset(uid, 0, sizeof(struct dasd_uid)); | 709 | memset(uid, 0, sizeof(struct dasd_uid)); |
| 708 | memcpy(uid->vendor, private->ned->HDA_manufacturer, | 710 | memcpy(uid->vendor, private->ned->HDA_manufacturer, |
| 709 | sizeof(uid->vendor) - 1); | 711 | sizeof(uid->vendor) - 1); |
| @@ -726,9 +728,25 @@ static int dasd_eckd_generate_uid(struct dasd_device *device, | |||
| 726 | private->vdsneq->uit[count]); | 728 | private->vdsneq->uit[count]); |
| 727 | } | 729 | } |
| 728 | } | 730 | } |
| 731 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 729 | return 0; | 732 | return 0; |
| 730 | } | 733 | } |
| 731 | 734 | ||
| 735 | static int dasd_eckd_get_uid(struct dasd_device *device, struct dasd_uid *uid) | ||
| 736 | { | ||
| 737 | struct dasd_eckd_private *private; | ||
| 738 | unsigned long flags; | ||
| 739 | |||
| 740 | if (device->private) { | ||
| 741 | private = (struct dasd_eckd_private *)device->private; | ||
| 742 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 743 | *uid = private->uid; | ||
| 744 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 745 | return 0; | ||
| 746 | } | ||
| 747 | return -EINVAL; | ||
| 748 | } | ||
| 749 | |||
| 732 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, | 750 | static struct dasd_ccw_req *dasd_eckd_build_rcd_lpm(struct dasd_device *device, |
| 733 | void *rcd_buffer, | 751 | void *rcd_buffer, |
| 734 | struct ciw *ciw, __u8 lpm) | 752 | struct ciw *ciw, __u8 lpm) |
| @@ -1088,6 +1106,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1088 | { | 1106 | { |
| 1089 | struct dasd_eckd_private *private; | 1107 | struct dasd_eckd_private *private; |
| 1090 | struct dasd_block *block; | 1108 | struct dasd_block *block; |
| 1109 | struct dasd_uid temp_uid; | ||
| 1091 | int is_known, rc; | 1110 | int is_known, rc; |
| 1092 | int readonly; | 1111 | int readonly; |
| 1093 | 1112 | ||
| @@ -1124,13 +1143,13 @@ dasd_eckd_check_characteristics(struct dasd_device *device) | |||
| 1124 | if (rc) | 1143 | if (rc) |
| 1125 | goto out_err1; | 1144 | goto out_err1; |
| 1126 | 1145 | ||
| 1127 | /* Generate device unique id and register in devmap */ | 1146 | /* Generate device unique id */ |
| 1128 | rc = dasd_eckd_generate_uid(device, &private->uid); | 1147 | rc = dasd_eckd_generate_uid(device); |
| 1129 | if (rc) | 1148 | if (rc) |
| 1130 | goto out_err1; | 1149 | goto out_err1; |
| 1131 | dasd_set_uid(device->cdev, &private->uid); | ||
| 1132 | 1150 | ||
| 1133 | if (private->uid.type == UA_BASE_DEVICE) { | 1151 | dasd_eckd_get_uid(device, &temp_uid); |
| 1152 | if (temp_uid.type == UA_BASE_DEVICE) { | ||
| 1134 | block = dasd_alloc_block(); | 1153 | block = dasd_alloc_block(); |
| 1135 | if (IS_ERR(block)) { | 1154 | if (IS_ERR(block)) { |
| 1136 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", | 1155 | DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "%s", |
| @@ -1451,6 +1470,7 @@ static int dasd_eckd_ready_to_online(struct dasd_device *device) | |||
| 1451 | 1470 | ||
| 1452 | static int dasd_eckd_online_to_ready(struct dasd_device *device) | 1471 | static int dasd_eckd_online_to_ready(struct dasd_device *device) |
| 1453 | { | 1472 | { |
| 1473 | cancel_work_sync(&device->reload_device); | ||
| 1454 | return dasd_alias_remove_device(device); | 1474 | return dasd_alias_remove_device(device); |
| 1455 | }; | 1475 | }; |
| 1456 | 1476 | ||
| @@ -1709,10 +1729,27 @@ static void dasd_eckd_handle_unsolicited_interrupt(struct dasd_device *device, | |||
| 1709 | { | 1729 | { |
| 1710 | char mask; | 1730 | char mask; |
| 1711 | char *sense = NULL; | 1731 | char *sense = NULL; |
| 1732 | struct dasd_eckd_private *private; | ||
| 1712 | 1733 | ||
| 1734 | private = (struct dasd_eckd_private *) device->private; | ||
| 1713 | /* first of all check for state change pending interrupt */ | 1735 | /* first of all check for state change pending interrupt */ |
| 1714 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; | 1736 | mask = DEV_STAT_ATTENTION | DEV_STAT_DEV_END | DEV_STAT_UNIT_EXCEP; |
| 1715 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { | 1737 | if ((scsw_dstat(&irb->scsw) & mask) == mask) { |
| 1738 | /* for alias only and not in offline processing*/ | ||
| 1739 | if (!device->block && private->lcu && | ||
| 1740 | !test_bit(DASD_FLAG_OFFLINE, &device->flags)) { | ||
| 1741 | /* | ||
| 1742 | * the state change could be caused by an alias | ||
| 1743 | * reassignment remove device from alias handling | ||
| 1744 | * to prevent new requests from being scheduled on | ||
| 1745 | * the wrong alias device | ||
| 1746 | */ | ||
| 1747 | dasd_alias_remove_device(device); | ||
| 1748 | |||
| 1749 | /* schedule worker to reload device */ | ||
| 1750 | dasd_reload_device(device); | ||
| 1751 | } | ||
| 1752 | |||
| 1716 | dasd_generic_handle_state_change(device); | 1753 | dasd_generic_handle_state_change(device); |
| 1717 | return; | 1754 | return; |
| 1718 | } | 1755 | } |
| @@ -3259,7 +3296,7 @@ static void dasd_eckd_dump_sense(struct dasd_device *device, | |||
| 3259 | dasd_eckd_dump_sense_ccw(device, req, irb); | 3296 | dasd_eckd_dump_sense_ccw(device, req, irb); |
| 3260 | } | 3297 | } |
| 3261 | 3298 | ||
| 3262 | int dasd_eckd_pm_freeze(struct dasd_device *device) | 3299 | static int dasd_eckd_pm_freeze(struct dasd_device *device) |
| 3263 | { | 3300 | { |
| 3264 | /* | 3301 | /* |
| 3265 | * the device should be disconnected from our LCU structure | 3302 | * the device should be disconnected from our LCU structure |
| @@ -3272,7 +3309,7 @@ int dasd_eckd_pm_freeze(struct dasd_device *device) | |||
| 3272 | return 0; | 3309 | return 0; |
| 3273 | } | 3310 | } |
| 3274 | 3311 | ||
| 3275 | int dasd_eckd_restore_device(struct dasd_device *device) | 3312 | static int dasd_eckd_restore_device(struct dasd_device *device) |
| 3276 | { | 3313 | { |
| 3277 | struct dasd_eckd_private *private; | 3314 | struct dasd_eckd_private *private; |
| 3278 | struct dasd_eckd_characteristics temp_rdc_data; | 3315 | struct dasd_eckd_characteristics temp_rdc_data; |
| @@ -3287,15 +3324,16 @@ int dasd_eckd_restore_device(struct dasd_device *device) | |||
| 3287 | if (rc) | 3324 | if (rc) |
| 3288 | goto out_err; | 3325 | goto out_err; |
| 3289 | 3326 | ||
| 3290 | /* Generate device unique id and register in devmap */ | 3327 | dasd_eckd_get_uid(device, &temp_uid); |
| 3291 | rc = dasd_eckd_generate_uid(device, &private->uid); | 3328 | /* Generate device unique id */ |
| 3292 | dasd_get_uid(device->cdev, &temp_uid); | 3329 | rc = dasd_eckd_generate_uid(device); |
| 3330 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 3293 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) | 3331 | if (memcmp(&private->uid, &temp_uid, sizeof(struct dasd_uid)) != 0) |
| 3294 | dev_err(&device->cdev->dev, "The UID of the DASD has " | 3332 | dev_err(&device->cdev->dev, "The UID of the DASD has " |
| 3295 | "changed\n"); | 3333 | "changed\n"); |
| 3334 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 3296 | if (rc) | 3335 | if (rc) |
| 3297 | goto out_err; | 3336 | goto out_err; |
| 3298 | dasd_set_uid(device->cdev, &private->uid); | ||
| 3299 | 3337 | ||
| 3300 | /* register lcu with alias handling, enable PAV if this is a new lcu */ | 3338 | /* register lcu with alias handling, enable PAV if this is a new lcu */ |
| 3301 | is_known = dasd_alias_make_device_known_to_lcu(device); | 3339 | is_known = dasd_alias_make_device_known_to_lcu(device); |
| @@ -3336,6 +3374,56 @@ out_err: | |||
| 3336 | return -1; | 3374 | return -1; |
| 3337 | } | 3375 | } |
| 3338 | 3376 | ||
| 3377 | static int dasd_eckd_reload_device(struct dasd_device *device) | ||
| 3378 | { | ||
| 3379 | struct dasd_eckd_private *private; | ||
| 3380 | int rc, old_base; | ||
| 3381 | char print_uid[60]; | ||
| 3382 | struct dasd_uid uid; | ||
| 3383 | unsigned long flags; | ||
| 3384 | |||
| 3385 | private = (struct dasd_eckd_private *) device->private; | ||
| 3386 | |||
| 3387 | spin_lock_irqsave(get_ccwdev_lock(device->cdev), flags); | ||
| 3388 | old_base = private->uid.base_unit_addr; | ||
| 3389 | spin_unlock_irqrestore(get_ccwdev_lock(device->cdev), flags); | ||
| 3390 | |||
| 3391 | /* Read Configuration Data */ | ||
| 3392 | rc = dasd_eckd_read_conf(device); | ||
| 3393 | if (rc) | ||
| 3394 | goto out_err; | ||
| 3395 | |||
| 3396 | rc = dasd_eckd_generate_uid(device); | ||
| 3397 | if (rc) | ||
| 3398 | goto out_err; | ||
| 3399 | /* | ||
| 3400 | * update unit address configuration and | ||
| 3401 | * add device to alias management | ||
| 3402 | */ | ||
| 3403 | dasd_alias_update_add_device(device); | ||
| 3404 | |||
| 3405 | dasd_eckd_get_uid(device, &uid); | ||
| 3406 | |||
| 3407 | if (old_base != uid.base_unit_addr) { | ||
| 3408 | if (strlen(uid.vduit) > 0) | ||
| 3409 | snprintf(print_uid, sizeof(print_uid), | ||
| 3410 | "%s.%s.%04x.%02x.%s", uid.vendor, uid.serial, | ||
| 3411 | uid.ssid, uid.base_unit_addr, uid.vduit); | ||
| 3412 | else | ||
| 3413 | snprintf(print_uid, sizeof(print_uid), | ||
| 3414 | "%s.%s.%04x.%02x", uid.vendor, uid.serial, | ||
| 3415 | uid.ssid, uid.base_unit_addr); | ||
| 3416 | |||
| 3417 | dev_info(&device->cdev->dev, | ||
| 3418 | "An Alias device was reassigned to a new base device " | ||
| 3419 | "with UID: %s\n", print_uid); | ||
| 3420 | } | ||
| 3421 | return 0; | ||
| 3422 | |||
| 3423 | out_err: | ||
| 3424 | return -1; | ||
| 3425 | } | ||
| 3426 | |||
| 3339 | static struct ccw_driver dasd_eckd_driver = { | 3427 | static struct ccw_driver dasd_eckd_driver = { |
| 3340 | .name = "dasd-eckd", | 3428 | .name = "dasd-eckd", |
| 3341 | .owner = THIS_MODULE, | 3429 | .owner = THIS_MODULE, |
| @@ -3389,6 +3477,8 @@ static struct dasd_discipline dasd_eckd_discipline = { | |||
| 3389 | .ioctl = dasd_eckd_ioctl, | 3477 | .ioctl = dasd_eckd_ioctl, |
| 3390 | .freeze = dasd_eckd_pm_freeze, | 3478 | .freeze = dasd_eckd_pm_freeze, |
| 3391 | .restore = dasd_eckd_restore_device, | 3479 | .restore = dasd_eckd_restore_device, |
| 3480 | .reload = dasd_eckd_reload_device, | ||
| 3481 | .get_uid = dasd_eckd_get_uid, | ||
| 3392 | }; | 3482 | }; |
| 3393 | 3483 | ||
| 3394 | static int __init | 3484 | static int __init |
diff --git a/drivers/s390/block/dasd_eckd.h b/drivers/s390/block/dasd_eckd.h index 864d53c04201..dd6385a5af14 100644 --- a/drivers/s390/block/dasd_eckd.h +++ b/drivers/s390/block/dasd_eckd.h | |||
| @@ -426,7 +426,6 @@ struct alias_pav_group { | |||
| 426 | struct dasd_device *next; | 426 | struct dasd_device *next; |
| 427 | }; | 427 | }; |
| 428 | 428 | ||
| 429 | |||
| 430 | struct dasd_eckd_private { | 429 | struct dasd_eckd_private { |
| 431 | struct dasd_eckd_characteristics rdc_data; | 430 | struct dasd_eckd_characteristics rdc_data; |
| 432 | u8 *conf_data; | 431 | u8 *conf_data; |
| @@ -463,4 +462,5 @@ void dasd_alias_handle_summary_unit_check(struct dasd_device *, struct irb *); | |||
| 463 | void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); | 462 | void dasd_eckd_reset_ccw_to_base_io(struct dasd_ccw_req *); |
| 464 | void dasd_alias_lcu_setup_complete(struct dasd_device *); | 463 | void dasd_alias_lcu_setup_complete(struct dasd_device *); |
| 465 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *); | 464 | void dasd_alias_wait_for_lcu_setup(struct dasd_device *); |
| 465 | int dasd_alias_update_add_device(struct dasd_device *); | ||
| 466 | #endif /* DASD_ECKD_H */ | 466 | #endif /* DASD_ECKD_H */ |
diff --git a/drivers/s390/block/dasd_int.h b/drivers/s390/block/dasd_int.h index a91d4a97d4f2..32fac186ba3f 100644 --- a/drivers/s390/block/dasd_int.h +++ b/drivers/s390/block/dasd_int.h | |||
| @@ -81,6 +81,10 @@ struct dasd_block; | |||
| 81 | #define DASD_SIM_MSG_TO_OP 0x03 | 81 | #define DASD_SIM_MSG_TO_OP 0x03 |
| 82 | #define DASD_SIM_LOG 0x0C | 82 | #define DASD_SIM_LOG 0x0C |
| 83 | 83 | ||
| 84 | /* lock class for nested cdev lock */ | ||
| 85 | #define CDEV_NESTED_FIRST 1 | ||
| 86 | #define CDEV_NESTED_SECOND 2 | ||
| 87 | |||
| 84 | /* | 88 | /* |
| 85 | * SECTION: MACROs for klogd and s390 debug feature (dbf) | 89 | * SECTION: MACROs for klogd and s390 debug feature (dbf) |
| 86 | */ | 90 | */ |
| @@ -229,6 +233,24 @@ struct dasd_ccw_req { | |||
| 229 | typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); | 233 | typedef struct dasd_ccw_req *(*dasd_erp_fn_t) (struct dasd_ccw_req *); |
| 230 | 234 | ||
| 231 | /* | 235 | /* |
| 236 | * Unique identifier for dasd device. | ||
| 237 | */ | ||
| 238 | #define UA_NOT_CONFIGURED 0x00 | ||
| 239 | #define UA_BASE_DEVICE 0x01 | ||
| 240 | #define UA_BASE_PAV_ALIAS 0x02 | ||
| 241 | #define UA_HYPER_PAV_ALIAS 0x03 | ||
| 242 | |||
| 243 | struct dasd_uid { | ||
| 244 | __u8 type; | ||
| 245 | char vendor[4]; | ||
| 246 | char serial[15]; | ||
| 247 | __u16 ssid; | ||
| 248 | __u8 real_unit_addr; | ||
| 249 | __u8 base_unit_addr; | ||
| 250 | char vduit[33]; | ||
| 251 | }; | ||
| 252 | |||
| 253 | /* | ||
| 232 | * the struct dasd_discipline is | 254 | * the struct dasd_discipline is |
| 233 | * sth like a table of virtual functions, if you think of dasd_eckd | 255 | * sth like a table of virtual functions, if you think of dasd_eckd |
| 234 | * inheriting dasd... | 256 | * inheriting dasd... |
| @@ -312,28 +334,15 @@ struct dasd_discipline { | |||
| 312 | /* suspend/resume functions */ | 334 | /* suspend/resume functions */ |
| 313 | int (*freeze) (struct dasd_device *); | 335 | int (*freeze) (struct dasd_device *); |
| 314 | int (*restore) (struct dasd_device *); | 336 | int (*restore) (struct dasd_device *); |
| 315 | }; | ||
| 316 | 337 | ||
| 317 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | 338 | /* reload device after state change */ |
| 318 | 339 | int (*reload) (struct dasd_device *); | |
| 319 | /* | ||
| 320 | * Unique identifier for dasd device. | ||
| 321 | */ | ||
| 322 | #define UA_NOT_CONFIGURED 0x00 | ||
| 323 | #define UA_BASE_DEVICE 0x01 | ||
| 324 | #define UA_BASE_PAV_ALIAS 0x02 | ||
| 325 | #define UA_HYPER_PAV_ALIAS 0x03 | ||
| 326 | 340 | ||
| 327 | struct dasd_uid { | 341 | int (*get_uid) (struct dasd_device *, struct dasd_uid *); |
| 328 | __u8 type; | ||
| 329 | char vendor[4]; | ||
| 330 | char serial[15]; | ||
| 331 | __u16 ssid; | ||
| 332 | __u8 real_unit_addr; | ||
| 333 | __u8 base_unit_addr; | ||
| 334 | char vduit[33]; | ||
| 335 | }; | 342 | }; |
| 336 | 343 | ||
| 344 | extern struct dasd_discipline *dasd_diag_discipline_pointer; | ||
| 345 | |||
| 337 | /* | 346 | /* |
| 338 | * Notification numbers for extended error reporting notifications: | 347 | * Notification numbers for extended error reporting notifications: |
| 339 | * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's | 348 | * The DASD_EER_DISABLE notification is sent before a dasd_device (and it's |
| @@ -386,6 +395,7 @@ struct dasd_device { | |||
| 386 | struct tasklet_struct tasklet; | 395 | struct tasklet_struct tasklet; |
| 387 | struct work_struct kick_work; | 396 | struct work_struct kick_work; |
| 388 | struct work_struct restore_device; | 397 | struct work_struct restore_device; |
| 398 | struct work_struct reload_device; | ||
| 389 | struct timer_list timer; | 399 | struct timer_list timer; |
| 390 | 400 | ||
| 391 | debug_info_t *debug_area; | 401 | debug_info_t *debug_area; |
| @@ -582,6 +592,7 @@ void dasd_enable_device(struct dasd_device *); | |||
| 582 | void dasd_set_target_state(struct dasd_device *, int); | 592 | void dasd_set_target_state(struct dasd_device *, int); |
| 583 | void dasd_kick_device(struct dasd_device *); | 593 | void dasd_kick_device(struct dasd_device *); |
| 584 | void dasd_restore_device(struct dasd_device *); | 594 | void dasd_restore_device(struct dasd_device *); |
| 595 | void dasd_reload_device(struct dasd_device *); | ||
| 585 | 596 | ||
| 586 | void dasd_add_request_head(struct dasd_ccw_req *); | 597 | void dasd_add_request_head(struct dasd_ccw_req *); |
| 587 | void dasd_add_request_tail(struct dasd_ccw_req *); | 598 | void dasd_add_request_tail(struct dasd_ccw_req *); |
| @@ -629,8 +640,6 @@ void dasd_devmap_exit(void); | |||
| 629 | struct dasd_device *dasd_create_device(struct ccw_device *); | 640 | struct dasd_device *dasd_create_device(struct ccw_device *); |
| 630 | void dasd_delete_device(struct dasd_device *); | 641 | void dasd_delete_device(struct dasd_device *); |
| 631 | 642 | ||
| 632 | int dasd_get_uid(struct ccw_device *, struct dasd_uid *); | ||
| 633 | int dasd_set_uid(struct ccw_device *, struct dasd_uid *); | ||
| 634 | int dasd_get_feature(struct ccw_device *, int); | 643 | int dasd_get_feature(struct ccw_device *, int); |
| 635 | int dasd_set_feature(struct ccw_device *, int, int); | 644 | int dasd_set_feature(struct ccw_device *, int, int); |
| 636 | 645 | ||
diff --git a/drivers/s390/char/Kconfig b/drivers/s390/char/Kconfig index 4e34d3686c23..40834f18754c 100644 --- a/drivers/s390/char/Kconfig +++ b/drivers/s390/char/Kconfig | |||
| @@ -148,13 +148,12 @@ config VMLOGRDR | |||
| 148 | This driver depends on the IUCV support driver. | 148 | This driver depends on the IUCV support driver. |
| 149 | 149 | ||
| 150 | config VMCP | 150 | config VMCP |
| 151 | tristate "Support for the z/VM CP interface (VM only)" | 151 | bool "Support for the z/VM CP interface" |
| 152 | depends on S390 | 152 | depends on S390 |
| 153 | help | 153 | help |
| 154 | Select this option if you want to be able to interact with the control | 154 | Select this option if you want to be able to interact with the control |
| 155 | program on z/VM | 155 | program on z/VM |
| 156 | 156 | ||
| 157 | |||
| 158 | config MONREADER | 157 | config MONREADER |
| 159 | tristate "API for reading z/VM monitor service records" | 158 | tristate "API for reading z/VM monitor service records" |
| 160 | depends on IUCV | 159 | depends on IUCV |
diff --git a/drivers/s390/char/fs3270.c b/drivers/s390/char/fs3270.c index 0eabcca3c92d..857dfcb7b359 100644 --- a/drivers/s390/char/fs3270.c +++ b/drivers/s390/char/fs3270.c | |||
| @@ -484,6 +484,7 @@ fs3270_open(struct inode *inode, struct file *filp) | |||
| 484 | raw3270_del_view(&fp->view); | 484 | raw3270_del_view(&fp->view); |
| 485 | goto out; | 485 | goto out; |
| 486 | } | 486 | } |
| 487 | nonseekable_open(inode, filp); | ||
| 487 | filp->private_data = fp; | 488 | filp->private_data = fp; |
| 488 | out: | 489 | out: |
| 489 | mutex_unlock(&fs3270_mutex); | 490 | mutex_unlock(&fs3270_mutex); |
diff --git a/drivers/s390/char/keyboard.c b/drivers/s390/char/keyboard.c index cb6bffe7141a..18d9a497863b 100644 --- a/drivers/s390/char/keyboard.c +++ b/drivers/s390/char/keyboard.c | |||
| @@ -49,7 +49,7 @@ static unsigned char ret_diacr[NR_DEAD] = { | |||
| 49 | struct kbd_data * | 49 | struct kbd_data * |
| 50 | kbd_alloc(void) { | 50 | kbd_alloc(void) { |
| 51 | struct kbd_data *kbd; | 51 | struct kbd_data *kbd; |
| 52 | int i, len; | 52 | int i; |
| 53 | 53 | ||
| 54 | kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); | 54 | kbd = kzalloc(sizeof(struct kbd_data), GFP_KERNEL); |
| 55 | if (!kbd) | 55 | if (!kbd) |
| @@ -59,12 +59,11 @@ kbd_alloc(void) { | |||
| 59 | goto out_kbd; | 59 | goto out_kbd; |
| 60 | for (i = 0; i < ARRAY_SIZE(key_maps); i++) { | 60 | for (i = 0; i < ARRAY_SIZE(key_maps); i++) { |
| 61 | if (key_maps[i]) { | 61 | if (key_maps[i]) { |
| 62 | kbd->key_maps[i] = | 62 | kbd->key_maps[i] = kmemdup(key_maps[i], |
| 63 | kmalloc(sizeof(u_short)*NR_KEYS, GFP_KERNEL); | 63 | sizeof(u_short) * NR_KEYS, |
| 64 | GFP_KERNEL); | ||
| 64 | if (!kbd->key_maps[i]) | 65 | if (!kbd->key_maps[i]) |
| 65 | goto out_maps; | 66 | goto out_maps; |
| 66 | memcpy(kbd->key_maps[i], key_maps[i], | ||
| 67 | sizeof(u_short)*NR_KEYS); | ||
| 68 | } | 67 | } |
| 69 | } | 68 | } |
| 70 | kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); | 69 | kbd->func_table = kzalloc(sizeof(func_table), GFP_KERNEL); |
| @@ -72,23 +71,21 @@ kbd_alloc(void) { | |||
| 72 | goto out_maps; | 71 | goto out_maps; |
| 73 | for (i = 0; i < ARRAY_SIZE(func_table); i++) { | 72 | for (i = 0; i < ARRAY_SIZE(func_table); i++) { |
| 74 | if (func_table[i]) { | 73 | if (func_table[i]) { |
| 75 | len = strlen(func_table[i]) + 1; | 74 | kbd->func_table[i] = kstrdup(func_table[i], |
| 76 | kbd->func_table[i] = kmalloc(len, GFP_KERNEL); | 75 | GFP_KERNEL); |
| 77 | if (!kbd->func_table[i]) | 76 | if (!kbd->func_table[i]) |
| 78 | goto out_func; | 77 | goto out_func; |
| 79 | memcpy(kbd->func_table[i], func_table[i], len); | ||
| 80 | } | 78 | } |
| 81 | } | 79 | } |
| 82 | kbd->fn_handler = | 80 | kbd->fn_handler = |
| 83 | kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); | 81 | kzalloc(sizeof(fn_handler_fn *) * NR_FN_HANDLER, GFP_KERNEL); |
| 84 | if (!kbd->fn_handler) | 82 | if (!kbd->fn_handler) |
| 85 | goto out_func; | 83 | goto out_func; |
| 86 | kbd->accent_table = | 84 | kbd->accent_table = kmemdup(accent_table, |
| 87 | kmalloc(sizeof(struct kbdiacruc)*MAX_DIACR, GFP_KERNEL); | 85 | sizeof(struct kbdiacruc) * MAX_DIACR, |
| 86 | GFP_KERNEL); | ||
| 88 | if (!kbd->accent_table) | 87 | if (!kbd->accent_table) |
| 89 | goto out_fn_handler; | 88 | goto out_fn_handler; |
| 90 | memcpy(kbd->accent_table, accent_table, | ||
| 91 | sizeof(struct kbdiacruc)*MAX_DIACR); | ||
| 92 | kbd->accent_table_size = accent_table_size; | 89 | kbd->accent_table_size = accent_table_size; |
| 93 | return kbd; | 90 | return kbd; |
| 94 | 91 | ||
diff --git a/drivers/s390/char/vmcp.c b/drivers/s390/char/vmcp.c index 5bb59d36a6d4..04e532eec032 100644 --- a/drivers/s390/char/vmcp.c +++ b/drivers/s390/char/vmcp.c | |||
| @@ -1,24 +1,20 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright IBM Corp. 2004,2007 | 2 | * Copyright IBM Corp. 2004,2010 |
| 3 | * Interface implementation for communication with the z/VM control program | 3 | * Interface implementation for communication with the z/VM control program |
| 4 | * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> | ||
| 5 | * | 4 | * |
| 5 | * Author(s): Christian Borntraeger <borntraeger@de.ibm.com> | ||
| 6 | * | 6 | * |
| 7 | * z/VMs CP offers the possibility to issue commands via the diagnose code 8 | 7 | * z/VMs CP offers the possibility to issue commands via the diagnose code 8 |
| 8 | * this driver implements a character device that issues these commands and | 8 | * this driver implements a character device that issues these commands and |
| 9 | * returns the answer of CP. | 9 | * returns the answer of CP. |
| 10 | 10 | * | |
| 11 | * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS | 11 | * The idea of this driver is based on cpint from Neale Ferguson and #CP in CMS |
| 12 | */ | 12 | */ |
| 13 | 13 | ||
| 14 | #define KMSG_COMPONENT "vmcp" | ||
| 15 | #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt | ||
| 16 | |||
| 17 | #include <linux/fs.h> | 14 | #include <linux/fs.h> |
| 18 | #include <linux/init.h> | 15 | #include <linux/init.h> |
| 19 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
| 20 | #include <linux/miscdevice.h> | 17 | #include <linux/miscdevice.h> |
| 21 | #include <linux/module.h> | ||
| 22 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
| 23 | #include <asm/compat.h> | 19 | #include <asm/compat.h> |
| 24 | #include <asm/cpcmd.h> | 20 | #include <asm/cpcmd.h> |
| @@ -26,10 +22,6 @@ | |||
| 26 | #include <asm/uaccess.h> | 22 | #include <asm/uaccess.h> |
| 27 | #include "vmcp.h" | 23 | #include "vmcp.h" |
| 28 | 24 | ||
| 29 | MODULE_LICENSE("GPL"); | ||
| 30 | MODULE_AUTHOR("Christian Borntraeger <borntraeger@de.ibm.com>"); | ||
| 31 | MODULE_DESCRIPTION("z/VM CP interface"); | ||
| 32 | |||
| 33 | static debug_info_t *vmcp_debug; | 25 | static debug_info_t *vmcp_debug; |
| 34 | 26 | ||
| 35 | static int vmcp_open(struct inode *inode, struct file *file) | 27 | static int vmcp_open(struct inode *inode, struct file *file) |
| @@ -197,11 +189,8 @@ static int __init vmcp_init(void) | |||
| 197 | { | 189 | { |
| 198 | int ret; | 190 | int ret; |
| 199 | 191 | ||
| 200 | if (!MACHINE_IS_VM) { | 192 | if (!MACHINE_IS_VM) |
| 201 | pr_warning("The z/VM CP interface device driver cannot be " | 193 | return 0; |
| 202 | "loaded without z/VM\n"); | ||
| 203 | return -ENODEV; | ||
| 204 | } | ||
| 205 | 194 | ||
| 206 | vmcp_debug = debug_register("vmcp", 1, 1, 240); | 195 | vmcp_debug = debug_register("vmcp", 1, 1, 240); |
| 207 | if (!vmcp_debug) | 196 | if (!vmcp_debug) |
| @@ -214,19 +203,8 @@ static int __init vmcp_init(void) | |||
| 214 | } | 203 | } |
| 215 | 204 | ||
| 216 | ret = misc_register(&vmcp_dev); | 205 | ret = misc_register(&vmcp_dev); |
| 217 | if (ret) { | 206 | if (ret) |
| 218 | debug_unregister(vmcp_debug); | 207 | debug_unregister(vmcp_debug); |
| 219 | return ret; | 208 | return ret; |
| 220 | } | ||
| 221 | |||
| 222 | return 0; | ||
| 223 | } | ||
| 224 | |||
| 225 | static void __exit vmcp_exit(void) | ||
| 226 | { | ||
| 227 | misc_deregister(&vmcp_dev); | ||
| 228 | debug_unregister(vmcp_debug); | ||
| 229 | } | 209 | } |
| 230 | 210 | device_initcall(vmcp_init); | |
| 231 | module_init(vmcp_init); | ||
| 232 | module_exit(vmcp_exit); | ||
diff --git a/drivers/s390/char/zcore.c b/drivers/s390/char/zcore.c index 7217966f7d31..f5ea3384a4b9 100644 --- a/drivers/s390/char/zcore.c +++ b/drivers/s390/char/zcore.c | |||
| @@ -445,7 +445,7 @@ static int zcore_memmap_open(struct inode *inode, struct file *filp) | |||
| 445 | } | 445 | } |
| 446 | kfree(chunk_array); | 446 | kfree(chunk_array); |
| 447 | filp->private_data = buf; | 447 | filp->private_data = buf; |
| 448 | return 0; | 448 | return nonseekable_open(inode, filp); |
| 449 | } | 449 | } |
| 450 | 450 | ||
| 451 | static int zcore_memmap_release(struct inode *inode, struct file *filp) | 451 | static int zcore_memmap_release(struct inode *inode, struct file *filp) |
| @@ -473,7 +473,7 @@ static ssize_t zcore_reipl_write(struct file *filp, const char __user *buf, | |||
| 473 | 473 | ||
| 474 | static int zcore_reipl_open(struct inode *inode, struct file *filp) | 474 | static int zcore_reipl_open(struct inode *inode, struct file *filp) |
| 475 | { | 475 | { |
| 476 | return 0; | 476 | return nonseekable_open(inode, filp); |
| 477 | } | 477 | } |
| 478 | 478 | ||
| 479 | static int zcore_reipl_release(struct inode *inode, struct file *filp) | 479 | static int zcore_reipl_release(struct inode *inode, struct file *filp) |
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 3b6f4adc5094..a83877c664a6 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
| @@ -803,6 +803,7 @@ static long chsc_ioctl(struct file *filp, unsigned int cmd, | |||
| 803 | 803 | ||
| 804 | static const struct file_operations chsc_fops = { | 804 | static const struct file_operations chsc_fops = { |
| 805 | .owner = THIS_MODULE, | 805 | .owner = THIS_MODULE, |
| 806 | .open = nonseekable_open, | ||
| 806 | .unlocked_ioctl = chsc_ioctl, | 807 | .unlocked_ioctl = chsc_ioctl, |
| 807 | .compat_ioctl = chsc_ioctl, | 808 | .compat_ioctl = chsc_ioctl, |
| 808 | }; | 809 | }; |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 5feea1a371e1..f4e6cf3aceb8 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
| @@ -616,7 +616,8 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
| 616 | struct pt_regs *old_regs; | 616 | struct pt_regs *old_regs; |
| 617 | 617 | ||
| 618 | old_regs = set_irq_regs(regs); | 618 | old_regs = set_irq_regs(regs); |
| 619 | s390_idle_check(); | 619 | s390_idle_check(regs, S390_lowcore.int_clock, |
| 620 | S390_lowcore.async_enter_timer); | ||
| 620 | irq_enter(); | 621 | irq_enter(); |
| 621 | __get_cpu_var(s390_idle).nohz_delay = 1; | 622 | __get_cpu_var(s390_idle).nohz_delay = 1; |
| 622 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) | 623 | if (S390_lowcore.int_clock >= S390_lowcore.clock_comparator) |
diff --git a/drivers/s390/cio/css.c b/drivers/s390/cio/css.c index 511649115bd7..ac94ac751459 100644 --- a/drivers/s390/cio/css.c +++ b/drivers/s390/cio/css.c | |||
| @@ -648,6 +648,8 @@ static void css_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
| 648 | static void __init | 648 | static void __init |
| 649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | 649 | css_generate_pgid(struct channel_subsystem *css, u32 tod_high) |
| 650 | { | 650 | { |
| 651 | struct cpuid cpu_id; | ||
| 652 | |||
| 651 | if (css_general_characteristics.mcss) { | 653 | if (css_general_characteristics.mcss) { |
| 652 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; | 654 | css->global_pgid.pgid_high.ext_cssid.version = 0x80; |
| 653 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; | 655 | css->global_pgid.pgid_high.ext_cssid.cssid = css->cssid; |
| @@ -658,8 +660,9 @@ css_generate_pgid(struct channel_subsystem *css, u32 tod_high) | |||
| 658 | css->global_pgid.pgid_high.cpu_addr = 0; | 660 | css->global_pgid.pgid_high.cpu_addr = 0; |
| 659 | #endif | 661 | #endif |
| 660 | } | 662 | } |
| 661 | css->global_pgid.cpu_id = S390_lowcore.cpu_id.ident; | 663 | get_cpu_id(&cpu_id); |
| 662 | css->global_pgid.cpu_model = S390_lowcore.cpu_id.machine; | 664 | css->global_pgid.cpu_id = cpu_id.ident; |
| 665 | css->global_pgid.cpu_model = cpu_id.machine; | ||
| 663 | css->global_pgid.tod_high = tod_high; | 666 | css->global_pgid.tod_high = tod_high; |
| 664 | 667 | ||
| 665 | } | 668 | } |
| @@ -1062,6 +1065,7 @@ static ssize_t cio_settle_write(struct file *file, const char __user *buf, | |||
| 1062 | } | 1065 | } |
| 1063 | 1066 | ||
| 1064 | static const struct file_operations cio_settle_proc_fops = { | 1067 | static const struct file_operations cio_settle_proc_fops = { |
| 1068 | .open = nonseekable_open, | ||
| 1065 | .write = cio_settle_write, | 1069 | .write = cio_settle_write, |
| 1066 | }; | 1070 | }; |
| 1067 | 1071 | ||
diff --git a/drivers/s390/cio/qdio.h b/drivers/s390/cio/qdio.h index 48aa0647432b..f0037eefd44e 100644 --- a/drivers/s390/cio/qdio.h +++ b/drivers/s390/cio/qdio.h | |||
| @@ -13,8 +13,8 @@ | |||
| 13 | #include <asm/debug.h> | 13 | #include <asm/debug.h> |
| 14 | #include "chsc.h" | 14 | #include "chsc.h" |
| 15 | 15 | ||
| 16 | #define QDIO_BUSY_BIT_PATIENCE 100 /* 100 microseconds */ | 16 | #define QDIO_BUSY_BIT_PATIENCE (100 << 12) /* 100 microseconds */ |
| 17 | #define QDIO_INPUT_THRESHOLD 500 /* 500 microseconds */ | 17 | #define QDIO_INPUT_THRESHOLD (500 << 12) /* 500 microseconds */ |
| 18 | 18 | ||
| 19 | /* | 19 | /* |
| 20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait | 20 | * if an asynchronous HiperSockets queue runs full, the 10 seconds timer wait |
| @@ -296,10 +296,8 @@ struct qdio_q { | |||
| 296 | struct qdio_irq *irq_ptr; | 296 | struct qdio_irq *irq_ptr; |
| 297 | struct sl *sl; | 297 | struct sl *sl; |
| 298 | /* | 298 | /* |
| 299 | * Warning: Leave this member at the end so it won't be cleared in | 299 | * A page is allocated under this pointer and used for slib and sl. |
| 300 | * qdio_fill_qs. A page is allocated under this pointer and used for | 300 | * slib is 2048 bytes big and sl points to offset PAGE_SIZE / 2. |
| 301 | * slib and sl. slib is 2048 bytes big and sl points to offset | ||
| 302 | * PAGE_SIZE / 2. | ||
| 303 | */ | 301 | */ |
| 304 | struct slib *slib; | 302 | struct slib *slib; |
| 305 | } __attribute__ ((aligned(256))); | 303 | } __attribute__ ((aligned(256))); |
| @@ -372,11 +370,6 @@ static inline int multicast_outbound(struct qdio_q *q) | |||
| 372 | (q->nr == q->irq_ptr->nr_output_qs - 1); | 370 | (q->nr == q->irq_ptr->nr_output_qs - 1); |
| 373 | } | 371 | } |
| 374 | 372 | ||
| 375 | static inline unsigned long long get_usecs(void) | ||
| 376 | { | ||
| 377 | return monotonic_clock() >> 12; | ||
| 378 | } | ||
| 379 | |||
| 380 | #define pci_out_supported(q) \ | 373 | #define pci_out_supported(q) \ |
| 381 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) | 374 | (q->irq_ptr->qib.ac & QIB_AC_OUTBOUND_PCI_SUPPORTED) |
| 382 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) | 375 | #define is_qebsm(q) (q->irq_ptr->sch_token != 0) |
diff --git a/drivers/s390/cio/qdio_main.c b/drivers/s390/cio/qdio_main.c index 88be7b9ea6e1..00520f9a7a8e 100644 --- a/drivers/s390/cio/qdio_main.c +++ b/drivers/s390/cio/qdio_main.c | |||
| @@ -336,10 +336,10 @@ again: | |||
| 336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); | 336 | WARN_ON(queue_type(q) != QDIO_IQDIO_QFMT || cc != 2); |
| 337 | 337 | ||
| 338 | if (!start_time) { | 338 | if (!start_time) { |
| 339 | start_time = get_usecs(); | 339 | start_time = get_clock(); |
| 340 | goto again; | 340 | goto again; |
| 341 | } | 341 | } |
| 342 | if ((get_usecs() - start_time) < QDIO_BUSY_BIT_PATIENCE) | 342 | if ((get_clock() - start_time) < QDIO_BUSY_BIT_PATIENCE) |
| 343 | goto again; | 343 | goto again; |
| 344 | } | 344 | } |
| 345 | return cc; | 345 | return cc; |
| @@ -536,7 +536,7 @@ static int qdio_inbound_q_moved(struct qdio_q *q) | |||
| 536 | if ((bufnr != q->last_move) || q->qdio_error) { | 536 | if ((bufnr != q->last_move) || q->qdio_error) { |
| 537 | q->last_move = bufnr; | 537 | q->last_move = bufnr; |
| 538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) | 538 | if (!is_thinint_irq(q->irq_ptr) && MACHINE_IS_LPAR) |
| 539 | q->u.in.timestamp = get_usecs(); | 539 | q->u.in.timestamp = get_clock(); |
| 540 | return 1; | 540 | return 1; |
| 541 | } else | 541 | } else |
| 542 | return 0; | 542 | return 0; |
| @@ -567,7 +567,7 @@ static inline int qdio_inbound_q_done(struct qdio_q *q) | |||
| 567 | * At this point we know, that inbound first_to_check | 567 | * At this point we know, that inbound first_to_check |
| 568 | * has (probably) not moved (see qdio_inbound_processing). | 568 | * has (probably) not moved (see qdio_inbound_processing). |
| 569 | */ | 569 | */ |
| 570 | if (get_usecs() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { | 570 | if (get_clock() > q->u.in.timestamp + QDIO_INPUT_THRESHOLD) { |
| 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", | 571 | DBF_DEV_EVENT(DBF_INFO, q->irq_ptr, "in done:%02x", |
| 572 | q->first_to_check); | 572 | q->first_to_check); |
| 573 | return 1; | 573 | return 1; |
| @@ -606,7 +606,7 @@ static void qdio_kick_handler(struct qdio_q *q) | |||
| 606 | static void __qdio_inbound_processing(struct qdio_q *q) | 606 | static void __qdio_inbound_processing(struct qdio_q *q) |
| 607 | { | 607 | { |
| 608 | qperf_inc(q, tasklet_inbound); | 608 | qperf_inc(q, tasklet_inbound); |
| 609 | again: | 609 | |
| 610 | if (!qdio_inbound_q_moved(q)) | 610 | if (!qdio_inbound_q_moved(q)) |
| 611 | return; | 611 | return; |
| 612 | 612 | ||
| @@ -615,7 +615,10 @@ again: | |||
| 615 | if (!qdio_inbound_q_done(q)) { | 615 | if (!qdio_inbound_q_done(q)) { |
| 616 | /* means poll time is not yet over */ | 616 | /* means poll time is not yet over */ |
| 617 | qperf_inc(q, tasklet_inbound_resched); | 617 | qperf_inc(q, tasklet_inbound_resched); |
| 618 | goto again; | 618 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) { |
| 619 | tasklet_schedule(&q->tasklet); | ||
| 620 | return; | ||
| 621 | } | ||
| 619 | } | 622 | } |
| 620 | 623 | ||
| 621 | qdio_stop_polling(q); | 624 | qdio_stop_polling(q); |
| @@ -625,7 +628,8 @@ again: | |||
| 625 | */ | 628 | */ |
| 626 | if (!qdio_inbound_q_done(q)) { | 629 | if (!qdio_inbound_q_done(q)) { |
| 627 | qperf_inc(q, tasklet_inbound_resched2); | 630 | qperf_inc(q, tasklet_inbound_resched2); |
| 628 | goto again; | 631 | if (likely(q->irq_ptr->state != QDIO_IRQ_STATE_STOPPED)) |
| 632 | tasklet_schedule(&q->tasklet); | ||
| 629 | } | 633 | } |
| 630 | } | 634 | } |
| 631 | 635 | ||
| @@ -955,6 +959,9 @@ void qdio_int_handler(struct ccw_device *cdev, unsigned long intparm, | |||
| 955 | return; | 959 | return; |
| 956 | } | 960 | } |
| 957 | 961 | ||
| 962 | if (irq_ptr->perf_stat_enabled) | ||
| 963 | irq_ptr->perf_stat.qdio_int++; | ||
| 964 | |||
| 958 | if (IS_ERR(irb)) { | 965 | if (IS_ERR(irb)) { |
| 959 | switch (PTR_ERR(irb)) { | 966 | switch (PTR_ERR(irb)) { |
| 960 | case -EIO: | 967 | case -EIO: |
| @@ -1016,30 +1023,6 @@ int qdio_get_ssqd_desc(struct ccw_device *cdev, | |||
| 1016 | } | 1023 | } |
| 1017 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); | 1024 | EXPORT_SYMBOL_GPL(qdio_get_ssqd_desc); |
| 1018 | 1025 | ||
| 1019 | /** | ||
| 1020 | * qdio_cleanup - shutdown queues and free data structures | ||
| 1021 | * @cdev: associated ccw device | ||
| 1022 | * @how: use halt or clear to shutdown | ||
| 1023 | * | ||
| 1024 | * This function calls qdio_shutdown() for @cdev with method @how. | ||
| 1025 | * and qdio_free(). The qdio_free() return value is ignored since | ||
| 1026 | * !irq_ptr is already checked. | ||
| 1027 | */ | ||
| 1028 | int qdio_cleanup(struct ccw_device *cdev, int how) | ||
| 1029 | { | ||
| 1030 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | ||
| 1031 | int rc; | ||
| 1032 | |||
| 1033 | if (!irq_ptr) | ||
| 1034 | return -ENODEV; | ||
| 1035 | |||
| 1036 | rc = qdio_shutdown(cdev, how); | ||
| 1037 | |||
| 1038 | qdio_free(cdev); | ||
| 1039 | return rc; | ||
| 1040 | } | ||
| 1041 | EXPORT_SYMBOL_GPL(qdio_cleanup); | ||
| 1042 | |||
| 1043 | static void qdio_shutdown_queues(struct ccw_device *cdev) | 1026 | static void qdio_shutdown_queues(struct ccw_device *cdev) |
| 1044 | { | 1027 | { |
| 1045 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; | 1028 | struct qdio_irq *irq_ptr = cdev->private->qdio_data; |
| @@ -1157,28 +1140,6 @@ int qdio_free(struct ccw_device *cdev) | |||
| 1157 | EXPORT_SYMBOL_GPL(qdio_free); | 1140 | EXPORT_SYMBOL_GPL(qdio_free); |
| 1158 | 1141 | ||
| 1159 | /** | 1142 | /** |
| 1160 | * qdio_initialize - allocate and establish queues for a qdio subchannel | ||
| 1161 | * @init_data: initialization data | ||
| 1162 | * | ||
| 1163 | * This function first allocates queues via qdio_allocate() and on success | ||
| 1164 | * establishes them via qdio_establish(). | ||
| 1165 | */ | ||
| 1166 | int qdio_initialize(struct qdio_initialize *init_data) | ||
| 1167 | { | ||
| 1168 | int rc; | ||
| 1169 | |||
| 1170 | rc = qdio_allocate(init_data); | ||
| 1171 | if (rc) | ||
| 1172 | return rc; | ||
| 1173 | |||
| 1174 | rc = qdio_establish(init_data); | ||
| 1175 | if (rc) | ||
| 1176 | qdio_free(init_data->cdev); | ||
| 1177 | return rc; | ||
| 1178 | } | ||
| 1179 | EXPORT_SYMBOL_GPL(qdio_initialize); | ||
| 1180 | |||
| 1181 | /** | ||
| 1182 | * qdio_allocate - allocate qdio queues and associated data | 1143 | * qdio_allocate - allocate qdio queues and associated data |
| 1183 | * @init_data: initialization data | 1144 | * @init_data: initialization data |
| 1184 | */ | 1145 | */ |
diff --git a/drivers/s390/cio/qdio_setup.c b/drivers/s390/cio/qdio_setup.c index 7f4a75465140..6326b67c45d2 100644 --- a/drivers/s390/cio/qdio_setup.c +++ b/drivers/s390/cio/qdio_setup.c | |||
| @@ -106,10 +106,12 @@ int qdio_allocate_qs(struct qdio_irq *irq_ptr, int nr_input_qs, int nr_output_qs | |||
| 106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, | 106 | static void setup_queues_misc(struct qdio_q *q, struct qdio_irq *irq_ptr, |
| 107 | qdio_handler_t *handler, int i) | 107 | qdio_handler_t *handler, int i) |
| 108 | { | 108 | { |
| 109 | /* must be cleared by every qdio_establish */ | 109 | struct slib *slib = q->slib; |
| 110 | memset(q, 0, ((char *)&q->slib) - ((char *)q)); | ||
| 111 | memset(q->slib, 0, PAGE_SIZE); | ||
| 112 | 110 | ||
| 111 | /* queue must be cleared for qdio_establish */ | ||
| 112 | memset(q, 0, sizeof(*q)); | ||
| 113 | memset(slib, 0, PAGE_SIZE); | ||
| 114 | q->slib = slib; | ||
| 113 | q->irq_ptr = irq_ptr; | 115 | q->irq_ptr = irq_ptr; |
| 114 | q->mask = 1 << (31 - i); | 116 | q->mask = 1 << (31 - i); |
| 115 | q->nr = i; | 117 | q->nr = i; |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index ce5f8910ff83..8daf1b99f153 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
| @@ -95,7 +95,7 @@ void tiqdio_add_input_queues(struct qdio_irq *irq_ptr) | |||
| 95 | for_each_input_queue(irq_ptr, q, i) | 95 | for_each_input_queue(irq_ptr, q, i) |
| 96 | list_add_rcu(&q->entry, &tiq_list); | 96 | list_add_rcu(&q->entry, &tiq_list); |
| 97 | mutex_unlock(&tiq_list_lock); | 97 | mutex_unlock(&tiq_list_lock); |
| 98 | xchg(irq_ptr->dsci, 1); | 98 | xchg(irq_ptr->dsci, 1 << 7); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) | 101 | void tiqdio_remove_input_queues(struct qdio_irq *irq_ptr) |
| @@ -173,7 +173,7 @@ static void tiqdio_thinint_handler(void *ind, void *drv_data) | |||
| 173 | 173 | ||
| 174 | /* prevent racing */ | 174 | /* prevent racing */ |
| 175 | if (*tiqdio_alsi) | 175 | if (*tiqdio_alsi) |
| 176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1); | 176 | xchg(&q_indicators[TIQDIO_SHARED_IND].ind, 1 << 7); |
| 177 | } | 177 | } |
| 178 | } | 178 | } |
| 179 | 179 | ||
diff --git a/drivers/s390/crypto/zcrypt_api.c b/drivers/s390/crypto/zcrypt_api.c index 304caf549973..41e0aaefafd5 100644 --- a/drivers/s390/crypto/zcrypt_api.c +++ b/drivers/s390/crypto/zcrypt_api.c | |||
| @@ -302,7 +302,7 @@ static ssize_t zcrypt_write(struct file *filp, const char __user *buf, | |||
| 302 | static int zcrypt_open(struct inode *inode, struct file *filp) | 302 | static int zcrypt_open(struct inode *inode, struct file *filp) |
| 303 | { | 303 | { |
| 304 | atomic_inc(&zcrypt_open_count); | 304 | atomic_inc(&zcrypt_open_count); |
| 305 | return 0; | 305 | return nonseekable_open(inode, filp); |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | /** | 308 | /** |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 3ba738b2e271..28f71349fdec 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
| @@ -1292,13 +1292,14 @@ int qeth_qdio_clear_card(struct qeth_card *card, int use_halt) | |||
| 1292 | QETH_QDIO_CLEANING)) { | 1292 | QETH_QDIO_CLEANING)) { |
| 1293 | case QETH_QDIO_ESTABLISHED: | 1293 | case QETH_QDIO_ESTABLISHED: |
| 1294 | if (card->info.type == QETH_CARD_TYPE_IQD) | 1294 | if (card->info.type == QETH_CARD_TYPE_IQD) |
| 1295 | rc = qdio_cleanup(CARD_DDEV(card), | 1295 | rc = qdio_shutdown(CARD_DDEV(card), |
| 1296 | QDIO_FLAG_CLEANUP_USING_HALT); | 1296 | QDIO_FLAG_CLEANUP_USING_HALT); |
| 1297 | else | 1297 | else |
| 1298 | rc = qdio_cleanup(CARD_DDEV(card), | 1298 | rc = qdio_shutdown(CARD_DDEV(card), |
| 1299 | QDIO_FLAG_CLEANUP_USING_CLEAR); | 1299 | QDIO_FLAG_CLEANUP_USING_CLEAR); |
| 1300 | if (rc) | 1300 | if (rc) |
| 1301 | QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); | 1301 | QETH_DBF_TEXT_(TRACE, 3, "1err%d", rc); |
| 1302 | qdio_free(CARD_DDEV(card)); | ||
| 1302 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | 1303 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
| 1303 | break; | 1304 | break; |
| 1304 | case QETH_QDIO_CLEANING: | 1305 | case QETH_QDIO_CLEANING: |
| @@ -3810,10 +3811,18 @@ static int qeth_qdio_establish(struct qeth_card *card) | |||
| 3810 | 3811 | ||
| 3811 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, | 3812 | if (atomic_cmpxchg(&card->qdio.state, QETH_QDIO_ALLOCATED, |
| 3812 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { | 3813 | QETH_QDIO_ESTABLISHED) == QETH_QDIO_ALLOCATED) { |
| 3813 | rc = qdio_initialize(&init_data); | 3814 | rc = qdio_allocate(&init_data); |
| 3814 | if (rc) | 3815 | if (rc) { |
| 3816 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | ||
| 3817 | goto out; | ||
| 3818 | } | ||
| 3819 | rc = qdio_establish(&init_data); | ||
| 3820 | if (rc) { | ||
| 3815 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); | 3821 | atomic_set(&card->qdio.state, QETH_QDIO_ALLOCATED); |
| 3822 | qdio_free(CARD_DDEV(card)); | ||
| 3823 | } | ||
| 3816 | } | 3824 | } |
| 3825 | out: | ||
| 3817 | kfree(out_sbal_ptrs); | 3826 | kfree(out_sbal_ptrs); |
| 3818 | kfree(in_sbal_ptrs); | 3827 | kfree(in_sbal_ptrs); |
| 3819 | kfree(qib_param_field); | 3828 | kfree(qib_param_field); |
diff --git a/drivers/s390/scsi/zfcp_cfdc.c b/drivers/s390/scsi/zfcp_cfdc.c index 25d9e0ae9c57..1a2db0a35737 100644 --- a/drivers/s390/scsi/zfcp_cfdc.c +++ b/drivers/s390/scsi/zfcp_cfdc.c | |||
| @@ -254,6 +254,7 @@ static long zfcp_cfdc_dev_ioctl(struct file *file, unsigned int command, | |||
| 254 | } | 254 | } |
| 255 | 255 | ||
| 256 | static const struct file_operations zfcp_cfdc_fops = { | 256 | static const struct file_operations zfcp_cfdc_fops = { |
| 257 | .open = nonseekable_open, | ||
| 257 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, | 258 | .unlocked_ioctl = zfcp_cfdc_dev_ioctl, |
| 258 | #ifdef CONFIG_COMPAT | 259 | #ifdef CONFIG_COMPAT |
| 259 | .compat_ioctl = zfcp_cfdc_dev_ioctl | 260 | .compat_ioctl = zfcp_cfdc_dev_ioctl |
diff --git a/drivers/scsi/advansys.c b/drivers/scsi/advansys.c index 9201afe65609..7f87979da22d 100644 --- a/drivers/scsi/advansys.c +++ b/drivers/scsi/advansys.c | |||
| @@ -4724,6 +4724,10 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) | |||
| 4724 | BUG_ON((unsigned long)asc_dvc->overrun_buf & 7); | 4724 | BUG_ON((unsigned long)asc_dvc->overrun_buf & 7); |
| 4725 | asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf, | 4725 | asc_dvc->overrun_dma = dma_map_single(board->dev, asc_dvc->overrun_buf, |
| 4726 | ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); | 4726 | ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); |
| 4727 | if (dma_mapping_error(board->dev, asc_dvc->overrun_dma)) { | ||
| 4728 | warn_code = -ENOMEM; | ||
| 4729 | goto err_dma_map; | ||
| 4730 | } | ||
| 4727 | phy_addr = cpu_to_le32(asc_dvc->overrun_dma); | 4731 | phy_addr = cpu_to_le32(asc_dvc->overrun_dma); |
| 4728 | AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, | 4732 | AscMemDWordCopyPtrToLram(iop_base, ASCV_OVERRUN_PADDR_D, |
| 4729 | (uchar *)&phy_addr, 1); | 4733 | (uchar *)&phy_addr, 1); |
| @@ -4739,14 +4743,23 @@ static ushort AscInitMicroCodeVar(ASC_DVC_VAR *asc_dvc) | |||
| 4739 | AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); | 4743 | AscSetPCAddr(iop_base, ASC_MCODE_START_ADDR); |
| 4740 | if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { | 4744 | if (AscGetPCAddr(iop_base) != ASC_MCODE_START_ADDR) { |
| 4741 | asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; | 4745 | asc_dvc->err_code |= ASC_IERR_SET_PC_ADDR; |
| 4742 | return warn_code; | 4746 | warn_code = UW_ERR; |
| 4747 | goto err_mcode_start; | ||
| 4743 | } | 4748 | } |
| 4744 | if (AscStartChip(iop_base) != 1) { | 4749 | if (AscStartChip(iop_base) != 1) { |
| 4745 | asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; | 4750 | asc_dvc->err_code |= ASC_IERR_START_STOP_CHIP; |
| 4746 | return warn_code; | 4751 | warn_code = UW_ERR; |
| 4752 | goto err_mcode_start; | ||
| 4747 | } | 4753 | } |
| 4748 | 4754 | ||
| 4749 | return warn_code; | 4755 | return warn_code; |
| 4756 | |||
| 4757 | err_mcode_start: | ||
| 4758 | dma_unmap_single(board->dev, asc_dvc->overrun_dma, | ||
| 4759 | ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); | ||
| 4760 | err_dma_map: | ||
| 4761 | asc_dvc->overrun_dma = 0; | ||
| 4762 | return warn_code; | ||
| 4750 | } | 4763 | } |
| 4751 | 4764 | ||
| 4752 | static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) | 4765 | static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) |
| @@ -4802,6 +4815,8 @@ static ushort AscInitAsc1000Driver(ASC_DVC_VAR *asc_dvc) | |||
| 4802 | } | 4815 | } |
| 4803 | release_firmware(fw); | 4816 | release_firmware(fw); |
| 4804 | warn_code |= AscInitMicroCodeVar(asc_dvc); | 4817 | warn_code |= AscInitMicroCodeVar(asc_dvc); |
| 4818 | if (!asc_dvc->overrun_dma) | ||
| 4819 | return warn_code; | ||
| 4805 | asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; | 4820 | asc_dvc->init_state |= ASC_INIT_STATE_END_LOAD_MC; |
| 4806 | AscEnableInterrupt(iop_base); | 4821 | AscEnableInterrupt(iop_base); |
| 4807 | return warn_code; | 4822 | return warn_code; |
| @@ -7978,9 +7993,10 @@ static int advansys_reset(struct scsi_cmnd *scp) | |||
| 7978 | status = AscInitAsc1000Driver(asc_dvc); | 7993 | status = AscInitAsc1000Driver(asc_dvc); |
| 7979 | 7994 | ||
| 7980 | /* Refer to ASC_IERR_* definitions for meaning of 'err_code'. */ | 7995 | /* Refer to ASC_IERR_* definitions for meaning of 'err_code'. */ |
| 7981 | if (asc_dvc->err_code) { | 7996 | if (asc_dvc->err_code || !asc_dvc->overrun_dma) { |
| 7982 | scmd_printk(KERN_INFO, scp, "SCSI bus reset error: " | 7997 | scmd_printk(KERN_INFO, scp, "SCSI bus reset error: " |
| 7983 | "0x%x\n", asc_dvc->err_code); | 7998 | "0x%x, status: 0x%x\n", asc_dvc->err_code, |
| 7999 | status); | ||
| 7984 | ret = FAILED; | 8000 | ret = FAILED; |
| 7985 | } else if (status) { | 8001 | } else if (status) { |
| 7986 | scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: " | 8002 | scmd_printk(KERN_INFO, scp, "SCSI bus reset warning: " |
| @@ -12311,7 +12327,7 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, | |||
| 12311 | asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL); | 12327 | asc_dvc_varp->overrun_buf = kzalloc(ASC_OVERRUN_BSIZE, GFP_KERNEL); |
| 12312 | if (!asc_dvc_varp->overrun_buf) { | 12328 | if (!asc_dvc_varp->overrun_buf) { |
| 12313 | ret = -ENOMEM; | 12329 | ret = -ENOMEM; |
| 12314 | goto err_free_wide_mem; | 12330 | goto err_free_irq; |
| 12315 | } | 12331 | } |
| 12316 | warn_code = AscInitAsc1000Driver(asc_dvc_varp); | 12332 | warn_code = AscInitAsc1000Driver(asc_dvc_varp); |
| 12317 | 12333 | ||
| @@ -12320,30 +12336,36 @@ static int __devinit advansys_board_found(struct Scsi_Host *shost, | |||
| 12320 | "warn 0x%x, error 0x%x\n", | 12336 | "warn 0x%x, error 0x%x\n", |
| 12321 | asc_dvc_varp->init_state, warn_code, | 12337 | asc_dvc_varp->init_state, warn_code, |
| 12322 | asc_dvc_varp->err_code); | 12338 | asc_dvc_varp->err_code); |
| 12323 | if (asc_dvc_varp->err_code) { | 12339 | if (!asc_dvc_varp->overrun_dma) { |
| 12324 | ret = -ENODEV; | 12340 | ret = -ENODEV; |
| 12325 | kfree(asc_dvc_varp->overrun_buf); | 12341 | goto err_free_mem; |
| 12326 | } | 12342 | } |
| 12327 | } | 12343 | } |
| 12328 | } else { | 12344 | } else { |
| 12329 | if (advansys_wide_init_chip(shost)) | 12345 | if (advansys_wide_init_chip(shost)) { |
| 12330 | ret = -ENODEV; | 12346 | ret = -ENODEV; |
| 12347 | goto err_free_mem; | ||
| 12348 | } | ||
| 12331 | } | 12349 | } |
| 12332 | 12350 | ||
| 12333 | if (ret) | ||
| 12334 | goto err_free_wide_mem; | ||
| 12335 | |||
| 12336 | ASC_DBG_PRT_SCSI_HOST(2, shost); | 12351 | ASC_DBG_PRT_SCSI_HOST(2, shost); |
| 12337 | 12352 | ||
| 12338 | ret = scsi_add_host(shost, boardp->dev); | 12353 | ret = scsi_add_host(shost, boardp->dev); |
| 12339 | if (ret) | 12354 | if (ret) |
| 12340 | goto err_free_wide_mem; | 12355 | goto err_free_mem; |
| 12341 | 12356 | ||
| 12342 | scsi_scan_host(shost); | 12357 | scsi_scan_host(shost); |
| 12343 | return 0; | 12358 | return 0; |
| 12344 | 12359 | ||
| 12345 | err_free_wide_mem: | 12360 | err_free_mem: |
| 12346 | advansys_wide_free_mem(boardp); | 12361 | if (ASC_NARROW_BOARD(boardp)) { |
| 12362 | if (asc_dvc_varp->overrun_dma) | ||
| 12363 | dma_unmap_single(boardp->dev, asc_dvc_varp->overrun_dma, | ||
| 12364 | ASC_OVERRUN_BSIZE, DMA_FROM_DEVICE); | ||
| 12365 | kfree(asc_dvc_varp->overrun_buf); | ||
| 12366 | } else | ||
| 12367 | advansys_wide_free_mem(boardp); | ||
| 12368 | err_free_irq: | ||
| 12347 | free_irq(boardp->irq, shost); | 12369 | free_irq(boardp->irq, shost); |
| 12348 | err_free_dma: | 12370 | err_free_dma: |
| 12349 | #ifdef CONFIG_ISA | 12371 | #ifdef CONFIG_ISA |
diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 6d5ae4474bb3..633e09036357 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c | |||
| @@ -471,12 +471,12 @@ static int iscsi_prep_scsi_cmd_pdu(struct iscsi_task *task) | |||
| 471 | 471 | ||
| 472 | WARN_ON(hdrlength >= 256); | 472 | WARN_ON(hdrlength >= 256); |
| 473 | hdr->hlength = hdrlength & 0xFF; | 473 | hdr->hlength = hdrlength & 0xFF; |
| 474 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | ||
| 474 | 475 | ||
| 475 | if (session->tt->init_task && session->tt->init_task(task)) | 476 | if (session->tt->init_task && session->tt->init_task(task)) |
| 476 | return -EIO; | 477 | return -EIO; |
| 477 | 478 | ||
| 478 | task->state = ISCSI_TASK_RUNNING; | 479 | task->state = ISCSI_TASK_RUNNING; |
| 479 | hdr->cmdsn = task->cmdsn = cpu_to_be32(session->cmdsn); | ||
| 480 | session->cmdsn++; | 480 | session->cmdsn++; |
| 481 | 481 | ||
| 482 | conn->scsicmd_pdus_cnt++; | 482 | conn->scsicmd_pdus_cnt++; |
diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index b00efd19aadb..88f744672576 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c | |||
| @@ -395,11 +395,15 @@ int sas_ata_init_host_and_port(struct domain_device *found_dev, | |||
| 395 | void sas_ata_task_abort(struct sas_task *task) | 395 | void sas_ata_task_abort(struct sas_task *task) |
| 396 | { | 396 | { |
| 397 | struct ata_queued_cmd *qc = task->uldd_task; | 397 | struct ata_queued_cmd *qc = task->uldd_task; |
| 398 | struct request_queue *q = qc->scsicmd->device->request_queue; | ||
| 398 | struct completion *waiting; | 399 | struct completion *waiting; |
| 400 | unsigned long flags; | ||
| 399 | 401 | ||
| 400 | /* Bounce SCSI-initiated commands to the SCSI EH */ | 402 | /* Bounce SCSI-initiated commands to the SCSI EH */ |
| 401 | if (qc->scsicmd) { | 403 | if (qc->scsicmd) { |
| 404 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 402 | blk_abort_request(qc->scsicmd->request); | 405 | blk_abort_request(qc->scsicmd->request); |
| 406 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 403 | scsi_schedule_eh(qc->scsicmd->device->host); | 407 | scsi_schedule_eh(qc->scsicmd->device->host); |
| 404 | return; | 408 | return; |
| 405 | } | 409 | } |
diff --git a/drivers/scsi/libsas/sas_scsi_host.c b/drivers/scsi/libsas/sas_scsi_host.c index 2660e1b4569a..822835055cef 100644 --- a/drivers/scsi/libsas/sas_scsi_host.c +++ b/drivers/scsi/libsas/sas_scsi_host.c | |||
| @@ -1030,6 +1030,8 @@ int __sas_task_abort(struct sas_task *task) | |||
| 1030 | void sas_task_abort(struct sas_task *task) | 1030 | void sas_task_abort(struct sas_task *task) |
| 1031 | { | 1031 | { |
| 1032 | struct scsi_cmnd *sc = task->uldd_task; | 1032 | struct scsi_cmnd *sc = task->uldd_task; |
| 1033 | struct request_queue *q = sc->device->request_queue; | ||
| 1034 | unsigned long flags; | ||
| 1033 | 1035 | ||
| 1034 | /* Escape for libsas internal commands */ | 1036 | /* Escape for libsas internal commands */ |
| 1035 | if (!sc) { | 1037 | if (!sc) { |
| @@ -1044,7 +1046,9 @@ void sas_task_abort(struct sas_task *task) | |||
| 1044 | return; | 1046 | return; |
| 1045 | } | 1047 | } |
| 1046 | 1048 | ||
| 1049 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 1047 | blk_abort_request(sc->request); | 1050 | blk_abort_request(sc->request); |
| 1051 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 1048 | scsi_schedule_eh(sc->device->host); | 1052 | scsi_schedule_eh(sc->device->host); |
| 1049 | } | 1053 | } |
| 1050 | 1054 | ||
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c index 3e10c306de94..3a5bfd10b2cb 100644 --- a/drivers/scsi/scsi_debug.c +++ b/drivers/scsi/scsi_debug.c | |||
| @@ -957,7 +957,8 @@ static int resp_start_stop(struct scsi_cmnd * scp, | |||
| 957 | static sector_t get_sdebug_capacity(void) | 957 | static sector_t get_sdebug_capacity(void) |
| 958 | { | 958 | { |
| 959 | if (scsi_debug_virtual_gb > 0) | 959 | if (scsi_debug_virtual_gb > 0) |
| 960 | return 2048 * 1024 * (sector_t)scsi_debug_virtual_gb; | 960 | return (sector_t)scsi_debug_virtual_gb * |
| 961 | (1073741824 / scsi_debug_sector_size); | ||
| 961 | else | 962 | else |
| 962 | return sdebug_store_sectors; | 963 | return sdebug_store_sectors; |
| 963 | } | 964 | } |
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index d45c69ca5737..7ad53fa42766 100644 --- a/drivers/scsi/scsi_error.c +++ b/drivers/scsi/scsi_error.c | |||
| @@ -302,7 +302,20 @@ static int scsi_check_sense(struct scsi_cmnd *scmd) | |||
| 302 | if (scmd->device->allow_restart && | 302 | if (scmd->device->allow_restart && |
| 303 | (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) | 303 | (sshdr.asc == 0x04) && (sshdr.ascq == 0x02)) |
| 304 | return FAILED; | 304 | return FAILED; |
| 305 | return SUCCESS; | 305 | |
| 306 | if (blk_barrier_rq(scmd->request)) | ||
| 307 | /* | ||
| 308 | * barrier requests should always retry on UA | ||
| 309 | * otherwise block will get a spurious error | ||
| 310 | */ | ||
| 311 | return NEEDS_RETRY; | ||
| 312 | else | ||
| 313 | /* | ||
| 314 | * for normal (non barrier) commands, pass the | ||
| 315 | * UA upwards for a determination in the | ||
| 316 | * completion functions | ||
| 317 | */ | ||
| 318 | return SUCCESS; | ||
| 306 | 319 | ||
| 307 | /* these three are not supported */ | 320 | /* these three are not supported */ |
| 308 | case COPY_ABORTED: | 321 | case COPY_ABORTED: |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 8b827f37b03e..de6c60320f6f 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -1040,6 +1040,7 @@ static void sd_prepare_flush(struct request_queue *q, struct request *rq) | |||
| 1040 | { | 1040 | { |
| 1041 | rq->cmd_type = REQ_TYPE_BLOCK_PC; | 1041 | rq->cmd_type = REQ_TYPE_BLOCK_PC; |
| 1042 | rq->timeout = SD_TIMEOUT; | 1042 | rq->timeout = SD_TIMEOUT; |
| 1043 | rq->retries = SD_MAX_RETRIES; | ||
| 1043 | rq->cmd[0] = SYNCHRONIZE_CACHE; | 1044 | rq->cmd[0] = SYNCHRONIZE_CACHE; |
| 1044 | rq->cmd_len = 10; | 1045 | rq->cmd_len = 10; |
| 1045 | } | 1046 | } |
diff --git a/drivers/scsi/zorro7xx.c b/drivers/scsi/zorro7xx.c index 105449c15fa9..e17764d71476 100644 --- a/drivers/scsi/zorro7xx.c +++ b/drivers/scsi/zorro7xx.c | |||
| @@ -69,6 +69,7 @@ static struct zorro_device_id zorro7xx_zorro_tbl[] __devinitdata = { | |||
| 69 | }, | 69 | }, |
| 70 | { 0 } | 70 | { 0 } |
| 71 | }; | 71 | }; |
| 72 | MODULE_DEVICE_TABLE(zorro, zorro7xx_zorro_tbl); | ||
| 72 | 73 | ||
| 73 | static int __devinit zorro7xx_init_one(struct zorro_dev *z, | 74 | static int __devinit zorro7xx_init_one(struct zorro_dev *z, |
| 74 | const struct zorro_device_id *ent) | 75 | const struct zorro_device_id *ent) |
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c index 2c9bf9b68327..eed3c2d8dd1c 100644 --- a/drivers/serial/atmel_serial.c +++ b/drivers/serial/atmel_serial.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/dma-mapping.h> | 38 | #include <linux/dma-mapping.h> |
| 39 | #include <linux/atmel_pdc.h> | 39 | #include <linux/atmel_pdc.h> |
| 40 | #include <linux/atmel_serial.h> | 40 | #include <linux/atmel_serial.h> |
| 41 | #include <linux/uaccess.h> | ||
| 41 | 42 | ||
| 42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
| 43 | 44 | ||
| @@ -59,6 +60,9 @@ | |||
| 59 | 60 | ||
| 60 | #include <linux/serial_core.h> | 61 | #include <linux/serial_core.h> |
| 61 | 62 | ||
| 63 | static void atmel_start_rx(struct uart_port *port); | ||
| 64 | static void atmel_stop_rx(struct uart_port *port); | ||
| 65 | |||
| 62 | #ifdef CONFIG_SERIAL_ATMEL_TTYAT | 66 | #ifdef CONFIG_SERIAL_ATMEL_TTYAT |
| 63 | 67 | ||
| 64 | /* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we | 68 | /* Use device name ttyAT, major 204 and minor 154-169. This is necessary if we |
| @@ -93,6 +97,7 @@ | |||
| 93 | #define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR) | 97 | #define UART_GET_BRGR(port) __raw_readl((port)->membase + ATMEL_US_BRGR) |
| 94 | #define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR) | 98 | #define UART_PUT_BRGR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_BRGR) |
| 95 | #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) | 99 | #define UART_PUT_RTOR(port,v) __raw_writel(v, (port)->membase + ATMEL_US_RTOR) |
| 100 | #define UART_PUT_TTGR(port, v) __raw_writel(v, (port)->membase + ATMEL_US_TTGR) | ||
| 96 | 101 | ||
| 97 | /* PDC registers */ | 102 | /* PDC registers */ |
| 98 | #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) | 103 | #define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) |
| @@ -147,6 +152,9 @@ struct atmel_uart_port { | |||
| 147 | unsigned int irq_status_prev; | 152 | unsigned int irq_status_prev; |
| 148 | 153 | ||
| 149 | struct circ_buf rx_ring; | 154 | struct circ_buf rx_ring; |
| 155 | |||
| 156 | struct serial_rs485 rs485; /* rs485 settings */ | ||
| 157 | unsigned int tx_done_mask; | ||
| 150 | }; | 158 | }; |
| 151 | 159 | ||
| 152 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; | 160 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
| @@ -187,6 +195,46 @@ static bool atmel_use_dma_tx(struct uart_port *port) | |||
| 187 | } | 195 | } |
| 188 | #endif | 196 | #endif |
| 189 | 197 | ||
| 198 | /* Enable or disable the rs485 support */ | ||
| 199 | void atmel_config_rs485(struct uart_port *port, struct serial_rs485 *rs485conf) | ||
| 200 | { | ||
| 201 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 202 | unsigned int mode; | ||
| 203 | |||
| 204 | spin_lock(&port->lock); | ||
| 205 | |||
| 206 | /* Disable interrupts */ | ||
| 207 | UART_PUT_IDR(port, atmel_port->tx_done_mask); | ||
| 208 | |||
| 209 | mode = UART_GET_MR(port); | ||
| 210 | |||
| 211 | /* Resetting serial mode to RS232 (0x0) */ | ||
| 212 | mode &= ~ATMEL_US_USMODE; | ||
| 213 | |||
| 214 | atmel_port->rs485 = *rs485conf; | ||
| 215 | |||
| 216 | if (rs485conf->flags & SER_RS485_ENABLED) { | ||
| 217 | dev_dbg(port->dev, "Setting UART to RS485\n"); | ||
| 218 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | ||
| 219 | UART_PUT_TTGR(port, rs485conf->delay_rts_before_send); | ||
| 220 | mode |= ATMEL_US_USMODE_RS485; | ||
| 221 | } else { | ||
| 222 | dev_dbg(port->dev, "Setting UART to RS232\n"); | ||
| 223 | if (atmel_use_dma_tx(port)) | ||
| 224 | atmel_port->tx_done_mask = ATMEL_US_ENDTX | | ||
| 225 | ATMEL_US_TXBUFE; | ||
| 226 | else | ||
| 227 | atmel_port->tx_done_mask = ATMEL_US_TXRDY; | ||
| 228 | } | ||
| 229 | UART_PUT_MR(port, mode); | ||
| 230 | |||
| 231 | /* Enable interrupts */ | ||
| 232 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 233 | |||
| 234 | spin_unlock(&port->lock); | ||
| 235 | |||
| 236 | } | ||
| 237 | |||
| 190 | /* | 238 | /* |
| 191 | * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. | 239 | * Return TIOCSER_TEMT when transmitter FIFO and Shift register is empty. |
| 192 | */ | 240 | */ |
| @@ -202,6 +250,7 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) | |||
| 202 | { | 250 | { |
| 203 | unsigned int control = 0; | 251 | unsigned int control = 0; |
| 204 | unsigned int mode; | 252 | unsigned int mode; |
| 253 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 205 | 254 | ||
| 206 | #ifdef CONFIG_ARCH_AT91RM9200 | 255 | #ifdef CONFIG_ARCH_AT91RM9200 |
| 207 | if (cpu_is_at91rm9200()) { | 256 | if (cpu_is_at91rm9200()) { |
| @@ -236,6 +285,17 @@ static void atmel_set_mctrl(struct uart_port *port, u_int mctrl) | |||
| 236 | mode |= ATMEL_US_CHMODE_LOC_LOOP; | 285 | mode |= ATMEL_US_CHMODE_LOC_LOOP; |
| 237 | else | 286 | else |
| 238 | mode |= ATMEL_US_CHMODE_NORMAL; | 287 | mode |= ATMEL_US_CHMODE_NORMAL; |
| 288 | |||
| 289 | /* Resetting serial mode to RS232 (0x0) */ | ||
| 290 | mode &= ~ATMEL_US_USMODE; | ||
| 291 | |||
| 292 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | ||
| 293 | dev_dbg(port->dev, "Setting UART to RS485\n"); | ||
| 294 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | ||
| 295 | mode |= ATMEL_US_USMODE_RS485; | ||
| 296 | } else { | ||
| 297 | dev_dbg(port->dev, "Setting UART to RS232\n"); | ||
| 298 | } | ||
| 239 | UART_PUT_MR(port, mode); | 299 | UART_PUT_MR(port, mode); |
| 240 | } | 300 | } |
| 241 | 301 | ||
| @@ -268,12 +328,17 @@ static u_int atmel_get_mctrl(struct uart_port *port) | |||
| 268 | */ | 328 | */ |
| 269 | static void atmel_stop_tx(struct uart_port *port) | 329 | static void atmel_stop_tx(struct uart_port *port) |
| 270 | { | 330 | { |
| 331 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 332 | |||
| 271 | if (atmel_use_dma_tx(port)) { | 333 | if (atmel_use_dma_tx(port)) { |
| 272 | /* disable PDC transmit */ | 334 | /* disable PDC transmit */ |
| 273 | UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); | 335 | UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); |
| 274 | UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 336 | } |
| 275 | } else | 337 | /* Disable interrupts */ |
| 276 | UART_PUT_IDR(port, ATMEL_US_TXRDY); | 338 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
| 339 | |||
| 340 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | ||
| 341 | atmel_start_rx(port); | ||
| 277 | } | 342 | } |
| 278 | 343 | ||
| 279 | /* | 344 | /* |
| @@ -281,17 +346,39 @@ static void atmel_stop_tx(struct uart_port *port) | |||
| 281 | */ | 346 | */ |
| 282 | static void atmel_start_tx(struct uart_port *port) | 347 | static void atmel_start_tx(struct uart_port *port) |
| 283 | { | 348 | { |
| 349 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 350 | |||
| 284 | if (atmel_use_dma_tx(port)) { | 351 | if (atmel_use_dma_tx(port)) { |
| 285 | if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) | 352 | if (UART_GET_PTSR(port) & ATMEL_PDC_TXTEN) |
| 286 | /* The transmitter is already running. Yes, we | 353 | /* The transmitter is already running. Yes, we |
| 287 | really need this.*/ | 354 | really need this.*/ |
| 288 | return; | 355 | return; |
| 289 | 356 | ||
| 290 | UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 357 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) |
| 358 | atmel_stop_rx(port); | ||
| 359 | |||
| 291 | /* re-enable PDC transmit */ | 360 | /* re-enable PDC transmit */ |
| 292 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); | 361 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); |
| 293 | } else | 362 | } |
| 294 | UART_PUT_IER(port, ATMEL_US_TXRDY); | 363 | /* Enable interrupts */ |
| 364 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 365 | } | ||
| 366 | |||
| 367 | /* | ||
| 368 | * start receiving - port is in process of being opened. | ||
| 369 | */ | ||
| 370 | static void atmel_start_rx(struct uart_port *port) | ||
| 371 | { | ||
| 372 | UART_PUT_CR(port, ATMEL_US_RSTSTA); /* reset status and receiver */ | ||
| 373 | |||
| 374 | if (atmel_use_dma_rx(port)) { | ||
| 375 | /* enable PDC controller */ | ||
| 376 | UART_PUT_IER(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | | ||
| 377 | port->read_status_mask); | ||
| 378 | UART_PUT_PTCR(port, ATMEL_PDC_RXTEN); | ||
| 379 | } else { | ||
| 380 | UART_PUT_IER(port, ATMEL_US_RXRDY); | ||
| 381 | } | ||
| 295 | } | 382 | } |
| 296 | 383 | ||
| 297 | /* | 384 | /* |
| @@ -302,9 +389,11 @@ static void atmel_stop_rx(struct uart_port *port) | |||
| 302 | if (atmel_use_dma_rx(port)) { | 389 | if (atmel_use_dma_rx(port)) { |
| 303 | /* disable PDC receive */ | 390 | /* disable PDC receive */ |
| 304 | UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); | 391 | UART_PUT_PTCR(port, ATMEL_PDC_RXTDIS); |
| 305 | UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT); | 392 | UART_PUT_IDR(port, ATMEL_US_ENDRX | ATMEL_US_TIMEOUT | |
| 306 | } else | 393 | port->read_status_mask); |
| 394 | } else { | ||
| 307 | UART_PUT_IDR(port, ATMEL_US_RXRDY); | 395 | UART_PUT_IDR(port, ATMEL_US_RXRDY); |
| 396 | } | ||
| 308 | } | 397 | } |
| 309 | 398 | ||
| 310 | /* | 399 | /* |
| @@ -428,8 +517,9 @@ static void atmel_rx_chars(struct uart_port *port) | |||
| 428 | static void atmel_tx_chars(struct uart_port *port) | 517 | static void atmel_tx_chars(struct uart_port *port) |
| 429 | { | 518 | { |
| 430 | struct circ_buf *xmit = &port->state->xmit; | 519 | struct circ_buf *xmit = &port->state->xmit; |
| 520 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 431 | 521 | ||
| 432 | if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) { | 522 | if (port->x_char && UART_GET_CSR(port) & atmel_port->tx_done_mask) { |
| 433 | UART_PUT_CHAR(port, port->x_char); | 523 | UART_PUT_CHAR(port, port->x_char); |
| 434 | port->icount.tx++; | 524 | port->icount.tx++; |
| 435 | port->x_char = 0; | 525 | port->x_char = 0; |
| @@ -437,7 +527,7 @@ static void atmel_tx_chars(struct uart_port *port) | |||
| 437 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | 527 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) |
| 438 | return; | 528 | return; |
| 439 | 529 | ||
| 440 | while (UART_GET_CSR(port) & ATMEL_US_TXRDY) { | 530 | while (UART_GET_CSR(port) & atmel_port->tx_done_mask) { |
| 441 | UART_PUT_CHAR(port, xmit->buf[xmit->tail]); | 531 | UART_PUT_CHAR(port, xmit->buf[xmit->tail]); |
| 442 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 532 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| 443 | port->icount.tx++; | 533 | port->icount.tx++; |
| @@ -449,7 +539,8 @@ static void atmel_tx_chars(struct uart_port *port) | |||
| 449 | uart_write_wakeup(port); | 539 | uart_write_wakeup(port); |
| 450 | 540 | ||
| 451 | if (!uart_circ_empty(xmit)) | 541 | if (!uart_circ_empty(xmit)) |
| 452 | UART_PUT_IER(port, ATMEL_US_TXRDY); | 542 | /* Enable interrupts */ |
| 543 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 453 | } | 544 | } |
| 454 | 545 | ||
| 455 | /* | 546 | /* |
| @@ -501,18 +592,10 @@ atmel_handle_transmit(struct uart_port *port, unsigned int pending) | |||
| 501 | { | 592 | { |
| 502 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | 593 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); |
| 503 | 594 | ||
| 504 | if (atmel_use_dma_tx(port)) { | 595 | if (pending & atmel_port->tx_done_mask) { |
| 505 | /* PDC transmit */ | 596 | /* Either PDC or interrupt transmission */ |
| 506 | if (pending & (ATMEL_US_ENDTX | ATMEL_US_TXBUFE)) { | 597 | UART_PUT_IDR(port, atmel_port->tx_done_mask); |
| 507 | UART_PUT_IDR(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 598 | tasklet_schedule(&atmel_port->tasklet); |
| 508 | tasklet_schedule(&atmel_port->tasklet); | ||
| 509 | } | ||
| 510 | } else { | ||
| 511 | /* Interrupt transmit */ | ||
| 512 | if (pending & ATMEL_US_TXRDY) { | ||
| 513 | UART_PUT_IDR(port, ATMEL_US_TXRDY); | ||
| 514 | tasklet_schedule(&atmel_port->tasklet); | ||
| 515 | } | ||
| 516 | } | 599 | } |
| 517 | } | 600 | } |
| 518 | 601 | ||
| @@ -590,9 +673,15 @@ static void atmel_tx_dma(struct uart_port *port) | |||
| 590 | 673 | ||
| 591 | UART_PUT_TPR(port, pdc->dma_addr + xmit->tail); | 674 | UART_PUT_TPR(port, pdc->dma_addr + xmit->tail); |
| 592 | UART_PUT_TCR(port, count); | 675 | UART_PUT_TCR(port, count); |
| 593 | /* re-enable PDC transmit and interrupts */ | 676 | /* re-enable PDC transmit */ |
| 594 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); | 677 | UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); |
| 595 | UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); | 678 | /* Enable interrupts */ |
| 679 | UART_PUT_IER(port, atmel_port->tx_done_mask); | ||
| 680 | } else { | ||
| 681 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | ||
| 682 | /* DMA done, stop TX, start RX for RS485 */ | ||
| 683 | atmel_start_rx(port); | ||
| 684 | } | ||
| 596 | } | 685 | } |
| 597 | 686 | ||
| 598 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 687 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| @@ -1017,6 +1106,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1017 | { | 1106 | { |
| 1018 | unsigned long flags; | 1107 | unsigned long flags; |
| 1019 | unsigned int mode, imr, quot, baud; | 1108 | unsigned int mode, imr, quot, baud; |
| 1109 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 1020 | 1110 | ||
| 1021 | /* Get current mode register */ | 1111 | /* Get current mode register */ |
| 1022 | mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL | 1112 | mode = UART_GET_MR(port) & ~(ATMEL_US_USCLKS | ATMEL_US_CHRL |
| @@ -1115,6 +1205,17 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1115 | /* disable receiver and transmitter */ | 1205 | /* disable receiver and transmitter */ |
| 1116 | UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); | 1206 | UART_PUT_CR(port, ATMEL_US_TXDIS | ATMEL_US_RXDIS); |
| 1117 | 1207 | ||
| 1208 | /* Resetting serial mode to RS232 (0x0) */ | ||
| 1209 | mode &= ~ATMEL_US_USMODE; | ||
| 1210 | |||
| 1211 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) { | ||
| 1212 | dev_dbg(port->dev, "Setting UART to RS485\n"); | ||
| 1213 | UART_PUT_TTGR(port, atmel_port->rs485.delay_rts_before_send); | ||
| 1214 | mode |= ATMEL_US_USMODE_RS485; | ||
| 1215 | } else { | ||
| 1216 | dev_dbg(port->dev, "Setting UART to RS232\n"); | ||
| 1217 | } | ||
| 1218 | |||
| 1118 | /* set the parity, stop bits and data size */ | 1219 | /* set the parity, stop bits and data size */ |
| 1119 | UART_PUT_MR(port, mode); | 1220 | UART_PUT_MR(port, mode); |
| 1120 | 1221 | ||
| @@ -1231,6 +1332,35 @@ static void atmel_poll_put_char(struct uart_port *port, unsigned char ch) | |||
| 1231 | } | 1332 | } |
| 1232 | #endif | 1333 | #endif |
| 1233 | 1334 | ||
| 1335 | static int | ||
| 1336 | atmel_ioctl(struct uart_port *port, unsigned int cmd, unsigned long arg) | ||
| 1337 | { | ||
| 1338 | struct serial_rs485 rs485conf; | ||
| 1339 | |||
| 1340 | switch (cmd) { | ||
| 1341 | case TIOCSRS485: | ||
| 1342 | if (copy_from_user(&rs485conf, (struct serial_rs485 *) arg, | ||
| 1343 | sizeof(rs485conf))) | ||
| 1344 | return -EFAULT; | ||
| 1345 | |||
| 1346 | atmel_config_rs485(port, &rs485conf); | ||
| 1347 | break; | ||
| 1348 | |||
| 1349 | case TIOCGRS485: | ||
| 1350 | if (copy_to_user((struct serial_rs485 *) arg, | ||
| 1351 | &(to_atmel_uart_port(port)->rs485), | ||
| 1352 | sizeof(rs485conf))) | ||
| 1353 | return -EFAULT; | ||
| 1354 | break; | ||
| 1355 | |||
| 1356 | default: | ||
| 1357 | return -ENOIOCTLCMD; | ||
| 1358 | } | ||
| 1359 | return 0; | ||
| 1360 | } | ||
| 1361 | |||
| 1362 | |||
| 1363 | |||
| 1234 | static struct uart_ops atmel_pops = { | 1364 | static struct uart_ops atmel_pops = { |
| 1235 | .tx_empty = atmel_tx_empty, | 1365 | .tx_empty = atmel_tx_empty, |
| 1236 | .set_mctrl = atmel_set_mctrl, | 1366 | .set_mctrl = atmel_set_mctrl, |
| @@ -1250,6 +1380,7 @@ static struct uart_ops atmel_pops = { | |||
| 1250 | .config_port = atmel_config_port, | 1380 | .config_port = atmel_config_port, |
| 1251 | .verify_port = atmel_verify_port, | 1381 | .verify_port = atmel_verify_port, |
| 1252 | .pm = atmel_serial_pm, | 1382 | .pm = atmel_serial_pm, |
| 1383 | .ioctl = atmel_ioctl, | ||
| 1253 | #ifdef CONFIG_CONSOLE_POLL | 1384 | #ifdef CONFIG_CONSOLE_POLL |
| 1254 | .poll_get_char = atmel_poll_get_char, | 1385 | .poll_get_char = atmel_poll_get_char, |
| 1255 | .poll_put_char = atmel_poll_put_char, | 1386 | .poll_put_char = atmel_poll_put_char, |
| @@ -1265,13 +1396,12 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
| 1265 | struct uart_port *port = &atmel_port->uart; | 1396 | struct uart_port *port = &atmel_port->uart; |
| 1266 | struct atmel_uart_data *data = pdev->dev.platform_data; | 1397 | struct atmel_uart_data *data = pdev->dev.platform_data; |
| 1267 | 1398 | ||
| 1268 | port->iotype = UPIO_MEM; | 1399 | port->iotype = UPIO_MEM; |
| 1269 | port->flags = UPF_BOOT_AUTOCONF; | 1400 | port->flags = UPF_BOOT_AUTOCONF; |
| 1270 | port->ops = &atmel_pops; | 1401 | port->ops = &atmel_pops; |
| 1271 | port->fifosize = 1; | 1402 | port->fifosize = 1; |
| 1272 | port->line = pdev->id; | 1403 | port->line = pdev->id; |
| 1273 | port->dev = &pdev->dev; | 1404 | port->dev = &pdev->dev; |
| 1274 | |||
| 1275 | port->mapbase = pdev->resource[0].start; | 1405 | port->mapbase = pdev->resource[0].start; |
| 1276 | port->irq = pdev->resource[1].start; | 1406 | port->irq = pdev->resource[1].start; |
| 1277 | 1407 | ||
| @@ -1299,8 +1429,16 @@ static void __devinit atmel_init_port(struct atmel_uart_port *atmel_port, | |||
| 1299 | 1429 | ||
| 1300 | atmel_port->use_dma_rx = data->use_dma_rx; | 1430 | atmel_port->use_dma_rx = data->use_dma_rx; |
| 1301 | atmel_port->use_dma_tx = data->use_dma_tx; | 1431 | atmel_port->use_dma_tx = data->use_dma_tx; |
| 1302 | if (atmel_use_dma_tx(port)) | 1432 | atmel_port->rs485 = data->rs485; |
| 1433 | /* Use TXEMPTY for interrupt when rs485 else TXRDY or ENDTX|TXBUFE */ | ||
| 1434 | if (atmel_port->rs485.flags & SER_RS485_ENABLED) | ||
| 1435 | atmel_port->tx_done_mask = ATMEL_US_TXEMPTY; | ||
| 1436 | else if (atmel_use_dma_tx(port)) { | ||
| 1303 | port->fifosize = PDC_BUFFER_SIZE; | 1437 | port->fifosize = PDC_BUFFER_SIZE; |
| 1438 | atmel_port->tx_done_mask = ATMEL_US_ENDTX | ATMEL_US_TXBUFE; | ||
| 1439 | } else { | ||
| 1440 | atmel_port->tx_done_mask = ATMEL_US_TXRDY; | ||
| 1441 | } | ||
| 1304 | } | 1442 | } |
| 1305 | 1443 | ||
| 1306 | /* | 1444 | /* |
| @@ -1334,6 +1472,7 @@ static void atmel_console_putchar(struct uart_port *port, int ch) | |||
| 1334 | static void atmel_console_write(struct console *co, const char *s, u_int count) | 1472 | static void atmel_console_write(struct console *co, const char *s, u_int count) |
| 1335 | { | 1473 | { |
| 1336 | struct uart_port *port = &atmel_ports[co->index].uart; | 1474 | struct uart_port *port = &atmel_ports[co->index].uart; |
| 1475 | struct atmel_uart_port *atmel_port = to_atmel_uart_port(port); | ||
| 1337 | unsigned int status, imr; | 1476 | unsigned int status, imr; |
| 1338 | unsigned int pdc_tx; | 1477 | unsigned int pdc_tx; |
| 1339 | 1478 | ||
| @@ -1341,7 +1480,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count) | |||
| 1341 | * First, save IMR and then disable interrupts | 1480 | * First, save IMR and then disable interrupts |
| 1342 | */ | 1481 | */ |
| 1343 | imr = UART_GET_IMR(port); | 1482 | imr = UART_GET_IMR(port); |
| 1344 | UART_PUT_IDR(port, ATMEL_US_RXRDY | ATMEL_US_TXRDY); | 1483 | UART_PUT_IDR(port, ATMEL_US_RXRDY | atmel_port->tx_done_mask); |
| 1345 | 1484 | ||
| 1346 | /* Store PDC transmit status and disable it */ | 1485 | /* Store PDC transmit status and disable it */ |
| 1347 | pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; | 1486 | pdc_tx = UART_GET_PTSR(port) & ATMEL_PDC_TXTEN; |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 4315b23590bd..eacb588a9345 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
| @@ -120,7 +120,8 @@ | |||
| 120 | #define MX2_UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */ | 120 | #define MX2_UCR3_RXDMUXSEL (1<<2) /* RXD Muxed Input Select, on mx2/mx3 */ |
| 121 | #define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ | 121 | #define UCR3_INVT (1<<1) /* Inverted Infrared transmission */ |
| 122 | #define UCR3_BPEN (1<<0) /* Preset registers enable */ | 122 | #define UCR3_BPEN (1<<0) /* Preset registers enable */ |
| 123 | #define UCR4_CTSTL_32 (32<<10) /* CTS trigger level (32 chars) */ | 123 | #define UCR4_CTSTL_SHF 10 /* CTS trigger level shift */ |
| 124 | #define UCR4_CTSTL_MASK 0x3F /* CTS trigger is 6 bits wide */ | ||
| 124 | #define UCR4_INVR (1<<9) /* Inverted infrared reception */ | 125 | #define UCR4_INVR (1<<9) /* Inverted infrared reception */ |
| 125 | #define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ | 126 | #define UCR4_ENIRI (1<<8) /* Serial infrared interrupt enable */ |
| 126 | #define UCR4_WKEN (1<<7) /* Wake interrupt enable */ | 127 | #define UCR4_WKEN (1<<7) /* Wake interrupt enable */ |
| @@ -591,6 +592,9 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) | |||
| 591 | return 0; | 592 | return 0; |
| 592 | } | 593 | } |
| 593 | 594 | ||
| 595 | /* half the RX buffer size */ | ||
| 596 | #define CTSTL 16 | ||
| 597 | |||
| 594 | static int imx_startup(struct uart_port *port) | 598 | static int imx_startup(struct uart_port *port) |
| 595 | { | 599 | { |
| 596 | struct imx_port *sport = (struct imx_port *)port; | 600 | struct imx_port *sport = (struct imx_port *)port; |
| @@ -607,6 +611,10 @@ static int imx_startup(struct uart_port *port) | |||
| 607 | if (USE_IRDA(sport)) | 611 | if (USE_IRDA(sport)) |
| 608 | temp |= UCR4_IRSC; | 612 | temp |= UCR4_IRSC; |
| 609 | 613 | ||
| 614 | /* set the trigger level for CTS */ | ||
| 615 | temp &= ~(UCR4_CTSTL_MASK<< UCR4_CTSTL_SHF); | ||
| 616 | temp |= CTSTL<< UCR4_CTSTL_SHF; | ||
| 617 | |||
| 610 | writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); | 618 | writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); |
| 611 | 619 | ||
| 612 | if (USE_IRDA(sport)) { | 620 | if (USE_IRDA(sport)) { |
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index a176ab4bd65b..02469c31bf0b 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
| @@ -1467,7 +1467,7 @@ mpc52xx_uart_init(void) | |||
| 1467 | /* | 1467 | /* |
| 1468 | * Map the PSC FIFO Controller and init if on MPC512x. | 1468 | * Map the PSC FIFO Controller and init if on MPC512x. |
| 1469 | */ | 1469 | */ |
| 1470 | if (psc_ops->fifoc_init) { | 1470 | if (psc_ops && psc_ops->fifoc_init) { |
| 1471 | ret = psc_ops->fifoc_init(); | 1471 | ret = psc_ops->fifoc_init(); |
| 1472 | if (ret) | 1472 | if (ret) |
| 1473 | return ret; | 1473 | return ret; |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 8eb094c1f61b..8d993c4cceac 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -83,16 +83,16 @@ struct sci_port { | |||
| 83 | 83 | ||
| 84 | /* Interface clock */ | 84 | /* Interface clock */ |
| 85 | struct clk *iclk; | 85 | struct clk *iclk; |
| 86 | /* Data clock */ | 86 | /* Function clock */ |
| 87 | struct clk *dclk; | 87 | struct clk *fclk; |
| 88 | 88 | ||
| 89 | struct list_head node; | 89 | struct list_head node; |
| 90 | struct dma_chan *chan_tx; | 90 | struct dma_chan *chan_tx; |
| 91 | struct dma_chan *chan_rx; | 91 | struct dma_chan *chan_rx; |
| 92 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 92 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 93 | struct device *dma_dev; | 93 | struct device *dma_dev; |
| 94 | enum sh_dmae_slave_chan_id slave_tx; | 94 | unsigned int slave_tx; |
| 95 | enum sh_dmae_slave_chan_id slave_rx; | 95 | unsigned int slave_rx; |
| 96 | struct dma_async_tx_descriptor *desc_tx; | 96 | struct dma_async_tx_descriptor *desc_tx; |
| 97 | struct dma_async_tx_descriptor *desc_rx[2]; | 97 | struct dma_async_tx_descriptor *desc_rx[2]; |
| 98 | dma_cookie_t cookie_tx; | 98 | dma_cookie_t cookie_tx; |
| @@ -107,6 +107,7 @@ struct sci_port { | |||
| 107 | struct work_struct work_tx; | 107 | struct work_struct work_tx; |
| 108 | struct work_struct work_rx; | 108 | struct work_struct work_rx; |
| 109 | struct timer_list rx_timer; | 109 | struct timer_list rx_timer; |
| 110 | unsigned int rx_timeout; | ||
| 110 | #endif | 111 | #endif |
| 111 | }; | 112 | }; |
| 112 | 113 | ||
| @@ -674,22 +675,22 @@ static irqreturn_t sci_rx_interrupt(int irq, void *ptr) | |||
| 674 | struct sci_port *s = to_sci_port(port); | 675 | struct sci_port *s = to_sci_port(port); |
| 675 | 676 | ||
| 676 | if (s->chan_rx) { | 677 | if (s->chan_rx) { |
| 677 | unsigned long tout; | ||
| 678 | u16 scr = sci_in(port, SCSCR); | 678 | u16 scr = sci_in(port, SCSCR); |
| 679 | u16 ssr = sci_in(port, SCxSR); | 679 | u16 ssr = sci_in(port, SCxSR); |
| 680 | 680 | ||
| 681 | /* Disable future Rx interrupts */ | 681 | /* Disable future Rx interrupts */ |
| 682 | sci_out(port, SCSCR, scr & ~SCI_CTRL_FLAGS_RIE); | 682 | if (port->type == PORT_SCIFA) { |
| 683 | disable_irq_nosync(irq); | ||
| 684 | scr |= 0x4000; | ||
| 685 | } else { | ||
| 686 | scr &= ~SCI_CTRL_FLAGS_RIE; | ||
| 687 | } | ||
| 688 | sci_out(port, SCSCR, scr); | ||
| 683 | /* Clear current interrupt */ | 689 | /* Clear current interrupt */ |
| 684 | sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); | 690 | sci_out(port, SCxSR, ssr & ~(1 | SCxSR_RDxF(port))); |
| 685 | /* Calculate delay for 1.5 DMA buffers */ | 691 | dev_dbg(port->dev, "Rx IRQ %lu: setup t-out in %u jiffies\n", |
| 686 | tout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / | 692 | jiffies, s->rx_timeout); |
| 687 | port->fifosize / 2; | 693 | mod_timer(&s->rx_timer, jiffies + s->rx_timeout); |
| 688 | dev_dbg(port->dev, "Rx IRQ: setup timeout in %lu ms\n", | ||
| 689 | tout * 1000 / HZ); | ||
| 690 | if (tout < 2) | ||
| 691 | tout = 2; | ||
| 692 | mod_timer(&s->rx_timer, jiffies + tout); | ||
| 693 | 694 | ||
| 694 | return IRQ_HANDLED; | 695 | return IRQ_HANDLED; |
| 695 | } | 696 | } |
| @@ -799,7 +800,7 @@ static int sci_notifier(struct notifier_block *self, | |||
| 799 | (phase == CPUFREQ_RESUMECHANGE)) { | 800 | (phase == CPUFREQ_RESUMECHANGE)) { |
| 800 | spin_lock_irqsave(&priv->lock, flags); | 801 | spin_lock_irqsave(&priv->lock, flags); |
| 801 | list_for_each_entry(sci_port, &priv->ports, node) | 802 | list_for_each_entry(sci_port, &priv->ports, node) |
| 802 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | 803 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); |
| 803 | spin_unlock_irqrestore(&priv->lock, flags); | 804 | spin_unlock_irqrestore(&priv->lock, flags); |
| 804 | } | 805 | } |
| 805 | 806 | ||
| @@ -810,21 +811,17 @@ static void sci_clk_enable(struct uart_port *port) | |||
| 810 | { | 811 | { |
| 811 | struct sci_port *sci_port = to_sci_port(port); | 812 | struct sci_port *sci_port = to_sci_port(port); |
| 812 | 813 | ||
| 813 | clk_enable(sci_port->dclk); | 814 | clk_enable(sci_port->iclk); |
| 814 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | 815 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); |
| 815 | 816 | clk_enable(sci_port->fclk); | |
| 816 | if (sci_port->iclk) | ||
| 817 | clk_enable(sci_port->iclk); | ||
| 818 | } | 817 | } |
| 819 | 818 | ||
| 820 | static void sci_clk_disable(struct uart_port *port) | 819 | static void sci_clk_disable(struct uart_port *port) |
| 821 | { | 820 | { |
| 822 | struct sci_port *sci_port = to_sci_port(port); | 821 | struct sci_port *sci_port = to_sci_port(port); |
| 823 | 822 | ||
| 824 | if (sci_port->iclk) | 823 | clk_disable(sci_port->fclk); |
| 825 | clk_disable(sci_port->iclk); | 824 | clk_disable(sci_port->iclk); |
| 826 | |||
| 827 | clk_disable(sci_port->dclk); | ||
| 828 | } | 825 | } |
| 829 | 826 | ||
| 830 | static int sci_request_irq(struct sci_port *port) | 827 | static int sci_request_irq(struct sci_port *port) |
| @@ -913,22 +910,26 @@ static void sci_dma_tx_complete(void *arg) | |||
| 913 | 910 | ||
| 914 | spin_lock_irqsave(&port->lock, flags); | 911 | spin_lock_irqsave(&port->lock, flags); |
| 915 | 912 | ||
| 916 | xmit->tail += s->sg_tx.length; | 913 | xmit->tail += sg_dma_len(&s->sg_tx); |
| 917 | xmit->tail &= UART_XMIT_SIZE - 1; | 914 | xmit->tail &= UART_XMIT_SIZE - 1; |
| 918 | 915 | ||
| 919 | port->icount.tx += s->sg_tx.length; | 916 | port->icount.tx += sg_dma_len(&s->sg_tx); |
| 920 | 917 | ||
| 921 | async_tx_ack(s->desc_tx); | 918 | async_tx_ack(s->desc_tx); |
| 922 | s->cookie_tx = -EINVAL; | 919 | s->cookie_tx = -EINVAL; |
| 923 | s->desc_tx = NULL; | 920 | s->desc_tx = NULL; |
| 924 | 921 | ||
| 925 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 926 | |||
| 927 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 922 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
| 928 | uart_write_wakeup(port); | 923 | uart_write_wakeup(port); |
| 929 | 924 | ||
| 930 | if (uart_circ_chars_pending(xmit)) | 925 | if (!uart_circ_empty(xmit)) { |
| 931 | schedule_work(&s->work_tx); | 926 | schedule_work(&s->work_tx); |
| 927 | } else if (port->type == PORT_SCIFA) { | ||
| 928 | u16 ctrl = sci_in(port, SCSCR); | ||
| 929 | sci_out(port, SCSCR, ctrl & ~SCI_CTRL_FLAGS_TIE); | ||
| 930 | } | ||
| 931 | |||
| 932 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 932 | } | 933 | } |
| 933 | 934 | ||
| 934 | /* Locking: called with port lock held */ | 935 | /* Locking: called with port lock held */ |
| @@ -972,13 +973,13 @@ static void sci_dma_rx_complete(void *arg) | |||
| 972 | unsigned long flags; | 973 | unsigned long flags; |
| 973 | int count; | 974 | int count; |
| 974 | 975 | ||
| 975 | dev_dbg(port->dev, "%s(%d)\n", __func__, port->line); | 976 | dev_dbg(port->dev, "%s(%d) active #%d\n", __func__, port->line, s->active_rx); |
| 976 | 977 | ||
| 977 | spin_lock_irqsave(&port->lock, flags); | 978 | spin_lock_irqsave(&port->lock, flags); |
| 978 | 979 | ||
| 979 | count = sci_dma_rx_push(s, tty, s->buf_len_rx); | 980 | count = sci_dma_rx_push(s, tty, s->buf_len_rx); |
| 980 | 981 | ||
| 981 | mod_timer(&s->rx_timer, jiffies + msecs_to_jiffies(5)); | 982 | mod_timer(&s->rx_timer, jiffies + s->rx_timeout); |
| 982 | 983 | ||
| 983 | spin_unlock_irqrestore(&port->lock, flags); | 984 | spin_unlock_irqrestore(&port->lock, flags); |
| 984 | 985 | ||
| @@ -1050,6 +1051,8 @@ static void sci_submit_rx(struct sci_port *s) | |||
| 1050 | sci_rx_dma_release(s, true); | 1051 | sci_rx_dma_release(s, true); |
| 1051 | return; | 1052 | return; |
| 1052 | } | 1053 | } |
| 1054 | dev_dbg(s->port.dev, "%s(): cookie %d to #%d\n", __func__, | ||
| 1055 | s->cookie_rx[i], i); | ||
| 1053 | } | 1056 | } |
| 1054 | 1057 | ||
| 1055 | s->active_rx = s->cookie_rx[0]; | 1058 | s->active_rx = s->cookie_rx[0]; |
| @@ -1107,10 +1110,10 @@ static void work_fn_rx(struct work_struct *work) | |||
| 1107 | return; | 1110 | return; |
| 1108 | } | 1111 | } |
| 1109 | 1112 | ||
| 1110 | dev_dbg(port->dev, "%s: cookie %d #%d\n", __func__, | ||
| 1111 | s->cookie_rx[new], new); | ||
| 1112 | |||
| 1113 | s->active_rx = s->cookie_rx[!new]; | 1113 | s->active_rx = s->cookie_rx[!new]; |
| 1114 | |||
| 1115 | dev_dbg(port->dev, "%s: cookie %d #%d, new active #%d\n", __func__, | ||
| 1116 | s->cookie_rx[new], new, s->active_rx); | ||
| 1114 | } | 1117 | } |
| 1115 | 1118 | ||
| 1116 | static void work_fn_tx(struct work_struct *work) | 1119 | static void work_fn_tx(struct work_struct *work) |
| @@ -1131,14 +1134,13 @@ static void work_fn_tx(struct work_struct *work) | |||
| 1131 | */ | 1134 | */ |
| 1132 | spin_lock_irq(&port->lock); | 1135 | spin_lock_irq(&port->lock); |
| 1133 | sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); | 1136 | sg->offset = xmit->tail & (UART_XMIT_SIZE - 1); |
| 1134 | sg->dma_address = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + | 1137 | sg_dma_address(sg) = (sg_dma_address(sg) & ~(UART_XMIT_SIZE - 1)) + |
| 1135 | sg->offset; | 1138 | sg->offset; |
| 1136 | sg->length = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), | 1139 | sg_dma_len(sg) = min((int)CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE), |
| 1137 | CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); | 1140 | CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE)); |
| 1138 | sg->dma_length = sg->length; | ||
| 1139 | spin_unlock_irq(&port->lock); | 1141 | spin_unlock_irq(&port->lock); |
| 1140 | 1142 | ||
| 1141 | BUG_ON(!sg->length); | 1143 | BUG_ON(!sg_dma_len(sg)); |
| 1142 | 1144 | ||
| 1143 | desc = chan->device->device_prep_slave_sg(chan, | 1145 | desc = chan->device->device_prep_slave_sg(chan, |
| 1144 | sg, s->sg_len_tx, DMA_TO_DEVICE, | 1146 | sg, s->sg_len_tx, DMA_TO_DEVICE, |
| @@ -1173,23 +1175,28 @@ static void work_fn_tx(struct work_struct *work) | |||
| 1173 | 1175 | ||
| 1174 | static void sci_start_tx(struct uart_port *port) | 1176 | static void sci_start_tx(struct uart_port *port) |
| 1175 | { | 1177 | { |
| 1178 | struct sci_port *s = to_sci_port(port); | ||
| 1176 | unsigned short ctrl; | 1179 | unsigned short ctrl; |
| 1177 | 1180 | ||
| 1178 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | 1181 | #ifdef CONFIG_SERIAL_SH_SCI_DMA |
| 1179 | struct sci_port *s = to_sci_port(port); | 1182 | if (port->type == PORT_SCIFA) { |
| 1180 | 1183 | u16 new, scr = sci_in(port, SCSCR); | |
| 1181 | if (s->chan_tx) { | 1184 | if (s->chan_tx) |
| 1182 | if (!uart_circ_empty(&s->port.state->xmit) && s->cookie_tx < 0) | 1185 | new = scr | 0x8000; |
| 1183 | schedule_work(&s->work_tx); | 1186 | else |
| 1184 | 1187 | new = scr & ~0x8000; | |
| 1185 | return; | 1188 | if (new != scr) |
| 1189 | sci_out(port, SCSCR, new); | ||
| 1186 | } | 1190 | } |
| 1191 | if (s->chan_tx && !uart_circ_empty(&s->port.state->xmit) && | ||
| 1192 | s->cookie_tx < 0) | ||
| 1193 | schedule_work(&s->work_tx); | ||
| 1187 | #endif | 1194 | #endif |
| 1188 | 1195 | if (!s->chan_tx || port->type == PORT_SCIFA) { | |
| 1189 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1196 | /* Set TIE (Transmit Interrupt Enable) bit in SCSCR */ |
| 1190 | ctrl = sci_in(port, SCSCR); | 1197 | ctrl = sci_in(port, SCSCR); |
| 1191 | ctrl |= SCI_CTRL_FLAGS_TIE; | 1198 | sci_out(port, SCSCR, ctrl | SCI_CTRL_FLAGS_TIE); |
| 1192 | sci_out(port, SCSCR, ctrl); | 1199 | } |
| 1193 | } | 1200 | } |
| 1194 | 1201 | ||
| 1195 | static void sci_stop_tx(struct uart_port *port) | 1202 | static void sci_stop_tx(struct uart_port *port) |
| @@ -1198,6 +1205,8 @@ static void sci_stop_tx(struct uart_port *port) | |||
| 1198 | 1205 | ||
| 1199 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ | 1206 | /* Clear TIE (Transmit Interrupt Enable) bit in SCSCR */ |
| 1200 | ctrl = sci_in(port, SCSCR); | 1207 | ctrl = sci_in(port, SCSCR); |
| 1208 | if (port->type == PORT_SCIFA) | ||
| 1209 | ctrl &= ~0x8000; | ||
| 1201 | ctrl &= ~SCI_CTRL_FLAGS_TIE; | 1210 | ctrl &= ~SCI_CTRL_FLAGS_TIE; |
| 1202 | sci_out(port, SCSCR, ctrl); | 1211 | sci_out(port, SCSCR, ctrl); |
| 1203 | } | 1212 | } |
| @@ -1208,6 +1217,8 @@ static void sci_start_rx(struct uart_port *port) | |||
| 1208 | 1217 | ||
| 1209 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ | 1218 | /* Set RIE (Receive Interrupt Enable) bit in SCSCR */ |
| 1210 | ctrl |= sci_in(port, SCSCR); | 1219 | ctrl |= sci_in(port, SCSCR); |
| 1220 | if (port->type == PORT_SCIFA) | ||
| 1221 | ctrl &= ~0x4000; | ||
| 1211 | sci_out(port, SCSCR, ctrl); | 1222 | sci_out(port, SCSCR, ctrl); |
| 1212 | } | 1223 | } |
| 1213 | 1224 | ||
| @@ -1217,6 +1228,8 @@ static void sci_stop_rx(struct uart_port *port) | |||
| 1217 | 1228 | ||
| 1218 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ | 1229 | /* Clear RIE (Receive Interrupt Enable) bit in SCSCR */ |
| 1219 | ctrl = sci_in(port, SCSCR); | 1230 | ctrl = sci_in(port, SCSCR); |
| 1231 | if (port->type == PORT_SCIFA) | ||
| 1232 | ctrl &= ~0x4000; | ||
| 1220 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); | 1233 | ctrl &= ~(SCI_CTRL_FLAGS_RIE | SCI_CTRL_FLAGS_REIE); |
| 1221 | sci_out(port, SCSCR, ctrl); | 1234 | sci_out(port, SCSCR, ctrl); |
| 1222 | } | 1235 | } |
| @@ -1251,8 +1264,12 @@ static void rx_timer_fn(unsigned long arg) | |||
| 1251 | { | 1264 | { |
| 1252 | struct sci_port *s = (struct sci_port *)arg; | 1265 | struct sci_port *s = (struct sci_port *)arg; |
| 1253 | struct uart_port *port = &s->port; | 1266 | struct uart_port *port = &s->port; |
| 1254 | |||
| 1255 | u16 scr = sci_in(port, SCSCR); | 1267 | u16 scr = sci_in(port, SCSCR); |
| 1268 | |||
| 1269 | if (port->type == PORT_SCIFA) { | ||
| 1270 | scr &= ~0x4000; | ||
| 1271 | enable_irq(s->irqs[1]); | ||
| 1272 | } | ||
| 1256 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); | 1273 | sci_out(port, SCSCR, scr | SCI_CTRL_FLAGS_RIE); |
| 1257 | dev_dbg(port->dev, "DMA Rx timed out\n"); | 1274 | dev_dbg(port->dev, "DMA Rx timed out\n"); |
| 1258 | schedule_work(&s->work_rx); | 1275 | schedule_work(&s->work_rx); |
| @@ -1339,8 +1356,7 @@ static void sci_request_dma(struct uart_port *port) | |||
| 1339 | sg_init_table(sg, 1); | 1356 | sg_init_table(sg, 1); |
| 1340 | sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, | 1357 | sg_set_page(sg, virt_to_page(buf[i]), s->buf_len_rx, |
| 1341 | (int)buf[i] & ~PAGE_MASK); | 1358 | (int)buf[i] & ~PAGE_MASK); |
| 1342 | sg->dma_address = dma[i]; | 1359 | sg_dma_address(sg) = dma[i]; |
| 1343 | sg->dma_length = sg->length; | ||
| 1344 | } | 1360 | } |
| 1345 | 1361 | ||
| 1346 | INIT_WORK(&s->work_rx, work_fn_rx); | 1362 | INIT_WORK(&s->work_rx, work_fn_rx); |
| @@ -1403,8 +1419,12 @@ static void sci_shutdown(struct uart_port *port) | |||
| 1403 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 1419 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
| 1404 | struct ktermios *old) | 1420 | struct ktermios *old) |
| 1405 | { | 1421 | { |
| 1422 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
| 1423 | struct sci_port *s = to_sci_port(port); | ||
| 1424 | #endif | ||
| 1406 | unsigned int status, baud, smr_val, max_baud; | 1425 | unsigned int status, baud, smr_val, max_baud; |
| 1407 | int t = -1; | 1426 | int t = -1; |
| 1427 | u16 scfcr = 0; | ||
| 1408 | 1428 | ||
| 1409 | /* | 1429 | /* |
| 1410 | * earlyprintk comes here early on with port->uartclk set to zero. | 1430 | * earlyprintk comes here early on with port->uartclk set to zero. |
| @@ -1427,7 +1447,7 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1427 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ | 1447 | sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */ |
| 1428 | 1448 | ||
| 1429 | if (port->type != PORT_SCI) | 1449 | if (port->type != PORT_SCI) |
| 1430 | sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST); | 1450 | sci_out(port, SCFCR, scfcr | SCFCR_RFRST | SCFCR_TFRST); |
| 1431 | 1451 | ||
| 1432 | smr_val = sci_in(port, SCSMR) & 3; | 1452 | smr_val = sci_in(port, SCSMR) & 3; |
| 1433 | if ((termios->c_cflag & CSIZE) == CS7) | 1453 | if ((termios->c_cflag & CSIZE) == CS7) |
| @@ -1458,10 +1478,32 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 1458 | } | 1478 | } |
| 1459 | 1479 | ||
| 1460 | sci_init_pins(port, termios->c_cflag); | 1480 | sci_init_pins(port, termios->c_cflag); |
| 1461 | sci_out(port, SCFCR, (termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0); | 1481 | sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0)); |
| 1462 | 1482 | ||
| 1463 | sci_out(port, SCSCR, SCSCR_INIT(port)); | 1483 | sci_out(port, SCSCR, SCSCR_INIT(port)); |
| 1464 | 1484 | ||
| 1485 | #ifdef CONFIG_SERIAL_SH_SCI_DMA | ||
| 1486 | /* | ||
| 1487 | * Calculate delay for 1.5 DMA buffers: see | ||
| 1488 | * drivers/serial/serial_core.c::uart_update_timeout(). With 10 bits | ||
| 1489 | * (CS8), 250Hz, 115200 baud and 64 bytes FIFO, the above function | ||
| 1490 | * calculates 1 jiffie for the data plus 5 jiffies for the "slop(e)." | ||
| 1491 | * Then below we calculate 3 jiffies (12ms) for 1.5 DMA buffers (3 FIFO | ||
| 1492 | * sizes), but it has been found out experimentally, that this is not | ||
| 1493 | * enough: the driver too often needlessly runs on a DMA timeout. 20ms | ||
| 1494 | * as a minimum seem to work perfectly. | ||
| 1495 | */ | ||
| 1496 | if (s->chan_rx) { | ||
| 1497 | s->rx_timeout = (port->timeout - HZ / 50) * s->buf_len_rx * 3 / | ||
| 1498 | port->fifosize / 2; | ||
| 1499 | dev_dbg(port->dev, | ||
| 1500 | "DMA Rx t-out %ums, tty t-out %u jiffies\n", | ||
| 1501 | s->rx_timeout * 1000 / HZ, port->timeout); | ||
| 1502 | if (s->rx_timeout < msecs_to_jiffies(20)) | ||
| 1503 | s->rx_timeout = msecs_to_jiffies(20); | ||
| 1504 | } | ||
| 1505 | #endif | ||
| 1506 | |||
| 1465 | if ((termios->c_cflag & CREAD) != 0) | 1507 | if ((termios->c_cflag & CREAD) != 0) |
| 1466 | sci_start_rx(port); | 1508 | sci_start_rx(port); |
| 1467 | } | 1509 | } |
| @@ -1553,10 +1595,10 @@ static struct uart_ops sci_uart_ops = { | |||
| 1553 | #endif | 1595 | #endif |
| 1554 | }; | 1596 | }; |
| 1555 | 1597 | ||
| 1556 | static void __devinit sci_init_single(struct platform_device *dev, | 1598 | static int __devinit sci_init_single(struct platform_device *dev, |
| 1557 | struct sci_port *sci_port, | 1599 | struct sci_port *sci_port, |
| 1558 | unsigned int index, | 1600 | unsigned int index, |
| 1559 | struct plat_sci_port *p) | 1601 | struct plat_sci_port *p) |
| 1560 | { | 1602 | { |
| 1561 | struct uart_port *port = &sci_port->port; | 1603 | struct uart_port *port = &sci_port->port; |
| 1562 | 1604 | ||
| @@ -1577,8 +1619,23 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
| 1577 | } | 1619 | } |
| 1578 | 1620 | ||
| 1579 | if (dev) { | 1621 | if (dev) { |
| 1580 | sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; | 1622 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); |
| 1581 | sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); | 1623 | if (IS_ERR(sci_port->iclk)) { |
| 1624 | sci_port->iclk = clk_get(&dev->dev, "peripheral_clk"); | ||
| 1625 | if (IS_ERR(sci_port->iclk)) { | ||
| 1626 | dev_err(&dev->dev, "can't get iclk\n"); | ||
| 1627 | return PTR_ERR(sci_port->iclk); | ||
| 1628 | } | ||
| 1629 | } | ||
| 1630 | |||
| 1631 | /* | ||
| 1632 | * The function clock is optional, ignore it if we can't | ||
| 1633 | * find it. | ||
| 1634 | */ | ||
| 1635 | sci_port->fclk = clk_get(&dev->dev, "sci_fck"); | ||
| 1636 | if (IS_ERR(sci_port->fclk)) | ||
| 1637 | sci_port->fclk = NULL; | ||
| 1638 | |||
| 1582 | sci_port->enable = sci_clk_enable; | 1639 | sci_port->enable = sci_clk_enable; |
| 1583 | sci_port->disable = sci_clk_disable; | 1640 | sci_port->disable = sci_clk_disable; |
| 1584 | port->dev = &dev->dev; | 1641 | port->dev = &dev->dev; |
| @@ -1605,6 +1662,7 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
| 1605 | #endif | 1662 | #endif |
| 1606 | 1663 | ||
| 1607 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); | 1664 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); |
| 1665 | return 0; | ||
| 1608 | } | 1666 | } |
| 1609 | 1667 | ||
| 1610 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 1668 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE |
| @@ -1754,8 +1812,11 @@ static int sci_remove(struct platform_device *dev) | |||
| 1754 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); | 1812 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); |
| 1755 | 1813 | ||
| 1756 | spin_lock_irqsave(&priv->lock, flags); | 1814 | spin_lock_irqsave(&priv->lock, flags); |
| 1757 | list_for_each_entry(p, &priv->ports, node) | 1815 | list_for_each_entry(p, &priv->ports, node) { |
| 1758 | uart_remove_one_port(&sci_uart_driver, &p->port); | 1816 | uart_remove_one_port(&sci_uart_driver, &p->port); |
| 1817 | clk_put(p->iclk); | ||
| 1818 | clk_put(p->fclk); | ||
| 1819 | } | ||
| 1759 | spin_unlock_irqrestore(&priv->lock, flags); | 1820 | spin_unlock_irqrestore(&priv->lock, flags); |
| 1760 | 1821 | ||
| 1761 | kfree(priv); | 1822 | kfree(priv); |
| @@ -1781,7 +1842,9 @@ static int __devinit sci_probe_single(struct platform_device *dev, | |||
| 1781 | return 0; | 1842 | return 0; |
| 1782 | } | 1843 | } |
| 1783 | 1844 | ||
| 1784 | sci_init_single(dev, sciport, index, p); | 1845 | ret = sci_init_single(dev, sciport, index, p); |
| 1846 | if (ret) | ||
| 1847 | return ret; | ||
| 1785 | 1848 | ||
| 1786 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); | 1849 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); |
| 1787 | if (ret) | 1850 | if (ret) |
diff --git a/drivers/sh/Kconfig b/drivers/sh/Kconfig new file mode 100644 index 000000000000..a54de0b9b3df --- /dev/null +++ b/drivers/sh/Kconfig | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | config INTC_USERIMASK | ||
| 2 | bool "Userspace interrupt masking support" | ||
| 3 | depends on ARCH_SHMOBILE || (SUPERH && CPU_SH4A) | ||
| 4 | help | ||
| 5 | This enables support for hardware-assisted userspace hardirq | ||
| 6 | masking. | ||
| 7 | |||
| 8 | SH-4A and newer interrupt blocks all support a special shadowed | ||
| 9 | page with all non-masking registers obscured when mapped in to | ||
| 10 | userspace. This is primarily for use by userspace device | ||
| 11 | drivers that are using special priority levels. | ||
| 12 | |||
| 13 | If in doubt, say N. | ||
| 14 | |||
| 15 | config INTC_BALANCING | ||
| 16 | bool "Hardware IRQ balancing support" | ||
| 17 | depends on SMP && SUPERH && CPU_SUBTYPE_SH7786 | ||
| 18 | help | ||
| 19 | This enables support for IRQ auto-distribution mode on SH-X3 | ||
| 20 | SMP parts. All of the balancing and CPU wakeup decisions are | ||
| 21 | taken care of automatically by hardware for distributed | ||
| 22 | vectors. | ||
| 23 | |||
| 24 | If in doubt, say N. | ||
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile index 4956bf1f2134..78bb5127abd0 100644 --- a/drivers/sh/Makefile +++ b/drivers/sh/Makefile | |||
| @@ -4,4 +4,6 @@ | |||
| 4 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ | 4 | obj-$(CONFIG_SUPERHYWAY) += superhyway/ |
| 5 | obj-$(CONFIG_MAPLE) += maple/ | 5 | obj-$(CONFIG_MAPLE) += maple/ |
| 6 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o | 6 | obj-$(CONFIG_GENERIC_GPIO) += pfc.o |
| 7 | obj-$(CONFIG_SUPERH) += clk.o | ||
| 8 | obj-$(CONFIG_SH_CLK_CPG) += clk-cpg.o | ||
| 7 | obj-y += intc.o | 9 | obj-y += intc.o |
diff --git a/drivers/sh/clk-cpg.c b/drivers/sh/clk-cpg.c new file mode 100644 index 000000000000..f5c80ba9ab1c --- /dev/null +++ b/drivers/sh/clk-cpg.c | |||
| @@ -0,0 +1,298 @@ | |||
| 1 | #include <linux/clk.h> | ||
| 2 | #include <linux/compiler.h> | ||
| 3 | #include <linux/slab.h> | ||
| 4 | #include <linux/io.h> | ||
| 5 | #include <linux/sh_clk.h> | ||
| 6 | |||
| 7 | static int sh_clk_mstp32_enable(struct clk *clk) | ||
| 8 | { | ||
| 9 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit), | ||
| 10 | clk->enable_reg); | ||
| 11 | return 0; | ||
| 12 | } | ||
| 13 | |||
| 14 | static void sh_clk_mstp32_disable(struct clk *clk) | ||
| 15 | { | ||
| 16 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit), | ||
| 17 | clk->enable_reg); | ||
| 18 | } | ||
| 19 | |||
| 20 | static struct clk_ops sh_clk_mstp32_clk_ops = { | ||
| 21 | .enable = sh_clk_mstp32_enable, | ||
| 22 | .disable = sh_clk_mstp32_disable, | ||
| 23 | .recalc = followparent_recalc, | ||
| 24 | }; | ||
| 25 | |||
| 26 | int __init sh_clk_mstp32_register(struct clk *clks, int nr) | ||
| 27 | { | ||
| 28 | struct clk *clkp; | ||
| 29 | int ret = 0; | ||
| 30 | int k; | ||
| 31 | |||
| 32 | for (k = 0; !ret && (k < nr); k++) { | ||
| 33 | clkp = clks + k; | ||
| 34 | clkp->ops = &sh_clk_mstp32_clk_ops; | ||
| 35 | ret |= clk_register(clkp); | ||
| 36 | } | ||
| 37 | |||
| 38 | return ret; | ||
| 39 | } | ||
| 40 | |||
| 41 | static long sh_clk_div_round_rate(struct clk *clk, unsigned long rate) | ||
| 42 | { | ||
| 43 | return clk_rate_table_round(clk, clk->freq_table, rate); | ||
| 44 | } | ||
| 45 | |||
| 46 | static int sh_clk_div6_divisors[64] = { | ||
| 47 | 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, | ||
| 48 | 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, | ||
| 49 | 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, | ||
| 50 | 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64 | ||
| 51 | }; | ||
| 52 | |||
| 53 | static struct clk_div_mult_table sh_clk_div6_table = { | ||
| 54 | .divisors = sh_clk_div6_divisors, | ||
| 55 | .nr_divisors = ARRAY_SIZE(sh_clk_div6_divisors), | ||
| 56 | }; | ||
| 57 | |||
| 58 | static unsigned long sh_clk_div6_recalc(struct clk *clk) | ||
| 59 | { | ||
| 60 | struct clk_div_mult_table *table = &sh_clk_div6_table; | ||
| 61 | unsigned int idx; | ||
| 62 | |||
| 63 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
| 64 | table, NULL); | ||
| 65 | |||
| 66 | idx = __raw_readl(clk->enable_reg) & 0x003f; | ||
| 67 | |||
| 68 | return clk->freq_table[idx].frequency; | ||
| 69 | } | ||
| 70 | |||
| 71 | static int sh_clk_div6_set_rate(struct clk *clk, | ||
| 72 | unsigned long rate, int algo_id) | ||
| 73 | { | ||
| 74 | unsigned long value; | ||
| 75 | int idx; | ||
| 76 | |||
| 77 | idx = clk_rate_table_find(clk, clk->freq_table, rate); | ||
| 78 | if (idx < 0) | ||
| 79 | return idx; | ||
| 80 | |||
| 81 | value = __raw_readl(clk->enable_reg); | ||
| 82 | value &= ~0x3f; | ||
| 83 | value |= idx; | ||
| 84 | __raw_writel(value, clk->enable_reg); | ||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | static int sh_clk_div6_enable(struct clk *clk) | ||
| 89 | { | ||
| 90 | unsigned long value; | ||
| 91 | int ret; | ||
| 92 | |||
| 93 | ret = sh_clk_div6_set_rate(clk, clk->rate, 0); | ||
| 94 | if (ret == 0) { | ||
| 95 | value = __raw_readl(clk->enable_reg); | ||
| 96 | value &= ~0x100; /* clear stop bit to enable clock */ | ||
| 97 | __raw_writel(value, clk->enable_reg); | ||
| 98 | } | ||
| 99 | return ret; | ||
| 100 | } | ||
| 101 | |||
| 102 | static void sh_clk_div6_disable(struct clk *clk) | ||
| 103 | { | ||
| 104 | unsigned long value; | ||
| 105 | |||
| 106 | value = __raw_readl(clk->enable_reg); | ||
| 107 | value |= 0x100; /* stop clock */ | ||
| 108 | value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */ | ||
| 109 | __raw_writel(value, clk->enable_reg); | ||
| 110 | } | ||
| 111 | |||
| 112 | static struct clk_ops sh_clk_div6_clk_ops = { | ||
| 113 | .recalc = sh_clk_div6_recalc, | ||
| 114 | .round_rate = sh_clk_div_round_rate, | ||
| 115 | .set_rate = sh_clk_div6_set_rate, | ||
| 116 | .enable = sh_clk_div6_enable, | ||
| 117 | .disable = sh_clk_div6_disable, | ||
| 118 | }; | ||
| 119 | |||
| 120 | int __init sh_clk_div6_register(struct clk *clks, int nr) | ||
| 121 | { | ||
| 122 | struct clk *clkp; | ||
| 123 | void *freq_table; | ||
| 124 | int nr_divs = sh_clk_div6_table.nr_divisors; | ||
| 125 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
| 126 | int ret = 0; | ||
| 127 | int k; | ||
| 128 | |||
| 129 | freq_table_size *= (nr_divs + 1); | ||
| 130 | freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); | ||
| 131 | if (!freq_table) { | ||
| 132 | pr_err("sh_clk_div6_register: unable to alloc memory\n"); | ||
| 133 | return -ENOMEM; | ||
| 134 | } | ||
| 135 | |||
| 136 | for (k = 0; !ret && (k < nr); k++) { | ||
| 137 | clkp = clks + k; | ||
| 138 | |||
| 139 | clkp->ops = &sh_clk_div6_clk_ops; | ||
| 140 | clkp->id = -1; | ||
| 141 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
| 142 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
| 143 | |||
| 144 | ret = clk_register(clkp); | ||
| 145 | } | ||
| 146 | |||
| 147 | return ret; | ||
| 148 | } | ||
| 149 | |||
| 150 | static unsigned long sh_clk_div4_recalc(struct clk *clk) | ||
| 151 | { | ||
| 152 | struct clk_div4_table *d4t = clk->priv; | ||
| 153 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
| 154 | unsigned int idx; | ||
| 155 | |||
| 156 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
| 157 | table, &clk->arch_flags); | ||
| 158 | |||
| 159 | idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f; | ||
| 160 | |||
| 161 | return clk->freq_table[idx].frequency; | ||
| 162 | } | ||
| 163 | |||
| 164 | static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent) | ||
| 165 | { | ||
| 166 | struct clk_div4_table *d4t = clk->priv; | ||
| 167 | struct clk_div_mult_table *table = d4t->div_mult_table; | ||
| 168 | u32 value; | ||
| 169 | int ret; | ||
| 170 | |||
| 171 | /* we really need a better way to determine parent index, but for | ||
| 172 | * now assume internal parent comes with CLK_ENABLE_ON_INIT set, | ||
| 173 | * no CLK_ENABLE_ON_INIT means external clock... | ||
| 174 | */ | ||
| 175 | |||
| 176 | if (parent->flags & CLK_ENABLE_ON_INIT) | ||
| 177 | value = __raw_readl(clk->enable_reg) & ~(1 << 7); | ||
| 178 | else | ||
| 179 | value = __raw_readl(clk->enable_reg) | (1 << 7); | ||
| 180 | |||
| 181 | ret = clk_reparent(clk, parent); | ||
| 182 | if (ret < 0) | ||
| 183 | return ret; | ||
| 184 | |||
| 185 | __raw_writel(value, clk->enable_reg); | ||
| 186 | |||
| 187 | /* Rebiuld the frequency table */ | ||
| 188 | clk_rate_table_build(clk, clk->freq_table, table->nr_divisors, | ||
| 189 | table, &clk->arch_flags); | ||
| 190 | |||
| 191 | return 0; | ||
| 192 | } | ||
| 193 | |||
| 194 | static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate, int algo_id) | ||
| 195 | { | ||
| 196 | struct clk_div4_table *d4t = clk->priv; | ||
| 197 | unsigned long value; | ||
| 198 | int idx = clk_rate_table_find(clk, clk->freq_table, rate); | ||
| 199 | if (idx < 0) | ||
| 200 | return idx; | ||
| 201 | |||
| 202 | value = __raw_readl(clk->enable_reg); | ||
| 203 | value &= ~(0xf << clk->enable_bit); | ||
| 204 | value |= (idx << clk->enable_bit); | ||
| 205 | __raw_writel(value, clk->enable_reg); | ||
| 206 | |||
| 207 | if (d4t->kick) | ||
| 208 | d4t->kick(clk); | ||
| 209 | |||
| 210 | return 0; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int sh_clk_div4_enable(struct clk *clk) | ||
| 214 | { | ||
| 215 | __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg); | ||
| 216 | return 0; | ||
| 217 | } | ||
| 218 | |||
| 219 | static void sh_clk_div4_disable(struct clk *clk) | ||
| 220 | { | ||
| 221 | __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg); | ||
| 222 | } | ||
| 223 | |||
| 224 | static struct clk_ops sh_clk_div4_clk_ops = { | ||
| 225 | .recalc = sh_clk_div4_recalc, | ||
| 226 | .set_rate = sh_clk_div4_set_rate, | ||
| 227 | .round_rate = sh_clk_div_round_rate, | ||
| 228 | }; | ||
| 229 | |||
| 230 | static struct clk_ops sh_clk_div4_enable_clk_ops = { | ||
| 231 | .recalc = sh_clk_div4_recalc, | ||
| 232 | .set_rate = sh_clk_div4_set_rate, | ||
| 233 | .round_rate = sh_clk_div_round_rate, | ||
| 234 | .enable = sh_clk_div4_enable, | ||
| 235 | .disable = sh_clk_div4_disable, | ||
| 236 | }; | ||
| 237 | |||
| 238 | static struct clk_ops sh_clk_div4_reparent_clk_ops = { | ||
| 239 | .recalc = sh_clk_div4_recalc, | ||
| 240 | .set_rate = sh_clk_div4_set_rate, | ||
| 241 | .round_rate = sh_clk_div_round_rate, | ||
| 242 | .enable = sh_clk_div4_enable, | ||
| 243 | .disable = sh_clk_div4_disable, | ||
| 244 | .set_parent = sh_clk_div4_set_parent, | ||
| 245 | }; | ||
| 246 | |||
| 247 | static int __init sh_clk_div4_register_ops(struct clk *clks, int nr, | ||
| 248 | struct clk_div4_table *table, struct clk_ops *ops) | ||
| 249 | { | ||
| 250 | struct clk *clkp; | ||
| 251 | void *freq_table; | ||
| 252 | int nr_divs = table->div_mult_table->nr_divisors; | ||
| 253 | int freq_table_size = sizeof(struct cpufreq_frequency_table); | ||
| 254 | int ret = 0; | ||
| 255 | int k; | ||
| 256 | |||
| 257 | freq_table_size *= (nr_divs + 1); | ||
| 258 | freq_table = kzalloc(freq_table_size * nr, GFP_KERNEL); | ||
| 259 | if (!freq_table) { | ||
| 260 | pr_err("sh_clk_div4_register: unable to alloc memory\n"); | ||
| 261 | return -ENOMEM; | ||
| 262 | } | ||
| 263 | |||
| 264 | for (k = 0; !ret && (k < nr); k++) { | ||
| 265 | clkp = clks + k; | ||
| 266 | |||
| 267 | clkp->ops = ops; | ||
| 268 | clkp->id = -1; | ||
| 269 | clkp->priv = table; | ||
| 270 | |||
| 271 | clkp->freq_table = freq_table + (k * freq_table_size); | ||
| 272 | clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END; | ||
| 273 | |||
| 274 | ret = clk_register(clkp); | ||
| 275 | } | ||
| 276 | |||
| 277 | return ret; | ||
| 278 | } | ||
| 279 | |||
| 280 | int __init sh_clk_div4_register(struct clk *clks, int nr, | ||
| 281 | struct clk_div4_table *table) | ||
| 282 | { | ||
| 283 | return sh_clk_div4_register_ops(clks, nr, table, &sh_clk_div4_clk_ops); | ||
| 284 | } | ||
| 285 | |||
| 286 | int __init sh_clk_div4_enable_register(struct clk *clks, int nr, | ||
| 287 | struct clk_div4_table *table) | ||
| 288 | { | ||
| 289 | return sh_clk_div4_register_ops(clks, nr, table, | ||
| 290 | &sh_clk_div4_enable_clk_ops); | ||
| 291 | } | ||
| 292 | |||
| 293 | int __init sh_clk_div4_reparent_register(struct clk *clks, int nr, | ||
| 294 | struct clk_div4_table *table) | ||
| 295 | { | ||
| 296 | return sh_clk_div4_register_ops(clks, nr, table, | ||
| 297 | &sh_clk_div4_reparent_clk_ops); | ||
| 298 | } | ||
diff --git a/drivers/sh/clk.c b/drivers/sh/clk.c new file mode 100644 index 000000000000..5d84adac9ec4 --- /dev/null +++ b/drivers/sh/clk.c | |||
| @@ -0,0 +1,545 @@ | |||
| 1 | /* | ||
| 2 | * drivers/sh/clk.c - SuperH clock framework | ||
| 3 | * | ||
| 4 | * Copyright (C) 2005 - 2009 Paul Mundt | ||
| 5 | * | ||
| 6 | * This clock framework is derived from the OMAP version by: | ||
| 7 | * | ||
| 8 | * Copyright (C) 2004 - 2008 Nokia Corporation | ||
| 9 | * Written by Tuukka Tikkanen <tuukka.tikkanen@elektrobit.com> | ||
| 10 | * | ||
| 11 | * Modified for omap shared clock framework by Tony Lindgren <tony@atomide.com> | ||
| 12 | * | ||
| 13 | * This file is subject to the terms and conditions of the GNU General Public | ||
| 14 | * License. See the file "COPYING" in the main directory of this archive | ||
| 15 | * for more details. | ||
| 16 | */ | ||
| 17 | #include <linux/kernel.h> | ||
| 18 | #include <linux/init.h> | ||
| 19 | #include <linux/module.h> | ||
| 20 | #include <linux/mutex.h> | ||
| 21 | #include <linux/list.h> | ||
| 22 | #include <linux/kobject.h> | ||
| 23 | #include <linux/sysdev.h> | ||
| 24 | #include <linux/seq_file.h> | ||
| 25 | #include <linux/err.h> | ||
| 26 | #include <linux/platform_device.h> | ||
| 27 | #include <linux/debugfs.h> | ||
| 28 | #include <linux/cpufreq.h> | ||
| 29 | #include <linux/clk.h> | ||
| 30 | #include <linux/sh_clk.h> | ||
| 31 | |||
| 32 | static LIST_HEAD(clock_list); | ||
| 33 | static DEFINE_SPINLOCK(clock_lock); | ||
| 34 | static DEFINE_MUTEX(clock_list_sem); | ||
| 35 | |||
| 36 | void clk_rate_table_build(struct clk *clk, | ||
| 37 | struct cpufreq_frequency_table *freq_table, | ||
| 38 | int nr_freqs, | ||
| 39 | struct clk_div_mult_table *src_table, | ||
| 40 | unsigned long *bitmap) | ||
| 41 | { | ||
| 42 | unsigned long mult, div; | ||
| 43 | unsigned long freq; | ||
| 44 | int i; | ||
| 45 | |||
| 46 | for (i = 0; i < nr_freqs; i++) { | ||
| 47 | div = 1; | ||
| 48 | mult = 1; | ||
| 49 | |||
| 50 | if (src_table->divisors && i < src_table->nr_divisors) | ||
| 51 | div = src_table->divisors[i]; | ||
| 52 | |||
| 53 | if (src_table->multipliers && i < src_table->nr_multipliers) | ||
| 54 | mult = src_table->multipliers[i]; | ||
| 55 | |||
| 56 | if (!div || !mult || (bitmap && !test_bit(i, bitmap))) | ||
| 57 | freq = CPUFREQ_ENTRY_INVALID; | ||
| 58 | else | ||
| 59 | freq = clk->parent->rate * mult / div; | ||
| 60 | |||
| 61 | freq_table[i].index = i; | ||
| 62 | freq_table[i].frequency = freq; | ||
| 63 | } | ||
| 64 | |||
| 65 | /* Termination entry */ | ||
| 66 | freq_table[i].index = i; | ||
| 67 | freq_table[i].frequency = CPUFREQ_TABLE_END; | ||
| 68 | } | ||
| 69 | |||
| 70 | long clk_rate_table_round(struct clk *clk, | ||
| 71 | struct cpufreq_frequency_table *freq_table, | ||
| 72 | unsigned long rate) | ||
| 73 | { | ||
| 74 | unsigned long rate_error, rate_error_prev = ~0UL; | ||
| 75 | unsigned long rate_best_fit = rate; | ||
| 76 | unsigned long highest, lowest; | ||
| 77 | int i; | ||
| 78 | |||
| 79 | highest = lowest = 0; | ||
| 80 | |||
| 81 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | ||
| 82 | unsigned long freq = freq_table[i].frequency; | ||
| 83 | |||
| 84 | if (freq == CPUFREQ_ENTRY_INVALID) | ||
| 85 | continue; | ||
| 86 | |||
| 87 | if (freq > highest) | ||
| 88 | highest = freq; | ||
| 89 | if (freq < lowest) | ||
| 90 | lowest = freq; | ||
| 91 | |||
| 92 | rate_error = abs(freq - rate); | ||
| 93 | if (rate_error < rate_error_prev) { | ||
| 94 | rate_best_fit = freq; | ||
| 95 | rate_error_prev = rate_error; | ||
| 96 | } | ||
| 97 | |||
| 98 | if (rate_error == 0) | ||
| 99 | break; | ||
| 100 | } | ||
| 101 | |||
| 102 | if (rate >= highest) | ||
| 103 | rate_best_fit = highest; | ||
| 104 | if (rate <= lowest) | ||
| 105 | rate_best_fit = lowest; | ||
| 106 | |||
| 107 | return rate_best_fit; | ||
| 108 | } | ||
| 109 | |||
| 110 | int clk_rate_table_find(struct clk *clk, | ||
| 111 | struct cpufreq_frequency_table *freq_table, | ||
| 112 | unsigned long rate) | ||
| 113 | { | ||
| 114 | int i; | ||
| 115 | |||
| 116 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) { | ||
| 117 | unsigned long freq = freq_table[i].frequency; | ||
| 118 | |||
| 119 | if (freq == CPUFREQ_ENTRY_INVALID) | ||
| 120 | continue; | ||
| 121 | |||
| 122 | if (freq == rate) | ||
| 123 | return i; | ||
| 124 | } | ||
| 125 | |||
| 126 | return -ENOENT; | ||
| 127 | } | ||
| 128 | |||
| 129 | /* Used for clocks that always have same value as the parent clock */ | ||
| 130 | unsigned long followparent_recalc(struct clk *clk) | ||
| 131 | { | ||
| 132 | return clk->parent ? clk->parent->rate : 0; | ||
| 133 | } | ||
| 134 | |||
| 135 | int clk_reparent(struct clk *child, struct clk *parent) | ||
| 136 | { | ||
| 137 | list_del_init(&child->sibling); | ||
| 138 | if (parent) | ||
| 139 | list_add(&child->sibling, &parent->children); | ||
| 140 | child->parent = parent; | ||
| 141 | |||
| 142 | /* now do the debugfs renaming to reattach the child | ||
| 143 | to the proper parent */ | ||
| 144 | |||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | /* Propagate rate to children */ | ||
| 149 | void propagate_rate(struct clk *tclk) | ||
| 150 | { | ||
| 151 | struct clk *clkp; | ||
| 152 | |||
| 153 | list_for_each_entry(clkp, &tclk->children, sibling) { | ||
| 154 | if (clkp->ops && clkp->ops->recalc) | ||
| 155 | clkp->rate = clkp->ops->recalc(clkp); | ||
| 156 | |||
| 157 | propagate_rate(clkp); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | static void __clk_disable(struct clk *clk) | ||
| 162 | { | ||
| 163 | if (WARN(!clk->usecount, "Trying to disable clock %s with 0 usecount\n", | ||
| 164 | clk->name)) | ||
| 165 | return; | ||
| 166 | |||
| 167 | if (!(--clk->usecount)) { | ||
| 168 | if (likely(clk->ops && clk->ops->disable)) | ||
| 169 | clk->ops->disable(clk); | ||
| 170 | if (likely(clk->parent)) | ||
| 171 | __clk_disable(clk->parent); | ||
| 172 | } | ||
| 173 | } | ||
| 174 | |||
| 175 | void clk_disable(struct clk *clk) | ||
| 176 | { | ||
| 177 | unsigned long flags; | ||
| 178 | |||
| 179 | if (!clk) | ||
| 180 | return; | ||
| 181 | |||
| 182 | spin_lock_irqsave(&clock_lock, flags); | ||
| 183 | __clk_disable(clk); | ||
| 184 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 185 | } | ||
| 186 | EXPORT_SYMBOL_GPL(clk_disable); | ||
| 187 | |||
| 188 | static int __clk_enable(struct clk *clk) | ||
| 189 | { | ||
| 190 | int ret = 0; | ||
| 191 | |||
| 192 | if (clk->usecount++ == 0) { | ||
| 193 | if (clk->parent) { | ||
| 194 | ret = __clk_enable(clk->parent); | ||
| 195 | if (unlikely(ret)) | ||
| 196 | goto err; | ||
| 197 | } | ||
| 198 | |||
| 199 | if (clk->ops && clk->ops->enable) { | ||
| 200 | ret = clk->ops->enable(clk); | ||
| 201 | if (ret) { | ||
| 202 | if (clk->parent) | ||
| 203 | __clk_disable(clk->parent); | ||
| 204 | goto err; | ||
| 205 | } | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | return ret; | ||
| 210 | err: | ||
| 211 | clk->usecount--; | ||
| 212 | return ret; | ||
| 213 | } | ||
| 214 | |||
| 215 | int clk_enable(struct clk *clk) | ||
| 216 | { | ||
| 217 | unsigned long flags; | ||
| 218 | int ret; | ||
| 219 | |||
| 220 | if (!clk) | ||
| 221 | return -EINVAL; | ||
| 222 | |||
| 223 | spin_lock_irqsave(&clock_lock, flags); | ||
| 224 | ret = __clk_enable(clk); | ||
| 225 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 226 | |||
| 227 | return ret; | ||
| 228 | } | ||
| 229 | EXPORT_SYMBOL_GPL(clk_enable); | ||
| 230 | |||
| 231 | static LIST_HEAD(root_clks); | ||
| 232 | |||
| 233 | /** | ||
| 234 | * recalculate_root_clocks - recalculate and propagate all root clocks | ||
| 235 | * | ||
| 236 | * Recalculates all root clocks (clocks with no parent), which if the | ||
| 237 | * clock's .recalc is set correctly, should also propagate their rates. | ||
| 238 | * Called at init. | ||
| 239 | */ | ||
| 240 | void recalculate_root_clocks(void) | ||
| 241 | { | ||
| 242 | struct clk *clkp; | ||
| 243 | |||
| 244 | list_for_each_entry(clkp, &root_clks, sibling) { | ||
| 245 | if (clkp->ops && clkp->ops->recalc) | ||
| 246 | clkp->rate = clkp->ops->recalc(clkp); | ||
| 247 | propagate_rate(clkp); | ||
| 248 | } | ||
| 249 | } | ||
| 250 | |||
| 251 | int clk_register(struct clk *clk) | ||
| 252 | { | ||
| 253 | if (clk == NULL || IS_ERR(clk)) | ||
| 254 | return -EINVAL; | ||
| 255 | |||
| 256 | /* | ||
| 257 | * trap out already registered clocks | ||
| 258 | */ | ||
| 259 | if (clk->node.next || clk->node.prev) | ||
| 260 | return 0; | ||
| 261 | |||
| 262 | mutex_lock(&clock_list_sem); | ||
| 263 | |||
| 264 | INIT_LIST_HEAD(&clk->children); | ||
| 265 | clk->usecount = 0; | ||
| 266 | |||
| 267 | if (clk->parent) | ||
| 268 | list_add(&clk->sibling, &clk->parent->children); | ||
| 269 | else | ||
| 270 | list_add(&clk->sibling, &root_clks); | ||
| 271 | |||
| 272 | list_add(&clk->node, &clock_list); | ||
| 273 | if (clk->ops && clk->ops->init) | ||
| 274 | clk->ops->init(clk); | ||
| 275 | mutex_unlock(&clock_list_sem); | ||
| 276 | |||
| 277 | return 0; | ||
| 278 | } | ||
| 279 | EXPORT_SYMBOL_GPL(clk_register); | ||
| 280 | |||
| 281 | void clk_unregister(struct clk *clk) | ||
| 282 | { | ||
| 283 | mutex_lock(&clock_list_sem); | ||
| 284 | list_del(&clk->sibling); | ||
| 285 | list_del(&clk->node); | ||
| 286 | mutex_unlock(&clock_list_sem); | ||
| 287 | } | ||
| 288 | EXPORT_SYMBOL_GPL(clk_unregister); | ||
| 289 | |||
| 290 | void clk_enable_init_clocks(void) | ||
| 291 | { | ||
| 292 | struct clk *clkp; | ||
| 293 | |||
| 294 | list_for_each_entry(clkp, &clock_list, node) | ||
| 295 | if (clkp->flags & CLK_ENABLE_ON_INIT) | ||
| 296 | clk_enable(clkp); | ||
| 297 | } | ||
| 298 | |||
| 299 | unsigned long clk_get_rate(struct clk *clk) | ||
| 300 | { | ||
| 301 | return clk->rate; | ||
| 302 | } | ||
| 303 | EXPORT_SYMBOL_GPL(clk_get_rate); | ||
| 304 | |||
| 305 | int clk_set_rate(struct clk *clk, unsigned long rate) | ||
| 306 | { | ||
| 307 | return clk_set_rate_ex(clk, rate, 0); | ||
| 308 | } | ||
| 309 | EXPORT_SYMBOL_GPL(clk_set_rate); | ||
| 310 | |||
| 311 | int clk_set_rate_ex(struct clk *clk, unsigned long rate, int algo_id) | ||
| 312 | { | ||
| 313 | int ret = -EOPNOTSUPP; | ||
| 314 | unsigned long flags; | ||
| 315 | |||
| 316 | spin_lock_irqsave(&clock_lock, flags); | ||
| 317 | |||
| 318 | if (likely(clk->ops && clk->ops->set_rate)) { | ||
| 319 | ret = clk->ops->set_rate(clk, rate, algo_id); | ||
| 320 | if (ret != 0) | ||
| 321 | goto out_unlock; | ||
| 322 | } else { | ||
| 323 | clk->rate = rate; | ||
| 324 | ret = 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | if (clk->ops && clk->ops->recalc) | ||
| 328 | clk->rate = clk->ops->recalc(clk); | ||
| 329 | |||
| 330 | propagate_rate(clk); | ||
| 331 | |||
| 332 | out_unlock: | ||
| 333 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 334 | |||
| 335 | return ret; | ||
| 336 | } | ||
| 337 | EXPORT_SYMBOL_GPL(clk_set_rate_ex); | ||
| 338 | |||
| 339 | int clk_set_parent(struct clk *clk, struct clk *parent) | ||
| 340 | { | ||
| 341 | unsigned long flags; | ||
| 342 | int ret = -EINVAL; | ||
| 343 | |||
| 344 | if (!parent || !clk) | ||
| 345 | return ret; | ||
| 346 | if (clk->parent == parent) | ||
| 347 | return 0; | ||
| 348 | |||
| 349 | spin_lock_irqsave(&clock_lock, flags); | ||
| 350 | if (clk->usecount == 0) { | ||
| 351 | if (clk->ops->set_parent) | ||
| 352 | ret = clk->ops->set_parent(clk, parent); | ||
| 353 | else | ||
| 354 | ret = clk_reparent(clk, parent); | ||
| 355 | |||
| 356 | if (ret == 0) { | ||
| 357 | pr_debug("clock: set parent of %s to %s (new rate %ld)\n", | ||
| 358 | clk->name, clk->parent->name, clk->rate); | ||
| 359 | if (clk->ops->recalc) | ||
| 360 | clk->rate = clk->ops->recalc(clk); | ||
| 361 | propagate_rate(clk); | ||
| 362 | } | ||
| 363 | } else | ||
| 364 | ret = -EBUSY; | ||
| 365 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 366 | |||
| 367 | return ret; | ||
| 368 | } | ||
| 369 | EXPORT_SYMBOL_GPL(clk_set_parent); | ||
| 370 | |||
| 371 | struct clk *clk_get_parent(struct clk *clk) | ||
| 372 | { | ||
| 373 | return clk->parent; | ||
| 374 | } | ||
| 375 | EXPORT_SYMBOL_GPL(clk_get_parent); | ||
| 376 | |||
| 377 | long clk_round_rate(struct clk *clk, unsigned long rate) | ||
| 378 | { | ||
| 379 | if (likely(clk->ops && clk->ops->round_rate)) { | ||
| 380 | unsigned long flags, rounded; | ||
| 381 | |||
| 382 | spin_lock_irqsave(&clock_lock, flags); | ||
| 383 | rounded = clk->ops->round_rate(clk, rate); | ||
| 384 | spin_unlock_irqrestore(&clock_lock, flags); | ||
| 385 | |||
| 386 | return rounded; | ||
| 387 | } | ||
| 388 | |||
| 389 | return clk_get_rate(clk); | ||
| 390 | } | ||
| 391 | EXPORT_SYMBOL_GPL(clk_round_rate); | ||
| 392 | |||
| 393 | #ifdef CONFIG_PM | ||
| 394 | static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state) | ||
| 395 | { | ||
| 396 | static pm_message_t prev_state; | ||
| 397 | struct clk *clkp; | ||
| 398 | |||
| 399 | switch (state.event) { | ||
| 400 | case PM_EVENT_ON: | ||
| 401 | /* Resumeing from hibernation */ | ||
| 402 | if (prev_state.event != PM_EVENT_FREEZE) | ||
| 403 | break; | ||
| 404 | |||
| 405 | list_for_each_entry(clkp, &clock_list, node) { | ||
| 406 | if (likely(clkp->ops)) { | ||
| 407 | unsigned long rate = clkp->rate; | ||
| 408 | |||
| 409 | if (likely(clkp->ops->set_parent)) | ||
| 410 | clkp->ops->set_parent(clkp, | ||
| 411 | clkp->parent); | ||
| 412 | if (likely(clkp->ops->set_rate)) | ||
| 413 | clkp->ops->set_rate(clkp, | ||
| 414 | rate, NO_CHANGE); | ||
| 415 | else if (likely(clkp->ops->recalc)) | ||
| 416 | clkp->rate = clkp->ops->recalc(clkp); | ||
| 417 | } | ||
| 418 | } | ||
| 419 | break; | ||
| 420 | case PM_EVENT_FREEZE: | ||
| 421 | break; | ||
| 422 | case PM_EVENT_SUSPEND: | ||
| 423 | break; | ||
| 424 | } | ||
| 425 | |||
| 426 | prev_state = state; | ||
| 427 | return 0; | ||
| 428 | } | ||
| 429 | |||
| 430 | static int clks_sysdev_resume(struct sys_device *dev) | ||
| 431 | { | ||
| 432 | return clks_sysdev_suspend(dev, PMSG_ON); | ||
| 433 | } | ||
| 434 | |||
| 435 | static struct sysdev_class clks_sysdev_class = { | ||
| 436 | .name = "clks", | ||
| 437 | }; | ||
| 438 | |||
| 439 | static struct sysdev_driver clks_sysdev_driver = { | ||
| 440 | .suspend = clks_sysdev_suspend, | ||
| 441 | .resume = clks_sysdev_resume, | ||
| 442 | }; | ||
| 443 | |||
| 444 | static struct sys_device clks_sysdev_dev = { | ||
| 445 | .cls = &clks_sysdev_class, | ||
| 446 | }; | ||
| 447 | |||
| 448 | static int __init clk_sysdev_init(void) | ||
| 449 | { | ||
| 450 | sysdev_class_register(&clks_sysdev_class); | ||
| 451 | sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver); | ||
| 452 | sysdev_register(&clks_sysdev_dev); | ||
| 453 | |||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | subsys_initcall(clk_sysdev_init); | ||
| 457 | #endif | ||
| 458 | |||
| 459 | /* | ||
| 460 | * debugfs support to trace clock tree hierarchy and attributes | ||
| 461 | */ | ||
| 462 | static struct dentry *clk_debugfs_root; | ||
| 463 | |||
| 464 | static int clk_debugfs_register_one(struct clk *c) | ||
| 465 | { | ||
| 466 | int err; | ||
| 467 | struct dentry *d, *child, *child_tmp; | ||
| 468 | struct clk *pa = c->parent; | ||
| 469 | char s[255]; | ||
| 470 | char *p = s; | ||
| 471 | |||
| 472 | p += sprintf(p, "%s", c->name); | ||
| 473 | if (c->id >= 0) | ||
| 474 | sprintf(p, ":%d", c->id); | ||
| 475 | d = debugfs_create_dir(s, pa ? pa->dentry : clk_debugfs_root); | ||
| 476 | if (!d) | ||
| 477 | return -ENOMEM; | ||
| 478 | c->dentry = d; | ||
| 479 | |||
| 480 | d = debugfs_create_u8("usecount", S_IRUGO, c->dentry, (u8 *)&c->usecount); | ||
| 481 | if (!d) { | ||
| 482 | err = -ENOMEM; | ||
| 483 | goto err_out; | ||
| 484 | } | ||
| 485 | d = debugfs_create_u32("rate", S_IRUGO, c->dentry, (u32 *)&c->rate); | ||
| 486 | if (!d) { | ||
| 487 | err = -ENOMEM; | ||
| 488 | goto err_out; | ||
| 489 | } | ||
| 490 | d = debugfs_create_x32("flags", S_IRUGO, c->dentry, (u32 *)&c->flags); | ||
| 491 | if (!d) { | ||
| 492 | err = -ENOMEM; | ||
| 493 | goto err_out; | ||
| 494 | } | ||
| 495 | return 0; | ||
| 496 | |||
| 497 | err_out: | ||
| 498 | d = c->dentry; | ||
| 499 | list_for_each_entry_safe(child, child_tmp, &d->d_subdirs, d_u.d_child) | ||
| 500 | debugfs_remove(child); | ||
| 501 | debugfs_remove(c->dentry); | ||
| 502 | return err; | ||
| 503 | } | ||
| 504 | |||
| 505 | static int clk_debugfs_register(struct clk *c) | ||
| 506 | { | ||
| 507 | int err; | ||
| 508 | struct clk *pa = c->parent; | ||
| 509 | |||
| 510 | if (pa && !pa->dentry) { | ||
| 511 | err = clk_debugfs_register(pa); | ||
| 512 | if (err) | ||
| 513 | return err; | ||
| 514 | } | ||
| 515 | |||
| 516 | if (!c->dentry && c->name) { | ||
| 517 | err = clk_debugfs_register_one(c); | ||
| 518 | if (err) | ||
| 519 | return err; | ||
| 520 | } | ||
| 521 | return 0; | ||
| 522 | } | ||
| 523 | |||
| 524 | static int __init clk_debugfs_init(void) | ||
| 525 | { | ||
| 526 | struct clk *c; | ||
| 527 | struct dentry *d; | ||
| 528 | int err; | ||
| 529 | |||
| 530 | d = debugfs_create_dir("clock", NULL); | ||
| 531 | if (!d) | ||
| 532 | return -ENOMEM; | ||
| 533 | clk_debugfs_root = d; | ||
| 534 | |||
| 535 | list_for_each_entry(c, &clock_list, node) { | ||
| 536 | err = clk_debugfs_register(c); | ||
| 537 | if (err) | ||
| 538 | goto err_out; | ||
| 539 | } | ||
| 540 | return 0; | ||
| 541 | err_out: | ||
| 542 | debugfs_remove_recursive(clk_debugfs_root); | ||
| 543 | return err; | ||
| 544 | } | ||
| 545 | late_initcall(clk_debugfs_init); | ||
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 94ad6bd86a00..c585574b9aed 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/topology.h> | 28 | #include <linux/topology.h> |
| 29 | #include <linux/bitmap.h> | 29 | #include <linux/bitmap.h> |
| 30 | #include <linux/cpumask.h> | 30 | #include <linux/cpumask.h> |
| 31 | #include <asm/sizes.h> | ||
| 31 | 32 | ||
| 32 | #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ | 33 | #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ |
| 33 | ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ | 34 | ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ |
| @@ -45,6 +46,12 @@ struct intc_handle_int { | |||
| 45 | unsigned long handle; | 46 | unsigned long handle; |
| 46 | }; | 47 | }; |
| 47 | 48 | ||
| 49 | struct intc_window { | ||
| 50 | phys_addr_t phys; | ||
| 51 | void __iomem *virt; | ||
| 52 | unsigned long size; | ||
| 53 | }; | ||
| 54 | |||
| 48 | struct intc_desc_int { | 55 | struct intc_desc_int { |
| 49 | struct list_head list; | 56 | struct list_head list; |
| 50 | struct sys_device sysdev; | 57 | struct sys_device sysdev; |
| @@ -58,6 +65,8 @@ struct intc_desc_int { | |||
| 58 | unsigned int nr_prio; | 65 | unsigned int nr_prio; |
| 59 | struct intc_handle_int *sense; | 66 | struct intc_handle_int *sense; |
| 60 | unsigned int nr_sense; | 67 | unsigned int nr_sense; |
| 68 | struct intc_window *window; | ||
| 69 | unsigned int nr_windows; | ||
| 61 | struct irq_chip chip; | 70 | struct irq_chip chip; |
| 62 | }; | 71 | }; |
| 63 | 72 | ||
| @@ -87,8 +96,12 @@ static DEFINE_SPINLOCK(vector_lock); | |||
| 87 | #define SMP_NR(d, x) 1 | 96 | #define SMP_NR(d, x) 1 |
| 88 | #endif | 97 | #endif |
| 89 | 98 | ||
| 90 | static unsigned int intc_prio_level[NR_IRQS]; /* for now */ | 99 | static unsigned int intc_prio_level[NR_IRQS]; /* for now */ |
| 100 | static unsigned int default_prio_level = 2; /* 2 - 16 */ | ||
| 91 | static unsigned long ack_handle[NR_IRQS]; | 101 | static unsigned long ack_handle[NR_IRQS]; |
| 102 | #ifdef CONFIG_INTC_BALANCING | ||
| 103 | static unsigned long dist_handle[NR_IRQS]; | ||
| 104 | #endif | ||
| 92 | 105 | ||
| 93 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) | 106 | static inline struct intc_desc_int *get_intc_desc(unsigned int irq) |
| 94 | { | 107 | { |
| @@ -96,6 +109,47 @@ static inline struct intc_desc_int *get_intc_desc(unsigned int irq) | |||
| 96 | return container_of(chip, struct intc_desc_int, chip); | 109 | return container_of(chip, struct intc_desc_int, chip); |
| 97 | } | 110 | } |
| 98 | 111 | ||
| 112 | static unsigned long intc_phys_to_virt(struct intc_desc_int *d, | ||
| 113 | unsigned long address) | ||
| 114 | { | ||
| 115 | struct intc_window *window; | ||
| 116 | int k; | ||
| 117 | |||
| 118 | /* scan through physical windows and convert address */ | ||
| 119 | for (k = 0; k < d->nr_windows; k++) { | ||
| 120 | window = d->window + k; | ||
| 121 | |||
| 122 | if (address < window->phys) | ||
| 123 | continue; | ||
| 124 | |||
| 125 | if (address >= (window->phys + window->size)) | ||
| 126 | continue; | ||
| 127 | |||
| 128 | address -= window->phys; | ||
| 129 | address += (unsigned long)window->virt; | ||
| 130 | |||
| 131 | return address; | ||
| 132 | } | ||
| 133 | |||
| 134 | /* no windows defined, register must be 1:1 mapped virt:phys */ | ||
| 135 | return address; | ||
| 136 | } | ||
| 137 | |||
| 138 | static unsigned int intc_get_reg(struct intc_desc_int *d, unsigned long address) | ||
| 139 | { | ||
| 140 | unsigned int k; | ||
| 141 | |||
| 142 | address = intc_phys_to_virt(d, address); | ||
| 143 | |||
| 144 | for (k = 0; k < d->nr_reg; k++) { | ||
| 145 | if (d->reg[k] == address) | ||
| 146 | return k; | ||
| 147 | } | ||
| 148 | |||
| 149 | BUG(); | ||
| 150 | return 0; | ||
| 151 | } | ||
| 152 | |||
| 99 | static inline unsigned int set_field(unsigned int value, | 153 | static inline unsigned int set_field(unsigned int value, |
| 100 | unsigned int field_value, | 154 | unsigned int field_value, |
| 101 | unsigned int handle) | 155 | unsigned int handle) |
| @@ -229,6 +283,85 @@ static void (*intc_disable_fns[])(unsigned long addr, | |||
| 229 | [MODE_PCLR_REG] = intc_mode_field, | 283 | [MODE_PCLR_REG] = intc_mode_field, |
| 230 | }; | 284 | }; |
| 231 | 285 | ||
| 286 | #ifdef CONFIG_INTC_BALANCING | ||
| 287 | static inline void intc_balancing_enable(unsigned int irq) | ||
| 288 | { | ||
| 289 | struct intc_desc_int *d = get_intc_desc(irq); | ||
| 290 | unsigned long handle = dist_handle[irq]; | ||
| 291 | unsigned long addr; | ||
| 292 | |||
| 293 | if (irq_balancing_disabled(irq) || !handle) | ||
| 294 | return; | ||
| 295 | |||
| 296 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); | ||
| 297 | intc_reg_fns[_INTC_FN(handle)](addr, handle, 1); | ||
| 298 | } | ||
| 299 | |||
| 300 | static inline void intc_balancing_disable(unsigned int irq) | ||
| 301 | { | ||
| 302 | struct intc_desc_int *d = get_intc_desc(irq); | ||
| 303 | unsigned long handle = dist_handle[irq]; | ||
| 304 | unsigned long addr; | ||
| 305 | |||
| 306 | if (irq_balancing_disabled(irq) || !handle) | ||
| 307 | return; | ||
| 308 | |||
| 309 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); | ||
| 310 | intc_reg_fns[_INTC_FN(handle)](addr, handle, 0); | ||
| 311 | } | ||
| 312 | |||
| 313 | static unsigned int intc_dist_data(struct intc_desc *desc, | ||
| 314 | struct intc_desc_int *d, | ||
| 315 | intc_enum enum_id) | ||
| 316 | { | ||
| 317 | struct intc_mask_reg *mr = desc->hw.mask_regs; | ||
| 318 | unsigned int i, j, fn, mode; | ||
| 319 | unsigned long reg_e, reg_d; | ||
| 320 | |||
| 321 | for (i = 0; mr && enum_id && i < desc->hw.nr_mask_regs; i++) { | ||
| 322 | mr = desc->hw.mask_regs + i; | ||
| 323 | |||
| 324 | /* | ||
| 325 | * Skip this entry if there's no auto-distribution | ||
| 326 | * register associated with it. | ||
| 327 | */ | ||
| 328 | if (!mr->dist_reg) | ||
| 329 | continue; | ||
| 330 | |||
| 331 | for (j = 0; j < ARRAY_SIZE(mr->enum_ids); j++) { | ||
| 332 | if (mr->enum_ids[j] != enum_id) | ||
| 333 | continue; | ||
| 334 | |||
| 335 | fn = REG_FN_MODIFY_BASE; | ||
| 336 | mode = MODE_ENABLE_REG; | ||
| 337 | reg_e = mr->dist_reg; | ||
| 338 | reg_d = mr->dist_reg; | ||
| 339 | |||
| 340 | fn += (mr->reg_width >> 3) - 1; | ||
| 341 | return _INTC_MK(fn, mode, | ||
| 342 | intc_get_reg(d, reg_e), | ||
| 343 | intc_get_reg(d, reg_d), | ||
| 344 | 1, | ||
| 345 | (mr->reg_width - 1) - j); | ||
| 346 | } | ||
| 347 | } | ||
| 348 | |||
| 349 | /* | ||
| 350 | * It's possible we've gotten here with no distribution options | ||
| 351 | * available for the IRQ in question, so we just skip over those. | ||
| 352 | */ | ||
| 353 | return 0; | ||
| 354 | } | ||
| 355 | #else | ||
| 356 | static inline void intc_balancing_enable(unsigned int irq) | ||
| 357 | { | ||
| 358 | } | ||
| 359 | |||
| 360 | static inline void intc_balancing_disable(unsigned int irq) | ||
| 361 | { | ||
| 362 | } | ||
| 363 | #endif | ||
| 364 | |||
| 232 | static inline void _intc_enable(unsigned int irq, unsigned long handle) | 365 | static inline void _intc_enable(unsigned int irq, unsigned long handle) |
| 233 | { | 366 | { |
| 234 | struct intc_desc_int *d = get_intc_desc(irq); | 367 | struct intc_desc_int *d = get_intc_desc(irq); |
| @@ -244,6 +377,8 @@ static inline void _intc_enable(unsigned int irq, unsigned long handle) | |||
| 244 | intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ | 377 | intc_enable_fns[_INTC_MODE(handle)](addr, handle, intc_reg_fns\ |
| 245 | [_INTC_FN(handle)], irq); | 378 | [_INTC_FN(handle)], irq); |
| 246 | } | 379 | } |
| 380 | |||
| 381 | intc_balancing_enable(irq); | ||
| 247 | } | 382 | } |
| 248 | 383 | ||
| 249 | static void intc_enable(unsigned int irq) | 384 | static void intc_enable(unsigned int irq) |
| @@ -254,10 +389,12 @@ static void intc_enable(unsigned int irq) | |||
| 254 | static void intc_disable(unsigned int irq) | 389 | static void intc_disable(unsigned int irq) |
| 255 | { | 390 | { |
| 256 | struct intc_desc_int *d = get_intc_desc(irq); | 391 | struct intc_desc_int *d = get_intc_desc(irq); |
| 257 | unsigned long handle = (unsigned long) get_irq_chip_data(irq); | 392 | unsigned long handle = (unsigned long)get_irq_chip_data(irq); |
| 258 | unsigned long addr; | 393 | unsigned long addr; |
| 259 | unsigned int cpu; | 394 | unsigned int cpu; |
| 260 | 395 | ||
| 396 | intc_balancing_disable(irq); | ||
| 397 | |||
| 261 | for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { | 398 | for (cpu = 0; cpu < SMP_NR(d, _INTC_ADDR_D(handle)); cpu++) { |
| 262 | #ifdef CONFIG_SMP | 399 | #ifdef CONFIG_SMP |
| 263 | if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity)) | 400 | if (!cpumask_test_cpu(cpu, irq_to_desc(irq)->affinity)) |
| @@ -336,8 +473,7 @@ static void intc_mask_ack(unsigned int irq) | |||
| 336 | 473 | ||
| 337 | intc_disable(irq); | 474 | intc_disable(irq); |
| 338 | 475 | ||
| 339 | /* read register and write zero only to the assocaited bit */ | 476 | /* read register and write zero only to the associated bit */ |
| 340 | |||
| 341 | if (handle) { | 477 | if (handle) { |
| 342 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); | 478 | addr = INTC_REG(d, _INTC_ADDR_D(handle), 0); |
| 343 | switch (_INTC_FN(handle)) { | 479 | switch (_INTC_FN(handle)) { |
| @@ -366,7 +502,8 @@ static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, | |||
| 366 | { | 502 | { |
| 367 | int i; | 503 | int i; |
| 368 | 504 | ||
| 369 | /* this doesn't scale well, but... | 505 | /* |
| 506 | * this doesn't scale well, but... | ||
| 370 | * | 507 | * |
| 371 | * this function should only be used for cerain uncommon | 508 | * this function should only be used for cerain uncommon |
| 372 | * operations such as intc_set_priority() and intc_set_sense() | 509 | * operations such as intc_set_priority() and intc_set_sense() |
| @@ -377,7 +514,6 @@ static struct intc_handle_int *intc_find_irq(struct intc_handle_int *hp, | |||
| 377 | * memory footprint down is to make sure the array is sorted | 514 | * memory footprint down is to make sure the array is sorted |
| 378 | * and then perform a bisect to lookup the irq. | 515 | * and then perform a bisect to lookup the irq. |
| 379 | */ | 516 | */ |
| 380 | |||
| 381 | for (i = 0; i < nr_hp; i++) { | 517 | for (i = 0; i < nr_hp; i++) { |
| 382 | if ((hp + i)->irq != irq) | 518 | if ((hp + i)->irq != irq) |
| 383 | continue; | 519 | continue; |
| @@ -408,7 +544,6 @@ int intc_set_priority(unsigned int irq, unsigned int prio) | |||
| 408 | * primary masking method is using intc_prio_level[irq] | 544 | * primary masking method is using intc_prio_level[irq] |
| 409 | * priority level will be set during next enable() | 545 | * priority level will be set during next enable() |
| 410 | */ | 546 | */ |
| 411 | |||
| 412 | if (_INTC_FN(ihp->handle) != REG_FN_ERR) | 547 | if (_INTC_FN(ihp->handle) != REG_FN_ERR) |
| 413 | _intc_enable(irq, ihp->handle); | 548 | _intc_enable(irq, ihp->handle); |
| 414 | } | 549 | } |
| @@ -447,20 +582,6 @@ static int intc_set_sense(unsigned int irq, unsigned int type) | |||
| 447 | return 0; | 582 | return 0; |
| 448 | } | 583 | } |
| 449 | 584 | ||
| 450 | static unsigned int __init intc_get_reg(struct intc_desc_int *d, | ||
| 451 | unsigned long address) | ||
| 452 | { | ||
| 453 | unsigned int k; | ||
| 454 | |||
| 455 | for (k = 0; k < d->nr_reg; k++) { | ||
| 456 | if (d->reg[k] == address) | ||
| 457 | return k; | ||
| 458 | } | ||
| 459 | |||
| 460 | BUG(); | ||
| 461 | return 0; | ||
| 462 | } | ||
| 463 | |||
| 464 | static intc_enum __init intc_grp_id(struct intc_desc *desc, | 585 | static intc_enum __init intc_grp_id(struct intc_desc *desc, |
| 465 | intc_enum enum_id) | 586 | intc_enum enum_id) |
| 466 | { | 587 | { |
| @@ -718,13 +839,14 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 718 | */ | 839 | */ |
| 719 | set_bit(irq, intc_irq_map); | 840 | set_bit(irq, intc_irq_map); |
| 720 | 841 | ||
| 721 | /* Prefer single interrupt source bitmap over other combinations: | 842 | /* |
| 843 | * Prefer single interrupt source bitmap over other combinations: | ||
| 844 | * | ||
| 722 | * 1. bitmap, single interrupt source | 845 | * 1. bitmap, single interrupt source |
| 723 | * 2. priority, single interrupt source | 846 | * 2. priority, single interrupt source |
| 724 | * 3. bitmap, multiple interrupt sources (groups) | 847 | * 3. bitmap, multiple interrupt sources (groups) |
| 725 | * 4. priority, multiple interrupt sources (groups) | 848 | * 4. priority, multiple interrupt sources (groups) |
| 726 | */ | 849 | */ |
| 727 | |||
| 728 | data[0] = intc_mask_data(desc, d, enum_id, 0); | 850 | data[0] = intc_mask_data(desc, d, enum_id, 0); |
| 729 | data[1] = intc_prio_data(desc, d, enum_id, 0); | 851 | data[1] = intc_prio_data(desc, d, enum_id, 0); |
| 730 | 852 | ||
| @@ -749,10 +871,11 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 749 | handle_level_irq, "level"); | 871 | handle_level_irq, "level"); |
| 750 | set_irq_chip_data(irq, (void *)data[primary]); | 872 | set_irq_chip_data(irq, (void *)data[primary]); |
| 751 | 873 | ||
| 752 | /* set priority level | 874 | /* |
| 875 | * set priority level | ||
| 753 | * - this needs to be at least 2 for 5-bit priorities on 7780 | 876 | * - this needs to be at least 2 for 5-bit priorities on 7780 |
| 754 | */ | 877 | */ |
| 755 | intc_prio_level[irq] = 2; | 878 | intc_prio_level[irq] = default_prio_level; |
| 756 | 879 | ||
| 757 | /* enable secondary masking method if present */ | 880 | /* enable secondary masking method if present */ |
| 758 | if (data[!primary]) | 881 | if (data[!primary]) |
| @@ -769,7 +892,6 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 769 | * only secondary priority should access registers, so | 892 | * only secondary priority should access registers, so |
| 770 | * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority() | 893 | * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority() |
| 771 | */ | 894 | */ |
| 772 | |||
| 773 | hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0); | 895 | hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0); |
| 774 | hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0); | 896 | hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0); |
| 775 | } | 897 | } |
| @@ -790,6 +912,11 @@ static void __init intc_register_irq(struct intc_desc *desc, | |||
| 790 | if (desc->hw.ack_regs) | 912 | if (desc->hw.ack_regs) |
| 791 | ack_handle[irq] = intc_ack_data(desc, d, enum_id); | 913 | ack_handle[irq] = intc_ack_data(desc, d, enum_id); |
| 792 | 914 | ||
| 915 | #ifdef CONFIG_INTC_BALANCING | ||
| 916 | if (desc->hw.mask_regs) | ||
| 917 | dist_handle[irq] = intc_dist_data(desc, d, enum_id); | ||
| 918 | #endif | ||
| 919 | |||
| 793 | #ifdef CONFIG_ARM | 920 | #ifdef CONFIG_ARM |
| 794 | set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */ | 921 | set_irq_flags(irq, IRQF_VALID); /* Enable IRQ on ARM systems */ |
| 795 | #endif | 922 | #endif |
| @@ -801,6 +928,8 @@ static unsigned int __init save_reg(struct intc_desc_int *d, | |||
| 801 | unsigned int smp) | 928 | unsigned int smp) |
| 802 | { | 929 | { |
| 803 | if (value) { | 930 | if (value) { |
| 931 | value = intc_phys_to_virt(d, value); | ||
| 932 | |||
| 804 | d->reg[cnt] = value; | 933 | d->reg[cnt] = value; |
| 805 | #ifdef CONFIG_SMP | 934 | #ifdef CONFIG_SMP |
| 806 | d->smp[cnt] = smp; | 935 | d->smp[cnt] = smp; |
| @@ -816,25 +945,59 @@ static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc) | |||
| 816 | generic_handle_irq((unsigned int)get_irq_data(irq)); | 945 | generic_handle_irq((unsigned int)get_irq_data(irq)); |
| 817 | } | 946 | } |
| 818 | 947 | ||
| 819 | void __init register_intc_controller(struct intc_desc *desc) | 948 | int __init register_intc_controller(struct intc_desc *desc) |
| 820 | { | 949 | { |
| 821 | unsigned int i, k, smp; | 950 | unsigned int i, k, smp; |
| 822 | struct intc_hw_desc *hw = &desc->hw; | 951 | struct intc_hw_desc *hw = &desc->hw; |
| 823 | struct intc_desc_int *d; | 952 | struct intc_desc_int *d; |
| 953 | struct resource *res; | ||
| 954 | |||
| 955 | pr_info("intc: Registered controller '%s' with %u IRQs\n", | ||
| 956 | desc->name, hw->nr_vectors); | ||
| 824 | 957 | ||
| 825 | d = kzalloc(sizeof(*d), GFP_NOWAIT); | 958 | d = kzalloc(sizeof(*d), GFP_NOWAIT); |
| 959 | if (!d) | ||
| 960 | goto err0; | ||
| 826 | 961 | ||
| 827 | INIT_LIST_HEAD(&d->list); | 962 | INIT_LIST_HEAD(&d->list); |
| 828 | list_add(&d->list, &intc_list); | 963 | list_add(&d->list, &intc_list); |
| 829 | 964 | ||
| 965 | if (desc->num_resources) { | ||
| 966 | d->nr_windows = desc->num_resources; | ||
| 967 | d->window = kzalloc(d->nr_windows * sizeof(*d->window), | ||
| 968 | GFP_NOWAIT); | ||
| 969 | if (!d->window) | ||
| 970 | goto err1; | ||
| 971 | |||
| 972 | for (k = 0; k < d->nr_windows; k++) { | ||
| 973 | res = desc->resource + k; | ||
| 974 | WARN_ON(resource_type(res) != IORESOURCE_MEM); | ||
| 975 | d->window[k].phys = res->start; | ||
| 976 | d->window[k].size = resource_size(res); | ||
| 977 | d->window[k].virt = ioremap_nocache(res->start, | ||
| 978 | resource_size(res)); | ||
| 979 | if (!d->window[k].virt) | ||
| 980 | goto err2; | ||
| 981 | } | ||
| 982 | } | ||
| 983 | |||
| 830 | d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; | 984 | d->nr_reg = hw->mask_regs ? hw->nr_mask_regs * 2 : 0; |
| 985 | #ifdef CONFIG_INTC_BALANCING | ||
| 986 | if (d->nr_reg) | ||
| 987 | d->nr_reg += hw->nr_mask_regs; | ||
| 988 | #endif | ||
| 831 | d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; | 989 | d->nr_reg += hw->prio_regs ? hw->nr_prio_regs * 2 : 0; |
| 832 | d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; | 990 | d->nr_reg += hw->sense_regs ? hw->nr_sense_regs : 0; |
| 833 | d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; | 991 | d->nr_reg += hw->ack_regs ? hw->nr_ack_regs : 0; |
| 834 | 992 | ||
| 835 | d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); | 993 | d->reg = kzalloc(d->nr_reg * sizeof(*d->reg), GFP_NOWAIT); |
| 994 | if (!d->reg) | ||
| 995 | goto err2; | ||
| 996 | |||
| 836 | #ifdef CONFIG_SMP | 997 | #ifdef CONFIG_SMP |
| 837 | d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); | 998 | d->smp = kzalloc(d->nr_reg * sizeof(*d->smp), GFP_NOWAIT); |
| 999 | if (!d->smp) | ||
| 1000 | goto err3; | ||
| 838 | #endif | 1001 | #endif |
| 839 | k = 0; | 1002 | k = 0; |
| 840 | 1003 | ||
| @@ -843,12 +1006,17 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 843 | smp = IS_SMP(hw->mask_regs[i]); | 1006 | smp = IS_SMP(hw->mask_regs[i]); |
| 844 | k += save_reg(d, k, hw->mask_regs[i].set_reg, smp); | 1007 | k += save_reg(d, k, hw->mask_regs[i].set_reg, smp); |
| 845 | k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); | 1008 | k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); |
| 1009 | #ifdef CONFIG_INTC_BALANCING | ||
| 1010 | k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0); | ||
| 1011 | #endif | ||
| 846 | } | 1012 | } |
| 847 | } | 1013 | } |
| 848 | 1014 | ||
| 849 | if (hw->prio_regs) { | 1015 | if (hw->prio_regs) { |
| 850 | d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio), | 1016 | d->prio = kzalloc(hw->nr_vectors * sizeof(*d->prio), |
| 851 | GFP_NOWAIT); | 1017 | GFP_NOWAIT); |
| 1018 | if (!d->prio) | ||
| 1019 | goto err4; | ||
| 852 | 1020 | ||
| 853 | for (i = 0; i < hw->nr_prio_regs; i++) { | 1021 | for (i = 0; i < hw->nr_prio_regs; i++) { |
| 854 | smp = IS_SMP(hw->prio_regs[i]); | 1022 | smp = IS_SMP(hw->prio_regs[i]); |
| @@ -860,6 +1028,8 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 860 | if (hw->sense_regs) { | 1028 | if (hw->sense_regs) { |
| 861 | d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense), | 1029 | d->sense = kzalloc(hw->nr_vectors * sizeof(*d->sense), |
| 862 | GFP_NOWAIT); | 1030 | GFP_NOWAIT); |
| 1031 | if (!d->sense) | ||
| 1032 | goto err5; | ||
| 863 | 1033 | ||
| 864 | for (i = 0; i < hw->nr_sense_regs; i++) | 1034 | for (i = 0; i < hw->nr_sense_regs; i++) |
| 865 | k += save_reg(d, k, hw->sense_regs[i].reg, 0); | 1035 | k += save_reg(d, k, hw->sense_regs[i].reg, 0); |
| @@ -906,7 +1076,7 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 906 | 1076 | ||
| 907 | irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); | 1077 | irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); |
| 908 | if (unlikely(!irq_desc)) { | 1078 | if (unlikely(!irq_desc)) { |
| 909 | pr_info("can't get irq_desc for %d\n", irq); | 1079 | pr_err("can't get irq_desc for %d\n", irq); |
| 910 | continue; | 1080 | continue; |
| 911 | } | 1081 | } |
| 912 | 1082 | ||
| @@ -926,7 +1096,7 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 926 | */ | 1096 | */ |
| 927 | irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id()); | 1097 | irq_desc = irq_to_desc_alloc_node(irq2, numa_node_id()); |
| 928 | if (unlikely(!irq_desc)) { | 1098 | if (unlikely(!irq_desc)) { |
| 929 | pr_info("can't get irq_desc for %d\n", irq2); | 1099 | pr_err("can't get irq_desc for %d\n", irq2); |
| 930 | continue; | 1100 | continue; |
| 931 | } | 1101 | } |
| 932 | 1102 | ||
| @@ -942,8 +1112,100 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 942 | /* enable bits matching force_enable after registering irqs */ | 1112 | /* enable bits matching force_enable after registering irqs */ |
| 943 | if (desc->force_enable) | 1113 | if (desc->force_enable) |
| 944 | intc_enable_disable_enum(desc, d, desc->force_enable, 1); | 1114 | intc_enable_disable_enum(desc, d, desc->force_enable, 1); |
| 1115 | |||
| 1116 | return 0; | ||
| 1117 | err5: | ||
| 1118 | kfree(d->prio); | ||
| 1119 | err4: | ||
| 1120 | #ifdef CONFIG_SMP | ||
| 1121 | kfree(d->smp); | ||
| 1122 | err3: | ||
| 1123 | #endif | ||
| 1124 | kfree(d->reg); | ||
| 1125 | err2: | ||
| 1126 | for (k = 0; k < d->nr_windows; k++) | ||
| 1127 | if (d->window[k].virt) | ||
| 1128 | iounmap(d->window[k].virt); | ||
| 1129 | |||
| 1130 | kfree(d->window); | ||
| 1131 | err1: | ||
| 1132 | kfree(d); | ||
| 1133 | err0: | ||
| 1134 | pr_err("unable to allocate INTC memory\n"); | ||
| 1135 | |||
| 1136 | return -ENOMEM; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | #ifdef CONFIG_INTC_USERIMASK | ||
| 1140 | static void __iomem *uimask; | ||
| 1141 | |||
| 1142 | int register_intc_userimask(unsigned long addr) | ||
| 1143 | { | ||
| 1144 | if (unlikely(uimask)) | ||
| 1145 | return -EBUSY; | ||
| 1146 | |||
| 1147 | uimask = ioremap_nocache(addr, SZ_4K); | ||
| 1148 | if (unlikely(!uimask)) | ||
| 1149 | return -ENOMEM; | ||
| 1150 | |||
| 1151 | pr_info("intc: userimask support registered for levels 0 -> %d\n", | ||
| 1152 | default_prio_level - 1); | ||
| 1153 | |||
| 1154 | return 0; | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | static ssize_t | ||
| 1158 | show_intc_userimask(struct sysdev_class *cls, | ||
| 1159 | struct sysdev_class_attribute *attr, char *buf) | ||
| 1160 | { | ||
| 1161 | return sprintf(buf, "%d\n", (__raw_readl(uimask) >> 4) & 0xf); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | static ssize_t | ||
| 1165 | store_intc_userimask(struct sysdev_class *cls, | ||
| 1166 | struct sysdev_class_attribute *attr, | ||
| 1167 | const char *buf, size_t count) | ||
| 1168 | { | ||
| 1169 | unsigned long level; | ||
| 1170 | |||
| 1171 | level = simple_strtoul(buf, NULL, 10); | ||
| 1172 | |||
| 1173 | /* | ||
| 1174 | * Minimal acceptable IRQ levels are in the 2 - 16 range, but | ||
| 1175 | * these are chomped so as to not interfere with normal IRQs. | ||
| 1176 | * | ||
| 1177 | * Level 1 is a special case on some CPUs in that it's not | ||
| 1178 | * directly settable, but given that USERIMASK cuts off below a | ||
| 1179 | * certain level, we don't care about this limitation here. | ||
| 1180 | * Level 0 on the other hand equates to user masking disabled. | ||
| 1181 | * | ||
| 1182 | * We use default_prio_level as a cut off so that only special | ||
| 1183 | * case opt-in IRQs can be mangled. | ||
| 1184 | */ | ||
| 1185 | if (level >= default_prio_level) | ||
| 1186 | return -EINVAL; | ||
| 1187 | |||
| 1188 | __raw_writel(0xa5 << 24 | level << 4, uimask); | ||
| 1189 | |||
| 1190 | return count; | ||
| 945 | } | 1191 | } |
| 946 | 1192 | ||
| 1193 | static SYSDEV_CLASS_ATTR(userimask, S_IRUSR | S_IWUSR, | ||
| 1194 | show_intc_userimask, store_intc_userimask); | ||
| 1195 | #endif | ||
| 1196 | |||
| 1197 | static ssize_t | ||
| 1198 | show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf) | ||
| 1199 | { | ||
| 1200 | struct intc_desc_int *d; | ||
| 1201 | |||
| 1202 | d = container_of(dev, struct intc_desc_int, sysdev); | ||
| 1203 | |||
| 1204 | return sprintf(buf, "%s\n", d->chip.name); | ||
| 1205 | } | ||
| 1206 | |||
| 1207 | static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL); | ||
| 1208 | |||
| 947 | static int intc_suspend(struct sys_device *dev, pm_message_t state) | 1209 | static int intc_suspend(struct sys_device *dev, pm_message_t state) |
| 948 | { | 1210 | { |
| 949 | struct intc_desc_int *d; | 1211 | struct intc_desc_int *d; |
| @@ -1003,19 +1265,28 @@ static int __init register_intc_sysdevs(void) | |||
| 1003 | int id = 0; | 1265 | int id = 0; |
| 1004 | 1266 | ||
| 1005 | error = sysdev_class_register(&intc_sysdev_class); | 1267 | error = sysdev_class_register(&intc_sysdev_class); |
| 1268 | #ifdef CONFIG_INTC_USERIMASK | ||
| 1269 | if (!error && uimask) | ||
| 1270 | error = sysdev_class_create_file(&intc_sysdev_class, | ||
| 1271 | &attr_userimask); | ||
| 1272 | #endif | ||
| 1006 | if (!error) { | 1273 | if (!error) { |
| 1007 | list_for_each_entry(d, &intc_list, list) { | 1274 | list_for_each_entry(d, &intc_list, list) { |
| 1008 | d->sysdev.id = id; | 1275 | d->sysdev.id = id; |
| 1009 | d->sysdev.cls = &intc_sysdev_class; | 1276 | d->sysdev.cls = &intc_sysdev_class; |
| 1010 | error = sysdev_register(&d->sysdev); | 1277 | error = sysdev_register(&d->sysdev); |
| 1278 | if (error == 0) | ||
| 1279 | error = sysdev_create_file(&d->sysdev, | ||
| 1280 | &attr_name); | ||
| 1011 | if (error) | 1281 | if (error) |
| 1012 | break; | 1282 | break; |
| 1283 | |||
| 1013 | id++; | 1284 | id++; |
| 1014 | } | 1285 | } |
| 1015 | } | 1286 | } |
| 1016 | 1287 | ||
| 1017 | if (error) | 1288 | if (error) |
| 1018 | pr_warning("intc: sysdev registration error\n"); | 1289 | pr_err("intc: sysdev registration error\n"); |
| 1019 | 1290 | ||
| 1020 | return error; | 1291 | return error; |
| 1021 | } | 1292 | } |
| @@ -1048,7 +1319,7 @@ unsigned int create_irq_nr(unsigned int irq_want, int node) | |||
| 1048 | 1319 | ||
| 1049 | desc = irq_to_desc_alloc_node(new, node); | 1320 | desc = irq_to_desc_alloc_node(new, node); |
| 1050 | if (unlikely(!desc)) { | 1321 | if (unlikely(!desc)) { |
| 1051 | pr_info("can't get irq_desc for %d\n", new); | 1322 | pr_err("can't get irq_desc for %d\n", new); |
| 1052 | goto out_unlock; | 1323 | goto out_unlock; |
| 1053 | } | 1324 | } |
| 1054 | 1325 | ||
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 36828358a4d8..e76b1afafe07 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
| @@ -36,8 +36,7 @@ | |||
| 36 | #include <asm/delay.h> | 36 | #include <asm/delay.h> |
| 37 | 37 | ||
| 38 | #include <mach/dma.h> | 38 | #include <mach/dma.h> |
| 39 | #include <mach/regs-ssp.h> | 39 | #include <plat/ssp.h> |
| 40 | #include <mach/ssp.h> | ||
| 41 | #include <mach/pxa2xx_spi.h> | 40 | #include <mach/pxa2xx_spi.h> |
| 42 | 41 | ||
| 43 | MODULE_AUTHOR("Stephen Street"); | 42 | MODULE_AUTHOR("Stephen Street"); |
| @@ -1318,14 +1317,14 @@ static int setup(struct spi_device *spi) | |||
| 1318 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ | 1317 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ |
| 1319 | if (drv_data->ssp_type != PXA25x_SSP) | 1318 | if (drv_data->ssp_type != PXA25x_SSP) |
| 1320 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", | 1319 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", |
| 1321 | clk_get_rate(ssp->clk) | 1320 | clk_get_rate(ssp->clk) |
| 1322 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1321 | / (1 + ((chip->cr0 & SSCR0_SCR(0xfff)) >> 8)), |
| 1323 | chip->enable_dma ? "DMA" : "PIO"); | 1322 | chip->enable_dma ? "DMA" : "PIO"); |
| 1324 | else | 1323 | else |
| 1325 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", | 1324 | dev_dbg(&spi->dev, "%ld Hz actual, %s\n", |
| 1326 | clk_get_rate(ssp->clk) / 2 | 1325 | clk_get_rate(ssp->clk) / 2 |
| 1327 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1326 | / (1 + ((chip->cr0 & SSCR0_SCR(0x0ff)) >> 8)), |
| 1328 | chip->enable_dma ? "DMA" : "PIO"); | 1327 | chip->enable_dma ? "DMA" : "PIO"); |
| 1329 | 1328 | ||
| 1330 | if (spi->bits_per_word <= 8) { | 1329 | if (spi->bits_per_word <= 8) { |
| 1331 | chip->n_bytes = 1; | 1330 | chip->n_bytes = 1; |
| @@ -1466,7 +1465,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
| 1466 | 1465 | ||
| 1467 | platform_info = dev->platform_data; | 1466 | platform_info = dev->platform_data; |
| 1468 | 1467 | ||
| 1469 | ssp = ssp_request(pdev->id, pdev->name); | 1468 | ssp = pxa_ssp_request(pdev->id, pdev->name); |
| 1470 | if (ssp == NULL) { | 1469 | if (ssp == NULL) { |
| 1471 | dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); | 1470 | dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); |
| 1472 | return -ENODEV; | 1471 | return -ENODEV; |
| @@ -1476,7 +1475,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
| 1476 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); | 1475 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); |
| 1477 | if (!master) { | 1476 | if (!master) { |
| 1478 | dev_err(&pdev->dev, "cannot alloc spi_master\n"); | 1477 | dev_err(&pdev->dev, "cannot alloc spi_master\n"); |
| 1479 | ssp_free(ssp); | 1478 | pxa_ssp_free(ssp); |
| 1480 | return -ENOMEM; | 1479 | return -ENOMEM; |
| 1481 | } | 1480 | } |
| 1482 | drv_data = spi_master_get_devdata(master); | 1481 | drv_data = spi_master_get_devdata(master); |
| @@ -1558,7 +1557,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
| 1558 | write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | | 1557 | write_SSCR1(SSCR1_RxTresh(RX_THRESH_DFLT) | |
| 1559 | SSCR1_TxTresh(TX_THRESH_DFLT), | 1558 | SSCR1_TxTresh(TX_THRESH_DFLT), |
| 1560 | drv_data->ioaddr); | 1559 | drv_data->ioaddr); |
| 1561 | write_SSCR0(SSCR0_SerClkDiv(2) | 1560 | write_SSCR0(SSCR0_SCR(2) |
| 1562 | | SSCR0_Motorola | 1561 | | SSCR0_Motorola |
| 1563 | | SSCR0_DataSize(8), | 1562 | | SSCR0_DataSize(8), |
| 1564 | drv_data->ioaddr); | 1563 | drv_data->ioaddr); |
| @@ -1605,7 +1604,7 @@ out_error_irq_alloc: | |||
| 1605 | 1604 | ||
| 1606 | out_error_master_alloc: | 1605 | out_error_master_alloc: |
| 1607 | spi_master_put(master); | 1606 | spi_master_put(master); |
| 1608 | ssp_free(ssp); | 1607 | pxa_ssp_free(ssp); |
| 1609 | return status; | 1608 | return status; |
| 1610 | } | 1609 | } |
| 1611 | 1610 | ||
| @@ -1649,7 +1648,7 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) | |||
| 1649 | free_irq(ssp->irq, drv_data); | 1648 | free_irq(ssp->irq, drv_data); |
| 1650 | 1649 | ||
| 1651 | /* Release SSP */ | 1650 | /* Release SSP */ |
| 1652 | ssp_free(ssp); | 1651 | pxa_ssp_free(ssp); |
| 1653 | 1652 | ||
| 1654 | /* Disconnect from the SPI framework */ | 1653 | /* Disconnect from the SPI framework */ |
| 1655 | spi_unregister_master(drv_data->master); | 1654 | spi_unregister_master(drv_data->master); |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index 4a6366a42129..111a01a747fc 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
| @@ -380,6 +380,7 @@ static int usbfs_rmdir(struct inode *dir, struct dentry *dentry) | |||
| 380 | mutex_lock(&inode->i_mutex); | 380 | mutex_lock(&inode->i_mutex); |
| 381 | dentry_unhash(dentry); | 381 | dentry_unhash(dentry); |
| 382 | if (usbfs_empty(dentry)) { | 382 | if (usbfs_empty(dentry)) { |
| 383 | dont_mount(dentry); | ||
| 383 | drop_nlink(dentry->d_inode); | 384 | drop_nlink(dentry->d_inode); |
| 384 | drop_nlink(dentry->d_inode); | 385 | drop_nlink(dentry->d_inode); |
| 385 | dput(dentry); | 386 | dput(dentry); |
diff --git a/drivers/usb/gadget/at91_udc.c b/drivers/usb/gadget/at91_udc.c index df1bae9b048e..eaa79c8a9b8c 100644 --- a/drivers/usb/gadget/at91_udc.c +++ b/drivers/usb/gadget/at91_udc.c | |||
| @@ -366,6 +366,13 @@ rescan: | |||
| 366 | if (is_done) | 366 | if (is_done) |
| 367 | done(ep, req, 0); | 367 | done(ep, req, 0); |
| 368 | else if (ep->is_pingpong) { | 368 | else if (ep->is_pingpong) { |
| 369 | /* | ||
| 370 | * One dummy read to delay the code because of a HW glitch: | ||
| 371 | * CSR returns bad RXCOUNT when read too soon after updating | ||
| 372 | * RX_DATA_BK flags. | ||
| 373 | */ | ||
| 374 | csr = __raw_readl(creg); | ||
| 375 | |||
| 369 | bufferspace -= count; | 376 | bufferspace -= count; |
| 370 | buf += count; | 377 | buf += count; |
| 371 | goto rescan; | 378 | goto rescan; |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index e69d238c5af0..49fa953aaf6e 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
| @@ -1035,7 +1035,12 @@ int vhost_add_used(struct vhost_virtqueue *vq, unsigned int head, int len) | |||
| 1035 | /* This actually signals the guest, using eventfd. */ | 1035 | /* This actually signals the guest, using eventfd. */ |
| 1036 | void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) | 1036 | void vhost_signal(struct vhost_dev *dev, struct vhost_virtqueue *vq) |
| 1037 | { | 1037 | { |
| 1038 | __u16 flags = 0; | 1038 | __u16 flags; |
| 1039 | /* Flush out used index updates. This is paired | ||
| 1040 | * with the barrier that the Guest executes when enabling | ||
| 1041 | * interrupts. */ | ||
| 1042 | smp_mb(); | ||
| 1043 | |||
| 1039 | if (get_user(flags, &vq->avail->flags)) { | 1044 | if (get_user(flags, &vq->avail->flags)) { |
| 1040 | vq_err(vq, "Failed to get flags"); | 1045 | vq_err(vq, "Failed to get flags"); |
| 1041 | return; | 1046 | return; |
diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index dca48df98444..e5d6b56d4447 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c | |||
| @@ -50,8 +50,9 @@ | |||
| 50 | #include <linux/fb.h> | 50 | #include <linux/fb.h> |
| 51 | #include <linux/init.h> | 51 | #include <linux/init.h> |
| 52 | #include <linux/ioport.h> | 52 | #include <linux/ioport.h> |
| 53 | 53 | #include <linux/platform_device.h> | |
| 54 | #include <linux/uaccess.h> | 54 | #include <linux/uaccess.h> |
| 55 | |||
| 55 | #include <asm/system.h> | 56 | #include <asm/system.h> |
| 56 | #include <asm/irq.h> | 57 | #include <asm/irq.h> |
| 57 | #include <asm/amigahw.h> | 58 | #include <asm/amigahw.h> |
| @@ -1135,7 +1136,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg | |||
| 1135 | * Interface to the low level console driver | 1136 | * Interface to the low level console driver |
| 1136 | */ | 1137 | */ |
| 1137 | 1138 | ||
| 1138 | static void amifb_deinit(void); | 1139 | static void amifb_deinit(struct platform_device *pdev); |
| 1139 | 1140 | ||
| 1140 | /* | 1141 | /* |
| 1141 | * Internal routines | 1142 | * Internal routines |
| @@ -2246,7 +2247,7 @@ static inline void chipfree(void) | |||
| 2246 | * Initialisation | 2247 | * Initialisation |
| 2247 | */ | 2248 | */ |
| 2248 | 2249 | ||
| 2249 | static int __init amifb_init(void) | 2250 | static int __init amifb_probe(struct platform_device *pdev) |
| 2250 | { | 2251 | { |
| 2251 | int tag, i, err = 0; | 2252 | int tag, i, err = 0; |
| 2252 | u_long chipptr; | 2253 | u_long chipptr; |
| @@ -2261,16 +2262,6 @@ static int __init amifb_init(void) | |||
| 2261 | } | 2262 | } |
| 2262 | amifb_setup(option); | 2263 | amifb_setup(option); |
| 2263 | #endif | 2264 | #endif |
| 2264 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) | ||
| 2265 | return -ENODEV; | ||
| 2266 | |||
| 2267 | /* | ||
| 2268 | * We request all registers starting from bplpt[0] | ||
| 2269 | */ | ||
| 2270 | if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, | ||
| 2271 | "amifb [Denise/Lisa]")) | ||
| 2272 | return -EBUSY; | ||
| 2273 | |||
| 2274 | custom.dmacon = DMAF_ALL | DMAF_MASTER; | 2265 | custom.dmacon = DMAF_ALL | DMAF_MASTER; |
| 2275 | 2266 | ||
| 2276 | switch (amiga_chipset) { | 2267 | switch (amiga_chipset) { |
| @@ -2377,6 +2368,7 @@ default_chipset: | |||
| 2377 | fb_info.fbops = &amifb_ops; | 2368 | fb_info.fbops = &amifb_ops; |
| 2378 | fb_info.par = ¤tpar; | 2369 | fb_info.par = ¤tpar; |
| 2379 | fb_info.flags = FBINFO_DEFAULT; | 2370 | fb_info.flags = FBINFO_DEFAULT; |
| 2371 | fb_info.device = &pdev->dev; | ||
| 2380 | 2372 | ||
| 2381 | if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, | 2373 | if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, |
| 2382 | NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { | 2374 | NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { |
| @@ -2451,18 +2443,18 @@ default_chipset: | |||
| 2451 | return 0; | 2443 | return 0; |
| 2452 | 2444 | ||
| 2453 | amifb_error: | 2445 | amifb_error: |
| 2454 | amifb_deinit(); | 2446 | amifb_deinit(pdev); |
| 2455 | return err; | 2447 | return err; |
| 2456 | } | 2448 | } |
| 2457 | 2449 | ||
| 2458 | static void amifb_deinit(void) | 2450 | static void amifb_deinit(struct platform_device *pdev) |
| 2459 | { | 2451 | { |
| 2460 | if (fb_info.cmap.len) | 2452 | if (fb_info.cmap.len) |
| 2461 | fb_dealloc_cmap(&fb_info.cmap); | 2453 | fb_dealloc_cmap(&fb_info.cmap); |
| 2454 | fb_dealloc_cmap(&fb_info.cmap); | ||
| 2462 | chipfree(); | 2455 | chipfree(); |
| 2463 | if (videomemory) | 2456 | if (videomemory) |
| 2464 | iounmap((void*)videomemory); | 2457 | iounmap((void*)videomemory); |
| 2465 | release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); | ||
| 2466 | custom.dmacon = DMAF_ALL | DMAF_MASTER; | 2458 | custom.dmacon = DMAF_ALL | DMAF_MASTER; |
| 2467 | } | 2459 | } |
| 2468 | 2460 | ||
| @@ -3794,14 +3786,35 @@ static void ami_rebuild_copper(void) | |||
| 3794 | } | 3786 | } |
| 3795 | } | 3787 | } |
| 3796 | 3788 | ||
| 3797 | static void __exit amifb_exit(void) | 3789 | static int __exit amifb_remove(struct platform_device *pdev) |
| 3798 | { | 3790 | { |
| 3799 | unregister_framebuffer(&fb_info); | 3791 | unregister_framebuffer(&fb_info); |
| 3800 | amifb_deinit(); | 3792 | amifb_deinit(pdev); |
| 3801 | amifb_video_off(); | 3793 | amifb_video_off(); |
| 3794 | return 0; | ||
| 3795 | } | ||
| 3796 | |||
| 3797 | static struct platform_driver amifb_driver = { | ||
| 3798 | .remove = __exit_p(amifb_remove), | ||
| 3799 | .driver = { | ||
| 3800 | .name = "amiga-video", | ||
| 3801 | .owner = THIS_MODULE, | ||
| 3802 | }, | ||
| 3803 | }; | ||
| 3804 | |||
| 3805 | static int __init amifb_init(void) | ||
| 3806 | { | ||
| 3807 | return platform_driver_probe(&amifb_driver, amifb_probe); | ||
| 3802 | } | 3808 | } |
| 3803 | 3809 | ||
| 3804 | module_init(amifb_init); | 3810 | module_init(amifb_init); |
| 3811 | |||
| 3812 | static void __exit amifb_exit(void) | ||
| 3813 | { | ||
| 3814 | platform_driver_unregister(&amifb_driver); | ||
| 3815 | } | ||
| 3816 | |||
| 3805 | module_exit(amifb_exit); | 3817 | module_exit(amifb_exit); |
| 3806 | 3818 | ||
| 3807 | MODULE_LICENSE("GPL"); | 3819 | MODULE_LICENSE("GPL"); |
| 3820 | MODULE_ALIAS("platform:amiga-video"); | ||
diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 44e49c28b2a7..c2ec3dcd4e91 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c | |||
| @@ -488,9 +488,9 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) | |||
| 488 | fbinfo->fbops = &bfin_t350mcqb_fb_ops; | 488 | fbinfo->fbops = &bfin_t350mcqb_fb_ops; |
| 489 | fbinfo->flags = FBINFO_FLAG_DEFAULT; | 489 | fbinfo->flags = FBINFO_FLAG_DEFAULT; |
| 490 | 490 | ||
| 491 | info->fb_buffer = | 491 | info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len + |
| 492 | dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, | 492 | ACTIVE_VIDEO_MEM_OFFSET, |
| 493 | GFP_KERNEL); | 493 | &info->dma_handle, GFP_KERNEL); |
| 494 | 494 | ||
| 495 | if (NULL == info->fb_buffer) { | 495 | if (NULL == info->fb_buffer) { |
| 496 | printk(KERN_ERR DRIVER_NAME | 496 | printk(KERN_ERR DRIVER_NAME |
| @@ -568,8 +568,8 @@ out7: | |||
| 568 | out6: | 568 | out6: |
| 569 | fb_dealloc_cmap(&fbinfo->cmap); | 569 | fb_dealloc_cmap(&fbinfo->cmap); |
| 570 | out4: | 570 | out4: |
| 571 | dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, | 571 | dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET, |
| 572 | info->dma_handle); | 572 | info->fb_buffer, info->dma_handle); |
| 573 | out3: | 573 | out3: |
| 574 | framebuffer_release(fbinfo); | 574 | framebuffer_release(fbinfo); |
| 575 | out2: | 575 | out2: |
| @@ -592,8 +592,9 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev) | |||
| 592 | free_irq(info->irq, info); | 592 | free_irq(info->irq, info); |
| 593 | 593 | ||
| 594 | if (info->fb_buffer != NULL) | 594 | if (info->fb_buffer != NULL) |
| 595 | dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, | 595 | dma_free_coherent(NULL, fbinfo->fix.smem_len + |
| 596 | info->dma_handle); | 596 | ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer, |
| 597 | info->dma_handle); | ||
| 597 | 598 | ||
| 598 | fb_dealloc_cmap(&fbinfo->cmap); | 599 | fb_dealloc_cmap(&fbinfo->cmap); |
| 599 | 600 | ||
diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8d8dfda2f868..6df7c54db0a3 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c | |||
| @@ -299,6 +299,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = { | |||
| 299 | }, | 299 | }, |
| 300 | { 0 } | 300 | { 0 } |
| 301 | }; | 301 | }; |
| 302 | MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); | ||
| 302 | 303 | ||
| 303 | static const struct { | 304 | static const struct { |
| 304 | zorro_id id2; | 305 | zorro_id id2; |
diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 6c91c61cdb63..1b0feb8e7244 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c | |||
| @@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = { | |||
| 219 | { ZORRO_PROD_HELFRICH_RAINBOW_II }, | 219 | { ZORRO_PROD_HELFRICH_RAINBOW_II }, |
| 220 | { 0 } | 220 | { 0 } |
| 221 | }; | 221 | }; |
| 222 | MODULE_DEVICE_TABLE(zorro, fm2fb_devices); | ||
| 222 | 223 | ||
| 223 | static struct zorro_driver fm2fb_driver = { | 224 | static struct zorro_driver fm2fb_driver = { |
| 224 | .name = "fm2fb", | 225 | .name = "fm2fb", |
diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index e14bd0749129..e8c769944812 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c | |||
| @@ -695,6 +695,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, | |||
| 695 | * 1) Enable Runtime PM | 695 | * 1) Enable Runtime PM |
| 696 | * 2) Force Runtime PM Resume since hardware is accessed from probe() | 696 | * 2) Force Runtime PM Resume since hardware is accessed from probe() |
| 697 | */ | 697 | */ |
| 698 | priv->dev = &pdev->dev; | ||
| 698 | pm_runtime_enable(priv->dev); | 699 | pm_runtime_enable(priv->dev); |
| 699 | pm_runtime_resume(priv->dev); | 700 | pm_runtime_resume(priv->dev); |
| 700 | return 0; | 701 | return 0; |
| @@ -957,25 +958,24 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 957 | 958 | ||
| 958 | if (!pdev->dev.platform_data) { | 959 | if (!pdev->dev.platform_data) { |
| 959 | dev_err(&pdev->dev, "no platform data defined\n"); | 960 | dev_err(&pdev->dev, "no platform data defined\n"); |
| 960 | error = -EINVAL; | 961 | return -EINVAL; |
| 961 | goto err0; | ||
| 962 | } | 962 | } |
| 963 | 963 | ||
| 964 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 964 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| 965 | i = platform_get_irq(pdev, 0); | 965 | i = platform_get_irq(pdev, 0); |
| 966 | if (!res || i < 0) { | 966 | if (!res || i < 0) { |
| 967 | dev_err(&pdev->dev, "cannot get platform resources\n"); | 967 | dev_err(&pdev->dev, "cannot get platform resources\n"); |
| 968 | error = -ENOENT; | 968 | return -ENOENT; |
| 969 | goto err0; | ||
| 970 | } | 969 | } |
| 971 | 970 | ||
| 972 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 971 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 973 | if (!priv) { | 972 | if (!priv) { |
| 974 | dev_err(&pdev->dev, "cannot allocate device data\n"); | 973 | dev_err(&pdev->dev, "cannot allocate device data\n"); |
| 975 | error = -ENOMEM; | 974 | return -ENOMEM; |
| 976 | goto err0; | ||
| 977 | } | 975 | } |
| 978 | 976 | ||
| 977 | platform_set_drvdata(pdev, priv); | ||
| 978 | |||
| 979 | error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, | 979 | error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, |
| 980 | dev_name(&pdev->dev), priv); | 980 | dev_name(&pdev->dev), priv); |
| 981 | if (error) { | 981 | if (error) { |
| @@ -984,8 +984,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 984 | } | 984 | } |
| 985 | 985 | ||
| 986 | priv->irq = i; | 986 | priv->irq = i; |
| 987 | priv->dev = &pdev->dev; | ||
| 988 | platform_set_drvdata(pdev, priv); | ||
| 989 | pdata = pdev->dev.platform_data; | 987 | pdata = pdev->dev.platform_data; |
| 990 | 988 | ||
| 991 | j = 0; | 989 | j = 0; |
| @@ -1099,9 +1097,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1099 | info = ch->info; | 1097 | info = ch->info; |
| 1100 | 1098 | ||
| 1101 | if (info->fbdefio) { | 1099 | if (info->fbdefio) { |
| 1102 | priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * | 1100 | ch->sglist = vmalloc(sizeof(struct scatterlist) * |
| 1103 | info->fix.smem_len >> PAGE_SHIFT); | 1101 | info->fix.smem_len >> PAGE_SHIFT); |
| 1104 | if (!priv->ch->sglist) { | 1102 | if (!ch->sglist) { |
| 1105 | dev_err(&pdev->dev, "cannot allocate sglist\n"); | 1103 | dev_err(&pdev->dev, "cannot allocate sglist\n"); |
| 1106 | goto err1; | 1104 | goto err1; |
| 1107 | } | 1105 | } |
| @@ -1126,9 +1124,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) | |||
| 1126 | } | 1124 | } |
| 1127 | 1125 | ||
| 1128 | return 0; | 1126 | return 0; |
| 1129 | err1: | 1127 | err1: |
| 1130 | sh_mobile_lcdc_remove(pdev); | 1128 | sh_mobile_lcdc_remove(pdev); |
| 1131 | err0: | 1129 | |
| 1132 | return error; | 1130 | return error; |
| 1133 | } | 1131 | } |
| 1134 | 1132 | ||
| @@ -1139,7 +1137,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) | |||
| 1139 | int i; | 1137 | int i; |
| 1140 | 1138 | ||
| 1141 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) | 1139 | for (i = 0; i < ARRAY_SIZE(priv->ch); i++) |
| 1142 | if (priv->ch[i].info->dev) | 1140 | if (priv->ch[i].info && priv->ch[i].info->dev) |
| 1143 | unregister_framebuffer(priv->ch[i].info); | 1141 | unregister_framebuffer(priv->ch[i].info); |
| 1144 | 1142 | ||
| 1145 | sh_mobile_lcdc_stop(priv); | 1143 | sh_mobile_lcdc_stop(priv); |
| @@ -1162,7 +1160,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) | |||
| 1162 | if (priv->dot_clk) | 1160 | if (priv->dot_clk) |
| 1163 | clk_put(priv->dot_clk); | 1161 | clk_put(priv->dot_clk); |
| 1164 | 1162 | ||
| 1165 | pm_runtime_disable(priv->dev); | 1163 | if (priv->dev) |
| 1164 | pm_runtime_disable(priv->dev); | ||
| 1166 | 1165 | ||
| 1167 | if (priv->base) | 1166 | if (priv->base) |
| 1168 | iounmap(priv->base); | 1167 | iounmap(priv->base); |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 0bf5020d0d32..b87ba23442d2 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
| @@ -175,7 +175,7 @@ config SA1100_WATCHDOG | |||
| 175 | 175 | ||
| 176 | config MPCORE_WATCHDOG | 176 | config MPCORE_WATCHDOG |
| 177 | tristate "MPcore watchdog" | 177 | tristate "MPcore watchdog" |
| 178 | depends on ARM_MPCORE_PLATFORM && LOCAL_TIMERS | 178 | depends on HAVE_ARM_TWD |
| 179 | help | 179 | help |
| 180 | Watchdog timer embedded into the MPcore system. | 180 | Watchdog timer embedded into the MPcore system. |
| 181 | 181 | ||
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 016c6a791cab..b8ec7aca3c8e 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c | |||
| @@ -31,8 +31,9 @@ | |||
| 31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
| 32 | #include <linux/uaccess.h> | 32 | #include <linux/uaccess.h> |
| 33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
| 34 | #include <linux/io.h> | ||
| 34 | 35 | ||
| 35 | #include <asm/hardware/arm_twd.h> | 36 | #include <asm/smp_twd.h> |
| 36 | 37 | ||
| 37 | struct mpcore_wdt { | 38 | struct mpcore_wdt { |
| 38 | unsigned long timer_alive; | 39 | unsigned long timer_alive; |
| @@ -44,7 +45,7 @@ struct mpcore_wdt { | |||
| 44 | }; | 45 | }; |
| 45 | 46 | ||
| 46 | static struct platform_device *mpcore_wdt_dev; | 47 | static struct platform_device *mpcore_wdt_dev; |
| 47 | extern unsigned int mpcore_timer_rate; | 48 | static DEFINE_SPINLOCK(wdt_lock); |
| 48 | 49 | ||
| 49 | #define TIMER_MARGIN 60 | 50 | #define TIMER_MARGIN 60 |
| 50 | static int mpcore_margin = TIMER_MARGIN; | 51 | static int mpcore_margin = TIMER_MARGIN; |
| @@ -94,13 +95,15 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg) | |||
| 94 | */ | 95 | */ |
| 95 | static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) | 96 | static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) |
| 96 | { | 97 | { |
| 97 | unsigned int count; | 98 | unsigned long count; |
| 98 | 99 | ||
| 100 | spin_lock(&wdt_lock); | ||
| 99 | /* Assume prescale is set to 256 */ | 101 | /* Assume prescale is set to 256 */ |
| 100 | count = (mpcore_timer_rate / 256) * mpcore_margin; | 102 | count = __raw_readl(wdt->base + TWD_WDOG_COUNTER); |
| 103 | count = (0xFFFFFFFFU - count) * (HZ / 5); | ||
| 104 | count = (count / 256) * mpcore_margin; | ||
| 101 | 105 | ||
| 102 | /* Reload the counter */ | 106 | /* Reload the counter */ |
| 103 | spin_lock(&wdt_lock); | ||
| 104 | writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); | 107 | writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); |
| 105 | wdt->perturb = wdt->perturb ? 0 : 1; | 108 | wdt->perturb = wdt->perturb ? 0 : 1; |
| 106 | spin_unlock(&wdt_lock); | 109 | spin_unlock(&wdt_lock); |
| @@ -119,7 +122,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) | |||
| 119 | { | 122 | { |
| 120 | dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); | 123 | dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); |
| 121 | 124 | ||
| 122 | spin_lock(&wdt_lock); | ||
| 123 | /* This loads the count register but does NOT start the count yet */ | 125 | /* This loads the count register but does NOT start the count yet */ |
| 124 | mpcore_wdt_keepalive(wdt); | 126 | mpcore_wdt_keepalive(wdt); |
| 125 | 127 | ||
| @@ -130,7 +132,6 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) | |||
| 130 | /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ | 132 | /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ |
| 131 | writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); | 133 | writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); |
| 132 | } | 134 | } |
| 133 | spin_unlock(&wdt_lock); | ||
| 134 | } | 135 | } |
| 135 | 136 | ||
| 136 | static int mpcore_wdt_set_heartbeat(int t) | 137 | static int mpcore_wdt_set_heartbeat(int t) |
| @@ -360,7 +361,7 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) | |||
| 360 | mpcore_wdt_miscdev.parent = &dev->dev; | 361 | mpcore_wdt_miscdev.parent = &dev->dev; |
| 361 | ret = misc_register(&mpcore_wdt_miscdev); | 362 | ret = misc_register(&mpcore_wdt_miscdev); |
| 362 | if (ret) { | 363 | if (ret) { |
| 363 | dev_printk(KERN_ERR, _dev, | 364 | dev_printk(KERN_ERR, wdt->dev, |
| 364 | "cannot register miscdev on minor=%d (err=%d)\n", | 365 | "cannot register miscdev on minor=%d (err=%d)\n", |
| 365 | WATCHDOG_MINOR, ret); | 366 | WATCHDOG_MINOR, ret); |
| 366 | goto err_misc; | 367 | goto err_misc; |
| @@ -369,13 +370,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) | |||
| 369 | ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, | 370 | ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, |
| 370 | "mpcore_wdt", wdt); | 371 | "mpcore_wdt", wdt); |
| 371 | if (ret) { | 372 | if (ret) { |
| 372 | dev_printk(KERN_ERR, _dev, | 373 | dev_printk(KERN_ERR, wdt->dev, |
| 373 | "cannot register IRQ%d for watchdog\n", wdt->irq); | 374 | "cannot register IRQ%d for watchdog\n", wdt->irq); |
| 374 | goto err_irq; | 375 | goto err_irq; |
| 375 | } | 376 | } |
| 376 | 377 | ||
| 377 | mpcore_wdt_stop(wdt); | 378 | mpcore_wdt_stop(wdt); |
| 378 | platform_set_drvdata(&dev->dev, wdt); | 379 | platform_set_drvdata(dev, wdt); |
| 379 | mpcore_wdt_dev = dev; | 380 | mpcore_wdt_dev = dev; |
| 380 | 381 | ||
| 381 | return 0; | 382 | return 0; |
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 2ac4440e7b08..8943b8ccee1a 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -80,12 +80,6 @@ static void do_suspend(void) | |||
| 80 | 80 | ||
| 81 | shutting_down = SHUTDOWN_SUSPEND; | 81 | shutting_down = SHUTDOWN_SUSPEND; |
| 82 | 82 | ||
| 83 | err = stop_machine_create(); | ||
| 84 | if (err) { | ||
| 85 | printk(KERN_ERR "xen suspend: failed to setup stop_machine %d\n", err); | ||
| 86 | goto out; | ||
| 87 | } | ||
| 88 | |||
| 89 | #ifdef CONFIG_PREEMPT | 83 | #ifdef CONFIG_PREEMPT |
| 90 | /* If the kernel is preemptible, we need to freeze all the processes | 84 | /* If the kernel is preemptible, we need to freeze all the processes |
| 91 | to prevent them from being in the middle of a pagetable update | 85 | to prevent them from being in the middle of a pagetable update |
| @@ -93,7 +87,7 @@ static void do_suspend(void) | |||
| 93 | err = freeze_processes(); | 87 | err = freeze_processes(); |
| 94 | if (err) { | 88 | if (err) { |
| 95 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); | 89 | printk(KERN_ERR "xen suspend: freeze failed %d\n", err); |
| 96 | goto out_destroy_sm; | 90 | goto out; |
| 97 | } | 91 | } |
| 98 | #endif | 92 | #endif |
| 99 | 93 | ||
| @@ -136,12 +130,8 @@ out_resume: | |||
| 136 | out_thaw: | 130 | out_thaw: |
| 137 | #ifdef CONFIG_PREEMPT | 131 | #ifdef CONFIG_PREEMPT |
| 138 | thaw_processes(); | 132 | thaw_processes(); |
| 139 | |||
| 140 | out_destroy_sm: | ||
| 141 | #endif | ||
| 142 | stop_machine_destroy(); | ||
| 143 | |||
| 144 | out: | 133 | out: |
| 134 | #endif | ||
| 145 | shutting_down = SHUTDOWN_INVALID; | 135 | shutting_down = SHUTDOWN_INVALID; |
| 146 | } | 136 | } |
| 147 | #endif /* CONFIG_PM_SLEEP */ | 137 | #endif /* CONFIG_PM_SLEEP */ |
diff --git a/drivers/zorro/proc.c b/drivers/zorro/proc.c index d47c47fc048f..3c7046d79654 100644 --- a/drivers/zorro/proc.c +++ b/drivers/zorro/proc.c | |||
| @@ -97,7 +97,7 @@ static void zorro_seq_stop(struct seq_file *m, void *v) | |||
| 97 | 97 | ||
| 98 | static int zorro_seq_show(struct seq_file *m, void *v) | 98 | static int zorro_seq_show(struct seq_file *m, void *v) |
| 99 | { | 99 | { |
| 100 | u_int slot = *(loff_t *)v; | 100 | unsigned int slot = *(loff_t *)v; |
| 101 | struct zorro_dev *z = &zorro_autocon[slot]; | 101 | struct zorro_dev *z = &zorro_autocon[slot]; |
| 102 | 102 | ||
| 103 | seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id, | 103 | seq_printf(m, "%02x\t%08x\t%08lx\t%08lx\t%02x\n", slot, z->id, |
| @@ -129,7 +129,7 @@ static const struct file_operations zorro_devices_proc_fops = { | |||
| 129 | 129 | ||
| 130 | static struct proc_dir_entry *proc_bus_zorro_dir; | 130 | static struct proc_dir_entry *proc_bus_zorro_dir; |
| 131 | 131 | ||
| 132 | static int __init zorro_proc_attach_device(u_int slot) | 132 | static int __init zorro_proc_attach_device(unsigned int slot) |
| 133 | { | 133 | { |
| 134 | struct proc_dir_entry *entry; | 134 | struct proc_dir_entry *entry; |
| 135 | char name[4]; | 135 | char name[4]; |
| @@ -146,7 +146,7 @@ static int __init zorro_proc_attach_device(u_int slot) | |||
| 146 | 146 | ||
| 147 | static int __init zorro_proc_init(void) | 147 | static int __init zorro_proc_init(void) |
| 148 | { | 148 | { |
| 149 | u_int slot; | 149 | unsigned int slot; |
| 150 | 150 | ||
| 151 | if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { | 151 | if (MACH_IS_AMIGA && AMIGAHW_PRESENT(ZORRO)) { |
| 152 | proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL); | 152 | proc_bus_zorro_dir = proc_mkdir("bus/zorro", NULL); |
diff --git a/drivers/zorro/zorro-driver.c b/drivers/zorro/zorro-driver.c index 53180a37cc9a..7ee2b6e71786 100644 --- a/drivers/zorro/zorro-driver.c +++ b/drivers/zorro/zorro-driver.c | |||
| @@ -137,10 +137,34 @@ static int zorro_bus_match(struct device *dev, struct device_driver *drv) | |||
| 137 | return 0; | 137 | return 0; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | static int zorro_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
| 141 | { | ||
| 142 | #ifdef CONFIG_HOTPLUG | ||
| 143 | struct zorro_dev *z; | ||
| 144 | |||
| 145 | if (!dev) | ||
| 146 | return -ENODEV; | ||
| 147 | |||
| 148 | z = to_zorro_dev(dev); | ||
| 149 | if (!z) | ||
| 150 | return -ENODEV; | ||
| 151 | |||
| 152 | if (add_uevent_var(env, "ZORRO_ID=%08X", z->id) || | ||
| 153 | add_uevent_var(env, "ZORRO_SLOT_NAME=%s", dev_name(dev)) || | ||
| 154 | add_uevent_var(env, "ZORRO_SLOT_ADDR=%04X", z->slotaddr) || | ||
| 155 | add_uevent_var(env, "MODALIAS=" ZORRO_DEVICE_MODALIAS_FMT, z->id)) | ||
| 156 | return -ENOMEM; | ||
| 157 | |||
| 158 | return 0; | ||
| 159 | #else /* !CONFIG_HOTPLUG */ | ||
| 160 | return -ENODEV; | ||
| 161 | #endif /* !CONFIG_HOTPLUG */ | ||
| 162 | } | ||
| 140 | 163 | ||
| 141 | struct bus_type zorro_bus_type = { | 164 | struct bus_type zorro_bus_type = { |
| 142 | .name = "zorro", | 165 | .name = "zorro", |
| 143 | .match = zorro_bus_match, | 166 | .match = zorro_bus_match, |
| 167 | .uevent = zorro_uevent, | ||
| 144 | .probe = zorro_device_probe, | 168 | .probe = zorro_device_probe, |
| 145 | .remove = zorro_device_remove, | 169 | .remove = zorro_device_remove, |
| 146 | }; | 170 | }; |
diff --git a/drivers/zorro/zorro-sysfs.c b/drivers/zorro/zorro-sysfs.c index 1d2a772ea14c..eb924e0a64ce 100644 --- a/drivers/zorro/zorro-sysfs.c +++ b/drivers/zorro/zorro-sysfs.c | |||
| @@ -77,6 +77,16 @@ static struct bin_attribute zorro_config_attr = { | |||
| 77 | .read = zorro_read_config, | 77 | .read = zorro_read_config, |
| 78 | }; | 78 | }; |
| 79 | 79 | ||
| 80 | static ssize_t modalias_show(struct device *dev, struct device_attribute *attr, | ||
| 81 | char *buf) | ||
| 82 | { | ||
| 83 | struct zorro_dev *z = to_zorro_dev(dev); | ||
| 84 | |||
| 85 | return sprintf(buf, ZORRO_DEVICE_MODALIAS_FMT "\n", z->id); | ||
| 86 | } | ||
| 87 | |||
| 88 | static DEVICE_ATTR(modalias, S_IRUGO, modalias_show, NULL); | ||
| 89 | |||
| 80 | int zorro_create_sysfs_dev_files(struct zorro_dev *z) | 90 | int zorro_create_sysfs_dev_files(struct zorro_dev *z) |
| 81 | { | 91 | { |
| 82 | struct device *dev = &z->dev; | 92 | struct device *dev = &z->dev; |
| @@ -89,6 +99,7 @@ int zorro_create_sysfs_dev_files(struct zorro_dev *z) | |||
| 89 | (error = device_create_file(dev, &dev_attr_slotaddr)) || | 99 | (error = device_create_file(dev, &dev_attr_slotaddr)) || |
| 90 | (error = device_create_file(dev, &dev_attr_slotsize)) || | 100 | (error = device_create_file(dev, &dev_attr_slotsize)) || |
| 91 | (error = device_create_file(dev, &dev_attr_resource)) || | 101 | (error = device_create_file(dev, &dev_attr_resource)) || |
| 102 | (error = device_create_file(dev, &dev_attr_modalias)) || | ||
| 92 | (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr))) | 103 | (error = sysfs_create_bin_file(&dev->kobj, &zorro_config_attr))) |
| 93 | return error; | 104 | return error; |
| 94 | 105 | ||
diff --git a/drivers/zorro/zorro.c b/drivers/zorro/zorro.c index d45fb34e2d23..6455f3a244c5 100644 --- a/drivers/zorro/zorro.c +++ b/drivers/zorro/zorro.c | |||
| @@ -15,6 +15,8 @@ | |||
| 15 | #include <linux/zorro.h> | 15 | #include <linux/zorro.h> |
| 16 | #include <linux/bitops.h> | 16 | #include <linux/bitops.h> |
| 17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
| 18 | #include <linux/platform_device.h> | ||
| 19 | #include <linux/slab.h> | ||
| 18 | 20 | ||
| 19 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
| 20 | #include <asm/amigahw.h> | 22 | #include <asm/amigahw.h> |
| @@ -26,24 +28,17 @@ | |||
| 26 | * Zorro Expansion Devices | 28 | * Zorro Expansion Devices |
| 27 | */ | 29 | */ |
| 28 | 30 | ||
| 29 | u_int zorro_num_autocon = 0; | 31 | unsigned int zorro_num_autocon; |
| 30 | struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; | 32 | struct zorro_dev zorro_autocon[ZORRO_NUM_AUTO]; |
| 31 | 33 | ||
| 32 | 34 | ||
| 33 | /* | 35 | /* |
| 34 | * Single Zorro bus | 36 | * Zorro bus |
| 35 | */ | 37 | */ |
| 36 | 38 | ||
| 37 | struct zorro_bus zorro_bus = {\ | 39 | struct zorro_bus { |
| 38 | .resources = { | 40 | struct list_head devices; /* list of devices on this bus */ |
| 39 | /* Zorro II regions (on Zorro II/III) */ | 41 | struct device dev; |
| 40 | { .name = "Zorro II exp", .start = 0x00e80000, .end = 0x00efffff }, | ||
| 41 | { .name = "Zorro II mem", .start = 0x00200000, .end = 0x009fffff }, | ||
| 42 | /* Zorro III regions (on Zorro III only) */ | ||
| 43 | { .name = "Zorro III exp", .start = 0xff000000, .end = 0xffffffff }, | ||
| 44 | { .name = "Zorro III cfg", .start = 0x40000000, .end = 0x7fffffff } | ||
| 45 | }, | ||
| 46 | .name = "Zorro bus" | ||
| 47 | }; | 42 | }; |
| 48 | 43 | ||
| 49 | 44 | ||
| @@ -53,18 +48,19 @@ struct zorro_bus zorro_bus = {\ | |||
| 53 | 48 | ||
| 54 | struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) | 49 | struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) |
| 55 | { | 50 | { |
| 56 | struct zorro_dev *z; | 51 | struct zorro_dev *z; |
| 57 | 52 | ||
| 58 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) | 53 | if (!zorro_num_autocon) |
| 59 | return NULL; | 54 | return NULL; |
| 60 | 55 | ||
| 61 | for (z = from ? from+1 : &zorro_autocon[0]; | 56 | for (z = from ? from+1 : &zorro_autocon[0]; |
| 62 | z < zorro_autocon+zorro_num_autocon; | 57 | z < zorro_autocon+zorro_num_autocon; |
| 63 | z++) | 58 | z++) |
| 64 | if (id == ZORRO_WILDCARD || id == z->id) | 59 | if (id == ZORRO_WILDCARD || id == z->id) |
| 65 | return z; | 60 | return z; |
| 66 | return NULL; | 61 | return NULL; |
| 67 | } | 62 | } |
| 63 | EXPORT_SYMBOL(zorro_find_device); | ||
| 68 | 64 | ||
| 69 | 65 | ||
| 70 | /* | 66 | /* |
| @@ -83,121 +79,138 @@ struct zorro_dev *zorro_find_device(zorro_id id, struct zorro_dev *from) | |||
| 83 | */ | 79 | */ |
| 84 | 80 | ||
| 85 | DECLARE_BITMAP(zorro_unused_z2ram, 128); | 81 | DECLARE_BITMAP(zorro_unused_z2ram, 128); |
| 82 | EXPORT_SYMBOL(zorro_unused_z2ram); | ||
| 86 | 83 | ||
| 87 | 84 | ||
| 88 | static void __init mark_region(unsigned long start, unsigned long end, | 85 | static void __init mark_region(unsigned long start, unsigned long end, |
| 89 | int flag) | 86 | int flag) |
| 90 | { | 87 | { |
| 91 | if (flag) | ||
| 92 | start += Z2RAM_CHUNKMASK; | ||
| 93 | else | ||
| 94 | end += Z2RAM_CHUNKMASK; | ||
| 95 | start &= ~Z2RAM_CHUNKMASK; | ||
| 96 | end &= ~Z2RAM_CHUNKMASK; | ||
| 97 | |||
| 98 | if (end <= Z2RAM_START || start >= Z2RAM_END) | ||
| 99 | return; | ||
| 100 | start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; | ||
| 101 | end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; | ||
| 102 | while (start < end) { | ||
| 103 | u32 chunk = start>>Z2RAM_CHUNKSHIFT; | ||
| 104 | if (flag) | 88 | if (flag) |
| 105 | set_bit(chunk, zorro_unused_z2ram); | 89 | start += Z2RAM_CHUNKMASK; |
| 106 | else | 90 | else |
| 107 | clear_bit(chunk, zorro_unused_z2ram); | 91 | end += Z2RAM_CHUNKMASK; |
| 108 | start += Z2RAM_CHUNKSIZE; | 92 | start &= ~Z2RAM_CHUNKMASK; |
| 109 | } | 93 | end &= ~Z2RAM_CHUNKMASK; |
| 94 | |||
| 95 | if (end <= Z2RAM_START || start >= Z2RAM_END) | ||
| 96 | return; | ||
| 97 | start = start < Z2RAM_START ? 0x00000000 : start-Z2RAM_START; | ||
| 98 | end = end > Z2RAM_END ? Z2RAM_SIZE : end-Z2RAM_START; | ||
| 99 | while (start < end) { | ||
| 100 | u32 chunk = start>>Z2RAM_CHUNKSHIFT; | ||
| 101 | if (flag) | ||
| 102 | set_bit(chunk, zorro_unused_z2ram); | ||
| 103 | else | ||
| 104 | clear_bit(chunk, zorro_unused_z2ram); | ||
| 105 | start += Z2RAM_CHUNKSIZE; | ||
| 106 | } | ||
| 110 | } | 107 | } |
| 111 | 108 | ||
| 112 | 109 | ||
| 113 | static struct resource __init *zorro_find_parent_resource(struct zorro_dev *z) | 110 | static struct resource __init *zorro_find_parent_resource( |
| 111 | struct platform_device *bridge, struct zorro_dev *z) | ||
| 114 | { | 112 | { |
| 115 | int i; | 113 | int i; |
| 116 | 114 | ||
| 117 | for (i = 0; i < zorro_bus.num_resources; i++) | 115 | for (i = 0; i < bridge->num_resources; i++) { |
| 118 | if (zorro_resource_start(z) >= zorro_bus.resources[i].start && | 116 | struct resource *r = &bridge->resource[i]; |
| 119 | zorro_resource_end(z) <= zorro_bus.resources[i].end) | 117 | if (zorro_resource_start(z) >= r->start && |
| 120 | return &zorro_bus.resources[i]; | 118 | zorro_resource_end(z) <= r->end) |
| 121 | return &iomem_resource; | 119 | return r; |
| 120 | } | ||
| 121 | return &iomem_resource; | ||
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | 124 | ||
| 125 | /* | ||
| 126 | * Initialization | ||
| 127 | */ | ||
| 128 | 125 | ||
| 129 | static int __init zorro_init(void) | 126 | static int __init amiga_zorro_probe(struct platform_device *pdev) |
| 130 | { | 127 | { |
| 131 | struct zorro_dev *z; | 128 | struct zorro_bus *bus; |
| 132 | unsigned int i; | 129 | struct zorro_dev *z; |
| 133 | int error; | 130 | struct resource *r; |
| 134 | 131 | unsigned int i; | |
| 135 | if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(ZORRO)) | 132 | int error; |
| 136 | return 0; | 133 | |
| 137 | 134 | /* Initialize the Zorro bus */ | |
| 138 | pr_info("Zorro: Probing AutoConfig expansion devices: %d device%s\n", | 135 | bus = kzalloc(sizeof(*bus), GFP_KERNEL); |
| 139 | zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); | 136 | if (!bus) |
| 140 | 137 | return -ENOMEM; | |
| 141 | /* Initialize the Zorro bus */ | 138 | |
| 142 | INIT_LIST_HEAD(&zorro_bus.devices); | 139 | INIT_LIST_HEAD(&bus->devices); |
| 143 | dev_set_name(&zorro_bus.dev, "zorro"); | 140 | bus->dev.parent = &pdev->dev; |
| 144 | error = device_register(&zorro_bus.dev); | 141 | dev_set_name(&bus->dev, "zorro"); |
| 145 | if (error) { | 142 | error = device_register(&bus->dev); |
| 146 | pr_err("Zorro: Error registering zorro_bus\n"); | ||
| 147 | return error; | ||
| 148 | } | ||
| 149 | |||
| 150 | /* Request the resources */ | ||
| 151 | zorro_bus.num_resources = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2; | ||
| 152 | for (i = 0; i < zorro_bus.num_resources; i++) | ||
| 153 | request_resource(&iomem_resource, &zorro_bus.resources[i]); | ||
| 154 | |||
| 155 | /* Register all devices */ | ||
| 156 | for (i = 0; i < zorro_num_autocon; i++) { | ||
| 157 | z = &zorro_autocon[i]; | ||
| 158 | z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); | ||
| 159 | if (z->id == ZORRO_PROD_GVP_EPC_BASE) { | ||
| 160 | /* GVP quirk */ | ||
| 161 | unsigned long magic = zorro_resource_start(z)+0x8000; | ||
| 162 | z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; | ||
| 163 | } | ||
| 164 | sprintf(z->name, "Zorro device %08x", z->id); | ||
| 165 | zorro_name_device(z); | ||
| 166 | z->resource.name = z->name; | ||
| 167 | if (request_resource(zorro_find_parent_resource(z), &z->resource)) | ||
| 168 | pr_err("Zorro: Address space collision on device %s %pR\n", | ||
| 169 | z->name, &z->resource); | ||
| 170 | dev_set_name(&z->dev, "%02x", i); | ||
| 171 | z->dev.parent = &zorro_bus.dev; | ||
| 172 | z->dev.bus = &zorro_bus_type; | ||
| 173 | error = device_register(&z->dev); | ||
| 174 | if (error) { | 143 | if (error) { |
| 175 | pr_err("Zorro: Error registering device %s\n", z->name); | 144 | pr_err("Zorro: Error registering zorro_bus\n"); |
| 176 | continue; | 145 | kfree(bus); |
| 146 | return error; | ||
| 177 | } | 147 | } |
| 178 | error = zorro_create_sysfs_dev_files(z); | 148 | platform_set_drvdata(pdev, bus); |
| 179 | if (error) | 149 | |
| 180 | dev_err(&z->dev, "Error creating sysfs files\n"); | 150 | /* Register all devices */ |
| 181 | } | 151 | pr_info("Zorro: Probing AutoConfig expansion devices: %u device%s\n", |
| 182 | 152 | zorro_num_autocon, zorro_num_autocon == 1 ? "" : "s"); | |
| 183 | /* Mark all available Zorro II memory */ | 153 | |
| 184 | zorro_for_each_dev(z) { | 154 | for (i = 0; i < zorro_num_autocon; i++) { |
| 185 | if (z->rom.er_Type & ERTF_MEMLIST) | 155 | z = &zorro_autocon[i]; |
| 186 | mark_region(zorro_resource_start(z), zorro_resource_end(z)+1, 1); | 156 | z->id = (z->rom.er_Manufacturer<<16) | (z->rom.er_Product<<8); |
| 187 | } | 157 | if (z->id == ZORRO_PROD_GVP_EPC_BASE) { |
| 188 | 158 | /* GVP quirk */ | |
| 189 | /* Unmark all used Zorro II memory */ | 159 | unsigned long magic = zorro_resource_start(z)+0x8000; |
| 190 | for (i = 0; i < m68k_num_memory; i++) | 160 | z->id |= *(u16 *)ZTWO_VADDR(magic) & GVP_PRODMASK; |
| 191 | if (m68k_memory[i].addr < 16*1024*1024) | 161 | } |
| 192 | mark_region(m68k_memory[i].addr, | 162 | sprintf(z->name, "Zorro device %08x", z->id); |
| 193 | m68k_memory[i].addr+m68k_memory[i].size, 0); | 163 | zorro_name_device(z); |
| 194 | 164 | z->resource.name = z->name; | |
| 195 | return 0; | 165 | r = zorro_find_parent_resource(pdev, z); |
| 166 | error = request_resource(r, &z->resource); | ||
| 167 | if (error) | ||
| 168 | dev_err(&bus->dev, | ||
| 169 | "Address space collision on device %s %pR\n", | ||
| 170 | z->name, &z->resource); | ||
| 171 | dev_set_name(&z->dev, "%02x", i); | ||
| 172 | z->dev.parent = &bus->dev; | ||
| 173 | z->dev.bus = &zorro_bus_type; | ||
| 174 | error = device_register(&z->dev); | ||
| 175 | if (error) { | ||
| 176 | dev_err(&bus->dev, "Error registering device %s\n", | ||
| 177 | z->name); | ||
| 178 | continue; | ||
| 179 | } | ||
| 180 | error = zorro_create_sysfs_dev_files(z); | ||
| 181 | if (error) | ||
| 182 | dev_err(&z->dev, "Error creating sysfs files\n"); | ||
| 183 | } | ||
| 184 | |||
| 185 | /* Mark all available Zorro II memory */ | ||
| 186 | zorro_for_each_dev(z) { | ||
| 187 | if (z->rom.er_Type & ERTF_MEMLIST) | ||
| 188 | mark_region(zorro_resource_start(z), | ||
| 189 | zorro_resource_end(z)+1, 1); | ||
| 190 | } | ||
| 191 | |||
| 192 | /* Unmark all used Zorro II memory */ | ||
| 193 | for (i = 0; i < m68k_num_memory; i++) | ||
| 194 | if (m68k_memory[i].addr < 16*1024*1024) | ||
| 195 | mark_region(m68k_memory[i].addr, | ||
| 196 | m68k_memory[i].addr+m68k_memory[i].size, | ||
| 197 | 0); | ||
| 198 | |||
| 199 | return 0; | ||
| 196 | } | 200 | } |
| 197 | 201 | ||
| 198 | subsys_initcall(zorro_init); | 202 | static struct platform_driver amiga_zorro_driver = { |
| 203 | .driver = { | ||
| 204 | .name = "amiga-zorro", | ||
| 205 | .owner = THIS_MODULE, | ||
| 206 | }, | ||
| 207 | }; | ||
| 199 | 208 | ||
| 200 | EXPORT_SYMBOL(zorro_find_device); | 209 | static int __init amiga_zorro_init(void) |
| 201 | EXPORT_SYMBOL(zorro_unused_z2ram); | 210 | { |
| 211 | return platform_driver_probe(&amiga_zorro_driver, amiga_zorro_probe); | ||
| 212 | } | ||
| 213 | |||
| 214 | module_init(amiga_zorro_init); | ||
| 202 | 215 | ||
| 203 | MODULE_LICENSE("GPL"); | 216 | MODULE_LICENSE("GPL"); |
