diff options
Diffstat (limited to 'drivers')
561 files changed, 17693 insertions, 4572 deletions
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index 1e5d8a40101e..fefc2ca7cc3e 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c | |||
@@ -405,7 +405,7 @@ int apei_estatus_check(const struct acpi_hest_generic_status *estatus) | |||
405 | return rc; | 405 | return rc; |
406 | data_len = estatus->data_length; | 406 | data_len = estatus->data_length; |
407 | gdata = (struct acpi_hest_generic_data *)(estatus + 1); | 407 | gdata = (struct acpi_hest_generic_data *)(estatus + 1); |
408 | while (data_len > sizeof(*gdata)) { | 408 | while (data_len >= sizeof(*gdata)) { |
409 | gedata_len = gdata->error_data_length; | 409 | gedata_len = gdata->error_data_length; |
410 | if (gedata_len > data_len - sizeof(*gdata)) | 410 | if (gedata_len > data_len - sizeof(*gdata)) |
411 | return -EINVAL; | 411 | return -EINVAL; |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index ef6f155469b5..40a84cc6740c 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -36,12 +36,11 @@ int register_acpi_bus_type(struct acpi_bus_type *type) | |||
36 | { | 36 | { |
37 | if (acpi_disabled) | 37 | if (acpi_disabled) |
38 | return -ENODEV; | 38 | return -ENODEV; |
39 | if (type && type->bus && type->find_device) { | 39 | if (type && type->match && type->find_device) { |
40 | down_write(&bus_type_sem); | 40 | down_write(&bus_type_sem); |
41 | list_add_tail(&type->list, &bus_type_list); | 41 | list_add_tail(&type->list, &bus_type_list); |
42 | up_write(&bus_type_sem); | 42 | up_write(&bus_type_sem); |
43 | printk(KERN_INFO PREFIX "bus type %s registered\n", | 43 | printk(KERN_INFO PREFIX "bus type %s registered\n", type->name); |
44 | type->bus->name); | ||
45 | return 0; | 44 | return 0; |
46 | } | 45 | } |
47 | return -ENODEV; | 46 | return -ENODEV; |
@@ -56,24 +55,21 @@ int unregister_acpi_bus_type(struct acpi_bus_type *type) | |||
56 | down_write(&bus_type_sem); | 55 | down_write(&bus_type_sem); |
57 | list_del_init(&type->list); | 56 | list_del_init(&type->list); |
58 | up_write(&bus_type_sem); | 57 | up_write(&bus_type_sem); |
59 | printk(KERN_INFO PREFIX "ACPI bus type %s unregistered\n", | 58 | printk(KERN_INFO PREFIX "bus type %s unregistered\n", |
60 | type->bus->name); | 59 | type->name); |
61 | return 0; | 60 | return 0; |
62 | } | 61 | } |
63 | return -ENODEV; | 62 | return -ENODEV; |
64 | } | 63 | } |
65 | EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); | 64 | EXPORT_SYMBOL_GPL(unregister_acpi_bus_type); |
66 | 65 | ||
67 | static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) | 66 | static struct acpi_bus_type *acpi_get_bus_type(struct device *dev) |
68 | { | 67 | { |
69 | struct acpi_bus_type *tmp, *ret = NULL; | 68 | struct acpi_bus_type *tmp, *ret = NULL; |
70 | 69 | ||
71 | if (!type) | ||
72 | return NULL; | ||
73 | |||
74 | down_read(&bus_type_sem); | 70 | down_read(&bus_type_sem); |
75 | list_for_each_entry(tmp, &bus_type_list, list) { | 71 | list_for_each_entry(tmp, &bus_type_list, list) { |
76 | if (tmp->bus == type) { | 72 | if (tmp->match(dev)) { |
77 | ret = tmp; | 73 | ret = tmp; |
78 | break; | 74 | break; |
79 | } | 75 | } |
@@ -82,22 +78,6 @@ static struct acpi_bus_type *acpi_get_bus_type(struct bus_type *type) | |||
82 | return ret; | 78 | return ret; |
83 | } | 79 | } |
84 | 80 | ||
85 | static int acpi_find_bridge_device(struct device *dev, acpi_handle * handle) | ||
86 | { | ||
87 | struct acpi_bus_type *tmp; | ||
88 | int ret = -ENODEV; | ||
89 | |||
90 | down_read(&bus_type_sem); | ||
91 | list_for_each_entry(tmp, &bus_type_list, list) { | ||
92 | if (tmp->find_bridge && !tmp->find_bridge(dev, handle)) { | ||
93 | ret = 0; | ||
94 | break; | ||
95 | } | ||
96 | } | ||
97 | up_read(&bus_type_sem); | ||
98 | return ret; | ||
99 | } | ||
100 | |||
101 | static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, | 81 | static acpi_status do_acpi_find_child(acpi_handle handle, u32 lvl_not_used, |
102 | void *addr_p, void **ret_p) | 82 | void *addr_p, void **ret_p) |
103 | { | 83 | { |
@@ -261,29 +241,12 @@ err: | |||
261 | 241 | ||
262 | static int acpi_platform_notify(struct device *dev) | 242 | static int acpi_platform_notify(struct device *dev) |
263 | { | 243 | { |
264 | struct acpi_bus_type *type; | 244 | struct acpi_bus_type *type = acpi_get_bus_type(dev); |
265 | acpi_handle handle; | 245 | acpi_handle handle; |
266 | int ret; | 246 | int ret; |
267 | 247 | ||
268 | ret = acpi_bind_one(dev, NULL); | 248 | ret = acpi_bind_one(dev, NULL); |
269 | if (ret && (!dev->bus || !dev->parent)) { | 249 | if (ret && type) { |
270 | /* bridge devices genernally haven't bus or parent */ | ||
271 | ret = acpi_find_bridge_device(dev, &handle); | ||
272 | if (!ret) { | ||
273 | ret = acpi_bind_one(dev, handle); | ||
274 | if (ret) | ||
275 | goto out; | ||
276 | } | ||
277 | } | ||
278 | |||
279 | type = acpi_get_bus_type(dev->bus); | ||
280 | if (ret) { | ||
281 | if (!type || !type->find_device) { | ||
282 | DBG("No ACPI bus support for %s\n", dev_name(dev)); | ||
283 | ret = -EINVAL; | ||
284 | goto out; | ||
285 | } | ||
286 | |||
287 | ret = type->find_device(dev, &handle); | 250 | ret = type->find_device(dev, &handle); |
288 | if (ret) { | 251 | if (ret) { |
289 | DBG("Unable to get handle for %s\n", dev_name(dev)); | 252 | DBG("Unable to get handle for %s\n", dev_name(dev)); |
@@ -316,7 +279,7 @@ static int acpi_platform_notify_remove(struct device *dev) | |||
316 | { | 279 | { |
317 | struct acpi_bus_type *type; | 280 | struct acpi_bus_type *type; |
318 | 281 | ||
319 | type = acpi_get_bus_type(dev->bus); | 282 | type = acpi_get_bus_type(dev); |
320 | if (type && type->cleanup) | 283 | if (type && type->cleanup) |
321 | type->cleanup(dev); | 284 | type->cleanup(dev); |
322 | 285 | ||
diff --git a/drivers/acpi/pci_root.c b/drivers/acpi/pci_root.c index 0ac546d5e53f..5ff173066127 100644 --- a/drivers/acpi/pci_root.c +++ b/drivers/acpi/pci_root.c | |||
@@ -646,6 +646,7 @@ static void handle_root_bridge_insertion(acpi_handle handle) | |||
646 | 646 | ||
647 | static void handle_root_bridge_removal(struct acpi_device *device) | 647 | static void handle_root_bridge_removal(struct acpi_device *device) |
648 | { | 648 | { |
649 | acpi_status status; | ||
649 | struct acpi_eject_event *ej_event; | 650 | struct acpi_eject_event *ej_event; |
650 | 651 | ||
651 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); | 652 | ej_event = kmalloc(sizeof(*ej_event), GFP_KERNEL); |
@@ -661,7 +662,9 @@ static void handle_root_bridge_removal(struct acpi_device *device) | |||
661 | ej_event->device = device; | 662 | ej_event->device = device; |
662 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; | 663 | ej_event->event = ACPI_NOTIFY_EJECT_REQUEST; |
663 | 664 | ||
664 | acpi_bus_hot_remove_device(ej_event); | 665 | status = acpi_os_hotplug_execute(acpi_bus_hot_remove_device, ej_event); |
666 | if (ACPI_FAILURE(status)) | ||
667 | kfree(ej_event); | ||
665 | } | 668 | } |
666 | 669 | ||
667 | static void _handle_hotplug_event_root(struct work_struct *work) | 670 | static void _handle_hotplug_event_root(struct work_struct *work) |
@@ -676,8 +679,9 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
676 | handle = hp_work->handle; | 679 | handle = hp_work->handle; |
677 | type = hp_work->type; | 680 | type = hp_work->type; |
678 | 681 | ||
679 | root = acpi_pci_find_root(handle); | 682 | acpi_scan_lock_acquire(); |
680 | 683 | ||
684 | root = acpi_pci_find_root(handle); | ||
681 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); | 685 | acpi_get_name(handle, ACPI_FULL_PATHNAME, &buffer); |
682 | 686 | ||
683 | switch (type) { | 687 | switch (type) { |
@@ -711,6 +715,7 @@ static void _handle_hotplug_event_root(struct work_struct *work) | |||
711 | break; | 715 | break; |
712 | } | 716 | } |
713 | 717 | ||
718 | acpi_scan_lock_release(); | ||
714 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ | 719 | kfree(hp_work); /* allocated in handle_hotplug_event_bridge */ |
715 | kfree(buffer.pointer); | 720 | kfree(buffer.pointer); |
716 | } | 721 | } |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index eff722278ff5..164d49569aeb 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
@@ -158,8 +158,7 @@ static int map_mat_entry(acpi_handle handle, int type, u32 acpi_id) | |||
158 | } | 158 | } |
159 | 159 | ||
160 | exit: | 160 | exit: |
161 | if (buffer.pointer) | 161 | kfree(buffer.pointer); |
162 | kfree(buffer.pointer); | ||
163 | return apic_id; | 162 | return apic_id; |
164 | } | 163 | } |
165 | 164 | ||
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index df34bd04ae62..bec717ffd25f 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c | |||
@@ -559,7 +559,7 @@ static int __cpuinit acpi_processor_add(struct acpi_device *device) | |||
559 | return 0; | 559 | return 0; |
560 | #endif | 560 | #endif |
561 | 561 | ||
562 | BUG_ON((pr->id >= nr_cpu_ids) || (pr->id < 0)); | 562 | BUG_ON(pr->id >= nr_cpu_ids); |
563 | 563 | ||
564 | /* | 564 | /* |
565 | * Buggy BIOS check | 565 | * Buggy BIOS check |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 53e7ac9403a7..e854582f29a6 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -465,7 +465,7 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) | |||
465 | return result; | 465 | return result; |
466 | } | 466 | } |
467 | 467 | ||
468 | static int acpi_processor_get_performance_info(struct acpi_processor *pr) | 468 | int acpi_processor_get_performance_info(struct acpi_processor *pr) |
469 | { | 469 | { |
470 | int result = 0; | 470 | int result = 0; |
471 | acpi_status status = AE_OK; | 471 | acpi_status status = AE_OK; |
@@ -509,7 +509,7 @@ static int acpi_processor_get_performance_info(struct acpi_processor *pr) | |||
509 | #endif | 509 | #endif |
510 | return result; | 510 | return result; |
511 | } | 511 | } |
512 | 512 | EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info); | |
513 | int acpi_processor_notify_smm(struct module *calling_module) | 513 | int acpi_processor_notify_smm(struct module *calling_module) |
514 | { | 514 | { |
515 | acpi_status status; | 515 | acpi_status status; |
diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 6d3a06a629a1..9c1a435d10e6 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c | |||
@@ -193,6 +193,14 @@ static struct dmi_system_id __initdata acpisleep_dmi_table[] = { | |||
193 | }, | 193 | }, |
194 | { | 194 | { |
195 | .callback = init_nvs_nosave, | 195 | .callback = init_nvs_nosave, |
196 | .ident = "Sony Vaio VGN-FW21M", | ||
197 | .matches = { | ||
198 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | ||
199 | DMI_MATCH(DMI_PRODUCT_NAME, "VGN-FW21M"), | ||
200 | }, | ||
201 | }, | ||
202 | { | ||
203 | .callback = init_nvs_nosave, | ||
196 | .ident = "Sony Vaio VPCEB17FX", | 204 | .ident = "Sony Vaio VPCEB17FX", |
197 | .matches = { | 205 | .matches = { |
198 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), | 206 | DMI_MATCH(DMI_SYS_VENDOR, "Sony Corporation"), |
@@ -599,7 +607,6 @@ static void acpi_sleep_suspend_setup(void) | |||
599 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); | 607 | status = acpi_get_sleep_type_data(i, &type_a, &type_b); |
600 | if (ACPI_SUCCESS(status)) { | 608 | if (ACPI_SUCCESS(status)) { |
601 | sleep_states[i] = 1; | 609 | sleep_states[i] = 1; |
602 | pr_cont(" S%d", i); | ||
603 | } | 610 | } |
604 | } | 611 | } |
605 | 612 | ||
@@ -742,7 +749,6 @@ static void acpi_sleep_hibernate_setup(void) | |||
742 | hibernation_set_ops(old_suspend_ordering ? | 749 | hibernation_set_ops(old_suspend_ordering ? |
743 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); | 750 | &acpi_hibernation_ops_old : &acpi_hibernation_ops); |
744 | sleep_states[ACPI_STATE_S4] = 1; | 751 | sleep_states[ACPI_STATE_S4] = 1; |
745 | pr_cont(KERN_CONT " S4"); | ||
746 | if (nosigcheck) | 752 | if (nosigcheck) |
747 | return; | 753 | return; |
748 | 754 | ||
@@ -788,6 +794,9 @@ int __init acpi_sleep_init(void) | |||
788 | { | 794 | { |
789 | acpi_status status; | 795 | acpi_status status; |
790 | u8 type_a, type_b; | 796 | u8 type_a, type_b; |
797 | char supported[ACPI_S_STATE_COUNT * 3 + 1]; | ||
798 | char *pos = supported; | ||
799 | int i; | ||
791 | 800 | ||
792 | if (acpi_disabled) | 801 | if (acpi_disabled) |
793 | return 0; | 802 | return 0; |
@@ -795,7 +804,6 @@ int __init acpi_sleep_init(void) | |||
795 | acpi_sleep_dmi_check(); | 804 | acpi_sleep_dmi_check(); |
796 | 805 | ||
797 | sleep_states[ACPI_STATE_S0] = 1; | 806 | sleep_states[ACPI_STATE_S0] = 1; |
798 | pr_info(PREFIX "(supports S0"); | ||
799 | 807 | ||
800 | acpi_sleep_suspend_setup(); | 808 | acpi_sleep_suspend_setup(); |
801 | acpi_sleep_hibernate_setup(); | 809 | acpi_sleep_hibernate_setup(); |
@@ -803,11 +811,17 @@ int __init acpi_sleep_init(void) | |||
803 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); | 811 | status = acpi_get_sleep_type_data(ACPI_STATE_S5, &type_a, &type_b); |
804 | if (ACPI_SUCCESS(status)) { | 812 | if (ACPI_SUCCESS(status)) { |
805 | sleep_states[ACPI_STATE_S5] = 1; | 813 | sleep_states[ACPI_STATE_S5] = 1; |
806 | pr_cont(" S5"); | ||
807 | pm_power_off_prepare = acpi_power_off_prepare; | 814 | pm_power_off_prepare = acpi_power_off_prepare; |
808 | pm_power_off = acpi_power_off; | 815 | pm_power_off = acpi_power_off; |
809 | } | 816 | } |
810 | pr_cont(")\n"); | 817 | |
818 | supported[0] = 0; | ||
819 | for (i = 0; i < ACPI_S_STATE_COUNT; i++) { | ||
820 | if (sleep_states[i]) | ||
821 | pos += sprintf(pos, " S%d", i); | ||
822 | } | ||
823 | pr_info(PREFIX "(supports%s)\n", supported); | ||
824 | |||
811 | /* | 825 | /* |
812 | * Register the tts_notifier to reboot notifier list so that the _TTS | 826 | * Register the tts_notifier to reboot notifier list so that the _TTS |
813 | * object can also be evaluated when the system enters S5. | 827 | * object can also be evaluated when the system enters S5. |
diff --git a/drivers/amba/tegra-ahb.c b/drivers/amba/tegra-ahb.c index 093c43554963..1f44e56cc65d 100644 --- a/drivers/amba/tegra-ahb.c +++ b/drivers/amba/tegra-ahb.c | |||
@@ -158,7 +158,7 @@ int tegra_ahb_enable_smmu(struct device_node *dn) | |||
158 | EXPORT_SYMBOL(tegra_ahb_enable_smmu); | 158 | EXPORT_SYMBOL(tegra_ahb_enable_smmu); |
159 | #endif | 159 | #endif |
160 | 160 | ||
161 | #ifdef CONFIG_PM_SLEEP | 161 | #ifdef CONFIG_PM |
162 | static int tegra_ahb_suspend(struct device *dev) | 162 | static int tegra_ahb_suspend(struct device *dev) |
163 | { | 163 | { |
164 | int i; | 164 | int i; |
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index 3e751b74615e..a5a3ebcbdd2c 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -59,15 +59,16 @@ config ATA_ACPI | |||
59 | option libata.noacpi=1 | 59 | option libata.noacpi=1 |
60 | 60 | ||
61 | config SATA_ZPODD | 61 | config SATA_ZPODD |
62 | bool "SATA Zero Power ODD Support" | 62 | bool "SATA Zero Power Optical Disc Drive (ZPODD) support" |
63 | depends on ATA_ACPI | 63 | depends on ATA_ACPI |
64 | default n | 64 | default n |
65 | help | 65 | help |
66 | This option adds support for SATA ZPODD. It requires both | 66 | This option adds support for SATA Zero Power Optical Disc |
67 | ODD and the platform support, and if enabled, will automatically | 67 | Drive (ZPODD). It requires both the ODD and the platform |
68 | power on/off the ODD when certain condition is satisfied. This | 68 | support, and if enabled, will automatically power on/off the |
69 | does not impact user's experience of the ODD, only power is saved | 69 | ODD when certain condition is satisfied. This does not impact |
70 | when ODD is not in use(i.e. no disc inside). | 70 | end user's experience of the ODD, only power is saved when |
71 | the ODD is not in use (i.e. no disc inside). | ||
71 | 72 | ||
72 | If unsure, say N. | 73 | If unsure, say N. |
73 | 74 | ||
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index a99112cfd8b1..6a67b07de494 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -281,6 +281,8 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
281 | { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */ | 281 | { PCI_VDEVICE(INTEL, 0x1f37), board_ahci }, /* Avoton RAID */ |
282 | { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */ | 282 | { PCI_VDEVICE(INTEL, 0x1f3e), board_ahci }, /* Avoton RAID */ |
283 | { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */ | 283 | { PCI_VDEVICE(INTEL, 0x1f3f), board_ahci }, /* Avoton RAID */ |
284 | { PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Wellsburg RAID */ | ||
285 | { PCI_VDEVICE(INTEL, 0x2827), board_ahci }, /* Wellsburg RAID */ | ||
284 | { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ | 286 | { PCI_VDEVICE(INTEL, 0x8d02), board_ahci }, /* Wellsburg AHCI */ |
285 | { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ | 287 | { PCI_VDEVICE(INTEL, 0x8d04), board_ahci }, /* Wellsburg RAID */ |
286 | { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ | 288 | { PCI_VDEVICE(INTEL, 0x8d06), board_ahci }, /* Wellsburg RAID */ |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index d2ba439cfe54..ffdd32d22602 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
@@ -1547,6 +1547,10 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev) | |||
1547 | 1547 | ||
1548 | static int prefer_ms_hyperv = 1; | 1548 | static int prefer_ms_hyperv = 1; |
1549 | module_param(prefer_ms_hyperv, int, 0); | 1549 | module_param(prefer_ms_hyperv, int, 0); |
1550 | MODULE_PARM_DESC(prefer_ms_hyperv, | ||
1551 | "Prefer Hyper-V paravirtualization drivers instead of ATA, " | ||
1552 | "0 - Use ATA drivers, " | ||
1553 | "1 (Default) - Use the paravirtualization drivers."); | ||
1550 | 1554 | ||
1551 | static void piix_ignore_devices_quirk(struct ata_host *host) | 1555 | static void piix_ignore_devices_quirk(struct ata_host *host) |
1552 | { | 1556 | { |
diff --git a/drivers/ata/libata-acpi.c b/drivers/ata/libata-acpi.c index 0ea1018280bd..8a52dab412e2 100644 --- a/drivers/ata/libata-acpi.c +++ b/drivers/ata/libata-acpi.c | |||
@@ -1027,7 +1027,7 @@ static void ata_acpi_register_power_resource(struct ata_device *dev) | |||
1027 | 1027 | ||
1028 | handle = ata_dev_acpi_handle(dev); | 1028 | handle = ata_dev_acpi_handle(dev); |
1029 | if (handle) | 1029 | if (handle) |
1030 | acpi_dev_pm_remove_dependent(handle, &sdev->sdev_gendev); | 1030 | acpi_dev_pm_add_dependent(handle, &sdev->sdev_gendev); |
1031 | } | 1031 | } |
1032 | 1032 | ||
1033 | static void ata_acpi_unregister_power_resource(struct ata_device *dev) | 1033 | static void ata_acpi_unregister_power_resource(struct ata_device *dev) |
@@ -1144,13 +1144,8 @@ static int ata_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
1144 | return -ENODEV; | 1144 | return -ENODEV; |
1145 | } | 1145 | } |
1146 | 1146 | ||
1147 | static int ata_acpi_find_dummy(struct device *dev, acpi_handle *handle) | ||
1148 | { | ||
1149 | return -ENODEV; | ||
1150 | } | ||
1151 | |||
1152 | static struct acpi_bus_type ata_acpi_bus = { | 1147 | static struct acpi_bus_type ata_acpi_bus = { |
1153 | .find_bridge = ata_acpi_find_dummy, | 1148 | .name = "ATA", |
1154 | .find_device = ata_acpi_find_device, | 1149 | .find_device = ata_acpi_find_device, |
1155 | }; | 1150 | }; |
1156 | 1151 | ||
diff --git a/drivers/ata/pata_samsung_cf.c b/drivers/ata/pata_samsung_cf.c index 70b0e01372b3..6ef27e98c508 100644 --- a/drivers/ata/pata_samsung_cf.c +++ b/drivers/ata/pata_samsung_cf.c | |||
@@ -661,18 +661,7 @@ static struct platform_driver pata_s3c_driver = { | |||
661 | }, | 661 | }, |
662 | }; | 662 | }; |
663 | 663 | ||
664 | static int __init pata_s3c_init(void) | 664 | module_platform_driver_probe(pata_s3c_driver, pata_s3c_probe); |
665 | { | ||
666 | return platform_driver_probe(&pata_s3c_driver, pata_s3c_probe); | ||
667 | } | ||
668 | |||
669 | static void __exit pata_s3c_exit(void) | ||
670 | { | ||
671 | platform_driver_unregister(&pata_s3c_driver); | ||
672 | } | ||
673 | |||
674 | module_init(pata_s3c_init); | ||
675 | module_exit(pata_s3c_exit); | ||
676 | 665 | ||
677 | MODULE_AUTHOR("Abhilash Kesavan, <a.kesavan@samsung.com>"); | 666 | MODULE_AUTHOR("Abhilash Kesavan, <a.kesavan@samsung.com>"); |
678 | MODULE_DESCRIPTION("low-level driver for Samsung PATA controller"); | 667 | MODULE_DESCRIPTION("low-level driver for Samsung PATA controller"); |
diff --git a/drivers/ata/sata_fsl.c b/drivers/ata/sata_fsl.c index 124b2c1d9c0b..608f82fed632 100644 --- a/drivers/ata/sata_fsl.c +++ b/drivers/ata/sata_fsl.c | |||
@@ -1511,8 +1511,7 @@ error_exit_with_cleanup: | |||
1511 | 1511 | ||
1512 | if (hcr_base) | 1512 | if (hcr_base) |
1513 | iounmap(hcr_base); | 1513 | iounmap(hcr_base); |
1514 | if (host_priv) | 1514 | kfree(host_priv); |
1515 | kfree(host_priv); | ||
1516 | 1515 | ||
1517 | return retval; | 1516 | return retval; |
1518 | } | 1517 | } |
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 2b7f77d3fcb0..15beb500a4e4 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -99,7 +99,6 @@ void device_pm_add(struct device *dev) | |||
99 | dev_warn(dev, "parent %s should not be sleeping\n", | 99 | dev_warn(dev, "parent %s should not be sleeping\n", |
100 | dev_name(dev->parent)); | 100 | dev_name(dev->parent)); |
101 | list_add_tail(&dev->power.entry, &dpm_list); | 101 | list_add_tail(&dev->power.entry, &dpm_list); |
102 | dev_pm_qos_constraints_init(dev); | ||
103 | mutex_unlock(&dpm_list_mtx); | 102 | mutex_unlock(&dpm_list_mtx); |
104 | } | 103 | } |
105 | 104 | ||
@@ -113,7 +112,6 @@ void device_pm_remove(struct device *dev) | |||
113 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); | 112 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
114 | complete_all(&dev->power.completion); | 113 | complete_all(&dev->power.completion); |
115 | mutex_lock(&dpm_list_mtx); | 114 | mutex_lock(&dpm_list_mtx); |
116 | dev_pm_qos_constraints_destroy(dev); | ||
117 | list_del_init(&dev->power.entry); | 115 | list_del_init(&dev->power.entry); |
118 | mutex_unlock(&dpm_list_mtx); | 116 | mutex_unlock(&dpm_list_mtx); |
119 | device_wakeup_disable(dev); | 117 | device_wakeup_disable(dev); |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index b16686a0a5a2..cfc3226ec492 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -4,7 +4,7 @@ static inline void device_pm_init_common(struct device *dev) | |||
4 | { | 4 | { |
5 | if (!dev->power.early_init) { | 5 | if (!dev->power.early_init) { |
6 | spin_lock_init(&dev->power.lock); | 6 | spin_lock_init(&dev->power.lock); |
7 | dev->power.power_state = PMSG_INVALID; | 7 | dev->power.qos = NULL; |
8 | dev->power.early_init = true; | 8 | dev->power.early_init = true; |
9 | } | 9 | } |
10 | } | 10 | } |
@@ -56,14 +56,10 @@ extern void device_pm_move_last(struct device *); | |||
56 | 56 | ||
57 | static inline void device_pm_sleep_init(struct device *dev) {} | 57 | static inline void device_pm_sleep_init(struct device *dev) {} |
58 | 58 | ||
59 | static inline void device_pm_add(struct device *dev) | 59 | static inline void device_pm_add(struct device *dev) {} |
60 | { | ||
61 | dev_pm_qos_constraints_init(dev); | ||
62 | } | ||
63 | 60 | ||
64 | static inline void device_pm_remove(struct device *dev) | 61 | static inline void device_pm_remove(struct device *dev) |
65 | { | 62 | { |
66 | dev_pm_qos_constraints_destroy(dev); | ||
67 | pm_runtime_remove(dev); | 63 | pm_runtime_remove(dev); |
68 | } | 64 | } |
69 | 65 | ||
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 3d4d1f8aac5c..5f74587ef258 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/mutex.h> | 41 | #include <linux/mutex.h> |
42 | #include <linux/export.h> | 42 | #include <linux/export.h> |
43 | #include <linux/pm_runtime.h> | 43 | #include <linux/pm_runtime.h> |
44 | #include <linux/err.h> | ||
44 | 45 | ||
45 | #include "power.h" | 46 | #include "power.h" |
46 | 47 | ||
@@ -61,7 +62,7 @@ enum pm_qos_flags_status __dev_pm_qos_flags(struct device *dev, s32 mask) | |||
61 | struct pm_qos_flags *pqf; | 62 | struct pm_qos_flags *pqf; |
62 | s32 val; | 63 | s32 val; |
63 | 64 | ||
64 | if (!qos) | 65 | if (IS_ERR_OR_NULL(qos)) |
65 | return PM_QOS_FLAGS_UNDEFINED; | 66 | return PM_QOS_FLAGS_UNDEFINED; |
66 | 67 | ||
67 | pqf = &qos->flags; | 68 | pqf = &qos->flags; |
@@ -101,7 +102,8 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_flags); | |||
101 | */ | 102 | */ |
102 | s32 __dev_pm_qos_read_value(struct device *dev) | 103 | s32 __dev_pm_qos_read_value(struct device *dev) |
103 | { | 104 | { |
104 | return dev->power.qos ? pm_qos_read_value(&dev->power.qos->latency) : 0; | 105 | return IS_ERR_OR_NULL(dev->power.qos) ? |
106 | 0 : pm_qos_read_value(&dev->power.qos->latency); | ||
105 | } | 107 | } |
106 | 108 | ||
107 | /** | 109 | /** |
@@ -198,20 +200,8 @@ static int dev_pm_qos_constraints_allocate(struct device *dev) | |||
198 | return 0; | 200 | return 0; |
199 | } | 201 | } |
200 | 202 | ||
201 | /** | 203 | static void __dev_pm_qos_hide_latency_limit(struct device *dev); |
202 | * dev_pm_qos_constraints_init - Initalize device's PM QoS constraints pointer. | 204 | static void __dev_pm_qos_hide_flags(struct device *dev); |
203 | * @dev: target device | ||
204 | * | ||
205 | * Called from the device PM subsystem during device insertion under | ||
206 | * device_pm_lock(). | ||
207 | */ | ||
208 | void dev_pm_qos_constraints_init(struct device *dev) | ||
209 | { | ||
210 | mutex_lock(&dev_pm_qos_mtx); | ||
211 | dev->power.qos = NULL; | ||
212 | dev->power.power_state = PMSG_ON; | ||
213 | mutex_unlock(&dev_pm_qos_mtx); | ||
214 | } | ||
215 | 205 | ||
216 | /** | 206 | /** |
217 | * dev_pm_qos_constraints_destroy | 207 | * dev_pm_qos_constraints_destroy |
@@ -226,16 +216,15 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
226 | struct pm_qos_constraints *c; | 216 | struct pm_qos_constraints *c; |
227 | struct pm_qos_flags *f; | 217 | struct pm_qos_flags *f; |
228 | 218 | ||
219 | mutex_lock(&dev_pm_qos_mtx); | ||
220 | |||
229 | /* | 221 | /* |
230 | * If the device's PM QoS resume latency limit or PM QoS flags have been | 222 | * If the device's PM QoS resume latency limit or PM QoS flags have been |
231 | * exposed to user space, they have to be hidden at this point. | 223 | * exposed to user space, they have to be hidden at this point. |
232 | */ | 224 | */ |
233 | dev_pm_qos_hide_latency_limit(dev); | 225 | __dev_pm_qos_hide_latency_limit(dev); |
234 | dev_pm_qos_hide_flags(dev); | 226 | __dev_pm_qos_hide_flags(dev); |
235 | 227 | ||
236 | mutex_lock(&dev_pm_qos_mtx); | ||
237 | |||
238 | dev->power.power_state = PMSG_INVALID; | ||
239 | qos = dev->power.qos; | 228 | qos = dev->power.qos; |
240 | if (!qos) | 229 | if (!qos) |
241 | goto out; | 230 | goto out; |
@@ -257,7 +246,7 @@ void dev_pm_qos_constraints_destroy(struct device *dev) | |||
257 | } | 246 | } |
258 | 247 | ||
259 | spin_lock_irq(&dev->power.lock); | 248 | spin_lock_irq(&dev->power.lock); |
260 | dev->power.qos = NULL; | 249 | dev->power.qos = ERR_PTR(-ENODEV); |
261 | spin_unlock_irq(&dev->power.lock); | 250 | spin_unlock_irq(&dev->power.lock); |
262 | 251 | ||
263 | kfree(c->notifiers); | 252 | kfree(c->notifiers); |
@@ -301,32 +290,19 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, | |||
301 | "%s() called for already added request\n", __func__)) | 290 | "%s() called for already added request\n", __func__)) |
302 | return -EINVAL; | 291 | return -EINVAL; |
303 | 292 | ||
304 | req->dev = dev; | ||
305 | |||
306 | mutex_lock(&dev_pm_qos_mtx); | 293 | mutex_lock(&dev_pm_qos_mtx); |
307 | 294 | ||
308 | if (!dev->power.qos) { | 295 | if (IS_ERR(dev->power.qos)) |
309 | if (dev->power.power_state.event == PM_EVENT_INVALID) { | 296 | ret = -ENODEV; |
310 | /* The device has been removed from the system. */ | 297 | else if (!dev->power.qos) |
311 | req->dev = NULL; | 298 | ret = dev_pm_qos_constraints_allocate(dev); |
312 | ret = -ENODEV; | ||
313 | goto out; | ||
314 | } else { | ||
315 | /* | ||
316 | * Allocate the constraints data on the first call to | ||
317 | * add_request, i.e. only if the data is not already | ||
318 | * allocated and if the device has not been removed. | ||
319 | */ | ||
320 | ret = dev_pm_qos_constraints_allocate(dev); | ||
321 | } | ||
322 | } | ||
323 | 299 | ||
324 | if (!ret) { | 300 | if (!ret) { |
301 | req->dev = dev; | ||
325 | req->type = type; | 302 | req->type = type; |
326 | ret = apply_constraint(req, PM_QOS_ADD_REQ, value); | 303 | ret = apply_constraint(req, PM_QOS_ADD_REQ, value); |
327 | } | 304 | } |
328 | 305 | ||
329 | out: | ||
330 | mutex_unlock(&dev_pm_qos_mtx); | 306 | mutex_unlock(&dev_pm_qos_mtx); |
331 | 307 | ||
332 | return ret; | 308 | return ret; |
@@ -344,7 +320,14 @@ static int __dev_pm_qos_update_request(struct dev_pm_qos_request *req, | |||
344 | s32 curr_value; | 320 | s32 curr_value; |
345 | int ret = 0; | 321 | int ret = 0; |
346 | 322 | ||
347 | if (!req->dev->power.qos) | 323 | if (!req) /*guard against callers passing in null */ |
324 | return -EINVAL; | ||
325 | |||
326 | if (WARN(!dev_pm_qos_request_active(req), | ||
327 | "%s() called for unknown object\n", __func__)) | ||
328 | return -EINVAL; | ||
329 | |||
330 | if (IS_ERR_OR_NULL(req->dev->power.qos)) | ||
348 | return -ENODEV; | 331 | return -ENODEV; |
349 | 332 | ||
350 | switch(req->type) { | 333 | switch(req->type) { |
@@ -386,6 +369,17 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value) | |||
386 | { | 369 | { |
387 | int ret; | 370 | int ret; |
388 | 371 | ||
372 | mutex_lock(&dev_pm_qos_mtx); | ||
373 | ret = __dev_pm_qos_update_request(req, new_value); | ||
374 | mutex_unlock(&dev_pm_qos_mtx); | ||
375 | return ret; | ||
376 | } | ||
377 | EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); | ||
378 | |||
379 | static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | ||
380 | { | ||
381 | int ret; | ||
382 | |||
389 | if (!req) /*guard against callers passing in null */ | 383 | if (!req) /*guard against callers passing in null */ |
390 | return -EINVAL; | 384 | return -EINVAL; |
391 | 385 | ||
@@ -393,13 +387,13 @@ int dev_pm_qos_update_request(struct dev_pm_qos_request *req, s32 new_value) | |||
393 | "%s() called for unknown object\n", __func__)) | 387 | "%s() called for unknown object\n", __func__)) |
394 | return -EINVAL; | 388 | return -EINVAL; |
395 | 389 | ||
396 | mutex_lock(&dev_pm_qos_mtx); | 390 | if (IS_ERR_OR_NULL(req->dev->power.qos)) |
397 | ret = __dev_pm_qos_update_request(req, new_value); | 391 | return -ENODEV; |
398 | mutex_unlock(&dev_pm_qos_mtx); | ||
399 | 392 | ||
393 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); | ||
394 | memset(req, 0, sizeof(*req)); | ||
400 | return ret; | 395 | return ret; |
401 | } | 396 | } |
402 | EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); | ||
403 | 397 | ||
404 | /** | 398 | /** |
405 | * dev_pm_qos_remove_request - modifies an existing qos request | 399 | * dev_pm_qos_remove_request - modifies an existing qos request |
@@ -418,26 +412,10 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_update_request); | |||
418 | */ | 412 | */ |
419 | int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) | 413 | int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) |
420 | { | 414 | { |
421 | int ret = 0; | 415 | int ret; |
422 | |||
423 | if (!req) /*guard against callers passing in null */ | ||
424 | return -EINVAL; | ||
425 | |||
426 | if (WARN(!dev_pm_qos_request_active(req), | ||
427 | "%s() called for unknown object\n", __func__)) | ||
428 | return -EINVAL; | ||
429 | 416 | ||
430 | mutex_lock(&dev_pm_qos_mtx); | 417 | mutex_lock(&dev_pm_qos_mtx); |
431 | 418 | ret = __dev_pm_qos_remove_request(req); | |
432 | if (req->dev->power.qos) { | ||
433 | ret = apply_constraint(req, PM_QOS_REMOVE_REQ, | ||
434 | PM_QOS_DEFAULT_VALUE); | ||
435 | memset(req, 0, sizeof(*req)); | ||
436 | } else { | ||
437 | /* Return if the device has been removed */ | ||
438 | ret = -ENODEV; | ||
439 | } | ||
440 | |||
441 | mutex_unlock(&dev_pm_qos_mtx); | 419 | mutex_unlock(&dev_pm_qos_mtx); |
442 | return ret; | 420 | return ret; |
443 | } | 421 | } |
@@ -462,9 +440,10 @@ int dev_pm_qos_add_notifier(struct device *dev, struct notifier_block *notifier) | |||
462 | 440 | ||
463 | mutex_lock(&dev_pm_qos_mtx); | 441 | mutex_lock(&dev_pm_qos_mtx); |
464 | 442 | ||
465 | if (!dev->power.qos) | 443 | if (IS_ERR(dev->power.qos)) |
466 | ret = dev->power.power_state.event != PM_EVENT_INVALID ? | 444 | ret = -ENODEV; |
467 | dev_pm_qos_constraints_allocate(dev) : -ENODEV; | 445 | else if (!dev->power.qos) |
446 | ret = dev_pm_qos_constraints_allocate(dev); | ||
468 | 447 | ||
469 | if (!ret) | 448 | if (!ret) |
470 | ret = blocking_notifier_chain_register( | 449 | ret = blocking_notifier_chain_register( |
@@ -493,7 +472,7 @@ int dev_pm_qos_remove_notifier(struct device *dev, | |||
493 | mutex_lock(&dev_pm_qos_mtx); | 472 | mutex_lock(&dev_pm_qos_mtx); |
494 | 473 | ||
495 | /* Silently return if the constraints object is not present. */ | 474 | /* Silently return if the constraints object is not present. */ |
496 | if (dev->power.qos) | 475 | if (!IS_ERR_OR_NULL(dev->power.qos)) |
497 | retval = blocking_notifier_chain_unregister( | 476 | retval = blocking_notifier_chain_unregister( |
498 | dev->power.qos->latency.notifiers, | 477 | dev->power.qos->latency.notifiers, |
499 | notifier); | 478 | notifier); |
@@ -563,16 +542,20 @@ EXPORT_SYMBOL_GPL(dev_pm_qos_add_ancestor_request); | |||
563 | static void __dev_pm_qos_drop_user_request(struct device *dev, | 542 | static void __dev_pm_qos_drop_user_request(struct device *dev, |
564 | enum dev_pm_qos_req_type type) | 543 | enum dev_pm_qos_req_type type) |
565 | { | 544 | { |
545 | struct dev_pm_qos_request *req = NULL; | ||
546 | |||
566 | switch(type) { | 547 | switch(type) { |
567 | case DEV_PM_QOS_LATENCY: | 548 | case DEV_PM_QOS_LATENCY: |
568 | dev_pm_qos_remove_request(dev->power.qos->latency_req); | 549 | req = dev->power.qos->latency_req; |
569 | dev->power.qos->latency_req = NULL; | 550 | dev->power.qos->latency_req = NULL; |
570 | break; | 551 | break; |
571 | case DEV_PM_QOS_FLAGS: | 552 | case DEV_PM_QOS_FLAGS: |
572 | dev_pm_qos_remove_request(dev->power.qos->flags_req); | 553 | req = dev->power.qos->flags_req; |
573 | dev->power.qos->flags_req = NULL; | 554 | dev->power.qos->flags_req = NULL; |
574 | break; | 555 | break; |
575 | } | 556 | } |
557 | __dev_pm_qos_remove_request(req); | ||
558 | kfree(req); | ||
576 | } | 559 | } |
577 | 560 | ||
578 | /** | 561 | /** |
@@ -588,36 +571,57 @@ int dev_pm_qos_expose_latency_limit(struct device *dev, s32 value) | |||
588 | if (!device_is_registered(dev) || value < 0) | 571 | if (!device_is_registered(dev) || value < 0) |
589 | return -EINVAL; | 572 | return -EINVAL; |
590 | 573 | ||
591 | if (dev->power.qos && dev->power.qos->latency_req) | ||
592 | return -EEXIST; | ||
593 | |||
594 | req = kzalloc(sizeof(*req), GFP_KERNEL); | 574 | req = kzalloc(sizeof(*req), GFP_KERNEL); |
595 | if (!req) | 575 | if (!req) |
596 | return -ENOMEM; | 576 | return -ENOMEM; |
597 | 577 | ||
598 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value); | 578 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_LATENCY, value); |
599 | if (ret < 0) | 579 | if (ret < 0) { |
580 | kfree(req); | ||
600 | return ret; | 581 | return ret; |
582 | } | ||
583 | |||
584 | mutex_lock(&dev_pm_qos_mtx); | ||
585 | |||
586 | if (IS_ERR_OR_NULL(dev->power.qos)) | ||
587 | ret = -ENODEV; | ||
588 | else if (dev->power.qos->latency_req) | ||
589 | ret = -EEXIST; | ||
590 | |||
591 | if (ret < 0) { | ||
592 | __dev_pm_qos_remove_request(req); | ||
593 | kfree(req); | ||
594 | goto out; | ||
595 | } | ||
601 | 596 | ||
602 | dev->power.qos->latency_req = req; | 597 | dev->power.qos->latency_req = req; |
603 | ret = pm_qos_sysfs_add_latency(dev); | 598 | ret = pm_qos_sysfs_add_latency(dev); |
604 | if (ret) | 599 | if (ret) |
605 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); | 600 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); |
606 | 601 | ||
602 | out: | ||
603 | mutex_unlock(&dev_pm_qos_mtx); | ||
607 | return ret; | 604 | return ret; |
608 | } | 605 | } |
609 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); | 606 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_limit); |
610 | 607 | ||
608 | static void __dev_pm_qos_hide_latency_limit(struct device *dev) | ||
609 | { | ||
610 | if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->latency_req) { | ||
611 | pm_qos_sysfs_remove_latency(dev); | ||
612 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); | ||
613 | } | ||
614 | } | ||
615 | |||
611 | /** | 616 | /** |
612 | * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space. | 617 | * dev_pm_qos_hide_latency_limit - Hide PM QoS latency limit from user space. |
613 | * @dev: Device whose PM QoS latency limit is to be hidden from user space. | 618 | * @dev: Device whose PM QoS latency limit is to be hidden from user space. |
614 | */ | 619 | */ |
615 | void dev_pm_qos_hide_latency_limit(struct device *dev) | 620 | void dev_pm_qos_hide_latency_limit(struct device *dev) |
616 | { | 621 | { |
617 | if (dev->power.qos && dev->power.qos->latency_req) { | 622 | mutex_lock(&dev_pm_qos_mtx); |
618 | pm_qos_sysfs_remove_latency(dev); | 623 | __dev_pm_qos_hide_latency_limit(dev); |
619 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_LATENCY); | 624 | mutex_unlock(&dev_pm_qos_mtx); |
620 | } | ||
621 | } | 625 | } |
622 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); | 626 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_limit); |
623 | 627 | ||
@@ -634,41 +638,61 @@ int dev_pm_qos_expose_flags(struct device *dev, s32 val) | |||
634 | if (!device_is_registered(dev)) | 638 | if (!device_is_registered(dev)) |
635 | return -EINVAL; | 639 | return -EINVAL; |
636 | 640 | ||
637 | if (dev->power.qos && dev->power.qos->flags_req) | ||
638 | return -EEXIST; | ||
639 | |||
640 | req = kzalloc(sizeof(*req), GFP_KERNEL); | 641 | req = kzalloc(sizeof(*req), GFP_KERNEL); |
641 | if (!req) | 642 | if (!req) |
642 | return -ENOMEM; | 643 | return -ENOMEM; |
643 | 644 | ||
644 | pm_runtime_get_sync(dev); | ||
645 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val); | 645 | ret = dev_pm_qos_add_request(dev, req, DEV_PM_QOS_FLAGS, val); |
646 | if (ret < 0) | 646 | if (ret < 0) { |
647 | goto fail; | 647 | kfree(req); |
648 | return ret; | ||
649 | } | ||
650 | |||
651 | pm_runtime_get_sync(dev); | ||
652 | mutex_lock(&dev_pm_qos_mtx); | ||
653 | |||
654 | if (IS_ERR_OR_NULL(dev->power.qos)) | ||
655 | ret = -ENODEV; | ||
656 | else if (dev->power.qos->flags_req) | ||
657 | ret = -EEXIST; | ||
658 | |||
659 | if (ret < 0) { | ||
660 | __dev_pm_qos_remove_request(req); | ||
661 | kfree(req); | ||
662 | goto out; | ||
663 | } | ||
648 | 664 | ||
649 | dev->power.qos->flags_req = req; | 665 | dev->power.qos->flags_req = req; |
650 | ret = pm_qos_sysfs_add_flags(dev); | 666 | ret = pm_qos_sysfs_add_flags(dev); |
651 | if (ret) | 667 | if (ret) |
652 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); | 668 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); |
653 | 669 | ||
654 | fail: | 670 | out: |
671 | mutex_unlock(&dev_pm_qos_mtx); | ||
655 | pm_runtime_put(dev); | 672 | pm_runtime_put(dev); |
656 | return ret; | 673 | return ret; |
657 | } | 674 | } |
658 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); | 675 | EXPORT_SYMBOL_GPL(dev_pm_qos_expose_flags); |
659 | 676 | ||
677 | static void __dev_pm_qos_hide_flags(struct device *dev) | ||
678 | { | ||
679 | if (!IS_ERR_OR_NULL(dev->power.qos) && dev->power.qos->flags_req) { | ||
680 | pm_qos_sysfs_remove_flags(dev); | ||
681 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); | ||
682 | } | ||
683 | } | ||
684 | |||
660 | /** | 685 | /** |
661 | * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space. | 686 | * dev_pm_qos_hide_flags - Hide PM QoS flags of a device from user space. |
662 | * @dev: Device whose PM QoS flags are to be hidden from user space. | 687 | * @dev: Device whose PM QoS flags are to be hidden from user space. |
663 | */ | 688 | */ |
664 | void dev_pm_qos_hide_flags(struct device *dev) | 689 | void dev_pm_qos_hide_flags(struct device *dev) |
665 | { | 690 | { |
666 | if (dev->power.qos && dev->power.qos->flags_req) { | 691 | pm_runtime_get_sync(dev); |
667 | pm_qos_sysfs_remove_flags(dev); | 692 | mutex_lock(&dev_pm_qos_mtx); |
668 | pm_runtime_get_sync(dev); | 693 | __dev_pm_qos_hide_flags(dev); |
669 | __dev_pm_qos_drop_user_request(dev, DEV_PM_QOS_FLAGS); | 694 | mutex_unlock(&dev_pm_qos_mtx); |
670 | pm_runtime_put(dev); | 695 | pm_runtime_put(dev); |
671 | } | ||
672 | } | 696 | } |
673 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); | 697 | EXPORT_SYMBOL_GPL(dev_pm_qos_hide_flags); |
674 | 698 | ||
@@ -683,12 +707,14 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) | |||
683 | s32 value; | 707 | s32 value; |
684 | int ret; | 708 | int ret; |
685 | 709 | ||
686 | if (!dev->power.qos || !dev->power.qos->flags_req) | ||
687 | return -EINVAL; | ||
688 | |||
689 | pm_runtime_get_sync(dev); | 710 | pm_runtime_get_sync(dev); |
690 | mutex_lock(&dev_pm_qos_mtx); | 711 | mutex_lock(&dev_pm_qos_mtx); |
691 | 712 | ||
713 | if (IS_ERR_OR_NULL(dev->power.qos) || !dev->power.qos->flags_req) { | ||
714 | ret = -EINVAL; | ||
715 | goto out; | ||
716 | } | ||
717 | |||
692 | value = dev_pm_qos_requested_flags(dev); | 718 | value = dev_pm_qos_requested_flags(dev); |
693 | if (set) | 719 | if (set) |
694 | value |= mask; | 720 | value |= mask; |
@@ -697,9 +723,12 @@ int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set) | |||
697 | 723 | ||
698 | ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value); | 724 | ret = __dev_pm_qos_update_request(dev->power.qos->flags_req, value); |
699 | 725 | ||
726 | out: | ||
700 | mutex_unlock(&dev_pm_qos_mtx); | 727 | mutex_unlock(&dev_pm_qos_mtx); |
701 | pm_runtime_put(dev); | 728 | pm_runtime_put(dev); |
702 | |||
703 | return ret; | 729 | return ret; |
704 | } | 730 | } |
731 | #else /* !CONFIG_PM_RUNTIME */ | ||
732 | static void __dev_pm_qos_hide_latency_limit(struct device *dev) {} | ||
733 | static void __dev_pm_qos_hide_flags(struct device *dev) {} | ||
705 | #endif /* CONFIG_PM_RUNTIME */ | 734 | #endif /* CONFIG_PM_RUNTIME */ |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index 50d16e3cb0a9..a53ebd265701 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -708,6 +708,7 @@ void rpm_sysfs_remove(struct device *dev) | |||
708 | 708 | ||
709 | void dpm_sysfs_remove(struct device *dev) | 709 | void dpm_sysfs_remove(struct device *dev) |
710 | { | 710 | { |
711 | dev_pm_qos_constraints_destroy(dev); | ||
711 | rpm_sysfs_remove(dev); | 712 | rpm_sysfs_remove(dev); |
712 | sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); | 713 | sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); |
713 | sysfs_remove_group(&dev->kobj, &pm_attr_group); | 714 | sysfs_remove_group(&dev->kobj, &pm_attr_group); |
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 4706c63d0bc6..020ea2b9fd2f 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c | |||
@@ -184,6 +184,7 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) | |||
184 | if (ret < 0) { | 184 | if (ret < 0) { |
185 | dev_err(map->dev, "IRQ thread failed to resume: %d\n", | 185 | dev_err(map->dev, "IRQ thread failed to resume: %d\n", |
186 | ret); | 186 | ret); |
187 | pm_runtime_put(map->dev); | ||
187 | return IRQ_NONE; | 188 | return IRQ_NONE; |
188 | } | 189 | } |
189 | } | 190 | } |
diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index d3bde6cec927..30629a3d44cc 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c | |||
@@ -404,6 +404,8 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) | |||
404 | return; | 404 | return; |
405 | } | 405 | } |
406 | 406 | ||
407 | spin_lock_init(&pc_host->cfgspace_lock); | ||
408 | |||
407 | pc->host_controller = pc_host; | 409 | pc->host_controller = pc_host; |
408 | pc_host->pci_controller.io_resource = &pc_host->io_resource; | 410 | pc_host->pci_controller.io_resource = &pc_host->io_resource; |
409 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; | 411 | pc_host->pci_controller.mem_resource = &pc_host->mem_resource; |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index 5dc0daed8fac..b81ddfea1da0 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
@@ -532,11 +532,11 @@ config BLK_DEV_RBD | |||
532 | If unsure, say N. | 532 | If unsure, say N. |
533 | 533 | ||
534 | config BLK_DEV_RSXX | 534 | config BLK_DEV_RSXX |
535 | tristate "RamSam PCIe Flash SSD Device Driver" | 535 | tristate "IBM FlashSystem 70/80 PCIe SSD Device Driver" |
536 | depends on PCI | 536 | depends on PCI |
537 | help | 537 | help |
538 | Device driver for IBM's high speed PCIe SSD | 538 | Device driver for IBM's high speed PCIe SSD |
539 | storage devices: RamSan-70 and RamSan-80. | 539 | storage devices: FlashSystem-70 and FlashSystem-80. |
540 | 540 | ||
541 | To compile this driver as a module, choose M here: the | 541 | To compile this driver as a module, choose M here: the |
542 | module will be called rsxx. | 542 | module will be called rsxx. |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index ade58bc8f3c4..1c1b8e544aa2 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
@@ -4206,7 +4206,7 @@ static int cciss_find_cfgtables(ctlr_info_t *h) | |||
4206 | if (rc) | 4206 | if (rc) |
4207 | return rc; | 4207 | return rc; |
4208 | h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev, | 4208 | h->cfgtable = remap_pci_mem(pci_resource_start(h->pdev, |
4209 | cfg_base_addr_index) + cfg_offset, sizeof(h->cfgtable)); | 4209 | cfg_base_addr_index) + cfg_offset, sizeof(*h->cfgtable)); |
4210 | if (!h->cfgtable) | 4210 | if (!h->cfgtable) |
4211 | return -ENOMEM; | 4211 | return -ENOMEM; |
4212 | rc = write_driver_ver_to_cfgtable(h->cfgtable); | 4212 | rc = write_driver_ver_to_cfgtable(h->cfgtable); |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index 747bb2af69dc..fe5f6403417f 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
@@ -1044,12 +1044,29 @@ static int loop_clr_fd(struct loop_device *lo) | |||
1044 | lo->lo_state = Lo_unbound; | 1044 | lo->lo_state = Lo_unbound; |
1045 | /* This is safe: open() is still holding a reference. */ | 1045 | /* This is safe: open() is still holding a reference. */ |
1046 | module_put(THIS_MODULE); | 1046 | module_put(THIS_MODULE); |
1047 | if (lo->lo_flags & LO_FLAGS_PARTSCAN && bdev) | ||
1048 | ioctl_by_bdev(bdev, BLKRRPART, 0); | ||
1049 | lo->lo_flags = 0; | 1047 | lo->lo_flags = 0; |
1050 | if (!part_shift) | 1048 | if (!part_shift) |
1051 | lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN; | 1049 | lo->lo_disk->flags |= GENHD_FL_NO_PART_SCAN; |
1052 | mutex_unlock(&lo->lo_ctl_mutex); | 1050 | mutex_unlock(&lo->lo_ctl_mutex); |
1051 | |||
1052 | /* | ||
1053 | * Remove all partitions, since BLKRRPART won't remove user | ||
1054 | * added partitions when max_part=0 | ||
1055 | */ | ||
1056 | if (bdev) { | ||
1057 | struct disk_part_iter piter; | ||
1058 | struct hd_struct *part; | ||
1059 | |||
1060 | mutex_lock_nested(&bdev->bd_mutex, 1); | ||
1061 | invalidate_partition(bdev->bd_disk, 0); | ||
1062 | disk_part_iter_init(&piter, bdev->bd_disk, | ||
1063 | DISK_PITER_INCL_EMPTY); | ||
1064 | while ((part = disk_part_iter_next(&piter))) | ||
1065 | delete_partition(bdev->bd_disk, part->partno); | ||
1066 | disk_part_iter_exit(&piter); | ||
1067 | mutex_unlock(&bdev->bd_mutex); | ||
1068 | } | ||
1069 | |||
1053 | /* | 1070 | /* |
1054 | * Need not hold lo_ctl_mutex to fput backing file. | 1071 | * Need not hold lo_ctl_mutex to fput backing file. |
1055 | * Calling fput holding lo_ctl_mutex triggers a circular | 1072 | * Calling fput holding lo_ctl_mutex triggers a circular |
@@ -1623,6 +1640,7 @@ static int loop_add(struct loop_device **l, int i) | |||
1623 | goto out_free_dev; | 1640 | goto out_free_dev; |
1624 | i = err; | 1641 | i = err; |
1625 | 1642 | ||
1643 | err = -ENOMEM; | ||
1626 | lo->lo_queue = blk_alloc_queue(GFP_KERNEL); | 1644 | lo->lo_queue = blk_alloc_queue(GFP_KERNEL); |
1627 | if (!lo->lo_queue) | 1645 | if (!lo->lo_queue) |
1628 | goto out_free_dev; | 1646 | goto out_free_dev; |
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index 1788f491e0fb..076ae7f1b781 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c | |||
@@ -890,8 +890,10 @@ static int mg_probe(struct platform_device *plat_dev) | |||
890 | gpio_direction_output(host->rst, 1); | 890 | gpio_direction_output(host->rst, 1); |
891 | 891 | ||
892 | /* reset out pin */ | 892 | /* reset out pin */ |
893 | if (!(prv_data->dev_attr & MG_DEV_MASK)) | 893 | if (!(prv_data->dev_attr & MG_DEV_MASK)) { |
894 | err = -EINVAL; | ||
894 | goto probe_err_3a; | 895 | goto probe_err_3a; |
896 | } | ||
895 | 897 | ||
896 | if (prv_data->dev_attr != MG_BOOT_DEV) { | 898 | if (prv_data->dev_attr != MG_BOOT_DEV) { |
897 | rsc = platform_get_resource_byname(plat_dev, IORESOURCE_IO, | 899 | rsc = platform_get_resource_byname(plat_dev, IORESOURCE_IO, |
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 11cc9522cdd4..92250af84e7d 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
@@ -4224,6 +4224,7 @@ static int mtip_pci_probe(struct pci_dev *pdev, | |||
4224 | dd->isr_workq = create_workqueue(dd->workq_name); | 4224 | dd->isr_workq = create_workqueue(dd->workq_name); |
4225 | if (!dd->isr_workq) { | 4225 | if (!dd->isr_workq) { |
4226 | dev_warn(&pdev->dev, "Can't create wq %d\n", dd->instance); | 4226 | dev_warn(&pdev->dev, "Can't create wq %d\n", dd->instance); |
4227 | rv = -ENOMEM; | ||
4227 | goto block_initialize_err; | 4228 | goto block_initialize_err; |
4228 | } | 4229 | } |
4229 | 4230 | ||
@@ -4282,7 +4283,8 @@ static int mtip_pci_probe(struct pci_dev *pdev, | |||
4282 | INIT_WORK(&dd->work[7].work, mtip_workq_sdbf7); | 4283 | INIT_WORK(&dd->work[7].work, mtip_workq_sdbf7); |
4283 | 4284 | ||
4284 | pci_set_master(pdev); | 4285 | pci_set_master(pdev); |
4285 | if (pci_enable_msi(pdev)) { | 4286 | rv = pci_enable_msi(pdev); |
4287 | if (rv) { | ||
4286 | dev_warn(&pdev->dev, | 4288 | dev_warn(&pdev->dev, |
4287 | "Unable to enable MSI interrupt.\n"); | 4289 | "Unable to enable MSI interrupt.\n"); |
4288 | goto block_initialize_err; | 4290 | goto block_initialize_err; |
diff --git a/drivers/block/nvme.c b/drivers/block/nvme.c index 07fb2dfaae13..9dcefe40380b 100644 --- a/drivers/block/nvme.c +++ b/drivers/block/nvme.c | |||
@@ -135,6 +135,7 @@ static inline void _nvme_check_size(void) | |||
135 | BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096); | 135 | BUILD_BUG_ON(sizeof(struct nvme_id_ctrl) != 4096); |
136 | BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096); | 136 | BUILD_BUG_ON(sizeof(struct nvme_id_ns) != 4096); |
137 | BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64); | 137 | BUILD_BUG_ON(sizeof(struct nvme_lba_range_type) != 64); |
138 | BUILD_BUG_ON(sizeof(struct nvme_smart_log) != 512); | ||
138 | } | 139 | } |
139 | 140 | ||
140 | typedef void (*nvme_completion_fn)(struct nvme_dev *, void *, | 141 | typedef void (*nvme_completion_fn)(struct nvme_dev *, void *, |
@@ -237,7 +238,8 @@ static void *free_cmdid(struct nvme_queue *nvmeq, int cmdid, | |||
237 | *fn = special_completion; | 238 | *fn = special_completion; |
238 | return CMD_CTX_INVALID; | 239 | return CMD_CTX_INVALID; |
239 | } | 240 | } |
240 | *fn = info[cmdid].fn; | 241 | if (fn) |
242 | *fn = info[cmdid].fn; | ||
241 | ctx = info[cmdid].ctx; | 243 | ctx = info[cmdid].ctx; |
242 | info[cmdid].fn = special_completion; | 244 | info[cmdid].fn = special_completion; |
243 | info[cmdid].ctx = CMD_CTX_COMPLETED; | 245 | info[cmdid].ctx = CMD_CTX_COMPLETED; |
@@ -335,6 +337,7 @@ nvme_alloc_iod(unsigned nseg, unsigned nbytes, gfp_t gfp) | |||
335 | iod->offset = offsetof(struct nvme_iod, sg[nseg]); | 337 | iod->offset = offsetof(struct nvme_iod, sg[nseg]); |
336 | iod->npages = -1; | 338 | iod->npages = -1; |
337 | iod->length = nbytes; | 339 | iod->length = nbytes; |
340 | iod->nents = 0; | ||
338 | } | 341 | } |
339 | 342 | ||
340 | return iod; | 343 | return iod; |
@@ -375,7 +378,8 @@ static void bio_completion(struct nvme_dev *dev, void *ctx, | |||
375 | struct bio *bio = iod->private; | 378 | struct bio *bio = iod->private; |
376 | u16 status = le16_to_cpup(&cqe->status) >> 1; | 379 | u16 status = le16_to_cpup(&cqe->status) >> 1; |
377 | 380 | ||
378 | dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents, | 381 | if (iod->nents) |
382 | dma_unmap_sg(&dev->pci_dev->dev, iod->sg, iod->nents, | ||
379 | bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); | 383 | bio_data_dir(bio) ? DMA_TO_DEVICE : DMA_FROM_DEVICE); |
380 | nvme_free_iod(dev, iod); | 384 | nvme_free_iod(dev, iod); |
381 | if (status) { | 385 | if (status) { |
@@ -589,7 +593,7 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, | |||
589 | 593 | ||
590 | result = nvme_map_bio(nvmeq->q_dmadev, iod, bio, dma_dir, psegs); | 594 | result = nvme_map_bio(nvmeq->q_dmadev, iod, bio, dma_dir, psegs); |
591 | if (result < 0) | 595 | if (result < 0) |
592 | goto free_iod; | 596 | goto free_cmdid; |
593 | length = result; | 597 | length = result; |
594 | 598 | ||
595 | cmnd->rw.command_id = cmdid; | 599 | cmnd->rw.command_id = cmdid; |
@@ -609,6 +613,8 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns, | |||
609 | 613 | ||
610 | return 0; | 614 | return 0; |
611 | 615 | ||
616 | free_cmdid: | ||
617 | free_cmdid(nvmeq, cmdid, NULL); | ||
612 | free_iod: | 618 | free_iod: |
613 | nvme_free_iod(nvmeq->dev, iod); | 619 | nvme_free_iod(nvmeq->dev, iod); |
614 | nomem: | 620 | nomem: |
@@ -835,8 +841,8 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns, | |||
835 | return nvme_submit_admin_cmd(dev, &c, NULL); | 841 | return nvme_submit_admin_cmd(dev, &c, NULL); |
836 | } | 842 | } |
837 | 843 | ||
838 | static int nvme_get_features(struct nvme_dev *dev, unsigned fid, | 844 | static int nvme_get_features(struct nvme_dev *dev, unsigned fid, unsigned nsid, |
839 | unsigned nsid, dma_addr_t dma_addr) | 845 | dma_addr_t dma_addr, u32 *result) |
840 | { | 846 | { |
841 | struct nvme_command c; | 847 | struct nvme_command c; |
842 | 848 | ||
@@ -846,7 +852,7 @@ static int nvme_get_features(struct nvme_dev *dev, unsigned fid, | |||
846 | c.features.prp1 = cpu_to_le64(dma_addr); | 852 | c.features.prp1 = cpu_to_le64(dma_addr); |
847 | c.features.fid = cpu_to_le32(fid); | 853 | c.features.fid = cpu_to_le32(fid); |
848 | 854 | ||
849 | return nvme_submit_admin_cmd(dev, &c, NULL); | 855 | return nvme_submit_admin_cmd(dev, &c, result); |
850 | } | 856 | } |
851 | 857 | ||
852 | static int nvme_set_features(struct nvme_dev *dev, unsigned fid, | 858 | static int nvme_set_features(struct nvme_dev *dev, unsigned fid, |
@@ -906,6 +912,10 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid) | |||
906 | 912 | ||
907 | spin_lock_irq(&nvmeq->q_lock); | 913 | spin_lock_irq(&nvmeq->q_lock); |
908 | nvme_cancel_ios(nvmeq, false); | 914 | nvme_cancel_ios(nvmeq, false); |
915 | while (bio_list_peek(&nvmeq->sq_cong)) { | ||
916 | struct bio *bio = bio_list_pop(&nvmeq->sq_cong); | ||
917 | bio_endio(bio, -EIO); | ||
918 | } | ||
909 | spin_unlock_irq(&nvmeq->q_lock); | 919 | spin_unlock_irq(&nvmeq->q_lock); |
910 | 920 | ||
911 | irq_set_affinity_hint(vector, NULL); | 921 | irq_set_affinity_hint(vector, NULL); |
@@ -1230,12 +1240,17 @@ static int nvme_user_admin_cmd(struct nvme_dev *dev, | |||
1230 | if (length != cmd.data_len) | 1240 | if (length != cmd.data_len) |
1231 | status = -ENOMEM; | 1241 | status = -ENOMEM; |
1232 | else | 1242 | else |
1233 | status = nvme_submit_admin_cmd(dev, &c, NULL); | 1243 | status = nvme_submit_admin_cmd(dev, &c, &cmd.result); |
1234 | 1244 | ||
1235 | if (cmd.data_len) { | 1245 | if (cmd.data_len) { |
1236 | nvme_unmap_user_pages(dev, cmd.opcode & 1, iod); | 1246 | nvme_unmap_user_pages(dev, cmd.opcode & 1, iod); |
1237 | nvme_free_iod(dev, iod); | 1247 | nvme_free_iod(dev, iod); |
1238 | } | 1248 | } |
1249 | |||
1250 | if (!status && copy_to_user(&ucmd->result, &cmd.result, | ||
1251 | sizeof(cmd.result))) | ||
1252 | status = -EFAULT; | ||
1253 | |||
1239 | return status; | 1254 | return status; |
1240 | } | 1255 | } |
1241 | 1256 | ||
@@ -1523,9 +1538,9 @@ static int nvme_dev_add(struct nvme_dev *dev) | |||
1523 | continue; | 1538 | continue; |
1524 | 1539 | ||
1525 | res = nvme_get_features(dev, NVME_FEAT_LBA_RANGE, i, | 1540 | res = nvme_get_features(dev, NVME_FEAT_LBA_RANGE, i, |
1526 | dma_addr + 4096); | 1541 | dma_addr + 4096, NULL); |
1527 | if (res) | 1542 | if (res) |
1528 | continue; | 1543 | memset(mem + 4096, 0, 4096); |
1529 | 1544 | ||
1530 | ns = nvme_alloc_ns(dev, i, mem, mem + 4096); | 1545 | ns = nvme_alloc_ns(dev, i, mem, mem + 4096); |
1531 | if (ns) | 1546 | if (ns) |
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c index 6c81a4c040b9..f556f8a8b3f9 100644 --- a/drivers/block/rbd.c +++ b/drivers/block/rbd.c | |||
@@ -1264,6 +1264,32 @@ static bool obj_request_done_test(struct rbd_obj_request *obj_request) | |||
1264 | return atomic_read(&obj_request->done) != 0; | 1264 | return atomic_read(&obj_request->done) != 0; |
1265 | } | 1265 | } |
1266 | 1266 | ||
1267 | static void | ||
1268 | rbd_img_obj_request_read_callback(struct rbd_obj_request *obj_request) | ||
1269 | { | ||
1270 | dout("%s: obj %p img %p result %d %llu/%llu\n", __func__, | ||
1271 | obj_request, obj_request->img_request, obj_request->result, | ||
1272 | obj_request->xferred, obj_request->length); | ||
1273 | /* | ||
1274 | * ENOENT means a hole in the image. We zero-fill the | ||
1275 | * entire length of the request. A short read also implies | ||
1276 | * zero-fill to the end of the request. Either way we | ||
1277 | * update the xferred count to indicate the whole request | ||
1278 | * was satisfied. | ||
1279 | */ | ||
1280 | BUG_ON(obj_request->type != OBJ_REQUEST_BIO); | ||
1281 | if (obj_request->result == -ENOENT) { | ||
1282 | zero_bio_chain(obj_request->bio_list, 0); | ||
1283 | obj_request->result = 0; | ||
1284 | obj_request->xferred = obj_request->length; | ||
1285 | } else if (obj_request->xferred < obj_request->length && | ||
1286 | !obj_request->result) { | ||
1287 | zero_bio_chain(obj_request->bio_list, obj_request->xferred); | ||
1288 | obj_request->xferred = obj_request->length; | ||
1289 | } | ||
1290 | obj_request_done_set(obj_request); | ||
1291 | } | ||
1292 | |||
1267 | static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) | 1293 | static void rbd_obj_request_complete(struct rbd_obj_request *obj_request) |
1268 | { | 1294 | { |
1269 | dout("%s: obj %p cb %p\n", __func__, obj_request, | 1295 | dout("%s: obj %p cb %p\n", __func__, obj_request, |
@@ -1284,23 +1310,10 @@ static void rbd_osd_read_callback(struct rbd_obj_request *obj_request) | |||
1284 | { | 1310 | { |
1285 | dout("%s: obj %p result %d %llu/%llu\n", __func__, obj_request, | 1311 | dout("%s: obj %p result %d %llu/%llu\n", __func__, obj_request, |
1286 | obj_request->result, obj_request->xferred, obj_request->length); | 1312 | obj_request->result, obj_request->xferred, obj_request->length); |
1287 | /* | 1313 | if (obj_request->img_request) |
1288 | * ENOENT means a hole in the object. We zero-fill the | 1314 | rbd_img_obj_request_read_callback(obj_request); |
1289 | * entire length of the request. A short read also implies | 1315 | else |
1290 | * zero-fill to the end of the request. Either way we | 1316 | obj_request_done_set(obj_request); |
1291 | * update the xferred count to indicate the whole request | ||
1292 | * was satisfied. | ||
1293 | */ | ||
1294 | if (obj_request->result == -ENOENT) { | ||
1295 | zero_bio_chain(obj_request->bio_list, 0); | ||
1296 | obj_request->result = 0; | ||
1297 | obj_request->xferred = obj_request->length; | ||
1298 | } else if (obj_request->xferred < obj_request->length && | ||
1299 | !obj_request->result) { | ||
1300 | zero_bio_chain(obj_request->bio_list, obj_request->xferred); | ||
1301 | obj_request->xferred = obj_request->length; | ||
1302 | } | ||
1303 | obj_request_done_set(obj_request); | ||
1304 | } | 1317 | } |
1305 | 1318 | ||
1306 | static void rbd_osd_write_callback(struct rbd_obj_request *obj_request) | 1319 | static void rbd_osd_write_callback(struct rbd_obj_request *obj_request) |
diff --git a/drivers/block/rsxx/Makefile b/drivers/block/rsxx/Makefile index f35cd0b71f7b..b1c53c0aa450 100644 --- a/drivers/block/rsxx/Makefile +++ b/drivers/block/rsxx/Makefile | |||
@@ -1,2 +1,2 @@ | |||
1 | obj-$(CONFIG_BLK_DEV_RSXX) += rsxx.o | 1 | obj-$(CONFIG_BLK_DEV_RSXX) += rsxx.o |
2 | rsxx-y := config.o core.o cregs.o dev.o dma.o | 2 | rsxx-objs := config.o core.o cregs.o dev.o dma.o |
diff --git a/drivers/block/rsxx/config.c b/drivers/block/rsxx/config.c index a295e7e9ee41..10cd530d3e10 100644 --- a/drivers/block/rsxx/config.c +++ b/drivers/block/rsxx/config.c | |||
@@ -29,15 +29,13 @@ | |||
29 | #include "rsxx_priv.h" | 29 | #include "rsxx_priv.h" |
30 | #include "rsxx_cfg.h" | 30 | #include "rsxx_cfg.h" |
31 | 31 | ||
32 | static void initialize_config(void *config) | 32 | static void initialize_config(struct rsxx_card_cfg *cfg) |
33 | { | 33 | { |
34 | struct rsxx_card_cfg *cfg = config; | ||
35 | |||
36 | cfg->hdr.version = RSXX_CFG_VERSION; | 34 | cfg->hdr.version = RSXX_CFG_VERSION; |
37 | 35 | ||
38 | cfg->data.block_size = RSXX_HW_BLK_SIZE; | 36 | cfg->data.block_size = RSXX_HW_BLK_SIZE; |
39 | cfg->data.stripe_size = RSXX_HW_BLK_SIZE; | 37 | cfg->data.stripe_size = RSXX_HW_BLK_SIZE; |
40 | cfg->data.vendor_id = RSXX_VENDOR_ID_TMS_IBM; | 38 | cfg->data.vendor_id = RSXX_VENDOR_ID_IBM; |
41 | cfg->data.cache_order = (-1); | 39 | cfg->data.cache_order = (-1); |
42 | cfg->data.intr_coal.mode = RSXX_INTR_COAL_DISABLED; | 40 | cfg->data.intr_coal.mode = RSXX_INTR_COAL_DISABLED; |
43 | cfg->data.intr_coal.count = 0; | 41 | cfg->data.intr_coal.count = 0; |
@@ -181,7 +179,7 @@ int rsxx_load_config(struct rsxx_cardinfo *card) | |||
181 | } else { | 179 | } else { |
182 | dev_info(CARD_TO_DEV(card), | 180 | dev_info(CARD_TO_DEV(card), |
183 | "Initializing card configuration.\n"); | 181 | "Initializing card configuration.\n"); |
184 | initialize_config(card); | 182 | initialize_config(&card->config); |
185 | st = rsxx_save_config(card); | 183 | st = rsxx_save_config(card); |
186 | if (st) | 184 | if (st) |
187 | return st; | 185 | return st; |
diff --git a/drivers/block/rsxx/core.c b/drivers/block/rsxx/core.c index e5162487686a..5af21f2db29c 100644 --- a/drivers/block/rsxx/core.c +++ b/drivers/block/rsxx/core.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/reboot.h> | 30 | #include <linux/reboot.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/bitops.h> | 32 | #include <linux/bitops.h> |
33 | #include <linux/delay.h> | ||
33 | 34 | ||
34 | #include <linux/genhd.h> | 35 | #include <linux/genhd.h> |
35 | #include <linux/idr.h> | 36 | #include <linux/idr.h> |
@@ -39,8 +40,8 @@ | |||
39 | 40 | ||
40 | #define NO_LEGACY 0 | 41 | #define NO_LEGACY 0 |
41 | 42 | ||
42 | MODULE_DESCRIPTION("IBM RamSan PCIe Flash SSD Device Driver"); | 43 | MODULE_DESCRIPTION("IBM FlashSystem 70/80 PCIe SSD Device Driver"); |
43 | MODULE_AUTHOR("IBM <support@ramsan.com>"); | 44 | MODULE_AUTHOR("Joshua Morris/Philip Kelleher, IBM"); |
44 | MODULE_LICENSE("GPL"); | 45 | MODULE_LICENSE("GPL"); |
45 | MODULE_VERSION(DRIVER_VERSION); | 46 | MODULE_VERSION(DRIVER_VERSION); |
46 | 47 | ||
@@ -52,6 +53,13 @@ static DEFINE_IDA(rsxx_disk_ida); | |||
52 | static DEFINE_SPINLOCK(rsxx_ida_lock); | 53 | static DEFINE_SPINLOCK(rsxx_ida_lock); |
53 | 54 | ||
54 | /*----------------- Interrupt Control & Handling -------------------*/ | 55 | /*----------------- Interrupt Control & Handling -------------------*/ |
56 | |||
57 | static void rsxx_mask_interrupts(struct rsxx_cardinfo *card) | ||
58 | { | ||
59 | card->isr_mask = 0; | ||
60 | card->ier_mask = 0; | ||
61 | } | ||
62 | |||
55 | static void __enable_intr(unsigned int *mask, unsigned int intr) | 63 | static void __enable_intr(unsigned int *mask, unsigned int intr) |
56 | { | 64 | { |
57 | *mask |= intr; | 65 | *mask |= intr; |
@@ -71,7 +79,8 @@ static void __disable_intr(unsigned int *mask, unsigned int intr) | |||
71 | */ | 79 | */ |
72 | void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr) | 80 | void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr) |
73 | { | 81 | { |
74 | if (unlikely(card->halt)) | 82 | if (unlikely(card->halt) || |
83 | unlikely(card->eeh_state)) | ||
75 | return; | 84 | return; |
76 | 85 | ||
77 | __enable_intr(&card->ier_mask, intr); | 86 | __enable_intr(&card->ier_mask, intr); |
@@ -80,6 +89,9 @@ void rsxx_enable_ier(struct rsxx_cardinfo *card, unsigned int intr) | |||
80 | 89 | ||
81 | void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr) | 90 | void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr) |
82 | { | 91 | { |
92 | if (unlikely(card->eeh_state)) | ||
93 | return; | ||
94 | |||
83 | __disable_intr(&card->ier_mask, intr); | 95 | __disable_intr(&card->ier_mask, intr); |
84 | iowrite32(card->ier_mask, card->regmap + IER); | 96 | iowrite32(card->ier_mask, card->regmap + IER); |
85 | } | 97 | } |
@@ -87,7 +99,8 @@ void rsxx_disable_ier(struct rsxx_cardinfo *card, unsigned int intr) | |||
87 | void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card, | 99 | void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card, |
88 | unsigned int intr) | 100 | unsigned int intr) |
89 | { | 101 | { |
90 | if (unlikely(card->halt)) | 102 | if (unlikely(card->halt) || |
103 | unlikely(card->eeh_state)) | ||
91 | return; | 104 | return; |
92 | 105 | ||
93 | __enable_intr(&card->isr_mask, intr); | 106 | __enable_intr(&card->isr_mask, intr); |
@@ -97,6 +110,9 @@ void rsxx_enable_ier_and_isr(struct rsxx_cardinfo *card, | |||
97 | void rsxx_disable_ier_and_isr(struct rsxx_cardinfo *card, | 110 | void rsxx_disable_ier_and_isr(struct rsxx_cardinfo *card, |
98 | unsigned int intr) | 111 | unsigned int intr) |
99 | { | 112 | { |
113 | if (unlikely(card->eeh_state)) | ||
114 | return; | ||
115 | |||
100 | __disable_intr(&card->isr_mask, intr); | 116 | __disable_intr(&card->isr_mask, intr); |
101 | __disable_intr(&card->ier_mask, intr); | 117 | __disable_intr(&card->ier_mask, intr); |
102 | iowrite32(card->ier_mask, card->regmap + IER); | 118 | iowrite32(card->ier_mask, card->regmap + IER); |
@@ -115,6 +131,9 @@ static irqreturn_t rsxx_isr(int irq, void *pdata) | |||
115 | do { | 131 | do { |
116 | reread_isr = 0; | 132 | reread_isr = 0; |
117 | 133 | ||
134 | if (unlikely(card->eeh_state)) | ||
135 | break; | ||
136 | |||
118 | isr = ioread32(card->regmap + ISR); | 137 | isr = ioread32(card->regmap + ISR); |
119 | if (isr == 0xffffffff) { | 138 | if (isr == 0xffffffff) { |
120 | /* | 139 | /* |
@@ -161,9 +180,9 @@ static irqreturn_t rsxx_isr(int irq, void *pdata) | |||
161 | } | 180 | } |
162 | 181 | ||
163 | /*----------------- Card Event Handler -------------------*/ | 182 | /*----------------- Card Event Handler -------------------*/ |
164 | static char *rsxx_card_state_to_str(unsigned int state) | 183 | static const char * const rsxx_card_state_to_str(unsigned int state) |
165 | { | 184 | { |
166 | static char *state_strings[] = { | 185 | static const char * const state_strings[] = { |
167 | "Unknown", "Shutdown", "Starting", "Formatting", | 186 | "Unknown", "Shutdown", "Starting", "Formatting", |
168 | "Uninitialized", "Good", "Shutting Down", | 187 | "Uninitialized", "Good", "Shutting Down", |
169 | "Fault", "Read Only Fault", "dStroying" | 188 | "Fault", "Read Only Fault", "dStroying" |
@@ -304,6 +323,192 @@ static int card_shutdown(struct rsxx_cardinfo *card) | |||
304 | return 0; | 323 | return 0; |
305 | } | 324 | } |
306 | 325 | ||
326 | static int rsxx_eeh_frozen(struct pci_dev *dev) | ||
327 | { | ||
328 | struct rsxx_cardinfo *card = pci_get_drvdata(dev); | ||
329 | int i; | ||
330 | int st; | ||
331 | |||
332 | dev_warn(&dev->dev, "IBM FlashSystem PCI: preparing for slot reset.\n"); | ||
333 | |||
334 | card->eeh_state = 1; | ||
335 | rsxx_mask_interrupts(card); | ||
336 | |||
337 | /* | ||
338 | * We need to guarantee that the write for eeh_state and masking | ||
339 | * interrupts does not become reordered. This will prevent a possible | ||
340 | * race condition with the EEH code. | ||
341 | */ | ||
342 | wmb(); | ||
343 | |||
344 | pci_disable_device(dev); | ||
345 | |||
346 | st = rsxx_eeh_save_issued_dmas(card); | ||
347 | if (st) | ||
348 | return st; | ||
349 | |||
350 | rsxx_eeh_save_issued_creg(card); | ||
351 | |||
352 | for (i = 0; i < card->n_targets; i++) { | ||
353 | if (card->ctrl[i].status.buf) | ||
354 | pci_free_consistent(card->dev, STATUS_BUFFER_SIZE8, | ||
355 | card->ctrl[i].status.buf, | ||
356 | card->ctrl[i].status.dma_addr); | ||
357 | if (card->ctrl[i].cmd.buf) | ||
358 | pci_free_consistent(card->dev, COMMAND_BUFFER_SIZE8, | ||
359 | card->ctrl[i].cmd.buf, | ||
360 | card->ctrl[i].cmd.dma_addr); | ||
361 | } | ||
362 | |||
363 | return 0; | ||
364 | } | ||
365 | |||
366 | static void rsxx_eeh_failure(struct pci_dev *dev) | ||
367 | { | ||
368 | struct rsxx_cardinfo *card = pci_get_drvdata(dev); | ||
369 | int i; | ||
370 | |||
371 | dev_err(&dev->dev, "IBM FlashSystem PCI: disabling failed card.\n"); | ||
372 | |||
373 | card->eeh_state = 1; | ||
374 | |||
375 | for (i = 0; i < card->n_targets; i++) | ||
376 | del_timer_sync(&card->ctrl[i].activity_timer); | ||
377 | |||
378 | rsxx_eeh_cancel_dmas(card); | ||
379 | } | ||
380 | |||
381 | static int rsxx_eeh_fifo_flush_poll(struct rsxx_cardinfo *card) | ||
382 | { | ||
383 | unsigned int status; | ||
384 | int iter = 0; | ||
385 | |||
386 | /* We need to wait for the hardware to reset */ | ||
387 | while (iter++ < 10) { | ||
388 | status = ioread32(card->regmap + PCI_RECONFIG); | ||
389 | |||
390 | if (status & RSXX_FLUSH_BUSY) { | ||
391 | ssleep(1); | ||
392 | continue; | ||
393 | } | ||
394 | |||
395 | if (status & RSXX_FLUSH_TIMEOUT) | ||
396 | dev_warn(CARD_TO_DEV(card), "HW: flash controller timeout\n"); | ||
397 | return 0; | ||
398 | } | ||
399 | |||
400 | /* Hardware failed resetting itself. */ | ||
401 | return -1; | ||
402 | } | ||
403 | |||
404 | static pci_ers_result_t rsxx_error_detected(struct pci_dev *dev, | ||
405 | enum pci_channel_state error) | ||
406 | { | ||
407 | int st; | ||
408 | |||
409 | if (dev->revision < RSXX_EEH_SUPPORT) | ||
410 | return PCI_ERS_RESULT_NONE; | ||
411 | |||
412 | if (error == pci_channel_io_perm_failure) { | ||
413 | rsxx_eeh_failure(dev); | ||
414 | return PCI_ERS_RESULT_DISCONNECT; | ||
415 | } | ||
416 | |||
417 | st = rsxx_eeh_frozen(dev); | ||
418 | if (st) { | ||
419 | dev_err(&dev->dev, "Slot reset setup failed\n"); | ||
420 | rsxx_eeh_failure(dev); | ||
421 | return PCI_ERS_RESULT_DISCONNECT; | ||
422 | } | ||
423 | |||
424 | return PCI_ERS_RESULT_NEED_RESET; | ||
425 | } | ||
426 | |||
427 | static pci_ers_result_t rsxx_slot_reset(struct pci_dev *dev) | ||
428 | { | ||
429 | struct rsxx_cardinfo *card = pci_get_drvdata(dev); | ||
430 | unsigned long flags; | ||
431 | int i; | ||
432 | int st; | ||
433 | |||
434 | dev_warn(&dev->dev, | ||
435 | "IBM FlashSystem PCI: recovering from slot reset.\n"); | ||
436 | |||
437 | st = pci_enable_device(dev); | ||
438 | if (st) | ||
439 | goto failed_hw_setup; | ||
440 | |||
441 | pci_set_master(dev); | ||
442 | |||
443 | st = rsxx_eeh_fifo_flush_poll(card); | ||
444 | if (st) | ||
445 | goto failed_hw_setup; | ||
446 | |||
447 | rsxx_dma_queue_reset(card); | ||
448 | |||
449 | for (i = 0; i < card->n_targets; i++) { | ||
450 | st = rsxx_hw_buffers_init(dev, &card->ctrl[i]); | ||
451 | if (st) | ||
452 | goto failed_hw_buffers_init; | ||
453 | } | ||
454 | |||
455 | if (card->config_valid) | ||
456 | rsxx_dma_configure(card); | ||
457 | |||
458 | /* Clears the ISR register from spurious interrupts */ | ||
459 | st = ioread32(card->regmap + ISR); | ||
460 | |||
461 | card->eeh_state = 0; | ||
462 | |||
463 | st = rsxx_eeh_remap_dmas(card); | ||
464 | if (st) | ||
465 | goto failed_remap_dmas; | ||
466 | |||
467 | spin_lock_irqsave(&card->irq_lock, flags); | ||
468 | if (card->n_targets & RSXX_MAX_TARGETS) | ||
469 | rsxx_enable_ier_and_isr(card, CR_INTR_ALL_G); | ||
470 | else | ||
471 | rsxx_enable_ier_and_isr(card, CR_INTR_ALL_C); | ||
472 | spin_unlock_irqrestore(&card->irq_lock, flags); | ||
473 | |||
474 | rsxx_kick_creg_queue(card); | ||
475 | |||
476 | for (i = 0; i < card->n_targets; i++) { | ||
477 | spin_lock(&card->ctrl[i].queue_lock); | ||
478 | if (list_empty(&card->ctrl[i].queue)) { | ||
479 | spin_unlock(&card->ctrl[i].queue_lock); | ||
480 | continue; | ||
481 | } | ||
482 | spin_unlock(&card->ctrl[i].queue_lock); | ||
483 | |||
484 | queue_work(card->ctrl[i].issue_wq, | ||
485 | &card->ctrl[i].issue_dma_work); | ||
486 | } | ||
487 | |||
488 | dev_info(&dev->dev, "IBM FlashSystem PCI: recovery complete.\n"); | ||
489 | |||
490 | return PCI_ERS_RESULT_RECOVERED; | ||
491 | |||
492 | failed_hw_buffers_init: | ||
493 | failed_remap_dmas: | ||
494 | for (i = 0; i < card->n_targets; i++) { | ||
495 | if (card->ctrl[i].status.buf) | ||
496 | pci_free_consistent(card->dev, | ||
497 | STATUS_BUFFER_SIZE8, | ||
498 | card->ctrl[i].status.buf, | ||
499 | card->ctrl[i].status.dma_addr); | ||
500 | if (card->ctrl[i].cmd.buf) | ||
501 | pci_free_consistent(card->dev, | ||
502 | COMMAND_BUFFER_SIZE8, | ||
503 | card->ctrl[i].cmd.buf, | ||
504 | card->ctrl[i].cmd.dma_addr); | ||
505 | } | ||
506 | failed_hw_setup: | ||
507 | rsxx_eeh_failure(dev); | ||
508 | return PCI_ERS_RESULT_DISCONNECT; | ||
509 | |||
510 | } | ||
511 | |||
307 | /*----------------- Driver Initialization & Setup -------------------*/ | 512 | /*----------------- Driver Initialization & Setup -------------------*/ |
308 | /* Returns: 0 if the driver is compatible with the device | 513 | /* Returns: 0 if the driver is compatible with the device |
309 | -1 if the driver is NOT compatible with the device */ | 514 | -1 if the driver is NOT compatible with the device */ |
@@ -383,6 +588,7 @@ static int rsxx_pci_probe(struct pci_dev *dev, | |||
383 | 588 | ||
384 | spin_lock_init(&card->irq_lock); | 589 | spin_lock_init(&card->irq_lock); |
385 | card->halt = 0; | 590 | card->halt = 0; |
591 | card->eeh_state = 0; | ||
386 | 592 | ||
387 | spin_lock_irq(&card->irq_lock); | 593 | spin_lock_irq(&card->irq_lock); |
388 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); | 594 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); |
@@ -538,9 +744,6 @@ static void rsxx_pci_remove(struct pci_dev *dev) | |||
538 | rsxx_disable_ier_and_isr(card, CR_INTR_EVENT); | 744 | rsxx_disable_ier_and_isr(card, CR_INTR_EVENT); |
539 | spin_unlock_irqrestore(&card->irq_lock, flags); | 745 | spin_unlock_irqrestore(&card->irq_lock, flags); |
540 | 746 | ||
541 | /* Prevent work_structs from re-queuing themselves. */ | ||
542 | card->halt = 1; | ||
543 | |||
544 | cancel_work_sync(&card->event_work); | 747 | cancel_work_sync(&card->event_work); |
545 | 748 | ||
546 | rsxx_destroy_dev(card); | 749 | rsxx_destroy_dev(card); |
@@ -549,6 +752,10 @@ static void rsxx_pci_remove(struct pci_dev *dev) | |||
549 | spin_lock_irqsave(&card->irq_lock, flags); | 752 | spin_lock_irqsave(&card->irq_lock, flags); |
550 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); | 753 | rsxx_disable_ier_and_isr(card, CR_INTR_ALL); |
551 | spin_unlock_irqrestore(&card->irq_lock, flags); | 754 | spin_unlock_irqrestore(&card->irq_lock, flags); |
755 | |||
756 | /* Prevent work_structs from re-queuing themselves. */ | ||
757 | card->halt = 1; | ||
758 | |||
552 | free_irq(dev->irq, card); | 759 | free_irq(dev->irq, card); |
553 | 760 | ||
554 | if (!force_legacy) | 761 | if (!force_legacy) |
@@ -592,11 +799,14 @@ static void rsxx_pci_shutdown(struct pci_dev *dev) | |||
592 | card_shutdown(card); | 799 | card_shutdown(card); |
593 | } | 800 | } |
594 | 801 | ||
802 | static const struct pci_error_handlers rsxx_err_handler = { | ||
803 | .error_detected = rsxx_error_detected, | ||
804 | .slot_reset = rsxx_slot_reset, | ||
805 | }; | ||
806 | |||
595 | static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = { | 807 | static DEFINE_PCI_DEVICE_TABLE(rsxx_pci_ids) = { |
596 | {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS70_FLASH)}, | 808 | {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS70_FLASH)}, |
597 | {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS70D_FLASH)}, | 809 | {PCI_DEVICE(PCI_VENDOR_ID_IBM, PCI_DEVICE_ID_FS80_FLASH)}, |
598 | {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS80_FLASH)}, | ||
599 | {PCI_DEVICE(PCI_VENDOR_ID_TMS_IBM, PCI_DEVICE_ID_RS81_FLASH)}, | ||
600 | {0,}, | 810 | {0,}, |
601 | }; | 811 | }; |
602 | 812 | ||
@@ -609,6 +819,7 @@ static struct pci_driver rsxx_pci_driver = { | |||
609 | .remove = rsxx_pci_remove, | 819 | .remove = rsxx_pci_remove, |
610 | .suspend = rsxx_pci_suspend, | 820 | .suspend = rsxx_pci_suspend, |
611 | .shutdown = rsxx_pci_shutdown, | 821 | .shutdown = rsxx_pci_shutdown, |
822 | .err_handler = &rsxx_err_handler, | ||
612 | }; | 823 | }; |
613 | 824 | ||
614 | static int __init rsxx_core_init(void) | 825 | static int __init rsxx_core_init(void) |
diff --git a/drivers/block/rsxx/cregs.c b/drivers/block/rsxx/cregs.c index 80bbe639fccd..4b5c020a0a65 100644 --- a/drivers/block/rsxx/cregs.c +++ b/drivers/block/rsxx/cregs.c | |||
@@ -58,7 +58,7 @@ static struct kmem_cache *creg_cmd_pool; | |||
58 | #error Unknown endianess!!! Aborting... | 58 | #error Unknown endianess!!! Aborting... |
59 | #endif | 59 | #endif |
60 | 60 | ||
61 | static void copy_to_creg_data(struct rsxx_cardinfo *card, | 61 | static int copy_to_creg_data(struct rsxx_cardinfo *card, |
62 | int cnt8, | 62 | int cnt8, |
63 | void *buf, | 63 | void *buf, |
64 | unsigned int stream) | 64 | unsigned int stream) |
@@ -66,6 +66,9 @@ static void copy_to_creg_data(struct rsxx_cardinfo *card, | |||
66 | int i = 0; | 66 | int i = 0; |
67 | u32 *data = buf; | 67 | u32 *data = buf; |
68 | 68 | ||
69 | if (unlikely(card->eeh_state)) | ||
70 | return -EIO; | ||
71 | |||
69 | for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { | 72 | for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { |
70 | /* | 73 | /* |
71 | * Firmware implementation makes it necessary to byte swap on | 74 | * Firmware implementation makes it necessary to byte swap on |
@@ -76,10 +79,12 @@ static void copy_to_creg_data(struct rsxx_cardinfo *card, | |||
76 | else | 79 | else |
77 | iowrite32(data[i], card->regmap + CREG_DATA(i)); | 80 | iowrite32(data[i], card->regmap + CREG_DATA(i)); |
78 | } | 81 | } |
82 | |||
83 | return 0; | ||
79 | } | 84 | } |
80 | 85 | ||
81 | 86 | ||
82 | static void copy_from_creg_data(struct rsxx_cardinfo *card, | 87 | static int copy_from_creg_data(struct rsxx_cardinfo *card, |
83 | int cnt8, | 88 | int cnt8, |
84 | void *buf, | 89 | void *buf, |
85 | unsigned int stream) | 90 | unsigned int stream) |
@@ -87,6 +92,9 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card, | |||
87 | int i = 0; | 92 | int i = 0; |
88 | u32 *data = buf; | 93 | u32 *data = buf; |
89 | 94 | ||
95 | if (unlikely(card->eeh_state)) | ||
96 | return -EIO; | ||
97 | |||
90 | for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { | 98 | for (i = 0; cnt8 > 0; i++, cnt8 -= 4) { |
91 | /* | 99 | /* |
92 | * Firmware implementation makes it necessary to byte swap on | 100 | * Firmware implementation makes it necessary to byte swap on |
@@ -97,41 +105,31 @@ static void copy_from_creg_data(struct rsxx_cardinfo *card, | |||
97 | else | 105 | else |
98 | data[i] = ioread32(card->regmap + CREG_DATA(i)); | 106 | data[i] = ioread32(card->regmap + CREG_DATA(i)); |
99 | } | 107 | } |
100 | } | ||
101 | |||
102 | static struct creg_cmd *pop_active_cmd(struct rsxx_cardinfo *card) | ||
103 | { | ||
104 | struct creg_cmd *cmd; | ||
105 | 108 | ||
106 | /* | 109 | return 0; |
107 | * Spin lock is needed because this can be called in atomic/interrupt | ||
108 | * context. | ||
109 | */ | ||
110 | spin_lock_bh(&card->creg_ctrl.lock); | ||
111 | cmd = card->creg_ctrl.active_cmd; | ||
112 | card->creg_ctrl.active_cmd = NULL; | ||
113 | spin_unlock_bh(&card->creg_ctrl.lock); | ||
114 | |||
115 | return cmd; | ||
116 | } | 110 | } |
117 | 111 | ||
118 | static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) | 112 | static void creg_issue_cmd(struct rsxx_cardinfo *card, struct creg_cmd *cmd) |
119 | { | 113 | { |
114 | int st; | ||
115 | |||
116 | if (unlikely(card->eeh_state)) | ||
117 | return; | ||
118 | |||
120 | iowrite32(cmd->addr, card->regmap + CREG_ADD); | 119 | iowrite32(cmd->addr, card->regmap + CREG_ADD); |
121 | iowrite32(cmd->cnt8, card->regmap + CREG_CNT); | 120 | iowrite32(cmd->cnt8, card->regmap + CREG_CNT); |
122 | 121 | ||
123 | if (cmd->op == CREG_OP_WRITE) { | 122 | if (cmd->op == CREG_OP_WRITE) { |
124 | if (cmd->buf) | 123 | if (cmd->buf) { |
125 | copy_to_creg_data(card, cmd->cnt8, | 124 | st = copy_to_creg_data(card, cmd->cnt8, |
126 | cmd->buf, cmd->stream); | 125 | cmd->buf, cmd->stream); |
126 | if (st) | ||
127 | return; | ||
128 | } | ||
127 | } | 129 | } |
128 | 130 | ||
129 | /* | 131 | if (unlikely(card->eeh_state)) |
130 | * Data copy must complete before initiating the command. This is | 132 | return; |
131 | * needed for weakly ordered processors (i.e. PowerPC), so that all | ||
132 | * neccessary registers are written before we kick the hardware. | ||
133 | */ | ||
134 | wmb(); | ||
135 | 133 | ||
136 | /* Setting the valid bit will kick off the command. */ | 134 | /* Setting the valid bit will kick off the command. */ |
137 | iowrite32(cmd->op, card->regmap + CREG_CMD); | 135 | iowrite32(cmd->op, card->regmap + CREG_CMD); |
@@ -196,11 +194,11 @@ static int creg_queue_cmd(struct rsxx_cardinfo *card, | |||
196 | cmd->cb_private = cb_private; | 194 | cmd->cb_private = cb_private; |
197 | cmd->status = 0; | 195 | cmd->status = 0; |
198 | 196 | ||
199 | spin_lock(&card->creg_ctrl.lock); | 197 | spin_lock_bh(&card->creg_ctrl.lock); |
200 | list_add_tail(&cmd->list, &card->creg_ctrl.queue); | 198 | list_add_tail(&cmd->list, &card->creg_ctrl.queue); |
201 | card->creg_ctrl.q_depth++; | 199 | card->creg_ctrl.q_depth++; |
202 | creg_kick_queue(card); | 200 | creg_kick_queue(card); |
203 | spin_unlock(&card->creg_ctrl.lock); | 201 | spin_unlock_bh(&card->creg_ctrl.lock); |
204 | 202 | ||
205 | return 0; | 203 | return 0; |
206 | } | 204 | } |
@@ -210,7 +208,11 @@ static void creg_cmd_timed_out(unsigned long data) | |||
210 | struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; | 208 | struct rsxx_cardinfo *card = (struct rsxx_cardinfo *) data; |
211 | struct creg_cmd *cmd; | 209 | struct creg_cmd *cmd; |
212 | 210 | ||
213 | cmd = pop_active_cmd(card); | 211 | spin_lock(&card->creg_ctrl.lock); |
212 | cmd = card->creg_ctrl.active_cmd; | ||
213 | card->creg_ctrl.active_cmd = NULL; | ||
214 | spin_unlock(&card->creg_ctrl.lock); | ||
215 | |||
214 | if (cmd == NULL) { | 216 | if (cmd == NULL) { |
215 | card->creg_ctrl.creg_stats.creg_timeout++; | 217 | card->creg_ctrl.creg_stats.creg_timeout++; |
216 | dev_warn(CARD_TO_DEV(card), | 218 | dev_warn(CARD_TO_DEV(card), |
@@ -247,7 +249,11 @@ static void creg_cmd_done(struct work_struct *work) | |||
247 | if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) | 249 | if (del_timer_sync(&card->creg_ctrl.cmd_timer) == 0) |
248 | card->creg_ctrl.creg_stats.failed_cancel_timer++; | 250 | card->creg_ctrl.creg_stats.failed_cancel_timer++; |
249 | 251 | ||
250 | cmd = pop_active_cmd(card); | 252 | spin_lock_bh(&card->creg_ctrl.lock); |
253 | cmd = card->creg_ctrl.active_cmd; | ||
254 | card->creg_ctrl.active_cmd = NULL; | ||
255 | spin_unlock_bh(&card->creg_ctrl.lock); | ||
256 | |||
251 | if (cmd == NULL) { | 257 | if (cmd == NULL) { |
252 | dev_err(CARD_TO_DEV(card), | 258 | dev_err(CARD_TO_DEV(card), |
253 | "Spurious creg interrupt!\n"); | 259 | "Spurious creg interrupt!\n"); |
@@ -287,7 +293,7 @@ static void creg_cmd_done(struct work_struct *work) | |||
287 | goto creg_done; | 293 | goto creg_done; |
288 | } | 294 | } |
289 | 295 | ||
290 | copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream); | 296 | st = copy_from_creg_data(card, cnt8, cmd->buf, cmd->stream); |
291 | } | 297 | } |
292 | 298 | ||
293 | creg_done: | 299 | creg_done: |
@@ -296,10 +302,10 @@ creg_done: | |||
296 | 302 | ||
297 | kmem_cache_free(creg_cmd_pool, cmd); | 303 | kmem_cache_free(creg_cmd_pool, cmd); |
298 | 304 | ||
299 | spin_lock(&card->creg_ctrl.lock); | 305 | spin_lock_bh(&card->creg_ctrl.lock); |
300 | card->creg_ctrl.active = 0; | 306 | card->creg_ctrl.active = 0; |
301 | creg_kick_queue(card); | 307 | creg_kick_queue(card); |
302 | spin_unlock(&card->creg_ctrl.lock); | 308 | spin_unlock_bh(&card->creg_ctrl.lock); |
303 | } | 309 | } |
304 | 310 | ||
305 | static void creg_reset(struct rsxx_cardinfo *card) | 311 | static void creg_reset(struct rsxx_cardinfo *card) |
@@ -324,7 +330,7 @@ static void creg_reset(struct rsxx_cardinfo *card) | |||
324 | "Resetting creg interface for recovery\n"); | 330 | "Resetting creg interface for recovery\n"); |
325 | 331 | ||
326 | /* Cancel outstanding commands */ | 332 | /* Cancel outstanding commands */ |
327 | spin_lock(&card->creg_ctrl.lock); | 333 | spin_lock_bh(&card->creg_ctrl.lock); |
328 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { | 334 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { |
329 | list_del(&cmd->list); | 335 | list_del(&cmd->list); |
330 | card->creg_ctrl.q_depth--; | 336 | card->creg_ctrl.q_depth--; |
@@ -345,7 +351,7 @@ static void creg_reset(struct rsxx_cardinfo *card) | |||
345 | 351 | ||
346 | card->creg_ctrl.active = 0; | 352 | card->creg_ctrl.active = 0; |
347 | } | 353 | } |
348 | spin_unlock(&card->creg_ctrl.lock); | 354 | spin_unlock_bh(&card->creg_ctrl.lock); |
349 | 355 | ||
350 | card->creg_ctrl.reset = 0; | 356 | card->creg_ctrl.reset = 0; |
351 | spin_lock_irqsave(&card->irq_lock, flags); | 357 | spin_lock_irqsave(&card->irq_lock, flags); |
@@ -399,12 +405,12 @@ static int __issue_creg_rw(struct rsxx_cardinfo *card, | |||
399 | return st; | 405 | return st; |
400 | 406 | ||
401 | /* | 407 | /* |
402 | * This timeout is neccessary for unresponsive hardware. The additional | 408 | * This timeout is necessary for unresponsive hardware. The additional |
403 | * 20 seconds to used to guarantee that each cregs requests has time to | 409 | * 20 seconds to used to guarantee that each cregs requests has time to |
404 | * complete. | 410 | * complete. |
405 | */ | 411 | */ |
406 | timeout = msecs_to_jiffies((CREG_TIMEOUT_MSEC * | 412 | timeout = msecs_to_jiffies(CREG_TIMEOUT_MSEC * |
407 | card->creg_ctrl.q_depth) + 20000); | 413 | card->creg_ctrl.q_depth + 20000); |
408 | 414 | ||
409 | /* | 415 | /* |
410 | * The creg interface is guaranteed to complete. It has a timeout | 416 | * The creg interface is guaranteed to complete. It has a timeout |
@@ -690,6 +696,32 @@ int rsxx_reg_access(struct rsxx_cardinfo *card, | |||
690 | return 0; | 696 | return 0; |
691 | } | 697 | } |
692 | 698 | ||
699 | void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card) | ||
700 | { | ||
701 | struct creg_cmd *cmd = NULL; | ||
702 | |||
703 | cmd = card->creg_ctrl.active_cmd; | ||
704 | card->creg_ctrl.active_cmd = NULL; | ||
705 | |||
706 | if (cmd) { | ||
707 | del_timer_sync(&card->creg_ctrl.cmd_timer); | ||
708 | |||
709 | spin_lock_bh(&card->creg_ctrl.lock); | ||
710 | list_add(&cmd->list, &card->creg_ctrl.queue); | ||
711 | card->creg_ctrl.q_depth++; | ||
712 | card->creg_ctrl.active = 0; | ||
713 | spin_unlock_bh(&card->creg_ctrl.lock); | ||
714 | } | ||
715 | } | ||
716 | |||
717 | void rsxx_kick_creg_queue(struct rsxx_cardinfo *card) | ||
718 | { | ||
719 | spin_lock_bh(&card->creg_ctrl.lock); | ||
720 | if (!list_empty(&card->creg_ctrl.queue)) | ||
721 | creg_kick_queue(card); | ||
722 | spin_unlock_bh(&card->creg_ctrl.lock); | ||
723 | } | ||
724 | |||
693 | /*------------ Initialization & Setup --------------*/ | 725 | /*------------ Initialization & Setup --------------*/ |
694 | int rsxx_creg_setup(struct rsxx_cardinfo *card) | 726 | int rsxx_creg_setup(struct rsxx_cardinfo *card) |
695 | { | 727 | { |
@@ -712,7 +744,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card) | |||
712 | int cnt = 0; | 744 | int cnt = 0; |
713 | 745 | ||
714 | /* Cancel outstanding commands */ | 746 | /* Cancel outstanding commands */ |
715 | spin_lock(&card->creg_ctrl.lock); | 747 | spin_lock_bh(&card->creg_ctrl.lock); |
716 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { | 748 | list_for_each_entry_safe(cmd, tmp, &card->creg_ctrl.queue, list) { |
717 | list_del(&cmd->list); | 749 | list_del(&cmd->list); |
718 | if (cmd->cb) | 750 | if (cmd->cb) |
@@ -737,7 +769,7 @@ void rsxx_creg_destroy(struct rsxx_cardinfo *card) | |||
737 | "Canceled active creg command\n"); | 769 | "Canceled active creg command\n"); |
738 | kmem_cache_free(creg_cmd_pool, cmd); | 770 | kmem_cache_free(creg_cmd_pool, cmd); |
739 | } | 771 | } |
740 | spin_unlock(&card->creg_ctrl.lock); | 772 | spin_unlock_bh(&card->creg_ctrl.lock); |
741 | 773 | ||
742 | cancel_work_sync(&card->creg_ctrl.done_work); | 774 | cancel_work_sync(&card->creg_ctrl.done_work); |
743 | } | 775 | } |
diff --git a/drivers/block/rsxx/dma.c b/drivers/block/rsxx/dma.c index 63176e67662f..0607513cfb41 100644 --- a/drivers/block/rsxx/dma.c +++ b/drivers/block/rsxx/dma.c | |||
@@ -28,7 +28,7 @@ | |||
28 | struct rsxx_dma { | 28 | struct rsxx_dma { |
29 | struct list_head list; | 29 | struct list_head list; |
30 | u8 cmd; | 30 | u8 cmd; |
31 | unsigned int laddr; /* Logical address on the ramsan */ | 31 | unsigned int laddr; /* Logical address */ |
32 | struct { | 32 | struct { |
33 | u32 off; | 33 | u32 off; |
34 | u32 cnt; | 34 | u32 cnt; |
@@ -81,9 +81,6 @@ enum rsxx_hw_status { | |||
81 | HW_STATUS_FAULT = 0x08, | 81 | HW_STATUS_FAULT = 0x08, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | #define STATUS_BUFFER_SIZE8 4096 | ||
85 | #define COMMAND_BUFFER_SIZE8 4096 | ||
86 | |||
87 | static struct kmem_cache *rsxx_dma_pool; | 84 | static struct kmem_cache *rsxx_dma_pool; |
88 | 85 | ||
89 | struct dma_tracker { | 86 | struct dma_tracker { |
@@ -122,7 +119,7 @@ static unsigned int rsxx_get_dma_tgt(struct rsxx_cardinfo *card, u64 addr8) | |||
122 | return tgt; | 119 | return tgt; |
123 | } | 120 | } |
124 | 121 | ||
125 | static void rsxx_dma_queue_reset(struct rsxx_cardinfo *card) | 122 | void rsxx_dma_queue_reset(struct rsxx_cardinfo *card) |
126 | { | 123 | { |
127 | /* Reset all DMA Command/Status Queues */ | 124 | /* Reset all DMA Command/Status Queues */ |
128 | iowrite32(DMA_QUEUE_RESET, card->regmap + RESET); | 125 | iowrite32(DMA_QUEUE_RESET, card->regmap + RESET); |
@@ -210,7 +207,8 @@ static void dma_intr_coal_auto_tune(struct rsxx_cardinfo *card) | |||
210 | u32 q_depth = 0; | 207 | u32 q_depth = 0; |
211 | u32 intr_coal; | 208 | u32 intr_coal; |
212 | 209 | ||
213 | if (card->config.data.intr_coal.mode != RSXX_INTR_COAL_AUTO_TUNE) | 210 | if (card->config.data.intr_coal.mode != RSXX_INTR_COAL_AUTO_TUNE || |
211 | unlikely(card->eeh_state)) | ||
214 | return; | 212 | return; |
215 | 213 | ||
216 | for (i = 0; i < card->n_targets; i++) | 214 | for (i = 0; i < card->n_targets; i++) |
@@ -223,31 +221,26 @@ static void dma_intr_coal_auto_tune(struct rsxx_cardinfo *card) | |||
223 | } | 221 | } |
224 | 222 | ||
225 | /*----------------- RSXX DMA Handling -------------------*/ | 223 | /*----------------- RSXX DMA Handling -------------------*/ |
226 | static void rsxx_complete_dma(struct rsxx_cardinfo *card, | 224 | static void rsxx_complete_dma(struct rsxx_dma_ctrl *ctrl, |
227 | struct rsxx_dma *dma, | 225 | struct rsxx_dma *dma, |
228 | unsigned int status) | 226 | unsigned int status) |
229 | { | 227 | { |
230 | if (status & DMA_SW_ERR) | 228 | if (status & DMA_SW_ERR) |
231 | printk_ratelimited(KERN_ERR | 229 | ctrl->stats.dma_sw_err++; |
232 | "SW Error in DMA(cmd x%02x, laddr x%08x)\n", | ||
233 | dma->cmd, dma->laddr); | ||
234 | if (status & DMA_HW_FAULT) | 230 | if (status & DMA_HW_FAULT) |
235 | printk_ratelimited(KERN_ERR | 231 | ctrl->stats.dma_hw_fault++; |
236 | "HW Fault in DMA(cmd x%02x, laddr x%08x)\n", | ||
237 | dma->cmd, dma->laddr); | ||
238 | if (status & DMA_CANCELLED) | 232 | if (status & DMA_CANCELLED) |
239 | printk_ratelimited(KERN_ERR | 233 | ctrl->stats.dma_cancelled++; |
240 | "DMA Cancelled(cmd x%02x, laddr x%08x)\n", | ||
241 | dma->cmd, dma->laddr); | ||
242 | 234 | ||
243 | if (dma->dma_addr) | 235 | if (dma->dma_addr) |
244 | pci_unmap_page(card->dev, dma->dma_addr, get_dma_size(dma), | 236 | pci_unmap_page(ctrl->card->dev, dma->dma_addr, |
237 | get_dma_size(dma), | ||
245 | dma->cmd == HW_CMD_BLK_WRITE ? | 238 | dma->cmd == HW_CMD_BLK_WRITE ? |
246 | PCI_DMA_TODEVICE : | 239 | PCI_DMA_TODEVICE : |
247 | PCI_DMA_FROMDEVICE); | 240 | PCI_DMA_FROMDEVICE); |
248 | 241 | ||
249 | if (dma->cb) | 242 | if (dma->cb) |
250 | dma->cb(card, dma->cb_data, status ? 1 : 0); | 243 | dma->cb(ctrl->card, dma->cb_data, status ? 1 : 0); |
251 | 244 | ||
252 | kmem_cache_free(rsxx_dma_pool, dma); | 245 | kmem_cache_free(rsxx_dma_pool, dma); |
253 | } | 246 | } |
@@ -330,14 +323,15 @@ static void rsxx_handle_dma_error(struct rsxx_dma_ctrl *ctrl, | |||
330 | if (requeue_cmd) | 323 | if (requeue_cmd) |
331 | rsxx_requeue_dma(ctrl, dma); | 324 | rsxx_requeue_dma(ctrl, dma); |
332 | else | 325 | else |
333 | rsxx_complete_dma(ctrl->card, dma, status); | 326 | rsxx_complete_dma(ctrl, dma, status); |
334 | } | 327 | } |
335 | 328 | ||
336 | static void dma_engine_stalled(unsigned long data) | 329 | static void dma_engine_stalled(unsigned long data) |
337 | { | 330 | { |
338 | struct rsxx_dma_ctrl *ctrl = (struct rsxx_dma_ctrl *)data; | 331 | struct rsxx_dma_ctrl *ctrl = (struct rsxx_dma_ctrl *)data; |
339 | 332 | ||
340 | if (atomic_read(&ctrl->stats.hw_q_depth) == 0) | 333 | if (atomic_read(&ctrl->stats.hw_q_depth) == 0 || |
334 | unlikely(ctrl->card->eeh_state)) | ||
341 | return; | 335 | return; |
342 | 336 | ||
343 | if (ctrl->cmd.idx != ioread32(ctrl->regmap + SW_CMD_IDX)) { | 337 | if (ctrl->cmd.idx != ioread32(ctrl->regmap + SW_CMD_IDX)) { |
@@ -369,7 +363,8 @@ static void rsxx_issue_dmas(struct work_struct *work) | |||
369 | ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work); | 363 | ctrl = container_of(work, struct rsxx_dma_ctrl, issue_dma_work); |
370 | hw_cmd_buf = ctrl->cmd.buf; | 364 | hw_cmd_buf = ctrl->cmd.buf; |
371 | 365 | ||
372 | if (unlikely(ctrl->card->halt)) | 366 | if (unlikely(ctrl->card->halt) || |
367 | unlikely(ctrl->card->eeh_state)) | ||
373 | return; | 368 | return; |
374 | 369 | ||
375 | while (1) { | 370 | while (1) { |
@@ -397,7 +392,7 @@ static void rsxx_issue_dmas(struct work_struct *work) | |||
397 | */ | 392 | */ |
398 | if (unlikely(ctrl->card->dma_fault)) { | 393 | if (unlikely(ctrl->card->dma_fault)) { |
399 | push_tracker(ctrl->trackers, tag); | 394 | push_tracker(ctrl->trackers, tag); |
400 | rsxx_complete_dma(ctrl->card, dma, DMA_CANCELLED); | 395 | rsxx_complete_dma(ctrl, dma, DMA_CANCELLED); |
401 | continue; | 396 | continue; |
402 | } | 397 | } |
403 | 398 | ||
@@ -432,19 +427,15 @@ static void rsxx_issue_dmas(struct work_struct *work) | |||
432 | 427 | ||
433 | /* Let HW know we've queued commands. */ | 428 | /* Let HW know we've queued commands. */ |
434 | if (cmds_pending) { | 429 | if (cmds_pending) { |
435 | /* | ||
436 | * We must guarantee that the CPU writes to 'ctrl->cmd.buf' | ||
437 | * (which is in PCI-consistent system-memory) from the loop | ||
438 | * above make it into the coherency domain before the | ||
439 | * following PIO "trigger" updating the cmd.idx. A WMB is | ||
440 | * sufficient. We need not explicitly CPU cache-flush since | ||
441 | * the memory is a PCI-consistent (ie; coherent) mapping. | ||
442 | */ | ||
443 | wmb(); | ||
444 | |||
445 | atomic_add(cmds_pending, &ctrl->stats.hw_q_depth); | 430 | atomic_add(cmds_pending, &ctrl->stats.hw_q_depth); |
446 | mod_timer(&ctrl->activity_timer, | 431 | mod_timer(&ctrl->activity_timer, |
447 | jiffies + DMA_ACTIVITY_TIMEOUT); | 432 | jiffies + DMA_ACTIVITY_TIMEOUT); |
433 | |||
434 | if (unlikely(ctrl->card->eeh_state)) { | ||
435 | del_timer_sync(&ctrl->activity_timer); | ||
436 | return; | ||
437 | } | ||
438 | |||
448 | iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX); | 439 | iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX); |
449 | } | 440 | } |
450 | } | 441 | } |
@@ -463,7 +454,8 @@ static void rsxx_dma_done(struct work_struct *work) | |||
463 | hw_st_buf = ctrl->status.buf; | 454 | hw_st_buf = ctrl->status.buf; |
464 | 455 | ||
465 | if (unlikely(ctrl->card->halt) || | 456 | if (unlikely(ctrl->card->halt) || |
466 | unlikely(ctrl->card->dma_fault)) | 457 | unlikely(ctrl->card->dma_fault) || |
458 | unlikely(ctrl->card->eeh_state)) | ||
467 | return; | 459 | return; |
468 | 460 | ||
469 | count = le16_to_cpu(hw_st_buf[ctrl->status.idx].count); | 461 | count = le16_to_cpu(hw_st_buf[ctrl->status.idx].count); |
@@ -508,7 +500,7 @@ static void rsxx_dma_done(struct work_struct *work) | |||
508 | if (status) | 500 | if (status) |
509 | rsxx_handle_dma_error(ctrl, dma, status); | 501 | rsxx_handle_dma_error(ctrl, dma, status); |
510 | else | 502 | else |
511 | rsxx_complete_dma(ctrl->card, dma, 0); | 503 | rsxx_complete_dma(ctrl, dma, 0); |
512 | 504 | ||
513 | push_tracker(ctrl->trackers, tag); | 505 | push_tracker(ctrl->trackers, tag); |
514 | 506 | ||
@@ -727,20 +719,54 @@ bvec_err: | |||
727 | 719 | ||
728 | 720 | ||
729 | /*----------------- DMA Engine Initialization & Setup -------------------*/ | 721 | /*----------------- DMA Engine Initialization & Setup -------------------*/ |
722 | int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl) | ||
723 | { | ||
724 | ctrl->status.buf = pci_alloc_consistent(dev, STATUS_BUFFER_SIZE8, | ||
725 | &ctrl->status.dma_addr); | ||
726 | ctrl->cmd.buf = pci_alloc_consistent(dev, COMMAND_BUFFER_SIZE8, | ||
727 | &ctrl->cmd.dma_addr); | ||
728 | if (ctrl->status.buf == NULL || ctrl->cmd.buf == NULL) | ||
729 | return -ENOMEM; | ||
730 | |||
731 | memset(ctrl->status.buf, 0xac, STATUS_BUFFER_SIZE8); | ||
732 | iowrite32(lower_32_bits(ctrl->status.dma_addr), | ||
733 | ctrl->regmap + SB_ADD_LO); | ||
734 | iowrite32(upper_32_bits(ctrl->status.dma_addr), | ||
735 | ctrl->regmap + SB_ADD_HI); | ||
736 | |||
737 | memset(ctrl->cmd.buf, 0x83, COMMAND_BUFFER_SIZE8); | ||
738 | iowrite32(lower_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_LO); | ||
739 | iowrite32(upper_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_HI); | ||
740 | |||
741 | ctrl->status.idx = ioread32(ctrl->regmap + HW_STATUS_CNT); | ||
742 | if (ctrl->status.idx > RSXX_MAX_OUTSTANDING_CMDS) { | ||
743 | dev_crit(&dev->dev, "Failed reading status cnt x%x\n", | ||
744 | ctrl->status.idx); | ||
745 | return -EINVAL; | ||
746 | } | ||
747 | iowrite32(ctrl->status.idx, ctrl->regmap + HW_STATUS_CNT); | ||
748 | iowrite32(ctrl->status.idx, ctrl->regmap + SW_STATUS_CNT); | ||
749 | |||
750 | ctrl->cmd.idx = ioread32(ctrl->regmap + HW_CMD_IDX); | ||
751 | if (ctrl->cmd.idx > RSXX_MAX_OUTSTANDING_CMDS) { | ||
752 | dev_crit(&dev->dev, "Failed reading cmd cnt x%x\n", | ||
753 | ctrl->status.idx); | ||
754 | return -EINVAL; | ||
755 | } | ||
756 | iowrite32(ctrl->cmd.idx, ctrl->regmap + HW_CMD_IDX); | ||
757 | iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX); | ||
758 | |||
759 | return 0; | ||
760 | } | ||
761 | |||
730 | static int rsxx_dma_ctrl_init(struct pci_dev *dev, | 762 | static int rsxx_dma_ctrl_init(struct pci_dev *dev, |
731 | struct rsxx_dma_ctrl *ctrl) | 763 | struct rsxx_dma_ctrl *ctrl) |
732 | { | 764 | { |
733 | int i; | 765 | int i; |
766 | int st; | ||
734 | 767 | ||
735 | memset(&ctrl->stats, 0, sizeof(ctrl->stats)); | 768 | memset(&ctrl->stats, 0, sizeof(ctrl->stats)); |
736 | 769 | ||
737 | ctrl->status.buf = pci_alloc_consistent(dev, STATUS_BUFFER_SIZE8, | ||
738 | &ctrl->status.dma_addr); | ||
739 | ctrl->cmd.buf = pci_alloc_consistent(dev, COMMAND_BUFFER_SIZE8, | ||
740 | &ctrl->cmd.dma_addr); | ||
741 | if (ctrl->status.buf == NULL || ctrl->cmd.buf == NULL) | ||
742 | return -ENOMEM; | ||
743 | |||
744 | ctrl->trackers = vmalloc(DMA_TRACKER_LIST_SIZE8); | 770 | ctrl->trackers = vmalloc(DMA_TRACKER_LIST_SIZE8); |
745 | if (!ctrl->trackers) | 771 | if (!ctrl->trackers) |
746 | return -ENOMEM; | 772 | return -ENOMEM; |
@@ -770,35 +796,9 @@ static int rsxx_dma_ctrl_init(struct pci_dev *dev, | |||
770 | INIT_WORK(&ctrl->issue_dma_work, rsxx_issue_dmas); | 796 | INIT_WORK(&ctrl->issue_dma_work, rsxx_issue_dmas); |
771 | INIT_WORK(&ctrl->dma_done_work, rsxx_dma_done); | 797 | INIT_WORK(&ctrl->dma_done_work, rsxx_dma_done); |
772 | 798 | ||
773 | memset(ctrl->status.buf, 0xac, STATUS_BUFFER_SIZE8); | 799 | st = rsxx_hw_buffers_init(dev, ctrl); |
774 | iowrite32(lower_32_bits(ctrl->status.dma_addr), | 800 | if (st) |
775 | ctrl->regmap + SB_ADD_LO); | 801 | return st; |
776 | iowrite32(upper_32_bits(ctrl->status.dma_addr), | ||
777 | ctrl->regmap + SB_ADD_HI); | ||
778 | |||
779 | memset(ctrl->cmd.buf, 0x83, COMMAND_BUFFER_SIZE8); | ||
780 | iowrite32(lower_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_LO); | ||
781 | iowrite32(upper_32_bits(ctrl->cmd.dma_addr), ctrl->regmap + CB_ADD_HI); | ||
782 | |||
783 | ctrl->status.idx = ioread32(ctrl->regmap + HW_STATUS_CNT); | ||
784 | if (ctrl->status.idx > RSXX_MAX_OUTSTANDING_CMDS) { | ||
785 | dev_crit(&dev->dev, "Failed reading status cnt x%x\n", | ||
786 | ctrl->status.idx); | ||
787 | return -EINVAL; | ||
788 | } | ||
789 | iowrite32(ctrl->status.idx, ctrl->regmap + HW_STATUS_CNT); | ||
790 | iowrite32(ctrl->status.idx, ctrl->regmap + SW_STATUS_CNT); | ||
791 | |||
792 | ctrl->cmd.idx = ioread32(ctrl->regmap + HW_CMD_IDX); | ||
793 | if (ctrl->cmd.idx > RSXX_MAX_OUTSTANDING_CMDS) { | ||
794 | dev_crit(&dev->dev, "Failed reading cmd cnt x%x\n", | ||
795 | ctrl->status.idx); | ||
796 | return -EINVAL; | ||
797 | } | ||
798 | iowrite32(ctrl->cmd.idx, ctrl->regmap + HW_CMD_IDX); | ||
799 | iowrite32(ctrl->cmd.idx, ctrl->regmap + SW_CMD_IDX); | ||
800 | |||
801 | wmb(); | ||
802 | 802 | ||
803 | return 0; | 803 | return 0; |
804 | } | 804 | } |
@@ -834,7 +834,7 @@ static int rsxx_dma_stripe_setup(struct rsxx_cardinfo *card, | |||
834 | return 0; | 834 | return 0; |
835 | } | 835 | } |
836 | 836 | ||
837 | static int rsxx_dma_configure(struct rsxx_cardinfo *card) | 837 | int rsxx_dma_configure(struct rsxx_cardinfo *card) |
838 | { | 838 | { |
839 | u32 intr_coal; | 839 | u32 intr_coal; |
840 | 840 | ||
@@ -980,6 +980,103 @@ void rsxx_dma_destroy(struct rsxx_cardinfo *card) | |||
980 | } | 980 | } |
981 | } | 981 | } |
982 | 982 | ||
983 | int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card) | ||
984 | { | ||
985 | int i; | ||
986 | int j; | ||
987 | int cnt; | ||
988 | struct rsxx_dma *dma; | ||
989 | struct list_head *issued_dmas; | ||
990 | |||
991 | issued_dmas = kzalloc(sizeof(*issued_dmas) * card->n_targets, | ||
992 | GFP_KERNEL); | ||
993 | if (!issued_dmas) | ||
994 | return -ENOMEM; | ||
995 | |||
996 | for (i = 0; i < card->n_targets; i++) { | ||
997 | INIT_LIST_HEAD(&issued_dmas[i]); | ||
998 | cnt = 0; | ||
999 | for (j = 0; j < RSXX_MAX_OUTSTANDING_CMDS; j++) { | ||
1000 | dma = get_tracker_dma(card->ctrl[i].trackers, j); | ||
1001 | if (dma == NULL) | ||
1002 | continue; | ||
1003 | |||
1004 | if (dma->cmd == HW_CMD_BLK_WRITE) | ||
1005 | card->ctrl[i].stats.writes_issued--; | ||
1006 | else if (dma->cmd == HW_CMD_BLK_DISCARD) | ||
1007 | card->ctrl[i].stats.discards_issued--; | ||
1008 | else | ||
1009 | card->ctrl[i].stats.reads_issued--; | ||
1010 | |||
1011 | list_add_tail(&dma->list, &issued_dmas[i]); | ||
1012 | push_tracker(card->ctrl[i].trackers, j); | ||
1013 | cnt++; | ||
1014 | } | ||
1015 | |||
1016 | spin_lock(&card->ctrl[i].queue_lock); | ||
1017 | list_splice(&issued_dmas[i], &card->ctrl[i].queue); | ||
1018 | |||
1019 | atomic_sub(cnt, &card->ctrl[i].stats.hw_q_depth); | ||
1020 | card->ctrl[i].stats.sw_q_depth += cnt; | ||
1021 | card->ctrl[i].e_cnt = 0; | ||
1022 | |||
1023 | list_for_each_entry(dma, &card->ctrl[i].queue, list) { | ||
1024 | if (dma->dma_addr) | ||
1025 | pci_unmap_page(card->dev, dma->dma_addr, | ||
1026 | get_dma_size(dma), | ||
1027 | dma->cmd == HW_CMD_BLK_WRITE ? | ||
1028 | PCI_DMA_TODEVICE : | ||
1029 | PCI_DMA_FROMDEVICE); | ||
1030 | } | ||
1031 | spin_unlock(&card->ctrl[i].queue_lock); | ||
1032 | } | ||
1033 | |||
1034 | kfree(issued_dmas); | ||
1035 | |||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | void rsxx_eeh_cancel_dmas(struct rsxx_cardinfo *card) | ||
1040 | { | ||
1041 | struct rsxx_dma *dma; | ||
1042 | struct rsxx_dma *tmp; | ||
1043 | int i; | ||
1044 | |||
1045 | for (i = 0; i < card->n_targets; i++) { | ||
1046 | spin_lock(&card->ctrl[i].queue_lock); | ||
1047 | list_for_each_entry_safe(dma, tmp, &card->ctrl[i].queue, list) { | ||
1048 | list_del(&dma->list); | ||
1049 | |||
1050 | rsxx_complete_dma(&card->ctrl[i], dma, DMA_CANCELLED); | ||
1051 | } | ||
1052 | spin_unlock(&card->ctrl[i].queue_lock); | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card) | ||
1057 | { | ||
1058 | struct rsxx_dma *dma; | ||
1059 | int i; | ||
1060 | |||
1061 | for (i = 0; i < card->n_targets; i++) { | ||
1062 | spin_lock(&card->ctrl[i].queue_lock); | ||
1063 | list_for_each_entry(dma, &card->ctrl[i].queue, list) { | ||
1064 | dma->dma_addr = pci_map_page(card->dev, dma->page, | ||
1065 | dma->pg_off, get_dma_size(dma), | ||
1066 | dma->cmd == HW_CMD_BLK_WRITE ? | ||
1067 | PCI_DMA_TODEVICE : | ||
1068 | PCI_DMA_FROMDEVICE); | ||
1069 | if (!dma->dma_addr) { | ||
1070 | spin_unlock(&card->ctrl[i].queue_lock); | ||
1071 | kmem_cache_free(rsxx_dma_pool, dma); | ||
1072 | return -ENOMEM; | ||
1073 | } | ||
1074 | } | ||
1075 | spin_unlock(&card->ctrl[i].queue_lock); | ||
1076 | } | ||
1077 | |||
1078 | return 0; | ||
1079 | } | ||
983 | 1080 | ||
984 | int rsxx_dma_init(void) | 1081 | int rsxx_dma_init(void) |
985 | { | 1082 | { |
diff --git a/drivers/block/rsxx/rsxx.h b/drivers/block/rsxx/rsxx.h index 2e50b65902b7..24ba3642bd89 100644 --- a/drivers/block/rsxx/rsxx.h +++ b/drivers/block/rsxx/rsxx.h | |||
@@ -27,15 +27,17 @@ | |||
27 | 27 | ||
28 | /*----------------- IOCTL Definitions -------------------*/ | 28 | /*----------------- IOCTL Definitions -------------------*/ |
29 | 29 | ||
30 | #define RSXX_MAX_DATA 8 | ||
31 | |||
30 | struct rsxx_reg_access { | 32 | struct rsxx_reg_access { |
31 | __u32 addr; | 33 | __u32 addr; |
32 | __u32 cnt; | 34 | __u32 cnt; |
33 | __u32 stat; | 35 | __u32 stat; |
34 | __u32 stream; | 36 | __u32 stream; |
35 | __u32 data[8]; | 37 | __u32 data[RSXX_MAX_DATA]; |
36 | }; | 38 | }; |
37 | 39 | ||
38 | #define RSXX_MAX_REG_CNT (8 * (sizeof(__u32))) | 40 | #define RSXX_MAX_REG_CNT (RSXX_MAX_DATA * (sizeof(__u32))) |
39 | 41 | ||
40 | #define RSXX_IOC_MAGIC 'r' | 42 | #define RSXX_IOC_MAGIC 'r' |
41 | 43 | ||
diff --git a/drivers/block/rsxx/rsxx_cfg.h b/drivers/block/rsxx/rsxx_cfg.h index c025fe5fdb70..f384c943846d 100644 --- a/drivers/block/rsxx/rsxx_cfg.h +++ b/drivers/block/rsxx/rsxx_cfg.h | |||
@@ -58,7 +58,7 @@ struct rsxx_card_cfg { | |||
58 | }; | 58 | }; |
59 | 59 | ||
60 | /* Vendor ID Values */ | 60 | /* Vendor ID Values */ |
61 | #define RSXX_VENDOR_ID_TMS_IBM 0 | 61 | #define RSXX_VENDOR_ID_IBM 0 |
62 | #define RSXX_VENDOR_ID_DSI 1 | 62 | #define RSXX_VENDOR_ID_DSI 1 |
63 | #define RSXX_VENDOR_COUNT 2 | 63 | #define RSXX_VENDOR_COUNT 2 |
64 | 64 | ||
diff --git a/drivers/block/rsxx/rsxx_priv.h b/drivers/block/rsxx/rsxx_priv.h index a1ac907d8f4c..382e8bf5c03b 100644 --- a/drivers/block/rsxx/rsxx_priv.h +++ b/drivers/block/rsxx/rsxx_priv.h | |||
@@ -45,16 +45,13 @@ | |||
45 | 45 | ||
46 | struct proc_cmd; | 46 | struct proc_cmd; |
47 | 47 | ||
48 | #define PCI_VENDOR_ID_TMS_IBM 0x15B6 | 48 | #define PCI_DEVICE_ID_FS70_FLASH 0x04A9 |
49 | #define PCI_DEVICE_ID_RS70_FLASH 0x0019 | 49 | #define PCI_DEVICE_ID_FS80_FLASH 0x04AA |
50 | #define PCI_DEVICE_ID_RS70D_FLASH 0x001A | ||
51 | #define PCI_DEVICE_ID_RS80_FLASH 0x001C | ||
52 | #define PCI_DEVICE_ID_RS81_FLASH 0x001E | ||
53 | 50 | ||
54 | #define RS70_PCI_REV_SUPPORTED 4 | 51 | #define RS70_PCI_REV_SUPPORTED 4 |
55 | 52 | ||
56 | #define DRIVER_NAME "rsxx" | 53 | #define DRIVER_NAME "rsxx" |
57 | #define DRIVER_VERSION "3.7" | 54 | #define DRIVER_VERSION "4.0" |
58 | 55 | ||
59 | /* Block size is 4096 */ | 56 | /* Block size is 4096 */ |
60 | #define RSXX_HW_BLK_SHIFT 12 | 57 | #define RSXX_HW_BLK_SHIFT 12 |
@@ -67,6 +64,9 @@ struct proc_cmd; | |||
67 | #define RSXX_MAX_OUTSTANDING_CMDS 255 | 64 | #define RSXX_MAX_OUTSTANDING_CMDS 255 |
68 | #define RSXX_CS_IDX_MASK 0xff | 65 | #define RSXX_CS_IDX_MASK 0xff |
69 | 66 | ||
67 | #define STATUS_BUFFER_SIZE8 4096 | ||
68 | #define COMMAND_BUFFER_SIZE8 4096 | ||
69 | |||
70 | #define RSXX_MAX_TARGETS 8 | 70 | #define RSXX_MAX_TARGETS 8 |
71 | 71 | ||
72 | struct dma_tracker_list; | 72 | struct dma_tracker_list; |
@@ -91,6 +91,9 @@ struct rsxx_dma_stats { | |||
91 | u32 discards_failed; | 91 | u32 discards_failed; |
92 | u32 done_rescheduled; | 92 | u32 done_rescheduled; |
93 | u32 issue_rescheduled; | 93 | u32 issue_rescheduled; |
94 | u32 dma_sw_err; | ||
95 | u32 dma_hw_fault; | ||
96 | u32 dma_cancelled; | ||
94 | u32 sw_q_depth; /* Number of DMAs on the SW queue. */ | 97 | u32 sw_q_depth; /* Number of DMAs on the SW queue. */ |
95 | atomic_t hw_q_depth; /* Number of DMAs queued to HW. */ | 98 | atomic_t hw_q_depth; /* Number of DMAs queued to HW. */ |
96 | }; | 99 | }; |
@@ -116,6 +119,7 @@ struct rsxx_dma_ctrl { | |||
116 | struct rsxx_cardinfo { | 119 | struct rsxx_cardinfo { |
117 | struct pci_dev *dev; | 120 | struct pci_dev *dev; |
118 | unsigned int halt; | 121 | unsigned int halt; |
122 | unsigned int eeh_state; | ||
119 | 123 | ||
120 | void __iomem *regmap; | 124 | void __iomem *regmap; |
121 | spinlock_t irq_lock; | 125 | spinlock_t irq_lock; |
@@ -224,6 +228,7 @@ enum rsxx_pci_regmap { | |||
224 | PERF_RD512_HI = 0xac, | 228 | PERF_RD512_HI = 0xac, |
225 | PERF_WR512_LO = 0xb0, | 229 | PERF_WR512_LO = 0xb0, |
226 | PERF_WR512_HI = 0xb4, | 230 | PERF_WR512_HI = 0xb4, |
231 | PCI_RECONFIG = 0xb8, | ||
227 | }; | 232 | }; |
228 | 233 | ||
229 | enum rsxx_intr { | 234 | enum rsxx_intr { |
@@ -237,6 +242,8 @@ enum rsxx_intr { | |||
237 | CR_INTR_DMA5 = 0x00000080, | 242 | CR_INTR_DMA5 = 0x00000080, |
238 | CR_INTR_DMA6 = 0x00000100, | 243 | CR_INTR_DMA6 = 0x00000100, |
239 | CR_INTR_DMA7 = 0x00000200, | 244 | CR_INTR_DMA7 = 0x00000200, |
245 | CR_INTR_ALL_C = 0x0000003f, | ||
246 | CR_INTR_ALL_G = 0x000003ff, | ||
240 | CR_INTR_DMA_ALL = 0x000003f5, | 247 | CR_INTR_DMA_ALL = 0x000003f5, |
241 | CR_INTR_ALL = 0xffffffff, | 248 | CR_INTR_ALL = 0xffffffff, |
242 | }; | 249 | }; |
@@ -253,8 +260,14 @@ enum rsxx_pci_reset { | |||
253 | DMA_QUEUE_RESET = 0x00000001, | 260 | DMA_QUEUE_RESET = 0x00000001, |
254 | }; | 261 | }; |
255 | 262 | ||
263 | enum rsxx_hw_fifo_flush { | ||
264 | RSXX_FLUSH_BUSY = 0x00000002, | ||
265 | RSXX_FLUSH_TIMEOUT = 0x00000004, | ||
266 | }; | ||
267 | |||
256 | enum rsxx_pci_revision { | 268 | enum rsxx_pci_revision { |
257 | RSXX_DISCARD_SUPPORT = 2, | 269 | RSXX_DISCARD_SUPPORT = 2, |
270 | RSXX_EEH_SUPPORT = 3, | ||
258 | }; | 271 | }; |
259 | 272 | ||
260 | enum rsxx_creg_cmd { | 273 | enum rsxx_creg_cmd { |
@@ -360,11 +373,17 @@ int rsxx_dma_setup(struct rsxx_cardinfo *card); | |||
360 | void rsxx_dma_destroy(struct rsxx_cardinfo *card); | 373 | void rsxx_dma_destroy(struct rsxx_cardinfo *card); |
361 | int rsxx_dma_init(void); | 374 | int rsxx_dma_init(void); |
362 | void rsxx_dma_cleanup(void); | 375 | void rsxx_dma_cleanup(void); |
376 | void rsxx_dma_queue_reset(struct rsxx_cardinfo *card); | ||
377 | int rsxx_dma_configure(struct rsxx_cardinfo *card); | ||
363 | int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, | 378 | int rsxx_dma_queue_bio(struct rsxx_cardinfo *card, |
364 | struct bio *bio, | 379 | struct bio *bio, |
365 | atomic_t *n_dmas, | 380 | atomic_t *n_dmas, |
366 | rsxx_dma_cb cb, | 381 | rsxx_dma_cb cb, |
367 | void *cb_data); | 382 | void *cb_data); |
383 | int rsxx_hw_buffers_init(struct pci_dev *dev, struct rsxx_dma_ctrl *ctrl); | ||
384 | int rsxx_eeh_save_issued_dmas(struct rsxx_cardinfo *card); | ||
385 | void rsxx_eeh_cancel_dmas(struct rsxx_cardinfo *card); | ||
386 | int rsxx_eeh_remap_dmas(struct rsxx_cardinfo *card); | ||
368 | 387 | ||
369 | /***** cregs.c *****/ | 388 | /***** cregs.c *****/ |
370 | int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr, | 389 | int rsxx_creg_write(struct rsxx_cardinfo *card, u32 addr, |
@@ -389,10 +408,11 @@ int rsxx_creg_setup(struct rsxx_cardinfo *card); | |||
389 | void rsxx_creg_destroy(struct rsxx_cardinfo *card); | 408 | void rsxx_creg_destroy(struct rsxx_cardinfo *card); |
390 | int rsxx_creg_init(void); | 409 | int rsxx_creg_init(void); |
391 | void rsxx_creg_cleanup(void); | 410 | void rsxx_creg_cleanup(void); |
392 | |||
393 | int rsxx_reg_access(struct rsxx_cardinfo *card, | 411 | int rsxx_reg_access(struct rsxx_cardinfo *card, |
394 | struct rsxx_reg_access __user *ucmd, | 412 | struct rsxx_reg_access __user *ucmd, |
395 | int read); | 413 | int read); |
414 | void rsxx_eeh_save_issued_creg(struct rsxx_cardinfo *card); | ||
415 | void rsxx_kick_creg_queue(struct rsxx_cardinfo *card); | ||
396 | 416 | ||
397 | 417 | ||
398 | 418 | ||
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index de1f319f7bd7..dd5b2fed97e9 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c | |||
@@ -164,7 +164,7 @@ static void make_response(struct xen_blkif *blkif, u64 id, | |||
164 | 164 | ||
165 | #define foreach_grant_safe(pos, n, rbtree, node) \ | 165 | #define foreach_grant_safe(pos, n, rbtree, node) \ |
166 | for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \ | 166 | for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \ |
167 | (n) = rb_next(&(pos)->node); \ | 167 | (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL; \ |
168 | &(pos)->node != NULL; \ | 168 | &(pos)->node != NULL; \ |
169 | (pos) = container_of(n, typeof(*(pos)), node), \ | 169 | (pos) = container_of(n, typeof(*(pos)), node), \ |
170 | (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL) | 170 | (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL) |
@@ -381,8 +381,8 @@ irqreturn_t xen_blkif_be_int(int irq, void *dev_id) | |||
381 | 381 | ||
382 | static void print_stats(struct xen_blkif *blkif) | 382 | static void print_stats(struct xen_blkif *blkif) |
383 | { | 383 | { |
384 | pr_info("xen-blkback (%s): oo %3d | rd %4d | wr %4d | f %4d" | 384 | pr_info("xen-blkback (%s): oo %3llu | rd %4llu | wr %4llu | f %4llu" |
385 | " | ds %4d\n", | 385 | " | ds %4llu\n", |
386 | current->comm, blkif->st_oo_req, | 386 | current->comm, blkif->st_oo_req, |
387 | blkif->st_rd_req, blkif->st_wr_req, | 387 | blkif->st_rd_req, blkif->st_wr_req, |
388 | blkif->st_f_req, blkif->st_ds_req); | 388 | blkif->st_f_req, blkif->st_ds_req); |
@@ -442,7 +442,7 @@ int xen_blkif_schedule(void *arg) | |||
442 | } | 442 | } |
443 | 443 | ||
444 | struct seg_buf { | 444 | struct seg_buf { |
445 | unsigned long buf; | 445 | unsigned int offset; |
446 | unsigned int nsec; | 446 | unsigned int nsec; |
447 | }; | 447 | }; |
448 | /* | 448 | /* |
@@ -621,30 +621,21 @@ static int xen_blkbk_map(struct blkif_request *req, | |||
621 | * If this is a new persistent grant | 621 | * If this is a new persistent grant |
622 | * save the handler | 622 | * save the handler |
623 | */ | 623 | */ |
624 | persistent_gnts[i]->handle = map[j].handle; | 624 | persistent_gnts[i]->handle = map[j++].handle; |
625 | persistent_gnts[i]->dev_bus_addr = | ||
626 | map[j++].dev_bus_addr; | ||
627 | } | 625 | } |
628 | pending_handle(pending_req, i) = | 626 | pending_handle(pending_req, i) = |
629 | persistent_gnts[i]->handle; | 627 | persistent_gnts[i]->handle; |
630 | 628 | ||
631 | if (ret) | 629 | if (ret) |
632 | continue; | 630 | continue; |
633 | |||
634 | seg[i].buf = persistent_gnts[i]->dev_bus_addr | | ||
635 | (req->u.rw.seg[i].first_sect << 9); | ||
636 | } else { | 631 | } else { |
637 | pending_handle(pending_req, i) = map[j].handle; | 632 | pending_handle(pending_req, i) = map[j++].handle; |
638 | bitmap_set(pending_req->unmap_seg, i, 1); | 633 | bitmap_set(pending_req->unmap_seg, i, 1); |
639 | 634 | ||
640 | if (ret) { | 635 | if (ret) |
641 | j++; | ||
642 | continue; | 636 | continue; |
643 | } | ||
644 | |||
645 | seg[i].buf = map[j++].dev_bus_addr | | ||
646 | (req->u.rw.seg[i].first_sect << 9); | ||
647 | } | 637 | } |
638 | seg[i].offset = (req->u.rw.seg[i].first_sect << 9); | ||
648 | } | 639 | } |
649 | return ret; | 640 | return ret; |
650 | } | 641 | } |
@@ -679,6 +670,16 @@ static int dispatch_discard_io(struct xen_blkif *blkif, | |||
679 | return err; | 670 | return err; |
680 | } | 671 | } |
681 | 672 | ||
673 | static int dispatch_other_io(struct xen_blkif *blkif, | ||
674 | struct blkif_request *req, | ||
675 | struct pending_req *pending_req) | ||
676 | { | ||
677 | free_req(pending_req); | ||
678 | make_response(blkif, req->u.other.id, req->operation, | ||
679 | BLKIF_RSP_EOPNOTSUPP); | ||
680 | return -EIO; | ||
681 | } | ||
682 | |||
682 | static void xen_blk_drain_io(struct xen_blkif *blkif) | 683 | static void xen_blk_drain_io(struct xen_blkif *blkif) |
683 | { | 684 | { |
684 | atomic_set(&blkif->drain, 1); | 685 | atomic_set(&blkif->drain, 1); |
@@ -800,17 +801,30 @@ __do_block_io_op(struct xen_blkif *blkif) | |||
800 | 801 | ||
801 | /* Apply all sanity checks to /private copy/ of request. */ | 802 | /* Apply all sanity checks to /private copy/ of request. */ |
802 | barrier(); | 803 | barrier(); |
803 | if (unlikely(req.operation == BLKIF_OP_DISCARD)) { | 804 | |
805 | switch (req.operation) { | ||
806 | case BLKIF_OP_READ: | ||
807 | case BLKIF_OP_WRITE: | ||
808 | case BLKIF_OP_WRITE_BARRIER: | ||
809 | case BLKIF_OP_FLUSH_DISKCACHE: | ||
810 | if (dispatch_rw_block_io(blkif, &req, pending_req)) | ||
811 | goto done; | ||
812 | break; | ||
813 | case BLKIF_OP_DISCARD: | ||
804 | free_req(pending_req); | 814 | free_req(pending_req); |
805 | if (dispatch_discard_io(blkif, &req)) | 815 | if (dispatch_discard_io(blkif, &req)) |
806 | break; | 816 | goto done; |
807 | } else if (dispatch_rw_block_io(blkif, &req, pending_req)) | ||
808 | break; | 817 | break; |
818 | default: | ||
819 | if (dispatch_other_io(blkif, &req, pending_req)) | ||
820 | goto done; | ||
821 | break; | ||
822 | } | ||
809 | 823 | ||
810 | /* Yield point for this unbounded loop. */ | 824 | /* Yield point for this unbounded loop. */ |
811 | cond_resched(); | 825 | cond_resched(); |
812 | } | 826 | } |
813 | 827 | done: | |
814 | return more_to_do; | 828 | return more_to_do; |
815 | } | 829 | } |
816 | 830 | ||
@@ -904,7 +918,8 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, | |||
904 | pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n", | 918 | pr_debug(DRV_PFX "access denied: %s of [%llu,%llu] on dev=%04x\n", |
905 | operation == READ ? "read" : "write", | 919 | operation == READ ? "read" : "write", |
906 | preq.sector_number, | 920 | preq.sector_number, |
907 | preq.sector_number + preq.nr_sects, preq.dev); | 921 | preq.sector_number + preq.nr_sects, |
922 | blkif->vbd.pdevice); | ||
908 | goto fail_response; | 923 | goto fail_response; |
909 | } | 924 | } |
910 | 925 | ||
@@ -947,7 +962,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, | |||
947 | (bio_add_page(bio, | 962 | (bio_add_page(bio, |
948 | pages[i], | 963 | pages[i], |
949 | seg[i].nsec << 9, | 964 | seg[i].nsec << 9, |
950 | seg[i].buf & ~PAGE_MASK) == 0)) { | 965 | seg[i].offset) == 0)) { |
951 | 966 | ||
952 | bio = bio_alloc(GFP_KERNEL, nseg-i); | 967 | bio = bio_alloc(GFP_KERNEL, nseg-i); |
953 | if (unlikely(bio == NULL)) | 968 | if (unlikely(bio == NULL)) |
@@ -977,13 +992,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, | |||
977 | bio->bi_end_io = end_block_io_op; | 992 | bio->bi_end_io = end_block_io_op; |
978 | } | 993 | } |
979 | 994 | ||
980 | /* | ||
981 | * We set it one so that the last submit_bio does not have to call | ||
982 | * atomic_inc. | ||
983 | */ | ||
984 | atomic_set(&pending_req->pendcnt, nbio); | 995 | atomic_set(&pending_req->pendcnt, nbio); |
985 | |||
986 | /* Get a reference count for the disk queue and start sending I/O */ | ||
987 | blk_start_plug(&plug); | 996 | blk_start_plug(&plug); |
988 | 997 | ||
989 | for (i = 0; i < nbio; i++) | 998 | for (i = 0; i < nbio; i++) |
@@ -1011,6 +1020,7 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, | |||
1011 | fail_put_bio: | 1020 | fail_put_bio: |
1012 | for (i = 0; i < nbio; i++) | 1021 | for (i = 0; i < nbio; i++) |
1013 | bio_put(biolist[i]); | 1022 | bio_put(biolist[i]); |
1023 | atomic_set(&pending_req->pendcnt, 1); | ||
1014 | __end_block_io_op(pending_req, -EINVAL); | 1024 | __end_block_io_op(pending_req, -EINVAL); |
1015 | msleep(1); /* back off a bit */ | 1025 | msleep(1); /* back off a bit */ |
1016 | return -EIO; | 1026 | return -EIO; |
diff --git a/drivers/block/xen-blkback/common.h b/drivers/block/xen-blkback/common.h index 6072390c7f57..60103e2517ba 100644 --- a/drivers/block/xen-blkback/common.h +++ b/drivers/block/xen-blkback/common.h | |||
@@ -77,11 +77,18 @@ struct blkif_x86_32_request_discard { | |||
77 | uint64_t nr_sectors; | 77 | uint64_t nr_sectors; |
78 | } __attribute__((__packed__)); | 78 | } __attribute__((__packed__)); |
79 | 79 | ||
80 | struct blkif_x86_32_request_other { | ||
81 | uint8_t _pad1; | ||
82 | blkif_vdev_t _pad2; | ||
83 | uint64_t id; /* private guest value, echoed in resp */ | ||
84 | } __attribute__((__packed__)); | ||
85 | |||
80 | struct blkif_x86_32_request { | 86 | struct blkif_x86_32_request { |
81 | uint8_t operation; /* BLKIF_OP_??? */ | 87 | uint8_t operation; /* BLKIF_OP_??? */ |
82 | union { | 88 | union { |
83 | struct blkif_x86_32_request_rw rw; | 89 | struct blkif_x86_32_request_rw rw; |
84 | struct blkif_x86_32_request_discard discard; | 90 | struct blkif_x86_32_request_discard discard; |
91 | struct blkif_x86_32_request_other other; | ||
85 | } u; | 92 | } u; |
86 | } __attribute__((__packed__)); | 93 | } __attribute__((__packed__)); |
87 | 94 | ||
@@ -113,11 +120,19 @@ struct blkif_x86_64_request_discard { | |||
113 | uint64_t nr_sectors; | 120 | uint64_t nr_sectors; |
114 | } __attribute__((__packed__)); | 121 | } __attribute__((__packed__)); |
115 | 122 | ||
123 | struct blkif_x86_64_request_other { | ||
124 | uint8_t _pad1; | ||
125 | blkif_vdev_t _pad2; | ||
126 | uint32_t _pad3; /* offsetof(blkif_..,u.discard.id)==8 */ | ||
127 | uint64_t id; /* private guest value, echoed in resp */ | ||
128 | } __attribute__((__packed__)); | ||
129 | |||
116 | struct blkif_x86_64_request { | 130 | struct blkif_x86_64_request { |
117 | uint8_t operation; /* BLKIF_OP_??? */ | 131 | uint8_t operation; /* BLKIF_OP_??? */ |
118 | union { | 132 | union { |
119 | struct blkif_x86_64_request_rw rw; | 133 | struct blkif_x86_64_request_rw rw; |
120 | struct blkif_x86_64_request_discard discard; | 134 | struct blkif_x86_64_request_discard discard; |
135 | struct blkif_x86_64_request_other other; | ||
121 | } u; | 136 | } u; |
122 | } __attribute__((__packed__)); | 137 | } __attribute__((__packed__)); |
123 | 138 | ||
@@ -172,7 +187,6 @@ struct persistent_gnt { | |||
172 | struct page *page; | 187 | struct page *page; |
173 | grant_ref_t gnt; | 188 | grant_ref_t gnt; |
174 | grant_handle_t handle; | 189 | grant_handle_t handle; |
175 | uint64_t dev_bus_addr; | ||
176 | struct rb_node node; | 190 | struct rb_node node; |
177 | }; | 191 | }; |
178 | 192 | ||
@@ -208,13 +222,13 @@ struct xen_blkif { | |||
208 | 222 | ||
209 | /* statistics */ | 223 | /* statistics */ |
210 | unsigned long st_print; | 224 | unsigned long st_print; |
211 | int st_rd_req; | 225 | unsigned long long st_rd_req; |
212 | int st_wr_req; | 226 | unsigned long long st_wr_req; |
213 | int st_oo_req; | 227 | unsigned long long st_oo_req; |
214 | int st_f_req; | 228 | unsigned long long st_f_req; |
215 | int st_ds_req; | 229 | unsigned long long st_ds_req; |
216 | int st_rd_sect; | 230 | unsigned long long st_rd_sect; |
217 | int st_wr_sect; | 231 | unsigned long long st_wr_sect; |
218 | 232 | ||
219 | wait_queue_head_t waiting_to_free; | 233 | wait_queue_head_t waiting_to_free; |
220 | }; | 234 | }; |
@@ -278,6 +292,11 @@ static inline void blkif_get_x86_32_req(struct blkif_request *dst, | |||
278 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; | 292 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; |
279 | break; | 293 | break; |
280 | default: | 294 | default: |
295 | /* | ||
296 | * Don't know how to translate this op. Only get the | ||
297 | * ID so failure can be reported to the frontend. | ||
298 | */ | ||
299 | dst->u.other.id = src->u.other.id; | ||
281 | break; | 300 | break; |
282 | } | 301 | } |
283 | } | 302 | } |
@@ -309,6 +328,11 @@ static inline void blkif_get_x86_64_req(struct blkif_request *dst, | |||
309 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; | 328 | dst->u.discard.nr_sectors = src->u.discard.nr_sectors; |
310 | break; | 329 | break; |
311 | default: | 330 | default: |
331 | /* | ||
332 | * Don't know how to translate this op. Only get the | ||
333 | * ID so failure can be reported to the frontend. | ||
334 | */ | ||
335 | dst->u.other.id = src->u.other.id; | ||
312 | break; | 336 | break; |
313 | } | 337 | } |
314 | } | 338 | } |
diff --git a/drivers/block/xen-blkback/xenbus.c b/drivers/block/xen-blkback/xenbus.c index 5e237f630c47..8bfd1bcf95ec 100644 --- a/drivers/block/xen-blkback/xenbus.c +++ b/drivers/block/xen-blkback/xenbus.c | |||
@@ -230,13 +230,13 @@ int __init xen_blkif_interface_init(void) | |||
230 | } \ | 230 | } \ |
231 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) | 231 | static DEVICE_ATTR(name, S_IRUGO, show_##name, NULL) |
232 | 232 | ||
233 | VBD_SHOW(oo_req, "%d\n", be->blkif->st_oo_req); | 233 | VBD_SHOW(oo_req, "%llu\n", be->blkif->st_oo_req); |
234 | VBD_SHOW(rd_req, "%d\n", be->blkif->st_rd_req); | 234 | VBD_SHOW(rd_req, "%llu\n", be->blkif->st_rd_req); |
235 | VBD_SHOW(wr_req, "%d\n", be->blkif->st_wr_req); | 235 | VBD_SHOW(wr_req, "%llu\n", be->blkif->st_wr_req); |
236 | VBD_SHOW(f_req, "%d\n", be->blkif->st_f_req); | 236 | VBD_SHOW(f_req, "%llu\n", be->blkif->st_f_req); |
237 | VBD_SHOW(ds_req, "%d\n", be->blkif->st_ds_req); | 237 | VBD_SHOW(ds_req, "%llu\n", be->blkif->st_ds_req); |
238 | VBD_SHOW(rd_sect, "%d\n", be->blkif->st_rd_sect); | 238 | VBD_SHOW(rd_sect, "%llu\n", be->blkif->st_rd_sect); |
239 | VBD_SHOW(wr_sect, "%d\n", be->blkif->st_wr_sect); | 239 | VBD_SHOW(wr_sect, "%llu\n", be->blkif->st_wr_sect); |
240 | 240 | ||
241 | static struct attribute *xen_vbdstat_attrs[] = { | 241 | static struct attribute *xen_vbdstat_attrs[] = { |
242 | &dev_attr_oo_req.attr, | 242 | &dev_attr_oo_req.attr, |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index c3dae2e0f290..a894f88762d8 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include <linux/mutex.h> | 44 | #include <linux/mutex.h> |
45 | #include <linux/scatterlist.h> | 45 | #include <linux/scatterlist.h> |
46 | #include <linux/bitmap.h> | 46 | #include <linux/bitmap.h> |
47 | #include <linux/llist.h> | 47 | #include <linux/list.h> |
48 | 48 | ||
49 | #include <xen/xen.h> | 49 | #include <xen/xen.h> |
50 | #include <xen/xenbus.h> | 50 | #include <xen/xenbus.h> |
@@ -68,13 +68,12 @@ enum blkif_state { | |||
68 | struct grant { | 68 | struct grant { |
69 | grant_ref_t gref; | 69 | grant_ref_t gref; |
70 | unsigned long pfn; | 70 | unsigned long pfn; |
71 | struct llist_node node; | 71 | struct list_head node; |
72 | }; | 72 | }; |
73 | 73 | ||
74 | struct blk_shadow { | 74 | struct blk_shadow { |
75 | struct blkif_request req; | 75 | struct blkif_request req; |
76 | struct request *request; | 76 | struct request *request; |
77 | unsigned long frame[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | ||
78 | struct grant *grants_used[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | 77 | struct grant *grants_used[BLKIF_MAX_SEGMENTS_PER_REQUEST]; |
79 | }; | 78 | }; |
80 | 79 | ||
@@ -105,7 +104,7 @@ struct blkfront_info | |||
105 | struct work_struct work; | 104 | struct work_struct work; |
106 | struct gnttab_free_callback callback; | 105 | struct gnttab_free_callback callback; |
107 | struct blk_shadow shadow[BLK_RING_SIZE]; | 106 | struct blk_shadow shadow[BLK_RING_SIZE]; |
108 | struct llist_head persistent_gnts; | 107 | struct list_head persistent_gnts; |
109 | unsigned int persistent_gnts_c; | 108 | unsigned int persistent_gnts_c; |
110 | unsigned long shadow_free; | 109 | unsigned long shadow_free; |
111 | unsigned int feature_flush; | 110 | unsigned int feature_flush; |
@@ -165,6 +164,69 @@ static int add_id_to_freelist(struct blkfront_info *info, | |||
165 | return 0; | 164 | return 0; |
166 | } | 165 | } |
167 | 166 | ||
167 | static int fill_grant_buffer(struct blkfront_info *info, int num) | ||
168 | { | ||
169 | struct page *granted_page; | ||
170 | struct grant *gnt_list_entry, *n; | ||
171 | int i = 0; | ||
172 | |||
173 | while(i < num) { | ||
174 | gnt_list_entry = kzalloc(sizeof(struct grant), GFP_NOIO); | ||
175 | if (!gnt_list_entry) | ||
176 | goto out_of_memory; | ||
177 | |||
178 | granted_page = alloc_page(GFP_NOIO); | ||
179 | if (!granted_page) { | ||
180 | kfree(gnt_list_entry); | ||
181 | goto out_of_memory; | ||
182 | } | ||
183 | |||
184 | gnt_list_entry->pfn = page_to_pfn(granted_page); | ||
185 | gnt_list_entry->gref = GRANT_INVALID_REF; | ||
186 | list_add(&gnt_list_entry->node, &info->persistent_gnts); | ||
187 | i++; | ||
188 | } | ||
189 | |||
190 | return 0; | ||
191 | |||
192 | out_of_memory: | ||
193 | list_for_each_entry_safe(gnt_list_entry, n, | ||
194 | &info->persistent_gnts, node) { | ||
195 | list_del(&gnt_list_entry->node); | ||
196 | __free_page(pfn_to_page(gnt_list_entry->pfn)); | ||
197 | kfree(gnt_list_entry); | ||
198 | i--; | ||
199 | } | ||
200 | BUG_ON(i != 0); | ||
201 | return -ENOMEM; | ||
202 | } | ||
203 | |||
204 | static struct grant *get_grant(grant_ref_t *gref_head, | ||
205 | struct blkfront_info *info) | ||
206 | { | ||
207 | struct grant *gnt_list_entry; | ||
208 | unsigned long buffer_mfn; | ||
209 | |||
210 | BUG_ON(list_empty(&info->persistent_gnts)); | ||
211 | gnt_list_entry = list_first_entry(&info->persistent_gnts, struct grant, | ||
212 | node); | ||
213 | list_del(&gnt_list_entry->node); | ||
214 | |||
215 | if (gnt_list_entry->gref != GRANT_INVALID_REF) { | ||
216 | info->persistent_gnts_c--; | ||
217 | return gnt_list_entry; | ||
218 | } | ||
219 | |||
220 | /* Assign a gref to this page */ | ||
221 | gnt_list_entry->gref = gnttab_claim_grant_reference(gref_head); | ||
222 | BUG_ON(gnt_list_entry->gref == -ENOSPC); | ||
223 | buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn); | ||
224 | gnttab_grant_foreign_access_ref(gnt_list_entry->gref, | ||
225 | info->xbdev->otherend_id, | ||
226 | buffer_mfn, 0); | ||
227 | return gnt_list_entry; | ||
228 | } | ||
229 | |||
168 | static const char *op_name(int op) | 230 | static const char *op_name(int op) |
169 | { | 231 | { |
170 | static const char *const names[] = { | 232 | static const char *const names[] = { |
@@ -293,7 +355,6 @@ static int blkif_ioctl(struct block_device *bdev, fmode_t mode, | |||
293 | static int blkif_queue_request(struct request *req) | 355 | static int blkif_queue_request(struct request *req) |
294 | { | 356 | { |
295 | struct blkfront_info *info = req->rq_disk->private_data; | 357 | struct blkfront_info *info = req->rq_disk->private_data; |
296 | unsigned long buffer_mfn; | ||
297 | struct blkif_request *ring_req; | 358 | struct blkif_request *ring_req; |
298 | unsigned long id; | 359 | unsigned long id; |
299 | unsigned int fsect, lsect; | 360 | unsigned int fsect, lsect; |
@@ -306,7 +367,6 @@ static int blkif_queue_request(struct request *req) | |||
306 | */ | 367 | */ |
307 | bool new_persistent_gnts; | 368 | bool new_persistent_gnts; |
308 | grant_ref_t gref_head; | 369 | grant_ref_t gref_head; |
309 | struct page *granted_page; | ||
310 | struct grant *gnt_list_entry = NULL; | 370 | struct grant *gnt_list_entry = NULL; |
311 | struct scatterlist *sg; | 371 | struct scatterlist *sg; |
312 | 372 | ||
@@ -370,41 +430,8 @@ static int blkif_queue_request(struct request *req) | |||
370 | fsect = sg->offset >> 9; | 430 | fsect = sg->offset >> 9; |
371 | lsect = fsect + (sg->length >> 9) - 1; | 431 | lsect = fsect + (sg->length >> 9) - 1; |
372 | 432 | ||
373 | if (info->persistent_gnts_c) { | 433 | gnt_list_entry = get_grant(&gref_head, info); |
374 | BUG_ON(llist_empty(&info->persistent_gnts)); | 434 | ref = gnt_list_entry->gref; |
375 | gnt_list_entry = llist_entry( | ||
376 | llist_del_first(&info->persistent_gnts), | ||
377 | struct grant, node); | ||
378 | |||
379 | ref = gnt_list_entry->gref; | ||
380 | buffer_mfn = pfn_to_mfn(gnt_list_entry->pfn); | ||
381 | info->persistent_gnts_c--; | ||
382 | } else { | ||
383 | ref = gnttab_claim_grant_reference(&gref_head); | ||
384 | BUG_ON(ref == -ENOSPC); | ||
385 | |||
386 | gnt_list_entry = | ||
387 | kmalloc(sizeof(struct grant), | ||
388 | GFP_ATOMIC); | ||
389 | if (!gnt_list_entry) | ||
390 | return -ENOMEM; | ||
391 | |||
392 | granted_page = alloc_page(GFP_ATOMIC); | ||
393 | if (!granted_page) { | ||
394 | kfree(gnt_list_entry); | ||
395 | return -ENOMEM; | ||
396 | } | ||
397 | |||
398 | gnt_list_entry->pfn = | ||
399 | page_to_pfn(granted_page); | ||
400 | gnt_list_entry->gref = ref; | ||
401 | |||
402 | buffer_mfn = pfn_to_mfn(page_to_pfn( | ||
403 | granted_page)); | ||
404 | gnttab_grant_foreign_access_ref(ref, | ||
405 | info->xbdev->otherend_id, | ||
406 | buffer_mfn, 0); | ||
407 | } | ||
408 | 435 | ||
409 | info->shadow[id].grants_used[i] = gnt_list_entry; | 436 | info->shadow[id].grants_used[i] = gnt_list_entry; |
410 | 437 | ||
@@ -435,7 +462,6 @@ static int blkif_queue_request(struct request *req) | |||
435 | kunmap_atomic(shared_data); | 462 | kunmap_atomic(shared_data); |
436 | } | 463 | } |
437 | 464 | ||
438 | info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn); | ||
439 | ring_req->u.rw.seg[i] = | 465 | ring_req->u.rw.seg[i] = |
440 | (struct blkif_request_segment) { | 466 | (struct blkif_request_segment) { |
441 | .gref = ref, | 467 | .gref = ref, |
@@ -790,9 +816,8 @@ static void blkif_restart_queue(struct work_struct *work) | |||
790 | 816 | ||
791 | static void blkif_free(struct blkfront_info *info, int suspend) | 817 | static void blkif_free(struct blkfront_info *info, int suspend) |
792 | { | 818 | { |
793 | struct llist_node *all_gnts; | 819 | struct grant *persistent_gnt; |
794 | struct grant *persistent_gnt, *tmp; | 820 | struct grant *n; |
795 | struct llist_node *n; | ||
796 | 821 | ||
797 | /* Prevent new requests being issued until we fix things up. */ | 822 | /* Prevent new requests being issued until we fix things up. */ |
798 | spin_lock_irq(&info->io_lock); | 823 | spin_lock_irq(&info->io_lock); |
@@ -803,22 +828,20 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
803 | blk_stop_queue(info->rq); | 828 | blk_stop_queue(info->rq); |
804 | 829 | ||
805 | /* Remove all persistent grants */ | 830 | /* Remove all persistent grants */ |
806 | if (info->persistent_gnts_c) { | 831 | if (!list_empty(&info->persistent_gnts)) { |
807 | all_gnts = llist_del_all(&info->persistent_gnts); | 832 | list_for_each_entry_safe(persistent_gnt, n, |
808 | persistent_gnt = llist_entry(all_gnts, typeof(*(persistent_gnt)), node); | 833 | &info->persistent_gnts, node) { |
809 | while (persistent_gnt) { | 834 | list_del(&persistent_gnt->node); |
810 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); | 835 | if (persistent_gnt->gref != GRANT_INVALID_REF) { |
836 | gnttab_end_foreign_access(persistent_gnt->gref, | ||
837 | 0, 0UL); | ||
838 | info->persistent_gnts_c--; | ||
839 | } | ||
811 | __free_page(pfn_to_page(persistent_gnt->pfn)); | 840 | __free_page(pfn_to_page(persistent_gnt->pfn)); |
812 | tmp = persistent_gnt; | 841 | kfree(persistent_gnt); |
813 | n = persistent_gnt->node.next; | ||
814 | if (n) | ||
815 | persistent_gnt = llist_entry(n, typeof(*(persistent_gnt)), node); | ||
816 | else | ||
817 | persistent_gnt = NULL; | ||
818 | kfree(tmp); | ||
819 | } | 842 | } |
820 | info->persistent_gnts_c = 0; | ||
821 | } | 843 | } |
844 | BUG_ON(info->persistent_gnts_c != 0); | ||
822 | 845 | ||
823 | /* No more gnttab callback work. */ | 846 | /* No more gnttab callback work. */ |
824 | gnttab_cancel_free_callback(&info->callback); | 847 | gnttab_cancel_free_callback(&info->callback); |
@@ -875,7 +898,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | |||
875 | } | 898 | } |
876 | /* Add the persistent grant into the list of free grants */ | 899 | /* Add the persistent grant into the list of free grants */ |
877 | for (i = 0; i < s->req.u.rw.nr_segments; i++) { | 900 | for (i = 0; i < s->req.u.rw.nr_segments; i++) { |
878 | llist_add(&s->grants_used[i]->node, &info->persistent_gnts); | 901 | list_add(&s->grants_used[i]->node, &info->persistent_gnts); |
879 | info->persistent_gnts_c++; | 902 | info->persistent_gnts_c++; |
880 | } | 903 | } |
881 | } | 904 | } |
@@ -1013,6 +1036,12 @@ static int setup_blkring(struct xenbus_device *dev, | |||
1013 | 1036 | ||
1014 | sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST); | 1037 | sg_init_table(info->sg, BLKIF_MAX_SEGMENTS_PER_REQUEST); |
1015 | 1038 | ||
1039 | /* Allocate memory for grants */ | ||
1040 | err = fill_grant_buffer(info, BLK_RING_SIZE * | ||
1041 | BLKIF_MAX_SEGMENTS_PER_REQUEST); | ||
1042 | if (err) | ||
1043 | goto fail; | ||
1044 | |||
1016 | err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); | 1045 | err = xenbus_grant_ring(dev, virt_to_mfn(info->ring.sring)); |
1017 | if (err < 0) { | 1046 | if (err < 0) { |
1018 | free_page((unsigned long)sring); | 1047 | free_page((unsigned long)sring); |
@@ -1171,7 +1200,7 @@ static int blkfront_probe(struct xenbus_device *dev, | |||
1171 | spin_lock_init(&info->io_lock); | 1200 | spin_lock_init(&info->io_lock); |
1172 | info->xbdev = dev; | 1201 | info->xbdev = dev; |
1173 | info->vdevice = vdevice; | 1202 | info->vdevice = vdevice; |
1174 | init_llist_head(&info->persistent_gnts); | 1203 | INIT_LIST_HEAD(&info->persistent_gnts); |
1175 | info->persistent_gnts_c = 0; | 1204 | info->persistent_gnts_c = 0; |
1176 | info->connected = BLKIF_STATE_DISCONNECTED; | 1205 | info->connected = BLKIF_STATE_DISCONNECTED; |
1177 | INIT_WORK(&info->work, blkif_restart_queue); | 1206 | INIT_WORK(&info->work, blkif_restart_queue); |
@@ -1203,11 +1232,10 @@ static int blkif_recover(struct blkfront_info *info) | |||
1203 | int j; | 1232 | int j; |
1204 | 1233 | ||
1205 | /* Stage 1: Make a safe copy of the shadow state. */ | 1234 | /* Stage 1: Make a safe copy of the shadow state. */ |
1206 | copy = kmalloc(sizeof(info->shadow), | 1235 | copy = kmemdup(info->shadow, sizeof(info->shadow), |
1207 | GFP_NOIO | __GFP_REPEAT | __GFP_HIGH); | 1236 | GFP_NOIO | __GFP_REPEAT | __GFP_HIGH); |
1208 | if (!copy) | 1237 | if (!copy) |
1209 | return -ENOMEM; | 1238 | return -ENOMEM; |
1210 | memcpy(copy, info->shadow, sizeof(info->shadow)); | ||
1211 | 1239 | ||
1212 | /* Stage 2: Set up free list. */ | 1240 | /* Stage 2: Set up free list. */ |
1213 | memset(&info->shadow, 0, sizeof(info->shadow)); | 1241 | memset(&info->shadow, 0, sizeof(info->shadow)); |
@@ -1236,7 +1264,7 @@ static int blkif_recover(struct blkfront_info *info) | |||
1236 | gnttab_grant_foreign_access_ref( | 1264 | gnttab_grant_foreign_access_ref( |
1237 | req->u.rw.seg[j].gref, | 1265 | req->u.rw.seg[j].gref, |
1238 | info->xbdev->otherend_id, | 1266 | info->xbdev->otherend_id, |
1239 | pfn_to_mfn(info->shadow[req->u.rw.id].frame[j]), | 1267 | pfn_to_mfn(copy[i].grants_used[j]->pfn), |
1240 | 0); | 1268 | 0); |
1241 | } | 1269 | } |
1242 | info->shadow[req->u.rw.id].req = *req; | 1270 | info->shadow[req->u.rw.id].req = *req; |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index a8a41e07a221..6aab00ef4379 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -73,9 +73,13 @@ static struct usb_device_id ath3k_table[] = { | |||
73 | { USB_DEVICE(0x03F0, 0x311D) }, | 73 | { USB_DEVICE(0x03F0, 0x311D) }, |
74 | 74 | ||
75 | /* Atheros AR3012 with sflash firmware*/ | 75 | /* Atheros AR3012 with sflash firmware*/ |
76 | { USB_DEVICE(0x0CF3, 0x0036) }, | ||
76 | { USB_DEVICE(0x0CF3, 0x3004) }, | 77 | { USB_DEVICE(0x0CF3, 0x3004) }, |
78 | { USB_DEVICE(0x0CF3, 0x3008) }, | ||
77 | { USB_DEVICE(0x0CF3, 0x311D) }, | 79 | { USB_DEVICE(0x0CF3, 0x311D) }, |
80 | { USB_DEVICE(0x0CF3, 0x817a) }, | ||
78 | { USB_DEVICE(0x13d3, 0x3375) }, | 81 | { USB_DEVICE(0x13d3, 0x3375) }, |
82 | { USB_DEVICE(0x04CA, 0x3004) }, | ||
79 | { USB_DEVICE(0x04CA, 0x3005) }, | 83 | { USB_DEVICE(0x04CA, 0x3005) }, |
80 | { USB_DEVICE(0x04CA, 0x3006) }, | 84 | { USB_DEVICE(0x04CA, 0x3006) }, |
81 | { USB_DEVICE(0x04CA, 0x3008) }, | 85 | { USB_DEVICE(0x04CA, 0x3008) }, |
@@ -105,9 +109,13 @@ MODULE_DEVICE_TABLE(usb, ath3k_table); | |||
105 | static struct usb_device_id ath3k_blist_tbl[] = { | 109 | static struct usb_device_id ath3k_blist_tbl[] = { |
106 | 110 | ||
107 | /* Atheros AR3012 with sflash firmware*/ | 111 | /* Atheros AR3012 with sflash firmware*/ |
112 | { USB_DEVICE(0x0CF3, 0x0036), .driver_info = BTUSB_ATH3012 }, | ||
108 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 113 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
114 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
109 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | 115 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, |
116 | { USB_DEVICE(0x0CF3, 0x817a), .driver_info = BTUSB_ATH3012 }, | ||
110 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 117 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
118 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||
111 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 119 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
112 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | 120 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, |
113 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | 121 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 7e351e345476..2cc5f774a29c 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -131,9 +131,13 @@ static struct usb_device_id blacklist_table[] = { | |||
131 | { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, | 131 | { USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE }, |
132 | 132 | ||
133 | /* Atheros 3012 with sflash firmware */ | 133 | /* Atheros 3012 with sflash firmware */ |
134 | { USB_DEVICE(0x0cf3, 0x0036), .driver_info = BTUSB_ATH3012 }, | ||
134 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, | 135 | { USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 }, |
136 | { USB_DEVICE(0x0cf3, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
135 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | 137 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x0cf3, 0x817a), .driver_info = BTUSB_ATH3012 }, | ||
136 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 139 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
140 | { USB_DEVICE(0x04ca, 0x3004), .driver_info = BTUSB_ATH3012 }, | ||
137 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 141 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | 142 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, |
139 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | 143 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c index 1bafb40ec8a2..69ae5972713c 100644 --- a/drivers/char/hw_random/core.c +++ b/drivers/char/hw_random/core.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/init.h> | 40 | #include <linux/init.h> |
41 | #include <linux/miscdevice.h> | 41 | #include <linux/miscdevice.h> |
42 | #include <linux/delay.h> | 42 | #include <linux/delay.h> |
43 | #include <linux/slab.h> | ||
43 | #include <asm/uaccess.h> | 44 | #include <asm/uaccess.h> |
44 | 45 | ||
45 | 46 | ||
@@ -52,8 +53,12 @@ static struct hwrng *current_rng; | |||
52 | static LIST_HEAD(rng_list); | 53 | static LIST_HEAD(rng_list); |
53 | static DEFINE_MUTEX(rng_mutex); | 54 | static DEFINE_MUTEX(rng_mutex); |
54 | static int data_avail; | 55 | static int data_avail; |
55 | static u8 rng_buffer[SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES] | 56 | static u8 *rng_buffer; |
56 | __cacheline_aligned; | 57 | |
58 | static size_t rng_buffer_size(void) | ||
59 | { | ||
60 | return SMP_CACHE_BYTES < 32 ? 32 : SMP_CACHE_BYTES; | ||
61 | } | ||
57 | 62 | ||
58 | static inline int hwrng_init(struct hwrng *rng) | 63 | static inline int hwrng_init(struct hwrng *rng) |
59 | { | 64 | { |
@@ -116,7 +121,7 @@ static ssize_t rng_dev_read(struct file *filp, char __user *buf, | |||
116 | 121 | ||
117 | if (!data_avail) { | 122 | if (!data_avail) { |
118 | bytes_read = rng_get_data(current_rng, rng_buffer, | 123 | bytes_read = rng_get_data(current_rng, rng_buffer, |
119 | sizeof(rng_buffer), | 124 | rng_buffer_size(), |
120 | !(filp->f_flags & O_NONBLOCK)); | 125 | !(filp->f_flags & O_NONBLOCK)); |
121 | if (bytes_read < 0) { | 126 | if (bytes_read < 0) { |
122 | err = bytes_read; | 127 | err = bytes_read; |
@@ -307,6 +312,14 @@ int hwrng_register(struct hwrng *rng) | |||
307 | 312 | ||
308 | mutex_lock(&rng_mutex); | 313 | mutex_lock(&rng_mutex); |
309 | 314 | ||
315 | /* kmalloc makes this safe for virt_to_page() in virtio_rng.c */ | ||
316 | err = -ENOMEM; | ||
317 | if (!rng_buffer) { | ||
318 | rng_buffer = kmalloc(rng_buffer_size(), GFP_KERNEL); | ||
319 | if (!rng_buffer) | ||
320 | goto out_unlock; | ||
321 | } | ||
322 | |||
310 | /* Must not register two RNGs with the same name. */ | 323 | /* Must not register two RNGs with the same name. */ |
311 | err = -EEXIST; | 324 | err = -EEXIST; |
312 | list_for_each_entry(tmp, &rng_list, list) { | 325 | list_for_each_entry(tmp, &rng_list, list) { |
diff --git a/drivers/char/hw_random/virtio-rng.c b/drivers/char/hw_random/virtio-rng.c index 10fd71ccf587..6bf4d47324eb 100644 --- a/drivers/char/hw_random/virtio-rng.c +++ b/drivers/char/hw_random/virtio-rng.c | |||
@@ -92,14 +92,22 @@ static int probe_common(struct virtio_device *vdev) | |||
92 | { | 92 | { |
93 | int err; | 93 | int err; |
94 | 94 | ||
95 | if (vq) { | ||
96 | /* We only support one device for now */ | ||
97 | return -EBUSY; | ||
98 | } | ||
95 | /* We expect a single virtqueue. */ | 99 | /* We expect a single virtqueue. */ |
96 | vq = virtio_find_single_vq(vdev, random_recv_done, "input"); | 100 | vq = virtio_find_single_vq(vdev, random_recv_done, "input"); |
97 | if (IS_ERR(vq)) | 101 | if (IS_ERR(vq)) { |
98 | return PTR_ERR(vq); | 102 | err = PTR_ERR(vq); |
103 | vq = NULL; | ||
104 | return err; | ||
105 | } | ||
99 | 106 | ||
100 | err = hwrng_register(&virtio_hwrng); | 107 | err = hwrng_register(&virtio_hwrng); |
101 | if (err) { | 108 | if (err) { |
102 | vdev->config->del_vqs(vdev); | 109 | vdev->config->del_vqs(vdev); |
110 | vq = NULL; | ||
103 | return err; | 111 | return err; |
104 | } | 112 | } |
105 | 113 | ||
@@ -112,6 +120,7 @@ static void remove_common(struct virtio_device *vdev) | |||
112 | busy = false; | 120 | busy = false; |
113 | hwrng_unregister(&virtio_hwrng); | 121 | hwrng_unregister(&virtio_hwrng); |
114 | vdev->config->del_vqs(vdev); | 122 | vdev->config->del_vqs(vdev); |
123 | vq = NULL; | ||
115 | } | 124 | } |
116 | 125 | ||
117 | static int virtrng_probe(struct virtio_device *vdev) | 126 | static int virtrng_probe(struct virtio_device *vdev) |
diff --git a/drivers/char/random.c b/drivers/char/random.c index 594bda9dcfc8..32a6c5764950 100644 --- a/drivers/char/random.c +++ b/drivers/char/random.c | |||
@@ -852,6 +852,7 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
852 | int reserved) | 852 | int reserved) |
853 | { | 853 | { |
854 | unsigned long flags; | 854 | unsigned long flags; |
855 | int wakeup_write = 0; | ||
855 | 856 | ||
856 | /* Hold lock while accounting */ | 857 | /* Hold lock while accounting */ |
857 | spin_lock_irqsave(&r->lock, flags); | 858 | spin_lock_irqsave(&r->lock, flags); |
@@ -873,10 +874,8 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
873 | else | 874 | else |
874 | r->entropy_count = reserved; | 875 | r->entropy_count = reserved; |
875 | 876 | ||
876 | if (r->entropy_count < random_write_wakeup_thresh) { | 877 | if (r->entropy_count < random_write_wakeup_thresh) |
877 | wake_up_interruptible(&random_write_wait); | 878 | wakeup_write = 1; |
878 | kill_fasync(&fasync, SIGIO, POLL_OUT); | ||
879 | } | ||
880 | } | 879 | } |
881 | 880 | ||
882 | DEBUG_ENT("debiting %zu entropy credits from %s%s\n", | 881 | DEBUG_ENT("debiting %zu entropy credits from %s%s\n", |
@@ -884,6 +883,11 @@ static size_t account(struct entropy_store *r, size_t nbytes, int min, | |||
884 | 883 | ||
885 | spin_unlock_irqrestore(&r->lock, flags); | 884 | spin_unlock_irqrestore(&r->lock, flags); |
886 | 885 | ||
886 | if (wakeup_write) { | ||
887 | wake_up_interruptible(&random_write_wait); | ||
888 | kill_fasync(&fasync, SIGIO, POLL_OUT); | ||
889 | } | ||
890 | |||
887 | return nbytes; | 891 | return nbytes; |
888 | } | 892 | } |
889 | 893 | ||
diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index a47e6ee98b8c..a64caefdba12 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig | |||
@@ -63,6 +63,14 @@ config CLK_TWL6040 | |||
63 | McPDM. McPDM module is using the external bit clock on the McPDM bus | 63 | McPDM. McPDM module is using the external bit clock on the McPDM bus |
64 | as functional clock. | 64 | as functional clock. |
65 | 65 | ||
66 | config COMMON_CLK_AXI_CLKGEN | ||
67 | tristate "AXI clkgen driver" | ||
68 | depends on ARCH_ZYNQ || MICROBLAZE | ||
69 | help | ||
70 | ---help--- | ||
71 | Support for the Analog Devices axi-clkgen pcore clock generator for Xilinx | ||
72 | FPGAs. It is commonly used in Analog Devices' reference designs. | ||
73 | |||
66 | endmenu | 74 | endmenu |
67 | 75 | ||
68 | source "drivers/clk/mvebu/Kconfig" | 76 | source "drivers/clk/mvebu/Kconfig" |
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index 300d4775d926..79e98e416724 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile | |||
@@ -7,6 +7,7 @@ obj-$(CONFIG_COMMON_CLK) += clk-fixed-factor.o | |||
7 | obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o | 7 | obj-$(CONFIG_COMMON_CLK) += clk-fixed-rate.o |
8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o | 8 | obj-$(CONFIG_COMMON_CLK) += clk-gate.o |
9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o | 9 | obj-$(CONFIG_COMMON_CLK) += clk-mux.o |
10 | obj-$(CONFIG_COMMON_CLK) += clk-composite.o | ||
10 | 11 | ||
11 | # SoCs specific | 12 | # SoCs specific |
12 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o | 13 | obj-$(CONFIG_ARCH_BCM2835) += clk-bcm2835.o |
@@ -23,6 +24,7 @@ ifeq ($(CONFIG_COMMON_CLK), y) | |||
23 | obj-$(CONFIG_ARCH_MMP) += mmp/ | 24 | obj-$(CONFIG_ARCH_MMP) += mmp/ |
24 | endif | 25 | endif |
25 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o | 26 | obj-$(CONFIG_MACH_LOONGSON1) += clk-ls1x.o |
27 | obj-$(CONFIG_ARCH_SUNXI) += sunxi/ | ||
26 | obj-$(CONFIG_ARCH_U8500) += ux500/ | 28 | obj-$(CONFIG_ARCH_U8500) += ux500/ |
27 | obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o | 29 | obj-$(CONFIG_ARCH_VT8500) += clk-vt8500.o |
28 | obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o | 30 | obj-$(CONFIG_ARCH_ZYNQ) += clk-zynq.o |
@@ -31,6 +33,7 @@ obj-$(CONFIG_ARCH_TEGRA) += tegra/ | |||
31 | obj-$(CONFIG_X86) += x86/ | 33 | obj-$(CONFIG_X86) += x86/ |
32 | 34 | ||
33 | # Chip specific | 35 | # Chip specific |
36 | obj-$(CONFIG_COMMON_CLK_AXI_CLKGEN) += clk-axi-clkgen.o | ||
34 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o | 37 | obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o |
35 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o | 38 | obj-$(CONFIG_COMMON_CLK_MAX77686) += clk-max77686.o |
36 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o | 39 | obj-$(CONFIG_CLK_TWL6040) += clk-twl6040.o |
diff --git a/drivers/clk/clk-axi-clkgen.c b/drivers/clk/clk-axi-clkgen.c new file mode 100644 index 000000000000..8137327847c3 --- /dev/null +++ b/drivers/clk/clk-axi-clkgen.c | |||
@@ -0,0 +1,331 @@ | |||
1 | /* | ||
2 | * AXI clkgen driver | ||
3 | * | ||
4 | * Copyright 2012-2013 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2. | ||
8 | * | ||
9 | */ | ||
10 | |||
11 | #include <linux/platform_device.h> | ||
12 | #include <linux/clk-provider.h> | ||
13 | #include <linux/clk.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/io.h> | ||
16 | #include <linux/of.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/err.h> | ||
19 | |||
20 | #define AXI_CLKGEN_REG_UPDATE_ENABLE 0x04 | ||
21 | #define AXI_CLKGEN_REG_CLK_OUT1 0x08 | ||
22 | #define AXI_CLKGEN_REG_CLK_OUT2 0x0c | ||
23 | #define AXI_CLKGEN_REG_CLK_DIV 0x10 | ||
24 | #define AXI_CLKGEN_REG_CLK_FB1 0x14 | ||
25 | #define AXI_CLKGEN_REG_CLK_FB2 0x18 | ||
26 | #define AXI_CLKGEN_REG_LOCK1 0x1c | ||
27 | #define AXI_CLKGEN_REG_LOCK2 0x20 | ||
28 | #define AXI_CLKGEN_REG_LOCK3 0x24 | ||
29 | #define AXI_CLKGEN_REG_FILTER1 0x28 | ||
30 | #define AXI_CLKGEN_REG_FILTER2 0x2c | ||
31 | |||
32 | struct axi_clkgen { | ||
33 | void __iomem *base; | ||
34 | struct clk_hw clk_hw; | ||
35 | }; | ||
36 | |||
37 | static uint32_t axi_clkgen_lookup_filter(unsigned int m) | ||
38 | { | ||
39 | switch (m) { | ||
40 | case 0: | ||
41 | return 0x01001990; | ||
42 | case 1: | ||
43 | return 0x01001190; | ||
44 | case 2: | ||
45 | return 0x01009890; | ||
46 | case 3: | ||
47 | return 0x01001890; | ||
48 | case 4: | ||
49 | return 0x01008890; | ||
50 | case 5 ... 8: | ||
51 | return 0x01009090; | ||
52 | case 9 ... 11: | ||
53 | return 0x01000890; | ||
54 | case 12: | ||
55 | return 0x08009090; | ||
56 | case 13 ... 22: | ||
57 | return 0x01001090; | ||
58 | case 23 ... 36: | ||
59 | return 0x01008090; | ||
60 | case 37 ... 46: | ||
61 | return 0x08001090; | ||
62 | default: | ||
63 | return 0x08008090; | ||
64 | } | ||
65 | } | ||
66 | |||
67 | static const uint32_t axi_clkgen_lock_table[] = { | ||
68 | 0x060603e8, 0x060603e8, 0x080803e8, 0x0b0b03e8, | ||
69 | 0x0e0e03e8, 0x111103e8, 0x131303e8, 0x161603e8, | ||
70 | 0x191903e8, 0x1c1c03e8, 0x1f1f0384, 0x1f1f0339, | ||
71 | 0x1f1f02ee, 0x1f1f02bc, 0x1f1f028a, 0x1f1f0271, | ||
72 | 0x1f1f023f, 0x1f1f0226, 0x1f1f020d, 0x1f1f01f4, | ||
73 | 0x1f1f01db, 0x1f1f01c2, 0x1f1f01a9, 0x1f1f0190, | ||
74 | 0x1f1f0190, 0x1f1f0177, 0x1f1f015e, 0x1f1f015e, | ||
75 | 0x1f1f0145, 0x1f1f0145, 0x1f1f012c, 0x1f1f012c, | ||
76 | 0x1f1f012c, 0x1f1f0113, 0x1f1f0113, 0x1f1f0113, | ||
77 | }; | ||
78 | |||
79 | static uint32_t axi_clkgen_lookup_lock(unsigned int m) | ||
80 | { | ||
81 | if (m < ARRAY_SIZE(axi_clkgen_lock_table)) | ||
82 | return axi_clkgen_lock_table[m]; | ||
83 | return 0x1f1f00fa; | ||
84 | } | ||
85 | |||
86 | static const unsigned int fpfd_min = 10000; | ||
87 | static const unsigned int fpfd_max = 300000; | ||
88 | static const unsigned int fvco_min = 600000; | ||
89 | static const unsigned int fvco_max = 1200000; | ||
90 | |||
91 | static void axi_clkgen_calc_params(unsigned long fin, unsigned long fout, | ||
92 | unsigned int *best_d, unsigned int *best_m, unsigned int *best_dout) | ||
93 | { | ||
94 | unsigned long d, d_min, d_max, _d_min, _d_max; | ||
95 | unsigned long m, m_min, m_max; | ||
96 | unsigned long f, dout, best_f, fvco; | ||
97 | |||
98 | fin /= 1000; | ||
99 | fout /= 1000; | ||
100 | |||
101 | best_f = ULONG_MAX; | ||
102 | *best_d = 0; | ||
103 | *best_m = 0; | ||
104 | *best_dout = 0; | ||
105 | |||
106 | d_min = max_t(unsigned long, DIV_ROUND_UP(fin, fpfd_max), 1); | ||
107 | d_max = min_t(unsigned long, fin / fpfd_min, 80); | ||
108 | |||
109 | m_min = max_t(unsigned long, DIV_ROUND_UP(fvco_min, fin) * d_min, 1); | ||
110 | m_max = min_t(unsigned long, fvco_max * d_max / fin, 64); | ||
111 | |||
112 | for (m = m_min; m <= m_max; m++) { | ||
113 | _d_min = max(d_min, DIV_ROUND_UP(fin * m, fvco_max)); | ||
114 | _d_max = min(d_max, fin * m / fvco_min); | ||
115 | |||
116 | for (d = _d_min; d <= _d_max; d++) { | ||
117 | fvco = fin * m / d; | ||
118 | |||
119 | dout = DIV_ROUND_CLOSEST(fvco, fout); | ||
120 | dout = clamp_t(unsigned long, dout, 1, 128); | ||
121 | f = fvco / dout; | ||
122 | if (abs(f - fout) < abs(best_f - fout)) { | ||
123 | best_f = f; | ||
124 | *best_d = d; | ||
125 | *best_m = m; | ||
126 | *best_dout = dout; | ||
127 | if (best_f == fout) | ||
128 | return; | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | } | ||
133 | |||
134 | static void axi_clkgen_calc_clk_params(unsigned int divider, unsigned int *low, | ||
135 | unsigned int *high, unsigned int *edge, unsigned int *nocount) | ||
136 | { | ||
137 | if (divider == 1) | ||
138 | *nocount = 1; | ||
139 | else | ||
140 | *nocount = 0; | ||
141 | |||
142 | *high = divider / 2; | ||
143 | *edge = divider % 2; | ||
144 | *low = divider - *high; | ||
145 | } | ||
146 | |||
147 | static void axi_clkgen_write(struct axi_clkgen *axi_clkgen, | ||
148 | unsigned int reg, unsigned int val) | ||
149 | { | ||
150 | writel(val, axi_clkgen->base + reg); | ||
151 | } | ||
152 | |||
153 | static void axi_clkgen_read(struct axi_clkgen *axi_clkgen, | ||
154 | unsigned int reg, unsigned int *val) | ||
155 | { | ||
156 | *val = readl(axi_clkgen->base + reg); | ||
157 | } | ||
158 | |||
159 | static struct axi_clkgen *clk_hw_to_axi_clkgen(struct clk_hw *clk_hw) | ||
160 | { | ||
161 | return container_of(clk_hw, struct axi_clkgen, clk_hw); | ||
162 | } | ||
163 | |||
164 | static int axi_clkgen_set_rate(struct clk_hw *clk_hw, | ||
165 | unsigned long rate, unsigned long parent_rate) | ||
166 | { | ||
167 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
168 | unsigned int d, m, dout; | ||
169 | unsigned int nocount; | ||
170 | unsigned int high; | ||
171 | unsigned int edge; | ||
172 | unsigned int low; | ||
173 | uint32_t filter; | ||
174 | uint32_t lock; | ||
175 | |||
176 | if (parent_rate == 0 || rate == 0) | ||
177 | return -EINVAL; | ||
178 | |||
179 | axi_clkgen_calc_params(parent_rate, rate, &d, &m, &dout); | ||
180 | |||
181 | if (d == 0 || dout == 0 || m == 0) | ||
182 | return -EINVAL; | ||
183 | |||
184 | filter = axi_clkgen_lookup_filter(m - 1); | ||
185 | lock = axi_clkgen_lookup_lock(m - 1); | ||
186 | |||
187 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 0); | ||
188 | |||
189 | axi_clkgen_calc_clk_params(dout, &low, &high, &edge, &nocount); | ||
190 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, | ||
191 | (high << 6) | low); | ||
192 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT2, | ||
193 | (edge << 7) | (nocount << 6)); | ||
194 | |||
195 | axi_clkgen_calc_clk_params(d, &low, &high, &edge, &nocount); | ||
196 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, | ||
197 | (edge << 13) | (nocount << 12) | (high << 6) | low); | ||
198 | |||
199 | axi_clkgen_calc_clk_params(m, &low, &high, &edge, &nocount); | ||
200 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, | ||
201 | (high << 6) | low); | ||
202 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_CLK_FB2, | ||
203 | (edge << 7) | (nocount << 6)); | ||
204 | |||
205 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK1, lock & 0x3ff); | ||
206 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK2, | ||
207 | (((lock >> 16) & 0x1f) << 10) | 0x1); | ||
208 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_LOCK3, | ||
209 | (((lock >> 24) & 0x1f) << 10) | 0x3e9); | ||
210 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER1, filter >> 16); | ||
211 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_FILTER2, filter); | ||
212 | |||
213 | axi_clkgen_write(axi_clkgen, AXI_CLKGEN_REG_UPDATE_ENABLE, 1); | ||
214 | |||
215 | return 0; | ||
216 | } | ||
217 | |||
218 | static long axi_clkgen_round_rate(struct clk_hw *hw, unsigned long rate, | ||
219 | unsigned long *parent_rate) | ||
220 | { | ||
221 | unsigned int d, m, dout; | ||
222 | |||
223 | axi_clkgen_calc_params(*parent_rate, rate, &d, &m, &dout); | ||
224 | |||
225 | if (d == 0 || dout == 0 || m == 0) | ||
226 | return -EINVAL; | ||
227 | |||
228 | return *parent_rate / d * m / dout; | ||
229 | } | ||
230 | |||
231 | static unsigned long axi_clkgen_recalc_rate(struct clk_hw *clk_hw, | ||
232 | unsigned long parent_rate) | ||
233 | { | ||
234 | struct axi_clkgen *axi_clkgen = clk_hw_to_axi_clkgen(clk_hw); | ||
235 | unsigned int d, m, dout; | ||
236 | unsigned int reg; | ||
237 | unsigned long long tmp; | ||
238 | |||
239 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_OUT1, ®); | ||
240 | dout = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
241 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_DIV, ®); | ||
242 | d = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
243 | axi_clkgen_read(axi_clkgen, AXI_CLKGEN_REG_CLK_FB1, ®); | ||
244 | m = (reg & 0x3f) + ((reg >> 6) & 0x3f); | ||
245 | |||
246 | if (d == 0 || dout == 0) | ||
247 | return 0; | ||
248 | |||
249 | tmp = (unsigned long long)(parent_rate / d) * m; | ||
250 | do_div(tmp, dout); | ||
251 | |||
252 | if (tmp > ULONG_MAX) | ||
253 | return ULONG_MAX; | ||
254 | |||
255 | return tmp; | ||
256 | } | ||
257 | |||
258 | static const struct clk_ops axi_clkgen_ops = { | ||
259 | .recalc_rate = axi_clkgen_recalc_rate, | ||
260 | .round_rate = axi_clkgen_round_rate, | ||
261 | .set_rate = axi_clkgen_set_rate, | ||
262 | }; | ||
263 | |||
264 | static int axi_clkgen_probe(struct platform_device *pdev) | ||
265 | { | ||
266 | struct axi_clkgen *axi_clkgen; | ||
267 | struct clk_init_data init; | ||
268 | const char *parent_name; | ||
269 | const char *clk_name; | ||
270 | struct resource *mem; | ||
271 | struct clk *clk; | ||
272 | |||
273 | axi_clkgen = devm_kzalloc(&pdev->dev, sizeof(*axi_clkgen), GFP_KERNEL); | ||
274 | if (!axi_clkgen) | ||
275 | return -ENOMEM; | ||
276 | |||
277 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
278 | axi_clkgen->base = devm_ioremap_resource(&pdev->dev, mem); | ||
279 | if (IS_ERR(axi_clkgen->base)) | ||
280 | return PTR_ERR(axi_clkgen->base); | ||
281 | |||
282 | parent_name = of_clk_get_parent_name(pdev->dev.of_node, 0); | ||
283 | if (!parent_name) | ||
284 | return -EINVAL; | ||
285 | |||
286 | clk_name = pdev->dev.of_node->name; | ||
287 | of_property_read_string(pdev->dev.of_node, "clock-output-names", | ||
288 | &clk_name); | ||
289 | |||
290 | init.name = clk_name; | ||
291 | init.ops = &axi_clkgen_ops; | ||
292 | init.flags = 0; | ||
293 | init.parent_names = &parent_name; | ||
294 | init.num_parents = 1; | ||
295 | |||
296 | axi_clkgen->clk_hw.init = &init; | ||
297 | clk = devm_clk_register(&pdev->dev, &axi_clkgen->clk_hw); | ||
298 | if (IS_ERR(clk)) | ||
299 | return PTR_ERR(clk); | ||
300 | |||
301 | return of_clk_add_provider(pdev->dev.of_node, of_clk_src_simple_get, | ||
302 | clk); | ||
303 | } | ||
304 | |||
305 | static int axi_clkgen_remove(struct platform_device *pdev) | ||
306 | { | ||
307 | of_clk_del_provider(pdev->dev.of_node); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | static const struct of_device_id axi_clkgen_ids[] = { | ||
313 | { .compatible = "adi,axi-clkgen-1.00.a" }, | ||
314 | { }, | ||
315 | }; | ||
316 | MODULE_DEVICE_TABLE(of, axi_clkgen_ids); | ||
317 | |||
318 | static struct platform_driver axi_clkgen_driver = { | ||
319 | .driver = { | ||
320 | .name = "adi-axi-clkgen", | ||
321 | .owner = THIS_MODULE, | ||
322 | .of_match_table = axi_clkgen_ids, | ||
323 | }, | ||
324 | .probe = axi_clkgen_probe, | ||
325 | .remove = axi_clkgen_remove, | ||
326 | }; | ||
327 | module_platform_driver(axi_clkgen_driver); | ||
328 | |||
329 | MODULE_LICENSE("GPL v2"); | ||
330 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
331 | MODULE_DESCRIPTION("Driver for the Analog Devices' AXI clkgen pcore clock generator"); | ||
diff --git a/drivers/clk/clk-composite.c b/drivers/clk/clk-composite.c new file mode 100644 index 000000000000..097dee4fd209 --- /dev/null +++ b/drivers/clk/clk-composite.c | |||
@@ -0,0 +1,201 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2013 NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk.h> | ||
18 | #include <linux/clk-provider.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #define to_clk_composite(_hw) container_of(_hw, struct clk_composite, hw) | ||
23 | |||
24 | static u8 clk_composite_get_parent(struct clk_hw *hw) | ||
25 | { | ||
26 | struct clk_composite *composite = to_clk_composite(hw); | ||
27 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
28 | struct clk_hw *mux_hw = composite->mux_hw; | ||
29 | |||
30 | mux_hw->clk = hw->clk; | ||
31 | |||
32 | return mux_ops->get_parent(mux_hw); | ||
33 | } | ||
34 | |||
35 | static int clk_composite_set_parent(struct clk_hw *hw, u8 index) | ||
36 | { | ||
37 | struct clk_composite *composite = to_clk_composite(hw); | ||
38 | const struct clk_ops *mux_ops = composite->mux_ops; | ||
39 | struct clk_hw *mux_hw = composite->mux_hw; | ||
40 | |||
41 | mux_hw->clk = hw->clk; | ||
42 | |||
43 | return mux_ops->set_parent(mux_hw, index); | ||
44 | } | ||
45 | |||
46 | static unsigned long clk_composite_recalc_rate(struct clk_hw *hw, | ||
47 | unsigned long parent_rate) | ||
48 | { | ||
49 | struct clk_composite *composite = to_clk_composite(hw); | ||
50 | const struct clk_ops *div_ops = composite->div_ops; | ||
51 | struct clk_hw *div_hw = composite->div_hw; | ||
52 | |||
53 | div_hw->clk = hw->clk; | ||
54 | |||
55 | return div_ops->recalc_rate(div_hw, parent_rate); | ||
56 | } | ||
57 | |||
58 | static long clk_composite_round_rate(struct clk_hw *hw, unsigned long rate, | ||
59 | unsigned long *prate) | ||
60 | { | ||
61 | struct clk_composite *composite = to_clk_composite(hw); | ||
62 | const struct clk_ops *div_ops = composite->div_ops; | ||
63 | struct clk_hw *div_hw = composite->div_hw; | ||
64 | |||
65 | div_hw->clk = hw->clk; | ||
66 | |||
67 | return div_ops->round_rate(div_hw, rate, prate); | ||
68 | } | ||
69 | |||
70 | static int clk_composite_set_rate(struct clk_hw *hw, unsigned long rate, | ||
71 | unsigned long parent_rate) | ||
72 | { | ||
73 | struct clk_composite *composite = to_clk_composite(hw); | ||
74 | const struct clk_ops *div_ops = composite->div_ops; | ||
75 | struct clk_hw *div_hw = composite->div_hw; | ||
76 | |||
77 | div_hw->clk = hw->clk; | ||
78 | |||
79 | return div_ops->set_rate(div_hw, rate, parent_rate); | ||
80 | } | ||
81 | |||
82 | static int clk_composite_is_enabled(struct clk_hw *hw) | ||
83 | { | ||
84 | struct clk_composite *composite = to_clk_composite(hw); | ||
85 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
86 | struct clk_hw *gate_hw = composite->gate_hw; | ||
87 | |||
88 | gate_hw->clk = hw->clk; | ||
89 | |||
90 | return gate_ops->is_enabled(gate_hw); | ||
91 | } | ||
92 | |||
93 | static int clk_composite_enable(struct clk_hw *hw) | ||
94 | { | ||
95 | struct clk_composite *composite = to_clk_composite(hw); | ||
96 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
97 | struct clk_hw *gate_hw = composite->gate_hw; | ||
98 | |||
99 | gate_hw->clk = hw->clk; | ||
100 | |||
101 | return gate_ops->enable(gate_hw); | ||
102 | } | ||
103 | |||
104 | static void clk_composite_disable(struct clk_hw *hw) | ||
105 | { | ||
106 | struct clk_composite *composite = to_clk_composite(hw); | ||
107 | const struct clk_ops *gate_ops = composite->gate_ops; | ||
108 | struct clk_hw *gate_hw = composite->gate_hw; | ||
109 | |||
110 | gate_hw->clk = hw->clk; | ||
111 | |||
112 | gate_ops->disable(gate_hw); | ||
113 | } | ||
114 | |||
115 | struct clk *clk_register_composite(struct device *dev, const char *name, | ||
116 | const char **parent_names, int num_parents, | ||
117 | struct clk_hw *mux_hw, const struct clk_ops *mux_ops, | ||
118 | struct clk_hw *div_hw, const struct clk_ops *div_ops, | ||
119 | struct clk_hw *gate_hw, const struct clk_ops *gate_ops, | ||
120 | unsigned long flags) | ||
121 | { | ||
122 | struct clk *clk; | ||
123 | struct clk_init_data init; | ||
124 | struct clk_composite *composite; | ||
125 | struct clk_ops *clk_composite_ops; | ||
126 | |||
127 | composite = kzalloc(sizeof(*composite), GFP_KERNEL); | ||
128 | if (!composite) { | ||
129 | pr_err("%s: could not allocate composite clk\n", __func__); | ||
130 | return ERR_PTR(-ENOMEM); | ||
131 | } | ||
132 | |||
133 | init.name = name; | ||
134 | init.flags = flags | CLK_IS_BASIC; | ||
135 | init.parent_names = parent_names; | ||
136 | init.num_parents = num_parents; | ||
137 | |||
138 | clk_composite_ops = &composite->ops; | ||
139 | |||
140 | if (mux_hw && mux_ops) { | ||
141 | if (!mux_ops->get_parent || !mux_ops->set_parent) { | ||
142 | clk = ERR_PTR(-EINVAL); | ||
143 | goto err; | ||
144 | } | ||
145 | |||
146 | composite->mux_hw = mux_hw; | ||
147 | composite->mux_ops = mux_ops; | ||
148 | clk_composite_ops->get_parent = clk_composite_get_parent; | ||
149 | clk_composite_ops->set_parent = clk_composite_set_parent; | ||
150 | } | ||
151 | |||
152 | if (div_hw && div_ops) { | ||
153 | if (!div_ops->recalc_rate || !div_ops->round_rate || | ||
154 | !div_ops->set_rate) { | ||
155 | clk = ERR_PTR(-EINVAL); | ||
156 | goto err; | ||
157 | } | ||
158 | |||
159 | composite->div_hw = div_hw; | ||
160 | composite->div_ops = div_ops; | ||
161 | clk_composite_ops->recalc_rate = clk_composite_recalc_rate; | ||
162 | clk_composite_ops->round_rate = clk_composite_round_rate; | ||
163 | clk_composite_ops->set_rate = clk_composite_set_rate; | ||
164 | } | ||
165 | |||
166 | if (gate_hw && gate_ops) { | ||
167 | if (!gate_ops->is_enabled || !gate_ops->enable || | ||
168 | !gate_ops->disable) { | ||
169 | clk = ERR_PTR(-EINVAL); | ||
170 | goto err; | ||
171 | } | ||
172 | |||
173 | composite->gate_hw = gate_hw; | ||
174 | composite->gate_ops = gate_ops; | ||
175 | clk_composite_ops->is_enabled = clk_composite_is_enabled; | ||
176 | clk_composite_ops->enable = clk_composite_enable; | ||
177 | clk_composite_ops->disable = clk_composite_disable; | ||
178 | } | ||
179 | |||
180 | init.ops = clk_composite_ops; | ||
181 | composite->hw.init = &init; | ||
182 | |||
183 | clk = clk_register(dev, &composite->hw); | ||
184 | if (IS_ERR(clk)) | ||
185 | goto err; | ||
186 | |||
187 | if (composite->mux_hw) | ||
188 | composite->mux_hw->clk = clk; | ||
189 | |||
190 | if (composite->div_hw) | ||
191 | composite->div_hw->clk = clk; | ||
192 | |||
193 | if (composite->gate_hw) | ||
194 | composite->gate_hw->clk = clk; | ||
195 | |||
196 | return clk; | ||
197 | |||
198 | err: | ||
199 | kfree(composite); | ||
200 | return clk; | ||
201 | } | ||
diff --git a/drivers/clk/clk-mux.c b/drivers/clk/clk-mux.c index 508c032edce4..25b1734560d0 100644 --- a/drivers/clk/clk-mux.c +++ b/drivers/clk/clk-mux.c | |||
@@ -32,6 +32,7 @@ | |||
32 | static u8 clk_mux_get_parent(struct clk_hw *hw) | 32 | static u8 clk_mux_get_parent(struct clk_hw *hw) |
33 | { | 33 | { |
34 | struct clk_mux *mux = to_clk_mux(hw); | 34 | struct clk_mux *mux = to_clk_mux(hw); |
35 | int num_parents = __clk_get_num_parents(hw->clk); | ||
35 | u32 val; | 36 | u32 val; |
36 | 37 | ||
37 | /* | 38 | /* |
@@ -42,7 +43,16 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) | |||
42 | * val = 0x4 really means "bit 2, index starts at bit 0" | 43 | * val = 0x4 really means "bit 2, index starts at bit 0" |
43 | */ | 44 | */ |
44 | val = readl(mux->reg) >> mux->shift; | 45 | val = readl(mux->reg) >> mux->shift; |
45 | val &= (1 << mux->width) - 1; | 46 | val &= mux->mask; |
47 | |||
48 | if (mux->table) { | ||
49 | int i; | ||
50 | |||
51 | for (i = 0; i < num_parents; i++) | ||
52 | if (mux->table[i] == val) | ||
53 | return i; | ||
54 | return -EINVAL; | ||
55 | } | ||
46 | 56 | ||
47 | if (val && (mux->flags & CLK_MUX_INDEX_BIT)) | 57 | if (val && (mux->flags & CLK_MUX_INDEX_BIT)) |
48 | val = ffs(val) - 1; | 58 | val = ffs(val) - 1; |
@@ -50,7 +60,7 @@ static u8 clk_mux_get_parent(struct clk_hw *hw) | |||
50 | if (val && (mux->flags & CLK_MUX_INDEX_ONE)) | 60 | if (val && (mux->flags & CLK_MUX_INDEX_ONE)) |
51 | val--; | 61 | val--; |
52 | 62 | ||
53 | if (val >= __clk_get_num_parents(hw->clk)) | 63 | if (val >= num_parents) |
54 | return -EINVAL; | 64 | return -EINVAL; |
55 | 65 | ||
56 | return val; | 66 | return val; |
@@ -62,17 +72,22 @@ static int clk_mux_set_parent(struct clk_hw *hw, u8 index) | |||
62 | u32 val; | 72 | u32 val; |
63 | unsigned long flags = 0; | 73 | unsigned long flags = 0; |
64 | 74 | ||
65 | if (mux->flags & CLK_MUX_INDEX_BIT) | 75 | if (mux->table) |
66 | index = (1 << ffs(index)); | 76 | index = mux->table[index]; |
67 | 77 | ||
68 | if (mux->flags & CLK_MUX_INDEX_ONE) | 78 | else { |
69 | index++; | 79 | if (mux->flags & CLK_MUX_INDEX_BIT) |
80 | index = (1 << ffs(index)); | ||
81 | |||
82 | if (mux->flags & CLK_MUX_INDEX_ONE) | ||
83 | index++; | ||
84 | } | ||
70 | 85 | ||
71 | if (mux->lock) | 86 | if (mux->lock) |
72 | spin_lock_irqsave(mux->lock, flags); | 87 | spin_lock_irqsave(mux->lock, flags); |
73 | 88 | ||
74 | val = readl(mux->reg); | 89 | val = readl(mux->reg); |
75 | val &= ~(((1 << mux->width) - 1) << mux->shift); | 90 | val &= ~(mux->mask << mux->shift); |
76 | val |= index << mux->shift; | 91 | val |= index << mux->shift; |
77 | writel(val, mux->reg); | 92 | writel(val, mux->reg); |
78 | 93 | ||
@@ -88,10 +103,10 @@ const struct clk_ops clk_mux_ops = { | |||
88 | }; | 103 | }; |
89 | EXPORT_SYMBOL_GPL(clk_mux_ops); | 104 | EXPORT_SYMBOL_GPL(clk_mux_ops); |
90 | 105 | ||
91 | struct clk *clk_register_mux(struct device *dev, const char *name, | 106 | struct clk *clk_register_mux_table(struct device *dev, const char *name, |
92 | const char **parent_names, u8 num_parents, unsigned long flags, | 107 | const char **parent_names, u8 num_parents, unsigned long flags, |
93 | void __iomem *reg, u8 shift, u8 width, | 108 | void __iomem *reg, u8 shift, u32 mask, |
94 | u8 clk_mux_flags, spinlock_t *lock) | 109 | u8 clk_mux_flags, u32 *table, spinlock_t *lock) |
95 | { | 110 | { |
96 | struct clk_mux *mux; | 111 | struct clk_mux *mux; |
97 | struct clk *clk; | 112 | struct clk *clk; |
@@ -113,9 +128,10 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
113 | /* struct clk_mux assignments */ | 128 | /* struct clk_mux assignments */ |
114 | mux->reg = reg; | 129 | mux->reg = reg; |
115 | mux->shift = shift; | 130 | mux->shift = shift; |
116 | mux->width = width; | 131 | mux->mask = mask; |
117 | mux->flags = clk_mux_flags; | 132 | mux->flags = clk_mux_flags; |
118 | mux->lock = lock; | 133 | mux->lock = lock; |
134 | mux->table = table; | ||
119 | mux->hw.init = &init; | 135 | mux->hw.init = &init; |
120 | 136 | ||
121 | clk = clk_register(dev, &mux->hw); | 137 | clk = clk_register(dev, &mux->hw); |
@@ -125,3 +141,15 @@ struct clk *clk_register_mux(struct device *dev, const char *name, | |||
125 | 141 | ||
126 | return clk; | 142 | return clk; |
127 | } | 143 | } |
144 | |||
145 | struct clk *clk_register_mux(struct device *dev, const char *name, | ||
146 | const char **parent_names, u8 num_parents, unsigned long flags, | ||
147 | void __iomem *reg, u8 shift, u8 width, | ||
148 | u8 clk_mux_flags, spinlock_t *lock) | ||
149 | { | ||
150 | u32 mask = BIT(width) - 1; | ||
151 | |||
152 | return clk_register_mux_table(dev, name, parent_names, num_parents, | ||
153 | flags, reg, shift, mask, clk_mux_flags, | ||
154 | NULL, lock); | ||
155 | } | ||
diff --git a/drivers/clk/clk-prima2.c b/drivers/clk/clk-prima2.c index f8e9d0c27be2..643ca653fef0 100644 --- a/drivers/clk/clk-prima2.c +++ b/drivers/clk/clk-prima2.c | |||
@@ -1113,7 +1113,7 @@ void __init sirfsoc_of_clk_init(void) | |||
1113 | 1113 | ||
1114 | for (i = pll1; i < maxclk; i++) { | 1114 | for (i = pll1; i < maxclk; i++) { |
1115 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); | 1115 | prima2_clks[i] = clk_register(NULL, prima2_clk_hw_array[i]); |
1116 | BUG_ON(!prima2_clks[i]); | 1116 | BUG_ON(IS_ERR(prima2_clks[i])); |
1117 | } | 1117 | } |
1118 | clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); | 1118 | clk_register_clkdev(prima2_clks[cpu], NULL, "cpu"); |
1119 | clk_register_clkdev(prima2_clks[io], NULL, "io"); | 1119 | clk_register_clkdev(prima2_clks[io], NULL, "io"); |
diff --git a/drivers/clk/clk-vt8500.c b/drivers/clk/clk-vt8500.c index b5538bba7a10..09c63315e579 100644 --- a/drivers/clk/clk-vt8500.c +++ b/drivers/clk/clk-vt8500.c | |||
@@ -157,7 +157,7 @@ static int vt8500_dclk_set_rate(struct clk_hw *hw, unsigned long rate, | |||
157 | divisor = parent_rate / rate; | 157 | divisor = parent_rate / rate; |
158 | 158 | ||
159 | /* If prate / rate would be decimal, incr the divisor */ | 159 | /* If prate / rate would be decimal, incr the divisor */ |
160 | if (rate * divisor < *prate) | 160 | if (rate * divisor < parent_rate) |
161 | divisor++; | 161 | divisor++; |
162 | 162 | ||
163 | if (divisor == cdev->div_mask + 1) | 163 | if (divisor == cdev->div_mask + 1) |
diff --git a/drivers/clk/clk-zynq.c b/drivers/clk/clk-zynq.c index b14a25f39255..32062977f453 100644 --- a/drivers/clk/clk-zynq.c +++ b/drivers/clk/clk-zynq.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/clk-provider.h> | 22 | #include <linux/clk-provider.h> |
23 | #include <linux/clk/zynq.h> | ||
23 | 24 | ||
24 | static void __iomem *slcr_base; | 25 | static void __iomem *slcr_base; |
25 | 26 | ||
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index ed87b2405806..0230c9d95975 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c | |||
@@ -19,14 +19,77 @@ | |||
19 | #include <linux/of.h> | 19 | #include <linux/of.h> |
20 | #include <linux/device.h> | 20 | #include <linux/device.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/sched.h> | ||
22 | 23 | ||
23 | static DEFINE_SPINLOCK(enable_lock); | 24 | static DEFINE_SPINLOCK(enable_lock); |
24 | static DEFINE_MUTEX(prepare_lock); | 25 | static DEFINE_MUTEX(prepare_lock); |
25 | 26 | ||
27 | static struct task_struct *prepare_owner; | ||
28 | static struct task_struct *enable_owner; | ||
29 | |||
30 | static int prepare_refcnt; | ||
31 | static int enable_refcnt; | ||
32 | |||
26 | static HLIST_HEAD(clk_root_list); | 33 | static HLIST_HEAD(clk_root_list); |
27 | static HLIST_HEAD(clk_orphan_list); | 34 | static HLIST_HEAD(clk_orphan_list); |
28 | static LIST_HEAD(clk_notifier_list); | 35 | static LIST_HEAD(clk_notifier_list); |
29 | 36 | ||
37 | /*** locking ***/ | ||
38 | static void clk_prepare_lock(void) | ||
39 | { | ||
40 | if (!mutex_trylock(&prepare_lock)) { | ||
41 | if (prepare_owner == current) { | ||
42 | prepare_refcnt++; | ||
43 | return; | ||
44 | } | ||
45 | mutex_lock(&prepare_lock); | ||
46 | } | ||
47 | WARN_ON_ONCE(prepare_owner != NULL); | ||
48 | WARN_ON_ONCE(prepare_refcnt != 0); | ||
49 | prepare_owner = current; | ||
50 | prepare_refcnt = 1; | ||
51 | } | ||
52 | |||
53 | static void clk_prepare_unlock(void) | ||
54 | { | ||
55 | WARN_ON_ONCE(prepare_owner != current); | ||
56 | WARN_ON_ONCE(prepare_refcnt == 0); | ||
57 | |||
58 | if (--prepare_refcnt) | ||
59 | return; | ||
60 | prepare_owner = NULL; | ||
61 | mutex_unlock(&prepare_lock); | ||
62 | } | ||
63 | |||
64 | static unsigned long clk_enable_lock(void) | ||
65 | { | ||
66 | unsigned long flags; | ||
67 | |||
68 | if (!spin_trylock_irqsave(&enable_lock, flags)) { | ||
69 | if (enable_owner == current) { | ||
70 | enable_refcnt++; | ||
71 | return flags; | ||
72 | } | ||
73 | spin_lock_irqsave(&enable_lock, flags); | ||
74 | } | ||
75 | WARN_ON_ONCE(enable_owner != NULL); | ||
76 | WARN_ON_ONCE(enable_refcnt != 0); | ||
77 | enable_owner = current; | ||
78 | enable_refcnt = 1; | ||
79 | return flags; | ||
80 | } | ||
81 | |||
82 | static void clk_enable_unlock(unsigned long flags) | ||
83 | { | ||
84 | WARN_ON_ONCE(enable_owner != current); | ||
85 | WARN_ON_ONCE(enable_refcnt == 0); | ||
86 | |||
87 | if (--enable_refcnt) | ||
88 | return; | ||
89 | enable_owner = NULL; | ||
90 | spin_unlock_irqrestore(&enable_lock, flags); | ||
91 | } | ||
92 | |||
30 | /*** debugfs support ***/ | 93 | /*** debugfs support ***/ |
31 | 94 | ||
32 | #ifdef CONFIG_COMMON_CLK_DEBUG | 95 | #ifdef CONFIG_COMMON_CLK_DEBUG |
@@ -69,7 +132,7 @@ static int clk_summary_show(struct seq_file *s, void *data) | |||
69 | seq_printf(s, " clock enable_cnt prepare_cnt rate\n"); | 132 | seq_printf(s, " clock enable_cnt prepare_cnt rate\n"); |
70 | seq_printf(s, "---------------------------------------------------------------------\n"); | 133 | seq_printf(s, "---------------------------------------------------------------------\n"); |
71 | 134 | ||
72 | mutex_lock(&prepare_lock); | 135 | clk_prepare_lock(); |
73 | 136 | ||
74 | hlist_for_each_entry(c, &clk_root_list, child_node) | 137 | hlist_for_each_entry(c, &clk_root_list, child_node) |
75 | clk_summary_show_subtree(s, c, 0); | 138 | clk_summary_show_subtree(s, c, 0); |
@@ -77,7 +140,7 @@ static int clk_summary_show(struct seq_file *s, void *data) | |||
77 | hlist_for_each_entry(c, &clk_orphan_list, child_node) | 140 | hlist_for_each_entry(c, &clk_orphan_list, child_node) |
78 | clk_summary_show_subtree(s, c, 0); | 141 | clk_summary_show_subtree(s, c, 0); |
79 | 142 | ||
80 | mutex_unlock(&prepare_lock); | 143 | clk_prepare_unlock(); |
81 | 144 | ||
82 | return 0; | 145 | return 0; |
83 | } | 146 | } |
@@ -130,7 +193,7 @@ static int clk_dump(struct seq_file *s, void *data) | |||
130 | 193 | ||
131 | seq_printf(s, "{"); | 194 | seq_printf(s, "{"); |
132 | 195 | ||
133 | mutex_lock(&prepare_lock); | 196 | clk_prepare_lock(); |
134 | 197 | ||
135 | hlist_for_each_entry(c, &clk_root_list, child_node) { | 198 | hlist_for_each_entry(c, &clk_root_list, child_node) { |
136 | if (!first_node) | 199 | if (!first_node) |
@@ -144,7 +207,7 @@ static int clk_dump(struct seq_file *s, void *data) | |||
144 | clk_dump_subtree(s, c, 0); | 207 | clk_dump_subtree(s, c, 0); |
145 | } | 208 | } |
146 | 209 | ||
147 | mutex_unlock(&prepare_lock); | 210 | clk_prepare_unlock(); |
148 | 211 | ||
149 | seq_printf(s, "}"); | 212 | seq_printf(s, "}"); |
150 | return 0; | 213 | return 0; |
@@ -316,7 +379,7 @@ static int __init clk_debug_init(void) | |||
316 | if (!orphandir) | 379 | if (!orphandir) |
317 | return -ENOMEM; | 380 | return -ENOMEM; |
318 | 381 | ||
319 | mutex_lock(&prepare_lock); | 382 | clk_prepare_lock(); |
320 | 383 | ||
321 | hlist_for_each_entry(clk, &clk_root_list, child_node) | 384 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
322 | clk_debug_create_subtree(clk, rootdir); | 385 | clk_debug_create_subtree(clk, rootdir); |
@@ -326,7 +389,7 @@ static int __init clk_debug_init(void) | |||
326 | 389 | ||
327 | inited = 1; | 390 | inited = 1; |
328 | 391 | ||
329 | mutex_unlock(&prepare_lock); | 392 | clk_prepare_unlock(); |
330 | 393 | ||
331 | return 0; | 394 | return 0; |
332 | } | 395 | } |
@@ -336,6 +399,31 @@ static inline int clk_debug_register(struct clk *clk) { return 0; } | |||
336 | #endif | 399 | #endif |
337 | 400 | ||
338 | /* caller must hold prepare_lock */ | 401 | /* caller must hold prepare_lock */ |
402 | static void clk_unprepare_unused_subtree(struct clk *clk) | ||
403 | { | ||
404 | struct clk *child; | ||
405 | |||
406 | if (!clk) | ||
407 | return; | ||
408 | |||
409 | hlist_for_each_entry(child, &clk->children, child_node) | ||
410 | clk_unprepare_unused_subtree(child); | ||
411 | |||
412 | if (clk->prepare_count) | ||
413 | return; | ||
414 | |||
415 | if (clk->flags & CLK_IGNORE_UNUSED) | ||
416 | return; | ||
417 | |||
418 | if (__clk_is_prepared(clk)) { | ||
419 | if (clk->ops->unprepare_unused) | ||
420 | clk->ops->unprepare_unused(clk->hw); | ||
421 | else if (clk->ops->unprepare) | ||
422 | clk->ops->unprepare(clk->hw); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | /* caller must hold prepare_lock */ | ||
339 | static void clk_disable_unused_subtree(struct clk *clk) | 427 | static void clk_disable_unused_subtree(struct clk *clk) |
340 | { | 428 | { |
341 | struct clk *child; | 429 | struct clk *child; |
@@ -347,7 +435,7 @@ static void clk_disable_unused_subtree(struct clk *clk) | |||
347 | hlist_for_each_entry(child, &clk->children, child_node) | 435 | hlist_for_each_entry(child, &clk->children, child_node) |
348 | clk_disable_unused_subtree(child); | 436 | clk_disable_unused_subtree(child); |
349 | 437 | ||
350 | spin_lock_irqsave(&enable_lock, flags); | 438 | flags = clk_enable_lock(); |
351 | 439 | ||
352 | if (clk->enable_count) | 440 | if (clk->enable_count) |
353 | goto unlock_out; | 441 | goto unlock_out; |
@@ -368,7 +456,7 @@ static void clk_disable_unused_subtree(struct clk *clk) | |||
368 | } | 456 | } |
369 | 457 | ||
370 | unlock_out: | 458 | unlock_out: |
371 | spin_unlock_irqrestore(&enable_lock, flags); | 459 | clk_enable_unlock(flags); |
372 | 460 | ||
373 | out: | 461 | out: |
374 | return; | 462 | return; |
@@ -378,7 +466,7 @@ static int clk_disable_unused(void) | |||
378 | { | 466 | { |
379 | struct clk *clk; | 467 | struct clk *clk; |
380 | 468 | ||
381 | mutex_lock(&prepare_lock); | 469 | clk_prepare_lock(); |
382 | 470 | ||
383 | hlist_for_each_entry(clk, &clk_root_list, child_node) | 471 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
384 | clk_disable_unused_subtree(clk); | 472 | clk_disable_unused_subtree(clk); |
@@ -386,7 +474,13 @@ static int clk_disable_unused(void) | |||
386 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) | 474 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) |
387 | clk_disable_unused_subtree(clk); | 475 | clk_disable_unused_subtree(clk); |
388 | 476 | ||
389 | mutex_unlock(&prepare_lock); | 477 | hlist_for_each_entry(clk, &clk_root_list, child_node) |
478 | clk_unprepare_unused_subtree(clk); | ||
479 | |||
480 | hlist_for_each_entry(clk, &clk_orphan_list, child_node) | ||
481 | clk_unprepare_unused_subtree(clk); | ||
482 | |||
483 | clk_prepare_unlock(); | ||
390 | 484 | ||
391 | return 0; | 485 | return 0; |
392 | } | 486 | } |
@@ -451,6 +545,27 @@ unsigned long __clk_get_flags(struct clk *clk) | |||
451 | return !clk ? 0 : clk->flags; | 545 | return !clk ? 0 : clk->flags; |
452 | } | 546 | } |
453 | 547 | ||
548 | bool __clk_is_prepared(struct clk *clk) | ||
549 | { | ||
550 | int ret; | ||
551 | |||
552 | if (!clk) | ||
553 | return false; | ||
554 | |||
555 | /* | ||
556 | * .is_prepared is optional for clocks that can prepare | ||
557 | * fall back to software usage counter if it is missing | ||
558 | */ | ||
559 | if (!clk->ops->is_prepared) { | ||
560 | ret = clk->prepare_count ? 1 : 0; | ||
561 | goto out; | ||
562 | } | ||
563 | |||
564 | ret = clk->ops->is_prepared(clk->hw); | ||
565 | out: | ||
566 | return !!ret; | ||
567 | } | ||
568 | |||
454 | bool __clk_is_enabled(struct clk *clk) | 569 | bool __clk_is_enabled(struct clk *clk) |
455 | { | 570 | { |
456 | int ret; | 571 | int ret; |
@@ -548,9 +663,9 @@ void __clk_unprepare(struct clk *clk) | |||
548 | */ | 663 | */ |
549 | void clk_unprepare(struct clk *clk) | 664 | void clk_unprepare(struct clk *clk) |
550 | { | 665 | { |
551 | mutex_lock(&prepare_lock); | 666 | clk_prepare_lock(); |
552 | __clk_unprepare(clk); | 667 | __clk_unprepare(clk); |
553 | mutex_unlock(&prepare_lock); | 668 | clk_prepare_unlock(); |
554 | } | 669 | } |
555 | EXPORT_SYMBOL_GPL(clk_unprepare); | 670 | EXPORT_SYMBOL_GPL(clk_unprepare); |
556 | 671 | ||
@@ -596,9 +711,9 @@ int clk_prepare(struct clk *clk) | |||
596 | { | 711 | { |
597 | int ret; | 712 | int ret; |
598 | 713 | ||
599 | mutex_lock(&prepare_lock); | 714 | clk_prepare_lock(); |
600 | ret = __clk_prepare(clk); | 715 | ret = __clk_prepare(clk); |
601 | mutex_unlock(&prepare_lock); | 716 | clk_prepare_unlock(); |
602 | 717 | ||
603 | return ret; | 718 | return ret; |
604 | } | 719 | } |
@@ -640,9 +755,9 @@ void clk_disable(struct clk *clk) | |||
640 | { | 755 | { |
641 | unsigned long flags; | 756 | unsigned long flags; |
642 | 757 | ||
643 | spin_lock_irqsave(&enable_lock, flags); | 758 | flags = clk_enable_lock(); |
644 | __clk_disable(clk); | 759 | __clk_disable(clk); |
645 | spin_unlock_irqrestore(&enable_lock, flags); | 760 | clk_enable_unlock(flags); |
646 | } | 761 | } |
647 | EXPORT_SYMBOL_GPL(clk_disable); | 762 | EXPORT_SYMBOL_GPL(clk_disable); |
648 | 763 | ||
@@ -693,9 +808,9 @@ int clk_enable(struct clk *clk) | |||
693 | unsigned long flags; | 808 | unsigned long flags; |
694 | int ret; | 809 | int ret; |
695 | 810 | ||
696 | spin_lock_irqsave(&enable_lock, flags); | 811 | flags = clk_enable_lock(); |
697 | ret = __clk_enable(clk); | 812 | ret = __clk_enable(clk); |
698 | spin_unlock_irqrestore(&enable_lock, flags); | 813 | clk_enable_unlock(flags); |
699 | 814 | ||
700 | return ret; | 815 | return ret; |
701 | } | 816 | } |
@@ -740,9 +855,9 @@ long clk_round_rate(struct clk *clk, unsigned long rate) | |||
740 | { | 855 | { |
741 | unsigned long ret; | 856 | unsigned long ret; |
742 | 857 | ||
743 | mutex_lock(&prepare_lock); | 858 | clk_prepare_lock(); |
744 | ret = __clk_round_rate(clk, rate); | 859 | ret = __clk_round_rate(clk, rate); |
745 | mutex_unlock(&prepare_lock); | 860 | clk_prepare_unlock(); |
746 | 861 | ||
747 | return ret; | 862 | return ret; |
748 | } | 863 | } |
@@ -837,13 +952,13 @@ unsigned long clk_get_rate(struct clk *clk) | |||
837 | { | 952 | { |
838 | unsigned long rate; | 953 | unsigned long rate; |
839 | 954 | ||
840 | mutex_lock(&prepare_lock); | 955 | clk_prepare_lock(); |
841 | 956 | ||
842 | if (clk && (clk->flags & CLK_GET_RATE_NOCACHE)) | 957 | if (clk && (clk->flags & CLK_GET_RATE_NOCACHE)) |
843 | __clk_recalc_rates(clk, 0); | 958 | __clk_recalc_rates(clk, 0); |
844 | 959 | ||
845 | rate = __clk_get_rate(clk); | 960 | rate = __clk_get_rate(clk); |
846 | mutex_unlock(&prepare_lock); | 961 | clk_prepare_unlock(); |
847 | 962 | ||
848 | return rate; | 963 | return rate; |
849 | } | 964 | } |
@@ -974,7 +1089,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even | |||
974 | int ret = NOTIFY_DONE; | 1089 | int ret = NOTIFY_DONE; |
975 | 1090 | ||
976 | if (clk->rate == clk->new_rate) | 1091 | if (clk->rate == clk->new_rate) |
977 | return 0; | 1092 | return NULL; |
978 | 1093 | ||
979 | if (clk->notifier_count) { | 1094 | if (clk->notifier_count) { |
980 | ret = __clk_notify(clk, event, clk->rate, clk->new_rate); | 1095 | ret = __clk_notify(clk, event, clk->rate, clk->new_rate); |
@@ -1048,7 +1163,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
1048 | int ret = 0; | 1163 | int ret = 0; |
1049 | 1164 | ||
1050 | /* prevent racing with updates to the clock topology */ | 1165 | /* prevent racing with updates to the clock topology */ |
1051 | mutex_lock(&prepare_lock); | 1166 | clk_prepare_lock(); |
1052 | 1167 | ||
1053 | /* bail early if nothing to do */ | 1168 | /* bail early if nothing to do */ |
1054 | if (rate == clk->rate) | 1169 | if (rate == clk->rate) |
@@ -1080,7 +1195,7 @@ int clk_set_rate(struct clk *clk, unsigned long rate) | |||
1080 | clk_change_rate(top); | 1195 | clk_change_rate(top); |
1081 | 1196 | ||
1082 | out: | 1197 | out: |
1083 | mutex_unlock(&prepare_lock); | 1198 | clk_prepare_unlock(); |
1084 | 1199 | ||
1085 | return ret; | 1200 | return ret; |
1086 | } | 1201 | } |
@@ -1096,9 +1211,9 @@ struct clk *clk_get_parent(struct clk *clk) | |||
1096 | { | 1211 | { |
1097 | struct clk *parent; | 1212 | struct clk *parent; |
1098 | 1213 | ||
1099 | mutex_lock(&prepare_lock); | 1214 | clk_prepare_lock(); |
1100 | parent = __clk_get_parent(clk); | 1215 | parent = __clk_get_parent(clk); |
1101 | mutex_unlock(&prepare_lock); | 1216 | clk_prepare_unlock(); |
1102 | 1217 | ||
1103 | return parent; | 1218 | return parent; |
1104 | } | 1219 | } |
@@ -1242,19 +1357,19 @@ static int __clk_set_parent(struct clk *clk, struct clk *parent) | |||
1242 | __clk_prepare(parent); | 1357 | __clk_prepare(parent); |
1243 | 1358 | ||
1244 | /* FIXME replace with clk_is_enabled(clk) someday */ | 1359 | /* FIXME replace with clk_is_enabled(clk) someday */ |
1245 | spin_lock_irqsave(&enable_lock, flags); | 1360 | flags = clk_enable_lock(); |
1246 | if (clk->enable_count) | 1361 | if (clk->enable_count) |
1247 | __clk_enable(parent); | 1362 | __clk_enable(parent); |
1248 | spin_unlock_irqrestore(&enable_lock, flags); | 1363 | clk_enable_unlock(flags); |
1249 | 1364 | ||
1250 | /* change clock input source */ | 1365 | /* change clock input source */ |
1251 | ret = clk->ops->set_parent(clk->hw, i); | 1366 | ret = clk->ops->set_parent(clk->hw, i); |
1252 | 1367 | ||
1253 | /* clean up old prepare and enable */ | 1368 | /* clean up old prepare and enable */ |
1254 | spin_lock_irqsave(&enable_lock, flags); | 1369 | flags = clk_enable_lock(); |
1255 | if (clk->enable_count) | 1370 | if (clk->enable_count) |
1256 | __clk_disable(old_parent); | 1371 | __clk_disable(old_parent); |
1257 | spin_unlock_irqrestore(&enable_lock, flags); | 1372 | clk_enable_unlock(flags); |
1258 | 1373 | ||
1259 | if (clk->prepare_count) | 1374 | if (clk->prepare_count) |
1260 | __clk_unprepare(old_parent); | 1375 | __clk_unprepare(old_parent); |
@@ -1286,7 +1401,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
1286 | return -ENOSYS; | 1401 | return -ENOSYS; |
1287 | 1402 | ||
1288 | /* prevent racing with updates to the clock topology */ | 1403 | /* prevent racing with updates to the clock topology */ |
1289 | mutex_lock(&prepare_lock); | 1404 | clk_prepare_lock(); |
1290 | 1405 | ||
1291 | if (clk->parent == parent) | 1406 | if (clk->parent == parent) |
1292 | goto out; | 1407 | goto out; |
@@ -1315,7 +1430,7 @@ int clk_set_parent(struct clk *clk, struct clk *parent) | |||
1315 | __clk_reparent(clk, parent); | 1430 | __clk_reparent(clk, parent); |
1316 | 1431 | ||
1317 | out: | 1432 | out: |
1318 | mutex_unlock(&prepare_lock); | 1433 | clk_prepare_unlock(); |
1319 | 1434 | ||
1320 | return ret; | 1435 | return ret; |
1321 | } | 1436 | } |
@@ -1338,7 +1453,7 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
1338 | if (!clk) | 1453 | if (!clk) |
1339 | return -EINVAL; | 1454 | return -EINVAL; |
1340 | 1455 | ||
1341 | mutex_lock(&prepare_lock); | 1456 | clk_prepare_lock(); |
1342 | 1457 | ||
1343 | /* check to see if a clock with this name is already registered */ | 1458 | /* check to see if a clock with this name is already registered */ |
1344 | if (__clk_lookup(clk->name)) { | 1459 | if (__clk_lookup(clk->name)) { |
@@ -1462,7 +1577,7 @@ int __clk_init(struct device *dev, struct clk *clk) | |||
1462 | clk_debug_register(clk); | 1577 | clk_debug_register(clk); |
1463 | 1578 | ||
1464 | out: | 1579 | out: |
1465 | mutex_unlock(&prepare_lock); | 1580 | clk_prepare_unlock(); |
1466 | 1581 | ||
1467 | return ret; | 1582 | return ret; |
1468 | } | 1583 | } |
@@ -1696,7 +1811,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) | |||
1696 | if (!clk || !nb) | 1811 | if (!clk || !nb) |
1697 | return -EINVAL; | 1812 | return -EINVAL; |
1698 | 1813 | ||
1699 | mutex_lock(&prepare_lock); | 1814 | clk_prepare_lock(); |
1700 | 1815 | ||
1701 | /* search the list of notifiers for this clk */ | 1816 | /* search the list of notifiers for this clk */ |
1702 | list_for_each_entry(cn, &clk_notifier_list, node) | 1817 | list_for_each_entry(cn, &clk_notifier_list, node) |
@@ -1720,7 +1835,7 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) | |||
1720 | clk->notifier_count++; | 1835 | clk->notifier_count++; |
1721 | 1836 | ||
1722 | out: | 1837 | out: |
1723 | mutex_unlock(&prepare_lock); | 1838 | clk_prepare_unlock(); |
1724 | 1839 | ||
1725 | return ret; | 1840 | return ret; |
1726 | } | 1841 | } |
@@ -1745,7 +1860,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) | |||
1745 | if (!clk || !nb) | 1860 | if (!clk || !nb) |
1746 | return -EINVAL; | 1861 | return -EINVAL; |
1747 | 1862 | ||
1748 | mutex_lock(&prepare_lock); | 1863 | clk_prepare_lock(); |
1749 | 1864 | ||
1750 | list_for_each_entry(cn, &clk_notifier_list, node) | 1865 | list_for_each_entry(cn, &clk_notifier_list, node) |
1751 | if (cn->clk == clk) | 1866 | if (cn->clk == clk) |
@@ -1766,7 +1881,7 @@ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) | |||
1766 | ret = -ENOENT; | 1881 | ret = -ENOENT; |
1767 | } | 1882 | } |
1768 | 1883 | ||
1769 | mutex_unlock(&prepare_lock); | 1884 | clk_prepare_unlock(); |
1770 | 1885 | ||
1771 | return ret; | 1886 | return ret; |
1772 | } | 1887 | } |
diff --git a/drivers/clk/mxs/clk.c b/drivers/clk/mxs/clk.c index b24d56067c80..5301bce8957b 100644 --- a/drivers/clk/mxs/clk.c +++ b/drivers/clk/mxs/clk.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
14 | #include <linux/jiffies.h> | 14 | #include <linux/jiffies.h> |
15 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
16 | #include "clk.h" | ||
16 | 17 | ||
17 | DEFINE_SPINLOCK(mxs_lock); | 18 | DEFINE_SPINLOCK(mxs_lock); |
18 | 19 | ||
diff --git a/drivers/clk/spear/spear1340_clock.c b/drivers/clk/spear/spear1340_clock.c index 82abea366b78..35e7e2698e10 100644 --- a/drivers/clk/spear/spear1340_clock.c +++ b/drivers/clk/spear/spear1340_clock.c | |||
@@ -960,47 +960,47 @@ void __init spear1340_clk_init(void) | |||
960 | SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock); | 960 | SPEAR1340_SPDIF_IN_CLK_ENB, 0, &_lock); |
961 | clk_register_clkdev(clk, NULL, "d0100000.spdif-in"); | 961 | clk_register_clkdev(clk, NULL, "d0100000.spdif-in"); |
962 | 962 | ||
963 | clk = clk_register_gate(NULL, "acp_clk", "acp_mclk", 0, | 963 | clk = clk_register_gate(NULL, "acp_clk", "ahb_clk", 0, |
964 | SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0, | 964 | SPEAR1340_PERIP2_CLK_ENB, SPEAR1340_ACP_CLK_ENB, 0, |
965 | &_lock); | 965 | &_lock); |
966 | clk_register_clkdev(clk, NULL, "acp_clk"); | 966 | clk_register_clkdev(clk, NULL, "acp_clk"); |
967 | 967 | ||
968 | clk = clk_register_gate(NULL, "plgpio_clk", "plgpio_mclk", 0, | 968 | clk = clk_register_gate(NULL, "plgpio_clk", "ahb_clk", 0, |
969 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0, | 969 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_PLGPIO_CLK_ENB, 0, |
970 | &_lock); | 970 | &_lock); |
971 | clk_register_clkdev(clk, NULL, "e2800000.gpio"); | 971 | clk_register_clkdev(clk, NULL, "e2800000.gpio"); |
972 | 972 | ||
973 | clk = clk_register_gate(NULL, "video_dec_clk", "video_dec_mclk", 0, | 973 | clk = clk_register_gate(NULL, "video_dec_clk", "ahb_clk", 0, |
974 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB, | 974 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_DEC_CLK_ENB, |
975 | 0, &_lock); | 975 | 0, &_lock); |
976 | clk_register_clkdev(clk, NULL, "video_dec"); | 976 | clk_register_clkdev(clk, NULL, "video_dec"); |
977 | 977 | ||
978 | clk = clk_register_gate(NULL, "video_enc_clk", "video_enc_mclk", 0, | 978 | clk = clk_register_gate(NULL, "video_enc_clk", "ahb_clk", 0, |
979 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB, | 979 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_ENC_CLK_ENB, |
980 | 0, &_lock); | 980 | 0, &_lock); |
981 | clk_register_clkdev(clk, NULL, "video_enc"); | 981 | clk_register_clkdev(clk, NULL, "video_enc"); |
982 | 982 | ||
983 | clk = clk_register_gate(NULL, "video_in_clk", "video_in_mclk", 0, | 983 | clk = clk_register_gate(NULL, "video_in_clk", "ahb_clk", 0, |
984 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0, | 984 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_VIDEO_IN_CLK_ENB, 0, |
985 | &_lock); | 985 | &_lock); |
986 | clk_register_clkdev(clk, NULL, "spear_vip"); | 986 | clk_register_clkdev(clk, NULL, "spear_vip"); |
987 | 987 | ||
988 | clk = clk_register_gate(NULL, "cam0_clk", "cam0_mclk", 0, | 988 | clk = clk_register_gate(NULL, "cam0_clk", "ahb_clk", 0, |
989 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0, | 989 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM0_CLK_ENB, 0, |
990 | &_lock); | 990 | &_lock); |
991 | clk_register_clkdev(clk, NULL, "d0200000.cam0"); | 991 | clk_register_clkdev(clk, NULL, "d0200000.cam0"); |
992 | 992 | ||
993 | clk = clk_register_gate(NULL, "cam1_clk", "cam1_mclk", 0, | 993 | clk = clk_register_gate(NULL, "cam1_clk", "ahb_clk", 0, |
994 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0, | 994 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM1_CLK_ENB, 0, |
995 | &_lock); | 995 | &_lock); |
996 | clk_register_clkdev(clk, NULL, "d0300000.cam1"); | 996 | clk_register_clkdev(clk, NULL, "d0300000.cam1"); |
997 | 997 | ||
998 | clk = clk_register_gate(NULL, "cam2_clk", "cam2_mclk", 0, | 998 | clk = clk_register_gate(NULL, "cam2_clk", "ahb_clk", 0, |
999 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0, | 999 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM2_CLK_ENB, 0, |
1000 | &_lock); | 1000 | &_lock); |
1001 | clk_register_clkdev(clk, NULL, "d0400000.cam2"); | 1001 | clk_register_clkdev(clk, NULL, "d0400000.cam2"); |
1002 | 1002 | ||
1003 | clk = clk_register_gate(NULL, "cam3_clk", "cam3_mclk", 0, | 1003 | clk = clk_register_gate(NULL, "cam3_clk", "ahb_clk", 0, |
1004 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0, | 1004 | SPEAR1340_PERIP3_CLK_ENB, SPEAR1340_CAM3_CLK_ENB, 0, |
1005 | &_lock); | 1005 | &_lock); |
1006 | clk_register_clkdev(clk, NULL, "d0500000.cam3"); | 1006 | clk_register_clkdev(clk, NULL, "d0500000.cam3"); |
diff --git a/drivers/clk/sunxi/Makefile b/drivers/clk/sunxi/Makefile new file mode 100644 index 000000000000..b5bac917612c --- /dev/null +++ b/drivers/clk/sunxi/Makefile | |||
@@ -0,0 +1,5 @@ | |||
1 | # | ||
2 | # Makefile for sunxi specific clk | ||
3 | # | ||
4 | |||
5 | obj-y += clk-sunxi.o clk-factors.o | ||
diff --git a/drivers/clk/sunxi/clk-factors.c b/drivers/clk/sunxi/clk-factors.c new file mode 100644 index 000000000000..88523f91d9b7 --- /dev/null +++ b/drivers/clk/sunxi/clk-factors.c | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2013 Emilio López <emilio@elopez.com.ar> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Adjustable factor-based clock implementation | ||
9 | */ | ||
10 | |||
11 | #include <linux/clk-provider.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/io.h> | ||
15 | #include <linux/err.h> | ||
16 | #include <linux/string.h> | ||
17 | |||
18 | #include <linux/delay.h> | ||
19 | |||
20 | #include "clk-factors.h" | ||
21 | |||
22 | /* | ||
23 | * DOC: basic adjustable factor-based clock that cannot gate | ||
24 | * | ||
25 | * Traits of this clock: | ||
26 | * prepare - clk_prepare only ensures that parents are prepared | ||
27 | * enable - clk_enable only ensures that parents are enabled | ||
28 | * rate - rate is adjustable. | ||
29 | * clk->rate = (parent->rate * N * (K + 1) >> P) / (M + 1) | ||
30 | * parent - fixed parent. No clk_set_parent support | ||
31 | */ | ||
32 | |||
33 | struct clk_factors { | ||
34 | struct clk_hw hw; | ||
35 | void __iomem *reg; | ||
36 | struct clk_factors_config *config; | ||
37 | void (*get_factors) (u32 *rate, u32 parent, u8 *n, u8 *k, u8 *m, u8 *p); | ||
38 | spinlock_t *lock; | ||
39 | }; | ||
40 | |||
41 | #define to_clk_factors(_hw) container_of(_hw, struct clk_factors, hw) | ||
42 | |||
43 | #define SETMASK(len, pos) (((-1U) >> (31-len)) << (pos)) | ||
44 | #define CLRMASK(len, pos) (~(SETMASK(len, pos))) | ||
45 | #define FACTOR_GET(bit, len, reg) (((reg) & SETMASK(len, bit)) >> (bit)) | ||
46 | |||
47 | #define FACTOR_SET(bit, len, reg, val) \ | ||
48 | (((reg) & CLRMASK(len, bit)) | (val << (bit))) | ||
49 | |||
50 | static unsigned long clk_factors_recalc_rate(struct clk_hw *hw, | ||
51 | unsigned long parent_rate) | ||
52 | { | ||
53 | u8 n = 1, k = 0, p = 0, m = 0; | ||
54 | u32 reg; | ||
55 | unsigned long rate; | ||
56 | struct clk_factors *factors = to_clk_factors(hw); | ||
57 | struct clk_factors_config *config = factors->config; | ||
58 | |||
59 | /* Fetch the register value */ | ||
60 | reg = readl(factors->reg); | ||
61 | |||
62 | /* Get each individual factor if applicable */ | ||
63 | if (config->nwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
64 | n = FACTOR_GET(config->nshift, config->nwidth, reg); | ||
65 | if (config->kwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
66 | k = FACTOR_GET(config->kshift, config->kwidth, reg); | ||
67 | if (config->mwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
68 | m = FACTOR_GET(config->mshift, config->mwidth, reg); | ||
69 | if (config->pwidth != SUNXI_FACTORS_NOT_APPLICABLE) | ||
70 | p = FACTOR_GET(config->pshift, config->pwidth, reg); | ||
71 | |||
72 | /* Calculate the rate */ | ||
73 | rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | ||
74 | |||
75 | return rate; | ||
76 | } | ||
77 | |||
78 | static long clk_factors_round_rate(struct clk_hw *hw, unsigned long rate, | ||
79 | unsigned long *parent_rate) | ||
80 | { | ||
81 | struct clk_factors *factors = to_clk_factors(hw); | ||
82 | factors->get_factors((u32 *)&rate, (u32)*parent_rate, | ||
83 | NULL, NULL, NULL, NULL); | ||
84 | |||
85 | return rate; | ||
86 | } | ||
87 | |||
88 | static int clk_factors_set_rate(struct clk_hw *hw, unsigned long rate, | ||
89 | unsigned long parent_rate) | ||
90 | { | ||
91 | u8 n, k, m, p; | ||
92 | u32 reg; | ||
93 | struct clk_factors *factors = to_clk_factors(hw); | ||
94 | struct clk_factors_config *config = factors->config; | ||
95 | unsigned long flags = 0; | ||
96 | |||
97 | factors->get_factors((u32 *)&rate, (u32)parent_rate, &n, &k, &m, &p); | ||
98 | |||
99 | if (factors->lock) | ||
100 | spin_lock_irqsave(factors->lock, flags); | ||
101 | |||
102 | /* Fetch the register value */ | ||
103 | reg = readl(factors->reg); | ||
104 | |||
105 | /* Set up the new factors - macros do not do anything if width is 0 */ | ||
106 | reg = FACTOR_SET(config->nshift, config->nwidth, reg, n); | ||
107 | reg = FACTOR_SET(config->kshift, config->kwidth, reg, k); | ||
108 | reg = FACTOR_SET(config->mshift, config->mwidth, reg, m); | ||
109 | reg = FACTOR_SET(config->pshift, config->pwidth, reg, p); | ||
110 | |||
111 | /* Apply them now */ | ||
112 | writel(reg, factors->reg); | ||
113 | |||
114 | /* delay 500us so pll stabilizes */ | ||
115 | __delay((rate >> 20) * 500 / 2); | ||
116 | |||
117 | if (factors->lock) | ||
118 | spin_unlock_irqrestore(factors->lock, flags); | ||
119 | |||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static const struct clk_ops clk_factors_ops = { | ||
124 | .recalc_rate = clk_factors_recalc_rate, | ||
125 | .round_rate = clk_factors_round_rate, | ||
126 | .set_rate = clk_factors_set_rate, | ||
127 | }; | ||
128 | |||
129 | /** | ||
130 | * clk_register_factors - register a factors clock with | ||
131 | * the clock framework | ||
132 | * @dev: device registering this clock | ||
133 | * @name: name of this clock | ||
134 | * @parent_name: name of clock's parent | ||
135 | * @flags: framework-specific flags | ||
136 | * @reg: register address to adjust factors | ||
137 | * @config: shift and width of factors n, k, m and p | ||
138 | * @get_factors: function to calculate the factors for a given frequency | ||
139 | * @lock: shared register lock for this clock | ||
140 | */ | ||
141 | struct clk *clk_register_factors(struct device *dev, const char *name, | ||
142 | const char *parent_name, | ||
143 | unsigned long flags, void __iomem *reg, | ||
144 | struct clk_factors_config *config, | ||
145 | void (*get_factors)(u32 *rate, u32 parent, | ||
146 | u8 *n, u8 *k, u8 *m, u8 *p), | ||
147 | spinlock_t *lock) | ||
148 | { | ||
149 | struct clk_factors *factors; | ||
150 | struct clk *clk; | ||
151 | struct clk_init_data init; | ||
152 | |||
153 | /* allocate the factors */ | ||
154 | factors = kzalloc(sizeof(struct clk_factors), GFP_KERNEL); | ||
155 | if (!factors) { | ||
156 | pr_err("%s: could not allocate factors clk\n", __func__); | ||
157 | return ERR_PTR(-ENOMEM); | ||
158 | } | ||
159 | |||
160 | init.name = name; | ||
161 | init.ops = &clk_factors_ops; | ||
162 | init.flags = flags; | ||
163 | init.parent_names = (parent_name ? &parent_name : NULL); | ||
164 | init.num_parents = (parent_name ? 1 : 0); | ||
165 | |||
166 | /* struct clk_factors assignments */ | ||
167 | factors->reg = reg; | ||
168 | factors->config = config; | ||
169 | factors->lock = lock; | ||
170 | factors->hw.init = &init; | ||
171 | factors->get_factors = get_factors; | ||
172 | |||
173 | /* register the clock */ | ||
174 | clk = clk_register(dev, &factors->hw); | ||
175 | |||
176 | if (IS_ERR(clk)) | ||
177 | kfree(factors); | ||
178 | |||
179 | return clk; | ||
180 | } | ||
diff --git a/drivers/clk/sunxi/clk-factors.h b/drivers/clk/sunxi/clk-factors.h new file mode 100644 index 000000000000..f49851cc4380 --- /dev/null +++ b/drivers/clk/sunxi/clk-factors.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef __MACH_SUNXI_CLK_FACTORS_H | ||
2 | #define __MACH_SUNXI_CLK_FACTORS_H | ||
3 | |||
4 | #include <linux/clk-provider.h> | ||
5 | #include <linux/clkdev.h> | ||
6 | |||
7 | #define SUNXI_FACTORS_NOT_APPLICABLE (0) | ||
8 | |||
9 | struct clk_factors_config { | ||
10 | u8 nshift; | ||
11 | u8 nwidth; | ||
12 | u8 kshift; | ||
13 | u8 kwidth; | ||
14 | u8 mshift; | ||
15 | u8 mwidth; | ||
16 | u8 pshift; | ||
17 | u8 pwidth; | ||
18 | }; | ||
19 | |||
20 | struct clk *clk_register_factors(struct device *dev, const char *name, | ||
21 | const char *parent_name, | ||
22 | unsigned long flags, void __iomem *reg, | ||
23 | struct clk_factors_config *config, | ||
24 | void (*get_factors) (u32 *rate, u32 parent_rate, | ||
25 | u8 *n, u8 *k, u8 *m, u8 *p), | ||
26 | spinlock_t *lock); | ||
27 | #endif | ||
diff --git a/drivers/clk/sunxi/clk-sunxi.c b/drivers/clk/sunxi/clk-sunxi.c new file mode 100644 index 000000000000..d528a2496690 --- /dev/null +++ b/drivers/clk/sunxi/clk-sunxi.c | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Copyright 2013 Emilio López | ||
3 | * | ||
4 | * Emilio López <emilio@elopez.com.ar> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | */ | ||
16 | |||
17 | #include <linux/clk-provider.h> | ||
18 | #include <linux/clkdev.h> | ||
19 | #include <linux/clk/sunxi.h> | ||
20 | #include <linux/of.h> | ||
21 | #include <linux/of_address.h> | ||
22 | |||
23 | #include "clk-factors.h" | ||
24 | |||
25 | static DEFINE_SPINLOCK(clk_lock); | ||
26 | |||
27 | /** | ||
28 | * sunxi_osc_clk_setup() - Setup function for gatable oscillator | ||
29 | */ | ||
30 | |||
31 | #define SUNXI_OSC24M_GATE 0 | ||
32 | |||
33 | static void __init sunxi_osc_clk_setup(struct device_node *node) | ||
34 | { | ||
35 | struct clk *clk; | ||
36 | const char *clk_name = node->name; | ||
37 | const char *parent; | ||
38 | void *reg; | ||
39 | |||
40 | reg = of_iomap(node, 0); | ||
41 | |||
42 | parent = of_clk_get_parent_name(node, 0); | ||
43 | |||
44 | clk = clk_register_gate(NULL, clk_name, parent, CLK_IGNORE_UNUSED, | ||
45 | reg, SUNXI_OSC24M_GATE, 0, &clk_lock); | ||
46 | |||
47 | if (clk) { | ||
48 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
49 | clk_register_clkdev(clk, clk_name, NULL); | ||
50 | } | ||
51 | } | ||
52 | |||
53 | |||
54 | |||
55 | /** | ||
56 | * sunxi_get_pll1_factors() - calculates n, k, m, p factors for PLL1 | ||
57 | * PLL1 rate is calculated as follows | ||
58 | * rate = (parent_rate * n * (k + 1) >> p) / (m + 1); | ||
59 | * parent_rate is always 24Mhz | ||
60 | */ | ||
61 | |||
62 | static void sunxi_get_pll1_factors(u32 *freq, u32 parent_rate, | ||
63 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
64 | { | ||
65 | u8 div; | ||
66 | |||
67 | /* Normalize value to a 6M multiple */ | ||
68 | div = *freq / 6000000; | ||
69 | *freq = 6000000 * div; | ||
70 | |||
71 | /* we were called to round the frequency, we can now return */ | ||
72 | if (n == NULL) | ||
73 | return; | ||
74 | |||
75 | /* m is always zero for pll1 */ | ||
76 | *m = 0; | ||
77 | |||
78 | /* k is 1 only on these cases */ | ||
79 | if (*freq >= 768000000 || *freq == 42000000 || *freq == 54000000) | ||
80 | *k = 1; | ||
81 | else | ||
82 | *k = 0; | ||
83 | |||
84 | /* p will be 3 for divs under 10 */ | ||
85 | if (div < 10) | ||
86 | *p = 3; | ||
87 | |||
88 | /* p will be 2 for divs between 10 - 20 and odd divs under 32 */ | ||
89 | else if (div < 20 || (div < 32 && (div & 1))) | ||
90 | *p = 2; | ||
91 | |||
92 | /* p will be 1 for even divs under 32, divs under 40 and odd pairs | ||
93 | * of divs between 40-62 */ | ||
94 | else if (div < 40 || (div < 64 && (div & 2))) | ||
95 | *p = 1; | ||
96 | |||
97 | /* any other entries have p = 0 */ | ||
98 | else | ||
99 | *p = 0; | ||
100 | |||
101 | /* calculate a suitable n based on k and p */ | ||
102 | div <<= *p; | ||
103 | div /= (*k + 1); | ||
104 | *n = div / 4; | ||
105 | } | ||
106 | |||
107 | |||
108 | |||
109 | /** | ||
110 | * sunxi_get_apb1_factors() - calculates m, p factors for APB1 | ||
111 | * APB1 rate is calculated as follows | ||
112 | * rate = (parent_rate >> p) / (m + 1); | ||
113 | */ | ||
114 | |||
115 | static void sunxi_get_apb1_factors(u32 *freq, u32 parent_rate, | ||
116 | u8 *n, u8 *k, u8 *m, u8 *p) | ||
117 | { | ||
118 | u8 calcm, calcp; | ||
119 | |||
120 | if (parent_rate < *freq) | ||
121 | *freq = parent_rate; | ||
122 | |||
123 | parent_rate = (parent_rate + (*freq - 1)) / *freq; | ||
124 | |||
125 | /* Invalid rate! */ | ||
126 | if (parent_rate > 32) | ||
127 | return; | ||
128 | |||
129 | if (parent_rate <= 4) | ||
130 | calcp = 0; | ||
131 | else if (parent_rate <= 8) | ||
132 | calcp = 1; | ||
133 | else if (parent_rate <= 16) | ||
134 | calcp = 2; | ||
135 | else | ||
136 | calcp = 3; | ||
137 | |||
138 | calcm = (parent_rate >> calcp) - 1; | ||
139 | |||
140 | *freq = (parent_rate >> calcp) / (calcm + 1); | ||
141 | |||
142 | /* we were called to round the frequency, we can now return */ | ||
143 | if (n == NULL) | ||
144 | return; | ||
145 | |||
146 | *m = calcm; | ||
147 | *p = calcp; | ||
148 | } | ||
149 | |||
150 | |||
151 | |||
152 | /** | ||
153 | * sunxi_factors_clk_setup() - Setup function for factor clocks | ||
154 | */ | ||
155 | |||
156 | struct factors_data { | ||
157 | struct clk_factors_config *table; | ||
158 | void (*getter) (u32 *rate, u32 parent_rate, u8 *n, u8 *k, u8 *m, u8 *p); | ||
159 | }; | ||
160 | |||
161 | static struct clk_factors_config pll1_config = { | ||
162 | .nshift = 8, | ||
163 | .nwidth = 5, | ||
164 | .kshift = 4, | ||
165 | .kwidth = 2, | ||
166 | .mshift = 0, | ||
167 | .mwidth = 2, | ||
168 | .pshift = 16, | ||
169 | .pwidth = 2, | ||
170 | }; | ||
171 | |||
172 | static struct clk_factors_config apb1_config = { | ||
173 | .mshift = 0, | ||
174 | .mwidth = 5, | ||
175 | .pshift = 16, | ||
176 | .pwidth = 2, | ||
177 | }; | ||
178 | |||
179 | static const __initconst struct factors_data pll1_data = { | ||
180 | .table = &pll1_config, | ||
181 | .getter = sunxi_get_pll1_factors, | ||
182 | }; | ||
183 | |||
184 | static const __initconst struct factors_data apb1_data = { | ||
185 | .table = &apb1_config, | ||
186 | .getter = sunxi_get_apb1_factors, | ||
187 | }; | ||
188 | |||
189 | static void __init sunxi_factors_clk_setup(struct device_node *node, | ||
190 | struct factors_data *data) | ||
191 | { | ||
192 | struct clk *clk; | ||
193 | const char *clk_name = node->name; | ||
194 | const char *parent; | ||
195 | void *reg; | ||
196 | |||
197 | reg = of_iomap(node, 0); | ||
198 | |||
199 | parent = of_clk_get_parent_name(node, 0); | ||
200 | |||
201 | clk = clk_register_factors(NULL, clk_name, parent, CLK_IGNORE_UNUSED, | ||
202 | reg, data->table, data->getter, &clk_lock); | ||
203 | |||
204 | if (clk) { | ||
205 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
206 | clk_register_clkdev(clk, clk_name, NULL); | ||
207 | } | ||
208 | } | ||
209 | |||
210 | |||
211 | |||
212 | /** | ||
213 | * sunxi_mux_clk_setup() - Setup function for muxes | ||
214 | */ | ||
215 | |||
216 | #define SUNXI_MUX_GATE_WIDTH 2 | ||
217 | |||
218 | struct mux_data { | ||
219 | u8 shift; | ||
220 | }; | ||
221 | |||
222 | static const __initconst struct mux_data cpu_data = { | ||
223 | .shift = 16, | ||
224 | }; | ||
225 | |||
226 | static const __initconst struct mux_data apb1_mux_data = { | ||
227 | .shift = 24, | ||
228 | }; | ||
229 | |||
230 | static void __init sunxi_mux_clk_setup(struct device_node *node, | ||
231 | struct mux_data *data) | ||
232 | { | ||
233 | struct clk *clk; | ||
234 | const char *clk_name = node->name; | ||
235 | const char **parents = kmalloc(sizeof(char *) * 5, GFP_KERNEL); | ||
236 | void *reg; | ||
237 | int i = 0; | ||
238 | |||
239 | reg = of_iomap(node, 0); | ||
240 | |||
241 | while (i < 5 && (parents[i] = of_clk_get_parent_name(node, i)) != NULL) | ||
242 | i++; | ||
243 | |||
244 | clk = clk_register_mux(NULL, clk_name, parents, i, 0, reg, | ||
245 | data->shift, SUNXI_MUX_GATE_WIDTH, | ||
246 | 0, &clk_lock); | ||
247 | |||
248 | if (clk) { | ||
249 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
250 | clk_register_clkdev(clk, clk_name, NULL); | ||
251 | } | ||
252 | } | ||
253 | |||
254 | |||
255 | |||
256 | /** | ||
257 | * sunxi_divider_clk_setup() - Setup function for simple divider clocks | ||
258 | */ | ||
259 | |||
260 | #define SUNXI_DIVISOR_WIDTH 2 | ||
261 | |||
262 | struct div_data { | ||
263 | u8 shift; | ||
264 | u8 pow; | ||
265 | }; | ||
266 | |||
267 | static const __initconst struct div_data axi_data = { | ||
268 | .shift = 0, | ||
269 | .pow = 0, | ||
270 | }; | ||
271 | |||
272 | static const __initconst struct div_data ahb_data = { | ||
273 | .shift = 4, | ||
274 | .pow = 1, | ||
275 | }; | ||
276 | |||
277 | static const __initconst struct div_data apb0_data = { | ||
278 | .shift = 8, | ||
279 | .pow = 1, | ||
280 | }; | ||
281 | |||
282 | static void __init sunxi_divider_clk_setup(struct device_node *node, | ||
283 | struct div_data *data) | ||
284 | { | ||
285 | struct clk *clk; | ||
286 | const char *clk_name = node->name; | ||
287 | const char *clk_parent; | ||
288 | void *reg; | ||
289 | |||
290 | reg = of_iomap(node, 0); | ||
291 | |||
292 | clk_parent = of_clk_get_parent_name(node, 0); | ||
293 | |||
294 | clk = clk_register_divider(NULL, clk_name, clk_parent, 0, | ||
295 | reg, data->shift, SUNXI_DIVISOR_WIDTH, | ||
296 | data->pow ? CLK_DIVIDER_POWER_OF_TWO : 0, | ||
297 | &clk_lock); | ||
298 | if (clk) { | ||
299 | of_clk_add_provider(node, of_clk_src_simple_get, clk); | ||
300 | clk_register_clkdev(clk, clk_name, NULL); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | |||
305 | /* Matches for of_clk_init */ | ||
306 | static const __initconst struct of_device_id clk_match[] = { | ||
307 | {.compatible = "fixed-clock", .data = of_fixed_clk_setup,}, | ||
308 | {.compatible = "allwinner,sun4i-osc-clk", .data = sunxi_osc_clk_setup,}, | ||
309 | {} | ||
310 | }; | ||
311 | |||
312 | /* Matches for factors clocks */ | ||
313 | static const __initconst struct of_device_id clk_factors_match[] = { | ||
314 | {.compatible = "allwinner,sun4i-pll1-clk", .data = &pll1_data,}, | ||
315 | {.compatible = "allwinner,sun4i-apb1-clk", .data = &apb1_data,}, | ||
316 | {} | ||
317 | }; | ||
318 | |||
319 | /* Matches for divider clocks */ | ||
320 | static const __initconst struct of_device_id clk_div_match[] = { | ||
321 | {.compatible = "allwinner,sun4i-axi-clk", .data = &axi_data,}, | ||
322 | {.compatible = "allwinner,sun4i-ahb-clk", .data = &ahb_data,}, | ||
323 | {.compatible = "allwinner,sun4i-apb0-clk", .data = &apb0_data,}, | ||
324 | {} | ||
325 | }; | ||
326 | |||
327 | /* Matches for mux clocks */ | ||
328 | static const __initconst struct of_device_id clk_mux_match[] = { | ||
329 | {.compatible = "allwinner,sun4i-cpu-clk", .data = &cpu_data,}, | ||
330 | {.compatible = "allwinner,sun4i-apb1-mux-clk", .data = &apb1_mux_data,}, | ||
331 | {} | ||
332 | }; | ||
333 | |||
334 | static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_match, | ||
335 | void *function) | ||
336 | { | ||
337 | struct device_node *np; | ||
338 | const struct div_data *data; | ||
339 | const struct of_device_id *match; | ||
340 | void (*setup_function)(struct device_node *, const void *) = function; | ||
341 | |||
342 | for_each_matching_node(np, clk_match) { | ||
343 | match = of_match_node(clk_match, np); | ||
344 | data = match->data; | ||
345 | setup_function(np, data); | ||
346 | } | ||
347 | } | ||
348 | |||
349 | void __init sunxi_init_clocks(void) | ||
350 | { | ||
351 | /* Register all the simple sunxi clocks on DT */ | ||
352 | of_clk_init(clk_match); | ||
353 | |||
354 | /* Register factor clocks */ | ||
355 | of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup); | ||
356 | |||
357 | /* Register divider clocks */ | ||
358 | of_sunxi_table_clock_setup(clk_div_match, sunxi_divider_clk_setup); | ||
359 | |||
360 | /* Register mux clocks */ | ||
361 | of_sunxi_table_clock_setup(clk_mux_match, sunxi_mux_clk_setup); | ||
362 | } | ||
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile index 2b41b0f4f731..f49fac2d193a 100644 --- a/drivers/clk/tegra/Makefile +++ b/drivers/clk/tegra/Makefile | |||
@@ -9,3 +9,4 @@ obj-y += clk-super.o | |||
9 | 9 | ||
10 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o | 10 | obj-$(CONFIG_ARCH_TEGRA_2x_SOC) += clk-tegra20.o |
11 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o | 11 | obj-$(CONFIG_ARCH_TEGRA_3x_SOC) += clk-tegra30.o |
12 | obj-$(CONFIG_ARCH_TEGRA_114_SOC) += clk-tegra114.o | ||
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c index 6dd533251e7b..bafee9895a24 100644 --- a/drivers/clk/tegra/clk-periph-gate.c +++ b/drivers/clk/tegra/clk-periph-gate.c | |||
@@ -41,7 +41,9 @@ static DEFINE_SPINLOCK(periph_ref_lock); | |||
41 | #define write_rst_clr(val, gate) \ | 41 | #define write_rst_clr(val, gate) \ |
42 | writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg)) | 42 | writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg)) |
43 | 43 | ||
44 | #define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32)) | 44 | #define periph_clk_to_bit(gate) (1 << (gate->clk_num % 32)) |
45 | |||
46 | #define LVL2_CLK_GATE_OVRE 0x554 | ||
45 | 47 | ||
46 | /* Peripheral gate clock ops */ | 48 | /* Peripheral gate clock ops */ |
47 | static int clk_periph_is_enabled(struct clk_hw *hw) | 49 | static int clk_periph_is_enabled(struct clk_hw *hw) |
@@ -83,6 +85,13 @@ static int clk_periph_enable(struct clk_hw *hw) | |||
83 | } | 85 | } |
84 | } | 86 | } |
85 | 87 | ||
88 | if (gate->flags & TEGRA_PERIPH_WAR_1005168) { | ||
89 | writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); | ||
90 | writel_relaxed(BIT(22), gate->clk_base + LVL2_CLK_GATE_OVRE); | ||
91 | udelay(1); | ||
92 | writel_relaxed(0, gate->clk_base + LVL2_CLK_GATE_OVRE); | ||
93 | } | ||
94 | |||
86 | spin_unlock_irqrestore(&periph_ref_lock, flags); | 95 | spin_unlock_irqrestore(&periph_ref_lock, flags); |
87 | 96 | ||
88 | return 0; | 97 | return 0; |
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c index 788486e6331a..b2309d37a963 100644 --- a/drivers/clk/tegra/clk-periph.c +++ b/drivers/clk/tegra/clk-periph.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/clk.h> | 17 | #include <linux/clk.h> |
18 | #include <linux/clk-provider.h> | 18 | #include <linux/clk-provider.h> |
19 | #include <linux/export.h> | ||
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
20 | #include <linux/err.h> | 21 | #include <linux/err.h> |
21 | 22 | ||
@@ -128,6 +129,7 @@ void tegra_periph_reset_deassert(struct clk *c) | |||
128 | 129 | ||
129 | tegra_periph_reset(gate, 0); | 130 | tegra_periph_reset(gate, 0); |
130 | } | 131 | } |
132 | EXPORT_SYMBOL(tegra_periph_reset_deassert); | ||
131 | 133 | ||
132 | void tegra_periph_reset_assert(struct clk *c) | 134 | void tegra_periph_reset_assert(struct clk *c) |
133 | { | 135 | { |
@@ -147,6 +149,7 @@ void tegra_periph_reset_assert(struct clk *c) | |||
147 | 149 | ||
148 | tegra_periph_reset(gate, 1); | 150 | tegra_periph_reset(gate, 1); |
149 | } | 151 | } |
152 | EXPORT_SYMBOL(tegra_periph_reset_assert); | ||
150 | 153 | ||
151 | const struct clk_ops tegra_clk_periph_ops = { | 154 | const struct clk_ops tegra_clk_periph_ops = { |
152 | .get_parent = clk_periph_get_parent, | 155 | .get_parent = clk_periph_get_parent, |
@@ -170,14 +173,15 @@ const struct clk_ops tegra_clk_periph_nodiv_ops = { | |||
170 | static struct clk *_tegra_clk_register_periph(const char *name, | 173 | static struct clk *_tegra_clk_register_periph(const char *name, |
171 | const char **parent_names, int num_parents, | 174 | const char **parent_names, int num_parents, |
172 | struct tegra_clk_periph *periph, | 175 | struct tegra_clk_periph *periph, |
173 | void __iomem *clk_base, u32 offset, bool div) | 176 | void __iomem *clk_base, u32 offset, bool div, |
177 | unsigned long flags) | ||
174 | { | 178 | { |
175 | struct clk *clk; | 179 | struct clk *clk; |
176 | struct clk_init_data init; | 180 | struct clk_init_data init; |
177 | 181 | ||
178 | init.name = name; | 182 | init.name = name; |
179 | init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops; | 183 | init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops; |
180 | init.flags = div ? 0 : CLK_SET_RATE_PARENT; | 184 | init.flags = flags; |
181 | init.parent_names = parent_names; | 185 | init.parent_names = parent_names; |
182 | init.num_parents = num_parents; | 186 | init.num_parents = num_parents; |
183 | 187 | ||
@@ -202,10 +206,10 @@ static struct clk *_tegra_clk_register_periph(const char *name, | |||
202 | struct clk *tegra_clk_register_periph(const char *name, | 206 | struct clk *tegra_clk_register_periph(const char *name, |
203 | const char **parent_names, int num_parents, | 207 | const char **parent_names, int num_parents, |
204 | struct tegra_clk_periph *periph, void __iomem *clk_base, | 208 | struct tegra_clk_periph *periph, void __iomem *clk_base, |
205 | u32 offset) | 209 | u32 offset, unsigned long flags) |
206 | { | 210 | { |
207 | return _tegra_clk_register_periph(name, parent_names, num_parents, | 211 | return _tegra_clk_register_periph(name, parent_names, num_parents, |
208 | periph, clk_base, offset, true); | 212 | periph, clk_base, offset, true, flags); |
209 | } | 213 | } |
210 | 214 | ||
211 | struct clk *tegra_clk_register_periph_nodiv(const char *name, | 215 | struct clk *tegra_clk_register_periph_nodiv(const char *name, |
@@ -214,5 +218,5 @@ struct clk *tegra_clk_register_periph_nodiv(const char *name, | |||
214 | u32 offset) | 218 | u32 offset) |
215 | { | 219 | { |
216 | return _tegra_clk_register_periph(name, parent_names, num_parents, | 220 | return _tegra_clk_register_periph(name, parent_names, num_parents, |
217 | periph, clk_base, offset, false); | 221 | periph, clk_base, offset, false, CLK_SET_RATE_PARENT); |
218 | } | 222 | } |
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 165f24734c1b..17c2cc086eb4 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
5 | * under the terms and conditions of the GNU General Public License, | 5 | * under the terms and conditions of the GNU General Public License, |
@@ -79,6 +79,48 @@ | |||
79 | #define PLLE_SS_CTRL 0x68 | 79 | #define PLLE_SS_CTRL 0x68 |
80 | #define PLLE_SS_DISABLE (7 << 10) | 80 | #define PLLE_SS_DISABLE (7 << 10) |
81 | 81 | ||
82 | #define PLLE_AUX_PLLP_SEL BIT(2) | ||
83 | #define PLLE_AUX_ENABLE_SWCTL BIT(4) | ||
84 | #define PLLE_AUX_SEQ_ENABLE BIT(24) | ||
85 | #define PLLE_AUX_PLLRE_SEL BIT(28) | ||
86 | |||
87 | #define PLLE_MISC_PLLE_PTS BIT(8) | ||
88 | #define PLLE_MISC_IDDQ_SW_VALUE BIT(13) | ||
89 | #define PLLE_MISC_IDDQ_SW_CTRL BIT(14) | ||
90 | #define PLLE_MISC_VREG_BG_CTRL_SHIFT 4 | ||
91 | #define PLLE_MISC_VREG_BG_CTRL_MASK (3 << PLLE_MISC_VREG_BG_CTRL_SHIFT) | ||
92 | #define PLLE_MISC_VREG_CTRL_SHIFT 2 | ||
93 | #define PLLE_MISC_VREG_CTRL_MASK (2 << PLLE_MISC_VREG_CTRL_SHIFT) | ||
94 | |||
95 | #define PLLCX_MISC_STROBE BIT(31) | ||
96 | #define PLLCX_MISC_RESET BIT(30) | ||
97 | #define PLLCX_MISC_SDM_DIV_SHIFT 28 | ||
98 | #define PLLCX_MISC_SDM_DIV_MASK (0x3 << PLLCX_MISC_SDM_DIV_SHIFT) | ||
99 | #define PLLCX_MISC_FILT_DIV_SHIFT 26 | ||
100 | #define PLLCX_MISC_FILT_DIV_MASK (0x3 << PLLCX_MISC_FILT_DIV_SHIFT) | ||
101 | #define PLLCX_MISC_ALPHA_SHIFT 18 | ||
102 | #define PLLCX_MISC_DIV_LOW_RANGE \ | ||
103 | ((0x1 << PLLCX_MISC_SDM_DIV_SHIFT) | \ | ||
104 | (0x1 << PLLCX_MISC_FILT_DIV_SHIFT)) | ||
105 | #define PLLCX_MISC_DIV_HIGH_RANGE \ | ||
106 | ((0x2 << PLLCX_MISC_SDM_DIV_SHIFT) | \ | ||
107 | (0x2 << PLLCX_MISC_FILT_DIV_SHIFT)) | ||
108 | #define PLLCX_MISC_COEF_LOW_RANGE \ | ||
109 | ((0x14 << PLLCX_MISC_KA_SHIFT) | (0x38 << PLLCX_MISC_KB_SHIFT)) | ||
110 | #define PLLCX_MISC_KA_SHIFT 2 | ||
111 | #define PLLCX_MISC_KB_SHIFT 9 | ||
112 | #define PLLCX_MISC_DEFAULT (PLLCX_MISC_COEF_LOW_RANGE | \ | ||
113 | (0x19 << PLLCX_MISC_ALPHA_SHIFT) | \ | ||
114 | PLLCX_MISC_DIV_LOW_RANGE | \ | ||
115 | PLLCX_MISC_RESET) | ||
116 | #define PLLCX_MISC1_DEFAULT 0x000d2308 | ||
117 | #define PLLCX_MISC2_DEFAULT 0x30211200 | ||
118 | #define PLLCX_MISC3_DEFAULT 0x200 | ||
119 | |||
120 | #define PMC_PLLM_WB0_OVERRIDE 0x1dc | ||
121 | #define PMC_PLLM_WB0_OVERRIDE_2 0x2b0 | ||
122 | #define PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK BIT(27) | ||
123 | |||
82 | #define PMC_SATA_PWRGT 0x1ac | 124 | #define PMC_SATA_PWRGT 0x1ac |
83 | #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5) | 125 | #define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5) |
84 | #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4) | 126 | #define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4) |
@@ -101,6 +143,24 @@ | |||
101 | #define divn_max(p) (divn_mask(p)) | 143 | #define divn_max(p) (divn_mask(p)) |
102 | #define divp_max(p) (1 << (divp_mask(p))) | 144 | #define divp_max(p) (1 << (divp_mask(p))) |
103 | 145 | ||
146 | |||
147 | #ifdef CONFIG_ARCH_TEGRA_114_SOC | ||
148 | /* PLLXC has 4-bit PDIV, but entry 15 is not allowed in h/w */ | ||
149 | #define PLLXC_PDIV_MAX 14 | ||
150 | |||
151 | /* non-monotonic mapping below is not a typo */ | ||
152 | static u8 pllxc_p[PLLXC_PDIV_MAX + 1] = { | ||
153 | /* PDIV: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14 */ | ||
154 | /* p: */ 1, 2, 3, 4, 5, 6, 8, 10, 12, 16, 12, 16, 20, 24, 32 | ||
155 | }; | ||
156 | |||
157 | #define PLLCX_PDIV_MAX 7 | ||
158 | static u8 pllcx_p[PLLCX_PDIV_MAX + 1] = { | ||
159 | /* PDIV: 0, 1, 2, 3, 4, 5, 6, 7 */ | ||
160 | /* p: */ 1, 2, 3, 4, 6, 8, 12, 16 | ||
161 | }; | ||
162 | #endif | ||
163 | |||
104 | static void clk_pll_enable_lock(struct tegra_clk_pll *pll) | 164 | static void clk_pll_enable_lock(struct tegra_clk_pll *pll) |
105 | { | 165 | { |
106 | u32 val; | 166 | u32 val; |
@@ -108,25 +168,36 @@ static void clk_pll_enable_lock(struct tegra_clk_pll *pll) | |||
108 | if (!(pll->flags & TEGRA_PLL_USE_LOCK)) | 168 | if (!(pll->flags & TEGRA_PLL_USE_LOCK)) |
109 | return; | 169 | return; |
110 | 170 | ||
171 | if (!(pll->flags & TEGRA_PLL_HAS_LOCK_ENABLE)) | ||
172 | return; | ||
173 | |||
111 | val = pll_readl_misc(pll); | 174 | val = pll_readl_misc(pll); |
112 | val |= BIT(pll->params->lock_enable_bit_idx); | 175 | val |= BIT(pll->params->lock_enable_bit_idx); |
113 | pll_writel_misc(val, pll); | 176 | pll_writel_misc(val, pll); |
114 | } | 177 | } |
115 | 178 | ||
116 | static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll, | 179 | static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll) |
117 | void __iomem *lock_addr, u32 lock_bit_idx) | ||
118 | { | 180 | { |
119 | int i; | 181 | int i; |
120 | u32 val; | 182 | u32 val, lock_mask; |
183 | void __iomem *lock_addr; | ||
121 | 184 | ||
122 | if (!(pll->flags & TEGRA_PLL_USE_LOCK)) { | 185 | if (!(pll->flags & TEGRA_PLL_USE_LOCK)) { |
123 | udelay(pll->params->lock_delay); | 186 | udelay(pll->params->lock_delay); |
124 | return 0; | 187 | return 0; |
125 | } | 188 | } |
126 | 189 | ||
190 | lock_addr = pll->clk_base; | ||
191 | if (pll->flags & TEGRA_PLL_LOCK_MISC) | ||
192 | lock_addr += pll->params->misc_reg; | ||
193 | else | ||
194 | lock_addr += pll->params->base_reg; | ||
195 | |||
196 | lock_mask = pll->params->lock_mask; | ||
197 | |||
127 | for (i = 0; i < pll->params->lock_delay; i++) { | 198 | for (i = 0; i < pll->params->lock_delay; i++) { |
128 | val = readl_relaxed(lock_addr); | 199 | val = readl_relaxed(lock_addr); |
129 | if (val & BIT(lock_bit_idx)) { | 200 | if ((val & lock_mask) == lock_mask) { |
130 | udelay(PLL_POST_LOCK_DELAY); | 201 | udelay(PLL_POST_LOCK_DELAY); |
131 | return 0; | 202 | return 0; |
132 | } | 203 | } |
@@ -155,7 +226,7 @@ static int clk_pll_is_enabled(struct clk_hw *hw) | |||
155 | return val & PLL_BASE_ENABLE ? 1 : 0; | 226 | return val & PLL_BASE_ENABLE ? 1 : 0; |
156 | } | 227 | } |
157 | 228 | ||
158 | static int _clk_pll_enable(struct clk_hw *hw) | 229 | static void _clk_pll_enable(struct clk_hw *hw) |
159 | { | 230 | { |
160 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 231 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
161 | u32 val; | 232 | u32 val; |
@@ -163,7 +234,8 @@ static int _clk_pll_enable(struct clk_hw *hw) | |||
163 | clk_pll_enable_lock(pll); | 234 | clk_pll_enable_lock(pll); |
164 | 235 | ||
165 | val = pll_readl_base(pll); | 236 | val = pll_readl_base(pll); |
166 | val &= ~PLL_BASE_BYPASS; | 237 | if (pll->flags & TEGRA_PLL_BYPASS) |
238 | val &= ~PLL_BASE_BYPASS; | ||
167 | val |= PLL_BASE_ENABLE; | 239 | val |= PLL_BASE_ENABLE; |
168 | pll_writel_base(val, pll); | 240 | pll_writel_base(val, pll); |
169 | 241 | ||
@@ -172,11 +244,6 @@ static int _clk_pll_enable(struct clk_hw *hw) | |||
172 | val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; | 244 | val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE; |
173 | writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); | 245 | writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE); |
174 | } | 246 | } |
175 | |||
176 | clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg, | ||
177 | pll->params->lock_bit_idx); | ||
178 | |||
179 | return 0; | ||
180 | } | 247 | } |
181 | 248 | ||
182 | static void _clk_pll_disable(struct clk_hw *hw) | 249 | static void _clk_pll_disable(struct clk_hw *hw) |
@@ -185,7 +252,9 @@ static void _clk_pll_disable(struct clk_hw *hw) | |||
185 | u32 val; | 252 | u32 val; |
186 | 253 | ||
187 | val = pll_readl_base(pll); | 254 | val = pll_readl_base(pll); |
188 | val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); | 255 | if (pll->flags & TEGRA_PLL_BYPASS) |
256 | val &= ~PLL_BASE_BYPASS; | ||
257 | val &= ~PLL_BASE_ENABLE; | ||
189 | pll_writel_base(val, pll); | 258 | pll_writel_base(val, pll); |
190 | 259 | ||
191 | if (pll->flags & TEGRA_PLLM) { | 260 | if (pll->flags & TEGRA_PLLM) { |
@@ -204,7 +273,9 @@ static int clk_pll_enable(struct clk_hw *hw) | |||
204 | if (pll->lock) | 273 | if (pll->lock) |
205 | spin_lock_irqsave(pll->lock, flags); | 274 | spin_lock_irqsave(pll->lock, flags); |
206 | 275 | ||
207 | ret = _clk_pll_enable(hw); | 276 | _clk_pll_enable(hw); |
277 | |||
278 | ret = clk_pll_wait_for_lock(pll); | ||
208 | 279 | ||
209 | if (pll->lock) | 280 | if (pll->lock) |
210 | spin_unlock_irqrestore(pll->lock, flags); | 281 | spin_unlock_irqrestore(pll->lock, flags); |
@@ -241,8 +312,6 @@ static int _get_table_rate(struct clk_hw *hw, | |||
241 | if (sel->input_rate == 0) | 312 | if (sel->input_rate == 0) |
242 | return -EINVAL; | 313 | return -EINVAL; |
243 | 314 | ||
244 | BUG_ON(sel->p < 1); | ||
245 | |||
246 | cfg->input_rate = sel->input_rate; | 315 | cfg->input_rate = sel->input_rate; |
247 | cfg->output_rate = sel->output_rate; | 316 | cfg->output_rate = sel->output_rate; |
248 | cfg->m = sel->m; | 317 | cfg->m = sel->m; |
@@ -257,6 +326,7 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, | |||
257 | unsigned long rate, unsigned long parent_rate) | 326 | unsigned long rate, unsigned long parent_rate) |
258 | { | 327 | { |
259 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 328 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
329 | struct pdiv_map *p_tohw = pll->params->pdiv_tohw; | ||
260 | unsigned long cfreq; | 330 | unsigned long cfreq; |
261 | u32 p_div = 0; | 331 | u32 p_div = 0; |
262 | 332 | ||
@@ -290,88 +360,119 @@ static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, | |||
290 | cfg->output_rate <<= 1) | 360 | cfg->output_rate <<= 1) |
291 | p_div++; | 361 | p_div++; |
292 | 362 | ||
293 | cfg->p = 1 << p_div; | ||
294 | cfg->m = parent_rate / cfreq; | 363 | cfg->m = parent_rate / cfreq; |
295 | cfg->n = cfg->output_rate / cfreq; | 364 | cfg->n = cfg->output_rate / cfreq; |
296 | cfg->cpcon = OUT_OF_TABLE_CPCON; | 365 | cfg->cpcon = OUT_OF_TABLE_CPCON; |
297 | 366 | ||
298 | if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) || | 367 | if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) || |
299 | cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) { | 368 | (1 << p_div) > divp_max(pll) |
369 | || cfg->output_rate > pll->params->vco_max) { | ||
300 | pr_err("%s: Failed to set %s rate %lu\n", | 370 | pr_err("%s: Failed to set %s rate %lu\n", |
301 | __func__, __clk_get_name(hw->clk), rate); | 371 | __func__, __clk_get_name(hw->clk), rate); |
302 | return -EINVAL; | 372 | return -EINVAL; |
303 | } | 373 | } |
304 | 374 | ||
375 | if (p_tohw) { | ||
376 | p_div = 1 << p_div; | ||
377 | while (p_tohw->pdiv) { | ||
378 | if (p_div <= p_tohw->pdiv) { | ||
379 | cfg->p = p_tohw->hw_val; | ||
380 | break; | ||
381 | } | ||
382 | p_tohw++; | ||
383 | } | ||
384 | if (!p_tohw->pdiv) | ||
385 | return -EINVAL; | ||
386 | } else | ||
387 | cfg->p = p_div; | ||
388 | |||
305 | return 0; | 389 | return 0; |
306 | } | 390 | } |
307 | 391 | ||
308 | static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, | 392 | static void _update_pll_mnp(struct tegra_clk_pll *pll, |
309 | unsigned long rate) | 393 | struct tegra_clk_pll_freq_table *cfg) |
310 | { | 394 | { |
311 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 395 | u32 val; |
312 | unsigned long flags = 0; | ||
313 | u32 divp, val, old_base; | ||
314 | int state; | ||
315 | |||
316 | divp = __ffs(cfg->p); | ||
317 | |||
318 | if (pll->flags & TEGRA_PLLU) | ||
319 | divp ^= 1; | ||
320 | 396 | ||
321 | if (pll->lock) | 397 | val = pll_readl_base(pll); |
322 | spin_lock_irqsave(pll->lock, flags); | ||
323 | 398 | ||
324 | old_base = val = pll_readl_base(pll); | ||
325 | val &= ~((divm_mask(pll) << pll->divm_shift) | | 399 | val &= ~((divm_mask(pll) << pll->divm_shift) | |
326 | (divn_mask(pll) << pll->divn_shift) | | 400 | (divn_mask(pll) << pll->divn_shift) | |
327 | (divp_mask(pll) << pll->divp_shift)); | 401 | (divp_mask(pll) << pll->divp_shift)); |
328 | val |= ((cfg->m << pll->divm_shift) | | 402 | val |= ((cfg->m << pll->divm_shift) | |
329 | (cfg->n << pll->divn_shift) | | 403 | (cfg->n << pll->divn_shift) | |
330 | (divp << pll->divp_shift)); | 404 | (cfg->p << pll->divp_shift)); |
331 | if (val == old_base) { | 405 | |
332 | if (pll->lock) | 406 | pll_writel_base(val, pll); |
333 | spin_unlock_irqrestore(pll->lock, flags); | 407 | } |
334 | return 0; | 408 | |
409 | static void _get_pll_mnp(struct tegra_clk_pll *pll, | ||
410 | struct tegra_clk_pll_freq_table *cfg) | ||
411 | { | ||
412 | u32 val; | ||
413 | |||
414 | val = pll_readl_base(pll); | ||
415 | |||
416 | cfg->m = (val >> pll->divm_shift) & (divm_mask(pll)); | ||
417 | cfg->n = (val >> pll->divn_shift) & (divn_mask(pll)); | ||
418 | cfg->p = (val >> pll->divp_shift) & (divp_mask(pll)); | ||
419 | } | ||
420 | |||
421 | static void _update_pll_cpcon(struct tegra_clk_pll *pll, | ||
422 | struct tegra_clk_pll_freq_table *cfg, | ||
423 | unsigned long rate) | ||
424 | { | ||
425 | u32 val; | ||
426 | |||
427 | val = pll_readl_misc(pll); | ||
428 | |||
429 | val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT); | ||
430 | val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT; | ||
431 | |||
432 | if (pll->flags & TEGRA_PLL_SET_LFCON) { | ||
433 | val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT); | ||
434 | if (cfg->n >= PLLDU_LFCON_SET_DIVN) | ||
435 | val |= 1 << PLL_MISC_LFCON_SHIFT; | ||
436 | } else if (pll->flags & TEGRA_PLL_SET_DCCON) { | ||
437 | val &= ~(1 << PLL_MISC_DCCON_SHIFT); | ||
438 | if (rate >= (pll->params->vco_max >> 1)) | ||
439 | val |= 1 << PLL_MISC_DCCON_SHIFT; | ||
335 | } | 440 | } |
336 | 441 | ||
442 | pll_writel_misc(val, pll); | ||
443 | } | ||
444 | |||
445 | static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg, | ||
446 | unsigned long rate) | ||
447 | { | ||
448 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
449 | int state, ret = 0; | ||
450 | |||
337 | state = clk_pll_is_enabled(hw); | 451 | state = clk_pll_is_enabled(hw); |
338 | 452 | ||
339 | if (state) { | 453 | if (state) |
340 | _clk_pll_disable(hw); | 454 | _clk_pll_disable(hw); |
341 | val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE); | ||
342 | } | ||
343 | pll_writel_base(val, pll); | ||
344 | 455 | ||
345 | if (pll->flags & TEGRA_PLL_HAS_CPCON) { | 456 | _update_pll_mnp(pll, cfg); |
346 | val = pll_readl_misc(pll); | ||
347 | val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT); | ||
348 | val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT; | ||
349 | if (pll->flags & TEGRA_PLL_SET_LFCON) { | ||
350 | val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT); | ||
351 | if (cfg->n >= PLLDU_LFCON_SET_DIVN) | ||
352 | val |= 0x1 << PLL_MISC_LFCON_SHIFT; | ||
353 | } else if (pll->flags & TEGRA_PLL_SET_DCCON) { | ||
354 | val &= ~(0x1 << PLL_MISC_DCCON_SHIFT); | ||
355 | if (rate >= (pll->params->vco_max >> 1)) | ||
356 | val |= 0x1 << PLL_MISC_DCCON_SHIFT; | ||
357 | } | ||
358 | pll_writel_misc(val, pll); | ||
359 | } | ||
360 | 457 | ||
361 | if (pll->lock) | 458 | if (pll->flags & TEGRA_PLL_HAS_CPCON) |
362 | spin_unlock_irqrestore(pll->lock, flags); | 459 | _update_pll_cpcon(pll, cfg, rate); |
363 | 460 | ||
364 | if (state) | 461 | if (state) { |
365 | clk_pll_enable(hw); | 462 | _clk_pll_enable(hw); |
463 | ret = clk_pll_wait_for_lock(pll); | ||
464 | } | ||
366 | 465 | ||
367 | return 0; | 466 | return ret; |
368 | } | 467 | } |
369 | 468 | ||
370 | static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, | 469 | static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, |
371 | unsigned long parent_rate) | 470 | unsigned long parent_rate) |
372 | { | 471 | { |
373 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 472 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
374 | struct tegra_clk_pll_freq_table cfg; | 473 | struct tegra_clk_pll_freq_table cfg, old_cfg; |
474 | unsigned long flags = 0; | ||
475 | int ret = 0; | ||
375 | 476 | ||
376 | if (pll->flags & TEGRA_PLL_FIXED) { | 477 | if (pll->flags & TEGRA_PLL_FIXED) { |
377 | if (rate != pll->fixed_rate) { | 478 | if (rate != pll->fixed_rate) { |
@@ -387,7 +488,18 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate, | |||
387 | _calc_rate(hw, &cfg, rate, parent_rate)) | 488 | _calc_rate(hw, &cfg, rate, parent_rate)) |
388 | return -EINVAL; | 489 | return -EINVAL; |
389 | 490 | ||
390 | return _program_pll(hw, &cfg, rate); | 491 | if (pll->lock) |
492 | spin_lock_irqsave(pll->lock, flags); | ||
493 | |||
494 | _get_pll_mnp(pll, &old_cfg); | ||
495 | |||
496 | if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_cfg.p != cfg.p) | ||
497 | ret = _program_pll(hw, &cfg, rate); | ||
498 | |||
499 | if (pll->lock) | ||
500 | spin_unlock_irqrestore(pll->lock, flags); | ||
501 | |||
502 | return ret; | ||
391 | } | 503 | } |
392 | 504 | ||
393 | static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, | 505 | static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, |
@@ -409,7 +521,7 @@ static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate, | |||
409 | return -EINVAL; | 521 | return -EINVAL; |
410 | 522 | ||
411 | output_rate *= cfg.n; | 523 | output_rate *= cfg.n; |
412 | do_div(output_rate, cfg.m * cfg.p); | 524 | do_div(output_rate, cfg.m * (1 << cfg.p)); |
413 | 525 | ||
414 | return output_rate; | 526 | return output_rate; |
415 | } | 527 | } |
@@ -418,11 +530,15 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, | |||
418 | unsigned long parent_rate) | 530 | unsigned long parent_rate) |
419 | { | 531 | { |
420 | struct tegra_clk_pll *pll = to_clk_pll(hw); | 532 | struct tegra_clk_pll *pll = to_clk_pll(hw); |
421 | u32 val = pll_readl_base(pll); | 533 | struct tegra_clk_pll_freq_table cfg; |
422 | u32 divn = 0, divm = 0, divp = 0; | 534 | struct pdiv_map *p_tohw = pll->params->pdiv_tohw; |
535 | u32 val; | ||
423 | u64 rate = parent_rate; | 536 | u64 rate = parent_rate; |
537 | int pdiv; | ||
538 | |||
539 | val = pll_readl_base(pll); | ||
424 | 540 | ||
425 | if (val & PLL_BASE_BYPASS) | 541 | if ((pll->flags & TEGRA_PLL_BYPASS) && (val & PLL_BASE_BYPASS)) |
426 | return parent_rate; | 542 | return parent_rate; |
427 | 543 | ||
428 | if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) { | 544 | if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) { |
@@ -435,16 +551,29 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hw, | |||
435 | return pll->fixed_rate; | 551 | return pll->fixed_rate; |
436 | } | 552 | } |
437 | 553 | ||
438 | divp = (val >> pll->divp_shift) & (divp_mask(pll)); | 554 | _get_pll_mnp(pll, &cfg); |
439 | if (pll->flags & TEGRA_PLLU) | ||
440 | divp ^= 1; | ||
441 | 555 | ||
442 | divn = (val >> pll->divn_shift) & (divn_mask(pll)); | 556 | if (p_tohw) { |
443 | divm = (val >> pll->divm_shift) & (divm_mask(pll)); | 557 | while (p_tohw->pdiv) { |
444 | divm *= (1 << divp); | 558 | if (cfg.p == p_tohw->hw_val) { |
559 | pdiv = p_tohw->pdiv; | ||
560 | break; | ||
561 | } | ||
562 | p_tohw++; | ||
563 | } | ||
564 | |||
565 | if (!p_tohw->pdiv) { | ||
566 | WARN_ON(1); | ||
567 | pdiv = 1; | ||
568 | } | ||
569 | } else | ||
570 | pdiv = 1 << cfg.p; | ||
571 | |||
572 | cfg.m *= pdiv; | ||
573 | |||
574 | rate *= cfg.n; | ||
575 | do_div(rate, cfg.m); | ||
445 | 576 | ||
446 | rate *= divn; | ||
447 | do_div(rate, divm); | ||
448 | return rate; | 577 | return rate; |
449 | } | 578 | } |
450 | 579 | ||
@@ -538,8 +667,8 @@ static int clk_plle_enable(struct clk_hw *hw) | |||
538 | val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE); | 667 | val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE); |
539 | pll_writel_base(val, pll); | 668 | pll_writel_base(val, pll); |
540 | 669 | ||
541 | clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg, | 670 | clk_pll_wait_for_lock(pll); |
542 | pll->params->lock_bit_idx); | 671 | |
543 | return 0; | 672 | return 0; |
544 | } | 673 | } |
545 | 674 | ||
@@ -577,28 +706,531 @@ const struct clk_ops tegra_clk_plle_ops = { | |||
577 | .enable = clk_plle_enable, | 706 | .enable = clk_plle_enable, |
578 | }; | 707 | }; |
579 | 708 | ||
580 | static struct clk *_tegra_clk_register_pll(const char *name, | 709 | #ifdef CONFIG_ARCH_TEGRA_114_SOC |
581 | const char *parent_name, void __iomem *clk_base, | 710 | |
582 | void __iomem *pmc, unsigned long flags, | 711 | static int _pll_fixed_mdiv(struct tegra_clk_pll_params *pll_params, |
583 | unsigned long fixed_rate, | 712 | unsigned long parent_rate) |
584 | struct tegra_clk_pll_params *pll_params, u8 pll_flags, | 713 | { |
585 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock, | 714 | if (parent_rate > pll_params->cf_max) |
586 | const struct clk_ops *ops) | 715 | return 2; |
716 | else | ||
717 | return 1; | ||
718 | } | ||
719 | |||
720 | static int clk_pll_iddq_enable(struct clk_hw *hw) | ||
721 | { | ||
722 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
723 | unsigned long flags = 0; | ||
724 | |||
725 | u32 val; | ||
726 | int ret; | ||
727 | |||
728 | if (pll->lock) | ||
729 | spin_lock_irqsave(pll->lock, flags); | ||
730 | |||
731 | val = pll_readl(pll->params->iddq_reg, pll); | ||
732 | val &= ~BIT(pll->params->iddq_bit_idx); | ||
733 | pll_writel(val, pll->params->iddq_reg, pll); | ||
734 | udelay(2); | ||
735 | |||
736 | _clk_pll_enable(hw); | ||
737 | |||
738 | ret = clk_pll_wait_for_lock(pll); | ||
739 | |||
740 | if (pll->lock) | ||
741 | spin_unlock_irqrestore(pll->lock, flags); | ||
742 | |||
743 | return 0; | ||
744 | } | ||
745 | |||
746 | static void clk_pll_iddq_disable(struct clk_hw *hw) | ||
747 | { | ||
748 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
749 | unsigned long flags = 0; | ||
750 | u32 val; | ||
751 | |||
752 | if (pll->lock) | ||
753 | spin_lock_irqsave(pll->lock, flags); | ||
754 | |||
755 | _clk_pll_disable(hw); | ||
756 | |||
757 | val = pll_readl(pll->params->iddq_reg, pll); | ||
758 | val |= BIT(pll->params->iddq_bit_idx); | ||
759 | pll_writel(val, pll->params->iddq_reg, pll); | ||
760 | udelay(2); | ||
761 | |||
762 | if (pll->lock) | ||
763 | spin_unlock_irqrestore(pll->lock, flags); | ||
764 | } | ||
765 | |||
766 | static int _calc_dynamic_ramp_rate(struct clk_hw *hw, | ||
767 | struct tegra_clk_pll_freq_table *cfg, | ||
768 | unsigned long rate, unsigned long parent_rate) | ||
769 | { | ||
770 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
771 | unsigned int p; | ||
772 | |||
773 | if (!rate) | ||
774 | return -EINVAL; | ||
775 | |||
776 | p = DIV_ROUND_UP(pll->params->vco_min, rate); | ||
777 | cfg->m = _pll_fixed_mdiv(pll->params, parent_rate); | ||
778 | cfg->p = p; | ||
779 | cfg->output_rate = rate * cfg->p; | ||
780 | cfg->n = cfg->output_rate * cfg->m / parent_rate; | ||
781 | |||
782 | if (cfg->n > divn_max(pll) || cfg->output_rate > pll->params->vco_max) | ||
783 | return -EINVAL; | ||
784 | |||
785 | return 0; | ||
786 | } | ||
787 | |||
788 | static int _pll_ramp_calc_pll(struct clk_hw *hw, | ||
789 | struct tegra_clk_pll_freq_table *cfg, | ||
790 | unsigned long rate, unsigned long parent_rate) | ||
791 | { | ||
792 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
793 | int err = 0; | ||
794 | |||
795 | err = _get_table_rate(hw, cfg, rate, parent_rate); | ||
796 | if (err < 0) | ||
797 | err = _calc_dynamic_ramp_rate(hw, cfg, rate, parent_rate); | ||
798 | else if (cfg->m != _pll_fixed_mdiv(pll->params, parent_rate)) { | ||
799 | WARN_ON(1); | ||
800 | err = -EINVAL; | ||
801 | goto out; | ||
802 | } | ||
803 | |||
804 | if (!cfg->p || (cfg->p > pll->params->max_p)) | ||
805 | err = -EINVAL; | ||
806 | |||
807 | out: | ||
808 | return err; | ||
809 | } | ||
810 | |||
811 | static int clk_pllxc_set_rate(struct clk_hw *hw, unsigned long rate, | ||
812 | unsigned long parent_rate) | ||
813 | { | ||
814 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
815 | struct tegra_clk_pll_freq_table cfg, old_cfg; | ||
816 | unsigned long flags = 0; | ||
817 | int ret = 0; | ||
818 | u8 old_p; | ||
819 | |||
820 | ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate); | ||
821 | if (ret < 0) | ||
822 | return ret; | ||
823 | |||
824 | if (pll->lock) | ||
825 | spin_lock_irqsave(pll->lock, flags); | ||
826 | |||
827 | _get_pll_mnp(pll, &old_cfg); | ||
828 | |||
829 | old_p = pllxc_p[old_cfg.p]; | ||
830 | if (old_cfg.m != cfg.m || old_cfg.n != cfg.n || old_p != cfg.p) { | ||
831 | cfg.p -= 1; | ||
832 | ret = _program_pll(hw, &cfg, rate); | ||
833 | } | ||
834 | |||
835 | if (pll->lock) | ||
836 | spin_unlock_irqrestore(pll->lock, flags); | ||
837 | |||
838 | return ret; | ||
839 | } | ||
840 | |||
841 | static long clk_pll_ramp_round_rate(struct clk_hw *hw, unsigned long rate, | ||
842 | unsigned long *prate) | ||
843 | { | ||
844 | struct tegra_clk_pll_freq_table cfg; | ||
845 | int ret = 0; | ||
846 | u64 output_rate = *prate; | ||
847 | |||
848 | ret = _pll_ramp_calc_pll(hw, &cfg, rate, *prate); | ||
849 | if (ret < 0) | ||
850 | return ret; | ||
851 | |||
852 | output_rate *= cfg.n; | ||
853 | do_div(output_rate, cfg.m * cfg.p); | ||
854 | |||
855 | return output_rate; | ||
856 | } | ||
857 | |||
858 | static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate, | ||
859 | unsigned long parent_rate) | ||
860 | { | ||
861 | struct tegra_clk_pll_freq_table cfg; | ||
862 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
863 | unsigned long flags = 0; | ||
864 | int state, ret = 0; | ||
865 | u32 val; | ||
866 | |||
867 | if (pll->lock) | ||
868 | spin_lock_irqsave(pll->lock, flags); | ||
869 | |||
870 | state = clk_pll_is_enabled(hw); | ||
871 | if (state) { | ||
872 | if (rate != clk_get_rate(hw->clk)) { | ||
873 | pr_err("%s: Cannot change active PLLM\n", __func__); | ||
874 | ret = -EINVAL; | ||
875 | goto out; | ||
876 | } | ||
877 | goto out; | ||
878 | } | ||
879 | |||
880 | ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate); | ||
881 | if (ret < 0) | ||
882 | goto out; | ||
883 | |||
884 | cfg.p -= 1; | ||
885 | |||
886 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE); | ||
887 | if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE) { | ||
888 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE_2); | ||
889 | val = cfg.p ? (val | PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK) : | ||
890 | (val & ~PMC_PLLM_WB0_OVERRIDE_2_DIVP_MASK); | ||
891 | writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE_2); | ||
892 | |||
893 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE); | ||
894 | val &= ~(divn_mask(pll) | divm_mask(pll)); | ||
895 | val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift); | ||
896 | writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE); | ||
897 | } else | ||
898 | _update_pll_mnp(pll, &cfg); | ||
899 | |||
900 | |||
901 | out: | ||
902 | if (pll->lock) | ||
903 | spin_unlock_irqrestore(pll->lock, flags); | ||
904 | |||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | static void _pllcx_strobe(struct tegra_clk_pll *pll) | ||
909 | { | ||
910 | u32 val; | ||
911 | |||
912 | val = pll_readl_misc(pll); | ||
913 | val |= PLLCX_MISC_STROBE; | ||
914 | pll_writel_misc(val, pll); | ||
915 | udelay(2); | ||
916 | |||
917 | val &= ~PLLCX_MISC_STROBE; | ||
918 | pll_writel_misc(val, pll); | ||
919 | } | ||
920 | |||
921 | static int clk_pllc_enable(struct clk_hw *hw) | ||
922 | { | ||
923 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
924 | u32 val; | ||
925 | int ret = 0; | ||
926 | unsigned long flags = 0; | ||
927 | |||
928 | if (pll->lock) | ||
929 | spin_lock_irqsave(pll->lock, flags); | ||
930 | |||
931 | _clk_pll_enable(hw); | ||
932 | udelay(2); | ||
933 | |||
934 | val = pll_readl_misc(pll); | ||
935 | val &= ~PLLCX_MISC_RESET; | ||
936 | pll_writel_misc(val, pll); | ||
937 | udelay(2); | ||
938 | |||
939 | _pllcx_strobe(pll); | ||
940 | |||
941 | ret = clk_pll_wait_for_lock(pll); | ||
942 | |||
943 | if (pll->lock) | ||
944 | spin_unlock_irqrestore(pll->lock, flags); | ||
945 | |||
946 | return ret; | ||
947 | } | ||
948 | |||
949 | static void _clk_pllc_disable(struct clk_hw *hw) | ||
950 | { | ||
951 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
952 | u32 val; | ||
953 | |||
954 | _clk_pll_disable(hw); | ||
955 | |||
956 | val = pll_readl_misc(pll); | ||
957 | val |= PLLCX_MISC_RESET; | ||
958 | pll_writel_misc(val, pll); | ||
959 | udelay(2); | ||
960 | } | ||
961 | |||
962 | static void clk_pllc_disable(struct clk_hw *hw) | ||
963 | { | ||
964 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
965 | unsigned long flags = 0; | ||
966 | |||
967 | if (pll->lock) | ||
968 | spin_lock_irqsave(pll->lock, flags); | ||
969 | |||
970 | _clk_pllc_disable(hw); | ||
971 | |||
972 | if (pll->lock) | ||
973 | spin_unlock_irqrestore(pll->lock, flags); | ||
974 | } | ||
975 | |||
976 | static int _pllcx_update_dynamic_coef(struct tegra_clk_pll *pll, | ||
977 | unsigned long input_rate, u32 n) | ||
978 | { | ||
979 | u32 val, n_threshold; | ||
980 | |||
981 | switch (input_rate) { | ||
982 | case 12000000: | ||
983 | n_threshold = 70; | ||
984 | break; | ||
985 | case 13000000: | ||
986 | case 26000000: | ||
987 | n_threshold = 71; | ||
988 | break; | ||
989 | case 16800000: | ||
990 | n_threshold = 55; | ||
991 | break; | ||
992 | case 19200000: | ||
993 | n_threshold = 48; | ||
994 | break; | ||
995 | default: | ||
996 | pr_err("%s: Unexpected reference rate %lu\n", | ||
997 | __func__, input_rate); | ||
998 | return -EINVAL; | ||
999 | } | ||
1000 | |||
1001 | val = pll_readl_misc(pll); | ||
1002 | val &= ~(PLLCX_MISC_SDM_DIV_MASK | PLLCX_MISC_FILT_DIV_MASK); | ||
1003 | val |= n <= n_threshold ? | ||
1004 | PLLCX_MISC_DIV_LOW_RANGE : PLLCX_MISC_DIV_HIGH_RANGE; | ||
1005 | pll_writel_misc(val, pll); | ||
1006 | |||
1007 | return 0; | ||
1008 | } | ||
1009 | |||
1010 | static int clk_pllc_set_rate(struct clk_hw *hw, unsigned long rate, | ||
1011 | unsigned long parent_rate) | ||
1012 | { | ||
1013 | struct tegra_clk_pll_freq_table cfg; | ||
1014 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
1015 | unsigned long flags = 0; | ||
1016 | int state, ret = 0; | ||
1017 | u32 val; | ||
1018 | u16 old_m, old_n; | ||
1019 | u8 old_p; | ||
1020 | |||
1021 | if (pll->lock) | ||
1022 | spin_lock_irqsave(pll->lock, flags); | ||
1023 | |||
1024 | ret = _pll_ramp_calc_pll(hw, &cfg, rate, parent_rate); | ||
1025 | if (ret < 0) | ||
1026 | goto out; | ||
1027 | |||
1028 | val = pll_readl_base(pll); | ||
1029 | old_m = (val >> pll->divm_shift) & (divm_mask(pll)); | ||
1030 | old_n = (val >> pll->divn_shift) & (divn_mask(pll)); | ||
1031 | old_p = pllcx_p[(val >> pll->divp_shift) & (divp_mask(pll))]; | ||
1032 | |||
1033 | if (cfg.m != old_m) { | ||
1034 | WARN_ON(1); | ||
1035 | goto out; | ||
1036 | } | ||
1037 | |||
1038 | if (old_n == cfg.n && old_p == cfg.p) | ||
1039 | goto out; | ||
1040 | |||
1041 | cfg.p -= 1; | ||
1042 | |||
1043 | state = clk_pll_is_enabled(hw); | ||
1044 | if (state) | ||
1045 | _clk_pllc_disable(hw); | ||
1046 | |||
1047 | ret = _pllcx_update_dynamic_coef(pll, parent_rate, cfg.n); | ||
1048 | if (ret < 0) | ||
1049 | goto out; | ||
1050 | |||
1051 | _update_pll_mnp(pll, &cfg); | ||
1052 | |||
1053 | if (state) | ||
1054 | ret = clk_pllc_enable(hw); | ||
1055 | |||
1056 | out: | ||
1057 | if (pll->lock) | ||
1058 | spin_unlock_irqrestore(pll->lock, flags); | ||
1059 | |||
1060 | return ret; | ||
1061 | } | ||
1062 | |||
1063 | static long _pllre_calc_rate(struct tegra_clk_pll *pll, | ||
1064 | struct tegra_clk_pll_freq_table *cfg, | ||
1065 | unsigned long rate, unsigned long parent_rate) | ||
1066 | { | ||
1067 | u16 m, n; | ||
1068 | u64 output_rate = parent_rate; | ||
1069 | |||
1070 | m = _pll_fixed_mdiv(pll->params, parent_rate); | ||
1071 | n = rate * m / parent_rate; | ||
1072 | |||
1073 | output_rate *= n; | ||
1074 | do_div(output_rate, m); | ||
1075 | |||
1076 | if (cfg) { | ||
1077 | cfg->m = m; | ||
1078 | cfg->n = n; | ||
1079 | } | ||
1080 | |||
1081 | return output_rate; | ||
1082 | } | ||
1083 | static int clk_pllre_set_rate(struct clk_hw *hw, unsigned long rate, | ||
1084 | unsigned long parent_rate) | ||
1085 | { | ||
1086 | struct tegra_clk_pll_freq_table cfg, old_cfg; | ||
1087 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
1088 | unsigned long flags = 0; | ||
1089 | int state, ret = 0; | ||
1090 | |||
1091 | if (pll->lock) | ||
1092 | spin_lock_irqsave(pll->lock, flags); | ||
1093 | |||
1094 | _pllre_calc_rate(pll, &cfg, rate, parent_rate); | ||
1095 | _get_pll_mnp(pll, &old_cfg); | ||
1096 | cfg.p = old_cfg.p; | ||
1097 | |||
1098 | if (cfg.m != old_cfg.m || cfg.n != old_cfg.n) { | ||
1099 | state = clk_pll_is_enabled(hw); | ||
1100 | if (state) | ||
1101 | _clk_pll_disable(hw); | ||
1102 | |||
1103 | _update_pll_mnp(pll, &cfg); | ||
1104 | |||
1105 | if (state) { | ||
1106 | _clk_pll_enable(hw); | ||
1107 | ret = clk_pll_wait_for_lock(pll); | ||
1108 | } | ||
1109 | } | ||
1110 | |||
1111 | if (pll->lock) | ||
1112 | spin_unlock_irqrestore(pll->lock, flags); | ||
1113 | |||
1114 | return ret; | ||
1115 | } | ||
1116 | |||
1117 | static unsigned long clk_pllre_recalc_rate(struct clk_hw *hw, | ||
1118 | unsigned long parent_rate) | ||
1119 | { | ||
1120 | struct tegra_clk_pll_freq_table cfg; | ||
1121 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
1122 | u64 rate = parent_rate; | ||
1123 | |||
1124 | _get_pll_mnp(pll, &cfg); | ||
1125 | |||
1126 | rate *= cfg.n; | ||
1127 | do_div(rate, cfg.m); | ||
1128 | |||
1129 | return rate; | ||
1130 | } | ||
1131 | |||
1132 | static long clk_pllre_round_rate(struct clk_hw *hw, unsigned long rate, | ||
1133 | unsigned long *prate) | ||
1134 | { | ||
1135 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
1136 | |||
1137 | return _pllre_calc_rate(pll, NULL, rate, *prate); | ||
1138 | } | ||
1139 | |||
1140 | static int clk_plle_tegra114_enable(struct clk_hw *hw) | ||
1141 | { | ||
1142 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
1143 | struct tegra_clk_pll_freq_table sel; | ||
1144 | u32 val; | ||
1145 | int ret; | ||
1146 | unsigned long flags = 0; | ||
1147 | unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk)); | ||
1148 | |||
1149 | if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate)) | ||
1150 | return -EINVAL; | ||
1151 | |||
1152 | if (pll->lock) | ||
1153 | spin_lock_irqsave(pll->lock, flags); | ||
1154 | |||
1155 | val = pll_readl_base(pll); | ||
1156 | val &= ~BIT(29); /* Disable lock override */ | ||
1157 | pll_writel_base(val, pll); | ||
1158 | |||
1159 | val = pll_readl(pll->params->aux_reg, pll); | ||
1160 | val |= PLLE_AUX_ENABLE_SWCTL; | ||
1161 | val &= ~PLLE_AUX_SEQ_ENABLE; | ||
1162 | pll_writel(val, pll->params->aux_reg, pll); | ||
1163 | udelay(1); | ||
1164 | |||
1165 | val = pll_readl_misc(pll); | ||
1166 | val |= PLLE_MISC_LOCK_ENABLE; | ||
1167 | val |= PLLE_MISC_IDDQ_SW_CTRL; | ||
1168 | val &= ~PLLE_MISC_IDDQ_SW_VALUE; | ||
1169 | val |= PLLE_MISC_PLLE_PTS; | ||
1170 | val |= PLLE_MISC_VREG_BG_CTRL_MASK | PLLE_MISC_VREG_CTRL_MASK; | ||
1171 | pll_writel_misc(val, pll); | ||
1172 | udelay(5); | ||
1173 | |||
1174 | val = pll_readl(PLLE_SS_CTRL, pll); | ||
1175 | val |= PLLE_SS_DISABLE; | ||
1176 | pll_writel(val, PLLE_SS_CTRL, pll); | ||
1177 | |||
1178 | val = pll_readl_base(pll); | ||
1179 | val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); | ||
1180 | val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); | ||
1181 | val |= sel.m << pll->divm_shift; | ||
1182 | val |= sel.n << pll->divn_shift; | ||
1183 | val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; | ||
1184 | pll_writel_base(val, pll); | ||
1185 | udelay(1); | ||
1186 | |||
1187 | _clk_pll_enable(hw); | ||
1188 | ret = clk_pll_wait_for_lock(pll); | ||
1189 | |||
1190 | if (ret < 0) | ||
1191 | goto out; | ||
1192 | |||
1193 | /* TODO: enable hw control of xusb brick pll */ | ||
1194 | |||
1195 | out: | ||
1196 | if (pll->lock) | ||
1197 | spin_unlock_irqrestore(pll->lock, flags); | ||
1198 | |||
1199 | return ret; | ||
1200 | } | ||
1201 | |||
1202 | static void clk_plle_tegra114_disable(struct clk_hw *hw) | ||
1203 | { | ||
1204 | struct tegra_clk_pll *pll = to_clk_pll(hw); | ||
1205 | unsigned long flags = 0; | ||
1206 | u32 val; | ||
1207 | |||
1208 | if (pll->lock) | ||
1209 | spin_lock_irqsave(pll->lock, flags); | ||
1210 | |||
1211 | _clk_pll_disable(hw); | ||
1212 | |||
1213 | val = pll_readl_misc(pll); | ||
1214 | val |= PLLE_MISC_IDDQ_SW_CTRL | PLLE_MISC_IDDQ_SW_VALUE; | ||
1215 | pll_writel_misc(val, pll); | ||
1216 | udelay(1); | ||
1217 | |||
1218 | if (pll->lock) | ||
1219 | spin_unlock_irqrestore(pll->lock, flags); | ||
1220 | } | ||
1221 | #endif | ||
1222 | |||
1223 | static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base, | ||
1224 | void __iomem *pmc, unsigned long fixed_rate, | ||
1225 | struct tegra_clk_pll_params *pll_params, u32 pll_flags, | ||
1226 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) | ||
587 | { | 1227 | { |
588 | struct tegra_clk_pll *pll; | 1228 | struct tegra_clk_pll *pll; |
589 | struct clk *clk; | ||
590 | struct clk_init_data init; | ||
591 | 1229 | ||
592 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); | 1230 | pll = kzalloc(sizeof(*pll), GFP_KERNEL); |
593 | if (!pll) | 1231 | if (!pll) |
594 | return ERR_PTR(-ENOMEM); | 1232 | return ERR_PTR(-ENOMEM); |
595 | 1233 | ||
596 | init.name = name; | ||
597 | init.ops = ops; | ||
598 | init.flags = flags; | ||
599 | init.parent_names = (parent_name ? &parent_name : NULL); | ||
600 | init.num_parents = (parent_name ? 1 : 0); | ||
601 | |||
602 | pll->clk_base = clk_base; | 1234 | pll->clk_base = clk_base; |
603 | pll->pmc = pmc; | 1235 | pll->pmc = pmc; |
604 | 1236 | ||
@@ -615,34 +1247,336 @@ static struct clk *_tegra_clk_register_pll(const char *name, | |||
615 | pll->divm_shift = PLL_BASE_DIVM_SHIFT; | 1247 | pll->divm_shift = PLL_BASE_DIVM_SHIFT; |
616 | pll->divm_width = PLL_BASE_DIVM_WIDTH; | 1248 | pll->divm_width = PLL_BASE_DIVM_WIDTH; |
617 | 1249 | ||
1250 | return pll; | ||
1251 | } | ||
1252 | |||
1253 | static struct clk *_tegra_clk_register_pll(struct tegra_clk_pll *pll, | ||
1254 | const char *name, const char *parent_name, unsigned long flags, | ||
1255 | const struct clk_ops *ops) | ||
1256 | { | ||
1257 | struct clk_init_data init; | ||
1258 | |||
1259 | init.name = name; | ||
1260 | init.ops = ops; | ||
1261 | init.flags = flags; | ||
1262 | init.parent_names = (parent_name ? &parent_name : NULL); | ||
1263 | init.num_parents = (parent_name ? 1 : 0); | ||
1264 | |||
618 | /* Data in .init is copied by clk_register(), so stack variable OK */ | 1265 | /* Data in .init is copied by clk_register(), so stack variable OK */ |
619 | pll->hw.init = &init; | 1266 | pll->hw.init = &init; |
620 | 1267 | ||
621 | clk = clk_register(NULL, &pll->hw); | 1268 | return clk_register(NULL, &pll->hw); |
622 | if (IS_ERR(clk)) | ||
623 | kfree(pll); | ||
624 | |||
625 | return clk; | ||
626 | } | 1269 | } |
627 | 1270 | ||
628 | struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, | 1271 | struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, |
629 | void __iomem *clk_base, void __iomem *pmc, | 1272 | void __iomem *clk_base, void __iomem *pmc, |
630 | unsigned long flags, unsigned long fixed_rate, | 1273 | unsigned long flags, unsigned long fixed_rate, |
631 | struct tegra_clk_pll_params *pll_params, u8 pll_flags, | 1274 | struct tegra_clk_pll_params *pll_params, u32 pll_flags, |
632 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) | 1275 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) |
633 | { | 1276 | { |
634 | return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, | 1277 | struct tegra_clk_pll *pll; |
635 | flags, fixed_rate, pll_params, pll_flags, freq_table, | 1278 | struct clk *clk; |
636 | lock, &tegra_clk_pll_ops); | 1279 | |
1280 | pll_flags |= TEGRA_PLL_BYPASS; | ||
1281 | pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; | ||
1282 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, | ||
1283 | freq_table, lock); | ||
1284 | if (IS_ERR(pll)) | ||
1285 | return ERR_CAST(pll); | ||
1286 | |||
1287 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
1288 | &tegra_clk_pll_ops); | ||
1289 | if (IS_ERR(clk)) | ||
1290 | kfree(pll); | ||
1291 | |||
1292 | return clk; | ||
637 | } | 1293 | } |
638 | 1294 | ||
639 | struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, | 1295 | struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, |
640 | void __iomem *clk_base, void __iomem *pmc, | 1296 | void __iomem *clk_base, void __iomem *pmc, |
641 | unsigned long flags, unsigned long fixed_rate, | 1297 | unsigned long flags, unsigned long fixed_rate, |
642 | struct tegra_clk_pll_params *pll_params, u8 pll_flags, | 1298 | struct tegra_clk_pll_params *pll_params, u32 pll_flags, |
643 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) | 1299 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock) |
644 | { | 1300 | { |
645 | return _tegra_clk_register_pll(name, parent_name, clk_base, pmc, | 1301 | struct tegra_clk_pll *pll; |
646 | flags, fixed_rate, pll_params, pll_flags, freq_table, | 1302 | struct clk *clk; |
647 | lock, &tegra_clk_plle_ops); | 1303 | |
1304 | pll_flags |= TEGRA_PLL_LOCK_MISC | TEGRA_PLL_BYPASS; | ||
1305 | pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; | ||
1306 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, | ||
1307 | freq_table, lock); | ||
1308 | if (IS_ERR(pll)) | ||
1309 | return ERR_CAST(pll); | ||
1310 | |||
1311 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
1312 | &tegra_clk_plle_ops); | ||
1313 | if (IS_ERR(clk)) | ||
1314 | kfree(pll); | ||
1315 | |||
1316 | return clk; | ||
1317 | } | ||
1318 | |||
1319 | #ifdef CONFIG_ARCH_TEGRA_114_SOC | ||
1320 | const struct clk_ops tegra_clk_pllxc_ops = { | ||
1321 | .is_enabled = clk_pll_is_enabled, | ||
1322 | .enable = clk_pll_iddq_enable, | ||
1323 | .disable = clk_pll_iddq_disable, | ||
1324 | .recalc_rate = clk_pll_recalc_rate, | ||
1325 | .round_rate = clk_pll_ramp_round_rate, | ||
1326 | .set_rate = clk_pllxc_set_rate, | ||
1327 | }; | ||
1328 | |||
1329 | const struct clk_ops tegra_clk_pllm_ops = { | ||
1330 | .is_enabled = clk_pll_is_enabled, | ||
1331 | .enable = clk_pll_iddq_enable, | ||
1332 | .disable = clk_pll_iddq_disable, | ||
1333 | .recalc_rate = clk_pll_recalc_rate, | ||
1334 | .round_rate = clk_pll_ramp_round_rate, | ||
1335 | .set_rate = clk_pllm_set_rate, | ||
1336 | }; | ||
1337 | |||
1338 | const struct clk_ops tegra_clk_pllc_ops = { | ||
1339 | .is_enabled = clk_pll_is_enabled, | ||
1340 | .enable = clk_pllc_enable, | ||
1341 | .disable = clk_pllc_disable, | ||
1342 | .recalc_rate = clk_pll_recalc_rate, | ||
1343 | .round_rate = clk_pll_ramp_round_rate, | ||
1344 | .set_rate = clk_pllc_set_rate, | ||
1345 | }; | ||
1346 | |||
1347 | const struct clk_ops tegra_clk_pllre_ops = { | ||
1348 | .is_enabled = clk_pll_is_enabled, | ||
1349 | .enable = clk_pll_iddq_enable, | ||
1350 | .disable = clk_pll_iddq_disable, | ||
1351 | .recalc_rate = clk_pllre_recalc_rate, | ||
1352 | .round_rate = clk_pllre_round_rate, | ||
1353 | .set_rate = clk_pllre_set_rate, | ||
1354 | }; | ||
1355 | |||
1356 | const struct clk_ops tegra_clk_plle_tegra114_ops = { | ||
1357 | .is_enabled = clk_pll_is_enabled, | ||
1358 | .enable = clk_plle_tegra114_enable, | ||
1359 | .disable = clk_plle_tegra114_disable, | ||
1360 | .recalc_rate = clk_pll_recalc_rate, | ||
1361 | }; | ||
1362 | |||
1363 | |||
1364 | struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, | ||
1365 | void __iomem *clk_base, void __iomem *pmc, | ||
1366 | unsigned long flags, unsigned long fixed_rate, | ||
1367 | struct tegra_clk_pll_params *pll_params, | ||
1368 | u32 pll_flags, | ||
1369 | struct tegra_clk_pll_freq_table *freq_table, | ||
1370 | spinlock_t *lock) | ||
1371 | { | ||
1372 | struct tegra_clk_pll *pll; | ||
1373 | struct clk *clk; | ||
1374 | |||
1375 | if (!pll_params->pdiv_tohw) | ||
1376 | return ERR_PTR(-EINVAL); | ||
1377 | |||
1378 | pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; | ||
1379 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, | ||
1380 | freq_table, lock); | ||
1381 | if (IS_ERR(pll)) | ||
1382 | return ERR_CAST(pll); | ||
1383 | |||
1384 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
1385 | &tegra_clk_pllxc_ops); | ||
1386 | if (IS_ERR(clk)) | ||
1387 | kfree(pll); | ||
1388 | |||
1389 | return clk; | ||
1390 | } | ||
1391 | |||
1392 | struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, | ||
1393 | void __iomem *clk_base, void __iomem *pmc, | ||
1394 | unsigned long flags, unsigned long fixed_rate, | ||
1395 | struct tegra_clk_pll_params *pll_params, | ||
1396 | u32 pll_flags, | ||
1397 | struct tegra_clk_pll_freq_table *freq_table, | ||
1398 | spinlock_t *lock, unsigned long parent_rate) | ||
1399 | { | ||
1400 | u32 val; | ||
1401 | struct tegra_clk_pll *pll; | ||
1402 | struct clk *clk; | ||
1403 | |||
1404 | pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; | ||
1405 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, | ||
1406 | freq_table, lock); | ||
1407 | if (IS_ERR(pll)) | ||
1408 | return ERR_CAST(pll); | ||
1409 | |||
1410 | /* program minimum rate by default */ | ||
1411 | |||
1412 | val = pll_readl_base(pll); | ||
1413 | if (val & PLL_BASE_ENABLE) | ||
1414 | WARN_ON(val & pll_params->iddq_bit_idx); | ||
1415 | else { | ||
1416 | int m; | ||
1417 | |||
1418 | m = _pll_fixed_mdiv(pll_params, parent_rate); | ||
1419 | val = m << PLL_BASE_DIVM_SHIFT; | ||
1420 | val |= (pll_params->vco_min / parent_rate) | ||
1421 | << PLL_BASE_DIVN_SHIFT; | ||
1422 | pll_writel_base(val, pll); | ||
1423 | } | ||
1424 | |||
1425 | /* disable lock override */ | ||
1426 | |||
1427 | val = pll_readl_misc(pll); | ||
1428 | val &= ~BIT(29); | ||
1429 | pll_writel_misc(val, pll); | ||
1430 | |||
1431 | pll_flags |= TEGRA_PLL_LOCK_MISC; | ||
1432 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
1433 | &tegra_clk_pllre_ops); | ||
1434 | if (IS_ERR(clk)) | ||
1435 | kfree(pll); | ||
1436 | |||
1437 | return clk; | ||
1438 | } | ||
1439 | |||
1440 | struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, | ||
1441 | void __iomem *clk_base, void __iomem *pmc, | ||
1442 | unsigned long flags, unsigned long fixed_rate, | ||
1443 | struct tegra_clk_pll_params *pll_params, | ||
1444 | u32 pll_flags, | ||
1445 | struct tegra_clk_pll_freq_table *freq_table, | ||
1446 | spinlock_t *lock) | ||
1447 | { | ||
1448 | struct tegra_clk_pll *pll; | ||
1449 | struct clk *clk; | ||
1450 | |||
1451 | if (!pll_params->pdiv_tohw) | ||
1452 | return ERR_PTR(-EINVAL); | ||
1453 | |||
1454 | pll_flags |= TEGRA_PLL_BYPASS; | ||
1455 | pll_flags |= TEGRA_PLL_HAS_LOCK_ENABLE; | ||
1456 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, | ||
1457 | freq_table, lock); | ||
1458 | if (IS_ERR(pll)) | ||
1459 | return ERR_CAST(pll); | ||
1460 | |||
1461 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
1462 | &tegra_clk_pllm_ops); | ||
1463 | if (IS_ERR(clk)) | ||
1464 | kfree(pll); | ||
1465 | |||
1466 | return clk; | ||
1467 | } | ||
1468 | |||
1469 | struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, | ||
1470 | void __iomem *clk_base, void __iomem *pmc, | ||
1471 | unsigned long flags, unsigned long fixed_rate, | ||
1472 | struct tegra_clk_pll_params *pll_params, | ||
1473 | u32 pll_flags, | ||
1474 | struct tegra_clk_pll_freq_table *freq_table, | ||
1475 | spinlock_t *lock) | ||
1476 | { | ||
1477 | struct clk *parent, *clk; | ||
1478 | struct pdiv_map *p_tohw = pll_params->pdiv_tohw; | ||
1479 | struct tegra_clk_pll *pll; | ||
1480 | struct tegra_clk_pll_freq_table cfg; | ||
1481 | unsigned long parent_rate; | ||
1482 | |||
1483 | if (!p_tohw) | ||
1484 | return ERR_PTR(-EINVAL); | ||
1485 | |||
1486 | parent = __clk_lookup(parent_name); | ||
1487 | if (IS_ERR(parent)) { | ||
1488 | WARN(1, "parent clk %s of %s must be registered first\n", | ||
1489 | name, parent_name); | ||
1490 | return ERR_PTR(-EINVAL); | ||
1491 | } | ||
1492 | |||
1493 | pll_flags |= TEGRA_PLL_BYPASS; | ||
1494 | pll = _tegra_init_pll(clk_base, pmc, fixed_rate, pll_params, pll_flags, | ||
1495 | freq_table, lock); | ||
1496 | if (IS_ERR(pll)) | ||
1497 | return ERR_CAST(pll); | ||
1498 | |||
1499 | parent_rate = __clk_get_rate(parent); | ||
1500 | |||
1501 | /* | ||
1502 | * Most of PLLC register fields are shadowed, and can not be read | ||
1503 | * directly from PLL h/w. Hence, actual PLLC boot state is unknown. | ||
1504 | * Initialize PLL to default state: disabled, reset; shadow registers | ||
1505 | * loaded with default parameters; dividers are preset for half of | ||
1506 | * minimum VCO rate (the latter assured that shadowed divider settings | ||
1507 | * are within supported range). | ||
1508 | */ | ||
1509 | |||
1510 | cfg.m = _pll_fixed_mdiv(pll_params, parent_rate); | ||
1511 | cfg.n = cfg.m * pll_params->vco_min / parent_rate; | ||
1512 | |||
1513 | while (p_tohw->pdiv) { | ||
1514 | if (p_tohw->pdiv == 2) { | ||
1515 | cfg.p = p_tohw->hw_val; | ||
1516 | break; | ||
1517 | } | ||
1518 | p_tohw++; | ||
1519 | } | ||
1520 | |||
1521 | if (!p_tohw->pdiv) { | ||
1522 | WARN_ON(1); | ||
1523 | return ERR_PTR(-EINVAL); | ||
1524 | } | ||
1525 | |||
1526 | pll_writel_base(0, pll); | ||
1527 | _update_pll_mnp(pll, &cfg); | ||
1528 | |||
1529 | pll_writel_misc(PLLCX_MISC_DEFAULT, pll); | ||
1530 | pll_writel(PLLCX_MISC1_DEFAULT, pll_params->ext_misc_reg[0], pll); | ||
1531 | pll_writel(PLLCX_MISC2_DEFAULT, pll_params->ext_misc_reg[1], pll); | ||
1532 | pll_writel(PLLCX_MISC3_DEFAULT, pll_params->ext_misc_reg[2], pll); | ||
1533 | |||
1534 | _pllcx_update_dynamic_coef(pll, parent_rate, cfg.n); | ||
1535 | |||
1536 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
1537 | &tegra_clk_pllc_ops); | ||
1538 | if (IS_ERR(clk)) | ||
1539 | kfree(pll); | ||
1540 | |||
1541 | return clk; | ||
1542 | } | ||
1543 | |||
1544 | struct clk *tegra_clk_register_plle_tegra114(const char *name, | ||
1545 | const char *parent_name, | ||
1546 | void __iomem *clk_base, unsigned long flags, | ||
1547 | unsigned long fixed_rate, | ||
1548 | struct tegra_clk_pll_params *pll_params, | ||
1549 | struct tegra_clk_pll_freq_table *freq_table, | ||
1550 | spinlock_t *lock) | ||
1551 | { | ||
1552 | struct tegra_clk_pll *pll; | ||
1553 | struct clk *clk; | ||
1554 | u32 val, val_aux; | ||
1555 | |||
1556 | pll = _tegra_init_pll(clk_base, NULL, fixed_rate, pll_params, | ||
1557 | TEGRA_PLL_HAS_LOCK_ENABLE, freq_table, lock); | ||
1558 | if (IS_ERR(pll)) | ||
1559 | return ERR_CAST(pll); | ||
1560 | |||
1561 | /* ensure parent is set to pll_re_vco */ | ||
1562 | |||
1563 | val = pll_readl_base(pll); | ||
1564 | val_aux = pll_readl(pll_params->aux_reg, pll); | ||
1565 | |||
1566 | if (val & PLL_BASE_ENABLE) { | ||
1567 | if (!(val_aux & PLLE_AUX_PLLRE_SEL)) | ||
1568 | WARN(1, "pll_e enabled with unsupported parent %s\n", | ||
1569 | (val & PLLE_AUX_PLLP_SEL) ? "pllp_out0" : "pll_ref"); | ||
1570 | } else { | ||
1571 | val_aux |= PLLE_AUX_PLLRE_SEL; | ||
1572 | pll_writel(val, pll_params->aux_reg, pll); | ||
1573 | } | ||
1574 | |||
1575 | clk = _tegra_clk_register_pll(pll, name, parent_name, flags, | ||
1576 | &tegra_clk_plle_tegra114_ops); | ||
1577 | if (IS_ERR(clk)) | ||
1578 | kfree(pll); | ||
1579 | |||
1580 | return clk; | ||
648 | } | 1581 | } |
1582 | #endif | ||
diff --git a/drivers/clk/tegra/clk-tegra114.c b/drivers/clk/tegra/clk-tegra114.c new file mode 100644 index 000000000000..d78e16ee161c --- /dev/null +++ b/drivers/clk/tegra/clk-tegra114.c | |||
@@ -0,0 +1,2085 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012, 2013, NVIDIA CORPORATION. All rights reserved. | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License | ||
14 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
15 | */ | ||
16 | |||
17 | #include <linux/io.h> | ||
18 | #include <linux/clk.h> | ||
19 | #include <linux/clk-provider.h> | ||
20 | #include <linux/clkdev.h> | ||
21 | #include <linux/of.h> | ||
22 | #include <linux/of_address.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/clk/tegra.h> | ||
25 | |||
26 | #include "clk.h" | ||
27 | |||
28 | #define RST_DEVICES_L 0x004 | ||
29 | #define RST_DEVICES_H 0x008 | ||
30 | #define RST_DEVICES_U 0x00C | ||
31 | #define RST_DEVICES_V 0x358 | ||
32 | #define RST_DEVICES_W 0x35C | ||
33 | #define RST_DEVICES_X 0x28C | ||
34 | #define RST_DEVICES_SET_L 0x300 | ||
35 | #define RST_DEVICES_CLR_L 0x304 | ||
36 | #define RST_DEVICES_SET_H 0x308 | ||
37 | #define RST_DEVICES_CLR_H 0x30c | ||
38 | #define RST_DEVICES_SET_U 0x310 | ||
39 | #define RST_DEVICES_CLR_U 0x314 | ||
40 | #define RST_DEVICES_SET_V 0x430 | ||
41 | #define RST_DEVICES_CLR_V 0x434 | ||
42 | #define RST_DEVICES_SET_W 0x438 | ||
43 | #define RST_DEVICES_CLR_W 0x43c | ||
44 | #define RST_DEVICES_NUM 5 | ||
45 | |||
46 | #define CLK_OUT_ENB_L 0x010 | ||
47 | #define CLK_OUT_ENB_H 0x014 | ||
48 | #define CLK_OUT_ENB_U 0x018 | ||
49 | #define CLK_OUT_ENB_V 0x360 | ||
50 | #define CLK_OUT_ENB_W 0x364 | ||
51 | #define CLK_OUT_ENB_X 0x280 | ||
52 | #define CLK_OUT_ENB_SET_L 0x320 | ||
53 | #define CLK_OUT_ENB_CLR_L 0x324 | ||
54 | #define CLK_OUT_ENB_SET_H 0x328 | ||
55 | #define CLK_OUT_ENB_CLR_H 0x32c | ||
56 | #define CLK_OUT_ENB_SET_U 0x330 | ||
57 | #define CLK_OUT_ENB_CLR_U 0x334 | ||
58 | #define CLK_OUT_ENB_SET_V 0x440 | ||
59 | #define CLK_OUT_ENB_CLR_V 0x444 | ||
60 | #define CLK_OUT_ENB_SET_W 0x448 | ||
61 | #define CLK_OUT_ENB_CLR_W 0x44c | ||
62 | #define CLK_OUT_ENB_SET_X 0x284 | ||
63 | #define CLK_OUT_ENB_CLR_X 0x288 | ||
64 | #define CLK_OUT_ENB_NUM 6 | ||
65 | |||
66 | #define PLLC_BASE 0x80 | ||
67 | #define PLLC_MISC2 0x88 | ||
68 | #define PLLC_MISC 0x8c | ||
69 | #define PLLC2_BASE 0x4e8 | ||
70 | #define PLLC2_MISC 0x4ec | ||
71 | #define PLLC3_BASE 0x4fc | ||
72 | #define PLLC3_MISC 0x500 | ||
73 | #define PLLM_BASE 0x90 | ||
74 | #define PLLM_MISC 0x9c | ||
75 | #define PLLP_BASE 0xa0 | ||
76 | #define PLLP_MISC 0xac | ||
77 | #define PLLX_BASE 0xe0 | ||
78 | #define PLLX_MISC 0xe4 | ||
79 | #define PLLX_MISC2 0x514 | ||
80 | #define PLLX_MISC3 0x518 | ||
81 | #define PLLD_BASE 0xd0 | ||
82 | #define PLLD_MISC 0xdc | ||
83 | #define PLLD2_BASE 0x4b8 | ||
84 | #define PLLD2_MISC 0x4bc | ||
85 | #define PLLE_BASE 0xe8 | ||
86 | #define PLLE_MISC 0xec | ||
87 | #define PLLA_BASE 0xb0 | ||
88 | #define PLLA_MISC 0xbc | ||
89 | #define PLLU_BASE 0xc0 | ||
90 | #define PLLU_MISC 0xcc | ||
91 | #define PLLRE_BASE 0x4c4 | ||
92 | #define PLLRE_MISC 0x4c8 | ||
93 | |||
94 | #define PLL_MISC_LOCK_ENABLE 18 | ||
95 | #define PLLC_MISC_LOCK_ENABLE 24 | ||
96 | #define PLLDU_MISC_LOCK_ENABLE 22 | ||
97 | #define PLLE_MISC_LOCK_ENABLE 9 | ||
98 | #define PLLRE_MISC_LOCK_ENABLE 30 | ||
99 | |||
100 | #define PLLC_IDDQ_BIT 26 | ||
101 | #define PLLX_IDDQ_BIT 3 | ||
102 | #define PLLRE_IDDQ_BIT 16 | ||
103 | |||
104 | #define PLL_BASE_LOCK BIT(27) | ||
105 | #define PLLE_MISC_LOCK BIT(11) | ||
106 | #define PLLRE_MISC_LOCK BIT(24) | ||
107 | #define PLLCX_BASE_LOCK (BIT(26)|BIT(27)) | ||
108 | |||
109 | #define PLLE_AUX 0x48c | ||
110 | #define PLLC_OUT 0x84 | ||
111 | #define PLLM_OUT 0x94 | ||
112 | #define PLLP_OUTA 0xa4 | ||
113 | #define PLLP_OUTB 0xa8 | ||
114 | #define PLLA_OUT 0xb4 | ||
115 | |||
116 | #define AUDIO_SYNC_CLK_I2S0 0x4a0 | ||
117 | #define AUDIO_SYNC_CLK_I2S1 0x4a4 | ||
118 | #define AUDIO_SYNC_CLK_I2S2 0x4a8 | ||
119 | #define AUDIO_SYNC_CLK_I2S3 0x4ac | ||
120 | #define AUDIO_SYNC_CLK_I2S4 0x4b0 | ||
121 | #define AUDIO_SYNC_CLK_SPDIF 0x4b4 | ||
122 | |||
123 | #define AUDIO_SYNC_DOUBLER 0x49c | ||
124 | |||
125 | #define PMC_CLK_OUT_CNTRL 0x1a8 | ||
126 | #define PMC_DPD_PADS_ORIDE 0x1c | ||
127 | #define PMC_DPD_PADS_ORIDE_BLINK_ENB 20 | ||
128 | #define PMC_CTRL 0 | ||
129 | #define PMC_CTRL_BLINK_ENB 7 | ||
130 | |||
131 | #define OSC_CTRL 0x50 | ||
132 | #define OSC_CTRL_OSC_FREQ_SHIFT 28 | ||
133 | #define OSC_CTRL_PLL_REF_DIV_SHIFT 26 | ||
134 | |||
135 | #define PLLXC_SW_MAX_P 6 | ||
136 | |||
137 | #define CCLKG_BURST_POLICY 0x368 | ||
138 | #define CCLKLP_BURST_POLICY 0x370 | ||
139 | #define SCLK_BURST_POLICY 0x028 | ||
140 | #define SYSTEM_CLK_RATE 0x030 | ||
141 | |||
142 | #define UTMIP_PLL_CFG2 0x488 | ||
143 | #define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6) | ||
144 | #define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18) | ||
145 | #define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0) | ||
146 | #define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2) | ||
147 | #define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4) | ||
148 | |||
149 | #define UTMIP_PLL_CFG1 0x484 | ||
150 | #define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6) | ||
151 | #define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0) | ||
152 | #define UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP BIT(17) | ||
153 | #define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16) | ||
154 | #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP BIT(15) | ||
155 | #define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14) | ||
156 | #define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12) | ||
157 | |||
158 | #define UTMIPLL_HW_PWRDN_CFG0 0x52c | ||
159 | #define UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE BIT(25) | ||
160 | #define UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE BIT(24) | ||
161 | #define UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET BIT(6) | ||
162 | #define UTMIPLL_HW_PWRDN_CFG0_SEQ_RESET_INPUT_VALUE BIT(5) | ||
163 | #define UTMIPLL_HW_PWRDN_CFG0_SEQ_IN_SWCTL BIT(4) | ||
164 | #define UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL BIT(2) | ||
165 | #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE BIT(1) | ||
166 | #define UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL BIT(0) | ||
167 | |||
168 | #define CLK_SOURCE_I2S0 0x1d8 | ||
169 | #define CLK_SOURCE_I2S1 0x100 | ||
170 | #define CLK_SOURCE_I2S2 0x104 | ||
171 | #define CLK_SOURCE_NDFLASH 0x160 | ||
172 | #define CLK_SOURCE_I2S3 0x3bc | ||
173 | #define CLK_SOURCE_I2S4 0x3c0 | ||
174 | #define CLK_SOURCE_SPDIF_OUT 0x108 | ||
175 | #define CLK_SOURCE_SPDIF_IN 0x10c | ||
176 | #define CLK_SOURCE_PWM 0x110 | ||
177 | #define CLK_SOURCE_ADX 0x638 | ||
178 | #define CLK_SOURCE_AMX 0x63c | ||
179 | #define CLK_SOURCE_HDA 0x428 | ||
180 | #define CLK_SOURCE_HDA2CODEC_2X 0x3e4 | ||
181 | #define CLK_SOURCE_SBC1 0x134 | ||
182 | #define CLK_SOURCE_SBC2 0x118 | ||
183 | #define CLK_SOURCE_SBC3 0x11c | ||
184 | #define CLK_SOURCE_SBC4 0x1b4 | ||
185 | #define CLK_SOURCE_SBC5 0x3c8 | ||
186 | #define CLK_SOURCE_SBC6 0x3cc | ||
187 | #define CLK_SOURCE_SATA_OOB 0x420 | ||
188 | #define CLK_SOURCE_SATA 0x424 | ||
189 | #define CLK_SOURCE_NDSPEED 0x3f8 | ||
190 | #define CLK_SOURCE_VFIR 0x168 | ||
191 | #define CLK_SOURCE_SDMMC1 0x150 | ||
192 | #define CLK_SOURCE_SDMMC2 0x154 | ||
193 | #define CLK_SOURCE_SDMMC3 0x1bc | ||
194 | #define CLK_SOURCE_SDMMC4 0x164 | ||
195 | #define CLK_SOURCE_VDE 0x1c8 | ||
196 | #define CLK_SOURCE_CSITE 0x1d4 | ||
197 | #define CLK_SOURCE_LA 0x1f8 | ||
198 | #define CLK_SOURCE_TRACE 0x634 | ||
199 | #define CLK_SOURCE_OWR 0x1cc | ||
200 | #define CLK_SOURCE_NOR 0x1d0 | ||
201 | #define CLK_SOURCE_MIPI 0x174 | ||
202 | #define CLK_SOURCE_I2C1 0x124 | ||
203 | #define CLK_SOURCE_I2C2 0x198 | ||
204 | #define CLK_SOURCE_I2C3 0x1b8 | ||
205 | #define CLK_SOURCE_I2C4 0x3c4 | ||
206 | #define CLK_SOURCE_I2C5 0x128 | ||
207 | #define CLK_SOURCE_UARTA 0x178 | ||
208 | #define CLK_SOURCE_UARTB 0x17c | ||
209 | #define CLK_SOURCE_UARTC 0x1a0 | ||
210 | #define CLK_SOURCE_UARTD 0x1c0 | ||
211 | #define CLK_SOURCE_UARTE 0x1c4 | ||
212 | #define CLK_SOURCE_UARTA_DBG 0x178 | ||
213 | #define CLK_SOURCE_UARTB_DBG 0x17c | ||
214 | #define CLK_SOURCE_UARTC_DBG 0x1a0 | ||
215 | #define CLK_SOURCE_UARTD_DBG 0x1c0 | ||
216 | #define CLK_SOURCE_UARTE_DBG 0x1c4 | ||
217 | #define CLK_SOURCE_3D 0x158 | ||
218 | #define CLK_SOURCE_2D 0x15c | ||
219 | #define CLK_SOURCE_VI_SENSOR 0x1a8 | ||
220 | #define CLK_SOURCE_VI 0x148 | ||
221 | #define CLK_SOURCE_EPP 0x16c | ||
222 | #define CLK_SOURCE_MSENC 0x1f0 | ||
223 | #define CLK_SOURCE_TSEC 0x1f4 | ||
224 | #define CLK_SOURCE_HOST1X 0x180 | ||
225 | #define CLK_SOURCE_HDMI 0x18c | ||
226 | #define CLK_SOURCE_DISP1 0x138 | ||
227 | #define CLK_SOURCE_DISP2 0x13c | ||
228 | #define CLK_SOURCE_CILAB 0x614 | ||
229 | #define CLK_SOURCE_CILCD 0x618 | ||
230 | #define CLK_SOURCE_CILE 0x61c | ||
231 | #define CLK_SOURCE_DSIALP 0x620 | ||
232 | #define CLK_SOURCE_DSIBLP 0x624 | ||
233 | #define CLK_SOURCE_TSENSOR 0x3b8 | ||
234 | #define CLK_SOURCE_D_AUDIO 0x3d0 | ||
235 | #define CLK_SOURCE_DAM0 0x3d8 | ||
236 | #define CLK_SOURCE_DAM1 0x3dc | ||
237 | #define CLK_SOURCE_DAM2 0x3e0 | ||
238 | #define CLK_SOURCE_ACTMON 0x3e8 | ||
239 | #define CLK_SOURCE_EXTERN1 0x3ec | ||
240 | #define CLK_SOURCE_EXTERN2 0x3f0 | ||
241 | #define CLK_SOURCE_EXTERN3 0x3f4 | ||
242 | #define CLK_SOURCE_I2CSLOW 0x3fc | ||
243 | #define CLK_SOURCE_SE 0x42c | ||
244 | #define CLK_SOURCE_MSELECT 0x3b4 | ||
245 | #define CLK_SOURCE_SOC_THERM 0x644 | ||
246 | #define CLK_SOURCE_XUSB_HOST_SRC 0x600 | ||
247 | #define CLK_SOURCE_XUSB_FALCON_SRC 0x604 | ||
248 | #define CLK_SOURCE_XUSB_FS_SRC 0x608 | ||
249 | #define CLK_SOURCE_XUSB_SS_SRC 0x610 | ||
250 | #define CLK_SOURCE_XUSB_DEV_SRC 0x60c | ||
251 | #define CLK_SOURCE_EMC 0x19c | ||
252 | |||
253 | static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32]; | ||
254 | |||
255 | static void __iomem *clk_base; | ||
256 | static void __iomem *pmc_base; | ||
257 | |||
258 | static DEFINE_SPINLOCK(pll_d_lock); | ||
259 | static DEFINE_SPINLOCK(pll_d2_lock); | ||
260 | static DEFINE_SPINLOCK(pll_u_lock); | ||
261 | static DEFINE_SPINLOCK(pll_div_lock); | ||
262 | static DEFINE_SPINLOCK(pll_re_lock); | ||
263 | static DEFINE_SPINLOCK(clk_doubler_lock); | ||
264 | static DEFINE_SPINLOCK(clk_out_lock); | ||
265 | static DEFINE_SPINLOCK(sysrate_lock); | ||
266 | |||
267 | static struct pdiv_map pllxc_p[] = { | ||
268 | { .pdiv = 1, .hw_val = 0 }, | ||
269 | { .pdiv = 2, .hw_val = 1 }, | ||
270 | { .pdiv = 3, .hw_val = 2 }, | ||
271 | { .pdiv = 4, .hw_val = 3 }, | ||
272 | { .pdiv = 5, .hw_val = 4 }, | ||
273 | { .pdiv = 6, .hw_val = 5 }, | ||
274 | { .pdiv = 8, .hw_val = 6 }, | ||
275 | { .pdiv = 10, .hw_val = 7 }, | ||
276 | { .pdiv = 12, .hw_val = 8 }, | ||
277 | { .pdiv = 16, .hw_val = 9 }, | ||
278 | { .pdiv = 12, .hw_val = 10 }, | ||
279 | { .pdiv = 16, .hw_val = 11 }, | ||
280 | { .pdiv = 20, .hw_val = 12 }, | ||
281 | { .pdiv = 24, .hw_val = 13 }, | ||
282 | { .pdiv = 32, .hw_val = 14 }, | ||
283 | { .pdiv = 0, .hw_val = 0 }, | ||
284 | }; | ||
285 | |||
286 | static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { | ||
287 | { 12000000, 624000000, 104, 0, 2}, | ||
288 | { 12000000, 600000000, 100, 0, 2}, | ||
289 | { 13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */ | ||
290 | { 16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */ | ||
291 | { 19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */ | ||
292 | { 26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ | ||
293 | { 0, 0, 0, 0, 0, 0 }, | ||
294 | }; | ||
295 | |||
296 | static struct tegra_clk_pll_params pll_c_params = { | ||
297 | .input_min = 12000000, | ||
298 | .input_max = 800000000, | ||
299 | .cf_min = 12000000, | ||
300 | .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ | ||
301 | .vco_min = 600000000, | ||
302 | .vco_max = 1400000000, | ||
303 | .base_reg = PLLC_BASE, | ||
304 | .misc_reg = PLLC_MISC, | ||
305 | .lock_mask = PLL_BASE_LOCK, | ||
306 | .lock_enable_bit_idx = PLLC_MISC_LOCK_ENABLE, | ||
307 | .lock_delay = 300, | ||
308 | .iddq_reg = PLLC_MISC, | ||
309 | .iddq_bit_idx = PLLC_IDDQ_BIT, | ||
310 | .max_p = PLLXC_SW_MAX_P, | ||
311 | .dyn_ramp_reg = PLLC_MISC2, | ||
312 | .stepa_shift = 17, | ||
313 | .stepb_shift = 9, | ||
314 | .pdiv_tohw = pllxc_p, | ||
315 | }; | ||
316 | |||
317 | static struct pdiv_map pllc_p[] = { | ||
318 | { .pdiv = 1, .hw_val = 0 }, | ||
319 | { .pdiv = 2, .hw_val = 1 }, | ||
320 | { .pdiv = 4, .hw_val = 3 }, | ||
321 | { .pdiv = 8, .hw_val = 5 }, | ||
322 | { .pdiv = 16, .hw_val = 7 }, | ||
323 | { .pdiv = 0, .hw_val = 0 }, | ||
324 | }; | ||
325 | |||
326 | static struct tegra_clk_pll_freq_table pll_cx_freq_table[] = { | ||
327 | {12000000, 600000000, 100, 0, 2}, | ||
328 | {13000000, 600000000, 92, 0, 2}, /* actual: 598.0 MHz */ | ||
329 | {16800000, 600000000, 71, 0, 2}, /* actual: 596.4 MHz */ | ||
330 | {19200000, 600000000, 62, 0, 2}, /* actual: 595.2 MHz */ | ||
331 | {26000000, 600000000, 92, 1, 2}, /* actual: 598.0 MHz */ | ||
332 | {0, 0, 0, 0, 0, 0}, | ||
333 | }; | ||
334 | |||
335 | static struct tegra_clk_pll_params pll_c2_params = { | ||
336 | .input_min = 12000000, | ||
337 | .input_max = 48000000, | ||
338 | .cf_min = 12000000, | ||
339 | .cf_max = 19200000, | ||
340 | .vco_min = 600000000, | ||
341 | .vco_max = 1200000000, | ||
342 | .base_reg = PLLC2_BASE, | ||
343 | .misc_reg = PLLC2_MISC, | ||
344 | .lock_mask = PLL_BASE_LOCK, | ||
345 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
346 | .lock_delay = 300, | ||
347 | .pdiv_tohw = pllc_p, | ||
348 | .ext_misc_reg[0] = 0x4f0, | ||
349 | .ext_misc_reg[1] = 0x4f4, | ||
350 | .ext_misc_reg[2] = 0x4f8, | ||
351 | }; | ||
352 | |||
353 | static struct tegra_clk_pll_params pll_c3_params = { | ||
354 | .input_min = 12000000, | ||
355 | .input_max = 48000000, | ||
356 | .cf_min = 12000000, | ||
357 | .cf_max = 19200000, | ||
358 | .vco_min = 600000000, | ||
359 | .vco_max = 1200000000, | ||
360 | .base_reg = PLLC3_BASE, | ||
361 | .misc_reg = PLLC3_MISC, | ||
362 | .lock_mask = PLL_BASE_LOCK, | ||
363 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
364 | .lock_delay = 300, | ||
365 | .pdiv_tohw = pllc_p, | ||
366 | .ext_misc_reg[0] = 0x504, | ||
367 | .ext_misc_reg[1] = 0x508, | ||
368 | .ext_misc_reg[2] = 0x50c, | ||
369 | }; | ||
370 | |||
371 | static struct pdiv_map pllm_p[] = { | ||
372 | { .pdiv = 1, .hw_val = 0 }, | ||
373 | { .pdiv = 2, .hw_val = 1 }, | ||
374 | { .pdiv = 0, .hw_val = 0 }, | ||
375 | }; | ||
376 | |||
377 | static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { | ||
378 | {12000000, 800000000, 66, 0, 1}, /* actual: 792.0 MHz */ | ||
379 | {13000000, 800000000, 61, 0, 1}, /* actual: 793.0 MHz */ | ||
380 | {16800000, 800000000, 47, 0, 1}, /* actual: 789.6 MHz */ | ||
381 | {19200000, 800000000, 41, 0, 1}, /* actual: 787.2 MHz */ | ||
382 | {26000000, 800000000, 61, 1, 1}, /* actual: 793.0 MHz */ | ||
383 | {0, 0, 0, 0, 0, 0}, | ||
384 | }; | ||
385 | |||
386 | static struct tegra_clk_pll_params pll_m_params = { | ||
387 | .input_min = 12000000, | ||
388 | .input_max = 500000000, | ||
389 | .cf_min = 12000000, | ||
390 | .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ | ||
391 | .vco_min = 400000000, | ||
392 | .vco_max = 1066000000, | ||
393 | .base_reg = PLLM_BASE, | ||
394 | .misc_reg = PLLM_MISC, | ||
395 | .lock_mask = PLL_BASE_LOCK, | ||
396 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
397 | .lock_delay = 300, | ||
398 | .max_p = 2, | ||
399 | .pdiv_tohw = pllm_p, | ||
400 | }; | ||
401 | |||
402 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { | ||
403 | {12000000, 216000000, 432, 12, 1, 8}, | ||
404 | {13000000, 216000000, 432, 13, 1, 8}, | ||
405 | {16800000, 216000000, 360, 14, 1, 8}, | ||
406 | {19200000, 216000000, 360, 16, 1, 8}, | ||
407 | {26000000, 216000000, 432, 26, 1, 8}, | ||
408 | {0, 0, 0, 0, 0, 0}, | ||
409 | }; | ||
410 | |||
411 | static struct tegra_clk_pll_params pll_p_params = { | ||
412 | .input_min = 2000000, | ||
413 | .input_max = 31000000, | ||
414 | .cf_min = 1000000, | ||
415 | .cf_max = 6000000, | ||
416 | .vco_min = 200000000, | ||
417 | .vco_max = 700000000, | ||
418 | .base_reg = PLLP_BASE, | ||
419 | .misc_reg = PLLP_MISC, | ||
420 | .lock_mask = PLL_BASE_LOCK, | ||
421 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
422 | .lock_delay = 300, | ||
423 | }; | ||
424 | |||
425 | static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { | ||
426 | {9600000, 282240000, 147, 5, 0, 4}, | ||
427 | {9600000, 368640000, 192, 5, 0, 4}, | ||
428 | {9600000, 240000000, 200, 8, 0, 8}, | ||
429 | |||
430 | {28800000, 282240000, 245, 25, 0, 8}, | ||
431 | {28800000, 368640000, 320, 25, 0, 8}, | ||
432 | {28800000, 240000000, 200, 24, 0, 8}, | ||
433 | {0, 0, 0, 0, 0, 0}, | ||
434 | }; | ||
435 | |||
436 | |||
437 | static struct tegra_clk_pll_params pll_a_params = { | ||
438 | .input_min = 2000000, | ||
439 | .input_max = 31000000, | ||
440 | .cf_min = 1000000, | ||
441 | .cf_max = 6000000, | ||
442 | .vco_min = 200000000, | ||
443 | .vco_max = 700000000, | ||
444 | .base_reg = PLLA_BASE, | ||
445 | .misc_reg = PLLA_MISC, | ||
446 | .lock_mask = PLL_BASE_LOCK, | ||
447 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
448 | .lock_delay = 300, | ||
449 | }; | ||
450 | |||
451 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { | ||
452 | {12000000, 216000000, 864, 12, 2, 12}, | ||
453 | {13000000, 216000000, 864, 13, 2, 12}, | ||
454 | {16800000, 216000000, 720, 14, 2, 12}, | ||
455 | {19200000, 216000000, 720, 16, 2, 12}, | ||
456 | {26000000, 216000000, 864, 26, 2, 12}, | ||
457 | |||
458 | {12000000, 594000000, 594, 12, 0, 12}, | ||
459 | {13000000, 594000000, 594, 13, 0, 12}, | ||
460 | {16800000, 594000000, 495, 14, 0, 12}, | ||
461 | {19200000, 594000000, 495, 16, 0, 12}, | ||
462 | {26000000, 594000000, 594, 26, 0, 12}, | ||
463 | |||
464 | {12000000, 1000000000, 1000, 12, 0, 12}, | ||
465 | {13000000, 1000000000, 1000, 13, 0, 12}, | ||
466 | {19200000, 1000000000, 625, 12, 0, 12}, | ||
467 | {26000000, 1000000000, 1000, 26, 0, 12}, | ||
468 | |||
469 | {0, 0, 0, 0, 0, 0}, | ||
470 | }; | ||
471 | |||
472 | static struct tegra_clk_pll_params pll_d_params = { | ||
473 | .input_min = 2000000, | ||
474 | .input_max = 40000000, | ||
475 | .cf_min = 1000000, | ||
476 | .cf_max = 6000000, | ||
477 | .vco_min = 500000000, | ||
478 | .vco_max = 1000000000, | ||
479 | .base_reg = PLLD_BASE, | ||
480 | .misc_reg = PLLD_MISC, | ||
481 | .lock_mask = PLL_BASE_LOCK, | ||
482 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | ||
483 | .lock_delay = 1000, | ||
484 | }; | ||
485 | |||
486 | static struct tegra_clk_pll_params pll_d2_params = { | ||
487 | .input_min = 2000000, | ||
488 | .input_max = 40000000, | ||
489 | .cf_min = 1000000, | ||
490 | .cf_max = 6000000, | ||
491 | .vco_min = 500000000, | ||
492 | .vco_max = 1000000000, | ||
493 | .base_reg = PLLD2_BASE, | ||
494 | .misc_reg = PLLD2_MISC, | ||
495 | .lock_mask = PLL_BASE_LOCK, | ||
496 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | ||
497 | .lock_delay = 1000, | ||
498 | }; | ||
499 | |||
500 | static struct pdiv_map pllu_p[] = { | ||
501 | { .pdiv = 1, .hw_val = 1 }, | ||
502 | { .pdiv = 2, .hw_val = 0 }, | ||
503 | { .pdiv = 0, .hw_val = 0 }, | ||
504 | }; | ||
505 | |||
506 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { | ||
507 | {12000000, 480000000, 960, 12, 0, 12}, | ||
508 | {13000000, 480000000, 960, 13, 0, 12}, | ||
509 | {16800000, 480000000, 400, 7, 0, 5}, | ||
510 | {19200000, 480000000, 200, 4, 0, 3}, | ||
511 | {26000000, 480000000, 960, 26, 0, 12}, | ||
512 | {0, 0, 0, 0, 0, 0}, | ||
513 | }; | ||
514 | |||
515 | static struct tegra_clk_pll_params pll_u_params = { | ||
516 | .input_min = 2000000, | ||
517 | .input_max = 40000000, | ||
518 | .cf_min = 1000000, | ||
519 | .cf_max = 6000000, | ||
520 | .vco_min = 480000000, | ||
521 | .vco_max = 960000000, | ||
522 | .base_reg = PLLU_BASE, | ||
523 | .misc_reg = PLLU_MISC, | ||
524 | .lock_mask = PLL_BASE_LOCK, | ||
525 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | ||
526 | .lock_delay = 1000, | ||
527 | .pdiv_tohw = pllu_p, | ||
528 | }; | ||
529 | |||
530 | static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { | ||
531 | /* 1 GHz */ | ||
532 | {12000000, 1000000000, 83, 0, 1}, /* actual: 996.0 MHz */ | ||
533 | {13000000, 1000000000, 76, 0, 1}, /* actual: 988.0 MHz */ | ||
534 | {16800000, 1000000000, 59, 0, 1}, /* actual: 991.2 MHz */ | ||
535 | {19200000, 1000000000, 52, 0, 1}, /* actual: 998.4 MHz */ | ||
536 | {26000000, 1000000000, 76, 1, 1}, /* actual: 988.0 MHz */ | ||
537 | |||
538 | {0, 0, 0, 0, 0, 0}, | ||
539 | }; | ||
540 | |||
541 | static struct tegra_clk_pll_params pll_x_params = { | ||
542 | .input_min = 12000000, | ||
543 | .input_max = 800000000, | ||
544 | .cf_min = 12000000, | ||
545 | .cf_max = 19200000, /* s/w policy, h/w capability 50 MHz */ | ||
546 | .vco_min = 700000000, | ||
547 | .vco_max = 2400000000U, | ||
548 | .base_reg = PLLX_BASE, | ||
549 | .misc_reg = PLLX_MISC, | ||
550 | .lock_mask = PLL_BASE_LOCK, | ||
551 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | ||
552 | .lock_delay = 300, | ||
553 | .iddq_reg = PLLX_MISC3, | ||
554 | .iddq_bit_idx = PLLX_IDDQ_BIT, | ||
555 | .max_p = PLLXC_SW_MAX_P, | ||
556 | .dyn_ramp_reg = PLLX_MISC2, | ||
557 | .stepa_shift = 16, | ||
558 | .stepb_shift = 24, | ||
559 | .pdiv_tohw = pllxc_p, | ||
560 | }; | ||
561 | |||
562 | static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { | ||
563 | /* PLLE special case: use cpcon field to store cml divider value */ | ||
564 | {336000000, 100000000, 100, 21, 16, 11}, | ||
565 | {312000000, 100000000, 200, 26, 24, 13}, | ||
566 | {0, 0, 0, 0, 0, 0}, | ||
567 | }; | ||
568 | |||
569 | static struct tegra_clk_pll_params pll_e_params = { | ||
570 | .input_min = 12000000, | ||
571 | .input_max = 1000000000, | ||
572 | .cf_min = 12000000, | ||
573 | .cf_max = 75000000, | ||
574 | .vco_min = 1600000000, | ||
575 | .vco_max = 2400000000U, | ||
576 | .base_reg = PLLE_BASE, | ||
577 | .misc_reg = PLLE_MISC, | ||
578 | .aux_reg = PLLE_AUX, | ||
579 | .lock_mask = PLLE_MISC_LOCK, | ||
580 | .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, | ||
581 | .lock_delay = 300, | ||
582 | }; | ||
583 | |||
584 | static struct tegra_clk_pll_params pll_re_vco_params = { | ||
585 | .input_min = 12000000, | ||
586 | .input_max = 1000000000, | ||
587 | .cf_min = 12000000, | ||
588 | .cf_max = 19200000, /* s/w policy, h/w capability 38 MHz */ | ||
589 | .vco_min = 300000000, | ||
590 | .vco_max = 600000000, | ||
591 | .base_reg = PLLRE_BASE, | ||
592 | .misc_reg = PLLRE_MISC, | ||
593 | .lock_mask = PLLRE_MISC_LOCK, | ||
594 | .lock_enable_bit_idx = PLLRE_MISC_LOCK_ENABLE, | ||
595 | .lock_delay = 300, | ||
596 | .iddq_reg = PLLRE_MISC, | ||
597 | .iddq_bit_idx = PLLRE_IDDQ_BIT, | ||
598 | }; | ||
599 | |||
600 | /* Peripheral clock registers */ | ||
601 | |||
602 | static struct tegra_clk_periph_regs periph_l_regs = { | ||
603 | .enb_reg = CLK_OUT_ENB_L, | ||
604 | .enb_set_reg = CLK_OUT_ENB_SET_L, | ||
605 | .enb_clr_reg = CLK_OUT_ENB_CLR_L, | ||
606 | .rst_reg = RST_DEVICES_L, | ||
607 | .rst_set_reg = RST_DEVICES_SET_L, | ||
608 | .rst_clr_reg = RST_DEVICES_CLR_L, | ||
609 | }; | ||
610 | |||
611 | static struct tegra_clk_periph_regs periph_h_regs = { | ||
612 | .enb_reg = CLK_OUT_ENB_H, | ||
613 | .enb_set_reg = CLK_OUT_ENB_SET_H, | ||
614 | .enb_clr_reg = CLK_OUT_ENB_CLR_H, | ||
615 | .rst_reg = RST_DEVICES_H, | ||
616 | .rst_set_reg = RST_DEVICES_SET_H, | ||
617 | .rst_clr_reg = RST_DEVICES_CLR_H, | ||
618 | }; | ||
619 | |||
620 | static struct tegra_clk_periph_regs periph_u_regs = { | ||
621 | .enb_reg = CLK_OUT_ENB_U, | ||
622 | .enb_set_reg = CLK_OUT_ENB_SET_U, | ||
623 | .enb_clr_reg = CLK_OUT_ENB_CLR_U, | ||
624 | .rst_reg = RST_DEVICES_U, | ||
625 | .rst_set_reg = RST_DEVICES_SET_U, | ||
626 | .rst_clr_reg = RST_DEVICES_CLR_U, | ||
627 | }; | ||
628 | |||
629 | static struct tegra_clk_periph_regs periph_v_regs = { | ||
630 | .enb_reg = CLK_OUT_ENB_V, | ||
631 | .enb_set_reg = CLK_OUT_ENB_SET_V, | ||
632 | .enb_clr_reg = CLK_OUT_ENB_CLR_V, | ||
633 | .rst_reg = RST_DEVICES_V, | ||
634 | .rst_set_reg = RST_DEVICES_SET_V, | ||
635 | .rst_clr_reg = RST_DEVICES_CLR_V, | ||
636 | }; | ||
637 | |||
638 | static struct tegra_clk_periph_regs periph_w_regs = { | ||
639 | .enb_reg = CLK_OUT_ENB_W, | ||
640 | .enb_set_reg = CLK_OUT_ENB_SET_W, | ||
641 | .enb_clr_reg = CLK_OUT_ENB_CLR_W, | ||
642 | .rst_reg = RST_DEVICES_W, | ||
643 | .rst_set_reg = RST_DEVICES_SET_W, | ||
644 | .rst_clr_reg = RST_DEVICES_CLR_W, | ||
645 | }; | ||
646 | |||
647 | /* possible OSC frequencies in Hz */ | ||
648 | static unsigned long tegra114_input_freq[] = { | ||
649 | [0] = 13000000, | ||
650 | [1] = 16800000, | ||
651 | [4] = 19200000, | ||
652 | [5] = 38400000, | ||
653 | [8] = 12000000, | ||
654 | [9] = 48000000, | ||
655 | [12] = 260000000, | ||
656 | }; | ||
657 | |||
658 | #define MASK(x) (BIT(x) - 1) | ||
659 | |||
660 | #define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset, \ | ||
661 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
662 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
663 | 30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num, \ | ||
664 | periph_clk_enb_refcnt, _gate_flags, _clk_id, \ | ||
665 | _parents##_idx, 0) | ||
666 | |||
667 | #define TEGRA_INIT_DATA_MUX_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ | ||
668 | _clk_num, _regs, _gate_flags, _clk_id, flags)\ | ||
669 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
670 | 30, MASK(2), 0, 0, 8, 1, 0, _regs, _clk_num, \ | ||
671 | periph_clk_enb_refcnt, _gate_flags, _clk_id, \ | ||
672 | _parents##_idx, flags) | ||
673 | |||
674 | #define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \ | ||
675 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
676 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
677 | 29, MASK(3), 0, 0, 8, 1, 0, _regs, _clk_num, \ | ||
678 | periph_clk_enb_refcnt, _gate_flags, _clk_id, \ | ||
679 | _parents##_idx, 0) | ||
680 | |||
681 | #define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset, \ | ||
682 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
683 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
684 | 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\ | ||
685 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
686 | _clk_id, _parents##_idx, 0) | ||
687 | |||
688 | #define TEGRA_INIT_DATA_INT_FLAGS(_name, _con_id, _dev_id, _parents, _offset,\ | ||
689 | _clk_num, _regs, _gate_flags, _clk_id, flags)\ | ||
690 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
691 | 30, MASK(2), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\ | ||
692 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
693 | _clk_id, _parents##_idx, flags) | ||
694 | |||
695 | #define TEGRA_INIT_DATA_INT8(_name, _con_id, _dev_id, _parents, _offset,\ | ||
696 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
697 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
698 | 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,\ | ||
699 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
700 | _clk_id, _parents##_idx, 0) | ||
701 | |||
702 | #define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\ | ||
703 | _clk_num, _regs, _clk_id) \ | ||
704 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
705 | 30, MASK(2), 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,\ | ||
706 | _clk_num, periph_clk_enb_refcnt, 0, _clk_id, \ | ||
707 | _parents##_idx, 0) | ||
708 | |||
709 | #define TEGRA_INIT_DATA_I2C(_name, _con_id, _dev_id, _parents, _offset,\ | ||
710 | _clk_num, _regs, _clk_id) \ | ||
711 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
712 | 30, MASK(2), 0, 0, 16, 0, 0, _regs, _clk_num, \ | ||
713 | periph_clk_enb_refcnt, 0, _clk_id, _parents##_idx, 0) | ||
714 | |||
715 | #define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \ | ||
716 | _mux_shift, _mux_mask, _clk_num, _regs, \ | ||
717 | _gate_flags, _clk_id) \ | ||
718 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset,\ | ||
719 | _mux_shift, _mux_mask, 0, 0, 0, 0, 0, _regs, \ | ||
720 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
721 | _clk_id, _parents##_idx, 0) | ||
722 | |||
723 | #define TEGRA_INIT_DATA_XUSB(_name, _con_id, _dev_id, _parents, _offset, \ | ||
724 | _clk_num, _regs, _gate_flags, _clk_id) \ | ||
725 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parents, _offset, \ | ||
726 | 29, MASK(3), 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs, \ | ||
727 | _clk_num, periph_clk_enb_refcnt, _gate_flags, \ | ||
728 | _clk_id, _parents##_idx, 0) | ||
729 | |||
730 | #define TEGRA_INIT_DATA_AUDIO(_name, _con_id, _dev_id, _offset, _clk_num,\ | ||
731 | _regs, _gate_flags, _clk_id) \ | ||
732 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, mux_d_audio_clk, \ | ||
733 | _offset, 16, 0xE01F, 0, 0, 8, 1, 0, _regs, _clk_num, \ | ||
734 | periph_clk_enb_refcnt, _gate_flags , _clk_id, \ | ||
735 | mux_d_audio_clk_idx, 0) | ||
736 | |||
737 | enum tegra114_clk { | ||
738 | rtc = 4, timer = 5, uarta = 6, sdmmc2 = 9, i2s1 = 11, i2c1 = 12, | ||
739 | ndflash = 13, sdmmc1 = 14, sdmmc4 = 15, pwm = 17, i2s2 = 18, epp = 19, | ||
740 | gr_2d = 21, usbd = 22, isp = 23, gr_3d = 24, disp2 = 26, disp1 = 27, | ||
741 | host1x = 28, vcp = 29, i2s0 = 30, apbdma = 34, kbc = 36, kfuse = 40, | ||
742 | sbc1 = 41, nor = 42, sbc2 = 44, sbc3 = 46, i2c5 = 47, dsia = 48, | ||
743 | mipi = 50, hdmi = 51, csi = 52, i2c2 = 54, uartc = 55, mipi_cal = 56, | ||
744 | emc, usb2, usb3, vde = 61, bsea = 62, bsev = 63, uartd = 65, | ||
745 | i2c3 = 67, sbc4 = 68, sdmmc3 = 69, owr = 71, csite = 73, | ||
746 | la = 76, trace = 77, soc_therm = 78, dtv = 79, ndspeed = 80, | ||
747 | i2cslow = 81, dsib = 82, tsec = 83, xusb_host = 89, msenc = 91, | ||
748 | csus = 92, mselect = 99, tsensor = 100, i2s3 = 101, i2s4 = 102, | ||
749 | i2c4 = 103, sbc5 = 104, sbc6 = 105, d_audio, apbif = 107, dam0, dam1, | ||
750 | dam2, hda2codec_2x = 111, audio0_2x = 113, audio1_2x, audio2_2x, | ||
751 | audio3_2x, audio4_2x, spdif_2x, actmon = 119, extern1 = 120, | ||
752 | extern2 = 121, extern3 = 122, hda = 125, se = 127, hda2hdmi = 128, | ||
753 | cilab = 144, cilcd = 145, cile = 146, dsialp = 147, dsiblp = 148, | ||
754 | dds = 150, dp2 = 152, amx = 153, adx = 154, xusb_ss = 156, uartb = 192, | ||
755 | vfir, spdif_in, spdif_out, vi, vi_sensor, fuse, fuse_burn, clk_32k, | ||
756 | clk_m, clk_m_div2, clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_c2, | ||
757 | pll_c3, pll_m, pll_m_out1, pll_p, pll_p_out1, pll_p_out2, pll_p_out3, | ||
758 | pll_p_out4, pll_a, pll_a_out0, pll_d, pll_d_out0, pll_d2, pll_d2_out0, | ||
759 | pll_u, pll_u_480M, pll_u_60M, pll_u_48M, pll_u_12M, pll_x, pll_x_out0, | ||
760 | pll_re_vco, pll_re_out, pll_e_out0, spdif_in_sync, i2s0_sync, | ||
761 | i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync, vimclk_sync, audio0, | ||
762 | audio1, audio2, audio3, audio4, spdif, clk_out_1, clk_out_2, clk_out_3, | ||
763 | blink, xusb_host_src = 252, xusb_falcon_src, xusb_fs_src, xusb_ss_src, | ||
764 | xusb_dev_src, xusb_dev, xusb_hs_src, sclk, hclk, pclk, cclk_g, cclk_lp, | ||
765 | |||
766 | /* Mux clocks */ | ||
767 | |||
768 | audio0_mux = 300, audio1_mux, audio2_mux, audio3_mux, audio4_mux, | ||
769 | spdif_mux, clk_out_1_mux, clk_out_2_mux, clk_out_3_mux, dsia_mux, | ||
770 | dsib_mux, clk_max, | ||
771 | }; | ||
772 | |||
773 | struct utmi_clk_param { | ||
774 | /* Oscillator Frequency in KHz */ | ||
775 | u32 osc_frequency; | ||
776 | /* UTMIP PLL Enable Delay Count */ | ||
777 | u8 enable_delay_count; | ||
778 | /* UTMIP PLL Stable count */ | ||
779 | u8 stable_count; | ||
780 | /* UTMIP PLL Active delay count */ | ||
781 | u8 active_delay_count; | ||
782 | /* UTMIP PLL Xtal frequency count */ | ||
783 | u8 xtal_freq_count; | ||
784 | }; | ||
785 | |||
786 | static const struct utmi_clk_param utmi_parameters[] = { | ||
787 | {.osc_frequency = 13000000, .enable_delay_count = 0x02, | ||
788 | .stable_count = 0x33, .active_delay_count = 0x05, | ||
789 | .xtal_freq_count = 0x7F}, | ||
790 | {.osc_frequency = 19200000, .enable_delay_count = 0x03, | ||
791 | .stable_count = 0x4B, .active_delay_count = 0x06, | ||
792 | .xtal_freq_count = 0xBB}, | ||
793 | {.osc_frequency = 12000000, .enable_delay_count = 0x02, | ||
794 | .stable_count = 0x2F, .active_delay_count = 0x04, | ||
795 | .xtal_freq_count = 0x76}, | ||
796 | {.osc_frequency = 26000000, .enable_delay_count = 0x04, | ||
797 | .stable_count = 0x66, .active_delay_count = 0x09, | ||
798 | .xtal_freq_count = 0xFE}, | ||
799 | {.osc_frequency = 16800000, .enable_delay_count = 0x03, | ||
800 | .stable_count = 0x41, .active_delay_count = 0x0A, | ||
801 | .xtal_freq_count = 0xA4}, | ||
802 | }; | ||
803 | |||
804 | /* peripheral mux definitions */ | ||
805 | |||
806 | #define MUX_I2S_SPDIF(_id) \ | ||
807 | static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = { "pll_a_out0", \ | ||
808 | #_id, "pll_p",\ | ||
809 | "clk_m"}; | ||
810 | MUX_I2S_SPDIF(audio0) | ||
811 | MUX_I2S_SPDIF(audio1) | ||
812 | MUX_I2S_SPDIF(audio2) | ||
813 | MUX_I2S_SPDIF(audio3) | ||
814 | MUX_I2S_SPDIF(audio4) | ||
815 | MUX_I2S_SPDIF(audio) | ||
816 | |||
817 | #define mux_pllaout0_audio0_2x_pllp_clkm_idx NULL | ||
818 | #define mux_pllaout0_audio1_2x_pllp_clkm_idx NULL | ||
819 | #define mux_pllaout0_audio2_2x_pllp_clkm_idx NULL | ||
820 | #define mux_pllaout0_audio3_2x_pllp_clkm_idx NULL | ||
821 | #define mux_pllaout0_audio4_2x_pllp_clkm_idx NULL | ||
822 | #define mux_pllaout0_audio_2x_pllp_clkm_idx NULL | ||
823 | |||
824 | static const char *mux_pllp_pllc_pllm_clkm[] = { | ||
825 | "pll_p", "pll_c", "pll_m", "clk_m" | ||
826 | }; | ||
827 | #define mux_pllp_pllc_pllm_clkm_idx NULL | ||
828 | |||
829 | static const char *mux_pllp_pllc_pllm[] = { "pll_p", "pll_c", "pll_m" }; | ||
830 | #define mux_pllp_pllc_pllm_idx NULL | ||
831 | |||
832 | static const char *mux_pllp_pllc_clk32_clkm[] = { | ||
833 | "pll_p", "pll_c", "clk_32k", "clk_m" | ||
834 | }; | ||
835 | #define mux_pllp_pllc_clk32_clkm_idx NULL | ||
836 | |||
837 | static const char *mux_plla_pllc_pllp_clkm[] = { | ||
838 | "pll_a_out0", "pll_c", "pll_p", "clk_m" | ||
839 | }; | ||
840 | #define mux_plla_pllc_pllp_clkm_idx mux_pllp_pllc_pllm_clkm_idx | ||
841 | |||
842 | static const char *mux_pllp_pllc2_c_c3_pllm_clkm[] = { | ||
843 | "pll_p", "pll_c2", "pll_c", "pll_c3", "pll_m", "clk_m" | ||
844 | }; | ||
845 | static u32 mux_pllp_pllc2_c_c3_pllm_clkm_idx[] = { | ||
846 | [0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 6, | ||
847 | }; | ||
848 | |||
849 | static const char *mux_pllp_clkm[] = { | ||
850 | "pll_p", "clk_m" | ||
851 | }; | ||
852 | static u32 mux_pllp_clkm_idx[] = { | ||
853 | [0] = 0, [1] = 3, | ||
854 | }; | ||
855 | |||
856 | static const char *mux_pllm_pllc2_c_c3_pllp_plla[] = { | ||
857 | "pll_m", "pll_c2", "pll_c", "pll_c3", "pll_p", "pll_a_out0" | ||
858 | }; | ||
859 | #define mux_pllm_pllc2_c_c3_pllp_plla_idx mux_pllp_pllc2_c_c3_pllm_clkm_idx | ||
860 | |||
861 | static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = { | ||
862 | "pll_p", "pll_m", "pll_d_out0", "pll_a_out0", "pll_c", | ||
863 | "pll_d2_out0", "clk_m" | ||
864 | }; | ||
865 | #define mux_pllp_pllm_plld_plla_pllc_plld2_clkm_idx NULL | ||
866 | |||
867 | static const char *mux_pllm_pllc_pllp_plla[] = { | ||
868 | "pll_m", "pll_c", "pll_p", "pll_a_out0" | ||
869 | }; | ||
870 | #define mux_pllm_pllc_pllp_plla_idx mux_pllp_pllc_pllm_clkm_idx | ||
871 | |||
872 | static const char *mux_pllp_pllc_clkm[] = { | ||
873 | "pll_p", "pll_c", "pll_m" | ||
874 | }; | ||
875 | static u32 mux_pllp_pllc_clkm_idx[] = { | ||
876 | [0] = 0, [1] = 1, [2] = 3, | ||
877 | }; | ||
878 | |||
879 | static const char *mux_pllp_pllc_clkm_clk32[] = { | ||
880 | "pll_p", "pll_c", "clk_m", "clk_32k" | ||
881 | }; | ||
882 | #define mux_pllp_pllc_clkm_clk32_idx NULL | ||
883 | |||
884 | static const char *mux_plla_clk32_pllp_clkm_plle[] = { | ||
885 | "pll_a_out0", "clk_32k", "pll_p", "clk_m", "pll_e_out0" | ||
886 | }; | ||
887 | #define mux_plla_clk32_pllp_clkm_plle_idx NULL | ||
888 | |||
889 | static const char *mux_clkm_pllp_pllc_pllre[] = { | ||
890 | "clk_m", "pll_p", "pll_c", "pll_re_out" | ||
891 | }; | ||
892 | static u32 mux_clkm_pllp_pllc_pllre_idx[] = { | ||
893 | [0] = 0, [1] = 1, [2] = 3, [3] = 5, | ||
894 | }; | ||
895 | |||
896 | static const char *mux_clkm_48M_pllp_480M[] = { | ||
897 | "clk_m", "pll_u_48M", "pll_p", "pll_u_480M" | ||
898 | }; | ||
899 | #define mux_clkm_48M_pllp_480M_idx NULL | ||
900 | |||
901 | static const char *mux_clkm_pllre_clk32_480M_pllc_ref[] = { | ||
902 | "clk_m", "pll_re_out", "clk_32k", "pll_u_480M", "pll_c", "pll_ref" | ||
903 | }; | ||
904 | static u32 mux_clkm_pllre_clk32_480M_pllc_ref_idx[] = { | ||
905 | [0] = 0, [1] = 1, [2] = 3, [3] = 3, [4] = 4, [5] = 7, | ||
906 | }; | ||
907 | |||
908 | static const char *mux_plld_out0_plld2_out0[] = { | ||
909 | "pll_d_out0", "pll_d2_out0", | ||
910 | }; | ||
911 | #define mux_plld_out0_plld2_out0_idx NULL | ||
912 | |||
913 | static const char *mux_d_audio_clk[] = { | ||
914 | "pll_a_out0", "pll_p", "clk_m", "spdif_in_sync", "i2s0_sync", | ||
915 | "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", | ||
916 | }; | ||
917 | static u32 mux_d_audio_clk_idx[] = { | ||
918 | [0] = 0, [1] = 0x8000, [2] = 0xc000, [3] = 0xE000, [4] = 0xE001, | ||
919 | [5] = 0xE002, [6] = 0xE003, [7] = 0xE004, [8] = 0xE005, [9] = 0xE007, | ||
920 | }; | ||
921 | |||
922 | static const char *mux_pllmcp_clkm[] = { | ||
923 | "pll_m_out0", "pll_c_out0", "pll_p_out0", "clk_m", "pll_m_ud", | ||
924 | }; | ||
925 | |||
926 | static const struct clk_div_table pll_re_div_table[] = { | ||
927 | { .val = 0, .div = 1 }, | ||
928 | { .val = 1, .div = 2 }, | ||
929 | { .val = 2, .div = 3 }, | ||
930 | { .val = 3, .div = 4 }, | ||
931 | { .val = 4, .div = 5 }, | ||
932 | { .val = 5, .div = 6 }, | ||
933 | { .val = 0, .div = 0 }, | ||
934 | }; | ||
935 | |||
936 | static struct clk *clks[clk_max]; | ||
937 | static struct clk_onecell_data clk_data; | ||
938 | |||
939 | static unsigned long osc_freq; | ||
940 | static unsigned long pll_ref_freq; | ||
941 | |||
942 | static int __init tegra114_osc_clk_init(void __iomem *clk_base) | ||
943 | { | ||
944 | struct clk *clk; | ||
945 | u32 val, pll_ref_div; | ||
946 | |||
947 | val = readl_relaxed(clk_base + OSC_CTRL); | ||
948 | |||
949 | osc_freq = tegra114_input_freq[val >> OSC_CTRL_OSC_FREQ_SHIFT]; | ||
950 | if (!osc_freq) { | ||
951 | WARN_ON(1); | ||
952 | return -EINVAL; | ||
953 | } | ||
954 | |||
955 | /* clk_m */ | ||
956 | clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT, | ||
957 | osc_freq); | ||
958 | clk_register_clkdev(clk, "clk_m", NULL); | ||
959 | clks[clk_m] = clk; | ||
960 | |||
961 | /* pll_ref */ | ||
962 | val = (val >> OSC_CTRL_PLL_REF_DIV_SHIFT) & 3; | ||
963 | pll_ref_div = 1 << val; | ||
964 | clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m", | ||
965 | CLK_SET_RATE_PARENT, 1, pll_ref_div); | ||
966 | clk_register_clkdev(clk, "pll_ref", NULL); | ||
967 | clks[pll_ref] = clk; | ||
968 | |||
969 | pll_ref_freq = osc_freq / pll_ref_div; | ||
970 | |||
971 | return 0; | ||
972 | } | ||
973 | |||
974 | static void __init tegra114_fixed_clk_init(void __iomem *clk_base) | ||
975 | { | ||
976 | struct clk *clk; | ||
977 | |||
978 | /* clk_32k */ | ||
979 | clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT, | ||
980 | 32768); | ||
981 | clk_register_clkdev(clk, "clk_32k", NULL); | ||
982 | clks[clk_32k] = clk; | ||
983 | |||
984 | /* clk_m_div2 */ | ||
985 | clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m", | ||
986 | CLK_SET_RATE_PARENT, 1, 2); | ||
987 | clk_register_clkdev(clk, "clk_m_div2", NULL); | ||
988 | clks[clk_m_div2] = clk; | ||
989 | |||
990 | /* clk_m_div4 */ | ||
991 | clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m", | ||
992 | CLK_SET_RATE_PARENT, 1, 4); | ||
993 | clk_register_clkdev(clk, "clk_m_div4", NULL); | ||
994 | clks[clk_m_div4] = clk; | ||
995 | |||
996 | } | ||
997 | |||
998 | static __init void tegra114_utmi_param_configure(void __iomem *clk_base) | ||
999 | { | ||
1000 | u32 reg; | ||
1001 | int i; | ||
1002 | |||
1003 | for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) { | ||
1004 | if (osc_freq == utmi_parameters[i].osc_frequency) | ||
1005 | break; | ||
1006 | } | ||
1007 | |||
1008 | if (i >= ARRAY_SIZE(utmi_parameters)) { | ||
1009 | pr_err("%s: Unexpected oscillator freq %lu\n", __func__, | ||
1010 | osc_freq); | ||
1011 | return; | ||
1012 | } | ||
1013 | |||
1014 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2); | ||
1015 | |||
1016 | /* Program UTMIP PLL stable and active counts */ | ||
1017 | /* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */ | ||
1018 | reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0); | ||
1019 | reg |= UTMIP_PLL_CFG2_STABLE_COUNT(utmi_parameters[i].stable_count); | ||
1020 | |||
1021 | reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0); | ||
1022 | |||
1023 | reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(utmi_parameters[i]. | ||
1024 | active_delay_count); | ||
1025 | |||
1026 | /* Remove power downs from UTMIP PLL control bits */ | ||
1027 | reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN; | ||
1028 | reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN; | ||
1029 | reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN; | ||
1030 | |||
1031 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2); | ||
1032 | |||
1033 | /* Program UTMIP PLL delay and oscillator frequency counts */ | ||
1034 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); | ||
1035 | reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0); | ||
1036 | |||
1037 | reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(utmi_parameters[i]. | ||
1038 | enable_delay_count); | ||
1039 | |||
1040 | reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0); | ||
1041 | reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(utmi_parameters[i]. | ||
1042 | xtal_freq_count); | ||
1043 | |||
1044 | /* Remove power downs from UTMIP PLL control bits */ | ||
1045 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; | ||
1046 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN; | ||
1047 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERUP; | ||
1048 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN; | ||
1049 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); | ||
1050 | |||
1051 | /* Setup HW control of UTMIPLL */ | ||
1052 | reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); | ||
1053 | reg |= UTMIPLL_HW_PWRDN_CFG0_USE_LOCKDET; | ||
1054 | reg &= ~UTMIPLL_HW_PWRDN_CFG0_CLK_ENABLE_SWCTL; | ||
1055 | reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_START_STATE; | ||
1056 | writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); | ||
1057 | |||
1058 | reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1); | ||
1059 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERUP; | ||
1060 | reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN; | ||
1061 | writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1); | ||
1062 | |||
1063 | udelay(1); | ||
1064 | |||
1065 | /* Setup SW override of UTMIPLL assuming USB2.0 | ||
1066 | ports are assigned to USB2 */ | ||
1067 | reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); | ||
1068 | reg |= UTMIPLL_HW_PWRDN_CFG0_IDDQ_SWCTL; | ||
1069 | reg &= ~UTMIPLL_HW_PWRDN_CFG0_IDDQ_OVERRIDE; | ||
1070 | writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); | ||
1071 | |||
1072 | udelay(1); | ||
1073 | |||
1074 | /* Enable HW control UTMIPLL */ | ||
1075 | reg = readl_relaxed(clk_base + UTMIPLL_HW_PWRDN_CFG0); | ||
1076 | reg |= UTMIPLL_HW_PWRDN_CFG0_SEQ_ENABLE; | ||
1077 | writel_relaxed(reg, clk_base + UTMIPLL_HW_PWRDN_CFG0); | ||
1078 | } | ||
1079 | |||
1080 | static void __init _clip_vco_min(struct tegra_clk_pll_params *pll_params) | ||
1081 | { | ||
1082 | pll_params->vco_min = | ||
1083 | DIV_ROUND_UP(pll_params->vco_min, pll_ref_freq) * pll_ref_freq; | ||
1084 | } | ||
1085 | |||
1086 | static int __init _setup_dynamic_ramp(struct tegra_clk_pll_params *pll_params, | ||
1087 | void __iomem *clk_base) | ||
1088 | { | ||
1089 | u32 val; | ||
1090 | u32 step_a, step_b; | ||
1091 | |||
1092 | switch (pll_ref_freq) { | ||
1093 | case 12000000: | ||
1094 | case 13000000: | ||
1095 | case 26000000: | ||
1096 | step_a = 0x2B; | ||
1097 | step_b = 0x0B; | ||
1098 | break; | ||
1099 | case 16800000: | ||
1100 | step_a = 0x1A; | ||
1101 | step_b = 0x09; | ||
1102 | break; | ||
1103 | case 19200000: | ||
1104 | step_a = 0x12; | ||
1105 | step_b = 0x08; | ||
1106 | break; | ||
1107 | default: | ||
1108 | pr_err("%s: Unexpected reference rate %lu\n", | ||
1109 | __func__, pll_ref_freq); | ||
1110 | WARN_ON(1); | ||
1111 | return -EINVAL; | ||
1112 | } | ||
1113 | |||
1114 | val = step_a << pll_params->stepa_shift; | ||
1115 | val |= step_b << pll_params->stepb_shift; | ||
1116 | writel_relaxed(val, clk_base + pll_params->dyn_ramp_reg); | ||
1117 | |||
1118 | return 0; | ||
1119 | } | ||
1120 | |||
1121 | static void __init _init_iddq(struct tegra_clk_pll_params *pll_params, | ||
1122 | void __iomem *clk_base) | ||
1123 | { | ||
1124 | u32 val, val_iddq; | ||
1125 | |||
1126 | val = readl_relaxed(clk_base + pll_params->base_reg); | ||
1127 | val_iddq = readl_relaxed(clk_base + pll_params->iddq_reg); | ||
1128 | |||
1129 | if (val & BIT(30)) | ||
1130 | WARN_ON(val_iddq & BIT(pll_params->iddq_bit_idx)); | ||
1131 | else { | ||
1132 | val_iddq |= BIT(pll_params->iddq_bit_idx); | ||
1133 | writel_relaxed(val_iddq, clk_base + pll_params->iddq_reg); | ||
1134 | } | ||
1135 | } | ||
1136 | |||
1137 | static void __init tegra114_pll_init(void __iomem *clk_base, | ||
1138 | void __iomem *pmc) | ||
1139 | { | ||
1140 | u32 val; | ||
1141 | struct clk *clk; | ||
1142 | |||
1143 | /* PLLC */ | ||
1144 | _clip_vco_min(&pll_c_params); | ||
1145 | if (_setup_dynamic_ramp(&pll_c_params, clk_base) >= 0) { | ||
1146 | _init_iddq(&pll_c_params, clk_base); | ||
1147 | clk = tegra_clk_register_pllxc("pll_c", "pll_ref", clk_base, | ||
1148 | pmc, 0, 0, &pll_c_params, TEGRA_PLL_USE_LOCK, | ||
1149 | pll_c_freq_table, NULL); | ||
1150 | clk_register_clkdev(clk, "pll_c", NULL); | ||
1151 | clks[pll_c] = clk; | ||
1152 | |||
1153 | /* PLLC_OUT1 */ | ||
1154 | clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c", | ||
1155 | clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP, | ||
1156 | 8, 8, 1, NULL); | ||
1157 | clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div", | ||
1158 | clk_base + PLLC_OUT, 1, 0, | ||
1159 | CLK_SET_RATE_PARENT, 0, NULL); | ||
1160 | clk_register_clkdev(clk, "pll_c_out1", NULL); | ||
1161 | clks[pll_c_out1] = clk; | ||
1162 | } | ||
1163 | |||
1164 | /* PLLC2 */ | ||
1165 | _clip_vco_min(&pll_c2_params); | ||
1166 | clk = tegra_clk_register_pllc("pll_c2", "pll_ref", clk_base, pmc, 0, 0, | ||
1167 | &pll_c2_params, TEGRA_PLL_USE_LOCK, | ||
1168 | pll_cx_freq_table, NULL); | ||
1169 | clk_register_clkdev(clk, "pll_c2", NULL); | ||
1170 | clks[pll_c2] = clk; | ||
1171 | |||
1172 | /* PLLC3 */ | ||
1173 | _clip_vco_min(&pll_c3_params); | ||
1174 | clk = tegra_clk_register_pllc("pll_c3", "pll_ref", clk_base, pmc, 0, 0, | ||
1175 | &pll_c3_params, TEGRA_PLL_USE_LOCK, | ||
1176 | pll_cx_freq_table, NULL); | ||
1177 | clk_register_clkdev(clk, "pll_c3", NULL); | ||
1178 | clks[pll_c3] = clk; | ||
1179 | |||
1180 | /* PLLP */ | ||
1181 | clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc, 0, | ||
1182 | 408000000, &pll_p_params, | ||
1183 | TEGRA_PLL_FIXED | TEGRA_PLL_USE_LOCK, | ||
1184 | pll_p_freq_table, NULL); | ||
1185 | clk_register_clkdev(clk, "pll_p", NULL); | ||
1186 | clks[pll_p] = clk; | ||
1187 | |||
1188 | /* PLLP_OUT1 */ | ||
1189 | clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p", | ||
1190 | clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | | ||
1191 | TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock); | ||
1192 | clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div", | ||
1193 | clk_base + PLLP_OUTA, 1, 0, | ||
1194 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
1195 | &pll_div_lock); | ||
1196 | clk_register_clkdev(clk, "pll_p_out1", NULL); | ||
1197 | clks[pll_p_out1] = clk; | ||
1198 | |||
1199 | /* PLLP_OUT2 */ | ||
1200 | clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p", | ||
1201 | clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED | | ||
1202 | TEGRA_DIVIDER_ROUND_UP, 24, 8, 1, | ||
1203 | &pll_div_lock); | ||
1204 | clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div", | ||
1205 | clk_base + PLLP_OUTA, 17, 16, | ||
1206 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
1207 | &pll_div_lock); | ||
1208 | clk_register_clkdev(clk, "pll_p_out2", NULL); | ||
1209 | clks[pll_p_out2] = clk; | ||
1210 | |||
1211 | /* PLLP_OUT3 */ | ||
1212 | clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p", | ||
1213 | clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | | ||
1214 | TEGRA_DIVIDER_ROUND_UP, 8, 8, 1, &pll_div_lock); | ||
1215 | clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div", | ||
1216 | clk_base + PLLP_OUTB, 1, 0, | ||
1217 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
1218 | &pll_div_lock); | ||
1219 | clk_register_clkdev(clk, "pll_p_out3", NULL); | ||
1220 | clks[pll_p_out3] = clk; | ||
1221 | |||
1222 | /* PLLP_OUT4 */ | ||
1223 | clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p", | ||
1224 | clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED | | ||
1225 | TEGRA_DIVIDER_ROUND_UP, 24, 8, 1, | ||
1226 | &pll_div_lock); | ||
1227 | clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div", | ||
1228 | clk_base + PLLP_OUTB, 17, 16, | ||
1229 | CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0, | ||
1230 | &pll_div_lock); | ||
1231 | clk_register_clkdev(clk, "pll_p_out4", NULL); | ||
1232 | clks[pll_p_out4] = clk; | ||
1233 | |||
1234 | /* PLLM */ | ||
1235 | _clip_vco_min(&pll_m_params); | ||
1236 | clk = tegra_clk_register_pllm("pll_m", "pll_ref", clk_base, pmc, | ||
1237 | CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0, | ||
1238 | &pll_m_params, TEGRA_PLL_USE_LOCK, | ||
1239 | pll_m_freq_table, NULL); | ||
1240 | clk_register_clkdev(clk, "pll_m", NULL); | ||
1241 | clks[pll_m] = clk; | ||
1242 | |||
1243 | /* PLLM_OUT1 */ | ||
1244 | clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m", | ||
1245 | clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP, | ||
1246 | 8, 8, 1, NULL); | ||
1247 | clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div", | ||
1248 | clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED | | ||
1249 | CLK_SET_RATE_PARENT, 0, NULL); | ||
1250 | clk_register_clkdev(clk, "pll_m_out1", NULL); | ||
1251 | clks[pll_m_out1] = clk; | ||
1252 | |||
1253 | /* PLLM_UD */ | ||
1254 | clk = clk_register_fixed_factor(NULL, "pll_m_ud", "pll_m", | ||
1255 | CLK_SET_RATE_PARENT, 1, 1); | ||
1256 | |||
1257 | /* PLLX */ | ||
1258 | _clip_vco_min(&pll_x_params); | ||
1259 | if (_setup_dynamic_ramp(&pll_x_params, clk_base) >= 0) { | ||
1260 | _init_iddq(&pll_x_params, clk_base); | ||
1261 | clk = tegra_clk_register_pllxc("pll_x", "pll_ref", clk_base, | ||
1262 | pmc, CLK_IGNORE_UNUSED, 0, &pll_x_params, | ||
1263 | TEGRA_PLL_USE_LOCK, pll_x_freq_table, NULL); | ||
1264 | clk_register_clkdev(clk, "pll_x", NULL); | ||
1265 | clks[pll_x] = clk; | ||
1266 | } | ||
1267 | |||
1268 | /* PLLX_OUT0 */ | ||
1269 | clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x", | ||
1270 | CLK_SET_RATE_PARENT, 1, 2); | ||
1271 | clk_register_clkdev(clk, "pll_x_out0", NULL); | ||
1272 | clks[pll_x_out0] = clk; | ||
1273 | |||
1274 | /* PLLU */ | ||
1275 | val = readl(clk_base + pll_u_params.base_reg); | ||
1276 | val &= ~BIT(24); /* disable PLLU_OVERRIDE */ | ||
1277 | writel(val, clk_base + pll_u_params.base_reg); | ||
1278 | |||
1279 | clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc, 0, | ||
1280 | 0, &pll_u_params, TEGRA_PLLU | | ||
1281 | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | | ||
1282 | TEGRA_PLL_USE_LOCK, pll_u_freq_table, &pll_u_lock); | ||
1283 | clk_register_clkdev(clk, "pll_u", NULL); | ||
1284 | clks[pll_u] = clk; | ||
1285 | |||
1286 | tegra114_utmi_param_configure(clk_base); | ||
1287 | |||
1288 | /* PLLU_480M */ | ||
1289 | clk = clk_register_gate(NULL, "pll_u_480M", "pll_u", | ||
1290 | CLK_SET_RATE_PARENT, clk_base + PLLU_BASE, | ||
1291 | 22, 0, &pll_u_lock); | ||
1292 | clk_register_clkdev(clk, "pll_u_480M", NULL); | ||
1293 | clks[pll_u_480M] = clk; | ||
1294 | |||
1295 | /* PLLU_60M */ | ||
1296 | clk = clk_register_fixed_factor(NULL, "pll_u_60M", "pll_u", | ||
1297 | CLK_SET_RATE_PARENT, 1, 8); | ||
1298 | clk_register_clkdev(clk, "pll_u_60M", NULL); | ||
1299 | clks[pll_u_60M] = clk; | ||
1300 | |||
1301 | /* PLLU_48M */ | ||
1302 | clk = clk_register_fixed_factor(NULL, "pll_u_48M", "pll_u", | ||
1303 | CLK_SET_RATE_PARENT, 1, 10); | ||
1304 | clk_register_clkdev(clk, "pll_u_48M", NULL); | ||
1305 | clks[pll_u_48M] = clk; | ||
1306 | |||
1307 | /* PLLU_12M */ | ||
1308 | clk = clk_register_fixed_factor(NULL, "pll_u_12M", "pll_u", | ||
1309 | CLK_SET_RATE_PARENT, 1, 40); | ||
1310 | clk_register_clkdev(clk, "pll_u_12M", NULL); | ||
1311 | clks[pll_u_12M] = clk; | ||
1312 | |||
1313 | /* PLLD */ | ||
1314 | clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc, 0, | ||
1315 | 0, &pll_d_params, | ||
1316 | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | | ||
1317 | TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d_lock); | ||
1318 | clk_register_clkdev(clk, "pll_d", NULL); | ||
1319 | clks[pll_d] = clk; | ||
1320 | |||
1321 | /* PLLD_OUT0 */ | ||
1322 | clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d", | ||
1323 | CLK_SET_RATE_PARENT, 1, 2); | ||
1324 | clk_register_clkdev(clk, "pll_d_out0", NULL); | ||
1325 | clks[pll_d_out0] = clk; | ||
1326 | |||
1327 | /* PLLD2 */ | ||
1328 | clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc, 0, | ||
1329 | 0, &pll_d2_params, | ||
1330 | TEGRA_PLL_HAS_CPCON | TEGRA_PLL_SET_LFCON | | ||
1331 | TEGRA_PLL_USE_LOCK, pll_d_freq_table, &pll_d2_lock); | ||
1332 | clk_register_clkdev(clk, "pll_d2", NULL); | ||
1333 | clks[pll_d2] = clk; | ||
1334 | |||
1335 | /* PLLD2_OUT0 */ | ||
1336 | clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2", | ||
1337 | CLK_SET_RATE_PARENT, 1, 2); | ||
1338 | clk_register_clkdev(clk, "pll_d2_out0", NULL); | ||
1339 | clks[pll_d2_out0] = clk; | ||
1340 | |||
1341 | /* PLLA */ | ||
1342 | clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc, 0, | ||
1343 | 0, &pll_a_params, TEGRA_PLL_HAS_CPCON | | ||
1344 | TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL); | ||
1345 | clk_register_clkdev(clk, "pll_a", NULL); | ||
1346 | clks[pll_a] = clk; | ||
1347 | |||
1348 | /* PLLA_OUT0 */ | ||
1349 | clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a", | ||
1350 | clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP, | ||
1351 | 8, 8, 1, NULL); | ||
1352 | clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div", | ||
1353 | clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED | | ||
1354 | CLK_SET_RATE_PARENT, 0, NULL); | ||
1355 | clk_register_clkdev(clk, "pll_a_out0", NULL); | ||
1356 | clks[pll_a_out0] = clk; | ||
1357 | |||
1358 | /* PLLRE */ | ||
1359 | _clip_vco_min(&pll_re_vco_params); | ||
1360 | clk = tegra_clk_register_pllre("pll_re_vco", "pll_ref", clk_base, pmc, | ||
1361 | 0, 0, &pll_re_vco_params, TEGRA_PLL_USE_LOCK, | ||
1362 | NULL, &pll_re_lock, pll_ref_freq); | ||
1363 | clk_register_clkdev(clk, "pll_re_vco", NULL); | ||
1364 | clks[pll_re_vco] = clk; | ||
1365 | |||
1366 | clk = clk_register_divider_table(NULL, "pll_re_out", "pll_re_vco", 0, | ||
1367 | clk_base + PLLRE_BASE, 16, 4, 0, | ||
1368 | pll_re_div_table, &pll_re_lock); | ||
1369 | clk_register_clkdev(clk, "pll_re_out", NULL); | ||
1370 | clks[pll_re_out] = clk; | ||
1371 | |||
1372 | /* PLLE */ | ||
1373 | clk = tegra_clk_register_plle_tegra114("pll_e_out0", "pll_re_vco", | ||
1374 | clk_base, 0, 100000000, &pll_e_params, | ||
1375 | pll_e_freq_table, NULL); | ||
1376 | clk_register_clkdev(clk, "pll_e_out0", NULL); | ||
1377 | clks[pll_e_out0] = clk; | ||
1378 | } | ||
1379 | |||
1380 | static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync", | ||
1381 | "i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync", | ||
1382 | }; | ||
1383 | |||
1384 | static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2", | ||
1385 | "clk_m_div4", "extern1", | ||
1386 | }; | ||
1387 | |||
1388 | static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2", | ||
1389 | "clk_m_div4", "extern2", | ||
1390 | }; | ||
1391 | |||
1392 | static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2", | ||
1393 | "clk_m_div4", "extern3", | ||
1394 | }; | ||
1395 | |||
1396 | static void __init tegra114_audio_clk_init(void __iomem *clk_base) | ||
1397 | { | ||
1398 | struct clk *clk; | ||
1399 | |||
1400 | /* spdif_in_sync */ | ||
1401 | clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000, | ||
1402 | 24000000); | ||
1403 | clk_register_clkdev(clk, "spdif_in_sync", NULL); | ||
1404 | clks[spdif_in_sync] = clk; | ||
1405 | |||
1406 | /* i2s0_sync */ | ||
1407 | clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000); | ||
1408 | clk_register_clkdev(clk, "i2s0_sync", NULL); | ||
1409 | clks[i2s0_sync] = clk; | ||
1410 | |||
1411 | /* i2s1_sync */ | ||
1412 | clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000); | ||
1413 | clk_register_clkdev(clk, "i2s1_sync", NULL); | ||
1414 | clks[i2s1_sync] = clk; | ||
1415 | |||
1416 | /* i2s2_sync */ | ||
1417 | clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000); | ||
1418 | clk_register_clkdev(clk, "i2s2_sync", NULL); | ||
1419 | clks[i2s2_sync] = clk; | ||
1420 | |||
1421 | /* i2s3_sync */ | ||
1422 | clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000); | ||
1423 | clk_register_clkdev(clk, "i2s3_sync", NULL); | ||
1424 | clks[i2s3_sync] = clk; | ||
1425 | |||
1426 | /* i2s4_sync */ | ||
1427 | clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000); | ||
1428 | clk_register_clkdev(clk, "i2s4_sync", NULL); | ||
1429 | clks[i2s4_sync] = clk; | ||
1430 | |||
1431 | /* vimclk_sync */ | ||
1432 | clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000); | ||
1433 | clk_register_clkdev(clk, "vimclk_sync", NULL); | ||
1434 | clks[vimclk_sync] = clk; | ||
1435 | |||
1436 | /* audio0 */ | ||
1437 | clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk, | ||
1438 | ARRAY_SIZE(mux_audio_sync_clk), 0, | ||
1439 | clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, | ||
1440 | NULL); | ||
1441 | clks[audio0_mux] = clk; | ||
1442 | clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0, | ||
1443 | clk_base + AUDIO_SYNC_CLK_I2S0, 4, | ||
1444 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
1445 | clk_register_clkdev(clk, "audio0", NULL); | ||
1446 | clks[audio0] = clk; | ||
1447 | |||
1448 | /* audio1 */ | ||
1449 | clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk, | ||
1450 | ARRAY_SIZE(mux_audio_sync_clk), 0, | ||
1451 | clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, | ||
1452 | NULL); | ||
1453 | clks[audio1_mux] = clk; | ||
1454 | clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0, | ||
1455 | clk_base + AUDIO_SYNC_CLK_I2S1, 4, | ||
1456 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
1457 | clk_register_clkdev(clk, "audio1", NULL); | ||
1458 | clks[audio1] = clk; | ||
1459 | |||
1460 | /* audio2 */ | ||
1461 | clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk, | ||
1462 | ARRAY_SIZE(mux_audio_sync_clk), 0, | ||
1463 | clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, | ||
1464 | NULL); | ||
1465 | clks[audio2_mux] = clk; | ||
1466 | clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0, | ||
1467 | clk_base + AUDIO_SYNC_CLK_I2S2, 4, | ||
1468 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
1469 | clk_register_clkdev(clk, "audio2", NULL); | ||
1470 | clks[audio2] = clk; | ||
1471 | |||
1472 | /* audio3 */ | ||
1473 | clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk, | ||
1474 | ARRAY_SIZE(mux_audio_sync_clk), 0, | ||
1475 | clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, | ||
1476 | NULL); | ||
1477 | clks[audio3_mux] = clk; | ||
1478 | clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0, | ||
1479 | clk_base + AUDIO_SYNC_CLK_I2S3, 4, | ||
1480 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
1481 | clk_register_clkdev(clk, "audio3", NULL); | ||
1482 | clks[audio3] = clk; | ||
1483 | |||
1484 | /* audio4 */ | ||
1485 | clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk, | ||
1486 | ARRAY_SIZE(mux_audio_sync_clk), 0, | ||
1487 | clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, | ||
1488 | NULL); | ||
1489 | clks[audio4_mux] = clk; | ||
1490 | clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0, | ||
1491 | clk_base + AUDIO_SYNC_CLK_I2S4, 4, | ||
1492 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
1493 | clk_register_clkdev(clk, "audio4", NULL); | ||
1494 | clks[audio4] = clk; | ||
1495 | |||
1496 | /* spdif */ | ||
1497 | clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk, | ||
1498 | ARRAY_SIZE(mux_audio_sync_clk), 0, | ||
1499 | clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, | ||
1500 | NULL); | ||
1501 | clks[spdif_mux] = clk; | ||
1502 | clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0, | ||
1503 | clk_base + AUDIO_SYNC_CLK_SPDIF, 4, | ||
1504 | CLK_GATE_SET_TO_DISABLE, NULL); | ||
1505 | clk_register_clkdev(clk, "spdif", NULL); | ||
1506 | clks[spdif] = clk; | ||
1507 | |||
1508 | /* audio0_2x */ | ||
1509 | clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0", | ||
1510 | CLK_SET_RATE_PARENT, 2, 1); | ||
1511 | clk = tegra_clk_register_divider("audio0_div", "audio0_doubler", | ||
1512 | clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1, | ||
1513 | 0, &clk_doubler_lock); | ||
1514 | clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div", | ||
1515 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1516 | CLK_SET_RATE_PARENT, 113, &periph_v_regs, | ||
1517 | periph_clk_enb_refcnt); | ||
1518 | clk_register_clkdev(clk, "audio0_2x", NULL); | ||
1519 | clks[audio0_2x] = clk; | ||
1520 | |||
1521 | /* audio1_2x */ | ||
1522 | clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1", | ||
1523 | CLK_SET_RATE_PARENT, 2, 1); | ||
1524 | clk = tegra_clk_register_divider("audio1_div", "audio1_doubler", | ||
1525 | clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1, | ||
1526 | 0, &clk_doubler_lock); | ||
1527 | clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div", | ||
1528 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1529 | CLK_SET_RATE_PARENT, 114, &periph_v_regs, | ||
1530 | periph_clk_enb_refcnt); | ||
1531 | clk_register_clkdev(clk, "audio1_2x", NULL); | ||
1532 | clks[audio1_2x] = clk; | ||
1533 | |||
1534 | /* audio2_2x */ | ||
1535 | clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2", | ||
1536 | CLK_SET_RATE_PARENT, 2, 1); | ||
1537 | clk = tegra_clk_register_divider("audio2_div", "audio2_doubler", | ||
1538 | clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1, | ||
1539 | 0, &clk_doubler_lock); | ||
1540 | clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div", | ||
1541 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1542 | CLK_SET_RATE_PARENT, 115, &periph_v_regs, | ||
1543 | periph_clk_enb_refcnt); | ||
1544 | clk_register_clkdev(clk, "audio2_2x", NULL); | ||
1545 | clks[audio2_2x] = clk; | ||
1546 | |||
1547 | /* audio3_2x */ | ||
1548 | clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3", | ||
1549 | CLK_SET_RATE_PARENT, 2, 1); | ||
1550 | clk = tegra_clk_register_divider("audio3_div", "audio3_doubler", | ||
1551 | clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1, | ||
1552 | 0, &clk_doubler_lock); | ||
1553 | clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div", | ||
1554 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1555 | CLK_SET_RATE_PARENT, 116, &periph_v_regs, | ||
1556 | periph_clk_enb_refcnt); | ||
1557 | clk_register_clkdev(clk, "audio3_2x", NULL); | ||
1558 | clks[audio3_2x] = clk; | ||
1559 | |||
1560 | /* audio4_2x */ | ||
1561 | clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4", | ||
1562 | CLK_SET_RATE_PARENT, 2, 1); | ||
1563 | clk = tegra_clk_register_divider("audio4_div", "audio4_doubler", | ||
1564 | clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1, | ||
1565 | 0, &clk_doubler_lock); | ||
1566 | clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div", | ||
1567 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1568 | CLK_SET_RATE_PARENT, 117, &periph_v_regs, | ||
1569 | periph_clk_enb_refcnt); | ||
1570 | clk_register_clkdev(clk, "audio4_2x", NULL); | ||
1571 | clks[audio4_2x] = clk; | ||
1572 | |||
1573 | /* spdif_2x */ | ||
1574 | clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif", | ||
1575 | CLK_SET_RATE_PARENT, 2, 1); | ||
1576 | clk = tegra_clk_register_divider("spdif_div", "spdif_doubler", | ||
1577 | clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1, | ||
1578 | 0, &clk_doubler_lock); | ||
1579 | clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div", | ||
1580 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1581 | CLK_SET_RATE_PARENT, 118, | ||
1582 | &periph_v_regs, periph_clk_enb_refcnt); | ||
1583 | clk_register_clkdev(clk, "spdif_2x", NULL); | ||
1584 | clks[spdif_2x] = clk; | ||
1585 | } | ||
1586 | |||
1587 | static void __init tegra114_pmc_clk_init(void __iomem *pmc_base) | ||
1588 | { | ||
1589 | struct clk *clk; | ||
1590 | |||
1591 | /* clk_out_1 */ | ||
1592 | clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents, | ||
1593 | ARRAY_SIZE(clk_out1_parents), 0, | ||
1594 | pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0, | ||
1595 | &clk_out_lock); | ||
1596 | clks[clk_out_1_mux] = clk; | ||
1597 | clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0, | ||
1598 | pmc_base + PMC_CLK_OUT_CNTRL, 2, 0, | ||
1599 | &clk_out_lock); | ||
1600 | clk_register_clkdev(clk, "extern1", "clk_out_1"); | ||
1601 | clks[clk_out_1] = clk; | ||
1602 | |||
1603 | /* clk_out_2 */ | ||
1604 | clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents, | ||
1605 | ARRAY_SIZE(clk_out1_parents), 0, | ||
1606 | pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0, | ||
1607 | &clk_out_lock); | ||
1608 | clks[clk_out_2_mux] = clk; | ||
1609 | clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0, | ||
1610 | pmc_base + PMC_CLK_OUT_CNTRL, 10, 0, | ||
1611 | &clk_out_lock); | ||
1612 | clk_register_clkdev(clk, "extern2", "clk_out_2"); | ||
1613 | clks[clk_out_2] = clk; | ||
1614 | |||
1615 | /* clk_out_3 */ | ||
1616 | clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents, | ||
1617 | ARRAY_SIZE(clk_out1_parents), 0, | ||
1618 | pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0, | ||
1619 | &clk_out_lock); | ||
1620 | clks[clk_out_3_mux] = clk; | ||
1621 | clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0, | ||
1622 | pmc_base + PMC_CLK_OUT_CNTRL, 18, 0, | ||
1623 | &clk_out_lock); | ||
1624 | clk_register_clkdev(clk, "extern3", "clk_out_3"); | ||
1625 | clks[clk_out_3] = clk; | ||
1626 | |||
1627 | /* blink */ | ||
1628 | clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0, | ||
1629 | pmc_base + PMC_DPD_PADS_ORIDE, | ||
1630 | PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL); | ||
1631 | clk = clk_register_gate(NULL, "blink", "blink_override", 0, | ||
1632 | pmc_base + PMC_CTRL, | ||
1633 | PMC_CTRL_BLINK_ENB, 0, NULL); | ||
1634 | clk_register_clkdev(clk, "blink", NULL); | ||
1635 | clks[blink] = clk; | ||
1636 | |||
1637 | } | ||
1638 | |||
1639 | static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", | ||
1640 | "pll_p_out3", "pll_p_out2", "unused", | ||
1641 | "clk_32k", "pll_m_out1" }; | ||
1642 | |||
1643 | static const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", | ||
1644 | "pll_p", "pll_p_out4", "unused", | ||
1645 | "unused", "pll_x" }; | ||
1646 | |||
1647 | static const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", | ||
1648 | "pll_p", "pll_p_out4", "unused", | ||
1649 | "unused", "pll_x", "pll_x_out0" }; | ||
1650 | |||
1651 | static void __init tegra114_super_clk_init(void __iomem *clk_base) | ||
1652 | { | ||
1653 | struct clk *clk; | ||
1654 | |||
1655 | /* CCLKG */ | ||
1656 | clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents, | ||
1657 | ARRAY_SIZE(cclk_g_parents), | ||
1658 | CLK_SET_RATE_PARENT, | ||
1659 | clk_base + CCLKG_BURST_POLICY, | ||
1660 | 0, 4, 0, 0, NULL); | ||
1661 | clk_register_clkdev(clk, "cclk_g", NULL); | ||
1662 | clks[cclk_g] = clk; | ||
1663 | |||
1664 | /* CCLKLP */ | ||
1665 | clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents, | ||
1666 | ARRAY_SIZE(cclk_lp_parents), | ||
1667 | CLK_SET_RATE_PARENT, | ||
1668 | clk_base + CCLKLP_BURST_POLICY, | ||
1669 | 0, 4, 8, 9, NULL); | ||
1670 | clk_register_clkdev(clk, "cclk_lp", NULL); | ||
1671 | clks[cclk_lp] = clk; | ||
1672 | |||
1673 | /* SCLK */ | ||
1674 | clk = tegra_clk_register_super_mux("sclk", sclk_parents, | ||
1675 | ARRAY_SIZE(sclk_parents), | ||
1676 | CLK_SET_RATE_PARENT, | ||
1677 | clk_base + SCLK_BURST_POLICY, | ||
1678 | 0, 4, 0, 0, NULL); | ||
1679 | clk_register_clkdev(clk, "sclk", NULL); | ||
1680 | clks[sclk] = clk; | ||
1681 | |||
1682 | /* HCLK */ | ||
1683 | clk = clk_register_divider(NULL, "hclk_div", "sclk", 0, | ||
1684 | clk_base + SYSTEM_CLK_RATE, 4, 2, 0, | ||
1685 | &sysrate_lock); | ||
1686 | clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT | | ||
1687 | CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, | ||
1688 | 7, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); | ||
1689 | clk_register_clkdev(clk, "hclk", NULL); | ||
1690 | clks[hclk] = clk; | ||
1691 | |||
1692 | /* PCLK */ | ||
1693 | clk = clk_register_divider(NULL, "pclk_div", "hclk", 0, | ||
1694 | clk_base + SYSTEM_CLK_RATE, 0, 2, 0, | ||
1695 | &sysrate_lock); | ||
1696 | clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT | | ||
1697 | CLK_IGNORE_UNUSED, clk_base + SYSTEM_CLK_RATE, | ||
1698 | 3, CLK_GATE_SET_TO_DISABLE, &sysrate_lock); | ||
1699 | clk_register_clkdev(clk, "pclk", NULL); | ||
1700 | clks[pclk] = clk; | ||
1701 | } | ||
1702 | |||
1703 | static struct tegra_periph_init_data tegra_periph_clk_list[] = { | ||
1704 | TEGRA_INIT_DATA_MUX("i2s0", NULL, "tegra30-i2s.0", mux_pllaout0_audio0_2x_pllp_clkm, CLK_SOURCE_I2S0, 30, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0), | ||
1705 | TEGRA_INIT_DATA_MUX("i2s1", NULL, "tegra30-i2s.1", mux_pllaout0_audio1_2x_pllp_clkm, CLK_SOURCE_I2S1, 11, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1), | ||
1706 | TEGRA_INIT_DATA_MUX("i2s2", NULL, "tegra30-i2s.2", mux_pllaout0_audio2_2x_pllp_clkm, CLK_SOURCE_I2S2, 18, &periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2), | ||
1707 | TEGRA_INIT_DATA_MUX("i2s3", NULL, "tegra30-i2s.3", mux_pllaout0_audio3_2x_pllp_clkm, CLK_SOURCE_I2S3, 101, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3), | ||
1708 | TEGRA_INIT_DATA_MUX("i2s4", NULL, "tegra30-i2s.4", mux_pllaout0_audio4_2x_pllp_clkm, CLK_SOURCE_I2S4, 102, &periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4), | ||
1709 | TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out", "tegra30-spdif", mux_pllaout0_audio_2x_pllp_clkm, CLK_SOURCE_SPDIF_OUT, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out), | ||
1710 | TEGRA_INIT_DATA_MUX("spdif_in", "spdif_in", "tegra30-spdif", mux_pllp_pllc_pllm, CLK_SOURCE_SPDIF_IN, 10, &periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in), | ||
1711 | TEGRA_INIT_DATA_MUX("pwm", NULL, "pwm", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_PWM, 17, &periph_l_regs, TEGRA_PERIPH_ON_APB, pwm), | ||
1712 | TEGRA_INIT_DATA_MUX("adx", NULL, "adx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_ADX, 154, &periph_w_regs, TEGRA_PERIPH_ON_APB, adx), | ||
1713 | TEGRA_INIT_DATA_MUX("amx", NULL, "amx", mux_plla_pllc_pllp_clkm, CLK_SOURCE_AMX, 153, &periph_w_regs, TEGRA_PERIPH_ON_APB, amx), | ||
1714 | TEGRA_INIT_DATA_MUX("hda", "hda", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA, 125, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda), | ||
1715 | TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_HDA2CODEC_2X, 111, &periph_v_regs, TEGRA_PERIPH_ON_APB, hda2codec_2x), | ||
1716 | TEGRA_INIT_DATA_MUX("sbc1", NULL, "tegra11-spi.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC1, 41, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1), | ||
1717 | TEGRA_INIT_DATA_MUX("sbc2", NULL, "tegra11-spi.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC2, 44, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2), | ||
1718 | TEGRA_INIT_DATA_MUX("sbc3", NULL, "tegra11-spi.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC3, 46, &periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3), | ||
1719 | TEGRA_INIT_DATA_MUX("sbc4", NULL, "tegra11-spi.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC4, 68, &periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4), | ||
1720 | TEGRA_INIT_DATA_MUX("sbc5", NULL, "tegra11-spi.4", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC5, 104, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5), | ||
1721 | TEGRA_INIT_DATA_MUX("sbc6", NULL, "tegra11-spi.5", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SBC6, 105, &periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6), | ||
1722 | TEGRA_INIT_DATA_MUX8("ndflash", NULL, "tegra_nand", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDFLASH, 13, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed), | ||
1723 | TEGRA_INIT_DATA_MUX8("ndspeed", NULL, "tegra_nand_speed", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_NDSPEED, 80, &periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed), | ||
1724 | TEGRA_INIT_DATA_MUX("vfir", NULL, "vfir", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_VFIR, 7, &periph_l_regs, TEGRA_PERIPH_ON_APB, vfir), | ||
1725 | TEGRA_INIT_DATA_MUX("sdmmc1", NULL, "sdhci-tegra.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC1, 14, &periph_l_regs, 0, sdmmc1), | ||
1726 | TEGRA_INIT_DATA_MUX("sdmmc2", NULL, "sdhci-tegra.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC2, 9, &periph_l_regs, 0, sdmmc2), | ||
1727 | TEGRA_INIT_DATA_MUX("sdmmc3", NULL, "sdhci-tegra.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC3, 69, &periph_u_regs, 0, sdmmc3), | ||
1728 | TEGRA_INIT_DATA_MUX("sdmmc4", NULL, "sdhci-tegra.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_SDMMC4, 15, &periph_l_regs, 0, sdmmc4), | ||
1729 | TEGRA_INIT_DATA_INT("vde", NULL, "vde", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_VDE, 61, &periph_h_regs, 0, vde), | ||
1730 | TEGRA_INIT_DATA_MUX_FLAGS("csite", NULL, "csite", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_CSITE, 73, &periph_u_regs, TEGRA_PERIPH_ON_APB, csite, CLK_IGNORE_UNUSED), | ||
1731 | TEGRA_INIT_DATA_MUX("la", NULL, "la", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_LA, 76, &periph_u_regs, TEGRA_PERIPH_ON_APB, la), | ||
1732 | TEGRA_INIT_DATA_MUX("trace", NULL, "trace", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_TRACE, 77, &periph_u_regs, TEGRA_PERIPH_ON_APB, trace), | ||
1733 | TEGRA_INIT_DATA_MUX("owr", NULL, "tegra_w1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_OWR, 71, &periph_u_regs, TEGRA_PERIPH_ON_APB, owr), | ||
1734 | TEGRA_INIT_DATA_MUX("nor", NULL, "tegra-nor", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_NOR, 42, &periph_h_regs, 0, nor), | ||
1735 | TEGRA_INIT_DATA_MUX("mipi", NULL, "mipi", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_MIPI, 50, &periph_h_regs, TEGRA_PERIPH_ON_APB, mipi), | ||
1736 | TEGRA_INIT_DATA_I2C("i2c1", "div-clk", "tegra11-i2c.0", mux_pllp_clkm, CLK_SOURCE_I2C1, 12, &periph_l_regs, i2c1), | ||
1737 | TEGRA_INIT_DATA_I2C("i2c2", "div-clk", "tegra11-i2c.1", mux_pllp_clkm, CLK_SOURCE_I2C2, 54, &periph_h_regs, i2c2), | ||
1738 | TEGRA_INIT_DATA_I2C("i2c3", "div-clk", "tegra11-i2c.2", mux_pllp_clkm, CLK_SOURCE_I2C3, 67, &periph_u_regs, i2c3), | ||
1739 | TEGRA_INIT_DATA_I2C("i2c4", "div-clk", "tegra11-i2c.3", mux_pllp_clkm, CLK_SOURCE_I2C4, 103, &periph_v_regs, i2c4), | ||
1740 | TEGRA_INIT_DATA_I2C("i2c5", "div-clk", "tegra11-i2c.4", mux_pllp_clkm, CLK_SOURCE_I2C5, 47, &periph_h_regs, i2c5), | ||
1741 | TEGRA_INIT_DATA_UART("uarta", NULL, "tegra_uart.0", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTA, 6, &periph_l_regs, uarta), | ||
1742 | TEGRA_INIT_DATA_UART("uartb", NULL, "tegra_uart.1", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTB, 7, &periph_l_regs, uartb), | ||
1743 | TEGRA_INIT_DATA_UART("uartc", NULL, "tegra_uart.2", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTC, 55, &periph_h_regs, uartc), | ||
1744 | TEGRA_INIT_DATA_UART("uartd", NULL, "tegra_uart.3", mux_pllp_pllc_pllm_clkm, CLK_SOURCE_UARTD, 65, &periph_u_regs, uartd), | ||
1745 | TEGRA_INIT_DATA_INT("3d", NULL, "3d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_3D, 24, &periph_l_regs, 0, gr_3d), | ||
1746 | TEGRA_INIT_DATA_INT("2d", NULL, "2d", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_2D, 21, &periph_l_regs, 0, gr_2d), | ||
1747 | TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI_SENSOR, 20, &periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor), | ||
1748 | TEGRA_INIT_DATA_INT8("vi", "vi", "tegra_camera", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_VI, 20, &periph_l_regs, 0, vi), | ||
1749 | TEGRA_INIT_DATA_INT8("epp", NULL, "epp", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_EPP, 19, &periph_l_regs, 0, epp), | ||
1750 | TEGRA_INIT_DATA_INT8("msenc", NULL, "msenc", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_MSENC, 91, &periph_h_regs, TEGRA_PERIPH_WAR_1005168, msenc), | ||
1751 | TEGRA_INIT_DATA_INT8("tsec", NULL, "tsec", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_TSEC, 83, &periph_u_regs, 0, tsec), | ||
1752 | TEGRA_INIT_DATA_INT8("host1x", NULL, "host1x", mux_pllm_pllc2_c_c3_pllp_plla, CLK_SOURCE_HOST1X, 28, &periph_l_regs, 0, host1x), | ||
1753 | TEGRA_INIT_DATA_MUX8("hdmi", NULL, "hdmi", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_HDMI, 51, &periph_h_regs, 0, hdmi), | ||
1754 | TEGRA_INIT_DATA_MUX("cilab", "cilab", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILAB, 144, &periph_w_regs, 0, cilab), | ||
1755 | TEGRA_INIT_DATA_MUX("cilcd", "cilcd", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILCD, 145, &periph_w_regs, 0, cilcd), | ||
1756 | TEGRA_INIT_DATA_MUX("cile", "cile", "tegra_camera", mux_pllp_pllc_clkm, CLK_SOURCE_CILE, 146, &periph_w_regs, 0, cile), | ||
1757 | TEGRA_INIT_DATA_MUX("dsialp", "dsialp", "tegradc.0", mux_pllp_pllc_clkm, CLK_SOURCE_DSIALP, 147, &periph_w_regs, 0, dsialp), | ||
1758 | TEGRA_INIT_DATA_MUX("dsiblp", "dsiblp", "tegradc.1", mux_pllp_pllc_clkm, CLK_SOURCE_DSIBLP, 148, &periph_w_regs, 0, dsiblp), | ||
1759 | TEGRA_INIT_DATA_MUX("tsensor", NULL, "tegra-tsensor", mux_pllp_pllc_clkm_clk32, CLK_SOURCE_TSENSOR, 100, &periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor), | ||
1760 | TEGRA_INIT_DATA_MUX("actmon", NULL, "actmon", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_ACTMON, 119, &periph_v_regs, 0, actmon), | ||
1761 | TEGRA_INIT_DATA_MUX8("extern1", NULL, "extern1", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN1, 120, &periph_v_regs, 0, extern1), | ||
1762 | TEGRA_INIT_DATA_MUX8("extern2", NULL, "extern2", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN2, 121, &periph_v_regs, 0, extern2), | ||
1763 | TEGRA_INIT_DATA_MUX8("extern3", NULL, "extern3", mux_plla_clk32_pllp_clkm_plle, CLK_SOURCE_EXTERN3, 122, &periph_v_regs, 0, extern3), | ||
1764 | TEGRA_INIT_DATA_MUX("i2cslow", NULL, "i2cslow", mux_pllp_pllc_clk32_clkm, CLK_SOURCE_I2CSLOW, 81, &periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow), | ||
1765 | TEGRA_INIT_DATA_INT8("se", NULL, "se", mux_pllp_pllc2_c_c3_pllm_clkm, CLK_SOURCE_SE, 127, &periph_v_regs, TEGRA_PERIPH_ON_APB, se), | ||
1766 | TEGRA_INIT_DATA_INT_FLAGS("mselect", NULL, "mselect", mux_pllp_clkm, CLK_SOURCE_MSELECT, 99, &periph_v_regs, 0, mselect, CLK_IGNORE_UNUSED), | ||
1767 | TEGRA_INIT_DATA_MUX8("soc_therm", NULL, "soc_therm", mux_pllm_pllc_pllp_plla, CLK_SOURCE_SOC_THERM, 78, &periph_u_regs, TEGRA_PERIPH_ON_APB, soc_therm), | ||
1768 | TEGRA_INIT_DATA_XUSB("xusb_host_src", "host_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_HOST_SRC, 143, &periph_w_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_host_src), | ||
1769 | TEGRA_INIT_DATA_XUSB("xusb_falcon_src", "falcon_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_FALCON_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_falcon_src), | ||
1770 | TEGRA_INIT_DATA_XUSB("xusb_fs_src", "fs_src", "tegra_xhci", mux_clkm_48M_pllp_480M, CLK_SOURCE_XUSB_FS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_fs_src), | ||
1771 | TEGRA_INIT_DATA_XUSB("xusb_ss_src", "ss_src", "tegra_xhci", mux_clkm_pllre_clk32_480M_pllc_ref, CLK_SOURCE_XUSB_SS_SRC, 143, &periph_w_regs, TEGRA_PERIPH_NO_RESET, xusb_ss_src), | ||
1772 | TEGRA_INIT_DATA_XUSB("xusb_dev_src", "dev_src", "tegra_xhci", mux_clkm_pllp_pllc_pllre, CLK_SOURCE_XUSB_DEV_SRC, 95, &periph_u_regs, TEGRA_PERIPH_ON_APB | TEGRA_PERIPH_NO_RESET, xusb_dev_src), | ||
1773 | TEGRA_INIT_DATA_AUDIO("d_audio", "d_audio", "tegra30-ahub", CLK_SOURCE_D_AUDIO, 106, &periph_v_regs, TEGRA_PERIPH_ON_APB, d_audio), | ||
1774 | TEGRA_INIT_DATA_AUDIO("dam0", NULL, "tegra30-dam.0", CLK_SOURCE_DAM0, 108, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam0), | ||
1775 | TEGRA_INIT_DATA_AUDIO("dam1", NULL, "tegra30-dam.1", CLK_SOURCE_DAM1, 109, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam1), | ||
1776 | TEGRA_INIT_DATA_AUDIO("dam2", NULL, "tegra30-dam.2", CLK_SOURCE_DAM2, 110, &periph_v_regs, TEGRA_PERIPH_ON_APB, dam2), | ||
1777 | }; | ||
1778 | |||
1779 | static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = { | ||
1780 | TEGRA_INIT_DATA_NODIV("disp1", NULL, "tegradc.0", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP1, 29, 7, 27, &periph_l_regs, 0, disp1), | ||
1781 | TEGRA_INIT_DATA_NODIV("disp2", NULL, "tegradc.1", mux_pllp_pllm_plld_plla_pllc_plld2_clkm, CLK_SOURCE_DISP2, 29, 7, 26, &periph_l_regs, 0, disp2), | ||
1782 | }; | ||
1783 | |||
1784 | static __init void tegra114_periph_clk_init(void __iomem *clk_base) | ||
1785 | { | ||
1786 | struct tegra_periph_init_data *data; | ||
1787 | struct clk *clk; | ||
1788 | int i; | ||
1789 | u32 val; | ||
1790 | |||
1791 | /* apbdma */ | ||
1792 | clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, | ||
1793 | 0, 34, &periph_h_regs, | ||
1794 | periph_clk_enb_refcnt); | ||
1795 | clks[apbdma] = clk; | ||
1796 | |||
1797 | /* rtc */ | ||
1798 | clk = tegra_clk_register_periph_gate("rtc", "clk_32k", | ||
1799 | TEGRA_PERIPH_ON_APB | | ||
1800 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1801 | 0, 4, &periph_l_regs, | ||
1802 | periph_clk_enb_refcnt); | ||
1803 | clk_register_clkdev(clk, NULL, "rtc-tegra"); | ||
1804 | clks[rtc] = clk; | ||
1805 | |||
1806 | /* kbc */ | ||
1807 | clk = tegra_clk_register_periph_gate("kbc", "clk_32k", | ||
1808 | TEGRA_PERIPH_ON_APB | | ||
1809 | TEGRA_PERIPH_NO_RESET, clk_base, | ||
1810 | 0, 36, &periph_h_regs, | ||
1811 | periph_clk_enb_refcnt); | ||
1812 | clks[kbc] = clk; | ||
1813 | |||
1814 | /* timer */ | ||
1815 | clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, | ||
1816 | 0, 5, &periph_l_regs, | ||
1817 | periph_clk_enb_refcnt); | ||
1818 | clk_register_clkdev(clk, NULL, "timer"); | ||
1819 | clks[timer] = clk; | ||
1820 | |||
1821 | /* kfuse */ | ||
1822 | clk = tegra_clk_register_periph_gate("kfuse", "clk_m", | ||
1823 | TEGRA_PERIPH_ON_APB, clk_base, 0, 40, | ||
1824 | &periph_h_regs, periph_clk_enb_refcnt); | ||
1825 | clks[kfuse] = clk; | ||
1826 | |||
1827 | /* fuse */ | ||
1828 | clk = tegra_clk_register_periph_gate("fuse", "clk_m", | ||
1829 | TEGRA_PERIPH_ON_APB, clk_base, 0, 39, | ||
1830 | &periph_h_regs, periph_clk_enb_refcnt); | ||
1831 | clks[fuse] = clk; | ||
1832 | |||
1833 | /* fuse_burn */ | ||
1834 | clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m", | ||
1835 | TEGRA_PERIPH_ON_APB, clk_base, 0, 39, | ||
1836 | &periph_h_regs, periph_clk_enb_refcnt); | ||
1837 | clks[fuse_burn] = clk; | ||
1838 | |||
1839 | /* apbif */ | ||
1840 | clk = tegra_clk_register_periph_gate("apbif", "clk_m", | ||
1841 | TEGRA_PERIPH_ON_APB, clk_base, 0, 107, | ||
1842 | &periph_v_regs, periph_clk_enb_refcnt); | ||
1843 | clks[apbif] = clk; | ||
1844 | |||
1845 | /* hda2hdmi */ | ||
1846 | clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m", | ||
1847 | TEGRA_PERIPH_ON_APB, clk_base, 0, 128, | ||
1848 | &periph_w_regs, periph_clk_enb_refcnt); | ||
1849 | clks[hda2hdmi] = clk; | ||
1850 | |||
1851 | /* vcp */ | ||
1852 | clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, | ||
1853 | 29, &periph_l_regs, | ||
1854 | periph_clk_enb_refcnt); | ||
1855 | clks[vcp] = clk; | ||
1856 | |||
1857 | /* bsea */ | ||
1858 | clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, | ||
1859 | 0, 62, &periph_h_regs, | ||
1860 | periph_clk_enb_refcnt); | ||
1861 | clks[bsea] = clk; | ||
1862 | |||
1863 | /* bsev */ | ||
1864 | clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, | ||
1865 | 0, 63, &periph_h_regs, | ||
1866 | periph_clk_enb_refcnt); | ||
1867 | clks[bsev] = clk; | ||
1868 | |||
1869 | /* mipi-cal */ | ||
1870 | clk = tegra_clk_register_periph_gate("mipi-cal", "clk_m", 0, clk_base, | ||
1871 | 0, 56, &periph_h_regs, | ||
1872 | periph_clk_enb_refcnt); | ||
1873 | clks[mipi_cal] = clk; | ||
1874 | |||
1875 | /* usbd */ | ||
1876 | clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, | ||
1877 | 0, 22, &periph_l_regs, | ||
1878 | periph_clk_enb_refcnt); | ||
1879 | clks[usbd] = clk; | ||
1880 | |||
1881 | /* usb2 */ | ||
1882 | clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, | ||
1883 | 0, 58, &periph_h_regs, | ||
1884 | periph_clk_enb_refcnt); | ||
1885 | clks[usb2] = clk; | ||
1886 | |||
1887 | /* usb3 */ | ||
1888 | clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, | ||
1889 | 0, 59, &periph_h_regs, | ||
1890 | periph_clk_enb_refcnt); | ||
1891 | clks[usb3] = clk; | ||
1892 | |||
1893 | /* csi */ | ||
1894 | clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base, | ||
1895 | 0, 52, &periph_h_regs, | ||
1896 | periph_clk_enb_refcnt); | ||
1897 | clks[csi] = clk; | ||
1898 | |||
1899 | /* isp */ | ||
1900 | clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, | ||
1901 | 23, &periph_l_regs, | ||
1902 | periph_clk_enb_refcnt); | ||
1903 | clks[isp] = clk; | ||
1904 | |||
1905 | /* csus */ | ||
1906 | clk = tegra_clk_register_periph_gate("csus", "clk_m", | ||
1907 | TEGRA_PERIPH_NO_RESET, clk_base, 0, 92, | ||
1908 | &periph_u_regs, periph_clk_enb_refcnt); | ||
1909 | clks[csus] = clk; | ||
1910 | |||
1911 | /* dds */ | ||
1912 | clk = tegra_clk_register_periph_gate("dds", "clk_m", | ||
1913 | TEGRA_PERIPH_ON_APB, clk_base, 0, 150, | ||
1914 | &periph_w_regs, periph_clk_enb_refcnt); | ||
1915 | clks[dds] = clk; | ||
1916 | |||
1917 | /* dp2 */ | ||
1918 | clk = tegra_clk_register_periph_gate("dp2", "clk_m", | ||
1919 | TEGRA_PERIPH_ON_APB, clk_base, 0, 152, | ||
1920 | &periph_w_regs, periph_clk_enb_refcnt); | ||
1921 | clks[dp2] = clk; | ||
1922 | |||
1923 | /* dtv */ | ||
1924 | clk = tegra_clk_register_periph_gate("dtv", "clk_m", | ||
1925 | TEGRA_PERIPH_ON_APB, clk_base, 0, 79, | ||
1926 | &periph_u_regs, periph_clk_enb_refcnt); | ||
1927 | clks[dtv] = clk; | ||
1928 | |||
1929 | /* dsia */ | ||
1930 | clk = clk_register_mux(NULL, "dsia_mux", mux_plld_out0_plld2_out0, | ||
1931 | ARRAY_SIZE(mux_plld_out0_plld2_out0), 0, | ||
1932 | clk_base + PLLD_BASE, 25, 1, 0, &pll_d_lock); | ||
1933 | clks[dsia_mux] = clk; | ||
1934 | clk = tegra_clk_register_periph_gate("dsia", "dsia_mux", 0, clk_base, | ||
1935 | 0, 48, &periph_h_regs, | ||
1936 | periph_clk_enb_refcnt); | ||
1937 | clks[dsia] = clk; | ||
1938 | |||
1939 | /* dsib */ | ||
1940 | clk = clk_register_mux(NULL, "dsib_mux", mux_plld_out0_plld2_out0, | ||
1941 | ARRAY_SIZE(mux_plld_out0_plld2_out0), 0, | ||
1942 | clk_base + PLLD2_BASE, 25, 1, 0, &pll_d2_lock); | ||
1943 | clks[dsib_mux] = clk; | ||
1944 | clk = tegra_clk_register_periph_gate("dsib", "dsib_mux", 0, clk_base, | ||
1945 | 0, 82, &periph_u_regs, | ||
1946 | periph_clk_enb_refcnt); | ||
1947 | clks[dsib] = clk; | ||
1948 | |||
1949 | /* xusb_hs_src */ | ||
1950 | val = readl(clk_base + CLK_SOURCE_XUSB_SS_SRC); | ||
1951 | val |= BIT(25); /* always select PLLU_60M */ | ||
1952 | writel(val, clk_base + CLK_SOURCE_XUSB_SS_SRC); | ||
1953 | |||
1954 | clk = clk_register_fixed_factor(NULL, "xusb_hs_src", "pll_u_60M", 0, | ||
1955 | 1, 1); | ||
1956 | clks[xusb_hs_src] = clk; | ||
1957 | |||
1958 | /* xusb_host */ | ||
1959 | clk = tegra_clk_register_periph_gate("xusb_host", "xusb_host_src", 0, | ||
1960 | clk_base, 0, 89, &periph_u_regs, | ||
1961 | periph_clk_enb_refcnt); | ||
1962 | clks[xusb_host] = clk; | ||
1963 | |||
1964 | /* xusb_ss */ | ||
1965 | clk = tegra_clk_register_periph_gate("xusb_ss", "xusb_ss_src", 0, | ||
1966 | clk_base, 0, 156, &periph_w_regs, | ||
1967 | periph_clk_enb_refcnt); | ||
1968 | clks[xusb_host] = clk; | ||
1969 | |||
1970 | /* xusb_dev */ | ||
1971 | clk = tegra_clk_register_periph_gate("xusb_dev", "xusb_dev_src", 0, | ||
1972 | clk_base, 0, 95, &periph_u_regs, | ||
1973 | periph_clk_enb_refcnt); | ||
1974 | clks[xusb_dev] = clk; | ||
1975 | |||
1976 | /* emc */ | ||
1977 | clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm, | ||
1978 | ARRAY_SIZE(mux_pllmcp_clkm), 0, | ||
1979 | clk_base + CLK_SOURCE_EMC, | ||
1980 | 29, 3, 0, NULL); | ||
1981 | clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, | ||
1982 | CLK_IGNORE_UNUSED, 57, &periph_h_regs, | ||
1983 | periph_clk_enb_refcnt); | ||
1984 | clks[emc] = clk; | ||
1985 | |||
1986 | for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) { | ||
1987 | data = &tegra_periph_clk_list[i]; | ||
1988 | clk = tegra_clk_register_periph(data->name, data->parent_names, | ||
1989 | data->num_parents, &data->periph, | ||
1990 | clk_base, data->offset, data->flags); | ||
1991 | clks[data->clk_id] = clk; | ||
1992 | } | ||
1993 | |||
1994 | for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) { | ||
1995 | data = &tegra_periph_nodiv_clk_list[i]; | ||
1996 | clk = tegra_clk_register_periph_nodiv(data->name, | ||
1997 | data->parent_names, data->num_parents, | ||
1998 | &data->periph, clk_base, data->offset); | ||
1999 | clks[data->clk_id] = clk; | ||
2000 | } | ||
2001 | } | ||
2002 | |||
2003 | static struct tegra_cpu_car_ops tegra114_cpu_car_ops; | ||
2004 | |||
2005 | static const struct of_device_id pmc_match[] __initconst = { | ||
2006 | { .compatible = "nvidia,tegra114-pmc" }, | ||
2007 | {}, | ||
2008 | }; | ||
2009 | |||
2010 | static __initdata struct tegra_clk_init_table init_table[] = { | ||
2011 | {uarta, pll_p, 408000000, 0}, | ||
2012 | {uartb, pll_p, 408000000, 0}, | ||
2013 | {uartc, pll_p, 408000000, 0}, | ||
2014 | {uartd, pll_p, 408000000, 0}, | ||
2015 | {pll_a, clk_max, 564480000, 1}, | ||
2016 | {pll_a_out0, clk_max, 11289600, 1}, | ||
2017 | {extern1, pll_a_out0, 0, 1}, | ||
2018 | {clk_out_1_mux, extern1, 0, 1}, | ||
2019 | {clk_out_1, clk_max, 0, 1}, | ||
2020 | {i2s0, pll_a_out0, 11289600, 0}, | ||
2021 | {i2s1, pll_a_out0, 11289600, 0}, | ||
2022 | {i2s2, pll_a_out0, 11289600, 0}, | ||
2023 | {i2s3, pll_a_out0, 11289600, 0}, | ||
2024 | {i2s4, pll_a_out0, 11289600, 0}, | ||
2025 | {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */ | ||
2026 | }; | ||
2027 | |||
2028 | static void __init tegra114_clock_apply_init_table(void) | ||
2029 | { | ||
2030 | tegra_init_from_table(init_table, clks, clk_max); | ||
2031 | } | ||
2032 | |||
2033 | void __init tegra114_clock_init(struct device_node *np) | ||
2034 | { | ||
2035 | struct device_node *node; | ||
2036 | int i; | ||
2037 | |||
2038 | clk_base = of_iomap(np, 0); | ||
2039 | if (!clk_base) { | ||
2040 | pr_err("ioremap tegra114 CAR failed\n"); | ||
2041 | return; | ||
2042 | } | ||
2043 | |||
2044 | node = of_find_matching_node(NULL, pmc_match); | ||
2045 | if (!node) { | ||
2046 | pr_err("Failed to find pmc node\n"); | ||
2047 | WARN_ON(1); | ||
2048 | return; | ||
2049 | } | ||
2050 | |||
2051 | pmc_base = of_iomap(node, 0); | ||
2052 | if (!pmc_base) { | ||
2053 | pr_err("Can't map pmc registers\n"); | ||
2054 | WARN_ON(1); | ||
2055 | return; | ||
2056 | } | ||
2057 | |||
2058 | if (tegra114_osc_clk_init(clk_base) < 0) | ||
2059 | return; | ||
2060 | |||
2061 | tegra114_fixed_clk_init(clk_base); | ||
2062 | tegra114_pll_init(clk_base, pmc_base); | ||
2063 | tegra114_periph_clk_init(clk_base); | ||
2064 | tegra114_audio_clk_init(clk_base); | ||
2065 | tegra114_pmc_clk_init(pmc_base); | ||
2066 | tegra114_super_clk_init(clk_base); | ||
2067 | |||
2068 | for (i = 0; i < ARRAY_SIZE(clks); i++) { | ||
2069 | if (IS_ERR(clks[i])) { | ||
2070 | pr_err | ||
2071 | ("Tegra114 clk %d: register failed with %ld\n", | ||
2072 | i, PTR_ERR(clks[i])); | ||
2073 | } | ||
2074 | if (!clks[i]) | ||
2075 | clks[i] = ERR_PTR(-EINVAL); | ||
2076 | } | ||
2077 | |||
2078 | clk_data.clks = clks; | ||
2079 | clk_data.clk_num = ARRAY_SIZE(clks); | ||
2080 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | ||
2081 | |||
2082 | tegra_clk_apply_init_table = tegra114_clock_apply_init_table; | ||
2083 | |||
2084 | tegra_cpu_car_ops = &tegra114_cpu_car_ops; | ||
2085 | } | ||
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c index 143ce1f899ad..b0405b67f49c 100644 --- a/drivers/clk/tegra/clk-tegra20.c +++ b/drivers/clk/tegra/clk-tegra20.c | |||
@@ -86,8 +86,8 @@ | |||
86 | #define PLLE_BASE 0xe8 | 86 | #define PLLE_BASE 0xe8 |
87 | #define PLLE_MISC 0xec | 87 | #define PLLE_MISC 0xec |
88 | 88 | ||
89 | #define PLL_BASE_LOCK 27 | 89 | #define PLL_BASE_LOCK BIT(27) |
90 | #define PLLE_MISC_LOCK 11 | 90 | #define PLLE_MISC_LOCK BIT(11) |
91 | 91 | ||
92 | #define PLL_MISC_LOCK_ENABLE 18 | 92 | #define PLL_MISC_LOCK_ENABLE 18 |
93 | #define PLLDU_MISC_LOCK_ENABLE 22 | 93 | #define PLLDU_MISC_LOCK_ENABLE 22 |
@@ -236,7 +236,7 @@ enum tegra20_clk { | |||
236 | dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, | 236 | dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2, |
237 | usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, | 237 | usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, |
238 | pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb, | 238 | pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb, |
239 | iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev1, cdev2, | 239 | iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev2, cdev1, |
240 | uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve, | 240 | uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve, |
241 | osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0, | 241 | osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0, |
242 | pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1, | 242 | pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1, |
@@ -248,125 +248,125 @@ static struct clk *clks[clk_max]; | |||
248 | static struct clk_onecell_data clk_data; | 248 | static struct clk_onecell_data clk_data; |
249 | 249 | ||
250 | static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { | 250 | static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { |
251 | { 12000000, 600000000, 600, 12, 1, 8 }, | 251 | { 12000000, 600000000, 600, 12, 0, 8 }, |
252 | { 13000000, 600000000, 600, 13, 1, 8 }, | 252 | { 13000000, 600000000, 600, 13, 0, 8 }, |
253 | { 19200000, 600000000, 500, 16, 1, 6 }, | 253 | { 19200000, 600000000, 500, 16, 0, 6 }, |
254 | { 26000000, 600000000, 600, 26, 1, 8 }, | 254 | { 26000000, 600000000, 600, 26, 0, 8 }, |
255 | { 0, 0, 0, 0, 0, 0 }, | 255 | { 0, 0, 0, 0, 0, 0 }, |
256 | }; | 256 | }; |
257 | 257 | ||
258 | static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { | 258 | static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { |
259 | { 12000000, 666000000, 666, 12, 1, 8}, | 259 | { 12000000, 666000000, 666, 12, 0, 8}, |
260 | { 13000000, 666000000, 666, 13, 1, 8}, | 260 | { 13000000, 666000000, 666, 13, 0, 8}, |
261 | { 19200000, 666000000, 555, 16, 1, 8}, | 261 | { 19200000, 666000000, 555, 16, 0, 8}, |
262 | { 26000000, 666000000, 666, 26, 1, 8}, | 262 | { 26000000, 666000000, 666, 26, 0, 8}, |
263 | { 12000000, 600000000, 600, 12, 1, 8}, | 263 | { 12000000, 600000000, 600, 12, 0, 8}, |
264 | { 13000000, 600000000, 600, 13, 1, 8}, | 264 | { 13000000, 600000000, 600, 13, 0, 8}, |
265 | { 19200000, 600000000, 375, 12, 1, 6}, | 265 | { 19200000, 600000000, 375, 12, 0, 6}, |
266 | { 26000000, 600000000, 600, 26, 1, 8}, | 266 | { 26000000, 600000000, 600, 26, 0, 8}, |
267 | { 0, 0, 0, 0, 0, 0 }, | 267 | { 0, 0, 0, 0, 0, 0 }, |
268 | }; | 268 | }; |
269 | 269 | ||
270 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { | 270 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { |
271 | { 12000000, 216000000, 432, 12, 2, 8}, | 271 | { 12000000, 216000000, 432, 12, 1, 8}, |
272 | { 13000000, 216000000, 432, 13, 2, 8}, | 272 | { 13000000, 216000000, 432, 13, 1, 8}, |
273 | { 19200000, 216000000, 90, 4, 2, 1}, | 273 | { 19200000, 216000000, 90, 4, 1, 1}, |
274 | { 26000000, 216000000, 432, 26, 2, 8}, | 274 | { 26000000, 216000000, 432, 26, 1, 8}, |
275 | { 12000000, 432000000, 432, 12, 1, 8}, | 275 | { 12000000, 432000000, 432, 12, 0, 8}, |
276 | { 13000000, 432000000, 432, 13, 1, 8}, | 276 | { 13000000, 432000000, 432, 13, 0, 8}, |
277 | { 19200000, 432000000, 90, 4, 1, 1}, | 277 | { 19200000, 432000000, 90, 4, 0, 1}, |
278 | { 26000000, 432000000, 432, 26, 1, 8}, | 278 | { 26000000, 432000000, 432, 26, 0, 8}, |
279 | { 0, 0, 0, 0, 0, 0 }, | 279 | { 0, 0, 0, 0, 0, 0 }, |
280 | }; | 280 | }; |
281 | 281 | ||
282 | static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { | 282 | static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { |
283 | { 28800000, 56448000, 49, 25, 1, 1}, | 283 | { 28800000, 56448000, 49, 25, 0, 1}, |
284 | { 28800000, 73728000, 64, 25, 1, 1}, | 284 | { 28800000, 73728000, 64, 25, 0, 1}, |
285 | { 28800000, 24000000, 5, 6, 1, 1}, | 285 | { 28800000, 24000000, 5, 6, 0, 1}, |
286 | { 0, 0, 0, 0, 0, 0 }, | 286 | { 0, 0, 0, 0, 0, 0 }, |
287 | }; | 287 | }; |
288 | 288 | ||
289 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { | 289 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { |
290 | { 12000000, 216000000, 216, 12, 1, 4}, | 290 | { 12000000, 216000000, 216, 12, 0, 4}, |
291 | { 13000000, 216000000, 216, 13, 1, 4}, | 291 | { 13000000, 216000000, 216, 13, 0, 4}, |
292 | { 19200000, 216000000, 135, 12, 1, 3}, | 292 | { 19200000, 216000000, 135, 12, 0, 3}, |
293 | { 26000000, 216000000, 216, 26, 1, 4}, | 293 | { 26000000, 216000000, 216, 26, 0, 4}, |
294 | 294 | ||
295 | { 12000000, 594000000, 594, 12, 1, 8}, | 295 | { 12000000, 594000000, 594, 12, 0, 8}, |
296 | { 13000000, 594000000, 594, 13, 1, 8}, | 296 | { 13000000, 594000000, 594, 13, 0, 8}, |
297 | { 19200000, 594000000, 495, 16, 1, 8}, | 297 | { 19200000, 594000000, 495, 16, 0, 8}, |
298 | { 26000000, 594000000, 594, 26, 1, 8}, | 298 | { 26000000, 594000000, 594, 26, 0, 8}, |
299 | 299 | ||
300 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 300 | { 12000000, 1000000000, 1000, 12, 0, 12}, |
301 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 301 | { 13000000, 1000000000, 1000, 13, 0, 12}, |
302 | { 19200000, 1000000000, 625, 12, 1, 8}, | 302 | { 19200000, 1000000000, 625, 12, 0, 8}, |
303 | { 26000000, 1000000000, 1000, 26, 1, 12}, | 303 | { 26000000, 1000000000, 1000, 26, 0, 12}, |
304 | 304 | ||
305 | { 0, 0, 0, 0, 0, 0 }, | 305 | { 0, 0, 0, 0, 0, 0 }, |
306 | }; | 306 | }; |
307 | 307 | ||
308 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { | 308 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { |
309 | { 12000000, 480000000, 960, 12, 2, 0}, | 309 | { 12000000, 480000000, 960, 12, 0, 0}, |
310 | { 13000000, 480000000, 960, 13, 2, 0}, | 310 | { 13000000, 480000000, 960, 13, 0, 0}, |
311 | { 19200000, 480000000, 200, 4, 2, 0}, | 311 | { 19200000, 480000000, 200, 4, 0, 0}, |
312 | { 26000000, 480000000, 960, 26, 2, 0}, | 312 | { 26000000, 480000000, 960, 26, 0, 0}, |
313 | { 0, 0, 0, 0, 0, 0 }, | 313 | { 0, 0, 0, 0, 0, 0 }, |
314 | }; | 314 | }; |
315 | 315 | ||
316 | static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { | 316 | static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { |
317 | /* 1 GHz */ | 317 | /* 1 GHz */ |
318 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 318 | { 12000000, 1000000000, 1000, 12, 0, 12}, |
319 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 319 | { 13000000, 1000000000, 1000, 13, 0, 12}, |
320 | { 19200000, 1000000000, 625, 12, 1, 8}, | 320 | { 19200000, 1000000000, 625, 12, 0, 8}, |
321 | { 26000000, 1000000000, 1000, 26, 1, 12}, | 321 | { 26000000, 1000000000, 1000, 26, 0, 12}, |
322 | 322 | ||
323 | /* 912 MHz */ | 323 | /* 912 MHz */ |
324 | { 12000000, 912000000, 912, 12, 1, 12}, | 324 | { 12000000, 912000000, 912, 12, 0, 12}, |
325 | { 13000000, 912000000, 912, 13, 1, 12}, | 325 | { 13000000, 912000000, 912, 13, 0, 12}, |
326 | { 19200000, 912000000, 760, 16, 1, 8}, | 326 | { 19200000, 912000000, 760, 16, 0, 8}, |
327 | { 26000000, 912000000, 912, 26, 1, 12}, | 327 | { 26000000, 912000000, 912, 26, 0, 12}, |
328 | 328 | ||
329 | /* 816 MHz */ | 329 | /* 816 MHz */ |
330 | { 12000000, 816000000, 816, 12, 1, 12}, | 330 | { 12000000, 816000000, 816, 12, 0, 12}, |
331 | { 13000000, 816000000, 816, 13, 1, 12}, | 331 | { 13000000, 816000000, 816, 13, 0, 12}, |
332 | { 19200000, 816000000, 680, 16, 1, 8}, | 332 | { 19200000, 816000000, 680, 16, 0, 8}, |
333 | { 26000000, 816000000, 816, 26, 1, 12}, | 333 | { 26000000, 816000000, 816, 26, 0, 12}, |
334 | 334 | ||
335 | /* 760 MHz */ | 335 | /* 760 MHz */ |
336 | { 12000000, 760000000, 760, 12, 1, 12}, | 336 | { 12000000, 760000000, 760, 12, 0, 12}, |
337 | { 13000000, 760000000, 760, 13, 1, 12}, | 337 | { 13000000, 760000000, 760, 13, 0, 12}, |
338 | { 19200000, 760000000, 950, 24, 1, 8}, | 338 | { 19200000, 760000000, 950, 24, 0, 8}, |
339 | { 26000000, 760000000, 760, 26, 1, 12}, | 339 | { 26000000, 760000000, 760, 26, 0, 12}, |
340 | 340 | ||
341 | /* 750 MHz */ | 341 | /* 750 MHz */ |
342 | { 12000000, 750000000, 750, 12, 1, 12}, | 342 | { 12000000, 750000000, 750, 12, 0, 12}, |
343 | { 13000000, 750000000, 750, 13, 1, 12}, | 343 | { 13000000, 750000000, 750, 13, 0, 12}, |
344 | { 19200000, 750000000, 625, 16, 1, 8}, | 344 | { 19200000, 750000000, 625, 16, 0, 8}, |
345 | { 26000000, 750000000, 750, 26, 1, 12}, | 345 | { 26000000, 750000000, 750, 26, 0, 12}, |
346 | 346 | ||
347 | /* 608 MHz */ | 347 | /* 608 MHz */ |
348 | { 12000000, 608000000, 608, 12, 1, 12}, | 348 | { 12000000, 608000000, 608, 12, 0, 12}, |
349 | { 13000000, 608000000, 608, 13, 1, 12}, | 349 | { 13000000, 608000000, 608, 13, 0, 12}, |
350 | { 19200000, 608000000, 380, 12, 1, 8}, | 350 | { 19200000, 608000000, 380, 12, 0, 8}, |
351 | { 26000000, 608000000, 608, 26, 1, 12}, | 351 | { 26000000, 608000000, 608, 26, 0, 12}, |
352 | 352 | ||
353 | /* 456 MHz */ | 353 | /* 456 MHz */ |
354 | { 12000000, 456000000, 456, 12, 1, 12}, | 354 | { 12000000, 456000000, 456, 12, 0, 12}, |
355 | { 13000000, 456000000, 456, 13, 1, 12}, | 355 | { 13000000, 456000000, 456, 13, 0, 12}, |
356 | { 19200000, 456000000, 380, 16, 1, 8}, | 356 | { 19200000, 456000000, 380, 16, 0, 8}, |
357 | { 26000000, 456000000, 456, 26, 1, 12}, | 357 | { 26000000, 456000000, 456, 26, 0, 12}, |
358 | 358 | ||
359 | /* 312 MHz */ | 359 | /* 312 MHz */ |
360 | { 12000000, 312000000, 312, 12, 1, 12}, | 360 | { 12000000, 312000000, 312, 12, 0, 12}, |
361 | { 13000000, 312000000, 312, 13, 1, 12}, | 361 | { 13000000, 312000000, 312, 13, 0, 12}, |
362 | { 19200000, 312000000, 260, 16, 1, 8}, | 362 | { 19200000, 312000000, 260, 16, 0, 8}, |
363 | { 26000000, 312000000, 312, 26, 1, 12}, | 363 | { 26000000, 312000000, 312, 26, 0, 12}, |
364 | 364 | ||
365 | { 0, 0, 0, 0, 0, 0 }, | 365 | { 0, 0, 0, 0, 0, 0 }, |
366 | }; | 366 | }; |
367 | 367 | ||
368 | static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { | 368 | static struct tegra_clk_pll_freq_table pll_e_freq_table[] = { |
369 | { 12000000, 100000000, 200, 24, 1, 0 }, | 369 | { 12000000, 100000000, 200, 24, 0, 0 }, |
370 | { 0, 0, 0, 0, 0, 0 }, | 370 | { 0, 0, 0, 0, 0, 0 }, |
371 | }; | 371 | }; |
372 | 372 | ||
@@ -380,7 +380,7 @@ static struct tegra_clk_pll_params pll_c_params = { | |||
380 | .vco_max = 1400000000, | 380 | .vco_max = 1400000000, |
381 | .base_reg = PLLC_BASE, | 381 | .base_reg = PLLC_BASE, |
382 | .misc_reg = PLLC_MISC, | 382 | .misc_reg = PLLC_MISC, |
383 | .lock_bit_idx = PLL_BASE_LOCK, | 383 | .lock_mask = PLL_BASE_LOCK, |
384 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 384 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
385 | .lock_delay = 300, | 385 | .lock_delay = 300, |
386 | }; | 386 | }; |
@@ -394,7 +394,7 @@ static struct tegra_clk_pll_params pll_m_params = { | |||
394 | .vco_max = 1200000000, | 394 | .vco_max = 1200000000, |
395 | .base_reg = PLLM_BASE, | 395 | .base_reg = PLLM_BASE, |
396 | .misc_reg = PLLM_MISC, | 396 | .misc_reg = PLLM_MISC, |
397 | .lock_bit_idx = PLL_BASE_LOCK, | 397 | .lock_mask = PLL_BASE_LOCK, |
398 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 398 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
399 | .lock_delay = 300, | 399 | .lock_delay = 300, |
400 | }; | 400 | }; |
@@ -408,7 +408,7 @@ static struct tegra_clk_pll_params pll_p_params = { | |||
408 | .vco_max = 1400000000, | 408 | .vco_max = 1400000000, |
409 | .base_reg = PLLP_BASE, | 409 | .base_reg = PLLP_BASE, |
410 | .misc_reg = PLLP_MISC, | 410 | .misc_reg = PLLP_MISC, |
411 | .lock_bit_idx = PLL_BASE_LOCK, | 411 | .lock_mask = PLL_BASE_LOCK, |
412 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 412 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
413 | .lock_delay = 300, | 413 | .lock_delay = 300, |
414 | }; | 414 | }; |
@@ -422,7 +422,7 @@ static struct tegra_clk_pll_params pll_a_params = { | |||
422 | .vco_max = 1400000000, | 422 | .vco_max = 1400000000, |
423 | .base_reg = PLLA_BASE, | 423 | .base_reg = PLLA_BASE, |
424 | .misc_reg = PLLA_MISC, | 424 | .misc_reg = PLLA_MISC, |
425 | .lock_bit_idx = PLL_BASE_LOCK, | 425 | .lock_mask = PLL_BASE_LOCK, |
426 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 426 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
427 | .lock_delay = 300, | 427 | .lock_delay = 300, |
428 | }; | 428 | }; |
@@ -436,11 +436,17 @@ static struct tegra_clk_pll_params pll_d_params = { | |||
436 | .vco_max = 1000000000, | 436 | .vco_max = 1000000000, |
437 | .base_reg = PLLD_BASE, | 437 | .base_reg = PLLD_BASE, |
438 | .misc_reg = PLLD_MISC, | 438 | .misc_reg = PLLD_MISC, |
439 | .lock_bit_idx = PLL_BASE_LOCK, | 439 | .lock_mask = PLL_BASE_LOCK, |
440 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | 440 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, |
441 | .lock_delay = 1000, | 441 | .lock_delay = 1000, |
442 | }; | 442 | }; |
443 | 443 | ||
444 | static struct pdiv_map pllu_p[] = { | ||
445 | { .pdiv = 1, .hw_val = 1 }, | ||
446 | { .pdiv = 2, .hw_val = 0 }, | ||
447 | { .pdiv = 0, .hw_val = 0 }, | ||
448 | }; | ||
449 | |||
444 | static struct tegra_clk_pll_params pll_u_params = { | 450 | static struct tegra_clk_pll_params pll_u_params = { |
445 | .input_min = 2000000, | 451 | .input_min = 2000000, |
446 | .input_max = 40000000, | 452 | .input_max = 40000000, |
@@ -450,9 +456,10 @@ static struct tegra_clk_pll_params pll_u_params = { | |||
450 | .vco_max = 960000000, | 456 | .vco_max = 960000000, |
451 | .base_reg = PLLU_BASE, | 457 | .base_reg = PLLU_BASE, |
452 | .misc_reg = PLLU_MISC, | 458 | .misc_reg = PLLU_MISC, |
453 | .lock_bit_idx = PLL_BASE_LOCK, | 459 | .lock_mask = PLL_BASE_LOCK, |
454 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | 460 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, |
455 | .lock_delay = 1000, | 461 | .lock_delay = 1000, |
462 | .pdiv_tohw = pllu_p, | ||
456 | }; | 463 | }; |
457 | 464 | ||
458 | static struct tegra_clk_pll_params pll_x_params = { | 465 | static struct tegra_clk_pll_params pll_x_params = { |
@@ -464,7 +471,7 @@ static struct tegra_clk_pll_params pll_x_params = { | |||
464 | .vco_max = 1200000000, | 471 | .vco_max = 1200000000, |
465 | .base_reg = PLLX_BASE, | 472 | .base_reg = PLLX_BASE, |
466 | .misc_reg = PLLX_MISC, | 473 | .misc_reg = PLLX_MISC, |
467 | .lock_bit_idx = PLL_BASE_LOCK, | 474 | .lock_mask = PLL_BASE_LOCK, |
468 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 475 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
469 | .lock_delay = 300, | 476 | .lock_delay = 300, |
470 | }; | 477 | }; |
@@ -478,7 +485,7 @@ static struct tegra_clk_pll_params pll_e_params = { | |||
478 | .vco_max = 0, | 485 | .vco_max = 0, |
479 | .base_reg = PLLE_BASE, | 486 | .base_reg = PLLE_BASE, |
480 | .misc_reg = PLLE_MISC, | 487 | .misc_reg = PLLE_MISC, |
481 | .lock_bit_idx = PLLE_MISC_LOCK, | 488 | .lock_mask = PLLE_MISC_LOCK, |
482 | .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, | 489 | .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, |
483 | .lock_delay = 0, | 490 | .lock_delay = 0, |
484 | }; | 491 | }; |
@@ -711,8 +718,8 @@ static void tegra20_pll_init(void) | |||
711 | } | 718 | } |
712 | 719 | ||
713 | static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", | 720 | static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m", |
714 | "pll_p_cclk", "pll_p_out4_cclk", | 721 | "pll_p", "pll_p_out4", |
715 | "pll_p_out3_cclk", "clk_d", "pll_x" }; | 722 | "pll_p_out3", "clk_d", "pll_x" }; |
716 | static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", | 723 | static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4", |
717 | "pll_p_out3", "pll_p_out2", "clk_d", | 724 | "pll_p_out3", "pll_p_out2", "clk_d", |
718 | "clk_32k", "pll_m_out1" }; | 725 | "clk_32k", "pll_m_out1" }; |
@@ -721,38 +728,6 @@ static void tegra20_super_clk_init(void) | |||
721 | { | 728 | { |
722 | struct clk *clk; | 729 | struct clk *clk; |
723 | 730 | ||
724 | /* | ||
725 | * DIV_U71 dividers for CCLK, these dividers are used only | ||
726 | * if parent clock is fixed rate. | ||
727 | */ | ||
728 | |||
729 | /* | ||
730 | * Clock input to cclk divided from pll_p using | ||
731 | * U71 divider of cclk. | ||
732 | */ | ||
733 | clk = tegra_clk_register_divider("pll_p_cclk", "pll_p", | ||
734 | clk_base + SUPER_CCLK_DIVIDER, 0, | ||
735 | TEGRA_DIVIDER_INT, 16, 8, 1, NULL); | ||
736 | clk_register_clkdev(clk, "pll_p_cclk", NULL); | ||
737 | |||
738 | /* | ||
739 | * Clock input to cclk divided from pll_p_out3 using | ||
740 | * U71 divider of cclk. | ||
741 | */ | ||
742 | clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3", | ||
743 | clk_base + SUPER_CCLK_DIVIDER, 0, | ||
744 | TEGRA_DIVIDER_INT, 16, 8, 1, NULL); | ||
745 | clk_register_clkdev(clk, "pll_p_out3_cclk", NULL); | ||
746 | |||
747 | /* | ||
748 | * Clock input to cclk divided from pll_p_out4 using | ||
749 | * U71 divider of cclk. | ||
750 | */ | ||
751 | clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4", | ||
752 | clk_base + SUPER_CCLK_DIVIDER, 0, | ||
753 | TEGRA_DIVIDER_INT, 16, 8, 1, NULL); | ||
754 | clk_register_clkdev(clk, "pll_p_out4_cclk", NULL); | ||
755 | |||
756 | /* CCLK */ | 731 | /* CCLK */ |
757 | clk = tegra_clk_register_super_mux("cclk", cclk_parents, | 732 | clk = tegra_clk_register_super_mux("cclk", cclk_parents, |
758 | ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT, | 733 | ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT, |
@@ -1044,7 +1019,7 @@ static void __init tegra20_periph_clk_init(void) | |||
1044 | data = &tegra_periph_clk_list[i]; | 1019 | data = &tegra_periph_clk_list[i]; |
1045 | clk = tegra_clk_register_periph(data->name, data->parent_names, | 1020 | clk = tegra_clk_register_periph(data->name, data->parent_names, |
1046 | data->num_parents, &data->periph, | 1021 | data->num_parents, &data->periph, |
1047 | clk_base, data->offset); | 1022 | clk_base, data->offset, data->flags); |
1048 | clk_register_clkdev(clk, data->con_id, data->dev_id); | 1023 | clk_register_clkdev(clk, data->con_id, data->dev_id); |
1049 | clks[data->clk_id] = clk; | 1024 | clks[data->clk_id] = clk; |
1050 | } | 1025 | } |
@@ -1279,9 +1254,16 @@ static __initdata struct tegra_clk_init_table init_table[] = { | |||
1279 | {host1x, pll_c, 150000000, 0}, | 1254 | {host1x, pll_c, 150000000, 0}, |
1280 | {disp1, pll_p, 600000000, 0}, | 1255 | {disp1, pll_p, 600000000, 0}, |
1281 | {disp2, pll_p, 600000000, 0}, | 1256 | {disp2, pll_p, 600000000, 0}, |
1257 | {gr2d, pll_c, 300000000, 0}, | ||
1258 | {gr3d, pll_c, 300000000, 0}, | ||
1282 | {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */ | 1259 | {clk_max, clk_max, 0, 0}, /* This MUST be the last entry */ |
1283 | }; | 1260 | }; |
1284 | 1261 | ||
1262 | static void __init tegra20_clock_apply_init_table(void) | ||
1263 | { | ||
1264 | tegra_init_from_table(init_table, clks, clk_max); | ||
1265 | } | ||
1266 | |||
1285 | /* | 1267 | /* |
1286 | * Some clocks may be used by different drivers depending on the board | 1268 | * Some clocks may be used by different drivers depending on the board |
1287 | * configuration. List those here to register them twice in the clock lookup | 1269 | * configuration. List those here to register them twice in the clock lookup |
@@ -1292,7 +1274,6 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = { | |||
1292 | TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL), | 1274 | TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL), |
1293 | TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL), | 1275 | TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL), |
1294 | TEGRA_CLK_DUPLICATE(cclk, NULL, "cpu"), | 1276 | TEGRA_CLK_DUPLICATE(cclk, NULL, "cpu"), |
1295 | TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL), | ||
1296 | TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */ | 1277 | TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */ |
1297 | }; | 1278 | }; |
1298 | 1279 | ||
@@ -1349,7 +1330,7 @@ void __init tegra20_clock_init(struct device_node *np) | |||
1349 | clk_data.clk_num = ARRAY_SIZE(clks); | 1330 | clk_data.clk_num = ARRAY_SIZE(clks); |
1350 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | 1331 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); |
1351 | 1332 | ||
1352 | tegra_init_from_table(init_table, clks, clk_max); | 1333 | tegra_clk_apply_init_table = tegra20_clock_apply_init_table; |
1353 | 1334 | ||
1354 | tegra_cpu_car_ops = &tegra20_cpu_car_ops; | 1335 | tegra_cpu_car_ops = &tegra20_cpu_car_ops; |
1355 | } | 1336 | } |
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c index 32c61cb6d0bb..2dc0c5602613 100644 --- a/drivers/clk/tegra/clk-tegra30.c +++ b/drivers/clk/tegra/clk-tegra30.c | |||
@@ -116,8 +116,8 @@ | |||
116 | #define PLLDU_MISC_LOCK_ENABLE 22 | 116 | #define PLLDU_MISC_LOCK_ENABLE 22 |
117 | #define PLLE_MISC_LOCK_ENABLE 9 | 117 | #define PLLE_MISC_LOCK_ENABLE 9 |
118 | 118 | ||
119 | #define PLL_BASE_LOCK 27 | 119 | #define PLL_BASE_LOCK BIT(27) |
120 | #define PLLE_MISC_LOCK 11 | 120 | #define PLLE_MISC_LOCK BIT(11) |
121 | 121 | ||
122 | #define PLLE_AUX 0x48c | 122 | #define PLLE_AUX 0x48c |
123 | #define PLLC_OUT 0x84 | 123 | #define PLLC_OUT 0x84 |
@@ -330,7 +330,7 @@ enum tegra30_clk { | |||
330 | usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, | 330 | usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3, |
331 | pcie, owr, afi, csite, pciex, avpucq, la, dtv = 79, ndspeed, i2cslow, | 331 | pcie, owr, afi, csite, pciex, avpucq, la, dtv = 79, ndspeed, i2cslow, |
332 | dsib, irama = 84, iramb, iramc, iramd, cram2, audio_2x = 90, csus = 92, | 332 | dsib, irama = 84, iramb, iramc, iramd, cram2, audio_2x = 90, csus = 92, |
333 | cdev1, cdev2, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4, | 333 | cdev2, cdev1, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4, |
334 | i2c4, sbc5, sbc6, d_audio, apbif, dam0, dam1, dam2, hda2codec_2x, | 334 | i2c4, sbc5, sbc6, d_audio, apbif, dam0, dam1, dam2, hda2codec_2x, |
335 | atomics, audio0_2x, audio1_2x, audio2_2x, audio3_2x, audio4_2x, | 335 | atomics, audio0_2x, audio1_2x, audio2_2x, audio3_2x, audio4_2x, |
336 | spdif_2x, actmon, extern1, extern2, extern3, sata_oob, sata, hda, | 336 | spdif_2x, actmon, extern1, extern2, extern3, sata_oob, sata, hda, |
@@ -374,164 +374,170 @@ static const struct utmi_clk_param utmi_parameters[] = { | |||
374 | }; | 374 | }; |
375 | 375 | ||
376 | static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { | 376 | static struct tegra_clk_pll_freq_table pll_c_freq_table[] = { |
377 | { 12000000, 1040000000, 520, 6, 1, 8}, | 377 | { 12000000, 1040000000, 520, 6, 0, 8}, |
378 | { 13000000, 1040000000, 480, 6, 1, 8}, | 378 | { 13000000, 1040000000, 480, 6, 0, 8}, |
379 | { 16800000, 1040000000, 495, 8, 1, 8}, /* actual: 1039.5 MHz */ | 379 | { 16800000, 1040000000, 495, 8, 0, 8}, /* actual: 1039.5 MHz */ |
380 | { 19200000, 1040000000, 325, 6, 1, 6}, | 380 | { 19200000, 1040000000, 325, 6, 0, 6}, |
381 | { 26000000, 1040000000, 520, 13, 1, 8}, | 381 | { 26000000, 1040000000, 520, 13, 0, 8}, |
382 | 382 | ||
383 | { 12000000, 832000000, 416, 6, 1, 8}, | 383 | { 12000000, 832000000, 416, 6, 0, 8}, |
384 | { 13000000, 832000000, 832, 13, 1, 8}, | 384 | { 13000000, 832000000, 832, 13, 0, 8}, |
385 | { 16800000, 832000000, 396, 8, 1, 8}, /* actual: 831.6 MHz */ | 385 | { 16800000, 832000000, 396, 8, 0, 8}, /* actual: 831.6 MHz */ |
386 | { 19200000, 832000000, 260, 6, 1, 8}, | 386 | { 19200000, 832000000, 260, 6, 0, 8}, |
387 | { 26000000, 832000000, 416, 13, 1, 8}, | 387 | { 26000000, 832000000, 416, 13, 0, 8}, |
388 | 388 | ||
389 | { 12000000, 624000000, 624, 12, 1, 8}, | 389 | { 12000000, 624000000, 624, 12, 0, 8}, |
390 | { 13000000, 624000000, 624, 13, 1, 8}, | 390 | { 13000000, 624000000, 624, 13, 0, 8}, |
391 | { 16800000, 600000000, 520, 14, 1, 8}, | 391 | { 16800000, 600000000, 520, 14, 0, 8}, |
392 | { 19200000, 624000000, 520, 16, 1, 8}, | 392 | { 19200000, 624000000, 520, 16, 0, 8}, |
393 | { 26000000, 624000000, 624, 26, 1, 8}, | 393 | { 26000000, 624000000, 624, 26, 0, 8}, |
394 | 394 | ||
395 | { 12000000, 600000000, 600, 12, 1, 8}, | 395 | { 12000000, 600000000, 600, 12, 0, 8}, |
396 | { 13000000, 600000000, 600, 13, 1, 8}, | 396 | { 13000000, 600000000, 600, 13, 0, 8}, |
397 | { 16800000, 600000000, 500, 14, 1, 8}, | 397 | { 16800000, 600000000, 500, 14, 0, 8}, |
398 | { 19200000, 600000000, 375, 12, 1, 6}, | 398 | { 19200000, 600000000, 375, 12, 0, 6}, |
399 | { 26000000, 600000000, 600, 26, 1, 8}, | 399 | { 26000000, 600000000, 600, 26, 0, 8}, |
400 | 400 | ||
401 | { 12000000, 520000000, 520, 12, 1, 8}, | 401 | { 12000000, 520000000, 520, 12, 0, 8}, |
402 | { 13000000, 520000000, 520, 13, 1, 8}, | 402 | { 13000000, 520000000, 520, 13, 0, 8}, |
403 | { 16800000, 520000000, 495, 16, 1, 8}, /* actual: 519.75 MHz */ | 403 | { 16800000, 520000000, 495, 16, 0, 8}, /* actual: 519.75 MHz */ |
404 | { 19200000, 520000000, 325, 12, 1, 6}, | 404 | { 19200000, 520000000, 325, 12, 0, 6}, |
405 | { 26000000, 520000000, 520, 26, 1, 8}, | 405 | { 26000000, 520000000, 520, 26, 0, 8}, |
406 | 406 | ||
407 | { 12000000, 416000000, 416, 12, 1, 8}, | 407 | { 12000000, 416000000, 416, 12, 0, 8}, |
408 | { 13000000, 416000000, 416, 13, 1, 8}, | 408 | { 13000000, 416000000, 416, 13, 0, 8}, |
409 | { 16800000, 416000000, 396, 16, 1, 8}, /* actual: 415.8 MHz */ | 409 | { 16800000, 416000000, 396, 16, 0, 8}, /* actual: 415.8 MHz */ |
410 | { 19200000, 416000000, 260, 12, 1, 6}, | 410 | { 19200000, 416000000, 260, 12, 0, 6}, |
411 | { 26000000, 416000000, 416, 26, 1, 8}, | 411 | { 26000000, 416000000, 416, 26, 0, 8}, |
412 | { 0, 0, 0, 0, 0, 0 }, | 412 | { 0, 0, 0, 0, 0, 0 }, |
413 | }; | 413 | }; |
414 | 414 | ||
415 | static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { | 415 | static struct tegra_clk_pll_freq_table pll_m_freq_table[] = { |
416 | { 12000000, 666000000, 666, 12, 1, 8}, | 416 | { 12000000, 666000000, 666, 12, 0, 8}, |
417 | { 13000000, 666000000, 666, 13, 1, 8}, | 417 | { 13000000, 666000000, 666, 13, 0, 8}, |
418 | { 16800000, 666000000, 555, 14, 1, 8}, | 418 | { 16800000, 666000000, 555, 14, 0, 8}, |
419 | { 19200000, 666000000, 555, 16, 1, 8}, | 419 | { 19200000, 666000000, 555, 16, 0, 8}, |
420 | { 26000000, 666000000, 666, 26, 1, 8}, | 420 | { 26000000, 666000000, 666, 26, 0, 8}, |
421 | { 12000000, 600000000, 600, 12, 1, 8}, | 421 | { 12000000, 600000000, 600, 12, 0, 8}, |
422 | { 13000000, 600000000, 600, 13, 1, 8}, | 422 | { 13000000, 600000000, 600, 13, 0, 8}, |
423 | { 16800000, 600000000, 500, 14, 1, 8}, | 423 | { 16800000, 600000000, 500, 14, 0, 8}, |
424 | { 19200000, 600000000, 375, 12, 1, 6}, | 424 | { 19200000, 600000000, 375, 12, 0, 6}, |
425 | { 26000000, 600000000, 600, 26, 1, 8}, | 425 | { 26000000, 600000000, 600, 26, 0, 8}, |
426 | { 0, 0, 0, 0, 0, 0 }, | 426 | { 0, 0, 0, 0, 0, 0 }, |
427 | }; | 427 | }; |
428 | 428 | ||
429 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { | 429 | static struct tegra_clk_pll_freq_table pll_p_freq_table[] = { |
430 | { 12000000, 216000000, 432, 12, 2, 8}, | 430 | { 12000000, 216000000, 432, 12, 1, 8}, |
431 | { 13000000, 216000000, 432, 13, 2, 8}, | 431 | { 13000000, 216000000, 432, 13, 1, 8}, |
432 | { 16800000, 216000000, 360, 14, 2, 8}, | 432 | { 16800000, 216000000, 360, 14, 1, 8}, |
433 | { 19200000, 216000000, 360, 16, 2, 8}, | 433 | { 19200000, 216000000, 360, 16, 1, 8}, |
434 | { 26000000, 216000000, 432, 26, 2, 8}, | 434 | { 26000000, 216000000, 432, 26, 1, 8}, |
435 | { 0, 0, 0, 0, 0, 0 }, | 435 | { 0, 0, 0, 0, 0, 0 }, |
436 | }; | 436 | }; |
437 | 437 | ||
438 | static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { | 438 | static struct tegra_clk_pll_freq_table pll_a_freq_table[] = { |
439 | { 9600000, 564480000, 294, 5, 1, 4}, | 439 | { 9600000, 564480000, 294, 5, 0, 4}, |
440 | { 9600000, 552960000, 288, 5, 1, 4}, | 440 | { 9600000, 552960000, 288, 5, 0, 4}, |
441 | { 9600000, 24000000, 5, 2, 1, 1}, | 441 | { 9600000, 24000000, 5, 2, 0, 1}, |
442 | 442 | ||
443 | { 28800000, 56448000, 49, 25, 1, 1}, | 443 | { 28800000, 56448000, 49, 25, 0, 1}, |
444 | { 28800000, 73728000, 64, 25, 1, 1}, | 444 | { 28800000, 73728000, 64, 25, 0, 1}, |
445 | { 28800000, 24000000, 5, 6, 1, 1}, | 445 | { 28800000, 24000000, 5, 6, 0, 1}, |
446 | { 0, 0, 0, 0, 0, 0 }, | 446 | { 0, 0, 0, 0, 0, 0 }, |
447 | }; | 447 | }; |
448 | 448 | ||
449 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { | 449 | static struct tegra_clk_pll_freq_table pll_d_freq_table[] = { |
450 | { 12000000, 216000000, 216, 12, 1, 4}, | 450 | { 12000000, 216000000, 216, 12, 0, 4}, |
451 | { 13000000, 216000000, 216, 13, 1, 4}, | 451 | { 13000000, 216000000, 216, 13, 0, 4}, |
452 | { 16800000, 216000000, 180, 14, 1, 4}, | 452 | { 16800000, 216000000, 180, 14, 0, 4}, |
453 | { 19200000, 216000000, 180, 16, 1, 4}, | 453 | { 19200000, 216000000, 180, 16, 0, 4}, |
454 | { 26000000, 216000000, 216, 26, 1, 4}, | 454 | { 26000000, 216000000, 216, 26, 0, 4}, |
455 | 455 | ||
456 | { 12000000, 594000000, 594, 12, 1, 8}, | 456 | { 12000000, 594000000, 594, 12, 0, 8}, |
457 | { 13000000, 594000000, 594, 13, 1, 8}, | 457 | { 13000000, 594000000, 594, 13, 0, 8}, |
458 | { 16800000, 594000000, 495, 14, 1, 8}, | 458 | { 16800000, 594000000, 495, 14, 0, 8}, |
459 | { 19200000, 594000000, 495, 16, 1, 8}, | 459 | { 19200000, 594000000, 495, 16, 0, 8}, |
460 | { 26000000, 594000000, 594, 26, 1, 8}, | 460 | { 26000000, 594000000, 594, 26, 0, 8}, |
461 | 461 | ||
462 | { 12000000, 1000000000, 1000, 12, 1, 12}, | 462 | { 12000000, 1000000000, 1000, 12, 0, 12}, |
463 | { 13000000, 1000000000, 1000, 13, 1, 12}, | 463 | { 13000000, 1000000000, 1000, 13, 0, 12}, |
464 | { 19200000, 1000000000, 625, 12, 1, 8}, | 464 | { 19200000, 1000000000, 625, 12, 0, 8}, |
465 | { 26000000, 1000000000, 1000, 26, 1, 12}, | 465 | { 26000000, 1000000000, 1000, 26, 0, 12}, |
466 | 466 | ||
467 | { 0, 0, 0, 0, 0, 0 }, | 467 | { 0, 0, 0, 0, 0, 0 }, |
468 | }; | 468 | }; |
469 | 469 | ||
470 | static struct pdiv_map pllu_p[] = { | ||
471 | { .pdiv = 1, .hw_val = 1 }, | ||
472 | { .pdiv = 2, .hw_val = 0 }, | ||
473 | { .pdiv = 0, .hw_val = 0 }, | ||
474 | }; | ||
475 | |||
470 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { | 476 | static struct tegra_clk_pll_freq_table pll_u_freq_table[] = { |
471 | { 12000000, 480000000, 960, 12, 2, 12}, | 477 | { 12000000, 480000000, 960, 12, 0, 12}, |
472 | { 13000000, 480000000, 960, 13, 2, 12}, | 478 | { 13000000, 480000000, 960, 13, 0, 12}, |
473 | { 16800000, 480000000, 400, 7, 2, 5}, | 479 | { 16800000, 480000000, 400, 7, 0, 5}, |
474 | { 19200000, 480000000, 200, 4, 2, 3}, | 480 | { 19200000, 480000000, 200, 4, 0, 3}, |
475 | { 26000000, 480000000, 960, 26, 2, 12}, | 481 | { 26000000, 480000000, 960, 26, 0, 12}, |
476 | { 0, 0, 0, 0, 0, 0 }, | 482 | { 0, 0, 0, 0, 0, 0 }, |
477 | }; | 483 | }; |
478 | 484 | ||
479 | static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { | 485 | static struct tegra_clk_pll_freq_table pll_x_freq_table[] = { |
480 | /* 1.7 GHz */ | 486 | /* 1.7 GHz */ |
481 | { 12000000, 1700000000, 850, 6, 1, 8}, | 487 | { 12000000, 1700000000, 850, 6, 0, 8}, |
482 | { 13000000, 1700000000, 915, 7, 1, 8}, /* actual: 1699.2 MHz */ | 488 | { 13000000, 1700000000, 915, 7, 0, 8}, /* actual: 1699.2 MHz */ |
483 | { 16800000, 1700000000, 708, 7, 1, 8}, /* actual: 1699.2 MHz */ | 489 | { 16800000, 1700000000, 708, 7, 0, 8}, /* actual: 1699.2 MHz */ |
484 | { 19200000, 1700000000, 885, 10, 1, 8}, /* actual: 1699.2 MHz */ | 490 | { 19200000, 1700000000, 885, 10, 0, 8}, /* actual: 1699.2 MHz */ |
485 | { 26000000, 1700000000, 850, 13, 1, 8}, | 491 | { 26000000, 1700000000, 850, 13, 0, 8}, |
486 | 492 | ||
487 | /* 1.6 GHz */ | 493 | /* 1.6 GHz */ |
488 | { 12000000, 1600000000, 800, 6, 1, 8}, | 494 | { 12000000, 1600000000, 800, 6, 0, 8}, |
489 | { 13000000, 1600000000, 738, 6, 1, 8}, /* actual: 1599.0 MHz */ | 495 | { 13000000, 1600000000, 738, 6, 0, 8}, /* actual: 1599.0 MHz */ |
490 | { 16800000, 1600000000, 857, 9, 1, 8}, /* actual: 1599.7 MHz */ | 496 | { 16800000, 1600000000, 857, 9, 0, 8}, /* actual: 1599.7 MHz */ |
491 | { 19200000, 1600000000, 500, 6, 1, 8}, | 497 | { 19200000, 1600000000, 500, 6, 0, 8}, |
492 | { 26000000, 1600000000, 800, 13, 1, 8}, | 498 | { 26000000, 1600000000, 800, 13, 0, 8}, |
493 | 499 | ||
494 | /* 1.5 GHz */ | 500 | /* 1.5 GHz */ |
495 | { 12000000, 1500000000, 750, 6, 1, 8}, | 501 | { 12000000, 1500000000, 750, 6, 0, 8}, |
496 | { 13000000, 1500000000, 923, 8, 1, 8}, /* actual: 1499.8 MHz */ | 502 | { 13000000, 1500000000, 923, 8, 0, 8}, /* actual: 1499.8 MHz */ |
497 | { 16800000, 1500000000, 625, 7, 1, 8}, | 503 | { 16800000, 1500000000, 625, 7, 0, 8}, |
498 | { 19200000, 1500000000, 625, 8, 1, 8}, | 504 | { 19200000, 1500000000, 625, 8, 0, 8}, |
499 | { 26000000, 1500000000, 750, 13, 1, 8}, | 505 | { 26000000, 1500000000, 750, 13, 0, 8}, |
500 | 506 | ||
501 | /* 1.4 GHz */ | 507 | /* 1.4 GHz */ |
502 | { 12000000, 1400000000, 700, 6, 1, 8}, | 508 | { 12000000, 1400000000, 700, 6, 0, 8}, |
503 | { 13000000, 1400000000, 969, 9, 1, 8}, /* actual: 1399.7 MHz */ | 509 | { 13000000, 1400000000, 969, 9, 0, 8}, /* actual: 1399.7 MHz */ |
504 | { 16800000, 1400000000, 1000, 12, 1, 8}, | 510 | { 16800000, 1400000000, 1000, 12, 0, 8}, |
505 | { 19200000, 1400000000, 875, 12, 1, 8}, | 511 | { 19200000, 1400000000, 875, 12, 0, 8}, |
506 | { 26000000, 1400000000, 700, 13, 1, 8}, | 512 | { 26000000, 1400000000, 700, 13, 0, 8}, |
507 | 513 | ||
508 | /* 1.3 GHz */ | 514 | /* 1.3 GHz */ |
509 | { 12000000, 1300000000, 975, 9, 1, 8}, | 515 | { 12000000, 1300000000, 975, 9, 0, 8}, |
510 | { 13000000, 1300000000, 1000, 10, 1, 8}, | 516 | { 13000000, 1300000000, 1000, 10, 0, 8}, |
511 | { 16800000, 1300000000, 928, 12, 1, 8}, /* actual: 1299.2 MHz */ | 517 | { 16800000, 1300000000, 928, 12, 0, 8}, /* actual: 1299.2 MHz */ |
512 | { 19200000, 1300000000, 812, 12, 1, 8}, /* actual: 1299.2 MHz */ | 518 | { 19200000, 1300000000, 812, 12, 0, 8}, /* actual: 1299.2 MHz */ |
513 | { 26000000, 1300000000, 650, 13, 1, 8}, | 519 | { 26000000, 1300000000, 650, 13, 0, 8}, |
514 | 520 | ||
515 | /* 1.2 GHz */ | 521 | /* 1.2 GHz */ |
516 | { 12000000, 1200000000, 1000, 10, 1, 8}, | 522 | { 12000000, 1200000000, 1000, 10, 0, 8}, |
517 | { 13000000, 1200000000, 923, 10, 1, 8}, /* actual: 1199.9 MHz */ | 523 | { 13000000, 1200000000, 923, 10, 0, 8}, /* actual: 1199.9 MHz */ |
518 | { 16800000, 1200000000, 1000, 14, 1, 8}, | 524 | { 16800000, 1200000000, 1000, 14, 0, 8}, |
519 | { 19200000, 1200000000, 1000, 16, 1, 8}, | 525 | { 19200000, 1200000000, 1000, 16, 0, 8}, |
520 | { 26000000, 1200000000, 600, 13, 1, 8}, | 526 | { 26000000, 1200000000, 600, 13, 0, 8}, |
521 | 527 | ||
522 | /* 1.1 GHz */ | 528 | /* 1.1 GHz */ |
523 | { 12000000, 1100000000, 825, 9, 1, 8}, | 529 | { 12000000, 1100000000, 825, 9, 0, 8}, |
524 | { 13000000, 1100000000, 846, 10, 1, 8}, /* actual: 1099.8 MHz */ | 530 | { 13000000, 1100000000, 846, 10, 0, 8}, /* actual: 1099.8 MHz */ |
525 | { 16800000, 1100000000, 982, 15, 1, 8}, /* actual: 1099.8 MHz */ | 531 | { 16800000, 1100000000, 982, 15, 0, 8}, /* actual: 1099.8 MHz */ |
526 | { 19200000, 1100000000, 859, 15, 1, 8}, /* actual: 1099.5 MHz */ | 532 | { 19200000, 1100000000, 859, 15, 0, 8}, /* actual: 1099.5 MHz */ |
527 | { 26000000, 1100000000, 550, 13, 1, 8}, | 533 | { 26000000, 1100000000, 550, 13, 0, 8}, |
528 | 534 | ||
529 | /* 1 GHz */ | 535 | /* 1 GHz */ |
530 | { 12000000, 1000000000, 1000, 12, 1, 8}, | 536 | { 12000000, 1000000000, 1000, 12, 0, 8}, |
531 | { 13000000, 1000000000, 1000, 13, 1, 8}, | 537 | { 13000000, 1000000000, 1000, 13, 0, 8}, |
532 | { 16800000, 1000000000, 833, 14, 1, 8}, /* actual: 999.6 MHz */ | 538 | { 16800000, 1000000000, 833, 14, 0, 8}, /* actual: 999.6 MHz */ |
533 | { 19200000, 1000000000, 625, 12, 1, 8}, | 539 | { 19200000, 1000000000, 625, 12, 0, 8}, |
534 | { 26000000, 1000000000, 1000, 26, 1, 8}, | 540 | { 26000000, 1000000000, 1000, 26, 0, 8}, |
535 | 541 | ||
536 | { 0, 0, 0, 0, 0, 0 }, | 542 | { 0, 0, 0, 0, 0, 0 }, |
537 | }; | 543 | }; |
@@ -553,7 +559,7 @@ static struct tegra_clk_pll_params pll_c_params = { | |||
553 | .vco_max = 1400000000, | 559 | .vco_max = 1400000000, |
554 | .base_reg = PLLC_BASE, | 560 | .base_reg = PLLC_BASE, |
555 | .misc_reg = PLLC_MISC, | 561 | .misc_reg = PLLC_MISC, |
556 | .lock_bit_idx = PLL_BASE_LOCK, | 562 | .lock_mask = PLL_BASE_LOCK, |
557 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 563 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
558 | .lock_delay = 300, | 564 | .lock_delay = 300, |
559 | }; | 565 | }; |
@@ -567,7 +573,7 @@ static struct tegra_clk_pll_params pll_m_params = { | |||
567 | .vco_max = 1200000000, | 573 | .vco_max = 1200000000, |
568 | .base_reg = PLLM_BASE, | 574 | .base_reg = PLLM_BASE, |
569 | .misc_reg = PLLM_MISC, | 575 | .misc_reg = PLLM_MISC, |
570 | .lock_bit_idx = PLL_BASE_LOCK, | 576 | .lock_mask = PLL_BASE_LOCK, |
571 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 577 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
572 | .lock_delay = 300, | 578 | .lock_delay = 300, |
573 | }; | 579 | }; |
@@ -581,7 +587,7 @@ static struct tegra_clk_pll_params pll_p_params = { | |||
581 | .vco_max = 1400000000, | 587 | .vco_max = 1400000000, |
582 | .base_reg = PLLP_BASE, | 588 | .base_reg = PLLP_BASE, |
583 | .misc_reg = PLLP_MISC, | 589 | .misc_reg = PLLP_MISC, |
584 | .lock_bit_idx = PLL_BASE_LOCK, | 590 | .lock_mask = PLL_BASE_LOCK, |
585 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 591 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
586 | .lock_delay = 300, | 592 | .lock_delay = 300, |
587 | }; | 593 | }; |
@@ -595,7 +601,7 @@ static struct tegra_clk_pll_params pll_a_params = { | |||
595 | .vco_max = 1400000000, | 601 | .vco_max = 1400000000, |
596 | .base_reg = PLLA_BASE, | 602 | .base_reg = PLLA_BASE, |
597 | .misc_reg = PLLA_MISC, | 603 | .misc_reg = PLLA_MISC, |
598 | .lock_bit_idx = PLL_BASE_LOCK, | 604 | .lock_mask = PLL_BASE_LOCK, |
599 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 605 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
600 | .lock_delay = 300, | 606 | .lock_delay = 300, |
601 | }; | 607 | }; |
@@ -609,7 +615,7 @@ static struct tegra_clk_pll_params pll_d_params = { | |||
609 | .vco_max = 1000000000, | 615 | .vco_max = 1000000000, |
610 | .base_reg = PLLD_BASE, | 616 | .base_reg = PLLD_BASE, |
611 | .misc_reg = PLLD_MISC, | 617 | .misc_reg = PLLD_MISC, |
612 | .lock_bit_idx = PLL_BASE_LOCK, | 618 | .lock_mask = PLL_BASE_LOCK, |
613 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | 619 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, |
614 | .lock_delay = 1000, | 620 | .lock_delay = 1000, |
615 | }; | 621 | }; |
@@ -623,7 +629,7 @@ static struct tegra_clk_pll_params pll_d2_params = { | |||
623 | .vco_max = 1000000000, | 629 | .vco_max = 1000000000, |
624 | .base_reg = PLLD2_BASE, | 630 | .base_reg = PLLD2_BASE, |
625 | .misc_reg = PLLD2_MISC, | 631 | .misc_reg = PLLD2_MISC, |
626 | .lock_bit_idx = PLL_BASE_LOCK, | 632 | .lock_mask = PLL_BASE_LOCK, |
627 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | 633 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, |
628 | .lock_delay = 1000, | 634 | .lock_delay = 1000, |
629 | }; | 635 | }; |
@@ -637,9 +643,10 @@ static struct tegra_clk_pll_params pll_u_params = { | |||
637 | .vco_max = 960000000, | 643 | .vco_max = 960000000, |
638 | .base_reg = PLLU_BASE, | 644 | .base_reg = PLLU_BASE, |
639 | .misc_reg = PLLU_MISC, | 645 | .misc_reg = PLLU_MISC, |
640 | .lock_bit_idx = PLL_BASE_LOCK, | 646 | .lock_mask = PLL_BASE_LOCK, |
641 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, | 647 | .lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE, |
642 | .lock_delay = 1000, | 648 | .lock_delay = 1000, |
649 | .pdiv_tohw = pllu_p, | ||
643 | }; | 650 | }; |
644 | 651 | ||
645 | static struct tegra_clk_pll_params pll_x_params = { | 652 | static struct tegra_clk_pll_params pll_x_params = { |
@@ -651,7 +658,7 @@ static struct tegra_clk_pll_params pll_x_params = { | |||
651 | .vco_max = 1700000000, | 658 | .vco_max = 1700000000, |
652 | .base_reg = PLLX_BASE, | 659 | .base_reg = PLLX_BASE, |
653 | .misc_reg = PLLX_MISC, | 660 | .misc_reg = PLLX_MISC, |
654 | .lock_bit_idx = PLL_BASE_LOCK, | 661 | .lock_mask = PLL_BASE_LOCK, |
655 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, | 662 | .lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE, |
656 | .lock_delay = 300, | 663 | .lock_delay = 300, |
657 | }; | 664 | }; |
@@ -665,7 +672,7 @@ static struct tegra_clk_pll_params pll_e_params = { | |||
665 | .vco_max = 2400000000U, | 672 | .vco_max = 2400000000U, |
666 | .base_reg = PLLE_BASE, | 673 | .base_reg = PLLE_BASE, |
667 | .misc_reg = PLLE_MISC, | 674 | .misc_reg = PLLE_MISC, |
668 | .lock_bit_idx = PLLE_MISC_LOCK, | 675 | .lock_mask = PLLE_MISC_LOCK, |
669 | .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, | 676 | .lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE, |
670 | .lock_delay = 300, | 677 | .lock_delay = 300, |
671 | }; | 678 | }; |
@@ -1661,7 +1668,7 @@ static void __init tegra30_periph_clk_init(void) | |||
1661 | data = &tegra_periph_clk_list[i]; | 1668 | data = &tegra_periph_clk_list[i]; |
1662 | clk = tegra_clk_register_periph(data->name, data->parent_names, | 1669 | clk = tegra_clk_register_periph(data->name, data->parent_names, |
1663 | data->num_parents, &data->periph, | 1670 | data->num_parents, &data->periph, |
1664 | clk_base, data->offset); | 1671 | clk_base, data->offset, data->flags); |
1665 | clk_register_clkdev(clk, data->con_id, data->dev_id); | 1672 | clk_register_clkdev(clk, data->con_id, data->dev_id); |
1666 | clks[data->clk_id] = clk; | 1673 | clks[data->clk_id] = clk; |
1667 | } | 1674 | } |
@@ -1911,9 +1918,16 @@ static __initdata struct tegra_clk_init_table init_table[] = { | |||
1911 | {disp1, pll_p, 600000000, 0}, | 1918 | {disp1, pll_p, 600000000, 0}, |
1912 | {disp2, pll_p, 600000000, 0}, | 1919 | {disp2, pll_p, 600000000, 0}, |
1913 | {twd, clk_max, 0, 1}, | 1920 | {twd, clk_max, 0, 1}, |
1921 | {gr2d, pll_c, 300000000, 0}, | ||
1922 | {gr3d, pll_c, 300000000, 0}, | ||
1914 | {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */ | 1923 | {clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */ |
1915 | }; | 1924 | }; |
1916 | 1925 | ||
1926 | static void __init tegra30_clock_apply_init_table(void) | ||
1927 | { | ||
1928 | tegra_init_from_table(init_table, clks, clk_max); | ||
1929 | } | ||
1930 | |||
1917 | /* | 1931 | /* |
1918 | * Some clocks may be used by different drivers depending on the board | 1932 | * Some clocks may be used by different drivers depending on the board |
1919 | * configuration. List those here to register them twice in the clock lookup | 1933 | * configuration. List those here to register them twice in the clock lookup |
@@ -1931,7 +1945,6 @@ static struct tegra_clk_duplicate tegra_clk_duplicates[] = { | |||
1931 | TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL), | 1945 | TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL), |
1932 | TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"), | 1946 | TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"), |
1933 | TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"), | 1947 | TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"), |
1934 | TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL), | ||
1935 | TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"), | 1948 | TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"), |
1936 | TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */ | 1949 | TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */ |
1937 | }; | 1950 | }; |
@@ -1988,7 +2001,7 @@ void __init tegra30_clock_init(struct device_node *np) | |||
1988 | clk_data.clk_num = ARRAY_SIZE(clks); | 2001 | clk_data.clk_num = ARRAY_SIZE(clks); |
1989 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); | 2002 | of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); |
1990 | 2003 | ||
1991 | tegra_init_from_table(init_table, clks, clk_max); | 2004 | tegra_clk_apply_init_table = tegra30_clock_apply_init_table; |
1992 | 2005 | ||
1993 | tegra_cpu_car_ops = &tegra30_cpu_car_ops; | 2006 | tegra_cpu_car_ops = &tegra30_cpu_car_ops; |
1994 | } | 2007 | } |
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c index a603b9af0ad3..923ca7ee4694 100644 --- a/drivers/clk/tegra/clk.c +++ b/drivers/clk/tegra/clk.c | |||
@@ -22,7 +22,8 @@ | |||
22 | #include "clk.h" | 22 | #include "clk.h" |
23 | 23 | ||
24 | /* Global data of Tegra CPU CAR ops */ | 24 | /* Global data of Tegra CPU CAR ops */ |
25 | struct tegra_cpu_car_ops *tegra_cpu_car_ops; | 25 | static struct tegra_cpu_car_ops dummy_car_ops; |
26 | struct tegra_cpu_car_ops *tegra_cpu_car_ops = &dummy_car_ops; | ||
26 | 27 | ||
27 | void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, | 28 | void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list, |
28 | struct clk *clks[], int clk_max) | 29 | struct clk *clks[], int clk_max) |
@@ -76,6 +77,7 @@ void __init tegra_init_from_table(struct tegra_clk_init_table *tbl, | |||
76 | static const struct of_device_id tegra_dt_clk_match[] = { | 77 | static const struct of_device_id tegra_dt_clk_match[] = { |
77 | { .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init }, | 78 | { .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init }, |
78 | { .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init }, | 79 | { .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init }, |
80 | { .compatible = "nvidia,tegra114-car", .data = tegra114_clock_init }, | ||
79 | { } | 81 | { } |
80 | }; | 82 | }; |
81 | 83 | ||
@@ -83,3 +85,13 @@ void __init tegra_clocks_init(void) | |||
83 | { | 85 | { |
84 | of_clk_init(tegra_dt_clk_match); | 86 | of_clk_init(tegra_dt_clk_match); |
85 | } | 87 | } |
88 | |||
89 | tegra_clk_apply_init_table_func tegra_clk_apply_init_table; | ||
90 | |||
91 | void __init tegra_clocks_apply_init_table(void) | ||
92 | { | ||
93 | if (!tegra_clk_apply_init_table) | ||
94 | return; | ||
95 | |||
96 | tegra_clk_apply_init_table(); | ||
97 | } | ||
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 0744731c6229..e0565620d68e 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. | 2 | * Copyright (c) 2012, NVIDIA CORPORATION. All rights reserved. |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify it | 4 | * This program is free software; you can redistribute it and/or modify it |
@@ -117,6 +117,17 @@ struct tegra_clk_pll_freq_table { | |||
117 | }; | 117 | }; |
118 | 118 | ||
119 | /** | 119 | /** |
120 | * struct pdiv_map - map post divider to hw value | ||
121 | * | ||
122 | * @pdiv: post divider | ||
123 | * @hw_val: value to be written to the PLL hw | ||
124 | */ | ||
125 | struct pdiv_map { | ||
126 | u8 pdiv; | ||
127 | u8 hw_val; | ||
128 | }; | ||
129 | |||
130 | /** | ||
120 | * struct clk_pll_params - PLL parameters | 131 | * struct clk_pll_params - PLL parameters |
121 | * | 132 | * |
122 | * @input_min: Minimum input frequency | 133 | * @input_min: Minimum input frequency |
@@ -143,9 +154,18 @@ struct tegra_clk_pll_params { | |||
143 | u32 base_reg; | 154 | u32 base_reg; |
144 | u32 misc_reg; | 155 | u32 misc_reg; |
145 | u32 lock_reg; | 156 | u32 lock_reg; |
146 | u32 lock_bit_idx; | 157 | u32 lock_mask; |
147 | u32 lock_enable_bit_idx; | 158 | u32 lock_enable_bit_idx; |
159 | u32 iddq_reg; | ||
160 | u32 iddq_bit_idx; | ||
161 | u32 aux_reg; | ||
162 | u32 dyn_ramp_reg; | ||
163 | u32 ext_misc_reg[3]; | ||
164 | int stepa_shift; | ||
165 | int stepb_shift; | ||
148 | int lock_delay; | 166 | int lock_delay; |
167 | int max_p; | ||
168 | struct pdiv_map *pdiv_tohw; | ||
149 | }; | 169 | }; |
150 | 170 | ||
151 | /** | 171 | /** |
@@ -182,12 +202,16 @@ struct tegra_clk_pll_params { | |||
182 | * TEGRA_PLL_FIXED - We are not supposed to change output frequency | 202 | * TEGRA_PLL_FIXED - We are not supposed to change output frequency |
183 | * of some plls. | 203 | * of some plls. |
184 | * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling. | 204 | * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling. |
205 | * TEGRA_PLL_LOCK_MISC - Lock bit is in the misc register instead of the | ||
206 | * base register. | ||
207 | * TEGRA_PLL_BYPASS - PLL has bypass bit | ||
208 | * TEGRA_PLL_HAS_LOCK_ENABLE - PLL has bit to enable lock monitoring | ||
185 | */ | 209 | */ |
186 | struct tegra_clk_pll { | 210 | struct tegra_clk_pll { |
187 | struct clk_hw hw; | 211 | struct clk_hw hw; |
188 | void __iomem *clk_base; | 212 | void __iomem *clk_base; |
189 | void __iomem *pmc; | 213 | void __iomem *pmc; |
190 | u8 flags; | 214 | u32 flags; |
191 | unsigned long fixed_rate; | 215 | unsigned long fixed_rate; |
192 | spinlock_t *lock; | 216 | spinlock_t *lock; |
193 | u8 divn_shift; | 217 | u8 divn_shift; |
@@ -210,20 +234,64 @@ struct tegra_clk_pll { | |||
210 | #define TEGRA_PLLM BIT(5) | 234 | #define TEGRA_PLLM BIT(5) |
211 | #define TEGRA_PLL_FIXED BIT(6) | 235 | #define TEGRA_PLL_FIXED BIT(6) |
212 | #define TEGRA_PLLE_CONFIGURE BIT(7) | 236 | #define TEGRA_PLLE_CONFIGURE BIT(7) |
237 | #define TEGRA_PLL_LOCK_MISC BIT(8) | ||
238 | #define TEGRA_PLL_BYPASS BIT(9) | ||
239 | #define TEGRA_PLL_HAS_LOCK_ENABLE BIT(10) | ||
213 | 240 | ||
214 | extern const struct clk_ops tegra_clk_pll_ops; | 241 | extern const struct clk_ops tegra_clk_pll_ops; |
215 | extern const struct clk_ops tegra_clk_plle_ops; | 242 | extern const struct clk_ops tegra_clk_plle_ops; |
216 | struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, | 243 | struct clk *tegra_clk_register_pll(const char *name, const char *parent_name, |
217 | void __iomem *clk_base, void __iomem *pmc, | 244 | void __iomem *clk_base, void __iomem *pmc, |
218 | unsigned long flags, unsigned long fixed_rate, | 245 | unsigned long flags, unsigned long fixed_rate, |
219 | struct tegra_clk_pll_params *pll_params, u8 pll_flags, | 246 | struct tegra_clk_pll_params *pll_params, u32 pll_flags, |
220 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); | 247 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); |
248 | |||
221 | struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, | 249 | struct clk *tegra_clk_register_plle(const char *name, const char *parent_name, |
222 | void __iomem *clk_base, void __iomem *pmc, | 250 | void __iomem *clk_base, void __iomem *pmc, |
223 | unsigned long flags, unsigned long fixed_rate, | 251 | unsigned long flags, unsigned long fixed_rate, |
224 | struct tegra_clk_pll_params *pll_params, u8 pll_flags, | 252 | struct tegra_clk_pll_params *pll_params, u32 pll_flags, |
225 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); | 253 | struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock); |
226 | 254 | ||
255 | struct clk *tegra_clk_register_pllxc(const char *name, const char *parent_name, | ||
256 | void __iomem *clk_base, void __iomem *pmc, | ||
257 | unsigned long flags, unsigned long fixed_rate, | ||
258 | struct tegra_clk_pll_params *pll_params, | ||
259 | u32 pll_flags, | ||
260 | struct tegra_clk_pll_freq_table *freq_table, | ||
261 | spinlock_t *lock); | ||
262 | |||
263 | struct clk *tegra_clk_register_pllm(const char *name, const char *parent_name, | ||
264 | void __iomem *clk_base, void __iomem *pmc, | ||
265 | unsigned long flags, unsigned long fixed_rate, | ||
266 | struct tegra_clk_pll_params *pll_params, | ||
267 | u32 pll_flags, | ||
268 | struct tegra_clk_pll_freq_table *freq_table, | ||
269 | spinlock_t *lock); | ||
270 | |||
271 | struct clk *tegra_clk_register_pllc(const char *name, const char *parent_name, | ||
272 | void __iomem *clk_base, void __iomem *pmc, | ||
273 | unsigned long flags, unsigned long fixed_rate, | ||
274 | struct tegra_clk_pll_params *pll_params, | ||
275 | u32 pll_flags, | ||
276 | struct tegra_clk_pll_freq_table *freq_table, | ||
277 | spinlock_t *lock); | ||
278 | |||
279 | struct clk *tegra_clk_register_pllre(const char *name, const char *parent_name, | ||
280 | void __iomem *clk_base, void __iomem *pmc, | ||
281 | unsigned long flags, unsigned long fixed_rate, | ||
282 | struct tegra_clk_pll_params *pll_params, | ||
283 | u32 pll_flags, | ||
284 | struct tegra_clk_pll_freq_table *freq_table, | ||
285 | spinlock_t *lock, unsigned long parent_rate); | ||
286 | |||
287 | struct clk *tegra_clk_register_plle_tegra114(const char *name, | ||
288 | const char *parent_name, | ||
289 | void __iomem *clk_base, unsigned long flags, | ||
290 | unsigned long fixed_rate, | ||
291 | struct tegra_clk_pll_params *pll_params, | ||
292 | struct tegra_clk_pll_freq_table *freq_table, | ||
293 | spinlock_t *lock); | ||
294 | |||
227 | /** | 295 | /** |
228 | * struct tegra_clk_pll_out - PLL divider down clock | 296 | * struct tegra_clk_pll_out - PLL divider down clock |
229 | * | 297 | * |
@@ -290,6 +358,7 @@ struct tegra_clk_periph_regs { | |||
290 | * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the | 358 | * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the |
291 | * bus to flush the write operation in apb bus. This flag indicates | 359 | * bus to flush the write operation in apb bus. This flag indicates |
292 | * that this peripheral is in apb bus. | 360 | * that this peripheral is in apb bus. |
361 | * TEGRA_PERIPH_WAR_1005168 - Apply workaround for Tegra114 MSENC bug | ||
293 | */ | 362 | */ |
294 | struct tegra_clk_periph_gate { | 363 | struct tegra_clk_periph_gate { |
295 | u32 magic; | 364 | u32 magic; |
@@ -309,6 +378,7 @@ struct tegra_clk_periph_gate { | |||
309 | #define TEGRA_PERIPH_NO_RESET BIT(0) | 378 | #define TEGRA_PERIPH_NO_RESET BIT(0) |
310 | #define TEGRA_PERIPH_MANUAL_RESET BIT(1) | 379 | #define TEGRA_PERIPH_MANUAL_RESET BIT(1) |
311 | #define TEGRA_PERIPH_ON_APB BIT(2) | 380 | #define TEGRA_PERIPH_ON_APB BIT(2) |
381 | #define TEGRA_PERIPH_WAR_1005168 BIT(3) | ||
312 | 382 | ||
313 | void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert); | 383 | void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert); |
314 | extern const struct clk_ops tegra_clk_periph_gate_ops; | 384 | extern const struct clk_ops tegra_clk_periph_gate_ops; |
@@ -349,21 +419,22 @@ extern const struct clk_ops tegra_clk_periph_ops; | |||
349 | struct clk *tegra_clk_register_periph(const char *name, | 419 | struct clk *tegra_clk_register_periph(const char *name, |
350 | const char **parent_names, int num_parents, | 420 | const char **parent_names, int num_parents, |
351 | struct tegra_clk_periph *periph, void __iomem *clk_base, | 421 | struct tegra_clk_periph *periph, void __iomem *clk_base, |
352 | u32 offset); | 422 | u32 offset, unsigned long flags); |
353 | struct clk *tegra_clk_register_periph_nodiv(const char *name, | 423 | struct clk *tegra_clk_register_periph_nodiv(const char *name, |
354 | const char **parent_names, int num_parents, | 424 | const char **parent_names, int num_parents, |
355 | struct tegra_clk_periph *periph, void __iomem *clk_base, | 425 | struct tegra_clk_periph *periph, void __iomem *clk_base, |
356 | u32 offset); | 426 | u32 offset); |
357 | 427 | ||
358 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags, \ | 428 | #define TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, _mux_flags, \ |
359 | _div_shift, _div_width, _div_frac_width, \ | 429 | _div_shift, _div_width, _div_frac_width, \ |
360 | _div_flags, _clk_num, _enb_refcnt, _regs, \ | 430 | _div_flags, _clk_num, _enb_refcnt, _regs, \ |
361 | _gate_flags) \ | 431 | _gate_flags, _table) \ |
362 | { \ | 432 | { \ |
363 | .mux = { \ | 433 | .mux = { \ |
364 | .flags = _mux_flags, \ | 434 | .flags = _mux_flags, \ |
365 | .shift = _mux_shift, \ | 435 | .shift = _mux_shift, \ |
366 | .width = _mux_width, \ | 436 | .mask = _mux_mask, \ |
437 | .table = _table, \ | ||
367 | }, \ | 438 | }, \ |
368 | .divider = { \ | 439 | .divider = { \ |
369 | .flags = _div_flags, \ | 440 | .flags = _div_flags, \ |
@@ -391,28 +462,41 @@ struct tegra_periph_init_data { | |||
391 | u32 offset; | 462 | u32 offset; |
392 | const char *con_id; | 463 | const char *con_id; |
393 | const char *dev_id; | 464 | const char *dev_id; |
465 | unsigned long flags; | ||
394 | }; | 466 | }; |
395 | 467 | ||
396 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \ | 468 | #define TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ |
397 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | 469 | _mux_shift, _mux_mask, _mux_flags, _div_shift, \ |
398 | _div_width, _div_frac_width, _div_flags, _regs, \ | 470 | _div_width, _div_frac_width, _div_flags, _regs, \ |
399 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | 471 | _clk_num, _enb_refcnt, _gate_flags, _clk_id, _table,\ |
472 | _flags) \ | ||
400 | { \ | 473 | { \ |
401 | .name = _name, \ | 474 | .name = _name, \ |
402 | .clk_id = _clk_id, \ | 475 | .clk_id = _clk_id, \ |
403 | .parent_names = _parent_names, \ | 476 | .parent_names = _parent_names, \ |
404 | .num_parents = ARRAY_SIZE(_parent_names), \ | 477 | .num_parents = ARRAY_SIZE(_parent_names), \ |
405 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width, \ | 478 | .periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_mask, \ |
406 | _mux_flags, _div_shift, \ | 479 | _mux_flags, _div_shift, \ |
407 | _div_width, _div_frac_width, \ | 480 | _div_width, _div_frac_width, \ |
408 | _div_flags, _clk_num, \ | 481 | _div_flags, _clk_num, \ |
409 | _enb_refcnt, _regs, \ | 482 | _enb_refcnt, _regs, \ |
410 | _gate_flags), \ | 483 | _gate_flags, _table), \ |
411 | .offset = _offset, \ | 484 | .offset = _offset, \ |
412 | .con_id = _con_id, \ | 485 | .con_id = _con_id, \ |
413 | .dev_id = _dev_id, \ | 486 | .dev_id = _dev_id, \ |
487 | .flags = _flags \ | ||
414 | } | 488 | } |
415 | 489 | ||
490 | #define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
491 | _mux_shift, _mux_width, _mux_flags, _div_shift, \ | ||
492 | _div_width, _div_frac_width, _div_flags, _regs, \ | ||
493 | _clk_num, _enb_refcnt, _gate_flags, _clk_id) \ | ||
494 | TEGRA_INIT_DATA_TABLE(_name, _con_id, _dev_id, _parent_names, _offset,\ | ||
495 | _mux_shift, BIT(_mux_width) - 1, _mux_flags, \ | ||
496 | _div_shift, _div_width, _div_frac_width, _div_flags, \ | ||
497 | _regs, _clk_num, _enb_refcnt, _gate_flags, _clk_id,\ | ||
498 | NULL, 0) | ||
499 | |||
416 | /** | 500 | /** |
417 | * struct clk_super_mux - super clock | 501 | * struct clk_super_mux - super clock |
418 | * | 502 | * |
@@ -499,4 +583,13 @@ void tegra30_clock_init(struct device_node *np); | |||
499 | static inline void tegra30_clock_init(struct device_node *np) {} | 583 | static inline void tegra30_clock_init(struct device_node *np) {} |
500 | #endif /* CONFIG_ARCH_TEGRA_3x_SOC */ | 584 | #endif /* CONFIG_ARCH_TEGRA_3x_SOC */ |
501 | 585 | ||
586 | #ifdef CONFIG_ARCH_TEGRA_114_SOC | ||
587 | void tegra114_clock_init(struct device_node *np); | ||
588 | #else | ||
589 | static inline void tegra114_clock_init(struct device_node *np) {} | ||
590 | #endif /* CONFIG_ARCH_TEGRA114_SOC */ | ||
591 | |||
592 | typedef void (*tegra_clk_apply_init_table_func)(void); | ||
593 | extern tegra_clk_apply_init_table_func tegra_clk_apply_init_table; | ||
594 | |||
502 | #endif /* TEGRA_CLK_H */ | 595 | #endif /* TEGRA_CLK_H */ |
diff --git a/drivers/clk/ux500/clk-prcmu.c b/drivers/clk/ux500/clk-prcmu.c index 74faa7e3cf59..293a28854417 100644 --- a/drivers/clk/ux500/clk-prcmu.c +++ b/drivers/clk/ux500/clk-prcmu.c | |||
@@ -20,15 +20,23 @@ | |||
20 | struct clk_prcmu { | 20 | struct clk_prcmu { |
21 | struct clk_hw hw; | 21 | struct clk_hw hw; |
22 | u8 cg_sel; | 22 | u8 cg_sel; |
23 | int is_prepared; | ||
23 | int is_enabled; | 24 | int is_enabled; |
25 | int opp_requested; | ||
24 | }; | 26 | }; |
25 | 27 | ||
26 | /* PRCMU clock operations. */ | 28 | /* PRCMU clock operations. */ |
27 | 29 | ||
28 | static int clk_prcmu_prepare(struct clk_hw *hw) | 30 | static int clk_prcmu_prepare(struct clk_hw *hw) |
29 | { | 31 | { |
32 | int ret; | ||
30 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 33 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
31 | return prcmu_request_clock(clk->cg_sel, true); | 34 | |
35 | ret = prcmu_request_clock(clk->cg_sel, true); | ||
36 | if (!ret) | ||
37 | clk->is_prepared = 1; | ||
38 | |||
39 | return ret;; | ||
32 | } | 40 | } |
33 | 41 | ||
34 | static void clk_prcmu_unprepare(struct clk_hw *hw) | 42 | static void clk_prcmu_unprepare(struct clk_hw *hw) |
@@ -36,7 +44,15 @@ static void clk_prcmu_unprepare(struct clk_hw *hw) | |||
36 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 44 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
37 | if (prcmu_request_clock(clk->cg_sel, false)) | 45 | if (prcmu_request_clock(clk->cg_sel, false)) |
38 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 46 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
39 | hw->init->name); | 47 | __clk_get_name(hw->clk)); |
48 | else | ||
49 | clk->is_prepared = 0; | ||
50 | } | ||
51 | |||
52 | static int clk_prcmu_is_prepared(struct clk_hw *hw) | ||
53 | { | ||
54 | struct clk_prcmu *clk = to_clk_prcmu(hw); | ||
55 | return clk->is_prepared; | ||
40 | } | 56 | } |
41 | 57 | ||
42 | static int clk_prcmu_enable(struct clk_hw *hw) | 58 | static int clk_prcmu_enable(struct clk_hw *hw) |
@@ -79,58 +95,52 @@ static int clk_prcmu_set_rate(struct clk_hw *hw, unsigned long rate, | |||
79 | return prcmu_set_clock_rate(clk->cg_sel, rate); | 95 | return prcmu_set_clock_rate(clk->cg_sel, rate); |
80 | } | 96 | } |
81 | 97 | ||
82 | static int request_ape_opp100(bool enable) | ||
83 | { | ||
84 | static int reqs; | ||
85 | int err = 0; | ||
86 | |||
87 | if (enable) { | ||
88 | if (!reqs) | ||
89 | err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, | ||
90 | "clock", 100); | ||
91 | if (!err) | ||
92 | reqs++; | ||
93 | } else { | ||
94 | reqs--; | ||
95 | if (!reqs) | ||
96 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, | ||
97 | "clock"); | ||
98 | } | ||
99 | return err; | ||
100 | } | ||
101 | |||
102 | static int clk_prcmu_opp_prepare(struct clk_hw *hw) | 98 | static int clk_prcmu_opp_prepare(struct clk_hw *hw) |
103 | { | 99 | { |
104 | int err; | 100 | int err; |
105 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 101 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
106 | 102 | ||
107 | err = request_ape_opp100(true); | 103 | if (!clk->opp_requested) { |
108 | if (err) { | 104 | err = prcmu_qos_add_requirement(PRCMU_QOS_APE_OPP, |
109 | pr_err("clk_prcmu: %s failed to request APE OPP100 for %s.\n", | 105 | (char *)__clk_get_name(hw->clk), |
110 | __func__, hw->init->name); | 106 | 100); |
111 | return err; | 107 | if (err) { |
108 | pr_err("clk_prcmu: %s fail req APE OPP for %s.\n", | ||
109 | __func__, __clk_get_name(hw->clk)); | ||
110 | return err; | ||
111 | } | ||
112 | clk->opp_requested = 1; | ||
112 | } | 113 | } |
113 | 114 | ||
114 | err = prcmu_request_clock(clk->cg_sel, true); | 115 | err = prcmu_request_clock(clk->cg_sel, true); |
115 | if (err) | 116 | if (err) { |
116 | request_ape_opp100(false); | 117 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, |
118 | (char *)__clk_get_name(hw->clk)); | ||
119 | clk->opp_requested = 0; | ||
120 | return err; | ||
121 | } | ||
117 | 122 | ||
118 | return err; | 123 | clk->is_prepared = 1; |
124 | return 0; | ||
119 | } | 125 | } |
120 | 126 | ||
121 | static void clk_prcmu_opp_unprepare(struct clk_hw *hw) | 127 | static void clk_prcmu_opp_unprepare(struct clk_hw *hw) |
122 | { | 128 | { |
123 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 129 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
124 | 130 | ||
125 | if (prcmu_request_clock(clk->cg_sel, false)) | 131 | if (prcmu_request_clock(clk->cg_sel, false)) { |
126 | goto out_error; | 132 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
127 | if (request_ape_opp100(false)) | 133 | __clk_get_name(hw->clk)); |
128 | goto out_error; | 134 | return; |
129 | return; | 135 | } |
130 | 136 | ||
131 | out_error: | 137 | if (clk->opp_requested) { |
132 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 138 | prcmu_qos_remove_requirement(PRCMU_QOS_APE_OPP, |
133 | hw->init->name); | 139 | (char *)__clk_get_name(hw->clk)); |
140 | clk->opp_requested = 0; | ||
141 | } | ||
142 | |||
143 | clk->is_prepared = 0; | ||
134 | } | 144 | } |
135 | 145 | ||
136 | static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) | 146 | static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) |
@@ -138,38 +148,49 @@ static int clk_prcmu_opp_volt_prepare(struct clk_hw *hw) | |||
138 | int err; | 148 | int err; |
139 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 149 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
140 | 150 | ||
141 | err = prcmu_request_ape_opp_100_voltage(true); | 151 | if (!clk->opp_requested) { |
142 | if (err) { | 152 | err = prcmu_request_ape_opp_100_voltage(true); |
143 | pr_err("clk_prcmu: %s failed to request APE OPP VOLT for %s.\n", | 153 | if (err) { |
144 | __func__, hw->init->name); | 154 | pr_err("clk_prcmu: %s fail req APE OPP VOLT for %s.\n", |
145 | return err; | 155 | __func__, __clk_get_name(hw->clk)); |
156 | return err; | ||
157 | } | ||
158 | clk->opp_requested = 1; | ||
146 | } | 159 | } |
147 | 160 | ||
148 | err = prcmu_request_clock(clk->cg_sel, true); | 161 | err = prcmu_request_clock(clk->cg_sel, true); |
149 | if (err) | 162 | if (err) { |
150 | prcmu_request_ape_opp_100_voltage(false); | 163 | prcmu_request_ape_opp_100_voltage(false); |
164 | clk->opp_requested = 0; | ||
165 | return err; | ||
166 | } | ||
151 | 167 | ||
152 | return err; | 168 | clk->is_prepared = 1; |
169 | return 0; | ||
153 | } | 170 | } |
154 | 171 | ||
155 | static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) | 172 | static void clk_prcmu_opp_volt_unprepare(struct clk_hw *hw) |
156 | { | 173 | { |
157 | struct clk_prcmu *clk = to_clk_prcmu(hw); | 174 | struct clk_prcmu *clk = to_clk_prcmu(hw); |
158 | 175 | ||
159 | if (prcmu_request_clock(clk->cg_sel, false)) | 176 | if (prcmu_request_clock(clk->cg_sel, false)) { |
160 | goto out_error; | 177 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, |
161 | if (prcmu_request_ape_opp_100_voltage(false)) | 178 | __clk_get_name(hw->clk)); |
162 | goto out_error; | 179 | return; |
163 | return; | 180 | } |
164 | 181 | ||
165 | out_error: | 182 | if (clk->opp_requested) { |
166 | pr_err("clk_prcmu: %s failed to disable %s.\n", __func__, | 183 | prcmu_request_ape_opp_100_voltage(false); |
167 | hw->init->name); | 184 | clk->opp_requested = 0; |
185 | } | ||
186 | |||
187 | clk->is_prepared = 0; | ||
168 | } | 188 | } |
169 | 189 | ||
170 | static struct clk_ops clk_prcmu_scalable_ops = { | 190 | static struct clk_ops clk_prcmu_scalable_ops = { |
171 | .prepare = clk_prcmu_prepare, | 191 | .prepare = clk_prcmu_prepare, |
172 | .unprepare = clk_prcmu_unprepare, | 192 | .unprepare = clk_prcmu_unprepare, |
193 | .is_prepared = clk_prcmu_is_prepared, | ||
173 | .enable = clk_prcmu_enable, | 194 | .enable = clk_prcmu_enable, |
174 | .disable = clk_prcmu_disable, | 195 | .disable = clk_prcmu_disable, |
175 | .is_enabled = clk_prcmu_is_enabled, | 196 | .is_enabled = clk_prcmu_is_enabled, |
@@ -181,6 +202,7 @@ static struct clk_ops clk_prcmu_scalable_ops = { | |||
181 | static struct clk_ops clk_prcmu_gate_ops = { | 202 | static struct clk_ops clk_prcmu_gate_ops = { |
182 | .prepare = clk_prcmu_prepare, | 203 | .prepare = clk_prcmu_prepare, |
183 | .unprepare = clk_prcmu_unprepare, | 204 | .unprepare = clk_prcmu_unprepare, |
205 | .is_prepared = clk_prcmu_is_prepared, | ||
184 | .enable = clk_prcmu_enable, | 206 | .enable = clk_prcmu_enable, |
185 | .disable = clk_prcmu_disable, | 207 | .disable = clk_prcmu_disable, |
186 | .is_enabled = clk_prcmu_is_enabled, | 208 | .is_enabled = clk_prcmu_is_enabled, |
@@ -202,6 +224,7 @@ static struct clk_ops clk_prcmu_rate_ops = { | |||
202 | static struct clk_ops clk_prcmu_opp_gate_ops = { | 224 | static struct clk_ops clk_prcmu_opp_gate_ops = { |
203 | .prepare = clk_prcmu_opp_prepare, | 225 | .prepare = clk_prcmu_opp_prepare, |
204 | .unprepare = clk_prcmu_opp_unprepare, | 226 | .unprepare = clk_prcmu_opp_unprepare, |
227 | .is_prepared = clk_prcmu_is_prepared, | ||
205 | .enable = clk_prcmu_enable, | 228 | .enable = clk_prcmu_enable, |
206 | .disable = clk_prcmu_disable, | 229 | .disable = clk_prcmu_disable, |
207 | .is_enabled = clk_prcmu_is_enabled, | 230 | .is_enabled = clk_prcmu_is_enabled, |
@@ -211,6 +234,7 @@ static struct clk_ops clk_prcmu_opp_gate_ops = { | |||
211 | static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { | 234 | static struct clk_ops clk_prcmu_opp_volt_scalable_ops = { |
212 | .prepare = clk_prcmu_opp_volt_prepare, | 235 | .prepare = clk_prcmu_opp_volt_prepare, |
213 | .unprepare = clk_prcmu_opp_volt_unprepare, | 236 | .unprepare = clk_prcmu_opp_volt_unprepare, |
237 | .is_prepared = clk_prcmu_is_prepared, | ||
214 | .enable = clk_prcmu_enable, | 238 | .enable = clk_prcmu_enable, |
215 | .disable = clk_prcmu_disable, | 239 | .disable = clk_prcmu_disable, |
216 | .is_enabled = clk_prcmu_is_enabled, | 240 | .is_enabled = clk_prcmu_is_enabled, |
@@ -242,7 +266,9 @@ static struct clk *clk_reg_prcmu(const char *name, | |||
242 | } | 266 | } |
243 | 267 | ||
244 | clk->cg_sel = cg_sel; | 268 | clk->cg_sel = cg_sel; |
269 | clk->is_prepared = 1; | ||
245 | clk->is_enabled = 1; | 270 | clk->is_enabled = 1; |
271 | clk->opp_requested = 0; | ||
246 | /* "rate" can be used for changing the initial frequency */ | 272 | /* "rate" can be used for changing the initial frequency */ |
247 | if (rate) | 273 | if (rate) |
248 | prcmu_set_clock_rate(cg_sel, rate); | 274 | prcmu_set_clock_rate(cg_sel, rate); |
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index e507ab7df60b..3167fda9bbb3 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig | |||
@@ -31,6 +31,9 @@ config SUNXI_TIMER | |||
31 | config VT8500_TIMER | 31 | config VT8500_TIMER |
32 | bool | 32 | bool |
33 | 33 | ||
34 | config CADENCE_TTC_TIMER | ||
35 | bool | ||
36 | |||
34 | config CLKSRC_NOMADIK_MTU | 37 | config CLKSRC_NOMADIK_MTU |
35 | bool | 38 | bool |
36 | depends on (ARCH_NOMADIK || ARCH_U8500) | 39 | depends on (ARCH_NOMADIK || ARCH_U8500) |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 4d8283aec5b5..e74c8ce26bf0 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
@@ -19,6 +19,7 @@ obj-$(CONFIG_ARCH_BCM2835) += bcm2835_timer.o | |||
19 | obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o | 19 | obj-$(CONFIG_SUNXI_TIMER) += sunxi_timer.o |
20 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o | 20 | obj-$(CONFIG_ARCH_TEGRA) += tegra20_timer.o |
21 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o | 21 | obj-$(CONFIG_VT8500_TIMER) += vt8500_timer.o |
22 | obj-$(CONFIG_CADENCE_TTC_TIMER) += cadence_ttc_timer.o | ||
22 | 23 | ||
23 | obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o | 24 | obj-$(CONFIG_ARM_ARCH_TIMER) += arm_arch_timer.o |
24 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o | 25 | obj-$(CONFIG_CLKSRC_METAG_GENERIC) += metag_generic.o |
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c index 50c68fef944b..766611d29945 100644 --- a/drivers/clocksource/bcm2835_timer.c +++ b/drivers/clocksource/bcm2835_timer.c | |||
@@ -95,23 +95,13 @@ static irqreturn_t bcm2835_time_interrupt(int irq, void *dev_id) | |||
95 | } | 95 | } |
96 | } | 96 | } |
97 | 97 | ||
98 | static struct of_device_id bcm2835_time_match[] __initconst = { | 98 | static void __init bcm2835_timer_init(struct device_node *node) |
99 | { .compatible = "brcm,bcm2835-system-timer" }, | ||
100 | {} | ||
101 | }; | ||
102 | |||
103 | static void __init bcm2835_timer_init(void) | ||
104 | { | 99 | { |
105 | struct device_node *node; | ||
106 | void __iomem *base; | 100 | void __iomem *base; |
107 | u32 freq; | 101 | u32 freq; |
108 | int irq; | 102 | int irq; |
109 | struct bcm2835_timer *timer; | 103 | struct bcm2835_timer *timer; |
110 | 104 | ||
111 | node = of_find_matching_node(NULL, bcm2835_time_match); | ||
112 | if (!node) | ||
113 | panic("No bcm2835 timer node"); | ||
114 | |||
115 | base = of_iomap(node, 0); | 105 | base = of_iomap(node, 0); |
116 | if (!base) | 106 | if (!base) |
117 | panic("Can't remap registers"); | 107 | panic("Can't remap registers"); |
diff --git a/drivers/clocksource/cadence_ttc_timer.c b/drivers/clocksource/cadence_ttc_timer.c new file mode 100644 index 000000000000..685bc60e210a --- /dev/null +++ b/drivers/clocksource/cadence_ttc_timer.c | |||
@@ -0,0 +1,436 @@ | |||
1 | /* | ||
2 | * This file contains driver for the Cadence Triple Timer Counter Rev 06 | ||
3 | * | ||
4 | * Copyright (C) 2011-2013 Xilinx | ||
5 | * | ||
6 | * based on arch/mips/kernel/time.c timer driver | ||
7 | * | ||
8 | * This software is licensed under the terms of the GNU General Public | ||
9 | * License version 2, as published by the Free Software Foundation, and | ||
10 | * may be copied, distributed, and modified under those terms. | ||
11 | * | ||
12 | * This program is distributed in the hope that it will be useful, | ||
13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
15 | * GNU General Public License for more details. | ||
16 | */ | ||
17 | |||
18 | #include <linux/clk.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/clockchips.h> | ||
21 | #include <linux/of_address.h> | ||
22 | #include <linux/of_irq.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/clk-provider.h> | ||
25 | |||
26 | /* | ||
27 | * This driver configures the 2 16-bit count-up timers as follows: | ||
28 | * | ||
29 | * T1: Timer 1, clocksource for generic timekeeping | ||
30 | * T2: Timer 2, clockevent source for hrtimers | ||
31 | * T3: Timer 3, <unused> | ||
32 | * | ||
33 | * The input frequency to the timer module for emulation is 2.5MHz which is | ||
34 | * common to all the timer channels (T1, T2, and T3). With a pre-scaler of 32, | ||
35 | * the timers are clocked at 78.125KHz (12.8 us resolution). | ||
36 | |||
37 | * The input frequency to the timer module in silicon is configurable and | ||
38 | * obtained from device tree. The pre-scaler of 32 is used. | ||
39 | */ | ||
40 | |||
41 | /* | ||
42 | * Timer Register Offset Definitions of Timer 1, Increment base address by 4 | ||
43 | * and use same offsets for Timer 2 | ||
44 | */ | ||
45 | #define TTC_CLK_CNTRL_OFFSET 0x00 /* Clock Control Reg, RW */ | ||
46 | #define TTC_CNT_CNTRL_OFFSET 0x0C /* Counter Control Reg, RW */ | ||
47 | #define TTC_COUNT_VAL_OFFSET 0x18 /* Counter Value Reg, RO */ | ||
48 | #define TTC_INTR_VAL_OFFSET 0x24 /* Interval Count Reg, RW */ | ||
49 | #define TTC_ISR_OFFSET 0x54 /* Interrupt Status Reg, RO */ | ||
50 | #define TTC_IER_OFFSET 0x60 /* Interrupt Enable Reg, RW */ | ||
51 | |||
52 | #define TTC_CNT_CNTRL_DISABLE_MASK 0x1 | ||
53 | |||
54 | /* | ||
55 | * Setup the timers to use pre-scaling, using a fixed value for now that will | ||
56 | * work across most input frequency, but it may need to be more dynamic | ||
57 | */ | ||
58 | #define PRESCALE_EXPONENT 11 /* 2 ^ PRESCALE_EXPONENT = PRESCALE */ | ||
59 | #define PRESCALE 2048 /* The exponent must match this */ | ||
60 | #define CLK_CNTRL_PRESCALE ((PRESCALE_EXPONENT - 1) << 1) | ||
61 | #define CLK_CNTRL_PRESCALE_EN 1 | ||
62 | #define CNT_CNTRL_RESET (1 << 4) | ||
63 | |||
64 | /** | ||
65 | * struct ttc_timer - This definition defines local timer structure | ||
66 | * | ||
67 | * @base_addr: Base address of timer | ||
68 | * @clk: Associated clock source | ||
69 | * @clk_rate_change_nb Notifier block for clock rate changes | ||
70 | */ | ||
71 | struct ttc_timer { | ||
72 | void __iomem *base_addr; | ||
73 | struct clk *clk; | ||
74 | struct notifier_block clk_rate_change_nb; | ||
75 | }; | ||
76 | |||
77 | #define to_ttc_timer(x) \ | ||
78 | container_of(x, struct ttc_timer, clk_rate_change_nb) | ||
79 | |||
80 | struct ttc_timer_clocksource { | ||
81 | struct ttc_timer ttc; | ||
82 | struct clocksource cs; | ||
83 | }; | ||
84 | |||
85 | #define to_ttc_timer_clksrc(x) \ | ||
86 | container_of(x, struct ttc_timer_clocksource, cs) | ||
87 | |||
88 | struct ttc_timer_clockevent { | ||
89 | struct ttc_timer ttc; | ||
90 | struct clock_event_device ce; | ||
91 | }; | ||
92 | |||
93 | #define to_ttc_timer_clkevent(x) \ | ||
94 | container_of(x, struct ttc_timer_clockevent, ce) | ||
95 | |||
96 | /** | ||
97 | * ttc_set_interval - Set the timer interval value | ||
98 | * | ||
99 | * @timer: Pointer to the timer instance | ||
100 | * @cycles: Timer interval ticks | ||
101 | **/ | ||
102 | static void ttc_set_interval(struct ttc_timer *timer, | ||
103 | unsigned long cycles) | ||
104 | { | ||
105 | u32 ctrl_reg; | ||
106 | |||
107 | /* Disable the counter, set the counter value and re-enable counter */ | ||
108 | ctrl_reg = __raw_readl(timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
109 | ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; | ||
110 | __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
111 | |||
112 | __raw_writel(cycles, timer->base_addr + TTC_INTR_VAL_OFFSET); | ||
113 | |||
114 | /* | ||
115 | * Reset the counter (0x10) so that it starts from 0, one-shot | ||
116 | * mode makes this needed for timing to be right. | ||
117 | */ | ||
118 | ctrl_reg |= CNT_CNTRL_RESET; | ||
119 | ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; | ||
120 | __raw_writel(ctrl_reg, timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * ttc_clock_event_interrupt - Clock event timer interrupt handler | ||
125 | * | ||
126 | * @irq: IRQ number of the Timer | ||
127 | * @dev_id: void pointer to the ttc_timer instance | ||
128 | * | ||
129 | * returns: Always IRQ_HANDLED - success | ||
130 | **/ | ||
131 | static irqreturn_t ttc_clock_event_interrupt(int irq, void *dev_id) | ||
132 | { | ||
133 | struct ttc_timer_clockevent *ttce = dev_id; | ||
134 | struct ttc_timer *timer = &ttce->ttc; | ||
135 | |||
136 | /* Acknowledge the interrupt and call event handler */ | ||
137 | __raw_readl(timer->base_addr + TTC_ISR_OFFSET); | ||
138 | |||
139 | ttce->ce.event_handler(&ttce->ce); | ||
140 | |||
141 | return IRQ_HANDLED; | ||
142 | } | ||
143 | |||
144 | /** | ||
145 | * __ttc_clocksource_read - Reads the timer counter register | ||
146 | * | ||
147 | * returns: Current timer counter register value | ||
148 | **/ | ||
149 | static cycle_t __ttc_clocksource_read(struct clocksource *cs) | ||
150 | { | ||
151 | struct ttc_timer *timer = &to_ttc_timer_clksrc(cs)->ttc; | ||
152 | |||
153 | return (cycle_t)__raw_readl(timer->base_addr + | ||
154 | TTC_COUNT_VAL_OFFSET); | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * ttc_set_next_event - Sets the time interval for next event | ||
159 | * | ||
160 | * @cycles: Timer interval ticks | ||
161 | * @evt: Address of clock event instance | ||
162 | * | ||
163 | * returns: Always 0 - success | ||
164 | **/ | ||
165 | static int ttc_set_next_event(unsigned long cycles, | ||
166 | struct clock_event_device *evt) | ||
167 | { | ||
168 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); | ||
169 | struct ttc_timer *timer = &ttce->ttc; | ||
170 | |||
171 | ttc_set_interval(timer, cycles); | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | /** | ||
176 | * ttc_set_mode - Sets the mode of timer | ||
177 | * | ||
178 | * @mode: Mode to be set | ||
179 | * @evt: Address of clock event instance | ||
180 | **/ | ||
181 | static void ttc_set_mode(enum clock_event_mode mode, | ||
182 | struct clock_event_device *evt) | ||
183 | { | ||
184 | struct ttc_timer_clockevent *ttce = to_ttc_timer_clkevent(evt); | ||
185 | struct ttc_timer *timer = &ttce->ttc; | ||
186 | u32 ctrl_reg; | ||
187 | |||
188 | switch (mode) { | ||
189 | case CLOCK_EVT_MODE_PERIODIC: | ||
190 | ttc_set_interval(timer, | ||
191 | DIV_ROUND_CLOSEST(clk_get_rate(ttce->ttc.clk), | ||
192 | PRESCALE * HZ)); | ||
193 | break; | ||
194 | case CLOCK_EVT_MODE_ONESHOT: | ||
195 | case CLOCK_EVT_MODE_UNUSED: | ||
196 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
197 | ctrl_reg = __raw_readl(timer->base_addr + | ||
198 | TTC_CNT_CNTRL_OFFSET); | ||
199 | ctrl_reg |= TTC_CNT_CNTRL_DISABLE_MASK; | ||
200 | __raw_writel(ctrl_reg, | ||
201 | timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
202 | break; | ||
203 | case CLOCK_EVT_MODE_RESUME: | ||
204 | ctrl_reg = __raw_readl(timer->base_addr + | ||
205 | TTC_CNT_CNTRL_OFFSET); | ||
206 | ctrl_reg &= ~TTC_CNT_CNTRL_DISABLE_MASK; | ||
207 | __raw_writel(ctrl_reg, | ||
208 | timer->base_addr + TTC_CNT_CNTRL_OFFSET); | ||
209 | break; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static int ttc_rate_change_clocksource_cb(struct notifier_block *nb, | ||
214 | unsigned long event, void *data) | ||
215 | { | ||
216 | struct clk_notifier_data *ndata = data; | ||
217 | struct ttc_timer *ttc = to_ttc_timer(nb); | ||
218 | struct ttc_timer_clocksource *ttccs = container_of(ttc, | ||
219 | struct ttc_timer_clocksource, ttc); | ||
220 | |||
221 | switch (event) { | ||
222 | case POST_RATE_CHANGE: | ||
223 | /* | ||
224 | * Do whatever is necessary to maintain a proper time base | ||
225 | * | ||
226 | * I cannot find a way to adjust the currently used clocksource | ||
227 | * to the new frequency. __clocksource_updatefreq_hz() sounds | ||
228 | * good, but does not work. Not sure what's that missing. | ||
229 | * | ||
230 | * This approach works, but triggers two clocksource switches. | ||
231 | * The first after unregister to clocksource jiffies. And | ||
232 | * another one after the register to the newly registered timer. | ||
233 | * | ||
234 | * Alternatively we could 'waste' another HW timer to ping pong | ||
235 | * between clock sources. That would also use one register and | ||
236 | * one unregister call, but only trigger one clocksource switch | ||
237 | * for the cost of another HW timer used by the OS. | ||
238 | */ | ||
239 | clocksource_unregister(&ttccs->cs); | ||
240 | clocksource_register_hz(&ttccs->cs, | ||
241 | ndata->new_rate / PRESCALE); | ||
242 | /* fall through */ | ||
243 | case PRE_RATE_CHANGE: | ||
244 | case ABORT_RATE_CHANGE: | ||
245 | default: | ||
246 | return NOTIFY_DONE; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | static void __init ttc_setup_clocksource(struct clk *clk, void __iomem *base) | ||
251 | { | ||
252 | struct ttc_timer_clocksource *ttccs; | ||
253 | int err; | ||
254 | |||
255 | ttccs = kzalloc(sizeof(*ttccs), GFP_KERNEL); | ||
256 | if (WARN_ON(!ttccs)) | ||
257 | return; | ||
258 | |||
259 | ttccs->ttc.clk = clk; | ||
260 | |||
261 | err = clk_prepare_enable(ttccs->ttc.clk); | ||
262 | if (WARN_ON(err)) { | ||
263 | kfree(ttccs); | ||
264 | return; | ||
265 | } | ||
266 | |||
267 | ttccs->ttc.clk_rate_change_nb.notifier_call = | ||
268 | ttc_rate_change_clocksource_cb; | ||
269 | ttccs->ttc.clk_rate_change_nb.next = NULL; | ||
270 | if (clk_notifier_register(ttccs->ttc.clk, | ||
271 | &ttccs->ttc.clk_rate_change_nb)) | ||
272 | pr_warn("Unable to register clock notifier.\n"); | ||
273 | |||
274 | ttccs->ttc.base_addr = base; | ||
275 | ttccs->cs.name = "ttc_clocksource"; | ||
276 | ttccs->cs.rating = 200; | ||
277 | ttccs->cs.read = __ttc_clocksource_read; | ||
278 | ttccs->cs.mask = CLOCKSOURCE_MASK(16); | ||
279 | ttccs->cs.flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
280 | |||
281 | /* | ||
282 | * Setup the clock source counter to be an incrementing counter | ||
283 | * with no interrupt and it rolls over at 0xFFFF. Pre-scale | ||
284 | * it by 32 also. Let it start running now. | ||
285 | */ | ||
286 | __raw_writel(0x0, ttccs->ttc.base_addr + TTC_IER_OFFSET); | ||
287 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | ||
288 | ttccs->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); | ||
289 | __raw_writel(CNT_CNTRL_RESET, | ||
290 | ttccs->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); | ||
291 | |||
292 | err = clocksource_register_hz(&ttccs->cs, | ||
293 | clk_get_rate(ttccs->ttc.clk) / PRESCALE); | ||
294 | if (WARN_ON(err)) { | ||
295 | kfree(ttccs); | ||
296 | return; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | static int ttc_rate_change_clockevent_cb(struct notifier_block *nb, | ||
301 | unsigned long event, void *data) | ||
302 | { | ||
303 | struct clk_notifier_data *ndata = data; | ||
304 | struct ttc_timer *ttc = to_ttc_timer(nb); | ||
305 | struct ttc_timer_clockevent *ttcce = container_of(ttc, | ||
306 | struct ttc_timer_clockevent, ttc); | ||
307 | |||
308 | switch (event) { | ||
309 | case POST_RATE_CHANGE: | ||
310 | { | ||
311 | unsigned long flags; | ||
312 | |||
313 | /* | ||
314 | * clockevents_update_freq should be called with IRQ disabled on | ||
315 | * the CPU the timer provides events for. The timer we use is | ||
316 | * common to both CPUs, not sure if we need to run on both | ||
317 | * cores. | ||
318 | */ | ||
319 | local_irq_save(flags); | ||
320 | clockevents_update_freq(&ttcce->ce, | ||
321 | ndata->new_rate / PRESCALE); | ||
322 | local_irq_restore(flags); | ||
323 | |||
324 | /* fall through */ | ||
325 | } | ||
326 | case PRE_RATE_CHANGE: | ||
327 | case ABORT_RATE_CHANGE: | ||
328 | default: | ||
329 | return NOTIFY_DONE; | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static void __init ttc_setup_clockevent(struct clk *clk, | ||
334 | void __iomem *base, u32 irq) | ||
335 | { | ||
336 | struct ttc_timer_clockevent *ttcce; | ||
337 | int err; | ||
338 | |||
339 | ttcce = kzalloc(sizeof(*ttcce), GFP_KERNEL); | ||
340 | if (WARN_ON(!ttcce)) | ||
341 | return; | ||
342 | |||
343 | ttcce->ttc.clk = clk; | ||
344 | |||
345 | err = clk_prepare_enable(ttcce->ttc.clk); | ||
346 | if (WARN_ON(err)) { | ||
347 | kfree(ttcce); | ||
348 | return; | ||
349 | } | ||
350 | |||
351 | ttcce->ttc.clk_rate_change_nb.notifier_call = | ||
352 | ttc_rate_change_clockevent_cb; | ||
353 | ttcce->ttc.clk_rate_change_nb.next = NULL; | ||
354 | if (clk_notifier_register(ttcce->ttc.clk, | ||
355 | &ttcce->ttc.clk_rate_change_nb)) | ||
356 | pr_warn("Unable to register clock notifier.\n"); | ||
357 | |||
358 | ttcce->ttc.base_addr = base; | ||
359 | ttcce->ce.name = "ttc_clockevent"; | ||
360 | ttcce->ce.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; | ||
361 | ttcce->ce.set_next_event = ttc_set_next_event; | ||
362 | ttcce->ce.set_mode = ttc_set_mode; | ||
363 | ttcce->ce.rating = 200; | ||
364 | ttcce->ce.irq = irq; | ||
365 | ttcce->ce.cpumask = cpu_possible_mask; | ||
366 | |||
367 | /* | ||
368 | * Setup the clock event timer to be an interval timer which | ||
369 | * is prescaled by 32 using the interval interrupt. Leave it | ||
370 | * disabled for now. | ||
371 | */ | ||
372 | __raw_writel(0x23, ttcce->ttc.base_addr + TTC_CNT_CNTRL_OFFSET); | ||
373 | __raw_writel(CLK_CNTRL_PRESCALE | CLK_CNTRL_PRESCALE_EN, | ||
374 | ttcce->ttc.base_addr + TTC_CLK_CNTRL_OFFSET); | ||
375 | __raw_writel(0x1, ttcce->ttc.base_addr + TTC_IER_OFFSET); | ||
376 | |||
377 | err = request_irq(irq, ttc_clock_event_interrupt, | ||
378 | IRQF_DISABLED | IRQF_TIMER, | ||
379 | ttcce->ce.name, ttcce); | ||
380 | if (WARN_ON(err)) { | ||
381 | kfree(ttcce); | ||
382 | return; | ||
383 | } | ||
384 | |||
385 | clockevents_config_and_register(&ttcce->ce, | ||
386 | clk_get_rate(ttcce->ttc.clk) / PRESCALE, 1, 0xfffe); | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * ttc_timer_init - Initialize the timer | ||
391 | * | ||
392 | * Initializes the timer hardware and register the clock source and clock event | ||
393 | * timers with Linux kernal timer framework | ||
394 | */ | ||
395 | static void __init ttc_timer_init(struct device_node *timer) | ||
396 | { | ||
397 | unsigned int irq; | ||
398 | void __iomem *timer_baseaddr; | ||
399 | struct clk *clk; | ||
400 | static int initialized; | ||
401 | |||
402 | if (initialized) | ||
403 | return; | ||
404 | |||
405 | initialized = 1; | ||
406 | |||
407 | /* | ||
408 | * Get the 1st Triple Timer Counter (TTC) block from the device tree | ||
409 | * and use it. Note that the event timer uses the interrupt and it's the | ||
410 | * 2nd TTC hence the irq_of_parse_and_map(,1) | ||
411 | */ | ||
412 | timer_baseaddr = of_iomap(timer, 0); | ||
413 | if (!timer_baseaddr) { | ||
414 | pr_err("ERROR: invalid timer base address\n"); | ||
415 | BUG(); | ||
416 | } | ||
417 | |||
418 | irq = irq_of_parse_and_map(timer, 1); | ||
419 | if (irq <= 0) { | ||
420 | pr_err("ERROR: invalid interrupt number\n"); | ||
421 | BUG(); | ||
422 | } | ||
423 | |||
424 | clk = of_clk_get_by_name(timer, "cpu_1x"); | ||
425 | if (IS_ERR(clk)) { | ||
426 | pr_err("ERROR: timer input clock not found\n"); | ||
427 | BUG(); | ||
428 | } | ||
429 | |||
430 | ttc_setup_clocksource(clk, timer_baseaddr); | ||
431 | ttc_setup_clockevent(clk, timer_baseaddr + 4, irq); | ||
432 | |||
433 | pr_info("%s #0 at %p, irq=%d\n", timer->name, timer_baseaddr, irq); | ||
434 | } | ||
435 | |||
436 | CLOCKSOURCE_OF_DECLARE(ttc, "cdns,ttc", ttc_timer_init); | ||
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c index bdabdaa8d00f..37f5325bec95 100644 --- a/drivers/clocksource/clksrc-of.c +++ b/drivers/clocksource/clksrc-of.c | |||
@@ -16,6 +16,7 @@ | |||
16 | 16 | ||
17 | #include <linux/init.h> | 17 | #include <linux/init.h> |
18 | #include <linux/of.h> | 18 | #include <linux/of.h> |
19 | #include <linux/clocksource.h> | ||
19 | 20 | ||
20 | extern struct of_device_id __clksrc_of_table[]; | 21 | extern struct of_device_id __clksrc_of_table[]; |
21 | 22 | ||
@@ -26,10 +27,10 @@ void __init clocksource_of_init(void) | |||
26 | { | 27 | { |
27 | struct device_node *np; | 28 | struct device_node *np; |
28 | const struct of_device_id *match; | 29 | const struct of_device_id *match; |
29 | void (*init_func)(void); | 30 | clocksource_of_init_fn init_func; |
30 | 31 | ||
31 | for_each_matching_node_and_match(np, __clksrc_of_table, &match) { | 32 | for_each_matching_node_and_match(np, __clksrc_of_table, &match) { |
32 | init_func = match->data; | 33 | init_func = match->data; |
33 | init_func(); | 34 | init_func(np); |
34 | } | 35 | } |
35 | } | 36 | } |
diff --git a/drivers/clocksource/em_sti.c b/drivers/clocksource/em_sti.c index e6a553cb73e8..4329a29a5310 100644 --- a/drivers/clocksource/em_sti.c +++ b/drivers/clocksource/em_sti.c | |||
@@ -399,7 +399,18 @@ static struct platform_driver em_sti_device_driver = { | |||
399 | } | 399 | } |
400 | }; | 400 | }; |
401 | 401 | ||
402 | module_platform_driver(em_sti_device_driver); | 402 | static int __init em_sti_init(void) |
403 | { | ||
404 | return platform_driver_register(&em_sti_device_driver); | ||
405 | } | ||
406 | |||
407 | static void __exit em_sti_exit(void) | ||
408 | { | ||
409 | platform_driver_unregister(&em_sti_device_driver); | ||
410 | } | ||
411 | |||
412 | subsys_initcall(em_sti_init); | ||
413 | module_exit(em_sti_exit); | ||
403 | 414 | ||
404 | MODULE_AUTHOR("Magnus Damm"); | 415 | MODULE_AUTHOR("Magnus Damm"); |
405 | MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); | 416 | MODULE_DESCRIPTION("Renesas Emma Mobile STI Timer Driver"); |
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 488c14cc8dbf..08d0c418c94a 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
@@ -54,62 +54,100 @@ struct sh_cmt_priv { | |||
54 | struct clocksource cs; | 54 | struct clocksource cs; |
55 | unsigned long total_cycles; | 55 | unsigned long total_cycles; |
56 | bool cs_enabled; | 56 | bool cs_enabled; |
57 | |||
58 | /* callbacks for CMSTR and CMCSR access */ | ||
59 | unsigned long (*read_control)(void __iomem *base, unsigned long offs); | ||
60 | void (*write_control)(void __iomem *base, unsigned long offs, | ||
61 | unsigned long value); | ||
62 | |||
63 | /* callbacks for CMCNT and CMCOR access */ | ||
64 | unsigned long (*read_count)(void __iomem *base, unsigned long offs); | ||
65 | void (*write_count)(void __iomem *base, unsigned long offs, | ||
66 | unsigned long value); | ||
57 | }; | 67 | }; |
58 | 68 | ||
59 | static DEFINE_RAW_SPINLOCK(sh_cmt_lock); | 69 | /* Examples of supported CMT timer register layouts and I/O access widths: |
70 | * | ||
71 | * "16-bit counter and 16-bit control" as found on sh7263: | ||
72 | * CMSTR 0xfffec000 16-bit | ||
73 | * CMCSR 0xfffec002 16-bit | ||
74 | * CMCNT 0xfffec004 16-bit | ||
75 | * CMCOR 0xfffec006 16-bit | ||
76 | * | ||
77 | * "32-bit counter and 16-bit control" as found on sh7372, sh73a0, r8a7740: | ||
78 | * CMSTR 0xffca0000 16-bit | ||
79 | * CMCSR 0xffca0060 16-bit | ||
80 | * CMCNT 0xffca0064 32-bit | ||
81 | * CMCOR 0xffca0068 32-bit | ||
82 | */ | ||
83 | |||
84 | static unsigned long sh_cmt_read16(void __iomem *base, unsigned long offs) | ||
85 | { | ||
86 | return ioread16(base + (offs << 1)); | ||
87 | } | ||
88 | |||
89 | static unsigned long sh_cmt_read32(void __iomem *base, unsigned long offs) | ||
90 | { | ||
91 | return ioread32(base + (offs << 2)); | ||
92 | } | ||
93 | |||
94 | static void sh_cmt_write16(void __iomem *base, unsigned long offs, | ||
95 | unsigned long value) | ||
96 | { | ||
97 | iowrite16(value, base + (offs << 1)); | ||
98 | } | ||
99 | |||
100 | static void sh_cmt_write32(void __iomem *base, unsigned long offs, | ||
101 | unsigned long value) | ||
102 | { | ||
103 | iowrite32(value, base + (offs << 2)); | ||
104 | } | ||
60 | 105 | ||
61 | #define CMSTR -1 /* shared register */ | ||
62 | #define CMCSR 0 /* channel register */ | 106 | #define CMCSR 0 /* channel register */ |
63 | #define CMCNT 1 /* channel register */ | 107 | #define CMCNT 1 /* channel register */ |
64 | #define CMCOR 2 /* channel register */ | 108 | #define CMCOR 2 /* channel register */ |
65 | 109 | ||
66 | static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr) | 110 | static inline unsigned long sh_cmt_read_cmstr(struct sh_cmt_priv *p) |
67 | { | 111 | { |
68 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | 112 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
69 | void __iomem *base = p->mapbase; | ||
70 | unsigned long offs; | ||
71 | |||
72 | if (reg_nr == CMSTR) { | ||
73 | offs = 0; | ||
74 | base -= cfg->channel_offset; | ||
75 | } else | ||
76 | offs = reg_nr; | ||
77 | |||
78 | if (p->width == 16) | ||
79 | offs <<= 1; | ||
80 | else { | ||
81 | offs <<= 2; | ||
82 | if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) | ||
83 | return ioread32(base + offs); | ||
84 | } | ||
85 | 113 | ||
86 | return ioread16(base + offs); | 114 | return p->read_control(p->mapbase - cfg->channel_offset, 0); |
87 | } | 115 | } |
88 | 116 | ||
89 | static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr, | 117 | static inline unsigned long sh_cmt_read_cmcsr(struct sh_cmt_priv *p) |
90 | unsigned long value) | 118 | { |
119 | return p->read_control(p->mapbase, CMCSR); | ||
120 | } | ||
121 | |||
122 | static inline unsigned long sh_cmt_read_cmcnt(struct sh_cmt_priv *p) | ||
123 | { | ||
124 | return p->read_count(p->mapbase, CMCNT); | ||
125 | } | ||
126 | |||
127 | static inline void sh_cmt_write_cmstr(struct sh_cmt_priv *p, | ||
128 | unsigned long value) | ||
91 | { | 129 | { |
92 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | 130 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
93 | void __iomem *base = p->mapbase; | ||
94 | unsigned long offs; | ||
95 | |||
96 | if (reg_nr == CMSTR) { | ||
97 | offs = 0; | ||
98 | base -= cfg->channel_offset; | ||
99 | } else | ||
100 | offs = reg_nr; | ||
101 | |||
102 | if (p->width == 16) | ||
103 | offs <<= 1; | ||
104 | else { | ||
105 | offs <<= 2; | ||
106 | if ((reg_nr == CMCNT) || (reg_nr == CMCOR)) { | ||
107 | iowrite32(value, base + offs); | ||
108 | return; | ||
109 | } | ||
110 | } | ||
111 | 131 | ||
112 | iowrite16(value, base + offs); | 132 | p->write_control(p->mapbase - cfg->channel_offset, 0, value); |
133 | } | ||
134 | |||
135 | static inline void sh_cmt_write_cmcsr(struct sh_cmt_priv *p, | ||
136 | unsigned long value) | ||
137 | { | ||
138 | p->write_control(p->mapbase, CMCSR, value); | ||
139 | } | ||
140 | |||
141 | static inline void sh_cmt_write_cmcnt(struct sh_cmt_priv *p, | ||
142 | unsigned long value) | ||
143 | { | ||
144 | p->write_count(p->mapbase, CMCNT, value); | ||
145 | } | ||
146 | |||
147 | static inline void sh_cmt_write_cmcor(struct sh_cmt_priv *p, | ||
148 | unsigned long value) | ||
149 | { | ||
150 | p->write_count(p->mapbase, CMCOR, value); | ||
113 | } | 151 | } |
114 | 152 | ||
115 | static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, | 153 | static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, |
@@ -118,15 +156,15 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, | |||
118 | unsigned long v1, v2, v3; | 156 | unsigned long v1, v2, v3; |
119 | int o1, o2; | 157 | int o1, o2; |
120 | 158 | ||
121 | o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit; | 159 | o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit; |
122 | 160 | ||
123 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ | 161 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ |
124 | do { | 162 | do { |
125 | o2 = o1; | 163 | o2 = o1; |
126 | v1 = sh_cmt_read(p, CMCNT); | 164 | v1 = sh_cmt_read_cmcnt(p); |
127 | v2 = sh_cmt_read(p, CMCNT); | 165 | v2 = sh_cmt_read_cmcnt(p); |
128 | v3 = sh_cmt_read(p, CMCNT); | 166 | v3 = sh_cmt_read_cmcnt(p); |
129 | o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit; | 167 | o1 = sh_cmt_read_cmcsr(p) & p->overflow_bit; |
130 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) | 168 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) |
131 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); | 169 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); |
132 | 170 | ||
@@ -134,6 +172,7 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, | |||
134 | return v2; | 172 | return v2; |
135 | } | 173 | } |
136 | 174 | ||
175 | static DEFINE_RAW_SPINLOCK(sh_cmt_lock); | ||
137 | 176 | ||
138 | static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | 177 | static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) |
139 | { | 178 | { |
@@ -142,14 +181,14 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | |||
142 | 181 | ||
143 | /* start stop register shared by multiple timer channels */ | 182 | /* start stop register shared by multiple timer channels */ |
144 | raw_spin_lock_irqsave(&sh_cmt_lock, flags); | 183 | raw_spin_lock_irqsave(&sh_cmt_lock, flags); |
145 | value = sh_cmt_read(p, CMSTR); | 184 | value = sh_cmt_read_cmstr(p); |
146 | 185 | ||
147 | if (start) | 186 | if (start) |
148 | value |= 1 << cfg->timer_bit; | 187 | value |= 1 << cfg->timer_bit; |
149 | else | 188 | else |
150 | value &= ~(1 << cfg->timer_bit); | 189 | value &= ~(1 << cfg->timer_bit); |
151 | 190 | ||
152 | sh_cmt_write(p, CMSTR, value); | 191 | sh_cmt_write_cmstr(p, value); |
153 | raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); | 192 | raw_spin_unlock_irqrestore(&sh_cmt_lock, flags); |
154 | } | 193 | } |
155 | 194 | ||
@@ -173,14 +212,14 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | |||
173 | /* configure channel, periodic mode and maximum timeout */ | 212 | /* configure channel, periodic mode and maximum timeout */ |
174 | if (p->width == 16) { | 213 | if (p->width == 16) { |
175 | *rate = clk_get_rate(p->clk) / 512; | 214 | *rate = clk_get_rate(p->clk) / 512; |
176 | sh_cmt_write(p, CMCSR, 0x43); | 215 | sh_cmt_write_cmcsr(p, 0x43); |
177 | } else { | 216 | } else { |
178 | *rate = clk_get_rate(p->clk) / 8; | 217 | *rate = clk_get_rate(p->clk) / 8; |
179 | sh_cmt_write(p, CMCSR, 0x01a4); | 218 | sh_cmt_write_cmcsr(p, 0x01a4); |
180 | } | 219 | } |
181 | 220 | ||
182 | sh_cmt_write(p, CMCOR, 0xffffffff); | 221 | sh_cmt_write_cmcor(p, 0xffffffff); |
183 | sh_cmt_write(p, CMCNT, 0); | 222 | sh_cmt_write_cmcnt(p, 0); |
184 | 223 | ||
185 | /* | 224 | /* |
186 | * According to the sh73a0 user's manual, as CMCNT can be operated | 225 | * According to the sh73a0 user's manual, as CMCNT can be operated |
@@ -194,12 +233,12 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | |||
194 | * take RCLKx2 at maximum. | 233 | * take RCLKx2 at maximum. |
195 | */ | 234 | */ |
196 | for (k = 0; k < 100; k++) { | 235 | for (k = 0; k < 100; k++) { |
197 | if (!sh_cmt_read(p, CMCNT)) | 236 | if (!sh_cmt_read_cmcnt(p)) |
198 | break; | 237 | break; |
199 | udelay(1); | 238 | udelay(1); |
200 | } | 239 | } |
201 | 240 | ||
202 | if (sh_cmt_read(p, CMCNT)) { | 241 | if (sh_cmt_read_cmcnt(p)) { |
203 | dev_err(&p->pdev->dev, "cannot clear CMCNT\n"); | 242 | dev_err(&p->pdev->dev, "cannot clear CMCNT\n"); |
204 | ret = -ETIMEDOUT; | 243 | ret = -ETIMEDOUT; |
205 | goto err1; | 244 | goto err1; |
@@ -222,7 +261,7 @@ static void sh_cmt_disable(struct sh_cmt_priv *p) | |||
222 | sh_cmt_start_stop_ch(p, 0); | 261 | sh_cmt_start_stop_ch(p, 0); |
223 | 262 | ||
224 | /* disable interrupts in CMT block */ | 263 | /* disable interrupts in CMT block */ |
225 | sh_cmt_write(p, CMCSR, 0); | 264 | sh_cmt_write_cmcsr(p, 0); |
226 | 265 | ||
227 | /* stop clock */ | 266 | /* stop clock */ |
228 | clk_disable(p->clk); | 267 | clk_disable(p->clk); |
@@ -270,7 +309,7 @@ static void sh_cmt_clock_event_program_verify(struct sh_cmt_priv *p, | |||
270 | if (new_match > p->max_match_value) | 309 | if (new_match > p->max_match_value) |
271 | new_match = p->max_match_value; | 310 | new_match = p->max_match_value; |
272 | 311 | ||
273 | sh_cmt_write(p, CMCOR, new_match); | 312 | sh_cmt_write_cmcor(p, new_match); |
274 | 313 | ||
275 | now = sh_cmt_get_counter(p, &has_wrapped); | 314 | now = sh_cmt_get_counter(p, &has_wrapped); |
276 | if (has_wrapped && (new_match > p->match_value)) { | 315 | if (has_wrapped && (new_match > p->match_value)) { |
@@ -346,7 +385,7 @@ static irqreturn_t sh_cmt_interrupt(int irq, void *dev_id) | |||
346 | struct sh_cmt_priv *p = dev_id; | 385 | struct sh_cmt_priv *p = dev_id; |
347 | 386 | ||
348 | /* clear flags */ | 387 | /* clear flags */ |
349 | sh_cmt_write(p, CMCSR, sh_cmt_read(p, CMCSR) & p->clear_bits); | 388 | sh_cmt_write_cmcsr(p, sh_cmt_read_cmcsr(p) & p->clear_bits); |
350 | 389 | ||
351 | /* update clock source counter to begin with if enabled | 390 | /* update clock source counter to begin with if enabled |
352 | * the wrap flag should be cleared by the timer specific | 391 | * the wrap flag should be cleared by the timer specific |
@@ -625,14 +664,6 @@ static int sh_cmt_register(struct sh_cmt_priv *p, char *name, | |||
625 | unsigned long clockevent_rating, | 664 | unsigned long clockevent_rating, |
626 | unsigned long clocksource_rating) | 665 | unsigned long clocksource_rating) |
627 | { | 666 | { |
628 | if (p->width == (sizeof(p->max_match_value) * 8)) | ||
629 | p->max_match_value = ~0; | ||
630 | else | ||
631 | p->max_match_value = (1 << p->width) - 1; | ||
632 | |||
633 | p->match_value = p->max_match_value; | ||
634 | raw_spin_lock_init(&p->lock); | ||
635 | |||
636 | if (clockevent_rating) | 667 | if (clockevent_rating) |
637 | sh_cmt_register_clockevent(p, name, clockevent_rating); | 668 | sh_cmt_register_clockevent(p, name, clockevent_rating); |
638 | 669 | ||
@@ -657,8 +688,6 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
657 | goto err0; | 688 | goto err0; |
658 | } | 689 | } |
659 | 690 | ||
660 | platform_set_drvdata(pdev, p); | ||
661 | |||
662 | res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); | 691 | res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); |
663 | if (!res) { | 692 | if (!res) { |
664 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); | 693 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); |
@@ -693,32 +722,51 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
693 | goto err1; | 722 | goto err1; |
694 | } | 723 | } |
695 | 724 | ||
725 | p->read_control = sh_cmt_read16; | ||
726 | p->write_control = sh_cmt_write16; | ||
727 | |||
696 | if (resource_size(res) == 6) { | 728 | if (resource_size(res) == 6) { |
697 | p->width = 16; | 729 | p->width = 16; |
730 | p->read_count = sh_cmt_read16; | ||
731 | p->write_count = sh_cmt_write16; | ||
698 | p->overflow_bit = 0x80; | 732 | p->overflow_bit = 0x80; |
699 | p->clear_bits = ~0x80; | 733 | p->clear_bits = ~0x80; |
700 | } else { | 734 | } else { |
701 | p->width = 32; | 735 | p->width = 32; |
736 | p->read_count = sh_cmt_read32; | ||
737 | p->write_count = sh_cmt_write32; | ||
702 | p->overflow_bit = 0x8000; | 738 | p->overflow_bit = 0x8000; |
703 | p->clear_bits = ~0xc000; | 739 | p->clear_bits = ~0xc000; |
704 | } | 740 | } |
705 | 741 | ||
742 | if (p->width == (sizeof(p->max_match_value) * 8)) | ||
743 | p->max_match_value = ~0; | ||
744 | else | ||
745 | p->max_match_value = (1 << p->width) - 1; | ||
746 | |||
747 | p->match_value = p->max_match_value; | ||
748 | raw_spin_lock_init(&p->lock); | ||
749 | |||
706 | ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), | 750 | ret = sh_cmt_register(p, (char *)dev_name(&p->pdev->dev), |
707 | cfg->clockevent_rating, | 751 | cfg->clockevent_rating, |
708 | cfg->clocksource_rating); | 752 | cfg->clocksource_rating); |
709 | if (ret) { | 753 | if (ret) { |
710 | dev_err(&p->pdev->dev, "registration failed\n"); | 754 | dev_err(&p->pdev->dev, "registration failed\n"); |
711 | goto err1; | 755 | goto err2; |
712 | } | 756 | } |
713 | p->cs_enabled = false; | 757 | p->cs_enabled = false; |
714 | 758 | ||
715 | ret = setup_irq(irq, &p->irqaction); | 759 | ret = setup_irq(irq, &p->irqaction); |
716 | if (ret) { | 760 | if (ret) { |
717 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); | 761 | dev_err(&p->pdev->dev, "failed to request irq %d\n", irq); |
718 | goto err1; | 762 | goto err2; |
719 | } | 763 | } |
720 | 764 | ||
765 | platform_set_drvdata(pdev, p); | ||
766 | |||
721 | return 0; | 767 | return 0; |
768 | err2: | ||
769 | clk_put(p->clk); | ||
722 | 770 | ||
723 | err1: | 771 | err1: |
724 | iounmap(p->mapbase); | 772 | iounmap(p->mapbase); |
@@ -751,7 +799,6 @@ static int sh_cmt_probe(struct platform_device *pdev) | |||
751 | ret = sh_cmt_setup(p, pdev); | 799 | ret = sh_cmt_setup(p, pdev); |
752 | if (ret) { | 800 | if (ret) { |
753 | kfree(p); | 801 | kfree(p); |
754 | platform_set_drvdata(pdev, NULL); | ||
755 | pm_runtime_idle(&pdev->dev); | 802 | pm_runtime_idle(&pdev->dev); |
756 | return ret; | 803 | return ret; |
757 | } | 804 | } |
@@ -791,7 +838,7 @@ static void __exit sh_cmt_exit(void) | |||
791 | } | 838 | } |
792 | 839 | ||
793 | early_platform_init("earlytimer", &sh_cmt_device_driver); | 840 | early_platform_init("earlytimer", &sh_cmt_device_driver); |
794 | module_init(sh_cmt_init); | 841 | subsys_initcall(sh_cmt_init); |
795 | module_exit(sh_cmt_exit); | 842 | module_exit(sh_cmt_exit); |
796 | 843 | ||
797 | MODULE_AUTHOR("Magnus Damm"); | 844 | MODULE_AUTHOR("Magnus Damm"); |
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c index 83943e27cfac..4aac9ee0d0c0 100644 --- a/drivers/clocksource/sh_mtu2.c +++ b/drivers/clocksource/sh_mtu2.c | |||
@@ -386,7 +386,7 @@ static void __exit sh_mtu2_exit(void) | |||
386 | } | 386 | } |
387 | 387 | ||
388 | early_platform_init("earlytimer", &sh_mtu2_device_driver); | 388 | early_platform_init("earlytimer", &sh_mtu2_device_driver); |
389 | module_init(sh_mtu2_init); | 389 | subsys_initcall(sh_mtu2_init); |
390 | module_exit(sh_mtu2_exit); | 390 | module_exit(sh_mtu2_exit); |
391 | 391 | ||
392 | MODULE_AUTHOR("Magnus Damm"); | 392 | MODULE_AUTHOR("Magnus Damm"); |
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c index b4502edce2a1..78b8dae49628 100644 --- a/drivers/clocksource/sh_tmu.c +++ b/drivers/clocksource/sh_tmu.c | |||
@@ -549,7 +549,7 @@ static void __exit sh_tmu_exit(void) | |||
549 | } | 549 | } |
550 | 550 | ||
551 | early_platform_init("earlytimer", &sh_tmu_device_driver); | 551 | early_platform_init("earlytimer", &sh_tmu_device_driver); |
552 | module_init(sh_tmu_init); | 552 | subsys_initcall(sh_tmu_init); |
553 | module_exit(sh_tmu_exit); | 553 | module_exit(sh_tmu_exit); |
554 | 554 | ||
555 | MODULE_AUTHOR("Magnus Damm"); | 555 | MODULE_AUTHOR("Magnus Damm"); |
diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c index 4086b9167159..0ce85e29769b 100644 --- a/drivers/clocksource/sunxi_timer.c +++ b/drivers/clocksource/sunxi_timer.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/of_address.h> | 23 | #include <linux/of_address.h> |
24 | #include <linux/of_irq.h> | 24 | #include <linux/of_irq.h> |
25 | #include <linux/sunxi_timer.h> | 25 | #include <linux/sunxi_timer.h> |
26 | #include <linux/clk-provider.h> | 26 | #include <linux/clk/sunxi.h> |
27 | 27 | ||
28 | #define TIMER_CTL_REG 0x00 | 28 | #define TIMER_CTL_REG 0x00 |
29 | #define TIMER_CTL_ENABLE (1 << 0) | 29 | #define TIMER_CTL_ENABLE (1 << 0) |
@@ -123,7 +123,7 @@ void __init sunxi_timer_init(void) | |||
123 | if (irq <= 0) | 123 | if (irq <= 0) |
124 | panic("Can't parse IRQ"); | 124 | panic("Can't parse IRQ"); |
125 | 125 | ||
126 | of_clk_init(NULL); | 126 | sunxi_init_clocks(); |
127 | 127 | ||
128 | clk = of_clk_get(node, 0); | 128 | clk = of_clk_get(node, 0); |
129 | if (IS_ERR(clk)) | 129 | if (IS_ERR(clk)) |
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c index 0bde03feb095..ae877b021b54 100644 --- a/drivers/clocksource/tegra20_timer.c +++ b/drivers/clocksource/tegra20_timer.c | |||
@@ -154,29 +154,12 @@ static struct irqaction tegra_timer_irq = { | |||
154 | .dev_id = &tegra_clockevent, | 154 | .dev_id = &tegra_clockevent, |
155 | }; | 155 | }; |
156 | 156 | ||
157 | static const struct of_device_id timer_match[] __initconst = { | 157 | static void __init tegra20_init_timer(struct device_node *np) |
158 | { .compatible = "nvidia,tegra20-timer" }, | ||
159 | {} | ||
160 | }; | ||
161 | |||
162 | static const struct of_device_id rtc_match[] __initconst = { | ||
163 | { .compatible = "nvidia,tegra20-rtc" }, | ||
164 | {} | ||
165 | }; | ||
166 | |||
167 | static void __init tegra20_init_timer(void) | ||
168 | { | 158 | { |
169 | struct device_node *np; | ||
170 | struct clk *clk; | 159 | struct clk *clk; |
171 | unsigned long rate; | 160 | unsigned long rate; |
172 | int ret; | 161 | int ret; |
173 | 162 | ||
174 | np = of_find_matching_node(NULL, timer_match); | ||
175 | if (!np) { | ||
176 | pr_err("Failed to find timer DT node\n"); | ||
177 | BUG(); | ||
178 | } | ||
179 | |||
180 | timer_reg_base = of_iomap(np, 0); | 163 | timer_reg_base = of_iomap(np, 0); |
181 | if (!timer_reg_base) { | 164 | if (!timer_reg_base) { |
182 | pr_err("Can't map timer registers\n"); | 165 | pr_err("Can't map timer registers\n"); |
@@ -189,7 +172,7 @@ static void __init tegra20_init_timer(void) | |||
189 | BUG(); | 172 | BUG(); |
190 | } | 173 | } |
191 | 174 | ||
192 | clk = clk_get_sys("timer", NULL); | 175 | clk = of_clk_get(np, 0); |
193 | if (IS_ERR(clk)) { | 176 | if (IS_ERR(clk)) { |
194 | pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); | 177 | pr_warn("Unable to get timer clock. Assuming 12Mhz input clock.\n"); |
195 | rate = 12000000; | 178 | rate = 12000000; |
@@ -200,30 +183,6 @@ static void __init tegra20_init_timer(void) | |||
200 | 183 | ||
201 | of_node_put(np); | 184 | of_node_put(np); |
202 | 185 | ||
203 | np = of_find_matching_node(NULL, rtc_match); | ||
204 | if (!np) { | ||
205 | pr_err("Failed to find RTC DT node\n"); | ||
206 | BUG(); | ||
207 | } | ||
208 | |||
209 | rtc_base = of_iomap(np, 0); | ||
210 | if (!rtc_base) { | ||
211 | pr_err("Can't map RTC registers"); | ||
212 | BUG(); | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * rtc registers are used by read_persistent_clock, keep the rtc clock | ||
217 | * enabled | ||
218 | */ | ||
219 | clk = clk_get_sys("rtc-tegra", NULL); | ||
220 | if (IS_ERR(clk)) | ||
221 | pr_warn("Unable to get rtc-tegra clock\n"); | ||
222 | else | ||
223 | clk_prepare_enable(clk); | ||
224 | |||
225 | of_node_put(np); | ||
226 | |||
227 | switch (rate) { | 186 | switch (rate) { |
228 | case 12000000: | 187 | case 12000000: |
229 | timer_writel(0x000b, TIMERUS_USEC_CFG); | 188 | timer_writel(0x000b, TIMERUS_USEC_CFG); |
@@ -259,12 +218,34 @@ static void __init tegra20_init_timer(void) | |||
259 | tegra_clockevent.irq = tegra_timer_irq.irq; | 218 | tegra_clockevent.irq = tegra_timer_irq.irq; |
260 | clockevents_config_and_register(&tegra_clockevent, 1000000, | 219 | clockevents_config_and_register(&tegra_clockevent, 1000000, |
261 | 0x1, 0x1fffffff); | 220 | 0x1, 0x1fffffff); |
262 | #ifdef CONFIG_HAVE_ARM_TWD | 221 | } |
263 | twd_local_timer_of_register(); | 222 | CLOCKSOURCE_OF_DECLARE(tegra20_timer, "nvidia,tegra20-timer", tegra20_init_timer); |
264 | #endif | 223 | |
224 | static void __init tegra20_init_rtc(struct device_node *np) | ||
225 | { | ||
226 | struct clk *clk; | ||
227 | |||
228 | rtc_base = of_iomap(np, 0); | ||
229 | if (!rtc_base) { | ||
230 | pr_err("Can't map RTC registers"); | ||
231 | BUG(); | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * rtc registers are used by read_persistent_clock, keep the rtc clock | ||
236 | * enabled | ||
237 | */ | ||
238 | clk = of_clk_get(np, 0); | ||
239 | if (IS_ERR(clk)) | ||
240 | pr_warn("Unable to get rtc-tegra clock\n"); | ||
241 | else | ||
242 | clk_prepare_enable(clk); | ||
243 | |||
244 | of_node_put(np); | ||
245 | |||
265 | register_persistent_clock(NULL, tegra_read_persistent_clock); | 246 | register_persistent_clock(NULL, tegra_read_persistent_clock); |
266 | } | 247 | } |
267 | CLOCKSOURCE_OF_DECLARE(tegra20, "nvidia,tegra20-timer", tegra20_init_timer); | 248 | CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc); |
268 | 249 | ||
269 | #ifdef CONFIG_PM | 250 | #ifdef CONFIG_PM |
270 | static u32 usec_config; | 251 | static u32 usec_config; |
diff --git a/drivers/clocksource/vt8500_timer.c b/drivers/clocksource/vt8500_timer.c index 8efc86b5b5dd..64f553f04fa4 100644 --- a/drivers/clocksource/vt8500_timer.c +++ b/drivers/clocksource/vt8500_timer.c | |||
@@ -129,22 +129,10 @@ static struct irqaction irq = { | |||
129 | .dev_id = &clockevent, | 129 | .dev_id = &clockevent, |
130 | }; | 130 | }; |
131 | 131 | ||
132 | static struct of_device_id vt8500_timer_ids[] = { | 132 | static void __init vt8500_timer_init(struct device_node *np) |
133 | { .compatible = "via,vt8500-timer" }, | ||
134 | { } | ||
135 | }; | ||
136 | |||
137 | static void __init vt8500_timer_init(void) | ||
138 | { | 133 | { |
139 | struct device_node *np; | ||
140 | int timer_irq; | 134 | int timer_irq; |
141 | 135 | ||
142 | np = of_find_matching_node(NULL, vt8500_timer_ids); | ||
143 | if (!np) { | ||
144 | pr_err("%s: Timer description missing from Device Tree\n", | ||
145 | __func__); | ||
146 | return; | ||
147 | } | ||
148 | regbase = of_iomap(np, 0); | 136 | regbase = of_iomap(np, 0); |
149 | if (!regbase) { | 137 | if (!regbase) { |
150 | pr_err("%s: Missing iobase description in Device Tree\n", | 138 | pr_err("%s: Missing iobase description in Device Tree\n", |
@@ -177,4 +165,4 @@ static void __init vt8500_timer_init(void) | |||
177 | 4, 0xf0000000); | 165 | 4, 0xf0000000); |
178 | } | 166 | } |
179 | 167 | ||
180 | CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init) | 168 | CLOCKSOURCE_OF_DECLARE(vt8500, "via,vt8500-timer", vt8500_timer_init); |
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c index fce2000eec31..1110478dd0fd 100644 --- a/drivers/connector/cn_proc.c +++ b/drivers/connector/cn_proc.c | |||
@@ -313,6 +313,12 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, | |||
313 | (task_active_pid_ns(current) != &init_pid_ns)) | 313 | (task_active_pid_ns(current) != &init_pid_ns)) |
314 | return; | 314 | return; |
315 | 315 | ||
316 | /* Can only change if privileged. */ | ||
317 | if (!capable(CAP_NET_ADMIN)) { | ||
318 | err = EPERM; | ||
319 | goto out; | ||
320 | } | ||
321 | |||
316 | mc_op = (enum proc_cn_mcast_op *)msg->data; | 322 | mc_op = (enum proc_cn_mcast_op *)msg->data; |
317 | switch (*mc_op) { | 323 | switch (*mc_op) { |
318 | case PROC_CN_MCAST_LISTEN: | 324 | case PROC_CN_MCAST_LISTEN: |
@@ -325,6 +331,8 @@ static void cn_proc_mcast_ctl(struct cn_msg *msg, | |||
325 | err = EINVAL; | 331 | err = EINVAL; |
326 | break; | 332 | break; |
327 | } | 333 | } |
334 | |||
335 | out: | ||
328 | cn_proc_ack(err, msg->seq, msg->ack); | 336 | cn_proc_ack(err, msg->seq, msg->ack); |
329 | } | 337 | } |
330 | 338 | ||
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 937bc286591f..57a8774f0b4e 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -730,7 +730,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
730 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { | 730 | policy->shared_type == CPUFREQ_SHARED_TYPE_ANY) { |
731 | cpumask_copy(policy->cpus, perf->shared_cpu_map); | 731 | cpumask_copy(policy->cpus, perf->shared_cpu_map); |
732 | } | 732 | } |
733 | cpumask_copy(policy->related_cpus, perf->shared_cpu_map); | ||
734 | 733 | ||
735 | #ifdef CONFIG_SMP | 734 | #ifdef CONFIG_SMP |
736 | dmi_check_system(sw_any_bug_dmi_table); | 735 | dmi_check_system(sw_any_bug_dmi_table); |
@@ -742,7 +741,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) | |||
742 | if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) { | 741 | if (check_amd_hwpstate_cpu(cpu) && !acpi_pstate_strict) { |
743 | cpumask_clear(policy->cpus); | 742 | cpumask_clear(policy->cpus); |
744 | cpumask_set_cpu(cpu, policy->cpus); | 743 | cpumask_set_cpu(cpu, policy->cpus); |
745 | cpumask_copy(policy->related_cpus, cpu_sibling_mask(cpu)); | ||
746 | policy->shared_type = CPUFREQ_SHARED_TYPE_HW; | 744 | policy->shared_type = CPUFREQ_SHARED_TYPE_HW; |
747 | pr_info_once(PFX "overriding BIOS provided _PSD data\n"); | 745 | pr_info_once(PFX "overriding BIOS provided _PSD data\n"); |
748 | } | 746 | } |
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index d2ac91150600..46bde01eee62 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h | |||
@@ -64,7 +64,7 @@ static void *get_cpu_dbs_info_s(int cpu) \ | |||
64 | * dbs: used as a shortform for demand based switching It helps to keep variable | 64 | * dbs: used as a shortform for demand based switching It helps to keep variable |
65 | * names smaller, simpler | 65 | * names smaller, simpler |
66 | * cdbs: common dbs | 66 | * cdbs: common dbs |
67 | * on_*: On-demand governor | 67 | * od_*: On-demand governor |
68 | * cs_*: Conservative governor | 68 | * cs_*: Conservative governor |
69 | */ | 69 | */ |
70 | 70 | ||
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index 2fd779eb1ed1..bfd6273fd873 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c | |||
@@ -180,15 +180,19 @@ static void cpufreq_stats_free_sysfs(unsigned int cpu) | |||
180 | { | 180 | { |
181 | struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); | 181 | struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); |
182 | 182 | ||
183 | if (!cpufreq_frequency_get_table(cpu)) | 183 | if (!policy) |
184 | return; | 184 | return; |
185 | 185 | ||
186 | if (policy && !policy_is_shared(policy)) { | 186 | if (!cpufreq_frequency_get_table(cpu)) |
187 | goto put_ref; | ||
188 | |||
189 | if (!policy_is_shared(policy)) { | ||
187 | pr_debug("%s: Free sysfs stat\n", __func__); | 190 | pr_debug("%s: Free sysfs stat\n", __func__); |
188 | sysfs_remove_group(&policy->kobj, &stats_attr_group); | 191 | sysfs_remove_group(&policy->kobj, &stats_attr_group); |
189 | } | 192 | } |
190 | if (policy) | 193 | |
191 | cpufreq_cpu_put(policy); | 194 | put_ref: |
195 | cpufreq_cpu_put(policy); | ||
192 | } | 196 | } |
193 | 197 | ||
194 | static int cpufreq_stats_create_table(struct cpufreq_policy *policy, | 198 | static int cpufreq_stats_create_table(struct cpufreq_policy *policy, |
diff --git a/drivers/cpufreq/highbank-cpufreq.c b/drivers/cpufreq/highbank-cpufreq.c index 66e3a71b81a3..b61b5a3fad64 100644 --- a/drivers/cpufreq/highbank-cpufreq.c +++ b/drivers/cpufreq/highbank-cpufreq.c | |||
@@ -28,13 +28,7 @@ | |||
28 | 28 | ||
29 | static int hb_voltage_change(unsigned int freq) | 29 | static int hb_voltage_change(unsigned int freq) |
30 | { | 30 | { |
31 | int i; | 31 | u32 msg[HB_CPUFREQ_IPC_LEN] = {HB_CPUFREQ_CHANGE_NOTE, freq / 1000000}; |
32 | u32 msg[HB_CPUFREQ_IPC_LEN]; | ||
33 | |||
34 | msg[0] = HB_CPUFREQ_CHANGE_NOTE; | ||
35 | msg[1] = freq / 1000000; | ||
36 | for (i = 2; i < HB_CPUFREQ_IPC_LEN; i++) | ||
37 | msg[i] = 0; | ||
38 | 32 | ||
39 | return pl320_ipc_transmit(msg); | 33 | return pl320_ipc_transmit(msg); |
40 | } | 34 | } |
diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 096fde0ebcb5..ad72922919ed 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c | |||
@@ -358,14 +358,14 @@ static void intel_pstate_sysfs_expose_params(void) | |||
358 | static int intel_pstate_min_pstate(void) | 358 | static int intel_pstate_min_pstate(void) |
359 | { | 359 | { |
360 | u64 value; | 360 | u64 value; |
361 | rdmsrl(0xCE, value); | 361 | rdmsrl(MSR_PLATFORM_INFO, value); |
362 | return (value >> 40) & 0xFF; | 362 | return (value >> 40) & 0xFF; |
363 | } | 363 | } |
364 | 364 | ||
365 | static int intel_pstate_max_pstate(void) | 365 | static int intel_pstate_max_pstate(void) |
366 | { | 366 | { |
367 | u64 value; | 367 | u64 value; |
368 | rdmsrl(0xCE, value); | 368 | rdmsrl(MSR_PLATFORM_INFO, value); |
369 | return (value >> 8) & 0xFF; | 369 | return (value >> 8) & 0xFF; |
370 | } | 370 | } |
371 | 371 | ||
@@ -373,7 +373,7 @@ static int intel_pstate_turbo_pstate(void) | |||
373 | { | 373 | { |
374 | u64 value; | 374 | u64 value; |
375 | int nont, ret; | 375 | int nont, ret; |
376 | rdmsrl(0x1AD, value); | 376 | rdmsrl(MSR_NHM_TURBO_RATIO_LIMIT, value); |
377 | nont = intel_pstate_max_pstate(); | 377 | nont = intel_pstate_max_pstate(); |
378 | ret = ((value) & 255); | 378 | ret = ((value) & 255); |
379 | if (ret <= nont) | 379 | if (ret <= nont) |
@@ -454,7 +454,7 @@ static inline void intel_pstate_calc_busy(struct cpudata *cpu, | |||
454 | sample->idletime_us * 100, | 454 | sample->idletime_us * 100, |
455 | sample->duration_us); | 455 | sample->duration_us); |
456 | core_pct = div64_u64(sample->aperf * 100, sample->mperf); | 456 | core_pct = div64_u64(sample->aperf * 100, sample->mperf); |
457 | sample->freq = cpu->pstate.turbo_pstate * core_pct * 1000; | 457 | sample->freq = cpu->pstate.max_pstate * core_pct * 1000; |
458 | 458 | ||
459 | sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct), | 459 | sample->core_pct_busy = div_s64((sample->pstate_pct_busy * core_pct), |
460 | 100); | 460 | 100); |
@@ -662,6 +662,9 @@ static int intel_pstate_set_policy(struct cpufreq_policy *policy) | |||
662 | 662 | ||
663 | cpu = all_cpu_data[policy->cpu]; | 663 | cpu = all_cpu_data[policy->cpu]; |
664 | 664 | ||
665 | if (!policy->cpuinfo.max_freq) | ||
666 | return -ENODEV; | ||
667 | |||
665 | intel_pstate_get_min_max(cpu, &min, &max); | 668 | intel_pstate_get_min_max(cpu, &min, &max); |
666 | 669 | ||
667 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; | 670 | limits.min_perf_pct = (policy->min * 100) / policy->cpuinfo.max_freq; |
@@ -747,37 +750,34 @@ static struct cpufreq_driver intel_pstate_driver = { | |||
747 | .owner = THIS_MODULE, | 750 | .owner = THIS_MODULE, |
748 | }; | 751 | }; |
749 | 752 | ||
750 | static void intel_pstate_exit(void) | 753 | static int __initdata no_load; |
754 | |||
755 | static int intel_pstate_msrs_not_valid(void) | ||
751 | { | 756 | { |
752 | int cpu; | 757 | /* Check that all the msr's we are using are valid. */ |
758 | u64 aperf, mperf, tmp; | ||
753 | 759 | ||
754 | sysfs_remove_group(intel_pstate_kobject, | 760 | rdmsrl(MSR_IA32_APERF, aperf); |
755 | &intel_pstate_attr_group); | 761 | rdmsrl(MSR_IA32_MPERF, mperf); |
756 | debugfs_remove_recursive(debugfs_parent); | ||
757 | 762 | ||
758 | cpufreq_unregister_driver(&intel_pstate_driver); | 763 | if (!intel_pstate_min_pstate() || |
764 | !intel_pstate_max_pstate() || | ||
765 | !intel_pstate_turbo_pstate()) | ||
766 | return -ENODEV; | ||
759 | 767 | ||
760 | if (!all_cpu_data) | 768 | rdmsrl(MSR_IA32_APERF, tmp); |
761 | return; | 769 | if (!(tmp - aperf)) |
770 | return -ENODEV; | ||
762 | 771 | ||
763 | get_online_cpus(); | 772 | rdmsrl(MSR_IA32_MPERF, tmp); |
764 | for_each_online_cpu(cpu) { | 773 | if (!(tmp - mperf)) |
765 | if (all_cpu_data[cpu]) { | 774 | return -ENODEV; |
766 | del_timer_sync(&all_cpu_data[cpu]->timer); | ||
767 | kfree(all_cpu_data[cpu]); | ||
768 | } | ||
769 | } | ||
770 | 775 | ||
771 | put_online_cpus(); | 776 | return 0; |
772 | vfree(all_cpu_data); | ||
773 | } | 777 | } |
774 | module_exit(intel_pstate_exit); | ||
775 | |||
776 | static int __initdata no_load; | ||
777 | |||
778 | static int __init intel_pstate_init(void) | 778 | static int __init intel_pstate_init(void) |
779 | { | 779 | { |
780 | int rc = 0; | 780 | int cpu, rc = 0; |
781 | const struct x86_cpu_id *id; | 781 | const struct x86_cpu_id *id; |
782 | 782 | ||
783 | if (no_load) | 783 | if (no_load) |
@@ -787,6 +787,9 @@ static int __init intel_pstate_init(void) | |||
787 | if (!id) | 787 | if (!id) |
788 | return -ENODEV; | 788 | return -ENODEV; |
789 | 789 | ||
790 | if (intel_pstate_msrs_not_valid()) | ||
791 | return -ENODEV; | ||
792 | |||
790 | pr_info("Intel P-state driver initializing.\n"); | 793 | pr_info("Intel P-state driver initializing.\n"); |
791 | 794 | ||
792 | all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus()); | 795 | all_cpu_data = vmalloc(sizeof(void *) * num_possible_cpus()); |
@@ -802,7 +805,16 @@ static int __init intel_pstate_init(void) | |||
802 | intel_pstate_sysfs_expose_params(); | 805 | intel_pstate_sysfs_expose_params(); |
803 | return rc; | 806 | return rc; |
804 | out: | 807 | out: |
805 | intel_pstate_exit(); | 808 | get_online_cpus(); |
809 | for_each_online_cpu(cpu) { | ||
810 | if (all_cpu_data[cpu]) { | ||
811 | del_timer_sync(&all_cpu_data[cpu]->timer); | ||
812 | kfree(all_cpu_data[cpu]); | ||
813 | } | ||
814 | } | ||
815 | |||
816 | put_online_cpus(); | ||
817 | vfree(all_cpu_data); | ||
806 | return -ENODEV; | 818 | return -ENODEV; |
807 | } | 819 | } |
808 | device_initcall(intel_pstate_init); | 820 | device_initcall(intel_pstate_init); |
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c index b2a0a0726a54..cf268b14ae9a 100644 --- a/drivers/crypto/caam/caamalg.c +++ b/drivers/crypto/caam/caamalg.c | |||
@@ -1650,11 +1650,7 @@ struct caam_alg_template { | |||
1650 | }; | 1650 | }; |
1651 | 1651 | ||
1652 | static struct caam_alg_template driver_algs[] = { | 1652 | static struct caam_alg_template driver_algs[] = { |
1653 | /* | 1653 | /* single-pass ipsec_esp descriptor */ |
1654 | * single-pass ipsec_esp descriptor | ||
1655 | * authencesn(*,*) is also registered, although not present | ||
1656 | * explicitly here. | ||
1657 | */ | ||
1658 | { | 1654 | { |
1659 | .name = "authenc(hmac(md5),cbc(aes))", | 1655 | .name = "authenc(hmac(md5),cbc(aes))", |
1660 | .driver_name = "authenc-hmac-md5-cbc-aes-caam", | 1656 | .driver_name = "authenc-hmac-md5-cbc-aes-caam", |
@@ -2217,9 +2213,7 @@ static int __init caam_algapi_init(void) | |||
2217 | for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { | 2213 | for (i = 0; i < ARRAY_SIZE(driver_algs); i++) { |
2218 | /* TODO: check if h/w supports alg */ | 2214 | /* TODO: check if h/w supports alg */ |
2219 | struct caam_crypto_alg *t_alg; | 2215 | struct caam_crypto_alg *t_alg; |
2220 | bool done = false; | ||
2221 | 2216 | ||
2222 | authencesn: | ||
2223 | t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]); | 2217 | t_alg = caam_alg_alloc(ctrldev, &driver_algs[i]); |
2224 | if (IS_ERR(t_alg)) { | 2218 | if (IS_ERR(t_alg)) { |
2225 | err = PTR_ERR(t_alg); | 2219 | err = PTR_ERR(t_alg); |
@@ -2233,25 +2227,8 @@ authencesn: | |||
2233 | dev_warn(ctrldev, "%s alg registration failed\n", | 2227 | dev_warn(ctrldev, "%s alg registration failed\n", |
2234 | t_alg->crypto_alg.cra_driver_name); | 2228 | t_alg->crypto_alg.cra_driver_name); |
2235 | kfree(t_alg); | 2229 | kfree(t_alg); |
2236 | } else { | 2230 | } else |
2237 | list_add_tail(&t_alg->entry, &priv->alg_list); | 2231 | list_add_tail(&t_alg->entry, &priv->alg_list); |
2238 | if (driver_algs[i].type == CRYPTO_ALG_TYPE_AEAD && | ||
2239 | !memcmp(driver_algs[i].name, "authenc", 7) && | ||
2240 | !done) { | ||
2241 | char *name; | ||
2242 | |||
2243 | name = driver_algs[i].name; | ||
2244 | memmove(name + 10, name + 7, strlen(name) - 7); | ||
2245 | memcpy(name + 7, "esn", 3); | ||
2246 | |||
2247 | name = driver_algs[i].driver_name; | ||
2248 | memmove(name + 10, name + 7, strlen(name) - 7); | ||
2249 | memcpy(name + 7, "esn", 3); | ||
2250 | |||
2251 | done = true; | ||
2252 | goto authencesn; | ||
2253 | } | ||
2254 | } | ||
2255 | } | 2232 | } |
2256 | if (!list_empty(&priv->alg_list)) | 2233 | if (!list_empty(&priv->alg_list)) |
2257 | dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n", | 2234 | dev_info(ctrldev, "%s algorithms registered in /proc/crypto\n", |
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h index cf15e7813801..762aeff626ac 100644 --- a/drivers/crypto/caam/compat.h +++ b/drivers/crypto/caam/compat.h | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <linux/types.h> | 23 | #include <linux/types.h> |
24 | #include <linux/debugfs.h> | 24 | #include <linux/debugfs.h> |
25 | #include <linux/circ_buf.h> | 25 | #include <linux/circ_buf.h> |
26 | #include <linux/string.h> | ||
27 | #include <net/xfrm.h> | 26 | #include <net/xfrm.h> |
28 | 27 | ||
29 | #include <crypto/algapi.h> | 28 | #include <crypto/algapi.h> |
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c index 09b184adf31b..5b2b5e61e4f9 100644 --- a/drivers/crypto/talitos.c +++ b/drivers/crypto/talitos.c | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
39 | #include <linux/rtnetlink.h> | 39 | #include <linux/rtnetlink.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/string.h> | ||
42 | 41 | ||
43 | #include <crypto/algapi.h> | 42 | #include <crypto/algapi.h> |
44 | #include <crypto/aes.h> | 43 | #include <crypto/aes.h> |
@@ -1974,11 +1973,7 @@ struct talitos_alg_template { | |||
1974 | }; | 1973 | }; |
1975 | 1974 | ||
1976 | static struct talitos_alg_template driver_algs[] = { | 1975 | static struct talitos_alg_template driver_algs[] = { |
1977 | /* | 1976 | /* AEAD algorithms. These use a single-pass ipsec_esp descriptor */ |
1978 | * AEAD algorithms. These use a single-pass ipsec_esp descriptor. | ||
1979 | * authencesn(*,*) is also registered, although not present | ||
1980 | * explicitly here. | ||
1981 | */ | ||
1982 | { .type = CRYPTO_ALG_TYPE_AEAD, | 1977 | { .type = CRYPTO_ALG_TYPE_AEAD, |
1983 | .alg.crypto = { | 1978 | .alg.crypto = { |
1984 | .cra_name = "authenc(hmac(sha1),cbc(aes))", | 1979 | .cra_name = "authenc(hmac(sha1),cbc(aes))", |
@@ -2820,9 +2815,7 @@ static int talitos_probe(struct platform_device *ofdev) | |||
2820 | if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { | 2815 | if (hw_supports(dev, driver_algs[i].desc_hdr_template)) { |
2821 | struct talitos_crypto_alg *t_alg; | 2816 | struct talitos_crypto_alg *t_alg; |
2822 | char *name = NULL; | 2817 | char *name = NULL; |
2823 | bool authenc = false; | ||
2824 | 2818 | ||
2825 | authencesn: | ||
2826 | t_alg = talitos_alg_alloc(dev, &driver_algs[i]); | 2819 | t_alg = talitos_alg_alloc(dev, &driver_algs[i]); |
2827 | if (IS_ERR(t_alg)) { | 2820 | if (IS_ERR(t_alg)) { |
2828 | err = PTR_ERR(t_alg); | 2821 | err = PTR_ERR(t_alg); |
@@ -2837,8 +2830,6 @@ authencesn: | |||
2837 | err = crypto_register_alg( | 2830 | err = crypto_register_alg( |
2838 | &t_alg->algt.alg.crypto); | 2831 | &t_alg->algt.alg.crypto); |
2839 | name = t_alg->algt.alg.crypto.cra_driver_name; | 2832 | name = t_alg->algt.alg.crypto.cra_driver_name; |
2840 | authenc = authenc ? !authenc : | ||
2841 | !(bool)memcmp(name, "authenc", 7); | ||
2842 | break; | 2833 | break; |
2843 | case CRYPTO_ALG_TYPE_AHASH: | 2834 | case CRYPTO_ALG_TYPE_AHASH: |
2844 | err = crypto_register_ahash( | 2835 | err = crypto_register_ahash( |
@@ -2851,25 +2842,8 @@ authencesn: | |||
2851 | dev_err(dev, "%s alg registration failed\n", | 2842 | dev_err(dev, "%s alg registration failed\n", |
2852 | name); | 2843 | name); |
2853 | kfree(t_alg); | 2844 | kfree(t_alg); |
2854 | } else { | 2845 | } else |
2855 | list_add_tail(&t_alg->entry, &priv->alg_list); | 2846 | list_add_tail(&t_alg->entry, &priv->alg_list); |
2856 | if (authenc) { | ||
2857 | struct crypto_alg *alg = | ||
2858 | &driver_algs[i].alg.crypto; | ||
2859 | |||
2860 | name = alg->cra_name; | ||
2861 | memmove(name + 10, name + 7, | ||
2862 | strlen(name) - 7); | ||
2863 | memcpy(name + 7, "esn", 3); | ||
2864 | |||
2865 | name = alg->cra_driver_name; | ||
2866 | memmove(name + 10, name + 7, | ||
2867 | strlen(name) - 7); | ||
2868 | memcpy(name + 7, "esn", 3); | ||
2869 | |||
2870 | goto authencesn; | ||
2871 | } | ||
2872 | } | ||
2873 | } | 2847 | } |
2874 | } | 2848 | } |
2875 | if (!list_empty(&priv->alg_list)) | 2849 | if (!list_empty(&priv->alg_list)) |
diff --git a/drivers/dma/dw_dmac.c b/drivers/dma/dw_dmac.c index c599558faeda..43a5329d4483 100644 --- a/drivers/dma/dw_dmac.c +++ b/drivers/dma/dw_dmac.c | |||
@@ -1001,6 +1001,13 @@ static inline void convert_burst(u32 *maxburst) | |||
1001 | *maxburst = 0; | 1001 | *maxburst = 0; |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | static inline void convert_slave_id(struct dw_dma_chan *dwc) | ||
1005 | { | ||
1006 | struct dw_dma *dw = to_dw_dma(dwc->chan.device); | ||
1007 | |||
1008 | dwc->dma_sconfig.slave_id -= dw->request_line_base; | ||
1009 | } | ||
1010 | |||
1004 | static int | 1011 | static int |
1005 | set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) | 1012 | set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) |
1006 | { | 1013 | { |
@@ -1015,6 +1022,7 @@ set_runtime_config(struct dma_chan *chan, struct dma_slave_config *sconfig) | |||
1015 | 1022 | ||
1016 | convert_burst(&dwc->dma_sconfig.src_maxburst); | 1023 | convert_burst(&dwc->dma_sconfig.src_maxburst); |
1017 | convert_burst(&dwc->dma_sconfig.dst_maxburst); | 1024 | convert_burst(&dwc->dma_sconfig.dst_maxburst); |
1025 | convert_slave_id(dwc); | ||
1018 | 1026 | ||
1019 | return 0; | 1027 | return 0; |
1020 | } | 1028 | } |
@@ -1276,9 +1284,9 @@ static struct dma_chan *dw_dma_xlate(struct of_phandle_args *dma_spec, | |||
1276 | if (dma_spec->args_count != 3) | 1284 | if (dma_spec->args_count != 3) |
1277 | return NULL; | 1285 | return NULL; |
1278 | 1286 | ||
1279 | fargs.req = be32_to_cpup(dma_spec->args+0); | 1287 | fargs.req = dma_spec->args[0]; |
1280 | fargs.src = be32_to_cpup(dma_spec->args+1); | 1288 | fargs.src = dma_spec->args[1]; |
1281 | fargs.dst = be32_to_cpup(dma_spec->args+2); | 1289 | fargs.dst = dma_spec->args[2]; |
1282 | 1290 | ||
1283 | if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS || | 1291 | if (WARN_ON(fargs.req >= DW_DMA_MAX_NR_REQUESTS || |
1284 | fargs.src >= dw->nr_masters || | 1292 | fargs.src >= dw->nr_masters || |
@@ -1628,6 +1636,7 @@ dw_dma_parse_dt(struct platform_device *pdev) | |||
1628 | 1636 | ||
1629 | static int dw_probe(struct platform_device *pdev) | 1637 | static int dw_probe(struct platform_device *pdev) |
1630 | { | 1638 | { |
1639 | const struct platform_device_id *match; | ||
1631 | struct dw_dma_platform_data *pdata; | 1640 | struct dw_dma_platform_data *pdata; |
1632 | struct resource *io; | 1641 | struct resource *io; |
1633 | struct dw_dma *dw; | 1642 | struct dw_dma *dw; |
@@ -1711,6 +1720,11 @@ static int dw_probe(struct platform_device *pdev) | |||
1711 | memcpy(dw->data_width, pdata->data_width, 4); | 1720 | memcpy(dw->data_width, pdata->data_width, 4); |
1712 | } | 1721 | } |
1713 | 1722 | ||
1723 | /* Get the base request line if set */ | ||
1724 | match = platform_get_device_id(pdev); | ||
1725 | if (match) | ||
1726 | dw->request_line_base = (unsigned int)match->driver_data; | ||
1727 | |||
1714 | /* Calculate all channel mask before DMA setup */ | 1728 | /* Calculate all channel mask before DMA setup */ |
1715 | dw->all_chan_mask = (1 << nr_channels) - 1; | 1729 | dw->all_chan_mask = (1 << nr_channels) - 1; |
1716 | 1730 | ||
@@ -1906,7 +1920,8 @@ MODULE_DEVICE_TABLE(of, dw_dma_id_table); | |||
1906 | #endif | 1920 | #endif |
1907 | 1921 | ||
1908 | static const struct platform_device_id dw_dma_ids[] = { | 1922 | static const struct platform_device_id dw_dma_ids[] = { |
1909 | { "INTL9C60", 0 }, | 1923 | /* Name, Request Line Base */ |
1924 | { "INTL9C60", (kernel_ulong_t)16 }, | ||
1910 | { } | 1925 | { } |
1911 | }; | 1926 | }; |
1912 | 1927 | ||
diff --git a/drivers/dma/dw_dmac_regs.h b/drivers/dma/dw_dmac_regs.h index cf0ce5c77d60..4d02c3669b75 100644 --- a/drivers/dma/dw_dmac_regs.h +++ b/drivers/dma/dw_dmac_regs.h | |||
@@ -247,6 +247,7 @@ struct dw_dma { | |||
247 | /* hardware configuration */ | 247 | /* hardware configuration */ |
248 | unsigned char nr_masters; | 248 | unsigned char nr_masters; |
249 | unsigned char data_width[4]; | 249 | unsigned char data_width[4]; |
250 | unsigned int request_line_base; | ||
250 | 251 | ||
251 | struct dw_dma_chan chan[0]; | 252 | struct dw_dma_chan chan[0]; |
252 | }; | 253 | }; |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 910b0116c128..e1d13c463c90 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -2048,12 +2048,18 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
2048 | edac_dbg(1, "MC node: %d, csrow: %d\n", | 2048 | edac_dbg(1, "MC node: %d, csrow: %d\n", |
2049 | pvt->mc_node_id, i); | 2049 | pvt->mc_node_id, i); |
2050 | 2050 | ||
2051 | if (row_dct0) | 2051 | if (row_dct0) { |
2052 | nr_pages = amd64_csrow_nr_pages(pvt, 0, i); | 2052 | nr_pages = amd64_csrow_nr_pages(pvt, 0, i); |
2053 | csrow->channels[0]->dimm->nr_pages = nr_pages; | ||
2054 | } | ||
2053 | 2055 | ||
2054 | /* K8 has only one DCT */ | 2056 | /* K8 has only one DCT */ |
2055 | if (boot_cpu_data.x86 != 0xf && row_dct1) | 2057 | if (boot_cpu_data.x86 != 0xf && row_dct1) { |
2056 | nr_pages += amd64_csrow_nr_pages(pvt, 1, i); | 2058 | int row_dct1_pages = amd64_csrow_nr_pages(pvt, 1, i); |
2059 | |||
2060 | csrow->channels[1]->dimm->nr_pages = row_dct1_pages; | ||
2061 | nr_pages += row_dct1_pages; | ||
2062 | } | ||
2057 | 2063 | ||
2058 | mtype = amd64_determine_memory_type(pvt, i); | 2064 | mtype = amd64_determine_memory_type(pvt, i); |
2059 | 2065 | ||
@@ -2072,9 +2078,7 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
2072 | dimm = csrow->channels[j]->dimm; | 2078 | dimm = csrow->channels[j]->dimm; |
2073 | dimm->mtype = mtype; | 2079 | dimm->mtype = mtype; |
2074 | dimm->edac_mode = edac_mode; | 2080 | dimm->edac_mode = edac_mode; |
2075 | dimm->nr_pages = nr_pages; | ||
2076 | } | 2081 | } |
2077 | csrow->nr_pages = nr_pages; | ||
2078 | } | 2082 | } |
2079 | 2083 | ||
2080 | return empty; | 2084 | return empty; |
@@ -2419,7 +2423,6 @@ static int amd64_init_one_instance(struct pci_dev *F2) | |||
2419 | 2423 | ||
2420 | mci->pvt_info = pvt; | 2424 | mci->pvt_info = pvt; |
2421 | mci->pdev = &pvt->F2->dev; | 2425 | mci->pdev = &pvt->F2->dev; |
2422 | mci->csbased = 1; | ||
2423 | 2426 | ||
2424 | setup_mci_misc_attrs(mci, fam_type); | 2427 | setup_mci_misc_attrs(mci, fam_type); |
2425 | 2428 | ||
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index cdb81aa73ab7..27e86d938262 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -86,7 +86,7 @@ static void edac_mc_dump_dimm(struct dimm_info *dimm, int number) | |||
86 | edac_dimm_info_location(dimm, location, sizeof(location)); | 86 | edac_dimm_info_location(dimm, location, sizeof(location)); |
87 | 87 | ||
88 | edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n", | 88 | edac_dbg(4, "%s%i: %smapped as virtual row %d, chan %d\n", |
89 | dimm->mci->mem_is_per_rank ? "rank" : "dimm", | 89 | dimm->mci->csbased ? "rank" : "dimm", |
90 | number, location, dimm->csrow, dimm->cschannel); | 90 | number, location, dimm->csrow, dimm->cschannel); |
91 | edac_dbg(4, " dimm = %p\n", dimm); | 91 | edac_dbg(4, " dimm = %p\n", dimm); |
92 | edac_dbg(4, " dimm->label = '%s'\n", dimm->label); | 92 | edac_dbg(4, " dimm->label = '%s'\n", dimm->label); |
@@ -341,7 +341,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, | |||
341 | memcpy(mci->layers, layers, sizeof(*layer) * n_layers); | 341 | memcpy(mci->layers, layers, sizeof(*layer) * n_layers); |
342 | mci->nr_csrows = tot_csrows; | 342 | mci->nr_csrows = tot_csrows; |
343 | mci->num_cschannel = tot_channels; | 343 | mci->num_cschannel = tot_channels; |
344 | mci->mem_is_per_rank = per_rank; | 344 | mci->csbased = per_rank; |
345 | 345 | ||
346 | /* | 346 | /* |
347 | * Alocate and fill the csrow/channels structs | 347 | * Alocate and fill the csrow/channels structs |
@@ -1235,7 +1235,7 @@ void edac_mc_handle_error(const enum hw_event_mc_err_type type, | |||
1235 | * incrementing the compat API counters | 1235 | * incrementing the compat API counters |
1236 | */ | 1236 | */ |
1237 | edac_dbg(4, "%s csrows map: (%d,%d)\n", | 1237 | edac_dbg(4, "%s csrows map: (%d,%d)\n", |
1238 | mci->mem_is_per_rank ? "rank" : "dimm", | 1238 | mci->csbased ? "rank" : "dimm", |
1239 | dimm->csrow, dimm->cschannel); | 1239 | dimm->csrow, dimm->cschannel); |
1240 | if (row == -1) | 1240 | if (row == -1) |
1241 | row = dimm->csrow; | 1241 | row = dimm->csrow; |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 4f4b6137d74e..5899a76eec3b 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -143,7 +143,7 @@ static const char *edac_caps[] = { | |||
143 | * and the per-dimm/per-rank one | 143 | * and the per-dimm/per-rank one |
144 | */ | 144 | */ |
145 | #define DEVICE_ATTR_LEGACY(_name, _mode, _show, _store) \ | 145 | #define DEVICE_ATTR_LEGACY(_name, _mode, _show, _store) \ |
146 | struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store) | 146 | static struct device_attribute dev_attr_legacy_##_name = __ATTR(_name, _mode, _show, _store) |
147 | 147 | ||
148 | struct dev_ch_attribute { | 148 | struct dev_ch_attribute { |
149 | struct device_attribute attr; | 149 | struct device_attribute attr; |
@@ -180,9 +180,6 @@ static ssize_t csrow_size_show(struct device *dev, | |||
180 | int i; | 180 | int i; |
181 | u32 nr_pages = 0; | 181 | u32 nr_pages = 0; |
182 | 182 | ||
183 | if (csrow->mci->csbased) | ||
184 | return sprintf(data, "%u\n", PAGES_TO_MiB(csrow->nr_pages)); | ||
185 | |||
186 | for (i = 0; i < csrow->nr_channels; i++) | 183 | for (i = 0; i < csrow->nr_channels; i++) |
187 | nr_pages += csrow->channels[i]->dimm->nr_pages; | 184 | nr_pages += csrow->channels[i]->dimm->nr_pages; |
188 | return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); | 185 | return sprintf(data, "%u\n", PAGES_TO_MiB(nr_pages)); |
@@ -612,7 +609,7 @@ static int edac_create_dimm_object(struct mem_ctl_info *mci, | |||
612 | device_initialize(&dimm->dev); | 609 | device_initialize(&dimm->dev); |
613 | 610 | ||
614 | dimm->dev.parent = &mci->dev; | 611 | dimm->dev.parent = &mci->dev; |
615 | if (mci->mem_is_per_rank) | 612 | if (mci->csbased) |
616 | dev_set_name(&dimm->dev, "rank%d", index); | 613 | dev_set_name(&dimm->dev, "rank%d", index); |
617 | else | 614 | else |
618 | dev_set_name(&dimm->dev, "dimm%d", index); | 615 | dev_set_name(&dimm->dev, "dimm%d", index); |
@@ -778,14 +775,10 @@ static ssize_t mci_size_mb_show(struct device *dev, | |||
778 | for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { | 775 | for (csrow_idx = 0; csrow_idx < mci->nr_csrows; csrow_idx++) { |
779 | struct csrow_info *csrow = mci->csrows[csrow_idx]; | 776 | struct csrow_info *csrow = mci->csrows[csrow_idx]; |
780 | 777 | ||
781 | if (csrow->mci->csbased) { | 778 | for (j = 0; j < csrow->nr_channels; j++) { |
782 | total_pages += csrow->nr_pages; | 779 | struct dimm_info *dimm = csrow->channels[j]->dimm; |
783 | } else { | ||
784 | for (j = 0; j < csrow->nr_channels; j++) { | ||
785 | struct dimm_info *dimm = csrow->channels[j]->dimm; | ||
786 | 780 | ||
787 | total_pages += dimm->nr_pages; | 781 | total_pages += dimm->nr_pages; |
788 | } | ||
789 | } | 782 | } |
790 | } | 783 | } |
791 | 784 | ||
diff --git a/drivers/extcon/extcon-max77693.c b/drivers/extcon/extcon-max77693.c index b70e3815c459..8f3c947b0029 100644 --- a/drivers/extcon/extcon-max77693.c +++ b/drivers/extcon/extcon-max77693.c | |||
@@ -32,6 +32,38 @@ | |||
32 | #define DEV_NAME "max77693-muic" | 32 | #define DEV_NAME "max77693-muic" |
33 | #define DELAY_MS_DEFAULT 20000 /* unit: millisecond */ | 33 | #define DELAY_MS_DEFAULT 20000 /* unit: millisecond */ |
34 | 34 | ||
35 | /* | ||
36 | * Default value of MAX77693 register to bring up MUIC device. | ||
37 | * If user don't set some initial value for MUIC device through platform data, | ||
38 | * extcon-max77693 driver use 'default_init_data' to bring up base operation | ||
39 | * of MAX77693 MUIC device. | ||
40 | */ | ||
41 | struct max77693_reg_data default_init_data[] = { | ||
42 | { | ||
43 | /* STATUS2 - [3]ChgDetRun */ | ||
44 | .addr = MAX77693_MUIC_REG_STATUS2, | ||
45 | .data = STATUS2_CHGDETRUN_MASK, | ||
46 | }, { | ||
47 | /* INTMASK1 - Unmask [3]ADC1KM,[0]ADCM */ | ||
48 | .addr = MAX77693_MUIC_REG_INTMASK1, | ||
49 | .data = INTMASK1_ADC1K_MASK | ||
50 | | INTMASK1_ADC_MASK, | ||
51 | }, { | ||
52 | /* INTMASK2 - Unmask [0]ChgTypM */ | ||
53 | .addr = MAX77693_MUIC_REG_INTMASK2, | ||
54 | .data = INTMASK2_CHGTYP_MASK, | ||
55 | }, { | ||
56 | /* INTMASK3 - Mask all of interrupts */ | ||
57 | .addr = MAX77693_MUIC_REG_INTMASK3, | ||
58 | .data = 0x0, | ||
59 | }, { | ||
60 | /* CDETCTRL2 */ | ||
61 | .addr = MAX77693_MUIC_REG_CDETCTRL2, | ||
62 | .data = CDETCTRL2_VIDRMEN_MASK | ||
63 | | CDETCTRL2_DXOVPEN_MASK, | ||
64 | }, | ||
65 | }; | ||
66 | |||
35 | enum max77693_muic_adc_debounce_time { | 67 | enum max77693_muic_adc_debounce_time { |
36 | ADC_DEBOUNCE_TIME_5MS = 0, | 68 | ADC_DEBOUNCE_TIME_5MS = 0, |
37 | ADC_DEBOUNCE_TIME_10MS, | 69 | ADC_DEBOUNCE_TIME_10MS, |
@@ -1045,8 +1077,9 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1045 | { | 1077 | { |
1046 | struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); | 1078 | struct max77693_dev *max77693 = dev_get_drvdata(pdev->dev.parent); |
1047 | struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); | 1079 | struct max77693_platform_data *pdata = dev_get_platdata(max77693->dev); |
1048 | struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; | ||
1049 | struct max77693_muic_info *info; | 1080 | struct max77693_muic_info *info; |
1081 | struct max77693_reg_data *init_data; | ||
1082 | int num_init_data; | ||
1050 | int delay_jiffies; | 1083 | int delay_jiffies; |
1051 | int ret; | 1084 | int ret; |
1052 | int i; | 1085 | int i; |
@@ -1145,15 +1178,25 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1145 | goto err_irq; | 1178 | goto err_irq; |
1146 | } | 1179 | } |
1147 | 1180 | ||
1148 | /* Initialize MUIC register by using platform data */ | 1181 | |
1149 | for (i = 0 ; i < muic_pdata->num_init_data ; i++) { | 1182 | /* Initialize MUIC register by using platform data or default data */ |
1150 | enum max77693_irq_source irq_src = MAX77693_IRQ_GROUP_NR; | 1183 | if (pdata->muic_data) { |
1184 | init_data = pdata->muic_data->init_data; | ||
1185 | num_init_data = pdata->muic_data->num_init_data; | ||
1186 | } else { | ||
1187 | init_data = default_init_data; | ||
1188 | num_init_data = ARRAY_SIZE(default_init_data); | ||
1189 | } | ||
1190 | |||
1191 | for (i = 0 ; i < num_init_data ; i++) { | ||
1192 | enum max77693_irq_source irq_src | ||
1193 | = MAX77693_IRQ_GROUP_NR; | ||
1151 | 1194 | ||
1152 | max77693_write_reg(info->max77693->regmap_muic, | 1195 | max77693_write_reg(info->max77693->regmap_muic, |
1153 | muic_pdata->init_data[i].addr, | 1196 | init_data[i].addr, |
1154 | muic_pdata->init_data[i].data); | 1197 | init_data[i].data); |
1155 | 1198 | ||
1156 | switch (muic_pdata->init_data[i].addr) { | 1199 | switch (init_data[i].addr) { |
1157 | case MAX77693_MUIC_REG_INTMASK1: | 1200 | case MAX77693_MUIC_REG_INTMASK1: |
1158 | irq_src = MUIC_INT1; | 1201 | irq_src = MUIC_INT1; |
1159 | break; | 1202 | break; |
@@ -1167,22 +1210,40 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1167 | 1210 | ||
1168 | if (irq_src < MAX77693_IRQ_GROUP_NR) | 1211 | if (irq_src < MAX77693_IRQ_GROUP_NR) |
1169 | info->max77693->irq_masks_cur[irq_src] | 1212 | info->max77693->irq_masks_cur[irq_src] |
1170 | = muic_pdata->init_data[i].data; | 1213 | = init_data[i].data; |
1171 | } | 1214 | } |
1172 | 1215 | ||
1173 | /* | 1216 | if (pdata->muic_data) { |
1174 | * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB | 1217 | struct max77693_muic_platform_data *muic_pdata = pdata->muic_data; |
1175 | * h/w path of COMP2/COMN1 on CONTROL1 register. | ||
1176 | */ | ||
1177 | if (muic_pdata->path_uart) | ||
1178 | info->path_uart = muic_pdata->path_uart; | ||
1179 | else | ||
1180 | info->path_uart = CONTROL1_SW_UART; | ||
1181 | 1218 | ||
1182 | if (muic_pdata->path_usb) | 1219 | /* |
1183 | info->path_usb = muic_pdata->path_usb; | 1220 | * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB |
1184 | else | 1221 | * h/w path of COMP2/COMN1 on CONTROL1 register. |
1222 | */ | ||
1223 | if (muic_pdata->path_uart) | ||
1224 | info->path_uart = muic_pdata->path_uart; | ||
1225 | else | ||
1226 | info->path_uart = CONTROL1_SW_UART; | ||
1227 | |||
1228 | if (muic_pdata->path_usb) | ||
1229 | info->path_usb = muic_pdata->path_usb; | ||
1230 | else | ||
1231 | info->path_usb = CONTROL1_SW_USB; | ||
1232 | |||
1233 | /* | ||
1234 | * Default delay time for detecting cable state | ||
1235 | * after certain time. | ||
1236 | */ | ||
1237 | if (muic_pdata->detcable_delay_ms) | ||
1238 | delay_jiffies = | ||
1239 | msecs_to_jiffies(muic_pdata->detcable_delay_ms); | ||
1240 | else | ||
1241 | delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); | ||
1242 | } else { | ||
1185 | info->path_usb = CONTROL1_SW_USB; | 1243 | info->path_usb = CONTROL1_SW_USB; |
1244 | info->path_uart = CONTROL1_SW_UART; | ||
1245 | delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); | ||
1246 | } | ||
1186 | 1247 | ||
1187 | /* Set initial path for UART */ | 1248 | /* Set initial path for UART */ |
1188 | max77693_muic_set_path(info, info->path_uart, true); | 1249 | max77693_muic_set_path(info, info->path_uart, true); |
@@ -1208,10 +1269,6 @@ static int max77693_muic_probe(struct platform_device *pdev) | |||
1208 | * driver should notify cable state to upper layer. | 1269 | * driver should notify cable state to upper layer. |
1209 | */ | 1270 | */ |
1210 | INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); | 1271 | INIT_DELAYED_WORK(&info->wq_detcable, max77693_muic_detect_cable_wq); |
1211 | if (muic_pdata->detcable_delay_ms) | ||
1212 | delay_jiffies = msecs_to_jiffies(muic_pdata->detcable_delay_ms); | ||
1213 | else | ||
1214 | delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); | ||
1215 | schedule_delayed_work(&info->wq_detcable, delay_jiffies); | 1272 | schedule_delayed_work(&info->wq_detcable, delay_jiffies); |
1216 | 1273 | ||
1217 | return ret; | 1274 | return ret; |
diff --git a/drivers/extcon/extcon-max8997.c b/drivers/extcon/extcon-max8997.c index e636d950ad6c..69641bcae325 100644 --- a/drivers/extcon/extcon-max8997.c +++ b/drivers/extcon/extcon-max8997.c | |||
@@ -712,29 +712,45 @@ static int max8997_muic_probe(struct platform_device *pdev) | |||
712 | goto err_irq; | 712 | goto err_irq; |
713 | } | 713 | } |
714 | 714 | ||
715 | /* Initialize registers according to platform data */ | ||
716 | if (pdata->muic_pdata) { | 715 | if (pdata->muic_pdata) { |
717 | struct max8997_muic_platform_data *mdata = info->muic_pdata; | 716 | struct max8997_muic_platform_data *muic_pdata |
718 | 717 | = pdata->muic_pdata; | |
719 | for (i = 0; i < mdata->num_init_data; i++) { | 718 | |
720 | max8997_write_reg(info->muic, mdata->init_data[i].addr, | 719 | /* Initialize registers according to platform data */ |
721 | mdata->init_data[i].data); | 720 | for (i = 0; i < muic_pdata->num_init_data; i++) { |
721 | max8997_write_reg(info->muic, | ||
722 | muic_pdata->init_data[i].addr, | ||
723 | muic_pdata->init_data[i].data); | ||
722 | } | 724 | } |
723 | } | ||
724 | 725 | ||
725 | /* | 726 | /* |
726 | * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB | 727 | * Default usb/uart path whether UART/USB or AUX_UART/AUX_USB |
727 | * h/w path of COMP2/COMN1 on CONTROL1 register. | 728 | * h/w path of COMP2/COMN1 on CONTROL1 register. |
728 | */ | 729 | */ |
729 | if (pdata->muic_pdata->path_uart) | 730 | if (muic_pdata->path_uart) |
730 | info->path_uart = pdata->muic_pdata->path_uart; | 731 | info->path_uart = muic_pdata->path_uart; |
731 | else | 732 | else |
732 | info->path_uart = CONTROL1_SW_UART; | 733 | info->path_uart = CONTROL1_SW_UART; |
733 | 734 | ||
734 | if (pdata->muic_pdata->path_usb) | 735 | if (muic_pdata->path_usb) |
735 | info->path_usb = pdata->muic_pdata->path_usb; | 736 | info->path_usb = muic_pdata->path_usb; |
736 | else | 737 | else |
738 | info->path_usb = CONTROL1_SW_USB; | ||
739 | |||
740 | /* | ||
741 | * Default delay time for detecting cable state | ||
742 | * after certain time. | ||
743 | */ | ||
744 | if (muic_pdata->detcable_delay_ms) | ||
745 | delay_jiffies = | ||
746 | msecs_to_jiffies(muic_pdata->detcable_delay_ms); | ||
747 | else | ||
748 | delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); | ||
749 | } else { | ||
750 | info->path_uart = CONTROL1_SW_UART; | ||
737 | info->path_usb = CONTROL1_SW_USB; | 751 | info->path_usb = CONTROL1_SW_USB; |
752 | delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); | ||
753 | } | ||
738 | 754 | ||
739 | /* Set initial path for UART */ | 755 | /* Set initial path for UART */ |
740 | max8997_muic_set_path(info, info->path_uart, true); | 756 | max8997_muic_set_path(info, info->path_uart, true); |
@@ -751,10 +767,6 @@ static int max8997_muic_probe(struct platform_device *pdev) | |||
751 | * driver should notify cable state to upper layer. | 767 | * driver should notify cable state to upper layer. |
752 | */ | 768 | */ |
753 | INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq); | 769 | INIT_DELAYED_WORK(&info->wq_detcable, max8997_muic_detect_cable_wq); |
754 | if (pdata->muic_pdata->detcable_delay_ms) | ||
755 | delay_jiffies = msecs_to_jiffies(pdata->muic_pdata->detcable_delay_ms); | ||
756 | else | ||
757 | delay_jiffies = msecs_to_jiffies(DELAY_MS_DEFAULT); | ||
758 | schedule_delayed_work(&info->wq_detcable, delay_jiffies); | 770 | schedule_delayed_work(&info->wq_detcable, delay_jiffies); |
759 | 771 | ||
760 | return 0; | 772 | return 0; |
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index 9b00072a020f..42c759a4d047 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig | |||
@@ -53,6 +53,24 @@ config EFI_VARS | |||
53 | Subsequent efibootmgr releases may be found at: | 53 | Subsequent efibootmgr releases may be found at: |
54 | <http://linux.dell.com/efibootmgr> | 54 | <http://linux.dell.com/efibootmgr> |
55 | 55 | ||
56 | config EFI_VARS_PSTORE | ||
57 | bool "Register efivars backend for pstore" | ||
58 | depends on EFI_VARS && PSTORE | ||
59 | default y | ||
60 | help | ||
61 | Say Y here to enable use efivars as a backend to pstore. This | ||
62 | will allow writing console messages, crash dumps, or anything | ||
63 | else supported by pstore to EFI variables. | ||
64 | |||
65 | config EFI_VARS_PSTORE_DEFAULT_DISABLE | ||
66 | bool "Disable using efivars as a pstore backend by default" | ||
67 | depends on EFI_VARS_PSTORE | ||
68 | default n | ||
69 | help | ||
70 | Saying Y here will disable the use of efivars as a storage | ||
71 | backend for pstore by default. This setting can be overridden | ||
72 | using the efivars module's pstore_disable parameter. | ||
73 | |||
56 | config EFI_PCDP | 74 | config EFI_PCDP |
57 | bool "Console device selection via EFI PCDP or HCDP table" | 75 | bool "Console device selection via EFI PCDP or HCDP table" |
58 | depends on ACPI && EFI && IA64 | 76 | depends on ACPI && EFI && IA64 |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 982f1f5f5742..4cd392dbf115 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
@@ -442,7 +442,6 @@ static int __init dmi_present(const char __iomem *p) | |||
442 | static int __init smbios_present(const char __iomem *p) | 442 | static int __init smbios_present(const char __iomem *p) |
443 | { | 443 | { |
444 | u8 buf[32]; | 444 | u8 buf[32]; |
445 | int offset = 0; | ||
446 | 445 | ||
447 | memcpy_fromio(buf, p, 32); | 446 | memcpy_fromio(buf, p, 32); |
448 | if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { | 447 | if ((buf[5] < 32) && dmi_checksum(buf, buf[5])) { |
@@ -461,9 +460,9 @@ static int __init smbios_present(const char __iomem *p) | |||
461 | dmi_ver = 0x0206; | 460 | dmi_ver = 0x0206; |
462 | break; | 461 | break; |
463 | } | 462 | } |
464 | offset = 16; | 463 | return memcmp(p + 16, "_DMI_", 5) || dmi_present(p + 16); |
465 | } | 464 | } |
466 | return dmi_present(buf + offset); | 465 | return 1; |
467 | } | 466 | } |
468 | 467 | ||
469 | void __init dmi_scan_machine(void) | 468 | void __init dmi_scan_machine(void) |
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 7320bf891706..7acafb80fd4c 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -103,6 +103,11 @@ MODULE_VERSION(EFIVARS_VERSION); | |||
103 | */ | 103 | */ |
104 | #define GUID_LEN 36 | 104 | #define GUID_LEN 36 |
105 | 105 | ||
106 | static bool efivars_pstore_disable = | ||
107 | IS_ENABLED(CONFIG_EFI_VARS_PSTORE_DEFAULT_DISABLE); | ||
108 | |||
109 | module_param_named(pstore_disable, efivars_pstore_disable, bool, 0644); | ||
110 | |||
106 | /* | 111 | /* |
107 | * The maximum size of VariableName + Data = 1024 | 112 | * The maximum size of VariableName + Data = 1024 |
108 | * Therefore, it's reasonable to save that much | 113 | * Therefore, it's reasonable to save that much |
@@ -165,6 +170,7 @@ efivar_create_sysfs_entry(struct efivars *efivars, | |||
165 | 170 | ||
166 | static void efivar_update_sysfs_entries(struct work_struct *); | 171 | static void efivar_update_sysfs_entries(struct work_struct *); |
167 | static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries); | 172 | static DECLARE_WORK(efivar_work, efivar_update_sysfs_entries); |
173 | static bool efivar_wq_enabled = true; | ||
168 | 174 | ||
169 | /* Return the number of unicode characters in data */ | 175 | /* Return the number of unicode characters in data */ |
170 | static unsigned long | 176 | static unsigned long |
@@ -426,6 +432,44 @@ get_var_data(struct efivars *efivars, struct efi_variable *var) | |||
426 | return status; | 432 | return status; |
427 | } | 433 | } |
428 | 434 | ||
435 | static efi_status_t | ||
436 | check_var_size_locked(struct efivars *efivars, u32 attributes, | ||
437 | unsigned long size) | ||
438 | { | ||
439 | u64 storage_size, remaining_size, max_size; | ||
440 | efi_status_t status; | ||
441 | const struct efivar_operations *fops = efivars->ops; | ||
442 | |||
443 | if (!efivars->ops->query_variable_info) | ||
444 | return EFI_UNSUPPORTED; | ||
445 | |||
446 | status = fops->query_variable_info(attributes, &storage_size, | ||
447 | &remaining_size, &max_size); | ||
448 | |||
449 | if (status != EFI_SUCCESS) | ||
450 | return status; | ||
451 | |||
452 | if (!storage_size || size > remaining_size || size > max_size || | ||
453 | (remaining_size - size) < (storage_size / 2)) | ||
454 | return EFI_OUT_OF_RESOURCES; | ||
455 | |||
456 | return status; | ||
457 | } | ||
458 | |||
459 | |||
460 | static efi_status_t | ||
461 | check_var_size(struct efivars *efivars, u32 attributes, unsigned long size) | ||
462 | { | ||
463 | efi_status_t status; | ||
464 | unsigned long flags; | ||
465 | |||
466 | spin_lock_irqsave(&efivars->lock, flags); | ||
467 | status = check_var_size_locked(efivars, attributes, size); | ||
468 | spin_unlock_irqrestore(&efivars->lock, flags); | ||
469 | |||
470 | return status; | ||
471 | } | ||
472 | |||
429 | static ssize_t | 473 | static ssize_t |
430 | efivar_guid_read(struct efivar_entry *entry, char *buf) | 474 | efivar_guid_read(struct efivar_entry *entry, char *buf) |
431 | { | 475 | { |
@@ -547,11 +591,16 @@ efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count) | |||
547 | } | 591 | } |
548 | 592 | ||
549 | spin_lock_irq(&efivars->lock); | 593 | spin_lock_irq(&efivars->lock); |
550 | status = efivars->ops->set_variable(new_var->VariableName, | 594 | |
551 | &new_var->VendorGuid, | 595 | status = check_var_size_locked(efivars, new_var->Attributes, |
552 | new_var->Attributes, | 596 | new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); |
553 | new_var->DataSize, | 597 | |
554 | new_var->Data); | 598 | if (status == EFI_SUCCESS || status == EFI_UNSUPPORTED) |
599 | status = efivars->ops->set_variable(new_var->VariableName, | ||
600 | &new_var->VendorGuid, | ||
601 | new_var->Attributes, | ||
602 | new_var->DataSize, | ||
603 | new_var->Data); | ||
555 | 604 | ||
556 | spin_unlock_irq(&efivars->lock); | 605 | spin_unlock_irq(&efivars->lock); |
557 | 606 | ||
@@ -702,8 +751,7 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
702 | u32 attributes; | 751 | u32 attributes; |
703 | struct inode *inode = file->f_mapping->host; | 752 | struct inode *inode = file->f_mapping->host; |
704 | unsigned long datasize = count - sizeof(attributes); | 753 | unsigned long datasize = count - sizeof(attributes); |
705 | unsigned long newdatasize; | 754 | unsigned long newdatasize, varsize; |
706 | u64 storage_size, remaining_size, max_size; | ||
707 | ssize_t bytes = 0; | 755 | ssize_t bytes = 0; |
708 | 756 | ||
709 | if (count < sizeof(attributes)) | 757 | if (count < sizeof(attributes)) |
@@ -722,28 +770,18 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
722 | * amounts of memory. Pick a default size of 64K if | 770 | * amounts of memory. Pick a default size of 64K if |
723 | * QueryVariableInfo() isn't supported by the firmware. | 771 | * QueryVariableInfo() isn't supported by the firmware. |
724 | */ | 772 | */ |
725 | spin_lock_irq(&efivars->lock); | ||
726 | 773 | ||
727 | if (!efivars->ops->query_variable_info) | 774 | varsize = datasize + utf16_strsize(var->var.VariableName, 1024); |
728 | status = EFI_UNSUPPORTED; | 775 | status = check_var_size(efivars, attributes, varsize); |
729 | else { | ||
730 | const struct efivar_operations *fops = efivars->ops; | ||
731 | status = fops->query_variable_info(attributes, &storage_size, | ||
732 | &remaining_size, &max_size); | ||
733 | } | ||
734 | |||
735 | spin_unlock_irq(&efivars->lock); | ||
736 | 776 | ||
737 | if (status != EFI_SUCCESS) { | 777 | if (status != EFI_SUCCESS) { |
738 | if (status != EFI_UNSUPPORTED) | 778 | if (status != EFI_UNSUPPORTED) |
739 | return efi_status_to_err(status); | 779 | return efi_status_to_err(status); |
740 | 780 | ||
741 | remaining_size = 65536; | 781 | if (datasize > 65536) |
782 | return -ENOSPC; | ||
742 | } | 783 | } |
743 | 784 | ||
744 | if (datasize > remaining_size) | ||
745 | return -ENOSPC; | ||
746 | |||
747 | data = kmalloc(datasize, GFP_KERNEL); | 785 | data = kmalloc(datasize, GFP_KERNEL); |
748 | if (!data) | 786 | if (!data) |
749 | return -ENOMEM; | 787 | return -ENOMEM; |
@@ -765,6 +803,19 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
765 | */ | 803 | */ |
766 | spin_lock_irq(&efivars->lock); | 804 | spin_lock_irq(&efivars->lock); |
767 | 805 | ||
806 | /* | ||
807 | * Ensure that the available space hasn't shrunk below the safe level | ||
808 | */ | ||
809 | |||
810 | status = check_var_size_locked(efivars, attributes, varsize); | ||
811 | |||
812 | if (status != EFI_SUCCESS && status != EFI_UNSUPPORTED) { | ||
813 | spin_unlock_irq(&efivars->lock); | ||
814 | kfree(data); | ||
815 | |||
816 | return efi_status_to_err(status); | ||
817 | } | ||
818 | |||
768 | status = efivars->ops->set_variable(var->var.VariableName, | 819 | status = efivars->ops->set_variable(var->var.VariableName, |
769 | &var->var.VendorGuid, | 820 | &var->var.VendorGuid, |
770 | attributes, datasize, | 821 | attributes, datasize, |
@@ -929,8 +980,8 @@ static bool efivarfs_valid_name(const char *str, int len) | |||
929 | if (len < GUID_LEN + 2) | 980 | if (len < GUID_LEN + 2) |
930 | return false; | 981 | return false; |
931 | 982 | ||
932 | /* GUID should be right after the first '-' */ | 983 | /* GUID must be preceded by a '-' */ |
933 | if (s - 1 != strchr(str, '-')) | 984 | if (*(s - 1) != '-') |
934 | return false; | 985 | return false; |
935 | 986 | ||
936 | /* | 987 | /* |
@@ -1118,15 +1169,22 @@ static struct dentry_operations efivarfs_d_ops = { | |||
1118 | 1169 | ||
1119 | static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name) | 1170 | static struct dentry *efivarfs_alloc_dentry(struct dentry *parent, char *name) |
1120 | { | 1171 | { |
1172 | struct dentry *d; | ||
1121 | struct qstr q; | 1173 | struct qstr q; |
1174 | int err; | ||
1122 | 1175 | ||
1123 | q.name = name; | 1176 | q.name = name; |
1124 | q.len = strlen(name); | 1177 | q.len = strlen(name); |
1125 | 1178 | ||
1126 | if (efivarfs_d_hash(NULL, NULL, &q)) | 1179 | err = efivarfs_d_hash(NULL, NULL, &q); |
1127 | return NULL; | 1180 | if (err) |
1181 | return ERR_PTR(err); | ||
1182 | |||
1183 | d = d_alloc(parent, &q); | ||
1184 | if (d) | ||
1185 | return d; | ||
1128 | 1186 | ||
1129 | return d_alloc(parent, &q); | 1187 | return ERR_PTR(-ENOMEM); |
1130 | } | 1188 | } |
1131 | 1189 | ||
1132 | static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | 1190 | static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) |
@@ -1136,6 +1194,7 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
1136 | struct efivar_entry *entry, *n; | 1194 | struct efivar_entry *entry, *n; |
1137 | struct efivars *efivars = &__efivars; | 1195 | struct efivars *efivars = &__efivars; |
1138 | char *name; | 1196 | char *name; |
1197 | int err = -ENOMEM; | ||
1139 | 1198 | ||
1140 | efivarfs_sb = sb; | 1199 | efivarfs_sb = sb; |
1141 | 1200 | ||
@@ -1186,8 +1245,10 @@ static int efivarfs_fill_super(struct super_block *sb, void *data, int silent) | |||
1186 | goto fail_name; | 1245 | goto fail_name; |
1187 | 1246 | ||
1188 | dentry = efivarfs_alloc_dentry(root, name); | 1247 | dentry = efivarfs_alloc_dentry(root, name); |
1189 | if (!dentry) | 1248 | if (IS_ERR(dentry)) { |
1249 | err = PTR_ERR(dentry); | ||
1190 | goto fail_inode; | 1250 | goto fail_inode; |
1251 | } | ||
1191 | 1252 | ||
1192 | /* copied by the above to local storage in the dentry. */ | 1253 | /* copied by the above to local storage in the dentry. */ |
1193 | kfree(name); | 1254 | kfree(name); |
@@ -1214,7 +1275,7 @@ fail_inode: | |||
1214 | fail_name: | 1275 | fail_name: |
1215 | kfree(name); | 1276 | kfree(name); |
1216 | fail: | 1277 | fail: |
1217 | return -ENOMEM; | 1278 | return err; |
1218 | } | 1279 | } |
1219 | 1280 | ||
1220 | static struct dentry *efivarfs_mount(struct file_system_type *fs_type, | 1281 | static struct dentry *efivarfs_mount(struct file_system_type *fs_type, |
@@ -1234,6 +1295,7 @@ static struct file_system_type efivarfs_type = { | |||
1234 | .mount = efivarfs_mount, | 1295 | .mount = efivarfs_mount, |
1235 | .kill_sb = efivarfs_kill_sb, | 1296 | .kill_sb = efivarfs_kill_sb, |
1236 | }; | 1297 | }; |
1298 | MODULE_ALIAS_FS("efivarfs"); | ||
1237 | 1299 | ||
1238 | /* | 1300 | /* |
1239 | * Handle negative dentry. | 1301 | * Handle negative dentry. |
@@ -1253,9 +1315,7 @@ static const struct inode_operations efivarfs_dir_inode_operations = { | |||
1253 | .create = efivarfs_create, | 1315 | .create = efivarfs_create, |
1254 | }; | 1316 | }; |
1255 | 1317 | ||
1256 | static struct pstore_info efi_pstore_info; | 1318 | #ifdef CONFIG_EFI_VARS_PSTORE |
1257 | |||
1258 | #ifdef CONFIG_PSTORE | ||
1259 | 1319 | ||
1260 | static int efi_pstore_open(struct pstore_info *psi) | 1320 | static int efi_pstore_open(struct pstore_info *psi) |
1261 | { | 1321 | { |
@@ -1345,7 +1405,6 @@ static int efi_pstore_write(enum pstore_type_id type, | |||
1345 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; | 1405 | efi_guid_t vendor = LINUX_EFI_CRASH_GUID; |
1346 | struct efivars *efivars = psi->data; | 1406 | struct efivars *efivars = psi->data; |
1347 | int i, ret = 0; | 1407 | int i, ret = 0; |
1348 | u64 storage_space, remaining_space, max_variable_size; | ||
1349 | efi_status_t status = EFI_NOT_FOUND; | 1408 | efi_status_t status = EFI_NOT_FOUND; |
1350 | unsigned long flags; | 1409 | unsigned long flags; |
1351 | 1410 | ||
@@ -1365,11 +1424,11 @@ static int efi_pstore_write(enum pstore_type_id type, | |||
1365 | * size: a size of logging data | 1424 | * size: a size of logging data |
1366 | * DUMP_NAME_LEN * 2: a maximum size of variable name | 1425 | * DUMP_NAME_LEN * 2: a maximum size of variable name |
1367 | */ | 1426 | */ |
1368 | status = efivars->ops->query_variable_info(PSTORE_EFI_ATTRIBUTES, | 1427 | |
1369 | &storage_space, | 1428 | status = check_var_size_locked(efivars, PSTORE_EFI_ATTRIBUTES, |
1370 | &remaining_space, | 1429 | size + DUMP_NAME_LEN * 2); |
1371 | &max_variable_size); | 1430 | |
1372 | if (status || remaining_space < size + DUMP_NAME_LEN * 2) { | 1431 | if (status) { |
1373 | spin_unlock_irqrestore(&efivars->lock, flags); | 1432 | spin_unlock_irqrestore(&efivars->lock, flags); |
1374 | *id = part; | 1433 | *id = part; |
1375 | return -ENOSPC; | 1434 | return -ENOSPC; |
@@ -1386,7 +1445,7 @@ static int efi_pstore_write(enum pstore_type_id type, | |||
1386 | 1445 | ||
1387 | spin_unlock_irqrestore(&efivars->lock, flags); | 1446 | spin_unlock_irqrestore(&efivars->lock, flags); |
1388 | 1447 | ||
1389 | if (reason == KMSG_DUMP_OOPS) | 1448 | if (reason == KMSG_DUMP_OOPS && efivar_wq_enabled) |
1390 | schedule_work(&efivar_work); | 1449 | schedule_work(&efivar_work); |
1391 | 1450 | ||
1392 | *id = part; | 1451 | *id = part; |
@@ -1459,38 +1518,6 @@ static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, | |||
1459 | 1518 | ||
1460 | return 0; | 1519 | return 0; |
1461 | } | 1520 | } |
1462 | #else | ||
1463 | static int efi_pstore_open(struct pstore_info *psi) | ||
1464 | { | ||
1465 | return 0; | ||
1466 | } | ||
1467 | |||
1468 | static int efi_pstore_close(struct pstore_info *psi) | ||
1469 | { | ||
1470 | return 0; | ||
1471 | } | ||
1472 | |||
1473 | static ssize_t efi_pstore_read(u64 *id, enum pstore_type_id *type, int *count, | ||
1474 | struct timespec *timespec, | ||
1475 | char **buf, struct pstore_info *psi) | ||
1476 | { | ||
1477 | return -1; | ||
1478 | } | ||
1479 | |||
1480 | static int efi_pstore_write(enum pstore_type_id type, | ||
1481 | enum kmsg_dump_reason reason, u64 *id, | ||
1482 | unsigned int part, int count, size_t size, | ||
1483 | struct pstore_info *psi) | ||
1484 | { | ||
1485 | return 0; | ||
1486 | } | ||
1487 | |||
1488 | static int efi_pstore_erase(enum pstore_type_id type, u64 id, int count, | ||
1489 | struct timespec time, struct pstore_info *psi) | ||
1490 | { | ||
1491 | return 0; | ||
1492 | } | ||
1493 | #endif | ||
1494 | 1521 | ||
1495 | static struct pstore_info efi_pstore_info = { | 1522 | static struct pstore_info efi_pstore_info = { |
1496 | .owner = THIS_MODULE, | 1523 | .owner = THIS_MODULE, |
@@ -1502,6 +1529,24 @@ static struct pstore_info efi_pstore_info = { | |||
1502 | .erase = efi_pstore_erase, | 1529 | .erase = efi_pstore_erase, |
1503 | }; | 1530 | }; |
1504 | 1531 | ||
1532 | static void efivar_pstore_register(struct efivars *efivars) | ||
1533 | { | ||
1534 | efivars->efi_pstore_info = efi_pstore_info; | ||
1535 | efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); | ||
1536 | if (efivars->efi_pstore_info.buf) { | ||
1537 | efivars->efi_pstore_info.bufsize = 1024; | ||
1538 | efivars->efi_pstore_info.data = efivars; | ||
1539 | spin_lock_init(&efivars->efi_pstore_info.buf_lock); | ||
1540 | pstore_register(&efivars->efi_pstore_info); | ||
1541 | } | ||
1542 | } | ||
1543 | #else | ||
1544 | static void efivar_pstore_register(struct efivars *efivars) | ||
1545 | { | ||
1546 | return; | ||
1547 | } | ||
1548 | #endif | ||
1549 | |||
1505 | static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | 1550 | static ssize_t efivar_create(struct file *filp, struct kobject *kobj, |
1506 | struct bin_attribute *bin_attr, | 1551 | struct bin_attribute *bin_attr, |
1507 | char *buf, loff_t pos, size_t count) | 1552 | char *buf, loff_t pos, size_t count) |
@@ -1544,6 +1589,14 @@ static ssize_t efivar_create(struct file *filp, struct kobject *kobj, | |||
1544 | return -EINVAL; | 1589 | return -EINVAL; |
1545 | } | 1590 | } |
1546 | 1591 | ||
1592 | status = check_var_size_locked(efivars, new_var->Attributes, | ||
1593 | new_var->DataSize + utf16_strsize(new_var->VariableName, 1024)); | ||
1594 | |||
1595 | if (status && status != EFI_UNSUPPORTED) { | ||
1596 | spin_unlock_irq(&efivars->lock); | ||
1597 | return efi_status_to_err(status); | ||
1598 | } | ||
1599 | |||
1547 | /* now *really* create the variable via EFI */ | 1600 | /* now *really* create the variable via EFI */ |
1548 | status = efivars->ops->set_variable(new_var->VariableName, | 1601 | status = efivars->ops->set_variable(new_var->VariableName, |
1549 | &new_var->VendorGuid, | 1602 | &new_var->VendorGuid, |
@@ -1653,6 +1706,31 @@ static bool variable_is_present(efi_char16_t *variable_name, efi_guid_t *vendor) | |||
1653 | return found; | 1706 | return found; |
1654 | } | 1707 | } |
1655 | 1708 | ||
1709 | /* | ||
1710 | * Returns the size of variable_name, in bytes, including the | ||
1711 | * terminating NULL character, or variable_name_size if no NULL | ||
1712 | * character is found among the first variable_name_size bytes. | ||
1713 | */ | ||
1714 | static unsigned long var_name_strnsize(efi_char16_t *variable_name, | ||
1715 | unsigned long variable_name_size) | ||
1716 | { | ||
1717 | unsigned long len; | ||
1718 | efi_char16_t c; | ||
1719 | |||
1720 | /* | ||
1721 | * The variable name is, by definition, a NULL-terminated | ||
1722 | * string, so make absolutely sure that variable_name_size is | ||
1723 | * the value we expect it to be. If not, return the real size. | ||
1724 | */ | ||
1725 | for (len = 2; len <= variable_name_size; len += sizeof(c)) { | ||
1726 | c = variable_name[(len / sizeof(c)) - 1]; | ||
1727 | if (!c) | ||
1728 | break; | ||
1729 | } | ||
1730 | |||
1731 | return min(len, variable_name_size); | ||
1732 | } | ||
1733 | |||
1656 | static void efivar_update_sysfs_entries(struct work_struct *work) | 1734 | static void efivar_update_sysfs_entries(struct work_struct *work) |
1657 | { | 1735 | { |
1658 | struct efivars *efivars = &__efivars; | 1736 | struct efivars *efivars = &__efivars; |
@@ -1693,10 +1771,13 @@ static void efivar_update_sysfs_entries(struct work_struct *work) | |||
1693 | if (!found) { | 1771 | if (!found) { |
1694 | kfree(variable_name); | 1772 | kfree(variable_name); |
1695 | break; | 1773 | break; |
1696 | } else | 1774 | } else { |
1775 | variable_name_size = var_name_strnsize(variable_name, | ||
1776 | variable_name_size); | ||
1697 | efivar_create_sysfs_entry(efivars, | 1777 | efivar_create_sysfs_entry(efivars, |
1698 | variable_name_size, | 1778 | variable_name_size, |
1699 | variable_name, &vendor); | 1779 | variable_name, &vendor); |
1780 | } | ||
1700 | } | 1781 | } |
1701 | } | 1782 | } |
1702 | 1783 | ||
@@ -1895,6 +1976,35 @@ void unregister_efivars(struct efivars *efivars) | |||
1895 | } | 1976 | } |
1896 | EXPORT_SYMBOL_GPL(unregister_efivars); | 1977 | EXPORT_SYMBOL_GPL(unregister_efivars); |
1897 | 1978 | ||
1979 | /* | ||
1980 | * Print a warning when duplicate EFI variables are encountered and | ||
1981 | * disable the sysfs workqueue since the firmware is buggy. | ||
1982 | */ | ||
1983 | static void dup_variable_bug(efi_char16_t *s16, efi_guid_t *vendor_guid, | ||
1984 | unsigned long len16) | ||
1985 | { | ||
1986 | size_t i, len8 = len16 / sizeof(efi_char16_t); | ||
1987 | char *s8; | ||
1988 | |||
1989 | /* | ||
1990 | * Disable the workqueue since the algorithm it uses for | ||
1991 | * detecting new variables won't work with this buggy | ||
1992 | * implementation of GetNextVariableName(). | ||
1993 | */ | ||
1994 | efivar_wq_enabled = false; | ||
1995 | |||
1996 | s8 = kzalloc(len8, GFP_KERNEL); | ||
1997 | if (!s8) | ||
1998 | return; | ||
1999 | |||
2000 | for (i = 0; i < len8; i++) | ||
2001 | s8[i] = s16[i]; | ||
2002 | |||
2003 | printk(KERN_WARNING "efivars: duplicate variable: %s-%pUl\n", | ||
2004 | s8, vendor_guid); | ||
2005 | kfree(s8); | ||
2006 | } | ||
2007 | |||
1898 | int register_efivars(struct efivars *efivars, | 2008 | int register_efivars(struct efivars *efivars, |
1899 | const struct efivar_operations *ops, | 2009 | const struct efivar_operations *ops, |
1900 | struct kobject *parent_kobj) | 2010 | struct kobject *parent_kobj) |
@@ -1943,6 +2053,24 @@ int register_efivars(struct efivars *efivars, | |||
1943 | &vendor_guid); | 2053 | &vendor_guid); |
1944 | switch (status) { | 2054 | switch (status) { |
1945 | case EFI_SUCCESS: | 2055 | case EFI_SUCCESS: |
2056 | variable_name_size = var_name_strnsize(variable_name, | ||
2057 | variable_name_size); | ||
2058 | |||
2059 | /* | ||
2060 | * Some firmware implementations return the | ||
2061 | * same variable name on multiple calls to | ||
2062 | * get_next_variable(). Terminate the loop | ||
2063 | * immediately as there is no guarantee that | ||
2064 | * we'll ever see a different variable name, | ||
2065 | * and may end up looping here forever. | ||
2066 | */ | ||
2067 | if (variable_is_present(variable_name, &vendor_guid)) { | ||
2068 | dup_variable_bug(variable_name, &vendor_guid, | ||
2069 | variable_name_size); | ||
2070 | status = EFI_NOT_FOUND; | ||
2071 | break; | ||
2072 | } | ||
2073 | |||
1946 | efivar_create_sysfs_entry(efivars, | 2074 | efivar_create_sysfs_entry(efivars, |
1947 | variable_name_size, | 2075 | variable_name_size, |
1948 | variable_name, | 2076 | variable_name, |
@@ -1962,15 +2090,8 @@ int register_efivars(struct efivars *efivars, | |||
1962 | if (error) | 2090 | if (error) |
1963 | unregister_efivars(efivars); | 2091 | unregister_efivars(efivars); |
1964 | 2092 | ||
1965 | efivars->efi_pstore_info = efi_pstore_info; | 2093 | if (!efivars_pstore_disable) |
1966 | 2094 | efivar_pstore_register(efivars); | |
1967 | efivars->efi_pstore_info.buf = kmalloc(4096, GFP_KERNEL); | ||
1968 | if (efivars->efi_pstore_info.buf) { | ||
1969 | efivars->efi_pstore_info.bufsize = 1024; | ||
1970 | efivars->efi_pstore_info.data = efivars; | ||
1971 | spin_lock_init(&efivars->efi_pstore_info.buf_lock); | ||
1972 | pstore_register(&efivars->efi_pstore_info); | ||
1973 | } | ||
1974 | 2095 | ||
1975 | register_filesystem(&efivarfs_type); | 2096 | register_filesystem(&efivarfs_type); |
1976 | 2097 | ||
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 93aaadf99f28..b166e30b3bc4 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig | |||
@@ -227,12 +227,6 @@ config GPIO_TS5500 | |||
227 | blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 | 227 | blocks of the TS-5500: DIO1, DIO2 and the LCD port, and the TS-5600 |
228 | LCD port. | 228 | LCD port. |
229 | 229 | ||
230 | config GPIO_VT8500 | ||
231 | bool "VIA/Wondermedia SoC GPIO Support" | ||
232 | depends on ARCH_VT8500 | ||
233 | help | ||
234 | Say yes here to support the VT8500/WM8505/WM8650 GPIO controller. | ||
235 | |||
236 | config GPIO_XILINX | 230 | config GPIO_XILINX |
237 | bool "Xilinx GPIO support" | 231 | bool "Xilinx GPIO support" |
238 | depends on PPC_OF || MICROBLAZE | 232 | depends on PPC_OF || MICROBLAZE |
diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 22e07bc9fcb5..a274d7df3c8c 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile | |||
@@ -80,7 +80,6 @@ obj-$(CONFIG_GPIO_TWL6040) += gpio-twl6040.o | |||
80 | obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o | 80 | obj-$(CONFIG_GPIO_UCB1400) += gpio-ucb1400.o |
81 | obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o | 81 | obj-$(CONFIG_GPIO_VIPERBOARD) += gpio-viperboard.o |
82 | obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o | 82 | obj-$(CONFIG_GPIO_VR41XX) += gpio-vr41xx.o |
83 | obj-$(CONFIG_GPIO_VT8500) += gpio-vt8500.o | ||
84 | obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o | 83 | obj-$(CONFIG_GPIO_VX855) += gpio-vx855.o |
85 | obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o | 84 | obj-$(CONFIG_GPIO_WM831X) += gpio-wm831x.o |
86 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o | 85 | obj-$(CONFIG_GPIO_WM8350) += gpio-wm8350.o |
diff --git a/drivers/gpio/gpio-ich.c b/drivers/gpio/gpio-ich.c index 6f2306db8591..f9dbd503fc40 100644 --- a/drivers/gpio/gpio-ich.c +++ b/drivers/gpio/gpio-ich.c | |||
@@ -128,9 +128,9 @@ static int ichx_read_bit(int reg, unsigned nr) | |||
128 | return data & (1 << bit) ? 1 : 0; | 128 | return data & (1 << bit) ? 1 : 0; |
129 | } | 129 | } |
130 | 130 | ||
131 | static int ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) | 131 | static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) |
132 | { | 132 | { |
133 | return (ichx_priv.use_gpio & (1 << (nr / 32))) ? 0 : -ENXIO; | 133 | return ichx_priv.use_gpio & (1 << (nr / 32)); |
134 | } | 134 | } |
135 | 135 | ||
136 | static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) | 136 | static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7472182967ce..61a6fde6c089 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <linux/io.h> | 42 | #include <linux/io.h> |
43 | #include <linux/of_irq.h> | 43 | #include <linux/of_irq.h> |
44 | #include <linux/of_device.h> | 44 | #include <linux/of_device.h> |
45 | #include <linux/clk.h> | ||
45 | #include <linux/pinctrl/consumer.h> | 46 | #include <linux/pinctrl/consumer.h> |
46 | 47 | ||
47 | /* | 48 | /* |
@@ -496,6 +497,7 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
496 | struct resource *res; | 497 | struct resource *res; |
497 | struct irq_chip_generic *gc; | 498 | struct irq_chip_generic *gc; |
498 | struct irq_chip_type *ct; | 499 | struct irq_chip_type *ct; |
500 | struct clk *clk; | ||
499 | unsigned int ngpios; | 501 | unsigned int ngpios; |
500 | int soc_variant; | 502 | int soc_variant; |
501 | int i, cpu, id; | 503 | int i, cpu, id; |
@@ -529,6 +531,11 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
529 | return id; | 531 | return id; |
530 | } | 532 | } |
531 | 533 | ||
534 | clk = devm_clk_get(&pdev->dev, NULL); | ||
535 | /* Not all SoCs require a clock.*/ | ||
536 | if (!IS_ERR(clk)) | ||
537 | clk_prepare_enable(clk); | ||
538 | |||
532 | mvchip->soc_variant = soc_variant; | 539 | mvchip->soc_variant = soc_variant; |
533 | mvchip->chip.label = dev_name(&pdev->dev); | 540 | mvchip->chip.label = dev_name(&pdev->dev); |
534 | mvchip->chip.dev = &pdev->dev; | 541 | mvchip->chip.dev = &pdev->dev; |
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 58aa28fb5889..99e0fa49fcbd 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c | |||
@@ -3028,6 +3028,7 @@ static __init int samsung_gpiolib_init(void) | |||
3028 | static const struct of_device_id exynos_pinctrl_ids[] = { | 3028 | static const struct of_device_id exynos_pinctrl_ids[] = { |
3029 | { .compatible = "samsung,exynos4210-pinctrl", }, | 3029 | { .compatible = "samsung,exynos4210-pinctrl", }, |
3030 | { .compatible = "samsung,exynos4x12-pinctrl", }, | 3030 | { .compatible = "samsung,exynos4x12-pinctrl", }, |
3031 | { .compatible = "samsung,exynos5250-pinctrl", }, | ||
3031 | { .compatible = "samsung,exynos5440-pinctrl", }, | 3032 | { .compatible = "samsung,exynos5440-pinctrl", }, |
3032 | }; | 3033 | }; |
3033 | for_each_matching_node(pctrl_np, exynos_pinctrl_ids) | 3034 | for_each_matching_node(pctrl_np, exynos_pinctrl_ids) |
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c index 414ad912232f..e3956359202c 100644 --- a/drivers/gpio/gpio-tegra.c +++ b/drivers/gpio/gpio-tegra.c | |||
@@ -72,6 +72,7 @@ struct tegra_gpio_bank { | |||
72 | u32 oe[4]; | 72 | u32 oe[4]; |
73 | u32 int_enb[4]; | 73 | u32 int_enb[4]; |
74 | u32 int_lvl[4]; | 74 | u32 int_lvl[4]; |
75 | u32 wake_enb[4]; | ||
75 | #endif | 76 | #endif |
76 | }; | 77 | }; |
77 | 78 | ||
@@ -333,15 +334,31 @@ static int tegra_gpio_suspend(struct device *dev) | |||
333 | bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); | 334 | bank->oe[p] = tegra_gpio_readl(GPIO_OE(gpio)); |
334 | bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio)); | 335 | bank->int_enb[p] = tegra_gpio_readl(GPIO_INT_ENB(gpio)); |
335 | bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); | 336 | bank->int_lvl[p] = tegra_gpio_readl(GPIO_INT_LVL(gpio)); |
337 | |||
338 | /* Enable gpio irq for wake up source */ | ||
339 | tegra_gpio_writel(bank->wake_enb[p], | ||
340 | GPIO_INT_ENB(gpio)); | ||
336 | } | 341 | } |
337 | } | 342 | } |
338 | local_irq_restore(flags); | 343 | local_irq_restore(flags); |
339 | return 0; | 344 | return 0; |
340 | } | 345 | } |
341 | 346 | ||
342 | static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable) | 347 | static int tegra_gpio_irq_set_wake(struct irq_data *d, unsigned int enable) |
343 | { | 348 | { |
344 | struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); | 349 | struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d); |
350 | int gpio = d->hwirq; | ||
351 | u32 port, bit, mask; | ||
352 | |||
353 | port = GPIO_PORT(gpio); | ||
354 | bit = GPIO_BIT(gpio); | ||
355 | mask = BIT(bit); | ||
356 | |||
357 | if (enable) | ||
358 | bank->wake_enb[port] |= mask; | ||
359 | else | ||
360 | bank->wake_enb[port] &= ~mask; | ||
361 | |||
345 | return irq_set_irq_wake(bank->irq, enable); | 362 | return irq_set_irq_wake(bank->irq, enable); |
346 | } | 363 | } |
347 | #endif | 364 | #endif |
@@ -353,7 +370,7 @@ static struct irq_chip tegra_gpio_irq_chip = { | |||
353 | .irq_unmask = tegra_gpio_irq_unmask, | 370 | .irq_unmask = tegra_gpio_irq_unmask, |
354 | .irq_set_type = tegra_gpio_irq_set_type, | 371 | .irq_set_type = tegra_gpio_irq_set_type, |
355 | #ifdef CONFIG_PM_SLEEP | 372 | #ifdef CONFIG_PM_SLEEP |
356 | .irq_set_wake = tegra_gpio_wake_enable, | 373 | .irq_set_wake = tegra_gpio_irq_set_wake, |
357 | #endif | 374 | #endif |
358 | }; | 375 | }; |
359 | 376 | ||
diff --git a/drivers/gpio/gpio-vt8500.c b/drivers/gpio/gpio-vt8500.c deleted file mode 100644 index 81683ca35ac1..000000000000 --- a/drivers/gpio/gpio-vt8500.c +++ /dev/null | |||
@@ -1,355 +0,0 @@ | |||
1 | /* drivers/gpio/gpio-vt8500.c | ||
2 | * | ||
3 | * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz> | ||
4 | * Based on arch/arm/mach-vt8500/gpio.c: | ||
5 | * - Copyright (C) 2010 Alexey Charkov <alchark@gmail.com> | ||
6 | * | ||
7 | * This software is licensed under the terms of the GNU General Public | ||
8 | * License version 2, as published by the Free Software Foundation, and | ||
9 | * may be copied, distributed, and modified under those terms. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | */ | ||
17 | |||
18 | #include <linux/module.h> | ||
19 | #include <linux/err.h> | ||
20 | #include <linux/io.h> | ||
21 | #include <linux/gpio.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/bitops.h> | ||
24 | #include <linux/of.h> | ||
25 | #include <linux/of_address.h> | ||
26 | #include <linux/of_irq.h> | ||
27 | #include <linux/of_device.h> | ||
28 | |||
29 | /* | ||
30 | We handle GPIOs by bank, each bank containing up to 32 GPIOs covered | ||
31 | by one set of registers (although not all may be valid). | ||
32 | |||
33 | Because different SoC's have different register offsets, we pass the | ||
34 | register offsets as data in vt8500_gpio_dt_ids[]. | ||
35 | |||
36 | A value of NO_REG is used to indicate that this register is not | ||
37 | supported. Only used for ->en at the moment. | ||
38 | */ | ||
39 | |||
40 | #define NO_REG 0xFFFF | ||
41 | |||
42 | /* | ||
43 | * struct vt8500_gpio_bank_regoffsets | ||
44 | * @en: offset to enable register of the bank | ||
45 | * @dir: offset to direction register of the bank | ||
46 | * @data_out: offset to the data out register of the bank | ||
47 | * @data_in: offset to the data in register of the bank | ||
48 | * @ngpio: highest valid pin in this bank | ||
49 | */ | ||
50 | |||
51 | struct vt8500_gpio_bank_regoffsets { | ||
52 | unsigned int en; | ||
53 | unsigned int dir; | ||
54 | unsigned int data_out; | ||
55 | unsigned int data_in; | ||
56 | unsigned char ngpio; | ||
57 | }; | ||
58 | |||
59 | struct vt8500_gpio_data { | ||
60 | unsigned int num_banks; | ||
61 | struct vt8500_gpio_bank_regoffsets banks[]; | ||
62 | }; | ||
63 | |||
64 | #define VT8500_BANK(__en, __dir, __out, __in, __ngpio) \ | ||
65 | { \ | ||
66 | .en = __en, \ | ||
67 | .dir = __dir, \ | ||
68 | .data_out = __out, \ | ||
69 | .data_in = __in, \ | ||
70 | .ngpio = __ngpio, \ | ||
71 | } | ||
72 | |||
73 | static struct vt8500_gpio_data vt8500_data = { | ||
74 | .num_banks = 7, | ||
75 | .banks = { | ||
76 | VT8500_BANK(NO_REG, 0x3C, 0x5C, 0x7C, 9), | ||
77 | VT8500_BANK(0x00, 0x20, 0x40, 0x60, 26), | ||
78 | VT8500_BANK(0x04, 0x24, 0x44, 0x64, 28), | ||
79 | VT8500_BANK(0x08, 0x28, 0x48, 0x68, 31), | ||
80 | VT8500_BANK(0x0C, 0x2C, 0x4C, 0x6C, 19), | ||
81 | VT8500_BANK(0x10, 0x30, 0x50, 0x70, 19), | ||
82 | VT8500_BANK(0x14, 0x34, 0x54, 0x74, 23), | ||
83 | }, | ||
84 | }; | ||
85 | |||
86 | static struct vt8500_gpio_data wm8505_data = { | ||
87 | .num_banks = 10, | ||
88 | .banks = { | ||
89 | VT8500_BANK(0x64, 0x8C, 0xB4, 0xDC, 22), | ||
90 | VT8500_BANK(0x40, 0x68, 0x90, 0xB8, 8), | ||
91 | VT8500_BANK(0x44, 0x6C, 0x94, 0xBC, 32), | ||
92 | VT8500_BANK(0x48, 0x70, 0x98, 0xC0, 6), | ||
93 | VT8500_BANK(0x4C, 0x74, 0x9C, 0xC4, 16), | ||
94 | VT8500_BANK(0x50, 0x78, 0xA0, 0xC8, 25), | ||
95 | VT8500_BANK(0x54, 0x7C, 0xA4, 0xCC, 5), | ||
96 | VT8500_BANK(0x58, 0x80, 0xA8, 0xD0, 5), | ||
97 | VT8500_BANK(0x5C, 0x84, 0xAC, 0xD4, 12), | ||
98 | VT8500_BANK(0x60, 0x88, 0xB0, 0xD8, 16), | ||
99 | VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), | ||
100 | }, | ||
101 | }; | ||
102 | |||
103 | /* | ||
104 | * No information about which bits are valid so we just make | ||
105 | * them all available until its figured out. | ||
106 | */ | ||
107 | static struct vt8500_gpio_data wm8650_data = { | ||
108 | .num_banks = 9, | ||
109 | .banks = { | ||
110 | VT8500_BANK(0x40, 0x80, 0xC0, 0x00, 32), | ||
111 | VT8500_BANK(0x44, 0x84, 0xC4, 0x04, 32), | ||
112 | VT8500_BANK(0x48, 0x88, 0xC8, 0x08, 32), | ||
113 | VT8500_BANK(0x4C, 0x8C, 0xCC, 0x0C, 32), | ||
114 | VT8500_BANK(0x50, 0x90, 0xD0, 0x10, 32), | ||
115 | VT8500_BANK(0x54, 0x94, 0xD4, 0x14, 32), | ||
116 | VT8500_BANK(0x58, 0x98, 0xD8, 0x18, 32), | ||
117 | VT8500_BANK(0x5C, 0x9C, 0xDC, 0x1C, 32), | ||
118 | VT8500_BANK(0x7C, 0xBC, 0xFC, 0x3C, 32), | ||
119 | VT8500_BANK(0x500, 0x504, 0x508, 0x50C, 6), | ||
120 | }, | ||
121 | }; | ||
122 | |||
123 | struct vt8500_gpio_chip { | ||
124 | struct gpio_chip chip; | ||
125 | |||
126 | const struct vt8500_gpio_bank_regoffsets *regs; | ||
127 | void __iomem *base; | ||
128 | }; | ||
129 | |||
130 | struct vt8500_data { | ||
131 | struct vt8500_gpio_chip *chip; | ||
132 | void __iomem *iobase; | ||
133 | int num_banks; | ||
134 | }; | ||
135 | |||
136 | |||
137 | #define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip) | ||
138 | |||
139 | static int vt8500_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
140 | { | ||
141 | u32 val; | ||
142 | struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); | ||
143 | |||
144 | if (vt8500_chip->regs->en == NO_REG) | ||
145 | return 0; | ||
146 | |||
147 | val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en); | ||
148 | val |= BIT(offset); | ||
149 | writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en); | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static void vt8500_gpio_free(struct gpio_chip *chip, unsigned offset) | ||
155 | { | ||
156 | struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); | ||
157 | u32 val; | ||
158 | |||
159 | if (vt8500_chip->regs->en == NO_REG) | ||
160 | return; | ||
161 | |||
162 | val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->en); | ||
163 | val &= ~BIT(offset); | ||
164 | writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->en); | ||
165 | } | ||
166 | |||
167 | static int vt8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
168 | { | ||
169 | struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); | ||
170 | |||
171 | u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir); | ||
172 | val &= ~BIT(offset); | ||
173 | writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static int vt8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
179 | int value) | ||
180 | { | ||
181 | struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); | ||
182 | |||
183 | u32 val = readl_relaxed(vt8500_chip->base + vt8500_chip->regs->dir); | ||
184 | val |= BIT(offset); | ||
185 | writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->dir); | ||
186 | |||
187 | if (value) { | ||
188 | val = readl_relaxed(vt8500_chip->base + | ||
189 | vt8500_chip->regs->data_out); | ||
190 | val |= BIT(offset); | ||
191 | writel_relaxed(val, vt8500_chip->base + | ||
192 | vt8500_chip->regs->data_out); | ||
193 | } | ||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | static int vt8500_gpio_get_value(struct gpio_chip *chip, unsigned offset) | ||
198 | { | ||
199 | struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); | ||
200 | |||
201 | return (readl_relaxed(vt8500_chip->base + vt8500_chip->regs->data_in) >> | ||
202 | offset) & 1; | ||
203 | } | ||
204 | |||
205 | static void vt8500_gpio_set_value(struct gpio_chip *chip, unsigned offset, | ||
206 | int value) | ||
207 | { | ||
208 | struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip); | ||
209 | |||
210 | u32 val = readl_relaxed(vt8500_chip->base + | ||
211 | vt8500_chip->regs->data_out); | ||
212 | if (value) | ||
213 | val |= BIT(offset); | ||
214 | else | ||
215 | val &= ~BIT(offset); | ||
216 | |||
217 | writel_relaxed(val, vt8500_chip->base + vt8500_chip->regs->data_out); | ||
218 | } | ||
219 | |||
220 | static int vt8500_of_xlate(struct gpio_chip *gc, | ||
221 | const struct of_phandle_args *gpiospec, u32 *flags) | ||
222 | { | ||
223 | /* bank if specificed in gpiospec->args[0] */ | ||
224 | if (flags) | ||
225 | *flags = gpiospec->args[2]; | ||
226 | |||
227 | return gpiospec->args[1]; | ||
228 | } | ||
229 | |||
230 | static int vt8500_add_chips(struct platform_device *pdev, void __iomem *base, | ||
231 | const struct vt8500_gpio_data *data) | ||
232 | { | ||
233 | struct vt8500_data *priv; | ||
234 | struct vt8500_gpio_chip *vtchip; | ||
235 | struct gpio_chip *chip; | ||
236 | int i; | ||
237 | int pin_cnt = 0; | ||
238 | |||
239 | priv = devm_kzalloc(&pdev->dev, sizeof(struct vt8500_data), GFP_KERNEL); | ||
240 | if (!priv) { | ||
241 | dev_err(&pdev->dev, "failed to allocate memory\n"); | ||
242 | return -ENOMEM; | ||
243 | } | ||
244 | |||
245 | priv->chip = devm_kzalloc(&pdev->dev, | ||
246 | sizeof(struct vt8500_gpio_chip) * data->num_banks, | ||
247 | GFP_KERNEL); | ||
248 | if (!priv->chip) { | ||
249 | dev_err(&pdev->dev, "failed to allocate chip memory\n"); | ||
250 | return -ENOMEM; | ||
251 | } | ||
252 | |||
253 | priv->iobase = base; | ||
254 | priv->num_banks = data->num_banks; | ||
255 | platform_set_drvdata(pdev, priv); | ||
256 | |||
257 | vtchip = priv->chip; | ||
258 | |||
259 | for (i = 0; i < data->num_banks; i++) { | ||
260 | vtchip[i].base = base; | ||
261 | vtchip[i].regs = &data->banks[i]; | ||
262 | |||
263 | chip = &vtchip[i].chip; | ||
264 | |||
265 | chip->of_xlate = vt8500_of_xlate; | ||
266 | chip->of_gpio_n_cells = 3; | ||
267 | chip->of_node = pdev->dev.of_node; | ||
268 | |||
269 | chip->request = vt8500_gpio_request; | ||
270 | chip->free = vt8500_gpio_free; | ||
271 | chip->direction_input = vt8500_gpio_direction_input; | ||
272 | chip->direction_output = vt8500_gpio_direction_output; | ||
273 | chip->get = vt8500_gpio_get_value; | ||
274 | chip->set = vt8500_gpio_set_value; | ||
275 | chip->can_sleep = 0; | ||
276 | chip->base = pin_cnt; | ||
277 | chip->ngpio = data->banks[i].ngpio; | ||
278 | |||
279 | pin_cnt += data->banks[i].ngpio; | ||
280 | |||
281 | gpiochip_add(chip); | ||
282 | } | ||
283 | return 0; | ||
284 | } | ||
285 | |||
286 | static struct of_device_id vt8500_gpio_dt_ids[] = { | ||
287 | { .compatible = "via,vt8500-gpio", .data = &vt8500_data, }, | ||
288 | { .compatible = "wm,wm8505-gpio", .data = &wm8505_data, }, | ||
289 | { .compatible = "wm,wm8650-gpio", .data = &wm8650_data, }, | ||
290 | { /* Sentinel */ }, | ||
291 | }; | ||
292 | |||
293 | static int vt8500_gpio_probe(struct platform_device *pdev) | ||
294 | { | ||
295 | int ret; | ||
296 | void __iomem *gpio_base; | ||
297 | struct resource *res; | ||
298 | const struct of_device_id *of_id = | ||
299 | of_match_device(vt8500_gpio_dt_ids, &pdev->dev); | ||
300 | |||
301 | if (!of_id) { | ||
302 | dev_err(&pdev->dev, "No matching driver data\n"); | ||
303 | return -ENODEV; | ||
304 | } | ||
305 | |||
306 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
307 | if (!res) { | ||
308 | dev_err(&pdev->dev, "Unable to get IO resource\n"); | ||
309 | return -ENODEV; | ||
310 | } | ||
311 | |||
312 | gpio_base = devm_request_and_ioremap(&pdev->dev, res); | ||
313 | if (!gpio_base) { | ||
314 | dev_err(&pdev->dev, "Unable to map GPIO registers\n"); | ||
315 | return -ENOMEM; | ||
316 | } | ||
317 | |||
318 | ret = vt8500_add_chips(pdev, gpio_base, of_id->data); | ||
319 | |||
320 | return ret; | ||
321 | } | ||
322 | |||
323 | static int vt8500_gpio_remove(struct platform_device *pdev) | ||
324 | { | ||
325 | int i; | ||
326 | int ret; | ||
327 | struct vt8500_data *priv = platform_get_drvdata(pdev); | ||
328 | struct vt8500_gpio_chip *vtchip = priv->chip; | ||
329 | |||
330 | for (i = 0; i < priv->num_banks; i++) { | ||
331 | ret = gpiochip_remove(&vtchip[i].chip); | ||
332 | if (ret) | ||
333 | dev_warn(&pdev->dev, "gpiochip_remove returned %d\n", | ||
334 | ret); | ||
335 | } | ||
336 | |||
337 | return 0; | ||
338 | } | ||
339 | |||
340 | static struct platform_driver vt8500_gpio_driver = { | ||
341 | .probe = vt8500_gpio_probe, | ||
342 | .remove = vt8500_gpio_remove, | ||
343 | .driver = { | ||
344 | .name = "vt8500-gpio", | ||
345 | .owner = THIS_MODULE, | ||
346 | .of_match_table = vt8500_gpio_dt_ids, | ||
347 | }, | ||
348 | }; | ||
349 | |||
350 | module_platform_driver(vt8500_gpio_driver); | ||
351 | |||
352 | MODULE_DESCRIPTION("VT8500 GPIO Driver"); | ||
353 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
354 | MODULE_LICENSE("GPL v2"); | ||
355 | MODULE_DEVICE_TABLE(of, vt8500_gpio_dt_ids); | ||
diff --git a/drivers/gpio/gpiolib-of.c b/drivers/gpio/gpiolib-of.c index a71a54a3e3f7..5150df6cba08 100644 --- a/drivers/gpio/gpiolib-of.c +++ b/drivers/gpio/gpiolib-of.c | |||
@@ -193,7 +193,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) | |||
193 | if (!np) | 193 | if (!np) |
194 | return; | 194 | return; |
195 | 195 | ||
196 | do { | 196 | for (;; index++) { |
197 | ret = of_parse_phandle_with_args(np, "gpio-ranges", | 197 | ret = of_parse_phandle_with_args(np, "gpio-ranges", |
198 | "#gpio-range-cells", index, &pinspec); | 198 | "#gpio-range-cells", index, &pinspec); |
199 | if (ret) | 199 | if (ret) |
@@ -222,8 +222,7 @@ static void of_gpiochip_add_pin_range(struct gpio_chip *chip) | |||
222 | 222 | ||
223 | if (ret) | 223 | if (ret) |
224 | break; | 224 | break; |
225 | 225 | } | |
226 | } while (index++); | ||
227 | } | 226 | } |
228 | 227 | ||
229 | #else | 228 | #else |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index fff9786cdc64..c2534d62911c 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -88,13 +88,14 @@ static int gpiod_request(struct gpio_desc *desc, const char *label); | |||
88 | static void gpiod_free(struct gpio_desc *desc); | 88 | static void gpiod_free(struct gpio_desc *desc); |
89 | static int gpiod_direction_input(struct gpio_desc *desc); | 89 | static int gpiod_direction_input(struct gpio_desc *desc); |
90 | static int gpiod_direction_output(struct gpio_desc *desc, int value); | 90 | static int gpiod_direction_output(struct gpio_desc *desc, int value); |
91 | static int gpiod_get_direction(const struct gpio_desc *desc); | ||
91 | static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); | 92 | static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce); |
92 | static int gpiod_get_value_cansleep(struct gpio_desc *desc); | 93 | static int gpiod_get_value_cansleep(const struct gpio_desc *desc); |
93 | static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); | 94 | static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value); |
94 | static int gpiod_get_value(struct gpio_desc *desc); | 95 | static int gpiod_get_value(const struct gpio_desc *desc); |
95 | static void gpiod_set_value(struct gpio_desc *desc, int value); | 96 | static void gpiod_set_value(struct gpio_desc *desc, int value); |
96 | static int gpiod_cansleep(struct gpio_desc *desc); | 97 | static int gpiod_cansleep(const struct gpio_desc *desc); |
97 | static int gpiod_to_irq(struct gpio_desc *desc); | 98 | static int gpiod_to_irq(const struct gpio_desc *desc); |
98 | static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); | 99 | static int gpiod_export(struct gpio_desc *desc, bool direction_may_change); |
99 | static int gpiod_export_link(struct device *dev, const char *name, | 100 | static int gpiod_export_link(struct device *dev, const char *name, |
100 | struct gpio_desc *desc); | 101 | struct gpio_desc *desc); |
@@ -171,12 +172,12 @@ static int gpio_ensure_requested(struct gpio_desc *desc) | |||
171 | return 0; | 172 | return 0; |
172 | } | 173 | } |
173 | 174 | ||
174 | /* caller holds gpio_lock *OR* gpio is marked as requested */ | 175 | static struct gpio_chip *gpiod_to_chip(const struct gpio_desc *desc) |
175 | static struct gpio_chip *gpiod_to_chip(struct gpio_desc *desc) | ||
176 | { | 176 | { |
177 | return desc->chip; | 177 | return desc ? desc->chip : NULL; |
178 | } | 178 | } |
179 | 179 | ||
180 | /* caller holds gpio_lock *OR* gpio is marked as requested */ | ||
180 | struct gpio_chip *gpio_to_chip(unsigned gpio) | 181 | struct gpio_chip *gpio_to_chip(unsigned gpio) |
181 | { | 182 | { |
182 | return gpiod_to_chip(gpio_to_desc(gpio)); | 183 | return gpiod_to_chip(gpio_to_desc(gpio)); |
@@ -207,7 +208,7 @@ static int gpiochip_find_base(int ngpio) | |||
207 | } | 208 | } |
208 | 209 | ||
209 | /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ | 210 | /* caller ensures gpio is valid and requested, chip->get_direction may sleep */ |
210 | static int gpiod_get_direction(struct gpio_desc *desc) | 211 | static int gpiod_get_direction(const struct gpio_desc *desc) |
211 | { | 212 | { |
212 | struct gpio_chip *chip; | 213 | struct gpio_chip *chip; |
213 | unsigned offset; | 214 | unsigned offset; |
@@ -223,11 +224,13 @@ static int gpiod_get_direction(struct gpio_desc *desc) | |||
223 | if (status > 0) { | 224 | if (status > 0) { |
224 | /* GPIOF_DIR_IN, or other positive */ | 225 | /* GPIOF_DIR_IN, or other positive */ |
225 | status = 1; | 226 | status = 1; |
226 | clear_bit(FLAG_IS_OUT, &desc->flags); | 227 | /* FLAG_IS_OUT is just a cache of the result of get_direction(), |
228 | * so it does not affect constness per se */ | ||
229 | clear_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags); | ||
227 | } | 230 | } |
228 | if (status == 0) { | 231 | if (status == 0) { |
229 | /* GPIOF_DIR_OUT */ | 232 | /* GPIOF_DIR_OUT */ |
230 | set_bit(FLAG_IS_OUT, &desc->flags); | 233 | set_bit(FLAG_IS_OUT, &((struct gpio_desc *)desc)->flags); |
231 | } | 234 | } |
232 | return status; | 235 | return status; |
233 | } | 236 | } |
@@ -263,7 +266,7 @@ static DEFINE_MUTEX(sysfs_lock); | |||
263 | static ssize_t gpio_direction_show(struct device *dev, | 266 | static ssize_t gpio_direction_show(struct device *dev, |
264 | struct device_attribute *attr, char *buf) | 267 | struct device_attribute *attr, char *buf) |
265 | { | 268 | { |
266 | struct gpio_desc *desc = dev_get_drvdata(dev); | 269 | const struct gpio_desc *desc = dev_get_drvdata(dev); |
267 | ssize_t status; | 270 | ssize_t status; |
268 | 271 | ||
269 | mutex_lock(&sysfs_lock); | 272 | mutex_lock(&sysfs_lock); |
@@ -654,6 +657,11 @@ static ssize_t export_store(struct class *class, | |||
654 | goto done; | 657 | goto done; |
655 | 658 | ||
656 | desc = gpio_to_desc(gpio); | 659 | desc = gpio_to_desc(gpio); |
660 | /* reject invalid GPIOs */ | ||
661 | if (!desc) { | ||
662 | pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); | ||
663 | return -EINVAL; | ||
664 | } | ||
657 | 665 | ||
658 | /* No extra locking here; FLAG_SYSFS just signifies that the | 666 | /* No extra locking here; FLAG_SYSFS just signifies that the |
659 | * request and export were done by on behalf of userspace, so | 667 | * request and export were done by on behalf of userspace, so |
@@ -690,12 +698,14 @@ static ssize_t unexport_store(struct class *class, | |||
690 | if (status < 0) | 698 | if (status < 0) |
691 | goto done; | 699 | goto done; |
692 | 700 | ||
693 | status = -EINVAL; | ||
694 | |||
695 | desc = gpio_to_desc(gpio); | 701 | desc = gpio_to_desc(gpio); |
696 | /* reject bogus commands (gpio_unexport ignores them) */ | 702 | /* reject bogus commands (gpio_unexport ignores them) */ |
697 | if (!desc) | 703 | if (!desc) { |
698 | goto done; | 704 | pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); |
705 | return -EINVAL; | ||
706 | } | ||
707 | |||
708 | status = -EINVAL; | ||
699 | 709 | ||
700 | /* No extra locking here; FLAG_SYSFS just signifies that the | 710 | /* No extra locking here; FLAG_SYSFS just signifies that the |
701 | * request and export were done by on behalf of userspace, so | 711 | * request and export were done by on behalf of userspace, so |
@@ -846,8 +856,10 @@ static int gpiod_export_link(struct device *dev, const char *name, | |||
846 | { | 856 | { |
847 | int status = -EINVAL; | 857 | int status = -EINVAL; |
848 | 858 | ||
849 | if (!desc) | 859 | if (!desc) { |
850 | goto done; | 860 | pr_warn("%s: invalid GPIO\n", __func__); |
861 | return -EINVAL; | ||
862 | } | ||
851 | 863 | ||
852 | mutex_lock(&sysfs_lock); | 864 | mutex_lock(&sysfs_lock); |
853 | 865 | ||
@@ -865,7 +877,6 @@ static int gpiod_export_link(struct device *dev, const char *name, | |||
865 | 877 | ||
866 | mutex_unlock(&sysfs_lock); | 878 | mutex_unlock(&sysfs_lock); |
867 | 879 | ||
868 | done: | ||
869 | if (status) | 880 | if (status) |
870 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), | 881 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), |
871 | status); | 882 | status); |
@@ -896,8 +907,10 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) | |||
896 | struct device *dev = NULL; | 907 | struct device *dev = NULL; |
897 | int status = -EINVAL; | 908 | int status = -EINVAL; |
898 | 909 | ||
899 | if (!desc) | 910 | if (!desc) { |
900 | goto done; | 911 | pr_warn("%s: invalid GPIO\n", __func__); |
912 | return -EINVAL; | ||
913 | } | ||
901 | 914 | ||
902 | mutex_lock(&sysfs_lock); | 915 | mutex_lock(&sysfs_lock); |
903 | 916 | ||
@@ -914,7 +927,6 @@ static int gpiod_sysfs_set_active_low(struct gpio_desc *desc, int value) | |||
914 | unlock: | 927 | unlock: |
915 | mutex_unlock(&sysfs_lock); | 928 | mutex_unlock(&sysfs_lock); |
916 | 929 | ||
917 | done: | ||
918 | if (status) | 930 | if (status) |
919 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), | 931 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), |
920 | status); | 932 | status); |
@@ -940,8 +952,8 @@ static void gpiod_unexport(struct gpio_desc *desc) | |||
940 | struct device *dev = NULL; | 952 | struct device *dev = NULL; |
941 | 953 | ||
942 | if (!desc) { | 954 | if (!desc) { |
943 | status = -EINVAL; | 955 | pr_warn("%s: invalid GPIO\n", __func__); |
944 | goto done; | 956 | return; |
945 | } | 957 | } |
946 | 958 | ||
947 | mutex_lock(&sysfs_lock); | 959 | mutex_lock(&sysfs_lock); |
@@ -962,7 +974,7 @@ static void gpiod_unexport(struct gpio_desc *desc) | |||
962 | device_unregister(dev); | 974 | device_unregister(dev); |
963 | put_device(dev); | 975 | put_device(dev); |
964 | } | 976 | } |
965 | done: | 977 | |
966 | if (status) | 978 | if (status) |
967 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), | 979 | pr_debug("%s: gpio%d status %d\n", __func__, desc_to_gpio(desc), |
968 | status); | 980 | status); |
@@ -1384,12 +1396,13 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) | |||
1384 | int status = -EPROBE_DEFER; | 1396 | int status = -EPROBE_DEFER; |
1385 | unsigned long flags; | 1397 | unsigned long flags; |
1386 | 1398 | ||
1387 | spin_lock_irqsave(&gpio_lock, flags); | ||
1388 | |||
1389 | if (!desc) { | 1399 | if (!desc) { |
1390 | status = -EINVAL; | 1400 | pr_warn("%s: invalid GPIO\n", __func__); |
1391 | goto done; | 1401 | return -EINVAL; |
1392 | } | 1402 | } |
1403 | |||
1404 | spin_lock_irqsave(&gpio_lock, flags); | ||
1405 | |||
1393 | chip = desc->chip; | 1406 | chip = desc->chip; |
1394 | if (chip == NULL) | 1407 | if (chip == NULL) |
1395 | goto done; | 1408 | goto done; |
@@ -1432,8 +1445,7 @@ static int gpiod_request(struct gpio_desc *desc, const char *label) | |||
1432 | done: | 1445 | done: |
1433 | if (status) | 1446 | if (status) |
1434 | pr_debug("_gpio_request: gpio-%d (%s) status %d\n", | 1447 | pr_debug("_gpio_request: gpio-%d (%s) status %d\n", |
1435 | desc ? desc_to_gpio(desc) : -1, | 1448 | desc_to_gpio(desc), label ? : "?", status); |
1436 | label ? : "?", status); | ||
1437 | spin_unlock_irqrestore(&gpio_lock, flags); | 1449 | spin_unlock_irqrestore(&gpio_lock, flags); |
1438 | return status; | 1450 | return status; |
1439 | } | 1451 | } |
@@ -1616,10 +1628,13 @@ static int gpiod_direction_input(struct gpio_desc *desc) | |||
1616 | int status = -EINVAL; | 1628 | int status = -EINVAL; |
1617 | int offset; | 1629 | int offset; |
1618 | 1630 | ||
1631 | if (!desc) { | ||
1632 | pr_warn("%s: invalid GPIO\n", __func__); | ||
1633 | return -EINVAL; | ||
1634 | } | ||
1635 | |||
1619 | spin_lock_irqsave(&gpio_lock, flags); | 1636 | spin_lock_irqsave(&gpio_lock, flags); |
1620 | 1637 | ||
1621 | if (!desc) | ||
1622 | goto fail; | ||
1623 | chip = desc->chip; | 1638 | chip = desc->chip; |
1624 | if (!chip || !chip->get || !chip->direction_input) | 1639 | if (!chip || !chip->get || !chip->direction_input) |
1625 | goto fail; | 1640 | goto fail; |
@@ -1655,13 +1670,9 @@ lose: | |||
1655 | return status; | 1670 | return status; |
1656 | fail: | 1671 | fail: |
1657 | spin_unlock_irqrestore(&gpio_lock, flags); | 1672 | spin_unlock_irqrestore(&gpio_lock, flags); |
1658 | if (status) { | 1673 | if (status) |
1659 | int gpio = -1; | 1674 | pr_debug("%s: gpio-%d status %d\n", __func__, |
1660 | if (desc) | 1675 | desc_to_gpio(desc), status); |
1661 | gpio = desc_to_gpio(desc); | ||
1662 | pr_debug("%s: gpio-%d status %d\n", | ||
1663 | __func__, gpio, status); | ||
1664 | } | ||
1665 | return status; | 1676 | return status; |
1666 | } | 1677 | } |
1667 | 1678 | ||
@@ -1678,6 +1689,11 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
1678 | int status = -EINVAL; | 1689 | int status = -EINVAL; |
1679 | int offset; | 1690 | int offset; |
1680 | 1691 | ||
1692 | if (!desc) { | ||
1693 | pr_warn("%s: invalid GPIO\n", __func__); | ||
1694 | return -EINVAL; | ||
1695 | } | ||
1696 | |||
1681 | /* Open drain pin should not be driven to 1 */ | 1697 | /* Open drain pin should not be driven to 1 */ |
1682 | if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) | 1698 | if (value && test_bit(FLAG_OPEN_DRAIN, &desc->flags)) |
1683 | return gpiod_direction_input(desc); | 1699 | return gpiod_direction_input(desc); |
@@ -1688,8 +1704,6 @@ static int gpiod_direction_output(struct gpio_desc *desc, int value) | |||
1688 | 1704 | ||
1689 | spin_lock_irqsave(&gpio_lock, flags); | 1705 | spin_lock_irqsave(&gpio_lock, flags); |
1690 | 1706 | ||
1691 | if (!desc) | ||
1692 | goto fail; | ||
1693 | chip = desc->chip; | 1707 | chip = desc->chip; |
1694 | if (!chip || !chip->set || !chip->direction_output) | 1708 | if (!chip || !chip->set || !chip->direction_output) |
1695 | goto fail; | 1709 | goto fail; |
@@ -1725,13 +1739,9 @@ lose: | |||
1725 | return status; | 1739 | return status; |
1726 | fail: | 1740 | fail: |
1727 | spin_unlock_irqrestore(&gpio_lock, flags); | 1741 | spin_unlock_irqrestore(&gpio_lock, flags); |
1728 | if (status) { | 1742 | if (status) |
1729 | int gpio = -1; | 1743 | pr_debug("%s: gpio-%d status %d\n", __func__, |
1730 | if (desc) | 1744 | desc_to_gpio(desc), status); |
1731 | gpio = desc_to_gpio(desc); | ||
1732 | pr_debug("%s: gpio-%d status %d\n", | ||
1733 | __func__, gpio, status); | ||
1734 | } | ||
1735 | return status; | 1745 | return status; |
1736 | } | 1746 | } |
1737 | 1747 | ||
@@ -1753,10 +1763,13 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) | |||
1753 | int status = -EINVAL; | 1763 | int status = -EINVAL; |
1754 | int offset; | 1764 | int offset; |
1755 | 1765 | ||
1766 | if (!desc) { | ||
1767 | pr_warn("%s: invalid GPIO\n", __func__); | ||
1768 | return -EINVAL; | ||
1769 | } | ||
1770 | |||
1756 | spin_lock_irqsave(&gpio_lock, flags); | 1771 | spin_lock_irqsave(&gpio_lock, flags); |
1757 | 1772 | ||
1758 | if (!desc) | ||
1759 | goto fail; | ||
1760 | chip = desc->chip; | 1773 | chip = desc->chip; |
1761 | if (!chip || !chip->set || !chip->set_debounce) | 1774 | if (!chip || !chip->set || !chip->set_debounce) |
1762 | goto fail; | 1775 | goto fail; |
@@ -1776,13 +1789,9 @@ static int gpiod_set_debounce(struct gpio_desc *desc, unsigned debounce) | |||
1776 | 1789 | ||
1777 | fail: | 1790 | fail: |
1778 | spin_unlock_irqrestore(&gpio_lock, flags); | 1791 | spin_unlock_irqrestore(&gpio_lock, flags); |
1779 | if (status) { | 1792 | if (status) |
1780 | int gpio = -1; | 1793 | pr_debug("%s: gpio-%d status %d\n", __func__, |
1781 | if (desc) | 1794 | desc_to_gpio(desc), status); |
1782 | gpio = desc_to_gpio(desc); | ||
1783 | pr_debug("%s: gpio-%d status %d\n", | ||
1784 | __func__, gpio, status); | ||
1785 | } | ||
1786 | 1795 | ||
1787 | return status; | 1796 | return status; |
1788 | } | 1797 | } |
@@ -1824,12 +1833,14 @@ EXPORT_SYMBOL_GPL(gpio_set_debounce); | |||
1824 | * It returns the zero or nonzero value provided by the associated | 1833 | * It returns the zero or nonzero value provided by the associated |
1825 | * gpio_chip.get() method; or zero if no such method is provided. | 1834 | * gpio_chip.get() method; or zero if no such method is provided. |
1826 | */ | 1835 | */ |
1827 | static int gpiod_get_value(struct gpio_desc *desc) | 1836 | static int gpiod_get_value(const struct gpio_desc *desc) |
1828 | { | 1837 | { |
1829 | struct gpio_chip *chip; | 1838 | struct gpio_chip *chip; |
1830 | int value; | 1839 | int value; |
1831 | int offset; | 1840 | int offset; |
1832 | 1841 | ||
1842 | if (!desc) | ||
1843 | return 0; | ||
1833 | chip = desc->chip; | 1844 | chip = desc->chip; |
1834 | offset = gpio_chip_hwgpio(desc); | 1845 | offset = gpio_chip_hwgpio(desc); |
1835 | /* Should be using gpio_get_value_cansleep() */ | 1846 | /* Should be using gpio_get_value_cansleep() */ |
@@ -1912,6 +1923,8 @@ static void gpiod_set_value(struct gpio_desc *desc, int value) | |||
1912 | { | 1923 | { |
1913 | struct gpio_chip *chip; | 1924 | struct gpio_chip *chip; |
1914 | 1925 | ||
1926 | if (!desc) | ||
1927 | return; | ||
1915 | chip = desc->chip; | 1928 | chip = desc->chip; |
1916 | /* Should be using gpio_set_value_cansleep() */ | 1929 | /* Should be using gpio_set_value_cansleep() */ |
1917 | WARN_ON(chip->can_sleep); | 1930 | WARN_ON(chip->can_sleep); |
@@ -1938,8 +1951,10 @@ EXPORT_SYMBOL_GPL(__gpio_set_value); | |||
1938 | * This is used directly or indirectly to implement gpio_cansleep(). It | 1951 | * This is used directly or indirectly to implement gpio_cansleep(). It |
1939 | * returns nonzero if access reading or writing the GPIO value can sleep. | 1952 | * returns nonzero if access reading or writing the GPIO value can sleep. |
1940 | */ | 1953 | */ |
1941 | static int gpiod_cansleep(struct gpio_desc *desc) | 1954 | static int gpiod_cansleep(const struct gpio_desc *desc) |
1942 | { | 1955 | { |
1956 | if (!desc) | ||
1957 | return 0; | ||
1943 | /* only call this on GPIOs that are valid! */ | 1958 | /* only call this on GPIOs that are valid! */ |
1944 | return desc->chip->can_sleep; | 1959 | return desc->chip->can_sleep; |
1945 | } | 1960 | } |
@@ -1959,11 +1974,13 @@ EXPORT_SYMBOL_GPL(__gpio_cansleep); | |||
1959 | * It returns the number of the IRQ signaled by this (input) GPIO, | 1974 | * It returns the number of the IRQ signaled by this (input) GPIO, |
1960 | * or a negative errno. | 1975 | * or a negative errno. |
1961 | */ | 1976 | */ |
1962 | static int gpiod_to_irq(struct gpio_desc *desc) | 1977 | static int gpiod_to_irq(const struct gpio_desc *desc) |
1963 | { | 1978 | { |
1964 | struct gpio_chip *chip; | 1979 | struct gpio_chip *chip; |
1965 | int offset; | 1980 | int offset; |
1966 | 1981 | ||
1982 | if (!desc) | ||
1983 | return -EINVAL; | ||
1967 | chip = desc->chip; | 1984 | chip = desc->chip; |
1968 | offset = gpio_chip_hwgpio(desc); | 1985 | offset = gpio_chip_hwgpio(desc); |
1969 | return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; | 1986 | return chip->to_irq ? chip->to_irq(chip, offset) : -ENXIO; |
@@ -1980,13 +1997,15 @@ EXPORT_SYMBOL_GPL(__gpio_to_irq); | |||
1980 | * Common examples include ones connected to I2C or SPI chips. | 1997 | * Common examples include ones connected to I2C or SPI chips. |
1981 | */ | 1998 | */ |
1982 | 1999 | ||
1983 | static int gpiod_get_value_cansleep(struct gpio_desc *desc) | 2000 | static int gpiod_get_value_cansleep(const struct gpio_desc *desc) |
1984 | { | 2001 | { |
1985 | struct gpio_chip *chip; | 2002 | struct gpio_chip *chip; |
1986 | int value; | 2003 | int value; |
1987 | int offset; | 2004 | int offset; |
1988 | 2005 | ||
1989 | might_sleep_if(extra_checks); | 2006 | might_sleep_if(extra_checks); |
2007 | if (!desc) | ||
2008 | return 0; | ||
1990 | chip = desc->chip; | 2009 | chip = desc->chip; |
1991 | offset = gpio_chip_hwgpio(desc); | 2010 | offset = gpio_chip_hwgpio(desc); |
1992 | value = chip->get ? chip->get(chip, offset) : 0; | 2011 | value = chip->get ? chip->get(chip, offset) : 0; |
@@ -2005,6 +2024,8 @@ static void gpiod_set_value_cansleep(struct gpio_desc *desc, int value) | |||
2005 | struct gpio_chip *chip; | 2024 | struct gpio_chip *chip; |
2006 | 2025 | ||
2007 | might_sleep_if(extra_checks); | 2026 | might_sleep_if(extra_checks); |
2027 | if (!desc) | ||
2028 | return; | ||
2008 | chip = desc->chip; | 2029 | chip = desc->chip; |
2009 | trace_gpio_value(desc_to_gpio(desc), 0, value); | 2030 | trace_gpio_value(desc_to_gpio(desc), 0, value); |
2010 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) | 2031 | if (test_bit(FLAG_OPEN_DRAIN, &desc->flags)) |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index c194f4e680ad..e2acfdbf7d3c 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -1634,7 +1634,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
1634 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; | 1634 | unsigned vblank = (pt->vactive_vblank_hi & 0xf) << 8 | pt->vblank_lo; |
1635 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; | 1635 | unsigned hsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc0) << 2 | pt->hsync_offset_lo; |
1636 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; | 1636 | unsigned hsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x30) << 4 | pt->hsync_pulse_width_lo; |
1637 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) >> 2 | pt->vsync_offset_pulse_width_lo >> 4; | 1637 | unsigned vsync_offset = (pt->hsync_vsync_offset_pulse_width_hi & 0xc) << 2 | pt->vsync_offset_pulse_width_lo >> 4; |
1638 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); | 1638 | unsigned vsync_pulse_width = (pt->hsync_vsync_offset_pulse_width_hi & 0x3) << 4 | (pt->vsync_offset_pulse_width_lo & 0xf); |
1639 | 1639 | ||
1640 | /* ignore tiny modes */ | 1640 | /* ignore tiny modes */ |
@@ -1715,6 +1715,7 @@ set_size: | |||
1715 | } | 1715 | } |
1716 | 1716 | ||
1717 | mode->type = DRM_MODE_TYPE_DRIVER; | 1717 | mode->type = DRM_MODE_TYPE_DRIVER; |
1718 | mode->vrefresh = drm_mode_vrefresh(mode); | ||
1718 | drm_mode_set_name(mode); | 1719 | drm_mode_set_name(mode); |
1719 | 1720 | ||
1720 | return mode; | 1721 | return mode; |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c index 36493ce71f9a..98cc14725ba9 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c +++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c | |||
@@ -38,11 +38,12 @@ | |||
38 | /* position control register for hardware window 0, 2 ~ 4.*/ | 38 | /* position control register for hardware window 0, 2 ~ 4.*/ |
39 | #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16) | 39 | #define VIDOSD_A(win) (VIDOSD_BASE + 0x00 + (win) * 16) |
40 | #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16) | 40 | #define VIDOSD_B(win) (VIDOSD_BASE + 0x04 + (win) * 16) |
41 | /* size control register for hardware window 0. */ | 41 | /* |
42 | #define VIDOSD_C_SIZE_W0 (VIDOSD_BASE + 0x08) | 42 | * size control register for hardware windows 0 and alpha control register |
43 | /* alpha control register for hardware window 1 ~ 4. */ | 43 | * for hardware windows 1 ~ 4 |
44 | #define VIDOSD_C(win) (VIDOSD_BASE + 0x18 + (win) * 16) | 44 | */ |
45 | /* size control register for hardware window 1 ~ 4. */ | 45 | #define VIDOSD_C(win) (VIDOSD_BASE + 0x08 + (win) * 16) |
46 | /* size control register for hardware windows 1 ~ 2. */ | ||
46 | #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16) | 47 | #define VIDOSD_D(win) (VIDOSD_BASE + 0x0C + (win) * 16) |
47 | 48 | ||
48 | #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8) | 49 | #define VIDWx_BUF_START(win, buf) (VIDW_BUF_START(buf) + (win) * 8) |
@@ -50,9 +51,9 @@ | |||
50 | #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4) | 51 | #define VIDWx_BUF_SIZE(win, buf) (VIDW_BUF_SIZE(buf) + (win) * 4) |
51 | 52 | ||
52 | /* color key control register for hardware window 1 ~ 4. */ | 53 | /* color key control register for hardware window 1 ~ 4. */ |
53 | #define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + (x * 8)) | 54 | #define WKEYCON0_BASE(x) ((WKEYCON0 + 0x140) + ((x - 1) * 8)) |
54 | /* color key value register for hardware window 1 ~ 4. */ | 55 | /* color key value register for hardware window 1 ~ 4. */ |
55 | #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + (x * 8)) | 56 | #define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8)) |
56 | 57 | ||
57 | /* FIMD has totally five hardware windows. */ | 58 | /* FIMD has totally five hardware windows. */ |
58 | #define WINDOWS_NR 5 | 59 | #define WINDOWS_NR 5 |
@@ -109,9 +110,9 @@ struct fimd_context { | |||
109 | 110 | ||
110 | #ifdef CONFIG_OF | 111 | #ifdef CONFIG_OF |
111 | static const struct of_device_id fimd_driver_dt_match[] = { | 112 | static const struct of_device_id fimd_driver_dt_match[] = { |
112 | { .compatible = "samsung,exynos4-fimd", | 113 | { .compatible = "samsung,exynos4210-fimd", |
113 | .data = &exynos4_fimd_driver_data }, | 114 | .data = &exynos4_fimd_driver_data }, |
114 | { .compatible = "samsung,exynos5-fimd", | 115 | { .compatible = "samsung,exynos5250-fimd", |
115 | .data = &exynos5_fimd_driver_data }, | 116 | .data = &exynos5_fimd_driver_data }, |
116 | {}, | 117 | {}, |
117 | }; | 118 | }; |
@@ -581,7 +582,7 @@ static void fimd_win_commit(struct device *dev, int zpos) | |||
581 | if (win != 3 && win != 4) { | 582 | if (win != 3 && win != 4) { |
582 | u32 offset = VIDOSD_D(win); | 583 | u32 offset = VIDOSD_D(win); |
583 | if (win == 0) | 584 | if (win == 0) |
584 | offset = VIDOSD_C_SIZE_W0; | 585 | offset = VIDOSD_C(win); |
585 | val = win_data->ovl_width * win_data->ovl_height; | 586 | val = win_data->ovl_width * win_data->ovl_height; |
586 | writel(val, ctx->regs + offset); | 587 | writel(val, ctx->regs + offset); |
587 | 588 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 3b0da0378acf..47a493c8a71f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -48,8 +48,14 @@ | |||
48 | 48 | ||
49 | /* registers for base address */ | 49 | /* registers for base address */ |
50 | #define G2D_SRC_BASE_ADDR 0x0304 | 50 | #define G2D_SRC_BASE_ADDR 0x0304 |
51 | #define G2D_SRC_COLOR_MODE 0x030C | ||
52 | #define G2D_SRC_LEFT_TOP 0x0310 | ||
53 | #define G2D_SRC_RIGHT_BOTTOM 0x0314 | ||
51 | #define G2D_SRC_PLANE2_BASE_ADDR 0x0318 | 54 | #define G2D_SRC_PLANE2_BASE_ADDR 0x0318 |
52 | #define G2D_DST_BASE_ADDR 0x0404 | 55 | #define G2D_DST_BASE_ADDR 0x0404 |
56 | #define G2D_DST_COLOR_MODE 0x040C | ||
57 | #define G2D_DST_LEFT_TOP 0x0410 | ||
58 | #define G2D_DST_RIGHT_BOTTOM 0x0414 | ||
53 | #define G2D_DST_PLANE2_BASE_ADDR 0x0418 | 59 | #define G2D_DST_PLANE2_BASE_ADDR 0x0418 |
54 | #define G2D_PAT_BASE_ADDR 0x0500 | 60 | #define G2D_PAT_BASE_ADDR 0x0500 |
55 | #define G2D_MSK_BASE_ADDR 0x0520 | 61 | #define G2D_MSK_BASE_ADDR 0x0520 |
@@ -82,7 +88,7 @@ | |||
82 | #define G2D_DMA_LIST_DONE_COUNT_OFFSET 17 | 88 | #define G2D_DMA_LIST_DONE_COUNT_OFFSET 17 |
83 | 89 | ||
84 | /* G2D_DMA_HOLD_CMD */ | 90 | /* G2D_DMA_HOLD_CMD */ |
85 | #define G2D_USET_HOLD (1 << 2) | 91 | #define G2D_USER_HOLD (1 << 2) |
86 | #define G2D_LIST_HOLD (1 << 1) | 92 | #define G2D_LIST_HOLD (1 << 1) |
87 | #define G2D_BITBLT_HOLD (1 << 0) | 93 | #define G2D_BITBLT_HOLD (1 << 0) |
88 | 94 | ||
@@ -91,13 +97,27 @@ | |||
91 | #define G2D_START_NHOLT (1 << 1) | 97 | #define G2D_START_NHOLT (1 << 1) |
92 | #define G2D_START_BITBLT (1 << 0) | 98 | #define G2D_START_BITBLT (1 << 0) |
93 | 99 | ||
100 | /* buffer color format */ | ||
101 | #define G2D_FMT_XRGB8888 0 | ||
102 | #define G2D_FMT_ARGB8888 1 | ||
103 | #define G2D_FMT_RGB565 2 | ||
104 | #define G2D_FMT_XRGB1555 3 | ||
105 | #define G2D_FMT_ARGB1555 4 | ||
106 | #define G2D_FMT_XRGB4444 5 | ||
107 | #define G2D_FMT_ARGB4444 6 | ||
108 | #define G2D_FMT_PACKED_RGB888 7 | ||
109 | #define G2D_FMT_A8 11 | ||
110 | #define G2D_FMT_L8 12 | ||
111 | |||
112 | /* buffer valid length */ | ||
113 | #define G2D_LEN_MIN 1 | ||
114 | #define G2D_LEN_MAX 8000 | ||
115 | |||
94 | #define G2D_CMDLIST_SIZE (PAGE_SIZE / 4) | 116 | #define G2D_CMDLIST_SIZE (PAGE_SIZE / 4) |
95 | #define G2D_CMDLIST_NUM 64 | 117 | #define G2D_CMDLIST_NUM 64 |
96 | #define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM) | 118 | #define G2D_CMDLIST_POOL_SIZE (G2D_CMDLIST_SIZE * G2D_CMDLIST_NUM) |
97 | #define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2) | 119 | #define G2D_CMDLIST_DATA_NUM (G2D_CMDLIST_SIZE / sizeof(u32) - 2) |
98 | 120 | ||
99 | #define MAX_BUF_ADDR_NR 6 | ||
100 | |||
101 | /* maximum buffer pool size of userptr is 64MB as default */ | 121 | /* maximum buffer pool size of userptr is 64MB as default */ |
102 | #define MAX_POOL (64 * 1024 * 1024) | 122 | #define MAX_POOL (64 * 1024 * 1024) |
103 | 123 | ||
@@ -106,6 +126,17 @@ enum { | |||
106 | BUF_TYPE_USERPTR, | 126 | BUF_TYPE_USERPTR, |
107 | }; | 127 | }; |
108 | 128 | ||
129 | enum g2d_reg_type { | ||
130 | REG_TYPE_NONE = -1, | ||
131 | REG_TYPE_SRC, | ||
132 | REG_TYPE_SRC_PLANE2, | ||
133 | REG_TYPE_DST, | ||
134 | REG_TYPE_DST_PLANE2, | ||
135 | REG_TYPE_PAT, | ||
136 | REG_TYPE_MSK, | ||
137 | MAX_REG_TYPE_NR | ||
138 | }; | ||
139 | |||
109 | /* cmdlist data structure */ | 140 | /* cmdlist data structure */ |
110 | struct g2d_cmdlist { | 141 | struct g2d_cmdlist { |
111 | u32 head; | 142 | u32 head; |
@@ -113,6 +144,42 @@ struct g2d_cmdlist { | |||
113 | u32 last; /* last data offset */ | 144 | u32 last; /* last data offset */ |
114 | }; | 145 | }; |
115 | 146 | ||
147 | /* | ||
148 | * A structure of buffer description | ||
149 | * | ||
150 | * @format: color format | ||
151 | * @left_x: the x coordinates of left top corner | ||
152 | * @top_y: the y coordinates of left top corner | ||
153 | * @right_x: the x coordinates of right bottom corner | ||
154 | * @bottom_y: the y coordinates of right bottom corner | ||
155 | * | ||
156 | */ | ||
157 | struct g2d_buf_desc { | ||
158 | unsigned int format; | ||
159 | unsigned int left_x; | ||
160 | unsigned int top_y; | ||
161 | unsigned int right_x; | ||
162 | unsigned int bottom_y; | ||
163 | }; | ||
164 | |||
165 | /* | ||
166 | * A structure of buffer information | ||
167 | * | ||
168 | * @map_nr: manages the number of mapped buffers | ||
169 | * @reg_types: stores regitster type in the order of requested command | ||
170 | * @handles: stores buffer handle in its reg_type position | ||
171 | * @types: stores buffer type in its reg_type position | ||
172 | * @descs: stores buffer description in its reg_type position | ||
173 | * | ||
174 | */ | ||
175 | struct g2d_buf_info { | ||
176 | unsigned int map_nr; | ||
177 | enum g2d_reg_type reg_types[MAX_REG_TYPE_NR]; | ||
178 | unsigned long handles[MAX_REG_TYPE_NR]; | ||
179 | unsigned int types[MAX_REG_TYPE_NR]; | ||
180 | struct g2d_buf_desc descs[MAX_REG_TYPE_NR]; | ||
181 | }; | ||
182 | |||
116 | struct drm_exynos_pending_g2d_event { | 183 | struct drm_exynos_pending_g2d_event { |
117 | struct drm_pending_event base; | 184 | struct drm_pending_event base; |
118 | struct drm_exynos_g2d_event event; | 185 | struct drm_exynos_g2d_event event; |
@@ -131,14 +198,11 @@ struct g2d_cmdlist_userptr { | |||
131 | bool in_pool; | 198 | bool in_pool; |
132 | bool out_of_list; | 199 | bool out_of_list; |
133 | }; | 200 | }; |
134 | |||
135 | struct g2d_cmdlist_node { | 201 | struct g2d_cmdlist_node { |
136 | struct list_head list; | 202 | struct list_head list; |
137 | struct g2d_cmdlist *cmdlist; | 203 | struct g2d_cmdlist *cmdlist; |
138 | unsigned int map_nr; | ||
139 | unsigned long handles[MAX_BUF_ADDR_NR]; | ||
140 | unsigned int obj_type[MAX_BUF_ADDR_NR]; | ||
141 | dma_addr_t dma_addr; | 204 | dma_addr_t dma_addr; |
205 | struct g2d_buf_info buf_info; | ||
142 | 206 | ||
143 | struct drm_exynos_pending_g2d_event *event; | 207 | struct drm_exynos_pending_g2d_event *event; |
144 | }; | 208 | }; |
@@ -188,6 +252,7 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) | |||
188 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; | 252 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; |
189 | int nr; | 253 | int nr; |
190 | int ret; | 254 | int ret; |
255 | struct g2d_buf_info *buf_info; | ||
191 | 256 | ||
192 | init_dma_attrs(&g2d->cmdlist_dma_attrs); | 257 | init_dma_attrs(&g2d->cmdlist_dma_attrs); |
193 | dma_set_attr(DMA_ATTR_WRITE_COMBINE, &g2d->cmdlist_dma_attrs); | 258 | dma_set_attr(DMA_ATTR_WRITE_COMBINE, &g2d->cmdlist_dma_attrs); |
@@ -209,11 +274,17 @@ static int g2d_init_cmdlist(struct g2d_data *g2d) | |||
209 | } | 274 | } |
210 | 275 | ||
211 | for (nr = 0; nr < G2D_CMDLIST_NUM; nr++) { | 276 | for (nr = 0; nr < G2D_CMDLIST_NUM; nr++) { |
277 | unsigned int i; | ||
278 | |||
212 | node[nr].cmdlist = | 279 | node[nr].cmdlist = |
213 | g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE; | 280 | g2d->cmdlist_pool_virt + nr * G2D_CMDLIST_SIZE; |
214 | node[nr].dma_addr = | 281 | node[nr].dma_addr = |
215 | g2d->cmdlist_pool + nr * G2D_CMDLIST_SIZE; | 282 | g2d->cmdlist_pool + nr * G2D_CMDLIST_SIZE; |
216 | 283 | ||
284 | buf_info = &node[nr].buf_info; | ||
285 | for (i = 0; i < MAX_REG_TYPE_NR; i++) | ||
286 | buf_info->reg_types[i] = REG_TYPE_NONE; | ||
287 | |||
217 | list_add_tail(&node[nr].list, &g2d->free_cmdlist); | 288 | list_add_tail(&node[nr].list, &g2d->free_cmdlist); |
218 | } | 289 | } |
219 | 290 | ||
@@ -450,7 +521,7 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | |||
450 | DMA_BIDIRECTIONAL); | 521 | DMA_BIDIRECTIONAL); |
451 | if (ret < 0) { | 522 | if (ret < 0) { |
452 | DRM_ERROR("failed to map sgt with dma region.\n"); | 523 | DRM_ERROR("failed to map sgt with dma region.\n"); |
453 | goto err_free_sgt; | 524 | goto err_sg_free_table; |
454 | } | 525 | } |
455 | 526 | ||
456 | g2d_userptr->dma_addr = sgt->sgl[0].dma_address; | 527 | g2d_userptr->dma_addr = sgt->sgl[0].dma_address; |
@@ -467,8 +538,10 @@ static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | |||
467 | 538 | ||
468 | return &g2d_userptr->dma_addr; | 539 | return &g2d_userptr->dma_addr; |
469 | 540 | ||
470 | err_free_sgt: | 541 | err_sg_free_table: |
471 | sg_free_table(sgt); | 542 | sg_free_table(sgt); |
543 | |||
544 | err_free_sgt: | ||
472 | kfree(sgt); | 545 | kfree(sgt); |
473 | sgt = NULL; | 546 | sgt = NULL; |
474 | 547 | ||
@@ -506,36 +579,172 @@ static void g2d_userptr_free_all(struct drm_device *drm_dev, | |||
506 | g2d->current_pool = 0; | 579 | g2d->current_pool = 0; |
507 | } | 580 | } |
508 | 581 | ||
582 | static enum g2d_reg_type g2d_get_reg_type(int reg_offset) | ||
583 | { | ||
584 | enum g2d_reg_type reg_type; | ||
585 | |||
586 | switch (reg_offset) { | ||
587 | case G2D_SRC_BASE_ADDR: | ||
588 | case G2D_SRC_COLOR_MODE: | ||
589 | case G2D_SRC_LEFT_TOP: | ||
590 | case G2D_SRC_RIGHT_BOTTOM: | ||
591 | reg_type = REG_TYPE_SRC; | ||
592 | break; | ||
593 | case G2D_SRC_PLANE2_BASE_ADDR: | ||
594 | reg_type = REG_TYPE_SRC_PLANE2; | ||
595 | break; | ||
596 | case G2D_DST_BASE_ADDR: | ||
597 | case G2D_DST_COLOR_MODE: | ||
598 | case G2D_DST_LEFT_TOP: | ||
599 | case G2D_DST_RIGHT_BOTTOM: | ||
600 | reg_type = REG_TYPE_DST; | ||
601 | break; | ||
602 | case G2D_DST_PLANE2_BASE_ADDR: | ||
603 | reg_type = REG_TYPE_DST_PLANE2; | ||
604 | break; | ||
605 | case G2D_PAT_BASE_ADDR: | ||
606 | reg_type = REG_TYPE_PAT; | ||
607 | break; | ||
608 | case G2D_MSK_BASE_ADDR: | ||
609 | reg_type = REG_TYPE_MSK; | ||
610 | break; | ||
611 | default: | ||
612 | reg_type = REG_TYPE_NONE; | ||
613 | DRM_ERROR("Unknown register offset![%d]\n", reg_offset); | ||
614 | break; | ||
615 | }; | ||
616 | |||
617 | return reg_type; | ||
618 | } | ||
619 | |||
620 | static unsigned long g2d_get_buf_bpp(unsigned int format) | ||
621 | { | ||
622 | unsigned long bpp; | ||
623 | |||
624 | switch (format) { | ||
625 | case G2D_FMT_XRGB8888: | ||
626 | case G2D_FMT_ARGB8888: | ||
627 | bpp = 4; | ||
628 | break; | ||
629 | case G2D_FMT_RGB565: | ||
630 | case G2D_FMT_XRGB1555: | ||
631 | case G2D_FMT_ARGB1555: | ||
632 | case G2D_FMT_XRGB4444: | ||
633 | case G2D_FMT_ARGB4444: | ||
634 | bpp = 2; | ||
635 | break; | ||
636 | case G2D_FMT_PACKED_RGB888: | ||
637 | bpp = 3; | ||
638 | break; | ||
639 | default: | ||
640 | bpp = 1; | ||
641 | break; | ||
642 | } | ||
643 | |||
644 | return bpp; | ||
645 | } | ||
646 | |||
647 | static bool g2d_check_buf_desc_is_valid(struct g2d_buf_desc *buf_desc, | ||
648 | enum g2d_reg_type reg_type, | ||
649 | unsigned long size) | ||
650 | { | ||
651 | unsigned int width, height; | ||
652 | unsigned long area; | ||
653 | |||
654 | /* | ||
655 | * check source and destination buffers only. | ||
656 | * so the others are always valid. | ||
657 | */ | ||
658 | if (reg_type != REG_TYPE_SRC && reg_type != REG_TYPE_DST) | ||
659 | return true; | ||
660 | |||
661 | width = buf_desc->right_x - buf_desc->left_x; | ||
662 | if (width < G2D_LEN_MIN || width > G2D_LEN_MAX) { | ||
663 | DRM_ERROR("width[%u] is out of range!\n", width); | ||
664 | return false; | ||
665 | } | ||
666 | |||
667 | height = buf_desc->bottom_y - buf_desc->top_y; | ||
668 | if (height < G2D_LEN_MIN || height > G2D_LEN_MAX) { | ||
669 | DRM_ERROR("height[%u] is out of range!\n", height); | ||
670 | return false; | ||
671 | } | ||
672 | |||
673 | area = (unsigned long)width * (unsigned long)height * | ||
674 | g2d_get_buf_bpp(buf_desc->format); | ||
675 | if (area > size) { | ||
676 | DRM_ERROR("area[%lu] is out of range[%lu]!\n", area, size); | ||
677 | return false; | ||
678 | } | ||
679 | |||
680 | return true; | ||
681 | } | ||
682 | |||
509 | static int g2d_map_cmdlist_gem(struct g2d_data *g2d, | 683 | static int g2d_map_cmdlist_gem(struct g2d_data *g2d, |
510 | struct g2d_cmdlist_node *node, | 684 | struct g2d_cmdlist_node *node, |
511 | struct drm_device *drm_dev, | 685 | struct drm_device *drm_dev, |
512 | struct drm_file *file) | 686 | struct drm_file *file) |
513 | { | 687 | { |
514 | struct g2d_cmdlist *cmdlist = node->cmdlist; | 688 | struct g2d_cmdlist *cmdlist = node->cmdlist; |
689 | struct g2d_buf_info *buf_info = &node->buf_info; | ||
515 | int offset; | 690 | int offset; |
691 | int ret; | ||
516 | int i; | 692 | int i; |
517 | 693 | ||
518 | for (i = 0; i < node->map_nr; i++) { | 694 | for (i = 0; i < buf_info->map_nr; i++) { |
695 | struct g2d_buf_desc *buf_desc; | ||
696 | enum g2d_reg_type reg_type; | ||
697 | int reg_pos; | ||
519 | unsigned long handle; | 698 | unsigned long handle; |
520 | dma_addr_t *addr; | 699 | dma_addr_t *addr; |
521 | 700 | ||
522 | offset = cmdlist->last - (i * 2 + 1); | 701 | reg_pos = cmdlist->last - 2 * (i + 1); |
523 | handle = cmdlist->data[offset]; | 702 | |
703 | offset = cmdlist->data[reg_pos]; | ||
704 | handle = cmdlist->data[reg_pos + 1]; | ||
705 | |||
706 | reg_type = g2d_get_reg_type(offset); | ||
707 | if (reg_type == REG_TYPE_NONE) { | ||
708 | ret = -EFAULT; | ||
709 | goto err; | ||
710 | } | ||
711 | |||
712 | buf_desc = &buf_info->descs[reg_type]; | ||
713 | |||
714 | if (buf_info->types[reg_type] == BUF_TYPE_GEM) { | ||
715 | unsigned long size; | ||
716 | |||
717 | size = exynos_drm_gem_get_size(drm_dev, handle, file); | ||
718 | if (!size) { | ||
719 | ret = -EFAULT; | ||
720 | goto err; | ||
721 | } | ||
722 | |||
723 | if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, | ||
724 | size)) { | ||
725 | ret = -EFAULT; | ||
726 | goto err; | ||
727 | } | ||
524 | 728 | ||
525 | if (node->obj_type[i] == BUF_TYPE_GEM) { | ||
526 | addr = exynos_drm_gem_get_dma_addr(drm_dev, handle, | 729 | addr = exynos_drm_gem_get_dma_addr(drm_dev, handle, |
527 | file); | 730 | file); |
528 | if (IS_ERR(addr)) { | 731 | if (IS_ERR(addr)) { |
529 | node->map_nr = i; | 732 | ret = -EFAULT; |
530 | return -EFAULT; | 733 | goto err; |
531 | } | 734 | } |
532 | } else { | 735 | } else { |
533 | struct drm_exynos_g2d_userptr g2d_userptr; | 736 | struct drm_exynos_g2d_userptr g2d_userptr; |
534 | 737 | ||
535 | if (copy_from_user(&g2d_userptr, (void __user *)handle, | 738 | if (copy_from_user(&g2d_userptr, (void __user *)handle, |
536 | sizeof(struct drm_exynos_g2d_userptr))) { | 739 | sizeof(struct drm_exynos_g2d_userptr))) { |
537 | node->map_nr = i; | 740 | ret = -EFAULT; |
538 | return -EFAULT; | 741 | goto err; |
742 | } | ||
743 | |||
744 | if (!g2d_check_buf_desc_is_valid(buf_desc, reg_type, | ||
745 | g2d_userptr.size)) { | ||
746 | ret = -EFAULT; | ||
747 | goto err; | ||
539 | } | 748 | } |
540 | 749 | ||
541 | addr = g2d_userptr_get_dma_addr(drm_dev, | 750 | addr = g2d_userptr_get_dma_addr(drm_dev, |
@@ -544,16 +753,21 @@ static int g2d_map_cmdlist_gem(struct g2d_data *g2d, | |||
544 | file, | 753 | file, |
545 | &handle); | 754 | &handle); |
546 | if (IS_ERR(addr)) { | 755 | if (IS_ERR(addr)) { |
547 | node->map_nr = i; | 756 | ret = -EFAULT; |
548 | return -EFAULT; | 757 | goto err; |
549 | } | 758 | } |
550 | } | 759 | } |
551 | 760 | ||
552 | cmdlist->data[offset] = *addr; | 761 | cmdlist->data[reg_pos + 1] = *addr; |
553 | node->handles[i] = handle; | 762 | buf_info->reg_types[i] = reg_type; |
763 | buf_info->handles[reg_type] = handle; | ||
554 | } | 764 | } |
555 | 765 | ||
556 | return 0; | 766 | return 0; |
767 | |||
768 | err: | ||
769 | buf_info->map_nr = i; | ||
770 | return ret; | ||
557 | } | 771 | } |
558 | 772 | ||
559 | static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, | 773 | static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, |
@@ -561,22 +775,33 @@ static void g2d_unmap_cmdlist_gem(struct g2d_data *g2d, | |||
561 | struct drm_file *filp) | 775 | struct drm_file *filp) |
562 | { | 776 | { |
563 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; | 777 | struct exynos_drm_subdrv *subdrv = &g2d->subdrv; |
778 | struct g2d_buf_info *buf_info = &node->buf_info; | ||
564 | int i; | 779 | int i; |
565 | 780 | ||
566 | for (i = 0; i < node->map_nr; i++) { | 781 | for (i = 0; i < buf_info->map_nr; i++) { |
567 | unsigned long handle = node->handles[i]; | 782 | struct g2d_buf_desc *buf_desc; |
783 | enum g2d_reg_type reg_type; | ||
784 | unsigned long handle; | ||
785 | |||
786 | reg_type = buf_info->reg_types[i]; | ||
787 | |||
788 | buf_desc = &buf_info->descs[reg_type]; | ||
789 | handle = buf_info->handles[reg_type]; | ||
568 | 790 | ||
569 | if (node->obj_type[i] == BUF_TYPE_GEM) | 791 | if (buf_info->types[reg_type] == BUF_TYPE_GEM) |
570 | exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle, | 792 | exynos_drm_gem_put_dma_addr(subdrv->drm_dev, handle, |
571 | filp); | 793 | filp); |
572 | else | 794 | else |
573 | g2d_userptr_put_dma_addr(subdrv->drm_dev, handle, | 795 | g2d_userptr_put_dma_addr(subdrv->drm_dev, handle, |
574 | false); | 796 | false); |
575 | 797 | ||
576 | node->handles[i] = 0; | 798 | buf_info->reg_types[i] = REG_TYPE_NONE; |
799 | buf_info->handles[reg_type] = 0; | ||
800 | buf_info->types[reg_type] = 0; | ||
801 | memset(buf_desc, 0x00, sizeof(*buf_desc)); | ||
577 | } | 802 | } |
578 | 803 | ||
579 | node->map_nr = 0; | 804 | buf_info->map_nr = 0; |
580 | } | 805 | } |
581 | 806 | ||
582 | static void g2d_dma_start(struct g2d_data *g2d, | 807 | static void g2d_dma_start(struct g2d_data *g2d, |
@@ -589,10 +814,6 @@ static void g2d_dma_start(struct g2d_data *g2d, | |||
589 | pm_runtime_get_sync(g2d->dev); | 814 | pm_runtime_get_sync(g2d->dev); |
590 | clk_enable(g2d->gate_clk); | 815 | clk_enable(g2d->gate_clk); |
591 | 816 | ||
592 | /* interrupt enable */ | ||
593 | writel_relaxed(G2D_INTEN_ACF | G2D_INTEN_UCF | G2D_INTEN_GCF, | ||
594 | g2d->regs + G2D_INTEN); | ||
595 | |||
596 | writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); | 817 | writel_relaxed(node->dma_addr, g2d->regs + G2D_DMA_SFR_BASE_ADDR); |
597 | writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); | 818 | writel_relaxed(G2D_DMA_START, g2d->regs + G2D_DMA_COMMAND); |
598 | } | 819 | } |
@@ -643,7 +864,6 @@ static void g2d_runqueue_worker(struct work_struct *work) | |||
643 | struct g2d_data *g2d = container_of(work, struct g2d_data, | 864 | struct g2d_data *g2d = container_of(work, struct g2d_data, |
644 | runqueue_work); | 865 | runqueue_work); |
645 | 866 | ||
646 | |||
647 | mutex_lock(&g2d->runqueue_mutex); | 867 | mutex_lock(&g2d->runqueue_mutex); |
648 | clk_disable(g2d->gate_clk); | 868 | clk_disable(g2d->gate_clk); |
649 | pm_runtime_put_sync(g2d->dev); | 869 | pm_runtime_put_sync(g2d->dev); |
@@ -724,20 +944,14 @@ static int g2d_check_reg_offset(struct device *dev, | |||
724 | int i; | 944 | int i; |
725 | 945 | ||
726 | for (i = 0; i < nr; i++) { | 946 | for (i = 0; i < nr; i++) { |
727 | index = cmdlist->last - 2 * (i + 1); | 947 | struct g2d_buf_info *buf_info = &node->buf_info; |
948 | struct g2d_buf_desc *buf_desc; | ||
949 | enum g2d_reg_type reg_type; | ||
950 | unsigned long value; | ||
728 | 951 | ||
729 | if (for_addr) { | 952 | index = cmdlist->last - 2 * (i + 1); |
730 | /* check userptr buffer type. */ | ||
731 | reg_offset = (cmdlist->data[index] & | ||
732 | ~0x7fffffff) >> 31; | ||
733 | if (reg_offset) { | ||
734 | node->obj_type[i] = BUF_TYPE_USERPTR; | ||
735 | cmdlist->data[index] &= ~G2D_BUF_USERPTR; | ||
736 | } | ||
737 | } | ||
738 | 953 | ||
739 | reg_offset = cmdlist->data[index] & ~0xfffff000; | 954 | reg_offset = cmdlist->data[index] & ~0xfffff000; |
740 | |||
741 | if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END) | 955 | if (reg_offset < G2D_VALID_START || reg_offset > G2D_VALID_END) |
742 | goto err; | 956 | goto err; |
743 | if (reg_offset % 4) | 957 | if (reg_offset % 4) |
@@ -753,8 +967,60 @@ static int g2d_check_reg_offset(struct device *dev, | |||
753 | if (!for_addr) | 967 | if (!for_addr) |
754 | goto err; | 968 | goto err; |
755 | 969 | ||
756 | if (node->obj_type[i] != BUF_TYPE_USERPTR) | 970 | reg_type = g2d_get_reg_type(reg_offset); |
757 | node->obj_type[i] = BUF_TYPE_GEM; | 971 | if (reg_type == REG_TYPE_NONE) |
972 | goto err; | ||
973 | |||
974 | /* check userptr buffer type. */ | ||
975 | if ((cmdlist->data[index] & ~0x7fffffff) >> 31) { | ||
976 | buf_info->types[reg_type] = BUF_TYPE_USERPTR; | ||
977 | cmdlist->data[index] &= ~G2D_BUF_USERPTR; | ||
978 | } else | ||
979 | buf_info->types[reg_type] = BUF_TYPE_GEM; | ||
980 | break; | ||
981 | case G2D_SRC_COLOR_MODE: | ||
982 | case G2D_DST_COLOR_MODE: | ||
983 | if (for_addr) | ||
984 | goto err; | ||
985 | |||
986 | reg_type = g2d_get_reg_type(reg_offset); | ||
987 | if (reg_type == REG_TYPE_NONE) | ||
988 | goto err; | ||
989 | |||
990 | buf_desc = &buf_info->descs[reg_type]; | ||
991 | value = cmdlist->data[index + 1]; | ||
992 | |||
993 | buf_desc->format = value & 0xf; | ||
994 | break; | ||
995 | case G2D_SRC_LEFT_TOP: | ||
996 | case G2D_DST_LEFT_TOP: | ||
997 | if (for_addr) | ||
998 | goto err; | ||
999 | |||
1000 | reg_type = g2d_get_reg_type(reg_offset); | ||
1001 | if (reg_type == REG_TYPE_NONE) | ||
1002 | goto err; | ||
1003 | |||
1004 | buf_desc = &buf_info->descs[reg_type]; | ||
1005 | value = cmdlist->data[index + 1]; | ||
1006 | |||
1007 | buf_desc->left_x = value & 0x1fff; | ||
1008 | buf_desc->top_y = (value & 0x1fff0000) >> 16; | ||
1009 | break; | ||
1010 | case G2D_SRC_RIGHT_BOTTOM: | ||
1011 | case G2D_DST_RIGHT_BOTTOM: | ||
1012 | if (for_addr) | ||
1013 | goto err; | ||
1014 | |||
1015 | reg_type = g2d_get_reg_type(reg_offset); | ||
1016 | if (reg_type == REG_TYPE_NONE) | ||
1017 | goto err; | ||
1018 | |||
1019 | buf_desc = &buf_info->descs[reg_type]; | ||
1020 | value = cmdlist->data[index + 1]; | ||
1021 | |||
1022 | buf_desc->right_x = value & 0x1fff; | ||
1023 | buf_desc->bottom_y = (value & 0x1fff0000) >> 16; | ||
758 | break; | 1024 | break; |
759 | default: | 1025 | default: |
760 | if (for_addr) | 1026 | if (for_addr) |
@@ -860,9 +1126,23 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, | |||
860 | cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR; | 1126 | cmdlist->data[cmdlist->last++] = G2D_SRC_BASE_ADDR; |
861 | cmdlist->data[cmdlist->last++] = 0; | 1127 | cmdlist->data[cmdlist->last++] = 0; |
862 | 1128 | ||
1129 | /* | ||
1130 | * 'LIST_HOLD' command should be set to the DMA_HOLD_CMD_REG | ||
1131 | * and GCF bit should be set to INTEN register if user wants | ||
1132 | * G2D interrupt event once current command list execution is | ||
1133 | * finished. | ||
1134 | * Otherwise only ACF bit should be set to INTEN register so | ||
1135 | * that one interrupt is occured after all command lists | ||
1136 | * have been completed. | ||
1137 | */ | ||
863 | if (node->event) { | 1138 | if (node->event) { |
1139 | cmdlist->data[cmdlist->last++] = G2D_INTEN; | ||
1140 | cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF | G2D_INTEN_GCF; | ||
864 | cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD; | 1141 | cmdlist->data[cmdlist->last++] = G2D_DMA_HOLD_CMD; |
865 | cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD; | 1142 | cmdlist->data[cmdlist->last++] = G2D_LIST_HOLD; |
1143 | } else { | ||
1144 | cmdlist->data[cmdlist->last++] = G2D_INTEN; | ||
1145 | cmdlist->data[cmdlist->last++] = G2D_INTEN_ACF; | ||
866 | } | 1146 | } |
867 | 1147 | ||
868 | /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */ | 1148 | /* Check size of cmdlist: last 2 is about G2D_BITBLT_START */ |
@@ -887,7 +1167,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data, | |||
887 | if (ret < 0) | 1167 | if (ret < 0) |
888 | goto err_free_event; | 1168 | goto err_free_event; |
889 | 1169 | ||
890 | node->map_nr = req->cmd_buf_nr; | 1170 | node->buf_info.map_nr = req->cmd_buf_nr; |
891 | if (req->cmd_buf_nr) { | 1171 | if (req->cmd_buf_nr) { |
892 | struct drm_exynos_g2d_cmd *cmd_buf; | 1172 | struct drm_exynos_g2d_cmd *cmd_buf; |
893 | 1173 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c index 67e17ce112b6..0e6fe000578c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.c +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c | |||
@@ -164,6 +164,27 @@ out: | |||
164 | exynos_gem_obj = NULL; | 164 | exynos_gem_obj = NULL; |
165 | } | 165 | } |
166 | 166 | ||
167 | unsigned long exynos_drm_gem_get_size(struct drm_device *dev, | ||
168 | unsigned int gem_handle, | ||
169 | struct drm_file *file_priv) | ||
170 | { | ||
171 | struct exynos_drm_gem_obj *exynos_gem_obj; | ||
172 | struct drm_gem_object *obj; | ||
173 | |||
174 | obj = drm_gem_object_lookup(dev, file_priv, gem_handle); | ||
175 | if (!obj) { | ||
176 | DRM_ERROR("failed to lookup gem object.\n"); | ||
177 | return 0; | ||
178 | } | ||
179 | |||
180 | exynos_gem_obj = to_exynos_gem_obj(obj); | ||
181 | |||
182 | drm_gem_object_unreference_unlocked(obj); | ||
183 | |||
184 | return exynos_gem_obj->buffer->size; | ||
185 | } | ||
186 | |||
187 | |||
167 | struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, | 188 | struct exynos_drm_gem_obj *exynos_drm_gem_init(struct drm_device *dev, |
168 | unsigned long size) | 189 | unsigned long size) |
169 | { | 190 | { |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.h b/drivers/gpu/drm/exynos/exynos_drm_gem.h index 35ebac47dc2b..468766bee450 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_gem.h +++ b/drivers/gpu/drm/exynos/exynos_drm_gem.h | |||
@@ -130,6 +130,11 @@ int exynos_drm_gem_userptr_ioctl(struct drm_device *dev, void *data, | |||
130 | int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, | 130 | int exynos_drm_gem_get_ioctl(struct drm_device *dev, void *data, |
131 | struct drm_file *file_priv); | 131 | struct drm_file *file_priv); |
132 | 132 | ||
133 | /* get buffer size to gem handle. */ | ||
134 | unsigned long exynos_drm_gem_get_size(struct drm_device *dev, | ||
135 | unsigned int gem_handle, | ||
136 | struct drm_file *file_priv); | ||
137 | |||
133 | /* initialize gem object. */ | 138 | /* initialize gem object. */ |
134 | int exynos_drm_gem_init_object(struct drm_gem_object *obj); | 139 | int exynos_drm_gem_init_object(struct drm_gem_object *obj); |
135 | 140 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index 13ccbd4bcfaa..9504b0cd825a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c | |||
@@ -117,13 +117,12 @@ static struct edid *vidi_get_edid(struct device *dev, | |||
117 | } | 117 | } |
118 | 118 | ||
119 | edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; | 119 | edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; |
120 | edid = kzalloc(edid_len, GFP_KERNEL); | 120 | edid = kmemdup(ctx->raw_edid, edid_len, GFP_KERNEL); |
121 | if (!edid) { | 121 | if (!edid) { |
122 | DRM_DEBUG_KMS("failed to allocate edid\n"); | 122 | DRM_DEBUG_KMS("failed to allocate edid\n"); |
123 | return ERR_PTR(-ENOMEM); | 123 | return ERR_PTR(-ENOMEM); |
124 | } | 124 | } |
125 | 125 | ||
126 | memcpy(edid, ctx->raw_edid, edid_len); | ||
127 | return edid; | 126 | return edid; |
128 | } | 127 | } |
129 | 128 | ||
@@ -563,12 +562,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, | |||
563 | return -EINVAL; | 562 | return -EINVAL; |
564 | } | 563 | } |
565 | edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; | 564 | edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; |
566 | ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); | 565 | ctx->raw_edid = kmemdup(raw_edid, edid_len, GFP_KERNEL); |
567 | if (!ctx->raw_edid) { | 566 | if (!ctx->raw_edid) { |
568 | DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); | 567 | DRM_DEBUG_KMS("failed to allocate raw_edid.\n"); |
569 | return -ENOMEM; | 568 | return -ENOMEM; |
570 | } | 569 | } |
571 | memcpy(ctx->raw_edid, raw_edid, edid_len); | ||
572 | } else { | 570 | } else { |
573 | /* | 571 | /* |
574 | * with connection = 0, free raw_edid | 572 | * with connection = 0, free raw_edid |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index e919aba29b3d..2f4f72f07047 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -818,7 +818,7 @@ static void mixer_win_disable(void *ctx, int win) | |||
818 | mixer_ctx->win_data[win].enabled = false; | 818 | mixer_ctx->win_data[win].enabled = false; |
819 | } | 819 | } |
820 | 820 | ||
821 | int mixer_check_timing(void *ctx, struct fb_videomode *timing) | 821 | static int mixer_check_timing(void *ctx, struct fb_videomode *timing) |
822 | { | 822 | { |
823 | struct mixer_context *mixer_ctx = ctx; | 823 | struct mixer_context *mixer_ctx = ctx; |
824 | u32 w, h; | 824 | u32 w, h; |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index aae31489c893..7299ea45dd03 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -103,7 +103,7 @@ static const char *cache_level_str(int type) | |||
103 | static void | 103 | static void |
104 | describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) | 104 | describe_obj(struct seq_file *m, struct drm_i915_gem_object *obj) |
105 | { | 105 | { |
106 | seq_printf(m, "%p: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s", | 106 | seq_printf(m, "%pK: %s%s %8zdKiB %02x %02x %d %d %d%s%s%s", |
107 | &obj->base, | 107 | &obj->base, |
108 | get_pin_flag(obj), | 108 | get_pin_flag(obj), |
109 | get_tiling_flag(obj), | 109 | get_tiling_flag(obj), |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index c5b8c81b9440..e9b57893db2b 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -125,6 +125,11 @@ MODULE_PARM_DESC(preliminary_hw_support, | |||
125 | "Enable Haswell and ValleyView Support. " | 125 | "Enable Haswell and ValleyView Support. " |
126 | "(default: false)"); | 126 | "(default: false)"); |
127 | 127 | ||
128 | int i915_disable_power_well __read_mostly = 0; | ||
129 | module_param_named(disable_power_well, i915_disable_power_well, int, 0600); | ||
130 | MODULE_PARM_DESC(disable_power_well, | ||
131 | "Disable the power well when possible (default: false)"); | ||
132 | |||
128 | static struct drm_driver driver; | 133 | static struct drm_driver driver; |
129 | extern int intel_agp_enabled; | 134 | extern int intel_agp_enabled; |
130 | 135 | ||
@@ -379,15 +384,15 @@ static const struct pci_device_id pciidlist[] = { /* aka */ | |||
379 | INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ | 384 | INTEL_VGA_DEVICE(0x0A06, &intel_haswell_m_info), /* ULT GT1 mobile */ |
380 | INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ | 385 | INTEL_VGA_DEVICE(0x0A16, &intel_haswell_m_info), /* ULT GT2 mobile */ |
381 | INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ | 386 | INTEL_VGA_DEVICE(0x0A26, &intel_haswell_m_info), /* ULT GT2 mobile */ |
382 | INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT1 desktop */ | 387 | INTEL_VGA_DEVICE(0x0D02, &intel_haswell_d_info), /* CRW GT1 desktop */ |
388 | INTEL_VGA_DEVICE(0x0D12, &intel_haswell_d_info), /* CRW GT2 desktop */ | ||
383 | INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ | 389 | INTEL_VGA_DEVICE(0x0D22, &intel_haswell_d_info), /* CRW GT2 desktop */ |
384 | INTEL_VGA_DEVICE(0x0D32, &intel_haswell_d_info), /* CRW GT2 desktop */ | 390 | INTEL_VGA_DEVICE(0x0D0A, &intel_haswell_d_info), /* CRW GT1 server */ |
385 | INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT1 server */ | 391 | INTEL_VGA_DEVICE(0x0D1A, &intel_haswell_d_info), /* CRW GT2 server */ |
386 | INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ | 392 | INTEL_VGA_DEVICE(0x0D2A, &intel_haswell_d_info), /* CRW GT2 server */ |
387 | INTEL_VGA_DEVICE(0x0D3A, &intel_haswell_d_info), /* CRW GT2 server */ | 393 | INTEL_VGA_DEVICE(0x0D06, &intel_haswell_m_info), /* CRW GT1 mobile */ |
388 | INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT1 mobile */ | 394 | INTEL_VGA_DEVICE(0x0D16, &intel_haswell_m_info), /* CRW GT2 mobile */ |
389 | INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ | 395 | INTEL_VGA_DEVICE(0x0D26, &intel_haswell_m_info), /* CRW GT2 mobile */ |
390 | INTEL_VGA_DEVICE(0x0D36, &intel_haswell_m_info), /* CRW GT2 mobile */ | ||
391 | INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), | 396 | INTEL_VGA_DEVICE(0x0f30, &intel_valleyview_m_info), |
392 | INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), | 397 | INTEL_VGA_DEVICE(0x0157, &intel_valleyview_m_info), |
393 | INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), | 398 | INTEL_VGA_DEVICE(0x0155, &intel_valleyview_d_info), |
@@ -495,6 +500,7 @@ static int i915_drm_freeze(struct drm_device *dev) | |||
495 | intel_modeset_disable(dev); | 500 | intel_modeset_disable(dev); |
496 | 501 | ||
497 | drm_irq_uninstall(dev); | 502 | drm_irq_uninstall(dev); |
503 | dev_priv->enable_hotplug_processing = false; | ||
498 | } | 504 | } |
499 | 505 | ||
500 | i915_save_state(dev); | 506 | i915_save_state(dev); |
@@ -568,10 +574,20 @@ static int __i915_drm_thaw(struct drm_device *dev) | |||
568 | error = i915_gem_init_hw(dev); | 574 | error = i915_gem_init_hw(dev); |
569 | mutex_unlock(&dev->struct_mutex); | 575 | mutex_unlock(&dev->struct_mutex); |
570 | 576 | ||
577 | /* We need working interrupts for modeset enabling ... */ | ||
578 | drm_irq_install(dev); | ||
579 | |||
571 | intel_modeset_init_hw(dev); | 580 | intel_modeset_init_hw(dev); |
572 | intel_modeset_setup_hw_state(dev, false); | 581 | intel_modeset_setup_hw_state(dev, false); |
573 | drm_irq_install(dev); | 582 | |
583 | /* | ||
584 | * ... but also need to make sure that hotplug processing | ||
585 | * doesn't cause havoc. Like in the driver load code we don't | ||
586 | * bother with the tiny race here where we might loose hotplug | ||
587 | * notifications. | ||
588 | * */ | ||
574 | intel_hpd_init(dev); | 589 | intel_hpd_init(dev); |
590 | dev_priv->enable_hotplug_processing = true; | ||
575 | } | 591 | } |
576 | 592 | ||
577 | intel_opregion_init(dev); | 593 | intel_opregion_init(dev); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index e95337c97459..01769e2a9953 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -1398,6 +1398,7 @@ extern int i915_enable_fbc __read_mostly; | |||
1398 | extern bool i915_enable_hangcheck __read_mostly; | 1398 | extern bool i915_enable_hangcheck __read_mostly; |
1399 | extern int i915_enable_ppgtt __read_mostly; | 1399 | extern int i915_enable_ppgtt __read_mostly; |
1400 | extern unsigned int i915_preliminary_hw_support __read_mostly; | 1400 | extern unsigned int i915_preliminary_hw_support __read_mostly; |
1401 | extern int i915_disable_power_well __read_mostly; | ||
1401 | 1402 | ||
1402 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); | 1403 | extern int i915_suspend(struct drm_device *dev, pm_message_t state); |
1403 | extern int i915_resume(struct drm_device *dev); | 1404 | extern int i915_resume(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index 2f2daebd0eef..3b11ab0fbc96 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -732,6 +732,8 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, | |||
732 | int count) | 732 | int count) |
733 | { | 733 | { |
734 | int i; | 734 | int i; |
735 | int relocs_total = 0; | ||
736 | int relocs_max = INT_MAX / sizeof(struct drm_i915_gem_relocation_entry); | ||
735 | 737 | ||
736 | for (i = 0; i < count; i++) { | 738 | for (i = 0; i < count; i++) { |
737 | char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; | 739 | char __user *ptr = (char __user *)(uintptr_t)exec[i].relocs_ptr; |
@@ -740,10 +742,13 @@ validate_exec_list(struct drm_i915_gem_exec_object2 *exec, | |||
740 | if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS) | 742 | if (exec[i].flags & __EXEC_OBJECT_UNKNOWN_FLAGS) |
741 | return -EINVAL; | 743 | return -EINVAL; |
742 | 744 | ||
743 | /* First check for malicious input causing overflow */ | 745 | /* First check for malicious input causing overflow in |
744 | if (exec[i].relocation_count > | 746 | * the worst case where we need to allocate the entire |
745 | INT_MAX / sizeof(struct drm_i915_gem_relocation_entry)) | 747 | * relocation tree as a single array. |
748 | */ | ||
749 | if (exec[i].relocation_count > relocs_max - relocs_total) | ||
746 | return -EINVAL; | 750 | return -EINVAL; |
751 | relocs_total += exec[i].relocation_count; | ||
747 | 752 | ||
748 | length = exec[i].relocation_count * | 753 | length = exec[i].relocation_count * |
749 | sizeof(struct drm_i915_gem_relocation_entry); | 754 | sizeof(struct drm_i915_gem_relocation_entry); |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2cd97d1cc920..3c7bb0410b51 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -701,7 +701,7 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) | |||
701 | { | 701 | { |
702 | struct drm_device *dev = (struct drm_device *) arg; | 702 | struct drm_device *dev = (struct drm_device *) arg; |
703 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 703 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
704 | u32 de_iir, gt_iir, de_ier, pm_iir; | 704 | u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier; |
705 | irqreturn_t ret = IRQ_NONE; | 705 | irqreturn_t ret = IRQ_NONE; |
706 | int i; | 706 | int i; |
707 | 707 | ||
@@ -711,6 +711,15 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) | |||
711 | de_ier = I915_READ(DEIER); | 711 | de_ier = I915_READ(DEIER); |
712 | I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); | 712 | I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); |
713 | 713 | ||
714 | /* Disable south interrupts. We'll only write to SDEIIR once, so further | ||
715 | * interrupts will will be stored on its back queue, and then we'll be | ||
716 | * able to process them after we restore SDEIER (as soon as we restore | ||
717 | * it, we'll get an interrupt if SDEIIR still has something to process | ||
718 | * due to its back queue). */ | ||
719 | sde_ier = I915_READ(SDEIER); | ||
720 | I915_WRITE(SDEIER, 0); | ||
721 | POSTING_READ(SDEIER); | ||
722 | |||
714 | gt_iir = I915_READ(GTIIR); | 723 | gt_iir = I915_READ(GTIIR); |
715 | if (gt_iir) { | 724 | if (gt_iir) { |
716 | snb_gt_irq_handler(dev, dev_priv, gt_iir); | 725 | snb_gt_irq_handler(dev, dev_priv, gt_iir); |
@@ -759,6 +768,8 @@ static irqreturn_t ivybridge_irq_handler(int irq, void *arg) | |||
759 | 768 | ||
760 | I915_WRITE(DEIER, de_ier); | 769 | I915_WRITE(DEIER, de_ier); |
761 | POSTING_READ(DEIER); | 770 | POSTING_READ(DEIER); |
771 | I915_WRITE(SDEIER, sde_ier); | ||
772 | POSTING_READ(SDEIER); | ||
762 | 773 | ||
763 | return ret; | 774 | return ret; |
764 | } | 775 | } |
@@ -778,7 +789,7 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) | |||
778 | struct drm_device *dev = (struct drm_device *) arg; | 789 | struct drm_device *dev = (struct drm_device *) arg; |
779 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; | 790 | drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; |
780 | int ret = IRQ_NONE; | 791 | int ret = IRQ_NONE; |
781 | u32 de_iir, gt_iir, de_ier, pm_iir; | 792 | u32 de_iir, gt_iir, de_ier, pm_iir, sde_ier; |
782 | 793 | ||
783 | atomic_inc(&dev_priv->irq_received); | 794 | atomic_inc(&dev_priv->irq_received); |
784 | 795 | ||
@@ -787,6 +798,15 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) | |||
787 | I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); | 798 | I915_WRITE(DEIER, de_ier & ~DE_MASTER_IRQ_CONTROL); |
788 | POSTING_READ(DEIER); | 799 | POSTING_READ(DEIER); |
789 | 800 | ||
801 | /* Disable south interrupts. We'll only write to SDEIIR once, so further | ||
802 | * interrupts will will be stored on its back queue, and then we'll be | ||
803 | * able to process them after we restore SDEIER (as soon as we restore | ||
804 | * it, we'll get an interrupt if SDEIIR still has something to process | ||
805 | * due to its back queue). */ | ||
806 | sde_ier = I915_READ(SDEIER); | ||
807 | I915_WRITE(SDEIER, 0); | ||
808 | POSTING_READ(SDEIER); | ||
809 | |||
790 | de_iir = I915_READ(DEIIR); | 810 | de_iir = I915_READ(DEIIR); |
791 | gt_iir = I915_READ(GTIIR); | 811 | gt_iir = I915_READ(GTIIR); |
792 | pm_iir = I915_READ(GEN6_PMIIR); | 812 | pm_iir = I915_READ(GEN6_PMIIR); |
@@ -849,6 +869,8 @@ static irqreturn_t ironlake_irq_handler(int irq, void *arg) | |||
849 | done: | 869 | done: |
850 | I915_WRITE(DEIER, de_ier); | 870 | I915_WRITE(DEIER, de_ier); |
851 | POSTING_READ(DEIER); | 871 | POSTING_READ(DEIER); |
872 | I915_WRITE(SDEIER, sde_ier); | ||
873 | POSTING_READ(SDEIER); | ||
852 | 874 | ||
853 | return ret; | 875 | return ret; |
854 | } | 876 | } |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 527b664d3434..848992f67d56 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -1613,9 +1613,9 @@ | |||
1613 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) | 1613 | #define ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16) |
1614 | #define ADPA_USE_VGA_HVPOLARITY (1<<15) | 1614 | #define ADPA_USE_VGA_HVPOLARITY (1<<15) |
1615 | #define ADPA_SETS_HVPOLARITY 0 | 1615 | #define ADPA_SETS_HVPOLARITY 0 |
1616 | #define ADPA_VSYNC_CNTL_DISABLE (1<<11) | 1616 | #define ADPA_VSYNC_CNTL_DISABLE (1<<10) |
1617 | #define ADPA_VSYNC_CNTL_ENABLE 0 | 1617 | #define ADPA_VSYNC_CNTL_ENABLE 0 |
1618 | #define ADPA_HSYNC_CNTL_DISABLE (1<<10) | 1618 | #define ADPA_HSYNC_CNTL_DISABLE (1<<11) |
1619 | #define ADPA_HSYNC_CNTL_ENABLE 0 | 1619 | #define ADPA_HSYNC_CNTL_ENABLE 0 |
1620 | #define ADPA_VSYNC_ACTIVE_HIGH (1<<4) | 1620 | #define ADPA_VSYNC_ACTIVE_HIGH (1<<4) |
1621 | #define ADPA_VSYNC_ACTIVE_LOW 0 | 1621 | #define ADPA_VSYNC_ACTIVE_LOW 0 |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 969d08c72d10..32a3693905ec 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -88,7 +88,7 @@ static void intel_disable_crt(struct intel_encoder *encoder) | |||
88 | u32 temp; | 88 | u32 temp; |
89 | 89 | ||
90 | temp = I915_READ(crt->adpa_reg); | 90 | temp = I915_READ(crt->adpa_reg); |
91 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); | 91 | temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE; |
92 | temp &= ~ADPA_DAC_ENABLE; | 92 | temp &= ~ADPA_DAC_ENABLE; |
93 | I915_WRITE(crt->adpa_reg, temp); | 93 | I915_WRITE(crt->adpa_reg, temp); |
94 | } | 94 | } |
diff --git a/drivers/gpu/drm/i915/intel_ddi.c b/drivers/gpu/drm/i915/intel_ddi.c index d64af5aa4a1c..8d0bac3c35d7 100644 --- a/drivers/gpu/drm/i915/intel_ddi.c +++ b/drivers/gpu/drm/i915/intel_ddi.c | |||
@@ -1391,8 +1391,8 @@ void intel_ddi_prepare_link_retrain(struct drm_encoder *encoder) | |||
1391 | struct intel_dp *intel_dp = &intel_dig_port->dp; | 1391 | struct intel_dp *intel_dp = &intel_dig_port->dp; |
1392 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; | 1392 | struct drm_i915_private *dev_priv = encoder->dev->dev_private; |
1393 | enum port port = intel_dig_port->port; | 1393 | enum port port = intel_dig_port->port; |
1394 | bool wait; | ||
1395 | uint32_t val; | 1394 | uint32_t val; |
1395 | bool wait = false; | ||
1396 | 1396 | ||
1397 | if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { | 1397 | if (I915_READ(DP_TP_CTL(port)) & DP_TP_CTL_ENABLE) { |
1398 | val = I915_READ(DDI_BUF_CTL(port)); | 1398 | val = I915_READ(DDI_BUF_CTL(port)); |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a05ac2c91ba2..b20d50192fcc 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -3604,6 +3604,30 @@ static void intel_crtc_dpms_overlay(struct intel_crtc *intel_crtc, bool enable) | |||
3604 | */ | 3604 | */ |
3605 | } | 3605 | } |
3606 | 3606 | ||
3607 | /** | ||
3608 | * i9xx_fixup_plane - ugly workaround for G45 to fire up the hardware | ||
3609 | * cursor plane briefly if not already running after enabling the display | ||
3610 | * plane. | ||
3611 | * This workaround avoids occasional blank screens when self refresh is | ||
3612 | * enabled. | ||
3613 | */ | ||
3614 | static void | ||
3615 | g4x_fixup_plane(struct drm_i915_private *dev_priv, enum pipe pipe) | ||
3616 | { | ||
3617 | u32 cntl = I915_READ(CURCNTR(pipe)); | ||
3618 | |||
3619 | if ((cntl & CURSOR_MODE) == 0) { | ||
3620 | u32 fw_bcl_self = I915_READ(FW_BLC_SELF); | ||
3621 | |||
3622 | I915_WRITE(FW_BLC_SELF, fw_bcl_self & ~FW_BLC_SELF_EN); | ||
3623 | I915_WRITE(CURCNTR(pipe), CURSOR_MODE_64_ARGB_AX); | ||
3624 | intel_wait_for_vblank(dev_priv->dev, pipe); | ||
3625 | I915_WRITE(CURCNTR(pipe), cntl); | ||
3626 | I915_WRITE(CURBASE(pipe), I915_READ(CURBASE(pipe))); | ||
3627 | I915_WRITE(FW_BLC_SELF, fw_bcl_self); | ||
3628 | } | ||
3629 | } | ||
3630 | |||
3607 | static void i9xx_crtc_enable(struct drm_crtc *crtc) | 3631 | static void i9xx_crtc_enable(struct drm_crtc *crtc) |
3608 | { | 3632 | { |
3609 | struct drm_device *dev = crtc->dev; | 3633 | struct drm_device *dev = crtc->dev; |
@@ -3629,6 +3653,8 @@ static void i9xx_crtc_enable(struct drm_crtc *crtc) | |||
3629 | 3653 | ||
3630 | intel_enable_pipe(dev_priv, pipe, false); | 3654 | intel_enable_pipe(dev_priv, pipe, false); |
3631 | intel_enable_plane(dev_priv, plane, pipe); | 3655 | intel_enable_plane(dev_priv, plane, pipe); |
3656 | if (IS_G4X(dev)) | ||
3657 | g4x_fixup_plane(dev_priv, pipe); | ||
3632 | 3658 | ||
3633 | intel_crtc_load_lut(crtc); | 3659 | intel_crtc_load_lut(crtc); |
3634 | intel_update_fbc(dev); | 3660 | intel_update_fbc(dev); |
@@ -5745,6 +5771,11 @@ static int haswell_crtc_mode_set(struct drm_crtc *crtc, | |||
5745 | num_connectors++; | 5771 | num_connectors++; |
5746 | } | 5772 | } |
5747 | 5773 | ||
5774 | if (is_cpu_edp) | ||
5775 | intel_crtc->cpu_transcoder = TRANSCODER_EDP; | ||
5776 | else | ||
5777 | intel_crtc->cpu_transcoder = pipe; | ||
5778 | |||
5748 | /* We are not sure yet this won't happen. */ | 5779 | /* We are not sure yet this won't happen. */ |
5749 | WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n", | 5780 | WARN(!HAS_PCH_LPT(dev), "Unexpected PCH type %d\n", |
5750 | INTEL_PCH_TYPE(dev)); | 5781 | INTEL_PCH_TYPE(dev)); |
@@ -5811,11 +5842,6 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc, | |||
5811 | int pipe = intel_crtc->pipe; | 5842 | int pipe = intel_crtc->pipe; |
5812 | int ret; | 5843 | int ret; |
5813 | 5844 | ||
5814 | if (IS_HASWELL(dev) && intel_pipe_has_type(crtc, INTEL_OUTPUT_EDP)) | ||
5815 | intel_crtc->cpu_transcoder = TRANSCODER_EDP; | ||
5816 | else | ||
5817 | intel_crtc->cpu_transcoder = pipe; | ||
5818 | |||
5819 | drm_vblank_pre_modeset(dev, pipe); | 5845 | drm_vblank_pre_modeset(dev, pipe); |
5820 | 5846 | ||
5821 | ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, | 5847 | ret = dev_priv->display.crtc_mode_set(crtc, mode, adjusted_mode, |
@@ -7256,8 +7282,8 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7256 | { | 7282 | { |
7257 | struct drm_device *dev = crtc->dev; | 7283 | struct drm_device *dev = crtc->dev; |
7258 | struct drm_i915_private *dev_priv = dev->dev_private; | 7284 | struct drm_i915_private *dev_priv = dev->dev_private; |
7259 | struct intel_framebuffer *intel_fb; | 7285 | struct drm_framebuffer *old_fb = crtc->fb; |
7260 | struct drm_i915_gem_object *obj; | 7286 | struct drm_i915_gem_object *obj = to_intel_framebuffer(fb)->obj; |
7261 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 7287 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
7262 | struct intel_unpin_work *work; | 7288 | struct intel_unpin_work *work; |
7263 | unsigned long flags; | 7289 | unsigned long flags; |
@@ -7282,8 +7308,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7282 | 7308 | ||
7283 | work->event = event; | 7309 | work->event = event; |
7284 | work->crtc = crtc; | 7310 | work->crtc = crtc; |
7285 | intel_fb = to_intel_framebuffer(crtc->fb); | 7311 | work->old_fb_obj = to_intel_framebuffer(old_fb)->obj; |
7286 | work->old_fb_obj = intel_fb->obj; | ||
7287 | INIT_WORK(&work->work, intel_unpin_work_fn); | 7312 | INIT_WORK(&work->work, intel_unpin_work_fn); |
7288 | 7313 | ||
7289 | ret = drm_vblank_get(dev, intel_crtc->pipe); | 7314 | ret = drm_vblank_get(dev, intel_crtc->pipe); |
@@ -7303,9 +7328,6 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7303 | intel_crtc->unpin_work = work; | 7328 | intel_crtc->unpin_work = work; |
7304 | spin_unlock_irqrestore(&dev->event_lock, flags); | 7329 | spin_unlock_irqrestore(&dev->event_lock, flags); |
7305 | 7330 | ||
7306 | intel_fb = to_intel_framebuffer(fb); | ||
7307 | obj = intel_fb->obj; | ||
7308 | |||
7309 | if (atomic_read(&intel_crtc->unpin_work_count) >= 2) | 7331 | if (atomic_read(&intel_crtc->unpin_work_count) >= 2) |
7310 | flush_workqueue(dev_priv->wq); | 7332 | flush_workqueue(dev_priv->wq); |
7311 | 7333 | ||
@@ -7340,6 +7362,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
7340 | 7362 | ||
7341 | cleanup_pending: | 7363 | cleanup_pending: |
7342 | atomic_dec(&intel_crtc->unpin_work_count); | 7364 | atomic_dec(&intel_crtc->unpin_work_count); |
7365 | crtc->fb = old_fb; | ||
7343 | drm_gem_object_unreference(&work->old_fb_obj->base); | 7366 | drm_gem_object_unreference(&work->old_fb_obj->base); |
7344 | drm_gem_object_unreference(&obj->base); | 7367 | drm_gem_object_unreference(&obj->base); |
7345 | mutex_unlock(&dev->struct_mutex); | 7368 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index f61cb7998c72..d7d4afe01341 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -353,7 +353,8 @@ intel_dp_aux_wait_done(struct intel_dp *intel_dp, bool has_aux_irq) | |||
353 | 353 | ||
354 | #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) | 354 | #define C (((status = I915_READ_NOTRACE(ch_ctl)) & DP_AUX_CH_CTL_SEND_BUSY) == 0) |
355 | if (has_aux_irq) | 355 | if (has_aux_irq) |
356 | done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, 10); | 356 | done = wait_event_timeout(dev_priv->gmbus_wait_queue, C, |
357 | msecs_to_jiffies(10)); | ||
357 | else | 358 | else |
358 | done = wait_for_atomic(C, 10) == 0; | 359 | done = wait_for_atomic(C, 10) == 0; |
359 | if (!done) | 360 | if (!done) |
@@ -819,6 +820,7 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
819 | struct intel_link_m_n m_n; | 820 | struct intel_link_m_n m_n; |
820 | int pipe = intel_crtc->pipe; | 821 | int pipe = intel_crtc->pipe; |
821 | enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; | 822 | enum transcoder cpu_transcoder = intel_crtc->cpu_transcoder; |
823 | int target_clock; | ||
822 | 824 | ||
823 | /* | 825 | /* |
824 | * Find the lane count in the intel_encoder private | 826 | * Find the lane count in the intel_encoder private |
@@ -834,13 +836,22 @@ intel_dp_set_m_n(struct drm_crtc *crtc, struct drm_display_mode *mode, | |||
834 | } | 836 | } |
835 | } | 837 | } |
836 | 838 | ||
839 | target_clock = mode->clock; | ||
840 | for_each_encoder_on_crtc(dev, crtc, intel_encoder) { | ||
841 | if (intel_encoder->type == INTEL_OUTPUT_EDP) { | ||
842 | target_clock = intel_edp_target_clock(intel_encoder, | ||
843 | mode); | ||
844 | break; | ||
845 | } | ||
846 | } | ||
847 | |||
837 | /* | 848 | /* |
838 | * Compute the GMCH and Link ratios. The '3' here is | 849 | * Compute the GMCH and Link ratios. The '3' here is |
839 | * the number of bytes_per_pixel post-LUT, which we always | 850 | * the number of bytes_per_pixel post-LUT, which we always |
840 | * set up for 8-bits of R/G/B, or 3 bytes total. | 851 | * set up for 8-bits of R/G/B, or 3 bytes total. |
841 | */ | 852 | */ |
842 | intel_link_compute_m_n(intel_crtc->bpp, lane_count, | 853 | intel_link_compute_m_n(intel_crtc->bpp, lane_count, |
843 | mode->clock, adjusted_mode->clock, &m_n); | 854 | target_clock, adjusted_mode->clock, &m_n); |
844 | 855 | ||
845 | if (IS_HASWELL(dev)) { | 856 | if (IS_HASWELL(dev)) { |
846 | I915_WRITE(PIPE_DATA_M1(cpu_transcoder), | 857 | I915_WRITE(PIPE_DATA_M1(cpu_transcoder), |
@@ -1929,7 +1940,7 @@ intel_dp_start_link_train(struct intel_dp *intel_dp) | |||
1929 | for (i = 0; i < intel_dp->lane_count; i++) | 1940 | for (i = 0; i < intel_dp->lane_count; i++) |
1930 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) | 1941 | if ((intel_dp->train_set[i] & DP_TRAIN_MAX_SWING_REACHED) == 0) |
1931 | break; | 1942 | break; |
1932 | if (i == intel_dp->lane_count && voltage_tries == 5) { | 1943 | if (i == intel_dp->lane_count) { |
1933 | ++loop_tries; | 1944 | ++loop_tries; |
1934 | if (loop_tries == 5) { | 1945 | if (loop_tries == 5) { |
1935 | DRM_DEBUG_KMS("too many full retries, give up\n"); | 1946 | DRM_DEBUG_KMS("too many full retries, give up\n"); |
diff --git a/drivers/gpu/drm/i915/intel_i2c.c b/drivers/gpu/drm/i915/intel_i2c.c index acf8aec9ada7..ef4744e1bf0b 100644 --- a/drivers/gpu/drm/i915/intel_i2c.c +++ b/drivers/gpu/drm/i915/intel_i2c.c | |||
@@ -203,7 +203,13 @@ intel_gpio_setup(struct intel_gmbus *bus, u32 pin) | |||
203 | algo->data = bus; | 203 | algo->data = bus; |
204 | } | 204 | } |
205 | 205 | ||
206 | #define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 4) | 206 | /* |
207 | * gmbus on gen4 seems to be able to generate legacy interrupts even when in MSI | ||
208 | * mode. This results in spurious interrupt warnings if the legacy irq no. is | ||
209 | * shared with another device. The kernel then disables that interrupt source | ||
210 | * and so prevents the other device from working properly. | ||
211 | */ | ||
212 | #define HAS_GMBUS_IRQ(dev) (INTEL_INFO(dev)->gen >= 5) | ||
207 | static int | 213 | static int |
208 | gmbus_wait_hw_status(struct drm_i915_private *dev_priv, | 214 | gmbus_wait_hw_status(struct drm_i915_private *dev_priv, |
209 | u32 gmbus2_status, | 215 | u32 gmbus2_status, |
@@ -214,6 +220,9 @@ gmbus_wait_hw_status(struct drm_i915_private *dev_priv, | |||
214 | u32 gmbus2 = 0; | 220 | u32 gmbus2 = 0; |
215 | DEFINE_WAIT(wait); | 221 | DEFINE_WAIT(wait); |
216 | 222 | ||
223 | if (!HAS_GMBUS_IRQ(dev_priv->dev)) | ||
224 | gmbus4_irq_en = 0; | ||
225 | |||
217 | /* Important: The hw handles only the first bit, so set only one! Since | 226 | /* Important: The hw handles only the first bit, so set only one! Since |
218 | * we also need to check for NAKs besides the hw ready/idle signal, we | 227 | * we also need to check for NAKs besides the hw ready/idle signal, we |
219 | * need to wake up periodically and check that ourselves. */ | 228 | * need to wake up periodically and check that ourselves. */ |
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c index a3730e0289e5..bee8cb6108a7 100644 --- a/drivers/gpu/drm/i915/intel_panel.c +++ b/drivers/gpu/drm/i915/intel_panel.c | |||
@@ -321,9 +321,6 @@ void intel_panel_enable_backlight(struct drm_device *dev, | |||
321 | if (dev_priv->backlight_level == 0) | 321 | if (dev_priv->backlight_level == 0) |
322 | dev_priv->backlight_level = intel_panel_get_max_backlight(dev); | 322 | dev_priv->backlight_level = intel_panel_get_max_backlight(dev); |
323 | 323 | ||
324 | dev_priv->backlight_enabled = true; | ||
325 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); | ||
326 | |||
327 | if (INTEL_INFO(dev)->gen >= 4) { | 324 | if (INTEL_INFO(dev)->gen >= 4) { |
328 | uint32_t reg, tmp; | 325 | uint32_t reg, tmp; |
329 | 326 | ||
@@ -359,12 +356,12 @@ void intel_panel_enable_backlight(struct drm_device *dev, | |||
359 | } | 356 | } |
360 | 357 | ||
361 | set_level: | 358 | set_level: |
362 | /* Check the current backlight level and try to set again if it's zero. | 359 | /* Call below after setting BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1. |
363 | * On some machines, BLC_PWM_CPU_CTL is cleared to zero automatically | 360 | * BLC_PWM_CPU_CTL may be cleared to zero automatically when these |
364 | * when BLC_PWM_CPU_CTL2 and BLC_PWM_PCH_CTL1 are written. | 361 | * registers are set. |
365 | */ | 362 | */ |
366 | if (!intel_panel_get_backlight(dev)) | 363 | dev_priv->backlight_enabled = true; |
367 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); | 364 | intel_panel_actually_set_backlight(dev, dev_priv->backlight_level); |
368 | } | 365 | } |
369 | 366 | ||
370 | static void intel_panel_init_backlight(struct drm_device *dev) | 367 | static void intel_panel_init_backlight(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 61fee7fcdc2c..adca00783e61 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -2574,7 +2574,7 @@ static void gen6_enable_rps(struct drm_device *dev) | |||
2574 | I915_WRITE(GEN6_RC_SLEEP, 0); | 2574 | I915_WRITE(GEN6_RC_SLEEP, 0); |
2575 | I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); | 2575 | I915_WRITE(GEN6_RC1e_THRESHOLD, 1000); |
2576 | I915_WRITE(GEN6_RC6_THRESHOLD, 50000); | 2576 | I915_WRITE(GEN6_RC6_THRESHOLD, 50000); |
2577 | I915_WRITE(GEN6_RC6p_THRESHOLD, 100000); | 2577 | I915_WRITE(GEN6_RC6p_THRESHOLD, 150000); |
2578 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ | 2578 | I915_WRITE(GEN6_RC6pp_THRESHOLD, 64000); /* unused */ |
2579 | 2579 | ||
2580 | /* Check if we are enabling RC6 */ | 2580 | /* Check if we are enabling RC6 */ |
@@ -4079,6 +4079,9 @@ void intel_set_power_well(struct drm_device *dev, bool enable) | |||
4079 | if (!IS_HASWELL(dev)) | 4079 | if (!IS_HASWELL(dev)) |
4080 | return; | 4080 | return; |
4081 | 4081 | ||
4082 | if (!i915_disable_power_well && !enable) | ||
4083 | return; | ||
4084 | |||
4082 | tmp = I915_READ(HSW_PWR_WELL_DRIVER); | 4085 | tmp = I915_READ(HSW_PWR_WELL_DRIVER); |
4083 | is_enabled = tmp & HSW_PWR_WELL_STATE; | 4086 | is_enabled = tmp & HSW_PWR_WELL_STATE; |
4084 | enable_requested = tmp & HSW_PWR_WELL_ENABLE; | 4087 | enable_requested = tmp & HSW_PWR_WELL_ENABLE; |
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h index 5ea5033eae0a..4d932c46725d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_drv.h +++ b/drivers/gpu/drm/mgag200/mgag200_drv.h | |||
@@ -112,7 +112,6 @@ struct mga_framebuffer { | |||
112 | struct mga_fbdev { | 112 | struct mga_fbdev { |
113 | struct drm_fb_helper helper; | 113 | struct drm_fb_helper helper; |
114 | struct mga_framebuffer mfb; | 114 | struct mga_framebuffer mfb; |
115 | struct list_head fbdev_list; | ||
116 | void *sysram; | 115 | void *sysram; |
117 | int size; | 116 | int size; |
118 | struct ttm_bo_kmap_obj mapping; | 117 | struct ttm_bo_kmap_obj mapping; |
diff --git a/drivers/gpu/drm/mgag200/mgag200_i2c.c b/drivers/gpu/drm/mgag200/mgag200_i2c.c index 5a88ec51b513..d3dcf54e6233 100644 --- a/drivers/gpu/drm/mgag200/mgag200_i2c.c +++ b/drivers/gpu/drm/mgag200/mgag200_i2c.c | |||
@@ -92,6 +92,7 @@ struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev) | |||
92 | int ret; | 92 | int ret; |
93 | int data, clock; | 93 | int data, clock; |
94 | 94 | ||
95 | WREG_DAC(MGA1064_GEN_IO_CTL2, 1); | ||
95 | WREG_DAC(MGA1064_GEN_IO_DATA, 0xff); | 96 | WREG_DAC(MGA1064_GEN_IO_DATA, 0xff); |
96 | WREG_DAC(MGA1064_GEN_IO_CTL, 0); | 97 | WREG_DAC(MGA1064_GEN_IO_CTL, 0); |
97 | 98 | ||
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c index d3d99a28ddef..fe22bb780e1d 100644 --- a/drivers/gpu/drm/mgag200/mgag200_mode.c +++ b/drivers/gpu/drm/mgag200/mgag200_mode.c | |||
@@ -382,19 +382,19 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) | |||
382 | m = n = p = 0; | 382 | m = n = p = 0; |
383 | vcomax = 800000; | 383 | vcomax = 800000; |
384 | vcomin = 400000; | 384 | vcomin = 400000; |
385 | pllreffreq = 3333; | 385 | pllreffreq = 33333; |
386 | 386 | ||
387 | delta = 0xffffffff; | 387 | delta = 0xffffffff; |
388 | permitteddelta = clock * 5 / 1000; | 388 | permitteddelta = clock * 5 / 1000; |
389 | 389 | ||
390 | for (testp = 16; testp > 0; testp--) { | 390 | for (testp = 16; testp > 0; testp >>= 1) { |
391 | if (clock * testp > vcomax) | 391 | if (clock * testp > vcomax) |
392 | continue; | 392 | continue; |
393 | if (clock * testp < vcomin) | 393 | if (clock * testp < vcomin) |
394 | continue; | 394 | continue; |
395 | 395 | ||
396 | for (testm = 1; testm < 33; testm++) { | 396 | for (testm = 1; testm < 33; testm++) { |
397 | for (testn = 1; testn < 257; testn++) { | 397 | for (testn = 17; testn < 257; testn++) { |
398 | computed = (pllreffreq * testn) / | 398 | computed = (pllreffreq * testn) / |
399 | (testm * testp); | 399 | (testm * testp); |
400 | if (computed > clock) | 400 | if (computed > clock) |
@@ -404,11 +404,11 @@ static int mga_g200eh_set_plls(struct mga_device *mdev, long clock) | |||
404 | if (tmpdelta < delta) { | 404 | if (tmpdelta < delta) { |
405 | delta = tmpdelta; | 405 | delta = tmpdelta; |
406 | n = testn - 1; | 406 | n = testn - 1; |
407 | m = (testm - 1) | ((n >> 1) & 0x80); | 407 | m = (testm - 1); |
408 | p = testp - 1; | 408 | p = testp - 1; |
409 | } | 409 | } |
410 | if ((clock * testp) >= 600000) | 410 | if ((clock * testp) >= 600000) |
411 | p |= 80; | 411 | p |= 0x80; |
412 | } | 412 | } |
413 | } | 413 | } |
414 | } | 414 | } |
@@ -1406,6 +1406,14 @@ static int mga_vga_get_modes(struct drm_connector *connector) | |||
1406 | static int mga_vga_mode_valid(struct drm_connector *connector, | 1406 | static int mga_vga_mode_valid(struct drm_connector *connector, |
1407 | struct drm_display_mode *mode) | 1407 | struct drm_display_mode *mode) |
1408 | { | 1408 | { |
1409 | struct drm_device *dev = connector->dev; | ||
1410 | struct mga_device *mdev = (struct mga_device*)dev->dev_private; | ||
1411 | struct mga_fbdev *mfbdev = mdev->mfbdev; | ||
1412 | struct drm_fb_helper *fb_helper = &mfbdev->helper; | ||
1413 | struct drm_fb_helper_connector *fb_helper_conn = NULL; | ||
1414 | int bpp = 32; | ||
1415 | int i = 0; | ||
1416 | |||
1409 | /* FIXME: Add bandwidth and g200se limitations */ | 1417 | /* FIXME: Add bandwidth and g200se limitations */ |
1410 | 1418 | ||
1411 | if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || | 1419 | if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 || |
@@ -1415,6 +1423,25 @@ static int mga_vga_mode_valid(struct drm_connector *connector, | |||
1415 | return MODE_BAD; | 1423 | return MODE_BAD; |
1416 | } | 1424 | } |
1417 | 1425 | ||
1426 | /* Validate the mode input by the user */ | ||
1427 | for (i = 0; i < fb_helper->connector_count; i++) { | ||
1428 | if (fb_helper->connector_info[i]->connector == connector) { | ||
1429 | /* Found the helper for this connector */ | ||
1430 | fb_helper_conn = fb_helper->connector_info[i]; | ||
1431 | if (fb_helper_conn->cmdline_mode.specified) { | ||
1432 | if (fb_helper_conn->cmdline_mode.bpp_specified) { | ||
1433 | bpp = fb_helper_conn->cmdline_mode.bpp; | ||
1434 | } | ||
1435 | } | ||
1436 | } | ||
1437 | } | ||
1438 | |||
1439 | if ((mode->hdisplay * mode->vdisplay * (bpp/8)) > mdev->mc.vram_size) { | ||
1440 | if (fb_helper_conn) | ||
1441 | fb_helper_conn->cmdline_mode.specified = false; | ||
1442 | return MODE_BAD; | ||
1443 | } | ||
1444 | |||
1418 | return MODE_OK; | 1445 | return MODE_OK; |
1419 | } | 1446 | } |
1420 | 1447 | ||
diff --git a/drivers/gpu/drm/nouveau/core/core/object.c b/drivers/gpu/drm/nouveau/core/core/object.c index 0daab62ea14c..3b2e7b6304d3 100644 --- a/drivers/gpu/drm/nouveau/core/core/object.c +++ b/drivers/gpu/drm/nouveau/core/core/object.c | |||
@@ -278,7 +278,6 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle) | |||
278 | struct nouveau_object *parent = NULL; | 278 | struct nouveau_object *parent = NULL; |
279 | struct nouveau_object *namedb = NULL; | 279 | struct nouveau_object *namedb = NULL; |
280 | struct nouveau_handle *handle = NULL; | 280 | struct nouveau_handle *handle = NULL; |
281 | int ret = -EINVAL; | ||
282 | 281 | ||
283 | parent = nouveau_handle_ref(client, _parent); | 282 | parent = nouveau_handle_ref(client, _parent); |
284 | if (!parent) | 283 | if (!parent) |
@@ -295,7 +294,7 @@ nouveau_object_del(struct nouveau_object *client, u32 _parent, u32 _handle) | |||
295 | } | 294 | } |
296 | 295 | ||
297 | nouveau_object_ref(NULL, &parent); | 296 | nouveau_object_ref(NULL, &parent); |
298 | return ret; | 297 | return handle ? 0 : -EINVAL; |
299 | } | 298 | } |
300 | 299 | ||
301 | int | 300 | int |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 5fa13267bd9f..02e369f80449 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
@@ -544,13 +544,13 @@ nv50_disp_curs_ofuncs = { | |||
544 | static void | 544 | static void |
545 | nv50_disp_base_vblank_enable(struct nouveau_event *event, int head) | 545 | nv50_disp_base_vblank_enable(struct nouveau_event *event, int head) |
546 | { | 546 | { |
547 | nv_mask(event->priv, 0x61002c, (1 << head), (1 << head)); | 547 | nv_mask(event->priv, 0x61002c, (4 << head), (4 << head)); |
548 | } | 548 | } |
549 | 549 | ||
550 | static void | 550 | static void |
551 | nv50_disp_base_vblank_disable(struct nouveau_event *event, int head) | 551 | nv50_disp_base_vblank_disable(struct nouveau_event *event, int head) |
552 | { | 552 | { |
553 | nv_mask(event->priv, 0x61002c, (1 << head), (0 << head)); | 553 | nv_mask(event->priv, 0x61002c, (4 << head), 0); |
554 | } | 554 | } |
555 | 555 | ||
556 | static int | 556 | static int |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c index 61cec0f6ff1c..4857f913efdd 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nve0.c | |||
@@ -350,7 +350,7 @@ nve0_graph_init_gpc_0(struct nvc0_graph_priv *priv) | |||
350 | nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); | 350 | nv_wr32(priv, GPC_UNIT(gpc, 0x0918), magicgpc918); |
351 | } | 351 | } |
352 | 352 | ||
353 | nv_wr32(priv, GPC_BCAST(0x1bd4), magicgpc918); | 353 | nv_wr32(priv, GPC_BCAST(0x3fd4), magicgpc918); |
354 | nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); | 354 | nv_wr32(priv, GPC_BCAST(0x08ac), nv_rd32(priv, 0x100800)); |
355 | } | 355 | } |
356 | 356 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h index 6b17b614629f..0b20fc0d19c1 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/therm.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/therm.h | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <core/device.h> | 4 | #include <core/device.h> |
5 | #include <core/subdev.h> | 5 | #include <core/subdev.h> |
6 | 6 | ||
7 | enum nouveau_therm_mode { | 7 | enum nouveau_therm_fan_mode { |
8 | NOUVEAU_THERM_CTRL_NONE = 0, | 8 | NOUVEAU_THERM_CTRL_NONE = 0, |
9 | NOUVEAU_THERM_CTRL_MANUAL = 1, | 9 | NOUVEAU_THERM_CTRL_MANUAL = 1, |
10 | NOUVEAU_THERM_CTRL_AUTO = 2, | 10 | NOUVEAU_THERM_CTRL_AUTO = 2, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 2cc1e6a5eb6a..9c41b58d57e2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c | |||
@@ -869,7 +869,7 @@ init_idx_addr_latched(struct nvbios_init *init) | |||
869 | init->offset += 2; | 869 | init->offset += 2; |
870 | 870 | ||
871 | init_wr32(init, dreg, idata); | 871 | init_wr32(init, dreg, idata); |
872 | init_mask(init, creg, ~mask, data | idata); | 872 | init_mask(init, creg, ~mask, data | iaddr); |
873 | } | 873 | } |
874 | } | 874 | } |
875 | 875 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index a114a0ed7e98..2e98e8a3f1aa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | |||
@@ -142,6 +142,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent, | |||
142 | /* drop port's i2c subdev refcount, i2c handles this itself */ | 142 | /* drop port's i2c subdev refcount, i2c handles this itself */ |
143 | if (ret == 0) { | 143 | if (ret == 0) { |
144 | list_add_tail(&port->head, &i2c->ports); | 144 | list_add_tail(&port->head, &i2c->ports); |
145 | atomic_dec(&parent->refcount); | ||
145 | atomic_dec(&engine->refcount); | 146 | atomic_dec(&engine->refcount); |
146 | } | 147 | } |
147 | 148 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index f794dc89a3b2..a00a5a76e2d6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c | |||
@@ -134,7 +134,7 @@ nouveau_therm_alarm(struct nouveau_alarm *alarm) | |||
134 | } | 134 | } |
135 | 135 | ||
136 | int | 136 | int |
137 | nouveau_therm_mode(struct nouveau_therm *therm, int mode) | 137 | nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode) |
138 | { | 138 | { |
139 | struct nouveau_therm_priv *priv = (void *)therm; | 139 | struct nouveau_therm_priv *priv = (void *)therm; |
140 | struct nouveau_device *device = nv_device(therm); | 140 | struct nouveau_device *device = nv_device(therm); |
@@ -149,10 +149,15 @@ nouveau_therm_mode(struct nouveau_therm *therm, int mode) | |||
149 | (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) | 149 | (mode != NOUVEAU_THERM_CTRL_NONE && device->card_type >= NV_C0)) |
150 | return -EINVAL; | 150 | return -EINVAL; |
151 | 151 | ||
152 | /* do not allow automatic fan management if the thermal sensor is | ||
153 | * not available */ | ||
154 | if (priv->mode == 2 && therm->temp_get(therm) < 0) | ||
155 | return -EINVAL; | ||
156 | |||
152 | if (priv->mode == mode) | 157 | if (priv->mode == mode) |
153 | return 0; | 158 | return 0; |
154 | 159 | ||
155 | nv_info(therm, "Thermal management: %s\n", name[mode]); | 160 | nv_info(therm, "fan management: %s\n", name[mode]); |
156 | nouveau_therm_update(therm, mode); | 161 | nouveau_therm_update(therm, mode); |
157 | return 0; | 162 | return 0; |
158 | } | 163 | } |
@@ -213,7 +218,7 @@ nouveau_therm_attr_set(struct nouveau_therm *therm, | |||
213 | priv->fan->bios.max_duty = value; | 218 | priv->fan->bios.max_duty = value; |
214 | return 0; | 219 | return 0; |
215 | case NOUVEAU_THERM_ATTR_FAN_MODE: | 220 | case NOUVEAU_THERM_ATTR_FAN_MODE: |
216 | return nouveau_therm_mode(therm, value); | 221 | return nouveau_therm_fan_mode(therm, value); |
217 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: | 222 | case NOUVEAU_THERM_ATTR_THRS_FAN_BOOST: |
218 | priv->bios_sensor.thrs_fan_boost.temp = value; | 223 | priv->bios_sensor.thrs_fan_boost.temp = value; |
219 | priv->sensor.program_alarms(therm); | 224 | priv->sensor.program_alarms(therm); |
@@ -263,7 +268,7 @@ _nouveau_therm_init(struct nouveau_object *object) | |||
263 | return ret; | 268 | return ret; |
264 | 269 | ||
265 | if (priv->suspend >= 0) | 270 | if (priv->suspend >= 0) |
266 | nouveau_therm_mode(therm, priv->mode); | 271 | nouveau_therm_fan_mode(therm, priv->mode); |
267 | priv->sensor.program_alarms(therm); | 272 | priv->sensor.program_alarms(therm); |
268 | return 0; | 273 | return 0; |
269 | } | 274 | } |
@@ -313,11 +318,12 @@ nouveau_therm_create_(struct nouveau_object *parent, | |||
313 | int | 318 | int |
314 | nouveau_therm_preinit(struct nouveau_therm *therm) | 319 | nouveau_therm_preinit(struct nouveau_therm *therm) |
315 | { | 320 | { |
316 | nouveau_therm_ic_ctor(therm); | ||
317 | nouveau_therm_sensor_ctor(therm); | 321 | nouveau_therm_sensor_ctor(therm); |
322 | nouveau_therm_ic_ctor(therm); | ||
318 | nouveau_therm_fan_ctor(therm); | 323 | nouveau_therm_fan_ctor(therm); |
319 | 324 | ||
320 | nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_NONE); | 325 | nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_NONE); |
326 | nouveau_therm_sensor_preinit(therm); | ||
321 | return 0; | 327 | return 0; |
322 | } | 328 | } |
323 | 329 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c index e24090bac195..8b3adec5fbb1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/ic.c | |||
@@ -32,6 +32,7 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, | |||
32 | struct i2c_board_info *info) | 32 | struct i2c_board_info *info) |
33 | { | 33 | { |
34 | struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); | 34 | struct nouveau_therm_priv *priv = (void *)nouveau_therm(i2c); |
35 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; | ||
35 | struct i2c_client *client; | 36 | struct i2c_client *client; |
36 | 37 | ||
37 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); | 38 | request_module("%s%s", I2C_MODULE_PREFIX, info->type); |
@@ -46,8 +47,9 @@ probe_monitoring_device(struct nouveau_i2c_port *i2c, | |||
46 | } | 47 | } |
47 | 48 | ||
48 | nv_info(priv, | 49 | nv_info(priv, |
49 | "Found an %s at address 0x%x (controlled by lm_sensors)\n", | 50 | "Found an %s at address 0x%x (controlled by lm_sensors, " |
50 | info->type, info->addr); | 51 | "temp offset %+i C)\n", |
52 | info->type, info->addr, sensor->offset_constant); | ||
51 | priv->ic = client; | 53 | priv->ic = client; |
52 | 54 | ||
53 | return true; | 55 | return true; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c index 0f5363edb964..a70d1b7e397b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/nv40.c | |||
@@ -29,54 +29,83 @@ struct nv40_therm_priv { | |||
29 | struct nouveau_therm_priv base; | 29 | struct nouveau_therm_priv base; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | enum nv40_sensor_style { INVALID_STYLE = -1, OLD_STYLE = 0, NEW_STYLE = 1 }; | ||
33 | |||
34 | static enum nv40_sensor_style | ||
35 | nv40_sensor_style(struct nouveau_therm *therm) | ||
36 | { | ||
37 | struct nouveau_device *device = nv_device(therm); | ||
38 | |||
39 | switch (device->chipset) { | ||
40 | case 0x43: | ||
41 | case 0x44: | ||
42 | case 0x4a: | ||
43 | case 0x47: | ||
44 | return OLD_STYLE; | ||
45 | |||
46 | case 0x46: | ||
47 | case 0x49: | ||
48 | case 0x4b: | ||
49 | case 0x4e: | ||
50 | case 0x4c: | ||
51 | case 0x67: | ||
52 | case 0x68: | ||
53 | case 0x63: | ||
54 | return NEW_STYLE; | ||
55 | default: | ||
56 | return INVALID_STYLE; | ||
57 | } | ||
58 | } | ||
59 | |||
32 | static int | 60 | static int |
33 | nv40_sensor_setup(struct nouveau_therm *therm) | 61 | nv40_sensor_setup(struct nouveau_therm *therm) |
34 | { | 62 | { |
35 | struct nouveau_device *device = nv_device(therm); | 63 | enum nv40_sensor_style style = nv40_sensor_style(therm); |
36 | 64 | ||
37 | /* enable ADC readout and disable the ALARM threshold */ | 65 | /* enable ADC readout and disable the ALARM threshold */ |
38 | if (device->chipset >= 0x46) { | 66 | if (style == NEW_STYLE) { |
39 | nv_mask(therm, 0x15b8, 0x80000000, 0); | 67 | nv_mask(therm, 0x15b8, 0x80000000, 0); |
40 | nv_wr32(therm, 0x15b0, 0x80003fff); | 68 | nv_wr32(therm, 0x15b0, 0x80003fff); |
41 | mdelay(10); /* wait for the temperature to stabilize */ | 69 | mdelay(20); /* wait for the temperature to stabilize */ |
42 | return nv_rd32(therm, 0x15b4) & 0x3fff; | 70 | return nv_rd32(therm, 0x15b4) & 0x3fff; |
43 | } else { | 71 | } else if (style == OLD_STYLE) { |
44 | nv_wr32(therm, 0x15b0, 0xff); | 72 | nv_wr32(therm, 0x15b0, 0xff); |
73 | mdelay(20); /* wait for the temperature to stabilize */ | ||
45 | return nv_rd32(therm, 0x15b4) & 0xff; | 74 | return nv_rd32(therm, 0x15b4) & 0xff; |
46 | } | 75 | } else |
76 | return -ENODEV; | ||
47 | } | 77 | } |
48 | 78 | ||
49 | static int | 79 | static int |
50 | nv40_temp_get(struct nouveau_therm *therm) | 80 | nv40_temp_get(struct nouveau_therm *therm) |
51 | { | 81 | { |
52 | struct nouveau_therm_priv *priv = (void *)therm; | 82 | struct nouveau_therm_priv *priv = (void *)therm; |
53 | struct nouveau_device *device = nv_device(therm); | ||
54 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; | 83 | struct nvbios_therm_sensor *sensor = &priv->bios_sensor; |
84 | enum nv40_sensor_style style = nv40_sensor_style(therm); | ||
55 | int core_temp; | 85 | int core_temp; |
56 | 86 | ||
57 | if (device->chipset >= 0x46) { | 87 | if (style == NEW_STYLE) { |
58 | nv_wr32(therm, 0x15b0, 0x80003fff); | 88 | nv_wr32(therm, 0x15b0, 0x80003fff); |
59 | core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; | 89 | core_temp = nv_rd32(therm, 0x15b4) & 0x3fff; |
60 | } else { | 90 | } else if (style == OLD_STYLE) { |
61 | nv_wr32(therm, 0x15b0, 0xff); | 91 | nv_wr32(therm, 0x15b0, 0xff); |
62 | core_temp = nv_rd32(therm, 0x15b4) & 0xff; | 92 | core_temp = nv_rd32(therm, 0x15b4) & 0xff; |
63 | } | 93 | } else |
64 | 94 | return -ENODEV; | |
65 | /* Setup the sensor if the temperature is 0 */ | ||
66 | if (core_temp == 0) | ||
67 | core_temp = nv40_sensor_setup(therm); | ||
68 | 95 | ||
69 | if (sensor->slope_div == 0) | 96 | /* if the slope or the offset is unset, do no use the sensor */ |
70 | sensor->slope_div = 1; | 97 | if (!sensor->slope_div || !sensor->slope_mult || |
71 | if (sensor->offset_den == 0) | 98 | !sensor->offset_num || !sensor->offset_den) |
72 | sensor->offset_den = 1; | 99 | return -ENODEV; |
73 | if (sensor->slope_mult < 1) | ||
74 | sensor->slope_mult = 1; | ||
75 | 100 | ||
76 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; | 101 | core_temp = core_temp * sensor->slope_mult / sensor->slope_div; |
77 | core_temp = core_temp + sensor->offset_num / sensor->offset_den; | 102 | core_temp = core_temp + sensor->offset_num / sensor->offset_den; |
78 | core_temp = core_temp + sensor->offset_constant - 8; | 103 | core_temp = core_temp + sensor->offset_constant - 8; |
79 | 104 | ||
105 | /* reserve negative temperatures for errors */ | ||
106 | if (core_temp < 0) | ||
107 | core_temp = 0; | ||
108 | |||
80 | return core_temp; | 109 | return core_temp; |
81 | } | 110 | } |
82 | 111 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index 06b98706b3fc..438d9824b774 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | |||
@@ -102,7 +102,7 @@ struct nouveau_therm_priv { | |||
102 | struct i2c_client *ic; | 102 | struct i2c_client *ic; |
103 | }; | 103 | }; |
104 | 104 | ||
105 | int nouveau_therm_mode(struct nouveau_therm *therm, int mode); | 105 | int nouveau_therm_fan_mode(struct nouveau_therm *therm, int mode); |
106 | int nouveau_therm_attr_get(struct nouveau_therm *therm, | 106 | int nouveau_therm_attr_get(struct nouveau_therm *therm, |
107 | enum nouveau_therm_attr_type type); | 107 | enum nouveau_therm_attr_type type); |
108 | int nouveau_therm_attr_set(struct nouveau_therm *therm, | 108 | int nouveau_therm_attr_set(struct nouveau_therm *therm, |
@@ -122,6 +122,7 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm); | |||
122 | 122 | ||
123 | int nouveau_therm_preinit(struct nouveau_therm *); | 123 | int nouveau_therm_preinit(struct nouveau_therm *); |
124 | 124 | ||
125 | void nouveau_therm_sensor_preinit(struct nouveau_therm *); | ||
125 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, | 126 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, |
126 | enum nouveau_therm_thrs thrs, | 127 | enum nouveau_therm_thrs thrs, |
127 | enum nouveau_therm_thrs_state st); | 128 | enum nouveau_therm_thrs_state st); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index b37624af8297..470f6a47b656 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | |||
@@ -34,10 +34,6 @@ nouveau_therm_temp_set_defaults(struct nouveau_therm *therm) | |||
34 | { | 34 | { |
35 | struct nouveau_therm_priv *priv = (void *)therm; | 35 | struct nouveau_therm_priv *priv = (void *)therm; |
36 | 36 | ||
37 | priv->bios_sensor.slope_mult = 1; | ||
38 | priv->bios_sensor.slope_div = 1; | ||
39 | priv->bios_sensor.offset_num = 0; | ||
40 | priv->bios_sensor.offset_den = 1; | ||
41 | priv->bios_sensor.offset_constant = 0; | 37 | priv->bios_sensor.offset_constant = 0; |
42 | 38 | ||
43 | priv->bios_sensor.thrs_fan_boost.temp = 90; | 39 | priv->bios_sensor.thrs_fan_boost.temp = 90; |
@@ -60,11 +56,6 @@ nouveau_therm_temp_safety_checks(struct nouveau_therm *therm) | |||
60 | struct nouveau_therm_priv *priv = (void *)therm; | 56 | struct nouveau_therm_priv *priv = (void *)therm; |
61 | struct nvbios_therm_sensor *s = &priv->bios_sensor; | 57 | struct nvbios_therm_sensor *s = &priv->bios_sensor; |
62 | 58 | ||
63 | if (!priv->bios_sensor.slope_div) | ||
64 | priv->bios_sensor.slope_div = 1; | ||
65 | if (!priv->bios_sensor.offset_den) | ||
66 | priv->bios_sensor.offset_den = 1; | ||
67 | |||
68 | /* enforce a minimum hysteresis on thresholds */ | 59 | /* enforce a minimum hysteresis on thresholds */ |
69 | s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); | 60 | s->thrs_fan_boost.hysteresis = max_t(u8, s->thrs_fan_boost.hysteresis, 2); |
70 | s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2); | 61 | s->thrs_down_clock.hysteresis = max_t(u8, s->thrs_down_clock.hysteresis, 2); |
@@ -106,16 +97,16 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, | |||
106 | const char *thresolds[] = { | 97 | const char *thresolds[] = { |
107 | "fanboost", "downclock", "critical", "shutdown" | 98 | "fanboost", "downclock", "critical", "shutdown" |
108 | }; | 99 | }; |
109 | uint8_t temperature = therm->temp_get(therm); | 100 | int temperature = therm->temp_get(therm); |
110 | 101 | ||
111 | if (thrs < 0 || thrs > 3) | 102 | if (thrs < 0 || thrs > 3) |
112 | return; | 103 | return; |
113 | 104 | ||
114 | if (dir == NOUVEAU_THERM_THRS_FALLING) | 105 | if (dir == NOUVEAU_THERM_THRS_FALLING) |
115 | nv_info(therm, "temperature (%u C) went below the '%s' threshold\n", | 106 | nv_info(therm, "temperature (%i C) went below the '%s' threshold\n", |
116 | temperature, thresolds[thrs]); | 107 | temperature, thresolds[thrs]); |
117 | else | 108 | else |
118 | nv_info(therm, "temperature (%u C) hit the '%s' threshold\n", | 109 | nv_info(therm, "temperature (%i C) hit the '%s' threshold\n", |
119 | temperature, thresolds[thrs]); | 110 | temperature, thresolds[thrs]); |
120 | 111 | ||
121 | active = (dir == NOUVEAU_THERM_THRS_RISING); | 112 | active = (dir == NOUVEAU_THERM_THRS_RISING); |
@@ -123,7 +114,7 @@ void nouveau_therm_sensor_event(struct nouveau_therm *therm, | |||
123 | case NOUVEAU_THERM_THRS_FANBOOST: | 114 | case NOUVEAU_THERM_THRS_FANBOOST: |
124 | if (active) { | 115 | if (active) { |
125 | nouveau_therm_fan_set(therm, true, 100); | 116 | nouveau_therm_fan_set(therm, true, 100); |
126 | nouveau_therm_mode(therm, NOUVEAU_THERM_CTRL_AUTO); | 117 | nouveau_therm_fan_mode(therm, NOUVEAU_THERM_CTRL_AUTO); |
127 | } | 118 | } |
128 | break; | 119 | break; |
129 | case NOUVEAU_THERM_THRS_DOWNCLOCK: | 120 | case NOUVEAU_THERM_THRS_DOWNCLOCK: |
@@ -202,7 +193,7 @@ alarm_timer_callback(struct nouveau_alarm *alarm) | |||
202 | NOUVEAU_THERM_THRS_SHUTDOWN); | 193 | NOUVEAU_THERM_THRS_SHUTDOWN); |
203 | 194 | ||
204 | /* schedule the next poll in one second */ | 195 | /* schedule the next poll in one second */ |
205 | if (list_empty(&alarm->head)) | 196 | if (therm->temp_get(therm) >= 0 && list_empty(&alarm->head)) |
206 | ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); | 197 | ptimer->alarm(ptimer, 1000 * 1000 * 1000, alarm); |
207 | 198 | ||
208 | spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); | 199 | spin_unlock_irqrestore(&priv->sensor.alarm_program_lock, flags); |
@@ -225,6 +216,17 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) | |||
225 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); | 216 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); |
226 | } | 217 | } |
227 | 218 | ||
219 | void | ||
220 | nouveau_therm_sensor_preinit(struct nouveau_therm *therm) | ||
221 | { | ||
222 | const char *sensor_avail = "yes"; | ||
223 | |||
224 | if (therm->temp_get(therm) < 0) | ||
225 | sensor_avail = "no"; | ||
226 | |||
227 | nv_info(therm, "internal sensor: %s\n", sensor_avail); | ||
228 | } | ||
229 | |||
228 | int | 230 | int |
229 | nouveau_therm_sensor_ctor(struct nouveau_therm *therm) | 231 | nouveau_therm_sensor_ctor(struct nouveau_therm *therm) |
230 | { | 232 | { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_abi16.c b/drivers/gpu/drm/nouveau/nouveau_abi16.c index 41241922263f..3b6dc883e150 100644 --- a/drivers/gpu/drm/nouveau/nouveau_abi16.c +++ b/drivers/gpu/drm/nouveau/nouveau_abi16.c | |||
@@ -116,6 +116,11 @@ nouveau_abi16_chan_fini(struct nouveau_abi16 *abi16, | |||
116 | { | 116 | { |
117 | struct nouveau_abi16_ntfy *ntfy, *temp; | 117 | struct nouveau_abi16_ntfy *ntfy, *temp; |
118 | 118 | ||
119 | /* wait for all activity to stop before releasing notify object, which | ||
120 | * may be still in use */ | ||
121 | if (chan->chan && chan->ntfy) | ||
122 | nouveau_channel_idle(chan->chan); | ||
123 | |||
119 | /* cleanup notifier state */ | 124 | /* cleanup notifier state */ |
120 | list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) { | 125 | list_for_each_entry_safe(ntfy, temp, &chan->notifiers, head) { |
121 | nouveau_abi16_ntfy_fini(chan, ntfy); | 126 | nouveau_abi16_ntfy_fini(chan, ntfy); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_agp.c b/drivers/gpu/drm/nouveau/nouveau_agp.c index d28430cd2ba6..6e7a55f93a85 100644 --- a/drivers/gpu/drm/nouveau/nouveau_agp.c +++ b/drivers/gpu/drm/nouveau/nouveau_agp.c | |||
@@ -47,6 +47,18 @@ nouveau_agp_enabled(struct nouveau_drm *drm) | |||
47 | if (drm->agp.stat == UNKNOWN) { | 47 | if (drm->agp.stat == UNKNOWN) { |
48 | if (!nouveau_agpmode) | 48 | if (!nouveau_agpmode) |
49 | return false; | 49 | return false; |
50 | #ifdef __powerpc__ | ||
51 | /* Disable AGP by default on all PowerPC machines for | ||
52 | * now -- At least some UniNorth-2 AGP bridges are | ||
53 | * known to be broken: DMA from the host to the card | ||
54 | * works just fine, but writeback from the card to the | ||
55 | * host goes straight to memory untranslated bypassing | ||
56 | * the GATT somehow, making them quite painful to deal | ||
57 | * with... | ||
58 | */ | ||
59 | if (nouveau_agpmode == -1) | ||
60 | return false; | ||
61 | #endif | ||
50 | return true; | 62 | return true; |
51 | } | 63 | } |
52 | 64 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 11ca82148edc..7ff10711a4d0 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -801,7 +801,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | |||
801 | stride = 16 * 4; | 801 | stride = 16 * 4; |
802 | height = amount / stride; | 802 | height = amount / stride; |
803 | 803 | ||
804 | if (new_mem->mem_type == TTM_PL_VRAM && | 804 | if (old_mem->mem_type == TTM_PL_VRAM && |
805 | nouveau_bo_tile_layout(nvbo)) { | 805 | nouveau_bo_tile_layout(nvbo)) { |
806 | ret = RING_SPACE(chan, 8); | 806 | ret = RING_SPACE(chan, 8); |
807 | if (ret) | 807 | if (ret) |
@@ -823,7 +823,7 @@ nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo, | |||
823 | BEGIN_NV04(chan, NvSubCopy, 0x0200, 1); | 823 | BEGIN_NV04(chan, NvSubCopy, 0x0200, 1); |
824 | OUT_RING (chan, 1); | 824 | OUT_RING (chan, 1); |
825 | } | 825 | } |
826 | if (old_mem->mem_type == TTM_PL_VRAM && | 826 | if (new_mem->mem_type == TTM_PL_VRAM && |
827 | nouveau_bo_tile_layout(nvbo)) { | 827 | nouveau_bo_tile_layout(nvbo)) { |
828 | ret = RING_SPACE(chan, 8); | 828 | ret = RING_SPACE(chan, 8); |
829 | if (ret) | 829 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c b/drivers/gpu/drm/nouveau/nouveau_pm.c index bb54098c6d97..936b442a6ab7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_pm.c +++ b/drivers/gpu/drm/nouveau/nouveau_pm.c | |||
@@ -402,8 +402,12 @@ nouveau_hwmon_show_temp(struct device *d, struct device_attribute *a, char *buf) | |||
402 | struct drm_device *dev = dev_get_drvdata(d); | 402 | struct drm_device *dev = dev_get_drvdata(d); |
403 | struct nouveau_drm *drm = nouveau_drm(dev); | 403 | struct nouveau_drm *drm = nouveau_drm(dev); |
404 | struct nouveau_therm *therm = nouveau_therm(drm->device); | 404 | struct nouveau_therm *therm = nouveau_therm(drm->device); |
405 | int temp = therm->temp_get(therm); | ||
405 | 406 | ||
406 | return snprintf(buf, PAGE_SIZE, "%d\n", therm->temp_get(therm) * 1000); | 407 | if (temp < 0) |
408 | return temp; | ||
409 | |||
410 | return snprintf(buf, PAGE_SIZE, "%d\n", temp * 1000); | ||
407 | } | 411 | } |
408 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, | 412 | static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, nouveau_hwmon_show_temp, |
409 | NULL, 0); | 413 | NULL, 0); |
@@ -871,7 +875,12 @@ static SENSOR_DEVICE_ATTR(pwm1_max, S_IRUGO | S_IWUSR, | |||
871 | nouveau_hwmon_get_pwm1_max, | 875 | nouveau_hwmon_get_pwm1_max, |
872 | nouveau_hwmon_set_pwm1_max, 0); | 876 | nouveau_hwmon_set_pwm1_max, 0); |
873 | 877 | ||
874 | static struct attribute *hwmon_attributes[] = { | 878 | static struct attribute *hwmon_default_attributes[] = { |
879 | &sensor_dev_attr_name.dev_attr.attr, | ||
880 | &sensor_dev_attr_update_rate.dev_attr.attr, | ||
881 | NULL | ||
882 | }; | ||
883 | static struct attribute *hwmon_temp_attributes[] = { | ||
875 | &sensor_dev_attr_temp1_input.dev_attr.attr, | 884 | &sensor_dev_attr_temp1_input.dev_attr.attr, |
876 | &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr, | 885 | &sensor_dev_attr_temp1_auto_point1_pwm.dev_attr.attr, |
877 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, | 886 | &sensor_dev_attr_temp1_auto_point1_temp.dev_attr.attr, |
@@ -882,8 +891,6 @@ static struct attribute *hwmon_attributes[] = { | |||
882 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, | 891 | &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr, |
883 | &sensor_dev_attr_temp1_emergency.dev_attr.attr, | 892 | &sensor_dev_attr_temp1_emergency.dev_attr.attr, |
884 | &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, | 893 | &sensor_dev_attr_temp1_emergency_hyst.dev_attr.attr, |
885 | &sensor_dev_attr_name.dev_attr.attr, | ||
886 | &sensor_dev_attr_update_rate.dev_attr.attr, | ||
887 | NULL | 894 | NULL |
888 | }; | 895 | }; |
889 | static struct attribute *hwmon_fan_rpm_attributes[] = { | 896 | static struct attribute *hwmon_fan_rpm_attributes[] = { |
@@ -898,8 +905,11 @@ static struct attribute *hwmon_pwm_fan_attributes[] = { | |||
898 | NULL | 905 | NULL |
899 | }; | 906 | }; |
900 | 907 | ||
901 | static const struct attribute_group hwmon_attrgroup = { | 908 | static const struct attribute_group hwmon_default_attrgroup = { |
902 | .attrs = hwmon_attributes, | 909 | .attrs = hwmon_default_attributes, |
910 | }; | ||
911 | static const struct attribute_group hwmon_temp_attrgroup = { | ||
912 | .attrs = hwmon_temp_attributes, | ||
903 | }; | 913 | }; |
904 | static const struct attribute_group hwmon_fan_rpm_attrgroup = { | 914 | static const struct attribute_group hwmon_fan_rpm_attrgroup = { |
905 | .attrs = hwmon_fan_rpm_attributes, | 915 | .attrs = hwmon_fan_rpm_attributes, |
@@ -931,13 +941,22 @@ nouveau_hwmon_init(struct drm_device *dev) | |||
931 | } | 941 | } |
932 | dev_set_drvdata(hwmon_dev, dev); | 942 | dev_set_drvdata(hwmon_dev, dev); |
933 | 943 | ||
934 | /* default sysfs entries */ | 944 | /* set the default attributes */ |
935 | ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_attrgroup); | 945 | ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_default_attrgroup); |
936 | if (ret) { | 946 | if (ret) { |
937 | if (ret) | 947 | if (ret) |
938 | goto error; | 948 | goto error; |
939 | } | 949 | } |
940 | 950 | ||
951 | /* if the card has a working thermal sensor */ | ||
952 | if (therm->temp_get(therm) >= 0) { | ||
953 | ret = sysfs_create_group(&hwmon_dev->kobj, &hwmon_temp_attrgroup); | ||
954 | if (ret) { | ||
955 | if (ret) | ||
956 | goto error; | ||
957 | } | ||
958 | } | ||
959 | |||
941 | /* if the card has a pwm fan */ | 960 | /* if the card has a pwm fan */ |
942 | /*XXX: incorrect, need better detection for this, some boards have | 961 | /*XXX: incorrect, need better detection for this, some boards have |
943 | * the gpio entries for pwm fan control even when there's no | 962 | * the gpio entries for pwm fan control even when there's no |
@@ -979,11 +998,10 @@ nouveau_hwmon_fini(struct drm_device *dev) | |||
979 | struct nouveau_pm *pm = nouveau_pm(dev); | 998 | struct nouveau_pm *pm = nouveau_pm(dev); |
980 | 999 | ||
981 | if (pm->hwmon) { | 1000 | if (pm->hwmon) { |
982 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_attrgroup); | 1001 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_default_attrgroup); |
983 | sysfs_remove_group(&pm->hwmon->kobj, | 1002 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_temp_attrgroup); |
984 | &hwmon_pwm_fan_attrgroup); | 1003 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_pwm_fan_attrgroup); |
985 | sysfs_remove_group(&pm->hwmon->kobj, | 1004 | sysfs_remove_group(&pm->hwmon->kobj, &hwmon_fan_rpm_attrgroup); |
986 | &hwmon_fan_rpm_attrgroup); | ||
987 | 1005 | ||
988 | hwmon_device_unregister(pm->hwmon); | 1006 | hwmon_device_unregister(pm->hwmon); |
989 | } | 1007 | } |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index a6237c9cbbc3..7f0e6c3f37d1 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -55,9 +55,9 @@ | |||
55 | 55 | ||
56 | /* offsets in shared sync bo of various structures */ | 56 | /* offsets in shared sync bo of various structures */ |
57 | #define EVO_SYNC(c, o) ((c) * 0x0100 + (o)) | 57 | #define EVO_SYNC(c, o) ((c) * 0x0100 + (o)) |
58 | #define EVO_MAST_NTFY EVO_SYNC( 0, 0x00) | 58 | #define EVO_MAST_NTFY EVO_SYNC( 0, 0x00) |
59 | #define EVO_FLIP_SEM0(c) EVO_SYNC((c), 0x00) | 59 | #define EVO_FLIP_SEM0(c) EVO_SYNC((c) + 1, 0x00) |
60 | #define EVO_FLIP_SEM1(c) EVO_SYNC((c), 0x10) | 60 | #define EVO_FLIP_SEM1(c) EVO_SYNC((c) + 1, 0x10) |
61 | 61 | ||
62 | #define EVO_CORE_HANDLE (0xd1500000) | 62 | #define EVO_CORE_HANDLE (0xd1500000) |
63 | #define EVO_CHAN_HANDLE(t,i) (0xd15c0000 | (((t) & 0x00ff) << 8) | (i)) | 63 | #define EVO_CHAN_HANDLE(t,i) (0xd15c0000 | (((t) & 0x00ff) << 8) | (i)) |
@@ -341,10 +341,8 @@ struct nv50_curs { | |||
341 | 341 | ||
342 | struct nv50_sync { | 342 | struct nv50_sync { |
343 | struct nv50_dmac base; | 343 | struct nv50_dmac base; |
344 | struct { | 344 | u32 addr; |
345 | u32 offset; | 345 | u32 data; |
346 | u16 value; | ||
347 | } sem; | ||
348 | }; | 346 | }; |
349 | 347 | ||
350 | struct nv50_ovly { | 348 | struct nv50_ovly { |
@@ -471,13 +469,33 @@ nv50_display_crtc_sema(struct drm_device *dev, int crtc) | |||
471 | return nv50_disp(dev)->sync; | 469 | return nv50_disp(dev)->sync; |
472 | } | 470 | } |
473 | 471 | ||
472 | struct nv50_display_flip { | ||
473 | struct nv50_disp *disp; | ||
474 | struct nv50_sync *chan; | ||
475 | }; | ||
476 | |||
477 | static bool | ||
478 | nv50_display_flip_wait(void *data) | ||
479 | { | ||
480 | struct nv50_display_flip *flip = data; | ||
481 | if (nouveau_bo_rd32(flip->disp->sync, flip->chan->addr / 4) == | ||
482 | flip->chan->data); | ||
483 | return true; | ||
484 | usleep_range(1, 2); | ||
485 | return false; | ||
486 | } | ||
487 | |||
474 | void | 488 | void |
475 | nv50_display_flip_stop(struct drm_crtc *crtc) | 489 | nv50_display_flip_stop(struct drm_crtc *crtc) |
476 | { | 490 | { |
477 | struct nv50_sync *sync = nv50_sync(crtc); | 491 | struct nouveau_device *device = nouveau_dev(crtc->dev); |
492 | struct nv50_display_flip flip = { | ||
493 | .disp = nv50_disp(crtc->dev), | ||
494 | .chan = nv50_sync(crtc), | ||
495 | }; | ||
478 | u32 *push; | 496 | u32 *push; |
479 | 497 | ||
480 | push = evo_wait(sync, 8); | 498 | push = evo_wait(flip.chan, 8); |
481 | if (push) { | 499 | if (push) { |
482 | evo_mthd(push, 0x0084, 1); | 500 | evo_mthd(push, 0x0084, 1); |
483 | evo_data(push, 0x00000000); | 501 | evo_data(push, 0x00000000); |
@@ -487,8 +505,10 @@ nv50_display_flip_stop(struct drm_crtc *crtc) | |||
487 | evo_data(push, 0x00000000); | 505 | evo_data(push, 0x00000000); |
488 | evo_mthd(push, 0x0080, 1); | 506 | evo_mthd(push, 0x0080, 1); |
489 | evo_data(push, 0x00000000); | 507 | evo_data(push, 0x00000000); |
490 | evo_kick(push, sync); | 508 | evo_kick(push, flip.chan); |
491 | } | 509 | } |
510 | |||
511 | nv_wait_cb(device, nv50_display_flip_wait, &flip); | ||
492 | } | 512 | } |
493 | 513 | ||
494 | int | 514 | int |
@@ -496,73 +516,78 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
496 | struct nouveau_channel *chan, u32 swap_interval) | 516 | struct nouveau_channel *chan, u32 swap_interval) |
497 | { | 517 | { |
498 | struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); | 518 | struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb); |
499 | struct nv50_disp *disp = nv50_disp(crtc->dev); | ||
500 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 519 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
501 | struct nv50_sync *sync = nv50_sync(crtc); | 520 | struct nv50_sync *sync = nv50_sync(crtc); |
521 | int head = nv_crtc->index, ret; | ||
502 | u32 *push; | 522 | u32 *push; |
503 | int ret; | ||
504 | 523 | ||
505 | swap_interval <<= 4; | 524 | swap_interval <<= 4; |
506 | if (swap_interval == 0) | 525 | if (swap_interval == 0) |
507 | swap_interval |= 0x100; | 526 | swap_interval |= 0x100; |
527 | if (chan == NULL) | ||
528 | evo_sync(crtc->dev); | ||
508 | 529 | ||
509 | push = evo_wait(sync, 128); | 530 | push = evo_wait(sync, 128); |
510 | if (unlikely(push == NULL)) | 531 | if (unlikely(push == NULL)) |
511 | return -EBUSY; | 532 | return -EBUSY; |
512 | 533 | ||
513 | /* synchronise with the rendering channel, if necessary */ | 534 | if (chan && nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) { |
514 | if (likely(chan)) { | 535 | ret = RING_SPACE(chan, 8); |
536 | if (ret) | ||
537 | return ret; | ||
538 | |||
539 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2); | ||
540 | OUT_RING (chan, NvEvoSema0 + head); | ||
541 | OUT_RING (chan, sync->addr ^ 0x10); | ||
542 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1); | ||
543 | OUT_RING (chan, sync->data + 1); | ||
544 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_OFFSET, 2); | ||
545 | OUT_RING (chan, sync->addr); | ||
546 | OUT_RING (chan, sync->data); | ||
547 | } else | ||
548 | if (chan && nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) { | ||
549 | u64 addr = nv84_fence_crtc(chan, head) + sync->addr; | ||
550 | ret = RING_SPACE(chan, 12); | ||
551 | if (ret) | ||
552 | return ret; | ||
553 | |||
554 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); | ||
555 | OUT_RING (chan, chan->vram); | ||
556 | BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); | ||
557 | OUT_RING (chan, upper_32_bits(addr ^ 0x10)); | ||
558 | OUT_RING (chan, lower_32_bits(addr ^ 0x10)); | ||
559 | OUT_RING (chan, sync->data + 1); | ||
560 | OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG); | ||
561 | BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); | ||
562 | OUT_RING (chan, upper_32_bits(addr)); | ||
563 | OUT_RING (chan, lower_32_bits(addr)); | ||
564 | OUT_RING (chan, sync->data); | ||
565 | OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL); | ||
566 | } else | ||
567 | if (chan) { | ||
568 | u64 addr = nv84_fence_crtc(chan, head) + sync->addr; | ||
515 | ret = RING_SPACE(chan, 10); | 569 | ret = RING_SPACE(chan, 10); |
516 | if (ret) | 570 | if (ret) |
517 | return ret; | 571 | return ret; |
518 | 572 | ||
519 | if (nv_mclass(chan->object) < NV84_CHANNEL_IND_CLASS) { | 573 | BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); |
520 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 2); | 574 | OUT_RING (chan, upper_32_bits(addr ^ 0x10)); |
521 | OUT_RING (chan, NvEvoSema0 + nv_crtc->index); | 575 | OUT_RING (chan, lower_32_bits(addr ^ 0x10)); |
522 | OUT_RING (chan, sync->sem.offset); | 576 | OUT_RING (chan, sync->data + 1); |
523 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_RELEASE, 1); | 577 | OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_WRITE_LONG | |
524 | OUT_RING (chan, 0xf00d0000 | sync->sem.value); | 578 | NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD); |
525 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_SEMAPHORE_OFFSET, 2); | 579 | BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); |
526 | OUT_RING (chan, sync->sem.offset ^ 0x10); | 580 | OUT_RING (chan, upper_32_bits(addr)); |
527 | OUT_RING (chan, 0x74b1e000); | 581 | OUT_RING (chan, lower_32_bits(addr)); |
528 | BEGIN_NV04(chan, 0, NV11_SUBCHAN_DMA_SEMAPHORE, 1); | 582 | OUT_RING (chan, sync->data); |
529 | OUT_RING (chan, NvSema); | 583 | OUT_RING (chan, NV84_SUBCHAN_SEMAPHORE_TRIGGER_ACQUIRE_EQUAL | |
530 | } else | 584 | NVC0_SUBCHAN_SEMAPHORE_TRIGGER_YIELD); |
531 | if (nv_mclass(chan->object) < NVC0_CHANNEL_IND_CLASS) { | 585 | } |
532 | u64 offset = nv84_fence_crtc(chan, nv_crtc->index); | ||
533 | offset += sync->sem.offset; | ||
534 | |||
535 | BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); | ||
536 | OUT_RING (chan, upper_32_bits(offset)); | ||
537 | OUT_RING (chan, lower_32_bits(offset)); | ||
538 | OUT_RING (chan, 0xf00d0000 | sync->sem.value); | ||
539 | OUT_RING (chan, 0x00000002); | ||
540 | BEGIN_NV04(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); | ||
541 | OUT_RING (chan, upper_32_bits(offset)); | ||
542 | OUT_RING (chan, lower_32_bits(offset ^ 0x10)); | ||
543 | OUT_RING (chan, 0x74b1e000); | ||
544 | OUT_RING (chan, 0x00000001); | ||
545 | } else { | ||
546 | u64 offset = nv84_fence_crtc(chan, nv_crtc->index); | ||
547 | offset += sync->sem.offset; | ||
548 | |||
549 | BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); | ||
550 | OUT_RING (chan, upper_32_bits(offset)); | ||
551 | OUT_RING (chan, lower_32_bits(offset)); | ||
552 | OUT_RING (chan, 0xf00d0000 | sync->sem.value); | ||
553 | OUT_RING (chan, 0x00001002); | ||
554 | BEGIN_NVC0(chan, 0, NV84_SUBCHAN_SEMAPHORE_ADDRESS_HIGH, 4); | ||
555 | OUT_RING (chan, upper_32_bits(offset)); | ||
556 | OUT_RING (chan, lower_32_bits(offset ^ 0x10)); | ||
557 | OUT_RING (chan, 0x74b1e000); | ||
558 | OUT_RING (chan, 0x00001001); | ||
559 | } | ||
560 | 586 | ||
587 | if (chan) { | ||
588 | sync->addr ^= 0x10; | ||
589 | sync->data++; | ||
561 | FIRE_RING (chan); | 590 | FIRE_RING (chan); |
562 | } else { | ||
563 | nouveau_bo_wr32(disp->sync, sync->sem.offset / 4, | ||
564 | 0xf00d0000 | sync->sem.value); | ||
565 | evo_sync(crtc->dev); | ||
566 | } | 591 | } |
567 | 592 | ||
568 | /* queue the flip */ | 593 | /* queue the flip */ |
@@ -575,9 +600,9 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
575 | evo_data(push, 0x40000000); | 600 | evo_data(push, 0x40000000); |
576 | } | 601 | } |
577 | evo_mthd(push, 0x0088, 4); | 602 | evo_mthd(push, 0x0088, 4); |
578 | evo_data(push, sync->sem.offset); | 603 | evo_data(push, sync->addr); |
579 | evo_data(push, 0xf00d0000 | sync->sem.value); | 604 | evo_data(push, sync->data++); |
580 | evo_data(push, 0x74b1e000); | 605 | evo_data(push, sync->data); |
581 | evo_data(push, NvEvoSync); | 606 | evo_data(push, NvEvoSync); |
582 | evo_mthd(push, 0x00a0, 2); | 607 | evo_mthd(push, 0x00a0, 2); |
583 | evo_data(push, 0x00000000); | 608 | evo_data(push, 0x00000000); |
@@ -605,9 +630,6 @@ nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb, | |||
605 | evo_mthd(push, 0x0080, 1); | 630 | evo_mthd(push, 0x0080, 1); |
606 | evo_data(push, 0x00000000); | 631 | evo_data(push, 0x00000000); |
607 | evo_kick(push, sync); | 632 | evo_kick(push, sync); |
608 | |||
609 | sync->sem.offset ^= 0x10; | ||
610 | sync->sem.value++; | ||
611 | return 0; | 633 | return 0; |
612 | } | 634 | } |
613 | 635 | ||
@@ -1379,7 +1401,8 @@ nv50_crtc_create(struct drm_device *dev, struct nouveau_object *core, int index) | |||
1379 | if (ret) | 1401 | if (ret) |
1380 | goto out; | 1402 | goto out; |
1381 | 1403 | ||
1382 | head->sync.sem.offset = EVO_SYNC(1 + index, 0x00); | 1404 | head->sync.addr = EVO_FLIP_SEM0(index); |
1405 | head->sync.data = 0x00000000; | ||
1383 | 1406 | ||
1384 | /* allocate overlay resources */ | 1407 | /* allocate overlay resources */ |
1385 | ret = nv50_pioc_create(disp->core, NV50_DISP_OIMM_CLASS, index, | 1408 | ret = nv50_pioc_create(disp->core, NV50_DISP_OIMM_CLASS, index, |
@@ -2112,15 +2135,23 @@ nv50_display_fini(struct drm_device *dev) | |||
2112 | int | 2135 | int |
2113 | nv50_display_init(struct drm_device *dev) | 2136 | nv50_display_init(struct drm_device *dev) |
2114 | { | 2137 | { |
2115 | u32 *push = evo_wait(nv50_mast(dev), 32); | 2138 | struct nv50_disp *disp = nv50_disp(dev); |
2116 | if (push) { | 2139 | struct drm_crtc *crtc; |
2117 | evo_mthd(push, 0x0088, 1); | 2140 | u32 *push; |
2118 | evo_data(push, NvEvoSync); | 2141 | |
2119 | evo_kick(push, nv50_mast(dev)); | 2142 | push = evo_wait(nv50_mast(dev), 32); |
2120 | return 0; | 2143 | if (!push) |
2144 | return -EBUSY; | ||
2145 | |||
2146 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
2147 | struct nv50_sync *sync = nv50_sync(crtc); | ||
2148 | nouveau_bo_wr32(disp->sync, sync->addr / 4, sync->data); | ||
2121 | } | 2149 | } |
2122 | 2150 | ||
2123 | return -EBUSY; | 2151 | evo_mthd(push, 0x0088, 1); |
2152 | evo_data(push, NvEvoSync); | ||
2153 | evo_kick(push, nv50_mast(dev)); | ||
2154 | return 0; | ||
2124 | } | 2155 | } |
2125 | 2156 | ||
2126 | void | 2157 | void |
@@ -2245,6 +2276,7 @@ nv50_display_create(struct drm_device *dev) | |||
2245 | NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n", | 2276 | NV_WARN(drm, "failed to create encoder %d/%d/%d: %d\n", |
2246 | dcbe->location, dcbe->type, | 2277 | dcbe->location, dcbe->type, |
2247 | ffs(dcbe->or) - 1, ret); | 2278 | ffs(dcbe->or) - 1, ret); |
2279 | ret = 0; | ||
2248 | } | 2280 | } |
2249 | } | 2281 | } |
2250 | 2282 | ||
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 3c38ea46531c..305a657bf215 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -2438,6 +2438,12 @@ static u32 evergreen_gpu_check_soft_reset(struct radeon_device *rdev) | |||
2438 | if (tmp & L2_BUSY) | 2438 | if (tmp & L2_BUSY) |
2439 | reset_mask |= RADEON_RESET_VMC; | 2439 | reset_mask |= RADEON_RESET_VMC; |
2440 | 2440 | ||
2441 | /* Skip MC reset as it's mostly likely not hung, just busy */ | ||
2442 | if (reset_mask & RADEON_RESET_MC) { | ||
2443 | DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask); | ||
2444 | reset_mask &= ~RADEON_RESET_MC; | ||
2445 | } | ||
2446 | |||
2441 | return reset_mask; | 2447 | return reset_mask; |
2442 | } | 2448 | } |
2443 | 2449 | ||
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 99fb13286fd0..eb8ac315f92f 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
@@ -834,7 +834,7 @@ static int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, | |||
834 | __func__, __LINE__, toffset, surf.base_align); | 834 | __func__, __LINE__, toffset, surf.base_align); |
835 | return -EINVAL; | 835 | return -EINVAL; |
836 | } | 836 | } |
837 | if (moffset & (surf.base_align - 1)) { | 837 | if (surf.nsamples <= 1 && moffset & (surf.base_align - 1)) { |
838 | dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n", | 838 | dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n", |
839 | __func__, __LINE__, moffset, surf.base_align); | 839 | __func__, __LINE__, moffset, surf.base_align); |
840 | return -EINVAL; | 840 | return -EINVAL; |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 7cead763be9e..27769e724b6d 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -468,13 +468,19 @@ static void cayman_gpu_init(struct radeon_device *rdev) | |||
468 | (rdev->pdev->device == 0x9907) || | 468 | (rdev->pdev->device == 0x9907) || |
469 | (rdev->pdev->device == 0x9908) || | 469 | (rdev->pdev->device == 0x9908) || |
470 | (rdev->pdev->device == 0x9909) || | 470 | (rdev->pdev->device == 0x9909) || |
471 | (rdev->pdev->device == 0x990B) || | ||
472 | (rdev->pdev->device == 0x990C) || | ||
473 | (rdev->pdev->device == 0x990F) || | ||
471 | (rdev->pdev->device == 0x9910) || | 474 | (rdev->pdev->device == 0x9910) || |
472 | (rdev->pdev->device == 0x9917)) { | 475 | (rdev->pdev->device == 0x9917) || |
476 | (rdev->pdev->device == 0x9999)) { | ||
473 | rdev->config.cayman.max_simds_per_se = 6; | 477 | rdev->config.cayman.max_simds_per_se = 6; |
474 | rdev->config.cayman.max_backends_per_se = 2; | 478 | rdev->config.cayman.max_backends_per_se = 2; |
475 | } else if ((rdev->pdev->device == 0x9903) || | 479 | } else if ((rdev->pdev->device == 0x9903) || |
476 | (rdev->pdev->device == 0x9904) || | 480 | (rdev->pdev->device == 0x9904) || |
477 | (rdev->pdev->device == 0x990A) || | 481 | (rdev->pdev->device == 0x990A) || |
482 | (rdev->pdev->device == 0x990D) || | ||
483 | (rdev->pdev->device == 0x990E) || | ||
478 | (rdev->pdev->device == 0x9913) || | 484 | (rdev->pdev->device == 0x9913) || |
479 | (rdev->pdev->device == 0x9918)) { | 485 | (rdev->pdev->device == 0x9918)) { |
480 | rdev->config.cayman.max_simds_per_se = 4; | 486 | rdev->config.cayman.max_simds_per_se = 4; |
@@ -483,6 +489,9 @@ static void cayman_gpu_init(struct radeon_device *rdev) | |||
483 | (rdev->pdev->device == 0x9990) || | 489 | (rdev->pdev->device == 0x9990) || |
484 | (rdev->pdev->device == 0x9991) || | 490 | (rdev->pdev->device == 0x9991) || |
485 | (rdev->pdev->device == 0x9994) || | 491 | (rdev->pdev->device == 0x9994) || |
492 | (rdev->pdev->device == 0x9995) || | ||
493 | (rdev->pdev->device == 0x9996) || | ||
494 | (rdev->pdev->device == 0x999A) || | ||
486 | (rdev->pdev->device == 0x99A0)) { | 495 | (rdev->pdev->device == 0x99A0)) { |
487 | rdev->config.cayman.max_simds_per_se = 3; | 496 | rdev->config.cayman.max_simds_per_se = 3; |
488 | rdev->config.cayman.max_backends_per_se = 1; | 497 | rdev->config.cayman.max_backends_per_se = 1; |
@@ -616,11 +625,22 @@ static void cayman_gpu_init(struct radeon_device *rdev) | |||
616 | WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config); | 625 | WREG32(DMA_TILING_CONFIG + DMA0_REGISTER_OFFSET, gb_addr_config); |
617 | WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config); | 626 | WREG32(DMA_TILING_CONFIG + DMA1_REGISTER_OFFSET, gb_addr_config); |
618 | 627 | ||
619 | tmp = gb_addr_config & NUM_PIPES_MASK; | 628 | if ((rdev->config.cayman.max_backends_per_se == 1) && |
620 | tmp = r6xx_remap_render_backend(rdev, tmp, | 629 | (rdev->flags & RADEON_IS_IGP)) { |
621 | rdev->config.cayman.max_backends_per_se * | 630 | if ((disabled_rb_mask & 3) == 1) { |
622 | rdev->config.cayman.max_shader_engines, | 631 | /* RB0 disabled, RB1 enabled */ |
623 | CAYMAN_MAX_BACKENDS, disabled_rb_mask); | 632 | tmp = 0x11111111; |
633 | } else { | ||
634 | /* RB1 disabled, RB0 enabled */ | ||
635 | tmp = 0x00000000; | ||
636 | } | ||
637 | } else { | ||
638 | tmp = gb_addr_config & NUM_PIPES_MASK; | ||
639 | tmp = r6xx_remap_render_backend(rdev, tmp, | ||
640 | rdev->config.cayman.max_backends_per_se * | ||
641 | rdev->config.cayman.max_shader_engines, | ||
642 | CAYMAN_MAX_BACKENDS, disabled_rb_mask); | ||
643 | } | ||
624 | WREG32(GB_BACKEND_MAP, tmp); | 644 | WREG32(GB_BACKEND_MAP, tmp); |
625 | 645 | ||
626 | cgts_tcc_disable = 0xffff0000; | 646 | cgts_tcc_disable = 0xffff0000; |
@@ -1381,6 +1401,12 @@ static u32 cayman_gpu_check_soft_reset(struct radeon_device *rdev) | |||
1381 | if (tmp & L2_BUSY) | 1401 | if (tmp & L2_BUSY) |
1382 | reset_mask |= RADEON_RESET_VMC; | 1402 | reset_mask |= RADEON_RESET_VMC; |
1383 | 1403 | ||
1404 | /* Skip MC reset as it's mostly likely not hung, just busy */ | ||
1405 | if (reset_mask & RADEON_RESET_MC) { | ||
1406 | DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask); | ||
1407 | reset_mask &= ~RADEON_RESET_MC; | ||
1408 | } | ||
1409 | |||
1384 | return reset_mask; | 1410 | return reset_mask; |
1385 | } | 1411 | } |
1386 | 1412 | ||
@@ -1765,6 +1791,7 @@ int cayman_resume(struct radeon_device *rdev) | |||
1765 | int cayman_suspend(struct radeon_device *rdev) | 1791 | int cayman_suspend(struct radeon_device *rdev) |
1766 | { | 1792 | { |
1767 | r600_audio_fini(rdev); | 1793 | r600_audio_fini(rdev); |
1794 | radeon_vm_manager_fini(rdev); | ||
1768 | cayman_cp_enable(rdev, false); | 1795 | cayman_cp_enable(rdev, false); |
1769 | cayman_dma_stop(rdev); | 1796 | cayman_dma_stop(rdev); |
1770 | evergreen_irq_suspend(rdev); | 1797 | evergreen_irq_suspend(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 6d4b5611daf4..0740db3fcd22 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1394,6 +1394,12 @@ static u32 r600_gpu_check_soft_reset(struct radeon_device *rdev) | |||
1394 | if (r600_is_display_hung(rdev)) | 1394 | if (r600_is_display_hung(rdev)) |
1395 | reset_mask |= RADEON_RESET_DISPLAY; | 1395 | reset_mask |= RADEON_RESET_DISPLAY; |
1396 | 1396 | ||
1397 | /* Skip MC reset as it's mostly likely not hung, just busy */ | ||
1398 | if (reset_mask & RADEON_RESET_MC) { | ||
1399 | DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask); | ||
1400 | reset_mask &= ~RADEON_RESET_MC; | ||
1401 | } | ||
1402 | |||
1397 | return reset_mask; | 1403 | return reset_mask; |
1398 | } | 1404 | } |
1399 | 1405 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_benchmark.c b/drivers/gpu/drm/radeon/radeon_benchmark.c index bedda9caadd9..6e05a2e75a46 100644 --- a/drivers/gpu/drm/radeon/radeon_benchmark.c +++ b/drivers/gpu/drm/radeon/radeon_benchmark.c | |||
@@ -122,10 +122,7 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, | |||
122 | goto out_cleanup; | 122 | goto out_cleanup; |
123 | } | 123 | } |
124 | 124 | ||
125 | /* r100 doesn't have dma engine so skip the test */ | 125 | if (rdev->asic->copy.dma) { |
126 | /* also, VRAM-to-VRAM test doesn't make much sense for DMA */ | ||
127 | /* skip it as well if domains are the same */ | ||
128 | if ((rdev->asic->copy.dma) && (sdomain != ddomain)) { | ||
129 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, | 126 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, |
130 | RADEON_BENCHMARK_COPY_DMA, n); | 127 | RADEON_BENCHMARK_COPY_DMA, n); |
131 | if (time < 0) | 128 | if (time < 0) |
@@ -135,13 +132,15 @@ static void radeon_benchmark_move(struct radeon_device *rdev, unsigned size, | |||
135 | sdomain, ddomain, "dma"); | 132 | sdomain, ddomain, "dma"); |
136 | } | 133 | } |
137 | 134 | ||
138 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, | 135 | if (rdev->asic->copy.blit) { |
139 | RADEON_BENCHMARK_COPY_BLIT, n); | 136 | time = radeon_benchmark_do_move(rdev, size, saddr, daddr, |
140 | if (time < 0) | 137 | RADEON_BENCHMARK_COPY_BLIT, n); |
141 | goto out_cleanup; | 138 | if (time < 0) |
142 | if (time > 0) | 139 | goto out_cleanup; |
143 | radeon_benchmark_log_results(n, size, time, | 140 | if (time > 0) |
144 | sdomain, ddomain, "blit"); | 141 | radeon_benchmark_log_results(n, size, time, |
142 | sdomain, ddomain, "blit"); | ||
143 | } | ||
145 | 144 | ||
146 | out_cleanup: | 145 | out_cleanup: |
147 | if (sobj) { | 146 | if (sobj) { |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 3e403bdda58f..78edadc9e86b 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -970,6 +970,15 @@ struct radeon_encoder_primary_dac *radeon_combios_get_primary_dac_info(struct | |||
970 | found = 1; | 970 | found = 1; |
971 | } | 971 | } |
972 | 972 | ||
973 | /* quirks */ | ||
974 | /* Radeon 9100 (R200) */ | ||
975 | if ((dev->pdev->device == 0x514D) && | ||
976 | (dev->pdev->subsystem_vendor == 0x174B) && | ||
977 | (dev->pdev->subsystem_device == 0x7149)) { | ||
978 | /* vbios value is bad, use the default */ | ||
979 | found = 0; | ||
980 | } | ||
981 | |||
973 | if (!found) /* fallback to defaults */ | 982 | if (!found) /* fallback to defaults */ |
974 | radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac); | 983 | radeon_legacy_get_primary_dac_info_from_table(rdev, p_dac); |
975 | 984 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 167758488ed6..66a7f0fd9620 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -70,9 +70,10 @@ | |||
70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA | 70 | * 2.27.0 - r600-SI: Add CS ioctl support for async DMA |
71 | * 2.28.0 - r600-eg: Add MEM_WRITE packet support | 71 | * 2.28.0 - r600-eg: Add MEM_WRITE packet support |
72 | * 2.29.0 - R500 FP16 color clear registers | 72 | * 2.29.0 - R500 FP16 color clear registers |
73 | * 2.30.0 - fix for FMASK texturing | ||
73 | */ | 74 | */ |
74 | #define KMS_DRIVER_MAJOR 2 | 75 | #define KMS_DRIVER_MAJOR 2 |
75 | #define KMS_DRIVER_MINOR 29 | 76 | #define KMS_DRIVER_MINOR 30 |
76 | #define KMS_DRIVER_PATCHLEVEL 0 | 77 | #define KMS_DRIVER_PATCHLEVEL 0 |
77 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 78 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
78 | int radeon_driver_unload_kms(struct drm_device *dev); | 79 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_irq_kms.c b/drivers/gpu/drm/radeon/radeon_irq_kms.c index 90374dd77960..48f80cd42d8f 100644 --- a/drivers/gpu/drm/radeon/radeon_irq_kms.c +++ b/drivers/gpu/drm/radeon/radeon_irq_kms.c | |||
@@ -400,6 +400,9 @@ void radeon_irq_kms_enable_afmt(struct radeon_device *rdev, int block) | |||
400 | { | 400 | { |
401 | unsigned long irqflags; | 401 | unsigned long irqflags; |
402 | 402 | ||
403 | if (!rdev->ddev->irq_enabled) | ||
404 | return; | ||
405 | |||
403 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | 406 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
404 | rdev->irq.afmt[block] = true; | 407 | rdev->irq.afmt[block] = true; |
405 | radeon_irq_set(rdev); | 408 | radeon_irq_set(rdev); |
@@ -419,6 +422,9 @@ void radeon_irq_kms_disable_afmt(struct radeon_device *rdev, int block) | |||
419 | { | 422 | { |
420 | unsigned long irqflags; | 423 | unsigned long irqflags; |
421 | 424 | ||
425 | if (!rdev->ddev->irq_enabled) | ||
426 | return; | ||
427 | |||
422 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | 428 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
423 | rdev->irq.afmt[block] = false; | 429 | rdev->irq.afmt[block] = false; |
424 | radeon_irq_set(rdev); | 430 | radeon_irq_set(rdev); |
@@ -438,6 +444,9 @@ void radeon_irq_kms_enable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | |||
438 | unsigned long irqflags; | 444 | unsigned long irqflags; |
439 | int i; | 445 | int i; |
440 | 446 | ||
447 | if (!rdev->ddev->irq_enabled) | ||
448 | return; | ||
449 | |||
441 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | 450 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
442 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | 451 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) |
443 | rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); | 452 | rdev->irq.hpd[i] |= !!(hpd_mask & (1 << i)); |
@@ -458,6 +467,9 @@ void radeon_irq_kms_disable_hpd(struct radeon_device *rdev, unsigned hpd_mask) | |||
458 | unsigned long irqflags; | 467 | unsigned long irqflags; |
459 | int i; | 468 | int i; |
460 | 469 | ||
470 | if (!rdev->ddev->irq_enabled) | ||
471 | return; | ||
472 | |||
461 | spin_lock_irqsave(&rdev->irq.lock, irqflags); | 473 | spin_lock_irqsave(&rdev->irq.lock, irqflags); |
462 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) | 474 | for (i = 0; i < RADEON_MAX_HPD_PINS; ++i) |
463 | rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); | 475 | rdev->irq.hpd[i] &= !(hpd_mask & (1 << i)); |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 80979ed951eb..bafbe3216952 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -2284,6 +2284,12 @@ static u32 si_gpu_check_soft_reset(struct radeon_device *rdev) | |||
2284 | if (tmp & L2_BUSY) | 2284 | if (tmp & L2_BUSY) |
2285 | reset_mask |= RADEON_RESET_VMC; | 2285 | reset_mask |= RADEON_RESET_VMC; |
2286 | 2286 | ||
2287 | /* Skip MC reset as it's mostly likely not hung, just busy */ | ||
2288 | if (reset_mask & RADEON_RESET_MC) { | ||
2289 | DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask); | ||
2290 | reset_mask &= ~RADEON_RESET_MC; | ||
2291 | } | ||
2292 | |||
2287 | return reset_mask; | 2293 | return reset_mask; |
2288 | } | 2294 | } |
2289 | 2295 | ||
@@ -4463,6 +4469,7 @@ int si_resume(struct radeon_device *rdev) | |||
4463 | 4469 | ||
4464 | int si_suspend(struct radeon_device *rdev) | 4470 | int si_suspend(struct radeon_device *rdev) |
4465 | { | 4471 | { |
4472 | radeon_vm_manager_fini(rdev); | ||
4466 | si_cp_enable(rdev, false); | 4473 | si_cp_enable(rdev, false); |
4467 | cayman_dma_stop(rdev); | 4474 | cayman_dma_stop(rdev); |
4468 | si_irq_suspend(rdev); | 4475 | si_irq_suspend(rdev); |
diff --git a/drivers/gpu/drm/tegra/Kconfig b/drivers/gpu/drm/tegra/Kconfig index c92955df0658..be1daf7344d3 100644 --- a/drivers/gpu/drm/tegra/Kconfig +++ b/drivers/gpu/drm/tegra/Kconfig | |||
@@ -4,7 +4,6 @@ config DRM_TEGRA | |||
4 | select DRM_KMS_HELPER | 4 | select DRM_KMS_HELPER |
5 | select DRM_GEM_CMA_HELPER | 5 | select DRM_GEM_CMA_HELPER |
6 | select DRM_KMS_CMA_HELPER | 6 | select DRM_KMS_CMA_HELPER |
7 | select DRM_HDMI | ||
8 | select FB_CFB_FILLRECT | 7 | select FB_CFB_FILLRECT |
9 | select FB_CFB_COPYAREA | 8 | select FB_CFB_COPYAREA |
10 | select FB_CFB_IMAGEBLIT | 9 | select FB_CFB_IMAGEBLIT |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 92e47e5c9564..c4388776f4e4 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -590,6 +590,9 @@ | |||
590 | #define USB_VENDOR_ID_MONTEREY 0x0566 | 590 | #define USB_VENDOR_ID_MONTEREY 0x0566 |
591 | #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 | 591 | #define USB_DEVICE_ID_GENIUS_KB29E 0x3004 |
592 | 592 | ||
593 | #define USB_VENDOR_ID_MSI 0x1770 | ||
594 | #define USB_DEVICE_ID_MSI_GX680R_LED_PANEL 0xff00 | ||
595 | |||
593 | #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 | 596 | #define USB_VENDOR_ID_NATIONAL_SEMICONDUCTOR 0x0400 |
594 | #define USB_DEVICE_ID_N_S_HARMONY 0xc359 | 597 | #define USB_DEVICE_ID_N_S_HARMONY 0xc359 |
595 | 598 | ||
@@ -684,6 +687,9 @@ | |||
684 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 | 687 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001 0x3001 |
685 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 | 688 | #define USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008 0x3008 |
686 | 689 | ||
690 | #define USB_VENDOR_ID_REALTEK 0x0bda | ||
691 | #define USB_DEVICE_ID_REALTEK_READER 0x0152 | ||
692 | |||
687 | #define USB_VENDOR_ID_ROCCAT 0x1e7d | 693 | #define USB_VENDOR_ID_ROCCAT 0x1e7d |
688 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 | 694 | #define USB_DEVICE_ID_ROCCAT_ARVO 0x30d4 |
689 | #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c | 695 | #define USB_DEVICE_ID_ROCCAT_ISKU 0x319c |
diff --git a/drivers/hid/hid-logitech-dj.c b/drivers/hid/hid-logitech-dj.c index 9500f2f3f8fe..8758f38c948c 100644 --- a/drivers/hid/hid-logitech-dj.c +++ b/drivers/hid/hid-logitech-dj.c | |||
@@ -459,19 +459,25 @@ static int logi_dj_recv_send_report(struct dj_receiver_dev *djrcv_dev, | |||
459 | struct dj_report *dj_report) | 459 | struct dj_report *dj_report) |
460 | { | 460 | { |
461 | struct hid_device *hdev = djrcv_dev->hdev; | 461 | struct hid_device *hdev = djrcv_dev->hdev; |
462 | int sent_bytes; | 462 | struct hid_report *report; |
463 | struct hid_report_enum *output_report_enum; | ||
464 | u8 *data = (u8 *)(&dj_report->device_index); | ||
465 | int i; | ||
463 | 466 | ||
464 | if (!hdev->hid_output_raw_report) { | 467 | output_report_enum = &hdev->report_enum[HID_OUTPUT_REPORT]; |
465 | dev_err(&hdev->dev, "%s:" | 468 | report = output_report_enum->report_id_hash[REPORT_ID_DJ_SHORT]; |
466 | "hid_output_raw_report is null\n", __func__); | 469 | |
470 | if (!report) { | ||
471 | dev_err(&hdev->dev, "%s: unable to find dj report\n", __func__); | ||
467 | return -ENODEV; | 472 | return -ENODEV; |
468 | } | 473 | } |
469 | 474 | ||
470 | sent_bytes = hdev->hid_output_raw_report(hdev, (u8 *) dj_report, | 475 | for (i = 0; i < report->field[0]->report_count; i++) |
471 | sizeof(struct dj_report), | 476 | report->field[0]->value[i] = data[i]; |
472 | HID_OUTPUT_REPORT); | 477 | |
478 | usbhid_submit_report(hdev, report, USB_DIR_OUT); | ||
473 | 479 | ||
474 | return (sent_bytes < 0) ? sent_bytes : 0; | 480 | return 0; |
475 | } | 481 | } |
476 | 482 | ||
477 | static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) | 483 | static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev) |
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c index 7a1ebb867cf4..82e9211b3ca9 100644 --- a/drivers/hid/hid-multitouch.c +++ b/drivers/hid/hid-multitouch.c | |||
@@ -621,6 +621,7 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, | |||
621 | { | 621 | { |
622 | struct mt_device *td = hid_get_drvdata(hid); | 622 | struct mt_device *td = hid_get_drvdata(hid); |
623 | __s32 quirks = td->mtclass.quirks; | 623 | __s32 quirks = td->mtclass.quirks; |
624 | struct input_dev *input = field->hidinput->input; | ||
624 | 625 | ||
625 | if (hid->claimed & HID_CLAIMED_INPUT) { | 626 | if (hid->claimed & HID_CLAIMED_INPUT) { |
626 | switch (usage->hid) { | 627 | switch (usage->hid) { |
@@ -670,13 +671,16 @@ static void mt_process_mt_event(struct hid_device *hid, struct hid_field *field, | |||
670 | break; | 671 | break; |
671 | 672 | ||
672 | default: | 673 | default: |
674 | if (usage->type) | ||
675 | input_event(input, usage->type, usage->code, | ||
676 | value); | ||
673 | return; | 677 | return; |
674 | } | 678 | } |
675 | 679 | ||
676 | if (usage->usage_index + 1 == field->report_count) { | 680 | if (usage->usage_index + 1 == field->report_count) { |
677 | /* we only take into account the last report. */ | 681 | /* we only take into account the last report. */ |
678 | if (usage->hid == td->last_slot_field) | 682 | if (usage->hid == td->last_slot_field) |
679 | mt_complete_slot(td, field->hidinput->input); | 683 | mt_complete_slot(td, input); |
680 | 684 | ||
681 | if (field->index == td->last_field_index | 685 | if (field->index == td->last_field_index |
682 | && td->num_received >= td->num_expected) | 686 | && td->num_received >= td->num_expected) |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index e0e6abf1cd3b..19b8360f2330 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -73,6 +73,7 @@ static const struct hid_blacklist { | |||
73 | { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, | 73 | { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, |
74 | { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, | 74 | { USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET }, |
75 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, | 75 | { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET }, |
76 | { USB_VENDOR_ID_MSI, USB_DEVICE_ID_MSI_GX680R_LED_PANEL, HID_QUIRK_NO_INIT_REPORTS }, | ||
76 | { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, | 77 | { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, |
77 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, | 78 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS }, |
78 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, | 79 | { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS }, |
@@ -80,6 +81,7 @@ static const struct hid_blacklist { | |||
80 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, | 81 | { USB_VENDOR_ID_PRODIGE, USB_DEVICE_ID_PRODIGE_CORDLESS, HID_QUIRK_NOGET }, |
81 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, | 82 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3001, HID_QUIRK_NOGET }, |
82 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, | 83 | { USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH_3008, HID_QUIRK_NOGET }, |
84 | { USB_VENDOR_ID_REALTEK, USB_DEVICE_ID_REALTEK_READER, HID_QUIRK_NO_INIT_REPORTS }, | ||
83 | { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, | 85 | { USB_VENDOR_ID_SENNHEISER, USB_DEVICE_ID_SENNHEISER_BTD500USB, HID_QUIRK_NOGET }, |
84 | { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, | 86 | { USB_VENDOR_ID_SIGMATEL, USB_DEVICE_ID_SIGMATEL_STMP3780, HID_QUIRK_NOGET }, |
85 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, | 87 | { USB_VENDOR_ID_SUN, USB_DEVICE_ID_RARITAN_KVM_DONGLE, HID_QUIRK_NOGET }, |
diff --git a/drivers/hwmon/lineage-pem.c b/drivers/hwmon/lineage-pem.c index 41df29f59b0e..ebbb9f4f27a3 100644 --- a/drivers/hwmon/lineage-pem.c +++ b/drivers/hwmon/lineage-pem.c | |||
@@ -422,6 +422,7 @@ static struct attribute *pem_input_attributes[] = { | |||
422 | &sensor_dev_attr_in2_input.dev_attr.attr, | 422 | &sensor_dev_attr_in2_input.dev_attr.attr, |
423 | &sensor_dev_attr_curr1_input.dev_attr.attr, | 423 | &sensor_dev_attr_curr1_input.dev_attr.attr, |
424 | &sensor_dev_attr_power1_input.dev_attr.attr, | 424 | &sensor_dev_attr_power1_input.dev_attr.attr, |
425 | NULL | ||
425 | }; | 426 | }; |
426 | 427 | ||
427 | static const struct attribute_group pem_input_group = { | 428 | static const struct attribute_group pem_input_group = { |
@@ -432,6 +433,7 @@ static struct attribute *pem_fan_attributes[] = { | |||
432 | &sensor_dev_attr_fan1_input.dev_attr.attr, | 433 | &sensor_dev_attr_fan1_input.dev_attr.attr, |
433 | &sensor_dev_attr_fan2_input.dev_attr.attr, | 434 | &sensor_dev_attr_fan2_input.dev_attr.attr, |
434 | &sensor_dev_attr_fan3_input.dev_attr.attr, | 435 | &sensor_dev_attr_fan3_input.dev_attr.attr, |
436 | NULL | ||
435 | }; | 437 | }; |
436 | 438 | ||
437 | static const struct attribute_group pem_fan_group = { | 439 | static const struct attribute_group pem_fan_group = { |
diff --git a/drivers/hwmon/lm75.h b/drivers/hwmon/lm75.h index 668ff4721323..5cde94e56f17 100644 --- a/drivers/hwmon/lm75.h +++ b/drivers/hwmon/lm75.h | |||
@@ -25,7 +25,7 @@ | |||
25 | which contains this code, we don't worry about the wasted space. | 25 | which contains this code, we don't worry about the wasted space. |
26 | */ | 26 | */ |
27 | 27 | ||
28 | #include <linux/hwmon.h> | 28 | #include <linux/kernel.h> |
29 | 29 | ||
30 | /* straight from the datasheet */ | 30 | /* straight from the datasheet */ |
31 | #define LM75_TEMP_MIN (-55000) | 31 | #define LM75_TEMP_MIN (-55000) |
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c index 9652a2c92a24..6d6130752f94 100644 --- a/drivers/hwmon/pmbus/ltc2978.c +++ b/drivers/hwmon/pmbus/ltc2978.c | |||
@@ -59,10 +59,10 @@ enum chips { ltc2978, ltc3880 }; | |||
59 | struct ltc2978_data { | 59 | struct ltc2978_data { |
60 | enum chips id; | 60 | enum chips id; |
61 | int vin_min, vin_max; | 61 | int vin_min, vin_max; |
62 | int temp_min, temp_max; | 62 | int temp_min, temp_max[2]; |
63 | int vout_min[8], vout_max[8]; | 63 | int vout_min[8], vout_max[8]; |
64 | int iout_max[2]; | 64 | int iout_max[2]; |
65 | int temp2_max[2]; | 65 | int temp2_max; |
66 | struct pmbus_driver_info info; | 66 | struct pmbus_driver_info info; |
67 | }; | 67 | }; |
68 | 68 | ||
@@ -113,9 +113,10 @@ static int ltc2978_read_word_data_common(struct i2c_client *client, int page, | |||
113 | ret = pmbus_read_word_data(client, page, | 113 | ret = pmbus_read_word_data(client, page, |
114 | LTC2978_MFR_TEMPERATURE_PEAK); | 114 | LTC2978_MFR_TEMPERATURE_PEAK); |
115 | if (ret >= 0) { | 115 | if (ret >= 0) { |
116 | if (lin11_to_val(ret) > lin11_to_val(data->temp_max)) | 116 | if (lin11_to_val(ret) |
117 | data->temp_max = ret; | 117 | > lin11_to_val(data->temp_max[page])) |
118 | ret = data->temp_max; | 118 | data->temp_max[page] = ret; |
119 | ret = data->temp_max[page]; | ||
119 | } | 120 | } |
120 | break; | 121 | break; |
121 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | 122 | case PMBUS_VIRT_RESET_VOUT_HISTORY: |
@@ -204,10 +205,9 @@ static int ltc3880_read_word_data(struct i2c_client *client, int page, int reg) | |||
204 | ret = pmbus_read_word_data(client, page, | 205 | ret = pmbus_read_word_data(client, page, |
205 | LTC3880_MFR_TEMPERATURE2_PEAK); | 206 | LTC3880_MFR_TEMPERATURE2_PEAK); |
206 | if (ret >= 0) { | 207 | if (ret >= 0) { |
207 | if (lin11_to_val(ret) | 208 | if (lin11_to_val(ret) > lin11_to_val(data->temp2_max)) |
208 | > lin11_to_val(data->temp2_max[page])) | 209 | data->temp2_max = ret; |
209 | data->temp2_max[page] = ret; | 210 | ret = data->temp2_max; |
210 | ret = data->temp2_max[page]; | ||
211 | } | 211 | } |
212 | break; | 212 | break; |
213 | case PMBUS_VIRT_READ_VIN_MIN: | 213 | case PMBUS_VIRT_READ_VIN_MIN: |
@@ -248,11 +248,11 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page, | |||
248 | 248 | ||
249 | switch (reg) { | 249 | switch (reg) { |
250 | case PMBUS_VIRT_RESET_IOUT_HISTORY: | 250 | case PMBUS_VIRT_RESET_IOUT_HISTORY: |
251 | data->iout_max[page] = 0x7fff; | 251 | data->iout_max[page] = 0x7c00; |
252 | ret = ltc2978_clear_peaks(client, page, data->id); | 252 | ret = ltc2978_clear_peaks(client, page, data->id); |
253 | break; | 253 | break; |
254 | case PMBUS_VIRT_RESET_TEMP2_HISTORY: | 254 | case PMBUS_VIRT_RESET_TEMP2_HISTORY: |
255 | data->temp2_max[page] = 0x7fff; | 255 | data->temp2_max = 0x7c00; |
256 | ret = ltc2978_clear_peaks(client, page, data->id); | 256 | ret = ltc2978_clear_peaks(client, page, data->id); |
257 | break; | 257 | break; |
258 | case PMBUS_VIRT_RESET_VOUT_HISTORY: | 258 | case PMBUS_VIRT_RESET_VOUT_HISTORY: |
@@ -262,12 +262,12 @@ static int ltc2978_write_word_data(struct i2c_client *client, int page, | |||
262 | break; | 262 | break; |
263 | case PMBUS_VIRT_RESET_VIN_HISTORY: | 263 | case PMBUS_VIRT_RESET_VIN_HISTORY: |
264 | data->vin_min = 0x7bff; | 264 | data->vin_min = 0x7bff; |
265 | data->vin_max = 0; | 265 | data->vin_max = 0x7c00; |
266 | ret = ltc2978_clear_peaks(client, page, data->id); | 266 | ret = ltc2978_clear_peaks(client, page, data->id); |
267 | break; | 267 | break; |
268 | case PMBUS_VIRT_RESET_TEMP_HISTORY: | 268 | case PMBUS_VIRT_RESET_TEMP_HISTORY: |
269 | data->temp_min = 0x7bff; | 269 | data->temp_min = 0x7bff; |
270 | data->temp_max = 0x7fff; | 270 | data->temp_max[page] = 0x7c00; |
271 | ret = ltc2978_clear_peaks(client, page, data->id); | 271 | ret = ltc2978_clear_peaks(client, page, data->id); |
272 | break; | 272 | break; |
273 | default: | 273 | default: |
@@ -321,12 +321,14 @@ static int ltc2978_probe(struct i2c_client *client, | |||
321 | info = &data->info; | 321 | info = &data->info; |
322 | info->write_word_data = ltc2978_write_word_data; | 322 | info->write_word_data = ltc2978_write_word_data; |
323 | 323 | ||
324 | data->vout_min[0] = 0xffff; | ||
325 | data->vin_min = 0x7bff; | 324 | data->vin_min = 0x7bff; |
325 | data->vin_max = 0x7c00; | ||
326 | data->temp_min = 0x7bff; | 326 | data->temp_min = 0x7bff; |
327 | data->temp_max = 0x7fff; | 327 | for (i = 0; i < ARRAY_SIZE(data->temp_max); i++) |
328 | data->temp_max[i] = 0x7c00; | ||
329 | data->temp2_max = 0x7c00; | ||
328 | 330 | ||
329 | switch (id->driver_data) { | 331 | switch (data->id) { |
330 | case ltc2978: | 332 | case ltc2978: |
331 | info->read_word_data = ltc2978_read_word_data; | 333 | info->read_word_data = ltc2978_read_word_data; |
332 | info->pages = 8; | 334 | info->pages = 8; |
@@ -336,7 +338,6 @@ static int ltc2978_probe(struct i2c_client *client, | |||
336 | for (i = 1; i < 8; i++) { | 338 | for (i = 1; i < 8; i++) { |
337 | info->func[i] = PMBUS_HAVE_VOUT | 339 | info->func[i] = PMBUS_HAVE_VOUT |
338 | | PMBUS_HAVE_STATUS_VOUT; | 340 | | PMBUS_HAVE_STATUS_VOUT; |
339 | data->vout_min[i] = 0xffff; | ||
340 | } | 341 | } |
341 | break; | 342 | break; |
342 | case ltc3880: | 343 | case ltc3880: |
@@ -352,11 +353,14 @@ static int ltc2978_probe(struct i2c_client *client, | |||
352 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT | 353 | | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT |
353 | | PMBUS_HAVE_POUT | 354 | | PMBUS_HAVE_POUT |
354 | | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; | 355 | | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP; |
355 | data->vout_min[1] = 0xffff; | 356 | data->iout_max[0] = 0x7c00; |
357 | data->iout_max[1] = 0x7c00; | ||
356 | break; | 358 | break; |
357 | default: | 359 | default: |
358 | return -ENODEV; | 360 | return -ENODEV; |
359 | } | 361 | } |
362 | for (i = 0; i < info->pages; i++) | ||
363 | data->vout_min[i] = 0xffff; | ||
360 | 364 | ||
361 | return pmbus_do_probe(client, id, info); | 365 | return pmbus_do_probe(client, id, info); |
362 | } | 366 | } |
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c index 80eef50c50fd..9add60920ac0 100644 --- a/drivers/hwmon/pmbus/pmbus_core.c +++ b/drivers/hwmon/pmbus/pmbus_core.c | |||
@@ -766,12 +766,14 @@ static ssize_t pmbus_show_label(struct device *dev, | |||
766 | static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) | 766 | static int pmbus_add_attribute(struct pmbus_data *data, struct attribute *attr) |
767 | { | 767 | { |
768 | if (data->num_attributes >= data->max_attributes - 1) { | 768 | if (data->num_attributes >= data->max_attributes - 1) { |
769 | data->max_attributes += PMBUS_ATTR_ALLOC_SIZE; | 769 | int new_max_attrs = data->max_attributes + PMBUS_ATTR_ALLOC_SIZE; |
770 | data->group.attrs = krealloc(data->group.attrs, | 770 | void *new_attrs = krealloc(data->group.attrs, |
771 | sizeof(struct attribute *) * | 771 | new_max_attrs * sizeof(void *), |
772 | data->max_attributes, GFP_KERNEL); | 772 | GFP_KERNEL); |
773 | if (data->group.attrs == NULL) | 773 | if (!new_attrs) |
774 | return -ENOMEM; | 774 | return -ENOMEM; |
775 | data->group.attrs = new_attrs; | ||
776 | data->max_attributes = new_max_attrs; | ||
775 | } | 777 | } |
776 | 778 | ||
777 | data->group.attrs[data->num_attributes++] = attr; | 779 | data->group.attrs[data->num_attributes++] = attr; |
diff --git a/drivers/hwmon/sht15.c b/drivers/hwmon/sht15.c index bfe326e896df..2507f902fb7a 100644 --- a/drivers/hwmon/sht15.c +++ b/drivers/hwmon/sht15.c | |||
@@ -965,7 +965,13 @@ static int sht15_probe(struct platform_device *pdev) | |||
965 | if (voltage) | 965 | if (voltage) |
966 | data->supply_uv = voltage; | 966 | data->supply_uv = voltage; |
967 | 967 | ||
968 | regulator_enable(data->reg); | 968 | ret = regulator_enable(data->reg); |
969 | if (ret != 0) { | ||
970 | dev_err(&pdev->dev, | ||
971 | "failed to enable regulator: %d\n", ret); | ||
972 | return ret; | ||
973 | } | ||
974 | |||
969 | /* | 975 | /* |
970 | * Setup a notifier block to update this if another device | 976 | * Setup a notifier block to update this if another device |
971 | * causes the voltage to change | 977 | * causes the voltage to change |
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 46cde098c11c..e380c6eef3af 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig | |||
@@ -4,7 +4,6 @@ | |||
4 | 4 | ||
5 | menuconfig I2C | 5 | menuconfig I2C |
6 | tristate "I2C support" | 6 | tristate "I2C support" |
7 | depends on !S390 | ||
8 | select RT_MUTEXES | 7 | select RT_MUTEXES |
9 | ---help--- | 8 | ---help--- |
10 | I2C (pronounce: I-squared-C) is a slow serial bus protocol used in | 9 | I2C (pronounce: I-squared-C) is a slow serial bus protocol used in |
@@ -76,6 +75,7 @@ config I2C_HELPER_AUTO | |||
76 | 75 | ||
77 | config I2C_SMBUS | 76 | config I2C_SMBUS |
78 | tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO | 77 | tristate "SMBus-specific protocols" if !I2C_HELPER_AUTO |
78 | depends on GENERIC_HARDIRQS | ||
79 | help | 79 | help |
80 | Say Y here if you want support for SMBus extensions to the I2C | 80 | Say Y here if you want support for SMBus extensions to the I2C |
81 | specification. At the moment, the only supported extension is | 81 | specification. At the moment, the only supported extension is |
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index a3725de92384..adfee98486b1 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig | |||
@@ -114,7 +114,7 @@ config I2C_I801 | |||
114 | 114 | ||
115 | config I2C_ISCH | 115 | config I2C_ISCH |
116 | tristate "Intel SCH SMBus 1.0" | 116 | tristate "Intel SCH SMBus 1.0" |
117 | depends on PCI | 117 | depends on PCI && GENERIC_HARDIRQS |
118 | select LPC_SCH | 118 | select LPC_SCH |
119 | help | 119 | help |
120 | Say Y here if you want to use SMBus controller on the Intel SCH | 120 | Say Y here if you want to use SMBus controller on the Intel SCH |
@@ -543,6 +543,7 @@ config I2C_NUC900 | |||
543 | 543 | ||
544 | config I2C_OCORES | 544 | config I2C_OCORES |
545 | tristate "OpenCores I2C Controller" | 545 | tristate "OpenCores I2C Controller" |
546 | depends on GENERIC_HARDIRQS | ||
546 | help | 547 | help |
547 | If you say yes to this option, support will be included for the | 548 | If you say yes to this option, support will be included for the |
548 | OpenCores I2C controller. For details see | 549 | OpenCores I2C controller. For details see |
@@ -777,7 +778,7 @@ config I2C_DIOLAN_U2C | |||
777 | 778 | ||
778 | config I2C_PARPORT | 779 | config I2C_PARPORT |
779 | tristate "Parallel port adapter" | 780 | tristate "Parallel port adapter" |
780 | depends on PARPORT | 781 | depends on PARPORT && GENERIC_HARDIRQS |
781 | select I2C_ALGOBIT | 782 | select I2C_ALGOBIT |
782 | select I2C_SMBUS | 783 | select I2C_SMBUS |
783 | help | 784 | help |
@@ -802,6 +803,7 @@ config I2C_PARPORT | |||
802 | 803 | ||
803 | config I2C_PARPORT_LIGHT | 804 | config I2C_PARPORT_LIGHT |
804 | tristate "Parallel port adapter (light)" | 805 | tristate "Parallel port adapter (light)" |
806 | depends on GENERIC_HARDIRQS | ||
805 | select I2C_ALGOBIT | 807 | select I2C_ALGOBIT |
806 | select I2C_SMBUS | 808 | select I2C_SMBUS |
807 | help | 809 | help |
diff --git a/drivers/i2c/busses/i2c-ismt.c b/drivers/i2c/busses/i2c-ismt.c index e9205ee8cf94..130f02cc9d94 100644 --- a/drivers/i2c/busses/i2c-ismt.c +++ b/drivers/i2c/busses/i2c-ismt.c | |||
@@ -80,6 +80,7 @@ | |||
80 | /* PCI DIDs for the Intel SMBus Message Transport (SMT) Devices */ | 80 | /* PCI DIDs for the Intel SMBus Message Transport (SMT) Devices */ |
81 | #define PCI_DEVICE_ID_INTEL_S1200_SMT0 0x0c59 | 81 | #define PCI_DEVICE_ID_INTEL_S1200_SMT0 0x0c59 |
82 | #define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a | 82 | #define PCI_DEVICE_ID_INTEL_S1200_SMT1 0x0c5a |
83 | #define PCI_DEVICE_ID_INTEL_AVOTON_SMT 0x1f15 | ||
83 | 84 | ||
84 | #define ISMT_DESC_ENTRIES 32 /* number of descriptor entries */ | 85 | #define ISMT_DESC_ENTRIES 32 /* number of descriptor entries */ |
85 | #define ISMT_MAX_RETRIES 3 /* number of SMBus retries to attempt */ | 86 | #define ISMT_MAX_RETRIES 3 /* number of SMBus retries to attempt */ |
@@ -185,6 +186,7 @@ struct ismt_priv { | |||
185 | static const DEFINE_PCI_DEVICE_TABLE(ismt_ids) = { | 186 | static const DEFINE_PCI_DEVICE_TABLE(ismt_ids) = { |
186 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) }, | 187 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT0) }, |
187 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) }, | 188 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_S1200_SMT1) }, |
189 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_AVOTON_SMT) }, | ||
188 | { 0, } | 190 | { 0, } |
189 | }; | 191 | }; |
190 | 192 | ||
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 36704e3ab3fa..b714776b6ddd 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c | |||
@@ -411,7 +411,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) | |||
411 | int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE; | 411 | int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE; |
412 | u32 clk_divisor; | 412 | u32 clk_divisor; |
413 | 413 | ||
414 | tegra_i2c_clock_enable(i2c_dev); | 414 | err = tegra_i2c_clock_enable(i2c_dev); |
415 | if (err < 0) { | ||
416 | dev_err(i2c_dev->dev, "Clock enable failed %d\n", err); | ||
417 | return err; | ||
418 | } | ||
415 | 419 | ||
416 | tegra_periph_reset_assert(i2c_dev->div_clk); | 420 | tegra_periph_reset_assert(i2c_dev->div_clk); |
417 | udelay(2); | 421 | udelay(2); |
@@ -628,7 +632,12 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], | |||
628 | if (i2c_dev->is_suspended) | 632 | if (i2c_dev->is_suspended) |
629 | return -EBUSY; | 633 | return -EBUSY; |
630 | 634 | ||
631 | tegra_i2c_clock_enable(i2c_dev); | 635 | ret = tegra_i2c_clock_enable(i2c_dev); |
636 | if (ret < 0) { | ||
637 | dev_err(i2c_dev->dev, "Clock enable failed %d\n", ret); | ||
638 | return ret; | ||
639 | } | ||
640 | |||
632 | for (i = 0; i < num; i++) { | 641 | for (i = 0; i < num; i++) { |
633 | enum msg_end_type end_type = MSG_END_STOP; | 642 | enum msg_end_type end_type = MSG_END_STOP; |
634 | if (i < (num - 1)) { | 643 | if (i < (num - 1)) { |
diff --git a/drivers/i2c/muxes/i2c-mux-pca9541.c b/drivers/i2c/muxes/i2c-mux-pca9541.c index f3b8f9a6a89b..966a18a5d12d 100644 --- a/drivers/i2c/muxes/i2c-mux-pca9541.c +++ b/drivers/i2c/muxes/i2c-mux-pca9541.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * | 3 | * |
4 | * Copyright (c) 2010 Ericsson AB. | 4 | * Copyright (c) 2010 Ericsson AB. |
5 | * | 5 | * |
6 | * Author: Guenter Roeck <guenter.roeck@ericsson.com> | 6 | * Author: Guenter Roeck <linux@roeck-us.net> |
7 | * | 7 | * |
8 | * Derived from: | 8 | * Derived from: |
9 | * pca954x.c | 9 | * pca954x.c |
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c index 0198324a8b0c..bd33473f8e38 100644 --- a/drivers/iio/common/st_sensors/st_sensors_core.c +++ b/drivers/iio/common/st_sensors/st_sensors_core.c | |||
@@ -62,7 +62,7 @@ st_sensors_match_odr_error: | |||
62 | int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr) | 62 | int st_sensors_set_odr(struct iio_dev *indio_dev, unsigned int odr) |
63 | { | 63 | { |
64 | int err; | 64 | int err; |
65 | struct st_sensor_odr_avl odr_out; | 65 | struct st_sensor_odr_avl odr_out = {0, 0}; |
66 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 66 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
67 | 67 | ||
68 | err = st_sensors_match_odr(sdata->sensor, odr, &odr_out); | 68 | err = st_sensors_match_odr(sdata->sensor, odr, &odr_out); |
@@ -114,7 +114,7 @@ st_sensors_match_odr_error: | |||
114 | 114 | ||
115 | static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs) | 115 | static int st_sensors_set_fullscale(struct iio_dev *indio_dev, unsigned int fs) |
116 | { | 116 | { |
117 | int err, i; | 117 | int err, i = 0; |
118 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 118 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
119 | 119 | ||
120 | err = st_sensors_match_fs(sdata->sensor, fs, &i); | 120 | err = st_sensors_match_fs(sdata->sensor, fs, &i); |
@@ -139,14 +139,13 @@ st_accel_set_fullscale_error: | |||
139 | 139 | ||
140 | int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable) | 140 | int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable) |
141 | { | 141 | { |
142 | bool found; | ||
143 | u8 tmp_value; | 142 | u8 tmp_value; |
144 | int err = -EINVAL; | 143 | int err = -EINVAL; |
145 | struct st_sensor_odr_avl odr_out; | 144 | bool found = false; |
145 | struct st_sensor_odr_avl odr_out = {0, 0}; | ||
146 | struct st_sensor_data *sdata = iio_priv(indio_dev); | 146 | struct st_sensor_data *sdata = iio_priv(indio_dev); |
147 | 147 | ||
148 | if (enable) { | 148 | if (enable) { |
149 | found = false; | ||
150 | tmp_value = sdata->sensor->pw.value_on; | 149 | tmp_value = sdata->sensor->pw.value_on; |
151 | if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) && | 150 | if ((sdata->sensor->odr.addr == sdata->sensor->pw.addr) && |
152 | (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) { | 151 | (sdata->sensor->odr.mask == sdata->sensor->pw.mask)) { |
diff --git a/drivers/iio/dac/ad5064.c b/drivers/iio/dac/ad5064.c index 2fe1d4edcb2f..74f2d52795f6 100644 --- a/drivers/iio/dac/ad5064.c +++ b/drivers/iio/dac/ad5064.c | |||
@@ -27,7 +27,6 @@ | |||
27 | #define AD5064_ADDR(x) ((x) << 20) | 27 | #define AD5064_ADDR(x) ((x) << 20) |
28 | #define AD5064_CMD(x) ((x) << 24) | 28 | #define AD5064_CMD(x) ((x) << 24) |
29 | 29 | ||
30 | #define AD5064_ADDR_DAC(chan) (chan) | ||
31 | #define AD5064_ADDR_ALL_DAC 0xF | 30 | #define AD5064_ADDR_ALL_DAC 0xF |
32 | 31 | ||
33 | #define AD5064_CMD_WRITE_INPUT_N 0x0 | 32 | #define AD5064_CMD_WRITE_INPUT_N 0x0 |
@@ -131,15 +130,15 @@ static int ad5064_write(struct ad5064_state *st, unsigned int cmd, | |||
131 | } | 130 | } |
132 | 131 | ||
133 | static int ad5064_sync_powerdown_mode(struct ad5064_state *st, | 132 | static int ad5064_sync_powerdown_mode(struct ad5064_state *st, |
134 | unsigned int channel) | 133 | const struct iio_chan_spec *chan) |
135 | { | 134 | { |
136 | unsigned int val; | 135 | unsigned int val; |
137 | int ret; | 136 | int ret; |
138 | 137 | ||
139 | val = (0x1 << channel); | 138 | val = (0x1 << chan->address); |
140 | 139 | ||
141 | if (st->pwr_down[channel]) | 140 | if (st->pwr_down[chan->channel]) |
142 | val |= st->pwr_down_mode[channel] << 8; | 141 | val |= st->pwr_down_mode[chan->channel] << 8; |
143 | 142 | ||
144 | ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); | 143 | ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, 0, val, 0); |
145 | 144 | ||
@@ -169,7 +168,7 @@ static int ad5064_set_powerdown_mode(struct iio_dev *indio_dev, | |||
169 | mutex_lock(&indio_dev->mlock); | 168 | mutex_lock(&indio_dev->mlock); |
170 | st->pwr_down_mode[chan->channel] = mode + 1; | 169 | st->pwr_down_mode[chan->channel] = mode + 1; |
171 | 170 | ||
172 | ret = ad5064_sync_powerdown_mode(st, chan->channel); | 171 | ret = ad5064_sync_powerdown_mode(st, chan); |
173 | mutex_unlock(&indio_dev->mlock); | 172 | mutex_unlock(&indio_dev->mlock); |
174 | 173 | ||
175 | return ret; | 174 | return ret; |
@@ -205,7 +204,7 @@ static ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev, | |||
205 | mutex_lock(&indio_dev->mlock); | 204 | mutex_lock(&indio_dev->mlock); |
206 | st->pwr_down[chan->channel] = pwr_down; | 205 | st->pwr_down[chan->channel] = pwr_down; |
207 | 206 | ||
208 | ret = ad5064_sync_powerdown_mode(st, chan->channel); | 207 | ret = ad5064_sync_powerdown_mode(st, chan); |
209 | mutex_unlock(&indio_dev->mlock); | 208 | mutex_unlock(&indio_dev->mlock); |
210 | return ret ? ret : len; | 209 | return ret ? ret : len; |
211 | } | 210 | } |
@@ -258,7 +257,7 @@ static int ad5064_write_raw(struct iio_dev *indio_dev, | |||
258 | 257 | ||
259 | switch (mask) { | 258 | switch (mask) { |
260 | case IIO_CHAN_INFO_RAW: | 259 | case IIO_CHAN_INFO_RAW: |
261 | if (val > (1 << chan->scan_type.realbits) || val < 0) | 260 | if (val >= (1 << chan->scan_type.realbits) || val < 0) |
262 | return -EINVAL; | 261 | return -EINVAL; |
263 | 262 | ||
264 | mutex_lock(&indio_dev->mlock); | 263 | mutex_lock(&indio_dev->mlock); |
@@ -292,34 +291,44 @@ static const struct iio_chan_spec_ext_info ad5064_ext_info[] = { | |||
292 | { }, | 291 | { }, |
293 | }; | 292 | }; |
294 | 293 | ||
295 | #define AD5064_CHANNEL(chan, bits) { \ | 294 | #define AD5064_CHANNEL(chan, addr, bits) { \ |
296 | .type = IIO_VOLTAGE, \ | 295 | .type = IIO_VOLTAGE, \ |
297 | .indexed = 1, \ | 296 | .indexed = 1, \ |
298 | .output = 1, \ | 297 | .output = 1, \ |
299 | .channel = (chan), \ | 298 | .channel = (chan), \ |
300 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ | 299 | .info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT | \ |
301 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ | 300 | IIO_CHAN_INFO_SCALE_SEPARATE_BIT, \ |
302 | .address = AD5064_ADDR_DAC(chan), \ | 301 | .address = addr, \ |
303 | .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \ | 302 | .scan_type = IIO_ST('u', (bits), 16, 20 - (bits)), \ |
304 | .ext_info = ad5064_ext_info, \ | 303 | .ext_info = ad5064_ext_info, \ |
305 | } | 304 | } |
306 | 305 | ||
307 | #define DECLARE_AD5064_CHANNELS(name, bits) \ | 306 | #define DECLARE_AD5064_CHANNELS(name, bits) \ |
308 | const struct iio_chan_spec name[] = { \ | 307 | const struct iio_chan_spec name[] = { \ |
309 | AD5064_CHANNEL(0, bits), \ | 308 | AD5064_CHANNEL(0, 0, bits), \ |
310 | AD5064_CHANNEL(1, bits), \ | 309 | AD5064_CHANNEL(1, 1, bits), \ |
311 | AD5064_CHANNEL(2, bits), \ | 310 | AD5064_CHANNEL(2, 2, bits), \ |
312 | AD5064_CHANNEL(3, bits), \ | 311 | AD5064_CHANNEL(3, 3, bits), \ |
313 | AD5064_CHANNEL(4, bits), \ | 312 | AD5064_CHANNEL(4, 4, bits), \ |
314 | AD5064_CHANNEL(5, bits), \ | 313 | AD5064_CHANNEL(5, 5, bits), \ |
315 | AD5064_CHANNEL(6, bits), \ | 314 | AD5064_CHANNEL(6, 6, bits), \ |
316 | AD5064_CHANNEL(7, bits), \ | 315 | AD5064_CHANNEL(7, 7, bits), \ |
316 | } | ||
317 | |||
318 | #define DECLARE_AD5065_CHANNELS(name, bits) \ | ||
319 | const struct iio_chan_spec name[] = { \ | ||
320 | AD5064_CHANNEL(0, 0, bits), \ | ||
321 | AD5064_CHANNEL(1, 3, bits), \ | ||
317 | } | 322 | } |
318 | 323 | ||
319 | static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); | 324 | static DECLARE_AD5064_CHANNELS(ad5024_channels, 12); |
320 | static DECLARE_AD5064_CHANNELS(ad5044_channels, 14); | 325 | static DECLARE_AD5064_CHANNELS(ad5044_channels, 14); |
321 | static DECLARE_AD5064_CHANNELS(ad5064_channels, 16); | 326 | static DECLARE_AD5064_CHANNELS(ad5064_channels, 16); |
322 | 327 | ||
328 | static DECLARE_AD5065_CHANNELS(ad5025_channels, 12); | ||
329 | static DECLARE_AD5065_CHANNELS(ad5045_channels, 14); | ||
330 | static DECLARE_AD5065_CHANNELS(ad5065_channels, 16); | ||
331 | |||
323 | static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { | 332 | static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { |
324 | [ID_AD5024] = { | 333 | [ID_AD5024] = { |
325 | .shared_vref = false, | 334 | .shared_vref = false, |
@@ -328,7 +337,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { | |||
328 | }, | 337 | }, |
329 | [ID_AD5025] = { | 338 | [ID_AD5025] = { |
330 | .shared_vref = false, | 339 | .shared_vref = false, |
331 | .channels = ad5024_channels, | 340 | .channels = ad5025_channels, |
332 | .num_channels = 2, | 341 | .num_channels = 2, |
333 | }, | 342 | }, |
334 | [ID_AD5044] = { | 343 | [ID_AD5044] = { |
@@ -338,7 +347,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { | |||
338 | }, | 347 | }, |
339 | [ID_AD5045] = { | 348 | [ID_AD5045] = { |
340 | .shared_vref = false, | 349 | .shared_vref = false, |
341 | .channels = ad5044_channels, | 350 | .channels = ad5045_channels, |
342 | .num_channels = 2, | 351 | .num_channels = 2, |
343 | }, | 352 | }, |
344 | [ID_AD5064] = { | 353 | [ID_AD5064] = { |
@@ -353,7 +362,7 @@ static const struct ad5064_chip_info ad5064_chip_info_tbl[] = { | |||
353 | }, | 362 | }, |
354 | [ID_AD5065] = { | 363 | [ID_AD5065] = { |
355 | .shared_vref = false, | 364 | .shared_vref = false, |
356 | .channels = ad5064_channels, | 365 | .channels = ad5065_channels, |
357 | .num_channels = 2, | 366 | .num_channels = 2, |
358 | }, | 367 | }, |
359 | [ID_AD5628_1] = { | 368 | [ID_AD5628_1] = { |
@@ -429,6 +438,7 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, | |||
429 | { | 438 | { |
430 | struct iio_dev *indio_dev; | 439 | struct iio_dev *indio_dev; |
431 | struct ad5064_state *st; | 440 | struct ad5064_state *st; |
441 | unsigned int midscale; | ||
432 | unsigned int i; | 442 | unsigned int i; |
433 | int ret; | 443 | int ret; |
434 | 444 | ||
@@ -465,11 +475,6 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, | |||
465 | goto error_free_reg; | 475 | goto error_free_reg; |
466 | } | 476 | } |
467 | 477 | ||
468 | for (i = 0; i < st->chip_info->num_channels; ++i) { | ||
469 | st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; | ||
470 | st->dac_cache[i] = 0x8000; | ||
471 | } | ||
472 | |||
473 | indio_dev->dev.parent = dev; | 478 | indio_dev->dev.parent = dev; |
474 | indio_dev->name = name; | 479 | indio_dev->name = name; |
475 | indio_dev->info = &ad5064_info; | 480 | indio_dev->info = &ad5064_info; |
@@ -477,6 +482,13 @@ static int ad5064_probe(struct device *dev, enum ad5064_type type, | |||
477 | indio_dev->channels = st->chip_info->channels; | 482 | indio_dev->channels = st->chip_info->channels; |
478 | indio_dev->num_channels = st->chip_info->num_channels; | 483 | indio_dev->num_channels = st->chip_info->num_channels; |
479 | 484 | ||
485 | midscale = (1 << indio_dev->channels[0].scan_type.realbits) / 2; | ||
486 | |||
487 | for (i = 0; i < st->chip_info->num_channels; ++i) { | ||
488 | st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K; | ||
489 | st->dac_cache[i] = midscale; | ||
490 | } | ||
491 | |||
480 | ret = iio_device_register(indio_dev); | 492 | ret = iio_device_register(indio_dev); |
481 | if (ret) | 493 | if (ret) |
482 | goto error_disable_reg; | 494 | goto error_disable_reg; |
diff --git a/drivers/iio/imu/inv_mpu6050/Kconfig b/drivers/iio/imu/inv_mpu6050/Kconfig index b5cfa3a354cf..361b2328453d 100644 --- a/drivers/iio/imu/inv_mpu6050/Kconfig +++ b/drivers/iio/imu/inv_mpu6050/Kconfig | |||
@@ -5,6 +5,7 @@ | |||
5 | config INV_MPU6050_IIO | 5 | config INV_MPU6050_IIO |
6 | tristate "Invensense MPU6050 devices" | 6 | tristate "Invensense MPU6050 devices" |
7 | depends on I2C && SYSFS | 7 | depends on I2C && SYSFS |
8 | select IIO_BUFFER | ||
8 | select IIO_TRIGGERED_BUFFER | 9 | select IIO_TRIGGERED_BUFFER |
9 | help | 10 | help |
10 | This driver supports the Invensense MPU6050 devices. | 11 | This driver supports the Invensense MPU6050 devices. |
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 565bfb161c1a..a3fde52840ca 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c | |||
@@ -1575,6 +1575,12 @@ static int c4iw_reconnect(struct c4iw_ep *ep) | |||
1575 | 1575 | ||
1576 | neigh = dst_neigh_lookup(ep->dst, | 1576 | neigh = dst_neigh_lookup(ep->dst, |
1577 | &ep->com.cm_id->remote_addr.sin_addr.s_addr); | 1577 | &ep->com.cm_id->remote_addr.sin_addr.s_addr); |
1578 | if (!neigh) { | ||
1579 | pr_err("%s - cannot alloc neigh.\n", __func__); | ||
1580 | err = -ENOMEM; | ||
1581 | goto fail4; | ||
1582 | } | ||
1583 | |||
1578 | /* get a l2t entry */ | 1584 | /* get a l2t entry */ |
1579 | if (neigh->dev->flags & IFF_LOOPBACK) { | 1585 | if (neigh->dev->flags & IFF_LOOPBACK) { |
1580 | PDBG("%s LOOPBACK\n", __func__); | 1586 | PDBG("%s LOOPBACK\n", __func__); |
@@ -3053,6 +3059,12 @@ static int rx_pkt(struct c4iw_dev *dev, struct sk_buff *skb) | |||
3053 | dst = &rt->dst; | 3059 | dst = &rt->dst; |
3054 | neigh = dst_neigh_lookup_skb(dst, skb); | 3060 | neigh = dst_neigh_lookup_skb(dst, skb); |
3055 | 3061 | ||
3062 | if (!neigh) { | ||
3063 | pr_err("%s - failed to allocate neigh!\n", | ||
3064 | __func__); | ||
3065 | goto free_dst; | ||
3066 | } | ||
3067 | |||
3056 | if (neigh->dev->flags & IFF_LOOPBACK) { | 3068 | if (neigh->dev->flags & IFF_LOOPBACK) { |
3057 | pdev = ip_dev_find(&init_net, iph->daddr); | 3069 | pdev = ip_dev_find(&init_net, iph->daddr); |
3058 | e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, | 3070 | e = cxgb4_l2t_get(dev->rdev.lldi.l2t, neigh, |
diff --git a/drivers/infiniband/hw/cxgb4/qp.c b/drivers/infiniband/hw/cxgb4/qp.c index 17ba4f8bc12d..70b1808a08f4 100644 --- a/drivers/infiniband/hw/cxgb4/qp.c +++ b/drivers/infiniband/hw/cxgb4/qp.c | |||
@@ -186,8 +186,10 @@ static int create_qp(struct c4iw_rdev *rdev, struct t4_wq *wq, | |||
186 | wq->rq.queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev), | 186 | wq->rq.queue = dma_alloc_coherent(&(rdev->lldi.pdev->dev), |
187 | wq->rq.memsize, &(wq->rq.dma_addr), | 187 | wq->rq.memsize, &(wq->rq.dma_addr), |
188 | GFP_KERNEL); | 188 | GFP_KERNEL); |
189 | if (!wq->rq.queue) | 189 | if (!wq->rq.queue) { |
190 | ret = -ENOMEM; | ||
190 | goto free_sq; | 191 | goto free_sq; |
192 | } | ||
191 | PDBG("%s sq base va 0x%p pa 0x%llx rq base va 0x%p pa 0x%llx\n", | 193 | PDBG("%s sq base va 0x%p pa 0x%llx rq base va 0x%p pa 0x%llx\n", |
192 | __func__, wq->sq.queue, | 194 | __func__, wq->sq.queue, |
193 | (unsigned long long)virt_to_phys(wq->sq.queue), | 195 | (unsigned long long)virt_to_phys(wq->sq.queue), |
diff --git a/drivers/infiniband/hw/ipath/ipath_fs.c b/drivers/infiniband/hw/ipath/ipath_fs.c index a479375a8fd8..e0c404bdc4a8 100644 --- a/drivers/infiniband/hw/ipath/ipath_fs.c +++ b/drivers/infiniband/hw/ipath/ipath_fs.c | |||
@@ -410,6 +410,7 @@ static struct file_system_type ipathfs_fs_type = { | |||
410 | .mount = ipathfs_mount, | 410 | .mount = ipathfs_mount, |
411 | .kill_sb = ipathfs_kill_super, | 411 | .kill_sb = ipathfs_kill_super, |
412 | }; | 412 | }; |
413 | MODULE_ALIAS_FS("ipathfs"); | ||
413 | 414 | ||
414 | int __init ipath_init_ipathfs(void) | 415 | int __init ipath_init_ipathfs(void) |
415 | { | 416 | { |
diff --git a/drivers/infiniband/hw/ipath/ipath_verbs.c b/drivers/infiniband/hw/ipath/ipath_verbs.c index 439c35d4a669..ea93870266eb 100644 --- a/drivers/infiniband/hw/ipath/ipath_verbs.c +++ b/drivers/infiniband/hw/ipath/ipath_verbs.c | |||
@@ -620,7 +620,7 @@ void ipath_ib_rcv(struct ipath_ibdev *dev, void *rhdr, void *data, | |||
620 | goto bail; | 620 | goto bail; |
621 | } | 621 | } |
622 | 622 | ||
623 | opcode = be32_to_cpu(ohdr->bth[0]) >> 24; | 623 | opcode = (be32_to_cpu(ohdr->bth[0]) >> 24) & 0x7f; |
624 | dev->opstats[opcode].n_bytes += tlen; | 624 | dev->opstats[opcode].n_bytes += tlen; |
625 | dev->opstats[opcode].n_packets++; | 625 | dev->opstats[opcode].n_packets++; |
626 | 626 | ||
diff --git a/drivers/infiniband/hw/mlx4/cm.c b/drivers/infiniband/hw/mlx4/cm.c index e0d79b2395e4..add98d01476c 100644 --- a/drivers/infiniband/hw/mlx4/cm.c +++ b/drivers/infiniband/hw/mlx4/cm.c | |||
@@ -362,7 +362,6 @@ void mlx4_ib_cm_paravirt_init(struct mlx4_ib_dev *dev) | |||
362 | INIT_LIST_HEAD(&dev->sriov.cm_list); | 362 | INIT_LIST_HEAD(&dev->sriov.cm_list); |
363 | dev->sriov.sl_id_map = RB_ROOT; | 363 | dev->sriov.sl_id_map = RB_ROOT; |
364 | idr_init(&dev->sriov.pv_id_table); | 364 | idr_init(&dev->sriov.pv_id_table); |
365 | idr_pre_get(&dev->sriov.pv_id_table, GFP_KERNEL); | ||
366 | } | 365 | } |
367 | 366 | ||
368 | /* slave = -1 ==> all slaves */ | 367 | /* slave = -1 ==> all slaves */ |
diff --git a/drivers/infiniband/hw/qib/Kconfig b/drivers/infiniband/hw/qib/Kconfig index 8349f9c5064c..1e603a375069 100644 --- a/drivers/infiniband/hw/qib/Kconfig +++ b/drivers/infiniband/hw/qib/Kconfig | |||
@@ -1,7 +1,7 @@ | |||
1 | config INFINIBAND_QIB | 1 | config INFINIBAND_QIB |
2 | tristate "QLogic PCIe HCA support" | 2 | tristate "Intel PCIe HCA support" |
3 | depends on 64BIT | 3 | depends on 64BIT |
4 | ---help--- | 4 | ---help--- |
5 | This is a low-level driver for QLogic PCIe QLE InfiniBand host | 5 | This is a low-level driver for Intel PCIe QLE InfiniBand host |
6 | channel adapters. This driver does not support the QLogic | 6 | channel adapters. This driver does not support the Intel |
7 | HyperTransport card (model QHT7140). | 7 | HyperTransport card (model QHT7140). |
diff --git a/drivers/infiniband/hw/qib/qib_driver.c b/drivers/infiniband/hw/qib/qib_driver.c index 5423edcab51f..216092477dfc 100644 --- a/drivers/infiniband/hw/qib/qib_driver.c +++ b/drivers/infiniband/hw/qib/qib_driver.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2013 Intel Corporation. All rights reserved. | ||
2 | * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. | 3 | * Copyright (c) 2006, 2007, 2008, 2009 QLogic Corporation. All rights reserved. |
3 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
4 | * | 5 | * |
@@ -63,8 +64,8 @@ MODULE_PARM_DESC(compat_ddr_negotiate, | |||
63 | "Attempt pre-IBTA 1.2 DDR speed negotiation"); | 64 | "Attempt pre-IBTA 1.2 DDR speed negotiation"); |
64 | 65 | ||
65 | MODULE_LICENSE("Dual BSD/GPL"); | 66 | MODULE_LICENSE("Dual BSD/GPL"); |
66 | MODULE_AUTHOR("QLogic <support@qlogic.com>"); | 67 | MODULE_AUTHOR("Intel <ibsupport@intel.com>"); |
67 | MODULE_DESCRIPTION("QLogic IB driver"); | 68 | MODULE_DESCRIPTION("Intel IB driver"); |
68 | MODULE_VERSION(QIB_DRIVER_VERSION); | 69 | MODULE_VERSION(QIB_DRIVER_VERSION); |
69 | 70 | ||
70 | /* | 71 | /* |
diff --git a/drivers/infiniband/hw/qib/qib_fs.c b/drivers/infiniband/hw/qib/qib_fs.c index 644bd6f6467c..f247fc6e6182 100644 --- a/drivers/infiniband/hw/qib/qib_fs.c +++ b/drivers/infiniband/hw/qib/qib_fs.c | |||
@@ -604,6 +604,7 @@ static struct file_system_type qibfs_fs_type = { | |||
604 | .mount = qibfs_mount, | 604 | .mount = qibfs_mount, |
605 | .kill_sb = qibfs_kill_super, | 605 | .kill_sb = qibfs_kill_super, |
606 | }; | 606 | }; |
607 | MODULE_ALIAS_FS("ipathfs"); | ||
607 | 608 | ||
608 | int __init qib_init_qibfs(void) | 609 | int __init qib_init_qibfs(void) |
609 | { | 610 | { |
diff --git a/drivers/infiniband/hw/qib/qib_iba6120.c b/drivers/infiniband/hw/qib/qib_iba6120.c index a099ac171e22..0232ae56b1fa 100644 --- a/drivers/infiniband/hw/qib/qib_iba6120.c +++ b/drivers/infiniband/hw/qib/qib_iba6120.c | |||
@@ -1,4 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2013 Intel Corporation. All rights reserved. | ||
2 | * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation. | 3 | * Copyright (c) 2006, 2007, 2008, 2009, 2010 QLogic Corporation. |
3 | * All rights reserved. | 4 | * All rights reserved. |
4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 5 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
@@ -51,7 +52,7 @@ static u32 qib_6120_iblink_state(u64); | |||
51 | 52 | ||
52 | /* | 53 | /* |
53 | * This file contains all the chip-specific register information and | 54 | * This file contains all the chip-specific register information and |
54 | * access functions for the QLogic QLogic_IB PCI-Express chip. | 55 | * access functions for the Intel Intel_IB PCI-Express chip. |
55 | * | 56 | * |
56 | */ | 57 | */ |
57 | 58 | ||
diff --git a/drivers/infiniband/hw/qib/qib_init.c b/drivers/infiniband/hw/qib/qib_init.c index 50e33aa0b4e3..173f805790da 100644 --- a/drivers/infiniband/hw/qib/qib_init.c +++ b/drivers/infiniband/hw/qib/qib_init.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012 Intel Corporation. All rights reserved. | 2 | * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. |
3 | * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. | 3 | * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. |
4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
5 | * | 5 | * |
@@ -1138,7 +1138,7 @@ void qib_disable_after_error(struct qib_devdata *dd) | |||
1138 | static void qib_remove_one(struct pci_dev *); | 1138 | static void qib_remove_one(struct pci_dev *); |
1139 | static int qib_init_one(struct pci_dev *, const struct pci_device_id *); | 1139 | static int qib_init_one(struct pci_dev *, const struct pci_device_id *); |
1140 | 1140 | ||
1141 | #define DRIVER_LOAD_MSG "QLogic " QIB_DRV_NAME " loaded: " | 1141 | #define DRIVER_LOAD_MSG "Intel " QIB_DRV_NAME " loaded: " |
1142 | #define PFX QIB_DRV_NAME ": " | 1142 | #define PFX QIB_DRV_NAME ": " |
1143 | 1143 | ||
1144 | static DEFINE_PCI_DEVICE_TABLE(qib_pci_tbl) = { | 1144 | static DEFINE_PCI_DEVICE_TABLE(qib_pci_tbl) = { |
@@ -1355,7 +1355,7 @@ static int qib_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1355 | dd = qib_init_iba6120_funcs(pdev, ent); | 1355 | dd = qib_init_iba6120_funcs(pdev, ent); |
1356 | #else | 1356 | #else |
1357 | qib_early_err(&pdev->dev, | 1357 | qib_early_err(&pdev->dev, |
1358 | "QLogic PCIE device 0x%x cannot work if CONFIG_PCI_MSI is not enabled\n", | 1358 | "Intel PCIE device 0x%x cannot work if CONFIG_PCI_MSI is not enabled\n", |
1359 | ent->device); | 1359 | ent->device); |
1360 | dd = ERR_PTR(-ENODEV); | 1360 | dd = ERR_PTR(-ENODEV); |
1361 | #endif | 1361 | #endif |
@@ -1371,7 +1371,7 @@ static int qib_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1371 | 1371 | ||
1372 | default: | 1372 | default: |
1373 | qib_early_err(&pdev->dev, | 1373 | qib_early_err(&pdev->dev, |
1374 | "Failing on unknown QLogic deviceid 0x%x\n", | 1374 | "Failing on unknown Intel deviceid 0x%x\n", |
1375 | ent->device); | 1375 | ent->device); |
1376 | ret = -ENODEV; | 1376 | ret = -ENODEV; |
1377 | } | 1377 | } |
diff --git a/drivers/infiniband/hw/qib/qib_sd7220.c b/drivers/infiniband/hw/qib/qib_sd7220.c index 50a8a0d4fe67..08a6c6d39e56 100644 --- a/drivers/infiniband/hw/qib/qib_sd7220.c +++ b/drivers/infiniband/hw/qib/qib_sd7220.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012 Intel Corporation. All rights reserved. | 2 | * Copyright (c) 2013 Intel Corporation. All rights reserved. |
3 | * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. | 3 | * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. |
4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. | 4 | * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. |
5 | * | 5 | * |
@@ -44,7 +44,7 @@ | |||
44 | #include "qib.h" | 44 | #include "qib.h" |
45 | #include "qib_7220.h" | 45 | #include "qib_7220.h" |
46 | 46 | ||
47 | #define SD7220_FW_NAME "qlogic/sd7220.fw" | 47 | #define SD7220_FW_NAME "intel/sd7220.fw" |
48 | MODULE_FIRMWARE(SD7220_FW_NAME); | 48 | MODULE_FIRMWARE(SD7220_FW_NAME); |
49 | 49 | ||
50 | /* | 50 | /* |
diff --git a/drivers/infiniband/hw/qib/qib_verbs.c b/drivers/infiniband/hw/qib/qib_verbs.c index ba51a4715a1d..7c0ab16a2fe2 100644 --- a/drivers/infiniband/hw/qib/qib_verbs.c +++ b/drivers/infiniband/hw/qib/qib_verbs.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2012 Intel Corporation. All rights reserved. | 2 | * Copyright (c) 2012, 2013 Intel Corporation. All rights reserved. |
3 | * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. | 3 | * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. |
4 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. | 4 | * Copyright (c) 2005, 2006 PathScale, Inc. All rights reserved. |
5 | * | 5 | * |
@@ -2224,7 +2224,7 @@ int qib_register_ib_device(struct qib_devdata *dd) | |||
2224 | ibdev->dma_ops = &qib_dma_mapping_ops; | 2224 | ibdev->dma_ops = &qib_dma_mapping_ops; |
2225 | 2225 | ||
2226 | snprintf(ibdev->node_desc, sizeof(ibdev->node_desc), | 2226 | snprintf(ibdev->node_desc, sizeof(ibdev->node_desc), |
2227 | "QLogic Infiniband HCA %s", init_utsname()->nodename); | 2227 | "Intel Infiniband HCA %s", init_utsname()->nodename); |
2228 | 2228 | ||
2229 | ret = ib_register_device(ibdev, qib_create_port_files); | 2229 | ret = ib_register_device(ibdev, qib_create_port_files); |
2230 | if (ret) | 2230 | if (ret) |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 67b0c1d23678..1ef880de3a41 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -758,9 +758,13 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ | |||
758 | if (++priv->tx_outstanding == ipoib_sendq_size) { | 758 | if (++priv->tx_outstanding == ipoib_sendq_size) { |
759 | ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", | 759 | ipoib_dbg(priv, "TX ring 0x%x full, stopping kernel net queue\n", |
760 | tx->qp->qp_num); | 760 | tx->qp->qp_num); |
761 | if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP)) | ||
762 | ipoib_warn(priv, "request notify on send CQ failed\n"); | ||
763 | netif_stop_queue(dev); | 761 | netif_stop_queue(dev); |
762 | rc = ib_req_notify_cq(priv->send_cq, | ||
763 | IB_CQ_NEXT_COMP | IB_CQ_REPORT_MISSED_EVENTS); | ||
764 | if (rc < 0) | ||
765 | ipoib_warn(priv, "request notify on send CQ failed\n"); | ||
766 | else if (rc) | ||
767 | ipoib_send_comp_handler(priv->send_cq, dev); | ||
764 | } | 768 | } |
765 | } | 769 | } |
766 | } | 770 | } |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 7cd74e29cbc8..9135606c8649 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -158,14 +158,10 @@ static unsigned int get_time_pit(void) | |||
158 | #define GET_TIME(x) rdtscl(x) | 158 | #define GET_TIME(x) rdtscl(x) |
159 | #define DELTA(x,y) ((y)-(x)) | 159 | #define DELTA(x,y) ((y)-(x)) |
160 | #define TIME_NAME "TSC" | 160 | #define TIME_NAME "TSC" |
161 | #elif defined(__alpha__) | 161 | #elif defined(__alpha__) || defined(CONFIG_MN10300) || defined(CONFIG_ARM) || defined(CONFIG_TILE) |
162 | #define GET_TIME(x) do { x = get_cycles(); } while (0) | 162 | #define GET_TIME(x) do { x = get_cycles(); } while (0) |
163 | #define DELTA(x,y) ((y)-(x)) | 163 | #define DELTA(x,y) ((y)-(x)) |
164 | #define TIME_NAME "PCC" | 164 | #define TIME_NAME "get_cycles" |
165 | #elif defined(CONFIG_MN10300) || defined(CONFIG_TILE) | ||
166 | #define GET_TIME(x) do { x = get_cycles(); } while (0) | ||
167 | #define DELTA(x, y) ((x) - (y)) | ||
168 | #define TIME_NAME "TSC" | ||
169 | #else | 165 | #else |
170 | #define FAKE_TIME | 166 | #define FAKE_TIME |
171 | static unsigned long analog_faketime = 0; | 167 | static unsigned long analog_faketime = 0; |
diff --git a/drivers/input/keyboard/tc3589x-keypad.c b/drivers/input/keyboard/tc3589x-keypad.c index 2fb0d76a04c4..208de7cbb7fa 100644 --- a/drivers/input/keyboard/tc3589x-keypad.c +++ b/drivers/input/keyboard/tc3589x-keypad.c | |||
@@ -70,8 +70,6 @@ | |||
70 | #define TC3589x_EVT_INT_CLR 0x2 | 70 | #define TC3589x_EVT_INT_CLR 0x2 |
71 | #define TC3589x_KBD_INT_CLR 0x1 | 71 | #define TC3589x_KBD_INT_CLR 0x1 |
72 | 72 | ||
73 | #define TC3589x_KBD_KEYMAP_SIZE 64 | ||
74 | |||
75 | /** | 73 | /** |
76 | * struct tc_keypad - data structure used by keypad driver | 74 | * struct tc_keypad - data structure used by keypad driver |
77 | * @tc3589x: pointer to tc35893 | 75 | * @tc3589x: pointer to tc35893 |
@@ -88,7 +86,7 @@ struct tc_keypad { | |||
88 | const struct tc3589x_keypad_platform_data *board; | 86 | const struct tc3589x_keypad_platform_data *board; |
89 | unsigned int krow; | 87 | unsigned int krow; |
90 | unsigned int kcol; | 88 | unsigned int kcol; |
91 | unsigned short keymap[TC3589x_KBD_KEYMAP_SIZE]; | 89 | unsigned short *keymap; |
92 | bool keypad_stopped; | 90 | bool keypad_stopped; |
93 | }; | 91 | }; |
94 | 92 | ||
@@ -338,12 +336,14 @@ static int tc3589x_keypad_probe(struct platform_device *pdev) | |||
338 | 336 | ||
339 | error = matrix_keypad_build_keymap(plat->keymap_data, NULL, | 337 | error = matrix_keypad_build_keymap(plat->keymap_data, NULL, |
340 | TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, | 338 | TC3589x_MAX_KPROW, TC3589x_MAX_KPCOL, |
341 | keypad->keymap, input); | 339 | NULL, input); |
342 | if (error) { | 340 | if (error) { |
343 | dev_err(&pdev->dev, "Failed to build keymap\n"); | 341 | dev_err(&pdev->dev, "Failed to build keymap\n"); |
344 | goto err_free_mem; | 342 | goto err_free_mem; |
345 | } | 343 | } |
346 | 344 | ||
345 | keypad->keymap = input->keycode; | ||
346 | |||
347 | input_set_capability(input, EV_MSC, MSC_SCAN); | 347 | input_set_capability(input, EV_MSC, MSC_SCAN); |
348 | if (!plat->no_autorepeat) | 348 | if (!plat->no_autorepeat) |
349 | __set_bit(EV_REP, input->evbit); | 349 | __set_bit(EV_REP, input->evbit); |
diff --git a/drivers/input/mouse/alps.c b/drivers/input/mouse/alps.c index 7b99fc7c9438..0238e0e14335 100644 --- a/drivers/input/mouse/alps.c +++ b/drivers/input/mouse/alps.c | |||
@@ -490,6 +490,29 @@ static void alps_decode_rushmore(struct alps_fields *f, unsigned char *p) | |||
490 | f->y_map |= (p[5] & 0x20) << 6; | 490 | f->y_map |= (p[5] & 0x20) << 6; |
491 | } | 491 | } |
492 | 492 | ||
493 | static void alps_decode_dolphin(struct alps_fields *f, unsigned char *p) | ||
494 | { | ||
495 | f->first_mp = !!(p[0] & 0x02); | ||
496 | f->is_mp = !!(p[0] & 0x20); | ||
497 | |||
498 | f->fingers = ((p[0] & 0x6) >> 1 | | ||
499 | (p[0] & 0x10) >> 2); | ||
500 | f->x_map = ((p[2] & 0x60) >> 5) | | ||
501 | ((p[4] & 0x7f) << 2) | | ||
502 | ((p[5] & 0x7f) << 9) | | ||
503 | ((p[3] & 0x07) << 16) | | ||
504 | ((p[3] & 0x70) << 15) | | ||
505 | ((p[0] & 0x01) << 22); | ||
506 | f->y_map = (p[1] & 0x7f) | | ||
507 | ((p[2] & 0x1f) << 7); | ||
508 | |||
509 | f->x = ((p[1] & 0x7f) | ((p[4] & 0x0f) << 7)); | ||
510 | f->y = ((p[2] & 0x7f) | ((p[4] & 0xf0) << 3)); | ||
511 | f->z = (p[0] & 4) ? 0 : p[5] & 0x7f; | ||
512 | |||
513 | alps_decode_buttons_v3(f, p); | ||
514 | } | ||
515 | |||
493 | static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) | 516 | static void alps_process_touchpad_packet_v3(struct psmouse *psmouse) |
494 | { | 517 | { |
495 | struct alps_data *priv = psmouse->private; | 518 | struct alps_data *priv = psmouse->private; |
@@ -874,7 +897,8 @@ static psmouse_ret_t alps_process_byte(struct psmouse *psmouse) | |||
874 | } | 897 | } |
875 | 898 | ||
876 | /* Bytes 2 - pktsize should have 0 in the highest bit */ | 899 | /* Bytes 2 - pktsize should have 0 in the highest bit */ |
877 | if (psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && | 900 | if (priv->proto_version != ALPS_PROTO_V5 && |
901 | psmouse->pktcnt >= 2 && psmouse->pktcnt <= psmouse->pktsize && | ||
878 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { | 902 | (psmouse->packet[psmouse->pktcnt - 1] & 0x80)) { |
879 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", | 903 | psmouse_dbg(psmouse, "refusing packet[%i] = %x\n", |
880 | psmouse->pktcnt - 1, | 904 | psmouse->pktcnt - 1, |
@@ -994,8 +1018,7 @@ static int alps_rpt_cmd(struct psmouse *psmouse, int init_command, | |||
994 | return 0; | 1018 | return 0; |
995 | } | 1019 | } |
996 | 1020 | ||
997 | static int alps_enter_command_mode(struct psmouse *psmouse, | 1021 | static int alps_enter_command_mode(struct psmouse *psmouse) |
998 | unsigned char *resp) | ||
999 | { | 1022 | { |
1000 | unsigned char param[4]; | 1023 | unsigned char param[4]; |
1001 | 1024 | ||
@@ -1004,14 +1027,12 @@ static int alps_enter_command_mode(struct psmouse *psmouse, | |||
1004 | return -1; | 1027 | return -1; |
1005 | } | 1028 | } |
1006 | 1029 | ||
1007 | if (param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) { | 1030 | if ((param[0] != 0x88 || (param[1] != 0x07 && param[1] != 0x08)) && |
1031 | param[0] != 0x73) { | ||
1008 | psmouse_dbg(psmouse, | 1032 | psmouse_dbg(psmouse, |
1009 | "unknown response while entering command mode\n"); | 1033 | "unknown response while entering command mode\n"); |
1010 | return -1; | 1034 | return -1; |
1011 | } | 1035 | } |
1012 | |||
1013 | if (resp) | ||
1014 | *resp = param[2]; | ||
1015 | return 0; | 1036 | return 0; |
1016 | } | 1037 | } |
1017 | 1038 | ||
@@ -1176,7 +1197,7 @@ static int alps_passthrough_mode_v3(struct psmouse *psmouse, | |||
1176 | { | 1197 | { |
1177 | int reg_val, ret = -1; | 1198 | int reg_val, ret = -1; |
1178 | 1199 | ||
1179 | if (alps_enter_command_mode(psmouse, NULL)) | 1200 | if (alps_enter_command_mode(psmouse)) |
1180 | return -1; | 1201 | return -1; |
1181 | 1202 | ||
1182 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); | 1203 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x0008); |
@@ -1216,7 +1237,7 @@ static int alps_probe_trackstick_v3(struct psmouse *psmouse, int reg_base) | |||
1216 | { | 1237 | { |
1217 | int ret = -EIO, reg_val; | 1238 | int ret = -EIO, reg_val; |
1218 | 1239 | ||
1219 | if (alps_enter_command_mode(psmouse, NULL)) | 1240 | if (alps_enter_command_mode(psmouse)) |
1220 | goto error; | 1241 | goto error; |
1221 | 1242 | ||
1222 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); | 1243 | reg_val = alps_command_mode_read_reg(psmouse, reg_base + 0x08); |
@@ -1279,7 +1300,7 @@ static int alps_setup_trackstick_v3(struct psmouse *psmouse, int reg_base) | |||
1279 | * supported by this driver. If bit 1 isn't set the packet | 1300 | * supported by this driver. If bit 1 isn't set the packet |
1280 | * format is different. | 1301 | * format is different. |
1281 | */ | 1302 | */ |
1282 | if (alps_enter_command_mode(psmouse, NULL) || | 1303 | if (alps_enter_command_mode(psmouse) || |
1283 | alps_command_mode_write_reg(psmouse, | 1304 | alps_command_mode_write_reg(psmouse, |
1284 | reg_base + 0x08, 0x82) || | 1305 | reg_base + 0x08, 0x82) || |
1285 | alps_exit_command_mode(psmouse)) | 1306 | alps_exit_command_mode(psmouse)) |
@@ -1306,7 +1327,7 @@ static int alps_hw_init_v3(struct psmouse *psmouse) | |||
1306 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) | 1327 | alps_setup_trackstick_v3(psmouse, ALPS_REG_BASE_PINNACLE) == -EIO) |
1307 | goto error; | 1328 | goto error; |
1308 | 1329 | ||
1309 | if (alps_enter_command_mode(psmouse, NULL) || | 1330 | if (alps_enter_command_mode(psmouse) || |
1310 | alps_absolute_mode_v3(psmouse)) { | 1331 | alps_absolute_mode_v3(psmouse)) { |
1311 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); | 1332 | psmouse_err(psmouse, "Failed to enter absolute mode\n"); |
1312 | goto error; | 1333 | goto error; |
@@ -1381,7 +1402,7 @@ static int alps_hw_init_rushmore_v3(struct psmouse *psmouse) | |||
1381 | priv->flags &= ~ALPS_DUALPOINT; | 1402 | priv->flags &= ~ALPS_DUALPOINT; |
1382 | } | 1403 | } |
1383 | 1404 | ||
1384 | if (alps_enter_command_mode(psmouse, NULL) || | 1405 | if (alps_enter_command_mode(psmouse) || |
1385 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || | 1406 | alps_command_mode_read_reg(psmouse, 0xc2d9) == -1 || |
1386 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) | 1407 | alps_command_mode_write_reg(psmouse, 0xc2cb, 0x00)) |
1387 | goto error; | 1408 | goto error; |
@@ -1431,7 +1452,7 @@ static int alps_hw_init_v4(struct psmouse *psmouse) | |||
1431 | struct ps2dev *ps2dev = &psmouse->ps2dev; | 1452 | struct ps2dev *ps2dev = &psmouse->ps2dev; |
1432 | unsigned char param[4]; | 1453 | unsigned char param[4]; |
1433 | 1454 | ||
1434 | if (alps_enter_command_mode(psmouse, NULL)) | 1455 | if (alps_enter_command_mode(psmouse)) |
1435 | goto error; | 1456 | goto error; |
1436 | 1457 | ||
1437 | if (alps_absolute_mode_v4(psmouse)) { | 1458 | if (alps_absolute_mode_v4(psmouse)) { |
@@ -1499,6 +1520,23 @@ error: | |||
1499 | return -1; | 1520 | return -1; |
1500 | } | 1521 | } |
1501 | 1522 | ||
1523 | static int alps_hw_init_dolphin_v1(struct psmouse *psmouse) | ||
1524 | { | ||
1525 | struct ps2dev *ps2dev = &psmouse->ps2dev; | ||
1526 | unsigned char param[2]; | ||
1527 | |||
1528 | /* This is dolphin "v1" as empirically defined by florin9doi */ | ||
1529 | param[0] = 0x64; | ||
1530 | param[1] = 0x28; | ||
1531 | |||
1532 | if (ps2_command(ps2dev, NULL, PSMOUSE_CMD_SETSTREAM) || | ||
1533 | ps2_command(ps2dev, ¶m[0], PSMOUSE_CMD_SETRATE) || | ||
1534 | ps2_command(ps2dev, ¶m[1], PSMOUSE_CMD_SETRATE)) | ||
1535 | return -1; | ||
1536 | |||
1537 | return 0; | ||
1538 | } | ||
1539 | |||
1502 | static void alps_set_defaults(struct alps_data *priv) | 1540 | static void alps_set_defaults(struct alps_data *priv) |
1503 | { | 1541 | { |
1504 | priv->byte0 = 0x8f; | 1542 | priv->byte0 = 0x8f; |
@@ -1532,6 +1570,21 @@ static void alps_set_defaults(struct alps_data *priv) | |||
1532 | priv->nibble_commands = alps_v4_nibble_commands; | 1570 | priv->nibble_commands = alps_v4_nibble_commands; |
1533 | priv->addr_command = PSMOUSE_CMD_DISABLE; | 1571 | priv->addr_command = PSMOUSE_CMD_DISABLE; |
1534 | break; | 1572 | break; |
1573 | case ALPS_PROTO_V5: | ||
1574 | priv->hw_init = alps_hw_init_dolphin_v1; | ||
1575 | priv->process_packet = alps_process_packet_v3; | ||
1576 | priv->decode_fields = alps_decode_dolphin; | ||
1577 | priv->set_abs_params = alps_set_abs_params_mt; | ||
1578 | priv->nibble_commands = alps_v3_nibble_commands; | ||
1579 | priv->addr_command = PSMOUSE_CMD_RESET_WRAP; | ||
1580 | priv->byte0 = 0xc8; | ||
1581 | priv->mask0 = 0xc8; | ||
1582 | priv->flags = 0; | ||
1583 | priv->x_max = 1360; | ||
1584 | priv->y_max = 660; | ||
1585 | priv->x_bits = 23; | ||
1586 | priv->y_bits = 12; | ||
1587 | break; | ||
1535 | } | 1588 | } |
1536 | } | 1589 | } |
1537 | 1590 | ||
@@ -1592,6 +1645,12 @@ static int alps_identify(struct psmouse *psmouse, struct alps_data *priv) | |||
1592 | 1645 | ||
1593 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { | 1646 | if (alps_match_table(psmouse, priv, e7, ec) == 0) { |
1594 | return 0; | 1647 | return 0; |
1648 | } else if (e7[0] == 0x73 && e7[1] == 0x03 && e7[2] == 0x50 && | ||
1649 | ec[0] == 0x73 && ec[1] == 0x01) { | ||
1650 | priv->proto_version = ALPS_PROTO_V5; | ||
1651 | alps_set_defaults(priv); | ||
1652 | |||
1653 | return 0; | ||
1595 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { | 1654 | } else if (ec[0] == 0x88 && ec[1] == 0x08) { |
1596 | priv->proto_version = ALPS_PROTO_V3; | 1655 | priv->proto_version = ALPS_PROTO_V3; |
1597 | alps_set_defaults(priv); | 1656 | alps_set_defaults(priv); |
diff --git a/drivers/input/mouse/alps.h b/drivers/input/mouse/alps.h index 970480551b6e..eee59853b9ce 100644 --- a/drivers/input/mouse/alps.h +++ b/drivers/input/mouse/alps.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #define ALPS_PROTO_V2 2 | 16 | #define ALPS_PROTO_V2 2 |
17 | #define ALPS_PROTO_V3 3 | 17 | #define ALPS_PROTO_V3 3 |
18 | #define ALPS_PROTO_V4 4 | 18 | #define ALPS_PROTO_V4 4 |
19 | #define ALPS_PROTO_V5 5 | ||
19 | 20 | ||
20 | /** | 21 | /** |
21 | * struct alps_model_info - touchpad ID table | 22 | * struct alps_model_info - touchpad ID table |
diff --git a/drivers/input/mouse/cypress_ps2.c b/drivers/input/mouse/cypress_ps2.c index 1673dc6c8092..f51765fff054 100644 --- a/drivers/input/mouse/cypress_ps2.c +++ b/drivers/input/mouse/cypress_ps2.c | |||
@@ -236,6 +236,13 @@ static int cypress_read_fw_version(struct psmouse *psmouse) | |||
236 | cytp->fw_version = param[2] & FW_VERSION_MASX; | 236 | cytp->fw_version = param[2] & FW_VERSION_MASX; |
237 | cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; | 237 | cytp->tp_metrics_supported = (param[2] & TP_METRICS_MASK) ? 1 : 0; |
238 | 238 | ||
239 | /* | ||
240 | * Trackpad fw_version 11 (in Dell XPS12) yields a bogus response to | ||
241 | * CYTP_CMD_READ_TP_METRICS so do not try to use it. LP: #1103594. | ||
242 | */ | ||
243 | if (cytp->fw_version >= 11) | ||
244 | cytp->tp_metrics_supported = 0; | ||
245 | |||
239 | psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); | 246 | psmouse_dbg(psmouse, "cytp->fw_version = %d\n", cytp->fw_version); |
240 | psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", | 247 | psmouse_dbg(psmouse, "cytp->tp_metrics_supported = %d\n", |
241 | cytp->tp_metrics_supported); | 248 | cytp->tp_metrics_supported); |
@@ -258,6 +265,9 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) | |||
258 | cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; | 265 | cytp->tp_res_x = cytp->tp_max_abs_x / cytp->tp_width; |
259 | cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; | 266 | cytp->tp_res_y = cytp->tp_max_abs_y / cytp->tp_high; |
260 | 267 | ||
268 | if (!cytp->tp_metrics_supported) | ||
269 | return 0; | ||
270 | |||
261 | memset(param, 0, sizeof(param)); | 271 | memset(param, 0, sizeof(param)); |
262 | if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { | 272 | if (cypress_send_ext_cmd(psmouse, CYTP_CMD_READ_TP_METRICS, param) == 0) { |
263 | /* Update trackpad parameters. */ | 273 | /* Update trackpad parameters. */ |
@@ -315,18 +325,15 @@ static int cypress_read_tp_metrics(struct psmouse *psmouse) | |||
315 | 325 | ||
316 | static int cypress_query_hardware(struct psmouse *psmouse) | 326 | static int cypress_query_hardware(struct psmouse *psmouse) |
317 | { | 327 | { |
318 | struct cytp_data *cytp = psmouse->private; | ||
319 | int ret; | 328 | int ret; |
320 | 329 | ||
321 | ret = cypress_read_fw_version(psmouse); | 330 | ret = cypress_read_fw_version(psmouse); |
322 | if (ret) | 331 | if (ret) |
323 | return ret; | 332 | return ret; |
324 | 333 | ||
325 | if (cytp->tp_metrics_supported) { | 334 | ret = cypress_read_tp_metrics(psmouse); |
326 | ret = cypress_read_tp_metrics(psmouse); | 335 | if (ret) |
327 | if (ret) | 336 | return ret; |
328 | return ret; | ||
329 | } | ||
330 | 337 | ||
331 | return 0; | 338 | return 0; |
332 | } | 339 | } |
diff --git a/drivers/input/tablet/wacom_wac.c b/drivers/input/tablet/wacom_wac.c index 41b6fbf60112..1daa97913b7d 100644 --- a/drivers/input/tablet/wacom_wac.c +++ b/drivers/input/tablet/wacom_wac.c | |||
@@ -2017,6 +2017,9 @@ static const struct wacom_features wacom_features_0x100 = | |||
2017 | static const struct wacom_features wacom_features_0x101 = | 2017 | static const struct wacom_features wacom_features_0x101 = |
2018 | { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, | 2018 | { "Wacom ISDv4 101", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, |
2019 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2019 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
2020 | static const struct wacom_features wacom_features_0x10D = | ||
2021 | { "Wacom ISDv4 10D", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, | ||
2022 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | ||
2020 | static const struct wacom_features wacom_features_0x4001 = | 2023 | static const struct wacom_features wacom_features_0x4001 = |
2021 | { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, | 2024 | { "Wacom ISDv4 4001", WACOM_PKGLEN_MTTPC, 26202, 16325, 255, |
2022 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; | 2025 | 0, MTTPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES }; |
@@ -2201,6 +2204,7 @@ const struct usb_device_id wacom_ids[] = { | |||
2201 | { USB_DEVICE_WACOM(0xEF) }, | 2204 | { USB_DEVICE_WACOM(0xEF) }, |
2202 | { USB_DEVICE_WACOM(0x100) }, | 2205 | { USB_DEVICE_WACOM(0x100) }, |
2203 | { USB_DEVICE_WACOM(0x101) }, | 2206 | { USB_DEVICE_WACOM(0x101) }, |
2207 | { USB_DEVICE_WACOM(0x10D) }, | ||
2204 | { USB_DEVICE_WACOM(0x4001) }, | 2208 | { USB_DEVICE_WACOM(0x4001) }, |
2205 | { USB_DEVICE_WACOM(0x47) }, | 2209 | { USB_DEVICE_WACOM(0x47) }, |
2206 | { USB_DEVICE_WACOM(0xF4) }, | 2210 | { USB_DEVICE_WACOM(0xF4) }, |
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c index 4f702b3ec1a3..434c3df250ca 100644 --- a/drivers/input/touchscreen/ads7846.c +++ b/drivers/input/touchscreen/ads7846.c | |||
@@ -236,7 +236,12 @@ static void __ads7846_disable(struct ads7846 *ts) | |||
236 | /* Must be called with ts->lock held */ | 236 | /* Must be called with ts->lock held */ |
237 | static void __ads7846_enable(struct ads7846 *ts) | 237 | static void __ads7846_enable(struct ads7846 *ts) |
238 | { | 238 | { |
239 | regulator_enable(ts->reg); | 239 | int error; |
240 | |||
241 | error = regulator_enable(ts->reg); | ||
242 | if (error != 0) | ||
243 | dev_err(&ts->spi->dev, "Failed to enable supply: %d\n", error); | ||
244 | |||
240 | ads7846_restart(ts); | 245 | ads7846_restart(ts); |
241 | } | 246 | } |
242 | 247 | ||
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index d04f810cb1dd..59aa24002c7b 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
@@ -176,11 +176,17 @@ | |||
176 | /* Define for MXT_GEN_COMMAND_T6 */ | 176 | /* Define for MXT_GEN_COMMAND_T6 */ |
177 | #define MXT_BOOT_VALUE 0xa5 | 177 | #define MXT_BOOT_VALUE 0xa5 |
178 | #define MXT_BACKUP_VALUE 0x55 | 178 | #define MXT_BACKUP_VALUE 0x55 |
179 | #define MXT_BACKUP_TIME 25 /* msec */ | 179 | #define MXT_BACKUP_TIME 50 /* msec */ |
180 | #define MXT_RESET_TIME 65 /* msec */ | 180 | #define MXT_RESET_TIME 200 /* msec */ |
181 | 181 | ||
182 | #define MXT_FWRESET_TIME 175 /* msec */ | 182 | #define MXT_FWRESET_TIME 175 /* msec */ |
183 | 183 | ||
184 | /* MXT_SPT_GPIOPWM_T19 field */ | ||
185 | #define MXT_GPIO0_MASK 0x04 | ||
186 | #define MXT_GPIO1_MASK 0x08 | ||
187 | #define MXT_GPIO2_MASK 0x10 | ||
188 | #define MXT_GPIO3_MASK 0x20 | ||
189 | |||
184 | /* Command to unlock bootloader */ | 190 | /* Command to unlock bootloader */ |
185 | #define MXT_UNLOCK_CMD_MSB 0xaa | 191 | #define MXT_UNLOCK_CMD_MSB 0xaa |
186 | #define MXT_UNLOCK_CMD_LSB 0xdc | 192 | #define MXT_UNLOCK_CMD_LSB 0xdc |
@@ -212,6 +218,8 @@ | |||
212 | /* Touchscreen absolute values */ | 218 | /* Touchscreen absolute values */ |
213 | #define MXT_MAX_AREA 0xff | 219 | #define MXT_MAX_AREA 0xff |
214 | 220 | ||
221 | #define MXT_PIXELS_PER_MM 20 | ||
222 | |||
215 | struct mxt_info { | 223 | struct mxt_info { |
216 | u8 family_id; | 224 | u8 family_id; |
217 | u8 variant_id; | 225 | u8 variant_id; |
@@ -243,6 +251,8 @@ struct mxt_data { | |||
243 | const struct mxt_platform_data *pdata; | 251 | const struct mxt_platform_data *pdata; |
244 | struct mxt_object *object_table; | 252 | struct mxt_object *object_table; |
245 | struct mxt_info info; | 253 | struct mxt_info info; |
254 | bool is_tp; | ||
255 | |||
246 | unsigned int irq; | 256 | unsigned int irq; |
247 | unsigned int max_x; | 257 | unsigned int max_x; |
248 | unsigned int max_y; | 258 | unsigned int max_y; |
@@ -251,6 +261,7 @@ struct mxt_data { | |||
251 | u8 T6_reportid; | 261 | u8 T6_reportid; |
252 | u8 T9_reportid_min; | 262 | u8 T9_reportid_min; |
253 | u8 T9_reportid_max; | 263 | u8 T9_reportid_max; |
264 | u8 T19_reportid; | ||
254 | }; | 265 | }; |
255 | 266 | ||
256 | static bool mxt_object_readable(unsigned int type) | 267 | static bool mxt_object_readable(unsigned int type) |
@@ -502,6 +513,21 @@ static int mxt_write_object(struct mxt_data *data, | |||
502 | return mxt_write_reg(data->client, reg + offset, val); | 513 | return mxt_write_reg(data->client, reg + offset, val); |
503 | } | 514 | } |
504 | 515 | ||
516 | static void mxt_input_button(struct mxt_data *data, struct mxt_message *message) | ||
517 | { | ||
518 | struct input_dev *input = data->input_dev; | ||
519 | bool button; | ||
520 | int i; | ||
521 | |||
522 | /* Active-low switch */ | ||
523 | for (i = 0; i < MXT_NUM_GPIO; i++) { | ||
524 | if (data->pdata->key_map[i] == KEY_RESERVED) | ||
525 | continue; | ||
526 | button = !(message->message[0] & MXT_GPIO0_MASK << i); | ||
527 | input_report_key(input, data->pdata->key_map[i], button); | ||
528 | } | ||
529 | } | ||
530 | |||
505 | static void mxt_input_touchevent(struct mxt_data *data, | 531 | static void mxt_input_touchevent(struct mxt_data *data, |
506 | struct mxt_message *message, int id) | 532 | struct mxt_message *message, int id) |
507 | { | 533 | { |
@@ -585,6 +611,9 @@ static irqreturn_t mxt_interrupt(int irq, void *dev_id) | |||
585 | int id = reportid - data->T9_reportid_min; | 611 | int id = reportid - data->T9_reportid_min; |
586 | mxt_input_touchevent(data, &message, id); | 612 | mxt_input_touchevent(data, &message, id); |
587 | update_input = true; | 613 | update_input = true; |
614 | } else if (message.reportid == data->T19_reportid) { | ||
615 | mxt_input_button(data, &message); | ||
616 | update_input = true; | ||
588 | } else { | 617 | } else { |
589 | mxt_dump_message(dev, &message); | 618 | mxt_dump_message(dev, &message); |
590 | } | 619 | } |
@@ -764,6 +793,9 @@ static int mxt_get_object_table(struct mxt_data *data) | |||
764 | data->T9_reportid_min = min_id; | 793 | data->T9_reportid_min = min_id; |
765 | data->T9_reportid_max = max_id; | 794 | data->T9_reportid_max = max_id; |
766 | break; | 795 | break; |
796 | case MXT_SPT_GPIOPWM_T19: | ||
797 | data->T19_reportid = min_id; | ||
798 | break; | ||
767 | } | 799 | } |
768 | } | 800 | } |
769 | 801 | ||
@@ -777,7 +809,7 @@ static void mxt_free_object_table(struct mxt_data *data) | |||
777 | data->T6_reportid = 0; | 809 | data->T6_reportid = 0; |
778 | data->T9_reportid_min = 0; | 810 | data->T9_reportid_min = 0; |
779 | data->T9_reportid_max = 0; | 811 | data->T9_reportid_max = 0; |
780 | 812 | data->T19_reportid = 0; | |
781 | } | 813 | } |
782 | 814 | ||
783 | static int mxt_initialize(struct mxt_data *data) | 815 | static int mxt_initialize(struct mxt_data *data) |
@@ -1115,9 +1147,13 @@ static int mxt_probe(struct i2c_client *client, | |||
1115 | goto err_free_mem; | 1147 | goto err_free_mem; |
1116 | } | 1148 | } |
1117 | 1149 | ||
1118 | input_dev->name = "Atmel maXTouch Touchscreen"; | 1150 | data->is_tp = pdata && pdata->is_tp; |
1151 | |||
1152 | input_dev->name = (data->is_tp) ? "Atmel maXTouch Touchpad" : | ||
1153 | "Atmel maXTouch Touchscreen"; | ||
1119 | snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", | 1154 | snprintf(data->phys, sizeof(data->phys), "i2c-%u-%04x/input0", |
1120 | client->adapter->nr, client->addr); | 1155 | client->adapter->nr, client->addr); |
1156 | |||
1121 | input_dev->phys = data->phys; | 1157 | input_dev->phys = data->phys; |
1122 | 1158 | ||
1123 | input_dev->id.bustype = BUS_I2C; | 1159 | input_dev->id.bustype = BUS_I2C; |
@@ -1140,6 +1176,29 @@ static int mxt_probe(struct i2c_client *client, | |||
1140 | __set_bit(EV_KEY, input_dev->evbit); | 1176 | __set_bit(EV_KEY, input_dev->evbit); |
1141 | __set_bit(BTN_TOUCH, input_dev->keybit); | 1177 | __set_bit(BTN_TOUCH, input_dev->keybit); |
1142 | 1178 | ||
1179 | if (data->is_tp) { | ||
1180 | int i; | ||
1181 | __set_bit(INPUT_PROP_POINTER, input_dev->propbit); | ||
1182 | __set_bit(INPUT_PROP_BUTTONPAD, input_dev->propbit); | ||
1183 | |||
1184 | for (i = 0; i < MXT_NUM_GPIO; i++) | ||
1185 | if (pdata->key_map[i] != KEY_RESERVED) | ||
1186 | __set_bit(pdata->key_map[i], input_dev->keybit); | ||
1187 | |||
1188 | __set_bit(BTN_TOOL_FINGER, input_dev->keybit); | ||
1189 | __set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit); | ||
1190 | __set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit); | ||
1191 | __set_bit(BTN_TOOL_QUADTAP, input_dev->keybit); | ||
1192 | __set_bit(BTN_TOOL_QUINTTAP, input_dev->keybit); | ||
1193 | |||
1194 | input_abs_set_res(input_dev, ABS_X, MXT_PIXELS_PER_MM); | ||
1195 | input_abs_set_res(input_dev, ABS_Y, MXT_PIXELS_PER_MM); | ||
1196 | input_abs_set_res(input_dev, ABS_MT_POSITION_X, | ||
1197 | MXT_PIXELS_PER_MM); | ||
1198 | input_abs_set_res(input_dev, ABS_MT_POSITION_Y, | ||
1199 | MXT_PIXELS_PER_MM); | ||
1200 | } | ||
1201 | |||
1143 | /* For single touch */ | 1202 | /* For single touch */ |
1144 | input_set_abs_params(input_dev, ABS_X, | 1203 | input_set_abs_params(input_dev, ABS_X, |
1145 | 0, data->max_x, 0, 0); | 1204 | 0, data->max_x, 0, 0); |
@@ -1258,6 +1317,7 @@ static SIMPLE_DEV_PM_OPS(mxt_pm_ops, mxt_suspend, mxt_resume); | |||
1258 | static const struct i2c_device_id mxt_id[] = { | 1317 | static const struct i2c_device_id mxt_id[] = { |
1259 | { "qt602240_ts", 0 }, | 1318 | { "qt602240_ts", 0 }, |
1260 | { "atmel_mxt_ts", 0 }, | 1319 | { "atmel_mxt_ts", 0 }, |
1320 | { "atmel_mxt_tp", 0 }, | ||
1261 | { "mXT224", 0 }, | 1321 | { "mXT224", 0 }, |
1262 | { } | 1322 | { } |
1263 | }; | 1323 | }; |
diff --git a/drivers/input/touchscreen/mms114.c b/drivers/input/touchscreen/mms114.c index 4a29ddf6bf1e..1443532fe6c4 100644 --- a/drivers/input/touchscreen/mms114.c +++ b/drivers/input/touchscreen/mms114.c | |||
@@ -314,15 +314,27 @@ static int mms114_start(struct mms114_data *data) | |||
314 | struct i2c_client *client = data->client; | 314 | struct i2c_client *client = data->client; |
315 | int error; | 315 | int error; |
316 | 316 | ||
317 | if (data->core_reg) | 317 | error = regulator_enable(data->core_reg); |
318 | regulator_enable(data->core_reg); | 318 | if (error) { |
319 | if (data->io_reg) | 319 | dev_err(&client->dev, "Failed to enable avdd: %d\n", error); |
320 | regulator_enable(data->io_reg); | 320 | return error; |
321 | } | ||
322 | |||
323 | error = regulator_enable(data->io_reg); | ||
324 | if (error) { | ||
325 | dev_err(&client->dev, "Failed to enable vdd: %d\n", error); | ||
326 | regulator_disable(data->core_reg); | ||
327 | return error; | ||
328 | } | ||
329 | |||
321 | mdelay(MMS114_POWERON_DELAY); | 330 | mdelay(MMS114_POWERON_DELAY); |
322 | 331 | ||
323 | error = mms114_setup_regs(data); | 332 | error = mms114_setup_regs(data); |
324 | if (error < 0) | 333 | if (error < 0) { |
334 | regulator_disable(data->io_reg); | ||
335 | regulator_disable(data->core_reg); | ||
325 | return error; | 336 | return error; |
337 | } | ||
326 | 338 | ||
327 | if (data->pdata->cfg_pin) | 339 | if (data->pdata->cfg_pin) |
328 | data->pdata->cfg_pin(true); | 340 | data->pdata->cfg_pin(true); |
@@ -335,16 +347,20 @@ static int mms114_start(struct mms114_data *data) | |||
335 | static void mms114_stop(struct mms114_data *data) | 347 | static void mms114_stop(struct mms114_data *data) |
336 | { | 348 | { |
337 | struct i2c_client *client = data->client; | 349 | struct i2c_client *client = data->client; |
350 | int error; | ||
338 | 351 | ||
339 | disable_irq(client->irq); | 352 | disable_irq(client->irq); |
340 | 353 | ||
341 | if (data->pdata->cfg_pin) | 354 | if (data->pdata->cfg_pin) |
342 | data->pdata->cfg_pin(false); | 355 | data->pdata->cfg_pin(false); |
343 | 356 | ||
344 | if (data->io_reg) | 357 | error = regulator_disable(data->io_reg); |
345 | regulator_disable(data->io_reg); | 358 | if (error) |
346 | if (data->core_reg) | 359 | dev_warn(&client->dev, "Failed to disable vdd: %d\n", error); |
347 | regulator_disable(data->core_reg); | 360 | |
361 | error = regulator_disable(data->core_reg); | ||
362 | if (error) | ||
363 | dev_warn(&client->dev, "Failed to disable avdd: %d\n", error); | ||
348 | } | 364 | } |
349 | 365 | ||
350 | static int mms114_input_open(struct input_dev *dev) | 366 | static int mms114_input_open(struct input_dev *dev) |
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig index 5c514d0711d1..c332fb98480d 100644 --- a/drivers/iommu/Kconfig +++ b/drivers/iommu/Kconfig | |||
@@ -130,7 +130,7 @@ config IRQ_REMAP | |||
130 | # OMAP IOMMU support | 130 | # OMAP IOMMU support |
131 | config OMAP_IOMMU | 131 | config OMAP_IOMMU |
132 | bool "OMAP IOMMU Support" | 132 | bool "OMAP IOMMU Support" |
133 | depends on ARCH_OMAP | 133 | depends on ARCH_OMAP2PLUS |
134 | select IOMMU_API | 134 | select IOMMU_API |
135 | 135 | ||
136 | config OMAP_IOVMM | 136 | config OMAP_IOVMM |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index 98f555dafb55..b287ca33833d 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -2466,18 +2466,16 @@ static int device_change_notifier(struct notifier_block *nb, | |||
2466 | 2466 | ||
2467 | /* allocate a protection domain if a device is added */ | 2467 | /* allocate a protection domain if a device is added */ |
2468 | dma_domain = find_protection_domain(devid); | 2468 | dma_domain = find_protection_domain(devid); |
2469 | if (dma_domain) | 2469 | if (!dma_domain) { |
2470 | goto out; | 2470 | dma_domain = dma_ops_domain_alloc(); |
2471 | dma_domain = dma_ops_domain_alloc(); | 2471 | if (!dma_domain) |
2472 | if (!dma_domain) | 2472 | goto out; |
2473 | goto out; | 2473 | dma_domain->target_dev = devid; |
2474 | dma_domain->target_dev = devid; | 2474 | |
2475 | 2475 | spin_lock_irqsave(&iommu_pd_list_lock, flags); | |
2476 | spin_lock_irqsave(&iommu_pd_list_lock, flags); | 2476 | list_add_tail(&dma_domain->list, &iommu_pd_list); |
2477 | list_add_tail(&dma_domain->list, &iommu_pd_list); | 2477 | spin_unlock_irqrestore(&iommu_pd_list_lock, flags); |
2478 | spin_unlock_irqrestore(&iommu_pd_list_lock, flags); | 2478 | } |
2479 | |||
2480 | dev_data = get_dev_data(dev); | ||
2481 | 2479 | ||
2482 | dev->archdata.dma_ops = &amd_iommu_dma_ops; | 2480 | dev->archdata.dma_ops = &amd_iommu_dma_ops; |
2483 | 2481 | ||
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index b6ecddb63cd0..e3c2d74b7684 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -980,7 +980,7 @@ static void __init free_iommu_all(void) | |||
980 | * BIOS should disable L2B micellaneous clock gating by setting | 980 | * BIOS should disable L2B micellaneous clock gating by setting |
981 | * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b | 981 | * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b |
982 | */ | 982 | */ |
983 | static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) | 983 | static void amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) |
984 | { | 984 | { |
985 | u32 value; | 985 | u32 value; |
986 | 986 | ||
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index dc7e478b7e5f..e5cdaf87822c 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -1083,6 +1083,7 @@ static const char *dma_remap_fault_reasons[] = | |||
1083 | "non-zero reserved fields in RTP", | 1083 | "non-zero reserved fields in RTP", |
1084 | "non-zero reserved fields in CTP", | 1084 | "non-zero reserved fields in CTP", |
1085 | "non-zero reserved fields in PTE", | 1085 | "non-zero reserved fields in PTE", |
1086 | "PCE for translation request specifies blocking", | ||
1086 | }; | 1087 | }; |
1087 | 1088 | ||
1088 | static const char *irq_remap_fault_reasons[] = | 1089 | static const char *irq_remap_fault_reasons[] = |
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index d56f8c17c5fe..7c11ff368d07 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
@@ -2,7 +2,6 @@ | |||
2 | #include <linux/cpumask.h> | 2 | #include <linux/cpumask.h> |
3 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
4 | #include <linux/string.h> | 4 | #include <linux/string.h> |
5 | #include <linux/cpumask.h> | ||
6 | #include <linux/errno.h> | 5 | #include <linux/errno.h> |
7 | #include <linux/msi.h> | 6 | #include <linux/msi.h> |
8 | #include <linux/irq.h> | 7 | #include <linux/irq.h> |
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index a350969e5efe..4a33351c25dc 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig | |||
@@ -25,6 +25,14 @@ config ARM_VIC_NR | |||
25 | The maximum number of VICs available in the system, for | 25 | The maximum number of VICs available in the system, for |
26 | power management. | 26 | power management. |
27 | 27 | ||
28 | config RENESAS_INTC_IRQPIN | ||
29 | bool | ||
30 | select IRQ_DOMAIN | ||
31 | |||
32 | config RENESAS_IRQC | ||
33 | bool | ||
34 | select IRQ_DOMAIN | ||
35 | |||
28 | config VERSATILE_FPGA_IRQ | 36 | config VERSATILE_FPGA_IRQ |
29 | bool | 37 | bool |
30 | select IRQ_DOMAIN | 38 | select IRQ_DOMAIN |
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 4d65a21eb9b8..acf98953272a 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile | |||
@@ -9,4 +9,6 @@ obj-$(CONFIG_ARCH_SUNXI) += irq-sunxi.o | |||
9 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o | 9 | obj-$(CONFIG_ARCH_SPEAR3XX) += spear-shirq.o |
10 | obj-$(CONFIG_ARM_GIC) += irq-gic.o | 10 | obj-$(CONFIG_ARM_GIC) += irq-gic.o |
11 | obj-$(CONFIG_ARM_VIC) += irq-vic.o | 11 | obj-$(CONFIG_ARM_VIC) += irq-vic.o |
12 | obj-$(CONFIG_RENESAS_INTC_IRQPIN) += irq-renesas-intc-irqpin.o | ||
13 | obj-$(CONFIG_RENESAS_IRQC) += irq-renesas-irqc.o | ||
12 | obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o | 14 | obj-$(CONFIG_VERSATILE_FPGA_IRQ) += irq-versatile-fpga.o |
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c index 644d72468423..a32e0d5aa45f 100644 --- a/drivers/irqchip/irq-gic.c +++ b/drivers/irqchip/irq-gic.c | |||
@@ -648,7 +648,7 @@ void gic_raise_softirq(const struct cpumask *mask, unsigned int irq) | |||
648 | 648 | ||
649 | /* Convert our logical CPU mask into a physical one. */ | 649 | /* Convert our logical CPU mask into a physical one. */ |
650 | for_each_cpu(cpu, mask) | 650 | for_each_cpu(cpu, mask) |
651 | map |= 1 << cpu_logical_map(cpu); | 651 | map |= gic_cpu_map[cpu]; |
652 | 652 | ||
653 | /* | 653 | /* |
654 | * Ensure that stores to Normal memory are visible to the | 654 | * Ensure that stores to Normal memory are visible to the |
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c new file mode 100644 index 000000000000..5a68e5accec1 --- /dev/null +++ b/drivers/irqchip/irq-renesas-intc-irqpin.c | |||
@@ -0,0 +1,547 @@ | |||
1 | /* | ||
2 | * Renesas INTC External IRQ Pin Driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Magnus Damm | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/irqdomain.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/platform_data/irq-renesas-intc-irqpin.h> | ||
32 | |||
33 | #define INTC_IRQPIN_MAX 8 /* maximum 8 interrupts per driver instance */ | ||
34 | |||
35 | #define INTC_IRQPIN_REG_SENSE 0 /* ICRn */ | ||
36 | #define INTC_IRQPIN_REG_PRIO 1 /* INTPRInn */ | ||
37 | #define INTC_IRQPIN_REG_SOURCE 2 /* INTREQnn */ | ||
38 | #define INTC_IRQPIN_REG_MASK 3 /* INTMSKnn */ | ||
39 | #define INTC_IRQPIN_REG_CLEAR 4 /* INTMSKCLRnn */ | ||
40 | #define INTC_IRQPIN_REG_NR 5 | ||
41 | |||
42 | /* INTC external IRQ PIN hardware register access: | ||
43 | * | ||
44 | * SENSE is read-write 32-bit with 2-bits or 4-bits per IRQ (*) | ||
45 | * PRIO is read-write 32-bit with 4-bits per IRQ (**) | ||
46 | * SOURCE is read-only 32-bit or 8-bit with 1-bit per IRQ (***) | ||
47 | * MASK is write-only 32-bit or 8-bit with 1-bit per IRQ (***) | ||
48 | * CLEAR is write-only 32-bit or 8-bit with 1-bit per IRQ (***) | ||
49 | * | ||
50 | * (*) May be accessed by more than one driver instance - lock needed | ||
51 | * (**) Read-modify-write access by one driver instance - lock needed | ||
52 | * (***) Accessed by one driver instance only - no locking needed | ||
53 | */ | ||
54 | |||
55 | struct intc_irqpin_iomem { | ||
56 | void __iomem *iomem; | ||
57 | unsigned long (*read)(void __iomem *iomem); | ||
58 | void (*write)(void __iomem *iomem, unsigned long data); | ||
59 | int width; | ||
60 | }; | ||
61 | |||
62 | struct intc_irqpin_irq { | ||
63 | int hw_irq; | ||
64 | int requested_irq; | ||
65 | int domain_irq; | ||
66 | struct intc_irqpin_priv *p; | ||
67 | }; | ||
68 | |||
69 | struct intc_irqpin_priv { | ||
70 | struct intc_irqpin_iomem iomem[INTC_IRQPIN_REG_NR]; | ||
71 | struct intc_irqpin_irq irq[INTC_IRQPIN_MAX]; | ||
72 | struct renesas_intc_irqpin_config config; | ||
73 | unsigned int number_of_irqs; | ||
74 | struct platform_device *pdev; | ||
75 | struct irq_chip irq_chip; | ||
76 | struct irq_domain *irq_domain; | ||
77 | bool shared_irqs; | ||
78 | u8 shared_irq_mask; | ||
79 | }; | ||
80 | |||
81 | static unsigned long intc_irqpin_read32(void __iomem *iomem) | ||
82 | { | ||
83 | return ioread32(iomem); | ||
84 | } | ||
85 | |||
86 | static unsigned long intc_irqpin_read8(void __iomem *iomem) | ||
87 | { | ||
88 | return ioread8(iomem); | ||
89 | } | ||
90 | |||
91 | static void intc_irqpin_write32(void __iomem *iomem, unsigned long data) | ||
92 | { | ||
93 | iowrite32(data, iomem); | ||
94 | } | ||
95 | |||
96 | static void intc_irqpin_write8(void __iomem *iomem, unsigned long data) | ||
97 | { | ||
98 | iowrite8(data, iomem); | ||
99 | } | ||
100 | |||
101 | static inline unsigned long intc_irqpin_read(struct intc_irqpin_priv *p, | ||
102 | int reg) | ||
103 | { | ||
104 | struct intc_irqpin_iomem *i = &p->iomem[reg]; | ||
105 | |||
106 | return i->read(i->iomem); | ||
107 | } | ||
108 | |||
109 | static inline void intc_irqpin_write(struct intc_irqpin_priv *p, | ||
110 | int reg, unsigned long data) | ||
111 | { | ||
112 | struct intc_irqpin_iomem *i = &p->iomem[reg]; | ||
113 | |||
114 | i->write(i->iomem, data); | ||
115 | } | ||
116 | |||
117 | static inline unsigned long intc_irqpin_hwirq_mask(struct intc_irqpin_priv *p, | ||
118 | int reg, int hw_irq) | ||
119 | { | ||
120 | return BIT((p->iomem[reg].width - 1) - hw_irq); | ||
121 | } | ||
122 | |||
123 | static inline void intc_irqpin_irq_write_hwirq(struct intc_irqpin_priv *p, | ||
124 | int reg, int hw_irq) | ||
125 | { | ||
126 | intc_irqpin_write(p, reg, intc_irqpin_hwirq_mask(p, reg, hw_irq)); | ||
127 | } | ||
128 | |||
129 | static DEFINE_RAW_SPINLOCK(intc_irqpin_lock); /* only used by slow path */ | ||
130 | |||
131 | static void intc_irqpin_read_modify_write(struct intc_irqpin_priv *p, | ||
132 | int reg, int shift, | ||
133 | int width, int value) | ||
134 | { | ||
135 | unsigned long flags; | ||
136 | unsigned long tmp; | ||
137 | |||
138 | raw_spin_lock_irqsave(&intc_irqpin_lock, flags); | ||
139 | |||
140 | tmp = intc_irqpin_read(p, reg); | ||
141 | tmp &= ~(((1 << width) - 1) << shift); | ||
142 | tmp |= value << shift; | ||
143 | intc_irqpin_write(p, reg, tmp); | ||
144 | |||
145 | raw_spin_unlock_irqrestore(&intc_irqpin_lock, flags); | ||
146 | } | ||
147 | |||
148 | static void intc_irqpin_mask_unmask_prio(struct intc_irqpin_priv *p, | ||
149 | int irq, int do_mask) | ||
150 | { | ||
151 | int bitfield_width = 4; /* PRIO assumed to have fixed bitfield width */ | ||
152 | int shift = (7 - irq) * bitfield_width; /* PRIO assumed to be 32-bit */ | ||
153 | |||
154 | intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_PRIO, | ||
155 | shift, bitfield_width, | ||
156 | do_mask ? 0 : (1 << bitfield_width) - 1); | ||
157 | } | ||
158 | |||
159 | static int intc_irqpin_set_sense(struct intc_irqpin_priv *p, int irq, int value) | ||
160 | { | ||
161 | int bitfield_width = p->config.sense_bitfield_width; | ||
162 | int shift = (7 - irq) * bitfield_width; /* SENSE assumed to be 32-bit */ | ||
163 | |||
164 | dev_dbg(&p->pdev->dev, "sense irq = %d, mode = %d\n", irq, value); | ||
165 | |||
166 | if (value >= (1 << bitfield_width)) | ||
167 | return -EINVAL; | ||
168 | |||
169 | intc_irqpin_read_modify_write(p, INTC_IRQPIN_REG_SENSE, shift, | ||
170 | bitfield_width, value); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void intc_irqpin_dbg(struct intc_irqpin_irq *i, char *str) | ||
175 | { | ||
176 | dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n", | ||
177 | str, i->requested_irq, i->hw_irq, i->domain_irq); | ||
178 | } | ||
179 | |||
180 | static void intc_irqpin_irq_enable(struct irq_data *d) | ||
181 | { | ||
182 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
183 | int hw_irq = irqd_to_hwirq(d); | ||
184 | |||
185 | intc_irqpin_dbg(&p->irq[hw_irq], "enable"); | ||
186 | intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq); | ||
187 | } | ||
188 | |||
189 | static void intc_irqpin_irq_disable(struct irq_data *d) | ||
190 | { | ||
191 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
192 | int hw_irq = irqd_to_hwirq(d); | ||
193 | |||
194 | intc_irqpin_dbg(&p->irq[hw_irq], "disable"); | ||
195 | intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq); | ||
196 | } | ||
197 | |||
198 | static void intc_irqpin_shared_irq_enable(struct irq_data *d) | ||
199 | { | ||
200 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
201 | int hw_irq = irqd_to_hwirq(d); | ||
202 | |||
203 | intc_irqpin_dbg(&p->irq[hw_irq], "shared enable"); | ||
204 | intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_CLEAR, hw_irq); | ||
205 | |||
206 | p->shared_irq_mask &= ~BIT(hw_irq); | ||
207 | } | ||
208 | |||
209 | static void intc_irqpin_shared_irq_disable(struct irq_data *d) | ||
210 | { | ||
211 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
212 | int hw_irq = irqd_to_hwirq(d); | ||
213 | |||
214 | intc_irqpin_dbg(&p->irq[hw_irq], "shared disable"); | ||
215 | intc_irqpin_irq_write_hwirq(p, INTC_IRQPIN_REG_MASK, hw_irq); | ||
216 | |||
217 | p->shared_irq_mask |= BIT(hw_irq); | ||
218 | } | ||
219 | |||
220 | static void intc_irqpin_irq_enable_force(struct irq_data *d) | ||
221 | { | ||
222 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
223 | int irq = p->irq[irqd_to_hwirq(d)].requested_irq; | ||
224 | |||
225 | intc_irqpin_irq_enable(d); | ||
226 | |||
227 | /* enable interrupt through parent interrupt controller, | ||
228 | * assumes non-shared interrupt with 1:1 mapping | ||
229 | * needed for busted IRQs on some SoCs like sh73a0 | ||
230 | */ | ||
231 | irq_get_chip(irq)->irq_unmask(irq_get_irq_data(irq)); | ||
232 | } | ||
233 | |||
234 | static void intc_irqpin_irq_disable_force(struct irq_data *d) | ||
235 | { | ||
236 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
237 | int irq = p->irq[irqd_to_hwirq(d)].requested_irq; | ||
238 | |||
239 | /* disable interrupt through parent interrupt controller, | ||
240 | * assumes non-shared interrupt with 1:1 mapping | ||
241 | * needed for busted IRQs on some SoCs like sh73a0 | ||
242 | */ | ||
243 | irq_get_chip(irq)->irq_mask(irq_get_irq_data(irq)); | ||
244 | intc_irqpin_irq_disable(d); | ||
245 | } | ||
246 | |||
247 | #define INTC_IRQ_SENSE_VALID 0x10 | ||
248 | #define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID) | ||
249 | |||
250 | static unsigned char intc_irqpin_sense[IRQ_TYPE_SENSE_MASK + 1] = { | ||
251 | [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x00), | ||
252 | [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x01), | ||
253 | [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x02), | ||
254 | [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x03), | ||
255 | [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x04), | ||
256 | }; | ||
257 | |||
258 | static int intc_irqpin_irq_set_type(struct irq_data *d, unsigned int type) | ||
259 | { | ||
260 | unsigned char value = intc_irqpin_sense[type & IRQ_TYPE_SENSE_MASK]; | ||
261 | struct intc_irqpin_priv *p = irq_data_get_irq_chip_data(d); | ||
262 | |||
263 | if (!(value & INTC_IRQ_SENSE_VALID)) | ||
264 | return -EINVAL; | ||
265 | |||
266 | return intc_irqpin_set_sense(p, irqd_to_hwirq(d), | ||
267 | value ^ INTC_IRQ_SENSE_VALID); | ||
268 | } | ||
269 | |||
270 | static irqreturn_t intc_irqpin_irq_handler(int irq, void *dev_id) | ||
271 | { | ||
272 | struct intc_irqpin_irq *i = dev_id; | ||
273 | struct intc_irqpin_priv *p = i->p; | ||
274 | unsigned long bit; | ||
275 | |||
276 | intc_irqpin_dbg(i, "demux1"); | ||
277 | bit = intc_irqpin_hwirq_mask(p, INTC_IRQPIN_REG_SOURCE, i->hw_irq); | ||
278 | |||
279 | if (intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE) & bit) { | ||
280 | intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, ~bit); | ||
281 | intc_irqpin_dbg(i, "demux2"); | ||
282 | generic_handle_irq(i->domain_irq); | ||
283 | return IRQ_HANDLED; | ||
284 | } | ||
285 | return IRQ_NONE; | ||
286 | } | ||
287 | |||
288 | static irqreturn_t intc_irqpin_shared_irq_handler(int irq, void *dev_id) | ||
289 | { | ||
290 | struct intc_irqpin_priv *p = dev_id; | ||
291 | unsigned int reg_source = intc_irqpin_read(p, INTC_IRQPIN_REG_SOURCE); | ||
292 | irqreturn_t status = IRQ_NONE; | ||
293 | int k; | ||
294 | |||
295 | for (k = 0; k < 8; k++) { | ||
296 | if (reg_source & BIT(7 - k)) { | ||
297 | if (BIT(k) & p->shared_irq_mask) | ||
298 | continue; | ||
299 | |||
300 | status |= intc_irqpin_irq_handler(irq, &p->irq[k]); | ||
301 | } | ||
302 | } | ||
303 | |||
304 | return status; | ||
305 | } | ||
306 | |||
307 | static int intc_irqpin_irq_domain_map(struct irq_domain *h, unsigned int virq, | ||
308 | irq_hw_number_t hw) | ||
309 | { | ||
310 | struct intc_irqpin_priv *p = h->host_data; | ||
311 | |||
312 | p->irq[hw].domain_irq = virq; | ||
313 | p->irq[hw].hw_irq = hw; | ||
314 | |||
315 | intc_irqpin_dbg(&p->irq[hw], "map"); | ||
316 | irq_set_chip_data(virq, h->host_data); | ||
317 | irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); | ||
318 | set_irq_flags(virq, IRQF_VALID); /* kill me now */ | ||
319 | return 0; | ||
320 | } | ||
321 | |||
322 | static struct irq_domain_ops intc_irqpin_irq_domain_ops = { | ||
323 | .map = intc_irqpin_irq_domain_map, | ||
324 | .xlate = irq_domain_xlate_twocell, | ||
325 | }; | ||
326 | |||
327 | static int intc_irqpin_probe(struct platform_device *pdev) | ||
328 | { | ||
329 | struct renesas_intc_irqpin_config *pdata = pdev->dev.platform_data; | ||
330 | struct intc_irqpin_priv *p; | ||
331 | struct intc_irqpin_iomem *i; | ||
332 | struct resource *io[INTC_IRQPIN_REG_NR]; | ||
333 | struct resource *irq; | ||
334 | struct irq_chip *irq_chip; | ||
335 | void (*enable_fn)(struct irq_data *d); | ||
336 | void (*disable_fn)(struct irq_data *d); | ||
337 | const char *name = dev_name(&pdev->dev); | ||
338 | int ref_irq; | ||
339 | int ret; | ||
340 | int k; | ||
341 | |||
342 | p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL); | ||
343 | if (!p) { | ||
344 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
345 | ret = -ENOMEM; | ||
346 | goto err0; | ||
347 | } | ||
348 | |||
349 | /* deal with driver instance configuration */ | ||
350 | if (pdata) | ||
351 | memcpy(&p->config, pdata, sizeof(*pdata)); | ||
352 | if (!p->config.sense_bitfield_width) | ||
353 | p->config.sense_bitfield_width = 4; /* default to 4 bits */ | ||
354 | |||
355 | p->pdev = pdev; | ||
356 | platform_set_drvdata(pdev, p); | ||
357 | |||
358 | /* get hold of manadatory IOMEM */ | ||
359 | for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { | ||
360 | io[k] = platform_get_resource(pdev, IORESOURCE_MEM, k); | ||
361 | if (!io[k]) { | ||
362 | dev_err(&pdev->dev, "not enough IOMEM resources\n"); | ||
363 | ret = -EINVAL; | ||
364 | goto err0; | ||
365 | } | ||
366 | } | ||
367 | |||
368 | /* allow any number of IRQs between 1 and INTC_IRQPIN_MAX */ | ||
369 | for (k = 0; k < INTC_IRQPIN_MAX; k++) { | ||
370 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, k); | ||
371 | if (!irq) | ||
372 | break; | ||
373 | |||
374 | p->irq[k].p = p; | ||
375 | p->irq[k].requested_irq = irq->start; | ||
376 | } | ||
377 | |||
378 | p->number_of_irqs = k; | ||
379 | if (p->number_of_irqs < 1) { | ||
380 | dev_err(&pdev->dev, "not enough IRQ resources\n"); | ||
381 | ret = -EINVAL; | ||
382 | goto err0; | ||
383 | } | ||
384 | |||
385 | /* ioremap IOMEM and setup read/write callbacks */ | ||
386 | for (k = 0; k < INTC_IRQPIN_REG_NR; k++) { | ||
387 | i = &p->iomem[k]; | ||
388 | |||
389 | switch (resource_size(io[k])) { | ||
390 | case 1: | ||
391 | i->width = 8; | ||
392 | i->read = intc_irqpin_read8; | ||
393 | i->write = intc_irqpin_write8; | ||
394 | break; | ||
395 | case 4: | ||
396 | i->width = 32; | ||
397 | i->read = intc_irqpin_read32; | ||
398 | i->write = intc_irqpin_write32; | ||
399 | break; | ||
400 | default: | ||
401 | dev_err(&pdev->dev, "IOMEM size mismatch\n"); | ||
402 | ret = -EINVAL; | ||
403 | goto err0; | ||
404 | } | ||
405 | |||
406 | i->iomem = devm_ioremap_nocache(&pdev->dev, io[k]->start, | ||
407 | resource_size(io[k])); | ||
408 | if (!i->iomem) { | ||
409 | dev_err(&pdev->dev, "failed to remap IOMEM\n"); | ||
410 | ret = -ENXIO; | ||
411 | goto err0; | ||
412 | } | ||
413 | } | ||
414 | |||
415 | /* mask all interrupts using priority */ | ||
416 | for (k = 0; k < p->number_of_irqs; k++) | ||
417 | intc_irqpin_mask_unmask_prio(p, k, 1); | ||
418 | |||
419 | /* clear all pending interrupts */ | ||
420 | intc_irqpin_write(p, INTC_IRQPIN_REG_SOURCE, 0x0); | ||
421 | |||
422 | /* scan for shared interrupt lines */ | ||
423 | ref_irq = p->irq[0].requested_irq; | ||
424 | p->shared_irqs = true; | ||
425 | for (k = 1; k < p->number_of_irqs; k++) { | ||
426 | if (ref_irq != p->irq[k].requested_irq) { | ||
427 | p->shared_irqs = false; | ||
428 | break; | ||
429 | } | ||
430 | } | ||
431 | |||
432 | /* use more severe masking method if requested */ | ||
433 | if (p->config.control_parent) { | ||
434 | enable_fn = intc_irqpin_irq_enable_force; | ||
435 | disable_fn = intc_irqpin_irq_disable_force; | ||
436 | } else if (!p->shared_irqs) { | ||
437 | enable_fn = intc_irqpin_irq_enable; | ||
438 | disable_fn = intc_irqpin_irq_disable; | ||
439 | } else { | ||
440 | enable_fn = intc_irqpin_shared_irq_enable; | ||
441 | disable_fn = intc_irqpin_shared_irq_disable; | ||
442 | } | ||
443 | |||
444 | irq_chip = &p->irq_chip; | ||
445 | irq_chip->name = name; | ||
446 | irq_chip->irq_mask = disable_fn; | ||
447 | irq_chip->irq_unmask = enable_fn; | ||
448 | irq_chip->irq_enable = enable_fn; | ||
449 | irq_chip->irq_disable = disable_fn; | ||
450 | irq_chip->irq_set_type = intc_irqpin_irq_set_type; | ||
451 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | ||
452 | |||
453 | p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, | ||
454 | p->number_of_irqs, | ||
455 | p->config.irq_base, | ||
456 | &intc_irqpin_irq_domain_ops, p); | ||
457 | if (!p->irq_domain) { | ||
458 | ret = -ENXIO; | ||
459 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); | ||
460 | goto err0; | ||
461 | } | ||
462 | |||
463 | if (p->shared_irqs) { | ||
464 | /* request one shared interrupt */ | ||
465 | if (devm_request_irq(&pdev->dev, p->irq[0].requested_irq, | ||
466 | intc_irqpin_shared_irq_handler, | ||
467 | IRQF_SHARED, name, p)) { | ||
468 | dev_err(&pdev->dev, "failed to request low IRQ\n"); | ||
469 | ret = -ENOENT; | ||
470 | goto err1; | ||
471 | } | ||
472 | } else { | ||
473 | /* request interrupts one by one */ | ||
474 | for (k = 0; k < p->number_of_irqs; k++) { | ||
475 | if (devm_request_irq(&pdev->dev, | ||
476 | p->irq[k].requested_irq, | ||
477 | intc_irqpin_irq_handler, | ||
478 | 0, name, &p->irq[k])) { | ||
479 | dev_err(&pdev->dev, | ||
480 | "failed to request low IRQ\n"); | ||
481 | ret = -ENOENT; | ||
482 | goto err1; | ||
483 | } | ||
484 | } | ||
485 | } | ||
486 | |||
487 | /* unmask all interrupts on prio level */ | ||
488 | for (k = 0; k < p->number_of_irqs; k++) | ||
489 | intc_irqpin_mask_unmask_prio(p, k, 0); | ||
490 | |||
491 | dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); | ||
492 | |||
493 | /* warn in case of mismatch if irq base is specified */ | ||
494 | if (p->config.irq_base) { | ||
495 | if (p->config.irq_base != p->irq[0].domain_irq) | ||
496 | dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n", | ||
497 | p->config.irq_base, p->irq[0].domain_irq); | ||
498 | } | ||
499 | |||
500 | return 0; | ||
501 | |||
502 | err1: | ||
503 | irq_domain_remove(p->irq_domain); | ||
504 | err0: | ||
505 | return ret; | ||
506 | } | ||
507 | |||
508 | static int intc_irqpin_remove(struct platform_device *pdev) | ||
509 | { | ||
510 | struct intc_irqpin_priv *p = platform_get_drvdata(pdev); | ||
511 | |||
512 | irq_domain_remove(p->irq_domain); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static const struct of_device_id intc_irqpin_dt_ids[] = { | ||
518 | { .compatible = "renesas,intc-irqpin", }, | ||
519 | {}, | ||
520 | }; | ||
521 | MODULE_DEVICE_TABLE(of, intc_irqpin_dt_ids); | ||
522 | |||
523 | static struct platform_driver intc_irqpin_device_driver = { | ||
524 | .probe = intc_irqpin_probe, | ||
525 | .remove = intc_irqpin_remove, | ||
526 | .driver = { | ||
527 | .name = "renesas_intc_irqpin", | ||
528 | .of_match_table = intc_irqpin_dt_ids, | ||
529 | .owner = THIS_MODULE, | ||
530 | } | ||
531 | }; | ||
532 | |||
533 | static int __init intc_irqpin_init(void) | ||
534 | { | ||
535 | return platform_driver_register(&intc_irqpin_device_driver); | ||
536 | } | ||
537 | postcore_initcall(intc_irqpin_init); | ||
538 | |||
539 | static void __exit intc_irqpin_exit(void) | ||
540 | { | ||
541 | platform_driver_unregister(&intc_irqpin_device_driver); | ||
542 | } | ||
543 | module_exit(intc_irqpin_exit); | ||
544 | |||
545 | MODULE_AUTHOR("Magnus Damm"); | ||
546 | MODULE_DESCRIPTION("Renesas INTC External IRQ Pin Driver"); | ||
547 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c new file mode 100644 index 000000000000..927bff373aac --- /dev/null +++ b/drivers/irqchip/irq-renesas-irqc.c | |||
@@ -0,0 +1,307 @@ | |||
1 | /* | ||
2 | * Renesas IRQC Driver | ||
3 | * | ||
4 | * Copyright (C) 2013 Magnus Damm | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
18 | */ | ||
19 | |||
20 | #include <linux/init.h> | ||
21 | #include <linux/platform_device.h> | ||
22 | #include <linux/spinlock.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/io.h> | ||
26 | #include <linux/irq.h> | ||
27 | #include <linux/irqdomain.h> | ||
28 | #include <linux/err.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/module.h> | ||
31 | #include <linux/platform_data/irq-renesas-irqc.h> | ||
32 | |||
33 | #define IRQC_IRQ_MAX 32 /* maximum 32 interrupts per driver instance */ | ||
34 | |||
35 | #define IRQC_REQ_STS 0x00 | ||
36 | #define IRQC_EN_STS 0x04 | ||
37 | #define IRQC_EN_SET 0x08 | ||
38 | #define IRQC_INT_CPU_BASE(n) (0x000 + ((n) * 0x10)) | ||
39 | #define DETECT_STATUS 0x100 | ||
40 | #define IRQC_CONFIG(n) (0x180 + ((n) * 0x04)) | ||
41 | |||
42 | struct irqc_irq { | ||
43 | int hw_irq; | ||
44 | int requested_irq; | ||
45 | int domain_irq; | ||
46 | struct irqc_priv *p; | ||
47 | }; | ||
48 | |||
49 | struct irqc_priv { | ||
50 | void __iomem *iomem; | ||
51 | void __iomem *cpu_int_base; | ||
52 | struct irqc_irq irq[IRQC_IRQ_MAX]; | ||
53 | struct renesas_irqc_config config; | ||
54 | unsigned int number_of_irqs; | ||
55 | struct platform_device *pdev; | ||
56 | struct irq_chip irq_chip; | ||
57 | struct irq_domain *irq_domain; | ||
58 | }; | ||
59 | |||
60 | static void irqc_dbg(struct irqc_irq *i, char *str) | ||
61 | { | ||
62 | dev_dbg(&i->p->pdev->dev, "%s (%d:%d:%d)\n", | ||
63 | str, i->requested_irq, i->hw_irq, i->domain_irq); | ||
64 | } | ||
65 | |||
66 | static void irqc_irq_enable(struct irq_data *d) | ||
67 | { | ||
68 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | ||
69 | int hw_irq = irqd_to_hwirq(d); | ||
70 | |||
71 | irqc_dbg(&p->irq[hw_irq], "enable"); | ||
72 | iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_SET); | ||
73 | } | ||
74 | |||
75 | static void irqc_irq_disable(struct irq_data *d) | ||
76 | { | ||
77 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | ||
78 | int hw_irq = irqd_to_hwirq(d); | ||
79 | |||
80 | irqc_dbg(&p->irq[hw_irq], "disable"); | ||
81 | iowrite32(BIT(hw_irq), p->cpu_int_base + IRQC_EN_STS); | ||
82 | } | ||
83 | |||
84 | #define INTC_IRQ_SENSE_VALID 0x10 | ||
85 | #define INTC_IRQ_SENSE(x) (x + INTC_IRQ_SENSE_VALID) | ||
86 | |||
87 | static unsigned char irqc_sense[IRQ_TYPE_SENSE_MASK + 1] = { | ||
88 | [IRQ_TYPE_LEVEL_LOW] = INTC_IRQ_SENSE(0x01), | ||
89 | [IRQ_TYPE_LEVEL_HIGH] = INTC_IRQ_SENSE(0x02), | ||
90 | [IRQ_TYPE_EDGE_FALLING] = INTC_IRQ_SENSE(0x04), /* Synchronous */ | ||
91 | [IRQ_TYPE_EDGE_RISING] = INTC_IRQ_SENSE(0x08), /* Synchronous */ | ||
92 | [IRQ_TYPE_EDGE_BOTH] = INTC_IRQ_SENSE(0x0c), /* Synchronous */ | ||
93 | }; | ||
94 | |||
95 | static int irqc_irq_set_type(struct irq_data *d, unsigned int type) | ||
96 | { | ||
97 | struct irqc_priv *p = irq_data_get_irq_chip_data(d); | ||
98 | int hw_irq = irqd_to_hwirq(d); | ||
99 | unsigned char value = irqc_sense[type & IRQ_TYPE_SENSE_MASK]; | ||
100 | unsigned long tmp; | ||
101 | |||
102 | irqc_dbg(&p->irq[hw_irq], "sense"); | ||
103 | |||
104 | if (!(value & INTC_IRQ_SENSE_VALID)) | ||
105 | return -EINVAL; | ||
106 | |||
107 | tmp = ioread32(p->iomem + IRQC_CONFIG(hw_irq)); | ||
108 | tmp &= ~0x3f; | ||
109 | tmp |= value ^ INTC_IRQ_SENSE_VALID; | ||
110 | iowrite32(tmp, p->iomem + IRQC_CONFIG(hw_irq)); | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static irqreturn_t irqc_irq_handler(int irq, void *dev_id) | ||
115 | { | ||
116 | struct irqc_irq *i = dev_id; | ||
117 | struct irqc_priv *p = i->p; | ||
118 | unsigned long bit = BIT(i->hw_irq); | ||
119 | |||
120 | irqc_dbg(i, "demux1"); | ||
121 | |||
122 | if (ioread32(p->iomem + DETECT_STATUS) & bit) { | ||
123 | iowrite32(bit, p->iomem + DETECT_STATUS); | ||
124 | irqc_dbg(i, "demux2"); | ||
125 | generic_handle_irq(i->domain_irq); | ||
126 | return IRQ_HANDLED; | ||
127 | } | ||
128 | return IRQ_NONE; | ||
129 | } | ||
130 | |||
131 | static int irqc_irq_domain_map(struct irq_domain *h, unsigned int virq, | ||
132 | irq_hw_number_t hw) | ||
133 | { | ||
134 | struct irqc_priv *p = h->host_data; | ||
135 | |||
136 | p->irq[hw].domain_irq = virq; | ||
137 | p->irq[hw].hw_irq = hw; | ||
138 | |||
139 | irqc_dbg(&p->irq[hw], "map"); | ||
140 | irq_set_chip_data(virq, h->host_data); | ||
141 | irq_set_chip_and_handler(virq, &p->irq_chip, handle_level_irq); | ||
142 | set_irq_flags(virq, IRQF_VALID); /* kill me now */ | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | static struct irq_domain_ops irqc_irq_domain_ops = { | ||
147 | .map = irqc_irq_domain_map, | ||
148 | .xlate = irq_domain_xlate_twocell, | ||
149 | }; | ||
150 | |||
151 | static int irqc_probe(struct platform_device *pdev) | ||
152 | { | ||
153 | struct renesas_irqc_config *pdata = pdev->dev.platform_data; | ||
154 | struct irqc_priv *p; | ||
155 | struct resource *io; | ||
156 | struct resource *irq; | ||
157 | struct irq_chip *irq_chip; | ||
158 | const char *name = dev_name(&pdev->dev); | ||
159 | int ret; | ||
160 | int k; | ||
161 | |||
162 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
163 | if (!p) { | ||
164 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
165 | ret = -ENOMEM; | ||
166 | goto err0; | ||
167 | } | ||
168 | |||
169 | /* deal with driver instance configuration */ | ||
170 | if (pdata) | ||
171 | memcpy(&p->config, pdata, sizeof(*pdata)); | ||
172 | |||
173 | p->pdev = pdev; | ||
174 | platform_set_drvdata(pdev, p); | ||
175 | |||
176 | /* get hold of manadatory IOMEM */ | ||
177 | io = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
178 | if (!io) { | ||
179 | dev_err(&pdev->dev, "not enough IOMEM resources\n"); | ||
180 | ret = -EINVAL; | ||
181 | goto err1; | ||
182 | } | ||
183 | |||
184 | /* allow any number of IRQs between 1 and IRQC_IRQ_MAX */ | ||
185 | for (k = 0; k < IRQC_IRQ_MAX; k++) { | ||
186 | irq = platform_get_resource(pdev, IORESOURCE_IRQ, k); | ||
187 | if (!irq) | ||
188 | break; | ||
189 | |||
190 | p->irq[k].p = p; | ||
191 | p->irq[k].requested_irq = irq->start; | ||
192 | } | ||
193 | |||
194 | p->number_of_irqs = k; | ||
195 | if (p->number_of_irqs < 1) { | ||
196 | dev_err(&pdev->dev, "not enough IRQ resources\n"); | ||
197 | ret = -EINVAL; | ||
198 | goto err1; | ||
199 | } | ||
200 | |||
201 | /* ioremap IOMEM and setup read/write callbacks */ | ||
202 | p->iomem = ioremap_nocache(io->start, resource_size(io)); | ||
203 | if (!p->iomem) { | ||
204 | dev_err(&pdev->dev, "failed to remap IOMEM\n"); | ||
205 | ret = -ENXIO; | ||
206 | goto err2; | ||
207 | } | ||
208 | |||
209 | p->cpu_int_base = p->iomem + IRQC_INT_CPU_BASE(0); /* SYS-SPI */ | ||
210 | |||
211 | irq_chip = &p->irq_chip; | ||
212 | irq_chip->name = name; | ||
213 | irq_chip->irq_mask = irqc_irq_disable; | ||
214 | irq_chip->irq_unmask = irqc_irq_enable; | ||
215 | irq_chip->irq_enable = irqc_irq_enable; | ||
216 | irq_chip->irq_disable = irqc_irq_disable; | ||
217 | irq_chip->irq_set_type = irqc_irq_set_type; | ||
218 | irq_chip->flags = IRQCHIP_SKIP_SET_WAKE; | ||
219 | |||
220 | p->irq_domain = irq_domain_add_simple(pdev->dev.of_node, | ||
221 | p->number_of_irqs, | ||
222 | p->config.irq_base, | ||
223 | &irqc_irq_domain_ops, p); | ||
224 | if (!p->irq_domain) { | ||
225 | ret = -ENXIO; | ||
226 | dev_err(&pdev->dev, "cannot initialize irq domain\n"); | ||
227 | goto err2; | ||
228 | } | ||
229 | |||
230 | /* request interrupts one by one */ | ||
231 | for (k = 0; k < p->number_of_irqs; k++) { | ||
232 | if (request_irq(p->irq[k].requested_irq, irqc_irq_handler, | ||
233 | 0, name, &p->irq[k])) { | ||
234 | dev_err(&pdev->dev, "failed to request IRQ\n"); | ||
235 | ret = -ENOENT; | ||
236 | goto err3; | ||
237 | } | ||
238 | } | ||
239 | |||
240 | dev_info(&pdev->dev, "driving %d irqs\n", p->number_of_irqs); | ||
241 | |||
242 | /* warn in case of mismatch if irq base is specified */ | ||
243 | if (p->config.irq_base) { | ||
244 | if (p->config.irq_base != p->irq[0].domain_irq) | ||
245 | dev_warn(&pdev->dev, "irq base mismatch (%d/%d)\n", | ||
246 | p->config.irq_base, p->irq[0].domain_irq); | ||
247 | } | ||
248 | |||
249 | return 0; | ||
250 | err3: | ||
251 | for (; k >= 0; k--) | ||
252 | free_irq(p->irq[k - 1].requested_irq, &p->irq[k - 1]); | ||
253 | |||
254 | irq_domain_remove(p->irq_domain); | ||
255 | err2: | ||
256 | iounmap(p->iomem); | ||
257 | err1: | ||
258 | kfree(p); | ||
259 | err0: | ||
260 | return ret; | ||
261 | } | ||
262 | |||
263 | static int irqc_remove(struct platform_device *pdev) | ||
264 | { | ||
265 | struct irqc_priv *p = platform_get_drvdata(pdev); | ||
266 | int k; | ||
267 | |||
268 | for (k = 0; k < p->number_of_irqs; k++) | ||
269 | free_irq(p->irq[k].requested_irq, &p->irq[k]); | ||
270 | |||
271 | irq_domain_remove(p->irq_domain); | ||
272 | iounmap(p->iomem); | ||
273 | kfree(p); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | static const struct of_device_id irqc_dt_ids[] = { | ||
278 | { .compatible = "renesas,irqc", }, | ||
279 | {}, | ||
280 | }; | ||
281 | MODULE_DEVICE_TABLE(of, irqc_dt_ids); | ||
282 | |||
283 | static struct platform_driver irqc_device_driver = { | ||
284 | .probe = irqc_probe, | ||
285 | .remove = irqc_remove, | ||
286 | .driver = { | ||
287 | .name = "renesas_irqc", | ||
288 | .of_match_table = irqc_dt_ids, | ||
289 | .owner = THIS_MODULE, | ||
290 | } | ||
291 | }; | ||
292 | |||
293 | static int __init irqc_init(void) | ||
294 | { | ||
295 | return platform_driver_register(&irqc_device_driver); | ||
296 | } | ||
297 | postcore_initcall(irqc_init); | ||
298 | |||
299 | static void __exit irqc_exit(void) | ||
300 | { | ||
301 | platform_driver_unregister(&irqc_device_driver); | ||
302 | } | ||
303 | module_exit(irqc_exit); | ||
304 | |||
305 | MODULE_AUTHOR("Magnus Damm"); | ||
306 | MODULE_DESCRIPTION("Renesas IRQC Driver"); | ||
307 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/isdn/hisax/Kconfig b/drivers/isdn/hisax/Kconfig index 5313c9ea44dc..d9edcc94c2a8 100644 --- a/drivers/isdn/hisax/Kconfig +++ b/drivers/isdn/hisax/Kconfig | |||
@@ -237,7 +237,8 @@ config HISAX_MIC | |||
237 | 237 | ||
238 | config HISAX_NETJET | 238 | config HISAX_NETJET |
239 | bool "NETjet card" | 239 | bool "NETjet card" |
240 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) | 240 | depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) |
241 | depends on VIRT_TO_BUS | ||
241 | help | 242 | help |
242 | This enables HiSax support for the NetJet from Traverse | 243 | This enables HiSax support for the NetJet from Traverse |
243 | Technologies. | 244 | Technologies. |
@@ -248,7 +249,8 @@ config HISAX_NETJET | |||
248 | 249 | ||
249 | config HISAX_NETJET_U | 250 | config HISAX_NETJET_U |
250 | bool "NETspider U card" | 251 | bool "NETspider U card" |
251 | depends on PCI && (BROKEN || !(SPARC || PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) | 252 | depends on PCI && (BROKEN || !(PPC || PARISC || M68K || (MIPS && !CPU_LITTLE_ENDIAN) || FRV || (XTENSA && !CPU_LITTLE_ENDIAN))) |
253 | depends on VIRT_TO_BUS | ||
252 | help | 254 | help |
253 | This enables HiSax support for the Netspider U interface ISDN card | 255 | This enables HiSax support for the Netspider U interface ISDN card |
254 | from Traverse Technologies. | 256 | from Traverse Technologies. |
diff --git a/drivers/isdn/hisax/st5481_usb.c b/drivers/isdn/hisax/st5481_usb.c index 017c67ea3f4c..ead0a4fb7448 100644 --- a/drivers/isdn/hisax/st5481_usb.c +++ b/drivers/isdn/hisax/st5481_usb.c | |||
@@ -294,13 +294,13 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
294 | // Allocate URBs and buffers for interrupt endpoint | 294 | // Allocate URBs and buffers for interrupt endpoint |
295 | urb = usb_alloc_urb(0, GFP_KERNEL); | 295 | urb = usb_alloc_urb(0, GFP_KERNEL); |
296 | if (!urb) { | 296 | if (!urb) { |
297 | return -ENOMEM; | 297 | goto err1; |
298 | } | 298 | } |
299 | intr->urb = urb; | 299 | intr->urb = urb; |
300 | 300 | ||
301 | buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL); | 301 | buf = kmalloc(INT_PKT_SIZE, GFP_KERNEL); |
302 | if (!buf) { | 302 | if (!buf) { |
303 | return -ENOMEM; | 303 | goto err2; |
304 | } | 304 | } |
305 | 305 | ||
306 | endpoint = &altsetting->endpoint[EP_INT-1]; | 306 | endpoint = &altsetting->endpoint[EP_INT-1]; |
@@ -313,6 +313,14 @@ int st5481_setup_usb(struct st5481_adapter *adapter) | |||
313 | endpoint->desc.bInterval); | 313 | endpoint->desc.bInterval); |
314 | 314 | ||
315 | return 0; | 315 | return 0; |
316 | err2: | ||
317 | usb_free_urb(intr->urb); | ||
318 | intr->urb = NULL; | ||
319 | err1: | ||
320 | usb_free_urb(ctrl->urb); | ||
321 | ctrl->urb = NULL; | ||
322 | |||
323 | return -ENOMEM; | ||
316 | } | 324 | } |
317 | 325 | ||
318 | /* | 326 | /* |
diff --git a/drivers/isdn/i4l/isdn_tty.c b/drivers/isdn/i4l/isdn_tty.c index d8a7d8323414..ebaebdf30f98 100644 --- a/drivers/isdn/i4l/isdn_tty.c +++ b/drivers/isdn/i4l/isdn_tty.c | |||
@@ -902,7 +902,9 @@ isdn_tty_send_msg(modem_info *info, atemu *m, char *msg) | |||
902 | int j; | 902 | int j; |
903 | int l; | 903 | int l; |
904 | 904 | ||
905 | l = strlen(msg); | 905 | l = min(strlen(msg), sizeof(cmd.parm) - sizeof(cmd.parm.cmsg) |
906 | + sizeof(cmd.parm.cmsg.para) - 2); | ||
907 | |||
906 | if (!l) { | 908 | if (!l) { |
907 | isdn_tty_modem_result(RESULT_ERROR, info); | 909 | isdn_tty_modem_result(RESULT_ERROR, info); |
908 | return; | 910 | return; |
diff --git a/drivers/mailbox/pl320-ipc.c b/drivers/mailbox/pl320-ipc.c index c45b3aedafba..d873cbae2fbb 100644 --- a/drivers/mailbox/pl320-ipc.c +++ b/drivers/mailbox/pl320-ipc.c | |||
@@ -138,8 +138,7 @@ int pl320_ipc_unregister_notifier(struct notifier_block *nb) | |||
138 | } | 138 | } |
139 | EXPORT_SYMBOL_GPL(pl320_ipc_unregister_notifier); | 139 | EXPORT_SYMBOL_GPL(pl320_ipc_unregister_notifier); |
140 | 140 | ||
141 | static int __init pl320_probe(struct amba_device *adev, | 141 | static int pl320_probe(struct amba_device *adev, const struct amba_id *id) |
142 | const struct amba_id *id) | ||
143 | { | 142 | { |
144 | int ret; | 143 | int ret; |
145 | 144 | ||
diff --git a/drivers/md/Kconfig b/drivers/md/Kconfig index e30b490055aa..4d8d90b4fe78 100644 --- a/drivers/md/Kconfig +++ b/drivers/md/Kconfig | |||
@@ -154,17 +154,6 @@ config MD_RAID456 | |||
154 | 154 | ||
155 | If unsure, say Y. | 155 | If unsure, say Y. |
156 | 156 | ||
157 | config MULTICORE_RAID456 | ||
158 | bool "RAID-4/RAID-5/RAID-6 Multicore processing (EXPERIMENTAL)" | ||
159 | depends on MD_RAID456 | ||
160 | depends on SMP | ||
161 | depends on EXPERIMENTAL | ||
162 | ---help--- | ||
163 | Enable the raid456 module to dispatch per-stripe raid operations to a | ||
164 | thread pool. | ||
165 | |||
166 | If unsure, say N. | ||
167 | |||
168 | config MD_MULTIPATH | 157 | config MD_MULTIPATH |
169 | tristate "Multipath I/O support" | 158 | tristate "Multipath I/O support" |
170 | depends on BLK_DEV_MD | 159 | depends on BLK_DEV_MD |
diff --git a/drivers/md/dm-bufio.c b/drivers/md/dm-bufio.c index 3c955e10a618..c6083132c4b8 100644 --- a/drivers/md/dm-bufio.c +++ b/drivers/md/dm-bufio.c | |||
@@ -1025,6 +1025,8 @@ void dm_bufio_prefetch(struct dm_bufio_client *c, | |||
1025 | { | 1025 | { |
1026 | struct blk_plug plug; | 1026 | struct blk_plug plug; |
1027 | 1027 | ||
1028 | BUG_ON(dm_bufio_in_request()); | ||
1029 | |||
1028 | blk_start_plug(&plug); | 1030 | blk_start_plug(&plug); |
1029 | dm_bufio_lock(c); | 1031 | dm_bufio_lock(c); |
1030 | 1032 | ||
diff --git a/drivers/md/dm-cache-metadata.c b/drivers/md/dm-cache-metadata.c index fbd3625f2748..83e995fece88 100644 --- a/drivers/md/dm-cache-metadata.c +++ b/drivers/md/dm-cache-metadata.c | |||
@@ -83,6 +83,8 @@ struct cache_disk_superblock { | |||
83 | __le32 read_misses; | 83 | __le32 read_misses; |
84 | __le32 write_hits; | 84 | __le32 write_hits; |
85 | __le32 write_misses; | 85 | __le32 write_misses; |
86 | |||
87 | __le32 policy_version[CACHE_POLICY_VERSION_SIZE]; | ||
86 | } __packed; | 88 | } __packed; |
87 | 89 | ||
88 | struct dm_cache_metadata { | 90 | struct dm_cache_metadata { |
@@ -109,6 +111,7 @@ struct dm_cache_metadata { | |||
109 | bool clean_when_opened:1; | 111 | bool clean_when_opened:1; |
110 | 112 | ||
111 | char policy_name[CACHE_POLICY_NAME_SIZE]; | 113 | char policy_name[CACHE_POLICY_NAME_SIZE]; |
114 | unsigned policy_version[CACHE_POLICY_VERSION_SIZE]; | ||
112 | size_t policy_hint_size; | 115 | size_t policy_hint_size; |
113 | struct dm_cache_statistics stats; | 116 | struct dm_cache_statistics stats; |
114 | }; | 117 | }; |
@@ -268,7 +271,8 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd) | |||
268 | memset(disk_super->uuid, 0, sizeof(disk_super->uuid)); | 271 | memset(disk_super->uuid, 0, sizeof(disk_super->uuid)); |
269 | disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC); | 272 | disk_super->magic = cpu_to_le64(CACHE_SUPERBLOCK_MAGIC); |
270 | disk_super->version = cpu_to_le32(CACHE_VERSION); | 273 | disk_super->version = cpu_to_le32(CACHE_VERSION); |
271 | memset(disk_super->policy_name, 0, CACHE_POLICY_NAME_SIZE); | 274 | memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name)); |
275 | memset(disk_super->policy_version, 0, sizeof(disk_super->policy_version)); | ||
272 | disk_super->policy_hint_size = 0; | 276 | disk_super->policy_hint_size = 0; |
273 | 277 | ||
274 | r = dm_sm_copy_root(cmd->metadata_sm, &disk_super->metadata_space_map_root, | 278 | r = dm_sm_copy_root(cmd->metadata_sm, &disk_super->metadata_space_map_root, |
@@ -284,7 +288,6 @@ static int __write_initial_superblock(struct dm_cache_metadata *cmd) | |||
284 | disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); | 288 | disk_super->metadata_block_size = cpu_to_le32(DM_CACHE_METADATA_BLOCK_SIZE >> SECTOR_SHIFT); |
285 | disk_super->data_block_size = cpu_to_le32(cmd->data_block_size); | 289 | disk_super->data_block_size = cpu_to_le32(cmd->data_block_size); |
286 | disk_super->cache_blocks = cpu_to_le32(0); | 290 | disk_super->cache_blocks = cpu_to_le32(0); |
287 | memset(disk_super->policy_name, 0, sizeof(disk_super->policy_name)); | ||
288 | 291 | ||
289 | disk_super->read_hits = cpu_to_le32(0); | 292 | disk_super->read_hits = cpu_to_le32(0); |
290 | disk_super->read_misses = cpu_to_le32(0); | 293 | disk_super->read_misses = cpu_to_le32(0); |
@@ -478,6 +481,9 @@ static void read_superblock_fields(struct dm_cache_metadata *cmd, | |||
478 | cmd->data_block_size = le32_to_cpu(disk_super->data_block_size); | 481 | cmd->data_block_size = le32_to_cpu(disk_super->data_block_size); |
479 | cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks)); | 482 | cmd->cache_blocks = to_cblock(le32_to_cpu(disk_super->cache_blocks)); |
480 | strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name)); | 483 | strncpy(cmd->policy_name, disk_super->policy_name, sizeof(cmd->policy_name)); |
484 | cmd->policy_version[0] = le32_to_cpu(disk_super->policy_version[0]); | ||
485 | cmd->policy_version[1] = le32_to_cpu(disk_super->policy_version[1]); | ||
486 | cmd->policy_version[2] = le32_to_cpu(disk_super->policy_version[2]); | ||
481 | cmd->policy_hint_size = le32_to_cpu(disk_super->policy_hint_size); | 487 | cmd->policy_hint_size = le32_to_cpu(disk_super->policy_hint_size); |
482 | 488 | ||
483 | cmd->stats.read_hits = le32_to_cpu(disk_super->read_hits); | 489 | cmd->stats.read_hits = le32_to_cpu(disk_super->read_hits); |
@@ -572,6 +578,9 @@ static int __commit_transaction(struct dm_cache_metadata *cmd, | |||
572 | disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks)); | 578 | disk_super->discard_nr_blocks = cpu_to_le64(from_dblock(cmd->discard_nr_blocks)); |
573 | disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks)); | 579 | disk_super->cache_blocks = cpu_to_le32(from_cblock(cmd->cache_blocks)); |
574 | strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name)); | 580 | strncpy(disk_super->policy_name, cmd->policy_name, sizeof(disk_super->policy_name)); |
581 | disk_super->policy_version[0] = cpu_to_le32(cmd->policy_version[0]); | ||
582 | disk_super->policy_version[1] = cpu_to_le32(cmd->policy_version[1]); | ||
583 | disk_super->policy_version[2] = cpu_to_le32(cmd->policy_version[2]); | ||
575 | 584 | ||
576 | disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits); | 585 | disk_super->read_hits = cpu_to_le32(cmd->stats.read_hits); |
577 | disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses); | 586 | disk_super->read_misses = cpu_to_le32(cmd->stats.read_misses); |
@@ -854,18 +863,43 @@ struct thunk { | |||
854 | bool hints_valid; | 863 | bool hints_valid; |
855 | }; | 864 | }; |
856 | 865 | ||
866 | static bool policy_unchanged(struct dm_cache_metadata *cmd, | ||
867 | struct dm_cache_policy *policy) | ||
868 | { | ||
869 | const char *policy_name = dm_cache_policy_get_name(policy); | ||
870 | const unsigned *policy_version = dm_cache_policy_get_version(policy); | ||
871 | size_t policy_hint_size = dm_cache_policy_get_hint_size(policy); | ||
872 | |||
873 | /* | ||
874 | * Ensure policy names match. | ||
875 | */ | ||
876 | if (strncmp(cmd->policy_name, policy_name, sizeof(cmd->policy_name))) | ||
877 | return false; | ||
878 | |||
879 | /* | ||
880 | * Ensure policy major versions match. | ||
881 | */ | ||
882 | if (cmd->policy_version[0] != policy_version[0]) | ||
883 | return false; | ||
884 | |||
885 | /* | ||
886 | * Ensure policy hint sizes match. | ||
887 | */ | ||
888 | if (cmd->policy_hint_size != policy_hint_size) | ||
889 | return false; | ||
890 | |||
891 | return true; | ||
892 | } | ||
893 | |||
857 | static bool hints_array_initialized(struct dm_cache_metadata *cmd) | 894 | static bool hints_array_initialized(struct dm_cache_metadata *cmd) |
858 | { | 895 | { |
859 | return cmd->hint_root && cmd->policy_hint_size; | 896 | return cmd->hint_root && cmd->policy_hint_size; |
860 | } | 897 | } |
861 | 898 | ||
862 | static bool hints_array_available(struct dm_cache_metadata *cmd, | 899 | static bool hints_array_available(struct dm_cache_metadata *cmd, |
863 | const char *policy_name) | 900 | struct dm_cache_policy *policy) |
864 | { | 901 | { |
865 | bool policy_names_match = !strncmp(cmd->policy_name, policy_name, | 902 | return cmd->clean_when_opened && policy_unchanged(cmd, policy) && |
866 | sizeof(cmd->policy_name)); | ||
867 | |||
868 | return cmd->clean_when_opened && policy_names_match && | ||
869 | hints_array_initialized(cmd); | 903 | hints_array_initialized(cmd); |
870 | } | 904 | } |
871 | 905 | ||
@@ -899,7 +933,8 @@ static int __load_mapping(void *context, uint64_t cblock, void *leaf) | |||
899 | return r; | 933 | return r; |
900 | } | 934 | } |
901 | 935 | ||
902 | static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_name, | 936 | static int __load_mappings(struct dm_cache_metadata *cmd, |
937 | struct dm_cache_policy *policy, | ||
903 | load_mapping_fn fn, void *context) | 938 | load_mapping_fn fn, void *context) |
904 | { | 939 | { |
905 | struct thunk thunk; | 940 | struct thunk thunk; |
@@ -909,18 +944,19 @@ static int __load_mappings(struct dm_cache_metadata *cmd, const char *policy_nam | |||
909 | 944 | ||
910 | thunk.cmd = cmd; | 945 | thunk.cmd = cmd; |
911 | thunk.respect_dirty_flags = cmd->clean_when_opened; | 946 | thunk.respect_dirty_flags = cmd->clean_when_opened; |
912 | thunk.hints_valid = hints_array_available(cmd, policy_name); | 947 | thunk.hints_valid = hints_array_available(cmd, policy); |
913 | 948 | ||
914 | return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk); | 949 | return dm_array_walk(&cmd->info, cmd->root, __load_mapping, &thunk); |
915 | } | 950 | } |
916 | 951 | ||
917 | int dm_cache_load_mappings(struct dm_cache_metadata *cmd, const char *policy_name, | 952 | int dm_cache_load_mappings(struct dm_cache_metadata *cmd, |
953 | struct dm_cache_policy *policy, | ||
918 | load_mapping_fn fn, void *context) | 954 | load_mapping_fn fn, void *context) |
919 | { | 955 | { |
920 | int r; | 956 | int r; |
921 | 957 | ||
922 | down_read(&cmd->root_lock); | 958 | down_read(&cmd->root_lock); |
923 | r = __load_mappings(cmd, policy_name, fn, context); | 959 | r = __load_mappings(cmd, policy, fn, context); |
924 | up_read(&cmd->root_lock); | 960 | up_read(&cmd->root_lock); |
925 | 961 | ||
926 | return r; | 962 | return r; |
@@ -979,7 +1015,7 @@ static int __dirty(struct dm_cache_metadata *cmd, dm_cblock_t cblock, bool dirty | |||
979 | /* nothing to be done */ | 1015 | /* nothing to be done */ |
980 | return 0; | 1016 | return 0; |
981 | 1017 | ||
982 | value = pack_value(oblock, flags | (dirty ? M_DIRTY : 0)); | 1018 | value = pack_value(oblock, (flags & ~M_DIRTY) | (dirty ? M_DIRTY : 0)); |
983 | __dm_bless_for_disk(&value); | 1019 | __dm_bless_for_disk(&value); |
984 | 1020 | ||
985 | r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock), | 1021 | r = dm_array_set_value(&cmd->info, cmd->root, from_cblock(cblock), |
@@ -1070,13 +1106,15 @@ static int begin_hints(struct dm_cache_metadata *cmd, struct dm_cache_policy *po | |||
1070 | __le32 value; | 1106 | __le32 value; |
1071 | size_t hint_size; | 1107 | size_t hint_size; |
1072 | const char *policy_name = dm_cache_policy_get_name(policy); | 1108 | const char *policy_name = dm_cache_policy_get_name(policy); |
1109 | const unsigned *policy_version = dm_cache_policy_get_version(policy); | ||
1073 | 1110 | ||
1074 | if (!policy_name[0] || | 1111 | if (!policy_name[0] || |
1075 | (strlen(policy_name) > sizeof(cmd->policy_name) - 1)) | 1112 | (strlen(policy_name) > sizeof(cmd->policy_name) - 1)) |
1076 | return -EINVAL; | 1113 | return -EINVAL; |
1077 | 1114 | ||
1078 | if (strcmp(cmd->policy_name, policy_name)) { | 1115 | if (!policy_unchanged(cmd, policy)) { |
1079 | strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name)); | 1116 | strncpy(cmd->policy_name, policy_name, sizeof(cmd->policy_name)); |
1117 | memcpy(cmd->policy_version, policy_version, sizeof(cmd->policy_version)); | ||
1080 | 1118 | ||
1081 | hint_size = dm_cache_policy_get_hint_size(policy); | 1119 | hint_size = dm_cache_policy_get_hint_size(policy); |
1082 | if (!hint_size) | 1120 | if (!hint_size) |
diff --git a/drivers/md/dm-cache-metadata.h b/drivers/md/dm-cache-metadata.h index 135864ea0eee..f45cef21f3d0 100644 --- a/drivers/md/dm-cache-metadata.h +++ b/drivers/md/dm-cache-metadata.h | |||
@@ -89,7 +89,7 @@ typedef int (*load_mapping_fn)(void *context, dm_oblock_t oblock, | |||
89 | dm_cblock_t cblock, bool dirty, | 89 | dm_cblock_t cblock, bool dirty, |
90 | uint32_t hint, bool hint_valid); | 90 | uint32_t hint, bool hint_valid); |
91 | int dm_cache_load_mappings(struct dm_cache_metadata *cmd, | 91 | int dm_cache_load_mappings(struct dm_cache_metadata *cmd, |
92 | const char *policy_name, | 92 | struct dm_cache_policy *policy, |
93 | load_mapping_fn fn, | 93 | load_mapping_fn fn, |
94 | void *context); | 94 | void *context); |
95 | 95 | ||
diff --git a/drivers/md/dm-cache-policy-cleaner.c b/drivers/md/dm-cache-policy-cleaner.c index cc05d70b3cb8..b04d1f904d07 100644 --- a/drivers/md/dm-cache-policy-cleaner.c +++ b/drivers/md/dm-cache-policy-cleaner.c | |||
@@ -17,7 +17,6 @@ | |||
17 | /*----------------------------------------------------------------*/ | 17 | /*----------------------------------------------------------------*/ |
18 | 18 | ||
19 | #define DM_MSG_PREFIX "cache cleaner" | 19 | #define DM_MSG_PREFIX "cache cleaner" |
20 | #define CLEANER_VERSION "1.0.0" | ||
21 | 20 | ||
22 | /* Cache entry struct. */ | 21 | /* Cache entry struct. */ |
23 | struct wb_cache_entry { | 22 | struct wb_cache_entry { |
@@ -434,6 +433,7 @@ static struct dm_cache_policy *wb_create(dm_cblock_t cache_size, | |||
434 | 433 | ||
435 | static struct dm_cache_policy_type wb_policy_type = { | 434 | static struct dm_cache_policy_type wb_policy_type = { |
436 | .name = "cleaner", | 435 | .name = "cleaner", |
436 | .version = {1, 0, 0}, | ||
437 | .hint_size = 0, | 437 | .hint_size = 0, |
438 | .owner = THIS_MODULE, | 438 | .owner = THIS_MODULE, |
439 | .create = wb_create | 439 | .create = wb_create |
@@ -446,7 +446,10 @@ static int __init wb_init(void) | |||
446 | if (r < 0) | 446 | if (r < 0) |
447 | DMERR("register failed %d", r); | 447 | DMERR("register failed %d", r); |
448 | else | 448 | else |
449 | DMINFO("version " CLEANER_VERSION " loaded"); | 449 | DMINFO("version %u.%u.%u loaded", |
450 | wb_policy_type.version[0], | ||
451 | wb_policy_type.version[1], | ||
452 | wb_policy_type.version[2]); | ||
450 | 453 | ||
451 | return r; | 454 | return r; |
452 | } | 455 | } |
diff --git a/drivers/md/dm-cache-policy-internal.h b/drivers/md/dm-cache-policy-internal.h index 52a75beeced5..0928abdc49f0 100644 --- a/drivers/md/dm-cache-policy-internal.h +++ b/drivers/md/dm-cache-policy-internal.h | |||
@@ -117,6 +117,8 @@ void dm_cache_policy_destroy(struct dm_cache_policy *p); | |||
117 | */ | 117 | */ |
118 | const char *dm_cache_policy_get_name(struct dm_cache_policy *p); | 118 | const char *dm_cache_policy_get_name(struct dm_cache_policy *p); |
119 | 119 | ||
120 | const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p); | ||
121 | |||
120 | size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p); | 122 | size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p); |
121 | 123 | ||
122 | /*----------------------------------------------------------------*/ | 124 | /*----------------------------------------------------------------*/ |
diff --git a/drivers/md/dm-cache-policy-mq.c b/drivers/md/dm-cache-policy-mq.c index 964153255076..dc112a7137fe 100644 --- a/drivers/md/dm-cache-policy-mq.c +++ b/drivers/md/dm-cache-policy-mq.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/vmalloc.h> | 14 | #include <linux/vmalloc.h> |
15 | 15 | ||
16 | #define DM_MSG_PREFIX "cache-policy-mq" | 16 | #define DM_MSG_PREFIX "cache-policy-mq" |
17 | #define MQ_VERSION "1.0.0" | ||
18 | 17 | ||
19 | static struct kmem_cache *mq_entry_cache; | 18 | static struct kmem_cache *mq_entry_cache; |
20 | 19 | ||
@@ -1133,6 +1132,7 @@ bad_cache_alloc: | |||
1133 | 1132 | ||
1134 | static struct dm_cache_policy_type mq_policy_type = { | 1133 | static struct dm_cache_policy_type mq_policy_type = { |
1135 | .name = "mq", | 1134 | .name = "mq", |
1135 | .version = {1, 0, 0}, | ||
1136 | .hint_size = 4, | 1136 | .hint_size = 4, |
1137 | .owner = THIS_MODULE, | 1137 | .owner = THIS_MODULE, |
1138 | .create = mq_create | 1138 | .create = mq_create |
@@ -1140,6 +1140,7 @@ static struct dm_cache_policy_type mq_policy_type = { | |||
1140 | 1140 | ||
1141 | static struct dm_cache_policy_type default_policy_type = { | 1141 | static struct dm_cache_policy_type default_policy_type = { |
1142 | .name = "default", | 1142 | .name = "default", |
1143 | .version = {1, 0, 0}, | ||
1143 | .hint_size = 4, | 1144 | .hint_size = 4, |
1144 | .owner = THIS_MODULE, | 1145 | .owner = THIS_MODULE, |
1145 | .create = mq_create | 1146 | .create = mq_create |
@@ -1164,7 +1165,10 @@ static int __init mq_init(void) | |||
1164 | 1165 | ||
1165 | r = dm_cache_policy_register(&default_policy_type); | 1166 | r = dm_cache_policy_register(&default_policy_type); |
1166 | if (!r) { | 1167 | if (!r) { |
1167 | DMINFO("version " MQ_VERSION " loaded"); | 1168 | DMINFO("version %u.%u.%u loaded", |
1169 | mq_policy_type.version[0], | ||
1170 | mq_policy_type.version[1], | ||
1171 | mq_policy_type.version[2]); | ||
1168 | return 0; | 1172 | return 0; |
1169 | } | 1173 | } |
1170 | 1174 | ||
diff --git a/drivers/md/dm-cache-policy.c b/drivers/md/dm-cache-policy.c index 2cbf5fdaac52..21c03c570c06 100644 --- a/drivers/md/dm-cache-policy.c +++ b/drivers/md/dm-cache-policy.c | |||
@@ -150,6 +150,14 @@ const char *dm_cache_policy_get_name(struct dm_cache_policy *p) | |||
150 | } | 150 | } |
151 | EXPORT_SYMBOL_GPL(dm_cache_policy_get_name); | 151 | EXPORT_SYMBOL_GPL(dm_cache_policy_get_name); |
152 | 152 | ||
153 | const unsigned *dm_cache_policy_get_version(struct dm_cache_policy *p) | ||
154 | { | ||
155 | struct dm_cache_policy_type *t = p->private; | ||
156 | |||
157 | return t->version; | ||
158 | } | ||
159 | EXPORT_SYMBOL_GPL(dm_cache_policy_get_version); | ||
160 | |||
153 | size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p) | 161 | size_t dm_cache_policy_get_hint_size(struct dm_cache_policy *p) |
154 | { | 162 | { |
155 | struct dm_cache_policy_type *t = p->private; | 163 | struct dm_cache_policy_type *t = p->private; |
diff --git a/drivers/md/dm-cache-policy.h b/drivers/md/dm-cache-policy.h index f0f51b260544..558bdfdabf5f 100644 --- a/drivers/md/dm-cache-policy.h +++ b/drivers/md/dm-cache-policy.h | |||
@@ -196,6 +196,7 @@ struct dm_cache_policy { | |||
196 | * We maintain a little register of the different policy types. | 196 | * We maintain a little register of the different policy types. |
197 | */ | 197 | */ |
198 | #define CACHE_POLICY_NAME_SIZE 16 | 198 | #define CACHE_POLICY_NAME_SIZE 16 |
199 | #define CACHE_POLICY_VERSION_SIZE 3 | ||
199 | 200 | ||
200 | struct dm_cache_policy_type { | 201 | struct dm_cache_policy_type { |
201 | /* For use by the register code only. */ | 202 | /* For use by the register code only. */ |
@@ -206,6 +207,7 @@ struct dm_cache_policy_type { | |||
206 | * what gets passed on the target line to select your policy. | 207 | * what gets passed on the target line to select your policy. |
207 | */ | 208 | */ |
208 | char name[CACHE_POLICY_NAME_SIZE]; | 209 | char name[CACHE_POLICY_NAME_SIZE]; |
210 | unsigned version[CACHE_POLICY_VERSION_SIZE]; | ||
209 | 211 | ||
210 | /* | 212 | /* |
211 | * Policies may store a hint for each each cache block. | 213 | * Policies may store a hint for each each cache block. |
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c index 0f4e84b15c30..66120bd46d15 100644 --- a/drivers/md/dm-cache-target.c +++ b/drivers/md/dm-cache-target.c | |||
@@ -142,6 +142,7 @@ struct cache { | |||
142 | spinlock_t lock; | 142 | spinlock_t lock; |
143 | struct bio_list deferred_bios; | 143 | struct bio_list deferred_bios; |
144 | struct bio_list deferred_flush_bios; | 144 | struct bio_list deferred_flush_bios; |
145 | struct bio_list deferred_writethrough_bios; | ||
145 | struct list_head quiesced_migrations; | 146 | struct list_head quiesced_migrations; |
146 | struct list_head completed_migrations; | 147 | struct list_head completed_migrations; |
147 | struct list_head need_commit_migrations; | 148 | struct list_head need_commit_migrations; |
@@ -158,7 +159,7 @@ struct cache { | |||
158 | /* | 159 | /* |
159 | * origin_blocks entries, discarded if set. | 160 | * origin_blocks entries, discarded if set. |
160 | */ | 161 | */ |
161 | sector_t discard_block_size; /* a power of 2 times sectors per block */ | 162 | uint32_t discard_block_size; /* a power of 2 times sectors per block */ |
162 | dm_dblock_t discard_nr_blocks; | 163 | dm_dblock_t discard_nr_blocks; |
163 | unsigned long *discard_bitset; | 164 | unsigned long *discard_bitset; |
164 | 165 | ||
@@ -199,6 +200,11 @@ struct per_bio_data { | |||
199 | bool tick:1; | 200 | bool tick:1; |
200 | unsigned req_nr:2; | 201 | unsigned req_nr:2; |
201 | struct dm_deferred_entry *all_io_entry; | 202 | struct dm_deferred_entry *all_io_entry; |
203 | |||
204 | /* writethrough fields */ | ||
205 | struct cache *cache; | ||
206 | dm_cblock_t cblock; | ||
207 | bio_end_io_t *saved_bi_end_io; | ||
202 | }; | 208 | }; |
203 | 209 | ||
204 | struct dm_cache_migration { | 210 | struct dm_cache_migration { |
@@ -412,17 +418,24 @@ static bool block_size_is_power_of_two(struct cache *cache) | |||
412 | return cache->sectors_per_block_shift >= 0; | 418 | return cache->sectors_per_block_shift >= 0; |
413 | } | 419 | } |
414 | 420 | ||
421 | static dm_block_t block_div(dm_block_t b, uint32_t n) | ||
422 | { | ||
423 | do_div(b, n); | ||
424 | |||
425 | return b; | ||
426 | } | ||
427 | |||
415 | static dm_dblock_t oblock_to_dblock(struct cache *cache, dm_oblock_t oblock) | 428 | static dm_dblock_t oblock_to_dblock(struct cache *cache, dm_oblock_t oblock) |
416 | { | 429 | { |
417 | sector_t discard_blocks = cache->discard_block_size; | 430 | uint32_t discard_blocks = cache->discard_block_size; |
418 | dm_block_t b = from_oblock(oblock); | 431 | dm_block_t b = from_oblock(oblock); |
419 | 432 | ||
420 | if (!block_size_is_power_of_two(cache)) | 433 | if (!block_size_is_power_of_two(cache)) |
421 | (void) sector_div(discard_blocks, cache->sectors_per_block); | 434 | discard_blocks = discard_blocks / cache->sectors_per_block; |
422 | else | 435 | else |
423 | discard_blocks >>= cache->sectors_per_block_shift; | 436 | discard_blocks >>= cache->sectors_per_block_shift; |
424 | 437 | ||
425 | (void) sector_div(b, discard_blocks); | 438 | b = block_div(b, discard_blocks); |
426 | 439 | ||
427 | return to_dblock(b); | 440 | return to_dblock(b); |
428 | } | 441 | } |
@@ -609,6 +622,56 @@ static void issue(struct cache *cache, struct bio *bio) | |||
609 | spin_unlock_irqrestore(&cache->lock, flags); | 622 | spin_unlock_irqrestore(&cache->lock, flags); |
610 | } | 623 | } |
611 | 624 | ||
625 | static void defer_writethrough_bio(struct cache *cache, struct bio *bio) | ||
626 | { | ||
627 | unsigned long flags; | ||
628 | |||
629 | spin_lock_irqsave(&cache->lock, flags); | ||
630 | bio_list_add(&cache->deferred_writethrough_bios, bio); | ||
631 | spin_unlock_irqrestore(&cache->lock, flags); | ||
632 | |||
633 | wake_worker(cache); | ||
634 | } | ||
635 | |||
636 | static void writethrough_endio(struct bio *bio, int err) | ||
637 | { | ||
638 | struct per_bio_data *pb = get_per_bio_data(bio); | ||
639 | bio->bi_end_io = pb->saved_bi_end_io; | ||
640 | |||
641 | if (err) { | ||
642 | bio_endio(bio, err); | ||
643 | return; | ||
644 | } | ||
645 | |||
646 | remap_to_cache(pb->cache, bio, pb->cblock); | ||
647 | |||
648 | /* | ||
649 | * We can't issue this bio directly, since we're in interrupt | ||
650 | * context. So it get's put on a bio list for processing by the | ||
651 | * worker thread. | ||
652 | */ | ||
653 | defer_writethrough_bio(pb->cache, bio); | ||
654 | } | ||
655 | |||
656 | /* | ||
657 | * When running in writethrough mode we need to send writes to clean blocks | ||
658 | * to both the cache and origin devices. In future we'd like to clone the | ||
659 | * bio and send them in parallel, but for now we're doing them in | ||
660 | * series as this is easier. | ||
661 | */ | ||
662 | static void remap_to_origin_then_cache(struct cache *cache, struct bio *bio, | ||
663 | dm_oblock_t oblock, dm_cblock_t cblock) | ||
664 | { | ||
665 | struct per_bio_data *pb = get_per_bio_data(bio); | ||
666 | |||
667 | pb->cache = cache; | ||
668 | pb->cblock = cblock; | ||
669 | pb->saved_bi_end_io = bio->bi_end_io; | ||
670 | bio->bi_end_io = writethrough_endio; | ||
671 | |||
672 | remap_to_origin_clear_discard(pb->cache, bio, oblock); | ||
673 | } | ||
674 | |||
612 | /*---------------------------------------------------------------- | 675 | /*---------------------------------------------------------------- |
613 | * Migration processing | 676 | * Migration processing |
614 | * | 677 | * |
@@ -1002,7 +1065,7 @@ static void process_discard_bio(struct cache *cache, struct bio *bio) | |||
1002 | dm_block_t end_block = bio->bi_sector + bio_sectors(bio); | 1065 | dm_block_t end_block = bio->bi_sector + bio_sectors(bio); |
1003 | dm_block_t b; | 1066 | dm_block_t b; |
1004 | 1067 | ||
1005 | (void) sector_div(end_block, cache->discard_block_size); | 1068 | end_block = block_div(end_block, cache->discard_block_size); |
1006 | 1069 | ||
1007 | for (b = start_block; b < end_block; b++) | 1070 | for (b = start_block; b < end_block; b++) |
1008 | set_discard(cache, to_dblock(b)); | 1071 | set_discard(cache, to_dblock(b)); |
@@ -1070,14 +1133,9 @@ static void process_bio(struct cache *cache, struct prealloc *structs, | |||
1070 | inc_hit_counter(cache, bio); | 1133 | inc_hit_counter(cache, bio); |
1071 | pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds); | 1134 | pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds); |
1072 | 1135 | ||
1073 | if (is_writethrough_io(cache, bio, lookup_result.cblock)) { | 1136 | if (is_writethrough_io(cache, bio, lookup_result.cblock)) |
1074 | /* | 1137 | remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock); |
1075 | * No need to mark anything dirty in write through mode. | 1138 | else |
1076 | */ | ||
1077 | pb->req_nr == 0 ? | ||
1078 | remap_to_cache(cache, bio, lookup_result.cblock) : | ||
1079 | remap_to_origin_clear_discard(cache, bio, block); | ||
1080 | } else | ||
1081 | remap_to_cache_dirty(cache, bio, block, lookup_result.cblock); | 1139 | remap_to_cache_dirty(cache, bio, block, lookup_result.cblock); |
1082 | 1140 | ||
1083 | issue(cache, bio); | 1141 | issue(cache, bio); |
@@ -1086,17 +1144,8 @@ static void process_bio(struct cache *cache, struct prealloc *structs, | |||
1086 | case POLICY_MISS: | 1144 | case POLICY_MISS: |
1087 | inc_miss_counter(cache, bio); | 1145 | inc_miss_counter(cache, bio); |
1088 | pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds); | 1146 | pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds); |
1089 | 1147 | remap_to_origin_clear_discard(cache, bio, block); | |
1090 | if (pb->req_nr != 0) { | 1148 | issue(cache, bio); |
1091 | /* | ||
1092 | * This is a duplicate writethrough io that is no | ||
1093 | * longer needed because the block has been demoted. | ||
1094 | */ | ||
1095 | bio_endio(bio, 0); | ||
1096 | } else { | ||
1097 | remap_to_origin_clear_discard(cache, bio, block); | ||
1098 | issue(cache, bio); | ||
1099 | } | ||
1100 | break; | 1149 | break; |
1101 | 1150 | ||
1102 | case POLICY_NEW: | 1151 | case POLICY_NEW: |
@@ -1217,6 +1266,23 @@ static void process_deferred_flush_bios(struct cache *cache, bool submit_bios) | |||
1217 | submit_bios ? generic_make_request(bio) : bio_io_error(bio); | 1266 | submit_bios ? generic_make_request(bio) : bio_io_error(bio); |
1218 | } | 1267 | } |
1219 | 1268 | ||
1269 | static void process_deferred_writethrough_bios(struct cache *cache) | ||
1270 | { | ||
1271 | unsigned long flags; | ||
1272 | struct bio_list bios; | ||
1273 | struct bio *bio; | ||
1274 | |||
1275 | bio_list_init(&bios); | ||
1276 | |||
1277 | spin_lock_irqsave(&cache->lock, flags); | ||
1278 | bio_list_merge(&bios, &cache->deferred_writethrough_bios); | ||
1279 | bio_list_init(&cache->deferred_writethrough_bios); | ||
1280 | spin_unlock_irqrestore(&cache->lock, flags); | ||
1281 | |||
1282 | while ((bio = bio_list_pop(&bios))) | ||
1283 | generic_make_request(bio); | ||
1284 | } | ||
1285 | |||
1220 | static void writeback_some_dirty_blocks(struct cache *cache) | 1286 | static void writeback_some_dirty_blocks(struct cache *cache) |
1221 | { | 1287 | { |
1222 | int r = 0; | 1288 | int r = 0; |
@@ -1313,6 +1379,7 @@ static int more_work(struct cache *cache) | |||
1313 | else | 1379 | else |
1314 | return !bio_list_empty(&cache->deferred_bios) || | 1380 | return !bio_list_empty(&cache->deferred_bios) || |
1315 | !bio_list_empty(&cache->deferred_flush_bios) || | 1381 | !bio_list_empty(&cache->deferred_flush_bios) || |
1382 | !bio_list_empty(&cache->deferred_writethrough_bios) || | ||
1316 | !list_empty(&cache->quiesced_migrations) || | 1383 | !list_empty(&cache->quiesced_migrations) || |
1317 | !list_empty(&cache->completed_migrations) || | 1384 | !list_empty(&cache->completed_migrations) || |
1318 | !list_empty(&cache->need_commit_migrations); | 1385 | !list_empty(&cache->need_commit_migrations); |
@@ -1331,6 +1398,8 @@ static void do_worker(struct work_struct *ws) | |||
1331 | 1398 | ||
1332 | writeback_some_dirty_blocks(cache); | 1399 | writeback_some_dirty_blocks(cache); |
1333 | 1400 | ||
1401 | process_deferred_writethrough_bios(cache); | ||
1402 | |||
1334 | if (commit_if_needed(cache)) { | 1403 | if (commit_if_needed(cache)) { |
1335 | process_deferred_flush_bios(cache, false); | 1404 | process_deferred_flush_bios(cache, false); |
1336 | 1405 | ||
@@ -1756,8 +1825,11 @@ static int create_cache_policy(struct cache *cache, struct cache_args *ca, | |||
1756 | } | 1825 | } |
1757 | 1826 | ||
1758 | r = set_config_values(cache->policy, ca->policy_argc, ca->policy_argv); | 1827 | r = set_config_values(cache->policy, ca->policy_argc, ca->policy_argv); |
1759 | if (r) | 1828 | if (r) { |
1829 | *error = "Error setting cache policy's config values"; | ||
1760 | dm_cache_policy_destroy(cache->policy); | 1830 | dm_cache_policy_destroy(cache->policy); |
1831 | cache->policy = NULL; | ||
1832 | } | ||
1761 | 1833 | ||
1762 | return r; | 1834 | return r; |
1763 | } | 1835 | } |
@@ -1793,8 +1865,6 @@ static sector_t calculate_discard_block_size(sector_t cache_block_size, | |||
1793 | 1865 | ||
1794 | #define DEFAULT_MIGRATION_THRESHOLD (2048 * 100) | 1866 | #define DEFAULT_MIGRATION_THRESHOLD (2048 * 100) |
1795 | 1867 | ||
1796 | static unsigned cache_num_write_bios(struct dm_target *ti, struct bio *bio); | ||
1797 | |||
1798 | static int cache_create(struct cache_args *ca, struct cache **result) | 1868 | static int cache_create(struct cache_args *ca, struct cache **result) |
1799 | { | 1869 | { |
1800 | int r = 0; | 1870 | int r = 0; |
@@ -1821,9 +1891,6 @@ static int cache_create(struct cache_args *ca, struct cache **result) | |||
1821 | 1891 | ||
1822 | memcpy(&cache->features, &ca->features, sizeof(cache->features)); | 1892 | memcpy(&cache->features, &ca->features, sizeof(cache->features)); |
1823 | 1893 | ||
1824 | if (cache->features.write_through) | ||
1825 | ti->num_write_bios = cache_num_write_bios; | ||
1826 | |||
1827 | cache->callbacks.congested_fn = cache_is_congested; | 1894 | cache->callbacks.congested_fn = cache_is_congested; |
1828 | dm_table_add_target_callbacks(ti->table, &cache->callbacks); | 1895 | dm_table_add_target_callbacks(ti->table, &cache->callbacks); |
1829 | 1896 | ||
@@ -1835,7 +1902,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) | |||
1835 | 1902 | ||
1836 | /* FIXME: factor out this whole section */ | 1903 | /* FIXME: factor out this whole section */ |
1837 | origin_blocks = cache->origin_sectors = ca->origin_sectors; | 1904 | origin_blocks = cache->origin_sectors = ca->origin_sectors; |
1838 | (void) sector_div(origin_blocks, ca->block_size); | 1905 | origin_blocks = block_div(origin_blocks, ca->block_size); |
1839 | cache->origin_blocks = to_oblock(origin_blocks); | 1906 | cache->origin_blocks = to_oblock(origin_blocks); |
1840 | 1907 | ||
1841 | cache->sectors_per_block = ca->block_size; | 1908 | cache->sectors_per_block = ca->block_size; |
@@ -1848,7 +1915,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) | |||
1848 | dm_block_t cache_size = ca->cache_sectors; | 1915 | dm_block_t cache_size = ca->cache_sectors; |
1849 | 1916 | ||
1850 | cache->sectors_per_block_shift = -1; | 1917 | cache->sectors_per_block_shift = -1; |
1851 | (void) sector_div(cache_size, ca->block_size); | 1918 | cache_size = block_div(cache_size, ca->block_size); |
1852 | cache->cache_size = to_cblock(cache_size); | 1919 | cache->cache_size = to_cblock(cache_size); |
1853 | } else { | 1920 | } else { |
1854 | cache->sectors_per_block_shift = __ffs(ca->block_size); | 1921 | cache->sectors_per_block_shift = __ffs(ca->block_size); |
@@ -1873,6 +1940,7 @@ static int cache_create(struct cache_args *ca, struct cache **result) | |||
1873 | spin_lock_init(&cache->lock); | 1940 | spin_lock_init(&cache->lock); |
1874 | bio_list_init(&cache->deferred_bios); | 1941 | bio_list_init(&cache->deferred_bios); |
1875 | bio_list_init(&cache->deferred_flush_bios); | 1942 | bio_list_init(&cache->deferred_flush_bios); |
1943 | bio_list_init(&cache->deferred_writethrough_bios); | ||
1876 | INIT_LIST_HEAD(&cache->quiesced_migrations); | 1944 | INIT_LIST_HEAD(&cache->quiesced_migrations); |
1877 | INIT_LIST_HEAD(&cache->completed_migrations); | 1945 | INIT_LIST_HEAD(&cache->completed_migrations); |
1878 | INIT_LIST_HEAD(&cache->need_commit_migrations); | 1946 | INIT_LIST_HEAD(&cache->need_commit_migrations); |
@@ -2002,6 +2070,8 @@ static int cache_ctr(struct dm_target *ti, unsigned argc, char **argv) | |||
2002 | goto out; | 2070 | goto out; |
2003 | 2071 | ||
2004 | r = cache_create(ca, &cache); | 2072 | r = cache_create(ca, &cache); |
2073 | if (r) | ||
2074 | goto out; | ||
2005 | 2075 | ||
2006 | r = copy_ctr_args(cache, argc - 3, (const char **)argv + 3); | 2076 | r = copy_ctr_args(cache, argc - 3, (const char **)argv + 3); |
2007 | if (r) { | 2077 | if (r) { |
@@ -2016,20 +2086,6 @@ out: | |||
2016 | return r; | 2086 | return r; |
2017 | } | 2087 | } |
2018 | 2088 | ||
2019 | static unsigned cache_num_write_bios(struct dm_target *ti, struct bio *bio) | ||
2020 | { | ||
2021 | int r; | ||
2022 | struct cache *cache = ti->private; | ||
2023 | dm_oblock_t block = get_bio_block(cache, bio); | ||
2024 | dm_cblock_t cblock; | ||
2025 | |||
2026 | r = policy_lookup(cache->policy, block, &cblock); | ||
2027 | if (r < 0) | ||
2028 | return 2; /* assume the worst */ | ||
2029 | |||
2030 | return (!r && !is_dirty(cache, cblock)) ? 2 : 1; | ||
2031 | } | ||
2032 | |||
2033 | static int cache_map(struct dm_target *ti, struct bio *bio) | 2089 | static int cache_map(struct dm_target *ti, struct bio *bio) |
2034 | { | 2090 | { |
2035 | struct cache *cache = ti->private; | 2091 | struct cache *cache = ti->private; |
@@ -2097,18 +2153,12 @@ static int cache_map(struct dm_target *ti, struct bio *bio) | |||
2097 | inc_hit_counter(cache, bio); | 2153 | inc_hit_counter(cache, bio); |
2098 | pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds); | 2154 | pb->all_io_entry = dm_deferred_entry_inc(cache->all_io_ds); |
2099 | 2155 | ||
2100 | if (is_writethrough_io(cache, bio, lookup_result.cblock)) { | 2156 | if (is_writethrough_io(cache, bio, lookup_result.cblock)) |
2101 | /* | 2157 | remap_to_origin_then_cache(cache, bio, block, lookup_result.cblock); |
2102 | * No need to mark anything dirty in write through mode. | 2158 | else |
2103 | */ | ||
2104 | pb->req_nr == 0 ? | ||
2105 | remap_to_cache(cache, bio, lookup_result.cblock) : | ||
2106 | remap_to_origin_clear_discard(cache, bio, block); | ||
2107 | cell_defer(cache, cell, false); | ||
2108 | } else { | ||
2109 | remap_to_cache_dirty(cache, bio, block, lookup_result.cblock); | 2159 | remap_to_cache_dirty(cache, bio, block, lookup_result.cblock); |
2110 | cell_defer(cache, cell, false); | 2160 | |
2111 | } | 2161 | cell_defer(cache, cell, false); |
2112 | break; | 2162 | break; |
2113 | 2163 | ||
2114 | case POLICY_MISS: | 2164 | case POLICY_MISS: |
@@ -2319,8 +2369,7 @@ static int cache_preresume(struct dm_target *ti) | |||
2319 | } | 2369 | } |
2320 | 2370 | ||
2321 | if (!cache->loaded_mappings) { | 2371 | if (!cache->loaded_mappings) { |
2322 | r = dm_cache_load_mappings(cache->cmd, | 2372 | r = dm_cache_load_mappings(cache->cmd, cache->policy, |
2323 | dm_cache_policy_get_name(cache->policy), | ||
2324 | load_mapping, cache); | 2373 | load_mapping, cache); |
2325 | if (r) { | 2374 | if (r) { |
2326 | DMERR("could not load cache mappings"); | 2375 | DMERR("could not load cache mappings"); |
@@ -2535,7 +2584,7 @@ static void cache_io_hints(struct dm_target *ti, struct queue_limits *limits) | |||
2535 | 2584 | ||
2536 | static struct target_type cache_target = { | 2585 | static struct target_type cache_target = { |
2537 | .name = "cache", | 2586 | .name = "cache", |
2538 | .version = {1, 0, 0}, | 2587 | .version = {1, 1, 0}, |
2539 | .module = THIS_MODULE, | 2588 | .module = THIS_MODULE, |
2540 | .ctr = cache_ctr, | 2589 | .ctr = cache_ctr, |
2541 | .dtr = cache_dtr, | 2590 | .dtr = cache_dtr, |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 9a01d1e4c783..311e3d35b272 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -91,15 +91,44 @@ static struct raid_type { | |||
91 | {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} | 91 | {"raid6_nc", "RAID6 (N continue)", 2, 4, 6, ALGORITHM_ROTATING_N_CONTINUE} |
92 | }; | 92 | }; |
93 | 93 | ||
94 | static char *raid10_md_layout_to_format(int layout) | ||
95 | { | ||
96 | /* | ||
97 | * Bit 16 and 17 stand for "offset" and "use_far_sets" | ||
98 | * Refer to MD's raid10.c for details | ||
99 | */ | ||
100 | if ((layout & 0x10000) && (layout & 0x20000)) | ||
101 | return "offset"; | ||
102 | |||
103 | if ((layout & 0xFF) > 1) | ||
104 | return "near"; | ||
105 | |||
106 | return "far"; | ||
107 | } | ||
108 | |||
94 | static unsigned raid10_md_layout_to_copies(int layout) | 109 | static unsigned raid10_md_layout_to_copies(int layout) |
95 | { | 110 | { |
96 | return layout & 0xFF; | 111 | if ((layout & 0xFF) > 1) |
112 | return layout & 0xFF; | ||
113 | return (layout >> 8) & 0xFF; | ||
97 | } | 114 | } |
98 | 115 | ||
99 | static int raid10_format_to_md_layout(char *format, unsigned copies) | 116 | static int raid10_format_to_md_layout(char *format, unsigned copies) |
100 | { | 117 | { |
101 | /* 1 "far" copy, and 'copies' "near" copies */ | 118 | unsigned n = 1, f = 1; |
102 | return (1 << 8) | (copies & 0xFF); | 119 | |
120 | if (!strcmp("near", format)) | ||
121 | n = copies; | ||
122 | else | ||
123 | f = copies; | ||
124 | |||
125 | if (!strcmp("offset", format)) | ||
126 | return 0x30000 | (f << 8) | n; | ||
127 | |||
128 | if (!strcmp("far", format)) | ||
129 | return 0x20000 | (f << 8) | n; | ||
130 | |||
131 | return (f << 8) | n; | ||
103 | } | 132 | } |
104 | 133 | ||
105 | static struct raid_type *get_raid_type(char *name) | 134 | static struct raid_type *get_raid_type(char *name) |
@@ -352,6 +381,7 @@ static int validate_raid_redundancy(struct raid_set *rs) | |||
352 | { | 381 | { |
353 | unsigned i, rebuild_cnt = 0; | 382 | unsigned i, rebuild_cnt = 0; |
354 | unsigned rebuilds_per_group, copies, d; | 383 | unsigned rebuilds_per_group, copies, d; |
384 | unsigned group_size, last_group_start; | ||
355 | 385 | ||
356 | for (i = 0; i < rs->md.raid_disks; i++) | 386 | for (i = 0; i < rs->md.raid_disks; i++) |
357 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || | 387 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || |
@@ -379,9 +409,6 @@ static int validate_raid_redundancy(struct raid_set *rs) | |||
379 | * as long as the failed devices occur in different mirror | 409 | * as long as the failed devices occur in different mirror |
380 | * groups (i.e. different stripes). | 410 | * groups (i.e. different stripes). |
381 | * | 411 | * |
382 | * Right now, we only allow for "near" copies. When other | ||
383 | * formats are added, we will have to check those too. | ||
384 | * | ||
385 | * When checking "near" format, make sure no adjacent devices | 412 | * When checking "near" format, make sure no adjacent devices |
386 | * have failed beyond what can be handled. In addition to the | 413 | * have failed beyond what can be handled. In addition to the |
387 | * simple case where the number of devices is a multiple of the | 414 | * simple case where the number of devices is a multiple of the |
@@ -391,14 +418,41 @@ static int validate_raid_redundancy(struct raid_set *rs) | |||
391 | * A A B B C | 418 | * A A B B C |
392 | * C D D E E | 419 | * C D D E E |
393 | */ | 420 | */ |
394 | for (i = 0; i < rs->md.raid_disks * copies; i++) { | 421 | if (!strcmp("near", raid10_md_layout_to_format(rs->md.layout))) { |
395 | if (!(i % copies)) | 422 | for (i = 0; i < rs->md.raid_disks * copies; i++) { |
423 | if (!(i % copies)) | ||
424 | rebuilds_per_group = 0; | ||
425 | d = i % rs->md.raid_disks; | ||
426 | if ((!rs->dev[d].rdev.sb_page || | ||
427 | !test_bit(In_sync, &rs->dev[d].rdev.flags)) && | ||
428 | (++rebuilds_per_group >= copies)) | ||
429 | goto too_many; | ||
430 | } | ||
431 | break; | ||
432 | } | ||
433 | |||
434 | /* | ||
435 | * When checking "far" and "offset" formats, we need to ensure | ||
436 | * that the device that holds its copy is not also dead or | ||
437 | * being rebuilt. (Note that "far" and "offset" formats only | ||
438 | * support two copies right now. These formats also only ever | ||
439 | * use the 'use_far_sets' variant.) | ||
440 | * | ||
441 | * This check is somewhat complicated by the need to account | ||
442 | * for arrays that are not a multiple of (far) copies. This | ||
443 | * results in the need to treat the last (potentially larger) | ||
444 | * set differently. | ||
445 | */ | ||
446 | group_size = (rs->md.raid_disks / copies); | ||
447 | last_group_start = (rs->md.raid_disks / group_size) - 1; | ||
448 | last_group_start *= group_size; | ||
449 | for (i = 0; i < rs->md.raid_disks; i++) { | ||
450 | if (!(i % copies) && !(i > last_group_start)) | ||
396 | rebuilds_per_group = 0; | 451 | rebuilds_per_group = 0; |
397 | d = i % rs->md.raid_disks; | 452 | if ((!rs->dev[i].rdev.sb_page || |
398 | if ((!rs->dev[d].rdev.sb_page || | 453 | !test_bit(In_sync, &rs->dev[i].rdev.flags)) && |
399 | !test_bit(In_sync, &rs->dev[d].rdev.flags)) && | ||
400 | (++rebuilds_per_group >= copies)) | 454 | (++rebuilds_per_group >= copies)) |
401 | goto too_many; | 455 | goto too_many; |
402 | } | 456 | } |
403 | break; | 457 | break; |
404 | default: | 458 | default: |
@@ -433,7 +487,7 @@ too_many: | |||
433 | * | 487 | * |
434 | * RAID10-only options: | 488 | * RAID10-only options: |
435 | * [raid10_copies <# copies>] Number of copies. (Default: 2) | 489 | * [raid10_copies <# copies>] Number of copies. (Default: 2) |
436 | * [raid10_format <near>] Layout algorithm. (Default: near) | 490 | * [raid10_format <near|far|offset>] Layout algorithm. (Default: near) |
437 | */ | 491 | */ |
438 | static int parse_raid_params(struct raid_set *rs, char **argv, | 492 | static int parse_raid_params(struct raid_set *rs, char **argv, |
439 | unsigned num_raid_params) | 493 | unsigned num_raid_params) |
@@ -520,7 +574,9 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
520 | rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; | 574 | rs->ti->error = "'raid10_format' is an invalid parameter for this RAID type"; |
521 | return -EINVAL; | 575 | return -EINVAL; |
522 | } | 576 | } |
523 | if (strcmp("near", argv[i])) { | 577 | if (strcmp("near", argv[i]) && |
578 | strcmp("far", argv[i]) && | ||
579 | strcmp("offset", argv[i])) { | ||
524 | rs->ti->error = "Invalid 'raid10_format' value given"; | 580 | rs->ti->error = "Invalid 'raid10_format' value given"; |
525 | return -EINVAL; | 581 | return -EINVAL; |
526 | } | 582 | } |
@@ -644,6 +700,15 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
644 | return -EINVAL; | 700 | return -EINVAL; |
645 | } | 701 | } |
646 | 702 | ||
703 | /* | ||
704 | * If the format is not "near", we only support | ||
705 | * two copies at the moment. | ||
706 | */ | ||
707 | if (strcmp("near", raid10_format) && (raid10_copies > 2)) { | ||
708 | rs->ti->error = "Too many copies for given RAID10 format."; | ||
709 | return -EINVAL; | ||
710 | } | ||
711 | |||
647 | /* (Len * #mirrors) / #devices */ | 712 | /* (Len * #mirrors) / #devices */ |
648 | sectors_per_dev = rs->ti->len * raid10_copies; | 713 | sectors_per_dev = rs->ti->len * raid10_copies; |
649 | sector_div(sectors_per_dev, rs->md.raid_disks); | 714 | sector_div(sectors_per_dev, rs->md.raid_disks); |
@@ -854,17 +919,30 @@ static int super_init_validation(struct mddev *mddev, struct md_rdev *rdev) | |||
854 | /* | 919 | /* |
855 | * Reshaping is not currently allowed | 920 | * Reshaping is not currently allowed |
856 | */ | 921 | */ |
857 | if ((le32_to_cpu(sb->level) != mddev->level) || | 922 | if (le32_to_cpu(sb->level) != mddev->level) { |
858 | (le32_to_cpu(sb->layout) != mddev->layout) || | 923 | DMERR("Reshaping arrays not yet supported. (RAID level change)"); |
859 | (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors)) { | 924 | return -EINVAL; |
860 | DMERR("Reshaping arrays not yet supported."); | 925 | } |
926 | if (le32_to_cpu(sb->layout) != mddev->layout) { | ||
927 | DMERR("Reshaping arrays not yet supported. (RAID layout change)"); | ||
928 | DMERR(" 0x%X vs 0x%X", le32_to_cpu(sb->layout), mddev->layout); | ||
929 | DMERR(" Old layout: %s w/ %d copies", | ||
930 | raid10_md_layout_to_format(le32_to_cpu(sb->layout)), | ||
931 | raid10_md_layout_to_copies(le32_to_cpu(sb->layout))); | ||
932 | DMERR(" New layout: %s w/ %d copies", | ||
933 | raid10_md_layout_to_format(mddev->layout), | ||
934 | raid10_md_layout_to_copies(mddev->layout)); | ||
935 | return -EINVAL; | ||
936 | } | ||
937 | if (le32_to_cpu(sb->stripe_sectors) != mddev->chunk_sectors) { | ||
938 | DMERR("Reshaping arrays not yet supported. (stripe sectors change)"); | ||
861 | return -EINVAL; | 939 | return -EINVAL; |
862 | } | 940 | } |
863 | 941 | ||
864 | /* We can only change the number of devices in RAID1 right now */ | 942 | /* We can only change the number of devices in RAID1 right now */ |
865 | if ((rs->raid_type->level != 1) && | 943 | if ((rs->raid_type->level != 1) && |
866 | (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) { | 944 | (le32_to_cpu(sb->num_devices) != mddev->raid_disks)) { |
867 | DMERR("Reshaping arrays not yet supported."); | 945 | DMERR("Reshaping arrays not yet supported. (device count change)"); |
868 | return -EINVAL; | 946 | return -EINVAL; |
869 | } | 947 | } |
870 | 948 | ||
@@ -1329,7 +1407,8 @@ static void raid_status(struct dm_target *ti, status_type_t type, | |||
1329 | raid10_md_layout_to_copies(rs->md.layout)); | 1407 | raid10_md_layout_to_copies(rs->md.layout)); |
1330 | 1408 | ||
1331 | if (rs->print_flags & DMPF_RAID10_FORMAT) | 1409 | if (rs->print_flags & DMPF_RAID10_FORMAT) |
1332 | DMEMIT(" raid10_format near"); | 1410 | DMEMIT(" raid10_format %s", |
1411 | raid10_md_layout_to_format(rs->md.layout)); | ||
1333 | 1412 | ||
1334 | DMEMIT(" %d", rs->md.raid_disks); | 1413 | DMEMIT(" %d", rs->md.raid_disks); |
1335 | for (i = 0; i < rs->md.raid_disks; i++) { | 1414 | for (i = 0; i < rs->md.raid_disks; i++) { |
@@ -1418,6 +1497,10 @@ static struct target_type raid_target = { | |||
1418 | 1497 | ||
1419 | static int __init dm_raid_init(void) | 1498 | static int __init dm_raid_init(void) |
1420 | { | 1499 | { |
1500 | DMINFO("Loading target version %u.%u.%u", | ||
1501 | raid_target.version[0], | ||
1502 | raid_target.version[1], | ||
1503 | raid_target.version[2]); | ||
1421 | return dm_register_target(&raid_target); | 1504 | return dm_register_target(&raid_target); |
1422 | } | 1505 | } |
1423 | 1506 | ||
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 009339d62828..004ad1652b73 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -1577,6 +1577,11 @@ static bool data_dev_supports_discard(struct pool_c *pt) | |||
1577 | return q && blk_queue_discard(q); | 1577 | return q && blk_queue_discard(q); |
1578 | } | 1578 | } |
1579 | 1579 | ||
1580 | static bool is_factor(sector_t block_size, uint32_t n) | ||
1581 | { | ||
1582 | return !sector_div(block_size, n); | ||
1583 | } | ||
1584 | |||
1580 | /* | 1585 | /* |
1581 | * If discard_passdown was enabled verify that the data device | 1586 | * If discard_passdown was enabled verify that the data device |
1582 | * supports discards. Disable discard_passdown if not. | 1587 | * supports discards. Disable discard_passdown if not. |
@@ -1602,7 +1607,7 @@ static void disable_passdown_if_not_supported(struct pool_c *pt) | |||
1602 | else if (data_limits->discard_granularity > block_size) | 1607 | else if (data_limits->discard_granularity > block_size) |
1603 | reason = "discard granularity larger than a block"; | 1608 | reason = "discard granularity larger than a block"; |
1604 | 1609 | ||
1605 | else if (block_size & (data_limits->discard_granularity - 1)) | 1610 | else if (!is_factor(block_size, data_limits->discard_granularity)) |
1606 | reason = "discard granularity not a factor of block size"; | 1611 | reason = "discard granularity not a factor of block size"; |
1607 | 1612 | ||
1608 | if (reason) { | 1613 | if (reason) { |
@@ -2544,7 +2549,7 @@ static struct target_type pool_target = { | |||
2544 | .name = "thin-pool", | 2549 | .name = "thin-pool", |
2545 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | | 2550 | .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE | |
2546 | DM_TARGET_IMMUTABLE, | 2551 | DM_TARGET_IMMUTABLE, |
2547 | .version = {1, 6, 1}, | 2552 | .version = {1, 7, 0}, |
2548 | .module = THIS_MODULE, | 2553 | .module = THIS_MODULE, |
2549 | .ctr = pool_ctr, | 2554 | .ctr = pool_ctr, |
2550 | .dtr = pool_dtr, | 2555 | .dtr = pool_dtr, |
@@ -2831,7 +2836,7 @@ static int thin_iterate_devices(struct dm_target *ti, | |||
2831 | 2836 | ||
2832 | static struct target_type thin_target = { | 2837 | static struct target_type thin_target = { |
2833 | .name = "thin", | 2838 | .name = "thin", |
2834 | .version = {1, 7, 1}, | 2839 | .version = {1, 8, 0}, |
2835 | .module = THIS_MODULE, | 2840 | .module = THIS_MODULE, |
2836 | .ctr = thin_ctr, | 2841 | .ctr = thin_ctr, |
2837 | .dtr = thin_dtr, | 2842 | .dtr = thin_dtr, |
diff --git a/drivers/md/dm-verity.c b/drivers/md/dm-verity.c index 6ad538375c3c..a746f1d21c66 100644 --- a/drivers/md/dm-verity.c +++ b/drivers/md/dm-verity.c | |||
@@ -93,6 +93,13 @@ struct dm_verity_io { | |||
93 | */ | 93 | */ |
94 | }; | 94 | }; |
95 | 95 | ||
96 | struct dm_verity_prefetch_work { | ||
97 | struct work_struct work; | ||
98 | struct dm_verity *v; | ||
99 | sector_t block; | ||
100 | unsigned n_blocks; | ||
101 | }; | ||
102 | |||
96 | static struct shash_desc *io_hash_desc(struct dm_verity *v, struct dm_verity_io *io) | 103 | static struct shash_desc *io_hash_desc(struct dm_verity *v, struct dm_verity_io *io) |
97 | { | 104 | { |
98 | return (struct shash_desc *)(io + 1); | 105 | return (struct shash_desc *)(io + 1); |
@@ -424,15 +431,18 @@ static void verity_end_io(struct bio *bio, int error) | |||
424 | * The root buffer is not prefetched, it is assumed that it will be cached | 431 | * The root buffer is not prefetched, it is assumed that it will be cached |
425 | * all the time. | 432 | * all the time. |
426 | */ | 433 | */ |
427 | static void verity_prefetch_io(struct dm_verity *v, struct dm_verity_io *io) | 434 | static void verity_prefetch_io(struct work_struct *work) |
428 | { | 435 | { |
436 | struct dm_verity_prefetch_work *pw = | ||
437 | container_of(work, struct dm_verity_prefetch_work, work); | ||
438 | struct dm_verity *v = pw->v; | ||
429 | int i; | 439 | int i; |
430 | 440 | ||
431 | for (i = v->levels - 2; i >= 0; i--) { | 441 | for (i = v->levels - 2; i >= 0; i--) { |
432 | sector_t hash_block_start; | 442 | sector_t hash_block_start; |
433 | sector_t hash_block_end; | 443 | sector_t hash_block_end; |
434 | verity_hash_at_level(v, io->block, i, &hash_block_start, NULL); | 444 | verity_hash_at_level(v, pw->block, i, &hash_block_start, NULL); |
435 | verity_hash_at_level(v, io->block + io->n_blocks - 1, i, &hash_block_end, NULL); | 445 | verity_hash_at_level(v, pw->block + pw->n_blocks - 1, i, &hash_block_end, NULL); |
436 | if (!i) { | 446 | if (!i) { |
437 | unsigned cluster = ACCESS_ONCE(dm_verity_prefetch_cluster); | 447 | unsigned cluster = ACCESS_ONCE(dm_verity_prefetch_cluster); |
438 | 448 | ||
@@ -452,6 +462,25 @@ no_prefetch_cluster: | |||
452 | dm_bufio_prefetch(v->bufio, hash_block_start, | 462 | dm_bufio_prefetch(v->bufio, hash_block_start, |
453 | hash_block_end - hash_block_start + 1); | 463 | hash_block_end - hash_block_start + 1); |
454 | } | 464 | } |
465 | |||
466 | kfree(pw); | ||
467 | } | ||
468 | |||
469 | static void verity_submit_prefetch(struct dm_verity *v, struct dm_verity_io *io) | ||
470 | { | ||
471 | struct dm_verity_prefetch_work *pw; | ||
472 | |||
473 | pw = kmalloc(sizeof(struct dm_verity_prefetch_work), | ||
474 | GFP_NOIO | __GFP_NORETRY | __GFP_NOMEMALLOC | __GFP_NOWARN); | ||
475 | |||
476 | if (!pw) | ||
477 | return; | ||
478 | |||
479 | INIT_WORK(&pw->work, verity_prefetch_io); | ||
480 | pw->v = v; | ||
481 | pw->block = io->block; | ||
482 | pw->n_blocks = io->n_blocks; | ||
483 | queue_work(v->verify_wq, &pw->work); | ||
455 | } | 484 | } |
456 | 485 | ||
457 | /* | 486 | /* |
@@ -498,7 +527,7 @@ static int verity_map(struct dm_target *ti, struct bio *bio) | |||
498 | memcpy(io->io_vec, bio_iovec(bio), | 527 | memcpy(io->io_vec, bio_iovec(bio), |
499 | io->io_vec_size * sizeof(struct bio_vec)); | 528 | io->io_vec_size * sizeof(struct bio_vec)); |
500 | 529 | ||
501 | verity_prefetch_io(v, io); | 530 | verity_submit_prefetch(v, io); |
502 | 531 | ||
503 | generic_make_request(bio); | 532 | generic_make_request(bio); |
504 | 533 | ||
@@ -858,7 +887,7 @@ bad: | |||
858 | 887 | ||
859 | static struct target_type verity_target = { | 888 | static struct target_type verity_target = { |
860 | .name = "verity", | 889 | .name = "verity", |
861 | .version = {1, 1, 1}, | 890 | .version = {1, 2, 0}, |
862 | .module = THIS_MODULE, | 891 | .module = THIS_MODULE, |
863 | .ctr = verity_ctr, | 892 | .ctr = verity_ctr, |
864 | .dtr = verity_dtr, | 893 | .dtr = verity_dtr, |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 3db3d1b271f7..aeceedfc530b 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
@@ -307,6 +307,10 @@ static void md_make_request(struct request_queue *q, struct bio *bio) | |||
307 | bio_io_error(bio); | 307 | bio_io_error(bio); |
308 | return; | 308 | return; |
309 | } | 309 | } |
310 | if (mddev->ro == 1 && unlikely(rw == WRITE)) { | ||
311 | bio_endio(bio, bio_sectors(bio) == 0 ? 0 : -EROFS); | ||
312 | return; | ||
313 | } | ||
310 | smp_rmb(); /* Ensure implications of 'active' are visible */ | 314 | smp_rmb(); /* Ensure implications of 'active' are visible */ |
311 | rcu_read_lock(); | 315 | rcu_read_lock(); |
312 | if (mddev->suspended) { | 316 | if (mddev->suspended) { |
@@ -2994,6 +2998,9 @@ rdev_size_store(struct md_rdev *rdev, const char *buf, size_t len) | |||
2994 | } else if (!sectors) | 2998 | } else if (!sectors) |
2995 | sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) - | 2999 | sectors = (i_size_read(rdev->bdev->bd_inode) >> 9) - |
2996 | rdev->data_offset; | 3000 | rdev->data_offset; |
3001 | if (!my_mddev->pers->resize) | ||
3002 | /* Cannot change size for RAID0 or Linear etc */ | ||
3003 | return -EINVAL; | ||
2997 | } | 3004 | } |
2998 | if (sectors < my_mddev->dev_sectors) | 3005 | if (sectors < my_mddev->dev_sectors) |
2999 | return -EINVAL; /* component must fit device */ | 3006 | return -EINVAL; /* component must fit device */ |
@@ -6525,7 +6532,17 @@ static int md_ioctl(struct block_device *bdev, fmode_t mode, | |||
6525 | mddev->ro = 0; | 6532 | mddev->ro = 0; |
6526 | sysfs_notify_dirent_safe(mddev->sysfs_state); | 6533 | sysfs_notify_dirent_safe(mddev->sysfs_state); |
6527 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); | 6534 | set_bit(MD_RECOVERY_NEEDED, &mddev->recovery); |
6528 | md_wakeup_thread(mddev->thread); | 6535 | /* mddev_unlock will wake thread */ |
6536 | /* If a device failed while we were read-only, we | ||
6537 | * need to make sure the metadata is updated now. | ||
6538 | */ | ||
6539 | if (test_bit(MD_CHANGE_DEVS, &mddev->flags)) { | ||
6540 | mddev_unlock(mddev); | ||
6541 | wait_event(mddev->sb_wait, | ||
6542 | !test_bit(MD_CHANGE_DEVS, &mddev->flags) && | ||
6543 | !test_bit(MD_CHANGE_PENDING, &mddev->flags)); | ||
6544 | mddev_lock(mddev); | ||
6545 | } | ||
6529 | } else { | 6546 | } else { |
6530 | err = -EROFS; | 6547 | err = -EROFS; |
6531 | goto abort_unlock; | 6548 | goto abort_unlock; |
@@ -7646,10 +7663,8 @@ static int remove_and_add_spares(struct mddev *mddev) | |||
7646 | removed++; | 7663 | removed++; |
7647 | } | 7664 | } |
7648 | } | 7665 | } |
7649 | if (removed) | 7666 | if (removed && mddev->kobj.sd) |
7650 | sysfs_notify(&mddev->kobj, NULL, | 7667 | sysfs_notify(&mddev->kobj, NULL, "degraded"); |
7651 | "degraded"); | ||
7652 | |||
7653 | 7668 | ||
7654 | rdev_for_each(rdev, mddev) { | 7669 | rdev_for_each(rdev, mddev) { |
7655 | if (rdev->raid_disk >= 0 && | 7670 | if (rdev->raid_disk >= 0 && |
diff --git a/drivers/md/md.h b/drivers/md/md.h index eca59c3074ef..d90fb1a879e1 100644 --- a/drivers/md/md.h +++ b/drivers/md/md.h | |||
@@ -506,7 +506,7 @@ static inline char * mdname (struct mddev * mddev) | |||
506 | static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev) | 506 | static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev) |
507 | { | 507 | { |
508 | char nm[20]; | 508 | char nm[20]; |
509 | if (!test_bit(Replacement, &rdev->flags)) { | 509 | if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) { |
510 | sprintf(nm, "rd%d", rdev->raid_disk); | 510 | sprintf(nm, "rd%d", rdev->raid_disk); |
511 | return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); | 511 | return sysfs_create_link(&mddev->kobj, &rdev->kobj, nm); |
512 | } else | 512 | } else |
@@ -516,7 +516,7 @@ static inline int sysfs_link_rdev(struct mddev *mddev, struct md_rdev *rdev) | |||
516 | static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev) | 516 | static inline void sysfs_unlink_rdev(struct mddev *mddev, struct md_rdev *rdev) |
517 | { | 517 | { |
518 | char nm[20]; | 518 | char nm[20]; |
519 | if (!test_bit(Replacement, &rdev->flags)) { | 519 | if (!test_bit(Replacement, &rdev->flags) && mddev->kobj.sd) { |
520 | sprintf(nm, "rd%d", rdev->raid_disk); | 520 | sprintf(nm, "rd%d", rdev->raid_disk); |
521 | sysfs_remove_link(&mddev->kobj, nm); | 521 | sysfs_remove_link(&mddev->kobj, nm); |
522 | } | 522 | } |
diff --git a/drivers/md/persistent-data/dm-btree-remove.c b/drivers/md/persistent-data/dm-btree-remove.c index c4f28133ef82..b88757cd0d1d 100644 --- a/drivers/md/persistent-data/dm-btree-remove.c +++ b/drivers/md/persistent-data/dm-btree-remove.c | |||
@@ -139,15 +139,8 @@ struct child { | |||
139 | struct btree_node *n; | 139 | struct btree_node *n; |
140 | }; | 140 | }; |
141 | 141 | ||
142 | static struct dm_btree_value_type le64_type = { | 142 | static int init_child(struct dm_btree_info *info, struct dm_btree_value_type *vt, |
143 | .context = NULL, | 143 | struct btree_node *parent, |
144 | .size = sizeof(__le64), | ||
145 | .inc = NULL, | ||
146 | .dec = NULL, | ||
147 | .equal = NULL | ||
148 | }; | ||
149 | |||
150 | static int init_child(struct dm_btree_info *info, struct btree_node *parent, | ||
151 | unsigned index, struct child *result) | 144 | unsigned index, struct child *result) |
152 | { | 145 | { |
153 | int r, inc; | 146 | int r, inc; |
@@ -164,7 +157,7 @@ static int init_child(struct dm_btree_info *info, struct btree_node *parent, | |||
164 | result->n = dm_block_data(result->block); | 157 | result->n = dm_block_data(result->block); |
165 | 158 | ||
166 | if (inc) | 159 | if (inc) |
167 | inc_children(info->tm, result->n, &le64_type); | 160 | inc_children(info->tm, result->n, vt); |
168 | 161 | ||
169 | *((__le64 *) value_ptr(parent, index)) = | 162 | *((__le64 *) value_ptr(parent, index)) = |
170 | cpu_to_le64(dm_block_location(result->block)); | 163 | cpu_to_le64(dm_block_location(result->block)); |
@@ -236,7 +229,7 @@ static void __rebalance2(struct dm_btree_info *info, struct btree_node *parent, | |||
236 | } | 229 | } |
237 | 230 | ||
238 | static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, | 231 | static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, |
239 | unsigned left_index) | 232 | struct dm_btree_value_type *vt, unsigned left_index) |
240 | { | 233 | { |
241 | int r; | 234 | int r; |
242 | struct btree_node *parent; | 235 | struct btree_node *parent; |
@@ -244,11 +237,11 @@ static int rebalance2(struct shadow_spine *s, struct dm_btree_info *info, | |||
244 | 237 | ||
245 | parent = dm_block_data(shadow_current(s)); | 238 | parent = dm_block_data(shadow_current(s)); |
246 | 239 | ||
247 | r = init_child(info, parent, left_index, &left); | 240 | r = init_child(info, vt, parent, left_index, &left); |
248 | if (r) | 241 | if (r) |
249 | return r; | 242 | return r; |
250 | 243 | ||
251 | r = init_child(info, parent, left_index + 1, &right); | 244 | r = init_child(info, vt, parent, left_index + 1, &right); |
252 | if (r) { | 245 | if (r) { |
253 | exit_child(info, &left); | 246 | exit_child(info, &left); |
254 | return r; | 247 | return r; |
@@ -368,7 +361,7 @@ static void __rebalance3(struct dm_btree_info *info, struct btree_node *parent, | |||
368 | } | 361 | } |
369 | 362 | ||
370 | static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, | 363 | static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, |
371 | unsigned left_index) | 364 | struct dm_btree_value_type *vt, unsigned left_index) |
372 | { | 365 | { |
373 | int r; | 366 | int r; |
374 | struct btree_node *parent = dm_block_data(shadow_current(s)); | 367 | struct btree_node *parent = dm_block_data(shadow_current(s)); |
@@ -377,17 +370,17 @@ static int rebalance3(struct shadow_spine *s, struct dm_btree_info *info, | |||
377 | /* | 370 | /* |
378 | * FIXME: fill out an array? | 371 | * FIXME: fill out an array? |
379 | */ | 372 | */ |
380 | r = init_child(info, parent, left_index, &left); | 373 | r = init_child(info, vt, parent, left_index, &left); |
381 | if (r) | 374 | if (r) |
382 | return r; | 375 | return r; |
383 | 376 | ||
384 | r = init_child(info, parent, left_index + 1, ¢er); | 377 | r = init_child(info, vt, parent, left_index + 1, ¢er); |
385 | if (r) { | 378 | if (r) { |
386 | exit_child(info, &left); | 379 | exit_child(info, &left); |
387 | return r; | 380 | return r; |
388 | } | 381 | } |
389 | 382 | ||
390 | r = init_child(info, parent, left_index + 2, &right); | 383 | r = init_child(info, vt, parent, left_index + 2, &right); |
391 | if (r) { | 384 | if (r) { |
392 | exit_child(info, &left); | 385 | exit_child(info, &left); |
393 | exit_child(info, ¢er); | 386 | exit_child(info, ¢er); |
@@ -434,7 +427,8 @@ static int get_nr_entries(struct dm_transaction_manager *tm, | |||
434 | } | 427 | } |
435 | 428 | ||
436 | static int rebalance_children(struct shadow_spine *s, | 429 | static int rebalance_children(struct shadow_spine *s, |
437 | struct dm_btree_info *info, uint64_t key) | 430 | struct dm_btree_info *info, |
431 | struct dm_btree_value_type *vt, uint64_t key) | ||
438 | { | 432 | { |
439 | int i, r, has_left_sibling, has_right_sibling; | 433 | int i, r, has_left_sibling, has_right_sibling; |
440 | uint32_t child_entries; | 434 | uint32_t child_entries; |
@@ -472,13 +466,13 @@ static int rebalance_children(struct shadow_spine *s, | |||
472 | has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1); | 466 | has_right_sibling = i < (le32_to_cpu(n->header.nr_entries) - 1); |
473 | 467 | ||
474 | if (!has_left_sibling) | 468 | if (!has_left_sibling) |
475 | r = rebalance2(s, info, i); | 469 | r = rebalance2(s, info, vt, i); |
476 | 470 | ||
477 | else if (!has_right_sibling) | 471 | else if (!has_right_sibling) |
478 | r = rebalance2(s, info, i - 1); | 472 | r = rebalance2(s, info, vt, i - 1); |
479 | 473 | ||
480 | else | 474 | else |
481 | r = rebalance3(s, info, i - 1); | 475 | r = rebalance3(s, info, vt, i - 1); |
482 | 476 | ||
483 | return r; | 477 | return r; |
484 | } | 478 | } |
@@ -529,7 +523,7 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info, | |||
529 | if (le32_to_cpu(n->header.flags) & LEAF_NODE) | 523 | if (le32_to_cpu(n->header.flags) & LEAF_NODE) |
530 | return do_leaf(n, key, index); | 524 | return do_leaf(n, key, index); |
531 | 525 | ||
532 | r = rebalance_children(s, info, key); | 526 | r = rebalance_children(s, info, vt, key); |
533 | if (r) | 527 | if (r) |
534 | break; | 528 | break; |
535 | 529 | ||
@@ -550,6 +544,14 @@ static int remove_raw(struct shadow_spine *s, struct dm_btree_info *info, | |||
550 | return r; | 544 | return r; |
551 | } | 545 | } |
552 | 546 | ||
547 | static struct dm_btree_value_type le64_type = { | ||
548 | .context = NULL, | ||
549 | .size = sizeof(__le64), | ||
550 | .inc = NULL, | ||
551 | .dec = NULL, | ||
552 | .equal = NULL | ||
553 | }; | ||
554 | |||
553 | int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, | 555 | int dm_btree_remove(struct dm_btree_info *info, dm_block_t root, |
554 | uint64_t *keys, dm_block_t *new_root) | 556 | uint64_t *keys, dm_block_t *new_root) |
555 | { | 557 | { |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index 24b359717a7e..0505452de8d6 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
@@ -175,7 +175,13 @@ static int create_strip_zones(struct mddev *mddev, struct r0conf **private_conf) | |||
175 | rdev1->new_raid_disk = j; | 175 | rdev1->new_raid_disk = j; |
176 | } | 176 | } |
177 | 177 | ||
178 | if (j < 0 || j >= mddev->raid_disks) { | 178 | if (j < 0) { |
179 | printk(KERN_ERR | ||
180 | "md/raid0:%s: remove inactive devices before converting to RAID0\n", | ||
181 | mdname(mddev)); | ||
182 | goto abort; | ||
183 | } | ||
184 | if (j >= mddev->raid_disks) { | ||
179 | printk(KERN_ERR "md/raid0:%s: bad disk number %d - " | 185 | printk(KERN_ERR "md/raid0:%s: bad disk number %d - " |
180 | "aborting!\n", mdname(mddev), j); | 186 | "aborting!\n", mdname(mddev), j); |
181 | goto abort; | 187 | goto abort; |
@@ -289,7 +295,7 @@ abort: | |||
289 | kfree(conf->strip_zone); | 295 | kfree(conf->strip_zone); |
290 | kfree(conf->devlist); | 296 | kfree(conf->devlist); |
291 | kfree(conf); | 297 | kfree(conf); |
292 | *private_conf = NULL; | 298 | *private_conf = ERR_PTR(err); |
293 | return err; | 299 | return err; |
294 | } | 300 | } |
295 | 301 | ||
@@ -411,7 +417,8 @@ static sector_t raid0_size(struct mddev *mddev, sector_t sectors, int raid_disks | |||
411 | "%s does not support generic reshape\n", __func__); | 417 | "%s does not support generic reshape\n", __func__); |
412 | 418 | ||
413 | rdev_for_each(rdev, mddev) | 419 | rdev_for_each(rdev, mddev) |
414 | array_sectors += rdev->sectors; | 420 | array_sectors += (rdev->sectors & |
421 | ~(sector_t)(mddev->chunk_sectors-1)); | ||
415 | 422 | ||
416 | return array_sectors; | 423 | return array_sectors; |
417 | } | 424 | } |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index d5bddfc4010e..fd86b372692d 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
@@ -967,6 +967,7 @@ static void raid1_unplug(struct blk_plug_cb *cb, bool from_schedule) | |||
967 | bio_list_merge(&conf->pending_bio_list, &plug->pending); | 967 | bio_list_merge(&conf->pending_bio_list, &plug->pending); |
968 | conf->pending_count += plug->pending_cnt; | 968 | conf->pending_count += plug->pending_cnt; |
969 | spin_unlock_irq(&conf->device_lock); | 969 | spin_unlock_irq(&conf->device_lock); |
970 | wake_up(&conf->wait_barrier); | ||
970 | md_wakeup_thread(mddev->thread); | 971 | md_wakeup_thread(mddev->thread); |
971 | kfree(plug); | 972 | kfree(plug); |
972 | return; | 973 | return; |
@@ -1000,6 +1001,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) | |||
1000 | const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); | 1001 | const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA)); |
1001 | const unsigned long do_discard = (bio->bi_rw | 1002 | const unsigned long do_discard = (bio->bi_rw |
1002 | & (REQ_DISCARD | REQ_SECURE)); | 1003 | & (REQ_DISCARD | REQ_SECURE)); |
1004 | const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); | ||
1003 | struct md_rdev *blocked_rdev; | 1005 | struct md_rdev *blocked_rdev; |
1004 | struct blk_plug_cb *cb; | 1006 | struct blk_plug_cb *cb; |
1005 | struct raid1_plug_cb *plug = NULL; | 1007 | struct raid1_plug_cb *plug = NULL; |
@@ -1301,7 +1303,8 @@ read_again: | |||
1301 | conf->mirrors[i].rdev->data_offset); | 1303 | conf->mirrors[i].rdev->data_offset); |
1302 | mbio->bi_bdev = conf->mirrors[i].rdev->bdev; | 1304 | mbio->bi_bdev = conf->mirrors[i].rdev->bdev; |
1303 | mbio->bi_end_io = raid1_end_write_request; | 1305 | mbio->bi_end_io = raid1_end_write_request; |
1304 | mbio->bi_rw = WRITE | do_flush_fua | do_sync | do_discard; | 1306 | mbio->bi_rw = |
1307 | WRITE | do_flush_fua | do_sync | do_discard | do_same; | ||
1305 | mbio->bi_private = r1_bio; | 1308 | mbio->bi_private = r1_bio; |
1306 | 1309 | ||
1307 | atomic_inc(&r1_bio->remaining); | 1310 | atomic_inc(&r1_bio->remaining); |
@@ -2818,6 +2821,9 @@ static int run(struct mddev *mddev) | |||
2818 | if (IS_ERR(conf)) | 2821 | if (IS_ERR(conf)) |
2819 | return PTR_ERR(conf); | 2822 | return PTR_ERR(conf); |
2820 | 2823 | ||
2824 | if (mddev->queue) | ||
2825 | blk_queue_max_write_same_sectors(mddev->queue, | ||
2826 | mddev->chunk_sectors); | ||
2821 | rdev_for_each(rdev, mddev) { | 2827 | rdev_for_each(rdev, mddev) { |
2822 | if (!mddev->gendisk) | 2828 | if (!mddev->gendisk) |
2823 | continue; | 2829 | continue; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 64d48249c03b..77b562d18a90 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
@@ -38,21 +38,36 @@ | |||
38 | * near_copies (stored in low byte of layout) | 38 | * near_copies (stored in low byte of layout) |
39 | * far_copies (stored in second byte of layout) | 39 | * far_copies (stored in second byte of layout) |
40 | * far_offset (stored in bit 16 of layout ) | 40 | * far_offset (stored in bit 16 of layout ) |
41 | * use_far_sets (stored in bit 17 of layout ) | ||
41 | * | 42 | * |
42 | * The data to be stored is divided into chunks using chunksize. | 43 | * The data to be stored is divided into chunks using chunksize. Each device |
43 | * Each device is divided into far_copies sections. | 44 | * is divided into far_copies sections. In each section, chunks are laid out |
44 | * In each section, chunks are laid out in a style similar to raid0, but | 45 | * in a style similar to raid0, but near_copies copies of each chunk is stored |
45 | * near_copies copies of each chunk is stored (each on a different drive). | 46 | * (each on a different drive). The starting device for each section is offset |
46 | * The starting device for each section is offset near_copies from the starting | 47 | * near_copies from the starting device of the previous section. Thus there |
47 | * device of the previous section. | 48 | * are (near_copies * far_copies) of each chunk, and each is on a different |
48 | * Thus they are (near_copies*far_copies) of each chunk, and each is on a different | 49 | * drive. near_copies and far_copies must be at least one, and their product |
49 | * drive. | 50 | * is at most raid_disks. |
50 | * near_copies and far_copies must be at least one, and their product is at most | ||
51 | * raid_disks. | ||
52 | * | 51 | * |
53 | * If far_offset is true, then the far_copies are handled a bit differently. | 52 | * If far_offset is true, then the far_copies are handled a bit differently. |
54 | * The copies are still in different stripes, but instead of be very far apart | 53 | * The copies are still in different stripes, but instead of being very far |
55 | * on disk, there are adjacent stripes. | 54 | * apart on disk, there are adjacent stripes. |
55 | * | ||
56 | * The far and offset algorithms are handled slightly differently if | ||
57 | * 'use_far_sets' is true. In this case, the array's devices are grouped into | ||
58 | * sets that are (near_copies * far_copies) in size. The far copied stripes | ||
59 | * are still shifted by 'near_copies' devices, but this shifting stays confined | ||
60 | * to the set rather than the entire array. This is done to improve the number | ||
61 | * of device combinations that can fail without causing the array to fail. | ||
62 | * Example 'far' algorithm w/o 'use_far_sets' (each letter represents a chunk | ||
63 | * on a device): | ||
64 | * A B C D A B C D E | ||
65 | * ... ... | ||
66 | * D A B C E A B C D | ||
67 | * Example 'far' algorithm w/ 'use_far_sets' enabled (sets illustrated w/ []'s): | ||
68 | * [A B] [C D] [A B] [C D E] | ||
69 | * |...| |...| |...| | ... | | ||
70 | * [B A] [D C] [B A] [E C D] | ||
56 | */ | 71 | */ |
57 | 72 | ||
58 | /* | 73 | /* |
@@ -535,6 +550,13 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) | |||
535 | sector_t stripe; | 550 | sector_t stripe; |
536 | int dev; | 551 | int dev; |
537 | int slot = 0; | 552 | int slot = 0; |
553 | int last_far_set_start, last_far_set_size; | ||
554 | |||
555 | last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; | ||
556 | last_far_set_start *= geo->far_set_size; | ||
557 | |||
558 | last_far_set_size = geo->far_set_size; | ||
559 | last_far_set_size += (geo->raid_disks % geo->far_set_size); | ||
538 | 560 | ||
539 | /* now calculate first sector/dev */ | 561 | /* now calculate first sector/dev */ |
540 | chunk = r10bio->sector >> geo->chunk_shift; | 562 | chunk = r10bio->sector >> geo->chunk_shift; |
@@ -551,15 +573,25 @@ static void __raid10_find_phys(struct geom *geo, struct r10bio *r10bio) | |||
551 | /* and calculate all the others */ | 573 | /* and calculate all the others */ |
552 | for (n = 0; n < geo->near_copies; n++) { | 574 | for (n = 0; n < geo->near_copies; n++) { |
553 | int d = dev; | 575 | int d = dev; |
576 | int set; | ||
554 | sector_t s = sector; | 577 | sector_t s = sector; |
555 | r10bio->devs[slot].addr = sector; | ||
556 | r10bio->devs[slot].devnum = d; | 578 | r10bio->devs[slot].devnum = d; |
579 | r10bio->devs[slot].addr = s; | ||
557 | slot++; | 580 | slot++; |
558 | 581 | ||
559 | for (f = 1; f < geo->far_copies; f++) { | 582 | for (f = 1; f < geo->far_copies; f++) { |
583 | set = d / geo->far_set_size; | ||
560 | d += geo->near_copies; | 584 | d += geo->near_copies; |
561 | if (d >= geo->raid_disks) | 585 | |
562 | d -= geo->raid_disks; | 586 | if ((geo->raid_disks % geo->far_set_size) && |
587 | (d > last_far_set_start)) { | ||
588 | d -= last_far_set_start; | ||
589 | d %= last_far_set_size; | ||
590 | d += last_far_set_start; | ||
591 | } else { | ||
592 | d %= geo->far_set_size; | ||
593 | d += geo->far_set_size * set; | ||
594 | } | ||
563 | s += geo->stride; | 595 | s += geo->stride; |
564 | r10bio->devs[slot].devnum = d; | 596 | r10bio->devs[slot].devnum = d; |
565 | r10bio->devs[slot].addr = s; | 597 | r10bio->devs[slot].addr = s; |
@@ -595,6 +627,20 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev) | |||
595 | * or recovery, so reshape isn't happening | 627 | * or recovery, so reshape isn't happening |
596 | */ | 628 | */ |
597 | struct geom *geo = &conf->geo; | 629 | struct geom *geo = &conf->geo; |
630 | int far_set_start = (dev / geo->far_set_size) * geo->far_set_size; | ||
631 | int far_set_size = geo->far_set_size; | ||
632 | int last_far_set_start; | ||
633 | |||
634 | if (geo->raid_disks % geo->far_set_size) { | ||
635 | last_far_set_start = (geo->raid_disks / geo->far_set_size) - 1; | ||
636 | last_far_set_start *= geo->far_set_size; | ||
637 | |||
638 | if (dev >= last_far_set_start) { | ||
639 | far_set_size = geo->far_set_size; | ||
640 | far_set_size += (geo->raid_disks % geo->far_set_size); | ||
641 | far_set_start = last_far_set_start; | ||
642 | } | ||
643 | } | ||
598 | 644 | ||
599 | offset = sector & geo->chunk_mask; | 645 | offset = sector & geo->chunk_mask; |
600 | if (geo->far_offset) { | 646 | if (geo->far_offset) { |
@@ -602,13 +648,13 @@ static sector_t raid10_find_virt(struct r10conf *conf, sector_t sector, int dev) | |||
602 | chunk = sector >> geo->chunk_shift; | 648 | chunk = sector >> geo->chunk_shift; |
603 | fc = sector_div(chunk, geo->far_copies); | 649 | fc = sector_div(chunk, geo->far_copies); |
604 | dev -= fc * geo->near_copies; | 650 | dev -= fc * geo->near_copies; |
605 | if (dev < 0) | 651 | if (dev < far_set_start) |
606 | dev += geo->raid_disks; | 652 | dev += far_set_size; |
607 | } else { | 653 | } else { |
608 | while (sector >= geo->stride) { | 654 | while (sector >= geo->stride) { |
609 | sector -= geo->stride; | 655 | sector -= geo->stride; |
610 | if (dev < geo->near_copies) | 656 | if (dev < (geo->near_copies + far_set_start)) |
611 | dev += geo->raid_disks - geo->near_copies; | 657 | dev += far_set_size - geo->near_copies; |
612 | else | 658 | else |
613 | dev -= geo->near_copies; | 659 | dev -= geo->near_copies; |
614 | } | 660 | } |
@@ -1073,6 +1119,7 @@ static void raid10_unplug(struct blk_plug_cb *cb, bool from_schedule) | |||
1073 | bio_list_merge(&conf->pending_bio_list, &plug->pending); | 1119 | bio_list_merge(&conf->pending_bio_list, &plug->pending); |
1074 | conf->pending_count += plug->pending_cnt; | 1120 | conf->pending_count += plug->pending_cnt; |
1075 | spin_unlock_irq(&conf->device_lock); | 1121 | spin_unlock_irq(&conf->device_lock); |
1122 | wake_up(&conf->wait_barrier); | ||
1076 | md_wakeup_thread(mddev->thread); | 1123 | md_wakeup_thread(mddev->thread); |
1077 | kfree(plug); | 1124 | kfree(plug); |
1078 | return; | 1125 | return; |
@@ -1105,6 +1152,7 @@ static void make_request(struct mddev *mddev, struct bio * bio) | |||
1105 | const unsigned long do_fua = (bio->bi_rw & REQ_FUA); | 1152 | const unsigned long do_fua = (bio->bi_rw & REQ_FUA); |
1106 | const unsigned long do_discard = (bio->bi_rw | 1153 | const unsigned long do_discard = (bio->bi_rw |
1107 | & (REQ_DISCARD | REQ_SECURE)); | 1154 | & (REQ_DISCARD | REQ_SECURE)); |
1155 | const unsigned long do_same = (bio->bi_rw & REQ_WRITE_SAME); | ||
1108 | unsigned long flags; | 1156 | unsigned long flags; |
1109 | struct md_rdev *blocked_rdev; | 1157 | struct md_rdev *blocked_rdev; |
1110 | struct blk_plug_cb *cb; | 1158 | struct blk_plug_cb *cb; |
@@ -1460,7 +1508,8 @@ retry_write: | |||
1460 | rdev)); | 1508 | rdev)); |
1461 | mbio->bi_bdev = rdev->bdev; | 1509 | mbio->bi_bdev = rdev->bdev; |
1462 | mbio->bi_end_io = raid10_end_write_request; | 1510 | mbio->bi_end_io = raid10_end_write_request; |
1463 | mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; | 1511 | mbio->bi_rw = |
1512 | WRITE | do_sync | do_fua | do_discard | do_same; | ||
1464 | mbio->bi_private = r10_bio; | 1513 | mbio->bi_private = r10_bio; |
1465 | 1514 | ||
1466 | atomic_inc(&r10_bio->remaining); | 1515 | atomic_inc(&r10_bio->remaining); |
@@ -1502,7 +1551,8 @@ retry_write: | |||
1502 | r10_bio, rdev)); | 1551 | r10_bio, rdev)); |
1503 | mbio->bi_bdev = rdev->bdev; | 1552 | mbio->bi_bdev = rdev->bdev; |
1504 | mbio->bi_end_io = raid10_end_write_request; | 1553 | mbio->bi_end_io = raid10_end_write_request; |
1505 | mbio->bi_rw = WRITE | do_sync | do_fua | do_discard; | 1554 | mbio->bi_rw = |
1555 | WRITE | do_sync | do_fua | do_discard | do_same; | ||
1506 | mbio->bi_private = r10_bio; | 1556 | mbio->bi_private = r10_bio; |
1507 | 1557 | ||
1508 | atomic_inc(&r10_bio->remaining); | 1558 | atomic_inc(&r10_bio->remaining); |
@@ -3436,7 +3486,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) | |||
3436 | disks = mddev->raid_disks + mddev->delta_disks; | 3486 | disks = mddev->raid_disks + mddev->delta_disks; |
3437 | break; | 3487 | break; |
3438 | } | 3488 | } |
3439 | if (layout >> 17) | 3489 | if (layout >> 18) |
3440 | return -1; | 3490 | return -1; |
3441 | if (chunk < (PAGE_SIZE >> 9) || | 3491 | if (chunk < (PAGE_SIZE >> 9) || |
3442 | !is_power_of_2(chunk)) | 3492 | !is_power_of_2(chunk)) |
@@ -3448,6 +3498,7 @@ static int setup_geo(struct geom *geo, struct mddev *mddev, enum geo_type new) | |||
3448 | geo->near_copies = nc; | 3498 | geo->near_copies = nc; |
3449 | geo->far_copies = fc; | 3499 | geo->far_copies = fc; |
3450 | geo->far_offset = fo; | 3500 | geo->far_offset = fo; |
3501 | geo->far_set_size = (layout & (1<<17)) ? disks / fc : disks; | ||
3451 | geo->chunk_mask = chunk - 1; | 3502 | geo->chunk_mask = chunk - 1; |
3452 | geo->chunk_shift = ffz(~chunk); | 3503 | geo->chunk_shift = ffz(~chunk); |
3453 | return nc*fc; | 3504 | return nc*fc; |
@@ -3569,6 +3620,8 @@ static int run(struct mddev *mddev) | |||
3569 | if (mddev->queue) { | 3620 | if (mddev->queue) { |
3570 | blk_queue_max_discard_sectors(mddev->queue, | 3621 | blk_queue_max_discard_sectors(mddev->queue, |
3571 | mddev->chunk_sectors); | 3622 | mddev->chunk_sectors); |
3623 | blk_queue_max_write_same_sectors(mddev->queue, | ||
3624 | mddev->chunk_sectors); | ||
3572 | blk_queue_io_min(mddev->queue, chunk_size); | 3625 | blk_queue_io_min(mddev->queue, chunk_size); |
3573 | if (conf->geo.raid_disks % conf->geo.near_copies) | 3626 | if (conf->geo.raid_disks % conf->geo.near_copies) |
3574 | blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); | 3627 | blk_queue_io_opt(mddev->queue, chunk_size * conf->geo.raid_disks); |
diff --git a/drivers/md/raid10.h b/drivers/md/raid10.h index 1054cf602345..157d69e83ff4 100644 --- a/drivers/md/raid10.h +++ b/drivers/md/raid10.h | |||
@@ -33,6 +33,11 @@ struct r10conf { | |||
33 | * far_offset, in which case it is | 33 | * far_offset, in which case it is |
34 | * 1 stripe. | 34 | * 1 stripe. |
35 | */ | 35 | */ |
36 | int far_set_size; /* The number of devices in a set, | ||
37 | * where a 'set' are devices that | ||
38 | * contain far/offset copies of | ||
39 | * each other. | ||
40 | */ | ||
36 | int chunk_shift; /* shift from chunks to sectors */ | 41 | int chunk_shift; /* shift from chunks to sectors */ |
37 | sector_t chunk_mask; | 42 | sector_t chunk_mask; |
38 | } prev, geo; | 43 | } prev, geo; |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5af2d2709081..24909eb13fec 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
@@ -671,9 +671,11 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) | |||
671 | bi->bi_next = NULL; | 671 | bi->bi_next = NULL; |
672 | if (rrdev) | 672 | if (rrdev) |
673 | set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags); | 673 | set_bit(R5_DOUBLE_LOCKED, &sh->dev[i].flags); |
674 | trace_block_bio_remap(bdev_get_queue(bi->bi_bdev), | 674 | |
675 | bi, disk_devt(conf->mddev->gendisk), | 675 | if (conf->mddev->gendisk) |
676 | sh->dev[i].sector); | 676 | trace_block_bio_remap(bdev_get_queue(bi->bi_bdev), |
677 | bi, disk_devt(conf->mddev->gendisk), | ||
678 | sh->dev[i].sector); | ||
677 | generic_make_request(bi); | 679 | generic_make_request(bi); |
678 | } | 680 | } |
679 | if (rrdev) { | 681 | if (rrdev) { |
@@ -701,9 +703,10 @@ static void ops_run_io(struct stripe_head *sh, struct stripe_head_state *s) | |||
701 | rbi->bi_io_vec[0].bv_offset = 0; | 703 | rbi->bi_io_vec[0].bv_offset = 0; |
702 | rbi->bi_size = STRIPE_SIZE; | 704 | rbi->bi_size = STRIPE_SIZE; |
703 | rbi->bi_next = NULL; | 705 | rbi->bi_next = NULL; |
704 | trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev), | 706 | if (conf->mddev->gendisk) |
705 | rbi, disk_devt(conf->mddev->gendisk), | 707 | trace_block_bio_remap(bdev_get_queue(rbi->bi_bdev), |
706 | sh->dev[i].sector); | 708 | rbi, disk_devt(conf->mddev->gendisk), |
709 | sh->dev[i].sector); | ||
707 | generic_make_request(rbi); | 710 | generic_make_request(rbi); |
708 | } | 711 | } |
709 | if (!rdev && !rrdev) { | 712 | if (!rdev && !rrdev) { |
@@ -1403,7 +1406,7 @@ static void ops_run_check_pq(struct stripe_head *sh, struct raid5_percpu *percpu | |||
1403 | &sh->ops.zero_sum_result, percpu->spare_page, &submit); | 1406 | &sh->ops.zero_sum_result, percpu->spare_page, &submit); |
1404 | } | 1407 | } |
1405 | 1408 | ||
1406 | static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request) | 1409 | static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) |
1407 | { | 1410 | { |
1408 | int overlap_clear = 0, i, disks = sh->disks; | 1411 | int overlap_clear = 0, i, disks = sh->disks; |
1409 | struct dma_async_tx_descriptor *tx = NULL; | 1412 | struct dma_async_tx_descriptor *tx = NULL; |
@@ -1468,36 +1471,6 @@ static void __raid_run_ops(struct stripe_head *sh, unsigned long ops_request) | |||
1468 | put_cpu(); | 1471 | put_cpu(); |
1469 | } | 1472 | } |
1470 | 1473 | ||
1471 | #ifdef CONFIG_MULTICORE_RAID456 | ||
1472 | static void async_run_ops(void *param, async_cookie_t cookie) | ||
1473 | { | ||
1474 | struct stripe_head *sh = param; | ||
1475 | unsigned long ops_request = sh->ops.request; | ||
1476 | |||
1477 | clear_bit_unlock(STRIPE_OPS_REQ_PENDING, &sh->state); | ||
1478 | wake_up(&sh->ops.wait_for_ops); | ||
1479 | |||
1480 | __raid_run_ops(sh, ops_request); | ||
1481 | release_stripe(sh); | ||
1482 | } | ||
1483 | |||
1484 | static void raid_run_ops(struct stripe_head *sh, unsigned long ops_request) | ||
1485 | { | ||
1486 | /* since handle_stripe can be called outside of raid5d context | ||
1487 | * we need to ensure sh->ops.request is de-staged before another | ||
1488 | * request arrives | ||
1489 | */ | ||
1490 | wait_event(sh->ops.wait_for_ops, | ||
1491 | !test_and_set_bit_lock(STRIPE_OPS_REQ_PENDING, &sh->state)); | ||
1492 | sh->ops.request = ops_request; | ||
1493 | |||
1494 | atomic_inc(&sh->count); | ||
1495 | async_schedule(async_run_ops, sh); | ||
1496 | } | ||
1497 | #else | ||
1498 | #define raid_run_ops __raid_run_ops | ||
1499 | #endif | ||
1500 | |||
1501 | static int grow_one_stripe(struct r5conf *conf) | 1474 | static int grow_one_stripe(struct r5conf *conf) |
1502 | { | 1475 | { |
1503 | struct stripe_head *sh; | 1476 | struct stripe_head *sh; |
@@ -1506,9 +1479,6 @@ static int grow_one_stripe(struct r5conf *conf) | |||
1506 | return 0; | 1479 | return 0; |
1507 | 1480 | ||
1508 | sh->raid_conf = conf; | 1481 | sh->raid_conf = conf; |
1509 | #ifdef CONFIG_MULTICORE_RAID456 | ||
1510 | init_waitqueue_head(&sh->ops.wait_for_ops); | ||
1511 | #endif | ||
1512 | 1482 | ||
1513 | spin_lock_init(&sh->stripe_lock); | 1483 | spin_lock_init(&sh->stripe_lock); |
1514 | 1484 | ||
@@ -1627,9 +1597,6 @@ static int resize_stripes(struct r5conf *conf, int newsize) | |||
1627 | break; | 1597 | break; |
1628 | 1598 | ||
1629 | nsh->raid_conf = conf; | 1599 | nsh->raid_conf = conf; |
1630 | #ifdef CONFIG_MULTICORE_RAID456 | ||
1631 | init_waitqueue_head(&nsh->ops.wait_for_ops); | ||
1632 | #endif | ||
1633 | spin_lock_init(&nsh->stripe_lock); | 1600 | spin_lock_init(&nsh->stripe_lock); |
1634 | 1601 | ||
1635 | list_add(&nsh->lru, &newstripes); | 1602 | list_add(&nsh->lru, &newstripes); |
@@ -2316,17 +2283,6 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s, | |||
2316 | int level = conf->level; | 2283 | int level = conf->level; |
2317 | 2284 | ||
2318 | if (rcw) { | 2285 | if (rcw) { |
2319 | /* if we are not expanding this is a proper write request, and | ||
2320 | * there will be bios with new data to be drained into the | ||
2321 | * stripe cache | ||
2322 | */ | ||
2323 | if (!expand) { | ||
2324 | sh->reconstruct_state = reconstruct_state_drain_run; | ||
2325 | set_bit(STRIPE_OP_BIODRAIN, &s->ops_request); | ||
2326 | } else | ||
2327 | sh->reconstruct_state = reconstruct_state_run; | ||
2328 | |||
2329 | set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request); | ||
2330 | 2286 | ||
2331 | for (i = disks; i--; ) { | 2287 | for (i = disks; i--; ) { |
2332 | struct r5dev *dev = &sh->dev[i]; | 2288 | struct r5dev *dev = &sh->dev[i]; |
@@ -2339,6 +2295,21 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s, | |||
2339 | s->locked++; | 2295 | s->locked++; |
2340 | } | 2296 | } |
2341 | } | 2297 | } |
2298 | /* if we are not expanding this is a proper write request, and | ||
2299 | * there will be bios with new data to be drained into the | ||
2300 | * stripe cache | ||
2301 | */ | ||
2302 | if (!expand) { | ||
2303 | if (!s->locked) | ||
2304 | /* False alarm, nothing to do */ | ||
2305 | return; | ||
2306 | sh->reconstruct_state = reconstruct_state_drain_run; | ||
2307 | set_bit(STRIPE_OP_BIODRAIN, &s->ops_request); | ||
2308 | } else | ||
2309 | sh->reconstruct_state = reconstruct_state_run; | ||
2310 | |||
2311 | set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request); | ||
2312 | |||
2342 | if (s->locked + conf->max_degraded == disks) | 2313 | if (s->locked + conf->max_degraded == disks) |
2343 | if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state)) | 2314 | if (!test_and_set_bit(STRIPE_FULL_WRITE, &sh->state)) |
2344 | atomic_inc(&conf->pending_full_writes); | 2315 | atomic_inc(&conf->pending_full_writes); |
@@ -2347,11 +2318,6 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s, | |||
2347 | BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) || | 2318 | BUG_ON(!(test_bit(R5_UPTODATE, &sh->dev[pd_idx].flags) || |
2348 | test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags))); | 2319 | test_bit(R5_Wantcompute, &sh->dev[pd_idx].flags))); |
2349 | 2320 | ||
2350 | sh->reconstruct_state = reconstruct_state_prexor_drain_run; | ||
2351 | set_bit(STRIPE_OP_PREXOR, &s->ops_request); | ||
2352 | set_bit(STRIPE_OP_BIODRAIN, &s->ops_request); | ||
2353 | set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request); | ||
2354 | |||
2355 | for (i = disks; i--; ) { | 2321 | for (i = disks; i--; ) { |
2356 | struct r5dev *dev = &sh->dev[i]; | 2322 | struct r5dev *dev = &sh->dev[i]; |
2357 | if (i == pd_idx) | 2323 | if (i == pd_idx) |
@@ -2366,6 +2332,13 @@ schedule_reconstruction(struct stripe_head *sh, struct stripe_head_state *s, | |||
2366 | s->locked++; | 2332 | s->locked++; |
2367 | } | 2333 | } |
2368 | } | 2334 | } |
2335 | if (!s->locked) | ||
2336 | /* False alarm - nothing to do */ | ||
2337 | return; | ||
2338 | sh->reconstruct_state = reconstruct_state_prexor_drain_run; | ||
2339 | set_bit(STRIPE_OP_PREXOR, &s->ops_request); | ||
2340 | set_bit(STRIPE_OP_BIODRAIN, &s->ops_request); | ||
2341 | set_bit(STRIPE_OP_RECONSTRUCT, &s->ops_request); | ||
2369 | } | 2342 | } |
2370 | 2343 | ||
2371 | /* keep the parity disk(s) locked while asynchronous operations | 2344 | /* keep the parity disk(s) locked while asynchronous operations |
@@ -2600,6 +2573,8 @@ handle_failed_sync(struct r5conf *conf, struct stripe_head *sh, | |||
2600 | int i; | 2573 | int i; |
2601 | 2574 | ||
2602 | clear_bit(STRIPE_SYNCING, &sh->state); | 2575 | clear_bit(STRIPE_SYNCING, &sh->state); |
2576 | if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags)) | ||
2577 | wake_up(&conf->wait_for_overlap); | ||
2603 | s->syncing = 0; | 2578 | s->syncing = 0; |
2604 | s->replacing = 0; | 2579 | s->replacing = 0; |
2605 | /* There is nothing more to do for sync/check/repair. | 2580 | /* There is nothing more to do for sync/check/repair. |
@@ -2773,6 +2748,7 @@ static void handle_stripe_clean_event(struct r5conf *conf, | |||
2773 | { | 2748 | { |
2774 | int i; | 2749 | int i; |
2775 | struct r5dev *dev; | 2750 | struct r5dev *dev; |
2751 | int discard_pending = 0; | ||
2776 | 2752 | ||
2777 | for (i = disks; i--; ) | 2753 | for (i = disks; i--; ) |
2778 | if (sh->dev[i].written) { | 2754 | if (sh->dev[i].written) { |
@@ -2801,9 +2777,23 @@ static void handle_stripe_clean_event(struct r5conf *conf, | |||
2801 | STRIPE_SECTORS, | 2777 | STRIPE_SECTORS, |
2802 | !test_bit(STRIPE_DEGRADED, &sh->state), | 2778 | !test_bit(STRIPE_DEGRADED, &sh->state), |
2803 | 0); | 2779 | 0); |
2804 | } | 2780 | } else if (test_bit(R5_Discard, &dev->flags)) |
2805 | } else if (test_bit(R5_Discard, &sh->dev[i].flags)) | 2781 | discard_pending = 1; |
2806 | clear_bit(R5_Discard, &sh->dev[i].flags); | 2782 | } |
2783 | if (!discard_pending && | ||
2784 | test_bit(R5_Discard, &sh->dev[sh->pd_idx].flags)) { | ||
2785 | clear_bit(R5_Discard, &sh->dev[sh->pd_idx].flags); | ||
2786 | clear_bit(R5_UPTODATE, &sh->dev[sh->pd_idx].flags); | ||
2787 | if (sh->qd_idx >= 0) { | ||
2788 | clear_bit(R5_Discard, &sh->dev[sh->qd_idx].flags); | ||
2789 | clear_bit(R5_UPTODATE, &sh->dev[sh->qd_idx].flags); | ||
2790 | } | ||
2791 | /* now that discard is done we can proceed with any sync */ | ||
2792 | clear_bit(STRIPE_DISCARD, &sh->state); | ||
2793 | if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) | ||
2794 | set_bit(STRIPE_HANDLE, &sh->state); | ||
2795 | |||
2796 | } | ||
2807 | 2797 | ||
2808 | if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) | 2798 | if (test_and_clear_bit(STRIPE_FULL_WRITE, &sh->state)) |
2809 | if (atomic_dec_and_test(&conf->pending_full_writes)) | 2799 | if (atomic_dec_and_test(&conf->pending_full_writes)) |
@@ -2862,8 +2852,10 @@ static void handle_stripe_dirtying(struct r5conf *conf, | |||
2862 | set_bit(STRIPE_HANDLE, &sh->state); | 2852 | set_bit(STRIPE_HANDLE, &sh->state); |
2863 | if (rmw < rcw && rmw > 0) { | 2853 | if (rmw < rcw && rmw > 0) { |
2864 | /* prefer read-modify-write, but need to get some data */ | 2854 | /* prefer read-modify-write, but need to get some data */ |
2865 | blk_add_trace_msg(conf->mddev->queue, "raid5 rmw %llu %d", | 2855 | if (conf->mddev->queue) |
2866 | (unsigned long long)sh->sector, rmw); | 2856 | blk_add_trace_msg(conf->mddev->queue, |
2857 | "raid5 rmw %llu %d", | ||
2858 | (unsigned long long)sh->sector, rmw); | ||
2867 | for (i = disks; i--; ) { | 2859 | for (i = disks; i--; ) { |
2868 | struct r5dev *dev = &sh->dev[i]; | 2860 | struct r5dev *dev = &sh->dev[i]; |
2869 | if ((dev->towrite || i == sh->pd_idx) && | 2861 | if ((dev->towrite || i == sh->pd_idx) && |
@@ -2913,7 +2905,7 @@ static void handle_stripe_dirtying(struct r5conf *conf, | |||
2913 | } | 2905 | } |
2914 | } | 2906 | } |
2915 | } | 2907 | } |
2916 | if (rcw) | 2908 | if (rcw && conf->mddev->queue) |
2917 | blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d", | 2909 | blk_add_trace_msg(conf->mddev->queue, "raid5 rcw %llu %d %d %d", |
2918 | (unsigned long long)sh->sector, | 2910 | (unsigned long long)sh->sector, |
2919 | rcw, qread, test_bit(STRIPE_DELAYED, &sh->state)); | 2911 | rcw, qread, test_bit(STRIPE_DELAYED, &sh->state)); |
@@ -3453,9 +3445,15 @@ static void handle_stripe(struct stripe_head *sh) | |||
3453 | return; | 3445 | return; |
3454 | } | 3446 | } |
3455 | 3447 | ||
3456 | if (test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) { | 3448 | if (test_bit(STRIPE_SYNC_REQUESTED, &sh->state)) { |
3457 | set_bit(STRIPE_SYNCING, &sh->state); | 3449 | spin_lock(&sh->stripe_lock); |
3458 | clear_bit(STRIPE_INSYNC, &sh->state); | 3450 | /* Cannot process 'sync' concurrently with 'discard' */ |
3451 | if (!test_bit(STRIPE_DISCARD, &sh->state) && | ||
3452 | test_and_clear_bit(STRIPE_SYNC_REQUESTED, &sh->state)) { | ||
3453 | set_bit(STRIPE_SYNCING, &sh->state); | ||
3454 | clear_bit(STRIPE_INSYNC, &sh->state); | ||
3455 | } | ||
3456 | spin_unlock(&sh->stripe_lock); | ||
3459 | } | 3457 | } |
3460 | clear_bit(STRIPE_DELAYED, &sh->state); | 3458 | clear_bit(STRIPE_DELAYED, &sh->state); |
3461 | 3459 | ||
@@ -3615,6 +3613,8 @@ static void handle_stripe(struct stripe_head *sh) | |||
3615 | test_bit(STRIPE_INSYNC, &sh->state)) { | 3613 | test_bit(STRIPE_INSYNC, &sh->state)) { |
3616 | md_done_sync(conf->mddev, STRIPE_SECTORS, 1); | 3614 | md_done_sync(conf->mddev, STRIPE_SECTORS, 1); |
3617 | clear_bit(STRIPE_SYNCING, &sh->state); | 3615 | clear_bit(STRIPE_SYNCING, &sh->state); |
3616 | if (test_and_clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags)) | ||
3617 | wake_up(&conf->wait_for_overlap); | ||
3618 | } | 3618 | } |
3619 | 3619 | ||
3620 | /* If the failed drives are just a ReadError, then we might need | 3620 | /* If the failed drives are just a ReadError, then we might need |
@@ -4018,9 +4018,10 @@ static int chunk_aligned_read(struct mddev *mddev, struct bio * raid_bio) | |||
4018 | atomic_inc(&conf->active_aligned_reads); | 4018 | atomic_inc(&conf->active_aligned_reads); |
4019 | spin_unlock_irq(&conf->device_lock); | 4019 | spin_unlock_irq(&conf->device_lock); |
4020 | 4020 | ||
4021 | trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev), | 4021 | if (mddev->gendisk) |
4022 | align_bi, disk_devt(mddev->gendisk), | 4022 | trace_block_bio_remap(bdev_get_queue(align_bi->bi_bdev), |
4023 | raid_bio->bi_sector); | 4023 | align_bi, disk_devt(mddev->gendisk), |
4024 | raid_bio->bi_sector); | ||
4024 | generic_make_request(align_bi); | 4025 | generic_make_request(align_bi); |
4025 | return 1; | 4026 | return 1; |
4026 | } else { | 4027 | } else { |
@@ -4114,7 +4115,8 @@ static void raid5_unplug(struct blk_plug_cb *blk_cb, bool from_schedule) | |||
4114 | } | 4115 | } |
4115 | spin_unlock_irq(&conf->device_lock); | 4116 | spin_unlock_irq(&conf->device_lock); |
4116 | } | 4117 | } |
4117 | trace_block_unplug(mddev->queue, cnt, !from_schedule); | 4118 | if (mddev->queue) |
4119 | trace_block_unplug(mddev->queue, cnt, !from_schedule); | ||
4118 | kfree(cb); | 4120 | kfree(cb); |
4119 | } | 4121 | } |
4120 | 4122 | ||
@@ -4177,6 +4179,13 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi) | |||
4177 | sh = get_active_stripe(conf, logical_sector, 0, 0, 0); | 4179 | sh = get_active_stripe(conf, logical_sector, 0, 0, 0); |
4178 | prepare_to_wait(&conf->wait_for_overlap, &w, | 4180 | prepare_to_wait(&conf->wait_for_overlap, &w, |
4179 | TASK_UNINTERRUPTIBLE); | 4181 | TASK_UNINTERRUPTIBLE); |
4182 | set_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags); | ||
4183 | if (test_bit(STRIPE_SYNCING, &sh->state)) { | ||
4184 | release_stripe(sh); | ||
4185 | schedule(); | ||
4186 | goto again; | ||
4187 | } | ||
4188 | clear_bit(R5_Overlap, &sh->dev[sh->pd_idx].flags); | ||
4180 | spin_lock_irq(&sh->stripe_lock); | 4189 | spin_lock_irq(&sh->stripe_lock); |
4181 | for (d = 0; d < conf->raid_disks; d++) { | 4190 | for (d = 0; d < conf->raid_disks; d++) { |
4182 | if (d == sh->pd_idx || d == sh->qd_idx) | 4191 | if (d == sh->pd_idx || d == sh->qd_idx) |
@@ -4189,6 +4198,7 @@ static void make_discard_request(struct mddev *mddev, struct bio *bi) | |||
4189 | goto again; | 4198 | goto again; |
4190 | } | 4199 | } |
4191 | } | 4200 | } |
4201 | set_bit(STRIPE_DISCARD, &sh->state); | ||
4192 | finish_wait(&conf->wait_for_overlap, &w); | 4202 | finish_wait(&conf->wait_for_overlap, &w); |
4193 | for (d = 0; d < conf->raid_disks; d++) { | 4203 | for (d = 0; d < conf->raid_disks; d++) { |
4194 | if (d == sh->pd_idx || d == sh->qd_idx) | 4204 | if (d == sh->pd_idx || d == sh->qd_idx) |
diff --git a/drivers/md/raid5.h b/drivers/md/raid5.h index 18b2c4a8a1fd..b0b663b119a8 100644 --- a/drivers/md/raid5.h +++ b/drivers/md/raid5.h | |||
@@ -221,10 +221,6 @@ struct stripe_head { | |||
221 | struct stripe_operations { | 221 | struct stripe_operations { |
222 | int target, target2; | 222 | int target, target2; |
223 | enum sum_check_flags zero_sum_result; | 223 | enum sum_check_flags zero_sum_result; |
224 | #ifdef CONFIG_MULTICORE_RAID456 | ||
225 | unsigned long request; | ||
226 | wait_queue_head_t wait_for_ops; | ||
227 | #endif | ||
228 | } ops; | 224 | } ops; |
229 | struct r5dev { | 225 | struct r5dev { |
230 | /* rreq and rvec are used for the replacement device when | 226 | /* rreq and rvec are used for the replacement device when |
@@ -323,6 +319,7 @@ enum { | |||
323 | STRIPE_COMPUTE_RUN, | 319 | STRIPE_COMPUTE_RUN, |
324 | STRIPE_OPS_REQ_PENDING, | 320 | STRIPE_OPS_REQ_PENDING, |
325 | STRIPE_ON_UNPLUG_LIST, | 321 | STRIPE_ON_UNPLUG_LIST, |
322 | STRIPE_DISCARD, | ||
326 | }; | 323 | }; |
327 | 324 | ||
328 | /* | 325 | /* |
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index d4e7567b367c..0b899cb6cda1 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c | |||
@@ -724,7 +724,7 @@ static int m5mols_s_stream(struct v4l2_subdev *sd, int enable) | |||
724 | if (enable) { | 724 | if (enable) { |
725 | if (is_code(code, M5MOLS_RESTYPE_MONITOR)) | 725 | if (is_code(code, M5MOLS_RESTYPE_MONITOR)) |
726 | ret = m5mols_start_monitor(info); | 726 | ret = m5mols_start_monitor(info); |
727 | if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) | 727 | else if (is_code(code, M5MOLS_RESTYPE_CAPTURE)) |
728 | ret = m5mols_start_capture(info); | 728 | ret = m5mols_start_capture(info); |
729 | else | 729 | else |
730 | ret = -EINVAL; | 730 | ret = -EINVAL; |
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c index ccd18e4ee789..54579e4c740b 100644 --- a/drivers/media/pci/bt8xx/bttv-driver.c +++ b/drivers/media/pci/bt8xx/bttv-driver.c | |||
@@ -250,17 +250,19 @@ static u8 SRAM_Table[][60] = | |||
250 | vdelay start of active video in 2 * field lines relative to | 250 | vdelay start of active video in 2 * field lines relative to |
251 | trailing edge of /VRESET pulse (VDELAY register). | 251 | trailing edge of /VRESET pulse (VDELAY register). |
252 | sheight height of active video in 2 * field lines. | 252 | sheight height of active video in 2 * field lines. |
253 | extraheight Added to sheight for cropcap.bounds.height only | ||
253 | videostart0 ITU-R frame line number of the line corresponding | 254 | videostart0 ITU-R frame line number of the line corresponding |
254 | to vdelay in the first field. */ | 255 | to vdelay in the first field. */ |
255 | #define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \ | 256 | #define CROPCAP(minhdelayx1, hdelayx1, swidth, totalwidth, sqwidth, \ |
256 | vdelay, sheight, videostart0) \ | 257 | vdelay, sheight, extraheight, videostart0) \ |
257 | .cropcap.bounds.left = minhdelayx1, \ | 258 | .cropcap.bounds.left = minhdelayx1, \ |
258 | /* * 2 because vertically we count field lines times two, */ \ | 259 | /* * 2 because vertically we count field lines times two, */ \ |
259 | /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \ | 260 | /* e.g. 23 * 2 to 23 * 2 + 576 in PAL-BGHI defrect. */ \ |
260 | .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \ | 261 | .cropcap.bounds.top = (videostart0) * 2 - (vdelay) + MIN_VDELAY, \ |
261 | /* 4 is a safety margin at the end of the line. */ \ | 262 | /* 4 is a safety margin at the end of the line. */ \ |
262 | .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \ | 263 | .cropcap.bounds.width = (totalwidth) - (minhdelayx1) - 4, \ |
263 | .cropcap.bounds.height = (sheight) + (vdelay) - MIN_VDELAY, \ | 264 | .cropcap.bounds.height = (sheight) + (extraheight) + (vdelay) - \ |
265 | MIN_VDELAY, \ | ||
264 | .cropcap.defrect.left = hdelayx1, \ | 266 | .cropcap.defrect.left = hdelayx1, \ |
265 | .cropcap.defrect.top = (videostart0) * 2, \ | 267 | .cropcap.defrect.top = (videostart0) * 2, \ |
266 | .cropcap.defrect.width = swidth, \ | 268 | .cropcap.defrect.width = swidth, \ |
@@ -301,9 +303,10 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
301 | /* totalwidth */ 1135, | 303 | /* totalwidth */ 1135, |
302 | /* sqwidth */ 944, | 304 | /* sqwidth */ 944, |
303 | /* vdelay */ 0x20, | 305 | /* vdelay */ 0x20, |
304 | /* bt878 (and bt848?) can capture another | 306 | /* sheight */ 576, |
305 | line below active video. */ | 307 | /* bt878 (and bt848?) can capture another |
306 | /* sheight */ (576 + 2) + 0x20 - 2, | 308 | line below active video. */ |
309 | /* extraheight */ 2, | ||
307 | /* videostart0 */ 23) | 310 | /* videostart0 */ 23) |
308 | },{ | 311 | },{ |
309 | .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, | 312 | .v4l2_id = V4L2_STD_NTSC_M | V4L2_STD_NTSC_M_KR, |
@@ -330,6 +333,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
330 | /* sqwidth */ 780, | 333 | /* sqwidth */ 780, |
331 | /* vdelay */ 0x1a, | 334 | /* vdelay */ 0x1a, |
332 | /* sheight */ 480, | 335 | /* sheight */ 480, |
336 | /* extraheight */ 0, | ||
333 | /* videostart0 */ 23) | 337 | /* videostart0 */ 23) |
334 | },{ | 338 | },{ |
335 | .v4l2_id = V4L2_STD_SECAM, | 339 | .v4l2_id = V4L2_STD_SECAM, |
@@ -355,6 +359,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
355 | /* sqwidth */ 944, | 359 | /* sqwidth */ 944, |
356 | /* vdelay */ 0x20, | 360 | /* vdelay */ 0x20, |
357 | /* sheight */ 576, | 361 | /* sheight */ 576, |
362 | /* extraheight */ 0, | ||
358 | /* videostart0 */ 23) | 363 | /* videostart0 */ 23) |
359 | },{ | 364 | },{ |
360 | .v4l2_id = V4L2_STD_PAL_Nc, | 365 | .v4l2_id = V4L2_STD_PAL_Nc, |
@@ -380,6 +385,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
380 | /* sqwidth */ 780, | 385 | /* sqwidth */ 780, |
381 | /* vdelay */ 0x1a, | 386 | /* vdelay */ 0x1a, |
382 | /* sheight */ 576, | 387 | /* sheight */ 576, |
388 | /* extraheight */ 0, | ||
383 | /* videostart0 */ 23) | 389 | /* videostart0 */ 23) |
384 | },{ | 390 | },{ |
385 | .v4l2_id = V4L2_STD_PAL_M, | 391 | .v4l2_id = V4L2_STD_PAL_M, |
@@ -405,6 +411,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
405 | /* sqwidth */ 780, | 411 | /* sqwidth */ 780, |
406 | /* vdelay */ 0x1a, | 412 | /* vdelay */ 0x1a, |
407 | /* sheight */ 480, | 413 | /* sheight */ 480, |
414 | /* extraheight */ 0, | ||
408 | /* videostart0 */ 23) | 415 | /* videostart0 */ 23) |
409 | },{ | 416 | },{ |
410 | .v4l2_id = V4L2_STD_PAL_N, | 417 | .v4l2_id = V4L2_STD_PAL_N, |
@@ -430,6 +437,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
430 | /* sqwidth */ 944, | 437 | /* sqwidth */ 944, |
431 | /* vdelay */ 0x20, | 438 | /* vdelay */ 0x20, |
432 | /* sheight */ 576, | 439 | /* sheight */ 576, |
440 | /* extraheight */ 0, | ||
433 | /* videostart0 */ 23) | 441 | /* videostart0 */ 23) |
434 | },{ | 442 | },{ |
435 | .v4l2_id = V4L2_STD_NTSC_M_JP, | 443 | .v4l2_id = V4L2_STD_NTSC_M_JP, |
@@ -455,6 +463,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
455 | /* sqwidth */ 780, | 463 | /* sqwidth */ 780, |
456 | /* vdelay */ 0x16, | 464 | /* vdelay */ 0x16, |
457 | /* sheight */ 480, | 465 | /* sheight */ 480, |
466 | /* extraheight */ 0, | ||
458 | /* videostart0 */ 23) | 467 | /* videostart0 */ 23) |
459 | },{ | 468 | },{ |
460 | /* that one hopefully works with the strange timing | 469 | /* that one hopefully works with the strange timing |
@@ -484,6 +493,7 @@ const struct bttv_tvnorm bttv_tvnorms[] = { | |||
484 | /* sqwidth */ 944, | 493 | /* sqwidth */ 944, |
485 | /* vdelay */ 0x1a, | 494 | /* vdelay */ 0x1a, |
486 | /* sheight */ 480, | 495 | /* sheight */ 480, |
496 | /* extraheight */ 0, | ||
487 | /* videostart0 */ 23) | 497 | /* videostart0 */ 23) |
488 | } | 498 | } |
489 | }; | 499 | }; |
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c index 82d9f6ac12f3..33b5ffc8d66d 100644 --- a/drivers/media/platform/exynos-gsc/gsc-core.c +++ b/drivers/media/platform/exynos-gsc/gsc-core.c | |||
@@ -1054,16 +1054,18 @@ static int gsc_m2m_suspend(struct gsc_dev *gsc) | |||
1054 | 1054 | ||
1055 | static int gsc_m2m_resume(struct gsc_dev *gsc) | 1055 | static int gsc_m2m_resume(struct gsc_dev *gsc) |
1056 | { | 1056 | { |
1057 | struct gsc_ctx *ctx; | ||
1057 | unsigned long flags; | 1058 | unsigned long flags; |
1058 | 1059 | ||
1059 | spin_lock_irqsave(&gsc->slock, flags); | 1060 | spin_lock_irqsave(&gsc->slock, flags); |
1060 | /* Clear for full H/W setup in first run after resume */ | 1061 | /* Clear for full H/W setup in first run after resume */ |
1062 | ctx = gsc->m2m.ctx; | ||
1061 | gsc->m2m.ctx = NULL; | 1063 | gsc->m2m.ctx = NULL; |
1062 | spin_unlock_irqrestore(&gsc->slock, flags); | 1064 | spin_unlock_irqrestore(&gsc->slock, flags); |
1063 | 1065 | ||
1064 | if (test_and_clear_bit(ST_M2M_SUSPENDED, &gsc->state)) | 1066 | if (test_and_clear_bit(ST_M2M_SUSPENDED, &gsc->state)) |
1065 | gsc_m2m_job_finish(gsc->m2m.ctx, | 1067 | gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); |
1066 | VB2_BUF_STATE_ERROR); | 1068 | |
1067 | return 0; | 1069 | return 0; |
1068 | } | 1070 | } |
1069 | 1071 | ||
@@ -1204,7 +1206,7 @@ static int gsc_resume(struct device *dev) | |||
1204 | /* Do not resume if the device was idle before system suspend */ | 1206 | /* Do not resume if the device was idle before system suspend */ |
1205 | spin_lock_irqsave(&gsc->slock, flags); | 1207 | spin_lock_irqsave(&gsc->slock, flags); |
1206 | if (!test_and_clear_bit(ST_SUSPEND, &gsc->state) || | 1208 | if (!test_and_clear_bit(ST_SUSPEND, &gsc->state) || |
1207 | !gsc_m2m_active(gsc)) { | 1209 | !gsc_m2m_opened(gsc)) { |
1208 | spin_unlock_irqrestore(&gsc->slock, flags); | 1210 | spin_unlock_irqrestore(&gsc->slock, flags); |
1209 | return 0; | 1211 | return 0; |
1210 | } | 1212 | } |
diff --git a/drivers/media/platform/s5p-fimc/fimc-core.c b/drivers/media/platform/s5p-fimc/fimc-core.c index e3916bde45cf..0f513dd19f86 100644 --- a/drivers/media/platform/s5p-fimc/fimc-core.c +++ b/drivers/media/platform/s5p-fimc/fimc-core.c | |||
@@ -850,16 +850,18 @@ static int fimc_m2m_suspend(struct fimc_dev *fimc) | |||
850 | 850 | ||
851 | static int fimc_m2m_resume(struct fimc_dev *fimc) | 851 | static int fimc_m2m_resume(struct fimc_dev *fimc) |
852 | { | 852 | { |
853 | struct fimc_ctx *ctx; | ||
853 | unsigned long flags; | 854 | unsigned long flags; |
854 | 855 | ||
855 | spin_lock_irqsave(&fimc->slock, flags); | 856 | spin_lock_irqsave(&fimc->slock, flags); |
856 | /* Clear for full H/W setup in first run after resume */ | 857 | /* Clear for full H/W setup in first run after resume */ |
858 | ctx = fimc->m2m.ctx; | ||
857 | fimc->m2m.ctx = NULL; | 859 | fimc->m2m.ctx = NULL; |
858 | spin_unlock_irqrestore(&fimc->slock, flags); | 860 | spin_unlock_irqrestore(&fimc->slock, flags); |
859 | 861 | ||
860 | if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state)) | 862 | if (test_and_clear_bit(ST_M2M_SUSPENDED, &fimc->state)) |
861 | fimc_m2m_job_finish(fimc->m2m.ctx, | 863 | fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR); |
862 | VB2_BUF_STATE_ERROR); | 864 | |
863 | return 0; | 865 | return 0; |
864 | } | 866 | } |
865 | 867 | ||
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite-reg.c b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c index f0af0754a7b4..ac9663ce2a49 100644 --- a/drivers/media/platform/s5p-fimc/fimc-lite-reg.c +++ b/drivers/media/platform/s5p-fimc/fimc-lite-reg.c | |||
@@ -128,10 +128,10 @@ static const u32 src_pixfmt_map[8][3] = { | |||
128 | void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f) | 128 | void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f) |
129 | { | 129 | { |
130 | enum v4l2_mbus_pixelcode pixelcode = dev->fmt->mbus_code; | 130 | enum v4l2_mbus_pixelcode pixelcode = dev->fmt->mbus_code; |
131 | unsigned int i = ARRAY_SIZE(src_pixfmt_map); | 131 | int i = ARRAY_SIZE(src_pixfmt_map); |
132 | u32 cfg; | 132 | u32 cfg; |
133 | 133 | ||
134 | while (i-- >= 0) { | 134 | while (--i >= 0) { |
135 | if (src_pixfmt_map[i][0] == pixelcode) | 135 | if (src_pixfmt_map[i][0] == pixelcode) |
136 | break; | 136 | break; |
137 | } | 137 | } |
@@ -224,9 +224,9 @@ static void flite_hw_set_out_order(struct fimc_lite *dev, struct flite_frame *f) | |||
224 | { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY }, | 224 | { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CIODMAFMT_CRYCBY }, |
225 | }; | 225 | }; |
226 | u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT); | 226 | u32 cfg = readl(dev->regs + FLITE_REG_CIODMAFMT); |
227 | unsigned int i = ARRAY_SIZE(pixcode); | 227 | int i = ARRAY_SIZE(pixcode); |
228 | 228 | ||
229 | while (i-- >= 0) | 229 | while (--i >= 0) |
230 | if (pixcode[i][0] == dev->fmt->mbus_code) | 230 | if (pixcode[i][0] == dev->fmt->mbus_code) |
231 | break; | 231 | break; |
232 | cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK; | 232 | cfg &= ~FLITE_REG_CIODMAFMT_YCBCR_ORDER_MASK; |
diff --git a/drivers/media/platform/s5p-fimc/fimc-lite.c b/drivers/media/platform/s5p-fimc/fimc-lite.c index bfc4206935c8..bbc35de7db27 100644 --- a/drivers/media/platform/s5p-fimc/fimc-lite.c +++ b/drivers/media/platform/s5p-fimc/fimc-lite.c | |||
@@ -1408,6 +1408,7 @@ static const struct v4l2_ctrl_config fimc_lite_ctrl = { | |||
1408 | .id = V4L2_CTRL_CLASS_USER | 0x1001, | 1408 | .id = V4L2_CTRL_CLASS_USER | 0x1001, |
1409 | .type = V4L2_CTRL_TYPE_BOOLEAN, | 1409 | .type = V4L2_CTRL_TYPE_BOOLEAN, |
1410 | .name = "Test Pattern 640x480", | 1410 | .name = "Test Pattern 640x480", |
1411 | .step = 1, | ||
1411 | }; | 1412 | }; |
1412 | 1413 | ||
1413 | static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc) | 1414 | static int fimc_lite_create_capture_subdev(struct fimc_lite *fimc) |
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index a17fcb2d5d41..cd38d708ab58 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c | |||
@@ -827,7 +827,7 @@ static int fimc_md_link_notify(struct media_pad *source, | |||
827 | struct fimc_pipeline *pipeline; | 827 | struct fimc_pipeline *pipeline; |
828 | struct v4l2_subdev *sd; | 828 | struct v4l2_subdev *sd; |
829 | struct mutex *lock; | 829 | struct mutex *lock; |
830 | int ret = 0; | 830 | int i, ret = 0; |
831 | int ref_count; | 831 | int ref_count; |
832 | 832 | ||
833 | if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) | 833 | if (media_entity_type(sink->entity) != MEDIA_ENT_T_V4L2_SUBDEV) |
@@ -854,29 +854,28 @@ static int fimc_md_link_notify(struct media_pad *source, | |||
854 | return 0; | 854 | return 0; |
855 | } | 855 | } |
856 | 856 | ||
857 | mutex_lock(lock); | ||
858 | ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count; | ||
859 | |||
857 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { | 860 | if (!(flags & MEDIA_LNK_FL_ENABLED)) { |
858 | int i; | 861 | if (ref_count > 0) { |
859 | mutex_lock(lock); | 862 | ret = __fimc_pipeline_close(pipeline); |
860 | ret = __fimc_pipeline_close(pipeline); | 863 | if (!ret && fimc) |
864 | fimc_ctrls_delete(fimc->vid_cap.ctx); | ||
865 | } | ||
861 | for (i = 0; i < IDX_MAX; i++) | 866 | for (i = 0; i < IDX_MAX; i++) |
862 | pipeline->subdevs[i] = NULL; | 867 | pipeline->subdevs[i] = NULL; |
863 | if (fimc) | 868 | } else if (ref_count > 0) { |
864 | fimc_ctrls_delete(fimc->vid_cap.ctx); | 869 | /* |
865 | mutex_unlock(lock); | 870 | * Link activation. Enable power of pipeline elements only if |
866 | return ret; | 871 | * the pipeline is already in use, i.e. its video node is open. |
872 | * Recreate the controls destroyed during the link deactivation. | ||
873 | */ | ||
874 | ret = __fimc_pipeline_open(pipeline, | ||
875 | source->entity, true); | ||
876 | if (!ret && fimc) | ||
877 | ret = fimc_capture_ctrls_create(fimc); | ||
867 | } | 878 | } |
868 | /* | ||
869 | * Link activation. Enable power of pipeline elements only if the | ||
870 | * pipeline is already in use, i.e. its video node is opened. | ||
871 | * Recreate the controls destroyed during the link deactivation. | ||
872 | */ | ||
873 | mutex_lock(lock); | ||
874 | |||
875 | ref_count = fimc ? fimc->vid_cap.refcnt : fimc_lite->ref_count; | ||
876 | if (ref_count > 0) | ||
877 | ret = __fimc_pipeline_open(pipeline, source->entity, true); | ||
878 | if (!ret && fimc) | ||
879 | ret = fimc_capture_ctrls_create(fimc); | ||
880 | 879 | ||
881 | mutex_unlock(lock); | 880 | mutex_unlock(lock); |
882 | return ret ? -EPIPE : ret; | 881 | return ret ? -EPIPE : ret; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index e84703c314ce..1cb6d57987c6 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -276,7 +276,7 @@ static void s5p_mfc_handle_frame_new(struct s5p_mfc_ctx *ctx, unsigned int err) | |||
276 | unsigned int frame_type; | 276 | unsigned int frame_type; |
277 | 277 | ||
278 | dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); | 278 | dspl_y_addr = s5p_mfc_hw_call(dev->mfc_ops, get_dspl_y_adr, dev); |
279 | frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_dec_frame_type, dev); | 279 | frame_type = s5p_mfc_hw_call(dev->mfc_ops, get_disp_frame_type, ctx); |
280 | 280 | ||
281 | /* If frame is same as previous then skip and do not dequeue */ | 281 | /* If frame is same as previous then skip and do not dequeue */ |
282 | if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) { | 282 | if (frame_type == S5P_FIMV_DECODE_FRAME_SKIPPED) { |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c index 2356fd52a169..4f6b553c4b2d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c | |||
@@ -232,6 +232,7 @@ static struct mfc_control controls[] = { | |||
232 | .minimum = 0, | 232 | .minimum = 0, |
233 | .maximum = 1, | 233 | .maximum = 1, |
234 | .default_value = 0, | 234 | .default_value = 0, |
235 | .step = 1, | ||
235 | .menu_skip_mask = 0, | 236 | .menu_skip_mask = 0, |
236 | }, | 237 | }, |
237 | { | 238 | { |
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig index 19f3563c61da..5a79c333d45e 100644 --- a/drivers/media/rc/Kconfig +++ b/drivers/media/rc/Kconfig | |||
@@ -291,7 +291,7 @@ config IR_TTUSBIR | |||
291 | 291 | ||
292 | config IR_RX51 | 292 | config IR_RX51 |
293 | tristate "Nokia N900 IR transmitter diode" | 293 | tristate "Nokia N900 IR transmitter diode" |
294 | depends on OMAP_DM_TIMER && LIRC && !ARCH_MULTIPLATFORM | 294 | depends on OMAP_DM_TIMER && ARCH_OMAP2PLUS && LIRC && !ARCH_MULTIPLATFORM |
295 | ---help--- | 295 | ---help--- |
296 | Say Y or M here if you want to enable support for the IR | 296 | Say Y or M here if you want to enable support for the IR |
297 | transmitter diode built in the Nokia N900 (RX51) device. | 297 | transmitter diode built in the Nokia N900 (RX51) device. |
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile index a9d355230e8e..768aaf62d5dc 100644 --- a/drivers/media/v4l2-core/Makefile +++ b/drivers/media/v4l2-core/Makefile | |||
@@ -10,7 +10,7 @@ ifeq ($(CONFIG_COMPAT),y) | |||
10 | videodev-objs += v4l2-compat-ioctl32.o | 10 | videodev-objs += v4l2-compat-ioctl32.o |
11 | endif | 11 | endif |
12 | 12 | ||
13 | obj-$(CONFIG_VIDEO_DEV) += videodev.o | 13 | obj-$(CONFIG_VIDEO_V4L2) += videodev.o |
14 | obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o | 14 | obj-$(CONFIG_VIDEO_V4L2_INT_DEVICE) += v4l2-int-device.o |
15 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o | 15 | obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o |
16 | 16 | ||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 671f5b171c73..c346941a2515 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -858,6 +858,7 @@ config EZX_PCAP | |||
858 | config AB8500_CORE | 858 | config AB8500_CORE |
859 | bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" | 859 | bool "ST-Ericsson AB8500 Mixed Signal Power Management chip" |
860 | depends on GENERIC_HARDIRQS && ABX500_CORE && MFD_DB8500_PRCMU | 860 | depends on GENERIC_HARDIRQS && ABX500_CORE && MFD_DB8500_PRCMU |
861 | select POWER_SUPPLY | ||
861 | select MFD_CORE | 862 | select MFD_CORE |
862 | select IRQ_DOMAIN | 863 | select IRQ_DOMAIN |
863 | help | 864 | help |
diff --git a/drivers/mfd/ab8500-gpadc.c b/drivers/mfd/ab8500-gpadc.c index b1f3561b023f..5f341a50ee5a 100644 --- a/drivers/mfd/ab8500-gpadc.c +++ b/drivers/mfd/ab8500-gpadc.c | |||
@@ -594,9 +594,12 @@ static int ab8500_gpadc_runtime_suspend(struct device *dev) | |||
594 | static int ab8500_gpadc_runtime_resume(struct device *dev) | 594 | static int ab8500_gpadc_runtime_resume(struct device *dev) |
595 | { | 595 | { |
596 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); | 596 | struct ab8500_gpadc *gpadc = dev_get_drvdata(dev); |
597 | int ret; | ||
597 | 598 | ||
598 | regulator_enable(gpadc->regu); | 599 | ret = regulator_enable(gpadc->regu); |
599 | return 0; | 600 | if (ret) |
601 | dev_err(dev, "Failed to enable vtvout LDO: %d\n", ret); | ||
602 | return ret; | ||
600 | } | 603 | } |
601 | 604 | ||
602 | static int ab8500_gpadc_runtime_idle(struct device *dev) | 605 | static int ab8500_gpadc_runtime_idle(struct device *dev) |
@@ -643,7 +646,7 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
643 | } | 646 | } |
644 | 647 | ||
645 | /* VTVout LDO used to power up ab8500-GPADC */ | 648 | /* VTVout LDO used to power up ab8500-GPADC */ |
646 | gpadc->regu = regulator_get(&pdev->dev, "vddadc"); | 649 | gpadc->regu = devm_regulator_get(&pdev->dev, "vddadc"); |
647 | if (IS_ERR(gpadc->regu)) { | 650 | if (IS_ERR(gpadc->regu)) { |
648 | ret = PTR_ERR(gpadc->regu); | 651 | ret = PTR_ERR(gpadc->regu); |
649 | dev_err(gpadc->dev, "failed to get vtvout LDO\n"); | 652 | dev_err(gpadc->dev, "failed to get vtvout LDO\n"); |
@@ -652,7 +655,11 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
652 | 655 | ||
653 | platform_set_drvdata(pdev, gpadc); | 656 | platform_set_drvdata(pdev, gpadc); |
654 | 657 | ||
655 | regulator_enable(gpadc->regu); | 658 | ret = regulator_enable(gpadc->regu); |
659 | if (ret) { | ||
660 | dev_err(gpadc->dev, "Failed to enable vtvout LDO: %d\n", ret); | ||
661 | goto fail_enable; | ||
662 | } | ||
656 | 663 | ||
657 | pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY); | 664 | pm_runtime_set_autosuspend_delay(gpadc->dev, GPADC_AUDOSUSPEND_DELAY); |
658 | pm_runtime_use_autosuspend(gpadc->dev); | 665 | pm_runtime_use_autosuspend(gpadc->dev); |
@@ -663,6 +670,8 @@ static int ab8500_gpadc_probe(struct platform_device *pdev) | |||
663 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); | 670 | list_add_tail(&gpadc->node, &ab8500_gpadc_list); |
664 | dev_dbg(gpadc->dev, "probe success\n"); | 671 | dev_dbg(gpadc->dev, "probe success\n"); |
665 | return 0; | 672 | return 0; |
673 | |||
674 | fail_enable: | ||
666 | fail_irq: | 675 | fail_irq: |
667 | free_irq(gpadc->irq, gpadc); | 676 | free_irq(gpadc->irq, gpadc); |
668 | fail: | 677 | fail: |
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c index 6b5edf64de2b..4febc5c7fdee 100644 --- a/drivers/mfd/omap-usb-host.c +++ b/drivers/mfd/omap-usb-host.c | |||
@@ -460,15 +460,15 @@ static void omap_usbhs_init(struct device *dev) | |||
460 | 460 | ||
461 | switch (omap->usbhs_rev) { | 461 | switch (omap->usbhs_rev) { |
462 | case OMAP_USBHS_REV1: | 462 | case OMAP_USBHS_REV1: |
463 | omap_usbhs_rev1_hostconfig(omap, reg); | 463 | reg = omap_usbhs_rev1_hostconfig(omap, reg); |
464 | break; | 464 | break; |
465 | 465 | ||
466 | case OMAP_USBHS_REV2: | 466 | case OMAP_USBHS_REV2: |
467 | omap_usbhs_rev2_hostconfig(omap, reg); | 467 | reg = omap_usbhs_rev2_hostconfig(omap, reg); |
468 | break; | 468 | break; |
469 | 469 | ||
470 | default: /* newer revisions */ | 470 | default: /* newer revisions */ |
471 | omap_usbhs_rev2_hostconfig(omap, reg); | 471 | reg = omap_usbhs_rev2_hostconfig(omap, reg); |
472 | break; | 472 | break; |
473 | } | 473 | } |
474 | 474 | ||
diff --git a/drivers/mfd/palmas.c b/drivers/mfd/palmas.c index bbdbc50a3cca..73bf76df1044 100644 --- a/drivers/mfd/palmas.c +++ b/drivers/mfd/palmas.c | |||
@@ -257,9 +257,24 @@ static struct regmap_irq_chip palmas_irq_chip = { | |||
257 | PALMAS_INT1_MASK), | 257 | PALMAS_INT1_MASK), |
258 | }; | 258 | }; |
259 | 259 | ||
260 | static void palmas_dt_to_pdata(struct device_node *node, | 260 | static int palmas_set_pdata_irq_flag(struct i2c_client *i2c, |
261 | struct palmas_platform_data *pdata) | 261 | struct palmas_platform_data *pdata) |
262 | { | 262 | { |
263 | struct irq_data *irq_data = irq_get_irq_data(i2c->irq); | ||
264 | if (!irq_data) { | ||
265 | dev_err(&i2c->dev, "Invalid IRQ: %d\n", i2c->irq); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | pdata->irq_flags = irqd_get_trigger_type(irq_data); | ||
270 | dev_info(&i2c->dev, "Irq flag is 0x%08x\n", pdata->irq_flags); | ||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static void palmas_dt_to_pdata(struct i2c_client *i2c, | ||
275 | struct palmas_platform_data *pdata) | ||
276 | { | ||
277 | struct device_node *node = i2c->dev.of_node; | ||
263 | int ret; | 278 | int ret; |
264 | u32 prop; | 279 | u32 prop; |
265 | 280 | ||
@@ -283,6 +298,8 @@ static void palmas_dt_to_pdata(struct device_node *node, | |||
283 | pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK | | 298 | pdata->power_ctrl = PALMAS_POWER_CTRL_NSLEEP_MASK | |
284 | PALMAS_POWER_CTRL_ENABLE1_MASK | | 299 | PALMAS_POWER_CTRL_ENABLE1_MASK | |
285 | PALMAS_POWER_CTRL_ENABLE2_MASK; | 300 | PALMAS_POWER_CTRL_ENABLE2_MASK; |
301 | if (i2c->irq) | ||
302 | palmas_set_pdata_irq_flag(i2c, pdata); | ||
286 | } | 303 | } |
287 | 304 | ||
288 | static int palmas_i2c_probe(struct i2c_client *i2c, | 305 | static int palmas_i2c_probe(struct i2c_client *i2c, |
@@ -304,7 +321,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, | |||
304 | if (!pdata) | 321 | if (!pdata) |
305 | return -ENOMEM; | 322 | return -ENOMEM; |
306 | 323 | ||
307 | palmas_dt_to_pdata(node, pdata); | 324 | palmas_dt_to_pdata(i2c, pdata); |
308 | } | 325 | } |
309 | 326 | ||
310 | if (!pdata) | 327 | if (!pdata) |
@@ -344,6 +361,19 @@ static int palmas_i2c_probe(struct i2c_client *i2c, | |||
344 | } | 361 | } |
345 | } | 362 | } |
346 | 363 | ||
364 | /* Change interrupt line output polarity */ | ||
365 | if (pdata->irq_flags & IRQ_TYPE_LEVEL_HIGH) | ||
366 | reg = PALMAS_POLARITY_CTRL_INT_POLARITY; | ||
367 | else | ||
368 | reg = 0; | ||
369 | ret = palmas_update_bits(palmas, PALMAS_PU_PD_OD_BASE, | ||
370 | PALMAS_POLARITY_CTRL, PALMAS_POLARITY_CTRL_INT_POLARITY, | ||
371 | reg); | ||
372 | if (ret < 0) { | ||
373 | dev_err(palmas->dev, "POLARITY_CTRL updat failed: %d\n", ret); | ||
374 | goto err; | ||
375 | } | ||
376 | |||
347 | /* Change IRQ into clear on read mode for efficiency */ | 377 | /* Change IRQ into clear on read mode for efficiency */ |
348 | slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE); | 378 | slave = PALMAS_BASE_TO_SLAVE(PALMAS_INTERRUPT_BASE); |
349 | addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL); | 379 | addr = PALMAS_BASE_TO_REG(PALMAS_INTERRUPT_BASE, PALMAS_INT_CTRL); |
@@ -352,7 +382,7 @@ static int palmas_i2c_probe(struct i2c_client *i2c, | |||
352 | regmap_write(palmas->regmap[slave], addr, reg); | 382 | regmap_write(palmas->regmap[slave], addr, reg); |
353 | 383 | ||
354 | ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq, | 384 | ret = regmap_add_irq_chip(palmas->regmap[slave], palmas->irq, |
355 | IRQF_ONESHOT | IRQF_TRIGGER_LOW, 0, &palmas_irq_chip, | 385 | IRQF_ONESHOT | pdata->irq_flags, 0, &palmas_irq_chip, |
356 | &palmas->irq_data); | 386 | &palmas->irq_data); |
357 | if (ret < 0) | 387 | if (ret < 0) |
358 | goto err; | 388 | goto err; |
diff --git a/drivers/mfd/tps65912-core.c b/drivers/mfd/tps65912-core.c index 4658b5bdcd84..aeb8e40ab424 100644 --- a/drivers/mfd/tps65912-core.c +++ b/drivers/mfd/tps65912-core.c | |||
@@ -169,6 +169,7 @@ err: | |||
169 | void tps65912_device_exit(struct tps65912 *tps65912) | 169 | void tps65912_device_exit(struct tps65912 *tps65912) |
170 | { | 170 | { |
171 | mfd_remove_devices(tps65912->dev); | 171 | mfd_remove_devices(tps65912->dev); |
172 | tps65912_irq_exit(tps65912); | ||
172 | kfree(tps65912); | 173 | kfree(tps65912); |
173 | } | 174 | } |
174 | 175 | ||
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c index e16edca92670..d2ab222138c2 100644 --- a/drivers/mfd/twl4030-audio.c +++ b/drivers/mfd/twl4030-audio.c | |||
@@ -118,7 +118,7 @@ EXPORT_SYMBOL_GPL(twl4030_audio_enable_resource); | |||
118 | * Disable the resource. | 118 | * Disable the resource. |
119 | * The function returns with error or the content of the register | 119 | * The function returns with error or the content of the register |
120 | */ | 120 | */ |
121 | int twl4030_audio_disable_resource(unsigned id) | 121 | int twl4030_audio_disable_resource(enum twl4030_audio_res id) |
122 | { | 122 | { |
123 | struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev); | 123 | struct twl4030_audio *audio = platform_get_drvdata(twl4030_audio_dev); |
124 | int val; | 124 | int val; |
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c index 88ff9dc83305..942b666a2a07 100644 --- a/drivers/mfd/twl4030-madc.c +++ b/drivers/mfd/twl4030-madc.c | |||
@@ -800,7 +800,7 @@ static int twl4030_madc_remove(struct platform_device *pdev) | |||
800 | 800 | ||
801 | static struct platform_driver twl4030_madc_driver = { | 801 | static struct platform_driver twl4030_madc_driver = { |
802 | .probe = twl4030_madc_probe, | 802 | .probe = twl4030_madc_probe, |
803 | .remove = __exit_p(twl4030_madc_remove), | 803 | .remove = twl4030_madc_remove, |
804 | .driver = { | 804 | .driver = { |
805 | .name = "twl4030_madc", | 805 | .name = "twl4030_madc", |
806 | .owner = THIS_MODULE, | 806 | .owner = THIS_MODULE, |
diff --git a/drivers/misc/ibmasm/ibmasmfs.c b/drivers/misc/ibmasm/ibmasmfs.c index 6673e578b3e9..ce5b75616b45 100644 --- a/drivers/misc/ibmasm/ibmasmfs.c +++ b/drivers/misc/ibmasm/ibmasmfs.c | |||
@@ -110,6 +110,7 @@ static struct file_system_type ibmasmfs_type = { | |||
110 | .mount = ibmasmfs_mount, | 110 | .mount = ibmasmfs_mount, |
111 | .kill_sb = kill_litter_super, | 111 | .kill_sb = kill_litter_super, |
112 | }; | 112 | }; |
113 | MODULE_ALIAS_FS("ibmasmfs"); | ||
113 | 114 | ||
114 | static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent) | 115 | static int ibmasmfs_fill_super (struct super_block *sb, void *data, int silent) |
115 | { | 116 | { |
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 45ea7185c003..642c6223fa6c 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -152,6 +152,20 @@ static void mei_me_intr_disable(struct mei_device *dev) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | /** | 154 | /** |
155 | * mei_me_hw_reset_release - release device from the reset | ||
156 | * | ||
157 | * @dev: the device structure | ||
158 | */ | ||
159 | static void mei_me_hw_reset_release(struct mei_device *dev) | ||
160 | { | ||
161 | struct mei_me_hw *hw = to_me_hw(dev); | ||
162 | u32 hcsr = mei_hcsr_read(hw); | ||
163 | |||
164 | hcsr |= H_IG; | ||
165 | hcsr &= ~H_RST; | ||
166 | mei_hcsr_set(hw, hcsr); | ||
167 | } | ||
168 | /** | ||
155 | * mei_me_hw_reset - resets fw via mei csr register. | 169 | * mei_me_hw_reset - resets fw via mei csr register. |
156 | * | 170 | * |
157 | * @dev: the device structure | 171 | * @dev: the device structure |
@@ -169,18 +183,14 @@ static void mei_me_hw_reset(struct mei_device *dev, bool intr_enable) | |||
169 | if (intr_enable) | 183 | if (intr_enable) |
170 | hcsr |= H_IE; | 184 | hcsr |= H_IE; |
171 | else | 185 | else |
172 | hcsr &= ~H_IE; | 186 | hcsr |= ~H_IE; |
173 | |||
174 | mei_hcsr_set(hw, hcsr); | ||
175 | |||
176 | hcsr = mei_hcsr_read(hw) | H_IG; | ||
177 | hcsr &= ~H_RST; | ||
178 | 187 | ||
179 | mei_hcsr_set(hw, hcsr); | 188 | mei_hcsr_set(hw, hcsr); |
180 | 189 | ||
181 | hcsr = mei_hcsr_read(hw); | 190 | if (dev->dev_state == MEI_DEV_POWER_DOWN) |
191 | mei_me_hw_reset_release(dev); | ||
182 | 192 | ||
183 | dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", hcsr); | 193 | dev_dbg(&dev->pdev->dev, "current HCSR = 0x%08x.\n", mei_hcsr_read(hw)); |
184 | } | 194 | } |
185 | 195 | ||
186 | /** | 196 | /** |
@@ -466,7 +476,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) | |||
466 | mutex_unlock(&dev->device_lock); | 476 | mutex_unlock(&dev->device_lock); |
467 | return IRQ_HANDLED; | 477 | return IRQ_HANDLED; |
468 | } else { | 478 | } else { |
469 | dev_dbg(&dev->pdev->dev, "FW not ready.\n"); | 479 | dev_dbg(&dev->pdev->dev, "Reset Completed.\n"); |
480 | mei_me_hw_reset_release(dev); | ||
470 | mutex_unlock(&dev->device_lock); | 481 | mutex_unlock(&dev->device_lock); |
471 | return IRQ_HANDLED; | 482 | return IRQ_HANDLED; |
472 | } | 483 | } |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 6ec530168afb..356179991a2e 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -183,6 +183,24 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
183 | mei_cl_all_write_clear(dev); | 183 | mei_cl_all_write_clear(dev); |
184 | } | 184 | } |
185 | 185 | ||
186 | void mei_stop(struct mei_device *dev) | ||
187 | { | ||
188 | dev_dbg(&dev->pdev->dev, "stopping the device.\n"); | ||
189 | |||
190 | mutex_lock(&dev->device_lock); | ||
191 | |||
192 | cancel_delayed_work(&dev->timer_work); | ||
193 | |||
194 | mei_wd_stop(dev); | ||
195 | |||
196 | dev->dev_state = MEI_DEV_POWER_DOWN; | ||
197 | mei_reset(dev, 0); | ||
198 | |||
199 | mutex_unlock(&dev->device_lock); | ||
200 | |||
201 | flush_scheduled_work(); | ||
202 | } | ||
203 | |||
186 | 204 | ||
187 | 205 | ||
188 | 206 | ||
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index cb80166161f0..97873812e33b 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -381,6 +381,7 @@ static inline unsigned long mei_secs_to_jiffies(unsigned long sec) | |||
381 | void mei_device_init(struct mei_device *dev); | 381 | void mei_device_init(struct mei_device *dev); |
382 | void mei_reset(struct mei_device *dev, int interrupts); | 382 | void mei_reset(struct mei_device *dev, int interrupts); |
383 | int mei_hw_init(struct mei_device *dev); | 383 | int mei_hw_init(struct mei_device *dev); |
384 | void mei_stop(struct mei_device *dev); | ||
384 | 385 | ||
385 | /* | 386 | /* |
386 | * MEI interrupt functions prototype | 387 | * MEI interrupt functions prototype |
diff --git a/drivers/misc/mei/pci-me.c b/drivers/misc/mei/pci-me.c index b40ec0601ab0..b8b5c9c3ad03 100644 --- a/drivers/misc/mei/pci-me.c +++ b/drivers/misc/mei/pci-me.c | |||
@@ -247,44 +247,14 @@ static void mei_remove(struct pci_dev *pdev) | |||
247 | 247 | ||
248 | hw = to_me_hw(dev); | 248 | hw = to_me_hw(dev); |
249 | 249 | ||
250 | mutex_lock(&dev->device_lock); | ||
251 | |||
252 | cancel_delayed_work(&dev->timer_work); | ||
253 | 250 | ||
254 | mei_wd_stop(dev); | 251 | dev_err(&pdev->dev, "stop\n"); |
252 | mei_stop(dev); | ||
255 | 253 | ||
256 | mei_pdev = NULL; | 254 | mei_pdev = NULL; |
257 | 255 | ||
258 | if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) { | ||
259 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTING; | ||
260 | mei_cl_disconnect(&dev->iamthif_cl); | ||
261 | } | ||
262 | if (dev->wd_cl.state == MEI_FILE_CONNECTED) { | ||
263 | dev->wd_cl.state = MEI_FILE_DISCONNECTING; | ||
264 | mei_cl_disconnect(&dev->wd_cl); | ||
265 | } | ||
266 | |||
267 | /* Unregistering watchdog device */ | ||
268 | mei_watchdog_unregister(dev); | 256 | mei_watchdog_unregister(dev); |
269 | 257 | ||
270 | /* remove entry if already in list */ | ||
271 | dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n"); | ||
272 | |||
273 | if (dev->open_handle_count > 0) | ||
274 | dev->open_handle_count--; | ||
275 | mei_cl_unlink(&dev->wd_cl); | ||
276 | |||
277 | if (dev->open_handle_count > 0) | ||
278 | dev->open_handle_count--; | ||
279 | mei_cl_unlink(&dev->iamthif_cl); | ||
280 | |||
281 | dev->iamthif_current_cb = NULL; | ||
282 | dev->me_clients_num = 0; | ||
283 | |||
284 | mutex_unlock(&dev->device_lock); | ||
285 | |||
286 | flush_scheduled_work(); | ||
287 | |||
288 | /* disable interrupts */ | 258 | /* disable interrupts */ |
289 | mei_disable_interrupts(dev); | 259 | mei_disable_interrupts(dev); |
290 | 260 | ||
@@ -308,28 +278,20 @@ static int mei_pci_suspend(struct device *device) | |||
308 | { | 278 | { |
309 | struct pci_dev *pdev = to_pci_dev(device); | 279 | struct pci_dev *pdev = to_pci_dev(device); |
310 | struct mei_device *dev = pci_get_drvdata(pdev); | 280 | struct mei_device *dev = pci_get_drvdata(pdev); |
311 | int err; | ||
312 | 281 | ||
313 | if (!dev) | 282 | if (!dev) |
314 | return -ENODEV; | 283 | return -ENODEV; |
315 | mutex_lock(&dev->device_lock); | ||
316 | 284 | ||
317 | cancel_delayed_work(&dev->timer_work); | 285 | dev_err(&pdev->dev, "suspend\n"); |
318 | 286 | ||
319 | /* Stop watchdog if exists */ | 287 | mei_stop(dev); |
320 | err = mei_wd_stop(dev); | 288 | |
321 | /* Set new mei state */ | 289 | mei_disable_interrupts(dev); |
322 | if (dev->dev_state == MEI_DEV_ENABLED || | ||
323 | dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { | ||
324 | dev->dev_state = MEI_DEV_POWER_DOWN; | ||
325 | mei_reset(dev, 0); | ||
326 | } | ||
327 | mutex_unlock(&dev->device_lock); | ||
328 | 290 | ||
329 | free_irq(pdev->irq, dev); | 291 | free_irq(pdev->irq, dev); |
330 | pci_disable_msi(pdev); | 292 | pci_disable_msi(pdev); |
331 | 293 | ||
332 | return err; | 294 | return 0; |
333 | } | 295 | } |
334 | 296 | ||
335 | static int mei_pci_resume(struct device *device) | 297 | static int mei_pci_resume(struct device *device) |
diff --git a/drivers/misc/vmw_vmci/vmci_datagram.c b/drivers/misc/vmw_vmci/vmci_datagram.c index ed5c433cd493..f3cdd904fe4d 100644 --- a/drivers/misc/vmw_vmci/vmci_datagram.c +++ b/drivers/misc/vmw_vmci/vmci_datagram.c | |||
@@ -42,9 +42,11 @@ struct datagram_entry { | |||
42 | 42 | ||
43 | struct delayed_datagram_info { | 43 | struct delayed_datagram_info { |
44 | struct datagram_entry *entry; | 44 | struct datagram_entry *entry; |
45 | struct vmci_datagram msg; | ||
46 | struct work_struct work; | 45 | struct work_struct work; |
47 | bool in_dg_host_queue; | 46 | bool in_dg_host_queue; |
47 | /* msg and msg_payload must be together. */ | ||
48 | struct vmci_datagram msg; | ||
49 | u8 msg_payload[]; | ||
48 | }; | 50 | }; |
49 | 51 | ||
50 | /* Number of in-flight host->host datagrams */ | 52 | /* Number of in-flight host->host datagrams */ |
diff --git a/drivers/mtd/bcm47xxpart.c b/drivers/mtd/bcm47xxpart.c index 63feb75cc8e0..9279a9174f84 100644 --- a/drivers/mtd/bcm47xxpart.c +++ b/drivers/mtd/bcm47xxpart.c | |||
@@ -19,6 +19,12 @@ | |||
19 | /* 10 parts were found on sflash on Netgear WNDR4500 */ | 19 | /* 10 parts were found on sflash on Netgear WNDR4500 */ |
20 | #define BCM47XXPART_MAX_PARTS 12 | 20 | #define BCM47XXPART_MAX_PARTS 12 |
21 | 21 | ||
22 | /* | ||
23 | * Amount of bytes we read when analyzing each block of flash memory. | ||
24 | * Set it big enough to allow detecting partition and reading important data. | ||
25 | */ | ||
26 | #define BCM47XXPART_BYTES_TO_READ 0x404 | ||
27 | |||
22 | /* Magics */ | 28 | /* Magics */ |
23 | #define BOARD_DATA_MAGIC 0x5246504D /* MPFR */ | 29 | #define BOARD_DATA_MAGIC 0x5246504D /* MPFR */ |
24 | #define POT_MAGIC1 0x54544f50 /* POTT */ | 30 | #define POT_MAGIC1 0x54544f50 /* POTT */ |
@@ -57,17 +63,15 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
57 | struct trx_header *trx; | 63 | struct trx_header *trx; |
58 | int trx_part = -1; | 64 | int trx_part = -1; |
59 | int last_trx_part = -1; | 65 | int last_trx_part = -1; |
60 | int max_bytes_to_read = 0x8004; | 66 | int possible_nvram_sizes[] = { 0x8000, 0xF000, 0x10000, }; |
61 | 67 | ||
62 | if (blocksize <= 0x10000) | 68 | if (blocksize <= 0x10000) |
63 | blocksize = 0x10000; | 69 | blocksize = 0x10000; |
64 | if (blocksize == 0x20000) | ||
65 | max_bytes_to_read = 0x18004; | ||
66 | 70 | ||
67 | /* Alloc */ | 71 | /* Alloc */ |
68 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, | 72 | parts = kzalloc(sizeof(struct mtd_partition) * BCM47XXPART_MAX_PARTS, |
69 | GFP_KERNEL); | 73 | GFP_KERNEL); |
70 | buf = kzalloc(max_bytes_to_read, GFP_KERNEL); | 74 | buf = kzalloc(BCM47XXPART_BYTES_TO_READ, GFP_KERNEL); |
71 | 75 | ||
72 | /* Parse block by block looking for magics */ | 76 | /* Parse block by block looking for magics */ |
73 | for (offset = 0; offset <= master->size - blocksize; | 77 | for (offset = 0; offset <= master->size - blocksize; |
@@ -82,7 +86,7 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
82 | } | 86 | } |
83 | 87 | ||
84 | /* Read beginning of the block */ | 88 | /* Read beginning of the block */ |
85 | if (mtd_read(master, offset, max_bytes_to_read, | 89 | if (mtd_read(master, offset, BCM47XXPART_BYTES_TO_READ, |
86 | &bytes_read, (uint8_t *)buf) < 0) { | 90 | &bytes_read, (uint8_t *)buf) < 0) { |
87 | pr_err("mtd_read error while parsing (offset: 0x%X)!\n", | 91 | pr_err("mtd_read error while parsing (offset: 0x%X)!\n", |
88 | offset); | 92 | offset); |
@@ -96,20 +100,6 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
96 | continue; | 100 | continue; |
97 | } | 101 | } |
98 | 102 | ||
99 | /* Standard NVRAM */ | ||
100 | if (buf[0x000 / 4] == NVRAM_HEADER || | ||
101 | buf[0x1000 / 4] == NVRAM_HEADER || | ||
102 | buf[0x8000 / 4] == NVRAM_HEADER || | ||
103 | (blocksize == 0x20000 && ( | ||
104 | buf[0x10000 / 4] == NVRAM_HEADER || | ||
105 | buf[0x11000 / 4] == NVRAM_HEADER || | ||
106 | buf[0x18000 / 4] == NVRAM_HEADER))) { | ||
107 | bcm47xxpart_add_part(&parts[curr_part++], "nvram", | ||
108 | offset, 0); | ||
109 | offset = rounddown(offset, blocksize); | ||
110 | continue; | ||
111 | } | ||
112 | |||
113 | /* | 103 | /* |
114 | * board_data starts with board_id which differs across boards, | 104 | * board_data starts with board_id which differs across boards, |
115 | * but we can use 'MPFR' (hopefully) magic at 0x100 | 105 | * but we can use 'MPFR' (hopefully) magic at 0x100 |
@@ -178,6 +168,30 @@ static int bcm47xxpart_parse(struct mtd_info *master, | |||
178 | continue; | 168 | continue; |
179 | } | 169 | } |
180 | } | 170 | } |
171 | |||
172 | /* Look for NVRAM at the end of the last block. */ | ||
173 | for (i = 0; i < ARRAY_SIZE(possible_nvram_sizes); i++) { | ||
174 | if (curr_part > BCM47XXPART_MAX_PARTS) { | ||
175 | pr_warn("Reached maximum number of partitions, scanning stopped!\n"); | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | offset = master->size - possible_nvram_sizes[i]; | ||
180 | if (mtd_read(master, offset, 0x4, &bytes_read, | ||
181 | (uint8_t *)buf) < 0) { | ||
182 | pr_err("mtd_read error while reading at offset 0x%X!\n", | ||
183 | offset); | ||
184 | continue; | ||
185 | } | ||
186 | |||
187 | /* Standard NVRAM */ | ||
188 | if (buf[0] == NVRAM_HEADER) { | ||
189 | bcm47xxpart_add_part(&parts[curr_part++], "nvram", | ||
190 | master->size - blocksize, 0); | ||
191 | break; | ||
192 | } | ||
193 | } | ||
194 | |||
181 | kfree(buf); | 195 | kfree(buf); |
182 | 196 | ||
183 | /* | 197 | /* |
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index 82c06165d3d2..92ab30ab00dc 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c | |||
@@ -1238,6 +1238,7 @@ static struct file_system_type mtd_inodefs_type = { | |||
1238 | .mount = mtd_inodefs_mount, | 1238 | .mount = mtd_inodefs_mount, |
1239 | .kill_sb = kill_anon_super, | 1239 | .kill_sb = kill_anon_super, |
1240 | }; | 1240 | }; |
1241 | MODULE_ALIAS_FS("mtd_inodefs"); | ||
1241 | 1242 | ||
1242 | static int __init init_mtdchar(void) | 1243 | static int __init init_mtdchar(void) |
1243 | { | 1244 | { |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 43214151b882..42c63927609d 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -1523,6 +1523,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, | |||
1523 | oobreadlen -= toread; | 1523 | oobreadlen -= toread; |
1524 | } | 1524 | } |
1525 | } | 1525 | } |
1526 | |||
1527 | if (chip->options & NAND_NEED_READRDY) { | ||
1528 | /* Apply delay or wait for ready/busy pin */ | ||
1529 | if (!chip->dev_ready) | ||
1530 | udelay(chip->chip_delay); | ||
1531 | else | ||
1532 | nand_wait_ready(mtd); | ||
1533 | } | ||
1526 | } else { | 1534 | } else { |
1527 | memcpy(buf, chip->buffers->databuf + col, bytes); | 1535 | memcpy(buf, chip->buffers->databuf + col, bytes); |
1528 | buf += bytes; | 1536 | buf += bytes; |
@@ -1787,6 +1795,14 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, | |||
1787 | len = min(len, readlen); | 1795 | len = min(len, readlen); |
1788 | buf = nand_transfer_oob(chip, buf, ops, len); | 1796 | buf = nand_transfer_oob(chip, buf, ops, len); |
1789 | 1797 | ||
1798 | if (chip->options & NAND_NEED_READRDY) { | ||
1799 | /* Apply delay or wait for ready/busy pin */ | ||
1800 | if (!chip->dev_ready) | ||
1801 | udelay(chip->chip_delay); | ||
1802 | else | ||
1803 | nand_wait_ready(mtd); | ||
1804 | } | ||
1805 | |||
1790 | readlen -= len; | 1806 | readlen -= len; |
1791 | if (!readlen) | 1807 | if (!readlen) |
1792 | break; | 1808 | break; |
diff --git a/drivers/mtd/nand/nand_ids.c b/drivers/mtd/nand/nand_ids.c index e3aa2748a6e7..9c612388e5de 100644 --- a/drivers/mtd/nand/nand_ids.c +++ b/drivers/mtd/nand/nand_ids.c | |||
@@ -22,49 +22,51 @@ | |||
22 | * 512 512 Byte page size | 22 | * 512 512 Byte page size |
23 | */ | 23 | */ |
24 | struct nand_flash_dev nand_flash_ids[] = { | 24 | struct nand_flash_dev nand_flash_ids[] = { |
25 | #define SP_OPTIONS NAND_NEED_READRDY | ||
26 | #define SP_OPTIONS16 (SP_OPTIONS | NAND_BUSWIDTH_16) | ||
25 | 27 | ||
26 | #ifdef CONFIG_MTD_NAND_MUSEUM_IDS | 28 | #ifdef CONFIG_MTD_NAND_MUSEUM_IDS |
27 | {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, 0}, | 29 | {"NAND 1MiB 5V 8-bit", 0x6e, 256, 1, 0x1000, SP_OPTIONS}, |
28 | {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, 0}, | 30 | {"NAND 2MiB 5V 8-bit", 0x64, 256, 2, 0x1000, SP_OPTIONS}, |
29 | {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, 0}, | 31 | {"NAND 4MiB 5V 8-bit", 0x6b, 512, 4, 0x2000, SP_OPTIONS}, |
30 | {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, 0}, | 32 | {"NAND 1MiB 3,3V 8-bit", 0xe8, 256, 1, 0x1000, SP_OPTIONS}, |
31 | {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, 0}, | 33 | {"NAND 1MiB 3,3V 8-bit", 0xec, 256, 1, 0x1000, SP_OPTIONS}, |
32 | {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, 0}, | 34 | {"NAND 2MiB 3,3V 8-bit", 0xea, 256, 2, 0x1000, SP_OPTIONS}, |
33 | {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, 0}, | 35 | {"NAND 4MiB 3,3V 8-bit", 0xd5, 512, 4, 0x2000, SP_OPTIONS}, |
34 | {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, 0}, | 36 | {"NAND 4MiB 3,3V 8-bit", 0xe3, 512, 4, 0x2000, SP_OPTIONS}, |
35 | {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, 0}, | 37 | {"NAND 4MiB 3,3V 8-bit", 0xe5, 512, 4, 0x2000, SP_OPTIONS}, |
36 | {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, 0}, | 38 | {"NAND 8MiB 3,3V 8-bit", 0xd6, 512, 8, 0x2000, SP_OPTIONS}, |
37 | 39 | ||
38 | {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, 0}, | 40 | {"NAND 8MiB 1,8V 8-bit", 0x39, 512, 8, 0x2000, SP_OPTIONS}, |
39 | {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, 0}, | 41 | {"NAND 8MiB 3,3V 8-bit", 0xe6, 512, 8, 0x2000, SP_OPTIONS}, |
40 | {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, NAND_BUSWIDTH_16}, | 42 | {"NAND 8MiB 1,8V 16-bit", 0x49, 512, 8, 0x2000, SP_OPTIONS16}, |
41 | {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, NAND_BUSWIDTH_16}, | 43 | {"NAND 8MiB 3,3V 16-bit", 0x59, 512, 8, 0x2000, SP_OPTIONS16}, |
42 | #endif | 44 | #endif |
43 | 45 | ||
44 | {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, 0}, | 46 | {"NAND 16MiB 1,8V 8-bit", 0x33, 512, 16, 0x4000, SP_OPTIONS}, |
45 | {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, 0}, | 47 | {"NAND 16MiB 3,3V 8-bit", 0x73, 512, 16, 0x4000, SP_OPTIONS}, |
46 | {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, NAND_BUSWIDTH_16}, | 48 | {"NAND 16MiB 1,8V 16-bit", 0x43, 512, 16, 0x4000, SP_OPTIONS16}, |
47 | {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, NAND_BUSWIDTH_16}, | 49 | {"NAND 16MiB 3,3V 16-bit", 0x53, 512, 16, 0x4000, SP_OPTIONS16}, |
48 | 50 | ||
49 | {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, 0}, | 51 | {"NAND 32MiB 1,8V 8-bit", 0x35, 512, 32, 0x4000, SP_OPTIONS}, |
50 | {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, 0}, | 52 | {"NAND 32MiB 3,3V 8-bit", 0x75, 512, 32, 0x4000, SP_OPTIONS}, |
51 | {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, NAND_BUSWIDTH_16}, | 53 | {"NAND 32MiB 1,8V 16-bit", 0x45, 512, 32, 0x4000, SP_OPTIONS16}, |
52 | {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, NAND_BUSWIDTH_16}, | 54 | {"NAND 32MiB 3,3V 16-bit", 0x55, 512, 32, 0x4000, SP_OPTIONS16}, |
53 | 55 | ||
54 | {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, 0}, | 56 | {"NAND 64MiB 1,8V 8-bit", 0x36, 512, 64, 0x4000, SP_OPTIONS}, |
55 | {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, 0}, | 57 | {"NAND 64MiB 3,3V 8-bit", 0x76, 512, 64, 0x4000, SP_OPTIONS}, |
56 | {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, NAND_BUSWIDTH_16}, | 58 | {"NAND 64MiB 1,8V 16-bit", 0x46, 512, 64, 0x4000, SP_OPTIONS16}, |
57 | {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, NAND_BUSWIDTH_16}, | 59 | {"NAND 64MiB 3,3V 16-bit", 0x56, 512, 64, 0x4000, SP_OPTIONS16}, |
58 | 60 | ||
59 | {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, 0}, | 61 | {"NAND 128MiB 1,8V 8-bit", 0x78, 512, 128, 0x4000, SP_OPTIONS}, |
60 | {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, 0}, | 62 | {"NAND 128MiB 1,8V 8-bit", 0x39, 512, 128, 0x4000, SP_OPTIONS}, |
61 | {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, 0}, | 63 | {"NAND 128MiB 3,3V 8-bit", 0x79, 512, 128, 0x4000, SP_OPTIONS}, |
62 | {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | 64 | {"NAND 128MiB 1,8V 16-bit", 0x72, 512, 128, 0x4000, SP_OPTIONS16}, |
63 | {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | 65 | {"NAND 128MiB 1,8V 16-bit", 0x49, 512, 128, 0x4000, SP_OPTIONS16}, |
64 | {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | 66 | {"NAND 128MiB 3,3V 16-bit", 0x74, 512, 128, 0x4000, SP_OPTIONS16}, |
65 | {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, NAND_BUSWIDTH_16}, | 67 | {"NAND 128MiB 3,3V 16-bit", 0x59, 512, 128, 0x4000, SP_OPTIONS16}, |
66 | 68 | ||
67 | {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, 0}, | 69 | {"NAND 256MiB 3,3V 8-bit", 0x71, 512, 256, 0x4000, SP_OPTIONS}, |
68 | 70 | ||
69 | /* | 71 | /* |
70 | * These are the new chips with large page size. The pagesize and the | 72 | * These are the new chips with large page size. The pagesize and the |
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 11d01d67b3f5..6bbd90e1123c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1629,7 +1629,7 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1629 | 1629 | ||
1630 | /* If this is the first slave, then we need to set the master's hardware | 1630 | /* If this is the first slave, then we need to set the master's hardware |
1631 | * address to be the same as the slave's. */ | 1631 | * address to be the same as the slave's. */ |
1632 | if (bond->dev_addr_from_first) | 1632 | if (bond->slave_cnt == 0 && bond->dev_addr_from_first) |
1633 | bond_set_dev_addr(bond->dev, slave_dev); | 1633 | bond_set_dev_addr(bond->dev, slave_dev); |
1634 | 1634 | ||
1635 | new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); | 1635 | new_slave = kzalloc(sizeof(struct slave), GFP_KERNEL); |
@@ -1746,6 +1746,8 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1746 | 1746 | ||
1747 | bond_compute_features(bond); | 1747 | bond_compute_features(bond); |
1748 | 1748 | ||
1749 | bond_update_speed_duplex(new_slave); | ||
1750 | |||
1749 | read_lock(&bond->lock); | 1751 | read_lock(&bond->lock); |
1750 | 1752 | ||
1751 | new_slave->last_arp_rx = jiffies - | 1753 | new_slave->last_arp_rx = jiffies - |
@@ -1798,8 +1800,6 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1798 | new_slave->link == BOND_LINK_DOWN ? "DOWN" : | 1800 | new_slave->link == BOND_LINK_DOWN ? "DOWN" : |
1799 | (new_slave->link == BOND_LINK_UP ? "UP" : "BACK")); | 1801 | (new_slave->link == BOND_LINK_UP ? "UP" : "BACK")); |
1800 | 1802 | ||
1801 | bond_update_speed_duplex(new_slave); | ||
1802 | |||
1803 | if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { | 1803 | if (USES_PRIMARY(bond->params.mode) && bond->params.primary[0]) { |
1804 | /* if there is a primary slave, remember it */ | 1804 | /* if there is a primary slave, remember it */ |
1805 | if (strcmp(bond->params.primary, new_slave->dev->name) == 0) { | 1805 | if (strcmp(bond->params.primary, new_slave->dev->name) == 0) { |
@@ -1964,7 +1964,6 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
1964 | } | 1964 | } |
1965 | 1965 | ||
1966 | block_netpoll_tx(); | 1966 | block_netpoll_tx(); |
1967 | call_netdevice_notifiers(NETDEV_RELEASE, bond_dev); | ||
1968 | write_lock_bh(&bond->lock); | 1967 | write_lock_bh(&bond->lock); |
1969 | 1968 | ||
1970 | slave = bond_get_slave_by_dev(bond, slave_dev); | 1969 | slave = bond_get_slave_by_dev(bond, slave_dev); |
@@ -2066,8 +2065,10 @@ static int __bond_release_one(struct net_device *bond_dev, | |||
2066 | write_unlock_bh(&bond->lock); | 2065 | write_unlock_bh(&bond->lock); |
2067 | unblock_netpoll_tx(); | 2066 | unblock_netpoll_tx(); |
2068 | 2067 | ||
2069 | if (bond->slave_cnt == 0) | 2068 | if (bond->slave_cnt == 0) { |
2070 | call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); | 2069 | call_netdevice_notifiers(NETDEV_CHANGEADDR, bond->dev); |
2070 | call_netdevice_notifiers(NETDEV_RELEASE, bond->dev); | ||
2071 | } | ||
2071 | 2072 | ||
2072 | bond_compute_features(bond); | 2073 | bond_compute_features(bond); |
2073 | if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) && | 2074 | if (!(bond_dev->features & NETIF_F_VLAN_CHALLENGED) && |
@@ -2373,8 +2374,6 @@ static void bond_miimon_commit(struct bonding *bond) | |||
2373 | bond_set_backup_slave(slave); | 2374 | bond_set_backup_slave(slave); |
2374 | } | 2375 | } |
2375 | 2376 | ||
2376 | bond_update_speed_duplex(slave); | ||
2377 | |||
2378 | pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n", | 2377 | pr_info("%s: link status definitely up for interface %s, %u Mbps %s duplex.\n", |
2379 | bond->dev->name, slave->dev->name, | 2378 | bond->dev->name, slave->dev->name, |
2380 | slave->speed, slave->duplex ? "full" : "half"); | 2379 | slave->speed, slave->duplex ? "full" : "half"); |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 1c9e09fbdff8..db103e03ba05 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -183,6 +183,11 @@ int bond_create_slave_symlinks(struct net_device *master, | |||
183 | sprintf(linkname, "slave_%s", slave->name); | 183 | sprintf(linkname, "slave_%s", slave->name); |
184 | ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj), | 184 | ret = sysfs_create_link(&(master->dev.kobj), &(slave->dev.kobj), |
185 | linkname); | 185 | linkname); |
186 | |||
187 | /* free the master link created earlier in case of error */ | ||
188 | if (ret) | ||
189 | sysfs_remove_link(&(slave->dev.kobj), "master"); | ||
190 | |||
186 | return ret; | 191 | return ret; |
187 | 192 | ||
188 | } | 193 | } |
diff --git a/drivers/net/ethernet/broadcom/bgmac.c b/drivers/net/ethernet/broadcom/bgmac.c index 639049d7e92d..da5f4397f87c 100644 --- a/drivers/net/ethernet/broadcom/bgmac.c +++ b/drivers/net/ethernet/broadcom/bgmac.c | |||
@@ -301,12 +301,16 @@ static int bgmac_dma_rx_read(struct bgmac *bgmac, struct bgmac_dma_ring *ring, | |||
301 | bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n", | 301 | bgmac_err(bgmac, "Found poisoned packet at slot %d, DMA issue!\n", |
302 | ring->start); | 302 | ring->start); |
303 | } else { | 303 | } else { |
304 | /* Omit CRC. */ | ||
305 | len -= ETH_FCS_LEN; | ||
306 | |||
304 | new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len); | 307 | new_skb = netdev_alloc_skb_ip_align(bgmac->net_dev, len); |
305 | if (new_skb) { | 308 | if (new_skb) { |
306 | skb_put(new_skb, len); | 309 | skb_put(new_skb, len); |
307 | skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET, | 310 | skb_copy_from_linear_data_offset(skb, BGMAC_RX_FRAME_OFFSET, |
308 | new_skb->data, | 311 | new_skb->data, |
309 | len); | 312 | len); |
313 | skb_checksum_none_assert(skb); | ||
310 | new_skb->protocol = | 314 | new_skb->protocol = |
311 | eth_type_trans(new_skb, bgmac->net_dev); | 315 | eth_type_trans(new_skb, bgmac->net_dev); |
312 | netif_receive_skb(new_skb); | 316 | netif_receive_skb(new_skb); |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index ecac04a3687c..4046f97378c2 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -2760,6 +2760,7 @@ load_error2: | |||
2760 | bp->port.pmf = 0; | 2760 | bp->port.pmf = 0; |
2761 | load_error1: | 2761 | load_error1: |
2762 | bnx2x_napi_disable(bp); | 2762 | bnx2x_napi_disable(bp); |
2763 | bnx2x_del_all_napi(bp); | ||
2763 | 2764 | ||
2764 | /* clear pf_load status, as it was already set */ | 2765 | /* clear pf_load status, as it was already set */ |
2765 | if (IS_PF(bp)) | 2766 | if (IS_PF(bp)) |
@@ -3142,7 +3143,7 @@ static inline __le16 bnx2x_csum_fix(unsigned char *t_header, u16 csum, s8 fix) | |||
3142 | tsum = ~csum_fold(csum_add((__force __wsum) csum, | 3143 | tsum = ~csum_fold(csum_add((__force __wsum) csum, |
3143 | csum_partial(t_header, -fix, 0))); | 3144 | csum_partial(t_header, -fix, 0))); |
3144 | 3145 | ||
3145 | return bswab16(csum); | 3146 | return bswab16(tsum); |
3146 | } | 3147 | } |
3147 | 3148 | ||
3148 | static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) | 3149 | static inline u32 bnx2x_xmit_type(struct bnx2x *bp, struct sk_buff *skb) |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c index 568205436a15..91ecd6a00d05 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_dcb.c | |||
@@ -2139,12 +2139,12 @@ static u8 bnx2x_dcbnl_get_cap(struct net_device *netdev, int capid, u8 *cap) | |||
2139 | break; | 2139 | break; |
2140 | default: | 2140 | default: |
2141 | BNX2X_ERR("Non valid capability ID\n"); | 2141 | BNX2X_ERR("Non valid capability ID\n"); |
2142 | rval = -EINVAL; | 2142 | rval = 1; |
2143 | break; | 2143 | break; |
2144 | } | 2144 | } |
2145 | } else { | 2145 | } else { |
2146 | DP(BNX2X_MSG_DCB, "DCB disabled\n"); | 2146 | DP(BNX2X_MSG_DCB, "DCB disabled\n"); |
2147 | rval = -EINVAL; | 2147 | rval = 1; |
2148 | } | 2148 | } |
2149 | 2149 | ||
2150 | DP(BNX2X_MSG_DCB, "capid %d:%x\n", capid, *cap); | 2150 | DP(BNX2X_MSG_DCB, "capid %d:%x\n", capid, *cap); |
@@ -2170,12 +2170,12 @@ static int bnx2x_dcbnl_get_numtcs(struct net_device *netdev, int tcid, u8 *num) | |||
2170 | break; | 2170 | break; |
2171 | default: | 2171 | default: |
2172 | BNX2X_ERR("Non valid TC-ID\n"); | 2172 | BNX2X_ERR("Non valid TC-ID\n"); |
2173 | rval = -EINVAL; | 2173 | rval = 1; |
2174 | break; | 2174 | break; |
2175 | } | 2175 | } |
2176 | } else { | 2176 | } else { |
2177 | DP(BNX2X_MSG_DCB, "DCB disabled\n"); | 2177 | DP(BNX2X_MSG_DCB, "DCB disabled\n"); |
2178 | rval = -EINVAL; | 2178 | rval = 1; |
2179 | } | 2179 | } |
2180 | 2180 | ||
2181 | return rval; | 2181 | return rval; |
@@ -2188,7 +2188,7 @@ static int bnx2x_dcbnl_set_numtcs(struct net_device *netdev, int tcid, u8 num) | |||
2188 | return -EINVAL; | 2188 | return -EINVAL; |
2189 | } | 2189 | } |
2190 | 2190 | ||
2191 | static u8 bnx2x_dcbnl_get_pfc_state(struct net_device *netdev) | 2191 | static u8 bnx2x_dcbnl_get_pfc_state(struct net_device *netdev) |
2192 | { | 2192 | { |
2193 | struct bnx2x *bp = netdev_priv(netdev); | 2193 | struct bnx2x *bp = netdev_priv(netdev); |
2194 | DP(BNX2X_MSG_DCB, "state = %d\n", bp->dcbx_local_feat.pfc.enabled); | 2194 | DP(BNX2X_MSG_DCB, "state = %d\n", bp->dcbx_local_feat.pfc.enabled); |
@@ -2390,12 +2390,12 @@ static u8 bnx2x_dcbnl_get_featcfg(struct net_device *netdev, int featid, | |||
2390 | break; | 2390 | break; |
2391 | default: | 2391 | default: |
2392 | BNX2X_ERR("Non valid featrue-ID\n"); | 2392 | BNX2X_ERR("Non valid featrue-ID\n"); |
2393 | rval = -EINVAL; | 2393 | rval = 1; |
2394 | break; | 2394 | break; |
2395 | } | 2395 | } |
2396 | } else { | 2396 | } else { |
2397 | DP(BNX2X_MSG_DCB, "DCB disabled\n"); | 2397 | DP(BNX2X_MSG_DCB, "DCB disabled\n"); |
2398 | rval = -EINVAL; | 2398 | rval = 1; |
2399 | } | 2399 | } |
2400 | 2400 | ||
2401 | return rval; | 2401 | return rval; |
@@ -2431,12 +2431,12 @@ static u8 bnx2x_dcbnl_set_featcfg(struct net_device *netdev, int featid, | |||
2431 | break; | 2431 | break; |
2432 | default: | 2432 | default: |
2433 | BNX2X_ERR("Non valid featrue-ID\n"); | 2433 | BNX2X_ERR("Non valid featrue-ID\n"); |
2434 | rval = -EINVAL; | 2434 | rval = 1; |
2435 | break; | 2435 | break; |
2436 | } | 2436 | } |
2437 | } else { | 2437 | } else { |
2438 | DP(BNX2X_MSG_DCB, "dcbnl call not valid\n"); | 2438 | DP(BNX2X_MSG_DCB, "dcbnl call not valid\n"); |
2439 | rval = -EINVAL; | 2439 | rval = 1; |
2440 | } | 2440 | } |
2441 | 2441 | ||
2442 | return rval; | 2442 | return rval; |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 9a674b14b403..edfa67adf2f9 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | |||
@@ -281,6 +281,8 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
281 | cmd->lp_advertising |= ADVERTISED_2500baseX_Full; | 281 | cmd->lp_advertising |= ADVERTISED_2500baseX_Full; |
282 | if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE) | 282 | if (status & LINK_STATUS_LINK_PARTNER_10GXFD_CAPABLE) |
283 | cmd->lp_advertising |= ADVERTISED_10000baseT_Full; | 283 | cmd->lp_advertising |= ADVERTISED_10000baseT_Full; |
284 | if (status & LINK_STATUS_LINK_PARTNER_20GXFD_CAPABLE) | ||
285 | cmd->lp_advertising |= ADVERTISED_20000baseKR2_Full; | ||
284 | } | 286 | } |
285 | 287 | ||
286 | cmd->maxtxpkt = 0; | 288 | cmd->maxtxpkt = 0; |
@@ -463,6 +465,10 @@ static int bnx2x_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
463 | ADVERTISED_10000baseKR_Full)) | 465 | ADVERTISED_10000baseKR_Full)) |
464 | bp->link_params.speed_cap_mask[cfg_idx] |= | 466 | bp->link_params.speed_cap_mask[cfg_idx] |= |
465 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G; | 467 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G; |
468 | |||
469 | if (cmd->advertising & ADVERTISED_20000baseKR2_Full) | ||
470 | bp->link_params.speed_cap_mask[cfg_idx] |= | ||
471 | PORT_HW_CFG_SPEED_CAPABILITY_D0_20G; | ||
466 | } | 472 | } |
467 | } else { /* forced speed */ | 473 | } else { /* forced speed */ |
468 | /* advertise the requested speed and duplex if supported */ | 474 | /* advertise the requested speed and duplex if supported */ |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c index 1663e0b6b5a0..77ebae0ac64a 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c | |||
@@ -8647,7 +8647,9 @@ void bnx2x_handle_module_detect_int(struct link_params *params) | |||
8647 | MDIO_WC_DEVAD, | 8647 | MDIO_WC_DEVAD, |
8648 | MDIO_WC_REG_DIGITAL5_MISC6, | 8648 | MDIO_WC_REG_DIGITAL5_MISC6, |
8649 | &rx_tx_in_reset); | 8649 | &rx_tx_in_reset); |
8650 | if (!rx_tx_in_reset) { | 8650 | if ((!rx_tx_in_reset) && |
8651 | (params->link_flags & | ||
8652 | PHY_INITIALIZED)) { | ||
8651 | bnx2x_warpcore_reset_lane(bp, phy, 1); | 8653 | bnx2x_warpcore_reset_lane(bp, phy, 1); |
8652 | bnx2x_warpcore_config_sfi(phy, params); | 8654 | bnx2x_warpcore_config_sfi(phy, params); |
8653 | bnx2x_warpcore_reset_lane(bp, phy, 0); | 8655 | bnx2x_warpcore_reset_lane(bp, phy, 0); |
@@ -10422,6 +10424,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, | |||
10422 | MDIO_PMA_DEVAD, | 10424 | MDIO_PMA_DEVAD, |
10423 | MDIO_PMA_REG_8481_LED1_MASK, | 10425 | MDIO_PMA_REG_8481_LED1_MASK, |
10424 | 0x0); | 10426 | 0x0); |
10427 | if (phy->type == | ||
10428 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { | ||
10429 | /* Disable MI_INT interrupt before setting LED4 | ||
10430 | * source to constant off. | ||
10431 | */ | ||
10432 | if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10433 | params->port*4) & | ||
10434 | NIG_MASK_MI_INT) { | ||
10435 | params->link_flags |= | ||
10436 | LINK_FLAGS_INT_DISABLED; | ||
10437 | |||
10438 | bnx2x_bits_dis( | ||
10439 | bp, | ||
10440 | NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10441 | params->port*4, | ||
10442 | NIG_MASK_MI_INT); | ||
10443 | } | ||
10444 | bnx2x_cl45_write(bp, phy, | ||
10445 | MDIO_PMA_DEVAD, | ||
10446 | MDIO_PMA_REG_8481_SIGNAL_MASK, | ||
10447 | 0x0); | ||
10448 | } | ||
10425 | } | 10449 | } |
10426 | break; | 10450 | break; |
10427 | case LED_MODE_ON: | 10451 | case LED_MODE_ON: |
@@ -10468,6 +10492,28 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, | |||
10468 | MDIO_PMA_DEVAD, | 10492 | MDIO_PMA_DEVAD, |
10469 | MDIO_PMA_REG_8481_LED1_MASK, | 10493 | MDIO_PMA_REG_8481_LED1_MASK, |
10470 | 0x20); | 10494 | 0x20); |
10495 | if (phy->type == | ||
10496 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { | ||
10497 | /* Disable MI_INT interrupt before setting LED4 | ||
10498 | * source to constant on. | ||
10499 | */ | ||
10500 | if (REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10501 | params->port*4) & | ||
10502 | NIG_MASK_MI_INT) { | ||
10503 | params->link_flags |= | ||
10504 | LINK_FLAGS_INT_DISABLED; | ||
10505 | |||
10506 | bnx2x_bits_dis( | ||
10507 | bp, | ||
10508 | NIG_REG_MASK_INTERRUPT_PORT0 + | ||
10509 | params->port*4, | ||
10510 | NIG_MASK_MI_INT); | ||
10511 | } | ||
10512 | bnx2x_cl45_write(bp, phy, | ||
10513 | MDIO_PMA_DEVAD, | ||
10514 | MDIO_PMA_REG_8481_SIGNAL_MASK, | ||
10515 | 0x20); | ||
10516 | } | ||
10471 | } | 10517 | } |
10472 | break; | 10518 | break; |
10473 | 10519 | ||
@@ -10532,6 +10578,22 @@ static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy, | |||
10532 | MDIO_PMA_DEVAD, | 10578 | MDIO_PMA_DEVAD, |
10533 | MDIO_PMA_REG_8481_LINK_SIGNAL, | 10579 | MDIO_PMA_REG_8481_LINK_SIGNAL, |
10534 | val); | 10580 | val); |
10581 | if (phy->type == | ||
10582 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84834) { | ||
10583 | /* Restore LED4 source to external link, | ||
10584 | * and re-enable interrupts. | ||
10585 | */ | ||
10586 | bnx2x_cl45_write(bp, phy, | ||
10587 | MDIO_PMA_DEVAD, | ||
10588 | MDIO_PMA_REG_8481_SIGNAL_MASK, | ||
10589 | 0x40); | ||
10590 | if (params->link_flags & | ||
10591 | LINK_FLAGS_INT_DISABLED) { | ||
10592 | bnx2x_link_int_enable(params); | ||
10593 | params->link_flags &= | ||
10594 | ~LINK_FLAGS_INT_DISABLED; | ||
10595 | } | ||
10596 | } | ||
10535 | } | 10597 | } |
10536 | break; | 10598 | break; |
10537 | } | 10599 | } |
@@ -11791,6 +11853,8 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port, | |||
11791 | phy->media_type = ETH_PHY_KR; | 11853 | phy->media_type = ETH_PHY_KR; |
11792 | phy->flags |= FLAGS_WC_DUAL_MODE; | 11854 | phy->flags |= FLAGS_WC_DUAL_MODE; |
11793 | phy->supported &= (SUPPORTED_20000baseKR2_Full | | 11855 | phy->supported &= (SUPPORTED_20000baseKR2_Full | |
11856 | SUPPORTED_10000baseT_Full | | ||
11857 | SUPPORTED_1000baseT_Full | | ||
11794 | SUPPORTED_Autoneg | | 11858 | SUPPORTED_Autoneg | |
11795 | SUPPORTED_FIBRE | | 11859 | SUPPORTED_FIBRE | |
11796 | SUPPORTED_Pause | | 11860 | SUPPORTED_Pause | |
@@ -12465,6 +12529,8 @@ int bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | |||
12465 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | 12529 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; |
12466 | vars->mac_type = MAC_TYPE_NONE; | 12530 | vars->mac_type = MAC_TYPE_NONE; |
12467 | vars->phy_flags = 0; | 12531 | vars->phy_flags = 0; |
12532 | vars->check_kr2_recovery_cnt = 0; | ||
12533 | params->link_flags = PHY_INITIALIZED; | ||
12468 | /* Driver opens NIG-BRB filters */ | 12534 | /* Driver opens NIG-BRB filters */ |
12469 | bnx2x_set_rx_filter(params, 1); | 12535 | bnx2x_set_rx_filter(params, 1); |
12470 | /* Check if link flap can be avoided */ | 12536 | /* Check if link flap can be avoided */ |
@@ -12629,6 +12695,7 @@ int bnx2x_lfa_reset(struct link_params *params, | |||
12629 | struct bnx2x *bp = params->bp; | 12695 | struct bnx2x *bp = params->bp; |
12630 | vars->link_up = 0; | 12696 | vars->link_up = 0; |
12631 | vars->phy_flags = 0; | 12697 | vars->phy_flags = 0; |
12698 | params->link_flags &= ~PHY_INITIALIZED; | ||
12632 | if (!params->lfa_base) | 12699 | if (!params->lfa_base) |
12633 | return bnx2x_link_reset(params, vars, 1); | 12700 | return bnx2x_link_reset(params, vars, 1); |
12634 | /* | 12701 | /* |
@@ -13349,6 +13416,7 @@ static void bnx2x_disable_kr2(struct link_params *params, | |||
13349 | vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE; | 13416 | vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE; |
13350 | bnx2x_update_link_attr(params, vars->link_attr_sync); | 13417 | bnx2x_update_link_attr(params, vars->link_attr_sync); |
13351 | 13418 | ||
13419 | vars->check_kr2_recovery_cnt = CHECK_KR2_RECOVERY_CNT; | ||
13352 | /* Restart AN on leading lane */ | 13420 | /* Restart AN on leading lane */ |
13353 | bnx2x_warpcore_restart_AN_KR(phy, params); | 13421 | bnx2x_warpcore_restart_AN_KR(phy, params); |
13354 | } | 13422 | } |
@@ -13377,6 +13445,15 @@ static void bnx2x_check_kr2_wa(struct link_params *params, | |||
13377 | return; | 13445 | return; |
13378 | } | 13446 | } |
13379 | 13447 | ||
13448 | /* Once KR2 was disabled, wait 5 seconds before checking KR2 recovery | ||
13449 | * since some switches tend to reinit the AN process and clear the | ||
13450 | * advertised BP/NP after ~2 seconds causing the KR2 to be disabled | ||
13451 | * and recovered many times | ||
13452 | */ | ||
13453 | if (vars->check_kr2_recovery_cnt > 0) { | ||
13454 | vars->check_kr2_recovery_cnt--; | ||
13455 | return; | ||
13456 | } | ||
13380 | lane = bnx2x_get_warpcore_lane(phy, params); | 13457 | lane = bnx2x_get_warpcore_lane(phy, params); |
13381 | CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, | 13458 | CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, |
13382 | MDIO_AER_BLOCK_AER_REG, lane); | 13459 | MDIO_AER_BLOCK_AER_REG, lane); |
@@ -13437,7 +13514,7 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars) | |||
13437 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; | 13514 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; |
13438 | bnx2x_set_aer_mmd(params, phy); | 13515 | bnx2x_set_aer_mmd(params, phy); |
13439 | if ((phy->supported & SUPPORTED_20000baseKR2_Full) && | 13516 | if ((phy->supported & SUPPORTED_20000baseKR2_Full) && |
13440 | (phy->speed_cap_mask & SPEED_20000)) | 13517 | (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) |
13441 | bnx2x_check_kr2_wa(params, vars, phy); | 13518 | bnx2x_check_kr2_wa(params, vars, phy); |
13442 | bnx2x_check_over_curr(params, vars); | 13519 | bnx2x_check_over_curr(params, vars); |
13443 | if (vars->rx_tx_asic_rst) | 13520 | if (vars->rx_tx_asic_rst) |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h index d25c7d79787a..56c2aae4e2c8 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.h | |||
@@ -307,7 +307,9 @@ struct link_params { | |||
307 | struct bnx2x *bp; | 307 | struct bnx2x *bp; |
308 | u16 req_fc_auto_adv; /* Should be set to TX / BOTH when | 308 | u16 req_fc_auto_adv; /* Should be set to TX / BOTH when |
309 | req_flow_ctrl is set to AUTO */ | 309 | req_flow_ctrl is set to AUTO */ |
310 | u16 rsrv1; | 310 | u16 link_flags; |
311 | #define LINK_FLAGS_INT_DISABLED (1<<0) | ||
312 | #define PHY_INITIALIZED (1<<1) | ||
311 | u32 lfa_base; | 313 | u32 lfa_base; |
312 | }; | 314 | }; |
313 | 315 | ||
@@ -341,7 +343,8 @@ struct link_vars { | |||
341 | u32 link_status; | 343 | u32 link_status; |
342 | u32 eee_status; | 344 | u32 eee_status; |
343 | u8 fault_detected; | 345 | u8 fault_detected; |
344 | u8 rsrv1; | 346 | u8 check_kr2_recovery_cnt; |
347 | #define CHECK_KR2_RECOVERY_CNT 5 | ||
345 | u16 periodic_flags; | 348 | u16 periodic_flags; |
346 | #define PERIODIC_FLAGS_LINK_EVENT 0x0001 | 349 | #define PERIODIC_FLAGS_LINK_EVENT 0x0001 |
347 | 350 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h index 364e37ecbc5c..198f6f1c9ad5 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.h | |||
@@ -459,8 +459,9 @@ struct bnx2x_fw_port_stats_old { | |||
459 | 459 | ||
460 | #define UPDATE_QSTAT(s, t) \ | 460 | #define UPDATE_QSTAT(s, t) \ |
461 | do { \ | 461 | do { \ |
462 | qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi); \ | ||
463 | qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \ | 462 | qstats->t##_lo = qstats_old->t##_lo + le32_to_cpu(s.lo); \ |
463 | qstats->t##_hi = qstats_old->t##_hi + le32_to_cpu(s.hi) \ | ||
464 | + ((qstats->t##_lo < qstats_old->t##_lo) ? 1 : 0); \ | ||
464 | } while (0) | 465 | } while (0) |
465 | 466 | ||
466 | #define UPDATE_QSTAT_OLD(f) \ | 467 | #define UPDATE_QSTAT_OLD(f) \ |
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index fdb9b5655414..67d2663b3974 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -1869,6 +1869,8 @@ static void tg3_link_report(struct tg3 *tp) | |||
1869 | 1869 | ||
1870 | tg3_ump_link_report(tp); | 1870 | tg3_ump_link_report(tp); |
1871 | } | 1871 | } |
1872 | |||
1873 | tp->link_up = netif_carrier_ok(tp->dev); | ||
1872 | } | 1874 | } |
1873 | 1875 | ||
1874 | static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) | 1876 | static u16 tg3_advert_flowctrl_1000X(u8 flow_ctrl) |
@@ -2522,12 +2524,6 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) | |||
2522 | return err; | 2524 | return err; |
2523 | } | 2525 | } |
2524 | 2526 | ||
2525 | static void tg3_carrier_on(struct tg3 *tp) | ||
2526 | { | ||
2527 | netif_carrier_on(tp->dev); | ||
2528 | tp->link_up = true; | ||
2529 | } | ||
2530 | |||
2531 | static void tg3_carrier_off(struct tg3 *tp) | 2527 | static void tg3_carrier_off(struct tg3 *tp) |
2532 | { | 2528 | { |
2533 | netif_carrier_off(tp->dev); | 2529 | netif_carrier_off(tp->dev); |
@@ -2553,7 +2549,7 @@ static int tg3_phy_reset(struct tg3 *tp) | |||
2553 | return -EBUSY; | 2549 | return -EBUSY; |
2554 | 2550 | ||
2555 | if (netif_running(tp->dev) && tp->link_up) { | 2551 | if (netif_running(tp->dev) && tp->link_up) { |
2556 | tg3_carrier_off(tp); | 2552 | netif_carrier_off(tp->dev); |
2557 | tg3_link_report(tp); | 2553 | tg3_link_report(tp); |
2558 | } | 2554 | } |
2559 | 2555 | ||
@@ -4134,6 +4130,14 @@ static void tg3_phy_copper_begin(struct tg3 *tp) | |||
4134 | tp->link_config.active_speed = tp->link_config.speed; | 4130 | tp->link_config.active_speed = tp->link_config.speed; |
4135 | tp->link_config.active_duplex = tp->link_config.duplex; | 4131 | tp->link_config.active_duplex = tp->link_config.duplex; |
4136 | 4132 | ||
4133 | if (tg3_asic_rev(tp) == ASIC_REV_5714) { | ||
4134 | /* With autoneg disabled, 5715 only links up when the | ||
4135 | * advertisement register has the configured speed | ||
4136 | * enabled. | ||
4137 | */ | ||
4138 | tg3_writephy(tp, MII_ADVERTISE, ADVERTISE_ALL); | ||
4139 | } | ||
4140 | |||
4137 | bmcr = 0; | 4141 | bmcr = 0; |
4138 | switch (tp->link_config.speed) { | 4142 | switch (tp->link_config.speed) { |
4139 | default: | 4143 | default: |
@@ -4262,9 +4266,9 @@ static bool tg3_test_and_report_link_chg(struct tg3 *tp, int curr_link_up) | |||
4262 | { | 4266 | { |
4263 | if (curr_link_up != tp->link_up) { | 4267 | if (curr_link_up != tp->link_up) { |
4264 | if (curr_link_up) { | 4268 | if (curr_link_up) { |
4265 | tg3_carrier_on(tp); | 4269 | netif_carrier_on(tp->dev); |
4266 | } else { | 4270 | } else { |
4267 | tg3_carrier_off(tp); | 4271 | netif_carrier_off(tp->dev); |
4268 | if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) | 4272 | if (tp->phy_flags & TG3_PHYFLG_MII_SERDES) |
4269 | tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; | 4273 | tp->phy_flags &= ~TG3_PHYFLG_PARALLEL_DETECT; |
4270 | } | 4274 | } |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 4ce62031f62f..8049268ce0f2 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | |||
@@ -497,8 +497,9 @@ int t4_memory_write(struct adapter *adap, int mtype, u32 addr, u32 len, | |||
497 | } | 497 | } |
498 | 498 | ||
499 | #define EEPROM_STAT_ADDR 0x7bfc | 499 | #define EEPROM_STAT_ADDR 0x7bfc |
500 | #define VPD_BASE 0 | ||
501 | #define VPD_LEN 512 | 500 | #define VPD_LEN 512 |
501 | #define VPD_BASE 0x400 | ||
502 | #define VPD_BASE_OLD 0 | ||
502 | 503 | ||
503 | /** | 504 | /** |
504 | * t4_seeprom_wp - enable/disable EEPROM write protection | 505 | * t4_seeprom_wp - enable/disable EEPROM write protection |
@@ -524,7 +525,7 @@ int t4_seeprom_wp(struct adapter *adapter, bool enable) | |||
524 | int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | 525 | int get_vpd_params(struct adapter *adapter, struct vpd_params *p) |
525 | { | 526 | { |
526 | u32 cclk_param, cclk_val; | 527 | u32 cclk_param, cclk_val; |
527 | int i, ret; | 528 | int i, ret, addr; |
528 | int ec, sn; | 529 | int ec, sn; |
529 | u8 *vpd, csum; | 530 | u8 *vpd, csum; |
530 | unsigned int vpdr_len, kw_offset, id_len; | 531 | unsigned int vpdr_len, kw_offset, id_len; |
@@ -533,7 +534,12 @@ int get_vpd_params(struct adapter *adapter, struct vpd_params *p) | |||
533 | if (!vpd) | 534 | if (!vpd) |
534 | return -ENOMEM; | 535 | return -ENOMEM; |
535 | 536 | ||
536 | ret = pci_read_vpd(adapter->pdev, VPD_BASE, VPD_LEN, vpd); | 537 | ret = pci_read_vpd(adapter->pdev, VPD_BASE, sizeof(u32), vpd); |
538 | if (ret < 0) | ||
539 | goto out; | ||
540 | addr = *vpd == 0x82 ? VPD_BASE : VPD_BASE_OLD; | ||
541 | |||
542 | ret = pci_read_vpd(adapter->pdev, addr, VPD_LEN, vpd); | ||
537 | if (ret < 0) | 543 | if (ret < 0) |
538 | goto out; | 544 | goto out; |
539 | 545 | ||
diff --git a/drivers/net/ethernet/dec/tulip/Kconfig b/drivers/net/ethernet/dec/tulip/Kconfig index 0c37fb2cc867..1df33c799c00 100644 --- a/drivers/net/ethernet/dec/tulip/Kconfig +++ b/drivers/net/ethernet/dec/tulip/Kconfig | |||
@@ -108,6 +108,7 @@ config TULIP_DM910X | |||
108 | config DE4X5 | 108 | config DE4X5 |
109 | tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA" | 109 | tristate "Generic DECchip & DIGITAL EtherWORKS PCI/EISA" |
110 | depends on (PCI || EISA) | 110 | depends on (PCI || EISA) |
111 | depends on VIRT_TO_BUS || ALPHA || PPC || SPARC | ||
111 | select CRC32 | 112 | select CRC32 |
112 | ---help--- | 113 | ---help--- |
113 | This is support for the DIGITAL series of PCI/EISA Ethernet cards. | 114 | This is support for the DIGITAL series of PCI/EISA Ethernet cards. |
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 28ceb8414185..29aff55f2eea 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -349,6 +349,7 @@ struct be_adapter { | |||
349 | struct pci_dev *pdev; | 349 | struct pci_dev *pdev; |
350 | struct net_device *netdev; | 350 | struct net_device *netdev; |
351 | 351 | ||
352 | u8 __iomem *csr; /* CSR BAR used only for BE2/3 */ | ||
352 | u8 __iomem *db; /* Door Bell */ | 353 | u8 __iomem *db; /* Door Bell */ |
353 | 354 | ||
354 | struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ | 355 | struct mutex mbox_lock; /* For serializing mbox cmds to BE card */ |
diff --git a/drivers/net/ethernet/emulex/benet/be_cmds.c b/drivers/net/ethernet/emulex/benet/be_cmds.c index 071aea79d218..3c9b4f12e3e5 100644 --- a/drivers/net/ethernet/emulex/benet/be_cmds.c +++ b/drivers/net/ethernet/emulex/benet/be_cmds.c | |||
@@ -473,19 +473,17 @@ static int be_mbox_notify_wait(struct be_adapter *adapter) | |||
473 | return 0; | 473 | return 0; |
474 | } | 474 | } |
475 | 475 | ||
476 | static int be_POST_stage_get(struct be_adapter *adapter, u16 *stage) | 476 | static u16 be_POST_stage_get(struct be_adapter *adapter) |
477 | { | 477 | { |
478 | u32 sem; | 478 | u32 sem; |
479 | u32 reg = skyhawk_chip(adapter) ? SLIPORT_SEMAPHORE_OFFSET_SH : | ||
480 | SLIPORT_SEMAPHORE_OFFSET_BE; | ||
481 | 479 | ||
482 | pci_read_config_dword(adapter->pdev, reg, &sem); | 480 | if (BEx_chip(adapter)) |
483 | *stage = sem & POST_STAGE_MASK; | 481 | sem = ioread32(adapter->csr + SLIPORT_SEMAPHORE_OFFSET_BEx); |
484 | |||
485 | if ((sem >> POST_ERR_SHIFT) & POST_ERR_MASK) | ||
486 | return -1; | ||
487 | else | 482 | else |
488 | return 0; | 483 | pci_read_config_dword(adapter->pdev, |
484 | SLIPORT_SEMAPHORE_OFFSET_SH, &sem); | ||
485 | |||
486 | return sem & POST_STAGE_MASK; | ||
489 | } | 487 | } |
490 | 488 | ||
491 | int lancer_wait_ready(struct be_adapter *adapter) | 489 | int lancer_wait_ready(struct be_adapter *adapter) |
@@ -579,19 +577,17 @@ int be_fw_wait_ready(struct be_adapter *adapter) | |||
579 | } | 577 | } |
580 | 578 | ||
581 | do { | 579 | do { |
582 | status = be_POST_stage_get(adapter, &stage); | 580 | stage = be_POST_stage_get(adapter); |
583 | if (status) { | 581 | if (stage == POST_STAGE_ARMFW_RDY) |
584 | dev_err(dev, "POST error; stage=0x%x\n", stage); | ||
585 | return -1; | ||
586 | } else if (stage != POST_STAGE_ARMFW_RDY) { | ||
587 | if (msleep_interruptible(2000)) { | ||
588 | dev_err(dev, "Waiting for POST aborted\n"); | ||
589 | return -EINTR; | ||
590 | } | ||
591 | timeout += 2; | ||
592 | } else { | ||
593 | return 0; | 582 | return 0; |
583 | |||
584 | dev_info(dev, "Waiting for POST, %ds elapsed\n", | ||
585 | timeout); | ||
586 | if (msleep_interruptible(2000)) { | ||
587 | dev_err(dev, "Waiting for POST aborted\n"); | ||
588 | return -EINTR; | ||
594 | } | 589 | } |
590 | timeout += 2; | ||
595 | } while (timeout < 60); | 591 | } while (timeout < 60); |
596 | 592 | ||
597 | dev_err(dev, "POST timeout; stage=0x%x\n", stage); | 593 | dev_err(dev, "POST timeout; stage=0x%x\n", stage); |
diff --git a/drivers/net/ethernet/emulex/benet/be_hw.h b/drivers/net/ethernet/emulex/benet/be_hw.h index 541d4530d5bf..62dc220695f7 100644 --- a/drivers/net/ethernet/emulex/benet/be_hw.h +++ b/drivers/net/ethernet/emulex/benet/be_hw.h | |||
@@ -32,8 +32,8 @@ | |||
32 | #define MPU_EP_CONTROL 0 | 32 | #define MPU_EP_CONTROL 0 |
33 | 33 | ||
34 | /********** MPU semphore: used for SH & BE *************/ | 34 | /********** MPU semphore: used for SH & BE *************/ |
35 | #define SLIPORT_SEMAPHORE_OFFSET_BE 0x7c | 35 | #define SLIPORT_SEMAPHORE_OFFSET_BEx 0xac /* CSR BAR offset */ |
36 | #define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 | 36 | #define SLIPORT_SEMAPHORE_OFFSET_SH 0x94 /* PCI-CFG offset */ |
37 | #define POST_STAGE_MASK 0x0000FFFF | 37 | #define POST_STAGE_MASK 0x0000FFFF |
38 | #define POST_ERR_MASK 0x1 | 38 | #define POST_ERR_MASK 0x1 |
39 | #define POST_ERR_SHIFT 31 | 39 | #define POST_ERR_SHIFT 31 |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 3860888ac711..08e54f3d288b 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -3688,6 +3688,8 @@ static void be_netdev_init(struct net_device *netdev) | |||
3688 | 3688 | ||
3689 | static void be_unmap_pci_bars(struct be_adapter *adapter) | 3689 | static void be_unmap_pci_bars(struct be_adapter *adapter) |
3690 | { | 3690 | { |
3691 | if (adapter->csr) | ||
3692 | pci_iounmap(adapter->pdev, adapter->csr); | ||
3691 | if (adapter->db) | 3693 | if (adapter->db) |
3692 | pci_iounmap(adapter->pdev, adapter->db); | 3694 | pci_iounmap(adapter->pdev, adapter->db); |
3693 | } | 3695 | } |
@@ -3721,6 +3723,12 @@ static int be_map_pci_bars(struct be_adapter *adapter) | |||
3721 | adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> | 3723 | adapter->if_type = (sli_intf & SLI_INTF_IF_TYPE_MASK) >> |
3722 | SLI_INTF_IF_TYPE_SHIFT; | 3724 | SLI_INTF_IF_TYPE_SHIFT; |
3723 | 3725 | ||
3726 | if (BEx_chip(adapter) && be_physfn(adapter)) { | ||
3727 | adapter->csr = pci_iomap(adapter->pdev, 2, 0); | ||
3728 | if (adapter->csr == NULL) | ||
3729 | return -ENOMEM; | ||
3730 | } | ||
3731 | |||
3724 | addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); | 3732 | addr = pci_iomap(adapter->pdev, db_bar(adapter), 0); |
3725 | if (addr == NULL) | 3733 | if (addr == NULL) |
3726 | goto pci_map_err; | 3734 | goto pci_map_err; |
@@ -4329,6 +4337,8 @@ static pci_ers_result_t be_eeh_reset(struct pci_dev *pdev) | |||
4329 | pci_restore_state(pdev); | 4337 | pci_restore_state(pdev); |
4330 | 4338 | ||
4331 | /* Check if card is ok and fw is ready */ | 4339 | /* Check if card is ok and fw is ready */ |
4340 | dev_info(&adapter->pdev->dev, | ||
4341 | "Waiting for FW to be ready after EEH reset\n"); | ||
4332 | status = be_fw_wait_ready(adapter); | 4342 | status = be_fw_wait_ready(adapter); |
4333 | if (status) | 4343 | if (status) |
4334 | return PCI_ERS_RESULT_DISCONNECT; | 4344 | return PCI_ERS_RESULT_DISCONNECT; |
diff --git a/drivers/net/ethernet/freescale/fec.c b/drivers/net/ethernet/freescale/fec.c index fccc3bf2141d..911d0253dbb2 100644 --- a/drivers/net/ethernet/freescale/fec.c +++ b/drivers/net/ethernet/freescale/fec.c | |||
@@ -246,14 +246,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
246 | struct bufdesc *bdp; | 246 | struct bufdesc *bdp; |
247 | void *bufaddr; | 247 | void *bufaddr; |
248 | unsigned short status; | 248 | unsigned short status; |
249 | unsigned long flags; | 249 | unsigned int index; |
250 | 250 | ||
251 | if (!fep->link) { | 251 | if (!fep->link) { |
252 | /* Link is down or autonegotiation is in progress. */ | 252 | /* Link is down or autonegotiation is in progress. */ |
253 | return NETDEV_TX_BUSY; | 253 | return NETDEV_TX_BUSY; |
254 | } | 254 | } |
255 | 255 | ||
256 | spin_lock_irqsave(&fep->hw_lock, flags); | ||
257 | /* Fill in a Tx ring entry */ | 256 | /* Fill in a Tx ring entry */ |
258 | bdp = fep->cur_tx; | 257 | bdp = fep->cur_tx; |
259 | 258 | ||
@@ -264,7 +263,6 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
264 | * This should not happen, since ndev->tbusy should be set. | 263 | * This should not happen, since ndev->tbusy should be set. |
265 | */ | 264 | */ |
266 | printk("%s: tx queue full!.\n", ndev->name); | 265 | printk("%s: tx queue full!.\n", ndev->name); |
267 | spin_unlock_irqrestore(&fep->hw_lock, flags); | ||
268 | return NETDEV_TX_BUSY; | 266 | return NETDEV_TX_BUSY; |
269 | } | 267 | } |
270 | 268 | ||
@@ -280,13 +278,13 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
280 | * 4-byte boundaries. Use bounce buffers to copy data | 278 | * 4-byte boundaries. Use bounce buffers to copy data |
281 | * and get it aligned. Ugh. | 279 | * and get it aligned. Ugh. |
282 | */ | 280 | */ |
281 | if (fep->bufdesc_ex) | ||
282 | index = (struct bufdesc_ex *)bdp - | ||
283 | (struct bufdesc_ex *)fep->tx_bd_base; | ||
284 | else | ||
285 | index = bdp - fep->tx_bd_base; | ||
286 | |||
283 | if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { | 287 | if (((unsigned long) bufaddr) & FEC_ALIGNMENT) { |
284 | unsigned int index; | ||
285 | if (fep->bufdesc_ex) | ||
286 | index = (struct bufdesc_ex *)bdp - | ||
287 | (struct bufdesc_ex *)fep->tx_bd_base; | ||
288 | else | ||
289 | index = bdp - fep->tx_bd_base; | ||
290 | memcpy(fep->tx_bounce[index], skb->data, skb->len); | 288 | memcpy(fep->tx_bounce[index], skb->data, skb->len); |
291 | bufaddr = fep->tx_bounce[index]; | 289 | bufaddr = fep->tx_bounce[index]; |
292 | } | 290 | } |
@@ -300,10 +298,7 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
300 | swap_buffer(bufaddr, skb->len); | 298 | swap_buffer(bufaddr, skb->len); |
301 | 299 | ||
302 | /* Save skb pointer */ | 300 | /* Save skb pointer */ |
303 | fep->tx_skbuff[fep->skb_cur] = skb; | 301 | fep->tx_skbuff[index] = skb; |
304 | |||
305 | ndev->stats.tx_bytes += skb->len; | ||
306 | fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK; | ||
307 | 302 | ||
308 | /* Push the data cache so the CPM does not get stale memory | 303 | /* Push the data cache so the CPM does not get stale memory |
309 | * data. | 304 | * data. |
@@ -331,26 +326,22 @@ fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
331 | ebdp->cbd_esc = BD_ENET_TX_INT; | 326 | ebdp->cbd_esc = BD_ENET_TX_INT; |
332 | } | 327 | } |
333 | } | 328 | } |
334 | /* Trigger transmission start */ | ||
335 | writel(0, fep->hwp + FEC_X_DES_ACTIVE); | ||
336 | |||
337 | /* If this was the last BD in the ring, start at the beginning again. */ | 329 | /* If this was the last BD in the ring, start at the beginning again. */ |
338 | if (status & BD_ENET_TX_WRAP) | 330 | if (status & BD_ENET_TX_WRAP) |
339 | bdp = fep->tx_bd_base; | 331 | bdp = fep->tx_bd_base; |
340 | else | 332 | else |
341 | bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); | 333 | bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); |
342 | 334 | ||
343 | if (bdp == fep->dirty_tx) { | 335 | fep->cur_tx = bdp; |
344 | fep->tx_full = 1; | 336 | |
337 | if (fep->cur_tx == fep->dirty_tx) | ||
345 | netif_stop_queue(ndev); | 338 | netif_stop_queue(ndev); |
346 | } | ||
347 | 339 | ||
348 | fep->cur_tx = bdp; | 340 | /* Trigger transmission start */ |
341 | writel(0, fep->hwp + FEC_X_DES_ACTIVE); | ||
349 | 342 | ||
350 | skb_tx_timestamp(skb); | 343 | skb_tx_timestamp(skb); |
351 | 344 | ||
352 | spin_unlock_irqrestore(&fep->hw_lock, flags); | ||
353 | |||
354 | return NETDEV_TX_OK; | 345 | return NETDEV_TX_OK; |
355 | } | 346 | } |
356 | 347 | ||
@@ -406,11 +397,8 @@ fec_restart(struct net_device *ndev, int duplex) | |||
406 | writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) | 397 | writel((unsigned long)fep->bd_dma + sizeof(struct bufdesc) |
407 | * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); | 398 | * RX_RING_SIZE, fep->hwp + FEC_X_DES_START); |
408 | 399 | ||
409 | fep->dirty_tx = fep->cur_tx = fep->tx_bd_base; | ||
410 | fep->cur_rx = fep->rx_bd_base; | 400 | fep->cur_rx = fep->rx_bd_base; |
411 | 401 | ||
412 | /* Reset SKB transmit buffers. */ | ||
413 | fep->skb_cur = fep->skb_dirty = 0; | ||
414 | for (i = 0; i <= TX_RING_MOD_MASK; i++) { | 402 | for (i = 0; i <= TX_RING_MOD_MASK; i++) { |
415 | if (fep->tx_skbuff[i]) { | 403 | if (fep->tx_skbuff[i]) { |
416 | dev_kfree_skb_any(fep->tx_skbuff[i]); | 404 | dev_kfree_skb_any(fep->tx_skbuff[i]); |
@@ -573,20 +561,35 @@ fec_enet_tx(struct net_device *ndev) | |||
573 | struct bufdesc *bdp; | 561 | struct bufdesc *bdp; |
574 | unsigned short status; | 562 | unsigned short status; |
575 | struct sk_buff *skb; | 563 | struct sk_buff *skb; |
564 | int index = 0; | ||
576 | 565 | ||
577 | fep = netdev_priv(ndev); | 566 | fep = netdev_priv(ndev); |
578 | spin_lock(&fep->hw_lock); | ||
579 | bdp = fep->dirty_tx; | 567 | bdp = fep->dirty_tx; |
580 | 568 | ||
569 | /* get next bdp of dirty_tx */ | ||
570 | if (bdp->cbd_sc & BD_ENET_TX_WRAP) | ||
571 | bdp = fep->tx_bd_base; | ||
572 | else | ||
573 | bdp = fec_enet_get_nextdesc(bdp, fep->bufdesc_ex); | ||
574 | |||
581 | while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { | 575 | while (((status = bdp->cbd_sc) & BD_ENET_TX_READY) == 0) { |
582 | if (bdp == fep->cur_tx && fep->tx_full == 0) | 576 | |
577 | /* current queue is empty */ | ||
578 | if (bdp == fep->cur_tx) | ||
583 | break; | 579 | break; |
584 | 580 | ||
581 | if (fep->bufdesc_ex) | ||
582 | index = (struct bufdesc_ex *)bdp - | ||
583 | (struct bufdesc_ex *)fep->tx_bd_base; | ||
584 | else | ||
585 | index = bdp - fep->tx_bd_base; | ||
586 | |||
585 | dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, | 587 | dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr, |
586 | FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); | 588 | FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE); |
587 | bdp->cbd_bufaddr = 0; | 589 | bdp->cbd_bufaddr = 0; |
588 | 590 | ||
589 | skb = fep->tx_skbuff[fep->skb_dirty]; | 591 | skb = fep->tx_skbuff[index]; |
592 | |||
590 | /* Check for errors. */ | 593 | /* Check for errors. */ |
591 | if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | | 594 | if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC | |
592 | BD_ENET_TX_RL | BD_ENET_TX_UN | | 595 | BD_ENET_TX_RL | BD_ENET_TX_UN | |
@@ -631,8 +634,9 @@ fec_enet_tx(struct net_device *ndev) | |||
631 | 634 | ||
632 | /* Free the sk buffer associated with this last transmit */ | 635 | /* Free the sk buffer associated with this last transmit */ |
633 | dev_kfree_skb_any(skb); | 636 | dev_kfree_skb_any(skb); |
634 | fep->tx_skbuff[fep->skb_dirty] = NULL; | 637 | fep->tx_skbuff[index] = NULL; |
635 | fep->skb_dirty = (fep->skb_dirty + 1) & TX_RING_MOD_MASK; | 638 | |
639 | fep->dirty_tx = bdp; | ||
636 | 640 | ||
637 | /* Update pointer to next buffer descriptor to be transmitted */ | 641 | /* Update pointer to next buffer descriptor to be transmitted */ |
638 | if (status & BD_ENET_TX_WRAP) | 642 | if (status & BD_ENET_TX_WRAP) |
@@ -642,14 +646,12 @@ fec_enet_tx(struct net_device *ndev) | |||
642 | 646 | ||
643 | /* Since we have freed up a buffer, the ring is no longer full | 647 | /* Since we have freed up a buffer, the ring is no longer full |
644 | */ | 648 | */ |
645 | if (fep->tx_full) { | 649 | if (fep->dirty_tx != fep->cur_tx) { |
646 | fep->tx_full = 0; | ||
647 | if (netif_queue_stopped(ndev)) | 650 | if (netif_queue_stopped(ndev)) |
648 | netif_wake_queue(ndev); | 651 | netif_wake_queue(ndev); |
649 | } | 652 | } |
650 | } | 653 | } |
651 | fep->dirty_tx = bdp; | 654 | return; |
652 | spin_unlock(&fep->hw_lock); | ||
653 | } | 655 | } |
654 | 656 | ||
655 | 657 | ||
@@ -816,7 +818,7 @@ fec_enet_interrupt(int irq, void *dev_id) | |||
816 | int_events = readl(fep->hwp + FEC_IEVENT); | 818 | int_events = readl(fep->hwp + FEC_IEVENT); |
817 | writel(int_events, fep->hwp + FEC_IEVENT); | 819 | writel(int_events, fep->hwp + FEC_IEVENT); |
818 | 820 | ||
819 | if (int_events & FEC_ENET_RXF) { | 821 | if (int_events & (FEC_ENET_RXF | FEC_ENET_TXF)) { |
820 | ret = IRQ_HANDLED; | 822 | ret = IRQ_HANDLED; |
821 | 823 | ||
822 | /* Disable the RX interrupt */ | 824 | /* Disable the RX interrupt */ |
@@ -827,15 +829,6 @@ fec_enet_interrupt(int irq, void *dev_id) | |||
827 | } | 829 | } |
828 | } | 830 | } |
829 | 831 | ||
830 | /* Transmit OK, or non-fatal error. Update the buffer | ||
831 | * descriptors. FEC handles all errors, we just discover | ||
832 | * them as part of the transmit process. | ||
833 | */ | ||
834 | if (int_events & FEC_ENET_TXF) { | ||
835 | ret = IRQ_HANDLED; | ||
836 | fec_enet_tx(ndev); | ||
837 | } | ||
838 | |||
839 | if (int_events & FEC_ENET_MII) { | 832 | if (int_events & FEC_ENET_MII) { |
840 | ret = IRQ_HANDLED; | 833 | ret = IRQ_HANDLED; |
841 | complete(&fep->mdio_done); | 834 | complete(&fep->mdio_done); |
@@ -851,6 +844,8 @@ static int fec_enet_rx_napi(struct napi_struct *napi, int budget) | |||
851 | int pkts = fec_enet_rx(ndev, budget); | 844 | int pkts = fec_enet_rx(ndev, budget); |
852 | struct fec_enet_private *fep = netdev_priv(ndev); | 845 | struct fec_enet_private *fep = netdev_priv(ndev); |
853 | 846 | ||
847 | fec_enet_tx(ndev); | ||
848 | |||
854 | if (pkts < budget) { | 849 | if (pkts < budget) { |
855 | napi_complete(napi); | 850 | napi_complete(napi); |
856 | writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); | 851 | writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK); |
@@ -939,24 +934,28 @@ static void fec_enet_adjust_link(struct net_device *ndev) | |||
939 | goto spin_unlock; | 934 | goto spin_unlock; |
940 | } | 935 | } |
941 | 936 | ||
942 | /* Duplex link change */ | ||
943 | if (phy_dev->link) { | 937 | if (phy_dev->link) { |
944 | if (fep->full_duplex != phy_dev->duplex) { | 938 | if (!fep->link) { |
945 | fec_restart(ndev, phy_dev->duplex); | ||
946 | /* prevent unnecessary second fec_restart() below */ | ||
947 | fep->link = phy_dev->link; | 939 | fep->link = phy_dev->link; |
948 | status_change = 1; | 940 | status_change = 1; |
949 | } | 941 | } |
950 | } | ||
951 | 942 | ||
952 | /* Link on or off change */ | 943 | if (fep->full_duplex != phy_dev->duplex) |
953 | if (phy_dev->link != fep->link) { | 944 | status_change = 1; |
954 | fep->link = phy_dev->link; | 945 | |
955 | if (phy_dev->link) | 946 | if (phy_dev->speed != fep->speed) { |
947 | fep->speed = phy_dev->speed; | ||
948 | status_change = 1; | ||
949 | } | ||
950 | |||
951 | /* if any of the above changed restart the FEC */ | ||
952 | if (status_change) | ||
956 | fec_restart(ndev, phy_dev->duplex); | 953 | fec_restart(ndev, phy_dev->duplex); |
957 | else | 954 | } else { |
955 | if (fep->link) { | ||
958 | fec_stop(ndev); | 956 | fec_stop(ndev); |
959 | status_change = 1; | 957 | status_change = 1; |
958 | } | ||
960 | } | 959 | } |
961 | 960 | ||
962 | spin_unlock: | 961 | spin_unlock: |
@@ -1333,7 +1332,7 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) | |||
1333 | static void fec_enet_free_buffers(struct net_device *ndev) | 1332 | static void fec_enet_free_buffers(struct net_device *ndev) |
1334 | { | 1333 | { |
1335 | struct fec_enet_private *fep = netdev_priv(ndev); | 1334 | struct fec_enet_private *fep = netdev_priv(ndev); |
1336 | int i; | 1335 | unsigned int i; |
1337 | struct sk_buff *skb; | 1336 | struct sk_buff *skb; |
1338 | struct bufdesc *bdp; | 1337 | struct bufdesc *bdp; |
1339 | 1338 | ||
@@ -1357,7 +1356,7 @@ static void fec_enet_free_buffers(struct net_device *ndev) | |||
1357 | static int fec_enet_alloc_buffers(struct net_device *ndev) | 1356 | static int fec_enet_alloc_buffers(struct net_device *ndev) |
1358 | { | 1357 | { |
1359 | struct fec_enet_private *fep = netdev_priv(ndev); | 1358 | struct fec_enet_private *fep = netdev_priv(ndev); |
1360 | int i; | 1359 | unsigned int i; |
1361 | struct sk_buff *skb; | 1360 | struct sk_buff *skb; |
1362 | struct bufdesc *bdp; | 1361 | struct bufdesc *bdp; |
1363 | 1362 | ||
@@ -1442,6 +1441,7 @@ fec_enet_close(struct net_device *ndev) | |||
1442 | struct fec_enet_private *fep = netdev_priv(ndev); | 1441 | struct fec_enet_private *fep = netdev_priv(ndev); |
1443 | 1442 | ||
1444 | /* Don't know what to do yet. */ | 1443 | /* Don't know what to do yet. */ |
1444 | napi_disable(&fep->napi); | ||
1445 | fep->opened = 0; | 1445 | fep->opened = 0; |
1446 | netif_stop_queue(ndev); | 1446 | netif_stop_queue(ndev); |
1447 | fec_stop(ndev); | 1447 | fec_stop(ndev); |
@@ -1598,7 +1598,7 @@ static int fec_enet_init(struct net_device *ndev) | |||
1598 | struct fec_enet_private *fep = netdev_priv(ndev); | 1598 | struct fec_enet_private *fep = netdev_priv(ndev); |
1599 | struct bufdesc *cbd_base; | 1599 | struct bufdesc *cbd_base; |
1600 | struct bufdesc *bdp; | 1600 | struct bufdesc *bdp; |
1601 | int i; | 1601 | unsigned int i; |
1602 | 1602 | ||
1603 | /* Allocate memory for buffer descriptors. */ | 1603 | /* Allocate memory for buffer descriptors. */ |
1604 | cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, | 1604 | cbd_base = dma_alloc_coherent(NULL, PAGE_SIZE, &fep->bd_dma, |
@@ -1646,6 +1646,7 @@ static int fec_enet_init(struct net_device *ndev) | |||
1646 | 1646 | ||
1647 | /* ...and the same for transmit */ | 1647 | /* ...and the same for transmit */ |
1648 | bdp = fep->tx_bd_base; | 1648 | bdp = fep->tx_bd_base; |
1649 | fep->cur_tx = bdp; | ||
1649 | for (i = 0; i < TX_RING_SIZE; i++) { | 1650 | for (i = 0; i < TX_RING_SIZE; i++) { |
1650 | 1651 | ||
1651 | /* Initialize the BD for every fragment in the page. */ | 1652 | /* Initialize the BD for every fragment in the page. */ |
@@ -1657,6 +1658,7 @@ static int fec_enet_init(struct net_device *ndev) | |||
1657 | /* Set the last buffer to wrap */ | 1658 | /* Set the last buffer to wrap */ |
1658 | bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); | 1659 | bdp = fec_enet_get_prevdesc(bdp, fep->bufdesc_ex); |
1659 | bdp->cbd_sc |= BD_SC_WRAP; | 1660 | bdp->cbd_sc |= BD_SC_WRAP; |
1661 | fep->dirty_tx = bdp; | ||
1660 | 1662 | ||
1661 | fec_restart(ndev, 0); | 1663 | fec_restart(ndev, 0); |
1662 | 1664 | ||
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index 01579b8e37c4..eb4372962839 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h | |||
@@ -97,6 +97,13 @@ struct bufdesc { | |||
97 | unsigned short cbd_sc; /* Control and status info */ | 97 | unsigned short cbd_sc; /* Control and status info */ |
98 | unsigned long cbd_bufaddr; /* Buffer address */ | 98 | unsigned long cbd_bufaddr; /* Buffer address */ |
99 | }; | 99 | }; |
100 | #else | ||
101 | struct bufdesc { | ||
102 | unsigned short cbd_sc; /* Control and status info */ | ||
103 | unsigned short cbd_datlen; /* Data length */ | ||
104 | unsigned long cbd_bufaddr; /* Buffer address */ | ||
105 | }; | ||
106 | #endif | ||
100 | 107 | ||
101 | struct bufdesc_ex { | 108 | struct bufdesc_ex { |
102 | struct bufdesc desc; | 109 | struct bufdesc desc; |
@@ -107,14 +114,6 @@ struct bufdesc_ex { | |||
107 | unsigned short res0[4]; | 114 | unsigned short res0[4]; |
108 | }; | 115 | }; |
109 | 116 | ||
110 | #else | ||
111 | struct bufdesc { | ||
112 | unsigned short cbd_sc; /* Control and status info */ | ||
113 | unsigned short cbd_datlen; /* Data length */ | ||
114 | unsigned long cbd_bufaddr; /* Buffer address */ | ||
115 | }; | ||
116 | #endif | ||
117 | |||
118 | /* | 117 | /* |
119 | * The following definitions courtesy of commproc.h, which where | 118 | * The following definitions courtesy of commproc.h, which where |
120 | * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). | 119 | * Copyright (c) 1997 Dan Malek (dmalek@jlc.net). |
@@ -214,8 +213,6 @@ struct fec_enet_private { | |||
214 | unsigned char *tx_bounce[TX_RING_SIZE]; | 213 | unsigned char *tx_bounce[TX_RING_SIZE]; |
215 | struct sk_buff *tx_skbuff[TX_RING_SIZE]; | 214 | struct sk_buff *tx_skbuff[TX_RING_SIZE]; |
216 | struct sk_buff *rx_skbuff[RX_RING_SIZE]; | 215 | struct sk_buff *rx_skbuff[RX_RING_SIZE]; |
217 | ushort skb_cur; | ||
218 | ushort skb_dirty; | ||
219 | 216 | ||
220 | /* CPM dual port RAM relative addresses */ | 217 | /* CPM dual port RAM relative addresses */ |
221 | dma_addr_t bd_dma; | 218 | dma_addr_t bd_dma; |
@@ -227,7 +224,6 @@ struct fec_enet_private { | |||
227 | /* The ring entries to be free()ed */ | 224 | /* The ring entries to be free()ed */ |
228 | struct bufdesc *dirty_tx; | 225 | struct bufdesc *dirty_tx; |
229 | 226 | ||
230 | uint tx_full; | ||
231 | /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ | 227 | /* hold while accessing the HW like ringbuffer for tx/rx but not MAC */ |
232 | spinlock_t hw_lock; | 228 | spinlock_t hw_lock; |
233 | 229 | ||
@@ -244,6 +240,7 @@ struct fec_enet_private { | |||
244 | phy_interface_t phy_interface; | 240 | phy_interface_t phy_interface; |
245 | int link; | 241 | int link; |
246 | int full_duplex; | 242 | int full_duplex; |
243 | int speed; | ||
247 | struct completion mdio_done; | 244 | struct completion mdio_done; |
248 | int irq[FEC_IRQ_NUM]; | 245 | int irq[FEC_IRQ_NUM]; |
249 | int bufdesc_ex; | 246 | int bufdesc_ex; |
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 1f17ca0f2201..0d8df400a479 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c | |||
@@ -128,6 +128,7 @@ void fec_ptp_start_cyclecounter(struct net_device *ndev) | |||
128 | 128 | ||
129 | spin_unlock_irqrestore(&fep->tmreg_lock, flags); | 129 | spin_unlock_irqrestore(&fep->tmreg_lock, flags); |
130 | } | 130 | } |
131 | EXPORT_SYMBOL(fec_ptp_start_cyclecounter); | ||
131 | 132 | ||
132 | /** | 133 | /** |
133 | * fec_ptp_adjfreq - adjust ptp cycle frequency | 134 | * fec_ptp_adjfreq - adjust ptp cycle frequency |
@@ -318,6 +319,7 @@ int fec_ptp_ioctl(struct net_device *ndev, struct ifreq *ifr, int cmd) | |||
318 | return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? | 319 | return copy_to_user(ifr->ifr_data, &config, sizeof(config)) ? |
319 | -EFAULT : 0; | 320 | -EFAULT : 0; |
320 | } | 321 | } |
322 | EXPORT_SYMBOL(fec_ptp_ioctl); | ||
321 | 323 | ||
322 | /** | 324 | /** |
323 | * fec_time_keep - call timecounter_read every second to avoid timer overrun | 325 | * fec_time_keep - call timecounter_read every second to avoid timer overrun |
@@ -383,3 +385,4 @@ void fec_ptp_init(struct net_device *ndev, struct platform_device *pdev) | |||
383 | pr_info("registered PHC device on %s\n", ndev->name); | 385 | pr_info("registered PHC device on %s\n", ndev->name); |
384 | } | 386 | } |
385 | } | 387 | } |
388 | EXPORT_SYMBOL(fec_ptp_init); | ||
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index 2c1813737f6d..f91a8f3f9d48 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/vmalloc.h> | 37 | #include <linux/vmalloc.h> |
38 | #include <linux/mdio.h> | 38 | #include <linux/mdio.h> |
39 | #include <linux/pm_runtime.h> | ||
39 | 40 | ||
40 | #include "e1000.h" | 41 | #include "e1000.h" |
41 | 42 | ||
@@ -2229,7 +2230,19 @@ static int e1000e_get_ts_info(struct net_device *netdev, | |||
2229 | return 0; | 2230 | return 0; |
2230 | } | 2231 | } |
2231 | 2232 | ||
2233 | static int e1000e_ethtool_begin(struct net_device *netdev) | ||
2234 | { | ||
2235 | return pm_runtime_get_sync(netdev->dev.parent); | ||
2236 | } | ||
2237 | |||
2238 | static void e1000e_ethtool_complete(struct net_device *netdev) | ||
2239 | { | ||
2240 | pm_runtime_put_sync(netdev->dev.parent); | ||
2241 | } | ||
2242 | |||
2232 | static const struct ethtool_ops e1000_ethtool_ops = { | 2243 | static const struct ethtool_ops e1000_ethtool_ops = { |
2244 | .begin = e1000e_ethtool_begin, | ||
2245 | .complete = e1000e_ethtool_complete, | ||
2233 | .get_settings = e1000_get_settings, | 2246 | .get_settings = e1000_get_settings, |
2234 | .set_settings = e1000_set_settings, | 2247 | .set_settings = e1000_set_settings, |
2235 | .get_drvinfo = e1000_get_drvinfo, | 2248 | .get_drvinfo = e1000_get_drvinfo, |
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index dff7bff8b8e0..121a865c7fbd 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c | |||
@@ -782,6 +782,59 @@ release: | |||
782 | } | 782 | } |
783 | 783 | ||
784 | /** | 784 | /** |
785 | * e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP | ||
786 | * @hw: pointer to the HW structure | ||
787 | * @link: link up bool flag | ||
788 | * | ||
789 | * When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications | ||
790 | * preventing further DMA write requests. Workaround the issue by disabling | ||
791 | * the de-assertion of the clock request when in 1Gpbs mode. | ||
792 | **/ | ||
793 | static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link) | ||
794 | { | ||
795 | u32 fextnvm6 = er32(FEXTNVM6); | ||
796 | s32 ret_val = 0; | ||
797 | |||
798 | if (link && (er32(STATUS) & E1000_STATUS_SPEED_1000)) { | ||
799 | u16 kmrn_reg; | ||
800 | |||
801 | ret_val = hw->phy.ops.acquire(hw); | ||
802 | if (ret_val) | ||
803 | return ret_val; | ||
804 | |||
805 | ret_val = | ||
806 | e1000e_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG, | ||
807 | &kmrn_reg); | ||
808 | if (ret_val) | ||
809 | goto release; | ||
810 | |||
811 | ret_val = | ||
812 | e1000e_write_kmrn_reg_locked(hw, | ||
813 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
814 | kmrn_reg & | ||
815 | ~E1000_KMRNCTRLSTA_K1_ENABLE); | ||
816 | if (ret_val) | ||
817 | goto release; | ||
818 | |||
819 | usleep_range(10, 20); | ||
820 | |||
821 | ew32(FEXTNVM6, fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK); | ||
822 | |||
823 | ret_val = | ||
824 | e1000e_write_kmrn_reg_locked(hw, | ||
825 | E1000_KMRNCTRLSTA_K1_CONFIG, | ||
826 | kmrn_reg); | ||
827 | release: | ||
828 | hw->phy.ops.release(hw); | ||
829 | } else { | ||
830 | /* clear FEXTNVM6 bit 8 on link down or 10/100 */ | ||
831 | ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); | ||
832 | } | ||
833 | |||
834 | return ret_val; | ||
835 | } | ||
836 | |||
837 | /** | ||
785 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) | 838 | * e1000_check_for_copper_link_ich8lan - Check for link (Copper) |
786 | * @hw: pointer to the HW structure | 839 | * @hw: pointer to the HW structure |
787 | * | 840 | * |
@@ -818,6 +871,14 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw) | |||
818 | return ret_val; | 871 | return ret_val; |
819 | } | 872 | } |
820 | 873 | ||
874 | /* Work-around I218 hang issue */ | ||
875 | if ((hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_LM) || | ||
876 | (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPTLP_I218_V)) { | ||
877 | ret_val = e1000_k1_workaround_lpt_lp(hw, link); | ||
878 | if (ret_val) | ||
879 | return ret_val; | ||
880 | } | ||
881 | |||
821 | /* Clear link partner's EEE ability */ | 882 | /* Clear link partner's EEE ability */ |
822 | hw->dev_spec.ich8lan.eee_lp_ability = 0; | 883 | hw->dev_spec.ich8lan.eee_lp_ability = 0; |
823 | 884 | ||
@@ -3954,8 +4015,16 @@ void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw) | |||
3954 | 4015 | ||
3955 | phy_ctrl = er32(PHY_CTRL); | 4016 | phy_ctrl = er32(PHY_CTRL); |
3956 | phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; | 4017 | phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE; |
4018 | |||
3957 | if (hw->phy.type == e1000_phy_i217) { | 4019 | if (hw->phy.type == e1000_phy_i217) { |
3958 | u16 phy_reg; | 4020 | u16 phy_reg, device_id = hw->adapter->pdev->device; |
4021 | |||
4022 | if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) || | ||
4023 | (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V)) { | ||
4024 | u32 fextnvm6 = er32(FEXTNVM6); | ||
4025 | |||
4026 | ew32(FEXTNVM6, fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK); | ||
4027 | } | ||
3959 | 4028 | ||
3960 | ret_val = hw->phy.ops.acquire(hw); | 4029 | ret_val = hw->phy.ops.acquire(hw); |
3961 | if (ret_val) | 4030 | if (ret_val) |
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.h b/drivers/net/ethernet/intel/e1000e/ich8lan.h index b6d3174d7d2d..8bf4655c2e17 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.h +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.h | |||
@@ -92,6 +92,8 @@ | |||
92 | #define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 | 92 | #define E1000_FEXTNVM4_BEACON_DURATION_8USEC 0x7 |
93 | #define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 | 93 | #define E1000_FEXTNVM4_BEACON_DURATION_16USEC 0x3 |
94 | 94 | ||
95 | #define E1000_FEXTNVM6_REQ_PLL_CLK 0x00000100 | ||
96 | |||
95 | #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL | 97 | #define PCIE_ICH8_SNOOP_ALL PCIE_NO_SNOOP_ALL |
96 | 98 | ||
97 | #define E1000_ICH_RAR_ENTRIES 7 | 99 | #define E1000_ICH_RAR_ENTRIES 7 |
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index a177b8b65c44..948b86ffa4f0 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c | |||
@@ -4303,6 +4303,7 @@ static int e1000_open(struct net_device *netdev) | |||
4303 | netif_start_queue(netdev); | 4303 | netif_start_queue(netdev); |
4304 | 4304 | ||
4305 | adapter->idle_check = true; | 4305 | adapter->idle_check = true; |
4306 | hw->mac.get_link_status = true; | ||
4306 | pm_runtime_put(&pdev->dev); | 4307 | pm_runtime_put(&pdev->dev); |
4307 | 4308 | ||
4308 | /* fire a link status change interrupt to start the watchdog */ | 4309 | /* fire a link status change interrupt to start the watchdog */ |
@@ -4662,6 +4663,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter) | |||
4662 | (adapter->hw.phy.media_type == e1000_media_type_copper)) { | 4663 | (adapter->hw.phy.media_type == e1000_media_type_copper)) { |
4663 | int ret_val; | 4664 | int ret_val; |
4664 | 4665 | ||
4666 | pm_runtime_get_sync(&adapter->pdev->dev); | ||
4665 | ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr); | 4667 | ret_val = e1e_rphy(hw, MII_BMCR, &phy->bmcr); |
4666 | ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr); | 4668 | ret_val |= e1e_rphy(hw, MII_BMSR, &phy->bmsr); |
4667 | ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise); | 4669 | ret_val |= e1e_rphy(hw, MII_ADVERTISE, &phy->advertise); |
@@ -4672,6 +4674,7 @@ static void e1000_phy_read_status(struct e1000_adapter *adapter) | |||
4672 | ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus); | 4674 | ret_val |= e1e_rphy(hw, MII_ESTATUS, &phy->estatus); |
4673 | if (ret_val) | 4675 | if (ret_val) |
4674 | e_warn("Error reading PHY register\n"); | 4676 | e_warn("Error reading PHY register\n"); |
4677 | pm_runtime_put_sync(&adapter->pdev->dev); | ||
4675 | } else { | 4678 | } else { |
4676 | /* Do not read PHY registers if link is not up | 4679 | /* Do not read PHY registers if link is not up |
4677 | * Set values to typical power-on defaults | 4680 | * Set values to typical power-on defaults |
@@ -5887,8 +5890,7 @@ release: | |||
5887 | return retval; | 5890 | return retval; |
5888 | } | 5891 | } |
5889 | 5892 | ||
5890 | static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, | 5893 | static int __e1000_shutdown(struct pci_dev *pdev, bool runtime) |
5891 | bool runtime) | ||
5892 | { | 5894 | { |
5893 | struct net_device *netdev = pci_get_drvdata(pdev); | 5895 | struct net_device *netdev = pci_get_drvdata(pdev); |
5894 | struct e1000_adapter *adapter = netdev_priv(netdev); | 5896 | struct e1000_adapter *adapter = netdev_priv(netdev); |
@@ -5912,10 +5914,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, | |||
5912 | } | 5914 | } |
5913 | e1000e_reset_interrupt_capability(adapter); | 5915 | e1000e_reset_interrupt_capability(adapter); |
5914 | 5916 | ||
5915 | retval = pci_save_state(pdev); | ||
5916 | if (retval) | ||
5917 | return retval; | ||
5918 | |||
5919 | status = er32(STATUS); | 5917 | status = er32(STATUS); |
5920 | if (status & E1000_STATUS_LU) | 5918 | if (status & E1000_STATUS_LU) |
5921 | wufc &= ~E1000_WUFC_LNKC; | 5919 | wufc &= ~E1000_WUFC_LNKC; |
@@ -5971,13 +5969,6 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, | |||
5971 | ew32(WUFC, 0); | 5969 | ew32(WUFC, 0); |
5972 | } | 5970 | } |
5973 | 5971 | ||
5974 | *enable_wake = !!wufc; | ||
5975 | |||
5976 | /* make sure adapter isn't asleep if manageability is enabled */ | ||
5977 | if ((adapter->flags & FLAG_MNG_PT_ENABLED) || | ||
5978 | (hw->mac.ops.check_mng_mode(hw))) | ||
5979 | *enable_wake = true; | ||
5980 | |||
5981 | if (adapter->hw.phy.type == e1000_phy_igp_3) | 5972 | if (adapter->hw.phy.type == e1000_phy_igp_3) |
5982 | e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); | 5973 | e1000e_igp3_phy_powerdown_workaround_ich8lan(&adapter->hw); |
5983 | 5974 | ||
@@ -5986,27 +5977,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, | |||
5986 | */ | 5977 | */ |
5987 | e1000e_release_hw_control(adapter); | 5978 | e1000e_release_hw_control(adapter); |
5988 | 5979 | ||
5989 | pci_disable_device(pdev); | 5980 | pci_clear_master(pdev); |
5990 | |||
5991 | return 0; | ||
5992 | } | ||
5993 | |||
5994 | static void e1000_power_off(struct pci_dev *pdev, bool sleep, bool wake) | ||
5995 | { | ||
5996 | if (sleep && wake) { | ||
5997 | pci_prepare_to_sleep(pdev); | ||
5998 | return; | ||
5999 | } | ||
6000 | |||
6001 | pci_wake_from_d3(pdev, wake); | ||
6002 | pci_set_power_state(pdev, PCI_D3hot); | ||
6003 | } | ||
6004 | |||
6005 | static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, | ||
6006 | bool wake) | ||
6007 | { | ||
6008 | struct net_device *netdev = pci_get_drvdata(pdev); | ||
6009 | struct e1000_adapter *adapter = netdev_priv(netdev); | ||
6010 | 5981 | ||
6011 | /* The pci-e switch on some quad port adapters will report a | 5982 | /* The pci-e switch on some quad port adapters will report a |
6012 | * correctable error when the MAC transitions from D0 to D3. To | 5983 | * correctable error when the MAC transitions from D0 to D3. To |
@@ -6021,12 +5992,13 @@ static void e1000_complete_shutdown(struct pci_dev *pdev, bool sleep, | |||
6021 | pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, | 5992 | pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, |
6022 | (devctl & ~PCI_EXP_DEVCTL_CERE)); | 5993 | (devctl & ~PCI_EXP_DEVCTL_CERE)); |
6023 | 5994 | ||
6024 | e1000_power_off(pdev, sleep, wake); | 5995 | pci_save_state(pdev); |
5996 | pci_prepare_to_sleep(pdev); | ||
6025 | 5997 | ||
6026 | pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl); | 5998 | pcie_capability_write_word(us_dev, PCI_EXP_DEVCTL, devctl); |
6027 | } else { | ||
6028 | e1000_power_off(pdev, sleep, wake); | ||
6029 | } | 5999 | } |
6000 | |||
6001 | return 0; | ||
6030 | } | 6002 | } |
6031 | 6003 | ||
6032 | #ifdef CONFIG_PCIEASPM | 6004 | #ifdef CONFIG_PCIEASPM |
@@ -6084,9 +6056,7 @@ static int __e1000_resume(struct pci_dev *pdev) | |||
6084 | if (aspm_disable_flag) | 6056 | if (aspm_disable_flag) |
6085 | e1000e_disable_aspm(pdev, aspm_disable_flag); | 6057 | e1000e_disable_aspm(pdev, aspm_disable_flag); |
6086 | 6058 | ||
6087 | pci_set_power_state(pdev, PCI_D0); | 6059 | pci_set_master(pdev); |
6088 | pci_restore_state(pdev); | ||
6089 | pci_save_state(pdev); | ||
6090 | 6060 | ||
6091 | e1000e_set_interrupt_capability(adapter); | 6061 | e1000e_set_interrupt_capability(adapter); |
6092 | if (netif_running(netdev)) { | 6062 | if (netif_running(netdev)) { |
@@ -6152,14 +6122,8 @@ static int __e1000_resume(struct pci_dev *pdev) | |||
6152 | static int e1000_suspend(struct device *dev) | 6122 | static int e1000_suspend(struct device *dev) |
6153 | { | 6123 | { |
6154 | struct pci_dev *pdev = to_pci_dev(dev); | 6124 | struct pci_dev *pdev = to_pci_dev(dev); |
6155 | int retval; | ||
6156 | bool wake; | ||
6157 | |||
6158 | retval = __e1000_shutdown(pdev, &wake, false); | ||
6159 | if (!retval) | ||
6160 | e1000_complete_shutdown(pdev, true, wake); | ||
6161 | 6125 | ||
6162 | return retval; | 6126 | return __e1000_shutdown(pdev, false); |
6163 | } | 6127 | } |
6164 | 6128 | ||
6165 | static int e1000_resume(struct device *dev) | 6129 | static int e1000_resume(struct device *dev) |
@@ -6182,13 +6146,10 @@ static int e1000_runtime_suspend(struct device *dev) | |||
6182 | struct net_device *netdev = pci_get_drvdata(pdev); | 6146 | struct net_device *netdev = pci_get_drvdata(pdev); |
6183 | struct e1000_adapter *adapter = netdev_priv(netdev); | 6147 | struct e1000_adapter *adapter = netdev_priv(netdev); |
6184 | 6148 | ||
6185 | if (e1000e_pm_ready(adapter)) { | 6149 | if (!e1000e_pm_ready(adapter)) |
6186 | bool wake; | 6150 | return 0; |
6187 | |||
6188 | __e1000_shutdown(pdev, &wake, true); | ||
6189 | } | ||
6190 | 6151 | ||
6191 | return 0; | 6152 | return __e1000_shutdown(pdev, true); |
6192 | } | 6153 | } |
6193 | 6154 | ||
6194 | static int e1000_idle(struct device *dev) | 6155 | static int e1000_idle(struct device *dev) |
@@ -6226,12 +6187,7 @@ static int e1000_runtime_resume(struct device *dev) | |||
6226 | 6187 | ||
6227 | static void e1000_shutdown(struct pci_dev *pdev) | 6188 | static void e1000_shutdown(struct pci_dev *pdev) |
6228 | { | 6189 | { |
6229 | bool wake = false; | 6190 | __e1000_shutdown(pdev, false); |
6230 | |||
6231 | __e1000_shutdown(pdev, &wake, false); | ||
6232 | |||
6233 | if (system_state == SYSTEM_POWER_OFF) | ||
6234 | e1000_complete_shutdown(pdev, false, wake); | ||
6235 | } | 6191 | } |
6236 | 6192 | ||
6237 | #ifdef CONFIG_NET_POLL_CONTROLLER | 6193 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -6352,9 +6308,9 @@ static pci_ers_result_t e1000_io_slot_reset(struct pci_dev *pdev) | |||
6352 | "Cannot re-enable PCI device after reset.\n"); | 6308 | "Cannot re-enable PCI device after reset.\n"); |
6353 | result = PCI_ERS_RESULT_DISCONNECT; | 6309 | result = PCI_ERS_RESULT_DISCONNECT; |
6354 | } else { | 6310 | } else { |
6355 | pci_set_master(pdev); | ||
6356 | pdev->state_saved = true; | 6311 | pdev->state_saved = true; |
6357 | pci_restore_state(pdev); | 6312 | pci_restore_state(pdev); |
6313 | pci_set_master(pdev); | ||
6358 | 6314 | ||
6359 | pci_enable_wake(pdev, PCI_D3hot, 0); | 6315 | pci_enable_wake(pdev, PCI_D3hot, 0); |
6360 | pci_enable_wake(pdev, PCI_D3cold, 0); | 6316 | pci_enable_wake(pdev, PCI_D3cold, 0); |
@@ -6783,7 +6739,11 @@ static int e1000_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
6783 | 6739 | ||
6784 | /* initialize the wol settings based on the eeprom settings */ | 6740 | /* initialize the wol settings based on the eeprom settings */ |
6785 | adapter->wol = adapter->eeprom_wol; | 6741 | adapter->wol = adapter->eeprom_wol; |
6786 | device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol); | 6742 | |
6743 | /* make sure adapter isn't asleep if manageability is enabled */ | ||
6744 | if (adapter->wol || (adapter->flags & FLAG_MNG_PT_ENABLED) || | ||
6745 | (hw->mac.ops.check_mng_mode(hw))) | ||
6746 | device_wakeup_enable(&pdev->dev); | ||
6787 | 6747 | ||
6788 | /* save off EEPROM version number */ | 6748 | /* save off EEPROM version number */ |
6789 | e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers); | 6749 | e1000_read_nvm(&adapter->hw, 5, 1, &adapter->eeprom_vers); |
diff --git a/drivers/net/ethernet/intel/e1000e/regs.h b/drivers/net/ethernet/intel/e1000e/regs.h index 794fe1497666..a7e6a3e37257 100644 --- a/drivers/net/ethernet/intel/e1000e/regs.h +++ b/drivers/net/ethernet/intel/e1000e/regs.h | |||
@@ -42,6 +42,7 @@ | |||
42 | #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ | 42 | #define E1000_FEXTNVM 0x00028 /* Future Extended NVM - RW */ |
43 | #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ | 43 | #define E1000_FEXTNVM3 0x0003C /* Future Extended NVM 3 - RW */ |
44 | #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ | 44 | #define E1000_FEXTNVM4 0x00024 /* Future Extended NVM 4 - RW */ |
45 | #define E1000_FEXTNVM6 0x00010 /* Future Extended NVM 6 - RW */ | ||
45 | #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ | 46 | #define E1000_FEXTNVM7 0x000E4 /* Future Extended NVM 7 - RW */ |
46 | #define E1000_FCT 0x00030 /* Flow Control Type - RW */ | 47 | #define E1000_FCT 0x00030 /* Flow Control Type - RW */ |
47 | #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ | 48 | #define E1000_VET 0x00038 /* VLAN Ether Type - RW */ |
diff --git a/drivers/net/ethernet/intel/igb/e1000_82575.c b/drivers/net/ethernet/intel/igb/e1000_82575.c index 84e7e0909def..12b1d8480808 100644 --- a/drivers/net/ethernet/intel/igb/e1000_82575.c +++ b/drivers/net/ethernet/intel/igb/e1000_82575.c | |||
@@ -1361,11 +1361,16 @@ static s32 igb_setup_copper_link_82575(struct e1000_hw *hw) | |||
1361 | switch (hw->phy.type) { | 1361 | switch (hw->phy.type) { |
1362 | case e1000_phy_i210: | 1362 | case e1000_phy_i210: |
1363 | case e1000_phy_m88: | 1363 | case e1000_phy_m88: |
1364 | if (hw->phy.id == I347AT4_E_PHY_ID || | 1364 | switch (hw->phy.id) { |
1365 | hw->phy.id == M88E1112_E_PHY_ID) | 1365 | case I347AT4_E_PHY_ID: |
1366 | case M88E1112_E_PHY_ID: | ||
1367 | case I210_I_PHY_ID: | ||
1366 | ret_val = igb_copper_link_setup_m88_gen2(hw); | 1368 | ret_val = igb_copper_link_setup_m88_gen2(hw); |
1367 | else | 1369 | break; |
1370 | default: | ||
1368 | ret_val = igb_copper_link_setup_m88(hw); | 1371 | ret_val = igb_copper_link_setup_m88(hw); |
1372 | break; | ||
1373 | } | ||
1369 | break; | 1374 | break; |
1370 | case e1000_phy_igp_3: | 1375 | case e1000_phy_igp_3: |
1371 | ret_val = igb_copper_link_setup_igp(hw); | 1376 | ret_val = igb_copper_link_setup_igp(hw); |
@@ -1813,27 +1818,32 @@ out: | |||
1813 | **/ | 1818 | **/ |
1814 | void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) | 1819 | void igb_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) |
1815 | { | 1820 | { |
1816 | u32 dtxswc; | 1821 | u32 reg_val, reg_offset; |
1817 | 1822 | ||
1818 | switch (hw->mac.type) { | 1823 | switch (hw->mac.type) { |
1819 | case e1000_82576: | 1824 | case e1000_82576: |
1825 | reg_offset = E1000_DTXSWC; | ||
1826 | break; | ||
1820 | case e1000_i350: | 1827 | case e1000_i350: |
1821 | dtxswc = rd32(E1000_DTXSWC); | 1828 | reg_offset = E1000_TXSWC; |
1822 | if (enable) { | ||
1823 | dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK | | ||
1824 | E1000_DTXSWC_VLAN_SPOOF_MASK); | ||
1825 | /* The PF can spoof - it has to in order to | ||
1826 | * support emulation mode NICs */ | ||
1827 | dtxswc ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); | ||
1828 | } else { | ||
1829 | dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | | ||
1830 | E1000_DTXSWC_VLAN_SPOOF_MASK); | ||
1831 | } | ||
1832 | wr32(E1000_DTXSWC, dtxswc); | ||
1833 | break; | 1829 | break; |
1834 | default: | 1830 | default: |
1835 | break; | 1831 | return; |
1832 | } | ||
1833 | |||
1834 | reg_val = rd32(reg_offset); | ||
1835 | if (enable) { | ||
1836 | reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | | ||
1837 | E1000_DTXSWC_VLAN_SPOOF_MASK); | ||
1838 | /* The PF can spoof - it has to in order to | ||
1839 | * support emulation mode NICs | ||
1840 | */ | ||
1841 | reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); | ||
1842 | } else { | ||
1843 | reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | | ||
1844 | E1000_DTXSWC_VLAN_SPOOF_MASK); | ||
1836 | } | 1845 | } |
1846 | wr32(reg_offset, reg_val); | ||
1837 | } | 1847 | } |
1838 | 1848 | ||
1839 | /** | 1849 | /** |
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h index d27edbc63923..25151401c2ab 100644 --- a/drivers/net/ethernet/intel/igb/igb.h +++ b/drivers/net/ethernet/intel/igb/igb.h | |||
@@ -447,7 +447,7 @@ struct igb_adapter { | |||
447 | #endif | 447 | #endif |
448 | struct i2c_algo_bit_data i2c_algo; | 448 | struct i2c_algo_bit_data i2c_algo; |
449 | struct i2c_adapter i2c_adap; | 449 | struct i2c_adapter i2c_adap; |
450 | struct igb_i2c_client_list *i2c_clients; | 450 | struct i2c_client *i2c_client; |
451 | }; | 451 | }; |
452 | 452 | ||
453 | #define IGB_FLAG_HAS_MSI (1 << 0) | 453 | #define IGB_FLAG_HAS_MSI (1 << 0) |
diff --git a/drivers/net/ethernet/intel/igb/igb_hwmon.c b/drivers/net/ethernet/intel/igb/igb_hwmon.c index 0a9b073d0b03..0478a1abe541 100644 --- a/drivers/net/ethernet/intel/igb/igb_hwmon.c +++ b/drivers/net/ethernet/intel/igb/igb_hwmon.c | |||
@@ -39,6 +39,10 @@ | |||
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | 40 | ||
41 | #ifdef CONFIG_IGB_HWMON | 41 | #ifdef CONFIG_IGB_HWMON |
42 | static struct i2c_board_info i350_sensor_info = { | ||
43 | I2C_BOARD_INFO("i350bb", (0Xf8 >> 1)), | ||
44 | }; | ||
45 | |||
42 | /* hwmon callback functions */ | 46 | /* hwmon callback functions */ |
43 | static ssize_t igb_hwmon_show_location(struct device *dev, | 47 | static ssize_t igb_hwmon_show_location(struct device *dev, |
44 | struct device_attribute *attr, | 48 | struct device_attribute *attr, |
@@ -188,6 +192,7 @@ int igb_sysfs_init(struct igb_adapter *adapter) | |||
188 | unsigned int i; | 192 | unsigned int i; |
189 | int n_attrs; | 193 | int n_attrs; |
190 | int rc = 0; | 194 | int rc = 0; |
195 | struct i2c_client *client = NULL; | ||
191 | 196 | ||
192 | /* If this method isn't defined we don't support thermals */ | 197 | /* If this method isn't defined we don't support thermals */ |
193 | if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) | 198 | if (adapter->hw.mac.ops.init_thermal_sensor_thresh == NULL) |
@@ -198,6 +203,15 @@ int igb_sysfs_init(struct igb_adapter *adapter) | |||
198 | if (rc) | 203 | if (rc) |
199 | goto exit; | 204 | goto exit; |
200 | 205 | ||
206 | /* init i2c_client */ | ||
207 | client = i2c_new_device(&adapter->i2c_adap, &i350_sensor_info); | ||
208 | if (client == NULL) { | ||
209 | dev_info(&adapter->pdev->dev, | ||
210 | "Failed to create new i2c device..\n"); | ||
211 | goto exit; | ||
212 | } | ||
213 | adapter->i2c_client = client; | ||
214 | |||
201 | /* Allocation space for max attributes | 215 | /* Allocation space for max attributes |
202 | * max num sensors * values (loc, temp, max, caution) | 216 | * max num sensors * values (loc, temp, max, caution) |
203 | */ | 217 | */ |
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c index ed79a1c53b59..8496adfc6a68 100644 --- a/drivers/net/ethernet/intel/igb/igb_main.c +++ b/drivers/net/ethernet/intel/igb/igb_main.c | |||
@@ -1923,10 +1923,6 @@ void igb_set_fw_version(struct igb_adapter *adapter) | |||
1923 | return; | 1923 | return; |
1924 | } | 1924 | } |
1925 | 1925 | ||
1926 | static const struct i2c_board_info i350_sensor_info = { | ||
1927 | I2C_BOARD_INFO("i350bb", 0Xf8), | ||
1928 | }; | ||
1929 | |||
1930 | /* igb_init_i2c - Init I2C interface | 1926 | /* igb_init_i2c - Init I2C interface |
1931 | * @adapter: pointer to adapter structure | 1927 | * @adapter: pointer to adapter structure |
1932 | * | 1928 | * |
@@ -2546,8 +2542,8 @@ static void igb_probe_vfs(struct igb_adapter *adapter) | |||
2546 | if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) | 2542 | if ((hw->mac.type == e1000_i210) || (hw->mac.type == e1000_i211)) |
2547 | return; | 2543 | return; |
2548 | 2544 | ||
2549 | igb_enable_sriov(pdev, max_vfs); | ||
2550 | pci_sriov_set_totalvfs(pdev, 7); | 2545 | pci_sriov_set_totalvfs(pdev, 7); |
2546 | igb_enable_sriov(pdev, max_vfs); | ||
2551 | 2547 | ||
2552 | #endif /* CONFIG_PCI_IOV */ | 2548 | #endif /* CONFIG_PCI_IOV */ |
2553 | } | 2549 | } |
@@ -2656,7 +2652,7 @@ static int igb_sw_init(struct igb_adapter *adapter) | |||
2656 | if (max_vfs > 7) { | 2652 | if (max_vfs > 7) { |
2657 | dev_warn(&pdev->dev, | 2653 | dev_warn(&pdev->dev, |
2658 | "Maximum of 7 VFs per PF, using max\n"); | 2654 | "Maximum of 7 VFs per PF, using max\n"); |
2659 | adapter->vfs_allocated_count = 7; | 2655 | max_vfs = adapter->vfs_allocated_count = 7; |
2660 | } else | 2656 | } else |
2661 | adapter->vfs_allocated_count = max_vfs; | 2657 | adapter->vfs_allocated_count = max_vfs; |
2662 | if (adapter->vfs_allocated_count) | 2658 | if (adapter->vfs_allocated_count) |
@@ -6227,13 +6223,6 @@ static struct sk_buff *igb_build_rx_buffer(struct igb_ring *rx_ring, | |||
6227 | /* If we spanned a buffer we have a huge mess so test for it */ | 6223 | /* If we spanned a buffer we have a huge mess so test for it */ |
6228 | BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))); | 6224 | BUG_ON(unlikely(!igb_test_staterr(rx_desc, E1000_RXD_STAT_EOP))); |
6229 | 6225 | ||
6230 | /* Guarantee this function can be used by verifying buffer sizes */ | ||
6231 | BUILD_BUG_ON(SKB_WITH_OVERHEAD(IGB_RX_BUFSZ) < (NET_SKB_PAD + | ||
6232 | NET_IP_ALIGN + | ||
6233 | IGB_TS_HDR_LEN + | ||
6234 | ETH_FRAME_LEN + | ||
6235 | ETH_FCS_LEN)); | ||
6236 | |||
6237 | rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; | 6226 | rx_buffer = &rx_ring->rx_buffer_info[rx_ring->next_to_clean]; |
6238 | page = rx_buffer->page; | 6227 | page = rx_buffer->page; |
6239 | prefetchw(page); | 6228 | prefetchw(page); |
@@ -7724,67 +7713,6 @@ static void igb_init_dmac(struct igb_adapter *adapter, u32 pba) | |||
7724 | } | 7713 | } |
7725 | } | 7714 | } |
7726 | 7715 | ||
7727 | static DEFINE_SPINLOCK(i2c_clients_lock); | ||
7728 | |||
7729 | /* igb_get_i2c_client - returns matching client | ||
7730 | * in adapters's client list. | ||
7731 | * @adapter: adapter struct | ||
7732 | * @dev_addr: device address of i2c needed. | ||
7733 | */ | ||
7734 | static struct i2c_client * | ||
7735 | igb_get_i2c_client(struct igb_adapter *adapter, u8 dev_addr) | ||
7736 | { | ||
7737 | ulong flags; | ||
7738 | struct igb_i2c_client_list *client_list; | ||
7739 | struct i2c_client *client = NULL; | ||
7740 | struct i2c_board_info client_info = { | ||
7741 | I2C_BOARD_INFO("igb", 0x00), | ||
7742 | }; | ||
7743 | |||
7744 | spin_lock_irqsave(&i2c_clients_lock, flags); | ||
7745 | client_list = adapter->i2c_clients; | ||
7746 | |||
7747 | /* See if we already have an i2c_client */ | ||
7748 | while (client_list) { | ||
7749 | if (client_list->client->addr == (dev_addr >> 1)) { | ||
7750 | client = client_list->client; | ||
7751 | goto exit; | ||
7752 | } else { | ||
7753 | client_list = client_list->next; | ||
7754 | } | ||
7755 | } | ||
7756 | |||
7757 | /* no client_list found, create a new one */ | ||
7758 | client_list = kzalloc(sizeof(*client_list), GFP_ATOMIC); | ||
7759 | if (client_list == NULL) | ||
7760 | goto exit; | ||
7761 | |||
7762 | /* dev_addr passed to us is left-shifted by 1 bit | ||
7763 | * i2c_new_device call expects it to be flush to the right. | ||
7764 | */ | ||
7765 | client_info.addr = dev_addr >> 1; | ||
7766 | client_info.platform_data = adapter; | ||
7767 | client_list->client = i2c_new_device(&adapter->i2c_adap, &client_info); | ||
7768 | if (client_list->client == NULL) { | ||
7769 | dev_info(&adapter->pdev->dev, | ||
7770 | "Failed to create new i2c device..\n"); | ||
7771 | goto err_no_client; | ||
7772 | } | ||
7773 | |||
7774 | /* insert new client at head of list */ | ||
7775 | client_list->next = adapter->i2c_clients; | ||
7776 | adapter->i2c_clients = client_list; | ||
7777 | |||
7778 | client = client_list->client; | ||
7779 | goto exit; | ||
7780 | |||
7781 | err_no_client: | ||
7782 | kfree(client_list); | ||
7783 | exit: | ||
7784 | spin_unlock_irqrestore(&i2c_clients_lock, flags); | ||
7785 | return client; | ||
7786 | } | ||
7787 | |||
7788 | /* igb_read_i2c_byte - Reads 8 bit word over I2C | 7716 | /* igb_read_i2c_byte - Reads 8 bit word over I2C |
7789 | * @hw: pointer to hardware structure | 7717 | * @hw: pointer to hardware structure |
7790 | * @byte_offset: byte offset to read | 7718 | * @byte_offset: byte offset to read |
@@ -7798,7 +7726,7 @@ s32 igb_read_i2c_byte(struct e1000_hw *hw, u8 byte_offset, | |||
7798 | u8 dev_addr, u8 *data) | 7726 | u8 dev_addr, u8 *data) |
7799 | { | 7727 | { |
7800 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); | 7728 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); |
7801 | struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr); | 7729 | struct i2c_client *this_client = adapter->i2c_client; |
7802 | s32 status; | 7730 | s32 status; |
7803 | u16 swfw_mask = 0; | 7731 | u16 swfw_mask = 0; |
7804 | 7732 | ||
@@ -7835,7 +7763,7 @@ s32 igb_write_i2c_byte(struct e1000_hw *hw, u8 byte_offset, | |||
7835 | u8 dev_addr, u8 data) | 7763 | u8 dev_addr, u8 data) |
7836 | { | 7764 | { |
7837 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); | 7765 | struct igb_adapter *adapter = container_of(hw, struct igb_adapter, hw); |
7838 | struct i2c_client *this_client = igb_get_i2c_client(adapter, dev_addr); | 7766 | struct i2c_client *this_client = adapter->i2c_client; |
7839 | s32 status; | 7767 | s32 status; |
7840 | u16 swfw_mask = E1000_SWFW_PHY0_SM; | 7768 | u16 swfw_mask = E1000_SWFW_PHY0_SM; |
7841 | 7769 | ||
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c index 0987822359f0..0a237507ee85 100644 --- a/drivers/net/ethernet/intel/igb/igb_ptp.c +++ b/drivers/net/ethernet/intel/igb/igb_ptp.c | |||
@@ -740,7 +740,7 @@ void igb_ptp_init(struct igb_adapter *adapter) | |||
740 | case e1000_82576: | 740 | case e1000_82576: |
741 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); | 741 | snprintf(adapter->ptp_caps.name, 16, "%pm", netdev->dev_addr); |
742 | adapter->ptp_caps.owner = THIS_MODULE; | 742 | adapter->ptp_caps.owner = THIS_MODULE; |
743 | adapter->ptp_caps.max_adj = 1000000000; | 743 | adapter->ptp_caps.max_adj = 999999881; |
744 | adapter->ptp_caps.n_ext_ts = 0; | 744 | adapter->ptp_caps.n_ext_ts = 0; |
745 | adapter->ptp_caps.pps = 0; | 745 | adapter->ptp_caps.pps = 0; |
746 | adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; | 746 | adapter->ptp_caps.adjfreq = igb_ptp_adjfreq_82576; |
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c index c3db6cd69b68..2b6cb5ca48ee 100644 --- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c +++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c | |||
@@ -944,9 +944,17 @@ free_queue_irqs: | |||
944 | free_irq(adapter->msix_entries[vector].vector, | 944 | free_irq(adapter->msix_entries[vector].vector, |
945 | adapter->q_vector[vector]); | 945 | adapter->q_vector[vector]); |
946 | } | 946 | } |
947 | pci_disable_msix(adapter->pdev); | 947 | /* This failure is non-recoverable - it indicates the system is |
948 | kfree(adapter->msix_entries); | 948 | * out of MSIX vector resources and the VF driver cannot run |
949 | adapter->msix_entries = NULL; | 949 | * without them. Set the number of msix vectors to zero |
950 | * indicating that not enough can be allocated. The error | ||
951 | * will be returned to the user indicating device open failed. | ||
952 | * Any further attempts to force the driver to open will also | ||
953 | * fail. The only way to recover is to unload the driver and | ||
954 | * reload it again. If the system has recovered some MSIX | ||
955 | * vectors then it may succeed. | ||
956 | */ | ||
957 | adapter->num_msix_vectors = 0; | ||
950 | return err; | 958 | return err; |
951 | } | 959 | } |
952 | 960 | ||
@@ -2572,6 +2580,15 @@ static int ixgbevf_open(struct net_device *netdev) | |||
2572 | struct ixgbe_hw *hw = &adapter->hw; | 2580 | struct ixgbe_hw *hw = &adapter->hw; |
2573 | int err; | 2581 | int err; |
2574 | 2582 | ||
2583 | /* A previous failure to open the device because of a lack of | ||
2584 | * available MSIX vector resources may have reset the number | ||
2585 | * of msix vectors variable to zero. The only way to recover | ||
2586 | * is to unload/reload the driver and hope that the system has | ||
2587 | * been able to recover some MSIX vector resources. | ||
2588 | */ | ||
2589 | if (!adapter->num_msix_vectors) | ||
2590 | return -ENOMEM; | ||
2591 | |||
2575 | /* disallow open during test */ | 2592 | /* disallow open during test */ |
2576 | if (test_bit(__IXGBEVF_TESTING, &adapter->state)) | 2593 | if (test_bit(__IXGBEVF_TESTING, &adapter->state)) |
2577 | return -EBUSY; | 2594 | return -EBUSY; |
@@ -2628,7 +2645,6 @@ static int ixgbevf_open(struct net_device *netdev) | |||
2628 | 2645 | ||
2629 | err_req_irq: | 2646 | err_req_irq: |
2630 | ixgbevf_down(adapter); | 2647 | ixgbevf_down(adapter); |
2631 | ixgbevf_free_irq(adapter); | ||
2632 | err_setup_rx: | 2648 | err_setup_rx: |
2633 | ixgbevf_free_all_rx_resources(adapter); | 2649 | ixgbevf_free_all_rx_resources(adapter); |
2634 | err_setup_tx: | 2650 | err_setup_tx: |
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c index 6a2127489af7..bfdb06860397 100644 --- a/drivers/net/ethernet/lantiq_etop.c +++ b/drivers/net/ethernet/lantiq_etop.c | |||
@@ -769,7 +769,7 @@ ltq_etop_probe(struct platform_device *pdev) | |||
769 | return 0; | 769 | return 0; |
770 | 770 | ||
771 | err_free: | 771 | err_free: |
772 | kfree(dev); | 772 | free_netdev(dev); |
773 | err_out: | 773 | err_out: |
774 | return err; | 774 | return err; |
775 | } | 775 | } |
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c index 29140502b71a..6562c736a1d8 100644 --- a/drivers/net/ethernet/marvell/mv643xx_eth.c +++ b/drivers/net/ethernet/marvell/mv643xx_eth.c | |||
@@ -1081,6 +1081,45 @@ static void txq_set_fixed_prio_mode(struct tx_queue *txq) | |||
1081 | 1081 | ||
1082 | 1082 | ||
1083 | /* mii management interface *************************************************/ | 1083 | /* mii management interface *************************************************/ |
1084 | static void mv643xx_adjust_pscr(struct mv643xx_eth_private *mp) | ||
1085 | { | ||
1086 | u32 pscr = rdlp(mp, PORT_SERIAL_CONTROL); | ||
1087 | u32 autoneg_disable = FORCE_LINK_PASS | | ||
1088 | DISABLE_AUTO_NEG_SPEED_GMII | | ||
1089 | DISABLE_AUTO_NEG_FOR_FLOW_CTRL | | ||
1090 | DISABLE_AUTO_NEG_FOR_DUPLEX; | ||
1091 | |||
1092 | if (mp->phy->autoneg == AUTONEG_ENABLE) { | ||
1093 | /* enable auto negotiation */ | ||
1094 | pscr &= ~autoneg_disable; | ||
1095 | goto out_write; | ||
1096 | } | ||
1097 | |||
1098 | pscr |= autoneg_disable; | ||
1099 | |||
1100 | if (mp->phy->speed == SPEED_1000) { | ||
1101 | /* force gigabit, half duplex not supported */ | ||
1102 | pscr |= SET_GMII_SPEED_TO_1000; | ||
1103 | pscr |= SET_FULL_DUPLEX_MODE; | ||
1104 | goto out_write; | ||
1105 | } | ||
1106 | |||
1107 | pscr &= ~SET_GMII_SPEED_TO_1000; | ||
1108 | |||
1109 | if (mp->phy->speed == SPEED_100) | ||
1110 | pscr |= SET_MII_SPEED_TO_100; | ||
1111 | else | ||
1112 | pscr &= ~SET_MII_SPEED_TO_100; | ||
1113 | |||
1114 | if (mp->phy->duplex == DUPLEX_FULL) | ||
1115 | pscr |= SET_FULL_DUPLEX_MODE; | ||
1116 | else | ||
1117 | pscr &= ~SET_FULL_DUPLEX_MODE; | ||
1118 | |||
1119 | out_write: | ||
1120 | wrlp(mp, PORT_SERIAL_CONTROL, pscr); | ||
1121 | } | ||
1122 | |||
1084 | static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id) | 1123 | static irqreturn_t mv643xx_eth_err_irq(int irq, void *dev_id) |
1085 | { | 1124 | { |
1086 | struct mv643xx_eth_shared_private *msp = dev_id; | 1125 | struct mv643xx_eth_shared_private *msp = dev_id; |
@@ -1499,6 +1538,7 @@ static int | |||
1499 | mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | 1538 | mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) |
1500 | { | 1539 | { |
1501 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 1540 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
1541 | int ret; | ||
1502 | 1542 | ||
1503 | if (mp->phy == NULL) | 1543 | if (mp->phy == NULL) |
1504 | return -EINVAL; | 1544 | return -EINVAL; |
@@ -1508,7 +1548,10 @@ mv643xx_eth_set_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
1508 | */ | 1548 | */ |
1509 | cmd->advertising &= ~ADVERTISED_1000baseT_Half; | 1549 | cmd->advertising &= ~ADVERTISED_1000baseT_Half; |
1510 | 1550 | ||
1511 | return phy_ethtool_sset(mp->phy, cmd); | 1551 | ret = phy_ethtool_sset(mp->phy, cmd); |
1552 | if (!ret) | ||
1553 | mv643xx_adjust_pscr(mp); | ||
1554 | return ret; | ||
1512 | } | 1555 | } |
1513 | 1556 | ||
1514 | static void mv643xx_eth_get_drvinfo(struct net_device *dev, | 1557 | static void mv643xx_eth_get_drvinfo(struct net_device *dev, |
@@ -2442,11 +2485,15 @@ static int mv643xx_eth_stop(struct net_device *dev) | |||
2442 | static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 2485 | static int mv643xx_eth_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
2443 | { | 2486 | { |
2444 | struct mv643xx_eth_private *mp = netdev_priv(dev); | 2487 | struct mv643xx_eth_private *mp = netdev_priv(dev); |
2488 | int ret; | ||
2445 | 2489 | ||
2446 | if (mp->phy != NULL) | 2490 | if (mp->phy == NULL) |
2447 | return phy_mii_ioctl(mp->phy, ifr, cmd); | 2491 | return -ENOTSUPP; |
2448 | 2492 | ||
2449 | return -EOPNOTSUPP; | 2493 | ret = phy_mii_ioctl(mp->phy, ifr, cmd); |
2494 | if (!ret) | ||
2495 | mv643xx_adjust_pscr(mp); | ||
2496 | return ret; | ||
2450 | } | 2497 | } |
2451 | 2498 | ||
2452 | static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu) | 2499 | static int mv643xx_eth_change_mtu(struct net_device *dev, int new_mtu) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/cq.c b/drivers/net/ethernet/mellanox/mlx4/cq.c index 7e64033d7de3..0706623cfb96 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cq.c +++ b/drivers/net/ethernet/mellanox/mlx4/cq.c | |||
@@ -226,7 +226,7 @@ void __mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn) | |||
226 | 226 | ||
227 | static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn) | 227 | static void mlx4_cq_free_icm(struct mlx4_dev *dev, int cqn) |
228 | { | 228 | { |
229 | u64 in_param; | 229 | u64 in_param = 0; |
230 | int err; | 230 | int err; |
231 | 231 | ||
232 | if (mlx4_is_mfunc(dev)) { | 232 | if (mlx4_is_mfunc(dev)) { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c index bb4d8d99f36d..f278b10ef714 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_netdev.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_netdev.c | |||
@@ -565,34 +565,38 @@ static void mlx4_en_put_qp(struct mlx4_en_priv *priv) | |||
565 | struct mlx4_en_dev *mdev = priv->mdev; | 565 | struct mlx4_en_dev *mdev = priv->mdev; |
566 | struct mlx4_dev *dev = mdev->dev; | 566 | struct mlx4_dev *dev = mdev->dev; |
567 | int qpn = priv->base_qpn; | 567 | int qpn = priv->base_qpn; |
568 | u64 mac = mlx4_en_mac_to_u64(priv->dev->dev_addr); | 568 | u64 mac; |
569 | |||
570 | en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n", | ||
571 | priv->dev->dev_addr); | ||
572 | mlx4_unregister_mac(dev, priv->port, mac); | ||
573 | 569 | ||
574 | if (dev->caps.steering_mode != MLX4_STEERING_MODE_A0) { | 570 | if (dev->caps.steering_mode == MLX4_STEERING_MODE_A0) { |
571 | mac = mlx4_en_mac_to_u64(priv->dev->dev_addr); | ||
572 | en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n", | ||
573 | priv->dev->dev_addr); | ||
574 | mlx4_unregister_mac(dev, priv->port, mac); | ||
575 | } else { | ||
575 | struct mlx4_mac_entry *entry; | 576 | struct mlx4_mac_entry *entry; |
576 | struct hlist_node *tmp; | 577 | struct hlist_node *tmp; |
577 | struct hlist_head *bucket; | 578 | struct hlist_head *bucket; |
578 | unsigned int mac_hash; | 579 | unsigned int i; |
579 | 580 | ||
580 | mac_hash = priv->dev->dev_addr[MLX4_EN_MAC_HASH_IDX]; | 581 | for (i = 0; i < MLX4_EN_MAC_HASH_SIZE; ++i) { |
581 | bucket = &priv->mac_hash[mac_hash]; | 582 | bucket = &priv->mac_hash[i]; |
582 | hlist_for_each_entry_safe(entry, tmp, bucket, hlist) { | 583 | hlist_for_each_entry_safe(entry, tmp, bucket, hlist) { |
583 | if (ether_addr_equal_64bits(entry->mac, | 584 | mac = mlx4_en_mac_to_u64(entry->mac); |
584 | priv->dev->dev_addr)) { | 585 | en_dbg(DRV, priv, "Registering MAC: %pM for deleting\n", |
585 | en_dbg(DRV, priv, "Releasing qp: port %d, MAC %pM, qpn %d\n", | 586 | entry->mac); |
586 | priv->port, priv->dev->dev_addr, qpn); | ||
587 | mlx4_en_uc_steer_release(priv, entry->mac, | 587 | mlx4_en_uc_steer_release(priv, entry->mac, |
588 | qpn, entry->reg_id); | 588 | qpn, entry->reg_id); |
589 | mlx4_qp_release_range(dev, qpn, 1); | ||
590 | 589 | ||
590 | mlx4_unregister_mac(dev, priv->port, mac); | ||
591 | hlist_del_rcu(&entry->hlist); | 591 | hlist_del_rcu(&entry->hlist); |
592 | kfree_rcu(entry, rcu); | 592 | kfree_rcu(entry, rcu); |
593 | break; | ||
594 | } | 593 | } |
595 | } | 594 | } |
595 | |||
596 | en_dbg(DRV, priv, "Releasing qp: port %d, qpn %d\n", | ||
597 | priv->port, qpn); | ||
598 | mlx4_qp_release_range(dev, qpn, 1); | ||
599 | priv->flags &= ~MLX4_EN_FLAG_FORCE_PROMISC; | ||
596 | } | 600 | } |
597 | } | 601 | } |
598 | 602 | ||
@@ -650,28 +654,10 @@ u64 mlx4_en_mac_to_u64(u8 *addr) | |||
650 | return mac; | 654 | return mac; |
651 | } | 655 | } |
652 | 656 | ||
653 | static int mlx4_en_set_mac(struct net_device *dev, void *addr) | 657 | static int mlx4_en_do_set_mac(struct mlx4_en_priv *priv) |
654 | { | ||
655 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
656 | struct mlx4_en_dev *mdev = priv->mdev; | ||
657 | struct sockaddr *saddr = addr; | ||
658 | |||
659 | if (!is_valid_ether_addr(saddr->sa_data)) | ||
660 | return -EADDRNOTAVAIL; | ||
661 | |||
662 | memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN); | ||
663 | queue_work(mdev->workqueue, &priv->mac_task); | ||
664 | return 0; | ||
665 | } | ||
666 | |||
667 | static void mlx4_en_do_set_mac(struct work_struct *work) | ||
668 | { | 658 | { |
669 | struct mlx4_en_priv *priv = container_of(work, struct mlx4_en_priv, | ||
670 | mac_task); | ||
671 | struct mlx4_en_dev *mdev = priv->mdev; | ||
672 | int err = 0; | 659 | int err = 0; |
673 | 660 | ||
674 | mutex_lock(&mdev->state_lock); | ||
675 | if (priv->port_up) { | 661 | if (priv->port_up) { |
676 | /* Remove old MAC and insert the new one */ | 662 | /* Remove old MAC and insert the new one */ |
677 | err = mlx4_en_replace_mac(priv, priv->base_qpn, | 663 | err = mlx4_en_replace_mac(priv, priv->base_qpn, |
@@ -683,7 +669,26 @@ static void mlx4_en_do_set_mac(struct work_struct *work) | |||
683 | } else | 669 | } else |
684 | en_dbg(HW, priv, "Port is down while registering mac, exiting...\n"); | 670 | en_dbg(HW, priv, "Port is down while registering mac, exiting...\n"); |
685 | 671 | ||
672 | return err; | ||
673 | } | ||
674 | |||
675 | static int mlx4_en_set_mac(struct net_device *dev, void *addr) | ||
676 | { | ||
677 | struct mlx4_en_priv *priv = netdev_priv(dev); | ||
678 | struct mlx4_en_dev *mdev = priv->mdev; | ||
679 | struct sockaddr *saddr = addr; | ||
680 | int err; | ||
681 | |||
682 | if (!is_valid_ether_addr(saddr->sa_data)) | ||
683 | return -EADDRNOTAVAIL; | ||
684 | |||
685 | memcpy(dev->dev_addr, saddr->sa_data, ETH_ALEN); | ||
686 | |||
687 | mutex_lock(&mdev->state_lock); | ||
688 | err = mlx4_en_do_set_mac(priv); | ||
686 | mutex_unlock(&mdev->state_lock); | 689 | mutex_unlock(&mdev->state_lock); |
690 | |||
691 | return err; | ||
687 | } | 692 | } |
688 | 693 | ||
689 | static void mlx4_en_clear_list(struct net_device *dev) | 694 | static void mlx4_en_clear_list(struct net_device *dev) |
@@ -1348,7 +1353,7 @@ static void mlx4_en_do_get_stats(struct work_struct *work) | |||
1348 | queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); | 1353 | queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY); |
1349 | } | 1354 | } |
1350 | if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) { | 1355 | if (mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port]) { |
1351 | queue_work(mdev->workqueue, &priv->mac_task); | 1356 | mlx4_en_do_set_mac(priv); |
1352 | mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0; | 1357 | mdev->mac_removed[MLX4_MAX_PORTS + 1 - priv->port] = 0; |
1353 | } | 1358 | } |
1354 | mutex_unlock(&mdev->state_lock); | 1359 | mutex_unlock(&mdev->state_lock); |
@@ -1632,6 +1637,17 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) | |||
1632 | /* Flush multicast filter */ | 1637 | /* Flush multicast filter */ |
1633 | mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); | 1638 | mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG); |
1634 | 1639 | ||
1640 | /* Remove flow steering rules for the port*/ | ||
1641 | if (mdev->dev->caps.steering_mode == | ||
1642 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
1643 | ASSERT_RTNL(); | ||
1644 | list_for_each_entry_safe(flow, tmp_flow, | ||
1645 | &priv->ethtool_list, list) { | ||
1646 | mlx4_flow_detach(mdev->dev, flow->id); | ||
1647 | list_del(&flow->list); | ||
1648 | } | ||
1649 | } | ||
1650 | |||
1635 | mlx4_en_destroy_drop_qp(priv); | 1651 | mlx4_en_destroy_drop_qp(priv); |
1636 | 1652 | ||
1637 | /* Free TX Rings */ | 1653 | /* Free TX Rings */ |
@@ -1652,17 +1668,6 @@ void mlx4_en_stop_port(struct net_device *dev, int detach) | |||
1652 | if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN)) | 1668 | if (!(mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAGS2_REASSIGN_MAC_EN)) |
1653 | mdev->mac_removed[priv->port] = 1; | 1669 | mdev->mac_removed[priv->port] = 1; |
1654 | 1670 | ||
1655 | /* Remove flow steering rules for the port*/ | ||
1656 | if (mdev->dev->caps.steering_mode == | ||
1657 | MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
1658 | ASSERT_RTNL(); | ||
1659 | list_for_each_entry_safe(flow, tmp_flow, | ||
1660 | &priv->ethtool_list, list) { | ||
1661 | mlx4_flow_detach(mdev->dev, flow->id); | ||
1662 | list_del(&flow->list); | ||
1663 | } | ||
1664 | } | ||
1665 | |||
1666 | /* Free RX Rings */ | 1671 | /* Free RX Rings */ |
1667 | for (i = 0; i < priv->rx_ring_num; i++) { | 1672 | for (i = 0; i < priv->rx_ring_num; i++) { |
1668 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); | 1673 | mlx4_en_deactivate_rx_ring(priv, &priv->rx_ring[i]); |
@@ -1828,9 +1833,11 @@ int mlx4_en_alloc_resources(struct mlx4_en_priv *priv) | |||
1828 | } | 1833 | } |
1829 | 1834 | ||
1830 | #ifdef CONFIG_RFS_ACCEL | 1835 | #ifdef CONFIG_RFS_ACCEL |
1831 | priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool); | 1836 | if (priv->mdev->dev->caps.comp_pool) { |
1832 | if (!priv->dev->rx_cpu_rmap) | 1837 | priv->dev->rx_cpu_rmap = alloc_irq_cpu_rmap(priv->mdev->dev->caps.comp_pool); |
1833 | goto err; | 1838 | if (!priv->dev->rx_cpu_rmap) |
1839 | goto err; | ||
1840 | } | ||
1834 | #endif | 1841 | #endif |
1835 | 1842 | ||
1836 | return 0; | 1843 | return 0; |
@@ -2078,7 +2085,6 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port, | |||
2078 | priv->msg_enable = MLX4_EN_MSG_LEVEL; | 2085 | priv->msg_enable = MLX4_EN_MSG_LEVEL; |
2079 | spin_lock_init(&priv->stats_lock); | 2086 | spin_lock_init(&priv->stats_lock); |
2080 | INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); | 2087 | INIT_WORK(&priv->rx_mode_task, mlx4_en_do_set_rx_mode); |
2081 | INIT_WORK(&priv->mac_task, mlx4_en_do_set_mac); | ||
2082 | INIT_WORK(&priv->watchdog_task, mlx4_en_restart); | 2088 | INIT_WORK(&priv->watchdog_task, mlx4_en_restart); |
2083 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); | 2089 | INIT_WORK(&priv->linkstate_task, mlx4_en_linkstate); |
2084 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); | 2090 | INIT_DELAYED_WORK(&priv->stats_task, mlx4_en_do_get_stats); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/eq.c b/drivers/net/ethernet/mellanox/mlx4/eq.c index 251ae2f93116..8e3123a1df88 100644 --- a/drivers/net/ethernet/mellanox/mlx4/eq.c +++ b/drivers/net/ethernet/mellanox/mlx4/eq.c | |||
@@ -771,7 +771,7 @@ int mlx4_MAP_EQ_wrapper(struct mlx4_dev *dev, int slave, | |||
771 | struct mlx4_slave_event_eq_info *event_eq = | 771 | struct mlx4_slave_event_eq_info *event_eq = |
772 | priv->mfunc.master.slave_state[slave].event_eq; | 772 | priv->mfunc.master.slave_state[slave].event_eq; |
773 | u32 in_modifier = vhcr->in_modifier; | 773 | u32 in_modifier = vhcr->in_modifier; |
774 | u32 eqn = in_modifier & 0x1FF; | 774 | u32 eqn = in_modifier & 0x3FF; |
775 | u64 in_param = vhcr->in_param; | 775 | u64 in_param = vhcr->in_param; |
776 | int err = 0; | 776 | int err = 0; |
777 | int i; | 777 | int i; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/fw.c b/drivers/net/ethernet/mellanox/mlx4/fw.c index 50917eb3013e..f6245579962d 100644 --- a/drivers/net/ethernet/mellanox/mlx4/fw.c +++ b/drivers/net/ethernet/mellanox/mlx4/fw.c | |||
@@ -787,6 +787,14 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave, | |||
787 | bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN; | 787 | bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN; |
788 | MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); | 788 | MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET); |
789 | 789 | ||
790 | /* turn off device-managed steering capability if not enabled */ | ||
791 | if (dev->caps.steering_mode != MLX4_STEERING_MODE_DEVICE_MANAGED) { | ||
792 | MLX4_GET(field, outbox->buf, | ||
793 | QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); | ||
794 | field &= 0x7f; | ||
795 | MLX4_PUT(outbox->buf, field, | ||
796 | QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET); | ||
797 | } | ||
790 | return 0; | 798 | return 0; |
791 | } | 799 | } |
792 | 800 | ||
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index d180bc46826a..16abde20e1fc 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -1555,7 +1555,7 @@ void __mlx4_counter_free(struct mlx4_dev *dev, u32 idx) | |||
1555 | 1555 | ||
1556 | void mlx4_counter_free(struct mlx4_dev *dev, u32 idx) | 1556 | void mlx4_counter_free(struct mlx4_dev *dev, u32 idx) |
1557 | { | 1557 | { |
1558 | u64 in_param; | 1558 | u64 in_param = 0; |
1559 | 1559 | ||
1560 | if (mlx4_is_mfunc(dev)) { | 1560 | if (mlx4_is_mfunc(dev)) { |
1561 | set_param_l(&in_param, idx); | 1561 | set_param_l(&in_param, idx); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4.h b/drivers/net/ethernet/mellanox/mlx4/mlx4.h index cf883345af88..d738454116a0 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4.h | |||
@@ -1235,7 +1235,7 @@ int mlx4_get_qp_per_mgm(struct mlx4_dev *dev); | |||
1235 | 1235 | ||
1236 | static inline void set_param_l(u64 *arg, u32 val) | 1236 | static inline void set_param_l(u64 *arg, u32 val) |
1237 | { | 1237 | { |
1238 | *((u32 *)arg) = val; | 1238 | *arg = (*arg & 0xffffffff00000000ULL) | (u64) val; |
1239 | } | 1239 | } |
1240 | 1240 | ||
1241 | static inline void set_param_h(u64 *arg, u32 val) | 1241 | static inline void set_param_h(u64 *arg, u32 val) |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h index c313d7e943a9..f710b7ce0dcb 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h +++ b/drivers/net/ethernet/mellanox/mlx4/mlx4_en.h | |||
@@ -509,7 +509,6 @@ struct mlx4_en_priv { | |||
509 | struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; | 509 | struct mlx4_en_cq rx_cq[MAX_RX_RINGS]; |
510 | struct mlx4_qp drop_qp; | 510 | struct mlx4_qp drop_qp; |
511 | struct work_struct rx_mode_task; | 511 | struct work_struct rx_mode_task; |
512 | struct work_struct mac_task; | ||
513 | struct work_struct watchdog_task; | 512 | struct work_struct watchdog_task; |
514 | struct work_struct linkstate_task; | 513 | struct work_struct linkstate_task; |
515 | struct delayed_work stats_task; | 514 | struct delayed_work stats_task; |
diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 602ca9bf78e4..f91719a08cba 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c | |||
@@ -183,7 +183,7 @@ u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) | |||
183 | 183 | ||
184 | static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) | 184 | static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order) |
185 | { | 185 | { |
186 | u64 in_param; | 186 | u64 in_param = 0; |
187 | u64 out_param; | 187 | u64 out_param; |
188 | int err; | 188 | int err; |
189 | 189 | ||
@@ -240,7 +240,7 @@ void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order) | |||
240 | 240 | ||
241 | static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order) | 241 | static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order) |
242 | { | 242 | { |
243 | u64 in_param; | 243 | u64 in_param = 0; |
244 | int err; | 244 | int err; |
245 | 245 | ||
246 | if (mlx4_is_mfunc(dev)) { | 246 | if (mlx4_is_mfunc(dev)) { |
@@ -351,7 +351,7 @@ void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index) | |||
351 | 351 | ||
352 | static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index) | 352 | static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index) |
353 | { | 353 | { |
354 | u64 in_param; | 354 | u64 in_param = 0; |
355 | 355 | ||
356 | if (mlx4_is_mfunc(dev)) { | 356 | if (mlx4_is_mfunc(dev)) { |
357 | set_param_l(&in_param, index); | 357 | set_param_l(&in_param, index); |
@@ -374,7 +374,7 @@ int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index) | |||
374 | 374 | ||
375 | static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index) | 375 | static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index) |
376 | { | 376 | { |
377 | u64 param; | 377 | u64 param = 0; |
378 | 378 | ||
379 | if (mlx4_is_mfunc(dev)) { | 379 | if (mlx4_is_mfunc(dev)) { |
380 | set_param_l(¶m, index); | 380 | set_param_l(¶m, index); |
@@ -395,7 +395,7 @@ void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index) | |||
395 | 395 | ||
396 | static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index) | 396 | static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index) |
397 | { | 397 | { |
398 | u64 in_param; | 398 | u64 in_param = 0; |
399 | 399 | ||
400 | if (mlx4_is_mfunc(dev)) { | 400 | if (mlx4_is_mfunc(dev)) { |
401 | set_param_l(&in_param, index); | 401 | set_param_l(&in_param, index); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/pd.c b/drivers/net/ethernet/mellanox/mlx4/pd.c index 1ac88637ad9d..00f223acada7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/pd.c +++ b/drivers/net/ethernet/mellanox/mlx4/pd.c | |||
@@ -101,7 +101,7 @@ void __mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) | |||
101 | 101 | ||
102 | void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) | 102 | void mlx4_xrcd_free(struct mlx4_dev *dev, u32 xrcdn) |
103 | { | 103 | { |
104 | u64 in_param; | 104 | u64 in_param = 0; |
105 | int err; | 105 | int err; |
106 | 106 | ||
107 | if (mlx4_is_mfunc(dev)) { | 107 | if (mlx4_is_mfunc(dev)) { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index 719ead15e491..10c57c86388b 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c | |||
@@ -175,7 +175,7 @@ EXPORT_SYMBOL_GPL(__mlx4_register_mac); | |||
175 | 175 | ||
176 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) | 176 | int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) |
177 | { | 177 | { |
178 | u64 out_param; | 178 | u64 out_param = 0; |
179 | int err; | 179 | int err; |
180 | 180 | ||
181 | if (mlx4_is_mfunc(dev)) { | 181 | if (mlx4_is_mfunc(dev)) { |
@@ -222,7 +222,7 @@ EXPORT_SYMBOL_GPL(__mlx4_unregister_mac); | |||
222 | 222 | ||
223 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) | 223 | void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, u64 mac) |
224 | { | 224 | { |
225 | u64 out_param; | 225 | u64 out_param = 0; |
226 | 226 | ||
227 | if (mlx4_is_mfunc(dev)) { | 227 | if (mlx4_is_mfunc(dev)) { |
228 | set_param_l(&out_param, port); | 228 | set_param_l(&out_param, port); |
@@ -361,7 +361,7 @@ out: | |||
361 | 361 | ||
362 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) | 362 | int mlx4_register_vlan(struct mlx4_dev *dev, u8 port, u16 vlan, int *index) |
363 | { | 363 | { |
364 | u64 out_param; | 364 | u64 out_param = 0; |
365 | int err; | 365 | int err; |
366 | 366 | ||
367 | if (mlx4_is_mfunc(dev)) { | 367 | if (mlx4_is_mfunc(dev)) { |
@@ -406,7 +406,7 @@ out: | |||
406 | 406 | ||
407 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) | 407 | void mlx4_unregister_vlan(struct mlx4_dev *dev, u8 port, int index) |
408 | { | 408 | { |
409 | u64 in_param; | 409 | u64 in_param = 0; |
410 | int err; | 410 | int err; |
411 | 411 | ||
412 | if (mlx4_is_mfunc(dev)) { | 412 | if (mlx4_is_mfunc(dev)) { |
diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 81e2abe07bbb..e891b058c1be 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c | |||
@@ -222,7 +222,7 @@ int __mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, | |||
222 | 222 | ||
223 | int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base) | 223 | int mlx4_qp_reserve_range(struct mlx4_dev *dev, int cnt, int align, int *base) |
224 | { | 224 | { |
225 | u64 in_param; | 225 | u64 in_param = 0; |
226 | u64 out_param; | 226 | u64 out_param; |
227 | int err; | 227 | int err; |
228 | 228 | ||
@@ -255,7 +255,7 @@ void __mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) | |||
255 | 255 | ||
256 | void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) | 256 | void mlx4_qp_release_range(struct mlx4_dev *dev, int base_qpn, int cnt) |
257 | { | 257 | { |
258 | u64 in_param; | 258 | u64 in_param = 0; |
259 | int err; | 259 | int err; |
260 | 260 | ||
261 | if (mlx4_is_mfunc(dev)) { | 261 | if (mlx4_is_mfunc(dev)) { |
@@ -319,7 +319,7 @@ err_out: | |||
319 | 319 | ||
320 | static int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn) | 320 | static int mlx4_qp_alloc_icm(struct mlx4_dev *dev, int qpn) |
321 | { | 321 | { |
322 | u64 param; | 322 | u64 param = 0; |
323 | 323 | ||
324 | if (mlx4_is_mfunc(dev)) { | 324 | if (mlx4_is_mfunc(dev)) { |
325 | set_param_l(¶m, qpn); | 325 | set_param_l(¶m, qpn); |
@@ -344,7 +344,7 @@ void __mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn) | |||
344 | 344 | ||
345 | static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn) | 345 | static void mlx4_qp_free_icm(struct mlx4_dev *dev, int qpn) |
346 | { | 346 | { |
347 | u64 in_param; | 347 | u64 in_param = 0; |
348 | 348 | ||
349 | if (mlx4_is_mfunc(dev)) { | 349 | if (mlx4_is_mfunc(dev)) { |
350 | set_param_l(&in_param, qpn); | 350 | set_param_l(&in_param, qpn); |
diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 083fb48dc3d7..1391b52f443a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c | |||
@@ -99,6 +99,7 @@ struct res_qp { | |||
99 | struct list_head mcg_list; | 99 | struct list_head mcg_list; |
100 | spinlock_t mcg_spl; | 100 | spinlock_t mcg_spl; |
101 | int local_qpn; | 101 | int local_qpn; |
102 | atomic_t ref_count; | ||
102 | }; | 103 | }; |
103 | 104 | ||
104 | enum res_mtt_states { | 105 | enum res_mtt_states { |
@@ -197,6 +198,7 @@ enum res_fs_rule_states { | |||
197 | 198 | ||
198 | struct res_fs_rule { | 199 | struct res_fs_rule { |
199 | struct res_common com; | 200 | struct res_common com; |
201 | int qpn; | ||
200 | }; | 202 | }; |
201 | 203 | ||
202 | static void *res_tracker_lookup(struct rb_root *root, u64 res_id) | 204 | static void *res_tracker_lookup(struct rb_root *root, u64 res_id) |
@@ -355,7 +357,7 @@ static int mpt_mask(struct mlx4_dev *dev) | |||
355 | return dev->caps.num_mpts - 1; | 357 | return dev->caps.num_mpts - 1; |
356 | } | 358 | } |
357 | 359 | ||
358 | static void *find_res(struct mlx4_dev *dev, int res_id, | 360 | static void *find_res(struct mlx4_dev *dev, u64 res_id, |
359 | enum mlx4_resource type) | 361 | enum mlx4_resource type) |
360 | { | 362 | { |
361 | struct mlx4_priv *priv = mlx4_priv(dev); | 363 | struct mlx4_priv *priv = mlx4_priv(dev); |
@@ -447,6 +449,7 @@ static struct res_common *alloc_qp_tr(int id) | |||
447 | ret->local_qpn = id; | 449 | ret->local_qpn = id; |
448 | INIT_LIST_HEAD(&ret->mcg_list); | 450 | INIT_LIST_HEAD(&ret->mcg_list); |
449 | spin_lock_init(&ret->mcg_spl); | 451 | spin_lock_init(&ret->mcg_spl); |
452 | atomic_set(&ret->ref_count, 0); | ||
450 | 453 | ||
451 | return &ret->com; | 454 | return &ret->com; |
452 | } | 455 | } |
@@ -554,7 +557,7 @@ static struct res_common *alloc_xrcdn_tr(int id) | |||
554 | return &ret->com; | 557 | return &ret->com; |
555 | } | 558 | } |
556 | 559 | ||
557 | static struct res_common *alloc_fs_rule_tr(u64 id) | 560 | static struct res_common *alloc_fs_rule_tr(u64 id, int qpn) |
558 | { | 561 | { |
559 | struct res_fs_rule *ret; | 562 | struct res_fs_rule *ret; |
560 | 563 | ||
@@ -564,7 +567,7 @@ static struct res_common *alloc_fs_rule_tr(u64 id) | |||
564 | 567 | ||
565 | ret->com.res_id = id; | 568 | ret->com.res_id = id; |
566 | ret->com.state = RES_FS_RULE_ALLOCATED; | 569 | ret->com.state = RES_FS_RULE_ALLOCATED; |
567 | 570 | ret->qpn = qpn; | |
568 | return &ret->com; | 571 | return &ret->com; |
569 | } | 572 | } |
570 | 573 | ||
@@ -602,7 +605,7 @@ static struct res_common *alloc_tr(u64 id, enum mlx4_resource type, int slave, | |||
602 | ret = alloc_xrcdn_tr(id); | 605 | ret = alloc_xrcdn_tr(id); |
603 | break; | 606 | break; |
604 | case RES_FS_RULE: | 607 | case RES_FS_RULE: |
605 | ret = alloc_fs_rule_tr(id); | 608 | ret = alloc_fs_rule_tr(id, extra); |
606 | break; | 609 | break; |
607 | default: | 610 | default: |
608 | return NULL; | 611 | return NULL; |
@@ -671,10 +674,14 @@ undo: | |||
671 | 674 | ||
672 | static int remove_qp_ok(struct res_qp *res) | 675 | static int remove_qp_ok(struct res_qp *res) |
673 | { | 676 | { |
674 | if (res->com.state == RES_QP_BUSY) | 677 | if (res->com.state == RES_QP_BUSY || atomic_read(&res->ref_count) || |
678 | !list_empty(&res->mcg_list)) { | ||
679 | pr_err("resource tracker: fail to remove qp, state %d, ref_count %d\n", | ||
680 | res->com.state, atomic_read(&res->ref_count)); | ||
675 | return -EBUSY; | 681 | return -EBUSY; |
676 | else if (res->com.state != RES_QP_RESERVED) | 682 | } else if (res->com.state != RES_QP_RESERVED) { |
677 | return -EPERM; | 683 | return -EPERM; |
684 | } | ||
678 | 685 | ||
679 | return 0; | 686 | return 0; |
680 | } | 687 | } |
@@ -2990,6 +2997,9 @@ int mlx4_QP_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
2990 | u8 steer_type_mask = 2; | 2997 | u8 steer_type_mask = 2; |
2991 | enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1; | 2998 | enum mlx4_steer_type type = (gid[7] & steer_type_mask) >> 1; |
2992 | 2999 | ||
3000 | if (dev->caps.steering_mode != MLX4_STEERING_MODE_B0) | ||
3001 | return -EINVAL; | ||
3002 | |||
2993 | qpn = vhcr->in_modifier & 0xffffff; | 3003 | qpn = vhcr->in_modifier & 0xffffff; |
2994 | err = get_res(dev, slave, qpn, RES_QP, &rqp); | 3004 | err = get_res(dev, slave, qpn, RES_QP, &rqp); |
2995 | if (err) | 3005 | if (err) |
@@ -3121,6 +3131,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3121 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; | 3131 | struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC]; |
3122 | int err; | 3132 | int err; |
3123 | int qpn; | 3133 | int qpn; |
3134 | struct res_qp *rqp; | ||
3124 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; | 3135 | struct mlx4_net_trans_rule_hw_ctrl *ctrl; |
3125 | struct _rule_hw *rule_header; | 3136 | struct _rule_hw *rule_header; |
3126 | int header_id; | 3137 | int header_id; |
@@ -3131,7 +3142,7 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3131 | 3142 | ||
3132 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; | 3143 | ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf; |
3133 | qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; | 3144 | qpn = be32_to_cpu(ctrl->qpn) & 0xffffff; |
3134 | err = get_res(dev, slave, qpn, RES_QP, NULL); | 3145 | err = get_res(dev, slave, qpn, RES_QP, &rqp); |
3135 | if (err) { | 3146 | if (err) { |
3136 | pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); | 3147 | pr_err("Steering rule with qpn 0x%x rejected.\n", qpn); |
3137 | return err; | 3148 | return err; |
@@ -3172,14 +3183,16 @@ int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3172 | if (err) | 3183 | if (err) |
3173 | goto err_put; | 3184 | goto err_put; |
3174 | 3185 | ||
3175 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, 0); | 3186 | err = add_res_range(dev, slave, vhcr->out_param, 1, RES_FS_RULE, qpn); |
3176 | if (err) { | 3187 | if (err) { |
3177 | mlx4_err(dev, "Fail to add flow steering resources.\n "); | 3188 | mlx4_err(dev, "Fail to add flow steering resources.\n "); |
3178 | /* detach rule*/ | 3189 | /* detach rule*/ |
3179 | mlx4_cmd(dev, vhcr->out_param, 0, 0, | 3190 | mlx4_cmd(dev, vhcr->out_param, 0, 0, |
3180 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, | 3191 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, |
3181 | MLX4_CMD_NATIVE); | 3192 | MLX4_CMD_NATIVE); |
3193 | goto err_put; | ||
3182 | } | 3194 | } |
3195 | atomic_inc(&rqp->ref_count); | ||
3183 | err_put: | 3196 | err_put: |
3184 | put_res(dev, slave, qpn, RES_QP); | 3197 | put_res(dev, slave, qpn, RES_QP); |
3185 | return err; | 3198 | return err; |
@@ -3192,20 +3205,35 @@ int mlx4_QP_FLOW_STEERING_DETACH_wrapper(struct mlx4_dev *dev, int slave, | |||
3192 | struct mlx4_cmd_info *cmd) | 3205 | struct mlx4_cmd_info *cmd) |
3193 | { | 3206 | { |
3194 | int err; | 3207 | int err; |
3208 | struct res_qp *rqp; | ||
3209 | struct res_fs_rule *rrule; | ||
3195 | 3210 | ||
3196 | if (dev->caps.steering_mode != | 3211 | if (dev->caps.steering_mode != |
3197 | MLX4_STEERING_MODE_DEVICE_MANAGED) | 3212 | MLX4_STEERING_MODE_DEVICE_MANAGED) |
3198 | return -EOPNOTSUPP; | 3213 | return -EOPNOTSUPP; |
3199 | 3214 | ||
3215 | err = get_res(dev, slave, vhcr->in_param, RES_FS_RULE, &rrule); | ||
3216 | if (err) | ||
3217 | return err; | ||
3218 | /* Release the rule form busy state before removal */ | ||
3219 | put_res(dev, slave, vhcr->in_param, RES_FS_RULE); | ||
3220 | err = get_res(dev, slave, rrule->qpn, RES_QP, &rqp); | ||
3221 | if (err) | ||
3222 | return err; | ||
3223 | |||
3200 | err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0); | 3224 | err = rem_res_range(dev, slave, vhcr->in_param, 1, RES_FS_RULE, 0); |
3201 | if (err) { | 3225 | if (err) { |
3202 | mlx4_err(dev, "Fail to remove flow steering resources.\n "); | 3226 | mlx4_err(dev, "Fail to remove flow steering resources.\n "); |
3203 | return err; | 3227 | goto out; |
3204 | } | 3228 | } |
3205 | 3229 | ||
3206 | err = mlx4_cmd(dev, vhcr->in_param, 0, 0, | 3230 | err = mlx4_cmd(dev, vhcr->in_param, 0, 0, |
3207 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, | 3231 | MLX4_QP_FLOW_STEERING_DETACH, MLX4_CMD_TIME_CLASS_A, |
3208 | MLX4_CMD_NATIVE); | 3232 | MLX4_CMD_NATIVE); |
3233 | if (!err) | ||
3234 | atomic_dec(&rqp->ref_count); | ||
3235 | out: | ||
3236 | put_res(dev, slave, rrule->qpn, RES_QP); | ||
3209 | return err; | 3237 | return err; |
3210 | } | 3238 | } |
3211 | 3239 | ||
@@ -3803,6 +3831,7 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) | |||
3803 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); | 3831 | mutex_lock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); |
3804 | /*VLAN*/ | 3832 | /*VLAN*/ |
3805 | rem_slave_macs(dev, slave); | 3833 | rem_slave_macs(dev, slave); |
3834 | rem_slave_fs_rule(dev, slave); | ||
3806 | rem_slave_qps(dev, slave); | 3835 | rem_slave_qps(dev, slave); |
3807 | rem_slave_srqs(dev, slave); | 3836 | rem_slave_srqs(dev, slave); |
3808 | rem_slave_cqs(dev, slave); | 3837 | rem_slave_cqs(dev, slave); |
@@ -3811,6 +3840,5 @@ void mlx4_delete_all_resources_for_slave(struct mlx4_dev *dev, int slave) | |||
3811 | rem_slave_mtts(dev, slave); | 3840 | rem_slave_mtts(dev, slave); |
3812 | rem_slave_counters(dev, slave); | 3841 | rem_slave_counters(dev, slave); |
3813 | rem_slave_xrcdns(dev, slave); | 3842 | rem_slave_xrcdns(dev, slave); |
3814 | rem_slave_fs_rule(dev, slave); | ||
3815 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); | 3843 | mutex_unlock(&priv->mfunc.master.res_tracker.slave_list[slave].mutex); |
3816 | } | 3844 | } |
diff --git a/drivers/net/ethernet/mellanox/mlx4/srq.c b/drivers/net/ethernet/mellanox/mlx4/srq.c index feda6c00829f..e329fe1f11b7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/srq.c +++ b/drivers/net/ethernet/mellanox/mlx4/srq.c | |||
@@ -149,7 +149,7 @@ void __mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn) | |||
149 | 149 | ||
150 | static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn) | 150 | static void mlx4_srq_free_icm(struct mlx4_dev *dev, int srqn) |
151 | { | 151 | { |
152 | u64 in_param; | 152 | u64 in_param = 0; |
153 | 153 | ||
154 | if (mlx4_is_mfunc(dev)) { | 154 | if (mlx4_is_mfunc(dev)) { |
155 | set_param_l(&in_param, srqn); | 155 | set_param_l(&in_param, srqn); |
diff --git a/drivers/net/ethernet/nxp/lpc_eth.c b/drivers/net/ethernet/nxp/lpc_eth.c index c4122c86f829..efa29b712d5f 100644 --- a/drivers/net/ethernet/nxp/lpc_eth.c +++ b/drivers/net/ethernet/nxp/lpc_eth.c | |||
@@ -1472,7 +1472,8 @@ static int lpc_eth_drv_probe(struct platform_device *pdev) | |||
1472 | } | 1472 | } |
1473 | platform_set_drvdata(pdev, ndev); | 1473 | platform_set_drvdata(pdev, ndev); |
1474 | 1474 | ||
1475 | if (lpc_mii_init(pldat) != 0) | 1475 | ret = lpc_mii_init(pldat); |
1476 | if (ret) | ||
1476 | goto err_out_unregister_netdev; | 1477 | goto err_out_unregister_netdev; |
1477 | 1478 | ||
1478 | netdev_info(ndev, "LPC mac at 0x%08x irq %d\n", | 1479 | netdev_info(ndev, "LPC mac at 0x%08x irq %d\n", |
diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c index 39ab4d09faaa..73ce7dd6b954 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c +++ b/drivers/net/ethernet/oki-semi/pch_gbe/pch_gbe_main.c | |||
@@ -1726,9 +1726,9 @@ pch_gbe_clean_rx(struct pch_gbe_adapter *adapter, | |||
1726 | 1726 | ||
1727 | skb->protocol = eth_type_trans(skb, netdev); | 1727 | skb->protocol = eth_type_trans(skb, netdev); |
1728 | if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) | 1728 | if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) |
1729 | skb->ip_summed = CHECKSUM_NONE; | ||
1730 | else | ||
1731 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1729 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1730 | else | ||
1731 | skb->ip_summed = CHECKSUM_NONE; | ||
1732 | 1732 | ||
1733 | napi_gro_receive(&adapter->napi, skb); | 1733 | napi_gro_receive(&adapter->napi, skb); |
1734 | (*work_done)++; | 1734 | (*work_done)++; |
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 8900398ba103..28fb50a1e9c3 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c | |||
@@ -4765,8 +4765,10 @@ static void rtl_hw_start_8168bb(struct rtl8169_private *tp) | |||
4765 | 4765 | ||
4766 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4766 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4767 | 4767 | ||
4768 | rtl_tx_performance_tweak(pdev, | 4768 | if (tp->dev->mtu <= ETH_DATA_LEN) { |
4769 | (0x5 << MAX_READ_REQUEST_SHIFT) | PCI_EXP_DEVCTL_NOSNOOP_EN); | 4769 | rtl_tx_performance_tweak(pdev, (0x5 << MAX_READ_REQUEST_SHIFT) | |
4770 | PCI_EXP_DEVCTL_NOSNOOP_EN); | ||
4771 | } | ||
4770 | } | 4772 | } |
4771 | 4773 | ||
4772 | static void rtl_hw_start_8168bef(struct rtl8169_private *tp) | 4774 | static void rtl_hw_start_8168bef(struct rtl8169_private *tp) |
@@ -4789,7 +4791,8 @@ static void __rtl_hw_start_8168cp(struct rtl8169_private *tp) | |||
4789 | 4791 | ||
4790 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); | 4792 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); |
4791 | 4793 | ||
4792 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4794 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4795 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4793 | 4796 | ||
4794 | rtl_disable_clock_request(pdev); | 4797 | rtl_disable_clock_request(pdev); |
4795 | 4798 | ||
@@ -4822,7 +4825,8 @@ static void rtl_hw_start_8168cp_2(struct rtl8169_private *tp) | |||
4822 | 4825 | ||
4823 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); | 4826 | RTL_W8(Config3, RTL_R8(Config3) & ~Beacon_en); |
4824 | 4827 | ||
4825 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4828 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4829 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4826 | 4830 | ||
4827 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4831 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4828 | } | 4832 | } |
@@ -4841,7 +4845,8 @@ static void rtl_hw_start_8168cp_3(struct rtl8169_private *tp) | |||
4841 | 4845 | ||
4842 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4846 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4843 | 4847 | ||
4844 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4848 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4849 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4845 | 4850 | ||
4846 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4851 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4847 | } | 4852 | } |
@@ -4901,7 +4906,8 @@ static void rtl_hw_start_8168d(struct rtl8169_private *tp) | |||
4901 | 4906 | ||
4902 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4907 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4903 | 4908 | ||
4904 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4909 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4910 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4905 | 4911 | ||
4906 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); | 4912 | RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) & ~R8168_CPCMD_QUIRK_MASK); |
4907 | } | 4913 | } |
@@ -4913,7 +4919,8 @@ static void rtl_hw_start_8168dp(struct rtl8169_private *tp) | |||
4913 | 4919 | ||
4914 | rtl_csi_access_enable_1(tp); | 4920 | rtl_csi_access_enable_1(tp); |
4915 | 4921 | ||
4916 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4922 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4923 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4917 | 4924 | ||
4918 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4925 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4919 | 4926 | ||
@@ -4972,7 +4979,8 @@ static void rtl_hw_start_8168e_1(struct rtl8169_private *tp) | |||
4972 | 4979 | ||
4973 | rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); | 4980 | rtl_ephy_init(tp, e_info_8168e_1, ARRAY_SIZE(e_info_8168e_1)); |
4974 | 4981 | ||
4975 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 4982 | if (tp->dev->mtu <= ETH_DATA_LEN) |
4983 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
4976 | 4984 | ||
4977 | RTL_W8(MaxTxPacketSize, TxPacketMax); | 4985 | RTL_W8(MaxTxPacketSize, TxPacketMax); |
4978 | 4986 | ||
@@ -4998,7 +5006,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) | |||
4998 | 5006 | ||
4999 | rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); | 5007 | rtl_ephy_init(tp, e_info_8168e_2, ARRAY_SIZE(e_info_8168e_2)); |
5000 | 5008 | ||
5001 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | 5009 | if (tp->dev->mtu <= ETH_DATA_LEN) |
5010 | rtl_tx_performance_tweak(pdev, 0x5 << MAX_READ_REQUEST_SHIFT); | ||
5002 | 5011 | ||
5003 | rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); | 5012 | rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); |
5004 | rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); | 5013 | rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); |
diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c index 33e96176e4d8..bf5e3cf97c4d 100644 --- a/drivers/net/ethernet/renesas/sh_eth.c +++ b/drivers/net/ethernet/renesas/sh_eth.c | |||
@@ -2220,6 +2220,7 @@ static void sh_eth_tsu_init(struct sh_eth_private *mdp) | |||
2220 | /* MDIO bus release function */ | 2220 | /* MDIO bus release function */ |
2221 | static int sh_mdio_release(struct net_device *ndev) | 2221 | static int sh_mdio_release(struct net_device *ndev) |
2222 | { | 2222 | { |
2223 | struct sh_eth_private *mdp = netdev_priv(ndev); | ||
2223 | struct mii_bus *bus = dev_get_drvdata(&ndev->dev); | 2224 | struct mii_bus *bus = dev_get_drvdata(&ndev->dev); |
2224 | 2225 | ||
2225 | /* unregister mdio bus */ | 2226 | /* unregister mdio bus */ |
@@ -2234,6 +2235,9 @@ static int sh_mdio_release(struct net_device *ndev) | |||
2234 | /* free bitbang info */ | 2235 | /* free bitbang info */ |
2235 | free_mdio_bitbang(bus); | 2236 | free_mdio_bitbang(bus); |
2236 | 2237 | ||
2238 | /* free bitbang memory */ | ||
2239 | kfree(mdp->bitbang); | ||
2240 | |||
2237 | return 0; | 2241 | return 0; |
2238 | } | 2242 | } |
2239 | 2243 | ||
@@ -2262,6 +2266,7 @@ static int sh_mdio_init(struct net_device *ndev, int id, | |||
2262 | bitbang->ctrl.ops = &bb_ops; | 2266 | bitbang->ctrl.ops = &bb_ops; |
2263 | 2267 | ||
2264 | /* MII controller setting */ | 2268 | /* MII controller setting */ |
2269 | mdp->bitbang = bitbang; | ||
2265 | mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl); | 2270 | mdp->mii_bus = alloc_mdio_bitbang(&bitbang->ctrl); |
2266 | if (!mdp->mii_bus) { | 2271 | if (!mdp->mii_bus) { |
2267 | ret = -ENOMEM; | 2272 | ret = -ENOMEM; |
@@ -2441,6 +2446,11 @@ static int sh_eth_drv_probe(struct platform_device *pdev) | |||
2441 | } | 2446 | } |
2442 | mdp->tsu_addr = ioremap(rtsu->start, | 2447 | mdp->tsu_addr = ioremap(rtsu->start, |
2443 | resource_size(rtsu)); | 2448 | resource_size(rtsu)); |
2449 | if (mdp->tsu_addr == NULL) { | ||
2450 | ret = -ENOMEM; | ||
2451 | dev_err(&pdev->dev, "TSU ioremap failed.\n"); | ||
2452 | goto out_release; | ||
2453 | } | ||
2444 | mdp->port = devno % 2; | 2454 | mdp->port = devno % 2; |
2445 | ndev->features = NETIF_F_HW_VLAN_FILTER; | 2455 | ndev->features = NETIF_F_HW_VLAN_FILTER; |
2446 | } | 2456 | } |
diff --git a/drivers/net/ethernet/renesas/sh_eth.h b/drivers/net/ethernet/renesas/sh_eth.h index bae84fd2e73a..e6655678458e 100644 --- a/drivers/net/ethernet/renesas/sh_eth.h +++ b/drivers/net/ethernet/renesas/sh_eth.h | |||
@@ -705,6 +705,7 @@ struct sh_eth_private { | |||
705 | const u16 *reg_offset; | 705 | const u16 *reg_offset; |
706 | void __iomem *addr; | 706 | void __iomem *addr; |
707 | void __iomem *tsu_addr; | 707 | void __iomem *tsu_addr; |
708 | struct bb_info *bitbang; | ||
708 | u32 num_rx_ring; | 709 | u32 num_rx_ring; |
709 | u32 num_tx_ring; | 710 | u32 num_tx_ring; |
710 | dma_addr_t rx_desc_dma; | 711 | dma_addr_t rx_desc_dma; |
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index bf57b3cb16ab..0bc00991d310 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -779,6 +779,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) | |||
779 | tx_queue->txd.entries); | 779 | tx_queue->txd.entries); |
780 | } | 780 | } |
781 | 781 | ||
782 | efx_device_detach_sync(efx); | ||
782 | efx_stop_all(efx); | 783 | efx_stop_all(efx); |
783 | efx_stop_interrupts(efx, true); | 784 | efx_stop_interrupts(efx, true); |
784 | 785 | ||
@@ -832,6 +833,7 @@ out: | |||
832 | 833 | ||
833 | efx_start_interrupts(efx, true); | 834 | efx_start_interrupts(efx, true); |
834 | efx_start_all(efx); | 835 | efx_start_all(efx); |
836 | netif_device_attach(efx->net_dev); | ||
835 | return rc; | 837 | return rc; |
836 | 838 | ||
837 | rollback: | 839 | rollback: |
@@ -1641,8 +1643,12 @@ static void efx_stop_all(struct efx_nic *efx) | |||
1641 | /* Flush efx_mac_work(), refill_workqueue, monitor_work */ | 1643 | /* Flush efx_mac_work(), refill_workqueue, monitor_work */ |
1642 | efx_flush_all(efx); | 1644 | efx_flush_all(efx); |
1643 | 1645 | ||
1644 | /* Stop the kernel transmit interface late, so the watchdog | 1646 | /* Stop the kernel transmit interface. This is only valid if |
1645 | * timer isn't ticking over the flush */ | 1647 | * the device is stopped or detached; otherwise the watchdog |
1648 | * may fire immediately. | ||
1649 | */ | ||
1650 | WARN_ON(netif_running(efx->net_dev) && | ||
1651 | netif_device_present(efx->net_dev)); | ||
1646 | netif_tx_disable(efx->net_dev); | 1652 | netif_tx_disable(efx->net_dev); |
1647 | 1653 | ||
1648 | efx_stop_datapath(efx); | 1654 | efx_stop_datapath(efx); |
@@ -1963,16 +1969,18 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) | |||
1963 | if (new_mtu > EFX_MAX_MTU) | 1969 | if (new_mtu > EFX_MAX_MTU) |
1964 | return -EINVAL; | 1970 | return -EINVAL; |
1965 | 1971 | ||
1966 | efx_stop_all(efx); | ||
1967 | |||
1968 | netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); | 1972 | netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu); |
1969 | 1973 | ||
1974 | efx_device_detach_sync(efx); | ||
1975 | efx_stop_all(efx); | ||
1976 | |||
1970 | mutex_lock(&efx->mac_lock); | 1977 | mutex_lock(&efx->mac_lock); |
1971 | net_dev->mtu = new_mtu; | 1978 | net_dev->mtu = new_mtu; |
1972 | efx->type->reconfigure_mac(efx); | 1979 | efx->type->reconfigure_mac(efx); |
1973 | mutex_unlock(&efx->mac_lock); | 1980 | mutex_unlock(&efx->mac_lock); |
1974 | 1981 | ||
1975 | efx_start_all(efx); | 1982 | efx_start_all(efx); |
1983 | netif_device_attach(efx->net_dev); | ||
1976 | return 0; | 1984 | return 0; |
1977 | } | 1985 | } |
1978 | 1986 | ||
diff --git a/drivers/net/ethernet/sfc/efx.h b/drivers/net/ethernet/sfc/efx.h index 50247dfe8f57..d2f790df6dcb 100644 --- a/drivers/net/ethernet/sfc/efx.h +++ b/drivers/net/ethernet/sfc/efx.h | |||
@@ -171,9 +171,9 @@ static inline void efx_device_detach_sync(struct efx_nic *efx) | |||
171 | * TX scheduler is stopped when we're done and before | 171 | * TX scheduler is stopped when we're done and before |
172 | * netif_device_present() becomes false. | 172 | * netif_device_present() becomes false. |
173 | */ | 173 | */ |
174 | netif_tx_lock(dev); | 174 | netif_tx_lock_bh(dev); |
175 | netif_device_detach(dev); | 175 | netif_device_detach(dev); |
176 | netif_tx_unlock(dev); | 176 | netif_tx_unlock_bh(dev); |
177 | } | 177 | } |
178 | 178 | ||
179 | #endif /* EFX_EFX_H */ | 179 | #endif /* EFX_EFX_H */ |
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h index 2d756c1d7142..0a90abd2421b 100644 --- a/drivers/net/ethernet/sfc/net_driver.h +++ b/drivers/net/ethernet/sfc/net_driver.h | |||
@@ -210,6 +210,7 @@ struct efx_tx_queue { | |||
210 | * Will be %NULL if the buffer slot is currently free. | 210 | * Will be %NULL if the buffer slot is currently free. |
211 | * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. | 211 | * @page: The associated page buffer. Valif iff @flags & %EFX_RX_BUF_PAGE. |
212 | * Will be %NULL if the buffer slot is currently free. | 212 | * Will be %NULL if the buffer slot is currently free. |
213 | * @page_offset: Offset within page. Valid iff @flags & %EFX_RX_BUF_PAGE. | ||
213 | * @len: Buffer length, in bytes. | 214 | * @len: Buffer length, in bytes. |
214 | * @flags: Flags for buffer and packet state. | 215 | * @flags: Flags for buffer and packet state. |
215 | */ | 216 | */ |
@@ -219,7 +220,8 @@ struct efx_rx_buffer { | |||
219 | struct sk_buff *skb; | 220 | struct sk_buff *skb; |
220 | struct page *page; | 221 | struct page *page; |
221 | } u; | 222 | } u; |
222 | unsigned int len; | 223 | u16 page_offset; |
224 | u16 len; | ||
223 | u16 flags; | 225 | u16 flags; |
224 | }; | 226 | }; |
225 | #define EFX_RX_BUF_PAGE 0x0001 | 227 | #define EFX_RX_BUF_PAGE 0x0001 |
diff --git a/drivers/net/ethernet/sfc/nic.c b/drivers/net/ethernet/sfc/nic.c index 0ad790cc473c..eaa8e874a3cb 100644 --- a/drivers/net/ethernet/sfc/nic.c +++ b/drivers/net/ethernet/sfc/nic.c | |||
@@ -376,7 +376,8 @@ efx_may_push_tx_desc(struct efx_tx_queue *tx_queue, unsigned int write_count) | |||
376 | return false; | 376 | return false; |
377 | 377 | ||
378 | tx_queue->empty_read_count = 0; | 378 | tx_queue->empty_read_count = 0; |
379 | return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0; | 379 | return ((empty_read_count ^ write_count) & ~EFX_EMPTY_COUNT_VALID) == 0 |
380 | && tx_queue->write_count - write_count == 1; | ||
380 | } | 381 | } |
381 | 382 | ||
382 | /* For each entry inserted into the software descriptor ring, create a | 383 | /* For each entry inserted into the software descriptor ring, create a |
diff --git a/drivers/net/ethernet/sfc/rx.c b/drivers/net/ethernet/sfc/rx.c index d780a0d096b4..bb579a6128c8 100644 --- a/drivers/net/ethernet/sfc/rx.c +++ b/drivers/net/ethernet/sfc/rx.c | |||
@@ -90,11 +90,7 @@ static unsigned int rx_refill_threshold; | |||
90 | static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, | 90 | static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx, |
91 | struct efx_rx_buffer *buf) | 91 | struct efx_rx_buffer *buf) |
92 | { | 92 | { |
93 | /* Offset is always within one page, so we don't need to consider | 93 | return buf->page_offset + efx->type->rx_buffer_hash_size; |
94 | * the page order. | ||
95 | */ | ||
96 | return ((unsigned int) buf->dma_addr & (PAGE_SIZE - 1)) + | ||
97 | efx->type->rx_buffer_hash_size; | ||
98 | } | 94 | } |
99 | static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) | 95 | static inline unsigned int efx_rx_buf_size(struct efx_nic *efx) |
100 | { | 96 | { |
@@ -187,6 +183,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
187 | struct efx_nic *efx = rx_queue->efx; | 183 | struct efx_nic *efx = rx_queue->efx; |
188 | struct efx_rx_buffer *rx_buf; | 184 | struct efx_rx_buffer *rx_buf; |
189 | struct page *page; | 185 | struct page *page; |
186 | unsigned int page_offset; | ||
190 | struct efx_rx_page_state *state; | 187 | struct efx_rx_page_state *state; |
191 | dma_addr_t dma_addr; | 188 | dma_addr_t dma_addr; |
192 | unsigned index, count; | 189 | unsigned index, count; |
@@ -211,12 +208,14 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
211 | state->dma_addr = dma_addr; | 208 | state->dma_addr = dma_addr; |
212 | 209 | ||
213 | dma_addr += sizeof(struct efx_rx_page_state); | 210 | dma_addr += sizeof(struct efx_rx_page_state); |
211 | page_offset = sizeof(struct efx_rx_page_state); | ||
214 | 212 | ||
215 | split: | 213 | split: |
216 | index = rx_queue->added_count & rx_queue->ptr_mask; | 214 | index = rx_queue->added_count & rx_queue->ptr_mask; |
217 | rx_buf = efx_rx_buffer(rx_queue, index); | 215 | rx_buf = efx_rx_buffer(rx_queue, index); |
218 | rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; | 216 | rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN; |
219 | rx_buf->u.page = page; | 217 | rx_buf->u.page = page; |
218 | rx_buf->page_offset = page_offset + EFX_PAGE_IP_ALIGN; | ||
220 | rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; | 219 | rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN; |
221 | rx_buf->flags = EFX_RX_BUF_PAGE; | 220 | rx_buf->flags = EFX_RX_BUF_PAGE; |
222 | ++rx_queue->added_count; | 221 | ++rx_queue->added_count; |
@@ -227,6 +226,7 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
227 | /* Use the second half of the page */ | 226 | /* Use the second half of the page */ |
228 | get_page(page); | 227 | get_page(page); |
229 | dma_addr += (PAGE_SIZE >> 1); | 228 | dma_addr += (PAGE_SIZE >> 1); |
229 | page_offset += (PAGE_SIZE >> 1); | ||
230 | ++count; | 230 | ++count; |
231 | goto split; | 231 | goto split; |
232 | } | 232 | } |
@@ -236,7 +236,8 @@ static int efx_init_rx_buffers_page(struct efx_rx_queue *rx_queue) | |||
236 | } | 236 | } |
237 | 237 | ||
238 | static void efx_unmap_rx_buffer(struct efx_nic *efx, | 238 | static void efx_unmap_rx_buffer(struct efx_nic *efx, |
239 | struct efx_rx_buffer *rx_buf) | 239 | struct efx_rx_buffer *rx_buf, |
240 | unsigned int used_len) | ||
240 | { | 241 | { |
241 | if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { | 242 | if ((rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.page) { |
242 | struct efx_rx_page_state *state; | 243 | struct efx_rx_page_state *state; |
@@ -247,6 +248,10 @@ static void efx_unmap_rx_buffer(struct efx_nic *efx, | |||
247 | state->dma_addr, | 248 | state->dma_addr, |
248 | efx_rx_buf_size(efx), | 249 | efx_rx_buf_size(efx), |
249 | DMA_FROM_DEVICE); | 250 | DMA_FROM_DEVICE); |
251 | } else if (used_len) { | ||
252 | dma_sync_single_for_cpu(&efx->pci_dev->dev, | ||
253 | rx_buf->dma_addr, used_len, | ||
254 | DMA_FROM_DEVICE); | ||
250 | } | 255 | } |
251 | } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { | 256 | } else if (!(rx_buf->flags & EFX_RX_BUF_PAGE) && rx_buf->u.skb) { |
252 | dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr, | 257 | dma_unmap_single(&efx->pci_dev->dev, rx_buf->dma_addr, |
@@ -269,7 +274,7 @@ static void efx_free_rx_buffer(struct efx_nic *efx, | |||
269 | static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, | 274 | static void efx_fini_rx_buffer(struct efx_rx_queue *rx_queue, |
270 | struct efx_rx_buffer *rx_buf) | 275 | struct efx_rx_buffer *rx_buf) |
271 | { | 276 | { |
272 | efx_unmap_rx_buffer(rx_queue->efx, rx_buf); | 277 | efx_unmap_rx_buffer(rx_queue->efx, rx_buf, 0); |
273 | efx_free_rx_buffer(rx_queue->efx, rx_buf); | 278 | efx_free_rx_buffer(rx_queue->efx, rx_buf); |
274 | } | 279 | } |
275 | 280 | ||
@@ -535,10 +540,10 @@ void efx_rx_packet(struct efx_rx_queue *rx_queue, unsigned int index, | |||
535 | goto out; | 540 | goto out; |
536 | } | 541 | } |
537 | 542 | ||
538 | /* Release card resources - assumes all RX buffers consumed in-order | 543 | /* Release and/or sync DMA mapping - assumes all RX buffers |
539 | * per RX queue | 544 | * consumed in-order per RX queue |
540 | */ | 545 | */ |
541 | efx_unmap_rx_buffer(efx, rx_buf); | 546 | efx_unmap_rx_buffer(efx, rx_buf, len); |
542 | 547 | ||
543 | /* Prefetch nice and early so data will (hopefully) be in cache by | 548 | /* Prefetch nice and early so data will (hopefully) be in cache by |
544 | * the time we look at it. | 549 | * the time we look at it. |
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 7e93df6585e7..df32a090d08e 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c | |||
@@ -731,7 +731,7 @@ static inline void cpsw_add_default_vlan(struct cpsw_priv *priv) | |||
731 | 731 | ||
732 | writel(vlan, &priv->host_port_regs->port_vlan); | 732 | writel(vlan, &priv->host_port_regs->port_vlan); |
733 | 733 | ||
734 | for (i = 0; i < 2; i++) | 734 | for (i = 0; i < priv->data.slaves; i++) |
735 | slave_write(priv->slaves + i, vlan, reg); | 735 | slave_write(priv->slaves + i, vlan, reg); |
736 | 736 | ||
737 | cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, | 737 | cpsw_ale_add_vlan(priv->ale, vlan, ALE_ALL_PORTS << port, |
@@ -905,7 +905,7 @@ static netdev_tx_t cpsw_ndo_start_xmit(struct sk_buff *skb, | |||
905 | /* If there is no more tx desc left free then we need to | 905 | /* If there is no more tx desc left free then we need to |
906 | * tell the kernel to stop sending us tx frames. | 906 | * tell the kernel to stop sending us tx frames. |
907 | */ | 907 | */ |
908 | if (unlikely(cpdma_check_free_tx_desc(priv->txch))) | 908 | if (unlikely(!cpdma_check_free_tx_desc(priv->txch))) |
909 | netif_stop_queue(ndev); | 909 | netif_stop_queue(ndev); |
910 | 910 | ||
911 | return NETDEV_TX_OK; | 911 | return NETDEV_TX_OK; |
@@ -1364,7 +1364,7 @@ static int cpsw_probe_dt(struct cpsw_platform_data *data, | |||
1364 | struct platform_device *mdio; | 1364 | struct platform_device *mdio; |
1365 | 1365 | ||
1366 | parp = of_get_property(slave_node, "phy_id", &lenp); | 1366 | parp = of_get_property(slave_node, "phy_id", &lenp); |
1367 | if ((parp == NULL) && (lenp != (sizeof(void *) * 2))) { | 1367 | if ((parp == NULL) || (lenp != (sizeof(void *) * 2))) { |
1368 | pr_err("Missing slave[%d] phy_id property\n", i); | 1368 | pr_err("Missing slave[%d] phy_id property\n", i); |
1369 | ret = -EINVAL; | 1369 | ret = -EINVAL; |
1370 | goto error_ret; | 1370 | goto error_ret; |
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 52c05366599a..ae1b77aa199f 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c | |||
@@ -1102,7 +1102,7 @@ static int emac_dev_xmit(struct sk_buff *skb, struct net_device *ndev) | |||
1102 | /* If there is no more tx desc left free then we need to | 1102 | /* If there is no more tx desc left free then we need to |
1103 | * tell the kernel to stop sending us tx frames. | 1103 | * tell the kernel to stop sending us tx frames. |
1104 | */ | 1104 | */ |
1105 | if (unlikely(cpdma_check_free_tx_desc(priv->txchan))) | 1105 | if (unlikely(!cpdma_check_free_tx_desc(priv->txchan))) |
1106 | netif_stop_queue(ndev); | 1106 | netif_stop_queue(ndev); |
1107 | 1107 | ||
1108 | return NETDEV_TX_OK; | 1108 | return NETDEV_TX_OK; |
diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index e5b19b056909..3c4d6274bb9b 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c | |||
@@ -202,6 +202,9 @@ static int rr_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
202 | return 0; | 202 | return 0; |
203 | 203 | ||
204 | out: | 204 | out: |
205 | if (rrpriv->evt_ring) | ||
206 | pci_free_consistent(pdev, EVT_RING_SIZE, rrpriv->evt_ring, | ||
207 | rrpriv->evt_ring_dma); | ||
205 | if (rrpriv->rx_ring) | 208 | if (rrpriv->rx_ring) |
206 | pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring, | 209 | pci_free_consistent(pdev, RX_TOTAL_SIZE, rrpriv->rx_ring, |
207 | rrpriv->rx_ring_dma); | 210 | rrpriv->rx_ring_dma); |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 417b2af1aa80..73abbc1655d5 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -660,6 +660,7 @@ void macvlan_common_setup(struct net_device *dev) | |||
660 | ether_setup(dev); | 660 | ether_setup(dev); |
661 | 661 | ||
662 | dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); | 662 | dev->priv_flags &= ~(IFF_XMIT_DST_RELEASE | IFF_TX_SKB_SHARING); |
663 | dev->priv_flags |= IFF_UNICAST_FLT; | ||
663 | dev->netdev_ops = &macvlan_netdev_ops; | 664 | dev->netdev_ops = &macvlan_netdev_ops; |
664 | dev->destructor = free_netdev; | 665 | dev->destructor = free_netdev; |
665 | dev->header_ops = &macvlan_hard_header_ops, | 666 | dev->header_ops = &macvlan_hard_header_ops, |
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c index 37add21a3d7d..59ac143dec25 100644 --- a/drivers/net/netconsole.c +++ b/drivers/net/netconsole.c | |||
@@ -666,6 +666,7 @@ static int netconsole_netdev_event(struct notifier_block *this, | |||
666 | goto done; | 666 | goto done; |
667 | 667 | ||
668 | spin_lock_irqsave(&target_list_lock, flags); | 668 | spin_lock_irqsave(&target_list_lock, flags); |
669 | restart: | ||
669 | list_for_each_entry(nt, &target_list, list) { | 670 | list_for_each_entry(nt, &target_list, list) { |
670 | netconsole_target_get(nt); | 671 | netconsole_target_get(nt); |
671 | if (nt->np.dev == dev) { | 672 | if (nt->np.dev == dev) { |
@@ -678,15 +679,17 @@ static int netconsole_netdev_event(struct notifier_block *this, | |||
678 | case NETDEV_UNREGISTER: | 679 | case NETDEV_UNREGISTER: |
679 | /* | 680 | /* |
680 | * rtnl_lock already held | 681 | * rtnl_lock already held |
682 | * we might sleep in __netpoll_cleanup() | ||
681 | */ | 683 | */ |
682 | if (nt->np.dev) { | 684 | spin_unlock_irqrestore(&target_list_lock, flags); |
683 | __netpoll_cleanup(&nt->np); | 685 | __netpoll_cleanup(&nt->np); |
684 | dev_put(nt->np.dev); | 686 | spin_lock_irqsave(&target_list_lock, flags); |
685 | nt->np.dev = NULL; | 687 | dev_put(nt->np.dev); |
686 | } | 688 | nt->np.dev = NULL; |
687 | nt->enabled = 0; | 689 | nt->enabled = 0; |
688 | stopped = true; | 690 | stopped = true; |
689 | break; | 691 | netconsole_target_put(nt); |
692 | goto restart; | ||
690 | } | 693 | } |
691 | } | 694 | } |
692 | netconsole_target_put(nt); | 695 | netconsole_target_put(nt); |
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index 29934446436a..abf7b6153d00 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c | |||
@@ -257,8 +257,7 @@ static struct phy_driver ksphy_driver[] = { | |||
257 | .phy_id = PHY_ID_KSZ9021, | 257 | .phy_id = PHY_ID_KSZ9021, |
258 | .phy_id_mask = 0x000ffffe, | 258 | .phy_id_mask = 0x000ffffe, |
259 | .name = "Micrel KSZ9021 Gigabit PHY", | 259 | .name = "Micrel KSZ9021 Gigabit PHY", |
260 | .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause | 260 | .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), |
261 | | SUPPORTED_Asym_Pause), | ||
262 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, | 261 | .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, |
263 | .config_init = kszphy_config_init, | 262 | .config_init = kszphy_config_init, |
264 | .config_aneg = genphy_config_aneg, | 263 | .config_aneg = genphy_config_aneg, |
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index 9930f9999561..3657b4a29124 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c | |||
@@ -44,13 +44,13 @@ MODULE_LICENSE("GPL"); | |||
44 | 44 | ||
45 | void phy_device_free(struct phy_device *phydev) | 45 | void phy_device_free(struct phy_device *phydev) |
46 | { | 46 | { |
47 | kfree(phydev); | 47 | put_device(&phydev->dev); |
48 | } | 48 | } |
49 | EXPORT_SYMBOL(phy_device_free); | 49 | EXPORT_SYMBOL(phy_device_free); |
50 | 50 | ||
51 | static void phy_device_release(struct device *dev) | 51 | static void phy_device_release(struct device *dev) |
52 | { | 52 | { |
53 | phy_device_free(to_phy_device(dev)); | 53 | kfree(to_phy_device(dev)); |
54 | } | 54 | } |
55 | 55 | ||
56 | static struct phy_driver genphy_driver; | 56 | static struct phy_driver genphy_driver; |
@@ -201,6 +201,8 @@ struct phy_device *phy_device_create(struct mii_bus *bus, int addr, int phy_id, | |||
201 | there's no driver _already_ loaded. */ | 201 | there's no driver _already_ loaded. */ |
202 | request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id)); | 202 | request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phy_id)); |
203 | 203 | ||
204 | device_initialize(&dev->dev); | ||
205 | |||
204 | return dev; | 206 | return dev; |
205 | } | 207 | } |
206 | EXPORT_SYMBOL(phy_device_create); | 208 | EXPORT_SYMBOL(phy_device_create); |
@@ -363,9 +365,9 @@ int phy_device_register(struct phy_device *phydev) | |||
363 | /* Run all of the fixups for this PHY */ | 365 | /* Run all of the fixups for this PHY */ |
364 | phy_scan_fixups(phydev); | 366 | phy_scan_fixups(phydev); |
365 | 367 | ||
366 | err = device_register(&phydev->dev); | 368 | err = device_add(&phydev->dev); |
367 | if (err) { | 369 | if (err) { |
368 | pr_err("phy %d failed to register\n", phydev->addr); | 370 | pr_err("PHY %d failed to add\n", phydev->addr); |
369 | goto out; | 371 | goto out; |
370 | } | 372 | } |
371 | 373 | ||
diff --git a/drivers/net/team/team.c b/drivers/net/team/team.c index 05c5efe84591..bf3419297875 100644 --- a/drivers/net/team/team.c +++ b/drivers/net/team/team.c | |||
@@ -1138,6 +1138,8 @@ static int team_port_del(struct team *team, struct net_device *port_dev) | |||
1138 | netdev_upper_dev_unlink(port_dev, dev); | 1138 | netdev_upper_dev_unlink(port_dev, dev); |
1139 | team_port_disable_netpoll(port); | 1139 | team_port_disable_netpoll(port); |
1140 | vlan_vids_del_by_dev(port_dev, dev); | 1140 | vlan_vids_del_by_dev(port_dev, dev); |
1141 | dev_uc_unsync(port_dev, dev); | ||
1142 | dev_mc_unsync(port_dev, dev); | ||
1141 | dev_close(port_dev); | 1143 | dev_close(port_dev); |
1142 | team_port_leave(team, port); | 1144 | team_port_leave(team, port); |
1143 | 1145 | ||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index 2c6a22e278ea..b7c457adc0dc 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -747,6 +747,8 @@ static netdev_tx_t tun_net_xmit(struct sk_buff *skb, struct net_device *dev) | |||
747 | goto drop; | 747 | goto drop; |
748 | skb_orphan(skb); | 748 | skb_orphan(skb); |
749 | 749 | ||
750 | nf_reset(skb); | ||
751 | |||
750 | /* Enqueue packet */ | 752 | /* Enqueue packet */ |
751 | skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb); | 753 | skb_queue_tail(&tfile->socket.sk->sk_receive_queue, skb); |
752 | 754 | ||
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index da92ed3797aa..7c769d8e25ad 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -156,6 +156,24 @@ config USB_NET_AX8817X | |||
156 | This driver creates an interface named "ethX", where X depends on | 156 | This driver creates an interface named "ethX", where X depends on |
157 | what other networking devices you have in use. | 157 | what other networking devices you have in use. |
158 | 158 | ||
159 | config USB_NET_AX88179_178A | ||
160 | tristate "ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet" | ||
161 | depends on USB_USBNET | ||
162 | select CRC32 | ||
163 | select PHYLIB | ||
164 | default y | ||
165 | help | ||
166 | This option adds support for ASIX AX88179 based USB 3.0/2.0 | ||
167 | to Gigabit Ethernet adapters. | ||
168 | |||
169 | This driver should work with at least the following devices: | ||
170 | * ASIX AX88179 | ||
171 | * ASIX AX88178A | ||
172 | * Sitcomm LN-032 | ||
173 | |||
174 | This driver creates an interface named "ethX", where X depends on | ||
175 | what other networking devices you have in use. | ||
176 | |||
159 | config USB_NET_CDCETHER | 177 | config USB_NET_CDCETHER |
160 | tristate "CDC Ethernet support (smart devices such as cable modems)" | 178 | tristate "CDC Ethernet support (smart devices such as cable modems)" |
161 | depends on USB_USBNET | 179 | depends on USB_USBNET |
@@ -250,7 +268,7 @@ config USB_NET_SMSC75XX | |||
250 | select CRC16 | 268 | select CRC16 |
251 | select CRC32 | 269 | select CRC32 |
252 | help | 270 | help |
253 | This option adds support for SMSC LAN95XX based USB 2.0 | 271 | This option adds support for SMSC LAN75XX based USB 2.0 |
254 | Gigabit Ethernet adapters. | 272 | Gigabit Ethernet adapters. |
255 | 273 | ||
256 | config USB_NET_SMSC95XX | 274 | config USB_NET_SMSC95XX |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 478691326f37..119b06c9aa16 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_USB_RTL8150) += rtl8150.o | |||
9 | obj-$(CONFIG_USB_HSO) += hso.o | 9 | obj-$(CONFIG_USB_HSO) += hso.o |
10 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o | 10 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o |
11 | asix-y := asix_devices.o asix_common.o ax88172a.o | 11 | asix-y := asix_devices.o asix_common.o ax88172a.o |
12 | obj-$(CONFIG_USB_NET_AX88179_178A) += ax88179_178a.o | ||
12 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o | 13 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o |
13 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o | 14 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o |
14 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o | 15 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o |
diff --git a/drivers/net/usb/asix_devices.c b/drivers/net/usb/asix_devices.c index 2205dbc8d32f..709753469099 100644 --- a/drivers/net/usb/asix_devices.c +++ b/drivers/net/usb/asix_devices.c | |||
@@ -924,6 +924,29 @@ static const struct driver_info ax88178_info = { | |||
924 | .tx_fixup = asix_tx_fixup, | 924 | .tx_fixup = asix_tx_fixup, |
925 | }; | 925 | }; |
926 | 926 | ||
927 | /* | ||
928 | * USBLINK 20F9 "USB 2.0 LAN" USB ethernet adapter, typically found in | ||
929 | * no-name packaging. | ||
930 | * USB device strings are: | ||
931 | * 1: Manufacturer: USBLINK | ||
932 | * 2: Product: HG20F9 USB2.0 | ||
933 | * 3: Serial: 000003 | ||
934 | * Appears to be compatible with Asix 88772B. | ||
935 | */ | ||
936 | static const struct driver_info hg20f9_info = { | ||
937 | .description = "HG20F9 USB 2.0 Ethernet", | ||
938 | .bind = ax88772_bind, | ||
939 | .unbind = ax88772_unbind, | ||
940 | .status = asix_status, | ||
941 | .link_reset = ax88772_link_reset, | ||
942 | .reset = ax88772_reset, | ||
943 | .flags = FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | | ||
944 | FLAG_MULTI_PACKET, | ||
945 | .rx_fixup = asix_rx_fixup_common, | ||
946 | .tx_fixup = asix_tx_fixup, | ||
947 | .data = FLAG_EEPROM_MAC, | ||
948 | }; | ||
949 | |||
927 | extern const struct driver_info ax88172a_info; | 950 | extern const struct driver_info ax88172a_info; |
928 | 951 | ||
929 | static const struct usb_device_id products [] = { | 952 | static const struct usb_device_id products [] = { |
@@ -1063,6 +1086,14 @@ static const struct usb_device_id products [] = { | |||
1063 | /* ASIX 88172a demo board */ | 1086 | /* ASIX 88172a demo board */ |
1064 | USB_DEVICE(0x0b95, 0x172a), | 1087 | USB_DEVICE(0x0b95, 0x172a), |
1065 | .driver_info = (unsigned long) &ax88172a_info, | 1088 | .driver_info = (unsigned long) &ax88172a_info, |
1089 | }, { | ||
1090 | /* | ||
1091 | * USBLINK HG20F9 "USB 2.0 LAN" | ||
1092 | * Appears to have gazumped Linksys's manufacturer ID but | ||
1093 | * doesn't (yet) conflict with any known Linksys product. | ||
1094 | */ | ||
1095 | USB_DEVICE(0x066b, 0x20f9), | ||
1096 | .driver_info = (unsigned long) &hg20f9_info, | ||
1066 | }, | 1097 | }, |
1067 | { }, // END | 1098 | { }, // END |
1068 | }; | 1099 | }; |
diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c new file mode 100644 index 000000000000..71c27d8d214f --- /dev/null +++ b/drivers/net/usb/ax88179_178a.c | |||
@@ -0,0 +1,1448 @@ | |||
1 | /* | ||
2 | * ASIX AX88179/178A USB 3.0/2.0 to Gigabit Ethernet Devices | ||
3 | * | ||
4 | * Copyright (C) 2011-2013 ASIX | ||
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 | ||
8 | * as published by the Free Software Foundation; either version 2 | ||
9 | * of the License, or (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License | ||
17 | * along with this program; if not, write to the Free Software | ||
18 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
19 | */ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/etherdevice.h> | ||
23 | #include <linux/mii.h> | ||
24 | #include <linux/usb.h> | ||
25 | #include <linux/crc32.h> | ||
26 | #include <linux/usb/usbnet.h> | ||
27 | |||
28 | #define AX88179_PHY_ID 0x03 | ||
29 | #define AX_EEPROM_LEN 0x100 | ||
30 | #define AX88179_EEPROM_MAGIC 0x17900b95 | ||
31 | #define AX_MCAST_FLTSIZE 8 | ||
32 | #define AX_MAX_MCAST 64 | ||
33 | #define AX_INT_PPLS_LINK ((u32)BIT(16)) | ||
34 | #define AX_RXHDR_L4_TYPE_MASK 0x1c | ||
35 | #define AX_RXHDR_L4_TYPE_UDP 4 | ||
36 | #define AX_RXHDR_L4_TYPE_TCP 16 | ||
37 | #define AX_RXHDR_L3CSUM_ERR 2 | ||
38 | #define AX_RXHDR_L4CSUM_ERR 1 | ||
39 | #define AX_RXHDR_CRC_ERR ((u32)BIT(31)) | ||
40 | #define AX_RXHDR_DROP_ERR ((u32)BIT(30)) | ||
41 | #define AX_ACCESS_MAC 0x01 | ||
42 | #define AX_ACCESS_PHY 0x02 | ||
43 | #define AX_ACCESS_EEPROM 0x04 | ||
44 | #define AX_ACCESS_EFUS 0x05 | ||
45 | #define AX_PAUSE_WATERLVL_HIGH 0x54 | ||
46 | #define AX_PAUSE_WATERLVL_LOW 0x55 | ||
47 | |||
48 | #define PHYSICAL_LINK_STATUS 0x02 | ||
49 | #define AX_USB_SS 0x04 | ||
50 | #define AX_USB_HS 0x02 | ||
51 | |||
52 | #define GENERAL_STATUS 0x03 | ||
53 | /* Check AX88179 version. UA1:Bit2 = 0, UA2:Bit2 = 1 */ | ||
54 | #define AX_SECLD 0x04 | ||
55 | |||
56 | #define AX_SROM_ADDR 0x07 | ||
57 | #define AX_SROM_CMD 0x0a | ||
58 | #define EEP_RD 0x04 | ||
59 | #define EEP_BUSY 0x10 | ||
60 | |||
61 | #define AX_SROM_DATA_LOW 0x08 | ||
62 | #define AX_SROM_DATA_HIGH 0x09 | ||
63 | |||
64 | #define AX_RX_CTL 0x0b | ||
65 | #define AX_RX_CTL_DROPCRCERR 0x0100 | ||
66 | #define AX_RX_CTL_IPE 0x0200 | ||
67 | #define AX_RX_CTL_START 0x0080 | ||
68 | #define AX_RX_CTL_AP 0x0020 | ||
69 | #define AX_RX_CTL_AM 0x0010 | ||
70 | #define AX_RX_CTL_AB 0x0008 | ||
71 | #define AX_RX_CTL_AMALL 0x0002 | ||
72 | #define AX_RX_CTL_PRO 0x0001 | ||
73 | #define AX_RX_CTL_STOP 0x0000 | ||
74 | |||
75 | #define AX_NODE_ID 0x10 | ||
76 | #define AX_MULFLTARY 0x16 | ||
77 | |||
78 | #define AX_MEDIUM_STATUS_MODE 0x22 | ||
79 | #define AX_MEDIUM_GIGAMODE 0x01 | ||
80 | #define AX_MEDIUM_FULL_DUPLEX 0x02 | ||
81 | #define AX_MEDIUM_ALWAYS_ONE 0x04 | ||
82 | #define AX_MEDIUM_EN_125MHZ 0x08 | ||
83 | #define AX_MEDIUM_RXFLOW_CTRLEN 0x10 | ||
84 | #define AX_MEDIUM_TXFLOW_CTRLEN 0x20 | ||
85 | #define AX_MEDIUM_RECEIVE_EN 0x100 | ||
86 | #define AX_MEDIUM_PS 0x200 | ||
87 | #define AX_MEDIUM_JUMBO_EN 0x8040 | ||
88 | |||
89 | #define AX_MONITOR_MOD 0x24 | ||
90 | #define AX_MONITOR_MODE_RWLC 0x02 | ||
91 | #define AX_MONITOR_MODE_RWMP 0x04 | ||
92 | #define AX_MONITOR_MODE_PMEPOL 0x20 | ||
93 | #define AX_MONITOR_MODE_PMETYPE 0x40 | ||
94 | |||
95 | #define AX_GPIO_CTRL 0x25 | ||
96 | #define AX_GPIO_CTRL_GPIO3EN 0x80 | ||
97 | #define AX_GPIO_CTRL_GPIO2EN 0x40 | ||
98 | #define AX_GPIO_CTRL_GPIO1EN 0x20 | ||
99 | |||
100 | #define AX_PHYPWR_RSTCTL 0x26 | ||
101 | #define AX_PHYPWR_RSTCTL_BZ 0x0010 | ||
102 | #define AX_PHYPWR_RSTCTL_IPRL 0x0020 | ||
103 | #define AX_PHYPWR_RSTCTL_AT 0x1000 | ||
104 | |||
105 | #define AX_RX_BULKIN_QCTRL 0x2e | ||
106 | #define AX_CLK_SELECT 0x33 | ||
107 | #define AX_CLK_SELECT_BCS 0x01 | ||
108 | #define AX_CLK_SELECT_ACS 0x02 | ||
109 | #define AX_CLK_SELECT_ULR 0x08 | ||
110 | |||
111 | #define AX_RXCOE_CTL 0x34 | ||
112 | #define AX_RXCOE_IP 0x01 | ||
113 | #define AX_RXCOE_TCP 0x02 | ||
114 | #define AX_RXCOE_UDP 0x04 | ||
115 | #define AX_RXCOE_TCPV6 0x20 | ||
116 | #define AX_RXCOE_UDPV6 0x40 | ||
117 | |||
118 | #define AX_TXCOE_CTL 0x35 | ||
119 | #define AX_TXCOE_IP 0x01 | ||
120 | #define AX_TXCOE_TCP 0x02 | ||
121 | #define AX_TXCOE_UDP 0x04 | ||
122 | #define AX_TXCOE_TCPV6 0x20 | ||
123 | #define AX_TXCOE_UDPV6 0x40 | ||
124 | |||
125 | #define AX_LEDCTRL 0x73 | ||
126 | |||
127 | #define GMII_PHY_PHYSR 0x11 | ||
128 | #define GMII_PHY_PHYSR_SMASK 0xc000 | ||
129 | #define GMII_PHY_PHYSR_GIGA 0x8000 | ||
130 | #define GMII_PHY_PHYSR_100 0x4000 | ||
131 | #define GMII_PHY_PHYSR_FULL 0x2000 | ||
132 | #define GMII_PHY_PHYSR_LINK 0x400 | ||
133 | |||
134 | #define GMII_LED_ACT 0x1a | ||
135 | #define GMII_LED_ACTIVE_MASK 0xff8f | ||
136 | #define GMII_LED0_ACTIVE BIT(4) | ||
137 | #define GMII_LED1_ACTIVE BIT(5) | ||
138 | #define GMII_LED2_ACTIVE BIT(6) | ||
139 | |||
140 | #define GMII_LED_LINK 0x1c | ||
141 | #define GMII_LED_LINK_MASK 0xf888 | ||
142 | #define GMII_LED0_LINK_10 BIT(0) | ||
143 | #define GMII_LED0_LINK_100 BIT(1) | ||
144 | #define GMII_LED0_LINK_1000 BIT(2) | ||
145 | #define GMII_LED1_LINK_10 BIT(4) | ||
146 | #define GMII_LED1_LINK_100 BIT(5) | ||
147 | #define GMII_LED1_LINK_1000 BIT(6) | ||
148 | #define GMII_LED2_LINK_10 BIT(8) | ||
149 | #define GMII_LED2_LINK_100 BIT(9) | ||
150 | #define GMII_LED2_LINK_1000 BIT(10) | ||
151 | #define LED0_ACTIVE BIT(0) | ||
152 | #define LED0_LINK_10 BIT(1) | ||
153 | #define LED0_LINK_100 BIT(2) | ||
154 | #define LED0_LINK_1000 BIT(3) | ||
155 | #define LED0_FD BIT(4) | ||
156 | #define LED0_USB3_MASK 0x001f | ||
157 | #define LED1_ACTIVE BIT(5) | ||
158 | #define LED1_LINK_10 BIT(6) | ||
159 | #define LED1_LINK_100 BIT(7) | ||
160 | #define LED1_LINK_1000 BIT(8) | ||
161 | #define LED1_FD BIT(9) | ||
162 | #define LED1_USB3_MASK 0x03e0 | ||
163 | #define LED2_ACTIVE BIT(10) | ||
164 | #define LED2_LINK_1000 BIT(13) | ||
165 | #define LED2_LINK_100 BIT(12) | ||
166 | #define LED2_LINK_10 BIT(11) | ||
167 | #define LED2_FD BIT(14) | ||
168 | #define LED_VALID BIT(15) | ||
169 | #define LED2_USB3_MASK 0x7c00 | ||
170 | |||
171 | #define GMII_PHYPAGE 0x1e | ||
172 | #define GMII_PHY_PAGE_SELECT 0x1f | ||
173 | #define GMII_PHY_PGSEL_EXT 0x0007 | ||
174 | #define GMII_PHY_PGSEL_PAGE0 0x0000 | ||
175 | |||
176 | struct ax88179_data { | ||
177 | u16 rxctl; | ||
178 | u16 reserved; | ||
179 | }; | ||
180 | |||
181 | struct ax88179_int_data { | ||
182 | __le32 intdata1; | ||
183 | __le32 intdata2; | ||
184 | }; | ||
185 | |||
186 | static const struct { | ||
187 | unsigned char ctrl, timer_l, timer_h, size, ifg; | ||
188 | } AX88179_BULKIN_SIZE[] = { | ||
189 | {7, 0x4f, 0, 0x12, 0xff}, | ||
190 | {7, 0x20, 3, 0x16, 0xff}, | ||
191 | {7, 0xae, 7, 0x18, 0xff}, | ||
192 | {7, 0xcc, 0x4c, 0x18, 8}, | ||
193 | }; | ||
194 | |||
195 | static int __ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
196 | u16 size, void *data, int in_pm) | ||
197 | { | ||
198 | int ret; | ||
199 | int (*fn)(struct usbnet *, u8, u8, u16, u16, void *, u16); | ||
200 | |||
201 | BUG_ON(!dev); | ||
202 | |||
203 | if (!in_pm) | ||
204 | fn = usbnet_read_cmd; | ||
205 | else | ||
206 | fn = usbnet_read_cmd_nopm; | ||
207 | |||
208 | ret = fn(dev, cmd, USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
209 | value, index, data, size); | ||
210 | |||
211 | if (unlikely(ret < 0)) | ||
212 | netdev_warn(dev->net, "Failed to read reg index 0x%04x: %d\n", | ||
213 | index, ret); | ||
214 | |||
215 | return ret; | ||
216 | } | ||
217 | |||
218 | static int __ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
219 | u16 size, void *data, int in_pm) | ||
220 | { | ||
221 | int ret; | ||
222 | int (*fn)(struct usbnet *, u8, u8, u16, u16, const void *, u16); | ||
223 | |||
224 | BUG_ON(!dev); | ||
225 | |||
226 | if (!in_pm) | ||
227 | fn = usbnet_write_cmd; | ||
228 | else | ||
229 | fn = usbnet_write_cmd_nopm; | ||
230 | |||
231 | ret = fn(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
232 | value, index, data, size); | ||
233 | |||
234 | if (unlikely(ret < 0)) | ||
235 | netdev_warn(dev->net, "Failed to write reg index 0x%04x: %d\n", | ||
236 | index, ret); | ||
237 | |||
238 | return ret; | ||
239 | } | ||
240 | |||
241 | static void ax88179_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, | ||
242 | u16 index, u16 size, void *data) | ||
243 | { | ||
244 | u16 buf; | ||
245 | |||
246 | if (2 == size) { | ||
247 | buf = *((u16 *)data); | ||
248 | cpu_to_le16s(&buf); | ||
249 | usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | | ||
250 | USB_RECIP_DEVICE, value, index, &buf, | ||
251 | size); | ||
252 | } else { | ||
253 | usbnet_write_cmd_async(dev, cmd, USB_DIR_OUT | USB_TYPE_VENDOR | | ||
254 | USB_RECIP_DEVICE, value, index, data, | ||
255 | size); | ||
256 | } | ||
257 | } | ||
258 | |||
259 | static int ax88179_read_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, | ||
260 | u16 index, u16 size, void *data) | ||
261 | { | ||
262 | int ret; | ||
263 | |||
264 | if (2 == size) { | ||
265 | u16 buf; | ||
266 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); | ||
267 | le16_to_cpus(&buf); | ||
268 | *((u16 *)data) = buf; | ||
269 | } else if (4 == size) { | ||
270 | u32 buf; | ||
271 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 1); | ||
272 | le32_to_cpus(&buf); | ||
273 | *((u32 *)data) = buf; | ||
274 | } else { | ||
275 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 1); | ||
276 | } | ||
277 | |||
278 | return ret; | ||
279 | } | ||
280 | |||
281 | static int ax88179_write_cmd_nopm(struct usbnet *dev, u8 cmd, u16 value, | ||
282 | u16 index, u16 size, void *data) | ||
283 | { | ||
284 | int ret; | ||
285 | |||
286 | if (2 == size) { | ||
287 | u16 buf; | ||
288 | buf = *((u16 *)data); | ||
289 | cpu_to_le16s(&buf); | ||
290 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
291 | size, &buf, 1); | ||
292 | } else { | ||
293 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
294 | size, data, 1); | ||
295 | } | ||
296 | |||
297 | return ret; | ||
298 | } | ||
299 | |||
300 | static int ax88179_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
301 | u16 size, void *data) | ||
302 | { | ||
303 | int ret; | ||
304 | |||
305 | if (2 == size) { | ||
306 | u16 buf; | ||
307 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); | ||
308 | le16_to_cpus(&buf); | ||
309 | *((u16 *)data) = buf; | ||
310 | } else if (4 == size) { | ||
311 | u32 buf; | ||
312 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, &buf, 0); | ||
313 | le32_to_cpus(&buf); | ||
314 | *((u32 *)data) = buf; | ||
315 | } else { | ||
316 | ret = __ax88179_read_cmd(dev, cmd, value, index, size, data, 0); | ||
317 | } | ||
318 | |||
319 | return ret; | ||
320 | } | ||
321 | |||
322 | static int ax88179_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
323 | u16 size, void *data) | ||
324 | { | ||
325 | int ret; | ||
326 | |||
327 | if (2 == size) { | ||
328 | u16 buf; | ||
329 | buf = *((u16 *)data); | ||
330 | cpu_to_le16s(&buf); | ||
331 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
332 | size, &buf, 0); | ||
333 | } else { | ||
334 | ret = __ax88179_write_cmd(dev, cmd, value, index, | ||
335 | size, data, 0); | ||
336 | } | ||
337 | |||
338 | return ret; | ||
339 | } | ||
340 | |||
341 | static void ax88179_status(struct usbnet *dev, struct urb *urb) | ||
342 | { | ||
343 | struct ax88179_int_data *event; | ||
344 | u32 link; | ||
345 | |||
346 | if (urb->actual_length < 8) | ||
347 | return; | ||
348 | |||
349 | event = urb->transfer_buffer; | ||
350 | le32_to_cpus((void *)&event->intdata1); | ||
351 | |||
352 | link = (((__force u32)event->intdata1) & AX_INT_PPLS_LINK) >> 16; | ||
353 | |||
354 | if (netif_carrier_ok(dev->net) != link) { | ||
355 | if (link) | ||
356 | usbnet_defer_kevent(dev, EVENT_LINK_RESET); | ||
357 | else | ||
358 | netif_carrier_off(dev->net); | ||
359 | |||
360 | netdev_info(dev->net, "ax88179 - Link status is: %d\n", link); | ||
361 | } | ||
362 | } | ||
363 | |||
364 | static int ax88179_mdio_read(struct net_device *netdev, int phy_id, int loc) | ||
365 | { | ||
366 | struct usbnet *dev = netdev_priv(netdev); | ||
367 | u16 res; | ||
368 | |||
369 | ax88179_read_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); | ||
370 | return res; | ||
371 | } | ||
372 | |||
373 | static void ax88179_mdio_write(struct net_device *netdev, int phy_id, int loc, | ||
374 | int val) | ||
375 | { | ||
376 | struct usbnet *dev = netdev_priv(netdev); | ||
377 | u16 res = (u16) val; | ||
378 | |||
379 | ax88179_write_cmd(dev, AX_ACCESS_PHY, phy_id, (__u16)loc, 2, &res); | ||
380 | } | ||
381 | |||
382 | static int ax88179_suspend(struct usb_interface *intf, pm_message_t message) | ||
383 | { | ||
384 | struct usbnet *dev = usb_get_intfdata(intf); | ||
385 | u16 tmp16; | ||
386 | u8 tmp8; | ||
387 | |||
388 | usbnet_suspend(intf, message); | ||
389 | |||
390 | /* Disable RX path */ | ||
391 | ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
392 | 2, 2, &tmp16); | ||
393 | tmp16 &= ~AX_MEDIUM_RECEIVE_EN; | ||
394 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
395 | 2, 2, &tmp16); | ||
396 | |||
397 | /* Force bulk-in zero length */ | ||
398 | ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
399 | 2, 2, &tmp16); | ||
400 | |||
401 | tmp16 |= AX_PHYPWR_RSTCTL_BZ | AX_PHYPWR_RSTCTL_IPRL; | ||
402 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
403 | 2, 2, &tmp16); | ||
404 | |||
405 | /* change clock */ | ||
406 | tmp8 = 0; | ||
407 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
408 | |||
409 | /* Configure RX control register => stop operation */ | ||
410 | tmp16 = AX_RX_CTL_STOP; | ||
411 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); | ||
412 | |||
413 | return 0; | ||
414 | } | ||
415 | |||
416 | /* This function is used to enable the autodetach function. */ | ||
417 | /* This function is determined by offset 0x43 of EEPROM */ | ||
418 | static int ax88179_auto_detach(struct usbnet *dev, int in_pm) | ||
419 | { | ||
420 | u16 tmp16; | ||
421 | u8 tmp8; | ||
422 | int (*fnr)(struct usbnet *, u8, u16, u16, u16, void *); | ||
423 | int (*fnw)(struct usbnet *, u8, u16, u16, u16, void *); | ||
424 | |||
425 | if (!in_pm) { | ||
426 | fnr = ax88179_read_cmd; | ||
427 | fnw = ax88179_write_cmd; | ||
428 | } else { | ||
429 | fnr = ax88179_read_cmd_nopm; | ||
430 | fnw = ax88179_write_cmd_nopm; | ||
431 | } | ||
432 | |||
433 | if (fnr(dev, AX_ACCESS_EEPROM, 0x43, 1, 2, &tmp16) < 0) | ||
434 | return 0; | ||
435 | |||
436 | if ((tmp16 == 0xFFFF) || (!(tmp16 & 0x0100))) | ||
437 | return 0; | ||
438 | |||
439 | /* Enable Auto Detach bit */ | ||
440 | tmp8 = 0; | ||
441 | fnr(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
442 | tmp8 |= AX_CLK_SELECT_ULR; | ||
443 | fnw(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
444 | |||
445 | fnr(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); | ||
446 | tmp16 |= AX_PHYPWR_RSTCTL_AT; | ||
447 | fnw(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); | ||
448 | |||
449 | return 0; | ||
450 | } | ||
451 | |||
452 | static int ax88179_resume(struct usb_interface *intf) | ||
453 | { | ||
454 | struct usbnet *dev = usb_get_intfdata(intf); | ||
455 | u16 tmp16; | ||
456 | u8 tmp8; | ||
457 | |||
458 | netif_carrier_off(dev->net); | ||
459 | |||
460 | /* Power up ethernet PHY */ | ||
461 | tmp16 = 0; | ||
462 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
463 | 2, 2, &tmp16); | ||
464 | udelay(1000); | ||
465 | |||
466 | tmp16 = AX_PHYPWR_RSTCTL_IPRL; | ||
467 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, | ||
468 | 2, 2, &tmp16); | ||
469 | msleep(200); | ||
470 | |||
471 | /* Ethernet PHY Auto Detach*/ | ||
472 | ax88179_auto_detach(dev, 1); | ||
473 | |||
474 | /* Enable clock */ | ||
475 | ax88179_read_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
476 | tmp8 |= AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; | ||
477 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp8); | ||
478 | msleep(100); | ||
479 | |||
480 | /* Configure RX control register => start operation */ | ||
481 | tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | | ||
482 | AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; | ||
483 | ax88179_write_cmd_nopm(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); | ||
484 | |||
485 | return usbnet_resume(intf); | ||
486 | } | ||
487 | |||
488 | static void | ||
489 | ax88179_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
490 | { | ||
491 | struct usbnet *dev = netdev_priv(net); | ||
492 | u8 opt; | ||
493 | |||
494 | if (ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, | ||
495 | 1, 1, &opt) < 0) { | ||
496 | wolinfo->supported = 0; | ||
497 | wolinfo->wolopts = 0; | ||
498 | return; | ||
499 | } | ||
500 | |||
501 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | ||
502 | wolinfo->wolopts = 0; | ||
503 | if (opt & AX_MONITOR_MODE_RWLC) | ||
504 | wolinfo->wolopts |= WAKE_PHY; | ||
505 | if (opt & AX_MONITOR_MODE_RWMP) | ||
506 | wolinfo->wolopts |= WAKE_MAGIC; | ||
507 | } | ||
508 | |||
509 | static int | ||
510 | ax88179_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
511 | { | ||
512 | struct usbnet *dev = netdev_priv(net); | ||
513 | u8 opt = 0; | ||
514 | |||
515 | if (wolinfo->wolopts & WAKE_PHY) | ||
516 | opt |= AX_MONITOR_MODE_RWLC; | ||
517 | if (wolinfo->wolopts & WAKE_MAGIC) | ||
518 | opt |= AX_MONITOR_MODE_RWMP; | ||
519 | |||
520 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, | ||
521 | 1, 1, &opt) < 0) | ||
522 | return -EINVAL; | ||
523 | |||
524 | return 0; | ||
525 | } | ||
526 | |||
527 | static int ax88179_get_eeprom_len(struct net_device *net) | ||
528 | { | ||
529 | return AX_EEPROM_LEN; | ||
530 | } | ||
531 | |||
532 | static int | ||
533 | ax88179_get_eeprom(struct net_device *net, struct ethtool_eeprom *eeprom, | ||
534 | u8 *data) | ||
535 | { | ||
536 | struct usbnet *dev = netdev_priv(net); | ||
537 | u16 *eeprom_buff; | ||
538 | int first_word, last_word; | ||
539 | int i, ret; | ||
540 | |||
541 | if (eeprom->len == 0) | ||
542 | return -EINVAL; | ||
543 | |||
544 | eeprom->magic = AX88179_EEPROM_MAGIC; | ||
545 | |||
546 | first_word = eeprom->offset >> 1; | ||
547 | last_word = (eeprom->offset + eeprom->len - 1) >> 1; | ||
548 | eeprom_buff = kmalloc(sizeof(u16) * (last_word - first_word + 1), | ||
549 | GFP_KERNEL); | ||
550 | if (!eeprom_buff) | ||
551 | return -ENOMEM; | ||
552 | |||
553 | /* ax88179/178A returns 2 bytes from eeprom on read */ | ||
554 | for (i = first_word; i <= last_word; i++) { | ||
555 | ret = __ax88179_read_cmd(dev, AX_ACCESS_EEPROM, i, 1, 2, | ||
556 | &eeprom_buff[i - first_word], | ||
557 | 0); | ||
558 | if (ret < 0) { | ||
559 | kfree(eeprom_buff); | ||
560 | return -EIO; | ||
561 | } | ||
562 | } | ||
563 | |||
564 | memcpy(data, (u8 *)eeprom_buff + (eeprom->offset & 1), eeprom->len); | ||
565 | kfree(eeprom_buff); | ||
566 | return 0; | ||
567 | } | ||
568 | |||
569 | static int ax88179_get_settings(struct net_device *net, struct ethtool_cmd *cmd) | ||
570 | { | ||
571 | struct usbnet *dev = netdev_priv(net); | ||
572 | return mii_ethtool_gset(&dev->mii, cmd); | ||
573 | } | ||
574 | |||
575 | static int ax88179_set_settings(struct net_device *net, struct ethtool_cmd *cmd) | ||
576 | { | ||
577 | struct usbnet *dev = netdev_priv(net); | ||
578 | return mii_ethtool_sset(&dev->mii, cmd); | ||
579 | } | ||
580 | |||
581 | |||
582 | static int ax88179_ioctl(struct net_device *net, struct ifreq *rq, int cmd) | ||
583 | { | ||
584 | struct usbnet *dev = netdev_priv(net); | ||
585 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
586 | } | ||
587 | |||
588 | static const struct ethtool_ops ax88179_ethtool_ops = { | ||
589 | .get_link = ethtool_op_get_link, | ||
590 | .get_msglevel = usbnet_get_msglevel, | ||
591 | .set_msglevel = usbnet_set_msglevel, | ||
592 | .get_wol = ax88179_get_wol, | ||
593 | .set_wol = ax88179_set_wol, | ||
594 | .get_eeprom_len = ax88179_get_eeprom_len, | ||
595 | .get_eeprom = ax88179_get_eeprom, | ||
596 | .get_settings = ax88179_get_settings, | ||
597 | .set_settings = ax88179_set_settings, | ||
598 | .nway_reset = usbnet_nway_reset, | ||
599 | }; | ||
600 | |||
601 | static void ax88179_set_multicast(struct net_device *net) | ||
602 | { | ||
603 | struct usbnet *dev = netdev_priv(net); | ||
604 | struct ax88179_data *data = (struct ax88179_data *)dev->data; | ||
605 | u8 *m_filter = ((u8 *)dev->data) + 12; | ||
606 | |||
607 | data->rxctl = (AX_RX_CTL_START | AX_RX_CTL_AB | AX_RX_CTL_IPE); | ||
608 | |||
609 | if (net->flags & IFF_PROMISC) { | ||
610 | data->rxctl |= AX_RX_CTL_PRO; | ||
611 | } else if (net->flags & IFF_ALLMULTI || | ||
612 | netdev_mc_count(net) > AX_MAX_MCAST) { | ||
613 | data->rxctl |= AX_RX_CTL_AMALL; | ||
614 | } else if (netdev_mc_empty(net)) { | ||
615 | /* just broadcast and directed */ | ||
616 | } else { | ||
617 | /* We use the 20 byte dev->data for our 8 byte filter buffer | ||
618 | * to avoid allocating memory that is tricky to free later | ||
619 | */ | ||
620 | u32 crc_bits; | ||
621 | struct netdev_hw_addr *ha; | ||
622 | |||
623 | memset(m_filter, 0, AX_MCAST_FLTSIZE); | ||
624 | |||
625 | netdev_for_each_mc_addr(ha, net) { | ||
626 | crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; | ||
627 | *(m_filter + (crc_bits >> 3)) |= (1 << (crc_bits & 7)); | ||
628 | } | ||
629 | |||
630 | ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_MULFLTARY, | ||
631 | AX_MCAST_FLTSIZE, AX_MCAST_FLTSIZE, | ||
632 | m_filter); | ||
633 | |||
634 | data->rxctl |= AX_RX_CTL_AM; | ||
635 | } | ||
636 | |||
637 | ax88179_write_cmd_async(dev, AX_ACCESS_MAC, AX_RX_CTL, | ||
638 | 2, 2, &data->rxctl); | ||
639 | } | ||
640 | |||
641 | static int | ||
642 | ax88179_set_features(struct net_device *net, netdev_features_t features) | ||
643 | { | ||
644 | u8 tmp; | ||
645 | struct usbnet *dev = netdev_priv(net); | ||
646 | netdev_features_t changed = net->features ^ features; | ||
647 | |||
648 | if (changed & NETIF_F_IP_CSUM) { | ||
649 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
650 | tmp ^= AX_TXCOE_TCP | AX_TXCOE_UDP; | ||
651 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
652 | } | ||
653 | |||
654 | if (changed & NETIF_F_IPV6_CSUM) { | ||
655 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
656 | tmp ^= AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; | ||
657 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, &tmp); | ||
658 | } | ||
659 | |||
660 | if (changed & NETIF_F_RXCSUM) { | ||
661 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); | ||
662 | tmp ^= AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | | ||
663 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; | ||
664 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, &tmp); | ||
665 | } | ||
666 | |||
667 | return 0; | ||
668 | } | ||
669 | |||
670 | static int ax88179_change_mtu(struct net_device *net, int new_mtu) | ||
671 | { | ||
672 | struct usbnet *dev = netdev_priv(net); | ||
673 | u16 tmp16; | ||
674 | |||
675 | if (new_mtu <= 0 || new_mtu > 4088) | ||
676 | return -EINVAL; | ||
677 | |||
678 | net->mtu = new_mtu; | ||
679 | dev->hard_mtu = net->mtu + net->hard_header_len; | ||
680 | |||
681 | if (net->mtu > 1500) { | ||
682 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
683 | 2, 2, &tmp16); | ||
684 | tmp16 |= AX_MEDIUM_JUMBO_EN; | ||
685 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
686 | 2, 2, &tmp16); | ||
687 | } else { | ||
688 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
689 | 2, 2, &tmp16); | ||
690 | tmp16 &= ~AX_MEDIUM_JUMBO_EN; | ||
691 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
692 | 2, 2, &tmp16); | ||
693 | } | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | static int ax88179_set_mac_addr(struct net_device *net, void *p) | ||
699 | { | ||
700 | struct usbnet *dev = netdev_priv(net); | ||
701 | struct sockaddr *addr = p; | ||
702 | |||
703 | if (netif_running(net)) | ||
704 | return -EBUSY; | ||
705 | if (!is_valid_ether_addr(addr->sa_data)) | ||
706 | return -EADDRNOTAVAIL; | ||
707 | |||
708 | memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); | ||
709 | |||
710 | /* Set the MAC address */ | ||
711 | return ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, | ||
712 | ETH_ALEN, net->dev_addr); | ||
713 | } | ||
714 | |||
715 | static const struct net_device_ops ax88179_netdev_ops = { | ||
716 | .ndo_open = usbnet_open, | ||
717 | .ndo_stop = usbnet_stop, | ||
718 | .ndo_start_xmit = usbnet_start_xmit, | ||
719 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
720 | .ndo_change_mtu = ax88179_change_mtu, | ||
721 | .ndo_set_mac_address = ax88179_set_mac_addr, | ||
722 | .ndo_validate_addr = eth_validate_addr, | ||
723 | .ndo_do_ioctl = ax88179_ioctl, | ||
724 | .ndo_set_rx_mode = ax88179_set_multicast, | ||
725 | .ndo_set_features = ax88179_set_features, | ||
726 | }; | ||
727 | |||
728 | static int ax88179_check_eeprom(struct usbnet *dev) | ||
729 | { | ||
730 | u8 i, buf, eeprom[20]; | ||
731 | u16 csum, delay = HZ / 10; | ||
732 | unsigned long jtimeout; | ||
733 | |||
734 | /* Read EEPROM content */ | ||
735 | for (i = 0; i < 6; i++) { | ||
736 | buf = i; | ||
737 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, | ||
738 | 1, 1, &buf) < 0) | ||
739 | return -EINVAL; | ||
740 | |||
741 | buf = EEP_RD; | ||
742 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
743 | 1, 1, &buf) < 0) | ||
744 | return -EINVAL; | ||
745 | |||
746 | jtimeout = jiffies + delay; | ||
747 | do { | ||
748 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
749 | 1, 1, &buf); | ||
750 | |||
751 | if (time_after(jiffies, jtimeout)) | ||
752 | return -EINVAL; | ||
753 | |||
754 | } while (buf & EEP_BUSY); | ||
755 | |||
756 | __ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, | ||
757 | 2, 2, &eeprom[i * 2], 0); | ||
758 | |||
759 | if ((i == 0) && (eeprom[0] == 0xFF)) | ||
760 | return -EINVAL; | ||
761 | } | ||
762 | |||
763 | csum = eeprom[6] + eeprom[7] + eeprom[8] + eeprom[9]; | ||
764 | csum = (csum >> 8) + (csum & 0xff); | ||
765 | if ((csum + eeprom[10]) != 0xff) | ||
766 | return -EINVAL; | ||
767 | |||
768 | return 0; | ||
769 | } | ||
770 | |||
771 | static int ax88179_check_efuse(struct usbnet *dev, u16 *ledmode) | ||
772 | { | ||
773 | u8 i; | ||
774 | u8 efuse[64]; | ||
775 | u16 csum = 0; | ||
776 | |||
777 | if (ax88179_read_cmd(dev, AX_ACCESS_EFUS, 0, 64, 64, efuse) < 0) | ||
778 | return -EINVAL; | ||
779 | |||
780 | if (*efuse == 0xFF) | ||
781 | return -EINVAL; | ||
782 | |||
783 | for (i = 0; i < 64; i++) | ||
784 | csum = csum + efuse[i]; | ||
785 | |||
786 | while (csum > 255) | ||
787 | csum = (csum & 0x00FF) + ((csum >> 8) & 0x00FF); | ||
788 | |||
789 | if (csum != 0xFF) | ||
790 | return -EINVAL; | ||
791 | |||
792 | *ledmode = (efuse[51] << 8) | efuse[52]; | ||
793 | |||
794 | return 0; | ||
795 | } | ||
796 | |||
797 | static int ax88179_convert_old_led(struct usbnet *dev, u16 *ledvalue) | ||
798 | { | ||
799 | u16 led; | ||
800 | |||
801 | /* Loaded the old eFuse LED Mode */ | ||
802 | if (ax88179_read_cmd(dev, AX_ACCESS_EEPROM, 0x3C, 1, 2, &led) < 0) | ||
803 | return -EINVAL; | ||
804 | |||
805 | led >>= 8; | ||
806 | switch (led) { | ||
807 | case 0xFF: | ||
808 | led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | | ||
809 | LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | | ||
810 | LED2_LINK_100 | LED2_LINK_1000 | LED_VALID; | ||
811 | break; | ||
812 | case 0xFE: | ||
813 | led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | LED_VALID; | ||
814 | break; | ||
815 | case 0xFD: | ||
816 | led = LED0_ACTIVE | LED1_LINK_1000 | LED2_LINK_100 | | ||
817 | LED2_LINK_10 | LED_VALID; | ||
818 | break; | ||
819 | case 0xFC: | ||
820 | led = LED0_ACTIVE | LED1_ACTIVE | LED1_LINK_1000 | LED2_ACTIVE | | ||
821 | LED2_LINK_100 | LED2_LINK_10 | LED_VALID; | ||
822 | break; | ||
823 | default: | ||
824 | led = LED0_ACTIVE | LED1_LINK_10 | LED1_LINK_100 | | ||
825 | LED1_LINK_1000 | LED2_ACTIVE | LED2_LINK_10 | | ||
826 | LED2_LINK_100 | LED2_LINK_1000 | LED_VALID; | ||
827 | break; | ||
828 | } | ||
829 | |||
830 | *ledvalue = led; | ||
831 | |||
832 | return 0; | ||
833 | } | ||
834 | |||
835 | static int ax88179_led_setting(struct usbnet *dev) | ||
836 | { | ||
837 | u8 ledfd, value = 0; | ||
838 | u16 tmp, ledact, ledlink, ledvalue = 0, delay = HZ / 10; | ||
839 | unsigned long jtimeout; | ||
840 | |||
841 | /* Check AX88179 version. UA1 or UA2*/ | ||
842 | ax88179_read_cmd(dev, AX_ACCESS_MAC, GENERAL_STATUS, 1, 1, &value); | ||
843 | |||
844 | if (!(value & AX_SECLD)) { /* UA1 */ | ||
845 | value = AX_GPIO_CTRL_GPIO3EN | AX_GPIO_CTRL_GPIO2EN | | ||
846 | AX_GPIO_CTRL_GPIO1EN; | ||
847 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_GPIO_CTRL, | ||
848 | 1, 1, &value) < 0) | ||
849 | return -EINVAL; | ||
850 | } | ||
851 | |||
852 | /* Check EEPROM */ | ||
853 | if (!ax88179_check_eeprom(dev)) { | ||
854 | value = 0x42; | ||
855 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_ADDR, | ||
856 | 1, 1, &value) < 0) | ||
857 | return -EINVAL; | ||
858 | |||
859 | value = EEP_RD; | ||
860 | if (ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
861 | 1, 1, &value) < 0) | ||
862 | return -EINVAL; | ||
863 | |||
864 | jtimeout = jiffies + delay; | ||
865 | do { | ||
866 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_CMD, | ||
867 | 1, 1, &value); | ||
868 | |||
869 | if (time_after(jiffies, jtimeout)) | ||
870 | return -EINVAL; | ||
871 | |||
872 | } while (value & EEP_BUSY); | ||
873 | |||
874 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_HIGH, | ||
875 | 1, 1, &value); | ||
876 | ledvalue = (value << 8); | ||
877 | |||
878 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_SROM_DATA_LOW, | ||
879 | 1, 1, &value); | ||
880 | ledvalue |= value; | ||
881 | |||
882 | /* load internal ROM for defaule setting */ | ||
883 | if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) | ||
884 | ax88179_convert_old_led(dev, &ledvalue); | ||
885 | |||
886 | } else if (!ax88179_check_efuse(dev, &ledvalue)) { | ||
887 | if ((ledvalue == 0xFFFF) || ((ledvalue & LED_VALID) == 0)) | ||
888 | ax88179_convert_old_led(dev, &ledvalue); | ||
889 | } else { | ||
890 | ax88179_convert_old_led(dev, &ledvalue); | ||
891 | } | ||
892 | |||
893 | tmp = GMII_PHY_PGSEL_EXT; | ||
894 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
895 | GMII_PHY_PAGE_SELECT, 2, &tmp); | ||
896 | |||
897 | tmp = 0x2c; | ||
898 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
899 | GMII_PHYPAGE, 2, &tmp); | ||
900 | |||
901 | ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
902 | GMII_LED_ACT, 2, &ledact); | ||
903 | |||
904 | ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
905 | GMII_LED_LINK, 2, &ledlink); | ||
906 | |||
907 | ledact &= GMII_LED_ACTIVE_MASK; | ||
908 | ledlink &= GMII_LED_LINK_MASK; | ||
909 | |||
910 | if (ledvalue & LED0_ACTIVE) | ||
911 | ledact |= GMII_LED0_ACTIVE; | ||
912 | |||
913 | if (ledvalue & LED1_ACTIVE) | ||
914 | ledact |= GMII_LED1_ACTIVE; | ||
915 | |||
916 | if (ledvalue & LED2_ACTIVE) | ||
917 | ledact |= GMII_LED2_ACTIVE; | ||
918 | |||
919 | if (ledvalue & LED0_LINK_10) | ||
920 | ledlink |= GMII_LED0_LINK_10; | ||
921 | |||
922 | if (ledvalue & LED1_LINK_10) | ||
923 | ledlink |= GMII_LED1_LINK_10; | ||
924 | |||
925 | if (ledvalue & LED2_LINK_10) | ||
926 | ledlink |= GMII_LED2_LINK_10; | ||
927 | |||
928 | if (ledvalue & LED0_LINK_100) | ||
929 | ledlink |= GMII_LED0_LINK_100; | ||
930 | |||
931 | if (ledvalue & LED1_LINK_100) | ||
932 | ledlink |= GMII_LED1_LINK_100; | ||
933 | |||
934 | if (ledvalue & LED2_LINK_100) | ||
935 | ledlink |= GMII_LED2_LINK_100; | ||
936 | |||
937 | if (ledvalue & LED0_LINK_1000) | ||
938 | ledlink |= GMII_LED0_LINK_1000; | ||
939 | |||
940 | if (ledvalue & LED1_LINK_1000) | ||
941 | ledlink |= GMII_LED1_LINK_1000; | ||
942 | |||
943 | if (ledvalue & LED2_LINK_1000) | ||
944 | ledlink |= GMII_LED2_LINK_1000; | ||
945 | |||
946 | tmp = ledact; | ||
947 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
948 | GMII_LED_ACT, 2, &tmp); | ||
949 | |||
950 | tmp = ledlink; | ||
951 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
952 | GMII_LED_LINK, 2, &tmp); | ||
953 | |||
954 | tmp = GMII_PHY_PGSEL_PAGE0; | ||
955 | ax88179_write_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
956 | GMII_PHY_PAGE_SELECT, 2, &tmp); | ||
957 | |||
958 | /* LED full duplex setting */ | ||
959 | ledfd = 0; | ||
960 | if (ledvalue & LED0_FD) | ||
961 | ledfd |= 0x01; | ||
962 | else if ((ledvalue & LED0_USB3_MASK) == 0) | ||
963 | ledfd |= 0x02; | ||
964 | |||
965 | if (ledvalue & LED1_FD) | ||
966 | ledfd |= 0x04; | ||
967 | else if ((ledvalue & LED1_USB3_MASK) == 0) | ||
968 | ledfd |= 0x08; | ||
969 | |||
970 | if (ledvalue & LED2_FD) | ||
971 | ledfd |= 0x10; | ||
972 | else if ((ledvalue & LED2_USB3_MASK) == 0) | ||
973 | ledfd |= 0x20; | ||
974 | |||
975 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_LEDCTRL, 1, 1, &ledfd); | ||
976 | |||
977 | return 0; | ||
978 | } | ||
979 | |||
980 | static int ax88179_bind(struct usbnet *dev, struct usb_interface *intf) | ||
981 | { | ||
982 | u8 buf[5]; | ||
983 | u16 *tmp16; | ||
984 | u8 *tmp; | ||
985 | struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; | ||
986 | |||
987 | usbnet_get_endpoints(dev, intf); | ||
988 | |||
989 | tmp16 = (u16 *)buf; | ||
990 | tmp = (u8 *)buf; | ||
991 | |||
992 | memset(ax179_data, 0, sizeof(*ax179_data)); | ||
993 | |||
994 | /* Power up ethernet PHY */ | ||
995 | *tmp16 = 0; | ||
996 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
997 | *tmp16 = AX_PHYPWR_RSTCTL_IPRL; | ||
998 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
999 | msleep(200); | ||
1000 | |||
1001 | *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; | ||
1002 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); | ||
1003 | msleep(100); | ||
1004 | |||
1005 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, | ||
1006 | ETH_ALEN, dev->net->dev_addr); | ||
1007 | memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); | ||
1008 | |||
1009 | /* RX bulk configuration */ | ||
1010 | memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); | ||
1011 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); | ||
1012 | |||
1013 | dev->rx_urb_size = 1024 * 20; | ||
1014 | |||
1015 | *tmp = 0x34; | ||
1016 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); | ||
1017 | |||
1018 | *tmp = 0x52; | ||
1019 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, | ||
1020 | 1, 1, tmp); | ||
1021 | |||
1022 | dev->net->netdev_ops = &ax88179_netdev_ops; | ||
1023 | dev->net->ethtool_ops = &ax88179_ethtool_ops; | ||
1024 | dev->net->needed_headroom = 8; | ||
1025 | |||
1026 | /* Initialize MII structure */ | ||
1027 | dev->mii.dev = dev->net; | ||
1028 | dev->mii.mdio_read = ax88179_mdio_read; | ||
1029 | dev->mii.mdio_write = ax88179_mdio_write; | ||
1030 | dev->mii.phy_id_mask = 0xff; | ||
1031 | dev->mii.reg_num_mask = 0xff; | ||
1032 | dev->mii.phy_id = 0x03; | ||
1033 | dev->mii.supports_gmii = 1; | ||
1034 | |||
1035 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1036 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1037 | |||
1038 | dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1039 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1040 | |||
1041 | /* Enable checksum offload */ | ||
1042 | *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | | ||
1043 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; | ||
1044 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); | ||
1045 | |||
1046 | *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | | ||
1047 | AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; | ||
1048 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); | ||
1049 | |||
1050 | /* Configure RX control register => start operation */ | ||
1051 | *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | | ||
1052 | AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; | ||
1053 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); | ||
1054 | |||
1055 | *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | | ||
1056 | AX_MONITOR_MODE_RWMP; | ||
1057 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); | ||
1058 | |||
1059 | /* Configure default medium type => giga */ | ||
1060 | *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | | ||
1061 | AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE | | ||
1062 | AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; | ||
1063 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1064 | 2, 2, tmp16); | ||
1065 | |||
1066 | ax88179_led_setting(dev); | ||
1067 | |||
1068 | /* Restart autoneg */ | ||
1069 | mii_nway_restart(&dev->mii); | ||
1070 | |||
1071 | netif_carrier_off(dev->net); | ||
1072 | |||
1073 | return 0; | ||
1074 | } | ||
1075 | |||
1076 | static void ax88179_unbind(struct usbnet *dev, struct usb_interface *intf) | ||
1077 | { | ||
1078 | u16 tmp16; | ||
1079 | |||
1080 | /* Configure RX control register => stop operation */ | ||
1081 | tmp16 = AX_RX_CTL_STOP; | ||
1082 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &tmp16); | ||
1083 | |||
1084 | tmp16 = 0; | ||
1085 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, &tmp16); | ||
1086 | |||
1087 | /* Power down ethernet PHY */ | ||
1088 | tmp16 = 0; | ||
1089 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, &tmp16); | ||
1090 | } | ||
1091 | |||
1092 | static void | ||
1093 | ax88179_rx_checksum(struct sk_buff *skb, u32 *pkt_hdr) | ||
1094 | { | ||
1095 | skb->ip_summed = CHECKSUM_NONE; | ||
1096 | |||
1097 | /* checksum error bit is set */ | ||
1098 | if ((*pkt_hdr & AX_RXHDR_L3CSUM_ERR) || | ||
1099 | (*pkt_hdr & AX_RXHDR_L4CSUM_ERR)) | ||
1100 | return; | ||
1101 | |||
1102 | /* It must be a TCP or UDP packet with a valid checksum */ | ||
1103 | if (((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_TCP) || | ||
1104 | ((*pkt_hdr & AX_RXHDR_L4_TYPE_MASK) == AX_RXHDR_L4_TYPE_UDP)) | ||
1105 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
1106 | } | ||
1107 | |||
1108 | static int ax88179_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
1109 | { | ||
1110 | struct sk_buff *ax_skb; | ||
1111 | int pkt_cnt; | ||
1112 | u32 rx_hdr; | ||
1113 | u16 hdr_off; | ||
1114 | u32 *pkt_hdr; | ||
1115 | |||
1116 | skb_trim(skb, skb->len - 4); | ||
1117 | memcpy(&rx_hdr, skb_tail_pointer(skb), 4); | ||
1118 | le32_to_cpus(&rx_hdr); | ||
1119 | |||
1120 | pkt_cnt = (u16)rx_hdr; | ||
1121 | hdr_off = (u16)(rx_hdr >> 16); | ||
1122 | pkt_hdr = (u32 *)(skb->data + hdr_off); | ||
1123 | |||
1124 | while (pkt_cnt--) { | ||
1125 | u16 pkt_len; | ||
1126 | |||
1127 | le32_to_cpus(pkt_hdr); | ||
1128 | pkt_len = (*pkt_hdr >> 16) & 0x1fff; | ||
1129 | |||
1130 | /* Check CRC or runt packet */ | ||
1131 | if ((*pkt_hdr & AX_RXHDR_CRC_ERR) || | ||
1132 | (*pkt_hdr & AX_RXHDR_DROP_ERR)) { | ||
1133 | skb_pull(skb, (pkt_len + 7) & 0xFFF8); | ||
1134 | pkt_hdr++; | ||
1135 | continue; | ||
1136 | } | ||
1137 | |||
1138 | if (pkt_cnt == 0) { | ||
1139 | /* Skip IP alignment psudo header */ | ||
1140 | skb_pull(skb, 2); | ||
1141 | skb->len = pkt_len; | ||
1142 | skb_set_tail_pointer(skb, pkt_len); | ||
1143 | skb->truesize = pkt_len + sizeof(struct sk_buff); | ||
1144 | ax88179_rx_checksum(skb, pkt_hdr); | ||
1145 | return 1; | ||
1146 | } | ||
1147 | |||
1148 | ax_skb = skb_clone(skb, GFP_ATOMIC); | ||
1149 | if (ax_skb) { | ||
1150 | ax_skb->len = pkt_len; | ||
1151 | ax_skb->data = skb->data + 2; | ||
1152 | skb_set_tail_pointer(ax_skb, pkt_len); | ||
1153 | ax_skb->truesize = pkt_len + sizeof(struct sk_buff); | ||
1154 | ax88179_rx_checksum(ax_skb, pkt_hdr); | ||
1155 | usbnet_skb_return(dev, ax_skb); | ||
1156 | } else { | ||
1157 | return 0; | ||
1158 | } | ||
1159 | |||
1160 | skb_pull(skb, (pkt_len + 7) & 0xFFF8); | ||
1161 | pkt_hdr++; | ||
1162 | } | ||
1163 | return 1; | ||
1164 | } | ||
1165 | |||
1166 | static struct sk_buff * | ||
1167 | ax88179_tx_fixup(struct usbnet *dev, struct sk_buff *skb, gfp_t flags) | ||
1168 | { | ||
1169 | u32 tx_hdr1, tx_hdr2; | ||
1170 | int frame_size = dev->maxpacket; | ||
1171 | int mss = skb_shinfo(skb)->gso_size; | ||
1172 | int headroom; | ||
1173 | int tailroom; | ||
1174 | |||
1175 | tx_hdr1 = skb->len; | ||
1176 | tx_hdr2 = mss; | ||
1177 | if (((skb->len + 8) % frame_size) == 0) | ||
1178 | tx_hdr2 |= 0x80008000; /* Enable padding */ | ||
1179 | |||
1180 | skb_linearize(skb); | ||
1181 | headroom = skb_headroom(skb); | ||
1182 | tailroom = skb_tailroom(skb); | ||
1183 | |||
1184 | if (!skb_header_cloned(skb) && | ||
1185 | !skb_cloned(skb) && | ||
1186 | (headroom + tailroom) >= 8) { | ||
1187 | if (headroom < 8) { | ||
1188 | skb->data = memmove(skb->head + 8, skb->data, skb->len); | ||
1189 | skb_set_tail_pointer(skb, skb->len); | ||
1190 | } | ||
1191 | } else { | ||
1192 | struct sk_buff *skb2; | ||
1193 | |||
1194 | skb2 = skb_copy_expand(skb, 8, 0, flags); | ||
1195 | dev_kfree_skb_any(skb); | ||
1196 | skb = skb2; | ||
1197 | if (!skb) | ||
1198 | return NULL; | ||
1199 | } | ||
1200 | |||
1201 | skb_push(skb, 4); | ||
1202 | cpu_to_le32s(&tx_hdr2); | ||
1203 | skb_copy_to_linear_data(skb, &tx_hdr2, 4); | ||
1204 | |||
1205 | skb_push(skb, 4); | ||
1206 | cpu_to_le32s(&tx_hdr1); | ||
1207 | skb_copy_to_linear_data(skb, &tx_hdr1, 4); | ||
1208 | |||
1209 | return skb; | ||
1210 | } | ||
1211 | |||
1212 | static int ax88179_link_reset(struct usbnet *dev) | ||
1213 | { | ||
1214 | struct ax88179_data *ax179_data = (struct ax88179_data *)dev->data; | ||
1215 | u8 tmp[5], link_sts; | ||
1216 | u16 mode, tmp16, delay = HZ / 10; | ||
1217 | u32 tmp32 = 0x40000000; | ||
1218 | unsigned long jtimeout; | ||
1219 | |||
1220 | jtimeout = jiffies + delay; | ||
1221 | while (tmp32 & 0x40000000) { | ||
1222 | mode = 0; | ||
1223 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, &mode); | ||
1224 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, | ||
1225 | &ax179_data->rxctl); | ||
1226 | |||
1227 | /*link up, check the usb device control TX FIFO full or empty*/ | ||
1228 | ax88179_read_cmd(dev, 0x81, 0x8c, 0, 4, &tmp32); | ||
1229 | |||
1230 | if (time_after(jiffies, jtimeout)) | ||
1231 | return 0; | ||
1232 | } | ||
1233 | |||
1234 | mode = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | | ||
1235 | AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE; | ||
1236 | |||
1237 | ax88179_read_cmd(dev, AX_ACCESS_MAC, PHYSICAL_LINK_STATUS, | ||
1238 | 1, 1, &link_sts); | ||
1239 | |||
1240 | ax88179_read_cmd(dev, AX_ACCESS_PHY, AX88179_PHY_ID, | ||
1241 | GMII_PHY_PHYSR, 2, &tmp16); | ||
1242 | |||
1243 | if (!(tmp16 & GMII_PHY_PHYSR_LINK)) { | ||
1244 | return 0; | ||
1245 | } else if (GMII_PHY_PHYSR_GIGA == (tmp16 & GMII_PHY_PHYSR_SMASK)) { | ||
1246 | mode |= AX_MEDIUM_GIGAMODE | AX_MEDIUM_EN_125MHZ; | ||
1247 | if (dev->net->mtu > 1500) | ||
1248 | mode |= AX_MEDIUM_JUMBO_EN; | ||
1249 | |||
1250 | if (link_sts & AX_USB_SS) | ||
1251 | memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); | ||
1252 | else if (link_sts & AX_USB_HS) | ||
1253 | memcpy(tmp, &AX88179_BULKIN_SIZE[1], 5); | ||
1254 | else | ||
1255 | memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); | ||
1256 | } else if (GMII_PHY_PHYSR_100 == (tmp16 & GMII_PHY_PHYSR_SMASK)) { | ||
1257 | mode |= AX_MEDIUM_PS; | ||
1258 | |||
1259 | if (link_sts & (AX_USB_SS | AX_USB_HS)) | ||
1260 | memcpy(tmp, &AX88179_BULKIN_SIZE[2], 5); | ||
1261 | else | ||
1262 | memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); | ||
1263 | } else { | ||
1264 | memcpy(tmp, &AX88179_BULKIN_SIZE[3], 5); | ||
1265 | } | ||
1266 | |||
1267 | /* RX bulk configuration */ | ||
1268 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); | ||
1269 | |||
1270 | dev->rx_urb_size = (1024 * (tmp[3] + 2)); | ||
1271 | |||
1272 | if (tmp16 & GMII_PHY_PHYSR_FULL) | ||
1273 | mode |= AX_MEDIUM_FULL_DUPLEX; | ||
1274 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1275 | 2, 2, &mode); | ||
1276 | |||
1277 | netif_carrier_on(dev->net); | ||
1278 | |||
1279 | return 0; | ||
1280 | } | ||
1281 | |||
1282 | static int ax88179_reset(struct usbnet *dev) | ||
1283 | { | ||
1284 | u8 buf[5]; | ||
1285 | u16 *tmp16; | ||
1286 | u8 *tmp; | ||
1287 | |||
1288 | tmp16 = (u16 *)buf; | ||
1289 | tmp = (u8 *)buf; | ||
1290 | |||
1291 | /* Power up ethernet PHY */ | ||
1292 | *tmp16 = 0; | ||
1293 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
1294 | |||
1295 | *tmp16 = AX_PHYPWR_RSTCTL_IPRL; | ||
1296 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16); | ||
1297 | msleep(200); | ||
1298 | |||
1299 | *tmp = AX_CLK_SELECT_ACS | AX_CLK_SELECT_BCS; | ||
1300 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_CLK_SELECT, 1, 1, tmp); | ||
1301 | msleep(100); | ||
1302 | |||
1303 | /* Ethernet PHY Auto Detach*/ | ||
1304 | ax88179_auto_detach(dev, 0); | ||
1305 | |||
1306 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, ETH_ALEN, ETH_ALEN, | ||
1307 | dev->net->dev_addr); | ||
1308 | memcpy(dev->net->perm_addr, dev->net->dev_addr, ETH_ALEN); | ||
1309 | |||
1310 | /* RX bulk configuration */ | ||
1311 | memcpy(tmp, &AX88179_BULKIN_SIZE[0], 5); | ||
1312 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_BULKIN_QCTRL, 5, 5, tmp); | ||
1313 | |||
1314 | dev->rx_urb_size = 1024 * 20; | ||
1315 | |||
1316 | *tmp = 0x34; | ||
1317 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_LOW, 1, 1, tmp); | ||
1318 | |||
1319 | *tmp = 0x52; | ||
1320 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_PAUSE_WATERLVL_HIGH, | ||
1321 | 1, 1, tmp); | ||
1322 | |||
1323 | dev->net->features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1324 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1325 | |||
1326 | dev->net->hw_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | | ||
1327 | NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_TSO; | ||
1328 | |||
1329 | /* Enable checksum offload */ | ||
1330 | *tmp = AX_RXCOE_IP | AX_RXCOE_TCP | AX_RXCOE_UDP | | ||
1331 | AX_RXCOE_TCPV6 | AX_RXCOE_UDPV6; | ||
1332 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RXCOE_CTL, 1, 1, tmp); | ||
1333 | |||
1334 | *tmp = AX_TXCOE_IP | AX_TXCOE_TCP | AX_TXCOE_UDP | | ||
1335 | AX_TXCOE_TCPV6 | AX_TXCOE_UDPV6; | ||
1336 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_TXCOE_CTL, 1, 1, tmp); | ||
1337 | |||
1338 | /* Configure RX control register => start operation */ | ||
1339 | *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START | | ||
1340 | AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB; | ||
1341 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16); | ||
1342 | |||
1343 | *tmp = AX_MONITOR_MODE_PMETYPE | AX_MONITOR_MODE_PMEPOL | | ||
1344 | AX_MONITOR_MODE_RWMP; | ||
1345 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MONITOR_MOD, 1, 1, tmp); | ||
1346 | |||
1347 | /* Configure default medium type => giga */ | ||
1348 | *tmp16 = AX_MEDIUM_RECEIVE_EN | AX_MEDIUM_TXFLOW_CTRLEN | | ||
1349 | AX_MEDIUM_RXFLOW_CTRLEN | AX_MEDIUM_ALWAYS_ONE | | ||
1350 | AX_MEDIUM_FULL_DUPLEX | AX_MEDIUM_GIGAMODE; | ||
1351 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1352 | 2, 2, tmp16); | ||
1353 | |||
1354 | ax88179_led_setting(dev); | ||
1355 | |||
1356 | /* Restart autoneg */ | ||
1357 | mii_nway_restart(&dev->mii); | ||
1358 | |||
1359 | netif_carrier_off(dev->net); | ||
1360 | |||
1361 | return 0; | ||
1362 | } | ||
1363 | |||
1364 | static int ax88179_stop(struct usbnet *dev) | ||
1365 | { | ||
1366 | u16 tmp16; | ||
1367 | |||
1368 | ax88179_read_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1369 | 2, 2, &tmp16); | ||
1370 | tmp16 &= ~AX_MEDIUM_RECEIVE_EN; | ||
1371 | ax88179_write_cmd(dev, AX_ACCESS_MAC, AX_MEDIUM_STATUS_MODE, | ||
1372 | 2, 2, &tmp16); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | static const struct driver_info ax88179_info = { | ||
1378 | .description = "ASIX AX88179 USB 3.0 Gigibit Ethernet", | ||
1379 | .bind = ax88179_bind, | ||
1380 | .unbind = ax88179_unbind, | ||
1381 | .status = ax88179_status, | ||
1382 | .link_reset = ax88179_link_reset, | ||
1383 | .reset = ax88179_reset, | ||
1384 | .stop = ax88179_stop, | ||
1385 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
1386 | .rx_fixup = ax88179_rx_fixup, | ||
1387 | .tx_fixup = ax88179_tx_fixup, | ||
1388 | }; | ||
1389 | |||
1390 | static const struct driver_info ax88178a_info = { | ||
1391 | .description = "ASIX AX88178A USB 2.0 Gigibit Ethernet", | ||
1392 | .bind = ax88179_bind, | ||
1393 | .unbind = ax88179_unbind, | ||
1394 | .status = ax88179_status, | ||
1395 | .link_reset = ax88179_link_reset, | ||
1396 | .reset = ax88179_reset, | ||
1397 | .stop = ax88179_stop, | ||
1398 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
1399 | .rx_fixup = ax88179_rx_fixup, | ||
1400 | .tx_fixup = ax88179_tx_fixup, | ||
1401 | }; | ||
1402 | |||
1403 | static const struct driver_info sitecom_info = { | ||
1404 | .description = "Sitecom USB 3.0 to Gigabit Adapter", | ||
1405 | .bind = ax88179_bind, | ||
1406 | .unbind = ax88179_unbind, | ||
1407 | .status = ax88179_status, | ||
1408 | .link_reset = ax88179_link_reset, | ||
1409 | .reset = ax88179_reset, | ||
1410 | .stop = ax88179_stop, | ||
1411 | .flags = FLAG_ETHER | FLAG_FRAMING_AX, | ||
1412 | .rx_fixup = ax88179_rx_fixup, | ||
1413 | .tx_fixup = ax88179_tx_fixup, | ||
1414 | }; | ||
1415 | |||
1416 | static const struct usb_device_id products[] = { | ||
1417 | { | ||
1418 | /* ASIX AX88179 10/100/1000 */ | ||
1419 | USB_DEVICE(0x0b95, 0x1790), | ||
1420 | .driver_info = (unsigned long)&ax88179_info, | ||
1421 | }, { | ||
1422 | /* ASIX AX88178A 10/100/1000 */ | ||
1423 | USB_DEVICE(0x0b95, 0x178a), | ||
1424 | .driver_info = (unsigned long)&ax88178a_info, | ||
1425 | }, { | ||
1426 | /* Sitecom USB 3.0 to Gigabit Adapter */ | ||
1427 | USB_DEVICE(0x0df6, 0x0072), | ||
1428 | .driver_info = (unsigned long) &sitecom_info, | ||
1429 | }, | ||
1430 | { }, | ||
1431 | }; | ||
1432 | MODULE_DEVICE_TABLE(usb, products); | ||
1433 | |||
1434 | static struct usb_driver ax88179_178a_driver = { | ||
1435 | .name = "ax88179_178a", | ||
1436 | .id_table = products, | ||
1437 | .probe = usbnet_probe, | ||
1438 | .suspend = ax88179_suspend, | ||
1439 | .resume = ax88179_resume, | ||
1440 | .disconnect = usbnet_disconnect, | ||
1441 | .supports_autosuspend = 1, | ||
1442 | .disable_hub_initiated_lpm = 1, | ||
1443 | }; | ||
1444 | |||
1445 | module_usb_driver(ax88179_178a_driver); | ||
1446 | |||
1447 | MODULE_DESCRIPTION("ASIX AX88179/178A based USB 3.0/2.0 Gigabit Ethernet Devices"); | ||
1448 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 248d2dc765a5..16c842997291 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c | |||
@@ -68,18 +68,9 @@ static int cdc_mbim_bind(struct usbnet *dev, struct usb_interface *intf) | |||
68 | struct cdc_ncm_ctx *ctx; | 68 | struct cdc_ncm_ctx *ctx; |
69 | struct usb_driver *subdriver = ERR_PTR(-ENODEV); | 69 | struct usb_driver *subdriver = ERR_PTR(-ENODEV); |
70 | int ret = -ENODEV; | 70 | int ret = -ENODEV; |
71 | u8 data_altsetting = CDC_NCM_DATA_ALTSETTING_NCM; | 71 | u8 data_altsetting = cdc_ncm_select_altsetting(dev, intf); |
72 | struct cdc_mbim_state *info = (void *)&dev->data; | 72 | struct cdc_mbim_state *info = (void *)&dev->data; |
73 | 73 | ||
74 | /* see if interface supports MBIM alternate setting */ | ||
75 | if (intf->num_altsetting == 2) { | ||
76 | if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) | ||
77 | usb_set_interface(dev->udev, | ||
78 | intf->cur_altsetting->desc.bInterfaceNumber, | ||
79 | CDC_NCM_COMM_ALTSETTING_MBIM); | ||
80 | data_altsetting = CDC_NCM_DATA_ALTSETTING_MBIM; | ||
81 | } | ||
82 | |||
83 | /* Probably NCM, defer for cdc_ncm_bind */ | 74 | /* Probably NCM, defer for cdc_ncm_bind */ |
84 | if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) | 75 | if (!cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) |
85 | goto err; | 76 | goto err; |
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 4a8c25a22294..4709fa3497cf 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
@@ -55,6 +55,14 @@ | |||
55 | 55 | ||
56 | #define DRIVER_VERSION "14-Mar-2012" | 56 | #define DRIVER_VERSION "14-Mar-2012" |
57 | 57 | ||
58 | #if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) | ||
59 | static bool prefer_mbim = true; | ||
60 | #else | ||
61 | static bool prefer_mbim; | ||
62 | #endif | ||
63 | module_param(prefer_mbim, bool, S_IRUGO | S_IWUSR); | ||
64 | MODULE_PARM_DESC(prefer_mbim, "Prefer MBIM setting on dual NCM/MBIM functions"); | ||
65 | |||
58 | static void cdc_ncm_txpath_bh(unsigned long param); | 66 | static void cdc_ncm_txpath_bh(unsigned long param); |
59 | static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx); | 67 | static void cdc_ncm_tx_timeout_start(struct cdc_ncm_ctx *ctx); |
60 | static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); | 68 | static enum hrtimer_restart cdc_ncm_tx_timer_cb(struct hrtimer *hr_timer); |
@@ -550,9 +558,12 @@ void cdc_ncm_unbind(struct usbnet *dev, struct usb_interface *intf) | |||
550 | } | 558 | } |
551 | EXPORT_SYMBOL_GPL(cdc_ncm_unbind); | 559 | EXPORT_SYMBOL_GPL(cdc_ncm_unbind); |
552 | 560 | ||
553 | static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) | 561 | /* Select the MBIM altsetting iff it is preferred and available, |
562 | * returning the number of the corresponding data interface altsetting | ||
563 | */ | ||
564 | u8 cdc_ncm_select_altsetting(struct usbnet *dev, struct usb_interface *intf) | ||
554 | { | 565 | { |
555 | int ret; | 566 | struct usb_host_interface *alt; |
556 | 567 | ||
557 | /* The MBIM spec defines a NCM compatible default altsetting, | 568 | /* The MBIM spec defines a NCM compatible default altsetting, |
558 | * which we may have matched: | 569 | * which we may have matched: |
@@ -568,23 +579,27 @@ static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) | |||
568 | * endpoint descriptors, shall be constructed according to | 579 | * endpoint descriptors, shall be constructed according to |
569 | * the rules given in section 6 (USB Device Model) of this | 580 | * the rules given in section 6 (USB Device Model) of this |
570 | * specification." | 581 | * specification." |
571 | * | ||
572 | * Do not bind to such interfaces, allowing cdc_mbim to handle | ||
573 | * them | ||
574 | */ | 582 | */ |
575 | #if IS_ENABLED(CONFIG_USB_NET_CDC_MBIM) | 583 | if (prefer_mbim && intf->num_altsetting == 2) { |
576 | if ((intf->num_altsetting == 2) && | 584 | alt = usb_altnum_to_altsetting(intf, CDC_NCM_COMM_ALTSETTING_MBIM); |
577 | !usb_set_interface(dev->udev, | 585 | if (alt && cdc_ncm_comm_intf_is_mbim(alt) && |
578 | intf->cur_altsetting->desc.bInterfaceNumber, | 586 | !usb_set_interface(dev->udev, |
579 | CDC_NCM_COMM_ALTSETTING_MBIM)) { | 587 | intf->cur_altsetting->desc.bInterfaceNumber, |
580 | if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) | 588 | CDC_NCM_COMM_ALTSETTING_MBIM)) |
581 | return -ENODEV; | 589 | return CDC_NCM_DATA_ALTSETTING_MBIM; |
582 | else | ||
583 | usb_set_interface(dev->udev, | ||
584 | intf->cur_altsetting->desc.bInterfaceNumber, | ||
585 | CDC_NCM_COMM_ALTSETTING_NCM); | ||
586 | } | 590 | } |
587 | #endif | 591 | return CDC_NCM_DATA_ALTSETTING_NCM; |
592 | } | ||
593 | EXPORT_SYMBOL_GPL(cdc_ncm_select_altsetting); | ||
594 | |||
595 | static int cdc_ncm_bind(struct usbnet *dev, struct usb_interface *intf) | ||
596 | { | ||
597 | int ret; | ||
598 | |||
599 | /* MBIM backwards compatible function? */ | ||
600 | cdc_ncm_select_altsetting(dev, intf); | ||
601 | if (cdc_ncm_comm_intf_is_mbim(intf->cur_altsetting)) | ||
602 | return -ENODEV; | ||
588 | 603 | ||
589 | /* NCM data altsetting is always 1 */ | 604 | /* NCM data altsetting is always 1 */ |
590 | ret = cdc_ncm_bind_common(dev, intf, 1); | 605 | ret = cdc_ncm_bind_common(dev, intf, 1); |
@@ -1213,6 +1228,14 @@ static const struct usb_device_id cdc_devs[] = { | |||
1213 | .driver_info = (unsigned long) &wwan_info, | 1228 | .driver_info = (unsigned long) &wwan_info, |
1214 | }, | 1229 | }, |
1215 | 1230 | ||
1231 | /* tag Huawei devices as wwan */ | ||
1232 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, | ||
1233 | USB_CLASS_COMM, | ||
1234 | USB_CDC_SUBCLASS_NCM, | ||
1235 | USB_CDC_PROTO_NONE), | ||
1236 | .driver_info = (unsigned long)&wwan_info, | ||
1237 | }, | ||
1238 | |||
1216 | /* Huawei NCM devices disguised as vendor specific */ | 1239 | /* Huawei NCM devices disguised as vendor specific */ |
1217 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), | 1240 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x16), |
1218 | .driver_info = (unsigned long)&wwan_info, | 1241 | .driver_info = (unsigned long)&wwan_info, |
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index efb5c7c33a28..968d5d50751d 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
@@ -139,16 +139,9 @@ static int qmi_wwan_bind(struct usbnet *dev, struct usb_interface *intf) | |||
139 | 139 | ||
140 | BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state))); | 140 | BUILD_BUG_ON((sizeof(((struct usbnet *)0)->data) < sizeof(struct qmi_wwan_state))); |
141 | 141 | ||
142 | /* control and data is shared? */ | 142 | /* set up initial state */ |
143 | if (intf->cur_altsetting->desc.bNumEndpoints == 3) { | 143 | info->control = intf; |
144 | info->control = intf; | 144 | info->data = intf; |
145 | info->data = intf; | ||
146 | goto shared; | ||
147 | } | ||
148 | |||
149 | /* else require a single interrupt status endpoint on control intf */ | ||
150 | if (intf->cur_altsetting->desc.bNumEndpoints != 1) | ||
151 | goto err; | ||
152 | 145 | ||
153 | /* and a number of CDC descriptors */ | 146 | /* and a number of CDC descriptors */ |
154 | while (len > 3) { | 147 | while (len > 3) { |
@@ -207,25 +200,14 @@ next_desc: | |||
207 | buf += h->bLength; | 200 | buf += h->bLength; |
208 | } | 201 | } |
209 | 202 | ||
210 | /* did we find all the required ones? */ | 203 | /* Use separate control and data interfaces if we found a CDC Union */ |
211 | if (!(found & (1 << USB_CDC_HEADER_TYPE)) || | 204 | if (cdc_union) { |
212 | !(found & (1 << USB_CDC_UNION_TYPE))) { | 205 | info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0); |
213 | dev_err(&intf->dev, "CDC functional descriptors missing\n"); | 206 | if (desc->bInterfaceNumber != cdc_union->bMasterInterface0 || !info->data) { |
214 | goto err; | 207 | dev_err(&intf->dev, "bogus CDC Union: master=%u, slave=%u\n", |
215 | } | 208 | cdc_union->bMasterInterface0, cdc_union->bSlaveInterface0); |
216 | 209 | goto err; | |
217 | /* verify CDC Union */ | 210 | } |
218 | if (desc->bInterfaceNumber != cdc_union->bMasterInterface0) { | ||
219 | dev_err(&intf->dev, "bogus CDC Union: master=%u\n", cdc_union->bMasterInterface0); | ||
220 | goto err; | ||
221 | } | ||
222 | |||
223 | /* need to save these for unbind */ | ||
224 | info->control = intf; | ||
225 | info->data = usb_ifnum_to_if(dev->udev, cdc_union->bSlaveInterface0); | ||
226 | if (!info->data) { | ||
227 | dev_err(&intf->dev, "bogus CDC Union: slave=%u\n", cdc_union->bSlaveInterface0); | ||
228 | goto err; | ||
229 | } | 211 | } |
230 | 212 | ||
231 | /* errors aren't fatal - we can live with the dynamic address */ | 213 | /* errors aren't fatal - we can live with the dynamic address */ |
@@ -235,11 +217,12 @@ next_desc: | |||
235 | } | 217 | } |
236 | 218 | ||
237 | /* claim data interface and set it up */ | 219 | /* claim data interface and set it up */ |
238 | status = usb_driver_claim_interface(driver, info->data, dev); | 220 | if (info->control != info->data) { |
239 | if (status < 0) | 221 | status = usb_driver_claim_interface(driver, info->data, dev); |
240 | goto err; | 222 | if (status < 0) |
223 | goto err; | ||
224 | } | ||
241 | 225 | ||
242 | shared: | ||
243 | status = qmi_wwan_register_subdriver(dev); | 226 | status = qmi_wwan_register_subdriver(dev); |
244 | if (status < 0 && info->control != info->data) { | 227 | if (status < 0 && info->control != info->data) { |
245 | usb_set_intfdata(info->data, NULL); | 228 | usb_set_intfdata(info->data, NULL); |
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index 4aad350e4dae..eae7a03d4f9b 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c | |||
@@ -2958,6 +2958,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, | |||
2958 | 2958 | ||
2959 | adapter->num_rx_queues = num_rx_queues; | 2959 | adapter->num_rx_queues = num_rx_queues; |
2960 | adapter->num_tx_queues = num_tx_queues; | 2960 | adapter->num_tx_queues = num_tx_queues; |
2961 | adapter->rx_buf_per_pkt = 1; | ||
2961 | 2962 | ||
2962 | size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues; | 2963 | size = sizeof(struct Vmxnet3_TxQueueDesc) * adapter->num_tx_queues; |
2963 | size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues; | 2964 | size += sizeof(struct Vmxnet3_RxQueueDesc) * adapter->num_rx_queues; |
diff --git a/drivers/net/vmxnet3/vmxnet3_ethtool.c b/drivers/net/vmxnet3/vmxnet3_ethtool.c index a0feb17a0238..63a124340cbe 100644 --- a/drivers/net/vmxnet3/vmxnet3_ethtool.c +++ b/drivers/net/vmxnet3/vmxnet3_ethtool.c | |||
@@ -472,6 +472,12 @@ vmxnet3_set_ringparam(struct net_device *netdev, | |||
472 | VMXNET3_RX_RING_MAX_SIZE) | 472 | VMXNET3_RX_RING_MAX_SIZE) |
473 | return -EINVAL; | 473 | return -EINVAL; |
474 | 474 | ||
475 | /* if adapter not yet initialized, do nothing */ | ||
476 | if (adapter->rx_buf_per_pkt == 0) { | ||
477 | netdev_err(netdev, "adapter not completely initialized, " | ||
478 | "ring size cannot be changed yet\n"); | ||
479 | return -EOPNOTSUPP; | ||
480 | } | ||
475 | 481 | ||
476 | /* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */ | 482 | /* round it up to a multiple of VMXNET3_RING_SIZE_ALIGN */ |
477 | new_tx_ring_size = (param->tx_pending + VMXNET3_RING_SIZE_MASK) & | 483 | new_tx_ring_size = (param->tx_pending + VMXNET3_RING_SIZE_MASK) & |
diff --git a/drivers/net/vmxnet3/vmxnet3_int.h b/drivers/net/vmxnet3/vmxnet3_int.h index 3198384689d9..35418146fa17 100644 --- a/drivers/net/vmxnet3/vmxnet3_int.h +++ b/drivers/net/vmxnet3/vmxnet3_int.h | |||
@@ -70,10 +70,10 @@ | |||
70 | /* | 70 | /* |
71 | * Version numbers | 71 | * Version numbers |
72 | */ | 72 | */ |
73 | #define VMXNET3_DRIVER_VERSION_STRING "1.1.29.0-k" | 73 | #define VMXNET3_DRIVER_VERSION_STRING "1.1.30.0-k" |
74 | 74 | ||
75 | /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ | 75 | /* a 32-bit int, each byte encode a verion number in VMXNET3_DRIVER_VERSION */ |
76 | #define VMXNET3_DRIVER_VERSION_NUM 0x01011D00 | 76 | #define VMXNET3_DRIVER_VERSION_NUM 0x01011E00 |
77 | 77 | ||
78 | #if defined(CONFIG_PCI_MSI) | 78 | #if defined(CONFIG_PCI_MSI) |
79 | /* RSS only makes sense if MSI-X is supported. */ | 79 | /* RSS only makes sense if MSI-X is supported. */ |
diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index f10e58ac9c1b..7cee7a3068ec 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c | |||
@@ -961,6 +961,8 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
961 | iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); | 961 | iph->ttl = ttl ? : ip4_dst_hoplimit(&rt->dst); |
962 | tunnel_ip_select_ident(skb, old_iph, &rt->dst); | 962 | tunnel_ip_select_ident(skb, old_iph, &rt->dst); |
963 | 963 | ||
964 | nf_reset(skb); | ||
965 | |||
964 | vxlan_set_owner(dev, skb); | 966 | vxlan_set_owner(dev, skb); |
965 | 967 | ||
966 | /* See iptunnel_xmit() */ | 968 | /* See iptunnel_xmit() */ |
@@ -1504,6 +1506,14 @@ static __net_init int vxlan_init_net(struct net *net) | |||
1504 | static __net_exit void vxlan_exit_net(struct net *net) | 1506 | static __net_exit void vxlan_exit_net(struct net *net) |
1505 | { | 1507 | { |
1506 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); | 1508 | struct vxlan_net *vn = net_generic(net, vxlan_net_id); |
1509 | struct vxlan_dev *vxlan; | ||
1510 | unsigned h; | ||
1511 | |||
1512 | rtnl_lock(); | ||
1513 | for (h = 0; h < VNI_HASH_SIZE; ++h) | ||
1514 | hlist_for_each_entry(vxlan, &vn->vni_list[h], hlist) | ||
1515 | dev_close(vxlan->dev); | ||
1516 | rtnl_unlock(); | ||
1507 | 1517 | ||
1508 | if (vn->sock) { | 1518 | if (vn->sock) { |
1509 | sk_release_kernel(vn->sock->sk); | 1519 | sk_release_kernel(vn->sock->sk); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 4cc13940c895..f76c3ca07a45 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -1023,6 +1023,7 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
1023 | AR_PHY_AGC_CONTROL_FLTR_CAL | | 1023 | AR_PHY_AGC_CONTROL_FLTR_CAL | |
1024 | AR_PHY_AGC_CONTROL_PKDET_CAL; | 1024 | AR_PHY_AGC_CONTROL_PKDET_CAL; |
1025 | 1025 | ||
1026 | /* Use chip chainmask only for calibration */ | ||
1026 | ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); | 1027 | ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); |
1027 | 1028 | ||
1028 | if (rtt) { | 1029 | if (rtt) { |
@@ -1150,6 +1151,9 @@ skip_tx_iqcal: | |||
1150 | ar9003_hw_rtt_disable(ah); | 1151 | ar9003_hw_rtt_disable(ah); |
1151 | } | 1152 | } |
1152 | 1153 | ||
1154 | /* Revert chainmask to runtime parameters */ | ||
1155 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); | ||
1156 | |||
1153 | /* Initialize list pointers */ | 1157 | /* Initialize list pointers */ |
1154 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; | 1158 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
1155 | 1159 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index 5f845beeb18b..050ca4a4850d 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -27,7 +27,7 @@ | |||
27 | #define WME_MAX_BA WME_BA_BMP_SIZE | 27 | #define WME_MAX_BA WME_BA_BMP_SIZE |
28 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) | 28 | #define ATH_TID_MAX_BUFS (2 * WME_MAX_BA) |
29 | 29 | ||
30 | #define ATH_RSSI_DUMMY_MARKER 0x127 | 30 | #define ATH_RSSI_DUMMY_MARKER 127 |
31 | #define ATH_RSSI_LPF_LEN 10 | 31 | #define ATH_RSSI_LPF_LEN 10 |
32 | #define RSSI_LPF_THRESHOLD -20 | 32 | #define RSSI_LPF_THRESHOLD -20 |
33 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) | 33 | #define ATH_RSSI_EP_MULTIPLIER (1<<7) |
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 96bfb18078fa..d3b099d7898b 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/firmware.h> | 22 | #include <linux/firmware.h> |
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <linux/netdevice.h> | 24 | #include <linux/netdevice.h> |
25 | #include <linux/etherdevice.h> | ||
25 | #include <linux/leds.h> | 26 | #include <linux/leds.h> |
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <net/mac80211.h> | 28 | #include <net/mac80211.h> |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index 3ad1fd05c5e7..bd8251c1c749 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -1067,15 +1067,19 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
1067 | 1067 | ||
1068 | last_rssi = priv->rx.last_rssi; | 1068 | last_rssi = priv->rx.last_rssi; |
1069 | 1069 | ||
1070 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) | 1070 | if (ieee80211_is_beacon(hdr->frame_control) && |
1071 | rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi, | 1071 | !is_zero_ether_addr(common->curbssid) && |
1072 | ATH_RSSI_EP_MULTIPLIER); | 1072 | ether_addr_equal(hdr->addr3, common->curbssid)) { |
1073 | s8 rssi = rxbuf->rxstatus.rs_rssi; | ||
1073 | 1074 | ||
1074 | if (rxbuf->rxstatus.rs_rssi < 0) | 1075 | if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) |
1075 | rxbuf->rxstatus.rs_rssi = 0; | 1076 | rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); |
1076 | 1077 | ||
1077 | if (ieee80211_is_beacon(fc)) | 1078 | if (rssi < 0) |
1078 | priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi; | 1079 | rssi = 0; |
1080 | |||
1081 | priv->ah->stats.avgbrssi = rssi; | ||
1082 | } | ||
1079 | 1083 | ||
1080 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); | 1084 | rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp); |
1081 | rx_status->band = hw->conf.channel->band; | 1085 | rx_status->band = hw->conf.channel->band; |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 2a2ae403e0e5..07e25260c31d 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -1463,7 +1463,9 @@ static bool ath9k_hw_chip_reset(struct ath_hw *ah, | |||
1463 | reset_type = ATH9K_RESET_POWER_ON; | 1463 | reset_type = ATH9K_RESET_POWER_ON; |
1464 | else | 1464 | else |
1465 | reset_type = ATH9K_RESET_COLD; | 1465 | reset_type = ATH9K_RESET_COLD; |
1466 | } | 1466 | } else if (ah->chip_fullsleep || REG_READ(ah, AR_Q_TXE) || |
1467 | (REG_READ(ah, AR_CR) & AR_CR_RXE)) | ||
1468 | reset_type = ATH9K_RESET_COLD; | ||
1467 | 1469 | ||
1468 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) | 1470 | if (!ath9k_hw_set_reset_reg(ah, reset_type)) |
1469 | return false; | 1471 | return false; |
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index ade3afb21f91..39c84ecf6a42 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -28,21 +28,21 @@ void ath_tx_complete_poll_work(struct work_struct *work) | |||
28 | int i; | 28 | int i; |
29 | bool needreset = false; | 29 | bool needreset = false; |
30 | 30 | ||
31 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) | 31 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { |
32 | if (ATH_TXQ_SETUP(sc, i)) { | 32 | txq = sc->tx.txq_map[i]; |
33 | txq = &sc->tx.txq[i]; | 33 | |
34 | ath_txq_lock(sc, txq); | 34 | ath_txq_lock(sc, txq); |
35 | if (txq->axq_depth) { | 35 | if (txq->axq_depth) { |
36 | if (txq->axq_tx_inprogress) { | 36 | if (txq->axq_tx_inprogress) { |
37 | needreset = true; | 37 | needreset = true; |
38 | ath_txq_unlock(sc, txq); | 38 | ath_txq_unlock(sc, txq); |
39 | break; | 39 | break; |
40 | } else { | 40 | } else { |
41 | txq->axq_tx_inprogress = true; | 41 | txq->axq_tx_inprogress = true; |
42 | } | ||
43 | } | 42 | } |
44 | ath_txq_unlock_complete(sc, txq); | ||
45 | } | 43 | } |
44 | ath_txq_unlock_complete(sc, txq); | ||
45 | } | ||
46 | 46 | ||
47 | if (needreset) { | 47 | if (needreset) { |
48 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, | 48 | ath_dbg(ath9k_hw_common(sc->sc_ah), RESET, |
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index 3630a41df50d..c353b5f19c8c 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -475,6 +475,7 @@ il3945_tx_skb(struct il_priv *il, | |||
475 | dma_addr_t txcmd_phys; | 475 | dma_addr_t txcmd_phys; |
476 | int txq_id = skb_get_queue_mapping(skb); | 476 | int txq_id = skb_get_queue_mapping(skb); |
477 | u16 len, idx, hdr_len; | 477 | u16 len, idx, hdr_len; |
478 | u16 firstlen, secondlen; | ||
478 | u8 id; | 479 | u8 id; |
479 | u8 unicast; | 480 | u8 unicast; |
480 | u8 sta_id; | 481 | u8 sta_id; |
@@ -589,21 +590,22 @@ il3945_tx_skb(struct il_priv *il, | |||
589 | len = | 590 | len = |
590 | sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) + | 591 | sizeof(struct il3945_tx_cmd) + sizeof(struct il_cmd_header) + |
591 | hdr_len; | 592 | hdr_len; |
592 | len = (len + 3) & ~3; | 593 | firstlen = (len + 3) & ~3; |
593 | 594 | ||
594 | /* Physical address of this Tx command's header (not MAC header!), | 595 | /* Physical address of this Tx command's header (not MAC header!), |
595 | * within command buffer array. */ | 596 | * within command buffer array. */ |
596 | txcmd_phys = | 597 | txcmd_phys = |
597 | pci_map_single(il->pci_dev, &out_cmd->hdr, len, PCI_DMA_TODEVICE); | 598 | pci_map_single(il->pci_dev, &out_cmd->hdr, firstlen, |
599 | PCI_DMA_TODEVICE); | ||
598 | if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys))) | 600 | if (unlikely(pci_dma_mapping_error(il->pci_dev, txcmd_phys))) |
599 | goto drop_unlock; | 601 | goto drop_unlock; |
600 | 602 | ||
601 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 603 | /* Set up TFD's 2nd entry to point directly to remainder of skb, |
602 | * if any (802.11 null frames have no payload). */ | 604 | * if any (802.11 null frames have no payload). */ |
603 | len = skb->len - hdr_len; | 605 | secondlen = skb->len - hdr_len; |
604 | if (len) { | 606 | if (secondlen > 0) { |
605 | phys_addr = | 607 | phys_addr = |
606 | pci_map_single(il->pci_dev, skb->data + hdr_len, len, | 608 | pci_map_single(il->pci_dev, skb->data + hdr_len, secondlen, |
607 | PCI_DMA_TODEVICE); | 609 | PCI_DMA_TODEVICE); |
608 | if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) | 610 | if (unlikely(pci_dma_mapping_error(il->pci_dev, phys_addr))) |
609 | goto drop_unlock; | 611 | goto drop_unlock; |
@@ -611,12 +613,12 @@ il3945_tx_skb(struct il_priv *il, | |||
611 | 613 | ||
612 | /* Add buffer containing Tx command and MAC(!) header to TFD's | 614 | /* Add buffer containing Tx command and MAC(!) header to TFD's |
613 | * first entry */ | 615 | * first entry */ |
614 | il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, len, 1, 0); | 616 | il->ops->txq_attach_buf_to_tfd(il, txq, txcmd_phys, firstlen, 1, 0); |
615 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | 617 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); |
616 | dma_unmap_len_set(out_meta, len, len); | 618 | dma_unmap_len_set(out_meta, len, firstlen); |
617 | if (len) | 619 | if (secondlen > 0) |
618 | il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, len, 0, | 620 | il->ops->txq_attach_buf_to_tfd(il, txq, phys_addr, secondlen, 0, |
619 | U32_PAD(len)); | 621 | U32_PAD(secondlen)); |
620 | 622 | ||
621 | if (!ieee80211_has_morefrags(hdr->frame_control)) { | 623 | if (!ieee80211_has_morefrags(hdr->frame_control)) { |
622 | txq->need_update = 1; | 624 | txq->need_update = 1; |
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c index 94ef33838bc6..b775769f8322 100644 --- a/drivers/net/wireless/iwlwifi/dvm/sta.c +++ b/drivers/net/wireless/iwlwifi/dvm/sta.c | |||
@@ -151,7 +151,7 @@ int iwl_send_add_sta(struct iwl_priv *priv, | |||
151 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); | 151 | sta_id, sta->sta.addr, flags & CMD_ASYNC ? "a" : ""); |
152 | 152 | ||
153 | if (!(flags & CMD_ASYNC)) { | 153 | if (!(flags & CMD_ASYNC)) { |
154 | cmd.flags |= CMD_WANT_SKB | CMD_WANT_HCMD; | 154 | cmd.flags |= CMD_WANT_SKB; |
155 | might_sleep(); | 155 | might_sleep(); |
156 | } | 156 | } |
157 | 157 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-devtrace.h b/drivers/net/wireless/iwlwifi/iwl-devtrace.h index 9a0f45ec9e01..81aa91fab5aa 100644 --- a/drivers/net/wireless/iwlwifi/iwl-devtrace.h +++ b/drivers/net/wireless/iwlwifi/iwl-devtrace.h | |||
@@ -349,25 +349,23 @@ TRACE_EVENT(iwlwifi_dev_rx_data, | |||
349 | TRACE_EVENT(iwlwifi_dev_hcmd, | 349 | TRACE_EVENT(iwlwifi_dev_hcmd, |
350 | TP_PROTO(const struct device *dev, | 350 | TP_PROTO(const struct device *dev, |
351 | struct iwl_host_cmd *cmd, u16 total_size, | 351 | struct iwl_host_cmd *cmd, u16 total_size, |
352 | const void *hdr, size_t hdr_len), | 352 | struct iwl_cmd_header *hdr), |
353 | TP_ARGS(dev, cmd, total_size, hdr, hdr_len), | 353 | TP_ARGS(dev, cmd, total_size, hdr), |
354 | TP_STRUCT__entry( | 354 | TP_STRUCT__entry( |
355 | DEV_ENTRY | 355 | DEV_ENTRY |
356 | __dynamic_array(u8, hcmd, total_size) | 356 | __dynamic_array(u8, hcmd, total_size) |
357 | __field(u32, flags) | 357 | __field(u32, flags) |
358 | ), | 358 | ), |
359 | TP_fast_assign( | 359 | TP_fast_assign( |
360 | int i, offset = hdr_len; | 360 | int i, offset = sizeof(*hdr); |
361 | 361 | ||
362 | DEV_ASSIGN; | 362 | DEV_ASSIGN; |
363 | __entry->flags = cmd->flags; | 363 | __entry->flags = cmd->flags; |
364 | memcpy(__get_dynamic_array(hcmd), hdr, hdr_len); | 364 | memcpy(__get_dynamic_array(hcmd), hdr, sizeof(*hdr)); |
365 | 365 | ||
366 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 366 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { |
367 | if (!cmd->len[i]) | 367 | if (!cmd->len[i]) |
368 | continue; | 368 | continue; |
369 | if (!(cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY)) | ||
370 | continue; | ||
371 | memcpy((u8 *)__get_dynamic_array(hcmd) + offset, | 369 | memcpy((u8 *)__get_dynamic_array(hcmd) + offset, |
372 | cmd->data[i], cmd->len[i]); | 370 | cmd->data[i], cmd->len[i]); |
373 | offset += cmd->len[i]; | 371 | offset += cmd->len[i]; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 6f228bb2b844..fbfd2d137117 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -1102,7 +1102,6 @@ void iwl_drv_stop(struct iwl_drv *drv) | |||
1102 | 1102 | ||
1103 | /* shared module parameters */ | 1103 | /* shared module parameters */ |
1104 | struct iwl_mod_params iwlwifi_mod_params = { | 1104 | struct iwl_mod_params iwlwifi_mod_params = { |
1105 | .amsdu_size_8K = 1, | ||
1106 | .restart_fw = 1, | 1105 | .restart_fw = 1, |
1107 | .plcp_check = true, | 1106 | .plcp_check = true, |
1108 | .bt_coex_active = true, | 1107 | .bt_coex_active = true, |
@@ -1207,7 +1206,7 @@ MODULE_PARM_DESC(11n_disable, | |||
1207 | "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); | 1206 | "disable 11n functionality, bitmap: 1: full, 2: agg TX, 4: agg RX"); |
1208 | module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, | 1207 | module_param_named(amsdu_size_8K, iwlwifi_mod_params.amsdu_size_8K, |
1209 | int, S_IRUGO); | 1208 | int, S_IRUGO); |
1210 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size"); | 1209 | MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size (default 0)"); |
1211 | module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO); | 1210 | module_param_named(fw_restart, iwlwifi_mod_params.restart_fw, int, S_IRUGO); |
1212 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); | 1211 | MODULE_PARM_DESC(fw_restart, "restart firmware in case of error"); |
1213 | 1212 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h index e5e3a79eae2f..2c2a729092f5 100644 --- a/drivers/net/wireless/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h | |||
@@ -91,7 +91,7 @@ enum iwl_power_level { | |||
91 | * @sw_crypto: using hardware encryption, default = 0 | 91 | * @sw_crypto: using hardware encryption, default = 0 |
92 | * @disable_11n: disable 11n capabilities, default = 0, | 92 | * @disable_11n: disable 11n capabilities, default = 0, |
93 | * use IWL_DISABLE_HT_* constants | 93 | * use IWL_DISABLE_HT_* constants |
94 | * @amsdu_size_8K: enable 8K amsdu size, default = 1 | 94 | * @amsdu_size_8K: enable 8K amsdu size, default = 0 |
95 | * @restart_fw: restart firmware, default = 1 | 95 | * @restart_fw: restart firmware, default = 1 |
96 | * @plcp_check: enable plcp health check, default = true | 96 | * @plcp_check: enable plcp health check, default = true |
97 | * @wd_disable: enable stuck queue check, default = 0 | 97 | * @wd_disable: enable stuck queue check, default = 0 |
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c index 14fc8d39fc28..3392011a8768 100644 --- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c +++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c | |||
@@ -136,12 +136,6 @@ struct iwl_calib_res_notif_phy_db { | |||
136 | u8 data[]; | 136 | u8 data[]; |
137 | } __packed; | 137 | } __packed; |
138 | 138 | ||
139 | #define IWL_PHY_DB_STATIC_PIC cpu_to_le32(0x21436587) | ||
140 | static inline void iwl_phy_db_test_pic(__le32 pic) | ||
141 | { | ||
142 | WARN_ON(IWL_PHY_DB_STATIC_PIC != pic); | ||
143 | } | ||
144 | |||
145 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) | 139 | struct iwl_phy_db *iwl_phy_db_init(struct iwl_trans *trans) |
146 | { | 140 | { |
147 | struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), | 141 | struct iwl_phy_db *phy_db = kzalloc(sizeof(struct iwl_phy_db), |
@@ -260,11 +254,6 @@ int iwl_phy_db_set_section(struct iwl_phy_db *phy_db, struct iwl_rx_packet *pkt, | |||
260 | (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; | 254 | (size - CHANNEL_NUM_SIZE) / phy_db->channel_num; |
261 | } | 255 | } |
262 | 256 | ||
263 | /* Test PIC */ | ||
264 | if (type != IWL_PHY_DB_CFG) | ||
265 | iwl_phy_db_test_pic(*(((__le32 *)phy_db_notif->data) + | ||
266 | (size / sizeof(__le32)) - 1)); | ||
267 | |||
268 | IWL_DEBUG_INFO(phy_db->trans, | 257 | IWL_DEBUG_INFO(phy_db->trans, |
269 | "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", | 258 | "%s(%d): [PHYDB]SET: Type %d , Size: %d\n", |
270 | __func__, __LINE__, type, size); | 259 | __func__, __LINE__, type, size); |
@@ -372,11 +361,6 @@ int iwl_phy_db_get_section_data(struct iwl_phy_db *phy_db, | |||
372 | *size = entry->size; | 361 | *size = entry->size; |
373 | } | 362 | } |
374 | 363 | ||
375 | /* Test PIC */ | ||
376 | if (type != IWL_PHY_DB_CFG) | ||
377 | iwl_phy_db_test_pic(*(((__le32 *)*data) + | ||
378 | (*size / sizeof(__le32)) - 1)); | ||
379 | |||
380 | IWL_DEBUG_INFO(phy_db->trans, | 364 | IWL_DEBUG_INFO(phy_db->trans, |
381 | "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", | 365 | "%s(%d): [PHYDB] GET: Type %d , Size: %d\n", |
382 | __func__, __LINE__, type, *size); | 366 | __func__, __LINE__, type, *size); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index 8c7bec6b9a0b..0cac2b7af78b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -186,19 +186,13 @@ struct iwl_rx_packet { | |||
186 | * @CMD_ASYNC: Return right away and don't want for the response | 186 | * @CMD_ASYNC: Return right away and don't want for the response |
187 | * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the | 187 | * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the |
188 | * response. The caller needs to call iwl_free_resp when done. | 188 | * response. The caller needs to call iwl_free_resp when done. |
189 | * @CMD_WANT_HCMD: The caller needs to get the HCMD that was sent in the | ||
190 | * response handler. Chunks flagged by %IWL_HCMD_DFL_NOCOPY won't be | ||
191 | * copied. The pointer passed to the response handler is in the transport | ||
192 | * ownership and don't need to be freed by the op_mode. This also means | ||
193 | * that the pointer is invalidated after the op_mode's handler returns. | ||
194 | * @CMD_ON_DEMAND: This command is sent by the test mode pipe. | 189 | * @CMD_ON_DEMAND: This command is sent by the test mode pipe. |
195 | */ | 190 | */ |
196 | enum CMD_MODE { | 191 | enum CMD_MODE { |
197 | CMD_SYNC = 0, | 192 | CMD_SYNC = 0, |
198 | CMD_ASYNC = BIT(0), | 193 | CMD_ASYNC = BIT(0), |
199 | CMD_WANT_SKB = BIT(1), | 194 | CMD_WANT_SKB = BIT(1), |
200 | CMD_WANT_HCMD = BIT(2), | 195 | CMD_ON_DEMAND = BIT(2), |
201 | CMD_ON_DEMAND = BIT(3), | ||
202 | }; | 196 | }; |
203 | 197 | ||
204 | #define DEF_CMD_PAYLOAD_SIZE 320 | 198 | #define DEF_CMD_PAYLOAD_SIZE 320 |
@@ -217,7 +211,11 @@ struct iwl_device_cmd { | |||
217 | 211 | ||
218 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) | 212 | #define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd)) |
219 | 213 | ||
220 | #define IWL_MAX_CMD_TFDS 2 | 214 | /* |
215 | * number of transfer buffers (fragments) per transmit frame descriptor; | ||
216 | * this is just the driver's idea, the hardware supports 20 | ||
217 | */ | ||
218 | #define IWL_MAX_CMD_TBS_PER_TFD 2 | ||
221 | 219 | ||
222 | /** | 220 | /** |
223 | * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command | 221 | * struct iwl_hcmd_dataflag - flag for each one of the chunks of the command |
@@ -254,15 +252,15 @@ enum iwl_hcmd_dataflag { | |||
254 | * @id: id of the host command | 252 | * @id: id of the host command |
255 | */ | 253 | */ |
256 | struct iwl_host_cmd { | 254 | struct iwl_host_cmd { |
257 | const void *data[IWL_MAX_CMD_TFDS]; | 255 | const void *data[IWL_MAX_CMD_TBS_PER_TFD]; |
258 | struct iwl_rx_packet *resp_pkt; | 256 | struct iwl_rx_packet *resp_pkt; |
259 | unsigned long _rx_page_addr; | 257 | unsigned long _rx_page_addr; |
260 | u32 _rx_page_order; | 258 | u32 _rx_page_order; |
261 | int handler_status; | 259 | int handler_status; |
262 | 260 | ||
263 | u32 flags; | 261 | u32 flags; |
264 | u16 len[IWL_MAX_CMD_TFDS]; | 262 | u16 len[IWL_MAX_CMD_TBS_PER_TFD]; |
265 | u8 dataflags[IWL_MAX_CMD_TFDS]; | 263 | u8 dataflags[IWL_MAX_CMD_TBS_PER_TFD]; |
266 | u8 id; | 264 | u8 id; |
267 | }; | 265 | }; |
268 | 266 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index c64d864799cd..994c8c263dc0 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -61,6 +61,7 @@ | |||
61 | * | 61 | * |
62 | *****************************************************************************/ | 62 | *****************************************************************************/ |
63 | 63 | ||
64 | #include <linux/etherdevice.h> | ||
64 | #include <net/cfg80211.h> | 65 | #include <net/cfg80211.h> |
65 | #include <net/ipv6.h> | 66 | #include <net/ipv6.h> |
66 | #include "iwl-modparams.h" | 67 | #include "iwl-modparams.h" |
@@ -192,6 +193,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
192 | sizeof(wkc), &wkc); | 193 | sizeof(wkc), &wkc); |
193 | data->error = ret != 0; | 194 | data->error = ret != 0; |
194 | 195 | ||
196 | mvm->ptk_ivlen = key->iv_len; | ||
197 | mvm->ptk_icvlen = key->icv_len; | ||
198 | mvm->gtk_ivlen = key->iv_len; | ||
199 | mvm->gtk_icvlen = key->icv_len; | ||
200 | |||
195 | /* don't upload key again */ | 201 | /* don't upload key again */ |
196 | goto out_unlock; | 202 | goto out_unlock; |
197 | } | 203 | } |
@@ -304,9 +310,13 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw, | |||
304 | */ | 310 | */ |
305 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { | 311 | if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { |
306 | key->hw_key_idx = 0; | 312 | key->hw_key_idx = 0; |
313 | mvm->ptk_ivlen = key->iv_len; | ||
314 | mvm->ptk_icvlen = key->icv_len; | ||
307 | } else { | 315 | } else { |
308 | data->gtk_key_idx++; | 316 | data->gtk_key_idx++; |
309 | key->hw_key_idx = data->gtk_key_idx; | 317 | key->hw_key_idx = data->gtk_key_idx; |
318 | mvm->gtk_ivlen = key->iv_len; | ||
319 | mvm->gtk_icvlen = key->icv_len; | ||
310 | } | 320 | } |
311 | 321 | ||
312 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); | 322 | ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true); |
@@ -649,6 +659,11 @@ int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
649 | /* We reprogram keys and shouldn't allocate new key indices */ | 659 | /* We reprogram keys and shouldn't allocate new key indices */ |
650 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); | 660 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); |
651 | 661 | ||
662 | mvm->ptk_ivlen = 0; | ||
663 | mvm->ptk_icvlen = 0; | ||
664 | mvm->ptk_ivlen = 0; | ||
665 | mvm->ptk_icvlen = 0; | ||
666 | |||
652 | /* | 667 | /* |
653 | * The D3 firmware still hardcodes the AP station ID for the | 668 | * The D3 firmware still hardcodes the AP station ID for the |
654 | * BSS we're associated with as 0. As a result, we have to move | 669 | * BSS we're associated with as 0. As a result, we have to move |
@@ -783,7 +798,6 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
783 | struct iwl_wowlan_status *status; | 798 | struct iwl_wowlan_status *status; |
784 | u32 reasons; | 799 | u32 reasons; |
785 | int ret, len; | 800 | int ret, len; |
786 | bool pkt8023 = false; | ||
787 | struct sk_buff *pkt = NULL; | 801 | struct sk_buff *pkt = NULL; |
788 | 802 | ||
789 | iwl_trans_read_mem_bytes(mvm->trans, base, | 803 | iwl_trans_read_mem_bytes(mvm->trans, base, |
@@ -824,7 +838,8 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
824 | status = (void *)cmd.resp_pkt->data; | 838 | status = (void *)cmd.resp_pkt->data; |
825 | 839 | ||
826 | if (len - sizeof(struct iwl_cmd_header) != | 840 | if (len - sizeof(struct iwl_cmd_header) != |
827 | sizeof(*status) + le32_to_cpu(status->wake_packet_bufsize)) { | 841 | sizeof(*status) + |
842 | ALIGN(le32_to_cpu(status->wake_packet_bufsize), 4)) { | ||
828 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); | 843 | IWL_ERR(mvm, "Invalid WoWLAN status response!\n"); |
829 | goto out; | 844 | goto out; |
830 | } | 845 | } |
@@ -836,61 +851,96 @@ static void iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm, | |||
836 | goto report; | 851 | goto report; |
837 | } | 852 | } |
838 | 853 | ||
839 | if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) { | 854 | if (reasons & IWL_WOWLAN_WAKEUP_BY_MAGIC_PACKET) |
840 | wakeup.magic_pkt = true; | 855 | wakeup.magic_pkt = true; |
841 | pkt8023 = true; | ||
842 | } | ||
843 | 856 | ||
844 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) { | 857 | if (reasons & IWL_WOWLAN_WAKEUP_BY_PATTERN) |
845 | wakeup.pattern_idx = | 858 | wakeup.pattern_idx = |
846 | le16_to_cpu(status->pattern_number); | 859 | le16_to_cpu(status->pattern_number); |
847 | pkt8023 = true; | ||
848 | } | ||
849 | 860 | ||
850 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | | 861 | if (reasons & (IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_MISSED_BEACON | |
851 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) | 862 | IWL_WOWLAN_WAKEUP_BY_DISCONNECTION_ON_DEAUTH)) |
852 | wakeup.disconnect = true; | 863 | wakeup.disconnect = true; |
853 | 864 | ||
854 | if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) { | 865 | if (reasons & IWL_WOWLAN_WAKEUP_BY_GTK_REKEY_FAILURE) |
855 | wakeup.gtk_rekey_failure = true; | 866 | wakeup.gtk_rekey_failure = true; |
856 | pkt8023 = true; | ||
857 | } | ||
858 | 867 | ||
859 | if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) { | 868 | if (reasons & IWL_WOWLAN_WAKEUP_BY_RFKILL_DEASSERTED) |
860 | wakeup.rfkill_release = true; | 869 | wakeup.rfkill_release = true; |
861 | pkt8023 = true; | ||
862 | } | ||
863 | 870 | ||
864 | if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) { | 871 | if (reasons & IWL_WOWLAN_WAKEUP_BY_EAPOL_REQUEST) |
865 | wakeup.eap_identity_req = true; | 872 | wakeup.eap_identity_req = true; |
866 | pkt8023 = true; | ||
867 | } | ||
868 | 873 | ||
869 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) { | 874 | if (reasons & IWL_WOWLAN_WAKEUP_BY_FOUR_WAY_HANDSHAKE) |
870 | wakeup.four_way_handshake = true; | 875 | wakeup.four_way_handshake = true; |
871 | pkt8023 = true; | ||
872 | } | ||
873 | 876 | ||
874 | if (status->wake_packet_bufsize) { | 877 | if (status->wake_packet_bufsize) { |
875 | u32 pktsize = le32_to_cpu(status->wake_packet_bufsize); | 878 | int pktsize = le32_to_cpu(status->wake_packet_bufsize); |
876 | u32 pktlen = le32_to_cpu(status->wake_packet_length); | 879 | int pktlen = le32_to_cpu(status->wake_packet_length); |
880 | const u8 *pktdata = status->wake_packet; | ||
881 | struct ieee80211_hdr *hdr = (void *)pktdata; | ||
882 | int truncated = pktlen - pktsize; | ||
883 | |||
884 | /* this would be a firmware bug */ | ||
885 | if (WARN_ON_ONCE(truncated < 0)) | ||
886 | truncated = 0; | ||
887 | |||
888 | if (ieee80211_is_data(hdr->frame_control)) { | ||
889 | int hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
890 | int ivlen = 0, icvlen = 4; /* also FCS */ | ||
877 | 891 | ||
878 | if (pkt8023) { | ||
879 | pkt = alloc_skb(pktsize, GFP_KERNEL); | 892 | pkt = alloc_skb(pktsize, GFP_KERNEL); |
880 | if (!pkt) | 893 | if (!pkt) |
881 | goto report; | 894 | goto report; |
882 | memcpy(skb_put(pkt, pktsize), status->wake_packet, | 895 | |
883 | pktsize); | 896 | memcpy(skb_put(pkt, hdrlen), pktdata, hdrlen); |
897 | pktdata += hdrlen; | ||
898 | pktsize -= hdrlen; | ||
899 | |||
900 | if (ieee80211_has_protected(hdr->frame_control)) { | ||
901 | if (is_multicast_ether_addr(hdr->addr1)) { | ||
902 | ivlen = mvm->gtk_ivlen; | ||
903 | icvlen += mvm->gtk_icvlen; | ||
904 | } else { | ||
905 | ivlen = mvm->ptk_ivlen; | ||
906 | icvlen += mvm->ptk_icvlen; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | /* if truncated, FCS/ICV is (partially) gone */ | ||
911 | if (truncated >= icvlen) { | ||
912 | icvlen = 0; | ||
913 | truncated -= icvlen; | ||
914 | } else { | ||
915 | icvlen -= truncated; | ||
916 | truncated = 0; | ||
917 | } | ||
918 | |||
919 | pktsize -= ivlen + icvlen; | ||
920 | pktdata += ivlen; | ||
921 | |||
922 | memcpy(skb_put(pkt, pktsize), pktdata, pktsize); | ||
923 | |||
884 | if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) | 924 | if (ieee80211_data_to_8023(pkt, vif->addr, vif->type)) |
885 | goto report; | 925 | goto report; |
886 | wakeup.packet = pkt->data; | 926 | wakeup.packet = pkt->data; |
887 | wakeup.packet_present_len = pkt->len; | 927 | wakeup.packet_present_len = pkt->len; |
888 | wakeup.packet_len = pkt->len - (pktlen - pktsize); | 928 | wakeup.packet_len = pkt->len - truncated; |
889 | wakeup.packet_80211 = false; | 929 | wakeup.packet_80211 = false; |
890 | } else { | 930 | } else { |
931 | int fcslen = 4; | ||
932 | |||
933 | if (truncated >= 4) { | ||
934 | truncated -= 4; | ||
935 | fcslen = 0; | ||
936 | } else { | ||
937 | fcslen -= truncated; | ||
938 | truncated = 0; | ||
939 | } | ||
940 | pktsize -= fcslen; | ||
891 | wakeup.packet = status->wake_packet; | 941 | wakeup.packet = status->wake_packet; |
892 | wakeup.packet_present_len = pktsize; | 942 | wakeup.packet_present_len = pktsize; |
893 | wakeup.packet_len = pktlen; | 943 | wakeup.packet_len = pktlen - truncated; |
894 | wakeup.packet_80211 = true; | 944 | wakeup.packet_80211 = true; |
895 | } | 945 | } |
896 | } | 946 | } |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 23eebda848b0..2adb61f103f4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h | |||
@@ -762,18 +762,20 @@ struct iwl_phy_context_cmd { | |||
762 | #define IWL_RX_INFO_PHY_CNT 8 | 762 | #define IWL_RX_INFO_PHY_CNT 8 |
763 | #define IWL_RX_INFO_AGC_IDX 1 | 763 | #define IWL_RX_INFO_AGC_IDX 1 |
764 | #define IWL_RX_INFO_RSSI_AB_IDX 2 | 764 | #define IWL_RX_INFO_RSSI_AB_IDX 2 |
765 | #define IWL_RX_INFO_RSSI_C_IDX 3 | 765 | #define IWL_OFDM_AGC_A_MSK 0x0000007f |
766 | #define IWL_OFDM_AGC_DB_MSK 0xfe00 | 766 | #define IWL_OFDM_AGC_A_POS 0 |
767 | #define IWL_OFDM_AGC_DB_POS 9 | 767 | #define IWL_OFDM_AGC_B_MSK 0x00003f80 |
768 | #define IWL_OFDM_AGC_B_POS 7 | ||
769 | #define IWL_OFDM_AGC_CODE_MSK 0x3fe00000 | ||
770 | #define IWL_OFDM_AGC_CODE_POS 20 | ||
768 | #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff | 771 | #define IWL_OFDM_RSSI_INBAND_A_MSK 0x00ff |
769 | #define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 | ||
770 | #define IWL_OFDM_RSSI_A_POS 0 | 772 | #define IWL_OFDM_RSSI_A_POS 0 |
773 | #define IWL_OFDM_RSSI_ALLBAND_A_MSK 0xff00 | ||
774 | #define IWL_OFDM_RSSI_ALLBAND_A_POS 8 | ||
771 | #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 | 775 | #define IWL_OFDM_RSSI_INBAND_B_MSK 0xff0000 |
772 | #define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 | ||
773 | #define IWL_OFDM_RSSI_B_POS 16 | 776 | #define IWL_OFDM_RSSI_B_POS 16 |
774 | #define IWL_OFDM_RSSI_INBAND_C_MSK 0x00ff | 777 | #define IWL_OFDM_RSSI_ALLBAND_B_MSK 0xff000000 |
775 | #define IWL_OFDM_RSSI_ALLBAND_C_MSK 0xff00 | 778 | #define IWL_OFDM_RSSI_ALLBAND_B_POS 24 |
776 | #define IWL_OFDM_RSSI_C_POS 0 | ||
777 | 779 | ||
778 | /** | 780 | /** |
779 | * struct iwl_rx_phy_info - phy info | 781 | * struct iwl_rx_phy_info - phy info |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index d3d959db03a9..500f818dba04 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -79,17 +79,8 @@ | |||
79 | #define UCODE_VALID_OK cpu_to_le32(0x1) | 79 | #define UCODE_VALID_OK cpu_to_le32(0x1) |
80 | 80 | ||
81 | /* Default calibration values for WkP - set to INIT image w/o running */ | 81 | /* Default calibration values for WkP - set to INIT image w/o running */ |
82 | static const u8 wkp_calib_values_bb_filter[] = { 0xbf, 0x00, 0x5f, 0x00, 0x2f, | ||
83 | 0x00, 0x18, 0x00 }; | ||
84 | static const u8 wkp_calib_values_rx_dc[] = { 0x7f, 0x7f, 0x7f, 0x7f, 0x7f, | ||
85 | 0x7f, 0x7f, 0x7f }; | ||
86 | static const u8 wkp_calib_values_tx_lo[] = { 0x00, 0x00, 0x00, 0x00 }; | ||
87 | static const u8 wkp_calib_values_tx_iq[] = { 0xff, 0x00, 0xff, 0x00, 0x00, | ||
88 | 0x00 }; | ||
89 | static const u8 wkp_calib_values_rx_iq[] = { 0xff, 0x00, 0x00, 0x00 }; | ||
90 | static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 }; | 82 | static const u8 wkp_calib_values_rx_iq_skew[] = { 0x00, 0x00, 0x01, 0x00 }; |
91 | static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 }; | 83 | static const u8 wkp_calib_values_tx_iq_skew[] = { 0x01, 0x00, 0x00, 0x00 }; |
92 | static const u8 wkp_calib_values_xtal[] = { 0xd2, 0xd2 }; | ||
93 | 84 | ||
94 | struct iwl_calib_default_data { | 85 | struct iwl_calib_default_data { |
95 | u16 size; | 86 | u16 size; |
@@ -99,12 +90,7 @@ struct iwl_calib_default_data { | |||
99 | #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf} | 90 | #define CALIB_SIZE_N_DATA(_buf) {.size = sizeof(_buf), .data = &_buf} |
100 | 91 | ||
101 | static const struct iwl_calib_default_data wkp_calib_default_data[12] = { | 92 | static const struct iwl_calib_default_data wkp_calib_default_data[12] = { |
102 | [5] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_dc), | ||
103 | [6] = CALIB_SIZE_N_DATA(wkp_calib_values_bb_filter), | ||
104 | [7] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_lo), | ||
105 | [8] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq), | ||
106 | [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew), | 93 | [9] = CALIB_SIZE_N_DATA(wkp_calib_values_tx_iq_skew), |
107 | [10] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq), | ||
108 | [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew), | 94 | [11] = CALIB_SIZE_N_DATA(wkp_calib_values_rx_iq_skew), |
109 | }; | 95 | }; |
110 | 96 | ||
@@ -241,20 +227,6 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm, | |||
241 | 227 | ||
242 | return 0; | 228 | return 0; |
243 | } | 229 | } |
244 | #define IWL_HW_REV_ID_RAINBOW 0x2 | ||
245 | #define IWL_PROJ_TYPE_LHP 0x5 | ||
246 | |||
247 | static u32 iwl_mvm_build_phy_cfg(struct iwl_mvm *mvm) | ||
248 | { | ||
249 | struct iwl_nvm_data *data = mvm->nvm_data; | ||
250 | /* Temp calls to static definitions, will be changed to CSR calls */ | ||
251 | u8 hw_rev_id = IWL_HW_REV_ID_RAINBOW; | ||
252 | u8 project_type = IWL_PROJ_TYPE_LHP; | ||
253 | |||
254 | return data->radio_cfg_dash | (data->radio_cfg_step << 2) | | ||
255 | (hw_rev_id << 4) | ((project_type & 0x7f) << 6) | | ||
256 | (data->valid_tx_ant << 16) | (data->valid_rx_ant << 20); | ||
257 | } | ||
258 | 230 | ||
259 | static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | 231 | static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) |
260 | { | 232 | { |
@@ -262,7 +234,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | |||
262 | enum iwl_ucode_type ucode_type = mvm->cur_ucode; | 234 | enum iwl_ucode_type ucode_type = mvm->cur_ucode; |
263 | 235 | ||
264 | /* Set parameters */ | 236 | /* Set parameters */ |
265 | phy_cfg_cmd.phy_cfg = cpu_to_le32(iwl_mvm_build_phy_cfg(mvm)); | 237 | phy_cfg_cmd.phy_cfg = cpu_to_le32(mvm->fw->phy_config); |
266 | phy_cfg_cmd.calib_control.event_trigger = | 238 | phy_cfg_cmd.calib_control.event_trigger = |
267 | mvm->fw->default_calib[ucode_type].event_trigger; | 239 | mvm->fw->default_calib[ucode_type].event_trigger; |
268 | phy_cfg_cmd.calib_control.flow_trigger = | 240 | phy_cfg_cmd.calib_control.flow_trigger = |
@@ -275,103 +247,6 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm) | |||
275 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); | 247 | sizeof(phy_cfg_cmd), &phy_cfg_cmd); |
276 | } | 248 | } |
277 | 249 | ||
278 | /* Starting with the new PHY DB implementation - New calibs are enabled */ | ||
279 | /* Value - 0x405e7 */ | ||
280 | #define IWL_CALIB_DEFAULT_FLOW_INIT (IWL_CALIB_CFG_XTAL_IDX |\ | ||
281 | IWL_CALIB_CFG_TEMPERATURE_IDX |\ | ||
282 | IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ | ||
283 | IWL_CALIB_CFG_DC_IDX |\ | ||
284 | IWL_CALIB_CFG_BB_FILTER_IDX |\ | ||
285 | IWL_CALIB_CFG_LO_LEAKAGE_IDX |\ | ||
286 | IWL_CALIB_CFG_TX_IQ_IDX |\ | ||
287 | IWL_CALIB_CFG_RX_IQ_IDX |\ | ||
288 | IWL_CALIB_CFG_AGC_IDX) | ||
289 | |||
290 | #define IWL_CALIB_DEFAULT_EVENT_INIT 0x0 | ||
291 | |||
292 | /* Value 0x41567 */ | ||
293 | #define IWL_CALIB_DEFAULT_FLOW_RUN (IWL_CALIB_CFG_XTAL_IDX |\ | ||
294 | IWL_CALIB_CFG_TEMPERATURE_IDX |\ | ||
295 | IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ | ||
296 | IWL_CALIB_CFG_BB_FILTER_IDX |\ | ||
297 | IWL_CALIB_CFG_DC_IDX |\ | ||
298 | IWL_CALIB_CFG_TX_IQ_IDX |\ | ||
299 | IWL_CALIB_CFG_RX_IQ_IDX |\ | ||
300 | IWL_CALIB_CFG_SENSITIVITY_IDX |\ | ||
301 | IWL_CALIB_CFG_AGC_IDX) | ||
302 | |||
303 | #define IWL_CALIB_DEFAULT_EVENT_RUN (IWL_CALIB_CFG_XTAL_IDX |\ | ||
304 | IWL_CALIB_CFG_TEMPERATURE_IDX |\ | ||
305 | IWL_CALIB_CFG_VOLTAGE_READ_IDX |\ | ||
306 | IWL_CALIB_CFG_TX_PWR_IDX |\ | ||
307 | IWL_CALIB_CFG_DC_IDX |\ | ||
308 | IWL_CALIB_CFG_TX_IQ_IDX |\ | ||
309 | IWL_CALIB_CFG_SENSITIVITY_IDX) | ||
310 | |||
311 | /* | ||
312 | * Sets the calibrations trigger values that will be sent to the FW for runtime | ||
313 | * and init calibrations. | ||
314 | * The ones given in the FW TLV are not correct. | ||
315 | */ | ||
316 | static void iwl_set_default_calib_trigger(struct iwl_mvm *mvm) | ||
317 | { | ||
318 | struct iwl_tlv_calib_ctrl default_calib; | ||
319 | |||
320 | /* | ||
321 | * WkP FW TLV calib bits are wrong, overwrite them. | ||
322 | * This defines the dynamic calibrations which are implemented in the | ||
323 | * uCode both for init(flow) calculation and event driven calibs. | ||
324 | */ | ||
325 | |||
326 | /* Init Image */ | ||
327 | default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_INIT); | ||
328 | default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_INIT); | ||
329 | |||
330 | if (default_calib.event_trigger != | ||
331 | mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger) | ||
332 | IWL_ERR(mvm, | ||
333 | "Updating the event calib for INIT image: 0x%x -> 0x%x\n", | ||
334 | mvm->fw->default_calib[IWL_UCODE_INIT].event_trigger, | ||
335 | default_calib.event_trigger); | ||
336 | if (default_calib.flow_trigger != | ||
337 | mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger) | ||
338 | IWL_ERR(mvm, | ||
339 | "Updating the flow calib for INIT image: 0x%x -> 0x%x\n", | ||
340 | mvm->fw->default_calib[IWL_UCODE_INIT].flow_trigger, | ||
341 | default_calib.flow_trigger); | ||
342 | |||
343 | memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_INIT], | ||
344 | &default_calib, sizeof(struct iwl_tlv_calib_ctrl)); | ||
345 | IWL_ERR(mvm, | ||
346 | "Setting uCode init calibrations event 0x%x, trigger 0x%x\n", | ||
347 | default_calib.event_trigger, | ||
348 | default_calib.flow_trigger); | ||
349 | |||
350 | /* Run time image */ | ||
351 | default_calib.event_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_EVENT_RUN); | ||
352 | default_calib.flow_trigger = cpu_to_le32(IWL_CALIB_DEFAULT_FLOW_RUN); | ||
353 | |||
354 | if (default_calib.event_trigger != | ||
355 | mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger) | ||
356 | IWL_ERR(mvm, | ||
357 | "Updating the event calib for RT image: 0x%x -> 0x%x\n", | ||
358 | mvm->fw->default_calib[IWL_UCODE_REGULAR].event_trigger, | ||
359 | default_calib.event_trigger); | ||
360 | if (default_calib.flow_trigger != | ||
361 | mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger) | ||
362 | IWL_ERR(mvm, | ||
363 | "Updating the flow calib for RT image: 0x%x -> 0x%x\n", | ||
364 | mvm->fw->default_calib[IWL_UCODE_REGULAR].flow_trigger, | ||
365 | default_calib.flow_trigger); | ||
366 | |||
367 | memcpy((void *)&mvm->fw->default_calib[IWL_UCODE_REGULAR], | ||
368 | &default_calib, sizeof(struct iwl_tlv_calib_ctrl)); | ||
369 | IWL_ERR(mvm, | ||
370 | "Setting uCode runtime calibs event 0x%x, trigger 0x%x\n", | ||
371 | default_calib.event_trigger, | ||
372 | default_calib.flow_trigger); | ||
373 | } | ||
374 | |||
375 | static int iwl_set_default_calibrations(struct iwl_mvm *mvm) | 250 | static int iwl_set_default_calibrations(struct iwl_mvm *mvm) |
376 | { | 251 | { |
377 | u8 cmd_raw[16]; /* holds the variable size commands */ | 252 | u8 cmd_raw[16]; /* holds the variable size commands */ |
@@ -446,8 +321,10 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
446 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); | 321 | ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans); |
447 | WARN_ON(ret); | 322 | WARN_ON(ret); |
448 | 323 | ||
449 | /* Override the calibrations from TLV and the const of fw */ | 324 | /* Send TX valid antennas before triggering calibrations */ |
450 | iwl_set_default_calib_trigger(mvm); | 325 | ret = iwl_send_tx_ant_cfg(mvm, mvm->nvm_data->valid_tx_ant); |
326 | if (ret) | ||
327 | goto error; | ||
451 | 328 | ||
452 | /* WkP doesn't have all calibrations, need to set default values */ | 329 | /* WkP doesn't have all calibrations, need to set default values */ |
453 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { | 330 | if (mvm->cfg->device_family == IWL_DEVICE_FAMILY_7000) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index e8264e11b12d..7e169b085afe 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -557,11 +557,9 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
557 | return ret; | 557 | return ret; |
558 | } | 558 | } |
559 | 559 | ||
560 | static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | 560 | static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, |
561 | struct ieee80211_vif *vif) | 561 | struct ieee80211_vif *vif) |
562 | { | 562 | { |
563 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
564 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
565 | u32 tfd_msk = 0, ac; | 563 | u32 tfd_msk = 0, ac; |
566 | 564 | ||
567 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) | 565 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) |
@@ -594,12 +592,21 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | |||
594 | */ | 592 | */ |
595 | flush_work(&mvm->sta_drained_wk); | 593 | flush_work(&mvm->sta_drained_wk); |
596 | } | 594 | } |
595 | } | ||
596 | |||
597 | static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw, | ||
598 | struct ieee80211_vif *vif) | ||
599 | { | ||
600 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
601 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
602 | |||
603 | iwl_mvm_prepare_mac_removal(mvm, vif); | ||
597 | 604 | ||
598 | mutex_lock(&mvm->mutex); | 605 | mutex_lock(&mvm->mutex); |
599 | 606 | ||
600 | /* | 607 | /* |
601 | * For AP/GO interface, the tear down of the resources allocated to the | 608 | * For AP/GO interface, the tear down of the resources allocated to the |
602 | * interface should be handled as part of the bss_info_changed flow. | 609 | * interface is be handled as part of the stop_ap flow. |
603 | */ | 610 | */ |
604 | if (vif->type == NL80211_IFTYPE_AP) { | 611 | if (vif->type == NL80211_IFTYPE_AP) { |
605 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); | 612 | iwl_mvm_dealloc_int_sta(mvm, &mvmvif->bcast_sta); |
@@ -763,6 +770,8 @@ static void iwl_mvm_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
763 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | 770 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); |
764 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 771 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
765 | 772 | ||
773 | iwl_mvm_prepare_mac_removal(mvm, vif); | ||
774 | |||
766 | mutex_lock(&mvm->mutex); | 775 | mutex_lock(&mvm->mutex); |
767 | 776 | ||
768 | mvmvif->ap_active = false; | 777 | mvmvif->ap_active = false; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 4e339ccfa800..bdae700c769e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -80,7 +80,8 @@ | |||
80 | 80 | ||
81 | #define IWL_INVALID_MAC80211_QUEUE 0xff | 81 | #define IWL_INVALID_MAC80211_QUEUE 0xff |
82 | #define IWL_MVM_MAX_ADDRESSES 2 | 82 | #define IWL_MVM_MAX_ADDRESSES 2 |
83 | #define IWL_RSSI_OFFSET 44 | 83 | /* RSSI offset for WkP */ |
84 | #define IWL_RSSI_OFFSET 50 | ||
84 | 85 | ||
85 | enum iwl_mvm_tx_fifo { | 86 | enum iwl_mvm_tx_fifo { |
86 | IWL_MVM_TX_FIFO_BK = 0, | 87 | IWL_MVM_TX_FIFO_BK = 0, |
@@ -327,6 +328,10 @@ struct iwl_mvm { | |||
327 | struct led_classdev led; | 328 | struct led_classdev led; |
328 | 329 | ||
329 | struct ieee80211_vif *p2p_device_vif; | 330 | struct ieee80211_vif *p2p_device_vif; |
331 | |||
332 | #ifdef CONFIG_PM_SLEEP | ||
333 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; | ||
334 | #endif | ||
330 | }; | 335 | }; |
331 | 336 | ||
332 | /* Extract MVM priv from op_mode and _hw */ | 337 | /* Extract MVM priv from op_mode and _hw */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index aa59adf87db3..d0f9c1e0475e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -624,12 +624,8 @@ static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | |||
624 | ieee80211_free_txskb(mvm->hw, skb); | 624 | ieee80211_free_txskb(mvm->hw, skb); |
625 | } | 625 | } |
626 | 626 | ||
627 | static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | 627 | static void iwl_mvm_nic_restart(struct iwl_mvm *mvm) |
628 | { | 628 | { |
629 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
630 | |||
631 | iwl_mvm_dump_nic_error_log(mvm); | ||
632 | |||
633 | iwl_abort_notification_waits(&mvm->notif_wait); | 629 | iwl_abort_notification_waits(&mvm->notif_wait); |
634 | 630 | ||
635 | /* | 631 | /* |
@@ -663,9 +659,21 @@ static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | |||
663 | } | 659 | } |
664 | } | 660 | } |
665 | 661 | ||
662 | static void iwl_mvm_nic_error(struct iwl_op_mode *op_mode) | ||
663 | { | ||
664 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
665 | |||
666 | iwl_mvm_dump_nic_error_log(mvm); | ||
667 | |||
668 | iwl_mvm_nic_restart(mvm); | ||
669 | } | ||
670 | |||
666 | static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode) | 671 | static void iwl_mvm_cmd_queue_full(struct iwl_op_mode *op_mode) |
667 | { | 672 | { |
673 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | ||
674 | |||
668 | WARN_ON(1); | 675 | WARN_ON(1); |
676 | iwl_mvm_nic_restart(mvm); | ||
669 | } | 677 | } |
670 | 678 | ||
671 | static const struct iwl_op_mode_ops iwl_mvm_ops = { | 679 | static const struct iwl_op_mode_ops iwl_mvm_ops = { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 3f40ab05bbd8..b0b190d0ec23 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c | |||
@@ -131,33 +131,42 @@ static void iwl_mvm_pass_packet_to_mac80211(struct iwl_mvm *mvm, | |||
131 | static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, | 131 | static int iwl_mvm_calc_rssi(struct iwl_mvm *mvm, |
132 | struct iwl_rx_phy_info *phy_info) | 132 | struct iwl_rx_phy_info *phy_info) |
133 | { | 133 | { |
134 | u32 rssi_a, rssi_b, rssi_c, max_rssi, agc_db; | 134 | int rssi_a, rssi_b, rssi_a_dbm, rssi_b_dbm, max_rssi_dbm; |
135 | int rssi_all_band_a, rssi_all_band_b; | ||
136 | u32 agc_a, agc_b, max_agc; | ||
135 | u32 val; | 137 | u32 val; |
136 | 138 | ||
137 | /* Find max rssi among 3 possible receivers. | 139 | /* Find max rssi among 2 possible receivers. |
138 | * These values are measured by the Digital Signal Processor (DSP). | 140 | * These values are measured by the Digital Signal Processor (DSP). |
139 | * They should stay fairly constant even as the signal strength varies, | 141 | * They should stay fairly constant even as the signal strength varies, |
140 | * if the radio's Automatic Gain Control (AGC) is working right. | 142 | * if the radio's Automatic Gain Control (AGC) is working right. |
141 | * AGC value (see below) will provide the "interesting" info. | 143 | * AGC value (see below) will provide the "interesting" info. |
142 | */ | 144 | */ |
145 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); | ||
146 | agc_a = (val & IWL_OFDM_AGC_A_MSK) >> IWL_OFDM_AGC_A_POS; | ||
147 | agc_b = (val & IWL_OFDM_AGC_B_MSK) >> IWL_OFDM_AGC_B_POS; | ||
148 | max_agc = max_t(u32, agc_a, agc_b); | ||
149 | |||
143 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]); | 150 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_AB_IDX]); |
144 | rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS; | 151 | rssi_a = (val & IWL_OFDM_RSSI_INBAND_A_MSK) >> IWL_OFDM_RSSI_A_POS; |
145 | rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS; | 152 | rssi_b = (val & IWL_OFDM_RSSI_INBAND_B_MSK) >> IWL_OFDM_RSSI_B_POS; |
146 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_RSSI_C_IDX]); | 153 | rssi_all_band_a = (val & IWL_OFDM_RSSI_ALLBAND_A_MSK) >> |
147 | rssi_c = (val & IWL_OFDM_RSSI_INBAND_C_MSK) >> IWL_OFDM_RSSI_C_POS; | 154 | IWL_OFDM_RSSI_ALLBAND_A_POS; |
148 | 155 | rssi_all_band_b = (val & IWL_OFDM_RSSI_ALLBAND_B_MSK) >> | |
149 | val = le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_AGC_IDX]); | 156 | IWL_OFDM_RSSI_ALLBAND_B_POS; |
150 | agc_db = (val & IWL_OFDM_AGC_DB_MSK) >> IWL_OFDM_AGC_DB_POS; | ||
151 | 157 | ||
152 | max_rssi = max_t(u32, rssi_a, rssi_b); | 158 | /* |
153 | max_rssi = max_t(u32, max_rssi, rssi_c); | 159 | * dBm = rssi dB - agc dB - constant. |
160 | * Higher AGC (higher radio gain) means lower signal. | ||
161 | */ | ||
162 | rssi_a_dbm = rssi_a - IWL_RSSI_OFFSET - agc_a; | ||
163 | rssi_b_dbm = rssi_b - IWL_RSSI_OFFSET - agc_b; | ||
164 | max_rssi_dbm = max_t(int, rssi_a_dbm, rssi_b_dbm); | ||
154 | 165 | ||
155 | IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d C %d Max %d AGC dB %d\n", | 166 | IWL_DEBUG_STATS(mvm, "Rssi In A %d B %d Max %d AGCA %d AGCB %d\n", |
156 | rssi_a, rssi_b, rssi_c, max_rssi, agc_db); | 167 | rssi_a_dbm, rssi_b_dbm, max_rssi_dbm, agc_a, agc_b); |
157 | 168 | ||
158 | /* dBm = max_rssi dB - agc dB - constant. | 169 | return max_rssi_dbm; |
159 | * Higher AGC (higher radio gain) means lower signal. */ | ||
160 | return max_rssi - agc_db - IWL_RSSI_OFFSET; | ||
161 | } | 170 | } |
162 | 171 | ||
163 | /* | 172 | /* |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 861a7f9f8e7f..274f44e2ef60 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -770,6 +770,16 @@ int iwl_mvm_sta_tx_agg_stop(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
770 | u16 txq_id; | 770 | u16 txq_id; |
771 | int err; | 771 | int err; |
772 | 772 | ||
773 | |||
774 | /* | ||
775 | * If mac80211 is cleaning its state, then say that we finished since | ||
776 | * our state has been cleared anyway. | ||
777 | */ | ||
778 | if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status)) { | ||
779 | ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); | ||
780 | return 0; | ||
781 | } | ||
782 | |||
773 | spin_lock_bh(&mvmsta->lock); | 783 | spin_lock_bh(&mvmsta->lock); |
774 | 784 | ||
775 | txq_id = tid_data->txq_id; | 785 | txq_id = tid_data->txq_id; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 6b67ce3f679c..6645efe5c03e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -607,12 +607,8 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, | |||
607 | 607 | ||
608 | /* Single frame failure in an AMPDU queue => send BAR */ | 608 | /* Single frame failure in an AMPDU queue => send BAR */ |
609 | if (txq_id >= IWL_FIRST_AMPDU_QUEUE && | 609 | if (txq_id >= IWL_FIRST_AMPDU_QUEUE && |
610 | !(info->flags & IEEE80211_TX_STAT_ACK)) { | 610 | !(info->flags & IEEE80211_TX_STAT_ACK)) |
611 | /* there must be only one skb in the skb_list */ | ||
612 | WARN_ON_ONCE(skb_freed > 1 || | ||
613 | !skb_queue_empty(&skbs)); | ||
614 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; | 611 | info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; |
615 | } | ||
616 | 612 | ||
617 | /* W/A FW bug: seq_ctl is wrong when the queue is flushed */ | 613 | /* W/A FW bug: seq_ctl is wrong when the queue is flushed */ |
618 | if (status == TX_STATUS_FAIL_FIFO_FLUSHED) { | 614 | if (status == TX_STATUS_FAIL_FIFO_FLUSHED) { |
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h index aa2a39a637dd..148843e7f34f 100644 --- a/drivers/net/wireless/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/iwlwifi/pcie/internal.h | |||
@@ -137,10 +137,6 @@ static inline int iwl_queue_dec_wrap(int index, int n_bd) | |||
137 | struct iwl_cmd_meta { | 137 | struct iwl_cmd_meta { |
138 | /* only for SYNC commands, iff the reply skb is wanted */ | 138 | /* only for SYNC commands, iff the reply skb is wanted */ |
139 | struct iwl_host_cmd *source; | 139 | struct iwl_host_cmd *source; |
140 | |||
141 | DEFINE_DMA_UNMAP_ADDR(mapping); | ||
142 | DEFINE_DMA_UNMAP_LEN(len); | ||
143 | |||
144 | u32 flags; | 140 | u32 flags; |
145 | }; | 141 | }; |
146 | 142 | ||
@@ -182,19 +178,39 @@ struct iwl_queue { | |||
182 | #define TFD_TX_CMD_SLOTS 256 | 178 | #define TFD_TX_CMD_SLOTS 256 |
183 | #define TFD_CMD_SLOTS 32 | 179 | #define TFD_CMD_SLOTS 32 |
184 | 180 | ||
181 | /* | ||
182 | * The FH will write back to the first TB only, so we need | ||
183 | * to copy some data into the buffer regardless of whether | ||
184 | * it should be mapped or not. This indicates how big the | ||
185 | * first TB must be to include the scratch buffer. Since | ||
186 | * the scratch is 4 bytes at offset 12, it's 16 now. If we | ||
187 | * make it bigger then allocations will be bigger and copy | ||
188 | * slower, so that's probably not useful. | ||
189 | */ | ||
190 | #define IWL_HCMD_SCRATCHBUF_SIZE 16 | ||
191 | |||
185 | struct iwl_pcie_txq_entry { | 192 | struct iwl_pcie_txq_entry { |
186 | struct iwl_device_cmd *cmd; | 193 | struct iwl_device_cmd *cmd; |
187 | struct iwl_device_cmd *copy_cmd; | ||
188 | struct sk_buff *skb; | 194 | struct sk_buff *skb; |
189 | /* buffer to free after command completes */ | 195 | /* buffer to free after command completes */ |
190 | const void *free_buf; | 196 | const void *free_buf; |
191 | struct iwl_cmd_meta meta; | 197 | struct iwl_cmd_meta meta; |
192 | }; | 198 | }; |
193 | 199 | ||
200 | struct iwl_pcie_txq_scratch_buf { | ||
201 | struct iwl_cmd_header hdr; | ||
202 | u8 buf[8]; | ||
203 | __le32 scratch; | ||
204 | }; | ||
205 | |||
194 | /** | 206 | /** |
195 | * struct iwl_txq - Tx Queue for DMA | 207 | * struct iwl_txq - Tx Queue for DMA |
196 | * @q: generic Rx/Tx queue descriptor | 208 | * @q: generic Rx/Tx queue descriptor |
197 | * @tfds: transmit frame descriptors (DMA memory) | 209 | * @tfds: transmit frame descriptors (DMA memory) |
210 | * @scratchbufs: start of command headers, including scratch buffers, for | ||
211 | * the writeback -- this is DMA memory and an array holding one buffer | ||
212 | * for each command on the queue | ||
213 | * @scratchbufs_dma: DMA address for the scratchbufs start | ||
198 | * @entries: transmit entries (driver state) | 214 | * @entries: transmit entries (driver state) |
199 | * @lock: queue lock | 215 | * @lock: queue lock |
200 | * @stuck_timer: timer that fires if queue gets stuck | 216 | * @stuck_timer: timer that fires if queue gets stuck |
@@ -208,6 +224,8 @@ struct iwl_pcie_txq_entry { | |||
208 | struct iwl_txq { | 224 | struct iwl_txq { |
209 | struct iwl_queue q; | 225 | struct iwl_queue q; |
210 | struct iwl_tfd *tfds; | 226 | struct iwl_tfd *tfds; |
227 | struct iwl_pcie_txq_scratch_buf *scratchbufs; | ||
228 | dma_addr_t scratchbufs_dma; | ||
211 | struct iwl_pcie_txq_entry *entries; | 229 | struct iwl_pcie_txq_entry *entries; |
212 | spinlock_t lock; | 230 | spinlock_t lock; |
213 | struct timer_list stuck_timer; | 231 | struct timer_list stuck_timer; |
@@ -216,6 +234,13 @@ struct iwl_txq { | |||
216 | u8 active; | 234 | u8 active; |
217 | }; | 235 | }; |
218 | 236 | ||
237 | static inline dma_addr_t | ||
238 | iwl_pcie_get_scratchbuf_dma(struct iwl_txq *txq, int idx) | ||
239 | { | ||
240 | return txq->scratchbufs_dma + | ||
241 | sizeof(struct iwl_pcie_txq_scratch_buf) * idx; | ||
242 | } | ||
243 | |||
219 | /** | 244 | /** |
220 | * struct iwl_trans_pcie - PCIe transport specific data | 245 | * struct iwl_trans_pcie - PCIe transport specific data |
221 | * @rxq: all the RX queue data | 246 | * @rxq: all the RX queue data |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index b0ae06d2456f..567e67ad1f61 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -637,22 +637,14 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, | |||
637 | index = SEQ_TO_INDEX(sequence); | 637 | index = SEQ_TO_INDEX(sequence); |
638 | cmd_index = get_cmd_index(&txq->q, index); | 638 | cmd_index = get_cmd_index(&txq->q, index); |
639 | 639 | ||
640 | if (reclaim) { | 640 | if (reclaim) |
641 | struct iwl_pcie_txq_entry *ent; | 641 | cmd = txq->entries[cmd_index].cmd; |
642 | ent = &txq->entries[cmd_index]; | 642 | else |
643 | cmd = ent->copy_cmd; | ||
644 | WARN_ON_ONCE(!cmd && ent->meta.flags & CMD_WANT_HCMD); | ||
645 | } else { | ||
646 | cmd = NULL; | 643 | cmd = NULL; |
647 | } | ||
648 | 644 | ||
649 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); | 645 | err = iwl_op_mode_rx(trans->op_mode, &rxcb, cmd); |
650 | 646 | ||
651 | if (reclaim) { | 647 | if (reclaim) { |
652 | /* The original command isn't needed any more */ | ||
653 | kfree(txq->entries[cmd_index].copy_cmd); | ||
654 | txq->entries[cmd_index].copy_cmd = NULL; | ||
655 | /* nor is the duplicated part of the command */ | ||
656 | kfree(txq->entries[cmd_index].free_buf); | 648 | kfree(txq->entries[cmd_index].free_buf); |
657 | txq->entries[cmd_index].free_buf = NULL; | 649 | txq->entries[cmd_index].free_buf = NULL; |
658 | } | 650 | } |
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c index 8e9e3212fe78..8595c16f74de 100644 --- a/drivers/net/wireless/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/iwlwifi/pcie/tx.c | |||
@@ -191,12 +191,9 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data) | |||
191 | } | 191 | } |
192 | 192 | ||
193 | for (i = q->read_ptr; i != q->write_ptr; | 193 | for (i = q->read_ptr; i != q->write_ptr; |
194 | i = iwl_queue_inc_wrap(i, q->n_bd)) { | 194 | i = iwl_queue_inc_wrap(i, q->n_bd)) |
195 | struct iwl_tx_cmd *tx_cmd = | ||
196 | (struct iwl_tx_cmd *)txq->entries[i].cmd->payload; | ||
197 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, | 195 | IWL_ERR(trans, "scratch %d = 0x%08x\n", i, |
198 | get_unaligned_le32(&tx_cmd->scratch)); | 196 | le32_to_cpu(txq->scratchbufs[i].scratch)); |
199 | } | ||
200 | 197 | ||
201 | iwl_op_mode_nic_error(trans->op_mode); | 198 | iwl_op_mode_nic_error(trans->op_mode); |
202 | } | 199 | } |
@@ -367,8 +364,8 @@ static inline u8 iwl_pcie_tfd_get_num_tbs(struct iwl_tfd *tfd) | |||
367 | } | 364 | } |
368 | 365 | ||
369 | static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, | 366 | static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, |
370 | struct iwl_cmd_meta *meta, struct iwl_tfd *tfd, | 367 | struct iwl_cmd_meta *meta, |
371 | enum dma_data_direction dma_dir) | 368 | struct iwl_tfd *tfd) |
372 | { | 369 | { |
373 | int i; | 370 | int i; |
374 | int num_tbs; | 371 | int num_tbs; |
@@ -382,17 +379,12 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, | |||
382 | return; | 379 | return; |
383 | } | 380 | } |
384 | 381 | ||
385 | /* Unmap tx_cmd */ | 382 | /* first TB is never freed - it's the scratchbuf data */ |
386 | if (num_tbs) | ||
387 | dma_unmap_single(trans->dev, | ||
388 | dma_unmap_addr(meta, mapping), | ||
389 | dma_unmap_len(meta, len), | ||
390 | DMA_BIDIRECTIONAL); | ||
391 | 383 | ||
392 | /* Unmap chunks, if any. */ | ||
393 | for (i = 1; i < num_tbs; i++) | 384 | for (i = 1; i < num_tbs; i++) |
394 | dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i), | 385 | dma_unmap_single(trans->dev, iwl_pcie_tfd_tb_get_addr(tfd, i), |
395 | iwl_pcie_tfd_tb_get_len(tfd, i), dma_dir); | 386 | iwl_pcie_tfd_tb_get_len(tfd, i), |
387 | DMA_TO_DEVICE); | ||
396 | 388 | ||
397 | tfd->num_tbs = 0; | 389 | tfd->num_tbs = 0; |
398 | } | 390 | } |
@@ -406,8 +398,7 @@ static void iwl_pcie_tfd_unmap(struct iwl_trans *trans, | |||
406 | * Does NOT advance any TFD circular buffer read/write indexes | 398 | * Does NOT advance any TFD circular buffer read/write indexes |
407 | * Does NOT free the TFD itself (which is within circular buffer) | 399 | * Does NOT free the TFD itself (which is within circular buffer) |
408 | */ | 400 | */ |
409 | static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, | 401 | static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq) |
410 | enum dma_data_direction dma_dir) | ||
411 | { | 402 | { |
412 | struct iwl_tfd *tfd_tmp = txq->tfds; | 403 | struct iwl_tfd *tfd_tmp = txq->tfds; |
413 | 404 | ||
@@ -418,8 +409,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq, | |||
418 | lockdep_assert_held(&txq->lock); | 409 | lockdep_assert_held(&txq->lock); |
419 | 410 | ||
420 | /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ | 411 | /* We have only q->n_window txq->entries, but we use q->n_bd tfds */ |
421 | iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr], | 412 | iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]); |
422 | dma_dir); | ||
423 | 413 | ||
424 | /* free SKB */ | 414 | /* free SKB */ |
425 | if (txq->entries) { | 415 | if (txq->entries) { |
@@ -479,6 +469,7 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans, | |||
479 | { | 469 | { |
480 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 470 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
481 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; | 471 | size_t tfd_sz = sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX; |
472 | size_t scratchbuf_sz; | ||
482 | int i; | 473 | int i; |
483 | 474 | ||
484 | if (WARN_ON(txq->entries || txq->tfds)) | 475 | if (WARN_ON(txq->entries || txq->tfds)) |
@@ -514,9 +505,25 @@ static int iwl_pcie_txq_alloc(struct iwl_trans *trans, | |||
514 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); | 505 | IWL_ERR(trans, "dma_alloc_coherent(%zd) failed\n", tfd_sz); |
515 | goto error; | 506 | goto error; |
516 | } | 507 | } |
508 | |||
509 | BUILD_BUG_ON(IWL_HCMD_SCRATCHBUF_SIZE != sizeof(*txq->scratchbufs)); | ||
510 | BUILD_BUG_ON(offsetof(struct iwl_pcie_txq_scratch_buf, scratch) != | ||
511 | sizeof(struct iwl_cmd_header) + | ||
512 | offsetof(struct iwl_tx_cmd, scratch)); | ||
513 | |||
514 | scratchbuf_sz = sizeof(*txq->scratchbufs) * slots_num; | ||
515 | |||
516 | txq->scratchbufs = dma_alloc_coherent(trans->dev, scratchbuf_sz, | ||
517 | &txq->scratchbufs_dma, | ||
518 | GFP_KERNEL); | ||
519 | if (!txq->scratchbufs) | ||
520 | goto err_free_tfds; | ||
521 | |||
517 | txq->q.id = txq_id; | 522 | txq->q.id = txq_id; |
518 | 523 | ||
519 | return 0; | 524 | return 0; |
525 | err_free_tfds: | ||
526 | dma_free_coherent(trans->dev, tfd_sz, txq->tfds, txq->q.dma_addr); | ||
520 | error: | 527 | error: |
521 | if (txq->entries && txq_id == trans_pcie->cmd_queue) | 528 | if (txq->entries && txq_id == trans_pcie->cmd_queue) |
522 | for (i = 0; i < slots_num; i++) | 529 | for (i = 0; i < slots_num; i++) |
@@ -565,22 +572,13 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id) | |||
565 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); | 572 | struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); |
566 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; | 573 | struct iwl_txq *txq = &trans_pcie->txq[txq_id]; |
567 | struct iwl_queue *q = &txq->q; | 574 | struct iwl_queue *q = &txq->q; |
568 | enum dma_data_direction dma_dir; | ||
569 | 575 | ||
570 | if (!q->n_bd) | 576 | if (!q->n_bd) |
571 | return; | 577 | return; |
572 | 578 | ||
573 | /* In the command queue, all the TBs are mapped as BIDI | ||
574 | * so unmap them as such. | ||
575 | */ | ||
576 | if (txq_id == trans_pcie->cmd_queue) | ||
577 | dma_dir = DMA_BIDIRECTIONAL; | ||
578 | else | ||
579 | dma_dir = DMA_TO_DEVICE; | ||
580 | |||
581 | spin_lock_bh(&txq->lock); | 579 | spin_lock_bh(&txq->lock); |
582 | while (q->write_ptr != q->read_ptr) { | 580 | while (q->write_ptr != q->read_ptr) { |
583 | iwl_pcie_txq_free_tfd(trans, txq, dma_dir); | 581 | iwl_pcie_txq_free_tfd(trans, txq); |
584 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | 582 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); |
585 | } | 583 | } |
586 | spin_unlock_bh(&txq->lock); | 584 | spin_unlock_bh(&txq->lock); |
@@ -610,7 +608,6 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) | |||
610 | if (txq_id == trans_pcie->cmd_queue) | 608 | if (txq_id == trans_pcie->cmd_queue) |
611 | for (i = 0; i < txq->q.n_window; i++) { | 609 | for (i = 0; i < txq->q.n_window; i++) { |
612 | kfree(txq->entries[i].cmd); | 610 | kfree(txq->entries[i].cmd); |
613 | kfree(txq->entries[i].copy_cmd); | ||
614 | kfree(txq->entries[i].free_buf); | 611 | kfree(txq->entries[i].free_buf); |
615 | } | 612 | } |
616 | 613 | ||
@@ -619,6 +616,10 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id) | |||
619 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * | 616 | dma_free_coherent(dev, sizeof(struct iwl_tfd) * |
620 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); | 617 | txq->q.n_bd, txq->tfds, txq->q.dma_addr); |
621 | txq->q.dma_addr = 0; | 618 | txq->q.dma_addr = 0; |
619 | |||
620 | dma_free_coherent(dev, | ||
621 | sizeof(*txq->scratchbufs) * txq->q.n_window, | ||
622 | txq->scratchbufs, txq->scratchbufs_dma); | ||
622 | } | 623 | } |
623 | 624 | ||
624 | kfree(txq->entries); | 625 | kfree(txq->entries); |
@@ -962,7 +963,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn, | |||
962 | 963 | ||
963 | iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); | 964 | iwl_pcie_txq_inval_byte_cnt_tbl(trans, txq); |
964 | 965 | ||
965 | iwl_pcie_txq_free_tfd(trans, txq, DMA_TO_DEVICE); | 966 | iwl_pcie_txq_free_tfd(trans, txq); |
966 | } | 967 | } |
967 | 968 | ||
968 | iwl_pcie_txq_progress(trans_pcie, txq); | 969 | iwl_pcie_txq_progress(trans_pcie, txq); |
@@ -1152,20 +1153,37 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1152 | void *dup_buf = NULL; | 1153 | void *dup_buf = NULL; |
1153 | dma_addr_t phys_addr; | 1154 | dma_addr_t phys_addr; |
1154 | int idx; | 1155 | int idx; |
1155 | u16 copy_size, cmd_size; | 1156 | u16 copy_size, cmd_size, scratch_size; |
1156 | bool had_nocopy = false; | 1157 | bool had_nocopy = false; |
1157 | int i; | 1158 | int i; |
1158 | u32 cmd_pos; | 1159 | u32 cmd_pos; |
1160 | const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; | ||
1161 | u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; | ||
1159 | 1162 | ||
1160 | copy_size = sizeof(out_cmd->hdr); | 1163 | copy_size = sizeof(out_cmd->hdr); |
1161 | cmd_size = sizeof(out_cmd->hdr); | 1164 | cmd_size = sizeof(out_cmd->hdr); |
1162 | 1165 | ||
1163 | /* need one for the header if the first is NOCOPY */ | 1166 | /* need one for the header if the first is NOCOPY */ |
1164 | BUILD_BUG_ON(IWL_MAX_CMD_TFDS > IWL_NUM_OF_TBS - 1); | 1167 | BUILD_BUG_ON(IWL_MAX_CMD_TBS_PER_TFD > IWL_NUM_OF_TBS - 1); |
1168 | |||
1169 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { | ||
1170 | cmddata[i] = cmd->data[i]; | ||
1171 | cmdlen[i] = cmd->len[i]; | ||
1165 | 1172 | ||
1166 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | ||
1167 | if (!cmd->len[i]) | 1173 | if (!cmd->len[i]) |
1168 | continue; | 1174 | continue; |
1175 | |||
1176 | /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ | ||
1177 | if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { | ||
1178 | int copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; | ||
1179 | |||
1180 | if (copy > cmdlen[i]) | ||
1181 | copy = cmdlen[i]; | ||
1182 | cmdlen[i] -= copy; | ||
1183 | cmddata[i] += copy; | ||
1184 | copy_size += copy; | ||
1185 | } | ||
1186 | |||
1169 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { | 1187 | if (cmd->dataflags[i] & IWL_HCMD_DFL_NOCOPY) { |
1170 | had_nocopy = true; | 1188 | had_nocopy = true; |
1171 | if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { | 1189 | if (WARN_ON(cmd->dataflags[i] & IWL_HCMD_DFL_DUP)) { |
@@ -1185,7 +1203,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1185 | goto free_dup_buf; | 1203 | goto free_dup_buf; |
1186 | } | 1204 | } |
1187 | 1205 | ||
1188 | dup_buf = kmemdup(cmd->data[i], cmd->len[i], | 1206 | dup_buf = kmemdup(cmddata[i], cmdlen[i], |
1189 | GFP_ATOMIC); | 1207 | GFP_ATOMIC); |
1190 | if (!dup_buf) | 1208 | if (!dup_buf) |
1191 | return -ENOMEM; | 1209 | return -ENOMEM; |
@@ -1195,7 +1213,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1195 | idx = -EINVAL; | 1213 | idx = -EINVAL; |
1196 | goto free_dup_buf; | 1214 | goto free_dup_buf; |
1197 | } | 1215 | } |
1198 | copy_size += cmd->len[i]; | 1216 | copy_size += cmdlen[i]; |
1199 | } | 1217 | } |
1200 | cmd_size += cmd->len[i]; | 1218 | cmd_size += cmd->len[i]; |
1201 | } | 1219 | } |
@@ -1242,30 +1260,30 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1242 | 1260 | ||
1243 | /* and copy the data that needs to be copied */ | 1261 | /* and copy the data that needs to be copied */ |
1244 | cmd_pos = offsetof(struct iwl_device_cmd, payload); | 1262 | cmd_pos = offsetof(struct iwl_device_cmd, payload); |
1245 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 1263 | copy_size = sizeof(out_cmd->hdr); |
1246 | if (!cmd->len[i]) | 1264 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { |
1265 | int copy = 0; | ||
1266 | |||
1267 | if (!cmd->len) | ||
1247 | continue; | 1268 | continue; |
1248 | if (cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | ||
1249 | IWL_HCMD_DFL_DUP)) | ||
1250 | break; | ||
1251 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], cmd->len[i]); | ||
1252 | cmd_pos += cmd->len[i]; | ||
1253 | } | ||
1254 | 1269 | ||
1255 | WARN_ON_ONCE(txq->entries[idx].copy_cmd); | 1270 | /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */ |
1271 | if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) { | ||
1272 | copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size; | ||
1256 | 1273 | ||
1257 | /* | 1274 | if (copy > cmd->len[i]) |
1258 | * since out_cmd will be the source address of the FH, it will write | 1275 | copy = cmd->len[i]; |
1259 | * the retry count there. So when the user needs to receivce the HCMD | 1276 | } |
1260 | * that corresponds to the response in the response handler, it needs | 1277 | |
1261 | * to set CMD_WANT_HCMD. | 1278 | /* copy everything if not nocopy/dup */ |
1262 | */ | 1279 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
1263 | if (cmd->flags & CMD_WANT_HCMD) { | 1280 | IWL_HCMD_DFL_DUP))) |
1264 | txq->entries[idx].copy_cmd = | 1281 | copy = cmd->len[i]; |
1265 | kmemdup(out_cmd, cmd_pos, GFP_ATOMIC); | 1282 | |
1266 | if (unlikely(!txq->entries[idx].copy_cmd)) { | 1283 | if (copy) { |
1267 | idx = -ENOMEM; | 1284 | memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy); |
1268 | goto out; | 1285 | cmd_pos += copy; |
1286 | copy_size += copy; | ||
1269 | } | 1287 | } |
1270 | } | 1288 | } |
1271 | 1289 | ||
@@ -1275,22 +1293,35 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1275 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), | 1293 | out_cmd->hdr.cmd, le16_to_cpu(out_cmd->hdr.sequence), |
1276 | cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); | 1294 | cmd_size, q->write_ptr, idx, trans_pcie->cmd_queue); |
1277 | 1295 | ||
1278 | phys_addr = dma_map_single(trans->dev, &out_cmd->hdr, copy_size, | 1296 | /* start the TFD with the scratchbuf */ |
1279 | DMA_BIDIRECTIONAL); | 1297 | scratch_size = min_t(int, copy_size, IWL_HCMD_SCRATCHBUF_SIZE); |
1280 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { | 1298 | memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size); |
1281 | idx = -ENOMEM; | 1299 | iwl_pcie_txq_build_tfd(trans, txq, |
1282 | goto out; | 1300 | iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr), |
1283 | } | 1301 | scratch_size, 1); |
1284 | 1302 | ||
1285 | dma_unmap_addr_set(out_meta, mapping, phys_addr); | 1303 | /* map first command fragment, if any remains */ |
1286 | dma_unmap_len_set(out_meta, len, copy_size); | 1304 | if (copy_size > scratch_size) { |
1305 | phys_addr = dma_map_single(trans->dev, | ||
1306 | ((u8 *)&out_cmd->hdr) + scratch_size, | ||
1307 | copy_size - scratch_size, | ||
1308 | DMA_TO_DEVICE); | ||
1309 | if (dma_mapping_error(trans->dev, phys_addr)) { | ||
1310 | iwl_pcie_tfd_unmap(trans, out_meta, | ||
1311 | &txq->tfds[q->write_ptr]); | ||
1312 | idx = -ENOMEM; | ||
1313 | goto out; | ||
1314 | } | ||
1287 | 1315 | ||
1288 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, copy_size, 1); | 1316 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, |
1317 | copy_size - scratch_size, 0); | ||
1318 | } | ||
1289 | 1319 | ||
1290 | for (i = 0; i < IWL_MAX_CMD_TFDS; i++) { | 1320 | /* map the remaining (adjusted) nocopy/dup fragments */ |
1291 | const void *data = cmd->data[i]; | 1321 | for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) { |
1322 | const void *data = cmddata[i]; | ||
1292 | 1323 | ||
1293 | if (!cmd->len[i]) | 1324 | if (!cmdlen[i]) |
1294 | continue; | 1325 | continue; |
1295 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | | 1326 | if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY | |
1296 | IWL_HCMD_DFL_DUP))) | 1327 | IWL_HCMD_DFL_DUP))) |
@@ -1298,16 +1329,15 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1298 | if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) | 1329 | if (cmd->dataflags[i] & IWL_HCMD_DFL_DUP) |
1299 | data = dup_buf; | 1330 | data = dup_buf; |
1300 | phys_addr = dma_map_single(trans->dev, (void *)data, | 1331 | phys_addr = dma_map_single(trans->dev, (void *)data, |
1301 | cmd->len[i], DMA_BIDIRECTIONAL); | 1332 | cmdlen[i], DMA_TO_DEVICE); |
1302 | if (dma_mapping_error(trans->dev, phys_addr)) { | 1333 | if (dma_mapping_error(trans->dev, phys_addr)) { |
1303 | iwl_pcie_tfd_unmap(trans, out_meta, | 1334 | iwl_pcie_tfd_unmap(trans, out_meta, |
1304 | &txq->tfds[q->write_ptr], | 1335 | &txq->tfds[q->write_ptr]); |
1305 | DMA_BIDIRECTIONAL); | ||
1306 | idx = -ENOMEM; | 1336 | idx = -ENOMEM; |
1307 | goto out; | 1337 | goto out; |
1308 | } | 1338 | } |
1309 | 1339 | ||
1310 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmd->len[i], 0); | 1340 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0); |
1311 | } | 1341 | } |
1312 | 1342 | ||
1313 | out_meta->flags = cmd->flags; | 1343 | out_meta->flags = cmd->flags; |
@@ -1317,8 +1347,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, | |||
1317 | 1347 | ||
1318 | txq->need_update = 1; | 1348 | txq->need_update = 1; |
1319 | 1349 | ||
1320 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, | 1350 | trace_iwlwifi_dev_hcmd(trans->dev, cmd, cmd_size, &out_cmd->hdr); |
1321 | &out_cmd->hdr, copy_size); | ||
1322 | 1351 | ||
1323 | /* start timer if queue currently empty */ | 1352 | /* start timer if queue currently empty */ |
1324 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) | 1353 | if (q->read_ptr == q->write_ptr && trans_pcie->wd_timeout) |
@@ -1377,7 +1406,7 @@ void iwl_pcie_hcmd_complete(struct iwl_trans *trans, | |||
1377 | cmd = txq->entries[cmd_index].cmd; | 1406 | cmd = txq->entries[cmd_index].cmd; |
1378 | meta = &txq->entries[cmd_index].meta; | 1407 | meta = &txq->entries[cmd_index].meta; |
1379 | 1408 | ||
1380 | iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index], DMA_BIDIRECTIONAL); | 1409 | iwl_pcie_tfd_unmap(trans, meta, &txq->tfds[index]); |
1381 | 1410 | ||
1382 | /* Input error checking is done when commands are added to queue. */ | 1411 | /* Input error checking is done when commands are added to queue. */ |
1383 | if (meta->flags & CMD_WANT_SKB) { | 1412 | if (meta->flags & CMD_WANT_SKB) { |
@@ -1556,10 +1585,9 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1556 | struct iwl_cmd_meta *out_meta; | 1585 | struct iwl_cmd_meta *out_meta; |
1557 | struct iwl_txq *txq; | 1586 | struct iwl_txq *txq; |
1558 | struct iwl_queue *q; | 1587 | struct iwl_queue *q; |
1559 | dma_addr_t phys_addr = 0; | 1588 | dma_addr_t tb0_phys, tb1_phys, scratch_phys; |
1560 | dma_addr_t txcmd_phys; | 1589 | void *tb1_addr; |
1561 | dma_addr_t scratch_phys; | 1590 | u16 len, tb1_len, tb2_len; |
1562 | u16 len, firstlen, secondlen; | ||
1563 | u8 wait_write_ptr = 0; | 1591 | u8 wait_write_ptr = 0; |
1564 | __le16 fc = hdr->frame_control; | 1592 | __le16 fc = hdr->frame_control; |
1565 | u8 hdr_len = ieee80211_hdrlen(fc); | 1593 | u8 hdr_len = ieee80211_hdrlen(fc); |
@@ -1597,85 +1625,80 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb, | |||
1597 | cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | | 1625 | cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) | |
1598 | INDEX_TO_SEQ(q->write_ptr))); | 1626 | INDEX_TO_SEQ(q->write_ptr))); |
1599 | 1627 | ||
1628 | tb0_phys = iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr); | ||
1629 | scratch_phys = tb0_phys + sizeof(struct iwl_cmd_header) + | ||
1630 | offsetof(struct iwl_tx_cmd, scratch); | ||
1631 | |||
1632 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1633 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1634 | |||
1600 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ | 1635 | /* Set up first empty entry in queue's array of Tx/cmd buffers */ |
1601 | out_meta = &txq->entries[q->write_ptr].meta; | 1636 | out_meta = &txq->entries[q->write_ptr].meta; |
1602 | 1637 | ||
1603 | /* | 1638 | /* |
1604 | * Use the first empty entry in this queue's command buffer array | 1639 | * The second TB (tb1) points to the remainder of the TX command |
1605 | * to contain the Tx command and MAC header concatenated together | 1640 | * and the 802.11 header - dword aligned size |
1606 | * (payload data will be in another buffer). | 1641 | * (This calculation modifies the TX command, so do it before the |
1607 | * Size of this varies, due to varying MAC header length. | 1642 | * setup of the first TB) |
1608 | * If end is not dword aligned, we'll have 2 extra bytes at the end | ||
1609 | * of the MAC header (device reads on dword boundaries). | ||
1610 | * We'll tell device about this padding later. | ||
1611 | */ | 1643 | */ |
1612 | len = sizeof(struct iwl_tx_cmd) + | 1644 | len = sizeof(struct iwl_tx_cmd) + sizeof(struct iwl_cmd_header) + |
1613 | sizeof(struct iwl_cmd_header) + hdr_len; | 1645 | hdr_len - IWL_HCMD_SCRATCHBUF_SIZE; |
1614 | firstlen = (len + 3) & ~3; | 1646 | tb1_len = (len + 3) & ~3; |
1615 | 1647 | ||
1616 | /* Tell NIC about any 2-byte padding after MAC header */ | 1648 | /* Tell NIC about any 2-byte padding after MAC header */ |
1617 | if (firstlen != len) | 1649 | if (tb1_len != len) |
1618 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; | 1650 | tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK; |
1619 | 1651 | ||
1620 | /* Physical address of this Tx command's header (not MAC header!), | 1652 | /* The first TB points to the scratchbuf data - min_copy bytes */ |
1621 | * within command buffer array. */ | 1653 | memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr, |
1622 | txcmd_phys = dma_map_single(trans->dev, | 1654 | IWL_HCMD_SCRATCHBUF_SIZE); |
1623 | &dev_cmd->hdr, firstlen, | 1655 | iwl_pcie_txq_build_tfd(trans, txq, tb0_phys, |
1624 | DMA_BIDIRECTIONAL); | 1656 | IWL_HCMD_SCRATCHBUF_SIZE, 1); |
1625 | if (unlikely(dma_mapping_error(trans->dev, txcmd_phys))) | ||
1626 | goto out_err; | ||
1627 | dma_unmap_addr_set(out_meta, mapping, txcmd_phys); | ||
1628 | dma_unmap_len_set(out_meta, len, firstlen); | ||
1629 | 1657 | ||
1630 | if (!ieee80211_has_morefrags(fc)) { | 1658 | /* there must be data left over for TB1 or this code must be changed */ |
1631 | txq->need_update = 1; | 1659 | BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE); |
1632 | } else { | 1660 | |
1633 | wait_write_ptr = 1; | 1661 | /* map the data for TB1 */ |
1634 | txq->need_update = 0; | 1662 | tb1_addr = ((u8 *)&dev_cmd->hdr) + IWL_HCMD_SCRATCHBUF_SIZE; |
1635 | } | 1663 | tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE); |
1664 | if (unlikely(dma_mapping_error(trans->dev, tb1_phys))) | ||
1665 | goto out_err; | ||
1666 | iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0); | ||
1636 | 1667 | ||
1637 | /* Set up TFD's 2nd entry to point directly to remainder of skb, | 1668 | /* |
1638 | * if any (802.11 null frames have no payload). */ | 1669 | * Set up TFD's third entry to point directly to remainder |
1639 | secondlen = skb->len - hdr_len; | 1670 | * of skb, if any (802.11 null frames have no payload). |
1640 | if (secondlen > 0) { | 1671 | */ |
1641 | phys_addr = dma_map_single(trans->dev, skb->data + hdr_len, | 1672 | tb2_len = skb->len - hdr_len; |
1642 | secondlen, DMA_TO_DEVICE); | 1673 | if (tb2_len > 0) { |
1643 | if (unlikely(dma_mapping_error(trans->dev, phys_addr))) { | 1674 | dma_addr_t tb2_phys = dma_map_single(trans->dev, |
1644 | dma_unmap_single(trans->dev, | 1675 | skb->data + hdr_len, |
1645 | dma_unmap_addr(out_meta, mapping), | 1676 | tb2_len, DMA_TO_DEVICE); |
1646 | dma_unmap_len(out_meta, len), | 1677 | if (unlikely(dma_mapping_error(trans->dev, tb2_phys))) { |
1647 | DMA_BIDIRECTIONAL); | 1678 | iwl_pcie_tfd_unmap(trans, out_meta, |
1679 | &txq->tfds[q->write_ptr]); | ||
1648 | goto out_err; | 1680 | goto out_err; |
1649 | } | 1681 | } |
1682 | iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0); | ||
1650 | } | 1683 | } |
1651 | 1684 | ||
1652 | /* Attach buffers to TFD */ | ||
1653 | iwl_pcie_txq_build_tfd(trans, txq, txcmd_phys, firstlen, 1); | ||
1654 | if (secondlen > 0) | ||
1655 | iwl_pcie_txq_build_tfd(trans, txq, phys_addr, secondlen, 0); | ||
1656 | |||
1657 | scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) + | ||
1658 | offsetof(struct iwl_tx_cmd, scratch); | ||
1659 | |||
1660 | /* take back ownership of DMA buffer to enable update */ | ||
1661 | dma_sync_single_for_cpu(trans->dev, txcmd_phys, firstlen, | ||
1662 | DMA_BIDIRECTIONAL); | ||
1663 | tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys); | ||
1664 | tx_cmd->dram_msb_ptr = iwl_get_dma_hi_addr(scratch_phys); | ||
1665 | |||
1666 | /* Set up entry for this TFD in Tx byte-count array */ | 1685 | /* Set up entry for this TFD in Tx byte-count array */ |
1667 | iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); | 1686 | iwl_pcie_txq_update_byte_cnt_tbl(trans, txq, le16_to_cpu(tx_cmd->len)); |
1668 | 1687 | ||
1669 | dma_sync_single_for_device(trans->dev, txcmd_phys, firstlen, | ||
1670 | DMA_BIDIRECTIONAL); | ||
1671 | |||
1672 | trace_iwlwifi_dev_tx(trans->dev, skb, | 1688 | trace_iwlwifi_dev_tx(trans->dev, skb, |
1673 | &txq->tfds[txq->q.write_ptr], | 1689 | &txq->tfds[txq->q.write_ptr], |
1674 | sizeof(struct iwl_tfd), | 1690 | sizeof(struct iwl_tfd), |
1675 | &dev_cmd->hdr, firstlen, | 1691 | &dev_cmd->hdr, IWL_HCMD_SCRATCHBUF_SIZE + tb1_len, |
1676 | skb->data + hdr_len, secondlen); | 1692 | skb->data + hdr_len, tb2_len); |
1677 | trace_iwlwifi_dev_tx_data(trans->dev, skb, | 1693 | trace_iwlwifi_dev_tx_data(trans->dev, skb, |
1678 | skb->data + hdr_len, secondlen); | 1694 | skb->data + hdr_len, tb2_len); |
1695 | |||
1696 | if (!ieee80211_has_morefrags(fc)) { | ||
1697 | txq->need_update = 1; | ||
1698 | } else { | ||
1699 | wait_write_ptr = 1; | ||
1700 | txq->need_update = 0; | ||
1701 | } | ||
1679 | 1702 | ||
1680 | /* start timer if queue currently empty */ | 1703 | /* start timer if queue currently empty */ |
1681 | if (txq->need_update && q->read_ptr == q->write_ptr && | 1704 | if (txq->need_update && q->read_ptr == q->write_ptr && |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index 739309e70d8b..45578335e420 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -825,6 +825,11 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) | |||
825 | 825 | ||
826 | sdio_release_host(func); | 826 | sdio_release_host(func); |
827 | 827 | ||
828 | /* Set fw_ready before queuing any commands so that | ||
829 | * lbs_thread won't block from sending them to firmware. | ||
830 | */ | ||
831 | priv->fw_ready = 1; | ||
832 | |||
828 | /* | 833 | /* |
829 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions | 834 | * FUNC_INIT is required for SD8688 WLAN/BT multiple functions |
830 | */ | 835 | */ |
@@ -839,7 +844,6 @@ static void if_sdio_finish_power_on(struct if_sdio_card *card) | |||
839 | netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); | 844 | netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n"); |
840 | } | 845 | } |
841 | 846 | ||
842 | priv->fw_ready = 1; | ||
843 | wake_up(&card->pwron_waitq); | 847 | wake_up(&card->pwron_waitq); |
844 | 848 | ||
845 | if (!card->started) { | 849 | if (!card->started) { |
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 20a6c5555873..b5c8b962ce12 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c | |||
@@ -157,6 +157,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
157 | return -1; | 157 | return -1; |
158 | } | 158 | } |
159 | 159 | ||
160 | cmd_code = le16_to_cpu(host_cmd->command); | ||
161 | cmd_size = le16_to_cpu(host_cmd->size); | ||
162 | |||
163 | if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET && | ||
164 | cmd_code != HostCmd_CMD_FUNC_SHUTDOWN && | ||
165 | cmd_code != HostCmd_CMD_FUNC_INIT) { | ||
166 | dev_err(adapter->dev, | ||
167 | "DNLD_CMD: FW in reset state, ignore cmd %#x\n", | ||
168 | cmd_code); | ||
169 | mwifiex_complete_cmd(adapter, cmd_node); | ||
170 | mwifiex_insert_cmd_to_free_q(adapter, cmd_node); | ||
171 | return -1; | ||
172 | } | ||
173 | |||
160 | /* Set command sequence number */ | 174 | /* Set command sequence number */ |
161 | adapter->seq_num++; | 175 | adapter->seq_num++; |
162 | host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO | 176 | host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO |
@@ -168,9 +182,6 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, | |||
168 | adapter->curr_cmd = cmd_node; | 182 | adapter->curr_cmd = cmd_node; |
169 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); | 183 | spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); |
170 | 184 | ||
171 | cmd_code = le16_to_cpu(host_cmd->command); | ||
172 | cmd_size = le16_to_cpu(host_cmd->size); | ||
173 | |||
174 | /* Adjust skb length */ | 185 | /* Adjust skb length */ |
175 | if (cmd_node->cmd_skb->len > cmd_size) | 186 | if (cmd_node->cmd_skb->len > cmd_size) |
176 | /* | 187 | /* |
@@ -484,8 +495,6 @@ int mwifiex_send_cmd_sync(struct mwifiex_private *priv, uint16_t cmd_no, | |||
484 | 495 | ||
485 | ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, | 496 | ret = mwifiex_send_cmd_async(priv, cmd_no, cmd_action, cmd_oid, |
486 | data_buf); | 497 | data_buf); |
487 | if (!ret) | ||
488 | ret = mwifiex_wait_queue_complete(adapter); | ||
489 | 498 | ||
490 | return ret; | 499 | return ret; |
491 | } | 500 | } |
@@ -588,9 +597,10 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no, | |||
588 | if (cmd_no == HostCmd_CMD_802_11_SCAN) { | 597 | if (cmd_no == HostCmd_CMD_802_11_SCAN) { |
589 | mwifiex_queue_scan_cmd(priv, cmd_node); | 598 | mwifiex_queue_scan_cmd(priv, cmd_node); |
590 | } else { | 599 | } else { |
591 | adapter->cmd_queued = cmd_node; | ||
592 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); | 600 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); |
593 | queue_work(adapter->workqueue, &adapter->main_work); | 601 | queue_work(adapter->workqueue, &adapter->main_work); |
602 | if (cmd_node->wait_q_enabled) | ||
603 | ret = mwifiex_wait_queue_complete(adapter, cmd_node); | ||
594 | } | 604 | } |
595 | 605 | ||
596 | return ret; | 606 | return ret; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index e38aa9b3663d..0ff4c37ab42a 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -709,6 +709,14 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
709 | return ret; | 709 | return ret; |
710 | } | 710 | } |
711 | 711 | ||
712 | /* cancel current command */ | ||
713 | if (adapter->curr_cmd) { | ||
714 | dev_warn(adapter->dev, "curr_cmd is still in processing\n"); | ||
715 | del_timer(&adapter->cmd_timer); | ||
716 | mwifiex_insert_cmd_to_free_q(adapter, adapter->curr_cmd); | ||
717 | adapter->curr_cmd = NULL; | ||
718 | } | ||
719 | |||
712 | /* shut down mwifiex */ | 720 | /* shut down mwifiex */ |
713 | dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); | 721 | dev_dbg(adapter->dev, "info: shutdown mwifiex...\n"); |
714 | 722 | ||
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 246aa62a4817..2fe0ceba4400 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -1117,10 +1117,9 @@ mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, | |||
1117 | adhoc_join->bss_descriptor.bssid, | 1117 | adhoc_join->bss_descriptor.bssid, |
1118 | adhoc_join->bss_descriptor.ssid); | 1118 | adhoc_join->bss_descriptor.ssid); |
1119 | 1119 | ||
1120 | for (i = 0; bss_desc->supported_rates[i] && | 1120 | for (i = 0; i < MWIFIEX_SUPPORTED_RATES && |
1121 | i < MWIFIEX_SUPPORTED_RATES; | 1121 | bss_desc->supported_rates[i]; i++) |
1122 | i++) | 1122 | ; |
1123 | ; | ||
1124 | rates_size = i; | 1123 | rates_size = i; |
1125 | 1124 | ||
1126 | /* Copy Data Rates from the Rates recorded in scan response */ | 1125 | /* Copy Data Rates from the Rates recorded in scan response */ |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 553adfb0aa81..7035ade9af74 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -723,7 +723,6 @@ struct mwifiex_adapter { | |||
723 | u16 cmd_wait_q_required; | 723 | u16 cmd_wait_q_required; |
724 | struct mwifiex_wait_queue cmd_wait_q; | 724 | struct mwifiex_wait_queue cmd_wait_q; |
725 | u8 scan_wait_q_woken; | 725 | u8 scan_wait_q_woken; |
726 | struct cmd_ctrl_node *cmd_queued; | ||
727 | spinlock_t queue_lock; /* lock for tx queues */ | 726 | spinlock_t queue_lock; /* lock for tx queues */ |
728 | struct completion fw_load; | 727 | struct completion fw_load; |
729 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; | 728 | u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; |
@@ -1018,7 +1017,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, | |||
1018 | struct mwifiex_multicast_list *mcast_list); | 1017 | struct mwifiex_multicast_list *mcast_list); |
1019 | int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | 1018 | int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, |
1020 | struct net_device *dev); | 1019 | struct net_device *dev); |
1021 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); | 1020 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, |
1021 | struct cmd_ctrl_node *cmd_queued); | ||
1022 | int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | 1022 | int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, |
1023 | struct cfg80211_ssid *req_ssid); | 1023 | struct cfg80211_ssid *req_ssid); |
1024 | int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); | 1024 | int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 35c79722c361..5c395e2e6a2b 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -302,7 +302,7 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | |||
302 | i++; | 302 | i++; |
303 | usleep_range(10, 20); | 303 | usleep_range(10, 20); |
304 | /* 50ms max wait */ | 304 | /* 50ms max wait */ |
305 | if (i == 50000) | 305 | if (i == 5000) |
306 | break; | 306 | break; |
307 | } | 307 | } |
308 | 308 | ||
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index bb60c2754a97..d215b4d3c51b 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1388,10 +1388,13 @@ int mwifiex_scan_networks(struct mwifiex_private *priv, | |||
1388 | list_del(&cmd_node->list); | 1388 | list_del(&cmd_node->list); |
1389 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1389 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1390 | flags); | 1390 | flags); |
1391 | adapter->cmd_queued = cmd_node; | ||
1392 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, | 1391 | mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, |
1393 | true); | 1392 | true); |
1394 | queue_work(adapter->workqueue, &adapter->main_work); | 1393 | queue_work(adapter->workqueue, &adapter->main_work); |
1394 | |||
1395 | /* Perform internal scan synchronously */ | ||
1396 | if (!priv->scan_request) | ||
1397 | mwifiex_wait_queue_complete(adapter, cmd_node); | ||
1395 | } else { | 1398 | } else { |
1396 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, | 1399 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, |
1397 | flags); | 1400 | flags); |
@@ -1946,9 +1949,6 @@ int mwifiex_request_scan(struct mwifiex_private *priv, | |||
1946 | /* Normal scan */ | 1949 | /* Normal scan */ |
1947 | ret = mwifiex_scan_networks(priv, NULL); | 1950 | ret = mwifiex_scan_networks(priv, NULL); |
1948 | 1951 | ||
1949 | if (!ret) | ||
1950 | ret = mwifiex_wait_queue_complete(priv->adapter); | ||
1951 | |||
1952 | up(&priv->async_sem); | 1952 | up(&priv->async_sem); |
1953 | 1953 | ||
1954 | return ret; | 1954 | return ret; |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 9f33c92c90f5..13100f8de3db 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -54,16 +54,10 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | |||
54 | * This function waits on a cmd wait queue. It also cancels the pending | 54 | * This function waits on a cmd wait queue. It also cancels the pending |
55 | * request after waking up, in case of errors. | 55 | * request after waking up, in case of errors. |
56 | */ | 56 | */ |
57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | 57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, |
58 | struct cmd_ctrl_node *cmd_queued) | ||
58 | { | 59 | { |
59 | int status; | 60 | int status; |
60 | struct cmd_ctrl_node *cmd_queued; | ||
61 | |||
62 | if (!adapter->cmd_queued) | ||
63 | return 0; | ||
64 | |||
65 | cmd_queued = adapter->cmd_queued; | ||
66 | adapter->cmd_queued = NULL; | ||
67 | 61 | ||
68 | dev_dbg(adapter->dev, "cmd pending\n"); | 62 | dev_dbg(adapter->dev, "cmd pending\n"); |
69 | atomic_inc(&adapter->cmd_pending); | 63 | atomic_inc(&adapter->cmd_pending); |
diff --git a/drivers/net/wireless/rt2x00/Kconfig b/drivers/net/wireless/rt2x00/Kconfig index 44d6ead43341..2bf4efa33186 100644 --- a/drivers/net/wireless/rt2x00/Kconfig +++ b/drivers/net/wireless/rt2x00/Kconfig | |||
@@ -55,10 +55,10 @@ config RT61PCI | |||
55 | 55 | ||
56 | config RT2800PCI | 56 | config RT2800PCI |
57 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" | 57 | tristate "Ralink rt27xx/rt28xx/rt30xx (PCI/PCIe/PCMCIA) support" |
58 | depends on PCI || RALINK_RT288X || RALINK_RT305X | 58 | depends on PCI || SOC_RT288X || SOC_RT305X |
59 | select RT2800_LIB | 59 | select RT2800_LIB |
60 | select RT2X00_LIB_PCI if PCI | 60 | select RT2X00_LIB_PCI if PCI |
61 | select RT2X00_LIB_SOC if RALINK_RT288X || RALINK_RT305X | 61 | select RT2X00_LIB_SOC if SOC_RT288X || SOC_RT305X |
62 | select RT2X00_LIB_FIRMWARE | 62 | select RT2X00_LIB_FIRMWARE |
63 | select RT2X00_LIB_CRYPTO | 63 | select RT2X00_LIB_CRYPTO |
64 | select CRC_CCITT | 64 | select CRC_CCITT |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c index 48a01aa21f1c..ded73da4de0b 100644 --- a/drivers/net/wireless/rt2x00/rt2800pci.c +++ b/drivers/net/wireless/rt2x00/rt2800pci.c | |||
@@ -89,7 +89,7 @@ static void rt2800pci_mcu_status(struct rt2x00_dev *rt2x00dev, const u8 token) | |||
89 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); | 89 | rt2x00pci_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0); |
90 | } | 90 | } |
91 | 91 | ||
92 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 92 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
93 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | 93 | static int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) |
94 | { | 94 | { |
95 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); | 95 | void __iomem *base_addr = ioremap(0x1F040000, EEPROM_SIZE); |
@@ -107,7 +107,7 @@ static inline int rt2800pci_read_eeprom_soc(struct rt2x00_dev *rt2x00dev) | |||
107 | { | 107 | { |
108 | return -ENOMEM; | 108 | return -ENOMEM; |
109 | } | 109 | } |
110 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ | 110 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ |
111 | 111 | ||
112 | #ifdef CONFIG_PCI | 112 | #ifdef CONFIG_PCI |
113 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) | 113 | static void rt2800pci_eepromregister_read(struct eeprom_93cx6 *eeprom) |
@@ -1177,7 +1177,7 @@ MODULE_DEVICE_TABLE(pci, rt2800pci_device_table); | |||
1177 | #endif /* CONFIG_PCI */ | 1177 | #endif /* CONFIG_PCI */ |
1178 | MODULE_LICENSE("GPL"); | 1178 | MODULE_LICENSE("GPL"); |
1179 | 1179 | ||
1180 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1180 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1181 | static int rt2800soc_probe(struct platform_device *pdev) | 1181 | static int rt2800soc_probe(struct platform_device *pdev) |
1182 | { | 1182 | { |
1183 | return rt2x00soc_probe(pdev, &rt2800pci_ops); | 1183 | return rt2x00soc_probe(pdev, &rt2800pci_ops); |
@@ -1194,7 +1194,7 @@ static struct platform_driver rt2800soc_driver = { | |||
1194 | .suspend = rt2x00soc_suspend, | 1194 | .suspend = rt2x00soc_suspend, |
1195 | .resume = rt2x00soc_resume, | 1195 | .resume = rt2x00soc_resume, |
1196 | }; | 1196 | }; |
1197 | #endif /* CONFIG_RALINK_RT288X || CONFIG_RALINK_RT305X */ | 1197 | #endif /* CONFIG_SOC_RT288X || CONFIG_SOC_RT305X */ |
1198 | 1198 | ||
1199 | #ifdef CONFIG_PCI | 1199 | #ifdef CONFIG_PCI |
1200 | static int rt2800pci_probe(struct pci_dev *pci_dev, | 1200 | static int rt2800pci_probe(struct pci_dev *pci_dev, |
@@ -1217,7 +1217,7 @@ static int __init rt2800pci_init(void) | |||
1217 | { | 1217 | { |
1218 | int ret = 0; | 1218 | int ret = 0; |
1219 | 1219 | ||
1220 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1220 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1221 | ret = platform_driver_register(&rt2800soc_driver); | 1221 | ret = platform_driver_register(&rt2800soc_driver); |
1222 | if (ret) | 1222 | if (ret) |
1223 | return ret; | 1223 | return ret; |
@@ -1225,7 +1225,7 @@ static int __init rt2800pci_init(void) | |||
1225 | #ifdef CONFIG_PCI | 1225 | #ifdef CONFIG_PCI |
1226 | ret = pci_register_driver(&rt2800pci_driver); | 1226 | ret = pci_register_driver(&rt2800pci_driver); |
1227 | if (ret) { | 1227 | if (ret) { |
1228 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1228 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1229 | platform_driver_unregister(&rt2800soc_driver); | 1229 | platform_driver_unregister(&rt2800soc_driver); |
1230 | #endif | 1230 | #endif |
1231 | return ret; | 1231 | return ret; |
@@ -1240,7 +1240,7 @@ static void __exit rt2800pci_exit(void) | |||
1240 | #ifdef CONFIG_PCI | 1240 | #ifdef CONFIG_PCI |
1241 | pci_unregister_driver(&rt2800pci_driver); | 1241 | pci_unregister_driver(&rt2800pci_driver); |
1242 | #endif | 1242 | #endif |
1243 | #if defined(CONFIG_RALINK_RT288X) || defined(CONFIG_RALINK_RT305X) | 1243 | #if defined(CONFIG_SOC_RT288X) || defined(CONFIG_SOC_RT305X) |
1244 | platform_driver_unregister(&rt2800soc_driver); | 1244 | platform_driver_unregister(&rt2800soc_driver); |
1245 | #endif | 1245 | #endif |
1246 | } | 1246 | } |
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index 1031db66474a..189744db65e0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -1236,8 +1236,10 @@ static inline void rt2x00lib_set_if_combinations(struct rt2x00_dev *rt2x00dev) | |||
1236 | */ | 1236 | */ |
1237 | if_limit = &rt2x00dev->if_limits_ap; | 1237 | if_limit = &rt2x00dev->if_limits_ap; |
1238 | if_limit->max = rt2x00dev->ops->max_ap_intf; | 1238 | if_limit->max = rt2x00dev->ops->max_ap_intf; |
1239 | if_limit->types = BIT(NL80211_IFTYPE_AP) | | 1239 | if_limit->types = BIT(NL80211_IFTYPE_AP); |
1240 | BIT(NL80211_IFTYPE_MESH_POINT); | 1240 | #ifdef CONFIG_MAC80211_MESH |
1241 | if_limit->types |= BIT(NL80211_IFTYPE_MESH_POINT); | ||
1242 | #endif | ||
1241 | 1243 | ||
1242 | /* | 1244 | /* |
1243 | * Build up AP interface combinations structure. | 1245 | * Build up AP interface combinations structure. |
@@ -1309,7 +1311,9 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev) | |||
1309 | rt2x00dev->hw->wiphy->interface_modes |= | 1311 | rt2x00dev->hw->wiphy->interface_modes |= |
1310 | BIT(NL80211_IFTYPE_ADHOC) | | 1312 | BIT(NL80211_IFTYPE_ADHOC) | |
1311 | BIT(NL80211_IFTYPE_AP) | | 1313 | BIT(NL80211_IFTYPE_AP) | |
1314 | #ifdef CONFIG_MAC80211_MESH | ||
1312 | BIT(NL80211_IFTYPE_MESH_POINT) | | 1315 | BIT(NL80211_IFTYPE_MESH_POINT) | |
1316 | #endif | ||
1313 | BIT(NL80211_IFTYPE_WDS); | 1317 | BIT(NL80211_IFTYPE_WDS); |
1314 | 1318 | ||
1315 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 1319 | rt2x00dev->hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index b1ccff474c79..c08d0f4c5f3d 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -1377,74 +1377,57 @@ void rtl92cu_card_disable(struct ieee80211_hw *hw) | |||
1377 | 1377 | ||
1378 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) | 1378 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid) |
1379 | { | 1379 | { |
1380 | /* dummy routine needed for callback from rtl_op_configure_filter() */ | ||
1381 | } | ||
1382 | |||
1383 | /*========================================================================== */ | ||
1384 | |||
1385 | static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw, | ||
1386 | enum nl80211_iftype type) | ||
1387 | { | ||
1388 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1380 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1389 | u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); | ||
1390 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); | 1381 | struct rtl_hal *rtlhal = rtl_hal(rtlpriv); |
1391 | struct rtl_phy *rtlphy = &(rtlpriv->phy); | 1382 | u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR); |
1392 | u8 filterout_non_associated_bssid = false; | ||
1393 | 1383 | ||
1394 | switch (type) { | 1384 | if (rtlpriv->psc.rfpwr_state != ERFON) |
1395 | case NL80211_IFTYPE_ADHOC: | 1385 | return; |
1396 | case NL80211_IFTYPE_STATION: | 1386 | |
1397 | filterout_non_associated_bssid = true; | 1387 | if (check_bssid) { |
1398 | break; | 1388 | u8 tmp; |
1399 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1400 | case NL80211_IFTYPE_AP: | ||
1401 | default: | ||
1402 | break; | ||
1403 | } | ||
1404 | if (filterout_non_associated_bssid) { | ||
1405 | if (IS_NORMAL_CHIP(rtlhal->version)) { | 1389 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1406 | switch (rtlphy->current_io_type) { | 1390 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
1407 | case IO_CMD_RESUME_DM_BY_SCAN: | 1391 | tmp = BIT(4); |
1408 | reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN); | ||
1409 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1410 | HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1411 | /* enable update TSF */ | ||
1412 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); | ||
1413 | break; | ||
1414 | case IO_CMD_PAUSE_DM_BY_SCAN: | ||
1415 | reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); | ||
1416 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1417 | HW_VAR_RCR, (u8 *)(®_rcr)); | ||
1418 | /* disable update TSF */ | ||
1419 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
1420 | break; | ||
1421 | } | ||
1422 | } else { | 1392 | } else { |
1423 | reg_rcr |= (RCR_CBSSID); | 1393 | reg_rcr |= RCR_CBSSID; |
1424 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | 1394 | tmp = BIT(4) | BIT(5); |
1425 | (u8 *)(®_rcr)); | ||
1426 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5))); | ||
1427 | } | 1395 | } |
1428 | } else if (filterout_non_associated_bssid == false) { | 1396 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, |
1397 | (u8 *) (®_rcr)); | ||
1398 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, tmp); | ||
1399 | } else { | ||
1400 | u8 tmp; | ||
1429 | if (IS_NORMAL_CHIP(rtlhal->version)) { | 1401 | if (IS_NORMAL_CHIP(rtlhal->version)) { |
1430 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); | 1402 | reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN); |
1431 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | 1403 | tmp = BIT(4); |
1432 | (u8 *)(®_rcr)); | ||
1433 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0); | ||
1434 | } else { | 1404 | } else { |
1435 | reg_rcr &= (~RCR_CBSSID); | 1405 | reg_rcr &= ~RCR_CBSSID; |
1436 | rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR, | 1406 | tmp = BIT(4) | BIT(5); |
1437 | (u8 *)(®_rcr)); | ||
1438 | _rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0); | ||
1439 | } | 1407 | } |
1408 | reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN)); | ||
1409 | rtlpriv->cfg->ops->set_hw_reg(hw, | ||
1410 | HW_VAR_RCR, (u8 *) (®_rcr)); | ||
1411 | _rtl92cu_set_bcn_ctrl_reg(hw, tmp, 0); | ||
1440 | } | 1412 | } |
1441 | } | 1413 | } |
1442 | 1414 | ||
1415 | /*========================================================================== */ | ||
1416 | |||
1443 | int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) | 1417 | int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type) |
1444 | { | 1418 | { |
1419 | struct rtl_priv *rtlpriv = rtl_priv(hw); | ||
1420 | |||
1445 | if (_rtl92cu_set_media_status(hw, type)) | 1421 | if (_rtl92cu_set_media_status(hw, type)) |
1446 | return -EOPNOTSUPP; | 1422 | return -EOPNOTSUPP; |
1447 | _rtl92cu_set_check_bssid(hw, type); | 1423 | |
1424 | if (rtlpriv->mac80211.link_state == MAC80211_LINKED) { | ||
1425 | if (type != NL80211_IFTYPE_AP) | ||
1426 | rtl92cu_set_check_bssid(hw, true); | ||
1427 | } else { | ||
1428 | rtl92cu_set_check_bssid(hw, false); | ||
1429 | } | ||
1430 | |||
1448 | return 0; | 1431 | return 0; |
1449 | } | 1432 | } |
1450 | 1433 | ||
@@ -2058,8 +2041,6 @@ void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw, | |||
2058 | (shortgi_rate << 4) | (shortgi_rate); | 2041 | (shortgi_rate << 4) | (shortgi_rate); |
2059 | } | 2042 | } |
2060 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); | 2043 | rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value); |
2061 | RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, "%x\n", | ||
2062 | rtl_read_dword(rtlpriv, REG_ARFR0)); | ||
2063 | } | 2044 | } |
2064 | 2045 | ||
2065 | void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) | 2046 | void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level) |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 156b52732f3d..5847d6d0881e 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -851,6 +851,7 @@ static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
851 | if (unlikely(!_urb)) { | 851 | if (unlikely(!_urb)) { |
852 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 852 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, |
853 | "Can't allocate urb. Drop skb!\n"); | 853 | "Can't allocate urb. Drop skb!\n"); |
854 | kfree_skb(skb); | ||
854 | return; | 855 | return; |
855 | } | 856 | } |
856 | _rtl_submit_tx_urb(hw, _urb); | 857 | _rtl_submit_tx_urb(hw, _urb); |
diff --git a/drivers/of/base.c b/drivers/of/base.c index 321d3ef05006..c6443de58fb0 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c | |||
@@ -746,6 +746,64 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
746 | EXPORT_SYMBOL(of_find_node_by_phandle); | 746 | EXPORT_SYMBOL(of_find_node_by_phandle); |
747 | 747 | ||
748 | /** | 748 | /** |
749 | * of_find_property_value_of_size | ||
750 | * | ||
751 | * @np: device node from which the property value is to be read. | ||
752 | * @propname: name of the property to be searched. | ||
753 | * @len: requested length of property value | ||
754 | * | ||
755 | * Search for a property in a device node and valid the requested size. | ||
756 | * Returns the property value on success, -EINVAL if the property does not | ||
757 | * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
758 | * property data isn't large enough. | ||
759 | * | ||
760 | */ | ||
761 | static void *of_find_property_value_of_size(const struct device_node *np, | ||
762 | const char *propname, u32 len) | ||
763 | { | ||
764 | struct property *prop = of_find_property(np, propname, NULL); | ||
765 | |||
766 | if (!prop) | ||
767 | return ERR_PTR(-EINVAL); | ||
768 | if (!prop->value) | ||
769 | return ERR_PTR(-ENODATA); | ||
770 | if (len > prop->length) | ||
771 | return ERR_PTR(-EOVERFLOW); | ||
772 | |||
773 | return prop->value; | ||
774 | } | ||
775 | |||
776 | /** | ||
777 | * of_property_read_u32_index - Find and read a u32 from a multi-value property. | ||
778 | * | ||
779 | * @np: device node from which the property value is to be read. | ||
780 | * @propname: name of the property to be searched. | ||
781 | * @index: index of the u32 in the list of values | ||
782 | * @out_value: pointer to return value, modified only if no error. | ||
783 | * | ||
784 | * Search for a property in a device node and read nth 32-bit value from | ||
785 | * it. Returns 0 on success, -EINVAL if the property does not exist, | ||
786 | * -ENODATA if property does not have a value, and -EOVERFLOW if the | ||
787 | * property data isn't large enough. | ||
788 | * | ||
789 | * The out_value is modified only if a valid u32 value can be decoded. | ||
790 | */ | ||
791 | int of_property_read_u32_index(const struct device_node *np, | ||
792 | const char *propname, | ||
793 | u32 index, u32 *out_value) | ||
794 | { | ||
795 | const u32 *val = of_find_property_value_of_size(np, propname, | ||
796 | ((index + 1) * sizeof(*out_value))); | ||
797 | |||
798 | if (IS_ERR(val)) | ||
799 | return PTR_ERR(val); | ||
800 | |||
801 | *out_value = be32_to_cpup(((__be32 *)val) + index); | ||
802 | return 0; | ||
803 | } | ||
804 | EXPORT_SYMBOL_GPL(of_property_read_u32_index); | ||
805 | |||
806 | /** | ||
749 | * of_property_read_u8_array - Find and read an array of u8 from a property. | 807 | * of_property_read_u8_array - Find and read an array of u8 from a property. |
750 | * | 808 | * |
751 | * @np: device node from which the property value is to be read. | 809 | * @np: device node from which the property value is to be read. |
@@ -766,17 +824,12 @@ EXPORT_SYMBOL(of_find_node_by_phandle); | |||
766 | int of_property_read_u8_array(const struct device_node *np, | 824 | int of_property_read_u8_array(const struct device_node *np, |
767 | const char *propname, u8 *out_values, size_t sz) | 825 | const char *propname, u8 *out_values, size_t sz) |
768 | { | 826 | { |
769 | struct property *prop = of_find_property(np, propname, NULL); | 827 | const u8 *val = of_find_property_value_of_size(np, propname, |
770 | const u8 *val; | 828 | (sz * sizeof(*out_values))); |
771 | 829 | ||
772 | if (!prop) | 830 | if (IS_ERR(val)) |
773 | return -EINVAL; | 831 | return PTR_ERR(val); |
774 | if (!prop->value) | ||
775 | return -ENODATA; | ||
776 | if ((sz * sizeof(*out_values)) > prop->length) | ||
777 | return -EOVERFLOW; | ||
778 | 832 | ||
779 | val = prop->value; | ||
780 | while (sz--) | 833 | while (sz--) |
781 | *out_values++ = *val++; | 834 | *out_values++ = *val++; |
782 | return 0; | 835 | return 0; |
@@ -804,17 +857,12 @@ EXPORT_SYMBOL_GPL(of_property_read_u8_array); | |||
804 | int of_property_read_u16_array(const struct device_node *np, | 857 | int of_property_read_u16_array(const struct device_node *np, |
805 | const char *propname, u16 *out_values, size_t sz) | 858 | const char *propname, u16 *out_values, size_t sz) |
806 | { | 859 | { |
807 | struct property *prop = of_find_property(np, propname, NULL); | 860 | const __be16 *val = of_find_property_value_of_size(np, propname, |
808 | const __be16 *val; | 861 | (sz * sizeof(*out_values))); |
809 | 862 | ||
810 | if (!prop) | 863 | if (IS_ERR(val)) |
811 | return -EINVAL; | 864 | return PTR_ERR(val); |
812 | if (!prop->value) | ||
813 | return -ENODATA; | ||
814 | if ((sz * sizeof(*out_values)) > prop->length) | ||
815 | return -EOVERFLOW; | ||
816 | 865 | ||
817 | val = prop->value; | ||
818 | while (sz--) | 866 | while (sz--) |
819 | *out_values++ = be16_to_cpup(val++); | 867 | *out_values++ = be16_to_cpup(val++); |
820 | return 0; | 868 | return 0; |
@@ -841,17 +889,12 @@ int of_property_read_u32_array(const struct device_node *np, | |||
841 | const char *propname, u32 *out_values, | 889 | const char *propname, u32 *out_values, |
842 | size_t sz) | 890 | size_t sz) |
843 | { | 891 | { |
844 | struct property *prop = of_find_property(np, propname, NULL); | 892 | const __be32 *val = of_find_property_value_of_size(np, propname, |
845 | const __be32 *val; | 893 | (sz * sizeof(*out_values))); |
846 | 894 | ||
847 | if (!prop) | 895 | if (IS_ERR(val)) |
848 | return -EINVAL; | 896 | return PTR_ERR(val); |
849 | if (!prop->value) | ||
850 | return -ENODATA; | ||
851 | if ((sz * sizeof(*out_values)) > prop->length) | ||
852 | return -EOVERFLOW; | ||
853 | 897 | ||
854 | val = prop->value; | ||
855 | while (sz--) | 898 | while (sz--) |
856 | *out_values++ = be32_to_cpup(val++); | 899 | *out_values++ = be32_to_cpup(val++); |
857 | return 0; | 900 | return 0; |
@@ -874,15 +917,13 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_array); | |||
874 | int of_property_read_u64(const struct device_node *np, const char *propname, | 917 | int of_property_read_u64(const struct device_node *np, const char *propname, |
875 | u64 *out_value) | 918 | u64 *out_value) |
876 | { | 919 | { |
877 | struct property *prop = of_find_property(np, propname, NULL); | 920 | const __be32 *val = of_find_property_value_of_size(np, propname, |
921 | sizeof(*out_value)); | ||
878 | 922 | ||
879 | if (!prop) | 923 | if (IS_ERR(val)) |
880 | return -EINVAL; | 924 | return PTR_ERR(val); |
881 | if (!prop->value) | 925 | |
882 | return -ENODATA; | 926 | *out_value = of_read_number(val, 2); |
883 | if (sizeof(*out_value) > prop->length) | ||
884 | return -EOVERFLOW; | ||
885 | *out_value = of_read_number(prop->value, 2); | ||
886 | return 0; | 927 | return 0; |
887 | } | 928 | } |
888 | EXPORT_SYMBOL_GPL(of_property_read_u64); | 929 | EXPORT_SYMBOL_GPL(of_property_read_u64); |
diff --git a/drivers/oprofile/oprofilefs.c b/drivers/oprofile/oprofilefs.c index 445ffda715ad..7c12d9c2b230 100644 --- a/drivers/oprofile/oprofilefs.c +++ b/drivers/oprofile/oprofilefs.c | |||
@@ -276,6 +276,7 @@ static struct file_system_type oprofilefs_type = { | |||
276 | .mount = oprofilefs_mount, | 276 | .mount = oprofilefs_mount, |
277 | .kill_sb = kill_litter_super, | 277 | .kill_sb = kill_litter_super, |
278 | }; | 278 | }; |
279 | MODULE_ALIAS_FS("oprofilefs"); | ||
279 | 280 | ||
280 | 281 | ||
281 | int __init oprofilefs_register(void) | 282 | int __init oprofilefs_register(void) |
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c index 39c937f9b426..dee5dddaa292 100644 --- a/drivers/pci/pci-acpi.c +++ b/drivers/pci/pci-acpi.c | |||
@@ -331,8 +331,14 @@ static void pci_acpi_cleanup(struct device *dev) | |||
331 | } | 331 | } |
332 | } | 332 | } |
333 | 333 | ||
334 | static bool pci_acpi_bus_match(struct device *dev) | ||
335 | { | ||
336 | return dev->bus == &pci_bus_type; | ||
337 | } | ||
338 | |||
334 | static struct acpi_bus_type acpi_pci_bus = { | 339 | static struct acpi_bus_type acpi_pci_bus = { |
335 | .bus = &pci_bus_type, | 340 | .name = "PCI", |
341 | .match = pci_acpi_bus_match, | ||
336 | .find_device = acpi_pci_find_device, | 342 | .find_device = acpi_pci_find_device, |
337 | .setup = pci_acpi_setup, | 343 | .setup = pci_acpi_setup, |
338 | .cleanup = pci_acpi_cleanup, | 344 | .cleanup = pci_acpi_cleanup, |
diff --git a/drivers/pci/rom.c b/drivers/pci/rom.c index ab886b7ee327..b41ac7756a4b 100644 --- a/drivers/pci/rom.c +++ b/drivers/pci/rom.c | |||
@@ -100,6 +100,27 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) | |||
100 | return min((size_t)(image - rom), size); | 100 | return min((size_t)(image - rom), size); |
101 | } | 101 | } |
102 | 102 | ||
103 | static loff_t pci_find_rom(struct pci_dev *pdev, size_t *size) | ||
104 | { | ||
105 | struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; | ||
106 | loff_t start; | ||
107 | |||
108 | /* assign the ROM an address if it doesn't have one */ | ||
109 | if (res->parent == NULL && pci_assign_resource(pdev, PCI_ROM_RESOURCE)) | ||
110 | return 0; | ||
111 | start = pci_resource_start(pdev, PCI_ROM_RESOURCE); | ||
112 | *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); | ||
113 | |||
114 | if (*size == 0) | ||
115 | return 0; | ||
116 | |||
117 | /* Enable ROM space decodes */ | ||
118 | if (pci_enable_rom(pdev)) | ||
119 | return 0; | ||
120 | |||
121 | return start; | ||
122 | } | ||
123 | |||
103 | /** | 124 | /** |
104 | * pci_map_rom - map a PCI ROM to kernel space | 125 | * pci_map_rom - map a PCI ROM to kernel space |
105 | * @pdev: pointer to pci device struct | 126 | * @pdev: pointer to pci device struct |
@@ -114,21 +135,15 @@ size_t pci_get_rom_size(struct pci_dev *pdev, void __iomem *rom, size_t size) | |||
114 | void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | 135 | void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) |
115 | { | 136 | { |
116 | struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; | 137 | struct resource *res = &pdev->resource[PCI_ROM_RESOURCE]; |
117 | loff_t start; | 138 | loff_t start = 0; |
118 | void __iomem *rom; | 139 | void __iomem *rom; |
119 | 140 | ||
120 | /* | 141 | /* |
121 | * Some devices may provide ROMs via a source other than the BAR | ||
122 | */ | ||
123 | if (pdev->rom && pdev->romlen) { | ||
124 | *size = pdev->romlen; | ||
125 | return phys_to_virt(pdev->rom); | ||
126 | /* | ||
127 | * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy | 142 | * IORESOURCE_ROM_SHADOW set on x86, x86_64 and IA64 supports legacy |
128 | * memory map if the VGA enable bit of the Bridge Control register is | 143 | * memory map if the VGA enable bit of the Bridge Control register is |
129 | * set for embedded VGA. | 144 | * set for embedded VGA. |
130 | */ | 145 | */ |
131 | } else if (res->flags & IORESOURCE_ROM_SHADOW) { | 146 | if (res->flags & IORESOURCE_ROM_SHADOW) { |
132 | /* primary video rom always starts here */ | 147 | /* primary video rom always starts here */ |
133 | start = (loff_t)0xC0000; | 148 | start = (loff_t)0xC0000; |
134 | *size = 0x20000; /* cover C000:0 through E000:0 */ | 149 | *size = 0x20000; /* cover C000:0 through E000:0 */ |
@@ -139,21 +154,21 @@ void __iomem *pci_map_rom(struct pci_dev *pdev, size_t *size) | |||
139 | return (void __iomem *)(unsigned long) | 154 | return (void __iomem *)(unsigned long) |
140 | pci_resource_start(pdev, PCI_ROM_RESOURCE); | 155 | pci_resource_start(pdev, PCI_ROM_RESOURCE); |
141 | } else { | 156 | } else { |
142 | /* assign the ROM an address if it doesn't have one */ | 157 | start = pci_find_rom(pdev, size); |
143 | if (res->parent == NULL && | ||
144 | pci_assign_resource(pdev,PCI_ROM_RESOURCE)) | ||
145 | return NULL; | ||
146 | start = pci_resource_start(pdev, PCI_ROM_RESOURCE); | ||
147 | *size = pci_resource_len(pdev, PCI_ROM_RESOURCE); | ||
148 | if (*size == 0) | ||
149 | return NULL; | ||
150 | |||
151 | /* Enable ROM space decodes */ | ||
152 | if (pci_enable_rom(pdev)) | ||
153 | return NULL; | ||
154 | } | 158 | } |
155 | } | 159 | } |
156 | 160 | ||
161 | /* | ||
162 | * Some devices may provide ROMs via a source other than the BAR | ||
163 | */ | ||
164 | if (!start && pdev->rom && pdev->romlen) { | ||
165 | *size = pdev->romlen; | ||
166 | return phys_to_virt(pdev->rom); | ||
167 | } | ||
168 | |||
169 | if (!start) | ||
170 | return NULL; | ||
171 | |||
157 | rom = ioremap(start, *size); | 172 | rom = ioremap(start, *size); |
158 | if (!rom) { | 173 | if (!rom) { |
159 | /* restore enable if ioremap fails */ | 174 | /* restore enable if ioremap fails */ |
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 34f51d2d90d2..35e94009829b 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -229,6 +229,7 @@ config PINCTRL_EXYNOS5440 | |||
229 | source "drivers/pinctrl/mvebu/Kconfig" | 229 | source "drivers/pinctrl/mvebu/Kconfig" |
230 | source "drivers/pinctrl/sh-pfc/Kconfig" | 230 | source "drivers/pinctrl/sh-pfc/Kconfig" |
231 | source "drivers/pinctrl/spear/Kconfig" | 231 | source "drivers/pinctrl/spear/Kconfig" |
232 | source "drivers/pinctrl/vt8500/Kconfig" | ||
232 | 233 | ||
233 | config PINCTRL_XWAY | 234 | config PINCTRL_XWAY |
234 | bool | 235 | bool |
diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index f82cc5baf767..a5a52c83c13a 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile | |||
@@ -52,3 +52,4 @@ obj-$(CONFIG_PLAT_ORION) += mvebu/ | |||
52 | obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/ | 52 | obj-$(CONFIG_ARCH_SHMOBILE) += sh-pfc/ |
53 | obj-$(CONFIG_SUPERH) += sh-pfc/ | 53 | obj-$(CONFIG_SUPERH) += sh-pfc/ |
54 | obj-$(CONFIG_PLAT_SPEAR) += spear/ | 54 | obj-$(CONFIG_PLAT_SPEAR) += spear/ |
55 | obj-$(CONFIG_ARCH_VT8500) += vt8500/ | ||
diff --git a/drivers/pinctrl/mvebu/pinctrl-mvebu.c b/drivers/pinctrl/mvebu/pinctrl-mvebu.c index c689c04a4f52..2d2f0a43d36b 100644 --- a/drivers/pinctrl/mvebu/pinctrl-mvebu.c +++ b/drivers/pinctrl/mvebu/pinctrl-mvebu.c | |||
@@ -620,7 +620,7 @@ int mvebu_pinctrl_probe(struct platform_device *pdev) | |||
620 | 620 | ||
621 | /* special soc specific control */ | 621 | /* special soc specific control */ |
622 | if (ctrl->mpp_get || ctrl->mpp_set) { | 622 | if (ctrl->mpp_get || ctrl->mpp_set) { |
623 | if (!ctrl->name || !ctrl->mpp_set || !ctrl->mpp_set) { | 623 | if (!ctrl->name || !ctrl->mpp_get || !ctrl->mpp_set) { |
624 | dev_err(&pdev->dev, "wrong soc control info\n"); | 624 | dev_err(&pdev->dev, "wrong soc control info\n"); |
625 | return -EINVAL; | 625 | return -EINVAL; |
626 | } | 626 | } |
diff --git a/drivers/pinctrl/pinconf.c b/drivers/pinctrl/pinconf.c index ac8d382a79bb..d611ecfcbf70 100644 --- a/drivers/pinctrl/pinconf.c +++ b/drivers/pinctrl/pinconf.c | |||
@@ -622,7 +622,7 @@ static const struct file_operations pinconf_dbg_pinname_fops = { | |||
622 | static int pinconf_dbg_state_print(struct seq_file *s, void *d) | 622 | static int pinconf_dbg_state_print(struct seq_file *s, void *d) |
623 | { | 623 | { |
624 | if (strlen(dbg_state_name)) | 624 | if (strlen(dbg_state_name)) |
625 | seq_printf(s, "%s\n", dbg_pinname); | 625 | seq_printf(s, "%s\n", dbg_state_name); |
626 | else | 626 | else |
627 | seq_printf(s, "No pin state set\n"); | 627 | seq_printf(s, "No pin state set\n"); |
628 | return 0; | 628 | return 0; |
diff --git a/drivers/pinctrl/pinconf.h b/drivers/pinctrl/pinconf.h index e3ed8cb072a5..bfda73d64eed 100644 --- a/drivers/pinctrl/pinconf.h +++ b/drivers/pinctrl/pinconf.h | |||
@@ -90,7 +90,7 @@ static inline void pinconf_init_device_debugfs(struct dentry *devroot, | |||
90 | * pin config. | 90 | * pin config. |
91 | */ | 91 | */ |
92 | 92 | ||
93 | #ifdef CONFIG_GENERIC_PINCONF | 93 | #if defined(CONFIG_GENERIC_PINCONF) && defined(CONFIG_DEBUG_FS) |
94 | 94 | ||
95 | void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, | 95 | void pinconf_generic_dump_pin(struct pinctrl_dev *pctldev, |
96 | struct seq_file *s, unsigned pin); | 96 | struct seq_file *s, unsigned pin); |
diff --git a/drivers/pinctrl/pinctrl-abx500.c b/drivers/pinctrl/pinctrl-abx500.c index caecdd373061..c542a97c82f3 100644 --- a/drivers/pinctrl/pinctrl-abx500.c +++ b/drivers/pinctrl/pinctrl-abx500.c | |||
@@ -422,7 +422,7 @@ static u8 abx500_get_mode(struct pinctrl_dev *pctldev, struct gpio_chip *chip, | |||
422 | } | 422 | } |
423 | 423 | ||
424 | /* check if pin use AlternateFunction register */ | 424 | /* check if pin use AlternateFunction register */ |
425 | if ((af.alt_bit1 == UNUSED) && (af.alt_bit1 == UNUSED)) | 425 | if ((af.alt_bit1 == UNUSED) && (af.alt_bit2 == UNUSED)) |
426 | return mode; | 426 | return mode; |
427 | /* | 427 | /* |
428 | * if pin GPIOSEL bit is set and pin supports alternate function, | 428 | * if pin GPIOSEL bit is set and pin supports alternate function, |
diff --git a/drivers/pinctrl/pinctrl-at91.c b/drivers/pinctrl/pinctrl-at91.c index 75933a6aa828..efb7f10e902a 100644 --- a/drivers/pinctrl/pinctrl-at91.c +++ b/drivers/pinctrl/pinctrl-at91.c | |||
@@ -1277,21 +1277,80 @@ static int alt_gpio_irq_type(struct irq_data *d, unsigned type) | |||
1277 | } | 1277 | } |
1278 | 1278 | ||
1279 | #ifdef CONFIG_PM | 1279 | #ifdef CONFIG_PM |
1280 | |||
1281 | static u32 wakeups[MAX_GPIO_BANKS]; | ||
1282 | static u32 backups[MAX_GPIO_BANKS]; | ||
1283 | |||
1280 | static int gpio_irq_set_wake(struct irq_data *d, unsigned state) | 1284 | static int gpio_irq_set_wake(struct irq_data *d, unsigned state) |
1281 | { | 1285 | { |
1282 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); | 1286 | struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(d); |
1283 | unsigned bank = at91_gpio->pioc_idx; | 1287 | unsigned bank = at91_gpio->pioc_idx; |
1288 | unsigned mask = 1 << d->hwirq; | ||
1284 | 1289 | ||
1285 | if (unlikely(bank >= MAX_GPIO_BANKS)) | 1290 | if (unlikely(bank >= MAX_GPIO_BANKS)) |
1286 | return -EINVAL; | 1291 | return -EINVAL; |
1287 | 1292 | ||
1293 | if (state) | ||
1294 | wakeups[bank] |= mask; | ||
1295 | else | ||
1296 | wakeups[bank] &= ~mask; | ||
1297 | |||
1288 | irq_set_irq_wake(at91_gpio->pioc_virq, state); | 1298 | irq_set_irq_wake(at91_gpio->pioc_virq, state); |
1289 | 1299 | ||
1290 | return 0; | 1300 | return 0; |
1291 | } | 1301 | } |
1302 | |||
1303 | void at91_pinctrl_gpio_suspend(void) | ||
1304 | { | ||
1305 | int i; | ||
1306 | |||
1307 | for (i = 0; i < gpio_banks; i++) { | ||
1308 | void __iomem *pio; | ||
1309 | |||
1310 | if (!gpio_chips[i]) | ||
1311 | continue; | ||
1312 | |||
1313 | pio = gpio_chips[i]->regbase; | ||
1314 | |||
1315 | backups[i] = __raw_readl(pio + PIO_IMR); | ||
1316 | __raw_writel(backups[i], pio + PIO_IDR); | ||
1317 | __raw_writel(wakeups[i], pio + PIO_IER); | ||
1318 | |||
1319 | if (!wakeups[i]) { | ||
1320 | clk_unprepare(gpio_chips[i]->clock); | ||
1321 | clk_disable(gpio_chips[i]->clock); | ||
1322 | } else { | ||
1323 | printk(KERN_DEBUG "GPIO-%c may wake for %08x\n", | ||
1324 | 'A'+i, wakeups[i]); | ||
1325 | } | ||
1326 | } | ||
1327 | } | ||
1328 | |||
1329 | void at91_pinctrl_gpio_resume(void) | ||
1330 | { | ||
1331 | int i; | ||
1332 | |||
1333 | for (i = 0; i < gpio_banks; i++) { | ||
1334 | void __iomem *pio; | ||
1335 | |||
1336 | if (!gpio_chips[i]) | ||
1337 | continue; | ||
1338 | |||
1339 | pio = gpio_chips[i]->regbase; | ||
1340 | |||
1341 | if (!wakeups[i]) { | ||
1342 | if (clk_prepare(gpio_chips[i]->clock) == 0) | ||
1343 | clk_enable(gpio_chips[i]->clock); | ||
1344 | } | ||
1345 | |||
1346 | __raw_writel(wakeups[i], pio + PIO_IDR); | ||
1347 | __raw_writel(backups[i], pio + PIO_IER); | ||
1348 | } | ||
1349 | } | ||
1350 | |||
1292 | #else | 1351 | #else |
1293 | #define gpio_irq_set_wake NULL | 1352 | #define gpio_irq_set_wake NULL |
1294 | #endif | 1353 | #endif /* CONFIG_PM */ |
1295 | 1354 | ||
1296 | static struct irq_chip gpio_irqchip = { | 1355 | static struct irq_chip gpio_irqchip = { |
1297 | .name = "GPIO", | 1356 | .name = "GPIO", |
diff --git a/drivers/pinctrl/pinctrl-bcm2835.c b/drivers/pinctrl/pinctrl-bcm2835.c index 4eb6d2c4e4df..2a2e427d765e 100644 --- a/drivers/pinctrl/pinctrl-bcm2835.c +++ b/drivers/pinctrl/pinctrl-bcm2835.c | |||
@@ -699,11 +699,6 @@ static int bcm2835_pctl_dt_node_to_map_pull(struct bcm2835_pinctrl *pc, | |||
699 | return 0; | 699 | return 0; |
700 | } | 700 | } |
701 | 701 | ||
702 | static inline u32 prop_u32(struct property *p, int i) | ||
703 | { | ||
704 | return be32_to_cpup(((__be32 *)p->value) + i); | ||
705 | } | ||
706 | |||
707 | static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, | 702 | static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, |
708 | struct device_node *np, | 703 | struct device_node *np, |
709 | struct pinctrl_map **map, unsigned *num_maps) | 704 | struct pinctrl_map **map, unsigned *num_maps) |
@@ -761,7 +756,9 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, | |||
761 | return -ENOMEM; | 756 | return -ENOMEM; |
762 | 757 | ||
763 | for (i = 0; i < num_pins; i++) { | 758 | for (i = 0; i < num_pins; i++) { |
764 | pin = prop_u32(pins, i); | 759 | err = of_property_read_u32_index(np, "brcm,pins", i, &pin); |
760 | if (err) | ||
761 | goto out; | ||
765 | if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) { | 762 | if (pin >= ARRAY_SIZE(bcm2835_gpio_pins)) { |
766 | dev_err(pc->dev, "%s: invalid brcm,pins value %d\n", | 763 | dev_err(pc->dev, "%s: invalid brcm,pins value %d\n", |
767 | of_node_full_name(np), pin); | 764 | of_node_full_name(np), pin); |
@@ -770,14 +767,20 @@ static int bcm2835_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, | |||
770 | } | 767 | } |
771 | 768 | ||
772 | if (num_funcs) { | 769 | if (num_funcs) { |
773 | func = prop_u32(funcs, (num_funcs > 1) ? i : 0); | 770 | err = of_property_read_u32_index(np, "brcm,function", |
771 | (num_funcs > 1) ? i : 0, &func); | ||
772 | if (err) | ||
773 | goto out; | ||
774 | err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin, | 774 | err = bcm2835_pctl_dt_node_to_map_func(pc, np, pin, |
775 | func, &cur_map); | 775 | func, &cur_map); |
776 | if (err) | 776 | if (err) |
777 | goto out; | 777 | goto out; |
778 | } | 778 | } |
779 | if (num_pulls) { | 779 | if (num_pulls) { |
780 | pull = prop_u32(pulls, (num_pulls > 1) ? i : 0); | 780 | err = of_property_read_u32_index(np, "brcm,pull", |
781 | (num_funcs > 1) ? i : 0, &pull); | ||
782 | if (err) | ||
783 | goto out; | ||
781 | err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin, | 784 | err = bcm2835_pctl_dt_node_to_map_pull(pc, np, pin, |
782 | pull, &cur_map); | 785 | pull, &cur_map); |
783 | if (err) | 786 | if (err) |
diff --git a/drivers/pinctrl/pinctrl-exynos.c b/drivers/pinctrl/pinctrl-exynos.c index 538b9ddaadf7..8738933a57d7 100644 --- a/drivers/pinctrl/pinctrl-exynos.c +++ b/drivers/pinctrl/pinctrl-exynos.c | |||
@@ -677,3 +677,111 @@ struct samsung_pin_ctrl exynos4x12_pin_ctrl[] = { | |||
677 | .label = "exynos4x12-gpio-ctrl3", | 677 | .label = "exynos4x12-gpio-ctrl3", |
678 | }, | 678 | }, |
679 | }; | 679 | }; |
680 | |||
681 | /* pin banks of exynos5250 pin-controller 0 */ | ||
682 | static struct samsung_pin_bank exynos5250_pin_banks0[] = { | ||
683 | EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpa0", 0x00), | ||
684 | EXYNOS_PIN_BANK_EINTG(6, 0x020, "gpa1", 0x04), | ||
685 | EXYNOS_PIN_BANK_EINTG(8, 0x040, "gpa2", 0x08), | ||
686 | EXYNOS_PIN_BANK_EINTG(5, 0x060, "gpb0", 0x0c), | ||
687 | EXYNOS_PIN_BANK_EINTG(5, 0x080, "gpb1", 0x10), | ||
688 | EXYNOS_PIN_BANK_EINTG(4, 0x0A0, "gpb2", 0x14), | ||
689 | EXYNOS_PIN_BANK_EINTG(4, 0x0C0, "gpb3", 0x18), | ||
690 | EXYNOS_PIN_BANK_EINTG(7, 0x0E0, "gpc0", 0x1c), | ||
691 | EXYNOS_PIN_BANK_EINTG(4, 0x100, "gpc1", 0x20), | ||
692 | EXYNOS_PIN_BANK_EINTG(7, 0x120, "gpc2", 0x24), | ||
693 | EXYNOS_PIN_BANK_EINTG(7, 0x140, "gpc3", 0x28), | ||
694 | EXYNOS_PIN_BANK_EINTG(4, 0x160, "gpd0", 0x2c), | ||
695 | EXYNOS_PIN_BANK_EINTG(8, 0x180, "gpd1", 0x30), | ||
696 | EXYNOS_PIN_BANK_EINTG(7, 0x2E0, "gpc4", 0x34), | ||
697 | EXYNOS_PIN_BANK_EINTN(6, 0x1A0, "gpy0"), | ||
698 | EXYNOS_PIN_BANK_EINTN(4, 0x1C0, "gpy1"), | ||
699 | EXYNOS_PIN_BANK_EINTN(6, 0x1E0, "gpy2"), | ||
700 | EXYNOS_PIN_BANK_EINTN(8, 0x200, "gpy3"), | ||
701 | EXYNOS_PIN_BANK_EINTN(8, 0x220, "gpy4"), | ||
702 | EXYNOS_PIN_BANK_EINTN(8, 0x240, "gpy5"), | ||
703 | EXYNOS_PIN_BANK_EINTN(8, 0x260, "gpy6"), | ||
704 | EXYNOS_PIN_BANK_EINTW(8, 0xC00, "gpx0", 0x00), | ||
705 | EXYNOS_PIN_BANK_EINTW(8, 0xC20, "gpx1", 0x04), | ||
706 | EXYNOS_PIN_BANK_EINTW(8, 0xC40, "gpx2", 0x08), | ||
707 | EXYNOS_PIN_BANK_EINTW(8, 0xC60, "gpx3", 0x0c), | ||
708 | }; | ||
709 | |||
710 | /* pin banks of exynos5250 pin-controller 1 */ | ||
711 | static struct samsung_pin_bank exynos5250_pin_banks1[] = { | ||
712 | EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpe0", 0x00), | ||
713 | EXYNOS_PIN_BANK_EINTG(2, 0x020, "gpe1", 0x04), | ||
714 | EXYNOS_PIN_BANK_EINTG(4, 0x040, "gpf0", 0x08), | ||
715 | EXYNOS_PIN_BANK_EINTG(4, 0x060, "gpf1", 0x0c), | ||
716 | EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpg0", 0x10), | ||
717 | EXYNOS_PIN_BANK_EINTG(8, 0x0A0, "gpg1", 0x14), | ||
718 | EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpg2", 0x18), | ||
719 | EXYNOS_PIN_BANK_EINTG(4, 0x0E0, "gph0", 0x1c), | ||
720 | EXYNOS_PIN_BANK_EINTG(8, 0x100, "gph1", 0x20), | ||
721 | }; | ||
722 | |||
723 | /* pin banks of exynos5250 pin-controller 2 */ | ||
724 | static struct samsung_pin_bank exynos5250_pin_banks2[] = { | ||
725 | EXYNOS_PIN_BANK_EINTG(8, 0x000, "gpv0", 0x00), | ||
726 | EXYNOS_PIN_BANK_EINTG(8, 0x020, "gpv1", 0x04), | ||
727 | EXYNOS_PIN_BANK_EINTG(8, 0x060, "gpv2", 0x08), | ||
728 | EXYNOS_PIN_BANK_EINTG(8, 0x080, "gpv3", 0x0c), | ||
729 | EXYNOS_PIN_BANK_EINTG(2, 0x0C0, "gpv4", 0x10), | ||
730 | }; | ||
731 | |||
732 | /* pin banks of exynos5250 pin-controller 3 */ | ||
733 | static struct samsung_pin_bank exynos5250_pin_banks3[] = { | ||
734 | EXYNOS_PIN_BANK_EINTG(7, 0x000, "gpz", 0x00), | ||
735 | }; | ||
736 | |||
737 | /* | ||
738 | * Samsung pinctrl driver data for Exynos5250 SoC. Exynos5250 SoC includes | ||
739 | * four gpio/pin-mux/pinconfig controllers. | ||
740 | */ | ||
741 | struct samsung_pin_ctrl exynos5250_pin_ctrl[] = { | ||
742 | { | ||
743 | /* pin-controller instance 0 data */ | ||
744 | .pin_banks = exynos5250_pin_banks0, | ||
745 | .nr_banks = ARRAY_SIZE(exynos5250_pin_banks0), | ||
746 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
747 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
748 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
749 | .weint_con = EXYNOS_WKUP_ECON_OFFSET, | ||
750 | .weint_mask = EXYNOS_WKUP_EMASK_OFFSET, | ||
751 | .weint_pend = EXYNOS_WKUP_EPEND_OFFSET, | ||
752 | .svc = EXYNOS_SVC_OFFSET, | ||
753 | .eint_gpio_init = exynos_eint_gpio_init, | ||
754 | .eint_wkup_init = exynos_eint_wkup_init, | ||
755 | .label = "exynos5250-gpio-ctrl0", | ||
756 | }, { | ||
757 | /* pin-controller instance 1 data */ | ||
758 | .pin_banks = exynos5250_pin_banks1, | ||
759 | .nr_banks = ARRAY_SIZE(exynos5250_pin_banks1), | ||
760 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
761 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
762 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
763 | .svc = EXYNOS_SVC_OFFSET, | ||
764 | .eint_gpio_init = exynos_eint_gpio_init, | ||
765 | .label = "exynos5250-gpio-ctrl1", | ||
766 | }, { | ||
767 | /* pin-controller instance 2 data */ | ||
768 | .pin_banks = exynos5250_pin_banks2, | ||
769 | .nr_banks = ARRAY_SIZE(exynos5250_pin_banks2), | ||
770 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
771 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
772 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
773 | .svc = EXYNOS_SVC_OFFSET, | ||
774 | .eint_gpio_init = exynos_eint_gpio_init, | ||
775 | .label = "exynos5250-gpio-ctrl2", | ||
776 | }, { | ||
777 | /* pin-controller instance 3 data */ | ||
778 | .pin_banks = exynos5250_pin_banks3, | ||
779 | .nr_banks = ARRAY_SIZE(exynos5250_pin_banks3), | ||
780 | .geint_con = EXYNOS_GPIO_ECON_OFFSET, | ||
781 | .geint_mask = EXYNOS_GPIO_EMASK_OFFSET, | ||
782 | .geint_pend = EXYNOS_GPIO_EPEND_OFFSET, | ||
783 | .svc = EXYNOS_SVC_OFFSET, | ||
784 | .eint_gpio_init = exynos_eint_gpio_init, | ||
785 | .label = "exynos5250-gpio-ctrl3", | ||
786 | }, | ||
787 | }; | ||
diff --git a/drivers/pinctrl/pinctrl-samsung.c b/drivers/pinctrl/pinctrl-samsung.c index f206df175656..3d5cf639aa46 100644 --- a/drivers/pinctrl/pinctrl-samsung.c +++ b/drivers/pinctrl/pinctrl-samsung.c | |||
@@ -948,6 +948,8 @@ static const struct of_device_id samsung_pinctrl_dt_match[] = { | |||
948 | .data = (void *)exynos4210_pin_ctrl }, | 948 | .data = (void *)exynos4210_pin_ctrl }, |
949 | { .compatible = "samsung,exynos4x12-pinctrl", | 949 | { .compatible = "samsung,exynos4x12-pinctrl", |
950 | .data = (void *)exynos4x12_pin_ctrl }, | 950 | .data = (void *)exynos4x12_pin_ctrl }, |
951 | { .compatible = "samsung,exynos5250-pinctrl", | ||
952 | .data = (void *)exynos5250_pin_ctrl }, | ||
951 | {}, | 953 | {}, |
952 | }; | 954 | }; |
953 | MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); | 955 | MODULE_DEVICE_TABLE(of, samsung_pinctrl_dt_match); |
diff --git a/drivers/pinctrl/pinctrl-samsung.h b/drivers/pinctrl/pinctrl-samsung.h index e2d4e67f7e88..ee964aadce0c 100644 --- a/drivers/pinctrl/pinctrl-samsung.h +++ b/drivers/pinctrl/pinctrl-samsung.h | |||
@@ -237,5 +237,6 @@ struct samsung_pmx_func { | |||
237 | /* list of all exported SoC specific data */ | 237 | /* list of all exported SoC specific data */ |
238 | extern struct samsung_pin_ctrl exynos4210_pin_ctrl[]; | 238 | extern struct samsung_pin_ctrl exynos4210_pin_ctrl[]; |
239 | extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[]; | 239 | extern struct samsung_pin_ctrl exynos4x12_pin_ctrl[]; |
240 | extern struct samsung_pin_ctrl exynos5250_pin_ctrl[]; | ||
240 | 241 | ||
241 | #endif /* __PINCTRL_SAMSUNG_H */ | 242 | #endif /* __PINCTRL_SAMSUNG_H */ |
diff --git a/drivers/pinctrl/pinmux.c b/drivers/pinctrl/pinmux.c index 1a00658b3ea0..bd83c8b01cd1 100644 --- a/drivers/pinctrl/pinmux.c +++ b/drivers/pinctrl/pinmux.c | |||
@@ -194,6 +194,11 @@ static const char *pin_free(struct pinctrl_dev *pctldev, int pin, | |||
194 | } | 194 | } |
195 | 195 | ||
196 | if (!gpio_range) { | 196 | if (!gpio_range) { |
197 | /* | ||
198 | * A pin should not be freed more times than allocated. | ||
199 | */ | ||
200 | if (WARN_ON(!desc->mux_usecount)) | ||
201 | return NULL; | ||
197 | desc->mux_usecount--; | 202 | desc->mux_usecount--; |
198 | if (desc->mux_usecount) | 203 | if (desc->mux_usecount) |
199 | return NULL; | 204 | return NULL; |
diff --git a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c index 709008e94124..6f15c03077a0 100644 --- a/drivers/pinctrl/sh-pfc/pfc-sh73a0.c +++ b/drivers/pinctrl/sh-pfc/pfc-sh73a0.c | |||
@@ -2733,9 +2733,9 @@ static struct pinmux_data_reg pinmux_data_regs[] = { | |||
2733 | { }, | 2733 | { }, |
2734 | }; | 2734 | }; |
2735 | 2735 | ||
2736 | /* IRQ pins through INTCS with IRQ0->15 from 0x200 and IRQ16-31 from 0x3200 */ | 2736 | /* External IRQ pins mapped at IRQPIN_BASE */ |
2737 | #define EXT_IRQ16L(n) intcs_evt2irq(0x200 + ((n) << 5)) | 2737 | #define EXT_IRQ16L(n) irq_pin(n) |
2738 | #define EXT_IRQ16H(n) intcs_evt2irq(0x3200 + ((n - 16) << 5)) | 2738 | #define EXT_IRQ16H(n) irq_pin(n) |
2739 | 2739 | ||
2740 | static struct pinmux_irq pinmux_irqs[] = { | 2740 | static struct pinmux_irq pinmux_irqs[] = { |
2741 | PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), | 2741 | PINMUX_IRQ(EXT_IRQ16H(19), PORT9_FN0), |
diff --git a/drivers/pinctrl/vt8500/Kconfig b/drivers/pinctrl/vt8500/Kconfig new file mode 100644 index 000000000000..55724a73d94a --- /dev/null +++ b/drivers/pinctrl/vt8500/Kconfig | |||
@@ -0,0 +1,52 @@ | |||
1 | # | ||
2 | # VIA/Wondermedia PINCTRL drivers | ||
3 | # | ||
4 | |||
5 | if ARCH_VT8500 | ||
6 | |||
7 | config PINCTRL_WMT | ||
8 | bool | ||
9 | select PINMUX | ||
10 | select GENERIC_PINCONF | ||
11 | |||
12 | config PINCTRL_VT8500 | ||
13 | bool "VIA VT8500 pin controller driver" | ||
14 | depends on ARCH_WM8505 | ||
15 | select PINCTRL_WMT | ||
16 | help | ||
17 | Say yes here to support the gpio/pin control module on | ||
18 | VIA VT8500 SoCs. | ||
19 | |||
20 | config PINCTRL_WM8505 | ||
21 | bool "Wondermedia WM8505 pin controller driver" | ||
22 | depends on ARCH_WM8505 | ||
23 | select PINCTRL_WMT | ||
24 | help | ||
25 | Say yes here to support the gpio/pin control module on | ||
26 | Wondermedia WM8505 SoCs. | ||
27 | |||
28 | config PINCTRL_WM8650 | ||
29 | bool "Wondermedia WM8650 pin controller driver" | ||
30 | depends on ARCH_WM8505 | ||
31 | select PINCTRL_WMT | ||
32 | help | ||
33 | Say yes here to support the gpio/pin control module on | ||
34 | Wondermedia WM8650 SoCs. | ||
35 | |||
36 | config PINCTRL_WM8750 | ||
37 | bool "Wondermedia WM8750 pin controller driver" | ||
38 | depends on ARCH_WM8750 | ||
39 | select PINCTRL_WMT | ||
40 | help | ||
41 | Say yes here to support the gpio/pin control module on | ||
42 | Wondermedia WM8750 SoCs. | ||
43 | |||
44 | config PINCTRL_WM8850 | ||
45 | bool "Wondermedia WM8850 pin controller driver" | ||
46 | depends on ARCH_WM8850 | ||
47 | select PINCTRL_WMT | ||
48 | help | ||
49 | Say yes here to support the gpio/pin control module on | ||
50 | Wondermedia WM8850 SoCs. | ||
51 | |||
52 | endif | ||
diff --git a/drivers/pinctrl/vt8500/Makefile b/drivers/pinctrl/vt8500/Makefile new file mode 100644 index 000000000000..24ec45dd0d80 --- /dev/null +++ b/drivers/pinctrl/vt8500/Makefile | |||
@@ -0,0 +1,8 @@ | |||
1 | # VIA/Wondermedia pinctrl support | ||
2 | |||
3 | obj-$(CONFIG_PINCTRL_WMT) += pinctrl-wmt.o | ||
4 | obj-$(CONFIG_PINCTRL_VT8500) += pinctrl-vt8500.o | ||
5 | obj-$(CONFIG_PINCTRL_WM8505) += pinctrl-wm8505.o | ||
6 | obj-$(CONFIG_PINCTRL_WM8650) += pinctrl-wm8650.o | ||
7 | obj-$(CONFIG_PINCTRL_WM8750) += pinctrl-wm8750.o | ||
8 | obj-$(CONFIG_PINCTRL_WM8850) += pinctrl-wm8850.o | ||
diff --git a/drivers/pinctrl/vt8500/pinctrl-vt8500.c b/drivers/pinctrl/vt8500/pinctrl-vt8500.c new file mode 100644 index 000000000000..f2fe9f85cfa6 --- /dev/null +++ b/drivers/pinctrl/vt8500/pinctrl-vt8500.c | |||
@@ -0,0 +1,501 @@ | |||
1 | /* | ||
2 | * Pinctrl data for VIA VT8500 SoC | ||
3 | * | ||
4 | * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/pinctrl/pinctrl.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include "pinctrl-wmt.h" | ||
23 | |||
24 | /* | ||
25 | * Describe the register offsets within the GPIO memory space | ||
26 | * The dedicated external GPIO's should always be listed in bank 0 | ||
27 | * so they are exported in the 0..31 range which is what users | ||
28 | * expect. | ||
29 | * | ||
30 | * Do not reorder these banks as it will change the pin numbering | ||
31 | */ | ||
32 | static const struct wmt_pinctrl_bank_registers vt8500_banks[] = { | ||
33 | WMT_PINCTRL_BANK(NO_REG, 0x3C, 0x5C, 0x7C, NO_REG, NO_REG), /* 0 */ | ||
34 | WMT_PINCTRL_BANK(0x00, 0x20, 0x40, 0x60, NO_REG, NO_REG), /* 1 */ | ||
35 | WMT_PINCTRL_BANK(0x04, 0x24, 0x44, 0x64, NO_REG, NO_REG), /* 2 */ | ||
36 | WMT_PINCTRL_BANK(0x08, 0x28, 0x48, 0x68, NO_REG, NO_REG), /* 3 */ | ||
37 | WMT_PINCTRL_BANK(0x0C, 0x2C, 0x4C, 0x6C, NO_REG, NO_REG), /* 4 */ | ||
38 | WMT_PINCTRL_BANK(0x10, 0x30, 0x50, 0x70, NO_REG, NO_REG), /* 5 */ | ||
39 | WMT_PINCTRL_BANK(0x14, 0x34, 0x54, 0x74, NO_REG, NO_REG), /* 6 */ | ||
40 | }; | ||
41 | |||
42 | /* Please keep sorted by bank/bit */ | ||
43 | #define WMT_PIN_EXTGPIO0 WMT_PIN(0, 0) | ||
44 | #define WMT_PIN_EXTGPIO1 WMT_PIN(0, 1) | ||
45 | #define WMT_PIN_EXTGPIO2 WMT_PIN(0, 2) | ||
46 | #define WMT_PIN_EXTGPIO3 WMT_PIN(0, 3) | ||
47 | #define WMT_PIN_EXTGPIO4 WMT_PIN(0, 4) | ||
48 | #define WMT_PIN_EXTGPIO5 WMT_PIN(0, 5) | ||
49 | #define WMT_PIN_EXTGPIO6 WMT_PIN(0, 6) | ||
50 | #define WMT_PIN_EXTGPIO7 WMT_PIN(0, 7) | ||
51 | #define WMT_PIN_EXTGPIO8 WMT_PIN(0, 8) | ||
52 | #define WMT_PIN_UART0RTS WMT_PIN(1, 0) | ||
53 | #define WMT_PIN_UART0TXD WMT_PIN(1, 1) | ||
54 | #define WMT_PIN_UART0CTS WMT_PIN(1, 2) | ||
55 | #define WMT_PIN_UART0RXD WMT_PIN(1, 3) | ||
56 | #define WMT_PIN_UART1RTS WMT_PIN(1, 4) | ||
57 | #define WMT_PIN_UART1TXD WMT_PIN(1, 5) | ||
58 | #define WMT_PIN_UART1CTS WMT_PIN(1, 6) | ||
59 | #define WMT_PIN_UART1RXD WMT_PIN(1, 7) | ||
60 | #define WMT_PIN_SPI0CLK WMT_PIN(1, 8) | ||
61 | #define WMT_PIN_SPI0SS WMT_PIN(1, 9) | ||
62 | #define WMT_PIN_SPI0MISO WMT_PIN(1, 10) | ||
63 | #define WMT_PIN_SPI0MOSI WMT_PIN(1, 11) | ||
64 | #define WMT_PIN_SPI1CLK WMT_PIN(1, 12) | ||
65 | #define WMT_PIN_SPI1SS WMT_PIN(1, 13) | ||
66 | #define WMT_PIN_SPI1MISO WMT_PIN(1, 14) | ||
67 | #define WMT_PIN_SPI1MOSI WMT_PIN(1, 15) | ||
68 | #define WMT_PIN_SPI2CLK WMT_PIN(1, 16) | ||
69 | #define WMT_PIN_SPI2SS WMT_PIN(1, 17) | ||
70 | #define WMT_PIN_SPI2MISO WMT_PIN(1, 18) | ||
71 | #define WMT_PIN_SPI2MOSI WMT_PIN(1, 19) | ||
72 | #define WMT_PIN_SDDATA0 WMT_PIN(2, 0) | ||
73 | #define WMT_PIN_SDDATA1 WMT_PIN(2, 1) | ||
74 | #define WMT_PIN_SDDATA2 WMT_PIN(2, 2) | ||
75 | #define WMT_PIN_SDDATA3 WMT_PIN(2, 3) | ||
76 | #define WMT_PIN_MMCDATA0 WMT_PIN(2, 4) | ||
77 | #define WMT_PIN_MMCDATA1 WMT_PIN(2, 5) | ||
78 | #define WMT_PIN_MMCDATA2 WMT_PIN(2, 6) | ||
79 | #define WMT_PIN_MMCDATA3 WMT_PIN(2, 7) | ||
80 | #define WMT_PIN_SDCLK WMT_PIN(2, 8) | ||
81 | #define WMT_PIN_SDWP WMT_PIN(2, 9) | ||
82 | #define WMT_PIN_SDCMD WMT_PIN(2, 10) | ||
83 | #define WMT_PIN_MSDATA0 WMT_PIN(2, 16) | ||
84 | #define WMT_PIN_MSDATA1 WMT_PIN(2, 17) | ||
85 | #define WMT_PIN_MSDATA2 WMT_PIN(2, 18) | ||
86 | #define WMT_PIN_MSDATA3 WMT_PIN(2, 19) | ||
87 | #define WMT_PIN_MSCLK WMT_PIN(2, 20) | ||
88 | #define WMT_PIN_MSBS WMT_PIN(2, 21) | ||
89 | #define WMT_PIN_MSINS WMT_PIN(2, 22) | ||
90 | #define WMT_PIN_I2C0SCL WMT_PIN(2, 24) | ||
91 | #define WMT_PIN_I2C0SDA WMT_PIN(2, 25) | ||
92 | #define WMT_PIN_I2C1SCL WMT_PIN(2, 26) | ||
93 | #define WMT_PIN_I2C1SDA WMT_PIN(2, 27) | ||
94 | #define WMT_PIN_MII0RXD0 WMT_PIN(3, 0) | ||
95 | #define WMT_PIN_MII0RXD1 WMT_PIN(3, 1) | ||
96 | #define WMT_PIN_MII0RXD2 WMT_PIN(3, 2) | ||
97 | #define WMT_PIN_MII0RXD3 WMT_PIN(3, 3) | ||
98 | #define WMT_PIN_MII0RXCLK WMT_PIN(3, 4) | ||
99 | #define WMT_PIN_MII0RXDV WMT_PIN(3, 5) | ||
100 | #define WMT_PIN_MII0RXERR WMT_PIN(3, 6) | ||
101 | #define WMT_PIN_MII0PHYRST WMT_PIN(3, 7) | ||
102 | #define WMT_PIN_MII0TXD0 WMT_PIN(3, 8) | ||
103 | #define WMT_PIN_MII0TXD1 WMT_PIN(3, 9) | ||
104 | #define WMT_PIN_MII0TXD2 WMT_PIN(3, 10) | ||
105 | #define WMT_PIN_MII0TXD3 WMT_PIN(3, 11) | ||
106 | #define WMT_PIN_MII0TXCLK WMT_PIN(3, 12) | ||
107 | #define WMT_PIN_MII0TXEN WMT_PIN(3, 13) | ||
108 | #define WMT_PIN_MII0TXERR WMT_PIN(3, 14) | ||
109 | #define WMT_PIN_MII0PHYPD WMT_PIN(3, 15) | ||
110 | #define WMT_PIN_MII0COL WMT_PIN(3, 16) | ||
111 | #define WMT_PIN_MII0CRS WMT_PIN(3, 17) | ||
112 | #define WMT_PIN_MII0MDIO WMT_PIN(3, 18) | ||
113 | #define WMT_PIN_MII0MDC WMT_PIN(3, 19) | ||
114 | #define WMT_PIN_SEECS WMT_PIN(3, 20) | ||
115 | #define WMT_PIN_SEECK WMT_PIN(3, 21) | ||
116 | #define WMT_PIN_SEEDI WMT_PIN(3, 22) | ||
117 | #define WMT_PIN_SEEDO WMT_PIN(3, 23) | ||
118 | #define WMT_PIN_IDEDREQ0 WMT_PIN(3, 24) | ||
119 | #define WMT_PIN_IDEDREQ1 WMT_PIN(3, 25) | ||
120 | #define WMT_PIN_IDEIOW WMT_PIN(3, 26) | ||
121 | #define WMT_PIN_IDEIOR WMT_PIN(3, 27) | ||
122 | #define WMT_PIN_IDEDACK WMT_PIN(3, 28) | ||
123 | #define WMT_PIN_IDEIORDY WMT_PIN(3, 29) | ||
124 | #define WMT_PIN_IDEINTRQ WMT_PIN(3, 30) | ||
125 | #define WMT_PIN_VDIN0 WMT_PIN(4, 0) | ||
126 | #define WMT_PIN_VDIN1 WMT_PIN(4, 1) | ||
127 | #define WMT_PIN_VDIN2 WMT_PIN(4, 2) | ||
128 | #define WMT_PIN_VDIN3 WMT_PIN(4, 3) | ||
129 | #define WMT_PIN_VDIN4 WMT_PIN(4, 4) | ||
130 | #define WMT_PIN_VDIN5 WMT_PIN(4, 5) | ||
131 | #define WMT_PIN_VDIN6 WMT_PIN(4, 6) | ||
132 | #define WMT_PIN_VDIN7 WMT_PIN(4, 7) | ||
133 | #define WMT_PIN_VDOUT0 WMT_PIN(4, 8) | ||
134 | #define WMT_PIN_VDOUT1 WMT_PIN(4, 9) | ||
135 | #define WMT_PIN_VDOUT2 WMT_PIN(4, 10) | ||
136 | #define WMT_PIN_VDOUT3 WMT_PIN(4, 11) | ||
137 | #define WMT_PIN_VDOUT4 WMT_PIN(4, 12) | ||
138 | #define WMT_PIN_VDOUT5 WMT_PIN(4, 13) | ||
139 | #define WMT_PIN_NANDCLE0 WMT_PIN(4, 14) | ||
140 | #define WMT_PIN_NANDCLE1 WMT_PIN(4, 15) | ||
141 | #define WMT_PIN_VDOUT6_7 WMT_PIN(4, 16) | ||
142 | #define WMT_PIN_VHSYNC WMT_PIN(4, 17) | ||
143 | #define WMT_PIN_VVSYNC WMT_PIN(4, 18) | ||
144 | #define WMT_PIN_TSDIN0 WMT_PIN(5, 8) | ||
145 | #define WMT_PIN_TSDIN1 WMT_PIN(5, 9) | ||
146 | #define WMT_PIN_TSDIN2 WMT_PIN(5, 10) | ||
147 | #define WMT_PIN_TSDIN3 WMT_PIN(5, 11) | ||
148 | #define WMT_PIN_TSDIN4 WMT_PIN(5, 12) | ||
149 | #define WMT_PIN_TSDIN5 WMT_PIN(5, 13) | ||
150 | #define WMT_PIN_TSDIN6 WMT_PIN(5, 14) | ||
151 | #define WMT_PIN_TSDIN7 WMT_PIN(5, 15) | ||
152 | #define WMT_PIN_TSSYNC WMT_PIN(5, 16) | ||
153 | #define WMT_PIN_TSVALID WMT_PIN(5, 17) | ||
154 | #define WMT_PIN_TSCLK WMT_PIN(5, 18) | ||
155 | #define WMT_PIN_LCDD0 WMT_PIN(6, 0) | ||
156 | #define WMT_PIN_LCDD1 WMT_PIN(6, 1) | ||
157 | #define WMT_PIN_LCDD2 WMT_PIN(6, 2) | ||
158 | #define WMT_PIN_LCDD3 WMT_PIN(6, 3) | ||
159 | #define WMT_PIN_LCDD4 WMT_PIN(6, 4) | ||
160 | #define WMT_PIN_LCDD5 WMT_PIN(6, 5) | ||
161 | #define WMT_PIN_LCDD6 WMT_PIN(6, 6) | ||
162 | #define WMT_PIN_LCDD7 WMT_PIN(6, 7) | ||
163 | #define WMT_PIN_LCDD8 WMT_PIN(6, 8) | ||
164 | #define WMT_PIN_LCDD9 WMT_PIN(6, 9) | ||
165 | #define WMT_PIN_LCDD10 WMT_PIN(6, 10) | ||
166 | #define WMT_PIN_LCDD11 WMT_PIN(6, 11) | ||
167 | #define WMT_PIN_LCDD12 WMT_PIN(6, 12) | ||
168 | #define WMT_PIN_LCDD13 WMT_PIN(6, 13) | ||
169 | #define WMT_PIN_LCDD14 WMT_PIN(6, 14) | ||
170 | #define WMT_PIN_LCDD15 WMT_PIN(6, 15) | ||
171 | #define WMT_PIN_LCDD16 WMT_PIN(6, 16) | ||
172 | #define WMT_PIN_LCDD17 WMT_PIN(6, 17) | ||
173 | #define WMT_PIN_LCDCLK WMT_PIN(6, 18) | ||
174 | #define WMT_PIN_LCDDEN WMT_PIN(6, 19) | ||
175 | #define WMT_PIN_LCDLINE WMT_PIN(6, 20) | ||
176 | #define WMT_PIN_LCDFRM WMT_PIN(6, 21) | ||
177 | #define WMT_PIN_LCDBIAS WMT_PIN(6, 22) | ||
178 | |||
179 | static const struct pinctrl_pin_desc vt8500_pins[] = { | ||
180 | PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"), | ||
181 | PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"), | ||
182 | PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"), | ||
183 | PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"), | ||
184 | PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"), | ||
185 | PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"), | ||
186 | PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"), | ||
187 | PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"), | ||
188 | PINCTRL_PIN(WMT_PIN_EXTGPIO8, "extgpio8"), | ||
189 | PINCTRL_PIN(WMT_PIN_UART0RTS, "uart0_rts"), | ||
190 | PINCTRL_PIN(WMT_PIN_UART0TXD, "uart0_txd"), | ||
191 | PINCTRL_PIN(WMT_PIN_UART0CTS, "uart0_cts"), | ||
192 | PINCTRL_PIN(WMT_PIN_UART0RXD, "uart0_rxd"), | ||
193 | PINCTRL_PIN(WMT_PIN_UART1RTS, "uart1_rts"), | ||
194 | PINCTRL_PIN(WMT_PIN_UART1TXD, "uart1_txd"), | ||
195 | PINCTRL_PIN(WMT_PIN_UART1CTS, "uart1_cts"), | ||
196 | PINCTRL_PIN(WMT_PIN_UART1RXD, "uart1_rxd"), | ||
197 | PINCTRL_PIN(WMT_PIN_SPI0CLK, "spi0_clk"), | ||
198 | PINCTRL_PIN(WMT_PIN_SPI0SS, "spi0_ss"), | ||
199 | PINCTRL_PIN(WMT_PIN_SPI0MISO, "spi0_miso"), | ||
200 | PINCTRL_PIN(WMT_PIN_SPI0MOSI, "spi0_mosi"), | ||
201 | PINCTRL_PIN(WMT_PIN_SPI1CLK, "spi1_clk"), | ||
202 | PINCTRL_PIN(WMT_PIN_SPI1SS, "spi1_ss"), | ||
203 | PINCTRL_PIN(WMT_PIN_SPI1MISO, "spi1_miso"), | ||
204 | PINCTRL_PIN(WMT_PIN_SPI1MOSI, "spi1_mosi"), | ||
205 | PINCTRL_PIN(WMT_PIN_SPI2CLK, "spi2_clk"), | ||
206 | PINCTRL_PIN(WMT_PIN_SPI2SS, "spi2_ss"), | ||
207 | PINCTRL_PIN(WMT_PIN_SPI2MISO, "spi2_miso"), | ||
208 | PINCTRL_PIN(WMT_PIN_SPI2MOSI, "spi2_mosi"), | ||
209 | PINCTRL_PIN(WMT_PIN_SDDATA0, "sd_data0"), | ||
210 | PINCTRL_PIN(WMT_PIN_SDDATA1, "sd_data1"), | ||
211 | PINCTRL_PIN(WMT_PIN_SDDATA2, "sd_data2"), | ||
212 | PINCTRL_PIN(WMT_PIN_SDDATA3, "sd_data3"), | ||
213 | PINCTRL_PIN(WMT_PIN_MMCDATA0, "mmc_data0"), | ||
214 | PINCTRL_PIN(WMT_PIN_MMCDATA1, "mmc_data1"), | ||
215 | PINCTRL_PIN(WMT_PIN_MMCDATA2, "mmc_data2"), | ||
216 | PINCTRL_PIN(WMT_PIN_MMCDATA3, "mmc_data3"), | ||
217 | PINCTRL_PIN(WMT_PIN_SDCLK, "sd_clk"), | ||
218 | PINCTRL_PIN(WMT_PIN_SDWP, "sd_wp"), | ||
219 | PINCTRL_PIN(WMT_PIN_SDCMD, "sd_cmd"), | ||
220 | PINCTRL_PIN(WMT_PIN_MSDATA0, "ms_data0"), | ||
221 | PINCTRL_PIN(WMT_PIN_MSDATA1, "ms_data1"), | ||
222 | PINCTRL_PIN(WMT_PIN_MSDATA2, "ms_data2"), | ||
223 | PINCTRL_PIN(WMT_PIN_MSDATA3, "ms_data3"), | ||
224 | PINCTRL_PIN(WMT_PIN_MSCLK, "ms_clk"), | ||
225 | PINCTRL_PIN(WMT_PIN_MSBS, "ms_bs"), | ||
226 | PINCTRL_PIN(WMT_PIN_MSINS, "ms_ins"), | ||
227 | PINCTRL_PIN(WMT_PIN_I2C0SCL, "i2c0_scl"), | ||
228 | PINCTRL_PIN(WMT_PIN_I2C0SDA, "i2c0_sda"), | ||
229 | PINCTRL_PIN(WMT_PIN_I2C1SCL, "i2c1_scl"), | ||
230 | PINCTRL_PIN(WMT_PIN_I2C1SDA, "i2c1_sda"), | ||
231 | PINCTRL_PIN(WMT_PIN_MII0RXD0, "mii0_rxd0"), | ||
232 | PINCTRL_PIN(WMT_PIN_MII0RXD1, "mii0_rxd1"), | ||
233 | PINCTRL_PIN(WMT_PIN_MII0RXD2, "mii0_rxd2"), | ||
234 | PINCTRL_PIN(WMT_PIN_MII0RXD3, "mii0_rxd3"), | ||
235 | PINCTRL_PIN(WMT_PIN_MII0RXCLK, "mii0_rxclk"), | ||
236 | PINCTRL_PIN(WMT_PIN_MII0RXDV, "mii0_rxdv"), | ||
237 | PINCTRL_PIN(WMT_PIN_MII0RXERR, "mii0_rxerr"), | ||
238 | PINCTRL_PIN(WMT_PIN_MII0PHYRST, "mii0_phyrst"), | ||
239 | PINCTRL_PIN(WMT_PIN_MII0TXD0, "mii0_txd0"), | ||
240 | PINCTRL_PIN(WMT_PIN_MII0TXD1, "mii0_txd1"), | ||
241 | PINCTRL_PIN(WMT_PIN_MII0TXD2, "mii0_txd2"), | ||
242 | PINCTRL_PIN(WMT_PIN_MII0TXD3, "mii0_txd3"), | ||
243 | PINCTRL_PIN(WMT_PIN_MII0TXCLK, "mii0_txclk"), | ||
244 | PINCTRL_PIN(WMT_PIN_MII0TXEN, "mii0_txen"), | ||
245 | PINCTRL_PIN(WMT_PIN_MII0TXERR, "mii0_txerr"), | ||
246 | PINCTRL_PIN(WMT_PIN_MII0PHYPD, "mii0_phypd"), | ||
247 | PINCTRL_PIN(WMT_PIN_MII0COL, "mii0_col"), | ||
248 | PINCTRL_PIN(WMT_PIN_MII0CRS, "mii0_crs"), | ||
249 | PINCTRL_PIN(WMT_PIN_MII0MDIO, "mii0_mdio"), | ||
250 | PINCTRL_PIN(WMT_PIN_MII0MDC, "mii0_mdc"), | ||
251 | PINCTRL_PIN(WMT_PIN_SEECS, "see_cs"), | ||
252 | PINCTRL_PIN(WMT_PIN_SEECK, "see_ck"), | ||
253 | PINCTRL_PIN(WMT_PIN_SEEDI, "see_di"), | ||
254 | PINCTRL_PIN(WMT_PIN_SEEDO, "see_do"), | ||
255 | PINCTRL_PIN(WMT_PIN_IDEDREQ0, "ide_dreq0"), | ||
256 | PINCTRL_PIN(WMT_PIN_IDEDREQ1, "ide_dreq1"), | ||
257 | PINCTRL_PIN(WMT_PIN_IDEIOW, "ide_iow"), | ||
258 | PINCTRL_PIN(WMT_PIN_IDEIOR, "ide_ior"), | ||
259 | PINCTRL_PIN(WMT_PIN_IDEDACK, "ide_dack"), | ||
260 | PINCTRL_PIN(WMT_PIN_IDEIORDY, "ide_iordy"), | ||
261 | PINCTRL_PIN(WMT_PIN_IDEINTRQ, "ide_intrq"), | ||
262 | PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"), | ||
263 | PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"), | ||
264 | PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"), | ||
265 | PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"), | ||
266 | PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"), | ||
267 | PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"), | ||
268 | PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"), | ||
269 | PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"), | ||
270 | PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"), | ||
271 | PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"), | ||
272 | PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"), | ||
273 | PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"), | ||
274 | PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"), | ||
275 | PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"), | ||
276 | PINCTRL_PIN(WMT_PIN_NANDCLE0, "nand_cle0"), | ||
277 | PINCTRL_PIN(WMT_PIN_NANDCLE1, "nand_cle1"), | ||
278 | PINCTRL_PIN(WMT_PIN_VDOUT6_7, "vdout6_7"), | ||
279 | PINCTRL_PIN(WMT_PIN_VHSYNC, "vhsync"), | ||
280 | PINCTRL_PIN(WMT_PIN_VVSYNC, "vvsync"), | ||
281 | PINCTRL_PIN(WMT_PIN_TSDIN0, "tsdin0"), | ||
282 | PINCTRL_PIN(WMT_PIN_TSDIN1, "tsdin1"), | ||
283 | PINCTRL_PIN(WMT_PIN_TSDIN2, "tsdin2"), | ||
284 | PINCTRL_PIN(WMT_PIN_TSDIN3, "tsdin3"), | ||
285 | PINCTRL_PIN(WMT_PIN_TSDIN4, "tsdin4"), | ||
286 | PINCTRL_PIN(WMT_PIN_TSDIN5, "tsdin5"), | ||
287 | PINCTRL_PIN(WMT_PIN_TSDIN6, "tsdin6"), | ||
288 | PINCTRL_PIN(WMT_PIN_TSDIN7, "tsdin7"), | ||
289 | PINCTRL_PIN(WMT_PIN_TSSYNC, "tssync"), | ||
290 | PINCTRL_PIN(WMT_PIN_TSVALID, "tsvalid"), | ||
291 | PINCTRL_PIN(WMT_PIN_TSCLK, "tsclk"), | ||
292 | PINCTRL_PIN(WMT_PIN_LCDD0, "lcd_d0"), | ||
293 | PINCTRL_PIN(WMT_PIN_LCDD1, "lcd_d1"), | ||
294 | PINCTRL_PIN(WMT_PIN_LCDD2, "lcd_d2"), | ||
295 | PINCTRL_PIN(WMT_PIN_LCDD3, "lcd_d3"), | ||
296 | PINCTRL_PIN(WMT_PIN_LCDD4, "lcd_d4"), | ||
297 | PINCTRL_PIN(WMT_PIN_LCDD5, "lcd_d5"), | ||
298 | PINCTRL_PIN(WMT_PIN_LCDD6, "lcd_d6"), | ||
299 | PINCTRL_PIN(WMT_PIN_LCDD7, "lcd_d7"), | ||
300 | PINCTRL_PIN(WMT_PIN_LCDD8, "lcd_d8"), | ||
301 | PINCTRL_PIN(WMT_PIN_LCDD9, "lcd_d9"), | ||
302 | PINCTRL_PIN(WMT_PIN_LCDD10, "lcd_d10"), | ||
303 | PINCTRL_PIN(WMT_PIN_LCDD11, "lcd_d11"), | ||
304 | PINCTRL_PIN(WMT_PIN_LCDD12, "lcd_d12"), | ||
305 | PINCTRL_PIN(WMT_PIN_LCDD13, "lcd_d13"), | ||
306 | PINCTRL_PIN(WMT_PIN_LCDD14, "lcd_d14"), | ||
307 | PINCTRL_PIN(WMT_PIN_LCDD15, "lcd_d15"), | ||
308 | PINCTRL_PIN(WMT_PIN_LCDD16, "lcd_d16"), | ||
309 | PINCTRL_PIN(WMT_PIN_LCDD17, "lcd_d17"), | ||
310 | PINCTRL_PIN(WMT_PIN_LCDCLK, "lcd_clk"), | ||
311 | PINCTRL_PIN(WMT_PIN_LCDDEN, "lcd_den"), | ||
312 | PINCTRL_PIN(WMT_PIN_LCDLINE, "lcd_line"), | ||
313 | PINCTRL_PIN(WMT_PIN_LCDFRM, "lcd_frm"), | ||
314 | PINCTRL_PIN(WMT_PIN_LCDBIAS, "lcd_bias"), | ||
315 | }; | ||
316 | |||
317 | /* Order of these names must match the above list */ | ||
318 | static const char * const vt8500_groups[] = { | ||
319 | "extgpio0", | ||
320 | "extgpio1", | ||
321 | "extgpio2", | ||
322 | "extgpio3", | ||
323 | "extgpio4", | ||
324 | "extgpio5", | ||
325 | "extgpio6", | ||
326 | "extgpio7", | ||
327 | "extgpio8", | ||
328 | "uart0_rts", | ||
329 | "uart0_txd", | ||
330 | "uart0_cts", | ||
331 | "uart0_rxd", | ||
332 | "uart1_rts", | ||
333 | "uart1_txd", | ||
334 | "uart1_cts", | ||
335 | "uart1_rxd", | ||
336 | "spi0_clk", | ||
337 | "spi0_ss", | ||
338 | "spi0_miso", | ||
339 | "spi0_mosi", | ||
340 | "spi1_clk", | ||
341 | "spi1_ss", | ||
342 | "spi1_miso", | ||
343 | "spi1_mosi", | ||
344 | "spi2_clk", | ||
345 | "spi2_ss", | ||
346 | "spi2_miso", | ||
347 | "spi2_mosi", | ||
348 | "sd_data0", | ||
349 | "sd_data1", | ||
350 | "sd_data2", | ||
351 | "sd_data3", | ||
352 | "mmc_data0", | ||
353 | "mmc_data1", | ||
354 | "mmc_data2", | ||
355 | "mmc_data3", | ||
356 | "sd_clk", | ||
357 | "sd_wp", | ||
358 | "sd_cmd", | ||
359 | "ms_data0", | ||
360 | "ms_data1", | ||
361 | "ms_data2", | ||
362 | "ms_data3", | ||
363 | "ms_clk", | ||
364 | "ms_bs", | ||
365 | "ms_ins", | ||
366 | "i2c0_scl", | ||
367 | "i2c0_sda", | ||
368 | "i2c1_scl", | ||
369 | "i2c1_sda", | ||
370 | "mii0_rxd0", | ||
371 | "mii0_rxd1", | ||
372 | "mii0_rxd2", | ||
373 | "mii0_rxd3", | ||
374 | "mii0_rxclk", | ||
375 | "mii0_rxdv", | ||
376 | "mii0_rxerr", | ||
377 | "mii0_phyrst", | ||
378 | "mii0_txd0", | ||
379 | "mii0_txd1", | ||
380 | "mii0_txd2", | ||
381 | "mii0_txd3", | ||
382 | "mii0_txclk", | ||
383 | "mii0_txen", | ||
384 | "mii0_txerr", | ||
385 | "mii0_phypd", | ||
386 | "mii0_col", | ||
387 | "mii0_crs", | ||
388 | "mii0_mdio", | ||
389 | "mii0_mdc", | ||
390 | "see_cs", | ||
391 | "see_ck", | ||
392 | "see_di", | ||
393 | "see_do", | ||
394 | "ide_dreq0", | ||
395 | "ide_dreq1", | ||
396 | "ide_iow", | ||
397 | "ide_ior", | ||
398 | "ide_dack", | ||
399 | "ide_iordy", | ||
400 | "ide_intrq", | ||
401 | "vdin0", | ||
402 | "vdin1", | ||
403 | "vdin2", | ||
404 | "vdin3", | ||
405 | "vdin4", | ||
406 | "vdin5", | ||
407 | "vdin6", | ||
408 | "vdin7", | ||
409 | "vdout0", | ||
410 | "vdout1", | ||
411 | "vdout2", | ||
412 | "vdout3", | ||
413 | "vdout4", | ||
414 | "vdout5", | ||
415 | "nand_cle0", | ||
416 | "nand_cle1", | ||
417 | "vdout6_7", | ||
418 | "vhsync", | ||
419 | "vvsync", | ||
420 | "tsdin0", | ||
421 | "tsdin1", | ||
422 | "tsdin2", | ||
423 | "tsdin3", | ||
424 | "tsdin4", | ||
425 | "tsdin5", | ||
426 | "tsdin6", | ||
427 | "tsdin7", | ||
428 | "tssync", | ||
429 | "tsvalid", | ||
430 | "tsclk", | ||
431 | "lcd_d0", | ||
432 | "lcd_d1", | ||
433 | "lcd_d2", | ||
434 | "lcd_d3", | ||
435 | "lcd_d4", | ||
436 | "lcd_d5", | ||
437 | "lcd_d6", | ||
438 | "lcd_d7", | ||
439 | "lcd_d8", | ||
440 | "lcd_d9", | ||
441 | "lcd_d10", | ||
442 | "lcd_d11", | ||
443 | "lcd_d12", | ||
444 | "lcd_d13", | ||
445 | "lcd_d14", | ||
446 | "lcd_d15", | ||
447 | "lcd_d16", | ||
448 | "lcd_d17", | ||
449 | "lcd_clk", | ||
450 | "lcd_den", | ||
451 | "lcd_line", | ||
452 | "lcd_frm", | ||
453 | "lcd_bias", | ||
454 | }; | ||
455 | |||
456 | static int vt8500_pinctrl_probe(struct platform_device *pdev) | ||
457 | { | ||
458 | struct wmt_pinctrl_data *data; | ||
459 | |||
460 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
461 | if (!data) { | ||
462 | dev_err(&pdev->dev, "failed to allocate data\n"); | ||
463 | return -ENOMEM; | ||
464 | } | ||
465 | |||
466 | data->banks = vt8500_banks; | ||
467 | data->nbanks = ARRAY_SIZE(vt8500_banks); | ||
468 | data->pins = vt8500_pins; | ||
469 | data->npins = ARRAY_SIZE(vt8500_pins); | ||
470 | data->groups = vt8500_groups; | ||
471 | data->ngroups = ARRAY_SIZE(vt8500_groups); | ||
472 | |||
473 | return wmt_pinctrl_probe(pdev, data); | ||
474 | } | ||
475 | |||
476 | static int vt8500_pinctrl_remove(struct platform_device *pdev) | ||
477 | { | ||
478 | return wmt_pinctrl_remove(pdev); | ||
479 | } | ||
480 | |||
481 | static struct of_device_id wmt_pinctrl_of_match[] = { | ||
482 | { .compatible = "via,vt8500-pinctrl" }, | ||
483 | { /* sentinel */ }, | ||
484 | }; | ||
485 | |||
486 | static struct platform_driver wmt_pinctrl_driver = { | ||
487 | .probe = vt8500_pinctrl_probe, | ||
488 | .remove = vt8500_pinctrl_remove, | ||
489 | .driver = { | ||
490 | .name = "pinctrl-vt8500", | ||
491 | .owner = THIS_MODULE, | ||
492 | .of_match_table = wmt_pinctrl_of_match, | ||
493 | }, | ||
494 | }; | ||
495 | |||
496 | module_platform_driver(wmt_pinctrl_driver); | ||
497 | |||
498 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
499 | MODULE_DESCRIPTION("VIA VT8500 Pincontrol driver"); | ||
500 | MODULE_LICENSE("GPL v2"); | ||
501 | MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); | ||
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8505.c b/drivers/pinctrl/vt8500/pinctrl-wm8505.c new file mode 100644 index 000000000000..483ba732694e --- /dev/null +++ b/drivers/pinctrl/vt8500/pinctrl-wm8505.c | |||
@@ -0,0 +1,532 @@ | |||
1 | /* | ||
2 | * Pinctrl data for Wondermedia WM8505 SoC | ||
3 | * | ||
4 | * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/pinctrl/pinctrl.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include "pinctrl-wmt.h" | ||
23 | |||
24 | /* | ||
25 | * Describe the register offsets within the GPIO memory space | ||
26 | * The dedicated external GPIO's should always be listed in bank 0 | ||
27 | * so they are exported in the 0..31 range which is what users | ||
28 | * expect. | ||
29 | * | ||
30 | * Do not reorder these banks as it will change the pin numbering | ||
31 | */ | ||
32 | static const struct wmt_pinctrl_bank_registers wm8505_banks[] = { | ||
33 | WMT_PINCTRL_BANK(0x64, 0x8C, 0xB4, 0xDC, NO_REG, NO_REG), /* 0 */ | ||
34 | WMT_PINCTRL_BANK(0x40, 0x68, 0x90, 0xB8, NO_REG, NO_REG), /* 1 */ | ||
35 | WMT_PINCTRL_BANK(0x44, 0x6C, 0x94, 0xBC, NO_REG, NO_REG), /* 2 */ | ||
36 | WMT_PINCTRL_BANK(0x48, 0x70, 0x98, 0xC0, NO_REG, NO_REG), /* 3 */ | ||
37 | WMT_PINCTRL_BANK(0x4C, 0x74, 0x9C, 0xC4, NO_REG, NO_REG), /* 4 */ | ||
38 | WMT_PINCTRL_BANK(0x50, 0x78, 0xA0, 0xC8, NO_REG, NO_REG), /* 5 */ | ||
39 | WMT_PINCTRL_BANK(0x54, 0x7C, 0xA4, 0xD0, NO_REG, NO_REG), /* 6 */ | ||
40 | WMT_PINCTRL_BANK(0x58, 0x80, 0xA8, 0xD4, NO_REG, NO_REG), /* 7 */ | ||
41 | WMT_PINCTRL_BANK(0x5C, 0x84, 0xAC, 0xD8, NO_REG, NO_REG), /* 8 */ | ||
42 | WMT_PINCTRL_BANK(0x60, 0x88, 0xB0, 0xDC, NO_REG, NO_REG), /* 9 */ | ||
43 | WMT_PINCTRL_BANK(0x500, 0x504, 0x508, 0x50C, NO_REG, NO_REG), /* 10 */ | ||
44 | }; | ||
45 | |||
46 | /* Please keep sorted by bank/bit */ | ||
47 | #define WMT_PIN_EXTGPIO0 WMT_PIN(0, 0) | ||
48 | #define WMT_PIN_EXTGPIO1 WMT_PIN(0, 1) | ||
49 | #define WMT_PIN_EXTGPIO2 WMT_PIN(0, 2) | ||
50 | #define WMT_PIN_EXTGPIO3 WMT_PIN(0, 3) | ||
51 | #define WMT_PIN_EXTGPIO4 WMT_PIN(0, 4) | ||
52 | #define WMT_PIN_EXTGPIO5 WMT_PIN(0, 5) | ||
53 | #define WMT_PIN_EXTGPIO6 WMT_PIN(0, 6) | ||
54 | #define WMT_PIN_EXTGPIO7 WMT_PIN(0, 7) | ||
55 | #define WMT_PIN_WAKEUP0 WMT_PIN(0, 16) | ||
56 | #define WMT_PIN_WAKEUP1 WMT_PIN(0, 17) | ||
57 | #define WMT_PIN_WAKEUP2 WMT_PIN(0, 18) | ||
58 | #define WMT_PIN_WAKEUP3 WMT_PIN(0, 19) | ||
59 | #define WMT_PIN_SUSGPIO0 WMT_PIN(0, 21) | ||
60 | #define WMT_PIN_SDDATA0 WMT_PIN(1, 0) | ||
61 | #define WMT_PIN_SDDATA1 WMT_PIN(1, 1) | ||
62 | #define WMT_PIN_SDDATA2 WMT_PIN(1, 2) | ||
63 | #define WMT_PIN_SDDATA3 WMT_PIN(1, 3) | ||
64 | #define WMT_PIN_MMCDATA0 WMT_PIN(1, 4) | ||
65 | #define WMT_PIN_MMCDATA1 WMT_PIN(1, 5) | ||
66 | #define WMT_PIN_MMCDATA2 WMT_PIN(1, 6) | ||
67 | #define WMT_PIN_MMCDATA3 WMT_PIN(1, 7) | ||
68 | #define WMT_PIN_VDIN0 WMT_PIN(2, 0) | ||
69 | #define WMT_PIN_VDIN1 WMT_PIN(2, 1) | ||
70 | #define WMT_PIN_VDIN2 WMT_PIN(2, 2) | ||
71 | #define WMT_PIN_VDIN3 WMT_PIN(2, 3) | ||
72 | #define WMT_PIN_VDIN4 WMT_PIN(2, 4) | ||
73 | #define WMT_PIN_VDIN5 WMT_PIN(2, 5) | ||
74 | #define WMT_PIN_VDIN6 WMT_PIN(2, 6) | ||
75 | #define WMT_PIN_VDIN7 WMT_PIN(2, 7) | ||
76 | #define WMT_PIN_VDOUT0 WMT_PIN(2, 8) | ||
77 | #define WMT_PIN_VDOUT1 WMT_PIN(2, 9) | ||
78 | #define WMT_PIN_VDOUT2 WMT_PIN(2, 10) | ||
79 | #define WMT_PIN_VDOUT3 WMT_PIN(2, 11) | ||
80 | #define WMT_PIN_VDOUT4 WMT_PIN(2, 12) | ||
81 | #define WMT_PIN_VDOUT5 WMT_PIN(2, 13) | ||
82 | #define WMT_PIN_VDOUT6 WMT_PIN(2, 14) | ||
83 | #define WMT_PIN_VDOUT7 WMT_PIN(2, 15) | ||
84 | #define WMT_PIN_VDOUT8 WMT_PIN(2, 16) | ||
85 | #define WMT_PIN_VDOUT9 WMT_PIN(2, 17) | ||
86 | #define WMT_PIN_VDOUT10 WMT_PIN(2, 18) | ||
87 | #define WMT_PIN_VDOUT11 WMT_PIN(2, 19) | ||
88 | #define WMT_PIN_VDOUT12 WMT_PIN(2, 20) | ||
89 | #define WMT_PIN_VDOUT13 WMT_PIN(2, 21) | ||
90 | #define WMT_PIN_VDOUT14 WMT_PIN(2, 22) | ||
91 | #define WMT_PIN_VDOUT15 WMT_PIN(2, 23) | ||
92 | #define WMT_PIN_VDOUT16 WMT_PIN(2, 24) | ||
93 | #define WMT_PIN_VDOUT17 WMT_PIN(2, 25) | ||
94 | #define WMT_PIN_VDOUT18 WMT_PIN(2, 26) | ||
95 | #define WMT_PIN_VDOUT19 WMT_PIN(2, 27) | ||
96 | #define WMT_PIN_VDOUT20 WMT_PIN(2, 28) | ||
97 | #define WMT_PIN_VDOUT21 WMT_PIN(2, 29) | ||
98 | #define WMT_PIN_VDOUT22 WMT_PIN(2, 30) | ||
99 | #define WMT_PIN_VDOUT23 WMT_PIN(2, 31) | ||
100 | #define WMT_PIN_VHSYNC WMT_PIN(3, 0) | ||
101 | #define WMT_PIN_VVSYNC WMT_PIN(3, 1) | ||
102 | #define WMT_PIN_VGAHSYNC WMT_PIN(3, 2) | ||
103 | #define WMT_PIN_VGAVSYNC WMT_PIN(3, 3) | ||
104 | #define WMT_PIN_VDHSYNC WMT_PIN(3, 4) | ||
105 | #define WMT_PIN_VDVSYNC WMT_PIN(3, 5) | ||
106 | #define WMT_PIN_NORD0 WMT_PIN(4, 0) | ||
107 | #define WMT_PIN_NORD1 WMT_PIN(4, 1) | ||
108 | #define WMT_PIN_NORD2 WMT_PIN(4, 2) | ||
109 | #define WMT_PIN_NORD3 WMT_PIN(4, 3) | ||
110 | #define WMT_PIN_NORD4 WMT_PIN(4, 4) | ||
111 | #define WMT_PIN_NORD5 WMT_PIN(4, 5) | ||
112 | #define WMT_PIN_NORD6 WMT_PIN(4, 6) | ||
113 | #define WMT_PIN_NORD7 WMT_PIN(4, 7) | ||
114 | #define WMT_PIN_NORD8 WMT_PIN(4, 8) | ||
115 | #define WMT_PIN_NORD9 WMT_PIN(4, 9) | ||
116 | #define WMT_PIN_NORD10 WMT_PIN(4, 10) | ||
117 | #define WMT_PIN_NORD11 WMT_PIN(4, 11) | ||
118 | #define WMT_PIN_NORD12 WMT_PIN(4, 12) | ||
119 | #define WMT_PIN_NORD13 WMT_PIN(4, 13) | ||
120 | #define WMT_PIN_NORD14 WMT_PIN(4, 14) | ||
121 | #define WMT_PIN_NORD15 WMT_PIN(4, 15) | ||
122 | #define WMT_PIN_NORA0 WMT_PIN(5, 0) | ||
123 | #define WMT_PIN_NORA1 WMT_PIN(5, 1) | ||
124 | #define WMT_PIN_NORA2 WMT_PIN(5, 2) | ||
125 | #define WMT_PIN_NORA3 WMT_PIN(5, 3) | ||
126 | #define WMT_PIN_NORA4 WMT_PIN(5, 4) | ||
127 | #define WMT_PIN_NORA5 WMT_PIN(5, 5) | ||
128 | #define WMT_PIN_NORA6 WMT_PIN(5, 6) | ||
129 | #define WMT_PIN_NORA7 WMT_PIN(5, 7) | ||
130 | #define WMT_PIN_NORA8 WMT_PIN(5, 8) | ||
131 | #define WMT_PIN_NORA9 WMT_PIN(5, 9) | ||
132 | #define WMT_PIN_NORA10 WMT_PIN(5, 10) | ||
133 | #define WMT_PIN_NORA11 WMT_PIN(5, 11) | ||
134 | #define WMT_PIN_NORA12 WMT_PIN(5, 12) | ||
135 | #define WMT_PIN_NORA13 WMT_PIN(5, 13) | ||
136 | #define WMT_PIN_NORA14 WMT_PIN(5, 14) | ||
137 | #define WMT_PIN_NORA15 WMT_PIN(5, 15) | ||
138 | #define WMT_PIN_NORA16 WMT_PIN(5, 16) | ||
139 | #define WMT_PIN_NORA17 WMT_PIN(5, 17) | ||
140 | #define WMT_PIN_NORA18 WMT_PIN(5, 18) | ||
141 | #define WMT_PIN_NORA19 WMT_PIN(5, 19) | ||
142 | #define WMT_PIN_NORA20 WMT_PIN(5, 20) | ||
143 | #define WMT_PIN_NORA21 WMT_PIN(5, 21) | ||
144 | #define WMT_PIN_NORA22 WMT_PIN(5, 22) | ||
145 | #define WMT_PIN_NORA23 WMT_PIN(5, 23) | ||
146 | #define WMT_PIN_NORA24 WMT_PIN(5, 24) | ||
147 | #define WMT_PIN_AC97SDI WMT_PIN(6, 0) | ||
148 | #define WMT_PIN_AC97SYNC WMT_PIN(6, 1) | ||
149 | #define WMT_PIN_AC97SDO WMT_PIN(6, 2) | ||
150 | #define WMT_PIN_AC97BCLK WMT_PIN(6, 3) | ||
151 | #define WMT_PIN_AC97RST WMT_PIN(6, 4) | ||
152 | #define WMT_PIN_SFDO WMT_PIN(7, 0) | ||
153 | #define WMT_PIN_SFCS0 WMT_PIN(7, 1) | ||
154 | #define WMT_PIN_SFCS1 WMT_PIN(7, 2) | ||
155 | #define WMT_PIN_SFCLK WMT_PIN(7, 3) | ||
156 | #define WMT_PIN_SFDI WMT_PIN(7, 4) | ||
157 | #define WMT_PIN_SPI0CLK WMT_PIN(8, 0) | ||
158 | #define WMT_PIN_SPI0MISO WMT_PIN(8, 1) | ||
159 | #define WMT_PIN_SPI0MOSI WMT_PIN(8, 2) | ||
160 | #define WMT_PIN_SPI0SS WMT_PIN(8, 3) | ||
161 | #define WMT_PIN_SPI1CLK WMT_PIN(8, 4) | ||
162 | #define WMT_PIN_SPI1MISO WMT_PIN(8, 5) | ||
163 | #define WMT_PIN_SPI1MOSI WMT_PIN(8, 6) | ||
164 | #define WMT_PIN_SPI1SS WMT_PIN(8, 7) | ||
165 | #define WMT_PIN_SPI2CLK WMT_PIN(8, 8) | ||
166 | #define WMT_PIN_SPI2MISO WMT_PIN(8, 9) | ||
167 | #define WMT_PIN_SPI2MOSI WMT_PIN(8, 10) | ||
168 | #define WMT_PIN_SPI2SS WMT_PIN(8, 11) | ||
169 | #define WMT_PIN_UART0_RTS WMT_PIN(9, 0) | ||
170 | #define WMT_PIN_UART0_TXD WMT_PIN(9, 1) | ||
171 | #define WMT_PIN_UART0_CTS WMT_PIN(9, 2) | ||
172 | #define WMT_PIN_UART0_RXD WMT_PIN(9, 3) | ||
173 | #define WMT_PIN_UART1_RTS WMT_PIN(9, 4) | ||
174 | #define WMT_PIN_UART1_TXD WMT_PIN(9, 5) | ||
175 | #define WMT_PIN_UART1_CTS WMT_PIN(9, 6) | ||
176 | #define WMT_PIN_UART1_RXD WMT_PIN(9, 7) | ||
177 | #define WMT_PIN_UART2_RTS WMT_PIN(9, 8) | ||
178 | #define WMT_PIN_UART2_TXD WMT_PIN(9, 9) | ||
179 | #define WMT_PIN_UART2_CTS WMT_PIN(9, 10) | ||
180 | #define WMT_PIN_UART2_RXD WMT_PIN(9, 11) | ||
181 | #define WMT_PIN_UART3_RTS WMT_PIN(9, 12) | ||
182 | #define WMT_PIN_UART3_TXD WMT_PIN(9, 13) | ||
183 | #define WMT_PIN_UART3_CTS WMT_PIN(9, 14) | ||
184 | #define WMT_PIN_UART3_RXD WMT_PIN(9, 15) | ||
185 | #define WMT_PIN_I2C0SCL WMT_PIN(10, 0) | ||
186 | #define WMT_PIN_I2C0SDA WMT_PIN(10, 1) | ||
187 | #define WMT_PIN_I2C1SCL WMT_PIN(10, 2) | ||
188 | #define WMT_PIN_I2C1SDA WMT_PIN(10, 3) | ||
189 | #define WMT_PIN_I2C2SCL WMT_PIN(10, 4) | ||
190 | #define WMT_PIN_I2C2SDA WMT_PIN(10, 5) | ||
191 | |||
192 | static const struct pinctrl_pin_desc wm8505_pins[] = { | ||
193 | PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"), | ||
194 | PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"), | ||
195 | PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"), | ||
196 | PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"), | ||
197 | PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"), | ||
198 | PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"), | ||
199 | PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"), | ||
200 | PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"), | ||
201 | PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"), | ||
202 | PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"), | ||
203 | PINCTRL_PIN(WMT_PIN_WAKEUP2, "wakeup2"), | ||
204 | PINCTRL_PIN(WMT_PIN_WAKEUP3, "wakeup3"), | ||
205 | PINCTRL_PIN(WMT_PIN_SUSGPIO0, "susgpio0"), | ||
206 | PINCTRL_PIN(WMT_PIN_SDDATA0, "sd_data0"), | ||
207 | PINCTRL_PIN(WMT_PIN_SDDATA1, "sd_data1"), | ||
208 | PINCTRL_PIN(WMT_PIN_SDDATA2, "sd_data2"), | ||
209 | PINCTRL_PIN(WMT_PIN_SDDATA3, "sd_data3"), | ||
210 | PINCTRL_PIN(WMT_PIN_MMCDATA0, "mmc_data0"), | ||
211 | PINCTRL_PIN(WMT_PIN_MMCDATA1, "mmc_data1"), | ||
212 | PINCTRL_PIN(WMT_PIN_MMCDATA2, "mmc_data2"), | ||
213 | PINCTRL_PIN(WMT_PIN_MMCDATA3, "mmc_data3"), | ||
214 | PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"), | ||
215 | PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"), | ||
216 | PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"), | ||
217 | PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"), | ||
218 | PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"), | ||
219 | PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"), | ||
220 | PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"), | ||
221 | PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"), | ||
222 | PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"), | ||
223 | PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"), | ||
224 | PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"), | ||
225 | PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"), | ||
226 | PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"), | ||
227 | PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"), | ||
228 | PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"), | ||
229 | PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"), | ||
230 | PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"), | ||
231 | PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"), | ||
232 | PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"), | ||
233 | PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"), | ||
234 | PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"), | ||
235 | PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"), | ||
236 | PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"), | ||
237 | PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"), | ||
238 | PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"), | ||
239 | PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"), | ||
240 | PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"), | ||
241 | PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"), | ||
242 | PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"), | ||
243 | PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"), | ||
244 | PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"), | ||
245 | PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"), | ||
246 | PINCTRL_PIN(WMT_PIN_VHSYNC, "v_hsync"), | ||
247 | PINCTRL_PIN(WMT_PIN_VVSYNC, "v_vsync"), | ||
248 | PINCTRL_PIN(WMT_PIN_VGAHSYNC, "vga_hsync"), | ||
249 | PINCTRL_PIN(WMT_PIN_VGAVSYNC, "vga_vsync"), | ||
250 | PINCTRL_PIN(WMT_PIN_VDHSYNC, "vd_hsync"), | ||
251 | PINCTRL_PIN(WMT_PIN_VDVSYNC, "vd_vsync"), | ||
252 | PINCTRL_PIN(WMT_PIN_NORD0, "nor_d0"), | ||
253 | PINCTRL_PIN(WMT_PIN_NORD1, "nor_d1"), | ||
254 | PINCTRL_PIN(WMT_PIN_NORD2, "nor_d2"), | ||
255 | PINCTRL_PIN(WMT_PIN_NORD3, "nor_d3"), | ||
256 | PINCTRL_PIN(WMT_PIN_NORD4, "nor_d4"), | ||
257 | PINCTRL_PIN(WMT_PIN_NORD5, "nor_d5"), | ||
258 | PINCTRL_PIN(WMT_PIN_NORD6, "nor_d6"), | ||
259 | PINCTRL_PIN(WMT_PIN_NORD7, "nor_d7"), | ||
260 | PINCTRL_PIN(WMT_PIN_NORD8, "nor_d8"), | ||
261 | PINCTRL_PIN(WMT_PIN_NORD9, "nor_d9"), | ||
262 | PINCTRL_PIN(WMT_PIN_NORD10, "nor_d10"), | ||
263 | PINCTRL_PIN(WMT_PIN_NORD11, "nor_d11"), | ||
264 | PINCTRL_PIN(WMT_PIN_NORD12, "nor_d12"), | ||
265 | PINCTRL_PIN(WMT_PIN_NORD13, "nor_d13"), | ||
266 | PINCTRL_PIN(WMT_PIN_NORD14, "nor_d14"), | ||
267 | PINCTRL_PIN(WMT_PIN_NORD15, "nor_d15"), | ||
268 | PINCTRL_PIN(WMT_PIN_NORA0, "nor_a0"), | ||
269 | PINCTRL_PIN(WMT_PIN_NORA1, "nor_a1"), | ||
270 | PINCTRL_PIN(WMT_PIN_NORA2, "nor_a2"), | ||
271 | PINCTRL_PIN(WMT_PIN_NORA3, "nor_a3"), | ||
272 | PINCTRL_PIN(WMT_PIN_NORA4, "nor_a4"), | ||
273 | PINCTRL_PIN(WMT_PIN_NORA5, "nor_a5"), | ||
274 | PINCTRL_PIN(WMT_PIN_NORA6, "nor_a6"), | ||
275 | PINCTRL_PIN(WMT_PIN_NORA7, "nor_a7"), | ||
276 | PINCTRL_PIN(WMT_PIN_NORA8, "nor_a8"), | ||
277 | PINCTRL_PIN(WMT_PIN_NORA9, "nor_a9"), | ||
278 | PINCTRL_PIN(WMT_PIN_NORA10, "nor_a10"), | ||
279 | PINCTRL_PIN(WMT_PIN_NORA11, "nor_a11"), | ||
280 | PINCTRL_PIN(WMT_PIN_NORA12, "nor_a12"), | ||
281 | PINCTRL_PIN(WMT_PIN_NORA13, "nor_a13"), | ||
282 | PINCTRL_PIN(WMT_PIN_NORA14, "nor_a14"), | ||
283 | PINCTRL_PIN(WMT_PIN_NORA15, "nor_a15"), | ||
284 | PINCTRL_PIN(WMT_PIN_NORA16, "nor_a16"), | ||
285 | PINCTRL_PIN(WMT_PIN_NORA17, "nor_a17"), | ||
286 | PINCTRL_PIN(WMT_PIN_NORA18, "nor_a18"), | ||
287 | PINCTRL_PIN(WMT_PIN_NORA19, "nor_a19"), | ||
288 | PINCTRL_PIN(WMT_PIN_NORA20, "nor_a20"), | ||
289 | PINCTRL_PIN(WMT_PIN_NORA21, "nor_a21"), | ||
290 | PINCTRL_PIN(WMT_PIN_NORA22, "nor_a22"), | ||
291 | PINCTRL_PIN(WMT_PIN_NORA23, "nor_a23"), | ||
292 | PINCTRL_PIN(WMT_PIN_NORA24, "nor_a24"), | ||
293 | PINCTRL_PIN(WMT_PIN_AC97SDI, "ac97_sdi"), | ||
294 | PINCTRL_PIN(WMT_PIN_AC97SYNC, "ac97_sync"), | ||
295 | PINCTRL_PIN(WMT_PIN_AC97SDO, "ac97_sdo"), | ||
296 | PINCTRL_PIN(WMT_PIN_AC97BCLK, "ac97_bclk"), | ||
297 | PINCTRL_PIN(WMT_PIN_AC97RST, "ac97_rst"), | ||
298 | PINCTRL_PIN(WMT_PIN_SFDO, "sf_do"), | ||
299 | PINCTRL_PIN(WMT_PIN_SFCS0, "sf_cs0"), | ||
300 | PINCTRL_PIN(WMT_PIN_SFCS1, "sf_cs1"), | ||
301 | PINCTRL_PIN(WMT_PIN_SFCLK, "sf_clk"), | ||
302 | PINCTRL_PIN(WMT_PIN_SFDI, "sf_di"), | ||
303 | PINCTRL_PIN(WMT_PIN_SPI0CLK, "spi0_clk"), | ||
304 | PINCTRL_PIN(WMT_PIN_SPI0MISO, "spi0_miso"), | ||
305 | PINCTRL_PIN(WMT_PIN_SPI0MOSI, "spi0_mosi"), | ||
306 | PINCTRL_PIN(WMT_PIN_SPI0SS, "spi0_ss"), | ||
307 | PINCTRL_PIN(WMT_PIN_SPI1CLK, "spi1_clk"), | ||
308 | PINCTRL_PIN(WMT_PIN_SPI1MISO, "spi1_miso"), | ||
309 | PINCTRL_PIN(WMT_PIN_SPI1MOSI, "spi1_mosi"), | ||
310 | PINCTRL_PIN(WMT_PIN_SPI1SS, "spi1_ss"), | ||
311 | PINCTRL_PIN(WMT_PIN_SPI2CLK, "spi2_clk"), | ||
312 | PINCTRL_PIN(WMT_PIN_SPI2MISO, "spi2_miso"), | ||
313 | PINCTRL_PIN(WMT_PIN_SPI2MOSI, "spi2_mosi"), | ||
314 | PINCTRL_PIN(WMT_PIN_SPI2SS, "spi2_ss"), | ||
315 | PINCTRL_PIN(WMT_PIN_UART0_RTS, "uart0_rts"), | ||
316 | PINCTRL_PIN(WMT_PIN_UART0_TXD, "uart0_txd"), | ||
317 | PINCTRL_PIN(WMT_PIN_UART0_CTS, "uart0_cts"), | ||
318 | PINCTRL_PIN(WMT_PIN_UART0_RXD, "uart0_rxd"), | ||
319 | PINCTRL_PIN(WMT_PIN_UART1_RTS, "uart1_rts"), | ||
320 | PINCTRL_PIN(WMT_PIN_UART1_TXD, "uart1_txd"), | ||
321 | PINCTRL_PIN(WMT_PIN_UART1_CTS, "uart1_cts"), | ||
322 | PINCTRL_PIN(WMT_PIN_UART1_RXD, "uart1_rxd"), | ||
323 | PINCTRL_PIN(WMT_PIN_UART2_RTS, "uart2_rts"), | ||
324 | PINCTRL_PIN(WMT_PIN_UART2_TXD, "uart2_txd"), | ||
325 | PINCTRL_PIN(WMT_PIN_UART2_CTS, "uart2_cts"), | ||
326 | PINCTRL_PIN(WMT_PIN_UART2_RXD, "uart2_rxd"), | ||
327 | PINCTRL_PIN(WMT_PIN_UART3_RTS, "uart3_rts"), | ||
328 | PINCTRL_PIN(WMT_PIN_UART3_TXD, "uart3_txd"), | ||
329 | PINCTRL_PIN(WMT_PIN_UART3_CTS, "uart3_cts"), | ||
330 | PINCTRL_PIN(WMT_PIN_UART3_RXD, "uart3_rxd"), | ||
331 | PINCTRL_PIN(WMT_PIN_I2C0SCL, "i2c0_scl"), | ||
332 | PINCTRL_PIN(WMT_PIN_I2C0SDA, "i2c0_sda"), | ||
333 | PINCTRL_PIN(WMT_PIN_I2C1SCL, "i2c1_scl"), | ||
334 | PINCTRL_PIN(WMT_PIN_I2C1SDA, "i2c1_sda"), | ||
335 | PINCTRL_PIN(WMT_PIN_I2C2SCL, "i2c2_scl"), | ||
336 | PINCTRL_PIN(WMT_PIN_I2C2SDA, "i2c2_sda"), | ||
337 | }; | ||
338 | |||
339 | /* Order of these names must match the above list */ | ||
340 | static const char * const wm8505_groups[] = { | ||
341 | "extgpio0", | ||
342 | "extgpio1", | ||
343 | "extgpio2", | ||
344 | "extgpio3", | ||
345 | "extgpio4", | ||
346 | "extgpio5", | ||
347 | "extgpio6", | ||
348 | "extgpio7", | ||
349 | "wakeup0", | ||
350 | "wakeup1", | ||
351 | "wakeup2", | ||
352 | "wakeup3", | ||
353 | "susgpio0", | ||
354 | "sd_data0", | ||
355 | "sd_data1", | ||
356 | "sd_data2", | ||
357 | "sd_data3", | ||
358 | "mmc_data0", | ||
359 | "mmc_data1", | ||
360 | "mmc_data2", | ||
361 | "mmc_data3", | ||
362 | "vdin0", | ||
363 | "vdin1", | ||
364 | "vdin2", | ||
365 | "vdin3", | ||
366 | "vdin4", | ||
367 | "vdin5", | ||
368 | "vdin6", | ||
369 | "vdin7", | ||
370 | "vdout0", | ||
371 | "vdout1", | ||
372 | "vdout2", | ||
373 | "vdout3", | ||
374 | "vdout4", | ||
375 | "vdout5", | ||
376 | "vdout6", | ||
377 | "vdout7", | ||
378 | "vdout8", | ||
379 | "vdout9", | ||
380 | "vdout10", | ||
381 | "vdout11", | ||
382 | "vdout12", | ||
383 | "vdout13", | ||
384 | "vdout14", | ||
385 | "vdout15", | ||
386 | "vdout16", | ||
387 | "vdout17", | ||
388 | "vdout18", | ||
389 | "vdout19", | ||
390 | "vdout20", | ||
391 | "vdout21", | ||
392 | "vdout22", | ||
393 | "vdout23", | ||
394 | "v_hsync", | ||
395 | "v_vsync", | ||
396 | "vga_hsync", | ||
397 | "vga_vsync", | ||
398 | "vd_hsync", | ||
399 | "vd_vsync", | ||
400 | "nor_d0", | ||
401 | "nor_d1", | ||
402 | "nor_d2", | ||
403 | "nor_d3", | ||
404 | "nor_d4", | ||
405 | "nor_d5", | ||
406 | "nor_d6", | ||
407 | "nor_d7", | ||
408 | "nor_d8", | ||
409 | "nor_d9", | ||
410 | "nor_d10", | ||
411 | "nor_d11", | ||
412 | "nor_d12", | ||
413 | "nor_d13", | ||
414 | "nor_d14", | ||
415 | "nor_d15", | ||
416 | "nor_a0", | ||
417 | "nor_a1", | ||
418 | "nor_a2", | ||
419 | "nor_a3", | ||
420 | "nor_a4", | ||
421 | "nor_a5", | ||
422 | "nor_a6", | ||
423 | "nor_a7", | ||
424 | "nor_a8", | ||
425 | "nor_a9", | ||
426 | "nor_a10", | ||
427 | "nor_a11", | ||
428 | "nor_a12", | ||
429 | "nor_a13", | ||
430 | "nor_a14", | ||
431 | "nor_a15", | ||
432 | "nor_a16", | ||
433 | "nor_a17", | ||
434 | "nor_a18", | ||
435 | "nor_a19", | ||
436 | "nor_a20", | ||
437 | "nor_a21", | ||
438 | "nor_a22", | ||
439 | "nor_a23", | ||
440 | "nor_a24", | ||
441 | "ac97_sdi", | ||
442 | "ac97_sync", | ||
443 | "ac97_sdo", | ||
444 | "ac97_bclk", | ||
445 | "ac97_rst", | ||
446 | "sf_do", | ||
447 | "sf_cs0", | ||
448 | "sf_cs1", | ||
449 | "sf_clk", | ||
450 | "sf_di", | ||
451 | "spi0_clk", | ||
452 | "spi0_miso", | ||
453 | "spi0_mosi", | ||
454 | "spi0_ss", | ||
455 | "spi1_clk", | ||
456 | "spi1_miso", | ||
457 | "spi1_mosi", | ||
458 | "spi1_ss", | ||
459 | "spi2_clk", | ||
460 | "spi2_miso", | ||
461 | "spi2_mosi", | ||
462 | "spi2_ss", | ||
463 | "uart0_rts", | ||
464 | "uart0_txd", | ||
465 | "uart0_cts", | ||
466 | "uart0_rxd", | ||
467 | "uart1_rts", | ||
468 | "uart1_txd", | ||
469 | "uart1_cts", | ||
470 | "uart1_rxd", | ||
471 | "uart2_rts", | ||
472 | "uart2_txd", | ||
473 | "uart2_cts", | ||
474 | "uart2_rxd", | ||
475 | "uart3_rts", | ||
476 | "uart3_txd", | ||
477 | "uart3_cts", | ||
478 | "uart3_rxd", | ||
479 | "i2c0_scl", | ||
480 | "i2c0_sda", | ||
481 | "i2c1_scl", | ||
482 | "i2c1_sda", | ||
483 | "i2c2_scl", | ||
484 | "i2c2_sda", | ||
485 | }; | ||
486 | |||
487 | static int wm8505_pinctrl_probe(struct platform_device *pdev) | ||
488 | { | ||
489 | struct wmt_pinctrl_data *data; | ||
490 | |||
491 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
492 | if (!data) { | ||
493 | dev_err(&pdev->dev, "failed to allocate data\n"); | ||
494 | return -ENOMEM; | ||
495 | } | ||
496 | |||
497 | data->banks = wm8505_banks; | ||
498 | data->nbanks = ARRAY_SIZE(wm8505_banks); | ||
499 | data->pins = wm8505_pins; | ||
500 | data->npins = ARRAY_SIZE(wm8505_pins); | ||
501 | data->groups = wm8505_groups; | ||
502 | data->ngroups = ARRAY_SIZE(wm8505_groups); | ||
503 | |||
504 | return wmt_pinctrl_probe(pdev, data); | ||
505 | } | ||
506 | |||
507 | static int wm8505_pinctrl_remove(struct platform_device *pdev) | ||
508 | { | ||
509 | return wmt_pinctrl_remove(pdev); | ||
510 | } | ||
511 | |||
512 | static struct of_device_id wmt_pinctrl_of_match[] = { | ||
513 | { .compatible = "wm,wm8505-pinctrl" }, | ||
514 | { /* sentinel */ }, | ||
515 | }; | ||
516 | |||
517 | static struct platform_driver wmt_pinctrl_driver = { | ||
518 | .probe = wm8505_pinctrl_probe, | ||
519 | .remove = wm8505_pinctrl_remove, | ||
520 | .driver = { | ||
521 | .name = "pinctrl-wm8505", | ||
522 | .owner = THIS_MODULE, | ||
523 | .of_match_table = wmt_pinctrl_of_match, | ||
524 | }, | ||
525 | }; | ||
526 | |||
527 | module_platform_driver(wmt_pinctrl_driver); | ||
528 | |||
529 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
530 | MODULE_DESCRIPTION("Wondermedia WM8505 Pincontrol driver"); | ||
531 | MODULE_LICENSE("GPL v2"); | ||
532 | MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); | ||
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8650.c b/drivers/pinctrl/vt8500/pinctrl-wm8650.c new file mode 100644 index 000000000000..7de57f063153 --- /dev/null +++ b/drivers/pinctrl/vt8500/pinctrl-wm8650.c | |||
@@ -0,0 +1,370 @@ | |||
1 | /* | ||
2 | * Pinctrl data for Wondermedia WM8650 SoC | ||
3 | * | ||
4 | * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/pinctrl/pinctrl.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include "pinctrl-wmt.h" | ||
23 | |||
24 | /* | ||
25 | * Describe the register offsets within the GPIO memory space | ||
26 | * The dedicated external GPIO's should always be listed in bank 0 | ||
27 | * so they are exported in the 0..31 range which is what users | ||
28 | * expect. | ||
29 | * | ||
30 | * Do not reorder these banks as it will change the pin numbering | ||
31 | */ | ||
32 | static const struct wmt_pinctrl_bank_registers wm8650_banks[] = { | ||
33 | WMT_PINCTRL_BANK(0x40, 0x80, 0xC0, 0x00, 0x480, 0x4C0), /* 0 */ | ||
34 | WMT_PINCTRL_BANK(0x44, 0x84, 0xC4, 0x04, 0x484, 0x4C4), /* 1 */ | ||
35 | WMT_PINCTRL_BANK(0x48, 0x88, 0xC8, 0x08, 0x488, 0x4C8), /* 2 */ | ||
36 | WMT_PINCTRL_BANK(0x4C, 0x8C, 0xCC, 0x0C, 0x48C, 0x4CC), /* 3 */ | ||
37 | WMT_PINCTRL_BANK(0x50, 0x90, 0xD0, 0x10, 0x490, 0x4D0), /* 4 */ | ||
38 | WMT_PINCTRL_BANK(0x54, 0x94, 0xD4, 0x14, 0x494, 0x4D4), /* 5 */ | ||
39 | WMT_PINCTRL_BANK(0x58, 0x98, 0xD8, 0x18, 0x498, 0x4D8), /* 6 */ | ||
40 | WMT_PINCTRL_BANK(0x5C, 0x9C, 0xDC, 0x1C, 0x49C, 0x4DC), /* 7 */ | ||
41 | }; | ||
42 | |||
43 | /* Please keep sorted by bank/bit */ | ||
44 | #define WMT_PIN_EXTGPIO0 WMT_PIN(0, 0) | ||
45 | #define WMT_PIN_EXTGPIO1 WMT_PIN(0, 1) | ||
46 | #define WMT_PIN_EXTGPIO2 WMT_PIN(0, 2) | ||
47 | #define WMT_PIN_EXTGPIO3 WMT_PIN(0, 3) | ||
48 | #define WMT_PIN_EXTGPIO4 WMT_PIN(0, 4) | ||
49 | #define WMT_PIN_EXTGPIO5 WMT_PIN(0, 5) | ||
50 | #define WMT_PIN_EXTGPIO6 WMT_PIN(0, 6) | ||
51 | #define WMT_PIN_EXTGPIO7 WMT_PIN(0, 7) | ||
52 | #define WMT_PIN_WAKEUP0 WMT_PIN(0, 16) | ||
53 | #define WMT_PIN_WAKEUP1 WMT_PIN(0, 17) | ||
54 | #define WMT_PIN_SUSGPIO0 WMT_PIN(0, 21) | ||
55 | #define WMT_PIN_SD0CD WMT_PIN(0, 28) | ||
56 | #define WMT_PIN_SD1CD WMT_PIN(0, 29) | ||
57 | #define WMT_PIN_VDOUT0 WMT_PIN(1, 0) | ||
58 | #define WMT_PIN_VDOUT1 WMT_PIN(1, 1) | ||
59 | #define WMT_PIN_VDOUT2 WMT_PIN(1, 2) | ||
60 | #define WMT_PIN_VDOUT3 WMT_PIN(1, 3) | ||
61 | #define WMT_PIN_VDOUT4 WMT_PIN(1, 4) | ||
62 | #define WMT_PIN_VDOUT5 WMT_PIN(1, 5) | ||
63 | #define WMT_PIN_VDOUT6 WMT_PIN(1, 6) | ||
64 | #define WMT_PIN_VDOUT7 WMT_PIN(1, 7) | ||
65 | #define WMT_PIN_VDOUT8 WMT_PIN(1, 8) | ||
66 | #define WMT_PIN_VDOUT9 WMT_PIN(1, 9) | ||
67 | #define WMT_PIN_VDOUT10 WMT_PIN(1, 10) | ||
68 | #define WMT_PIN_VDOUT11 WMT_PIN(1, 11) | ||
69 | #define WMT_PIN_VDOUT12 WMT_PIN(1, 12) | ||
70 | #define WMT_PIN_VDOUT13 WMT_PIN(1, 13) | ||
71 | #define WMT_PIN_VDOUT14 WMT_PIN(1, 14) | ||
72 | #define WMT_PIN_VDOUT15 WMT_PIN(1, 15) | ||
73 | #define WMT_PIN_VDOUT16 WMT_PIN(1, 16) | ||
74 | #define WMT_PIN_VDOUT17 WMT_PIN(1, 17) | ||
75 | #define WMT_PIN_VDOUT18 WMT_PIN(1, 18) | ||
76 | #define WMT_PIN_VDOUT19 WMT_PIN(1, 19) | ||
77 | #define WMT_PIN_VDOUT20 WMT_PIN(1, 20) | ||
78 | #define WMT_PIN_VDOUT21 WMT_PIN(1, 21) | ||
79 | #define WMT_PIN_VDOUT22 WMT_PIN(1, 22) | ||
80 | #define WMT_PIN_VDOUT23 WMT_PIN(1, 23) | ||
81 | #define WMT_PIN_VDIN0 WMT_PIN(2, 0) | ||
82 | #define WMT_PIN_VDIN1 WMT_PIN(2, 1) | ||
83 | #define WMT_PIN_VDIN2 WMT_PIN(2, 2) | ||
84 | #define WMT_PIN_VDIN3 WMT_PIN(2, 3) | ||
85 | #define WMT_PIN_VDIN4 WMT_PIN(2, 4) | ||
86 | #define WMT_PIN_VDIN5 WMT_PIN(2, 5) | ||
87 | #define WMT_PIN_VDIN6 WMT_PIN(2, 6) | ||
88 | #define WMT_PIN_VDIN7 WMT_PIN(2, 7) | ||
89 | #define WMT_PIN_I2C1SCL WMT_PIN(2, 12) | ||
90 | #define WMT_PIN_I2C1SDA WMT_PIN(2, 13) | ||
91 | #define WMT_PIN_SPI0MOSI WMT_PIN(2, 24) | ||
92 | #define WMT_PIN_SPI0MISO WMT_PIN(2, 25) | ||
93 | #define WMT_PIN_SPI0SS0 WMT_PIN(2, 26) | ||
94 | #define WMT_PIN_SPI0CLK WMT_PIN(2, 27) | ||
95 | #define WMT_PIN_SD0DATA0 WMT_PIN(3, 8) | ||
96 | #define WMT_PIN_SD0DATA1 WMT_PIN(3, 9) | ||
97 | #define WMT_PIN_SD0DATA2 WMT_PIN(3, 10) | ||
98 | #define WMT_PIN_SD0DATA3 WMT_PIN(3, 11) | ||
99 | #define WMT_PIN_SD0CLK WMT_PIN(3, 12) | ||
100 | #define WMT_PIN_SD0WP WMT_PIN(3, 13) | ||
101 | #define WMT_PIN_SD0CMD WMT_PIN(3, 14) | ||
102 | #define WMT_PIN_SD1DATA0 WMT_PIN(3, 24) | ||
103 | #define WMT_PIN_SD1DATA1 WMT_PIN(3, 25) | ||
104 | #define WMT_PIN_SD1DATA2 WMT_PIN(3, 26) | ||
105 | #define WMT_PIN_SD1DATA3 WMT_PIN(3, 27) | ||
106 | #define WMT_PIN_SD1DATA4 WMT_PIN(3, 28) | ||
107 | #define WMT_PIN_SD1DATA5 WMT_PIN(3, 29) | ||
108 | #define WMT_PIN_SD1DATA6 WMT_PIN(3, 30) | ||
109 | #define WMT_PIN_SD1DATA7 WMT_PIN(3, 31) | ||
110 | #define WMT_PIN_I2C0SCL WMT_PIN(5, 8) | ||
111 | #define WMT_PIN_I2C0SDA WMT_PIN(5, 9) | ||
112 | #define WMT_PIN_UART0RTS WMT_PIN(5, 16) | ||
113 | #define WMT_PIN_UART0TXD WMT_PIN(5, 17) | ||
114 | #define WMT_PIN_UART0CTS WMT_PIN(5, 18) | ||
115 | #define WMT_PIN_UART0RXD WMT_PIN(5, 19) | ||
116 | #define WMT_PIN_UART1RTS WMT_PIN(5, 20) | ||
117 | #define WMT_PIN_UART1TXD WMT_PIN(5, 21) | ||
118 | #define WMT_PIN_UART1CTS WMT_PIN(5, 22) | ||
119 | #define WMT_PIN_UART1RXD WMT_PIN(5, 23) | ||
120 | #define WMT_PIN_UART2RTS WMT_PIN(5, 24) | ||
121 | #define WMT_PIN_UART2TXD WMT_PIN(5, 25) | ||
122 | #define WMT_PIN_UART2CTS WMT_PIN(5, 26) | ||
123 | #define WMT_PIN_UART2RXD WMT_PIN(5, 27) | ||
124 | #define WMT_PIN_UART3RTS WMT_PIN(5, 28) | ||
125 | #define WMT_PIN_UART3TXD WMT_PIN(5, 29) | ||
126 | #define WMT_PIN_UART3CTS WMT_PIN(5, 30) | ||
127 | #define WMT_PIN_UART3RXD WMT_PIN(5, 31) | ||
128 | #define WMT_PIN_KPADROW0 WMT_PIN(6, 16) | ||
129 | #define WMT_PIN_KPADROW1 WMT_PIN(6, 17) | ||
130 | #define WMT_PIN_KPADCOL0 WMT_PIN(6, 18) | ||
131 | #define WMT_PIN_KPADCOL1 WMT_PIN(6, 19) | ||
132 | #define WMT_PIN_SD1CLK WMT_PIN(7, 0) | ||
133 | #define WMT_PIN_SD1CMD WMT_PIN(7, 1) | ||
134 | #define WMT_PIN_SD1WP WMT_PIN(7, 13) | ||
135 | |||
136 | static const struct pinctrl_pin_desc wm8650_pins[] = { | ||
137 | PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"), | ||
138 | PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"), | ||
139 | PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"), | ||
140 | PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"), | ||
141 | PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"), | ||
142 | PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"), | ||
143 | PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"), | ||
144 | PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"), | ||
145 | PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"), | ||
146 | PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"), | ||
147 | PINCTRL_PIN(WMT_PIN_SUSGPIO0, "susgpio0"), | ||
148 | PINCTRL_PIN(WMT_PIN_SD0CD, "sd0_cd"), | ||
149 | PINCTRL_PIN(WMT_PIN_SD1CD, "sd1_cd"), | ||
150 | PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"), | ||
151 | PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"), | ||
152 | PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"), | ||
153 | PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"), | ||
154 | PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"), | ||
155 | PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"), | ||
156 | PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"), | ||
157 | PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"), | ||
158 | PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"), | ||
159 | PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"), | ||
160 | PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"), | ||
161 | PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"), | ||
162 | PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"), | ||
163 | PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"), | ||
164 | PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"), | ||
165 | PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"), | ||
166 | PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"), | ||
167 | PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"), | ||
168 | PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"), | ||
169 | PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"), | ||
170 | PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"), | ||
171 | PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"), | ||
172 | PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"), | ||
173 | PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"), | ||
174 | PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"), | ||
175 | PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"), | ||
176 | PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"), | ||
177 | PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"), | ||
178 | PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"), | ||
179 | PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"), | ||
180 | PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"), | ||
181 | PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"), | ||
182 | PINCTRL_PIN(WMT_PIN_I2C1SCL, "i2c1_scl"), | ||
183 | PINCTRL_PIN(WMT_PIN_I2C1SDA, "i2c1_sda"), | ||
184 | PINCTRL_PIN(WMT_PIN_SPI0MOSI, "spi0_mosi"), | ||
185 | PINCTRL_PIN(WMT_PIN_SPI0MISO, "spi0_miso"), | ||
186 | PINCTRL_PIN(WMT_PIN_SPI0SS0, "spi0_ss0"), | ||
187 | PINCTRL_PIN(WMT_PIN_SPI0CLK, "spi0_clk"), | ||
188 | PINCTRL_PIN(WMT_PIN_SD0DATA0, "sd0_data0"), | ||
189 | PINCTRL_PIN(WMT_PIN_SD0DATA1, "sd0_data1"), | ||
190 | PINCTRL_PIN(WMT_PIN_SD0DATA2, "sd0_data2"), | ||
191 | PINCTRL_PIN(WMT_PIN_SD0DATA3, "sd0_data3"), | ||
192 | PINCTRL_PIN(WMT_PIN_SD0CLK, "sd0_clk"), | ||
193 | PINCTRL_PIN(WMT_PIN_SD0WP, "sd0_wp"), | ||
194 | PINCTRL_PIN(WMT_PIN_SD0CMD, "sd0_cmd"), | ||
195 | PINCTRL_PIN(WMT_PIN_SD1DATA0, "sd1_data0"), | ||
196 | PINCTRL_PIN(WMT_PIN_SD1DATA1, "sd1_data1"), | ||
197 | PINCTRL_PIN(WMT_PIN_SD1DATA2, "sd1_data2"), | ||
198 | PINCTRL_PIN(WMT_PIN_SD1DATA3, "sd1_data3"), | ||
199 | PINCTRL_PIN(WMT_PIN_SD1DATA4, "sd1_data4"), | ||
200 | PINCTRL_PIN(WMT_PIN_SD1DATA5, "sd1_data5"), | ||
201 | PINCTRL_PIN(WMT_PIN_SD1DATA6, "sd1_data6"), | ||
202 | PINCTRL_PIN(WMT_PIN_SD1DATA7, "sd1_data7"), | ||
203 | PINCTRL_PIN(WMT_PIN_I2C0SCL, "i2c0_scl"), | ||
204 | PINCTRL_PIN(WMT_PIN_I2C0SDA, "i2c0_sda"), | ||
205 | PINCTRL_PIN(WMT_PIN_UART0RTS, "uart0_rts"), | ||
206 | PINCTRL_PIN(WMT_PIN_UART0TXD, "uart0_txd"), | ||
207 | PINCTRL_PIN(WMT_PIN_UART0CTS, "uart0_cts"), | ||
208 | PINCTRL_PIN(WMT_PIN_UART0RXD, "uart0_rxd"), | ||
209 | PINCTRL_PIN(WMT_PIN_UART1RTS, "uart1_rts"), | ||
210 | PINCTRL_PIN(WMT_PIN_UART1TXD, "uart1_txd"), | ||
211 | PINCTRL_PIN(WMT_PIN_UART1CTS, "uart1_cts"), | ||
212 | PINCTRL_PIN(WMT_PIN_UART1RXD, "uart1_rxd"), | ||
213 | PINCTRL_PIN(WMT_PIN_UART2RTS, "uart2_rts"), | ||
214 | PINCTRL_PIN(WMT_PIN_UART2TXD, "uart2_txd"), | ||
215 | PINCTRL_PIN(WMT_PIN_UART2CTS, "uart2_cts"), | ||
216 | PINCTRL_PIN(WMT_PIN_UART2RXD, "uart2_rxd"), | ||
217 | PINCTRL_PIN(WMT_PIN_UART3RTS, "uart3_rts"), | ||
218 | PINCTRL_PIN(WMT_PIN_UART3TXD, "uart3_txd"), | ||
219 | PINCTRL_PIN(WMT_PIN_UART3CTS, "uart3_cts"), | ||
220 | PINCTRL_PIN(WMT_PIN_UART3RXD, "uart3_rxd"), | ||
221 | PINCTRL_PIN(WMT_PIN_KPADROW0, "kpadrow0"), | ||
222 | PINCTRL_PIN(WMT_PIN_KPADROW1, "kpadrow1"), | ||
223 | PINCTRL_PIN(WMT_PIN_KPADCOL0, "kpadcol0"), | ||
224 | PINCTRL_PIN(WMT_PIN_KPADCOL1, "kpadcol1"), | ||
225 | PINCTRL_PIN(WMT_PIN_SD1CLK, "sd1_clk"), | ||
226 | PINCTRL_PIN(WMT_PIN_SD1CMD, "sd1_cmd"), | ||
227 | PINCTRL_PIN(WMT_PIN_SD1WP, "sd1_wp"), | ||
228 | }; | ||
229 | |||
230 | /* Order of these names must match the above list */ | ||
231 | static const char * const wm8650_groups[] = { | ||
232 | "extgpio0", | ||
233 | "extgpio1", | ||
234 | "extgpio2", | ||
235 | "extgpio3", | ||
236 | "extgpio4", | ||
237 | "extgpio5", | ||
238 | "extgpio6", | ||
239 | "extgpio7", | ||
240 | "wakeup0", | ||
241 | "wakeup1", | ||
242 | "susgpio0", | ||
243 | "sd0_cd", | ||
244 | "sd1_cd", | ||
245 | "vdout0", | ||
246 | "vdout1", | ||
247 | "vdout2", | ||
248 | "vdout3", | ||
249 | "vdout4", | ||
250 | "vdout5", | ||
251 | "vdout6", | ||
252 | "vdout7", | ||
253 | "vdout8", | ||
254 | "vdout9", | ||
255 | "vdout10", | ||
256 | "vdout11", | ||
257 | "vdout12", | ||
258 | "vdout13", | ||
259 | "vdout14", | ||
260 | "vdout15", | ||
261 | "vdout16", | ||
262 | "vdout17", | ||
263 | "vdout18", | ||
264 | "vdout19", | ||
265 | "vdout20", | ||
266 | "vdout21", | ||
267 | "vdout22", | ||
268 | "vdout23", | ||
269 | "vdin0", | ||
270 | "vdin1", | ||
271 | "vdin2", | ||
272 | "vdin3", | ||
273 | "vdin4", | ||
274 | "vdin5", | ||
275 | "vdin6", | ||
276 | "vdin7", | ||
277 | "i2c1_scl", | ||
278 | "i2c1_sda", | ||
279 | "spi0_mosi", | ||
280 | "spi0_miso", | ||
281 | "spi0_ss0", | ||
282 | "spi0_clk", | ||
283 | "sd0_data0", | ||
284 | "sd0_data1", | ||
285 | "sd0_data2", | ||
286 | "sd0_data3", | ||
287 | "sd0_clk", | ||
288 | "sd0_wp", | ||
289 | "sd0_cmd", | ||
290 | "sd1_data0", | ||
291 | "sd1_data1", | ||
292 | "sd1_data2", | ||
293 | "sd1_data3", | ||
294 | "sd1_data4", | ||
295 | "sd1_data5", | ||
296 | "sd1_data6", | ||
297 | "sd1_data7", | ||
298 | "i2c0_scl", | ||
299 | "i2c0_sda", | ||
300 | "uart0_rts", | ||
301 | "uart0_txd", | ||
302 | "uart0_cts", | ||
303 | "uart0_rxd", | ||
304 | "uart1_rts", | ||
305 | "uart1_txd", | ||
306 | "uart1_cts", | ||
307 | "uart1_rxd", | ||
308 | "uart2_rts", | ||
309 | "uart2_txd", | ||
310 | "uart2_cts", | ||
311 | "uart2_rxd", | ||
312 | "uart3_rts", | ||
313 | "uart3_txd", | ||
314 | "uart3_cts", | ||
315 | "uart3_rxd", | ||
316 | "kpadrow0", | ||
317 | "kpadrow1", | ||
318 | "kpadcol0", | ||
319 | "kpadcol1", | ||
320 | "sd1_clk", | ||
321 | "sd1_cmd", | ||
322 | "sd1_wp", | ||
323 | }; | ||
324 | |||
325 | static int wm8650_pinctrl_probe(struct platform_device *pdev) | ||
326 | { | ||
327 | struct wmt_pinctrl_data *data; | ||
328 | |||
329 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
330 | if (!data) { | ||
331 | dev_err(&pdev->dev, "failed to allocate data\n"); | ||
332 | return -ENOMEM; | ||
333 | } | ||
334 | |||
335 | data->banks = wm8650_banks; | ||
336 | data->nbanks = ARRAY_SIZE(wm8650_banks); | ||
337 | data->pins = wm8650_pins; | ||
338 | data->npins = ARRAY_SIZE(wm8650_pins); | ||
339 | data->groups = wm8650_groups; | ||
340 | data->ngroups = ARRAY_SIZE(wm8650_groups); | ||
341 | |||
342 | return wmt_pinctrl_probe(pdev, data); | ||
343 | } | ||
344 | |||
345 | static int wm8650_pinctrl_remove(struct platform_device *pdev) | ||
346 | { | ||
347 | return wmt_pinctrl_remove(pdev); | ||
348 | } | ||
349 | |||
350 | static struct of_device_id wmt_pinctrl_of_match[] = { | ||
351 | { .compatible = "wm,wm8650-pinctrl" }, | ||
352 | { /* sentinel */ }, | ||
353 | }; | ||
354 | |||
355 | static struct platform_driver wmt_pinctrl_driver = { | ||
356 | .probe = wm8650_pinctrl_probe, | ||
357 | .remove = wm8650_pinctrl_remove, | ||
358 | .driver = { | ||
359 | .name = "pinctrl-wm8650", | ||
360 | .owner = THIS_MODULE, | ||
361 | .of_match_table = wmt_pinctrl_of_match, | ||
362 | }, | ||
363 | }; | ||
364 | |||
365 | module_platform_driver(wmt_pinctrl_driver); | ||
366 | |||
367 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
368 | MODULE_DESCRIPTION("Wondermedia WM8650 Pincontrol driver"); | ||
369 | MODULE_LICENSE("GPL v2"); | ||
370 | MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); | ||
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8750.c b/drivers/pinctrl/vt8500/pinctrl-wm8750.c new file mode 100644 index 000000000000..b964cc550568 --- /dev/null +++ b/drivers/pinctrl/vt8500/pinctrl-wm8750.c | |||
@@ -0,0 +1,409 @@ | |||
1 | /* | ||
2 | * Pinctrl data for Wondermedia WM8750 SoC | ||
3 | * | ||
4 | * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/pinctrl/pinctrl.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include "pinctrl-wmt.h" | ||
23 | |||
24 | /* | ||
25 | * Describe the register offsets within the GPIO memory space | ||
26 | * The dedicated external GPIO's should always be listed in bank 0 | ||
27 | * so they are exported in the 0..31 range which is what users | ||
28 | * expect. | ||
29 | * | ||
30 | * Do not reorder these banks as it will change the pin numbering | ||
31 | */ | ||
32 | static const struct wmt_pinctrl_bank_registers wm8750_banks[] = { | ||
33 | WMT_PINCTRL_BANK(0x40, 0x80, 0xC0, 0x00, 0x480, 0x4C0), /* 0 */ | ||
34 | WMT_PINCTRL_BANK(0x44, 0x84, 0xC4, 0x04, 0x484, 0x4C4), /* 1 */ | ||
35 | WMT_PINCTRL_BANK(0x48, 0x88, 0xC8, 0x08, 0x488, 0x4C8), /* 2 */ | ||
36 | WMT_PINCTRL_BANK(0x4C, 0x8C, 0xCC, 0x0C, 0x48C, 0x4CC), /* 3 */ | ||
37 | WMT_PINCTRL_BANK(0x50, 0x90, 0xD0, 0x10, 0x490, 0x4D0), /* 4 */ | ||
38 | WMT_PINCTRL_BANK(0x54, 0x94, 0xD4, 0x14, 0x494, 0x4D4), /* 5 */ | ||
39 | WMT_PINCTRL_BANK(0x58, 0x98, 0xD8, 0x18, 0x498, 0x4D8), /* 6 */ | ||
40 | WMT_PINCTRL_BANK(0x5C, 0x9C, 0xDC, 0x1C, 0x49C, 0x4DC), /* 7 */ | ||
41 | WMT_PINCTRL_BANK(0x60, 0xA0, 0xE0, 0x20, 0x4A0, 0x4E0), /* 8 */ | ||
42 | WMT_PINCTRL_BANK(0x70, 0xB0, 0xF0, 0x30, 0x4B0, 0x4F0), /* 9 */ | ||
43 | WMT_PINCTRL_BANK(0x7C, 0xBC, 0xDC, 0x3C, 0x4BC, 0x4FC), /* 10 */ | ||
44 | }; | ||
45 | |||
46 | /* Please keep sorted by bank/bit */ | ||
47 | #define WMT_PIN_EXTGPIO0 WMT_PIN(0, 0) | ||
48 | #define WMT_PIN_EXTGPIO1 WMT_PIN(0, 1) | ||
49 | #define WMT_PIN_EXTGPIO2 WMT_PIN(0, 2) | ||
50 | #define WMT_PIN_EXTGPIO3 WMT_PIN(0, 3) | ||
51 | #define WMT_PIN_EXTGPIO4 WMT_PIN(0, 4) | ||
52 | #define WMT_PIN_EXTGPIO5 WMT_PIN(0, 5) | ||
53 | #define WMT_PIN_EXTGPIO6 WMT_PIN(0, 6) | ||
54 | #define WMT_PIN_EXTGPIO7 WMT_PIN(0, 7) | ||
55 | #define WMT_PIN_WAKEUP0 WMT_PIN(0, 16) | ||
56 | #define WMT_PIN_WAKEUP1 WMT_PIN(0, 16) | ||
57 | #define WMT_PIN_SD0CD WMT_PIN(0, 28) | ||
58 | #define WMT_PIN_VDOUT0 WMT_PIN(1, 0) | ||
59 | #define WMT_PIN_VDOUT1 WMT_PIN(1, 1) | ||
60 | #define WMT_PIN_VDOUT2 WMT_PIN(1, 2) | ||
61 | #define WMT_PIN_VDOUT3 WMT_PIN(1, 3) | ||
62 | #define WMT_PIN_VDOUT4 WMT_PIN(1, 4) | ||
63 | #define WMT_PIN_VDOUT5 WMT_PIN(1, 5) | ||
64 | #define WMT_PIN_VDOUT6 WMT_PIN(1, 6) | ||
65 | #define WMT_PIN_VDOUT7 WMT_PIN(1, 7) | ||
66 | #define WMT_PIN_VDOUT8 WMT_PIN(1, 8) | ||
67 | #define WMT_PIN_VDOUT9 WMT_PIN(1, 9) | ||
68 | #define WMT_PIN_VDOUT10 WMT_PIN(1, 10) | ||
69 | #define WMT_PIN_VDOUT11 WMT_PIN(1, 11) | ||
70 | #define WMT_PIN_VDOUT12 WMT_PIN(1, 12) | ||
71 | #define WMT_PIN_VDOUT13 WMT_PIN(1, 13) | ||
72 | #define WMT_PIN_VDOUT14 WMT_PIN(1, 14) | ||
73 | #define WMT_PIN_VDOUT15 WMT_PIN(1, 15) | ||
74 | #define WMT_PIN_VDOUT16 WMT_PIN(1, 16) | ||
75 | #define WMT_PIN_VDOUT17 WMT_PIN(1, 17) | ||
76 | #define WMT_PIN_VDOUT18 WMT_PIN(1, 18) | ||
77 | #define WMT_PIN_VDOUT19 WMT_PIN(1, 19) | ||
78 | #define WMT_PIN_VDOUT20 WMT_PIN(1, 20) | ||
79 | #define WMT_PIN_VDOUT21 WMT_PIN(1, 21) | ||
80 | #define WMT_PIN_VDOUT22 WMT_PIN(1, 22) | ||
81 | #define WMT_PIN_VDOUT23 WMT_PIN(1, 23) | ||
82 | #define WMT_PIN_VDIN0 WMT_PIN(2, 0) | ||
83 | #define WMT_PIN_VDIN1 WMT_PIN(2, 1) | ||
84 | #define WMT_PIN_VDIN2 WMT_PIN(2, 2) | ||
85 | #define WMT_PIN_VDIN3 WMT_PIN(2, 3) | ||
86 | #define WMT_PIN_VDIN4 WMT_PIN(2, 4) | ||
87 | #define WMT_PIN_VDIN5 WMT_PIN(2, 5) | ||
88 | #define WMT_PIN_VDIN6 WMT_PIN(2, 6) | ||
89 | #define WMT_PIN_VDIN7 WMT_PIN(2, 7) | ||
90 | #define WMT_PIN_SPI0_MOSI WMT_PIN(2, 24) | ||
91 | #define WMT_PIN_SPI0_MISO WMT_PIN(2, 25) | ||
92 | #define WMT_PIN_SPI0_SS WMT_PIN(2, 26) | ||
93 | #define WMT_PIN_SPI0_CLK WMT_PIN(2, 27) | ||
94 | #define WMT_PIN_SPI0_SSB WMT_PIN(2, 28) | ||
95 | #define WMT_PIN_SD0CLK WMT_PIN(3, 17) | ||
96 | #define WMT_PIN_SD0CMD WMT_PIN(3, 18) | ||
97 | #define WMT_PIN_SD0WP WMT_PIN(3, 19) | ||
98 | #define WMT_PIN_SD0DATA0 WMT_PIN(3, 20) | ||
99 | #define WMT_PIN_SD0DATA1 WMT_PIN(3, 21) | ||
100 | #define WMT_PIN_SD0DATA2 WMT_PIN(3, 22) | ||
101 | #define WMT_PIN_SD0DATA3 WMT_PIN(3, 23) | ||
102 | #define WMT_PIN_SD1DATA0 WMT_PIN(3, 24) | ||
103 | #define WMT_PIN_SD1DATA1 WMT_PIN(3, 25) | ||
104 | #define WMT_PIN_SD1DATA2 WMT_PIN(3, 26) | ||
105 | #define WMT_PIN_SD1DATA3 WMT_PIN(3, 27) | ||
106 | #define WMT_PIN_SD1DATA4 WMT_PIN(3, 28) | ||
107 | #define WMT_PIN_SD1DATA5 WMT_PIN(3, 29) | ||
108 | #define WMT_PIN_SD1DATA6 WMT_PIN(3, 30) | ||
109 | #define WMT_PIN_SD1DATA7 WMT_PIN(3, 31) | ||
110 | #define WMT_PIN_I2C0_SCL WMT_PIN(5, 8) | ||
111 | #define WMT_PIN_I2C0_SDA WMT_PIN(5, 9) | ||
112 | #define WMT_PIN_I2C1_SCL WMT_PIN(5, 10) | ||
113 | #define WMT_PIN_I2C1_SDA WMT_PIN(5, 11) | ||
114 | #define WMT_PIN_I2C2_SCL WMT_PIN(5, 12) | ||
115 | #define WMT_PIN_I2C2_SDA WMT_PIN(5, 13) | ||
116 | #define WMT_PIN_UART0_RTS WMT_PIN(5, 16) | ||
117 | #define WMT_PIN_UART0_TXD WMT_PIN(5, 17) | ||
118 | #define WMT_PIN_UART0_CTS WMT_PIN(5, 18) | ||
119 | #define WMT_PIN_UART0_RXD WMT_PIN(5, 19) | ||
120 | #define WMT_PIN_UART1_RTS WMT_PIN(5, 20) | ||
121 | #define WMT_PIN_UART1_TXD WMT_PIN(5, 21) | ||
122 | #define WMT_PIN_UART1_CTS WMT_PIN(5, 22) | ||
123 | #define WMT_PIN_UART1_RXD WMT_PIN(5, 23) | ||
124 | #define WMT_PIN_UART2_RTS WMT_PIN(5, 24) | ||
125 | #define WMT_PIN_UART2_TXD WMT_PIN(5, 25) | ||
126 | #define WMT_PIN_UART2_CTS WMT_PIN(5, 26) | ||
127 | #define WMT_PIN_UART2_RXD WMT_PIN(5, 27) | ||
128 | #define WMT_PIN_UART3_RTS WMT_PIN(5, 28) | ||
129 | #define WMT_PIN_UART3_TXD WMT_PIN(5, 29) | ||
130 | #define WMT_PIN_UART3_CTS WMT_PIN(5, 30) | ||
131 | #define WMT_PIN_UART3_RXD WMT_PIN(5, 31) | ||
132 | #define WMT_PIN_SD2CD WMT_PIN(6, 0) | ||
133 | #define WMT_PIN_SD2DATA3 WMT_PIN(6, 1) | ||
134 | #define WMT_PIN_SD2DATA0 WMT_PIN(6, 2) | ||
135 | #define WMT_PIN_SD2WP WMT_PIN(6, 3) | ||
136 | #define WMT_PIN_SD2DATA1 WMT_PIN(6, 4) | ||
137 | #define WMT_PIN_SD2DATA2 WMT_PIN(6, 5) | ||
138 | #define WMT_PIN_SD2CMD WMT_PIN(6, 6) | ||
139 | #define WMT_PIN_SD2CLK WMT_PIN(6, 7) | ||
140 | #define WMT_PIN_SD2PWR WMT_PIN(6, 9) | ||
141 | #define WMT_PIN_SD1CLK WMT_PIN(7, 0) | ||
142 | #define WMT_PIN_SD1CMD WMT_PIN(7, 1) | ||
143 | #define WMT_PIN_SD1PWR WMT_PIN(7, 10) | ||
144 | #define WMT_PIN_SD1WP WMT_PIN(7, 11) | ||
145 | #define WMT_PIN_SD1CD WMT_PIN(7, 12) | ||
146 | #define WMT_PIN_SPI0SS3 WMT_PIN(7, 24) | ||
147 | #define WMT_PIN_SPI0SS2 WMT_PIN(7, 25) | ||
148 | #define WMT_PIN_PWMOUT1 WMT_PIN(7, 26) | ||
149 | #define WMT_PIN_PWMOUT0 WMT_PIN(7, 27) | ||
150 | |||
151 | static const struct pinctrl_pin_desc wm8750_pins[] = { | ||
152 | PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"), | ||
153 | PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"), | ||
154 | PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"), | ||
155 | PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"), | ||
156 | PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"), | ||
157 | PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"), | ||
158 | PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"), | ||
159 | PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"), | ||
160 | PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"), | ||
161 | PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"), | ||
162 | PINCTRL_PIN(WMT_PIN_SD0CD, "sd0_cd"), | ||
163 | PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"), | ||
164 | PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"), | ||
165 | PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"), | ||
166 | PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"), | ||
167 | PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"), | ||
168 | PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"), | ||
169 | PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"), | ||
170 | PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"), | ||
171 | PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"), | ||
172 | PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"), | ||
173 | PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"), | ||
174 | PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"), | ||
175 | PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"), | ||
176 | PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"), | ||
177 | PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"), | ||
178 | PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"), | ||
179 | PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"), | ||
180 | PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"), | ||
181 | PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"), | ||
182 | PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"), | ||
183 | PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"), | ||
184 | PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"), | ||
185 | PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"), | ||
186 | PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"), | ||
187 | PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"), | ||
188 | PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"), | ||
189 | PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"), | ||
190 | PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"), | ||
191 | PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"), | ||
192 | PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"), | ||
193 | PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"), | ||
194 | PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"), | ||
195 | PINCTRL_PIN(WMT_PIN_SPI0_MOSI, "spi0_mosi"), | ||
196 | PINCTRL_PIN(WMT_PIN_SPI0_MISO, "spi0_miso"), | ||
197 | PINCTRL_PIN(WMT_PIN_SPI0_SS, "spi0_ss"), | ||
198 | PINCTRL_PIN(WMT_PIN_SPI0_CLK, "spi0_clk"), | ||
199 | PINCTRL_PIN(WMT_PIN_SPI0_SSB, "spi0_ssb"), | ||
200 | PINCTRL_PIN(WMT_PIN_SD0CLK, "sd0_clk"), | ||
201 | PINCTRL_PIN(WMT_PIN_SD0CMD, "sd0_cmd"), | ||
202 | PINCTRL_PIN(WMT_PIN_SD0WP, "sd0_wp"), | ||
203 | PINCTRL_PIN(WMT_PIN_SD0DATA0, "sd0_data0"), | ||
204 | PINCTRL_PIN(WMT_PIN_SD0DATA1, "sd0_data1"), | ||
205 | PINCTRL_PIN(WMT_PIN_SD0DATA2, "sd0_data2"), | ||
206 | PINCTRL_PIN(WMT_PIN_SD0DATA3, "sd0_data3"), | ||
207 | PINCTRL_PIN(WMT_PIN_SD1DATA0, "sd1_data0"), | ||
208 | PINCTRL_PIN(WMT_PIN_SD1DATA1, "sd1_data1"), | ||
209 | PINCTRL_PIN(WMT_PIN_SD1DATA2, "sd1_data2"), | ||
210 | PINCTRL_PIN(WMT_PIN_SD1DATA3, "sd1_data3"), | ||
211 | PINCTRL_PIN(WMT_PIN_SD1DATA4, "sd1_data4"), | ||
212 | PINCTRL_PIN(WMT_PIN_SD1DATA5, "sd1_data5"), | ||
213 | PINCTRL_PIN(WMT_PIN_SD1DATA6, "sd1_data6"), | ||
214 | PINCTRL_PIN(WMT_PIN_SD1DATA7, "sd1_data7"), | ||
215 | PINCTRL_PIN(WMT_PIN_I2C0_SCL, "i2c0_scl"), | ||
216 | PINCTRL_PIN(WMT_PIN_I2C0_SDA, "i2c0_sda"), | ||
217 | PINCTRL_PIN(WMT_PIN_I2C1_SCL, "i2c1_scl"), | ||
218 | PINCTRL_PIN(WMT_PIN_I2C1_SDA, "i2c1_sda"), | ||
219 | PINCTRL_PIN(WMT_PIN_I2C2_SCL, "i2c2_scl"), | ||
220 | PINCTRL_PIN(WMT_PIN_I2C2_SDA, "i2c2_sda"), | ||
221 | PINCTRL_PIN(WMT_PIN_UART0_RTS, "uart0_rts"), | ||
222 | PINCTRL_PIN(WMT_PIN_UART0_TXD, "uart0_txd"), | ||
223 | PINCTRL_PIN(WMT_PIN_UART0_CTS, "uart0_cts"), | ||
224 | PINCTRL_PIN(WMT_PIN_UART0_RXD, "uart0_rxd"), | ||
225 | PINCTRL_PIN(WMT_PIN_UART1_RTS, "uart1_rts"), | ||
226 | PINCTRL_PIN(WMT_PIN_UART1_TXD, "uart1_txd"), | ||
227 | PINCTRL_PIN(WMT_PIN_UART1_CTS, "uart1_cts"), | ||
228 | PINCTRL_PIN(WMT_PIN_UART1_RXD, "uart1_rxd"), | ||
229 | PINCTRL_PIN(WMT_PIN_UART2_RTS, "uart2_rts"), | ||
230 | PINCTRL_PIN(WMT_PIN_UART2_TXD, "uart2_txd"), | ||
231 | PINCTRL_PIN(WMT_PIN_UART2_CTS, "uart2_cts"), | ||
232 | PINCTRL_PIN(WMT_PIN_UART2_RXD, "uart2_rxd"), | ||
233 | PINCTRL_PIN(WMT_PIN_UART3_RTS, "uart3_rts"), | ||
234 | PINCTRL_PIN(WMT_PIN_UART3_TXD, "uart3_txd"), | ||
235 | PINCTRL_PIN(WMT_PIN_UART3_CTS, "uart3_cts"), | ||
236 | PINCTRL_PIN(WMT_PIN_UART3_RXD, "uart3_rxd"), | ||
237 | PINCTRL_PIN(WMT_PIN_SD2CD, "sd2_cd"), | ||
238 | PINCTRL_PIN(WMT_PIN_SD2DATA3, "sd2_data3"), | ||
239 | PINCTRL_PIN(WMT_PIN_SD2DATA0, "sd2_data0"), | ||
240 | PINCTRL_PIN(WMT_PIN_SD2WP, "sd2_wp"), | ||
241 | PINCTRL_PIN(WMT_PIN_SD2DATA1, "sd2_data1"), | ||
242 | PINCTRL_PIN(WMT_PIN_SD2DATA2, "sd2_data2"), | ||
243 | PINCTRL_PIN(WMT_PIN_SD2CMD, "sd2_cmd"), | ||
244 | PINCTRL_PIN(WMT_PIN_SD2CLK, "sd2_clk"), | ||
245 | PINCTRL_PIN(WMT_PIN_SD2PWR, "sd2_pwr"), | ||
246 | PINCTRL_PIN(WMT_PIN_SD1CLK, "sd1_clk"), | ||
247 | PINCTRL_PIN(WMT_PIN_SD1CMD, "sd1_cmd"), | ||
248 | PINCTRL_PIN(WMT_PIN_SD1PWR, "sd1_pwr"), | ||
249 | PINCTRL_PIN(WMT_PIN_SD1WP, "sd1_wp"), | ||
250 | PINCTRL_PIN(WMT_PIN_SD1CD, "sd1_cd"), | ||
251 | PINCTRL_PIN(WMT_PIN_SPI0SS3, "spi0_ss3"), | ||
252 | PINCTRL_PIN(WMT_PIN_SPI0SS2, "spi0_ss2"), | ||
253 | PINCTRL_PIN(WMT_PIN_PWMOUT1, "pwmout1"), | ||
254 | PINCTRL_PIN(WMT_PIN_PWMOUT0, "pwmout0"), | ||
255 | }; | ||
256 | |||
257 | /* Order of these names must match the above list */ | ||
258 | static const char * const wm8750_groups[] = { | ||
259 | "extgpio0", | ||
260 | "extgpio1", | ||
261 | "extgpio2", | ||
262 | "extgpio3", | ||
263 | "extgpio4", | ||
264 | "extgpio5", | ||
265 | "extgpio6", | ||
266 | "extgpio7", | ||
267 | "wakeup0", | ||
268 | "wakeup1", | ||
269 | "sd0_cd", | ||
270 | "vdout0", | ||
271 | "vdout1", | ||
272 | "vdout2", | ||
273 | "vdout3", | ||
274 | "vdout4", | ||
275 | "vdout5", | ||
276 | "vdout6", | ||
277 | "vdout7", | ||
278 | "vdout8", | ||
279 | "vdout9", | ||
280 | "vdout10", | ||
281 | "vdout11", | ||
282 | "vdout12", | ||
283 | "vdout13", | ||
284 | "vdout14", | ||
285 | "vdout15", | ||
286 | "vdout16", | ||
287 | "vdout17", | ||
288 | "vdout18", | ||
289 | "vdout19", | ||
290 | "vdout20", | ||
291 | "vdout21", | ||
292 | "vdout22", | ||
293 | "vdout23", | ||
294 | "vdin0", | ||
295 | "vdin1", | ||
296 | "vdin2", | ||
297 | "vdin3", | ||
298 | "vdin4", | ||
299 | "vdin5", | ||
300 | "vdin6", | ||
301 | "vdin7", | ||
302 | "spi0_mosi", | ||
303 | "spi0_miso", | ||
304 | "spi0_ss", | ||
305 | "spi0_clk", | ||
306 | "spi0_ssb", | ||
307 | "sd0_clk", | ||
308 | "sd0_cmd", | ||
309 | "sd0_wp", | ||
310 | "sd0_data0", | ||
311 | "sd0_data1", | ||
312 | "sd0_data2", | ||
313 | "sd0_data3", | ||
314 | "sd1_data0", | ||
315 | "sd1_data1", | ||
316 | "sd1_data2", | ||
317 | "sd1_data3", | ||
318 | "sd1_data4", | ||
319 | "sd1_data5", | ||
320 | "sd1_data6", | ||
321 | "sd1_data7", | ||
322 | "i2c0_scl", | ||
323 | "i2c0_sda", | ||
324 | "i2c1_scl", | ||
325 | "i2c1_sda", | ||
326 | "i2c2_scl", | ||
327 | "i2c2_sda", | ||
328 | "uart0_rts", | ||
329 | "uart0_txd", | ||
330 | "uart0_cts", | ||
331 | "uart0_rxd", | ||
332 | "uart1_rts", | ||
333 | "uart1_txd", | ||
334 | "uart1_cts", | ||
335 | "uart1_rxd", | ||
336 | "uart2_rts", | ||
337 | "uart2_txd", | ||
338 | "uart2_cts", | ||
339 | "uart2_rxd", | ||
340 | "uart3_rts", | ||
341 | "uart3_txd", | ||
342 | "uart3_cts", | ||
343 | "uart3_rxd", | ||
344 | "sd2_cd", | ||
345 | "sd2_data3", | ||
346 | "sd2_data0", | ||
347 | "sd2_wp", | ||
348 | "sd2_data1", | ||
349 | "sd2_data2", | ||
350 | "sd2_cmd", | ||
351 | "sd2_clk", | ||
352 | "sd2_pwr", | ||
353 | "sd1_clk", | ||
354 | "sd1_cmd", | ||
355 | "sd1_pwr", | ||
356 | "sd1_wp", | ||
357 | "sd1_cd", | ||
358 | "spi0_ss3", | ||
359 | "spi0_ss2", | ||
360 | "pwmout1", | ||
361 | "pwmout0", | ||
362 | }; | ||
363 | |||
364 | static int wm8750_pinctrl_probe(struct platform_device *pdev) | ||
365 | { | ||
366 | struct wmt_pinctrl_data *data; | ||
367 | |||
368 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
369 | if (!data) { | ||
370 | dev_err(&pdev->dev, "failed to allocate data\n"); | ||
371 | return -ENOMEM; | ||
372 | } | ||
373 | |||
374 | data->banks = wm8750_banks; | ||
375 | data->nbanks = ARRAY_SIZE(wm8750_banks); | ||
376 | data->pins = wm8750_pins; | ||
377 | data->npins = ARRAY_SIZE(wm8750_pins); | ||
378 | data->groups = wm8750_groups; | ||
379 | data->ngroups = ARRAY_SIZE(wm8750_groups); | ||
380 | |||
381 | return wmt_pinctrl_probe(pdev, data); | ||
382 | } | ||
383 | |||
384 | static int wm8750_pinctrl_remove(struct platform_device *pdev) | ||
385 | { | ||
386 | return wmt_pinctrl_remove(pdev); | ||
387 | } | ||
388 | |||
389 | static struct of_device_id wmt_pinctrl_of_match[] = { | ||
390 | { .compatible = "wm,wm8750-pinctrl" }, | ||
391 | { /* sentinel */ }, | ||
392 | }; | ||
393 | |||
394 | static struct platform_driver wmt_pinctrl_driver = { | ||
395 | .probe = wm8750_pinctrl_probe, | ||
396 | .remove = wm8750_pinctrl_remove, | ||
397 | .driver = { | ||
398 | .name = "pinctrl-wm8750", | ||
399 | .owner = THIS_MODULE, | ||
400 | .of_match_table = wmt_pinctrl_of_match, | ||
401 | }, | ||
402 | }; | ||
403 | |||
404 | module_platform_driver(wmt_pinctrl_driver); | ||
405 | |||
406 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
407 | MODULE_DESCRIPTION("Wondermedia WM8750 Pincontrol driver"); | ||
408 | MODULE_LICENSE("GPL v2"); | ||
409 | MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); | ||
diff --git a/drivers/pinctrl/vt8500/pinctrl-wm8850.c b/drivers/pinctrl/vt8500/pinctrl-wm8850.c new file mode 100644 index 000000000000..ecadce9c91d5 --- /dev/null +++ b/drivers/pinctrl/vt8500/pinctrl-wm8850.c | |||
@@ -0,0 +1,388 @@ | |||
1 | /* | ||
2 | * Pinctrl data for Wondermedia WM8850 SoC | ||
3 | * | ||
4 | * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/io.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/pinctrl/pinctrl.h> | ||
19 | #include <linux/platform_device.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include "pinctrl-wmt.h" | ||
23 | |||
24 | /* | ||
25 | * Describe the register offsets within the GPIO memory space | ||
26 | * The dedicated external GPIO's should always be listed in bank 0 | ||
27 | * so they are exported in the 0..31 range which is what users | ||
28 | * expect. | ||
29 | * | ||
30 | * Do not reorder these banks as it will change the pin numbering | ||
31 | */ | ||
32 | static const struct wmt_pinctrl_bank_registers wm8850_banks[] = { | ||
33 | WMT_PINCTRL_BANK(0x40, 0x80, 0xC0, 0x00, 0x480, 0x4C0), /* 0 */ | ||
34 | WMT_PINCTRL_BANK(0x44, 0x84, 0xC4, 0x04, 0x484, 0x4C4), /* 1 */ | ||
35 | WMT_PINCTRL_BANK(0x48, 0x88, 0xC8, 0x08, 0x488, 0x4C8), /* 2 */ | ||
36 | WMT_PINCTRL_BANK(0x4C, 0x8C, 0xCC, 0x0C, 0x48C, 0x4CC), /* 3 */ | ||
37 | WMT_PINCTRL_BANK(0x50, 0x90, 0xD0, 0x10, 0x490, 0x4D0), /* 4 */ | ||
38 | WMT_PINCTRL_BANK(0x54, 0x94, 0xD4, 0x14, 0x494, 0x4D4), /* 5 */ | ||
39 | WMT_PINCTRL_BANK(0x58, 0x98, 0xD8, 0x18, 0x498, 0x4D8), /* 6 */ | ||
40 | WMT_PINCTRL_BANK(0x5C, 0x9C, 0xDC, 0x1C, 0x49C, 0x4DC), /* 7 */ | ||
41 | WMT_PINCTRL_BANK(0x60, 0xA0, 0xE0, 0x20, 0x4A0, 0x4E0), /* 8 */ | ||
42 | WMT_PINCTRL_BANK(0x70, 0xB0, 0xF0, 0x30, 0x4B0, 0x4F0), /* 9 */ | ||
43 | WMT_PINCTRL_BANK(0x7C, 0xBC, 0xDC, 0x3C, 0x4BC, 0x4FC), /* 10 */ | ||
44 | }; | ||
45 | |||
46 | /* Please keep sorted by bank/bit */ | ||
47 | #define WMT_PIN_EXTGPIO0 WMT_PIN(0, 0) | ||
48 | #define WMT_PIN_EXTGPIO1 WMT_PIN(0, 1) | ||
49 | #define WMT_PIN_EXTGPIO2 WMT_PIN(0, 2) | ||
50 | #define WMT_PIN_EXTGPIO3 WMT_PIN(0, 3) | ||
51 | #define WMT_PIN_EXTGPIO4 WMT_PIN(0, 4) | ||
52 | #define WMT_PIN_EXTGPIO5 WMT_PIN(0, 5) | ||
53 | #define WMT_PIN_EXTGPIO6 WMT_PIN(0, 6) | ||
54 | #define WMT_PIN_EXTGPIO7 WMT_PIN(0, 7) | ||
55 | #define WMT_PIN_WAKEUP0 WMT_PIN(0, 16) | ||
56 | #define WMT_PIN_WAKEUP1 WMT_PIN(0, 17) | ||
57 | #define WMT_PIN_WAKEUP2 WMT_PIN(0, 18) | ||
58 | #define WMT_PIN_WAKEUP3 WMT_PIN(0, 19) | ||
59 | #define WMT_PIN_SUSGPIO0 WMT_PIN(0, 21) | ||
60 | #define WMT_PIN_SUSGPIO1 WMT_PIN(0, 22) | ||
61 | #define WMT_PIN_SD0CD WMT_PIN(0, 28) | ||
62 | #define WMT_PIN_VDOUT0 WMT_PIN(1, 0) | ||
63 | #define WMT_PIN_VDOUT1 WMT_PIN(1, 1) | ||
64 | #define WMT_PIN_VDOUT2 WMT_PIN(1, 2) | ||
65 | #define WMT_PIN_VDOUT3 WMT_PIN(1, 3) | ||
66 | #define WMT_PIN_VDOUT4 WMT_PIN(1, 4) | ||
67 | #define WMT_PIN_VDOUT5 WMT_PIN(1, 5) | ||
68 | #define WMT_PIN_VDOUT6 WMT_PIN(1, 6) | ||
69 | #define WMT_PIN_VDOUT7 WMT_PIN(1, 7) | ||
70 | #define WMT_PIN_VDOUT8 WMT_PIN(1, 8) | ||
71 | #define WMT_PIN_VDOUT9 WMT_PIN(1, 9) | ||
72 | #define WMT_PIN_VDOUT10 WMT_PIN(1, 10) | ||
73 | #define WMT_PIN_VDOUT11 WMT_PIN(1, 11) | ||
74 | #define WMT_PIN_VDOUT12 WMT_PIN(1, 12) | ||
75 | #define WMT_PIN_VDOUT13 WMT_PIN(1, 13) | ||
76 | #define WMT_PIN_VDOUT14 WMT_PIN(1, 14) | ||
77 | #define WMT_PIN_VDOUT15 WMT_PIN(1, 15) | ||
78 | #define WMT_PIN_VDOUT16 WMT_PIN(1, 16) | ||
79 | #define WMT_PIN_VDOUT17 WMT_PIN(1, 17) | ||
80 | #define WMT_PIN_VDOUT18 WMT_PIN(1, 18) | ||
81 | #define WMT_PIN_VDOUT19 WMT_PIN(1, 19) | ||
82 | #define WMT_PIN_VDOUT20 WMT_PIN(1, 20) | ||
83 | #define WMT_PIN_VDOUT21 WMT_PIN(1, 21) | ||
84 | #define WMT_PIN_VDOUT22 WMT_PIN(1, 22) | ||
85 | #define WMT_PIN_VDOUT23 WMT_PIN(1, 23) | ||
86 | #define WMT_PIN_VDIN0 WMT_PIN(2, 0) | ||
87 | #define WMT_PIN_VDIN1 WMT_PIN(2, 1) | ||
88 | #define WMT_PIN_VDIN2 WMT_PIN(2, 2) | ||
89 | #define WMT_PIN_VDIN3 WMT_PIN(2, 3) | ||
90 | #define WMT_PIN_VDIN4 WMT_PIN(2, 4) | ||
91 | #define WMT_PIN_VDIN5 WMT_PIN(2, 5) | ||
92 | #define WMT_PIN_VDIN6 WMT_PIN(2, 6) | ||
93 | #define WMT_PIN_VDIN7 WMT_PIN(2, 7) | ||
94 | #define WMT_PIN_SPI0_MOSI WMT_PIN(2, 24) | ||
95 | #define WMT_PIN_SPI0_MISO WMT_PIN(2, 25) | ||
96 | #define WMT_PIN_SPI0_SS WMT_PIN(2, 26) | ||
97 | #define WMT_PIN_SPI0_CLK WMT_PIN(2, 27) | ||
98 | #define WMT_PIN_SPI0_SSB WMT_PIN(2, 28) | ||
99 | #define WMT_PIN_SD0CLK WMT_PIN(3, 17) | ||
100 | #define WMT_PIN_SD0CMD WMT_PIN(3, 18) | ||
101 | #define WMT_PIN_SD0WP WMT_PIN(3, 19) | ||
102 | #define WMT_PIN_SD0DATA0 WMT_PIN(3, 20) | ||
103 | #define WMT_PIN_SD0DATA1 WMT_PIN(3, 21) | ||
104 | #define WMT_PIN_SD0DATA2 WMT_PIN(3, 22) | ||
105 | #define WMT_PIN_SD0DATA3 WMT_PIN(3, 23) | ||
106 | #define WMT_PIN_SD1DATA0 WMT_PIN(3, 24) | ||
107 | #define WMT_PIN_SD1DATA1 WMT_PIN(3, 25) | ||
108 | #define WMT_PIN_SD1DATA2 WMT_PIN(3, 26) | ||
109 | #define WMT_PIN_SD1DATA3 WMT_PIN(3, 27) | ||
110 | #define WMT_PIN_SD1DATA4 WMT_PIN(3, 28) | ||
111 | #define WMT_PIN_SD1DATA5 WMT_PIN(3, 29) | ||
112 | #define WMT_PIN_SD1DATA6 WMT_PIN(3, 30) | ||
113 | #define WMT_PIN_SD1DATA7 WMT_PIN(3, 31) | ||
114 | #define WMT_PIN_I2C0_SCL WMT_PIN(5, 8) | ||
115 | #define WMT_PIN_I2C0_SDA WMT_PIN(5, 9) | ||
116 | #define WMT_PIN_I2C1_SCL WMT_PIN(5, 10) | ||
117 | #define WMT_PIN_I2C1_SDA WMT_PIN(5, 11) | ||
118 | #define WMT_PIN_I2C2_SCL WMT_PIN(5, 12) | ||
119 | #define WMT_PIN_I2C2_SDA WMT_PIN(5, 13) | ||
120 | #define WMT_PIN_UART0_RTS WMT_PIN(5, 16) | ||
121 | #define WMT_PIN_UART0_TXD WMT_PIN(5, 17) | ||
122 | #define WMT_PIN_UART0_CTS WMT_PIN(5, 18) | ||
123 | #define WMT_PIN_UART0_RXD WMT_PIN(5, 19) | ||
124 | #define WMT_PIN_UART1_RTS WMT_PIN(5, 20) | ||
125 | #define WMT_PIN_UART1_TXD WMT_PIN(5, 21) | ||
126 | #define WMT_PIN_UART1_CTS WMT_PIN(5, 22) | ||
127 | #define WMT_PIN_UART1_RXD WMT_PIN(5, 23) | ||
128 | #define WMT_PIN_UART2_RTS WMT_PIN(5, 24) | ||
129 | #define WMT_PIN_UART2_TXD WMT_PIN(5, 25) | ||
130 | #define WMT_PIN_UART2_CTS WMT_PIN(5, 26) | ||
131 | #define WMT_PIN_UART2_RXD WMT_PIN(5, 27) | ||
132 | #define WMT_PIN_SD2WP WMT_PIN(6, 3) | ||
133 | #define WMT_PIN_SD2CMD WMT_PIN(6, 6) | ||
134 | #define WMT_PIN_SD2CLK WMT_PIN(6, 7) | ||
135 | #define WMT_PIN_SD2PWR WMT_PIN(6, 9) | ||
136 | #define WMT_PIN_SD1CLK WMT_PIN(7, 0) | ||
137 | #define WMT_PIN_SD1CMD WMT_PIN(7, 1) | ||
138 | #define WMT_PIN_SD1PWR WMT_PIN(7, 10) | ||
139 | #define WMT_PIN_SD1WP WMT_PIN(7, 11) | ||
140 | #define WMT_PIN_SD1CD WMT_PIN(7, 12) | ||
141 | #define WMT_PIN_PWMOUT1 WMT_PIN(7, 26) | ||
142 | #define WMT_PIN_PWMOUT0 WMT_PIN(7, 27) | ||
143 | |||
144 | static const struct pinctrl_pin_desc wm8850_pins[] = { | ||
145 | PINCTRL_PIN(WMT_PIN_EXTGPIO0, "extgpio0"), | ||
146 | PINCTRL_PIN(WMT_PIN_EXTGPIO1, "extgpio1"), | ||
147 | PINCTRL_PIN(WMT_PIN_EXTGPIO2, "extgpio2"), | ||
148 | PINCTRL_PIN(WMT_PIN_EXTGPIO3, "extgpio3"), | ||
149 | PINCTRL_PIN(WMT_PIN_EXTGPIO4, "extgpio4"), | ||
150 | PINCTRL_PIN(WMT_PIN_EXTGPIO5, "extgpio5"), | ||
151 | PINCTRL_PIN(WMT_PIN_EXTGPIO6, "extgpio6"), | ||
152 | PINCTRL_PIN(WMT_PIN_EXTGPIO7, "extgpio7"), | ||
153 | PINCTRL_PIN(WMT_PIN_WAKEUP0, "wakeup0"), | ||
154 | PINCTRL_PIN(WMT_PIN_WAKEUP1, "wakeup1"), | ||
155 | PINCTRL_PIN(WMT_PIN_WAKEUP2, "wakeup2"), | ||
156 | PINCTRL_PIN(WMT_PIN_WAKEUP3, "wakeup3"), | ||
157 | PINCTRL_PIN(WMT_PIN_SUSGPIO0, "susgpio0"), | ||
158 | PINCTRL_PIN(WMT_PIN_SUSGPIO1, "susgpio1"), | ||
159 | PINCTRL_PIN(WMT_PIN_SD0CD, "sd0_cd"), | ||
160 | PINCTRL_PIN(WMT_PIN_VDOUT0, "vdout0"), | ||
161 | PINCTRL_PIN(WMT_PIN_VDOUT1, "vdout1"), | ||
162 | PINCTRL_PIN(WMT_PIN_VDOUT2, "vdout2"), | ||
163 | PINCTRL_PIN(WMT_PIN_VDOUT3, "vdout3"), | ||
164 | PINCTRL_PIN(WMT_PIN_VDOUT4, "vdout4"), | ||
165 | PINCTRL_PIN(WMT_PIN_VDOUT5, "vdout5"), | ||
166 | PINCTRL_PIN(WMT_PIN_VDOUT6, "vdout6"), | ||
167 | PINCTRL_PIN(WMT_PIN_VDOUT7, "vdout7"), | ||
168 | PINCTRL_PIN(WMT_PIN_VDOUT8, "vdout8"), | ||
169 | PINCTRL_PIN(WMT_PIN_VDOUT9, "vdout9"), | ||
170 | PINCTRL_PIN(WMT_PIN_VDOUT10, "vdout10"), | ||
171 | PINCTRL_PIN(WMT_PIN_VDOUT11, "vdout11"), | ||
172 | PINCTRL_PIN(WMT_PIN_VDOUT12, "vdout12"), | ||
173 | PINCTRL_PIN(WMT_PIN_VDOUT13, "vdout13"), | ||
174 | PINCTRL_PIN(WMT_PIN_VDOUT14, "vdout14"), | ||
175 | PINCTRL_PIN(WMT_PIN_VDOUT15, "vdout15"), | ||
176 | PINCTRL_PIN(WMT_PIN_VDOUT16, "vdout16"), | ||
177 | PINCTRL_PIN(WMT_PIN_VDOUT17, "vdout17"), | ||
178 | PINCTRL_PIN(WMT_PIN_VDOUT18, "vdout18"), | ||
179 | PINCTRL_PIN(WMT_PIN_VDOUT19, "vdout19"), | ||
180 | PINCTRL_PIN(WMT_PIN_VDOUT20, "vdout20"), | ||
181 | PINCTRL_PIN(WMT_PIN_VDOUT21, "vdout21"), | ||
182 | PINCTRL_PIN(WMT_PIN_VDOUT22, "vdout22"), | ||
183 | PINCTRL_PIN(WMT_PIN_VDOUT23, "vdout23"), | ||
184 | PINCTRL_PIN(WMT_PIN_VDIN0, "vdin0"), | ||
185 | PINCTRL_PIN(WMT_PIN_VDIN1, "vdin1"), | ||
186 | PINCTRL_PIN(WMT_PIN_VDIN2, "vdin2"), | ||
187 | PINCTRL_PIN(WMT_PIN_VDIN3, "vdin3"), | ||
188 | PINCTRL_PIN(WMT_PIN_VDIN4, "vdin4"), | ||
189 | PINCTRL_PIN(WMT_PIN_VDIN5, "vdin5"), | ||
190 | PINCTRL_PIN(WMT_PIN_VDIN6, "vdin6"), | ||
191 | PINCTRL_PIN(WMT_PIN_VDIN7, "vdin7"), | ||
192 | PINCTRL_PIN(WMT_PIN_SPI0_MOSI, "spi0_mosi"), | ||
193 | PINCTRL_PIN(WMT_PIN_SPI0_MISO, "spi0_miso"), | ||
194 | PINCTRL_PIN(WMT_PIN_SPI0_SS, "spi0_ss"), | ||
195 | PINCTRL_PIN(WMT_PIN_SPI0_CLK, "spi0_clk"), | ||
196 | PINCTRL_PIN(WMT_PIN_SPI0_SSB, "spi0_ssb"), | ||
197 | PINCTRL_PIN(WMT_PIN_SD0CLK, "sd0_clk"), | ||
198 | PINCTRL_PIN(WMT_PIN_SD0CMD, "sd0_cmd"), | ||
199 | PINCTRL_PIN(WMT_PIN_SD0WP, "sd0_wp"), | ||
200 | PINCTRL_PIN(WMT_PIN_SD0DATA0, "sd0_data0"), | ||
201 | PINCTRL_PIN(WMT_PIN_SD0DATA1, "sd0_data1"), | ||
202 | PINCTRL_PIN(WMT_PIN_SD0DATA2, "sd0_data2"), | ||
203 | PINCTRL_PIN(WMT_PIN_SD0DATA3, "sd0_data3"), | ||
204 | PINCTRL_PIN(WMT_PIN_SD1DATA0, "sd1_data0"), | ||
205 | PINCTRL_PIN(WMT_PIN_SD1DATA1, "sd1_data1"), | ||
206 | PINCTRL_PIN(WMT_PIN_SD1DATA2, "sd1_data2"), | ||
207 | PINCTRL_PIN(WMT_PIN_SD1DATA3, "sd1_data3"), | ||
208 | PINCTRL_PIN(WMT_PIN_SD1DATA4, "sd1_data4"), | ||
209 | PINCTRL_PIN(WMT_PIN_SD1DATA5, "sd1_data5"), | ||
210 | PINCTRL_PIN(WMT_PIN_SD1DATA6, "sd1_data6"), | ||
211 | PINCTRL_PIN(WMT_PIN_SD1DATA7, "sd1_data7"), | ||
212 | PINCTRL_PIN(WMT_PIN_I2C0_SCL, "i2c0_scl"), | ||
213 | PINCTRL_PIN(WMT_PIN_I2C0_SDA, "i2c0_sda"), | ||
214 | PINCTRL_PIN(WMT_PIN_I2C1_SCL, "i2c1_scl"), | ||
215 | PINCTRL_PIN(WMT_PIN_I2C1_SDA, "i2c1_sda"), | ||
216 | PINCTRL_PIN(WMT_PIN_I2C2_SCL, "i2c2_scl"), | ||
217 | PINCTRL_PIN(WMT_PIN_I2C2_SDA, "i2c2_sda"), | ||
218 | PINCTRL_PIN(WMT_PIN_UART0_RTS, "uart0_rts"), | ||
219 | PINCTRL_PIN(WMT_PIN_UART0_TXD, "uart0_txd"), | ||
220 | PINCTRL_PIN(WMT_PIN_UART0_CTS, "uart0_cts"), | ||
221 | PINCTRL_PIN(WMT_PIN_UART0_RXD, "uart0_rxd"), | ||
222 | PINCTRL_PIN(WMT_PIN_UART1_RTS, "uart1_rts"), | ||
223 | PINCTRL_PIN(WMT_PIN_UART1_TXD, "uart1_txd"), | ||
224 | PINCTRL_PIN(WMT_PIN_UART1_CTS, "uart1_cts"), | ||
225 | PINCTRL_PIN(WMT_PIN_UART1_RXD, "uart1_rxd"), | ||
226 | PINCTRL_PIN(WMT_PIN_UART2_RTS, "uart2_rts"), | ||
227 | PINCTRL_PIN(WMT_PIN_UART2_TXD, "uart2_txd"), | ||
228 | PINCTRL_PIN(WMT_PIN_UART2_CTS, "uart2_cts"), | ||
229 | PINCTRL_PIN(WMT_PIN_UART2_RXD, "uart2_rxd"), | ||
230 | PINCTRL_PIN(WMT_PIN_SD2WP, "sd2_wp"), | ||
231 | PINCTRL_PIN(WMT_PIN_SD2CMD, "sd2_cmd"), | ||
232 | PINCTRL_PIN(WMT_PIN_SD2CLK, "sd2_clk"), | ||
233 | PINCTRL_PIN(WMT_PIN_SD2PWR, "sd2_pwr"), | ||
234 | PINCTRL_PIN(WMT_PIN_SD1CLK, "sd1_clk"), | ||
235 | PINCTRL_PIN(WMT_PIN_SD1CMD, "sd1_cmd"), | ||
236 | PINCTRL_PIN(WMT_PIN_SD1PWR, "sd1_pwr"), | ||
237 | PINCTRL_PIN(WMT_PIN_SD1WP, "sd1_wp"), | ||
238 | PINCTRL_PIN(WMT_PIN_SD1CD, "sd1_cd"), | ||
239 | PINCTRL_PIN(WMT_PIN_PWMOUT1, "pwmout1"), | ||
240 | PINCTRL_PIN(WMT_PIN_PWMOUT0, "pwmout0"), | ||
241 | }; | ||
242 | |||
243 | /* Order of these names must match the above list */ | ||
244 | static const char * const wm8850_groups[] = { | ||
245 | "extgpio0", | ||
246 | "extgpio1", | ||
247 | "extgpio2", | ||
248 | "extgpio3", | ||
249 | "extgpio4", | ||
250 | "extgpio5", | ||
251 | "extgpio6", | ||
252 | "extgpio7", | ||
253 | "wakeup0", | ||
254 | "wakeup1", | ||
255 | "wakeup2", | ||
256 | "wakeup3", | ||
257 | "susgpio0", | ||
258 | "susgpio1", | ||
259 | "sd0_cd", | ||
260 | "vdout0", | ||
261 | "vdout1", | ||
262 | "vdout2", | ||
263 | "vdout3", | ||
264 | "vdout4", | ||
265 | "vdout5", | ||
266 | "vdout6", | ||
267 | "vdout7", | ||
268 | "vdout8", | ||
269 | "vdout9", | ||
270 | "vdout10", | ||
271 | "vdout11", | ||
272 | "vdout12", | ||
273 | "vdout13", | ||
274 | "vdout14", | ||
275 | "vdout15", | ||
276 | "vdout16", | ||
277 | "vdout17", | ||
278 | "vdout18", | ||
279 | "vdout19", | ||
280 | "vdout20", | ||
281 | "vdout21", | ||
282 | "vdout22", | ||
283 | "vdout23", | ||
284 | "vdin0", | ||
285 | "vdin1", | ||
286 | "vdin2", | ||
287 | "vdin3", | ||
288 | "vdin4", | ||
289 | "vdin5", | ||
290 | "vdin6", | ||
291 | "vdin7", | ||
292 | "spi0_mosi", | ||
293 | "spi0_miso", | ||
294 | "spi0_ss", | ||
295 | "spi0_clk", | ||
296 | "spi0_ssb", | ||
297 | "sd0_clk", | ||
298 | "sd0_cmd", | ||
299 | "sd0_wp", | ||
300 | "sd0_data0", | ||
301 | "sd0_data1", | ||
302 | "sd0_data2", | ||
303 | "sd0_data3", | ||
304 | "sd1_data0", | ||
305 | "sd1_data1", | ||
306 | "sd1_data2", | ||
307 | "sd1_data3", | ||
308 | "sd1_data4", | ||
309 | "sd1_data5", | ||
310 | "sd1_data6", | ||
311 | "sd1_data7", | ||
312 | "i2c0_scl", | ||
313 | "i2c0_sda", | ||
314 | "i2c1_scl", | ||
315 | "i2c1_sda", | ||
316 | "i2c2_scl", | ||
317 | "i2c2_sda", | ||
318 | "uart0_rts", | ||
319 | "uart0_txd", | ||
320 | "uart0_cts", | ||
321 | "uart0_rxd", | ||
322 | "uart1_rts", | ||
323 | "uart1_txd", | ||
324 | "uart1_cts", | ||
325 | "uart1_rxd", | ||
326 | "uart2_rts", | ||
327 | "uart2_txd", | ||
328 | "uart2_cts", | ||
329 | "uart2_rxd", | ||
330 | "sd2_wp", | ||
331 | "sd2_cmd", | ||
332 | "sd2_clk", | ||
333 | "sd2_pwr", | ||
334 | "sd1_clk", | ||
335 | "sd1_cmd", | ||
336 | "sd1_pwr", | ||
337 | "sd1_wp", | ||
338 | "sd1_cd", | ||
339 | "pwmout1", | ||
340 | "pwmout0", | ||
341 | }; | ||
342 | |||
343 | static int wm8850_pinctrl_probe(struct platform_device *pdev) | ||
344 | { | ||
345 | struct wmt_pinctrl_data *data; | ||
346 | |||
347 | data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); | ||
348 | if (!data) { | ||
349 | dev_err(&pdev->dev, "failed to allocate data\n"); | ||
350 | return -ENOMEM; | ||
351 | } | ||
352 | |||
353 | data->banks = wm8850_banks; | ||
354 | data->nbanks = ARRAY_SIZE(wm8850_banks); | ||
355 | data->pins = wm8850_pins; | ||
356 | data->npins = ARRAY_SIZE(wm8850_pins); | ||
357 | data->groups = wm8850_groups; | ||
358 | data->ngroups = ARRAY_SIZE(wm8850_groups); | ||
359 | |||
360 | return wmt_pinctrl_probe(pdev, data); | ||
361 | } | ||
362 | |||
363 | static int wm8850_pinctrl_remove(struct platform_device *pdev) | ||
364 | { | ||
365 | return wmt_pinctrl_remove(pdev); | ||
366 | } | ||
367 | |||
368 | static struct of_device_id wmt_pinctrl_of_match[] = { | ||
369 | { .compatible = "wm,wm8850-pinctrl" }, | ||
370 | { /* sentinel */ }, | ||
371 | }; | ||
372 | |||
373 | static struct platform_driver wmt_pinctrl_driver = { | ||
374 | .probe = wm8850_pinctrl_probe, | ||
375 | .remove = wm8850_pinctrl_remove, | ||
376 | .driver = { | ||
377 | .name = "pinctrl-wm8850", | ||
378 | .owner = THIS_MODULE, | ||
379 | .of_match_table = wmt_pinctrl_of_match, | ||
380 | }, | ||
381 | }; | ||
382 | |||
383 | module_platform_driver(wmt_pinctrl_driver); | ||
384 | |||
385 | MODULE_AUTHOR("Tony Prisk <linux@prisktech.co.nz>"); | ||
386 | MODULE_DESCRIPTION("Wondermedia WM8850 Pincontrol driver"); | ||
387 | MODULE_LICENSE("GPL v2"); | ||
388 | MODULE_DEVICE_TABLE(of, wmt_pinctrl_of_match); | ||
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.c b/drivers/pinctrl/vt8500/pinctrl-wmt.c new file mode 100644 index 000000000000..14400a7974bd --- /dev/null +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.c | |||
@@ -0,0 +1,632 @@ | |||
1 | /* | ||
2 | * Pinctrl driver for the Wondermedia SoC's | ||
3 | * | ||
4 | * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/err.h> | ||
17 | #include <linux/gpio.h> | ||
18 | #include <linux/interrupt.h> | ||
19 | #include <linux/io.h> | ||
20 | #include <linux/irq.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/of.h> | ||
23 | #include <linux/of_irq.h> | ||
24 | #include <linux/pinctrl/consumer.h> | ||
25 | #include <linux/pinctrl/machine.h> | ||
26 | #include <linux/pinctrl/pinconf.h> | ||
27 | #include <linux/pinctrl/pinconf-generic.h> | ||
28 | #include <linux/pinctrl/pinctrl.h> | ||
29 | #include <linux/pinctrl/pinmux.h> | ||
30 | #include <linux/platform_device.h> | ||
31 | #include <linux/slab.h> | ||
32 | |||
33 | #include "pinctrl-wmt.h" | ||
34 | |||
35 | static inline void wmt_setbits(struct wmt_pinctrl_data *data, u32 reg, | ||
36 | u32 mask) | ||
37 | { | ||
38 | u32 val; | ||
39 | |||
40 | val = readl_relaxed(data->base + reg); | ||
41 | val |= mask; | ||
42 | writel_relaxed(val, data->base + reg); | ||
43 | } | ||
44 | |||
45 | static inline void wmt_clearbits(struct wmt_pinctrl_data *data, u32 reg, | ||
46 | u32 mask) | ||
47 | { | ||
48 | u32 val; | ||
49 | |||
50 | val = readl_relaxed(data->base + reg); | ||
51 | val &= ~mask; | ||
52 | writel_relaxed(val, data->base + reg); | ||
53 | } | ||
54 | |||
55 | enum wmt_func_sel { | ||
56 | WMT_FSEL_GPIO_IN = 0, | ||
57 | WMT_FSEL_GPIO_OUT = 1, | ||
58 | WMT_FSEL_ALT = 2, | ||
59 | WMT_FSEL_COUNT = 3, | ||
60 | }; | ||
61 | |||
62 | static const char * const wmt_functions[WMT_FSEL_COUNT] = { | ||
63 | [WMT_FSEL_GPIO_IN] = "gpio_in", | ||
64 | [WMT_FSEL_GPIO_OUT] = "gpio_out", | ||
65 | [WMT_FSEL_ALT] = "alt", | ||
66 | }; | ||
67 | |||
68 | static int wmt_pmx_get_functions_count(struct pinctrl_dev *pctldev) | ||
69 | { | ||
70 | return WMT_FSEL_COUNT; | ||
71 | } | ||
72 | |||
73 | static const char *wmt_pmx_get_function_name(struct pinctrl_dev *pctldev, | ||
74 | unsigned selector) | ||
75 | { | ||
76 | return wmt_functions[selector]; | ||
77 | } | ||
78 | |||
79 | static int wmt_pmx_get_function_groups(struct pinctrl_dev *pctldev, | ||
80 | unsigned selector, | ||
81 | const char * const **groups, | ||
82 | unsigned * const num_groups) | ||
83 | { | ||
84 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
85 | |||
86 | /* every pin does every function */ | ||
87 | *groups = data->groups; | ||
88 | *num_groups = data->ngroups; | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | static int wmt_set_pinmux(struct wmt_pinctrl_data *data, unsigned func, | ||
94 | unsigned pin) | ||
95 | { | ||
96 | u32 bank = WMT_BANK_FROM_PIN(pin); | ||
97 | u32 bit = WMT_BIT_FROM_PIN(pin); | ||
98 | u32 reg_en = data->banks[bank].reg_en; | ||
99 | u32 reg_dir = data->banks[bank].reg_dir; | ||
100 | |||
101 | if (reg_dir == NO_REG) { | ||
102 | dev_err(data->dev, "pin:%d no direction register defined\n", | ||
103 | pin); | ||
104 | return -EINVAL; | ||
105 | } | ||
106 | |||
107 | /* | ||
108 | * If reg_en == NO_REG, we assume it is a dedicated GPIO and cannot be | ||
109 | * disabled (as on VT8500) and that no alternate function is available. | ||
110 | */ | ||
111 | switch (func) { | ||
112 | case WMT_FSEL_GPIO_IN: | ||
113 | if (reg_en != NO_REG) | ||
114 | wmt_setbits(data, reg_en, BIT(bit)); | ||
115 | wmt_clearbits(data, reg_dir, BIT(bit)); | ||
116 | break; | ||
117 | case WMT_FSEL_GPIO_OUT: | ||
118 | if (reg_en != NO_REG) | ||
119 | wmt_setbits(data, reg_en, BIT(bit)); | ||
120 | wmt_setbits(data, reg_dir, BIT(bit)); | ||
121 | break; | ||
122 | case WMT_FSEL_ALT: | ||
123 | if (reg_en == NO_REG) { | ||
124 | dev_err(data->dev, "pin:%d no alt function available\n", | ||
125 | pin); | ||
126 | return -EINVAL; | ||
127 | } | ||
128 | wmt_clearbits(data, reg_en, BIT(bit)); | ||
129 | } | ||
130 | |||
131 | return 0; | ||
132 | } | ||
133 | |||
134 | static int wmt_pmx_enable(struct pinctrl_dev *pctldev, | ||
135 | unsigned func_selector, | ||
136 | unsigned group_selector) | ||
137 | { | ||
138 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
139 | u32 pinnum = data->pins[group_selector].number; | ||
140 | |||
141 | return wmt_set_pinmux(data, func_selector, pinnum); | ||
142 | } | ||
143 | |||
144 | static void wmt_pmx_disable(struct pinctrl_dev *pctldev, | ||
145 | unsigned func_selector, | ||
146 | unsigned group_selector) | ||
147 | { | ||
148 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
149 | u32 pinnum = data->pins[group_selector].number; | ||
150 | |||
151 | /* disable by setting GPIO_IN */ | ||
152 | wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, pinnum); | ||
153 | } | ||
154 | |||
155 | static void wmt_pmx_gpio_disable_free(struct pinctrl_dev *pctldev, | ||
156 | struct pinctrl_gpio_range *range, | ||
157 | unsigned offset) | ||
158 | { | ||
159 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
160 | |||
161 | /* disable by setting GPIO_IN */ | ||
162 | wmt_set_pinmux(data, WMT_FSEL_GPIO_IN, offset); | ||
163 | } | ||
164 | |||
165 | static int wmt_pmx_gpio_set_direction(struct pinctrl_dev *pctldev, | ||
166 | struct pinctrl_gpio_range *range, | ||
167 | unsigned offset, | ||
168 | bool input) | ||
169 | { | ||
170 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
171 | |||
172 | wmt_set_pinmux(data, (input ? WMT_FSEL_GPIO_IN : WMT_FSEL_GPIO_OUT), | ||
173 | offset); | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static struct pinmux_ops wmt_pinmux_ops = { | ||
179 | .get_functions_count = wmt_pmx_get_functions_count, | ||
180 | .get_function_name = wmt_pmx_get_function_name, | ||
181 | .get_function_groups = wmt_pmx_get_function_groups, | ||
182 | .enable = wmt_pmx_enable, | ||
183 | .disable = wmt_pmx_disable, | ||
184 | .gpio_disable_free = wmt_pmx_gpio_disable_free, | ||
185 | .gpio_set_direction = wmt_pmx_gpio_set_direction, | ||
186 | }; | ||
187 | |||
188 | static int wmt_get_groups_count(struct pinctrl_dev *pctldev) | ||
189 | { | ||
190 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
191 | |||
192 | return data->ngroups; | ||
193 | } | ||
194 | |||
195 | static const char *wmt_get_group_name(struct pinctrl_dev *pctldev, | ||
196 | unsigned selector) | ||
197 | { | ||
198 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
199 | |||
200 | return data->groups[selector]; | ||
201 | } | ||
202 | |||
203 | static int wmt_get_group_pins(struct pinctrl_dev *pctldev, | ||
204 | unsigned selector, | ||
205 | const unsigned **pins, | ||
206 | unsigned *num_pins) | ||
207 | { | ||
208 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
209 | |||
210 | *pins = &data->pins[selector].number; | ||
211 | *num_pins = 1; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int wmt_pctl_find_group_by_pin(struct wmt_pinctrl_data *data, u32 pin) | ||
217 | { | ||
218 | int i; | ||
219 | |||
220 | for (i = 0; i < data->npins; i++) { | ||
221 | if (data->pins[i].number == pin) | ||
222 | return i; | ||
223 | } | ||
224 | |||
225 | return -EINVAL; | ||
226 | } | ||
227 | |||
228 | static int wmt_pctl_dt_node_to_map_func(struct wmt_pinctrl_data *data, | ||
229 | struct device_node *np, | ||
230 | u32 pin, u32 fnum, | ||
231 | struct pinctrl_map **maps) | ||
232 | { | ||
233 | int group; | ||
234 | struct pinctrl_map *map = *maps; | ||
235 | |||
236 | if (fnum >= ARRAY_SIZE(wmt_functions)) { | ||
237 | dev_err(data->dev, "invalid wm,function %d\n", fnum); | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | group = wmt_pctl_find_group_by_pin(data, pin); | ||
242 | if (group < 0) { | ||
243 | dev_err(data->dev, "unable to match pin %d to group\n", pin); | ||
244 | return group; | ||
245 | } | ||
246 | |||
247 | map->type = PIN_MAP_TYPE_MUX_GROUP; | ||
248 | map->data.mux.group = data->groups[group]; | ||
249 | map->data.mux.function = wmt_functions[fnum]; | ||
250 | (*maps)++; | ||
251 | |||
252 | return 0; | ||
253 | } | ||
254 | |||
255 | static int wmt_pctl_dt_node_to_map_pull(struct wmt_pinctrl_data *data, | ||
256 | struct device_node *np, | ||
257 | u32 pin, u32 pull, | ||
258 | struct pinctrl_map **maps) | ||
259 | { | ||
260 | int group; | ||
261 | unsigned long *configs; | ||
262 | struct pinctrl_map *map = *maps; | ||
263 | |||
264 | if (pull > 2) { | ||
265 | dev_err(data->dev, "invalid wm,pull %d\n", pull); | ||
266 | return -EINVAL; | ||
267 | } | ||
268 | |||
269 | group = wmt_pctl_find_group_by_pin(data, pin); | ||
270 | if (group < 0) { | ||
271 | dev_err(data->dev, "unable to match pin %d to group\n", pin); | ||
272 | return group; | ||
273 | } | ||
274 | |||
275 | configs = kzalloc(sizeof(*configs), GFP_KERNEL); | ||
276 | if (!configs) | ||
277 | return -ENOMEM; | ||
278 | |||
279 | configs[0] = pull; | ||
280 | |||
281 | map->type = PIN_MAP_TYPE_CONFIGS_PIN; | ||
282 | map->data.configs.group_or_pin = data->groups[group]; | ||
283 | map->data.configs.configs = configs; | ||
284 | map->data.configs.num_configs = 1; | ||
285 | (*maps)++; | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static void wmt_pctl_dt_free_map(struct pinctrl_dev *pctldev, | ||
291 | struct pinctrl_map *maps, | ||
292 | unsigned num_maps) | ||
293 | { | ||
294 | int i; | ||
295 | |||
296 | for (i = 0; i < num_maps; i++) | ||
297 | if (maps[i].type == PIN_MAP_TYPE_CONFIGS_PIN) | ||
298 | kfree(maps[i].data.configs.configs); | ||
299 | |||
300 | kfree(maps); | ||
301 | } | ||
302 | |||
303 | static int wmt_pctl_dt_node_to_map(struct pinctrl_dev *pctldev, | ||
304 | struct device_node *np, | ||
305 | struct pinctrl_map **map, | ||
306 | unsigned *num_maps) | ||
307 | { | ||
308 | struct pinctrl_map *maps, *cur_map; | ||
309 | struct property *pins, *funcs, *pulls; | ||
310 | u32 pin, func, pull; | ||
311 | int num_pins, num_funcs, num_pulls, maps_per_pin; | ||
312 | int i, err; | ||
313 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
314 | |||
315 | pins = of_find_property(np, "wm,pins", NULL); | ||
316 | if (!pins) { | ||
317 | dev_err(data->dev, "missing wmt,pins property\n"); | ||
318 | return -EINVAL; | ||
319 | } | ||
320 | |||
321 | funcs = of_find_property(np, "wm,function", NULL); | ||
322 | pulls = of_find_property(np, "wm,pull", NULL); | ||
323 | |||
324 | if (!funcs && !pulls) { | ||
325 | dev_err(data->dev, "neither wm,function nor wm,pull specified\n"); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | /* | ||
330 | * The following lines calculate how many values are defined for each | ||
331 | * of the properties. | ||
332 | */ | ||
333 | num_pins = pins->length / sizeof(u32); | ||
334 | num_funcs = funcs ? (funcs->length / sizeof(u32)) : 0; | ||
335 | num_pulls = pulls ? (pulls->length / sizeof(u32)) : 0; | ||
336 | |||
337 | if (num_funcs > 1 && num_funcs != num_pins) { | ||
338 | dev_err(data->dev, "wm,function must have 1 or %d entries\n", | ||
339 | num_pins); | ||
340 | return -EINVAL; | ||
341 | } | ||
342 | |||
343 | if (num_pulls > 1 && num_pulls != num_pins) { | ||
344 | dev_err(data->dev, "wm,pull must have 1 or %d entries\n", | ||
345 | num_pins); | ||
346 | return -EINVAL; | ||
347 | } | ||
348 | |||
349 | maps_per_pin = 0; | ||
350 | if (num_funcs) | ||
351 | maps_per_pin++; | ||
352 | if (num_pulls) | ||
353 | maps_per_pin++; | ||
354 | |||
355 | cur_map = maps = kzalloc(num_pins * maps_per_pin * sizeof(*maps), | ||
356 | GFP_KERNEL); | ||
357 | if (!maps) | ||
358 | return -ENOMEM; | ||
359 | |||
360 | for (i = 0; i < num_pins; i++) { | ||
361 | err = of_property_read_u32_index(np, "wm,pins", i, &pin); | ||
362 | if (err) | ||
363 | goto fail; | ||
364 | |||
365 | if (pin >= (data->nbanks * 32)) { | ||
366 | dev_err(data->dev, "invalid wm,pins value\n"); | ||
367 | err = -EINVAL; | ||
368 | goto fail; | ||
369 | } | ||
370 | |||
371 | if (num_funcs) { | ||
372 | err = of_property_read_u32_index(np, "wm,function", | ||
373 | (num_funcs > 1 ? i : 0), &func); | ||
374 | if (err) | ||
375 | goto fail; | ||
376 | |||
377 | err = wmt_pctl_dt_node_to_map_func(data, np, pin, func, | ||
378 | &cur_map); | ||
379 | if (err) | ||
380 | goto fail; | ||
381 | } | ||
382 | |||
383 | if (num_pulls) { | ||
384 | err = of_property_read_u32_index(np, "wm,pull", | ||
385 | (num_pulls > 1 ? i : 0), &pull); | ||
386 | if (err) | ||
387 | goto fail; | ||
388 | |||
389 | err = wmt_pctl_dt_node_to_map_pull(data, np, pin, pull, | ||
390 | &cur_map); | ||
391 | if (err) | ||
392 | goto fail; | ||
393 | } | ||
394 | } | ||
395 | *map = maps; | ||
396 | *num_maps = num_pins * maps_per_pin; | ||
397 | return 0; | ||
398 | |||
399 | /* | ||
400 | * The fail path removes any maps that have been allocated. The fail path is | ||
401 | * only called from code after maps has been kzalloc'd. It is also safe to | ||
402 | * pass 'num_pins * maps_per_pin' as the map count even though we probably | ||
403 | * failed before all the mappings were read as all maps are allocated at once, | ||
404 | * and configs are only allocated for .type = PIN_MAP_TYPE_CONFIGS_PIN - there | ||
405 | * is no failpath where a config can be allocated without .type being set. | ||
406 | */ | ||
407 | fail: | ||
408 | wmt_pctl_dt_free_map(pctldev, maps, num_pins * maps_per_pin); | ||
409 | return err; | ||
410 | } | ||
411 | |||
412 | static struct pinctrl_ops wmt_pctl_ops = { | ||
413 | .get_groups_count = wmt_get_groups_count, | ||
414 | .get_group_name = wmt_get_group_name, | ||
415 | .get_group_pins = wmt_get_group_pins, | ||
416 | .dt_node_to_map = wmt_pctl_dt_node_to_map, | ||
417 | .dt_free_map = wmt_pctl_dt_free_map, | ||
418 | }; | ||
419 | |||
420 | static int wmt_pinconf_get(struct pinctrl_dev *pctldev, unsigned pin, | ||
421 | unsigned long *config) | ||
422 | { | ||
423 | return -ENOTSUPP; | ||
424 | } | ||
425 | |||
426 | static int wmt_pinconf_set(struct pinctrl_dev *pctldev, unsigned pin, | ||
427 | unsigned long config) | ||
428 | { | ||
429 | struct wmt_pinctrl_data *data = pinctrl_dev_get_drvdata(pctldev); | ||
430 | enum pin_config_param param = pinconf_to_config_param(config); | ||
431 | u16 arg = pinconf_to_config_argument(config); | ||
432 | u32 bank = WMT_BANK_FROM_PIN(pin); | ||
433 | u32 bit = WMT_BIT_FROM_PIN(pin); | ||
434 | u32 reg_pull_en = data->banks[bank].reg_pull_en; | ||
435 | u32 reg_pull_cfg = data->banks[bank].reg_pull_cfg; | ||
436 | |||
437 | if ((reg_pull_en == NO_REG) || (reg_pull_cfg == NO_REG)) { | ||
438 | dev_err(data->dev, "bias functions not supported on pin %d\n", | ||
439 | pin); | ||
440 | return -EINVAL; | ||
441 | } | ||
442 | |||
443 | if ((param == PIN_CONFIG_BIAS_PULL_DOWN) || | ||
444 | (param == PIN_CONFIG_BIAS_PULL_UP)) { | ||
445 | if (arg == 0) | ||
446 | param = PIN_CONFIG_BIAS_DISABLE; | ||
447 | } | ||
448 | |||
449 | switch (param) { | ||
450 | case PIN_CONFIG_BIAS_DISABLE: | ||
451 | wmt_clearbits(data, reg_pull_en, BIT(bit)); | ||
452 | break; | ||
453 | case PIN_CONFIG_BIAS_PULL_DOWN: | ||
454 | wmt_clearbits(data, reg_pull_cfg, BIT(bit)); | ||
455 | wmt_setbits(data, reg_pull_en, BIT(bit)); | ||
456 | break; | ||
457 | case PIN_CONFIG_BIAS_PULL_UP: | ||
458 | wmt_setbits(data, reg_pull_cfg, BIT(bit)); | ||
459 | wmt_setbits(data, reg_pull_en, BIT(bit)); | ||
460 | break; | ||
461 | default: | ||
462 | dev_err(data->dev, "unknown pinconf param\n"); | ||
463 | return -EINVAL; | ||
464 | } | ||
465 | |||
466 | return 0; | ||
467 | } | ||
468 | |||
469 | static struct pinconf_ops wmt_pinconf_ops = { | ||
470 | .pin_config_get = wmt_pinconf_get, | ||
471 | .pin_config_set = wmt_pinconf_set, | ||
472 | }; | ||
473 | |||
474 | static struct pinctrl_desc wmt_desc = { | ||
475 | .owner = THIS_MODULE, | ||
476 | .name = "pinctrl-wmt", | ||
477 | .pctlops = &wmt_pctl_ops, | ||
478 | .pmxops = &wmt_pinmux_ops, | ||
479 | .confops = &wmt_pinconf_ops, | ||
480 | }; | ||
481 | |||
482 | static int wmt_gpio_request(struct gpio_chip *chip, unsigned offset) | ||
483 | { | ||
484 | return pinctrl_request_gpio(chip->base + offset); | ||
485 | } | ||
486 | |||
487 | static void wmt_gpio_free(struct gpio_chip *chip, unsigned offset) | ||
488 | { | ||
489 | pinctrl_free_gpio(chip->base + offset); | ||
490 | } | ||
491 | |||
492 | static int wmt_gpio_get_direction(struct gpio_chip *chip, unsigned offset) | ||
493 | { | ||
494 | struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev); | ||
495 | u32 bank = WMT_BANK_FROM_PIN(offset); | ||
496 | u32 bit = WMT_BIT_FROM_PIN(offset); | ||
497 | u32 reg_dir = data->banks[bank].reg_dir; | ||
498 | u32 val; | ||
499 | |||
500 | val = readl_relaxed(data->base + reg_dir); | ||
501 | if (val & BIT(bit)) | ||
502 | return GPIOF_DIR_OUT; | ||
503 | else | ||
504 | return GPIOF_DIR_IN; | ||
505 | } | ||
506 | |||
507 | static int wmt_gpio_direction_input(struct gpio_chip *chip, unsigned offset) | ||
508 | { | ||
509 | return pinctrl_gpio_direction_input(chip->base + offset); | ||
510 | } | ||
511 | |||
512 | static int wmt_gpio_direction_output(struct gpio_chip *chip, unsigned offset, | ||
513 | int value) | ||
514 | { | ||
515 | return pinctrl_gpio_direction_output(chip->base + offset); | ||
516 | } | ||
517 | |||
518 | static int wmt_gpio_get_value(struct gpio_chip *chip, unsigned offset) | ||
519 | { | ||
520 | struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev); | ||
521 | u32 bank = WMT_BANK_FROM_PIN(offset); | ||
522 | u32 bit = WMT_BIT_FROM_PIN(offset); | ||
523 | u32 reg_data_in = data->banks[bank].reg_data_in; | ||
524 | |||
525 | if (reg_data_in == NO_REG) { | ||
526 | dev_err(data->dev, "no data in register defined\n"); | ||
527 | return -EINVAL; | ||
528 | } | ||
529 | |||
530 | return !!(readl_relaxed(data->base + reg_data_in) & BIT(bit)); | ||
531 | } | ||
532 | |||
533 | static void wmt_gpio_set_value(struct gpio_chip *chip, unsigned offset, | ||
534 | int val) | ||
535 | { | ||
536 | struct wmt_pinctrl_data *data = dev_get_drvdata(chip->dev); | ||
537 | u32 bank = WMT_BANK_FROM_PIN(offset); | ||
538 | u32 bit = WMT_BIT_FROM_PIN(offset); | ||
539 | u32 reg_data_out = data->banks[bank].reg_data_out; | ||
540 | |||
541 | if (reg_data_out == NO_REG) { | ||
542 | dev_err(data->dev, "no data out register defined\n"); | ||
543 | return; | ||
544 | } | ||
545 | |||
546 | if (val) | ||
547 | wmt_setbits(data, reg_data_out, BIT(bit)); | ||
548 | else | ||
549 | wmt_clearbits(data, reg_data_out, BIT(bit)); | ||
550 | } | ||
551 | |||
552 | static struct gpio_chip wmt_gpio_chip = { | ||
553 | .label = "gpio-wmt", | ||
554 | .owner = THIS_MODULE, | ||
555 | .request = wmt_gpio_request, | ||
556 | .free = wmt_gpio_free, | ||
557 | .get_direction = wmt_gpio_get_direction, | ||
558 | .direction_input = wmt_gpio_direction_input, | ||
559 | .direction_output = wmt_gpio_direction_output, | ||
560 | .get = wmt_gpio_get_value, | ||
561 | .set = wmt_gpio_set_value, | ||
562 | .can_sleep = 0, | ||
563 | }; | ||
564 | |||
565 | int wmt_pinctrl_probe(struct platform_device *pdev, | ||
566 | struct wmt_pinctrl_data *data) | ||
567 | { | ||
568 | int err; | ||
569 | struct resource *res; | ||
570 | |||
571 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
572 | data->base = devm_request_and_ioremap(&pdev->dev, res); | ||
573 | if (!data->base) { | ||
574 | dev_err(&pdev->dev, "failed to map memory resource\n"); | ||
575 | return -EBUSY; | ||
576 | } | ||
577 | |||
578 | wmt_desc.pins = data->pins; | ||
579 | wmt_desc.npins = data->npins; | ||
580 | |||
581 | data->gpio_chip = wmt_gpio_chip; | ||
582 | data->gpio_chip.dev = &pdev->dev; | ||
583 | data->gpio_chip.of_node = pdev->dev.of_node; | ||
584 | data->gpio_chip.ngpio = data->nbanks * 32; | ||
585 | |||
586 | platform_set_drvdata(pdev, data); | ||
587 | |||
588 | data->dev = &pdev->dev; | ||
589 | |||
590 | data->pctl_dev = pinctrl_register(&wmt_desc, &pdev->dev, data); | ||
591 | if (IS_ERR(data->pctl_dev)) { | ||
592 | dev_err(&pdev->dev, "Failed to register pinctrl\n"); | ||
593 | return -EINVAL; | ||
594 | } | ||
595 | |||
596 | err = gpiochip_add(&data->gpio_chip); | ||
597 | if (err) { | ||
598 | dev_err(&pdev->dev, "could not add GPIO chip\n"); | ||
599 | goto fail_gpio; | ||
600 | } | ||
601 | |||
602 | err = gpiochip_add_pin_range(&data->gpio_chip, dev_name(data->dev), | ||
603 | 0, 0, data->nbanks * 32); | ||
604 | if (err) | ||
605 | goto fail_range; | ||
606 | |||
607 | dev_info(&pdev->dev, "Pin controller initialized\n"); | ||
608 | |||
609 | return 0; | ||
610 | |||
611 | fail_range: | ||
612 | err = gpiochip_remove(&data->gpio_chip); | ||
613 | if (err) | ||
614 | dev_err(&pdev->dev, "failed to remove gpio chip\n"); | ||
615 | fail_gpio: | ||
616 | pinctrl_unregister(data->pctl_dev); | ||
617 | return err; | ||
618 | } | ||
619 | |||
620 | int wmt_pinctrl_remove(struct platform_device *pdev) | ||
621 | { | ||
622 | struct wmt_pinctrl_data *data = platform_get_drvdata(pdev); | ||
623 | int err; | ||
624 | |||
625 | err = gpiochip_remove(&data->gpio_chip); | ||
626 | if (err) | ||
627 | dev_err(&pdev->dev, "failed to remove gpio chip\n"); | ||
628 | |||
629 | pinctrl_unregister(data->pctl_dev); | ||
630 | |||
631 | return 0; | ||
632 | } | ||
diff --git a/drivers/pinctrl/vt8500/pinctrl-wmt.h b/drivers/pinctrl/vt8500/pinctrl-wmt.h new file mode 100644 index 000000000000..41f5f2deb5d6 --- /dev/null +++ b/drivers/pinctrl/vt8500/pinctrl-wmt.h | |||
@@ -0,0 +1,79 @@ | |||
1 | /* | ||
2 | * Pinctrl driver for the Wondermedia SoC's | ||
3 | * | ||
4 | * Copyright (c) 2013 Tony Prisk <linux@prisktech.co.nz> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | */ | ||
15 | |||
16 | #include <linux/gpio.h> | ||
17 | |||
18 | /* VT8500 has no enable register in the extgpio bank. */ | ||
19 | #define NO_REG 0xFFFF | ||
20 | |||
21 | #define WMT_PINCTRL_BANK(__en, __dir, __dout, __din, __pen, __pcfg) \ | ||
22 | { \ | ||
23 | .reg_en = __en, \ | ||
24 | .reg_dir = __dir, \ | ||
25 | .reg_data_out = __dout, \ | ||
26 | .reg_data_in = __din, \ | ||
27 | .reg_pull_en = __pen, \ | ||
28 | .reg_pull_cfg = __pcfg, \ | ||
29 | } | ||
30 | |||
31 | /* Encode/decode the bank/bit pairs into a pin value */ | ||
32 | #define WMT_PIN(__bank, __offset) ((__bank << 5) | __offset) | ||
33 | #define WMT_BANK_FROM_PIN(__pin) (__pin >> 5) | ||
34 | #define WMT_BIT_FROM_PIN(__pin) (__pin & 0x1f) | ||
35 | |||
36 | #define WMT_GROUP(__name, __data) \ | ||
37 | { \ | ||
38 | .name = __name, \ | ||
39 | .pins = __data, \ | ||
40 | .npins = ARRAY_SIZE(__data), \ | ||
41 | } | ||
42 | |||
43 | struct wmt_pinctrl_bank_registers { | ||
44 | u32 reg_en; | ||
45 | u32 reg_dir; | ||
46 | u32 reg_data_out; | ||
47 | u32 reg_data_in; | ||
48 | |||
49 | u32 reg_pull_en; | ||
50 | u32 reg_pull_cfg; | ||
51 | }; | ||
52 | |||
53 | struct wmt_pinctrl_group { | ||
54 | const char *name; | ||
55 | const unsigned int *pins; | ||
56 | const unsigned npins; | ||
57 | }; | ||
58 | |||
59 | struct wmt_pinctrl_data { | ||
60 | struct device *dev; | ||
61 | struct pinctrl_dev *pctl_dev; | ||
62 | |||
63 | /* must be initialized before calling wmt_pinctrl_probe */ | ||
64 | void __iomem *base; | ||
65 | const struct wmt_pinctrl_bank_registers *banks; | ||
66 | const struct pinctrl_pin_desc *pins; | ||
67 | const char * const *groups; | ||
68 | |||
69 | u32 nbanks; | ||
70 | u32 npins; | ||
71 | u32 ngroups; | ||
72 | |||
73 | struct gpio_chip gpio_chip; | ||
74 | struct pinctrl_gpio_range gpio_range; | ||
75 | }; | ||
76 | |||
77 | int wmt_pinctrl_probe(struct platform_device *pdev, | ||
78 | struct wmt_pinctrl_data *data); | ||
79 | int wmt_pinctrl_remove(struct platform_device *pdev); | ||
diff --git a/drivers/platform/x86/chromeos_laptop.c b/drivers/platform/x86/chromeos_laptop.c index 93d66809355a..3e5b4497a1d0 100644 --- a/drivers/platform/x86/chromeos_laptop.c +++ b/drivers/platform/x86/chromeos_laptop.c | |||
@@ -23,6 +23,9 @@ | |||
23 | 23 | ||
24 | #include <linux/dmi.h> | 24 | #include <linux/dmi.h> |
25 | #include <linux/i2c.h> | 25 | #include <linux/i2c.h> |
26 | #include <linux/i2c/atmel_mxt_ts.h> | ||
27 | #include <linux/input.h> | ||
28 | #include <linux/interrupt.h> | ||
26 | #include <linux/module.h> | 29 | #include <linux/module.h> |
27 | 30 | ||
28 | #define ATMEL_TP_I2C_ADDR 0x4b | 31 | #define ATMEL_TP_I2C_ADDR 0x4b |
@@ -67,15 +70,49 @@ static struct i2c_board_info __initdata tsl2563_als_device = { | |||
67 | I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), | 70 | I2C_BOARD_INFO("tsl2563", TAOS_ALS_I2C_ADDR), |
68 | }; | 71 | }; |
69 | 72 | ||
73 | static struct mxt_platform_data atmel_224s_tp_platform_data = { | ||
74 | .x_line = 18, | ||
75 | .y_line = 12, | ||
76 | .x_size = 102*20, | ||
77 | .y_size = 68*20, | ||
78 | .blen = 0x80, /* Gain setting is in upper 4 bits */ | ||
79 | .threshold = 0x32, | ||
80 | .voltage = 0, /* 3.3V */ | ||
81 | .orient = MXT_VERTICAL_FLIP, | ||
82 | .irqflags = IRQF_TRIGGER_FALLING, | ||
83 | .is_tp = true, | ||
84 | .key_map = { KEY_RESERVED, | ||
85 | KEY_RESERVED, | ||
86 | KEY_RESERVED, | ||
87 | BTN_LEFT }, | ||
88 | .config = NULL, | ||
89 | .config_length = 0, | ||
90 | }; | ||
91 | |||
70 | static struct i2c_board_info __initdata atmel_224s_tp_device = { | 92 | static struct i2c_board_info __initdata atmel_224s_tp_device = { |
71 | I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), | 93 | I2C_BOARD_INFO("atmel_mxt_tp", ATMEL_TP_I2C_ADDR), |
72 | .platform_data = NULL, | 94 | .platform_data = &atmel_224s_tp_platform_data, |
73 | .flags = I2C_CLIENT_WAKE, | 95 | .flags = I2C_CLIENT_WAKE, |
74 | }; | 96 | }; |
75 | 97 | ||
98 | static struct mxt_platform_data atmel_1664s_platform_data = { | ||
99 | .x_line = 32, | ||
100 | .y_line = 50, | ||
101 | .x_size = 1700, | ||
102 | .y_size = 2560, | ||
103 | .blen = 0x89, /* Gain setting is in upper 4 bits */ | ||
104 | .threshold = 0x28, | ||
105 | .voltage = 0, /* 3.3V */ | ||
106 | .orient = MXT_ROTATED_90_COUNTER, | ||
107 | .irqflags = IRQF_TRIGGER_FALLING, | ||
108 | .is_tp = false, | ||
109 | .config = NULL, | ||
110 | .config_length = 0, | ||
111 | }; | ||
112 | |||
76 | static struct i2c_board_info __initdata atmel_1664s_device = { | 113 | static struct i2c_board_info __initdata atmel_1664s_device = { |
77 | I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), | 114 | I2C_BOARD_INFO("atmel_mxt_ts", ATMEL_TS_I2C_ADDR), |
78 | .platform_data = NULL, | 115 | .platform_data = &atmel_1664s_platform_data, |
79 | .flags = I2C_CLIENT_WAKE, | 116 | .flags = I2C_CLIENT_WAKE, |
80 | }; | 117 | }; |
81 | 118 | ||
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c index 8813fc03aa09..55cd459a3908 100644 --- a/drivers/pnp/pnpacpi/core.c +++ b/drivers/pnp/pnpacpi/core.c | |||
@@ -353,8 +353,14 @@ static int __init acpi_pnp_find_device(struct device *dev, acpi_handle * handle) | |||
353 | /* complete initialization of a PNPACPI device includes having | 353 | /* complete initialization of a PNPACPI device includes having |
354 | * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. | 354 | * pnpdev->dev.archdata.acpi_handle point to its ACPI sibling. |
355 | */ | 355 | */ |
356 | static bool acpi_pnp_bus_match(struct device *dev) | ||
357 | { | ||
358 | return dev->bus == &pnp_bus_type; | ||
359 | } | ||
360 | |||
356 | static struct acpi_bus_type __initdata acpi_pnp_bus = { | 361 | static struct acpi_bus_type __initdata acpi_pnp_bus = { |
357 | .bus = &pnp_bus_type, | 362 | .name = "PNP", |
363 | .match = acpi_pnp_bus_match, | ||
358 | .find_device = acpi_pnp_find_device, | 364 | .find_device = acpi_pnp_find_device, |
359 | }; | 365 | }; |
360 | 366 | ||
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index da9782bd27d0..e3661c20cf38 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -2830,7 +2830,7 @@ EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); | |||
2830 | * regulator_allow_bypass - allow the regulator to go into bypass mode | 2830 | * regulator_allow_bypass - allow the regulator to go into bypass mode |
2831 | * | 2831 | * |
2832 | * @regulator: Regulator to configure | 2832 | * @regulator: Regulator to configure |
2833 | * @allow: enable or disable bypass mode | 2833 | * @enable: enable or disable bypass mode |
2834 | * | 2834 | * |
2835 | * Allow the regulator to go into bypass mode if all other consumers | 2835 | * Allow the regulator to go into bypass mode if all other consumers |
2836 | * for the regulator also enable bypass mode and the machine | 2836 | * for the regulator also enable bypass mode and the machine |
@@ -3057,9 +3057,13 @@ int regulator_bulk_enable(int num_consumers, | |||
3057 | return 0; | 3057 | return 0; |
3058 | 3058 | ||
3059 | err: | 3059 | err: |
3060 | pr_err("Failed to enable %s: %d\n", consumers[i].supply, ret); | 3060 | for (i = 0; i < num_consumers; i++) { |
3061 | while (--i >= 0) | 3061 | if (consumers[i].ret < 0) |
3062 | regulator_disable(consumers[i].consumer); | 3062 | pr_err("Failed to enable %s: %d\n", consumers[i].supply, |
3063 | consumers[i].ret); | ||
3064 | else | ||
3065 | regulator_disable(consumers[i].consumer); | ||
3066 | } | ||
3063 | 3067 | ||
3064 | return ret; | 3068 | return ret; |
3065 | } | 3069 | } |
diff --git a/drivers/regulator/db8500-prcmu.c b/drivers/regulator/db8500-prcmu.c index 219d162b651e..a53c11a529d5 100644 --- a/drivers/regulator/db8500-prcmu.c +++ b/drivers/regulator/db8500-prcmu.c | |||
@@ -528,7 +528,7 @@ static int db8500_regulator_probe(struct platform_device *pdev) | |||
528 | return 0; | 528 | return 0; |
529 | } | 529 | } |
530 | 530 | ||
531 | static int __exit db8500_regulator_remove(struct platform_device *pdev) | 531 | static int db8500_regulator_remove(struct platform_device *pdev) |
532 | { | 532 | { |
533 | int i; | 533 | int i; |
534 | 534 | ||
@@ -553,7 +553,7 @@ static struct platform_driver db8500_regulator_driver = { | |||
553 | .owner = THIS_MODULE, | 553 | .owner = THIS_MODULE, |
554 | }, | 554 | }, |
555 | .probe = db8500_regulator_probe, | 555 | .probe = db8500_regulator_probe, |
556 | .remove = __exit_p(db8500_regulator_remove), | 556 | .remove = db8500_regulator_remove, |
557 | }; | 557 | }; |
558 | 558 | ||
559 | static int __init db8500_regulator_init(void) | 559 | static int __init db8500_regulator_init(void) |
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index cde13bb5a8fb..39cf14606784 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c | |||
@@ -4,6 +4,7 @@ | |||
4 | * Copyright 2011-2012 Texas Instruments Inc. | 4 | * Copyright 2011-2012 Texas Instruments Inc. |
5 | * | 5 | * |
6 | * Author: Graeme Gregory <gg@slimlogic.co.uk> | 6 | * Author: Graeme Gregory <gg@slimlogic.co.uk> |
7 | * Author: Ian Lartey <ian@slimlogic.co.uk> | ||
7 | * | 8 | * |
8 | * This program is free software; you can redistribute it and/or modify it | 9 | * This program is free software; you can redistribute it and/or modify it |
9 | * under the terms of the GNU General Public License as published by the | 10 | * under the terms of the GNU General Public License as published by the |
@@ -156,7 +157,7 @@ static const struct regs_info palmas_regs_info[] = { | |||
156 | * | 157 | * |
157 | * So they are basically (maxV-minV)/stepV | 158 | * So they are basically (maxV-minV)/stepV |
158 | */ | 159 | */ |
159 | #define PALMAS_SMPS_NUM_VOLTAGES 116 | 160 | #define PALMAS_SMPS_NUM_VOLTAGES 117 |
160 | #define PALMAS_SMPS10_NUM_VOLTAGES 2 | 161 | #define PALMAS_SMPS10_NUM_VOLTAGES 2 |
161 | #define PALMAS_LDO_NUM_VOLTAGES 50 | 162 | #define PALMAS_LDO_NUM_VOLTAGES 50 |
162 | 163 | ||
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c index 74508cc62d67..f705d25b437c 100644 --- a/drivers/regulator/twl-regulator.c +++ b/drivers/regulator/twl-regulator.c | |||
@@ -471,24 +471,23 @@ twl4030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) | |||
471 | selector); | 471 | selector); |
472 | } | 472 | } |
473 | 473 | ||
474 | static int twl4030ldo_get_voltage(struct regulator_dev *rdev) | 474 | static int twl4030ldo_get_voltage_sel(struct regulator_dev *rdev) |
475 | { | 475 | { |
476 | struct twlreg_info *info = rdev_get_drvdata(rdev); | 476 | struct twlreg_info *info = rdev_get_drvdata(rdev); |
477 | int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, | 477 | int vsel = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE); |
478 | VREG_VOLTAGE); | ||
479 | 478 | ||
480 | if (vsel < 0) | 479 | if (vsel < 0) |
481 | return vsel; | 480 | return vsel; |
482 | 481 | ||
483 | vsel &= info->table_len - 1; | 482 | vsel &= info->table_len - 1; |
484 | return LDO_MV(info->table[vsel]) * 1000; | 483 | return vsel; |
485 | } | 484 | } |
486 | 485 | ||
487 | static struct regulator_ops twl4030ldo_ops = { | 486 | static struct regulator_ops twl4030ldo_ops = { |
488 | .list_voltage = twl4030ldo_list_voltage, | 487 | .list_voltage = twl4030ldo_list_voltage, |
489 | 488 | ||
490 | .set_voltage_sel = twl4030ldo_set_voltage_sel, | 489 | .set_voltage_sel = twl4030ldo_set_voltage_sel, |
491 | .get_voltage = twl4030ldo_get_voltage, | 490 | .get_voltage_sel = twl4030ldo_get_voltage_sel, |
492 | 491 | ||
493 | .enable = twl4030reg_enable, | 492 | .enable = twl4030reg_enable, |
494 | .disable = twl4030reg_disable, | 493 | .disable = twl4030reg_disable, |
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c index 434ebc3a99dc..0a9f27e094ea 100644 --- a/drivers/rtc/rtc-at91rm9200.c +++ b/drivers/rtc/rtc-at91rm9200.c | |||
@@ -44,6 +44,7 @@ static DECLARE_COMPLETION(at91_rtc_updated); | |||
44 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; | 44 | static unsigned int at91_alarm_year = AT91_RTC_EPOCH; |
45 | static void __iomem *at91_rtc_regs; | 45 | static void __iomem *at91_rtc_regs; |
46 | static int irq; | 46 | static int irq; |
47 | static u32 at91_rtc_imr; | ||
47 | 48 | ||
48 | /* | 49 | /* |
49 | * Decode time/date into rtc_time structure | 50 | * Decode time/date into rtc_time structure |
@@ -108,9 +109,11 @@ static int at91_rtc_settime(struct device *dev, struct rtc_time *tm) | |||
108 | cr = at91_rtc_read(AT91_RTC_CR); | 109 | cr = at91_rtc_read(AT91_RTC_CR); |
109 | at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); | 110 | at91_rtc_write(AT91_RTC_CR, cr | AT91_RTC_UPDCAL | AT91_RTC_UPDTIM); |
110 | 111 | ||
112 | at91_rtc_imr |= AT91_RTC_ACKUPD; | ||
111 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD); | 113 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ACKUPD); |
112 | wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ | 114 | wait_for_completion(&at91_rtc_updated); /* wait for ACKUPD interrupt */ |
113 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); | 115 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD); |
116 | at91_rtc_imr &= ~AT91_RTC_ACKUPD; | ||
114 | 117 | ||
115 | at91_rtc_write(AT91_RTC_TIMR, | 118 | at91_rtc_write(AT91_RTC_TIMR, |
116 | bin2bcd(tm->tm_sec) << 0 | 119 | bin2bcd(tm->tm_sec) << 0 |
@@ -142,7 +145,7 @@ static int at91_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
142 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); | 145 | tm->tm_yday = rtc_year_days(tm->tm_mday, tm->tm_mon, tm->tm_year); |
143 | tm->tm_year = at91_alarm_year - 1900; | 146 | tm->tm_year = at91_alarm_year - 1900; |
144 | 147 | ||
145 | alrm->enabled = (at91_rtc_read(AT91_RTC_IMR) & AT91_RTC_ALARM) | 148 | alrm->enabled = (at91_rtc_imr & AT91_RTC_ALARM) |
146 | ? 1 : 0; | 149 | ? 1 : 0; |
147 | 150 | ||
148 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, | 151 | dev_dbg(dev, "%s(): %4d-%02d-%02d %02d:%02d:%02d\n", __func__, |
@@ -168,6 +171,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
168 | tm.tm_sec = alrm->time.tm_sec; | 171 | tm.tm_sec = alrm->time.tm_sec; |
169 | 172 | ||
170 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 173 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
174 | at91_rtc_imr &= ~AT91_RTC_ALARM; | ||
171 | at91_rtc_write(AT91_RTC_TIMALR, | 175 | at91_rtc_write(AT91_RTC_TIMALR, |
172 | bin2bcd(tm.tm_sec) << 0 | 176 | bin2bcd(tm.tm_sec) << 0 |
173 | | bin2bcd(tm.tm_min) << 8 | 177 | | bin2bcd(tm.tm_min) << 8 |
@@ -180,6 +184,7 @@ static int at91_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm) | |||
180 | 184 | ||
181 | if (alrm->enabled) { | 185 | if (alrm->enabled) { |
182 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | 186 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); |
187 | at91_rtc_imr |= AT91_RTC_ALARM; | ||
183 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); | 188 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); |
184 | } | 189 | } |
185 | 190 | ||
@@ -196,9 +201,12 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
196 | 201 | ||
197 | if (enabled) { | 202 | if (enabled) { |
198 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); | 203 | at91_rtc_write(AT91_RTC_SCCR, AT91_RTC_ALARM); |
204 | at91_rtc_imr |= AT91_RTC_ALARM; | ||
199 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); | 205 | at91_rtc_write(AT91_RTC_IER, AT91_RTC_ALARM); |
200 | } else | 206 | } else { |
201 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); | 207 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ALARM); |
208 | at91_rtc_imr &= ~AT91_RTC_ALARM; | ||
209 | } | ||
202 | 210 | ||
203 | return 0; | 211 | return 0; |
204 | } | 212 | } |
@@ -207,12 +215,10 @@ static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled) | |||
207 | */ | 215 | */ |
208 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) | 216 | static int at91_rtc_proc(struct device *dev, struct seq_file *seq) |
209 | { | 217 | { |
210 | unsigned long imr = at91_rtc_read(AT91_RTC_IMR); | ||
211 | |||
212 | seq_printf(seq, "update_IRQ\t: %s\n", | 218 | seq_printf(seq, "update_IRQ\t: %s\n", |
213 | (imr & AT91_RTC_ACKUPD) ? "yes" : "no"); | 219 | (at91_rtc_imr & AT91_RTC_ACKUPD) ? "yes" : "no"); |
214 | seq_printf(seq, "periodic_IRQ\t: %s\n", | 220 | seq_printf(seq, "periodic_IRQ\t: %s\n", |
215 | (imr & AT91_RTC_SECEV) ? "yes" : "no"); | 221 | (at91_rtc_imr & AT91_RTC_SECEV) ? "yes" : "no"); |
216 | 222 | ||
217 | return 0; | 223 | return 0; |
218 | } | 224 | } |
@@ -227,7 +233,7 @@ static irqreturn_t at91_rtc_interrupt(int irq, void *dev_id) | |||
227 | unsigned int rtsr; | 233 | unsigned int rtsr; |
228 | unsigned long events = 0; | 234 | unsigned long events = 0; |
229 | 235 | ||
230 | rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_read(AT91_RTC_IMR); | 236 | rtsr = at91_rtc_read(AT91_RTC_SR) & at91_rtc_imr; |
231 | if (rtsr) { /* this interrupt is shared! Is it ours? */ | 237 | if (rtsr) { /* this interrupt is shared! Is it ours? */ |
232 | if (rtsr & AT91_RTC_ALARM) | 238 | if (rtsr & AT91_RTC_ALARM) |
233 | events |= (RTC_AF | RTC_IRQF); | 239 | events |= (RTC_AF | RTC_IRQF); |
@@ -291,6 +297,7 @@ static int __init at91_rtc_probe(struct platform_device *pdev) | |||
291 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | | 297 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | |
292 | AT91_RTC_SECEV | AT91_RTC_TIMEV | | 298 | AT91_RTC_SECEV | AT91_RTC_TIMEV | |
293 | AT91_RTC_CALEV); | 299 | AT91_RTC_CALEV); |
300 | at91_rtc_imr = 0; | ||
294 | 301 | ||
295 | ret = request_irq(irq, at91_rtc_interrupt, | 302 | ret = request_irq(irq, at91_rtc_interrupt, |
296 | IRQF_SHARED, | 303 | IRQF_SHARED, |
@@ -329,6 +336,7 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
329 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | | 336 | at91_rtc_write(AT91_RTC_IDR, AT91_RTC_ACKUPD | AT91_RTC_ALARM | |
330 | AT91_RTC_SECEV | AT91_RTC_TIMEV | | 337 | AT91_RTC_SECEV | AT91_RTC_TIMEV | |
331 | AT91_RTC_CALEV); | 338 | AT91_RTC_CALEV); |
339 | at91_rtc_imr = 0; | ||
332 | free_irq(irq, pdev); | 340 | free_irq(irq, pdev); |
333 | 341 | ||
334 | rtc_device_unregister(rtc); | 342 | rtc_device_unregister(rtc); |
@@ -341,31 +349,35 @@ static int __exit at91_rtc_remove(struct platform_device *pdev) | |||
341 | 349 | ||
342 | /* AT91RM9200 RTC Power management control */ | 350 | /* AT91RM9200 RTC Power management control */ |
343 | 351 | ||
344 | static u32 at91_rtc_imr; | 352 | static u32 at91_rtc_bkpimr; |
353 | |||
345 | 354 | ||
346 | static int at91_rtc_suspend(struct device *dev) | 355 | static int at91_rtc_suspend(struct device *dev) |
347 | { | 356 | { |
348 | /* this IRQ is shared with DBGU and other hardware which isn't | 357 | /* this IRQ is shared with DBGU and other hardware which isn't |
349 | * necessarily doing PM like we are... | 358 | * necessarily doing PM like we are... |
350 | */ | 359 | */ |
351 | at91_rtc_imr = at91_rtc_read(AT91_RTC_IMR) | 360 | at91_rtc_bkpimr = at91_rtc_imr & (AT91_RTC_ALARM|AT91_RTC_SECEV); |
352 | & (AT91_RTC_ALARM|AT91_RTC_SECEV); | 361 | if (at91_rtc_bkpimr) { |
353 | if (at91_rtc_imr) { | 362 | if (device_may_wakeup(dev)) { |
354 | if (device_may_wakeup(dev)) | ||
355 | enable_irq_wake(irq); | 363 | enable_irq_wake(irq); |
356 | else | 364 | } else { |
357 | at91_rtc_write(AT91_RTC_IDR, at91_rtc_imr); | 365 | at91_rtc_write(AT91_RTC_IDR, at91_rtc_bkpimr); |
358 | } | 366 | at91_rtc_imr &= ~at91_rtc_bkpimr; |
367 | } | ||
368 | } | ||
359 | return 0; | 369 | return 0; |
360 | } | 370 | } |
361 | 371 | ||
362 | static int at91_rtc_resume(struct device *dev) | 372 | static int at91_rtc_resume(struct device *dev) |
363 | { | 373 | { |
364 | if (at91_rtc_imr) { | 374 | if (at91_rtc_bkpimr) { |
365 | if (device_may_wakeup(dev)) | 375 | if (device_may_wakeup(dev)) { |
366 | disable_irq_wake(irq); | 376 | disable_irq_wake(irq); |
367 | else | 377 | } else { |
368 | at91_rtc_write(AT91_RTC_IER, at91_rtc_imr); | 378 | at91_rtc_imr |= at91_rtc_bkpimr; |
379 | at91_rtc_write(AT91_RTC_IER, at91_rtc_bkpimr); | ||
380 | } | ||
369 | } | 381 | } |
370 | return 0; | 382 | return 0; |
371 | } | 383 | } |
diff --git a/drivers/rtc/rtc-at91rm9200.h b/drivers/rtc/rtc-at91rm9200.h index da1945e5f714..5f940b6844cb 100644 --- a/drivers/rtc/rtc-at91rm9200.h +++ b/drivers/rtc/rtc-at91rm9200.h | |||
@@ -64,7 +64,6 @@ | |||
64 | #define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */ | 64 | #define AT91_RTC_SCCR 0x1c /* Status Clear Command Register */ |
65 | #define AT91_RTC_IER 0x20 /* Interrupt Enable Register */ | 65 | #define AT91_RTC_IER 0x20 /* Interrupt Enable Register */ |
66 | #define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ | 66 | #define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ |
67 | #define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */ | ||
68 | 67 | ||
69 | #define AT91_RTC_VER 0x2c /* Valid Entry Register */ | 68 | #define AT91_RTC_VER 0x2c /* Valid Entry Register */ |
70 | #define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */ | 69 | #define AT91_RTC_NVTIM (1 << 0) /* Non valid Time */ |
diff --git a/drivers/rtc/rtc-da9052.c b/drivers/rtc/rtc-da9052.c index 0dde688ca09b..969abbad7fe3 100644 --- a/drivers/rtc/rtc-da9052.c +++ b/drivers/rtc/rtc-da9052.c | |||
@@ -239,11 +239,9 @@ static int da9052_rtc_probe(struct platform_device *pdev) | |||
239 | 239 | ||
240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); | 240 | rtc->da9052 = dev_get_drvdata(pdev->dev.parent); |
241 | platform_set_drvdata(pdev, rtc); | 241 | platform_set_drvdata(pdev, rtc); |
242 | rtc->irq = platform_get_irq_byname(pdev, "ALM"); | 242 | rtc->irq = DA9052_IRQ_ALARM; |
243 | ret = devm_request_threaded_irq(&pdev->dev, rtc->irq, NULL, | 243 | ret = da9052_request_irq(rtc->da9052, rtc->irq, "ALM", |
244 | da9052_rtc_irq, | 244 | da9052_rtc_irq, rtc); |
245 | IRQF_TRIGGER_LOW | IRQF_ONESHOT, | ||
246 | "ALM", rtc); | ||
247 | if (ret != 0) { | 245 | if (ret != 0) { |
248 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); | 246 | rtc_err(rtc->da9052, "irq registration failed: %d\n", ret); |
249 | return ret; | 247 | return ret; |
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c index 57233c885998..8f87fec27ce7 100644 --- a/drivers/rtc/rtc-mv.c +++ b/drivers/rtc/rtc-mv.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/platform_device.h> | 14 | #include <linux/platform_device.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/clk.h> | ||
17 | #include <linux/gfp.h> | 18 | #include <linux/gfp.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | 20 | ||
@@ -41,6 +42,7 @@ struct rtc_plat_data { | |||
41 | struct rtc_device *rtc; | 42 | struct rtc_device *rtc; |
42 | void __iomem *ioaddr; | 43 | void __iomem *ioaddr; |
43 | int irq; | 44 | int irq; |
45 | struct clk *clk; | ||
44 | }; | 46 | }; |
45 | 47 | ||
46 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) | 48 | static int mv_rtc_set_time(struct device *dev, struct rtc_time *tm) |
@@ -221,6 +223,7 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
221 | struct rtc_plat_data *pdata; | 223 | struct rtc_plat_data *pdata; |
222 | resource_size_t size; | 224 | resource_size_t size; |
223 | u32 rtc_time; | 225 | u32 rtc_time; |
226 | int ret = 0; | ||
224 | 227 | ||
225 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 228 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
226 | if (!res) | 229 | if (!res) |
@@ -239,11 +242,17 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
239 | if (!pdata->ioaddr) | 242 | if (!pdata->ioaddr) |
240 | return -ENOMEM; | 243 | return -ENOMEM; |
241 | 244 | ||
245 | pdata->clk = devm_clk_get(&pdev->dev, NULL); | ||
246 | /* Not all SoCs require a clock.*/ | ||
247 | if (!IS_ERR(pdata->clk)) | ||
248 | clk_prepare_enable(pdata->clk); | ||
249 | |||
242 | /* make sure the 24 hours mode is enabled */ | 250 | /* make sure the 24 hours mode is enabled */ |
243 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); | 251 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); |
244 | if (rtc_time & RTC_HOURS_12H_MODE) { | 252 | if (rtc_time & RTC_HOURS_12H_MODE) { |
245 | dev_err(&pdev->dev, "24 Hours mode not supported.\n"); | 253 | dev_err(&pdev->dev, "24 Hours mode not supported.\n"); |
246 | return -EINVAL; | 254 | ret = -EINVAL; |
255 | goto out; | ||
247 | } | 256 | } |
248 | 257 | ||
249 | /* make sure it is actually functional */ | 258 | /* make sure it is actually functional */ |
@@ -252,7 +261,8 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
252 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); | 261 | rtc_time = readl(pdata->ioaddr + RTC_TIME_REG_OFFS); |
253 | if (rtc_time == 0x01000000) { | 262 | if (rtc_time == 0x01000000) { |
254 | dev_err(&pdev->dev, "internal RTC not ticking\n"); | 263 | dev_err(&pdev->dev, "internal RTC not ticking\n"); |
255 | return -ENODEV; | 264 | ret = -ENODEV; |
265 | goto out; | ||
256 | } | 266 | } |
257 | } | 267 | } |
258 | 268 | ||
@@ -268,8 +278,10 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
268 | } else | 278 | } else |
269 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, | 279 | pdata->rtc = rtc_device_register(pdev->name, &pdev->dev, |
270 | &mv_rtc_ops, THIS_MODULE); | 280 | &mv_rtc_ops, THIS_MODULE); |
271 | if (IS_ERR(pdata->rtc)) | 281 | if (IS_ERR(pdata->rtc)) { |
272 | return PTR_ERR(pdata->rtc); | 282 | ret = PTR_ERR(pdata->rtc); |
283 | goto out; | ||
284 | } | ||
273 | 285 | ||
274 | if (pdata->irq >= 0) { | 286 | if (pdata->irq >= 0) { |
275 | writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); | 287 | writel(0, pdata->ioaddr + RTC_ALARM_INTERRUPT_MASK_REG_OFFS); |
@@ -282,6 +294,11 @@ static int mv_rtc_probe(struct platform_device *pdev) | |||
282 | } | 294 | } |
283 | 295 | ||
284 | return 0; | 296 | return 0; |
297 | out: | ||
298 | if (!IS_ERR(pdata->clk)) | ||
299 | clk_disable_unprepare(pdata->clk); | ||
300 | |||
301 | return ret; | ||
285 | } | 302 | } |
286 | 303 | ||
287 | static int __exit mv_rtc_remove(struct platform_device *pdev) | 304 | static int __exit mv_rtc_remove(struct platform_device *pdev) |
@@ -292,6 +309,9 @@ static int __exit mv_rtc_remove(struct platform_device *pdev) | |||
292 | device_init_wakeup(&pdev->dev, 0); | 309 | device_init_wakeup(&pdev->dev, 0); |
293 | 310 | ||
294 | rtc_device_unregister(pdata->rtc); | 311 | rtc_device_unregister(pdata->rtc); |
312 | if (!IS_ERR(pdata->clk)) | ||
313 | clk_disable_unprepare(pdata->clk); | ||
314 | |||
295 | return 0; | 315 | return 0; |
296 | } | 316 | } |
297 | 317 | ||
diff --git a/drivers/s390/block/scm_blk.c b/drivers/s390/block/scm_blk.c index 9978ad4433cb..5ac9c935c151 100644 --- a/drivers/s390/block/scm_blk.c +++ b/drivers/s390/block/scm_blk.c | |||
@@ -135,6 +135,11 @@ static const struct block_device_operations scm_blk_devops = { | |||
135 | .release = scm_release, | 135 | .release = scm_release, |
136 | }; | 136 | }; |
137 | 137 | ||
138 | static bool scm_permit_request(struct scm_blk_dev *bdev, struct request *req) | ||
139 | { | ||
140 | return rq_data_dir(req) != WRITE || bdev->state != SCM_WR_PROHIBIT; | ||
141 | } | ||
142 | |||
138 | static void scm_request_prepare(struct scm_request *scmrq) | 143 | static void scm_request_prepare(struct scm_request *scmrq) |
139 | { | 144 | { |
140 | struct scm_blk_dev *bdev = scmrq->bdev; | 145 | struct scm_blk_dev *bdev = scmrq->bdev; |
@@ -195,14 +200,18 @@ void scm_request_requeue(struct scm_request *scmrq) | |||
195 | 200 | ||
196 | scm_release_cluster(scmrq); | 201 | scm_release_cluster(scmrq); |
197 | blk_requeue_request(bdev->rq, scmrq->request); | 202 | blk_requeue_request(bdev->rq, scmrq->request); |
203 | atomic_dec(&bdev->queued_reqs); | ||
198 | scm_request_done(scmrq); | 204 | scm_request_done(scmrq); |
199 | scm_ensure_queue_restart(bdev); | 205 | scm_ensure_queue_restart(bdev); |
200 | } | 206 | } |
201 | 207 | ||
202 | void scm_request_finish(struct scm_request *scmrq) | 208 | void scm_request_finish(struct scm_request *scmrq) |
203 | { | 209 | { |
210 | struct scm_blk_dev *bdev = scmrq->bdev; | ||
211 | |||
204 | scm_release_cluster(scmrq); | 212 | scm_release_cluster(scmrq); |
205 | blk_end_request_all(scmrq->request, scmrq->error); | 213 | blk_end_request_all(scmrq->request, scmrq->error); |
214 | atomic_dec(&bdev->queued_reqs); | ||
206 | scm_request_done(scmrq); | 215 | scm_request_done(scmrq); |
207 | } | 216 | } |
208 | 217 | ||
@@ -218,6 +227,10 @@ static void scm_blk_request(struct request_queue *rq) | |||
218 | if (req->cmd_type != REQ_TYPE_FS) | 227 | if (req->cmd_type != REQ_TYPE_FS) |
219 | continue; | 228 | continue; |
220 | 229 | ||
230 | if (!scm_permit_request(bdev, req)) { | ||
231 | scm_ensure_queue_restart(bdev); | ||
232 | return; | ||
233 | } | ||
221 | scmrq = scm_request_fetch(); | 234 | scmrq = scm_request_fetch(); |
222 | if (!scmrq) { | 235 | if (!scmrq) { |
223 | SCM_LOG(5, "no request"); | 236 | SCM_LOG(5, "no request"); |
@@ -231,11 +244,13 @@ static void scm_blk_request(struct request_queue *rq) | |||
231 | return; | 244 | return; |
232 | } | 245 | } |
233 | if (scm_need_cluster_request(scmrq)) { | 246 | if (scm_need_cluster_request(scmrq)) { |
247 | atomic_inc(&bdev->queued_reqs); | ||
234 | blk_start_request(req); | 248 | blk_start_request(req); |
235 | scm_initiate_cluster_request(scmrq); | 249 | scm_initiate_cluster_request(scmrq); |
236 | return; | 250 | return; |
237 | } | 251 | } |
238 | scm_request_prepare(scmrq); | 252 | scm_request_prepare(scmrq); |
253 | atomic_inc(&bdev->queued_reqs); | ||
239 | blk_start_request(req); | 254 | blk_start_request(req); |
240 | 255 | ||
241 | ret = scm_start_aob(scmrq->aob); | 256 | ret = scm_start_aob(scmrq->aob); |
@@ -244,7 +259,6 @@ static void scm_blk_request(struct request_queue *rq) | |||
244 | scm_request_requeue(scmrq); | 259 | scm_request_requeue(scmrq); |
245 | return; | 260 | return; |
246 | } | 261 | } |
247 | atomic_inc(&bdev->queued_reqs); | ||
248 | } | 262 | } |
249 | } | 263 | } |
250 | 264 | ||
@@ -280,6 +294,38 @@ void scm_blk_irq(struct scm_device *scmdev, void *data, int error) | |||
280 | tasklet_hi_schedule(&bdev->tasklet); | 294 | tasklet_hi_schedule(&bdev->tasklet); |
281 | } | 295 | } |
282 | 296 | ||
297 | static void scm_blk_handle_error(struct scm_request *scmrq) | ||
298 | { | ||
299 | struct scm_blk_dev *bdev = scmrq->bdev; | ||
300 | unsigned long flags; | ||
301 | |||
302 | if (scmrq->error != -EIO) | ||
303 | goto restart; | ||
304 | |||
305 | /* For -EIO the response block is valid. */ | ||
306 | switch (scmrq->aob->response.eqc) { | ||
307 | case EQC_WR_PROHIBIT: | ||
308 | spin_lock_irqsave(&bdev->lock, flags); | ||
309 | if (bdev->state != SCM_WR_PROHIBIT) | ||
310 | pr_info("%lu: Write access to the SCM increment is suspended\n", | ||
311 | (unsigned long) bdev->scmdev->address); | ||
312 | bdev->state = SCM_WR_PROHIBIT; | ||
313 | spin_unlock_irqrestore(&bdev->lock, flags); | ||
314 | goto requeue; | ||
315 | default: | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | restart: | ||
320 | if (!scm_start_aob(scmrq->aob)) | ||
321 | return; | ||
322 | |||
323 | requeue: | ||
324 | spin_lock_irqsave(&bdev->rq_lock, flags); | ||
325 | scm_request_requeue(scmrq); | ||
326 | spin_unlock_irqrestore(&bdev->rq_lock, flags); | ||
327 | } | ||
328 | |||
283 | static void scm_blk_tasklet(struct scm_blk_dev *bdev) | 329 | static void scm_blk_tasklet(struct scm_blk_dev *bdev) |
284 | { | 330 | { |
285 | struct scm_request *scmrq; | 331 | struct scm_request *scmrq; |
@@ -293,11 +339,8 @@ static void scm_blk_tasklet(struct scm_blk_dev *bdev) | |||
293 | spin_unlock_irqrestore(&bdev->lock, flags); | 339 | spin_unlock_irqrestore(&bdev->lock, flags); |
294 | 340 | ||
295 | if (scmrq->error && scmrq->retries-- > 0) { | 341 | if (scmrq->error && scmrq->retries-- > 0) { |
296 | if (scm_start_aob(scmrq->aob)) { | 342 | scm_blk_handle_error(scmrq); |
297 | spin_lock_irqsave(&bdev->rq_lock, flags); | 343 | |
298 | scm_request_requeue(scmrq); | ||
299 | spin_unlock_irqrestore(&bdev->rq_lock, flags); | ||
300 | } | ||
301 | /* Request restarted or requeued, handle next. */ | 344 | /* Request restarted or requeued, handle next. */ |
302 | spin_lock_irqsave(&bdev->lock, flags); | 345 | spin_lock_irqsave(&bdev->lock, flags); |
303 | continue; | 346 | continue; |
@@ -310,7 +353,6 @@ static void scm_blk_tasklet(struct scm_blk_dev *bdev) | |||
310 | } | 353 | } |
311 | 354 | ||
312 | scm_request_finish(scmrq); | 355 | scm_request_finish(scmrq); |
313 | atomic_dec(&bdev->queued_reqs); | ||
314 | spin_lock_irqsave(&bdev->lock, flags); | 356 | spin_lock_irqsave(&bdev->lock, flags); |
315 | } | 357 | } |
316 | spin_unlock_irqrestore(&bdev->lock, flags); | 358 | spin_unlock_irqrestore(&bdev->lock, flags); |
@@ -332,6 +374,7 @@ int scm_blk_dev_setup(struct scm_blk_dev *bdev, struct scm_device *scmdev) | |||
332 | } | 374 | } |
333 | 375 | ||
334 | bdev->scmdev = scmdev; | 376 | bdev->scmdev = scmdev; |
377 | bdev->state = SCM_OPER; | ||
335 | spin_lock_init(&bdev->rq_lock); | 378 | spin_lock_init(&bdev->rq_lock); |
336 | spin_lock_init(&bdev->lock); | 379 | spin_lock_init(&bdev->lock); |
337 | INIT_LIST_HEAD(&bdev->finished_requests); | 380 | INIT_LIST_HEAD(&bdev->finished_requests); |
@@ -396,6 +439,18 @@ void scm_blk_dev_cleanup(struct scm_blk_dev *bdev) | |||
396 | put_disk(bdev->gendisk); | 439 | put_disk(bdev->gendisk); |
397 | } | 440 | } |
398 | 441 | ||
442 | void scm_blk_set_available(struct scm_blk_dev *bdev) | ||
443 | { | ||
444 | unsigned long flags; | ||
445 | |||
446 | spin_lock_irqsave(&bdev->lock, flags); | ||
447 | if (bdev->state == SCM_WR_PROHIBIT) | ||
448 | pr_info("%lu: Write access to the SCM increment is restored\n", | ||
449 | (unsigned long) bdev->scmdev->address); | ||
450 | bdev->state = SCM_OPER; | ||
451 | spin_unlock_irqrestore(&bdev->lock, flags); | ||
452 | } | ||
453 | |||
399 | static int __init scm_blk_init(void) | 454 | static int __init scm_blk_init(void) |
400 | { | 455 | { |
401 | int ret = -EINVAL; | 456 | int ret = -EINVAL; |
diff --git a/drivers/s390/block/scm_blk.h b/drivers/s390/block/scm_blk.h index 3c1ccf494647..8b387b32fd62 100644 --- a/drivers/s390/block/scm_blk.h +++ b/drivers/s390/block/scm_blk.h | |||
@@ -21,6 +21,7 @@ struct scm_blk_dev { | |||
21 | spinlock_t rq_lock; /* guard the request queue */ | 21 | spinlock_t rq_lock; /* guard the request queue */ |
22 | spinlock_t lock; /* guard the rest of the blockdev */ | 22 | spinlock_t lock; /* guard the rest of the blockdev */ |
23 | atomic_t queued_reqs; | 23 | atomic_t queued_reqs; |
24 | enum {SCM_OPER, SCM_WR_PROHIBIT} state; | ||
24 | struct list_head finished_requests; | 25 | struct list_head finished_requests; |
25 | #ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE | 26 | #ifdef CONFIG_SCM_BLOCK_CLUSTER_WRITE |
26 | struct list_head cluster_list; | 27 | struct list_head cluster_list; |
@@ -48,6 +49,7 @@ struct scm_request { | |||
48 | 49 | ||
49 | int scm_blk_dev_setup(struct scm_blk_dev *, struct scm_device *); | 50 | int scm_blk_dev_setup(struct scm_blk_dev *, struct scm_device *); |
50 | void scm_blk_dev_cleanup(struct scm_blk_dev *); | 51 | void scm_blk_dev_cleanup(struct scm_blk_dev *); |
52 | void scm_blk_set_available(struct scm_blk_dev *); | ||
51 | void scm_blk_irq(struct scm_device *, void *, int); | 53 | void scm_blk_irq(struct scm_device *, void *, int); |
52 | 54 | ||
53 | void scm_request_finish(struct scm_request *); | 55 | void scm_request_finish(struct scm_request *); |
diff --git a/drivers/s390/block/scm_drv.c b/drivers/s390/block/scm_drv.c index 9fa0a908607b..5f6180d6ff08 100644 --- a/drivers/s390/block/scm_drv.c +++ b/drivers/s390/block/scm_drv.c | |||
@@ -13,12 +13,23 @@ | |||
13 | #include <asm/eadm.h> | 13 | #include <asm/eadm.h> |
14 | #include "scm_blk.h" | 14 | #include "scm_blk.h" |
15 | 15 | ||
16 | static void notify(struct scm_device *scmdev) | 16 | static void scm_notify(struct scm_device *scmdev, enum scm_event event) |
17 | { | 17 | { |
18 | pr_info("%lu: The capabilities of the SCM increment changed\n", | 18 | struct scm_blk_dev *bdev = dev_get_drvdata(&scmdev->dev); |
19 | (unsigned long) scmdev->address); | 19 | |
20 | SCM_LOG(2, "State changed"); | 20 | switch (event) { |
21 | SCM_LOG_STATE(2, scmdev); | 21 | case SCM_CHANGE: |
22 | pr_info("%lu: The capabilities of the SCM increment changed\n", | ||
23 | (unsigned long) scmdev->address); | ||
24 | SCM_LOG(2, "State changed"); | ||
25 | SCM_LOG_STATE(2, scmdev); | ||
26 | break; | ||
27 | case SCM_AVAIL: | ||
28 | SCM_LOG(2, "Increment available"); | ||
29 | SCM_LOG_STATE(2, scmdev); | ||
30 | scm_blk_set_available(bdev); | ||
31 | break; | ||
32 | } | ||
22 | } | 33 | } |
23 | 34 | ||
24 | static int scm_probe(struct scm_device *scmdev) | 35 | static int scm_probe(struct scm_device *scmdev) |
@@ -64,7 +75,7 @@ static struct scm_driver scm_drv = { | |||
64 | .name = "scm_block", | 75 | .name = "scm_block", |
65 | .owner = THIS_MODULE, | 76 | .owner = THIS_MODULE, |
66 | }, | 77 | }, |
67 | .notify = notify, | 78 | .notify = scm_notify, |
68 | .probe = scm_probe, | 79 | .probe = scm_probe, |
69 | .remove = scm_remove, | 80 | .remove = scm_remove, |
70 | .handler = scm_blk_irq, | 81 | .handler = scm_blk_irq, |
diff --git a/drivers/s390/char/sclp_cmd.c b/drivers/s390/char/sclp_cmd.c index 30a2255389e5..cd798386b622 100644 --- a/drivers/s390/char/sclp_cmd.c +++ b/drivers/s390/char/sclp_cmd.c | |||
@@ -627,6 +627,8 @@ static int __init sclp_detect_standby_memory(void) | |||
627 | struct read_storage_sccb *sccb; | 627 | struct read_storage_sccb *sccb; |
628 | int i, id, assigned, rc; | 628 | int i, id, assigned, rc; |
629 | 629 | ||
630 | if (OLDMEM_BASE) /* No standby memory in kdump mode */ | ||
631 | return 0; | ||
630 | if (!early_read_info_sccb_valid) | 632 | if (!early_read_info_sccb_valid) |
631 | return 0; | 633 | return 0; |
632 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) | 634 | if ((sclp_facilities & 0xe00000000000ULL) != 0xe00000000000ULL) |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 31ceef1beb8b..e16c553f6556 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -433,6 +433,20 @@ static void chsc_process_sei_scm_change(struct chsc_sei_nt0_area *sei_area) | |||
433 | " failed (rc=%d).\n", ret); | 433 | " failed (rc=%d).\n", ret); |
434 | } | 434 | } |
435 | 435 | ||
436 | static void chsc_process_sei_scm_avail(struct chsc_sei_nt0_area *sei_area) | ||
437 | { | ||
438 | int ret; | ||
439 | |||
440 | CIO_CRW_EVENT(4, "chsc: scm available information\n"); | ||
441 | if (sei_area->rs != 7) | ||
442 | return; | ||
443 | |||
444 | ret = scm_process_availability_information(); | ||
445 | if (ret) | ||
446 | CIO_CRW_EVENT(0, "chsc: process availability information" | ||
447 | " failed (rc=%d).\n", ret); | ||
448 | } | ||
449 | |||
436 | static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area) | 450 | static void chsc_process_sei_nt2(struct chsc_sei_nt2_area *sei_area) |
437 | { | 451 | { |
438 | switch (sei_area->cc) { | 452 | switch (sei_area->cc) { |
@@ -468,6 +482,9 @@ static void chsc_process_sei_nt0(struct chsc_sei_nt0_area *sei_area) | |||
468 | case 12: /* scm change notification */ | 482 | case 12: /* scm change notification */ |
469 | chsc_process_sei_scm_change(sei_area); | 483 | chsc_process_sei_scm_change(sei_area); |
470 | break; | 484 | break; |
485 | case 14: /* scm available notification */ | ||
486 | chsc_process_sei_scm_avail(sei_area); | ||
487 | break; | ||
471 | default: /* other stuff */ | 488 | default: /* other stuff */ |
472 | CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n", | 489 | CIO_CRW_EVENT(2, "chsc: sei nt0 unhandled cc=%d\n", |
473 | sei_area->cc); | 490 | sei_area->cc); |
diff --git a/drivers/s390/cio/chsc.h b/drivers/s390/cio/chsc.h index 227e05f674b3..349d5fc47196 100644 --- a/drivers/s390/cio/chsc.h +++ b/drivers/s390/cio/chsc.h | |||
@@ -156,8 +156,10 @@ int chsc_scm_info(struct chsc_scm_info *scm_area, u64 token); | |||
156 | 156 | ||
157 | #ifdef CONFIG_SCM_BUS | 157 | #ifdef CONFIG_SCM_BUS |
158 | int scm_update_information(void); | 158 | int scm_update_information(void); |
159 | int scm_process_availability_information(void); | ||
159 | #else /* CONFIG_SCM_BUS */ | 160 | #else /* CONFIG_SCM_BUS */ |
160 | static inline int scm_update_information(void) { return 0; } | 161 | static inline int scm_update_information(void) { return 0; } |
162 | static inline int scm_process_availability_information(void) { return 0; } | ||
161 | #endif /* CONFIG_SCM_BUS */ | 163 | #endif /* CONFIG_SCM_BUS */ |
162 | 164 | ||
163 | 165 | ||
diff --git a/drivers/s390/cio/scm.c b/drivers/s390/cio/scm.c index bcf20f3aa51b..46ec25632e8b 100644 --- a/drivers/s390/cio/scm.c +++ b/drivers/s390/cio/scm.c | |||
@@ -211,7 +211,7 @@ static void scmdev_update(struct scm_device *scmdev, struct sale *sale) | |||
211 | goto out; | 211 | goto out; |
212 | scmdrv = to_scm_drv(scmdev->dev.driver); | 212 | scmdrv = to_scm_drv(scmdev->dev.driver); |
213 | if (changed && scmdrv->notify) | 213 | if (changed && scmdrv->notify) |
214 | scmdrv->notify(scmdev); | 214 | scmdrv->notify(scmdev, SCM_CHANGE); |
215 | out: | 215 | out: |
216 | device_unlock(&scmdev->dev); | 216 | device_unlock(&scmdev->dev); |
217 | if (changed) | 217 | if (changed) |
@@ -297,6 +297,22 @@ int scm_update_information(void) | |||
297 | return ret; | 297 | return ret; |
298 | } | 298 | } |
299 | 299 | ||
300 | static int scm_dev_avail(struct device *dev, void *unused) | ||
301 | { | ||
302 | struct scm_driver *scmdrv = to_scm_drv(dev->driver); | ||
303 | struct scm_device *scmdev = to_scm_dev(dev); | ||
304 | |||
305 | if (dev->driver && scmdrv->notify) | ||
306 | scmdrv->notify(scmdev, SCM_AVAIL); | ||
307 | |||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | int scm_process_availability_information(void) | ||
312 | { | ||
313 | return bus_for_each_dev(&scm_bus_type, NULL, NULL, scm_dev_avail); | ||
314 | } | ||
315 | |||
300 | static int __init scm_init(void) | 316 | static int __init scm_init(void) |
301 | { | 317 | { |
302 | int ret; | 318 | int ret; |
diff --git a/drivers/s390/net/qeth_core.h b/drivers/s390/net/qeth_core.h index d87961d4c0de..8c0622399fcd 100644 --- a/drivers/s390/net/qeth_core.h +++ b/drivers/s390/net/qeth_core.h | |||
@@ -916,6 +916,7 @@ int qeth_send_control_data(struct qeth_card *, int, struct qeth_cmd_buffer *, | |||
916 | void *reply_param); | 916 | void *reply_param); |
917 | int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); | 917 | int qeth_get_priority_queue(struct qeth_card *, struct sk_buff *, int, int); |
918 | int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); | 918 | int qeth_get_elements_no(struct qeth_card *, void *, struct sk_buff *, int); |
919 | int qeth_get_elements_for_frags(struct sk_buff *); | ||
919 | int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, | 920 | int qeth_do_send_packet_fast(struct qeth_card *, struct qeth_qdio_out_q *, |
920 | struct sk_buff *, struct qeth_hdr *, int, int, int); | 921 | struct sk_buff *, struct qeth_hdr *, int, int, int); |
921 | int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *, | 922 | int qeth_do_send_packet(struct qeth_card *, struct qeth_qdio_out_q *, |
diff --git a/drivers/s390/net/qeth_core_main.c b/drivers/s390/net/qeth_core_main.c index 0d8cdff81813..0d73a999983d 100644 --- a/drivers/s390/net/qeth_core_main.c +++ b/drivers/s390/net/qeth_core_main.c | |||
@@ -3679,6 +3679,25 @@ int qeth_get_priority_queue(struct qeth_card *card, struct sk_buff *skb, | |||
3679 | } | 3679 | } |
3680 | EXPORT_SYMBOL_GPL(qeth_get_priority_queue); | 3680 | EXPORT_SYMBOL_GPL(qeth_get_priority_queue); |
3681 | 3681 | ||
3682 | int qeth_get_elements_for_frags(struct sk_buff *skb) | ||
3683 | { | ||
3684 | int cnt, length, e, elements = 0; | ||
3685 | struct skb_frag_struct *frag; | ||
3686 | char *data; | ||
3687 | |||
3688 | for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { | ||
3689 | frag = &skb_shinfo(skb)->frags[cnt]; | ||
3690 | data = (char *)page_to_phys(skb_frag_page(frag)) + | ||
3691 | frag->page_offset; | ||
3692 | length = frag->size; | ||
3693 | e = PFN_UP((unsigned long)data + length - 1) - | ||
3694 | PFN_DOWN((unsigned long)data); | ||
3695 | elements += e; | ||
3696 | } | ||
3697 | return elements; | ||
3698 | } | ||
3699 | EXPORT_SYMBOL_GPL(qeth_get_elements_for_frags); | ||
3700 | |||
3682 | int qeth_get_elements_no(struct qeth_card *card, void *hdr, | 3701 | int qeth_get_elements_no(struct qeth_card *card, void *hdr, |
3683 | struct sk_buff *skb, int elems) | 3702 | struct sk_buff *skb, int elems) |
3684 | { | 3703 | { |
@@ -3686,7 +3705,8 @@ int qeth_get_elements_no(struct qeth_card *card, void *hdr, | |||
3686 | int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) - | 3705 | int elements_needed = PFN_UP((unsigned long)skb->data + dlen - 1) - |
3687 | PFN_DOWN((unsigned long)skb->data); | 3706 | PFN_DOWN((unsigned long)skb->data); |
3688 | 3707 | ||
3689 | elements_needed += skb_shinfo(skb)->nr_frags; | 3708 | elements_needed += qeth_get_elements_for_frags(skb); |
3709 | |||
3690 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { | 3710 | if ((elements_needed + elems) > QETH_MAX_BUFFER_ELEMENTS(card)) { |
3691 | QETH_DBF_MESSAGE(2, "Invalid size of IP packet " | 3711 | QETH_DBF_MESSAGE(2, "Invalid size of IP packet " |
3692 | "(Number=%d / Length=%d). Discarded.\n", | 3712 | "(Number=%d / Length=%d). Discarded.\n", |
@@ -3771,12 +3791,23 @@ static inline void __qeth_fill_buffer(struct sk_buff *skb, | |||
3771 | 3791 | ||
3772 | for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { | 3792 | for (cnt = 0; cnt < skb_shinfo(skb)->nr_frags; cnt++) { |
3773 | frag = &skb_shinfo(skb)->frags[cnt]; | 3793 | frag = &skb_shinfo(skb)->frags[cnt]; |
3774 | buffer->element[element].addr = (char *) | 3794 | data = (char *)page_to_phys(skb_frag_page(frag)) + |
3775 | page_to_phys(skb_frag_page(frag)) | 3795 | frag->page_offset; |
3776 | + frag->page_offset; | 3796 | length = frag->size; |
3777 | buffer->element[element].length = frag->size; | 3797 | while (length > 0) { |
3778 | buffer->element[element].eflags = SBAL_EFLAGS_MIDDLE_FRAG; | 3798 | length_here = PAGE_SIZE - |
3779 | element++; | 3799 | ((unsigned long) data % PAGE_SIZE); |
3800 | if (length < length_here) | ||
3801 | length_here = length; | ||
3802 | |||
3803 | buffer->element[element].addr = data; | ||
3804 | buffer->element[element].length = length_here; | ||
3805 | buffer->element[element].eflags = | ||
3806 | SBAL_EFLAGS_MIDDLE_FRAG; | ||
3807 | length -= length_here; | ||
3808 | data += length_here; | ||
3809 | element++; | ||
3810 | } | ||
3780 | } | 3811 | } |
3781 | 3812 | ||
3782 | if (buffer->element[element - 1].eflags) | 3813 | if (buffer->element[element - 1].eflags) |
diff --git a/drivers/s390/net/qeth_l3_main.c b/drivers/s390/net/qeth_l3_main.c index 091ca0efa1c5..8710337dab3e 100644 --- a/drivers/s390/net/qeth_l3_main.c +++ b/drivers/s390/net/qeth_l3_main.c | |||
@@ -623,7 +623,7 @@ static int qeth_l3_send_setrouting(struct qeth_card *card, | |||
623 | return rc; | 623 | return rc; |
624 | } | 624 | } |
625 | 625 | ||
626 | static void qeth_l3_correct_routing_type(struct qeth_card *card, | 626 | static int qeth_l3_correct_routing_type(struct qeth_card *card, |
627 | enum qeth_routing_types *type, enum qeth_prot_versions prot) | 627 | enum qeth_routing_types *type, enum qeth_prot_versions prot) |
628 | { | 628 | { |
629 | if (card->info.type == QETH_CARD_TYPE_IQD) { | 629 | if (card->info.type == QETH_CARD_TYPE_IQD) { |
@@ -632,7 +632,7 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card, | |||
632 | case PRIMARY_CONNECTOR: | 632 | case PRIMARY_CONNECTOR: |
633 | case SECONDARY_CONNECTOR: | 633 | case SECONDARY_CONNECTOR: |
634 | case MULTICAST_ROUTER: | 634 | case MULTICAST_ROUTER: |
635 | return; | 635 | return 0; |
636 | default: | 636 | default: |
637 | goto out_inval; | 637 | goto out_inval; |
638 | } | 638 | } |
@@ -641,17 +641,18 @@ static void qeth_l3_correct_routing_type(struct qeth_card *card, | |||
641 | case NO_ROUTER: | 641 | case NO_ROUTER: |
642 | case PRIMARY_ROUTER: | 642 | case PRIMARY_ROUTER: |
643 | case SECONDARY_ROUTER: | 643 | case SECONDARY_ROUTER: |
644 | return; | 644 | return 0; |
645 | case MULTICAST_ROUTER: | 645 | case MULTICAST_ROUTER: |
646 | if (qeth_is_ipafunc_supported(card, prot, | 646 | if (qeth_is_ipafunc_supported(card, prot, |
647 | IPA_OSA_MC_ROUTER)) | 647 | IPA_OSA_MC_ROUTER)) |
648 | return; | 648 | return 0; |
649 | default: | 649 | default: |
650 | goto out_inval; | 650 | goto out_inval; |
651 | } | 651 | } |
652 | } | 652 | } |
653 | out_inval: | 653 | out_inval: |
654 | *type = NO_ROUTER; | 654 | *type = NO_ROUTER; |
655 | return -EINVAL; | ||
655 | } | 656 | } |
656 | 657 | ||
657 | int qeth_l3_setrouting_v4(struct qeth_card *card) | 658 | int qeth_l3_setrouting_v4(struct qeth_card *card) |
@@ -660,8 +661,10 @@ int qeth_l3_setrouting_v4(struct qeth_card *card) | |||
660 | 661 | ||
661 | QETH_CARD_TEXT(card, 3, "setrtg4"); | 662 | QETH_CARD_TEXT(card, 3, "setrtg4"); |
662 | 663 | ||
663 | qeth_l3_correct_routing_type(card, &card->options.route4.type, | 664 | rc = qeth_l3_correct_routing_type(card, &card->options.route4.type, |
664 | QETH_PROT_IPV4); | 665 | QETH_PROT_IPV4); |
666 | if (rc) | ||
667 | return rc; | ||
665 | 668 | ||
666 | rc = qeth_l3_send_setrouting(card, card->options.route4.type, | 669 | rc = qeth_l3_send_setrouting(card, card->options.route4.type, |
667 | QETH_PROT_IPV4); | 670 | QETH_PROT_IPV4); |
@@ -683,8 +686,10 @@ int qeth_l3_setrouting_v6(struct qeth_card *card) | |||
683 | 686 | ||
684 | if (!qeth_is_supported(card, IPA_IPV6)) | 687 | if (!qeth_is_supported(card, IPA_IPV6)) |
685 | return 0; | 688 | return 0; |
686 | qeth_l3_correct_routing_type(card, &card->options.route6.type, | 689 | rc = qeth_l3_correct_routing_type(card, &card->options.route6.type, |
687 | QETH_PROT_IPV6); | 690 | QETH_PROT_IPV6); |
691 | if (rc) | ||
692 | return rc; | ||
688 | 693 | ||
689 | rc = qeth_l3_send_setrouting(card, card->options.route6.type, | 694 | rc = qeth_l3_send_setrouting(card, card->options.route6.type, |
690 | QETH_PROT_IPV6); | 695 | QETH_PROT_IPV6); |
@@ -2898,7 +2903,9 @@ static inline int qeth_l3_tso_elements(struct sk_buff *skb) | |||
2898 | tcp_hdr(skb)->doff * 4; | 2903 | tcp_hdr(skb)->doff * 4; |
2899 | int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data); | 2904 | int tcpd_len = skb->len - (tcpd - (unsigned long)skb->data); |
2900 | int elements = PFN_UP(tcpd + tcpd_len - 1) - PFN_DOWN(tcpd); | 2905 | int elements = PFN_UP(tcpd + tcpd_len - 1) - PFN_DOWN(tcpd); |
2901 | elements += skb_shinfo(skb)->nr_frags; | 2906 | |
2907 | elements += qeth_get_elements_for_frags(skb); | ||
2908 | |||
2902 | return elements; | 2909 | return elements; |
2903 | } | 2910 | } |
2904 | 2911 | ||
@@ -3348,7 +3355,6 @@ static int __qeth_l3_set_online(struct ccwgroup_device *gdev, int recovery_mode) | |||
3348 | rc = -ENODEV; | 3355 | rc = -ENODEV; |
3349 | goto out_remove; | 3356 | goto out_remove; |
3350 | } | 3357 | } |
3351 | qeth_trace_features(card); | ||
3352 | 3358 | ||
3353 | if (!card->dev && qeth_l3_setup_netdev(card)) { | 3359 | if (!card->dev && qeth_l3_setup_netdev(card)) { |
3354 | rc = -ENODEV; | 3360 | rc = -ENODEV; |
@@ -3425,6 +3431,7 @@ contin: | |||
3425 | qeth_l3_set_multicast_list(card->dev); | 3431 | qeth_l3_set_multicast_list(card->dev); |
3426 | rtnl_unlock(); | 3432 | rtnl_unlock(); |
3427 | } | 3433 | } |
3434 | qeth_trace_features(card); | ||
3428 | /* let user_space know that device is online */ | 3435 | /* let user_space know that device is online */ |
3429 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); | 3436 | kobject_uevent(&gdev->dev.kobj, KOBJ_CHANGE); |
3430 | mutex_unlock(&card->conf_mutex); | 3437 | mutex_unlock(&card->conf_mutex); |
diff --git a/drivers/s390/net/qeth_l3_sys.c b/drivers/s390/net/qeth_l3_sys.c index ebc379486267..e70af2406ff9 100644 --- a/drivers/s390/net/qeth_l3_sys.c +++ b/drivers/s390/net/qeth_l3_sys.c | |||
@@ -87,6 +87,8 @@ static ssize_t qeth_l3_dev_route_store(struct qeth_card *card, | |||
87 | rc = qeth_l3_setrouting_v6(card); | 87 | rc = qeth_l3_setrouting_v6(card); |
88 | } | 88 | } |
89 | out: | 89 | out: |
90 | if (rc) | ||
91 | route->type = old_route_type; | ||
90 | mutex_unlock(&card->conf_mutex); | 92 | mutex_unlock(&card->conf_mutex); |
91 | return rc ? rc : count; | 93 | return rc ? rc : count; |
92 | } | 94 | } |
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index 765398c063c7..c31187d79343 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
@@ -71,9 +71,14 @@ struct kmem_cache *scsi_sdb_cache; | |||
71 | #ifdef CONFIG_ACPI | 71 | #ifdef CONFIG_ACPI |
72 | #include <acpi/acpi_bus.h> | 72 | #include <acpi/acpi_bus.h> |
73 | 73 | ||
74 | static bool acpi_scsi_bus_match(struct device *dev) | ||
75 | { | ||
76 | return dev->bus == &scsi_bus_type; | ||
77 | } | ||
78 | |||
74 | int scsi_register_acpi_bus_type(struct acpi_bus_type *bus) | 79 | int scsi_register_acpi_bus_type(struct acpi_bus_type *bus) |
75 | { | 80 | { |
76 | bus->bus = &scsi_bus_type; | 81 | bus->match = acpi_scsi_bus_match; |
77 | return register_acpi_bus_type(bus); | 82 | return register_acpi_bus_type(bus); |
78 | } | 83 | } |
79 | EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type); | 84 | EXPORT_SYMBOL_GPL(scsi_register_acpi_bus_type); |
diff --git a/drivers/staging/ccg/f_fs.c b/drivers/staging/ccg/f_fs.c index 8adc79d1b402..f6373dade7fb 100644 --- a/drivers/staging/ccg/f_fs.c +++ b/drivers/staging/ccg/f_fs.c | |||
@@ -1223,6 +1223,7 @@ static struct file_system_type ffs_fs_type = { | |||
1223 | .mount = ffs_fs_mount, | 1223 | .mount = ffs_fs_mount, |
1224 | .kill_sb = ffs_fs_kill_sb, | 1224 | .kill_sb = ffs_fs_kill_sb, |
1225 | }; | 1225 | }; |
1226 | MODULE_ALIAS_FS("functionfs"); | ||
1226 | 1227 | ||
1227 | 1228 | ||
1228 | /* Driver's main init/cleanup functions *************************************/ | 1229 | /* Driver's main init/cleanup functions *************************************/ |
diff --git a/drivers/staging/comedi/drivers/dt9812.c b/drivers/staging/comedi/drivers/dt9812.c index 192cf088f834..57b451904791 100644 --- a/drivers/staging/comedi/drivers/dt9812.c +++ b/drivers/staging/comedi/drivers/dt9812.c | |||
@@ -947,12 +947,13 @@ static int dt9812_di_rinsn(struct comedi_device *dev, | |||
947 | unsigned int *data) | 947 | unsigned int *data) |
948 | { | 948 | { |
949 | struct comedi_dt9812 *devpriv = dev->private; | 949 | struct comedi_dt9812 *devpriv = dev->private; |
950 | unsigned int channel = CR_CHAN(insn->chanspec); | ||
950 | int n; | 951 | int n; |
951 | u8 bits = 0; | 952 | u8 bits = 0; |
952 | 953 | ||
953 | dt9812_digital_in(devpriv->slot, &bits); | 954 | dt9812_digital_in(devpriv->slot, &bits); |
954 | for (n = 0; n < insn->n; n++) | 955 | for (n = 0; n < insn->n; n++) |
955 | data[n] = ((1 << insn->chanspec) & bits) != 0; | 956 | data[n] = ((1 << channel) & bits) != 0; |
956 | return n; | 957 | return n; |
957 | } | 958 | } |
958 | 959 | ||
@@ -961,12 +962,13 @@ static int dt9812_do_winsn(struct comedi_device *dev, | |||
961 | unsigned int *data) | 962 | unsigned int *data) |
962 | { | 963 | { |
963 | struct comedi_dt9812 *devpriv = dev->private; | 964 | struct comedi_dt9812 *devpriv = dev->private; |
965 | unsigned int channel = CR_CHAN(insn->chanspec); | ||
964 | int n; | 966 | int n; |
965 | u8 bits = 0; | 967 | u8 bits = 0; |
966 | 968 | ||
967 | dt9812_digital_out_shadow(devpriv->slot, &bits); | 969 | dt9812_digital_out_shadow(devpriv->slot, &bits); |
968 | for (n = 0; n < insn->n; n++) { | 970 | for (n = 0; n < insn->n; n++) { |
969 | u8 mask = 1 << insn->chanspec; | 971 | u8 mask = 1 << channel; |
970 | 972 | ||
971 | bits &= ~mask; | 973 | bits &= ~mask; |
972 | if (data[n]) | 974 | if (data[n]) |
@@ -981,13 +983,13 @@ static int dt9812_ai_rinsn(struct comedi_device *dev, | |||
981 | unsigned int *data) | 983 | unsigned int *data) |
982 | { | 984 | { |
983 | struct comedi_dt9812 *devpriv = dev->private; | 985 | struct comedi_dt9812 *devpriv = dev->private; |
986 | unsigned int channel = CR_CHAN(insn->chanspec); | ||
984 | int n; | 987 | int n; |
985 | 988 | ||
986 | for (n = 0; n < insn->n; n++) { | 989 | for (n = 0; n < insn->n; n++) { |
987 | u16 value = 0; | 990 | u16 value = 0; |
988 | 991 | ||
989 | dt9812_analog_in(devpriv->slot, insn->chanspec, &value, | 992 | dt9812_analog_in(devpriv->slot, channel, &value, DT9812_GAIN_1); |
990 | DT9812_GAIN_1); | ||
991 | data[n] = value; | 993 | data[n] = value; |
992 | } | 994 | } |
993 | return n; | 995 | return n; |
@@ -998,12 +1000,13 @@ static int dt9812_ao_rinsn(struct comedi_device *dev, | |||
998 | unsigned int *data) | 1000 | unsigned int *data) |
999 | { | 1001 | { |
1000 | struct comedi_dt9812 *devpriv = dev->private; | 1002 | struct comedi_dt9812 *devpriv = dev->private; |
1003 | unsigned int channel = CR_CHAN(insn->chanspec); | ||
1001 | int n; | 1004 | int n; |
1002 | u16 value; | 1005 | u16 value; |
1003 | 1006 | ||
1004 | for (n = 0; n < insn->n; n++) { | 1007 | for (n = 0; n < insn->n; n++) { |
1005 | value = 0; | 1008 | value = 0; |
1006 | dt9812_analog_out_shadow(devpriv->slot, insn->chanspec, &value); | 1009 | dt9812_analog_out_shadow(devpriv->slot, channel, &value); |
1007 | data[n] = value; | 1010 | data[n] = value; |
1008 | } | 1011 | } |
1009 | return n; | 1012 | return n; |
@@ -1014,10 +1017,11 @@ static int dt9812_ao_winsn(struct comedi_device *dev, | |||
1014 | unsigned int *data) | 1017 | unsigned int *data) |
1015 | { | 1018 | { |
1016 | struct comedi_dt9812 *devpriv = dev->private; | 1019 | struct comedi_dt9812 *devpriv = dev->private; |
1020 | unsigned int channel = CR_CHAN(insn->chanspec); | ||
1017 | int n; | 1021 | int n; |
1018 | 1022 | ||
1019 | for (n = 0; n < insn->n; n++) | 1023 | for (n = 0; n < insn->n; n++) |
1020 | dt9812_analog_out(devpriv->slot, insn->chanspec, data[n]); | 1024 | dt9812_analog_out(devpriv->slot, channel, data[n]); |
1021 | return n; | 1025 | return n; |
1022 | } | 1026 | } |
1023 | 1027 | ||
diff --git a/drivers/staging/comedi/drivers/s626.c b/drivers/staging/comedi/drivers/s626.c index 81a1fe661579..71a73ec5af8d 100644 --- a/drivers/staging/comedi/drivers/s626.c +++ b/drivers/staging/comedi/drivers/s626.c | |||
@@ -1483,7 +1483,7 @@ static int s626_ai_cmd(struct comedi_device *dev, struct comedi_subdevice *s) | |||
1483 | case TRIG_NONE: | 1483 | case TRIG_NONE: |
1484 | /* continous acquisition */ | 1484 | /* continous acquisition */ |
1485 | devpriv->ai_continous = 1; | 1485 | devpriv->ai_continous = 1; |
1486 | devpriv->ai_sample_count = 0; | 1486 | devpriv->ai_sample_count = 1; |
1487 | break; | 1487 | break; |
1488 | } | 1488 | } |
1489 | 1489 | ||
diff --git a/drivers/staging/comedi/drivers/usbdux.c b/drivers/staging/comedi/drivers/usbdux.c index 1a0062a04456..6aac1f60bc42 100644 --- a/drivers/staging/comedi/drivers/usbdux.c +++ b/drivers/staging/comedi/drivers/usbdux.c | |||
@@ -730,10 +730,14 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) | |||
730 | static int usbduxsub_start(struct usbduxsub *usbduxsub) | 730 | static int usbduxsub_start(struct usbduxsub *usbduxsub) |
731 | { | 731 | { |
732 | int errcode = 0; | 732 | int errcode = 0; |
733 | uint8_t local_transfer_buffer[16]; | 733 | uint8_t *local_transfer_buffer; |
734 | |||
735 | local_transfer_buffer = kmalloc(1, GFP_KERNEL); | ||
736 | if (!local_transfer_buffer) | ||
737 | return -ENOMEM; | ||
734 | 738 | ||
735 | /* 7f92 to zero */ | 739 | /* 7f92 to zero */ |
736 | local_transfer_buffer[0] = 0; | 740 | *local_transfer_buffer = 0; |
737 | errcode = usb_control_msg(usbduxsub->usbdev, | 741 | errcode = usb_control_msg(usbduxsub->usbdev, |
738 | /* create a pipe for a control transfer */ | 742 | /* create a pipe for a control transfer */ |
739 | usb_sndctrlpipe(usbduxsub->usbdev, 0), | 743 | usb_sndctrlpipe(usbduxsub->usbdev, 0), |
@@ -751,22 +755,25 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub) | |||
751 | 1, | 755 | 1, |
752 | /* Timeout */ | 756 | /* Timeout */ |
753 | BULK_TIMEOUT); | 757 | BULK_TIMEOUT); |
754 | if (errcode < 0) { | 758 | if (errcode < 0) |
755 | dev_err(&usbduxsub->interface->dev, | 759 | dev_err(&usbduxsub->interface->dev, |
756 | "comedi_: control msg failed (start)\n"); | 760 | "comedi_: control msg failed (start)\n"); |
757 | return errcode; | 761 | |
758 | } | 762 | kfree(local_transfer_buffer); |
759 | return 0; | 763 | return errcode; |
760 | } | 764 | } |
761 | 765 | ||
762 | static int usbduxsub_stop(struct usbduxsub *usbduxsub) | 766 | static int usbduxsub_stop(struct usbduxsub *usbduxsub) |
763 | { | 767 | { |
764 | int errcode = 0; | 768 | int errcode = 0; |
769 | uint8_t *local_transfer_buffer; | ||
765 | 770 | ||
766 | uint8_t local_transfer_buffer[16]; | 771 | local_transfer_buffer = kmalloc(1, GFP_KERNEL); |
772 | if (!local_transfer_buffer) | ||
773 | return -ENOMEM; | ||
767 | 774 | ||
768 | /* 7f92 to one */ | 775 | /* 7f92 to one */ |
769 | local_transfer_buffer[0] = 1; | 776 | *local_transfer_buffer = 1; |
770 | errcode = usb_control_msg(usbduxsub->usbdev, | 777 | errcode = usb_control_msg(usbduxsub->usbdev, |
771 | usb_sndctrlpipe(usbduxsub->usbdev, 0), | 778 | usb_sndctrlpipe(usbduxsub->usbdev, 0), |
772 | /* bRequest, "Firmware" */ | 779 | /* bRequest, "Firmware" */ |
@@ -781,12 +788,12 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub) | |||
781 | 1, | 788 | 1, |
782 | /* Timeout */ | 789 | /* Timeout */ |
783 | BULK_TIMEOUT); | 790 | BULK_TIMEOUT); |
784 | if (errcode < 0) { | 791 | if (errcode < 0) |
785 | dev_err(&usbduxsub->interface->dev, | 792 | dev_err(&usbduxsub->interface->dev, |
786 | "comedi_: control msg failed (stop)\n"); | 793 | "comedi_: control msg failed (stop)\n"); |
787 | return errcode; | 794 | |
788 | } | 795 | kfree(local_transfer_buffer); |
789 | return 0; | 796 | return errcode; |
790 | } | 797 | } |
791 | 798 | ||
792 | static int usbduxsub_upload(struct usbduxsub *usbduxsub, | 799 | static int usbduxsub_upload(struct usbduxsub *usbduxsub, |
diff --git a/drivers/staging/comedi/drivers/usbduxfast.c b/drivers/staging/comedi/drivers/usbduxfast.c index 4bf5dd094dc9..1ba0e3df492d 100644 --- a/drivers/staging/comedi/drivers/usbduxfast.c +++ b/drivers/staging/comedi/drivers/usbduxfast.c | |||
@@ -436,10 +436,14 @@ static void usbduxfastsub_ai_Irq(struct urb *urb) | |||
436 | static int usbduxfastsub_start(struct usbduxfastsub_s *udfs) | 436 | static int usbduxfastsub_start(struct usbduxfastsub_s *udfs) |
437 | { | 437 | { |
438 | int ret; | 438 | int ret; |
439 | unsigned char local_transfer_buffer[16]; | 439 | unsigned char *local_transfer_buffer; |
440 | |||
441 | local_transfer_buffer = kmalloc(1, GFP_KERNEL); | ||
442 | if (!local_transfer_buffer) | ||
443 | return -ENOMEM; | ||
440 | 444 | ||
441 | /* 7f92 to zero */ | 445 | /* 7f92 to zero */ |
442 | local_transfer_buffer[0] = 0; | 446 | *local_transfer_buffer = 0; |
443 | /* bRequest, "Firmware" */ | 447 | /* bRequest, "Firmware" */ |
444 | ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), | 448 | ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), |
445 | USBDUXFASTSUB_FIRMWARE, | 449 | USBDUXFASTSUB_FIRMWARE, |
@@ -450,22 +454,25 @@ static int usbduxfastsub_start(struct usbduxfastsub_s *udfs) | |||
450 | local_transfer_buffer, | 454 | local_transfer_buffer, |
451 | 1, /* Length */ | 455 | 1, /* Length */ |
452 | EZTIMEOUT); /* Timeout */ | 456 | EZTIMEOUT); /* Timeout */ |
453 | if (ret < 0) { | 457 | if (ret < 0) |
454 | dev_err(&udfs->interface->dev, | 458 | dev_err(&udfs->interface->dev, |
455 | "control msg failed (start)\n"); | 459 | "control msg failed (start)\n"); |
456 | return ret; | ||
457 | } | ||
458 | 460 | ||
459 | return 0; | 461 | kfree(local_transfer_buffer); |
462 | return ret; | ||
460 | } | 463 | } |
461 | 464 | ||
462 | static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs) | 465 | static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs) |
463 | { | 466 | { |
464 | int ret; | 467 | int ret; |
465 | unsigned char local_transfer_buffer[16]; | 468 | unsigned char *local_transfer_buffer; |
469 | |||
470 | local_transfer_buffer = kmalloc(1, GFP_KERNEL); | ||
471 | if (!local_transfer_buffer) | ||
472 | return -ENOMEM; | ||
466 | 473 | ||
467 | /* 7f92 to one */ | 474 | /* 7f92 to one */ |
468 | local_transfer_buffer[0] = 1; | 475 | *local_transfer_buffer = 1; |
469 | /* bRequest, "Firmware" */ | 476 | /* bRequest, "Firmware" */ |
470 | ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), | 477 | ret = usb_control_msg(udfs->usbdev, usb_sndctrlpipe(udfs->usbdev, 0), |
471 | USBDUXFASTSUB_FIRMWARE, | 478 | USBDUXFASTSUB_FIRMWARE, |
@@ -474,13 +481,12 @@ static int usbduxfastsub_stop(struct usbduxfastsub_s *udfs) | |||
474 | 0x0000, /* Index */ | 481 | 0x0000, /* Index */ |
475 | local_transfer_buffer, 1, /* Length */ | 482 | local_transfer_buffer, 1, /* Length */ |
476 | EZTIMEOUT); /* Timeout */ | 483 | EZTIMEOUT); /* Timeout */ |
477 | if (ret < 0) { | 484 | if (ret < 0) |
478 | dev_err(&udfs->interface->dev, | 485 | dev_err(&udfs->interface->dev, |
479 | "control msg failed (stop)\n"); | 486 | "control msg failed (stop)\n"); |
480 | return ret; | ||
481 | } | ||
482 | 487 | ||
483 | return 0; | 488 | kfree(local_transfer_buffer); |
489 | return ret; | ||
484 | } | 490 | } |
485 | 491 | ||
486 | static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs, | 492 | static int usbduxfastsub_upload(struct usbduxfastsub_s *udfs, |
diff --git a/drivers/staging/comedi/drivers/usbduxsigma.c b/drivers/staging/comedi/drivers/usbduxsigma.c index d066351a71b2..a728c8fc32a2 100644 --- a/drivers/staging/comedi/drivers/usbduxsigma.c +++ b/drivers/staging/comedi/drivers/usbduxsigma.c | |||
@@ -681,7 +681,11 @@ static void usbduxsub_ao_IsocIrq(struct urb *urb) | |||
681 | static int usbduxsub_start(struct usbduxsub *usbduxsub) | 681 | static int usbduxsub_start(struct usbduxsub *usbduxsub) |
682 | { | 682 | { |
683 | int errcode = 0; | 683 | int errcode = 0; |
684 | uint8_t local_transfer_buffer[16]; | 684 | uint8_t *local_transfer_buffer; |
685 | |||
686 | local_transfer_buffer = kmalloc(16, GFP_KERNEL); | ||
687 | if (!local_transfer_buffer) | ||
688 | return -ENOMEM; | ||
685 | 689 | ||
686 | /* 7f92 to zero */ | 690 | /* 7f92 to zero */ |
687 | local_transfer_buffer[0] = 0; | 691 | local_transfer_buffer[0] = 0; |
@@ -702,19 +706,22 @@ static int usbduxsub_start(struct usbduxsub *usbduxsub) | |||
702 | 1, | 706 | 1, |
703 | /* Timeout */ | 707 | /* Timeout */ |
704 | BULK_TIMEOUT); | 708 | BULK_TIMEOUT); |
705 | if (errcode < 0) { | 709 | if (errcode < 0) |
706 | dev_err(&usbduxsub->interface->dev, | 710 | dev_err(&usbduxsub->interface->dev, |
707 | "comedi_: control msg failed (start)\n"); | 711 | "comedi_: control msg failed (start)\n"); |
708 | return errcode; | 712 | |
709 | } | 713 | kfree(local_transfer_buffer); |
710 | return 0; | 714 | return errcode; |
711 | } | 715 | } |
712 | 716 | ||
713 | static int usbduxsub_stop(struct usbduxsub *usbduxsub) | 717 | static int usbduxsub_stop(struct usbduxsub *usbduxsub) |
714 | { | 718 | { |
715 | int errcode = 0; | 719 | int errcode = 0; |
720 | uint8_t *local_transfer_buffer; | ||
716 | 721 | ||
717 | uint8_t local_transfer_buffer[16]; | 722 | local_transfer_buffer = kmalloc(16, GFP_KERNEL); |
723 | if (!local_transfer_buffer) | ||
724 | return -ENOMEM; | ||
718 | 725 | ||
719 | /* 7f92 to one */ | 726 | /* 7f92 to one */ |
720 | local_transfer_buffer[0] = 1; | 727 | local_transfer_buffer[0] = 1; |
@@ -732,12 +739,12 @@ static int usbduxsub_stop(struct usbduxsub *usbduxsub) | |||
732 | 1, | 739 | 1, |
733 | /* Timeout */ | 740 | /* Timeout */ |
734 | BULK_TIMEOUT); | 741 | BULK_TIMEOUT); |
735 | if (errcode < 0) { | 742 | if (errcode < 0) |
736 | dev_err(&usbduxsub->interface->dev, | 743 | dev_err(&usbduxsub->interface->dev, |
737 | "comedi_: control msg failed (stop)\n"); | 744 | "comedi_: control msg failed (stop)\n"); |
738 | return errcode; | 745 | |
739 | } | 746 | kfree(local_transfer_buffer); |
740 | return 0; | 747 | return errcode; |
741 | } | 748 | } |
742 | 749 | ||
743 | static int usbduxsub_upload(struct usbduxsub *usbduxsub, | 750 | static int usbduxsub_upload(struct usbduxsub *usbduxsub, |
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c index 4b3a019409b5..b028b0d1317b 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c | |||
@@ -483,17 +483,6 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, | |||
483 | goto err_out; | 483 | goto err_out; |
484 | } | 484 | } |
485 | 485 | ||
486 | ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch, | ||
487 | IPU_IRQ_EOF); | ||
488 | ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, | ||
489 | "imx_drm", ipu_crtc); | ||
490 | if (ret < 0) { | ||
491 | dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); | ||
492 | goto err_out; | ||
493 | } | ||
494 | |||
495 | disable_irq(ipu_crtc->irq); | ||
496 | |||
497 | return 0; | 486 | return 0; |
498 | err_out: | 487 | err_out: |
499 | ipu_put_resources(ipu_crtc); | 488 | ipu_put_resources(ipu_crtc); |
@@ -504,6 +493,7 @@ err_out: | |||
504 | static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, | 493 | static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, |
505 | struct ipu_client_platformdata *pdata) | 494 | struct ipu_client_platformdata *pdata) |
506 | { | 495 | { |
496 | struct ipu_soc *ipu = dev_get_drvdata(ipu_crtc->dev->parent); | ||
507 | int ret; | 497 | int ret; |
508 | 498 | ||
509 | ret = ipu_get_resources(ipu_crtc, pdata); | 499 | ret = ipu_get_resources(ipu_crtc, pdata); |
@@ -522,6 +512,17 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc, | |||
522 | goto err_put_resources; | 512 | goto err_put_resources; |
523 | } | 513 | } |
524 | 514 | ||
515 | ipu_crtc->irq = ipu_idmac_channel_irq(ipu, ipu_crtc->ipu_ch, | ||
516 | IPU_IRQ_EOF); | ||
517 | ret = devm_request_irq(ipu_crtc->dev, ipu_crtc->irq, ipu_irq_handler, 0, | ||
518 | "imx_drm", ipu_crtc); | ||
519 | if (ret < 0) { | ||
520 | dev_err(ipu_crtc->dev, "irq request failed with %d.\n", ret); | ||
521 | goto err_put_resources; | ||
522 | } | ||
523 | |||
524 | disable_irq(ipu_crtc->irq); | ||
525 | |||
525 | return 0; | 526 | return 0; |
526 | 527 | ||
527 | err_put_resources: | 528 | err_put_resources: |
diff --git a/drivers/staging/tidspbridge/rmgr/drv.c b/drivers/staging/tidspbridge/rmgr/drv.c index db1da28cecba..be26917a6896 100644 --- a/drivers/staging/tidspbridge/rmgr/drv.c +++ b/drivers/staging/tidspbridge/rmgr/drv.c | |||
@@ -76,37 +76,28 @@ int drv_insert_node_res_element(void *hnode, void *node_resource, | |||
76 | struct node_res_object **node_res_obj = | 76 | struct node_res_object **node_res_obj = |
77 | (struct node_res_object **)node_resource; | 77 | (struct node_res_object **)node_resource; |
78 | struct process_context *ctxt = (struct process_context *)process_ctxt; | 78 | struct process_context *ctxt = (struct process_context *)process_ctxt; |
79 | int status = 0; | ||
80 | int retval; | 79 | int retval; |
81 | 80 | ||
82 | *node_res_obj = kzalloc(sizeof(struct node_res_object), GFP_KERNEL); | 81 | *node_res_obj = kzalloc(sizeof(struct node_res_object), GFP_KERNEL); |
83 | if (!*node_res_obj) { | 82 | if (!*node_res_obj) |
84 | status = -ENOMEM; | 83 | return -ENOMEM; |
85 | goto func_end; | ||
86 | } | ||
87 | 84 | ||
88 | (*node_res_obj)->node = hnode; | 85 | (*node_res_obj)->node = hnode; |
89 | retval = idr_get_new(ctxt->node_id, *node_res_obj, | 86 | retval = idr_alloc(ctxt->node_id, *node_res_obj, 0, 0, GFP_KERNEL); |
90 | &(*node_res_obj)->id); | 87 | if (retval >= 0) { |
91 | if (retval == -EAGAIN) { | 88 | (*node_res_obj)->id = retval; |
92 | if (!idr_pre_get(ctxt->node_id, GFP_KERNEL)) { | 89 | return 0; |
93 | pr_err("%s: OUT OF MEMORY\n", __func__); | ||
94 | status = -ENOMEM; | ||
95 | goto func_end; | ||
96 | } | ||
97 | |||
98 | retval = idr_get_new(ctxt->node_id, *node_res_obj, | ||
99 | &(*node_res_obj)->id); | ||
100 | } | 90 | } |
101 | if (retval) { | 91 | |
92 | kfree(*node_res_obj); | ||
93 | |||
94 | if (retval == -ENOSPC) { | ||
102 | pr_err("%s: FAILED, IDR is FULL\n", __func__); | 95 | pr_err("%s: FAILED, IDR is FULL\n", __func__); |
103 | status = -EFAULT; | 96 | return -EFAULT; |
97 | } else { | ||
98 | pr_err("%s: OUT OF MEMORY\n", __func__); | ||
99 | return -ENOMEM; | ||
104 | } | 100 | } |
105 | func_end: | ||
106 | if (status) | ||
107 | kfree(*node_res_obj); | ||
108 | |||
109 | return status; | ||
110 | } | 101 | } |
111 | 102 | ||
112 | /* Release all Node resources and its context | 103 | /* Release all Node resources and its context |
@@ -201,35 +192,26 @@ int drv_proc_insert_strm_res_element(void *stream_obj, | |||
201 | struct strm_res_object **pstrm_res = | 192 | struct strm_res_object **pstrm_res = |
202 | (struct strm_res_object **)strm_res; | 193 | (struct strm_res_object **)strm_res; |
203 | struct process_context *ctxt = (struct process_context *)process_ctxt; | 194 | struct process_context *ctxt = (struct process_context *)process_ctxt; |
204 | int status = 0; | ||
205 | int retval; | 195 | int retval; |
206 | 196 | ||
207 | *pstrm_res = kzalloc(sizeof(struct strm_res_object), GFP_KERNEL); | 197 | *pstrm_res = kzalloc(sizeof(struct strm_res_object), GFP_KERNEL); |
208 | if (*pstrm_res == NULL) { | 198 | if (*pstrm_res == NULL) |
209 | status = -EFAULT; | 199 | return -EFAULT; |
210 | goto func_end; | ||
211 | } | ||
212 | 200 | ||
213 | (*pstrm_res)->stream = stream_obj; | 201 | (*pstrm_res)->stream = stream_obj; |
214 | retval = idr_get_new(ctxt->stream_id, *pstrm_res, | 202 | retval = idr_alloc(ctxt->stream_id, *pstrm_res, 0, 0, GFP_KERNEL); |
215 | &(*pstrm_res)->id); | 203 | if (retval >= 0) { |
216 | if (retval == -EAGAIN) { | 204 | (*pstrm_res)->id = retval; |
217 | if (!idr_pre_get(ctxt->stream_id, GFP_KERNEL)) { | 205 | return 0; |
218 | pr_err("%s: OUT OF MEMORY\n", __func__); | ||
219 | status = -ENOMEM; | ||
220 | goto func_end; | ||
221 | } | ||
222 | |||
223 | retval = idr_get_new(ctxt->stream_id, *pstrm_res, | ||
224 | &(*pstrm_res)->id); | ||
225 | } | 206 | } |
226 | if (retval) { | 207 | |
208 | if (retval == -ENOSPC) { | ||
227 | pr_err("%s: FAILED, IDR is FULL\n", __func__); | 209 | pr_err("%s: FAILED, IDR is FULL\n", __func__); |
228 | status = -EPERM; | 210 | return -EPERM; |
211 | } else { | ||
212 | pr_err("%s: OUT OF MEMORY\n", __func__); | ||
213 | return -ENOMEM; | ||
229 | } | 214 | } |
230 | |||
231 | func_end: | ||
232 | return status; | ||
233 | } | 215 | } |
234 | 216 | ||
235 | static int drv_proc_free_strm_res(int id, void *p, void *process_ctxt) | 217 | static int drv_proc_free_strm_res(int id, void *p, void *process_ctxt) |
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c index 22918a106d73..d2479b766450 100644 --- a/drivers/staging/vt6656/card.c +++ b/drivers/staging/vt6656/card.c | |||
@@ -790,7 +790,7 @@ u64 CARDqGetNextTBTT(u64 qwTSF, WORD wBeaconInterval) | |||
790 | if ((~uLowNextTBTT) < uLowRemain) | 790 | if ((~uLowNextTBTT) < uLowRemain) |
791 | qwTSF = ((qwTSF >> 32) + 1) << 32; | 791 | qwTSF = ((qwTSF >> 32) + 1) << 32; |
792 | 792 | ||
793 | qwTSF = (qwTSF & 0xffffffff00000000UL) | | 793 | qwTSF = (qwTSF & 0xffffffff00000000ULL) | |
794 | (u64)(uLowNextTBTT + uLowRemain); | 794 | (u64)(uLowNextTBTT + uLowRemain); |
795 | 795 | ||
796 | return (qwTSF); | 796 | return (qwTSF); |
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c index d5f53e1a74a2..a5063a6f64d9 100644 --- a/drivers/staging/vt6656/main_usb.c +++ b/drivers/staging/vt6656/main_usb.c | |||
@@ -669,8 +669,6 @@ static int vt6656_suspend(struct usb_interface *intf, pm_message_t message) | |||
669 | if (device->flags & DEVICE_FLAGS_OPENED) | 669 | if (device->flags & DEVICE_FLAGS_OPENED) |
670 | device_close(device->dev); | 670 | device_close(device->dev); |
671 | 671 | ||
672 | usb_put_dev(interface_to_usbdev(intf)); | ||
673 | |||
674 | return 0; | 672 | return 0; |
675 | } | 673 | } |
676 | 674 | ||
@@ -681,8 +679,6 @@ static int vt6656_resume(struct usb_interface *intf) | |||
681 | if (!device || !device->dev) | 679 | if (!device || !device->dev) |
682 | return -ENODEV; | 680 | return -ENODEV; |
683 | 681 | ||
684 | usb_get_dev(interface_to_usbdev(intf)); | ||
685 | |||
686 | if (!(device->flags & DEVICE_FLAGS_OPENED)) | 682 | if (!(device->flags & DEVICE_FLAGS_OPENED)) |
687 | device_open(device->dev); | 683 | device_open(device->dev); |
688 | 684 | ||
diff --git a/drivers/staging/zcache/Kconfig b/drivers/staging/zcache/Kconfig index 73582705e8c5..5c3714530961 100644 --- a/drivers/staging/zcache/Kconfig +++ b/drivers/staging/zcache/Kconfig | |||
@@ -15,7 +15,7 @@ config RAMSTER | |||
15 | depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE=y | 15 | depends on CONFIGFS_FS=y && SYSFS=y && !HIGHMEM && ZCACHE=y |
16 | depends on NET | 16 | depends on NET |
17 | # must ensure struct page is 8-byte aligned | 17 | # must ensure struct page is 8-byte aligned |
18 | select HAVE_ALIGNED_STRUCT_PAGE if !64_BIT | 18 | select HAVE_ALIGNED_STRUCT_PAGE if !64BIT |
19 | default n | 19 | default n |
20 | help | 20 | help |
21 | RAMster allows RAM on other machines in a cluster to be utilized | 21 | RAMster allows RAM on other machines in a cluster to be utilized |
diff --git a/drivers/staging/zcache/ramster/tcp.c b/drivers/staging/zcache/ramster/tcp.c index aa2a1a763aa4..f6e1e5209d88 100644 --- a/drivers/staging/zcache/ramster/tcp.c +++ b/drivers/staging/zcache/ramster/tcp.c | |||
@@ -300,27 +300,22 @@ static u8 r2net_num_from_nn(struct r2net_node *nn) | |||
300 | 300 | ||
301 | static int r2net_prep_nsw(struct r2net_node *nn, struct r2net_status_wait *nsw) | 301 | static int r2net_prep_nsw(struct r2net_node *nn, struct r2net_status_wait *nsw) |
302 | { | 302 | { |
303 | int ret = 0; | 303 | int ret; |
304 | 304 | ||
305 | do { | 305 | spin_lock(&nn->nn_lock); |
306 | if (!idr_pre_get(&nn->nn_status_idr, GFP_ATOMIC)) { | 306 | ret = idr_alloc(&nn->nn_status_idr, nsw, 0, 0, GFP_ATOMIC); |
307 | ret = -EAGAIN; | 307 | if (ret >= 0) { |
308 | break; | 308 | nsw->ns_id = ret; |
309 | } | 309 | list_add_tail(&nsw->ns_node_item, &nn->nn_status_list); |
310 | spin_lock(&nn->nn_lock); | 310 | } |
311 | ret = idr_get_new(&nn->nn_status_idr, nsw, &nsw->ns_id); | 311 | spin_unlock(&nn->nn_lock); |
312 | if (ret == 0) | ||
313 | list_add_tail(&nsw->ns_node_item, | ||
314 | &nn->nn_status_list); | ||
315 | spin_unlock(&nn->nn_lock); | ||
316 | } while (ret == -EAGAIN); | ||
317 | 312 | ||
318 | if (ret == 0) { | 313 | if (ret >= 0) { |
319 | init_waitqueue_head(&nsw->ns_wq); | 314 | init_waitqueue_head(&nsw->ns_wq); |
320 | nsw->ns_sys_status = R2NET_ERR_NONE; | 315 | nsw->ns_sys_status = R2NET_ERR_NONE; |
321 | nsw->ns_status = 0; | 316 | nsw->ns_status = 0; |
317 | return 0; | ||
322 | } | 318 | } |
323 | |||
324 | return ret; | 319 | return ret; |
325 | } | 320 | } |
326 | 321 | ||
diff --git a/drivers/target/iscsi/iscsi_target_auth.c b/drivers/target/iscsi/iscsi_target_auth.c index db0cf7c8adde..a0fc7b9eea65 100644 --- a/drivers/target/iscsi/iscsi_target_auth.c +++ b/drivers/target/iscsi/iscsi_target_auth.c | |||
@@ -166,6 +166,7 @@ static int chap_server_compute_md5( | |||
166 | { | 166 | { |
167 | char *endptr; | 167 | char *endptr; |
168 | unsigned long id; | 168 | unsigned long id; |
169 | unsigned char id_as_uchar; | ||
169 | unsigned char digest[MD5_SIGNATURE_SIZE]; | 170 | unsigned char digest[MD5_SIGNATURE_SIZE]; |
170 | unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2]; | 171 | unsigned char type, response[MD5_SIGNATURE_SIZE * 2 + 2]; |
171 | unsigned char identifier[10], *challenge = NULL; | 172 | unsigned char identifier[10], *challenge = NULL; |
@@ -355,7 +356,9 @@ static int chap_server_compute_md5( | |||
355 | goto out; | 356 | goto out; |
356 | } | 357 | } |
357 | 358 | ||
358 | sg_init_one(&sg, &id, 1); | 359 | /* To handle both endiannesses */ |
360 | id_as_uchar = id; | ||
361 | sg_init_one(&sg, &id_as_uchar, 1); | ||
359 | ret = crypto_hash_update(&desc, &sg, 1); | 362 | ret = crypto_hash_update(&desc, &sg, 1); |
360 | if (ret < 0) { | 363 | if (ret < 0) { |
361 | pr_err("crypto_hash_update() failed for id\n"); | 364 | pr_err("crypto_hash_update() failed for id\n"); |
diff --git a/drivers/target/target_core_file.h b/drivers/target/target_core_file.h index bc02b018ae46..37ffc5bd2399 100644 --- a/drivers/target/target_core_file.h +++ b/drivers/target/target_core_file.h | |||
@@ -7,7 +7,7 @@ | |||
7 | #define FD_DEVICE_QUEUE_DEPTH 32 | 7 | #define FD_DEVICE_QUEUE_DEPTH 32 |
8 | #define FD_MAX_DEVICE_QUEUE_DEPTH 128 | 8 | #define FD_MAX_DEVICE_QUEUE_DEPTH 128 |
9 | #define FD_BLOCKSIZE 512 | 9 | #define FD_BLOCKSIZE 512 |
10 | #define FD_MAX_SECTORS 1024 | 10 | #define FD_MAX_SECTORS 2048 |
11 | 11 | ||
12 | #define RRF_EMULATE_CDB 0x01 | 12 | #define RRF_EMULATE_CDB 0x01 |
13 | #define RRF_GOT_LBA 0x02 | 13 | #define RRF_GOT_LBA 0x02 |
diff --git a/drivers/target/target_core_pscsi.c b/drivers/target/target_core_pscsi.c index 82e78d72fdb6..e992b27aa090 100644 --- a/drivers/target/target_core_pscsi.c +++ b/drivers/target/target_core_pscsi.c | |||
@@ -883,7 +883,14 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
883 | pr_debug("PSCSI: i: %d page: %p len: %d off: %d\n", i, | 883 | pr_debug("PSCSI: i: %d page: %p len: %d off: %d\n", i, |
884 | page, len, off); | 884 | page, len, off); |
885 | 885 | ||
886 | while (len > 0 && data_len > 0) { | 886 | /* |
887 | * We only have one page of data in each sg element, | ||
888 | * we can not cross a page boundary. | ||
889 | */ | ||
890 | if (off + len > PAGE_SIZE) | ||
891 | goto fail; | ||
892 | |||
893 | if (len > 0 && data_len > 0) { | ||
887 | bytes = min_t(unsigned int, len, PAGE_SIZE - off); | 894 | bytes = min_t(unsigned int, len, PAGE_SIZE - off); |
888 | bytes = min(bytes, data_len); | 895 | bytes = min(bytes, data_len); |
889 | 896 | ||
@@ -940,9 +947,7 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents, | |||
940 | bio = NULL; | 947 | bio = NULL; |
941 | } | 948 | } |
942 | 949 | ||
943 | len -= bytes; | ||
944 | data_len -= bytes; | 950 | data_len -= bytes; |
945 | off = 0; | ||
946 | } | 951 | } |
947 | } | 952 | } |
948 | 953 | ||
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 290230de2c53..60d4b5185f32 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -464,8 +464,11 @@ sbc_parse_cdb(struct se_cmd *cmd, struct sbc_ops *ops) | |||
464 | break; | 464 | break; |
465 | case SYNCHRONIZE_CACHE: | 465 | case SYNCHRONIZE_CACHE: |
466 | case SYNCHRONIZE_CACHE_16: | 466 | case SYNCHRONIZE_CACHE_16: |
467 | if (!ops->execute_sync_cache) | 467 | if (!ops->execute_sync_cache) { |
468 | return TCM_UNSUPPORTED_SCSI_OPCODE; | 468 | size = 0; |
469 | cmd->execute_cmd = sbc_emulate_noop; | ||
470 | break; | ||
471 | } | ||
469 | 472 | ||
470 | /* | 473 | /* |
471 | * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE | 474 | * Extract LBA and range to be flushed for emulated SYNCHRONIZE_CACHE |
diff --git a/drivers/target/target_core_tpg.c b/drivers/target/target_core_tpg.c index 9169d6a5d7e4..aac9d2727e3c 100644 --- a/drivers/target/target_core_tpg.c +++ b/drivers/target/target_core_tpg.c | |||
@@ -711,7 +711,8 @@ int core_tpg_register( | |||
711 | 711 | ||
712 | if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) { | 712 | if (se_tpg->se_tpg_type == TRANSPORT_TPG_TYPE_NORMAL) { |
713 | if (core_tpg_setup_virtual_lun0(se_tpg) < 0) { | 713 | if (core_tpg_setup_virtual_lun0(se_tpg) < 0) { |
714 | kfree(se_tpg); | 714 | array_free(se_tpg->tpg_lun_list, |
715 | TRANSPORT_MAX_LUNS_PER_TPG); | ||
715 | return -ENOMEM; | 716 | return -ENOMEM; |
716 | } | 717 | } |
717 | } | 718 | } |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index 2030b608136d..3243ea790eab 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -1139,8 +1139,10 @@ target_setup_cmd_from_cdb(struct se_cmd *cmd, unsigned char *cdb) | |||
1139 | return ret; | 1139 | return ret; |
1140 | 1140 | ||
1141 | ret = target_check_reservation(cmd); | 1141 | ret = target_check_reservation(cmd); |
1142 | if (ret) | 1142 | if (ret) { |
1143 | cmd->scsi_status = SAM_STAT_RESERVATION_CONFLICT; | ||
1143 | return ret; | 1144 | return ret; |
1145 | } | ||
1144 | 1146 | ||
1145 | ret = dev->transport->parse_cdb(cmd); | 1147 | ret = dev->transport->parse_cdb(cmd); |
1146 | if (ret) | 1148 | if (ret) |
diff --git a/drivers/thermal/dove_thermal.c b/drivers/thermal/dove_thermal.c index 7b0bfa0e7a9c..3078c403b42d 100644 --- a/drivers/thermal/dove_thermal.c +++ b/drivers/thermal/dove_thermal.c | |||
@@ -143,22 +143,18 @@ static int dove_thermal_probe(struct platform_device *pdev) | |||
143 | if (!priv) | 143 | if (!priv) |
144 | return -ENOMEM; | 144 | return -ENOMEM; |
145 | 145 | ||
146 | priv->sensor = devm_request_and_ioremap(&pdev->dev, res); | 146 | priv->sensor = devm_ioremap_resource(&pdev->dev, res); |
147 | if (!priv->sensor) { | 147 | if (IS_ERR(priv->sensor)) |
148 | dev_err(&pdev->dev, "Failed to request_ioremap memory\n"); | 148 | return PTR_ERR(priv->sensor); |
149 | return -EADDRNOTAVAIL; | ||
150 | } | ||
151 | 149 | ||
152 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 150 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
153 | if (!res) { | 151 | if (!res) { |
154 | dev_err(&pdev->dev, "Failed to get platform resource\n"); | 152 | dev_err(&pdev->dev, "Failed to get platform resource\n"); |
155 | return -ENODEV; | 153 | return -ENODEV; |
156 | } | 154 | } |
157 | priv->control = devm_request_and_ioremap(&pdev->dev, res); | 155 | priv->control = devm_ioremap_resource(&pdev->dev, res); |
158 | if (!priv->control) { | 156 | if (IS_ERR(priv->control)) |
159 | dev_err(&pdev->dev, "Failed to request_ioremap memory\n"); | 157 | return PTR_ERR(priv->control); |
160 | return -EADDRNOTAVAIL; | ||
161 | } | ||
162 | 158 | ||
163 | ret = dove_init_sensor(priv); | 159 | ret = dove_init_sensor(priv); |
164 | if (ret) { | 160 | if (ret) { |
diff --git a/drivers/thermal/exynos_thermal.c b/drivers/thermal/exynos_thermal.c index e04ebd8671ac..46568c078dee 100644 --- a/drivers/thermal/exynos_thermal.c +++ b/drivers/thermal/exynos_thermal.c | |||
@@ -476,7 +476,7 @@ static int exynos_register_thermal(struct thermal_sensor_conf *sensor_conf) | |||
476 | 476 | ||
477 | if (IS_ERR(th_zone->therm_dev)) { | 477 | if (IS_ERR(th_zone->therm_dev)) { |
478 | pr_err("Failed to register thermal zone device\n"); | 478 | pr_err("Failed to register thermal zone device\n"); |
479 | ret = -EINVAL; | 479 | ret = PTR_ERR(th_zone->therm_dev); |
480 | goto err_unregister; | 480 | goto err_unregister; |
481 | } | 481 | } |
482 | th_zone->mode = THERMAL_DEVICE_ENABLED; | 482 | th_zone->mode = THERMAL_DEVICE_ENABLED; |
diff --git a/drivers/thermal/kirkwood_thermal.c b/drivers/thermal/kirkwood_thermal.c index 65cb4f09e8f6..e5500edb5285 100644 --- a/drivers/thermal/kirkwood_thermal.c +++ b/drivers/thermal/kirkwood_thermal.c | |||
@@ -85,11 +85,9 @@ static int kirkwood_thermal_probe(struct platform_device *pdev) | |||
85 | if (!priv) | 85 | if (!priv) |
86 | return -ENOMEM; | 86 | return -ENOMEM; |
87 | 87 | ||
88 | priv->sensor = devm_request_and_ioremap(&pdev->dev, res); | 88 | priv->sensor = devm_ioremap_resource(&pdev->dev, res); |
89 | if (!priv->sensor) { | 89 | if (IS_ERR(priv->sensor)) |
90 | dev_err(&pdev->dev, "Failed to request_ioremap memory\n"); | 90 | return PTR_ERR(priv->sensor); |
91 | return -EADDRNOTAVAIL; | ||
92 | } | ||
93 | 91 | ||
94 | thermal = thermal_zone_device_register("kirkwood_thermal", 0, 0, | 92 | thermal = thermal_zone_device_register("kirkwood_thermal", 0, 0, |
95 | priv, &ops, NULL, 0, 0); | 93 | priv, &ops, NULL, 0, 0); |
diff --git a/drivers/thermal/rcar_thermal.c b/drivers/thermal/rcar_thermal.c index 28f091994013..2cc5b6115e3e 100644 --- a/drivers/thermal/rcar_thermal.c +++ b/drivers/thermal/rcar_thermal.c | |||
@@ -145,6 +145,7 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) | |||
145 | struct device *dev = rcar_priv_to_dev(priv); | 145 | struct device *dev = rcar_priv_to_dev(priv); |
146 | int i; | 146 | int i; |
147 | int ctemp, old, new; | 147 | int ctemp, old, new; |
148 | int ret = -EINVAL; | ||
148 | 149 | ||
149 | mutex_lock(&priv->lock); | 150 | mutex_lock(&priv->lock); |
150 | 151 | ||
@@ -174,7 +175,7 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) | |||
174 | 175 | ||
175 | if (!ctemp) { | 176 | if (!ctemp) { |
176 | dev_err(dev, "thermal sensor was broken\n"); | 177 | dev_err(dev, "thermal sensor was broken\n"); |
177 | return -EINVAL; | 178 | goto err_out_unlock; |
178 | } | 179 | } |
179 | 180 | ||
180 | /* | 181 | /* |
@@ -192,10 +193,10 @@ static int rcar_thermal_update_temp(struct rcar_thermal_priv *priv) | |||
192 | dev_dbg(dev, "thermal%d %d -> %d\n", priv->id, priv->ctemp, ctemp); | 193 | dev_dbg(dev, "thermal%d %d -> %d\n", priv->id, priv->ctemp, ctemp); |
193 | 194 | ||
194 | priv->ctemp = ctemp; | 195 | priv->ctemp = ctemp; |
195 | 196 | ret = 0; | |
197 | err_out_unlock: | ||
196 | mutex_unlock(&priv->lock); | 198 | mutex_unlock(&priv->lock); |
197 | 199 | return ret; | |
198 | return 0; | ||
199 | } | 200 | } |
200 | 201 | ||
201 | static int rcar_thermal_get_temp(struct thermal_zone_device *zone, | 202 | static int rcar_thermal_get_temp(struct thermal_zone_device *zone, |
@@ -363,6 +364,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
363 | struct resource *res, *irq; | 364 | struct resource *res, *irq; |
364 | int mres = 0; | 365 | int mres = 0; |
365 | int i; | 366 | int i; |
367 | int ret = -ENODEV; | ||
366 | int idle = IDLE_INTERVAL; | 368 | int idle = IDLE_INTERVAL; |
367 | 369 | ||
368 | common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL); | 370 | common = devm_kzalloc(dev, sizeof(*common), GFP_KERNEL); |
@@ -399,11 +401,9 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
399 | /* | 401 | /* |
400 | * rcar_has_irq_support() will be enabled | 402 | * rcar_has_irq_support() will be enabled |
401 | */ | 403 | */ |
402 | common->base = devm_request_and_ioremap(dev, res); | 404 | common->base = devm_ioremap_resource(dev, res); |
403 | if (!common->base) { | 405 | if (IS_ERR(common->base)) |
404 | dev_err(dev, "Unable to ioremap thermal register\n"); | 406 | return PTR_ERR(common->base); |
405 | return -ENOMEM; | ||
406 | } | ||
407 | 407 | ||
408 | /* enable temperature comparation */ | 408 | /* enable temperature comparation */ |
409 | rcar_thermal_common_write(common, ENR, 0x00030303); | 409 | rcar_thermal_common_write(common, ENR, 0x00030303); |
@@ -422,11 +422,9 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
422 | return -ENOMEM; | 422 | return -ENOMEM; |
423 | } | 423 | } |
424 | 424 | ||
425 | priv->base = devm_request_and_ioremap(dev, res); | 425 | priv->base = devm_ioremap_resource(dev, res); |
426 | if (!priv->base) { | 426 | if (IS_ERR(priv->base)) |
427 | dev_err(dev, "Unable to ioremap priv register\n"); | 427 | return PTR_ERR(priv->base); |
428 | return -ENOMEM; | ||
429 | } | ||
430 | 428 | ||
431 | priv->common = common; | 429 | priv->common = common; |
432 | priv->id = i; | 430 | priv->id = i; |
@@ -441,6 +439,7 @@ static int rcar_thermal_probe(struct platform_device *pdev) | |||
441 | idle); | 439 | idle); |
442 | if (IS_ERR(priv->zone)) { | 440 | if (IS_ERR(priv->zone)) { |
443 | dev_err(dev, "can't register thermal zone\n"); | 441 | dev_err(dev, "can't register thermal zone\n"); |
442 | ret = PTR_ERR(priv->zone); | ||
444 | goto error_unregister; | 443 | goto error_unregister; |
445 | } | 444 | } |
446 | 445 | ||
@@ -460,7 +459,7 @@ error_unregister: | |||
460 | rcar_thermal_for_each_priv(priv, common) | 459 | rcar_thermal_for_each_priv(priv, common) |
461 | thermal_zone_device_unregister(priv->zone); | 460 | thermal_zone_device_unregister(priv->zone); |
462 | 461 | ||
463 | return -ENODEV; | 462 | return ret; |
464 | } | 463 | } |
465 | 464 | ||
466 | static int rcar_thermal_remove(struct platform_device *pdev) | 465 | static int rcar_thermal_remove(struct platform_device *pdev) |
diff --git a/drivers/tty/hvc/hvcs.c b/drivers/tty/hvc/hvcs.c index 1956593ee89d..81e939e90c4c 100644 --- a/drivers/tty/hvc/hvcs.c +++ b/drivers/tty/hvc/hvcs.c | |||
@@ -881,17 +881,12 @@ static struct vio_driver hvcs_vio_driver = { | |||
881 | /* Only called from hvcs_get_pi please */ | 881 | /* Only called from hvcs_get_pi please */ |
882 | static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd) | 882 | static void hvcs_set_pi(struct hvcs_partner_info *pi, struct hvcs_struct *hvcsd) |
883 | { | 883 | { |
884 | int clclength; | ||
885 | |||
886 | hvcsd->p_unit_address = pi->unit_address; | 884 | hvcsd->p_unit_address = pi->unit_address; |
887 | hvcsd->p_partition_ID = pi->partition_ID; | 885 | hvcsd->p_partition_ID = pi->partition_ID; |
888 | clclength = strlen(&pi->location_code[0]); | ||
889 | if (clclength > HVCS_CLC_LENGTH) | ||
890 | clclength = HVCS_CLC_LENGTH; | ||
891 | 886 | ||
892 | /* copy the null-term char too */ | 887 | /* copy the null-term char too */ |
893 | strncpy(&hvcsd->p_location_code[0], | 888 | strlcpy(&hvcsd->p_location_code[0], |
894 | &pi->location_code[0], clclength + 1); | 889 | &pi->location_code[0], sizeof(hvcsd->p_location_code)); |
895 | } | 890 | } |
896 | 891 | ||
897 | /* | 892 | /* |
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250_core.c index 0efc815a4968..35f9c96aada9 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250_core.c | |||
@@ -301,7 +301,28 @@ static const struct serial8250_config uart_config[] = { | |||
301 | }, | 301 | }, |
302 | [PORT_8250_CIR] = { | 302 | [PORT_8250_CIR] = { |
303 | .name = "CIR port" | 303 | .name = "CIR port" |
304 | } | 304 | }, |
305 | [PORT_ALTR_16550_F32] = { | ||
306 | .name = "Altera 16550 FIFO32", | ||
307 | .fifo_size = 32, | ||
308 | .tx_loadsz = 32, | ||
309 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
310 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | ||
311 | }, | ||
312 | [PORT_ALTR_16550_F64] = { | ||
313 | .name = "Altera 16550 FIFO64", | ||
314 | .fifo_size = 64, | ||
315 | .tx_loadsz = 64, | ||
316 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
317 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | ||
318 | }, | ||
319 | [PORT_ALTR_16550_F128] = { | ||
320 | .name = "Altera 16550 FIFO128", | ||
321 | .fifo_size = 128, | ||
322 | .tx_loadsz = 128, | ||
323 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | ||
324 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | ||
325 | }, | ||
305 | }; | 326 | }; |
306 | 327 | ||
307 | /* Uart divisor latch read */ | 328 | /* Uart divisor latch read */ |
@@ -3396,3 +3417,34 @@ module_param_array(probe_rsa, ulong, &probe_rsa_count, 0444); | |||
3396 | MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); | 3417 | MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA"); |
3397 | #endif | 3418 | #endif |
3398 | MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); | 3419 | MODULE_ALIAS_CHARDEV_MAJOR(TTY_MAJOR); |
3420 | |||
3421 | #ifdef CONFIG_SERIAL_8250_DEPRECATED_OPTIONS | ||
3422 | #ifndef MODULE | ||
3423 | /* This module was renamed to 8250_core in 3.7. Keep the old "8250" name | ||
3424 | * working as well for the module options so we don't break people. We | ||
3425 | * need to keep the names identical and the convenient macros will happily | ||
3426 | * refuse to let us do that by failing the build with redefinition errors | ||
3427 | * of global variables. So we stick them inside a dummy function to avoid | ||
3428 | * those conflicts. The options still get parsed, and the redefined | ||
3429 | * MODULE_PARAM_PREFIX lets us keep the "8250." syntax alive. | ||
3430 | * | ||
3431 | * This is hacky. I'm sorry. | ||
3432 | */ | ||
3433 | static void __used s8250_options(void) | ||
3434 | { | ||
3435 | #undef MODULE_PARAM_PREFIX | ||
3436 | #define MODULE_PARAM_PREFIX "8250_core." | ||
3437 | |||
3438 | module_param_cb(share_irqs, ¶m_ops_uint, &share_irqs, 0644); | ||
3439 | module_param_cb(nr_uarts, ¶m_ops_uint, &nr_uarts, 0644); | ||
3440 | module_param_cb(skip_txen_test, ¶m_ops_uint, &skip_txen_test, 0644); | ||
3441 | #ifdef CONFIG_SERIAL_8250_RSA | ||
3442 | __module_param_call(MODULE_PARAM_PREFIX, probe_rsa, | ||
3443 | ¶m_array_ops, .arr = &__param_arr_probe_rsa, | ||
3444 | 0444, -1); | ||
3445 | #endif | ||
3446 | } | ||
3447 | #else | ||
3448 | MODULE_ALIAS("8250_core"); | ||
3449 | #endif | ||
3450 | #endif | ||
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 791c5a77ec61..26e3a97ab157 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -1554,6 +1554,7 @@ pci_wch_ch353_setup(struct serial_private *priv, | |||
1554 | #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 | 1554 | #define PCI_DEVICE_ID_PLX_CRONYX_OMEGA 0xc001 |
1555 | #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d | 1555 | #define PCI_DEVICE_ID_INTEL_PATSBURG_KT 0x1d3d |
1556 | #define PCI_VENDOR_ID_WCH 0x4348 | 1556 | #define PCI_VENDOR_ID_WCH 0x4348 |
1557 | #define PCI_DEVICE_ID_WCH_CH352_2S 0x3253 | ||
1557 | #define PCI_DEVICE_ID_WCH_CH353_4S 0x3453 | 1558 | #define PCI_DEVICE_ID_WCH_CH353_4S 0x3453 |
1558 | #define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046 | 1559 | #define PCI_DEVICE_ID_WCH_CH353_2S1PF 0x5046 |
1559 | #define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053 | 1560 | #define PCI_DEVICE_ID_WCH_CH353_2S1P 0x7053 |
@@ -1571,6 +1572,7 @@ pci_wch_ch353_setup(struct serial_private *priv, | |||
1571 | 1572 | ||
1572 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ | 1573 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
1573 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 | 1574 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1584 0x1584 |
1575 | #define PCI_SUBDEVICE_ID_UNKNOWN_0x1588 0x1588 | ||
1574 | 1576 | ||
1575 | /* | 1577 | /* |
1576 | * Master list of serial port init/setup/exit quirks. | 1578 | * Master list of serial port init/setup/exit quirks. |
@@ -1852,15 +1854,6 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1852 | }, | 1854 | }, |
1853 | { | 1855 | { |
1854 | .vendor = PCI_VENDOR_ID_PLX, | 1856 | .vendor = PCI_VENDOR_ID_PLX, |
1855 | .device = PCI_DEVICE_ID_PLX_9050, | ||
1856 | .subvendor = PCI_VENDOR_ID_PLX, | ||
1857 | .subdevice = PCI_SUBDEVICE_ID_UNKNOWN_0x1584, | ||
1858 | .init = pci_plx9050_init, | ||
1859 | .setup = pci_default_setup, | ||
1860 | .exit = pci_plx9050_exit, | ||
1861 | }, | ||
1862 | { | ||
1863 | .vendor = PCI_VENDOR_ID_PLX, | ||
1864 | .device = PCI_DEVICE_ID_PLX_ROMULUS, | 1857 | .device = PCI_DEVICE_ID_PLX_ROMULUS, |
1865 | .subvendor = PCI_VENDOR_ID_PLX, | 1858 | .subvendor = PCI_VENDOR_ID_PLX, |
1866 | .subdevice = PCI_DEVICE_ID_PLX_ROMULUS, | 1859 | .subdevice = PCI_DEVICE_ID_PLX_ROMULUS, |
@@ -2180,6 +2173,14 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
2180 | .subdevice = PCI_ANY_ID, | 2173 | .subdevice = PCI_ANY_ID, |
2181 | .setup = pci_wch_ch353_setup, | 2174 | .setup = pci_wch_ch353_setup, |
2182 | }, | 2175 | }, |
2176 | /* WCH CH352 2S card (16550 clone) */ | ||
2177 | { | ||
2178 | .vendor = PCI_VENDOR_ID_WCH, | ||
2179 | .device = PCI_DEVICE_ID_WCH_CH352_2S, | ||
2180 | .subvendor = PCI_ANY_ID, | ||
2181 | .subdevice = PCI_ANY_ID, | ||
2182 | .setup = pci_wch_ch353_setup, | ||
2183 | }, | ||
2183 | /* | 2184 | /* |
2184 | * ASIX devices with FIFO bug | 2185 | * ASIX devices with FIFO bug |
2185 | */ | 2186 | */ |
@@ -3733,7 +3734,12 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
3733 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, | 3734 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, |
3734 | PCI_VENDOR_ID_PLX, | 3735 | PCI_VENDOR_ID_PLX, |
3735 | PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0, | 3736 | PCI_SUBDEVICE_ID_UNKNOWN_0x1584, 0, 0, |
3736 | pbn_b0_4_115200 }, | 3737 | pbn_b2_4_115200 }, |
3738 | /* Unknown card - subdevice 0x1588 */ | ||
3739 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, | ||
3740 | PCI_VENDOR_ID_PLX, | ||
3741 | PCI_SUBDEVICE_ID_UNKNOWN_0x1588, 0, 0, | ||
3742 | pbn_b2_8_115200 }, | ||
3737 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, | 3743 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, |
3738 | PCI_SUBVENDOR_ID_KEYSPAN, | 3744 | PCI_SUBVENDOR_ID_KEYSPAN, |
3739 | PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, | 3745 | PCI_SUBDEVICE_ID_KEYSPAN_SX2, 0, 0, |
@@ -4791,6 +4797,10 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
4791 | PCI_VENDOR_ID_IBM, 0x0299, | 4797 | PCI_VENDOR_ID_IBM, 0x0299, |
4792 | 0, 0, pbn_b0_bt_2_115200 }, | 4798 | 0, 0, pbn_b0_bt_2_115200 }, |
4793 | 4799 | ||
4800 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9835, | ||
4801 | 0x1000, 0x0012, | ||
4802 | 0, 0, pbn_b0_bt_2_115200 }, | ||
4803 | |||
4794 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, | 4804 | { PCI_VENDOR_ID_NETMOS, PCI_DEVICE_ID_NETMOS_9901, |
4795 | 0xA000, 0x1000, | 4805 | 0xA000, 0x1000, |
4796 | 0, 0, pbn_b0_1_115200 }, | 4806 | 0, 0, pbn_b0_1_115200 }, |
@@ -4869,6 +4879,10 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
4869 | PCI_ANY_ID, PCI_ANY_ID, | 4879 | PCI_ANY_ID, PCI_ANY_ID, |
4870 | 0, 0, pbn_b0_bt_2_115200 }, | 4880 | 0, 0, pbn_b0_bt_2_115200 }, |
4871 | 4881 | ||
4882 | { PCI_VENDOR_ID_WCH, PCI_DEVICE_ID_WCH_CH352_2S, | ||
4883 | PCI_ANY_ID, PCI_ANY_ID, | ||
4884 | 0, 0, pbn_b0_bt_2_115200 }, | ||
4885 | |||
4872 | /* | 4886 | /* |
4873 | * Commtech, Inc. Fastcom adapters | 4887 | * Commtech, Inc. Fastcom adapters |
4874 | */ | 4888 | */ |
diff --git a/drivers/tty/serial/8250/8250_pnp.c b/drivers/tty/serial/8250/8250_pnp.c index 35d9ab95c5cb..b3455a970a1d 100644 --- a/drivers/tty/serial/8250/8250_pnp.c +++ b/drivers/tty/serial/8250/8250_pnp.c | |||
@@ -429,6 +429,7 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) | |||
429 | { | 429 | { |
430 | struct uart_8250_port uart; | 430 | struct uart_8250_port uart; |
431 | int ret, line, flags = dev_id->driver_data; | 431 | int ret, line, flags = dev_id->driver_data; |
432 | struct resource *res = NULL; | ||
432 | 433 | ||
433 | if (flags & UNKNOWN_DEV) { | 434 | if (flags & UNKNOWN_DEV) { |
434 | ret = serial_pnp_guess_board(dev); | 435 | ret = serial_pnp_guess_board(dev); |
@@ -439,11 +440,12 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) | |||
439 | memset(&uart, 0, sizeof(uart)); | 440 | memset(&uart, 0, sizeof(uart)); |
440 | if (pnp_irq_valid(dev, 0)) | 441 | if (pnp_irq_valid(dev, 0)) |
441 | uart.port.irq = pnp_irq(dev, 0); | 442 | uart.port.irq = pnp_irq(dev, 0); |
442 | if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) { | 443 | if ((flags & CIR_PORT) && pnp_port_valid(dev, 2)) |
443 | uart.port.iobase = pnp_port_start(dev, 2); | 444 | res = pnp_get_resource(dev, IORESOURCE_IO, 2); |
444 | uart.port.iotype = UPIO_PORT; | 445 | else if (pnp_port_valid(dev, 0)) |
445 | } else if (pnp_port_valid(dev, 0)) { | 446 | res = pnp_get_resource(dev, IORESOURCE_IO, 0); |
446 | uart.port.iobase = pnp_port_start(dev, 0); | 447 | if (pnp_resource_enabled(res)) { |
448 | uart.port.iobase = res->start; | ||
447 | uart.port.iotype = UPIO_PORT; | 449 | uart.port.iotype = UPIO_PORT; |
448 | } else if (pnp_mem_valid(dev, 0)) { | 450 | } else if (pnp_mem_valid(dev, 0)) { |
449 | uart.port.mapbase = pnp_mem_start(dev, 0); | 451 | uart.port.mapbase = pnp_mem_start(dev, 0); |
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig index 2ef9537bcb2c..80fe91e64a52 100644 --- a/drivers/tty/serial/8250/Kconfig +++ b/drivers/tty/serial/8250/Kconfig | |||
@@ -33,6 +33,23 @@ config SERIAL_8250 | |||
33 | Most people will say Y or M here, so that they can use serial mice, | 33 | Most people will say Y or M here, so that they can use serial mice, |
34 | modems and similar devices connecting to the standard serial ports. | 34 | modems and similar devices connecting to the standard serial ports. |
35 | 35 | ||
36 | config SERIAL_8250_DEPRECATED_OPTIONS | ||
37 | bool "Support 8250_core.* kernel options (DEPRECATED)" | ||
38 | depends on SERIAL_8250 | ||
39 | default y | ||
40 | ---help--- | ||
41 | In 3.7 we renamed 8250 to 8250_core by mistake, so now we have to | ||
42 | accept kernel parameters in both forms like 8250_core.nr_uarts=4 and | ||
43 | 8250.nr_uarts=4. We now renamed the module back to 8250, but if | ||
44 | anybody noticed in 3.7 and changed their userspace we still have to | ||
45 | keep the 8350_core.* options around until they revert the changes | ||
46 | they already did. | ||
47 | |||
48 | If 8250 is built as a module, this adds 8250_core alias instead. | ||
49 | |||
50 | If you did not notice yet and/or you have userspace from pre-3.7, it | ||
51 | is safe (and recommended) to say N here. | ||
52 | |||
36 | config SERIAL_8250_PNP | 53 | config SERIAL_8250_PNP |
37 | bool "8250/16550 PNP device support" if EXPERT | 54 | bool "8250/16550 PNP device support" if EXPERT |
38 | depends on SERIAL_8250 && PNP | 55 | depends on SERIAL_8250 && PNP |
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile index a23838a4d535..36d68d054307 100644 --- a/drivers/tty/serial/8250/Makefile +++ b/drivers/tty/serial/8250/Makefile | |||
@@ -2,10 +2,10 @@ | |||
2 | # Makefile for the 8250 serial device drivers. | 2 | # Makefile for the 8250 serial device drivers. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_SERIAL_8250) += 8250_core.o | 5 | obj-$(CONFIG_SERIAL_8250) += 8250.o |
6 | 8250_core-y := 8250.o | 6 | 8250-y := 8250_core.o |
7 | 8250_core-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o | 7 | 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o |
8 | 8250_core-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o | 8 | 8250-$(CONFIG_SERIAL_8250_DMA) += 8250_dma.o |
9 | obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o | 9 | obj-$(CONFIG_SERIAL_8250_GSC) += 8250_gsc.o |
10 | obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o | 10 | obj-$(CONFIG_SERIAL_8250_PCI) += 8250_pci.o |
11 | obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o | 11 | obj-$(CONFIG_SERIAL_8250_HP300) += 8250_hp300.o |
diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index cf9210db9fa9..7e7006fd404e 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig | |||
@@ -211,14 +211,14 @@ config SERIAL_SAMSUNG | |||
211 | config SERIAL_SAMSUNG_UARTS_4 | 211 | config SERIAL_SAMSUNG_UARTS_4 |
212 | bool | 212 | bool |
213 | depends on PLAT_SAMSUNG | 213 | depends on PLAT_SAMSUNG |
214 | default y if !(CPU_S3C2410 || SERIAL_S3C2412 || CPU_S3C2440 || CPU_S3C2442) | 214 | default y if !(CPU_S3C2410 || CPU_S3C2412 || CPU_S3C2440 || CPU_S3C2442) |
215 | help | 215 | help |
216 | Internal node for the common case of 4 Samsung compatible UARTs | 216 | Internal node for the common case of 4 Samsung compatible UARTs |
217 | 217 | ||
218 | config SERIAL_SAMSUNG_UARTS | 218 | config SERIAL_SAMSUNG_UARTS |
219 | int | 219 | int |
220 | depends on PLAT_SAMSUNG | 220 | depends on PLAT_SAMSUNG |
221 | default 6 if ARCH_S5P6450 | 221 | default 6 if CPU_S5P6450 |
222 | default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416 | 222 | default 4 if SERIAL_SAMSUNG_UARTS_4 || CPU_S3C2416 |
223 | default 3 | 223 | default 3 |
224 | help | 224 | help |
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c index d4a7c241b751..3467462869ce 100644 --- a/drivers/tty/serial/atmel_serial.c +++ b/drivers/tty/serial/atmel_serial.c | |||
@@ -158,7 +158,7 @@ struct atmel_uart_port { | |||
158 | }; | 158 | }; |
159 | 159 | ||
160 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; | 160 | static struct atmel_uart_port atmel_ports[ATMEL_MAX_UART]; |
161 | static unsigned long atmel_ports_in_use; | 161 | static DECLARE_BITMAP(atmel_ports_in_use, ATMEL_MAX_UART); |
162 | 162 | ||
163 | #ifdef SUPPORT_SYSRQ | 163 | #ifdef SUPPORT_SYSRQ |
164 | static struct console atmel_console; | 164 | static struct console atmel_console; |
@@ -1769,15 +1769,14 @@ static int atmel_serial_probe(struct platform_device *pdev) | |||
1769 | if (ret < 0) | 1769 | if (ret < 0) |
1770 | /* port id not found in platform data nor device-tree aliases: | 1770 | /* port id not found in platform data nor device-tree aliases: |
1771 | * auto-enumerate it */ | 1771 | * auto-enumerate it */ |
1772 | ret = find_first_zero_bit(&atmel_ports_in_use, | 1772 | ret = find_first_zero_bit(atmel_ports_in_use, ATMEL_MAX_UART); |
1773 | sizeof(atmel_ports_in_use)); | ||
1774 | 1773 | ||
1775 | if (ret > ATMEL_MAX_UART) { | 1774 | if (ret >= ATMEL_MAX_UART) { |
1776 | ret = -ENODEV; | 1775 | ret = -ENODEV; |
1777 | goto err; | 1776 | goto err; |
1778 | } | 1777 | } |
1779 | 1778 | ||
1780 | if (test_and_set_bit(ret, &atmel_ports_in_use)) { | 1779 | if (test_and_set_bit(ret, atmel_ports_in_use)) { |
1781 | /* port already in use */ | 1780 | /* port already in use */ |
1782 | ret = -EBUSY; | 1781 | ret = -EBUSY; |
1783 | goto err; | 1782 | goto err; |
@@ -1857,7 +1856,7 @@ static int atmel_serial_remove(struct platform_device *pdev) | |||
1857 | 1856 | ||
1858 | /* "port" is allocated statically, so we shouldn't free it */ | 1857 | /* "port" is allocated statically, so we shouldn't free it */ |
1859 | 1858 | ||
1860 | clear_bit(port->line, &atmel_ports_in_use); | 1859 | clear_bit(port->line, atmel_ports_in_use); |
1861 | 1860 | ||
1862 | clk_put(atmel_port->clk); | 1861 | clk_put(atmel_port->clk); |
1863 | 1862 | ||
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c index 719594e5fc21..52a3ecd40421 100644 --- a/drivers/tty/serial/bcm63xx_uart.c +++ b/drivers/tty/serial/bcm63xx_uart.c | |||
@@ -235,7 +235,7 @@ static const char *bcm_uart_type(struct uart_port *port) | |||
235 | */ | 235 | */ |
236 | static void bcm_uart_do_rx(struct uart_port *port) | 236 | static void bcm_uart_do_rx(struct uart_port *port) |
237 | { | 237 | { |
238 | struct tty_port *port = &port->state->port; | 238 | struct tty_port *tty_port = &port->state->port; |
239 | unsigned int max_count; | 239 | unsigned int max_count; |
240 | 240 | ||
241 | /* limit number of char read in interrupt, should not be | 241 | /* limit number of char read in interrupt, should not be |
@@ -260,7 +260,7 @@ static void bcm_uart_do_rx(struct uart_port *port) | |||
260 | bcm_uart_writel(port, val, UART_CTL_REG); | 260 | bcm_uart_writel(port, val, UART_CTL_REG); |
261 | 261 | ||
262 | port->icount.overrun++; | 262 | port->icount.overrun++; |
263 | tty_insert_flip_char(port, 0, TTY_OVERRUN); | 263 | tty_insert_flip_char(tty_port, 0, TTY_OVERRUN); |
264 | } | 264 | } |
265 | 265 | ||
266 | if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY))) | 266 | if (!(iestat & UART_IR_STAT(UART_IR_RXNOTEMPTY))) |
@@ -299,11 +299,11 @@ static void bcm_uart_do_rx(struct uart_port *port) | |||
299 | 299 | ||
300 | 300 | ||
301 | if ((cstat & port->ignore_status_mask) == 0) | 301 | if ((cstat & port->ignore_status_mask) == 0) |
302 | tty_insert_flip_char(port, c, flag); | 302 | tty_insert_flip_char(tty_port, c, flag); |
303 | 303 | ||
304 | } while (--max_count); | 304 | } while (--max_count); |
305 | 305 | ||
306 | tty_flip_buffer_push(port); | 306 | tty_flip_buffer_push(tty_port); |
307 | } | 307 | } |
308 | 308 | ||
309 | /* | 309 | /* |
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c index c0e1fad51be7..018bad922554 100644 --- a/drivers/tty/serial/mpc52xx_uart.c +++ b/drivers/tty/serial/mpc52xx_uart.c | |||
@@ -550,7 +550,7 @@ static int mpc512x_psc_clock(struct uart_port *port, int enable) | |||
550 | return 0; | 550 | return 0; |
551 | 551 | ||
552 | psc_num = (port->mapbase & 0xf00) >> 8; | 552 | psc_num = (port->mapbase & 0xf00) >> 8; |
553 | snprintf(clk_name, sizeof(clk_name), "psc%d_clk", psc_num); | 553 | snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num); |
554 | psc_clk = clk_get(port->dev, clk_name); | 554 | psc_clk = clk_get(port->dev, clk_name); |
555 | if (IS_ERR(psc_clk)) { | 555 | if (IS_ERR(psc_clk)) { |
556 | dev_err(port->dev, "Failed to get PSC clock entry!\n"); | 556 | dev_err(port->dev, "Failed to get PSC clock entry!\n"); |
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c index d5874605682b..b025d5438275 100644 --- a/drivers/tty/serial/of_serial.c +++ b/drivers/tty/serial/of_serial.c | |||
@@ -241,6 +241,12 @@ static struct of_device_id of_platform_serial_table[] = { | |||
241 | { .compatible = "ns16850", .data = (void *)PORT_16850, }, | 241 | { .compatible = "ns16850", .data = (void *)PORT_16850, }, |
242 | { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, | 242 | { .compatible = "nvidia,tegra20-uart", .data = (void *)PORT_TEGRA, }, |
243 | { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, | 243 | { .compatible = "nxp,lpc3220-uart", .data = (void *)PORT_LPC3220, }, |
244 | { .compatible = "altr,16550-FIFO32", | ||
245 | .data = (void *)PORT_ALTR_16550_F32, }, | ||
246 | { .compatible = "altr,16550-FIFO64", | ||
247 | .data = (void *)PORT_ALTR_16550_F64, }, | ||
248 | { .compatible = "altr,16550-FIFO128", | ||
249 | .data = (void *)PORT_ALTR_16550_F128, }, | ||
244 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL | 250 | #ifdef CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL |
245 | { .compatible = "ibm,qpace-nwp-serial", | 251 | { .compatible = "ibm,qpace-nwp-serial", |
246 | .data = (void *)PORT_NWPSERIAL, }, | 252 | .data = (void *)PORT_NWPSERIAL, }, |
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c index e343d6670854..451687cb9685 100644 --- a/drivers/tty/serial/sunsu.c +++ b/drivers/tty/serial/sunsu.c | |||
@@ -968,6 +968,7 @@ static struct uart_ops sunsu_pops = { | |||
968 | #define UART_NR 4 | 968 | #define UART_NR 4 |
969 | 969 | ||
970 | static struct uart_sunsu_port sunsu_ports[UART_NR]; | 970 | static struct uart_sunsu_port sunsu_ports[UART_NR]; |
971 | static int nr_inst; /* Number of already registered ports */ | ||
971 | 972 | ||
972 | #ifdef CONFIG_SERIO | 973 | #ifdef CONFIG_SERIO |
973 | 974 | ||
@@ -1337,13 +1338,8 @@ static int __init sunsu_console_setup(struct console *co, char *options) | |||
1337 | printk("Console: ttyS%d (SU)\n", | 1338 | printk("Console: ttyS%d (SU)\n", |
1338 | (sunsu_reg.minor - 64) + co->index); | 1339 | (sunsu_reg.minor - 64) + co->index); |
1339 | 1340 | ||
1340 | /* | 1341 | if (co->index > nr_inst) |
1341 | * Check whether an invalid uart number has been specified, and | 1342 | return -ENODEV; |
1342 | * if so, search for the first available port that does have | ||
1343 | * console support. | ||
1344 | */ | ||
1345 | if (co->index >= UART_NR) | ||
1346 | co->index = 0; | ||
1347 | port = &sunsu_ports[co->index].port; | 1343 | port = &sunsu_ports[co->index].port; |
1348 | 1344 | ||
1349 | /* | 1345 | /* |
@@ -1408,7 +1404,6 @@ static enum su_type su_get_type(struct device_node *dp) | |||
1408 | 1404 | ||
1409 | static int su_probe(struct platform_device *op) | 1405 | static int su_probe(struct platform_device *op) |
1410 | { | 1406 | { |
1411 | static int inst; | ||
1412 | struct device_node *dp = op->dev.of_node; | 1407 | struct device_node *dp = op->dev.of_node; |
1413 | struct uart_sunsu_port *up; | 1408 | struct uart_sunsu_port *up; |
1414 | struct resource *rp; | 1409 | struct resource *rp; |
@@ -1418,16 +1413,16 @@ static int su_probe(struct platform_device *op) | |||
1418 | 1413 | ||
1419 | type = su_get_type(dp); | 1414 | type = su_get_type(dp); |
1420 | if (type == SU_PORT_PORT) { | 1415 | if (type == SU_PORT_PORT) { |
1421 | if (inst >= UART_NR) | 1416 | if (nr_inst >= UART_NR) |
1422 | return -EINVAL; | 1417 | return -EINVAL; |
1423 | up = &sunsu_ports[inst]; | 1418 | up = &sunsu_ports[nr_inst]; |
1424 | } else { | 1419 | } else { |
1425 | up = kzalloc(sizeof(*up), GFP_KERNEL); | 1420 | up = kzalloc(sizeof(*up), GFP_KERNEL); |
1426 | if (!up) | 1421 | if (!up) |
1427 | return -ENOMEM; | 1422 | return -ENOMEM; |
1428 | } | 1423 | } |
1429 | 1424 | ||
1430 | up->port.line = inst; | 1425 | up->port.line = nr_inst; |
1431 | 1426 | ||
1432 | spin_lock_init(&up->port.lock); | 1427 | spin_lock_init(&up->port.lock); |
1433 | 1428 | ||
@@ -1461,6 +1456,8 @@ static int su_probe(struct platform_device *op) | |||
1461 | } | 1456 | } |
1462 | dev_set_drvdata(&op->dev, up); | 1457 | dev_set_drvdata(&op->dev, up); |
1463 | 1458 | ||
1459 | nr_inst++; | ||
1460 | |||
1464 | return 0; | 1461 | return 0; |
1465 | } | 1462 | } |
1466 | 1463 | ||
@@ -1488,7 +1485,7 @@ static int su_probe(struct platform_device *op) | |||
1488 | 1485 | ||
1489 | dev_set_drvdata(&op->dev, up); | 1486 | dev_set_drvdata(&op->dev, up); |
1490 | 1487 | ||
1491 | inst++; | 1488 | nr_inst++; |
1492 | 1489 | ||
1493 | return 0; | 1490 | return 0; |
1494 | 1491 | ||
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index a3f9dd5c9dff..705240e6c4ec 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c | |||
@@ -611,14 +611,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) | |||
611 | vt8500_port->uart.dev = &pdev->dev; | 611 | vt8500_port->uart.dev = &pdev->dev; |
612 | vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; | 612 | vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; |
613 | 613 | ||
614 | vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); | 614 | vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); |
615 | if (!IS_ERR(vt8500_port->clk)) { | ||
616 | vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); | ||
617 | } else { | ||
618 | /* use the default of 24Mhz if not specified and warn */ | ||
619 | pr_warn("%s: serial clock source not specified\n", __func__); | ||
620 | vt8500_port->uart.uartclk = 24000000; | ||
621 | } | ||
622 | 615 | ||
623 | snprintf(vt8500_port->name, sizeof(vt8500_port->name), | 616 | snprintf(vt8500_port->name, sizeof(vt8500_port->name), |
624 | "VT8500 UART%d", pdev->id); | 617 | "VT8500 UART%d", pdev->id); |
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index ba451c7209fc..f36bbba1ac8b 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -578,6 +578,8 @@ static int xuartps_startup(struct uart_port *port) | |||
578 | /* Receive Timeout register is enabled with value of 10 */ | 578 | /* Receive Timeout register is enabled with value of 10 */ |
579 | xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); | 579 | xuartps_writel(10, XUARTPS_RXTOUT_OFFSET); |
580 | 580 | ||
581 | /* Clear out any pending interrupts before enabling them */ | ||
582 | xuartps_writel(xuartps_readl(XUARTPS_ISR_OFFSET), XUARTPS_ISR_OFFSET); | ||
581 | 583 | ||
582 | /* Set the Interrupt Registers with desired interrupts */ | 584 | /* Set the Interrupt Registers with desired interrupts */ |
583 | xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | | 585 | xuartps_writel(XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_PARITY | |
diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c index bb119934e76c..578aa7594b11 100644 --- a/drivers/tty/tty_buffer.c +++ b/drivers/tty/tty_buffer.c | |||
@@ -425,7 +425,7 @@ static void flush_to_ldisc(struct work_struct *work) | |||
425 | struct tty_ldisc *disc; | 425 | struct tty_ldisc *disc; |
426 | 426 | ||
427 | tty = port->itty; | 427 | tty = port->itty; |
428 | if (WARN_RATELIMIT(tty == NULL, "tty is NULL\n")) | 428 | if (tty == NULL) |
429 | return; | 429 | return; |
430 | 430 | ||
431 | disc = tty_ldisc_ref(tty); | 431 | disc = tty_ldisc_ref(tty); |
diff --git a/drivers/tty/vt/vc_screen.c b/drivers/tty/vt/vc_screen.c index e4ca345873c3..d7799deacb21 100644 --- a/drivers/tty/vt/vc_screen.c +++ b/drivers/tty/vt/vc_screen.c | |||
@@ -93,7 +93,7 @@ vcs_poll_data_free(struct vcs_poll_data *poll) | |||
93 | static struct vcs_poll_data * | 93 | static struct vcs_poll_data * |
94 | vcs_poll_data_get(struct file *file) | 94 | vcs_poll_data_get(struct file *file) |
95 | { | 95 | { |
96 | struct vcs_poll_data *poll = file->private_data; | 96 | struct vcs_poll_data *poll = file->private_data, *kill = NULL; |
97 | 97 | ||
98 | if (poll) | 98 | if (poll) |
99 | return poll; | 99 | return poll; |
@@ -122,10 +122,12 @@ vcs_poll_data_get(struct file *file) | |||
122 | file->private_data = poll; | 122 | file->private_data = poll; |
123 | } else { | 123 | } else { |
124 | /* someone else raced ahead of us */ | 124 | /* someone else raced ahead of us */ |
125 | vcs_poll_data_free(poll); | 125 | kill = poll; |
126 | poll = file->private_data; | 126 | poll = file->private_data; |
127 | } | 127 | } |
128 | spin_unlock(&file->f_lock); | 128 | spin_unlock(&file->f_lock); |
129 | if (kill) | ||
130 | vcs_poll_data_free(kill); | ||
129 | 131 | ||
130 | return poll; | 132 | return poll; |
131 | } | 133 | } |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index f5ed3d75fa5a..8f5ebced5df0 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
@@ -46,7 +46,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ | |||
46 | obj-$(CONFIG_USB_SERIAL) += serial/ | 46 | obj-$(CONFIG_USB_SERIAL) += serial/ |
47 | 47 | ||
48 | obj-$(CONFIG_USB) += misc/ | 48 | obj-$(CONFIG_USB) += misc/ |
49 | obj-$(CONFIG_USB_COMMON) += phy/ | 49 | obj-$(CONFIG_USB_OTG_UTILS) += phy/ |
50 | obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ | 50 | obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ |
51 | 51 | ||
52 | obj-$(CONFIG_USB_ATM) += atm/ | 52 | obj-$(CONFIG_USB_ATM) += atm/ |
diff --git a/drivers/usb/c67x00/c67x00-sched.c b/drivers/usb/c67x00/c67x00-sched.c index a03fbc15fa9c..aa491627a45b 100644 --- a/drivers/usb/c67x00/c67x00-sched.c +++ b/drivers/usb/c67x00/c67x00-sched.c | |||
@@ -100,7 +100,7 @@ struct c67x00_urb_priv { | |||
100 | #define TD_PIDEP_OFFSET 0x04 | 100 | #define TD_PIDEP_OFFSET 0x04 |
101 | #define TD_PIDEPMASK_PID 0xF0 | 101 | #define TD_PIDEPMASK_PID 0xF0 |
102 | #define TD_PIDEPMASK_EP 0x0F | 102 | #define TD_PIDEPMASK_EP 0x0F |
103 | #define TD_PORTLENMASK_DL 0x02FF | 103 | #define TD_PORTLENMASK_DL 0x03FF |
104 | #define TD_PORTLENMASK_PN 0xC000 | 104 | #define TD_PORTLENMASK_PN 0xC000 |
105 | 105 | ||
106 | #define TD_STATUS_OFFSET 0x07 | 106 | #define TD_STATUS_OFFSET 0x07 |
@@ -590,7 +590,7 @@ static int c67x00_create_td(struct c67x00_hcd *c67x00, struct urb *urb, | |||
590 | { | 590 | { |
591 | struct c67x00_td *td; | 591 | struct c67x00_td *td; |
592 | struct c67x00_urb_priv *urbp = urb->hcpriv; | 592 | struct c67x00_urb_priv *urbp = urb->hcpriv; |
593 | const __u8 active_flag = 1, retry_cnt = 1; | 593 | const __u8 active_flag = 1, retry_cnt = 3; |
594 | __u8 cmd = 0; | 594 | __u8 cmd = 0; |
595 | int tt = 0; | 595 | int tt = 0; |
596 | 596 | ||
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c index 2f45bba8561d..f64fbea1cf20 100644 --- a/drivers/usb/chipidea/udc.c +++ b/drivers/usb/chipidea/udc.c | |||
@@ -1767,7 +1767,7 @@ static int udc_start(struct ci13xxx *ci) | |||
1767 | goto put_transceiver; | 1767 | goto put_transceiver; |
1768 | } | 1768 | } |
1769 | 1769 | ||
1770 | retval = dbg_create_files(&ci->gadget.dev); | 1770 | retval = dbg_create_files(ci->dev); |
1771 | if (retval) | 1771 | if (retval) |
1772 | goto unreg_device; | 1772 | goto unreg_device; |
1773 | 1773 | ||
@@ -1796,7 +1796,7 @@ remove_trans: | |||
1796 | 1796 | ||
1797 | dev_err(dev, "error = %i\n", retval); | 1797 | dev_err(dev, "error = %i\n", retval); |
1798 | remove_dbg: | 1798 | remove_dbg: |
1799 | dbg_remove_files(&ci->gadget.dev); | 1799 | dbg_remove_files(ci->dev); |
1800 | unreg_device: | 1800 | unreg_device: |
1801 | device_unregister(&ci->gadget.dev); | 1801 | device_unregister(&ci->gadget.dev); |
1802 | put_transceiver: | 1802 | put_transceiver: |
@@ -1836,7 +1836,7 @@ static void udc_stop(struct ci13xxx *ci) | |||
1836 | if (ci->global_phy) | 1836 | if (ci->global_phy) |
1837 | usb_put_phy(ci->transceiver); | 1837 | usb_put_phy(ci->transceiver); |
1838 | } | 1838 | } |
1839 | dbg_remove_files(&ci->gadget.dev); | 1839 | dbg_remove_files(ci->dev); |
1840 | device_unregister(&ci->gadget.dev); | 1840 | device_unregister(&ci->gadget.dev); |
1841 | /* my kobject is dynamic, I swear! */ | 1841 | /* my kobject is dynamic, I swear! */ |
1842 | memset(&ci->gadget, 0, sizeof(ci->gadget)); | 1842 | memset(&ci->gadget, 0, sizeof(ci->gadget)); |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 8ac25adf31b4..387dc6c8ad25 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -593,7 +593,6 @@ static void acm_port_destruct(struct tty_port *port) | |||
593 | 593 | ||
594 | dev_dbg(&acm->control->dev, "%s\n", __func__); | 594 | dev_dbg(&acm->control->dev, "%s\n", __func__); |
595 | 595 | ||
596 | tty_unregister_device(acm_tty_driver, acm->minor); | ||
597 | acm_release_minor(acm); | 596 | acm_release_minor(acm); |
598 | usb_put_intf(acm->control); | 597 | usb_put_intf(acm->control); |
599 | kfree(acm->country_codes); | 598 | kfree(acm->country_codes); |
@@ -977,6 +976,8 @@ static int acm_probe(struct usb_interface *intf, | |||
977 | int num_rx_buf; | 976 | int num_rx_buf; |
978 | int i; | 977 | int i; |
979 | int combined_interfaces = 0; | 978 | int combined_interfaces = 0; |
979 | struct device *tty_dev; | ||
980 | int rv = -ENOMEM; | ||
980 | 981 | ||
981 | /* normal quirks */ | 982 | /* normal quirks */ |
982 | quirks = (unsigned long)id->driver_info; | 983 | quirks = (unsigned long)id->driver_info; |
@@ -1339,11 +1340,24 @@ skip_countries: | |||
1339 | usb_set_intfdata(data_interface, acm); | 1340 | usb_set_intfdata(data_interface, acm); |
1340 | 1341 | ||
1341 | usb_get_intf(control_interface); | 1342 | usb_get_intf(control_interface); |
1342 | tty_port_register_device(&acm->port, acm_tty_driver, minor, | 1343 | tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, |
1343 | &control_interface->dev); | 1344 | &control_interface->dev); |
1345 | if (IS_ERR(tty_dev)) { | ||
1346 | rv = PTR_ERR(tty_dev); | ||
1347 | goto alloc_fail8; | ||
1348 | } | ||
1344 | 1349 | ||
1345 | return 0; | 1350 | return 0; |
1351 | alloc_fail8: | ||
1352 | if (acm->country_codes) { | ||
1353 | device_remove_file(&acm->control->dev, | ||
1354 | &dev_attr_wCountryCodes); | ||
1355 | device_remove_file(&acm->control->dev, | ||
1356 | &dev_attr_iCountryCodeRelDate); | ||
1357 | } | ||
1358 | device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); | ||
1346 | alloc_fail7: | 1359 | alloc_fail7: |
1360 | usb_set_intfdata(intf, NULL); | ||
1347 | for (i = 0; i < ACM_NW; i++) | 1361 | for (i = 0; i < ACM_NW; i++) |
1348 | usb_free_urb(acm->wb[i].urb); | 1362 | usb_free_urb(acm->wb[i].urb); |
1349 | alloc_fail6: | 1363 | alloc_fail6: |
@@ -1359,7 +1373,7 @@ alloc_fail2: | |||
1359 | acm_release_minor(acm); | 1373 | acm_release_minor(acm); |
1360 | kfree(acm); | 1374 | kfree(acm); |
1361 | alloc_fail: | 1375 | alloc_fail: |
1362 | return -ENOMEM; | 1376 | return rv; |
1363 | } | 1377 | } |
1364 | 1378 | ||
1365 | static void stop_data_traffic(struct acm *acm) | 1379 | static void stop_data_traffic(struct acm *acm) |
@@ -1411,6 +1425,8 @@ static void acm_disconnect(struct usb_interface *intf) | |||
1411 | 1425 | ||
1412 | stop_data_traffic(acm); | 1426 | stop_data_traffic(acm); |
1413 | 1427 | ||
1428 | tty_unregister_device(acm_tty_driver, acm->minor); | ||
1429 | |||
1414 | usb_free_urb(acm->ctrlurb); | 1430 | usb_free_urb(acm->ctrlurb); |
1415 | for (i = 0; i < ACM_NW; i++) | 1431 | for (i = 0; i < ACM_NW; i++) |
1416 | usb_free_urb(acm->wb[i].urb); | 1432 | usb_free_urb(acm->wb[i].urb); |
diff --git a/drivers/usb/class/cdc-wdm.c b/drivers/usb/class/cdc-wdm.c index 5f0cb417b736..122d056d96d5 100644 --- a/drivers/usb/class/cdc-wdm.c +++ b/drivers/usb/class/cdc-wdm.c | |||
@@ -56,6 +56,7 @@ MODULE_DEVICE_TABLE (usb, wdm_ids); | |||
56 | #define WDM_RESPONDING 7 | 56 | #define WDM_RESPONDING 7 |
57 | #define WDM_SUSPENDING 8 | 57 | #define WDM_SUSPENDING 8 |
58 | #define WDM_RESETTING 9 | 58 | #define WDM_RESETTING 9 |
59 | #define WDM_OVERFLOW 10 | ||
59 | 60 | ||
60 | #define WDM_MAX 16 | 61 | #define WDM_MAX 16 |
61 | 62 | ||
@@ -155,6 +156,7 @@ static void wdm_in_callback(struct urb *urb) | |||
155 | { | 156 | { |
156 | struct wdm_device *desc = urb->context; | 157 | struct wdm_device *desc = urb->context; |
157 | int status = urb->status; | 158 | int status = urb->status; |
159 | int length = urb->actual_length; | ||
158 | 160 | ||
159 | spin_lock(&desc->iuspin); | 161 | spin_lock(&desc->iuspin); |
160 | clear_bit(WDM_RESPONDING, &desc->flags); | 162 | clear_bit(WDM_RESPONDING, &desc->flags); |
@@ -185,9 +187,17 @@ static void wdm_in_callback(struct urb *urb) | |||
185 | } | 187 | } |
186 | 188 | ||
187 | desc->rerr = status; | 189 | desc->rerr = status; |
188 | desc->reslength = urb->actual_length; | 190 | if (length + desc->length > desc->wMaxCommand) { |
189 | memmove(desc->ubuf + desc->length, desc->inbuf, desc->reslength); | 191 | /* The buffer would overflow */ |
190 | desc->length += desc->reslength; | 192 | set_bit(WDM_OVERFLOW, &desc->flags); |
193 | } else { | ||
194 | /* we may already be in overflow */ | ||
195 | if (!test_bit(WDM_OVERFLOW, &desc->flags)) { | ||
196 | memmove(desc->ubuf + desc->length, desc->inbuf, length); | ||
197 | desc->length += length; | ||
198 | desc->reslength = length; | ||
199 | } | ||
200 | } | ||
191 | skip_error: | 201 | skip_error: |
192 | wake_up(&desc->wait); | 202 | wake_up(&desc->wait); |
193 | 203 | ||
@@ -435,6 +445,11 @@ retry: | |||
435 | rv = -ENODEV; | 445 | rv = -ENODEV; |
436 | goto err; | 446 | goto err; |
437 | } | 447 | } |
448 | if (test_bit(WDM_OVERFLOW, &desc->flags)) { | ||
449 | clear_bit(WDM_OVERFLOW, &desc->flags); | ||
450 | rv = -ENOBUFS; | ||
451 | goto err; | ||
452 | } | ||
438 | i++; | 453 | i++; |
439 | if (file->f_flags & O_NONBLOCK) { | 454 | if (file->f_flags & O_NONBLOCK) { |
440 | if (!test_bit(WDM_READ, &desc->flags)) { | 455 | if (!test_bit(WDM_READ, &desc->flags)) { |
@@ -478,6 +493,7 @@ retry: | |||
478 | spin_unlock_irq(&desc->iuspin); | 493 | spin_unlock_irq(&desc->iuspin); |
479 | goto retry; | 494 | goto retry; |
480 | } | 495 | } |
496 | |||
481 | if (!desc->reslength) { /* zero length read */ | 497 | if (!desc->reslength) { /* zero length read */ |
482 | dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); | 498 | dev_dbg(&desc->intf->dev, "%s: zero length - clearing WDM_READ\n", __func__); |
483 | clear_bit(WDM_READ, &desc->flags); | 499 | clear_bit(WDM_READ, &desc->flags); |
@@ -1004,6 +1020,7 @@ static int wdm_post_reset(struct usb_interface *intf) | |||
1004 | struct wdm_device *desc = wdm_find_device(intf); | 1020 | struct wdm_device *desc = wdm_find_device(intf); |
1005 | int rv; | 1021 | int rv; |
1006 | 1022 | ||
1023 | clear_bit(WDM_OVERFLOW, &desc->flags); | ||
1007 | clear_bit(WDM_RESETTING, &desc->flags); | 1024 | clear_bit(WDM_RESETTING, &desc->flags); |
1008 | rv = recover_from_urb_loss(desc); | 1025 | rv = recover_from_urb_loss(desc); |
1009 | mutex_unlock(&desc->wlock); | 1026 | mutex_unlock(&desc->wlock); |
diff --git a/drivers/usb/core/hcd-pci.c b/drivers/usb/core/hcd-pci.c index 622b4a48e732..2b487d4797bd 100644 --- a/drivers/usb/core/hcd-pci.c +++ b/drivers/usb/core/hcd-pci.c | |||
@@ -173,6 +173,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
173 | struct hc_driver *driver; | 173 | struct hc_driver *driver; |
174 | struct usb_hcd *hcd; | 174 | struct usb_hcd *hcd; |
175 | int retval; | 175 | int retval; |
176 | int hcd_irq = 0; | ||
176 | 177 | ||
177 | if (usb_disabled()) | 178 | if (usb_disabled()) |
178 | return -ENODEV; | 179 | return -ENODEV; |
@@ -187,15 +188,19 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
187 | return -ENODEV; | 188 | return -ENODEV; |
188 | dev->current_state = PCI_D0; | 189 | dev->current_state = PCI_D0; |
189 | 190 | ||
190 | /* The xHCI driver supports MSI and MSI-X, | 191 | /* |
191 | * so don't fail if the BIOS doesn't provide a legacy IRQ. | 192 | * The xHCI driver has its own irq management |
193 | * make sure irq setup is not touched for xhci in generic hcd code | ||
192 | */ | 194 | */ |
193 | if (!dev->irq && (driver->flags & HCD_MASK) != HCD_USB3) { | 195 | if ((driver->flags & HCD_MASK) != HCD_USB3) { |
194 | dev_err(&dev->dev, | 196 | if (!dev->irq) { |
195 | "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", | 197 | dev_err(&dev->dev, |
196 | pci_name(dev)); | 198 | "Found HC with no IRQ. Check BIOS/PCI %s setup!\n", |
197 | retval = -ENODEV; | 199 | pci_name(dev)); |
198 | goto disable_pci; | 200 | retval = -ENODEV; |
201 | goto disable_pci; | ||
202 | } | ||
203 | hcd_irq = dev->irq; | ||
199 | } | 204 | } |
200 | 205 | ||
201 | hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev)); | 206 | hcd = usb_create_hcd(driver, &dev->dev, pci_name(dev)); |
@@ -245,7 +250,7 @@ int usb_hcd_pci_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
245 | 250 | ||
246 | pci_set_master(dev); | 251 | pci_set_master(dev); |
247 | 252 | ||
248 | retval = usb_add_hcd(hcd, dev->irq, IRQF_SHARED); | 253 | retval = usb_add_hcd(hcd, hcd_irq, IRQF_SHARED); |
249 | if (retval != 0) | 254 | if (retval != 0) |
250 | goto unmap_registers; | 255 | goto unmap_registers; |
251 | set_hs_companion(dev, hcd); | 256 | set_hs_companion(dev, hcd); |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 99b34a30354f..f9ec44cbb82f 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -2412,6 +2412,14 @@ int usb_hcd_is_primary_hcd(struct usb_hcd *hcd) | |||
2412 | } | 2412 | } |
2413 | EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); | 2413 | EXPORT_SYMBOL_GPL(usb_hcd_is_primary_hcd); |
2414 | 2414 | ||
2415 | int usb_hcd_find_raw_port_number(struct usb_hcd *hcd, int port1) | ||
2416 | { | ||
2417 | if (!hcd->driver->find_raw_port_number) | ||
2418 | return port1; | ||
2419 | |||
2420 | return hcd->driver->find_raw_port_number(hcd, port1); | ||
2421 | } | ||
2422 | |||
2415 | static int usb_hcd_request_irqs(struct usb_hcd *hcd, | 2423 | static int usb_hcd_request_irqs(struct usb_hcd *hcd, |
2416 | unsigned int irqnum, unsigned long irqflags) | 2424 | unsigned int irqnum, unsigned long irqflags) |
2417 | { | 2425 | { |
diff --git a/drivers/usb/core/usb-acpi.c b/drivers/usb/core/usb-acpi.c index cef4252bb31a..255c14464bf2 100644 --- a/drivers/usb/core/usb-acpi.c +++ b/drivers/usb/core/usb-acpi.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
16 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
17 | #include <linux/pci.h> | 17 | #include <linux/pci.h> |
18 | #include <linux/usb/hcd.h> | ||
18 | #include <acpi/acpi_bus.h> | 19 | #include <acpi/acpi_bus.h> |
19 | 20 | ||
20 | #include "usb.h" | 21 | #include "usb.h" |
@@ -188,8 +189,13 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
188 | * connected to. | 189 | * connected to. |
189 | */ | 190 | */ |
190 | if (!udev->parent) { | 191 | if (!udev->parent) { |
191 | *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), | 192 | struct usb_hcd *hcd = bus_to_hcd(udev->bus); |
193 | int raw_port_num; | ||
194 | |||
195 | raw_port_num = usb_hcd_find_raw_port_number(hcd, | ||
192 | port_num); | 196 | port_num); |
197 | *handle = acpi_get_child(DEVICE_ACPI_HANDLE(&udev->dev), | ||
198 | raw_port_num); | ||
193 | if (!*handle) | 199 | if (!*handle) |
194 | return -ENODEV; | 200 | return -ENODEV; |
195 | } else { | 201 | } else { |
@@ -210,9 +216,14 @@ static int usb_acpi_find_device(struct device *dev, acpi_handle *handle) | |||
210 | return 0; | 216 | return 0; |
211 | } | 217 | } |
212 | 218 | ||
219 | static bool usb_acpi_bus_match(struct device *dev) | ||
220 | { | ||
221 | return is_usb_device(dev) || is_usb_port(dev); | ||
222 | } | ||
223 | |||
213 | static struct acpi_bus_type usb_acpi_bus = { | 224 | static struct acpi_bus_type usb_acpi_bus = { |
214 | .bus = &usb_bus_type, | 225 | .name = "USB", |
215 | .find_bridge = usb_acpi_find_device, | 226 | .match = usb_acpi_bus_match, |
216 | .find_device = usb_acpi_find_device, | 227 | .find_device = usb_acpi_find_device, |
217 | }; | 228 | }; |
218 | 229 | ||
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c index 999909451e37..ffa6b004a84b 100644 --- a/drivers/usb/dwc3/core.c +++ b/drivers/usb/dwc3/core.c | |||
@@ -583,6 +583,7 @@ static int dwc3_remove(struct platform_device *pdev) | |||
583 | break; | 583 | break; |
584 | } | 584 | } |
585 | 585 | ||
586 | dwc3_free_event_buffers(dwc); | ||
586 | dwc3_core_exit(dwc); | 587 | dwc3_core_exit(dwc); |
587 | 588 | ||
588 | return 0; | 589 | return 0; |
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c index b50da53e9a52..b082bec7343e 100644 --- a/drivers/usb/dwc3/dwc3-exynos.c +++ b/drivers/usb/dwc3/dwc3-exynos.c | |||
@@ -23,8 +23,6 @@ | |||
23 | #include <linux/usb/nop-usb-xceiv.h> | 23 | #include <linux/usb/nop-usb-xceiv.h> |
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | 25 | ||
26 | #include "core.h" | ||
27 | |||
28 | struct dwc3_exynos { | 26 | struct dwc3_exynos { |
29 | struct platform_device *dwc3; | 27 | struct platform_device *dwc3; |
30 | struct platform_device *usb2_phy; | 28 | struct platform_device *usb2_phy; |
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c index 22f337f57219..afa05e3c9cf4 100644 --- a/drivers/usb/dwc3/dwc3-omap.c +++ b/drivers/usb/dwc3/dwc3-omap.c | |||
@@ -54,8 +54,6 @@ | |||
54 | #include <linux/usb/otg.h> | 54 | #include <linux/usb/otg.h> |
55 | #include <linux/usb/nop-usb-xceiv.h> | 55 | #include <linux/usb/nop-usb-xceiv.h> |
56 | 56 | ||
57 | #include "core.h" | ||
58 | |||
59 | /* | 57 | /* |
60 | * All these registers belong to OMAP's Wrapper around the | 58 | * All these registers belong to OMAP's Wrapper around the |
61 | * DesignWare USB3 Core. | 59 | * DesignWare USB3 Core. |
@@ -465,20 +463,20 @@ static int dwc3_omap_remove(struct platform_device *pdev) | |||
465 | return 0; | 463 | return 0; |
466 | } | 464 | } |
467 | 465 | ||
468 | static const struct of_device_id of_dwc3_matach[] = { | 466 | static const struct of_device_id of_dwc3_match[] = { |
469 | { | 467 | { |
470 | "ti,dwc3", | 468 | "ti,dwc3", |
471 | }, | 469 | }, |
472 | { }, | 470 | { }, |
473 | }; | 471 | }; |
474 | MODULE_DEVICE_TABLE(of, of_dwc3_matach); | 472 | MODULE_DEVICE_TABLE(of, of_dwc3_match); |
475 | 473 | ||
476 | static struct platform_driver dwc3_omap_driver = { | 474 | static struct platform_driver dwc3_omap_driver = { |
477 | .probe = dwc3_omap_probe, | 475 | .probe = dwc3_omap_probe, |
478 | .remove = dwc3_omap_remove, | 476 | .remove = dwc3_omap_remove, |
479 | .driver = { | 477 | .driver = { |
480 | .name = "omap-dwc3", | 478 | .name = "omap-dwc3", |
481 | .of_match_table = of_dwc3_matach, | 479 | .of_match_table = of_dwc3_match, |
482 | }, | 480 | }, |
483 | }; | 481 | }; |
484 | 482 | ||
diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 7d70f44567d2..e8d77689a322 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c | |||
@@ -45,8 +45,6 @@ | |||
45 | #include <linux/usb/otg.h> | 45 | #include <linux/usb/otg.h> |
46 | #include <linux/usb/nop-usb-xceiv.h> | 46 | #include <linux/usb/nop-usb-xceiv.h> |
47 | 47 | ||
48 | #include "core.h" | ||
49 | |||
50 | /* FIXME define these in <linux/pci_ids.h> */ | 48 | /* FIXME define these in <linux/pci_ids.h> */ |
51 | #define PCI_VENDOR_ID_SYNOPSYS 0x16c3 | 49 | #define PCI_VENDOR_ID_SYNOPSYS 0x16c3 |
52 | #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd | 50 | #define PCI_DEVICE_ID_SYNOPSYS_HAPSUSB3 0xabcd |
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c index d7da073a23fe..1d139ca05ef1 100644 --- a/drivers/usb/dwc3/ep0.c +++ b/drivers/usb/dwc3/ep0.c | |||
@@ -891,7 +891,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
891 | DWC3_TRBCTL_CONTROL_DATA); | 891 | DWC3_TRBCTL_CONTROL_DATA); |
892 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) | 892 | } else if (!IS_ALIGNED(req->request.length, dep->endpoint.maxpacket) |
893 | && (dep->number == 0)) { | 893 | && (dep->number == 0)) { |
894 | u32 transfer_size; | 894 | u32 transfer_size; |
895 | u32 maxpacket; | ||
895 | 896 | ||
896 | ret = usb_gadget_map_request(&dwc->gadget, &req->request, | 897 | ret = usb_gadget_map_request(&dwc->gadget, &req->request, |
897 | dep->number); | 898 | dep->number); |
@@ -902,8 +903,8 @@ static void __dwc3_ep0_do_control_data(struct dwc3 *dwc, | |||
902 | 903 | ||
903 | WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); | 904 | WARN_ON(req->request.length > DWC3_EP0_BOUNCE_SIZE); |
904 | 905 | ||
905 | transfer_size = roundup(req->request.length, | 906 | maxpacket = dep->endpoint.maxpacket; |
906 | (u32) dep->endpoint.maxpacket); | 907 | transfer_size = roundup(req->request.length, maxpacket); |
907 | 908 | ||
908 | dwc->ep0_bounced = true; | 909 | dwc->ep0_bounced = true; |
909 | 910 | ||
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index a04342f6cbfa..82e160e96fca 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -2159,7 +2159,6 @@ static void dwc3_gadget_phy_suspend(struct dwc3 *dwc, u8 speed) | |||
2159 | 2159 | ||
2160 | static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) | 2160 | static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) |
2161 | { | 2161 | { |
2162 | struct dwc3_gadget_ep_cmd_params params; | ||
2163 | struct dwc3_ep *dep; | 2162 | struct dwc3_ep *dep; |
2164 | int ret; | 2163 | int ret; |
2165 | u32 reg; | 2164 | u32 reg; |
@@ -2167,8 +2166,6 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc) | |||
2167 | 2166 | ||
2168 | dev_vdbg(dwc->dev, "%s\n", __func__); | 2167 | dev_vdbg(dwc->dev, "%s\n", __func__); |
2169 | 2168 | ||
2170 | memset(¶ms, 0x00, sizeof(params)); | ||
2171 | |||
2172 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); | 2169 | reg = dwc3_readl(dwc->regs, DWC3_DSTS); |
2173 | speed = reg & DWC3_DSTS_CONNECTSPD; | 2170 | speed = reg & DWC3_DSTS_CONNECTSPD; |
2174 | dwc->speed = speed; | 2171 | dwc->speed = speed; |
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig index 5a0c541daf89..c7525b1cad74 100644 --- a/drivers/usb/gadget/Kconfig +++ b/drivers/usb/gadget/Kconfig | |||
@@ -145,6 +145,7 @@ config USB_LPC32XX | |||
145 | tristate "LPC32XX USB Peripheral Controller" | 145 | tristate "LPC32XX USB Peripheral Controller" |
146 | depends on ARCH_LPC32XX | 146 | depends on ARCH_LPC32XX |
147 | select USB_ISP1301 | 147 | select USB_ISP1301 |
148 | select USB_OTG_UTILS | ||
148 | help | 149 | help |
149 | This option selects the USB device controller in the LPC32xx SoC. | 150 | This option selects the USB device controller in the LPC32xx SoC. |
150 | 151 | ||
diff --git a/drivers/usb/gadget/Makefile b/drivers/usb/gadget/Makefile index 97a13c349cc5..82fb22511356 100644 --- a/drivers/usb/gadget/Makefile +++ b/drivers/usb/gadget/Makefile | |||
@@ -35,6 +35,12 @@ mv_udc-y := mv_udc_core.o | |||
35 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o | 35 | obj-$(CONFIG_USB_FUSB300) += fusb300_udc.o |
36 | obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o | 36 | obj-$(CONFIG_USB_MV_U3D) += mv_u3d_core.o |
37 | 37 | ||
38 | # USB Functions | ||
39 | obj-$(CONFIG_USB_F_ACM) += f_acm.o | ||
40 | f_ss_lb-y := f_loopback.o f_sourcesink.o | ||
41 | obj-$(CONFIG_USB_F_SS_LB) += f_ss_lb.o | ||
42 | obj-$(CONFIG_USB_U_SERIAL) += u_serial.o | ||
43 | |||
38 | # | 44 | # |
39 | # USB gadget drivers | 45 | # USB gadget drivers |
40 | # | 46 | # |
@@ -74,9 +80,3 @@ obj-$(CONFIG_USB_G_WEBCAM) += g_webcam.o | |||
74 | obj-$(CONFIG_USB_G_NCM) += g_ncm.o | 80 | obj-$(CONFIG_USB_G_NCM) += g_ncm.o |
75 | obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o | 81 | obj-$(CONFIG_USB_G_ACM_MS) += g_acm_ms.o |
76 | obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o | 82 | obj-$(CONFIG_USB_GADGET_TARGET) += tcm_usb_gadget.o |
77 | |||
78 | # USB Functions | ||
79 | obj-$(CONFIG_USB_F_ACM) += f_acm.o | ||
80 | f_ss_lb-y := f_loopback.o f_sourcesink.o | ||
81 | obj-$(CONFIG_USB_F_SS_LB) += f_ss_lb.o | ||
82 | obj-$(CONFIG_USB_U_SERIAL) += u_serial.o | ||
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c index 7c821de8ce3d..c0d62b278610 100644 --- a/drivers/usb/gadget/composite.c +++ b/drivers/usb/gadget/composite.c | |||
@@ -1757,10 +1757,7 @@ static const struct usb_gadget_driver composite_driver_template = { | |||
1757 | /** | 1757 | /** |
1758 | * usb_composite_probe() - register a composite driver | 1758 | * usb_composite_probe() - register a composite driver |
1759 | * @driver: the driver to register | 1759 | * @driver: the driver to register |
1760 | * @bind: the callback used to allocate resources that are shared across the | 1760 | * |
1761 | * whole device, such as string IDs, and add its configurations using | ||
1762 | * @usb_add_config(). This may fail by returning a negative errno | ||
1763 | * value; it should return zero on successful initialization. | ||
1764 | * Context: single threaded during gadget setup | 1761 | * Context: single threaded during gadget setup |
1765 | * | 1762 | * |
1766 | * This function is used to register drivers using the composite driver | 1763 | * This function is used to register drivers using the composite driver |
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 38388d7844fc..c377ff84bf2c 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c | |||
@@ -1235,6 +1235,7 @@ static struct file_system_type ffs_fs_type = { | |||
1235 | .mount = ffs_fs_mount, | 1235 | .mount = ffs_fs_mount, |
1236 | .kill_sb = ffs_fs_kill_sb, | 1236 | .kill_sb = ffs_fs_kill_sb, |
1237 | }; | 1237 | }; |
1238 | MODULE_ALIAS_FS("functionfs"); | ||
1238 | 1239 | ||
1239 | 1240 | ||
1240 | /* Driver's main init/cleanup functions *************************************/ | 1241 | /* Driver's main init/cleanup functions *************************************/ |
diff --git a/drivers/usb/gadget/f_rndis.c b/drivers/usb/gadget/f_rndis.c index 71beeb833558..cc9c49c57c80 100644 --- a/drivers/usb/gadget/f_rndis.c +++ b/drivers/usb/gadget/f_rndis.c | |||
@@ -447,14 +447,13 @@ static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req) | |||
447 | static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req) | 447 | static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req) |
448 | { | 448 | { |
449 | struct f_rndis *rndis = req->context; | 449 | struct f_rndis *rndis = req->context; |
450 | struct usb_composite_dev *cdev = rndis->port.func.config->cdev; | ||
451 | int status; | 450 | int status; |
452 | 451 | ||
453 | /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ | 452 | /* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */ |
454 | // spin_lock(&dev->lock); | 453 | // spin_lock(&dev->lock); |
455 | status = rndis_msg_parser(rndis->config, (u8 *) req->buf); | 454 | status = rndis_msg_parser(rndis->config, (u8 *) req->buf); |
456 | if (status < 0) | 455 | if (status < 0) |
457 | ERROR(cdev, "RNDIS command error %d, %d/%d\n", | 456 | pr_err("RNDIS command error %d, %d/%d\n", |
458 | status, req->actual, req->length); | 457 | status, req->actual, req->length); |
459 | // spin_unlock(&dev->lock); | 458 | // spin_unlock(&dev->lock); |
460 | } | 459 | } |
diff --git a/drivers/usb/gadget/f_uac1.c b/drivers/usb/gadget/f_uac1.c index f570e667a640..fa8ea4ea00c1 100644 --- a/drivers/usb/gadget/f_uac1.c +++ b/drivers/usb/gadget/f_uac1.c | |||
@@ -418,6 +418,7 @@ static int audio_get_intf_req(struct usb_function *f, | |||
418 | 418 | ||
419 | req->context = audio; | 419 | req->context = audio; |
420 | req->complete = f_audio_complete; | 420 | req->complete = f_audio_complete; |
421 | len = min_t(size_t, sizeof(value), len); | ||
421 | memcpy(req->buf, &value, len); | 422 | memcpy(req->buf, &value, len); |
422 | 423 | ||
423 | return len; | 424 | return len; |
diff --git a/drivers/usb/gadget/g_ffs.c b/drivers/usb/gadget/g_ffs.c index 3953dd4d7186..3b343b23e4b0 100644 --- a/drivers/usb/gadget/g_ffs.c +++ b/drivers/usb/gadget/g_ffs.c | |||
@@ -357,7 +357,7 @@ static int gfs_bind(struct usb_composite_dev *cdev) | |||
357 | goto error; | 357 | goto error; |
358 | gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; | 358 | gfs_dev_desc.iProduct = gfs_strings[USB_GADGET_PRODUCT_IDX].id; |
359 | 359 | ||
360 | for (i = func_num; --i; ) { | 360 | for (i = func_num; i--; ) { |
361 | ret = functionfs_bind(ffs_tab[i].ffs_data, cdev); | 361 | ret = functionfs_bind(ffs_tab[i].ffs_data, cdev); |
362 | if (unlikely(ret < 0)) { | 362 | if (unlikely(ret < 0)) { |
363 | while (++i < func_num) | 363 | while (++i < func_num) |
@@ -413,7 +413,7 @@ static int gfs_unbind(struct usb_composite_dev *cdev) | |||
413 | gether_cleanup(); | 413 | gether_cleanup(); |
414 | gfs_ether_setup = false; | 414 | gfs_ether_setup = false; |
415 | 415 | ||
416 | for (i = func_num; --i; ) | 416 | for (i = func_num; i--; ) |
417 | if (ffs_tab[i].ffs_data) | 417 | if (ffs_tab[i].ffs_data) |
418 | functionfs_unbind(ffs_tab[i].ffs_data); | 418 | functionfs_unbind(ffs_tab[i].ffs_data); |
419 | 419 | ||
diff --git a/drivers/usb/gadget/imx_udc.c b/drivers/usb/gadget/imx_udc.c index 8efd7555fa21..5bd930d779b9 100644 --- a/drivers/usb/gadget/imx_udc.c +++ b/drivers/usb/gadget/imx_udc.c | |||
@@ -1334,27 +1334,18 @@ static int imx_udc_start(struct usb_gadget *gadget, | |||
1334 | struct usb_gadget_driver *driver) | 1334 | struct usb_gadget_driver *driver) |
1335 | { | 1335 | { |
1336 | struct imx_udc_struct *imx_usb; | 1336 | struct imx_udc_struct *imx_usb; |
1337 | int retval; | ||
1338 | 1337 | ||
1339 | imx_usb = container_of(gadget, struct imx_udc_struct, gadget); | 1338 | imx_usb = container_of(gadget, struct imx_udc_struct, gadget); |
1340 | /* first hook up the driver ... */ | 1339 | /* first hook up the driver ... */ |
1341 | imx_usb->driver = driver; | 1340 | imx_usb->driver = driver; |
1342 | imx_usb->gadget.dev.driver = &driver->driver; | 1341 | imx_usb->gadget.dev.driver = &driver->driver; |
1343 | 1342 | ||
1344 | retval = device_add(&imx_usb->gadget.dev); | ||
1345 | if (retval) | ||
1346 | goto fail; | ||
1347 | |||
1348 | D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n", | 1343 | D_INI(imx_usb->dev, "<%s> registered gadget driver '%s'\n", |
1349 | __func__, driver->driver.name); | 1344 | __func__, driver->driver.name); |
1350 | 1345 | ||
1351 | imx_udc_enable(imx_usb); | 1346 | imx_udc_enable(imx_usb); |
1352 | 1347 | ||
1353 | return 0; | 1348 | return 0; |
1354 | fail: | ||
1355 | imx_usb->driver = NULL; | ||
1356 | imx_usb->gadget.dev.driver = NULL; | ||
1357 | return retval; | ||
1358 | } | 1349 | } |
1359 | 1350 | ||
1360 | static int imx_udc_stop(struct usb_gadget *gadget, | 1351 | static int imx_udc_stop(struct usb_gadget *gadget, |
@@ -1370,8 +1361,6 @@ static int imx_udc_stop(struct usb_gadget *gadget, | |||
1370 | imx_usb->gadget.dev.driver = NULL; | 1361 | imx_usb->gadget.dev.driver = NULL; |
1371 | imx_usb->driver = NULL; | 1362 | imx_usb->driver = NULL; |
1372 | 1363 | ||
1373 | device_del(&imx_usb->gadget.dev); | ||
1374 | |||
1375 | D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n", | 1364 | D_INI(imx_usb->dev, "<%s> unregistered gadget driver '%s'\n", |
1376 | __func__, driver->driver.name); | 1365 | __func__, driver->driver.name); |
1377 | 1366 | ||
@@ -1477,6 +1466,10 @@ static int __init imx_udc_probe(struct platform_device *pdev) | |||
1477 | imx_usb->gadget.dev.parent = &pdev->dev; | 1466 | imx_usb->gadget.dev.parent = &pdev->dev; |
1478 | imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; | 1467 | imx_usb->gadget.dev.dma_mask = pdev->dev.dma_mask; |
1479 | 1468 | ||
1469 | ret = device_add(&imx_usb->gadget.dev); | ||
1470 | if (retval) | ||
1471 | goto fail4; | ||
1472 | |||
1480 | platform_set_drvdata(pdev, imx_usb); | 1473 | platform_set_drvdata(pdev, imx_usb); |
1481 | 1474 | ||
1482 | usb_init_data(imx_usb); | 1475 | usb_init_data(imx_usb); |
@@ -1488,9 +1481,11 @@ static int __init imx_udc_probe(struct platform_device *pdev) | |||
1488 | 1481 | ||
1489 | ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget); | 1482 | ret = usb_add_gadget_udc(&pdev->dev, &imx_usb->gadget); |
1490 | if (ret) | 1483 | if (ret) |
1491 | goto fail4; | 1484 | goto fail5; |
1492 | 1485 | ||
1493 | return 0; | 1486 | return 0; |
1487 | fail5: | ||
1488 | device_unregister(&imx_usb->gadget.dev); | ||
1494 | fail4: | 1489 | fail4: |
1495 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) | 1490 | for (i = 0; i < IMX_USB_NB_EP + 1; i++) |
1496 | free_irq(imx_usb->usbd_int[i], imx_usb); | 1491 | free_irq(imx_usb->usbd_int[i], imx_usb); |
@@ -1514,6 +1509,7 @@ static int __exit imx_udc_remove(struct platform_device *pdev) | |||
1514 | int i; | 1509 | int i; |
1515 | 1510 | ||
1516 | usb_del_gadget_udc(&imx_usb->gadget); | 1511 | usb_del_gadget_udc(&imx_usb->gadget); |
1512 | device_unregister(&imx_usb->gadget.dev); | ||
1517 | imx_udc_disable(imx_usb); | 1513 | imx_udc_disable(imx_usb); |
1518 | del_timer(&imx_usb->timer); | 1514 | del_timer(&imx_usb->timer); |
1519 | 1515 | ||
diff --git a/drivers/usb/gadget/inode.c b/drivers/usb/gadget/inode.c index 8ac840f25ba9..e2b2e9cf254a 100644 --- a/drivers/usb/gadget/inode.c +++ b/drivers/usb/gadget/inode.c | |||
@@ -2105,6 +2105,7 @@ static struct file_system_type gadgetfs_type = { | |||
2105 | .mount = gadgetfs_mount, | 2105 | .mount = gadgetfs_mount, |
2106 | .kill_sb = gadgetfs_kill_sb, | 2106 | .kill_sb = gadgetfs_kill_sb, |
2107 | }; | 2107 | }; |
2108 | MODULE_ALIAS_FS("gadgetfs"); | ||
2108 | 2109 | ||
2109 | /*----------------------------------------------------------------------*/ | 2110 | /*----------------------------------------------------------------------*/ |
2110 | 2111 | ||
diff --git a/drivers/usb/gadget/net2272.c b/drivers/usb/gadget/net2272.c index d226058e3b88..32524b631959 100644 --- a/drivers/usb/gadget/net2272.c +++ b/drivers/usb/gadget/net2272.c | |||
@@ -59,7 +59,7 @@ static const char * const ep_name[] = { | |||
59 | }; | 59 | }; |
60 | 60 | ||
61 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) | 61 | #define DMA_ADDR_INVALID (~(dma_addr_t)0) |
62 | #ifdef CONFIG_USB_GADGET_NET2272_DMA | 62 | #ifdef CONFIG_USB_NET2272_DMA |
63 | /* | 63 | /* |
64 | * use_dma: the NET2272 can use an external DMA controller. | 64 | * use_dma: the NET2272 can use an external DMA controller. |
65 | * Note that since there is no generic DMA api, some functions, | 65 | * Note that since there is no generic DMA api, some functions, |
@@ -1495,6 +1495,13 @@ stop_activity(struct net2272 *dev, struct usb_gadget_driver *driver) | |||
1495 | for (i = 0; i < 4; ++i) | 1495 | for (i = 0; i < 4; ++i) |
1496 | net2272_dequeue_all(&dev->ep[i]); | 1496 | net2272_dequeue_all(&dev->ep[i]); |
1497 | 1497 | ||
1498 | /* report disconnect; the driver is already quiesced */ | ||
1499 | if (driver) { | ||
1500 | spin_unlock(&dev->lock); | ||
1501 | driver->disconnect(&dev->gadget); | ||
1502 | spin_lock(&dev->lock); | ||
1503 | } | ||
1504 | |||
1498 | net2272_usb_reinit(dev); | 1505 | net2272_usb_reinit(dev); |
1499 | } | 1506 | } |
1500 | 1507 | ||
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c index a1b650e11339..3bd0f992fb49 100644 --- a/drivers/usb/gadget/net2280.c +++ b/drivers/usb/gadget/net2280.c | |||
@@ -1924,7 +1924,6 @@ static int net2280_start(struct usb_gadget *_gadget, | |||
1924 | err_func: | 1924 | err_func: |
1925 | device_remove_file (&dev->pdev->dev, &dev_attr_function); | 1925 | device_remove_file (&dev->pdev->dev, &dev_attr_function); |
1926 | err_unbind: | 1926 | err_unbind: |
1927 | driver->unbind (&dev->gadget); | ||
1928 | dev->gadget.dev.driver = NULL; | 1927 | dev->gadget.dev.driver = NULL; |
1929 | dev->driver = NULL; | 1928 | dev->driver = NULL; |
1930 | return retval; | 1929 | return retval; |
@@ -1946,6 +1945,13 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver) | |||
1946 | for (i = 0; i < 7; i++) | 1945 | for (i = 0; i < 7; i++) |
1947 | nuke (&dev->ep [i]); | 1946 | nuke (&dev->ep [i]); |
1948 | 1947 | ||
1948 | /* report disconnect; the driver is already quiesced */ | ||
1949 | if (driver) { | ||
1950 | spin_unlock(&dev->lock); | ||
1951 | driver->disconnect(&dev->gadget); | ||
1952 | spin_lock(&dev->lock); | ||
1953 | } | ||
1954 | |||
1949 | usb_reinit (dev); | 1955 | usb_reinit (dev); |
1950 | } | 1956 | } |
1951 | 1957 | ||
diff --git a/drivers/usb/gadget/omap_udc.c b/drivers/usb/gadget/omap_udc.c index 06be85c2b233..f8445653577f 100644 --- a/drivers/usb/gadget/omap_udc.c +++ b/drivers/usb/gadget/omap_udc.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #define DRIVER_VERSION "4 October 2004" | 62 | #define DRIVER_VERSION "4 October 2004" |
63 | 63 | ||
64 | #define OMAP_DMA_USB_W2FC_TX0 29 | 64 | #define OMAP_DMA_USB_W2FC_TX0 29 |
65 | #define OMAP_DMA_USB_W2FC_RX0 26 | ||
65 | 66 | ||
66 | /* | 67 | /* |
67 | * The OMAP UDC needs _very_ early endpoint setup: before enabling the | 68 | * The OMAP UDC needs _very_ early endpoint setup: before enabling the |
@@ -1310,7 +1311,7 @@ static int omap_pullup(struct usb_gadget *gadget, int is_on) | |||
1310 | } | 1311 | } |
1311 | 1312 | ||
1312 | static int omap_udc_start(struct usb_gadget *g, | 1313 | static int omap_udc_start(struct usb_gadget *g, |
1313 | struct usb_gadget_driver *driver) | 1314 | struct usb_gadget_driver *driver); |
1314 | static int omap_udc_stop(struct usb_gadget *g, | 1315 | static int omap_udc_stop(struct usb_gadget *g, |
1315 | struct usb_gadget_driver *driver); | 1316 | struct usb_gadget_driver *driver); |
1316 | 1317 | ||
diff --git a/drivers/usb/gadget/pxa25x_udc.c b/drivers/usb/gadget/pxa25x_udc.c index 2bbcdce942dc..d0f37484b6b0 100644 --- a/drivers/usb/gadget/pxa25x_udc.c +++ b/drivers/usb/gadget/pxa25x_udc.c | |||
@@ -1266,13 +1266,6 @@ static int pxa25x_udc_start(struct usb_gadget *g, | |||
1266 | dev->gadget.dev.driver = &driver->driver; | 1266 | dev->gadget.dev.driver = &driver->driver; |
1267 | dev->pullup = 1; | 1267 | dev->pullup = 1; |
1268 | 1268 | ||
1269 | retval = device_add (&dev->gadget.dev); | ||
1270 | if (retval) { | ||
1271 | dev->driver = NULL; | ||
1272 | dev->gadget.dev.driver = NULL; | ||
1273 | return retval; | ||
1274 | } | ||
1275 | |||
1276 | /* ... then enable host detection and ep0; and we're ready | 1269 | /* ... then enable host detection and ep0; and we're ready |
1277 | * for set_configuration as well as eventual disconnect. | 1270 | * for set_configuration as well as eventual disconnect. |
1278 | */ | 1271 | */ |
@@ -1310,6 +1303,10 @@ stop_activity(struct pxa25x_udc *dev, struct usb_gadget_driver *driver) | |||
1310 | } | 1303 | } |
1311 | del_timer_sync(&dev->timer); | 1304 | del_timer_sync(&dev->timer); |
1312 | 1305 | ||
1306 | /* report disconnect; the driver is already quiesced */ | ||
1307 | if (driver) | ||
1308 | driver->disconnect(&dev->gadget); | ||
1309 | |||
1313 | /* re-init driver-visible data structures */ | 1310 | /* re-init driver-visible data structures */ |
1314 | udc_reinit(dev); | 1311 | udc_reinit(dev); |
1315 | } | 1312 | } |
@@ -1331,7 +1328,6 @@ static int pxa25x_udc_stop(struct usb_gadget*g, | |||
1331 | dev->gadget.dev.driver = NULL; | 1328 | dev->gadget.dev.driver = NULL; |
1332 | dev->driver = NULL; | 1329 | dev->driver = NULL; |
1333 | 1330 | ||
1334 | device_del (&dev->gadget.dev); | ||
1335 | dump_state(dev); | 1331 | dump_state(dev); |
1336 | 1332 | ||
1337 | return 0; | 1333 | return 0; |
@@ -2146,6 +2142,13 @@ static int __init pxa25x_udc_probe(struct platform_device *pdev) | |||
2146 | dev->gadget.dev.parent = &pdev->dev; | 2142 | dev->gadget.dev.parent = &pdev->dev; |
2147 | dev->gadget.dev.dma_mask = pdev->dev.dma_mask; | 2143 | dev->gadget.dev.dma_mask = pdev->dev.dma_mask; |
2148 | 2144 | ||
2145 | retval = device_add(&dev->gadget.dev); | ||
2146 | if (retval) { | ||
2147 | dev->driver = NULL; | ||
2148 | dev->gadget.dev.driver = NULL; | ||
2149 | goto err_device_add; | ||
2150 | } | ||
2151 | |||
2149 | the_controller = dev; | 2152 | the_controller = dev; |
2150 | platform_set_drvdata(pdev, dev); | 2153 | platform_set_drvdata(pdev, dev); |
2151 | 2154 | ||
@@ -2196,6 +2199,8 @@ lubbock_fail0: | |||
2196 | free_irq(irq, dev); | 2199 | free_irq(irq, dev); |
2197 | #endif | 2200 | #endif |
2198 | err_irq1: | 2201 | err_irq1: |
2202 | device_unregister(&dev->gadget.dev); | ||
2203 | err_device_add: | ||
2199 | if (gpio_is_valid(dev->mach->gpio_pullup)) | 2204 | if (gpio_is_valid(dev->mach->gpio_pullup)) |
2200 | gpio_free(dev->mach->gpio_pullup); | 2205 | gpio_free(dev->mach->gpio_pullup); |
2201 | err_gpio_pullup: | 2206 | err_gpio_pullup: |
@@ -2217,10 +2222,11 @@ static int __exit pxa25x_udc_remove(struct platform_device *pdev) | |||
2217 | { | 2222 | { |
2218 | struct pxa25x_udc *dev = platform_get_drvdata(pdev); | 2223 | struct pxa25x_udc *dev = platform_get_drvdata(pdev); |
2219 | 2224 | ||
2220 | usb_del_gadget_udc(&dev->gadget); | ||
2221 | if (dev->driver) | 2225 | if (dev->driver) |
2222 | return -EBUSY; | 2226 | return -EBUSY; |
2223 | 2227 | ||
2228 | usb_del_gadget_udc(&dev->gadget); | ||
2229 | device_unregister(&dev->gadget.dev); | ||
2224 | dev->pullup = 0; | 2230 | dev->pullup = 0; |
2225 | pullup(dev); | 2231 | pullup(dev); |
2226 | 2232 | ||
diff --git a/drivers/usb/gadget/pxa27x_udc.c b/drivers/usb/gadget/pxa27x_udc.c index f7d25795821a..2fc867652ef5 100644 --- a/drivers/usb/gadget/pxa27x_udc.c +++ b/drivers/usb/gadget/pxa27x_udc.c | |||
@@ -1814,11 +1814,6 @@ static int pxa27x_udc_start(struct usb_gadget *g, | |||
1814 | udc->gadget.dev.driver = &driver->driver; | 1814 | udc->gadget.dev.driver = &driver->driver; |
1815 | dplus_pullup(udc, 1); | 1815 | dplus_pullup(udc, 1); |
1816 | 1816 | ||
1817 | retval = device_add(&udc->gadget.dev); | ||
1818 | if (retval) { | ||
1819 | dev_err(udc->dev, "device_add error %d\n", retval); | ||
1820 | goto fail; | ||
1821 | } | ||
1822 | if (!IS_ERR_OR_NULL(udc->transceiver)) { | 1817 | if (!IS_ERR_OR_NULL(udc->transceiver)) { |
1823 | retval = otg_set_peripheral(udc->transceiver->otg, | 1818 | retval = otg_set_peripheral(udc->transceiver->otg, |
1824 | &udc->gadget); | 1819 | &udc->gadget); |
@@ -1876,7 +1871,6 @@ static int pxa27x_udc_stop(struct usb_gadget *g, | |||
1876 | 1871 | ||
1877 | udc->driver = NULL; | 1872 | udc->driver = NULL; |
1878 | 1873 | ||
1879 | device_del(&udc->gadget.dev); | ||
1880 | 1874 | ||
1881 | if (!IS_ERR_OR_NULL(udc->transceiver)) | 1875 | if (!IS_ERR_OR_NULL(udc->transceiver)) |
1882 | return otg_set_peripheral(udc->transceiver->otg, NULL); | 1876 | return otg_set_peripheral(udc->transceiver->otg, NULL); |
@@ -2480,13 +2474,24 @@ static int __init pxa_udc_probe(struct platform_device *pdev) | |||
2480 | driver_name, udc->irq, retval); | 2474 | driver_name, udc->irq, retval); |
2481 | goto err_irq; | 2475 | goto err_irq; |
2482 | } | 2476 | } |
2477 | |||
2478 | retval = device_add(&udc->gadget.dev); | ||
2479 | if (retval) { | ||
2480 | dev_err(udc->dev, "device_add error %d\n", retval); | ||
2481 | goto err_dev_add; | ||
2482 | } | ||
2483 | |||
2483 | retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget); | 2484 | retval = usb_add_gadget_udc(&pdev->dev, &udc->gadget); |
2484 | if (retval) | 2485 | if (retval) |
2485 | goto err_add_udc; | 2486 | goto err_add_udc; |
2486 | 2487 | ||
2487 | pxa_init_debugfs(udc); | 2488 | pxa_init_debugfs(udc); |
2489 | |||
2488 | return 0; | 2490 | return 0; |
2491 | |||
2489 | err_add_udc: | 2492 | err_add_udc: |
2493 | device_unregister(&udc->gadget.dev); | ||
2494 | err_dev_add: | ||
2490 | free_irq(udc->irq, udc); | 2495 | free_irq(udc->irq, udc); |
2491 | err_irq: | 2496 | err_irq: |
2492 | iounmap(udc->regs); | 2497 | iounmap(udc->regs); |
@@ -2507,6 +2512,7 @@ static int __exit pxa_udc_remove(struct platform_device *_dev) | |||
2507 | int gpio = udc->mach->gpio_pullup; | 2512 | int gpio = udc->mach->gpio_pullup; |
2508 | 2513 | ||
2509 | usb_del_gadget_udc(&udc->gadget); | 2514 | usb_del_gadget_udc(&udc->gadget); |
2515 | device_del(&udc->gadget.dev); | ||
2510 | usb_gadget_unregister_driver(udc->driver); | 2516 | usb_gadget_unregister_driver(udc->driver); |
2511 | free_irq(udc->irq, udc); | 2517 | free_irq(udc->irq, udc); |
2512 | pxa_cleanup_debugfs(udc); | 2518 | pxa_cleanup_debugfs(udc); |
diff --git a/drivers/usb/gadget/s3c2410_udc.c b/drivers/usb/gadget/s3c2410_udc.c index fc07b4381286..08f89652533b 100644 --- a/drivers/usb/gadget/s3c2410_udc.c +++ b/drivers/usb/gadget/s3c2410_udc.c | |||
@@ -1668,8 +1668,7 @@ static void s3c2410_udc_enable(struct s3c2410_udc *dev) | |||
1668 | static int s3c2410_udc_start(struct usb_gadget *g, | 1668 | static int s3c2410_udc_start(struct usb_gadget *g, |
1669 | struct usb_gadget_driver *driver) | 1669 | struct usb_gadget_driver *driver) |
1670 | { | 1670 | { |
1671 | struct s3c2410_udc *udc = to_s3c2410(g) | 1671 | struct s3c2410_udc *udc = to_s3c2410(g); |
1672 | int retval; | ||
1673 | 1672 | ||
1674 | dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name); | 1673 | dprintk(DEBUG_NORMAL, "%s() '%s'\n", __func__, driver->driver.name); |
1675 | 1674 | ||
@@ -1677,22 +1676,10 @@ static int s3c2410_udc_start(struct usb_gadget *g, | |||
1677 | udc->driver = driver; | 1676 | udc->driver = driver; |
1678 | udc->gadget.dev.driver = &driver->driver; | 1677 | udc->gadget.dev.driver = &driver->driver; |
1679 | 1678 | ||
1680 | /* Bind the driver */ | ||
1681 | retval = device_add(&udc->gadget.dev); | ||
1682 | if (retval) { | ||
1683 | dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); | ||
1684 | goto register_error; | ||
1685 | } | ||
1686 | |||
1687 | /* Enable udc */ | 1679 | /* Enable udc */ |
1688 | s3c2410_udc_enable(udc); | 1680 | s3c2410_udc_enable(udc); |
1689 | 1681 | ||
1690 | return 0; | 1682 | return 0; |
1691 | |||
1692 | register_error: | ||
1693 | udc->driver = NULL; | ||
1694 | udc->gadget.dev.driver = NULL; | ||
1695 | return retval; | ||
1696 | } | 1683 | } |
1697 | 1684 | ||
1698 | static int s3c2410_udc_stop(struct usb_gadget *g, | 1685 | static int s3c2410_udc_stop(struct usb_gadget *g, |
@@ -1700,7 +1687,6 @@ static int s3c2410_udc_stop(struct usb_gadget *g, | |||
1700 | { | 1687 | { |
1701 | struct s3c2410_udc *udc = to_s3c2410(g); | 1688 | struct s3c2410_udc *udc = to_s3c2410(g); |
1702 | 1689 | ||
1703 | device_del(&udc->gadget.dev); | ||
1704 | udc->driver = NULL; | 1690 | udc->driver = NULL; |
1705 | 1691 | ||
1706 | /* Disable udc */ | 1692 | /* Disable udc */ |
@@ -1842,6 +1828,13 @@ static int s3c2410_udc_probe(struct platform_device *pdev) | |||
1842 | udc->gadget.dev.parent = &pdev->dev; | 1828 | udc->gadget.dev.parent = &pdev->dev; |
1843 | udc->gadget.dev.dma_mask = pdev->dev.dma_mask; | 1829 | udc->gadget.dev.dma_mask = pdev->dev.dma_mask; |
1844 | 1830 | ||
1831 | /* Bind the driver */ | ||
1832 | retval = device_add(&udc->gadget.dev); | ||
1833 | if (retval) { | ||
1834 | dev_err(&udc->gadget.dev, "Error in device_add() : %d\n", retval); | ||
1835 | goto err_device_add; | ||
1836 | } | ||
1837 | |||
1845 | the_controller = udc; | 1838 | the_controller = udc; |
1846 | platform_set_drvdata(pdev, udc); | 1839 | platform_set_drvdata(pdev, udc); |
1847 | 1840 | ||
@@ -1930,6 +1923,8 @@ err_gpio_claim: | |||
1930 | err_int: | 1923 | err_int: |
1931 | free_irq(IRQ_USBD, udc); | 1924 | free_irq(IRQ_USBD, udc); |
1932 | err_map: | 1925 | err_map: |
1926 | device_unregister(&udc->gadget.dev); | ||
1927 | err_device_add: | ||
1933 | iounmap(base_addr); | 1928 | iounmap(base_addr); |
1934 | err_mem: | 1929 | err_mem: |
1935 | release_mem_region(rsrc_start, rsrc_len); | 1930 | release_mem_region(rsrc_start, rsrc_len); |
@@ -1947,10 +1942,11 @@ static int s3c2410_udc_remove(struct platform_device *pdev) | |||
1947 | 1942 | ||
1948 | dev_dbg(&pdev->dev, "%s()\n", __func__); | 1943 | dev_dbg(&pdev->dev, "%s()\n", __func__); |
1949 | 1944 | ||
1950 | usb_del_gadget_udc(&udc->gadget); | ||
1951 | if (udc->driver) | 1945 | if (udc->driver) |
1952 | return -EBUSY; | 1946 | return -EBUSY; |
1953 | 1947 | ||
1948 | usb_del_gadget_udc(&udc->gadget); | ||
1949 | device_unregister(&udc->gadget.dev); | ||
1954 | debugfs_remove(udc->regs_info); | 1950 | debugfs_remove(udc->regs_info); |
1955 | 1951 | ||
1956 | if (udc_info && !udc_info->udc_command && | 1952 | if (udc_info && !udc_info->udc_command && |
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index c5034d9c946b..b369292d4b90 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c | |||
@@ -136,7 +136,7 @@ static struct portmaster { | |||
136 | pr_debug(fmt, ##arg) | 136 | pr_debug(fmt, ##arg) |
137 | #endif /* pr_vdebug */ | 137 | #endif /* pr_vdebug */ |
138 | #else | 138 | #else |
139 | #ifndef pr_vdebig | 139 | #ifndef pr_vdebug |
140 | #define pr_vdebug(fmt, arg...) \ | 140 | #define pr_vdebug(fmt, arg...) \ |
141 | ({ if (0) pr_debug(fmt, ##arg); }) | 141 | ({ if (0) pr_debug(fmt, ##arg); }) |
142 | #endif /* pr_vdebug */ | 142 | #endif /* pr_vdebug */ |
diff --git a/drivers/usb/gadget/u_uac1.c b/drivers/usb/gadget/u_uac1.c index e0c5e88e03ed..c7d460f43390 100644 --- a/drivers/usb/gadget/u_uac1.c +++ b/drivers/usb/gadget/u_uac1.c | |||
@@ -240,8 +240,11 @@ static int gaudio_open_snd_dev(struct gaudio *card) | |||
240 | snd = &card->playback; | 240 | snd = &card->playback; |
241 | snd->filp = filp_open(fn_play, O_WRONLY, 0); | 241 | snd->filp = filp_open(fn_play, O_WRONLY, 0); |
242 | if (IS_ERR(snd->filp)) { | 242 | if (IS_ERR(snd->filp)) { |
243 | int ret = PTR_ERR(snd->filp); | ||
244 | |||
243 | ERROR(card, "No such PCM playback device: %s\n", fn_play); | 245 | ERROR(card, "No such PCM playback device: %s\n", fn_play); |
244 | snd->filp = NULL; | 246 | snd->filp = NULL; |
247 | return ret; | ||
245 | } | 248 | } |
246 | pcm_file = snd->filp->private_data; | 249 | pcm_file = snd->filp->private_data; |
247 | snd->substream = pcm_file->substream; | 250 | snd->substream = pcm_file->substream; |
diff --git a/drivers/usb/gadget/udc-core.c b/drivers/usb/gadget/udc-core.c index 2a9cd369f71c..f8f62c3ed65e 100644 --- a/drivers/usb/gadget/udc-core.c +++ b/drivers/usb/gadget/udc-core.c | |||
@@ -216,7 +216,7 @@ static void usb_gadget_remove_driver(struct usb_udc *udc) | |||
216 | usb_gadget_disconnect(udc->gadget); | 216 | usb_gadget_disconnect(udc->gadget); |
217 | udc->driver->disconnect(udc->gadget); | 217 | udc->driver->disconnect(udc->gadget); |
218 | udc->driver->unbind(udc->gadget); | 218 | udc->driver->unbind(udc->gadget); |
219 | usb_gadget_udc_stop(udc->gadget, udc->driver); | 219 | usb_gadget_udc_stop(udc->gadget, NULL); |
220 | 220 | ||
221 | udc->driver = NULL; | 221 | udc->driver = NULL; |
222 | udc->dev.driver = NULL; | 222 | udc->dev.driver = NULL; |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index b416a3fc9959..416a6dce5e11 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -302,6 +302,7 @@ static void ehci_quiesce (struct ehci_hcd *ehci) | |||
302 | 302 | ||
303 | static void end_unlink_async(struct ehci_hcd *ehci); | 303 | static void end_unlink_async(struct ehci_hcd *ehci); |
304 | static void unlink_empty_async(struct ehci_hcd *ehci); | 304 | static void unlink_empty_async(struct ehci_hcd *ehci); |
305 | static void unlink_empty_async_suspended(struct ehci_hcd *ehci); | ||
305 | static void ehci_work(struct ehci_hcd *ehci); | 306 | static void ehci_work(struct ehci_hcd *ehci); |
306 | static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); | 307 | static void start_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); |
307 | static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); | 308 | static void end_unlink_intr(struct ehci_hcd *ehci, struct ehci_qh *qh); |
@@ -748,11 +749,9 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
748 | /* guard against (alleged) silicon errata */ | 749 | /* guard against (alleged) silicon errata */ |
749 | if (cmd & CMD_IAAD) | 750 | if (cmd & CMD_IAAD) |
750 | ehci_dbg(ehci, "IAA with IAAD still set?\n"); | 751 | ehci_dbg(ehci, "IAA with IAAD still set?\n"); |
751 | if (ehci->async_iaa) { | 752 | if (ehci->async_iaa) |
752 | COUNT(ehci->stats.iaa); | 753 | COUNT(ehci->stats.iaa); |
753 | end_unlink_async(ehci); | 754 | end_unlink_async(ehci); |
754 | } else | ||
755 | ehci_dbg(ehci, "IAA with nothing unlinked?\n"); | ||
756 | } | 755 | } |
757 | 756 | ||
758 | /* remote wakeup [4.3.1] */ | 757 | /* remote wakeup [4.3.1] */ |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 4d3b294f203e..7d06e77f6c4f 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -328,7 +328,7 @@ static int ehci_bus_suspend (struct usb_hcd *hcd) | |||
328 | ehci->rh_state = EHCI_RH_SUSPENDED; | 328 | ehci->rh_state = EHCI_RH_SUSPENDED; |
329 | 329 | ||
330 | end_unlink_async(ehci); | 330 | end_unlink_async(ehci); |
331 | unlink_empty_async(ehci); | 331 | unlink_empty_async_suspended(ehci); |
332 | ehci_handle_intr_unlinks(ehci); | 332 | ehci_handle_intr_unlinks(ehci); |
333 | end_free_itds(ehci); | 333 | end_free_itds(ehci); |
334 | 334 | ||
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index fd252f0cfb3a..23d136904285 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -135,7 +135,7 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
135 | * qtd is updated in qh_completions(). Update the QH | 135 | * qtd is updated in qh_completions(). Update the QH |
136 | * overlay here. | 136 | * overlay here. |
137 | */ | 137 | */ |
138 | if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) { | 138 | if (qh->hw->hw_token & ACTIVE_BIT(ehci)) { |
139 | qh->hw->hw_qtd_next = qtd->hw_next; | 139 | qh->hw->hw_qtd_next = qtd->hw_next; |
140 | qtd = NULL; | 140 | qtd = NULL; |
141 | } | 141 | } |
@@ -449,11 +449,19 @@ qh_completions (struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
449 | else if (last_status == -EINPROGRESS && !urb->unlinked) | 449 | else if (last_status == -EINPROGRESS && !urb->unlinked) |
450 | continue; | 450 | continue; |
451 | 451 | ||
452 | /* qh unlinked; token in overlay may be most current */ | 452 | /* |
453 | if (state == QH_STATE_IDLE | 453 | * If this was the active qtd when the qh was unlinked |
454 | && cpu_to_hc32(ehci, qtd->qtd_dma) | 454 | * and the overlay's token is active, then the overlay |
455 | == hw->hw_current) { | 455 | * hasn't been written back to the qtd yet so use its |
456 | * token instead of the qtd's. After the qtd is | ||
457 | * processed and removed, the overlay won't be valid | ||
458 | * any more. | ||
459 | */ | ||
460 | if (state == QH_STATE_IDLE && | ||
461 | qh->qtd_list.next == &qtd->qtd_list && | ||
462 | (hw->hw_token & ACTIVE_BIT(ehci))) { | ||
456 | token = hc32_to_cpu(ehci, hw->hw_token); | 463 | token = hc32_to_cpu(ehci, hw->hw_token); |
464 | hw->hw_token &= ~ACTIVE_BIT(ehci); | ||
457 | 465 | ||
458 | /* An unlink may leave an incomplete | 466 | /* An unlink may leave an incomplete |
459 | * async transaction in the TT buffer. | 467 | * async transaction in the TT buffer. |
@@ -1170,7 +1178,7 @@ static void single_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh) | |||
1170 | struct ehci_qh *prev; | 1178 | struct ehci_qh *prev; |
1171 | 1179 | ||
1172 | /* Add to the end of the list of QHs waiting for the next IAAD */ | 1180 | /* Add to the end of the list of QHs waiting for the next IAAD */ |
1173 | qh->qh_state = QH_STATE_UNLINK; | 1181 | qh->qh_state = QH_STATE_UNLINK_WAIT; |
1174 | if (ehci->async_unlink) | 1182 | if (ehci->async_unlink) |
1175 | ehci->async_unlink_last->unlink_next = qh; | 1183 | ehci->async_unlink_last->unlink_next = qh; |
1176 | else | 1184 | else |
@@ -1213,9 +1221,19 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested) | |||
1213 | 1221 | ||
1214 | /* Do only the first waiting QH (nVidia bug?) */ | 1222 | /* Do only the first waiting QH (nVidia bug?) */ |
1215 | qh = ehci->async_unlink; | 1223 | qh = ehci->async_unlink; |
1216 | ehci->async_iaa = qh; | 1224 | |
1217 | ehci->async_unlink = qh->unlink_next; | 1225 | /* |
1218 | qh->unlink_next = NULL; | 1226 | * Intel (?) bug: The HC can write back the overlay region |
1227 | * even after the IAA interrupt occurs. In self-defense, | ||
1228 | * always go through two IAA cycles for each QH. | ||
1229 | */ | ||
1230 | if (qh->qh_state == QH_STATE_UNLINK_WAIT) { | ||
1231 | qh->qh_state = QH_STATE_UNLINK; | ||
1232 | } else { | ||
1233 | ehci->async_iaa = qh; | ||
1234 | ehci->async_unlink = qh->unlink_next; | ||
1235 | qh->unlink_next = NULL; | ||
1236 | } | ||
1219 | 1237 | ||
1220 | /* Make sure the unlinks are all visible to the hardware */ | 1238 | /* Make sure the unlinks are all visible to the hardware */ |
1221 | wmb(); | 1239 | wmb(); |
@@ -1298,6 +1316,19 @@ static void unlink_empty_async(struct ehci_hcd *ehci) | |||
1298 | } | 1316 | } |
1299 | } | 1317 | } |
1300 | 1318 | ||
1319 | /* The root hub is suspended; unlink all the async QHs */ | ||
1320 | static void unlink_empty_async_suspended(struct ehci_hcd *ehci) | ||
1321 | { | ||
1322 | struct ehci_qh *qh; | ||
1323 | |||
1324 | while (ehci->async->qh_next.qh) { | ||
1325 | qh = ehci->async->qh_next.qh; | ||
1326 | WARN_ON(!list_empty(&qh->qtd_list)); | ||
1327 | single_unlink_async(ehci, qh); | ||
1328 | } | ||
1329 | start_iaa_cycle(ehci, false); | ||
1330 | } | ||
1331 | |||
1301 | /* makes sure the async qh will become idle */ | 1332 | /* makes sure the async qh will become idle */ |
1302 | /* caller must own ehci->lock */ | 1333 | /* caller must own ehci->lock */ |
1303 | 1334 | ||
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index b476daf49f6f..010f686d8881 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -1214,6 +1214,7 @@ itd_urb_transaction ( | |||
1214 | 1214 | ||
1215 | memset (itd, 0, sizeof *itd); | 1215 | memset (itd, 0, sizeof *itd); |
1216 | itd->itd_dma = itd_dma; | 1216 | itd->itd_dma = itd_dma; |
1217 | itd->frame = 9999; /* an invalid value */ | ||
1217 | list_add (&itd->itd_list, &sched->td_list); | 1218 | list_add (&itd->itd_list, &sched->td_list); |
1218 | } | 1219 | } |
1219 | spin_unlock_irqrestore (&ehci->lock, flags); | 1220 | spin_unlock_irqrestore (&ehci->lock, flags); |
@@ -1915,6 +1916,7 @@ sitd_urb_transaction ( | |||
1915 | 1916 | ||
1916 | memset (sitd, 0, sizeof *sitd); | 1917 | memset (sitd, 0, sizeof *sitd); |
1917 | sitd->sitd_dma = sitd_dma; | 1918 | sitd->sitd_dma = sitd_dma; |
1919 | sitd->frame = 9999; /* an invalid value */ | ||
1918 | list_add (&sitd->sitd_list, &iso_sched->td_list); | 1920 | list_add (&sitd->sitd_list, &iso_sched->td_list); |
1919 | } | 1921 | } |
1920 | 1922 | ||
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 20dbdcbe9b0f..c3fa1305f830 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c | |||
@@ -304,7 +304,7 @@ static void ehci_iaa_watchdog(struct ehci_hcd *ehci) | |||
304 | * (a) SMP races against real IAA firing and retriggering, and | 304 | * (a) SMP races against real IAA firing and retriggering, and |
305 | * (b) clean HC shutdown, when IAA watchdog was pending. | 305 | * (b) clean HC shutdown, when IAA watchdog was pending. |
306 | */ | 306 | */ |
307 | if (ehci->async_iaa) { | 307 | if (1) { |
308 | u32 cmd, status; | 308 | u32 cmd, status; |
309 | 309 | ||
310 | /* If we get here, IAA is *REALLY* late. It's barely | 310 | /* If we get here, IAA is *REALLY* late. It's barely |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index 35616ffbe3ae..6dc238c592bc 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -1022,44 +1022,24 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci, | |||
1022 | * is attached to (or the roothub port its ancestor hub is attached to). All we | 1022 | * is attached to (or the roothub port its ancestor hub is attached to). All we |
1023 | * know is the index of that port under either the USB 2.0 or the USB 3.0 | 1023 | * know is the index of that port under either the USB 2.0 or the USB 3.0 |
1024 | * roothub, but that doesn't give us the real index into the HW port status | 1024 | * roothub, but that doesn't give us the real index into the HW port status |
1025 | * registers. Scan through the xHCI roothub port array, looking for the Nth | 1025 | * registers. Call xhci_find_raw_port_number() to get real index. |
1026 | * entry of the correct port speed. Return the port number of that entry. | ||
1027 | */ | 1026 | */ |
1028 | static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, | 1027 | static u32 xhci_find_real_port_number(struct xhci_hcd *xhci, |
1029 | struct usb_device *udev) | 1028 | struct usb_device *udev) |
1030 | { | 1029 | { |
1031 | struct usb_device *top_dev; | 1030 | struct usb_device *top_dev; |
1032 | unsigned int num_similar_speed_ports; | 1031 | struct usb_hcd *hcd; |
1033 | unsigned int faked_port_num; | 1032 | |
1034 | int i; | 1033 | if (udev->speed == USB_SPEED_SUPER) |
1034 | hcd = xhci->shared_hcd; | ||
1035 | else | ||
1036 | hcd = xhci->main_hcd; | ||
1035 | 1037 | ||
1036 | for (top_dev = udev; top_dev->parent && top_dev->parent->parent; | 1038 | for (top_dev = udev; top_dev->parent && top_dev->parent->parent; |
1037 | top_dev = top_dev->parent) | 1039 | top_dev = top_dev->parent) |
1038 | /* Found device below root hub */; | 1040 | /* Found device below root hub */; |
1039 | faked_port_num = top_dev->portnum; | ||
1040 | for (i = 0, num_similar_speed_ports = 0; | ||
1041 | i < HCS_MAX_PORTS(xhci->hcs_params1); i++) { | ||
1042 | u8 port_speed = xhci->port_array[i]; | ||
1043 | |||
1044 | /* | ||
1045 | * Skip ports that don't have known speeds, or have duplicate | ||
1046 | * Extended Capabilities port speed entries. | ||
1047 | */ | ||
1048 | if (port_speed == 0 || port_speed == DUPLICATE_ENTRY) | ||
1049 | continue; | ||
1050 | 1041 | ||
1051 | /* | 1042 | return xhci_find_raw_port_number(hcd, top_dev->portnum); |
1052 | * USB 3.0 ports are always under a USB 3.0 hub. USB 2.0 and | ||
1053 | * 1.1 ports are under the USB 2.0 hub. If the port speed | ||
1054 | * matches the device speed, it's a similar speed port. | ||
1055 | */ | ||
1056 | if ((port_speed == 0x03) == (udev->speed == USB_SPEED_SUPER)) | ||
1057 | num_similar_speed_ports++; | ||
1058 | if (num_similar_speed_ports == faked_port_num) | ||
1059 | /* Roothub ports are numbered from 1 to N */ | ||
1060 | return i+1; | ||
1061 | } | ||
1062 | return 0; | ||
1063 | } | 1043 | } |
1064 | 1044 | ||
1065 | /* Setup an xHCI virtual device for a Set Address command */ | 1045 | /* Setup an xHCI virtual device for a Set Address command */ |
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c index af259e0ec172..1a30c380043c 100644 --- a/drivers/usb/host/xhci-pci.c +++ b/drivers/usb/host/xhci-pci.c | |||
@@ -313,6 +313,7 @@ static const struct hc_driver xhci_pci_hc_driver = { | |||
313 | .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, | 313 | .set_usb2_hw_lpm = xhci_set_usb2_hardware_lpm, |
314 | .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, | 314 | .enable_usb3_lpm_timeout = xhci_enable_usb3_lpm_timeout, |
315 | .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, | 315 | .disable_usb3_lpm_timeout = xhci_disable_usb3_lpm_timeout, |
316 | .find_raw_port_number = xhci_find_raw_port_number, | ||
316 | }; | 317 | }; |
317 | 318 | ||
318 | /*-------------------------------------------------------------------------*/ | 319 | /*-------------------------------------------------------------------------*/ |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index 882875465301..1969c001b3f9 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1599,14 +1599,20 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1599 | max_ports = HCS_MAX_PORTS(xhci->hcs_params1); | 1599 | max_ports = HCS_MAX_PORTS(xhci->hcs_params1); |
1600 | if ((port_id <= 0) || (port_id > max_ports)) { | 1600 | if ((port_id <= 0) || (port_id > max_ports)) { |
1601 | xhci_warn(xhci, "Invalid port id %d\n", port_id); | 1601 | xhci_warn(xhci, "Invalid port id %d\n", port_id); |
1602 | bogus_port_status = true; | 1602 | inc_deq(xhci, xhci->event_ring); |
1603 | goto cleanup; | 1603 | return; |
1604 | } | 1604 | } |
1605 | 1605 | ||
1606 | /* Figure out which usb_hcd this port is attached to: | 1606 | /* Figure out which usb_hcd this port is attached to: |
1607 | * is it a USB 3.0 port or a USB 2.0/1.1 port? | 1607 | * is it a USB 3.0 port or a USB 2.0/1.1 port? |
1608 | */ | 1608 | */ |
1609 | major_revision = xhci->port_array[port_id - 1]; | 1609 | major_revision = xhci->port_array[port_id - 1]; |
1610 | |||
1611 | /* Find the right roothub. */ | ||
1612 | hcd = xhci_to_hcd(xhci); | ||
1613 | if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) | ||
1614 | hcd = xhci->shared_hcd; | ||
1615 | |||
1610 | if (major_revision == 0) { | 1616 | if (major_revision == 0) { |
1611 | xhci_warn(xhci, "Event for port %u not in " | 1617 | xhci_warn(xhci, "Event for port %u not in " |
1612 | "Extended Capabilities, ignoring.\n", | 1618 | "Extended Capabilities, ignoring.\n", |
@@ -1629,10 +1635,6 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1629 | * into the index into the ports on the correct split roothub, and the | 1635 | * into the index into the ports on the correct split roothub, and the |
1630 | * correct bus_state structure. | 1636 | * correct bus_state structure. |
1631 | */ | 1637 | */ |
1632 | /* Find the right roothub. */ | ||
1633 | hcd = xhci_to_hcd(xhci); | ||
1634 | if ((major_revision == 0x03) != (hcd->speed == HCD_USB3)) | ||
1635 | hcd = xhci->shared_hcd; | ||
1636 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 1638 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
1637 | if (hcd->speed == HCD_USB3) | 1639 | if (hcd->speed == HCD_USB3) |
1638 | port_array = xhci->usb3_ports; | 1640 | port_array = xhci->usb3_ports; |
@@ -2027,8 +2029,8 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
2027 | if (event_trb != ep_ring->dequeue && | 2029 | if (event_trb != ep_ring->dequeue && |
2028 | event_trb != td->last_trb) | 2030 | event_trb != td->last_trb) |
2029 | td->urb->actual_length = | 2031 | td->urb->actual_length = |
2030 | td->urb->transfer_buffer_length | 2032 | td->urb->transfer_buffer_length - |
2031 | - TRB_LEN(le32_to_cpu(event->transfer_len)); | 2033 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); |
2032 | else | 2034 | else |
2033 | td->urb->actual_length = 0; | 2035 | td->urb->actual_length = 0; |
2034 | 2036 | ||
@@ -2060,7 +2062,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
2060 | /* Maybe the event was for the data stage? */ | 2062 | /* Maybe the event was for the data stage? */ |
2061 | td->urb->actual_length = | 2063 | td->urb->actual_length = |
2062 | td->urb->transfer_buffer_length - | 2064 | td->urb->transfer_buffer_length - |
2063 | TRB_LEN(le32_to_cpu(event->transfer_len)); | 2065 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); |
2064 | xhci_dbg(xhci, "Waiting for status " | 2066 | xhci_dbg(xhci, "Waiting for status " |
2065 | "stage event\n"); | 2067 | "stage event\n"); |
2066 | return 0; | 2068 | return 0; |
@@ -2096,7 +2098,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
2096 | /* handle completion code */ | 2098 | /* handle completion code */ |
2097 | switch (trb_comp_code) { | 2099 | switch (trb_comp_code) { |
2098 | case COMP_SUCCESS: | 2100 | case COMP_SUCCESS: |
2099 | if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { | 2101 | if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) { |
2100 | frame->status = 0; | 2102 | frame->status = 0; |
2101 | break; | 2103 | break; |
2102 | } | 2104 | } |
@@ -2141,7 +2143,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
2141 | len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); | 2143 | len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])); |
2142 | } | 2144 | } |
2143 | len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - | 2145 | len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - |
2144 | TRB_LEN(le32_to_cpu(event->transfer_len)); | 2146 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); |
2145 | 2147 | ||
2146 | if (trb_comp_code != COMP_STOP_INVAL) { | 2148 | if (trb_comp_code != COMP_STOP_INVAL) { |
2147 | frame->actual_length = len; | 2149 | frame->actual_length = len; |
@@ -2199,7 +2201,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
2199 | case COMP_SUCCESS: | 2201 | case COMP_SUCCESS: |
2200 | /* Double check that the HW transferred everything. */ | 2202 | /* Double check that the HW transferred everything. */ |
2201 | if (event_trb != td->last_trb || | 2203 | if (event_trb != td->last_trb || |
2202 | TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { | 2204 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { |
2203 | xhci_warn(xhci, "WARN Successful completion " | 2205 | xhci_warn(xhci, "WARN Successful completion " |
2204 | "on short TX\n"); | 2206 | "on short TX\n"); |
2205 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | 2207 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) |
@@ -2227,18 +2229,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
2227 | "%d bytes untransferred\n", | 2229 | "%d bytes untransferred\n", |
2228 | td->urb->ep->desc.bEndpointAddress, | 2230 | td->urb->ep->desc.bEndpointAddress, |
2229 | td->urb->transfer_buffer_length, | 2231 | td->urb->transfer_buffer_length, |
2230 | TRB_LEN(le32_to_cpu(event->transfer_len))); | 2232 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); |
2231 | /* Fast path - was this the last TRB in the TD for this URB? */ | 2233 | /* Fast path - was this the last TRB in the TD for this URB? */ |
2232 | if (event_trb == td->last_trb) { | 2234 | if (event_trb == td->last_trb) { |
2233 | if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { | 2235 | if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) { |
2234 | td->urb->actual_length = | 2236 | td->urb->actual_length = |
2235 | td->urb->transfer_buffer_length - | 2237 | td->urb->transfer_buffer_length - |
2236 | TRB_LEN(le32_to_cpu(event->transfer_len)); | 2238 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); |
2237 | if (td->urb->transfer_buffer_length < | 2239 | if (td->urb->transfer_buffer_length < |
2238 | td->urb->actual_length) { | 2240 | td->urb->actual_length) { |
2239 | xhci_warn(xhci, "HC gave bad length " | 2241 | xhci_warn(xhci, "HC gave bad length " |
2240 | "of %d bytes left\n", | 2242 | "of %d bytes left\n", |
2241 | TRB_LEN(le32_to_cpu(event->transfer_len))); | 2243 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len))); |
2242 | td->urb->actual_length = 0; | 2244 | td->urb->actual_length = 0; |
2243 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) | 2245 | if (td->urb->transfer_flags & URB_SHORT_NOT_OK) |
2244 | *status = -EREMOTEIO; | 2246 | *status = -EREMOTEIO; |
@@ -2280,7 +2282,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td, | |||
2280 | if (trb_comp_code != COMP_STOP_INVAL) | 2282 | if (trb_comp_code != COMP_STOP_INVAL) |
2281 | td->urb->actual_length += | 2283 | td->urb->actual_length += |
2282 | TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - | 2284 | TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) - |
2283 | TRB_LEN(le32_to_cpu(event->transfer_len)); | 2285 | EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)); |
2284 | } | 2286 | } |
2285 | 2287 | ||
2286 | return finish_td(xhci, td, event_trb, event, ep, status, false); | 2288 | return finish_td(xhci, td, event_trb, event, ep, status, false); |
@@ -2368,7 +2370,7 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2368 | * transfer type | 2370 | * transfer type |
2369 | */ | 2371 | */ |
2370 | case COMP_SUCCESS: | 2372 | case COMP_SUCCESS: |
2371 | if (TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) | 2373 | if (EVENT_TRB_LEN(le32_to_cpu(event->transfer_len)) == 0) |
2372 | break; | 2374 | break; |
2373 | if (xhci->quirks & XHCI_TRUST_TX_LENGTH) | 2375 | if (xhci->quirks & XHCI_TRUST_TX_LENGTH) |
2374 | trb_comp_code = COMP_SHORT_TX; | 2376 | trb_comp_code = COMP_SHORT_TX; |
@@ -2461,14 +2463,21 @@ static int handle_tx_event(struct xhci_hcd *xhci, | |||
2461 | * TD list. | 2463 | * TD list. |
2462 | */ | 2464 | */ |
2463 | if (list_empty(&ep_ring->td_list)) { | 2465 | if (list_empty(&ep_ring->td_list)) { |
2464 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d " | 2466 | /* |
2465 | "with no TDs queued?\n", | 2467 | * A stopped endpoint may generate an extra completion |
2466 | TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), | 2468 | * event if the device was suspended. Don't print |
2467 | ep_index); | 2469 | * warnings. |
2468 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | 2470 | */ |
2469 | (le32_to_cpu(event->flags) & | 2471 | if (!(trb_comp_code == COMP_STOP || |
2470 | TRB_TYPE_BITMASK)>>10); | 2472 | trb_comp_code == COMP_STOP_INVAL)) { |
2471 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); | 2473 | xhci_warn(xhci, "WARN Event TRB for slot %d ep %d with no TDs queued?\n", |
2474 | TRB_TO_SLOT_ID(le32_to_cpu(event->flags)), | ||
2475 | ep_index); | ||
2476 | xhci_dbg(xhci, "Event TRB with TRB type ID %u\n", | ||
2477 | (le32_to_cpu(event->flags) & | ||
2478 | TRB_TYPE_BITMASK)>>10); | ||
2479 | xhci_print_trb_offsets(xhci, (union xhci_trb *) event); | ||
2480 | } | ||
2472 | if (ep->skip) { | 2481 | if (ep->skip) { |
2473 | ep->skip = false; | 2482 | ep->skip = false; |
2474 | xhci_dbg(xhci, "td_list is empty while skip " | 2483 | xhci_dbg(xhci, "td_list is empty while skip " |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index f1f01a834ba7..53b8f89a0b1c 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -350,7 +350,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) | |||
350 | * generate interrupts. Don't even try to enable MSI. | 350 | * generate interrupts. Don't even try to enable MSI. |
351 | */ | 351 | */ |
352 | if (xhci->quirks & XHCI_BROKEN_MSI) | 352 | if (xhci->quirks & XHCI_BROKEN_MSI) |
353 | return 0; | 353 | goto legacy_irq; |
354 | 354 | ||
355 | /* unregister the legacy interrupt */ | 355 | /* unregister the legacy interrupt */ |
356 | if (hcd->irq) | 356 | if (hcd->irq) |
@@ -371,6 +371,7 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd) | |||
371 | return -EINVAL; | 371 | return -EINVAL; |
372 | } | 372 | } |
373 | 373 | ||
374 | legacy_irq: | ||
374 | /* fall back to legacy interrupt*/ | 375 | /* fall back to legacy interrupt*/ |
375 | ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, | 376 | ret = request_irq(pdev->irq, &usb_hcd_irq, IRQF_SHARED, |
376 | hcd->irq_descr, hcd); | 377 | hcd->irq_descr, hcd); |
@@ -3778,6 +3779,28 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev) | |||
3778 | return 0; | 3779 | return 0; |
3779 | } | 3780 | } |
3780 | 3781 | ||
3782 | /* | ||
3783 | * Transfer the port index into real index in the HW port status | ||
3784 | * registers. Caculate offset between the port's PORTSC register | ||
3785 | * and port status base. Divide the number of per port register | ||
3786 | * to get the real index. The raw port number bases 1. | ||
3787 | */ | ||
3788 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1) | ||
3789 | { | ||
3790 | struct xhci_hcd *xhci = hcd_to_xhci(hcd); | ||
3791 | __le32 __iomem *base_addr = &xhci->op_regs->port_status_base; | ||
3792 | __le32 __iomem *addr; | ||
3793 | int raw_port; | ||
3794 | |||
3795 | if (hcd->speed != HCD_USB3) | ||
3796 | addr = xhci->usb2_ports[port1 - 1]; | ||
3797 | else | ||
3798 | addr = xhci->usb3_ports[port1 - 1]; | ||
3799 | |||
3800 | raw_port = (addr - base_addr)/NUM_PORT_REGS + 1; | ||
3801 | return raw_port; | ||
3802 | } | ||
3803 | |||
3781 | #ifdef CONFIG_USB_SUSPEND | 3804 | #ifdef CONFIG_USB_SUSPEND |
3782 | 3805 | ||
3783 | /* BESL to HIRD Encoding array for USB2 LPM */ | 3806 | /* BESL to HIRD Encoding array for USB2 LPM */ |
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h index f791bd0aee6c..63582719e0fb 100644 --- a/drivers/usb/host/xhci.h +++ b/drivers/usb/host/xhci.h | |||
@@ -206,8 +206,8 @@ struct xhci_op_regs { | |||
206 | /* bits 12:31 are reserved (and should be preserved on writes). */ | 206 | /* bits 12:31 are reserved (and should be preserved on writes). */ |
207 | 207 | ||
208 | /* IMAN - Interrupt Management Register */ | 208 | /* IMAN - Interrupt Management Register */ |
209 | #define IMAN_IP (1 << 1) | 209 | #define IMAN_IE (1 << 1) |
210 | #define IMAN_IE (1 << 0) | 210 | #define IMAN_IP (1 << 0) |
211 | 211 | ||
212 | /* USBSTS - USB status - status bitmasks */ | 212 | /* USBSTS - USB status - status bitmasks */ |
213 | /* HC not running - set to 1 when run/stop bit is cleared. */ | 213 | /* HC not running - set to 1 when run/stop bit is cleared. */ |
@@ -972,6 +972,10 @@ struct xhci_transfer_event { | |||
972 | __le32 flags; | 972 | __le32 flags; |
973 | }; | 973 | }; |
974 | 974 | ||
975 | /* Transfer event TRB length bit mask */ | ||
976 | /* bits 0:23 */ | ||
977 | #define EVENT_TRB_LEN(p) ((p) & 0xffffff) | ||
978 | |||
975 | /** Transfer Event bit fields **/ | 979 | /** Transfer Event bit fields **/ |
976 | #define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) | 980 | #define TRB_TO_EP_ID(p) (((p) >> 16) & 0x1f) |
977 | 981 | ||
@@ -1829,6 +1833,7 @@ void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array, | |||
1829 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, | 1833 | int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, u16 wIndex, |
1830 | char *buf, u16 wLength); | 1834 | char *buf, u16 wLength); |
1831 | int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); | 1835 | int xhci_hub_status_data(struct usb_hcd *hcd, char *buf); |
1836 | int xhci_find_raw_port_number(struct usb_hcd *hcd, int port1); | ||
1832 | 1837 | ||
1833 | #ifdef CONFIG_PM | 1838 | #ifdef CONFIG_PM |
1834 | int xhci_bus_suspend(struct usb_hcd *hcd); | 1839 | int xhci_bus_suspend(struct usb_hcd *hcd); |
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig index 45b19e2c60ba..05e51432dd2f 100644 --- a/drivers/usb/musb/Kconfig +++ b/drivers/usb/musb/Kconfig | |||
@@ -7,11 +7,6 @@ | |||
7 | config USB_MUSB_HDRC | 7 | config USB_MUSB_HDRC |
8 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' | 8 | tristate 'Inventra Highspeed Dual Role Controller (TI, ADI, ...)' |
9 | depends on USB && USB_GADGET | 9 | depends on USB && USB_GADGET |
10 | select NOP_USB_XCEIV if (ARCH_DAVINCI || MACH_OMAP3EVM || BLACKFIN) | ||
11 | select NOP_USB_XCEIV if (SOC_TI81XX || SOC_AM33XX) | ||
12 | select TWL4030_USB if MACH_OMAP_3430SDP | ||
13 | select TWL6030_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA | ||
14 | select OMAP_CONTROL_USB if MACH_OMAP_4430SDP || MACH_OMAP4_PANDA | ||
15 | select USB_OTG_UTILS | 10 | select USB_OTG_UTILS |
16 | help | 11 | help |
17 | Say Y here if your system has a dual role high speed USB | 12 | Say Y here if your system has a dual role high speed USB |
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c index 7c71769d71ff..41613a2b35e8 100644 --- a/drivers/usb/musb/da8xx.c +++ b/drivers/usb/musb/da8xx.c | |||
@@ -327,7 +327,7 @@ static irqreturn_t da8xx_musb_interrupt(int irq, void *hci) | |||
327 | u8 devctl = musb_readb(mregs, MUSB_DEVCTL); | 327 | u8 devctl = musb_readb(mregs, MUSB_DEVCTL); |
328 | int err; | 328 | int err; |
329 | 329 | ||
330 | err = musb->int_usb & USB_INTR_VBUSERROR; | 330 | err = musb->int_usb & MUSB_INTR_VBUSERROR; |
331 | if (err) { | 331 | if (err) { |
332 | /* | 332 | /* |
333 | * The Mentor core doesn't debounce VBUS as needed | 333 | * The Mentor core doesn't debounce VBUS as needed |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 60b41cc28da4..daec6e0f7e38 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -1624,8 +1624,6 @@ EXPORT_SYMBOL_GPL(musb_dma_completion); | |||
1624 | 1624 | ||
1625 | /*-------------------------------------------------------------------------*/ | 1625 | /*-------------------------------------------------------------------------*/ |
1626 | 1626 | ||
1627 | #ifdef CONFIG_SYSFS | ||
1628 | |||
1629 | static ssize_t | 1627 | static ssize_t |
1630 | musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf) | 1628 | musb_mode_show(struct device *dev, struct device_attribute *attr, char *buf) |
1631 | { | 1629 | { |
@@ -1742,8 +1740,6 @@ static const struct attribute_group musb_attr_group = { | |||
1742 | .attrs = musb_attributes, | 1740 | .attrs = musb_attributes, |
1743 | }; | 1741 | }; |
1744 | 1742 | ||
1745 | #endif /* sysfs */ | ||
1746 | |||
1747 | /* Only used to provide driver mode change events */ | 1743 | /* Only used to provide driver mode change events */ |
1748 | static void musb_irq_work(struct work_struct *data) | 1744 | static void musb_irq_work(struct work_struct *data) |
1749 | { | 1745 | { |
@@ -1968,11 +1964,9 @@ musb_init_controller(struct device *dev, int nIrq, void __iomem *ctrl) | |||
1968 | if (status < 0) | 1964 | if (status < 0) |
1969 | goto fail4; | 1965 | goto fail4; |
1970 | 1966 | ||
1971 | #ifdef CONFIG_SYSFS | ||
1972 | status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); | 1967 | status = sysfs_create_group(&musb->controller->kobj, &musb_attr_group); |
1973 | if (status) | 1968 | if (status) |
1974 | goto fail5; | 1969 | goto fail5; |
1975 | #endif | ||
1976 | 1970 | ||
1977 | pm_runtime_put(musb->controller); | 1971 | pm_runtime_put(musb->controller); |
1978 | 1972 | ||
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c index be18537c5f14..83eddedcd9be 100644 --- a/drivers/usb/musb/musb_gadget.c +++ b/drivers/usb/musb/musb_gadget.c | |||
@@ -141,7 +141,9 @@ static inline void map_dma_buffer(struct musb_request *request, | |||
141 | static inline void unmap_dma_buffer(struct musb_request *request, | 141 | static inline void unmap_dma_buffer(struct musb_request *request, |
142 | struct musb *musb) | 142 | struct musb *musb) |
143 | { | 143 | { |
144 | if (!is_buffer_mapped(request)) | 144 | struct musb_ep *musb_ep = request->ep; |
145 | |||
146 | if (!is_buffer_mapped(request) || !musb_ep->dma) | ||
145 | return; | 147 | return; |
146 | 148 | ||
147 | if (request->request.dma == DMA_ADDR_INVALID) { | 149 | if (request->request.dma == DMA_ADDR_INVALID) { |
@@ -195,7 +197,10 @@ __acquires(ep->musb->lock) | |||
195 | 197 | ||
196 | ep->busy = 1; | 198 | ep->busy = 1; |
197 | spin_unlock(&musb->lock); | 199 | spin_unlock(&musb->lock); |
198 | unmap_dma_buffer(req, musb); | 200 | |
201 | if (!dma_mapping_error(&musb->g.dev, request->dma)) | ||
202 | unmap_dma_buffer(req, musb); | ||
203 | |||
199 | if (request->status == 0) | 204 | if (request->status == 0) |
200 | dev_dbg(musb->controller, "%s done request %p, %d/%d\n", | 205 | dev_dbg(musb->controller, "%s done request %p, %d/%d\n", |
201 | ep->end_point.name, request, | 206 | ep->end_point.name, request, |
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c index 1762354fe793..1a42a458f2c4 100644 --- a/drivers/usb/musb/omap2430.c +++ b/drivers/usb/musb/omap2430.c | |||
@@ -51,7 +51,7 @@ struct omap2430_glue { | |||
51 | }; | 51 | }; |
52 | #define glue_to_musb(g) platform_get_drvdata(g->musb) | 52 | #define glue_to_musb(g) platform_get_drvdata(g->musb) |
53 | 53 | ||
54 | struct omap2430_glue *_glue; | 54 | static struct omap2430_glue *_glue; |
55 | 55 | ||
56 | static struct timer_list musb_idle_timer; | 56 | static struct timer_list musb_idle_timer; |
57 | 57 | ||
@@ -237,9 +237,13 @@ void omap_musb_mailbox(enum omap_musb_vbus_id_status status) | |||
237 | { | 237 | { |
238 | struct omap2430_glue *glue = _glue; | 238 | struct omap2430_glue *glue = _glue; |
239 | 239 | ||
240 | if (glue && glue_to_musb(glue)) { | 240 | if (!glue) { |
241 | glue->status = status; | 241 | pr_err("%s: musb core is not yet initialized\n", __func__); |
242 | } else { | 242 | return; |
243 | } | ||
244 | glue->status = status; | ||
245 | |||
246 | if (!glue_to_musb(glue)) { | ||
243 | pr_err("%s: musb core is not yet ready\n", __func__); | 247 | pr_err("%s: musb core is not yet ready\n", __func__); |
244 | return; | 248 | return; |
245 | } | 249 | } |
diff --git a/drivers/usb/otg/otg.c b/drivers/usb/otg/otg.c index e1814397ca3a..2bd03d261a50 100644 --- a/drivers/usb/otg/otg.c +++ b/drivers/usb/otg/otg.c | |||
@@ -130,7 +130,7 @@ struct usb_phy *usb_get_phy(enum usb_phy_type type) | |||
130 | spin_lock_irqsave(&phy_lock, flags); | 130 | spin_lock_irqsave(&phy_lock, flags); |
131 | 131 | ||
132 | phy = __usb_find_phy(&phy_list, type); | 132 | phy = __usb_find_phy(&phy_list, type); |
133 | if (IS_ERR(phy)) { | 133 | if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { |
134 | pr_err("unable to find transceiver of type %s\n", | 134 | pr_err("unable to find transceiver of type %s\n", |
135 | usb_phy_type_string(type)); | 135 | usb_phy_type_string(type)); |
136 | goto err0; | 136 | goto err0; |
@@ -228,7 +228,7 @@ struct usb_phy *usb_get_phy_dev(struct device *dev, u8 index) | |||
228 | spin_lock_irqsave(&phy_lock, flags); | 228 | spin_lock_irqsave(&phy_lock, flags); |
229 | 229 | ||
230 | phy = __usb_find_phy_dev(dev, &phy_bind_list, index); | 230 | phy = __usb_find_phy_dev(dev, &phy_bind_list, index); |
231 | if (IS_ERR(phy)) { | 231 | if (IS_ERR(phy) || !try_module_get(phy->dev->driver->owner)) { |
232 | pr_err("unable to find transceiver\n"); | 232 | pr_err("unable to find transceiver\n"); |
233 | goto err0; | 233 | goto err0; |
234 | } | 234 | } |
@@ -301,8 +301,12 @@ EXPORT_SYMBOL(devm_usb_put_phy); | |||
301 | */ | 301 | */ |
302 | void usb_put_phy(struct usb_phy *x) | 302 | void usb_put_phy(struct usb_phy *x) |
303 | { | 303 | { |
304 | if (x) | 304 | if (x) { |
305 | struct module *owner = x->dev->driver->owner; | ||
306 | |||
305 | put_device(x->dev); | 307 | put_device(x->dev); |
308 | module_put(owner); | ||
309 | } | ||
306 | } | 310 | } |
307 | EXPORT_SYMBOL(usb_put_phy); | 311 | EXPORT_SYMBOL(usb_put_phy); |
308 | 312 | ||
diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig index 65217a590068..90549382eba5 100644 --- a/drivers/usb/phy/Kconfig +++ b/drivers/usb/phy/Kconfig | |||
@@ -38,6 +38,7 @@ config USB_ISP1301 | |||
38 | tristate "NXP ISP1301 USB transceiver support" | 38 | tristate "NXP ISP1301 USB transceiver support" |
39 | depends on USB || USB_GADGET | 39 | depends on USB || USB_GADGET |
40 | depends on I2C | 40 | depends on I2C |
41 | select USB_OTG_UTILS | ||
41 | help | 42 | help |
42 | Say Y here to add support for the NXP ISP1301 USB transceiver driver. | 43 | Say Y here to add support for the NXP ISP1301 USB transceiver driver. |
43 | This chip is typically used as USB transceiver for USB host, gadget | 44 | This chip is typically used as USB transceiver for USB host, gadget |
diff --git a/drivers/usb/phy/omap-control-usb.c b/drivers/usb/phy/omap-control-usb.c index 5323b71c3521..1419ceda9759 100644 --- a/drivers/usb/phy/omap-control-usb.c +++ b/drivers/usb/phy/omap-control-usb.c | |||
@@ -219,32 +219,26 @@ static int omap_control_usb_probe(struct platform_device *pdev) | |||
219 | 219 | ||
220 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 220 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
221 | "control_dev_conf"); | 221 | "control_dev_conf"); |
222 | control_usb->dev_conf = devm_request_and_ioremap(&pdev->dev, res); | 222 | control_usb->dev_conf = devm_ioremap_resource(&pdev->dev, res); |
223 | if (!control_usb->dev_conf) { | 223 | if (IS_ERR(control_usb->dev_conf)) |
224 | dev_err(&pdev->dev, "Failed to obtain io memory\n"); | 224 | return PTR_ERR(control_usb->dev_conf); |
225 | return -EADDRNOTAVAIL; | ||
226 | } | ||
227 | 225 | ||
228 | if (control_usb->type == OMAP_CTRL_DEV_TYPE1) { | 226 | if (control_usb->type == OMAP_CTRL_DEV_TYPE1) { |
229 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 227 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
230 | "otghs_control"); | 228 | "otghs_control"); |
231 | control_usb->otghs_control = devm_request_and_ioremap( | 229 | control_usb->otghs_control = devm_ioremap_resource( |
232 | &pdev->dev, res); | 230 | &pdev->dev, res); |
233 | if (!control_usb->otghs_control) { | 231 | if (IS_ERR(control_usb->otghs_control)) |
234 | dev_err(&pdev->dev, "Failed to obtain io memory\n"); | 232 | return PTR_ERR(control_usb->otghs_control); |
235 | return -EADDRNOTAVAIL; | ||
236 | } | ||
237 | } | 233 | } |
238 | 234 | ||
239 | if (control_usb->type == OMAP_CTRL_DEV_TYPE2) { | 235 | if (control_usb->type == OMAP_CTRL_DEV_TYPE2) { |
240 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, | 236 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, |
241 | "phy_power_usb"); | 237 | "phy_power_usb"); |
242 | control_usb->phy_power = devm_request_and_ioremap( | 238 | control_usb->phy_power = devm_ioremap_resource( |
243 | &pdev->dev, res); | 239 | &pdev->dev, res); |
244 | if (!control_usb->phy_power) { | 240 | if (IS_ERR(control_usb->phy_power)) |
245 | dev_dbg(&pdev->dev, "Failed to obtain io memory\n"); | 241 | return PTR_ERR(control_usb->phy_power); |
246 | return -EADDRNOTAVAIL; | ||
247 | } | ||
248 | 242 | ||
249 | control_usb->sys_clk = devm_clk_get(control_usb->dev, | 243 | control_usb->sys_clk = devm_clk_get(control_usb->dev, |
250 | "sys_clkin"); | 244 | "sys_clkin"); |
diff --git a/drivers/usb/phy/omap-usb3.c b/drivers/usb/phy/omap-usb3.c index fadc0c2b65bb..a6e60b1e102e 100644 --- a/drivers/usb/phy/omap-usb3.c +++ b/drivers/usb/phy/omap-usb3.c | |||
@@ -212,11 +212,9 @@ static int omap_usb3_probe(struct platform_device *pdev) | |||
212 | } | 212 | } |
213 | 213 | ||
214 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); | 214 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pll_ctrl"); |
215 | phy->pll_ctrl_base = devm_request_and_ioremap(&pdev->dev, res); | 215 | phy->pll_ctrl_base = devm_ioremap_resource(&pdev->dev, res); |
216 | if (!phy->pll_ctrl_base) { | 216 | if (IS_ERR(phy->pll_ctrl_base)) |
217 | dev_err(&pdev->dev, "ioremap of pll_ctrl failed\n"); | 217 | return PTR_ERR(phy->pll_ctrl_base); |
218 | return -ENOMEM; | ||
219 | } | ||
220 | 218 | ||
221 | phy->dev = &pdev->dev; | 219 | phy->dev = &pdev->dev; |
222 | 220 | ||
diff --git a/drivers/usb/phy/samsung-usbphy.c b/drivers/usb/phy/samsung-usbphy.c index 6ea553733832..967101ec15fd 100644 --- a/drivers/usb/phy/samsung-usbphy.c +++ b/drivers/usb/phy/samsung-usbphy.c | |||
@@ -787,11 +787,9 @@ static int samsung_usbphy_probe(struct platform_device *pdev) | |||
787 | return -ENODEV; | 787 | return -ENODEV; |
788 | } | 788 | } |
789 | 789 | ||
790 | phy_base = devm_request_and_ioremap(dev, phy_mem); | 790 | phy_base = devm_ioremap_resource(dev, phy_mem); |
791 | if (!phy_base) { | 791 | if (IS_ERR(phy_base)) |
792 | dev_err(dev, "%s: register mapping failed\n", __func__); | 792 | return PTR_ERR(phy_base); |
793 | return -ENXIO; | ||
794 | } | ||
795 | 793 | ||
796 | sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); | 794 | sphy = devm_kzalloc(dev, sizeof(*sphy), GFP_KERNEL); |
797 | if (!sphy) | 795 | if (!sphy) |
diff --git a/drivers/usb/serial/ark3116.c b/drivers/usb/serial/ark3116.c index cbd904b8fba5..4775f8209e55 100644 --- a/drivers/usb/serial/ark3116.c +++ b/drivers/usb/serial/ark3116.c | |||
@@ -62,7 +62,6 @@ static int is_irda(struct usb_serial *serial) | |||
62 | } | 62 | } |
63 | 63 | ||
64 | struct ark3116_private { | 64 | struct ark3116_private { |
65 | wait_queue_head_t delta_msr_wait; | ||
66 | struct async_icount icount; | 65 | struct async_icount icount; |
67 | int irda; /* 1 for irda device */ | 66 | int irda; /* 1 for irda device */ |
68 | 67 | ||
@@ -146,7 +145,6 @@ static int ark3116_port_probe(struct usb_serial_port *port) | |||
146 | if (!priv) | 145 | if (!priv) |
147 | return -ENOMEM; | 146 | return -ENOMEM; |
148 | 147 | ||
149 | init_waitqueue_head(&priv->delta_msr_wait); | ||
150 | mutex_init(&priv->hw_lock); | 148 | mutex_init(&priv->hw_lock); |
151 | spin_lock_init(&priv->status_lock); | 149 | spin_lock_init(&priv->status_lock); |
152 | 150 | ||
@@ -456,10 +454,14 @@ static int ark3116_ioctl(struct tty_struct *tty, | |||
456 | case TIOCMIWAIT: | 454 | case TIOCMIWAIT: |
457 | for (;;) { | 455 | for (;;) { |
458 | struct async_icount prev = priv->icount; | 456 | struct async_icount prev = priv->icount; |
459 | interruptible_sleep_on(&priv->delta_msr_wait); | 457 | interruptible_sleep_on(&port->delta_msr_wait); |
460 | /* see if a signal did it */ | 458 | /* see if a signal did it */ |
461 | if (signal_pending(current)) | 459 | if (signal_pending(current)) |
462 | return -ERESTARTSYS; | 460 | return -ERESTARTSYS; |
461 | |||
462 | if (port->serial->disconnected) | ||
463 | return -EIO; | ||
464 | |||
463 | if ((prev.rng == priv->icount.rng) && | 465 | if ((prev.rng == priv->icount.rng) && |
464 | (prev.dsr == priv->icount.dsr) && | 466 | (prev.dsr == priv->icount.dsr) && |
465 | (prev.dcd == priv->icount.dcd) && | 467 | (prev.dcd == priv->icount.dcd) && |
@@ -580,7 +582,7 @@ static void ark3116_update_msr(struct usb_serial_port *port, __u8 msr) | |||
580 | priv->icount.dcd++; | 582 | priv->icount.dcd++; |
581 | if (msr & UART_MSR_TERI) | 583 | if (msr & UART_MSR_TERI) |
582 | priv->icount.rng++; | 584 | priv->icount.rng++; |
583 | wake_up_interruptible(&priv->delta_msr_wait); | 585 | wake_up_interruptible(&port->delta_msr_wait); |
584 | } | 586 | } |
585 | } | 587 | } |
586 | 588 | ||
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index d255f66e708e..07d4650a32ab 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c | |||
@@ -80,7 +80,6 @@ MODULE_DEVICE_TABLE(usb, id_table); | |||
80 | 80 | ||
81 | struct ch341_private { | 81 | struct ch341_private { |
82 | spinlock_t lock; /* access lock */ | 82 | spinlock_t lock; /* access lock */ |
83 | wait_queue_head_t delta_msr_wait; /* wait queue for modem status */ | ||
84 | unsigned baud_rate; /* set baud rate */ | 83 | unsigned baud_rate; /* set baud rate */ |
85 | u8 line_control; /* set line control value RTS/DTR */ | 84 | u8 line_control; /* set line control value RTS/DTR */ |
86 | u8 line_status; /* active status of modem control inputs */ | 85 | u8 line_status; /* active status of modem control inputs */ |
@@ -252,7 +251,6 @@ static int ch341_port_probe(struct usb_serial_port *port) | |||
252 | return -ENOMEM; | 251 | return -ENOMEM; |
253 | 252 | ||
254 | spin_lock_init(&priv->lock); | 253 | spin_lock_init(&priv->lock); |
255 | init_waitqueue_head(&priv->delta_msr_wait); | ||
256 | priv->baud_rate = DEFAULT_BAUD_RATE; | 254 | priv->baud_rate = DEFAULT_BAUD_RATE; |
257 | priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; | 255 | priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; |
258 | 256 | ||
@@ -298,7 +296,7 @@ static void ch341_dtr_rts(struct usb_serial_port *port, int on) | |||
298 | priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR); | 296 | priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR); |
299 | spin_unlock_irqrestore(&priv->lock, flags); | 297 | spin_unlock_irqrestore(&priv->lock, flags); |
300 | ch341_set_handshake(port->serial->dev, priv->line_control); | 298 | ch341_set_handshake(port->serial->dev, priv->line_control); |
301 | wake_up_interruptible(&priv->delta_msr_wait); | 299 | wake_up_interruptible(&port->delta_msr_wait); |
302 | } | 300 | } |
303 | 301 | ||
304 | static void ch341_close(struct usb_serial_port *port) | 302 | static void ch341_close(struct usb_serial_port *port) |
@@ -491,7 +489,7 @@ static void ch341_read_int_callback(struct urb *urb) | |||
491 | tty_kref_put(tty); | 489 | tty_kref_put(tty); |
492 | } | 490 | } |
493 | 491 | ||
494 | wake_up_interruptible(&priv->delta_msr_wait); | 492 | wake_up_interruptible(&port->delta_msr_wait); |
495 | } | 493 | } |
496 | 494 | ||
497 | exit: | 495 | exit: |
@@ -517,11 +515,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
517 | spin_unlock_irqrestore(&priv->lock, flags); | 515 | spin_unlock_irqrestore(&priv->lock, flags); |
518 | 516 | ||
519 | while (!multi_change) { | 517 | while (!multi_change) { |
520 | interruptible_sleep_on(&priv->delta_msr_wait); | 518 | interruptible_sleep_on(&port->delta_msr_wait); |
521 | /* see if a signal did it */ | 519 | /* see if a signal did it */ |
522 | if (signal_pending(current)) | 520 | if (signal_pending(current)) |
523 | return -ERESTARTSYS; | 521 | return -ERESTARTSYS; |
524 | 522 | ||
523 | if (port->serial->disconnected) | ||
524 | return -EIO; | ||
525 | |||
525 | spin_lock_irqsave(&priv->lock, flags); | 526 | spin_lock_irqsave(&priv->lock, flags); |
526 | status = priv->line_status; | 527 | status = priv->line_status; |
527 | multi_change = priv->multi_status_change; | 528 | multi_change = priv->multi_status_change; |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index edc0f0dcad83..4747d1c328ff 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -85,6 +85,7 @@ static const struct usb_device_id id_table[] = { | |||
85 | { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ | 85 | { USB_DEVICE(0x10C4, 0x813F) }, /* Tams Master Easy Control */ |
86 | { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ | 86 | { USB_DEVICE(0x10C4, 0x814A) }, /* West Mountain Radio RIGblaster P&P */ |
87 | { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ | 87 | { USB_DEVICE(0x10C4, 0x814B) }, /* West Mountain Radio RIGtalk */ |
88 | { USB_DEVICE(0x2405, 0x0003) }, /* West Mountain Radio RIGblaster Advantage */ | ||
88 | { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ | 89 | { USB_DEVICE(0x10C4, 0x8156) }, /* B&G H3000 link cable */ |
89 | { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ | 90 | { USB_DEVICE(0x10C4, 0x815E) }, /* Helicomm IP-Link 1220-DVM */ |
90 | { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ | 91 | { USB_DEVICE(0x10C4, 0x815F) }, /* Timewave HamLinkUSB */ |
@@ -150,6 +151,25 @@ static const struct usb_device_id id_table[] = { | |||
150 | { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ | 151 | { USB_DEVICE(0x1BE3, 0x07A6) }, /* WAGO 750-923 USB Service Cable */ |
151 | { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ | 152 | { USB_DEVICE(0x1E29, 0x0102) }, /* Festo CPX-USB */ |
152 | { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ | 153 | { USB_DEVICE(0x1E29, 0x0501) }, /* Festo CMSP */ |
154 | { USB_DEVICE(0x1FB9, 0x0100) }, /* Lake Shore Model 121 Current Source */ | ||
155 | { USB_DEVICE(0x1FB9, 0x0200) }, /* Lake Shore Model 218A Temperature Monitor */ | ||
156 | { USB_DEVICE(0x1FB9, 0x0201) }, /* Lake Shore Model 219 Temperature Monitor */ | ||
157 | { USB_DEVICE(0x1FB9, 0x0202) }, /* Lake Shore Model 233 Temperature Transmitter */ | ||
158 | { USB_DEVICE(0x1FB9, 0x0203) }, /* Lake Shore Model 235 Temperature Transmitter */ | ||
159 | { USB_DEVICE(0x1FB9, 0x0300) }, /* Lake Shore Model 335 Temperature Controller */ | ||
160 | { USB_DEVICE(0x1FB9, 0x0301) }, /* Lake Shore Model 336 Temperature Controller */ | ||
161 | { USB_DEVICE(0x1FB9, 0x0302) }, /* Lake Shore Model 350 Temperature Controller */ | ||
162 | { USB_DEVICE(0x1FB9, 0x0303) }, /* Lake Shore Model 371 AC Bridge */ | ||
163 | { USB_DEVICE(0x1FB9, 0x0400) }, /* Lake Shore Model 411 Handheld Gaussmeter */ | ||
164 | { USB_DEVICE(0x1FB9, 0x0401) }, /* Lake Shore Model 425 Gaussmeter */ | ||
165 | { USB_DEVICE(0x1FB9, 0x0402) }, /* Lake Shore Model 455A Gaussmeter */ | ||
166 | { USB_DEVICE(0x1FB9, 0x0403) }, /* Lake Shore Model 475A Gaussmeter */ | ||
167 | { USB_DEVICE(0x1FB9, 0x0404) }, /* Lake Shore Model 465 Three Axis Gaussmeter */ | ||
168 | { USB_DEVICE(0x1FB9, 0x0600) }, /* Lake Shore Model 625A Superconducting MPS */ | ||
169 | { USB_DEVICE(0x1FB9, 0x0601) }, /* Lake Shore Model 642A Magnet Power Supply */ | ||
170 | { USB_DEVICE(0x1FB9, 0x0602) }, /* Lake Shore Model 648 Magnet Power Supply */ | ||
171 | { USB_DEVICE(0x1FB9, 0x0700) }, /* Lake Shore Model 737 VSM Controller */ | ||
172 | { USB_DEVICE(0x1FB9, 0x0701) }, /* Lake Shore Model 776 Hall Matrix */ | ||
153 | { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ | 173 | { USB_DEVICE(0x3195, 0xF190) }, /* Link Instruments MSO-19 */ |
154 | { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ | 174 | { USB_DEVICE(0x3195, 0xF280) }, /* Link Instruments MSO-28 */ |
155 | { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ | 175 | { USB_DEVICE(0x3195, 0xF281) }, /* Link Instruments MSO-28 */ |
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index 8efa19d0e9fb..ba7352e4187e 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
@@ -111,7 +111,6 @@ struct cypress_private { | |||
111 | int baud_rate; /* stores current baud rate in | 111 | int baud_rate; /* stores current baud rate in |
112 | integer form */ | 112 | integer form */ |
113 | int isthrottled; /* if throttled, discard reads */ | 113 | int isthrottled; /* if throttled, discard reads */ |
114 | wait_queue_head_t delta_msr_wait; /* used for TIOCMIWAIT */ | ||
115 | char prev_status, diff_status; /* used for TIOCMIWAIT */ | 114 | char prev_status, diff_status; /* used for TIOCMIWAIT */ |
116 | /* we pass a pointer to this as the argument sent to | 115 | /* we pass a pointer to this as the argument sent to |
117 | cypress_set_termios old_termios */ | 116 | cypress_set_termios old_termios */ |
@@ -449,7 +448,6 @@ static int cypress_generic_port_probe(struct usb_serial_port *port) | |||
449 | kfree(priv); | 448 | kfree(priv); |
450 | return -ENOMEM; | 449 | return -ENOMEM; |
451 | } | 450 | } |
452 | init_waitqueue_head(&priv->delta_msr_wait); | ||
453 | 451 | ||
454 | usb_reset_configuration(serial->dev); | 452 | usb_reset_configuration(serial->dev); |
455 | 453 | ||
@@ -868,12 +866,16 @@ static int cypress_ioctl(struct tty_struct *tty, | |||
868 | switch (cmd) { | 866 | switch (cmd) { |
869 | /* This code comes from drivers/char/serial.c and ftdi_sio.c */ | 867 | /* This code comes from drivers/char/serial.c and ftdi_sio.c */ |
870 | case TIOCMIWAIT: | 868 | case TIOCMIWAIT: |
871 | while (priv != NULL) { | 869 | for (;;) { |
872 | interruptible_sleep_on(&priv->delta_msr_wait); | 870 | interruptible_sleep_on(&port->delta_msr_wait); |
873 | /* see if a signal did it */ | 871 | /* see if a signal did it */ |
874 | if (signal_pending(current)) | 872 | if (signal_pending(current)) |
875 | return -ERESTARTSYS; | 873 | return -ERESTARTSYS; |
876 | else { | 874 | |
875 | if (port->serial->disconnected) | ||
876 | return -EIO; | ||
877 | |||
878 | { | ||
877 | char diff = priv->diff_status; | 879 | char diff = priv->diff_status; |
878 | if (diff == 0) | 880 | if (diff == 0) |
879 | return -EIO; /* no change => error */ | 881 | return -EIO; /* no change => error */ |
@@ -1187,7 +1189,7 @@ static void cypress_read_int_callback(struct urb *urb) | |||
1187 | if (priv->current_status != priv->prev_status) { | 1189 | if (priv->current_status != priv->prev_status) { |
1188 | priv->diff_status |= priv->current_status ^ | 1190 | priv->diff_status |= priv->current_status ^ |
1189 | priv->prev_status; | 1191 | priv->prev_status; |
1190 | wake_up_interruptible(&priv->delta_msr_wait); | 1192 | wake_up_interruptible(&port->delta_msr_wait); |
1191 | priv->prev_status = priv->current_status; | 1193 | priv->prev_status = priv->current_status; |
1192 | } | 1194 | } |
1193 | spin_unlock_irqrestore(&priv->lock, flags); | 1195 | spin_unlock_irqrestore(&priv->lock, flags); |
diff --git a/drivers/usb/serial/f81232.c b/drivers/usb/serial/f81232.c index b1b2dc64b50b..a172ad5c5ce8 100644 --- a/drivers/usb/serial/f81232.c +++ b/drivers/usb/serial/f81232.c | |||
@@ -47,7 +47,6 @@ MODULE_DEVICE_TABLE(usb, id_table); | |||
47 | 47 | ||
48 | struct f81232_private { | 48 | struct f81232_private { |
49 | spinlock_t lock; | 49 | spinlock_t lock; |
50 | wait_queue_head_t delta_msr_wait; | ||
51 | u8 line_control; | 50 | u8 line_control; |
52 | u8 line_status; | 51 | u8 line_status; |
53 | }; | 52 | }; |
@@ -111,7 +110,7 @@ static void f81232_process_read_urb(struct urb *urb) | |||
111 | line_status = priv->line_status; | 110 | line_status = priv->line_status; |
112 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; | 111 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; |
113 | spin_unlock_irqrestore(&priv->lock, flags); | 112 | spin_unlock_irqrestore(&priv->lock, flags); |
114 | wake_up_interruptible(&priv->delta_msr_wait); | 113 | wake_up_interruptible(&port->delta_msr_wait); |
115 | 114 | ||
116 | if (!urb->actual_length) | 115 | if (!urb->actual_length) |
117 | return; | 116 | return; |
@@ -256,11 +255,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
256 | spin_unlock_irqrestore(&priv->lock, flags); | 255 | spin_unlock_irqrestore(&priv->lock, flags); |
257 | 256 | ||
258 | while (1) { | 257 | while (1) { |
259 | interruptible_sleep_on(&priv->delta_msr_wait); | 258 | interruptible_sleep_on(&port->delta_msr_wait); |
260 | /* see if a signal did it */ | 259 | /* see if a signal did it */ |
261 | if (signal_pending(current)) | 260 | if (signal_pending(current)) |
262 | return -ERESTARTSYS; | 261 | return -ERESTARTSYS; |
263 | 262 | ||
263 | if (port->serial->disconnected) | ||
264 | return -EIO; | ||
265 | |||
264 | spin_lock_irqsave(&priv->lock, flags); | 266 | spin_lock_irqsave(&priv->lock, flags); |
265 | status = priv->line_status; | 267 | status = priv->line_status; |
266 | spin_unlock_irqrestore(&priv->lock, flags); | 268 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -322,7 +324,6 @@ static int f81232_port_probe(struct usb_serial_port *port) | |||
322 | return -ENOMEM; | 324 | return -ENOMEM; |
323 | 325 | ||
324 | spin_lock_init(&priv->lock); | 326 | spin_lock_init(&priv->lock); |
325 | init_waitqueue_head(&priv->delta_msr_wait); | ||
326 | 327 | ||
327 | usb_set_serial_port_data(port, priv); | 328 | usb_set_serial_port_data(port, priv); |
328 | 329 | ||
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index edd162df49ca..9886180e45f1 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -69,9 +69,7 @@ struct ftdi_private { | |||
69 | int flags; /* some ASYNC_xxxx flags are supported */ | 69 | int flags; /* some ASYNC_xxxx flags are supported */ |
70 | unsigned long last_dtr_rts; /* saved modem control outputs */ | 70 | unsigned long last_dtr_rts; /* saved modem control outputs */ |
71 | struct async_icount icount; | 71 | struct async_icount icount; |
72 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
73 | char prev_status; /* Used for TIOCMIWAIT */ | 72 | char prev_status; /* Used for TIOCMIWAIT */ |
74 | bool dev_gone; /* Used to abort TIOCMIWAIT */ | ||
75 | char transmit_empty; /* If transmitter is empty or not */ | 73 | char transmit_empty; /* If transmitter is empty or not */ |
76 | __u16 interface; /* FT2232C, FT2232H or FT4232H port interface | 74 | __u16 interface; /* FT2232C, FT2232H or FT4232H port interface |
77 | (0 for FT232/245) */ | 75 | (0 for FT232/245) */ |
@@ -642,6 +640,7 @@ static struct usb_device_id id_table_combined [] = { | |||
642 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, | 640 | { USB_DEVICE(FTDI_VID, FTDI_RM_CANVIEW_PID) }, |
643 | { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, | 641 | { USB_DEVICE(ACTON_VID, ACTON_SPECTRAPRO_PID) }, |
644 | { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, | 642 | { USB_DEVICE(CONTEC_VID, CONTEC_COM1USBH_PID) }, |
643 | { USB_DEVICE(MITSUBISHI_VID, MITSUBISHI_FXUSB_PID) }, | ||
645 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, | 644 | { USB_DEVICE(BANDB_VID, BANDB_USOTL4_PID) }, |
646 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, | 645 | { USB_DEVICE(BANDB_VID, BANDB_USTL4_PID) }, |
647 | { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, | 646 | { USB_DEVICE(BANDB_VID, BANDB_USO9ML2_PID) }, |
@@ -1691,10 +1690,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
1691 | 1690 | ||
1692 | kref_init(&priv->kref); | 1691 | kref_init(&priv->kref); |
1693 | mutex_init(&priv->cfg_lock); | 1692 | mutex_init(&priv->cfg_lock); |
1694 | init_waitqueue_head(&priv->delta_msr_wait); | ||
1695 | 1693 | ||
1696 | priv->flags = ASYNC_LOW_LATENCY; | 1694 | priv->flags = ASYNC_LOW_LATENCY; |
1697 | priv->dev_gone = false; | ||
1698 | 1695 | ||
1699 | if (quirk && quirk->port_probe) | 1696 | if (quirk && quirk->port_probe) |
1700 | quirk->port_probe(priv); | 1697 | quirk->port_probe(priv); |
@@ -1840,8 +1837,7 @@ static int ftdi_sio_port_remove(struct usb_serial_port *port) | |||
1840 | { | 1837 | { |
1841 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1838 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
1842 | 1839 | ||
1843 | priv->dev_gone = true; | 1840 | wake_up_interruptible(&port->delta_msr_wait); |
1844 | wake_up_interruptible_all(&priv->delta_msr_wait); | ||
1845 | 1841 | ||
1846 | remove_sysfs_attrs(port); | 1842 | remove_sysfs_attrs(port); |
1847 | 1843 | ||
@@ -1989,7 +1985,7 @@ static int ftdi_process_packet(struct usb_serial_port *port, | |||
1989 | if (diff_status & FTDI_RS0_RLSD) | 1985 | if (diff_status & FTDI_RS0_RLSD) |
1990 | priv->icount.dcd++; | 1986 | priv->icount.dcd++; |
1991 | 1987 | ||
1992 | wake_up_interruptible_all(&priv->delta_msr_wait); | 1988 | wake_up_interruptible(&port->delta_msr_wait); |
1993 | priv->prev_status = status; | 1989 | priv->prev_status = status; |
1994 | } | 1990 | } |
1995 | 1991 | ||
@@ -2440,11 +2436,15 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2440 | */ | 2436 | */ |
2441 | case TIOCMIWAIT: | 2437 | case TIOCMIWAIT: |
2442 | cprev = priv->icount; | 2438 | cprev = priv->icount; |
2443 | while (!priv->dev_gone) { | 2439 | for (;;) { |
2444 | interruptible_sleep_on(&priv->delta_msr_wait); | 2440 | interruptible_sleep_on(&port->delta_msr_wait); |
2445 | /* see if a signal did it */ | 2441 | /* see if a signal did it */ |
2446 | if (signal_pending(current)) | 2442 | if (signal_pending(current)) |
2447 | return -ERESTARTSYS; | 2443 | return -ERESTARTSYS; |
2444 | |||
2445 | if (port->serial->disconnected) | ||
2446 | return -EIO; | ||
2447 | |||
2448 | cnow = priv->icount; | 2448 | cnow = priv->icount; |
2449 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || | 2449 | if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) || |
2450 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || | 2450 | ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) || |
@@ -2454,8 +2454,6 @@ static int ftdi_ioctl(struct tty_struct *tty, | |||
2454 | } | 2454 | } |
2455 | cprev = cnow; | 2455 | cprev = cnow; |
2456 | } | 2456 | } |
2457 | return -EIO; | ||
2458 | break; | ||
2459 | case TIOCSERGETLSR: | 2457 | case TIOCSERGETLSR: |
2460 | return get_lsr_info(port, (struct serial_struct __user *)arg); | 2458 | return get_lsr_info(port, (struct serial_struct __user *)arg); |
2461 | break; | 2459 | break; |
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 9d359e189a64..e79861eeed4c 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -584,6 +584,13 @@ | |||
584 | #define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ | 584 | #define CONTEC_COM1USBH_PID 0x8311 /* COM-1(USB)H */ |
585 | 585 | ||
586 | /* | 586 | /* |
587 | * Mitsubishi Electric Corp. (http://www.meau.com) | ||
588 | * Submitted by Konstantin Holoborodko | ||
589 | */ | ||
590 | #define MITSUBISHI_VID 0x06D3 | ||
591 | #define MITSUBISHI_FXUSB_PID 0x0284 /* USB/RS422 converters: FX-USB-AW/-BD */ | ||
592 | |||
593 | /* | ||
587 | * Definitions for B&B Electronics products. | 594 | * Definitions for B&B Electronics products. |
588 | */ | 595 | */ |
589 | #define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ | 596 | #define BANDB_VID 0x0856 /* B&B Electronics Vendor ID */ |
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 1a07b12ef341..81caf5623ee2 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
@@ -956,10 +956,7 @@ static void garmin_close(struct usb_serial_port *port) | |||
956 | if (!serial) | 956 | if (!serial) |
957 | return; | 957 | return; |
958 | 958 | ||
959 | mutex_lock(&port->serial->disc_mutex); | 959 | garmin_clear(garmin_data_p); |
960 | |||
961 | if (!port->serial->disconnected) | ||
962 | garmin_clear(garmin_data_p); | ||
963 | 960 | ||
964 | /* shutdown our urbs */ | 961 | /* shutdown our urbs */ |
965 | usb_kill_urb(port->read_urb); | 962 | usb_kill_urb(port->read_urb); |
@@ -968,8 +965,6 @@ static void garmin_close(struct usb_serial_port *port) | |||
968 | /* keep reset state so we know that we must start a new session */ | 965 | /* keep reset state so we know that we must start a new session */ |
969 | if (garmin_data_p->state != STATE_RESET) | 966 | if (garmin_data_p->state != STATE_RESET) |
970 | garmin_data_p->state = STATE_DISCONNECTED; | 967 | garmin_data_p->state = STATE_DISCONNECTED; |
971 | |||
972 | mutex_unlock(&port->serial->disc_mutex); | ||
973 | } | 968 | } |
974 | 969 | ||
975 | 970 | ||
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index b00e5cbf741f..efd8b978128c 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
@@ -110,7 +110,6 @@ struct edgeport_port { | |||
110 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ | 110 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ |
111 | wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */ | 111 | wait_queue_head_t wait_open; /* for handling sleeping while waiting for open to finish */ |
112 | wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ | 112 | wait_queue_head_t wait_command; /* for handling sleeping while waiting for command to finish */ |
113 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ | ||
114 | 113 | ||
115 | struct async_icount icount; | 114 | struct async_icount icount; |
116 | struct usb_serial_port *port; /* loop back to the owner of this object */ | 115 | struct usb_serial_port *port; /* loop back to the owner of this object */ |
@@ -884,7 +883,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
884 | /* initialize our wait queues */ | 883 | /* initialize our wait queues */ |
885 | init_waitqueue_head(&edge_port->wait_open); | 884 | init_waitqueue_head(&edge_port->wait_open); |
886 | init_waitqueue_head(&edge_port->wait_chase); | 885 | init_waitqueue_head(&edge_port->wait_chase); |
887 | init_waitqueue_head(&edge_port->delta_msr_wait); | ||
888 | init_waitqueue_head(&edge_port->wait_command); | 886 | init_waitqueue_head(&edge_port->wait_command); |
889 | 887 | ||
890 | /* initialize our icount structure */ | 888 | /* initialize our icount structure */ |
@@ -1669,13 +1667,17 @@ static int edge_ioctl(struct tty_struct *tty, | |||
1669 | dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); | 1667 | dev_dbg(&port->dev, "%s (%d) TIOCMIWAIT\n", __func__, port->number); |
1670 | cprev = edge_port->icount; | 1668 | cprev = edge_port->icount; |
1671 | while (1) { | 1669 | while (1) { |
1672 | prepare_to_wait(&edge_port->delta_msr_wait, | 1670 | prepare_to_wait(&port->delta_msr_wait, |
1673 | &wait, TASK_INTERRUPTIBLE); | 1671 | &wait, TASK_INTERRUPTIBLE); |
1674 | schedule(); | 1672 | schedule(); |
1675 | finish_wait(&edge_port->delta_msr_wait, &wait); | 1673 | finish_wait(&port->delta_msr_wait, &wait); |
1676 | /* see if a signal did it */ | 1674 | /* see if a signal did it */ |
1677 | if (signal_pending(current)) | 1675 | if (signal_pending(current)) |
1678 | return -ERESTARTSYS; | 1676 | return -ERESTARTSYS; |
1677 | |||
1678 | if (port->serial->disconnected) | ||
1679 | return -EIO; | ||
1680 | |||
1679 | cnow = edge_port->icount; | 1681 | cnow = edge_port->icount; |
1680 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | 1682 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && |
1681 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | 1683 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) |
@@ -2051,7 +2053,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 newMsr) | |||
2051 | icount->dcd++; | 2053 | icount->dcd++; |
2052 | if (newMsr & EDGEPORT_MSR_DELTA_RI) | 2054 | if (newMsr & EDGEPORT_MSR_DELTA_RI) |
2053 | icount->rng++; | 2055 | icount->rng++; |
2054 | wake_up_interruptible(&edge_port->delta_msr_wait); | 2056 | wake_up_interruptible(&edge_port->port->delta_msr_wait); |
2055 | } | 2057 | } |
2056 | 2058 | ||
2057 | /* Save the new modem status */ | 2059 | /* Save the new modem status */ |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index c23776679f70..7777172206de 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -87,9 +87,6 @@ struct edgeport_port { | |||
87 | int close_pending; | 87 | int close_pending; |
88 | int lsr_event; | 88 | int lsr_event; |
89 | struct async_icount icount; | 89 | struct async_icount icount; |
90 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while | ||
91 | waiting for msr change to | ||
92 | happen */ | ||
93 | struct edgeport_serial *edge_serial; | 90 | struct edgeport_serial *edge_serial; |
94 | struct usb_serial_port *port; | 91 | struct usb_serial_port *port; |
95 | __u8 bUartMode; /* Port type, 0: RS232, etc. */ | 92 | __u8 bUartMode; /* Port type, 0: RS232, etc. */ |
@@ -1459,7 +1456,7 @@ static void handle_new_msr(struct edgeport_port *edge_port, __u8 msr) | |||
1459 | icount->dcd++; | 1456 | icount->dcd++; |
1460 | if (msr & EDGEPORT_MSR_DELTA_RI) | 1457 | if (msr & EDGEPORT_MSR_DELTA_RI) |
1461 | icount->rng++; | 1458 | icount->rng++; |
1462 | wake_up_interruptible(&edge_port->delta_msr_wait); | 1459 | wake_up_interruptible(&edge_port->port->delta_msr_wait); |
1463 | } | 1460 | } |
1464 | 1461 | ||
1465 | /* Save the new modem status */ | 1462 | /* Save the new modem status */ |
@@ -1754,7 +1751,6 @@ static int edge_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1754 | dev = port->serial->dev; | 1751 | dev = port->serial->dev; |
1755 | 1752 | ||
1756 | memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); | 1753 | memset(&(edge_port->icount), 0x00, sizeof(edge_port->icount)); |
1757 | init_waitqueue_head(&edge_port->delta_msr_wait); | ||
1758 | 1754 | ||
1759 | /* turn off loopback */ | 1755 | /* turn off loopback */ |
1760 | status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0); | 1756 | status = ti_do_config(edge_port, UMPC_SET_CLR_LOOPBACK, 0); |
@@ -2434,10 +2430,14 @@ static int edge_ioctl(struct tty_struct *tty, | |||
2434 | dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); | 2430 | dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); |
2435 | cprev = edge_port->icount; | 2431 | cprev = edge_port->icount; |
2436 | while (1) { | 2432 | while (1) { |
2437 | interruptible_sleep_on(&edge_port->delta_msr_wait); | 2433 | interruptible_sleep_on(&port->delta_msr_wait); |
2438 | /* see if a signal did it */ | 2434 | /* see if a signal did it */ |
2439 | if (signal_pending(current)) | 2435 | if (signal_pending(current)) |
2440 | return -ERESTARTSYS; | 2436 | return -ERESTARTSYS; |
2437 | |||
2438 | if (port->serial->disconnected) | ||
2439 | return -EIO; | ||
2440 | |||
2441 | cnow = edge_port->icount; | 2441 | cnow = edge_port->icount; |
2442 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | 2442 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && |
2443 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | 2443 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) |
@@ -2649,6 +2649,7 @@ static struct usb_serial_driver edgeport_2port_device = { | |||
2649 | .set_termios = edge_set_termios, | 2649 | .set_termios = edge_set_termios, |
2650 | .tiocmget = edge_tiocmget, | 2650 | .tiocmget = edge_tiocmget, |
2651 | .tiocmset = edge_tiocmset, | 2651 | .tiocmset = edge_tiocmset, |
2652 | .get_icount = edge_get_icount, | ||
2652 | .write = edge_write, | 2653 | .write = edge_write, |
2653 | .write_room = edge_write_room, | 2654 | .write_room = edge_write_room, |
2654 | .chars_in_buffer = edge_chars_in_buffer, | 2655 | .chars_in_buffer = edge_chars_in_buffer, |
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index a64d420f687b..06d5a60be2c4 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
@@ -114,8 +114,6 @@ struct mct_u232_private { | |||
114 | unsigned char last_msr; /* Modem Status Register */ | 114 | unsigned char last_msr; /* Modem Status Register */ |
115 | unsigned int rx_flags; /* Throttling flags */ | 115 | unsigned int rx_flags; /* Throttling flags */ |
116 | struct async_icount icount; | 116 | struct async_icount icount; |
117 | wait_queue_head_t msr_wait; /* for handling sleeping while waiting | ||
118 | for msr change to happen */ | ||
119 | }; | 117 | }; |
120 | 118 | ||
121 | #define THROTTLED 0x01 | 119 | #define THROTTLED 0x01 |
@@ -409,7 +407,6 @@ static int mct_u232_port_probe(struct usb_serial_port *port) | |||
409 | return -ENOMEM; | 407 | return -ENOMEM; |
410 | 408 | ||
411 | spin_lock_init(&priv->lock); | 409 | spin_lock_init(&priv->lock); |
412 | init_waitqueue_head(&priv->msr_wait); | ||
413 | 410 | ||
414 | usb_set_serial_port_data(port, priv); | 411 | usb_set_serial_port_data(port, priv); |
415 | 412 | ||
@@ -601,7 +598,7 @@ static void mct_u232_read_int_callback(struct urb *urb) | |||
601 | tty_kref_put(tty); | 598 | tty_kref_put(tty); |
602 | } | 599 | } |
603 | #endif | 600 | #endif |
604 | wake_up_interruptible(&priv->msr_wait); | 601 | wake_up_interruptible(&port->delta_msr_wait); |
605 | spin_unlock_irqrestore(&priv->lock, flags); | 602 | spin_unlock_irqrestore(&priv->lock, flags); |
606 | exit: | 603 | exit: |
607 | retval = usb_submit_urb(urb, GFP_ATOMIC); | 604 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
@@ -810,13 +807,17 @@ static int mct_u232_ioctl(struct tty_struct *tty, | |||
810 | cprev = mct_u232_port->icount; | 807 | cprev = mct_u232_port->icount; |
811 | spin_unlock_irqrestore(&mct_u232_port->lock, flags); | 808 | spin_unlock_irqrestore(&mct_u232_port->lock, flags); |
812 | for ( ; ; ) { | 809 | for ( ; ; ) { |
813 | prepare_to_wait(&mct_u232_port->msr_wait, | 810 | prepare_to_wait(&port->delta_msr_wait, |
814 | &wait, TASK_INTERRUPTIBLE); | 811 | &wait, TASK_INTERRUPTIBLE); |
815 | schedule(); | 812 | schedule(); |
816 | finish_wait(&mct_u232_port->msr_wait, &wait); | 813 | finish_wait(&port->delta_msr_wait, &wait); |
817 | /* see if a signal did it */ | 814 | /* see if a signal did it */ |
818 | if (signal_pending(current)) | 815 | if (signal_pending(current)) |
819 | return -ERESTARTSYS; | 816 | return -ERESTARTSYS; |
817 | |||
818 | if (port->serial->disconnected) | ||
819 | return -EIO; | ||
820 | |||
820 | spin_lock_irqsave(&mct_u232_port->lock, flags); | 821 | spin_lock_irqsave(&mct_u232_port->lock, flags); |
821 | cnow = mct_u232_port->icount; | 822 | cnow = mct_u232_port->icount; |
822 | spin_unlock_irqrestore(&mct_u232_port->lock, flags); | 823 | spin_unlock_irqrestore(&mct_u232_port->lock, flags); |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 809fb329eca5..b8051fa61911 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
@@ -219,7 +219,6 @@ struct moschip_port { | |||
219 | char open; | 219 | char open; |
220 | char open_ports; | 220 | char open_ports; |
221 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ | 221 | wait_queue_head_t wait_chase; /* for handling sleeping while waiting for chase to finish */ |
222 | wait_queue_head_t delta_msr_wait; /* for handling sleeping while waiting for msr change to happen */ | ||
223 | int delta_msr_cond; | 222 | int delta_msr_cond; |
224 | struct async_icount icount; | 223 | struct async_icount icount; |
225 | struct usb_serial_port *port; /* loop back to the owner of this object */ | 224 | struct usb_serial_port *port; /* loop back to the owner of this object */ |
@@ -423,6 +422,9 @@ static void mos7840_handle_new_msr(struct moschip_port *port, __u8 new_msr) | |||
423 | icount->rng++; | 422 | icount->rng++; |
424 | smp_wmb(); | 423 | smp_wmb(); |
425 | } | 424 | } |
425 | |||
426 | mos7840_port->delta_msr_cond = 1; | ||
427 | wake_up_interruptible(&port->port->delta_msr_wait); | ||
426 | } | 428 | } |
427 | } | 429 | } |
428 | 430 | ||
@@ -1127,7 +1129,6 @@ static int mos7840_open(struct tty_struct *tty, struct usb_serial_port *port) | |||
1127 | 1129 | ||
1128 | /* initialize our wait queues */ | 1130 | /* initialize our wait queues */ |
1129 | init_waitqueue_head(&mos7840_port->wait_chase); | 1131 | init_waitqueue_head(&mos7840_port->wait_chase); |
1130 | init_waitqueue_head(&mos7840_port->delta_msr_wait); | ||
1131 | 1132 | ||
1132 | /* initialize our icount structure */ | 1133 | /* initialize our icount structure */ |
1133 | memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); | 1134 | memset(&(mos7840_port->icount), 0x00, sizeof(mos7840_port->icount)); |
@@ -2017,8 +2018,6 @@ static void mos7840_change_port_settings(struct tty_struct *tty, | |||
2017 | mos7840_port->read_urb_busy = false; | 2018 | mos7840_port->read_urb_busy = false; |
2018 | } | 2019 | } |
2019 | } | 2020 | } |
2020 | wake_up(&mos7840_port->delta_msr_wait); | ||
2021 | mos7840_port->delta_msr_cond = 1; | ||
2022 | dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__, | 2021 | dev_dbg(&port->dev, "%s - mos7840_port->shadowLCR is End %x\n", __func__, |
2023 | mos7840_port->shadowLCR); | 2022 | mos7840_port->shadowLCR); |
2024 | } | 2023 | } |
@@ -2219,13 +2218,18 @@ static int mos7840_ioctl(struct tty_struct *tty, | |||
2219 | while (1) { | 2218 | while (1) { |
2220 | /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ | 2219 | /* interruptible_sleep_on(&mos7840_port->delta_msr_wait); */ |
2221 | mos7840_port->delta_msr_cond = 0; | 2220 | mos7840_port->delta_msr_cond = 0; |
2222 | wait_event_interruptible(mos7840_port->delta_msr_wait, | 2221 | wait_event_interruptible(port->delta_msr_wait, |
2223 | (mos7840_port-> | 2222 | (port->serial->disconnected || |
2223 | mos7840_port-> | ||
2224 | delta_msr_cond == 1)); | 2224 | delta_msr_cond == 1)); |
2225 | 2225 | ||
2226 | /* see if a signal did it */ | 2226 | /* see if a signal did it */ |
2227 | if (signal_pending(current)) | 2227 | if (signal_pending(current)) |
2228 | return -ERESTARTSYS; | 2228 | return -ERESTARTSYS; |
2229 | |||
2230 | if (port->serial->disconnected) | ||
2231 | return -EIO; | ||
2232 | |||
2229 | cnow = mos7840_port->icount; | 2233 | cnow = mos7840_port->icount; |
2230 | smp_rmb(); | 2234 | smp_rmb(); |
2231 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | 2235 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && |
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index f7d339d8187b..558adfc05007 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -341,6 +341,8 @@ static void option_instat_callback(struct urb *urb); | |||
341 | #define CINTERION_PRODUCT_EU3_E 0x0051 | 341 | #define CINTERION_PRODUCT_EU3_E 0x0051 |
342 | #define CINTERION_PRODUCT_EU3_P 0x0052 | 342 | #define CINTERION_PRODUCT_EU3_P 0x0052 |
343 | #define CINTERION_PRODUCT_PH8 0x0053 | 343 | #define CINTERION_PRODUCT_PH8 0x0053 |
344 | #define CINTERION_PRODUCT_AH6 0x0055 | ||
345 | #define CINTERION_PRODUCT_PLS8 0x0060 | ||
344 | 346 | ||
345 | /* Olivetti products */ | 347 | /* Olivetti products */ |
346 | #define OLIVETTI_VENDOR_ID 0x0b3c | 348 | #define OLIVETTI_VENDOR_ID 0x0b3c |
@@ -579,6 +581,7 @@ static const struct usb_device_id option_ids[] = { | |||
579 | { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42), | 581 | { USB_DEVICE(QUANTA_VENDOR_ID, 0xea42), |
580 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | 582 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, |
581 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) }, | 583 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c05, USB_CLASS_COMM, 0x02, 0xff) }, |
584 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c1f, USB_CLASS_COMM, 0x02, 0xff) }, | ||
582 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, | 585 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x1c23, USB_CLASS_COMM, 0x02, 0xff) }, |
583 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), | 586 | { USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, HUAWEI_PRODUCT_E173, 0xff, 0xff, 0xff), |
584 | .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, | 587 | .driver_info = (kernel_ulong_t) &net_intf1_blacklist }, |
@@ -1260,6 +1263,8 @@ static const struct usb_device_id option_ids[] = { | |||
1260 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, | 1263 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_E) }, |
1261 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, | 1264 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) }, |
1262 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, | 1265 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8) }, |
1266 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AH6) }, | ||
1267 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLS8) }, | ||
1263 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, | 1268 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) }, |
1264 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, | 1269 | { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDMNET) }, |
1265 | { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, | 1270 | { USB_DEVICE(SIEMENS_VENDOR_ID, CINTERION_PRODUCT_HC25_MDM) }, |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index a958fd41b5b3..87c71ccfee87 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
@@ -188,7 +188,6 @@ struct oti6858_private { | |||
188 | u8 setup_done; | 188 | u8 setup_done; |
189 | struct delayed_work delayed_setup_work; | 189 | struct delayed_work delayed_setup_work; |
190 | 190 | ||
191 | wait_queue_head_t intr_wait; | ||
192 | struct usb_serial_port *port; /* USB port with which associated */ | 191 | struct usb_serial_port *port; /* USB port with which associated */ |
193 | }; | 192 | }; |
194 | 193 | ||
@@ -339,7 +338,6 @@ static int oti6858_port_probe(struct usb_serial_port *port) | |||
339 | return -ENOMEM; | 338 | return -ENOMEM; |
340 | 339 | ||
341 | spin_lock_init(&priv->lock); | 340 | spin_lock_init(&priv->lock); |
342 | init_waitqueue_head(&priv->intr_wait); | ||
343 | priv->port = port; | 341 | priv->port = port; |
344 | INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); | 342 | INIT_DELAYED_WORK(&priv->delayed_setup_work, setup_line); |
345 | INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); | 343 | INIT_DELAYED_WORK(&priv->delayed_write_work, send_data); |
@@ -664,11 +662,15 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
664 | spin_unlock_irqrestore(&priv->lock, flags); | 662 | spin_unlock_irqrestore(&priv->lock, flags); |
665 | 663 | ||
666 | while (1) { | 664 | while (1) { |
667 | wait_event_interruptible(priv->intr_wait, | 665 | wait_event_interruptible(port->delta_msr_wait, |
666 | port->serial->disconnected || | ||
668 | priv->status.pin_state != prev); | 667 | priv->status.pin_state != prev); |
669 | if (signal_pending(current)) | 668 | if (signal_pending(current)) |
670 | return -ERESTARTSYS; | 669 | return -ERESTARTSYS; |
671 | 670 | ||
671 | if (port->serial->disconnected) | ||
672 | return -EIO; | ||
673 | |||
672 | spin_lock_irqsave(&priv->lock, flags); | 674 | spin_lock_irqsave(&priv->lock, flags); |
673 | status = priv->status.pin_state & PIN_MASK; | 675 | status = priv->status.pin_state & PIN_MASK; |
674 | spin_unlock_irqrestore(&priv->lock, flags); | 676 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -763,7 +765,7 @@ static void oti6858_read_int_callback(struct urb *urb) | |||
763 | 765 | ||
764 | if (!priv->transient) { | 766 | if (!priv->transient) { |
765 | if (xs->pin_state != priv->status.pin_state) | 767 | if (xs->pin_state != priv->status.pin_state) |
766 | wake_up_interruptible(&priv->intr_wait); | 768 | wake_up_interruptible(&port->delta_msr_wait); |
767 | memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE); | 769 | memcpy(&priv->status, xs, OTI6858_CTRL_PKT_SIZE); |
768 | } | 770 | } |
769 | 771 | ||
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 54adc9125e5c..3b10018d89a3 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
@@ -139,7 +139,6 @@ struct pl2303_serial_private { | |||
139 | 139 | ||
140 | struct pl2303_private { | 140 | struct pl2303_private { |
141 | spinlock_t lock; | 141 | spinlock_t lock; |
142 | wait_queue_head_t delta_msr_wait; | ||
143 | u8 line_control; | 142 | u8 line_control; |
144 | u8 line_status; | 143 | u8 line_status; |
145 | }; | 144 | }; |
@@ -233,7 +232,6 @@ static int pl2303_port_probe(struct usb_serial_port *port) | |||
233 | return -ENOMEM; | 232 | return -ENOMEM; |
234 | 233 | ||
235 | spin_lock_init(&priv->lock); | 234 | spin_lock_init(&priv->lock); |
236 | init_waitqueue_head(&priv->delta_msr_wait); | ||
237 | 235 | ||
238 | usb_set_serial_port_data(port, priv); | 236 | usb_set_serial_port_data(port, priv); |
239 | 237 | ||
@@ -607,11 +605,14 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
607 | spin_unlock_irqrestore(&priv->lock, flags); | 605 | spin_unlock_irqrestore(&priv->lock, flags); |
608 | 606 | ||
609 | while (1) { | 607 | while (1) { |
610 | interruptible_sleep_on(&priv->delta_msr_wait); | 608 | interruptible_sleep_on(&port->delta_msr_wait); |
611 | /* see if a signal did it */ | 609 | /* see if a signal did it */ |
612 | if (signal_pending(current)) | 610 | if (signal_pending(current)) |
613 | return -ERESTARTSYS; | 611 | return -ERESTARTSYS; |
614 | 612 | ||
613 | if (port->serial->disconnected) | ||
614 | return -EIO; | ||
615 | |||
615 | spin_lock_irqsave(&priv->lock, flags); | 616 | spin_lock_irqsave(&priv->lock, flags); |
616 | status = priv->line_status; | 617 | status = priv->line_status; |
617 | spin_unlock_irqrestore(&priv->lock, flags); | 618 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -719,7 +720,7 @@ static void pl2303_update_line_status(struct usb_serial_port *port, | |||
719 | spin_unlock_irqrestore(&priv->lock, flags); | 720 | spin_unlock_irqrestore(&priv->lock, flags); |
720 | if (priv->line_status & UART_BREAK_ERROR) | 721 | if (priv->line_status & UART_BREAK_ERROR) |
721 | usb_serial_handle_break(port); | 722 | usb_serial_handle_break(port); |
722 | wake_up_interruptible(&priv->delta_msr_wait); | 723 | wake_up_interruptible(&port->delta_msr_wait); |
723 | 724 | ||
724 | tty = tty_port_tty_get(&port->port); | 725 | tty = tty_port_tty_get(&port->port); |
725 | if (!tty) | 726 | if (!tty) |
@@ -783,7 +784,7 @@ static void pl2303_process_read_urb(struct urb *urb) | |||
783 | line_status = priv->line_status; | 784 | line_status = priv->line_status; |
784 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; | 785 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; |
785 | spin_unlock_irqrestore(&priv->lock, flags); | 786 | spin_unlock_irqrestore(&priv->lock, flags); |
786 | wake_up_interruptible(&priv->delta_msr_wait); | 787 | wake_up_interruptible(&port->delta_msr_wait); |
787 | 788 | ||
788 | if (!urb->actual_length) | 789 | if (!urb->actual_length) |
789 | return; | 790 | return; |
diff --git a/drivers/usb/serial/qcaux.c b/drivers/usb/serial/qcaux.c index 9b1b96f2d095..31f81c3c15eb 100644 --- a/drivers/usb/serial/qcaux.c +++ b/drivers/usb/serial/qcaux.c | |||
@@ -69,6 +69,7 @@ static struct usb_device_id id_table[] = { | |||
69 | { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */ | 69 | { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfd, 0xff) }, /* NMEA */ |
70 | { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */ | 70 | { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xfe, 0xff) }, /* WMC */ |
71 | { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */ | 71 | { USB_VENDOR_AND_INTERFACE_INFO(UTSTARCOM_VENDOR_ID, 0xff, 0xff, 0xff) }, /* DIAG */ |
72 | { USB_DEVICE_AND_INTERFACE_INFO(0x1fac, 0x0151, 0xff, 0xff, 0xff) }, | ||
72 | { }, | 73 | { }, |
73 | }; | 74 | }; |
74 | MODULE_DEVICE_TABLE(usb, id_table); | 75 | MODULE_DEVICE_TABLE(usb, id_table); |
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index 24662547dc5b..59b32b782126 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c | |||
@@ -197,12 +197,15 @@ static int qcprobe(struct usb_serial *serial, const struct usb_device_id *id) | |||
197 | 197 | ||
198 | if (is_gobi1k) { | 198 | if (is_gobi1k) { |
199 | /* Gobi 1K USB layout: | 199 | /* Gobi 1K USB layout: |
200 | * 0: serial port (doesn't respond) | 200 | * 0: DM/DIAG (use libqcdm from ModemManager for communication) |
201 | * 1: serial port (doesn't respond) | 201 | * 1: serial port (doesn't respond) |
202 | * 2: AT-capable modem port | 202 | * 2: AT-capable modem port |
203 | * 3: QMI/net | 203 | * 3: QMI/net |
204 | */ | 204 | */ |
205 | if (ifnum == 2) | 205 | if (ifnum == 0) { |
206 | dev_dbg(dev, "Gobi 1K DM/DIAG interface found\n"); | ||
207 | altsetting = 1; | ||
208 | } else if (ifnum == 2) | ||
206 | dev_dbg(dev, "Modem port found\n"); | 209 | dev_dbg(dev, "Modem port found\n"); |
207 | else | 210 | else |
208 | altsetting = -1; | 211 | altsetting = -1; |
diff --git a/drivers/usb/serial/quatech2.c b/drivers/usb/serial/quatech2.c index 00e6c9bac8a3..75f125ddb0c9 100644 --- a/drivers/usb/serial/quatech2.c +++ b/drivers/usb/serial/quatech2.c | |||
@@ -128,7 +128,6 @@ struct qt2_port_private { | |||
128 | u8 shadowLSR; | 128 | u8 shadowLSR; |
129 | u8 shadowMSR; | 129 | u8 shadowMSR; |
130 | 130 | ||
131 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
132 | struct async_icount icount; | 131 | struct async_icount icount; |
133 | 132 | ||
134 | struct usb_serial_port *port; | 133 | struct usb_serial_port *port; |
@@ -506,8 +505,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
506 | spin_unlock_irqrestore(&priv->lock, flags); | 505 | spin_unlock_irqrestore(&priv->lock, flags); |
507 | 506 | ||
508 | while (1) { | 507 | while (1) { |
509 | wait_event_interruptible(priv->delta_msr_wait, | 508 | wait_event_interruptible(port->delta_msr_wait, |
510 | ((priv->icount.rng != prev.rng) || | 509 | (port->serial->disconnected || |
510 | (priv->icount.rng != prev.rng) || | ||
511 | (priv->icount.dsr != prev.dsr) || | 511 | (priv->icount.dsr != prev.dsr) || |
512 | (priv->icount.dcd != prev.dcd) || | 512 | (priv->icount.dcd != prev.dcd) || |
513 | (priv->icount.cts != prev.cts))); | 513 | (priv->icount.cts != prev.cts))); |
@@ -515,6 +515,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
515 | if (signal_pending(current)) | 515 | if (signal_pending(current)) |
516 | return -ERESTARTSYS; | 516 | return -ERESTARTSYS; |
517 | 517 | ||
518 | if (port->serial->disconnected) | ||
519 | return -EIO; | ||
520 | |||
518 | spin_lock_irqsave(&priv->lock, flags); | 521 | spin_lock_irqsave(&priv->lock, flags); |
519 | cur = priv->icount; | 522 | cur = priv->icount; |
520 | spin_unlock_irqrestore(&priv->lock, flags); | 523 | spin_unlock_irqrestore(&priv->lock, flags); |
@@ -661,7 +664,9 @@ void qt2_process_read_urb(struct urb *urb) | |||
661 | __func__); | 664 | __func__); |
662 | break; | 665 | break; |
663 | } | 666 | } |
664 | tty_flip_buffer_push(&port->port); | 667 | |
668 | if (port_priv->is_open) | ||
669 | tty_flip_buffer_push(&port->port); | ||
665 | 670 | ||
666 | newport = *(ch + 3); | 671 | newport = *(ch + 3); |
667 | 672 | ||
@@ -704,7 +709,8 @@ void qt2_process_read_urb(struct urb *urb) | |||
704 | tty_insert_flip_string(&port->port, ch, 1); | 709 | tty_insert_flip_string(&port->port, ch, 1); |
705 | } | 710 | } |
706 | 711 | ||
707 | tty_flip_buffer_push(&port->port); | 712 | if (port_priv->is_open) |
713 | tty_flip_buffer_push(&port->port); | ||
708 | } | 714 | } |
709 | 715 | ||
710 | static void qt2_write_bulk_callback(struct urb *urb) | 716 | static void qt2_write_bulk_callback(struct urb *urb) |
@@ -824,7 +830,6 @@ static int qt2_port_probe(struct usb_serial_port *port) | |||
824 | 830 | ||
825 | spin_lock_init(&port_priv->lock); | 831 | spin_lock_init(&port_priv->lock); |
826 | spin_lock_init(&port_priv->urb_lock); | 832 | spin_lock_init(&port_priv->urb_lock); |
827 | init_waitqueue_head(&port_priv->delta_msr_wait); | ||
828 | port_priv->port = port; | 833 | port_priv->port = port; |
829 | 834 | ||
830 | port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); | 835 | port_priv->write_urb = usb_alloc_urb(0, GFP_KERNEL); |
@@ -967,7 +972,7 @@ static void qt2_update_msr(struct usb_serial_port *port, unsigned char *ch) | |||
967 | if (newMSR & UART_MSR_TERI) | 972 | if (newMSR & UART_MSR_TERI) |
968 | port_priv->icount.rng++; | 973 | port_priv->icount.rng++; |
969 | 974 | ||
970 | wake_up_interruptible(&port_priv->delta_msr_wait); | 975 | wake_up_interruptible(&port->delta_msr_wait); |
971 | } | 976 | } |
972 | } | 977 | } |
973 | 978 | ||
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 91ff8e3bddbd..549ef68ff5fa 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
@@ -149,7 +149,6 @@ enum spcp8x5_type { | |||
149 | struct spcp8x5_private { | 149 | struct spcp8x5_private { |
150 | spinlock_t lock; | 150 | spinlock_t lock; |
151 | enum spcp8x5_type type; | 151 | enum spcp8x5_type type; |
152 | wait_queue_head_t delta_msr_wait; | ||
153 | u8 line_control; | 152 | u8 line_control; |
154 | u8 line_status; | 153 | u8 line_status; |
155 | }; | 154 | }; |
@@ -179,7 +178,6 @@ static int spcp8x5_port_probe(struct usb_serial_port *port) | |||
179 | return -ENOMEM; | 178 | return -ENOMEM; |
180 | 179 | ||
181 | spin_lock_init(&priv->lock); | 180 | spin_lock_init(&priv->lock); |
182 | init_waitqueue_head(&priv->delta_msr_wait); | ||
183 | priv->type = type; | 181 | priv->type = type; |
184 | 182 | ||
185 | usb_set_serial_port_data(port , priv); | 183 | usb_set_serial_port_data(port , priv); |
@@ -475,7 +473,7 @@ static void spcp8x5_process_read_urb(struct urb *urb) | |||
475 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; | 473 | priv->line_status &= ~UART_STATE_TRANSIENT_MASK; |
476 | spin_unlock_irqrestore(&priv->lock, flags); | 474 | spin_unlock_irqrestore(&priv->lock, flags); |
477 | /* wake up the wait for termios */ | 475 | /* wake up the wait for termios */ |
478 | wake_up_interruptible(&priv->delta_msr_wait); | 476 | wake_up_interruptible(&port->delta_msr_wait); |
479 | 477 | ||
480 | if (!urb->actual_length) | 478 | if (!urb->actual_length) |
481 | return; | 479 | return; |
@@ -526,12 +524,15 @@ static int spcp8x5_wait_modem_info(struct usb_serial_port *port, | |||
526 | 524 | ||
527 | while (1) { | 525 | while (1) { |
528 | /* wake up in bulk read */ | 526 | /* wake up in bulk read */ |
529 | interruptible_sleep_on(&priv->delta_msr_wait); | 527 | interruptible_sleep_on(&port->delta_msr_wait); |
530 | 528 | ||
531 | /* see if a signal did it */ | 529 | /* see if a signal did it */ |
532 | if (signal_pending(current)) | 530 | if (signal_pending(current)) |
533 | return -ERESTARTSYS; | 531 | return -ERESTARTSYS; |
534 | 532 | ||
533 | if (port->serial->disconnected) | ||
534 | return -EIO; | ||
535 | |||
535 | spin_lock_irqsave(&priv->lock, flags); | 536 | spin_lock_irqsave(&priv->lock, flags); |
536 | status = priv->line_status; | 537 | status = priv->line_status; |
537 | spin_unlock_irqrestore(&priv->lock, flags); | 538 | spin_unlock_irqrestore(&priv->lock, flags); |
diff --git a/drivers/usb/serial/ssu100.c b/drivers/usb/serial/ssu100.c index b57cf841c5b6..4b2a19757b4d 100644 --- a/drivers/usb/serial/ssu100.c +++ b/drivers/usb/serial/ssu100.c | |||
@@ -61,7 +61,6 @@ struct ssu100_port_private { | |||
61 | spinlock_t status_lock; | 61 | spinlock_t status_lock; |
62 | u8 shadowLSR; | 62 | u8 shadowLSR; |
63 | u8 shadowMSR; | 63 | u8 shadowMSR; |
64 | wait_queue_head_t delta_msr_wait; /* Used for TIOCMIWAIT */ | ||
65 | struct async_icount icount; | 64 | struct async_icount icount; |
66 | }; | 65 | }; |
67 | 66 | ||
@@ -355,8 +354,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
355 | spin_unlock_irqrestore(&priv->status_lock, flags); | 354 | spin_unlock_irqrestore(&priv->status_lock, flags); |
356 | 355 | ||
357 | while (1) { | 356 | while (1) { |
358 | wait_event_interruptible(priv->delta_msr_wait, | 357 | wait_event_interruptible(port->delta_msr_wait, |
359 | ((priv->icount.rng != prev.rng) || | 358 | (port->serial->disconnected || |
359 | (priv->icount.rng != prev.rng) || | ||
360 | (priv->icount.dsr != prev.dsr) || | 360 | (priv->icount.dsr != prev.dsr) || |
361 | (priv->icount.dcd != prev.dcd) || | 361 | (priv->icount.dcd != prev.dcd) || |
362 | (priv->icount.cts != prev.cts))); | 362 | (priv->icount.cts != prev.cts))); |
@@ -364,6 +364,9 @@ static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | |||
364 | if (signal_pending(current)) | 364 | if (signal_pending(current)) |
365 | return -ERESTARTSYS; | 365 | return -ERESTARTSYS; |
366 | 366 | ||
367 | if (port->serial->disconnected) | ||
368 | return -EIO; | ||
369 | |||
367 | spin_lock_irqsave(&priv->status_lock, flags); | 370 | spin_lock_irqsave(&priv->status_lock, flags); |
368 | cur = priv->icount; | 371 | cur = priv->icount; |
369 | spin_unlock_irqrestore(&priv->status_lock, flags); | 372 | spin_unlock_irqrestore(&priv->status_lock, flags); |
@@ -445,7 +448,6 @@ static int ssu100_port_probe(struct usb_serial_port *port) | |||
445 | return -ENOMEM; | 448 | return -ENOMEM; |
446 | 449 | ||
447 | spin_lock_init(&priv->status_lock); | 450 | spin_lock_init(&priv->status_lock); |
448 | init_waitqueue_head(&priv->delta_msr_wait); | ||
449 | 451 | ||
450 | usb_set_serial_port_data(port, priv); | 452 | usb_set_serial_port_data(port, priv); |
451 | 453 | ||
@@ -537,7 +539,7 @@ static void ssu100_update_msr(struct usb_serial_port *port, u8 msr) | |||
537 | priv->icount.dcd++; | 539 | priv->icount.dcd++; |
538 | if (msr & UART_MSR_TERI) | 540 | if (msr & UART_MSR_TERI) |
539 | priv->icount.rng++; | 541 | priv->icount.rng++; |
540 | wake_up_interruptible(&priv->delta_msr_wait); | 542 | wake_up_interruptible(&port->delta_msr_wait); |
541 | } | 543 | } |
542 | } | 544 | } |
543 | 545 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 39cb9b807c3c..73deb029fc05 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
@@ -74,7 +74,6 @@ struct ti_port { | |||
74 | int tp_flags; | 74 | int tp_flags; |
75 | int tp_closing_wait;/* in .01 secs */ | 75 | int tp_closing_wait;/* in .01 secs */ |
76 | struct async_icount tp_icount; | 76 | struct async_icount tp_icount; |
77 | wait_queue_head_t tp_msr_wait; /* wait for msr change */ | ||
78 | wait_queue_head_t tp_write_wait; | 77 | wait_queue_head_t tp_write_wait; |
79 | struct ti_device *tp_tdev; | 78 | struct ti_device *tp_tdev; |
80 | struct usb_serial_port *tp_port; | 79 | struct usb_serial_port *tp_port; |
@@ -432,7 +431,6 @@ static int ti_port_probe(struct usb_serial_port *port) | |||
432 | else | 431 | else |
433 | tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; | 432 | tport->tp_uart_base_addr = TI_UART2_BASE_ADDR; |
434 | tport->tp_closing_wait = closing_wait; | 433 | tport->tp_closing_wait = closing_wait; |
435 | init_waitqueue_head(&tport->tp_msr_wait); | ||
436 | init_waitqueue_head(&tport->tp_write_wait); | 434 | init_waitqueue_head(&tport->tp_write_wait); |
437 | if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { | 435 | if (kfifo_alloc(&tport->write_fifo, TI_WRITE_BUF_SIZE, GFP_KERNEL)) { |
438 | kfree(tport); | 436 | kfree(tport); |
@@ -784,9 +782,13 @@ static int ti_ioctl(struct tty_struct *tty, | |||
784 | dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); | 782 | dev_dbg(&port->dev, "%s - TIOCMIWAIT\n", __func__); |
785 | cprev = tport->tp_icount; | 783 | cprev = tport->tp_icount; |
786 | while (1) { | 784 | while (1) { |
787 | interruptible_sleep_on(&tport->tp_msr_wait); | 785 | interruptible_sleep_on(&port->delta_msr_wait); |
788 | if (signal_pending(current)) | 786 | if (signal_pending(current)) |
789 | return -ERESTARTSYS; | 787 | return -ERESTARTSYS; |
788 | |||
789 | if (port->serial->disconnected) | ||
790 | return -EIO; | ||
791 | |||
790 | cnow = tport->tp_icount; | 792 | cnow = tport->tp_icount; |
791 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && | 793 | if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && |
792 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) | 794 | cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) |
@@ -1392,7 +1394,7 @@ static void ti_handle_new_msr(struct ti_port *tport, __u8 msr) | |||
1392 | icount->dcd++; | 1394 | icount->dcd++; |
1393 | if (msr & TI_MSR_DELTA_RI) | 1395 | if (msr & TI_MSR_DELTA_RI) |
1394 | icount->rng++; | 1396 | icount->rng++; |
1395 | wake_up_interruptible(&tport->tp_msr_wait); | 1397 | wake_up_interruptible(&tport->tp_port->delta_msr_wait); |
1396 | spin_unlock_irqrestore(&tport->tp_lock, flags); | 1398 | spin_unlock_irqrestore(&tport->tp_lock, flags); |
1397 | } | 1399 | } |
1398 | 1400 | ||
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index a19ed74d770d..5d9b178484fd 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
@@ -151,6 +151,7 @@ static void destroy_serial(struct kref *kref) | |||
151 | } | 151 | } |
152 | } | 152 | } |
153 | 153 | ||
154 | usb_put_intf(serial->interface); | ||
154 | usb_put_dev(serial->dev); | 155 | usb_put_dev(serial->dev); |
155 | kfree(serial); | 156 | kfree(serial); |
156 | } | 157 | } |
@@ -620,7 +621,7 @@ static struct usb_serial *create_serial(struct usb_device *dev, | |||
620 | } | 621 | } |
621 | serial->dev = usb_get_dev(dev); | 622 | serial->dev = usb_get_dev(dev); |
622 | serial->type = driver; | 623 | serial->type = driver; |
623 | serial->interface = interface; | 624 | serial->interface = usb_get_intf(interface); |
624 | kref_init(&serial->kref); | 625 | kref_init(&serial->kref); |
625 | mutex_init(&serial->disc_mutex); | 626 | mutex_init(&serial->disc_mutex); |
626 | serial->minor = SERIAL_TTY_NO_MINOR; | 627 | serial->minor = SERIAL_TTY_NO_MINOR; |
@@ -902,6 +903,7 @@ static int usb_serial_probe(struct usb_interface *interface, | |||
902 | port->port.ops = &serial_port_ops; | 903 | port->port.ops = &serial_port_ops; |
903 | port->serial = serial; | 904 | port->serial = serial; |
904 | spin_lock_init(&port->lock); | 905 | spin_lock_init(&port->lock); |
906 | init_waitqueue_head(&port->delta_msr_wait); | ||
905 | /* Keep this for private driver use for the moment but | 907 | /* Keep this for private driver use for the moment but |
906 | should probably go away */ | 908 | should probably go away */ |
907 | INIT_WORK(&port->work, usb_serial_port_work); | 909 | INIT_WORK(&port->work, usb_serial_port_work); |
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 7ab9046ae0ec..105d900150c1 100644 --- a/drivers/usb/storage/initializers.c +++ b/drivers/usb/storage/initializers.c | |||
@@ -92,8 +92,8 @@ int usb_stor_ucr61s2b_init(struct us_data *us) | |||
92 | return 0; | 92 | return 0; |
93 | } | 93 | } |
94 | 94 | ||
95 | /* This places the HUAWEI usb dongles in multi-port mode */ | 95 | /* This places the HUAWEI E220 devices in multi-port mode */ |
96 | static int usb_stor_huawei_feature_init(struct us_data *us) | 96 | int usb_stor_huawei_e220_init(struct us_data *us) |
97 | { | 97 | { |
98 | int result; | 98 | int result; |
99 | 99 | ||
@@ -104,75 +104,3 @@ static int usb_stor_huawei_feature_init(struct us_data *us) | |||
104 | US_DEBUGP("Huawei mode set result is %d\n", result); | 104 | US_DEBUGP("Huawei mode set result is %d\n", result); |
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
107 | |||
108 | /* | ||
109 | * It will send a scsi switch command called rewind' to huawei dongle. | ||
110 | * When the dongle receives this command at the first time, | ||
111 | * it will reboot immediately. After rebooted, it will ignore this command. | ||
112 | * So it is unnecessary to read its response. | ||
113 | */ | ||
114 | static int usb_stor_huawei_scsi_init(struct us_data *us) | ||
115 | { | ||
116 | int result = 0; | ||
117 | int act_len = 0; | ||
118 | struct bulk_cb_wrap *bcbw = (struct bulk_cb_wrap *) us->iobuf; | ||
119 | char rewind_cmd[] = {0x11, 0x06, 0x20, 0x00, 0x00, 0x01, 0x01, 0x00, | ||
120 | 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; | ||
121 | |||
122 | bcbw->Signature = cpu_to_le32(US_BULK_CB_SIGN); | ||
123 | bcbw->Tag = 0; | ||
124 | bcbw->DataTransferLength = 0; | ||
125 | bcbw->Flags = bcbw->Lun = 0; | ||
126 | bcbw->Length = sizeof(rewind_cmd); | ||
127 | memset(bcbw->CDB, 0, sizeof(bcbw->CDB)); | ||
128 | memcpy(bcbw->CDB, rewind_cmd, sizeof(rewind_cmd)); | ||
129 | |||
130 | result = usb_stor_bulk_transfer_buf(us, us->send_bulk_pipe, bcbw, | ||
131 | US_BULK_CB_WRAP_LEN, &act_len); | ||
132 | US_DEBUGP("transfer actual length=%d, result=%d\n", act_len, result); | ||
133 | return result; | ||
134 | } | ||
135 | |||
136 | /* | ||
137 | * It tries to find the supported Huawei USB dongles. | ||
138 | * In Huawei, they assign the following product IDs | ||
139 | * for all of their mobile broadband dongles, | ||
140 | * including the new dongles in the future. | ||
141 | * So if the product ID is not included in this list, | ||
142 | * it means it is not Huawei's mobile broadband dongles. | ||
143 | */ | ||
144 | static int usb_stor_huawei_dongles_pid(struct us_data *us) | ||
145 | { | ||
146 | struct usb_interface_descriptor *idesc; | ||
147 | int idProduct; | ||
148 | |||
149 | idesc = &us->pusb_intf->cur_altsetting->desc; | ||
150 | idProduct = le16_to_cpu(us->pusb_dev->descriptor.idProduct); | ||
151 | /* The first port is CDROM, | ||
152 | * means the dongle in the single port mode, | ||
153 | * and a switch command is required to be sent. */ | ||
154 | if (idesc && idesc->bInterfaceNumber == 0) { | ||
155 | if ((idProduct == 0x1001) | ||
156 | || (idProduct == 0x1003) | ||
157 | || (idProduct == 0x1004) | ||
158 | || (idProduct >= 0x1401 && idProduct <= 0x1500) | ||
159 | || (idProduct >= 0x1505 && idProduct <= 0x1600) | ||
160 | || (idProduct >= 0x1c02 && idProduct <= 0x2202)) { | ||
161 | return 1; | ||
162 | } | ||
163 | } | ||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | int usb_stor_huawei_init(struct us_data *us) | ||
168 | { | ||
169 | int result = 0; | ||
170 | |||
171 | if (usb_stor_huawei_dongles_pid(us)) { | ||
172 | if (le16_to_cpu(us->pusb_dev->descriptor.idProduct) >= 0x1446) | ||
173 | result = usb_stor_huawei_scsi_init(us); | ||
174 | else | ||
175 | result = usb_stor_huawei_feature_init(us); | ||
176 | } | ||
177 | return result; | ||
178 | } | ||
diff --git a/drivers/usb/storage/initializers.h b/drivers/usb/storage/initializers.h index 5376d4fc76f0..529327fbb06b 100644 --- a/drivers/usb/storage/initializers.h +++ b/drivers/usb/storage/initializers.h | |||
@@ -46,5 +46,5 @@ int usb_stor_euscsi_init(struct us_data *us); | |||
46 | * flash reader */ | 46 | * flash reader */ |
47 | int usb_stor_ucr61s2b_init(struct us_data *us); | 47 | int usb_stor_ucr61s2b_init(struct us_data *us); |
48 | 48 | ||
49 | /* This places the HUAWEI usb dongles in multi-port mode */ | 49 | /* This places the HUAWEI E220 devices in multi-port mode */ |
50 | int usb_stor_huawei_init(struct us_data *us); | 50 | int usb_stor_huawei_e220_init(struct us_data *us); |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index 72923b56bbf6..1799335288bd 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -53,6 +53,14 @@ | |||
53 | * as opposed to devices that do something strangely or wrongly. | 53 | * as opposed to devices that do something strangely or wrongly. |
54 | */ | 54 | */ |
55 | 55 | ||
56 | /* In-kernel mode switching is deprecated. Do not add new devices to | ||
57 | * this list for the sole purpose of switching them to a different | ||
58 | * mode. Existing userspace solutions are superior. | ||
59 | * | ||
60 | * New mode switching devices should instead be added to the database | ||
61 | * maintained at http://www.draisberghof.de/usb_modeswitch/ | ||
62 | */ | ||
63 | |||
56 | #if !defined(CONFIG_USB_STORAGE_SDDR09) && \ | 64 | #if !defined(CONFIG_USB_STORAGE_SDDR09) && \ |
57 | !defined(CONFIG_USB_STORAGE_SDDR09_MODULE) | 65 | !defined(CONFIG_USB_STORAGE_SDDR09_MODULE) |
58 | #define NO_SDDR09 | 66 | #define NO_SDDR09 |
@@ -488,6 +496,13 @@ UNUSUAL_DEV( 0x04e8, 0x5122, 0x0000, 0x9999, | |||
488 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, | 496 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, |
489 | US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), | 497 | US_FL_MAX_SECTORS_64 | US_FL_BULK_IGNORE_TAG), |
490 | 498 | ||
499 | /* Added by Dmitry Artamonow <mad_soft@inbox.ru> */ | ||
500 | UNUSUAL_DEV( 0x04e8, 0x5136, 0x0000, 0x9999, | ||
501 | "Samsung", | ||
502 | "YP-Z3", | ||
503 | USB_SC_DEVICE, USB_PR_DEVICE, NULL, | ||
504 | US_FL_MAX_SECTORS_64), | ||
505 | |||
491 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. | 506 | /* Entry and supporting patch by Theodore Kilgore <kilgota@auburn.edu>. |
492 | * Device uses standards-violating 32-byte Bulk Command Block Wrappers and | 507 | * Device uses standards-violating 32-byte Bulk Command Block Wrappers and |
493 | * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. | 508 | * reports itself as "Proprietary SCSI Bulk." Cf. device entry 0x084d:0x0011. |
@@ -1527,10 +1542,335 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, | |||
1527 | /* Reported by fangxiaozhi <huananhu@huawei.com> | 1542 | /* Reported by fangxiaozhi <huananhu@huawei.com> |
1528 | * This brings the HUAWEI data card devices into multi-port mode | 1543 | * This brings the HUAWEI data card devices into multi-port mode |
1529 | */ | 1544 | */ |
1530 | UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50, | 1545 | UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000, |
1546 | "HUAWEI MOBILE", | ||
1547 | "Mass Storage", | ||
1548 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1549 | 0), | ||
1550 | UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000, | ||
1551 | "HUAWEI MOBILE", | ||
1552 | "Mass Storage", | ||
1553 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1554 | 0), | ||
1555 | UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000, | ||
1556 | "HUAWEI MOBILE", | ||
1557 | "Mass Storage", | ||
1558 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1559 | 0), | ||
1560 | UNUSUAL_DEV( 0x12d1, 0x1401, 0x0000, 0x0000, | ||
1561 | "HUAWEI MOBILE", | ||
1562 | "Mass Storage", | ||
1563 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1564 | 0), | ||
1565 | UNUSUAL_DEV( 0x12d1, 0x1402, 0x0000, 0x0000, | ||
1566 | "HUAWEI MOBILE", | ||
1567 | "Mass Storage", | ||
1568 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1569 | 0), | ||
1570 | UNUSUAL_DEV( 0x12d1, 0x1403, 0x0000, 0x0000, | ||
1571 | "HUAWEI MOBILE", | ||
1572 | "Mass Storage", | ||
1573 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1574 | 0), | ||
1575 | UNUSUAL_DEV( 0x12d1, 0x1404, 0x0000, 0x0000, | ||
1576 | "HUAWEI MOBILE", | ||
1577 | "Mass Storage", | ||
1578 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1579 | 0), | ||
1580 | UNUSUAL_DEV( 0x12d1, 0x1405, 0x0000, 0x0000, | ||
1581 | "HUAWEI MOBILE", | ||
1582 | "Mass Storage", | ||
1583 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1584 | 0), | ||
1585 | UNUSUAL_DEV( 0x12d1, 0x1406, 0x0000, 0x0000, | ||
1586 | "HUAWEI MOBILE", | ||
1587 | "Mass Storage", | ||
1588 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1589 | 0), | ||
1590 | UNUSUAL_DEV( 0x12d1, 0x1407, 0x0000, 0x0000, | ||
1591 | "HUAWEI MOBILE", | ||
1592 | "Mass Storage", | ||
1593 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1594 | 0), | ||
1595 | UNUSUAL_DEV( 0x12d1, 0x1408, 0x0000, 0x0000, | ||
1596 | "HUAWEI MOBILE", | ||
1597 | "Mass Storage", | ||
1598 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1599 | 0), | ||
1600 | UNUSUAL_DEV( 0x12d1, 0x1409, 0x0000, 0x0000, | ||
1601 | "HUAWEI MOBILE", | ||
1602 | "Mass Storage", | ||
1603 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1604 | 0), | ||
1605 | UNUSUAL_DEV( 0x12d1, 0x140A, 0x0000, 0x0000, | ||
1606 | "HUAWEI MOBILE", | ||
1607 | "Mass Storage", | ||
1608 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1609 | 0), | ||
1610 | UNUSUAL_DEV( 0x12d1, 0x140B, 0x0000, 0x0000, | ||
1611 | "HUAWEI MOBILE", | ||
1612 | "Mass Storage", | ||
1613 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1614 | 0), | ||
1615 | UNUSUAL_DEV( 0x12d1, 0x140C, 0x0000, 0x0000, | ||
1616 | "HUAWEI MOBILE", | ||
1617 | "Mass Storage", | ||
1618 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1619 | 0), | ||
1620 | UNUSUAL_DEV( 0x12d1, 0x140D, 0x0000, 0x0000, | ||
1621 | "HUAWEI MOBILE", | ||
1622 | "Mass Storage", | ||
1623 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1624 | 0), | ||
1625 | UNUSUAL_DEV( 0x12d1, 0x140E, 0x0000, 0x0000, | ||
1626 | "HUAWEI MOBILE", | ||
1627 | "Mass Storage", | ||
1628 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1629 | 0), | ||
1630 | UNUSUAL_DEV( 0x12d1, 0x140F, 0x0000, 0x0000, | ||
1631 | "HUAWEI MOBILE", | ||
1632 | "Mass Storage", | ||
1633 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1634 | 0), | ||
1635 | UNUSUAL_DEV( 0x12d1, 0x1410, 0x0000, 0x0000, | ||
1636 | "HUAWEI MOBILE", | ||
1637 | "Mass Storage", | ||
1638 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1639 | 0), | ||
1640 | UNUSUAL_DEV( 0x12d1, 0x1411, 0x0000, 0x0000, | ||
1641 | "HUAWEI MOBILE", | ||
1642 | "Mass Storage", | ||
1643 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1644 | 0), | ||
1645 | UNUSUAL_DEV( 0x12d1, 0x1412, 0x0000, 0x0000, | ||
1646 | "HUAWEI MOBILE", | ||
1647 | "Mass Storage", | ||
1648 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1649 | 0), | ||
1650 | UNUSUAL_DEV( 0x12d1, 0x1413, 0x0000, 0x0000, | ||
1651 | "HUAWEI MOBILE", | ||
1652 | "Mass Storage", | ||
1653 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1654 | 0), | ||
1655 | UNUSUAL_DEV( 0x12d1, 0x1414, 0x0000, 0x0000, | ||
1656 | "HUAWEI MOBILE", | ||
1657 | "Mass Storage", | ||
1658 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1659 | 0), | ||
1660 | UNUSUAL_DEV( 0x12d1, 0x1415, 0x0000, 0x0000, | ||
1661 | "HUAWEI MOBILE", | ||
1662 | "Mass Storage", | ||
1663 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1664 | 0), | ||
1665 | UNUSUAL_DEV( 0x12d1, 0x1416, 0x0000, 0x0000, | ||
1666 | "HUAWEI MOBILE", | ||
1667 | "Mass Storage", | ||
1668 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1669 | 0), | ||
1670 | UNUSUAL_DEV( 0x12d1, 0x1417, 0x0000, 0x0000, | ||
1671 | "HUAWEI MOBILE", | ||
1672 | "Mass Storage", | ||
1673 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1674 | 0), | ||
1675 | UNUSUAL_DEV( 0x12d1, 0x1418, 0x0000, 0x0000, | ||
1676 | "HUAWEI MOBILE", | ||
1677 | "Mass Storage", | ||
1678 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1679 | 0), | ||
1680 | UNUSUAL_DEV( 0x12d1, 0x1419, 0x0000, 0x0000, | ||
1681 | "HUAWEI MOBILE", | ||
1682 | "Mass Storage", | ||
1683 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1684 | 0), | ||
1685 | UNUSUAL_DEV( 0x12d1, 0x141A, 0x0000, 0x0000, | ||
1686 | "HUAWEI MOBILE", | ||
1687 | "Mass Storage", | ||
1688 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1689 | 0), | ||
1690 | UNUSUAL_DEV( 0x12d1, 0x141B, 0x0000, 0x0000, | ||
1691 | "HUAWEI MOBILE", | ||
1692 | "Mass Storage", | ||
1693 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1694 | 0), | ||
1695 | UNUSUAL_DEV( 0x12d1, 0x141C, 0x0000, 0x0000, | ||
1696 | "HUAWEI MOBILE", | ||
1697 | "Mass Storage", | ||
1698 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1699 | 0), | ||
1700 | UNUSUAL_DEV( 0x12d1, 0x141D, 0x0000, 0x0000, | ||
1701 | "HUAWEI MOBILE", | ||
1702 | "Mass Storage", | ||
1703 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1704 | 0), | ||
1705 | UNUSUAL_DEV( 0x12d1, 0x141E, 0x0000, 0x0000, | ||
1706 | "HUAWEI MOBILE", | ||
1707 | "Mass Storage", | ||
1708 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1709 | 0), | ||
1710 | UNUSUAL_DEV( 0x12d1, 0x141F, 0x0000, 0x0000, | ||
1711 | "HUAWEI MOBILE", | ||
1712 | "Mass Storage", | ||
1713 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1714 | 0), | ||
1715 | UNUSUAL_DEV( 0x12d1, 0x1420, 0x0000, 0x0000, | ||
1716 | "HUAWEI MOBILE", | ||
1717 | "Mass Storage", | ||
1718 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1719 | 0), | ||
1720 | UNUSUAL_DEV( 0x12d1, 0x1421, 0x0000, 0x0000, | ||
1721 | "HUAWEI MOBILE", | ||
1722 | "Mass Storage", | ||
1723 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1724 | 0), | ||
1725 | UNUSUAL_DEV( 0x12d1, 0x1422, 0x0000, 0x0000, | ||
1726 | "HUAWEI MOBILE", | ||
1727 | "Mass Storage", | ||
1728 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1729 | 0), | ||
1730 | UNUSUAL_DEV( 0x12d1, 0x1423, 0x0000, 0x0000, | ||
1731 | "HUAWEI MOBILE", | ||
1732 | "Mass Storage", | ||
1733 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1734 | 0), | ||
1735 | UNUSUAL_DEV( 0x12d1, 0x1424, 0x0000, 0x0000, | ||
1736 | "HUAWEI MOBILE", | ||
1737 | "Mass Storage", | ||
1738 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1739 | 0), | ||
1740 | UNUSUAL_DEV( 0x12d1, 0x1425, 0x0000, 0x0000, | ||
1741 | "HUAWEI MOBILE", | ||
1742 | "Mass Storage", | ||
1743 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1744 | 0), | ||
1745 | UNUSUAL_DEV( 0x12d1, 0x1426, 0x0000, 0x0000, | ||
1746 | "HUAWEI MOBILE", | ||
1747 | "Mass Storage", | ||
1748 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1749 | 0), | ||
1750 | UNUSUAL_DEV( 0x12d1, 0x1427, 0x0000, 0x0000, | ||
1751 | "HUAWEI MOBILE", | ||
1752 | "Mass Storage", | ||
1753 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1754 | 0), | ||
1755 | UNUSUAL_DEV( 0x12d1, 0x1428, 0x0000, 0x0000, | ||
1756 | "HUAWEI MOBILE", | ||
1757 | "Mass Storage", | ||
1758 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1759 | 0), | ||
1760 | UNUSUAL_DEV( 0x12d1, 0x1429, 0x0000, 0x0000, | ||
1761 | "HUAWEI MOBILE", | ||
1762 | "Mass Storage", | ||
1763 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1764 | 0), | ||
1765 | UNUSUAL_DEV( 0x12d1, 0x142A, 0x0000, 0x0000, | ||
1766 | "HUAWEI MOBILE", | ||
1767 | "Mass Storage", | ||
1768 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1769 | 0), | ||
1770 | UNUSUAL_DEV( 0x12d1, 0x142B, 0x0000, 0x0000, | ||
1771 | "HUAWEI MOBILE", | ||
1772 | "Mass Storage", | ||
1773 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1774 | 0), | ||
1775 | UNUSUAL_DEV( 0x12d1, 0x142C, 0x0000, 0x0000, | ||
1776 | "HUAWEI MOBILE", | ||
1777 | "Mass Storage", | ||
1778 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1779 | 0), | ||
1780 | UNUSUAL_DEV( 0x12d1, 0x142D, 0x0000, 0x0000, | ||
1781 | "HUAWEI MOBILE", | ||
1782 | "Mass Storage", | ||
1783 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1784 | 0), | ||
1785 | UNUSUAL_DEV( 0x12d1, 0x142E, 0x0000, 0x0000, | ||
1786 | "HUAWEI MOBILE", | ||
1787 | "Mass Storage", | ||
1788 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1789 | 0), | ||
1790 | UNUSUAL_DEV( 0x12d1, 0x142F, 0x0000, 0x0000, | ||
1791 | "HUAWEI MOBILE", | ||
1792 | "Mass Storage", | ||
1793 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1794 | 0), | ||
1795 | UNUSUAL_DEV( 0x12d1, 0x1430, 0x0000, 0x0000, | ||
1796 | "HUAWEI MOBILE", | ||
1797 | "Mass Storage", | ||
1798 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1799 | 0), | ||
1800 | UNUSUAL_DEV( 0x12d1, 0x1431, 0x0000, 0x0000, | ||
1801 | "HUAWEI MOBILE", | ||
1802 | "Mass Storage", | ||
1803 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1804 | 0), | ||
1805 | UNUSUAL_DEV( 0x12d1, 0x1432, 0x0000, 0x0000, | ||
1806 | "HUAWEI MOBILE", | ||
1807 | "Mass Storage", | ||
1808 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1809 | 0), | ||
1810 | UNUSUAL_DEV( 0x12d1, 0x1433, 0x0000, 0x0000, | ||
1811 | "HUAWEI MOBILE", | ||
1812 | "Mass Storage", | ||
1813 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1814 | 0), | ||
1815 | UNUSUAL_DEV( 0x12d1, 0x1434, 0x0000, 0x0000, | ||
1816 | "HUAWEI MOBILE", | ||
1817 | "Mass Storage", | ||
1818 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1819 | 0), | ||
1820 | UNUSUAL_DEV( 0x12d1, 0x1435, 0x0000, 0x0000, | ||
1821 | "HUAWEI MOBILE", | ||
1822 | "Mass Storage", | ||
1823 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1824 | 0), | ||
1825 | UNUSUAL_DEV( 0x12d1, 0x1436, 0x0000, 0x0000, | ||
1826 | "HUAWEI MOBILE", | ||
1827 | "Mass Storage", | ||
1828 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1829 | 0), | ||
1830 | UNUSUAL_DEV( 0x12d1, 0x1437, 0x0000, 0x0000, | ||
1831 | "HUAWEI MOBILE", | ||
1832 | "Mass Storage", | ||
1833 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1834 | 0), | ||
1835 | UNUSUAL_DEV( 0x12d1, 0x1438, 0x0000, 0x0000, | ||
1836 | "HUAWEI MOBILE", | ||
1837 | "Mass Storage", | ||
1838 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1839 | 0), | ||
1840 | UNUSUAL_DEV( 0x12d1, 0x1439, 0x0000, 0x0000, | ||
1841 | "HUAWEI MOBILE", | ||
1842 | "Mass Storage", | ||
1843 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1844 | 0), | ||
1845 | UNUSUAL_DEV( 0x12d1, 0x143A, 0x0000, 0x0000, | ||
1846 | "HUAWEI MOBILE", | ||
1847 | "Mass Storage", | ||
1848 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1849 | 0), | ||
1850 | UNUSUAL_DEV( 0x12d1, 0x143B, 0x0000, 0x0000, | ||
1851 | "HUAWEI MOBILE", | ||
1852 | "Mass Storage", | ||
1853 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1854 | 0), | ||
1855 | UNUSUAL_DEV( 0x12d1, 0x143C, 0x0000, 0x0000, | ||
1856 | "HUAWEI MOBILE", | ||
1857 | "Mass Storage", | ||
1858 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1859 | 0), | ||
1860 | UNUSUAL_DEV( 0x12d1, 0x143D, 0x0000, 0x0000, | ||
1861 | "HUAWEI MOBILE", | ||
1862 | "Mass Storage", | ||
1863 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1864 | 0), | ||
1865 | UNUSUAL_DEV( 0x12d1, 0x143E, 0x0000, 0x0000, | ||
1866 | "HUAWEI MOBILE", | ||
1867 | "Mass Storage", | ||
1868 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1869 | 0), | ||
1870 | UNUSUAL_DEV( 0x12d1, 0x143F, 0x0000, 0x0000, | ||
1531 | "HUAWEI MOBILE", | 1871 | "HUAWEI MOBILE", |
1532 | "Mass Storage", | 1872 | "Mass Storage", |
1533 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init, | 1873 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, |
1534 | 0), | 1874 | 0), |
1535 | 1875 | ||
1536 | /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ | 1876 | /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ |
diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 964ff22bf281..aeb00fc2d3be 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/pci.h> | 27 | #include <linux/pci.h> |
28 | #include <linux/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <linux/vfio.h> | 29 | #include <linux/vfio.h> |
30 | #include <linux/slab.h> | ||
30 | 31 | ||
31 | #include "vfio_pci_private.h" | 32 | #include "vfio_pci_private.h" |
32 | 33 | ||
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 3639371fa697..a96509187deb 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/vfio.h> | 22 | #include <linux/vfio.h> |
23 | #include <linux/wait.h> | 23 | #include <linux/wait.h> |
24 | #include <linux/workqueue.h> | 24 | #include <linux/workqueue.h> |
25 | #include <linux/slab.h> | ||
25 | 26 | ||
26 | #include "vfio_pci_private.h" | 27 | #include "vfio_pci_private.h" |
27 | 28 | ||
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index 959b1cd89e6a..ec6fb3fa59bb 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -339,7 +339,8 @@ static void handle_tx(struct vhost_net *net) | |||
339 | msg.msg_controllen = 0; | 339 | msg.msg_controllen = 0; |
340 | ubufs = NULL; | 340 | ubufs = NULL; |
341 | } else { | 341 | } else { |
342 | struct ubuf_info *ubuf = &vq->ubuf_info[head]; | 342 | struct ubuf_info *ubuf; |
343 | ubuf = vq->ubuf_info + vq->upend_idx; | ||
343 | 344 | ||
344 | vq->heads[vq->upend_idx].len = | 345 | vq->heads[vq->upend_idx].len = |
345 | VHOST_DMA_IN_PROGRESS; | 346 | VHOST_DMA_IN_PROGRESS; |
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index 9951297b2427..2968b4934659 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c | |||
@@ -60,6 +60,15 @@ enum { | |||
60 | VHOST_SCSI_VQ_IO = 2, | 60 | VHOST_SCSI_VQ_IO = 2, |
61 | }; | 61 | }; |
62 | 62 | ||
63 | /* | ||
64 | * VIRTIO_RING_F_EVENT_IDX seems broken. Not sure the bug is in | ||
65 | * kernel but disabling it helps. | ||
66 | * TODO: debug and remove the workaround. | ||
67 | */ | ||
68 | enum { | ||
69 | VHOST_SCSI_FEATURES = VHOST_FEATURES & (~VIRTIO_RING_F_EVENT_IDX) | ||
70 | }; | ||
71 | |||
63 | #define VHOST_SCSI_MAX_TARGET 256 | 72 | #define VHOST_SCSI_MAX_TARGET 256 |
64 | #define VHOST_SCSI_MAX_VQ 128 | 73 | #define VHOST_SCSI_MAX_VQ 128 |
65 | 74 | ||
@@ -850,7 +859,7 @@ static int vhost_scsi_clear_endpoint( | |||
850 | for (index = 0; index < vs->dev.nvqs; ++index) { | 859 | for (index = 0; index < vs->dev.nvqs; ++index) { |
851 | if (!vhost_vq_access_ok(&vs->vqs[index])) { | 860 | if (!vhost_vq_access_ok(&vs->vqs[index])) { |
852 | ret = -EFAULT; | 861 | ret = -EFAULT; |
853 | goto err; | 862 | goto err_dev; |
854 | } | 863 | } |
855 | } | 864 | } |
856 | for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) { | 865 | for (i = 0; i < VHOST_SCSI_MAX_TARGET; i++) { |
@@ -860,10 +869,11 @@ static int vhost_scsi_clear_endpoint( | |||
860 | if (!tv_tpg) | 869 | if (!tv_tpg) |
861 | continue; | 870 | continue; |
862 | 871 | ||
872 | mutex_lock(&tv_tpg->tv_tpg_mutex); | ||
863 | tv_tport = tv_tpg->tport; | 873 | tv_tport = tv_tpg->tport; |
864 | if (!tv_tport) { | 874 | if (!tv_tport) { |
865 | ret = -ENODEV; | 875 | ret = -ENODEV; |
866 | goto err; | 876 | goto err_tpg; |
867 | } | 877 | } |
868 | 878 | ||
869 | if (strcmp(tv_tport->tport_name, t->vhost_wwpn)) { | 879 | if (strcmp(tv_tport->tport_name, t->vhost_wwpn)) { |
@@ -872,16 +882,19 @@ static int vhost_scsi_clear_endpoint( | |||
872 | tv_tport->tport_name, tv_tpg->tport_tpgt, | 882 | tv_tport->tport_name, tv_tpg->tport_tpgt, |
873 | t->vhost_wwpn, t->vhost_tpgt); | 883 | t->vhost_wwpn, t->vhost_tpgt); |
874 | ret = -EINVAL; | 884 | ret = -EINVAL; |
875 | goto err; | 885 | goto err_tpg; |
876 | } | 886 | } |
877 | tv_tpg->tv_tpg_vhost_count--; | 887 | tv_tpg->tv_tpg_vhost_count--; |
878 | vs->vs_tpg[target] = NULL; | 888 | vs->vs_tpg[target] = NULL; |
879 | vs->vs_endpoint = false; | 889 | vs->vs_endpoint = false; |
890 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | ||
880 | } | 891 | } |
881 | mutex_unlock(&vs->dev.mutex); | 892 | mutex_unlock(&vs->dev.mutex); |
882 | return 0; | 893 | return 0; |
883 | 894 | ||
884 | err: | 895 | err_tpg: |
896 | mutex_unlock(&tv_tpg->tv_tpg_mutex); | ||
897 | err_dev: | ||
885 | mutex_unlock(&vs->dev.mutex); | 898 | mutex_unlock(&vs->dev.mutex); |
886 | return ret; | 899 | return ret; |
887 | } | 900 | } |
@@ -937,11 +950,12 @@ static void vhost_scsi_flush(struct vhost_scsi *vs) | |||
937 | 950 | ||
938 | for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) | 951 | for (i = 0; i < VHOST_SCSI_MAX_VQ; i++) |
939 | vhost_scsi_flush_vq(vs, i); | 952 | vhost_scsi_flush_vq(vs, i); |
953 | vhost_work_flush(&vs->dev, &vs->vs_completion_work); | ||
940 | } | 954 | } |
941 | 955 | ||
942 | static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) | 956 | static int vhost_scsi_set_features(struct vhost_scsi *vs, u64 features) |
943 | { | 957 | { |
944 | if (features & ~VHOST_FEATURES) | 958 | if (features & ~VHOST_SCSI_FEATURES) |
945 | return -EOPNOTSUPP; | 959 | return -EOPNOTSUPP; |
946 | 960 | ||
947 | mutex_lock(&vs->dev.mutex); | 961 | mutex_lock(&vs->dev.mutex); |
@@ -987,7 +1001,7 @@ static long vhost_scsi_ioctl(struct file *f, unsigned int ioctl, | |||
987 | return -EFAULT; | 1001 | return -EFAULT; |
988 | return 0; | 1002 | return 0; |
989 | case VHOST_GET_FEATURES: | 1003 | case VHOST_GET_FEATURES: |
990 | features = VHOST_FEATURES; | 1004 | features = VHOST_SCSI_FEATURES; |
991 | if (copy_to_user(featurep, &features, sizeof features)) | 1005 | if (copy_to_user(featurep, &features, sizeof features)) |
992 | return -EFAULT; | 1006 | return -EFAULT; |
993 | return 0; | 1007 | return 0; |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 12cf5f31ee8f..c1a2914447e1 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
@@ -34,6 +34,77 @@ | |||
34 | #define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */ | 34 | #define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */ |
35 | #define ATMEL_LCDC_FIFO_SIZE 512 /* words */ | 35 | #define ATMEL_LCDC_FIFO_SIZE 512 /* words */ |
36 | 36 | ||
37 | struct atmel_lcdfb_config { | ||
38 | bool have_alt_pixclock; | ||
39 | bool have_hozval; | ||
40 | bool have_intensity_bit; | ||
41 | }; | ||
42 | |||
43 | static struct atmel_lcdfb_config at91sam9261_config = { | ||
44 | .have_hozval = true, | ||
45 | .have_intensity_bit = true, | ||
46 | }; | ||
47 | |||
48 | static struct atmel_lcdfb_config at91sam9263_config = { | ||
49 | .have_intensity_bit = true, | ||
50 | }; | ||
51 | |||
52 | static struct atmel_lcdfb_config at91sam9g10_config = { | ||
53 | .have_hozval = true, | ||
54 | }; | ||
55 | |||
56 | static struct atmel_lcdfb_config at91sam9g45_config = { | ||
57 | .have_alt_pixclock = true, | ||
58 | }; | ||
59 | |||
60 | static struct atmel_lcdfb_config at91sam9g45es_config = { | ||
61 | }; | ||
62 | |||
63 | static struct atmel_lcdfb_config at91sam9rl_config = { | ||
64 | .have_intensity_bit = true, | ||
65 | }; | ||
66 | |||
67 | static struct atmel_lcdfb_config at32ap_config = { | ||
68 | .have_hozval = true, | ||
69 | }; | ||
70 | |||
71 | static const struct platform_device_id atmel_lcdfb_devtypes[] = { | ||
72 | { | ||
73 | .name = "at91sam9261-lcdfb", | ||
74 | .driver_data = (unsigned long)&at91sam9261_config, | ||
75 | }, { | ||
76 | .name = "at91sam9263-lcdfb", | ||
77 | .driver_data = (unsigned long)&at91sam9263_config, | ||
78 | }, { | ||
79 | .name = "at91sam9g10-lcdfb", | ||
80 | .driver_data = (unsigned long)&at91sam9g10_config, | ||
81 | }, { | ||
82 | .name = "at91sam9g45-lcdfb", | ||
83 | .driver_data = (unsigned long)&at91sam9g45_config, | ||
84 | }, { | ||
85 | .name = "at91sam9g45es-lcdfb", | ||
86 | .driver_data = (unsigned long)&at91sam9g45es_config, | ||
87 | }, { | ||
88 | .name = "at91sam9rl-lcdfb", | ||
89 | .driver_data = (unsigned long)&at91sam9rl_config, | ||
90 | }, { | ||
91 | .name = "at32ap-lcdfb", | ||
92 | .driver_data = (unsigned long)&at32ap_config, | ||
93 | }, { | ||
94 | /* terminator */ | ||
95 | } | ||
96 | }; | ||
97 | |||
98 | static struct atmel_lcdfb_config * | ||
99 | atmel_lcdfb_get_config(struct platform_device *pdev) | ||
100 | { | ||
101 | unsigned long data; | ||
102 | |||
103 | data = platform_get_device_id(pdev)->driver_data; | ||
104 | |||
105 | return (struct atmel_lcdfb_config *)data; | ||
106 | } | ||
107 | |||
37 | #if defined(CONFIG_ARCH_AT91) | 108 | #if defined(CONFIG_ARCH_AT91) |
38 | #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ | 109 | #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ |
39 | | FBINFO_PARTIAL_PAN_OK \ | 110 | | FBINFO_PARTIAL_PAN_OK \ |
@@ -193,14 +264,16 @@ static struct fb_fix_screeninfo atmel_lcdfb_fix __initdata = { | |||
193 | .accel = FB_ACCEL_NONE, | 264 | .accel = FB_ACCEL_NONE, |
194 | }; | 265 | }; |
195 | 266 | ||
196 | static unsigned long compute_hozval(unsigned long xres, unsigned long lcdcon2) | 267 | static unsigned long compute_hozval(struct atmel_lcdfb_info *sinfo, |
268 | unsigned long xres) | ||
197 | { | 269 | { |
270 | unsigned long lcdcon2; | ||
198 | unsigned long value; | 271 | unsigned long value; |
199 | 272 | ||
200 | if (!(cpu_is_at91sam9261() || cpu_is_at91sam9g10() | 273 | if (!sinfo->config->have_hozval) |
201 | || cpu_is_at32ap7000())) | ||
202 | return xres; | 274 | return xres; |
203 | 275 | ||
276 | lcdcon2 = lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2); | ||
204 | value = xres; | 277 | value = xres; |
205 | if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) { | 278 | if ((lcdcon2 & ATMEL_LCDC_DISTYPE) != ATMEL_LCDC_DISTYPE_TFT) { |
206 | /* STN display */ | 279 | /* STN display */ |
@@ -422,17 +495,22 @@ static int atmel_lcdfb_check_var(struct fb_var_screeninfo *var, | |||
422 | = var->bits_per_pixel; | 495 | = var->bits_per_pixel; |
423 | break; | 496 | break; |
424 | case 16: | 497 | case 16: |
498 | /* Older SOCs use IBGR:555 rather than BGR:565. */ | ||
499 | if (sinfo->config->have_intensity_bit) | ||
500 | var->green.length = 5; | ||
501 | else | ||
502 | var->green.length = 6; | ||
503 | |||
425 | if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { | 504 | if (sinfo->lcd_wiring_mode == ATMEL_LCDC_WIRING_RGB) { |
426 | /* RGB:565 mode */ | 505 | /* RGB:5X5 mode */ |
427 | var->red.offset = 11; | 506 | var->red.offset = var->green.length + 5; |
428 | var->blue.offset = 0; | 507 | var->blue.offset = 0; |
429 | } else { | 508 | } else { |
430 | /* BGR:565 mode */ | 509 | /* BGR:5X5 mode */ |
431 | var->red.offset = 0; | 510 | var->red.offset = 0; |
432 | var->blue.offset = 11; | 511 | var->blue.offset = var->green.length + 5; |
433 | } | 512 | } |
434 | var->green.offset = 5; | 513 | var->green.offset = 5; |
435 | var->green.length = 6; | ||
436 | var->red.length = var->blue.length = 5; | 514 | var->red.length = var->blue.length = 5; |
437 | break; | 515 | break; |
438 | case 32: | 516 | case 32: |
@@ -526,7 +604,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
526 | /* Now, the LCDC core... */ | 604 | /* Now, the LCDC core... */ |
527 | 605 | ||
528 | /* Set pixel clock */ | 606 | /* Set pixel clock */ |
529 | if (cpu_is_at91sam9g45() && !cpu_is_at91sam9g45es()) | 607 | if (sinfo->config->have_alt_pixclock) |
530 | pix_factor = 1; | 608 | pix_factor = 1; |
531 | 609 | ||
532 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; | 610 | clk_value_khz = clk_get_rate(sinfo->lcdc_clk) / 1000; |
@@ -586,8 +664,7 @@ static int atmel_lcdfb_set_par(struct fb_info *info) | |||
586 | lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); | 664 | lcdc_writel(sinfo, ATMEL_LCDC_TIM2, value); |
587 | 665 | ||
588 | /* Horizontal value (aka line size) */ | 666 | /* Horizontal value (aka line size) */ |
589 | hozval_linesz = compute_hozval(info->var.xres, | 667 | hozval_linesz = compute_hozval(sinfo, info->var.xres); |
590 | lcdc_readl(sinfo, ATMEL_LCDC_LCDCON2)); | ||
591 | 668 | ||
592 | /* Display size */ | 669 | /* Display size */ |
593 | value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET; | 670 | value = (hozval_linesz - 1) << ATMEL_LCDC_HOZVAL_OFFSET; |
@@ -679,8 +756,7 @@ static int atmel_lcdfb_setcolreg(unsigned int regno, unsigned int red, | |||
679 | 756 | ||
680 | case FB_VISUAL_PSEUDOCOLOR: | 757 | case FB_VISUAL_PSEUDOCOLOR: |
681 | if (regno < 256) { | 758 | if (regno < 256) { |
682 | if (cpu_is_at91sam9261() || cpu_is_at91sam9263() | 759 | if (sinfo->config->have_intensity_bit) { |
683 | || cpu_is_at91sam9rl()) { | ||
684 | /* old style I+BGR:555 */ | 760 | /* old style I+BGR:555 */ |
685 | val = ((red >> 11) & 0x001f); | 761 | val = ((red >> 11) & 0x001f); |
686 | val |= ((green >> 6) & 0x03e0); | 762 | val |= ((green >> 6) & 0x03e0); |
@@ -817,15 +893,13 @@ static int __init atmel_lcdfb_init_fbinfo(struct atmel_lcdfb_info *sinfo) | |||
817 | 893 | ||
818 | static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) | 894 | static void atmel_lcdfb_start_clock(struct atmel_lcdfb_info *sinfo) |
819 | { | 895 | { |
820 | if (sinfo->bus_clk) | 896 | clk_enable(sinfo->bus_clk); |
821 | clk_enable(sinfo->bus_clk); | ||
822 | clk_enable(sinfo->lcdc_clk); | 897 | clk_enable(sinfo->lcdc_clk); |
823 | } | 898 | } |
824 | 899 | ||
825 | static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) | 900 | static void atmel_lcdfb_stop_clock(struct atmel_lcdfb_info *sinfo) |
826 | { | 901 | { |
827 | if (sinfo->bus_clk) | 902 | clk_disable(sinfo->bus_clk); |
828 | clk_disable(sinfo->bus_clk); | ||
829 | clk_disable(sinfo->lcdc_clk); | 903 | clk_disable(sinfo->lcdc_clk); |
830 | } | 904 | } |
831 | 905 | ||
@@ -870,6 +944,9 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
870 | } | 944 | } |
871 | sinfo->info = info; | 945 | sinfo->info = info; |
872 | sinfo->pdev = pdev; | 946 | sinfo->pdev = pdev; |
947 | sinfo->config = atmel_lcdfb_get_config(pdev); | ||
948 | if (!sinfo->config) | ||
949 | goto free_info; | ||
873 | 950 | ||
874 | strcpy(info->fix.id, sinfo->pdev->name); | 951 | strcpy(info->fix.id, sinfo->pdev->name); |
875 | info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; | 952 | info->flags = ATMEL_LCDFB_FBINFO_DEFAULT; |
@@ -880,13 +957,10 @@ static int __init atmel_lcdfb_probe(struct platform_device *pdev) | |||
880 | info->fix = atmel_lcdfb_fix; | 957 | info->fix = atmel_lcdfb_fix; |
881 | 958 | ||
882 | /* Enable LCDC Clocks */ | 959 | /* Enable LCDC Clocks */ |
883 | if (cpu_is_at91sam9261() || cpu_is_at91sam9g10() | 960 | sinfo->bus_clk = clk_get(dev, "hclk"); |
884 | || cpu_is_at32ap7000()) { | 961 | if (IS_ERR(sinfo->bus_clk)) { |
885 | sinfo->bus_clk = clk_get(dev, "hck1"); | 962 | ret = PTR_ERR(sinfo->bus_clk); |
886 | if (IS_ERR(sinfo->bus_clk)) { | 963 | goto free_info; |
887 | ret = PTR_ERR(sinfo->bus_clk); | ||
888 | goto free_info; | ||
889 | } | ||
890 | } | 964 | } |
891 | sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); | 965 | sinfo->lcdc_clk = clk_get(dev, "lcdc_clk"); |
892 | if (IS_ERR(sinfo->lcdc_clk)) { | 966 | if (IS_ERR(sinfo->lcdc_clk)) { |
@@ -1047,8 +1121,7 @@ stop_clk: | |||
1047 | atmel_lcdfb_stop_clock(sinfo); | 1121 | atmel_lcdfb_stop_clock(sinfo); |
1048 | clk_put(sinfo->lcdc_clk); | 1122 | clk_put(sinfo->lcdc_clk); |
1049 | put_bus_clk: | 1123 | put_bus_clk: |
1050 | if (sinfo->bus_clk) | 1124 | clk_put(sinfo->bus_clk); |
1051 | clk_put(sinfo->bus_clk); | ||
1052 | free_info: | 1125 | free_info: |
1053 | framebuffer_release(info); | 1126 | framebuffer_release(info); |
1054 | out: | 1127 | out: |
@@ -1073,8 +1146,7 @@ static int __exit atmel_lcdfb_remove(struct platform_device *pdev) | |||
1073 | unregister_framebuffer(info); | 1146 | unregister_framebuffer(info); |
1074 | atmel_lcdfb_stop_clock(sinfo); | 1147 | atmel_lcdfb_stop_clock(sinfo); |
1075 | clk_put(sinfo->lcdc_clk); | 1148 | clk_put(sinfo->lcdc_clk); |
1076 | if (sinfo->bus_clk) | 1149 | clk_put(sinfo->bus_clk); |
1077 | clk_put(sinfo->bus_clk); | ||
1078 | fb_dealloc_cmap(&info->cmap); | 1150 | fb_dealloc_cmap(&info->cmap); |
1079 | free_irq(sinfo->irq_base, info); | 1151 | free_irq(sinfo->irq_base, info); |
1080 | iounmap(sinfo->mmio); | 1152 | iounmap(sinfo->mmio); |
@@ -1143,7 +1215,7 @@ static struct platform_driver atmel_lcdfb_driver = { | |||
1143 | .remove = __exit_p(atmel_lcdfb_remove), | 1215 | .remove = __exit_p(atmel_lcdfb_remove), |
1144 | .suspend = atmel_lcdfb_suspend, | 1216 | .suspend = atmel_lcdfb_suspend, |
1145 | .resume = atmel_lcdfb_resume, | 1217 | .resume = atmel_lcdfb_resume, |
1146 | 1218 | .id_table = atmel_lcdfb_devtypes, | |
1147 | .driver = { | 1219 | .driver = { |
1148 | .name = "atmel_lcdfb", | 1220 | .name = "atmel_lcdfb", |
1149 | .owner = THIS_MODULE, | 1221 | .owner = THIS_MODULE, |
diff --git a/drivers/video/ep93xx-fb.c b/drivers/video/ep93xx-fb.c index 3f2519d30715..e06cd5d90c97 100644 --- a/drivers/video/ep93xx-fb.c +++ b/drivers/video/ep93xx-fb.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
25 | #include <linux/fb.h> | 25 | #include <linux/fb.h> |
26 | #include <linux/io.h> | ||
26 | 27 | ||
27 | #include <linux/platform_data/video-ep93xx.h> | 28 | #include <linux/platform_data/video-ep93xx.h> |
28 | 29 | ||
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index 755556ca5b2d..45169cbaba6e 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
@@ -169,6 +169,7 @@ struct mxsfb_info { | |||
169 | unsigned dotclk_delay; | 169 | unsigned dotclk_delay; |
170 | const struct mxsfb_devdata *devdata; | 170 | const struct mxsfb_devdata *devdata; |
171 | int mapped; | 171 | int mapped; |
172 | u32 sync; | ||
172 | }; | 173 | }; |
173 | 174 | ||
174 | #define mxsfb_is_v3(host) (host->devdata->ipversion == 3) | 175 | #define mxsfb_is_v3(host) (host->devdata->ipversion == 3) |
@@ -456,9 +457,9 @@ static int mxsfb_set_par(struct fb_info *fb_info) | |||
456 | vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH; | 457 | vdctrl0 |= VDCTRL0_HSYNC_ACT_HIGH; |
457 | if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT) | 458 | if (fb_info->var.sync & FB_SYNC_VERT_HIGH_ACT) |
458 | vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH; | 459 | vdctrl0 |= VDCTRL0_VSYNC_ACT_HIGH; |
459 | if (fb_info->var.sync & FB_SYNC_DATA_ENABLE_HIGH_ACT) | 460 | if (host->sync & MXSFB_SYNC_DATA_ENABLE_HIGH_ACT) |
460 | vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; | 461 | vdctrl0 |= VDCTRL0_ENABLE_ACT_HIGH; |
461 | if (fb_info->var.sync & FB_SYNC_DOTCLK_FAILING_ACT) | 462 | if (host->sync & MXSFB_SYNC_DOTCLK_FAILING_ACT) |
462 | vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING; | 463 | vdctrl0 |= VDCTRL0_DOTCLK_ACT_FAILING; |
463 | 464 | ||
464 | writel(vdctrl0, host->base + LCDC_VDCTRL0); | 465 | writel(vdctrl0, host->base + LCDC_VDCTRL0); |
@@ -861,6 +862,8 @@ static int mxsfb_probe(struct platform_device *pdev) | |||
861 | 862 | ||
862 | INIT_LIST_HEAD(&fb_info->modelist); | 863 | INIT_LIST_HEAD(&fb_info->modelist); |
863 | 864 | ||
865 | host->sync = pdata->sync; | ||
866 | |||
864 | ret = mxsfb_init_fbinfo(host); | 867 | ret = mxsfb_init_fbinfo(host); |
865 | if (ret != 0) | 868 | if (ret != 0) |
866 | goto error_init_fb; | 869 | goto error_init_fb; |
diff --git a/drivers/video/omap/lcd_ams_delta.c b/drivers/video/omap/lcd_ams_delta.c index ed4cad87fbcd..4a5f2cd3d3bf 100644 --- a/drivers/video/omap/lcd_ams_delta.c +++ b/drivers/video/omap/lcd_ams_delta.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/lcd.h> | 27 | #include <linux/lcd.h> |
28 | #include <linux/gpio.h> | 28 | #include <linux/gpio.h> |
29 | 29 | ||
30 | #include <mach/hardware.h> | ||
30 | #include <mach/board-ams-delta.h> | 31 | #include <mach/board-ams-delta.h> |
31 | 32 | ||
32 | #include "omapfb.h" | 33 | #include "omapfb.h" |
diff --git a/drivers/video/omap/lcd_osk.c b/drivers/video/omap/lcd_osk.c index 3aa62da89195..7fbe04bce0ed 100644 --- a/drivers/video/omap/lcd_osk.c +++ b/drivers/video/omap/lcd_osk.c | |||
@@ -24,7 +24,10 @@ | |||
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | 25 | ||
26 | #include <asm/gpio.h> | 26 | #include <asm/gpio.h> |
27 | |||
28 | #include <mach/hardware.h> | ||
27 | #include <mach/mux.h> | 29 | #include <mach/mux.h> |
30 | |||
28 | #include "omapfb.h" | 31 | #include "omapfb.h" |
29 | 32 | ||
30 | static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) | 33 | static int osk_panel_init(struct lcd_panel *panel, struct omapfb_device *fbdev) |
diff --git a/drivers/video/omap/omapfb_main.c b/drivers/video/omap/omapfb_main.c index e31f5b33b501..d40612c31a98 100644 --- a/drivers/video/omap/omapfb_main.c +++ b/drivers/video/omap/omapfb_main.c | |||
@@ -32,6 +32,8 @@ | |||
32 | 32 | ||
33 | #include <linux/omap-dma.h> | 33 | #include <linux/omap-dma.h> |
34 | 34 | ||
35 | #include <mach/hardware.h> | ||
36 | |||
35 | #include "omapfb.h" | 37 | #include "omapfb.h" |
36 | #include "lcdc.h" | 38 | #include "lcdc.h" |
37 | 39 | ||
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index 6b6643911d29..048c98381ef6 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c | |||
@@ -63,6 +63,9 @@ struct tpo_td043_device { | |||
63 | u32 power_on_resume:1; | 63 | u32 power_on_resume:1; |
64 | }; | 64 | }; |
65 | 65 | ||
66 | /* used to pass spi_device from SPI to DSS portion of the driver */ | ||
67 | static struct tpo_td043_device *g_tpo_td043; | ||
68 | |||
66 | static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data) | 69 | static int tpo_td043_write(struct spi_device *spi, u8 addr, u8 data) |
67 | { | 70 | { |
68 | struct spi_message m; | 71 | struct spi_message m; |
@@ -403,7 +406,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev) | |||
403 | 406 | ||
404 | static int tpo_td043_probe(struct omap_dss_device *dssdev) | 407 | static int tpo_td043_probe(struct omap_dss_device *dssdev) |
405 | { | 408 | { |
406 | struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); | 409 | struct tpo_td043_device *tpo_td043 = g_tpo_td043; |
407 | int nreset_gpio = dssdev->reset_gpio; | 410 | int nreset_gpio = dssdev->reset_gpio; |
408 | int ret = 0; | 411 | int ret = 0; |
409 | 412 | ||
@@ -440,6 +443,8 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev) | |||
440 | if (ret) | 443 | if (ret) |
441 | dev_warn(&dssdev->dev, "failed to create sysfs files\n"); | 444 | dev_warn(&dssdev->dev, "failed to create sysfs files\n"); |
442 | 445 | ||
446 | dev_set_drvdata(&dssdev->dev, tpo_td043); | ||
447 | |||
443 | return 0; | 448 | return 0; |
444 | 449 | ||
445 | fail_gpio_req: | 450 | fail_gpio_req: |
@@ -505,6 +510,9 @@ static int tpo_td043_spi_probe(struct spi_device *spi) | |||
505 | return -ENODEV; | 510 | return -ENODEV; |
506 | } | 511 | } |
507 | 512 | ||
513 | if (g_tpo_td043 != NULL) | ||
514 | return -EBUSY; | ||
515 | |||
508 | spi->bits_per_word = 16; | 516 | spi->bits_per_word = 16; |
509 | spi->mode = SPI_MODE_0; | 517 | spi->mode = SPI_MODE_0; |
510 | 518 | ||
@@ -521,7 +529,7 @@ static int tpo_td043_spi_probe(struct spi_device *spi) | |||
521 | tpo_td043->spi = spi; | 529 | tpo_td043->spi = spi; |
522 | tpo_td043->nreset_gpio = dssdev->reset_gpio; | 530 | tpo_td043->nreset_gpio = dssdev->reset_gpio; |
523 | dev_set_drvdata(&spi->dev, tpo_td043); | 531 | dev_set_drvdata(&spi->dev, tpo_td043); |
524 | dev_set_drvdata(&dssdev->dev, tpo_td043); | 532 | g_tpo_td043 = tpo_td043; |
525 | 533 | ||
526 | omap_dss_register_driver(&tpo_td043_driver); | 534 | omap_dss_register_driver(&tpo_td043_driver); |
527 | 535 | ||
@@ -534,6 +542,7 @@ static int tpo_td043_spi_remove(struct spi_device *spi) | |||
534 | 542 | ||
535 | omap_dss_unregister_driver(&tpo_td043_driver); | 543 | omap_dss_unregister_driver(&tpo_td043_driver); |
536 | kfree(tpo_td043); | 544 | kfree(tpo_td043); |
545 | g_tpo_td043 = NULL; | ||
537 | 546 | ||
538 | return 0; | 547 | return 0; |
539 | } | 548 | } |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index d7d66ef5cb58..7f791aeda4d2 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -202,12 +202,10 @@ static const enum omap_dss_output_id omap3630_dss_supported_outputs[] = { | |||
202 | 202 | ||
203 | static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { | 203 | static const enum omap_dss_output_id omap4_dss_supported_outputs[] = { |
204 | /* OMAP_DSS_CHANNEL_LCD */ | 204 | /* OMAP_DSS_CHANNEL_LCD */ |
205 | OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | | 205 | OMAP_DSS_OUTPUT_DBI | OMAP_DSS_OUTPUT_DSI1, |
206 | OMAP_DSS_OUTPUT_DSI1, | ||
207 | 206 | ||
208 | /* OMAP_DSS_CHANNEL_DIGIT */ | 207 | /* OMAP_DSS_CHANNEL_DIGIT */ |
209 | OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI | | 208 | OMAP_DSS_OUTPUT_VENC | OMAP_DSS_OUTPUT_HDMI, |
210 | OMAP_DSS_OUTPUT_DPI, | ||
211 | 209 | ||
212 | /* OMAP_DSS_CHANNEL_LCD2 */ | 210 | /* OMAP_DSS_CHANNEL_LCD2 */ |
213 | OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | | 211 | OMAP_DSS_OUTPUT_DPI | OMAP_DSS_OUTPUT_DBI | |
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c index d39dfa4cc235..46d97014342e 100644 --- a/drivers/w1/masters/w1-gpio.c +++ b/drivers/w1/masters/w1-gpio.c | |||
@@ -47,11 +47,13 @@ static u8 w1_gpio_read_bit(void *data) | |||
47 | return gpio_get_value(pdata->pin) ? 1 : 0; | 47 | return gpio_get_value(pdata->pin) ? 1 : 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | #if defined(CONFIG_OF) | ||
50 | static struct of_device_id w1_gpio_dt_ids[] = { | 51 | static struct of_device_id w1_gpio_dt_ids[] = { |
51 | { .compatible = "w1-gpio" }, | 52 | { .compatible = "w1-gpio" }, |
52 | {} | 53 | {} |
53 | }; | 54 | }; |
54 | MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); | 55 | MODULE_DEVICE_TABLE(of, w1_gpio_dt_ids); |
56 | #endif | ||
55 | 57 | ||
56 | static int w1_gpio_probe_dt(struct platform_device *pdev) | 58 | static int w1_gpio_probe_dt(struct platform_device *pdev) |
57 | { | 59 | { |
@@ -158,7 +160,7 @@ static int w1_gpio_probe(struct platform_device *pdev) | |||
158 | return err; | 160 | return err; |
159 | } | 161 | } |
160 | 162 | ||
161 | static int __exit w1_gpio_remove(struct platform_device *pdev) | 163 | static int w1_gpio_remove(struct platform_device *pdev) |
162 | { | 164 | { |
163 | struct w1_bus_master *master = platform_get_drvdata(pdev); | 165 | struct w1_bus_master *master = platform_get_drvdata(pdev); |
164 | struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; | 166 | struct w1_gpio_platform_data *pdata = pdev->dev.platform_data; |
@@ -210,7 +212,7 @@ static struct platform_driver w1_gpio_driver = { | |||
210 | .of_match_table = of_match_ptr(w1_gpio_dt_ids), | 212 | .of_match_table = of_match_ptr(w1_gpio_dt_ids), |
211 | }, | 213 | }, |
212 | .probe = w1_gpio_probe, | 214 | .probe = w1_gpio_probe, |
213 | .remove = __exit_p(w1_gpio_remove), | 215 | .remove = w1_gpio_remove, |
214 | .suspend = w1_gpio_suspend, | 216 | .suspend = w1_gpio_suspend, |
215 | .resume = w1_gpio_resume, | 217 | .resume = w1_gpio_resume, |
216 | }; | 218 | }; |
diff --git a/drivers/w1/w1.c b/drivers/w1/w1.c index 7994d933f040..7ce277d2bb67 100644 --- a/drivers/w1/w1.c +++ b/drivers/w1/w1.c | |||
@@ -924,7 +924,8 @@ void w1_search(struct w1_master *dev, u8 search_type, w1_slave_found_callback cb | |||
924 | tmp64 = (triplet_ret >> 2); | 924 | tmp64 = (triplet_ret >> 2); |
925 | rn |= (tmp64 << i); | 925 | rn |= (tmp64 << i); |
926 | 926 | ||
927 | if (kthread_should_stop()) { | 927 | /* ensure we're called from kthread and not by netlink callback */ |
928 | if (!dev->priv && kthread_should_stop()) { | ||
928 | mutex_unlock(&dev->bus_mutex); | 929 | mutex_unlock(&dev->bus_mutex); |
929 | dev_dbg(&dev->dev, "Abort w1_search\n"); | 930 | dev_dbg(&dev->dev, "Abort w1_search\n"); |
930 | return; | 931 | return; |
diff --git a/drivers/watchdog/sp5100_tco.c b/drivers/watchdog/sp5100_tco.c index e3b8f757d2d3..0e9d8c479c35 100644 --- a/drivers/watchdog/sp5100_tco.c +++ b/drivers/watchdog/sp5100_tco.c | |||
@@ -40,13 +40,12 @@ | |||
40 | #include "sp5100_tco.h" | 40 | #include "sp5100_tco.h" |
41 | 41 | ||
42 | /* Module and version information */ | 42 | /* Module and version information */ |
43 | #define TCO_VERSION "0.03" | 43 | #define TCO_VERSION "0.05" |
44 | #define TCO_MODULE_NAME "SP5100 TCO timer" | 44 | #define TCO_MODULE_NAME "SP5100 TCO timer" |
45 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION | 45 | #define TCO_DRIVER_NAME TCO_MODULE_NAME ", v" TCO_VERSION |
46 | 46 | ||
47 | /* internal variables */ | 47 | /* internal variables */ |
48 | static u32 tcobase_phys; | 48 | static u32 tcobase_phys; |
49 | static u32 resbase_phys; | ||
50 | static u32 tco_wdt_fired; | 49 | static u32 tco_wdt_fired; |
51 | static void __iomem *tcobase; | 50 | static void __iomem *tcobase; |
52 | static unsigned int pm_iobase; | 51 | static unsigned int pm_iobase; |
@@ -54,10 +53,6 @@ static DEFINE_SPINLOCK(tco_lock); /* Guards the hardware */ | |||
54 | static unsigned long timer_alive; | 53 | static unsigned long timer_alive; |
55 | static char tco_expect_close; | 54 | static char tco_expect_close; |
56 | static struct pci_dev *sp5100_tco_pci; | 55 | static struct pci_dev *sp5100_tco_pci; |
57 | static struct resource wdt_res = { | ||
58 | .name = "Watchdog Timer", | ||
59 | .flags = IORESOURCE_MEM, | ||
60 | }; | ||
61 | 56 | ||
62 | /* the watchdog platform device */ | 57 | /* the watchdog platform device */ |
63 | static struct platform_device *sp5100_tco_platform_device; | 58 | static struct platform_device *sp5100_tco_platform_device; |
@@ -75,12 +70,6 @@ module_param(nowayout, bool, 0); | |||
75 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started." | 70 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started." |
76 | " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 71 | " (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
77 | 72 | ||
78 | static unsigned int force_addr; | ||
79 | module_param(force_addr, uint, 0); | ||
80 | MODULE_PARM_DESC(force_addr, "Force the use of specified MMIO address." | ||
81 | " ONLY USE THIS PARAMETER IF YOU REALLY KNOW" | ||
82 | " WHAT YOU ARE DOING (default=none)"); | ||
83 | |||
84 | /* | 73 | /* |
85 | * Some TCO specific functions | 74 | * Some TCO specific functions |
86 | */ | 75 | */ |
@@ -176,39 +165,6 @@ static void tco_timer_enable(void) | |||
176 | } | 165 | } |
177 | } | 166 | } |
178 | 167 | ||
179 | static void tco_timer_disable(void) | ||
180 | { | ||
181 | int val; | ||
182 | |||
183 | if (sp5100_tco_pci->revision >= 0x40) { | ||
184 | /* For SB800 or later */ | ||
185 | /* Enable watchdog decode bit and Disable watchdog timer */ | ||
186 | outb(SB800_PM_WATCHDOG_CONTROL, SB800_IO_PM_INDEX_REG); | ||
187 | val = inb(SB800_IO_PM_DATA_REG); | ||
188 | val |= SB800_PCI_WATCHDOG_DECODE_EN; | ||
189 | val |= SB800_PM_WATCHDOG_DISABLE; | ||
190 | outb(val, SB800_IO_PM_DATA_REG); | ||
191 | } else { | ||
192 | /* For SP5100 or SB7x0 */ | ||
193 | /* Enable watchdog decode bit */ | ||
194 | pci_read_config_dword(sp5100_tco_pci, | ||
195 | SP5100_PCI_WATCHDOG_MISC_REG, | ||
196 | &val); | ||
197 | |||
198 | val |= SP5100_PCI_WATCHDOG_DECODE_EN; | ||
199 | |||
200 | pci_write_config_dword(sp5100_tco_pci, | ||
201 | SP5100_PCI_WATCHDOG_MISC_REG, | ||
202 | val); | ||
203 | |||
204 | /* Disable Watchdog timer */ | ||
205 | outb(SP5100_PM_WATCHDOG_CONTROL, SP5100_IO_PM_INDEX_REG); | ||
206 | val = inb(SP5100_IO_PM_DATA_REG); | ||
207 | val |= SP5100_PM_WATCHDOG_DISABLE; | ||
208 | outb(val, SP5100_IO_PM_DATA_REG); | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /* | 168 | /* |
213 | * /dev/watchdog handling | 169 | * /dev/watchdog handling |
214 | */ | 170 | */ |
@@ -361,7 +317,7 @@ static unsigned char sp5100_tco_setupdevice(void) | |||
361 | { | 317 | { |
362 | struct pci_dev *dev = NULL; | 318 | struct pci_dev *dev = NULL; |
363 | const char *dev_name = NULL; | 319 | const char *dev_name = NULL; |
364 | u32 val, tmp_val; | 320 | u32 val; |
365 | u32 index_reg, data_reg, base_addr; | 321 | u32 index_reg, data_reg, base_addr; |
366 | 322 | ||
367 | /* Match the PCI device */ | 323 | /* Match the PCI device */ |
@@ -459,63 +415,8 @@ static unsigned char sp5100_tco_setupdevice(void) | |||
459 | } else | 415 | } else |
460 | pr_debug("SBResource_MMIO is disabled(0x%04x)\n", val); | 416 | pr_debug("SBResource_MMIO is disabled(0x%04x)\n", val); |
461 | 417 | ||
462 | /* | 418 | pr_notice("failed to find MMIO address, giving up.\n"); |
463 | * Lastly re-programming the watchdog timer MMIO address, | 419 | goto unreg_region; |
464 | * This method is a last resort... | ||
465 | * | ||
466 | * Before re-programming, to ensure that the watchdog timer | ||
467 | * is disabled, disable the watchdog timer. | ||
468 | */ | ||
469 | tco_timer_disable(); | ||
470 | |||
471 | if (force_addr) { | ||
472 | /* | ||
473 | * Force the use of watchdog timer MMIO address, and aligned to | ||
474 | * 8byte boundary. | ||
475 | */ | ||
476 | force_addr &= ~0x7; | ||
477 | val = force_addr; | ||
478 | |||
479 | pr_info("Force the use of 0x%04x as MMIO address\n", val); | ||
480 | } else { | ||
481 | /* | ||
482 | * Get empty slot into the resource tree for watchdog timer. | ||
483 | */ | ||
484 | if (allocate_resource(&iomem_resource, | ||
485 | &wdt_res, | ||
486 | SP5100_WDT_MEM_MAP_SIZE, | ||
487 | 0xf0000000, | ||
488 | 0xfffffff8, | ||
489 | 0x8, | ||
490 | NULL, | ||
491 | NULL)) { | ||
492 | pr_err("MMIO allocation failed\n"); | ||
493 | goto unreg_region; | ||
494 | } | ||
495 | |||
496 | val = resbase_phys = wdt_res.start; | ||
497 | pr_debug("Got 0x%04x from resource tree\n", val); | ||
498 | } | ||
499 | |||
500 | /* Restore to the low three bits */ | ||
501 | outb(base_addr+0, index_reg); | ||
502 | tmp_val = val | (inb(data_reg) & 0x7); | ||
503 | |||
504 | /* Re-programming the watchdog timer base address */ | ||
505 | outb(base_addr+0, index_reg); | ||
506 | outb((tmp_val >> 0) & 0xff, data_reg); | ||
507 | outb(base_addr+1, index_reg); | ||
508 | outb((tmp_val >> 8) & 0xff, data_reg); | ||
509 | outb(base_addr+2, index_reg); | ||
510 | outb((tmp_val >> 16) & 0xff, data_reg); | ||
511 | outb(base_addr+3, index_reg); | ||
512 | outb((tmp_val >> 24) & 0xff, data_reg); | ||
513 | |||
514 | if (!request_mem_region_exclusive(val, SP5100_WDT_MEM_MAP_SIZE, | ||
515 | dev_name)) { | ||
516 | pr_err("MMIO address 0x%04x already in use\n", val); | ||
517 | goto unreg_resource; | ||
518 | } | ||
519 | 420 | ||
520 | setup_wdt: | 421 | setup_wdt: |
521 | tcobase_phys = val; | 422 | tcobase_phys = val; |
@@ -555,9 +456,6 @@ setup_wdt: | |||
555 | 456 | ||
556 | unreg_mem_region: | 457 | unreg_mem_region: |
557 | release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); | 458 | release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); |
558 | unreg_resource: | ||
559 | if (resbase_phys) | ||
560 | release_resource(&wdt_res); | ||
561 | unreg_region: | 459 | unreg_region: |
562 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); | 460 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); |
563 | exit: | 461 | exit: |
@@ -567,7 +465,6 @@ exit: | |||
567 | static int sp5100_tco_init(struct platform_device *dev) | 465 | static int sp5100_tco_init(struct platform_device *dev) |
568 | { | 466 | { |
569 | int ret; | 467 | int ret; |
570 | char addr_str[16]; | ||
571 | 468 | ||
572 | /* | 469 | /* |
573 | * Check whether or not the hardware watchdog is there. If found, then | 470 | * Check whether or not the hardware watchdog is there. If found, then |
@@ -599,23 +496,14 @@ static int sp5100_tco_init(struct platform_device *dev) | |||
599 | clear_bit(0, &timer_alive); | 496 | clear_bit(0, &timer_alive); |
600 | 497 | ||
601 | /* Show module parameters */ | 498 | /* Show module parameters */ |
602 | if (force_addr == tcobase_phys) | 499 | pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", |
603 | /* The force_addr is vaild */ | 500 | tcobase, heartbeat, nowayout); |
604 | sprintf(addr_str, "0x%04x", force_addr); | ||
605 | else | ||
606 | strcpy(addr_str, "none"); | ||
607 | |||
608 | pr_info("initialized (0x%p). heartbeat=%d sec (nowayout=%d, " | ||
609 | "force_addr=%s)\n", | ||
610 | tcobase, heartbeat, nowayout, addr_str); | ||
611 | 501 | ||
612 | return 0; | 502 | return 0; |
613 | 503 | ||
614 | exit: | 504 | exit: |
615 | iounmap(tcobase); | 505 | iounmap(tcobase); |
616 | release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); | 506 | release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); |
617 | if (resbase_phys) | ||
618 | release_resource(&wdt_res); | ||
619 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); | 507 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); |
620 | return ret; | 508 | return ret; |
621 | } | 509 | } |
@@ -630,8 +518,6 @@ static void sp5100_tco_cleanup(void) | |||
630 | misc_deregister(&sp5100_tco_miscdev); | 518 | misc_deregister(&sp5100_tco_miscdev); |
631 | iounmap(tcobase); | 519 | iounmap(tcobase); |
632 | release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); | 520 | release_mem_region(tcobase_phys, SP5100_WDT_MEM_MAP_SIZE); |
633 | if (resbase_phys) | ||
634 | release_resource(&wdt_res); | ||
635 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); | 521 | release_region(pm_iobase, SP5100_PM_IOPORTS_SIZE); |
636 | } | 522 | } |
637 | 523 | ||
diff --git a/drivers/watchdog/sp5100_tco.h b/drivers/watchdog/sp5100_tco.h index 71594a0c14b7..2b28c00da0df 100644 --- a/drivers/watchdog/sp5100_tco.h +++ b/drivers/watchdog/sp5100_tco.h | |||
@@ -57,7 +57,7 @@ | |||
57 | #define SB800_PM_WATCHDOG_DISABLE (1 << 2) | 57 | #define SB800_PM_WATCHDOG_DISABLE (1 << 2) |
58 | #define SB800_PM_WATCHDOG_SECOND_RES (3 << 0) | 58 | #define SB800_PM_WATCHDOG_SECOND_RES (3 << 0) |
59 | #define SB800_ACPI_MMIO_DECODE_EN (1 << 0) | 59 | #define SB800_ACPI_MMIO_DECODE_EN (1 << 0) |
60 | #define SB800_ACPI_MMIO_SEL (1 << 2) | 60 | #define SB800_ACPI_MMIO_SEL (1 << 1) |
61 | 61 | ||
62 | 62 | ||
63 | #define SB800_PM_WDT_MMIO_OFFSET 0xB00 | 63 | #define SB800_PM_WDT_MMIO_OFFSET 0xB00 |
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 5a32232cf7c1..67af155cf602 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
@@ -182,7 +182,7 @@ config XEN_PRIVCMD | |||
182 | 182 | ||
183 | config XEN_STUB | 183 | config XEN_STUB |
184 | bool "Xen stub drivers" | 184 | bool "Xen stub drivers" |
185 | depends on XEN && X86_64 | 185 | depends on XEN && X86_64 && BROKEN |
186 | default n | 186 | default n |
187 | help | 187 | help |
188 | Allow kernel to install stub drivers, to reserve space for Xen drivers, | 188 | Allow kernel to install stub drivers, to reserve space for Xen drivers, |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index d17aa41a9041..aa85881d17b2 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -403,11 +403,23 @@ static void unmask_evtchn(int port) | |||
403 | 403 | ||
404 | if (unlikely((cpu != cpu_from_evtchn(port)))) | 404 | if (unlikely((cpu != cpu_from_evtchn(port)))) |
405 | do_hypercall = 1; | 405 | do_hypercall = 1; |
406 | else | 406 | else { |
407 | /* | ||
408 | * Need to clear the mask before checking pending to | ||
409 | * avoid a race with an event becoming pending. | ||
410 | * | ||
411 | * EVTCHNOP_unmask will only trigger an upcall if the | ||
412 | * mask bit was set, so if a hypercall is needed | ||
413 | * remask the event. | ||
414 | */ | ||
415 | sync_clear_bit(port, BM(&s->evtchn_mask[0])); | ||
407 | evtchn_pending = sync_test_bit(port, BM(&s->evtchn_pending[0])); | 416 | evtchn_pending = sync_test_bit(port, BM(&s->evtchn_pending[0])); |
408 | 417 | ||
409 | if (unlikely(evtchn_pending && xen_hvm_domain())) | 418 | if (unlikely(evtchn_pending && xen_hvm_domain())) { |
410 | do_hypercall = 1; | 419 | sync_set_bit(port, BM(&s->evtchn_mask[0])); |
420 | do_hypercall = 1; | ||
421 | } | ||
422 | } | ||
411 | 423 | ||
412 | /* Slow path (hypercall) if this is a non-local port or if this is | 424 | /* Slow path (hypercall) if this is a non-local port or if this is |
413 | * an hvm domain and an event is pending (hvm domains don't have | 425 | * an hvm domain and an event is pending (hvm domains don't have |
@@ -418,8 +430,6 @@ static void unmask_evtchn(int port) | |||
418 | } else { | 430 | } else { |
419 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); | 431 | struct vcpu_info *vcpu_info = __this_cpu_read(xen_vcpu); |
420 | 432 | ||
421 | sync_clear_bit(port, BM(&s->evtchn_mask[0])); | ||
422 | |||
423 | /* | 433 | /* |
424 | * The following is basically the equivalent of | 434 | * The following is basically the equivalent of |
425 | * 'hw_resend_irq'. Just like a real IO-APIC we 'lose | 435 | * 'hw_resend_irq'. Just like a real IO-APIC we 'lose |
diff --git a/drivers/xen/fallback.c b/drivers/xen/fallback.c index 0ef7c4d40f86..b04fb64c5a91 100644 --- a/drivers/xen/fallback.c +++ b/drivers/xen/fallback.c | |||
@@ -44,7 +44,7 @@ int xen_event_channel_op_compat(int cmd, void *arg) | |||
44 | } | 44 | } |
45 | EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); | 45 | EXPORT_SYMBOL_GPL(xen_event_channel_op_compat); |
46 | 46 | ||
47 | int HYPERVISOR_physdev_op_compat(int cmd, void *arg) | 47 | int xen_physdev_op_compat(int cmd, void *arg) |
48 | { | 48 | { |
49 | struct physdev_op op; | 49 | struct physdev_op op; |
50 | int rc; | 50 | int rc; |
@@ -78,3 +78,4 @@ int HYPERVISOR_physdev_op_compat(int cmd, void *arg) | |||
78 | 78 | ||
79 | return rc; | 79 | return rc; |
80 | } | 80 | } |
81 | EXPORT_SYMBOL_GPL(xen_physdev_op_compat); | ||
diff --git a/drivers/xen/xen-acpi-processor.c b/drivers/xen/xen-acpi-processor.c index 316df65163cf..90e34ac7e522 100644 --- a/drivers/xen/xen-acpi-processor.c +++ b/drivers/xen/xen-acpi-processor.c | |||
@@ -500,16 +500,19 @@ static int __init xen_acpi_processor_init(void) | |||
500 | (void)acpi_processor_preregister_performance(acpi_perf_data); | 500 | (void)acpi_processor_preregister_performance(acpi_perf_data); |
501 | 501 | ||
502 | for_each_possible_cpu(i) { | 502 | for_each_possible_cpu(i) { |
503 | struct acpi_processor *pr; | ||
503 | struct acpi_processor_performance *perf; | 504 | struct acpi_processor_performance *perf; |
504 | 505 | ||
506 | pr = per_cpu(processors, i); | ||
505 | perf = per_cpu_ptr(acpi_perf_data, i); | 507 | perf = per_cpu_ptr(acpi_perf_data, i); |
506 | rc = acpi_processor_register_performance(perf, i); | 508 | if (!pr) |
509 | continue; | ||
510 | |||
511 | pr->performance = perf; | ||
512 | rc = acpi_processor_get_performance_info(pr); | ||
507 | if (rc) | 513 | if (rc) |
508 | goto err_out; | 514 | goto err_out; |
509 | } | 515 | } |
510 | rc = acpi_processor_notify_smm(THIS_MODULE); | ||
511 | if (rc) | ||
512 | goto err_unregister; | ||
513 | 516 | ||
514 | for_each_possible_cpu(i) { | 517 | for_each_possible_cpu(i) { |
515 | struct acpi_processor *_pr; | 518 | struct acpi_processor *_pr; |
diff --git a/drivers/xen/xen-pciback/pci_stub.c b/drivers/xen/xen-pciback/pci_stub.c index 9204126f1560..a2278ba7fb27 100644 --- a/drivers/xen/xen-pciback/pci_stub.c +++ b/drivers/xen/xen-pciback/pci_stub.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <xen/events.h> | 17 | #include <xen/events.h> |
18 | #include <asm/xen/pci.h> | 18 | #include <asm/xen/pci.h> |
19 | #include <asm/xen/hypervisor.h> | 19 | #include <asm/xen/hypervisor.h> |
20 | #include <xen/interface/physdev.h> | ||
20 | #include "pciback.h" | 21 | #include "pciback.h" |
21 | #include "conf_space.h" | 22 | #include "conf_space.h" |
22 | #include "conf_space_quirks.h" | 23 | #include "conf_space_quirks.h" |
@@ -85,37 +86,52 @@ static struct pcistub_device *pcistub_device_alloc(struct pci_dev *dev) | |||
85 | static void pcistub_device_release(struct kref *kref) | 86 | static void pcistub_device_release(struct kref *kref) |
86 | { | 87 | { |
87 | struct pcistub_device *psdev; | 88 | struct pcistub_device *psdev; |
89 | struct pci_dev *dev; | ||
88 | struct xen_pcibk_dev_data *dev_data; | 90 | struct xen_pcibk_dev_data *dev_data; |
89 | 91 | ||
90 | psdev = container_of(kref, struct pcistub_device, kref); | 92 | psdev = container_of(kref, struct pcistub_device, kref); |
91 | dev_data = pci_get_drvdata(psdev->dev); | 93 | dev = psdev->dev; |
94 | dev_data = pci_get_drvdata(dev); | ||
92 | 95 | ||
93 | dev_dbg(&psdev->dev->dev, "pcistub_device_release\n"); | 96 | dev_dbg(&dev->dev, "pcistub_device_release\n"); |
94 | 97 | ||
95 | xen_unregister_device_domain_owner(psdev->dev); | 98 | xen_unregister_device_domain_owner(dev); |
96 | 99 | ||
97 | /* Call the reset function which does not take lock as this | 100 | /* Call the reset function which does not take lock as this |
98 | * is called from "unbind" which takes a device_lock mutex. | 101 | * is called from "unbind" which takes a device_lock mutex. |
99 | */ | 102 | */ |
100 | __pci_reset_function_locked(psdev->dev); | 103 | __pci_reset_function_locked(dev); |
101 | if (pci_load_and_free_saved_state(psdev->dev, | 104 | if (pci_load_and_free_saved_state(dev, &dev_data->pci_saved_state)) |
102 | &dev_data->pci_saved_state)) { | 105 | dev_dbg(&dev->dev, "Could not reload PCI state\n"); |
103 | dev_dbg(&psdev->dev->dev, "Could not reload PCI state\n"); | 106 | else |
104 | } else | 107 | pci_restore_state(dev); |
105 | pci_restore_state(psdev->dev); | 108 | |
109 | if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { | ||
110 | struct physdev_pci_device ppdev = { | ||
111 | .seg = pci_domain_nr(dev->bus), | ||
112 | .bus = dev->bus->number, | ||
113 | .devfn = dev->devfn | ||
114 | }; | ||
115 | int err = HYPERVISOR_physdev_op(PHYSDEVOP_release_msix, | ||
116 | &ppdev); | ||
117 | |||
118 | if (err) | ||
119 | dev_warn(&dev->dev, "MSI-X release failed (%d)\n", | ||
120 | err); | ||
121 | } | ||
106 | 122 | ||
107 | /* Disable the device */ | 123 | /* Disable the device */ |
108 | xen_pcibk_reset_device(psdev->dev); | 124 | xen_pcibk_reset_device(dev); |
109 | 125 | ||
110 | kfree(dev_data); | 126 | kfree(dev_data); |
111 | pci_set_drvdata(psdev->dev, NULL); | 127 | pci_set_drvdata(dev, NULL); |
112 | 128 | ||
113 | /* Clean-up the device */ | 129 | /* Clean-up the device */ |
114 | xen_pcibk_config_free_dyn_fields(psdev->dev); | 130 | xen_pcibk_config_free_dyn_fields(dev); |
115 | xen_pcibk_config_free_dev(psdev->dev); | 131 | xen_pcibk_config_free_dev(dev); |
116 | 132 | ||
117 | psdev->dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; | 133 | dev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED; |
118 | pci_dev_put(psdev->dev); | 134 | pci_dev_put(dev); |
119 | 135 | ||
120 | kfree(psdev); | 136 | kfree(psdev); |
121 | } | 137 | } |
@@ -355,6 +371,19 @@ static int pcistub_init_device(struct pci_dev *dev) | |||
355 | if (err) | 371 | if (err) |
356 | goto config_release; | 372 | goto config_release; |
357 | 373 | ||
374 | if (pci_find_capability(dev, PCI_CAP_ID_MSIX)) { | ||
375 | struct physdev_pci_device ppdev = { | ||
376 | .seg = pci_domain_nr(dev->bus), | ||
377 | .bus = dev->bus->number, | ||
378 | .devfn = dev->devfn | ||
379 | }; | ||
380 | |||
381 | err = HYPERVISOR_physdev_op(PHYSDEVOP_prepare_msix, &ppdev); | ||
382 | if (err) | ||
383 | dev_err(&dev->dev, "MSI-X preparation failed (%d)\n", | ||
384 | err); | ||
385 | } | ||
386 | |||
358 | /* We need the device active to save the state. */ | 387 | /* We need the device active to save the state. */ |
359 | dev_dbg(&dev->dev, "save state of device\n"); | 388 | dev_dbg(&dev->dev, "save state of device\n"); |
360 | pci_save_state(dev); | 389 | pci_save_state(dev); |
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 37c1f825f513..b98cf0c35725 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c | |||
@@ -113,7 +113,8 @@ void xen_pcibk_reset_device(struct pci_dev *dev) | |||
113 | if (dev->msi_enabled) | 113 | if (dev->msi_enabled) |
114 | pci_disable_msi(dev); | 114 | pci_disable_msi(dev); |
115 | #endif | 115 | #endif |
116 | pci_disable_device(dev); | 116 | if (pci_is_enabled(dev)) |
117 | pci_disable_device(dev); | ||
117 | 118 | ||
118 | pci_write_config_word(dev, PCI_COMMAND, 0); | 119 | pci_write_config_word(dev, PCI_COMMAND, 0); |
119 | 120 | ||
diff --git a/drivers/xen/xen-stub.c b/drivers/xen/xen-stub.c index d85e411cbf89..bbef194c5b01 100644 --- a/drivers/xen/xen-stub.c +++ b/drivers/xen/xen-stub.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include <linux/export.h> | 25 | #include <linux/export.h> |
26 | #include <linux/types.h> | 26 | #include <linux/types.h> |
27 | #include <linux/acpi.h> | 27 | #include <linux/acpi.h> |
28 | #include <acpi/acpi_drivers.h> | ||
29 | #include <xen/acpi.h> | 28 | #include <xen/acpi.h> |
30 | 29 | ||
31 | #ifdef CONFIG_ACPI | 30 | #ifdef CONFIG_ACPI |
diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c index ec0abb6df3c3..71679875f056 100644 --- a/drivers/xen/xenfs/super.c +++ b/drivers/xen/xenfs/super.c | |||
@@ -75,6 +75,7 @@ static struct file_system_type xenfs_type = { | |||
75 | .mount = xenfs_mount, | 75 | .mount = xenfs_mount, |
76 | .kill_sb = kill_litter_super, | 76 | .kill_sb = kill_litter_super, |
77 | }; | 77 | }; |
78 | MODULE_ALIAS_FS("xenfs"); | ||
78 | 79 | ||
79 | static int __init xenfs_init(void) | 80 | static int __init xenfs_init(void) |
80 | { | 81 | { |