diff options
Diffstat (limited to 'drivers')
577 files changed, 14538 insertions, 4605 deletions
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c index 00a783661d0b..46f80e2c92f7 100644 --- a/drivers/acpi/apei/apei-base.c +++ b/drivers/acpi/apei/apei-base.c | |||
@@ -590,6 +590,9 @@ static int apei_check_gar(struct acpi_generic_address *reg, u64 *paddr, | |||
590 | if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && | 590 | if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 && |
591 | *access_bit_width < 32) | 591 | *access_bit_width < 32) |
592 | *access_bit_width = 32; | 592 | *access_bit_width = 32; |
593 | else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 && | ||
594 | *access_bit_width < 64) | ||
595 | *access_bit_width = 64; | ||
593 | 596 | ||
594 | if ((bit_width + bit_offset) > *access_bit_width) { | 597 | if ((bit_width + bit_offset) > *access_bit_width) { |
595 | pr_warning(FW_BUG APEI_PFX | 598 | pr_warning(FW_BUG APEI_PFX |
diff --git a/drivers/acpi/apei/cper.c b/drivers/acpi/apei/cper.c index e6defd86b424..1e5d8a40101e 100644 --- a/drivers/acpi/apei/cper.c +++ b/drivers/acpi/apei/cper.c | |||
@@ -29,6 +29,7 @@ | |||
29 | #include <linux/time.h> | 29 | #include <linux/time.h> |
30 | #include <linux/cper.h> | 30 | #include <linux/cper.h> |
31 | #include <linux/acpi.h> | 31 | #include <linux/acpi.h> |
32 | #include <linux/pci.h> | ||
32 | #include <linux/aer.h> | 33 | #include <linux/aer.h> |
33 | 34 | ||
34 | /* | 35 | /* |
@@ -249,6 +250,10 @@ static const char *cper_pcie_port_type_strs[] = { | |||
249 | static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, | 250 | static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, |
250 | const struct acpi_hest_generic_data *gdata) | 251 | const struct acpi_hest_generic_data *gdata) |
251 | { | 252 | { |
253 | #ifdef CONFIG_ACPI_APEI_PCIEAER | ||
254 | struct pci_dev *dev; | ||
255 | #endif | ||
256 | |||
252 | if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) | 257 | if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE) |
253 | printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, | 258 | printk("%s""port_type: %d, %s\n", pfx, pcie->port_type, |
254 | pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? | 259 | pcie->port_type < ARRAY_SIZE(cper_pcie_port_type_strs) ? |
@@ -281,10 +286,18 @@ static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie, | |||
281 | "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", | 286 | "%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n", |
282 | pfx, pcie->bridge.secondary_status, pcie->bridge.control); | 287 | pfx, pcie->bridge.secondary_status, pcie->bridge.control); |
283 | #ifdef CONFIG_ACPI_APEI_PCIEAER | 288 | #ifdef CONFIG_ACPI_APEI_PCIEAER |
284 | if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) { | 289 | dev = pci_get_domain_bus_and_slot(pcie->device_id.segment, |
285 | struct aer_capability_regs *aer_regs = (void *)pcie->aer_info; | 290 | pcie->device_id.bus, pcie->device_id.function); |
286 | cper_print_aer(pfx, gdata->error_severity, aer_regs); | 291 | if (!dev) { |
292 | pr_err("PCI AER Cannot get PCI device %04x:%02x:%02x.%d\n", | ||
293 | pcie->device_id.segment, pcie->device_id.bus, | ||
294 | pcie->device_id.slot, pcie->device_id.function); | ||
295 | return; | ||
287 | } | 296 | } |
297 | if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) | ||
298 | cper_print_aer(pfx, dev, gdata->error_severity, | ||
299 | (struct aer_capability_regs *) pcie->aer_info); | ||
300 | pci_dev_put(dev); | ||
288 | #endif | 301 | #endif |
289 | } | 302 | } |
290 | 303 | ||
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 95af6f674a6c..35da18113216 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -297,7 +297,7 @@ static int acpi_platform_notify(struct device *dev) | |||
297 | if (!ret) { | 297 | if (!ret) { |
298 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 298 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
299 | 299 | ||
300 | acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer); | 300 | acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer); |
301 | DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); | 301 | DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer); |
302 | kfree(buffer.pointer); | 302 | kfree(buffer.pointer); |
303 | } else | 303 | } else |
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index 3ff267861541..bd22f8667eed 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c | |||
@@ -250,7 +250,7 @@ acpi_physical_address __init acpi_os_get_root_pointer(void) | |||
250 | return acpi_rsdp; | 250 | return acpi_rsdp; |
251 | #endif | 251 | #endif |
252 | 252 | ||
253 | if (efi_enabled) { | 253 | if (efi_enabled(EFI_CONFIG_TABLES)) { |
254 | if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) | 254 | if (efi.acpi20 != EFI_INVALID_TABLE_ADDR) |
255 | return efi.acpi20; | 255 | return efi.acpi20; |
256 | else if (efi.acpi != EFI_INVALID_TABLE_ADDR) | 256 | else if (efi.acpi != EFI_INVALID_TABLE_ADDR) |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index f1a5da44591d..ed9a1cc690be 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
@@ -958,6 +958,9 @@ static int acpi_processor_setup_cpuidle_cx(struct acpi_processor *pr) | |||
958 | return -EINVAL; | 958 | return -EINVAL; |
959 | } | 959 | } |
960 | 960 | ||
961 | if (!dev) | ||
962 | return -EINVAL; | ||
963 | |||
961 | dev->cpu = pr->id; | 964 | dev->cpu = pr->id; |
962 | 965 | ||
963 | if (max_cstate == 0) | 966 | if (max_cstate == 0) |
@@ -1149,6 +1152,7 @@ int acpi_processor_cst_has_changed(struct acpi_processor *pr) | |||
1149 | } | 1152 | } |
1150 | 1153 | ||
1151 | /* Populate Updated C-state information */ | 1154 | /* Populate Updated C-state information */ |
1155 | acpi_processor_get_power_info(pr); | ||
1152 | acpi_processor_setup_cpuidle_states(pr); | 1156 | acpi_processor_setup_cpuidle_states(pr); |
1153 | 1157 | ||
1154 | /* Enable all cpuidle devices */ | 1158 | /* Enable all cpuidle devices */ |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index 836bfe069042..53e7ac9403a7 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
@@ -340,6 +340,13 @@ static void amd_fixup_frequency(struct acpi_processor_px *px, int i) | |||
340 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) | 340 | if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10) |
341 | || boot_cpu_data.x86 == 0x11) { | 341 | || boot_cpu_data.x86 == 0x11) { |
342 | rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); | 342 | rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi); |
343 | /* | ||
344 | * MSR C001_0064+: | ||
345 | * Bit 63: PstateEn. Read-write. If set, the P-state is valid. | ||
346 | */ | ||
347 | if (!(hi & BIT(31))) | ||
348 | return; | ||
349 | |||
343 | fid = lo & 0x3f; | 350 | fid = lo & 0x3f; |
344 | did = (lo >> 6) & 7; | 351 | did = (lo >> 6) & 7; |
345 | if (boot_cpu_data.x86 == 0x10) | 352 | if (boot_cpu_data.x86 == 0x10) |
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 7862d17976b7..495aeed26779 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
@@ -53,6 +53,7 @@ | |||
53 | 53 | ||
54 | enum { | 54 | enum { |
55 | AHCI_PCI_BAR_STA2X11 = 0, | 55 | AHCI_PCI_BAR_STA2X11 = 0, |
56 | AHCI_PCI_BAR_ENMOTUS = 2, | ||
56 | AHCI_PCI_BAR_STANDARD = 5, | 57 | AHCI_PCI_BAR_STANDARD = 5, |
57 | }; | 58 | }; |
58 | 59 | ||
@@ -410,6 +411,9 @@ static const struct pci_device_id ahci_pci_tbl[] = { | |||
410 | { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ | 411 | { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci }, /* ASM1061 */ |
411 | { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ | 412 | { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci }, /* ASM1062 */ |
412 | 413 | ||
414 | /* Enmotus */ | ||
415 | { PCI_DEVICE(0x1c44, 0x8000), board_ahci }, | ||
416 | |||
413 | /* Generic, PCI class code for AHCI */ | 417 | /* Generic, PCI class code for AHCI */ |
414 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, | 418 | { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, |
415 | PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, | 419 | PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci }, |
@@ -1057,6 +1061,86 @@ static inline void ahci_gtf_filter_workaround(struct ata_host *host) | |||
1057 | {} | 1061 | {} |
1058 | #endif | 1062 | #endif |
1059 | 1063 | ||
1064 | int ahci_init_interrupts(struct pci_dev *pdev, struct ahci_host_priv *hpriv) | ||
1065 | { | ||
1066 | int rc; | ||
1067 | unsigned int maxvec; | ||
1068 | |||
1069 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) { | ||
1070 | rc = pci_enable_msi_block_auto(pdev, &maxvec); | ||
1071 | if (rc > 0) { | ||
1072 | if ((rc == maxvec) || (rc == 1)) | ||
1073 | return rc; | ||
1074 | /* | ||
1075 | * Assume that advantage of multipe MSIs is negated, | ||
1076 | * so fallback to single MSI mode to save resources | ||
1077 | */ | ||
1078 | pci_disable_msi(pdev); | ||
1079 | if (!pci_enable_msi(pdev)) | ||
1080 | return 1; | ||
1081 | } | ||
1082 | } | ||
1083 | |||
1084 | pci_intx(pdev, 1); | ||
1085 | return 0; | ||
1086 | } | ||
1087 | |||
1088 | /** | ||
1089 | * ahci_host_activate - start AHCI host, request IRQs and register it | ||
1090 | * @host: target ATA host | ||
1091 | * @irq: base IRQ number to request | ||
1092 | * @n_msis: number of MSIs allocated for this host | ||
1093 | * @irq_handler: irq_handler used when requesting IRQs | ||
1094 | * @irq_flags: irq_flags used when requesting IRQs | ||
1095 | * | ||
1096 | * Similar to ata_host_activate, but requests IRQs according to AHCI-1.1 | ||
1097 | * when multiple MSIs were allocated. That is one MSI per port, starting | ||
1098 | * from @irq. | ||
1099 | * | ||
1100 | * LOCKING: | ||
1101 | * Inherited from calling layer (may sleep). | ||
1102 | * | ||
1103 | * RETURNS: | ||
1104 | * 0 on success, -errno otherwise. | ||
1105 | */ | ||
1106 | int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis) | ||
1107 | { | ||
1108 | int i, rc; | ||
1109 | |||
1110 | /* Sharing Last Message among several ports is not supported */ | ||
1111 | if (n_msis < host->n_ports) | ||
1112 | return -EINVAL; | ||
1113 | |||
1114 | rc = ata_host_start(host); | ||
1115 | if (rc) | ||
1116 | return rc; | ||
1117 | |||
1118 | for (i = 0; i < host->n_ports; i++) { | ||
1119 | rc = devm_request_threaded_irq(host->dev, | ||
1120 | irq + i, ahci_hw_interrupt, ahci_thread_fn, IRQF_SHARED, | ||
1121 | dev_driver_string(host->dev), host->ports[i]); | ||
1122 | if (rc) | ||
1123 | goto out_free_irqs; | ||
1124 | } | ||
1125 | |||
1126 | for (i = 0; i < host->n_ports; i++) | ||
1127 | ata_port_desc(host->ports[i], "irq %d", irq + i); | ||
1128 | |||
1129 | rc = ata_host_register(host, &ahci_sht); | ||
1130 | if (rc) | ||
1131 | goto out_free_all_irqs; | ||
1132 | |||
1133 | return 0; | ||
1134 | |||
1135 | out_free_all_irqs: | ||
1136 | i = host->n_ports; | ||
1137 | out_free_irqs: | ||
1138 | for (i--; i >= 0; i--) | ||
1139 | devm_free_irq(host->dev, irq + i, host->ports[i]); | ||
1140 | |||
1141 | return rc; | ||
1142 | } | ||
1143 | |||
1060 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 1144 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
1061 | { | 1145 | { |
1062 | unsigned int board_id = ent->driver_data; | 1146 | unsigned int board_id = ent->driver_data; |
@@ -1065,7 +1149,7 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1065 | struct device *dev = &pdev->dev; | 1149 | struct device *dev = &pdev->dev; |
1066 | struct ahci_host_priv *hpriv; | 1150 | struct ahci_host_priv *hpriv; |
1067 | struct ata_host *host; | 1151 | struct ata_host *host; |
1068 | int n_ports, i, rc; | 1152 | int n_ports, n_msis, i, rc; |
1069 | int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; | 1153 | int ahci_pci_bar = AHCI_PCI_BAR_STANDARD; |
1070 | 1154 | ||
1071 | VPRINTK("ENTER\n"); | 1155 | VPRINTK("ENTER\n"); |
@@ -1098,9 +1182,11 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1098 | dev_info(&pdev->dev, | 1182 | dev_info(&pdev->dev, |
1099 | "PDC42819 can only drive SATA devices with this driver\n"); | 1183 | "PDC42819 can only drive SATA devices with this driver\n"); |
1100 | 1184 | ||
1101 | /* The Connext uses non-standard BAR */ | 1185 | /* Both Connext and Enmotus devices use non-standard BARs */ |
1102 | if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) | 1186 | if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06) |
1103 | ahci_pci_bar = AHCI_PCI_BAR_STA2X11; | 1187 | ahci_pci_bar = AHCI_PCI_BAR_STA2X11; |
1188 | else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000) | ||
1189 | ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS; | ||
1104 | 1190 | ||
1105 | /* acquire resources */ | 1191 | /* acquire resources */ |
1106 | rc = pcim_enable_device(pdev); | 1192 | rc = pcim_enable_device(pdev); |
@@ -1150,11 +1236,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1150 | if (ahci_sb600_enable_64bit(pdev)) | 1236 | if (ahci_sb600_enable_64bit(pdev)) |
1151 | hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; | 1237 | hpriv->flags &= ~AHCI_HFLAG_32BIT_ONLY; |
1152 | 1238 | ||
1153 | if ((hpriv->flags & AHCI_HFLAG_NO_MSI) || pci_enable_msi(pdev)) | ||
1154 | pci_intx(pdev, 1); | ||
1155 | |||
1156 | hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; | 1239 | hpriv->mmio = pcim_iomap_table(pdev)[ahci_pci_bar]; |
1157 | 1240 | ||
1241 | n_msis = ahci_init_interrupts(pdev, hpriv); | ||
1242 | if (n_msis > 1) | ||
1243 | hpriv->flags |= AHCI_HFLAG_MULTI_MSI; | ||
1244 | |||
1158 | /* save initial config */ | 1245 | /* save initial config */ |
1159 | ahci_pci_save_initial_config(pdev, hpriv); | 1246 | ahci_pci_save_initial_config(pdev, hpriv); |
1160 | 1247 | ||
@@ -1250,6 +1337,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
1250 | ahci_pci_print_info(host); | 1337 | ahci_pci_print_info(host); |
1251 | 1338 | ||
1252 | pci_set_master(pdev); | 1339 | pci_set_master(pdev); |
1340 | |||
1341 | if (hpriv->flags & AHCI_HFLAG_MULTI_MSI) | ||
1342 | return ahci_host_activate(host, pdev->irq, n_msis); | ||
1343 | |||
1253 | return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, | 1344 | return ata_host_activate(host, pdev->irq, ahci_interrupt, IRQF_SHARED, |
1254 | &ahci_sht); | 1345 | &ahci_sht); |
1255 | } | 1346 | } |
diff --git a/drivers/ata/ahci.h b/drivers/ata/ahci.h index 9be471200a07..b830e6c9fe49 100644 --- a/drivers/ata/ahci.h +++ b/drivers/ata/ahci.h | |||
@@ -231,6 +231,7 @@ enum { | |||
231 | AHCI_HFLAG_DELAY_ENGINE = (1 << 15), /* do not start engine on | 231 | AHCI_HFLAG_DELAY_ENGINE = (1 << 15), /* do not start engine on |
232 | port start (wait until | 232 | port start (wait until |
233 | error-handling stage) */ | 233 | error-handling stage) */ |
234 | AHCI_HFLAG_MULTI_MSI = (1 << 16), /* multiple PCI MSIs */ | ||
234 | 235 | ||
235 | /* ap->flags bits */ | 236 | /* ap->flags bits */ |
236 | 237 | ||
@@ -297,6 +298,8 @@ struct ahci_port_priv { | |||
297 | unsigned int ncq_saw_d2h:1; | 298 | unsigned int ncq_saw_d2h:1; |
298 | unsigned int ncq_saw_dmas:1; | 299 | unsigned int ncq_saw_dmas:1; |
299 | unsigned int ncq_saw_sdb:1; | 300 | unsigned int ncq_saw_sdb:1; |
301 | u32 intr_status; /* interrupts to handle */ | ||
302 | spinlock_t lock; /* protects parent ata_port */ | ||
300 | u32 intr_mask; /* interrupts to enable */ | 303 | u32 intr_mask; /* interrupts to enable */ |
301 | bool fbs_supported; /* set iff FBS is supported */ | 304 | bool fbs_supported; /* set iff FBS is supported */ |
302 | bool fbs_enabled; /* set iff FBS is enabled */ | 305 | bool fbs_enabled; /* set iff FBS is enabled */ |
@@ -359,7 +362,10 @@ void ahci_set_em_messages(struct ahci_host_priv *hpriv, | |||
359 | struct ata_port_info *pi); | 362 | struct ata_port_info *pi); |
360 | int ahci_reset_em(struct ata_host *host); | 363 | int ahci_reset_em(struct ata_host *host); |
361 | irqreturn_t ahci_interrupt(int irq, void *dev_instance); | 364 | irqreturn_t ahci_interrupt(int irq, void *dev_instance); |
365 | irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance); | ||
366 | irqreturn_t ahci_thread_fn(int irq, void *dev_instance); | ||
362 | void ahci_print_info(struct ata_host *host, const char *scc_s); | 367 | void ahci_print_info(struct ata_host *host, const char *scc_s); |
368 | int ahci_host_activate(struct ata_host *host, int irq, unsigned int n_msis); | ||
363 | 369 | ||
364 | static inline void __iomem *__ahci_port_base(struct ata_host *host, | 370 | static inline void __iomem *__ahci_port_base(struct ata_host *host, |
365 | unsigned int port_no) | 371 | unsigned int port_no) |
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c index 320712a7b9ea..34c82167b962 100644 --- a/drivers/ata/libahci.c +++ b/drivers/ata/libahci.c | |||
@@ -1655,19 +1655,16 @@ static void ahci_error_intr(struct ata_port *ap, u32 irq_stat) | |||
1655 | ata_port_abort(ap); | 1655 | ata_port_abort(ap); |
1656 | } | 1656 | } |
1657 | 1657 | ||
1658 | static void ahci_port_intr(struct ata_port *ap) | 1658 | static void ahci_handle_port_interrupt(struct ata_port *ap, |
1659 | void __iomem *port_mmio, u32 status) | ||
1659 | { | 1660 | { |
1660 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1661 | struct ata_eh_info *ehi = &ap->link.eh_info; | 1661 | struct ata_eh_info *ehi = &ap->link.eh_info; |
1662 | struct ahci_port_priv *pp = ap->private_data; | 1662 | struct ahci_port_priv *pp = ap->private_data; |
1663 | struct ahci_host_priv *hpriv = ap->host->private_data; | 1663 | struct ahci_host_priv *hpriv = ap->host->private_data; |
1664 | int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); | 1664 | int resetting = !!(ap->pflags & ATA_PFLAG_RESETTING); |
1665 | u32 status, qc_active = 0; | 1665 | u32 qc_active = 0; |
1666 | int rc; | 1666 | int rc; |
1667 | 1667 | ||
1668 | status = readl(port_mmio + PORT_IRQ_STAT); | ||
1669 | writel(status, port_mmio + PORT_IRQ_STAT); | ||
1670 | |||
1671 | /* ignore BAD_PMP while resetting */ | 1668 | /* ignore BAD_PMP while resetting */ |
1672 | if (unlikely(resetting)) | 1669 | if (unlikely(resetting)) |
1673 | status &= ~PORT_IRQ_BAD_PMP; | 1670 | status &= ~PORT_IRQ_BAD_PMP; |
@@ -1743,6 +1740,107 @@ static void ahci_port_intr(struct ata_port *ap) | |||
1743 | } | 1740 | } |
1744 | } | 1741 | } |
1745 | 1742 | ||
1743 | void ahci_port_intr(struct ata_port *ap) | ||
1744 | { | ||
1745 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1746 | u32 status; | ||
1747 | |||
1748 | status = readl(port_mmio + PORT_IRQ_STAT); | ||
1749 | writel(status, port_mmio + PORT_IRQ_STAT); | ||
1750 | |||
1751 | ahci_handle_port_interrupt(ap, port_mmio, status); | ||
1752 | } | ||
1753 | |||
1754 | irqreturn_t ahci_thread_fn(int irq, void *dev_instance) | ||
1755 | { | ||
1756 | struct ata_port *ap = dev_instance; | ||
1757 | struct ahci_port_priv *pp = ap->private_data; | ||
1758 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1759 | unsigned long flags; | ||
1760 | u32 status; | ||
1761 | |||
1762 | spin_lock_irqsave(&ap->host->lock, flags); | ||
1763 | status = pp->intr_status; | ||
1764 | if (status) | ||
1765 | pp->intr_status = 0; | ||
1766 | spin_unlock_irqrestore(&ap->host->lock, flags); | ||
1767 | |||
1768 | spin_lock_bh(ap->lock); | ||
1769 | ahci_handle_port_interrupt(ap, port_mmio, status); | ||
1770 | spin_unlock_bh(ap->lock); | ||
1771 | |||
1772 | return IRQ_HANDLED; | ||
1773 | } | ||
1774 | EXPORT_SYMBOL_GPL(ahci_thread_fn); | ||
1775 | |||
1776 | void ahci_hw_port_interrupt(struct ata_port *ap) | ||
1777 | { | ||
1778 | void __iomem *port_mmio = ahci_port_base(ap); | ||
1779 | struct ahci_port_priv *pp = ap->private_data; | ||
1780 | u32 status; | ||
1781 | |||
1782 | status = readl(port_mmio + PORT_IRQ_STAT); | ||
1783 | writel(status, port_mmio + PORT_IRQ_STAT); | ||
1784 | |||
1785 | pp->intr_status |= status; | ||
1786 | } | ||
1787 | |||
1788 | irqreturn_t ahci_hw_interrupt(int irq, void *dev_instance) | ||
1789 | { | ||
1790 | struct ata_port *ap_this = dev_instance; | ||
1791 | struct ahci_port_priv *pp = ap_this->private_data; | ||
1792 | struct ata_host *host = ap_this->host; | ||
1793 | struct ahci_host_priv *hpriv = host->private_data; | ||
1794 | void __iomem *mmio = hpriv->mmio; | ||
1795 | unsigned int i; | ||
1796 | u32 irq_stat, irq_masked; | ||
1797 | |||
1798 | VPRINTK("ENTER\n"); | ||
1799 | |||
1800 | spin_lock(&host->lock); | ||
1801 | |||
1802 | irq_stat = readl(mmio + HOST_IRQ_STAT); | ||
1803 | |||
1804 | if (!irq_stat) { | ||
1805 | u32 status = pp->intr_status; | ||
1806 | |||
1807 | spin_unlock(&host->lock); | ||
1808 | |||
1809 | VPRINTK("EXIT\n"); | ||
1810 | |||
1811 | return status ? IRQ_WAKE_THREAD : IRQ_NONE; | ||
1812 | } | ||
1813 | |||
1814 | irq_masked = irq_stat & hpriv->port_map; | ||
1815 | |||
1816 | for (i = 0; i < host->n_ports; i++) { | ||
1817 | struct ata_port *ap; | ||
1818 | |||
1819 | if (!(irq_masked & (1 << i))) | ||
1820 | continue; | ||
1821 | |||
1822 | ap = host->ports[i]; | ||
1823 | if (ap) { | ||
1824 | ahci_hw_port_interrupt(ap); | ||
1825 | VPRINTK("port %u\n", i); | ||
1826 | } else { | ||
1827 | VPRINTK("port %u (no irq)\n", i); | ||
1828 | if (ata_ratelimit()) | ||
1829 | dev_warn(host->dev, | ||
1830 | "interrupt on disabled port %u\n", i); | ||
1831 | } | ||
1832 | } | ||
1833 | |||
1834 | writel(irq_stat, mmio + HOST_IRQ_STAT); | ||
1835 | |||
1836 | spin_unlock(&host->lock); | ||
1837 | |||
1838 | VPRINTK("EXIT\n"); | ||
1839 | |||
1840 | return IRQ_WAKE_THREAD; | ||
1841 | } | ||
1842 | EXPORT_SYMBOL_GPL(ahci_hw_interrupt); | ||
1843 | |||
1746 | irqreturn_t ahci_interrupt(int irq, void *dev_instance) | 1844 | irqreturn_t ahci_interrupt(int irq, void *dev_instance) |
1747 | { | 1845 | { |
1748 | struct ata_host *host = dev_instance; | 1846 | struct ata_host *host = dev_instance; |
@@ -1951,13 +2049,13 @@ static void ahci_set_aggressive_devslp(struct ata_port *ap, bool sleep) | |||
1951 | /* Use the nominal value 10 ms if the read MDAT is zero, | 2049 | /* Use the nominal value 10 ms if the read MDAT is zero, |
1952 | * the nominal value of DETO is 20 ms. | 2050 | * the nominal value of DETO is 20 ms. |
1953 | */ | 2051 | */ |
1954 | if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] & | 2052 | if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] & |
1955 | ATA_LOG_DEVSLP_VALID_MASK) { | 2053 | ATA_LOG_DEVSLP_VALID_MASK) { |
1956 | mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] & | 2054 | mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] & |
1957 | ATA_LOG_DEVSLP_MDAT_MASK; | 2055 | ATA_LOG_DEVSLP_MDAT_MASK; |
1958 | if (!mdat) | 2056 | if (!mdat) |
1959 | mdat = 10; | 2057 | mdat = 10; |
1960 | deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO]; | 2058 | deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO]; |
1961 | if (!deto) | 2059 | if (!deto) |
1962 | deto = 20; | 2060 | deto = 20; |
1963 | } else { | 2061 | } else { |
@@ -2196,6 +2294,14 @@ static int ahci_port_start(struct ata_port *ap) | |||
2196 | */ | 2294 | */ |
2197 | pp->intr_mask = DEF_PORT_IRQ; | 2295 | pp->intr_mask = DEF_PORT_IRQ; |
2198 | 2296 | ||
2297 | /* | ||
2298 | * Switch to per-port locking in case each port has its own MSI vector. | ||
2299 | */ | ||
2300 | if ((hpriv->flags & AHCI_HFLAG_MULTI_MSI)) { | ||
2301 | spin_lock_init(&pp->lock); | ||
2302 | ap->lock = &pp->lock; | ||
2303 | } | ||
2304 | |||
2199 | ap->private_data = pp; | 2305 | ap->private_data = pp; |
2200 | 2306 | ||
2201 | /* engage engines, captain */ | 2307 | /* engage engines, captain */ |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9e8b99af400d..46cd3f4c6aaa 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -2325,24 +2325,28 @@ int ata_dev_configure(struct ata_device *dev) | |||
2325 | } | 2325 | } |
2326 | } | 2326 | } |
2327 | 2327 | ||
2328 | /* check and mark DevSlp capability */ | 2328 | /* Check and mark DevSlp capability. Get DevSlp timing variables |
2329 | if (ata_id_has_devslp(dev->id)) | 2329 | * from SATA Settings page of Identify Device Data Log. |
2330 | dev->flags |= ATA_DFLAG_DEVSLP; | ||
2331 | |||
2332 | /* Obtain SATA Settings page from Identify Device Data Log, | ||
2333 | * which contains DevSlp timing variables etc. | ||
2334 | * Exclude old devices with ata_id_has_ncq() | ||
2335 | */ | 2330 | */ |
2336 | if (ata_id_has_ncq(dev->id)) { | 2331 | if (ata_id_has_devslp(dev->id)) { |
2332 | u8 sata_setting[ATA_SECT_SIZE]; | ||
2333 | int i, j; | ||
2334 | |||
2335 | dev->flags |= ATA_DFLAG_DEVSLP; | ||
2337 | err_mask = ata_read_log_page(dev, | 2336 | err_mask = ata_read_log_page(dev, |
2338 | ATA_LOG_SATA_ID_DEV_DATA, | 2337 | ATA_LOG_SATA_ID_DEV_DATA, |
2339 | ATA_LOG_SATA_SETTINGS, | 2338 | ATA_LOG_SATA_SETTINGS, |
2340 | dev->sata_settings, | 2339 | sata_setting, |
2341 | 1); | 2340 | 1); |
2342 | if (err_mask) | 2341 | if (err_mask) |
2343 | ata_dev_dbg(dev, | 2342 | ata_dev_dbg(dev, |
2344 | "failed to get Identify Device Data, Emask 0x%x\n", | 2343 | "failed to get Identify Device Data, Emask 0x%x\n", |
2345 | err_mask); | 2344 | err_mask); |
2345 | else | ||
2346 | for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) { | ||
2347 | j = ATA_LOG_DEVSLP_OFFSET + i; | ||
2348 | dev->devslp_timing[i] = sata_setting[j]; | ||
2349 | } | ||
2346 | } | 2350 | } |
2347 | 2351 | ||
2348 | dev->cdb_len = 16; | 2352 | dev->cdb_len = 16; |
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index bf039b0e97b7..bcf4437214f5 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c | |||
@@ -2094,7 +2094,7 @@ static unsigned int ata_eh_speed_down(struct ata_device *dev, | |||
2094 | */ | 2094 | */ |
2095 | static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc) | 2095 | static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc) |
2096 | { | 2096 | { |
2097 | if (qc->flags & AC_ERR_MEDIA) | 2097 | if (qc->err_mask & AC_ERR_MEDIA) |
2098 | return 0; /* don't retry media errors */ | 2098 | return 0; /* don't retry media errors */ |
2099 | if (qc->flags & ATA_QCFLAG_IO) | 2099 | if (qc->flags & ATA_QCFLAG_IO) |
2100 | return 1; /* otherwise retry anything from fs stack */ | 2100 | return 1; /* otherwise retry anything from fs stack */ |
diff --git a/drivers/atm/iphase.h b/drivers/atm/iphase.h index 6a0955e6d4fc..53ecac5a2161 100644 --- a/drivers/atm/iphase.h +++ b/drivers/atm/iphase.h | |||
@@ -636,82 +636,82 @@ struct rx_buf_desc { | |||
636 | #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE | 636 | #define SEG_BASE IPHASE5575_FRAG_CONTROL_REG_BASE |
637 | #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE | 637 | #define REASS_BASE IPHASE5575_REASS_CONTROL_REG_BASE |
638 | 638 | ||
639 | typedef volatile u_int freg_t; | 639 | typedef volatile u_int ffreg_t; |
640 | typedef u_int rreg_t; | 640 | typedef u_int rreg_t; |
641 | 641 | ||
642 | typedef struct _ffredn_t { | 642 | typedef struct _ffredn_t { |
643 | freg_t idlehead_high; /* Idle cell header (high) */ | 643 | ffreg_t idlehead_high; /* Idle cell header (high) */ |
644 | freg_t idlehead_low; /* Idle cell header (low) */ | 644 | ffreg_t idlehead_low; /* Idle cell header (low) */ |
645 | freg_t maxrate; /* Maximum rate */ | 645 | ffreg_t maxrate; /* Maximum rate */ |
646 | freg_t stparms; /* Traffic Management Parameters */ | 646 | ffreg_t stparms; /* Traffic Management Parameters */ |
647 | freg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ | 647 | ffreg_t abrubr_abr; /* ABRUBR Priority Byte 1, TCR Byte 0 */ |
648 | freg_t rm_type; /* */ | 648 | ffreg_t rm_type; /* */ |
649 | u_int filler5[0x17 - 0x06]; | 649 | u_int filler5[0x17 - 0x06]; |
650 | freg_t cmd_reg; /* Command register */ | 650 | ffreg_t cmd_reg; /* Command register */ |
651 | u_int filler18[0x20 - 0x18]; | 651 | u_int filler18[0x20 - 0x18]; |
652 | freg_t cbr_base; /* CBR Pointer Base */ | 652 | ffreg_t cbr_base; /* CBR Pointer Base */ |
653 | freg_t vbr_base; /* VBR Pointer Base */ | 653 | ffreg_t vbr_base; /* VBR Pointer Base */ |
654 | freg_t abr_base; /* ABR Pointer Base */ | 654 | ffreg_t abr_base; /* ABR Pointer Base */ |
655 | freg_t ubr_base; /* UBR Pointer Base */ | 655 | ffreg_t ubr_base; /* UBR Pointer Base */ |
656 | u_int filler24; | 656 | u_int filler24; |
657 | freg_t vbrwq_base; /* VBR Wait Queue Base */ | 657 | ffreg_t vbrwq_base; /* VBR Wait Queue Base */ |
658 | freg_t abrwq_base; /* ABR Wait Queue Base */ | 658 | ffreg_t abrwq_base; /* ABR Wait Queue Base */ |
659 | freg_t ubrwq_base; /* UBR Wait Queue Base */ | 659 | ffreg_t ubrwq_base; /* UBR Wait Queue Base */ |
660 | freg_t vct_base; /* Main VC Table Base */ | 660 | ffreg_t vct_base; /* Main VC Table Base */ |
661 | freg_t vcte_base; /* Extended Main VC Table Base */ | 661 | ffreg_t vcte_base; /* Extended Main VC Table Base */ |
662 | u_int filler2a[0x2C - 0x2A]; | 662 | u_int filler2a[0x2C - 0x2A]; |
663 | freg_t cbr_tab_beg; /* CBR Table Begin */ | 663 | ffreg_t cbr_tab_beg; /* CBR Table Begin */ |
664 | freg_t cbr_tab_end; /* CBR Table End */ | 664 | ffreg_t cbr_tab_end; /* CBR Table End */ |
665 | freg_t cbr_pointer; /* CBR Pointer */ | 665 | ffreg_t cbr_pointer; /* CBR Pointer */ |
666 | u_int filler2f[0x30 - 0x2F]; | 666 | u_int filler2f[0x30 - 0x2F]; |
667 | freg_t prq_st_adr; /* Packet Ready Queue Start Address */ | 667 | ffreg_t prq_st_adr; /* Packet Ready Queue Start Address */ |
668 | freg_t prq_ed_adr; /* Packet Ready Queue End Address */ | 668 | ffreg_t prq_ed_adr; /* Packet Ready Queue End Address */ |
669 | freg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ | 669 | ffreg_t prq_rd_ptr; /* Packet Ready Queue read pointer */ |
670 | freg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ | 670 | ffreg_t prq_wr_ptr; /* Packet Ready Queue write pointer */ |
671 | freg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ | 671 | ffreg_t tcq_st_adr; /* Transmit Complete Queue Start Address*/ |
672 | freg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ | 672 | ffreg_t tcq_ed_adr; /* Transmit Complete Queue End Address */ |
673 | freg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ | 673 | ffreg_t tcq_rd_ptr; /* Transmit Complete Queue read pointer */ |
674 | freg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ | 674 | ffreg_t tcq_wr_ptr; /* Transmit Complete Queue write pointer*/ |
675 | u_int filler38[0x40 - 0x38]; | 675 | u_int filler38[0x40 - 0x38]; |
676 | freg_t queue_base; /* Base address for PRQ and TCQ */ | 676 | ffreg_t queue_base; /* Base address for PRQ and TCQ */ |
677 | freg_t desc_base; /* Base address of descriptor table */ | 677 | ffreg_t desc_base; /* Base address of descriptor table */ |
678 | u_int filler42[0x45 - 0x42]; | 678 | u_int filler42[0x45 - 0x42]; |
679 | freg_t mode_reg_0; /* Mode register 0 */ | 679 | ffreg_t mode_reg_0; /* Mode register 0 */ |
680 | freg_t mode_reg_1; /* Mode register 1 */ | 680 | ffreg_t mode_reg_1; /* Mode register 1 */ |
681 | freg_t intr_status_reg;/* Interrupt Status register */ | 681 | ffreg_t intr_status_reg;/* Interrupt Status register */ |
682 | freg_t mask_reg; /* Mask Register */ | 682 | ffreg_t mask_reg; /* Mask Register */ |
683 | freg_t cell_ctr_high1; /* Total cell transfer count (high) */ | 683 | ffreg_t cell_ctr_high1; /* Total cell transfer count (high) */ |
684 | freg_t cell_ctr_lo1; /* Total cell transfer count (low) */ | 684 | ffreg_t cell_ctr_lo1; /* Total cell transfer count (low) */ |
685 | freg_t state_reg; /* Status register */ | 685 | ffreg_t state_reg; /* Status register */ |
686 | u_int filler4c[0x58 - 0x4c]; | 686 | u_int filler4c[0x58 - 0x4c]; |
687 | freg_t curr_desc_num; /* Contains the current descriptor num */ | 687 | ffreg_t curr_desc_num; /* Contains the current descriptor num */ |
688 | freg_t next_desc; /* Next descriptor */ | 688 | ffreg_t next_desc; /* Next descriptor */ |
689 | freg_t next_vc; /* Next VC */ | 689 | ffreg_t next_vc; /* Next VC */ |
690 | u_int filler5b[0x5d - 0x5b]; | 690 | u_int filler5b[0x5d - 0x5b]; |
691 | freg_t present_slot_cnt;/* Present slot count */ | 691 | ffreg_t present_slot_cnt;/* Present slot count */ |
692 | u_int filler5e[0x6a - 0x5e]; | 692 | u_int filler5e[0x6a - 0x5e]; |
693 | freg_t new_desc_num; /* New descriptor number */ | 693 | ffreg_t new_desc_num; /* New descriptor number */ |
694 | freg_t new_vc; /* New VC */ | 694 | ffreg_t new_vc; /* New VC */ |
695 | freg_t sched_tbl_ptr; /* Schedule table pointer */ | 695 | ffreg_t sched_tbl_ptr; /* Schedule table pointer */ |
696 | freg_t vbrwq_wptr; /* VBR wait queue write pointer */ | 696 | ffreg_t vbrwq_wptr; /* VBR wait queue write pointer */ |
697 | freg_t vbrwq_rptr; /* VBR wait queue read pointer */ | 697 | ffreg_t vbrwq_rptr; /* VBR wait queue read pointer */ |
698 | freg_t abrwq_wptr; /* ABR wait queue write pointer */ | 698 | ffreg_t abrwq_wptr; /* ABR wait queue write pointer */ |
699 | freg_t abrwq_rptr; /* ABR wait queue read pointer */ | 699 | ffreg_t abrwq_rptr; /* ABR wait queue read pointer */ |
700 | freg_t ubrwq_wptr; /* UBR wait queue write pointer */ | 700 | ffreg_t ubrwq_wptr; /* UBR wait queue write pointer */ |
701 | freg_t ubrwq_rptr; /* UBR wait queue read pointer */ | 701 | ffreg_t ubrwq_rptr; /* UBR wait queue read pointer */ |
702 | freg_t cbr_vc; /* CBR VC */ | 702 | ffreg_t cbr_vc; /* CBR VC */ |
703 | freg_t vbr_sb_vc; /* VBR SB VC */ | 703 | ffreg_t vbr_sb_vc; /* VBR SB VC */ |
704 | freg_t abr_sb_vc; /* ABR SB VC */ | 704 | ffreg_t abr_sb_vc; /* ABR SB VC */ |
705 | freg_t ubr_sb_vc; /* UBR SB VC */ | 705 | ffreg_t ubr_sb_vc; /* UBR SB VC */ |
706 | freg_t vbr_next_link; /* VBR next link */ | 706 | ffreg_t vbr_next_link; /* VBR next link */ |
707 | freg_t abr_next_link; /* ABR next link */ | 707 | ffreg_t abr_next_link; /* ABR next link */ |
708 | freg_t ubr_next_link; /* UBR next link */ | 708 | ffreg_t ubr_next_link; /* UBR next link */ |
709 | u_int filler7a[0x7c-0x7a]; | 709 | u_int filler7a[0x7c-0x7a]; |
710 | freg_t out_rate_head; /* Out of rate head */ | 710 | ffreg_t out_rate_head; /* Out of rate head */ |
711 | u_int filler7d[0xca-0x7d]; /* pad out to full address space */ | 711 | u_int filler7d[0xca-0x7d]; /* pad out to full address space */ |
712 | freg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ | 712 | ffreg_t cell_ctr_high1_nc;/* Total cell transfer count (high) */ |
713 | freg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ | 713 | ffreg_t cell_ctr_lo1_nc;/* Total cell transfer count (low) */ |
714 | u_int fillercc[0x100-0xcc]; /* pad out to full address space */ | 714 | u_int fillercc[0x100-0xcc]; /* pad out to full address space */ |
715 | } ffredn_t; | 715 | } ffredn_t; |
716 | 716 | ||
717 | typedef struct _rfredn_t { | 717 | typedef struct _rfredn_t { |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index 63452943abd1..fb10728f6372 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -224,7 +224,7 @@ static void cpu_device_release(struct device *dev) | |||
224 | * by the cpu device. | 224 | * by the cpu device. |
225 | * | 225 | * |
226 | * Never copy this way of doing things, or you too will be made fun of | 226 | * Never copy this way of doing things, or you too will be made fun of |
227 | * on the linux-kerenl list, you have been warned. | 227 | * on the linux-kernel list, you have been warned. |
228 | */ | 228 | */ |
229 | } | 229 | } |
230 | 230 | ||
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index d81460309182..b392b353be39 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -305,7 +305,7 @@ static bool fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf | |||
305 | char *buf; | 305 | char *buf; |
306 | 306 | ||
307 | size = fw_file_size(file); | 307 | size = fw_file_size(file); |
308 | if (size < 0) | 308 | if (size <= 0) |
309 | return false; | 309 | return false; |
310 | buf = vmalloc(size); | 310 | buf = vmalloc(size); |
311 | if (!buf) | 311 | if (!buf) |
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index 5e75d1b683e2..cf129980abd0 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_REGMAP) += regmap.o regcache.o | 1 | obj-$(CONFIG_REGMAP) += regmap.o regcache.o |
2 | obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o | 2 | obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o |
3 | obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o | 3 | obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o |
4 | obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o | 4 | obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o |
5 | obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o | 5 | obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o |
diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index 401d1919635a..5a22bd33ce3d 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/regmap.h> | 16 | #include <linux/regmap.h> |
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/list.h> | 18 | #include <linux/list.h> |
19 | #include <linux/wait.h> | ||
19 | 20 | ||
20 | struct regmap; | 21 | struct regmap; |
21 | struct regcache_ops; | 22 | struct regcache_ops; |
@@ -25,6 +26,7 @@ struct regmap_debugfs_off_cache { | |||
25 | off_t min; | 26 | off_t min; |
26 | off_t max; | 27 | off_t max; |
27 | unsigned int base_reg; | 28 | unsigned int base_reg; |
29 | unsigned int max_reg; | ||
28 | }; | 30 | }; |
29 | 31 | ||
30 | struct regmap_format { | 32 | struct regmap_format { |
@@ -39,6 +41,13 @@ struct regmap_format { | |||
39 | unsigned int (*parse_val)(void *buf); | 41 | unsigned int (*parse_val)(void *buf); |
40 | }; | 42 | }; |
41 | 43 | ||
44 | struct regmap_async { | ||
45 | struct list_head list; | ||
46 | struct work_struct cleanup; | ||
47 | struct regmap *map; | ||
48 | void *work_buf; | ||
49 | }; | ||
50 | |||
42 | struct regmap { | 51 | struct regmap { |
43 | struct mutex mutex; | 52 | struct mutex mutex; |
44 | spinlock_t spinlock; | 53 | spinlock_t spinlock; |
@@ -53,6 +62,11 @@ struct regmap { | |||
53 | void *bus_context; | 62 | void *bus_context; |
54 | const char *name; | 63 | const char *name; |
55 | 64 | ||
65 | spinlock_t async_lock; | ||
66 | wait_queue_head_t async_waitq; | ||
67 | struct list_head async_list; | ||
68 | int async_ret; | ||
69 | |||
56 | #ifdef CONFIG_DEBUG_FS | 70 | #ifdef CONFIG_DEBUG_FS |
57 | struct dentry *debugfs; | 71 | struct dentry *debugfs; |
58 | const char *debugfs_name; | 72 | const char *debugfs_name; |
@@ -74,6 +88,11 @@ struct regmap { | |||
74 | const struct regmap_access_table *volatile_table; | 88 | const struct regmap_access_table *volatile_table; |
75 | const struct regmap_access_table *precious_table; | 89 | const struct regmap_access_table *precious_table; |
76 | 90 | ||
91 | int (*reg_read)(void *context, unsigned int reg, unsigned int *val); | ||
92 | int (*reg_write)(void *context, unsigned int reg, unsigned int val); | ||
93 | |||
94 | bool defer_caching; | ||
95 | |||
77 | u8 read_flag_mask; | 96 | u8 read_flag_mask; |
78 | u8 write_flag_mask; | 97 | u8 write_flag_mask; |
79 | 98 | ||
@@ -175,7 +194,10 @@ bool regcache_set_val(void *base, unsigned int idx, | |||
175 | unsigned int val, unsigned int word_size); | 194 | unsigned int val, unsigned int word_size); |
176 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); | 195 | int regcache_lookup_reg(struct regmap *map, unsigned int reg); |
177 | 196 | ||
197 | void regmap_async_complete_cb(struct regmap_async *async, int ret); | ||
198 | |||
178 | extern struct regcache_ops regcache_rbtree_ops; | 199 | extern struct regcache_ops regcache_rbtree_ops; |
179 | extern struct regcache_ops regcache_lzo_ops; | 200 | extern struct regcache_ops regcache_lzo_ops; |
201 | extern struct regcache_ops regcache_flat_ops; | ||
180 | 202 | ||
181 | #endif | 203 | #endif |
diff --git a/drivers/base/regmap/regcache-flat.c b/drivers/base/regmap/regcache-flat.c new file mode 100644 index 000000000000..d9762e41959b --- /dev/null +++ b/drivers/base/regmap/regcache-flat.c | |||
@@ -0,0 +1,72 @@ | |||
1 | /* | ||
2 | * Register cache access API - flat caching support | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics plc | ||
5 | * | ||
6 | * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | */ | ||
12 | |||
13 | #include <linux/slab.h> | ||
14 | #include <linux/device.h> | ||
15 | #include <linux/seq_file.h> | ||
16 | |||
17 | #include "internal.h" | ||
18 | |||
19 | static int regcache_flat_init(struct regmap *map) | ||
20 | { | ||
21 | int i; | ||
22 | unsigned int *cache; | ||
23 | |||
24 | map->cache = kzalloc(sizeof(unsigned int) * (map->max_register + 1), | ||
25 | GFP_KERNEL); | ||
26 | if (!map->cache) | ||
27 | return -ENOMEM; | ||
28 | |||
29 | cache = map->cache; | ||
30 | |||
31 | for (i = 0; i < map->num_reg_defaults; i++) | ||
32 | cache[map->reg_defaults[i].reg] = map->reg_defaults[i].def; | ||
33 | |||
34 | return 0; | ||
35 | } | ||
36 | |||
37 | static int regcache_flat_exit(struct regmap *map) | ||
38 | { | ||
39 | kfree(map->cache); | ||
40 | map->cache = NULL; | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int regcache_flat_read(struct regmap *map, | ||
46 | unsigned int reg, unsigned int *value) | ||
47 | { | ||
48 | unsigned int *cache = map->cache; | ||
49 | |||
50 | *value = cache[reg]; | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int regcache_flat_write(struct regmap *map, unsigned int reg, | ||
56 | unsigned int value) | ||
57 | { | ||
58 | unsigned int *cache = map->cache; | ||
59 | |||
60 | cache[reg] = value; | ||
61 | |||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | struct regcache_ops regcache_flat_ops = { | ||
66 | .type = REGCACHE_FLAT, | ||
67 | .name = "flat", | ||
68 | .init = regcache_flat_init, | ||
69 | .exit = regcache_flat_exit, | ||
70 | .read = regcache_flat_read, | ||
71 | .write = regcache_flat_write, | ||
72 | }; | ||
diff --git a/drivers/base/regmap/regcache.c b/drivers/base/regmap/regcache.c index 835883bda977..e69ff3e4742c 100644 --- a/drivers/base/regmap/regcache.c +++ b/drivers/base/regmap/regcache.c | |||
@@ -22,6 +22,7 @@ | |||
22 | static const struct regcache_ops *cache_types[] = { | 22 | static const struct regcache_ops *cache_types[] = { |
23 | ®cache_rbtree_ops, | 23 | ®cache_rbtree_ops, |
24 | ®cache_lzo_ops, | 24 | ®cache_lzo_ops, |
25 | ®cache_flat_ops, | ||
25 | }; | 26 | }; |
26 | 27 | ||
27 | static int regcache_hw_init(struct regmap *map) | 28 | static int regcache_hw_init(struct regmap *map) |
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c index 07aad786f817..78d5f20c5f5b 100644 --- a/drivers/base/regmap/regmap-debugfs.c +++ b/drivers/base/regmap/regmap-debugfs.c | |||
@@ -56,6 +56,19 @@ static const struct file_operations regmap_name_fops = { | |||
56 | .llseek = default_llseek, | 56 | .llseek = default_llseek, |
57 | }; | 57 | }; |
58 | 58 | ||
59 | static void regmap_debugfs_free_dump_cache(struct regmap *map) | ||
60 | { | ||
61 | struct regmap_debugfs_off_cache *c; | ||
62 | |||
63 | while (!list_empty(&map->debugfs_off_cache)) { | ||
64 | c = list_first_entry(&map->debugfs_off_cache, | ||
65 | struct regmap_debugfs_off_cache, | ||
66 | list); | ||
67 | list_del(&c->list); | ||
68 | kfree(c); | ||
69 | } | ||
70 | } | ||
71 | |||
59 | /* | 72 | /* |
60 | * Work out where the start offset maps into register numbers, bearing | 73 | * Work out where the start offset maps into register numbers, bearing |
61 | * in mind that we suppress hidden registers. | 74 | * in mind that we suppress hidden registers. |
@@ -68,6 +81,8 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
68 | struct regmap_debugfs_off_cache *c = NULL; | 81 | struct regmap_debugfs_off_cache *c = NULL; |
69 | loff_t p = 0; | 82 | loff_t p = 0; |
70 | unsigned int i, ret; | 83 | unsigned int i, ret; |
84 | unsigned int fpos_offset; | ||
85 | unsigned int reg_offset; | ||
71 | 86 | ||
72 | /* | 87 | /* |
73 | * If we don't have a cache build one so we don't have to do a | 88 | * If we don't have a cache build one so we don't have to do a |
@@ -80,6 +95,9 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
80 | regmap_precious(map, i)) { | 95 | regmap_precious(map, i)) { |
81 | if (c) { | 96 | if (c) { |
82 | c->max = p - 1; | 97 | c->max = p - 1; |
98 | fpos_offset = c->max - c->min; | ||
99 | reg_offset = fpos_offset / map->debugfs_tot_len; | ||
100 | c->max_reg = c->base_reg + reg_offset; | ||
83 | list_add_tail(&c->list, | 101 | list_add_tail(&c->list, |
84 | &map->debugfs_off_cache); | 102 | &map->debugfs_off_cache); |
85 | c = NULL; | 103 | c = NULL; |
@@ -91,8 +109,10 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
91 | /* No cache entry? Start a new one */ | 109 | /* No cache entry? Start a new one */ |
92 | if (!c) { | 110 | if (!c) { |
93 | c = kzalloc(sizeof(*c), GFP_KERNEL); | 111 | c = kzalloc(sizeof(*c), GFP_KERNEL); |
94 | if (!c) | 112 | if (!c) { |
95 | break; | 113 | regmap_debugfs_free_dump_cache(map); |
114 | return base; | ||
115 | } | ||
96 | c->min = p; | 116 | c->min = p; |
97 | c->base_reg = i; | 117 | c->base_reg = i; |
98 | } | 118 | } |
@@ -101,19 +121,53 @@ static unsigned int regmap_debugfs_get_dump_start(struct regmap *map, | |||
101 | } | 121 | } |
102 | } | 122 | } |
103 | 123 | ||
104 | /* Find the relevant block */ | 124 | /* Close the last entry off if we didn't scan beyond it */ |
125 | if (c) { | ||
126 | c->max = p - 1; | ||
127 | fpos_offset = c->max - c->min; | ||
128 | reg_offset = fpos_offset / map->debugfs_tot_len; | ||
129 | c->max_reg = c->base_reg + reg_offset; | ||
130 | list_add_tail(&c->list, | ||
131 | &map->debugfs_off_cache); | ||
132 | } | ||
133 | |||
134 | /* | ||
135 | * This should never happen; we return above if we fail to | ||
136 | * allocate and we should never be in this code if there are | ||
137 | * no registers at all. | ||
138 | */ | ||
139 | WARN_ON(list_empty(&map->debugfs_off_cache)); | ||
140 | ret = base; | ||
141 | |||
142 | /* Find the relevant block:offset */ | ||
105 | list_for_each_entry(c, &map->debugfs_off_cache, list) { | 143 | list_for_each_entry(c, &map->debugfs_off_cache, list) { |
106 | if (*pos >= c->min && *pos <= c->max) { | 144 | if (from >= c->min && from <= c->max) { |
107 | *pos = c->min; | 145 | fpos_offset = from - c->min; |
108 | return c->base_reg; | 146 | reg_offset = fpos_offset / map->debugfs_tot_len; |
147 | *pos = c->min + (reg_offset * map->debugfs_tot_len); | ||
148 | return c->base_reg + reg_offset; | ||
109 | } | 149 | } |
110 | 150 | ||
111 | ret = c->max; | 151 | *pos = c->max; |
152 | ret = c->max_reg; | ||
112 | } | 153 | } |
113 | 154 | ||
114 | return ret; | 155 | return ret; |
115 | } | 156 | } |
116 | 157 | ||
158 | static inline void regmap_calc_tot_len(struct regmap *map, | ||
159 | void *buf, size_t count) | ||
160 | { | ||
161 | /* Calculate the length of a fixed format */ | ||
162 | if (!map->debugfs_tot_len) { | ||
163 | map->debugfs_reg_len = regmap_calc_reg_len(map->max_register, | ||
164 | buf, count); | ||
165 | map->debugfs_val_len = 2 * map->format.val_bytes; | ||
166 | map->debugfs_tot_len = map->debugfs_reg_len + | ||
167 | map->debugfs_val_len + 3; /* : \n */ | ||
168 | } | ||
169 | } | ||
170 | |||
117 | static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, | 171 | static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, |
118 | unsigned int to, char __user *user_buf, | 172 | unsigned int to, char __user *user_buf, |
119 | size_t count, loff_t *ppos) | 173 | size_t count, loff_t *ppos) |
@@ -132,14 +186,7 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, | |||
132 | if (!buf) | 186 | if (!buf) |
133 | return -ENOMEM; | 187 | return -ENOMEM; |
134 | 188 | ||
135 | /* Calculate the length of a fixed format */ | 189 | regmap_calc_tot_len(map, buf, count); |
136 | if (!map->debugfs_tot_len) { | ||
137 | map->debugfs_reg_len = regmap_calc_reg_len(map->max_register, | ||
138 | buf, count); | ||
139 | map->debugfs_val_len = 2 * map->format.val_bytes; | ||
140 | map->debugfs_tot_len = map->debugfs_reg_len + | ||
141 | map->debugfs_val_len + 3; /* : \n */ | ||
142 | } | ||
143 | 190 | ||
144 | /* Work out which register we're starting at */ | 191 | /* Work out which register we're starting at */ |
145 | start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p); | 192 | start_reg = regmap_debugfs_get_dump_start(map, from, *ppos, &p); |
@@ -154,7 +201,7 @@ static ssize_t regmap_read_debugfs(struct regmap *map, unsigned int from, | |||
154 | /* If we're in the region the user is trying to read */ | 201 | /* If we're in the region the user is trying to read */ |
155 | if (p >= *ppos) { | 202 | if (p >= *ppos) { |
156 | /* ...but not beyond it */ | 203 | /* ...but not beyond it */ |
157 | if (buf_pos + 1 + map->debugfs_tot_len >= count) | 204 | if (buf_pos + map->debugfs_tot_len > count) |
158 | break; | 205 | break; |
159 | 206 | ||
160 | /* Format the register */ | 207 | /* Format the register */ |
@@ -387,16 +434,8 @@ void regmap_debugfs_init(struct regmap *map, const char *name) | |||
387 | 434 | ||
388 | void regmap_debugfs_exit(struct regmap *map) | 435 | void regmap_debugfs_exit(struct regmap *map) |
389 | { | 436 | { |
390 | struct regmap_debugfs_off_cache *c; | ||
391 | |||
392 | debugfs_remove_recursive(map->debugfs); | 437 | debugfs_remove_recursive(map->debugfs); |
393 | while (!list_empty(&map->debugfs_off_cache)) { | 438 | regmap_debugfs_free_dump_cache(map); |
394 | c = list_first_entry(&map->debugfs_off_cache, | ||
395 | struct regmap_debugfs_off_cache, | ||
396 | list); | ||
397 | list_del(&c->list); | ||
398 | kfree(c); | ||
399 | } | ||
400 | kfree(map->debugfs_name); | 439 | kfree(map->debugfs_name); |
401 | } | 440 | } |
402 | 441 | ||
diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index 5972ad958544..4706c63d0bc6 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c | |||
@@ -34,6 +34,7 @@ struct regmap_irq_chip_data { | |||
34 | int irq; | 34 | int irq; |
35 | int wake_count; | 35 | int wake_count; |
36 | 36 | ||
37 | void *status_reg_buf; | ||
37 | unsigned int *status_buf; | 38 | unsigned int *status_buf; |
38 | unsigned int *mask_buf; | 39 | unsigned int *mask_buf; |
39 | unsigned int *mask_buf_def; | 40 | unsigned int *mask_buf_def; |
@@ -87,6 +88,23 @@ static void regmap_irq_sync_unlock(struct irq_data *data) | |||
87 | if (ret != 0) | 88 | if (ret != 0) |
88 | dev_err(d->map->dev, "Failed to sync masks in %x\n", | 89 | dev_err(d->map->dev, "Failed to sync masks in %x\n", |
89 | reg); | 90 | reg); |
91 | |||
92 | reg = d->chip->wake_base + | ||
93 | (i * map->reg_stride * d->irq_reg_stride); | ||
94 | if (d->wake_buf) { | ||
95 | if (d->chip->wake_invert) | ||
96 | ret = regmap_update_bits(d->map, reg, | ||
97 | d->mask_buf_def[i], | ||
98 | ~d->wake_buf[i]); | ||
99 | else | ||
100 | ret = regmap_update_bits(d->map, reg, | ||
101 | d->mask_buf_def[i], | ||
102 | d->wake_buf[i]); | ||
103 | if (ret != 0) | ||
104 | dev_err(d->map->dev, | ||
105 | "Failed to sync wakes in %x: %d\n", | ||
106 | reg, ret); | ||
107 | } | ||
90 | } | 108 | } |
91 | 109 | ||
92 | if (d->chip->runtime_pm) | 110 | if (d->chip->runtime_pm) |
@@ -129,16 +147,15 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on) | |||
129 | struct regmap *map = d->map; | 147 | struct regmap *map = d->map; |
130 | const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); | 148 | const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq); |
131 | 149 | ||
132 | if (!d->chip->wake_base) | ||
133 | return -EINVAL; | ||
134 | |||
135 | if (on) { | 150 | if (on) { |
136 | d->wake_buf[irq_data->reg_offset / map->reg_stride] | 151 | if (d->wake_buf) |
137 | &= ~irq_data->mask; | 152 | d->wake_buf[irq_data->reg_offset / map->reg_stride] |
153 | &= ~irq_data->mask; | ||
138 | d->wake_count++; | 154 | d->wake_count++; |
139 | } else { | 155 | } else { |
140 | d->wake_buf[irq_data->reg_offset / map->reg_stride] | 156 | if (d->wake_buf) |
141 | |= irq_data->mask; | 157 | d->wake_buf[irq_data->reg_offset / map->reg_stride] |
158 | |= irq_data->mask; | ||
142 | d->wake_count--; | 159 | d->wake_count--; |
143 | } | 160 | } |
144 | 161 | ||
@@ -172,25 +189,69 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) | |||
172 | } | 189 | } |
173 | 190 | ||
174 | /* | 191 | /* |
175 | * Ignore masked IRQs and ack if we need to; we ack early so | 192 | * Read in the statuses, using a single bulk read if possible |
176 | * there is no race between handling and acknowleding the | 193 | * in order to reduce the I/O overheads. |
177 | * interrupt. We assume that typically few of the interrupts | ||
178 | * will fire simultaneously so don't worry about overhead from | ||
179 | * doing a write per register. | ||
180 | */ | 194 | */ |
181 | for (i = 0; i < data->chip->num_regs; i++) { | 195 | if (!map->use_single_rw && map->reg_stride == 1 && |
182 | ret = regmap_read(map, chip->status_base + (i * map->reg_stride | 196 | data->irq_reg_stride == 1) { |
183 | * data->irq_reg_stride), | 197 | u8 *buf8 = data->status_reg_buf; |
184 | &data->status_buf[i]); | 198 | u16 *buf16 = data->status_reg_buf; |
199 | u32 *buf32 = data->status_reg_buf; | ||
185 | 200 | ||
201 | BUG_ON(!data->status_reg_buf); | ||
202 | |||
203 | ret = regmap_bulk_read(map, chip->status_base, | ||
204 | data->status_reg_buf, | ||
205 | chip->num_regs); | ||
186 | if (ret != 0) { | 206 | if (ret != 0) { |
187 | dev_err(map->dev, "Failed to read IRQ status: %d\n", | 207 | dev_err(map->dev, "Failed to read IRQ status: %d\n", |
188 | ret); | 208 | ret); |
189 | if (chip->runtime_pm) | ||
190 | pm_runtime_put(map->dev); | ||
191 | return IRQ_NONE; | 209 | return IRQ_NONE; |
192 | } | 210 | } |
193 | 211 | ||
212 | for (i = 0; i < data->chip->num_regs; i++) { | ||
213 | switch (map->format.val_bytes) { | ||
214 | case 1: | ||
215 | data->status_buf[i] = buf8[i]; | ||
216 | break; | ||
217 | case 2: | ||
218 | data->status_buf[i] = buf16[i]; | ||
219 | break; | ||
220 | case 4: | ||
221 | data->status_buf[i] = buf32[i]; | ||
222 | break; | ||
223 | default: | ||
224 | BUG(); | ||
225 | return IRQ_NONE; | ||
226 | } | ||
227 | } | ||
228 | |||
229 | } else { | ||
230 | for (i = 0; i < data->chip->num_regs; i++) { | ||
231 | ret = regmap_read(map, chip->status_base + | ||
232 | (i * map->reg_stride | ||
233 | * data->irq_reg_stride), | ||
234 | &data->status_buf[i]); | ||
235 | |||
236 | if (ret != 0) { | ||
237 | dev_err(map->dev, | ||
238 | "Failed to read IRQ status: %d\n", | ||
239 | ret); | ||
240 | if (chip->runtime_pm) | ||
241 | pm_runtime_put(map->dev); | ||
242 | return IRQ_NONE; | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * Ignore masked IRQs and ack if we need to; we ack early so | ||
249 | * there is no race between handling and acknowleding the | ||
250 | * interrupt. We assume that typically few of the interrupts | ||
251 | * will fire simultaneously so don't worry about overhead from | ||
252 | * doing a write per register. | ||
253 | */ | ||
254 | for (i = 0; i < data->chip->num_regs; i++) { | ||
194 | data->status_buf[i] &= ~data->mask_buf[i]; | 255 | data->status_buf[i] &= ~data->mask_buf[i]; |
195 | 256 | ||
196 | if (data->status_buf[i] && chip->ack_base) { | 257 | if (data->status_buf[i] && chip->ack_base) { |
@@ -316,11 +377,6 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, | |||
316 | 377 | ||
317 | d->irq_chip = regmap_irq_chip; | 378 | d->irq_chip = regmap_irq_chip; |
318 | d->irq_chip.name = chip->name; | 379 | d->irq_chip.name = chip->name; |
319 | if (!chip->wake_base) { | ||
320 | d->irq_chip.irq_set_wake = NULL; | ||
321 | d->irq_chip.flags |= IRQCHIP_MASK_ON_SUSPEND | | ||
322 | IRQCHIP_SKIP_SET_WAKE; | ||
323 | } | ||
324 | d->irq = irq; | 380 | d->irq = irq; |
325 | d->map = map; | 381 | d->map = map; |
326 | d->chip = chip; | 382 | d->chip = chip; |
@@ -331,6 +387,14 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, | |||
331 | else | 387 | else |
332 | d->irq_reg_stride = 1; | 388 | d->irq_reg_stride = 1; |
333 | 389 | ||
390 | if (!map->use_single_rw && map->reg_stride == 1 && | ||
391 | d->irq_reg_stride == 1) { | ||
392 | d->status_reg_buf = kmalloc(map->format.val_bytes * | ||
393 | chip->num_regs, GFP_KERNEL); | ||
394 | if (!d->status_reg_buf) | ||
395 | goto err_alloc; | ||
396 | } | ||
397 | |||
334 | mutex_init(&d->lock); | 398 | mutex_init(&d->lock); |
335 | 399 | ||
336 | for (i = 0; i < chip->num_irqs; i++) | 400 | for (i = 0; i < chip->num_irqs; i++) |
@@ -361,8 +425,15 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, | |||
361 | d->wake_buf[i] = d->mask_buf_def[i]; | 425 | d->wake_buf[i] = d->mask_buf_def[i]; |
362 | reg = chip->wake_base + | 426 | reg = chip->wake_base + |
363 | (i * map->reg_stride * d->irq_reg_stride); | 427 | (i * map->reg_stride * d->irq_reg_stride); |
364 | ret = regmap_update_bits(map, reg, d->wake_buf[i], | 428 | |
365 | d->wake_buf[i]); | 429 | if (chip->wake_invert) |
430 | ret = regmap_update_bits(map, reg, | ||
431 | d->mask_buf_def[i], | ||
432 | 0); | ||
433 | else | ||
434 | ret = regmap_update_bits(map, reg, | ||
435 | d->mask_buf_def[i], | ||
436 | d->wake_buf[i]); | ||
366 | if (ret != 0) { | 437 | if (ret != 0) { |
367 | dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", | 438 | dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", |
368 | reg, ret); | 439 | reg, ret); |
@@ -401,6 +472,7 @@ err_alloc: | |||
401 | kfree(d->mask_buf_def); | 472 | kfree(d->mask_buf_def); |
402 | kfree(d->mask_buf); | 473 | kfree(d->mask_buf); |
403 | kfree(d->status_buf); | 474 | kfree(d->status_buf); |
475 | kfree(d->status_reg_buf); | ||
404 | kfree(d); | 476 | kfree(d); |
405 | return ret; | 477 | return ret; |
406 | } | 478 | } |
@@ -422,6 +494,7 @@ void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *d) | |||
422 | kfree(d->wake_buf); | 494 | kfree(d->wake_buf); |
423 | kfree(d->mask_buf_def); | 495 | kfree(d->mask_buf_def); |
424 | kfree(d->mask_buf); | 496 | kfree(d->mask_buf); |
497 | kfree(d->status_reg_buf); | ||
425 | kfree(d->status_buf); | 498 | kfree(d->status_buf); |
426 | kfree(d); | 499 | kfree(d); |
427 | } | 500 | } |
diff --git a/drivers/base/regmap/regmap-mmio.c b/drivers/base/regmap/regmap-mmio.c index f05fc74dd84a..98745dd77e8c 100644 --- a/drivers/base/regmap/regmap-mmio.c +++ b/drivers/base/regmap/regmap-mmio.c | |||
@@ -16,6 +16,7 @@ | |||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | 16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
17 | */ | 17 | */ |
18 | 18 | ||
19 | #include <linux/clk.h> | ||
19 | #include <linux/err.h> | 20 | #include <linux/err.h> |
20 | #include <linux/init.h> | 21 | #include <linux/init.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
@@ -26,6 +27,7 @@ | |||
26 | struct regmap_mmio_context { | 27 | struct regmap_mmio_context { |
27 | void __iomem *regs; | 28 | void __iomem *regs; |
28 | unsigned val_bytes; | 29 | unsigned val_bytes; |
30 | struct clk *clk; | ||
29 | }; | 31 | }; |
30 | 32 | ||
31 | static int regmap_mmio_gather_write(void *context, | 33 | static int regmap_mmio_gather_write(void *context, |
@@ -34,9 +36,16 @@ static int regmap_mmio_gather_write(void *context, | |||
34 | { | 36 | { |
35 | struct regmap_mmio_context *ctx = context; | 37 | struct regmap_mmio_context *ctx = context; |
36 | u32 offset; | 38 | u32 offset; |
39 | int ret; | ||
37 | 40 | ||
38 | BUG_ON(reg_size != 4); | 41 | BUG_ON(reg_size != 4); |
39 | 42 | ||
43 | if (ctx->clk) { | ||
44 | ret = clk_enable(ctx->clk); | ||
45 | if (ret < 0) | ||
46 | return ret; | ||
47 | } | ||
48 | |||
40 | offset = *(u32 *)reg; | 49 | offset = *(u32 *)reg; |
41 | 50 | ||
42 | while (val_size) { | 51 | while (val_size) { |
@@ -64,6 +73,9 @@ static int regmap_mmio_gather_write(void *context, | |||
64 | offset += ctx->val_bytes; | 73 | offset += ctx->val_bytes; |
65 | } | 74 | } |
66 | 75 | ||
76 | if (ctx->clk) | ||
77 | clk_disable(ctx->clk); | ||
78 | |||
67 | return 0; | 79 | return 0; |
68 | } | 80 | } |
69 | 81 | ||
@@ -80,9 +92,16 @@ static int regmap_mmio_read(void *context, | |||
80 | { | 92 | { |
81 | struct regmap_mmio_context *ctx = context; | 93 | struct regmap_mmio_context *ctx = context; |
82 | u32 offset; | 94 | u32 offset; |
95 | int ret; | ||
83 | 96 | ||
84 | BUG_ON(reg_size != 4); | 97 | BUG_ON(reg_size != 4); |
85 | 98 | ||
99 | if (ctx->clk) { | ||
100 | ret = clk_enable(ctx->clk); | ||
101 | if (ret < 0) | ||
102 | return ret; | ||
103 | } | ||
104 | |||
86 | offset = *(u32 *)reg; | 105 | offset = *(u32 *)reg; |
87 | 106 | ||
88 | while (val_size) { | 107 | while (val_size) { |
@@ -110,11 +129,20 @@ static int regmap_mmio_read(void *context, | |||
110 | offset += ctx->val_bytes; | 129 | offset += ctx->val_bytes; |
111 | } | 130 | } |
112 | 131 | ||
132 | if (ctx->clk) | ||
133 | clk_disable(ctx->clk); | ||
134 | |||
113 | return 0; | 135 | return 0; |
114 | } | 136 | } |
115 | 137 | ||
116 | static void regmap_mmio_free_context(void *context) | 138 | static void regmap_mmio_free_context(void *context) |
117 | { | 139 | { |
140 | struct regmap_mmio_context *ctx = context; | ||
141 | |||
142 | if (ctx->clk) { | ||
143 | clk_unprepare(ctx->clk); | ||
144 | clk_put(ctx->clk); | ||
145 | } | ||
118 | kfree(context); | 146 | kfree(context); |
119 | } | 147 | } |
120 | 148 | ||
@@ -128,11 +156,14 @@ static struct regmap_bus regmap_mmio = { | |||
128 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, | 156 | .val_format_endian_default = REGMAP_ENDIAN_NATIVE, |
129 | }; | 157 | }; |
130 | 158 | ||
131 | static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, | 159 | static struct regmap_mmio_context *regmap_mmio_gen_context(struct device *dev, |
160 | const char *clk_id, | ||
161 | void __iomem *regs, | ||
132 | const struct regmap_config *config) | 162 | const struct regmap_config *config) |
133 | { | 163 | { |
134 | struct regmap_mmio_context *ctx; | 164 | struct regmap_mmio_context *ctx; |
135 | int min_stride; | 165 | int min_stride; |
166 | int ret; | ||
136 | 167 | ||
137 | if (config->reg_bits != 32) | 168 | if (config->reg_bits != 32) |
138 | return ERR_PTR(-EINVAL); | 169 | return ERR_PTR(-EINVAL); |
@@ -179,37 +210,59 @@ static struct regmap_mmio_context *regmap_mmio_gen_context(void __iomem *regs, | |||
179 | ctx->regs = regs; | 210 | ctx->regs = regs; |
180 | ctx->val_bytes = config->val_bits / 8; | 211 | ctx->val_bytes = config->val_bits / 8; |
181 | 212 | ||
213 | if (clk_id == NULL) | ||
214 | return ctx; | ||
215 | |||
216 | ctx->clk = clk_get(dev, clk_id); | ||
217 | if (IS_ERR(ctx->clk)) { | ||
218 | ret = PTR_ERR(ctx->clk); | ||
219 | goto err_free; | ||
220 | } | ||
221 | |||
222 | ret = clk_prepare(ctx->clk); | ||
223 | if (ret < 0) { | ||
224 | clk_put(ctx->clk); | ||
225 | goto err_free; | ||
226 | } | ||
227 | |||
182 | return ctx; | 228 | return ctx; |
229 | |||
230 | err_free: | ||
231 | kfree(ctx); | ||
232 | |||
233 | return ERR_PTR(ret); | ||
183 | } | 234 | } |
184 | 235 | ||
185 | /** | 236 | /** |
186 | * regmap_init_mmio(): Initialise register map | 237 | * regmap_init_mmio_clk(): Initialise register map with register clock |
187 | * | 238 | * |
188 | * @dev: Device that will be interacted with | 239 | * @dev: Device that will be interacted with |
240 | * @clk_id: register clock consumer ID | ||
189 | * @regs: Pointer to memory-mapped IO region | 241 | * @regs: Pointer to memory-mapped IO region |
190 | * @config: Configuration for register map | 242 | * @config: Configuration for register map |
191 | * | 243 | * |
192 | * The return value will be an ERR_PTR() on error or a valid pointer to | 244 | * The return value will be an ERR_PTR() on error or a valid pointer to |
193 | * a struct regmap. | 245 | * a struct regmap. |
194 | */ | 246 | */ |
195 | struct regmap *regmap_init_mmio(struct device *dev, | 247 | struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, |
196 | void __iomem *regs, | 248 | void __iomem *regs, |
197 | const struct regmap_config *config) | 249 | const struct regmap_config *config) |
198 | { | 250 | { |
199 | struct regmap_mmio_context *ctx; | 251 | struct regmap_mmio_context *ctx; |
200 | 252 | ||
201 | ctx = regmap_mmio_gen_context(regs, config); | 253 | ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); |
202 | if (IS_ERR(ctx)) | 254 | if (IS_ERR(ctx)) |
203 | return ERR_CAST(ctx); | 255 | return ERR_CAST(ctx); |
204 | 256 | ||
205 | return regmap_init(dev, ®map_mmio, ctx, config); | 257 | return regmap_init(dev, ®map_mmio, ctx, config); |
206 | } | 258 | } |
207 | EXPORT_SYMBOL_GPL(regmap_init_mmio); | 259 | EXPORT_SYMBOL_GPL(regmap_init_mmio_clk); |
208 | 260 | ||
209 | /** | 261 | /** |
210 | * devm_regmap_init_mmio(): Initialise managed register map | 262 | * devm_regmap_init_mmio_clk(): Initialise managed register map with clock |
211 | * | 263 | * |
212 | * @dev: Device that will be interacted with | 264 | * @dev: Device that will be interacted with |
265 | * @clk_id: register clock consumer ID | ||
213 | * @regs: Pointer to memory-mapped IO region | 266 | * @regs: Pointer to memory-mapped IO region |
214 | * @config: Configuration for register map | 267 | * @config: Configuration for register map |
215 | * | 268 | * |
@@ -217,18 +270,18 @@ EXPORT_SYMBOL_GPL(regmap_init_mmio); | |||
217 | * to a struct regmap. The regmap will be automatically freed by the | 270 | * to a struct regmap. The regmap will be automatically freed by the |
218 | * device management code. | 271 | * device management code. |
219 | */ | 272 | */ |
220 | struct regmap *devm_regmap_init_mmio(struct device *dev, | 273 | struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, |
221 | void __iomem *regs, | 274 | void __iomem *regs, |
222 | const struct regmap_config *config) | 275 | const struct regmap_config *config) |
223 | { | 276 | { |
224 | struct regmap_mmio_context *ctx; | 277 | struct regmap_mmio_context *ctx; |
225 | 278 | ||
226 | ctx = regmap_mmio_gen_context(regs, config); | 279 | ctx = regmap_mmio_gen_context(dev, clk_id, regs, config); |
227 | if (IS_ERR(ctx)) | 280 | if (IS_ERR(ctx)) |
228 | return ERR_CAST(ctx); | 281 | return ERR_CAST(ctx); |
229 | 282 | ||
230 | return devm_regmap_init(dev, ®map_mmio, ctx, config); | 283 | return devm_regmap_init(dev, ®map_mmio, ctx, config); |
231 | } | 284 | } |
232 | EXPORT_SYMBOL_GPL(devm_regmap_init_mmio); | 285 | EXPORT_SYMBOL_GPL(devm_regmap_init_mmio_clk); |
233 | 286 | ||
234 | MODULE_LICENSE("GPL v2"); | 287 | MODULE_LICENSE("GPL v2"); |
diff --git a/drivers/base/regmap/regmap-spi.c b/drivers/base/regmap/regmap-spi.c index ffa46a92ad33..4c506bd940f3 100644 --- a/drivers/base/regmap/regmap-spi.c +++ b/drivers/base/regmap/regmap-spi.c | |||
@@ -15,6 +15,21 @@ | |||
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | 17 | ||
18 | #include "internal.h" | ||
19 | |||
20 | struct regmap_async_spi { | ||
21 | struct regmap_async core; | ||
22 | struct spi_message m; | ||
23 | struct spi_transfer t[2]; | ||
24 | }; | ||
25 | |||
26 | static void regmap_spi_complete(void *data) | ||
27 | { | ||
28 | struct regmap_async_spi *async = data; | ||
29 | |||
30 | regmap_async_complete_cb(&async->core, async->m.status); | ||
31 | } | ||
32 | |||
18 | static int regmap_spi_write(void *context, const void *data, size_t count) | 33 | static int regmap_spi_write(void *context, const void *data, size_t count) |
19 | { | 34 | { |
20 | struct device *dev = context; | 35 | struct device *dev = context; |
@@ -40,6 +55,43 @@ static int regmap_spi_gather_write(void *context, | |||
40 | return spi_sync(spi, &m); | 55 | return spi_sync(spi, &m); |
41 | } | 56 | } |
42 | 57 | ||
58 | static int regmap_spi_async_write(void *context, | ||
59 | const void *reg, size_t reg_len, | ||
60 | const void *val, size_t val_len, | ||
61 | struct regmap_async *a) | ||
62 | { | ||
63 | struct regmap_async_spi *async = container_of(a, | ||
64 | struct regmap_async_spi, | ||
65 | core); | ||
66 | struct device *dev = context; | ||
67 | struct spi_device *spi = to_spi_device(dev); | ||
68 | |||
69 | async->t[0].tx_buf = reg; | ||
70 | async->t[0].len = reg_len; | ||
71 | async->t[1].tx_buf = val; | ||
72 | async->t[1].len = val_len; | ||
73 | |||
74 | spi_message_init(&async->m); | ||
75 | spi_message_add_tail(&async->t[0], &async->m); | ||
76 | spi_message_add_tail(&async->t[1], &async->m); | ||
77 | |||
78 | async->m.complete = regmap_spi_complete; | ||
79 | async->m.context = async; | ||
80 | |||
81 | return spi_async(spi, &async->m); | ||
82 | } | ||
83 | |||
84 | static struct regmap_async *regmap_spi_async_alloc(void) | ||
85 | { | ||
86 | struct regmap_async_spi *async_spi; | ||
87 | |||
88 | async_spi = kzalloc(sizeof(*async_spi), GFP_KERNEL); | ||
89 | if (!async_spi) | ||
90 | return NULL; | ||
91 | |||
92 | return &async_spi->core; | ||
93 | } | ||
94 | |||
43 | static int regmap_spi_read(void *context, | 95 | static int regmap_spi_read(void *context, |
44 | const void *reg, size_t reg_size, | 96 | const void *reg, size_t reg_size, |
45 | void *val, size_t val_size) | 97 | void *val, size_t val_size) |
@@ -53,6 +105,8 @@ static int regmap_spi_read(void *context, | |||
53 | static struct regmap_bus regmap_spi = { | 105 | static struct regmap_bus regmap_spi = { |
54 | .write = regmap_spi_write, | 106 | .write = regmap_spi_write, |
55 | .gather_write = regmap_spi_gather_write, | 107 | .gather_write = regmap_spi_gather_write, |
108 | .async_write = regmap_spi_async_write, | ||
109 | .async_alloc = regmap_spi_async_alloc, | ||
56 | .read = regmap_spi_read, | 110 | .read = regmap_spi_read, |
57 | .read_flag_mask = 0x80, | 111 | .read_flag_mask = 0x80, |
58 | }; | 112 | }; |
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 42d5cb0f503f..3d2367501fd0 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/mutex.h> | 16 | #include <linux/mutex.h> |
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/rbtree.h> | 18 | #include <linux/rbtree.h> |
19 | #include <linux/sched.h> | ||
19 | 20 | ||
20 | #define CREATE_TRACE_POINTS | 21 | #define CREATE_TRACE_POINTS |
21 | #include <trace/events/regmap.h> | 22 | #include <trace/events/regmap.h> |
@@ -34,6 +35,22 @@ static int _regmap_update_bits(struct regmap *map, unsigned int reg, | |||
34 | unsigned int mask, unsigned int val, | 35 | unsigned int mask, unsigned int val, |
35 | bool *change); | 36 | bool *change); |
36 | 37 | ||
38 | static int _regmap_bus_read(void *context, unsigned int reg, | ||
39 | unsigned int *val); | ||
40 | static int _regmap_bus_formatted_write(void *context, unsigned int reg, | ||
41 | unsigned int val); | ||
42 | static int _regmap_bus_raw_write(void *context, unsigned int reg, | ||
43 | unsigned int val); | ||
44 | |||
45 | static void async_cleanup(struct work_struct *work) | ||
46 | { | ||
47 | struct regmap_async *async = container_of(work, struct regmap_async, | ||
48 | cleanup); | ||
49 | |||
50 | kfree(async->work_buf); | ||
51 | kfree(async); | ||
52 | } | ||
53 | |||
37 | bool regmap_reg_in_ranges(unsigned int reg, | 54 | bool regmap_reg_in_ranges(unsigned int reg, |
38 | const struct regmap_range *ranges, | 55 | const struct regmap_range *ranges, |
39 | unsigned int nranges) | 56 | unsigned int nranges) |
@@ -372,7 +389,7 @@ struct regmap *regmap_init(struct device *dev, | |||
372 | enum regmap_endian reg_endian, val_endian; | 389 | enum regmap_endian reg_endian, val_endian; |
373 | int i, j; | 390 | int i, j; |
374 | 391 | ||
375 | if (!bus || !config) | 392 | if (!config) |
376 | goto err; | 393 | goto err; |
377 | 394 | ||
378 | map = kzalloc(sizeof(*map), GFP_KERNEL); | 395 | map = kzalloc(sizeof(*map), GFP_KERNEL); |
@@ -386,7 +403,8 @@ struct regmap *regmap_init(struct device *dev, | |||
386 | map->unlock = config->unlock; | 403 | map->unlock = config->unlock; |
387 | map->lock_arg = config->lock_arg; | 404 | map->lock_arg = config->lock_arg; |
388 | } else { | 405 | } else { |
389 | if (bus->fast_io) { | 406 | if ((bus && bus->fast_io) || |
407 | config->fast_io) { | ||
390 | spin_lock_init(&map->spinlock); | 408 | spin_lock_init(&map->spinlock); |
391 | map->lock = regmap_lock_spinlock; | 409 | map->lock = regmap_lock_spinlock; |
392 | map->unlock = regmap_unlock_spinlock; | 410 | map->unlock = regmap_unlock_spinlock; |
@@ -423,13 +441,27 @@ struct regmap *regmap_init(struct device *dev, | |||
423 | map->cache_type = config->cache_type; | 441 | map->cache_type = config->cache_type; |
424 | map->name = config->name; | 442 | map->name = config->name; |
425 | 443 | ||
444 | spin_lock_init(&map->async_lock); | ||
445 | INIT_LIST_HEAD(&map->async_list); | ||
446 | init_waitqueue_head(&map->async_waitq); | ||
447 | |||
426 | if (config->read_flag_mask || config->write_flag_mask) { | 448 | if (config->read_flag_mask || config->write_flag_mask) { |
427 | map->read_flag_mask = config->read_flag_mask; | 449 | map->read_flag_mask = config->read_flag_mask; |
428 | map->write_flag_mask = config->write_flag_mask; | 450 | map->write_flag_mask = config->write_flag_mask; |
429 | } else { | 451 | } else if (bus) { |
430 | map->read_flag_mask = bus->read_flag_mask; | 452 | map->read_flag_mask = bus->read_flag_mask; |
431 | } | 453 | } |
432 | 454 | ||
455 | if (!bus) { | ||
456 | map->reg_read = config->reg_read; | ||
457 | map->reg_write = config->reg_write; | ||
458 | |||
459 | map->defer_caching = false; | ||
460 | goto skip_format_initialization; | ||
461 | } else { | ||
462 | map->reg_read = _regmap_bus_read; | ||
463 | } | ||
464 | |||
433 | reg_endian = config->reg_format_endian; | 465 | reg_endian = config->reg_format_endian; |
434 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) | 466 | if (reg_endian == REGMAP_ENDIAN_DEFAULT) |
435 | reg_endian = bus->reg_format_endian_default; | 467 | reg_endian = bus->reg_format_endian_default; |
@@ -500,6 +532,12 @@ struct regmap *regmap_init(struct device *dev, | |||
500 | } | 532 | } |
501 | break; | 533 | break; |
502 | 534 | ||
535 | case 24: | ||
536 | if (reg_endian != REGMAP_ENDIAN_BIG) | ||
537 | goto err_map; | ||
538 | map->format.format_reg = regmap_format_24; | ||
539 | break; | ||
540 | |||
503 | case 32: | 541 | case 32: |
504 | switch (reg_endian) { | 542 | switch (reg_endian) { |
505 | case REGMAP_ENDIAN_BIG: | 543 | case REGMAP_ENDIAN_BIG: |
@@ -575,6 +613,16 @@ struct regmap *regmap_init(struct device *dev, | |||
575 | goto err_map; | 613 | goto err_map; |
576 | } | 614 | } |
577 | 615 | ||
616 | if (map->format.format_write) { | ||
617 | map->defer_caching = false; | ||
618 | map->reg_write = _regmap_bus_formatted_write; | ||
619 | } else if (map->format.format_val) { | ||
620 | map->defer_caching = true; | ||
621 | map->reg_write = _regmap_bus_raw_write; | ||
622 | } | ||
623 | |||
624 | skip_format_initialization: | ||
625 | |||
578 | map->range_tree = RB_ROOT; | 626 | map->range_tree = RB_ROOT; |
579 | for (i = 0; i < config->num_ranges; i++) { | 627 | for (i = 0; i < config->num_ranges; i++) { |
580 | const struct regmap_range_cfg *range_cfg = &config->ranges[i]; | 628 | const struct regmap_range_cfg *range_cfg = &config->ranges[i]; |
@@ -776,7 +824,7 @@ void regmap_exit(struct regmap *map) | |||
776 | regcache_exit(map); | 824 | regcache_exit(map); |
777 | regmap_debugfs_exit(map); | 825 | regmap_debugfs_exit(map); |
778 | regmap_range_exit(map); | 826 | regmap_range_exit(map); |
779 | if (map->bus->free_context) | 827 | if (map->bus && map->bus->free_context) |
780 | map->bus->free_context(map->bus_context); | 828 | map->bus->free_context(map->bus_context); |
781 | kfree(map->work_buf); | 829 | kfree(map->work_buf); |
782 | kfree(map); | 830 | kfree(map); |
@@ -870,15 +918,20 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg, | |||
870 | } | 918 | } |
871 | 919 | ||
872 | static int _regmap_raw_write(struct regmap *map, unsigned int reg, | 920 | static int _regmap_raw_write(struct regmap *map, unsigned int reg, |
873 | const void *val, size_t val_len) | 921 | const void *val, size_t val_len, bool async) |
874 | { | 922 | { |
875 | struct regmap_range_node *range; | 923 | struct regmap_range_node *range; |
924 | unsigned long flags; | ||
876 | u8 *u8 = map->work_buf; | 925 | u8 *u8 = map->work_buf; |
926 | void *work_val = map->work_buf + map->format.reg_bytes + | ||
927 | map->format.pad_bytes; | ||
877 | void *buf; | 928 | void *buf; |
878 | int ret = -ENOTSUPP; | 929 | int ret = -ENOTSUPP; |
879 | size_t len; | 930 | size_t len; |
880 | int i; | 931 | int i; |
881 | 932 | ||
933 | BUG_ON(!map->bus); | ||
934 | |||
882 | /* Check for unwritable registers before we start */ | 935 | /* Check for unwritable registers before we start */ |
883 | if (map->writeable_reg) | 936 | if (map->writeable_reg) |
884 | for (i = 0; i < val_len / map->format.val_bytes; i++) | 937 | for (i = 0; i < val_len / map->format.val_bytes; i++) |
@@ -918,7 +971,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
918 | dev_dbg(map->dev, "Writing window %d/%zu\n", | 971 | dev_dbg(map->dev, "Writing window %d/%zu\n", |
919 | win_residue, val_len / map->format.val_bytes); | 972 | win_residue, val_len / map->format.val_bytes); |
920 | ret = _regmap_raw_write(map, reg, val, win_residue * | 973 | ret = _regmap_raw_write(map, reg, val, win_residue * |
921 | map->format.val_bytes); | 974 | map->format.val_bytes, async); |
922 | if (ret != 0) | 975 | if (ret != 0) |
923 | return ret; | 976 | return ret; |
924 | 977 | ||
@@ -941,6 +994,50 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
941 | 994 | ||
942 | u8[0] |= map->write_flag_mask; | 995 | u8[0] |= map->write_flag_mask; |
943 | 996 | ||
997 | if (async && map->bus->async_write) { | ||
998 | struct regmap_async *async = map->bus->async_alloc(); | ||
999 | if (!async) | ||
1000 | return -ENOMEM; | ||
1001 | |||
1002 | async->work_buf = kzalloc(map->format.buf_size, | ||
1003 | GFP_KERNEL | GFP_DMA); | ||
1004 | if (!async->work_buf) { | ||
1005 | kfree(async); | ||
1006 | return -ENOMEM; | ||
1007 | } | ||
1008 | |||
1009 | INIT_WORK(&async->cleanup, async_cleanup); | ||
1010 | async->map = map; | ||
1011 | |||
1012 | /* If the caller supplied the value we can use it safely. */ | ||
1013 | memcpy(async->work_buf, map->work_buf, map->format.pad_bytes + | ||
1014 | map->format.reg_bytes + map->format.val_bytes); | ||
1015 | if (val == work_val) | ||
1016 | val = async->work_buf + map->format.pad_bytes + | ||
1017 | map->format.reg_bytes; | ||
1018 | |||
1019 | spin_lock_irqsave(&map->async_lock, flags); | ||
1020 | list_add_tail(&async->list, &map->async_list); | ||
1021 | spin_unlock_irqrestore(&map->async_lock, flags); | ||
1022 | |||
1023 | ret = map->bus->async_write(map->bus_context, async->work_buf, | ||
1024 | map->format.reg_bytes + | ||
1025 | map->format.pad_bytes, | ||
1026 | val, val_len, async); | ||
1027 | |||
1028 | if (ret != 0) { | ||
1029 | dev_err(map->dev, "Failed to schedule write: %d\n", | ||
1030 | ret); | ||
1031 | |||
1032 | spin_lock_irqsave(&map->async_lock, flags); | ||
1033 | list_del(&async->list); | ||
1034 | spin_unlock_irqrestore(&map->async_lock, flags); | ||
1035 | |||
1036 | kfree(async->work_buf); | ||
1037 | kfree(async); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
944 | trace_regmap_hw_write_start(map->dev, reg, | 1041 | trace_regmap_hw_write_start(map->dev, reg, |
945 | val_len / map->format.val_bytes); | 1042 | val_len / map->format.val_bytes); |
946 | 1043 | ||
@@ -948,8 +1045,7 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
948 | * send the work_buf directly, otherwise try to do a gather | 1045 | * send the work_buf directly, otherwise try to do a gather |
949 | * write. | 1046 | * write. |
950 | */ | 1047 | */ |
951 | if (val == (map->work_buf + map->format.pad_bytes + | 1048 | if (val == work_val) |
952 | map->format.reg_bytes)) | ||
953 | ret = map->bus->write(map->bus_context, map->work_buf, | 1049 | ret = map->bus->write(map->bus_context, map->work_buf, |
954 | map->format.reg_bytes + | 1050 | map->format.reg_bytes + |
955 | map->format.pad_bytes + | 1051 | map->format.pad_bytes + |
@@ -981,14 +1077,62 @@ static int _regmap_raw_write(struct regmap *map, unsigned int reg, | |||
981 | return ret; | 1077 | return ret; |
982 | } | 1078 | } |
983 | 1079 | ||
1080 | static int _regmap_bus_formatted_write(void *context, unsigned int reg, | ||
1081 | unsigned int val) | ||
1082 | { | ||
1083 | int ret; | ||
1084 | struct regmap_range_node *range; | ||
1085 | struct regmap *map = context; | ||
1086 | |||
1087 | BUG_ON(!map->bus || !map->format.format_write); | ||
1088 | |||
1089 | range = _regmap_range_lookup(map, reg); | ||
1090 | if (range) { | ||
1091 | ret = _regmap_select_page(map, ®, range, 1); | ||
1092 | if (ret != 0) | ||
1093 | return ret; | ||
1094 | } | ||
1095 | |||
1096 | map->format.format_write(map, reg, val); | ||
1097 | |||
1098 | trace_regmap_hw_write_start(map->dev, reg, 1); | ||
1099 | |||
1100 | ret = map->bus->write(map->bus_context, map->work_buf, | ||
1101 | map->format.buf_size); | ||
1102 | |||
1103 | trace_regmap_hw_write_done(map->dev, reg, 1); | ||
1104 | |||
1105 | return ret; | ||
1106 | } | ||
1107 | |||
1108 | static int _regmap_bus_raw_write(void *context, unsigned int reg, | ||
1109 | unsigned int val) | ||
1110 | { | ||
1111 | struct regmap *map = context; | ||
1112 | |||
1113 | BUG_ON(!map->bus || !map->format.format_val); | ||
1114 | |||
1115 | map->format.format_val(map->work_buf + map->format.reg_bytes | ||
1116 | + map->format.pad_bytes, val, 0); | ||
1117 | return _regmap_raw_write(map, reg, | ||
1118 | map->work_buf + | ||
1119 | map->format.reg_bytes + | ||
1120 | map->format.pad_bytes, | ||
1121 | map->format.val_bytes, false); | ||
1122 | } | ||
1123 | |||
1124 | static inline void *_regmap_map_get_context(struct regmap *map) | ||
1125 | { | ||
1126 | return (map->bus) ? map : map->bus_context; | ||
1127 | } | ||
1128 | |||
984 | int _regmap_write(struct regmap *map, unsigned int reg, | 1129 | int _regmap_write(struct regmap *map, unsigned int reg, |
985 | unsigned int val) | 1130 | unsigned int val) |
986 | { | 1131 | { |
987 | struct regmap_range_node *range; | ||
988 | int ret; | 1132 | int ret; |
989 | BUG_ON(!map->format.format_write && !map->format.format_val); | 1133 | void *context = _regmap_map_get_context(map); |
990 | 1134 | ||
991 | if (!map->cache_bypass && map->format.format_write) { | 1135 | if (!map->cache_bypass && !map->defer_caching) { |
992 | ret = regcache_write(map, reg, val); | 1136 | ret = regcache_write(map, reg, val); |
993 | if (ret != 0) | 1137 | if (ret != 0) |
994 | return ret; | 1138 | return ret; |
@@ -1005,33 +1149,7 @@ int _regmap_write(struct regmap *map, unsigned int reg, | |||
1005 | 1149 | ||
1006 | trace_regmap_reg_write(map->dev, reg, val); | 1150 | trace_regmap_reg_write(map->dev, reg, val); |
1007 | 1151 | ||
1008 | if (map->format.format_write) { | 1152 | return map->reg_write(context, reg, val); |
1009 | range = _regmap_range_lookup(map, reg); | ||
1010 | if (range) { | ||
1011 | ret = _regmap_select_page(map, ®, range, 1); | ||
1012 | if (ret != 0) | ||
1013 | return ret; | ||
1014 | } | ||
1015 | |||
1016 | map->format.format_write(map, reg, val); | ||
1017 | |||
1018 | trace_regmap_hw_write_start(map->dev, reg, 1); | ||
1019 | |||
1020 | ret = map->bus->write(map->bus_context, map->work_buf, | ||
1021 | map->format.buf_size); | ||
1022 | |||
1023 | trace_regmap_hw_write_done(map->dev, reg, 1); | ||
1024 | |||
1025 | return ret; | ||
1026 | } else { | ||
1027 | map->format.format_val(map->work_buf + map->format.reg_bytes | ||
1028 | + map->format.pad_bytes, val, 0); | ||
1029 | return _regmap_raw_write(map, reg, | ||
1030 | map->work_buf + | ||
1031 | map->format.reg_bytes + | ||
1032 | map->format.pad_bytes, | ||
1033 | map->format.val_bytes); | ||
1034 | } | ||
1035 | } | 1153 | } |
1036 | 1154 | ||
1037 | /** | 1155 | /** |
@@ -1082,6 +1200,8 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
1082 | { | 1200 | { |
1083 | int ret; | 1201 | int ret; |
1084 | 1202 | ||
1203 | if (!map->bus) | ||
1204 | return -EINVAL; | ||
1085 | if (val_len % map->format.val_bytes) | 1205 | if (val_len % map->format.val_bytes) |
1086 | return -EINVAL; | 1206 | return -EINVAL; |
1087 | if (reg % map->reg_stride) | 1207 | if (reg % map->reg_stride) |
@@ -1089,7 +1209,7 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, | |||
1089 | 1209 | ||
1090 | map->lock(map->lock_arg); | 1210 | map->lock(map->lock_arg); |
1091 | 1211 | ||
1092 | ret = _regmap_raw_write(map, reg, val, val_len); | 1212 | ret = _regmap_raw_write(map, reg, val, val_len, false); |
1093 | 1213 | ||
1094 | map->unlock(map->lock_arg); | 1214 | map->unlock(map->lock_arg); |
1095 | 1215 | ||
@@ -1106,7 +1226,7 @@ EXPORT_SYMBOL_GPL(regmap_raw_write); | |||
1106 | * @val_count: Number of registers to write | 1226 | * @val_count: Number of registers to write |
1107 | * | 1227 | * |
1108 | * This function is intended to be used for writing a large block of | 1228 | * This function is intended to be used for writing a large block of |
1109 | * data to be device either in single transfer or multiple transfer. | 1229 | * data to the device either in single transfer or multiple transfer. |
1110 | * | 1230 | * |
1111 | * A value of zero will be returned on success, a negative errno will | 1231 | * A value of zero will be returned on success, a negative errno will |
1112 | * be returned in error cases. | 1232 | * be returned in error cases. |
@@ -1118,6 +1238,8 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1118 | size_t val_bytes = map->format.val_bytes; | 1238 | size_t val_bytes = map->format.val_bytes; |
1119 | void *wval; | 1239 | void *wval; |
1120 | 1240 | ||
1241 | if (!map->bus) | ||
1242 | return -EINVAL; | ||
1121 | if (!map->format.parse_val) | 1243 | if (!map->format.parse_val) |
1122 | return -EINVAL; | 1244 | return -EINVAL; |
1123 | if (reg % map->reg_stride) | 1245 | if (reg % map->reg_stride) |
@@ -1145,14 +1267,15 @@ int regmap_bulk_write(struct regmap *map, unsigned int reg, const void *val, | |||
1145 | if (map->use_single_rw) { | 1267 | if (map->use_single_rw) { |
1146 | for (i = 0; i < val_count; i++) { | 1268 | for (i = 0; i < val_count; i++) { |
1147 | ret = regmap_raw_write(map, | 1269 | ret = regmap_raw_write(map, |
1148 | reg + (i * map->reg_stride), | 1270 | reg + (i * map->reg_stride), |
1149 | val + (i * val_bytes), | 1271 | val + (i * val_bytes), |
1150 | val_bytes); | 1272 | val_bytes); |
1151 | if (ret != 0) | 1273 | if (ret != 0) |
1152 | return ret; | 1274 | return ret; |
1153 | } | 1275 | } |
1154 | } else { | 1276 | } else { |
1155 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count); | 1277 | ret = _regmap_raw_write(map, reg, wval, val_bytes * val_count, |
1278 | false); | ||
1156 | } | 1279 | } |
1157 | 1280 | ||
1158 | if (val_bytes != 1) | 1281 | if (val_bytes != 1) |
@@ -1164,6 +1287,48 @@ out: | |||
1164 | } | 1287 | } |
1165 | EXPORT_SYMBOL_GPL(regmap_bulk_write); | 1288 | EXPORT_SYMBOL_GPL(regmap_bulk_write); |
1166 | 1289 | ||
1290 | /** | ||
1291 | * regmap_raw_write_async(): Write raw values to one or more registers | ||
1292 | * asynchronously | ||
1293 | * | ||
1294 | * @map: Register map to write to | ||
1295 | * @reg: Initial register to write to | ||
1296 | * @val: Block of data to be written, laid out for direct transmission to the | ||
1297 | * device. Must be valid until regmap_async_complete() is called. | ||
1298 | * @val_len: Length of data pointed to by val. | ||
1299 | * | ||
1300 | * This function is intended to be used for things like firmware | ||
1301 | * download where a large block of data needs to be transferred to the | ||
1302 | * device. No formatting will be done on the data provided. | ||
1303 | * | ||
1304 | * If supported by the underlying bus the write will be scheduled | ||
1305 | * asynchronously, helping maximise I/O speed on higher speed buses | ||
1306 | * like SPI. regmap_async_complete() can be called to ensure that all | ||
1307 | * asynchrnous writes have been completed. | ||
1308 | * | ||
1309 | * A value of zero will be returned on success, a negative errno will | ||
1310 | * be returned in error cases. | ||
1311 | */ | ||
1312 | int regmap_raw_write_async(struct regmap *map, unsigned int reg, | ||
1313 | const void *val, size_t val_len) | ||
1314 | { | ||
1315 | int ret; | ||
1316 | |||
1317 | if (val_len % map->format.val_bytes) | ||
1318 | return -EINVAL; | ||
1319 | if (reg % map->reg_stride) | ||
1320 | return -EINVAL; | ||
1321 | |||
1322 | map->lock(map->lock_arg); | ||
1323 | |||
1324 | ret = _regmap_raw_write(map, reg, val, val_len, true); | ||
1325 | |||
1326 | map->unlock(map->lock_arg); | ||
1327 | |||
1328 | return ret; | ||
1329 | } | ||
1330 | EXPORT_SYMBOL_GPL(regmap_raw_write_async); | ||
1331 | |||
1167 | static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | 1332 | static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, |
1168 | unsigned int val_len) | 1333 | unsigned int val_len) |
1169 | { | 1334 | { |
@@ -1171,6 +1336,8 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
1171 | u8 *u8 = map->work_buf; | 1336 | u8 *u8 = map->work_buf; |
1172 | int ret; | 1337 | int ret; |
1173 | 1338 | ||
1339 | BUG_ON(!map->bus); | ||
1340 | |||
1174 | range = _regmap_range_lookup(map, reg); | 1341 | range = _regmap_range_lookup(map, reg); |
1175 | if (range) { | 1342 | if (range) { |
1176 | ret = _regmap_select_page(map, ®, range, | 1343 | ret = _regmap_select_page(map, ®, range, |
@@ -1202,10 +1369,29 @@ static int _regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
1202 | return ret; | 1369 | return ret; |
1203 | } | 1370 | } |
1204 | 1371 | ||
1372 | static int _regmap_bus_read(void *context, unsigned int reg, | ||
1373 | unsigned int *val) | ||
1374 | { | ||
1375 | int ret; | ||
1376 | struct regmap *map = context; | ||
1377 | |||
1378 | if (!map->format.parse_val) | ||
1379 | return -EINVAL; | ||
1380 | |||
1381 | ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); | ||
1382 | if (ret == 0) | ||
1383 | *val = map->format.parse_val(map->work_buf); | ||
1384 | |||
1385 | return ret; | ||
1386 | } | ||
1387 | |||
1205 | static int _regmap_read(struct regmap *map, unsigned int reg, | 1388 | static int _regmap_read(struct regmap *map, unsigned int reg, |
1206 | unsigned int *val) | 1389 | unsigned int *val) |
1207 | { | 1390 | { |
1208 | int ret; | 1391 | int ret; |
1392 | void *context = _regmap_map_get_context(map); | ||
1393 | |||
1394 | BUG_ON(!map->reg_read); | ||
1209 | 1395 | ||
1210 | if (!map->cache_bypass) { | 1396 | if (!map->cache_bypass) { |
1211 | ret = regcache_read(map, reg, val); | 1397 | ret = regcache_read(map, reg, val); |
@@ -1213,26 +1399,21 @@ static int _regmap_read(struct regmap *map, unsigned int reg, | |||
1213 | return 0; | 1399 | return 0; |
1214 | } | 1400 | } |
1215 | 1401 | ||
1216 | if (!map->format.parse_val) | ||
1217 | return -EINVAL; | ||
1218 | |||
1219 | if (map->cache_only) | 1402 | if (map->cache_only) |
1220 | return -EBUSY; | 1403 | return -EBUSY; |
1221 | 1404 | ||
1222 | ret = _regmap_raw_read(map, reg, map->work_buf, map->format.val_bytes); | 1405 | ret = map->reg_read(context, reg, val); |
1223 | if (ret == 0) { | 1406 | if (ret == 0) { |
1224 | *val = map->format.parse_val(map->work_buf); | ||
1225 | |||
1226 | #ifdef LOG_DEVICE | 1407 | #ifdef LOG_DEVICE |
1227 | if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) | 1408 | if (strcmp(dev_name(map->dev), LOG_DEVICE) == 0) |
1228 | dev_info(map->dev, "%x => %x\n", reg, *val); | 1409 | dev_info(map->dev, "%x => %x\n", reg, *val); |
1229 | #endif | 1410 | #endif |
1230 | 1411 | ||
1231 | trace_regmap_reg_read(map->dev, reg, *val); | 1412 | trace_regmap_reg_read(map->dev, reg, *val); |
1232 | } | ||
1233 | 1413 | ||
1234 | if (ret == 0 && !map->cache_bypass) | 1414 | if (!map->cache_bypass) |
1235 | regcache_write(map, reg, *val); | 1415 | regcache_write(map, reg, *val); |
1416 | } | ||
1236 | 1417 | ||
1237 | return ret; | 1418 | return ret; |
1238 | } | 1419 | } |
@@ -1283,6 +1464,8 @@ int regmap_raw_read(struct regmap *map, unsigned int reg, void *val, | |||
1283 | unsigned int v; | 1464 | unsigned int v; |
1284 | int ret, i; | 1465 | int ret, i; |
1285 | 1466 | ||
1467 | if (!map->bus) | ||
1468 | return -EINVAL; | ||
1286 | if (val_len % map->format.val_bytes) | 1469 | if (val_len % map->format.val_bytes) |
1287 | return -EINVAL; | 1470 | return -EINVAL; |
1288 | if (reg % map->reg_stride) | 1471 | if (reg % map->reg_stride) |
@@ -1334,6 +1517,8 @@ int regmap_bulk_read(struct regmap *map, unsigned int reg, void *val, | |||
1334 | size_t val_bytes = map->format.val_bytes; | 1517 | size_t val_bytes = map->format.val_bytes; |
1335 | bool vol = regmap_volatile_range(map, reg, val_count); | 1518 | bool vol = regmap_volatile_range(map, reg, val_count); |
1336 | 1519 | ||
1520 | if (!map->bus) | ||
1521 | return -EINVAL; | ||
1337 | if (!map->format.parse_val) | 1522 | if (!map->format.parse_val) |
1338 | return -EINVAL; | 1523 | return -EINVAL; |
1339 | if (reg % map->reg_stride) | 1524 | if (reg % map->reg_stride) |
@@ -1450,6 +1635,68 @@ int regmap_update_bits_check(struct regmap *map, unsigned int reg, | |||
1450 | } | 1635 | } |
1451 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); | 1636 | EXPORT_SYMBOL_GPL(regmap_update_bits_check); |
1452 | 1637 | ||
1638 | void regmap_async_complete_cb(struct regmap_async *async, int ret) | ||
1639 | { | ||
1640 | struct regmap *map = async->map; | ||
1641 | bool wake; | ||
1642 | |||
1643 | spin_lock(&map->async_lock); | ||
1644 | |||
1645 | list_del(&async->list); | ||
1646 | wake = list_empty(&map->async_list); | ||
1647 | |||
1648 | if (ret != 0) | ||
1649 | map->async_ret = ret; | ||
1650 | |||
1651 | spin_unlock(&map->async_lock); | ||
1652 | |||
1653 | schedule_work(&async->cleanup); | ||
1654 | |||
1655 | if (wake) | ||
1656 | wake_up(&map->async_waitq); | ||
1657 | } | ||
1658 | EXPORT_SYMBOL_GPL(regmap_async_complete_cb); | ||
1659 | |||
1660 | static int regmap_async_is_done(struct regmap *map) | ||
1661 | { | ||
1662 | unsigned long flags; | ||
1663 | int ret; | ||
1664 | |||
1665 | spin_lock_irqsave(&map->async_lock, flags); | ||
1666 | ret = list_empty(&map->async_list); | ||
1667 | spin_unlock_irqrestore(&map->async_lock, flags); | ||
1668 | |||
1669 | return ret; | ||
1670 | } | ||
1671 | |||
1672 | /** | ||
1673 | * regmap_async_complete: Ensure all asynchronous I/O has completed. | ||
1674 | * | ||
1675 | * @map: Map to operate on. | ||
1676 | * | ||
1677 | * Blocks until any pending asynchronous I/O has completed. Returns | ||
1678 | * an error code for any failed I/O operations. | ||
1679 | */ | ||
1680 | int regmap_async_complete(struct regmap *map) | ||
1681 | { | ||
1682 | unsigned long flags; | ||
1683 | int ret; | ||
1684 | |||
1685 | /* Nothing to do with no async support */ | ||
1686 | if (!map->bus->async_write) | ||
1687 | return 0; | ||
1688 | |||
1689 | wait_event(map->async_waitq, regmap_async_is_done(map)); | ||
1690 | |||
1691 | spin_lock_irqsave(&map->async_lock, flags); | ||
1692 | ret = map->async_ret; | ||
1693 | map->async_ret = 0; | ||
1694 | spin_unlock_irqrestore(&map->async_lock, flags); | ||
1695 | |||
1696 | return ret; | ||
1697 | } | ||
1698 | EXPORT_SYMBOL_GPL(regmap_async_complete); | ||
1699 | |||
1453 | /** | 1700 | /** |
1454 | * regmap_register_patch: Register and apply register updates to be applied | 1701 | * regmap_register_patch: Register and apply register updates to be applied |
1455 | * on device initialistion | 1702 | * on device initialistion |
diff --git a/drivers/bcma/bcma_private.h b/drivers/bcma/bcma_private.h index 19e3fbfd5757..cb0c45488572 100644 --- a/drivers/bcma/bcma_private.h +++ b/drivers/bcma/bcma_private.h | |||
@@ -94,11 +94,16 @@ void bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc); | |||
94 | #ifdef CONFIG_BCMA_DRIVER_GPIO | 94 | #ifdef CONFIG_BCMA_DRIVER_GPIO |
95 | /* driver_gpio.c */ | 95 | /* driver_gpio.c */ |
96 | int bcma_gpio_init(struct bcma_drv_cc *cc); | 96 | int bcma_gpio_init(struct bcma_drv_cc *cc); |
97 | int bcma_gpio_unregister(struct bcma_drv_cc *cc); | ||
97 | #else | 98 | #else |
98 | static inline int bcma_gpio_init(struct bcma_drv_cc *cc) | 99 | static inline int bcma_gpio_init(struct bcma_drv_cc *cc) |
99 | { | 100 | { |
100 | return -ENOTSUPP; | 101 | return -ENOTSUPP; |
101 | } | 102 | } |
103 | static inline int bcma_gpio_unregister(struct bcma_drv_cc *cc) | ||
104 | { | ||
105 | return 0; | ||
106 | } | ||
102 | #endif /* CONFIG_BCMA_DRIVER_GPIO */ | 107 | #endif /* CONFIG_BCMA_DRIVER_GPIO */ |
103 | 108 | ||
104 | #endif | 109 | #endif |
diff --git a/drivers/bcma/driver_chipcommon_nflash.c b/drivers/bcma/driver_chipcommon_nflash.c index dbda91e4dff5..1f0b83e18f68 100644 --- a/drivers/bcma/driver_chipcommon_nflash.c +++ b/drivers/bcma/driver_chipcommon_nflash.c | |||
@@ -21,7 +21,7 @@ int bcma_nflash_init(struct bcma_drv_cc *cc) | |||
21 | struct bcma_bus *bus = cc->core->bus; | 21 | struct bcma_bus *bus = cc->core->bus; |
22 | 22 | ||
23 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && | 23 | if (bus->chipinfo.id != BCMA_CHIP_ID_BCM4706 && |
24 | cc->core->id.rev != 0x38) { | 24 | cc->core->id.rev != 38) { |
25 | bcma_err(bus, "NAND flash on unsupported board!\n"); | 25 | bcma_err(bus, "NAND flash on unsupported board!\n"); |
26 | return -ENOTSUPP; | 26 | return -ENOTSUPP; |
27 | } | 27 | } |
diff --git a/drivers/bcma/driver_gpio.c b/drivers/bcma/driver_gpio.c index 9a6f585da2d9..71f755c06fc6 100644 --- a/drivers/bcma/driver_gpio.c +++ b/drivers/bcma/driver_gpio.c | |||
@@ -96,3 +96,8 @@ int bcma_gpio_init(struct bcma_drv_cc *cc) | |||
96 | 96 | ||
97 | return gpiochip_add(chip); | 97 | return gpiochip_add(chip); |
98 | } | 98 | } |
99 | |||
100 | int bcma_gpio_unregister(struct bcma_drv_cc *cc) | ||
101 | { | ||
102 | return gpiochip_remove(&cc->gpio); | ||
103 | } | ||
diff --git a/drivers/bcma/main.c b/drivers/bcma/main.c index 4a92f647b58b..324f9debda88 100644 --- a/drivers/bcma/main.c +++ b/drivers/bcma/main.c | |||
@@ -268,6 +268,13 @@ int bcma_bus_register(struct bcma_bus *bus) | |||
268 | void bcma_bus_unregister(struct bcma_bus *bus) | 268 | void bcma_bus_unregister(struct bcma_bus *bus) |
269 | { | 269 | { |
270 | struct bcma_device *cores[3]; | 270 | struct bcma_device *cores[3]; |
271 | int err; | ||
272 | |||
273 | err = bcma_gpio_unregister(&bus->drv_cc); | ||
274 | if (err == -EBUSY) | ||
275 | bcma_err(bus, "Some GPIOs are still in use.\n"); | ||
276 | else if (err) | ||
277 | bcma_err(bus, "Can not unregister GPIO driver: %i\n", err); | ||
271 | 278 | ||
272 | cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); | 279 | cores[0] = bcma_find_core(bus, BCMA_CORE_MIPS_74K); |
273 | cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); | 280 | cores[1] = bcma_find_core(bus, BCMA_CORE_PCIE); |
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c index f58a4a4b4dfb..2b8303ad63c9 100644 --- a/drivers/block/drbd/drbd_req.c +++ b/drivers/block/drbd/drbd_req.c | |||
@@ -168,7 +168,7 @@ static void wake_all_senders(struct drbd_tconn *tconn) { | |||
168 | } | 168 | } |
169 | 169 | ||
170 | /* must hold resource->req_lock */ | 170 | /* must hold resource->req_lock */ |
171 | static void start_new_tl_epoch(struct drbd_tconn *tconn) | 171 | void start_new_tl_epoch(struct drbd_tconn *tconn) |
172 | { | 172 | { |
173 | /* no point closing an epoch, if it is empty, anyways. */ | 173 | /* no point closing an epoch, if it is empty, anyways. */ |
174 | if (tconn->current_tle_writes == 0) | 174 | if (tconn->current_tle_writes == 0) |
diff --git a/drivers/block/drbd/drbd_req.h b/drivers/block/drbd/drbd_req.h index 016de6b8bb57..c08d22964d06 100644 --- a/drivers/block/drbd/drbd_req.h +++ b/drivers/block/drbd/drbd_req.h | |||
@@ -267,6 +267,7 @@ struct bio_and_error { | |||
267 | int error; | 267 | int error; |
268 | }; | 268 | }; |
269 | 269 | ||
270 | extern void start_new_tl_epoch(struct drbd_tconn *tconn); | ||
270 | extern void drbd_req_destroy(struct kref *kref); | 271 | extern void drbd_req_destroy(struct kref *kref); |
271 | extern void _req_may_be_done(struct drbd_request *req, | 272 | extern void _req_may_be_done(struct drbd_request *req, |
272 | struct bio_and_error *m); | 273 | struct bio_and_error *m); |
diff --git a/drivers/block/drbd/drbd_state.c b/drivers/block/drbd/drbd_state.c index 53bf6182bac4..0fe220cfb9e9 100644 --- a/drivers/block/drbd/drbd_state.c +++ b/drivers/block/drbd/drbd_state.c | |||
@@ -931,6 +931,7 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, | |||
931 | enum drbd_state_rv rv = SS_SUCCESS; | 931 | enum drbd_state_rv rv = SS_SUCCESS; |
932 | enum sanitize_state_warnings ssw; | 932 | enum sanitize_state_warnings ssw; |
933 | struct after_state_chg_work *ascw; | 933 | struct after_state_chg_work *ascw; |
934 | bool did_remote, should_do_remote; | ||
934 | 935 | ||
935 | os = drbd_read_state(mdev); | 936 | os = drbd_read_state(mdev); |
936 | 937 | ||
@@ -981,11 +982,17 @@ __drbd_set_state(struct drbd_conf *mdev, union drbd_state ns, | |||
981 | (os.disk != D_DISKLESS && ns.disk == D_DISKLESS)) | 982 | (os.disk != D_DISKLESS && ns.disk == D_DISKLESS)) |
982 | atomic_inc(&mdev->local_cnt); | 983 | atomic_inc(&mdev->local_cnt); |
983 | 984 | ||
985 | did_remote = drbd_should_do_remote(mdev->state); | ||
984 | mdev->state.i = ns.i; | 986 | mdev->state.i = ns.i; |
987 | should_do_remote = drbd_should_do_remote(mdev->state); | ||
985 | mdev->tconn->susp = ns.susp; | 988 | mdev->tconn->susp = ns.susp; |
986 | mdev->tconn->susp_nod = ns.susp_nod; | 989 | mdev->tconn->susp_nod = ns.susp_nod; |
987 | mdev->tconn->susp_fen = ns.susp_fen; | 990 | mdev->tconn->susp_fen = ns.susp_fen; |
988 | 991 | ||
992 | /* put replicated vs not-replicated requests in seperate epochs */ | ||
993 | if (did_remote != should_do_remote) | ||
994 | start_new_tl_epoch(mdev->tconn); | ||
995 | |||
989 | if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING) | 996 | if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING) |
990 | drbd_print_uuids(mdev, "attached to UUIDs"); | 997 | drbd_print_uuids(mdev, "attached to UUIDs"); |
991 | 998 | ||
diff --git a/drivers/block/mtip32xx/mtip32xx.c b/drivers/block/mtip32xx/mtip32xx.c index 9694dd99bbbc..3fd100990453 100644 --- a/drivers/block/mtip32xx/mtip32xx.c +++ b/drivers/block/mtip32xx/mtip32xx.c | |||
@@ -626,12 +626,13 @@ static void mtip_timeout_function(unsigned long int data) | |||
626 | } | 626 | } |
627 | } | 627 | } |
628 | 628 | ||
629 | if (cmdto_cnt && !test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { | 629 | if (cmdto_cnt) { |
630 | print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); | 630 | print_tags(port->dd, "timed out", tagaccum, cmdto_cnt); |
631 | 631 | if (!test_bit(MTIP_PF_IC_ACTIVE_BIT, &port->flags)) { | |
632 | mtip_restart_port(port); | 632 | mtip_restart_port(port); |
633 | wake_up_interruptible(&port->svc_wait); | ||
634 | } | ||
633 | clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); | 635 | clear_bit(MTIP_PF_EH_ACTIVE_BIT, &port->flags); |
634 | wake_up_interruptible(&port->svc_wait); | ||
635 | } | 636 | } |
636 | 637 | ||
637 | if (port->ic_pause_timer) { | 638 | if (port->ic_pause_timer) { |
@@ -3887,7 +3888,12 @@ static int mtip_block_remove(struct driver_data *dd) | |||
3887 | * Delete our gendisk structure. This also removes the device | 3888 | * Delete our gendisk structure. This also removes the device |
3888 | * from /dev | 3889 | * from /dev |
3889 | */ | 3890 | */ |
3890 | del_gendisk(dd->disk); | 3891 | if (dd->disk) { |
3892 | if (dd->disk->queue) | ||
3893 | del_gendisk(dd->disk); | ||
3894 | else | ||
3895 | put_disk(dd->disk); | ||
3896 | } | ||
3891 | 3897 | ||
3892 | spin_lock(&rssd_index_lock); | 3898 | spin_lock(&rssd_index_lock); |
3893 | ida_remove(&rssd_index_ida, dd->index); | 3899 | ida_remove(&rssd_index_ida, dd->index); |
@@ -3921,7 +3927,13 @@ static int mtip_block_shutdown(struct driver_data *dd) | |||
3921 | "Shutting down %s ...\n", dd->disk->disk_name); | 3927 | "Shutting down %s ...\n", dd->disk->disk_name); |
3922 | 3928 | ||
3923 | /* Delete our gendisk structure, and cleanup the blk queue. */ | 3929 | /* Delete our gendisk structure, and cleanup the blk queue. */ |
3924 | del_gendisk(dd->disk); | 3930 | if (dd->disk) { |
3931 | if (dd->disk->queue) | ||
3932 | del_gendisk(dd->disk); | ||
3933 | else | ||
3934 | put_disk(dd->disk); | ||
3935 | } | ||
3936 | |||
3925 | 3937 | ||
3926 | spin_lock(&rssd_index_lock); | 3938 | spin_lock(&rssd_index_lock); |
3927 | ida_remove(&rssd_index_ida, dd->index); | 3939 | ida_remove(&rssd_index_ida, dd->index); |
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 564156a8e572..5814deb6963d 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c | |||
@@ -461,7 +461,7 @@ static int generic_request(struct vdc_port *port, u8 op, void *buf, int len) | |||
461 | int op_len, err; | 461 | int op_len, err; |
462 | void *req_buf; | 462 | void *req_buf; |
463 | 463 | ||
464 | if (!(((u64)1 << ((u64)op - 1)) & port->operations)) | 464 | if (!(((u64)1 << (u64)op) & port->operations)) |
465 | return -EOPNOTSUPP; | 465 | return -EOPNOTSUPP; |
466 | 466 | ||
467 | switch (op) { | 467 | switch (op) { |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 9d8409c02082..8ad21a25bc0d 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
@@ -889,6 +889,7 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
889 | { | 889 | { |
890 | struct virtio_blk *vblk = vdev->priv; | 890 | struct virtio_blk *vblk = vdev->priv; |
891 | int index = vblk->index; | 891 | int index = vblk->index; |
892 | int refc; | ||
892 | 893 | ||
893 | /* Prevent config work handler from accessing the device. */ | 894 | /* Prevent config work handler from accessing the device. */ |
894 | mutex_lock(&vblk->config_lock); | 895 | mutex_lock(&vblk->config_lock); |
@@ -903,11 +904,15 @@ static void virtblk_remove(struct virtio_device *vdev) | |||
903 | 904 | ||
904 | flush_work(&vblk->config_work); | 905 | flush_work(&vblk->config_work); |
905 | 906 | ||
907 | refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount); | ||
906 | put_disk(vblk->disk); | 908 | put_disk(vblk->disk); |
907 | mempool_destroy(vblk->pool); | 909 | mempool_destroy(vblk->pool); |
908 | vdev->config->del_vqs(vdev); | 910 | vdev->config->del_vqs(vdev); |
909 | kfree(vblk); | 911 | kfree(vblk); |
910 | ida_simple_remove(&vd_index_ida, index); | 912 | |
913 | /* Only free device id if we don't have any users */ | ||
914 | if (refc == 1) | ||
915 | ida_simple_remove(&vd_index_ida, index); | ||
911 | } | 916 | } |
912 | 917 | ||
913 | #ifdef CONFIG_PM | 918 | #ifdef CONFIG_PM |
diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index 74374fb762aa..5ac841ff6cc7 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c | |||
@@ -161,10 +161,12 @@ static int dispatch_rw_block_io(struct xen_blkif *blkif, | |||
161 | static void make_response(struct xen_blkif *blkif, u64 id, | 161 | static void make_response(struct xen_blkif *blkif, u64 id, |
162 | unsigned short op, int st); | 162 | unsigned short op, int st); |
163 | 163 | ||
164 | #define foreach_grant(pos, rbtree, node) \ | 164 | #define foreach_grant_safe(pos, n, rbtree, node) \ |
165 | for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node); \ | 165 | for ((pos) = container_of(rb_first((rbtree)), typeof(*(pos)), node), \ |
166 | (n) = rb_next(&(pos)->node); \ | ||
166 | &(pos)->node != NULL; \ | 167 | &(pos)->node != NULL; \ |
167 | (pos) = container_of(rb_next(&(pos)->node), typeof(*(pos)), node)) | 168 | (pos) = container_of(n, typeof(*(pos)), node), \ |
169 | (n) = (&(pos)->node != NULL) ? rb_next(&(pos)->node) : NULL) | ||
168 | 170 | ||
169 | 171 | ||
170 | static void add_persistent_gnt(struct rb_root *root, | 172 | static void add_persistent_gnt(struct rb_root *root, |
@@ -217,10 +219,11 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) | |||
217 | struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | 219 | struct gnttab_unmap_grant_ref unmap[BLKIF_MAX_SEGMENTS_PER_REQUEST]; |
218 | struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; | 220 | struct page *pages[BLKIF_MAX_SEGMENTS_PER_REQUEST]; |
219 | struct persistent_gnt *persistent_gnt; | 221 | struct persistent_gnt *persistent_gnt; |
222 | struct rb_node *n; | ||
220 | int ret = 0; | 223 | int ret = 0; |
221 | int segs_to_unmap = 0; | 224 | int segs_to_unmap = 0; |
222 | 225 | ||
223 | foreach_grant(persistent_gnt, root, node) { | 226 | foreach_grant_safe(persistent_gnt, n, root, node) { |
224 | BUG_ON(persistent_gnt->handle == | 227 | BUG_ON(persistent_gnt->handle == |
225 | BLKBACK_INVALID_HANDLE); | 228 | BLKBACK_INVALID_HANDLE); |
226 | gnttab_set_unmap_op(&unmap[segs_to_unmap], | 229 | gnttab_set_unmap_op(&unmap[segs_to_unmap], |
@@ -230,9 +233,6 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) | |||
230 | persistent_gnt->handle); | 233 | persistent_gnt->handle); |
231 | 234 | ||
232 | pages[segs_to_unmap] = persistent_gnt->page; | 235 | pages[segs_to_unmap] = persistent_gnt->page; |
233 | rb_erase(&persistent_gnt->node, root); | ||
234 | kfree(persistent_gnt); | ||
235 | num--; | ||
236 | 236 | ||
237 | if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || | 237 | if (++segs_to_unmap == BLKIF_MAX_SEGMENTS_PER_REQUEST || |
238 | !rb_next(&persistent_gnt->node)) { | 238 | !rb_next(&persistent_gnt->node)) { |
@@ -241,6 +241,10 @@ static void free_persistent_gnts(struct rb_root *root, unsigned int num) | |||
241 | BUG_ON(ret); | 241 | BUG_ON(ret); |
242 | segs_to_unmap = 0; | 242 | segs_to_unmap = 0; |
243 | } | 243 | } |
244 | |||
245 | rb_erase(&persistent_gnt->node, root); | ||
246 | kfree(persistent_gnt); | ||
247 | num--; | ||
244 | } | 248 | } |
245 | BUG_ON(num != 0); | 249 | BUG_ON(num != 0); |
246 | } | 250 | } |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index 96e9b00db081..11043c18ac5a 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
@@ -792,6 +792,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
792 | { | 792 | { |
793 | struct llist_node *all_gnts; | 793 | struct llist_node *all_gnts; |
794 | struct grant *persistent_gnt; | 794 | struct grant *persistent_gnt; |
795 | struct llist_node *n; | ||
795 | 796 | ||
796 | /* Prevent new requests being issued until we fix things up. */ | 797 | /* Prevent new requests being issued until we fix things up. */ |
797 | spin_lock_irq(&info->io_lock); | 798 | spin_lock_irq(&info->io_lock); |
@@ -804,7 +805,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
804 | /* Remove all persistent grants */ | 805 | /* Remove all persistent grants */ |
805 | if (info->persistent_gnts_c) { | 806 | if (info->persistent_gnts_c) { |
806 | all_gnts = llist_del_all(&info->persistent_gnts); | 807 | all_gnts = llist_del_all(&info->persistent_gnts); |
807 | llist_for_each_entry(persistent_gnt, all_gnts, node) { | 808 | llist_for_each_entry_safe(persistent_gnt, n, all_gnts, node) { |
808 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); | 809 | gnttab_end_foreign_access(persistent_gnt->gref, 0, 0UL); |
809 | __free_page(pfn_to_page(persistent_gnt->pfn)); | 810 | __free_page(pfn_to_page(persistent_gnt->pfn)); |
810 | kfree(persistent_gnt); | 811 | kfree(persistent_gnt); |
@@ -835,7 +836,7 @@ static void blkif_free(struct blkfront_info *info, int suspend) | |||
835 | static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | 836 | static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, |
836 | struct blkif_response *bret) | 837 | struct blkif_response *bret) |
837 | { | 838 | { |
838 | int i; | 839 | int i = 0; |
839 | struct bio_vec *bvec; | 840 | struct bio_vec *bvec; |
840 | struct req_iterator iter; | 841 | struct req_iterator iter; |
841 | unsigned long flags; | 842 | unsigned long flags; |
@@ -852,7 +853,8 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | |||
852 | */ | 853 | */ |
853 | rq_for_each_segment(bvec, s->request, iter) { | 854 | rq_for_each_segment(bvec, s->request, iter) { |
854 | BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE); | 855 | BUG_ON((bvec->bv_offset + bvec->bv_len) > PAGE_SIZE); |
855 | i = offset >> PAGE_SHIFT; | 856 | if (bvec->bv_offset < offset) |
857 | i++; | ||
856 | BUG_ON(i >= s->req.u.rw.nr_segments); | 858 | BUG_ON(i >= s->req.u.rw.nr_segments); |
857 | shared_data = kmap_atomic( | 859 | shared_data = kmap_atomic( |
858 | pfn_to_page(s->grants_used[i]->pfn)); | 860 | pfn_to_page(s->grants_used[i]->pfn)); |
@@ -861,7 +863,7 @@ static void blkif_completion(struct blk_shadow *s, struct blkfront_info *info, | |||
861 | bvec->bv_len); | 863 | bvec->bv_len); |
862 | bvec_kunmap_irq(bvec_data, &flags); | 864 | bvec_kunmap_irq(bvec_data, &flags); |
863 | kunmap_atomic(shared_data); | 865 | kunmap_atomic(shared_data); |
864 | offset += bvec->bv_len; | 866 | offset = bvec->bv_offset + bvec->bv_len; |
865 | } | 867 | } |
866 | } | 868 | } |
867 | /* Add the persistent grant into the list of free grants */ | 869 | /* Add the persistent grant into the list of free grants */ |
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c index b00000e8aef6..33c9a44a9678 100644 --- a/drivers/bluetooth/ath3k.c +++ b/drivers/bluetooth/ath3k.c | |||
@@ -77,10 +77,15 @@ static struct usb_device_id ath3k_table[] = { | |||
77 | { USB_DEVICE(0x0CF3, 0x311D) }, | 77 | { USB_DEVICE(0x0CF3, 0x311D) }, |
78 | { USB_DEVICE(0x13d3, 0x3375) }, | 78 | { USB_DEVICE(0x13d3, 0x3375) }, |
79 | { USB_DEVICE(0x04CA, 0x3005) }, | 79 | { USB_DEVICE(0x04CA, 0x3005) }, |
80 | { USB_DEVICE(0x04CA, 0x3006) }, | ||
81 | { USB_DEVICE(0x04CA, 0x3008) }, | ||
80 | { USB_DEVICE(0x13d3, 0x3362) }, | 82 | { USB_DEVICE(0x13d3, 0x3362) }, |
81 | { USB_DEVICE(0x0CF3, 0xE004) }, | 83 | { USB_DEVICE(0x0CF3, 0xE004) }, |
82 | { USB_DEVICE(0x0930, 0x0219) }, | 84 | { USB_DEVICE(0x0930, 0x0219) }, |
83 | { USB_DEVICE(0x0489, 0xe057) }, | 85 | { USB_DEVICE(0x0489, 0xe057) }, |
86 | { USB_DEVICE(0x13d3, 0x3393) }, | ||
87 | { USB_DEVICE(0x0489, 0xe04e) }, | ||
88 | { USB_DEVICE(0x0489, 0xe056) }, | ||
84 | 89 | ||
85 | /* Atheros AR5BBU12 with sflash firmware */ | 90 | /* Atheros AR5BBU12 with sflash firmware */ |
86 | { USB_DEVICE(0x0489, 0xE02C) }, | 91 | { USB_DEVICE(0x0489, 0xE02C) }, |
@@ -104,10 +109,15 @@ static struct usb_device_id ath3k_blist_tbl[] = { | |||
104 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, | 109 | { USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 }, |
105 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 110 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
106 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 111 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
112 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | ||
113 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
107 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, | 114 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
108 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, | 115 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, |
109 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, | 116 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
110 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, | 117 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, |
118 | { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, | ||
119 | { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, | ||
120 | { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, | ||
111 | 121 | ||
112 | /* Atheros AR5BBU22 with sflash firmware */ | 122 | /* Atheros AR5BBU22 with sflash firmware */ |
113 | { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, | 123 | { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 }, |
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index a1d4ede5b892..7e351e345476 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c | |||
@@ -135,10 +135,15 @@ static struct usb_device_id blacklist_table[] = { | |||
135 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, | 135 | { USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 }, |
136 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, | 136 | { USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 }, |
137 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, | 137 | { USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 }, |
138 | { USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 }, | ||
139 | { USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 }, | ||
138 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, | 140 | { USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 }, |
139 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, | 141 | { USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 }, |
140 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, | 142 | { USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 }, |
141 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, | 143 | { USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 }, |
144 | { USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 }, | ||
145 | { USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 }, | ||
146 | { USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 }, | ||
142 | 147 | ||
143 | /* Atheros AR5BBU12 with sflash firmware */ | 148 | /* Atheros AR5BBU12 with sflash firmware */ |
144 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, | 149 | { USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE }, |
diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 684b0d53764f..ee4dbeafb377 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c | |||
@@ -2062,7 +2062,8 @@ static void virtcons_remove(struct virtio_device *vdev) | |||
2062 | /* Disable interrupts for vqs */ | 2062 | /* Disable interrupts for vqs */ |
2063 | vdev->config->reset(vdev); | 2063 | vdev->config->reset(vdev); |
2064 | /* Finish up work that's lined up */ | 2064 | /* Finish up work that's lined up */ |
2065 | cancel_work_sync(&portdev->control_work); | 2065 | if (use_multiport(portdev)) |
2066 | cancel_work_sync(&portdev->control_work); | ||
2066 | 2067 | ||
2067 | list_for_each_entry_safe(port, port2, &portdev->ports, list) | 2068 | list_for_each_entry_safe(port, port2, &portdev->ports, list) |
2068 | unplug_port(port); | 2069 | unplug_port(port); |
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c index ff004578a119..9dd2551a0a41 100644 --- a/drivers/clk/mvebu/clk-cpu.c +++ b/drivers/clk/mvebu/clk-cpu.c | |||
@@ -124,7 +124,7 @@ void __init of_cpu_clk_setup(struct device_node *node) | |||
124 | 124 | ||
125 | clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL); | 125 | clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL); |
126 | if (WARN_ON(!clks)) | 126 | if (WARN_ON(!clks)) |
127 | return; | 127 | goto clks_out; |
128 | 128 | ||
129 | for_each_node_by_type(dn, "cpu") { | 129 | for_each_node_by_type(dn, "cpu") { |
130 | struct clk_init_data init; | 130 | struct clk_init_data init; |
@@ -134,11 +134,11 @@ void __init of_cpu_clk_setup(struct device_node *node) | |||
134 | int cpu, err; | 134 | int cpu, err; |
135 | 135 | ||
136 | if (WARN_ON(!clk_name)) | 136 | if (WARN_ON(!clk_name)) |
137 | return; | 137 | goto bail_out; |
138 | 138 | ||
139 | err = of_property_read_u32(dn, "reg", &cpu); | 139 | err = of_property_read_u32(dn, "reg", &cpu); |
140 | if (WARN_ON(err)) | 140 | if (WARN_ON(err)) |
141 | return; | 141 | goto bail_out; |
142 | 142 | ||
143 | sprintf(clk_name, "cpu%d", cpu); | 143 | sprintf(clk_name, "cpu%d", cpu); |
144 | parent_clk = of_clk_get(node, 0); | 144 | parent_clk = of_clk_get(node, 0); |
@@ -167,6 +167,9 @@ void __init of_cpu_clk_setup(struct device_node *node) | |||
167 | return; | 167 | return; |
168 | bail_out: | 168 | bail_out: |
169 | kfree(clks); | 169 | kfree(clks); |
170 | while(ncpus--) | ||
171 | kfree(cpuclk[ncpus].clk_name); | ||
172 | clks_out: | ||
170 | kfree(cpuclk); | 173 | kfree(cpuclk); |
171 | } | 174 | } |
172 | 175 | ||
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86 index 934854ae5eb4..7227cd734042 100644 --- a/drivers/cpufreq/Kconfig.x86 +++ b/drivers/cpufreq/Kconfig.x86 | |||
@@ -106,7 +106,7 @@ config X86_POWERNOW_K7_ACPI | |||
106 | config X86_POWERNOW_K8 | 106 | config X86_POWERNOW_K8 |
107 | tristate "AMD Opteron/Athlon64 PowerNow!" | 107 | tristate "AMD Opteron/Athlon64 PowerNow!" |
108 | select CPU_FREQ_TABLE | 108 | select CPU_FREQ_TABLE |
109 | depends on ACPI && ACPI_PROCESSOR | 109 | depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ |
110 | help | 110 | help |
111 | This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. | 111 | This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors. |
112 | Support for K10 and newer processors is now in acpi-cpufreq. | 112 | Support for K10 and newer processors is now in acpi-cpufreq. |
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 0d048f6a2b23..7b0d49d78c61 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c | |||
@@ -1030,4 +1030,11 @@ MODULE_PARM_DESC(acpi_pstate_strict, | |||
1030 | late_initcall(acpi_cpufreq_init); | 1030 | late_initcall(acpi_cpufreq_init); |
1031 | module_exit(acpi_cpufreq_exit); | 1031 | module_exit(acpi_cpufreq_exit); |
1032 | 1032 | ||
1033 | static const struct x86_cpu_id acpi_cpufreq_ids[] = { | ||
1034 | X86_FEATURE_MATCH(X86_FEATURE_ACPI), | ||
1035 | X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE), | ||
1036 | {} | ||
1037 | }; | ||
1038 | MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids); | ||
1039 | |||
1033 | MODULE_ALIAS("acpi"); | 1040 | MODULE_ALIAS("acpi"); |
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c index 52bf36d599f5..debc5a7c8db6 100644 --- a/drivers/cpufreq/cpufreq-cpu0.c +++ b/drivers/cpufreq/cpufreq-cpu0.c | |||
@@ -71,12 +71,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, | |||
71 | } | 71 | } |
72 | 72 | ||
73 | if (cpu_reg) { | 73 | if (cpu_reg) { |
74 | rcu_read_lock(); | ||
74 | opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); | 75 | opp = opp_find_freq_ceil(cpu_dev, &freq_Hz); |
75 | if (IS_ERR(opp)) { | 76 | if (IS_ERR(opp)) { |
77 | rcu_read_unlock(); | ||
76 | pr_err("failed to find OPP for %ld\n", freq_Hz); | 78 | pr_err("failed to find OPP for %ld\n", freq_Hz); |
77 | return PTR_ERR(opp); | 79 | return PTR_ERR(opp); |
78 | } | 80 | } |
79 | volt = opp_get_voltage(opp); | 81 | volt = opp_get_voltage(opp); |
82 | rcu_read_unlock(); | ||
80 | tol = volt * voltage_tolerance / 100; | 83 | tol = volt * voltage_tolerance / 100; |
81 | volt_old = regulator_get_voltage(cpu_reg); | 84 | volt_old = regulator_get_voltage(cpu_reg); |
82 | } | 85 | } |
@@ -236,12 +239,14 @@ static int cpu0_cpufreq_driver_init(void) | |||
236 | */ | 239 | */ |
237 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) | 240 | for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++) |
238 | ; | 241 | ; |
242 | rcu_read_lock(); | ||
239 | opp = opp_find_freq_exact(cpu_dev, | 243 | opp = opp_find_freq_exact(cpu_dev, |
240 | freq_table[0].frequency * 1000, true); | 244 | freq_table[0].frequency * 1000, true); |
241 | min_uV = opp_get_voltage(opp); | 245 | min_uV = opp_get_voltage(opp); |
242 | opp = opp_find_freq_exact(cpu_dev, | 246 | opp = opp_find_freq_exact(cpu_dev, |
243 | freq_table[i-1].frequency * 1000, true); | 247 | freq_table[i-1].frequency * 1000, true); |
244 | max_uV = opp_get_voltage(opp); | 248 | max_uV = opp_get_voltage(opp); |
249 | rcu_read_unlock(); | ||
245 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); | 250 | ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV); |
246 | if (ret > 0) | 251 | if (ret > 0) |
247 | transition_latency += ret * 1000; | 252 | transition_latency += ret * 1000; |
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c index 1f3417a8322d..97102b05843f 100644 --- a/drivers/cpufreq/omap-cpufreq.c +++ b/drivers/cpufreq/omap-cpufreq.c | |||
@@ -110,13 +110,16 @@ static int omap_target(struct cpufreq_policy *policy, | |||
110 | freq = ret; | 110 | freq = ret; |
111 | 111 | ||
112 | if (mpu_reg) { | 112 | if (mpu_reg) { |
113 | rcu_read_lock(); | ||
113 | opp = opp_find_freq_ceil(mpu_dev, &freq); | 114 | opp = opp_find_freq_ceil(mpu_dev, &freq); |
114 | if (IS_ERR(opp)) { | 115 | if (IS_ERR(opp)) { |
116 | rcu_read_unlock(); | ||
115 | dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", | 117 | dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n", |
116 | __func__, freqs.new); | 118 | __func__, freqs.new); |
117 | return -EINVAL; | 119 | return -EINVAL; |
118 | } | 120 | } |
119 | volt = opp_get_voltage(opp); | 121 | volt = opp_get_voltage(opp); |
122 | rcu_read_unlock(); | ||
120 | tol = volt * OPP_TOLERANCE / 100; | 123 | tol = volt * OPP_TOLERANCE / 100; |
121 | volt_old = regulator_get_voltage(mpu_reg); | 124 | volt_old = regulator_get_voltage(mpu_reg); |
122 | } | 125 | } |
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c index fb4a7dd57f94..e1f6860e069c 100644 --- a/drivers/cpuidle/cpuidle.c +++ b/drivers/cpuidle/cpuidle.c | |||
@@ -69,24 +69,15 @@ int cpuidle_play_dead(void) | |||
69 | { | 69 | { |
70 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); | 70 | struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices); |
71 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); | 71 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev); |
72 | int i, dead_state = -1; | 72 | int i; |
73 | int power_usage = INT_MAX; | ||
74 | 73 | ||
75 | if (!drv) | 74 | if (!drv) |
76 | return -ENODEV; | 75 | return -ENODEV; |
77 | 76 | ||
78 | /* Find lowest-power state that supports long-term idle */ | 77 | /* Find lowest-power state that supports long-term idle */ |
79 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) { | 78 | for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--) |
80 | struct cpuidle_state *s = &drv->states[i]; | 79 | if (drv->states[i].enter_dead) |
81 | 80 | return drv->states[i].enter_dead(dev, i); | |
82 | if (s->power_usage < power_usage && s->enter_dead) { | ||
83 | power_usage = s->power_usage; | ||
84 | dead_state = i; | ||
85 | } | ||
86 | } | ||
87 | |||
88 | if (dead_state != -1) | ||
89 | return drv->states[dead_state].enter_dead(dev, dead_state); | ||
90 | 81 | ||
91 | return -ENODEV; | 82 | return -ENODEV; |
92 | } | 83 | } |
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c index c2b281afe0ed..422c7b69ba7c 100644 --- a/drivers/cpuidle/driver.c +++ b/drivers/cpuidle/driver.c | |||
@@ -19,34 +19,9 @@ DEFINE_SPINLOCK(cpuidle_driver_lock); | |||
19 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); | 19 | static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu); |
20 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); | 20 | static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu); |
21 | 21 | ||
22 | static void set_power_states(struct cpuidle_driver *drv) | ||
23 | { | ||
24 | int i; | ||
25 | |||
26 | /* | ||
27 | * cpuidle driver should set the drv->power_specified bit | ||
28 | * before registering if the driver provides | ||
29 | * power_usage numbers. | ||
30 | * | ||
31 | * If power_specified is not set, | ||
32 | * we fill in power_usage with decreasing values as the | ||
33 | * cpuidle code has an implicit assumption that state Cn | ||
34 | * uses less power than C(n-1). | ||
35 | * | ||
36 | * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned | ||
37 | * an power value of -1. So we use -2, -3, etc, for other | ||
38 | * c-states. | ||
39 | */ | ||
40 | for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) | ||
41 | drv->states[i].power_usage = -1 - i; | ||
42 | } | ||
43 | |||
44 | static void __cpuidle_driver_init(struct cpuidle_driver *drv) | 22 | static void __cpuidle_driver_init(struct cpuidle_driver *drv) |
45 | { | 23 | { |
46 | drv->refcnt = 0; | 24 | drv->refcnt = 0; |
47 | |||
48 | if (!drv->power_specified) | ||
49 | set_power_states(drv); | ||
50 | } | 25 | } |
51 | 26 | ||
52 | static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) | 27 | static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu) |
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c index 20ea33afdda1..fe343a06b7da 100644 --- a/drivers/cpuidle/governors/menu.c +++ b/drivers/cpuidle/governors/menu.c | |||
@@ -312,7 +312,6 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
312 | { | 312 | { |
313 | struct menu_device *data = &__get_cpu_var(menu_devices); | 313 | struct menu_device *data = &__get_cpu_var(menu_devices); |
314 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); | 314 | int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY); |
315 | int power_usage = INT_MAX; | ||
316 | int i; | 315 | int i; |
317 | int multiplier; | 316 | int multiplier; |
318 | struct timespec t; | 317 | struct timespec t; |
@@ -383,11 +382,8 @@ static int menu_select(struct cpuidle_driver *drv, struct cpuidle_device *dev) | |||
383 | if (s->exit_latency * multiplier > data->predicted_us) | 382 | if (s->exit_latency * multiplier > data->predicted_us) |
384 | continue; | 383 | continue; |
385 | 384 | ||
386 | if (s->power_usage < power_usage) { | 385 | data->last_state_idx = i; |
387 | power_usage = s->power_usage; | 386 | data->exit_us = s->exit_latency; |
388 | data->last_state_idx = i; | ||
389 | data->exit_us = s->exit_latency; | ||
390 | } | ||
391 | } | 387 | } |
392 | 388 | ||
393 | /* not deepest C-state chosen for low predicted residency */ | 389 | /* not deepest C-state chosen for low predicted residency */ |
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c index 340942946106..428754af6236 100644 --- a/drivers/cpuidle/sysfs.c +++ b/drivers/cpuidle/sysfs.c | |||
@@ -374,7 +374,7 @@ static int cpuidle_add_state_sysfs(struct cpuidle_device *device) | |||
374 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); | 374 | struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device); |
375 | 375 | ||
376 | /* state statistics */ | 376 | /* state statistics */ |
377 | for (i = 0; i < drv->state_count; i++) { | 377 | for (i = 0; i < device->state_count; i++) { |
378 | kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); | 378 | kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL); |
379 | if (!kobj) | 379 | if (!kobj) |
380 | goto error_state; | 380 | goto error_state; |
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 53766f39aadd..3b367973a802 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c | |||
@@ -994,6 +994,11 @@ module_exit(devfreq_exit); | |||
994 | * @freq: The frequency given to target function | 994 | * @freq: The frequency given to target function |
995 | * @flags: Flags handed from devfreq framework. | 995 | * @flags: Flags handed from devfreq framework. |
996 | * | 996 | * |
997 | * Locking: This function must be called under rcu_read_lock(). opp is a rcu | ||
998 | * protected pointer. The reason for the same is that the opp pointer which is | ||
999 | * returned will remain valid for use with opp_get_{voltage, freq} only while | ||
1000 | * under the locked area. The pointer returned must be used prior to unlocking | ||
1001 | * with rcu_read_unlock() to maintain the integrity of the pointer. | ||
997 | */ | 1002 | */ |
998 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, | 1003 | struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq, |
999 | u32 flags) | 1004 | u32 flags) |
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c index 80c745e83082..46d94e9e95b5 100644 --- a/drivers/devfreq/exynos4_bus.c +++ b/drivers/devfreq/exynos4_bus.c | |||
@@ -73,6 +73,16 @@ enum busclk_level_idx { | |||
73 | #define EX4210_LV_NUM (LV_2 + 1) | 73 | #define EX4210_LV_NUM (LV_2 + 1) |
74 | #define EX4x12_LV_NUM (LV_4 + 1) | 74 | #define EX4x12_LV_NUM (LV_4 + 1) |
75 | 75 | ||
76 | /** | ||
77 | * struct busfreq_opp_info - opp information for bus | ||
78 | * @rate: Frequency in hertz | ||
79 | * @volt: Voltage in microvolts corresponding to this OPP | ||
80 | */ | ||
81 | struct busfreq_opp_info { | ||
82 | unsigned long rate; | ||
83 | unsigned long volt; | ||
84 | }; | ||
85 | |||
76 | struct busfreq_data { | 86 | struct busfreq_data { |
77 | enum exynos4_busf_type type; | 87 | enum exynos4_busf_type type; |
78 | struct device *dev; | 88 | struct device *dev; |
@@ -80,7 +90,7 @@ struct busfreq_data { | |||
80 | bool disabled; | 90 | bool disabled; |
81 | struct regulator *vdd_int; | 91 | struct regulator *vdd_int; |
82 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ | 92 | struct regulator *vdd_mif; /* Exynos4412/4212 only */ |
83 | struct opp *curr_opp; | 93 | struct busfreq_opp_info curr_oppinfo; |
84 | struct exynos4_ppmu dmc[2]; | 94 | struct exynos4_ppmu dmc[2]; |
85 | 95 | ||
86 | struct notifier_block pm_notifier; | 96 | struct notifier_block pm_notifier; |
@@ -296,13 +306,14 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = { | |||
296 | }; | 306 | }; |
297 | 307 | ||
298 | 308 | ||
299 | static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | 309 | static int exynos4210_set_busclk(struct busfreq_data *data, |
310 | struct busfreq_opp_info *oppi) | ||
300 | { | 311 | { |
301 | unsigned int index; | 312 | unsigned int index; |
302 | unsigned int tmp; | 313 | unsigned int tmp; |
303 | 314 | ||
304 | for (index = LV_0; index < EX4210_LV_NUM; index++) | 315 | for (index = LV_0; index < EX4210_LV_NUM; index++) |
305 | if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk) | 316 | if (oppi->rate == exynos4210_busclk_table[index].clk) |
306 | break; | 317 | break; |
307 | 318 | ||
308 | if (index == EX4210_LV_NUM) | 319 | if (index == EX4210_LV_NUM) |
@@ -361,13 +372,14 @@ static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp) | |||
361 | return 0; | 372 | return 0; |
362 | } | 373 | } |
363 | 374 | ||
364 | static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp) | 375 | static int exynos4x12_set_busclk(struct busfreq_data *data, |
376 | struct busfreq_opp_info *oppi) | ||
365 | { | 377 | { |
366 | unsigned int index; | 378 | unsigned int index; |
367 | unsigned int tmp; | 379 | unsigned int tmp; |
368 | 380 | ||
369 | for (index = LV_0; index < EX4x12_LV_NUM; index++) | 381 | for (index = LV_0; index < EX4x12_LV_NUM; index++) |
370 | if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk) | 382 | if (oppi->rate == exynos4x12_mifclk_table[index].clk) |
371 | break; | 383 | break; |
372 | 384 | ||
373 | if (index == EX4x12_LV_NUM) | 385 | if (index == EX4x12_LV_NUM) |
@@ -576,11 +588,12 @@ static int exynos4x12_get_intspec(unsigned long mifclk) | |||
576 | return -EINVAL; | 588 | return -EINVAL; |
577 | } | 589 | } |
578 | 590 | ||
579 | static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | 591 | static int exynos4_bus_setvolt(struct busfreq_data *data, |
580 | struct opp *oldopp) | 592 | struct busfreq_opp_info *oppi, |
593 | struct busfreq_opp_info *oldoppi) | ||
581 | { | 594 | { |
582 | int err = 0, tmp; | 595 | int err = 0, tmp; |
583 | unsigned long volt = opp_get_voltage(opp); | 596 | unsigned long volt = oppi->volt; |
584 | 597 | ||
585 | switch (data->type) { | 598 | switch (data->type) { |
586 | case TYPE_BUSF_EXYNOS4210: | 599 | case TYPE_BUSF_EXYNOS4210: |
@@ -595,11 +608,11 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
595 | if (err) | 608 | if (err) |
596 | break; | 609 | break; |
597 | 610 | ||
598 | tmp = exynos4x12_get_intspec(opp_get_freq(opp)); | 611 | tmp = exynos4x12_get_intspec(oppi->rate); |
599 | if (tmp < 0) { | 612 | if (tmp < 0) { |
600 | err = tmp; | 613 | err = tmp; |
601 | regulator_set_voltage(data->vdd_mif, | 614 | regulator_set_voltage(data->vdd_mif, |
602 | opp_get_voltage(oldopp), | 615 | oldoppi->volt, |
603 | MAX_SAFEVOLT); | 616 | MAX_SAFEVOLT); |
604 | break; | 617 | break; |
605 | } | 618 | } |
@@ -609,7 +622,7 @@ static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp, | |||
609 | /* Try to recover */ | 622 | /* Try to recover */ |
610 | if (err) | 623 | if (err) |
611 | regulator_set_voltage(data->vdd_mif, | 624 | regulator_set_voltage(data->vdd_mif, |
612 | opp_get_voltage(oldopp), | 625 | oldoppi->volt, |
613 | MAX_SAFEVOLT); | 626 | MAX_SAFEVOLT); |
614 | break; | 627 | break; |
615 | default: | 628 | default: |
@@ -626,17 +639,26 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
626 | struct platform_device *pdev = container_of(dev, struct platform_device, | 639 | struct platform_device *pdev = container_of(dev, struct platform_device, |
627 | dev); | 640 | dev); |
628 | struct busfreq_data *data = platform_get_drvdata(pdev); | 641 | struct busfreq_data *data = platform_get_drvdata(pdev); |
629 | struct opp *opp = devfreq_recommended_opp(dev, _freq, flags); | 642 | struct opp *opp; |
630 | unsigned long freq = opp_get_freq(opp); | 643 | unsigned long freq; |
631 | unsigned long old_freq = opp_get_freq(data->curr_opp); | 644 | unsigned long old_freq = data->curr_oppinfo.rate; |
645 | struct busfreq_opp_info new_oppinfo; | ||
632 | 646 | ||
633 | if (IS_ERR(opp)) | 647 | rcu_read_lock(); |
648 | opp = devfreq_recommended_opp(dev, _freq, flags); | ||
649 | if (IS_ERR(opp)) { | ||
650 | rcu_read_unlock(); | ||
634 | return PTR_ERR(opp); | 651 | return PTR_ERR(opp); |
652 | } | ||
653 | new_oppinfo.rate = opp_get_freq(opp); | ||
654 | new_oppinfo.volt = opp_get_voltage(opp); | ||
655 | rcu_read_unlock(); | ||
656 | freq = new_oppinfo.rate; | ||
635 | 657 | ||
636 | if (old_freq == freq) | 658 | if (old_freq == freq) |
637 | return 0; | 659 | return 0; |
638 | 660 | ||
639 | dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp)); | 661 | dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt); |
640 | 662 | ||
641 | mutex_lock(&data->lock); | 663 | mutex_lock(&data->lock); |
642 | 664 | ||
@@ -644,17 +666,18 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
644 | goto out; | 666 | goto out; |
645 | 667 | ||
646 | if (old_freq < freq) | 668 | if (old_freq < freq) |
647 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 669 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
670 | &data->curr_oppinfo); | ||
648 | if (err) | 671 | if (err) |
649 | goto out; | 672 | goto out; |
650 | 673 | ||
651 | if (old_freq != freq) { | 674 | if (old_freq != freq) { |
652 | switch (data->type) { | 675 | switch (data->type) { |
653 | case TYPE_BUSF_EXYNOS4210: | 676 | case TYPE_BUSF_EXYNOS4210: |
654 | err = exynos4210_set_busclk(data, opp); | 677 | err = exynos4210_set_busclk(data, &new_oppinfo); |
655 | break; | 678 | break; |
656 | case TYPE_BUSF_EXYNOS4x12: | 679 | case TYPE_BUSF_EXYNOS4x12: |
657 | err = exynos4x12_set_busclk(data, opp); | 680 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
658 | break; | 681 | break; |
659 | default: | 682 | default: |
660 | err = -EINVAL; | 683 | err = -EINVAL; |
@@ -664,11 +687,12 @@ static int exynos4_bus_target(struct device *dev, unsigned long *_freq, | |||
664 | goto out; | 687 | goto out; |
665 | 688 | ||
666 | if (old_freq > freq) | 689 | if (old_freq > freq) |
667 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 690 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
691 | &data->curr_oppinfo); | ||
668 | if (err) | 692 | if (err) |
669 | goto out; | 693 | goto out; |
670 | 694 | ||
671 | data->curr_opp = opp; | 695 | data->curr_oppinfo = new_oppinfo; |
672 | out: | 696 | out: |
673 | mutex_unlock(&data->lock); | 697 | mutex_unlock(&data->lock); |
674 | return err; | 698 | return err; |
@@ -702,7 +726,7 @@ static int exynos4_bus_get_dev_status(struct device *dev, | |||
702 | 726 | ||
703 | exynos4_read_ppmu(data); | 727 | exynos4_read_ppmu(data); |
704 | busier_dmc = exynos4_get_busier_dmc(data); | 728 | busier_dmc = exynos4_get_busier_dmc(data); |
705 | stat->current_frequency = opp_get_freq(data->curr_opp); | 729 | stat->current_frequency = data->curr_oppinfo.rate; |
706 | 730 | ||
707 | if (busier_dmc) | 731 | if (busier_dmc) |
708 | addr = S5P_VA_DMC1; | 732 | addr = S5P_VA_DMC1; |
@@ -933,6 +957,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
933 | struct busfreq_data *data = container_of(this, struct busfreq_data, | 957 | struct busfreq_data *data = container_of(this, struct busfreq_data, |
934 | pm_notifier); | 958 | pm_notifier); |
935 | struct opp *opp; | 959 | struct opp *opp; |
960 | struct busfreq_opp_info new_oppinfo; | ||
936 | unsigned long maxfreq = ULONG_MAX; | 961 | unsigned long maxfreq = ULONG_MAX; |
937 | int err = 0; | 962 | int err = 0; |
938 | 963 | ||
@@ -943,18 +968,29 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
943 | 968 | ||
944 | data->disabled = true; | 969 | data->disabled = true; |
945 | 970 | ||
971 | rcu_read_lock(); | ||
946 | opp = opp_find_freq_floor(data->dev, &maxfreq); | 972 | opp = opp_find_freq_floor(data->dev, &maxfreq); |
973 | if (IS_ERR(opp)) { | ||
974 | rcu_read_unlock(); | ||
975 | dev_err(data->dev, "%s: unable to find a min freq\n", | ||
976 | __func__); | ||
977 | return PTR_ERR(opp); | ||
978 | } | ||
979 | new_oppinfo.rate = opp_get_freq(opp); | ||
980 | new_oppinfo.volt = opp_get_voltage(opp); | ||
981 | rcu_read_unlock(); | ||
947 | 982 | ||
948 | err = exynos4_bus_setvolt(data, opp, data->curr_opp); | 983 | err = exynos4_bus_setvolt(data, &new_oppinfo, |
984 | &data->curr_oppinfo); | ||
949 | if (err) | 985 | if (err) |
950 | goto unlock; | 986 | goto unlock; |
951 | 987 | ||
952 | switch (data->type) { | 988 | switch (data->type) { |
953 | case TYPE_BUSF_EXYNOS4210: | 989 | case TYPE_BUSF_EXYNOS4210: |
954 | err = exynos4210_set_busclk(data, opp); | 990 | err = exynos4210_set_busclk(data, &new_oppinfo); |
955 | break; | 991 | break; |
956 | case TYPE_BUSF_EXYNOS4x12: | 992 | case TYPE_BUSF_EXYNOS4x12: |
957 | err = exynos4x12_set_busclk(data, opp); | 993 | err = exynos4x12_set_busclk(data, &new_oppinfo); |
958 | break; | 994 | break; |
959 | default: | 995 | default: |
960 | err = -EINVAL; | 996 | err = -EINVAL; |
@@ -962,7 +998,7 @@ static int exynos4_busfreq_pm_notifier_event(struct notifier_block *this, | |||
962 | if (err) | 998 | if (err) |
963 | goto unlock; | 999 | goto unlock; |
964 | 1000 | ||
965 | data->curr_opp = opp; | 1001 | data->curr_oppinfo = new_oppinfo; |
966 | unlock: | 1002 | unlock: |
967 | mutex_unlock(&data->lock); | 1003 | mutex_unlock(&data->lock); |
968 | if (err) | 1004 | if (err) |
@@ -1027,13 +1063,17 @@ static int exynos4_busfreq_probe(struct platform_device *pdev) | |||
1027 | } | 1063 | } |
1028 | } | 1064 | } |
1029 | 1065 | ||
1066 | rcu_read_lock(); | ||
1030 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); | 1067 | opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq); |
1031 | if (IS_ERR(opp)) { | 1068 | if (IS_ERR(opp)) { |
1069 | rcu_read_unlock(); | ||
1032 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", | 1070 | dev_err(dev, "Invalid initial frequency %lu kHz.\n", |
1033 | exynos4_devfreq_profile.initial_freq); | 1071 | exynos4_devfreq_profile.initial_freq); |
1034 | return PTR_ERR(opp); | 1072 | return PTR_ERR(opp); |
1035 | } | 1073 | } |
1036 | data->curr_opp = opp; | 1074 | data->curr_oppinfo.rate = opp_get_freq(opp); |
1075 | data->curr_oppinfo.volt = opp_get_voltage(opp); | ||
1076 | rcu_read_unlock(); | ||
1037 | 1077 | ||
1038 | platform_set_drvdata(pdev, data); | 1078 | platform_set_drvdata(pdev, data); |
1039 | 1079 | ||
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c index dbf0e6f8de8a..a7dcf78b1ff8 100644 --- a/drivers/dma/imx-dma.c +++ b/drivers/dma/imx-dma.c | |||
@@ -684,9 +684,8 @@ static int imxdma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, | |||
684 | break; | 684 | break; |
685 | } | 685 | } |
686 | 686 | ||
687 | imxdmac->hw_chaining = 1; | 687 | imxdmac->hw_chaining = 0; |
688 | if (!imxdma_hw_chain(imxdmac)) | 688 | |
689 | return -EINVAL; | ||
690 | imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | | 689 | imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) | |
691 | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | | 690 | ((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) | |
692 | CCR_REN; | 691 | CCR_REN; |
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c index e5fc944de1f0..3e9d66920eb3 100644 --- a/drivers/dma/ioat/dma_v3.c +++ b/drivers/dma/ioat/dma_v3.c | |||
@@ -951,7 +951,7 @@ static int ioat_xor_val_self_test(struct ioatdma_device *device) | |||
951 | goto free_resources; | 951 | goto free_resources; |
952 | } | 952 | } |
953 | } | 953 | } |
954 | dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE); | 954 | dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE); |
955 | 955 | ||
956 | /* skip validate if the capability is not present */ | 956 | /* skip validate if the capability is not present */ |
957 | if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) | 957 | if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask)) |
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index c39e61bc8172..3cad856fe67f 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c | |||
@@ -266,6 +266,7 @@ static struct tegra_dma_desc *tegra_dma_desc_get( | |||
266 | if (async_tx_test_ack(&dma_desc->txd)) { | 266 | if (async_tx_test_ack(&dma_desc->txd)) { |
267 | list_del(&dma_desc->node); | 267 | list_del(&dma_desc->node); |
268 | spin_unlock_irqrestore(&tdc->lock, flags); | 268 | spin_unlock_irqrestore(&tdc->lock, flags); |
269 | dma_desc->txd.flags = 0; | ||
269 | return dma_desc; | 270 | return dma_desc; |
270 | } | 271 | } |
271 | } | 272 | } |
@@ -1050,7 +1051,9 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( | |||
1050 | TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; | 1051 | TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT; |
1051 | ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; | 1052 | ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32; |
1052 | 1053 | ||
1053 | csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC; | 1054 | csr |= TEGRA_APBDMA_CSR_FLOW; |
1055 | if (flags & DMA_PREP_INTERRUPT) | ||
1056 | csr |= TEGRA_APBDMA_CSR_IE_EOC; | ||
1054 | csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; | 1057 | csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT; |
1055 | 1058 | ||
1056 | apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; | 1059 | apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1; |
@@ -1095,7 +1098,8 @@ struct dma_async_tx_descriptor *tegra_dma_prep_dma_cyclic( | |||
1095 | mem += len; | 1098 | mem += len; |
1096 | } | 1099 | } |
1097 | sg_req->last_sg = true; | 1100 | sg_req->last_sg = true; |
1098 | dma_desc->txd.flags = 0; | 1101 | if (flags & DMA_CTRL_ACK) |
1102 | dma_desc->txd.flags = DMA_CTRL_ACK; | ||
1099 | 1103 | ||
1100 | /* | 1104 | /* |
1101 | * Make sure that mode should not be conflicting with currently | 1105 | * Make sure that mode should not be conflicting with currently |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ad8bf2aa629d..2d3f8825e8b8 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -31,7 +31,7 @@ static struct ecc_settings **ecc_stngs; | |||
31 | * | 31 | * |
32 | *FIXME: Produce a better mapping/linearisation. | 32 | *FIXME: Produce a better mapping/linearisation. |
33 | */ | 33 | */ |
34 | struct scrubrate { | 34 | static const struct scrubrate { |
35 | u32 scrubval; /* bit pattern for scrub rate */ | 35 | u32 scrubval; /* bit pattern for scrub rate */ |
36 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ | 36 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ |
37 | } scrubrates[] = { | 37 | } scrubrates[] = { |
@@ -239,7 +239,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci) | |||
239 | * DRAM base/limit associated with node_id | 239 | * DRAM base/limit associated with node_id |
240 | */ | 240 | */ |
241 | static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, | 241 | static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, |
242 | unsigned nid) | 242 | u8 nid) |
243 | { | 243 | { |
244 | u64 addr; | 244 | u64 addr; |
245 | 245 | ||
@@ -265,7 +265,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
265 | u64 sys_addr) | 265 | u64 sys_addr) |
266 | { | 266 | { |
267 | struct amd64_pvt *pvt; | 267 | struct amd64_pvt *pvt; |
268 | unsigned node_id; | 268 | u8 node_id; |
269 | u32 intlv_en, bits; | 269 | u32 intlv_en, bits; |
270 | 270 | ||
271 | /* | 271 | /* |
@@ -939,7 +939,8 @@ static u64 get_error_address(struct mce *m) | |||
939 | struct amd64_pvt *pvt; | 939 | struct amd64_pvt *pvt; |
940 | u64 cc6_base, tmp_addr; | 940 | u64 cc6_base, tmp_addr; |
941 | u32 tmp; | 941 | u32 tmp; |
942 | u8 mce_nid, intlv_en; | 942 | u16 mce_nid; |
943 | u8 intlv_en; | ||
943 | 944 | ||
944 | if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7) | 945 | if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7) |
945 | return addr; | 946 | return addr; |
@@ -979,10 +980,29 @@ static u64 get_error_address(struct mce *m) | |||
979 | return addr; | 980 | return addr; |
980 | } | 981 | } |
981 | 982 | ||
983 | static struct pci_dev *pci_get_related_function(unsigned int vendor, | ||
984 | unsigned int device, | ||
985 | struct pci_dev *related) | ||
986 | { | ||
987 | struct pci_dev *dev = NULL; | ||
988 | |||
989 | while ((dev = pci_get_device(vendor, device, dev))) { | ||
990 | if (pci_domain_nr(dev->bus) == pci_domain_nr(related->bus) && | ||
991 | (dev->bus->number == related->bus->number) && | ||
992 | (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn))) | ||
993 | break; | ||
994 | } | ||
995 | |||
996 | return dev; | ||
997 | } | ||
998 | |||
982 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | 999 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) |
983 | { | 1000 | { |
1001 | struct amd_northbridge *nb; | ||
1002 | struct pci_dev *misc, *f1 = NULL; | ||
984 | struct cpuinfo_x86 *c = &boot_cpu_data; | 1003 | struct cpuinfo_x86 *c = &boot_cpu_data; |
985 | int off = range << 3; | 1004 | int off = range << 3; |
1005 | u32 llim; | ||
986 | 1006 | ||
987 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); | 1007 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); |
988 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); | 1008 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); |
@@ -996,30 +1016,32 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | |||
996 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off, &pvt->ranges[range].base.hi); | 1016 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off, &pvt->ranges[range].base.hi); |
997 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); | 1017 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); |
998 | 1018 | ||
999 | /* Factor in CC6 save area by reading dst node's limit reg */ | 1019 | /* F15h: factor in CC6 save area by reading dst node's limit reg */ |
1000 | if (c->x86 == 0x15) { | 1020 | if (c->x86 != 0x15) |
1001 | struct pci_dev *f1 = NULL; | 1021 | return; |
1002 | u8 nid = dram_dst_node(pvt, range); | ||
1003 | u32 llim; | ||
1004 | 1022 | ||
1005 | f1 = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x18 + nid, 1)); | 1023 | nb = node_to_amd_nb(dram_dst_node(pvt, range)); |
1006 | if (WARN_ON(!f1)) | 1024 | if (WARN_ON(!nb)) |
1007 | return; | 1025 | return; |
1008 | 1026 | ||
1009 | amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim); | 1027 | misc = nb->misc; |
1028 | f1 = pci_get_related_function(misc->vendor, PCI_DEVICE_ID_AMD_15H_NB_F1, misc); | ||
1029 | if (WARN_ON(!f1)) | ||
1030 | return; | ||
1010 | 1031 | ||
1011 | pvt->ranges[range].lim.lo &= GENMASK(0, 15); | 1032 | amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim); |
1012 | 1033 | ||
1013 | /* {[39:27],111b} */ | 1034 | pvt->ranges[range].lim.lo &= GENMASK(0, 15); |
1014 | pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16; | ||
1015 | 1035 | ||
1016 | pvt->ranges[range].lim.hi &= GENMASK(0, 7); | 1036 | /* {[39:27],111b} */ |
1037 | pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16; | ||
1017 | 1038 | ||
1018 | /* [47:40] */ | 1039 | pvt->ranges[range].lim.hi &= GENMASK(0, 7); |
1019 | pvt->ranges[range].lim.hi |= llim >> 13; | ||
1020 | 1040 | ||
1021 | pci_dev_put(f1); | 1041 | /* [47:40] */ |
1022 | } | 1042 | pvt->ranges[range].lim.hi |= llim >> 13; |
1043 | |||
1044 | pci_dev_put(f1); | ||
1023 | } | 1045 | } |
1024 | 1046 | ||
1025 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, | 1047 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, |
@@ -1305,7 +1327,7 @@ static u8 f1x_determine_channel(struct amd64_pvt *pvt, u64 sys_addr, | |||
1305 | } | 1327 | } |
1306 | 1328 | ||
1307 | /* Convert the sys_addr to the normalized DCT address */ | 1329 | /* Convert the sys_addr to the normalized DCT address */ |
1308 | static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, unsigned range, | 1330 | static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range, |
1309 | u64 sys_addr, bool hi_rng, | 1331 | u64 sys_addr, bool hi_rng, |
1310 | u32 dct_sel_base_addr) | 1332 | u32 dct_sel_base_addr) |
1311 | { | 1333 | { |
@@ -1381,7 +1403,7 @@ static int f10_process_possible_spare(struct amd64_pvt *pvt, u8 dct, int csrow) | |||
1381 | * -EINVAL: NOT FOUND | 1403 | * -EINVAL: NOT FOUND |
1382 | * 0..csrow = Chip-Select Row | 1404 | * 0..csrow = Chip-Select Row |
1383 | */ | 1405 | */ |
1384 | static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct) | 1406 | static int f1x_lookup_addr_in_dct(u64 in_addr, u8 nid, u8 dct) |
1385 | { | 1407 | { |
1386 | struct mem_ctl_info *mci; | 1408 | struct mem_ctl_info *mci; |
1387 | struct amd64_pvt *pvt; | 1409 | struct amd64_pvt *pvt; |
@@ -1672,23 +1694,6 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1672 | }, | 1694 | }, |
1673 | }; | 1695 | }; |
1674 | 1696 | ||
1675 | static struct pci_dev *pci_get_related_function(unsigned int vendor, | ||
1676 | unsigned int device, | ||
1677 | struct pci_dev *related) | ||
1678 | { | ||
1679 | struct pci_dev *dev = NULL; | ||
1680 | |||
1681 | dev = pci_get_device(vendor, device, dev); | ||
1682 | while (dev) { | ||
1683 | if ((dev->bus->number == related->bus->number) && | ||
1684 | (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn))) | ||
1685 | break; | ||
1686 | dev = pci_get_device(vendor, device, dev); | ||
1687 | } | ||
1688 | |||
1689 | return dev; | ||
1690 | } | ||
1691 | |||
1692 | /* | 1697 | /* |
1693 | * These are tables of eigenvectors (one per line) which can be used for the | 1698 | * These are tables of eigenvectors (one per line) which can be used for the |
1694 | * construction of the syndrome tables. The modified syndrome search algorithm | 1699 | * construction of the syndrome tables. The modified syndrome search algorithm |
@@ -1696,7 +1701,7 @@ static struct pci_dev *pci_get_related_function(unsigned int vendor, | |||
1696 | * | 1701 | * |
1697 | * Algorithm courtesy of Ross LaFetra from AMD. | 1702 | * Algorithm courtesy of Ross LaFetra from AMD. |
1698 | */ | 1703 | */ |
1699 | static u16 x4_vectors[] = { | 1704 | static const u16 x4_vectors[] = { |
1700 | 0x2f57, 0x1afe, 0x66cc, 0xdd88, | 1705 | 0x2f57, 0x1afe, 0x66cc, 0xdd88, |
1701 | 0x11eb, 0x3396, 0x7f4c, 0xeac8, | 1706 | 0x11eb, 0x3396, 0x7f4c, 0xeac8, |
1702 | 0x0001, 0x0002, 0x0004, 0x0008, | 1707 | 0x0001, 0x0002, 0x0004, 0x0008, |
@@ -1735,7 +1740,7 @@ static u16 x4_vectors[] = { | |||
1735 | 0x19a9, 0x2efe, 0xb5cc, 0x6f88, | 1740 | 0x19a9, 0x2efe, 0xb5cc, 0x6f88, |
1736 | }; | 1741 | }; |
1737 | 1742 | ||
1738 | static u16 x8_vectors[] = { | 1743 | static const u16 x8_vectors[] = { |
1739 | 0x0145, 0x028a, 0x2374, 0x43c8, 0xa1f0, 0x0520, 0x0a40, 0x1480, | 1744 | 0x0145, 0x028a, 0x2374, 0x43c8, 0xa1f0, 0x0520, 0x0a40, 0x1480, |
1740 | 0x0211, 0x0422, 0x0844, 0x1088, 0x01b0, 0x44e0, 0x23c0, 0xed80, | 1745 | 0x0211, 0x0422, 0x0844, 0x1088, 0x01b0, 0x44e0, 0x23c0, 0xed80, |
1741 | 0x1011, 0x0116, 0x022c, 0x0458, 0x08b0, 0x8c60, 0x2740, 0x4e80, | 1746 | 0x1011, 0x0116, 0x022c, 0x0458, 0x08b0, 0x8c60, 0x2740, 0x4e80, |
@@ -1757,7 +1762,7 @@ static u16 x8_vectors[] = { | |||
1757 | 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, | 1762 | 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, |
1758 | }; | 1763 | }; |
1759 | 1764 | ||
1760 | static int decode_syndrome(u16 syndrome, u16 *vectors, unsigned num_vecs, | 1765 | static int decode_syndrome(u16 syndrome, const u16 *vectors, unsigned num_vecs, |
1761 | unsigned v_dim) | 1766 | unsigned v_dim) |
1762 | { | 1767 | { |
1763 | unsigned int i, err_sym; | 1768 | unsigned int i, err_sym; |
@@ -2181,7 +2186,7 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
2181 | } | 2186 | } |
2182 | 2187 | ||
2183 | /* get all cores on this DCT */ | 2188 | /* get all cores on this DCT */ |
2184 | static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid) | 2189 | static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, u16 nid) |
2185 | { | 2190 | { |
2186 | int cpu; | 2191 | int cpu; |
2187 | 2192 | ||
@@ -2191,7 +2196,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid) | |||
2191 | } | 2196 | } |
2192 | 2197 | ||
2193 | /* check MCG_CTL on all the cpus on this node */ | 2198 | /* check MCG_CTL on all the cpus on this node */ |
2194 | static bool amd64_nb_mce_bank_enabled_on_node(unsigned nid) | 2199 | static bool amd64_nb_mce_bank_enabled_on_node(u16 nid) |
2195 | { | 2200 | { |
2196 | cpumask_var_t mask; | 2201 | cpumask_var_t mask; |
2197 | int cpu, nbe; | 2202 | int cpu, nbe; |
@@ -2224,7 +2229,7 @@ out: | |||
2224 | return ret; | 2229 | return ret; |
2225 | } | 2230 | } |
2226 | 2231 | ||
2227 | static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on) | 2232 | static int toggle_ecc_err_reporting(struct ecc_settings *s, u16 nid, bool on) |
2228 | { | 2233 | { |
2229 | cpumask_var_t cmask; | 2234 | cpumask_var_t cmask; |
2230 | int cpu; | 2235 | int cpu; |
@@ -2262,7 +2267,7 @@ static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on) | |||
2262 | return 0; | 2267 | return 0; |
2263 | } | 2268 | } |
2264 | 2269 | ||
2265 | static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, | 2270 | static bool enable_ecc_error_reporting(struct ecc_settings *s, u16 nid, |
2266 | struct pci_dev *F3) | 2271 | struct pci_dev *F3) |
2267 | { | 2272 | { |
2268 | bool ret = true; | 2273 | bool ret = true; |
@@ -2314,7 +2319,7 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, | |||
2314 | return ret; | 2319 | return ret; |
2315 | } | 2320 | } |
2316 | 2321 | ||
2317 | static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid, | 2322 | static void restore_ecc_error_reporting(struct ecc_settings *s, u16 nid, |
2318 | struct pci_dev *F3) | 2323 | struct pci_dev *F3) |
2319 | { | 2324 | { |
2320 | u32 value, mask = 0x3; /* UECC/CECC enable */ | 2325 | u32 value, mask = 0x3; /* UECC/CECC enable */ |
@@ -2353,7 +2358,7 @@ static const char *ecc_msg = | |||
2353 | "'ecc_enable_override'.\n" | 2358 | "'ecc_enable_override'.\n" |
2354 | " (Note that use of the override may cause unknown side effects.)\n"; | 2359 | " (Note that use of the override may cause unknown side effects.)\n"; |
2355 | 2360 | ||
2356 | static bool ecc_enabled(struct pci_dev *F3, u8 nid) | 2361 | static bool ecc_enabled(struct pci_dev *F3, u16 nid) |
2357 | { | 2362 | { |
2358 | u32 value; | 2363 | u32 value; |
2359 | u8 ecc_en = 0; | 2364 | u8 ecc_en = 0; |
@@ -2474,7 +2479,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) | |||
2474 | struct mem_ctl_info *mci = NULL; | 2479 | struct mem_ctl_info *mci = NULL; |
2475 | struct edac_mc_layer layers[2]; | 2480 | struct edac_mc_layer layers[2]; |
2476 | int err = 0, ret; | 2481 | int err = 0, ret; |
2477 | u8 nid = get_node_id(F2); | 2482 | u16 nid = amd_get_node_id(F2); |
2478 | 2483 | ||
2479 | ret = -ENOMEM; | 2484 | ret = -ENOMEM; |
2480 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); | 2485 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); |
@@ -2566,7 +2571,7 @@ err_ret: | |||
2566 | static int amd64_probe_one_instance(struct pci_dev *pdev, | 2571 | static int amd64_probe_one_instance(struct pci_dev *pdev, |
2567 | const struct pci_device_id *mc_type) | 2572 | const struct pci_device_id *mc_type) |
2568 | { | 2573 | { |
2569 | u8 nid = get_node_id(pdev); | 2574 | u16 nid = amd_get_node_id(pdev); |
2570 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | 2575 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; |
2571 | struct ecc_settings *s; | 2576 | struct ecc_settings *s; |
2572 | int ret = 0; | 2577 | int ret = 0; |
@@ -2616,7 +2621,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev) | |||
2616 | { | 2621 | { |
2617 | struct mem_ctl_info *mci; | 2622 | struct mem_ctl_info *mci; |
2618 | struct amd64_pvt *pvt; | 2623 | struct amd64_pvt *pvt; |
2619 | u8 nid = get_node_id(pdev); | 2624 | u16 nid = amd_get_node_id(pdev); |
2620 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | 2625 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; |
2621 | struct ecc_settings *s = ecc_stngs[nid]; | 2626 | struct ecc_settings *s = ecc_stngs[nid]; |
2622 | 2627 | ||
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index e864f407806c..35637d83f235 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -292,12 +292,6 @@ | |||
292 | /* MSRs */ | 292 | /* MSRs */ |
293 | #define MSR_MCGCTL_NBE BIT(4) | 293 | #define MSR_MCGCTL_NBE BIT(4) |
294 | 294 | ||
295 | /* AMD sets the first MC device at device ID 0x18. */ | ||
296 | static inline u8 get_node_id(struct pci_dev *pdev) | ||
297 | { | ||
298 | return PCI_SLOT(pdev->devfn) - 0x18; | ||
299 | } | ||
300 | |||
301 | enum amd_families { | 295 | enum amd_families { |
302 | K8_CPUS = 0, | 296 | K8_CPUS = 0, |
303 | F10_CPUS, | 297 | F10_CPUS, |
@@ -340,7 +334,7 @@ struct amd64_pvt { | |||
340 | /* pci_device handles which we utilize */ | 334 | /* pci_device handles which we utilize */ |
341 | struct pci_dev *F1, *F2, *F3; | 335 | struct pci_dev *F1, *F2, *F3; |
342 | 336 | ||
343 | unsigned mc_node_id; /* MC index of this MC node */ | 337 | u16 mc_node_id; /* MC index of this MC node */ |
344 | int ext_model; /* extended model value of this node */ | 338 | int ext_model; /* extended model value of this node */ |
345 | int channel_count; | 339 | int channel_count; |
346 | 340 | ||
@@ -393,7 +387,7 @@ struct err_info { | |||
393 | u32 offset; | 387 | u32 offset; |
394 | }; | 388 | }; |
395 | 389 | ||
396 | static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i) | 390 | static inline u64 get_dram_base(struct amd64_pvt *pvt, u8 i) |
397 | { | 391 | { |
398 | u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8; | 392 | u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8; |
399 | 393 | ||
@@ -403,7 +397,7 @@ static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i) | |||
403 | return (((u64)pvt->ranges[i].base.hi & 0x000000ff) << 40) | addr; | 397 | return (((u64)pvt->ranges[i].base.hi & 0x000000ff) << 40) | addr; |
404 | } | 398 | } |
405 | 399 | ||
406 | static inline u64 get_dram_limit(struct amd64_pvt *pvt, unsigned i) | 400 | static inline u64 get_dram_limit(struct amd64_pvt *pvt, u8 i) |
407 | { | 401 | { |
408 | u64 lim = (((u64)pvt->ranges[i].lim.lo & 0xffff0000) << 8) | 0x00ffffff; | 402 | u64 lim = (((u64)pvt->ranges[i].lim.lo & 0xffff0000) << 8) | 0x00ffffff; |
409 | 403 | ||
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 281f566a5513..d1e9eb191f2b 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -340,7 +340,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, | |||
340 | /* | 340 | /* |
341 | * Alocate and fill the csrow/channels structs | 341 | * Alocate and fill the csrow/channels structs |
342 | */ | 342 | */ |
343 | mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL); | 343 | mci->csrows = kcalloc(tot_csrows, sizeof(*mci->csrows), GFP_KERNEL); |
344 | if (!mci->csrows) | 344 | if (!mci->csrows) |
345 | goto error; | 345 | goto error; |
346 | for (row = 0; row < tot_csrows; row++) { | 346 | for (row = 0; row < tot_csrows; row++) { |
@@ -351,7 +351,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, | |||
351 | csr->csrow_idx = row; | 351 | csr->csrow_idx = row; |
352 | csr->mci = mci; | 352 | csr->mci = mci; |
353 | csr->nr_channels = tot_channels; | 353 | csr->nr_channels = tot_channels; |
354 | csr->channels = kcalloc(sizeof(*csr->channels), tot_channels, | 354 | csr->channels = kcalloc(tot_channels, sizeof(*csr->channels), |
355 | GFP_KERNEL); | 355 | GFP_KERNEL); |
356 | if (!csr->channels) | 356 | if (!csr->channels) |
357 | goto error; | 357 | goto error; |
@@ -369,7 +369,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num, | |||
369 | /* | 369 | /* |
370 | * Allocate and fill the dimm structs | 370 | * Allocate and fill the dimm structs |
371 | */ | 371 | */ |
372 | mci->dimms = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL); | 372 | mci->dimms = kcalloc(tot_dimms, sizeof(*mci->dimms), GFP_KERNEL); |
373 | if (!mci->dimms) | 373 | if (!mci->dimms) |
374 | goto error; | 374 | goto error; |
375 | 375 | ||
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index dc6e905ee1a5..0056c4dae9d5 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c | |||
@@ -256,7 +256,7 @@ static ssize_t edac_pci_dev_store(struct kobject *kobj, | |||
256 | struct edac_pci_dev_attribute *edac_pci_dev; | 256 | struct edac_pci_dev_attribute *edac_pci_dev; |
257 | edac_pci_dev = (struct edac_pci_dev_attribute *)attr; | 257 | edac_pci_dev = (struct edac_pci_dev_attribute *)attr; |
258 | 258 | ||
259 | if (edac_pci_dev->show) | 259 | if (edac_pci_dev->store) |
260 | return edac_pci_dev->store(edac_pci_dev->value, buffer, count); | 260 | return edac_pci_dev->store(edac_pci_dev->value, buffer, count); |
261 | return -EIO; | 261 | return -EIO; |
262 | } | 262 | } |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index fd3ae6290d71..982f1f5f5742 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
@@ -471,7 +471,7 @@ void __init dmi_scan_machine(void) | |||
471 | char __iomem *p, *q; | 471 | char __iomem *p, *q; |
472 | int rc; | 472 | int rc; |
473 | 473 | ||
474 | if (efi_enabled) { | 474 | if (efi_enabled(EFI_CONFIG_TABLES)) { |
475 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) | 475 | if (efi.smbios == EFI_INVALID_TABLE_ADDR) |
476 | goto error; | 476 | goto error; |
477 | 477 | ||
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c index 7b1c37497c9a..f5596db0cf58 100644 --- a/drivers/firmware/efivars.c +++ b/drivers/firmware/efivars.c | |||
@@ -674,7 +674,7 @@ static int efi_status_to_err(efi_status_t status) | |||
674 | err = -EACCES; | 674 | err = -EACCES; |
675 | break; | 675 | break; |
676 | case EFI_NOT_FOUND: | 676 | case EFI_NOT_FOUND: |
677 | err = -ENOENT; | 677 | err = -EIO; |
678 | break; | 678 | break; |
679 | default: | 679 | default: |
680 | err = -EINVAL; | 680 | err = -EINVAL; |
@@ -793,6 +793,7 @@ static ssize_t efivarfs_file_write(struct file *file, | |||
793 | spin_unlock(&efivars->lock); | 793 | spin_unlock(&efivars->lock); |
794 | efivar_unregister(var); | 794 | efivar_unregister(var); |
795 | drop_nlink(inode); | 795 | drop_nlink(inode); |
796 | d_delete(file->f_dentry); | ||
796 | dput(file->f_dentry); | 797 | dput(file->f_dentry); |
797 | 798 | ||
798 | } else { | 799 | } else { |
@@ -994,7 +995,7 @@ static int efivarfs_unlink(struct inode *dir, struct dentry *dentry) | |||
994 | list_del(&var->list); | 995 | list_del(&var->list); |
995 | spin_unlock(&efivars->lock); | 996 | spin_unlock(&efivars->lock); |
996 | efivar_unregister(var); | 997 | efivar_unregister(var); |
997 | drop_nlink(dir); | 998 | drop_nlink(dentry->d_inode); |
998 | dput(dentry); | 999 | dput(dentry); |
999 | return 0; | 1000 | return 0; |
1000 | } | 1001 | } |
@@ -1782,7 +1783,7 @@ efivars_init(void) | |||
1782 | printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, | 1783 | printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION, |
1783 | EFIVARS_DATE); | 1784 | EFIVARS_DATE); |
1784 | 1785 | ||
1785 | if (!efi_enabled) | 1786 | if (!efi_enabled(EFI_RUNTIME_SERVICES)) |
1786 | return 0; | 1787 | return 0; |
1787 | 1788 | ||
1788 | /* For now we'll register the efi directory at /sys/firmware/efi */ | 1789 | /* For now we'll register the efi directory at /sys/firmware/efi */ |
@@ -1822,7 +1823,7 @@ err_put: | |||
1822 | static void __exit | 1823 | static void __exit |
1823 | efivars_exit(void) | 1824 | efivars_exit(void) |
1824 | { | 1825 | { |
1825 | if (efi_enabled) { | 1826 | if (efi_enabled(EFI_RUNTIME_SERVICES)) { |
1826 | unregister_efivars(&__efivars); | 1827 | unregister_efivars(&__efivars); |
1827 | kobject_put(efi_kobj); | 1828 | kobject_put(efi_kobj); |
1828 | } | 1829 | } |
diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c index 4da4eb9ae926..2224f1dc074b 100644 --- a/drivers/firmware/iscsi_ibft_find.c +++ b/drivers/firmware/iscsi_ibft_find.c | |||
@@ -99,7 +99,7 @@ unsigned long __init find_ibft_region(unsigned long *sizep) | |||
99 | /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will | 99 | /* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will |
100 | * only use ACPI for this */ | 100 | * only use ACPI for this */ |
101 | 101 | ||
102 | if (!efi_enabled) | 102 | if (!efi_enabled(EFI_BOOT)) |
103 | find_ibft_in_mem(); | 103 | find_ibft_in_mem(); |
104 | 104 | ||
105 | if (ibft_addr) { | 105 | if (ibft_addr) { |
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c index 7d9bd94be8d2..6819d63cb167 100644 --- a/drivers/gpio/gpio-mvebu.c +++ b/drivers/gpio/gpio-mvebu.c | |||
@@ -547,7 +547,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
547 | mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); | 547 | mvchip->membase = devm_request_and_ioremap(&pdev->dev, res); |
548 | if (! mvchip->membase) { | 548 | if (! mvchip->membase) { |
549 | dev_err(&pdev->dev, "Cannot ioremap\n"); | 549 | dev_err(&pdev->dev, "Cannot ioremap\n"); |
550 | kfree(mvchip->chip.label); | ||
551 | return -ENOMEM; | 550 | return -ENOMEM; |
552 | } | 551 | } |
553 | 552 | ||
@@ -557,14 +556,12 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
557 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); | 556 | res = platform_get_resource(pdev, IORESOURCE_MEM, 1); |
558 | if (! res) { | 557 | if (! res) { |
559 | dev_err(&pdev->dev, "Cannot get memory resource\n"); | 558 | dev_err(&pdev->dev, "Cannot get memory resource\n"); |
560 | kfree(mvchip->chip.label); | ||
561 | return -ENODEV; | 559 | return -ENODEV; |
562 | } | 560 | } |
563 | 561 | ||
564 | mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); | 562 | mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res); |
565 | if (! mvchip->percpu_membase) { | 563 | if (! mvchip->percpu_membase) { |
566 | dev_err(&pdev->dev, "Cannot ioremap\n"); | 564 | dev_err(&pdev->dev, "Cannot ioremap\n"); |
567 | kfree(mvchip->chip.label); | ||
568 | return -ENOMEM; | 565 | return -ENOMEM; |
569 | } | 566 | } |
570 | } | 567 | } |
@@ -625,7 +622,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
625 | mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); | 622 | mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1); |
626 | if (mvchip->irqbase < 0) { | 623 | if (mvchip->irqbase < 0) { |
627 | dev_err(&pdev->dev, "no irqs\n"); | 624 | dev_err(&pdev->dev, "no irqs\n"); |
628 | kfree(mvchip->chip.label); | ||
629 | return -ENOMEM; | 625 | return -ENOMEM; |
630 | } | 626 | } |
631 | 627 | ||
@@ -633,7 +629,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
633 | mvchip->membase, handle_level_irq); | 629 | mvchip->membase, handle_level_irq); |
634 | if (! gc) { | 630 | if (! gc) { |
635 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); | 631 | dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n"); |
636 | kfree(mvchip->chip.label); | ||
637 | return -ENOMEM; | 632 | return -ENOMEM; |
638 | } | 633 | } |
639 | 634 | ||
@@ -668,7 +663,6 @@ static int mvebu_gpio_probe(struct platform_device *pdev) | |||
668 | irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, | 663 | irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST, |
669 | IRQ_LEVEL | IRQ_NOPROBE); | 664 | IRQ_LEVEL | IRQ_NOPROBE); |
670 | kfree(gc); | 665 | kfree(gc); |
671 | kfree(mvchip->chip.label); | ||
672 | return -ENODEV; | 666 | return -ENODEV; |
673 | } | 667 | } |
674 | 668 | ||
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c index 01f7fe955590..76be7eed79de 100644 --- a/drivers/gpio/gpio-samsung.c +++ b/drivers/gpio/gpio-samsung.c | |||
@@ -32,7 +32,6 @@ | |||
32 | 32 | ||
33 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
34 | #include <mach/map.h> | 34 | #include <mach/map.h> |
35 | #include <mach/regs-clock.h> | ||
36 | #include <mach/regs-gpio.h> | 35 | #include <mach/regs-gpio.h> |
37 | 36 | ||
38 | #include <plat/cpu.h> | 37 | #include <plat/cpu.h> |
@@ -446,7 +445,7 @@ static struct samsung_gpio_cfg s3c24xx_gpiocfg_banka = { | |||
446 | }; | 445 | }; |
447 | #endif | 446 | #endif |
448 | 447 | ||
449 | #if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5) | 448 | #if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250) |
450 | static struct samsung_gpio_cfg exynos_gpio_cfg = { | 449 | static struct samsung_gpio_cfg exynos_gpio_cfg = { |
451 | .set_pull = exynos_gpio_setpull, | 450 | .set_pull = exynos_gpio_setpull, |
452 | .get_pull = exynos_gpio_getpull, | 451 | .get_pull = exynos_gpio_getpull, |
@@ -2446,7 +2445,7 @@ static struct samsung_gpio_chip exynos4_gpios_3[] = { | |||
2446 | }; | 2445 | }; |
2447 | #endif | 2446 | #endif |
2448 | 2447 | ||
2449 | #ifdef CONFIG_ARCH_EXYNOS5 | 2448 | #ifdef CONFIG_SOC_EXYNOS5250 |
2450 | static struct samsung_gpio_chip exynos5_gpios_1[] = { | 2449 | static struct samsung_gpio_chip exynos5_gpios_1[] = { |
2451 | { | 2450 | { |
2452 | .chip = { | 2451 | .chip = { |
@@ -2614,7 +2613,7 @@ static struct samsung_gpio_chip exynos5_gpios_1[] = { | |||
2614 | }; | 2613 | }; |
2615 | #endif | 2614 | #endif |
2616 | 2615 | ||
2617 | #ifdef CONFIG_ARCH_EXYNOS5 | 2616 | #ifdef CONFIG_SOC_EXYNOS5250 |
2618 | static struct samsung_gpio_chip exynos5_gpios_2[] = { | 2617 | static struct samsung_gpio_chip exynos5_gpios_2[] = { |
2619 | { | 2618 | { |
2620 | .chip = { | 2619 | .chip = { |
@@ -2675,7 +2674,7 @@ static struct samsung_gpio_chip exynos5_gpios_2[] = { | |||
2675 | }; | 2674 | }; |
2676 | #endif | 2675 | #endif |
2677 | 2676 | ||
2678 | #ifdef CONFIG_ARCH_EXYNOS5 | 2677 | #ifdef CONFIG_SOC_EXYNOS5250 |
2679 | static struct samsung_gpio_chip exynos5_gpios_3[] = { | 2678 | static struct samsung_gpio_chip exynos5_gpios_3[] = { |
2680 | { | 2679 | { |
2681 | .chip = { | 2680 | .chip = { |
@@ -2711,7 +2710,7 @@ static struct samsung_gpio_chip exynos5_gpios_3[] = { | |||
2711 | }; | 2710 | }; |
2712 | #endif | 2711 | #endif |
2713 | 2712 | ||
2714 | #ifdef CONFIG_ARCH_EXYNOS5 | 2713 | #ifdef CONFIG_SOC_EXYNOS5250 |
2715 | static struct samsung_gpio_chip exynos5_gpios_4[] = { | 2714 | static struct samsung_gpio_chip exynos5_gpios_4[] = { |
2716 | { | 2715 | { |
2717 | .chip = { | 2716 | .chip = { |
@@ -3010,7 +3009,7 @@ static __init int samsung_gpiolib_init(void) | |||
3010 | int i, nr_chips; | 3009 | int i, nr_chips; |
3011 | int group = 0; | 3010 | int group = 0; |
3012 | 3011 | ||
3013 | #ifdef CONFIG_PINCTRL_SAMSUNG | 3012 | #if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440) |
3014 | /* | 3013 | /* |
3015 | * This gpio driver includes support for device tree support and there | 3014 | * This gpio driver includes support for device tree support and there |
3016 | * are platforms using it. In order to maintain compatibility with those | 3015 | * are platforms using it. In order to maintain compatibility with those |
@@ -3026,6 +3025,7 @@ static __init int samsung_gpiolib_init(void) | |||
3026 | static const struct of_device_id exynos_pinctrl_ids[] = { | 3025 | static const struct of_device_id exynos_pinctrl_ids[] = { |
3027 | { .compatible = "samsung,pinctrl-exynos4210", }, | 3026 | { .compatible = "samsung,pinctrl-exynos4210", }, |
3028 | { .compatible = "samsung,pinctrl-exynos4x12", }, | 3027 | { .compatible = "samsung,pinctrl-exynos4x12", }, |
3028 | { .compatible = "samsung,pinctrl-exynos5440", }, | ||
3029 | }; | 3029 | }; |
3030 | for_each_matching_node(pctrl_np, exynos_pinctrl_ids) | 3030 | for_each_matching_node(pctrl_np, exynos_pinctrl_ids) |
3031 | if (pctrl_np && of_device_is_available(pctrl_np)) | 3031 | if (pctrl_np && of_device_is_available(pctrl_np)) |
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c index 2bf9670ba29b..2aa331499f81 100644 --- a/drivers/gpu/drm/drm_mm.c +++ b/drivers/gpu/drm/drm_mm.c | |||
@@ -221,11 +221,13 @@ static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node, | |||
221 | 221 | ||
222 | BUG_ON(!hole_node->hole_follows || node->allocated); | 222 | BUG_ON(!hole_node->hole_follows || node->allocated); |
223 | 223 | ||
224 | if (mm->color_adjust) | ||
225 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); | ||
226 | |||
227 | if (adj_start < start) | 224 | if (adj_start < start) |
228 | adj_start = start; | 225 | adj_start = start; |
226 | if (adj_end > end) | ||
227 | adj_end = end; | ||
228 | |||
229 | if (mm->color_adjust) | ||
230 | mm->color_adjust(hole_node, color, &adj_start, &adj_end); | ||
229 | 231 | ||
230 | if (alignment) { | 232 | if (alignment) { |
231 | unsigned tmp = adj_start % alignment; | 233 | unsigned tmp = adj_start % alignment; |
@@ -506,7 +508,7 @@ void drm_mm_init_scan(struct drm_mm *mm, | |||
506 | mm->scan_size = size; | 508 | mm->scan_size = size; |
507 | mm->scanned_blocks = 0; | 509 | mm->scanned_blocks = 0; |
508 | mm->scan_hit_start = 0; | 510 | mm->scan_hit_start = 0; |
509 | mm->scan_hit_size = 0; | 511 | mm->scan_hit_end = 0; |
510 | mm->scan_check_range = 0; | 512 | mm->scan_check_range = 0; |
511 | mm->prev_scanned_node = NULL; | 513 | mm->prev_scanned_node = NULL; |
512 | } | 514 | } |
@@ -533,7 +535,7 @@ void drm_mm_init_scan_with_range(struct drm_mm *mm, | |||
533 | mm->scan_size = size; | 535 | mm->scan_size = size; |
534 | mm->scanned_blocks = 0; | 536 | mm->scanned_blocks = 0; |
535 | mm->scan_hit_start = 0; | 537 | mm->scan_hit_start = 0; |
536 | mm->scan_hit_size = 0; | 538 | mm->scan_hit_end = 0; |
537 | mm->scan_start = start; | 539 | mm->scan_start = start; |
538 | mm->scan_end = end; | 540 | mm->scan_end = end; |
539 | mm->scan_check_range = 1; | 541 | mm->scan_check_range = 1; |
@@ -552,8 +554,7 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
552 | struct drm_mm *mm = node->mm; | 554 | struct drm_mm *mm = node->mm; |
553 | struct drm_mm_node *prev_node; | 555 | struct drm_mm_node *prev_node; |
554 | unsigned long hole_start, hole_end; | 556 | unsigned long hole_start, hole_end; |
555 | unsigned long adj_start; | 557 | unsigned long adj_start, adj_end; |
556 | unsigned long adj_end; | ||
557 | 558 | ||
558 | mm->scanned_blocks++; | 559 | mm->scanned_blocks++; |
559 | 560 | ||
@@ -570,14 +571,8 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
570 | node->node_list.next = &mm->prev_scanned_node->node_list; | 571 | node->node_list.next = &mm->prev_scanned_node->node_list; |
571 | mm->prev_scanned_node = node; | 572 | mm->prev_scanned_node = node; |
572 | 573 | ||
573 | hole_start = drm_mm_hole_node_start(prev_node); | 574 | adj_start = hole_start = drm_mm_hole_node_start(prev_node); |
574 | hole_end = drm_mm_hole_node_end(prev_node); | 575 | adj_end = hole_end = drm_mm_hole_node_end(prev_node); |
575 | |||
576 | adj_start = hole_start; | ||
577 | adj_end = hole_end; | ||
578 | |||
579 | if (mm->color_adjust) | ||
580 | mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end); | ||
581 | 576 | ||
582 | if (mm->scan_check_range) { | 577 | if (mm->scan_check_range) { |
583 | if (adj_start < mm->scan_start) | 578 | if (adj_start < mm->scan_start) |
@@ -586,11 +581,14 @@ int drm_mm_scan_add_block(struct drm_mm_node *node) | |||
586 | adj_end = mm->scan_end; | 581 | adj_end = mm->scan_end; |
587 | } | 582 | } |
588 | 583 | ||
584 | if (mm->color_adjust) | ||
585 | mm->color_adjust(prev_node, mm->scan_color, | ||
586 | &adj_start, &adj_end); | ||
587 | |||
589 | if (check_free_hole(adj_start, adj_end, | 588 | if (check_free_hole(adj_start, adj_end, |
590 | mm->scan_size, mm->scan_alignment)) { | 589 | mm->scan_size, mm->scan_alignment)) { |
591 | mm->scan_hit_start = hole_start; | 590 | mm->scan_hit_start = hole_start; |
592 | mm->scan_hit_size = hole_end; | 591 | mm->scan_hit_end = hole_end; |
593 | |||
594 | return 1; | 592 | return 1; |
595 | } | 593 | } |
596 | 594 | ||
@@ -626,19 +624,10 @@ int drm_mm_scan_remove_block(struct drm_mm_node *node) | |||
626 | node_list); | 624 | node_list); |
627 | 625 | ||
628 | prev_node->hole_follows = node->scanned_preceeds_hole; | 626 | prev_node->hole_follows = node->scanned_preceeds_hole; |
629 | INIT_LIST_HEAD(&node->node_list); | ||
630 | list_add(&node->node_list, &prev_node->node_list); | 627 | list_add(&node->node_list, &prev_node->node_list); |
631 | 628 | ||
632 | /* Only need to check for containement because start&size for the | 629 | return (drm_mm_hole_node_end(node) > mm->scan_hit_start && |
633 | * complete resulting free block (not just the desired part) is | 630 | node->start < mm->scan_hit_end); |
634 | * stored. */ | ||
635 | if (node->start >= mm->scan_hit_start && | ||
636 | node->start + node->size | ||
637 | <= mm->scan_hit_start + mm->scan_hit_size) { | ||
638 | return 1; | ||
639 | } | ||
640 | |||
641 | return 0; | ||
642 | } | 631 | } |
643 | EXPORT_SYMBOL(drm_mm_scan_remove_block); | 632 | EXPORT_SYMBOL(drm_mm_scan_remove_block); |
644 | 633 | ||
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig index 1d1f1e5e33f0..046bcda36abe 100644 --- a/drivers/gpu/drm/exynos/Kconfig +++ b/drivers/gpu/drm/exynos/Kconfig | |||
@@ -24,7 +24,7 @@ config DRM_EXYNOS_DMABUF | |||
24 | 24 | ||
25 | config DRM_EXYNOS_FIMD | 25 | config DRM_EXYNOS_FIMD |
26 | bool "Exynos DRM FIMD" | 26 | bool "Exynos DRM FIMD" |
27 | depends on DRM_EXYNOS && !FB_S3C | 27 | depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM |
28 | help | 28 | help |
29 | Choose this option if you want to use Exynos FIMD for DRM. | 29 | Choose this option if you want to use Exynos FIMD for DRM. |
30 | 30 | ||
@@ -48,7 +48,7 @@ config DRM_EXYNOS_G2D | |||
48 | 48 | ||
49 | config DRM_EXYNOS_IPP | 49 | config DRM_EXYNOS_IPP |
50 | bool "Exynos DRM IPP" | 50 | bool "Exynos DRM IPP" |
51 | depends on DRM_EXYNOS | 51 | depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM |
52 | help | 52 | help |
53 | Choose this option if you want to use IPP feature for DRM. | 53 | Choose this option if you want to use IPP feature for DRM. |
54 | 54 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c index ab37437bad8a..4c5b6859c9ea 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_connector.c +++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include "exynos_drm_drv.h" | 18 | #include "exynos_drm_drv.h" |
19 | #include "exynos_drm_encoder.h" | 19 | #include "exynos_drm_encoder.h" |
20 | 20 | ||
21 | #define MAX_EDID 256 | ||
22 | #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ | 21 | #define to_exynos_connector(x) container_of(x, struct exynos_drm_connector,\ |
23 | drm_connector) | 22 | drm_connector) |
24 | 23 | ||
@@ -96,7 +95,9 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
96 | to_exynos_connector(connector); | 95 | to_exynos_connector(connector); |
97 | struct exynos_drm_manager *manager = exynos_connector->manager; | 96 | struct exynos_drm_manager *manager = exynos_connector->manager; |
98 | struct exynos_drm_display_ops *display_ops = manager->display_ops; | 97 | struct exynos_drm_display_ops *display_ops = manager->display_ops; |
99 | unsigned int count; | 98 | struct edid *edid = NULL; |
99 | unsigned int count = 0; | ||
100 | int ret; | ||
100 | 101 | ||
101 | DRM_DEBUG_KMS("%s\n", __FILE__); | 102 | DRM_DEBUG_KMS("%s\n", __FILE__); |
102 | 103 | ||
@@ -114,27 +115,21 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
114 | * because lcd panel has only one mode. | 115 | * because lcd panel has only one mode. |
115 | */ | 116 | */ |
116 | if (display_ops->get_edid) { | 117 | if (display_ops->get_edid) { |
117 | int ret; | 118 | edid = display_ops->get_edid(manager->dev, connector); |
118 | void *edid; | 119 | if (IS_ERR_OR_NULL(edid)) { |
119 | 120 | ret = PTR_ERR(edid); | |
120 | edid = kzalloc(MAX_EDID, GFP_KERNEL); | 121 | edid = NULL; |
121 | if (!edid) { | 122 | DRM_ERROR("Panel operation get_edid failed %d\n", ret); |
122 | DRM_ERROR("failed to allocate edid\n"); | 123 | goto out; |
123 | return 0; | ||
124 | } | 124 | } |
125 | 125 | ||
126 | ret = display_ops->get_edid(manager->dev, connector, | 126 | count = drm_add_edid_modes(connector, edid); |
127 | edid, MAX_EDID); | 127 | if (count < 0) { |
128 | if (ret < 0) { | 128 | DRM_ERROR("Add edid modes failed %d\n", count); |
129 | DRM_ERROR("failed to get edid data.\n"); | 129 | goto out; |
130 | kfree(edid); | ||
131 | edid = NULL; | ||
132 | return 0; | ||
133 | } | 130 | } |
134 | 131 | ||
135 | drm_mode_connector_update_edid_property(connector, edid); | 132 | drm_mode_connector_update_edid_property(connector, edid); |
136 | count = drm_add_edid_modes(connector, edid); | ||
137 | kfree(edid); | ||
138 | } else { | 133 | } else { |
139 | struct exynos_drm_panel_info *panel; | 134 | struct exynos_drm_panel_info *panel; |
140 | struct drm_display_mode *mode = drm_mode_create(connector->dev); | 135 | struct drm_display_mode *mode = drm_mode_create(connector->dev); |
@@ -161,6 +156,8 @@ static int exynos_drm_connector_get_modes(struct drm_connector *connector) | |||
161 | count = 1; | 156 | count = 1; |
162 | } | 157 | } |
163 | 158 | ||
159 | out: | ||
160 | kfree(edid); | ||
164 | return count; | 161 | return count; |
165 | } | 162 | } |
166 | 163 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c index 9df97714b6c0..ba0a3aa78547 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c +++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c | |||
@@ -19,6 +19,7 @@ | |||
19 | struct exynos_drm_dmabuf_attachment { | 19 | struct exynos_drm_dmabuf_attachment { |
20 | struct sg_table sgt; | 20 | struct sg_table sgt; |
21 | enum dma_data_direction dir; | 21 | enum dma_data_direction dir; |
22 | bool is_mapped; | ||
22 | }; | 23 | }; |
23 | 24 | ||
24 | static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf, | 25 | static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf, |
@@ -72,17 +73,10 @@ static struct sg_table * | |||
72 | 73 | ||
73 | DRM_DEBUG_PRIME("%s\n", __FILE__); | 74 | DRM_DEBUG_PRIME("%s\n", __FILE__); |
74 | 75 | ||
75 | if (WARN_ON(dir == DMA_NONE)) | ||
76 | return ERR_PTR(-EINVAL); | ||
77 | |||
78 | /* just return current sgt if already requested. */ | 76 | /* just return current sgt if already requested. */ |
79 | if (exynos_attach->dir == dir) | 77 | if (exynos_attach->dir == dir && exynos_attach->is_mapped) |
80 | return &exynos_attach->sgt; | 78 | return &exynos_attach->sgt; |
81 | 79 | ||
82 | /* reattaching is not allowed. */ | ||
83 | if (WARN_ON(exynos_attach->dir != DMA_NONE)) | ||
84 | return ERR_PTR(-EBUSY); | ||
85 | |||
86 | buf = gem_obj->buffer; | 80 | buf = gem_obj->buffer; |
87 | if (!buf) { | 81 | if (!buf) { |
88 | DRM_ERROR("buffer is null.\n"); | 82 | DRM_ERROR("buffer is null.\n"); |
@@ -107,13 +101,17 @@ static struct sg_table * | |||
107 | wr = sg_next(wr); | 101 | wr = sg_next(wr); |
108 | } | 102 | } |
109 | 103 | ||
110 | nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); | 104 | if (dir != DMA_NONE) { |
111 | if (!nents) { | 105 | nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir); |
112 | DRM_ERROR("failed to map sgl with iommu.\n"); | 106 | if (!nents) { |
113 | sgt = ERR_PTR(-EIO); | 107 | DRM_ERROR("failed to map sgl with iommu.\n"); |
114 | goto err_unlock; | 108 | sg_free_table(sgt); |
109 | sgt = ERR_PTR(-EIO); | ||
110 | goto err_unlock; | ||
111 | } | ||
115 | } | 112 | } |
116 | 113 | ||
114 | exynos_attach->is_mapped = true; | ||
117 | exynos_attach->dir = dir; | 115 | exynos_attach->dir = dir; |
118 | attach->priv = exynos_attach; | 116 | attach->priv = exynos_attach; |
119 | 117 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h index b9e51bc09e81..4606fac7241a 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_drv.h +++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h | |||
@@ -148,8 +148,8 @@ struct exynos_drm_overlay { | |||
148 | struct exynos_drm_display_ops { | 148 | struct exynos_drm_display_ops { |
149 | enum exynos_drm_output_type type; | 149 | enum exynos_drm_output_type type; |
150 | bool (*is_connected)(struct device *dev); | 150 | bool (*is_connected)(struct device *dev); |
151 | int (*get_edid)(struct device *dev, struct drm_connector *connector, | 151 | struct edid *(*get_edid)(struct device *dev, |
152 | u8 *edid, int len); | 152 | struct drm_connector *connector); |
153 | void *(*get_panel)(struct device *dev); | 153 | void *(*get_panel)(struct device *dev); |
154 | int (*check_timing)(struct device *dev, void *timing); | 154 | int (*check_timing)(struct device *dev, void *timing); |
155 | int (*power_on)(struct device *dev, int mode); | 155 | int (*power_on)(struct device *dev, int mode); |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c index 36c3905536a6..9a4c08e7453c 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c +++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c | |||
@@ -324,7 +324,7 @@ out: | |||
324 | g2d_userptr = NULL; | 324 | g2d_userptr = NULL; |
325 | } | 325 | } |
326 | 326 | ||
327 | dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, | 327 | static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev, |
328 | unsigned long userptr, | 328 | unsigned long userptr, |
329 | unsigned long size, | 329 | unsigned long size, |
330 | struct drm_file *filp, | 330 | struct drm_file *filp, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c index 850e9950b7da..28644539b305 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c | |||
@@ -108,18 +108,17 @@ static bool drm_hdmi_is_connected(struct device *dev) | |||
108 | return false; | 108 | return false; |
109 | } | 109 | } |
110 | 110 | ||
111 | static int drm_hdmi_get_edid(struct device *dev, | 111 | static struct edid *drm_hdmi_get_edid(struct device *dev, |
112 | struct drm_connector *connector, u8 *edid, int len) | 112 | struct drm_connector *connector) |
113 | { | 113 | { |
114 | struct drm_hdmi_context *ctx = to_context(dev); | 114 | struct drm_hdmi_context *ctx = to_context(dev); |
115 | 115 | ||
116 | DRM_DEBUG_KMS("%s\n", __FILE__); | 116 | DRM_DEBUG_KMS("%s\n", __FILE__); |
117 | 117 | ||
118 | if (hdmi_ops && hdmi_ops->get_edid) | 118 | if (hdmi_ops && hdmi_ops->get_edid) |
119 | return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid, | 119 | return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector); |
120 | len); | ||
121 | 120 | ||
122 | return 0; | 121 | return NULL; |
123 | } | 122 | } |
124 | 123 | ||
125 | static int drm_hdmi_check_timing(struct device *dev, void *timing) | 124 | static int drm_hdmi_check_timing(struct device *dev, void *timing) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h index 784a7e9a766c..d80516fc9ed7 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h +++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h | |||
@@ -30,8 +30,8 @@ struct exynos_drm_hdmi_context { | |||
30 | struct exynos_hdmi_ops { | 30 | struct exynos_hdmi_ops { |
31 | /* display */ | 31 | /* display */ |
32 | bool (*is_connected)(void *ctx); | 32 | bool (*is_connected)(void *ctx); |
33 | int (*get_edid)(void *ctx, struct drm_connector *connector, | 33 | struct edid *(*get_edid)(void *ctx, |
34 | u8 *edid, int len); | 34 | struct drm_connector *connector); |
35 | int (*check_timing)(void *ctx, void *timing); | 35 | int (*check_timing)(void *ctx, void *timing); |
36 | int (*power_on)(void *ctx, int mode); | 36 | int (*power_on)(void *ctx, int mode); |
37 | 37 | ||
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c index 0bda96454a02..1a556354e92f 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c +++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c | |||
@@ -869,7 +869,7 @@ static void ipp_put_event(struct drm_exynos_ipp_cmd_node *c_node, | |||
869 | } | 869 | } |
870 | } | 870 | } |
871 | 871 | ||
872 | void ipp_handle_cmd_work(struct device *dev, | 872 | static void ipp_handle_cmd_work(struct device *dev, |
873 | struct exynos_drm_ippdrv *ippdrv, | 873 | struct exynos_drm_ippdrv *ippdrv, |
874 | struct drm_exynos_ipp_cmd_work *cmd_work, | 874 | struct drm_exynos_ipp_cmd_work *cmd_work, |
875 | struct drm_exynos_ipp_cmd_node *c_node) | 875 | struct drm_exynos_ipp_cmd_node *c_node) |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c index e9e83ef688f0..f976e29def6e 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c +++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c | |||
@@ -734,7 +734,7 @@ static int rotator_remove(struct platform_device *pdev) | |||
734 | return 0; | 734 | return 0; |
735 | } | 735 | } |
736 | 736 | ||
737 | struct rot_limit_table rot_limit_tbl = { | 737 | static struct rot_limit_table rot_limit_tbl = { |
738 | .ycbcr420_2p = { | 738 | .ycbcr420_2p = { |
739 | .min_w = 32, | 739 | .min_w = 32, |
740 | .min_h = 32, | 740 | .min_h = 32, |
@@ -751,7 +751,7 @@ struct rot_limit_table rot_limit_tbl = { | |||
751 | }, | 751 | }, |
752 | }; | 752 | }; |
753 | 753 | ||
754 | struct platform_device_id rotator_driver_ids[] = { | 754 | static struct platform_device_id rotator_driver_ids[] = { |
755 | { | 755 | { |
756 | .name = "exynos-rot", | 756 | .name = "exynos-rot", |
757 | .driver_data = (unsigned long)&rot_limit_tbl, | 757 | .driver_data = (unsigned long)&rot_limit_tbl, |
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c index d0ca3c4e06c6..13ccbd4bcfaa 100644 --- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c +++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c | |||
@@ -98,10 +98,12 @@ static bool vidi_display_is_connected(struct device *dev) | |||
98 | return ctx->connected ? true : false; | 98 | return ctx->connected ? true : false; |
99 | } | 99 | } |
100 | 100 | ||
101 | static int vidi_get_edid(struct device *dev, struct drm_connector *connector, | 101 | static struct edid *vidi_get_edid(struct device *dev, |
102 | u8 *edid, int len) | 102 | struct drm_connector *connector) |
103 | { | 103 | { |
104 | struct vidi_context *ctx = get_vidi_context(dev); | 104 | struct vidi_context *ctx = get_vidi_context(dev); |
105 | struct edid *edid; | ||
106 | int edid_len; | ||
105 | 107 | ||
106 | DRM_DEBUG_KMS("%s\n", __FILE__); | 108 | DRM_DEBUG_KMS("%s\n", __FILE__); |
107 | 109 | ||
@@ -111,13 +113,18 @@ static int vidi_get_edid(struct device *dev, struct drm_connector *connector, | |||
111 | */ | 113 | */ |
112 | if (!ctx->raw_edid) { | 114 | if (!ctx->raw_edid) { |
113 | DRM_DEBUG_KMS("raw_edid is null.\n"); | 115 | DRM_DEBUG_KMS("raw_edid is null.\n"); |
114 | return -EFAULT; | 116 | return ERR_PTR(-EFAULT); |
115 | } | 117 | } |
116 | 118 | ||
117 | memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions) | 119 | edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH; |
118 | * EDID_LENGTH, len)); | 120 | edid = kzalloc(edid_len, GFP_KERNEL); |
121 | if (!edid) { | ||
122 | DRM_DEBUG_KMS("failed to allocate edid\n"); | ||
123 | return ERR_PTR(-ENOMEM); | ||
124 | } | ||
119 | 125 | ||
120 | return 0; | 126 | memcpy(edid, ctx->raw_edid, edid_len); |
127 | return edid; | ||
121 | } | 128 | } |
122 | 129 | ||
123 | static void *vidi_get_panel(struct device *dev) | 130 | static void *vidi_get_panel(struct device *dev) |
@@ -514,7 +521,6 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, | |||
514 | struct exynos_drm_manager *manager; | 521 | struct exynos_drm_manager *manager; |
515 | struct exynos_drm_display_ops *display_ops; | 522 | struct exynos_drm_display_ops *display_ops; |
516 | struct drm_exynos_vidi_connection *vidi = data; | 523 | struct drm_exynos_vidi_connection *vidi = data; |
517 | struct edid *raw_edid; | ||
518 | int edid_len; | 524 | int edid_len; |
519 | 525 | ||
520 | DRM_DEBUG_KMS("%s\n", __FILE__); | 526 | DRM_DEBUG_KMS("%s\n", __FILE__); |
@@ -551,11 +557,11 @@ int vidi_connection_ioctl(struct drm_device *drm_dev, void *data, | |||
551 | } | 557 | } |
552 | 558 | ||
553 | if (vidi->connection) { | 559 | if (vidi->connection) { |
554 | if (!vidi->edid) { | 560 | struct edid *raw_edid = (struct edid *)(uint32_t)vidi->edid; |
555 | DRM_DEBUG_KMS("edid data is null.\n"); | 561 | if (!drm_edid_is_valid(raw_edid)) { |
562 | DRM_DEBUG_KMS("edid data is invalid.\n"); | ||
556 | return -EINVAL; | 563 | return -EINVAL; |
557 | } | 564 | } |
558 | raw_edid = (struct edid *)(uint32_t)vidi->edid; | ||
559 | edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; | 565 | edid_len = (1 + raw_edid->extensions) * EDID_LENGTH; |
560 | ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); | 566 | ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL); |
561 | if (!ctx->raw_edid) { | 567 | if (!ctx->raw_edid) { |
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c index 41ff79d8ac8e..fbab3c468603 100644 --- a/drivers/gpu/drm/exynos/exynos_hdmi.c +++ b/drivers/gpu/drm/exynos/exynos_hdmi.c | |||
@@ -34,7 +34,6 @@ | |||
34 | #include <linux/regulator/consumer.h> | 34 | #include <linux/regulator/consumer.h> |
35 | #include <linux/io.h> | 35 | #include <linux/io.h> |
36 | #include <linux/of_gpio.h> | 36 | #include <linux/of_gpio.h> |
37 | #include <plat/gpio-cfg.h> | ||
38 | 37 | ||
39 | #include <drm/exynos_drm.h> | 38 | #include <drm/exynos_drm.h> |
40 | 39 | ||
@@ -98,8 +97,7 @@ struct hdmi_context { | |||
98 | 97 | ||
99 | void __iomem *regs; | 98 | void __iomem *regs; |
100 | void *parent_ctx; | 99 | void *parent_ctx; |
101 | int external_irq; | 100 | int irq; |
102 | int internal_irq; | ||
103 | 101 | ||
104 | struct i2c_client *ddc_port; | 102 | struct i2c_client *ddc_port; |
105 | struct i2c_client *hdmiphy_port; | 103 | struct i2c_client *hdmiphy_port; |
@@ -1391,8 +1389,7 @@ static bool hdmi_is_connected(void *ctx) | |||
1391 | return hdata->hpd; | 1389 | return hdata->hpd; |
1392 | } | 1390 | } |
1393 | 1391 | ||
1394 | static int hdmi_get_edid(void *ctx, struct drm_connector *connector, | 1392 | static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector) |
1395 | u8 *edid, int len) | ||
1396 | { | 1393 | { |
1397 | struct edid *raw_edid; | 1394 | struct edid *raw_edid; |
1398 | struct hdmi_context *hdata = ctx; | 1395 | struct hdmi_context *hdata = ctx; |
@@ -1400,22 +1397,18 @@ static int hdmi_get_edid(void *ctx, struct drm_connector *connector, | |||
1400 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | 1397 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); |
1401 | 1398 | ||
1402 | if (!hdata->ddc_port) | 1399 | if (!hdata->ddc_port) |
1403 | return -ENODEV; | 1400 | return ERR_PTR(-ENODEV); |
1404 | 1401 | ||
1405 | raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); | 1402 | raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter); |
1406 | if (raw_edid) { | 1403 | if (!raw_edid) |
1407 | hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); | 1404 | return ERR_PTR(-ENODEV); |
1408 | memcpy(edid, raw_edid, min((1 + raw_edid->extensions) | ||
1409 | * EDID_LENGTH, len)); | ||
1410 | DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", | ||
1411 | (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), | ||
1412 | raw_edid->width_cm, raw_edid->height_cm); | ||
1413 | kfree(raw_edid); | ||
1414 | } else { | ||
1415 | return -ENODEV; | ||
1416 | } | ||
1417 | 1405 | ||
1418 | return 0; | 1406 | hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid); |
1407 | DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n", | ||
1408 | (hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"), | ||
1409 | raw_edid->width_cm, raw_edid->height_cm); | ||
1410 | |||
1411 | return raw_edid; | ||
1419 | } | 1412 | } |
1420 | 1413 | ||
1421 | static int hdmi_v13_check_timing(struct fb_videomode *check_timing) | 1414 | static int hdmi_v13_check_timing(struct fb_videomode *check_timing) |
@@ -1652,16 +1645,16 @@ static void hdmi_conf_reset(struct hdmi_context *hdata) | |||
1652 | 1645 | ||
1653 | /* resetting HDMI core */ | 1646 | /* resetting HDMI core */ |
1654 | hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); | 1647 | hdmi_reg_writemask(hdata, reg, 0, HDMI_CORE_SW_RSTOUT); |
1655 | mdelay(10); | 1648 | usleep_range(10000, 12000); |
1656 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); | 1649 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); |
1657 | mdelay(10); | 1650 | usleep_range(10000, 12000); |
1658 | } | 1651 | } |
1659 | 1652 | ||
1660 | static void hdmi_conf_init(struct hdmi_context *hdata) | 1653 | static void hdmi_conf_init(struct hdmi_context *hdata) |
1661 | { | 1654 | { |
1662 | struct hdmi_infoframe infoframe; | 1655 | struct hdmi_infoframe infoframe; |
1663 | 1656 | ||
1664 | /* disable HPD interrupts */ | 1657 | /* disable HPD interrupts from HDMI IP block, use GPIO instead */ |
1665 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | | 1658 | hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | |
1666 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); | 1659 | HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); |
1667 | 1660 | ||
@@ -1779,7 +1772,7 @@ static void hdmi_v13_timing_apply(struct hdmi_context *hdata) | |||
1779 | u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); | 1772 | u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS); |
1780 | if (val & HDMI_PHY_STATUS_READY) | 1773 | if (val & HDMI_PHY_STATUS_READY) |
1781 | break; | 1774 | break; |
1782 | mdelay(1); | 1775 | usleep_range(1000, 2000); |
1783 | } | 1776 | } |
1784 | /* steady state not achieved */ | 1777 | /* steady state not achieved */ |
1785 | if (tries == 0) { | 1778 | if (tries == 0) { |
@@ -1946,7 +1939,7 @@ static void hdmi_v14_timing_apply(struct hdmi_context *hdata) | |||
1946 | u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); | 1939 | u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0); |
1947 | if (val & HDMI_PHY_STATUS_READY) | 1940 | if (val & HDMI_PHY_STATUS_READY) |
1948 | break; | 1941 | break; |
1949 | mdelay(1); | 1942 | usleep_range(1000, 2000); |
1950 | } | 1943 | } |
1951 | /* steady state not achieved */ | 1944 | /* steady state not achieved */ |
1952 | if (tries == 0) { | 1945 | if (tries == 0) { |
@@ -1998,9 +1991,9 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata) | |||
1998 | 1991 | ||
1999 | /* reset hdmiphy */ | 1992 | /* reset hdmiphy */ |
2000 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); | 1993 | hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT); |
2001 | mdelay(10); | 1994 | usleep_range(10000, 12000); |
2002 | hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); | 1995 | hdmi_reg_writemask(hdata, reg, 0, HDMI_PHY_SW_RSTOUT); |
2003 | mdelay(10); | 1996 | usleep_range(10000, 12000); |
2004 | } | 1997 | } |
2005 | 1998 | ||
2006 | static void hdmiphy_poweron(struct hdmi_context *hdata) | 1999 | static void hdmiphy_poweron(struct hdmi_context *hdata) |
@@ -2048,7 +2041,7 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata) | |||
2048 | return; | 2041 | return; |
2049 | } | 2042 | } |
2050 | 2043 | ||
2051 | mdelay(10); | 2044 | usleep_range(10000, 12000); |
2052 | 2045 | ||
2053 | /* operation mode */ | 2046 | /* operation mode */ |
2054 | operation[0] = 0x1f; | 2047 | operation[0] = 0x1f; |
@@ -2170,6 +2163,13 @@ static void hdmi_commit(void *ctx) | |||
2170 | 2163 | ||
2171 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | 2164 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); |
2172 | 2165 | ||
2166 | mutex_lock(&hdata->hdmi_mutex); | ||
2167 | if (!hdata->powered) { | ||
2168 | mutex_unlock(&hdata->hdmi_mutex); | ||
2169 | return; | ||
2170 | } | ||
2171 | mutex_unlock(&hdata->hdmi_mutex); | ||
2172 | |||
2173 | hdmi_conf_apply(hdata); | 2173 | hdmi_conf_apply(hdata); |
2174 | } | 2174 | } |
2175 | 2175 | ||
@@ -2265,7 +2265,7 @@ static struct exynos_hdmi_ops hdmi_ops = { | |||
2265 | .dpms = hdmi_dpms, | 2265 | .dpms = hdmi_dpms, |
2266 | }; | 2266 | }; |
2267 | 2267 | ||
2268 | static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) | 2268 | static irqreturn_t hdmi_irq_thread(int irq, void *arg) |
2269 | { | 2269 | { |
2270 | struct exynos_drm_hdmi_context *ctx = arg; | 2270 | struct exynos_drm_hdmi_context *ctx = arg; |
2271 | struct hdmi_context *hdata = ctx->ctx; | 2271 | struct hdmi_context *hdata = ctx->ctx; |
@@ -2280,31 +2280,6 @@ static irqreturn_t hdmi_external_irq_thread(int irq, void *arg) | |||
2280 | return IRQ_HANDLED; | 2280 | return IRQ_HANDLED; |
2281 | } | 2281 | } |
2282 | 2282 | ||
2283 | static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg) | ||
2284 | { | ||
2285 | struct exynos_drm_hdmi_context *ctx = arg; | ||
2286 | struct hdmi_context *hdata = ctx->ctx; | ||
2287 | u32 intc_flag; | ||
2288 | |||
2289 | intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); | ||
2290 | /* clearing flags for HPD plug/unplug */ | ||
2291 | if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { | ||
2292 | DRM_DEBUG_KMS("unplugged\n"); | ||
2293 | hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, | ||
2294 | HDMI_INTC_FLAG_HPD_UNPLUG); | ||
2295 | } | ||
2296 | if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { | ||
2297 | DRM_DEBUG_KMS("plugged\n"); | ||
2298 | hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, | ||
2299 | HDMI_INTC_FLAG_HPD_PLUG); | ||
2300 | } | ||
2301 | |||
2302 | if (ctx->drm_dev) | ||
2303 | drm_helper_hpd_irq_event(ctx->drm_dev); | ||
2304 | |||
2305 | return IRQ_HANDLED; | ||
2306 | } | ||
2307 | |||
2308 | static int hdmi_resources_init(struct hdmi_context *hdata) | 2283 | static int hdmi_resources_init(struct hdmi_context *hdata) |
2309 | { | 2284 | { |
2310 | struct device *dev = hdata->dev; | 2285 | struct device *dev = hdata->dev; |
@@ -2555,39 +2530,24 @@ static int hdmi_probe(struct platform_device *pdev) | |||
2555 | 2530 | ||
2556 | hdata->hdmiphy_port = hdmi_hdmiphy; | 2531 | hdata->hdmiphy_port = hdmi_hdmiphy; |
2557 | 2532 | ||
2558 | hdata->external_irq = gpio_to_irq(hdata->hpd_gpio); | 2533 | hdata->irq = gpio_to_irq(hdata->hpd_gpio); |
2559 | if (hdata->external_irq < 0) { | 2534 | if (hdata->irq < 0) { |
2560 | DRM_ERROR("failed to get GPIO external irq\n"); | 2535 | DRM_ERROR("failed to get GPIO irq\n"); |
2561 | ret = hdata->external_irq; | 2536 | ret = hdata->irq; |
2562 | goto err_hdmiphy; | ||
2563 | } | ||
2564 | |||
2565 | hdata->internal_irq = platform_get_irq(pdev, 0); | ||
2566 | if (hdata->internal_irq < 0) { | ||
2567 | DRM_ERROR("failed to get platform internal irq\n"); | ||
2568 | ret = hdata->internal_irq; | ||
2569 | goto err_hdmiphy; | 2537 | goto err_hdmiphy; |
2570 | } | 2538 | } |
2571 | 2539 | ||
2572 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | 2540 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); |
2573 | 2541 | ||
2574 | ret = request_threaded_irq(hdata->external_irq, NULL, | 2542 | ret = request_threaded_irq(hdata->irq, NULL, |
2575 | hdmi_external_irq_thread, IRQF_TRIGGER_RISING | | 2543 | hdmi_irq_thread, IRQF_TRIGGER_RISING | |
2576 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | 2544 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, |
2577 | "hdmi_external", drm_hdmi_ctx); | 2545 | "hdmi", drm_hdmi_ctx); |
2578 | if (ret) { | 2546 | if (ret) { |
2579 | DRM_ERROR("failed to register hdmi external interrupt\n"); | 2547 | DRM_ERROR("failed to register hdmi interrupt\n"); |
2580 | goto err_hdmiphy; | 2548 | goto err_hdmiphy; |
2581 | } | 2549 | } |
2582 | 2550 | ||
2583 | ret = request_threaded_irq(hdata->internal_irq, NULL, | ||
2584 | hdmi_internal_irq_thread, IRQF_ONESHOT, | ||
2585 | "hdmi_internal", drm_hdmi_ctx); | ||
2586 | if (ret) { | ||
2587 | DRM_ERROR("failed to register hdmi internal interrupt\n"); | ||
2588 | goto err_free_irq; | ||
2589 | } | ||
2590 | |||
2591 | /* Attach HDMI Driver to common hdmi. */ | 2551 | /* Attach HDMI Driver to common hdmi. */ |
2592 | exynos_hdmi_drv_attach(drm_hdmi_ctx); | 2552 | exynos_hdmi_drv_attach(drm_hdmi_ctx); |
2593 | 2553 | ||
@@ -2598,8 +2558,6 @@ static int hdmi_probe(struct platform_device *pdev) | |||
2598 | 2558 | ||
2599 | return 0; | 2559 | return 0; |
2600 | 2560 | ||
2601 | err_free_irq: | ||
2602 | free_irq(hdata->external_irq, drm_hdmi_ctx); | ||
2603 | err_hdmiphy: | 2561 | err_hdmiphy: |
2604 | i2c_del_driver(&hdmiphy_driver); | 2562 | i2c_del_driver(&hdmiphy_driver); |
2605 | err_ddc: | 2563 | err_ddc: |
@@ -2617,8 +2575,7 @@ static int hdmi_remove(struct platform_device *pdev) | |||
2617 | 2575 | ||
2618 | pm_runtime_disable(dev); | 2576 | pm_runtime_disable(dev); |
2619 | 2577 | ||
2620 | free_irq(hdata->internal_irq, hdata); | 2578 | free_irq(hdata->irq, hdata); |
2621 | free_irq(hdata->external_irq, hdata); | ||
2622 | 2579 | ||
2623 | 2580 | ||
2624 | /* hdmiphy i2c driver */ | 2581 | /* hdmiphy i2c driver */ |
@@ -2637,8 +2594,7 @@ static int hdmi_suspend(struct device *dev) | |||
2637 | 2594 | ||
2638 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); | 2595 | DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); |
2639 | 2596 | ||
2640 | disable_irq(hdata->internal_irq); | 2597 | disable_irq(hdata->irq); |
2641 | disable_irq(hdata->external_irq); | ||
2642 | 2598 | ||
2643 | hdata->hpd = false; | 2599 | hdata->hpd = false; |
2644 | if (ctx->drm_dev) | 2600 | if (ctx->drm_dev) |
@@ -2663,8 +2619,7 @@ static int hdmi_resume(struct device *dev) | |||
2663 | 2619 | ||
2664 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); | 2620 | hdata->hpd = gpio_get_value(hdata->hpd_gpio); |
2665 | 2621 | ||
2666 | enable_irq(hdata->external_irq); | 2622 | enable_irq(hdata->irq); |
2667 | enable_irq(hdata->internal_irq); | ||
2668 | 2623 | ||
2669 | if (!pm_runtime_suspended(dev)) { | 2624 | if (!pm_runtime_suspended(dev)) { |
2670 | DRM_DEBUG_KMS("%s : Already resumed\n", __func__); | 2625 | DRM_DEBUG_KMS("%s : Already resumed\n", __func__); |
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c index c187ea33b748..c414584bfbae 100644 --- a/drivers/gpu/drm/exynos/exynos_mixer.c +++ b/drivers/gpu/drm/exynos/exynos_mixer.c | |||
@@ -600,7 +600,7 @@ static void vp_win_reset(struct mixer_context *ctx) | |||
600 | /* waiting until VP_SRESET_PROCESSING is 0 */ | 600 | /* waiting until VP_SRESET_PROCESSING is 0 */ |
601 | if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) | 601 | if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING) |
602 | break; | 602 | break; |
603 | mdelay(10); | 603 | usleep_range(10000, 12000); |
604 | } | 604 | } |
605 | WARN(tries == 0, "failed to reset Video Processor\n"); | 605 | WARN(tries == 0, "failed to reset Video Processor\n"); |
606 | } | 606 | } |
@@ -776,6 +776,13 @@ static void mixer_win_commit(void *ctx, int win) | |||
776 | 776 | ||
777 | DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); | 777 | DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); |
778 | 778 | ||
779 | mutex_lock(&mixer_ctx->mixer_mutex); | ||
780 | if (!mixer_ctx->powered) { | ||
781 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
782 | return; | ||
783 | } | ||
784 | mutex_unlock(&mixer_ctx->mixer_mutex); | ||
785 | |||
779 | if (win > 1 && mixer_ctx->vp_enabled) | 786 | if (win > 1 && mixer_ctx->vp_enabled) |
780 | vp_video_buffer(mixer_ctx, win); | 787 | vp_video_buffer(mixer_ctx, win); |
781 | else | 788 | else |
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index e6a11ca85eaf..9d4a2c2adf0e 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/debugfs.h> | 30 | #include <linux/debugfs.h> |
31 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
32 | #include <linux/export.h> | 32 | #include <linux/export.h> |
33 | #include <generated/utsrelease.h> | ||
33 | #include <drm/drmP.h> | 34 | #include <drm/drmP.h> |
34 | #include "intel_drv.h" | 35 | #include "intel_drv.h" |
35 | #include "intel_ringbuffer.h" | 36 | #include "intel_ringbuffer.h" |
@@ -641,6 +642,7 @@ static void i915_ring_error_state(struct seq_file *m, | |||
641 | seq_printf(m, "%s command stream:\n", ring_str(ring)); | 642 | seq_printf(m, "%s command stream:\n", ring_str(ring)); |
642 | seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); | 643 | seq_printf(m, " HEAD: 0x%08x\n", error->head[ring]); |
643 | seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); | 644 | seq_printf(m, " TAIL: 0x%08x\n", error->tail[ring]); |
645 | seq_printf(m, " CTL: 0x%08x\n", error->ctl[ring]); | ||
644 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); | 646 | seq_printf(m, " ACTHD: 0x%08x\n", error->acthd[ring]); |
645 | seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); | 647 | seq_printf(m, " IPEIR: 0x%08x\n", error->ipeir[ring]); |
646 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); | 648 | seq_printf(m, " IPEHR: 0x%08x\n", error->ipehr[ring]); |
@@ -689,10 +691,13 @@ static int i915_error_state(struct seq_file *m, void *unused) | |||
689 | 691 | ||
690 | seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, | 692 | seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec, |
691 | error->time.tv_usec); | 693 | error->time.tv_usec); |
694 | seq_printf(m, "Kernel: " UTS_RELEASE); | ||
692 | seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); | 695 | seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device); |
693 | seq_printf(m, "EIR: 0x%08x\n", error->eir); | 696 | seq_printf(m, "EIR: 0x%08x\n", error->eir); |
694 | seq_printf(m, "IER: 0x%08x\n", error->ier); | 697 | seq_printf(m, "IER: 0x%08x\n", error->ier); |
695 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); | 698 | seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er); |
699 | seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake); | ||
700 | seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr); | ||
696 | seq_printf(m, "CCID: 0x%08x\n", error->ccid); | 701 | seq_printf(m, "CCID: 0x%08x\n", error->ccid); |
697 | 702 | ||
698 | for (i = 0; i < dev_priv->num_fence_regs; i++) | 703 | for (i = 0; i < dev_priv->num_fence_regs; i++) |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index ed3059575576..12ab3bdea54d 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -188,10 +188,13 @@ struct drm_i915_error_state { | |||
188 | u32 pgtbl_er; | 188 | u32 pgtbl_er; |
189 | u32 ier; | 189 | u32 ier; |
190 | u32 ccid; | 190 | u32 ccid; |
191 | u32 derrmr; | ||
192 | u32 forcewake; | ||
191 | bool waiting[I915_NUM_RINGS]; | 193 | bool waiting[I915_NUM_RINGS]; |
192 | u32 pipestat[I915_MAX_PIPES]; | 194 | u32 pipestat[I915_MAX_PIPES]; |
193 | u32 tail[I915_NUM_RINGS]; | 195 | u32 tail[I915_NUM_RINGS]; |
194 | u32 head[I915_NUM_RINGS]; | 196 | u32 head[I915_NUM_RINGS]; |
197 | u32 ctl[I915_NUM_RINGS]; | ||
195 | u32 ipeir[I915_NUM_RINGS]; | 198 | u32 ipeir[I915_NUM_RINGS]; |
196 | u32 ipehr[I915_NUM_RINGS]; | 199 | u32 ipehr[I915_NUM_RINGS]; |
197 | u32 instdone[I915_NUM_RINGS]; | 200 | u32 instdone[I915_NUM_RINGS]; |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index da3c82e301b1..8febea6daa08 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -1717,7 +1717,8 @@ i915_gem_object_put_pages(struct drm_i915_gem_object *obj) | |||
1717 | } | 1717 | } |
1718 | 1718 | ||
1719 | static long | 1719 | static long |
1720 | i915_gem_purge(struct drm_i915_private *dev_priv, long target) | 1720 | __i915_gem_shrink(struct drm_i915_private *dev_priv, long target, |
1721 | bool purgeable_only) | ||
1721 | { | 1722 | { |
1722 | struct drm_i915_gem_object *obj, *next; | 1723 | struct drm_i915_gem_object *obj, *next; |
1723 | long count = 0; | 1724 | long count = 0; |
@@ -1725,7 +1726,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) | |||
1725 | list_for_each_entry_safe(obj, next, | 1726 | list_for_each_entry_safe(obj, next, |
1726 | &dev_priv->mm.unbound_list, | 1727 | &dev_priv->mm.unbound_list, |
1727 | gtt_list) { | 1728 | gtt_list) { |
1728 | if (i915_gem_object_is_purgeable(obj) && | 1729 | if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && |
1729 | i915_gem_object_put_pages(obj) == 0) { | 1730 | i915_gem_object_put_pages(obj) == 0) { |
1730 | count += obj->base.size >> PAGE_SHIFT; | 1731 | count += obj->base.size >> PAGE_SHIFT; |
1731 | if (count >= target) | 1732 | if (count >= target) |
@@ -1736,7 +1737,7 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) | |||
1736 | list_for_each_entry_safe(obj, next, | 1737 | list_for_each_entry_safe(obj, next, |
1737 | &dev_priv->mm.inactive_list, | 1738 | &dev_priv->mm.inactive_list, |
1738 | mm_list) { | 1739 | mm_list) { |
1739 | if (i915_gem_object_is_purgeable(obj) && | 1740 | if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) && |
1740 | i915_gem_object_unbind(obj) == 0 && | 1741 | i915_gem_object_unbind(obj) == 0 && |
1741 | i915_gem_object_put_pages(obj) == 0) { | 1742 | i915_gem_object_put_pages(obj) == 0) { |
1742 | count += obj->base.size >> PAGE_SHIFT; | 1743 | count += obj->base.size >> PAGE_SHIFT; |
@@ -1748,6 +1749,12 @@ i915_gem_purge(struct drm_i915_private *dev_priv, long target) | |||
1748 | return count; | 1749 | return count; |
1749 | } | 1750 | } |
1750 | 1751 | ||
1752 | static long | ||
1753 | i915_gem_purge(struct drm_i915_private *dev_priv, long target) | ||
1754 | { | ||
1755 | return __i915_gem_shrink(dev_priv, target, true); | ||
1756 | } | ||
1757 | |||
1751 | static void | 1758 | static void |
1752 | i915_gem_shrink_all(struct drm_i915_private *dev_priv) | 1759 | i915_gem_shrink_all(struct drm_i915_private *dev_priv) |
1753 | { | 1760 | { |
@@ -3522,14 +3529,15 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, | |||
3522 | goto out; | 3529 | goto out; |
3523 | } | 3530 | } |
3524 | 3531 | ||
3525 | obj->user_pin_count++; | 3532 | if (obj->user_pin_count == 0) { |
3526 | obj->pin_filp = file; | ||
3527 | if (obj->user_pin_count == 1) { | ||
3528 | ret = i915_gem_object_pin(obj, args->alignment, true, false); | 3533 | ret = i915_gem_object_pin(obj, args->alignment, true, false); |
3529 | if (ret) | 3534 | if (ret) |
3530 | goto out; | 3535 | goto out; |
3531 | } | 3536 | } |
3532 | 3537 | ||
3538 | obj->user_pin_count++; | ||
3539 | obj->pin_filp = file; | ||
3540 | |||
3533 | /* XXX - flush the CPU caches for pinned objects | 3541 | /* XXX - flush the CPU caches for pinned objects |
3534 | * as the X server doesn't manage domains yet | 3542 | * as the X server doesn't manage domains yet |
3535 | */ | 3543 | */ |
@@ -4395,6 +4403,9 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) | |||
4395 | if (nr_to_scan) { | 4403 | if (nr_to_scan) { |
4396 | nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); | 4404 | nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan); |
4397 | if (nr_to_scan > 0) | 4405 | if (nr_to_scan > 0) |
4406 | nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan, | ||
4407 | false); | ||
4408 | if (nr_to_scan > 0) | ||
4398 | i915_gem_shrink_all(dev_priv); | 4409 | i915_gem_shrink_all(dev_priv); |
4399 | } | 4410 | } |
4400 | 4411 | ||
@@ -4402,7 +4413,7 @@ i915_gem_inactive_shrink(struct shrinker *shrinker, struct shrink_control *sc) | |||
4402 | list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) | 4413 | list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list) |
4403 | if (obj->pages_pin_count == 0) | 4414 | if (obj->pages_pin_count == 0) |
4404 | cnt += obj->base.size >> PAGE_SHIFT; | 4415 | cnt += obj->base.size >> PAGE_SHIFT; |
4405 | list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list) | 4416 | list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list) |
4406 | if (obj->pin_count == 0 && obj->pages_pin_count == 0) | 4417 | if (obj->pin_count == 0 && obj->pages_pin_count == 0) |
4407 | cnt += obj->base.size >> PAGE_SHIFT; | 4418 | cnt += obj->base.size >> PAGE_SHIFT; |
4408 | 4419 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c index d6a994a07393..26d08bb58218 100644 --- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c +++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c | |||
@@ -539,6 +539,8 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
539 | total = 0; | 539 | total = 0; |
540 | for (i = 0; i < count; i++) { | 540 | for (i = 0; i < count; i++) { |
541 | struct drm_i915_gem_relocation_entry __user *user_relocs; | 541 | struct drm_i915_gem_relocation_entry __user *user_relocs; |
542 | u64 invalid_offset = (u64)-1; | ||
543 | int j; | ||
542 | 544 | ||
543 | user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; | 545 | user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr; |
544 | 546 | ||
@@ -549,6 +551,25 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev, | |||
549 | goto err; | 551 | goto err; |
550 | } | 552 | } |
551 | 553 | ||
554 | /* As we do not update the known relocation offsets after | ||
555 | * relocating (due to the complexities in lock handling), | ||
556 | * we need to mark them as invalid now so that we force the | ||
557 | * relocation processing next time. Just in case the target | ||
558 | * object is evicted and then rebound into its old | ||
559 | * presumed_offset before the next execbuffer - if that | ||
560 | * happened we would make the mistake of assuming that the | ||
561 | * relocations were valid. | ||
562 | */ | ||
563 | for (j = 0; j < exec[i].relocation_count; j++) { | ||
564 | if (copy_to_user(&user_relocs[j].presumed_offset, | ||
565 | &invalid_offset, | ||
566 | sizeof(invalid_offset))) { | ||
567 | ret = -EFAULT; | ||
568 | mutex_lock(&dev->struct_mutex); | ||
569 | goto err; | ||
570 | } | ||
571 | } | ||
572 | |||
552 | reloc_offset[i] = total; | 573 | reloc_offset[i] = total; |
553 | total += exec[i].relocation_count; | 574 | total += exec[i].relocation_count; |
554 | } | 575 | } |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 2220dec3e5d9..fe843389c7b4 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -1157,6 +1157,7 @@ static void i915_record_ring_state(struct drm_device *dev, | |||
1157 | error->acthd[ring->id] = intel_ring_get_active_head(ring); | 1157 | error->acthd[ring->id] = intel_ring_get_active_head(ring); |
1158 | error->head[ring->id] = I915_READ_HEAD(ring); | 1158 | error->head[ring->id] = I915_READ_HEAD(ring); |
1159 | error->tail[ring->id] = I915_READ_TAIL(ring); | 1159 | error->tail[ring->id] = I915_READ_TAIL(ring); |
1160 | error->ctl[ring->id] = I915_READ_CTL(ring); | ||
1160 | 1161 | ||
1161 | error->cpu_ring_head[ring->id] = ring->head; | 1162 | error->cpu_ring_head[ring->id] = ring->head; |
1162 | error->cpu_ring_tail[ring->id] = ring->tail; | 1163 | error->cpu_ring_tail[ring->id] = ring->tail; |
@@ -1251,6 +1252,16 @@ static void i915_capture_error_state(struct drm_device *dev) | |||
1251 | else | 1252 | else |
1252 | error->ier = I915_READ(IER); | 1253 | error->ier = I915_READ(IER); |
1253 | 1254 | ||
1255 | if (INTEL_INFO(dev)->gen >= 6) | ||
1256 | error->derrmr = I915_READ(DERRMR); | ||
1257 | |||
1258 | if (IS_VALLEYVIEW(dev)) | ||
1259 | error->forcewake = I915_READ(FORCEWAKE_VLV); | ||
1260 | else if (INTEL_INFO(dev)->gen >= 7) | ||
1261 | error->forcewake = I915_READ(FORCEWAKE_MT); | ||
1262 | else if (INTEL_INFO(dev)->gen == 6) | ||
1263 | error->forcewake = I915_READ(FORCEWAKE); | ||
1264 | |||
1254 | for_each_pipe(pipe) | 1265 | for_each_pipe(pipe) |
1255 | error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); | 1266 | error->pipestat[pipe] = I915_READ(PIPESTAT(pipe)); |
1256 | 1267 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 186ee5c85b51..59afb7eb6db6 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -512,6 +512,8 @@ | |||
512 | #define GEN7_ERR_INT 0x44040 | 512 | #define GEN7_ERR_INT 0x44040 |
513 | #define ERR_INT_MMIO_UNCLAIMED (1<<13) | 513 | #define ERR_INT_MMIO_UNCLAIMED (1<<13) |
514 | 514 | ||
515 | #define DERRMR 0x44050 | ||
516 | |||
515 | /* GM45+ chicken bits -- debug workaround bits that may be required | 517 | /* GM45+ chicken bits -- debug workaround bits that may be required |
516 | * for various sorts of correct behavior. The top 16 bits of each are | 518 | * for various sorts of correct behavior. The top 16 bits of each are |
517 | * the enables for writing to the corresponding low bit. | 519 | * the enables for writing to the corresponding low bit. |
@@ -531,6 +533,7 @@ | |||
531 | #define MI_MODE 0x0209c | 533 | #define MI_MODE 0x0209c |
532 | # define VS_TIMER_DISPATCH (1 << 6) | 534 | # define VS_TIMER_DISPATCH (1 << 6) |
533 | # define MI_FLUSH_ENABLE (1 << 12) | 535 | # define MI_FLUSH_ENABLE (1 << 12) |
536 | # define ASYNC_FLIP_PERF_DISABLE (1 << 14) | ||
534 | 537 | ||
535 | #define GEN6_GT_MODE 0x20d0 | 538 | #define GEN6_GT_MODE 0x20d0 |
536 | #define GEN6_GT_MODE_HI (1 << 9) | 539 | #define GEN6_GT_MODE_HI (1 << 9) |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index a9fb046b94a1..da1ad9c80bb5 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -8598,19 +8598,30 @@ int intel_framebuffer_init(struct drm_device *dev, | |||
8598 | { | 8598 | { |
8599 | int ret; | 8599 | int ret; |
8600 | 8600 | ||
8601 | if (obj->tiling_mode == I915_TILING_Y) | 8601 | if (obj->tiling_mode == I915_TILING_Y) { |
8602 | DRM_DEBUG("hardware does not support tiling Y\n"); | ||
8602 | return -EINVAL; | 8603 | return -EINVAL; |
8604 | } | ||
8603 | 8605 | ||
8604 | if (mode_cmd->pitches[0] & 63) | 8606 | if (mode_cmd->pitches[0] & 63) { |
8607 | DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n", | ||
8608 | mode_cmd->pitches[0]); | ||
8605 | return -EINVAL; | 8609 | return -EINVAL; |
8610 | } | ||
8606 | 8611 | ||
8607 | /* FIXME <= Gen4 stride limits are bit unclear */ | 8612 | /* FIXME <= Gen4 stride limits are bit unclear */ |
8608 | if (mode_cmd->pitches[0] > 32768) | 8613 | if (mode_cmd->pitches[0] > 32768) { |
8614 | DRM_DEBUG("pitch (%d) must be at less than 32768\n", | ||
8615 | mode_cmd->pitches[0]); | ||
8609 | return -EINVAL; | 8616 | return -EINVAL; |
8617 | } | ||
8610 | 8618 | ||
8611 | if (obj->tiling_mode != I915_TILING_NONE && | 8619 | if (obj->tiling_mode != I915_TILING_NONE && |
8612 | mode_cmd->pitches[0] != obj->stride) | 8620 | mode_cmd->pitches[0] != obj->stride) { |
8621 | DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n", | ||
8622 | mode_cmd->pitches[0], obj->stride); | ||
8613 | return -EINVAL; | 8623 | return -EINVAL; |
8624 | } | ||
8614 | 8625 | ||
8615 | /* Reject formats not supported by any plane early. */ | 8626 | /* Reject formats not supported by any plane early. */ |
8616 | switch (mode_cmd->pixel_format) { | 8627 | switch (mode_cmd->pixel_format) { |
@@ -8621,8 +8632,10 @@ int intel_framebuffer_init(struct drm_device *dev, | |||
8621 | break; | 8632 | break; |
8622 | case DRM_FORMAT_XRGB1555: | 8633 | case DRM_FORMAT_XRGB1555: |
8623 | case DRM_FORMAT_ARGB1555: | 8634 | case DRM_FORMAT_ARGB1555: |
8624 | if (INTEL_INFO(dev)->gen > 3) | 8635 | if (INTEL_INFO(dev)->gen > 3) { |
8636 | DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); | ||
8625 | return -EINVAL; | 8637 | return -EINVAL; |
8638 | } | ||
8626 | break; | 8639 | break; |
8627 | case DRM_FORMAT_XBGR8888: | 8640 | case DRM_FORMAT_XBGR8888: |
8628 | case DRM_FORMAT_ABGR8888: | 8641 | case DRM_FORMAT_ABGR8888: |
@@ -8630,18 +8643,22 @@ int intel_framebuffer_init(struct drm_device *dev, | |||
8630 | case DRM_FORMAT_ARGB2101010: | 8643 | case DRM_FORMAT_ARGB2101010: |
8631 | case DRM_FORMAT_XBGR2101010: | 8644 | case DRM_FORMAT_XBGR2101010: |
8632 | case DRM_FORMAT_ABGR2101010: | 8645 | case DRM_FORMAT_ABGR2101010: |
8633 | if (INTEL_INFO(dev)->gen < 4) | 8646 | if (INTEL_INFO(dev)->gen < 4) { |
8647 | DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); | ||
8634 | return -EINVAL; | 8648 | return -EINVAL; |
8649 | } | ||
8635 | break; | 8650 | break; |
8636 | case DRM_FORMAT_YUYV: | 8651 | case DRM_FORMAT_YUYV: |
8637 | case DRM_FORMAT_UYVY: | 8652 | case DRM_FORMAT_UYVY: |
8638 | case DRM_FORMAT_YVYU: | 8653 | case DRM_FORMAT_YVYU: |
8639 | case DRM_FORMAT_VYUY: | 8654 | case DRM_FORMAT_VYUY: |
8640 | if (INTEL_INFO(dev)->gen < 6) | 8655 | if (INTEL_INFO(dev)->gen < 5) { |
8656 | DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format); | ||
8641 | return -EINVAL; | 8657 | return -EINVAL; |
8658 | } | ||
8642 | break; | 8659 | break; |
8643 | default: | 8660 | default: |
8644 | DRM_DEBUG_KMS("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format); | 8661 | DRM_DEBUG("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format); |
8645 | return -EINVAL; | 8662 | return -EINVAL; |
8646 | } | 8663 | } |
8647 | 8664 | ||
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c index 1b63d55318a0..fb3715b4b09d 100644 --- a/drivers/gpu/drm/i915/intel_dp.c +++ b/drivers/gpu/drm/i915/intel_dp.c | |||
@@ -2579,7 +2579,8 @@ intel_dp_add_properties(struct intel_dp *intel_dp, struct drm_connector *connect | |||
2579 | 2579 | ||
2580 | static void | 2580 | static void |
2581 | intel_dp_init_panel_power_sequencer(struct drm_device *dev, | 2581 | intel_dp_init_panel_power_sequencer(struct drm_device *dev, |
2582 | struct intel_dp *intel_dp) | 2582 | struct intel_dp *intel_dp, |
2583 | struct edp_power_seq *out) | ||
2583 | { | 2584 | { |
2584 | struct drm_i915_private *dev_priv = dev->dev_private; | 2585 | struct drm_i915_private *dev_priv = dev->dev_private; |
2585 | struct edp_power_seq cur, vbt, spec, final; | 2586 | struct edp_power_seq cur, vbt, spec, final; |
@@ -2650,16 +2651,35 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |||
2650 | intel_dp->panel_power_cycle_delay = get_delay(t11_t12); | 2651 | intel_dp->panel_power_cycle_delay = get_delay(t11_t12); |
2651 | #undef get_delay | 2652 | #undef get_delay |
2652 | 2653 | ||
2654 | DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", | ||
2655 | intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, | ||
2656 | intel_dp->panel_power_cycle_delay); | ||
2657 | |||
2658 | DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||
2659 | intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||
2660 | |||
2661 | if (out) | ||
2662 | *out = final; | ||
2663 | } | ||
2664 | |||
2665 | static void | ||
2666 | intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev, | ||
2667 | struct intel_dp *intel_dp, | ||
2668 | struct edp_power_seq *seq) | ||
2669 | { | ||
2670 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
2671 | u32 pp_on, pp_off, pp_div; | ||
2672 | |||
2653 | /* And finally store the new values in the power sequencer. */ | 2673 | /* And finally store the new values in the power sequencer. */ |
2654 | pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | | 2674 | pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) | |
2655 | (final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT); | 2675 | (seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT); |
2656 | pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | | 2676 | pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) | |
2657 | (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT); | 2677 | (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT); |
2658 | /* Compute the divisor for the pp clock, simply match the Bspec | 2678 | /* Compute the divisor for the pp clock, simply match the Bspec |
2659 | * formula. */ | 2679 | * formula. */ |
2660 | pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) | 2680 | pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1) |
2661 | << PP_REFERENCE_DIVIDER_SHIFT; | 2681 | << PP_REFERENCE_DIVIDER_SHIFT; |
2662 | pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000) | 2682 | pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000) |
2663 | << PANEL_POWER_CYCLE_DELAY_SHIFT); | 2683 | << PANEL_POWER_CYCLE_DELAY_SHIFT); |
2664 | 2684 | ||
2665 | /* Haswell doesn't have any port selection bits for the panel | 2685 | /* Haswell doesn't have any port selection bits for the panel |
@@ -2675,14 +2695,6 @@ intel_dp_init_panel_power_sequencer(struct drm_device *dev, | |||
2675 | I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); | 2695 | I915_WRITE(PCH_PP_OFF_DELAYS, pp_off); |
2676 | I915_WRITE(PCH_PP_DIVISOR, pp_div); | 2696 | I915_WRITE(PCH_PP_DIVISOR, pp_div); |
2677 | 2697 | ||
2678 | |||
2679 | DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n", | ||
2680 | intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay, | ||
2681 | intel_dp->panel_power_cycle_delay); | ||
2682 | |||
2683 | DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n", | ||
2684 | intel_dp->backlight_on_delay, intel_dp->backlight_off_delay); | ||
2685 | |||
2686 | DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", | 2698 | DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n", |
2687 | I915_READ(PCH_PP_ON_DELAYS), | 2699 | I915_READ(PCH_PP_ON_DELAYS), |
2688 | I915_READ(PCH_PP_OFF_DELAYS), | 2700 | I915_READ(PCH_PP_OFF_DELAYS), |
@@ -2699,6 +2711,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
2699 | struct drm_device *dev = intel_encoder->base.dev; | 2711 | struct drm_device *dev = intel_encoder->base.dev; |
2700 | struct drm_i915_private *dev_priv = dev->dev_private; | 2712 | struct drm_i915_private *dev_priv = dev->dev_private; |
2701 | struct drm_display_mode *fixed_mode = NULL; | 2713 | struct drm_display_mode *fixed_mode = NULL; |
2714 | struct edp_power_seq power_seq = { 0 }; | ||
2702 | enum port port = intel_dig_port->port; | 2715 | enum port port = intel_dig_port->port; |
2703 | const char *name = NULL; | 2716 | const char *name = NULL; |
2704 | int type; | 2717 | int type; |
@@ -2771,7 +2784,7 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
2771 | } | 2784 | } |
2772 | 2785 | ||
2773 | if (is_edp(intel_dp)) | 2786 | if (is_edp(intel_dp)) |
2774 | intel_dp_init_panel_power_sequencer(dev, intel_dp); | 2787 | intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq); |
2775 | 2788 | ||
2776 | intel_dp_i2c_init(intel_dp, intel_connector, name); | 2789 | intel_dp_i2c_init(intel_dp, intel_connector, name); |
2777 | 2790 | ||
@@ -2798,6 +2811,10 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port, | |||
2798 | return; | 2811 | return; |
2799 | } | 2812 | } |
2800 | 2813 | ||
2814 | /* We now know it's not a ghost, init power sequence regs. */ | ||
2815 | intel_dp_init_panel_power_sequencer_registers(dev, intel_dp, | ||
2816 | &power_seq); | ||
2817 | |||
2801 | ironlake_edp_panel_vdd_on(intel_dp); | 2818 | ironlake_edp_panel_vdd_on(intel_dp); |
2802 | edid = drm_get_edid(connector, &intel_dp->adapter); | 2819 | edid = drm_get_edid(connector, &intel_dp->adapter); |
2803 | if (edid) { | 2820 | if (edid) { |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b9a660a53677..17aee74258ad 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -776,14 +776,6 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
776 | }, | 776 | }, |
777 | { | 777 | { |
778 | .callback = intel_no_lvds_dmi_callback, | 778 | .callback = intel_no_lvds_dmi_callback, |
779 | .ident = "ZOTAC ZBOXSD-ID12/ID13", | ||
780 | .matches = { | ||
781 | DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"), | ||
782 | DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"), | ||
783 | }, | ||
784 | }, | ||
785 | { | ||
786 | .callback = intel_no_lvds_dmi_callback, | ||
787 | .ident = "Gigabyte GA-D525TUD", | 779 | .ident = "Gigabyte GA-D525TUD", |
788 | .matches = { | 780 | .matches = { |
789 | DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), | 781 | DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."), |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index e6f54ffab3ba..3280cffe50f4 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -44,6 +44,14 @@ | |||
44 | * i915.i915_enable_fbc parameter | 44 | * i915.i915_enable_fbc parameter |
45 | */ | 45 | */ |
46 | 46 | ||
47 | static bool intel_crtc_active(struct drm_crtc *crtc) | ||
48 | { | ||
49 | /* Be paranoid as we can arrive here with only partial | ||
50 | * state retrieved from the hardware during setup. | ||
51 | */ | ||
52 | return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock; | ||
53 | } | ||
54 | |||
47 | static void i8xx_disable_fbc(struct drm_device *dev) | 55 | static void i8xx_disable_fbc(struct drm_device *dev) |
48 | { | 56 | { |
49 | struct drm_i915_private *dev_priv = dev->dev_private; | 57 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -405,9 +413,8 @@ void intel_update_fbc(struct drm_device *dev) | |||
405 | * - going to an unsupported config (interlace, pixel multiply, etc.) | 413 | * - going to an unsupported config (interlace, pixel multiply, etc.) |
406 | */ | 414 | */ |
407 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { | 415 | list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) { |
408 | if (to_intel_crtc(tmp_crtc)->active && | 416 | if (intel_crtc_active(tmp_crtc) && |
409 | !to_intel_crtc(tmp_crtc)->primary_disabled && | 417 | !to_intel_crtc(tmp_crtc)->primary_disabled) { |
410 | tmp_crtc->fb) { | ||
411 | if (crtc) { | 418 | if (crtc) { |
412 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); | 419 | DRM_DEBUG_KMS("more than one pipe active, disabling compression\n"); |
413 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; | 420 | dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES; |
@@ -992,7 +999,7 @@ static struct drm_crtc *single_enabled_crtc(struct drm_device *dev) | |||
992 | struct drm_crtc *crtc, *enabled = NULL; | 999 | struct drm_crtc *crtc, *enabled = NULL; |
993 | 1000 | ||
994 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | 1001 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { |
995 | if (to_intel_crtc(crtc)->active && crtc->fb) { | 1002 | if (intel_crtc_active(crtc)) { |
996 | if (enabled) | 1003 | if (enabled) |
997 | return NULL; | 1004 | return NULL; |
998 | enabled = crtc; | 1005 | enabled = crtc; |
@@ -1086,7 +1093,7 @@ static bool g4x_compute_wm0(struct drm_device *dev, | |||
1086 | int entries, tlb_miss; | 1093 | int entries, tlb_miss; |
1087 | 1094 | ||
1088 | crtc = intel_get_crtc_for_plane(dev, plane); | 1095 | crtc = intel_get_crtc_for_plane(dev, plane); |
1089 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { | 1096 | if (!intel_crtc_active(crtc)) { |
1090 | *cursor_wm = cursor->guard_size; | 1097 | *cursor_wm = cursor->guard_size; |
1091 | *plane_wm = display->guard_size; | 1098 | *plane_wm = display->guard_size; |
1092 | return false; | 1099 | return false; |
@@ -1215,7 +1222,7 @@ static bool vlv_compute_drain_latency(struct drm_device *dev, | |||
1215 | int entries; | 1222 | int entries; |
1216 | 1223 | ||
1217 | crtc = intel_get_crtc_for_plane(dev, plane); | 1224 | crtc = intel_get_crtc_for_plane(dev, plane); |
1218 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) | 1225 | if (!intel_crtc_active(crtc)) |
1219 | return false; | 1226 | return false; |
1220 | 1227 | ||
1221 | clock = crtc->mode.clock; /* VESA DOT Clock */ | 1228 | clock = crtc->mode.clock; /* VESA DOT Clock */ |
@@ -1476,7 +1483,7 @@ static void i9xx_update_wm(struct drm_device *dev) | |||
1476 | 1483 | ||
1477 | fifo_size = dev_priv->display.get_fifo_size(dev, 0); | 1484 | fifo_size = dev_priv->display.get_fifo_size(dev, 0); |
1478 | crtc = intel_get_crtc_for_plane(dev, 0); | 1485 | crtc = intel_get_crtc_for_plane(dev, 0); |
1479 | if (to_intel_crtc(crtc)->active && crtc->fb) { | 1486 | if (intel_crtc_active(crtc)) { |
1480 | int cpp = crtc->fb->bits_per_pixel / 8; | 1487 | int cpp = crtc->fb->bits_per_pixel / 8; |
1481 | if (IS_GEN2(dev)) | 1488 | if (IS_GEN2(dev)) |
1482 | cpp = 4; | 1489 | cpp = 4; |
@@ -1490,7 +1497,7 @@ static void i9xx_update_wm(struct drm_device *dev) | |||
1490 | 1497 | ||
1491 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); | 1498 | fifo_size = dev_priv->display.get_fifo_size(dev, 1); |
1492 | crtc = intel_get_crtc_for_plane(dev, 1); | 1499 | crtc = intel_get_crtc_for_plane(dev, 1); |
1493 | if (to_intel_crtc(crtc)->active && crtc->fb) { | 1500 | if (intel_crtc_active(crtc)) { |
1494 | int cpp = crtc->fb->bits_per_pixel / 8; | 1501 | int cpp = crtc->fb->bits_per_pixel / 8; |
1495 | if (IS_GEN2(dev)) | 1502 | if (IS_GEN2(dev)) |
1496 | cpp = 4; | 1503 | cpp = 4; |
@@ -2044,7 +2051,7 @@ sandybridge_compute_sprite_wm(struct drm_device *dev, int plane, | |||
2044 | int entries, tlb_miss; | 2051 | int entries, tlb_miss; |
2045 | 2052 | ||
2046 | crtc = intel_get_crtc_for_plane(dev, plane); | 2053 | crtc = intel_get_crtc_for_plane(dev, plane); |
2047 | if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) { | 2054 | if (!intel_crtc_active(crtc)) { |
2048 | *sprite_wm = display->guard_size; | 2055 | *sprite_wm = display->guard_size; |
2049 | return false; | 2056 | return false; |
2050 | } | 2057 | } |
@@ -4243,7 +4250,8 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv) | |||
4243 | static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) | 4250 | static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv) |
4244 | { | 4251 | { |
4245 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); | 4252 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff)); |
4246 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ | 4253 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4254 | POSTING_READ(ECOBUS); | ||
4247 | } | 4255 | } |
4248 | 4256 | ||
4249 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | 4257 | static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) |
@@ -4260,7 +4268,8 @@ static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv) | |||
4260 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); | 4268 | DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n"); |
4261 | 4269 | ||
4262 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); | 4270 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL)); |
4263 | POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */ | 4271 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4272 | POSTING_READ(ECOBUS); | ||
4264 | 4273 | ||
4265 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), | 4274 | if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1), |
4266 | FORCEWAKE_ACK_TIMEOUT_MS)) | 4275 | FORCEWAKE_ACK_TIMEOUT_MS)) |
@@ -4297,14 +4306,16 @@ void gen6_gt_check_fifodbg(struct drm_i915_private *dev_priv) | |||
4297 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) | 4306 | static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv) |
4298 | { | 4307 | { |
4299 | I915_WRITE_NOTRACE(FORCEWAKE, 0); | 4308 | I915_WRITE_NOTRACE(FORCEWAKE, 0); |
4300 | /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ | 4309 | /* something from same cacheline, but !FORCEWAKE */ |
4310 | POSTING_READ(ECOBUS); | ||
4301 | gen6_gt_check_fifodbg(dev_priv); | 4311 | gen6_gt_check_fifodbg(dev_priv); |
4302 | } | 4312 | } |
4303 | 4313 | ||
4304 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) | 4314 | static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv) |
4305 | { | 4315 | { |
4306 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | 4316 | I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); |
4307 | /* gen6_gt_check_fifodbg doubles as the POSTING_READ */ | 4317 | /* something from same cacheline, but !FORCEWAKE_MT */ |
4318 | POSTING_READ(ECOBUS); | ||
4308 | gen6_gt_check_fifodbg(dev_priv); | 4319 | gen6_gt_check_fifodbg(dev_priv); |
4309 | } | 4320 | } |
4310 | 4321 | ||
@@ -4344,6 +4355,8 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv) | |||
4344 | static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) | 4355 | static void vlv_force_wake_reset(struct drm_i915_private *dev_priv) |
4345 | { | 4356 | { |
4346 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); | 4357 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff)); |
4358 | /* something from same cacheline, but !FORCEWAKE_VLV */ | ||
4359 | POSTING_READ(FORCEWAKE_ACK_VLV); | ||
4347 | } | 4360 | } |
4348 | 4361 | ||
4349 | static void vlv_force_wake_get(struct drm_i915_private *dev_priv) | 4362 | static void vlv_force_wake_get(struct drm_i915_private *dev_priv) |
@@ -4364,7 +4377,8 @@ static void vlv_force_wake_get(struct drm_i915_private *dev_priv) | |||
4364 | static void vlv_force_wake_put(struct drm_i915_private *dev_priv) | 4377 | static void vlv_force_wake_put(struct drm_i915_private *dev_priv) |
4365 | { | 4378 | { |
4366 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); | 4379 | I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL)); |
4367 | /* The below doubles as a POSTING_READ */ | 4380 | /* something from same cacheline, but !FORCEWAKE_VLV */ |
4381 | POSTING_READ(FORCEWAKE_ACK_VLV); | ||
4368 | gen6_gt_check_fifodbg(dev_priv); | 4382 | gen6_gt_check_fifodbg(dev_priv); |
4369 | } | 4383 | } |
4370 | 4384 | ||
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index ae253e04c391..42ff97d667d2 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -505,13 +505,25 @@ static int init_render_ring(struct intel_ring_buffer *ring) | |||
505 | struct drm_i915_private *dev_priv = dev->dev_private; | 505 | struct drm_i915_private *dev_priv = dev->dev_private; |
506 | int ret = init_ring_common(ring); | 506 | int ret = init_ring_common(ring); |
507 | 507 | ||
508 | if (INTEL_INFO(dev)->gen > 3) { | 508 | if (INTEL_INFO(dev)->gen > 3) |
509 | I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); | 509 | I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH)); |
510 | if (IS_GEN7(dev)) | 510 | |
511 | I915_WRITE(GFX_MODE_GEN7, | 511 | /* We need to disable the AsyncFlip performance optimisations in order |
512 | _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | | 512 | * to use MI_WAIT_FOR_EVENT within the CS. It should already be |
513 | _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); | 513 | * programmed to '1' on all products. |
514 | } | 514 | */ |
515 | if (INTEL_INFO(dev)->gen >= 6) | ||
516 | I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE)); | ||
517 | |||
518 | /* Required for the hardware to program scanline values for waiting */ | ||
519 | if (INTEL_INFO(dev)->gen == 6) | ||
520 | I915_WRITE(GFX_MODE, | ||
521 | _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS)); | ||
522 | |||
523 | if (IS_GEN7(dev)) | ||
524 | I915_WRITE(GFX_MODE_GEN7, | ||
525 | _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) | | ||
526 | _MASKED_BIT_ENABLE(GFX_REPLAY_MODE)); | ||
515 | 527 | ||
516 | if (INTEL_INFO(dev)->gen >= 5) { | 528 | if (INTEL_INFO(dev)->gen >= 5) { |
517 | ret = init_pipe_control(ring); | 529 | ret = init_pipe_control(ring); |
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c index 827dcd4edf1c..d7b060e0a231 100644 --- a/drivers/gpu/drm/i915/intel_sprite.c +++ b/drivers/gpu/drm/i915/intel_sprite.c | |||
@@ -120,11 +120,10 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
120 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); | 120 | I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]); |
121 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); | 121 | I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x); |
122 | 122 | ||
123 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 123 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
124 | sprsurf_offset = | 124 | sprsurf_offset = |
125 | intel_gen4_compute_offset_xtiled(&x, &y, | 125 | intel_gen4_compute_offset_xtiled(&x, &y, |
126 | fb->bits_per_pixel / 8, | 126 | pixel_size, fb->pitches[0]); |
127 | fb->pitches[0]); | ||
128 | linear_offset -= sprsurf_offset; | 127 | linear_offset -= sprsurf_offset; |
129 | 128 | ||
130 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET | 129 | /* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET |
@@ -286,11 +285,10 @@ ilk_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb, | |||
286 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); | 285 | I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]); |
287 | I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); | 286 | I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x); |
288 | 287 | ||
289 | linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8); | 288 | linear_offset = y * fb->pitches[0] + x * pixel_size; |
290 | dvssurf_offset = | 289 | dvssurf_offset = |
291 | intel_gen4_compute_offset_xtiled(&x, &y, | 290 | intel_gen4_compute_offset_xtiled(&x, &y, |
292 | fb->bits_per_pixel / 8, | 291 | pixel_size, fb->pitches[0]); |
293 | fb->pitches[0]); | ||
294 | linear_offset -= dvssurf_offset; | 292 | linear_offset -= dvssurf_offset; |
295 | 293 | ||
296 | if (obj->tiling_mode != I915_TILING_NONE) | 294 | if (obj->tiling_mode != I915_TILING_NONE) |
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c index c617f0480071..8bbb58f94a19 100644 --- a/drivers/gpu/drm/nouveau/core/core/client.c +++ b/drivers/gpu/drm/nouveau/core/core/client.c | |||
@@ -66,10 +66,8 @@ nouveau_client_create_(const char *name, u64 devname, const char *cfg, | |||
66 | 66 | ||
67 | ret = nouveau_handle_create(nv_object(client), ~0, ~0, | 67 | ret = nouveau_handle_create(nv_object(client), ~0, ~0, |
68 | nv_object(client), &client->root); | 68 | nv_object(client), &client->root); |
69 | if (ret) { | 69 | if (ret) |
70 | nouveau_namedb_destroy(&client->base); | ||
71 | return ret; | 70 | return ret; |
72 | } | ||
73 | 71 | ||
74 | /* prevent init/fini being called, os in in charge of this */ | 72 | /* prevent init/fini being called, os in in charge of this */ |
75 | atomic_set(&nv_object(client)->usecount, 2); | 73 | atomic_set(&nv_object(client)->usecount, 2); |
diff --git a/drivers/gpu/drm/nouveau/core/core/falcon.c b/drivers/gpu/drm/nouveau/core/core/falcon.c index 6b0843c33877..e05c15777588 100644 --- a/drivers/gpu/drm/nouveau/core/core/falcon.c +++ b/drivers/gpu/drm/nouveau/core/core/falcon.c | |||
@@ -73,8 +73,11 @@ _nouveau_falcon_init(struct nouveau_object *object) | |||
73 | nv_debug(falcon, "data limit: %d\n", falcon->data.limit); | 73 | nv_debug(falcon, "data limit: %d\n", falcon->data.limit); |
74 | 74 | ||
75 | /* wait for 'uc halted' to be signalled before continuing */ | 75 | /* wait for 'uc halted' to be signalled before continuing */ |
76 | if (falcon->secret) { | 76 | if (falcon->secret && falcon->version < 4) { |
77 | nv_wait(falcon, 0x008, 0x00000010, 0x00000010); | 77 | if (!falcon->version) |
78 | nv_wait(falcon, 0x008, 0x00000010, 0x00000010); | ||
79 | else | ||
80 | nv_wait(falcon, 0x180, 0x80000000, 0); | ||
78 | nv_wo32(falcon, 0x004, 0x00000010); | 81 | nv_wo32(falcon, 0x004, 0x00000010); |
79 | } | 82 | } |
80 | 83 | ||
diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c index b8d2cbf8a7a7..264c2b338ac3 100644 --- a/drivers/gpu/drm/nouveau/core/core/handle.c +++ b/drivers/gpu/drm/nouveau/core/core/handle.c | |||
@@ -109,7 +109,7 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, | |||
109 | while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) | 109 | while (!nv_iclass(namedb, NV_NAMEDB_CLASS)) |
110 | namedb = namedb->parent; | 110 | namedb = namedb->parent; |
111 | 111 | ||
112 | handle = *phandle = kzalloc(sizeof(*handle), GFP_KERNEL); | 112 | handle = kzalloc(sizeof(*handle), GFP_KERNEL); |
113 | if (!handle) | 113 | if (!handle) |
114 | return -ENOMEM; | 114 | return -ENOMEM; |
115 | 115 | ||
@@ -146,6 +146,9 @@ nouveau_handle_create(struct nouveau_object *parent, u32 _parent, u32 _handle, | |||
146 | } | 146 | } |
147 | 147 | ||
148 | hprintk(handle, TRACE, "created\n"); | 148 | hprintk(handle, TRACE, "created\n"); |
149 | |||
150 | *phandle = handle; | ||
151 | |||
149 | return 0; | 152 | return 0; |
150 | } | 153 | } |
151 | 154 | ||
diff --git a/drivers/gpu/drm/nouveau/core/core/subdev.c b/drivers/gpu/drm/nouveau/core/core/subdev.c index f74c30aa33a0..48f06378d3f9 100644 --- a/drivers/gpu/drm/nouveau/core/core/subdev.c +++ b/drivers/gpu/drm/nouveau/core/core/subdev.c | |||
@@ -99,7 +99,7 @@ nouveau_subdev_create_(struct nouveau_object *parent, | |||
99 | if (ret) | 99 | if (ret) |
100 | return ret; | 100 | return ret; |
101 | 101 | ||
102 | mutex_init(&subdev->mutex); | 102 | __mutex_init(&subdev->mutex, subname, &oclass->lock_class_key); |
103 | subdev->name = subname; | 103 | subdev->name = subname; |
104 | 104 | ||
105 | if (parent) { | 105 | if (parent) { |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 0f09af135415..ca1a7d76a95b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
@@ -851,20 +851,23 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) | |||
851 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 851 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) |
852 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); | 852 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); |
853 | 853 | ||
854 | if (nv_device(priv)->chipset < 0x90 || | 854 | if (!(ctrl & (1 << head))) { |
855 | nv_device(priv)->chipset == 0x92 || | 855 | if (nv_device(priv)->chipset < 0x90 || |
856 | nv_device(priv)->chipset == 0xa0) { | 856 | nv_device(priv)->chipset == 0x92 || |
857 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 857 | nv_device(priv)->chipset == 0xa0) { |
858 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); | 858 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) |
859 | i += 3; | 859 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); |
860 | } else { | 860 | i += 4; |
861 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 861 | } else { |
862 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); | 862 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) |
863 | i += 3; | 863 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); |
864 | i += 4; | ||
865 | } | ||
864 | } | 866 | } |
865 | 867 | ||
866 | if (!(ctrl & (1 << head))) | 868 | if (!(ctrl & (1 << head))) |
867 | return false; | 869 | return false; |
870 | i--; | ||
868 | 871 | ||
869 | data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); | 872 | data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info); |
870 | if (data) { | 873 | if (data) { |
@@ -898,20 +901,23 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, | |||
898 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 901 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) |
899 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); | 902 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); |
900 | 903 | ||
901 | if (nv_device(priv)->chipset < 0x90 || | 904 | if (!(ctrl & (1 << head))) { |
902 | nv_device(priv)->chipset == 0x92 || | 905 | if (nv_device(priv)->chipset < 0x90 || |
903 | nv_device(priv)->chipset == 0xa0) { | 906 | nv_device(priv)->chipset == 0x92 || |
904 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 907 | nv_device(priv)->chipset == 0xa0) { |
905 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); | 908 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) |
906 | i += 3; | 909 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); |
907 | } else { | 910 | i += 4; |
908 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 911 | } else { |
909 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); | 912 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) |
910 | i += 3; | 913 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); |
914 | i += 4; | ||
915 | } | ||
911 | } | 916 | } |
912 | 917 | ||
913 | if (!(ctrl & (1 << head))) | 918 | if (!(ctrl & (1 << head))) |
914 | return 0x0000; | 919 | return 0x0000; |
920 | i--; | ||
915 | 921 | ||
916 | data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); | 922 | data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1); |
917 | if (!data) | 923 | if (!data) |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h index 0193532ceac9..63acc0346ff2 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/client.h +++ b/drivers/gpu/drm/nouveau/core/include/core/client.h | |||
@@ -36,6 +36,9 @@ nouveau_client(void *obj) | |||
36 | 36 | ||
37 | int nouveau_client_create_(const char *name, u64 device, const char *cfg, | 37 | int nouveau_client_create_(const char *name, u64 device, const char *cfg, |
38 | const char *dbg, int, void **); | 38 | const char *dbg, int, void **); |
39 | #define nouveau_client_destroy(p) \ | ||
40 | nouveau_namedb_destroy(&(p)->base) | ||
41 | |||
39 | int nouveau_client_init(struct nouveau_client *); | 42 | int nouveau_client_init(struct nouveau_client *); |
40 | int nouveau_client_fini(struct nouveau_client *, bool suspend); | 43 | int nouveau_client_fini(struct nouveau_client *, bool suspend); |
41 | 44 | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/core/object.h b/drivers/gpu/drm/nouveau/core/include/core/object.h index 5982935ee23a..106bb19fdd9a 100644 --- a/drivers/gpu/drm/nouveau/core/include/core/object.h +++ b/drivers/gpu/drm/nouveau/core/include/core/object.h | |||
@@ -50,10 +50,13 @@ int nouveau_object_fini(struct nouveau_object *, bool suspend); | |||
50 | 50 | ||
51 | extern struct nouveau_ofuncs nouveau_object_ofuncs; | 51 | extern struct nouveau_ofuncs nouveau_object_ofuncs; |
52 | 52 | ||
53 | /* Don't allocate dynamically, because lockdep needs lock_class_keys to be in | ||
54 | * ".data". */ | ||
53 | struct nouveau_oclass { | 55 | struct nouveau_oclass { |
54 | u32 handle; | 56 | u32 handle; |
55 | struct nouveau_ofuncs *ofuncs; | 57 | struct nouveau_ofuncs * const ofuncs; |
56 | struct nouveau_omthds *omthds; | 58 | struct nouveau_omthds * const omthds; |
59 | struct lock_class_key lock_class_key; | ||
57 | }; | 60 | }; |
58 | 61 | ||
59 | #define nv_oclass(o) nv_object(o)->oclass | 62 | #define nv_oclass(o) nv_object(o)->oclass |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h index c345097592f2..b2f3d4d0aa49 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h | |||
@@ -38,6 +38,8 @@ enum nvbios_pll_type { | |||
38 | PLL_UNK42 = 0x42, | 38 | PLL_UNK42 = 0x42, |
39 | PLL_VPLL0 = 0x80, | 39 | PLL_VPLL0 = 0x80, |
40 | PLL_VPLL1 = 0x81, | 40 | PLL_VPLL1 = 0x81, |
41 | PLL_VPLL2 = 0x82, | ||
42 | PLL_VPLL3 = 0x83, | ||
41 | PLL_MAX = 0xff | 43 | PLL_MAX = 0xff |
42 | }; | 44 | }; |
43 | 45 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c index 2917d552689b..690ed438b2ad 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c | |||
@@ -1534,7 +1534,6 @@ init_io(struct nvbios_init *init) | |||
1534 | mdelay(10); | 1534 | mdelay(10); |
1535 | init_wr32(init, 0x614100, 0x10000018); | 1535 | init_wr32(init, 0x614100, 0x10000018); |
1536 | init_wr32(init, 0x614900, 0x10000018); | 1536 | init_wr32(init, 0x614900, 0x10000018); |
1537 | return; | ||
1538 | } | 1537 | } |
1539 | 1538 | ||
1540 | value = init_rdport(init, port) & mask; | 1539 | value = init_rdport(init, port) & mask; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c index f6962c9b6c36..7c9626258a46 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c | |||
@@ -52,6 +52,8 @@ nvc0_clock_pll_set(struct nouveau_clock *clk, u32 type, u32 freq) | |||
52 | switch (info.type) { | 52 | switch (info.type) { |
53 | case PLL_VPLL0: | 53 | case PLL_VPLL0: |
54 | case PLL_VPLL1: | 54 | case PLL_VPLL1: |
55 | case PLL_VPLL2: | ||
56 | case PLL_VPLL3: | ||
55 | nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); | 57 | nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100); |
56 | nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); | 58 | nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M); |
57 | nv_wr32(priv, info.reg + 0x10, fN << 16); | 59 | nv_wr32(priv, info.reg + 0x10, fN << 16); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c index d6d16007ec1a..d62045f454b2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/base.c | |||
@@ -86,8 +86,8 @@ nouveau_fb_preinit(struct nouveau_fb *pfb) | |||
86 | return ret; | 86 | return ret; |
87 | } | 87 | } |
88 | 88 | ||
89 | if (!nouveau_mm_initialised(&pfb->tags) && tags) { | 89 | if (!nouveau_mm_initialised(&pfb->tags)) { |
90 | ret = nouveau_mm_init(&pfb->tags, 0, ++tags, 1); | 90 | ret = nouveau_mm_init(&pfb->tags, 0, tags ? ++tags : 0, 1); |
91 | if (ret) | 91 | if (ret) |
92 | return ret; | 92 | return ret; |
93 | } | 93 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c index 487cb8c6c204..eac236ed19b2 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nv50.c | |||
@@ -99,7 +99,7 @@ nv50_fb_vram_init(struct nouveau_fb *pfb) | |||
99 | struct nouveau_bios *bios = nouveau_bios(device); | 99 | struct nouveau_bios *bios = nouveau_bios(device); |
100 | const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ | 100 | const u32 rsvd_head = ( 256 * 1024) >> 12; /* vga memory */ |
101 | const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ | 101 | const u32 rsvd_tail = (1024 * 1024) >> 12; /* vbios etc */ |
102 | u32 size; | 102 | u32 size, tags = 0; |
103 | int ret; | 103 | int ret; |
104 | 104 | ||
105 | pfb->ram.size = nv_rd32(pfb, 0x10020c); | 105 | pfb->ram.size = nv_rd32(pfb, 0x10020c); |
@@ -140,10 +140,11 @@ nv50_fb_vram_init(struct nouveau_fb *pfb) | |||
140 | return ret; | 140 | return ret; |
141 | 141 | ||
142 | pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1; | 142 | pfb->ram.ranks = (nv_rd32(pfb, 0x100200) & 0x4) ? 2 : 1; |
143 | tags = nv_rd32(pfb, 0x100320); | ||
143 | break; | 144 | break; |
144 | } | 145 | } |
145 | 146 | ||
146 | return nv_rd32(pfb, 0x100320); | 147 | return tags; |
147 | } | 148 | } |
148 | 149 | ||
149 | static int | 150 | static int |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c index 306bdf121452..7606ed15b6fa 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c | |||
@@ -145,14 +145,14 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
145 | mem->memtype = type; | 145 | mem->memtype = type; |
146 | mem->size = size; | 146 | mem->size = size; |
147 | 147 | ||
148 | mutex_lock(&mm->mutex); | 148 | mutex_lock(&pfb->base.mutex); |
149 | do { | 149 | do { |
150 | if (back) | 150 | if (back) |
151 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); | 151 | ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r); |
152 | else | 152 | else |
153 | ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); | 153 | ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r); |
154 | if (ret) { | 154 | if (ret) { |
155 | mutex_unlock(&mm->mutex); | 155 | mutex_unlock(&pfb->base.mutex); |
156 | pfb->ram.put(pfb, &mem); | 156 | pfb->ram.put(pfb, &mem); |
157 | return ret; | 157 | return ret; |
158 | } | 158 | } |
@@ -160,7 +160,7 @@ nvc0_fb_vram_new(struct nouveau_fb *pfb, u64 size, u32 align, u32 ncmin, | |||
160 | list_add_tail(&r->rl_entry, &mem->regions); | 160 | list_add_tail(&r->rl_entry, &mem->regions); |
161 | size -= r->length; | 161 | size -= r->length; |
162 | } while (size); | 162 | } while (size); |
163 | mutex_unlock(&mm->mutex); | 163 | mutex_unlock(&pfb->base.mutex); |
164 | 164 | ||
165 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); | 165 | r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry); |
166 | mem->offset = (u64)r->offset << 12; | 166 | mem->offset = (u64)r->offset << 12; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c index 1188227ca6aa..6565f3dbbe04 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c | |||
@@ -40,15 +40,21 @@ nouveau_instobj_create_(struct nouveau_object *parent, | |||
40 | if (ret) | 40 | if (ret) |
41 | return ret; | 41 | return ret; |
42 | 42 | ||
43 | mutex_lock(&imem->base.mutex); | ||
43 | list_add(&iobj->head, &imem->list); | 44 | list_add(&iobj->head, &imem->list); |
45 | mutex_unlock(&imem->base.mutex); | ||
44 | return 0; | 46 | return 0; |
45 | } | 47 | } |
46 | 48 | ||
47 | void | 49 | void |
48 | nouveau_instobj_destroy(struct nouveau_instobj *iobj) | 50 | nouveau_instobj_destroy(struct nouveau_instobj *iobj) |
49 | { | 51 | { |
50 | if (iobj->head.prev) | 52 | struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine); |
51 | list_del(&iobj->head); | 53 | |
54 | mutex_lock(&subdev->mutex); | ||
55 | list_del(&iobj->head); | ||
56 | mutex_unlock(&subdev->mutex); | ||
57 | |||
52 | return nouveau_object_destroy(&iobj->base); | 58 | return nouveau_object_destroy(&iobj->base); |
53 | } | 59 | } |
54 | 60 | ||
@@ -88,6 +94,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) | |||
88 | if (ret) | 94 | if (ret) |
89 | return ret; | 95 | return ret; |
90 | 96 | ||
97 | mutex_lock(&imem->base.mutex); | ||
98 | |||
91 | list_for_each_entry(iobj, &imem->list, head) { | 99 | list_for_each_entry(iobj, &imem->list, head) { |
92 | if (iobj->suspend) { | 100 | if (iobj->suspend) { |
93 | for (i = 0; i < iobj->size; i += 4) | 101 | for (i = 0; i < iobj->size; i += 4) |
@@ -97,6 +105,8 @@ nouveau_instmem_init(struct nouveau_instmem *imem) | |||
97 | } | 105 | } |
98 | } | 106 | } |
99 | 107 | ||
108 | mutex_unlock(&imem->base.mutex); | ||
109 | |||
100 | return 0; | 110 | return 0; |
101 | } | 111 | } |
102 | 112 | ||
@@ -104,17 +114,26 @@ int | |||
104 | nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) | 114 | nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend) |
105 | { | 115 | { |
106 | struct nouveau_instobj *iobj; | 116 | struct nouveau_instobj *iobj; |
107 | int i; | 117 | int i, ret = 0; |
108 | 118 | ||
109 | if (suspend) { | 119 | if (suspend) { |
120 | mutex_lock(&imem->base.mutex); | ||
121 | |||
110 | list_for_each_entry(iobj, &imem->list, head) { | 122 | list_for_each_entry(iobj, &imem->list, head) { |
111 | iobj->suspend = vmalloc(iobj->size); | 123 | iobj->suspend = vmalloc(iobj->size); |
112 | if (iobj->suspend) { | 124 | if (!iobj->suspend) { |
113 | for (i = 0; i < iobj->size; i += 4) | 125 | ret = -ENOMEM; |
114 | iobj->suspend[i / 4] = nv_ro32(iobj, i); | 126 | break; |
115 | } else | 127 | } |
116 | return -ENOMEM; | 128 | |
129 | for (i = 0; i < iobj->size; i += 4) | ||
130 | iobj->suspend[i / 4] = nv_ro32(iobj, i); | ||
117 | } | 131 | } |
132 | |||
133 | mutex_unlock(&imem->base.mutex); | ||
134 | |||
135 | if (ret) | ||
136 | return ret; | ||
118 | } | 137 | } |
119 | 138 | ||
120 | return nouveau_subdev_fini(&imem->base, suspend); | 139 | return nouveau_subdev_fini(&imem->base, suspend); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c index 082c11b75acb..77c67fc970e6 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c | |||
@@ -352,7 +352,7 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
352 | u64 mm_length = (offset + length) - mm_offset; | 352 | u64 mm_length = (offset + length) - mm_offset; |
353 | int ret; | 353 | int ret; |
354 | 354 | ||
355 | vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL); | 355 | vm = kzalloc(sizeof(*vm), GFP_KERNEL); |
356 | if (!vm) | 356 | if (!vm) |
357 | return -ENOMEM; | 357 | return -ENOMEM; |
358 | 358 | ||
@@ -376,6 +376,8 @@ nouveau_vm_create(struct nouveau_vmmgr *vmm, u64 offset, u64 length, | |||
376 | return ret; | 376 | return ret; |
377 | } | 377 | } |
378 | 378 | ||
379 | *pvm = vm; | ||
380 | |||
379 | return 0; | 381 | return 0; |
380 | } | 382 | } |
381 | 383 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index 69d7b1d0b9d6..1699a9083a2f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
@@ -28,6 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <core/engine.h> | 30 | #include <core/engine.h> |
31 | #include <linux/swiotlb.h> | ||
31 | 32 | ||
32 | #include <subdev/fb.h> | 33 | #include <subdev/fb.h> |
33 | #include <subdev/vm.h> | 34 | #include <subdev/vm.h> |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index ac340ba32017..e620ba8271b4 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -127,12 +127,26 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
127 | struct nouveau_encoder **pnv_encoder) | 127 | struct nouveau_encoder **pnv_encoder) |
128 | { | 128 | { |
129 | struct drm_device *dev = connector->dev; | 129 | struct drm_device *dev = connector->dev; |
130 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | ||
130 | struct nouveau_drm *drm = nouveau_drm(dev); | 131 | struct nouveau_drm *drm = nouveau_drm(dev); |
132 | struct nouveau_gpio *gpio = nouveau_gpio(drm->device); | ||
131 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); | 133 | struct nouveau_i2c *i2c = nouveau_i2c(drm->device); |
132 | int i; | 134 | struct nouveau_i2c_port *port = NULL; |
135 | int i, panel = -ENODEV; | ||
136 | |||
137 | /* eDP panels need powering on by us (if the VBIOS doesn't default it | ||
138 | * to on) before doing any AUX channel transactions. LVDS panel power | ||
139 | * is handled by the SOR itself, and not required for LVDS DDC. | ||
140 | */ | ||
141 | if (nv_connector->type == DCB_CONNECTOR_eDP) { | ||
142 | panel = gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff); | ||
143 | if (panel == 0) { | ||
144 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); | ||
145 | msleep(300); | ||
146 | } | ||
147 | } | ||
133 | 148 | ||
134 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | 149 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { |
135 | struct nouveau_i2c_port *port = NULL; | ||
136 | struct nouveau_encoder *nv_encoder; | 150 | struct nouveau_encoder *nv_encoder; |
137 | struct drm_mode_object *obj; | 151 | struct drm_mode_object *obj; |
138 | int id; | 152 | int id; |
@@ -150,11 +164,19 @@ nouveau_connector_ddc_detect(struct drm_connector *connector, | |||
150 | port = i2c->find(i2c, nv_encoder->dcb->i2c_index); | 164 | port = i2c->find(i2c, nv_encoder->dcb->i2c_index); |
151 | if (port && nv_probe_i2c(port, 0x50)) { | 165 | if (port && nv_probe_i2c(port, 0x50)) { |
152 | *pnv_encoder = nv_encoder; | 166 | *pnv_encoder = nv_encoder; |
153 | return port; | 167 | break; |
154 | } | 168 | } |
169 | |||
170 | port = NULL; | ||
155 | } | 171 | } |
156 | 172 | ||
157 | return NULL; | 173 | /* eDP panel not detected, restore panel power GPIO to previous |
174 | * state to avoid confusing the SOR for other output types. | ||
175 | */ | ||
176 | if (!port && panel == 0) | ||
177 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel); | ||
178 | |||
179 | return port; | ||
158 | } | 180 | } |
159 | 181 | ||
160 | static struct nouveau_encoder * | 182 | static struct nouveau_encoder * |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index e4188f24fc75..508b00a2ce0d 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -225,15 +225,6 @@ nouveau_display_init(struct drm_device *dev) | |||
225 | if (ret) | 225 | if (ret) |
226 | return ret; | 226 | return ret; |
227 | 227 | ||
228 | /* power on internal panel if it's not already. the init tables of | ||
229 | * some vbios default this to off for some reason, causing the | ||
230 | * panel to not work after resume | ||
231 | */ | ||
232 | if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) { | ||
233 | gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1); | ||
234 | msleep(300); | ||
235 | } | ||
236 | |||
237 | /* enable polling for external displays */ | 228 | /* enable polling for external displays */ |
238 | drm_kms_helper_poll_enable(dev); | 229 | drm_kms_helper_poll_enable(dev); |
239 | 230 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c index 180a45e3b525..5e7aef23825a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drm.c +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c | |||
@@ -84,11 +84,16 @@ nouveau_cli_create(struct pci_dev *pdev, const char *name, | |||
84 | struct nouveau_cli *cli; | 84 | struct nouveau_cli *cli; |
85 | int ret; | 85 | int ret; |
86 | 86 | ||
87 | *pcli = NULL; | ||
87 | ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, | 88 | ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config, |
88 | nouveau_debug, size, pcli); | 89 | nouveau_debug, size, pcli); |
89 | cli = *pcli; | 90 | cli = *pcli; |
90 | if (ret) | 91 | if (ret) { |
92 | if (cli) | ||
93 | nouveau_client_destroy(&cli->base); | ||
94 | *pcli = NULL; | ||
91 | return ret; | 95 | return ret; |
96 | } | ||
92 | 97 | ||
93 | mutex_init(&cli->mutex); | 98 | mutex_init(&cli->mutex); |
94 | return 0; | 99 | return 0; |
@@ -240,6 +245,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev, | |||
240 | return 0; | 245 | return 0; |
241 | } | 246 | } |
242 | 247 | ||
248 | static struct lock_class_key drm_client_lock_class_key; | ||
249 | |||
243 | static int | 250 | static int |
244 | nouveau_drm_load(struct drm_device *dev, unsigned long flags) | 251 | nouveau_drm_load(struct drm_device *dev, unsigned long flags) |
245 | { | 252 | { |
@@ -251,6 +258,7 @@ nouveau_drm_load(struct drm_device *dev, unsigned long flags) | |||
251 | ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); | 258 | ret = nouveau_cli_create(pdev, "DRM", sizeof(*drm), (void**)&drm); |
252 | if (ret) | 259 | if (ret) |
253 | return ret; | 260 | return ret; |
261 | lockdep_set_class(&drm->client.mutex, &drm_client_lock_class_key); | ||
254 | 262 | ||
255 | dev->dev_private = drm; | 263 | dev->dev_private = drm; |
256 | drm->dev = dev; | 264 | drm->dev = dev; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h index bedafd1c9539..cdb83acdffe2 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fence.h +++ b/drivers/gpu/drm/nouveau/nouveau_fence.h | |||
@@ -60,6 +60,7 @@ u32 nv10_fence_read(struct nouveau_channel *); | |||
60 | void nv10_fence_context_del(struct nouveau_channel *); | 60 | void nv10_fence_context_del(struct nouveau_channel *); |
61 | void nv10_fence_destroy(struct nouveau_drm *); | 61 | void nv10_fence_destroy(struct nouveau_drm *); |
62 | int nv10_fence_create(struct nouveau_drm *); | 62 | int nv10_fence_create(struct nouveau_drm *); |
63 | void nv17_fence_resume(struct nouveau_drm *drm); | ||
63 | 64 | ||
64 | int nv50_fence_create(struct nouveau_drm *); | 65 | int nv50_fence_create(struct nouveau_drm *); |
65 | int nv84_fence_create(struct nouveau_drm *); | 66 | int nv84_fence_create(struct nouveau_drm *); |
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c index 184cdf806761..39ffc07f906b 100644 --- a/drivers/gpu/drm/nouveau/nv04_dfp.c +++ b/drivers/gpu/drm/nouveau/nv04_dfp.c | |||
@@ -505,7 +505,7 @@ static void nv04_dfp_update_backlight(struct drm_encoder *encoder, int mode) | |||
505 | 505 | ||
506 | static inline bool is_powersaving_dpms(int mode) | 506 | static inline bool is_powersaving_dpms(int mode) |
507 | { | 507 | { |
508 | return (mode != DRM_MODE_DPMS_ON); | 508 | return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED; |
509 | } | 509 | } |
510 | 510 | ||
511 | static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) | 511 | static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode) |
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c index 7ae7f97a6d4d..03017f24d593 100644 --- a/drivers/gpu/drm/nouveau/nv10_fence.c +++ b/drivers/gpu/drm/nouveau/nv10_fence.c | |||
@@ -162,6 +162,13 @@ nv10_fence_destroy(struct nouveau_drm *drm) | |||
162 | kfree(priv); | 162 | kfree(priv); |
163 | } | 163 | } |
164 | 164 | ||
165 | void nv17_fence_resume(struct nouveau_drm *drm) | ||
166 | { | ||
167 | struct nv10_fence_priv *priv = drm->fence; | ||
168 | |||
169 | nouveau_bo_wr32(priv->bo, 0, priv->sequence); | ||
170 | } | ||
171 | |||
165 | int | 172 | int |
166 | nv10_fence_create(struct nouveau_drm *drm) | 173 | nv10_fence_create(struct nouveau_drm *drm) |
167 | { | 174 | { |
@@ -197,6 +204,7 @@ nv10_fence_create(struct nouveau_drm *drm) | |||
197 | if (ret == 0) { | 204 | if (ret == 0) { |
198 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); | 205 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); |
199 | priv->base.sync = nv17_fence_sync; | 206 | priv->base.sync = nv17_fence_sync; |
207 | priv->base.resume = nv17_fence_resume; | ||
200 | } | 208 | } |
201 | } | 209 | } |
202 | 210 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c index c20f2727ea0b..d889f3ac0d41 100644 --- a/drivers/gpu/drm/nouveau/nv50_fence.c +++ b/drivers/gpu/drm/nouveau/nv50_fence.c | |||
@@ -122,6 +122,7 @@ nv50_fence_create(struct nouveau_drm *drm) | |||
122 | if (ret == 0) { | 122 | if (ret == 0) { |
123 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); | 123 | nouveau_bo_wr32(priv->bo, 0x000, 0x00000000); |
124 | priv->base.sync = nv17_fence_sync; | 124 | priv->base.sync = nv17_fence_sync; |
125 | priv->base.resume = nv17_fence_resume; | ||
125 | } | 126 | } |
126 | 127 | ||
127 | if (ret) | 128 | if (ret) |
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 061fa0a28900..a2d478e8692a 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c | |||
@@ -1313,14 +1313,18 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav | |||
1313 | if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { | 1313 | if (!(tmp & EVERGREEN_CRTC_BLANK_DATA_EN)) { |
1314 | radeon_wait_for_vblank(rdev, i); | 1314 | radeon_wait_for_vblank(rdev, i); |
1315 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; | 1315 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; |
1316 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); | ||
1316 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); | 1317 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); |
1318 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); | ||
1317 | } | 1319 | } |
1318 | } else { | 1320 | } else { |
1319 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); | 1321 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); |
1320 | if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { | 1322 | if (!(tmp & EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE)) { |
1321 | radeon_wait_for_vblank(rdev, i); | 1323 | radeon_wait_for_vblank(rdev, i); |
1322 | tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; | 1324 | tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; |
1325 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); | ||
1323 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); | 1326 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); |
1327 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); | ||
1324 | } | 1328 | } |
1325 | } | 1329 | } |
1326 | /* wait for the next frame */ | 1330 | /* wait for the next frame */ |
@@ -1345,6 +1349,8 @@ void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *sav | |||
1345 | blackout &= ~BLACKOUT_MODE_MASK; | 1349 | blackout &= ~BLACKOUT_MODE_MASK; |
1346 | WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); | 1350 | WREG32(MC_SHARED_BLACKOUT_CNTL, blackout | 1); |
1347 | } | 1351 | } |
1352 | /* wait for the MC to settle */ | ||
1353 | udelay(100); | ||
1348 | } | 1354 | } |
1349 | 1355 | ||
1350 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) | 1356 | void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) |
@@ -1378,11 +1384,15 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s | |||
1378 | if (ASIC_IS_DCE6(rdev)) { | 1384 | if (ASIC_IS_DCE6(rdev)) { |
1379 | tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); | 1385 | tmp = RREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i]); |
1380 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; | 1386 | tmp |= EVERGREEN_CRTC_BLANK_DATA_EN; |
1387 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); | ||
1381 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); | 1388 | WREG32(EVERGREEN_CRTC_BLANK_CONTROL + crtc_offsets[i], tmp); |
1389 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); | ||
1382 | } else { | 1390 | } else { |
1383 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); | 1391 | tmp = RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i]); |
1384 | tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; | 1392 | tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE; |
1393 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 1); | ||
1385 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); | 1394 | WREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[i], tmp); |
1395 | WREG32(EVERGREEN_CRTC_UPDATE_LOCK + crtc_offsets[i], 0); | ||
1386 | } | 1396 | } |
1387 | /* wait for the next frame */ | 1397 | /* wait for the next frame */ |
1388 | frame_count = radeon_get_vblank_counter(rdev, i); | 1398 | frame_count = radeon_get_vblank_counter(rdev, i); |
@@ -2036,9 +2046,20 @@ static void evergreen_gpu_init(struct radeon_device *rdev) | |||
2036 | WREG32(HDP_ADDR_CONFIG, gb_addr_config); | 2046 | WREG32(HDP_ADDR_CONFIG, gb_addr_config); |
2037 | WREG32(DMA_TILING_CONFIG, gb_addr_config); | 2047 | WREG32(DMA_TILING_CONFIG, gb_addr_config); |
2038 | 2048 | ||
2039 | tmp = gb_addr_config & NUM_PIPES_MASK; | 2049 | if ((rdev->config.evergreen.max_backends == 1) && |
2040 | tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, | 2050 | (rdev->flags & RADEON_IS_IGP)) { |
2041 | EVERGREEN_MAX_BACKENDS, disabled_rb_mask); | 2051 | if ((disabled_rb_mask & 3) == 1) { |
2052 | /* RB0 disabled, RB1 enabled */ | ||
2053 | tmp = 0x11111111; | ||
2054 | } else { | ||
2055 | /* RB1 disabled, RB0 enabled */ | ||
2056 | tmp = 0x00000000; | ||
2057 | } | ||
2058 | } else { | ||
2059 | tmp = gb_addr_config & NUM_PIPES_MASK; | ||
2060 | tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.evergreen.max_backends, | ||
2061 | EVERGREEN_MAX_BACKENDS, disabled_rb_mask); | ||
2062 | } | ||
2042 | WREG32(GB_BACKEND_MAP, tmp); | 2063 | WREG32(GB_BACKEND_MAP, tmp); |
2043 | 2064 | ||
2044 | WREG32(CGTS_SYS_TCC_DISABLE, 0); | 2065 | WREG32(CGTS_SYS_TCC_DISABLE, 0); |
@@ -2401,6 +2422,12 @@ static int evergreen_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
2401 | { | 2422 | { |
2402 | struct evergreen_mc_save save; | 2423 | struct evergreen_mc_save save; |
2403 | 2424 | ||
2425 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
2426 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
2427 | |||
2428 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
2429 | reset_mask &= ~RADEON_RESET_DMA; | ||
2430 | |||
2404 | if (reset_mask == 0) | 2431 | if (reset_mask == 0) |
2405 | return 0; | 2432 | return 0; |
2406 | 2433 | ||
diff --git a/drivers/gpu/drm/radeon/evergreen_cs.c b/drivers/gpu/drm/radeon/evergreen_cs.c index 7a445666e71f..ee4cff534f10 100644 --- a/drivers/gpu/drm/radeon/evergreen_cs.c +++ b/drivers/gpu/drm/radeon/evergreen_cs.c | |||
@@ -2909,14 +2909,14 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
2909 | return -EINVAL; | 2909 | return -EINVAL; |
2910 | } | 2910 | } |
2911 | if (tiled) { | 2911 | if (tiled) { |
2912 | dst_offset = ib[idx+1]; | 2912 | dst_offset = radeon_get_ib_value(p, idx+1); |
2913 | dst_offset <<= 8; | 2913 | dst_offset <<= 8; |
2914 | 2914 | ||
2915 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | 2915 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); |
2916 | p->idx += count + 7; | 2916 | p->idx += count + 7; |
2917 | } else { | 2917 | } else { |
2918 | dst_offset = ib[idx+1]; | 2918 | dst_offset = radeon_get_ib_value(p, idx+1); |
2919 | dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32; | 2919 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; |
2920 | 2920 | ||
2921 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | 2921 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); |
2922 | ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | 2922 | ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; |
@@ -2954,12 +2954,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
2954 | DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); | 2954 | DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); |
2955 | return -EINVAL; | 2955 | return -EINVAL; |
2956 | } | 2956 | } |
2957 | dst_offset = ib[idx+1]; | 2957 | dst_offset = radeon_get_ib_value(p, idx+1); |
2958 | dst_offset <<= 8; | 2958 | dst_offset <<= 8; |
2959 | dst2_offset = ib[idx+2]; | 2959 | dst2_offset = radeon_get_ib_value(p, idx+2); |
2960 | dst2_offset <<= 8; | 2960 | dst2_offset <<= 8; |
2961 | src_offset = ib[idx+8]; | 2961 | src_offset = radeon_get_ib_value(p, idx+8); |
2962 | src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32; | 2962 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; |
2963 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | 2963 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { |
2964 | dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n", | 2964 | dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n", |
2965 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | 2965 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); |
@@ -3014,12 +3014,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3014 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); | 3014 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); |
3015 | return -EINVAL; | 3015 | return -EINVAL; |
3016 | } | 3016 | } |
3017 | dst_offset = ib[idx+1]; | 3017 | dst_offset = radeon_get_ib_value(p, idx+1); |
3018 | dst_offset <<= 8; | 3018 | dst_offset <<= 8; |
3019 | dst2_offset = ib[idx+2]; | 3019 | dst2_offset = radeon_get_ib_value(p, idx+2); |
3020 | dst2_offset <<= 8; | 3020 | dst2_offset <<= 8; |
3021 | src_offset = ib[idx+8]; | 3021 | src_offset = radeon_get_ib_value(p, idx+8); |
3022 | src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32; | 3022 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; |
3023 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | 3023 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { |
3024 | dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", | 3024 | dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", |
3025 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | 3025 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); |
@@ -3046,22 +3046,22 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3046 | /* detile bit */ | 3046 | /* detile bit */ |
3047 | if (idx_value & (1 << 31)) { | 3047 | if (idx_value & (1 << 31)) { |
3048 | /* tiled src, linear dst */ | 3048 | /* tiled src, linear dst */ |
3049 | src_offset = ib[idx+1]; | 3049 | src_offset = radeon_get_ib_value(p, idx+1); |
3050 | src_offset <<= 8; | 3050 | src_offset <<= 8; |
3051 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | 3051 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); |
3052 | 3052 | ||
3053 | dst_offset = ib[idx+7]; | 3053 | dst_offset = radeon_get_ib_value(p, idx+7); |
3054 | dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | 3054 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; |
3055 | ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | 3055 | ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); |
3056 | ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | 3056 | ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; |
3057 | } else { | 3057 | } else { |
3058 | /* linear src, tiled dst */ | 3058 | /* linear src, tiled dst */ |
3059 | src_offset = ib[idx+7]; | 3059 | src_offset = radeon_get_ib_value(p, idx+7); |
3060 | src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | 3060 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; |
3061 | ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | 3061 | ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); |
3062 | ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | 3062 | ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; |
3063 | 3063 | ||
3064 | dst_offset = ib[idx+1]; | 3064 | dst_offset = radeon_get_ib_value(p, idx+1); |
3065 | dst_offset <<= 8; | 3065 | dst_offset <<= 8; |
3066 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | 3066 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); |
3067 | } | 3067 | } |
@@ -3098,12 +3098,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3098 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); | 3098 | DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); |
3099 | return -EINVAL; | 3099 | return -EINVAL; |
3100 | } | 3100 | } |
3101 | dst_offset = ib[idx+1]; | 3101 | dst_offset = radeon_get_ib_value(p, idx+1); |
3102 | dst_offset <<= 8; | 3102 | dst_offset <<= 8; |
3103 | dst2_offset = ib[idx+2]; | 3103 | dst2_offset = radeon_get_ib_value(p, idx+2); |
3104 | dst2_offset <<= 8; | 3104 | dst2_offset <<= 8; |
3105 | src_offset = ib[idx+8]; | 3105 | src_offset = radeon_get_ib_value(p, idx+8); |
3106 | src_offset |= ((u64)(ib[idx+9] & 0xff)) << 32; | 3106 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; |
3107 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | 3107 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { |
3108 | dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", | 3108 | dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", |
3109 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | 3109 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); |
@@ -3135,22 +3135,22 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3135 | /* detile bit */ | 3135 | /* detile bit */ |
3136 | if (idx_value & (1 << 31)) { | 3136 | if (idx_value & (1 << 31)) { |
3137 | /* tiled src, linear dst */ | 3137 | /* tiled src, linear dst */ |
3138 | src_offset = ib[idx+1]; | 3138 | src_offset = radeon_get_ib_value(p, idx+1); |
3139 | src_offset <<= 8; | 3139 | src_offset <<= 8; |
3140 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | 3140 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); |
3141 | 3141 | ||
3142 | dst_offset = ib[idx+7]; | 3142 | dst_offset = radeon_get_ib_value(p, idx+7); |
3143 | dst_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | 3143 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; |
3144 | ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | 3144 | ib[idx+7] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); |
3145 | ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | 3145 | ib[idx+8] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; |
3146 | } else { | 3146 | } else { |
3147 | /* linear src, tiled dst */ | 3147 | /* linear src, tiled dst */ |
3148 | src_offset = ib[idx+7]; | 3148 | src_offset = radeon_get_ib_value(p, idx+7); |
3149 | src_offset |= ((u64)(ib[idx+8] & 0xff)) << 32; | 3149 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; |
3150 | ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | 3150 | ib[idx+7] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); |
3151 | ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | 3151 | ib[idx+8] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; |
3152 | 3152 | ||
3153 | dst_offset = ib[idx+1]; | 3153 | dst_offset = radeon_get_ib_value(p, idx+1); |
3154 | dst_offset <<= 8; | 3154 | dst_offset <<= 8; |
3155 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | 3155 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); |
3156 | } | 3156 | } |
@@ -3176,10 +3176,10 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3176 | switch (misc) { | 3176 | switch (misc) { |
3177 | case 0: | 3177 | case 0: |
3178 | /* L2L, byte */ | 3178 | /* L2L, byte */ |
3179 | src_offset = ib[idx+2]; | 3179 | src_offset = radeon_get_ib_value(p, idx+2); |
3180 | src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | 3180 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; |
3181 | dst_offset = ib[idx+1]; | 3181 | dst_offset = radeon_get_ib_value(p, idx+1); |
3182 | dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32; | 3182 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; |
3183 | if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) { | 3183 | if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) { |
3184 | dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n", | 3184 | dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n", |
3185 | src_offset + count, radeon_bo_size(src_reloc->robj)); | 3185 | src_offset + count, radeon_bo_size(src_reloc->robj)); |
@@ -3216,12 +3216,12 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3216 | DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n"); | 3216 | DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n"); |
3217 | return -EINVAL; | 3217 | return -EINVAL; |
3218 | } | 3218 | } |
3219 | dst_offset = ib[idx+1]; | 3219 | dst_offset = radeon_get_ib_value(p, idx+1); |
3220 | dst_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | 3220 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; |
3221 | dst2_offset = ib[idx+2]; | 3221 | dst2_offset = radeon_get_ib_value(p, idx+2); |
3222 | dst2_offset |= ((u64)(ib[idx+5] & 0xff)) << 32; | 3222 | dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32; |
3223 | src_offset = ib[idx+3]; | 3223 | src_offset = radeon_get_ib_value(p, idx+3); |
3224 | src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32; | 3224 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; |
3225 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | 3225 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { |
3226 | dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n", | 3226 | dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n", |
3227 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | 3227 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); |
@@ -3251,10 +3251,10 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3251 | } | 3251 | } |
3252 | } else { | 3252 | } else { |
3253 | /* L2L, dw */ | 3253 | /* L2L, dw */ |
3254 | src_offset = ib[idx+2]; | 3254 | src_offset = radeon_get_ib_value(p, idx+2); |
3255 | src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | 3255 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; |
3256 | dst_offset = ib[idx+1]; | 3256 | dst_offset = radeon_get_ib_value(p, idx+1); |
3257 | dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32; | 3257 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; |
3258 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { | 3258 | if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { |
3259 | dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n", | 3259 | dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n", |
3260 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); | 3260 | src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); |
@@ -3279,8 +3279,8 @@ int evergreen_dma_cs_parse(struct radeon_cs_parser *p) | |||
3279 | DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n"); | 3279 | DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n"); |
3280 | return -EINVAL; | 3280 | return -EINVAL; |
3281 | } | 3281 | } |
3282 | dst_offset = ib[idx+1]; | 3282 | dst_offset = radeon_get_ib_value(p, idx+1); |
3283 | dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16; | 3283 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16; |
3284 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | 3284 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { |
3285 | dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", | 3285 | dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", |
3286 | dst_offset, radeon_bo_size(dst_reloc->robj)); | 3286 | dst_offset, radeon_bo_size(dst_reloc->robj)); |
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 896f1cbc58a5..835992d8d067 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c | |||
@@ -1216,7 +1216,7 @@ void cayman_dma_stop(struct radeon_device *rdev) | |||
1216 | int cayman_dma_resume(struct radeon_device *rdev) | 1216 | int cayman_dma_resume(struct radeon_device *rdev) |
1217 | { | 1217 | { |
1218 | struct radeon_ring *ring; | 1218 | struct radeon_ring *ring; |
1219 | u32 rb_cntl, dma_cntl; | 1219 | u32 rb_cntl, dma_cntl, ib_cntl; |
1220 | u32 rb_bufsz; | 1220 | u32 rb_bufsz; |
1221 | u32 reg_offset, wb_offset; | 1221 | u32 reg_offset, wb_offset; |
1222 | int i, r; | 1222 | int i, r; |
@@ -1265,7 +1265,11 @@ int cayman_dma_resume(struct radeon_device *rdev) | |||
1265 | WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8); | 1265 | WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8); |
1266 | 1266 | ||
1267 | /* enable DMA IBs */ | 1267 | /* enable DMA IBs */ |
1268 | WREG32(DMA_IB_CNTL + reg_offset, DMA_IB_ENABLE | CMD_VMID_FORCE); | 1268 | ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE; |
1269 | #ifdef __BIG_ENDIAN | ||
1270 | ib_cntl |= DMA_IB_SWAP_ENABLE; | ||
1271 | #endif | ||
1272 | WREG32(DMA_IB_CNTL + reg_offset, ib_cntl); | ||
1269 | 1273 | ||
1270 | dma_cntl = RREG32(DMA_CNTL + reg_offset); | 1274 | dma_cntl = RREG32(DMA_CNTL + reg_offset); |
1271 | dma_cntl &= ~CTXEMPTY_INT_ENABLE; | 1275 | dma_cntl &= ~CTXEMPTY_INT_ENABLE; |
@@ -1409,6 +1413,12 @@ static int cayman_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1409 | { | 1413 | { |
1410 | struct evergreen_mc_save save; | 1414 | struct evergreen_mc_save save; |
1411 | 1415 | ||
1416 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1417 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
1418 | |||
1419 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
1420 | reset_mask &= ~RADEON_RESET_DMA; | ||
1421 | |||
1412 | if (reset_mask == 0) | 1422 | if (reset_mask == 0) |
1413 | return 0; | 1423 | return 0; |
1414 | 1424 | ||
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index 537e259b3837..becb03e8b32f 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -1378,6 +1378,12 @@ static int r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
1378 | { | 1378 | { |
1379 | struct rv515_mc_save save; | 1379 | struct rv515_mc_save save; |
1380 | 1380 | ||
1381 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
1382 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
1383 | |||
1384 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
1385 | reset_mask &= ~RADEON_RESET_DMA; | ||
1386 | |||
1381 | if (reset_mask == 0) | 1387 | if (reset_mask == 0) |
1382 | return 0; | 1388 | return 0; |
1383 | 1389 | ||
@@ -1456,12 +1462,15 @@ u32 r6xx_remap_render_backend(struct radeon_device *rdev, | |||
1456 | u32 disabled_rb_mask) | 1462 | u32 disabled_rb_mask) |
1457 | { | 1463 | { |
1458 | u32 rendering_pipe_num, rb_num_width, req_rb_num; | 1464 | u32 rendering_pipe_num, rb_num_width, req_rb_num; |
1459 | u32 pipe_rb_ratio, pipe_rb_remain; | 1465 | u32 pipe_rb_ratio, pipe_rb_remain, tmp; |
1460 | u32 data = 0, mask = 1 << (max_rb_num - 1); | 1466 | u32 data = 0, mask = 1 << (max_rb_num - 1); |
1461 | unsigned i, j; | 1467 | unsigned i, j; |
1462 | 1468 | ||
1463 | /* mask out the RBs that don't exist on that asic */ | 1469 | /* mask out the RBs that don't exist on that asic */ |
1464 | disabled_rb_mask |= (0xff << max_rb_num) & 0xff; | 1470 | tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff); |
1471 | /* make sure at least one RB is available */ | ||
1472 | if ((tmp & 0xff) != 0xff) | ||
1473 | disabled_rb_mask = tmp; | ||
1465 | 1474 | ||
1466 | rendering_pipe_num = 1 << tiling_pipe_num; | 1475 | rendering_pipe_num = 1 << tiling_pipe_num; |
1467 | req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); | 1476 | req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); |
@@ -2307,7 +2316,7 @@ void r600_dma_stop(struct radeon_device *rdev) | |||
2307 | int r600_dma_resume(struct radeon_device *rdev) | 2316 | int r600_dma_resume(struct radeon_device *rdev) |
2308 | { | 2317 | { |
2309 | struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; | 2318 | struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; |
2310 | u32 rb_cntl, dma_cntl; | 2319 | u32 rb_cntl, dma_cntl, ib_cntl; |
2311 | u32 rb_bufsz; | 2320 | u32 rb_bufsz; |
2312 | int r; | 2321 | int r; |
2313 | 2322 | ||
@@ -2347,7 +2356,11 @@ int r600_dma_resume(struct radeon_device *rdev) | |||
2347 | WREG32(DMA_RB_BASE, ring->gpu_addr >> 8); | 2356 | WREG32(DMA_RB_BASE, ring->gpu_addr >> 8); |
2348 | 2357 | ||
2349 | /* enable DMA IBs */ | 2358 | /* enable DMA IBs */ |
2350 | WREG32(DMA_IB_CNTL, DMA_IB_ENABLE); | 2359 | ib_cntl = DMA_IB_ENABLE; |
2360 | #ifdef __BIG_ENDIAN | ||
2361 | ib_cntl |= DMA_IB_SWAP_ENABLE; | ||
2362 | #endif | ||
2363 | WREG32(DMA_IB_CNTL, ib_cntl); | ||
2351 | 2364 | ||
2352 | dma_cntl = RREG32(DMA_CNTL); | 2365 | dma_cntl = RREG32(DMA_CNTL); |
2353 | dma_cntl &= ~CTXEMPTY_INT_ENABLE; | 2366 | dma_cntl &= ~CTXEMPTY_INT_ENABLE; |
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 03191a56eb44..9b2512bf1a46 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -2476,8 +2476,10 @@ static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error) | |||
2476 | kfree(parser->relocs); | 2476 | kfree(parser->relocs); |
2477 | for (i = 0; i < parser->nchunks; i++) { | 2477 | for (i = 0; i < parser->nchunks; i++) { |
2478 | kfree(parser->chunks[i].kdata); | 2478 | kfree(parser->chunks[i].kdata); |
2479 | kfree(parser->chunks[i].kpage[0]); | 2479 | if (parser->rdev && (parser->rdev->flags & RADEON_IS_AGP)) { |
2480 | kfree(parser->chunks[i].kpage[1]); | 2480 | kfree(parser->chunks[i].kpage[0]); |
2481 | kfree(parser->chunks[i].kpage[1]); | ||
2482 | } | ||
2481 | } | 2483 | } |
2482 | kfree(parser->chunks); | 2484 | kfree(parser->chunks); |
2483 | kfree(parser->chunks_array); | 2485 | kfree(parser->chunks_array); |
@@ -2561,16 +2563,16 @@ int r600_dma_cs_next_reloc(struct radeon_cs_parser *p, | |||
2561 | struct radeon_cs_chunk *relocs_chunk; | 2563 | struct radeon_cs_chunk *relocs_chunk; |
2562 | unsigned idx; | 2564 | unsigned idx; |
2563 | 2565 | ||
2566 | *cs_reloc = NULL; | ||
2564 | if (p->chunk_relocs_idx == -1) { | 2567 | if (p->chunk_relocs_idx == -1) { |
2565 | DRM_ERROR("No relocation chunk !\n"); | 2568 | DRM_ERROR("No relocation chunk !\n"); |
2566 | return -EINVAL; | 2569 | return -EINVAL; |
2567 | } | 2570 | } |
2568 | *cs_reloc = NULL; | ||
2569 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; | 2571 | relocs_chunk = &p->chunks[p->chunk_relocs_idx]; |
2570 | idx = p->dma_reloc_idx; | 2572 | idx = p->dma_reloc_idx; |
2571 | if (idx >= relocs_chunk->length_dw) { | 2573 | if (idx >= p->nrelocs) { |
2572 | DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", | 2574 | DRM_ERROR("Relocs at %d after relocations chunk end %d !\n", |
2573 | idx, relocs_chunk->length_dw); | 2575 | idx, p->nrelocs); |
2574 | return -EINVAL; | 2576 | return -EINVAL; |
2575 | } | 2577 | } |
2576 | *cs_reloc = p->relocs_ptr[idx]; | 2578 | *cs_reloc = p->relocs_ptr[idx]; |
@@ -2621,14 +2623,14 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p) | |||
2621 | return -EINVAL; | 2623 | return -EINVAL; |
2622 | } | 2624 | } |
2623 | if (tiled) { | 2625 | if (tiled) { |
2624 | dst_offset = ib[idx+1]; | 2626 | dst_offset = radeon_get_ib_value(p, idx+1); |
2625 | dst_offset <<= 8; | 2627 | dst_offset <<= 8; |
2626 | 2628 | ||
2627 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | 2629 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); |
2628 | p->idx += count + 5; | 2630 | p->idx += count + 5; |
2629 | } else { | 2631 | } else { |
2630 | dst_offset = ib[idx+1]; | 2632 | dst_offset = radeon_get_ib_value(p, idx+1); |
2631 | dst_offset |= ((u64)(ib[idx+2] & 0xff)) << 32; | 2633 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; |
2632 | 2634 | ||
2633 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | 2635 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); |
2634 | ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | 2636 | ib[idx+2] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; |
@@ -2656,32 +2658,32 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p) | |||
2656 | /* detile bit */ | 2658 | /* detile bit */ |
2657 | if (idx_value & (1 << 31)) { | 2659 | if (idx_value & (1 << 31)) { |
2658 | /* tiled src, linear dst */ | 2660 | /* tiled src, linear dst */ |
2659 | src_offset = ib[idx+1]; | 2661 | src_offset = radeon_get_ib_value(p, idx+1); |
2660 | src_offset <<= 8; | 2662 | src_offset <<= 8; |
2661 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); | 2663 | ib[idx+1] += (u32)(src_reloc->lobj.gpu_offset >> 8); |
2662 | 2664 | ||
2663 | dst_offset = ib[idx+5]; | 2665 | dst_offset = radeon_get_ib_value(p, idx+5); |
2664 | dst_offset |= ((u64)(ib[idx+6] & 0xff)) << 32; | 2666 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; |
2665 | ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | 2667 | ib[idx+5] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); |
2666 | ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; | 2668 | ib[idx+6] += upper_32_bits(dst_reloc->lobj.gpu_offset) & 0xff; |
2667 | } else { | 2669 | } else { |
2668 | /* linear src, tiled dst */ | 2670 | /* linear src, tiled dst */ |
2669 | src_offset = ib[idx+5]; | 2671 | src_offset = radeon_get_ib_value(p, idx+5); |
2670 | src_offset |= ((u64)(ib[idx+6] & 0xff)) << 32; | 2672 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; |
2671 | ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | 2673 | ib[idx+5] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); |
2672 | ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | 2674 | ib[idx+6] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; |
2673 | 2675 | ||
2674 | dst_offset = ib[idx+1]; | 2676 | dst_offset = radeon_get_ib_value(p, idx+1); |
2675 | dst_offset <<= 8; | 2677 | dst_offset <<= 8; |
2676 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); | 2678 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset >> 8); |
2677 | } | 2679 | } |
2678 | p->idx += 7; | 2680 | p->idx += 7; |
2679 | } else { | 2681 | } else { |
2680 | if (p->family >= CHIP_RV770) { | 2682 | if (p->family >= CHIP_RV770) { |
2681 | src_offset = ib[idx+2]; | 2683 | src_offset = radeon_get_ib_value(p, idx+2); |
2682 | src_offset |= ((u64)(ib[idx+4] & 0xff)) << 32; | 2684 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; |
2683 | dst_offset = ib[idx+1]; | 2685 | dst_offset = radeon_get_ib_value(p, idx+1); |
2684 | dst_offset |= ((u64)(ib[idx+3] & 0xff)) << 32; | 2686 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; |
2685 | 2687 | ||
2686 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | 2688 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); |
2687 | ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | 2689 | ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); |
@@ -2689,10 +2691,10 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p) | |||
2689 | ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; | 2691 | ib[idx+4] += upper_32_bits(src_reloc->lobj.gpu_offset) & 0xff; |
2690 | p->idx += 5; | 2692 | p->idx += 5; |
2691 | } else { | 2693 | } else { |
2692 | src_offset = ib[idx+2]; | 2694 | src_offset = radeon_get_ib_value(p, idx+2); |
2693 | src_offset |= ((u64)(ib[idx+3] & 0xff)) << 32; | 2695 | src_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; |
2694 | dst_offset = ib[idx+1]; | 2696 | dst_offset = radeon_get_ib_value(p, idx+1); |
2695 | dst_offset |= ((u64)(ib[idx+3] & 0xff0000)) << 16; | 2697 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff0000)) << 16; |
2696 | 2698 | ||
2697 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); | 2699 | ib[idx+1] += (u32)(dst_reloc->lobj.gpu_offset & 0xfffffffc); |
2698 | ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); | 2700 | ib[idx+2] += (u32)(src_reloc->lobj.gpu_offset & 0xfffffffc); |
@@ -2722,8 +2724,8 @@ int r600_dma_cs_parse(struct radeon_cs_parser *p) | |||
2722 | DRM_ERROR("bad DMA_PACKET_WRITE\n"); | 2724 | DRM_ERROR("bad DMA_PACKET_WRITE\n"); |
2723 | return -EINVAL; | 2725 | return -EINVAL; |
2724 | } | 2726 | } |
2725 | dst_offset = ib[idx+1]; | 2727 | dst_offset = radeon_get_ib_value(p, idx+1); |
2726 | dst_offset |= ((u64)(ib[idx+3] & 0x00ff0000)) << 16; | 2728 | dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16; |
2727 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { | 2729 | if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { |
2728 | dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", | 2730 | dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", |
2729 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); | 2731 | dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 34e52304a525..a08f657329a0 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -324,7 +324,6 @@ struct radeon_bo { | |||
324 | struct list_head list; | 324 | struct list_head list; |
325 | /* Protected by tbo.reserved */ | 325 | /* Protected by tbo.reserved */ |
326 | u32 placements[3]; | 326 | u32 placements[3]; |
327 | u32 busy_placements[3]; | ||
328 | struct ttm_placement placement; | 327 | struct ttm_placement placement; |
329 | struct ttm_buffer_object tbo; | 328 | struct ttm_buffer_object tbo; |
330 | struct ttm_bo_kmap_obj kmap; | 329 | struct ttm_bo_kmap_obj kmap; |
@@ -654,6 +653,8 @@ struct radeon_ring { | |||
654 | u32 ptr_reg_mask; | 653 | u32 ptr_reg_mask; |
655 | u32 nop; | 654 | u32 nop; |
656 | u32 idx; | 655 | u32 idx; |
656 | u64 last_semaphore_signal_addr; | ||
657 | u64 last_semaphore_wait_addr; | ||
657 | }; | 658 | }; |
658 | 659 | ||
659 | /* | 660 | /* |
diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 9056fafb00ea..0b202c07fe50 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c | |||
@@ -1445,7 +1445,7 @@ static struct radeon_asic cayman_asic = { | |||
1445 | .vm = { | 1445 | .vm = { |
1446 | .init = &cayman_vm_init, | 1446 | .init = &cayman_vm_init, |
1447 | .fini = &cayman_vm_fini, | 1447 | .fini = &cayman_vm_fini, |
1448 | .pt_ring_index = R600_RING_TYPE_DMA_INDEX, | 1448 | .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX, |
1449 | .set_page = &cayman_vm_set_page, | 1449 | .set_page = &cayman_vm_set_page, |
1450 | }, | 1450 | }, |
1451 | .ring = { | 1451 | .ring = { |
@@ -1572,7 +1572,7 @@ static struct radeon_asic trinity_asic = { | |||
1572 | .vm = { | 1572 | .vm = { |
1573 | .init = &cayman_vm_init, | 1573 | .init = &cayman_vm_init, |
1574 | .fini = &cayman_vm_fini, | 1574 | .fini = &cayman_vm_fini, |
1575 | .pt_ring_index = R600_RING_TYPE_DMA_INDEX, | 1575 | .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX, |
1576 | .set_page = &cayman_vm_set_page, | 1576 | .set_page = &cayman_vm_set_page, |
1577 | }, | 1577 | }, |
1578 | .ring = { | 1578 | .ring = { |
@@ -1699,7 +1699,7 @@ static struct radeon_asic si_asic = { | |||
1699 | .vm = { | 1699 | .vm = { |
1700 | .init = &si_vm_init, | 1700 | .init = &si_vm_init, |
1701 | .fini = &si_vm_fini, | 1701 | .fini = &si_vm_fini, |
1702 | .pt_ring_index = R600_RING_TYPE_DMA_INDEX, | 1702 | .pt_ring_index = RADEON_RING_TYPE_GFX_INDEX, |
1703 | .set_page = &si_vm_set_page, | 1703 | .set_page = &si_vm_set_page, |
1704 | }, | 1704 | }, |
1705 | .ring = { | 1705 | .ring = { |
diff --git a/drivers/gpu/drm/radeon/radeon_combios.c b/drivers/gpu/drm/radeon/radeon_combios.c index 33a56a09ff10..3e403bdda58f 100644 --- a/drivers/gpu/drm/radeon/radeon_combios.c +++ b/drivers/gpu/drm/radeon/radeon_combios.c | |||
@@ -2470,6 +2470,14 @@ bool radeon_get_legacy_connector_info_from_bios(struct drm_device *dev) | |||
2470 | 1), | 2470 | 1), |
2471 | ATOM_DEVICE_CRT1_SUPPORT); | 2471 | ATOM_DEVICE_CRT1_SUPPORT); |
2472 | } | 2472 | } |
2473 | /* RV100 board with external TDMS bit mis-set. | ||
2474 | * Actually uses internal TMDS, clear the bit. | ||
2475 | */ | ||
2476 | if (dev->pdev->device == 0x5159 && | ||
2477 | dev->pdev->subsystem_vendor == 0x1014 && | ||
2478 | dev->pdev->subsystem_device == 0x029A) { | ||
2479 | tmp &= ~(1 << 4); | ||
2480 | } | ||
2473 | if ((tmp >> 4) & 0x1) { | 2481 | if ((tmp >> 4) & 0x1) { |
2474 | devices |= ATOM_DEVICE_DFP2_SUPPORT; | 2482 | devices |= ATOM_DEVICE_DFP2_SUPPORT; |
2475 | radeon_add_legacy_encoder(dev, | 2483 | radeon_add_legacy_encoder(dev, |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 396baba0141a..5407459e56d2 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -279,13 +279,15 @@ int radeon_cs_parser_init(struct radeon_cs_parser *p, void *data) | |||
279 | p->chunks[p->chunk_ib_idx].length_dw); | 279 | p->chunks[p->chunk_ib_idx].length_dw); |
280 | return -EINVAL; | 280 | return -EINVAL; |
281 | } | 281 | } |
282 | if ((p->rdev->flags & RADEON_IS_AGP)) { | 282 | if (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) { |
283 | p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); | 283 | p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL); |
284 | p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); | 284 | p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL); |
285 | if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || | 285 | if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL || |
286 | p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { | 286 | p->chunks[p->chunk_ib_idx].kpage[1] == NULL) { |
287 | kfree(p->chunks[i].kpage[0]); | 287 | kfree(p->chunks[p->chunk_ib_idx].kpage[0]); |
288 | kfree(p->chunks[i].kpage[1]); | 288 | kfree(p->chunks[p->chunk_ib_idx].kpage[1]); |
289 | p->chunks[p->chunk_ib_idx].kpage[0] = NULL; | ||
290 | p->chunks[p->chunk_ib_idx].kpage[1] = NULL; | ||
289 | return -ENOMEM; | 291 | return -ENOMEM; |
290 | } | 292 | } |
291 | } | 293 | } |
@@ -583,7 +585,8 @@ static int radeon_cs_update_pages(struct radeon_cs_parser *p, int pg_idx) | |||
583 | struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; | 585 | struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx]; |
584 | int i; | 586 | int i; |
585 | int size = PAGE_SIZE; | 587 | int size = PAGE_SIZE; |
586 | bool copy1 = (p->rdev->flags & RADEON_IS_AGP) ? false : true; | 588 | bool copy1 = (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) ? |
589 | false : true; | ||
587 | 590 | ||
588 | for (i = ibc->last_copied_page + 1; i < pg_idx; i++) { | 591 | for (i = ibc->last_copied_page + 1; i < pg_idx; i++) { |
589 | if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)), | 592 | if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)), |
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c index ad6df625e8b8..0d67674b64b1 100644 --- a/drivers/gpu/drm/radeon/radeon_cursor.c +++ b/drivers/gpu/drm/radeon/radeon_cursor.c | |||
@@ -241,7 +241,8 @@ int radeon_crtc_cursor_move(struct drm_crtc *crtc, | |||
241 | y = 0; | 241 | y = 0; |
242 | } | 242 | } |
243 | 243 | ||
244 | if (ASIC_IS_AVIVO(rdev)) { | 244 | /* fixed on DCE6 and newer */ |
245 | if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) { | ||
245 | int i = 0; | 246 | int i = 0; |
246 | struct drm_crtc *crtc_p; | 247 | struct drm_crtc *crtc_p; |
247 | 248 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index edfc54e41842..0d6562bb0c93 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -429,7 +429,8 @@ bool radeon_card_posted(struct radeon_device *rdev) | |||
429 | { | 429 | { |
430 | uint32_t reg; | 430 | uint32_t reg; |
431 | 431 | ||
432 | if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) | 432 | if (efi_enabled(EFI_BOOT) && |
433 | rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE) | ||
433 | return false; | 434 | return false; |
434 | 435 | ||
435 | /* first check CRTCs */ | 436 | /* first check CRTCs */ |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 1da2386d7cf7..05c96fa0b051 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -1115,14 +1115,16 @@ radeon_user_framebuffer_create(struct drm_device *dev, | |||
1115 | } | 1115 | } |
1116 | 1116 | ||
1117 | radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); | 1117 | radeon_fb = kzalloc(sizeof(*radeon_fb), GFP_KERNEL); |
1118 | if (radeon_fb == NULL) | 1118 | if (radeon_fb == NULL) { |
1119 | drm_gem_object_unreference_unlocked(obj); | ||
1119 | return ERR_PTR(-ENOMEM); | 1120 | return ERR_PTR(-ENOMEM); |
1121 | } | ||
1120 | 1122 | ||
1121 | ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); | 1123 | ret = radeon_framebuffer_init(dev, radeon_fb, mode_cmd, obj); |
1122 | if (ret) { | 1124 | if (ret) { |
1123 | kfree(radeon_fb); | 1125 | kfree(radeon_fb); |
1124 | drm_gem_object_unreference_unlocked(obj); | 1126 | drm_gem_object_unreference_unlocked(obj); |
1125 | return NULL; | 1127 | return ERR_PTR(ret); |
1126 | } | 1128 | } |
1127 | 1129 | ||
1128 | return &radeon_fb->base; | 1130 | return &radeon_fb->base; |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index dff6cf77f953..d9bf96ee299a 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c | |||
@@ -69,9 +69,10 @@ | |||
69 | * 2.26.0 - r600-eg: fix htile size computation | 69 | * 2.26.0 - r600-eg: fix htile size computation |
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 | */ | 73 | */ |
73 | #define KMS_DRIVER_MAJOR 2 | 74 | #define KMS_DRIVER_MAJOR 2 |
74 | #define KMS_DRIVER_MINOR 28 | 75 | #define KMS_DRIVER_MINOR 29 |
75 | #define KMS_DRIVER_PATCHLEVEL 0 | 76 | #define KMS_DRIVER_PATCHLEVEL 0 |
76 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); | 77 | int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags); |
77 | int radeon_driver_unload_kms(struct drm_device *dev); | 78 | int radeon_driver_unload_kms(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c index f5ba2241dacc..62cd512f5c8d 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c | |||
@@ -640,6 +640,14 @@ static enum drm_connector_status radeon_legacy_primary_dac_detect(struct drm_enc | |||
640 | enum drm_connector_status found = connector_status_disconnected; | 640 | enum drm_connector_status found = connector_status_disconnected; |
641 | bool color = true; | 641 | bool color = true; |
642 | 642 | ||
643 | /* just don't bother on RN50 those chip are often connected to remoting | ||
644 | * console hw and often we get failure to load detect those. So to make | ||
645 | * everyone happy report the encoder as always connected. | ||
646 | */ | ||
647 | if (ASIC_IS_RN50(rdev)) { | ||
648 | return connector_status_connected; | ||
649 | } | ||
650 | |||
643 | /* save the regs we need */ | 651 | /* save the regs we need */ |
644 | vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); | 652 | vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL); |
645 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); | 653 | crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL); |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 883c95d8d90f..d3aface2d12d 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -84,6 +84,7 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | |||
84 | rbo->placement.fpfn = 0; | 84 | rbo->placement.fpfn = 0; |
85 | rbo->placement.lpfn = 0; | 85 | rbo->placement.lpfn = 0; |
86 | rbo->placement.placement = rbo->placements; | 86 | rbo->placement.placement = rbo->placements; |
87 | rbo->placement.busy_placement = rbo->placements; | ||
87 | if (domain & RADEON_GEM_DOMAIN_VRAM) | 88 | if (domain & RADEON_GEM_DOMAIN_VRAM) |
88 | rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | | 89 | rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | |
89 | TTM_PL_FLAG_VRAM; | 90 | TTM_PL_FLAG_VRAM; |
@@ -104,14 +105,6 @@ void radeon_ttm_placement_from_domain(struct radeon_bo *rbo, u32 domain) | |||
104 | if (!c) | 105 | if (!c) |
105 | rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; | 106 | rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM; |
106 | rbo->placement.num_placement = c; | 107 | rbo->placement.num_placement = c; |
107 | |||
108 | c = 0; | ||
109 | rbo->placement.busy_placement = rbo->busy_placements; | ||
110 | if (rbo->rdev->flags & RADEON_IS_AGP) { | ||
111 | rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT; | ||
112 | } else { | ||
113 | rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT; | ||
114 | } | ||
115 | rbo->placement.num_busy_placement = c; | 108 | rbo->placement.num_busy_placement = c; |
116 | } | 109 | } |
117 | 110 | ||
@@ -357,6 +350,7 @@ int radeon_bo_list_validate(struct list_head *head) | |||
357 | { | 350 | { |
358 | struct radeon_bo_list *lobj; | 351 | struct radeon_bo_list *lobj; |
359 | struct radeon_bo *bo; | 352 | struct radeon_bo *bo; |
353 | u32 domain; | ||
360 | int r; | 354 | int r; |
361 | 355 | ||
362 | r = ttm_eu_reserve_buffers(head); | 356 | r = ttm_eu_reserve_buffers(head); |
@@ -366,9 +360,17 @@ int radeon_bo_list_validate(struct list_head *head) | |||
366 | list_for_each_entry(lobj, head, tv.head) { | 360 | list_for_each_entry(lobj, head, tv.head) { |
367 | bo = lobj->bo; | 361 | bo = lobj->bo; |
368 | if (!bo->pin_count) { | 362 | if (!bo->pin_count) { |
363 | domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain; | ||
364 | |||
365 | retry: | ||
366 | radeon_ttm_placement_from_domain(bo, domain); | ||
369 | r = ttm_bo_validate(&bo->tbo, &bo->placement, | 367 | r = ttm_bo_validate(&bo->tbo, &bo->placement, |
370 | true, false); | 368 | true, false); |
371 | if (unlikely(r)) { | 369 | if (unlikely(r)) { |
370 | if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) { | ||
371 | domain |= RADEON_GEM_DOMAIN_GTT; | ||
372 | goto retry; | ||
373 | } | ||
372 | return r; | 374 | return r; |
373 | } | 375 | } |
374 | } | 376 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c index 141f2b6a9cf2..cd72062d5a91 100644 --- a/drivers/gpu/drm/radeon/radeon_ring.c +++ b/drivers/gpu/drm/radeon/radeon_ring.c | |||
@@ -377,6 +377,9 @@ int radeon_ring_alloc(struct radeon_device *rdev, struct radeon_ring *ring, unsi | |||
377 | { | 377 | { |
378 | int r; | 378 | int r; |
379 | 379 | ||
380 | /* make sure we aren't trying to allocate more space than there is on the ring */ | ||
381 | if (ndw > (ring->ring_size / 4)) | ||
382 | return -ENOMEM; | ||
380 | /* Align requested size with padding so unlock_commit can | 383 | /* Align requested size with padding so unlock_commit can |
381 | * pad safely */ | 384 | * pad safely */ |
382 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; | 385 | ndw = (ndw + ring->align_mask) & ~ring->align_mask; |
@@ -784,6 +787,8 @@ static int radeon_debugfs_ring_info(struct seq_file *m, void *data) | |||
784 | } | 787 | } |
785 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); | 788 | seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr); |
786 | seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); | 789 | seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr); |
790 | seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr); | ||
791 | seq_printf(m, "last semaphore wait addr : 0x%016llx\n", ring->last_semaphore_wait_addr); | ||
787 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); | 792 | seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw); |
788 | seq_printf(m, "%u dwords in ring\n", count); | 793 | seq_printf(m, "%u dwords in ring\n", count); |
789 | /* print 8 dw before current rptr as often it's the last executed | 794 | /* print 8 dw before current rptr as often it's the last executed |
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c index 97f3ece81cd2..8dcc20f53d73 100644 --- a/drivers/gpu/drm/radeon/radeon_semaphore.c +++ b/drivers/gpu/drm/radeon/radeon_semaphore.c | |||
@@ -95,6 +95,10 @@ int radeon_semaphore_sync_rings(struct radeon_device *rdev, | |||
95 | /* we assume caller has already allocated space on waiters ring */ | 95 | /* we assume caller has already allocated space on waiters ring */ |
96 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); | 96 | radeon_semaphore_emit_wait(rdev, waiter, semaphore); |
97 | 97 | ||
98 | /* for debugging lockup only, used by sysfs debug files */ | ||
99 | rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr; | ||
100 | rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr; | ||
101 | |||
98 | return 0; | 102 | return 0; |
99 | } | 103 | } |
100 | 104 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index 1d8ff2f850ba..93f760e27a92 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <drm/radeon_drm.h> | 38 | #include <drm/radeon_drm.h> |
39 | #include <linux/seq_file.h> | 39 | #include <linux/seq_file.h> |
40 | #include <linux/slab.h> | 40 | #include <linux/slab.h> |
41 | #include <linux/swiotlb.h> | ||
41 | #include "radeon_reg.h" | 42 | #include "radeon_reg.h" |
42 | #include "radeon.h" | 43 | #include "radeon.h" |
43 | 44 | ||
diff --git a/drivers/gpu/drm/radeon/reg_srcs/cayman b/drivers/gpu/drm/radeon/reg_srcs/cayman index 0f656b111c15..a072fa8c46b0 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/cayman +++ b/drivers/gpu/drm/radeon/reg_srcs/cayman | |||
@@ -1,5 +1,6 @@ | |||
1 | cayman 0x9400 | 1 | cayman 0x9400 |
2 | 0x0000802C GRBM_GFX_INDEX | 2 | 0x0000802C GRBM_GFX_INDEX |
3 | 0x00008040 WAIT_UNTIL | ||
3 | 0x000084FC CP_STRMOUT_CNTL | 4 | 0x000084FC CP_STRMOUT_CNTL |
4 | 0x000085F0 CP_COHER_CNTL | 5 | 0x000085F0 CP_COHER_CNTL |
5 | 0x000085F4 CP_COHER_SIZE | 6 | 0x000085F4 CP_COHER_SIZE |
diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515 index 911a8fbd32bb..78d5e99d759d 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/rv515 +++ b/drivers/gpu/drm/radeon/reg_srcs/rv515 | |||
@@ -324,6 +324,8 @@ rv515 0x6d40 | |||
324 | 0x46AC US_OUT_FMT_2 | 324 | 0x46AC US_OUT_FMT_2 |
325 | 0x46B0 US_OUT_FMT_3 | 325 | 0x46B0 US_OUT_FMT_3 |
326 | 0x46B4 US_W_FMT | 326 | 0x46B4 US_W_FMT |
327 | 0x46C0 RB3D_COLOR_CLEAR_VALUE_AR | ||
328 | 0x46C4 RB3D_COLOR_CLEAR_VALUE_GB | ||
327 | 0x4BC0 FG_FOG_BLEND | 329 | 0x4BC0 FG_FOG_BLEND |
328 | 0x4BC4 FG_FOG_FACTOR | 330 | 0x4BC4 FG_FOG_FACTOR |
329 | 0x4BC8 FG_FOG_COLOR_R | 331 | 0x4BC8 FG_FOG_COLOR_R |
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 2bb6d0e84b3d..435ed3551364 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c | |||
@@ -336,6 +336,8 @@ void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save) | |||
336 | WREG32(R600_CITF_CNTL, blackout); | 336 | WREG32(R600_CITF_CNTL, blackout); |
337 | } | 337 | } |
338 | } | 338 | } |
339 | /* wait for the MC to settle */ | ||
340 | udelay(100); | ||
339 | } | 341 | } |
340 | 342 | ||
341 | void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) | 343 | void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save) |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 3240a3d64f30..ae8b48205a6c 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
@@ -2215,6 +2215,12 @@ static int si_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) | |||
2215 | { | 2215 | { |
2216 | struct evergreen_mc_save save; | 2216 | struct evergreen_mc_save save; |
2217 | 2217 | ||
2218 | if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE)) | ||
2219 | reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE); | ||
2220 | |||
2221 | if (RREG32(DMA_STATUS_REG) & DMA_IDLE) | ||
2222 | reset_mask &= ~RADEON_RESET_DMA; | ||
2223 | |||
2218 | if (reset_mask == 0) | 2224 | if (reset_mask == 0) |
2219 | return 0; | 2225 | return 0; |
2220 | 2226 | ||
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 33d20be87db5..52b20b12c83a 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -434,6 +434,7 @@ static int ttm_bo_handle_move_mem(struct ttm_buffer_object *bo, | |||
434 | bo->mem = tmp_mem; | 434 | bo->mem = tmp_mem; |
435 | bdev->driver->move_notify(bo, mem); | 435 | bdev->driver->move_notify(bo, mem); |
436 | bo->mem = *mem; | 436 | bo->mem = *mem; |
437 | *mem = tmp_mem; | ||
437 | } | 438 | } |
438 | 439 | ||
439 | goto out_err; | 440 | goto out_err; |
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c index d73d6e3e17b2..8be35c809c7b 100644 --- a/drivers/gpu/drm/ttm/ttm_bo_util.c +++ b/drivers/gpu/drm/ttm/ttm_bo_util.c | |||
@@ -344,8 +344,12 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
344 | 344 | ||
345 | if (ttm->state == tt_unpopulated) { | 345 | if (ttm->state == tt_unpopulated) { |
346 | ret = ttm->bdev->driver->ttm_tt_populate(ttm); | 346 | ret = ttm->bdev->driver->ttm_tt_populate(ttm); |
347 | if (ret) | 347 | if (ret) { |
348 | /* if we fail here don't nuke the mm node | ||
349 | * as the bo still owns it */ | ||
350 | old_copy.mm_node = NULL; | ||
348 | goto out1; | 351 | goto out1; |
352 | } | ||
349 | } | 353 | } |
350 | 354 | ||
351 | add = 0; | 355 | add = 0; |
@@ -371,8 +375,11 @@ int ttm_bo_move_memcpy(struct ttm_buffer_object *bo, | |||
371 | prot); | 375 | prot); |
372 | } else | 376 | } else |
373 | ret = ttm_copy_io_page(new_iomap, old_iomap, page); | 377 | ret = ttm_copy_io_page(new_iomap, old_iomap, page); |
374 | if (ret) | 378 | if (ret) { |
379 | /* failing here, means keep old copy as-is */ | ||
380 | old_copy.mm_node = NULL; | ||
375 | goto out1; | 381 | goto out1; |
382 | } | ||
376 | } | 383 | } |
377 | mb(); | 384 | mb(); |
378 | out2: | 385 | out2: |
@@ -422,7 +429,7 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, | |||
422 | struct ttm_bo_device *bdev = bo->bdev; | 429 | struct ttm_bo_device *bdev = bo->bdev; |
423 | struct ttm_bo_driver *driver = bdev->driver; | 430 | struct ttm_bo_driver *driver = bdev->driver; |
424 | 431 | ||
425 | fbo = kzalloc(sizeof(*fbo), GFP_KERNEL); | 432 | fbo = kmalloc(sizeof(*fbo), GFP_KERNEL); |
426 | if (!fbo) | 433 | if (!fbo) |
427 | return -ENOMEM; | 434 | return -ENOMEM; |
428 | 435 | ||
@@ -441,7 +448,12 @@ static int ttm_buffer_object_transfer(struct ttm_buffer_object *bo, | |||
441 | fbo->vm_node = NULL; | 448 | fbo->vm_node = NULL; |
442 | atomic_set(&fbo->cpu_writers, 0); | 449 | atomic_set(&fbo->cpu_writers, 0); |
443 | 450 | ||
444 | fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); | 451 | spin_lock(&bdev->fence_lock); |
452 | if (bo->sync_obj) | ||
453 | fbo->sync_obj = driver->sync_obj_ref(bo->sync_obj); | ||
454 | else | ||
455 | fbo->sync_obj = NULL; | ||
456 | spin_unlock(&bdev->fence_lock); | ||
445 | kref_init(&fbo->list_kref); | 457 | kref_init(&fbo->list_kref); |
446 | kref_init(&fbo->kref); | 458 | kref_init(&fbo->kref); |
447 | fbo->destroy = &ttm_transfered_destroy; | 459 | fbo->destroy = &ttm_transfered_destroy; |
@@ -654,13 +666,11 @@ int ttm_bo_move_accel_cleanup(struct ttm_buffer_object *bo, | |||
654 | */ | 666 | */ |
655 | 667 | ||
656 | set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); | 668 | set_bit(TTM_BO_PRIV_FLAG_MOVING, &bo->priv_flags); |
657 | |||
658 | /* ttm_buffer_object_transfer accesses bo->sync_obj */ | ||
659 | ret = ttm_buffer_object_transfer(bo, &ghost_obj); | ||
660 | spin_unlock(&bdev->fence_lock); | 669 | spin_unlock(&bdev->fence_lock); |
661 | if (tmp_obj) | 670 | if (tmp_obj) |
662 | driver->sync_obj_unref(&tmp_obj); | 671 | driver->sync_obj_unref(&tmp_obj); |
663 | 672 | ||
673 | ret = ttm_buffer_object_transfer(bo, &ghost_obj); | ||
664 | if (ret) | 674 | if (ret) |
665 | return ret; | 675 | return ret; |
666 | 676 | ||
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c index 512f44add89f..fe5cdbcf2636 100644 --- a/drivers/gpu/drm/udl/udl_connector.c +++ b/drivers/gpu/drm/udl/udl_connector.c | |||
@@ -22,13 +22,17 @@ | |||
22 | static u8 *udl_get_edid(struct udl_device *udl) | 22 | static u8 *udl_get_edid(struct udl_device *udl) |
23 | { | 23 | { |
24 | u8 *block; | 24 | u8 *block; |
25 | char rbuf[3]; | 25 | char *rbuf; |
26 | int ret, i; | 26 | int ret, i; |
27 | 27 | ||
28 | block = kmalloc(EDID_LENGTH, GFP_KERNEL); | 28 | block = kmalloc(EDID_LENGTH, GFP_KERNEL); |
29 | if (block == NULL) | 29 | if (block == NULL) |
30 | return NULL; | 30 | return NULL; |
31 | 31 | ||
32 | rbuf = kmalloc(2, GFP_KERNEL); | ||
33 | if (rbuf == NULL) | ||
34 | goto error; | ||
35 | |||
32 | for (i = 0; i < EDID_LENGTH; i++) { | 36 | for (i = 0; i < EDID_LENGTH; i++) { |
33 | ret = usb_control_msg(udl->ddev->usbdev, | 37 | ret = usb_control_msg(udl->ddev->usbdev, |
34 | usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), | 38 | usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02), |
@@ -36,16 +40,17 @@ static u8 *udl_get_edid(struct udl_device *udl) | |||
36 | HZ); | 40 | HZ); |
37 | if (ret < 1) { | 41 | if (ret < 1) { |
38 | DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); | 42 | DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret); |
39 | i--; | ||
40 | goto error; | 43 | goto error; |
41 | } | 44 | } |
42 | block[i] = rbuf[1]; | 45 | block[i] = rbuf[1]; |
43 | } | 46 | } |
44 | 47 | ||
48 | kfree(rbuf); | ||
45 | return block; | 49 | return block; |
46 | 50 | ||
47 | error: | 51 | error: |
48 | kfree(block); | 52 | kfree(block); |
53 | kfree(rbuf); | ||
49 | return NULL; | 54 | return NULL; |
50 | } | 55 | } |
51 | 56 | ||
@@ -57,6 +62,14 @@ static int udl_get_modes(struct drm_connector *connector) | |||
57 | 62 | ||
58 | edid = (struct edid *)udl_get_edid(udl); | 63 | edid = (struct edid *)udl_get_edid(udl); |
59 | 64 | ||
65 | /* | ||
66 | * We only read the main block, but if the monitor reports extension | ||
67 | * blocks then the drm edid code expects them to be present, so patch | ||
68 | * the extension count to 0. | ||
69 | */ | ||
70 | edid->checksum += edid->extensions; | ||
71 | edid->extensions = 0; | ||
72 | |||
60 | drm_mode_connector_update_edid_property(connector, edid); | 73 | drm_mode_connector_update_edid_property(connector, edid); |
61 | ret = drm_add_edid_modes(connector, edid); | 74 | ret = drm_add_edid_modes(connector, edid); |
62 | kfree(edid); | 75 | kfree(edid); |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 4dfa605e2d14..34e25471aeaa 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -306,6 +306,9 @@ | |||
306 | #define USB_VENDOR_ID_EZKEY 0x0518 | 306 | #define USB_VENDOR_ID_EZKEY 0x0518 |
307 | #define USB_DEVICE_ID_BTC_8193 0x0002 | 307 | #define USB_DEVICE_ID_BTC_8193 0x0002 |
308 | 308 | ||
309 | #define USB_VENDOR_ID_FORMOSA 0x147a | ||
310 | #define USB_DEVICE_ID_FORMOSA_IR_RECEIVER 0xe03e | ||
311 | |||
309 | #define USB_VENDOR_ID_FREESCALE 0x15A2 | 312 | #define USB_VENDOR_ID_FREESCALE 0x15A2 |
310 | #define USB_DEVICE_ID_FREESCALE_MX28 0x004F | 313 | #define USB_DEVICE_ID_FREESCALE_MX28 0x004F |
311 | 314 | ||
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c index 12e4fdc810bf..e766b5614ef5 100644 --- a/drivers/hid/i2c-hid/i2c-hid.c +++ b/drivers/hid/i2c-hid/i2c-hid.c | |||
@@ -540,13 +540,24 @@ static int i2c_hid_output_raw_report(struct hid_device *hid, __u8 *buf, | |||
540 | { | 540 | { |
541 | struct i2c_client *client = hid->driver_data; | 541 | struct i2c_client *client = hid->driver_data; |
542 | int report_id = buf[0]; | 542 | int report_id = buf[0]; |
543 | int ret; | ||
543 | 544 | ||
544 | if (report_type == HID_INPUT_REPORT) | 545 | if (report_type == HID_INPUT_REPORT) |
545 | return -EINVAL; | 546 | return -EINVAL; |
546 | 547 | ||
547 | return i2c_hid_set_report(client, | 548 | if (report_id) { |
549 | buf++; | ||
550 | count--; | ||
551 | } | ||
552 | |||
553 | ret = i2c_hid_set_report(client, | ||
548 | report_type == HID_FEATURE_REPORT ? 0x03 : 0x02, | 554 | report_type == HID_FEATURE_REPORT ? 0x03 : 0x02, |
549 | report_id, buf, count); | 555 | report_id, buf, count); |
556 | |||
557 | if (report_id && ret >= 0) | ||
558 | ret++; /* add report_id to the number of transfered bytes */ | ||
559 | |||
560 | return ret; | ||
550 | } | 561 | } |
551 | 562 | ||
552 | static int i2c_hid_parse(struct hid_device *hid) | 563 | static int i2c_hid_parse(struct hid_device *hid) |
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c index ac9e35228254..e0e6abf1cd3b 100644 --- a/drivers/hid/usbhid/hid-quirks.c +++ b/drivers/hid/usbhid/hid-quirks.c | |||
@@ -70,6 +70,7 @@ static const struct hid_blacklist { | |||
70 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, | 70 | { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET }, |
71 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, | 71 | { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET }, |
72 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, | 72 | { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET }, |
73 | { USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS }, | ||
73 | { 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 }, |
74 | { 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 }, |
75 | { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, | 76 | { USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS }, |
diff --git a/drivers/hv/Kconfig b/drivers/hv/Kconfig index b38ef6d8d049..64630f15f181 100644 --- a/drivers/hv/Kconfig +++ b/drivers/hv/Kconfig | |||
@@ -2,7 +2,7 @@ menu "Microsoft Hyper-V guest support" | |||
2 | 2 | ||
3 | config HYPERV | 3 | config HYPERV |
4 | tristate "Microsoft Hyper-V client drivers" | 4 | tristate "Microsoft Hyper-V client drivers" |
5 | depends on X86 && ACPI && PCI | 5 | depends on X86 && ACPI && PCI && X86_LOCAL_APIC |
6 | help | 6 | help |
7 | Select this option to run Linux as a Hyper-V client operating | 7 | Select this option to run Linux as a Hyper-V client operating |
8 | system. | 8 | system. |
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c index f6c0011a0337..dd289fd179ca 100644 --- a/drivers/hv/hv_balloon.c +++ b/drivers/hv/hv_balloon.c | |||
@@ -403,7 +403,7 @@ struct dm_info_header { | |||
403 | */ | 403 | */ |
404 | 404 | ||
405 | struct dm_info_msg { | 405 | struct dm_info_msg { |
406 | struct dm_info_header header; | 406 | struct dm_header hdr; |
407 | __u32 reserved; | 407 | __u32 reserved; |
408 | __u32 info_size; | 408 | __u32 info_size; |
409 | __u8 info[]; | 409 | __u8 info[]; |
@@ -503,13 +503,17 @@ static void hot_add_req(struct hv_dynmem_device *dm, struct dm_hot_add *msg) | |||
503 | 503 | ||
504 | static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) | 504 | static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg) |
505 | { | 505 | { |
506 | switch (msg->header.type) { | 506 | struct dm_info_header *info_hdr; |
507 | |||
508 | info_hdr = (struct dm_info_header *)msg->info; | ||
509 | |||
510 | switch (info_hdr->type) { | ||
507 | case INFO_TYPE_MAX_PAGE_CNT: | 511 | case INFO_TYPE_MAX_PAGE_CNT: |
508 | pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n"); | 512 | pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n"); |
509 | pr_info("Data Size is %d\n", msg->header.data_size); | 513 | pr_info("Data Size is %d\n", info_hdr->data_size); |
510 | break; | 514 | break; |
511 | default: | 515 | default: |
512 | pr_info("Received Unknown type: %d\n", msg->header.type); | 516 | pr_info("Received Unknown type: %d\n", info_hdr->type); |
513 | } | 517 | } |
514 | } | 518 | } |
515 | 519 | ||
@@ -879,7 +883,7 @@ static int balloon_probe(struct hv_device *dev, | |||
879 | balloon_onchannelcallback, dev); | 883 | balloon_onchannelcallback, dev); |
880 | 884 | ||
881 | if (ret) | 885 | if (ret) |
882 | return ret; | 886 | goto probe_error0; |
883 | 887 | ||
884 | dm_device.dev = dev; | 888 | dm_device.dev = dev; |
885 | dm_device.state = DM_INITIALIZING; | 889 | dm_device.state = DM_INITIALIZING; |
@@ -891,7 +895,7 @@ static int balloon_probe(struct hv_device *dev, | |||
891 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); | 895 | kthread_run(dm_thread_func, &dm_device, "hv_balloon"); |
892 | if (IS_ERR(dm_device.thread)) { | 896 | if (IS_ERR(dm_device.thread)) { |
893 | ret = PTR_ERR(dm_device.thread); | 897 | ret = PTR_ERR(dm_device.thread); |
894 | goto probe_error0; | 898 | goto probe_error1; |
895 | } | 899 | } |
896 | 900 | ||
897 | hv_set_drvdata(dev, &dm_device); | 901 | hv_set_drvdata(dev, &dm_device); |
@@ -914,12 +918,12 @@ static int balloon_probe(struct hv_device *dev, | |||
914 | VM_PKT_DATA_INBAND, | 918 | VM_PKT_DATA_INBAND, |
915 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 919 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
916 | if (ret) | 920 | if (ret) |
917 | goto probe_error1; | 921 | goto probe_error2; |
918 | 922 | ||
919 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); | 923 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); |
920 | if (t == 0) { | 924 | if (t == 0) { |
921 | ret = -ETIMEDOUT; | 925 | ret = -ETIMEDOUT; |
922 | goto probe_error1; | 926 | goto probe_error2; |
923 | } | 927 | } |
924 | 928 | ||
925 | /* | 929 | /* |
@@ -928,7 +932,7 @@ static int balloon_probe(struct hv_device *dev, | |||
928 | */ | 932 | */ |
929 | if (dm_device.state == DM_INIT_ERROR) { | 933 | if (dm_device.state == DM_INIT_ERROR) { |
930 | ret = -ETIMEDOUT; | 934 | ret = -ETIMEDOUT; |
931 | goto probe_error1; | 935 | goto probe_error2; |
932 | } | 936 | } |
933 | /* | 937 | /* |
934 | * Now submit our capabilities to the host. | 938 | * Now submit our capabilities to the host. |
@@ -961,12 +965,12 @@ static int balloon_probe(struct hv_device *dev, | |||
961 | VM_PKT_DATA_INBAND, | 965 | VM_PKT_DATA_INBAND, |
962 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); | 966 | VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED); |
963 | if (ret) | 967 | if (ret) |
964 | goto probe_error1; | 968 | goto probe_error2; |
965 | 969 | ||
966 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); | 970 | t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ); |
967 | if (t == 0) { | 971 | if (t == 0) { |
968 | ret = -ETIMEDOUT; | 972 | ret = -ETIMEDOUT; |
969 | goto probe_error1; | 973 | goto probe_error2; |
970 | } | 974 | } |
971 | 975 | ||
972 | /* | 976 | /* |
@@ -975,18 +979,20 @@ static int balloon_probe(struct hv_device *dev, | |||
975 | */ | 979 | */ |
976 | if (dm_device.state == DM_INIT_ERROR) { | 980 | if (dm_device.state == DM_INIT_ERROR) { |
977 | ret = -ETIMEDOUT; | 981 | ret = -ETIMEDOUT; |
978 | goto probe_error1; | 982 | goto probe_error2; |
979 | } | 983 | } |
980 | 984 | ||
981 | dm_device.state = DM_INITIALIZED; | 985 | dm_device.state = DM_INITIALIZED; |
982 | 986 | ||
983 | return 0; | 987 | return 0; |
984 | 988 | ||
985 | probe_error1: | 989 | probe_error2: |
986 | kthread_stop(dm_device.thread); | 990 | kthread_stop(dm_device.thread); |
987 | 991 | ||
988 | probe_error0: | 992 | probe_error1: |
989 | vmbus_close(dev->channel); | 993 | vmbus_close(dev->channel); |
994 | probe_error0: | ||
995 | kfree(send_buffer); | ||
990 | return ret; | 996 | return ret; |
991 | } | 997 | } |
992 | 998 | ||
@@ -999,6 +1005,7 @@ static int balloon_remove(struct hv_device *dev) | |||
999 | 1005 | ||
1000 | vmbus_close(dev->channel); | 1006 | vmbus_close(dev->channel); |
1001 | kthread_stop(dm->thread); | 1007 | kthread_stop(dm->thread); |
1008 | kfree(send_buffer); | ||
1002 | 1009 | ||
1003 | return 0; | 1010 | return 0; |
1004 | } | 1011 | } |
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c index 86d7f6d858b1..d867e6bb2be1 100644 --- a/drivers/hwmon/vexpress.c +++ b/drivers/hwmon/vexpress.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/hwmon.h> | 19 | #include <linux/hwmon.h> |
20 | #include <linux/hwmon-sysfs.h> | 20 | #include <linux/hwmon-sysfs.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | 23 | #include <linux/of_device.h> |
23 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
24 | #include <linux/vexpress.h> | 25 | #include <linux/vexpress.h> |
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c index cbba7db9ad59..f5258c205de5 100644 --- a/drivers/i2c/busses/i2c-designware-core.c +++ b/drivers/i2c/busses/i2c-designware-core.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/io.h> | 34 | #include <linux/io.h> |
35 | #include <linux/pm_runtime.h> | 35 | #include <linux/pm_runtime.h> |
36 | #include <linux/delay.h> | 36 | #include <linux/delay.h> |
37 | #include <linux/module.h> | ||
37 | #include "i2c-designware-core.h" | 38 | #include "i2c-designware-core.h" |
38 | 39 | ||
39 | /* | 40 | /* |
@@ -725,3 +726,6 @@ u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev) | |||
725 | return dw_readl(dev, DW_IC_COMP_PARAM_1); | 726 | return dw_readl(dev, DW_IC_COMP_PARAM_1); |
726 | } | 727 | } |
727 | EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); | 728 | EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param); |
729 | |||
730 | MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core"); | ||
731 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c index 1b1a936eccc9..d6abaf2cf2e3 100644 --- a/drivers/i2c/busses/i2c-mxs.c +++ b/drivers/i2c/busses/i2c-mxs.c | |||
@@ -127,7 +127,7 @@ struct mxs_i2c_dev { | |||
127 | struct device *dev; | 127 | struct device *dev; |
128 | void __iomem *regs; | 128 | void __iomem *regs; |
129 | struct completion cmd_complete; | 129 | struct completion cmd_complete; |
130 | u32 cmd_err; | 130 | int cmd_err; |
131 | struct i2c_adapter adapter; | 131 | struct i2c_adapter adapter; |
132 | const struct mxs_i2c_speed_config *speed; | 132 | const struct mxs_i2c_speed_config *speed; |
133 | 133 | ||
@@ -316,7 +316,7 @@ static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, | |||
316 | if (msg->len == 0) | 316 | if (msg->len == 0) |
317 | return -EINVAL; | 317 | return -EINVAL; |
318 | 318 | ||
319 | init_completion(&i2c->cmd_complete); | 319 | INIT_COMPLETION(i2c->cmd_complete); |
320 | i2c->cmd_err = 0; | 320 | i2c->cmd_err = 0; |
321 | 321 | ||
322 | ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); | 322 | ret = mxs_i2c_dma_setup_xfer(adap, msg, flags); |
@@ -473,6 +473,8 @@ static int mxs_i2c_probe(struct platform_device *pdev) | |||
473 | i2c->dev = dev; | 473 | i2c->dev = dev; |
474 | i2c->speed = &mxs_i2c_95kHz_config; | 474 | i2c->speed = &mxs_i2c_95kHz_config; |
475 | 475 | ||
476 | init_completion(&i2c->cmd_complete); | ||
477 | |||
476 | if (dev->of_node) { | 478 | if (dev->of_node) { |
477 | err = mxs_i2c_get_ofdata(i2c); | 479 | err = mxs_i2c_get_ofdata(i2c); |
478 | if (err) | 480 | if (err) |
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 20d41bfa7c19..4cc2f0528c88 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c | |||
@@ -803,7 +803,7 @@ static int errata_omap3_i462(struct omap_i2c_dev *dev) | |||
803 | if (stat & OMAP_I2C_STAT_AL) { | 803 | if (stat & OMAP_I2C_STAT_AL) { |
804 | dev_err(dev->dev, "Arbitration lost\n"); | 804 | dev_err(dev->dev, "Arbitration lost\n"); |
805 | dev->cmd_err |= OMAP_I2C_STAT_AL; | 805 | dev->cmd_err |= OMAP_I2C_STAT_AL; |
806 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK); | 806 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL); |
807 | } | 807 | } |
808 | 808 | ||
809 | return -EIO; | 809 | return -EIO; |
@@ -963,7 +963,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) | |||
963 | i2c_omap_errata_i207(dev, stat); | 963 | i2c_omap_errata_i207(dev, stat); |
964 | 964 | ||
965 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); | 965 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR); |
966 | break; | 966 | continue; |
967 | } | 967 | } |
968 | 968 | ||
969 | if (stat & OMAP_I2C_STAT_RRDY) { | 969 | if (stat & OMAP_I2C_STAT_RRDY) { |
@@ -989,7 +989,7 @@ omap_i2c_isr_thread(int this_irq, void *dev_id) | |||
989 | break; | 989 | break; |
990 | 990 | ||
991 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR); | 991 | omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR); |
992 | break; | 992 | continue; |
993 | } | 993 | } |
994 | 994 | ||
995 | if (stat & OMAP_I2C_STAT_XRDY) { | 995 | if (stat & OMAP_I2C_STAT_XRDY) { |
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c index 3f1818b87974..e03381aee34f 100644 --- a/drivers/i2c/busses/i2c-sirf.c +++ b/drivers/i2c/busses/i2c-sirf.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/platform_device.h> | 13 | #include <linux/platform_device.h> |
14 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
15 | #include <linux/of_i2c.h> | ||
15 | #include <linux/clk.h> | 16 | #include <linux/clk.h> |
16 | #include <linux/err.h> | 17 | #include <linux/err.h> |
17 | #include <linux/io.h> | 18 | #include <linux/io.h> |
@@ -328,6 +329,7 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) | |||
328 | adap->algo = &i2c_sirfsoc_algo; | 329 | adap->algo = &i2c_sirfsoc_algo; |
329 | adap->algo_data = siic; | 330 | adap->algo_data = siic; |
330 | 331 | ||
332 | adap->dev.of_node = pdev->dev.of_node; | ||
331 | adap->dev.parent = &pdev->dev; | 333 | adap->dev.parent = &pdev->dev; |
332 | adap->nr = pdev->id; | 334 | adap->nr = pdev->id; |
333 | 335 | ||
@@ -371,6 +373,8 @@ static int i2c_sirfsoc_probe(struct platform_device *pdev) | |||
371 | 373 | ||
372 | clk_disable(clk); | 374 | clk_disable(clk); |
373 | 375 | ||
376 | of_i2c_register_devices(adap); | ||
377 | |||
374 | dev_info(&pdev->dev, " I2C adapter ready to operate\n"); | 378 | dev_info(&pdev->dev, " I2C adapter ready to operate\n"); |
375 | 379 | ||
376 | return 0; | 380 | return 0; |
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c index 1e44d04d1b22..a43c0ce5e3d8 100644 --- a/drivers/i2c/muxes/i2c-mux-pinctrl.c +++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c | |||
@@ -167,7 +167,7 @@ static int i2c_mux_pinctrl_probe(struct platform_device *pdev) | |||
167 | } | 167 | } |
168 | 168 | ||
169 | mux->busses = devm_kzalloc(&pdev->dev, | 169 | mux->busses = devm_kzalloc(&pdev->dev, |
170 | sizeof(mux->busses) * mux->pdata->bus_count, | 170 | sizeof(*mux->busses) * mux->pdata->bus_count, |
171 | GFP_KERNEL); | 171 | GFP_KERNEL); |
172 | if (!mux->busses) { | 172 | if (!mux->busses) { |
173 | dev_err(&pdev->dev, "Cannot allocate busses\n"); | 173 | dev_err(&pdev->dev, "Cannot allocate busses\n"); |
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c index 4ba384f1ab54..2df9414a72f7 100644 --- a/drivers/idle/intel_idle.c +++ b/drivers/idle/intel_idle.c | |||
@@ -448,8 +448,6 @@ static int intel_idle_probe(void) | |||
448 | else | 448 | else |
449 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); | 449 | on_each_cpu(__setup_broadcast_timer, (void *)true, 1); |
450 | 450 | ||
451 | register_cpu_notifier(&cpu_hotplug_notifier); | ||
452 | |||
453 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION | 451 | pr_debug(PREFIX "v" INTEL_IDLE_VERSION |
454 | " model 0x%X\n", boot_cpu_data.x86_model); | 452 | " model 0x%X\n", boot_cpu_data.x86_model); |
455 | 453 | ||
@@ -612,6 +610,7 @@ static int __init intel_idle_init(void) | |||
612 | return retval; | 610 | return retval; |
613 | } | 611 | } |
614 | } | 612 | } |
613 | register_cpu_notifier(&cpu_hotplug_notifier); | ||
615 | 614 | ||
616 | return 0; | 615 | return 0; |
617 | } | 616 | } |
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig index fe4bcd7c5b12..05e996fafc9d 100644 --- a/drivers/iio/accel/Kconfig +++ b/drivers/iio/accel/Kconfig | |||
@@ -8,6 +8,7 @@ config HID_SENSOR_ACCEL_3D | |||
8 | select IIO_BUFFER | 8 | select IIO_BUFFER |
9 | select IIO_TRIGGERED_BUFFER | 9 | select IIO_TRIGGERED_BUFFER |
10 | select HID_SENSOR_IIO_COMMON | 10 | select HID_SENSOR_IIO_COMMON |
11 | select HID_SENSOR_IIO_TRIGGER | ||
11 | tristate "HID Accelerometers 3D" | 12 | tristate "HID Accelerometers 3D" |
12 | help | 13 | help |
13 | Say yes here to build support for the HID SENSOR | 14 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c index 4a5f639bc684..bbad9b94cd75 100644 --- a/drivers/iio/adc/ad7266.c +++ b/drivers/iio/adc/ad7266.c | |||
@@ -411,7 +411,11 @@ static int ad7266_probe(struct spi_device *spi) | |||
411 | if (ret) | 411 | if (ret) |
412 | goto error_put_reg; | 412 | goto error_put_reg; |
413 | 413 | ||
414 | st->vref_uv = regulator_get_voltage(st->reg); | 414 | ret = regulator_get_voltage(st->reg); |
415 | if (ret < 0) | ||
416 | goto error_disable_reg; | ||
417 | |||
418 | st->vref_uv = ret; | ||
415 | } else { | 419 | } else { |
416 | /* Use internal reference */ | 420 | /* Use internal reference */ |
417 | st->vref_uv = 2500000; | 421 | st->vref_uv = 2500000; |
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c index 04b013561f0f..a526c0e3aaa8 100644 --- a/drivers/iio/adc/at91_adc.c +++ b/drivers/iio/adc/at91_adc.c | |||
@@ -80,7 +80,7 @@ static irqreturn_t at91_adc_trigger_handler(int irq, void *p) | |||
80 | *timestamp = pf->timestamp; | 80 | *timestamp = pf->timestamp; |
81 | } | 81 | } |
82 | 82 | ||
83 | iio_push_to_buffers(indio_dev, (u8 *)st->buffer); | 83 | iio_push_to_buffers(idev, (u8 *)st->buffer); |
84 | 84 | ||
85 | iio_trigger_notify_done(idev->trig); | 85 | iio_trigger_notify_done(idev->trig); |
86 | 86 | ||
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c index b5669be6f396..03b25b3dc71e 100644 --- a/drivers/iio/adc/max1363.c +++ b/drivers/iio/adc/max1363.c | |||
@@ -1605,19 +1605,20 @@ static int max1363_probe(struct i2c_client *client, | |||
1605 | 1605 | ||
1606 | return 0; | 1606 | return 0; |
1607 | error_free_irq: | 1607 | error_free_irq: |
1608 | free_irq(st->client->irq, indio_dev); | 1608 | if (client->irq) |
1609 | free_irq(st->client->irq, indio_dev); | ||
1609 | error_uninit_buffer: | 1610 | error_uninit_buffer: |
1610 | iio_buffer_unregister(indio_dev); | 1611 | iio_buffer_unregister(indio_dev); |
1611 | error_cleanup_buffer: | 1612 | error_cleanup_buffer: |
1612 | max1363_buffer_cleanup(indio_dev); | 1613 | max1363_buffer_cleanup(indio_dev); |
1613 | error_free_available_scan_masks: | 1614 | error_free_available_scan_masks: |
1614 | kfree(indio_dev->available_scan_masks); | 1615 | kfree(indio_dev->available_scan_masks); |
1615 | error_unregister_map: | ||
1616 | iio_map_array_unregister(indio_dev, client->dev.platform_data); | ||
1617 | error_disable_reg: | 1616 | error_disable_reg: |
1618 | regulator_disable(st->reg); | 1617 | regulator_disable(st->reg); |
1619 | error_put_reg: | 1618 | error_put_reg: |
1620 | regulator_put(st->reg); | 1619 | regulator_put(st->reg); |
1620 | error_unregister_map: | ||
1621 | iio_map_array_unregister(indio_dev, client->dev.platform_data); | ||
1621 | error_free_device: | 1622 | error_free_device: |
1622 | iio_device_free(indio_dev); | 1623 | iio_device_free(indio_dev); |
1623 | error_out: | 1624 | error_out: |
@@ -1635,10 +1636,8 @@ static int max1363_remove(struct i2c_client *client) | |||
1635 | iio_buffer_unregister(indio_dev); | 1636 | iio_buffer_unregister(indio_dev); |
1636 | max1363_buffer_cleanup(indio_dev); | 1637 | max1363_buffer_cleanup(indio_dev); |
1637 | kfree(indio_dev->available_scan_masks); | 1638 | kfree(indio_dev->available_scan_masks); |
1638 | if (!IS_ERR(st->reg)) { | 1639 | regulator_disable(st->reg); |
1639 | regulator_disable(st->reg); | 1640 | regulator_put(st->reg); |
1640 | regulator_put(st->reg); | ||
1641 | } | ||
1642 | iio_map_array_unregister(indio_dev, client->dev.platform_data); | 1641 | iio_map_array_unregister(indio_dev, client->dev.platform_data); |
1643 | iio_device_free(indio_dev); | 1642 | iio_device_free(indio_dev); |
1644 | 1643 | ||
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig index ae10778da7aa..1178121b55b0 100644 --- a/drivers/iio/common/hid-sensors/Kconfig +++ b/drivers/iio/common/hid-sensors/Kconfig | |||
@@ -6,7 +6,7 @@ menu "Hid Sensor IIO Common" | |||
6 | config HID_SENSOR_IIO_COMMON | 6 | config HID_SENSOR_IIO_COMMON |
7 | tristate "Common modules for all HID Sensor IIO drivers" | 7 | tristate "Common modules for all HID Sensor IIO drivers" |
8 | depends on HID_SENSOR_HUB | 8 | depends on HID_SENSOR_HUB |
9 | select IIO_TRIGGER if IIO_BUFFER | 9 | select HID_SENSOR_IIO_TRIGGER if IIO_BUFFER |
10 | help | 10 | help |
11 | Say yes here to build support for HID sensor to use | 11 | Say yes here to build support for HID sensor to use |
12 | HID sensor common processing for attributes and IIO triggers. | 12 | HID sensor common processing for attributes and IIO triggers. |
@@ -14,6 +14,17 @@ config HID_SENSOR_IIO_COMMON | |||
14 | HID sensor drivers, this module contains processing for those | 14 | HID sensor drivers, this module contains processing for those |
15 | attributes. | 15 | attributes. |
16 | 16 | ||
17 | config HID_SENSOR_IIO_TRIGGER | ||
18 | tristate "Common module (trigger) for all HID Sensor IIO drivers" | ||
19 | depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON | ||
20 | select IIO_TRIGGER | ||
21 | help | ||
22 | Say yes here to build trigger support for HID sensors. | ||
23 | Triggers will be send if all requested attributes were read. | ||
24 | |||
25 | If this driver is compiled as a module, it will be named | ||
26 | hid-sensor-trigger. | ||
27 | |||
17 | config HID_SENSOR_ENUM_BASE_QUIRKS | 28 | config HID_SENSOR_ENUM_BASE_QUIRKS |
18 | bool "ENUM base quirks for HID Sensor IIO drivers" | 29 | bool "ENUM base quirks for HID Sensor IIO drivers" |
19 | depends on HID_SENSOR_IIO_COMMON | 30 | depends on HID_SENSOR_IIO_COMMON |
diff --git a/drivers/iio/common/hid-sensors/Makefile b/drivers/iio/common/hid-sensors/Makefile index 1f463e00c242..22e7c5a82325 100644 --- a/drivers/iio/common/hid-sensors/Makefile +++ b/drivers/iio/common/hid-sensors/Makefile | |||
@@ -3,4 +3,5 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o | 5 | obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o |
6 | hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o | 6 | obj-$(CONFIG_HID_SENSOR_IIO_TRIGGER) += hid-sensor-trigger.o |
7 | hid-sensor-iio-common-y := hid-sensor-attributes.o | ||
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c index 6c7898c765d9..483fc379a2da 100644 --- a/drivers/iio/dac/ad5380.c +++ b/drivers/iio/dac/ad5380.c | |||
@@ -406,7 +406,11 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap, | |||
406 | goto error_free_reg; | 406 | goto error_free_reg; |
407 | } | 407 | } |
408 | 408 | ||
409 | st->vref = regulator_get_voltage(st->vref_reg); | 409 | ret = regulator_get_voltage(st->vref_reg); |
410 | if (ret < 0) | ||
411 | goto error_disable_reg; | ||
412 | |||
413 | st->vref = ret; | ||
410 | } else { | 414 | } else { |
411 | st->vref = st->chip_info->int_vref; | 415 | st->vref = st->chip_info->int_vref; |
412 | ctrl |= AD5380_CTRL_INT_VREF_EN; | 416 | ctrl |= AD5380_CTRL_INT_VREF_EN; |
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c index 29f653dab2f7..f5583aedfb59 100644 --- a/drivers/iio/dac/ad5446.c +++ b/drivers/iio/dac/ad5446.c | |||
@@ -226,7 +226,11 @@ static int ad5446_probe(struct device *dev, const char *name, | |||
226 | if (ret) | 226 | if (ret) |
227 | goto error_put_reg; | 227 | goto error_put_reg; |
228 | 228 | ||
229 | voltage_uv = regulator_get_voltage(reg); | 229 | ret = regulator_get_voltage(reg); |
230 | if (ret < 0) | ||
231 | goto error_disable_reg; | ||
232 | |||
233 | voltage_uv = ret; | ||
230 | } | 234 | } |
231 | 235 | ||
232 | indio_dev = iio_device_alloc(sizeof(*st)); | 236 | indio_dev = iio_device_alloc(sizeof(*st)); |
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c index b2a31a0468ed..0661829f2773 100644 --- a/drivers/iio/dac/ad5504.c +++ b/drivers/iio/dac/ad5504.c | |||
@@ -296,7 +296,11 @@ static int ad5504_probe(struct spi_device *spi) | |||
296 | if (ret) | 296 | if (ret) |
297 | goto error_put_reg; | 297 | goto error_put_reg; |
298 | 298 | ||
299 | voltage_uv = regulator_get_voltage(reg); | 299 | ret = regulator_get_voltage(reg); |
300 | if (ret < 0) | ||
301 | goto error_disable_reg; | ||
302 | |||
303 | voltage_uv = ret; | ||
300 | } | 304 | } |
301 | 305 | ||
302 | spi_set_drvdata(spi, indio_dev); | 306 | spi_set_drvdata(spi, indio_dev); |
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c index e9947969f9fe..f6e116627b71 100644 --- a/drivers/iio/dac/ad5624r_spi.c +++ b/drivers/iio/dac/ad5624r_spi.c | |||
@@ -238,7 +238,11 @@ static int ad5624r_probe(struct spi_device *spi) | |||
238 | if (ret) | 238 | if (ret) |
239 | goto error_put_reg; | 239 | goto error_put_reg; |
240 | 240 | ||
241 | voltage_uv = regulator_get_voltage(st->reg); | 241 | ret = regulator_get_voltage(st->reg); |
242 | if (ret < 0) | ||
243 | goto error_disable_reg; | ||
244 | |||
245 | voltage_uv = ret; | ||
242 | } | 246 | } |
243 | 247 | ||
244 | spi_set_drvdata(spi, indio_dev); | 248 | spi_set_drvdata(spi, indio_dev); |
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c index 36e51382ae52..ca9609d7a15c 100644 --- a/drivers/iio/dac/ad5686.c +++ b/drivers/iio/dac/ad5686.c | |||
@@ -332,7 +332,11 @@ static int ad5686_probe(struct spi_device *spi) | |||
332 | if (ret) | 332 | if (ret) |
333 | goto error_put_reg; | 333 | goto error_put_reg; |
334 | 334 | ||
335 | voltage_uv = regulator_get_voltage(st->reg); | 335 | ret = regulator_get_voltage(st->reg); |
336 | if (ret < 0) | ||
337 | goto error_disable_reg; | ||
338 | |||
339 | voltage_uv = ret; | ||
336 | } | 340 | } |
337 | 341 | ||
338 | st->chip_info = | 342 | st->chip_info = |
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c index c84180f23139..6407b5407ddd 100644 --- a/drivers/iio/dac/ad5791.c +++ b/drivers/iio/dac/ad5791.c | |||
@@ -365,7 +365,11 @@ static int ad5791_probe(struct spi_device *spi) | |||
365 | if (ret) | 365 | if (ret) |
366 | goto error_put_reg_pos; | 366 | goto error_put_reg_pos; |
367 | 367 | ||
368 | pos_voltage_uv = regulator_get_voltage(st->reg_vdd); | 368 | ret = regulator_get_voltage(st->reg_vdd); |
369 | if (ret < 0) | ||
370 | goto error_disable_reg_pos; | ||
371 | |||
372 | pos_voltage_uv = ret; | ||
369 | } | 373 | } |
370 | 374 | ||
371 | st->reg_vss = regulator_get(&spi->dev, "vss"); | 375 | st->reg_vss = regulator_get(&spi->dev, "vss"); |
@@ -374,7 +378,11 @@ static int ad5791_probe(struct spi_device *spi) | |||
374 | if (ret) | 378 | if (ret) |
375 | goto error_put_reg_neg; | 379 | goto error_put_reg_neg; |
376 | 380 | ||
377 | neg_voltage_uv = regulator_get_voltage(st->reg_vss); | 381 | ret = regulator_get_voltage(st->reg_vss); |
382 | if (ret < 0) | ||
383 | goto error_disable_reg_neg; | ||
384 | |||
385 | neg_voltage_uv = ret; | ||
378 | } | 386 | } |
379 | 387 | ||
380 | st->pwr_down = true; | 388 | st->pwr_down = true; |
@@ -428,6 +436,7 @@ error_put_reg_neg: | |||
428 | if (!IS_ERR(st->reg_vss)) | 436 | if (!IS_ERR(st->reg_vss)) |
429 | regulator_put(st->reg_vss); | 437 | regulator_put(st->reg_vss); |
430 | 438 | ||
439 | error_disable_reg_pos: | ||
431 | if (!IS_ERR(st->reg_vdd)) | 440 | if (!IS_ERR(st->reg_vdd)) |
432 | regulator_disable(st->reg_vdd); | 441 | regulator_disable(st->reg_vdd); |
433 | error_put_reg_pos: | 442 | error_put_reg_pos: |
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c index e5033b4cfba0..a884252ac66b 100644 --- a/drivers/iio/frequency/adf4350.c +++ b/drivers/iio/frequency/adf4350.c | |||
@@ -173,7 +173,7 @@ static int adf4350_set_freq(struct adf4350_state *st, unsigned long long freq) | |||
173 | } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); | 173 | } while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt); |
174 | } while (r_cnt == 0); | 174 | } while (r_cnt == 0); |
175 | 175 | ||
176 | tmp = freq * (u64)st->r1_mod + (st->fpfd > 1); | 176 | tmp = freq * (u64)st->r1_mod + (st->fpfd >> 1); |
177 | do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ | 177 | do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */ |
178 | st->r0_fract = do_div(tmp, st->r1_mod); | 178 | st->r0_fract = do_div(tmp, st->r1_mod); |
179 | st->r0_int = tmp; | 179 | st->r0_int = tmp; |
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig index 48ed1483ff27..96b68f63a902 100644 --- a/drivers/iio/gyro/Kconfig +++ b/drivers/iio/gyro/Kconfig | |||
@@ -17,6 +17,7 @@ config HID_SENSOR_GYRO_3D | |||
17 | select IIO_BUFFER | 17 | select IIO_BUFFER |
18 | select IIO_TRIGGERED_BUFFER | 18 | select IIO_TRIGGERED_BUFFER |
19 | select HID_SENSOR_IIO_COMMON | 19 | select HID_SENSOR_IIO_COMMON |
20 | select HID_SENSOR_IIO_TRIGGER | ||
20 | tristate "HID Gyroscope 3D" | 21 | tristate "HID Gyroscope 3D" |
21 | help | 22 | help |
22 | Say yes here to build support for the HID SENSOR | 23 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig index 1763c9bcb98a..dbf80abc834f 100644 --- a/drivers/iio/light/Kconfig +++ b/drivers/iio/light/Kconfig | |||
@@ -47,6 +47,7 @@ config HID_SENSOR_ALS | |||
47 | select IIO_BUFFER | 47 | select IIO_BUFFER |
48 | select IIO_TRIGGERED_BUFFER | 48 | select IIO_TRIGGERED_BUFFER |
49 | select HID_SENSOR_IIO_COMMON | 49 | select HID_SENSOR_IIO_COMMON |
50 | select HID_SENSOR_IIO_TRIGGER | ||
50 | tristate "HID ALS" | 51 | tristate "HID ALS" |
51 | help | 52 | help |
52 | Say yes here to build support for the HID SENSOR | 53 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig index c1f0cdd57037..ff11d68225cf 100644 --- a/drivers/iio/magnetometer/Kconfig +++ b/drivers/iio/magnetometer/Kconfig | |||
@@ -8,6 +8,7 @@ config HID_SENSOR_MAGNETOMETER_3D | |||
8 | select IIO_BUFFER | 8 | select IIO_BUFFER |
9 | select IIO_TRIGGERED_BUFFER | 9 | select IIO_TRIGGERED_BUFFER |
10 | select HID_SENSOR_IIO_COMMON | 10 | select HID_SENSOR_IIO_COMMON |
11 | select HID_SENSOR_IIO_TRIGGER | ||
11 | tristate "HID Magenetometer 3D" | 12 | tristate "HID Magenetometer 3D" |
12 | help | 13 | help |
13 | Say yes here to build support for the HID SENSOR | 14 | Say yes here to build support for the HID SENSOR |
diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index 4850d03870c2..35275099cafd 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c | |||
@@ -263,20 +263,15 @@ static void remove_qp(struct qib_ibdev *dev, struct qib_qp *qp) | |||
263 | struct qib_qp __rcu **qpp; | 263 | struct qib_qp __rcu **qpp; |
264 | 264 | ||
265 | qpp = &dev->qp_table[n]; | 265 | qpp = &dev->qp_table[n]; |
266 | q = rcu_dereference_protected(*qpp, | 266 | for (; (q = rcu_dereference_protected(*qpp, |
267 | lockdep_is_held(&dev->qpt_lock)); | 267 | lockdep_is_held(&dev->qpt_lock))) != NULL; |
268 | for (; q; qpp = &q->next) { | 268 | qpp = &q->next) |
269 | if (q == qp) { | 269 | if (q == qp) { |
270 | atomic_dec(&qp->refcount); | 270 | atomic_dec(&qp->refcount); |
271 | *qpp = qp->next; | 271 | *qpp = qp->next; |
272 | rcu_assign_pointer(qp->next, NULL); | 272 | rcu_assign_pointer(qp->next, NULL); |
273 | q = rcu_dereference_protected(*qpp, | ||
274 | lockdep_is_held(&dev->qpt_lock)); | ||
275 | break; | 273 | break; |
276 | } | 274 | } |
277 | q = rcu_dereference_protected(*qpp, | ||
278 | lockdep_is_held(&dev->qpt_lock)); | ||
279 | } | ||
280 | } | 275 | } |
281 | 276 | ||
282 | spin_unlock_irqrestore(&dev->qpt_lock, flags); | 277 | spin_unlock_irqrestore(&dev->qpt_lock, flags); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c index 03103d2bd641..67b0c1d23678 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c | |||
@@ -741,6 +741,9 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ | |||
741 | 741 | ||
742 | tx_req->mapping = addr; | 742 | tx_req->mapping = addr; |
743 | 743 | ||
744 | skb_orphan(skb); | ||
745 | skb_dst_drop(skb); | ||
746 | |||
744 | rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), | 747 | rc = post_send(priv, tx, tx->tx_head & (ipoib_sendq_size - 1), |
745 | addr, skb->len); | 748 | addr, skb->len); |
746 | if (unlikely(rc)) { | 749 | if (unlikely(rc)) { |
@@ -752,9 +755,6 @@ void ipoib_cm_send(struct net_device *dev, struct sk_buff *skb, struct ipoib_cm_ | |||
752 | dev->trans_start = jiffies; | 755 | dev->trans_start = jiffies; |
753 | ++tx->tx_head; | 756 | ++tx->tx_head; |
754 | 757 | ||
755 | skb_orphan(skb); | ||
756 | skb_dst_drop(skb); | ||
757 | |||
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); |
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c index a1bca70e20aa..2cfa76f5d99e 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c | |||
@@ -600,6 +600,9 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
600 | netif_stop_queue(dev); | 600 | netif_stop_queue(dev); |
601 | } | 601 | } |
602 | 602 | ||
603 | skb_orphan(skb); | ||
604 | skb_dst_drop(skb); | ||
605 | |||
603 | rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), | 606 | rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1), |
604 | address->ah, qpn, tx_req, phead, hlen); | 607 | address->ah, qpn, tx_req, phead, hlen); |
605 | if (unlikely(rc)) { | 608 | if (unlikely(rc)) { |
@@ -615,9 +618,6 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb, | |||
615 | 618 | ||
616 | address->last_send = priv->tx_head; | 619 | address->last_send = priv->tx_head; |
617 | ++priv->tx_head; | 620 | ++priv->tx_head; |
618 | |||
619 | skb_orphan(skb); | ||
620 | skb_dst_drop(skb); | ||
621 | } | 621 | } |
622 | 622 | ||
623 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) | 623 | if (unlikely(priv->tx_outstanding > MAX_SEND_CQE)) |
diff --git a/drivers/input/input.c b/drivers/input/input.c index ce01332f7b3a..c04469928925 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
@@ -1785,12 +1785,13 @@ static void devm_input_device_release(struct device *dev, void *res) | |||
1785 | * its driver (or binding fails). Once managed input device is allocated, | 1785 | * its driver (or binding fails). Once managed input device is allocated, |
1786 | * it is ready to be set up and registered in the same fashion as regular | 1786 | * it is ready to be set up and registered in the same fashion as regular |
1787 | * input device. There are no special devm_input_device_[un]register() | 1787 | * input device. There are no special devm_input_device_[un]register() |
1788 | * variants, regular ones work with both managed and unmanaged devices. | 1788 | * variants, regular ones work with both managed and unmanaged devices, |
1789 | * should you need them. In most cases however, managed input device need | ||
1790 | * not be explicitly unregistered or freed. | ||
1789 | * | 1791 | * |
1790 | * NOTE: the owner device is set up as parent of input device and users | 1792 | * NOTE: the owner device is set up as parent of input device and users |
1791 | * should not override it. | 1793 | * should not override it. |
1792 | */ | 1794 | */ |
1793 | |||
1794 | struct input_dev *devm_input_allocate_device(struct device *dev) | 1795 | struct input_dev *devm_input_allocate_device(struct device *dev) |
1795 | { | 1796 | { |
1796 | struct input_dev *input; | 1797 | struct input_dev *input; |
@@ -2004,6 +2005,17 @@ static void devm_input_device_unregister(struct device *dev, void *res) | |||
2004 | * Once device has been successfully registered it can be unregistered | 2005 | * Once device has been successfully registered it can be unregistered |
2005 | * with input_unregister_device(); input_free_device() should not be | 2006 | * with input_unregister_device(); input_free_device() should not be |
2006 | * called in this case. | 2007 | * called in this case. |
2008 | * | ||
2009 | * Note that this function is also used to register managed input devices | ||
2010 | * (ones allocated with devm_input_allocate_device()). Such managed input | ||
2011 | * devices need not be explicitly unregistered or freed, their tear down | ||
2012 | * is controlled by the devres infrastructure. It is also worth noting | ||
2013 | * that tear down of managed input devices is internally a 2-step process: | ||
2014 | * registered managed input device is first unregistered, but stays in | ||
2015 | * memory and can still handle input_event() calls (although events will | ||
2016 | * not be delivered anywhere). The freeing of managed input device will | ||
2017 | * happen later, when devres stack is unwound to the point where device | ||
2018 | * allocation was made. | ||
2007 | */ | 2019 | */ |
2008 | int input_register_device(struct input_dev *dev) | 2020 | int input_register_device(struct input_dev *dev) |
2009 | { | 2021 | { |
diff --git a/drivers/input/joystick/analog.c b/drivers/input/joystick/analog.c index 358cd7ee905b..7cd74e29cbc8 100644 --- a/drivers/input/joystick/analog.c +++ b/drivers/input/joystick/analog.c | |||
@@ -162,7 +162,7 @@ static unsigned int get_time_pit(void) | |||
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 "PCC" |
165 | #elif defined(CONFIG_MN10300) | 165 | #elif defined(CONFIG_MN10300) || defined(CONFIG_TILE) |
166 | #define GET_TIME(x) do { x = get_cycles(); } while (0) | 166 | #define GET_TIME(x) do { x = get_cycles(); } while (0) |
167 | #define DELTA(x, y) ((x) - (y)) | 167 | #define DELTA(x, y) ((x) - (y)) |
168 | #define TIME_NAME "TSC" | 168 | #define TIME_NAME "TSC" |
diff --git a/drivers/input/keyboard/lm8323.c b/drivers/input/keyboard/lm8323.c index 93c812662134..0de23f41b2d3 100644 --- a/drivers/input/keyboard/lm8323.c +++ b/drivers/input/keyboard/lm8323.c | |||
@@ -398,7 +398,7 @@ static irqreturn_t lm8323_irq(int irq, void *_lm) | |||
398 | lm8323_configure(lm); | 398 | lm8323_configure(lm); |
399 | } | 399 | } |
400 | for (i = 0; i < LM8323_NUM_PWMS; i++) { | 400 | for (i = 0; i < LM8323_NUM_PWMS; i++) { |
401 | if (ints & (1 << (INT_PWM1 + i))) { | 401 | if (ints & (INT_PWM1 << i)) { |
402 | dev_vdbg(&lm->client->dev, | 402 | dev_vdbg(&lm->client->dev, |
403 | "pwm%d engine completed\n", i); | 403 | "pwm%d engine completed\n", i); |
404 | pwm_done(&lm->pwm[i]); | 404 | pwm_done(&lm->pwm[i]); |
diff --git a/drivers/input/tablet/wacom_sys.c b/drivers/input/tablet/wacom_sys.c index f92d34f45a1c..aaf23aeae2ea 100644 --- a/drivers/input/tablet/wacom_sys.c +++ b/drivers/input/tablet/wacom_sys.c | |||
@@ -553,10 +553,10 @@ static int wacom_set_device_mode(struct usb_interface *intf, int report_id, int | |||
553 | if (!rep_data) | 553 | if (!rep_data) |
554 | return error; | 554 | return error; |
555 | 555 | ||
556 | rep_data[0] = report_id; | ||
557 | rep_data[1] = mode; | ||
558 | |||
559 | do { | 556 | do { |
557 | rep_data[0] = report_id; | ||
558 | rep_data[1] = mode; | ||
559 | |||
560 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, | 560 | error = wacom_set_report(intf, WAC_HID_FEATURE_REPORT, |
561 | report_id, rep_data, length, 1); | 561 | report_id, rep_data, length, 1); |
562 | if (error >= 0) | 562 | if (error >= 0) |
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c index c1c74e030a58..d33eaaf783ad 100644 --- a/drivers/iommu/amd_iommu.c +++ b/drivers/iommu/amd_iommu.c | |||
@@ -4017,10 +4017,10 @@ static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count) | |||
4017 | 4017 | ||
4018 | index -= count - 1; | 4018 | index -= count - 1; |
4019 | 4019 | ||
4020 | cfg->remapped = 1; | ||
4020 | irte_info = &cfg->irq_2_iommu; | 4021 | irte_info = &cfg->irq_2_iommu; |
4021 | irte_info->sub_handle = devid; | 4022 | irte_info->sub_handle = devid; |
4022 | irte_info->irte_index = index; | 4023 | irte_info->irte_index = index; |
4023 | irte_info->iommu = (void *)cfg; | ||
4024 | 4024 | ||
4025 | goto out; | 4025 | goto out; |
4026 | } | 4026 | } |
@@ -4127,9 +4127,9 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry, | |||
4127 | index = attr->ioapic_pin; | 4127 | index = attr->ioapic_pin; |
4128 | 4128 | ||
4129 | /* Setup IRQ remapping info */ | 4129 | /* Setup IRQ remapping info */ |
4130 | cfg->remapped = 1; | ||
4130 | irte_info->sub_handle = devid; | 4131 | irte_info->sub_handle = devid; |
4131 | irte_info->irte_index = index; | 4132 | irte_info->irte_index = index; |
4132 | irte_info->iommu = (void *)cfg; | ||
4133 | 4133 | ||
4134 | /* Setup IRTE for IOMMU */ | 4134 | /* Setup IRTE for IOMMU */ |
4135 | irte.val = 0; | 4135 | irte.val = 0; |
@@ -4288,9 +4288,9 @@ static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq, | |||
4288 | devid = get_device_id(&pdev->dev); | 4288 | devid = get_device_id(&pdev->dev); |
4289 | irte_info = &cfg->irq_2_iommu; | 4289 | irte_info = &cfg->irq_2_iommu; |
4290 | 4290 | ||
4291 | cfg->remapped = 1; | ||
4291 | irte_info->sub_handle = devid; | 4292 | irte_info->sub_handle = devid; |
4292 | irte_info->irte_index = index + offset; | 4293 | irte_info->irte_index = index + offset; |
4293 | irte_info->iommu = (void *)cfg; | ||
4294 | 4294 | ||
4295 | return 0; | 4295 | return 0; |
4296 | } | 4296 | } |
@@ -4314,9 +4314,9 @@ static int setup_hpet_msi(unsigned int irq, unsigned int id) | |||
4314 | if (index < 0) | 4314 | if (index < 0) |
4315 | return index; | 4315 | return index; |
4316 | 4316 | ||
4317 | cfg->remapped = 1; | ||
4317 | irte_info->sub_handle = devid; | 4318 | irte_info->sub_handle = devid; |
4318 | irte_info->irte_index = index; | 4319 | irte_info->irte_index = index; |
4319 | irte_info->iommu = (void *)cfg; | ||
4320 | 4320 | ||
4321 | return 0; | 4321 | return 0; |
4322 | } | 4322 | } |
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c index 81837b0710a9..faf10ba1ed9a 100644 --- a/drivers/iommu/amd_iommu_init.c +++ b/drivers/iommu/amd_iommu_init.c | |||
@@ -975,6 +975,38 @@ static void __init free_iommu_all(void) | |||
975 | } | 975 | } |
976 | 976 | ||
977 | /* | 977 | /* |
978 | * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations) | ||
979 | * Workaround: | ||
980 | * BIOS should disable L2B micellaneous clock gating by setting | ||
981 | * L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b | ||
982 | */ | ||
983 | static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu) | ||
984 | { | ||
985 | u32 value; | ||
986 | |||
987 | if ((boot_cpu_data.x86 != 0x15) || | ||
988 | (boot_cpu_data.x86_model < 0x10) || | ||
989 | (boot_cpu_data.x86_model > 0x1f)) | ||
990 | return; | ||
991 | |||
992 | pci_write_config_dword(iommu->dev, 0xf0, 0x90); | ||
993 | pci_read_config_dword(iommu->dev, 0xf4, &value); | ||
994 | |||
995 | if (value & BIT(2)) | ||
996 | return; | ||
997 | |||
998 | /* Select NB indirect register 0x90 and enable writing */ | ||
999 | pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8)); | ||
1000 | |||
1001 | pci_write_config_dword(iommu->dev, 0xf4, value | 0x4); | ||
1002 | pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n", | ||
1003 | dev_name(&iommu->dev->dev)); | ||
1004 | |||
1005 | /* Clear the enable writing bit */ | ||
1006 | pci_write_config_dword(iommu->dev, 0xf0, 0x90); | ||
1007 | } | ||
1008 | |||
1009 | /* | ||
978 | * This function clues the initialization function for one IOMMU | 1010 | * This function clues the initialization function for one IOMMU |
979 | * together and also allocates the command buffer and programs the | 1011 | * together and also allocates the command buffer and programs the |
980 | * hardware. It does NOT enable the IOMMU. This is done afterwards. | 1012 | * hardware. It does NOT enable the IOMMU. This is done afterwards. |
@@ -1172,6 +1204,8 @@ static int iommu_init_pci(struct amd_iommu *iommu) | |||
1172 | iommu->stored_l2[i] = iommu_read_l2(iommu, i); | 1204 | iommu->stored_l2[i] = iommu_read_l2(iommu, i); |
1173 | } | 1205 | } |
1174 | 1206 | ||
1207 | amd_iommu_erratum_746_workaround(iommu); | ||
1208 | |||
1175 | return pci_enable_device(iommu->dev); | 1209 | return pci_enable_device(iommu->dev); |
1176 | } | 1210 | } |
1177 | 1211 | ||
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 86e2f4a62b9a..174bb654453d 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -41,6 +41,8 @@ | |||
41 | #include <asm/irq_remapping.h> | 41 | #include <asm/irq_remapping.h> |
42 | #include <asm/iommu_table.h> | 42 | #include <asm/iommu_table.h> |
43 | 43 | ||
44 | #include "irq_remapping.h" | ||
45 | |||
44 | /* No locks are needed as DMA remapping hardware unit | 46 | /* No locks are needed as DMA remapping hardware unit |
45 | * list is constructed at boot time and hotplug of | 47 | * list is constructed at boot time and hotplug of |
46 | * these units are not supported by the architecture. | 48 | * these units are not supported by the architecture. |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index b9d091157884..43d5c8b8e7ad 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -46,6 +46,8 @@ | |||
46 | #include <asm/cacheflush.h> | 46 | #include <asm/cacheflush.h> |
47 | #include <asm/iommu.h> | 47 | #include <asm/iommu.h> |
48 | 48 | ||
49 | #include "irq_remapping.h" | ||
50 | |||
49 | #define ROOT_SIZE VTD_PAGE_SIZE | 51 | #define ROOT_SIZE VTD_PAGE_SIZE |
50 | #define CONTEXT_SIZE VTD_PAGE_SIZE | 52 | #define CONTEXT_SIZE VTD_PAGE_SIZE |
51 | 53 | ||
@@ -4234,6 +4236,21 @@ static struct iommu_ops intel_iommu_ops = { | |||
4234 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, | 4236 | .pgsize_bitmap = INTEL_IOMMU_PGSIZES, |
4235 | }; | 4237 | }; |
4236 | 4238 | ||
4239 | static void quirk_iommu_g4x_gfx(struct pci_dev *dev) | ||
4240 | { | ||
4241 | /* G4x/GM45 integrated gfx dmar support is totally busted. */ | ||
4242 | printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); | ||
4243 | dmar_map_gfx = 0; | ||
4244 | } | ||
4245 | |||
4246 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx); | ||
4247 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx); | ||
4248 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx); | ||
4249 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx); | ||
4250 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx); | ||
4251 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx); | ||
4252 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx); | ||
4253 | |||
4237 | static void quirk_iommu_rwbf(struct pci_dev *dev) | 4254 | static void quirk_iommu_rwbf(struct pci_dev *dev) |
4238 | { | 4255 | { |
4239 | /* | 4256 | /* |
@@ -4242,12 +4259,6 @@ static void quirk_iommu_rwbf(struct pci_dev *dev) | |||
4242 | */ | 4259 | */ |
4243 | printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); | 4260 | printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n"); |
4244 | rwbf_quirk = 1; | 4261 | rwbf_quirk = 1; |
4245 | |||
4246 | /* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */ | ||
4247 | if (dev->revision == 0x07) { | ||
4248 | printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n"); | ||
4249 | dmar_map_gfx = 0; | ||
4250 | } | ||
4251 | } | 4262 | } |
4252 | 4263 | ||
4253 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); | 4264 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf); |
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index af8904de1d44..f3b8f23b5d8f 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c | |||
@@ -68,6 +68,7 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
68 | { | 68 | { |
69 | struct ir_table *table = iommu->ir_table; | 69 | struct ir_table *table = iommu->ir_table; |
70 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); | 70 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
71 | struct irq_cfg *cfg = irq_get_chip_data(irq); | ||
71 | u16 index, start_index; | 72 | u16 index, start_index; |
72 | unsigned int mask = 0; | 73 | unsigned int mask = 0; |
73 | unsigned long flags; | 74 | unsigned long flags; |
@@ -115,6 +116,7 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) | |||
115 | for (i = index; i < index + count; i++) | 116 | for (i = index; i < index + count; i++) |
116 | table->base[i].present = 1; | 117 | table->base[i].present = 1; |
117 | 118 | ||
119 | cfg->remapped = 1; | ||
118 | irq_iommu->iommu = iommu; | 120 | irq_iommu->iommu = iommu; |
119 | irq_iommu->irte_index = index; | 121 | irq_iommu->irte_index = index; |
120 | irq_iommu->sub_handle = 0; | 122 | irq_iommu->sub_handle = 0; |
@@ -155,6 +157,7 @@ static int map_irq_to_irte_handle(int irq, u16 *sub_handle) | |||
155 | static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) | 157 | static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) |
156 | { | 158 | { |
157 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); | 159 | struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); |
160 | struct irq_cfg *cfg = irq_get_chip_data(irq); | ||
158 | unsigned long flags; | 161 | unsigned long flags; |
159 | 162 | ||
160 | if (!irq_iommu) | 163 | if (!irq_iommu) |
@@ -162,6 +165,7 @@ static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subha | |||
162 | 165 | ||
163 | raw_spin_lock_irqsave(&irq_2_ir_lock, flags); | 166 | raw_spin_lock_irqsave(&irq_2_ir_lock, flags); |
164 | 167 | ||
168 | cfg->remapped = 1; | ||
165 | irq_iommu->iommu = iommu; | 169 | irq_iommu->iommu = iommu; |
166 | irq_iommu->irte_index = index; | 170 | irq_iommu->irte_index = index; |
167 | irq_iommu->sub_handle = subhandle; | 171 | irq_iommu->sub_handle = subhandle; |
@@ -425,11 +429,22 @@ static void iommu_set_irq_remapping(struct intel_iommu *iommu, int mode) | |||
425 | 429 | ||
426 | /* Enable interrupt-remapping */ | 430 | /* Enable interrupt-remapping */ |
427 | iommu->gcmd |= DMA_GCMD_IRE; | 431 | iommu->gcmd |= DMA_GCMD_IRE; |
432 | iommu->gcmd &= ~DMA_GCMD_CFI; /* Block compatibility-format MSIs */ | ||
428 | writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG); | 433 | writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG); |
429 | 434 | ||
430 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, | 435 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, |
431 | readl, (sts & DMA_GSTS_IRES), sts); | 436 | readl, (sts & DMA_GSTS_IRES), sts); |
432 | 437 | ||
438 | /* | ||
439 | * With CFI clear in the Global Command register, we should be | ||
440 | * protected from dangerous (i.e. compatibility) interrupts | ||
441 | * regardless of x2apic status. Check just to be sure. | ||
442 | */ | ||
443 | if (sts & DMA_GSTS_CFIS) | ||
444 | WARN(1, KERN_WARNING | ||
445 | "Compatibility-format IRQs enabled despite intr remapping;\n" | ||
446 | "you are vulnerable to IRQ injection.\n"); | ||
447 | |||
433 | raw_spin_unlock_irqrestore(&iommu->register_lock, flags); | 448 | raw_spin_unlock_irqrestore(&iommu->register_lock, flags); |
434 | } | 449 | } |
435 | 450 | ||
@@ -526,20 +541,24 @@ static int __init intel_irq_remapping_supported(void) | |||
526 | static int __init intel_enable_irq_remapping(void) | 541 | static int __init intel_enable_irq_remapping(void) |
527 | { | 542 | { |
528 | struct dmar_drhd_unit *drhd; | 543 | struct dmar_drhd_unit *drhd; |
544 | bool x2apic_present; | ||
529 | int setup = 0; | 545 | int setup = 0; |
530 | int eim = 0; | 546 | int eim = 0; |
531 | 547 | ||
548 | x2apic_present = x2apic_supported(); | ||
549 | |||
532 | if (parse_ioapics_under_ir() != 1) { | 550 | if (parse_ioapics_under_ir() != 1) { |
533 | printk(KERN_INFO "Not enable interrupt remapping\n"); | 551 | printk(KERN_INFO "Not enable interrupt remapping\n"); |
534 | return -1; | 552 | goto error; |
535 | } | 553 | } |
536 | 554 | ||
537 | if (x2apic_supported()) { | 555 | if (x2apic_present) { |
538 | eim = !dmar_x2apic_optout(); | 556 | eim = !dmar_x2apic_optout(); |
539 | WARN(!eim, KERN_WARNING | 557 | if (!eim) |
540 | "Your BIOS is broken and requested that x2apic be disabled\n" | 558 | printk(KERN_WARNING |
541 | "This will leave your machine vulnerable to irq-injection attacks\n" | 559 | "Your BIOS is broken and requested that x2apic be disabled.\n" |
542 | "Use 'intremap=no_x2apic_optout' to override BIOS request\n"); | 560 | "This will slightly decrease performance.\n" |
561 | "Use 'intremap=no_x2apic_optout' to override BIOS request.\n"); | ||
543 | } | 562 | } |
544 | 563 | ||
545 | for_each_drhd_unit(drhd) { | 564 | for_each_drhd_unit(drhd) { |
@@ -578,7 +597,7 @@ static int __init intel_enable_irq_remapping(void) | |||
578 | if (eim && !ecap_eim_support(iommu->ecap)) { | 597 | if (eim && !ecap_eim_support(iommu->ecap)) { |
579 | printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " | 598 | printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " |
580 | " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); | 599 | " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); |
581 | return -1; | 600 | goto error; |
582 | } | 601 | } |
583 | } | 602 | } |
584 | 603 | ||
@@ -594,7 +613,7 @@ static int __init intel_enable_irq_remapping(void) | |||
594 | printk(KERN_ERR "DRHD %Lx: failed to enable queued, " | 613 | printk(KERN_ERR "DRHD %Lx: failed to enable queued, " |
595 | " invalidation, ecap %Lx, ret %d\n", | 614 | " invalidation, ecap %Lx, ret %d\n", |
596 | drhd->reg_base_addr, iommu->ecap, ret); | 615 | drhd->reg_base_addr, iommu->ecap, ret); |
597 | return -1; | 616 | goto error; |
598 | } | 617 | } |
599 | } | 618 | } |
600 | 619 | ||
@@ -617,6 +636,14 @@ static int __init intel_enable_irq_remapping(void) | |||
617 | goto error; | 636 | goto error; |
618 | 637 | ||
619 | irq_remapping_enabled = 1; | 638 | irq_remapping_enabled = 1; |
639 | |||
640 | /* | ||
641 | * VT-d has a different layout for IO-APIC entries when | ||
642 | * interrupt remapping is enabled. So it needs a special routine | ||
643 | * to print IO-APIC entries for debugging purposes too. | ||
644 | */ | ||
645 | x86_io_apic_ops.print_entries = intel_ir_io_apic_print_entries; | ||
646 | |||
620 | pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic"); | 647 | pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic"); |
621 | 648 | ||
622 | return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; | 649 | return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; |
@@ -625,6 +652,11 @@ error: | |||
625 | /* | 652 | /* |
626 | * handle error condition gracefully here! | 653 | * handle error condition gracefully here! |
627 | */ | 654 | */ |
655 | |||
656 | if (x2apic_present) | ||
657 | WARN(1, KERN_WARNING | ||
658 | "Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n"); | ||
659 | |||
628 | return -1; | 660 | return -1; |
629 | } | 661 | } |
630 | 662 | ||
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c index faf85d6e33fe..d56f8c17c5fe 100644 --- a/drivers/iommu/irq_remapping.c +++ b/drivers/iommu/irq_remapping.c | |||
@@ -1,11 +1,18 @@ | |||
1 | #include <linux/seq_file.h> | ||
2 | #include <linux/cpumask.h> | ||
1 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
2 | #include <linux/string.h> | 4 | #include <linux/string.h> |
3 | #include <linux/cpumask.h> | 5 | #include <linux/cpumask.h> |
4 | #include <linux/errno.h> | 6 | #include <linux/errno.h> |
5 | #include <linux/msi.h> | 7 | #include <linux/msi.h> |
8 | #include <linux/irq.h> | ||
9 | #include <linux/pci.h> | ||
6 | 10 | ||
7 | #include <asm/hw_irq.h> | 11 | #include <asm/hw_irq.h> |
8 | #include <asm/irq_remapping.h> | 12 | #include <asm/irq_remapping.h> |
13 | #include <asm/processor.h> | ||
14 | #include <asm/x86_init.h> | ||
15 | #include <asm/apic.h> | ||
9 | 16 | ||
10 | #include "irq_remapping.h" | 17 | #include "irq_remapping.h" |
11 | 18 | ||
@@ -17,6 +24,152 @@ int no_x2apic_optout; | |||
17 | 24 | ||
18 | static struct irq_remap_ops *remap_ops; | 25 | static struct irq_remap_ops *remap_ops; |
19 | 26 | ||
27 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); | ||
28 | static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, | ||
29 | int index, int sub_handle); | ||
30 | static int set_remapped_irq_affinity(struct irq_data *data, | ||
31 | const struct cpumask *mask, | ||
32 | bool force); | ||
33 | |||
34 | static bool irq_remapped(struct irq_cfg *cfg) | ||
35 | { | ||
36 | return (cfg->remapped == 1); | ||
37 | } | ||
38 | |||
39 | static void irq_remapping_disable_io_apic(void) | ||
40 | { | ||
41 | /* | ||
42 | * With interrupt-remapping, for now we will use virtual wire A | ||
43 | * mode, as virtual wire B is little complex (need to configure | ||
44 | * both IOAPIC RTE as well as interrupt-remapping table entry). | ||
45 | * As this gets called during crash dump, keep this simple for | ||
46 | * now. | ||
47 | */ | ||
48 | if (cpu_has_apic || apic_from_smp_config()) | ||
49 | disconnect_bsp_APIC(0); | ||
50 | } | ||
51 | |||
52 | static int do_setup_msi_irqs(struct pci_dev *dev, int nvec) | ||
53 | { | ||
54 | int node, ret, sub_handle, index = 0; | ||
55 | unsigned int irq; | ||
56 | struct msi_desc *msidesc; | ||
57 | |||
58 | nvec = __roundup_pow_of_two(nvec); | ||
59 | |||
60 | WARN_ON(!list_is_singular(&dev->msi_list)); | ||
61 | msidesc = list_entry(dev->msi_list.next, struct msi_desc, list); | ||
62 | WARN_ON(msidesc->irq); | ||
63 | WARN_ON(msidesc->msi_attrib.multiple); | ||
64 | |||
65 | node = dev_to_node(&dev->dev); | ||
66 | irq = __create_irqs(get_nr_irqs_gsi(), nvec, node); | ||
67 | if (irq == 0) | ||
68 | return -ENOSPC; | ||
69 | |||
70 | msidesc->msi_attrib.multiple = ilog2(nvec); | ||
71 | for (sub_handle = 0; sub_handle < nvec; sub_handle++) { | ||
72 | if (!sub_handle) { | ||
73 | index = msi_alloc_remapped_irq(dev, irq, nvec); | ||
74 | if (index < 0) { | ||
75 | ret = index; | ||
76 | goto error; | ||
77 | } | ||
78 | } else { | ||
79 | ret = msi_setup_remapped_irq(dev, irq + sub_handle, | ||
80 | index, sub_handle); | ||
81 | if (ret < 0) | ||
82 | goto error; | ||
83 | } | ||
84 | ret = setup_msi_irq(dev, msidesc, irq, sub_handle); | ||
85 | if (ret < 0) | ||
86 | goto error; | ||
87 | } | ||
88 | return 0; | ||
89 | |||
90 | error: | ||
91 | destroy_irqs(irq, nvec); | ||
92 | |||
93 | /* | ||
94 | * Restore altered MSI descriptor fields and prevent just destroyed | ||
95 | * IRQs from tearing down again in default_teardown_msi_irqs() | ||
96 | */ | ||
97 | msidesc->irq = 0; | ||
98 | msidesc->msi_attrib.multiple = 0; | ||
99 | |||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | static int do_setup_msix_irqs(struct pci_dev *dev, int nvec) | ||
104 | { | ||
105 | int node, ret, sub_handle, index = 0; | ||
106 | struct msi_desc *msidesc; | ||
107 | unsigned int irq; | ||
108 | |||
109 | node = dev_to_node(&dev->dev); | ||
110 | irq = get_nr_irqs_gsi(); | ||
111 | sub_handle = 0; | ||
112 | |||
113 | list_for_each_entry(msidesc, &dev->msi_list, list) { | ||
114 | |||
115 | irq = create_irq_nr(irq, node); | ||
116 | if (irq == 0) | ||
117 | return -1; | ||
118 | |||
119 | if (sub_handle == 0) | ||
120 | ret = index = msi_alloc_remapped_irq(dev, irq, nvec); | ||
121 | else | ||
122 | ret = msi_setup_remapped_irq(dev, irq, index, sub_handle); | ||
123 | |||
124 | if (ret < 0) | ||
125 | goto error; | ||
126 | |||
127 | ret = setup_msi_irq(dev, msidesc, irq, 0); | ||
128 | if (ret < 0) | ||
129 | goto error; | ||
130 | |||
131 | sub_handle += 1; | ||
132 | irq += 1; | ||
133 | } | ||
134 | |||
135 | return 0; | ||
136 | |||
137 | error: | ||
138 | destroy_irq(irq); | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | static int irq_remapping_setup_msi_irqs(struct pci_dev *dev, | ||
143 | int nvec, int type) | ||
144 | { | ||
145 | if (type == PCI_CAP_ID_MSI) | ||
146 | return do_setup_msi_irqs(dev, nvec); | ||
147 | else | ||
148 | return do_setup_msix_irqs(dev, nvec); | ||
149 | } | ||
150 | |||
151 | void eoi_ioapic_pin_remapped(int apic, int pin, int vector) | ||
152 | { | ||
153 | /* | ||
154 | * Intr-remapping uses pin number as the virtual vector | ||
155 | * in the RTE. Actual vector is programmed in | ||
156 | * intr-remapping table entry. Hence for the io-apic | ||
157 | * EOI we use the pin number. | ||
158 | */ | ||
159 | io_apic_eoi(apic, pin); | ||
160 | } | ||
161 | |||
162 | static void __init irq_remapping_modify_x86_ops(void) | ||
163 | { | ||
164 | x86_io_apic_ops.disable = irq_remapping_disable_io_apic; | ||
165 | x86_io_apic_ops.set_affinity = set_remapped_irq_affinity; | ||
166 | x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry; | ||
167 | x86_io_apic_ops.eoi_ioapic_pin = eoi_ioapic_pin_remapped; | ||
168 | x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs; | ||
169 | x86_msi.setup_hpet_msi = setup_hpet_msi_remapped; | ||
170 | x86_msi.compose_msi_msg = compose_remapped_msi_msg; | ||
171 | } | ||
172 | |||
20 | static __init int setup_nointremap(char *str) | 173 | static __init int setup_nointremap(char *str) |
21 | { | 174 | { |
22 | disable_irq_remap = 1; | 175 | disable_irq_remap = 1; |
@@ -79,15 +232,24 @@ int __init irq_remapping_prepare(void) | |||
79 | 232 | ||
80 | int __init irq_remapping_enable(void) | 233 | int __init irq_remapping_enable(void) |
81 | { | 234 | { |
235 | int ret; | ||
236 | |||
82 | if (!remap_ops || !remap_ops->enable) | 237 | if (!remap_ops || !remap_ops->enable) |
83 | return -ENODEV; | 238 | return -ENODEV; |
84 | 239 | ||
85 | return remap_ops->enable(); | 240 | ret = remap_ops->enable(); |
241 | |||
242 | if (irq_remapping_enabled) | ||
243 | irq_remapping_modify_x86_ops(); | ||
244 | |||
245 | return ret; | ||
86 | } | 246 | } |
87 | 247 | ||
88 | void irq_remapping_disable(void) | 248 | void irq_remapping_disable(void) |
89 | { | 249 | { |
90 | if (!remap_ops || !remap_ops->disable) | 250 | if (!irq_remapping_enabled || |
251 | !remap_ops || | ||
252 | !remap_ops->disable) | ||
91 | return; | 253 | return; |
92 | 254 | ||
93 | remap_ops->disable(); | 255 | remap_ops->disable(); |
@@ -95,7 +257,9 @@ void irq_remapping_disable(void) | |||
95 | 257 | ||
96 | int irq_remapping_reenable(int mode) | 258 | int irq_remapping_reenable(int mode) |
97 | { | 259 | { |
98 | if (!remap_ops || !remap_ops->reenable) | 260 | if (!irq_remapping_enabled || |
261 | !remap_ops || | ||
262 | !remap_ops->reenable) | ||
99 | return 0; | 263 | return 0; |
100 | 264 | ||
101 | return remap_ops->reenable(mode); | 265 | return remap_ops->reenable(mode); |
@@ -103,6 +267,9 @@ int irq_remapping_reenable(int mode) | |||
103 | 267 | ||
104 | int __init irq_remap_enable_fault_handling(void) | 268 | int __init irq_remap_enable_fault_handling(void) |
105 | { | 269 | { |
270 | if (!irq_remapping_enabled) | ||
271 | return 0; | ||
272 | |||
106 | if (!remap_ops || !remap_ops->enable_faulting) | 273 | if (!remap_ops || !remap_ops->enable_faulting) |
107 | return -ENODEV; | 274 | return -ENODEV; |
108 | 275 | ||
@@ -133,23 +300,28 @@ int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask, | |||
133 | 300 | ||
134 | void free_remapped_irq(int irq) | 301 | void free_remapped_irq(int irq) |
135 | { | 302 | { |
303 | struct irq_cfg *cfg = irq_get_chip_data(irq); | ||
304 | |||
136 | if (!remap_ops || !remap_ops->free_irq) | 305 | if (!remap_ops || !remap_ops->free_irq) |
137 | return; | 306 | return; |
138 | 307 | ||
139 | remap_ops->free_irq(irq); | 308 | if (irq_remapped(cfg)) |
309 | remap_ops->free_irq(irq); | ||
140 | } | 310 | } |
141 | 311 | ||
142 | void compose_remapped_msi_msg(struct pci_dev *pdev, | 312 | void compose_remapped_msi_msg(struct pci_dev *pdev, |
143 | unsigned int irq, unsigned int dest, | 313 | unsigned int irq, unsigned int dest, |
144 | struct msi_msg *msg, u8 hpet_id) | 314 | struct msi_msg *msg, u8 hpet_id) |
145 | { | 315 | { |
146 | if (!remap_ops || !remap_ops->compose_msi_msg) | 316 | struct irq_cfg *cfg = irq_get_chip_data(irq); |
147 | return; | ||
148 | 317 | ||
149 | remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); | 318 | if (!irq_remapped(cfg)) |
319 | native_compose_msi_msg(pdev, irq, dest, msg, hpet_id); | ||
320 | else if (remap_ops && remap_ops->compose_msi_msg) | ||
321 | remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); | ||
150 | } | 322 | } |
151 | 323 | ||
152 | int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) | 324 | static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) |
153 | { | 325 | { |
154 | if (!remap_ops || !remap_ops->msi_alloc_irq) | 326 | if (!remap_ops || !remap_ops->msi_alloc_irq) |
155 | return -ENODEV; | 327 | return -ENODEV; |
@@ -157,8 +329,8 @@ int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) | |||
157 | return remap_ops->msi_alloc_irq(pdev, irq, nvec); | 329 | return remap_ops->msi_alloc_irq(pdev, irq, nvec); |
158 | } | 330 | } |
159 | 331 | ||
160 | int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, | 332 | static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, |
161 | int index, int sub_handle) | 333 | int index, int sub_handle) |
162 | { | 334 | { |
163 | if (!remap_ops || !remap_ops->msi_setup_irq) | 335 | if (!remap_ops || !remap_ops->msi_setup_irq) |
164 | return -ENODEV; | 336 | return -ENODEV; |
@@ -173,3 +345,42 @@ int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) | |||
173 | 345 | ||
174 | return remap_ops->setup_hpet_msi(irq, id); | 346 | return remap_ops->setup_hpet_msi(irq, id); |
175 | } | 347 | } |
348 | |||
349 | void panic_if_irq_remap(const char *msg) | ||
350 | { | ||
351 | if (irq_remapping_enabled) | ||
352 | panic(msg); | ||
353 | } | ||
354 | |||
355 | static void ir_ack_apic_edge(struct irq_data *data) | ||
356 | { | ||
357 | ack_APIC_irq(); | ||
358 | } | ||
359 | |||
360 | static void ir_ack_apic_level(struct irq_data *data) | ||
361 | { | ||
362 | ack_APIC_irq(); | ||
363 | eoi_ioapic_irq(data->irq, data->chip_data); | ||
364 | } | ||
365 | |||
366 | static void ir_print_prefix(struct irq_data *data, struct seq_file *p) | ||
367 | { | ||
368 | seq_printf(p, " IR-%s", data->chip->name); | ||
369 | } | ||
370 | |||
371 | void irq_remap_modify_chip_defaults(struct irq_chip *chip) | ||
372 | { | ||
373 | chip->irq_print_chip = ir_print_prefix; | ||
374 | chip->irq_ack = ir_ack_apic_edge; | ||
375 | chip->irq_eoi = ir_ack_apic_level; | ||
376 | chip->irq_set_affinity = x86_io_apic_ops.set_affinity; | ||
377 | } | ||
378 | |||
379 | bool setup_remapped_irq(int irq, struct irq_cfg *cfg, struct irq_chip *chip) | ||
380 | { | ||
381 | if (!irq_remapped(cfg)) | ||
382 | return false; | ||
383 | irq_set_status_flags(irq, IRQ_MOVE_PCNTXT); | ||
384 | irq_remap_modify_chip_defaults(chip); | ||
385 | return true; | ||
386 | } | ||
diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h index 95363acb583f..ecb637670405 100644 --- a/drivers/iommu/irq_remapping.h +++ b/drivers/iommu/irq_remapping.h | |||
@@ -34,6 +34,7 @@ struct msi_msg; | |||
34 | extern int disable_irq_remap; | 34 | extern int disable_irq_remap; |
35 | extern int disable_sourceid_checking; | 35 | extern int disable_sourceid_checking; |
36 | extern int no_x2apic_optout; | 36 | extern int no_x2apic_optout; |
37 | extern int irq_remapping_enabled; | ||
37 | 38 | ||
38 | struct irq_remap_ops { | 39 | struct irq_remap_ops { |
39 | /* Check whether Interrupt Remapping is supported */ | 40 | /* Check whether Interrupt Remapping is supported */ |
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c index 68452b768da2..03a0a01a4054 100644 --- a/drivers/isdn/gigaset/capi.c +++ b/drivers/isdn/gigaset/capi.c | |||
@@ -248,6 +248,8 @@ static inline void dump_rawmsg(enum debuglevel level, const char *tag, | |||
248 | CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, | 248 | CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l, |
249 | CAPIMSG_CONTROL(data)); | 249 | CAPIMSG_CONTROL(data)); |
250 | l -= 12; | 250 | l -= 12; |
251 | if (l <= 0) | ||
252 | return; | ||
251 | dbgline = kmalloc(3 * l, GFP_ATOMIC); | 253 | dbgline = kmalloc(3 * l, GFP_ATOMIC); |
252 | if (!dbgline) | 254 | if (!dbgline) |
253 | return; | 255 | return; |
diff --git a/drivers/isdn/mISDN/stack.c b/drivers/isdn/mISDN/stack.c index 5f21f629b7ae..deda591f70b9 100644 --- a/drivers/isdn/mISDN/stack.c +++ b/drivers/isdn/mISDN/stack.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/mISDNif.h> | 19 | #include <linux/mISDNif.h> |
20 | #include <linux/kthread.h> | 20 | #include <linux/kthread.h> |
21 | #include <linux/sched.h> | ||
21 | #include "core.h" | 22 | #include "core.h" |
22 | 23 | ||
23 | static u_int *debug; | 24 | static u_int *debug; |
@@ -202,6 +203,9 @@ static int | |||
202 | mISDNStackd(void *data) | 203 | mISDNStackd(void *data) |
203 | { | 204 | { |
204 | struct mISDNstack *st = data; | 205 | struct mISDNstack *st = data; |
206 | #ifdef MISDN_MSG_STATS | ||
207 | cputime_t utime, stime; | ||
208 | #endif | ||
205 | int err = 0; | 209 | int err = 0; |
206 | 210 | ||
207 | sigfillset(¤t->blocked); | 211 | sigfillset(¤t->blocked); |
@@ -303,9 +307,10 @@ mISDNStackd(void *data) | |||
303 | "msg %d sleep %d stopped\n", | 307 | "msg %d sleep %d stopped\n", |
304 | dev_name(&st->dev->dev), st->msg_cnt, st->sleep_cnt, | 308 | dev_name(&st->dev->dev), st->msg_cnt, st->sleep_cnt, |
305 | st->stopped_cnt); | 309 | st->stopped_cnt); |
310 | task_cputime(st->thread, &utime, &stime); | ||
306 | printk(KERN_DEBUG | 311 | printk(KERN_DEBUG |
307 | "mISDNStackd daemon for %s utime(%ld) stime(%ld)\n", | 312 | "mISDNStackd daemon for %s utime(%ld) stime(%ld)\n", |
308 | dev_name(&st->dev->dev), st->thread->utime, st->thread->stime); | 313 | dev_name(&st->dev->dev), utime, stime); |
309 | printk(KERN_DEBUG | 314 | printk(KERN_DEBUG |
310 | "mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n", | 315 | "mISDNStackd daemon for %s nvcsw(%ld) nivcsw(%ld)\n", |
311 | dev_name(&st->dev->dev), st->thread->nvcsw, st->thread->nivcsw); | 316 | dev_name(&st->dev->dev), st->thread->nvcsw, st->thread->nivcsw); |
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 3d8984edeff7..9e58dbd8d8cb 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -340,24 +340,22 @@ static int validate_region_size(struct raid_set *rs, unsigned long region_size) | |||
340 | } | 340 | } |
341 | 341 | ||
342 | /* | 342 | /* |
343 | * validate_rebuild_devices | 343 | * validate_raid_redundancy |
344 | * @rs | 344 | * @rs |
345 | * | 345 | * |
346 | * Determine if the devices specified for rebuild can result in a valid | 346 | * Determine if there are enough devices in the array that haven't |
347 | * usable array that is capable of rebuilding the given devices. | 347 | * failed (or are being rebuilt) to form a usable array. |
348 | * | 348 | * |
349 | * Returns: 0 on success, -EINVAL on failure. | 349 | * Returns: 0 on success, -EINVAL on failure. |
350 | */ | 350 | */ |
351 | static int validate_rebuild_devices(struct raid_set *rs) | 351 | static int validate_raid_redundancy(struct raid_set *rs) |
352 | { | 352 | { |
353 | unsigned i, rebuild_cnt = 0; | 353 | unsigned i, rebuild_cnt = 0; |
354 | unsigned rebuilds_per_group, copies, d; | 354 | unsigned rebuilds_per_group, copies, d; |
355 | 355 | ||
356 | if (!(rs->print_flags & DMPF_REBUILD)) | ||
357 | return 0; | ||
358 | |||
359 | for (i = 0; i < rs->md.raid_disks; i++) | 356 | for (i = 0; i < rs->md.raid_disks; i++) |
360 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags)) | 357 | if (!test_bit(In_sync, &rs->dev[i].rdev.flags) || |
358 | !rs->dev[i].rdev.sb_page) | ||
361 | rebuild_cnt++; | 359 | rebuild_cnt++; |
362 | 360 | ||
363 | switch (rs->raid_type->level) { | 361 | switch (rs->raid_type->level) { |
@@ -393,27 +391,24 @@ static int validate_rebuild_devices(struct raid_set *rs) | |||
393 | * A A B B C | 391 | * A A B B C |
394 | * C D D E E | 392 | * C D D E E |
395 | */ | 393 | */ |
396 | rebuilds_per_group = 0; | ||
397 | for (i = 0; i < rs->md.raid_disks * copies; i++) { | 394 | for (i = 0; i < rs->md.raid_disks * copies; i++) { |
395 | if (!(i % copies)) | ||
396 | rebuilds_per_group = 0; | ||
398 | d = i % rs->md.raid_disks; | 397 | d = i % rs->md.raid_disks; |
399 | if (!test_bit(In_sync, &rs->dev[d].rdev.flags) && | 398 | if ((!rs->dev[d].rdev.sb_page || |
399 | !test_bit(In_sync, &rs->dev[d].rdev.flags)) && | ||
400 | (++rebuilds_per_group >= copies)) | 400 | (++rebuilds_per_group >= copies)) |
401 | goto too_many; | 401 | goto too_many; |
402 | if (!((i + 1) % copies)) | ||
403 | rebuilds_per_group = 0; | ||
404 | } | 402 | } |
405 | break; | 403 | break; |
406 | default: | 404 | default: |
407 | DMERR("The rebuild parameter is not supported for %s", | 405 | if (rebuild_cnt) |
408 | rs->raid_type->name); | 406 | return -EINVAL; |
409 | rs->ti->error = "Rebuild not supported for this RAID type"; | ||
410 | return -EINVAL; | ||
411 | } | 407 | } |
412 | 408 | ||
413 | return 0; | 409 | return 0; |
414 | 410 | ||
415 | too_many: | 411 | too_many: |
416 | rs->ti->error = "Too many rebuild devices specified"; | ||
417 | return -EINVAL; | 412 | return -EINVAL; |
418 | } | 413 | } |
419 | 414 | ||
@@ -664,9 +659,6 @@ static int parse_raid_params(struct raid_set *rs, char **argv, | |||
664 | } | 659 | } |
665 | rs->md.dev_sectors = sectors_per_dev; | 660 | rs->md.dev_sectors = sectors_per_dev; |
666 | 661 | ||
667 | if (validate_rebuild_devices(rs)) | ||
668 | return -EINVAL; | ||
669 | |||
670 | /* Assume there are no metadata devices until the drives are parsed */ | 662 | /* Assume there are no metadata devices until the drives are parsed */ |
671 | rs->md.persistent = 0; | 663 | rs->md.persistent = 0; |
672 | rs->md.external = 1; | 664 | rs->md.external = 1; |
@@ -995,28 +987,10 @@ static int super_validate(struct mddev *mddev, struct md_rdev *rdev) | |||
995 | static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) | 987 | static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) |
996 | { | 988 | { |
997 | int ret; | 989 | int ret; |
998 | unsigned redundancy = 0; | ||
999 | struct raid_dev *dev; | 990 | struct raid_dev *dev; |
1000 | struct md_rdev *rdev, *tmp, *freshest; | 991 | struct md_rdev *rdev, *tmp, *freshest; |
1001 | struct mddev *mddev = &rs->md; | 992 | struct mddev *mddev = &rs->md; |
1002 | 993 | ||
1003 | switch (rs->raid_type->level) { | ||
1004 | case 1: | ||
1005 | redundancy = rs->md.raid_disks - 1; | ||
1006 | break; | ||
1007 | case 4: | ||
1008 | case 5: | ||
1009 | case 6: | ||
1010 | redundancy = rs->raid_type->parity_devs; | ||
1011 | break; | ||
1012 | case 10: | ||
1013 | redundancy = raid10_md_layout_to_copies(mddev->layout) - 1; | ||
1014 | break; | ||
1015 | default: | ||
1016 | ti->error = "Unknown RAID type"; | ||
1017 | return -EINVAL; | ||
1018 | } | ||
1019 | |||
1020 | freshest = NULL; | 994 | freshest = NULL; |
1021 | rdev_for_each_safe(rdev, tmp, mddev) { | 995 | rdev_for_each_safe(rdev, tmp, mddev) { |
1022 | /* | 996 | /* |
@@ -1045,44 +1019,43 @@ static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs) | |||
1045 | break; | 1019 | break; |
1046 | default: | 1020 | default: |
1047 | dev = container_of(rdev, struct raid_dev, rdev); | 1021 | dev = container_of(rdev, struct raid_dev, rdev); |
1048 | if (redundancy--) { | 1022 | if (dev->meta_dev) |
1049 | if (dev->meta_dev) | 1023 | dm_put_device(ti, dev->meta_dev); |
1050 | dm_put_device(ti, dev->meta_dev); | ||
1051 | |||
1052 | dev->meta_dev = NULL; | ||
1053 | rdev->meta_bdev = NULL; | ||
1054 | 1024 | ||
1055 | if (rdev->sb_page) | 1025 | dev->meta_dev = NULL; |
1056 | put_page(rdev->sb_page); | 1026 | rdev->meta_bdev = NULL; |
1057 | 1027 | ||
1058 | rdev->sb_page = NULL; | 1028 | if (rdev->sb_page) |
1029 | put_page(rdev->sb_page); | ||
1059 | 1030 | ||
1060 | rdev->sb_loaded = 0; | 1031 | rdev->sb_page = NULL; |
1061 | 1032 | ||
1062 | /* | 1033 | rdev->sb_loaded = 0; |
1063 | * We might be able to salvage the data device | ||
1064 | * even though the meta device has failed. For | ||
1065 | * now, we behave as though '- -' had been | ||
1066 | * set for this device in the table. | ||
1067 | */ | ||
1068 | if (dev->data_dev) | ||
1069 | dm_put_device(ti, dev->data_dev); | ||
1070 | 1034 | ||
1071 | dev->data_dev = NULL; | 1035 | /* |
1072 | rdev->bdev = NULL; | 1036 | * We might be able to salvage the data device |
1037 | * even though the meta device has failed. For | ||
1038 | * now, we behave as though '- -' had been | ||
1039 | * set for this device in the table. | ||
1040 | */ | ||
1041 | if (dev->data_dev) | ||
1042 | dm_put_device(ti, dev->data_dev); | ||
1073 | 1043 | ||
1074 | list_del(&rdev->same_set); | 1044 | dev->data_dev = NULL; |
1045 | rdev->bdev = NULL; | ||
1075 | 1046 | ||
1076 | continue; | 1047 | list_del(&rdev->same_set); |
1077 | } | ||
1078 | ti->error = "Failed to load superblock"; | ||
1079 | return ret; | ||
1080 | } | 1048 | } |
1081 | } | 1049 | } |
1082 | 1050 | ||
1083 | if (!freshest) | 1051 | if (!freshest) |
1084 | return 0; | 1052 | return 0; |
1085 | 1053 | ||
1054 | if (validate_raid_redundancy(rs)) { | ||
1055 | rs->ti->error = "Insufficient redundancy to activate array"; | ||
1056 | return -EINVAL; | ||
1057 | } | ||
1058 | |||
1086 | /* | 1059 | /* |
1087 | * Validation of the freshest device provides the source of | 1060 | * Validation of the freshest device provides the source of |
1088 | * validation for the remaining devices. | 1061 | * validation for the remaining devices. |
@@ -1432,7 +1405,7 @@ static void raid_resume(struct dm_target *ti) | |||
1432 | 1405 | ||
1433 | static struct target_type raid_target = { | 1406 | static struct target_type raid_target = { |
1434 | .name = "raid", | 1407 | .name = "raid", |
1435 | .version = {1, 4, 0}, | 1408 | .version = {1, 4, 1}, |
1436 | .module = THIS_MODULE, | 1409 | .module = THIS_MODULE, |
1437 | .ctr = raid_ctr, | 1410 | .ctr = raid_ctr, |
1438 | .dtr = raid_dtr, | 1411 | .dtr = raid_dtr, |
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c index 675ae5274016..5409607d4875 100644 --- a/drivers/md/dm-thin.c +++ b/drivers/md/dm-thin.c | |||
@@ -2746,19 +2746,9 @@ static int thin_iterate_devices(struct dm_target *ti, | |||
2746 | return 0; | 2746 | return 0; |
2747 | } | 2747 | } |
2748 | 2748 | ||
2749 | /* | ||
2750 | * A thin device always inherits its queue limits from its pool. | ||
2751 | */ | ||
2752 | static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits) | ||
2753 | { | ||
2754 | struct thin_c *tc = ti->private; | ||
2755 | |||
2756 | *limits = bdev_get_queue(tc->pool_dev->bdev)->limits; | ||
2757 | } | ||
2758 | |||
2759 | static struct target_type thin_target = { | 2749 | static struct target_type thin_target = { |
2760 | .name = "thin", | 2750 | .name = "thin", |
2761 | .version = {1, 6, 0}, | 2751 | .version = {1, 7, 0}, |
2762 | .module = THIS_MODULE, | 2752 | .module = THIS_MODULE, |
2763 | .ctr = thin_ctr, | 2753 | .ctr = thin_ctr, |
2764 | .dtr = thin_dtr, | 2754 | .dtr = thin_dtr, |
@@ -2767,7 +2757,6 @@ static struct target_type thin_target = { | |||
2767 | .postsuspend = thin_postsuspend, | 2757 | .postsuspend = thin_postsuspend, |
2768 | .status = thin_status, | 2758 | .status = thin_status, |
2769 | .iterate_devices = thin_iterate_devices, | 2759 | .iterate_devices = thin_iterate_devices, |
2770 | .io_hints = thin_io_hints, | ||
2771 | }; | 2760 | }; |
2772 | 2761 | ||
2773 | /*----------------------------------------------------------------*/ | 2762 | /*----------------------------------------------------------------*/ |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index c72e4d5a9617..314a0e2faf79 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
@@ -1188,6 +1188,7 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci, | |||
1188 | { | 1188 | { |
1189 | struct dm_target *ti; | 1189 | struct dm_target *ti; |
1190 | sector_t len; | 1190 | sector_t len; |
1191 | unsigned num_requests; | ||
1191 | 1192 | ||
1192 | do { | 1193 | do { |
1193 | ti = dm_table_find_target(ci->map, ci->sector); | 1194 | ti = dm_table_find_target(ci->map, ci->sector); |
@@ -1200,7 +1201,8 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci, | |||
1200 | * reconfiguration might also have changed that since the | 1201 | * reconfiguration might also have changed that since the |
1201 | * check was performed. | 1202 | * check was performed. |
1202 | */ | 1203 | */ |
1203 | if (!get_num_requests || !get_num_requests(ti)) | 1204 | num_requests = get_num_requests ? get_num_requests(ti) : 0; |
1205 | if (!num_requests) | ||
1204 | return -EOPNOTSUPP; | 1206 | return -EOPNOTSUPP; |
1205 | 1207 | ||
1206 | if (is_split_required && !is_split_required(ti)) | 1208 | if (is_split_required && !is_split_required(ti)) |
@@ -1208,7 +1210,7 @@ static int __clone_and_map_changing_extent_only(struct clone_info *ci, | |||
1208 | else | 1210 | else |
1209 | len = min(ci->sector_count, max_io_len(ci->sector, ti)); | 1211 | len = min(ci->sector_count, max_io_len(ci->sector, ti)); |
1210 | 1212 | ||
1211 | __issue_target_requests(ci, ti, ti->num_discard_requests, len); | 1213 | __issue_target_requests(ci, ti, num_requests, len); |
1212 | 1214 | ||
1213 | ci->sector += len; | 1215 | ci->sector += len; |
1214 | } while (ci->sector_count -= len); | 1216 | } while (ci->sector_count -= len); |
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c index 49d95040096a..0223ad255cb4 100644 --- a/drivers/media/dvb-core/dvb_frontend.c +++ b/drivers/media/dvb-core/dvb_frontend.c | |||
@@ -1820,7 +1820,7 @@ static int dvb_frontend_ioctl(struct file *file, | |||
1820 | struct dvb_frontend *fe = dvbdev->priv; | 1820 | struct dvb_frontend *fe = dvbdev->priv; |
1821 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 1821 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
1822 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 1822 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
1823 | int err = -ENOTTY; | 1823 | int err = -EOPNOTSUPP; |
1824 | 1824 | ||
1825 | dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd)); | 1825 | dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd)); |
1826 | if (fepriv->exit != DVB_FE_NO_EXIT) | 1826 | if (fepriv->exit != DVB_FE_NO_EXIT) |
@@ -1938,7 +1938,7 @@ static int dvb_frontend_ioctl_properties(struct file *file, | |||
1938 | } | 1938 | } |
1939 | 1939 | ||
1940 | } else | 1940 | } else |
1941 | err = -ENOTTY; | 1941 | err = -EOPNOTSUPP; |
1942 | 1942 | ||
1943 | out: | 1943 | out: |
1944 | kfree(tvp); | 1944 | kfree(tvp); |
@@ -2071,7 +2071,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file, | |||
2071 | struct dvb_frontend *fe = dvbdev->priv; | 2071 | struct dvb_frontend *fe = dvbdev->priv; |
2072 | struct dvb_frontend_private *fepriv = fe->frontend_priv; | 2072 | struct dvb_frontend_private *fepriv = fe->frontend_priv; |
2073 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; | 2073 | struct dtv_frontend_properties *c = &fe->dtv_property_cache; |
2074 | int err = -ENOTTY; | 2074 | int err = -EOPNOTSUPP; |
2075 | 2075 | ||
2076 | switch (cmd) { | 2076 | switch (cmd) { |
2077 | case FE_GET_INFO: { | 2077 | case FE_GET_INFO: { |
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c index 8a8d42fe2633..d4e7567b367c 100644 --- a/drivers/media/i2c/m5mols/m5mols_core.c +++ b/drivers/media/i2c/m5mols/m5mols_core.c | |||
@@ -556,7 +556,7 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh, | |||
556 | mutex_lock(&info->lock); | 556 | mutex_lock(&info->lock); |
557 | 557 | ||
558 | format = __find_format(info, fh, fmt->which, info->res_type); | 558 | format = __find_format(info, fh, fmt->which, info->res_type); |
559 | if (!format) | 559 | if (format) |
560 | fmt->format = *format; | 560 | fmt->format = *format; |
561 | else | 561 | else |
562 | ret = -EINVAL; | 562 | ret = -EINVAL; |
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c index 1cf8293c0fb0..4a980e029ca7 100644 --- a/drivers/media/platform/coda.c +++ b/drivers/media/platform/coda.c | |||
@@ -23,8 +23,8 @@ | |||
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/videodev2.h> | 24 | #include <linux/videodev2.h> |
25 | #include <linux/of.h> | 25 | #include <linux/of.h> |
26 | #include <linux/platform_data/imx-iram.h> | ||
26 | 27 | ||
27 | #include <mach/iram.h> | ||
28 | #include <media/v4l2-ctrls.h> | 28 | #include <media/v4l2-ctrls.h> |
29 | #include <media/v4l2-device.h> | 29 | #include <media/v4l2-device.h> |
30 | #include <media/v4l2-ioctl.h> | 30 | #include <media/v4l2-ioctl.h> |
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c index e0d73a642186..8dac17511e61 100644 --- a/drivers/media/platform/omap3isp/ispvideo.c +++ b/drivers/media/platform/omap3isp/ispvideo.c | |||
@@ -35,9 +35,6 @@ | |||
35 | #include <linux/vmalloc.h> | 35 | #include <linux/vmalloc.h> |
36 | #include <media/v4l2-dev.h> | 36 | #include <media/v4l2-dev.h> |
37 | #include <media/v4l2-ioctl.h> | 37 | #include <media/v4l2-ioctl.h> |
38 | #include <plat/iommu.h> | ||
39 | #include <plat/iovmm.h> | ||
40 | #include <plat/omap-pm.h> | ||
41 | 38 | ||
42 | #include "ispvideo.h" | 39 | #include "ispvideo.h" |
43 | #include "isp.h" | 40 | #include "isp.h" |
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c index 4ab99f3a7b09..b4a68ecf0ca7 100644 --- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c +++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c | |||
@@ -593,7 +593,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd) | |||
593 | { | 593 | { |
594 | struct media_entity *source, *sink; | 594 | struct media_entity *source, *sink; |
595 | unsigned int flags = MEDIA_LNK_FL_ENABLED; | 595 | unsigned int flags = MEDIA_LNK_FL_ENABLED; |
596 | int i, ret; | 596 | int i, ret = 0; |
597 | 597 | ||
598 | for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { | 598 | for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) { |
599 | struct fimc_lite *fimc = fmd->fimc_lite[i]; | 599 | struct fimc_lite *fimc = fmd->fimc_lite[i]; |
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c index 379f57433711..681bc6ba149d 100644 --- a/drivers/media/platform/s5p-mfc/s5p_mfc.c +++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c | |||
@@ -412,62 +412,48 @@ leave_handle_frame: | |||
412 | } | 412 | } |
413 | 413 | ||
414 | /* Error handling for interrupt */ | 414 | /* Error handling for interrupt */ |
415 | static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx, | 415 | static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev, |
416 | unsigned int reason, unsigned int err) | 416 | struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err) |
417 | { | 417 | { |
418 | struct s5p_mfc_dev *dev; | ||
419 | unsigned long flags; | 418 | unsigned long flags; |
420 | 419 | ||
421 | /* If no context is available then all necessary | ||
422 | * processing has been done. */ | ||
423 | if (ctx == NULL) | ||
424 | return; | ||
425 | |||
426 | dev = ctx->dev; | ||
427 | mfc_err("Interrupt Error: %08x\n", err); | 420 | mfc_err("Interrupt Error: %08x\n", err); |
428 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | ||
429 | wake_up_dev(dev, reason, err); | ||
430 | 421 | ||
431 | /* Error recovery is dependent on the state of context */ | 422 | if (ctx != NULL) { |
432 | switch (ctx->state) { | 423 | /* Error recovery is dependent on the state of context */ |
433 | case MFCINST_INIT: | 424 | switch (ctx->state) { |
434 | /* This error had to happen while acquireing instance */ | 425 | case MFCINST_RES_CHANGE_INIT: |
435 | case MFCINST_GOT_INST: | 426 | case MFCINST_RES_CHANGE_FLUSH: |
436 | /* This error had to happen while parsing the header */ | 427 | case MFCINST_RES_CHANGE_END: |
437 | case MFCINST_HEAD_PARSED: | 428 | case MFCINST_FINISHING: |
438 | /* This error had to happen while setting dst buffers */ | 429 | case MFCINST_FINISHED: |
439 | case MFCINST_RETURN_INST: | 430 | case MFCINST_RUNNING: |
440 | /* This error had to happen while releasing instance */ | 431 | /* It is higly probable that an error occured |
441 | clear_work_bit(ctx); | 432 | * while decoding a frame */ |
442 | wake_up_ctx(ctx, reason, err); | 433 | clear_work_bit(ctx); |
443 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | 434 | ctx->state = MFCINST_ERROR; |
444 | BUG(); | 435 | /* Mark all dst buffers as having an error */ |
445 | s5p_mfc_clock_off(); | 436 | spin_lock_irqsave(&dev->irqlock, flags); |
446 | ctx->state = MFCINST_ERROR; | 437 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, |
447 | break; | 438 | &ctx->dst_queue, &ctx->vq_dst); |
448 | case MFCINST_FINISHING: | 439 | /* Mark all src buffers as having an error */ |
449 | case MFCINST_FINISHED: | 440 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, |
450 | case MFCINST_RUNNING: | 441 | &ctx->src_queue, &ctx->vq_src); |
451 | /* It is higly probable that an error occured | 442 | spin_unlock_irqrestore(&dev->irqlock, flags); |
452 | * while decoding a frame */ | 443 | wake_up_ctx(ctx, reason, err); |
453 | clear_work_bit(ctx); | 444 | break; |
454 | ctx->state = MFCINST_ERROR; | 445 | default: |
455 | /* Mark all dst buffers as having an error */ | 446 | clear_work_bit(ctx); |
456 | spin_lock_irqsave(&dev->irqlock, flags); | 447 | ctx->state = MFCINST_ERROR; |
457 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue, | 448 | wake_up_ctx(ctx, reason, err); |
458 | &ctx->vq_dst); | 449 | break; |
459 | /* Mark all src buffers as having an error */ | 450 | } |
460 | s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue, | ||
461 | &ctx->vq_src); | ||
462 | spin_unlock_irqrestore(&dev->irqlock, flags); | ||
463 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
464 | BUG(); | ||
465 | s5p_mfc_clock_off(); | ||
466 | break; | ||
467 | default: | ||
468 | mfc_err("Encountered an error interrupt which had not been handled\n"); | ||
469 | break; | ||
470 | } | 451 | } |
452 | if (test_and_clear_bit(0, &dev->hw_lock) == 0) | ||
453 | BUG(); | ||
454 | s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev); | ||
455 | s5p_mfc_clock_off(); | ||
456 | wake_up_dev(dev, reason, err); | ||
471 | return; | 457 | return; |
472 | } | 458 | } |
473 | 459 | ||
@@ -632,7 +618,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) | |||
632 | dev->warn_start) | 618 | dev->warn_start) |
633 | s5p_mfc_handle_frame(ctx, reason, err); | 619 | s5p_mfc_handle_frame(ctx, reason, err); |
634 | else | 620 | else |
635 | s5p_mfc_handle_error(ctx, reason, err); | 621 | s5p_mfc_handle_error(dev, ctx, reason, err); |
636 | clear_bit(0, &dev->enter_suspend); | 622 | clear_bit(0, &dev->enter_suspend); |
637 | break; | 623 | break; |
638 | 624 | ||
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c index e10e525f33e5..296941a9ae25 100644 --- a/drivers/media/radio/radio-keene.c +++ b/drivers/media/radio/radio-keene.c | |||
@@ -374,6 +374,7 @@ static int usb_keene_probe(struct usb_interface *intf, | |||
374 | radio->vdev.ioctl_ops = &usb_keene_ioctl_ops; | 374 | radio->vdev.ioctl_ops = &usb_keene_ioctl_ops; |
375 | radio->vdev.lock = &radio->lock; | 375 | radio->vdev.lock = &radio->lock; |
376 | radio->vdev.release = video_device_release_empty; | 376 | radio->vdev.release = video_device_release_empty; |
377 | radio->vdev.vfl_dir = VFL_DIR_TX; | ||
377 | 378 | ||
378 | radio->usbdev = interface_to_usbdev(intf); | 379 | radio->usbdev = interface_to_usbdev(intf); |
379 | radio->intf = intf; | 380 | radio->intf = intf; |
diff --git a/drivers/media/radio/radio-si4713.c b/drivers/media/radio/radio-si4713.c index a082e400ed0f..1507c9d508d7 100644 --- a/drivers/media/radio/radio-si4713.c +++ b/drivers/media/radio/radio-si4713.c | |||
@@ -250,6 +250,7 @@ static struct video_device radio_si4713_vdev_template = { | |||
250 | .name = "radio-si4713", | 250 | .name = "radio-si4713", |
251 | .release = video_device_release, | 251 | .release = video_device_release, |
252 | .ioctl_ops = &radio_si4713_ioctl_ops, | 252 | .ioctl_ops = &radio_si4713_ioctl_ops, |
253 | .vfl_dir = VFL_DIR_TX, | ||
253 | }; | 254 | }; |
254 | 255 | ||
255 | /* Platform driver interface */ | 256 | /* Platform driver interface */ |
diff --git a/drivers/media/radio/radio-wl1273.c b/drivers/media/radio/radio-wl1273.c index c48be195bbad..cabbe3adf435 100644 --- a/drivers/media/radio/radio-wl1273.c +++ b/drivers/media/radio/radio-wl1273.c | |||
@@ -1971,6 +1971,7 @@ static struct video_device wl1273_viddev_template = { | |||
1971 | .ioctl_ops = &wl1273_ioctl_ops, | 1971 | .ioctl_ops = &wl1273_ioctl_ops, |
1972 | .name = WL1273_FM_DRIVER_NAME, | 1972 | .name = WL1273_FM_DRIVER_NAME, |
1973 | .release = wl1273_vdev_release, | 1973 | .release = wl1273_vdev_release, |
1974 | .vfl_dir = VFL_DIR_TX, | ||
1974 | }; | 1975 | }; |
1975 | 1976 | ||
1976 | static int wl1273_fm_radio_remove(struct platform_device *pdev) | 1977 | static int wl1273_fm_radio_remove(struct platform_device *pdev) |
diff --git a/drivers/media/radio/wl128x/fmdrv_v4l2.c b/drivers/media/radio/wl128x/fmdrv_v4l2.c index 048de4536036..0a8ee8fab924 100644 --- a/drivers/media/radio/wl128x/fmdrv_v4l2.c +++ b/drivers/media/radio/wl128x/fmdrv_v4l2.c | |||
@@ -518,6 +518,16 @@ static struct video_device fm_viddev_template = { | |||
518 | .ioctl_ops = &fm_drv_ioctl_ops, | 518 | .ioctl_ops = &fm_drv_ioctl_ops, |
519 | .name = FM_DRV_NAME, | 519 | .name = FM_DRV_NAME, |
520 | .release = video_device_release, | 520 | .release = video_device_release, |
521 | /* | ||
522 | * To ensure both the tuner and modulator ioctls are accessible we | ||
523 | * set the vfl_dir to M2M to indicate this. | ||
524 | * | ||
525 | * It is not really a mem2mem device of course, but it can both receive | ||
526 | * and transmit using the same radio device. It's the only radio driver | ||
527 | * that does this and it should really be split in two radio devices, | ||
528 | * but that would affect applications using this driver. | ||
529 | */ | ||
530 | .vfl_dir = VFL_DIR_M2M, | ||
521 | }; | 531 | }; |
522 | 532 | ||
523 | int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) | 533 | int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr) |
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c index 40ad6687ee5d..3773a8a745df 100644 --- a/drivers/media/usb/gspca/kinect.c +++ b/drivers/media/usb/gspca/kinect.c | |||
@@ -381,6 +381,7 @@ static const struct sd_desc sd_desc = { | |||
381 | /* -- module initialisation -- */ | 381 | /* -- module initialisation -- */ |
382 | static const struct usb_device_id device_table[] = { | 382 | static const struct usb_device_id device_table[] = { |
383 | {USB_DEVICE(0x045e, 0x02ae)}, | 383 | {USB_DEVICE(0x045e, 0x02ae)}, |
384 | {USB_DEVICE(0x045e, 0x02bf)}, | ||
384 | {} | 385 | {} |
385 | }; | 386 | }; |
386 | 387 | ||
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c index 70511d5f9538..1220340e7602 100644 --- a/drivers/media/usb/gspca/sonixb.c +++ b/drivers/media/usb/gspca/sonixb.c | |||
@@ -496,7 +496,7 @@ static void reg_w(struct gspca_dev *gspca_dev, | |||
496 | } | 496 | } |
497 | } | 497 | } |
498 | 498 | ||
499 | static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) | 499 | static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf) |
500 | { | 500 | { |
501 | int retry = 60; | 501 | int retry = 60; |
502 | 502 | ||
@@ -504,16 +504,19 @@ static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer) | |||
504 | return; | 504 | return; |
505 | 505 | ||
506 | /* is i2c ready */ | 506 | /* is i2c ready */ |
507 | reg_w(gspca_dev, 0x08, buffer, 8); | 507 | reg_w(gspca_dev, 0x08, buf, 8); |
508 | while (retry--) { | 508 | while (retry--) { |
509 | if (gspca_dev->usb_err < 0) | 509 | if (gspca_dev->usb_err < 0) |
510 | return; | 510 | return; |
511 | msleep(10); | 511 | msleep(1); |
512 | reg_r(gspca_dev, 0x08); | 512 | reg_r(gspca_dev, 0x08); |
513 | if (gspca_dev->usb_buf[0] & 0x04) { | 513 | if (gspca_dev->usb_buf[0] & 0x04) { |
514 | if (gspca_dev->usb_buf[0] & 0x08) { | 514 | if (gspca_dev->usb_buf[0] & 0x08) { |
515 | dev_err(gspca_dev->v4l2_dev.dev, | 515 | dev_err(gspca_dev->v4l2_dev.dev, |
516 | "i2c write error\n"); | 516 | "i2c error writing %02x %02x %02x %02x" |
517 | " %02x %02x %02x %02x\n", | ||
518 | buf[0], buf[1], buf[2], buf[3], | ||
519 | buf[4], buf[5], buf[6], buf[7]); | ||
517 | gspca_dev->usb_err = -EIO; | 520 | gspca_dev->usb_err = -EIO; |
518 | } | 521 | } |
519 | return; | 522 | return; |
@@ -530,7 +533,7 @@ static void i2c_w_vector(struct gspca_dev *gspca_dev, | |||
530 | for (;;) { | 533 | for (;;) { |
531 | if (gspca_dev->usb_err < 0) | 534 | if (gspca_dev->usb_err < 0) |
532 | return; | 535 | return; |
533 | reg_w(gspca_dev, 0x08, *buffer, 8); | 536 | i2c_w(gspca_dev, *buffer); |
534 | len -= 8; | 537 | len -= 8; |
535 | if (len <= 0) | 538 | if (len <= 0) |
536 | break; | 539 | break; |
diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c index 5a86047b846f..36307a9028a9 100644 --- a/drivers/media/usb/gspca/sonixj.c +++ b/drivers/media/usb/gspca/sonixj.c | |||
@@ -1550,6 +1550,7 @@ static void i2c_w1(struct gspca_dev *gspca_dev, u8 reg, u8 val) | |||
1550 | 0, | 1550 | 0, |
1551 | gspca_dev->usb_buf, 8, | 1551 | gspca_dev->usb_buf, 8, |
1552 | 500); | 1552 | 500); |
1553 | msleep(2); | ||
1553 | if (ret < 0) { | 1554 | if (ret < 0) { |
1554 | pr_err("i2c_w1 err %d\n", ret); | 1555 | pr_err("i2c_w1 err %d\n", ret); |
1555 | gspca_dev->usb_err = ret; | 1556 | gspca_dev->usb_err = ret; |
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c index 2bb7613ddebb..d5baab17a5ef 100644 --- a/drivers/media/usb/uvc/uvc_ctrl.c +++ b/drivers/media/usb/uvc/uvc_ctrl.c | |||
@@ -1431,8 +1431,10 @@ int uvc_ctrl_set(struct uvc_video_chain *chain, | |||
1431 | int ret; | 1431 | int ret; |
1432 | 1432 | ||
1433 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); | 1433 | ctrl = uvc_find_control(chain, xctrl->id, &mapping); |
1434 | if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0) | 1434 | if (ctrl == NULL) |
1435 | return -EINVAL; | 1435 | return -EINVAL; |
1436 | if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR)) | ||
1437 | return -EACCES; | ||
1436 | 1438 | ||
1437 | /* Clamp out of range values. */ | 1439 | /* Clamp out of range values. */ |
1438 | switch (mapping->v4l2_type) { | 1440 | switch (mapping->v4l2_type) { |
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c index f2ee8c6b0d8d..68d59b527492 100644 --- a/drivers/media/usb/uvc/uvc_v4l2.c +++ b/drivers/media/usb/uvc/uvc_v4l2.c | |||
@@ -657,8 +657,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
657 | ret = uvc_ctrl_get(chain, ctrl); | 657 | ret = uvc_ctrl_get(chain, ctrl); |
658 | if (ret < 0) { | 658 | if (ret < 0) { |
659 | uvc_ctrl_rollback(handle); | 659 | uvc_ctrl_rollback(handle); |
660 | ctrls->error_idx = ret == -ENOENT | 660 | ctrls->error_idx = i; |
661 | ? ctrls->count : i; | ||
662 | return ret; | 661 | return ret; |
663 | } | 662 | } |
664 | } | 663 | } |
@@ -686,8 +685,7 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg) | |||
686 | ret = uvc_ctrl_set(chain, ctrl); | 685 | ret = uvc_ctrl_set(chain, ctrl); |
687 | if (ret < 0) { | 686 | if (ret < 0) { |
688 | uvc_ctrl_rollback(handle); | 687 | uvc_ctrl_rollback(handle); |
689 | ctrls->error_idx = (ret == -ENOENT && | 688 | ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS |
690 | cmd == VIDIOC_S_EXT_CTRLS) | ||
691 | ? ctrls->count : i; | 689 | ? ctrls->count : i; |
692 | return ret; | 690 | return ret; |
693 | } | 691 | } |
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c index 9f81be23a81f..e02c4797b1c6 100644 --- a/drivers/media/v4l2-core/videobuf2-core.c +++ b/drivers/media/v4l2-core/videobuf2-core.c | |||
@@ -921,8 +921,10 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b | |||
921 | * In videobuf we use our internal V4l2_planes struct for | 921 | * In videobuf we use our internal V4l2_planes struct for |
922 | * single-planar buffers as well, for simplicity. | 922 | * single-planar buffers as well, for simplicity. |
923 | */ | 923 | */ |
924 | if (V4L2_TYPE_IS_OUTPUT(b->type)) | 924 | if (V4L2_TYPE_IS_OUTPUT(b->type)) { |
925 | v4l2_planes[0].bytesused = b->bytesused; | 925 | v4l2_planes[0].bytesused = b->bytesused; |
926 | v4l2_planes[0].data_offset = 0; | ||
927 | } | ||
926 | 928 | ||
927 | if (b->memory == V4L2_MEMORY_USERPTR) { | 929 | if (b->memory == V4L2_MEMORY_USERPTR) { |
928 | v4l2_planes[0].m.userptr = b->m.userptr; | 930 | v4l2_planes[0].m.userptr = b->m.userptr; |
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index 1c0abd4dfc43..ff553babf455 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig | |||
@@ -237,6 +237,7 @@ config MFD_TPS65910 | |||
237 | depends on I2C=y && GPIOLIB | 237 | depends on I2C=y && GPIOLIB |
238 | select MFD_CORE | 238 | select MFD_CORE |
239 | select REGMAP_I2C | 239 | select REGMAP_I2C |
240 | select REGMAP_IRQ | ||
240 | select IRQ_DOMAIN | 241 | select IRQ_DOMAIN |
241 | help | 242 | help |
242 | if you say yes here you get support for the TPS65910 series of | 243 | if you say yes here you get support for the TPS65910 series of |
@@ -292,6 +293,7 @@ config TWL4030_CORE | |||
292 | bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" | 293 | bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support" |
293 | depends on I2C=y && GENERIC_HARDIRQS | 294 | depends on I2C=y && GENERIC_HARDIRQS |
294 | select IRQ_DOMAIN | 295 | select IRQ_DOMAIN |
296 | select REGMAP_I2C | ||
295 | help | 297 | help |
296 | Say yes here if you have TWL4030 / TWL6030 family chip on your board. | 298 | Say yes here if you have TWL4030 / TWL6030 family chip on your board. |
297 | This core driver provides register access and IRQ handling | 299 | This core driver provides register access and IRQ handling |
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c index e1650badd106..4778bb124efe 100644 --- a/drivers/mfd/ab8500-core.c +++ b/drivers/mfd/ab8500-core.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/mfd/core.h> | 19 | #include <linux/mfd/core.h> |
20 | #include <linux/mfd/abx500.h> | 20 | #include <linux/mfd/abx500.h> |
21 | #include <linux/mfd/abx500/ab8500.h> | 21 | #include <linux/mfd/abx500/ab8500.h> |
22 | #include <linux/mfd/abx500/ab8500-bm.h> | ||
22 | #include <linux/mfd/dbx500-prcmu.h> | 23 | #include <linux/mfd/dbx500-prcmu.h> |
23 | #include <linux/regulator/ab8500.h> | 24 | #include <linux/regulator/ab8500.h> |
24 | #include <linux/of.h> | 25 | #include <linux/of.h> |
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index bc8a3edb6bbf..222c03a5ddc0 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c | |||
@@ -239,7 +239,12 @@ static int arizona_runtime_resume(struct device *dev) | |||
239 | return ret; | 239 | return ret; |
240 | } | 240 | } |
241 | 241 | ||
242 | regcache_sync(arizona->regmap); | 242 | ret = regcache_sync(arizona->regmap); |
243 | if (ret != 0) { | ||
244 | dev_err(arizona->dev, "Failed to restore register cache\n"); | ||
245 | regulator_disable(arizona->dcvdd); | ||
246 | return ret; | ||
247 | } | ||
243 | 248 | ||
244 | return 0; | 249 | return 0; |
245 | } | 250 | } |
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c index 74713bf5371f..2bec5f0db3ee 100644 --- a/drivers/mfd/arizona-irq.c +++ b/drivers/mfd/arizona-irq.c | |||
@@ -176,14 +176,7 @@ int arizona_irq_init(struct arizona *arizona) | |||
176 | aod = &wm5102_aod; | 176 | aod = &wm5102_aod; |
177 | irq = &wm5102_irq; | 177 | irq = &wm5102_irq; |
178 | 178 | ||
179 | switch (arizona->rev) { | 179 | ctrlif_error = false; |
180 | case 0: | ||
181 | case 1: | ||
182 | ctrlif_error = false; | ||
183 | break; | ||
184 | default: | ||
185 | break; | ||
186 | } | ||
187 | break; | 180 | break; |
188 | #endif | 181 | #endif |
189 | #ifdef CONFIG_MFD_WM5110 | 182 | #ifdef CONFIG_MFD_WM5110 |
@@ -191,14 +184,7 @@ int arizona_irq_init(struct arizona *arizona) | |||
191 | aod = &wm5110_aod; | 184 | aod = &wm5110_aod; |
192 | irq = &wm5110_irq; | 185 | irq = &wm5110_irq; |
193 | 186 | ||
194 | switch (arizona->rev) { | 187 | ctrlif_error = false; |
195 | case 0: | ||
196 | case 1: | ||
197 | ctrlif_error = false; | ||
198 | break; | ||
199 | default: | ||
200 | break; | ||
201 | } | ||
202 | break; | 188 | break; |
203 | #endif | 189 | #endif |
204 | default: | 190 | default: |
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c index ac74a4d1daea..885e56780358 100644 --- a/drivers/mfd/da9052-i2c.c +++ b/drivers/mfd/da9052-i2c.c | |||
@@ -27,6 +27,66 @@ | |||
27 | #include <linux/of_device.h> | 27 | #include <linux/of_device.h> |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | /* I2C safe register check */ | ||
31 | static inline bool i2c_safe_reg(unsigned char reg) | ||
32 | { | ||
33 | switch (reg) { | ||
34 | case DA9052_STATUS_A_REG: | ||
35 | case DA9052_STATUS_B_REG: | ||
36 | case DA9052_STATUS_C_REG: | ||
37 | case DA9052_STATUS_D_REG: | ||
38 | case DA9052_ADC_RES_L_REG: | ||
39 | case DA9052_ADC_RES_H_REG: | ||
40 | case DA9052_VDD_RES_REG: | ||
41 | case DA9052_ICHG_AV_REG: | ||
42 | case DA9052_TBAT_RES_REG: | ||
43 | case DA9052_ADCIN4_RES_REG: | ||
44 | case DA9052_ADCIN5_RES_REG: | ||
45 | case DA9052_ADCIN6_RES_REG: | ||
46 | case DA9052_TJUNC_RES_REG: | ||
47 | case DA9052_TSI_X_MSB_REG: | ||
48 | case DA9052_TSI_Y_MSB_REG: | ||
49 | case DA9052_TSI_LSB_REG: | ||
50 | case DA9052_TSI_Z_MSB_REG: | ||
51 | return true; | ||
52 | default: | ||
53 | return false; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | /* | ||
58 | * There is an issue with DA9052 and DA9053_AA/BA/BB PMIC where the PMIC | ||
59 | * gets lockup up or fails to respond following a system reset. | ||
60 | * This fix is to follow any read or write with a dummy read to a safe | ||
61 | * register. | ||
62 | */ | ||
63 | int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg) | ||
64 | { | ||
65 | int val; | ||
66 | |||
67 | switch (da9052->chip_id) { | ||
68 | case DA9052: | ||
69 | case DA9053_AA: | ||
70 | case DA9053_BA: | ||
71 | case DA9053_BB: | ||
72 | /* A dummy read to a safe register address. */ | ||
73 | if (!i2c_safe_reg(reg)) | ||
74 | return regmap_read(da9052->regmap, | ||
75 | DA9052_PARK_REGISTER, | ||
76 | &val); | ||
77 | break; | ||
78 | default: | ||
79 | /* | ||
80 | * For other chips parking of I2C register | ||
81 | * to a safe place is not required. | ||
82 | */ | ||
83 | break; | ||
84 | } | ||
85 | |||
86 | return 0; | ||
87 | } | ||
88 | EXPORT_SYMBOL(da9052_i2c_fix); | ||
89 | |||
30 | static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) | 90 | static int da9052_i2c_enable_multiwrite(struct da9052 *da9052) |
31 | { | 91 | { |
32 | int reg_val, ret; | 92 | int reg_val, ret; |
@@ -83,6 +143,7 @@ static int da9052_i2c_probe(struct i2c_client *client, | |||
83 | 143 | ||
84 | da9052->dev = &client->dev; | 144 | da9052->dev = &client->dev; |
85 | da9052->chip_irq = client->irq; | 145 | da9052->chip_irq = client->irq; |
146 | da9052->fix_io = da9052_i2c_fix; | ||
86 | 147 | ||
87 | i2c_set_clientdata(client, da9052); | 148 | i2c_set_clientdata(client, da9052); |
88 | 149 | ||
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c index dc8826d8d69d..268f45d42394 100644 --- a/drivers/mfd/db8500-prcmu.c +++ b/drivers/mfd/db8500-prcmu.c | |||
@@ -2524,7 +2524,7 @@ static bool read_mailbox_0(void) | |||
2524 | 2524 | ||
2525 | for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) { | 2525 | for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) { |
2526 | if (ev & prcmu_irq_bit[n]) | 2526 | if (ev & prcmu_irq_bit[n]) |
2527 | generic_handle_irq(IRQ_PRCMU_BASE + n); | 2527 | generic_handle_irq(irq_find_mapping(db8500_irq_domain, n)); |
2528 | } | 2528 | } |
2529 | r = true; | 2529 | r = true; |
2530 | break; | 2530 | break; |
@@ -2737,13 +2737,14 @@ static int db8500_irq_map(struct irq_domain *d, unsigned int virq, | |||
2737 | } | 2737 | } |
2738 | 2738 | ||
2739 | static struct irq_domain_ops db8500_irq_ops = { | 2739 | static struct irq_domain_ops db8500_irq_ops = { |
2740 | .map = db8500_irq_map, | 2740 | .map = db8500_irq_map, |
2741 | .xlate = irq_domain_xlate_twocell, | 2741 | .xlate = irq_domain_xlate_twocell, |
2742 | }; | 2742 | }; |
2743 | 2743 | ||
2744 | static int db8500_irq_init(struct device_node *np) | 2744 | static int db8500_irq_init(struct device_node *np) |
2745 | { | 2745 | { |
2746 | int irq_base = -1; | 2746 | int irq_base = 0; |
2747 | int i; | ||
2747 | 2748 | ||
2748 | /* In the device tree case, just take some IRQs */ | 2749 | /* In the device tree case, just take some IRQs */ |
2749 | if (!np) | 2750 | if (!np) |
@@ -2758,6 +2759,10 @@ static int db8500_irq_init(struct device_node *np) | |||
2758 | return -ENOSYS; | 2759 | return -ENOSYS; |
2759 | } | 2760 | } |
2760 | 2761 | ||
2762 | /* All wakeups will be used, so create mappings for all */ | ||
2763 | for (i = 0; i < NUM_PRCMU_WAKEUPS; i++) | ||
2764 | irq_create_mapping(db8500_irq_domain, i); | ||
2765 | |||
2761 | return 0; | 2766 | return 0; |
2762 | } | 2767 | } |
2763 | 2768 | ||
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c index f6878f8db57d..4d73963cd8f0 100644 --- a/drivers/mfd/max77686.c +++ b/drivers/mfd/max77686.c | |||
@@ -93,15 +93,6 @@ static int max77686_i2c_probe(struct i2c_client *i2c, | |||
93 | if (max77686 == NULL) | 93 | if (max77686 == NULL) |
94 | return -ENOMEM; | 94 | return -ENOMEM; |
95 | 95 | ||
96 | max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); | ||
97 | if (IS_ERR(max77686->regmap)) { | ||
98 | ret = PTR_ERR(max77686->regmap); | ||
99 | dev_err(max77686->dev, "Failed to allocate register map: %d\n", | ||
100 | ret); | ||
101 | kfree(max77686); | ||
102 | return ret; | ||
103 | } | ||
104 | |||
105 | i2c_set_clientdata(i2c, max77686); | 96 | i2c_set_clientdata(i2c, max77686); |
106 | max77686->dev = &i2c->dev; | 97 | max77686->dev = &i2c->dev; |
107 | max77686->i2c = i2c; | 98 | max77686->i2c = i2c; |
@@ -111,6 +102,15 @@ static int max77686_i2c_probe(struct i2c_client *i2c, | |||
111 | max77686->irq_gpio = pdata->irq_gpio; | 102 | max77686->irq_gpio = pdata->irq_gpio; |
112 | max77686->irq = i2c->irq; | 103 | max77686->irq = i2c->irq; |
113 | 104 | ||
105 | max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config); | ||
106 | if (IS_ERR(max77686->regmap)) { | ||
107 | ret = PTR_ERR(max77686->regmap); | ||
108 | dev_err(max77686->dev, "Failed to allocate register map: %d\n", | ||
109 | ret); | ||
110 | kfree(max77686); | ||
111 | return ret; | ||
112 | } | ||
113 | |||
114 | if (regmap_read(max77686->regmap, | 114 | if (regmap_read(max77686->regmap, |
115 | MAX77686_REG_DEVICE_ID, &data) < 0) { | 115 | MAX77686_REG_DEVICE_ID, &data) < 0) { |
116 | dev_err(max77686->dev, | 116 | dev_err(max77686->dev, |
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c index cc5155e20494..9e60fed5ff82 100644 --- a/drivers/mfd/max77693.c +++ b/drivers/mfd/max77693.c | |||
@@ -114,35 +114,37 @@ static int max77693_i2c_probe(struct i2c_client *i2c, | |||
114 | u8 reg_data; | 114 | u8 reg_data; |
115 | int ret = 0; | 115 | int ret = 0; |
116 | 116 | ||
117 | if (!pdata) { | ||
118 | dev_err(&i2c->dev, "No platform data found.\n"); | ||
119 | return -EINVAL; | ||
120 | } | ||
121 | |||
117 | max77693 = devm_kzalloc(&i2c->dev, | 122 | max77693 = devm_kzalloc(&i2c->dev, |
118 | sizeof(struct max77693_dev), GFP_KERNEL); | 123 | sizeof(struct max77693_dev), GFP_KERNEL); |
119 | if (max77693 == NULL) | 124 | if (max77693 == NULL) |
120 | return -ENOMEM; | 125 | return -ENOMEM; |
121 | 126 | ||
122 | max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config); | ||
123 | if (IS_ERR(max77693->regmap)) { | ||
124 | ret = PTR_ERR(max77693->regmap); | ||
125 | dev_err(max77693->dev,"failed to allocate register map: %d\n", | ||
126 | ret); | ||
127 | goto err_regmap; | ||
128 | } | ||
129 | |||
130 | i2c_set_clientdata(i2c, max77693); | 127 | i2c_set_clientdata(i2c, max77693); |
131 | max77693->dev = &i2c->dev; | 128 | max77693->dev = &i2c->dev; |
132 | max77693->i2c = i2c; | 129 | max77693->i2c = i2c; |
133 | max77693->irq = i2c->irq; | 130 | max77693->irq = i2c->irq; |
134 | max77693->type = id->driver_data; | 131 | max77693->type = id->driver_data; |
135 | 132 | ||
136 | if (!pdata) | 133 | max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config); |
137 | goto err_regmap; | 134 | if (IS_ERR(max77693->regmap)) { |
135 | ret = PTR_ERR(max77693->regmap); | ||
136 | dev_err(max77693->dev, "failed to allocate register map: %d\n", | ||
137 | ret); | ||
138 | return ret; | ||
139 | } | ||
138 | 140 | ||
139 | max77693->wakeup = pdata->wakeup; | 141 | max77693->wakeup = pdata->wakeup; |
140 | 142 | ||
141 | if (max77693_read_reg(max77693->regmap, | 143 | ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2, |
142 | MAX77693_PMIC_REG_PMIC_ID2, ®_data) < 0) { | 144 | ®_data); |
145 | if (ret < 0) { | ||
143 | dev_err(max77693->dev, "device not found on this channel\n"); | 146 | dev_err(max77693->dev, "device not found on this channel\n"); |
144 | ret = -ENODEV; | 147 | return ret; |
145 | goto err_regmap; | ||
146 | } else | 148 | } else |
147 | dev_info(max77693->dev, "device ID: 0x%x\n", reg_data); | 149 | dev_info(max77693->dev, "device ID: 0x%x\n", reg_data); |
148 | 150 | ||
@@ -163,7 +165,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c, | |||
163 | ret = PTR_ERR(max77693->regmap_muic); | 165 | ret = PTR_ERR(max77693->regmap_muic); |
164 | dev_err(max77693->dev, | 166 | dev_err(max77693->dev, |
165 | "failed to allocate register map: %d\n", ret); | 167 | "failed to allocate register map: %d\n", ret); |
166 | goto err_regmap; | 168 | goto err_regmap_muic; |
167 | } | 169 | } |
168 | 170 | ||
169 | ret = max77693_irq_init(max77693); | 171 | ret = max77693_irq_init(max77693); |
@@ -184,9 +186,9 @@ static int max77693_i2c_probe(struct i2c_client *i2c, | |||
184 | err_mfd: | 186 | err_mfd: |
185 | max77693_irq_exit(max77693); | 187 | max77693_irq_exit(max77693); |
186 | err_irq: | 188 | err_irq: |
189 | err_regmap_muic: | ||
187 | i2c_unregister_device(max77693->muic); | 190 | i2c_unregister_device(max77693->muic); |
188 | i2c_unregister_device(max77693->haptic); | 191 | i2c_unregister_device(max77693->haptic); |
189 | err_regmap: | ||
190 | return ret; | 192 | return ret; |
191 | } | 193 | } |
192 | 194 | ||
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c index 64803f13bcec..d11567307fbe 100644 --- a/drivers/mfd/pcf50633-core.c +++ b/drivers/mfd/pcf50633-core.c | |||
@@ -208,6 +208,8 @@ static int pcf50633_probe(struct i2c_client *client, | |||
208 | if (!pcf) | 208 | if (!pcf) |
209 | return -ENOMEM; | 209 | return -ENOMEM; |
210 | 210 | ||
211 | i2c_set_clientdata(client, pcf); | ||
212 | pcf->dev = &client->dev; | ||
211 | pcf->pdata = pdata; | 213 | pcf->pdata = pdata; |
212 | 214 | ||
213 | mutex_init(&pcf->lock); | 215 | mutex_init(&pcf->lock); |
@@ -219,9 +221,6 @@ static int pcf50633_probe(struct i2c_client *client, | |||
219 | return ret; | 221 | return ret; |
220 | } | 222 | } |
221 | 223 | ||
222 | i2c_set_clientdata(client, pcf); | ||
223 | pcf->dev = &client->dev; | ||
224 | |||
225 | version = pcf50633_reg_read(pcf, 0); | 224 | version = pcf50633_reg_read(pcf, 0); |
226 | variant = pcf50633_reg_read(pcf, 1); | 225 | variant = pcf50633_reg_read(pcf, 1); |
227 | if (version < 0 || variant < 0) { | 226 | if (version < 0 || variant < 0) { |
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c index 89f046ca9e41..3d3b4addf81a 100644 --- a/drivers/mfd/rtl8411.c +++ b/drivers/mfd/rtl8411.c | |||
@@ -112,6 +112,21 @@ static int rtl8411_card_power_off(struct rtsx_pcr *pcr, int card) | |||
112 | BPP_LDO_POWB, BPP_LDO_SUSPEND); | 112 | BPP_LDO_POWB, BPP_LDO_SUSPEND); |
113 | } | 113 | } |
114 | 114 | ||
115 | static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | ||
116 | { | ||
117 | u8 mask, val; | ||
118 | |||
119 | mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK; | ||
120 | if (voltage == OUTPUT_3V3) | ||
121 | val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3; | ||
122 | else if (voltage == OUTPUT_1V8) | ||
123 | val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8; | ||
124 | else | ||
125 | return -EINVAL; | ||
126 | |||
127 | return rtsx_pci_write_register(pcr, LDO_CTL, mask, val); | ||
128 | } | ||
129 | |||
115 | static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) | 130 | static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) |
116 | { | 131 | { |
117 | unsigned int card_exist; | 132 | unsigned int card_exist; |
@@ -163,6 +178,18 @@ static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr) | |||
163 | return card_exist; | 178 | return card_exist; |
164 | } | 179 | } |
165 | 180 | ||
181 | static int rtl8411_conv_clk_and_div_n(int input, int dir) | ||
182 | { | ||
183 | int output; | ||
184 | |||
185 | if (dir == CLK_TO_DIV_N) | ||
186 | output = input * 4 / 5 - 2; | ||
187 | else | ||
188 | output = (input + 2) * 5 / 4; | ||
189 | |||
190 | return output; | ||
191 | } | ||
192 | |||
166 | static const struct pcr_ops rtl8411_pcr_ops = { | 193 | static const struct pcr_ops rtl8411_pcr_ops = { |
167 | .extra_init_hw = rtl8411_extra_init_hw, | 194 | .extra_init_hw = rtl8411_extra_init_hw, |
168 | .optimize_phy = NULL, | 195 | .optimize_phy = NULL, |
@@ -172,7 +199,9 @@ static const struct pcr_ops rtl8411_pcr_ops = { | |||
172 | .disable_auto_blink = rtl8411_disable_auto_blink, | 199 | .disable_auto_blink = rtl8411_disable_auto_blink, |
173 | .card_power_on = rtl8411_card_power_on, | 200 | .card_power_on = rtl8411_card_power_on, |
174 | .card_power_off = rtl8411_card_power_off, | 201 | .card_power_off = rtl8411_card_power_off, |
202 | .switch_output_voltage = rtl8411_switch_output_voltage, | ||
175 | .cd_deglitch = rtl8411_cd_deglitch, | 203 | .cd_deglitch = rtl8411_cd_deglitch, |
204 | .conv_clk_and_div_n = rtl8411_conv_clk_and_div_n, | ||
176 | }; | 205 | }; |
177 | 206 | ||
178 | /* SD Pull Control Enable: | 207 | /* SD Pull Control Enable: |
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c index 283a4f148084..98fe0f39463e 100644 --- a/drivers/mfd/rts5209.c +++ b/drivers/mfd/rts5209.c | |||
@@ -144,6 +144,25 @@ static int rts5209_card_power_off(struct rtsx_pcr *pcr, int card) | |||
144 | return rtsx_pci_send_cmd(pcr, 100); | 144 | return rtsx_pci_send_cmd(pcr, 100); |
145 | } | 145 | } |
146 | 146 | ||
147 | static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | ||
148 | { | ||
149 | int err; | ||
150 | |||
151 | if (voltage == OUTPUT_3V3) { | ||
152 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); | ||
153 | if (err < 0) | ||
154 | return err; | ||
155 | } else if (voltage == OUTPUT_1V8) { | ||
156 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); | ||
157 | if (err < 0) | ||
158 | return err; | ||
159 | } else { | ||
160 | return -EINVAL; | ||
161 | } | ||
162 | |||
163 | return 0; | ||
164 | } | ||
165 | |||
147 | static const struct pcr_ops rts5209_pcr_ops = { | 166 | static const struct pcr_ops rts5209_pcr_ops = { |
148 | .extra_init_hw = rts5209_extra_init_hw, | 167 | .extra_init_hw = rts5209_extra_init_hw, |
149 | .optimize_phy = rts5209_optimize_phy, | 168 | .optimize_phy = rts5209_optimize_phy, |
@@ -153,7 +172,9 @@ static const struct pcr_ops rts5209_pcr_ops = { | |||
153 | .disable_auto_blink = rts5209_disable_auto_blink, | 172 | .disable_auto_blink = rts5209_disable_auto_blink, |
154 | .card_power_on = rts5209_card_power_on, | 173 | .card_power_on = rts5209_card_power_on, |
155 | .card_power_off = rts5209_card_power_off, | 174 | .card_power_off = rts5209_card_power_off, |
175 | .switch_output_voltage = rts5209_switch_output_voltage, | ||
156 | .cd_deglitch = NULL, | 176 | .cd_deglitch = NULL, |
177 | .conv_clk_and_div_n = NULL, | ||
157 | }; | 178 | }; |
158 | 179 | ||
159 | /* SD Pull Control Enable: | 180 | /* SD Pull Control Enable: |
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c index b9dbab266fda..29d889cbb9c5 100644 --- a/drivers/mfd/rts5229.c +++ b/drivers/mfd/rts5229.c | |||
@@ -114,6 +114,25 @@ static int rts5229_card_power_off(struct rtsx_pcr *pcr, int card) | |||
114 | return rtsx_pci_send_cmd(pcr, 100); | 114 | return rtsx_pci_send_cmd(pcr, 100); |
115 | } | 115 | } |
116 | 116 | ||
117 | static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | ||
118 | { | ||
119 | int err; | ||
120 | |||
121 | if (voltage == OUTPUT_3V3) { | ||
122 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); | ||
123 | if (err < 0) | ||
124 | return err; | ||
125 | } else if (voltage == OUTPUT_1V8) { | ||
126 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); | ||
127 | if (err < 0) | ||
128 | return err; | ||
129 | } else { | ||
130 | return -EINVAL; | ||
131 | } | ||
132 | |||
133 | return 0; | ||
134 | } | ||
135 | |||
117 | static const struct pcr_ops rts5229_pcr_ops = { | 136 | static const struct pcr_ops rts5229_pcr_ops = { |
118 | .extra_init_hw = rts5229_extra_init_hw, | 137 | .extra_init_hw = rts5229_extra_init_hw, |
119 | .optimize_phy = rts5229_optimize_phy, | 138 | .optimize_phy = rts5229_optimize_phy, |
@@ -123,7 +142,9 @@ static const struct pcr_ops rts5229_pcr_ops = { | |||
123 | .disable_auto_blink = rts5229_disable_auto_blink, | 142 | .disable_auto_blink = rts5229_disable_auto_blink, |
124 | .card_power_on = rts5229_card_power_on, | 143 | .card_power_on = rts5229_card_power_on, |
125 | .card_power_off = rts5229_card_power_off, | 144 | .card_power_off = rts5229_card_power_off, |
145 | .switch_output_voltage = rts5229_switch_output_voltage, | ||
126 | .cd_deglitch = NULL, | 146 | .cd_deglitch = NULL, |
147 | .conv_clk_and_div_n = NULL, | ||
127 | }; | 148 | }; |
128 | 149 | ||
129 | /* SD Pull Control Enable: | 150 | /* SD Pull Control Enable: |
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c index 7a7b0bda4618..9fc57009e228 100644 --- a/drivers/mfd/rtsx_pcr.c +++ b/drivers/mfd/rtsx_pcr.c | |||
@@ -630,7 +630,10 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, | |||
630 | if (clk == pcr->cur_clock) | 630 | if (clk == pcr->cur_clock) |
631 | return 0; | 631 | return 0; |
632 | 632 | ||
633 | N = (u8)(clk - 2); | 633 | if (pcr->ops->conv_clk_and_div_n) |
634 | N = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N); | ||
635 | else | ||
636 | N = (u8)(clk - 2); | ||
634 | if ((clk <= 2) || (N > max_N)) | 637 | if ((clk <= 2) || (N > max_N)) |
635 | return -EINVAL; | 638 | return -EINVAL; |
636 | 639 | ||
@@ -641,7 +644,14 @@ int rtsx_pci_switch_clock(struct rtsx_pcr *pcr, unsigned int card_clock, | |||
641 | /* Make sure that the SSC clock div_n is equal or greater than min_N */ | 644 | /* Make sure that the SSC clock div_n is equal or greater than min_N */ |
642 | div = CLK_DIV_1; | 645 | div = CLK_DIV_1; |
643 | while ((N < min_N) && (div < max_div)) { | 646 | while ((N < min_N) && (div < max_div)) { |
644 | N = (N + 2) * 2 - 2; | 647 | if (pcr->ops->conv_clk_and_div_n) { |
648 | int dbl_clk = pcr->ops->conv_clk_and_div_n(N, | ||
649 | DIV_N_TO_CLK) * 2; | ||
650 | N = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk, | ||
651 | CLK_TO_DIV_N); | ||
652 | } else { | ||
653 | N = (N + 2) * 2 - 2; | ||
654 | } | ||
645 | div++; | 655 | div++; |
646 | } | 656 | } |
647 | dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div); | 657 | dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div); |
@@ -703,6 +713,15 @@ int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card) | |||
703 | } | 713 | } |
704 | EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); | 714 | EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off); |
705 | 715 | ||
716 | int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage) | ||
717 | { | ||
718 | if (pcr->ops->switch_output_voltage) | ||
719 | return pcr->ops->switch_output_voltage(pcr, voltage); | ||
720 | |||
721 | return 0; | ||
722 | } | ||
723 | EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage); | ||
724 | |||
706 | unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr) | 725 | unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr) |
707 | { | 726 | { |
708 | unsigned int val; | 727 | unsigned int val; |
@@ -767,10 +786,10 @@ static void rtsx_pci_card_detect(struct work_struct *work) | |||
767 | 786 | ||
768 | spin_unlock_irqrestore(&pcr->lock, flags); | 787 | spin_unlock_irqrestore(&pcr->lock, flags); |
769 | 788 | ||
770 | if (card_detect & SD_EXIST) | 789 | if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event) |
771 | pcr->slots[RTSX_SD_CARD].card_event( | 790 | pcr->slots[RTSX_SD_CARD].card_event( |
772 | pcr->slots[RTSX_SD_CARD].p_dev); | 791 | pcr->slots[RTSX_SD_CARD].p_dev); |
773 | if (card_detect & MS_EXIST) | 792 | if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event) |
774 | pcr->slots[RTSX_MS_CARD].card_event( | 793 | pcr->slots[RTSX_MS_CARD].card_event( |
775 | pcr->slots[RTSX_MS_CARD].p_dev); | 794 | pcr->slots[RTSX_MS_CARD].p_dev); |
776 | } | 795 | } |
diff --git a/drivers/mfd/sec-core.c b/drivers/mfd/sec-core.c index 49d361a618d0..77ee26ef5941 100644 --- a/drivers/mfd/sec-core.c +++ b/drivers/mfd/sec-core.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/err.h> | 17 | #include <linux/err.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/i2c.h> | 19 | #include <linux/i2c.h> |
20 | #include <linux/of_irq.h> | ||
20 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
21 | #include <linux/pm_runtime.h> | 22 | #include <linux/pm_runtime.h> |
22 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
@@ -60,6 +61,15 @@ static struct mfd_cell s2mps11_devs[] = { | |||
60 | }, | 61 | }, |
61 | }; | 62 | }; |
62 | 63 | ||
64 | #ifdef CONFIG_OF | ||
65 | static struct of_device_id sec_dt_match[] = { | ||
66 | { .compatible = "samsung,s5m8767-pmic", | ||
67 | .data = (void *)S5M8767X, | ||
68 | }, | ||
69 | {}, | ||
70 | }; | ||
71 | #endif | ||
72 | |||
63 | int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest) | 73 | int sec_reg_read(struct sec_pmic_dev *sec_pmic, u8 reg, void *dest) |
64 | { | 74 | { |
65 | return regmap_read(sec_pmic->regmap, reg, dest); | 75 | return regmap_read(sec_pmic->regmap, reg, dest); |
@@ -95,6 +105,57 @@ static struct regmap_config sec_regmap_config = { | |||
95 | .val_bits = 8, | 105 | .val_bits = 8, |
96 | }; | 106 | }; |
97 | 107 | ||
108 | |||
109 | #ifdef CONFIG_OF | ||
110 | /* | ||
111 | * Only the common platform data elements for s5m8767 are parsed here from the | ||
112 | * device tree. Other sub-modules of s5m8767 such as pmic, rtc , charger and | ||
113 | * others have to parse their own platform data elements from device tree. | ||
114 | * | ||
115 | * The s5m8767 platform data structure is instantiated here and the drivers for | ||
116 | * the sub-modules need not instantiate another instance while parsing their | ||
117 | * platform data. | ||
118 | */ | ||
119 | static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( | ||
120 | struct device *dev) | ||
121 | { | ||
122 | struct sec_platform_data *pd; | ||
123 | |||
124 | pd = devm_kzalloc(dev, sizeof(*pd), GFP_KERNEL); | ||
125 | if (!pd) { | ||
126 | dev_err(dev, "could not allocate memory for pdata\n"); | ||
127 | return ERR_PTR(-ENOMEM); | ||
128 | } | ||
129 | |||
130 | /* | ||
131 | * ToDo: the 'wakeup' member in the platform data is more of a linux | ||
132 | * specfic information. Hence, there is no binding for that yet and | ||
133 | * not parsed here. | ||
134 | */ | ||
135 | |||
136 | return pd; | ||
137 | } | ||
138 | #else | ||
139 | static struct sec_platform_data *sec_pmic_i2c_parse_dt_pdata( | ||
140 | struct device *dev) | ||
141 | { | ||
142 | return 0; | ||
143 | } | ||
144 | #endif | ||
145 | |||
146 | static inline int sec_i2c_get_driver_data(struct i2c_client *i2c, | ||
147 | const struct i2c_device_id *id) | ||
148 | { | ||
149 | #ifdef CONFIG_OF | ||
150 | if (i2c->dev.of_node) { | ||
151 | const struct of_device_id *match; | ||
152 | match = of_match_node(sec_dt_match, i2c->dev.of_node); | ||
153 | return (int)match->data; | ||
154 | } | ||
155 | #endif | ||
156 | return (int)id->driver_data; | ||
157 | } | ||
158 | |||
98 | static int sec_pmic_probe(struct i2c_client *i2c, | 159 | static int sec_pmic_probe(struct i2c_client *i2c, |
99 | const struct i2c_device_id *id) | 160 | const struct i2c_device_id *id) |
100 | { | 161 | { |
@@ -111,13 +172,22 @@ static int sec_pmic_probe(struct i2c_client *i2c, | |||
111 | sec_pmic->dev = &i2c->dev; | 172 | sec_pmic->dev = &i2c->dev; |
112 | sec_pmic->i2c = i2c; | 173 | sec_pmic->i2c = i2c; |
113 | sec_pmic->irq = i2c->irq; | 174 | sec_pmic->irq = i2c->irq; |
114 | sec_pmic->type = id->driver_data; | 175 | sec_pmic->type = sec_i2c_get_driver_data(i2c, id); |
115 | 176 | ||
177 | if (sec_pmic->dev->of_node) { | ||
178 | pdata = sec_pmic_i2c_parse_dt_pdata(sec_pmic->dev); | ||
179 | if (IS_ERR(pdata)) { | ||
180 | ret = PTR_ERR(pdata); | ||
181 | return ret; | ||
182 | } | ||
183 | pdata->device_type = sec_pmic->type; | ||
184 | } | ||
116 | if (pdata) { | 185 | if (pdata) { |
117 | sec_pmic->device_type = pdata->device_type; | 186 | sec_pmic->device_type = pdata->device_type; |
118 | sec_pmic->ono = pdata->ono; | 187 | sec_pmic->ono = pdata->ono; |
119 | sec_pmic->irq_base = pdata->irq_base; | 188 | sec_pmic->irq_base = pdata->irq_base; |
120 | sec_pmic->wakeup = pdata->wakeup; | 189 | sec_pmic->wakeup = pdata->wakeup; |
190 | sec_pmic->pdata = pdata; | ||
121 | } | 191 | } |
122 | 192 | ||
123 | sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); | 193 | sec_pmic->regmap = devm_regmap_init_i2c(i2c, &sec_regmap_config); |
@@ -192,6 +262,7 @@ static struct i2c_driver sec_pmic_driver = { | |||
192 | .driver = { | 262 | .driver = { |
193 | .name = "sec_pmic", | 263 | .name = "sec_pmic", |
194 | .owner = THIS_MODULE, | 264 | .owner = THIS_MODULE, |
265 | .of_match_table = of_match_ptr(sec_dt_match), | ||
195 | }, | 266 | }, |
196 | .probe = sec_pmic_probe, | 267 | .probe = sec_pmic_probe, |
197 | .remove = sec_pmic_remove, | 268 | .remove = sec_pmic_remove, |
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c index a06d66b929b1..ecc092c7f745 100644 --- a/drivers/mfd/tc3589x.c +++ b/drivers/mfd/tc3589x.c | |||
@@ -219,25 +219,18 @@ static void tc3589x_irq_unmap(struct irq_domain *d, unsigned int virq) | |||
219 | } | 219 | } |
220 | 220 | ||
221 | static struct irq_domain_ops tc3589x_irq_ops = { | 221 | static struct irq_domain_ops tc3589x_irq_ops = { |
222 | .map = tc3589x_irq_map, | 222 | .map = tc3589x_irq_map, |
223 | .unmap = tc3589x_irq_unmap, | 223 | .unmap = tc3589x_irq_unmap, |
224 | .xlate = irq_domain_xlate_twocell, | 224 | .xlate = irq_domain_xlate_twocell, |
225 | }; | 225 | }; |
226 | 226 | ||
227 | static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np) | 227 | static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np) |
228 | { | 228 | { |
229 | int base = tc3589x->irq_base; | 229 | int base = tc3589x->irq_base; |
230 | 230 | ||
231 | if (base) { | 231 | tc3589x->domain = irq_domain_add_simple( |
232 | tc3589x->domain = irq_domain_add_legacy( | 232 | np, TC3589x_NR_INTERNAL_IRQS, base, |
233 | NULL, TC3589x_NR_INTERNAL_IRQS, base, | 233 | &tc3589x_irq_ops, tc3589x); |
234 | 0, &tc3589x_irq_ops, tc3589x); | ||
235 | } | ||
236 | else { | ||
237 | tc3589x->domain = irq_domain_add_linear( | ||
238 | np, TC3589x_NR_INTERNAL_IRQS, | ||
239 | &tc3589x_irq_ops, tc3589x); | ||
240 | } | ||
241 | 234 | ||
242 | if (!tc3589x->domain) { | 235 | if (!tc3589x->domain) { |
243 | dev_err(tc3589x->dev, "Failed to create irqdomain\n"); | 236 | dev_err(tc3589x->dev, "Failed to create irqdomain\n"); |
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c index 4dae241e5017..dd362c1078e1 100644 --- a/drivers/mfd/twl4030-power.c +++ b/drivers/mfd/twl4030-power.c | |||
@@ -159,7 +159,7 @@ out: | |||
159 | static int twl4030_write_script(u8 address, struct twl4030_ins *script, | 159 | static int twl4030_write_script(u8 address, struct twl4030_ins *script, |
160 | int len) | 160 | int len) |
161 | { | 161 | { |
162 | int err; | 162 | int err = -EINVAL; |
163 | 163 | ||
164 | for (; len; len--, address++, script++) { | 164 | for (; len; len--, address++, script++) { |
165 | if (len == 1) { | 165 | if (len == 1) { |
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c index fae15d880758..3c1723aa6225 100644 --- a/drivers/mfd/vexpress-config.c +++ b/drivers/mfd/vexpress-config.c | |||
@@ -67,6 +67,7 @@ struct vexpress_config_bridge *vexpress_config_bridge_register( | |||
67 | 67 | ||
68 | return bridge; | 68 | return bridge; |
69 | } | 69 | } |
70 | EXPORT_SYMBOL(vexpress_config_bridge_register); | ||
70 | 71 | ||
71 | void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) | 72 | void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) |
72 | { | 73 | { |
@@ -83,6 +84,7 @@ void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge) | |||
83 | while (!list_empty(&__bridge.transactions)) | 84 | while (!list_empty(&__bridge.transactions)) |
84 | cpu_relax(); | 85 | cpu_relax(); |
85 | } | 86 | } |
87 | EXPORT_SYMBOL(vexpress_config_bridge_unregister); | ||
86 | 88 | ||
87 | 89 | ||
88 | struct vexpress_config_func { | 90 | struct vexpress_config_func { |
@@ -142,6 +144,7 @@ struct vexpress_config_func *__vexpress_config_func_get(struct device *dev, | |||
142 | 144 | ||
143 | return func; | 145 | return func; |
144 | } | 146 | } |
147 | EXPORT_SYMBOL(__vexpress_config_func_get); | ||
145 | 148 | ||
146 | void vexpress_config_func_put(struct vexpress_config_func *func) | 149 | void vexpress_config_func_put(struct vexpress_config_func *func) |
147 | { | 150 | { |
@@ -149,7 +152,7 @@ void vexpress_config_func_put(struct vexpress_config_func *func) | |||
149 | of_node_put(func->bridge->node); | 152 | of_node_put(func->bridge->node); |
150 | kfree(func); | 153 | kfree(func); |
151 | } | 154 | } |
152 | 155 | EXPORT_SYMBOL(vexpress_config_func_put); | |
153 | 156 | ||
154 | struct vexpress_config_trans { | 157 | struct vexpress_config_trans { |
155 | struct vexpress_config_func *func; | 158 | struct vexpress_config_func *func; |
@@ -229,6 +232,7 @@ void vexpress_config_complete(struct vexpress_config_bridge *bridge, | |||
229 | 232 | ||
230 | complete(&trans->completion); | 233 | complete(&trans->completion); |
231 | } | 234 | } |
235 | EXPORT_SYMBOL(vexpress_config_complete); | ||
232 | 236 | ||
233 | int vexpress_config_wait(struct vexpress_config_trans *trans) | 237 | int vexpress_config_wait(struct vexpress_config_trans *trans) |
234 | { | 238 | { |
@@ -236,7 +240,7 @@ int vexpress_config_wait(struct vexpress_config_trans *trans) | |||
236 | 240 | ||
237 | return trans->status; | 241 | return trans->status; |
238 | } | 242 | } |
239 | 243 | EXPORT_SYMBOL(vexpress_config_wait); | |
240 | 244 | ||
241 | int vexpress_config_read(struct vexpress_config_func *func, int offset, | 245 | int vexpress_config_read(struct vexpress_config_func *func, int offset, |
242 | u32 *data) | 246 | u32 *data) |
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c index e5d8f63b252a..77048b18439e 100644 --- a/drivers/mfd/vexpress-sysreg.c +++ b/drivers/mfd/vexpress-sysreg.c | |||
@@ -313,19 +313,11 @@ static void vexpress_sysreg_config_complete(unsigned long data) | |||
313 | } | 313 | } |
314 | 314 | ||
315 | 315 | ||
316 | void __init vexpress_sysreg_early_init(void __iomem *base) | 316 | void __init vexpress_sysreg_setup(struct device_node *node) |
317 | { | 317 | { |
318 | struct device_node *node = of_find_compatible_node(NULL, NULL, | 318 | if (WARN_ON(!vexpress_sysreg_base)) |
319 | "arm,vexpress-sysreg"); | ||
320 | |||
321 | if (node) | ||
322 | base = of_iomap(node, 0); | ||
323 | |||
324 | if (WARN_ON(!base)) | ||
325 | return; | 319 | return; |
326 | 320 | ||
327 | vexpress_sysreg_base = base; | ||
328 | |||
329 | if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) | 321 | if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE) |
330 | vexpress_master_site = VEXPRESS_SITE_DB2; | 322 | vexpress_master_site = VEXPRESS_SITE_DB2; |
331 | else | 323 | else |
@@ -336,9 +328,23 @@ void __init vexpress_sysreg_early_init(void __iomem *base) | |||
336 | WARN_ON(!vexpress_sysreg_config_bridge); | 328 | WARN_ON(!vexpress_sysreg_config_bridge); |
337 | } | 329 | } |
338 | 330 | ||
331 | void __init vexpress_sysreg_early_init(void __iomem *base) | ||
332 | { | ||
333 | vexpress_sysreg_base = base; | ||
334 | vexpress_sysreg_setup(NULL); | ||
335 | } | ||
336 | |||
339 | void __init vexpress_sysreg_of_early_init(void) | 337 | void __init vexpress_sysreg_of_early_init(void) |
340 | { | 338 | { |
341 | vexpress_sysreg_early_init(NULL); | 339 | struct device_node *node = of_find_compatible_node(NULL, NULL, |
340 | "arm,vexpress-sysreg"); | ||
341 | |||
342 | if (node) { | ||
343 | vexpress_sysreg_base = of_iomap(node, 0); | ||
344 | vexpress_sysreg_setup(node); | ||
345 | } else { | ||
346 | pr_info("vexpress-sysreg: No Device Tree node found."); | ||
347 | } | ||
342 | } | 348 | } |
343 | 349 | ||
344 | 350 | ||
@@ -426,9 +432,11 @@ static int vexpress_sysreg_probe(struct platform_device *pdev) | |||
426 | return -EBUSY; | 432 | return -EBUSY; |
427 | } | 433 | } |
428 | 434 | ||
429 | if (!vexpress_sysreg_base) | 435 | if (!vexpress_sysreg_base) { |
430 | vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, | 436 | vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start, |
431 | resource_size(res)); | 437 | resource_size(res)); |
438 | vexpress_sysreg_setup(pdev->dev.of_node); | ||
439 | } | ||
432 | 440 | ||
433 | if (!vexpress_sysreg_base) { | 441 | if (!vexpress_sysreg_base) { |
434 | dev_err(&pdev->dev, "Failed to obtain base address!\n"); | 442 | dev_err(&pdev->dev, "Failed to obtain base address!\n"); |
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c index 088872ab6338..f6fcb87b3504 100644 --- a/drivers/mfd/wm5102-tables.c +++ b/drivers/mfd/wm5102-tables.c | |||
@@ -96,6 +96,7 @@ const struct regmap_irq_chip wm5102_aod = { | |||
96 | .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, | 96 | .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, |
97 | .ack_base = ARIZONA_AOD_IRQ1, | 97 | .ack_base = ARIZONA_AOD_IRQ1, |
98 | .wake_base = ARIZONA_WAKE_CONTROL, | 98 | .wake_base = ARIZONA_WAKE_CONTROL, |
99 | .wake_invert = 1, | ||
99 | .num_regs = 1, | 100 | .num_regs = 1, |
100 | .irqs = wm5102_aod_irqs, | 101 | .irqs = wm5102_aod_irqs, |
101 | .num_irqs = ARRAY_SIZE(wm5102_aod_irqs), | 102 | .num_irqs = ARRAY_SIZE(wm5102_aod_irqs), |
@@ -1882,7 +1883,7 @@ static bool wm5102_volatile_register(struct device *dev, unsigned int reg) | |||
1882 | } | 1883 | } |
1883 | } | 1884 | } |
1884 | 1885 | ||
1885 | #define WM5102_MAX_REGISTER 0x1a8fff | 1886 | #define WM5102_MAX_REGISTER 0x1a9800 |
1886 | 1887 | ||
1887 | const struct regmap_config wm5102_spi_regmap = { | 1888 | const struct regmap_config wm5102_spi_regmap = { |
1888 | .reg_bits = 32, | 1889 | .reg_bits = 32, |
diff --git a/drivers/mfd/wm5110-tables.c b/drivers/mfd/wm5110-tables.c index adda6b10b90d..c41599815299 100644 --- a/drivers/mfd/wm5110-tables.c +++ b/drivers/mfd/wm5110-tables.c | |||
@@ -255,6 +255,7 @@ const struct regmap_irq_chip wm5110_aod = { | |||
255 | .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, | 255 | .mask_base = ARIZONA_AOD_IRQ_MASK_IRQ1, |
256 | .ack_base = ARIZONA_AOD_IRQ1, | 256 | .ack_base = ARIZONA_AOD_IRQ1, |
257 | .wake_base = ARIZONA_WAKE_CONTROL, | 257 | .wake_base = ARIZONA_WAKE_CONTROL, |
258 | .wake_invert = 1, | ||
258 | .num_regs = 1, | 259 | .num_regs = 1, |
259 | .irqs = wm5110_aod_irqs, | 260 | .irqs = wm5110_aod_irqs, |
260 | .num_irqs = ARRAY_SIZE(wm5110_aod_irqs), | 261 | .num_irqs = ARRAY_SIZE(wm5110_aod_irqs), |
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c index 158da5a81a66..3c09cbb70b1d 100644 --- a/drivers/misc/atmel-ssc.c +++ b/drivers/misc/atmel-ssc.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | 20 | ||
21 | #include <linux/of.h> | 21 | #include <linux/of.h> |
22 | #include <linux/pinctrl/consumer.h> | ||
22 | 23 | ||
23 | /* Serialize access to ssc_list and user count */ | 24 | /* Serialize access to ssc_list and user count */ |
24 | static DEFINE_SPINLOCK(user_lock); | 25 | static DEFINE_SPINLOCK(user_lock); |
@@ -131,6 +132,13 @@ static int ssc_probe(struct platform_device *pdev) | |||
131 | struct resource *regs; | 132 | struct resource *regs; |
132 | struct ssc_device *ssc; | 133 | struct ssc_device *ssc; |
133 | const struct atmel_ssc_platform_data *plat_dat; | 134 | const struct atmel_ssc_platform_data *plat_dat; |
135 | struct pinctrl *pinctrl; | ||
136 | |||
137 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
138 | if (IS_ERR(pinctrl)) { | ||
139 | dev_err(&pdev->dev, "Failed to request pinctrl\n"); | ||
140 | return PTR_ERR(pinctrl); | ||
141 | } | ||
134 | 142 | ||
135 | ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); | 143 | ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL); |
136 | if (!ssc) { | 144 | if (!ssc) { |
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 18794aea6062..e40ffd9502d1 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -187,13 +187,13 @@ int mei_amthif_read(struct mei_device *dev, struct file *file, | |||
187 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, | 187 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, |
188 | (cb = mei_amthif_find_read_list_entry(dev, file))); | 188 | (cb = mei_amthif_find_read_list_entry(dev, file))); |
189 | 189 | ||
190 | /* Locking again the Mutex */ | ||
191 | mutex_lock(&dev->device_lock); | ||
192 | |||
190 | if (wait_ret) | 193 | if (wait_ret) |
191 | return -ERESTARTSYS; | 194 | return -ERESTARTSYS; |
192 | 195 | ||
193 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); | 196 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); |
194 | |||
195 | /* Locking again the Mutex */ | ||
196 | mutex_lock(&dev->device_lock); | ||
197 | } | 197 | } |
198 | 198 | ||
199 | 199 | ||
diff --git a/drivers/misc/sgi-gru/grufile.c b/drivers/misc/sgi-gru/grufile.c index 492c8cac69ac..44d273c5e19d 100644 --- a/drivers/misc/sgi-gru/grufile.c +++ b/drivers/misc/sgi-gru/grufile.c | |||
@@ -517,7 +517,7 @@ static int __init gru_init(void) | |||
517 | { | 517 | { |
518 | int ret; | 518 | int ret; |
519 | 519 | ||
520 | if (!is_uv_system()) | 520 | if (!is_uv_system() || (is_uvx_hub() && !is_uv2_hub())) |
521 | return 0; | 521 | return 0; |
522 | 522 | ||
523 | #if defined CONFIG_IA64 | 523 | #if defined CONFIG_IA64 |
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c index 9ff942a346ed..83269f1d16e3 100644 --- a/drivers/misc/ti-st/st_kim.c +++ b/drivers/misc/ti-st/st_kim.c | |||
@@ -468,6 +468,11 @@ long st_kim_start(void *kim_data) | |||
468 | if (pdata->chip_enable) | 468 | if (pdata->chip_enable) |
469 | pdata->chip_enable(kim_gdata); | 469 | pdata->chip_enable(kim_gdata); |
470 | 470 | ||
471 | /* Configure BT nShutdown to HIGH state */ | ||
472 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
473 | mdelay(5); /* FIXME: a proper toggle */ | ||
474 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
475 | mdelay(100); | ||
471 | /* re-initialize the completion */ | 476 | /* re-initialize the completion */ |
472 | INIT_COMPLETION(kim_gdata->ldisc_installed); | 477 | INIT_COMPLETION(kim_gdata->ldisc_installed); |
473 | /* send notification to UIM */ | 478 | /* send notification to UIM */ |
@@ -509,7 +514,8 @@ long st_kim_start(void *kim_data) | |||
509 | * (b) upon failure to either install ldisc or download firmware. | 514 | * (b) upon failure to either install ldisc or download firmware. |
510 | * The function is responsible to (a) notify UIM about un-installation, | 515 | * The function is responsible to (a) notify UIM about un-installation, |
511 | * (b) flush UART if the ldisc was installed. | 516 | * (b) flush UART if the ldisc was installed. |
512 | * (c) invoke platform's chip disabling routine. | 517 | * (c) reset BT_EN - pull down nshutdown at the end. |
518 | * (d) invoke platform's chip disabling routine. | ||
513 | */ | 519 | */ |
514 | long st_kim_stop(void *kim_data) | 520 | long st_kim_stop(void *kim_data) |
515 | { | 521 | { |
@@ -541,6 +547,13 @@ long st_kim_stop(void *kim_data) | |||
541 | err = -ETIMEDOUT; | 547 | err = -ETIMEDOUT; |
542 | } | 548 | } |
543 | 549 | ||
550 | /* By default configure BT nShutdown to LOW state */ | ||
551 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
552 | mdelay(1); | ||
553 | gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH); | ||
554 | mdelay(1); | ||
555 | gpio_set_value(kim_gdata->nshutdown, GPIO_LOW); | ||
556 | |||
544 | /* platform specific disable */ | 557 | /* platform specific disable */ |
545 | if (pdata->chip_disable) | 558 | if (pdata->chip_disable) |
546 | pdata->chip_disable(kim_gdata); | 559 | pdata->chip_disable(kim_gdata); |
@@ -733,6 +746,20 @@ static int kim_probe(struct platform_device *pdev) | |||
733 | /* refer to itself */ | 746 | /* refer to itself */ |
734 | kim_gdata->core_data->kim_data = kim_gdata; | 747 | kim_gdata->core_data->kim_data = kim_gdata; |
735 | 748 | ||
749 | /* Claim the chip enable nShutdown gpio from the system */ | ||
750 | kim_gdata->nshutdown = pdata->nshutdown_gpio; | ||
751 | err = gpio_request(kim_gdata->nshutdown, "kim"); | ||
752 | if (unlikely(err)) { | ||
753 | pr_err(" gpio %ld request failed ", kim_gdata->nshutdown); | ||
754 | return err; | ||
755 | } | ||
756 | |||
757 | /* Configure nShutdown GPIO as output=0 */ | ||
758 | err = gpio_direction_output(kim_gdata->nshutdown, 0); | ||
759 | if (unlikely(err)) { | ||
760 | pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown); | ||
761 | return err; | ||
762 | } | ||
736 | /* get reference of pdev for request_firmware | 763 | /* get reference of pdev for request_firmware |
737 | */ | 764 | */ |
738 | kim_gdata->kim_pdev = pdev; | 765 | kim_gdata->kim_pdev = pdev; |
@@ -779,10 +806,18 @@ err_core_init: | |||
779 | 806 | ||
780 | static int kim_remove(struct platform_device *pdev) | 807 | static int kim_remove(struct platform_device *pdev) |
781 | { | 808 | { |
809 | /* free the GPIOs requested */ | ||
810 | struct ti_st_plat_data *pdata = pdev->dev.platform_data; | ||
782 | struct kim_data_s *kim_gdata; | 811 | struct kim_data_s *kim_gdata; |
783 | 812 | ||
784 | kim_gdata = dev_get_drvdata(&pdev->dev); | 813 | kim_gdata = dev_get_drvdata(&pdev->dev); |
785 | 814 | ||
815 | /* Free the Bluetooth/FM/GPIO | ||
816 | * nShutdown gpio from the system | ||
817 | */ | ||
818 | gpio_free(pdata->nshutdown_gpio); | ||
819 | pr_info("nshutdown GPIO Freed"); | ||
820 | |||
786 | debugfs_remove_recursive(kim_debugfs_dir); | 821 | debugfs_remove_recursive(kim_debugfs_dir); |
787 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); | 822 | sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp); |
788 | pr_info("sysfs entries removed"); | 823 | pr_info("sysfs entries removed"); |
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index de4c20b3936c..f8dd36102949 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
@@ -50,8 +50,6 @@ struct mvsd_host { | |||
50 | struct timer_list timer; | 50 | struct timer_list timer; |
51 | struct mmc_host *mmc; | 51 | struct mmc_host *mmc; |
52 | struct device *dev; | 52 | struct device *dev; |
53 | struct resource *res; | ||
54 | int irq; | ||
55 | struct clk *clk; | 53 | struct clk *clk; |
56 | int gpio_card_detect; | 54 | int gpio_card_detect; |
57 | int gpio_write_protect; | 55 | int gpio_write_protect; |
@@ -718,10 +716,6 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
718 | if (!r || irq < 0 || !mvsd_data) | 716 | if (!r || irq < 0 || !mvsd_data) |
719 | return -ENXIO; | 717 | return -ENXIO; |
720 | 718 | ||
721 | r = request_mem_region(r->start, SZ_1K, DRIVER_NAME); | ||
722 | if (!r) | ||
723 | return -EBUSY; | ||
724 | |||
725 | mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); | 719 | mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev); |
726 | if (!mmc) { | 720 | if (!mmc) { |
727 | ret = -ENOMEM; | 721 | ret = -ENOMEM; |
@@ -731,8 +725,8 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
731 | host = mmc_priv(mmc); | 725 | host = mmc_priv(mmc); |
732 | host->mmc = mmc; | 726 | host->mmc = mmc; |
733 | host->dev = &pdev->dev; | 727 | host->dev = &pdev->dev; |
734 | host->res = r; | ||
735 | host->base_clock = mvsd_data->clock / 2; | 728 | host->base_clock = mvsd_data->clock / 2; |
729 | host->clk = ERR_PTR(-EINVAL); | ||
736 | 730 | ||
737 | mmc->ops = &mvsd_ops; | 731 | mmc->ops = &mvsd_ops; |
738 | 732 | ||
@@ -752,7 +746,7 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
752 | 746 | ||
753 | spin_lock_init(&host->lock); | 747 | spin_lock_init(&host->lock); |
754 | 748 | ||
755 | host->base = ioremap(r->start, SZ_4K); | 749 | host->base = devm_request_and_ioremap(&pdev->dev, r); |
756 | if (!host->base) { | 750 | if (!host->base) { |
757 | ret = -ENOMEM; | 751 | ret = -ENOMEM; |
758 | goto out; | 752 | goto out; |
@@ -765,44 +759,45 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
765 | 759 | ||
766 | mvsd_power_down(host); | 760 | mvsd_power_down(host); |
767 | 761 | ||
768 | ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host); | 762 | ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host); |
769 | if (ret) { | 763 | if (ret) { |
770 | pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); | 764 | pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq); |
771 | goto out; | 765 | goto out; |
772 | } else | 766 | } |
773 | host->irq = irq; | ||
774 | 767 | ||
775 | /* Not all platforms can gate the clock, so it is not | 768 | /* Not all platforms can gate the clock, so it is not |
776 | an error if the clock does not exists. */ | 769 | an error if the clock does not exists. */ |
777 | host->clk = clk_get(&pdev->dev, NULL); | 770 | host->clk = devm_clk_get(&pdev->dev, NULL); |
778 | if (!IS_ERR(host->clk)) { | 771 | if (!IS_ERR(host->clk)) |
779 | clk_prepare_enable(host->clk); | 772 | clk_prepare_enable(host->clk); |
780 | } | ||
781 | 773 | ||
782 | if (mvsd_data->gpio_card_detect) { | 774 | if (mvsd_data->gpio_card_detect) { |
783 | ret = gpio_request(mvsd_data->gpio_card_detect, | 775 | ret = devm_gpio_request_one(&pdev->dev, |
784 | DRIVER_NAME " cd"); | 776 | mvsd_data->gpio_card_detect, |
777 | GPIOF_IN, DRIVER_NAME " cd"); | ||
785 | if (ret == 0) { | 778 | if (ret == 0) { |
786 | gpio_direction_input(mvsd_data->gpio_card_detect); | ||
787 | irq = gpio_to_irq(mvsd_data->gpio_card_detect); | 779 | irq = gpio_to_irq(mvsd_data->gpio_card_detect); |
788 | ret = request_irq(irq, mvsd_card_detect_irq, | 780 | ret = devm_request_irq(&pdev->dev, irq, |
789 | IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING, | 781 | mvsd_card_detect_irq, |
790 | DRIVER_NAME " cd", host); | 782 | IRQ_TYPE_EDGE_RISING | |
783 | IRQ_TYPE_EDGE_FALLING, | ||
784 | DRIVER_NAME " cd", host); | ||
791 | if (ret == 0) | 785 | if (ret == 0) |
792 | host->gpio_card_detect = | 786 | host->gpio_card_detect = |
793 | mvsd_data->gpio_card_detect; | 787 | mvsd_data->gpio_card_detect; |
794 | else | 788 | else |
795 | gpio_free(mvsd_data->gpio_card_detect); | 789 | devm_gpio_free(&pdev->dev, |
790 | mvsd_data->gpio_card_detect); | ||
796 | } | 791 | } |
797 | } | 792 | } |
798 | if (!host->gpio_card_detect) | 793 | if (!host->gpio_card_detect) |
799 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 794 | mmc->caps |= MMC_CAP_NEEDS_POLL; |
800 | 795 | ||
801 | if (mvsd_data->gpio_write_protect) { | 796 | if (mvsd_data->gpio_write_protect) { |
802 | ret = gpio_request(mvsd_data->gpio_write_protect, | 797 | ret = devm_gpio_request_one(&pdev->dev, |
803 | DRIVER_NAME " wp"); | 798 | mvsd_data->gpio_write_protect, |
799 | GPIOF_IN, DRIVER_NAME " wp"); | ||
804 | if (ret == 0) { | 800 | if (ret == 0) { |
805 | gpio_direction_input(mvsd_data->gpio_write_protect); | ||
806 | host->gpio_write_protect = | 801 | host->gpio_write_protect = |
807 | mvsd_data->gpio_write_protect; | 802 | mvsd_data->gpio_write_protect; |
808 | } | 803 | } |
@@ -824,26 +819,11 @@ static int __init mvsd_probe(struct platform_device *pdev) | |||
824 | return 0; | 819 | return 0; |
825 | 820 | ||
826 | out: | 821 | out: |
827 | if (host) { | 822 | if (mmc) { |
828 | if (host->irq) | 823 | if (!IS_ERR(host->clk)) |
829 | free_irq(host->irq, host); | ||
830 | if (host->gpio_card_detect) { | ||
831 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | ||
832 | gpio_free(host->gpio_card_detect); | ||
833 | } | ||
834 | if (host->gpio_write_protect) | ||
835 | gpio_free(host->gpio_write_protect); | ||
836 | if (host->base) | ||
837 | iounmap(host->base); | ||
838 | } | ||
839 | if (r) | ||
840 | release_resource(r); | ||
841 | if (mmc) | ||
842 | if (!IS_ERR_OR_NULL(host->clk)) { | ||
843 | clk_disable_unprepare(host->clk); | 824 | clk_disable_unprepare(host->clk); |
844 | clk_put(host->clk); | ||
845 | } | ||
846 | mmc_free_host(mmc); | 825 | mmc_free_host(mmc); |
826 | } | ||
847 | 827 | ||
848 | return ret; | 828 | return ret; |
849 | } | 829 | } |
@@ -852,28 +832,16 @@ static int __exit mvsd_remove(struct platform_device *pdev) | |||
852 | { | 832 | { |
853 | struct mmc_host *mmc = platform_get_drvdata(pdev); | 833 | struct mmc_host *mmc = platform_get_drvdata(pdev); |
854 | 834 | ||
855 | if (mmc) { | 835 | struct mvsd_host *host = mmc_priv(mmc); |
856 | struct mvsd_host *host = mmc_priv(mmc); | ||
857 | 836 | ||
858 | if (host->gpio_card_detect) { | 837 | mmc_remove_host(mmc); |
859 | free_irq(gpio_to_irq(host->gpio_card_detect), host); | 838 | del_timer_sync(&host->timer); |
860 | gpio_free(host->gpio_card_detect); | 839 | mvsd_power_down(host); |
861 | } | 840 | |
862 | mmc_remove_host(mmc); | 841 | if (!IS_ERR(host->clk)) |
863 | free_irq(host->irq, host); | 842 | clk_disable_unprepare(host->clk); |
864 | if (host->gpio_write_protect) | 843 | mmc_free_host(mmc); |
865 | gpio_free(host->gpio_write_protect); | ||
866 | del_timer_sync(&host->timer); | ||
867 | mvsd_power_down(host); | ||
868 | iounmap(host->base); | ||
869 | release_resource(host->res); | ||
870 | 844 | ||
871 | if (!IS_ERR(host->clk)) { | ||
872 | clk_disable_unprepare(host->clk); | ||
873 | clk_put(host->clk); | ||
874 | } | ||
875 | mmc_free_host(mmc); | ||
876 | } | ||
877 | platform_set_drvdata(pdev, NULL); | 845 | platform_set_drvdata(pdev, NULL); |
878 | return 0; | 846 | return 0; |
879 | } | 847 | } |
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c index 571915dfb218..f74b5adca642 100644 --- a/drivers/mmc/host/rtsx_pci_sdmmc.c +++ b/drivers/mmc/host/rtsx_pci_sdmmc.c | |||
@@ -1060,26 +1060,6 @@ static int sd_wait_voltage_stable_2(struct realtek_pci_sdmmc *host) | |||
1060 | return 0; | 1060 | return 0; |
1061 | } | 1061 | } |
1062 | 1062 | ||
1063 | static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage) | ||
1064 | { | ||
1065 | struct rtsx_pcr *pcr = host->pcr; | ||
1066 | int err; | ||
1067 | |||
1068 | if (voltage == SD_IO_3V3) { | ||
1069 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24); | ||
1070 | if (err < 0) | ||
1071 | return err; | ||
1072 | } else if (voltage == SD_IO_1V8) { | ||
1073 | err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24); | ||
1074 | if (err < 0) | ||
1075 | return err; | ||
1076 | } else { | ||
1077 | return -EINVAL; | ||
1078 | } | ||
1079 | |||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | 1063 | static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) |
1084 | { | 1064 | { |
1085 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); | 1065 | struct realtek_pci_sdmmc *host = mmc_priv(mmc); |
@@ -1098,11 +1078,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1098 | rtsx_pci_start_run(pcr); | 1078 | rtsx_pci_start_run(pcr); |
1099 | 1079 | ||
1100 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) | 1080 | if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330) |
1101 | voltage = SD_IO_3V3; | 1081 | voltage = OUTPUT_3V3; |
1102 | else | 1082 | else |
1103 | voltage = SD_IO_1V8; | 1083 | voltage = OUTPUT_1V8; |
1104 | 1084 | ||
1105 | if (voltage == SD_IO_1V8) { | 1085 | if (voltage == OUTPUT_1V8) { |
1106 | err = rtsx_pci_write_register(pcr, | 1086 | err = rtsx_pci_write_register(pcr, |
1107 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); | 1087 | SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B); |
1108 | if (err < 0) | 1088 | if (err < 0) |
@@ -1113,11 +1093,11 @@ static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios) | |||
1113 | goto out; | 1093 | goto out; |
1114 | } | 1094 | } |
1115 | 1095 | ||
1116 | err = sd_change_bank_voltage(host, voltage); | 1096 | err = rtsx_pci_switch_output_voltage(pcr, voltage); |
1117 | if (err < 0) | 1097 | if (err < 0) |
1118 | goto out; | 1098 | goto out; |
1119 | 1099 | ||
1120 | if (voltage == SD_IO_1V8) { | 1100 | if (voltage == OUTPUT_1V8) { |
1121 | err = sd_wait_voltage_stable_2(host); | 1101 | err = sd_wait_voltage_stable_2(host); |
1122 | if (err < 0) | 1102 | if (err < 0) |
1123 | goto out; | 1103 | goto out; |
diff --git a/drivers/mtd/devices/Kconfig b/drivers/mtd/devices/Kconfig index 27f80cd8aef3..46dcb54c32ec 100644 --- a/drivers/mtd/devices/Kconfig +++ b/drivers/mtd/devices/Kconfig | |||
@@ -272,6 +272,7 @@ config MTD_DOCG3 | |||
272 | tristate "M-Systems Disk-On-Chip G3" | 272 | tristate "M-Systems Disk-On-Chip G3" |
273 | select BCH | 273 | select BCH |
274 | select BCH_CONST_PARAMS | 274 | select BCH_CONST_PARAMS |
275 | select BITREVERSE | ||
275 | ---help--- | 276 | ---help--- |
276 | This provides an MTD device driver for the M-Systems DiskOnChip | 277 | This provides an MTD device driver for the M-Systems DiskOnChip |
277 | G3 devices. | 278 | G3 devices. |
diff --git a/drivers/mtd/maps/physmap_of.c b/drivers/mtd/maps/physmap_of.c index 67cc73c18ddd..7901d72c9242 100644 --- a/drivers/mtd/maps/physmap_of.c +++ b/drivers/mtd/maps/physmap_of.c | |||
@@ -170,7 +170,7 @@ static int of_flash_probe(struct platform_device *dev) | |||
170 | resource_size_t res_size; | 170 | resource_size_t res_size; |
171 | struct mtd_part_parser_data ppdata; | 171 | struct mtd_part_parser_data ppdata; |
172 | bool map_indirect; | 172 | bool map_indirect; |
173 | const char *mtd_name; | 173 | const char *mtd_name = NULL; |
174 | 174 | ||
175 | match = of_match_device(of_flash_match, &dev->dev); | 175 | match = of_match_device(of_flash_match, &dev->dev); |
176 | if (!match) | 176 | if (!match) |
diff --git a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c index 86c9a79b89b3..595de4012e71 100644 --- a/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c +++ b/drivers/mtd/nand/bcm47xxnflash/ops_bcm4706.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include "bcm47xxnflash.h" | 17 | #include "bcm47xxnflash.h" |
18 | 18 | ||
19 | /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has | 19 | /* Broadcom uses 1'000'000 but it seems to be too many. Tests on WNDR4500 has |
20 | * shown 164 retries as maxiumum. */ | 20 | * shown ~1000 retries as maxiumum. */ |
21 | #define NFLASH_READY_RETRIES 1000 | 21 | #define NFLASH_READY_RETRIES 10000 |
22 | 22 | ||
23 | #define NFLASH_SECTOR_SIZE 512 | 23 | #define NFLASH_SECTOR_SIZE 512 |
24 | 24 | ||
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 3502606f6480..feae55c7b880 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
@@ -523,7 +523,7 @@ static struct nand_ecclayout hwecc4_2048 __initconst = { | |||
523 | static const struct of_device_id davinci_nand_of_match[] = { | 523 | static const struct of_device_id davinci_nand_of_match[] = { |
524 | {.compatible = "ti,davinci-nand", }, | 524 | {.compatible = "ti,davinci-nand", }, |
525 | {}, | 525 | {}, |
526 | } | 526 | }; |
527 | MODULE_DEVICE_TABLE(of, davinci_nand_of_match); | 527 | MODULE_DEVICE_TABLE(of, davinci_nand_of_match); |
528 | 528 | ||
529 | static struct davinci_nand_pdata | 529 | static struct davinci_nand_pdata |
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 8323ac991ad1..3766682a0289 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c | |||
@@ -2857,8 +2857,11 @@ static int nand_flash_detect_onfi(struct mtd_info *mtd, struct nand_chip *chip, | |||
2857 | int i; | 2857 | int i; |
2858 | int val; | 2858 | int val; |
2859 | 2859 | ||
2860 | /* ONFI need to be probed in 8 bits mode */ | 2860 | /* ONFI need to be probed in 8 bits mode, and 16 bits should be selected with NAND_BUSWIDTH_AUTO */ |
2861 | WARN_ON(chip->options & NAND_BUSWIDTH_16); | 2861 | if (chip->options & NAND_BUSWIDTH_16) { |
2862 | pr_err("Trying ONFI probe in 16 bits mode, aborting !\n"); | ||
2863 | return 0; | ||
2864 | } | ||
2862 | /* Try ONFI for unknown chip or LP */ | 2865 | /* Try ONFI for unknown chip or LP */ |
2863 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); | 2866 | chip->cmdfunc(mtd, NAND_CMD_READID, 0x20, -1); |
2864 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || | 2867 | if (chip->read_byte(mtd) != 'O' || chip->read_byte(mtd) != 'N' || |
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c index 1877ed7ca086..1c9e09fbdff8 100644 --- a/drivers/net/bonding/bond_sysfs.c +++ b/drivers/net/bonding/bond_sysfs.c | |||
@@ -1053,6 +1053,7 @@ static ssize_t bonding_store_primary(struct device *d, | |||
1053 | pr_info("%s: Setting primary slave to None.\n", | 1053 | pr_info("%s: Setting primary slave to None.\n", |
1054 | bond->dev->name); | 1054 | bond->dev->name); |
1055 | bond->primary_slave = NULL; | 1055 | bond->primary_slave = NULL; |
1056 | memset(bond->params.primary, 0, sizeof(bond->params.primary)); | ||
1056 | bond_select_active_slave(bond); | 1057 | bond_select_active_slave(bond); |
1057 | goto out; | 1058 | goto out; |
1058 | } | 1059 | } |
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c index 5233b8f58d77..2282b1ae9765 100644 --- a/drivers/net/can/c_can/c_can.c +++ b/drivers/net/can/c_can/c_can.c | |||
@@ -488,8 +488,12 @@ static void c_can_setup_receive_object(struct net_device *dev, int iface, | |||
488 | 488 | ||
489 | priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), | 489 | priv->write_reg(priv, C_CAN_IFACE(MASK1_REG, iface), |
490 | IFX_WRITE_LOW_16BIT(mask)); | 490 | IFX_WRITE_LOW_16BIT(mask)); |
491 | |||
492 | /* According to C_CAN documentation, the reserved bit | ||
493 | * in IFx_MASK2 register is fixed 1 | ||
494 | */ | ||
491 | priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), | 495 | priv->write_reg(priv, C_CAN_IFACE(MASK2_REG, iface), |
492 | IFX_WRITE_HIGH_16BIT(mask)); | 496 | IFX_WRITE_HIGH_16BIT(mask) | BIT(13)); |
493 | 497 | ||
494 | priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), | 498 | priv->write_reg(priv, C_CAN_IFACE(ARB1_REG, iface), |
495 | IFX_WRITE_LOW_16BIT(id)); | 499 | IFX_WRITE_LOW_16BIT(id)); |
@@ -960,7 +964,7 @@ static int c_can_handle_bus_err(struct net_device *dev, | |||
960 | break; | 964 | break; |
961 | case LEC_ACK_ERROR: | 965 | case LEC_ACK_ERROR: |
962 | netdev_dbg(dev, "ack error\n"); | 966 | netdev_dbg(dev, "ack error\n"); |
963 | cf->data[2] |= (CAN_ERR_PROT_LOC_ACK | | 967 | cf->data[3] |= (CAN_ERR_PROT_LOC_ACK | |
964 | CAN_ERR_PROT_LOC_ACK_DEL); | 968 | CAN_ERR_PROT_LOC_ACK_DEL); |
965 | break; | 969 | break; |
966 | case LEC_BIT1_ERROR: | 970 | case LEC_BIT1_ERROR: |
@@ -973,7 +977,7 @@ static int c_can_handle_bus_err(struct net_device *dev, | |||
973 | break; | 977 | break; |
974 | case LEC_CRC_ERROR: | 978 | case LEC_CRC_ERROR: |
975 | netdev_dbg(dev, "CRC error\n"); | 979 | netdev_dbg(dev, "CRC error\n"); |
976 | cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ | | 980 | cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ | |
977 | CAN_ERR_PROT_LOC_CRC_DEL); | 981 | CAN_ERR_PROT_LOC_CRC_DEL); |
978 | break; | 982 | break; |
979 | default: | 983 | default: |
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c index 7d1748575b1f..5c314a961970 100644 --- a/drivers/net/can/pch_can.c +++ b/drivers/net/can/pch_can.c | |||
@@ -560,7 +560,7 @@ static void pch_can_error(struct net_device *ndev, u32 status) | |||
560 | stats->rx_errors++; | 560 | stats->rx_errors++; |
561 | break; | 561 | break; |
562 | case PCH_CRC_ERR: | 562 | case PCH_CRC_ERR: |
563 | cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | | 563 | cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | |
564 | CAN_ERR_PROT_LOC_CRC_DEL; | 564 | CAN_ERR_PROT_LOC_CRC_DEL; |
565 | priv->can.can_stats.bus_error++; | 565 | priv->can.can_stats.bus_error++; |
566 | stats->rx_errors++; | 566 | stats->rx_errors++; |
diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index d84888f03d92..600ac7226e5c 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c | |||
@@ -339,8 +339,7 @@ static void peak_pciec_set_leds(struct peak_pciec_card *card, u8 led_mask, u8 s) | |||
339 | */ | 339 | */ |
340 | static void peak_pciec_start_led_work(struct peak_pciec_card *card) | 340 | static void peak_pciec_start_led_work(struct peak_pciec_card *card) |
341 | { | 341 | { |
342 | if (!delayed_work_pending(&card->led_work)) | 342 | schedule_delayed_work(&card->led_work, HZ); |
343 | schedule_delayed_work(&card->led_work, HZ); | ||
344 | } | 343 | } |
345 | 344 | ||
346 | /* | 345 | /* |
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c index f898c6363729..300581b24ff3 100644 --- a/drivers/net/can/ti_hecc.c +++ b/drivers/net/can/ti_hecc.c | |||
@@ -746,12 +746,12 @@ static int ti_hecc_error(struct net_device *ndev, int int_status, | |||
746 | } | 746 | } |
747 | if (err_status & HECC_CANES_CRCE) { | 747 | if (err_status & HECC_CANES_CRCE) { |
748 | hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); | 748 | hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE); |
749 | cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ | | 749 | cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ | |
750 | CAN_ERR_PROT_LOC_CRC_DEL; | 750 | CAN_ERR_PROT_LOC_CRC_DEL; |
751 | } | 751 | } |
752 | if (err_status & HECC_CANES_ACKE) { | 752 | if (err_status & HECC_CANES_ACKE) { |
753 | hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); | 753 | hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE); |
754 | cf->data[2] |= CAN_ERR_PROT_LOC_ACK | | 754 | cf->data[3] |= CAN_ERR_PROT_LOC_ACK | |
755 | CAN_ERR_PROT_LOC_ACK_DEL; | 755 | CAN_ERR_PROT_LOC_ACK_DEL; |
756 | } | 756 | } |
757 | } | 757 | } |
diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c index 66df93638085..ffd8de28a76a 100644 --- a/drivers/net/ethernet/3com/3c574_cs.c +++ b/drivers/net/ethernet/3com/3c574_cs.c | |||
@@ -432,7 +432,7 @@ static int tc574_config(struct pcmcia_device *link) | |||
432 | netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n", | 432 | netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n", |
433 | cardname, dev->base_addr, dev->irq, dev->dev_addr); | 433 | cardname, dev->base_addr, dev->irq, dev->dev_addr); |
434 | netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n", | 434 | netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n", |
435 | 8 << config & Ram_size, | 435 | 8 << (config & Ram_size), |
436 | ram_split[(config & Ram_split) >> Ram_split_shift], | 436 | ram_split[(config & Ram_split) >> Ram_split_shift], |
437 | config & Autoselect ? "autoselect " : ""); | 437 | config & Autoselect ? "autoselect " : ""); |
438 | 438 | ||
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig index e49c0eff040b..a9481606bbcd 100644 --- a/drivers/net/ethernet/adi/Kconfig +++ b/drivers/net/ethernet/adi/Kconfig | |||
@@ -61,6 +61,7 @@ config BFIN_RX_DESC_NUM | |||
61 | 61 | ||
62 | config BFIN_MAC_USE_HWSTAMP | 62 | config BFIN_MAC_USE_HWSTAMP |
63 | bool "Use IEEE 1588 hwstamp" | 63 | bool "Use IEEE 1588 hwstamp" |
64 | depends on BFIN_MAC && BF518 | ||
64 | select PTP_1588_CLOCK | 65 | select PTP_1588_CLOCK |
65 | default y | 66 | default y |
66 | ---help--- | 67 | ---help--- |
diff --git a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c index 56d3f697e0c7..0035c01660b6 100644 --- a/drivers/net/ethernet/atheros/atl1c/atl1c_main.c +++ b/drivers/net/ethernet/atheros/atl1c/atl1c_main.c | |||
@@ -21,7 +21,7 @@ | |||
21 | 21 | ||
22 | #include "atl1c.h" | 22 | #include "atl1c.h" |
23 | 23 | ||
24 | #define ATL1C_DRV_VERSION "1.0.1.0-NAPI" | 24 | #define ATL1C_DRV_VERSION "1.0.1.1-NAPI" |
25 | char atl1c_driver_name[] = "atl1c"; | 25 | char atl1c_driver_name[] = "atl1c"; |
26 | char atl1c_driver_version[] = ATL1C_DRV_VERSION; | 26 | char atl1c_driver_version[] = ATL1C_DRV_VERSION; |
27 | 27 | ||
@@ -1652,6 +1652,7 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) | |||
1652 | u16 num_alloc = 0; | 1652 | u16 num_alloc = 0; |
1653 | u16 rfd_next_to_use, next_next; | 1653 | u16 rfd_next_to_use, next_next; |
1654 | struct atl1c_rx_free_desc *rfd_desc; | 1654 | struct atl1c_rx_free_desc *rfd_desc; |
1655 | dma_addr_t mapping; | ||
1655 | 1656 | ||
1656 | next_next = rfd_next_to_use = rfd_ring->next_to_use; | 1657 | next_next = rfd_next_to_use = rfd_ring->next_to_use; |
1657 | if (++next_next == rfd_ring->count) | 1658 | if (++next_next == rfd_ring->count) |
@@ -1678,9 +1679,18 @@ static int atl1c_alloc_rx_buffer(struct atl1c_adapter *adapter) | |||
1678 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); | 1679 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); |
1679 | buffer_info->skb = skb; | 1680 | buffer_info->skb = skb; |
1680 | buffer_info->length = adapter->rx_buffer_len; | 1681 | buffer_info->length = adapter->rx_buffer_len; |
1681 | buffer_info->dma = pci_map_single(pdev, vir_addr, | 1682 | mapping = pci_map_single(pdev, vir_addr, |
1682 | buffer_info->length, | 1683 | buffer_info->length, |
1683 | PCI_DMA_FROMDEVICE); | 1684 | PCI_DMA_FROMDEVICE); |
1685 | if (unlikely(pci_dma_mapping_error(pdev, mapping))) { | ||
1686 | dev_kfree_skb(skb); | ||
1687 | buffer_info->skb = NULL; | ||
1688 | buffer_info->length = 0; | ||
1689 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_FREE); | ||
1690 | netif_warn(adapter, rx_err, adapter->netdev, "RX pci_map_single failed"); | ||
1691 | break; | ||
1692 | } | ||
1693 | buffer_info->dma = mapping; | ||
1684 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, | 1694 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, |
1685 | ATL1C_PCIMAP_FROMDEVICE); | 1695 | ATL1C_PCIMAP_FROMDEVICE); |
1686 | rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); | 1696 | rfd_desc->buffer_addr = cpu_to_le64(buffer_info->dma); |
@@ -2015,7 +2025,29 @@ check_sum: | |||
2015 | return 0; | 2025 | return 0; |
2016 | } | 2026 | } |
2017 | 2027 | ||
2018 | static void atl1c_tx_map(struct atl1c_adapter *adapter, | 2028 | static void atl1c_tx_rollback(struct atl1c_adapter *adpt, |
2029 | struct atl1c_tpd_desc *first_tpd, | ||
2030 | enum atl1c_trans_queue type) | ||
2031 | { | ||
2032 | struct atl1c_tpd_ring *tpd_ring = &adpt->tpd_ring[type]; | ||
2033 | struct atl1c_buffer *buffer_info; | ||
2034 | struct atl1c_tpd_desc *tpd; | ||
2035 | u16 first_index, index; | ||
2036 | |||
2037 | first_index = first_tpd - (struct atl1c_tpd_desc *)tpd_ring->desc; | ||
2038 | index = first_index; | ||
2039 | while (index != tpd_ring->next_to_use) { | ||
2040 | tpd = ATL1C_TPD_DESC(tpd_ring, index); | ||
2041 | buffer_info = &tpd_ring->buffer_info[index]; | ||
2042 | atl1c_clean_buffer(adpt->pdev, buffer_info, 0); | ||
2043 | memset(tpd, 0, sizeof(struct atl1c_tpd_desc)); | ||
2044 | if (++index == tpd_ring->count) | ||
2045 | index = 0; | ||
2046 | } | ||
2047 | tpd_ring->next_to_use = first_index; | ||
2048 | } | ||
2049 | |||
2050 | static int atl1c_tx_map(struct atl1c_adapter *adapter, | ||
2019 | struct sk_buff *skb, struct atl1c_tpd_desc *tpd, | 2051 | struct sk_buff *skb, struct atl1c_tpd_desc *tpd, |
2020 | enum atl1c_trans_queue type) | 2052 | enum atl1c_trans_queue type) |
2021 | { | 2053 | { |
@@ -2040,7 +2072,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, | |||
2040 | buffer_info->length = map_len; | 2072 | buffer_info->length = map_len; |
2041 | buffer_info->dma = pci_map_single(adapter->pdev, | 2073 | buffer_info->dma = pci_map_single(adapter->pdev, |
2042 | skb->data, hdr_len, PCI_DMA_TODEVICE); | 2074 | skb->data, hdr_len, PCI_DMA_TODEVICE); |
2043 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); | 2075 | if (unlikely(pci_dma_mapping_error(adapter->pdev, |
2076 | buffer_info->dma))) | ||
2077 | goto err_dma; | ||
2078 | |||
2044 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, | 2079 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, |
2045 | ATL1C_PCIMAP_TODEVICE); | 2080 | ATL1C_PCIMAP_TODEVICE); |
2046 | mapped_len += map_len; | 2081 | mapped_len += map_len; |
@@ -2062,6 +2097,10 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, | |||
2062 | buffer_info->dma = | 2097 | buffer_info->dma = |
2063 | pci_map_single(adapter->pdev, skb->data + mapped_len, | 2098 | pci_map_single(adapter->pdev, skb->data + mapped_len, |
2064 | buffer_info->length, PCI_DMA_TODEVICE); | 2099 | buffer_info->length, PCI_DMA_TODEVICE); |
2100 | if (unlikely(pci_dma_mapping_error(adapter->pdev, | ||
2101 | buffer_info->dma))) | ||
2102 | goto err_dma; | ||
2103 | |||
2065 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); | 2104 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); |
2066 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, | 2105 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_SINGLE, |
2067 | ATL1C_PCIMAP_TODEVICE); | 2106 | ATL1C_PCIMAP_TODEVICE); |
@@ -2083,6 +2122,9 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, | |||
2083 | frag, 0, | 2122 | frag, 0, |
2084 | buffer_info->length, | 2123 | buffer_info->length, |
2085 | DMA_TO_DEVICE); | 2124 | DMA_TO_DEVICE); |
2125 | if (dma_mapping_error(&adapter->pdev->dev, buffer_info->dma)) | ||
2126 | goto err_dma; | ||
2127 | |||
2086 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); | 2128 | ATL1C_SET_BUFFER_STATE(buffer_info, ATL1C_BUFFER_BUSY); |
2087 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, | 2129 | ATL1C_SET_PCIMAP_TYPE(buffer_info, ATL1C_PCIMAP_PAGE, |
2088 | ATL1C_PCIMAP_TODEVICE); | 2130 | ATL1C_PCIMAP_TODEVICE); |
@@ -2095,6 +2137,13 @@ static void atl1c_tx_map(struct atl1c_adapter *adapter, | |||
2095 | /* The last buffer info contain the skb address, | 2137 | /* The last buffer info contain the skb address, |
2096 | so it will be free after unmap */ | 2138 | so it will be free after unmap */ |
2097 | buffer_info->skb = skb; | 2139 | buffer_info->skb = skb; |
2140 | |||
2141 | return 0; | ||
2142 | |||
2143 | err_dma: | ||
2144 | buffer_info->dma = 0; | ||
2145 | buffer_info->length = 0; | ||
2146 | return -1; | ||
2098 | } | 2147 | } |
2099 | 2148 | ||
2100 | static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, | 2149 | static void atl1c_tx_queue(struct atl1c_adapter *adapter, struct sk_buff *skb, |
@@ -2157,10 +2206,18 @@ static netdev_tx_t atl1c_xmit_frame(struct sk_buff *skb, | |||
2157 | if (skb_network_offset(skb) != ETH_HLEN) | 2206 | if (skb_network_offset(skb) != ETH_HLEN) |
2158 | tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */ | 2207 | tpd->word1 |= 1 << TPD_ETH_TYPE_SHIFT; /* Ethernet frame */ |
2159 | 2208 | ||
2160 | atl1c_tx_map(adapter, skb, tpd, type); | 2209 | if (atl1c_tx_map(adapter, skb, tpd, type) < 0) { |
2161 | atl1c_tx_queue(adapter, skb, tpd, type); | 2210 | netif_info(adapter, tx_done, adapter->netdev, |
2211 | "tx-skb droppted due to dma error\n"); | ||
2212 | /* roll back tpd/buffer */ | ||
2213 | atl1c_tx_rollback(adapter, tpd, type); | ||
2214 | spin_unlock_irqrestore(&adapter->tx_lock, flags); | ||
2215 | dev_kfree_skb(skb); | ||
2216 | } else { | ||
2217 | atl1c_tx_queue(adapter, skb, tpd, type); | ||
2218 | spin_unlock_irqrestore(&adapter->tx_lock, flags); | ||
2219 | } | ||
2162 | 2220 | ||
2163 | spin_unlock_irqrestore(&adapter->tx_lock, flags); | ||
2164 | return NETDEV_TX_OK; | 2221 | return NETDEV_TX_OK; |
2165 | } | 2222 | } |
2166 | 2223 | ||
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c index 01588b66a38c..a5edac8df67b 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c | |||
@@ -80,12 +80,37 @@ static inline void bnx2x_move_fp(struct bnx2x *bp, int from, int to) | |||
80 | new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET; | 80 | new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET; |
81 | } | 81 | } |
82 | 82 | ||
83 | memcpy(&bp->bnx2x_txq[old_txdata_index], | 83 | memcpy(&bp->bnx2x_txq[new_txdata_index], |
84 | &bp->bnx2x_txq[new_txdata_index], | 84 | &bp->bnx2x_txq[old_txdata_index], |
85 | sizeof(struct bnx2x_fp_txdata)); | 85 | sizeof(struct bnx2x_fp_txdata)); |
86 | to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; | 86 | to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index]; |
87 | } | 87 | } |
88 | 88 | ||
89 | /** | ||
90 | * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact | ||
91 | * | ||
92 | * @bp: driver handle | ||
93 | * @delta: number of eth queues which were not allocated | ||
94 | */ | ||
95 | static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta) | ||
96 | { | ||
97 | int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp); | ||
98 | |||
99 | /* Queue pointer cannot be re-set on an fp-basis, as moving pointer | ||
100 | * backward along the array could cause memory to be overriden | ||
101 | */ | ||
102 | for (cos = 1; cos < bp->max_cos; cos++) { | ||
103 | for (i = 0; i < old_eth_num - delta; i++) { | ||
104 | struct bnx2x_fastpath *fp = &bp->fp[i]; | ||
105 | int new_idx = cos * (old_eth_num - delta) + i; | ||
106 | |||
107 | memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos], | ||
108 | sizeof(struct bnx2x_fp_txdata)); | ||
109 | fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx]; | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
89 | int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ | 114 | int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */ |
90 | 115 | ||
91 | /* free skb in the packet ring at pos idx | 116 | /* free skb in the packet ring at pos idx |
@@ -479,13 +504,11 @@ static int bnx2x_fill_frag_skb(struct bnx2x *bp, struct bnx2x_fastpath *fp, | |||
479 | skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp, | 504 | skb_shinfo(skb)->gso_size = bnx2x_set_lro_mss(bp, |
480 | tpa_info->parsing_flags, len_on_bd); | 505 | tpa_info->parsing_flags, len_on_bd); |
481 | 506 | ||
482 | /* set for GRO */ | 507 | skb_shinfo(skb)->gso_type = |
483 | if (fp->mode == TPA_MODE_GRO) | 508 | (GET_FLAG(tpa_info->parsing_flags, |
484 | skb_shinfo(skb)->gso_type = | 509 | PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) == |
485 | (GET_FLAG(tpa_info->parsing_flags, | 510 | PRS_FLAG_OVERETH_IPV6) ? |
486 | PARSING_FLAGS_OVER_ETHERNET_PROTOCOL) == | 511 | SKB_GSO_TCPV6 : SKB_GSO_TCPV4; |
487 | PRS_FLAG_OVERETH_IPV6) ? | ||
488 | SKB_GSO_TCPV6 : SKB_GSO_TCPV4; | ||
489 | } | 512 | } |
490 | 513 | ||
491 | 514 | ||
@@ -3863,6 +3886,7 @@ int bnx2x_alloc_fp_mem(struct bnx2x *bp) | |||
3863 | int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; | 3886 | int delta = BNX2X_NUM_ETH_QUEUES(bp) - i; |
3864 | 3887 | ||
3865 | WARN_ON(delta < 0); | 3888 | WARN_ON(delta < 0); |
3889 | bnx2x_shrink_eth_fp(bp, delta); | ||
3866 | if (CNIC_SUPPORT(bp)) | 3890 | if (CNIC_SUPPORT(bp)) |
3867 | /* move non eth FPs next to last eth FP | 3891 | /* move non eth FPs next to last eth FP |
3868 | * must be done in that order | 3892 | * must be done in that order |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c index 277f17e3c8f8..a427b49a886c 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c | |||
@@ -2777,10 +2777,10 @@ static int bnx2x_set_rss_flags(struct bnx2x *bp, struct ethtool_rxnfc *info) | |||
2777 | } else if ((info->flow_type == UDP_V6_FLOW) && | 2777 | } else if ((info->flow_type == UDP_V6_FLOW) && |
2778 | (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { | 2778 | (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) { |
2779 | bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; | 2779 | bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested; |
2780 | return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); | ||
2781 | DP(BNX2X_MSG_ETHTOOL, | 2780 | DP(BNX2X_MSG_ETHTOOL, |
2782 | "rss re-configured, UDP 4-tupple %s\n", | 2781 | "rss re-configured, UDP 4-tupple %s\n", |
2783 | udp_rss_requested ? "enabled" : "disabled"); | 2782 | udp_rss_requested ? "enabled" : "disabled"); |
2783 | return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0); | ||
2784 | } else { | 2784 | } else { |
2785 | return 0; | 2785 | return 0; |
2786 | } | 2786 | } |
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c index 940ef859dc60..5523da3afcdc 100644 --- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c +++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c | |||
@@ -127,6 +127,17 @@ MODULE_PARM_DESC(debug, " Default debug msglevel"); | |||
127 | 127 | ||
128 | struct workqueue_struct *bnx2x_wq; | 128 | struct workqueue_struct *bnx2x_wq; |
129 | 129 | ||
130 | struct bnx2x_mac_vals { | ||
131 | u32 xmac_addr; | ||
132 | u32 xmac_val; | ||
133 | u32 emac_addr; | ||
134 | u32 emac_val; | ||
135 | u32 umac_addr; | ||
136 | u32 umac_val; | ||
137 | u32 bmac_addr; | ||
138 | u32 bmac_val[2]; | ||
139 | }; | ||
140 | |||
130 | enum bnx2x_board_type { | 141 | enum bnx2x_board_type { |
131 | BCM57710 = 0, | 142 | BCM57710 = 0, |
132 | BCM57711, | 143 | BCM57711, |
@@ -9420,12 +9431,19 @@ static inline void bnx2x_undi_int_disable(struct bnx2x *bp) | |||
9420 | bnx2x_undi_int_disable_e1h(bp); | 9431 | bnx2x_undi_int_disable_e1h(bp); |
9421 | } | 9432 | } |
9422 | 9433 | ||
9423 | static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | 9434 | static void bnx2x_prev_unload_close_mac(struct bnx2x *bp, |
9435 | struct bnx2x_mac_vals *vals) | ||
9424 | { | 9436 | { |
9425 | u32 val, base_addr, offset, mask, reset_reg; | 9437 | u32 val, base_addr, offset, mask, reset_reg; |
9426 | bool mac_stopped = false; | 9438 | bool mac_stopped = false; |
9427 | u8 port = BP_PORT(bp); | 9439 | u8 port = BP_PORT(bp); |
9428 | 9440 | ||
9441 | /* reset addresses as they also mark which values were changed */ | ||
9442 | vals->bmac_addr = 0; | ||
9443 | vals->umac_addr = 0; | ||
9444 | vals->xmac_addr = 0; | ||
9445 | vals->emac_addr = 0; | ||
9446 | |||
9429 | reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); | 9447 | reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2); |
9430 | 9448 | ||
9431 | if (!CHIP_IS_E3(bp)) { | 9449 | if (!CHIP_IS_E3(bp)) { |
@@ -9447,14 +9465,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | |||
9447 | */ | 9465 | */ |
9448 | wb_data[0] = REG_RD(bp, base_addr + offset); | 9466 | wb_data[0] = REG_RD(bp, base_addr + offset); |
9449 | wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); | 9467 | wb_data[1] = REG_RD(bp, base_addr + offset + 0x4); |
9468 | vals->bmac_addr = base_addr + offset; | ||
9469 | vals->bmac_val[0] = wb_data[0]; | ||
9470 | vals->bmac_val[1] = wb_data[1]; | ||
9450 | wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; | 9471 | wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE; |
9451 | REG_WR(bp, base_addr + offset, wb_data[0]); | 9472 | REG_WR(bp, vals->bmac_addr, wb_data[0]); |
9452 | REG_WR(bp, base_addr + offset + 0x4, wb_data[1]); | 9473 | REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]); |
9453 | 9474 | ||
9454 | } | 9475 | } |
9455 | BNX2X_DEV_INFO("Disable emac Rx\n"); | 9476 | BNX2X_DEV_INFO("Disable emac Rx\n"); |
9456 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0); | 9477 | vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4; |
9457 | 9478 | vals->emac_val = REG_RD(bp, vals->emac_addr); | |
9479 | REG_WR(bp, vals->emac_addr, 0); | ||
9458 | mac_stopped = true; | 9480 | mac_stopped = true; |
9459 | } else { | 9481 | } else { |
9460 | if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { | 9482 | if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) { |
@@ -9465,14 +9487,18 @@ static void bnx2x_prev_unload_close_mac(struct bnx2x *bp) | |||
9465 | val & ~(1 << 1)); | 9487 | val & ~(1 << 1)); |
9466 | REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, | 9488 | REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI, |
9467 | val | (1 << 1)); | 9489 | val | (1 << 1)); |
9468 | REG_WR(bp, base_addr + XMAC_REG_CTRL, 0); | 9490 | vals->xmac_addr = base_addr + XMAC_REG_CTRL; |
9491 | vals->xmac_val = REG_RD(bp, vals->xmac_addr); | ||
9492 | REG_WR(bp, vals->xmac_addr, 0); | ||
9469 | mac_stopped = true; | 9493 | mac_stopped = true; |
9470 | } | 9494 | } |
9471 | mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; | 9495 | mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port; |
9472 | if (mask & reset_reg) { | 9496 | if (mask & reset_reg) { |
9473 | BNX2X_DEV_INFO("Disable umac Rx\n"); | 9497 | BNX2X_DEV_INFO("Disable umac Rx\n"); |
9474 | base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; | 9498 | base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0; |
9475 | REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0); | 9499 | vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG; |
9500 | vals->umac_val = REG_RD(bp, vals->umac_addr); | ||
9501 | REG_WR(bp, vals->umac_addr, 0); | ||
9476 | mac_stopped = true; | 9502 | mac_stopped = true; |
9477 | } | 9503 | } |
9478 | } | 9504 | } |
@@ -9664,12 +9690,16 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9664 | { | 9690 | { |
9665 | u32 reset_reg, tmp_reg = 0, rc; | 9691 | u32 reset_reg, tmp_reg = 0, rc; |
9666 | bool prev_undi = false; | 9692 | bool prev_undi = false; |
9693 | struct bnx2x_mac_vals mac_vals; | ||
9694 | |||
9667 | /* It is possible a previous function received 'common' answer, | 9695 | /* It is possible a previous function received 'common' answer, |
9668 | * but hasn't loaded yet, therefore creating a scenario of | 9696 | * but hasn't loaded yet, therefore creating a scenario of |
9669 | * multiple functions receiving 'common' on the same path. | 9697 | * multiple functions receiving 'common' on the same path. |
9670 | */ | 9698 | */ |
9671 | BNX2X_DEV_INFO("Common unload Flow\n"); | 9699 | BNX2X_DEV_INFO("Common unload Flow\n"); |
9672 | 9700 | ||
9701 | memset(&mac_vals, 0, sizeof(mac_vals)); | ||
9702 | |||
9673 | if (bnx2x_prev_is_path_marked(bp)) | 9703 | if (bnx2x_prev_is_path_marked(bp)) |
9674 | return bnx2x_prev_mcp_done(bp); | 9704 | return bnx2x_prev_mcp_done(bp); |
9675 | 9705 | ||
@@ -9680,7 +9710,10 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9680 | u32 timer_count = 1000; | 9710 | u32 timer_count = 1000; |
9681 | 9711 | ||
9682 | /* Close the MAC Rx to prevent BRB from filling up */ | 9712 | /* Close the MAC Rx to prevent BRB from filling up */ |
9683 | bnx2x_prev_unload_close_mac(bp); | 9713 | bnx2x_prev_unload_close_mac(bp, &mac_vals); |
9714 | |||
9715 | /* close LLH filters towards the BRB */ | ||
9716 | bnx2x_set_rx_filter(&bp->link_params, 0); | ||
9684 | 9717 | ||
9685 | /* Check if the UNDI driver was previously loaded | 9718 | /* Check if the UNDI driver was previously loaded |
9686 | * UNDI driver initializes CID offset for normal bell to 0x7 | 9719 | * UNDI driver initializes CID offset for normal bell to 0x7 |
@@ -9727,6 +9760,17 @@ static int bnx2x_prev_unload_common(struct bnx2x *bp) | |||
9727 | /* No packets are in the pipeline, path is ready for reset */ | 9760 | /* No packets are in the pipeline, path is ready for reset */ |
9728 | bnx2x_reset_common(bp); | 9761 | bnx2x_reset_common(bp); |
9729 | 9762 | ||
9763 | if (mac_vals.xmac_addr) | ||
9764 | REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val); | ||
9765 | if (mac_vals.umac_addr) | ||
9766 | REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val); | ||
9767 | if (mac_vals.emac_addr) | ||
9768 | REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val); | ||
9769 | if (mac_vals.bmac_addr) { | ||
9770 | REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]); | ||
9771 | REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]); | ||
9772 | } | ||
9773 | |||
9730 | rc = bnx2x_prev_mark_path(bp, prev_undi); | 9774 | rc = bnx2x_prev_mark_path(bp, prev_undi); |
9731 | if (rc) { | 9775 | if (rc) { |
9732 | bnx2x_prev_mcp_done(bp); | 9776 | bnx2x_prev_mcp_done(bp); |
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index 78ea90c40e19..bdb086934cd9 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c | |||
@@ -1283,14 +1283,26 @@ static int tg3_phy_auxctl_write(struct tg3 *tp, int reg, u32 set) | |||
1283 | return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); | 1283 | return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg); |
1284 | } | 1284 | } |
1285 | 1285 | ||
1286 | #define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \ | 1286 | static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable) |
1287 | tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ | 1287 | { |
1288 | MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \ | 1288 | u32 val; |
1289 | MII_TG3_AUXCTL_ACTL_TX_6DB) | 1289 | int err; |
1290 | 1290 | ||
1291 | #define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \ | 1291 | err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val); |
1292 | tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \ | 1292 | |
1293 | MII_TG3_AUXCTL_ACTL_TX_6DB); | 1293 | if (err) |
1294 | return err; | ||
1295 | if (enable) | ||
1296 | |||
1297 | val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA; | ||
1298 | else | ||
1299 | val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA; | ||
1300 | |||
1301 | err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, | ||
1302 | val | MII_TG3_AUXCTL_ACTL_TX_6DB); | ||
1303 | |||
1304 | return err; | ||
1305 | } | ||
1294 | 1306 | ||
1295 | static int tg3_bmcr_reset(struct tg3 *tp) | 1307 | static int tg3_bmcr_reset(struct tg3 *tp) |
1296 | { | 1308 | { |
@@ -2223,7 +2235,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) | |||
2223 | 2235 | ||
2224 | otp = tp->phy_otp; | 2236 | otp = tp->phy_otp; |
2225 | 2237 | ||
2226 | if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) | 2238 | if (tg3_phy_toggle_auxctl_smdsp(tp, true)) |
2227 | return; | 2239 | return; |
2228 | 2240 | ||
2229 | phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); | 2241 | phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT); |
@@ -2248,7 +2260,7 @@ static void tg3_phy_apply_otp(struct tg3 *tp) | |||
2248 | ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); | 2260 | ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT); |
2249 | tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); | 2261 | tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy); |
2250 | 2262 | ||
2251 | TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 2263 | tg3_phy_toggle_auxctl_smdsp(tp, false); |
2252 | } | 2264 | } |
2253 | 2265 | ||
2254 | static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) | 2266 | static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) |
@@ -2284,9 +2296,9 @@ static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up) | |||
2284 | 2296 | ||
2285 | if (!tp->setlpicnt) { | 2297 | if (!tp->setlpicnt) { |
2286 | if (current_link_up == 1 && | 2298 | if (current_link_up == 1 && |
2287 | !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { | 2299 | !tg3_phy_toggle_auxctl_smdsp(tp, true)) { |
2288 | tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); | 2300 | tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000); |
2289 | TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 2301 | tg3_phy_toggle_auxctl_smdsp(tp, false); |
2290 | } | 2302 | } |
2291 | 2303 | ||
2292 | val = tr32(TG3_CPMU_EEE_MODE); | 2304 | val = tr32(TG3_CPMU_EEE_MODE); |
@@ -2302,11 +2314,11 @@ static void tg3_phy_eee_enable(struct tg3 *tp) | |||
2302 | (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || | 2314 | (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 || |
2303 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || | 2315 | GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 || |
2304 | tg3_flag(tp, 57765_CLASS)) && | 2316 | tg3_flag(tp, 57765_CLASS)) && |
2305 | !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { | 2317 | !tg3_phy_toggle_auxctl_smdsp(tp, true)) { |
2306 | val = MII_TG3_DSP_TAP26_ALNOKO | | 2318 | val = MII_TG3_DSP_TAP26_ALNOKO | |
2307 | MII_TG3_DSP_TAP26_RMRXSTO; | 2319 | MII_TG3_DSP_TAP26_RMRXSTO; |
2308 | tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); | 2320 | tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val); |
2309 | TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 2321 | tg3_phy_toggle_auxctl_smdsp(tp, false); |
2310 | } | 2322 | } |
2311 | 2323 | ||
2312 | val = tr32(TG3_CPMU_EEE_MODE); | 2324 | val = tr32(TG3_CPMU_EEE_MODE); |
@@ -2450,7 +2462,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) | |||
2450 | tg3_writephy(tp, MII_CTRL1000, | 2462 | tg3_writephy(tp, MII_CTRL1000, |
2451 | CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); | 2463 | CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER); |
2452 | 2464 | ||
2453 | err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); | 2465 | err = tg3_phy_toggle_auxctl_smdsp(tp, true); |
2454 | if (err) | 2466 | if (err) |
2455 | return err; | 2467 | return err; |
2456 | 2468 | ||
@@ -2471,7 +2483,7 @@ static int tg3_phy_reset_5703_4_5(struct tg3 *tp) | |||
2471 | tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); | 2483 | tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200); |
2472 | tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); | 2484 | tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000); |
2473 | 2485 | ||
2474 | TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 2486 | tg3_phy_toggle_auxctl_smdsp(tp, false); |
2475 | 2487 | ||
2476 | tg3_writephy(tp, MII_CTRL1000, phy9_orig); | 2488 | tg3_writephy(tp, MII_CTRL1000, phy9_orig); |
2477 | 2489 | ||
@@ -2572,10 +2584,10 @@ static int tg3_phy_reset(struct tg3 *tp) | |||
2572 | 2584 | ||
2573 | out: | 2585 | out: |
2574 | if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && | 2586 | if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) && |
2575 | !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { | 2587 | !tg3_phy_toggle_auxctl_smdsp(tp, true)) { |
2576 | tg3_phydsp_write(tp, 0x201f, 0x2aaa); | 2588 | tg3_phydsp_write(tp, 0x201f, 0x2aaa); |
2577 | tg3_phydsp_write(tp, 0x000a, 0x0323); | 2589 | tg3_phydsp_write(tp, 0x000a, 0x0323); |
2578 | TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 2590 | tg3_phy_toggle_auxctl_smdsp(tp, false); |
2579 | } | 2591 | } |
2580 | 2592 | ||
2581 | if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { | 2593 | if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) { |
@@ -2584,14 +2596,14 @@ out: | |||
2584 | } | 2596 | } |
2585 | 2597 | ||
2586 | if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { | 2598 | if (tp->phy_flags & TG3_PHYFLG_BER_BUG) { |
2587 | if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { | 2599 | if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { |
2588 | tg3_phydsp_write(tp, 0x000a, 0x310b); | 2600 | tg3_phydsp_write(tp, 0x000a, 0x310b); |
2589 | tg3_phydsp_write(tp, 0x201f, 0x9506); | 2601 | tg3_phydsp_write(tp, 0x201f, 0x9506); |
2590 | tg3_phydsp_write(tp, 0x401f, 0x14e2); | 2602 | tg3_phydsp_write(tp, 0x401f, 0x14e2); |
2591 | TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 2603 | tg3_phy_toggle_auxctl_smdsp(tp, false); |
2592 | } | 2604 | } |
2593 | } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { | 2605 | } else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) { |
2594 | if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) { | 2606 | if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) { |
2595 | tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); | 2607 | tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a); |
2596 | if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { | 2608 | if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) { |
2597 | tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); | 2609 | tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b); |
@@ -2600,7 +2612,7 @@ out: | |||
2600 | } else | 2612 | } else |
2601 | tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); | 2613 | tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b); |
2602 | 2614 | ||
2603 | TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 2615 | tg3_phy_toggle_auxctl_smdsp(tp, false); |
2604 | } | 2616 | } |
2605 | } | 2617 | } |
2606 | 2618 | ||
@@ -4009,7 +4021,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) | |||
4009 | tw32(TG3_CPMU_EEE_MODE, | 4021 | tw32(TG3_CPMU_EEE_MODE, |
4010 | tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); | 4022 | tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE); |
4011 | 4023 | ||
4012 | err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp); | 4024 | err = tg3_phy_toggle_auxctl_smdsp(tp, true); |
4013 | if (!err) { | 4025 | if (!err) { |
4014 | u32 err2; | 4026 | u32 err2; |
4015 | 4027 | ||
@@ -4042,7 +4054,7 @@ static int tg3_phy_autoneg_cfg(struct tg3 *tp, u32 advertise, u32 flowctrl) | |||
4042 | MII_TG3_DSP_CH34TP2_HIBW01); | 4054 | MII_TG3_DSP_CH34TP2_HIBW01); |
4043 | } | 4055 | } |
4044 | 4056 | ||
4045 | err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp); | 4057 | err2 = tg3_phy_toggle_auxctl_smdsp(tp, false); |
4046 | if (!err) | 4058 | if (!err) |
4047 | err = err2; | 4059 | err = err2; |
4048 | } | 4060 | } |
@@ -6950,6 +6962,9 @@ static void tg3_poll_controller(struct net_device *dev) | |||
6950 | int i; | 6962 | int i; |
6951 | struct tg3 *tp = netdev_priv(dev); | 6963 | struct tg3 *tp = netdev_priv(dev); |
6952 | 6964 | ||
6965 | if (tg3_irq_sync(tp)) | ||
6966 | return; | ||
6967 | |||
6953 | for (i = 0; i < tp->irq_cnt; i++) | 6968 | for (i = 0; i < tp->irq_cnt; i++) |
6954 | tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); | 6969 | tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]); |
6955 | } | 6970 | } |
@@ -16367,6 +16382,7 @@ static int tg3_init_one(struct pci_dev *pdev, | |||
16367 | tp->pm_cap = pm_cap; | 16382 | tp->pm_cap = pm_cap; |
16368 | tp->rx_mode = TG3_DEF_RX_MODE; | 16383 | tp->rx_mode = TG3_DEF_RX_MODE; |
16369 | tp->tx_mode = TG3_DEF_TX_MODE; | 16384 | tp->tx_mode = TG3_DEF_TX_MODE; |
16385 | tp->irq_sync = 1; | ||
16370 | 16386 | ||
16371 | if (tg3_debug > 0) | 16387 | if (tg3_debug > 0) |
16372 | tp->msg_enable = tg3_debug; | 16388 | tp->msg_enable = tg3_debug; |
diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index a9b0830fb39d..b9d4bb9530e5 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c | |||
@@ -693,6 +693,11 @@ static int macb_poll(struct napi_struct *napi, int budget) | |||
693 | * get notified when new packets arrive. | 693 | * get notified when new packets arrive. |
694 | */ | 694 | */ |
695 | macb_writel(bp, IER, MACB_RX_INT_FLAGS); | 695 | macb_writel(bp, IER, MACB_RX_INT_FLAGS); |
696 | |||
697 | /* Packets received while interrupts were disabled */ | ||
698 | status = macb_readl(bp, RSR); | ||
699 | if (unlikely(status)) | ||
700 | napi_reschedule(napi); | ||
696 | } | 701 | } |
697 | 702 | ||
698 | /* TODO: Handle errors */ | 703 | /* TODO: Handle errors */ |
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c index b407043ce9b0..f7f02900f650 100644 --- a/drivers/net/ethernet/calxeda/xgmac.c +++ b/drivers/net/ethernet/calxeda/xgmac.c | |||
@@ -548,6 +548,10 @@ static int desc_get_rx_status(struct xgmac_priv *priv, struct xgmac_dma_desc *p) | |||
548 | return -1; | 548 | return -1; |
549 | } | 549 | } |
550 | 550 | ||
551 | /* All frames should fit into a single buffer */ | ||
552 | if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG)) | ||
553 | return -1; | ||
554 | |||
551 | /* Check if packet has checksum already */ | 555 | /* Check if packet has checksum already */ |
552 | if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && | 556 | if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) && |
553 | !(ext_status & RXDESC_IP_PAYLOAD_MASK)) | 557 | !(ext_status & RXDESC_IP_PAYLOAD_MASK)) |
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index f0718e1a8369..c306df7d4568 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c | |||
@@ -1994,9 +1994,20 @@ static int set_coalesce(struct net_device *dev, struct ethtool_coalesce *c) | |||
1994 | { | 1994 | { |
1995 | const struct port_info *pi = netdev_priv(dev); | 1995 | const struct port_info *pi = netdev_priv(dev); |
1996 | struct adapter *adap = pi->adapter; | 1996 | struct adapter *adap = pi->adapter; |
1997 | 1997 | struct sge_rspq *q; | |
1998 | return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq, | 1998 | int i; |
1999 | c->rx_coalesce_usecs, c->rx_max_coalesced_frames); | 1999 | int r = 0; |
2000 | |||
2001 | for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) { | ||
2002 | q = &adap->sge.ethrxq[i].rspq; | ||
2003 | r = set_rxq_intr_params(adap, q, c->rx_coalesce_usecs, | ||
2004 | c->rx_max_coalesced_frames); | ||
2005 | if (r) { | ||
2006 | dev_err(&dev->dev, "failed to set coalesce %d\n", r); | ||
2007 | break; | ||
2008 | } | ||
2009 | } | ||
2010 | return r; | ||
2000 | } | 2011 | } |
2001 | 2012 | ||
2002 | static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) | 2013 | static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c) |
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 3bc1912afba9..f1b3df167ff2 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h | |||
@@ -36,13 +36,13 @@ | |||
36 | 36 | ||
37 | #define DRV_VER "4.4.161.0u" | 37 | #define DRV_VER "4.4.161.0u" |
38 | #define DRV_NAME "be2net" | 38 | #define DRV_NAME "be2net" |
39 | #define BE_NAME "ServerEngines BladeEngine2 10Gbps NIC" | 39 | #define BE_NAME "Emulex BladeEngine2" |
40 | #define BE3_NAME "ServerEngines BladeEngine3 10Gbps NIC" | 40 | #define BE3_NAME "Emulex BladeEngine3" |
41 | #define OC_NAME "Emulex OneConnect 10Gbps NIC" | 41 | #define OC_NAME "Emulex OneConnect" |
42 | #define OC_NAME_BE OC_NAME "(be3)" | 42 | #define OC_NAME_BE OC_NAME "(be3)" |
43 | #define OC_NAME_LANCER OC_NAME "(Lancer)" | 43 | #define OC_NAME_LANCER OC_NAME "(Lancer)" |
44 | #define OC_NAME_SH OC_NAME "(Skyhawk)" | 44 | #define OC_NAME_SH OC_NAME "(Skyhawk)" |
45 | #define DRV_DESC "ServerEngines BladeEngine 10Gbps NIC Driver" | 45 | #define DRV_DESC "Emulex OneConnect 10Gbps NIC Driver" |
46 | 46 | ||
47 | #define BE_VENDOR_ID 0x19a2 | 47 | #define BE_VENDOR_ID 0x19a2 |
48 | #define EMULEX_VENDOR_ID 0x10df | 48 | #define EMULEX_VENDOR_ID 0x10df |
@@ -190,6 +190,7 @@ struct be_eq_obj { | |||
190 | 190 | ||
191 | u8 idx; /* array index */ | 191 | u8 idx; /* array index */ |
192 | u16 tx_budget; | 192 | u16 tx_budget; |
193 | u16 spurious_intr; | ||
193 | struct napi_struct napi; | 194 | struct napi_struct napi; |
194 | struct be_adapter *adapter; | 195 | struct be_adapter *adapter; |
195 | } ____cacheline_aligned_in_smp; | 196 | } ____cacheline_aligned_in_smp; |
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 9dca22be8125..4d6f3c54427a 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c | |||
@@ -25,7 +25,7 @@ | |||
25 | MODULE_VERSION(DRV_VER); | 25 | MODULE_VERSION(DRV_VER); |
26 | MODULE_DEVICE_TABLE(pci, be_dev_ids); | 26 | MODULE_DEVICE_TABLE(pci, be_dev_ids); |
27 | MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); | 27 | MODULE_DESCRIPTION(DRV_DESC " " DRV_VER); |
28 | MODULE_AUTHOR("ServerEngines Corporation"); | 28 | MODULE_AUTHOR("Emulex Corporation"); |
29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
30 | 30 | ||
31 | static unsigned int num_vfs; | 31 | static unsigned int num_vfs; |
@@ -2026,19 +2026,30 @@ static irqreturn_t be_intx(int irq, void *dev) | |||
2026 | struct be_adapter *adapter = eqo->adapter; | 2026 | struct be_adapter *adapter = eqo->adapter; |
2027 | int num_evts = 0; | 2027 | int num_evts = 0; |
2028 | 2028 | ||
2029 | /* On Lancer, clear-intr bit of the EQ DB does not work. | 2029 | /* IRQ is not expected when NAPI is scheduled as the EQ |
2030 | * INTx is de-asserted only on notifying num evts. | 2030 | * will not be armed. |
2031 | * But, this can happen on Lancer INTx where it takes | ||
2032 | * a while to de-assert INTx or in BE2 where occasionaly | ||
2033 | * an interrupt may be raised even when EQ is unarmed. | ||
2034 | * If NAPI is already scheduled, then counting & notifying | ||
2035 | * events will orphan them. | ||
2031 | */ | 2036 | */ |
2032 | if (lancer_chip(adapter)) | 2037 | if (napi_schedule_prep(&eqo->napi)) { |
2033 | num_evts = events_get(eqo); | 2038 | num_evts = events_get(eqo); |
2039 | __napi_schedule(&eqo->napi); | ||
2040 | if (num_evts) | ||
2041 | eqo->spurious_intr = 0; | ||
2042 | } | ||
2043 | be_eq_notify(adapter, eqo->q.id, false, true, num_evts); | ||
2034 | 2044 | ||
2035 | /* The EQ-notify may not de-assert INTx rightaway, causing | 2045 | /* Return IRQ_HANDLED only for the the first spurious intr |
2036 | * the ISR to be invoked again. So, return HANDLED even when | 2046 | * after a valid intr to stop the kernel from branding |
2037 | * num_evts is zero. | 2047 | * this irq as a bad one! |
2038 | */ | 2048 | */ |
2039 | be_eq_notify(adapter, eqo->q.id, false, true, num_evts); | 2049 | if (num_evts || eqo->spurious_intr++ == 0) |
2040 | napi_schedule(&eqo->napi); | 2050 | return IRQ_HANDLED; |
2041 | return IRQ_HANDLED; | 2051 | else |
2052 | return IRQ_NONE; | ||
2042 | } | 2053 | } |
2043 | 2054 | ||
2044 | static irqreturn_t be_msix(int irq, void *dev) | 2055 | static irqreturn_t be_msix(int irq, void *dev) |
diff --git a/drivers/net/ethernet/intel/e1000e/defines.h b/drivers/net/ethernet/intel/e1000e/defines.h index 02a12b69555f..4dab6fc265a2 100644 --- a/drivers/net/ethernet/intel/e1000e/defines.h +++ b/drivers/net/ethernet/intel/e1000e/defines.h | |||
@@ -232,6 +232,7 @@ | |||
232 | #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ | 232 | #define E1000_CTRL_FRCDPX 0x00001000 /* Force Duplex */ |
233 | #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ | 233 | #define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ |
234 | #define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ | 234 | #define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ |
235 | #define E1000_CTRL_MEHE 0x00080000 /* Memory Error Handling Enable */ | ||
235 | #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ | 236 | #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ |
236 | #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ | 237 | #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ |
237 | #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ | 238 | #define E1000_CTRL_SWDPIO0 0x00400000 /* SWDPIN 0 Input or output */ |
@@ -389,6 +390,12 @@ | |||
389 | 390 | ||
390 | #define E1000_PBS_16K E1000_PBA_16K | 391 | #define E1000_PBS_16K E1000_PBA_16K |
391 | 392 | ||
393 | /* Uncorrectable/correctable ECC Error counts and enable bits */ | ||
394 | #define E1000_PBECCSTS_CORR_ERR_CNT_MASK 0x000000FF | ||
395 | #define E1000_PBECCSTS_UNCORR_ERR_CNT_MASK 0x0000FF00 | ||
396 | #define E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT 8 | ||
397 | #define E1000_PBECCSTS_ECC_ENABLE 0x00010000 | ||
398 | |||
392 | #define IFS_MAX 80 | 399 | #define IFS_MAX 80 |
393 | #define IFS_MIN 40 | 400 | #define IFS_MIN 40 |
394 | #define IFS_RATIO 4 | 401 | #define IFS_RATIO 4 |
@@ -408,6 +415,7 @@ | |||
408 | #define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ | 415 | #define E1000_ICR_RXSEQ 0x00000008 /* Rx sequence error */ |
409 | #define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ | 416 | #define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */ |
410 | #define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ | 417 | #define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */ |
418 | #define E1000_ICR_ECCER 0x00400000 /* Uncorrectable ECC Error */ | ||
411 | #define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ | 419 | #define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */ |
412 | #define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ | 420 | #define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */ |
413 | #define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ | 421 | #define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */ |
@@ -443,6 +451,7 @@ | |||
443 | #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ | 451 | #define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */ |
444 | #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ | 452 | #define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */ |
445 | #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ | 453 | #define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */ |
454 | #define E1000_IMS_ECCER E1000_ICR_ECCER /* Uncorrectable ECC Error */ | ||
446 | #define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ | 455 | #define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */ |
447 | #define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ | 456 | #define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */ |
448 | #define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ | 457 | #define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */ |
diff --git a/drivers/net/ethernet/intel/e1000e/e1000.h b/drivers/net/ethernet/intel/e1000e/e1000.h index 6782a2eea1bc..7e95f221d60b 100644 --- a/drivers/net/ethernet/intel/e1000e/e1000.h +++ b/drivers/net/ethernet/intel/e1000e/e1000.h | |||
@@ -309,6 +309,8 @@ struct e1000_adapter { | |||
309 | 309 | ||
310 | struct napi_struct napi; | 310 | struct napi_struct napi; |
311 | 311 | ||
312 | unsigned int uncorr_errors; /* uncorrectable ECC errors */ | ||
313 | unsigned int corr_errors; /* correctable ECC errors */ | ||
312 | unsigned int restart_queue; | 314 | unsigned int restart_queue; |
313 | u32 txd_cmd; | 315 | u32 txd_cmd; |
314 | 316 | ||
diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c index f95bc6ee1c22..fd4772a2691c 100644 --- a/drivers/net/ethernet/intel/e1000e/ethtool.c +++ b/drivers/net/ethernet/intel/e1000e/ethtool.c | |||
@@ -108,6 +108,8 @@ static const struct e1000_stats e1000_gstrings_stats[] = { | |||
108 | E1000_STAT("dropped_smbus", stats.mgpdc), | 108 | E1000_STAT("dropped_smbus", stats.mgpdc), |
109 | E1000_STAT("rx_dma_failed", rx_dma_failed), | 109 | E1000_STAT("rx_dma_failed", rx_dma_failed), |
110 | E1000_STAT("tx_dma_failed", tx_dma_failed), | 110 | E1000_STAT("tx_dma_failed", tx_dma_failed), |
111 | E1000_STAT("uncorr_ecc_errors", uncorr_errors), | ||
112 | E1000_STAT("corr_ecc_errors", corr_errors), | ||
111 | }; | 113 | }; |
112 | 114 | ||
113 | #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) | 115 | #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats) |
diff --git a/drivers/net/ethernet/intel/e1000e/hw.h b/drivers/net/ethernet/intel/e1000e/hw.h index cf217777586c..b88676ff3d86 100644 --- a/drivers/net/ethernet/intel/e1000e/hw.h +++ b/drivers/net/ethernet/intel/e1000e/hw.h | |||
@@ -77,6 +77,7 @@ enum e1e_registers { | |||
77 | #define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ | 77 | #define E1000_POEMB E1000_PHY_CTRL /* PHY OEM Bits */ |
78 | E1000_PBA = 0x01000, /* Packet Buffer Allocation - RW */ | 78 | E1000_PBA = 0x01000, /* Packet Buffer Allocation - RW */ |
79 | E1000_PBS = 0x01008, /* Packet Buffer Size */ | 79 | E1000_PBS = 0x01008, /* Packet Buffer Size */ |
80 | E1000_PBECCSTS = 0x0100C, /* Packet Buffer ECC Status - RW */ | ||
80 | E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */ | 81 | E1000_EEMNGCTL = 0x01010, /* MNG EEprom Control */ |
81 | E1000_EEWR = 0x0102C, /* EEPROM Write Register - RW */ | 82 | E1000_EEWR = 0x0102C, /* EEPROM Write Register - RW */ |
82 | E1000_FLOP = 0x0103C, /* FLASH Opcode Register */ | 83 | E1000_FLOP = 0x0103C, /* FLASH Opcode Register */ |
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index 976336547607..24d9f61956f0 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c | |||
@@ -3624,6 +3624,17 @@ static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw) | |||
3624 | if (hw->mac.type == e1000_ich8lan) | 3624 | if (hw->mac.type == e1000_ich8lan) |
3625 | reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); | 3625 | reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS); |
3626 | ew32(RFCTL, reg); | 3626 | ew32(RFCTL, reg); |
3627 | |||
3628 | /* Enable ECC on Lynxpoint */ | ||
3629 | if (hw->mac.type == e1000_pch_lpt) { | ||
3630 | reg = er32(PBECCSTS); | ||
3631 | reg |= E1000_PBECCSTS_ECC_ENABLE; | ||
3632 | ew32(PBECCSTS, reg); | ||
3633 | |||
3634 | reg = er32(CTRL); | ||
3635 | reg |= E1000_CTRL_MEHE; | ||
3636 | ew32(CTRL, reg); | ||
3637 | } | ||
3627 | } | 3638 | } |
3628 | 3639 | ||
3629 | /** | 3640 | /** |
diff --git a/drivers/net/ethernet/intel/e1000e/netdev.c b/drivers/net/ethernet/intel/e1000e/netdev.c index fbf75fdca994..643c883dd795 100644 --- a/drivers/net/ethernet/intel/e1000e/netdev.c +++ b/drivers/net/ethernet/intel/e1000e/netdev.c | |||
@@ -1678,6 +1678,23 @@ static irqreturn_t e1000_intr_msi(int irq, void *data) | |||
1678 | mod_timer(&adapter->watchdog_timer, jiffies + 1); | 1678 | mod_timer(&adapter->watchdog_timer, jiffies + 1); |
1679 | } | 1679 | } |
1680 | 1680 | ||
1681 | /* Reset on uncorrectable ECC error */ | ||
1682 | if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { | ||
1683 | u32 pbeccsts = er32(PBECCSTS); | ||
1684 | |||
1685 | adapter->corr_errors += | ||
1686 | pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; | ||
1687 | adapter->uncorr_errors += | ||
1688 | (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> | ||
1689 | E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; | ||
1690 | |||
1691 | /* Do the reset outside of interrupt context */ | ||
1692 | schedule_work(&adapter->reset_task); | ||
1693 | |||
1694 | /* return immediately since reset is imminent */ | ||
1695 | return IRQ_HANDLED; | ||
1696 | } | ||
1697 | |||
1681 | if (napi_schedule_prep(&adapter->napi)) { | 1698 | if (napi_schedule_prep(&adapter->napi)) { |
1682 | adapter->total_tx_bytes = 0; | 1699 | adapter->total_tx_bytes = 0; |
1683 | adapter->total_tx_packets = 0; | 1700 | adapter->total_tx_packets = 0; |
@@ -1741,6 +1758,23 @@ static irqreturn_t e1000_intr(int irq, void *data) | |||
1741 | mod_timer(&adapter->watchdog_timer, jiffies + 1); | 1758 | mod_timer(&adapter->watchdog_timer, jiffies + 1); |
1742 | } | 1759 | } |
1743 | 1760 | ||
1761 | /* Reset on uncorrectable ECC error */ | ||
1762 | if ((icr & E1000_ICR_ECCER) && (hw->mac.type == e1000_pch_lpt)) { | ||
1763 | u32 pbeccsts = er32(PBECCSTS); | ||
1764 | |||
1765 | adapter->corr_errors += | ||
1766 | pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; | ||
1767 | adapter->uncorr_errors += | ||
1768 | (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> | ||
1769 | E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; | ||
1770 | |||
1771 | /* Do the reset outside of interrupt context */ | ||
1772 | schedule_work(&adapter->reset_task); | ||
1773 | |||
1774 | /* return immediately since reset is imminent */ | ||
1775 | return IRQ_HANDLED; | ||
1776 | } | ||
1777 | |||
1744 | if (napi_schedule_prep(&adapter->napi)) { | 1778 | if (napi_schedule_prep(&adapter->napi)) { |
1745 | adapter->total_tx_bytes = 0; | 1779 | adapter->total_tx_bytes = 0; |
1746 | adapter->total_tx_packets = 0; | 1780 | adapter->total_tx_packets = 0; |
@@ -2104,6 +2138,8 @@ static void e1000_irq_enable(struct e1000_adapter *adapter) | |||
2104 | if (adapter->msix_entries) { | 2138 | if (adapter->msix_entries) { |
2105 | ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); | 2139 | ew32(EIAC_82574, adapter->eiac_mask & E1000_EIAC_MASK_82574); |
2106 | ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); | 2140 | ew32(IMS, adapter->eiac_mask | E1000_IMS_OTHER | E1000_IMS_LSC); |
2141 | } else if (hw->mac.type == e1000_pch_lpt) { | ||
2142 | ew32(IMS, IMS_ENABLE_MASK | E1000_IMS_ECCER); | ||
2107 | } else { | 2143 | } else { |
2108 | ew32(IMS, IMS_ENABLE_MASK); | 2144 | ew32(IMS, IMS_ENABLE_MASK); |
2109 | } | 2145 | } |
@@ -4251,6 +4287,16 @@ static void e1000e_update_stats(struct e1000_adapter *adapter) | |||
4251 | adapter->stats.mgptc += er32(MGTPTC); | 4287 | adapter->stats.mgptc += er32(MGTPTC); |
4252 | adapter->stats.mgprc += er32(MGTPRC); | 4288 | adapter->stats.mgprc += er32(MGTPRC); |
4253 | adapter->stats.mgpdc += er32(MGTPDC); | 4289 | adapter->stats.mgpdc += er32(MGTPDC); |
4290 | |||
4291 | /* Correctable ECC Errors */ | ||
4292 | if (hw->mac.type == e1000_pch_lpt) { | ||
4293 | u32 pbeccsts = er32(PBECCSTS); | ||
4294 | adapter->corr_errors += | ||
4295 | pbeccsts & E1000_PBECCSTS_CORR_ERR_CNT_MASK; | ||
4296 | adapter->uncorr_errors += | ||
4297 | (pbeccsts & E1000_PBECCSTS_UNCORR_ERR_CNT_MASK) >> | ||
4298 | E1000_PBECCSTS_UNCORR_ERR_CNT_SHIFT; | ||
4299 | } | ||
4254 | } | 4300 | } |
4255 | 4301 | ||
4256 | /** | 4302 | /** |
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile index f3a632bf8d96..687c83d1bdab 100644 --- a/drivers/net/ethernet/intel/ixgbe/Makefile +++ b/drivers/net/ethernet/intel/ixgbe/Makefile | |||
@@ -32,7 +32,7 @@ | |||
32 | 32 | ||
33 | obj-$(CONFIG_IXGBE) += ixgbe.o | 33 | obj-$(CONFIG_IXGBE) += ixgbe.o |
34 | 34 | ||
35 | ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\ | 35 | ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \ |
36 | ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ | 36 | ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \ |
37 | ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o | 37 | ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o |
38 | 38 | ||
@@ -40,4 +40,5 @@ ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \ | |||
40 | ixgbe_dcb_82599.o ixgbe_dcb_nl.o | 40 | ixgbe_dcb_82599.o ixgbe_dcb_nl.o |
41 | 41 | ||
42 | ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o | 42 | ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o |
43 | ixgbe-$(CONFIG_DEBUG_FS) += ixgbe_debugfs.o | ||
43 | ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o | 44 | ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c index 50aa546b8c7a..3504686d3af5 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c | |||
@@ -24,9 +24,6 @@ | |||
24 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 | 24 | Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 |
25 | 25 | ||
26 | *******************************************************************************/ | 26 | *******************************************************************************/ |
27 | |||
28 | #ifdef CONFIG_DEBUG_FS | ||
29 | |||
30 | #include <linux/debugfs.h> | 27 | #include <linux/debugfs.h> |
31 | #include <linux/module.h> | 28 | #include <linux/module.h> |
32 | 29 | ||
@@ -277,5 +274,3 @@ void ixgbe_dbg_exit(void) | |||
277 | { | 274 | { |
278 | debugfs_remove_recursive(ixgbe_dbg_root); | 275 | debugfs_remove_recursive(ixgbe_dbg_root); |
279 | } | 276 | } |
280 | |||
281 | #endif /* CONFIG_DEBUG_FS */ | ||
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 20a5af6d87d0..b3e3294cfe53 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -1401,6 +1401,7 @@ static void ixgbe_set_rsc_gso_size(struct ixgbe_ring *ring, | |||
1401 | /* set gso_size to avoid messing up TCP MSS */ | 1401 | /* set gso_size to avoid messing up TCP MSS */ |
1402 | skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len), | 1402 | skb_shinfo(skb)->gso_size = DIV_ROUND_UP((skb->len - hdr_len), |
1403 | IXGBE_CB(skb)->append_cnt); | 1403 | IXGBE_CB(skb)->append_cnt); |
1404 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | ||
1404 | } | 1405 | } |
1405 | 1406 | ||
1406 | static void ixgbe_update_rsc_stats(struct ixgbe_ring *rx_ring, | 1407 | static void ixgbe_update_rsc_stats(struct ixgbe_ring *rx_ring, |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c index 1a751c9d09c4..bb9256a1b0a9 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c | |||
@@ -660,11 +660,11 @@ int ixgbe_ptp_hwtstamp_ioctl(struct ixgbe_adapter *adapter, | |||
660 | break; | 660 | break; |
661 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: | 661 | case HWTSTAMP_FILTER_PTP_V1_L4_SYNC: |
662 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; | 662 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; |
663 | tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG; | 663 | tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG; |
664 | break; | 664 | break; |
665 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: | 665 | case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ: |
666 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; | 666 | tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1; |
667 | tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG; | 667 | tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG; |
668 | break; | 668 | break; |
669 | case HWTSTAMP_FILTER_PTP_V2_EVENT: | 669 | case HWTSTAMP_FILTER_PTP_V2_EVENT: |
670 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: | 670 | case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: |
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c index 2b799f4f1c37..6771b69f40d5 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c | |||
@@ -630,10 +630,15 @@ netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev) | |||
630 | ring->tx_csum++; | 630 | ring->tx_csum++; |
631 | } | 631 | } |
632 | 632 | ||
633 | /* Copy dst mac address to wqe */ | 633 | if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) { |
634 | ethh = (struct ethhdr *)skb->data; | 634 | /* Copy dst mac address to wqe. This allows loopback in eSwitch, |
635 | tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); | 635 | * so that VFs and PF can communicate with each other |
636 | tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); | 636 | */ |
637 | ethh = (struct ethhdr *)skb->data; | ||
638 | tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest); | ||
639 | tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2)); | ||
640 | } | ||
641 | |||
637 | /* Handle LSO (TSO) packets */ | 642 | /* Handle LSO (TSO) packets */ |
638 | if (lso_header_size) { | 643 | if (lso_header_size) { |
639 | /* Mark opcode as LSO */ | 644 | /* Mark opcode as LSO */ |
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c index e1bafffbc3b1..5163af314990 100644 --- a/drivers/net/ethernet/mellanox/mlx4/main.c +++ b/drivers/net/ethernet/mellanox/mlx4/main.c | |||
@@ -380,7 +380,7 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap) | |||
380 | } | 380 | } |
381 | } | 381 | } |
382 | 382 | ||
383 | if ((dev_cap->flags & | 383 | if ((dev->caps.flags & |
384 | (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) && | 384 | (MLX4_DEV_CAP_FLAG_64B_CQE | MLX4_DEV_CAP_FLAG_64B_EQE)) && |
385 | mlx4_is_master(dev)) | 385 | mlx4_is_master(dev)) |
386 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; | 386 | dev->caps.function_caps |= MLX4_FUNC_CAP_64B_EQE_CQE; |
@@ -1790,15 +1790,8 @@ static void mlx4_enable_msi_x(struct mlx4_dev *dev) | |||
1790 | int i; | 1790 | int i; |
1791 | 1791 | ||
1792 | if (msi_x) { | 1792 | if (msi_x) { |
1793 | /* In multifunction mode each function gets 2 msi-X vectors | 1793 | nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs, |
1794 | * one for data path completions anf the other for asynch events | 1794 | nreq); |
1795 | * or command completions */ | ||
1796 | if (mlx4_is_mfunc(dev)) { | ||
1797 | nreq = 2; | ||
1798 | } else { | ||
1799 | nreq = min_t(int, dev->caps.num_eqs - | ||
1800 | dev->caps.reserved_eqs, nreq); | ||
1801 | } | ||
1802 | 1795 | ||
1803 | entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); | 1796 | entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL); |
1804 | if (!entries) | 1797 | if (!entries) |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c index bc165f4d0f65..695667d471a1 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c | |||
@@ -144,7 +144,7 @@ void netxen_release_tx_buffers(struct netxen_adapter *adapter) | |||
144 | buffrag->length, PCI_DMA_TODEVICE); | 144 | buffrag->length, PCI_DMA_TODEVICE); |
145 | buffrag->dma = 0ULL; | 145 | buffrag->dma = 0ULL; |
146 | } | 146 | } |
147 | for (j = 0; j < cmd_buf->frag_count; j++) { | 147 | for (j = 1; j < cmd_buf->frag_count; j++) { |
148 | buffrag++; | 148 | buffrag++; |
149 | if (buffrag->dma) { | 149 | if (buffrag->dma) { |
150 | pci_unmap_page(adapter->pdev, buffrag->dma, | 150 | pci_unmap_page(adapter->pdev, buffrag->dma, |
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c index 6098fd4adfeb..69e321a65077 100644 --- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c +++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c | |||
@@ -1963,10 +1963,12 @@ unwind: | |||
1963 | while (--i >= 0) { | 1963 | while (--i >= 0) { |
1964 | nf = &pbuf->frag_array[i+1]; | 1964 | nf = &pbuf->frag_array[i+1]; |
1965 | pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); | 1965 | pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE); |
1966 | nf->dma = 0ULL; | ||
1966 | } | 1967 | } |
1967 | 1968 | ||
1968 | nf = &pbuf->frag_array[0]; | 1969 | nf = &pbuf->frag_array[0]; |
1969 | pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); | 1970 | pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE); |
1971 | nf->dma = 0ULL; | ||
1970 | 1972 | ||
1971 | out_err: | 1973 | out_err: |
1972 | return -ENOMEM; | 1974 | return -ENOMEM; |
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c index 6f82812d0fab..09aa310b6194 100644 --- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c +++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_io.c | |||
@@ -986,8 +986,13 @@ qlcnic_process_lro(struct qlcnic_adapter *adapter, | |||
986 | th->seq = htonl(seq_number); | 986 | th->seq = htonl(seq_number); |
987 | length = skb->len; | 987 | length = skb->len; |
988 | 988 | ||
989 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) | 989 | if (adapter->flags & QLCNIC_FW_LRO_MSS_CAP) { |
990 | skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); | 990 | skb_shinfo(skb)->gso_size = qlcnic_get_lro_sts_mss(sts_data1); |
991 | if (skb->protocol == htons(ETH_P_IPV6)) | ||
992 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV6; | ||
993 | else | ||
994 | skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4; | ||
995 | } | ||
991 | 996 | ||
992 | if (vid != 0xffff) | 997 | if (vid != 0xffff) |
993 | __vlan_hwaccel_put_tag(skb, vid); | 998 | __vlan_hwaccel_put_tag(skb, vid); |
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c index f80cd975daed..3e73742024b0 100644 --- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c +++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c | |||
@@ -4678,7 +4678,7 @@ static int qlge_probe(struct pci_dev *pdev, | |||
4678 | qdev = netdev_priv(ndev); | 4678 | qdev = netdev_priv(ndev); |
4679 | SET_NETDEV_DEV(ndev, &pdev->dev); | 4679 | SET_NETDEV_DEV(ndev, &pdev->dev); |
4680 | ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | | 4680 | ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | |
4681 | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN | | 4681 | NETIF_F_TSO | NETIF_F_TSO_ECN | |
4682 | NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; | 4682 | NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM; |
4683 | ndev->features = ndev->hw_features | | 4683 | ndev->features = ndev->hw_features | |
4684 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; | 4684 | NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER; |
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index ed96f309bca8..998974f78742 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c | |||
@@ -450,7 +450,6 @@ enum rtl8168_registers { | |||
450 | #define PWM_EN (1 << 22) | 450 | #define PWM_EN (1 << 22) |
451 | #define RXDV_GATED_EN (1 << 19) | 451 | #define RXDV_GATED_EN (1 << 19) |
452 | #define EARLY_TALLY_EN (1 << 16) | 452 | #define EARLY_TALLY_EN (1 << 16) |
453 | #define FORCE_CLK (1 << 15) /* force clock request */ | ||
454 | }; | 453 | }; |
455 | 454 | ||
456 | enum rtl_register_content { | 455 | enum rtl_register_content { |
@@ -514,7 +513,6 @@ enum rtl_register_content { | |||
514 | PMEnable = (1 << 0), /* Power Management Enable */ | 513 | PMEnable = (1 << 0), /* Power Management Enable */ |
515 | 514 | ||
516 | /* Config2 register p. 25 */ | 515 | /* Config2 register p. 25 */ |
517 | ClkReqEn = (1 << 7), /* Clock Request Enable */ | ||
518 | MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ | 516 | MSIEnable = (1 << 5), /* 8169 only. Reserved in the 8168. */ |
519 | PCI_Clock_66MHz = 0x01, | 517 | PCI_Clock_66MHz = 0x01, |
520 | PCI_Clock_33MHz = 0x00, | 518 | PCI_Clock_33MHz = 0x00, |
@@ -535,7 +533,6 @@ enum rtl_register_content { | |||
535 | Spi_en = (1 << 3), | 533 | Spi_en = (1 << 3), |
536 | LanWake = (1 << 1), /* LanWake enable/disable */ | 534 | LanWake = (1 << 1), /* LanWake enable/disable */ |
537 | PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ | 535 | PMEStatus = (1 << 0), /* PME status can be reset by PCI RST# */ |
538 | ASPM_en = (1 << 0), /* ASPM enable */ | ||
539 | 536 | ||
540 | /* TBICSR p.28 */ | 537 | /* TBICSR p.28 */ |
541 | TBIReset = 0x80000000, | 538 | TBIReset = 0x80000000, |
@@ -684,7 +681,6 @@ enum features { | |||
684 | RTL_FEATURE_WOL = (1 << 0), | 681 | RTL_FEATURE_WOL = (1 << 0), |
685 | RTL_FEATURE_MSI = (1 << 1), | 682 | RTL_FEATURE_MSI = (1 << 1), |
686 | RTL_FEATURE_GMII = (1 << 2), | 683 | RTL_FEATURE_GMII = (1 << 2), |
687 | RTL_FEATURE_FW_LOADED = (1 << 3), | ||
688 | }; | 684 | }; |
689 | 685 | ||
690 | struct rtl8169_counters { | 686 | struct rtl8169_counters { |
@@ -1826,8 +1822,6 @@ static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb) | |||
1826 | 1822 | ||
1827 | if (opts2 & RxVlanTag) | 1823 | if (opts2 & RxVlanTag) |
1828 | __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); | 1824 | __vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff)); |
1829 | |||
1830 | desc->opts2 = 0; | ||
1831 | } | 1825 | } |
1832 | 1826 | ||
1833 | static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) | 1827 | static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd) |
@@ -2391,10 +2385,8 @@ static void rtl_apply_firmware(struct rtl8169_private *tp) | |||
2391 | struct rtl_fw *rtl_fw = tp->rtl_fw; | 2385 | struct rtl_fw *rtl_fw = tp->rtl_fw; |
2392 | 2386 | ||
2393 | /* TODO: release firmware once rtl_phy_write_fw signals failures. */ | 2387 | /* TODO: release firmware once rtl_phy_write_fw signals failures. */ |
2394 | if (!IS_ERR_OR_NULL(rtl_fw)) { | 2388 | if (!IS_ERR_OR_NULL(rtl_fw)) |
2395 | rtl_phy_write_fw(tp, rtl_fw); | 2389 | rtl_phy_write_fw(tp, rtl_fw); |
2396 | tp->features |= RTL_FEATURE_FW_LOADED; | ||
2397 | } | ||
2398 | } | 2390 | } |
2399 | 2391 | ||
2400 | static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) | 2392 | static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) |
@@ -2405,31 +2397,6 @@ static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val) | |||
2405 | rtl_apply_firmware(tp); | 2397 | rtl_apply_firmware(tp); |
2406 | } | 2398 | } |
2407 | 2399 | ||
2408 | static void r810x_aldps_disable(struct rtl8169_private *tp) | ||
2409 | { | ||
2410 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2411 | rtl_writephy(tp, 0x18, 0x0310); | ||
2412 | msleep(100); | ||
2413 | } | ||
2414 | |||
2415 | static void r810x_aldps_enable(struct rtl8169_private *tp) | ||
2416 | { | ||
2417 | if (!(tp->features & RTL_FEATURE_FW_LOADED)) | ||
2418 | return; | ||
2419 | |||
2420 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2421 | rtl_writephy(tp, 0x18, 0x8310); | ||
2422 | } | ||
2423 | |||
2424 | static void r8168_aldps_enable_1(struct rtl8169_private *tp) | ||
2425 | { | ||
2426 | if (!(tp->features & RTL_FEATURE_FW_LOADED)) | ||
2427 | return; | ||
2428 | |||
2429 | rtl_writephy(tp, 0x1f, 0x0000); | ||
2430 | rtl_w1w0_phy(tp, 0x15, 0x1000, 0x0000); | ||
2431 | } | ||
2432 | |||
2433 | static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) | 2400 | static void rtl8169s_hw_phy_config(struct rtl8169_private *tp) |
2434 | { | 2401 | { |
2435 | static const struct phy_reg phy_reg_init[] = { | 2402 | static const struct phy_reg phy_reg_init[] = { |
@@ -3220,8 +3187,6 @@ static void rtl8168e_2_hw_phy_config(struct rtl8169_private *tp) | |||
3220 | rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); | 3187 | rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); |
3221 | rtl_writephy(tp, 0x1f, 0x0000); | 3188 | rtl_writephy(tp, 0x1f, 0x0000); |
3222 | 3189 | ||
3223 | r8168_aldps_enable_1(tp); | ||
3224 | |||
3225 | /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */ | 3190 | /* Broken BIOS workaround: feed GigaMAC registers with MAC address. */ |
3226 | rtl_rar_exgmac_set(tp, tp->dev->dev_addr); | 3191 | rtl_rar_exgmac_set(tp, tp->dev->dev_addr); |
3227 | } | 3192 | } |
@@ -3296,8 +3261,6 @@ static void rtl8168f_1_hw_phy_config(struct rtl8169_private *tp) | |||
3296 | rtl_writephy(tp, 0x05, 0x8b85); | 3261 | rtl_writephy(tp, 0x05, 0x8b85); |
3297 | rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); | 3262 | rtl_w1w0_phy(tp, 0x06, 0x4000, 0x0000); |
3298 | rtl_writephy(tp, 0x1f, 0x0000); | 3263 | rtl_writephy(tp, 0x1f, 0x0000); |
3299 | |||
3300 | r8168_aldps_enable_1(tp); | ||
3301 | } | 3264 | } |
3302 | 3265 | ||
3303 | static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) | 3266 | static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) |
@@ -3305,8 +3268,6 @@ static void rtl8168f_2_hw_phy_config(struct rtl8169_private *tp) | |||
3305 | rtl_apply_firmware(tp); | 3268 | rtl_apply_firmware(tp); |
3306 | 3269 | ||
3307 | rtl8168f_hw_phy_config(tp); | 3270 | rtl8168f_hw_phy_config(tp); |
3308 | |||
3309 | r8168_aldps_enable_1(tp); | ||
3310 | } | 3271 | } |
3311 | 3272 | ||
3312 | static void rtl8411_hw_phy_config(struct rtl8169_private *tp) | 3273 | static void rtl8411_hw_phy_config(struct rtl8169_private *tp) |
@@ -3404,8 +3365,6 @@ static void rtl8411_hw_phy_config(struct rtl8169_private *tp) | |||
3404 | rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); | 3365 | rtl_w1w0_phy(tp, 0x19, 0x0000, 0x0001); |
3405 | rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); | 3366 | rtl_w1w0_phy(tp, 0x10, 0x0000, 0x0400); |
3406 | rtl_writephy(tp, 0x1f, 0x0000); | 3367 | rtl_writephy(tp, 0x1f, 0x0000); |
3407 | |||
3408 | r8168_aldps_enable_1(tp); | ||
3409 | } | 3368 | } |
3410 | 3369 | ||
3411 | static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) | 3370 | static void rtl8168g_1_hw_phy_config(struct rtl8169_private *tp) |
@@ -3491,19 +3450,21 @@ static void rtl8105e_hw_phy_config(struct rtl8169_private *tp) | |||
3491 | }; | 3450 | }; |
3492 | 3451 | ||
3493 | /* Disable ALDPS before ram code */ | 3452 | /* Disable ALDPS before ram code */ |
3494 | r810x_aldps_disable(tp); | 3453 | rtl_writephy(tp, 0x1f, 0x0000); |
3454 | rtl_writephy(tp, 0x18, 0x0310); | ||
3455 | msleep(100); | ||
3495 | 3456 | ||
3496 | rtl_apply_firmware(tp); | 3457 | rtl_apply_firmware(tp); |
3497 | 3458 | ||
3498 | rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); | 3459 | rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); |
3499 | |||
3500 | r810x_aldps_enable(tp); | ||
3501 | } | 3460 | } |
3502 | 3461 | ||
3503 | static void rtl8402_hw_phy_config(struct rtl8169_private *tp) | 3462 | static void rtl8402_hw_phy_config(struct rtl8169_private *tp) |
3504 | { | 3463 | { |
3505 | /* Disable ALDPS before setting firmware */ | 3464 | /* Disable ALDPS before setting firmware */ |
3506 | r810x_aldps_disable(tp); | 3465 | rtl_writephy(tp, 0x1f, 0x0000); |
3466 | rtl_writephy(tp, 0x18, 0x0310); | ||
3467 | msleep(20); | ||
3507 | 3468 | ||
3508 | rtl_apply_firmware(tp); | 3469 | rtl_apply_firmware(tp); |
3509 | 3470 | ||
@@ -3513,8 +3474,6 @@ static void rtl8402_hw_phy_config(struct rtl8169_private *tp) | |||
3513 | rtl_writephy(tp, 0x10, 0x401f); | 3474 | rtl_writephy(tp, 0x10, 0x401f); |
3514 | rtl_writephy(tp, 0x19, 0x7030); | 3475 | rtl_writephy(tp, 0x19, 0x7030); |
3515 | rtl_writephy(tp, 0x1f, 0x0000); | 3476 | rtl_writephy(tp, 0x1f, 0x0000); |
3516 | |||
3517 | r810x_aldps_enable(tp); | ||
3518 | } | 3477 | } |
3519 | 3478 | ||
3520 | static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) | 3479 | static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) |
@@ -3527,7 +3486,9 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) | |||
3527 | }; | 3486 | }; |
3528 | 3487 | ||
3529 | /* Disable ALDPS before ram code */ | 3488 | /* Disable ALDPS before ram code */ |
3530 | r810x_aldps_disable(tp); | 3489 | rtl_writephy(tp, 0x1f, 0x0000); |
3490 | rtl_writephy(tp, 0x18, 0x0310); | ||
3491 | msleep(100); | ||
3531 | 3492 | ||
3532 | rtl_apply_firmware(tp); | 3493 | rtl_apply_firmware(tp); |
3533 | 3494 | ||
@@ -3535,8 +3496,6 @@ static void rtl8106e_hw_phy_config(struct rtl8169_private *tp) | |||
3535 | rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); | 3496 | rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init)); |
3536 | 3497 | ||
3537 | rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); | 3498 | rtl_eri_write(tp, 0x1d0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); |
3538 | |||
3539 | r810x_aldps_enable(tp); | ||
3540 | } | 3499 | } |
3541 | 3500 | ||
3542 | static void rtl_hw_phy_config(struct net_device *dev) | 3501 | static void rtl_hw_phy_config(struct net_device *dev) |
@@ -5053,6 +5012,8 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) | |||
5053 | 5012 | ||
5054 | RTL_W8(MaxTxPacketSize, EarlySize); | 5013 | RTL_W8(MaxTxPacketSize, EarlySize); |
5055 | 5014 | ||
5015 | rtl_disable_clock_request(pdev); | ||
5016 | |||
5056 | RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); | 5017 | RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); |
5057 | RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); | 5018 | RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); |
5058 | 5019 | ||
@@ -5061,8 +5022,7 @@ static void rtl_hw_start_8168e_2(struct rtl8169_private *tp) | |||
5061 | 5022 | ||
5062 | RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); | 5023 | RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); |
5063 | RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); | 5024 | RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); |
5064 | RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en); | 5025 | RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); |
5065 | RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); | ||
5066 | } | 5026 | } |
5067 | 5027 | ||
5068 | static void rtl_hw_start_8168f(struct rtl8169_private *tp) | 5028 | static void rtl_hw_start_8168f(struct rtl8169_private *tp) |
@@ -5087,12 +5047,13 @@ static void rtl_hw_start_8168f(struct rtl8169_private *tp) | |||
5087 | 5047 | ||
5088 | RTL_W8(MaxTxPacketSize, EarlySize); | 5048 | RTL_W8(MaxTxPacketSize, EarlySize); |
5089 | 5049 | ||
5050 | rtl_disable_clock_request(pdev); | ||
5051 | |||
5090 | RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); | 5052 | RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); |
5091 | RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); | 5053 | RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); |
5092 | RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); | 5054 | RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); |
5093 | RTL_W32(MISC, RTL_R32(MISC) | PWM_EN | FORCE_CLK); | 5055 | RTL_W32(MISC, RTL_R32(MISC) | PWM_EN); |
5094 | RTL_W8(Config5, (RTL_R8(Config5) & ~Spi_en) | ASPM_en); | 5056 | RTL_W8(Config5, RTL_R8(Config5) & ~Spi_en); |
5095 | RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); | ||
5096 | } | 5057 | } |
5097 | 5058 | ||
5098 | static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) | 5059 | static void rtl_hw_start_8168f_1(struct rtl8169_private *tp) |
@@ -5149,10 +5110,8 @@ static void rtl_hw_start_8168g_1(struct rtl8169_private *tp) | |||
5149 | rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); | 5110 | rtl_w1w0_eri(tp, 0xdc, ERIAR_MASK_0001, 0x01, 0x00, ERIAR_EXGMAC); |
5150 | 5111 | ||
5151 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); | 5112 | RTL_W8(ChipCmd, CmdTxEnb | CmdRxEnb); |
5152 | RTL_W32(MISC, (RTL_R32(MISC) | FORCE_CLK) & ~RXDV_GATED_EN); | 5113 | RTL_W32(MISC, RTL_R32(MISC) & ~RXDV_GATED_EN); |
5153 | RTL_W8(MaxTxPacketSize, EarlySize); | 5114 | RTL_W8(MaxTxPacketSize, EarlySize); |
5154 | RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); | ||
5155 | RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); | ||
5156 | 5115 | ||
5157 | rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); | 5116 | rtl_eri_write(tp, 0xc0, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); |
5158 | rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); | 5117 | rtl_eri_write(tp, 0xb8, ERIAR_MASK_0011, 0x0000, ERIAR_EXGMAC); |
@@ -5368,9 +5327,6 @@ static void rtl_hw_start_8105e_1(struct rtl8169_private *tp) | |||
5368 | 5327 | ||
5369 | RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); | 5328 | RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); |
5370 | RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); | 5329 | RTL_W8(DLLPR, RTL_R8(DLLPR) | PFM_EN); |
5371 | RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); | ||
5372 | RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); | ||
5373 | RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK); | ||
5374 | 5330 | ||
5375 | rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); | 5331 | rtl_ephy_init(tp, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1)); |
5376 | } | 5332 | } |
@@ -5396,9 +5352,6 @@ static void rtl_hw_start_8402(struct rtl8169_private *tp) | |||
5396 | 5352 | ||
5397 | RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); | 5353 | RTL_W32(TxConfig, RTL_R32(TxConfig) | TXCFG_AUTO_FIFO); |
5398 | RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); | 5354 | RTL_W8(MCU, RTL_R8(MCU) & ~NOW_IS_OOB); |
5399 | RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); | ||
5400 | RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); | ||
5401 | RTL_W32(MISC, RTL_R32(MISC) | FORCE_CLK); | ||
5402 | 5355 | ||
5403 | rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402)); | 5356 | rtl_ephy_init(tp, e_info_8402, ARRAY_SIZE(e_info_8402)); |
5404 | 5357 | ||
@@ -5420,10 +5373,7 @@ static void rtl_hw_start_8106(struct rtl8169_private *tp) | |||
5420 | /* Force LAN exit from ASPM if Rx/Tx are not idle */ | 5373 | /* Force LAN exit from ASPM if Rx/Tx are not idle */ |
5421 | RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); | 5374 | RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800); |
5422 | 5375 | ||
5423 | RTL_W32(MISC, | 5376 | RTL_W32(MISC, (RTL_R32(MISC) | DISABLE_LAN_EN) & ~EARLY_TALLY_EN); |
5424 | (RTL_R32(MISC) | DISABLE_LAN_EN | FORCE_CLK) & ~EARLY_TALLY_EN); | ||
5425 | RTL_W8(Config5, RTL_R8(Config5) | ASPM_en); | ||
5426 | RTL_W8(Config2, RTL_R8(Config2) | ClkReqEn); | ||
5427 | RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); | 5377 | RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET); |
5428 | RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); | 5378 | RTL_W8(DLLPR, RTL_R8(DLLPR) & ~PFM_EN); |
5429 | } | 5379 | } |
@@ -6064,8 +6014,6 @@ static int rtl_rx(struct net_device *dev, struct rtl8169_private *tp, u32 budget | |||
6064 | !(status & (RxRWT | RxFOVF)) && | 6014 | !(status & (RxRWT | RxFOVF)) && |
6065 | (dev->features & NETIF_F_RXALL)) | 6015 | (dev->features & NETIF_F_RXALL)) |
6066 | goto process_pkt; | 6016 | goto process_pkt; |
6067 | |||
6068 | rtl8169_mark_to_asic(desc, rx_buf_sz); | ||
6069 | } else { | 6017 | } else { |
6070 | struct sk_buff *skb; | 6018 | struct sk_buff *skb; |
6071 | dma_addr_t addr; | 6019 | dma_addr_t addr; |
@@ -6086,16 +6034,14 @@ process_pkt: | |||
6086 | if (unlikely(rtl8169_fragmented_frame(status))) { | 6034 | if (unlikely(rtl8169_fragmented_frame(status))) { |
6087 | dev->stats.rx_dropped++; | 6035 | dev->stats.rx_dropped++; |
6088 | dev->stats.rx_length_errors++; | 6036 | dev->stats.rx_length_errors++; |
6089 | rtl8169_mark_to_asic(desc, rx_buf_sz); | 6037 | goto release_descriptor; |
6090 | continue; | ||
6091 | } | 6038 | } |
6092 | 6039 | ||
6093 | skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], | 6040 | skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry], |
6094 | tp, pkt_size, addr); | 6041 | tp, pkt_size, addr); |
6095 | rtl8169_mark_to_asic(desc, rx_buf_sz); | ||
6096 | if (!skb) { | 6042 | if (!skb) { |
6097 | dev->stats.rx_dropped++; | 6043 | dev->stats.rx_dropped++; |
6098 | continue; | 6044 | goto release_descriptor; |
6099 | } | 6045 | } |
6100 | 6046 | ||
6101 | rtl8169_rx_csum(skb, status); | 6047 | rtl8169_rx_csum(skb, status); |
@@ -6111,13 +6057,10 @@ process_pkt: | |||
6111 | tp->rx_stats.bytes += pkt_size; | 6057 | tp->rx_stats.bytes += pkt_size; |
6112 | u64_stats_update_end(&tp->rx_stats.syncp); | 6058 | u64_stats_update_end(&tp->rx_stats.syncp); |
6113 | } | 6059 | } |
6114 | 6060 | release_descriptor: | |
6115 | /* Work around for AMD plateform. */ | 6061 | desc->opts2 = 0; |
6116 | if ((desc->opts2 & cpu_to_le32(0xfffe000)) && | 6062 | wmb(); |
6117 | (tp->mac_version == RTL_GIGA_MAC_VER_05)) { | 6063 | rtl8169_mark_to_asic(desc, rx_buf_sz); |
6118 | desc->opts2 = 0; | ||
6119 | cur_rx++; | ||
6120 | } | ||
6121 | } | 6064 | } |
6122 | 6065 | ||
6123 | count = cur_rx - tp->cur_rx; | 6066 | count = cur_rx - tp->cur_rx; |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index f07c0612abf6..b75f4b286895 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | |||
@@ -69,7 +69,7 @@ | |||
69 | 69 | ||
70 | #undef STMMAC_XMIT_DEBUG | 70 | #undef STMMAC_XMIT_DEBUG |
71 | /*#define STMMAC_XMIT_DEBUG*/ | 71 | /*#define STMMAC_XMIT_DEBUG*/ |
72 | #ifdef STMMAC_TX_DEBUG | 72 | #ifdef STMMAC_XMIT_DEBUG |
73 | #define TX_DBG(fmt, args...) printk(fmt, ## args) | 73 | #define TX_DBG(fmt, args...) printk(fmt, ## args) |
74 | #else | 74 | #else |
75 | #define TX_DBG(fmt, args...) do { } while (0) | 75 | #define TX_DBG(fmt, args...) do { } while (0) |
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index 0376a5e6b2bf..0b9829fe3eea 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c | |||
@@ -188,8 +188,6 @@ int stmmac_mdio_register(struct net_device *ndev) | |||
188 | goto bus_register_fail; | 188 | goto bus_register_fail; |
189 | } | 189 | } |
190 | 190 | ||
191 | priv->mii = new_bus; | ||
192 | |||
193 | found = 0; | 191 | found = 0; |
194 | for (addr = 0; addr < PHY_MAX_ADDR; addr++) { | 192 | for (addr = 0; addr < PHY_MAX_ADDR; addr++) { |
195 | struct phy_device *phydev = new_bus->phy_map[addr]; | 193 | struct phy_device *phydev = new_bus->phy_map[addr]; |
@@ -237,8 +235,14 @@ int stmmac_mdio_register(struct net_device *ndev) | |||
237 | } | 235 | } |
238 | } | 236 | } |
239 | 237 | ||
240 | if (!found) | 238 | if (!found) { |
241 | pr_warning("%s: No PHY found\n", ndev->name); | 239 | pr_warning("%s: No PHY found\n", ndev->name); |
240 | mdiobus_unregister(new_bus); | ||
241 | mdiobus_free(new_bus); | ||
242 | return -ENODEV; | ||
243 | } | ||
244 | |||
245 | priv->mii = new_bus; | ||
242 | 246 | ||
243 | return 0; | 247 | return 0; |
244 | 248 | ||
diff --git a/drivers/net/ethernet/via/via-rhine.c b/drivers/net/ethernet/via/via-rhine.c index 7992b3e05d3d..78ace59efd29 100644 --- a/drivers/net/ethernet/via/via-rhine.c +++ b/drivers/net/ethernet/via/via-rhine.c | |||
@@ -1801,7 +1801,7 @@ static void rhine_tx(struct net_device *dev) | |||
1801 | rp->tx_skbuff[entry]->len, | 1801 | rp->tx_skbuff[entry]->len, |
1802 | PCI_DMA_TODEVICE); | 1802 | PCI_DMA_TODEVICE); |
1803 | } | 1803 | } |
1804 | dev_kfree_skb_irq(rp->tx_skbuff[entry]); | 1804 | dev_kfree_skb(rp->tx_skbuff[entry]); |
1805 | rp->tx_skbuff[entry] = NULL; | 1805 | rp->tx_skbuff[entry] = NULL; |
1806 | entry = (++rp->dirty_tx) % TX_RING_SIZE; | 1806 | entry = (++rp->dirty_tx) % TX_RING_SIZE; |
1807 | } | 1807 | } |
@@ -2010,11 +2010,7 @@ static void rhine_slow_event_task(struct work_struct *work) | |||
2010 | if (intr_status & IntrPCIErr) | 2010 | if (intr_status & IntrPCIErr) |
2011 | netif_warn(rp, hw, dev, "PCI error\n"); | 2011 | netif_warn(rp, hw, dev, "PCI error\n"); |
2012 | 2012 | ||
2013 | napi_disable(&rp->napi); | 2013 | iowrite16(RHINE_EVENT & 0xffff, rp->base + IntrEnable); |
2014 | rhine_irq_disable(rp); | ||
2015 | /* Slow and safe. Consider __napi_schedule as a replacement ? */ | ||
2016 | napi_enable(&rp->napi); | ||
2017 | napi_schedule(&rp->napi); | ||
2018 | 2014 | ||
2019 | out_unlock: | 2015 | out_unlock: |
2020 | mutex_unlock(&rp->task_lock); | 2016 | mutex_unlock(&rp->task_lock); |
diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig index 5778a4ae1164..122d60c0481b 100644 --- a/drivers/net/ethernet/xilinx/Kconfig +++ b/drivers/net/ethernet/xilinx/Kconfig | |||
@@ -27,7 +27,7 @@ config XILINX_EMACLITE | |||
27 | 27 | ||
28 | config XILINX_AXI_EMAC | 28 | config XILINX_AXI_EMAC |
29 | tristate "Xilinx 10/100/1000 AXI Ethernet support" | 29 | tristate "Xilinx 10/100/1000 AXI Ethernet support" |
30 | depends on (PPC32 || MICROBLAZE) | 30 | depends on MICROBLAZE |
31 | select PHYLIB | 31 | select PHYLIB |
32 | ---help--- | 32 | ---help--- |
33 | This driver supports the 10/100/1000 Ethernet from Xilinx for the | 33 | This driver supports the 10/100/1000 Ethernet from Xilinx for the |
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index d9f69b82cc4f..6f47100e58d7 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c | |||
@@ -1590,7 +1590,7 @@ static int axienet_of_probe(struct platform_device *op) | |||
1590 | lp->rx_irq = irq_of_parse_and_map(np, 1); | 1590 | lp->rx_irq = irq_of_parse_and_map(np, 1); |
1591 | lp->tx_irq = irq_of_parse_and_map(np, 0); | 1591 | lp->tx_irq = irq_of_parse_and_map(np, 0); |
1592 | of_node_put(np); | 1592 | of_node_put(np); |
1593 | if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) { | 1593 | if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) { |
1594 | dev_err(&op->dev, "could not determine irqs\n"); | 1594 | dev_err(&op->dev, "could not determine irqs\n"); |
1595 | ret = -ENOMEM; | 1595 | ret = -ENOMEM; |
1596 | goto err_iounmap_2; | 1596 | goto err_iounmap_2; |
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h index 5fd6f4674326..e6fe0d80d612 100644 --- a/drivers/net/hyperv/hyperv_net.h +++ b/drivers/net/hyperv/hyperv_net.h | |||
@@ -84,7 +84,7 @@ struct hv_netvsc_packet { | |||
84 | }; | 84 | }; |
85 | 85 | ||
86 | struct netvsc_device_info { | 86 | struct netvsc_device_info { |
87 | unsigned char mac_adr[6]; | 87 | unsigned char mac_adr[ETH_ALEN]; |
88 | bool link_state; /* 0 - link up, 1 - link down */ | 88 | bool link_state; /* 0 - link up, 1 - link down */ |
89 | int ring_size; | 89 | int ring_size; |
90 | }; | 90 | }; |
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c index f825a629a699..8264f0ef7692 100644 --- a/drivers/net/hyperv/netvsc_drv.c +++ b/drivers/net/hyperv/netvsc_drv.c | |||
@@ -349,7 +349,7 @@ static int netvsc_set_mac_addr(struct net_device *ndev, void *p) | |||
349 | struct net_device_context *ndevctx = netdev_priv(ndev); | 349 | struct net_device_context *ndevctx = netdev_priv(ndev); |
350 | struct hv_device *hdev = ndevctx->device_ctx; | 350 | struct hv_device *hdev = ndevctx->device_ctx; |
351 | struct sockaddr *addr = p; | 351 | struct sockaddr *addr = p; |
352 | char save_adr[14]; | 352 | char save_adr[ETH_ALEN]; |
353 | unsigned char save_aatype; | 353 | unsigned char save_aatype; |
354 | int err; | 354 | int err; |
355 | 355 | ||
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c index 81f8f9e31db5..fcbf680c3e62 100644 --- a/drivers/net/loopback.c +++ b/drivers/net/loopback.c | |||
@@ -77,6 +77,11 @@ static netdev_tx_t loopback_xmit(struct sk_buff *skb, | |||
77 | 77 | ||
78 | skb_orphan(skb); | 78 | skb_orphan(skb); |
79 | 79 | ||
80 | /* Before queueing this packet to netif_rx(), | ||
81 | * make sure dst is refcounted. | ||
82 | */ | ||
83 | skb_dst_force(skb); | ||
84 | |||
80 | skb->protocol = eth_type_trans(skb, dev); | 85 | skb->protocol = eth_type_trans(skb, dev); |
81 | 86 | ||
82 | /* it's OK to use per_cpu_ptr() because BHs are off */ | 87 | /* it's OK to use per_cpu_ptr() because BHs are off */ |
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index 68a43fe602e7..d3fb97d97cbc 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c | |||
@@ -822,7 +822,10 @@ static int macvlan_changelink(struct net_device *dev, | |||
822 | 822 | ||
823 | static size_t macvlan_get_size(const struct net_device *dev) | 823 | static size_t macvlan_get_size(const struct net_device *dev) |
824 | { | 824 | { |
825 | return nla_total_size(4); | 825 | return (0 |
826 | + nla_total_size(4) /* IFLA_MACVLAN_MODE */ | ||
827 | + nla_total_size(2) /* IFLA_MACVLAN_FLAGS */ | ||
828 | ); | ||
826 | } | 829 | } |
827 | 830 | ||
828 | static int macvlan_fill_info(struct sk_buff *skb, | 831 | static int macvlan_fill_info(struct sk_buff *skb, |
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c index d5199cb4caec..b5ddd5077a80 100644 --- a/drivers/net/phy/icplus.c +++ b/drivers/net/phy/icplus.c | |||
@@ -36,8 +36,9 @@ MODULE_LICENSE("GPL"); | |||
36 | 36 | ||
37 | /* IP101A/G - IP1001 */ | 37 | /* IP101A/G - IP1001 */ |
38 | #define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */ | 38 | #define IP10XX_SPEC_CTRL_STATUS 16 /* Spec. Control Register */ |
39 | #define IP1001_RXPHASE_SEL (1<<0) /* Add delay on RX_CLK */ | ||
40 | #define IP1001_TXPHASE_SEL (1<<1) /* Add delay on TX_CLK */ | ||
39 | #define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */ | 41 | #define IP1001_SPEC_CTRL_STATUS_2 20 /* IP1001 Spec. Control Reg 2 */ |
40 | #define IP1001_PHASE_SEL_MASK 3 /* IP1001 RX/TXPHASE_SEL */ | ||
41 | #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ | 42 | #define IP1001_APS_ON 11 /* IP1001 APS Mode bit */ |
42 | #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ | 43 | #define IP101A_G_APS_ON 2 /* IP101A/G APS Mode bit */ |
43 | #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ | 44 | #define IP101A_G_IRQ_CONF_STATUS 0x11 /* Conf Info IRQ & Status Reg */ |
@@ -138,19 +139,24 @@ static int ip1001_config_init(struct phy_device *phydev) | |||
138 | if (c < 0) | 139 | if (c < 0) |
139 | return c; | 140 | return c; |
140 | 141 | ||
141 | /* INTR pin used: speed/link/duplex will cause an interrupt */ | 142 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || |
142 | c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); | 143 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || |
143 | if (c < 0) | 144 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || |
144 | return c; | 145 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) { |
145 | 146 | ||
146 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII) { | ||
147 | /* Additional delay (2ns) used to adjust RX clock phase | ||
148 | * at RGMII interface */ | ||
149 | c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); | 147 | c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); |
150 | if (c < 0) | 148 | if (c < 0) |
151 | return c; | 149 | return c; |
152 | 150 | ||
153 | c |= IP1001_PHASE_SEL_MASK; | 151 | c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); |
152 | |||
153 | if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) | ||
154 | c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL); | ||
155 | else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) | ||
156 | c |= IP1001_RXPHASE_SEL; | ||
157 | else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID) | ||
158 | c |= IP1001_TXPHASE_SEL; | ||
159 | |||
154 | c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); | 160 | c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c); |
155 | if (c < 0) | 161 | if (c < 0) |
156 | return c; | 162 | return c; |
@@ -167,6 +173,11 @@ static int ip101a_g_config_init(struct phy_device *phydev) | |||
167 | if (c < 0) | 173 | if (c < 0) |
168 | return c; | 174 | return c; |
169 | 175 | ||
176 | /* INTR pin used: speed/link/duplex will cause an interrupt */ | ||
177 | c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT); | ||
178 | if (c < 0) | ||
179 | return c; | ||
180 | |||
170 | /* Enable Auto Power Saving mode */ | 181 | /* Enable Auto Power Saving mode */ |
171 | c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); | 182 | c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS); |
172 | c |= IP101A_G_APS_ON; | 183 | c |= IP101A_G_APS_ON; |
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index 5d2a3f215887..22dec9c7ef05 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c | |||
@@ -353,15 +353,6 @@ static int m88e1111_config_init(struct phy_device *phydev) | |||
353 | int err; | 353 | int err; |
354 | int temp; | 354 | int temp; |
355 | 355 | ||
356 | /* Enable Fiber/Copper auto selection */ | ||
357 | temp = phy_read(phydev, MII_M1111_PHY_EXT_SR); | ||
358 | temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO; | ||
359 | phy_write(phydev, MII_M1111_PHY_EXT_SR, temp); | ||
360 | |||
361 | temp = phy_read(phydev, MII_BMCR); | ||
362 | temp |= BMCR_RESET; | ||
363 | phy_write(phydev, MII_BMCR, temp); | ||
364 | |||
365 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || | 356 | if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) || |
366 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || | 357 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) || |
367 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || | 358 | (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) || |
diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fbd106edbe59..2917a86f4c43 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c | |||
@@ -109,11 +109,11 @@ struct tap_filter { | |||
109 | unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; | 109 | unsigned char addr[FLT_EXACT_COUNT][ETH_ALEN]; |
110 | }; | 110 | }; |
111 | 111 | ||
112 | /* 1024 is probably a high enough limit: modern hypervisors seem to support on | 112 | /* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for |
113 | * the order of 100-200 CPUs so this leaves us some breathing space if we want | 113 | * the netdevice to be fit in one page. So we can make sure the success of |
114 | * to match a queue per guest CPU. | 114 | * memory allocation. TODO: increase the limit. */ |
115 | */ | 115 | #define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES |
116 | #define MAX_TAP_QUEUES 1024 | 116 | #define MAX_TAP_FLOWS 4096 |
117 | 117 | ||
118 | #define TUN_FLOW_EXPIRE (3 * HZ) | 118 | #define TUN_FLOW_EXPIRE (3 * HZ) |
119 | 119 | ||
@@ -185,6 +185,8 @@ struct tun_struct { | |||
185 | unsigned long ageing_time; | 185 | unsigned long ageing_time; |
186 | unsigned int numdisabled; | 186 | unsigned int numdisabled; |
187 | struct list_head disabled; | 187 | struct list_head disabled; |
188 | void *security; | ||
189 | u32 flow_count; | ||
188 | }; | 190 | }; |
189 | 191 | ||
190 | static inline u32 tun_hashfn(u32 rxhash) | 192 | static inline u32 tun_hashfn(u32 rxhash) |
@@ -218,6 +220,7 @@ static struct tun_flow_entry *tun_flow_create(struct tun_struct *tun, | |||
218 | e->queue_index = queue_index; | 220 | e->queue_index = queue_index; |
219 | e->tun = tun; | 221 | e->tun = tun; |
220 | hlist_add_head_rcu(&e->hash_link, head); | 222 | hlist_add_head_rcu(&e->hash_link, head); |
223 | ++tun->flow_count; | ||
221 | } | 224 | } |
222 | return e; | 225 | return e; |
223 | } | 226 | } |
@@ -228,6 +231,7 @@ static void tun_flow_delete(struct tun_struct *tun, struct tun_flow_entry *e) | |||
228 | e->rxhash, e->queue_index); | 231 | e->rxhash, e->queue_index); |
229 | hlist_del_rcu(&e->hash_link); | 232 | hlist_del_rcu(&e->hash_link); |
230 | kfree_rcu(e, rcu); | 233 | kfree_rcu(e, rcu); |
234 | --tun->flow_count; | ||
231 | } | 235 | } |
232 | 236 | ||
233 | static void tun_flow_flush(struct tun_struct *tun) | 237 | static void tun_flow_flush(struct tun_struct *tun) |
@@ -294,11 +298,12 @@ static void tun_flow_cleanup(unsigned long data) | |||
294 | } | 298 | } |
295 | 299 | ||
296 | static void tun_flow_update(struct tun_struct *tun, u32 rxhash, | 300 | static void tun_flow_update(struct tun_struct *tun, u32 rxhash, |
297 | u16 queue_index) | 301 | struct tun_file *tfile) |
298 | { | 302 | { |
299 | struct hlist_head *head; | 303 | struct hlist_head *head; |
300 | struct tun_flow_entry *e; | 304 | struct tun_flow_entry *e; |
301 | unsigned long delay = tun->ageing_time; | 305 | unsigned long delay = tun->ageing_time; |
306 | u16 queue_index = tfile->queue_index; | ||
302 | 307 | ||
303 | if (!rxhash) | 308 | if (!rxhash) |
304 | return; | 309 | return; |
@@ -307,7 +312,9 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash, | |||
307 | 312 | ||
308 | rcu_read_lock(); | 313 | rcu_read_lock(); |
309 | 314 | ||
310 | if (tun->numqueues == 1) | 315 | /* We may get a very small possibility of OOO during switching, not |
316 | * worth to optimize.*/ | ||
317 | if (tun->numqueues == 1 || tfile->detached) | ||
311 | goto unlock; | 318 | goto unlock; |
312 | 319 | ||
313 | e = tun_flow_find(head, rxhash); | 320 | e = tun_flow_find(head, rxhash); |
@@ -317,7 +324,8 @@ static void tun_flow_update(struct tun_struct *tun, u32 rxhash, | |||
317 | e->updated = jiffies; | 324 | e->updated = jiffies; |
318 | } else { | 325 | } else { |
319 | spin_lock_bh(&tun->lock); | 326 | spin_lock_bh(&tun->lock); |
320 | if (!tun_flow_find(head, rxhash)) | 327 | if (!tun_flow_find(head, rxhash) && |
328 | tun->flow_count < MAX_TAP_FLOWS) | ||
321 | tun_flow_create(tun, head, rxhash, queue_index); | 329 | tun_flow_create(tun, head, rxhash, queue_index); |
322 | 330 | ||
323 | if (!timer_pending(&tun->flow_gc_timer)) | 331 | if (!timer_pending(&tun->flow_gc_timer)) |
@@ -404,24 +412,23 @@ static void __tun_detach(struct tun_file *tfile, bool clean) | |||
404 | struct tun_struct *tun; | 412 | struct tun_struct *tun; |
405 | struct net_device *dev; | 413 | struct net_device *dev; |
406 | 414 | ||
407 | tun = rcu_dereference_protected(tfile->tun, | 415 | tun = rtnl_dereference(tfile->tun); |
408 | lockdep_rtnl_is_held()); | 416 | |
409 | if (tun) { | 417 | if (tun && !tfile->detached) { |
410 | u16 index = tfile->queue_index; | 418 | u16 index = tfile->queue_index; |
411 | BUG_ON(index >= tun->numqueues); | 419 | BUG_ON(index >= tun->numqueues); |
412 | dev = tun->dev; | 420 | dev = tun->dev; |
413 | 421 | ||
414 | rcu_assign_pointer(tun->tfiles[index], | 422 | rcu_assign_pointer(tun->tfiles[index], |
415 | tun->tfiles[tun->numqueues - 1]); | 423 | tun->tfiles[tun->numqueues - 1]); |
416 | rcu_assign_pointer(tfile->tun, NULL); | 424 | ntfile = rtnl_dereference(tun->tfiles[index]); |
417 | ntfile = rcu_dereference_protected(tun->tfiles[index], | ||
418 | lockdep_rtnl_is_held()); | ||
419 | ntfile->queue_index = index; | 425 | ntfile->queue_index = index; |
420 | 426 | ||
421 | --tun->numqueues; | 427 | --tun->numqueues; |
422 | if (clean) | 428 | if (clean) { |
429 | rcu_assign_pointer(tfile->tun, NULL); | ||
423 | sock_put(&tfile->sk); | 430 | sock_put(&tfile->sk); |
424 | else | 431 | } else |
425 | tun_disable_queue(tun, tfile); | 432 | tun_disable_queue(tun, tfile); |
426 | 433 | ||
427 | synchronize_net(); | 434 | synchronize_net(); |
@@ -429,14 +436,19 @@ static void __tun_detach(struct tun_file *tfile, bool clean) | |||
429 | /* Drop read queue */ | 436 | /* Drop read queue */ |
430 | skb_queue_purge(&tfile->sk.sk_receive_queue); | 437 | skb_queue_purge(&tfile->sk.sk_receive_queue); |
431 | tun_set_real_num_queues(tun); | 438 | tun_set_real_num_queues(tun); |
432 | } else if (tfile->detached && clean) | 439 | } else if (tfile->detached && clean) { |
433 | tun = tun_enable_queue(tfile); | 440 | tun = tun_enable_queue(tfile); |
441 | sock_put(&tfile->sk); | ||
442 | } | ||
434 | 443 | ||
435 | if (clean) { | 444 | if (clean) { |
436 | if (tun && tun->numqueues == 0 && tun->numdisabled == 0 && | 445 | if (tun && tun->numqueues == 0 && tun->numdisabled == 0) { |
437 | !(tun->flags & TUN_PERSIST)) | 446 | netif_carrier_off(tun->dev); |
438 | if (tun->dev->reg_state == NETREG_REGISTERED) | 447 | |
448 | if (!(tun->flags & TUN_PERSIST) && | ||
449 | tun->dev->reg_state == NETREG_REGISTERED) | ||
439 | unregister_netdevice(tun->dev); | 450 | unregister_netdevice(tun->dev); |
451 | } | ||
440 | 452 | ||
441 | BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, | 453 | BUG_ON(!test_bit(SOCK_EXTERNALLY_ALLOCATED, |
442 | &tfile->socket.flags)); | 454 | &tfile->socket.flags)); |
@@ -458,19 +470,21 @@ static void tun_detach_all(struct net_device *dev) | |||
458 | int i, n = tun->numqueues; | 470 | int i, n = tun->numqueues; |
459 | 471 | ||
460 | for (i = 0; i < n; i++) { | 472 | for (i = 0; i < n; i++) { |
461 | tfile = rcu_dereference_protected(tun->tfiles[i], | 473 | tfile = rtnl_dereference(tun->tfiles[i]); |
462 | lockdep_rtnl_is_held()); | ||
463 | BUG_ON(!tfile); | 474 | BUG_ON(!tfile); |
464 | wake_up_all(&tfile->wq.wait); | 475 | wake_up_all(&tfile->wq.wait); |
465 | rcu_assign_pointer(tfile->tun, NULL); | 476 | rcu_assign_pointer(tfile->tun, NULL); |
466 | --tun->numqueues; | 477 | --tun->numqueues; |
467 | } | 478 | } |
479 | list_for_each_entry(tfile, &tun->disabled, next) { | ||
480 | wake_up_all(&tfile->wq.wait); | ||
481 | rcu_assign_pointer(tfile->tun, NULL); | ||
482 | } | ||
468 | BUG_ON(tun->numqueues != 0); | 483 | BUG_ON(tun->numqueues != 0); |
469 | 484 | ||
470 | synchronize_net(); | 485 | synchronize_net(); |
471 | for (i = 0; i < n; i++) { | 486 | for (i = 0; i < n; i++) { |
472 | tfile = rcu_dereference_protected(tun->tfiles[i], | 487 | tfile = rtnl_dereference(tun->tfiles[i]); |
473 | lockdep_rtnl_is_held()); | ||
474 | /* Drop read queue */ | 488 | /* Drop read queue */ |
475 | skb_queue_purge(&tfile->sk.sk_receive_queue); | 489 | skb_queue_purge(&tfile->sk.sk_receive_queue); |
476 | sock_put(&tfile->sk); | 490 | sock_put(&tfile->sk); |
@@ -481,6 +495,9 @@ static void tun_detach_all(struct net_device *dev) | |||
481 | sock_put(&tfile->sk); | 495 | sock_put(&tfile->sk); |
482 | } | 496 | } |
483 | BUG_ON(tun->numdisabled != 0); | 497 | BUG_ON(tun->numdisabled != 0); |
498 | |||
499 | if (tun->flags & TUN_PERSIST) | ||
500 | module_put(THIS_MODULE); | ||
484 | } | 501 | } |
485 | 502 | ||
486 | static int tun_attach(struct tun_struct *tun, struct file *file) | 503 | static int tun_attach(struct tun_struct *tun, struct file *file) |
@@ -488,8 +505,12 @@ static int tun_attach(struct tun_struct *tun, struct file *file) | |||
488 | struct tun_file *tfile = file->private_data; | 505 | struct tun_file *tfile = file->private_data; |
489 | int err; | 506 | int err; |
490 | 507 | ||
508 | err = security_tun_dev_attach(tfile->socket.sk, tun->security); | ||
509 | if (err < 0) | ||
510 | goto out; | ||
511 | |||
491 | err = -EINVAL; | 512 | err = -EINVAL; |
492 | if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held())) | 513 | if (rtnl_dereference(tfile->tun) && !tfile->detached) |
493 | goto out; | 514 | goto out; |
494 | 515 | ||
495 | err = -EBUSY; | 516 | err = -EBUSY; |
@@ -1188,7 +1209,7 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile, | |||
1188 | tun->dev->stats.rx_packets++; | 1209 | tun->dev->stats.rx_packets++; |
1189 | tun->dev->stats.rx_bytes += len; | 1210 | tun->dev->stats.rx_bytes += len; |
1190 | 1211 | ||
1191 | tun_flow_update(tun, rxhash, tfile->queue_index); | 1212 | tun_flow_update(tun, rxhash, tfile); |
1192 | return total_len; | 1213 | return total_len; |
1193 | } | 1214 | } |
1194 | 1215 | ||
@@ -1371,6 +1392,7 @@ static void tun_free_netdev(struct net_device *dev) | |||
1371 | 1392 | ||
1372 | BUG_ON(!(list_empty(&tun->disabled))); | 1393 | BUG_ON(!(list_empty(&tun->disabled))); |
1373 | tun_flow_uninit(tun); | 1394 | tun_flow_uninit(tun); |
1395 | security_tun_dev_free_security(tun->security); | ||
1374 | free_netdev(dev); | 1396 | free_netdev(dev); |
1375 | } | 1397 | } |
1376 | 1398 | ||
@@ -1544,6 +1566,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1544 | struct net_device *dev; | 1566 | struct net_device *dev; |
1545 | int err; | 1567 | int err; |
1546 | 1568 | ||
1569 | if (tfile->detached) | ||
1570 | return -EINVAL; | ||
1571 | |||
1547 | dev = __dev_get_by_name(net, ifr->ifr_name); | 1572 | dev = __dev_get_by_name(net, ifr->ifr_name); |
1548 | if (dev) { | 1573 | if (dev) { |
1549 | if (ifr->ifr_flags & IFF_TUN_EXCL) | 1574 | if (ifr->ifr_flags & IFF_TUN_EXCL) |
@@ -1557,7 +1582,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1557 | 1582 | ||
1558 | if (tun_not_capable(tun)) | 1583 | if (tun_not_capable(tun)) |
1559 | return -EPERM; | 1584 | return -EPERM; |
1560 | err = security_tun_dev_attach(tfile->socket.sk); | 1585 | err = security_tun_dev_open(tun->security); |
1561 | if (err < 0) | 1586 | if (err < 0) |
1562 | return err; | 1587 | return err; |
1563 | 1588 | ||
@@ -1572,6 +1597,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1572 | else { | 1597 | else { |
1573 | char *name; | 1598 | char *name; |
1574 | unsigned long flags = 0; | 1599 | unsigned long flags = 0; |
1600 | int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ? | ||
1601 | MAX_TAP_QUEUES : 1; | ||
1575 | 1602 | ||
1576 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) | 1603 | if (!ns_capable(net->user_ns, CAP_NET_ADMIN)) |
1577 | return -EPERM; | 1604 | return -EPERM; |
@@ -1595,8 +1622,8 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1595 | name = ifr->ifr_name; | 1622 | name = ifr->ifr_name; |
1596 | 1623 | ||
1597 | dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, | 1624 | dev = alloc_netdev_mqs(sizeof(struct tun_struct), name, |
1598 | tun_setup, | 1625 | tun_setup, queues, queues); |
1599 | MAX_TAP_QUEUES, MAX_TAP_QUEUES); | 1626 | |
1600 | if (!dev) | 1627 | if (!dev) |
1601 | return -ENOMEM; | 1628 | return -ENOMEM; |
1602 | 1629 | ||
@@ -1614,7 +1641,9 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1614 | 1641 | ||
1615 | spin_lock_init(&tun->lock); | 1642 | spin_lock_init(&tun->lock); |
1616 | 1643 | ||
1617 | security_tun_dev_post_create(&tfile->sk); | 1644 | err = security_tun_dev_alloc_security(&tun->security); |
1645 | if (err < 0) | ||
1646 | goto err_free_dev; | ||
1618 | 1647 | ||
1619 | tun_net_init(dev); | 1648 | tun_net_init(dev); |
1620 | 1649 | ||
@@ -1639,10 +1668,10 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr) | |||
1639 | device_create_file(&tun->dev->dev, &dev_attr_owner) || | 1668 | device_create_file(&tun->dev->dev, &dev_attr_owner) || |
1640 | device_create_file(&tun->dev->dev, &dev_attr_group)) | 1669 | device_create_file(&tun->dev->dev, &dev_attr_group)) |
1641 | pr_err("Failed to create tun sysfs files\n"); | 1670 | pr_err("Failed to create tun sysfs files\n"); |
1642 | |||
1643 | netif_carrier_on(tun->dev); | ||
1644 | } | 1671 | } |
1645 | 1672 | ||
1673 | netif_carrier_on(tun->dev); | ||
1674 | |||
1646 | tun_debug(KERN_INFO, tun, "tun_set_iff\n"); | 1675 | tun_debug(KERN_INFO, tun, "tun_set_iff\n"); |
1647 | 1676 | ||
1648 | if (ifr->ifr_flags & IFF_NO_PI) | 1677 | if (ifr->ifr_flags & IFF_NO_PI) |
@@ -1738,8 +1767,7 @@ static void tun_detach_filter(struct tun_struct *tun, int n) | |||
1738 | struct tun_file *tfile; | 1767 | struct tun_file *tfile; |
1739 | 1768 | ||
1740 | for (i = 0; i < n; i++) { | 1769 | for (i = 0; i < n; i++) { |
1741 | tfile = rcu_dereference_protected(tun->tfiles[i], | 1770 | tfile = rtnl_dereference(tun->tfiles[i]); |
1742 | lockdep_rtnl_is_held()); | ||
1743 | sk_detach_filter(tfile->socket.sk); | 1771 | sk_detach_filter(tfile->socket.sk); |
1744 | } | 1772 | } |
1745 | 1773 | ||
@@ -1752,8 +1780,7 @@ static int tun_attach_filter(struct tun_struct *tun) | |||
1752 | struct tun_file *tfile; | 1780 | struct tun_file *tfile; |
1753 | 1781 | ||
1754 | for (i = 0; i < tun->numqueues; i++) { | 1782 | for (i = 0; i < tun->numqueues; i++) { |
1755 | tfile = rcu_dereference_protected(tun->tfiles[i], | 1783 | tfile = rtnl_dereference(tun->tfiles[i]); |
1756 | lockdep_rtnl_is_held()); | ||
1757 | ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); | 1784 | ret = sk_attach_filter(&tun->fprog, tfile->socket.sk); |
1758 | if (ret) { | 1785 | if (ret) { |
1759 | tun_detach_filter(tun, i); | 1786 | tun_detach_filter(tun, i); |
@@ -1771,8 +1798,7 @@ static void tun_set_sndbuf(struct tun_struct *tun) | |||
1771 | int i; | 1798 | int i; |
1772 | 1799 | ||
1773 | for (i = 0; i < tun->numqueues; i++) { | 1800 | for (i = 0; i < tun->numqueues; i++) { |
1774 | tfile = rcu_dereference_protected(tun->tfiles[i], | 1801 | tfile = rtnl_dereference(tun->tfiles[i]); |
1775 | lockdep_rtnl_is_held()); | ||
1776 | tfile->socket.sk->sk_sndbuf = tun->sndbuf; | 1802 | tfile->socket.sk->sk_sndbuf = tun->sndbuf; |
1777 | } | 1803 | } |
1778 | } | 1804 | } |
@@ -1787,22 +1813,24 @@ static int tun_set_queue(struct file *file, struct ifreq *ifr) | |||
1787 | 1813 | ||
1788 | if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { | 1814 | if (ifr->ifr_flags & IFF_ATTACH_QUEUE) { |
1789 | tun = tfile->detached; | 1815 | tun = tfile->detached; |
1790 | if (!tun) | 1816 | if (!tun) { |
1791 | ret = -EINVAL; | 1817 | ret = -EINVAL; |
1792 | else if (tun_not_capable(tun)) | 1818 | goto unlock; |
1793 | ret = -EPERM; | 1819 | } |
1794 | else | 1820 | ret = security_tun_dev_attach_queue(tun->security); |
1795 | ret = tun_attach(tun, file); | 1821 | if (ret < 0) |
1822 | goto unlock; | ||
1823 | ret = tun_attach(tun, file); | ||
1796 | } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { | 1824 | } else if (ifr->ifr_flags & IFF_DETACH_QUEUE) { |
1797 | tun = rcu_dereference_protected(tfile->tun, | 1825 | tun = rtnl_dereference(tfile->tun); |
1798 | lockdep_rtnl_is_held()); | 1826 | if (!tun || !(tun->flags & TUN_TAP_MQ) || tfile->detached) |
1799 | if (!tun || !(tun->flags & TUN_TAP_MQ)) | ||
1800 | ret = -EINVAL; | 1827 | ret = -EINVAL; |
1801 | else | 1828 | else |
1802 | __tun_detach(tfile, false); | 1829 | __tun_detach(tfile, false); |
1803 | } else | 1830 | } else |
1804 | ret = -EINVAL; | 1831 | ret = -EINVAL; |
1805 | 1832 | ||
1833 | unlock: | ||
1806 | rtnl_unlock(); | 1834 | rtnl_unlock(); |
1807 | return ret; | 1835 | return ret; |
1808 | } | 1836 | } |
@@ -1880,10 +1908,11 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, | |||
1880 | /* Disable/Enable persist mode. Keep an extra reference to the | 1908 | /* Disable/Enable persist mode. Keep an extra reference to the |
1881 | * module to prevent the module being unprobed. | 1909 | * module to prevent the module being unprobed. |
1882 | */ | 1910 | */ |
1883 | if (arg) { | 1911 | if (arg && !(tun->flags & TUN_PERSIST)) { |
1884 | tun->flags |= TUN_PERSIST; | 1912 | tun->flags |= TUN_PERSIST; |
1885 | __module_get(THIS_MODULE); | 1913 | __module_get(THIS_MODULE); |
1886 | } else { | 1914 | } |
1915 | if (!arg && (tun->flags & TUN_PERSIST)) { | ||
1887 | tun->flags &= ~TUN_PERSIST; | 1916 | tun->flags &= ~TUN_PERSIST; |
1888 | module_put(THIS_MODULE); | 1917 | module_put(THIS_MODULE); |
1889 | } | 1918 | } |
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c index 42f51c71ec1f..248d2dc765a5 100644 --- a/drivers/net/usb/cdc_mbim.c +++ b/drivers/net/usb/cdc_mbim.c | |||
@@ -374,6 +374,21 @@ static const struct driver_info cdc_mbim_info = { | |||
374 | .tx_fixup = cdc_mbim_tx_fixup, | 374 | .tx_fixup = cdc_mbim_tx_fixup, |
375 | }; | 375 | }; |
376 | 376 | ||
377 | /* MBIM and NCM devices should not need a ZLP after NTBs with | ||
378 | * dwNtbOutMaxSize length. This driver_info is for the exceptional | ||
379 | * devices requiring it anyway, allowing them to be supported without | ||
380 | * forcing the performance penalty on all the sane devices. | ||
381 | */ | ||
382 | static const struct driver_info cdc_mbim_info_zlp = { | ||
383 | .description = "CDC MBIM", | ||
384 | .flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP, | ||
385 | .bind = cdc_mbim_bind, | ||
386 | .unbind = cdc_mbim_unbind, | ||
387 | .manage_power = cdc_mbim_manage_power, | ||
388 | .rx_fixup = cdc_mbim_rx_fixup, | ||
389 | .tx_fixup = cdc_mbim_tx_fixup, | ||
390 | }; | ||
391 | |||
377 | static const struct usb_device_id mbim_devs[] = { | 392 | static const struct usb_device_id mbim_devs[] = { |
378 | /* This duplicate NCM entry is intentional. MBIM devices can | 393 | /* This duplicate NCM entry is intentional. MBIM devices can |
379 | * be disguised as NCM by default, and this is necessary to | 394 | * be disguised as NCM by default, and this is necessary to |
@@ -385,6 +400,10 @@ static const struct usb_device_id mbim_devs[] = { | |||
385 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), | 400 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), |
386 | .driver_info = (unsigned long)&cdc_mbim_info, | 401 | .driver_info = (unsigned long)&cdc_mbim_info, |
387 | }, | 402 | }, |
403 | /* Sierra Wireless MC7710 need ZLPs */ | ||
404 | { USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), | ||
405 | .driver_info = (unsigned long)&cdc_mbim_info_zlp, | ||
406 | }, | ||
388 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), | 407 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE), |
389 | .driver_info = (unsigned long)&cdc_mbim_info, | 408 | .driver_info = (unsigned long)&cdc_mbim_info, |
390 | }, | 409 | }, |
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c index 71b6e92b8e9b..00d3b2d37828 100644 --- a/drivers/net/usb/cdc_ncm.c +++ b/drivers/net/usb/cdc_ncm.c | |||
@@ -435,6 +435,13 @@ advance: | |||
435 | len -= temp; | 435 | len -= temp; |
436 | } | 436 | } |
437 | 437 | ||
438 | /* some buggy devices have an IAD but no CDC Union */ | ||
439 | if (!ctx->union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) { | ||
440 | ctx->control = intf; | ||
441 | ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1); | ||
442 | dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n"); | ||
443 | } | ||
444 | |||
438 | /* check if we got everything */ | 445 | /* check if we got everything */ |
439 | if ((ctx->control == NULL) || (ctx->data == NULL) || | 446 | if ((ctx->control == NULL) || (ctx->data == NULL) || |
440 | ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf)))) | 447 | ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf)))) |
@@ -497,7 +504,8 @@ advance: | |||
497 | error2: | 504 | error2: |
498 | usb_set_intfdata(ctx->control, NULL); | 505 | usb_set_intfdata(ctx->control, NULL); |
499 | usb_set_intfdata(ctx->data, NULL); | 506 | usb_set_intfdata(ctx->data, NULL); |
500 | usb_driver_release_interface(driver, ctx->data); | 507 | if (ctx->data != ctx->control) |
508 | usb_driver_release_interface(driver, ctx->data); | ||
501 | error: | 509 | error: |
502 | cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); | 510 | cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]); |
503 | dev->data[0] = 0; | 511 | dev->data[0] = 0; |
@@ -1155,6 +1163,20 @@ static const struct driver_info wwan_info = { | |||
1155 | .tx_fixup = cdc_ncm_tx_fixup, | 1163 | .tx_fixup = cdc_ncm_tx_fixup, |
1156 | }; | 1164 | }; |
1157 | 1165 | ||
1166 | /* Same as wwan_info, but with FLAG_NOARP */ | ||
1167 | static const struct driver_info wwan_noarp_info = { | ||
1168 | .description = "Mobile Broadband Network Device (NO ARP)", | ||
1169 | .flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET | ||
1170 | | FLAG_WWAN | FLAG_NOARP, | ||
1171 | .bind = cdc_ncm_bind, | ||
1172 | .unbind = cdc_ncm_unbind, | ||
1173 | .check_connect = cdc_ncm_check_connect, | ||
1174 | .manage_power = usbnet_manage_power, | ||
1175 | .status = cdc_ncm_status, | ||
1176 | .rx_fixup = cdc_ncm_rx_fixup, | ||
1177 | .tx_fixup = cdc_ncm_tx_fixup, | ||
1178 | }; | ||
1179 | |||
1158 | static const struct usb_device_id cdc_devs[] = { | 1180 | static const struct usb_device_id cdc_devs[] = { |
1159 | /* Ericsson MBM devices like F5521gw */ | 1181 | /* Ericsson MBM devices like F5521gw */ |
1160 | { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO | 1182 | { .match_flags = USB_DEVICE_ID_MATCH_INT_INFO |
@@ -1193,6 +1215,16 @@ static const struct usb_device_id cdc_devs[] = { | |||
1193 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), | 1215 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x46), |
1194 | .driver_info = (unsigned long)&wwan_info, | 1216 | .driver_info = (unsigned long)&wwan_info, |
1195 | }, | 1217 | }, |
1218 | { USB_VENDOR_AND_INTERFACE_INFO(0x12d1, 0xff, 0x02, 0x76), | ||
1219 | .driver_info = (unsigned long)&wwan_info, | ||
1220 | }, | ||
1221 | |||
1222 | /* Infineon(now Intel) HSPA Modem platform */ | ||
1223 | { USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443, | ||
1224 | USB_CLASS_COMM, | ||
1225 | USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE), | ||
1226 | .driver_info = (unsigned long)&wwan_noarp_info, | ||
1227 | }, | ||
1196 | 1228 | ||
1197 | /* Generic CDC-NCM devices */ | 1229 | /* Generic CDC-NCM devices */ |
1198 | { USB_INTERFACE_INFO(USB_CLASS_COMM, | 1230 | { USB_INTERFACE_INFO(USB_CLASS_COMM, |
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c index 3f554c1149f3..d7e99445518e 100644 --- a/drivers/net/usb/dm9601.c +++ b/drivers/net/usb/dm9601.c | |||
@@ -45,6 +45,12 @@ | |||
45 | #define DM_MCAST_ADDR 0x16 /* 8 bytes */ | 45 | #define DM_MCAST_ADDR 0x16 /* 8 bytes */ |
46 | #define DM_GPR_CTRL 0x1e | 46 | #define DM_GPR_CTRL 0x1e |
47 | #define DM_GPR_DATA 0x1f | 47 | #define DM_GPR_DATA 0x1f |
48 | #define DM_CHIP_ID 0x2c | ||
49 | #define DM_MODE_CTRL 0x91 /* only on dm9620 */ | ||
50 | |||
51 | /* chip id values */ | ||
52 | #define ID_DM9601 0 | ||
53 | #define ID_DM9620 1 | ||
48 | 54 | ||
49 | #define DM_MAX_MCAST 64 | 55 | #define DM_MAX_MCAST 64 |
50 | #define DM_MCAST_SIZE 8 | 56 | #define DM_MCAST_SIZE 8 |
@@ -53,7 +59,6 @@ | |||
53 | #define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ | 59 | #define DM_RX_OVERHEAD 7 /* 3 byte header + 4 byte crc tail */ |
54 | #define DM_TIMEOUT 1000 | 60 | #define DM_TIMEOUT 1000 |
55 | 61 | ||
56 | |||
57 | static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) | 62 | static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data) |
58 | { | 63 | { |
59 | int err; | 64 | int err; |
@@ -84,32 +89,23 @@ static int dm_write(struct usbnet *dev, u8 reg, u16 length, void *data) | |||
84 | 89 | ||
85 | static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) | 90 | static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value) |
86 | { | 91 | { |
87 | return usbnet_write_cmd(dev, DM_WRITE_REGS, | 92 | return usbnet_write_cmd(dev, DM_WRITE_REG, |
88 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 93 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
89 | value, reg, NULL, 0); | 94 | value, reg, NULL, 0); |
90 | } | 95 | } |
91 | 96 | ||
92 | static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value, | 97 | static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) |
93 | u16 length, void *data) | ||
94 | { | 98 | { |
95 | usbnet_write_cmd_async(dev, DM_WRITE_REGS, | 99 | usbnet_write_cmd_async(dev, DM_WRITE_REGS, |
96 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | 100 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
97 | value, reg, data, length); | 101 | 0, reg, data, length); |
98 | } | ||
99 | |||
100 | static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data) | ||
101 | { | ||
102 | netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length); | ||
103 | |||
104 | dm_write_async_helper(dev, reg, 0, length, data); | ||
105 | } | 102 | } |
106 | 103 | ||
107 | static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) | 104 | static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value) |
108 | { | 105 | { |
109 | netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n", | 106 | usbnet_write_cmd_async(dev, DM_WRITE_REG, |
110 | reg, value); | 107 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, |
111 | 108 | value, reg, NULL, 0); | |
112 | dm_write_async_helper(dev, reg, value, 0, NULL); | ||
113 | } | 109 | } |
114 | 110 | ||
115 | static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value) | 111 | static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value) |
@@ -358,7 +354,7 @@ static const struct net_device_ops dm9601_netdev_ops = { | |||
358 | static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) | 354 | static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) |
359 | { | 355 | { |
360 | int ret; | 356 | int ret; |
361 | u8 mac[ETH_ALEN]; | 357 | u8 mac[ETH_ALEN], id; |
362 | 358 | ||
363 | ret = usbnet_get_endpoints(dev, intf); | 359 | ret = usbnet_get_endpoints(dev, intf); |
364 | if (ret) | 360 | if (ret) |
@@ -399,6 +395,24 @@ static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf) | |||
399 | __dm9601_set_mac_address(dev); | 395 | __dm9601_set_mac_address(dev); |
400 | } | 396 | } |
401 | 397 | ||
398 | if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) { | ||
399 | netdev_err(dev->net, "Error reading chip ID\n"); | ||
400 | ret = -ENODEV; | ||
401 | goto out; | ||
402 | } | ||
403 | |||
404 | /* put dm9620 devices in dm9601 mode */ | ||
405 | if (id == ID_DM9620) { | ||
406 | u8 mode; | ||
407 | |||
408 | if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) { | ||
409 | netdev_err(dev->net, "Error reading MODE_CTRL\n"); | ||
410 | ret = -ENODEV; | ||
411 | goto out; | ||
412 | } | ||
413 | dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f); | ||
414 | } | ||
415 | |||
402 | /* power up phy */ | 416 | /* power up phy */ |
403 | dm_write_reg(dev, DM_GPR_CTRL, 1); | 417 | dm_write_reg(dev, DM_GPR_CTRL, 1); |
404 | dm_write_reg(dev, DM_GPR_DATA, 0); | 418 | dm_write_reg(dev, DM_GPR_DATA, 0); |
@@ -581,6 +595,10 @@ static const struct usb_device_id products[] = { | |||
581 | USB_DEVICE(0x0a46, 0x9000), /* DM9000E */ | 595 | USB_DEVICE(0x0a46, 0x9000), /* DM9000E */ |
582 | .driver_info = (unsigned long)&dm9601_info, | 596 | .driver_info = (unsigned long)&dm9601_info, |
583 | }, | 597 | }, |
598 | { | ||
599 | USB_DEVICE(0x0a46, 0x9620), /* DM9620 USB to Fast Ethernet Adapter */ | ||
600 | .driver_info = (unsigned long)&dm9601_info, | ||
601 | }, | ||
584 | {}, // END | 602 | {}, // END |
585 | }; | 603 | }; |
586 | 604 | ||
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c index 6a1ca500e612..19d903598b0d 100644 --- a/drivers/net/usb/qmi_wwan.c +++ b/drivers/net/usb/qmi_wwan.c | |||
@@ -351,6 +351,10 @@ static const struct usb_device_id products[] = { | |||
351 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), | 351 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 57), |
352 | .driver_info = (unsigned long)&qmi_wwan_info, | 352 | .driver_info = (unsigned long)&qmi_wwan_info, |
353 | }, | 353 | }, |
354 | { /* HUAWEI_INTERFACE_NDIS_CONTROL_QUALCOMM */ | ||
355 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x69), | ||
356 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
357 | }, | ||
354 | 358 | ||
355 | /* 2. Combined interface devices matching on class+protocol */ | 359 | /* 2. Combined interface devices matching on class+protocol */ |
356 | { /* Huawei E367 and possibly others in "Windows mode" */ | 360 | { /* Huawei E367 and possibly others in "Windows mode" */ |
@@ -361,6 +365,14 @@ static const struct usb_device_id products[] = { | |||
361 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), | 365 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17), |
362 | .driver_info = (unsigned long)&qmi_wwan_info, | 366 | .driver_info = (unsigned long)&qmi_wwan_info, |
363 | }, | 367 | }, |
368 | { /* HUAWEI_NDIS_SINGLE_INTERFACE_VDF */ | ||
369 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x37), | ||
370 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
371 | }, | ||
372 | { /* HUAWEI_INTERFACE_NDIS_HW_QUALCOMM */ | ||
373 | USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 0x01, 0x67), | ||
374 | .driver_info = (unsigned long)&qmi_wwan_info, | ||
375 | }, | ||
364 | { /* Pantech UML290, P4200 and more */ | 376 | { /* Pantech UML290, P4200 and more */ |
365 | USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), | 377 | USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff), |
366 | .driver_info = (unsigned long)&qmi_wwan_info, | 378 | .driver_info = (unsigned long)&qmi_wwan_info, |
@@ -399,6 +411,7 @@ static const struct usb_device_id products[] = { | |||
399 | }, | 411 | }, |
400 | 412 | ||
401 | /* 3. Combined interface devices matching on interface number */ | 413 | /* 3. Combined interface devices matching on interface number */ |
414 | {QMI_FIXED_INTF(0x0408, 0xea42, 4)}, /* Yota / Megafon M100-1 */ | ||
402 | {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ | 415 | {QMI_FIXED_INTF(0x12d1, 0x140c, 1)}, /* Huawei E173 */ |
403 | {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, | 416 | {QMI_FIXED_INTF(0x19d2, 0x0002, 1)}, |
404 | {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, | 417 | {QMI_FIXED_INTF(0x19d2, 0x0012, 1)}, |
@@ -433,6 +446,7 @@ static const struct usb_device_id products[] = { | |||
433 | {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ | 446 | {QMI_FIXED_INTF(0x19d2, 0x0199, 1)}, /* ZTE MF820S */ |
434 | {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, | 447 | {QMI_FIXED_INTF(0x19d2, 0x0200, 1)}, |
435 | {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ | 448 | {QMI_FIXED_INTF(0x19d2, 0x0257, 3)}, /* ZTE MF821 */ |
449 | {QMI_FIXED_INTF(0x19d2, 0x0265, 4)}, /* ONDA MT8205 4G LTE */ | ||
436 | {QMI_FIXED_INTF(0x19d2, 0x0284, 4)}, /* ZTE MF880 */ | 450 | {QMI_FIXED_INTF(0x19d2, 0x0284, 4)}, /* ZTE MF880 */ |
437 | {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ | 451 | {QMI_FIXED_INTF(0x19d2, 0x0326, 4)}, /* ZTE MF821D */ |
438 | {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ | 452 | {QMI_FIXED_INTF(0x19d2, 0x1008, 4)}, /* ZTE (Vodafone) K3570-Z */ |
@@ -459,6 +473,8 @@ static const struct usb_device_id products[] = { | |||
459 | {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ | 473 | {QMI_FIXED_INTF(0x1199, 0x68a2, 19)}, /* Sierra Wireless MC7710 in QMI mode */ |
460 | {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ | 474 | {QMI_FIXED_INTF(0x1199, 0x901c, 8)}, /* Sierra Wireless EM7700 */ |
461 | {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ | 475 | {QMI_FIXED_INTF(0x1bbb, 0x011e, 4)}, /* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */ |
476 | {QMI_FIXED_INTF(0x2357, 0x0201, 4)}, /* TP-LINK HSUPA Modem MA180 */ | ||
477 | {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */ | ||
462 | 478 | ||
463 | /* 4. Gobi 1000 devices */ | 479 | /* 4. Gobi 1000 devices */ |
464 | {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ | 480 | {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)}, /* Acer Gobi Modem Device */ |
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c index 3d4bf01641b4..5e33606c1366 100644 --- a/drivers/net/usb/usbnet.c +++ b/drivers/net/usb/usbnet.c | |||
@@ -380,6 +380,12 @@ static int rx_submit (struct usbnet *dev, struct urb *urb, gfp_t flags) | |||
380 | unsigned long lockflags; | 380 | unsigned long lockflags; |
381 | size_t size = dev->rx_urb_size; | 381 | size_t size = dev->rx_urb_size; |
382 | 382 | ||
383 | /* prevent rx skb allocation when error ratio is high */ | ||
384 | if (test_bit(EVENT_RX_KILL, &dev->flags)) { | ||
385 | usb_free_urb(urb); | ||
386 | return -ENOLINK; | ||
387 | } | ||
388 | |||
383 | skb = __netdev_alloc_skb_ip_align(dev->net, size, flags); | 389 | skb = __netdev_alloc_skb_ip_align(dev->net, size, flags); |
384 | if (!skb) { | 390 | if (!skb) { |
385 | netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); | 391 | netif_dbg(dev, rx_err, dev->net, "no rx skb\n"); |
@@ -539,6 +545,17 @@ block: | |||
539 | break; | 545 | break; |
540 | } | 546 | } |
541 | 547 | ||
548 | /* stop rx if packet error rate is high */ | ||
549 | if (++dev->pkt_cnt > 30) { | ||
550 | dev->pkt_cnt = 0; | ||
551 | dev->pkt_err = 0; | ||
552 | } else { | ||
553 | if (state == rx_cleanup) | ||
554 | dev->pkt_err++; | ||
555 | if (dev->pkt_err > 20) | ||
556 | set_bit(EVENT_RX_KILL, &dev->flags); | ||
557 | } | ||
558 | |||
542 | state = defer_bh(dev, skb, &dev->rxq, state); | 559 | state = defer_bh(dev, skb, &dev->rxq, state); |
543 | 560 | ||
544 | if (urb) { | 561 | if (urb) { |
@@ -791,6 +808,11 @@ int usbnet_open (struct net_device *net) | |||
791 | (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" : | 808 | (dev->driver_info->flags & FLAG_FRAMING_AX) ? "ASIX" : |
792 | "simple"); | 809 | "simple"); |
793 | 810 | ||
811 | /* reset rx error state */ | ||
812 | dev->pkt_cnt = 0; | ||
813 | dev->pkt_err = 0; | ||
814 | clear_bit(EVENT_RX_KILL, &dev->flags); | ||
815 | |||
794 | // delay posting reads until we're fully open | 816 | // delay posting reads until we're fully open |
795 | tasklet_schedule (&dev->bh); | 817 | tasklet_schedule (&dev->bh); |
796 | if (info->manage_power) { | 818 | if (info->manage_power) { |
@@ -1103,13 +1125,11 @@ netdev_tx_t usbnet_start_xmit (struct sk_buff *skb, | |||
1103 | if (info->tx_fixup) { | 1125 | if (info->tx_fixup) { |
1104 | skb = info->tx_fixup (dev, skb, GFP_ATOMIC); | 1126 | skb = info->tx_fixup (dev, skb, GFP_ATOMIC); |
1105 | if (!skb) { | 1127 | if (!skb) { |
1106 | if (netif_msg_tx_err(dev)) { | 1128 | /* packet collected; minidriver waiting for more */ |
1107 | netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); | 1129 | if (info->flags & FLAG_MULTI_PACKET) |
1108 | goto drop; | ||
1109 | } else { | ||
1110 | /* cdc_ncm collected packet; waits for more */ | ||
1111 | goto not_drop; | 1130 | goto not_drop; |
1112 | } | 1131 | netif_dbg(dev, tx_err, dev->net, "can't tx_fixup skb\n"); |
1132 | goto drop; | ||
1113 | } | 1133 | } |
1114 | } | 1134 | } |
1115 | length = skb->len; | 1135 | length = skb->len; |
@@ -1254,6 +1274,9 @@ static void usbnet_bh (unsigned long param) | |||
1254 | } | 1274 | } |
1255 | } | 1275 | } |
1256 | 1276 | ||
1277 | /* restart RX again after disabling due to high error rate */ | ||
1278 | clear_bit(EVENT_RX_KILL, &dev->flags); | ||
1279 | |||
1257 | // waiting for all pending urbs to complete? | 1280 | // waiting for all pending urbs to complete? |
1258 | if (dev->wait) { | 1281 | if (dev->wait) { |
1259 | if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { | 1282 | if ((dev->txq.qlen + dev->rxq.qlen + dev->done.qlen) == 0) { |
@@ -1448,6 +1471,10 @@ usbnet_probe (struct usb_interface *udev, const struct usb_device_id *prod) | |||
1448 | if ((dev->driver_info->flags & FLAG_WWAN) != 0) | 1471 | if ((dev->driver_info->flags & FLAG_WWAN) != 0) |
1449 | strcpy(net->name, "wwan%d"); | 1472 | strcpy(net->name, "wwan%d"); |
1450 | 1473 | ||
1474 | /* devices that cannot do ARP */ | ||
1475 | if ((dev->driver_info->flags & FLAG_NOARP) != 0) | ||
1476 | net->flags |= IFF_NOARP; | ||
1477 | |||
1451 | /* maybe the remote can't receive an Ethernet MTU */ | 1478 | /* maybe the remote can't receive an Ethernet MTU */ |
1452 | if (net->mtu > (dev->hard_mtu - net->hard_header_len)) | 1479 | if (net->mtu > (dev->hard_mtu - net->hard_header_len)) |
1453 | net->mtu = dev->hard_mtu - net->hard_header_len; | 1480 | net->mtu = dev->hard_mtu - net->hard_header_len; |
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index a6fcf15adc4f..35c00c5ea02a 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/scatterlist.h> | 26 | #include <linux/scatterlist.h> |
27 | #include <linux/if_vlan.h> | 27 | #include <linux/if_vlan.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/cpu.h> | ||
29 | 30 | ||
30 | static int napi_weight = 128; | 31 | static int napi_weight = 128; |
31 | module_param(napi_weight, int, 0444); | 32 | module_param(napi_weight, int, 0444); |
@@ -123,6 +124,12 @@ struct virtnet_info { | |||
123 | 124 | ||
124 | /* Does the affinity hint is set for virtqueues? */ | 125 | /* Does the affinity hint is set for virtqueues? */ |
125 | bool affinity_hint_set; | 126 | bool affinity_hint_set; |
127 | |||
128 | /* Per-cpu variable to show the mapping from CPU to virtqueue */ | ||
129 | int __percpu *vq_index; | ||
130 | |||
131 | /* CPU hot plug notifier */ | ||
132 | struct notifier_block nb; | ||
126 | }; | 133 | }; |
127 | 134 | ||
128 | struct skb_vnet_hdr { | 135 | struct skb_vnet_hdr { |
@@ -1013,32 +1020,75 @@ static int virtnet_vlan_rx_kill_vid(struct net_device *dev, u16 vid) | |||
1013 | return 0; | 1020 | return 0; |
1014 | } | 1021 | } |
1015 | 1022 | ||
1016 | static void virtnet_set_affinity(struct virtnet_info *vi, bool set) | 1023 | static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu) |
1017 | { | 1024 | { |
1018 | int i; | 1025 | int i; |
1026 | int cpu; | ||
1027 | |||
1028 | if (vi->affinity_hint_set) { | ||
1029 | for (i = 0; i < vi->max_queue_pairs; i++) { | ||
1030 | virtqueue_set_affinity(vi->rq[i].vq, -1); | ||
1031 | virtqueue_set_affinity(vi->sq[i].vq, -1); | ||
1032 | } | ||
1033 | |||
1034 | vi->affinity_hint_set = false; | ||
1035 | } | ||
1036 | |||
1037 | i = 0; | ||
1038 | for_each_online_cpu(cpu) { | ||
1039 | if (cpu == hcpu) { | ||
1040 | *per_cpu_ptr(vi->vq_index, cpu) = -1; | ||
1041 | } else { | ||
1042 | *per_cpu_ptr(vi->vq_index, cpu) = | ||
1043 | ++i % vi->curr_queue_pairs; | ||
1044 | } | ||
1045 | } | ||
1046 | } | ||
1047 | |||
1048 | static void virtnet_set_affinity(struct virtnet_info *vi) | ||
1049 | { | ||
1050 | int i; | ||
1051 | int cpu; | ||
1019 | 1052 | ||
1020 | /* In multiqueue mode, when the number of cpu is equal to the number of | 1053 | /* In multiqueue mode, when the number of cpu is equal to the number of |
1021 | * queue pairs, we let the queue pairs to be private to one cpu by | 1054 | * queue pairs, we let the queue pairs to be private to one cpu by |
1022 | * setting the affinity hint to eliminate the contention. | 1055 | * setting the affinity hint to eliminate the contention. |
1023 | */ | 1056 | */ |
1024 | if ((vi->curr_queue_pairs == 1 || | 1057 | if (vi->curr_queue_pairs == 1 || |
1025 | vi->max_queue_pairs != num_online_cpus()) && set) { | 1058 | vi->max_queue_pairs != num_online_cpus()) { |
1026 | if (vi->affinity_hint_set) | 1059 | virtnet_clean_affinity(vi, -1); |
1027 | set = false; | 1060 | return; |
1028 | else | ||
1029 | return; | ||
1030 | } | 1061 | } |
1031 | 1062 | ||
1032 | for (i = 0; i < vi->max_queue_pairs; i++) { | 1063 | i = 0; |
1033 | int cpu = set ? i : -1; | 1064 | for_each_online_cpu(cpu) { |
1034 | virtqueue_set_affinity(vi->rq[i].vq, cpu); | 1065 | virtqueue_set_affinity(vi->rq[i].vq, cpu); |
1035 | virtqueue_set_affinity(vi->sq[i].vq, cpu); | 1066 | virtqueue_set_affinity(vi->sq[i].vq, cpu); |
1067 | *per_cpu_ptr(vi->vq_index, cpu) = i; | ||
1068 | i++; | ||
1036 | } | 1069 | } |
1037 | 1070 | ||
1038 | if (set) | 1071 | vi->affinity_hint_set = true; |
1039 | vi->affinity_hint_set = true; | 1072 | } |
1040 | else | 1073 | |
1041 | vi->affinity_hint_set = false; | 1074 | static int virtnet_cpu_callback(struct notifier_block *nfb, |
1075 | unsigned long action, void *hcpu) | ||
1076 | { | ||
1077 | struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb); | ||
1078 | |||
1079 | switch(action & ~CPU_TASKS_FROZEN) { | ||
1080 | case CPU_ONLINE: | ||
1081 | case CPU_DOWN_FAILED: | ||
1082 | case CPU_DEAD: | ||
1083 | virtnet_set_affinity(vi); | ||
1084 | break; | ||
1085 | case CPU_DOWN_PREPARE: | ||
1086 | virtnet_clean_affinity(vi, (long)hcpu); | ||
1087 | break; | ||
1088 | default: | ||
1089 | break; | ||
1090 | } | ||
1091 | return NOTIFY_OK; | ||
1042 | } | 1092 | } |
1043 | 1093 | ||
1044 | static void virtnet_get_ringparam(struct net_device *dev, | 1094 | static void virtnet_get_ringparam(struct net_device *dev, |
@@ -1082,13 +1132,15 @@ static int virtnet_set_channels(struct net_device *dev, | |||
1082 | if (queue_pairs > vi->max_queue_pairs) | 1132 | if (queue_pairs > vi->max_queue_pairs) |
1083 | return -EINVAL; | 1133 | return -EINVAL; |
1084 | 1134 | ||
1135 | get_online_cpus(); | ||
1085 | err = virtnet_set_queues(vi, queue_pairs); | 1136 | err = virtnet_set_queues(vi, queue_pairs); |
1086 | if (!err) { | 1137 | if (!err) { |
1087 | netif_set_real_num_tx_queues(dev, queue_pairs); | 1138 | netif_set_real_num_tx_queues(dev, queue_pairs); |
1088 | netif_set_real_num_rx_queues(dev, queue_pairs); | 1139 | netif_set_real_num_rx_queues(dev, queue_pairs); |
1089 | 1140 | ||
1090 | virtnet_set_affinity(vi, true); | 1141 | virtnet_set_affinity(vi); |
1091 | } | 1142 | } |
1143 | put_online_cpus(); | ||
1092 | 1144 | ||
1093 | return err; | 1145 | return err; |
1094 | } | 1146 | } |
@@ -1127,12 +1179,19 @@ static int virtnet_change_mtu(struct net_device *dev, int new_mtu) | |||
1127 | 1179 | ||
1128 | /* To avoid contending a lock hold by a vcpu who would exit to host, select the | 1180 | /* To avoid contending a lock hold by a vcpu who would exit to host, select the |
1129 | * txq based on the processor id. | 1181 | * txq based on the processor id. |
1130 | * TODO: handle cpu hotplug. | ||
1131 | */ | 1182 | */ |
1132 | static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb) | 1183 | static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb) |
1133 | { | 1184 | { |
1134 | int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : | 1185 | int txq; |
1135 | smp_processor_id(); | 1186 | struct virtnet_info *vi = netdev_priv(dev); |
1187 | |||
1188 | if (skb_rx_queue_recorded(skb)) { | ||
1189 | txq = skb_get_rx_queue(skb); | ||
1190 | } else { | ||
1191 | txq = *__this_cpu_ptr(vi->vq_index); | ||
1192 | if (txq == -1) | ||
1193 | txq = 0; | ||
1194 | } | ||
1136 | 1195 | ||
1137 | while (unlikely(txq >= dev->real_num_tx_queues)) | 1196 | while (unlikely(txq >= dev->real_num_tx_queues)) |
1138 | txq -= dev->real_num_tx_queues; | 1197 | txq -= dev->real_num_tx_queues; |
@@ -1248,7 +1307,7 @@ static void virtnet_del_vqs(struct virtnet_info *vi) | |||
1248 | { | 1307 | { |
1249 | struct virtio_device *vdev = vi->vdev; | 1308 | struct virtio_device *vdev = vi->vdev; |
1250 | 1309 | ||
1251 | virtnet_set_affinity(vi, false); | 1310 | virtnet_clean_affinity(vi, -1); |
1252 | 1311 | ||
1253 | vdev->config->del_vqs(vdev); | 1312 | vdev->config->del_vqs(vdev); |
1254 | 1313 | ||
@@ -1371,7 +1430,10 @@ static int init_vqs(struct virtnet_info *vi) | |||
1371 | if (ret) | 1430 | if (ret) |
1372 | goto err_free; | 1431 | goto err_free; |
1373 | 1432 | ||
1374 | virtnet_set_affinity(vi, true); | 1433 | get_online_cpus(); |
1434 | virtnet_set_affinity(vi); | ||
1435 | put_online_cpus(); | ||
1436 | |||
1375 | return 0; | 1437 | return 0; |
1376 | 1438 | ||
1377 | err_free: | 1439 | err_free: |
@@ -1453,6 +1515,10 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1453 | if (vi->stats == NULL) | 1515 | if (vi->stats == NULL) |
1454 | goto free; | 1516 | goto free; |
1455 | 1517 | ||
1518 | vi->vq_index = alloc_percpu(int); | ||
1519 | if (vi->vq_index == NULL) | ||
1520 | goto free_stats; | ||
1521 | |||
1456 | mutex_init(&vi->config_lock); | 1522 | mutex_init(&vi->config_lock); |
1457 | vi->config_enable = true; | 1523 | vi->config_enable = true; |
1458 | INIT_WORK(&vi->config_work, virtnet_config_changed_work); | 1524 | INIT_WORK(&vi->config_work, virtnet_config_changed_work); |
@@ -1476,7 +1542,7 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1476 | /* Allocate/initialize the rx/tx queues, and invoke find_vqs */ | 1542 | /* Allocate/initialize the rx/tx queues, and invoke find_vqs */ |
1477 | err = init_vqs(vi); | 1543 | err = init_vqs(vi); |
1478 | if (err) | 1544 | if (err) |
1479 | goto free_stats; | 1545 | goto free_index; |
1480 | 1546 | ||
1481 | netif_set_real_num_tx_queues(dev, 1); | 1547 | netif_set_real_num_tx_queues(dev, 1); |
1482 | netif_set_real_num_rx_queues(dev, 1); | 1548 | netif_set_real_num_rx_queues(dev, 1); |
@@ -1499,6 +1565,13 @@ static int virtnet_probe(struct virtio_device *vdev) | |||
1499 | } | 1565 | } |
1500 | } | 1566 | } |
1501 | 1567 | ||
1568 | vi->nb.notifier_call = &virtnet_cpu_callback; | ||
1569 | err = register_hotcpu_notifier(&vi->nb); | ||
1570 | if (err) { | ||
1571 | pr_debug("virtio_net: registering cpu notifier failed\n"); | ||
1572 | goto free_recv_bufs; | ||
1573 | } | ||
1574 | |||
1502 | /* Assume link up if device can't report link status, | 1575 | /* Assume link up if device can't report link status, |
1503 | otherwise get link status from config. */ | 1576 | otherwise get link status from config. */ |
1504 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { | 1577 | if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) { |
@@ -1520,6 +1593,8 @@ free_recv_bufs: | |||
1520 | free_vqs: | 1593 | free_vqs: |
1521 | cancel_delayed_work_sync(&vi->refill); | 1594 | cancel_delayed_work_sync(&vi->refill); |
1522 | virtnet_del_vqs(vi); | 1595 | virtnet_del_vqs(vi); |
1596 | free_index: | ||
1597 | free_percpu(vi->vq_index); | ||
1523 | free_stats: | 1598 | free_stats: |
1524 | free_percpu(vi->stats); | 1599 | free_percpu(vi->stats); |
1525 | free: | 1600 | free: |
@@ -1543,6 +1618,8 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
1543 | { | 1618 | { |
1544 | struct virtnet_info *vi = vdev->priv; | 1619 | struct virtnet_info *vi = vdev->priv; |
1545 | 1620 | ||
1621 | unregister_hotcpu_notifier(&vi->nb); | ||
1622 | |||
1546 | /* Prevent config work handler from accessing the device. */ | 1623 | /* Prevent config work handler from accessing the device. */ |
1547 | mutex_lock(&vi->config_lock); | 1624 | mutex_lock(&vi->config_lock); |
1548 | vi->config_enable = false; | 1625 | vi->config_enable = false; |
@@ -1554,6 +1631,7 @@ static void virtnet_remove(struct virtio_device *vdev) | |||
1554 | 1631 | ||
1555 | flush_work(&vi->config_work); | 1632 | flush_work(&vi->config_work); |
1556 | 1633 | ||
1634 | free_percpu(vi->vq_index); | ||
1557 | free_percpu(vi->stats); | 1635 | free_percpu(vi->stats); |
1558 | free_netdev(vi->dev); | 1636 | free_netdev(vi->dev); |
1559 | } | 1637 | } |
diff --git a/drivers/net/vmxnet3/vmxnet3_drv.c b/drivers/net/vmxnet3/vmxnet3_drv.c index dc8913c6238c..12c6440d1649 100644 --- a/drivers/net/vmxnet3/vmxnet3_drv.c +++ b/drivers/net/vmxnet3/vmxnet3_drv.c | |||
@@ -154,8 +154,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue) | |||
154 | if (ret & 1) { /* Link is up. */ | 154 | if (ret & 1) { /* Link is up. */ |
155 | printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n", | 155 | printk(KERN_INFO "%s: NIC Link is Up %d Mbps\n", |
156 | adapter->netdev->name, adapter->link_speed); | 156 | adapter->netdev->name, adapter->link_speed); |
157 | if (!netif_carrier_ok(adapter->netdev)) | 157 | netif_carrier_on(adapter->netdev); |
158 | netif_carrier_on(adapter->netdev); | ||
159 | 158 | ||
160 | if (affectTxQueue) { | 159 | if (affectTxQueue) { |
161 | for (i = 0; i < adapter->num_tx_queues; i++) | 160 | for (i = 0; i < adapter->num_tx_queues; i++) |
@@ -165,8 +164,7 @@ vmxnet3_check_link(struct vmxnet3_adapter *adapter, bool affectTxQueue) | |||
165 | } else { | 164 | } else { |
166 | printk(KERN_INFO "%s: NIC Link is Down\n", | 165 | printk(KERN_INFO "%s: NIC Link is Down\n", |
167 | adapter->netdev->name); | 166 | adapter->netdev->name); |
168 | if (netif_carrier_ok(adapter->netdev)) | 167 | netif_carrier_off(adapter->netdev); |
169 | netif_carrier_off(adapter->netdev); | ||
170 | 168 | ||
171 | if (affectTxQueue) { | 169 | if (affectTxQueue) { |
172 | for (i = 0; i < adapter->num_tx_queues; i++) | 170 | for (i = 0; i < adapter->num_tx_queues; i++) |
@@ -3061,6 +3059,7 @@ vmxnet3_probe_device(struct pci_dev *pdev, | |||
3061 | netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues); | 3059 | netif_set_real_num_tx_queues(adapter->netdev, adapter->num_tx_queues); |
3062 | netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues); | 3060 | netif_set_real_num_rx_queues(adapter->netdev, adapter->num_rx_queues); |
3063 | 3061 | ||
3062 | netif_carrier_off(netdev); | ||
3064 | err = register_netdev(netdev); | 3063 | err = register_netdev(netdev); |
3065 | 3064 | ||
3066 | if (err) { | 3065 | if (err) { |
diff --git a/drivers/net/wimax/i2400m/netdev.c b/drivers/net/wimax/i2400m/netdev.c index 1d76ae855f07..530581ca0191 100644 --- a/drivers/net/wimax/i2400m/netdev.c +++ b/drivers/net/wimax/i2400m/netdev.c | |||
@@ -156,7 +156,7 @@ void i2400m_wake_tx_work(struct work_struct *ws) | |||
156 | struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws); | 156 | struct i2400m *i2400m = container_of(ws, struct i2400m, wake_tx_ws); |
157 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; | 157 | struct net_device *net_dev = i2400m->wimax_dev.net_dev; |
158 | struct device *dev = i2400m_dev(i2400m); | 158 | struct device *dev = i2400m_dev(i2400m); |
159 | struct sk_buff *skb = i2400m->wake_tx_skb; | 159 | struct sk_buff *skb; |
160 | unsigned long flags; | 160 | unsigned long flags; |
161 | 161 | ||
162 | spin_lock_irqsave(&i2400m->tx_lock, flags); | 162 | spin_lock_irqsave(&i2400m->tx_lock, flags); |
@@ -236,23 +236,26 @@ void i2400m_tx_prep_header(struct sk_buff *skb) | |||
236 | void i2400m_net_wake_stop(struct i2400m *i2400m) | 236 | void i2400m_net_wake_stop(struct i2400m *i2400m) |
237 | { | 237 | { |
238 | struct device *dev = i2400m_dev(i2400m); | 238 | struct device *dev = i2400m_dev(i2400m); |
239 | struct sk_buff *wake_tx_skb; | ||
240 | unsigned long flags; | ||
239 | 241 | ||
240 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); | 242 | d_fnstart(3, dev, "(i2400m %p)\n", i2400m); |
241 | /* See i2400m_hard_start_xmit(), references are taken there | 243 | /* |
242 | * and here we release them if the work was still | 244 | * See i2400m_hard_start_xmit(), references are taken there and |
243 | * pending. Note we can't differentiate work not pending vs | 245 | * here we release them if the packet was still pending. |
244 | * never scheduled, so the NULL check does that. */ | 246 | */ |
245 | if (cancel_work_sync(&i2400m->wake_tx_ws) == 0 | 247 | cancel_work_sync(&i2400m->wake_tx_ws); |
246 | && i2400m->wake_tx_skb != NULL) { | 248 | |
247 | unsigned long flags; | 249 | spin_lock_irqsave(&i2400m->tx_lock, flags); |
248 | struct sk_buff *wake_tx_skb; | 250 | wake_tx_skb = i2400m->wake_tx_skb; |
249 | spin_lock_irqsave(&i2400m->tx_lock, flags); | 251 | i2400m->wake_tx_skb = NULL; |
250 | wake_tx_skb = i2400m->wake_tx_skb; /* compat help */ | 252 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); |
251 | i2400m->wake_tx_skb = NULL; /* compat help */ | 253 | |
252 | spin_unlock_irqrestore(&i2400m->tx_lock, flags); | 254 | if (wake_tx_skb) { |
253 | i2400m_put(i2400m); | 255 | i2400m_put(i2400m); |
254 | kfree_skb(wake_tx_skb); | 256 | kfree_skb(wake_tx_skb); |
255 | } | 257 | } |
258 | |||
256 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); | 259 | d_fnend(3, dev, "(i2400m %p) = void\n", i2400m); |
257 | } | 260 | } |
258 | 261 | ||
@@ -288,7 +291,7 @@ int i2400m_net_wake_tx(struct i2400m *i2400m, struct net_device *net_dev, | |||
288 | * and if pending, release those resources. */ | 291 | * and if pending, release those resources. */ |
289 | result = 0; | 292 | result = 0; |
290 | spin_lock_irqsave(&i2400m->tx_lock, flags); | 293 | spin_lock_irqsave(&i2400m->tx_lock, flags); |
291 | if (!work_pending(&i2400m->wake_tx_ws)) { | 294 | if (!i2400m->wake_tx_skb) { |
292 | netif_stop_queue(net_dev); | 295 | netif_stop_queue(net_dev); |
293 | i2400m_get(i2400m); | 296 | i2400m_get(i2400m); |
294 | i2400m->wake_tx_skb = skb_get(skb); /* transfer ref count */ | 297 | i2400m->wake_tx_skb = skb_get(skb); /* transfer ref count */ |
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig index 1a67a4f829fe..2c02b4e84094 100644 --- a/drivers/net/wireless/ath/Kconfig +++ b/drivers/net/wireless/ath/Kconfig | |||
@@ -30,5 +30,6 @@ source "drivers/net/wireless/ath/ath9k/Kconfig" | |||
30 | source "drivers/net/wireless/ath/carl9170/Kconfig" | 30 | source "drivers/net/wireless/ath/carl9170/Kconfig" |
31 | source "drivers/net/wireless/ath/ath6kl/Kconfig" | 31 | source "drivers/net/wireless/ath/ath6kl/Kconfig" |
32 | source "drivers/net/wireless/ath/ar5523/Kconfig" | 32 | source "drivers/net/wireless/ath/ar5523/Kconfig" |
33 | source "drivers/net/wireless/ath/wil6210/Kconfig" | ||
33 | 34 | ||
34 | endif | 35 | endif |
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile index 1e18621326dc..97b964ded2be 100644 --- a/drivers/net/wireless/ath/Makefile +++ b/drivers/net/wireless/ath/Makefile | |||
@@ -3,6 +3,7 @@ obj-$(CONFIG_ATH9K_HW) += ath9k/ | |||
3 | obj-$(CONFIG_CARL9170) += carl9170/ | 3 | obj-$(CONFIG_CARL9170) += carl9170/ |
4 | obj-$(CONFIG_ATH6KL) += ath6kl/ | 4 | obj-$(CONFIG_ATH6KL) += ath6kl/ |
5 | obj-$(CONFIG_AR5523) += ar5523/ | 5 | obj-$(CONFIG_AR5523) += ar5523/ |
6 | obj-$(CONFIG_WIL6210) += wil6210/ | ||
6 | 7 | ||
7 | obj-$(CONFIG_ATH_COMMON) += ath.o | 8 | obj-$(CONFIG_ATH_COMMON) += ath.o |
8 | 9 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 8b0d8dcd7625..56317b0fb6b6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -976,6 +976,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah, | |||
976 | AR_PHY_CL_TAB_1, | 976 | AR_PHY_CL_TAB_1, |
977 | AR_PHY_CL_TAB_2 }; | 977 | AR_PHY_CL_TAB_2 }; |
978 | 978 | ||
979 | ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask); | ||
980 | |||
979 | if (rtt) { | 981 | if (rtt) { |
980 | if (!ar9003_hw_rtt_restore(ah, chan)) | 982 | if (!ar9003_hw_rtt_restore(ah, chan)) |
981 | run_rtt_cal = true; | 983 | run_rtt_cal = true; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index ce19c09fa8e8..3afc24bde6d6 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -586,32 +586,19 @@ static void ar9003_hw_init_bb(struct ath_hw *ah, | |||
586 | ath9k_hw_synth_delay(ah, chan, synthDelay); | 586 | ath9k_hw_synth_delay(ah, chan, synthDelay); |
587 | } | 587 | } |
588 | 588 | ||
589 | static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) | 589 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx) |
590 | { | 590 | { |
591 | switch (rx) { | 591 | if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5) |
592 | case 0x5: | ||
593 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | 592 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, |
594 | AR_PHY_SWAP_ALT_CHAIN); | 593 | AR_PHY_SWAP_ALT_CHAIN); |
595 | case 0x3: | 594 | |
596 | case 0x1: | 595 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); |
597 | case 0x2: | 596 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); |
598 | case 0x7: | ||
599 | REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx); | ||
600 | REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx); | ||
601 | break; | ||
602 | default: | ||
603 | break; | ||
604 | } | ||
605 | 597 | ||
606 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) | 598 | if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7)) |
607 | REG_WRITE(ah, AR_SELFGEN_MASK, 0x3); | 599 | tx = 3; |
608 | else | ||
609 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); | ||
610 | 600 | ||
611 | if (tx == 0x5) { | 601 | REG_WRITE(ah, AR_SELFGEN_MASK, tx); |
612 | REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP, | ||
613 | AR_PHY_SWAP_ALT_CHAIN); | ||
614 | } | ||
615 | } | 602 | } |
616 | 603 | ||
617 | /* | 604 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 86e26a19efda..42794c546a40 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -317,7 +317,6 @@ struct ath_rx { | |||
317 | u32 *rxlink; | 317 | u32 *rxlink; |
318 | u32 num_pkts; | 318 | u32 num_pkts; |
319 | unsigned int rxfilter; | 319 | unsigned int rxfilter; |
320 | spinlock_t rxbuflock; | ||
321 | struct list_head rxbuf; | 320 | struct list_head rxbuf; |
322 | struct ath_descdma rxdma; | 321 | struct ath_descdma rxdma; |
323 | struct ath_buf *rx_bufptr; | 322 | struct ath_buf *rx_bufptr; |
@@ -328,7 +327,6 @@ struct ath_rx { | |||
328 | 327 | ||
329 | int ath_startrecv(struct ath_softc *sc); | 328 | int ath_startrecv(struct ath_softc *sc); |
330 | bool ath_stoprecv(struct ath_softc *sc); | 329 | bool ath_stoprecv(struct ath_softc *sc); |
331 | void ath_flushrecv(struct ath_softc *sc); | ||
332 | u32 ath_calcrxfilter(struct ath_softc *sc); | 330 | u32 ath_calcrxfilter(struct ath_softc *sc); |
333 | int ath_rx_init(struct ath_softc *sc, int nbufs); | 331 | int ath_rx_init(struct ath_softc *sc, int nbufs); |
334 | void ath_rx_cleanup(struct ath_softc *sc); | 332 | void ath_rx_cleanup(struct ath_softc *sc); |
@@ -646,7 +644,6 @@ void ath_ant_comb_update(struct ath_softc *sc); | |||
646 | enum sc_op_flags { | 644 | enum sc_op_flags { |
647 | SC_OP_INVALID, | 645 | SC_OP_INVALID, |
648 | SC_OP_BEACONS, | 646 | SC_OP_BEACONS, |
649 | SC_OP_RXFLUSH, | ||
650 | SC_OP_ANI_RUN, | 647 | SC_OP_ANI_RUN, |
651 | SC_OP_PRIM_STA_VIF, | 648 | SC_OP_PRIM_STA_VIF, |
652 | SC_OP_HW_RESET, | 649 | SC_OP_HW_RESET, |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index 531fffd801a3..2ca355e94da6 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -147,6 +147,7 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, | |||
147 | skb->len, DMA_TO_DEVICE); | 147 | skb->len, DMA_TO_DEVICE); |
148 | dev_kfree_skb_any(skb); | 148 | dev_kfree_skb_any(skb); |
149 | bf->bf_buf_addr = 0; | 149 | bf->bf_buf_addr = 0; |
150 | bf->bf_mpdu = NULL; | ||
150 | } | 151 | } |
151 | 152 | ||
152 | skb = ieee80211_beacon_get(hw, vif); | 153 | skb = ieee80211_beacon_get(hw, vif); |
@@ -359,7 +360,6 @@ void ath9k_beacon_tasklet(unsigned long data) | |||
359 | return; | 360 | return; |
360 | 361 | ||
361 | bf = ath9k_beacon_generate(sc->hw, vif); | 362 | bf = ath9k_beacon_generate(sc->hw, vif); |
362 | WARN_ON(!bf); | ||
363 | 363 | ||
364 | if (sc->beacon.bmisscnt != 0) { | 364 | if (sc->beacon.bmisscnt != 0) { |
365 | ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n", | 365 | ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n", |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 13ff9edc2401..e585fc827c50 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -861,7 +861,6 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf, | |||
861 | RXS_ERR("RX-LENGTH-ERR", rx_len_err); | 861 | RXS_ERR("RX-LENGTH-ERR", rx_len_err); |
862 | RXS_ERR("RX-OOM-ERR", rx_oom_err); | 862 | RXS_ERR("RX-OOM-ERR", rx_oom_err); |
863 | RXS_ERR("RX-RATE-ERR", rx_rate_err); | 863 | RXS_ERR("RX-RATE-ERR", rx_rate_err); |
864 | RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush); | ||
865 | RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); | 864 | RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err); |
866 | 865 | ||
867 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); | 866 | PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 375c3b46411e..6df2ab62dcb7 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -216,7 +216,6 @@ struct ath_tx_stats { | |||
216 | * @rx_oom_err: No. of frames dropped due to OOM issues. | 216 | * @rx_oom_err: No. of frames dropped due to OOM issues. |
217 | * @rx_rate_err: No. of frames dropped due to rate errors. | 217 | * @rx_rate_err: No. of frames dropped due to rate errors. |
218 | * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. | 218 | * @rx_too_many_frags_err: Frames dropped due to too-many-frags received. |
219 | * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH. | ||
220 | * @rx_beacons: No. of beacons received. | 219 | * @rx_beacons: No. of beacons received. |
221 | * @rx_frags: No. of rx-fragements received. | 220 | * @rx_frags: No. of rx-fragements received. |
222 | */ | 221 | */ |
@@ -235,7 +234,6 @@ struct ath_rx_stats { | |||
235 | u32 rx_oom_err; | 234 | u32 rx_oom_err; |
236 | u32 rx_rate_err; | 235 | u32 rx_rate_err; |
237 | u32 rx_too_many_frags_err; | 236 | u32 rx_too_many_frags_err; |
238 | u32 rx_drop_rxflush; | ||
239 | u32 rx_beacons; | 237 | u32 rx_beacons; |
240 | u32 rx_frags; | 238 | u32 rx_frags; |
241 | }; | 239 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c index 4a9570dfba72..aac4a406a513 100644 --- a/drivers/net/wireless/ath/ath9k/htc_hst.c +++ b/drivers/net/wireless/ath/ath9k/htc_hst.c | |||
@@ -344,6 +344,8 @@ void ath9k_htc_txcompletion_cb(struct htc_target *htc_handle, | |||
344 | endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, | 344 | endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv, |
345 | skb, htc_hdr->endpoint_id, | 345 | skb, htc_hdr->endpoint_id, |
346 | txok); | 346 | txok); |
347 | } else { | ||
348 | kfree_skb(skb); | ||
347 | } | 349 | } |
348 | } | 350 | } |
349 | 351 | ||
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 7f1a8e91c908..9d26fc56ca56 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -1066,6 +1066,7 @@ void ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); | |||
1066 | int ar9003_paprd_init_table(struct ath_hw *ah); | 1066 | int ar9003_paprd_init_table(struct ath_hw *ah); |
1067 | bool ar9003_paprd_is_done(struct ath_hw *ah); | 1067 | bool ar9003_paprd_is_done(struct ath_hw *ah); |
1068 | bool ar9003_is_paprd_enabled(struct ath_hw *ah); | 1068 | bool ar9003_is_paprd_enabled(struct ath_hw *ah); |
1069 | void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx); | ||
1069 | 1070 | ||
1070 | /* Hardware family op attach helpers */ | 1071 | /* Hardware family op attach helpers */ |
1071 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); | 1072 | void ar5008_hw_attach_phy_ops(struct ath_hw *ah); |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index be30a9af1528..dd91f8fdc01c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -182,7 +182,7 @@ static void ath_restart_work(struct ath_softc *sc) | |||
182 | ath_start_ani(sc); | 182 | ath_start_ani(sc); |
183 | } | 183 | } |
184 | 184 | ||
185 | static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) | 185 | static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx) |
186 | { | 186 | { |
187 | struct ath_hw *ah = sc->sc_ah; | 187 | struct ath_hw *ah = sc->sc_ah; |
188 | bool ret = true; | 188 | bool ret = true; |
@@ -202,14 +202,6 @@ static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) | |||
202 | if (!ath_drain_all_txq(sc, retry_tx)) | 202 | if (!ath_drain_all_txq(sc, retry_tx)) |
203 | ret = false; | 203 | ret = false; |
204 | 204 | ||
205 | if (!flush) { | ||
206 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
207 | ath_rx_tasklet(sc, 1, true); | ||
208 | ath_rx_tasklet(sc, 1, false); | ||
209 | } else { | ||
210 | ath_flushrecv(sc); | ||
211 | } | ||
212 | |||
213 | return ret; | 205 | return ret; |
214 | } | 206 | } |
215 | 207 | ||
@@ -262,11 +254,11 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
262 | struct ath_common *common = ath9k_hw_common(ah); | 254 | struct ath_common *common = ath9k_hw_common(ah); |
263 | struct ath9k_hw_cal_data *caldata = NULL; | 255 | struct ath9k_hw_cal_data *caldata = NULL; |
264 | bool fastcc = true; | 256 | bool fastcc = true; |
265 | bool flush = false; | ||
266 | int r; | 257 | int r; |
267 | 258 | ||
268 | __ath_cancel_work(sc); | 259 | __ath_cancel_work(sc); |
269 | 260 | ||
261 | tasklet_disable(&sc->intr_tq); | ||
270 | spin_lock_bh(&sc->sc_pcu_lock); | 262 | spin_lock_bh(&sc->sc_pcu_lock); |
271 | 263 | ||
272 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { | 264 | if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) { |
@@ -276,11 +268,10 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
276 | 268 | ||
277 | if (!hchan) { | 269 | if (!hchan) { |
278 | fastcc = false; | 270 | fastcc = false; |
279 | flush = true; | ||
280 | hchan = ah->curchan; | 271 | hchan = ah->curchan; |
281 | } | 272 | } |
282 | 273 | ||
283 | if (!ath_prepare_reset(sc, retry_tx, flush)) | 274 | if (!ath_prepare_reset(sc, retry_tx)) |
284 | fastcc = false; | 275 | fastcc = false; |
285 | 276 | ||
286 | ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n", | 277 | ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n", |
@@ -302,6 +293,8 @@ static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | |||
302 | 293 | ||
303 | out: | 294 | out: |
304 | spin_unlock_bh(&sc->sc_pcu_lock); | 295 | spin_unlock_bh(&sc->sc_pcu_lock); |
296 | tasklet_enable(&sc->intr_tq); | ||
297 | |||
305 | return r; | 298 | return r; |
306 | } | 299 | } |
307 | 300 | ||
@@ -804,7 +797,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
804 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | 797 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); |
805 | } | 798 | } |
806 | 799 | ||
807 | ath_prepare_reset(sc, false, true); | 800 | ath_prepare_reset(sc, false); |
808 | 801 | ||
809 | if (sc->rx.frag) { | 802 | if (sc->rx.frag) { |
810 | dev_kfree_skb_any(sc->rx.frag); | 803 | dev_kfree_skb_any(sc->rx.frag); |
@@ -1833,6 +1826,9 @@ static u32 fill_chainmask(u32 cap, u32 new) | |||
1833 | 1826 | ||
1834 | static bool validate_antenna_mask(struct ath_hw *ah, u32 val) | 1827 | static bool validate_antenna_mask(struct ath_hw *ah, u32 val) |
1835 | { | 1828 | { |
1829 | if (AR_SREV_9300_20_OR_LATER(ah)) | ||
1830 | return true; | ||
1831 | |||
1836 | switch (val & 0x7) { | 1832 | switch (val & 0x7) { |
1837 | case 0x1: | 1833 | case 0x1: |
1838 | case 0x3: | 1834 | case 0x3: |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index d4df98a938bf..90752f246970 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -254,8 +254,6 @@ rx_init_fail: | |||
254 | 254 | ||
255 | static void ath_edma_start_recv(struct ath_softc *sc) | 255 | static void ath_edma_start_recv(struct ath_softc *sc) |
256 | { | 256 | { |
257 | spin_lock_bh(&sc->rx.rxbuflock); | ||
258 | |||
259 | ath9k_hw_rxena(sc->sc_ah); | 257 | ath9k_hw_rxena(sc->sc_ah); |
260 | 258 | ||
261 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, | 259 | ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP, |
@@ -267,8 +265,6 @@ static void ath_edma_start_recv(struct ath_softc *sc) | |||
267 | ath_opmode_init(sc); | 265 | ath_opmode_init(sc); |
268 | 266 | ||
269 | ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); | 267 | ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); |
270 | |||
271 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
272 | } | 268 | } |
273 | 269 | ||
274 | static void ath_edma_stop_recv(struct ath_softc *sc) | 270 | static void ath_edma_stop_recv(struct ath_softc *sc) |
@@ -285,8 +281,6 @@ int ath_rx_init(struct ath_softc *sc, int nbufs) | |||
285 | int error = 0; | 281 | int error = 0; |
286 | 282 | ||
287 | spin_lock_init(&sc->sc_pcu_lock); | 283 | spin_lock_init(&sc->sc_pcu_lock); |
288 | spin_lock_init(&sc->rx.rxbuflock); | ||
289 | clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); | ||
290 | 284 | ||
291 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + | 285 | common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 + |
292 | sc->sc_ah->caps.rx_status_len; | 286 | sc->sc_ah->caps.rx_status_len; |
@@ -447,7 +441,6 @@ int ath_startrecv(struct ath_softc *sc) | |||
447 | return 0; | 441 | return 0; |
448 | } | 442 | } |
449 | 443 | ||
450 | spin_lock_bh(&sc->rx.rxbuflock); | ||
451 | if (list_empty(&sc->rx.rxbuf)) | 444 | if (list_empty(&sc->rx.rxbuf)) |
452 | goto start_recv; | 445 | goto start_recv; |
453 | 446 | ||
@@ -468,26 +461,31 @@ start_recv: | |||
468 | ath_opmode_init(sc); | 461 | ath_opmode_init(sc); |
469 | ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); | 462 | ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)); |
470 | 463 | ||
471 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
472 | |||
473 | return 0; | 464 | return 0; |
474 | } | 465 | } |
475 | 466 | ||
467 | static void ath_flushrecv(struct ath_softc *sc) | ||
468 | { | ||
469 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
470 | ath_rx_tasklet(sc, 1, true); | ||
471 | ath_rx_tasklet(sc, 1, false); | ||
472 | } | ||
473 | |||
476 | bool ath_stoprecv(struct ath_softc *sc) | 474 | bool ath_stoprecv(struct ath_softc *sc) |
477 | { | 475 | { |
478 | struct ath_hw *ah = sc->sc_ah; | 476 | struct ath_hw *ah = sc->sc_ah; |
479 | bool stopped, reset = false; | 477 | bool stopped, reset = false; |
480 | 478 | ||
481 | spin_lock_bh(&sc->rx.rxbuflock); | ||
482 | ath9k_hw_abortpcurecv(ah); | 479 | ath9k_hw_abortpcurecv(ah); |
483 | ath9k_hw_setrxfilter(ah, 0); | 480 | ath9k_hw_setrxfilter(ah, 0); |
484 | stopped = ath9k_hw_stopdmarecv(ah, &reset); | 481 | stopped = ath9k_hw_stopdmarecv(ah, &reset); |
485 | 482 | ||
483 | ath_flushrecv(sc); | ||
484 | |||
486 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | 485 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
487 | ath_edma_stop_recv(sc); | 486 | ath_edma_stop_recv(sc); |
488 | else | 487 | else |
489 | sc->rx.rxlink = NULL; | 488 | sc->rx.rxlink = NULL; |
490 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
491 | 489 | ||
492 | if (!(ah->ah_flags & AH_UNPLUGGED) && | 490 | if (!(ah->ah_flags & AH_UNPLUGGED) && |
493 | unlikely(!stopped)) { | 491 | unlikely(!stopped)) { |
@@ -499,15 +497,6 @@ bool ath_stoprecv(struct ath_softc *sc) | |||
499 | return stopped && !reset; | 497 | return stopped && !reset; |
500 | } | 498 | } |
501 | 499 | ||
502 | void ath_flushrecv(struct ath_softc *sc) | ||
503 | { | ||
504 | set_bit(SC_OP_RXFLUSH, &sc->sc_flags); | ||
505 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) | ||
506 | ath_rx_tasklet(sc, 1, true); | ||
507 | ath_rx_tasklet(sc, 1, false); | ||
508 | clear_bit(SC_OP_RXFLUSH, &sc->sc_flags); | ||
509 | } | ||
510 | |||
511 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) | 500 | static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb) |
512 | { | 501 | { |
513 | /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ | 502 | /* Check whether the Beacon frame has DTIM indicating buffered bc/mc */ |
@@ -744,6 +733,7 @@ static struct ath_buf *ath_get_next_rx_buf(struct ath_softc *sc, | |||
744 | return NULL; | 733 | return NULL; |
745 | } | 734 | } |
746 | 735 | ||
736 | list_del(&bf->list); | ||
747 | if (!bf->bf_mpdu) | 737 | if (!bf->bf_mpdu) |
748 | return bf; | 738 | return bf; |
749 | 739 | ||
@@ -1059,16 +1049,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1059 | dma_type = DMA_FROM_DEVICE; | 1049 | dma_type = DMA_FROM_DEVICE; |
1060 | 1050 | ||
1061 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; | 1051 | qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP; |
1062 | spin_lock_bh(&sc->rx.rxbuflock); | ||
1063 | 1052 | ||
1064 | tsf = ath9k_hw_gettsf64(ah); | 1053 | tsf = ath9k_hw_gettsf64(ah); |
1065 | tsf_lower = tsf & 0xffffffff; | 1054 | tsf_lower = tsf & 0xffffffff; |
1066 | 1055 | ||
1067 | do { | 1056 | do { |
1068 | bool decrypt_error = false; | 1057 | bool decrypt_error = false; |
1069 | /* If handling rx interrupt and flush is in progress => exit */ | ||
1070 | if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0)) | ||
1071 | break; | ||
1072 | 1058 | ||
1073 | memset(&rs, 0, sizeof(rs)); | 1059 | memset(&rs, 0, sizeof(rs)); |
1074 | if (edma) | 1060 | if (edma) |
@@ -1111,15 +1097,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp) | |||
1111 | 1097 | ||
1112 | ath_debug_stat_rx(sc, &rs); | 1098 | ath_debug_stat_rx(sc, &rs); |
1113 | 1099 | ||
1114 | /* | ||
1115 | * If we're asked to flush receive queue, directly | ||
1116 | * chain it back at the queue without processing it. | ||
1117 | */ | ||
1118 | if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) { | ||
1119 | RX_STAT_INC(rx_drop_rxflush); | ||
1120 | goto requeue_drop_frag; | ||
1121 | } | ||
1122 | |||
1123 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); | 1100 | memset(rxs, 0, sizeof(struct ieee80211_rx_status)); |
1124 | 1101 | ||
1125 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; | 1102 | rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp; |
@@ -1254,19 +1231,18 @@ requeue_drop_frag: | |||
1254 | sc->rx.frag = NULL; | 1231 | sc->rx.frag = NULL; |
1255 | } | 1232 | } |
1256 | requeue: | 1233 | requeue: |
1234 | list_add_tail(&bf->list, &sc->rx.rxbuf); | ||
1235 | if (flush) | ||
1236 | continue; | ||
1237 | |||
1257 | if (edma) { | 1238 | if (edma) { |
1258 | list_add_tail(&bf->list, &sc->rx.rxbuf); | ||
1259 | ath_rx_edma_buf_link(sc, qtype); | 1239 | ath_rx_edma_buf_link(sc, qtype); |
1260 | } else { | 1240 | } else { |
1261 | list_move_tail(&bf->list, &sc->rx.rxbuf); | ||
1262 | ath_rx_buf_link(sc, bf); | 1241 | ath_rx_buf_link(sc, bf); |
1263 | if (!flush) | 1242 | ath9k_hw_rxena(ah); |
1264 | ath9k_hw_rxena(ah); | ||
1265 | } | 1243 | } |
1266 | } while (1); | 1244 | } while (1); |
1267 | 1245 | ||
1268 | spin_unlock_bh(&sc->rx.rxbuflock); | ||
1269 | |||
1270 | if (!(ah->imask & ATH9K_INT_RXEOL)) { | 1246 | if (!(ah->imask & ATH9K_INT_RXEOL)) { |
1271 | ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); | 1247 | ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN); |
1272 | ath9k_hw_set_interrupts(ah); | 1248 | ath9k_hw_set_interrupts(ah); |
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig new file mode 100644 index 000000000000..bac3d98a0cfb --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/Kconfig | |||
@@ -0,0 +1,29 @@ | |||
1 | config WIL6210 | ||
2 | tristate "Wilocity 60g WiFi card wil6210 support" | ||
3 | depends on CFG80211 | ||
4 | depends on PCI | ||
5 | default n | ||
6 | ---help--- | ||
7 | This module adds support for wireless adapter based on | ||
8 | wil6210 chip by Wilocity. It supports operation on the | ||
9 | 60 GHz band, covered by the IEEE802.11ad standard. | ||
10 | |||
11 | http://wireless.kernel.org/en/users/Drivers/wil6210 | ||
12 | |||
13 | If you choose to build it as a module, it will be called | ||
14 | wil6210 | ||
15 | |||
16 | config WIL6210_ISR_COR | ||
17 | bool "Use Clear-On-Read mode for ISR registers for wil6210" | ||
18 | depends on WIL6210 | ||
19 | default y | ||
20 | ---help--- | ||
21 | ISR registers on wil6210 chip may operate in either | ||
22 | COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode. | ||
23 | For production code, use COR (say y); is default since | ||
24 | it saves extra target transaction; | ||
25 | For ISR debug, use W1C (say n); is allows to monitor ISR | ||
26 | registers with debugfs. If COR were used, ISR would | ||
27 | self-clear when accessed for debug purposes, it makes | ||
28 | such monitoring impossible. | ||
29 | Say y unless you debug interrupts | ||
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile new file mode 100644 index 000000000000..9396dc9fe3c5 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/Makefile | |||
@@ -0,0 +1,13 @@ | |||
1 | obj-$(CONFIG_WIL6210) += wil6210.o | ||
2 | |||
3 | wil6210-objs := main.o | ||
4 | wil6210-objs += netdev.o | ||
5 | wil6210-objs += cfg80211.o | ||
6 | wil6210-objs += pcie_bus.o | ||
7 | wil6210-objs += debugfs.o | ||
8 | wil6210-objs += wmi.o | ||
9 | wil6210-objs += interrupt.o | ||
10 | wil6210-objs += txrx.o | ||
11 | |||
12 | subdir-ccflags-y += -Werror | ||
13 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c new file mode 100644 index 000000000000..116f4e807ae1 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -0,0 +1,573 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/ieee80211.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/version.h> | ||
25 | #include <net/cfg80211.h> | ||
26 | |||
27 | #include "wil6210.h" | ||
28 | #include "wmi.h" | ||
29 | |||
30 | #define CHAN60G(_channel, _flags) { \ | ||
31 | .band = IEEE80211_BAND_60GHZ, \ | ||
32 | .center_freq = 56160 + (2160 * (_channel)), \ | ||
33 | .hw_value = (_channel), \ | ||
34 | .flags = (_flags), \ | ||
35 | .max_antenna_gain = 0, \ | ||
36 | .max_power = 40, \ | ||
37 | } | ||
38 | |||
39 | static struct ieee80211_channel wil_60ghz_channels[] = { | ||
40 | CHAN60G(1, 0), | ||
41 | CHAN60G(2, 0), | ||
42 | CHAN60G(3, 0), | ||
43 | /* channel 4 not supported yet */ | ||
44 | }; | ||
45 | |||
46 | static struct ieee80211_supported_band wil_band_60ghz = { | ||
47 | .channels = wil_60ghz_channels, | ||
48 | .n_channels = ARRAY_SIZE(wil_60ghz_channels), | ||
49 | .ht_cap = { | ||
50 | .ht_supported = true, | ||
51 | .cap = 0, /* TODO */ | ||
52 | .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */ | ||
53 | .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */ | ||
54 | .mcs = { | ||
55 | /* MCS 1..12 - SC PHY */ | ||
56 | .rx_mask = {0xfe, 0x1f}, /* 1..12 */ | ||
57 | .tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */ | ||
58 | }, | ||
59 | }, | ||
60 | }; | ||
61 | |||
62 | static const struct ieee80211_txrx_stypes | ||
63 | wil_mgmt_stypes[NUM_NL80211_IFTYPES] = { | ||
64 | [NL80211_IFTYPE_STATION] = { | ||
65 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
66 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
67 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
68 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
69 | }, | ||
70 | [NL80211_IFTYPE_AP] = { | ||
71 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
72 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
73 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
74 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
75 | }, | ||
76 | [NL80211_IFTYPE_P2P_CLIENT] = { | ||
77 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
78 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
79 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
80 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
81 | }, | ||
82 | [NL80211_IFTYPE_P2P_GO] = { | ||
83 | .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
84 | BIT(IEEE80211_STYPE_PROBE_RESP >> 4), | ||
85 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
86 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4) | ||
87 | }, | ||
88 | }; | ||
89 | |||
90 | static const u32 wil_cipher_suites[] = { | ||
91 | WLAN_CIPHER_SUITE_GCMP, | ||
92 | }; | ||
93 | |||
94 | int wil_iftype_nl2wmi(enum nl80211_iftype type) | ||
95 | { | ||
96 | static const struct { | ||
97 | enum nl80211_iftype nl; | ||
98 | enum wmi_network_type wmi; | ||
99 | } __nl2wmi[] = { | ||
100 | {NL80211_IFTYPE_ADHOC, WMI_NETTYPE_ADHOC}, | ||
101 | {NL80211_IFTYPE_STATION, WMI_NETTYPE_INFRA}, | ||
102 | {NL80211_IFTYPE_AP, WMI_NETTYPE_AP}, | ||
103 | {NL80211_IFTYPE_P2P_CLIENT, WMI_NETTYPE_P2P}, | ||
104 | {NL80211_IFTYPE_P2P_GO, WMI_NETTYPE_P2P}, | ||
105 | {NL80211_IFTYPE_MONITOR, WMI_NETTYPE_ADHOC}, /* FIXME */ | ||
106 | }; | ||
107 | uint i; | ||
108 | |||
109 | for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) { | ||
110 | if (__nl2wmi[i].nl == type) | ||
111 | return __nl2wmi[i].wmi; | ||
112 | } | ||
113 | |||
114 | return -EOPNOTSUPP; | ||
115 | } | ||
116 | |||
117 | static int wil_cfg80211_get_station(struct wiphy *wiphy, | ||
118 | struct net_device *ndev, | ||
119 | u8 *mac, struct station_info *sinfo) | ||
120 | { | ||
121 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
122 | int rc; | ||
123 | struct wmi_notify_req_cmd cmd = { | ||
124 | .cid = 0, | ||
125 | .interval_usec = 0, | ||
126 | }; | ||
127 | |||
128 | if (memcmp(mac, wil->dst_addr[0], ETH_ALEN)) | ||
129 | return -ENOENT; | ||
130 | |||
131 | /* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */ | ||
132 | rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd), | ||
133 | WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20); | ||
134 | if (rc) | ||
135 | return rc; | ||
136 | |||
137 | sinfo->generation = wil->sinfo_gen; | ||
138 | |||
139 | sinfo->filled |= STATION_INFO_TX_BITRATE; | ||
140 | sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | ||
141 | sinfo->txrate.mcs = wil->stats.bf_mcs; | ||
142 | sinfo->filled |= STATION_INFO_RX_BITRATE; | ||
143 | sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G; | ||
144 | sinfo->rxrate.mcs = wil->stats.last_mcs_rx; | ||
145 | |||
146 | if (test_bit(wil_status_fwconnected, &wil->status)) { | ||
147 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
148 | sinfo->signal = 12; /* TODO: provide real value */ | ||
149 | } | ||
150 | |||
151 | return 0; | ||
152 | } | ||
153 | |||
154 | static int wil_cfg80211_change_iface(struct wiphy *wiphy, | ||
155 | struct net_device *ndev, | ||
156 | enum nl80211_iftype type, u32 *flags, | ||
157 | struct vif_params *params) | ||
158 | { | ||
159 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
160 | struct wireless_dev *wdev = wil->wdev; | ||
161 | |||
162 | switch (type) { | ||
163 | case NL80211_IFTYPE_STATION: | ||
164 | case NL80211_IFTYPE_AP: | ||
165 | case NL80211_IFTYPE_P2P_CLIENT: | ||
166 | case NL80211_IFTYPE_P2P_GO: | ||
167 | break; | ||
168 | case NL80211_IFTYPE_MONITOR: | ||
169 | if (flags) | ||
170 | wil->monitor_flags = *flags; | ||
171 | else | ||
172 | wil->monitor_flags = 0; | ||
173 | |||
174 | break; | ||
175 | default: | ||
176 | return -EOPNOTSUPP; | ||
177 | } | ||
178 | |||
179 | wdev->iftype = type; | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int wil_cfg80211_scan(struct wiphy *wiphy, | ||
185 | struct cfg80211_scan_request *request) | ||
186 | { | ||
187 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
188 | struct wireless_dev *wdev = wil->wdev; | ||
189 | struct { | ||
190 | struct wmi_start_scan_cmd cmd; | ||
191 | u16 chnl[4]; | ||
192 | } __packed cmd; | ||
193 | uint i, n; | ||
194 | |||
195 | if (wil->scan_request) { | ||
196 | wil_err(wil, "Already scanning\n"); | ||
197 | return -EAGAIN; | ||
198 | } | ||
199 | |||
200 | /* check we are client side */ | ||
201 | switch (wdev->iftype) { | ||
202 | case NL80211_IFTYPE_STATION: | ||
203 | case NL80211_IFTYPE_P2P_CLIENT: | ||
204 | break; | ||
205 | default: | ||
206 | return -EOPNOTSUPP; | ||
207 | |||
208 | } | ||
209 | |||
210 | /* FW don't support scan after connection attempt */ | ||
211 | if (test_bit(wil_status_dontscan, &wil->status)) { | ||
212 | wil_err(wil, "Scan after connect attempt not supported\n"); | ||
213 | return -EBUSY; | ||
214 | } | ||
215 | |||
216 | wil->scan_request = request; | ||
217 | |||
218 | memset(&cmd, 0, sizeof(cmd)); | ||
219 | cmd.cmd.num_channels = 0; | ||
220 | n = min(request->n_channels, 4U); | ||
221 | for (i = 0; i < n; i++) { | ||
222 | int ch = request->channels[i]->hw_value; | ||
223 | if (ch == 0) { | ||
224 | wil_err(wil, | ||
225 | "Scan requested for unknown frequency %dMhz\n", | ||
226 | request->channels[i]->center_freq); | ||
227 | continue; | ||
228 | } | ||
229 | /* 0-based channel indexes */ | ||
230 | cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1; | ||
231 | wil_dbg(wil, "Scan for ch %d : %d MHz\n", ch, | ||
232 | request->channels[i]->center_freq); | ||
233 | } | ||
234 | |||
235 | return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) + | ||
236 | cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0])); | ||
237 | } | ||
238 | |||
239 | static int wil_cfg80211_connect(struct wiphy *wiphy, | ||
240 | struct net_device *ndev, | ||
241 | struct cfg80211_connect_params *sme) | ||
242 | { | ||
243 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
244 | struct cfg80211_bss *bss; | ||
245 | struct wmi_connect_cmd conn; | ||
246 | const u8 *ssid_eid; | ||
247 | const u8 *rsn_eid; | ||
248 | int ch; | ||
249 | int rc = 0; | ||
250 | |||
251 | bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid, | ||
252 | sme->ssid, sme->ssid_len, | ||
253 | WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS); | ||
254 | if (!bss) { | ||
255 | wil_err(wil, "Unable to find BSS\n"); | ||
256 | return -ENOENT; | ||
257 | } | ||
258 | |||
259 | ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID); | ||
260 | if (!ssid_eid) { | ||
261 | wil_err(wil, "No SSID\n"); | ||
262 | rc = -ENOENT; | ||
263 | goto out; | ||
264 | } | ||
265 | |||
266 | rsn_eid = sme->ie ? | ||
267 | cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) : | ||
268 | NULL; | ||
269 | if (rsn_eid) { | ||
270 | if (sme->ie_len > WMI_MAX_IE_LEN) { | ||
271 | rc = -ERANGE; | ||
272 | wil_err(wil, "IE too large (%td bytes)\n", | ||
273 | sme->ie_len); | ||
274 | goto out; | ||
275 | } | ||
276 | /* | ||
277 | * For secure assoc, send: | ||
278 | * (1) WMI_DELETE_CIPHER_KEY_CMD | ||
279 | * (2) WMI_SET_APPIE_CMD | ||
280 | */ | ||
281 | rc = wmi_del_cipher_key(wil, 0, bss->bssid); | ||
282 | if (rc) { | ||
283 | wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n"); | ||
284 | goto out; | ||
285 | } | ||
286 | /* WMI_SET_APPIE_CMD */ | ||
287 | rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie); | ||
288 | if (rc) { | ||
289 | wil_err(wil, "WMI_SET_APPIE_CMD failed\n"); | ||
290 | goto out; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | /* WMI_CONNECT_CMD */ | ||
295 | memset(&conn, 0, sizeof(conn)); | ||
296 | switch (bss->capability & 0x03) { | ||
297 | case WLAN_CAPABILITY_DMG_TYPE_AP: | ||
298 | conn.network_type = WMI_NETTYPE_INFRA; | ||
299 | break; | ||
300 | case WLAN_CAPABILITY_DMG_TYPE_PBSS: | ||
301 | conn.network_type = WMI_NETTYPE_P2P; | ||
302 | break; | ||
303 | default: | ||
304 | wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n", | ||
305 | bss->capability); | ||
306 | goto out; | ||
307 | } | ||
308 | if (rsn_eid) { | ||
309 | conn.dot11_auth_mode = WMI_AUTH11_SHARED; | ||
310 | conn.auth_mode = WMI_AUTH_WPA2_PSK; | ||
311 | conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP; | ||
312 | conn.pairwise_crypto_len = 16; | ||
313 | } else { | ||
314 | conn.dot11_auth_mode = WMI_AUTH11_OPEN; | ||
315 | conn.auth_mode = WMI_AUTH_NONE; | ||
316 | } | ||
317 | |||
318 | conn.ssid_len = min_t(u8, ssid_eid[1], 32); | ||
319 | memcpy(conn.ssid, ssid_eid+2, conn.ssid_len); | ||
320 | |||
321 | ch = bss->channel->hw_value; | ||
322 | if (ch == 0) { | ||
323 | wil_err(wil, "BSS at unknown frequency %dMhz\n", | ||
324 | bss->channel->center_freq); | ||
325 | rc = -EOPNOTSUPP; | ||
326 | goto out; | ||
327 | } | ||
328 | conn.channel = ch - 1; | ||
329 | |||
330 | memcpy(conn.bssid, bss->bssid, 6); | ||
331 | memcpy(conn.dst_mac, bss->bssid, 6); | ||
332 | /* | ||
333 | * FW don't support scan after connection attempt | ||
334 | */ | ||
335 | set_bit(wil_status_dontscan, &wil->status); | ||
336 | |||
337 | rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn)); | ||
338 | if (rc == 0) { | ||
339 | /* Connect can take lots of time */ | ||
340 | mod_timer(&wil->connect_timer, | ||
341 | jiffies + msecs_to_jiffies(2000)); | ||
342 | } | ||
343 | |||
344 | out: | ||
345 | cfg80211_put_bss(bss); | ||
346 | |||
347 | return rc; | ||
348 | } | ||
349 | |||
350 | static int wil_cfg80211_disconnect(struct wiphy *wiphy, | ||
351 | struct net_device *ndev, | ||
352 | u16 reason_code) | ||
353 | { | ||
354 | int rc; | ||
355 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
356 | |||
357 | rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0); | ||
358 | |||
359 | return rc; | ||
360 | } | ||
361 | |||
362 | static int wil_cfg80211_set_channel(struct wiphy *wiphy, | ||
363 | struct cfg80211_chan_def *chandef) | ||
364 | { | ||
365 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
366 | struct wireless_dev *wdev = wil->wdev; | ||
367 | |||
368 | wdev->preset_chandef = *chandef; | ||
369 | |||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static int wil_cfg80211_add_key(struct wiphy *wiphy, | ||
374 | struct net_device *ndev, | ||
375 | u8 key_index, bool pairwise, | ||
376 | const u8 *mac_addr, | ||
377 | struct key_params *params) | ||
378 | { | ||
379 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
380 | |||
381 | /* group key is not used */ | ||
382 | if (!pairwise) | ||
383 | return 0; | ||
384 | |||
385 | return wmi_add_cipher_key(wil, key_index, mac_addr, | ||
386 | params->key_len, params->key); | ||
387 | } | ||
388 | |||
389 | static int wil_cfg80211_del_key(struct wiphy *wiphy, | ||
390 | struct net_device *ndev, | ||
391 | u8 key_index, bool pairwise, | ||
392 | const u8 *mac_addr) | ||
393 | { | ||
394 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
395 | |||
396 | /* group key is not used */ | ||
397 | if (!pairwise) | ||
398 | return 0; | ||
399 | |||
400 | return wmi_del_cipher_key(wil, key_index, mac_addr); | ||
401 | } | ||
402 | |||
403 | /* Need to be present or wiphy_new() will WARN */ | ||
404 | static int wil_cfg80211_set_default_key(struct wiphy *wiphy, | ||
405 | struct net_device *ndev, | ||
406 | u8 key_index, bool unicast, | ||
407 | bool multicast) | ||
408 | { | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | static int wil_cfg80211_start_ap(struct wiphy *wiphy, | ||
413 | struct net_device *ndev, | ||
414 | struct cfg80211_ap_settings *info) | ||
415 | { | ||
416 | int rc = 0; | ||
417 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
418 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
419 | struct ieee80211_channel *channel = info->chandef.chan; | ||
420 | struct cfg80211_beacon_data *bcon = &info->beacon; | ||
421 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
422 | |||
423 | if (!channel) { | ||
424 | wil_err(wil, "AP: No channel???\n"); | ||
425 | return -EINVAL; | ||
426 | } | ||
427 | |||
428 | wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value, | ||
429 | channel->center_freq, info->privacy ? "secure" : "open"); | ||
430 | print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET, | ||
431 | info->ssid, info->ssid_len); | ||
432 | |||
433 | rc = wil_reset(wil); | ||
434 | if (rc) | ||
435 | return rc; | ||
436 | |||
437 | rc = wmi_set_ssid(wil, info->ssid_len, info->ssid); | ||
438 | if (rc) | ||
439 | return rc; | ||
440 | |||
441 | rc = wmi_set_channel(wil, channel->hw_value); | ||
442 | if (rc) | ||
443 | return rc; | ||
444 | |||
445 | /* MAC address - pre-requisite for other commands */ | ||
446 | wmi_set_mac_address(wil, ndev->dev_addr); | ||
447 | |||
448 | /* IE's */ | ||
449 | /* bcon 'head IE's are not relevant for 60g band */ | ||
450 | wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len, | ||
451 | bcon->beacon_ies); | ||
452 | wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len, | ||
453 | bcon->proberesp_ies); | ||
454 | wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len, | ||
455 | bcon->assocresp_ies); | ||
456 | |||
457 | wil->secure_pcp = info->privacy; | ||
458 | |||
459 | rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype); | ||
460 | if (rc) | ||
461 | return rc; | ||
462 | |||
463 | /* Rx VRING. After MAC and beacon */ | ||
464 | rc = wil_rx_init(wil); | ||
465 | |||
466 | netif_carrier_on(ndev); | ||
467 | |||
468 | return rc; | ||
469 | } | ||
470 | |||
471 | static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | ||
472 | struct net_device *ndev) | ||
473 | { | ||
474 | int rc = 0; | ||
475 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | ||
476 | struct wireless_dev *wdev = ndev->ieee80211_ptr; | ||
477 | u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
478 | |||
479 | /* To stop beaconing, set BI to 0 */ | ||
480 | rc = wmi_set_bcon(wil, 0, wmi_nettype); | ||
481 | |||
482 | return rc; | ||
483 | } | ||
484 | |||
485 | static struct cfg80211_ops wil_cfg80211_ops = { | ||
486 | .scan = wil_cfg80211_scan, | ||
487 | .connect = wil_cfg80211_connect, | ||
488 | .disconnect = wil_cfg80211_disconnect, | ||
489 | .change_virtual_intf = wil_cfg80211_change_iface, | ||
490 | .get_station = wil_cfg80211_get_station, | ||
491 | .set_monitor_channel = wil_cfg80211_set_channel, | ||
492 | .add_key = wil_cfg80211_add_key, | ||
493 | .del_key = wil_cfg80211_del_key, | ||
494 | .set_default_key = wil_cfg80211_set_default_key, | ||
495 | /* AP mode */ | ||
496 | .start_ap = wil_cfg80211_start_ap, | ||
497 | .stop_ap = wil_cfg80211_stop_ap, | ||
498 | }; | ||
499 | |||
500 | static void wil_wiphy_init(struct wiphy *wiphy) | ||
501 | { | ||
502 | /* TODO: set real value */ | ||
503 | wiphy->max_scan_ssids = 10; | ||
504 | wiphy->max_num_pmkids = 0 /* TODO: */; | ||
505 | wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | | ||
506 | BIT(NL80211_IFTYPE_AP) | | ||
507 | BIT(NL80211_IFTYPE_MONITOR); | ||
508 | /* TODO: enable P2P when integrated with supplicant: | ||
509 | * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) | ||
510 | */ | ||
511 | wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | | ||
512 | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; | ||
513 | dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n", | ||
514 | __func__, wiphy->flags); | ||
515 | wiphy->probe_resp_offload = | ||
516 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | | ||
517 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | | ||
518 | NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; | ||
519 | |||
520 | wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz; | ||
521 | |||
522 | /* TODO: figure this out */ | ||
523 | wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | ||
524 | |||
525 | wiphy->cipher_suites = wil_cipher_suites; | ||
526 | wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites); | ||
527 | wiphy->mgmt_stypes = wil_mgmt_stypes; | ||
528 | } | ||
529 | |||
530 | struct wireless_dev *wil_cfg80211_init(struct device *dev) | ||
531 | { | ||
532 | int rc = 0; | ||
533 | struct wireless_dev *wdev; | ||
534 | |||
535 | wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); | ||
536 | if (!wdev) | ||
537 | return ERR_PTR(-ENOMEM); | ||
538 | |||
539 | wdev->wiphy = wiphy_new(&wil_cfg80211_ops, | ||
540 | sizeof(struct wil6210_priv)); | ||
541 | if (!wdev->wiphy) { | ||
542 | rc = -ENOMEM; | ||
543 | goto out; | ||
544 | } | ||
545 | |||
546 | set_wiphy_dev(wdev->wiphy, dev); | ||
547 | wil_wiphy_init(wdev->wiphy); | ||
548 | |||
549 | rc = wiphy_register(wdev->wiphy); | ||
550 | if (rc < 0) | ||
551 | goto out_failed_reg; | ||
552 | |||
553 | return wdev; | ||
554 | |||
555 | out_failed_reg: | ||
556 | wiphy_free(wdev->wiphy); | ||
557 | out: | ||
558 | kfree(wdev); | ||
559 | |||
560 | return ERR_PTR(rc); | ||
561 | } | ||
562 | |||
563 | void wil_wdev_free(struct wil6210_priv *wil) | ||
564 | { | ||
565 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
566 | |||
567 | if (!wdev) | ||
568 | return; | ||
569 | |||
570 | wiphy_unregister(wdev->wiphy); | ||
571 | wiphy_free(wdev->wiphy); | ||
572 | kfree(wdev); | ||
573 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h new file mode 100644 index 000000000000..6a315ba5aa7d --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h | |||
@@ -0,0 +1,30 @@ | |||
1 | #ifndef WIL_DBG_HEXDUMP_H_ | ||
2 | #define WIL_DBG_HEXDUMP_H_ | ||
3 | |||
4 | #if defined(CONFIG_DYNAMIC_DEBUG) | ||
5 | #define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
6 | groupsize, buf, len, ascii) \ | ||
7 | do { \ | ||
8 | DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, \ | ||
9 | __builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\ | ||
10 | if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT)) \ | ||
11 | print_hex_dump(KERN_DEBUG, prefix_str, \ | ||
12 | prefix_type, rowsize, groupsize, \ | ||
13 | buf, len, ascii); \ | ||
14 | } while (0) | ||
15 | |||
16 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
17 | groupsize, buf, len, ascii) \ | ||
18 | wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize, \ | ||
19 | groupsize, buf, len, ascii) | ||
20 | |||
21 | #define print_hex_dump_bytes(prefix_str, prefix_type, buf, len) \ | ||
22 | wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true) | ||
23 | #else /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
24 | #define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize, \ | ||
25 | groupsize, buf, len, ascii) \ | ||
26 | print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize, \ | ||
27 | groupsize, buf, len, ascii) | ||
28 | #endif /* defined(CONFIG_DYNAMIC_DEBUG) */ | ||
29 | |||
30 | #endif /* WIL_DBG_HEXDUMP_H_ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c new file mode 100644 index 000000000000..65fc9683bfd8 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/debugfs.c | |||
@@ -0,0 +1,603 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/debugfs.h> | ||
19 | #include <linux/seq_file.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/rtnetlink.h> | ||
22 | |||
23 | #include "wil6210.h" | ||
24 | #include "txrx.h" | ||
25 | |||
26 | /* Nasty hack. Better have per device instances */ | ||
27 | static u32 mem_addr; | ||
28 | static u32 dbg_txdesc_index; | ||
29 | |||
30 | static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil, | ||
31 | const char *name, struct vring *vring) | ||
32 | { | ||
33 | void __iomem *x = wmi_addr(wil, vring->hwtail); | ||
34 | |||
35 | seq_printf(s, "VRING %s = {\n", name); | ||
36 | seq_printf(s, " pa = 0x%016llx\n", (unsigned long long)vring->pa); | ||
37 | seq_printf(s, " va = 0x%p\n", vring->va); | ||
38 | seq_printf(s, " size = %d\n", vring->size); | ||
39 | seq_printf(s, " swtail = %d\n", vring->swtail); | ||
40 | seq_printf(s, " swhead = %d\n", vring->swhead); | ||
41 | seq_printf(s, " hwtail = [0x%08x] -> ", vring->hwtail); | ||
42 | if (x) | ||
43 | seq_printf(s, "0x%08x\n", ioread32(x)); | ||
44 | else | ||
45 | seq_printf(s, "???\n"); | ||
46 | |||
47 | if (vring->va && (vring->size < 1025)) { | ||
48 | uint i; | ||
49 | for (i = 0; i < vring->size; i++) { | ||
50 | volatile struct vring_tx_desc *d = &vring->va[i].tx; | ||
51 | if ((i % 64) == 0 && (i != 0)) | ||
52 | seq_printf(s, "\n"); | ||
53 | seq_printf(s, "%s", (d->dma.status & BIT(0)) ? | ||
54 | "S" : (vring->ctx[i] ? "H" : "h")); | ||
55 | } | ||
56 | seq_printf(s, "\n"); | ||
57 | } | ||
58 | seq_printf(s, "}\n"); | ||
59 | } | ||
60 | |||
61 | static int wil_vring_debugfs_show(struct seq_file *s, void *data) | ||
62 | { | ||
63 | uint i; | ||
64 | struct wil6210_priv *wil = s->private; | ||
65 | |||
66 | wil_print_vring(s, wil, "rx", &wil->vring_rx); | ||
67 | |||
68 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { | ||
69 | struct vring *vring = &(wil->vring_tx[i]); | ||
70 | if (vring->va) { | ||
71 | char name[10]; | ||
72 | snprintf(name, sizeof(name), "tx_%2d", i); | ||
73 | wil_print_vring(s, wil, name, vring); | ||
74 | } | ||
75 | } | ||
76 | |||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int wil_vring_seq_open(struct inode *inode, struct file *file) | ||
81 | { | ||
82 | return single_open(file, wil_vring_debugfs_show, inode->i_private); | ||
83 | } | ||
84 | |||
85 | static const struct file_operations fops_vring = { | ||
86 | .open = wil_vring_seq_open, | ||
87 | .release = single_release, | ||
88 | .read = seq_read, | ||
89 | .llseek = seq_lseek, | ||
90 | }; | ||
91 | |||
92 | static void wil_print_ring(struct seq_file *s, const char *prefix, | ||
93 | void __iomem *off) | ||
94 | { | ||
95 | struct wil6210_priv *wil = s->private; | ||
96 | struct wil6210_mbox_ring r; | ||
97 | int rsize; | ||
98 | uint i; | ||
99 | |||
100 | wil_memcpy_fromio_32(&r, off, sizeof(r)); | ||
101 | wil_mbox_ring_le2cpus(&r); | ||
102 | /* | ||
103 | * we just read memory block from NIC. This memory may be | ||
104 | * garbage. Check validity before using it. | ||
105 | */ | ||
106 | rsize = r.size / sizeof(struct wil6210_mbox_ring_desc); | ||
107 | |||
108 | seq_printf(s, "ring %s = {\n", prefix); | ||
109 | seq_printf(s, " base = 0x%08x\n", r.base); | ||
110 | seq_printf(s, " size = 0x%04x bytes -> %d entries\n", r.size, rsize); | ||
111 | seq_printf(s, " tail = 0x%08x\n", r.tail); | ||
112 | seq_printf(s, " head = 0x%08x\n", r.head); | ||
113 | seq_printf(s, " entry size = %d\n", r.entry_size); | ||
114 | |||
115 | if (r.size % sizeof(struct wil6210_mbox_ring_desc)) { | ||
116 | seq_printf(s, " ??? size is not multiple of %zd, garbage?\n", | ||
117 | sizeof(struct wil6210_mbox_ring_desc)); | ||
118 | goto out; | ||
119 | } | ||
120 | |||
121 | if (!wmi_addr(wil, r.base) || | ||
122 | !wmi_addr(wil, r.tail) || | ||
123 | !wmi_addr(wil, r.head)) { | ||
124 | seq_printf(s, " ??? pointers are garbage?\n"); | ||
125 | goto out; | ||
126 | } | ||
127 | |||
128 | for (i = 0; i < rsize; i++) { | ||
129 | struct wil6210_mbox_ring_desc d; | ||
130 | struct wil6210_mbox_hdr hdr; | ||
131 | size_t delta = i * sizeof(d); | ||
132 | void __iomem *x = wil->csr + HOSTADDR(r.base) + delta; | ||
133 | |||
134 | wil_memcpy_fromio_32(&d, x, sizeof(d)); | ||
135 | |||
136 | seq_printf(s, " [%2x] %s %s%s 0x%08x", i, | ||
137 | d.sync ? "F" : "E", | ||
138 | (r.tail - r.base == delta) ? "t" : " ", | ||
139 | (r.head - r.base == delta) ? "h" : " ", | ||
140 | le32_to_cpu(d.addr)); | ||
141 | if (0 == wmi_read_hdr(wil, d.addr, &hdr)) { | ||
142 | u16 len = le16_to_cpu(hdr.len); | ||
143 | seq_printf(s, " -> %04x %04x %04x %02x\n", | ||
144 | le16_to_cpu(hdr.seq), len, | ||
145 | le16_to_cpu(hdr.type), hdr.flags); | ||
146 | if (len <= MAX_MBOXITEM_SIZE) { | ||
147 | int n = 0; | ||
148 | unsigned char printbuf[16 * 3 + 2]; | ||
149 | unsigned char databuf[MAX_MBOXITEM_SIZE]; | ||
150 | void __iomem *src = wmi_buffer(wil, d.addr) + | ||
151 | sizeof(struct wil6210_mbox_hdr); | ||
152 | /* | ||
153 | * No need to check @src for validity - | ||
154 | * we already validated @d.addr while | ||
155 | * reading header | ||
156 | */ | ||
157 | wil_memcpy_fromio_32(databuf, src, len); | ||
158 | while (n < len) { | ||
159 | int l = min(len - n, 16); | ||
160 | hex_dump_to_buffer(databuf + n, l, | ||
161 | 16, 1, printbuf, | ||
162 | sizeof(printbuf), | ||
163 | false); | ||
164 | seq_printf(s, " : %s\n", printbuf); | ||
165 | n += l; | ||
166 | } | ||
167 | } | ||
168 | } else { | ||
169 | seq_printf(s, "\n"); | ||
170 | } | ||
171 | } | ||
172 | out: | ||
173 | seq_printf(s, "}\n"); | ||
174 | } | ||
175 | |||
176 | static int wil_mbox_debugfs_show(struct seq_file *s, void *data) | ||
177 | { | ||
178 | struct wil6210_priv *wil = s->private; | ||
179 | |||
180 | wil_print_ring(s, "tx", wil->csr + HOST_MBOX + | ||
181 | offsetof(struct wil6210_mbox_ctl, tx)); | ||
182 | wil_print_ring(s, "rx", wil->csr + HOST_MBOX + | ||
183 | offsetof(struct wil6210_mbox_ctl, rx)); | ||
184 | |||
185 | return 0; | ||
186 | } | ||
187 | |||
188 | static int wil_mbox_seq_open(struct inode *inode, struct file *file) | ||
189 | { | ||
190 | return single_open(file, wil_mbox_debugfs_show, inode->i_private); | ||
191 | } | ||
192 | |||
193 | static const struct file_operations fops_mbox = { | ||
194 | .open = wil_mbox_seq_open, | ||
195 | .release = single_release, | ||
196 | .read = seq_read, | ||
197 | .llseek = seq_lseek, | ||
198 | }; | ||
199 | |||
200 | static int wil_debugfs_iomem_x32_set(void *data, u64 val) | ||
201 | { | ||
202 | iowrite32(val, (void __iomem *)data); | ||
203 | wmb(); /* make sure write propagated to HW */ | ||
204 | |||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | static int wil_debugfs_iomem_x32_get(void *data, u64 *val) | ||
209 | { | ||
210 | *val = ioread32((void __iomem *)data); | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get, | ||
216 | wil_debugfs_iomem_x32_set, "0x%08llx\n"); | ||
217 | |||
218 | static struct dentry *wil_debugfs_create_iomem_x32(const char *name, | ||
219 | mode_t mode, | ||
220 | struct dentry *parent, | ||
221 | void __iomem *value) | ||
222 | { | ||
223 | return debugfs_create_file(name, mode, parent, (void * __force)value, | ||
224 | &fops_iomem_x32); | ||
225 | } | ||
226 | |||
227 | static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil, | ||
228 | const char *name, | ||
229 | struct dentry *parent, u32 off) | ||
230 | { | ||
231 | struct dentry *d = debugfs_create_dir(name, parent); | ||
232 | |||
233 | if (IS_ERR_OR_NULL(d)) | ||
234 | return -ENODEV; | ||
235 | |||
236 | wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d, | ||
237 | wil->csr + off); | ||
238 | wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d, | ||
239 | wil->csr + off + 4); | ||
240 | wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d, | ||
241 | wil->csr + off + 8); | ||
242 | wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d, | ||
243 | wil->csr + off + 12); | ||
244 | wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d, | ||
245 | wil->csr + off + 16); | ||
246 | wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d, | ||
247 | wil->csr + off + 20); | ||
248 | wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d, | ||
249 | wil->csr + off + 24); | ||
250 | |||
251 | return 0; | ||
252 | } | ||
253 | |||
254 | static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil, | ||
255 | struct dentry *parent) | ||
256 | { | ||
257 | struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent); | ||
258 | |||
259 | if (IS_ERR_OR_NULL(d)) | ||
260 | return -ENODEV; | ||
261 | |||
262 | wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr + | ||
263 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); | ||
264 | wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr + | ||
265 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
266 | wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr + | ||
267 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW)); | ||
268 | |||
269 | return 0; | ||
270 | } | ||
271 | |||
272 | static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil, | ||
273 | struct dentry *parent) | ||
274 | { | ||
275 | struct dentry *d = debugfs_create_dir("ITR_CNT", parent); | ||
276 | |||
277 | if (IS_ERR_OR_NULL(d)) | ||
278 | return -ENODEV; | ||
279 | |||
280 | wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr + | ||
281 | HOSTADDR(RGF_DMA_ITR_CNT_TRSH)); | ||
282 | wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr + | ||
283 | HOSTADDR(RGF_DMA_ITR_CNT_DATA)); | ||
284 | wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr + | ||
285 | HOSTADDR(RGF_DMA_ITR_CNT_CRL)); | ||
286 | |||
287 | return 0; | ||
288 | } | ||
289 | |||
290 | static int wil_memread_debugfs_show(struct seq_file *s, void *data) | ||
291 | { | ||
292 | struct wil6210_priv *wil = s->private; | ||
293 | void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr)); | ||
294 | |||
295 | if (a) | ||
296 | seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a)); | ||
297 | else | ||
298 | seq_printf(s, "[0x%08x] = INVALID\n", mem_addr); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int wil_memread_seq_open(struct inode *inode, struct file *file) | ||
304 | { | ||
305 | return single_open(file, wil_memread_debugfs_show, inode->i_private); | ||
306 | } | ||
307 | |||
308 | static const struct file_operations fops_memread = { | ||
309 | .open = wil_memread_seq_open, | ||
310 | .release = single_release, | ||
311 | .read = seq_read, | ||
312 | .llseek = seq_lseek, | ||
313 | }; | ||
314 | |||
315 | static int wil_default_open(struct inode *inode, struct file *file) | ||
316 | { | ||
317 | if (inode->i_private) | ||
318 | file->private_data = inode->i_private; | ||
319 | |||
320 | return 0; | ||
321 | } | ||
322 | |||
323 | static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf, | ||
324 | size_t count, loff_t *ppos) | ||
325 | { | ||
326 | enum { max_count = 4096 }; | ||
327 | struct debugfs_blob_wrapper *blob = file->private_data; | ||
328 | loff_t pos = *ppos; | ||
329 | size_t available = blob->size; | ||
330 | void *buf; | ||
331 | size_t ret; | ||
332 | |||
333 | if (pos < 0) | ||
334 | return -EINVAL; | ||
335 | |||
336 | if (pos >= available || !count) | ||
337 | return 0; | ||
338 | |||
339 | if (count > available - pos) | ||
340 | count = available - pos; | ||
341 | if (count > max_count) | ||
342 | count = max_count; | ||
343 | |||
344 | buf = kmalloc(count, GFP_KERNEL); | ||
345 | if (!buf) | ||
346 | return -ENOMEM; | ||
347 | |||
348 | wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data + | ||
349 | pos, count); | ||
350 | |||
351 | ret = copy_to_user(user_buf, buf, count); | ||
352 | kfree(buf); | ||
353 | if (ret == count) | ||
354 | return -EFAULT; | ||
355 | |||
356 | count -= ret; | ||
357 | *ppos = pos + count; | ||
358 | |||
359 | return count; | ||
360 | } | ||
361 | |||
362 | static const struct file_operations fops_ioblob = { | ||
363 | .read = wil_read_file_ioblob, | ||
364 | .open = wil_default_open, | ||
365 | .llseek = default_llseek, | ||
366 | }; | ||
367 | |||
368 | static | ||
369 | struct dentry *wil_debugfs_create_ioblob(const char *name, | ||
370 | mode_t mode, | ||
371 | struct dentry *parent, | ||
372 | struct debugfs_blob_wrapper *blob) | ||
373 | { | ||
374 | return debugfs_create_file(name, mode, parent, blob, &fops_ioblob); | ||
375 | } | ||
376 | /*---reset---*/ | ||
377 | static ssize_t wil_write_file_reset(struct file *file, const char __user *buf, | ||
378 | size_t len, loff_t *ppos) | ||
379 | { | ||
380 | struct wil6210_priv *wil = file->private_data; | ||
381 | struct net_device *ndev = wil_to_ndev(wil); | ||
382 | |||
383 | /** | ||
384 | * BUG: | ||
385 | * this code does NOT sync device state with the rest of system | ||
386 | * use with care, debug only!!! | ||
387 | */ | ||
388 | rtnl_lock(); | ||
389 | dev_close(ndev); | ||
390 | ndev->flags &= ~IFF_UP; | ||
391 | rtnl_unlock(); | ||
392 | wil_reset(wil); | ||
393 | |||
394 | return len; | ||
395 | } | ||
396 | |||
397 | static const struct file_operations fops_reset = { | ||
398 | .write = wil_write_file_reset, | ||
399 | .open = wil_default_open, | ||
400 | }; | ||
401 | /*---------Tx descriptor------------*/ | ||
402 | |||
403 | static int wil_txdesc_debugfs_show(struct seq_file *s, void *data) | ||
404 | { | ||
405 | struct wil6210_priv *wil = s->private; | ||
406 | struct vring *vring = &(wil->vring_tx[0]); | ||
407 | |||
408 | if (!vring->va) { | ||
409 | seq_printf(s, "No Tx VRING\n"); | ||
410 | return 0; | ||
411 | } | ||
412 | |||
413 | if (dbg_txdesc_index < vring->size) { | ||
414 | volatile struct vring_tx_desc *d = | ||
415 | &(vring->va[dbg_txdesc_index].tx); | ||
416 | volatile u32 *u = (volatile u32 *)d; | ||
417 | struct sk_buff *skb = vring->ctx[dbg_txdesc_index]; | ||
418 | |||
419 | seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index); | ||
420 | seq_printf(s, " MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
421 | u[0], u[1], u[2], u[3]); | ||
422 | seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n", | ||
423 | u[4], u[5], u[6], u[7]); | ||
424 | seq_printf(s, " SKB = %p\n", skb); | ||
425 | |||
426 | if (skb) { | ||
427 | unsigned char printbuf[16 * 3 + 2]; | ||
428 | int i = 0; | ||
429 | int len = skb_headlen(skb); | ||
430 | void *p = skb->data; | ||
431 | |||
432 | seq_printf(s, " len = %d\n", len); | ||
433 | |||
434 | while (i < len) { | ||
435 | int l = min(len - i, 16); | ||
436 | hex_dump_to_buffer(p + i, l, 16, 1, printbuf, | ||
437 | sizeof(printbuf), false); | ||
438 | seq_printf(s, " : %s\n", printbuf); | ||
439 | i += l; | ||
440 | } | ||
441 | } | ||
442 | seq_printf(s, "}\n"); | ||
443 | } else { | ||
444 | seq_printf(s, "TxDesc index (%d) >= size (%d)\n", | ||
445 | dbg_txdesc_index, vring->size); | ||
446 | } | ||
447 | |||
448 | return 0; | ||
449 | } | ||
450 | |||
451 | static int wil_txdesc_seq_open(struct inode *inode, struct file *file) | ||
452 | { | ||
453 | return single_open(file, wil_txdesc_debugfs_show, inode->i_private); | ||
454 | } | ||
455 | |||
456 | static const struct file_operations fops_txdesc = { | ||
457 | .open = wil_txdesc_seq_open, | ||
458 | .release = single_release, | ||
459 | .read = seq_read, | ||
460 | .llseek = seq_lseek, | ||
461 | }; | ||
462 | |||
463 | /*---------beamforming------------*/ | ||
464 | static int wil_bf_debugfs_show(struct seq_file *s, void *data) | ||
465 | { | ||
466 | struct wil6210_priv *wil = s->private; | ||
467 | seq_printf(s, | ||
468 | "TSF : 0x%016llx\n" | ||
469 | "TxMCS : %d\n" | ||
470 | "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n", | ||
471 | wil->stats.tsf, wil->stats.bf_mcs, | ||
472 | wil->stats.my_rx_sector, wil->stats.my_tx_sector, | ||
473 | wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int wil_bf_seq_open(struct inode *inode, struct file *file) | ||
478 | { | ||
479 | return single_open(file, wil_bf_debugfs_show, inode->i_private); | ||
480 | } | ||
481 | |||
482 | static const struct file_operations fops_bf = { | ||
483 | .open = wil_bf_seq_open, | ||
484 | .release = single_release, | ||
485 | .read = seq_read, | ||
486 | .llseek = seq_lseek, | ||
487 | }; | ||
488 | /*---------SSID------------*/ | ||
489 | static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf, | ||
490 | size_t count, loff_t *ppos) | ||
491 | { | ||
492 | struct wil6210_priv *wil = file->private_data; | ||
493 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
494 | |||
495 | return simple_read_from_buffer(user_buf, count, ppos, | ||
496 | wdev->ssid, wdev->ssid_len); | ||
497 | } | ||
498 | |||
499 | static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf, | ||
500 | size_t count, loff_t *ppos) | ||
501 | { | ||
502 | struct wil6210_priv *wil = file->private_data; | ||
503 | struct wireless_dev *wdev = wil_to_wdev(wil); | ||
504 | struct net_device *ndev = wil_to_ndev(wil); | ||
505 | |||
506 | if (*ppos != 0) { | ||
507 | wil_err(wil, "Unable to set SSID substring from [%d]\n", | ||
508 | (int)*ppos); | ||
509 | return -EINVAL; | ||
510 | } | ||
511 | |||
512 | if (count > sizeof(wdev->ssid)) { | ||
513 | wil_err(wil, "SSID too long, len = %d\n", (int)count); | ||
514 | return -EINVAL; | ||
515 | } | ||
516 | if (netif_running(ndev)) { | ||
517 | wil_err(wil, "Unable to change SSID on running interface\n"); | ||
518 | return -EINVAL; | ||
519 | } | ||
520 | |||
521 | wdev->ssid_len = count; | ||
522 | return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos, | ||
523 | buf, count); | ||
524 | } | ||
525 | |||
526 | static const struct file_operations fops_ssid = { | ||
527 | .read = wil_read_file_ssid, | ||
528 | .write = wil_write_file_ssid, | ||
529 | .open = wil_default_open, | ||
530 | }; | ||
531 | |||
532 | /*----------------*/ | ||
533 | int wil6210_debugfs_init(struct wil6210_priv *wil) | ||
534 | { | ||
535 | struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME, | ||
536 | wil_to_wiphy(wil)->debugfsdir); | ||
537 | |||
538 | if (IS_ERR_OR_NULL(dbg)) | ||
539 | return -ENODEV; | ||
540 | |||
541 | debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox); | ||
542 | debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring); | ||
543 | debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc); | ||
544 | debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg, | ||
545 | &dbg_txdesc_index); | ||
546 | debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf); | ||
547 | debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid); | ||
548 | debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg, | ||
549 | &wil->secure_pcp); | ||
550 | |||
551 | wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg, | ||
552 | HOSTADDR(RGF_USER_USER_ICR)); | ||
553 | wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg, | ||
554 | HOSTADDR(RGF_DMA_EP_TX_ICR)); | ||
555 | wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg, | ||
556 | HOSTADDR(RGF_DMA_EP_RX_ICR)); | ||
557 | wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg, | ||
558 | HOSTADDR(RGF_DMA_EP_MISC_ICR)); | ||
559 | wil6210_debugfs_create_pseudo_ISR(wil, dbg); | ||
560 | wil6210_debugfs_create_ITR_CNT(wil, dbg); | ||
561 | |||
562 | debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr); | ||
563 | debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread); | ||
564 | |||
565 | debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset); | ||
566 | |||
567 | wil->rgf_blob.data = (void * __force)wil->csr + 0; | ||
568 | wil->rgf_blob.size = 0xa000; | ||
569 | wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob); | ||
570 | |||
571 | wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000; | ||
572 | wil->fw_code_blob.size = 0x40000; | ||
573 | wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg, | ||
574 | &wil->fw_code_blob); | ||
575 | |||
576 | wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000; | ||
577 | wil->fw_data_blob.size = 0x8000; | ||
578 | wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg, | ||
579 | &wil->fw_data_blob); | ||
580 | |||
581 | wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000; | ||
582 | wil->fw_peri_blob.size = 0x18000; | ||
583 | wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg, | ||
584 | &wil->fw_peri_blob); | ||
585 | |||
586 | wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000; | ||
587 | wil->uc_code_blob.size = 0x10000; | ||
588 | wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg, | ||
589 | &wil->uc_code_blob); | ||
590 | |||
591 | wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000; | ||
592 | wil->uc_data_blob.size = 0x4000; | ||
593 | wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg, | ||
594 | &wil->uc_data_blob); | ||
595 | |||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | void wil6210_debugfs_remove(struct wil6210_priv *wil) | ||
600 | { | ||
601 | debugfs_remove_recursive(wil->debug); | ||
602 | wil->debug = NULL; | ||
603 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c new file mode 100644 index 000000000000..38049da71049 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/interrupt.c | |||
@@ -0,0 +1,471 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/interrupt.h> | ||
18 | |||
19 | #include "wil6210.h" | ||
20 | |||
21 | /** | ||
22 | * Theory of operation: | ||
23 | * | ||
24 | * There is ISR pseudo-cause register, | ||
25 | * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE | ||
26 | * Its bits represents OR'ed bits from 3 real ISR registers: | ||
27 | * TX, RX, and MISC. | ||
28 | * | ||
29 | * Registers may be configured to either "write 1 to clear" or | ||
30 | * "clear on read" mode | ||
31 | * | ||
32 | * When handling interrupt, one have to mask/unmask interrupts for the | ||
33 | * real ISR registers, or hardware may malfunction. | ||
34 | * | ||
35 | */ | ||
36 | |||
37 | #define WIL6210_IRQ_DISABLE (0xFFFFFFFFUL) | ||
38 | #define WIL6210_IMC_RX BIT_DMA_EP_RX_ICR_RX_DONE | ||
39 | #define WIL6210_IMC_TX (BIT_DMA_EP_TX_ICR_TX_DONE | \ | ||
40 | BIT_DMA_EP_TX_ICR_TX_DONE_N(0)) | ||
41 | #define WIL6210_IMC_MISC (ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT) | ||
42 | |||
43 | #define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \ | ||
44 | BIT_DMA_PSEUDO_CAUSE_TX | \ | ||
45 | BIT_DMA_PSEUDO_CAUSE_MISC)) | ||
46 | |||
47 | #if defined(CONFIG_WIL6210_ISR_COR) | ||
48 | /* configure to Clear-On-Read mode */ | ||
49 | #define WIL_ICR_ICC_VALUE (0xFFFFFFFFUL) | ||
50 | |||
51 | static inline void wil_icr_clear(u32 x, void __iomem *addr) | ||
52 | { | ||
53 | |||
54 | } | ||
55 | #else /* defined(CONFIG_WIL6210_ISR_COR) */ | ||
56 | /* configure to Write-1-to-Clear mode */ | ||
57 | #define WIL_ICR_ICC_VALUE (0UL) | ||
58 | |||
59 | static inline void wil_icr_clear(u32 x, void __iomem *addr) | ||
60 | { | ||
61 | iowrite32(x, addr); | ||
62 | } | ||
63 | #endif /* defined(CONFIG_WIL6210_ISR_COR) */ | ||
64 | |||
65 | static inline u32 wil_ioread32_and_clear(void __iomem *addr) | ||
66 | { | ||
67 | u32 x = ioread32(addr); | ||
68 | |||
69 | wil_icr_clear(x, addr); | ||
70 | |||
71 | return x; | ||
72 | } | ||
73 | |||
74 | static void wil6210_mask_irq_tx(struct wil6210_priv *wil) | ||
75 | { | ||
76 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
77 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
78 | offsetof(struct RGF_ICR, IMS)); | ||
79 | } | ||
80 | |||
81 | static void wil6210_mask_irq_rx(struct wil6210_priv *wil) | ||
82 | { | ||
83 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
84 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
85 | offsetof(struct RGF_ICR, IMS)); | ||
86 | } | ||
87 | |||
88 | static void wil6210_mask_irq_misc(struct wil6210_priv *wil) | ||
89 | { | ||
90 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
91 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
92 | offsetof(struct RGF_ICR, IMS)); | ||
93 | } | ||
94 | |||
95 | static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil) | ||
96 | { | ||
97 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
98 | |||
99 | iowrite32(WIL6210_IRQ_DISABLE, wil->csr + | ||
100 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
101 | |||
102 | clear_bit(wil_status_irqen, &wil->status); | ||
103 | } | ||
104 | |||
105 | static void wil6210_unmask_irq_tx(struct wil6210_priv *wil) | ||
106 | { | ||
107 | iowrite32(WIL6210_IMC_TX, wil->csr + | ||
108 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
109 | offsetof(struct RGF_ICR, IMC)); | ||
110 | } | ||
111 | |||
112 | static void wil6210_unmask_irq_rx(struct wil6210_priv *wil) | ||
113 | { | ||
114 | iowrite32(WIL6210_IMC_RX, wil->csr + | ||
115 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
116 | offsetof(struct RGF_ICR, IMC)); | ||
117 | } | ||
118 | |||
119 | static void wil6210_unmask_irq_misc(struct wil6210_priv *wil) | ||
120 | { | ||
121 | iowrite32(WIL6210_IMC_MISC, wil->csr + | ||
122 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
123 | offsetof(struct RGF_ICR, IMC)); | ||
124 | } | ||
125 | |||
126 | static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil) | ||
127 | { | ||
128 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
129 | |||
130 | set_bit(wil_status_irqen, &wil->status); | ||
131 | |||
132 | iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr + | ||
133 | HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW)); | ||
134 | } | ||
135 | |||
136 | void wil6210_disable_irq(struct wil6210_priv *wil) | ||
137 | { | ||
138 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
139 | |||
140 | wil6210_mask_irq_tx(wil); | ||
141 | wil6210_mask_irq_rx(wil); | ||
142 | wil6210_mask_irq_misc(wil); | ||
143 | wil6210_mask_irq_pseudo(wil); | ||
144 | } | ||
145 | |||
146 | void wil6210_enable_irq(struct wil6210_priv *wil) | ||
147 | { | ||
148 | wil_dbg_IRQ(wil, "%s()\n", __func__); | ||
149 | |||
150 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
151 | offsetof(struct RGF_ICR, ICC)); | ||
152 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
153 | offsetof(struct RGF_ICR, ICC)); | ||
154 | iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
155 | offsetof(struct RGF_ICR, ICC)); | ||
156 | |||
157 | wil6210_unmask_irq_pseudo(wil); | ||
158 | wil6210_unmask_irq_tx(wil); | ||
159 | wil6210_unmask_irq_rx(wil); | ||
160 | wil6210_unmask_irq_misc(wil); | ||
161 | } | ||
162 | |||
163 | static irqreturn_t wil6210_irq_rx(int irq, void *cookie) | ||
164 | { | ||
165 | struct wil6210_priv *wil = cookie; | ||
166 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
167 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
168 | offsetof(struct RGF_ICR, ICR)); | ||
169 | |||
170 | wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr); | ||
171 | |||
172 | if (!isr) { | ||
173 | wil_err(wil, "spurious IRQ: RX\n"); | ||
174 | return IRQ_NONE; | ||
175 | } | ||
176 | |||
177 | wil6210_mask_irq_rx(wil); | ||
178 | |||
179 | if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) { | ||
180 | wil_dbg_IRQ(wil, "RX done\n"); | ||
181 | isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE; | ||
182 | wil_rx_handle(wil); | ||
183 | } | ||
184 | |||
185 | if (isr) | ||
186 | wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr); | ||
187 | |||
188 | wil6210_unmask_irq_rx(wil); | ||
189 | |||
190 | return IRQ_HANDLED; | ||
191 | } | ||
192 | |||
193 | static irqreturn_t wil6210_irq_tx(int irq, void *cookie) | ||
194 | { | ||
195 | struct wil6210_priv *wil = cookie; | ||
196 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
197 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
198 | offsetof(struct RGF_ICR, ICR)); | ||
199 | |||
200 | wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr); | ||
201 | |||
202 | if (!isr) { | ||
203 | wil_err(wil, "spurious IRQ: TX\n"); | ||
204 | return IRQ_NONE; | ||
205 | } | ||
206 | |||
207 | wil6210_mask_irq_tx(wil); | ||
208 | |||
209 | if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) { | ||
210 | uint i; | ||
211 | wil_dbg_IRQ(wil, "TX done\n"); | ||
212 | isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE; | ||
213 | for (i = 0; i < 24; i++) { | ||
214 | u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i); | ||
215 | if (isr & mask) { | ||
216 | isr &= ~mask; | ||
217 | wil_dbg_IRQ(wil, "TX done(%i)\n", i); | ||
218 | wil_tx_complete(wil, i); | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | |||
223 | if (isr) | ||
224 | wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr); | ||
225 | |||
226 | wil6210_unmask_irq_tx(wil); | ||
227 | |||
228 | return IRQ_HANDLED; | ||
229 | } | ||
230 | |||
231 | static irqreturn_t wil6210_irq_misc(int irq, void *cookie) | ||
232 | { | ||
233 | struct wil6210_priv *wil = cookie; | ||
234 | u32 isr = wil_ioread32_and_clear(wil->csr + | ||
235 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
236 | offsetof(struct RGF_ICR, ICR)); | ||
237 | |||
238 | wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr); | ||
239 | |||
240 | if (!isr) { | ||
241 | wil_err(wil, "spurious IRQ: MISC\n"); | ||
242 | return IRQ_NONE; | ||
243 | } | ||
244 | |||
245 | wil6210_mask_irq_misc(wil); | ||
246 | |||
247 | if (isr & ISR_MISC_FW_READY) { | ||
248 | wil_dbg_IRQ(wil, "IRQ: FW ready\n"); | ||
249 | /** | ||
250 | * Actual FW ready indicated by the | ||
251 | * WMI_FW_READY_EVENTID | ||
252 | */ | ||
253 | isr &= ~ISR_MISC_FW_READY; | ||
254 | } | ||
255 | |||
256 | wil->isr_misc = isr; | ||
257 | |||
258 | if (isr) { | ||
259 | return IRQ_WAKE_THREAD; | ||
260 | } else { | ||
261 | wil6210_unmask_irq_misc(wil); | ||
262 | return IRQ_HANDLED; | ||
263 | } | ||
264 | } | ||
265 | |||
266 | static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie) | ||
267 | { | ||
268 | struct wil6210_priv *wil = cookie; | ||
269 | u32 isr = wil->isr_misc; | ||
270 | |||
271 | wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr); | ||
272 | |||
273 | if (isr & ISR_MISC_MBOX_EVT) { | ||
274 | wil_dbg_IRQ(wil, "MBOX event\n"); | ||
275 | wmi_recv_cmd(wil); | ||
276 | isr &= ~ISR_MISC_MBOX_EVT; | ||
277 | } | ||
278 | |||
279 | if (isr) | ||
280 | wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr); | ||
281 | |||
282 | wil->isr_misc = 0; | ||
283 | |||
284 | wil6210_unmask_irq_misc(wil); | ||
285 | |||
286 | return IRQ_HANDLED; | ||
287 | } | ||
288 | |||
289 | /** | ||
290 | * thread IRQ handler | ||
291 | */ | ||
292 | static irqreturn_t wil6210_thread_irq(int irq, void *cookie) | ||
293 | { | ||
294 | struct wil6210_priv *wil = cookie; | ||
295 | |||
296 | wil_dbg_IRQ(wil, "Thread IRQ\n"); | ||
297 | /* Discover real IRQ cause */ | ||
298 | if (wil->isr_misc) | ||
299 | wil6210_irq_misc_thread(irq, cookie); | ||
300 | |||
301 | wil6210_unmask_irq_pseudo(wil); | ||
302 | |||
303 | return IRQ_HANDLED; | ||
304 | } | ||
305 | |||
306 | /* DEBUG | ||
307 | * There is subtle bug in hardware that causes IRQ to raise when it should be | ||
308 | * masked. It is quite rare and hard to debug. | ||
309 | * | ||
310 | * Catch irq issue if it happens and print all I can. | ||
311 | */ | ||
312 | static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause) | ||
313 | { | ||
314 | if (!test_bit(wil_status_irqen, &wil->status)) { | ||
315 | u32 icm_rx = wil_ioread32_and_clear(wil->csr + | ||
316 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
317 | offsetof(struct RGF_ICR, ICM)); | ||
318 | u32 icr_rx = wil_ioread32_and_clear(wil->csr + | ||
319 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
320 | offsetof(struct RGF_ICR, ICR)); | ||
321 | u32 imv_rx = ioread32(wil->csr + | ||
322 | HOSTADDR(RGF_DMA_EP_RX_ICR) + | ||
323 | offsetof(struct RGF_ICR, IMV)); | ||
324 | u32 icm_tx = wil_ioread32_and_clear(wil->csr + | ||
325 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
326 | offsetof(struct RGF_ICR, ICM)); | ||
327 | u32 icr_tx = wil_ioread32_and_clear(wil->csr + | ||
328 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
329 | offsetof(struct RGF_ICR, ICR)); | ||
330 | u32 imv_tx = ioread32(wil->csr + | ||
331 | HOSTADDR(RGF_DMA_EP_TX_ICR) + | ||
332 | offsetof(struct RGF_ICR, IMV)); | ||
333 | u32 icm_misc = wil_ioread32_and_clear(wil->csr + | ||
334 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
335 | offsetof(struct RGF_ICR, ICM)); | ||
336 | u32 icr_misc = wil_ioread32_and_clear(wil->csr + | ||
337 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
338 | offsetof(struct RGF_ICR, ICR)); | ||
339 | u32 imv_misc = ioread32(wil->csr + | ||
340 | HOSTADDR(RGF_DMA_EP_MISC_ICR) + | ||
341 | offsetof(struct RGF_ICR, IMV)); | ||
342 | wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n" | ||
343 | "Rx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" | ||
344 | "Tx icm:icr:imv 0x%08x 0x%08x 0x%08x\n" | ||
345 | "Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n", | ||
346 | pseudo_cause, | ||
347 | icm_rx, icr_rx, imv_rx, | ||
348 | icm_tx, icr_tx, imv_tx, | ||
349 | icm_misc, icr_misc, imv_misc); | ||
350 | |||
351 | return -EINVAL; | ||
352 | } | ||
353 | |||
354 | return 0; | ||
355 | } | ||
356 | |||
357 | static irqreturn_t wil6210_hardirq(int irq, void *cookie) | ||
358 | { | ||
359 | irqreturn_t rc = IRQ_HANDLED; | ||
360 | struct wil6210_priv *wil = cookie; | ||
361 | u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE)); | ||
362 | |||
363 | /** | ||
364 | * pseudo_cause is Clear-On-Read, no need to ACK | ||
365 | */ | ||
366 | if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff)) | ||
367 | return IRQ_NONE; | ||
368 | |||
369 | /* FIXME: IRQ mask debug */ | ||
370 | if (wil6210_debug_irq_mask(wil, pseudo_cause)) | ||
371 | return IRQ_NONE; | ||
372 | |||
373 | wil6210_mask_irq_pseudo(wil); | ||
374 | |||
375 | /* Discover real IRQ cause | ||
376 | * There are 2 possible phases for every IRQ: | ||
377 | * - hard IRQ handler called right here | ||
378 | * - threaded handler called later | ||
379 | * | ||
380 | * Hard IRQ handler reads and clears ISR. | ||
381 | * | ||
382 | * If threaded handler requested, hard IRQ handler | ||
383 | * returns IRQ_WAKE_THREAD and saves ISR register value | ||
384 | * for the threaded handler use. | ||
385 | * | ||
386 | * voting for wake thread - need at least 1 vote | ||
387 | */ | ||
388 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) && | ||
389 | (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD)) | ||
390 | rc = IRQ_WAKE_THREAD; | ||
391 | |||
392 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) && | ||
393 | (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD)) | ||
394 | rc = IRQ_WAKE_THREAD; | ||
395 | |||
396 | if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) && | ||
397 | (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD)) | ||
398 | rc = IRQ_WAKE_THREAD; | ||
399 | |||
400 | /* if thread is requested, it will unmask IRQ */ | ||
401 | if (rc != IRQ_WAKE_THREAD) | ||
402 | wil6210_unmask_irq_pseudo(wil); | ||
403 | |||
404 | wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause); | ||
405 | |||
406 | return rc; | ||
407 | } | ||
408 | |||
409 | static int wil6210_request_3msi(struct wil6210_priv *wil, int irq) | ||
410 | { | ||
411 | int rc; | ||
412 | /* | ||
413 | * IRQ's are in the following order: | ||
414 | * - Tx | ||
415 | * - Rx | ||
416 | * - Misc | ||
417 | */ | ||
418 | |||
419 | rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED, | ||
420 | WIL_NAME"_tx", wil); | ||
421 | if (rc) | ||
422 | return rc; | ||
423 | |||
424 | rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED, | ||
425 | WIL_NAME"_rx", wil); | ||
426 | if (rc) | ||
427 | goto free0; | ||
428 | |||
429 | rc = request_threaded_irq(irq + 2, wil6210_irq_misc, | ||
430 | wil6210_irq_misc_thread, | ||
431 | IRQF_SHARED, WIL_NAME"_misc", wil); | ||
432 | if (rc) | ||
433 | goto free1; | ||
434 | |||
435 | return 0; | ||
436 | /* error branch */ | ||
437 | free1: | ||
438 | free_irq(irq + 1, wil); | ||
439 | free0: | ||
440 | free_irq(irq, wil); | ||
441 | |||
442 | return rc; | ||
443 | } | ||
444 | |||
445 | int wil6210_init_irq(struct wil6210_priv *wil, int irq) | ||
446 | { | ||
447 | int rc; | ||
448 | if (wil->n_msi == 3) | ||
449 | rc = wil6210_request_3msi(wil, irq); | ||
450 | else | ||
451 | rc = request_threaded_irq(irq, wil6210_hardirq, | ||
452 | wil6210_thread_irq, | ||
453 | wil->n_msi ? 0 : IRQF_SHARED, | ||
454 | WIL_NAME, wil); | ||
455 | if (rc) | ||
456 | return rc; | ||
457 | |||
458 | wil6210_enable_irq(wil); | ||
459 | |||
460 | return 0; | ||
461 | } | ||
462 | |||
463 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq) | ||
464 | { | ||
465 | wil6210_disable_irq(wil); | ||
466 | free_irq(irq, wil); | ||
467 | if (wil->n_msi == 3) { | ||
468 | free_irq(irq + 1, wil); | ||
469 | free_irq(irq + 2, wil); | ||
470 | } | ||
471 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c new file mode 100644 index 000000000000..95fcd361322b --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -0,0 +1,407 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/sched.h> | ||
20 | #include <linux/ieee80211.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <linux/slab.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | #include <linux/if_arp.h> | ||
25 | |||
26 | #include "wil6210.h" | ||
27 | |||
28 | /* | ||
29 | * Due to a hardware issue, | ||
30 | * one has to read/write to/from NIC in 32-bit chunks; | ||
31 | * regular memcpy_fromio and siblings will | ||
32 | * not work on 64-bit platform - it uses 64-bit transactions | ||
33 | * | ||
34 | * Force 32-bit transactions to enable NIC on 64-bit platforms | ||
35 | * | ||
36 | * To avoid byte swap on big endian host, __raw_{read|write}l | ||
37 | * should be used - {read|write}l would swap bytes to provide | ||
38 | * little endian on PCI value in host endianness. | ||
39 | */ | ||
40 | void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | ||
41 | size_t count) | ||
42 | { | ||
43 | u32 *d = dst; | ||
44 | const volatile u32 __iomem *s = src; | ||
45 | |||
46 | /* size_t is unsigned, if (count%4 != 0) it will wrap */ | ||
47 | for (count += 4; count > 4; count -= 4) | ||
48 | *d++ = __raw_readl(s++); | ||
49 | } | ||
50 | |||
51 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | ||
52 | size_t count) | ||
53 | { | ||
54 | volatile u32 __iomem *d = dst; | ||
55 | const u32 *s = src; | ||
56 | |||
57 | for (count += 4; count > 4; count -= 4) | ||
58 | __raw_writel(*s++, d++); | ||
59 | } | ||
60 | |||
61 | static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | ||
62 | { | ||
63 | uint i; | ||
64 | struct net_device *ndev = wil_to_ndev(wil); | ||
65 | struct wireless_dev *wdev = wil->wdev; | ||
66 | |||
67 | wil_dbg(wil, "%s()\n", __func__); | ||
68 | |||
69 | wil_link_off(wil); | ||
70 | clear_bit(wil_status_fwconnected, &wil->status); | ||
71 | |||
72 | switch (wdev->sme_state) { | ||
73 | case CFG80211_SME_CONNECTED: | ||
74 | cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
75 | NULL, 0, GFP_KERNEL); | ||
76 | break; | ||
77 | case CFG80211_SME_CONNECTING: | ||
78 | cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0, | ||
79 | WLAN_STATUS_UNSPECIFIED_FAILURE, | ||
80 | GFP_KERNEL); | ||
81 | break; | ||
82 | default: | ||
83 | ; | ||
84 | } | ||
85 | |||
86 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) | ||
87 | wil_vring_fini_tx(wil, i); | ||
88 | } | ||
89 | |||
90 | static void wil_disconnect_worker(struct work_struct *work) | ||
91 | { | ||
92 | struct wil6210_priv *wil = container_of(work, | ||
93 | struct wil6210_priv, disconnect_worker); | ||
94 | |||
95 | _wil6210_disconnect(wil, NULL); | ||
96 | } | ||
97 | |||
98 | static void wil_connect_timer_fn(ulong x) | ||
99 | { | ||
100 | struct wil6210_priv *wil = (void *)x; | ||
101 | |||
102 | wil_dbg(wil, "Connect timeout\n"); | ||
103 | |||
104 | /* reschedule to thread context - disconnect won't | ||
105 | * run from atomic context | ||
106 | */ | ||
107 | schedule_work(&wil->disconnect_worker); | ||
108 | } | ||
109 | |||
110 | int wil_priv_init(struct wil6210_priv *wil) | ||
111 | { | ||
112 | wil_dbg(wil, "%s()\n", __func__); | ||
113 | |||
114 | mutex_init(&wil->mutex); | ||
115 | mutex_init(&wil->wmi_mutex); | ||
116 | |||
117 | init_completion(&wil->wmi_ready); | ||
118 | |||
119 | wil->pending_connect_cid = -1; | ||
120 | setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil); | ||
121 | |||
122 | INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker); | ||
123 | INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker); | ||
124 | INIT_WORK(&wil->wmi_event_worker, wmi_event_worker); | ||
125 | |||
126 | INIT_LIST_HEAD(&wil->pending_wmi_ev); | ||
127 | spin_lock_init(&wil->wmi_ev_lock); | ||
128 | |||
129 | wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi"); | ||
130 | if (!wil->wmi_wq) | ||
131 | return -EAGAIN; | ||
132 | |||
133 | wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect"); | ||
134 | if (!wil->wmi_wq_conn) { | ||
135 | destroy_workqueue(wil->wmi_wq); | ||
136 | return -EAGAIN; | ||
137 | } | ||
138 | |||
139 | /* make shadow copy of registers that should not change on run time */ | ||
140 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
141 | sizeof(struct wil6210_mbox_ctl)); | ||
142 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
143 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid) | ||
149 | { | ||
150 | del_timer_sync(&wil->connect_timer); | ||
151 | _wil6210_disconnect(wil, bssid); | ||
152 | } | ||
153 | |||
154 | void wil_priv_deinit(struct wil6210_priv *wil) | ||
155 | { | ||
156 | cancel_work_sync(&wil->disconnect_worker); | ||
157 | wil6210_disconnect(wil, NULL); | ||
158 | wmi_event_flush(wil); | ||
159 | destroy_workqueue(wil->wmi_wq_conn); | ||
160 | destroy_workqueue(wil->wmi_wq); | ||
161 | } | ||
162 | |||
163 | static void wil_target_reset(struct wil6210_priv *wil) | ||
164 | { | ||
165 | wil_dbg(wil, "Resetting...\n"); | ||
166 | |||
167 | /* register write */ | ||
168 | #define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a)) | ||
169 | /* register set = read, OR, write */ | ||
170 | #define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \ | ||
171 | wil->csr + HOSTADDR(a)) | ||
172 | |||
173 | /* hpal_perst_from_pad_src_n_mask */ | ||
174 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6)); | ||
175 | /* car_perst_rst_src_n_mask */ | ||
176 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7)); | ||
177 | |||
178 | W(RGF_USER_MAC_CPU_0, BIT(1)); /* mac_cpu_man_rst */ | ||
179 | W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */ | ||
180 | |||
181 | msleep(100); | ||
182 | |||
183 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000); | ||
184 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F); | ||
185 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170); | ||
186 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00); | ||
187 | |||
188 | msleep(100); | ||
189 | |||
190 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0); | ||
191 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0); | ||
192 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0); | ||
193 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | ||
194 | |||
195 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001); | ||
196 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080); | ||
197 | W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0); | ||
198 | |||
199 | msleep(2000); | ||
200 | |||
201 | W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */ | ||
202 | |||
203 | msleep(2000); | ||
204 | |||
205 | wil_dbg(wil, "Reset completed\n"); | ||
206 | |||
207 | #undef W | ||
208 | #undef S | ||
209 | } | ||
210 | |||
211 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r) | ||
212 | { | ||
213 | le32_to_cpus(&r->base); | ||
214 | le16_to_cpus(&r->entry_size); | ||
215 | le16_to_cpus(&r->size); | ||
216 | le32_to_cpus(&r->tail); | ||
217 | le32_to_cpus(&r->head); | ||
218 | } | ||
219 | |||
220 | static int wil_wait_for_fw_ready(struct wil6210_priv *wil) | ||
221 | { | ||
222 | ulong to = msecs_to_jiffies(1000); | ||
223 | ulong left = wait_for_completion_timeout(&wil->wmi_ready, to); | ||
224 | if (0 == left) { | ||
225 | wil_err(wil, "Firmware not ready\n"); | ||
226 | return -ETIME; | ||
227 | } else { | ||
228 | wil_dbg(wil, "FW ready after %d ms\n", | ||
229 | jiffies_to_msecs(to-left)); | ||
230 | } | ||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | /* | ||
235 | * We reset all the structures, and we reset the UMAC. | ||
236 | * After calling this routine, you're expected to reload | ||
237 | * the firmware. | ||
238 | */ | ||
239 | int wil_reset(struct wil6210_priv *wil) | ||
240 | { | ||
241 | int rc; | ||
242 | |||
243 | cancel_work_sync(&wil->disconnect_worker); | ||
244 | wil6210_disconnect(wil, NULL); | ||
245 | |||
246 | wmi_event_flush(wil); | ||
247 | |||
248 | flush_workqueue(wil->wmi_wq); | ||
249 | flush_workqueue(wil->wmi_wq_conn); | ||
250 | |||
251 | wil6210_disable_irq(wil); | ||
252 | wil->status = 0; | ||
253 | |||
254 | /* TODO: put MAC in reset */ | ||
255 | wil_target_reset(wil); | ||
256 | |||
257 | /* init after reset */ | ||
258 | wil->pending_connect_cid = -1; | ||
259 | INIT_COMPLETION(wil->wmi_ready); | ||
260 | |||
261 | /* make shadow copy of registers that should not change on run time */ | ||
262 | wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX, | ||
263 | sizeof(struct wil6210_mbox_ctl)); | ||
264 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx); | ||
265 | wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx); | ||
266 | |||
267 | /* TODO: release MAC reset */ | ||
268 | wil6210_enable_irq(wil); | ||
269 | |||
270 | /* we just started MAC, wait for FW ready */ | ||
271 | rc = wil_wait_for_fw_ready(wil); | ||
272 | |||
273 | return rc; | ||
274 | } | ||
275 | |||
276 | |||
277 | void wil_link_on(struct wil6210_priv *wil) | ||
278 | { | ||
279 | struct net_device *ndev = wil_to_ndev(wil); | ||
280 | |||
281 | wil_dbg(wil, "%s()\n", __func__); | ||
282 | |||
283 | netif_carrier_on(ndev); | ||
284 | netif_tx_wake_all_queues(ndev); | ||
285 | } | ||
286 | |||
287 | void wil_link_off(struct wil6210_priv *wil) | ||
288 | { | ||
289 | struct net_device *ndev = wil_to_ndev(wil); | ||
290 | |||
291 | wil_dbg(wil, "%s()\n", __func__); | ||
292 | |||
293 | netif_tx_stop_all_queues(ndev); | ||
294 | netif_carrier_off(ndev); | ||
295 | } | ||
296 | |||
297 | static int __wil_up(struct wil6210_priv *wil) | ||
298 | { | ||
299 | struct net_device *ndev = wil_to_ndev(wil); | ||
300 | struct wireless_dev *wdev = wil->wdev; | ||
301 | struct ieee80211_channel *channel = wdev->preset_chandef.chan; | ||
302 | int rc; | ||
303 | int bi; | ||
304 | u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype); | ||
305 | |||
306 | rc = wil_reset(wil); | ||
307 | if (rc) | ||
308 | return rc; | ||
309 | |||
310 | /* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */ | ||
311 | wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC); | ||
312 | switch (wdev->iftype) { | ||
313 | case NL80211_IFTYPE_STATION: | ||
314 | wil_dbg(wil, "type: STATION\n"); | ||
315 | bi = 0; | ||
316 | ndev->type = ARPHRD_ETHER; | ||
317 | break; | ||
318 | case NL80211_IFTYPE_AP: | ||
319 | wil_dbg(wil, "type: AP\n"); | ||
320 | bi = 100; | ||
321 | ndev->type = ARPHRD_ETHER; | ||
322 | break; | ||
323 | case NL80211_IFTYPE_P2P_CLIENT: | ||
324 | wil_dbg(wil, "type: P2P_CLIENT\n"); | ||
325 | bi = 0; | ||
326 | ndev->type = ARPHRD_ETHER; | ||
327 | break; | ||
328 | case NL80211_IFTYPE_P2P_GO: | ||
329 | wil_dbg(wil, "type: P2P_GO\n"); | ||
330 | bi = 100; | ||
331 | ndev->type = ARPHRD_ETHER; | ||
332 | break; | ||
333 | case NL80211_IFTYPE_MONITOR: | ||
334 | wil_dbg(wil, "type: Monitor\n"); | ||
335 | bi = 0; | ||
336 | ndev->type = ARPHRD_IEEE80211_RADIOTAP; | ||
337 | /* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */ | ||
338 | break; | ||
339 | default: | ||
340 | return -EOPNOTSUPP; | ||
341 | } | ||
342 | |||
343 | /* Apply profile in the following order: */ | ||
344 | /* SSID and channel for the AP */ | ||
345 | switch (wdev->iftype) { | ||
346 | case NL80211_IFTYPE_AP: | ||
347 | case NL80211_IFTYPE_P2P_GO: | ||
348 | if (wdev->ssid_len == 0) { | ||
349 | wil_err(wil, "SSID not set\n"); | ||
350 | return -EINVAL; | ||
351 | } | ||
352 | wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid); | ||
353 | if (channel) | ||
354 | wmi_set_channel(wil, channel->hw_value); | ||
355 | break; | ||
356 | default: | ||
357 | ; | ||
358 | } | ||
359 | |||
360 | /* MAC address - pre-requisite for other commands */ | ||
361 | wmi_set_mac_address(wil, ndev->dev_addr); | ||
362 | |||
363 | /* Set up beaconing if required. */ | ||
364 | rc = wmi_set_bcon(wil, bi, wmi_nettype); | ||
365 | if (rc) | ||
366 | return rc; | ||
367 | |||
368 | /* Rx VRING. After MAC and beacon */ | ||
369 | wil_rx_init(wil); | ||
370 | |||
371 | return 0; | ||
372 | } | ||
373 | |||
374 | int wil_up(struct wil6210_priv *wil) | ||
375 | { | ||
376 | int rc; | ||
377 | |||
378 | mutex_lock(&wil->mutex); | ||
379 | rc = __wil_up(wil); | ||
380 | mutex_unlock(&wil->mutex); | ||
381 | |||
382 | return rc; | ||
383 | } | ||
384 | |||
385 | static int __wil_down(struct wil6210_priv *wil) | ||
386 | { | ||
387 | if (wil->scan_request) { | ||
388 | cfg80211_scan_done(wil->scan_request, true); | ||
389 | wil->scan_request = NULL; | ||
390 | } | ||
391 | |||
392 | wil6210_disconnect(wil, NULL); | ||
393 | wil_rx_fini(wil); | ||
394 | |||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | int wil_down(struct wil6210_priv *wil) | ||
399 | { | ||
400 | int rc; | ||
401 | |||
402 | mutex_lock(&wil->mutex); | ||
403 | rc = __wil_down(wil); | ||
404 | mutex_unlock(&wil->mutex); | ||
405 | |||
406 | return rc; | ||
407 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c new file mode 100644 index 000000000000..3068b5cb53a7 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/slab.h> | ||
21 | |||
22 | #include "wil6210.h" | ||
23 | |||
24 | static int wil_open(struct net_device *ndev) | ||
25 | { | ||
26 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
27 | |||
28 | return wil_up(wil); | ||
29 | } | ||
30 | |||
31 | static int wil_stop(struct net_device *ndev) | ||
32 | { | ||
33 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
34 | |||
35 | return wil_down(wil); | ||
36 | } | ||
37 | |||
38 | /* | ||
39 | * AC to queue mapping | ||
40 | * | ||
41 | * AC_VO -> queue 3 | ||
42 | * AC_VI -> queue 2 | ||
43 | * AC_BE -> queue 1 | ||
44 | * AC_BK -> queue 0 | ||
45 | */ | ||
46 | static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb) | ||
47 | { | ||
48 | static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; | ||
49 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
50 | u16 rc; | ||
51 | |||
52 | skb->priority = cfg80211_classify8021d(skb); | ||
53 | |||
54 | rc = wil_1d_to_queue[skb->priority]; | ||
55 | |||
56 | wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority, | ||
57 | (int)rc); | ||
58 | |||
59 | return rc; | ||
60 | } | ||
61 | |||
62 | static const struct net_device_ops wil_netdev_ops = { | ||
63 | .ndo_open = wil_open, | ||
64 | .ndo_stop = wil_stop, | ||
65 | .ndo_start_xmit = wil_start_xmit, | ||
66 | .ndo_select_queue = wil_select_queue, | ||
67 | .ndo_set_mac_address = eth_mac_addr, | ||
68 | .ndo_validate_addr = eth_validate_addr, | ||
69 | }; | ||
70 | |||
71 | void *wil_if_alloc(struct device *dev, void __iomem *csr) | ||
72 | { | ||
73 | struct net_device *ndev; | ||
74 | struct wireless_dev *wdev; | ||
75 | struct wil6210_priv *wil; | ||
76 | struct ieee80211_channel *ch; | ||
77 | int rc = 0; | ||
78 | |||
79 | wdev = wil_cfg80211_init(dev); | ||
80 | if (IS_ERR(wdev)) { | ||
81 | dev_err(dev, "wil_cfg80211_init failed\n"); | ||
82 | return wdev; | ||
83 | } | ||
84 | |||
85 | wil = wdev_to_wil(wdev); | ||
86 | wil->csr = csr; | ||
87 | wil->wdev = wdev; | ||
88 | |||
89 | rc = wil_priv_init(wil); | ||
90 | if (rc) { | ||
91 | dev_err(dev, "wil_priv_init failed\n"); | ||
92 | goto out_wdev; | ||
93 | } | ||
94 | |||
95 | wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */ | ||
96 | /* default monitor channel */ | ||
97 | ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels; | ||
98 | cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT); | ||
99 | |||
100 | ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1); | ||
101 | if (!ndev) { | ||
102 | dev_err(dev, "alloc_netdev_mqs failed\n"); | ||
103 | rc = -ENOMEM; | ||
104 | goto out_priv; | ||
105 | } | ||
106 | |||
107 | ndev->netdev_ops = &wil_netdev_ops; | ||
108 | ndev->ieee80211_ptr = wdev; | ||
109 | SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); | ||
110 | wdev->netdev = ndev; | ||
111 | |||
112 | wil_link_off(wil); | ||
113 | |||
114 | return wil; | ||
115 | |||
116 | out_priv: | ||
117 | wil_priv_deinit(wil); | ||
118 | |||
119 | out_wdev: | ||
120 | wil_wdev_free(wil); | ||
121 | |||
122 | return ERR_PTR(rc); | ||
123 | } | ||
124 | |||
125 | void wil_if_free(struct wil6210_priv *wil) | ||
126 | { | ||
127 | struct net_device *ndev = wil_to_ndev(wil); | ||
128 | if (!ndev) | ||
129 | return; | ||
130 | |||
131 | free_netdev(ndev); | ||
132 | wil_priv_deinit(wil); | ||
133 | wil_wdev_free(wil); | ||
134 | } | ||
135 | |||
136 | int wil_if_add(struct wil6210_priv *wil) | ||
137 | { | ||
138 | struct net_device *ndev = wil_to_ndev(wil); | ||
139 | int rc; | ||
140 | |||
141 | rc = register_netdev(ndev); | ||
142 | if (rc < 0) { | ||
143 | dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc); | ||
144 | return rc; | ||
145 | } | ||
146 | |||
147 | wil_link_off(wil); | ||
148 | |||
149 | return 0; | ||
150 | } | ||
151 | |||
152 | void wil_if_remove(struct wil6210_priv *wil) | ||
153 | { | ||
154 | struct net_device *ndev = wil_to_ndev(wil); | ||
155 | |||
156 | unregister_netdev(ndev); | ||
157 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c new file mode 100644 index 000000000000..0fc83edd6bad --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c | |||
@@ -0,0 +1,223 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/debugfs.h> | ||
22 | #include <linux/pci.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | |||
25 | #include "wil6210.h" | ||
26 | |||
27 | static int use_msi = 1; | ||
28 | module_param(use_msi, int, S_IRUGO); | ||
29 | MODULE_PARM_DESC(use_msi, | ||
30 | " Use MSI interrupt: " | ||
31 | "0 - don't, 1 - (default) - single, or 3"); | ||
32 | |||
33 | /* Bus ops */ | ||
34 | static int wil_if_pcie_enable(struct wil6210_priv *wil) | ||
35 | { | ||
36 | struct pci_dev *pdev = wil->pdev; | ||
37 | int rc; | ||
38 | |||
39 | pci_set_master(pdev); | ||
40 | |||
41 | /* | ||
42 | * how many MSI interrupts to request? | ||
43 | */ | ||
44 | switch (use_msi) { | ||
45 | case 3: | ||
46 | case 1: | ||
47 | case 0: | ||
48 | break; | ||
49 | default: | ||
50 | wil_err(wil, "Invalid use_msi=%d, default to 1\n", | ||
51 | use_msi); | ||
52 | use_msi = 1; | ||
53 | } | ||
54 | wil->n_msi = use_msi; | ||
55 | if (wil->n_msi) { | ||
56 | wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi); | ||
57 | rc = pci_enable_msi_block(pdev, wil->n_msi); | ||
58 | if (rc && (wil->n_msi == 3)) { | ||
59 | wil_err(wil, "3 MSI mode failed, try 1 MSI\n"); | ||
60 | wil->n_msi = 1; | ||
61 | rc = pci_enable_msi_block(pdev, wil->n_msi); | ||
62 | } | ||
63 | if (rc) { | ||
64 | wil_err(wil, "pci_enable_msi failed, use INTx\n"); | ||
65 | wil->n_msi = 0; | ||
66 | } | ||
67 | } else { | ||
68 | wil_dbg(wil, "MSI interrupts disabled, use INTx\n"); | ||
69 | } | ||
70 | |||
71 | rc = wil6210_init_irq(wil, pdev->irq); | ||
72 | if (rc) | ||
73 | goto stop_master; | ||
74 | |||
75 | /* need reset here to obtain MAC */ | ||
76 | rc = wil_reset(wil); | ||
77 | if (rc) | ||
78 | goto release_irq; | ||
79 | |||
80 | return 0; | ||
81 | |||
82 | release_irq: | ||
83 | wil6210_fini_irq(wil, pdev->irq); | ||
84 | /* safe to call if no MSI */ | ||
85 | pci_disable_msi(pdev); | ||
86 | stop_master: | ||
87 | pci_clear_master(pdev); | ||
88 | return rc; | ||
89 | } | ||
90 | |||
91 | static int wil_if_pcie_disable(struct wil6210_priv *wil) | ||
92 | { | ||
93 | struct pci_dev *pdev = wil->pdev; | ||
94 | |||
95 | pci_clear_master(pdev); | ||
96 | /* disable and release IRQ */ | ||
97 | wil6210_fini_irq(wil, pdev->irq); | ||
98 | /* safe to call if no MSI */ | ||
99 | pci_disable_msi(pdev); | ||
100 | /* TODO: disable HW */ | ||
101 | |||
102 | return 0; | ||
103 | } | ||
104 | |||
105 | static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id) | ||
106 | { | ||
107 | struct wil6210_priv *wil; | ||
108 | struct device *dev = &pdev->dev; | ||
109 | void __iomem *csr; | ||
110 | int rc; | ||
111 | |||
112 | /* check HW */ | ||
113 | dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n", | ||
114 | (int)pdev->vendor, (int)pdev->device, (int)pdev->revision); | ||
115 | |||
116 | if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) { | ||
117 | dev_err(&pdev->dev, "Not " WIL_NAME "? " | ||
118 | "BAR0 size is %lu while expecting %lu\n", | ||
119 | (ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE); | ||
120 | return -ENODEV; | ||
121 | } | ||
122 | |||
123 | rc = pci_enable_device(pdev); | ||
124 | if (rc) { | ||
125 | dev_err(&pdev->dev, "pci_enable_device failed\n"); | ||
126 | return -ENODEV; | ||
127 | } | ||
128 | /* rollback to err_disable_pdev */ | ||
129 | |||
130 | rc = pci_request_region(pdev, 0, WIL_NAME); | ||
131 | if (rc) { | ||
132 | dev_err(&pdev->dev, "pci_request_region failed\n"); | ||
133 | goto err_disable_pdev; | ||
134 | } | ||
135 | /* rollback to err_release_reg */ | ||
136 | |||
137 | csr = pci_ioremap_bar(pdev, 0); | ||
138 | if (!csr) { | ||
139 | dev_err(&pdev->dev, "pci_ioremap_bar failed\n"); | ||
140 | rc = -ENODEV; | ||
141 | goto err_release_reg; | ||
142 | } | ||
143 | /* rollback to err_iounmap */ | ||
144 | dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr); | ||
145 | |||
146 | wil = wil_if_alloc(dev, csr); | ||
147 | if (IS_ERR(wil)) { | ||
148 | rc = (int)PTR_ERR(wil); | ||
149 | dev_err(dev, "wil_if_alloc failed: %d\n", rc); | ||
150 | goto err_iounmap; | ||
151 | } | ||
152 | /* rollback to if_free */ | ||
153 | |||
154 | pci_set_drvdata(pdev, wil); | ||
155 | wil->pdev = pdev; | ||
156 | |||
157 | /* FW should raise IRQ when ready */ | ||
158 | rc = wil_if_pcie_enable(wil); | ||
159 | if (rc) { | ||
160 | wil_err(wil, "Enable device failed\n"); | ||
161 | goto if_free; | ||
162 | } | ||
163 | /* rollback to bus_disable */ | ||
164 | |||
165 | rc = wil_if_add(wil); | ||
166 | if (rc) { | ||
167 | wil_err(wil, "wil_if_add failed: %d\n", rc); | ||
168 | goto bus_disable; | ||
169 | } | ||
170 | |||
171 | wil6210_debugfs_init(wil); | ||
172 | |||
173 | /* check FW is alive */ | ||
174 | wmi_echo(wil); | ||
175 | |||
176 | return 0; | ||
177 | |||
178 | bus_disable: | ||
179 | wil_if_pcie_disable(wil); | ||
180 | if_free: | ||
181 | wil_if_free(wil); | ||
182 | err_iounmap: | ||
183 | pci_iounmap(pdev, csr); | ||
184 | err_release_reg: | ||
185 | pci_release_region(pdev, 0); | ||
186 | err_disable_pdev: | ||
187 | pci_disable_device(pdev); | ||
188 | |||
189 | return rc; | ||
190 | } | ||
191 | |||
192 | static void wil_pcie_remove(struct pci_dev *pdev) | ||
193 | { | ||
194 | struct wil6210_priv *wil = pci_get_drvdata(pdev); | ||
195 | |||
196 | wil6210_debugfs_remove(wil); | ||
197 | wil_if_pcie_disable(wil); | ||
198 | wil_if_remove(wil); | ||
199 | wil_if_free(wil); | ||
200 | pci_iounmap(pdev, wil->csr); | ||
201 | pci_release_region(pdev, 0); | ||
202 | pci_disable_device(pdev); | ||
203 | pci_set_drvdata(pdev, NULL); | ||
204 | } | ||
205 | |||
206 | static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = { | ||
207 | { PCI_DEVICE(0x1ae9, 0x0301) }, | ||
208 | { /* end: all zeroes */ }, | ||
209 | }; | ||
210 | MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids); | ||
211 | |||
212 | static struct pci_driver wil6210_driver = { | ||
213 | .probe = wil_pcie_probe, | ||
214 | .remove = wil_pcie_remove, | ||
215 | .id_table = wil6210_pcie_ids, | ||
216 | .name = WIL_NAME, | ||
217 | }; | ||
218 | |||
219 | module_pci_driver(wil6210_driver); | ||
220 | |||
221 | MODULE_LICENSE("Dual BSD/GPL"); | ||
222 | MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>"); | ||
223 | MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card"); | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c new file mode 100644 index 000000000000..f29c294413cf --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -0,0 +1,871 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/netdevice.h> | ||
19 | #include <linux/etherdevice.h> | ||
20 | #include <linux/hardirq.h> | ||
21 | #include <net/ieee80211_radiotap.h> | ||
22 | #include <linux/if_arp.h> | ||
23 | #include <linux/moduleparam.h> | ||
24 | |||
25 | #include "wil6210.h" | ||
26 | #include "wmi.h" | ||
27 | #include "txrx.h" | ||
28 | |||
29 | static bool rtap_include_phy_info; | ||
30 | module_param(rtap_include_phy_info, bool, S_IRUGO); | ||
31 | MODULE_PARM_DESC(rtap_include_phy_info, | ||
32 | " Include PHY info in the radiotap header, default - no"); | ||
33 | |||
34 | static inline int wil_vring_is_empty(struct vring *vring) | ||
35 | { | ||
36 | return vring->swhead == vring->swtail; | ||
37 | } | ||
38 | |||
39 | static inline u32 wil_vring_next_tail(struct vring *vring) | ||
40 | { | ||
41 | return (vring->swtail + 1) % vring->size; | ||
42 | } | ||
43 | |||
44 | static inline void wil_vring_advance_head(struct vring *vring, int n) | ||
45 | { | ||
46 | vring->swhead = (vring->swhead + n) % vring->size; | ||
47 | } | ||
48 | |||
49 | static inline int wil_vring_is_full(struct vring *vring) | ||
50 | { | ||
51 | return wil_vring_next_tail(vring) == vring->swhead; | ||
52 | } | ||
53 | /* | ||
54 | * Available space in Tx Vring | ||
55 | */ | ||
56 | static inline int wil_vring_avail_tx(struct vring *vring) | ||
57 | { | ||
58 | u32 swhead = vring->swhead; | ||
59 | u32 swtail = vring->swtail; | ||
60 | int used = (vring->size + swhead - swtail) % vring->size; | ||
61 | |||
62 | return vring->size - used - 1; | ||
63 | } | ||
64 | |||
65 | static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring) | ||
66 | { | ||
67 | struct device *dev = wil_to_dev(wil); | ||
68 | size_t sz = vring->size * sizeof(vring->va[0]); | ||
69 | uint i; | ||
70 | |||
71 | BUILD_BUG_ON(sizeof(vring->va[0]) != 32); | ||
72 | |||
73 | vring->swhead = 0; | ||
74 | vring->swtail = 0; | ||
75 | vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL); | ||
76 | if (!vring->ctx) { | ||
77 | wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n", | ||
78 | vring->size); | ||
79 | vring->va = NULL; | ||
80 | return -ENOMEM; | ||
81 | } | ||
82 | /* | ||
83 | * vring->va should be aligned on its size rounded up to power of 2 | ||
84 | * This is granted by the dma_alloc_coherent | ||
85 | */ | ||
86 | vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL); | ||
87 | if (!vring->va) { | ||
88 | wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n", | ||
89 | vring->size); | ||
90 | kfree(vring->ctx); | ||
91 | vring->ctx = NULL; | ||
92 | return -ENOMEM; | ||
93 | } | ||
94 | /* initially, all descriptors are SW owned | ||
95 | * For Tx and Rx, ownership bit is at the same location, thus | ||
96 | * we can use any | ||
97 | */ | ||
98 | for (i = 0; i < vring->size; i++) { | ||
99 | volatile struct vring_tx_desc *d = &(vring->va[i].tx); | ||
100 | d->dma.status = TX_DMA_STATUS_DU; | ||
101 | } | ||
102 | |||
103 | wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size, | ||
104 | vring->va, (unsigned long long)vring->pa, vring->ctx); | ||
105 | |||
106 | return 0; | ||
107 | } | ||
108 | |||
109 | static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring, | ||
110 | int tx) | ||
111 | { | ||
112 | struct device *dev = wil_to_dev(wil); | ||
113 | size_t sz = vring->size * sizeof(vring->va[0]); | ||
114 | |||
115 | while (!wil_vring_is_empty(vring)) { | ||
116 | if (tx) { | ||
117 | volatile struct vring_tx_desc *d = | ||
118 | &vring->va[vring->swtail].tx; | ||
119 | dma_addr_t pa = d->dma.addr_low | | ||
120 | ((u64)d->dma.addr_high << 32); | ||
121 | struct sk_buff *skb = vring->ctx[vring->swtail]; | ||
122 | if (skb) { | ||
123 | dma_unmap_single(dev, pa, d->dma.length, | ||
124 | DMA_TO_DEVICE); | ||
125 | dev_kfree_skb_any(skb); | ||
126 | vring->ctx[vring->swtail] = NULL; | ||
127 | } else { | ||
128 | dma_unmap_page(dev, pa, d->dma.length, | ||
129 | DMA_TO_DEVICE); | ||
130 | } | ||
131 | vring->swtail = wil_vring_next_tail(vring); | ||
132 | } else { /* rx */ | ||
133 | volatile struct vring_rx_desc *d = | ||
134 | &vring->va[vring->swtail].rx; | ||
135 | dma_addr_t pa = d->dma.addr_low | | ||
136 | ((u64)d->dma.addr_high << 32); | ||
137 | struct sk_buff *skb = vring->ctx[vring->swhead]; | ||
138 | dma_unmap_single(dev, pa, d->dma.length, | ||
139 | DMA_FROM_DEVICE); | ||
140 | kfree_skb(skb); | ||
141 | wil_vring_advance_head(vring, 1); | ||
142 | } | ||
143 | } | ||
144 | dma_free_coherent(dev, sz, (void *)vring->va, vring->pa); | ||
145 | kfree(vring->ctx); | ||
146 | vring->pa = 0; | ||
147 | vring->va = NULL; | ||
148 | vring->ctx = NULL; | ||
149 | } | ||
150 | |||
151 | /** | ||
152 | * Allocate one skb for Rx VRING | ||
153 | * | ||
154 | * Safe to call from IRQ | ||
155 | */ | ||
156 | static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, | ||
157 | u32 i, int headroom) | ||
158 | { | ||
159 | struct device *dev = wil_to_dev(wil); | ||
160 | unsigned int sz = RX_BUF_LEN; | ||
161 | volatile struct vring_rx_desc *d = &(vring->va[i].rx); | ||
162 | dma_addr_t pa; | ||
163 | |||
164 | /* TODO align */ | ||
165 | struct sk_buff *skb = dev_alloc_skb(sz + headroom); | ||
166 | if (unlikely(!skb)) | ||
167 | return -ENOMEM; | ||
168 | |||
169 | skb_reserve(skb, headroom); | ||
170 | skb_put(skb, sz); | ||
171 | |||
172 | pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE); | ||
173 | if (unlikely(dma_mapping_error(dev, pa))) { | ||
174 | kfree_skb(skb); | ||
175 | return -ENOMEM; | ||
176 | } | ||
177 | |||
178 | d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT; | ||
179 | d->dma.addr_low = lower_32_bits(pa); | ||
180 | d->dma.addr_high = (u16)upper_32_bits(pa); | ||
181 | /* ip_length don't care */ | ||
182 | /* b11 don't care */ | ||
183 | /* error don't care */ | ||
184 | d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ | ||
185 | d->dma.length = sz; | ||
186 | vring->ctx[i] = skb; | ||
187 | |||
188 | return 0; | ||
189 | } | ||
190 | |||
191 | /** | ||
192 | * Adds radiotap header | ||
193 | * | ||
194 | * Any error indicated as "Bad FCS" | ||
195 | * | ||
196 | * Vendor data for 04:ce:14-1 (Wilocity-1) consists of: | ||
197 | * - Rx descriptor: 32 bytes | ||
198 | * - Phy info | ||
199 | */ | ||
200 | static void wil_rx_add_radiotap_header(struct wil6210_priv *wil, | ||
201 | struct sk_buff *skb, | ||
202 | volatile struct vring_rx_desc *d) | ||
203 | { | ||
204 | struct wireless_dev *wdev = wil->wdev; | ||
205 | struct wil6210_rtap { | ||
206 | struct ieee80211_radiotap_header rthdr; | ||
207 | /* fields should be in the order of bits in rthdr.it_present */ | ||
208 | /* flags */ | ||
209 | u8 flags; | ||
210 | /* channel */ | ||
211 | __le16 chnl_freq __aligned(2); | ||
212 | __le16 chnl_flags; | ||
213 | /* MCS */ | ||
214 | u8 mcs_present; | ||
215 | u8 mcs_flags; | ||
216 | u8 mcs_index; | ||
217 | } __packed; | ||
218 | struct wil6210_rtap_vendor { | ||
219 | struct wil6210_rtap rtap; | ||
220 | /* vendor */ | ||
221 | u8 vendor_oui[3] __aligned(2); | ||
222 | u8 vendor_ns; | ||
223 | __le16 vendor_skip; | ||
224 | u8 vendor_data[0]; | ||
225 | } __packed; | ||
226 | struct wil6210_rtap_vendor *rtap_vendor; | ||
227 | int rtap_len = sizeof(struct wil6210_rtap); | ||
228 | int phy_length = 0; /* phy info header size, bytes */ | ||
229 | static char phy_data[128]; | ||
230 | struct ieee80211_channel *ch = wdev->preset_chandef.chan; | ||
231 | |||
232 | if (rtap_include_phy_info) { | ||
233 | rtap_len = sizeof(*rtap_vendor) + sizeof(*d); | ||
234 | /* calculate additional length */ | ||
235 | if (d->dma.status & RX_DMA_STATUS_PHY_INFO) { | ||
236 | /** | ||
237 | * PHY info starts from 8-byte boundary | ||
238 | * there are 8-byte lines, last line may be partially | ||
239 | * written (HW bug), thus FW configures for last line | ||
240 | * to be excessive. Driver skips this last line. | ||
241 | */ | ||
242 | int len = min_t(int, 8 + sizeof(phy_data), | ||
243 | wil_rxdesc_phy_length(d)); | ||
244 | if (len > 8) { | ||
245 | void *p = skb_tail_pointer(skb); | ||
246 | void *pa = PTR_ALIGN(p, 8); | ||
247 | if (skb_tailroom(skb) >= len + (pa - p)) { | ||
248 | phy_length = len - 8; | ||
249 | memcpy(phy_data, pa, phy_length); | ||
250 | } | ||
251 | } | ||
252 | } | ||
253 | rtap_len += phy_length; | ||
254 | } | ||
255 | |||
256 | if (skb_headroom(skb) < rtap_len && | ||
257 | pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) { | ||
258 | wil_err(wil, "Unable to expand headrom to %d\n", rtap_len); | ||
259 | return; | ||
260 | } | ||
261 | |||
262 | rtap_vendor = (void *)skb_push(skb, rtap_len); | ||
263 | memset(rtap_vendor, 0, rtap_len); | ||
264 | |||
265 | rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION; | ||
266 | rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len); | ||
267 | rtap_vendor->rtap.rthdr.it_present = cpu_to_le32( | ||
268 | (1 << IEEE80211_RADIOTAP_FLAGS) | | ||
269 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | ||
270 | (1 << IEEE80211_RADIOTAP_MCS)); | ||
271 | if (d->dma.status & RX_DMA_STATUS_ERROR) | ||
272 | rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS; | ||
273 | |||
274 | rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320); | ||
275 | rtap_vendor->rtap.chnl_flags = cpu_to_le16(0); | ||
276 | |||
277 | rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS; | ||
278 | rtap_vendor->rtap.mcs_flags = 0; | ||
279 | rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d); | ||
280 | |||
281 | if (rtap_include_phy_info) { | ||
282 | rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 << | ||
283 | IEEE80211_RADIOTAP_VENDOR_NAMESPACE); | ||
284 | /* OUI for Wilocity 04:ce:14 */ | ||
285 | rtap_vendor->vendor_oui[0] = 0x04; | ||
286 | rtap_vendor->vendor_oui[1] = 0xce; | ||
287 | rtap_vendor->vendor_oui[2] = 0x14; | ||
288 | rtap_vendor->vendor_ns = 1; | ||
289 | /* Rx descriptor + PHY data */ | ||
290 | rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) + | ||
291 | phy_length); | ||
292 | memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d)); | ||
293 | memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data, | ||
294 | phy_length); | ||
295 | } | ||
296 | } | ||
297 | |||
298 | /* | ||
299 | * Fast swap in place between 2 registers | ||
300 | */ | ||
301 | static void wil_swap_u16(u16 *a, u16 *b) | ||
302 | { | ||
303 | *a ^= *b; | ||
304 | *b ^= *a; | ||
305 | *a ^= *b; | ||
306 | } | ||
307 | |||
308 | static void wil_swap_ethaddr(void *data) | ||
309 | { | ||
310 | struct ethhdr *eth = data; | ||
311 | u16 *s = (u16 *)eth->h_source; | ||
312 | u16 *d = (u16 *)eth->h_dest; | ||
313 | |||
314 | wil_swap_u16(s++, d++); | ||
315 | wil_swap_u16(s++, d++); | ||
316 | wil_swap_u16(s, d); | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * reap 1 frame from @swhead | ||
321 | * | ||
322 | * Safe to call from IRQ | ||
323 | */ | ||
324 | static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | ||
325 | struct vring *vring) | ||
326 | { | ||
327 | struct device *dev = wil_to_dev(wil); | ||
328 | struct net_device *ndev = wil_to_ndev(wil); | ||
329 | volatile struct vring_rx_desc *d; | ||
330 | struct sk_buff *skb; | ||
331 | dma_addr_t pa; | ||
332 | unsigned int sz = RX_BUF_LEN; | ||
333 | u8 ftype; | ||
334 | u8 ds_bits; | ||
335 | |||
336 | if (wil_vring_is_empty(vring)) | ||
337 | return NULL; | ||
338 | |||
339 | d = &(vring->va[vring->swhead].rx); | ||
340 | if (!(d->dma.status & RX_DMA_STATUS_DU)) { | ||
341 | /* it is not error, we just reached end of Rx done area */ | ||
342 | return NULL; | ||
343 | } | ||
344 | |||
345 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
346 | skb = vring->ctx[vring->swhead]; | ||
347 | dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE); | ||
348 | skb_trim(skb, d->dma.length); | ||
349 | |||
350 | wil->stats.last_mcs_rx = wil_rxdesc_mcs(d); | ||
351 | |||
352 | /* use radiotap header only if required */ | ||
353 | if (ndev->type == ARPHRD_IEEE80211_RADIOTAP) | ||
354 | wil_rx_add_radiotap_header(wil, skb, d); | ||
355 | |||
356 | wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length); | ||
357 | wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4, | ||
358 | (const void *)d, sizeof(*d), false); | ||
359 | |||
360 | wil_vring_advance_head(vring, 1); | ||
361 | |||
362 | /* no extra checks if in sniffer mode */ | ||
363 | if (ndev->type != ARPHRD_ETHER) | ||
364 | return skb; | ||
365 | /* | ||
366 | * Non-data frames may be delivered through Rx DMA channel (ex: BAR) | ||
367 | * Driver should recognize it by frame type, that is found | ||
368 | * in Rx descriptor. If type is not data, it is 802.11 frame as is | ||
369 | */ | ||
370 | ftype = wil_rxdesc_ftype(d) << 2; | ||
371 | if (ftype != IEEE80211_FTYPE_DATA) { | ||
372 | wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype); | ||
373 | /* TODO: process it */ | ||
374 | kfree_skb(skb); | ||
375 | return NULL; | ||
376 | } | ||
377 | |||
378 | if (skb->len < ETH_HLEN) { | ||
379 | wil_err(wil, "Short frame, len = %d\n", skb->len); | ||
380 | /* TODO: process it (i.e. BAR) */ | ||
381 | kfree_skb(skb); | ||
382 | return NULL; | ||
383 | } | ||
384 | |||
385 | ds_bits = wil_rxdesc_ds_bits(d); | ||
386 | if (ds_bits == 1) { | ||
387 | /* | ||
388 | * HW bug - in ToDS mode, i.e. Rx on AP side, | ||
389 | * addresses get swapped | ||
390 | */ | ||
391 | wil_swap_ethaddr(skb->data); | ||
392 | } | ||
393 | |||
394 | return skb; | ||
395 | } | ||
396 | |||
397 | /** | ||
398 | * allocate and fill up to @count buffers in rx ring | ||
399 | * buffers posted at @swtail | ||
400 | */ | ||
401 | static int wil_rx_refill(struct wil6210_priv *wil, int count) | ||
402 | { | ||
403 | struct net_device *ndev = wil_to_ndev(wil); | ||
404 | struct vring *v = &wil->vring_rx; | ||
405 | u32 next_tail; | ||
406 | int rc = 0; | ||
407 | int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ? | ||
408 | WIL6210_RTAP_SIZE : 0; | ||
409 | |||
410 | for (; next_tail = wil_vring_next_tail(v), | ||
411 | (next_tail != v->swhead) && (count-- > 0); | ||
412 | v->swtail = next_tail) { | ||
413 | rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom); | ||
414 | if (rc) { | ||
415 | wil_err(wil, "Error %d in wil_rx_refill[%d]\n", | ||
416 | rc, v->swtail); | ||
417 | break; | ||
418 | } | ||
419 | } | ||
420 | iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail)); | ||
421 | |||
422 | return rc; | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * Pass Rx packet to the netif. Update statistics. | ||
427 | */ | ||
428 | static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev) | ||
429 | { | ||
430 | int rc; | ||
431 | unsigned int len = skb->len; | ||
432 | |||
433 | if (in_interrupt()) | ||
434 | rc = netif_rx(skb); | ||
435 | else | ||
436 | rc = netif_rx_ni(skb); | ||
437 | |||
438 | if (likely(rc == NET_RX_SUCCESS)) { | ||
439 | ndev->stats.rx_packets++; | ||
440 | ndev->stats.rx_bytes += len; | ||
441 | |||
442 | } else { | ||
443 | ndev->stats.rx_dropped++; | ||
444 | } | ||
445 | } | ||
446 | |||
447 | /** | ||
448 | * Proceed all completed skb's from Rx VRING | ||
449 | * | ||
450 | * Safe to call from IRQ | ||
451 | */ | ||
452 | void wil_rx_handle(struct wil6210_priv *wil) | ||
453 | { | ||
454 | struct net_device *ndev = wil_to_ndev(wil); | ||
455 | struct vring *v = &wil->vring_rx; | ||
456 | struct sk_buff *skb; | ||
457 | |||
458 | if (!v->va) { | ||
459 | wil_err(wil, "Rx IRQ while Rx not yet initialized\n"); | ||
460 | return; | ||
461 | } | ||
462 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
463 | while (NULL != (skb = wil_vring_reap_rx(wil, v))) { | ||
464 | wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1, | ||
465 | skb->data, skb_headlen(skb), false); | ||
466 | |||
467 | skb_orphan(skb); | ||
468 | |||
469 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
470 | skb->dev = ndev; | ||
471 | skb_reset_mac_header(skb); | ||
472 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
473 | skb->pkt_type = PACKET_OTHERHOST; | ||
474 | skb->protocol = htons(ETH_P_802_2); | ||
475 | |||
476 | } else { | ||
477 | skb->protocol = eth_type_trans(skb, ndev); | ||
478 | } | ||
479 | |||
480 | wil_netif_rx_any(skb, ndev); | ||
481 | } | ||
482 | wil_rx_refill(wil, v->size); | ||
483 | } | ||
484 | |||
485 | int wil_rx_init(struct wil6210_priv *wil) | ||
486 | { | ||
487 | struct net_device *ndev = wil_to_ndev(wil); | ||
488 | struct wireless_dev *wdev = wil->wdev; | ||
489 | struct vring *vring = &wil->vring_rx; | ||
490 | int rc; | ||
491 | struct wmi_cfg_rx_chain_cmd cmd = { | ||
492 | .action = WMI_RX_CHAIN_ADD, | ||
493 | .rx_sw_ring = { | ||
494 | .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), | ||
495 | }, | ||
496 | .mid = 0, /* TODO - what is it? */ | ||
497 | .decap_trans_type = WMI_DECAP_TYPE_802_3, | ||
498 | }; | ||
499 | struct { | ||
500 | struct wil6210_mbox_hdr_wmi wmi; | ||
501 | struct wmi_cfg_rx_chain_done_event evt; | ||
502 | } __packed evt; | ||
503 | |||
504 | vring->size = WIL6210_RX_RING_SIZE; | ||
505 | rc = wil_vring_alloc(wil, vring); | ||
506 | if (rc) | ||
507 | return rc; | ||
508 | |||
509 | cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | ||
510 | cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size); | ||
511 | if (wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
512 | struct ieee80211_channel *ch = wdev->preset_chandef.chan; | ||
513 | |||
514 | cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON); | ||
515 | if (ch) | ||
516 | cmd.sniffer_cfg.channel = ch->hw_value - 1; | ||
517 | cmd.sniffer_cfg.phy_info_mode = | ||
518 | cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP); | ||
519 | cmd.sniffer_cfg.phy_support = | ||
520 | cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL) | ||
521 | ? WMI_SNIFFER_CP : WMI_SNIFFER_DP); | ||
522 | } | ||
523 | /* typical time for secure PCP is 840ms */ | ||
524 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | ||
525 | WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000); | ||
526 | if (rc) | ||
527 | goto err_free; | ||
528 | |||
529 | vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr); | ||
530 | |||
531 | wil_dbg(wil, "Rx init: status %d tail 0x%08x\n", | ||
532 | le32_to_cpu(evt.evt.status), vring->hwtail); | ||
533 | |||
534 | rc = wil_rx_refill(wil, vring->size); | ||
535 | if (rc) | ||
536 | goto err_free; | ||
537 | |||
538 | return 0; | ||
539 | err_free: | ||
540 | wil_vring_free(wil, vring, 0); | ||
541 | |||
542 | return rc; | ||
543 | } | ||
544 | |||
545 | void wil_rx_fini(struct wil6210_priv *wil) | ||
546 | { | ||
547 | struct vring *vring = &wil->vring_rx; | ||
548 | |||
549 | if (vring->va) { | ||
550 | int rc; | ||
551 | struct wmi_cfg_rx_chain_cmd cmd = { | ||
552 | .action = cpu_to_le32(WMI_RX_CHAIN_DEL), | ||
553 | .rx_sw_ring = { | ||
554 | .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), | ||
555 | }, | ||
556 | }; | ||
557 | struct { | ||
558 | struct wil6210_mbox_hdr_wmi wmi; | ||
559 | struct wmi_cfg_rx_chain_done_event cfg; | ||
560 | } __packed wmi_rx_cfg_reply; | ||
561 | |||
562 | rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd), | ||
563 | WMI_CFG_RX_CHAIN_DONE_EVENTID, | ||
564 | &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply), | ||
565 | 100); | ||
566 | wil_vring_free(wil, vring, 0); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | ||
571 | int cid, int tid) | ||
572 | { | ||
573 | int rc; | ||
574 | struct wmi_vring_cfg_cmd cmd = { | ||
575 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), | ||
576 | .vring_cfg = { | ||
577 | .tx_sw_ring = { | ||
578 | .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), | ||
579 | }, | ||
580 | .ringid = id, | ||
581 | .cidxtid = (cid & 0xf) | ((tid & 0xf) << 4), | ||
582 | .encap_trans_type = WMI_VRING_ENC_TYPE_802_3, | ||
583 | .mac_ctrl = 0, | ||
584 | .to_resolution = 0, | ||
585 | .agg_max_wsize = 16, | ||
586 | .schd_params = { | ||
587 | .priority = cpu_to_le16(0), | ||
588 | .timeslot_us = cpu_to_le16(0xfff), | ||
589 | }, | ||
590 | }, | ||
591 | }; | ||
592 | struct { | ||
593 | struct wil6210_mbox_hdr_wmi wmi; | ||
594 | struct wmi_vring_cfg_done_event cmd; | ||
595 | } __packed reply; | ||
596 | struct vring *vring = &wil->vring_tx[id]; | ||
597 | |||
598 | if (vring->va) { | ||
599 | wil_err(wil, "Tx ring [%d] already allocated\n", id); | ||
600 | rc = -EINVAL; | ||
601 | goto out; | ||
602 | } | ||
603 | |||
604 | vring->size = size; | ||
605 | rc = wil_vring_alloc(wil, vring); | ||
606 | if (rc) | ||
607 | goto out; | ||
608 | |||
609 | cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa); | ||
610 | cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size); | ||
611 | |||
612 | rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd), | ||
613 | WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100); | ||
614 | if (rc) | ||
615 | goto out_free; | ||
616 | |||
617 | if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) { | ||
618 | wil_err(wil, "Tx config failed, status 0x%02x\n", | ||
619 | reply.cmd.status); | ||
620 | goto out_free; | ||
621 | } | ||
622 | vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr); | ||
623 | |||
624 | return 0; | ||
625 | out_free: | ||
626 | wil_vring_free(wil, vring, 1); | ||
627 | out: | ||
628 | |||
629 | return rc; | ||
630 | } | ||
631 | |||
632 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id) | ||
633 | { | ||
634 | struct vring *vring = &wil->vring_tx[id]; | ||
635 | |||
636 | if (!vring->va) | ||
637 | return; | ||
638 | |||
639 | wil_vring_free(wil, vring, 1); | ||
640 | } | ||
641 | |||
642 | static struct vring *wil_find_tx_vring(struct wil6210_priv *wil, | ||
643 | struct sk_buff *skb) | ||
644 | { | ||
645 | struct vring *v = &wil->vring_tx[0]; | ||
646 | |||
647 | if (v->va) | ||
648 | return v; | ||
649 | |||
650 | return NULL; | ||
651 | } | ||
652 | |||
653 | static int wil_tx_desc_map(volatile struct vring_tx_desc *d, | ||
654 | dma_addr_t pa, u32 len) | ||
655 | { | ||
656 | d->dma.addr_low = lower_32_bits(pa); | ||
657 | d->dma.addr_high = (u16)upper_32_bits(pa); | ||
658 | d->dma.ip_length = 0; | ||
659 | /* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/ | ||
660 | d->dma.b11 = 0/*14 | BIT(7)*/; | ||
661 | d->dma.error = 0; | ||
662 | d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */ | ||
663 | d->dma.length = len; | ||
664 | d->dma.d0 = 0; | ||
665 | d->mac.d[0] = 0; | ||
666 | d->mac.d[1] = 0; | ||
667 | d->mac.d[2] = 0; | ||
668 | d->mac.ucode_cmd = 0; | ||
669 | /* use dst index 0 */ | ||
670 | d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) | | ||
671 | (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS); | ||
672 | /* translation type: 0 - bypass; 1 - 802.3; 2 - native wifi */ | ||
673 | d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) | | ||
674 | (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS); | ||
675 | |||
676 | return 0; | ||
677 | } | ||
678 | |||
679 | static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring, | ||
680 | struct sk_buff *skb) | ||
681 | { | ||
682 | struct device *dev = wil_to_dev(wil); | ||
683 | volatile struct vring_tx_desc *d; | ||
684 | u32 swhead = vring->swhead; | ||
685 | int avail = wil_vring_avail_tx(vring); | ||
686 | int nr_frags = skb_shinfo(skb)->nr_frags; | ||
687 | uint f; | ||
688 | int vring_index = vring - wil->vring_tx; | ||
689 | uint i = swhead; | ||
690 | dma_addr_t pa; | ||
691 | |||
692 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
693 | |||
694 | if (avail < vring->size/8) | ||
695 | netif_tx_stop_all_queues(wil_to_ndev(wil)); | ||
696 | if (avail < 1 + nr_frags) { | ||
697 | wil_err(wil, "Tx ring full. No space for %d fragments\n", | ||
698 | 1 + nr_frags); | ||
699 | return -ENOMEM; | ||
700 | } | ||
701 | d = &(vring->va[i].tx); | ||
702 | |||
703 | /* FIXME FW can accept only unicast frames for the peer */ | ||
704 | memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN); | ||
705 | |||
706 | pa = dma_map_single(dev, skb->data, | ||
707 | skb_headlen(skb), DMA_TO_DEVICE); | ||
708 | |||
709 | wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb), | ||
710 | skb->data, (unsigned long long)pa); | ||
711 | wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1, | ||
712 | skb->data, skb_headlen(skb), false); | ||
713 | |||
714 | if (unlikely(dma_mapping_error(dev, pa))) | ||
715 | return -EINVAL; | ||
716 | /* 1-st segment */ | ||
717 | wil_tx_desc_map(d, pa, skb_headlen(skb)); | ||
718 | d->mac.d[2] |= ((nr_frags + 1) << | ||
719 | MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS); | ||
720 | /* middle segments */ | ||
721 | for (f = 0; f < nr_frags; f++) { | ||
722 | const struct skb_frag_struct *frag = | ||
723 | &skb_shinfo(skb)->frags[f]; | ||
724 | int len = skb_frag_size(frag); | ||
725 | i = (swhead + f + 1) % vring->size; | ||
726 | d = &(vring->va[i].tx); | ||
727 | pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag), | ||
728 | DMA_TO_DEVICE); | ||
729 | if (unlikely(dma_mapping_error(dev, pa))) | ||
730 | goto dma_error; | ||
731 | wil_tx_desc_map(d, pa, len); | ||
732 | vring->ctx[i] = NULL; | ||
733 | } | ||
734 | /* for the last seg only */ | ||
735 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS); | ||
736 | d->dma.d0 |= BIT(9); /* BUG: undocumented bit */ | ||
737 | d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS); | ||
738 | d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS); | ||
739 | |||
740 | wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4, | ||
741 | (const void *)d, sizeof(*d), false); | ||
742 | |||
743 | /* advance swhead */ | ||
744 | wil_vring_advance_head(vring, nr_frags + 1); | ||
745 | wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead); | ||
746 | iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail)); | ||
747 | /* hold reference to skb | ||
748 | * to prevent skb release before accounting | ||
749 | * in case of immediate "tx done" | ||
750 | */ | ||
751 | vring->ctx[i] = skb_get(skb); | ||
752 | |||
753 | return 0; | ||
754 | dma_error: | ||
755 | /* unmap what we have mapped */ | ||
756 | /* Note: increment @f to operate with positive index */ | ||
757 | for (f++; f > 0; f--) { | ||
758 | i = (swhead + f) % vring->size; | ||
759 | d = &(vring->va[i].tx); | ||
760 | d->dma.status = TX_DMA_STATUS_DU; | ||
761 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
762 | if (vring->ctx[i]) | ||
763 | dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
764 | else | ||
765 | dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
766 | } | ||
767 | |||
768 | return -EINVAL; | ||
769 | } | ||
770 | |||
771 | |||
772 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev) | ||
773 | { | ||
774 | struct wil6210_priv *wil = ndev_to_wil(ndev); | ||
775 | struct vring *vring; | ||
776 | int rc; | ||
777 | |||
778 | wil_dbg_TXRX(wil, "%s()\n", __func__); | ||
779 | if (!test_bit(wil_status_fwready, &wil->status)) { | ||
780 | wil_err(wil, "FW not ready\n"); | ||
781 | goto drop; | ||
782 | } | ||
783 | if (!test_bit(wil_status_fwconnected, &wil->status)) { | ||
784 | wil_err(wil, "FW not connected\n"); | ||
785 | goto drop; | ||
786 | } | ||
787 | if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) { | ||
788 | wil_err(wil, "Xmit in monitor mode not supported\n"); | ||
789 | goto drop; | ||
790 | } | ||
791 | if (skb->protocol == cpu_to_be16(ETH_P_PAE)) { | ||
792 | rc = wmi_tx_eapol(wil, skb); | ||
793 | } else { | ||
794 | /* find vring */ | ||
795 | vring = wil_find_tx_vring(wil, skb); | ||
796 | if (!vring) { | ||
797 | wil_err(wil, "No Tx VRING available\n"); | ||
798 | goto drop; | ||
799 | } | ||
800 | /* set up vring entry */ | ||
801 | rc = wil_tx_vring(wil, vring, skb); | ||
802 | } | ||
803 | switch (rc) { | ||
804 | case 0: | ||
805 | ndev->stats.tx_packets++; | ||
806 | ndev->stats.tx_bytes += skb->len; | ||
807 | dev_kfree_skb_any(skb); | ||
808 | return NETDEV_TX_OK; | ||
809 | case -ENOMEM: | ||
810 | return NETDEV_TX_BUSY; | ||
811 | default: | ||
812 | ; /* goto drop; */ | ||
813 | break; | ||
814 | } | ||
815 | drop: | ||
816 | netif_tx_stop_all_queues(ndev); | ||
817 | ndev->stats.tx_dropped++; | ||
818 | dev_kfree_skb_any(skb); | ||
819 | |||
820 | return NET_XMIT_DROP; | ||
821 | } | ||
822 | |||
823 | /** | ||
824 | * Clean up transmitted skb's from the Tx VRING | ||
825 | * | ||
826 | * Safe to call from IRQ | ||
827 | */ | ||
828 | void wil_tx_complete(struct wil6210_priv *wil, int ringid) | ||
829 | { | ||
830 | struct device *dev = wil_to_dev(wil); | ||
831 | struct vring *vring = &wil->vring_tx[ringid]; | ||
832 | |||
833 | if (!vring->va) { | ||
834 | wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid); | ||
835 | return; | ||
836 | } | ||
837 | |||
838 | wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid); | ||
839 | |||
840 | while (!wil_vring_is_empty(vring)) { | ||
841 | volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx; | ||
842 | dma_addr_t pa; | ||
843 | struct sk_buff *skb; | ||
844 | if (!(d->dma.status & TX_DMA_STATUS_DU)) | ||
845 | break; | ||
846 | |||
847 | wil_dbg_TXRX(wil, | ||
848 | "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n", | ||
849 | vring->swtail, d->dma.length, d->dma.status, | ||
850 | d->dma.error); | ||
851 | wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4, | ||
852 | (const void *)d, sizeof(*d), false); | ||
853 | |||
854 | pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32); | ||
855 | skb = vring->ctx[vring->swtail]; | ||
856 | if (skb) { | ||
857 | dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
858 | dev_kfree_skb_any(skb); | ||
859 | vring->ctx[vring->swtail] = NULL; | ||
860 | } else { | ||
861 | dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE); | ||
862 | } | ||
863 | d->dma.addr_low = 0; | ||
864 | d->dma.addr_high = 0; | ||
865 | d->dma.length = 0; | ||
866 | d->dma.status = TX_DMA_STATUS_DU; | ||
867 | vring->swtail = wil_vring_next_tail(vring); | ||
868 | } | ||
869 | if (wil_vring_avail_tx(vring) > vring->size/4) | ||
870 | netif_tx_wake_all_queues(wil_to_ndev(wil)); | ||
871 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h new file mode 100644 index 000000000000..45a61f597c5c --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/txrx.h | |||
@@ -0,0 +1,362 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef WIL6210_TXRX_H | ||
18 | #define WIL6210_TXRX_H | ||
19 | |||
20 | #define BUF_SW_OWNED (1) | ||
21 | #define BUF_HW_OWNED (0) | ||
22 | |||
23 | /* size of max. Rx packet */ | ||
24 | #define RX_BUF_LEN (2048) | ||
25 | #define TX_BUF_LEN (2048) | ||
26 | /* how many bytes to reserve for rtap header? */ | ||
27 | #define WIL6210_RTAP_SIZE (128) | ||
28 | |||
29 | /* Tx/Rx path */ | ||
30 | /* | ||
31 | * Tx descriptor - MAC part | ||
32 | * [dword 0] | ||
33 | * bit 0.. 9 : lifetime_expiry_value:10 | ||
34 | * bit 10 : interrup_en:1 | ||
35 | * bit 11 : status_en:1 | ||
36 | * bit 12..13 : txss_override:2 | ||
37 | * bit 14 : timestamp_insertion:1 | ||
38 | * bit 15 : duration_preserve:1 | ||
39 | * bit 16..21 : reserved0:6 | ||
40 | * bit 22..26 : mcs_index:5 | ||
41 | * bit 27 : mcs_en:1 | ||
42 | * bit 28..29 : reserved1:2 | ||
43 | * bit 30 : reserved2:1 | ||
44 | * bit 31 : sn_preserved:1 | ||
45 | * [dword 1] | ||
46 | * bit 0.. 3 : pkt_mode:4 | ||
47 | * bit 4 : pkt_mode_en:1 | ||
48 | * bit 5.. 7 : reserved0:3 | ||
49 | * bit 8..13 : reserved1:6 | ||
50 | * bit 14 : reserved2:1 | ||
51 | * bit 15 : ack_policy_en:1 | ||
52 | * bit 16..19 : dst_index:4 | ||
53 | * bit 20 : dst_index_en:1 | ||
54 | * bit 21..22 : ack_policy:2 | ||
55 | * bit 23 : lifetime_en:1 | ||
56 | * bit 24..30 : max_retry:7 | ||
57 | * bit 31 : max_retry_en:1 | ||
58 | * [dword 2] | ||
59 | * bit 0.. 7 : num_of_descriptors:8 | ||
60 | * bit 8..17 : reserved:10 | ||
61 | * bit 18..19 : l2_translation_type:2 | ||
62 | * bit 20 : snap_hdr_insertion_en:1 | ||
63 | * bit 21 : vlan_removal_en:1 | ||
64 | * bit 22..31 : reserved0:10 | ||
65 | * [dword 3] | ||
66 | * bit 0.. 31: ucode_cmd:32 | ||
67 | */ | ||
68 | struct vring_tx_mac { | ||
69 | u32 d[3]; | ||
70 | u32 ucode_cmd; | ||
71 | } __packed; | ||
72 | |||
73 | /* TX MAC Dword 0 */ | ||
74 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0 | ||
75 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10 | ||
76 | #define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF | ||
77 | |||
78 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10 | ||
79 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1 | ||
80 | #define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400 | ||
81 | |||
82 | #define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11 | ||
83 | #define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1 | ||
84 | #define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800 | ||
85 | |||
86 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12 | ||
87 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2 | ||
88 | #define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000 | ||
89 | |||
90 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14 | ||
91 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1 | ||
92 | #define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000 | ||
93 | |||
94 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15 | ||
95 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1 | ||
96 | #define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000 | ||
97 | |||
98 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22 | ||
99 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5 | ||
100 | #define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000 | ||
101 | |||
102 | #define MAC_CFG_DESC_TX_0_MCS_EN_POS 27 | ||
103 | #define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1 | ||
104 | #define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000 | ||
105 | |||
106 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31 | ||
107 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1 | ||
108 | #define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000 | ||
109 | |||
110 | /* TX MAC Dword 1 */ | ||
111 | #define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0 | ||
112 | #define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4 | ||
113 | #define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF | ||
114 | |||
115 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4 | ||
116 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1 | ||
117 | #define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10 | ||
118 | |||
119 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15 | ||
120 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1 | ||
121 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000 | ||
122 | |||
123 | #define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16 | ||
124 | #define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4 | ||
125 | #define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000 | ||
126 | |||
127 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20 | ||
128 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1 | ||
129 | #define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000 | ||
130 | |||
131 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21 | ||
132 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2 | ||
133 | #define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000 | ||
134 | |||
135 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23 | ||
136 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1 | ||
137 | #define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000 | ||
138 | |||
139 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24 | ||
140 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7 | ||
141 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000 | ||
142 | |||
143 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31 | ||
144 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1 | ||
145 | #define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000 | ||
146 | |||
147 | /* TX MAC Dword 2 */ | ||
148 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0 | ||
149 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8 | ||
150 | #define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF | ||
151 | |||
152 | #define MAC_CFG_DESC_TX_2_RESERVED_POS 8 | ||
153 | #define MAC_CFG_DESC_TX_2_RESERVED_LEN 10 | ||
154 | #define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00 | ||
155 | |||
156 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18 | ||
157 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2 | ||
158 | #define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000 | ||
159 | |||
160 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20 | ||
161 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1 | ||
162 | #define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000 | ||
163 | |||
164 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21 | ||
165 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1 | ||
166 | #define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000 | ||
167 | |||
168 | /* TX MAC Dword 3 */ | ||
169 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0 | ||
170 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32 | ||
171 | #define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF | ||
172 | |||
173 | /* TX DMA Dword 0 */ | ||
174 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0 | ||
175 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8 | ||
176 | #define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF | ||
177 | |||
178 | #define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8 | ||
179 | #define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1 | ||
180 | #define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100 | ||
181 | |||
182 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10 | ||
183 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1 | ||
184 | #define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400 | ||
185 | |||
186 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11 | ||
187 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2 | ||
188 | #define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800 | ||
189 | |||
190 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13 | ||
191 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1 | ||
192 | #define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000 | ||
193 | |||
194 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14 | ||
195 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1 | ||
196 | #define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000 | ||
197 | |||
198 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15 | ||
199 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1 | ||
200 | #define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000 | ||
201 | |||
202 | #define DMA_CFG_DESC_TX_0_QID_POS 16 | ||
203 | #define DMA_CFG_DESC_TX_0_QID_LEN 5 | ||
204 | #define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000 | ||
205 | |||
206 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21 | ||
207 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1 | ||
208 | #define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000 | ||
209 | |||
210 | #define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30 | ||
211 | #define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2 | ||
212 | #define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000 | ||
213 | |||
214 | |||
215 | #define TX_DMA_STATUS_DU BIT(0) | ||
216 | |||
217 | struct vring_tx_dma { | ||
218 | u32 d0; | ||
219 | u32 addr_low; | ||
220 | u16 addr_high; | ||
221 | u8 ip_length; | ||
222 | u8 b11; /* 0..6: mac_length; 7:ip_version */ | ||
223 | u8 error; /* 0..2: err; 3..7: reserved; */ | ||
224 | u8 status; /* 0: used; 1..7; reserved */ | ||
225 | u16 length; | ||
226 | } __packed; | ||
227 | |||
228 | /* | ||
229 | * Rx descriptor - MAC part | ||
230 | * [dword 0] | ||
231 | * bit 0.. 3 : tid:4 The QoS (b3-0) TID Field | ||
232 | * bit 4.. 6 : connection_id:3 :The Source index that was found during | ||
233 | * Parsing the TA. This field is used to define the source of the packet | ||
234 | * bit 7 : reserved:1 | ||
235 | * bit 8.. 9 : mac_id:2 : The MAC virtual Ring number (always zero) | ||
236 | * bit 10..11 : frame_type:2 : The FC Control (b3-2) - MPDU Type | ||
237 | * (management, data, control and extension) | ||
238 | * bit 12..15 : frame_subtype:4 : The FC Control (b7-4) - Frame Subtype | ||
239 | * bit 16..27 : seq_number:12 The received Sequence number field | ||
240 | * bit 28..31 : extended:4 extended subtype | ||
241 | * [dword 1] | ||
242 | * bit 0.. 3 : reserved | ||
243 | * bit 4.. 5 : key_id:2 | ||
244 | * bit 6 : decrypt_bypass:1 | ||
245 | * bit 7 : security:1 | ||
246 | * bit 8.. 9 : ds_bits:2 | ||
247 | * bit 10 : a_msdu_present:1 from qos header | ||
248 | * bit 11 : a_msdu_type:1 from qos header | ||
249 | * bit 12 : a_mpdu:1 part of AMPDU aggregation | ||
250 | * bit 13 : broadcast:1 | ||
251 | * bit 14 : mutlicast:1 | ||
252 | * bit 15 : reserved:1 | ||
253 | * bit 16..20 : rx_mac_qid:5 The Queue Identifier that the packet | ||
254 | * is received from | ||
255 | * bit 21..24 : mcs:4 | ||
256 | * bit 25..28 : mic_icr:4 | ||
257 | * bit 29..31 : reserved:3 | ||
258 | * [dword 2] | ||
259 | * bit 0.. 2 : time_slot:3 The timeslot that the MPDU is received | ||
260 | * bit 3 : fc_protocol_ver:1 The FC Control (b0) - Protocol Version | ||
261 | * bit 4 : fc_order:1 The FC Control (b15) -Order | ||
262 | * bit 5.. 7 : qos_ack_policy:3 The QoS (b6-5) ack policy Field | ||
263 | * bit 8 : esop:1 The QoS (b4) ESOP field | ||
264 | * bit 9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG field | ||
265 | * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved field | ||
266 | * bit 15 : qos_ac_constraint:1 | ||
267 | * bit 16..31 : pn_15_0:16 low 2 bytes of PN | ||
268 | * [dword 3] | ||
269 | * bit 0..31 : pn_47_16:32 high 4 bytes of PN | ||
270 | */ | ||
271 | struct vring_rx_mac { | ||
272 | u32 d0; | ||
273 | u32 d1; | ||
274 | u16 w4; | ||
275 | u16 pn_15_0; | ||
276 | u32 pn_47_16; | ||
277 | } __packed; | ||
278 | |||
279 | /* | ||
280 | * Rx descriptor - DMA part | ||
281 | * [dword 0] | ||
282 | * bit 0.. 7 : l4_length:8 layer 4 length | ||
283 | * bit 8.. 9 : reserved:2 | ||
284 | * bit 10 : cmd_dma_it:1 | ||
285 | * bit 11..15 : reserved:5 | ||
286 | * bit 16..29 : phy_info_length:14 | ||
287 | * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field | ||
288 | * [dword 1] | ||
289 | * bit 0..31 : addr_low:32 The payload buffer low address | ||
290 | * [dword 2] | ||
291 | * bit 0..15 : addr_high:16 The payload buffer high address | ||
292 | * bit 16..23 : ip_length:8 | ||
293 | * bit 24..30 : mac_length:7 | ||
294 | * bit 31 : ip_version:1 | ||
295 | * [dword 3] | ||
296 | * [byte 12] error | ||
297 | * [byte 13] status | ||
298 | * bit 0 : du:1 | ||
299 | * bit 1 : eop:1 | ||
300 | * bit 2 : error:1 | ||
301 | * bit 3 : mi:1 | ||
302 | * bit 4 : l3_identified:1 | ||
303 | * bit 5 : l4_identified:1 | ||
304 | * bit 6 : phy_info_included:1 | ||
305 | * bit 7 : reserved:1 | ||
306 | * [word 7] length | ||
307 | * | ||
308 | */ | ||
309 | |||
310 | #define RX_DMA_D0_CMD_DMA_IT BIT(10) | ||
311 | |||
312 | #define RX_DMA_STATUS_DU BIT(0) | ||
313 | #define RX_DMA_STATUS_ERROR BIT(2) | ||
314 | #define RX_DMA_STATUS_PHY_INFO BIT(6) | ||
315 | |||
316 | struct vring_rx_dma { | ||
317 | u32 d0; | ||
318 | u32 addr_low; | ||
319 | u16 addr_high; | ||
320 | u8 ip_length; | ||
321 | u8 b11; | ||
322 | u8 error; | ||
323 | u8 status; | ||
324 | u16 length; | ||
325 | } __packed; | ||
326 | |||
327 | struct vring_tx_desc { | ||
328 | struct vring_tx_mac mac; | ||
329 | struct vring_tx_dma dma; | ||
330 | } __packed; | ||
331 | |||
332 | struct vring_rx_desc { | ||
333 | struct vring_rx_mac mac; | ||
334 | struct vring_rx_dma dma; | ||
335 | } __packed; | ||
336 | |||
337 | union vring_desc { | ||
338 | struct vring_tx_desc tx; | ||
339 | struct vring_rx_desc rx; | ||
340 | } __packed; | ||
341 | |||
342 | static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d) | ||
343 | { | ||
344 | return WIL_GET_BITS(d->dma.d0, 16, 29); | ||
345 | } | ||
346 | |||
347 | static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d) | ||
348 | { | ||
349 | return WIL_GET_BITS(d->mac.d1, 21, 24); | ||
350 | } | ||
351 | |||
352 | static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d) | ||
353 | { | ||
354 | return WIL_GET_BITS(d->mac.d1, 8, 9); | ||
355 | } | ||
356 | |||
357 | static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d) | ||
358 | { | ||
359 | return WIL_GET_BITS(d->mac.d0, 10, 11); | ||
360 | } | ||
361 | |||
362 | #endif /* WIL6210_TXRX_H */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h new file mode 100644 index 000000000000..9bcfffa4006c --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -0,0 +1,363 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef __WIL6210_H__ | ||
18 | #define __WIL6210_H__ | ||
19 | |||
20 | #include <linux/netdevice.h> | ||
21 | #include <linux/wireless.h> | ||
22 | #include <net/cfg80211.h> | ||
23 | |||
24 | #include "dbg_hexdump.h" | ||
25 | |||
26 | #define WIL_NAME "wil6210" | ||
27 | |||
28 | /** | ||
29 | * extract bits [@b0:@b1] (inclusive) from the value @x | ||
30 | * it should be @b0 <= @b1, or result is incorrect | ||
31 | */ | ||
32 | static inline u32 WIL_GET_BITS(u32 x, int b0, int b1) | ||
33 | { | ||
34 | return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1); | ||
35 | } | ||
36 | |||
37 | #define WIL6210_MEM_SIZE (2*1024*1024UL) | ||
38 | |||
39 | #define WIL6210_TX_QUEUES (4) | ||
40 | |||
41 | #define WIL6210_RX_RING_SIZE (128) | ||
42 | #define WIL6210_TX_RING_SIZE (128) | ||
43 | #define WIL6210_MAX_TX_RINGS (24) | ||
44 | |||
45 | /* Hardware definitions begin */ | ||
46 | |||
47 | /* | ||
48 | * Mapping | ||
49 | * RGF File | Host addr | FW addr | ||
50 | * | | | ||
51 | * user_rgf | 0x000000 | 0x880000 | ||
52 | * dma_rgf | 0x001000 | 0x881000 | ||
53 | * pcie_rgf | 0x002000 | 0x882000 | ||
54 | * | | | ||
55 | */ | ||
56 | |||
57 | /* Where various structures placed in host address space */ | ||
58 | #define WIL6210_FW_HOST_OFF (0x880000UL) | ||
59 | |||
60 | #define HOSTADDR(fwaddr) (fwaddr - WIL6210_FW_HOST_OFF) | ||
61 | |||
62 | /* | ||
63 | * Interrupt control registers block | ||
64 | * | ||
65 | * each interrupt controlled by the same bit in all registers | ||
66 | */ | ||
67 | struct RGF_ICR { | ||
68 | u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */ | ||
69 | u32 ICR; /* Cause, W1C/COR depending on ICC */ | ||
70 | u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */ | ||
71 | u32 ICS; /* Cause Set, WO */ | ||
72 | u32 IMV; /* Mask, RW+S/C */ | ||
73 | u32 IMS; /* Mask Set, write 1 to set */ | ||
74 | u32 IMC; /* Mask Clear, write 1 to clear */ | ||
75 | } __packed; | ||
76 | |||
77 | /* registers - FW addresses */ | ||
78 | #define RGF_USER_USER_SCRATCH_PAD (0x8802bc) | ||
79 | #define RGF_USER_USER_ICR (0x880b4c) /* struct RGF_ICR */ | ||
80 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) | ||
81 | #define RGF_USER_CLKS_CTL_SW_RST_MASK_0 (0x880b14) | ||
82 | #define RGF_USER_MAC_CPU_0 (0x8801fc) | ||
83 | #define RGF_USER_USER_CPU_0 (0x8801e0) | ||
84 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_0 (0x880b04) | ||
85 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_1 (0x880b08) | ||
86 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_2 (0x880b0c) | ||
87 | #define RGF_USER_CLKS_CTL_SW_RST_VEC_3 (0x880b10) | ||
88 | |||
89 | #define RGF_DMA_PSEUDO_CAUSE (0x881c68) | ||
90 | #define RGF_DMA_PSEUDO_CAUSE_MASK_SW (0x881c6c) | ||
91 | #define RGF_DMA_PSEUDO_CAUSE_MASK_FW (0x881c70) | ||
92 | #define BIT_DMA_PSEUDO_CAUSE_RX BIT(0) | ||
93 | #define BIT_DMA_PSEUDO_CAUSE_TX BIT(1) | ||
94 | #define BIT_DMA_PSEUDO_CAUSE_MISC BIT(2) | ||
95 | |||
96 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ | ||
97 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) | ||
98 | #define BIT_DMA_EP_TX_ICR_TX_DONE_N(n) BIT(n+1) /* n = [0..23] */ | ||
99 | #define RGF_DMA_EP_RX_ICR (0x881bd0) /* struct RGF_ICR */ | ||
100 | #define BIT_DMA_EP_RX_ICR_RX_DONE BIT(0) | ||
101 | #define RGF_DMA_EP_MISC_ICR (0x881bec) /* struct RGF_ICR */ | ||
102 | #define BIT_DMA_EP_MISC_ICR_RX_HTRSH BIT(0) | ||
103 | #define BIT_DMA_EP_MISC_ICR_TX_NO_ACT BIT(1) | ||
104 | #define BIT_DMA_EP_MISC_ICR_FW_INT0 BIT(28) | ||
105 | #define BIT_DMA_EP_MISC_ICR_FW_INT1 BIT(29) | ||
106 | |||
107 | /* Interrupt moderation control */ | ||
108 | #define RGF_DMA_ITR_CNT_TRSH (0x881c5c) | ||
109 | #define RGF_DMA_ITR_CNT_DATA (0x881c60) | ||
110 | #define RGF_DMA_ITR_CNT_CRL (0x881C64) | ||
111 | #define BIT_DMA_ITR_CNT_CRL_EN BIT(0) | ||
112 | #define BIT_DMA_ITR_CNT_CRL_EXT_TICK BIT(1) | ||
113 | #define BIT_DMA_ITR_CNT_CRL_FOREVER BIT(2) | ||
114 | #define BIT_DMA_ITR_CNT_CRL_CLR BIT(3) | ||
115 | #define BIT_DMA_ITR_CNT_CRL_REACH_TRSH BIT(4) | ||
116 | |||
117 | /* popular locations */ | ||
118 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) | ||
119 | #define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \ | ||
120 | offsetof(struct RGF_ICR, ICS)) | ||
121 | #define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2 | ||
122 | |||
123 | /* ISR register bits */ | ||
124 | #define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0 | ||
125 | #define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1 | ||
126 | |||
127 | /* Hardware definitions end */ | ||
128 | |||
129 | struct wil6210_mbox_ring { | ||
130 | u32 base; | ||
131 | u16 entry_size; /* max. size of mbox entry, incl. all headers */ | ||
132 | u16 size; | ||
133 | u32 tail; | ||
134 | u32 head; | ||
135 | } __packed; | ||
136 | |||
137 | struct wil6210_mbox_ring_desc { | ||
138 | __le32 sync; | ||
139 | __le32 addr; | ||
140 | } __packed; | ||
141 | |||
142 | /* at HOST_OFF_WIL6210_MBOX_CTL */ | ||
143 | struct wil6210_mbox_ctl { | ||
144 | struct wil6210_mbox_ring tx; | ||
145 | struct wil6210_mbox_ring rx; | ||
146 | } __packed; | ||
147 | |||
148 | struct wil6210_mbox_hdr { | ||
149 | __le16 seq; | ||
150 | __le16 len; /* payload, bytes after this header */ | ||
151 | __le16 type; | ||
152 | u8 flags; | ||
153 | u8 reserved; | ||
154 | } __packed; | ||
155 | |||
156 | #define WIL_MBOX_HDR_TYPE_WMI (0) | ||
157 | |||
158 | /* max. value for wil6210_mbox_hdr.len */ | ||
159 | #define MAX_MBOXITEM_SIZE (240) | ||
160 | |||
161 | struct wil6210_mbox_hdr_wmi { | ||
162 | u8 reserved0[2]; | ||
163 | __le16 id; | ||
164 | __le16 info1; /* bits [0..3] - device_id, rest - unused */ | ||
165 | u8 reserved1[2]; | ||
166 | } __packed; | ||
167 | |||
168 | struct pending_wmi_event { | ||
169 | struct list_head list; | ||
170 | struct { | ||
171 | struct wil6210_mbox_hdr hdr; | ||
172 | struct wil6210_mbox_hdr_wmi wmi; | ||
173 | u8 data[0]; | ||
174 | } __packed event; | ||
175 | }; | ||
176 | |||
177 | union vring_desc; | ||
178 | |||
179 | struct vring { | ||
180 | dma_addr_t pa; | ||
181 | volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */ | ||
182 | u16 size; /* number of vring_desc elements */ | ||
183 | u32 swtail; | ||
184 | u32 swhead; | ||
185 | u32 hwtail; /* write here to inform hw */ | ||
186 | void **ctx; /* void *ctx[size] - software context */ | ||
187 | }; | ||
188 | |||
189 | enum { /* for wil6210_priv.status */ | ||
190 | wil_status_fwready = 0, | ||
191 | wil_status_fwconnected, | ||
192 | wil_status_dontscan, | ||
193 | wil_status_irqen, /* FIXME: interrupts enabled - for debug */ | ||
194 | }; | ||
195 | |||
196 | struct pci_dev; | ||
197 | |||
198 | struct wil6210_stats { | ||
199 | u64 tsf; | ||
200 | u32 snr; | ||
201 | u16 last_mcs_rx; | ||
202 | u16 bf_mcs; /* last BF, used for Tx */ | ||
203 | u16 my_rx_sector; | ||
204 | u16 my_tx_sector; | ||
205 | u16 peer_rx_sector; | ||
206 | u16 peer_tx_sector; | ||
207 | }; | ||
208 | |||
209 | struct wil6210_priv { | ||
210 | struct pci_dev *pdev; | ||
211 | int n_msi; | ||
212 | struct wireless_dev *wdev; | ||
213 | void __iomem *csr; | ||
214 | ulong status; | ||
215 | /* profile */ | ||
216 | u32 monitor_flags; | ||
217 | u32 secure_pcp; /* create secure PCP? */ | ||
218 | int sinfo_gen; | ||
219 | /* cached ISR registers */ | ||
220 | u32 isr_misc; | ||
221 | /* mailbox related */ | ||
222 | struct mutex wmi_mutex; | ||
223 | struct wil6210_mbox_ctl mbox_ctl; | ||
224 | struct completion wmi_ready; | ||
225 | u16 wmi_seq; | ||
226 | u16 reply_id; /**< wait for this WMI event */ | ||
227 | void *reply_buf; | ||
228 | u16 reply_size; | ||
229 | struct workqueue_struct *wmi_wq; /* for deferred calls */ | ||
230 | struct work_struct wmi_event_worker; | ||
231 | struct workqueue_struct *wmi_wq_conn; /* for connect worker */ | ||
232 | struct work_struct wmi_connect_worker; | ||
233 | struct work_struct disconnect_worker; | ||
234 | struct timer_list connect_timer; | ||
235 | int pending_connect_cid; | ||
236 | struct list_head pending_wmi_ev; | ||
237 | /* | ||
238 | * protect pending_wmi_ev | ||
239 | * - fill in IRQ from wil6210_irq_misc, | ||
240 | * - consumed in thread by wmi_event_worker | ||
241 | */ | ||
242 | spinlock_t wmi_ev_lock; | ||
243 | /* DMA related */ | ||
244 | struct vring vring_rx; | ||
245 | struct vring vring_tx[WIL6210_MAX_TX_RINGS]; | ||
246 | u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN]; | ||
247 | /* scan */ | ||
248 | struct cfg80211_scan_request *scan_request; | ||
249 | |||
250 | struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */ | ||
251 | /* statistics */ | ||
252 | struct wil6210_stats stats; | ||
253 | /* debugfs */ | ||
254 | struct dentry *debug; | ||
255 | struct debugfs_blob_wrapper fw_code_blob; | ||
256 | struct debugfs_blob_wrapper fw_data_blob; | ||
257 | struct debugfs_blob_wrapper fw_peri_blob; | ||
258 | struct debugfs_blob_wrapper uc_code_blob; | ||
259 | struct debugfs_blob_wrapper uc_data_blob; | ||
260 | struct debugfs_blob_wrapper rgf_blob; | ||
261 | }; | ||
262 | |||
263 | #define wil_to_wiphy(i) (i->wdev->wiphy) | ||
264 | #define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i))) | ||
265 | #define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w)) | ||
266 | #define wil_to_wdev(i) (i->wdev) | ||
267 | #define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w)) | ||
268 | #define wil_to_ndev(i) (wil_to_wdev(i)->netdev) | ||
269 | #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) | ||
270 | |||
271 | #define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg) | ||
272 | #define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg) | ||
273 | #define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg) | ||
274 | |||
275 | #define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg) | ||
276 | #define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg) | ||
277 | #define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg) | ||
278 | |||
279 | #define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize, \ | ||
280 | groupsize, buf, len, ascii) \ | ||
281 | wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\ | ||
282 | prefix_type, rowsize, \ | ||
283 | groupsize, buf, len, ascii) | ||
284 | |||
285 | #define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize, \ | ||
286 | groupsize, buf, len, ascii) \ | ||
287 | wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\ | ||
288 | prefix_type, rowsize, \ | ||
289 | groupsize, buf, len, ascii) | ||
290 | |||
291 | void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src, | ||
292 | size_t count); | ||
293 | void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | ||
294 | size_t count); | ||
295 | |||
296 | void *wil_if_alloc(struct device *dev, void __iomem *csr); | ||
297 | void wil_if_free(struct wil6210_priv *wil); | ||
298 | int wil_if_add(struct wil6210_priv *wil); | ||
299 | void wil_if_remove(struct wil6210_priv *wil); | ||
300 | int wil_priv_init(struct wil6210_priv *wil); | ||
301 | void wil_priv_deinit(struct wil6210_priv *wil); | ||
302 | int wil_reset(struct wil6210_priv *wil); | ||
303 | void wil_link_on(struct wil6210_priv *wil); | ||
304 | void wil_link_off(struct wil6210_priv *wil); | ||
305 | int wil_up(struct wil6210_priv *wil); | ||
306 | int wil_down(struct wil6210_priv *wil); | ||
307 | void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r); | ||
308 | |||
309 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr); | ||
310 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr); | ||
311 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, | ||
312 | struct wil6210_mbox_hdr *hdr); | ||
313 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len); | ||
314 | void wmi_recv_cmd(struct wil6210_priv *wil); | ||
315 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | ||
316 | u16 reply_id, void *reply, u8 reply_size, int to_msec); | ||
317 | void wmi_connect_worker(struct work_struct *work); | ||
318 | void wmi_event_worker(struct work_struct *work); | ||
319 | void wmi_event_flush(struct wil6210_priv *wil); | ||
320 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid); | ||
321 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid); | ||
322 | int wmi_set_channel(struct wil6210_priv *wil, int channel); | ||
323 | int wmi_get_channel(struct wil6210_priv *wil, int *channel); | ||
324 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb); | ||
325 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
326 | const void *mac_addr); | ||
327 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
328 | const void *mac_addr, int key_len, const void *key); | ||
329 | int wmi_echo(struct wil6210_priv *wil); | ||
330 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie); | ||
331 | |||
332 | int wil6210_init_irq(struct wil6210_priv *wil, int irq); | ||
333 | void wil6210_fini_irq(struct wil6210_priv *wil, int irq); | ||
334 | void wil6210_disable_irq(struct wil6210_priv *wil); | ||
335 | void wil6210_enable_irq(struct wil6210_priv *wil); | ||
336 | |||
337 | int wil6210_debugfs_init(struct wil6210_priv *wil); | ||
338 | void wil6210_debugfs_remove(struct wil6210_priv *wil); | ||
339 | |||
340 | struct wireless_dev *wil_cfg80211_init(struct device *dev); | ||
341 | void wil_wdev_free(struct wil6210_priv *wil); | ||
342 | |||
343 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | ||
344 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype); | ||
345 | void wil6210_disconnect(struct wil6210_priv *wil, void *bssid); | ||
346 | |||
347 | int wil_rx_init(struct wil6210_priv *wil); | ||
348 | void wil_rx_fini(struct wil6210_priv *wil); | ||
349 | |||
350 | /* TX API */ | ||
351 | int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | ||
352 | int cid, int tid); | ||
353 | void wil_vring_fini_tx(struct wil6210_priv *wil, int id); | ||
354 | |||
355 | netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev); | ||
356 | void wil_tx_complete(struct wil6210_priv *wil, int ringid); | ||
357 | |||
358 | /* RX API */ | ||
359 | void wil_rx_handle(struct wil6210_priv *wil); | ||
360 | |||
361 | int wil_iftype_nl2wmi(enum nl80211_iftype type); | ||
362 | |||
363 | #endif /* __WIL6210_H__ */ | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c new file mode 100644 index 000000000000..12915f6e7617 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -0,0 +1,975 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * | ||
4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
5 | * purpose with or without fee is hereby granted, provided that the above | ||
6 | * copyright notice and this permission notice appear in all copies. | ||
7 | * | ||
8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/pci.h> | ||
18 | #include <linux/io.h> | ||
19 | #include <linux/list.h> | ||
20 | #include <linux/etherdevice.h> | ||
21 | |||
22 | #include "wil6210.h" | ||
23 | #include "wmi.h" | ||
24 | |||
25 | /** | ||
26 | * WMI event receiving - theory of operations | ||
27 | * | ||
28 | * When firmware about to report WMI event, it fills memory area | ||
29 | * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for | ||
30 | * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler. | ||
31 | * | ||
32 | * @wmi_recv_cmd reads event, allocates memory chunk and attaches it to the | ||
33 | * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up | ||
34 | * and handles events within the @wmi_event_worker. Every event get detached | ||
35 | * from list, processed and deleted. | ||
36 | * | ||
37 | * Purpose for this mechanism is to release IRQ thread; otherwise, | ||
38 | * if WMI event handling involves another WMI command flow, this 2-nd flow | ||
39 | * won't be completed because of blocked IRQ thread. | ||
40 | */ | ||
41 | |||
42 | /** | ||
43 | * Addressing - theory of operations | ||
44 | * | ||
45 | * There are several buses present on the WIL6210 card. | ||
46 | * Same memory areas are visible at different address on | ||
47 | * the different busses. There are 3 main bus masters: | ||
48 | * - MAC CPU (ucode) | ||
49 | * - User CPU (firmware) | ||
50 | * - AHB (host) | ||
51 | * | ||
52 | * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing | ||
53 | * AHB addresses starting from 0x880000 | ||
54 | * | ||
55 | * Internally, firmware uses addresses that allows faster access but | ||
56 | * are invisible from the host. To read from these addresses, alternative | ||
57 | * AHB address must be used. | ||
58 | * | ||
59 | * Memory mapping | ||
60 | * Linker address PCI/Host address | ||
61 | * 0x880000 .. 0xa80000 2Mb BAR0 | ||
62 | * 0x800000 .. 0x807000 0x900000 .. 0x907000 28k DCCM | ||
63 | * 0x840000 .. 0x857000 0x908000 .. 0x91f000 92k PERIPH | ||
64 | */ | ||
65 | |||
66 | /** | ||
67 | * @fw_mapping provides memory remapping table | ||
68 | */ | ||
69 | static const struct { | ||
70 | u32 from; /* linker address - from, inclusive */ | ||
71 | u32 to; /* linker address - to, exclusive */ | ||
72 | u32 host; /* PCI/Host address - BAR0 + 0x880000 */ | ||
73 | } fw_mapping[] = { | ||
74 | {0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */ | ||
75 | {0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */ | ||
76 | {0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */ | ||
77 | {0x880000, 0x88a000, 0x880000}, /* various RGF */ | ||
78 | {0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */ | ||
79 | /* | ||
80 | * 920000..930000 ucode code RAM | ||
81 | * 930000..932000 ucode data RAM | ||
82 | */ | ||
83 | }; | ||
84 | |||
85 | /** | ||
86 | * return AHB address for given firmware/ucode internal (linker) address | ||
87 | * @x - internal address | ||
88 | * If address have no valid AHB mapping, return 0 | ||
89 | */ | ||
90 | static u32 wmi_addr_remap(u32 x) | ||
91 | { | ||
92 | uint i; | ||
93 | |||
94 | for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) { | ||
95 | if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to)) | ||
96 | return x + fw_mapping[i].host - fw_mapping[i].from; | ||
97 | } | ||
98 | |||
99 | return 0; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * Check address validity for WMI buffer; remap if needed | ||
104 | * @ptr - internal (linker) fw/ucode address | ||
105 | * | ||
106 | * Valid buffer should be DWORD aligned | ||
107 | * | ||
108 | * return address for accessing buffer from the host; | ||
109 | * if buffer is not valid, return NULL. | ||
110 | */ | ||
111 | void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_) | ||
112 | { | ||
113 | u32 off; | ||
114 | u32 ptr = le32_to_cpu(ptr_); | ||
115 | |||
116 | if (ptr % 4) | ||
117 | return NULL; | ||
118 | |||
119 | ptr = wmi_addr_remap(ptr); | ||
120 | if (ptr < WIL6210_FW_HOST_OFF) | ||
121 | return NULL; | ||
122 | |||
123 | off = HOSTADDR(ptr); | ||
124 | if (off > WIL6210_MEM_SIZE - 4) | ||
125 | return NULL; | ||
126 | |||
127 | return wil->csr + off; | ||
128 | } | ||
129 | |||
130 | /** | ||
131 | * Check address validity | ||
132 | */ | ||
133 | void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr) | ||
134 | { | ||
135 | u32 off; | ||
136 | |||
137 | if (ptr % 4) | ||
138 | return NULL; | ||
139 | |||
140 | if (ptr < WIL6210_FW_HOST_OFF) | ||
141 | return NULL; | ||
142 | |||
143 | off = HOSTADDR(ptr); | ||
144 | if (off > WIL6210_MEM_SIZE - 4) | ||
145 | return NULL; | ||
146 | |||
147 | return wil->csr + off; | ||
148 | } | ||
149 | |||
150 | int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr, | ||
151 | struct wil6210_mbox_hdr *hdr) | ||
152 | { | ||
153 | void __iomem *src = wmi_buffer(wil, ptr); | ||
154 | if (!src) | ||
155 | return -EINVAL; | ||
156 | |||
157 | wil_memcpy_fromio_32(hdr, src, sizeof(*hdr)); | ||
158 | |||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | ||
163 | { | ||
164 | struct { | ||
165 | struct wil6210_mbox_hdr hdr; | ||
166 | struct wil6210_mbox_hdr_wmi wmi; | ||
167 | } __packed cmd = { | ||
168 | .hdr = { | ||
169 | .type = WIL_MBOX_HDR_TYPE_WMI, | ||
170 | .flags = 0, | ||
171 | .len = cpu_to_le16(sizeof(cmd.wmi) + len), | ||
172 | }, | ||
173 | .wmi = { | ||
174 | .id = cpu_to_le16(cmdid), | ||
175 | .info1 = 0, | ||
176 | }, | ||
177 | }; | ||
178 | struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx; | ||
179 | struct wil6210_mbox_ring_desc d_head; | ||
180 | u32 next_head; | ||
181 | void __iomem *dst; | ||
182 | void __iomem *head = wmi_addr(wil, r->head); | ||
183 | uint retry; | ||
184 | |||
185 | if (sizeof(cmd) + len > r->entry_size) { | ||
186 | wil_err(wil, "WMI size too large: %d bytes, max is %d\n", | ||
187 | (int)(sizeof(cmd) + len), r->entry_size); | ||
188 | return -ERANGE; | ||
189 | |||
190 | } | ||
191 | |||
192 | might_sleep(); | ||
193 | |||
194 | if (!test_bit(wil_status_fwready, &wil->status)) { | ||
195 | wil_err(wil, "FW not ready\n"); | ||
196 | return -EAGAIN; | ||
197 | } | ||
198 | |||
199 | if (!head) { | ||
200 | wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head); | ||
201 | return -EINVAL; | ||
202 | } | ||
203 | /* read Tx head till it is not busy */ | ||
204 | for (retry = 5; retry > 0; retry--) { | ||
205 | wil_memcpy_fromio_32(&d_head, head, sizeof(d_head)); | ||
206 | if (d_head.sync == 0) | ||
207 | break; | ||
208 | msleep(20); | ||
209 | } | ||
210 | if (d_head.sync != 0) { | ||
211 | wil_err(wil, "WMI head busy\n"); | ||
212 | return -EBUSY; | ||
213 | } | ||
214 | /* next head */ | ||
215 | next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size); | ||
216 | wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); | ||
217 | /* wait till FW finish with previous command */ | ||
218 | for (retry = 5; retry > 0; retry--) { | ||
219 | r->tail = ioread32(wil->csr + HOST_MBOX + | ||
220 | offsetof(struct wil6210_mbox_ctl, tx.tail)); | ||
221 | if (next_head != r->tail) | ||
222 | break; | ||
223 | msleep(20); | ||
224 | } | ||
225 | if (next_head == r->tail) { | ||
226 | wil_err(wil, "WMI ring full\n"); | ||
227 | return -EBUSY; | ||
228 | } | ||
229 | dst = wmi_buffer(wil, d_head.addr); | ||
230 | if (!dst) { | ||
231 | wil_err(wil, "invalid WMI buffer: 0x%08x\n", | ||
232 | le32_to_cpu(d_head.addr)); | ||
233 | return -EINVAL; | ||
234 | } | ||
235 | cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq); | ||
236 | /* set command */ | ||
237 | wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len); | ||
238 | wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd, | ||
239 | sizeof(cmd), true); | ||
240 | wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf, | ||
241 | len, true); | ||
242 | wil_memcpy_toio_32(dst, &cmd, sizeof(cmd)); | ||
243 | wil_memcpy_toio_32(dst + sizeof(cmd), buf, len); | ||
244 | /* mark entry as full */ | ||
245 | iowrite32(1, wil->csr + HOSTADDR(r->head) + | ||
246 | offsetof(struct wil6210_mbox_ring_desc, sync)); | ||
247 | /* advance next ptr */ | ||
248 | iowrite32(r->head = next_head, wil->csr + HOST_MBOX + | ||
249 | offsetof(struct wil6210_mbox_ctl, tx.head)); | ||
250 | |||
251 | /* interrupt to FW */ | ||
252 | iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT); | ||
253 | |||
254 | return 0; | ||
255 | } | ||
256 | |||
257 | int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | ||
258 | { | ||
259 | int rc; | ||
260 | |||
261 | mutex_lock(&wil->wmi_mutex); | ||
262 | rc = __wmi_send(wil, cmdid, buf, len); | ||
263 | mutex_unlock(&wil->wmi_mutex); | ||
264 | |||
265 | return rc; | ||
266 | } | ||
267 | |||
268 | /*=== Event handlers ===*/ | ||
269 | static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len) | ||
270 | { | ||
271 | struct net_device *ndev = wil_to_ndev(wil); | ||
272 | struct wireless_dev *wdev = wil->wdev; | ||
273 | struct wmi_ready_event *evt = d; | ||
274 | u32 ver = le32_to_cpu(evt->sw_version); | ||
275 | |||
276 | wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac); | ||
277 | |||
278 | if (!is_valid_ether_addr(ndev->dev_addr)) { | ||
279 | memcpy(ndev->dev_addr, evt->mac, ETH_ALEN); | ||
280 | memcpy(ndev->perm_addr, evt->mac, ETH_ALEN); | ||
281 | } | ||
282 | snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version), | ||
283 | "%d", ver); | ||
284 | } | ||
285 | |||
286 | static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d, | ||
287 | int len) | ||
288 | { | ||
289 | wil_dbg_WMI(wil, "WMI: FW ready\n"); | ||
290 | |||
291 | set_bit(wil_status_fwready, &wil->status); | ||
292 | /* reuse wmi_ready for the firmware ready indication */ | ||
293 | complete(&wil->wmi_ready); | ||
294 | } | ||
295 | |||
296 | static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len) | ||
297 | { | ||
298 | struct wmi_rx_mgmt_packet_event *data = d; | ||
299 | struct wiphy *wiphy = wil_to_wiphy(wil); | ||
300 | struct ieee80211_mgmt *rx_mgmt_frame = | ||
301 | (struct ieee80211_mgmt *)data->payload; | ||
302 | int ch_no = data->info.channel+1; | ||
303 | u32 freq = ieee80211_channel_to_frequency(ch_no, | ||
304 | IEEE80211_BAND_60GHZ); | ||
305 | struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq); | ||
306 | /* TODO convert LE to CPU */ | ||
307 | s32 signal = 0; /* TODO */ | ||
308 | __le16 fc = rx_mgmt_frame->frame_control; | ||
309 | u32 d_len = le32_to_cpu(data->info.len); | ||
310 | u16 d_status = le16_to_cpu(data->info.status); | ||
311 | |||
312 | wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n", | ||
313 | data->info.channel, data->info.mcs, data->info.snr); | ||
314 | wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len, | ||
315 | le16_to_cpu(data->info.stype)); | ||
316 | wil_dbg_WMI(wil, "qid %d mid %d cid %d\n", | ||
317 | data->info.qid, data->info.mid, data->info.cid); | ||
318 | |||
319 | if (!channel) { | ||
320 | wil_err(wil, "Frame on unsupported channel\n"); | ||
321 | return; | ||
322 | } | ||
323 | |||
324 | if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) { | ||
325 | struct cfg80211_bss *bss; | ||
326 | u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp); | ||
327 | u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info); | ||
328 | u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int); | ||
329 | const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable; | ||
330 | size_t ie_len = d_len - offsetof(struct ieee80211_mgmt, | ||
331 | u.beacon.variable); | ||
332 | wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap); | ||
333 | |||
334 | bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid, | ||
335 | tsf, cap, bi, ie_buf, ie_len, | ||
336 | signal, GFP_KERNEL); | ||
337 | if (bss) { | ||
338 | wil_dbg_WMI(wil, "Added BSS %pM\n", | ||
339 | rx_mgmt_frame->bssid); | ||
340 | cfg80211_put_bss(bss); | ||
341 | } else { | ||
342 | wil_err(wil, "cfg80211_inform_bss() failed\n"); | ||
343 | } | ||
344 | } | ||
345 | } | ||
346 | |||
347 | static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id, | ||
348 | void *d, int len) | ||
349 | { | ||
350 | if (wil->scan_request) { | ||
351 | struct wmi_scan_complete_event *data = d; | ||
352 | bool aborted = (data->status != 0); | ||
353 | |||
354 | wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status); | ||
355 | cfg80211_scan_done(wil->scan_request, aborted); | ||
356 | wil->scan_request = NULL; | ||
357 | } else { | ||
358 | wil_err(wil, "SCAN_COMPLETE while not scanning\n"); | ||
359 | } | ||
360 | } | ||
361 | |||
362 | static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len) | ||
363 | { | ||
364 | struct net_device *ndev = wil_to_ndev(wil); | ||
365 | struct wireless_dev *wdev = wil->wdev; | ||
366 | struct wmi_connect_event *evt = d; | ||
367 | int ch; /* channel number */ | ||
368 | struct station_info sinfo; | ||
369 | u8 *assoc_req_ie, *assoc_resp_ie; | ||
370 | size_t assoc_req_ielen, assoc_resp_ielen; | ||
371 | /* capinfo(u16) + listen_interval(u16) + IEs */ | ||
372 | const size_t assoc_req_ie_offset = sizeof(u16) * 2; | ||
373 | /* capinfo(u16) + status_code(u16) + associd(u16) + IEs */ | ||
374 | const size_t assoc_resp_ie_offset = sizeof(u16) * 3; | ||
375 | |||
376 | if (len < sizeof(*evt)) { | ||
377 | wil_err(wil, "Connect event too short : %d bytes\n", len); | ||
378 | return; | ||
379 | } | ||
380 | if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len + | ||
381 | evt->assoc_resp_len) { | ||
382 | wil_err(wil, | ||
383 | "Connect event corrupted : %d != %d + %d + %d + %d\n", | ||
384 | len, (int)sizeof(*evt), evt->beacon_ie_len, | ||
385 | evt->assoc_req_len, evt->assoc_resp_len); | ||
386 | return; | ||
387 | } | ||
388 | ch = evt->channel + 1; | ||
389 | wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n", | ||
390 | evt->bssid, ch, evt->cid); | ||
391 | wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1, | ||
392 | evt->assoc_info, len - sizeof(*evt), true); | ||
393 | |||
394 | /* figure out IE's */ | ||
395 | assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len + | ||
396 | assoc_req_ie_offset]; | ||
397 | assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset; | ||
398 | if (evt->assoc_req_len <= assoc_req_ie_offset) { | ||
399 | assoc_req_ie = NULL; | ||
400 | assoc_req_ielen = 0; | ||
401 | } | ||
402 | |||
403 | assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len + | ||
404 | evt->assoc_req_len + | ||
405 | assoc_resp_ie_offset]; | ||
406 | assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset; | ||
407 | if (evt->assoc_resp_len <= assoc_resp_ie_offset) { | ||
408 | assoc_resp_ie = NULL; | ||
409 | assoc_resp_ielen = 0; | ||
410 | } | ||
411 | |||
412 | if ((wdev->iftype == NL80211_IFTYPE_STATION) || | ||
413 | (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) { | ||
414 | if (wdev->sme_state != CFG80211_SME_CONNECTING) { | ||
415 | wil_err(wil, "Not in connecting state\n"); | ||
416 | return; | ||
417 | } | ||
418 | del_timer_sync(&wil->connect_timer); | ||
419 | cfg80211_connect_result(ndev, evt->bssid, | ||
420 | assoc_req_ie, assoc_req_ielen, | ||
421 | assoc_resp_ie, assoc_resp_ielen, | ||
422 | WLAN_STATUS_SUCCESS, GFP_KERNEL); | ||
423 | |||
424 | } else if ((wdev->iftype == NL80211_IFTYPE_AP) || | ||
425 | (wdev->iftype == NL80211_IFTYPE_P2P_GO)) { | ||
426 | memset(&sinfo, 0, sizeof(sinfo)); | ||
427 | |||
428 | sinfo.generation = wil->sinfo_gen++; | ||
429 | |||
430 | if (assoc_req_ie) { | ||
431 | sinfo.assoc_req_ies = assoc_req_ie; | ||
432 | sinfo.assoc_req_ies_len = assoc_req_ielen; | ||
433 | sinfo.filled |= STATION_INFO_ASSOC_REQ_IES; | ||
434 | } | ||
435 | |||
436 | cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL); | ||
437 | } | ||
438 | set_bit(wil_status_fwconnected, &wil->status); | ||
439 | |||
440 | /* FIXME FW can transmit only ucast frames to peer */ | ||
441 | /* FIXME real ring_id instead of hard coded 0 */ | ||
442 | memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN); | ||
443 | |||
444 | wil->pending_connect_cid = evt->cid; | ||
445 | queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker); | ||
446 | } | ||
447 | |||
448 | static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | ||
449 | void *d, int len) | ||
450 | { | ||
451 | struct wmi_disconnect_event *evt = d; | ||
452 | |||
453 | wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n", | ||
454 | evt->bssid, | ||
455 | evt->protocol_reason_status, evt->disconnect_reason); | ||
456 | |||
457 | wil->sinfo_gen++; | ||
458 | |||
459 | wil6210_disconnect(wil, evt->bssid); | ||
460 | clear_bit(wil_status_dontscan, &wil->status); | ||
461 | } | ||
462 | |||
463 | static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len) | ||
464 | { | ||
465 | struct wmi_notify_req_done_event *evt = d; | ||
466 | |||
467 | if (len < sizeof(*evt)) { | ||
468 | wil_err(wil, "Short NOTIFY event\n"); | ||
469 | return; | ||
470 | } | ||
471 | |||
472 | wil->stats.tsf = le64_to_cpu(evt->tsf); | ||
473 | wil->stats.snr = le32_to_cpu(evt->snr_val); | ||
474 | wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs); | ||
475 | wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector); | ||
476 | wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector); | ||
477 | wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector); | ||
478 | wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector); | ||
479 | wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n" | ||
480 | "BF status 0x%08x SNR 0x%08x\n" | ||
481 | "Tx Tpt %d goodput %d Rx goodput %d\n" | ||
482 | "Sectors(rx:tx) my %d:%d peer %d:%d\n", | ||
483 | wil->stats.bf_mcs, wil->stats.tsf, evt->status, | ||
484 | wil->stats.snr, le32_to_cpu(evt->tx_tpt), | ||
485 | le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput), | ||
486 | wil->stats.my_rx_sector, wil->stats.my_tx_sector, | ||
487 | wil->stats.peer_rx_sector, wil->stats.peer_tx_sector); | ||
488 | } | ||
489 | |||
490 | /* | ||
491 | * Firmware reports EAPOL frame using WME event. | ||
492 | * Reconstruct Ethernet frame and deliver it via normal Rx | ||
493 | */ | ||
494 | static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id, | ||
495 | void *d, int len) | ||
496 | { | ||
497 | struct net_device *ndev = wil_to_ndev(wil); | ||
498 | struct wmi_eapol_rx_event *evt = d; | ||
499 | u16 eapol_len = le16_to_cpu(evt->eapol_len); | ||
500 | int sz = eapol_len + ETH_HLEN; | ||
501 | struct sk_buff *skb; | ||
502 | struct ethhdr *eth; | ||
503 | |||
504 | wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len, | ||
505 | evt->src_mac); | ||
506 | |||
507 | if (eapol_len > 196) { /* TODO: revisit size limit */ | ||
508 | wil_err(wil, "EAPOL too large\n"); | ||
509 | return; | ||
510 | } | ||
511 | |||
512 | skb = alloc_skb(sz, GFP_KERNEL); | ||
513 | if (!skb) { | ||
514 | wil_err(wil, "Failed to allocate skb\n"); | ||
515 | return; | ||
516 | } | ||
517 | eth = (struct ethhdr *)skb_put(skb, ETH_HLEN); | ||
518 | memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN); | ||
519 | memcpy(eth->h_source, evt->src_mac, ETH_ALEN); | ||
520 | eth->h_proto = cpu_to_be16(ETH_P_PAE); | ||
521 | memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len); | ||
522 | skb->protocol = eth_type_trans(skb, ndev); | ||
523 | if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) { | ||
524 | ndev->stats.rx_packets++; | ||
525 | ndev->stats.rx_bytes += skb->len; | ||
526 | } else { | ||
527 | ndev->stats.rx_dropped++; | ||
528 | } | ||
529 | } | ||
530 | |||
531 | static const struct { | ||
532 | int eventid; | ||
533 | void (*handler)(struct wil6210_priv *wil, int eventid, | ||
534 | void *data, int data_len); | ||
535 | } wmi_evt_handlers[] = { | ||
536 | {WMI_READY_EVENTID, wmi_evt_ready}, | ||
537 | {WMI_FW_READY_EVENTID, wmi_evt_fw_ready}, | ||
538 | {WMI_RX_MGMT_PACKET_EVENTID, wmi_evt_rx_mgmt}, | ||
539 | {WMI_SCAN_COMPLETE_EVENTID, wmi_evt_scan_complete}, | ||
540 | {WMI_CONNECT_EVENTID, wmi_evt_connect}, | ||
541 | {WMI_DISCONNECT_EVENTID, wmi_evt_disconnect}, | ||
542 | {WMI_NOTIFY_REQ_DONE_EVENTID, wmi_evt_notify}, | ||
543 | {WMI_EAPOL_RX_EVENTID, wmi_evt_eapol_rx}, | ||
544 | }; | ||
545 | |||
546 | /* | ||
547 | * Run in IRQ context | ||
548 | * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev | ||
549 | * that will be eventually handled by the @wmi_event_worker in the thread | ||
550 | * context of thread "wil6210_wmi" | ||
551 | */ | ||
552 | void wmi_recv_cmd(struct wil6210_priv *wil) | ||
553 | { | ||
554 | struct wil6210_mbox_ring_desc d_tail; | ||
555 | struct wil6210_mbox_hdr hdr; | ||
556 | struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx; | ||
557 | struct pending_wmi_event *evt; | ||
558 | u8 *cmd; | ||
559 | void __iomem *src; | ||
560 | ulong flags; | ||
561 | |||
562 | for (;;) { | ||
563 | u16 len; | ||
564 | |||
565 | r->head = ioread32(wil->csr + HOST_MBOX + | ||
566 | offsetof(struct wil6210_mbox_ctl, rx.head)); | ||
567 | if (r->tail == r->head) | ||
568 | return; | ||
569 | |||
570 | /* read cmd from tail */ | ||
571 | wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail), | ||
572 | sizeof(struct wil6210_mbox_ring_desc)); | ||
573 | if (d_tail.sync == 0) { | ||
574 | wil_err(wil, "Mbox evt not owned by FW?\n"); | ||
575 | return; | ||
576 | } | ||
577 | |||
578 | if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) { | ||
579 | wil_err(wil, "Mbox evt at 0x%08x?\n", | ||
580 | le32_to_cpu(d_tail.addr)); | ||
581 | return; | ||
582 | } | ||
583 | |||
584 | len = le16_to_cpu(hdr.len); | ||
585 | src = wmi_buffer(wil, d_tail.addr) + | ||
586 | sizeof(struct wil6210_mbox_hdr); | ||
587 | evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event, | ||
588 | event.wmi) + len, 4), | ||
589 | GFP_KERNEL); | ||
590 | if (!evt) { | ||
591 | wil_err(wil, "kmalloc for WMI event (%d) failed\n", | ||
592 | len); | ||
593 | return; | ||
594 | } | ||
595 | evt->event.hdr = hdr; | ||
596 | cmd = (void *)&evt->event.wmi; | ||
597 | wil_memcpy_fromio_32(cmd, src, len); | ||
598 | /* mark entry as empty */ | ||
599 | iowrite32(0, wil->csr + HOSTADDR(r->tail) + | ||
600 | offsetof(struct wil6210_mbox_ring_desc, sync)); | ||
601 | /* indicate */ | ||
602 | wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n", | ||
603 | le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type), | ||
604 | hdr.flags); | ||
605 | if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) && | ||
606 | (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { | ||
607 | wil_dbg_WMI(wil, "WMI event 0x%04x\n", | ||
608 | evt->event.wmi.id); | ||
609 | } | ||
610 | wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1, | ||
611 | &evt->event.hdr, sizeof(hdr) + len, true); | ||
612 | |||
613 | /* advance tail */ | ||
614 | r->tail = r->base + ((r->tail - r->base + | ||
615 | sizeof(struct wil6210_mbox_ring_desc)) % r->size); | ||
616 | iowrite32(r->tail, wil->csr + HOST_MBOX + | ||
617 | offsetof(struct wil6210_mbox_ctl, rx.tail)); | ||
618 | |||
619 | /* add to the pending list */ | ||
620 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
621 | list_add_tail(&evt->list, &wil->pending_wmi_ev); | ||
622 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
623 | { | ||
624 | int q = queue_work(wil->wmi_wq, | ||
625 | &wil->wmi_event_worker); | ||
626 | wil_dbg_WMI(wil, "queue_work -> %d\n", q); | ||
627 | } | ||
628 | } | ||
629 | } | ||
630 | |||
631 | int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len, | ||
632 | u16 reply_id, void *reply, u8 reply_size, int to_msec) | ||
633 | { | ||
634 | int rc; | ||
635 | int remain; | ||
636 | |||
637 | mutex_lock(&wil->wmi_mutex); | ||
638 | |||
639 | rc = __wmi_send(wil, cmdid, buf, len); | ||
640 | if (rc) | ||
641 | goto out; | ||
642 | |||
643 | wil->reply_id = reply_id; | ||
644 | wil->reply_buf = reply; | ||
645 | wil->reply_size = reply_size; | ||
646 | remain = wait_for_completion_timeout(&wil->wmi_ready, | ||
647 | msecs_to_jiffies(to_msec)); | ||
648 | if (0 == remain) { | ||
649 | wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n", | ||
650 | cmdid, reply_id, to_msec); | ||
651 | rc = -ETIME; | ||
652 | } else { | ||
653 | wil_dbg_WMI(wil, | ||
654 | "wmi_call(0x%04x->0x%04x) completed in %d msec\n", | ||
655 | cmdid, reply_id, | ||
656 | to_msec - jiffies_to_msecs(remain)); | ||
657 | } | ||
658 | wil->reply_id = 0; | ||
659 | wil->reply_buf = NULL; | ||
660 | wil->reply_size = 0; | ||
661 | out: | ||
662 | mutex_unlock(&wil->wmi_mutex); | ||
663 | |||
664 | return rc; | ||
665 | } | ||
666 | |||
667 | int wmi_echo(struct wil6210_priv *wil) | ||
668 | { | ||
669 | struct wmi_echo_cmd cmd = { | ||
670 | .value = cpu_to_le32(0x12345678), | ||
671 | }; | ||
672 | |||
673 | return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd), | ||
674 | WMI_ECHO_RSP_EVENTID, NULL, 0, 20); | ||
675 | } | ||
676 | |||
677 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr) | ||
678 | { | ||
679 | struct wmi_set_mac_address_cmd cmd; | ||
680 | |||
681 | memcpy(cmd.mac, addr, ETH_ALEN); | ||
682 | |||
683 | wil_dbg_WMI(wil, "Set MAC %pM\n", addr); | ||
684 | |||
685 | return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd)); | ||
686 | } | ||
687 | |||
688 | int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype) | ||
689 | { | ||
690 | struct wmi_bcon_ctrl_cmd cmd = { | ||
691 | .bcon_interval = cpu_to_le16(bi), | ||
692 | .network_type = wmi_nettype, | ||
693 | .disable_sec_offload = 1, | ||
694 | }; | ||
695 | |||
696 | if (!wil->secure_pcp) | ||
697 | cmd.disable_sec = 1; | ||
698 | |||
699 | return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd)); | ||
700 | } | ||
701 | |||
702 | int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid) | ||
703 | { | ||
704 | struct wmi_set_ssid_cmd cmd = { | ||
705 | .ssid_len = cpu_to_le32(ssid_len), | ||
706 | }; | ||
707 | |||
708 | if (ssid_len > sizeof(cmd.ssid)) | ||
709 | return -EINVAL; | ||
710 | |||
711 | memcpy(cmd.ssid, ssid, ssid_len); | ||
712 | |||
713 | return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd)); | ||
714 | } | ||
715 | |||
716 | int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid) | ||
717 | { | ||
718 | int rc; | ||
719 | struct { | ||
720 | struct wil6210_mbox_hdr_wmi wmi; | ||
721 | struct wmi_set_ssid_cmd cmd; | ||
722 | } __packed reply; | ||
723 | int len; /* reply.cmd.ssid_len in CPU order */ | ||
724 | |||
725 | rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID, | ||
726 | &reply, sizeof(reply), 20); | ||
727 | if (rc) | ||
728 | return rc; | ||
729 | |||
730 | len = le32_to_cpu(reply.cmd.ssid_len); | ||
731 | if (len > sizeof(reply.cmd.ssid)) | ||
732 | return -EINVAL; | ||
733 | |||
734 | *ssid_len = len; | ||
735 | memcpy(ssid, reply.cmd.ssid, len); | ||
736 | |||
737 | return 0; | ||
738 | } | ||
739 | |||
740 | int wmi_set_channel(struct wil6210_priv *wil, int channel) | ||
741 | { | ||
742 | struct wmi_set_pcp_channel_cmd cmd = { | ||
743 | .channel = channel - 1, | ||
744 | }; | ||
745 | |||
746 | return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd)); | ||
747 | } | ||
748 | |||
749 | int wmi_get_channel(struct wil6210_priv *wil, int *channel) | ||
750 | { | ||
751 | int rc; | ||
752 | struct { | ||
753 | struct wil6210_mbox_hdr_wmi wmi; | ||
754 | struct wmi_set_pcp_channel_cmd cmd; | ||
755 | } __packed reply; | ||
756 | |||
757 | rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0, | ||
758 | WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20); | ||
759 | if (rc) | ||
760 | return rc; | ||
761 | |||
762 | if (reply.cmd.channel > 3) | ||
763 | return -EINVAL; | ||
764 | |||
765 | *channel = reply.cmd.channel + 1; | ||
766 | |||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb) | ||
771 | { | ||
772 | struct wmi_eapol_tx_cmd *cmd; | ||
773 | struct ethhdr *eth; | ||
774 | u16 eapol_len = skb->len - ETH_HLEN; | ||
775 | void *eapol = skb->data + ETH_HLEN; | ||
776 | uint i; | ||
777 | int rc; | ||
778 | |||
779 | skb_set_mac_header(skb, 0); | ||
780 | eth = eth_hdr(skb); | ||
781 | wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest); | ||
782 | for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) { | ||
783 | if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0) | ||
784 | goto found_dest; | ||
785 | } | ||
786 | |||
787 | return -EINVAL; | ||
788 | |||
789 | found_dest: | ||
790 | /* find out eapol data & len */ | ||
791 | cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL); | ||
792 | if (!cmd) | ||
793 | return -EINVAL; | ||
794 | |||
795 | memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN); | ||
796 | cmd->eapol_len = cpu_to_le16(eapol_len); | ||
797 | memcpy(cmd->eapol, eapol, eapol_len); | ||
798 | rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len); | ||
799 | kfree(cmd); | ||
800 | |||
801 | return rc; | ||
802 | } | ||
803 | |||
804 | int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
805 | const void *mac_addr) | ||
806 | { | ||
807 | struct wmi_delete_cipher_key_cmd cmd = { | ||
808 | .key_index = key_index, | ||
809 | }; | ||
810 | |||
811 | if (mac_addr) | ||
812 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | ||
813 | |||
814 | return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | ||
815 | } | ||
816 | |||
817 | int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index, | ||
818 | const void *mac_addr, int key_len, const void *key) | ||
819 | { | ||
820 | struct wmi_add_cipher_key_cmd cmd = { | ||
821 | .key_index = key_index, | ||
822 | .key_usage = WMI_KEY_USE_PAIRWISE, | ||
823 | .key_len = key_len, | ||
824 | }; | ||
825 | |||
826 | if (!key || (key_len > sizeof(cmd.key))) | ||
827 | return -EINVAL; | ||
828 | |||
829 | memcpy(cmd.key, key, key_len); | ||
830 | if (mac_addr) | ||
831 | memcpy(cmd.mac, mac_addr, WMI_MAC_LEN); | ||
832 | |||
833 | return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd)); | ||
834 | } | ||
835 | |||
836 | int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie) | ||
837 | { | ||
838 | int rc; | ||
839 | u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len; | ||
840 | struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL); | ||
841 | if (!cmd) { | ||
842 | wil_err(wil, "kmalloc(%d) failed\n", len); | ||
843 | return -ENOMEM; | ||
844 | } | ||
845 | |||
846 | cmd->mgmt_frm_type = type; | ||
847 | /* BUG: FW API define ieLen as u8. Will fix FW */ | ||
848 | cmd->ie_len = cpu_to_le16(ie_len); | ||
849 | memcpy(cmd->ie_info, ie, ie_len); | ||
850 | rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len); | ||
851 | kfree(cmd); | ||
852 | |||
853 | return rc; | ||
854 | } | ||
855 | |||
856 | void wmi_event_flush(struct wil6210_priv *wil) | ||
857 | { | ||
858 | struct pending_wmi_event *evt, *t; | ||
859 | |||
860 | wil_dbg_WMI(wil, "%s()\n", __func__); | ||
861 | |||
862 | list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) { | ||
863 | list_del(&evt->list); | ||
864 | kfree(evt); | ||
865 | } | ||
866 | } | ||
867 | |||
868 | static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id, | ||
869 | void *d, int len) | ||
870 | { | ||
871 | uint i; | ||
872 | |||
873 | for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) { | ||
874 | if (wmi_evt_handlers[i].eventid == id) { | ||
875 | wmi_evt_handlers[i].handler(wil, id, d, len); | ||
876 | return true; | ||
877 | } | ||
878 | } | ||
879 | |||
880 | return false; | ||
881 | } | ||
882 | |||
883 | static void wmi_event_handle(struct wil6210_priv *wil, | ||
884 | struct wil6210_mbox_hdr *hdr) | ||
885 | { | ||
886 | u16 len = le16_to_cpu(hdr->len); | ||
887 | |||
888 | if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) && | ||
889 | (len >= sizeof(struct wil6210_mbox_hdr_wmi))) { | ||
890 | struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]); | ||
891 | void *evt_data = (void *)(&wmi[1]); | ||
892 | u16 id = le16_to_cpu(wmi->id); | ||
893 | /* check if someone waits for this event */ | ||
894 | if (wil->reply_id && wil->reply_id == id) { | ||
895 | if (wil->reply_buf) { | ||
896 | memcpy(wil->reply_buf, wmi, | ||
897 | min(len, wil->reply_size)); | ||
898 | } else { | ||
899 | wmi_evt_call_handler(wil, id, evt_data, | ||
900 | len - sizeof(*wmi)); | ||
901 | } | ||
902 | wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id); | ||
903 | complete(&wil->wmi_ready); | ||
904 | return; | ||
905 | } | ||
906 | /* unsolicited event */ | ||
907 | /* search for handler */ | ||
908 | if (!wmi_evt_call_handler(wil, id, evt_data, | ||
909 | len - sizeof(*wmi))) { | ||
910 | wil_err(wil, "Unhandled event 0x%04x\n", id); | ||
911 | } | ||
912 | } else { | ||
913 | wil_err(wil, "Unknown event type\n"); | ||
914 | print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1, | ||
915 | hdr, sizeof(*hdr) + len, true); | ||
916 | } | ||
917 | } | ||
918 | |||
919 | /* | ||
920 | * Retrieve next WMI event from the pending list | ||
921 | */ | ||
922 | static struct list_head *next_wmi_ev(struct wil6210_priv *wil) | ||
923 | { | ||
924 | ulong flags; | ||
925 | struct list_head *ret = NULL; | ||
926 | |||
927 | spin_lock_irqsave(&wil->wmi_ev_lock, flags); | ||
928 | |||
929 | if (!list_empty(&wil->pending_wmi_ev)) { | ||
930 | ret = wil->pending_wmi_ev.next; | ||
931 | list_del(ret); | ||
932 | } | ||
933 | |||
934 | spin_unlock_irqrestore(&wil->wmi_ev_lock, flags); | ||
935 | |||
936 | return ret; | ||
937 | } | ||
938 | |||
939 | /* | ||
940 | * Handler for the WMI events | ||
941 | */ | ||
942 | void wmi_event_worker(struct work_struct *work) | ||
943 | { | ||
944 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
945 | wmi_event_worker); | ||
946 | struct pending_wmi_event *evt; | ||
947 | struct list_head *lh; | ||
948 | |||
949 | while ((lh = next_wmi_ev(wil)) != NULL) { | ||
950 | evt = list_entry(lh, struct pending_wmi_event, list); | ||
951 | wmi_event_handle(wil, &evt->event.hdr); | ||
952 | kfree(evt); | ||
953 | } | ||
954 | } | ||
955 | |||
956 | void wmi_connect_worker(struct work_struct *work) | ||
957 | { | ||
958 | int rc; | ||
959 | struct wil6210_priv *wil = container_of(work, struct wil6210_priv, | ||
960 | wmi_connect_worker); | ||
961 | |||
962 | if (wil->pending_connect_cid < 0) { | ||
963 | wil_err(wil, "No connection pending\n"); | ||
964 | return; | ||
965 | } | ||
966 | |||
967 | wil_dbg_WMI(wil, "Configure for connection CID %d\n", | ||
968 | wil->pending_connect_cid); | ||
969 | |||
970 | rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE, | ||
971 | wil->pending_connect_cid, 0); | ||
972 | wil->pending_connect_cid = -1; | ||
973 | if (rc == 0) | ||
974 | wil_link_on(wil); | ||
975 | } | ||
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h new file mode 100644 index 000000000000..3bbf87572b07 --- /dev/null +++ b/drivers/net/wireless/ath/wil6210/wmi.h | |||
@@ -0,0 +1,1116 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2012 Qualcomm Atheros, Inc. | ||
3 | * Copyright (c) 2006-2012 Wilocity . | ||
4 | * | ||
5 | * Permission to use, copy, modify, and/or distribute this software for any | ||
6 | * purpose with or without fee is hereby granted, provided that the above | ||
7 | * copyright notice and this permission notice appear in all copies. | ||
8 | * | ||
9 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
10 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
11 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
12 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
13 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
14 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
15 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
16 | */ | ||
17 | |||
18 | /* | ||
19 | * This file contains the definitions of the WMI protocol specified in the | ||
20 | * Wireless Module Interface (WMI) for the Wilocity | ||
21 | * MARLON 60 Gigabit wireless solution. | ||
22 | * It includes definitions of all the commands and events. | ||
23 | * Commands are messages from the host to the WM. | ||
24 | * Events are messages from the WM to the host. | ||
25 | */ | ||
26 | |||
27 | #ifndef __WILOCITY_WMI_H__ | ||
28 | #define __WILOCITY_WMI_H__ | ||
29 | |||
30 | /* General */ | ||
31 | |||
32 | #define WMI_MAC_LEN (6) | ||
33 | #define WMI_PROX_RANGE_NUM (3) | ||
34 | |||
35 | /* List of Commands */ | ||
36 | enum wmi_command_id { | ||
37 | WMI_CONNECT_CMDID = 0x0001, | ||
38 | WMI_DISCONNECT_CMDID = 0x0003, | ||
39 | WMI_START_SCAN_CMDID = 0x0007, | ||
40 | WMI_SET_BSS_FILTER_CMDID = 0x0009, | ||
41 | WMI_SET_PROBED_SSID_CMDID = 0x000a, | ||
42 | WMI_SET_LISTEN_INT_CMDID = 0x000b, | ||
43 | WMI_BCON_CTRL_CMDID = 0x000f, | ||
44 | WMI_ADD_CIPHER_KEY_CMDID = 0x0016, | ||
45 | WMI_DELETE_CIPHER_KEY_CMDID = 0x0017, | ||
46 | WMI_SET_APPIE_CMDID = 0x003f, | ||
47 | WMI_GET_APPIE_CMDID = 0x0040, | ||
48 | WMI_SET_WSC_STATUS_CMDID = 0x0041, | ||
49 | WMI_PXMT_RANGE_CFG_CMDID = 0x0042, | ||
50 | WMI_PXMT_SNR2_RANGE_CFG_CMDID = 0x0043, | ||
51 | WMI_FAST_MEM_ACC_MODE_CMDID = 0x0300, | ||
52 | WMI_MEM_READ_CMDID = 0x0800, | ||
53 | WMI_MEM_WR_CMDID = 0x0801, | ||
54 | WMI_ECHO_CMDID = 0x0803, | ||
55 | WMI_DEEP_ECHO_CMDID = 0x0804, | ||
56 | WMI_CONFIG_MAC_CMDID = 0x0805, | ||
57 | WMI_CONFIG_PHY_DEBUG_CMDID = 0x0806, | ||
58 | WMI_ADD_STATION_CMDID = 0x0807, | ||
59 | WMI_ADD_DEBUG_TX_PCKT_CMDID = 0x0808, | ||
60 | WMI_PHY_GET_STATISTICS_CMDID = 0x0809, | ||
61 | WMI_FS_TUNE_CMDID = 0x080a, | ||
62 | WMI_CORR_MEASURE_CMDID = 0x080b, | ||
63 | WMI_TEMP_SENSE_CMDID = 0x080e, | ||
64 | WMI_DC_CALIB_CMDID = 0x080f, | ||
65 | WMI_SEND_TONE_CMDID = 0x0810, | ||
66 | WMI_IQ_TX_CALIB_CMDID = 0x0811, | ||
67 | WMI_IQ_RX_CALIB_CMDID = 0x0812, | ||
68 | WMI_SET_UCODE_IDLE_CMDID = 0x0813, | ||
69 | WMI_SET_WORK_MODE_CMDID = 0x0815, | ||
70 | WMI_LO_LEAKAGE_CALIB_CMDID = 0x0816, | ||
71 | WMI_MARLON_R_ACTIVATE_CMDID = 0x0817, | ||
72 | WMI_MARLON_R_READ_CMDID = 0x0818, | ||
73 | WMI_MARLON_R_WRITE_CMDID = 0x0819, | ||
74 | WMI_MARLON_R_TXRX_SEL_CMDID = 0x081a, | ||
75 | MAC_IO_STATIC_PARAMS_CMDID = 0x081b, | ||
76 | MAC_IO_DYNAMIC_PARAMS_CMDID = 0x081c, | ||
77 | WMI_SILENT_RSSI_CALIB_CMDID = 0x081d, | ||
78 | WMI_CFG_RX_CHAIN_CMDID = 0x0820, | ||
79 | WMI_VRING_CFG_CMDID = 0x0821, | ||
80 | WMI_RX_ON_CMDID = 0x0822, | ||
81 | WMI_VRING_BA_EN_CMDID = 0x0823, | ||
82 | WMI_VRING_BA_DIS_CMDID = 0x0824, | ||
83 | WMI_RCP_ADDBA_RESP_CMDID = 0x0825, | ||
84 | WMI_RCP_DELBA_CMDID = 0x0826, | ||
85 | WMI_SET_SSID_CMDID = 0x0827, | ||
86 | WMI_GET_SSID_CMDID = 0x0828, | ||
87 | WMI_SET_PCP_CHANNEL_CMDID = 0x0829, | ||
88 | WMI_GET_PCP_CHANNEL_CMDID = 0x082a, | ||
89 | WMI_SW_TX_REQ_CMDID = 0x082b, | ||
90 | WMI_RX_OFF_CMDID = 0x082c, | ||
91 | WMI_READ_MAC_RXQ_CMDID = 0x0830, | ||
92 | WMI_READ_MAC_TXQ_CMDID = 0x0831, | ||
93 | WMI_WRITE_MAC_RXQ_CMDID = 0x0832, | ||
94 | WMI_WRITE_MAC_TXQ_CMDID = 0x0833, | ||
95 | WMI_WRITE_MAC_XQ_FIELD_CMDID = 0x0834, | ||
96 | WMI_MLME_PUSH_CMDID = 0x0835, | ||
97 | WMI_BEAMFORMING_MGMT_CMDID = 0x0836, | ||
98 | WMI_BF_TXSS_MGMT_CMDID = 0x0837, | ||
99 | WMI_BF_SM_MGMT_CMDID = 0x0838, | ||
100 | WMI_BF_RXSS_MGMT_CMDID = 0x0839, | ||
101 | WMI_SET_SECTORS_CMDID = 0x0849, | ||
102 | WMI_MAINTAIN_PAUSE_CMDID = 0x0850, | ||
103 | WMI_MAINTAIN_RESUME_CMDID = 0x0851, | ||
104 | WMI_RS_MGMT_CMDID = 0x0852, | ||
105 | WMI_RF_MGMT_CMDID = 0x0853, | ||
106 | /* Performance monitoring commands */ | ||
107 | WMI_BF_CTRL_CMDID = 0x0862, | ||
108 | WMI_NOTIFY_REQ_CMDID = 0x0863, | ||
109 | WMI_GET_STATUS_CMDID = 0x0864, | ||
110 | WMI_UNIT_TEST_CMDID = 0x0900, | ||
111 | WMI_HICCUP_CMDID = 0x0901, | ||
112 | WMI_FLASH_READ_CMDID = 0x0902, | ||
113 | WMI_FLASH_WRITE_CMDID = 0x0903, | ||
114 | WMI_SECURITY_UNIT_TEST_CMDID = 0x0904, | ||
115 | |||
116 | WMI_SET_MAC_ADDRESS_CMDID = 0xf003, | ||
117 | WMI_ABORT_SCAN_CMDID = 0xf007, | ||
118 | WMI_SET_PMK_CMDID = 0xf028, | ||
119 | |||
120 | WMI_SET_PROMISCUOUS_MODE_CMDID = 0xf041, | ||
121 | WMI_GET_PMK_CMDID = 0xf048, | ||
122 | WMI_SET_PASSPHRASE_CMDID = 0xf049, | ||
123 | WMI_SEND_ASSOC_RES_CMDID = 0xf04a, | ||
124 | WMI_SET_ASSOC_REQ_RELAY_CMDID = 0xf04b, | ||
125 | WMI_EAPOL_TX_CMDID = 0xf04c, | ||
126 | WMI_MAC_ADDR_REQ_CMDID = 0xf04d, | ||
127 | WMI_FW_VER_CMDID = 0xf04e, | ||
128 | }; | ||
129 | |||
130 | /* | ||
131 | * Commands data structures | ||
132 | */ | ||
133 | |||
134 | /* | ||
135 | * Frame Types | ||
136 | */ | ||
137 | enum wmi_mgmt_frame_type { | ||
138 | WMI_FRAME_BEACON = 0, | ||
139 | WMI_FRAME_PROBE_REQ = 1, | ||
140 | WMI_FRAME_PROBE_RESP = 2, | ||
141 | WMI_FRAME_ASSOC_REQ = 3, | ||
142 | WMI_FRAME_ASSOC_RESP = 4, | ||
143 | WMI_NUM_MGMT_FRAME, | ||
144 | }; | ||
145 | |||
146 | /* | ||
147 | * WMI_CONNECT_CMDID | ||
148 | */ | ||
149 | enum wmi_network_type { | ||
150 | WMI_NETTYPE_INFRA = 0x01, | ||
151 | WMI_NETTYPE_ADHOC = 0x02, | ||
152 | WMI_NETTYPE_ADHOC_CREATOR = 0x04, | ||
153 | WMI_NETTYPE_AP = 0x10, | ||
154 | WMI_NETTYPE_P2P = 0x20, | ||
155 | WMI_NETTYPE_WBE = 0x40, /* PCIE over 60g */ | ||
156 | }; | ||
157 | |||
158 | enum wmi_dot11_auth_mode { | ||
159 | WMI_AUTH11_OPEN = 0x01, | ||
160 | WMI_AUTH11_SHARED = 0x02, | ||
161 | WMI_AUTH11_LEAP = 0x04, | ||
162 | WMI_AUTH11_WSC = 0x08, | ||
163 | }; | ||
164 | |||
165 | enum wmi_auth_mode { | ||
166 | WMI_AUTH_NONE = 0x01, | ||
167 | WMI_AUTH_WPA = 0x02, | ||
168 | WMI_AUTH_WPA2 = 0x04, | ||
169 | WMI_AUTH_WPA_PSK = 0x08, | ||
170 | WMI_AUTH_WPA2_PSK = 0x10, | ||
171 | WMI_AUTH_WPA_CCKM = 0x20, | ||
172 | WMI_AUTH_WPA2_CCKM = 0x40, | ||
173 | }; | ||
174 | |||
175 | enum wmi_crypto_type { | ||
176 | WMI_CRYPT_NONE = 0x01, | ||
177 | WMI_CRYPT_WEP = 0x02, | ||
178 | WMI_CRYPT_TKIP = 0x04, | ||
179 | WMI_CRYPT_AES = 0x08, | ||
180 | WMI_CRYPT_AES_GCMP = 0x20, | ||
181 | }; | ||
182 | |||
183 | |||
184 | enum wmi_connect_ctrl_flag_bits { | ||
185 | WMI_CONNECT_ASSOC_POLICY_USER = 0x0001, | ||
186 | WMI_CONNECT_SEND_REASSOC = 0x0002, | ||
187 | WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004, | ||
188 | WMI_CONNECT_PROFILE_MATCH_DONE = 0x0008, | ||
189 | WMI_CONNECT_IGNORE_AAC_BEACON = 0x0010, | ||
190 | WMI_CONNECT_CSA_FOLLOW_BSS = 0x0020, | ||
191 | WMI_CONNECT_DO_WPA_OFFLOAD = 0x0040, | ||
192 | WMI_CONNECT_DO_NOT_DEAUTH = 0x0080, | ||
193 | }; | ||
194 | |||
195 | #define WMI_MAX_SSID_LEN (32) | ||
196 | |||
197 | struct wmi_connect_cmd { | ||
198 | u8 network_type; | ||
199 | u8 dot11_auth_mode; | ||
200 | u8 auth_mode; | ||
201 | u8 pairwise_crypto_type; | ||
202 | u8 pairwise_crypto_len; | ||
203 | u8 group_crypto_type; | ||
204 | u8 group_crypto_len; | ||
205 | u8 ssid_len; | ||
206 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
207 | u8 channel; | ||
208 | u8 reserved0; | ||
209 | u8 bssid[WMI_MAC_LEN]; | ||
210 | __le32 ctrl_flags; | ||
211 | u8 dst_mac[WMI_MAC_LEN]; | ||
212 | u8 reserved1[2]; | ||
213 | } __packed; | ||
214 | |||
215 | |||
216 | /* | ||
217 | * WMI_RECONNECT_CMDID | ||
218 | */ | ||
219 | struct wmi_reconnect_cmd { | ||
220 | u8 channel; /* hint */ | ||
221 | u8 reserved; | ||
222 | u8 bssid[WMI_MAC_LEN]; /* mandatory if set */ | ||
223 | } __packed; | ||
224 | |||
225 | |||
226 | /* | ||
227 | * WMI_SET_PMK_CMDID | ||
228 | */ | ||
229 | |||
230 | #define WMI_MIN_KEY_INDEX (0) | ||
231 | #define WMI_MAX_KEY_INDEX (3) | ||
232 | #define WMI_MAX_KEY_LEN (32) | ||
233 | #define WMI_PASSPHRASE_LEN (64) | ||
234 | #define WMI_PMK_LEN (32) | ||
235 | |||
236 | struct wmi_set_pmk_cmd { | ||
237 | u8 pmk[WMI_PMK_LEN]; | ||
238 | } __packed; | ||
239 | |||
240 | |||
241 | /* | ||
242 | * WMI_SET_PASSPHRASE_CMDID | ||
243 | */ | ||
244 | struct wmi_set_passphrase_cmd { | ||
245 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
246 | u8 passphrase[WMI_PASSPHRASE_LEN]; | ||
247 | u8 ssid_len; | ||
248 | u8 passphrase_len; | ||
249 | } __packed; | ||
250 | |||
251 | /* | ||
252 | * WMI_ADD_CIPHER_KEY_CMDID | ||
253 | */ | ||
254 | enum wmi_key_usage { | ||
255 | WMI_KEY_USE_PAIRWISE = 0, | ||
256 | WMI_KEY_USE_GROUP = 1, | ||
257 | WMI_KEY_USE_TX = 2, /* default Tx Key - Static WEP only */ | ||
258 | }; | ||
259 | |||
260 | struct wmi_add_cipher_key_cmd { | ||
261 | u8 key_index; | ||
262 | u8 key_type; | ||
263 | u8 key_usage; /* enum wmi_key_usage */ | ||
264 | u8 key_len; | ||
265 | u8 key_rsc[8]; /* key replay sequence counter */ | ||
266 | u8 key[WMI_MAX_KEY_LEN]; | ||
267 | u8 key_op_ctrl; /* Additional Key Control information */ | ||
268 | u8 mac[WMI_MAC_LEN]; | ||
269 | } __packed; | ||
270 | |||
271 | /* | ||
272 | * WMI_DELETE_CIPHER_KEY_CMDID | ||
273 | */ | ||
274 | struct wmi_delete_cipher_key_cmd { | ||
275 | u8 key_index; | ||
276 | u8 mac[WMI_MAC_LEN]; | ||
277 | } __packed; | ||
278 | |||
279 | |||
280 | /* | ||
281 | * WMI_START_SCAN_CMDID | ||
282 | * | ||
283 | * Start L1 scan operation | ||
284 | * | ||
285 | * Returned events: | ||
286 | * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp. | ||
287 | * - WMI_SCAN_COMPLETE_EVENTID | ||
288 | */ | ||
289 | enum wmi_scan_type { | ||
290 | WMI_LONG_SCAN = 0, | ||
291 | WMI_SHORT_SCAN = 1, | ||
292 | }; | ||
293 | |||
294 | struct wmi_start_scan_cmd { | ||
295 | u8 reserved[8]; | ||
296 | __le32 home_dwell_time; /* Max duration in the home channel(ms) */ | ||
297 | __le32 force_scan_interval; /* Time interval between scans (ms)*/ | ||
298 | u8 scan_type; /* wmi_scan_type */ | ||
299 | u8 num_channels; /* how many channels follow */ | ||
300 | struct { | ||
301 | u8 channel; | ||
302 | u8 reserved; | ||
303 | } channel_list[0]; /* channels ID's */ | ||
304 | /* 0 - 58320 MHz */ | ||
305 | /* 1 - 60480 MHz */ | ||
306 | /* 2 - 62640 MHz */ | ||
307 | } __packed; | ||
308 | |||
309 | /* | ||
310 | * WMI_SET_PROBED_SSID_CMDID | ||
311 | */ | ||
312 | #define MAX_PROBED_SSID_INDEX (15) | ||
313 | |||
314 | enum wmi_ssid_flag { | ||
315 | WMI_SSID_FLAG_DISABLE = 0, /* disables entry */ | ||
316 | WMI_SSID_FLAG_SPECIFIC = 1, /* probes specified ssid */ | ||
317 | WMI_SSID_FLAG_ANY = 2, /* probes for any ssid */ | ||
318 | }; | ||
319 | |||
320 | struct wmi_probed_ssid_cmd { | ||
321 | u8 entry_index; /* 0 to MAX_PROBED_SSID_INDEX */ | ||
322 | u8 flag; /* enum wmi_ssid_flag */ | ||
323 | u8 ssid_len; | ||
324 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
325 | } __packed; | ||
326 | |||
327 | /* | ||
328 | * WMI_SET_APPIE_CMDID | ||
329 | * Add Application specified IE to a management frame | ||
330 | */ | ||
331 | struct wmi_set_appie_cmd { | ||
332 | u8 mgmt_frm_type; /* enum wmi_mgmt_frame_type */ | ||
333 | u8 reserved; | ||
334 | __le16 ie_len; /* Length of the IE to be added to MGMT frame */ | ||
335 | u8 ie_info[0]; | ||
336 | } __packed; | ||
337 | |||
338 | #define WMI_MAX_IE_LEN (1024) | ||
339 | |||
340 | struct wmi_pxmt_range_cfg_cmd { | ||
341 | u8 dst_mac[WMI_MAC_LEN]; | ||
342 | __le16 range; | ||
343 | } __packed; | ||
344 | |||
345 | struct wmi_pxmt_snr2_range_cfg_cmd { | ||
346 | s8 snr2range_arr[WMI_PROX_RANGE_NUM-1]; | ||
347 | } __packed; | ||
348 | |||
349 | /* | ||
350 | * WMI_RF_MGMT_CMDID | ||
351 | */ | ||
352 | enum wmi_rf_mgmt_type { | ||
353 | WMI_RF_MGMT_W_DISABLE = 0, | ||
354 | WMI_RF_MGMT_W_ENABLE = 1, | ||
355 | WMI_RF_MGMT_GET_STATUS = 2, | ||
356 | }; | ||
357 | |||
358 | struct wmi_rf_mgmt_cmd { | ||
359 | __le32 rf_mgmt_type; | ||
360 | } __packed; | ||
361 | |||
362 | /* | ||
363 | * WMI_SET_SSID_CMDID | ||
364 | */ | ||
365 | struct wmi_set_ssid_cmd { | ||
366 | __le32 ssid_len; | ||
367 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
368 | } __packed; | ||
369 | |||
370 | /* | ||
371 | * WMI_SET_PCP_CHANNEL_CMDID | ||
372 | */ | ||
373 | struct wmi_set_pcp_channel_cmd { | ||
374 | u8 channel; | ||
375 | u8 reserved[3]; | ||
376 | } __packed; | ||
377 | |||
378 | /* | ||
379 | * WMI_BCON_CTRL_CMDID | ||
380 | */ | ||
381 | struct wmi_bcon_ctrl_cmd { | ||
382 | __le16 bcon_interval; | ||
383 | __le16 frag_num; | ||
384 | __le64 ss_mask; | ||
385 | u8 network_type; | ||
386 | u8 reserved; | ||
387 | u8 disable_sec_offload; | ||
388 | u8 disable_sec; | ||
389 | } __packed; | ||
390 | |||
391 | /* | ||
392 | * WMI_SW_TX_REQ_CMDID | ||
393 | */ | ||
394 | struct wmi_sw_tx_req_cmd { | ||
395 | u8 dst_mac[WMI_MAC_LEN]; | ||
396 | __le16 len; | ||
397 | u8 payload[0]; | ||
398 | } __packed; | ||
399 | |||
400 | /* | ||
401 | * WMI_VRING_CFG_CMDID | ||
402 | */ | ||
403 | |||
404 | struct wmi_sw_ring_cfg { | ||
405 | __le64 ring_mem_base; | ||
406 | __le16 ring_size; | ||
407 | __le16 max_mpdu_size; | ||
408 | } __packed; | ||
409 | |||
410 | struct wmi_vring_cfg_schd { | ||
411 | __le16 priority; | ||
412 | __le16 timeslot_us; | ||
413 | } __packed; | ||
414 | |||
415 | enum wmi_vring_cfg_encap_trans_type { | ||
416 | WMI_VRING_ENC_TYPE_802_3 = 0, | ||
417 | WMI_VRING_ENC_TYPE_NATIVE_WIFI = 1, | ||
418 | }; | ||
419 | |||
420 | enum wmi_vring_cfg_ds_cfg { | ||
421 | WMI_VRING_DS_PBSS = 0, | ||
422 | WMI_VRING_DS_STATION = 1, | ||
423 | WMI_VRING_DS_AP = 2, | ||
424 | WMI_VRING_DS_ADDR4 = 3, | ||
425 | }; | ||
426 | |||
427 | enum wmi_vring_cfg_nwifi_ds_trans_type { | ||
428 | WMI_NWIFI_TX_TRANS_MODE_NO = 0, | ||
429 | WMI_NWIFI_TX_TRANS_MODE_AP2PBSS = 1, | ||
430 | WMI_NWIFI_TX_TRANS_MODE_STA2PBSS = 2, | ||
431 | }; | ||
432 | |||
433 | enum wmi_vring_cfg_schd_params_priority { | ||
434 | WMI_SCH_PRIO_REGULAR = 0, | ||
435 | WMI_SCH_PRIO_HIGH = 1, | ||
436 | }; | ||
437 | |||
438 | struct wmi_vring_cfg { | ||
439 | struct wmi_sw_ring_cfg tx_sw_ring; | ||
440 | u8 ringid; /* 0-23 vrings */ | ||
441 | |||
442 | #define CIDXTID_CID_POS (0) | ||
443 | #define CIDXTID_CID_LEN (4) | ||
444 | #define CIDXTID_CID_MSK (0xF) | ||
445 | #define CIDXTID_TID_POS (4) | ||
446 | #define CIDXTID_TID_LEN (4) | ||
447 | #define CIDXTID_TID_MSK (0xF0) | ||
448 | u8 cidxtid; | ||
449 | |||
450 | u8 encap_trans_type; | ||
451 | u8 ds_cfg; /* 802.3 DS cfg */ | ||
452 | u8 nwifi_ds_trans_type; | ||
453 | |||
454 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0) | ||
455 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1) | ||
456 | #define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1) | ||
457 | #define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1) | ||
458 | #define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1) | ||
459 | #define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2) | ||
460 | u8 mac_ctrl; | ||
461 | |||
462 | #define VRING_CFG_TO_RESOLUTION_VALUE_POS (0) | ||
463 | #define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6) | ||
464 | #define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F) | ||
465 | u8 to_resolution; | ||
466 | u8 agg_max_wsize; | ||
467 | struct wmi_vring_cfg_schd schd_params; | ||
468 | } __packed; | ||
469 | |||
470 | enum wmi_vring_cfg_cmd_action { | ||
471 | WMI_VRING_CMD_ADD = 0, | ||
472 | WMI_VRING_CMD_MODIFY = 1, | ||
473 | WMI_VRING_CMD_DELETE = 2, | ||
474 | }; | ||
475 | |||
476 | struct wmi_vring_cfg_cmd { | ||
477 | __le32 action; | ||
478 | struct wmi_vring_cfg vring_cfg; | ||
479 | } __packed; | ||
480 | |||
481 | /* | ||
482 | * WMI_VRING_BA_EN_CMDID | ||
483 | */ | ||
484 | struct wmi_vring_ba_en_cmd { | ||
485 | u8 ringid; | ||
486 | u8 agg_max_wsize; | ||
487 | __le16 ba_timeout; | ||
488 | } __packed; | ||
489 | |||
490 | /* | ||
491 | * WMI_VRING_BA_DIS_CMDID | ||
492 | */ | ||
493 | struct wmi_vring_ba_dis_cmd { | ||
494 | u8 ringid; | ||
495 | u8 reserved; | ||
496 | __le16 reason; | ||
497 | } __packed; | ||
498 | |||
499 | /* | ||
500 | * WMI_NOTIFY_REQ_CMDID | ||
501 | */ | ||
502 | struct wmi_notify_req_cmd { | ||
503 | u8 cid; | ||
504 | u8 reserved[3]; | ||
505 | __le32 interval_usec; | ||
506 | } __packed; | ||
507 | |||
508 | /* | ||
509 | * WMI_CFG_RX_CHAIN_CMDID | ||
510 | */ | ||
511 | enum wmi_sniffer_cfg_mode { | ||
512 | WMI_SNIFFER_OFF = 0, | ||
513 | WMI_SNIFFER_ON = 1, | ||
514 | }; | ||
515 | |||
516 | enum wmi_sniffer_cfg_phy_info_mode { | ||
517 | WMI_SNIFFER_PHY_INFO_DISABLED = 0, | ||
518 | WMI_SNIFFER_PHY_INFO_ENABLED = 1, | ||
519 | }; | ||
520 | |||
521 | enum wmi_sniffer_cfg_phy_support { | ||
522 | WMI_SNIFFER_CP = 0, | ||
523 | WMI_SNIFFER_DP = 1, | ||
524 | WMI_SNIFFER_BOTH_PHYS = 2, | ||
525 | }; | ||
526 | |||
527 | struct wmi_sniffer_cfg { | ||
528 | __le32 mode; /* enum wmi_sniffer_cfg_mode */ | ||
529 | __le32 phy_info_mode; /* enum wmi_sniffer_cfg_phy_info_mode */ | ||
530 | __le32 phy_support; /* enum wmi_sniffer_cfg_phy_support */ | ||
531 | u8 channel; | ||
532 | u8 reserved[3]; | ||
533 | } __packed; | ||
534 | |||
535 | enum wmi_cfg_rx_chain_cmd_action { | ||
536 | WMI_RX_CHAIN_ADD = 0, | ||
537 | WMI_RX_CHAIN_DEL = 1, | ||
538 | }; | ||
539 | |||
540 | enum wmi_cfg_rx_chain_cmd_decap_trans_type { | ||
541 | WMI_DECAP_TYPE_802_3 = 0, | ||
542 | WMI_DECAP_TYPE_NATIVE_WIFI = 1, | ||
543 | }; | ||
544 | |||
545 | enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type { | ||
546 | WMI_NWIFI_RX_TRANS_MODE_NO = 0, | ||
547 | WMI_NWIFI_RX_TRANS_MODE_PBSS2AP = 1, | ||
548 | WMI_NWIFI_RX_TRANS_MODE_PBSS2STA = 2, | ||
549 | }; | ||
550 | |||
551 | struct wmi_cfg_rx_chain_cmd { | ||
552 | __le32 action; | ||
553 | struct wmi_sw_ring_cfg rx_sw_ring; | ||
554 | u8 mid; | ||
555 | u8 decap_trans_type; | ||
556 | |||
557 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0) | ||
558 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1) | ||
559 | #define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1) | ||
560 | u8 l2_802_3_offload_ctrl; | ||
561 | |||
562 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0) | ||
563 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1) | ||
564 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1) | ||
565 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1) | ||
566 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1) | ||
567 | #define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2) | ||
568 | u8 l2_nwifi_offload_ctrl; | ||
569 | |||
570 | u8 vlan_id; | ||
571 | u8 nwifi_ds_trans_type; | ||
572 | |||
573 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0) | ||
574 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1) | ||
575 | #define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1) | ||
576 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1) | ||
577 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1) | ||
578 | #define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2) | ||
579 | u8 l3_l4_ctrl; | ||
580 | |||
581 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0) | ||
582 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1) | ||
583 | #define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1) | ||
584 | #define RING_CTRL_OVERRIDE_WB_THRSH_POS (1) | ||
585 | #define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1) | ||
586 | #define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2) | ||
587 | #define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2) | ||
588 | #define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1) | ||
589 | #define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4) | ||
590 | #define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3) | ||
591 | #define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1) | ||
592 | #define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8) | ||
593 | u8 ring_ctrl; | ||
594 | |||
595 | __le16 prefetch_thrsh; | ||
596 | __le16 wb_thrsh; | ||
597 | __le32 itr_value; | ||
598 | __le16 host_thrsh; | ||
599 | u8 reserved[2]; | ||
600 | struct wmi_sniffer_cfg sniffer_cfg; | ||
601 | } __packed; | ||
602 | |||
603 | /* | ||
604 | * WMI_RCP_ADDBA_RESP_CMDID | ||
605 | */ | ||
606 | struct wmi_rcp_addba_resp_cmd { | ||
607 | |||
608 | #define CIDXTID_CID_POS (0) | ||
609 | #define CIDXTID_CID_LEN (4) | ||
610 | #define CIDXTID_CID_MSK (0xF) | ||
611 | #define CIDXTID_TID_POS (4) | ||
612 | #define CIDXTID_TID_LEN (4) | ||
613 | #define CIDXTID_TID_MSK (0xF0) | ||
614 | u8 cidxtid; | ||
615 | |||
616 | u8 dialog_token; | ||
617 | __le16 status_code; | ||
618 | __le16 ba_param_set; /* ieee80211_ba_parameterset field to send */ | ||
619 | __le16 ba_timeout; | ||
620 | } __packed; | ||
621 | |||
622 | /* | ||
623 | * WMI_RCP_DELBA_CMDID | ||
624 | */ | ||
625 | struct wmi_rcp_delba_cmd { | ||
626 | |||
627 | #define CIDXTID_CID_POS (0) | ||
628 | #define CIDXTID_CID_LEN (4) | ||
629 | #define CIDXTID_CID_MSK (0xF) | ||
630 | #define CIDXTID_TID_POS (4) | ||
631 | #define CIDXTID_TID_LEN (4) | ||
632 | #define CIDXTID_TID_MSK (0xF0) | ||
633 | u8 cidxtid; | ||
634 | |||
635 | u8 reserved; | ||
636 | __le16 reason; | ||
637 | } __packed; | ||
638 | |||
639 | /* | ||
640 | * WMI_RCP_ADDBA_REQ_CMDID | ||
641 | */ | ||
642 | struct wmi_rcp_addba_req_cmd { | ||
643 | |||
644 | #define CIDXTID_CID_POS (0) | ||
645 | #define CIDXTID_CID_LEN (4) | ||
646 | #define CIDXTID_CID_MSK (0xF) | ||
647 | #define CIDXTID_TID_POS (4) | ||
648 | #define CIDXTID_TID_LEN (4) | ||
649 | #define CIDXTID_TID_MSK (0xF0) | ||
650 | u8 cidxtid; | ||
651 | |||
652 | u8 dialog_token; | ||
653 | /* ieee80211_ba_parameterset field as it received */ | ||
654 | __le16 ba_param_set; | ||
655 | __le16 ba_timeout; | ||
656 | /* ieee80211_ba_seqstrl field as it received */ | ||
657 | __le16 ba_seq_ctrl; | ||
658 | } __packed; | ||
659 | |||
660 | /* | ||
661 | * WMI_SET_MAC_ADDRESS_CMDID | ||
662 | */ | ||
663 | struct wmi_set_mac_address_cmd { | ||
664 | u8 mac[WMI_MAC_LEN]; | ||
665 | u8 reserved[2]; | ||
666 | } __packed; | ||
667 | |||
668 | |||
669 | /* | ||
670 | * WMI_EAPOL_TX_CMDID | ||
671 | */ | ||
672 | struct wmi_eapol_tx_cmd { | ||
673 | u8 dst_mac[WMI_MAC_LEN]; | ||
674 | __le16 eapol_len; | ||
675 | u8 eapol[0]; | ||
676 | } __packed; | ||
677 | |||
678 | /* | ||
679 | * WMI_ECHO_CMDID | ||
680 | * | ||
681 | * Check FW is alive | ||
682 | * | ||
683 | * WMI_DEEP_ECHO_CMDID | ||
684 | * | ||
685 | * Check FW and ucode are alive | ||
686 | * | ||
687 | * Returned event: WMI_ECHO_RSP_EVENTID | ||
688 | * same event for both commands | ||
689 | */ | ||
690 | struct wmi_echo_cmd { | ||
691 | __le32 value; | ||
692 | } __packed; | ||
693 | |||
694 | /* | ||
695 | * WMI Events | ||
696 | */ | ||
697 | |||
698 | /* | ||
699 | * List of Events (target to host) | ||
700 | */ | ||
701 | enum wmi_event_id { | ||
702 | WMI_IMM_RSP_EVENTID = 0x0000, | ||
703 | WMI_READY_EVENTID = 0x1001, | ||
704 | WMI_CONNECT_EVENTID = 0x1002, | ||
705 | WMI_DISCONNECT_EVENTID = 0x1003, | ||
706 | WMI_SCAN_COMPLETE_EVENTID = 0x100a, | ||
707 | WMI_REPORT_STATISTICS_EVENTID = 0x100b, | ||
708 | WMI_RD_MEM_RSP_EVENTID = 0x1800, | ||
709 | WMI_FW_READY_EVENTID = 0x1801, | ||
710 | WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID = 0x0200, | ||
711 | WMI_ECHO_RSP_EVENTID = 0x1803, | ||
712 | WMI_CONFIG_MAC_DONE_EVENTID = 0x1805, | ||
713 | WMI_CONFIG_PHY_DEBUG_DONE_EVENTID = 0x1806, | ||
714 | WMI_ADD_STATION_DONE_EVENTID = 0x1807, | ||
715 | WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID = 0x1808, | ||
716 | WMI_PHY_GET_STATISTICS_EVENTID = 0x1809, | ||
717 | WMI_FS_TUNE_DONE_EVENTID = 0x180a, | ||
718 | WMI_CORR_MEASURE_DONE_EVENTID = 0x180b, | ||
719 | WMI_TEMP_SENSE_DONE_EVENTID = 0x180e, | ||
720 | WMI_DC_CALIB_DONE_EVENTID = 0x180f, | ||
721 | WMI_IQ_TX_CALIB_DONE_EVENTID = 0x1811, | ||
722 | WMI_IQ_RX_CALIB_DONE_EVENTID = 0x1812, | ||
723 | WMI_SET_WORK_MODE_DONE_EVENTID = 0x1815, | ||
724 | WMI_LO_LEAKAGE_CALIB_DONE_EVENTID = 0x1816, | ||
725 | WMI_MARLON_R_ACTIVATE_DONE_EVENTID = 0x1817, | ||
726 | WMI_MARLON_R_READ_DONE_EVENTID = 0x1818, | ||
727 | WMI_MARLON_R_WRITE_DONE_EVENTID = 0x1819, | ||
728 | WMI_MARLON_R_TXRX_SEL_DONE_EVENTID = 0x181a, | ||
729 | WMI_SILENT_RSSI_CALIB_DONE_EVENTID = 0x181d, | ||
730 | |||
731 | WMI_CFG_RX_CHAIN_DONE_EVENTID = 0x1820, | ||
732 | WMI_VRING_CFG_DONE_EVENTID = 0x1821, | ||
733 | WMI_RX_ON_DONE_EVENTID = 0x1822, | ||
734 | WMI_BA_STATUS_EVENTID = 0x1823, | ||
735 | WMI_RCP_ADDBA_REQ_EVENTID = 0x1824, | ||
736 | WMI_ADDBA_RESP_SENT_EVENTID = 0x1825, | ||
737 | WMI_DELBA_EVENTID = 0x1826, | ||
738 | WMI_GET_SSID_EVENTID = 0x1828, | ||
739 | WMI_GET_PCP_CHANNEL_EVENTID = 0x182a, | ||
740 | WMI_SW_TX_COMPLETE_EVENTID = 0x182b, | ||
741 | WMI_RX_OFF_DONE_EVENTID = 0x182c, | ||
742 | |||
743 | WMI_READ_MAC_RXQ_EVENTID = 0x1830, | ||
744 | WMI_READ_MAC_TXQ_EVENTID = 0x1831, | ||
745 | WMI_WRITE_MAC_RXQ_EVENTID = 0x1832, | ||
746 | WMI_WRITE_MAC_TXQ_EVENTID = 0x1833, | ||
747 | WMI_WRITE_MAC_XQ_FIELD_EVENTID = 0x1834, | ||
748 | |||
749 | WMI_BEAFORMING_MGMT_DONE_EVENTID = 0x1836, | ||
750 | WMI_BF_TXSS_MGMT_DONE_EVENTID = 0x1837, | ||
751 | WMI_BF_RXSS_MGMT_DONE_EVENTID = 0x1839, | ||
752 | WMI_RS_MGMT_DONE_EVENTID = 0x1852, | ||
753 | WMI_RF_MGMT_STATUS_EVENTID = 0x1853, | ||
754 | WMI_BF_SM_MGMT_DONE_EVENTID = 0x1838, | ||
755 | WMI_RX_MGMT_PACKET_EVENTID = 0x1840, | ||
756 | |||
757 | /* Performance monitoring events */ | ||
758 | WMI_DATA_PORT_OPEN_EVENTID = 0x1860, | ||
759 | WMI_WBE_LINKDOWN_EVENTID = 0x1861, | ||
760 | |||
761 | WMI_BF_CTRL_DONE_EVENTID = 0x1862, | ||
762 | WMI_NOTIFY_REQ_DONE_EVENTID = 0x1863, | ||
763 | WMI_GET_STATUS_DONE_EVENTID = 0x1864, | ||
764 | |||
765 | WMI_UNIT_TEST_EVENTID = 0x1900, | ||
766 | WMI_FLASH_READ_DONE_EVENTID = 0x1902, | ||
767 | WMI_FLASH_WRITE_DONE_EVENTID = 0x1903, | ||
768 | |||
769 | WMI_SET_CHANNEL_EVENTID = 0x9000, | ||
770 | WMI_ASSOC_REQ_EVENTID = 0x9001, | ||
771 | WMI_EAPOL_RX_EVENTID = 0x9002, | ||
772 | WMI_MAC_ADDR_RESP_EVENTID = 0x9003, | ||
773 | WMI_FW_VER_EVENTID = 0x9004, | ||
774 | }; | ||
775 | |||
776 | /* | ||
777 | * Events data structures | ||
778 | */ | ||
779 | |||
780 | /* | ||
781 | * WMI_RF_MGMT_STATUS_EVENTID | ||
782 | */ | ||
783 | enum wmi_rf_status { | ||
784 | WMI_RF_ENABLED = 0, | ||
785 | WMI_RF_DISABLED_HW = 1, | ||
786 | WMI_RF_DISABLED_SW = 2, | ||
787 | WMI_RF_DISABLED_HW_SW = 3, | ||
788 | }; | ||
789 | |||
790 | struct wmi_rf_mgmt_status_event { | ||
791 | __le32 rf_status; | ||
792 | } __packed; | ||
793 | |||
794 | /* | ||
795 | * WMI_GET_STATUS_DONE_EVENTID | ||
796 | */ | ||
797 | struct wmi_get_status_done_event { | ||
798 | __le32 is_associated; | ||
799 | u8 cid; | ||
800 | u8 reserved0[3]; | ||
801 | u8 bssid[WMI_MAC_LEN]; | ||
802 | u8 channel; | ||
803 | u8 reserved1; | ||
804 | u8 network_type; | ||
805 | u8 reserved2[3]; | ||
806 | __le32 ssid_len; | ||
807 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
808 | __le32 rf_status; | ||
809 | __le32 is_secured; | ||
810 | } __packed; | ||
811 | |||
812 | /* | ||
813 | * WMI_FW_VER_EVENTID | ||
814 | */ | ||
815 | struct wmi_fw_ver_event { | ||
816 | u8 major; | ||
817 | u8 minor; | ||
818 | __le16 subminor; | ||
819 | __le16 build; | ||
820 | } __packed; | ||
821 | |||
822 | /* | ||
823 | * WMI_MAC_ADDR_RESP_EVENTID | ||
824 | */ | ||
825 | struct wmi_mac_addr_resp_event { | ||
826 | u8 mac[WMI_MAC_LEN]; | ||
827 | u8 auth_mode; | ||
828 | u8 crypt_mode; | ||
829 | __le32 offload_mode; | ||
830 | } __packed; | ||
831 | |||
832 | /* | ||
833 | * WMI_EAPOL_RX_EVENTID | ||
834 | */ | ||
835 | struct wmi_eapol_rx_event { | ||
836 | u8 src_mac[WMI_MAC_LEN]; | ||
837 | __le16 eapol_len; | ||
838 | u8 eapol[0]; | ||
839 | } __packed; | ||
840 | |||
841 | /* | ||
842 | * WMI_READY_EVENTID | ||
843 | */ | ||
844 | enum wmi_phy_capability { | ||
845 | WMI_11A_CAPABILITY = 1, | ||
846 | WMI_11G_CAPABILITY = 2, | ||
847 | WMI_11AG_CAPABILITY = 3, | ||
848 | WMI_11NA_CAPABILITY = 4, | ||
849 | WMI_11NG_CAPABILITY = 5, | ||
850 | WMI_11NAG_CAPABILITY = 6, | ||
851 | WMI_11AD_CAPABILITY = 7, | ||
852 | WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY, | ||
853 | }; | ||
854 | |||
855 | struct wmi_ready_event { | ||
856 | __le32 sw_version; | ||
857 | __le32 abi_version; | ||
858 | u8 mac[WMI_MAC_LEN]; | ||
859 | u8 phy_capability; /* enum wmi_phy_capability */ | ||
860 | u8 reserved; | ||
861 | } __packed; | ||
862 | |||
863 | /* | ||
864 | * WMI_NOTIFY_REQ_DONE_EVENTID | ||
865 | */ | ||
866 | struct wmi_notify_req_done_event { | ||
867 | __le32 status; | ||
868 | __le64 tsf; | ||
869 | __le32 snr_val; | ||
870 | __le32 tx_tpt; | ||
871 | __le32 tx_goodput; | ||
872 | __le32 rx_goodput; | ||
873 | __le16 bf_mcs; | ||
874 | __le16 my_rx_sector; | ||
875 | __le16 my_tx_sector; | ||
876 | __le16 other_rx_sector; | ||
877 | __le16 other_tx_sector; | ||
878 | __le16 range; | ||
879 | } __packed; | ||
880 | |||
881 | /* | ||
882 | * WMI_CONNECT_EVENTID | ||
883 | */ | ||
884 | struct wmi_connect_event { | ||
885 | u8 channel; | ||
886 | u8 reserved0; | ||
887 | u8 bssid[WMI_MAC_LEN]; | ||
888 | __le16 listen_interval; | ||
889 | __le16 beacon_interval; | ||
890 | u8 network_type; | ||
891 | u8 reserved1[3]; | ||
892 | u8 beacon_ie_len; | ||
893 | u8 assoc_req_len; | ||
894 | u8 assoc_resp_len; | ||
895 | u8 cid; | ||
896 | u8 reserved2[3]; | ||
897 | u8 assoc_info[0]; | ||
898 | } __packed; | ||
899 | |||
900 | /* | ||
901 | * WMI_DISCONNECT_EVENTID | ||
902 | */ | ||
903 | enum wmi_disconnect_reason { | ||
904 | WMI_DIS_REASON_NO_NETWORK_AVAIL = 1, | ||
905 | WMI_DIS_REASON_LOST_LINK = 2, /* bmiss */ | ||
906 | WMI_DIS_REASON_DISCONNECT_CMD = 3, | ||
907 | WMI_DIS_REASON_BSS_DISCONNECTED = 4, | ||
908 | WMI_DIS_REASON_AUTH_FAILED = 5, | ||
909 | WMI_DIS_REASON_ASSOC_FAILED = 6, | ||
910 | WMI_DIS_REASON_NO_RESOURCES_AVAIL = 7, | ||
911 | WMI_DIS_REASON_CSERV_DISCONNECT = 8, | ||
912 | WMI_DIS_REASON_INVALID_PROFILE = 10, | ||
913 | WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH = 11, | ||
914 | WMI_DIS_REASON_PROFILE_MISMATCH = 12, | ||
915 | WMI_DIS_REASON_CONNECTION_EVICTED = 13, | ||
916 | WMI_DIS_REASON_IBSS_MERGE = 14, | ||
917 | }; | ||
918 | |||
919 | struct wmi_disconnect_event { | ||
920 | __le16 protocol_reason_status; /* reason code, see 802.11 spec. */ | ||
921 | u8 bssid[WMI_MAC_LEN]; /* set if known */ | ||
922 | u8 disconnect_reason; /* see wmi_disconnect_reason_e */ | ||
923 | u8 assoc_resp_len; | ||
924 | u8 assoc_info[0]; | ||
925 | } __packed; | ||
926 | |||
927 | /* | ||
928 | * WMI_SCAN_COMPLETE_EVENTID | ||
929 | */ | ||
930 | struct wmi_scan_complete_event { | ||
931 | __le32 status; | ||
932 | } __packed; | ||
933 | |||
934 | /* | ||
935 | * WMI_BA_STATUS_EVENTID | ||
936 | */ | ||
937 | enum wmi_vring_ba_status { | ||
938 | WMI_BA_AGREED = 0, | ||
939 | WMI_BA_NON_AGREED = 1, | ||
940 | }; | ||
941 | |||
942 | struct wmi_vring_ba_status_event { | ||
943 | __le16 status; | ||
944 | u8 reserved[2]; | ||
945 | u8 ringid; | ||
946 | u8 agg_wsize; | ||
947 | __le16 ba_timeout; | ||
948 | } __packed; | ||
949 | |||
950 | /* | ||
951 | * WMI_DELBA_EVENTID | ||
952 | */ | ||
953 | struct wmi_delba_event { | ||
954 | |||
955 | #define CIDXTID_CID_POS (0) | ||
956 | #define CIDXTID_CID_LEN (4) | ||
957 | #define CIDXTID_CID_MSK (0xF) | ||
958 | #define CIDXTID_TID_POS (4) | ||
959 | #define CIDXTID_TID_LEN (4) | ||
960 | #define CIDXTID_TID_MSK (0xF0) | ||
961 | u8 cidxtid; | ||
962 | |||
963 | u8 from_initiator; | ||
964 | __le16 reason; | ||
965 | } __packed; | ||
966 | |||
967 | /* | ||
968 | * WMI_VRING_CFG_DONE_EVENTID | ||
969 | */ | ||
970 | enum wmi_vring_cfg_done_event_status { | ||
971 | WMI_VRING_CFG_SUCCESS = 0, | ||
972 | WMI_VRING_CFG_FAILURE = 1, | ||
973 | }; | ||
974 | |||
975 | struct wmi_vring_cfg_done_event { | ||
976 | u8 ringid; | ||
977 | u8 status; | ||
978 | u8 reserved[2]; | ||
979 | __le32 tx_vring_tail_ptr; | ||
980 | } __packed; | ||
981 | |||
982 | /* | ||
983 | * WMI_ADDBA_RESP_SENT_EVENTID | ||
984 | */ | ||
985 | enum wmi_rcp_addba_resp_sent_event_status { | ||
986 | WMI_ADDBA_SUCCESS = 0, | ||
987 | WMI_ADDBA_FAIL = 1, | ||
988 | }; | ||
989 | |||
990 | struct wmi_rcp_addba_resp_sent_event { | ||
991 | |||
992 | #define CIDXTID_CID_POS (0) | ||
993 | #define CIDXTID_CID_LEN (4) | ||
994 | #define CIDXTID_CID_MSK (0xF) | ||
995 | #define CIDXTID_TID_POS (4) | ||
996 | #define CIDXTID_TID_LEN (4) | ||
997 | #define CIDXTID_TID_MSK (0xF0) | ||
998 | u8 cidxtid; | ||
999 | |||
1000 | u8 reserved; | ||
1001 | __le16 status; | ||
1002 | } __packed; | ||
1003 | |||
1004 | /* | ||
1005 | * WMI_RCP_ADDBA_REQ_EVENTID | ||
1006 | */ | ||
1007 | struct wmi_rcp_addba_req_event { | ||
1008 | |||
1009 | #define CIDXTID_CID_POS (0) | ||
1010 | #define CIDXTID_CID_LEN (4) | ||
1011 | #define CIDXTID_CID_MSK (0xF) | ||
1012 | #define CIDXTID_TID_POS (4) | ||
1013 | #define CIDXTID_TID_LEN (4) | ||
1014 | #define CIDXTID_TID_MSK (0xF0) | ||
1015 | u8 cidxtid; | ||
1016 | |||
1017 | u8 dialog_token; | ||
1018 | __le16 ba_param_set; /* ieee80211_ba_parameterset as it received */ | ||
1019 | __le16 ba_timeout; | ||
1020 | __le16 ba_seq_ctrl; /* ieee80211_ba_seqstrl field as it received */ | ||
1021 | } __packed; | ||
1022 | |||
1023 | /* | ||
1024 | * WMI_CFG_RX_CHAIN_DONE_EVENTID | ||
1025 | */ | ||
1026 | enum wmi_cfg_rx_chain_done_event_status { | ||
1027 | WMI_CFG_RX_CHAIN_SUCCESS = 1, | ||
1028 | }; | ||
1029 | |||
1030 | struct wmi_cfg_rx_chain_done_event { | ||
1031 | __le32 rx_ring_tail_ptr; /* Rx V-Ring Tail pointer */ | ||
1032 | __le32 status; | ||
1033 | } __packed; | ||
1034 | |||
1035 | /* | ||
1036 | * WMI_WBE_LINKDOWN_EVENTID | ||
1037 | */ | ||
1038 | enum wmi_wbe_link_down_event_reason { | ||
1039 | WMI_WBE_REASON_USER_REQUEST = 0, | ||
1040 | WMI_WBE_REASON_RX_DISASSOC = 1, | ||
1041 | WMI_WBE_REASON_BAD_PHY_LINK = 2, | ||
1042 | }; | ||
1043 | |||
1044 | struct wmi_wbe_link_down_event { | ||
1045 | u8 cid; | ||
1046 | u8 reserved[3]; | ||
1047 | __le32 reason; | ||
1048 | } __packed; | ||
1049 | |||
1050 | /* | ||
1051 | * WMI_DATA_PORT_OPEN_EVENTID | ||
1052 | */ | ||
1053 | struct wmi_data_port_open_event { | ||
1054 | u8 cid; | ||
1055 | u8 reserved[3]; | ||
1056 | } __packed; | ||
1057 | |||
1058 | /* | ||
1059 | * WMI_GET_PCP_CHANNEL_EVENTID | ||
1060 | */ | ||
1061 | struct wmi_get_pcp_channel_event { | ||
1062 | u8 channel; | ||
1063 | u8 reserved[3]; | ||
1064 | } __packed; | ||
1065 | |||
1066 | /* | ||
1067 | * WMI_SW_TX_COMPLETE_EVENTID | ||
1068 | */ | ||
1069 | enum wmi_sw_tx_status { | ||
1070 | WMI_TX_SW_STATUS_SUCCESS = 0, | ||
1071 | WMI_TX_SW_STATUS_FAILED_NO_RESOURCES = 1, | ||
1072 | WMI_TX_SW_STATUS_FAILED_TX = 2, | ||
1073 | }; | ||
1074 | |||
1075 | struct wmi_sw_tx_complete_event { | ||
1076 | u8 status; /* enum wmi_sw_tx_status */ | ||
1077 | u8 reserved[3]; | ||
1078 | } __packed; | ||
1079 | |||
1080 | /* | ||
1081 | * WMI_GET_SSID_EVENTID | ||
1082 | */ | ||
1083 | struct wmi_get_ssid_event { | ||
1084 | __le32 ssid_len; | ||
1085 | u8 ssid[WMI_MAX_SSID_LEN]; | ||
1086 | } __packed; | ||
1087 | |||
1088 | /* | ||
1089 | * WMI_RX_MGMT_PACKET_EVENTID | ||
1090 | */ | ||
1091 | struct wmi_rx_mgmt_info { | ||
1092 | u8 mcs; | ||
1093 | s8 snr; | ||
1094 | __le16 range; | ||
1095 | __le16 stype; | ||
1096 | __le16 status; | ||
1097 | __le32 len; | ||
1098 | u8 qid; | ||
1099 | u8 mid; | ||
1100 | u8 cid; | ||
1101 | u8 channel; /* From Radio MNGR */ | ||
1102 | } __packed; | ||
1103 | |||
1104 | struct wmi_rx_mgmt_packet_event { | ||
1105 | struct wmi_rx_mgmt_info info; | ||
1106 | u8 payload[0]; | ||
1107 | } __packed; | ||
1108 | |||
1109 | /* | ||
1110 | * WMI_ECHO_RSP_EVENTID | ||
1111 | */ | ||
1112 | struct wmi_echo_event { | ||
1113 | __le32 echoed_value; | ||
1114 | } __packed; | ||
1115 | |||
1116 | #endif /* __WILOCITY_WMI_H__ */ | ||
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h index b298e5d68be2..10e288d470e7 100644 --- a/drivers/net/wireless/b43/b43.h +++ b/drivers/net/wireless/b43/b43.h | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/hw_random.h> | 7 | #include <linux/hw_random.h> |
8 | #include <linux/bcma/bcma.h> | 8 | #include <linux/bcma/bcma.h> |
9 | #include <linux/ssb/ssb.h> | 9 | #include <linux/ssb/ssb.h> |
10 | #include <linux/completion.h> | ||
10 | #include <net/mac80211.h> | 11 | #include <net/mac80211.h> |
11 | 12 | ||
12 | #include "debugfs.h" | 13 | #include "debugfs.h" |
@@ -722,6 +723,10 @@ enum b43_firmware_file_type { | |||
722 | struct b43_request_fw_context { | 723 | struct b43_request_fw_context { |
723 | /* The device we are requesting the fw for. */ | 724 | /* The device we are requesting the fw for. */ |
724 | struct b43_wldev *dev; | 725 | struct b43_wldev *dev; |
726 | /* a completion event structure needed if this call is asynchronous */ | ||
727 | struct completion fw_load_complete; | ||
728 | /* a pointer to the firmware object */ | ||
729 | const struct firmware *blob; | ||
725 | /* The type of firmware to request. */ | 730 | /* The type of firmware to request. */ |
726 | enum b43_firmware_file_type req_type; | 731 | enum b43_firmware_file_type req_type; |
727 | /* Error messages for each firmware type. */ | 732 | /* Error messages for each firmware type. */ |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 16ab280359bd..806e34c19281 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -2088,11 +2088,18 @@ static void b43_print_fw_helptext(struct b43_wl *wl, bool error) | |||
2088 | b43warn(wl, text); | 2088 | b43warn(wl, text); |
2089 | } | 2089 | } |
2090 | 2090 | ||
2091 | static void b43_fw_cb(const struct firmware *firmware, void *context) | ||
2092 | { | ||
2093 | struct b43_request_fw_context *ctx = context; | ||
2094 | |||
2095 | ctx->blob = firmware; | ||
2096 | complete(&ctx->fw_load_complete); | ||
2097 | } | ||
2098 | |||
2091 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 2099 | int b43_do_request_fw(struct b43_request_fw_context *ctx, |
2092 | const char *name, | 2100 | const char *name, |
2093 | struct b43_firmware_file *fw) | 2101 | struct b43_firmware_file *fw, bool async) |
2094 | { | 2102 | { |
2095 | const struct firmware *blob; | ||
2096 | struct b43_fw_header *hdr; | 2103 | struct b43_fw_header *hdr; |
2097 | u32 size; | 2104 | u32 size; |
2098 | int err; | 2105 | int err; |
@@ -2131,11 +2138,31 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2131 | B43_WARN_ON(1); | 2138 | B43_WARN_ON(1); |
2132 | return -ENOSYS; | 2139 | return -ENOSYS; |
2133 | } | 2140 | } |
2134 | err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev); | 2141 | if (async) { |
2142 | /* do this part asynchronously */ | ||
2143 | init_completion(&ctx->fw_load_complete); | ||
2144 | err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname, | ||
2145 | ctx->dev->dev->dev, GFP_KERNEL, | ||
2146 | ctx, b43_fw_cb); | ||
2147 | if (err < 0) { | ||
2148 | pr_err("Unable to load firmware\n"); | ||
2149 | return err; | ||
2150 | } | ||
2151 | /* stall here until fw ready */ | ||
2152 | wait_for_completion(&ctx->fw_load_complete); | ||
2153 | if (ctx->blob) | ||
2154 | goto fw_ready; | ||
2155 | /* On some ARM systems, the async request will fail, but the next sync | ||
2156 | * request works. For this reason, we dall through here | ||
2157 | */ | ||
2158 | } | ||
2159 | err = request_firmware(&ctx->blob, ctx->fwname, | ||
2160 | ctx->dev->dev->dev); | ||
2135 | if (err == -ENOENT) { | 2161 | if (err == -ENOENT) { |
2136 | snprintf(ctx->errors[ctx->req_type], | 2162 | snprintf(ctx->errors[ctx->req_type], |
2137 | sizeof(ctx->errors[ctx->req_type]), | 2163 | sizeof(ctx->errors[ctx->req_type]), |
2138 | "Firmware file \"%s\" not found\n", ctx->fwname); | 2164 | "Firmware file \"%s\" not found\n", |
2165 | ctx->fwname); | ||
2139 | return err; | 2166 | return err; |
2140 | } else if (err) { | 2167 | } else if (err) { |
2141 | snprintf(ctx->errors[ctx->req_type], | 2168 | snprintf(ctx->errors[ctx->req_type], |
@@ -2144,14 +2171,15 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2144 | ctx->fwname, err); | 2171 | ctx->fwname, err); |
2145 | return err; | 2172 | return err; |
2146 | } | 2173 | } |
2147 | if (blob->size < sizeof(struct b43_fw_header)) | 2174 | fw_ready: |
2175 | if (ctx->blob->size < sizeof(struct b43_fw_header)) | ||
2148 | goto err_format; | 2176 | goto err_format; |
2149 | hdr = (struct b43_fw_header *)(blob->data); | 2177 | hdr = (struct b43_fw_header *)(ctx->blob->data); |
2150 | switch (hdr->type) { | 2178 | switch (hdr->type) { |
2151 | case B43_FW_TYPE_UCODE: | 2179 | case B43_FW_TYPE_UCODE: |
2152 | case B43_FW_TYPE_PCM: | 2180 | case B43_FW_TYPE_PCM: |
2153 | size = be32_to_cpu(hdr->size); | 2181 | size = be32_to_cpu(hdr->size); |
2154 | if (size != blob->size - sizeof(struct b43_fw_header)) | 2182 | if (size != ctx->blob->size - sizeof(struct b43_fw_header)) |
2155 | goto err_format; | 2183 | goto err_format; |
2156 | /* fallthrough */ | 2184 | /* fallthrough */ |
2157 | case B43_FW_TYPE_IV: | 2185 | case B43_FW_TYPE_IV: |
@@ -2162,7 +2190,7 @@ int b43_do_request_fw(struct b43_request_fw_context *ctx, | |||
2162 | goto err_format; | 2190 | goto err_format; |
2163 | } | 2191 | } |
2164 | 2192 | ||
2165 | fw->data = blob; | 2193 | fw->data = ctx->blob; |
2166 | fw->filename = name; | 2194 | fw->filename = name; |
2167 | fw->type = ctx->req_type; | 2195 | fw->type = ctx->req_type; |
2168 | 2196 | ||
@@ -2172,7 +2200,7 @@ err_format: | |||
2172 | snprintf(ctx->errors[ctx->req_type], | 2200 | snprintf(ctx->errors[ctx->req_type], |
2173 | sizeof(ctx->errors[ctx->req_type]), | 2201 | sizeof(ctx->errors[ctx->req_type]), |
2174 | "Firmware file \"%s\" format error.\n", ctx->fwname); | 2202 | "Firmware file \"%s\" format error.\n", ctx->fwname); |
2175 | release_firmware(blob); | 2203 | release_firmware(ctx->blob); |
2176 | 2204 | ||
2177 | return -EPROTO; | 2205 | return -EPROTO; |
2178 | } | 2206 | } |
@@ -2223,7 +2251,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2223 | goto err_no_ucode; | 2251 | goto err_no_ucode; |
2224 | } | 2252 | } |
2225 | } | 2253 | } |
2226 | err = b43_do_request_fw(ctx, filename, &fw->ucode); | 2254 | err = b43_do_request_fw(ctx, filename, &fw->ucode, true); |
2227 | if (err) | 2255 | if (err) |
2228 | goto err_load; | 2256 | goto err_load; |
2229 | 2257 | ||
@@ -2235,7 +2263,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2235 | else | 2263 | else |
2236 | goto err_no_pcm; | 2264 | goto err_no_pcm; |
2237 | fw->pcm_request_failed = false; | 2265 | fw->pcm_request_failed = false; |
2238 | err = b43_do_request_fw(ctx, filename, &fw->pcm); | 2266 | err = b43_do_request_fw(ctx, filename, &fw->pcm, false); |
2239 | if (err == -ENOENT) { | 2267 | if (err == -ENOENT) { |
2240 | /* We did not find a PCM file? Not fatal, but | 2268 | /* We did not find a PCM file? Not fatal, but |
2241 | * core rev <= 10 must do without hwcrypto then. */ | 2269 | * core rev <= 10 must do without hwcrypto then. */ |
@@ -2296,7 +2324,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2296 | default: | 2324 | default: |
2297 | goto err_no_initvals; | 2325 | goto err_no_initvals; |
2298 | } | 2326 | } |
2299 | err = b43_do_request_fw(ctx, filename, &fw->initvals); | 2327 | err = b43_do_request_fw(ctx, filename, &fw->initvals, false); |
2300 | if (err) | 2328 | if (err) |
2301 | goto err_load; | 2329 | goto err_load; |
2302 | 2330 | ||
@@ -2355,7 +2383,7 @@ static int b43_try_request_fw(struct b43_request_fw_context *ctx) | |||
2355 | default: | 2383 | default: |
2356 | goto err_no_initvals; | 2384 | goto err_no_initvals; |
2357 | } | 2385 | } |
2358 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band); | 2386 | err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false); |
2359 | if (err) | 2387 | if (err) |
2360 | goto err_load; | 2388 | goto err_load; |
2361 | 2389 | ||
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h index 8c684cd33529..abac25ee958d 100644 --- a/drivers/net/wireless/b43/main.h +++ b/drivers/net/wireless/b43/main.h | |||
@@ -137,9 +137,8 @@ void b43_mac_phy_clock_set(struct b43_wldev *dev, bool on); | |||
137 | 137 | ||
138 | 138 | ||
139 | struct b43_request_fw_context; | 139 | struct b43_request_fw_context; |
140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, | 140 | int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name, |
141 | const char *name, | 141 | struct b43_firmware_file *fw, bool async); |
142 | struct b43_firmware_file *fw); | ||
143 | void b43_do_release_fw(struct b43_firmware_file *fw); | 142 | void b43_do_release_fw(struct b43_firmware_file *fw); |
144 | 143 | ||
145 | #endif /* B43_MAIN_H_ */ | 144 | #endif /* B43_MAIN_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 1fbd8ecbe2ea..e5fd20994bec 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include "debug.h" | 36 | #include "debug.h" |
37 | 37 | ||
38 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ | 38 | #define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ |
39 | #define BRCMS_FLUSH_TIMEOUT 500 /* msec */ | ||
39 | 40 | ||
40 | /* Flags we support */ | 41 | /* Flags we support */ |
41 | #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ | 42 | #define MAC_FILTERS (FIF_PROMISC_IN_BSS | \ |
@@ -708,16 +709,29 @@ static void brcms_ops_rfkill_poll(struct ieee80211_hw *hw) | |||
708 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); | 709 | wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, blocked); |
709 | } | 710 | } |
710 | 711 | ||
712 | static bool brcms_tx_flush_completed(struct brcms_info *wl) | ||
713 | { | ||
714 | bool result; | ||
715 | |||
716 | spin_lock_bh(&wl->lock); | ||
717 | result = brcms_c_tx_flush_completed(wl->wlc); | ||
718 | spin_unlock_bh(&wl->lock); | ||
719 | return result; | ||
720 | } | ||
721 | |||
711 | static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) | 722 | static void brcms_ops_flush(struct ieee80211_hw *hw, bool drop) |
712 | { | 723 | { |
713 | struct brcms_info *wl = hw->priv; | 724 | struct brcms_info *wl = hw->priv; |
725 | int ret; | ||
714 | 726 | ||
715 | no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); | 727 | no_printk("%s: drop = %s\n", __func__, drop ? "true" : "false"); |
716 | 728 | ||
717 | /* wait for packet queue and dma fifos to run empty */ | 729 | ret = wait_event_timeout(wl->tx_flush_wq, |
718 | spin_lock_bh(&wl->lock); | 730 | brcms_tx_flush_completed(wl), |
719 | brcms_c_wait_for_tx_completion(wl->wlc, drop); | 731 | msecs_to_jiffies(BRCMS_FLUSH_TIMEOUT)); |
720 | spin_unlock_bh(&wl->lock); | 732 | |
733 | brcms_dbg_mac80211(wl->wlc->hw->d11core, | ||
734 | "ret=%d\n", jiffies_to_msecs(ret)); | ||
721 | } | 735 | } |
722 | 736 | ||
723 | static const struct ieee80211_ops brcms_ops = { | 737 | static const struct ieee80211_ops brcms_ops = { |
@@ -772,6 +786,7 @@ void brcms_dpc(unsigned long data) | |||
772 | 786 | ||
773 | done: | 787 | done: |
774 | spin_unlock_bh(&wl->lock); | 788 | spin_unlock_bh(&wl->lock); |
789 | wake_up(&wl->tx_flush_wq); | ||
775 | } | 790 | } |
776 | 791 | ||
777 | /* | 792 | /* |
@@ -1020,6 +1035,8 @@ static struct brcms_info *brcms_attach(struct bcma_device *pdev) | |||
1020 | 1035 | ||
1021 | atomic_set(&wl->callbacks, 0); | 1036 | atomic_set(&wl->callbacks, 0); |
1022 | 1037 | ||
1038 | init_waitqueue_head(&wl->tx_flush_wq); | ||
1039 | |||
1023 | /* setup the bottom half handler */ | 1040 | /* setup the bottom half handler */ |
1024 | tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); | 1041 | tasklet_init(&wl->tasklet, brcms_dpc, (unsigned long) wl); |
1025 | 1042 | ||
@@ -1407,9 +1424,10 @@ void brcms_add_timer(struct brcms_timer *t, uint ms, int periodic) | |||
1407 | #endif | 1424 | #endif |
1408 | t->ms = ms; | 1425 | t->ms = ms; |
1409 | t->periodic = (bool) periodic; | 1426 | t->periodic = (bool) periodic; |
1410 | t->set = true; | 1427 | if (!t->set) { |
1411 | 1428 | t->set = true; | |
1412 | atomic_inc(&t->wl->callbacks); | 1429 | atomic_inc(&t->wl->callbacks); |
1430 | } | ||
1413 | 1431 | ||
1414 | ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); | 1432 | ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms)); |
1415 | } | 1433 | } |
@@ -1608,13 +1626,3 @@ bool brcms_rfkill_set_hw_state(struct brcms_info *wl) | |||
1608 | spin_lock_bh(&wl->lock); | 1626 | spin_lock_bh(&wl->lock); |
1609 | return blocked; | 1627 | return blocked; |
1610 | } | 1628 | } |
1611 | |||
1612 | /* | ||
1613 | * precondition: perimeter lock has been acquired | ||
1614 | */ | ||
1615 | void brcms_msleep(struct brcms_info *wl, uint ms) | ||
1616 | { | ||
1617 | spin_unlock_bh(&wl->lock); | ||
1618 | msleep(ms); | ||
1619 | spin_lock_bh(&wl->lock); | ||
1620 | } | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h index 9358bd5ebd35..947ccacf43e6 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h | |||
@@ -68,6 +68,8 @@ struct brcms_info { | |||
68 | spinlock_t lock; /* per-device perimeter lock */ | 68 | spinlock_t lock; /* per-device perimeter lock */ |
69 | spinlock_t isr_lock; /* per-device ISR synchronization lock */ | 69 | spinlock_t isr_lock; /* per-device ISR synchronization lock */ |
70 | 70 | ||
71 | /* tx flush */ | ||
72 | wait_queue_head_t tx_flush_wq; | ||
71 | 73 | ||
72 | /* timer related fields */ | 74 | /* timer related fields */ |
73 | atomic_t callbacks; /* # outstanding callback functions */ | 75 | atomic_t callbacks; /* # outstanding callback functions */ |
@@ -100,7 +102,6 @@ extern struct brcms_timer *brcms_init_timer(struct brcms_info *wl, | |||
100 | extern void brcms_free_timer(struct brcms_timer *timer); | 102 | extern void brcms_free_timer(struct brcms_timer *timer); |
101 | extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); | 103 | extern void brcms_add_timer(struct brcms_timer *timer, uint ms, int periodic); |
102 | extern bool brcms_del_timer(struct brcms_timer *timer); | 104 | extern bool brcms_del_timer(struct brcms_timer *timer); |
103 | extern void brcms_msleep(struct brcms_info *wl, uint ms); | ||
104 | extern void brcms_dpc(unsigned long data); | 105 | extern void brcms_dpc(unsigned long data); |
105 | extern void brcms_timer(struct brcms_timer *t); | 106 | extern void brcms_timer(struct brcms_timer *t); |
106 | extern void brcms_fatal_error(struct brcms_info *wl); | 107 | extern void brcms_fatal_error(struct brcms_info *wl); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 17594de4199e..8b5839008af3 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -1027,7 +1027,6 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) | |||
1027 | static bool | 1027 | static bool |
1028 | brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | 1028 | brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) |
1029 | { | 1029 | { |
1030 | bool morepending = false; | ||
1031 | struct bcma_device *core; | 1030 | struct bcma_device *core; |
1032 | struct tx_status txstatus, *txs; | 1031 | struct tx_status txstatus, *txs; |
1033 | u32 s1, s2; | 1032 | u32 s1, s2; |
@@ -1041,23 +1040,20 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
1041 | txs = &txstatus; | 1040 | txs = &txstatus; |
1042 | core = wlc_hw->d11core; | 1041 | core = wlc_hw->d11core; |
1043 | *fatal = false; | 1042 | *fatal = false; |
1044 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); | ||
1045 | while (!(*fatal) | ||
1046 | && (s1 & TXS_V)) { | ||
1047 | /* !give others some time to run! */ | ||
1048 | if (n >= max_tx_num) { | ||
1049 | morepending = true; | ||
1050 | break; | ||
1051 | } | ||
1052 | 1043 | ||
1044 | while (n < max_tx_num) { | ||
1045 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); | ||
1053 | if (s1 == 0xffffffff) { | 1046 | if (s1 == 0xffffffff) { |
1054 | brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, | 1047 | brcms_err(core, "wl%d: %s: dead chip\n", wlc_hw->unit, |
1055 | __func__); | 1048 | __func__); |
1056 | *fatal = true; | 1049 | *fatal = true; |
1057 | return false; | 1050 | return false; |
1058 | } | 1051 | } |
1059 | s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2)); | 1052 | /* only process when valid */ |
1053 | if (!(s1 & TXS_V)) | ||
1054 | break; | ||
1060 | 1055 | ||
1056 | s2 = bcma_read32(core, D11REGOFFS(frmtxstatus2)); | ||
1061 | txs->status = s1 & TXS_STATUS_MASK; | 1057 | txs->status = s1 & TXS_STATUS_MASK; |
1062 | txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; | 1058 | txs->frameid = (s1 & TXS_FID_MASK) >> TXS_FID_SHIFT; |
1063 | txs->sequence = s2 & TXS_SEQ_MASK; | 1059 | txs->sequence = s2 & TXS_SEQ_MASK; |
@@ -1065,15 +1061,12 @@ brcms_b_txstatus(struct brcms_hardware *wlc_hw, bool bound, bool *fatal) | |||
1065 | txs->lasttxtime = 0; | 1061 | txs->lasttxtime = 0; |
1066 | 1062 | ||
1067 | *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); | 1063 | *fatal = brcms_c_dotxstatus(wlc_hw->wlc, txs); |
1068 | 1064 | if (*fatal == true) | |
1069 | s1 = bcma_read32(core, D11REGOFFS(frmtxstatus)); | 1065 | return false; |
1070 | n++; | 1066 | n++; |
1071 | } | 1067 | } |
1072 | 1068 | ||
1073 | if (*fatal) | 1069 | return n >= max_tx_num; |
1074 | return false; | ||
1075 | |||
1076 | return morepending; | ||
1077 | } | 1070 | } |
1078 | 1071 | ||
1079 | static void brcms_c_tbtt(struct brcms_c_info *wlc) | 1072 | static void brcms_c_tbtt(struct brcms_c_info *wlc) |
@@ -7518,25 +7511,16 @@ int brcms_c_get_curband(struct brcms_c_info *wlc) | |||
7518 | return wlc->band->bandunit; | 7511 | return wlc->band->bandunit; |
7519 | } | 7512 | } |
7520 | 7513 | ||
7521 | void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, bool drop) | 7514 | bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc) |
7522 | { | 7515 | { |
7523 | int timeout = 20; | ||
7524 | int i; | 7516 | int i; |
7525 | 7517 | ||
7526 | /* Kick DMA to send any pending AMPDU */ | 7518 | /* Kick DMA to send any pending AMPDU */ |
7527 | for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++) | 7519 | for (i = 0; i < ARRAY_SIZE(wlc->hw->di); i++) |
7528 | if (wlc->hw->di[i]) | 7520 | if (wlc->hw->di[i]) |
7529 | dma_txflush(wlc->hw->di[i]); | 7521 | dma_kick_tx(wlc->hw->di[i]); |
7530 | |||
7531 | /* wait for queue and DMA fifos to run dry */ | ||
7532 | while (brcms_txpktpendtot(wlc) > 0) { | ||
7533 | brcms_msleep(wlc->wl, 1); | ||
7534 | |||
7535 | if (--timeout == 0) | ||
7536 | break; | ||
7537 | } | ||
7538 | 7522 | ||
7539 | WARN_ON_ONCE(timeout == 0); | 7523 | return !brcms_txpktpendtot(wlc); |
7540 | } | 7524 | } |
7541 | 7525 | ||
7542 | void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) | 7526 | void brcms_c_set_beacon_listen_interval(struct brcms_c_info *wlc, u8 interval) |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/pub.h b/drivers/net/wireless/brcm80211/brcmsmac/pub.h index 4fb2834f4e64..b0f14b7b8616 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/pub.h +++ b/drivers/net/wireless/brcm80211/brcmsmac/pub.h | |||
@@ -314,8 +314,6 @@ extern void brcms_c_associate_upd(struct brcms_c_info *wlc, bool state); | |||
314 | extern void brcms_c_scan_start(struct brcms_c_info *wlc); | 314 | extern void brcms_c_scan_start(struct brcms_c_info *wlc); |
315 | extern void brcms_c_scan_stop(struct brcms_c_info *wlc); | 315 | extern void brcms_c_scan_stop(struct brcms_c_info *wlc); |
316 | extern int brcms_c_get_curband(struct brcms_c_info *wlc); | 316 | extern int brcms_c_get_curband(struct brcms_c_info *wlc); |
317 | extern void brcms_c_wait_for_tx_completion(struct brcms_c_info *wlc, | ||
318 | bool drop); | ||
319 | extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); | 317 | extern int brcms_c_set_channel(struct brcms_c_info *wlc, u16 channel); |
320 | extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); | 318 | extern int brcms_c_set_rate_limit(struct brcms_c_info *wlc, u16 srl, u16 lrl); |
321 | extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, | 319 | extern void brcms_c_get_current_rateset(struct brcms_c_info *wlc, |
@@ -332,5 +330,6 @@ extern int brcms_c_set_tx_power(struct brcms_c_info *wlc, int txpwr); | |||
332 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); | 330 | extern int brcms_c_get_tx_power(struct brcms_c_info *wlc); |
333 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); | 331 | extern bool brcms_c_check_radio_disabled(struct brcms_c_info *wlc); |
334 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); | 332 | extern void brcms_c_mute(struct brcms_c_info *wlc, bool on); |
333 | extern bool brcms_c_tx_flush_completed(struct brcms_c_info *wlc); | ||
335 | 334 | ||
336 | #endif /* _BRCM_PUB_H_ */ | 335 | #endif /* _BRCM_PUB_H_ */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index d92b21a8e597..b3ab7b7becae 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -2181,9 +2181,10 @@ static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status) | |||
2181 | mod_delayed_work(system_wq, &priv->rf_kill, round_jiffies_relative(HZ)); | 2181 | mod_delayed_work(system_wq, &priv->rf_kill, round_jiffies_relative(HZ)); |
2182 | } | 2182 | } |
2183 | 2183 | ||
2184 | static void send_scan_event(void *data) | 2184 | static void ipw2100_scan_event(struct work_struct *work) |
2185 | { | 2185 | { |
2186 | struct ipw2100_priv *priv = data; | 2186 | struct ipw2100_priv *priv = container_of(work, struct ipw2100_priv, |
2187 | scan_event.work); | ||
2187 | union iwreq_data wrqu; | 2188 | union iwreq_data wrqu; |
2188 | 2189 | ||
2189 | wrqu.data.length = 0; | 2190 | wrqu.data.length = 0; |
@@ -2191,18 +2192,6 @@ static void send_scan_event(void *data) | |||
2191 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); | 2192 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); |
2192 | } | 2193 | } |
2193 | 2194 | ||
2194 | static void ipw2100_scan_event_later(struct work_struct *work) | ||
2195 | { | ||
2196 | send_scan_event(container_of(work, struct ipw2100_priv, | ||
2197 | scan_event_later.work)); | ||
2198 | } | ||
2199 | |||
2200 | static void ipw2100_scan_event_now(struct work_struct *work) | ||
2201 | { | ||
2202 | send_scan_event(container_of(work, struct ipw2100_priv, | ||
2203 | scan_event_now)); | ||
2204 | } | ||
2205 | |||
2206 | static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) | 2195 | static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) |
2207 | { | 2196 | { |
2208 | IPW_DEBUG_SCAN("scan complete\n"); | 2197 | IPW_DEBUG_SCAN("scan complete\n"); |
@@ -2212,13 +2201,11 @@ static void isr_scan_complete(struct ipw2100_priv *priv, u32 status) | |||
2212 | 2201 | ||
2213 | /* Only userspace-requested scan completion events go out immediately */ | 2202 | /* Only userspace-requested scan completion events go out immediately */ |
2214 | if (!priv->user_requested_scan) { | 2203 | if (!priv->user_requested_scan) { |
2215 | if (!delayed_work_pending(&priv->scan_event_later)) | 2204 | schedule_delayed_work(&priv->scan_event, |
2216 | schedule_delayed_work(&priv->scan_event_later, | 2205 | round_jiffies_relative(msecs_to_jiffies(4000))); |
2217 | round_jiffies_relative(msecs_to_jiffies(4000))); | ||
2218 | } else { | 2206 | } else { |
2219 | priv->user_requested_scan = 0; | 2207 | priv->user_requested_scan = 0; |
2220 | cancel_delayed_work(&priv->scan_event_later); | 2208 | mod_delayed_work(system_wq, &priv->scan_event, 0); |
2221 | schedule_work(&priv->scan_event_now); | ||
2222 | } | 2209 | } |
2223 | } | 2210 | } |
2224 | 2211 | ||
@@ -4459,8 +4446,7 @@ static void ipw2100_kill_works(struct ipw2100_priv *priv) | |||
4459 | cancel_delayed_work_sync(&priv->wx_event_work); | 4446 | cancel_delayed_work_sync(&priv->wx_event_work); |
4460 | cancel_delayed_work_sync(&priv->hang_check); | 4447 | cancel_delayed_work_sync(&priv->hang_check); |
4461 | cancel_delayed_work_sync(&priv->rf_kill); | 4448 | cancel_delayed_work_sync(&priv->rf_kill); |
4462 | cancel_work_sync(&priv->scan_event_now); | 4449 | cancel_delayed_work_sync(&priv->scan_event); |
4463 | cancel_delayed_work_sync(&priv->scan_event_later); | ||
4464 | } | 4450 | } |
4465 | 4451 | ||
4466 | static int ipw2100_tx_allocate(struct ipw2100_priv *priv) | 4452 | static int ipw2100_tx_allocate(struct ipw2100_priv *priv) |
@@ -6195,8 +6181,7 @@ static struct net_device *ipw2100_alloc_device(struct pci_dev *pci_dev, | |||
6195 | INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); | 6181 | INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work); |
6196 | INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); | 6182 | INIT_DELAYED_WORK(&priv->hang_check, ipw2100_hang_check); |
6197 | INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); | 6183 | INIT_DELAYED_WORK(&priv->rf_kill, ipw2100_rf_kill); |
6198 | INIT_WORK(&priv->scan_event_now, ipw2100_scan_event_now); | 6184 | INIT_DELAYED_WORK(&priv->scan_event, ipw2100_scan_event); |
6199 | INIT_DELAYED_WORK(&priv->scan_event_later, ipw2100_scan_event_later); | ||
6200 | 6185 | ||
6201 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) | 6186 | tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long)) |
6202 | ipw2100_irq_tasklet, (unsigned long)priv); | 6187 | ipw2100_irq_tasklet, (unsigned long)priv); |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.h b/drivers/net/wireless/ipw2x00/ipw2100.h index 5fe17cbab1f3..c6d78790cb0d 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.h +++ b/drivers/net/wireless/ipw2x00/ipw2100.h | |||
@@ -577,8 +577,7 @@ struct ipw2100_priv { | |||
577 | struct delayed_work wx_event_work; | 577 | struct delayed_work wx_event_work; |
578 | struct delayed_work hang_check; | 578 | struct delayed_work hang_check; |
579 | struct delayed_work rf_kill; | 579 | struct delayed_work rf_kill; |
580 | struct work_struct scan_event_now; | 580 | struct delayed_work scan_event; |
581 | struct delayed_work scan_event_later; | ||
582 | 581 | ||
583 | int user_requested_scan; | 582 | int user_requested_scan; |
584 | 583 | ||
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index 844f201b7b70..2c2d6db0536c 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -4480,18 +4480,11 @@ static void handle_scan_event(struct ipw_priv *priv) | |||
4480 | { | 4480 | { |
4481 | /* Only userspace-requested scan completion events go out immediately */ | 4481 | /* Only userspace-requested scan completion events go out immediately */ |
4482 | if (!priv->user_requested_scan) { | 4482 | if (!priv->user_requested_scan) { |
4483 | if (!delayed_work_pending(&priv->scan_event)) | 4483 | schedule_delayed_work(&priv->scan_event, |
4484 | schedule_delayed_work(&priv->scan_event, | 4484 | round_jiffies_relative(msecs_to_jiffies(4000))); |
4485 | round_jiffies_relative(msecs_to_jiffies(4000))); | ||
4486 | } else { | 4485 | } else { |
4487 | union iwreq_data wrqu; | ||
4488 | |||
4489 | priv->user_requested_scan = 0; | 4486 | priv->user_requested_scan = 0; |
4490 | cancel_delayed_work(&priv->scan_event); | 4487 | mod_delayed_work(system_wq, &priv->scan_event, 0); |
4491 | |||
4492 | wrqu.data.length = 0; | ||
4493 | wrqu.data.flags = 0; | ||
4494 | wireless_send_event(priv->net_dev, SIOCGIWSCAN, &wrqu, NULL); | ||
4495 | } | 4488 | } |
4496 | } | 4489 | } |
4497 | 4490 | ||
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c index d604b4036a76..3726cd6fcd75 100644 --- a/drivers/net/wireless/iwlegacy/3945-mac.c +++ b/drivers/net/wireless/iwlegacy/3945-mac.c | |||
@@ -3273,7 +3273,7 @@ il3945_store_measurement(struct device *d, struct device_attribute *attr, | |||
3273 | 3273 | ||
3274 | if (count) { | 3274 | if (count) { |
3275 | char *p = buffer; | 3275 | char *p = buffer; |
3276 | strncpy(buffer, buf, min(sizeof(buffer), count)); | 3276 | strlcpy(buffer, buf, sizeof(buffer)); |
3277 | channel = simple_strtoul(p, NULL, 0); | 3277 | channel = simple_strtoul(p, NULL, 0); |
3278 | if (channel) | 3278 | if (channel) |
3279 | params.channel = channel; | 3279 | params.channel = channel; |
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 7e16d10a7f14..90b8970eadf0 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c | |||
@@ -3958,17 +3958,21 @@ il_connection_init_rx_config(struct il_priv *il) | |||
3958 | 3958 | ||
3959 | memset(&il->staging, 0, sizeof(il->staging)); | 3959 | memset(&il->staging, 0, sizeof(il->staging)); |
3960 | 3960 | ||
3961 | if (!il->vif) { | 3961 | switch (il->iw_mode) { |
3962 | case NL80211_IFTYPE_UNSPECIFIED: | ||
3962 | il->staging.dev_type = RXON_DEV_TYPE_ESS; | 3963 | il->staging.dev_type = RXON_DEV_TYPE_ESS; |
3963 | } else if (il->vif->type == NL80211_IFTYPE_STATION) { | 3964 | break; |
3965 | case NL80211_IFTYPE_STATION: | ||
3964 | il->staging.dev_type = RXON_DEV_TYPE_ESS; | 3966 | il->staging.dev_type = RXON_DEV_TYPE_ESS; |
3965 | il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; | 3967 | il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK; |
3966 | } else if (il->vif->type == NL80211_IFTYPE_ADHOC) { | 3968 | break; |
3969 | case NL80211_IFTYPE_ADHOC: | ||
3967 | il->staging.dev_type = RXON_DEV_TYPE_IBSS; | 3970 | il->staging.dev_type = RXON_DEV_TYPE_IBSS; |
3968 | il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; | 3971 | il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK; |
3969 | il->staging.filter_flags = | 3972 | il->staging.filter_flags = |
3970 | RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; | 3973 | RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK; |
3971 | } else { | 3974 | break; |
3975 | default: | ||
3972 | IL_ERR("Unsupported interface type %d\n", il->vif->type); | 3976 | IL_ERR("Unsupported interface type %d\n", il->vif->type); |
3973 | return; | 3977 | return; |
3974 | } | 3978 | } |
@@ -4550,8 +4554,7 @@ out: | |||
4550 | EXPORT_SYMBOL(il_mac_add_interface); | 4554 | EXPORT_SYMBOL(il_mac_add_interface); |
4551 | 4555 | ||
4552 | static void | 4556 | static void |
4553 | il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, | 4557 | il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif) |
4554 | bool mode_change) | ||
4555 | { | 4558 | { |
4556 | lockdep_assert_held(&il->mutex); | 4559 | lockdep_assert_held(&il->mutex); |
4557 | 4560 | ||
@@ -4560,9 +4563,7 @@ il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif, | |||
4560 | il_force_scan_end(il); | 4563 | il_force_scan_end(il); |
4561 | } | 4564 | } |
4562 | 4565 | ||
4563 | if (!mode_change) | 4566 | il_set_mode(il); |
4564 | il_set_mode(il); | ||
4565 | |||
4566 | } | 4567 | } |
4567 | 4568 | ||
4568 | void | 4569 | void |
@@ -4575,8 +4576,8 @@ il_mac_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif) | |||
4575 | 4576 | ||
4576 | WARN_ON(il->vif != vif); | 4577 | WARN_ON(il->vif != vif); |
4577 | il->vif = NULL; | 4578 | il->vif = NULL; |
4578 | 4579 | il->iw_mode = NL80211_IFTYPE_UNSPECIFIED; | |
4579 | il_teardown_interface(il, vif, false); | 4580 | il_teardown_interface(il, vif); |
4580 | memset(il->bssid, 0, ETH_ALEN); | 4581 | memset(il->bssid, 0, ETH_ALEN); |
4581 | 4582 | ||
4582 | D_MAC80211("leave\n"); | 4583 | D_MAC80211("leave\n"); |
@@ -4685,18 +4686,10 @@ il_mac_change_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
4685 | } | 4686 | } |
4686 | 4687 | ||
4687 | /* success */ | 4688 | /* success */ |
4688 | il_teardown_interface(il, vif, true); | ||
4689 | vif->type = newtype; | 4689 | vif->type = newtype; |
4690 | vif->p2p = false; | 4690 | vif->p2p = false; |
4691 | err = il_set_mode(il); | 4691 | il->iw_mode = newtype; |
4692 | WARN_ON(err); | 4692 | il_teardown_interface(il, vif); |
4693 | /* | ||
4694 | * We've switched internally, but submitting to the | ||
4695 | * device may have failed for some reason. Mask this | ||
4696 | * error, because otherwise mac80211 will not switch | ||
4697 | * (and set the interface type back) and we'll be | ||
4698 | * out of sync with it. | ||
4699 | */ | ||
4700 | err = 0; | 4693 | err = 0; |
4701 | 4694 | ||
4702 | out: | 4695 | out: |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index da21328ca8ed..279796419ea0 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -1079,6 +1079,8 @@ static void iwlagn_set_tx_status(struct iwl_priv *priv, | |||
1079 | { | 1079 | { |
1080 | u16 status = le16_to_cpu(tx_resp->status.status); | 1080 | u16 status = le16_to_cpu(tx_resp->status.status); |
1081 | 1081 | ||
1082 | info->flags &= ~IEEE80211_TX_CTL_AMPDU; | ||
1083 | |||
1082 | info->status.rates[0].count = tx_resp->failure_frame + 1; | 1084 | info->status.rates[0].count = tx_resp->failure_frame + 1; |
1083 | info->flags |= iwl_tx_status_to_mac80211(status); | 1085 | info->flags |= iwl_tx_status_to_mac80211(status); |
1084 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), | 1086 | iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags), |
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c index dad4c4aad91f..8389cd38338b 100644 --- a/drivers/net/wireless/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/iwlwifi/pcie/rx.c | |||
@@ -1166,6 +1166,7 @@ static irqreturn_t iwl_pcie_isr(int irq, void *data) | |||
1166 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && | 1166 | else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) && |
1167 | !trans_pcie->inta) | 1167 | !trans_pcie->inta) |
1168 | iwl_enable_interrupts(trans); | 1168 | iwl_enable_interrupts(trans); |
1169 | return IRQ_HANDLED; | ||
1169 | 1170 | ||
1170 | none: | 1171 | none: |
1171 | /* re-enable interrupts here since we don't have anything to service. */ | 1172 | /* re-enable interrupts here since we don't have anything to service. */ |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index a875499f8945..cdb11b3964e2 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -1459,7 +1459,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
1459 | struct cfg80211_ssid req_ssid; | 1459 | struct cfg80211_ssid req_ssid; |
1460 | int ret, auth_type = 0; | 1460 | int ret, auth_type = 0; |
1461 | struct cfg80211_bss *bss = NULL; | 1461 | struct cfg80211_bss *bss = NULL; |
1462 | u8 is_scanning_required = 0, config_bands = 0; | 1462 | u8 is_scanning_required = 0; |
1463 | 1463 | ||
1464 | memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); | 1464 | memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); |
1465 | 1465 | ||
@@ -1478,19 +1478,6 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, | |||
1478 | /* disconnect before try to associate */ | 1478 | /* disconnect before try to associate */ |
1479 | mwifiex_deauthenticate(priv, NULL); | 1479 | mwifiex_deauthenticate(priv, NULL); |
1480 | 1480 | ||
1481 | if (channel) { | ||
1482 | if (mode == NL80211_IFTYPE_STATION) { | ||
1483 | if (channel->band == IEEE80211_BAND_2GHZ) | ||
1484 | config_bands = BAND_B | BAND_G | BAND_GN; | ||
1485 | else | ||
1486 | config_bands = BAND_A | BAND_AN; | ||
1487 | |||
1488 | if (!((config_bands | priv->adapter->fw_bands) & | ||
1489 | ~priv->adapter->fw_bands)) | ||
1490 | priv->adapter->config_bands = config_bands; | ||
1491 | } | ||
1492 | } | ||
1493 | |||
1494 | /* As this is new association, clear locally stored | 1481 | /* As this is new association, clear locally stored |
1495 | * keys and security related flags */ | 1482 | * keys and security related flags */ |
1496 | priv->sec_info.wpa_enabled = false; | 1483 | priv->sec_info.wpa_enabled = false; |
@@ -1707,9 +1694,9 @@ static int mwifiex_set_ibss_params(struct mwifiex_private *priv, | |||
1707 | 1694 | ||
1708 | if (cfg80211_get_chandef_type(¶ms->chandef) != | 1695 | if (cfg80211_get_chandef_type(¶ms->chandef) != |
1709 | NL80211_CHAN_NO_HT) | 1696 | NL80211_CHAN_NO_HT) |
1710 | config_bands |= BAND_GN; | 1697 | config_bands |= BAND_G | BAND_GN; |
1711 | } else { | 1698 | } else { |
1712 | if (cfg80211_get_chandef_type(¶ms->chandef) != | 1699 | if (cfg80211_get_chandef_type(¶ms->chandef) == |
1713 | NL80211_CHAN_NO_HT) | 1700 | NL80211_CHAN_NO_HT) |
1714 | config_bands = BAND_A; | 1701 | config_bands = BAND_A; |
1715 | else | 1702 | else |
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c index 13fbc4eb1595..b879e1338a54 100644 --- a/drivers/net/wireless/mwifiex/pcie.c +++ b/drivers/net/wireless/mwifiex/pcie.c | |||
@@ -161,7 +161,7 @@ static int mwifiex_pcie_suspend(struct pci_dev *pdev, pm_message_t state) | |||
161 | 161 | ||
162 | if (pdev) { | 162 | if (pdev) { |
163 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); | 163 | card = (struct pcie_service_card *) pci_get_drvdata(pdev); |
164 | if (!card || card->adapter) { | 164 | if (!card || !card->adapter) { |
165 | pr_err("Card or adapter structure is not valid\n"); | 165 | pr_err("Card or adapter structure is not valid\n"); |
166 | return 0; | 166 | return 0; |
167 | } | 167 | } |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 9189a32b7844..973a9d90e9ea 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1563,7 +1563,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1563 | dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n", | 1563 | dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n", |
1564 | scan_rsp->number_of_sets); | 1564 | scan_rsp->number_of_sets); |
1565 | ret = -1; | 1565 | ret = -1; |
1566 | goto done; | 1566 | goto check_next_scan; |
1567 | } | 1567 | } |
1568 | 1568 | ||
1569 | bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); | 1569 | bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); |
@@ -1634,7 +1634,8 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1634 | if (!beacon_size || beacon_size > bytes_left) { | 1634 | if (!beacon_size || beacon_size > bytes_left) { |
1635 | bss_info += bytes_left; | 1635 | bss_info += bytes_left; |
1636 | bytes_left = 0; | 1636 | bytes_left = 0; |
1637 | return -1; | 1637 | ret = -1; |
1638 | goto check_next_scan; | ||
1638 | } | 1639 | } |
1639 | 1640 | ||
1640 | /* Initialize the current working beacon pointer for this BSS | 1641 | /* Initialize the current working beacon pointer for this BSS |
@@ -1690,7 +1691,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1690 | dev_err(priv->adapter->dev, | 1691 | dev_err(priv->adapter->dev, |
1691 | "%s: bytes left < IE length\n", | 1692 | "%s: bytes left < IE length\n", |
1692 | __func__); | 1693 | __func__); |
1693 | goto done; | 1694 | goto check_next_scan; |
1694 | } | 1695 | } |
1695 | if (element_id == WLAN_EID_DS_PARAMS) { | 1696 | if (element_id == WLAN_EID_DS_PARAMS) { |
1696 | channel = *(current_ptr + sizeof(struct ieee_types_header)); | 1697 | channel = *(current_ptr + sizeof(struct ieee_types_header)); |
@@ -1753,6 +1754,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1753 | } | 1754 | } |
1754 | } | 1755 | } |
1755 | 1756 | ||
1757 | check_next_scan: | ||
1756 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); | 1758 | spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); |
1757 | if (list_empty(&adapter->scan_pending_q)) { | 1759 | if (list_empty(&adapter->scan_pending_q)) { |
1758 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); | 1760 | spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); |
@@ -1813,7 +1815,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, | |||
1813 | } | 1815 | } |
1814 | } | 1816 | } |
1815 | 1817 | ||
1816 | done: | ||
1817 | return ret; | 1818 | return ret; |
1818 | } | 1819 | } |
1819 | 1820 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index 5a1c1d0e5599..f2874c3392b4 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -1752,6 +1752,8 @@ mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) | |||
1752 | static struct mmc_host *reset_host; | 1752 | static struct mmc_host *reset_host; |
1753 | static void sdio_card_reset_worker(struct work_struct *work) | 1753 | static void sdio_card_reset_worker(struct work_struct *work) |
1754 | { | 1754 | { |
1755 | struct mmc_host *target = reset_host; | ||
1756 | |||
1755 | /* The actual reset operation must be run outside of driver thread. | 1757 | /* The actual reset operation must be run outside of driver thread. |
1756 | * This is because mmc_remove_host() will cause the device to be | 1758 | * This is because mmc_remove_host() will cause the device to be |
1757 | * instantly destroyed, and the driver then needs to end its thread, | 1759 | * instantly destroyed, and the driver then needs to end its thread, |
@@ -1761,10 +1763,10 @@ static void sdio_card_reset_worker(struct work_struct *work) | |||
1761 | */ | 1763 | */ |
1762 | 1764 | ||
1763 | pr_err("Resetting card...\n"); | 1765 | pr_err("Resetting card...\n"); |
1764 | mmc_remove_host(reset_host); | 1766 | mmc_remove_host(target); |
1765 | /* 20ms delay is based on experiment with sdhci controller */ | 1767 | /* 20ms delay is based on experiment with sdhci controller */ |
1766 | mdelay(20); | 1768 | mdelay(20); |
1767 | mmc_add_host(reset_host); | 1769 | mmc_add_host(target); |
1768 | } | 1770 | } |
1769 | static DECLARE_WORK(card_reset_work, sdio_card_reset_worker); | 1771 | static DECLARE_WORK(card_reset_work, sdio_card_reset_worker); |
1770 | 1772 | ||
@@ -1773,9 +1775,6 @@ static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) | |||
1773 | { | 1775 | { |
1774 | struct sdio_mmc_card *card = adapter->card; | 1776 | struct sdio_mmc_card *card = adapter->card; |
1775 | 1777 | ||
1776 | if (work_pending(&card_reset_work)) | ||
1777 | return; | ||
1778 | |||
1779 | reset_host = card->func->card->host; | 1778 | reset_host = card->func->card->host; |
1780 | schedule_work(&card_reset_work); | 1779 | schedule_work(&card_reset_work); |
1781 | } | 1780 | } |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index cb682561c438..f542bb8ccbc8 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -56,7 +56,6 @@ int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, | |||
56 | */ | 56 | */ |
57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | 57 | int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) |
58 | { | 58 | { |
59 | bool cancel_flag = false; | ||
60 | int status; | 59 | int status; |
61 | struct cmd_ctrl_node *cmd_queued; | 60 | struct cmd_ctrl_node *cmd_queued; |
62 | 61 | ||
@@ -70,14 +69,11 @@ int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter) | |||
70 | atomic_inc(&adapter->cmd_pending); | 69 | atomic_inc(&adapter->cmd_pending); |
71 | 70 | ||
72 | /* Wait for completion */ | 71 | /* Wait for completion */ |
73 | wait_event_interruptible(adapter->cmd_wait_q.wait, | 72 | status = wait_event_interruptible(adapter->cmd_wait_q.wait, |
74 | *(cmd_queued->condition)); | 73 | *(cmd_queued->condition)); |
75 | if (!*(cmd_queued->condition)) | 74 | if (status) { |
76 | cancel_flag = true; | 75 | dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status); |
77 | 76 | return status; | |
78 | if (cancel_flag) { | ||
79 | mwifiex_cancel_pending_ioctl(adapter); | ||
80 | dev_dbg(adapter->dev, "cmd cancel\n"); | ||
81 | } | 77 | } |
82 | 78 | ||
83 | status = adapter->cmd_wait_q.status; | 79 | status = adapter->cmd_wait_q.status; |
@@ -287,6 +283,20 @@ int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, | |||
287 | if (ret) | 283 | if (ret) |
288 | goto done; | 284 | goto done; |
289 | 285 | ||
286 | if (bss_desc) { | ||
287 | u8 config_bands = 0; | ||
288 | |||
289 | if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band) | ||
290 | == HostCmd_SCAN_RADIO_TYPE_BG) | ||
291 | config_bands = BAND_B | BAND_G | BAND_GN; | ||
292 | else | ||
293 | config_bands = BAND_A | BAND_AN; | ||
294 | |||
295 | if (!((config_bands | adapter->fw_bands) & | ||
296 | ~adapter->fw_bands)) | ||
297 | adapter->config_bands = config_bands; | ||
298 | } | ||
299 | |||
290 | ret = mwifiex_check_network_compatibility(priv, bss_desc); | 300 | ret = mwifiex_check_network_compatibility(priv, bss_desc); |
291 | if (ret) | 301 | if (ret) |
292 | goto done; | 302 | goto done; |
@@ -496,8 +506,11 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter) | |||
496 | return false; | 506 | return false; |
497 | } | 507 | } |
498 | 508 | ||
499 | wait_event_interruptible(adapter->hs_activate_wait_q, | 509 | if (wait_event_interruptible(adapter->hs_activate_wait_q, |
500 | adapter->hs_activate_wait_q_woken); | 510 | adapter->hs_activate_wait_q_woken)) { |
511 | dev_err(adapter->dev, "hs_activate_wait_q terminated\n"); | ||
512 | return false; | ||
513 | } | ||
501 | 514 | ||
502 | return true; | 515 | return true; |
503 | } | 516 | } |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index f221b95b90b3..a00a03ea4ec9 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -318,20 +318,20 @@ struct mwl8k_sta { | |||
318 | #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) | 318 | #define MWL8K_STA(_sta) ((struct mwl8k_sta *)&((_sta)->drv_priv)) |
319 | 319 | ||
320 | static const struct ieee80211_channel mwl8k_channels_24[] = { | 320 | static const struct ieee80211_channel mwl8k_channels_24[] = { |
321 | { .center_freq = 2412, .hw_value = 1, }, | 321 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2412, .hw_value = 1, }, |
322 | { .center_freq = 2417, .hw_value = 2, }, | 322 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2417, .hw_value = 2, }, |
323 | { .center_freq = 2422, .hw_value = 3, }, | 323 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2422, .hw_value = 3, }, |
324 | { .center_freq = 2427, .hw_value = 4, }, | 324 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2427, .hw_value = 4, }, |
325 | { .center_freq = 2432, .hw_value = 5, }, | 325 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2432, .hw_value = 5, }, |
326 | { .center_freq = 2437, .hw_value = 6, }, | 326 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2437, .hw_value = 6, }, |
327 | { .center_freq = 2442, .hw_value = 7, }, | 327 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2442, .hw_value = 7, }, |
328 | { .center_freq = 2447, .hw_value = 8, }, | 328 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2447, .hw_value = 8, }, |
329 | { .center_freq = 2452, .hw_value = 9, }, | 329 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2452, .hw_value = 9, }, |
330 | { .center_freq = 2457, .hw_value = 10, }, | 330 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2457, .hw_value = 10, }, |
331 | { .center_freq = 2462, .hw_value = 11, }, | 331 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2462, .hw_value = 11, }, |
332 | { .center_freq = 2467, .hw_value = 12, }, | 332 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2467, .hw_value = 12, }, |
333 | { .center_freq = 2472, .hw_value = 13, }, | 333 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2472, .hw_value = 13, }, |
334 | { .center_freq = 2484, .hw_value = 14, }, | 334 | { .band = IEEE80211_BAND_2GHZ, .center_freq = 2484, .hw_value = 14, }, |
335 | }; | 335 | }; |
336 | 336 | ||
337 | static const struct ieee80211_rate mwl8k_rates_24[] = { | 337 | static const struct ieee80211_rate mwl8k_rates_24[] = { |
@@ -352,10 +352,10 @@ static const struct ieee80211_rate mwl8k_rates_24[] = { | |||
352 | }; | 352 | }; |
353 | 353 | ||
354 | static const struct ieee80211_channel mwl8k_channels_50[] = { | 354 | static const struct ieee80211_channel mwl8k_channels_50[] = { |
355 | { .center_freq = 5180, .hw_value = 36, }, | 355 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5180, .hw_value = 36, }, |
356 | { .center_freq = 5200, .hw_value = 40, }, | 356 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5200, .hw_value = 40, }, |
357 | { .center_freq = 5220, .hw_value = 44, }, | 357 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5220, .hw_value = 44, }, |
358 | { .center_freq = 5240, .hw_value = 48, }, | 358 | { .band = IEEE80211_BAND_5GHZ, .center_freq = 5240, .hw_value = 48, }, |
359 | }; | 359 | }; |
360 | 360 | ||
361 | static const struct ieee80211_rate mwl8k_rates_50[] = { | 361 | static const struct ieee80211_rate mwl8k_rates_50[] = { |
@@ -4250,9 +4250,11 @@ static int mwl8k_cmd_update_stadb_add(struct ieee80211_hw *hw, | |||
4250 | p->amsdu_enabled = 0; | 4250 | p->amsdu_enabled = 0; |
4251 | 4251 | ||
4252 | rc = mwl8k_post_cmd(hw, &cmd->header); | 4252 | rc = mwl8k_post_cmd(hw, &cmd->header); |
4253 | if (!rc) | ||
4254 | rc = p->station_id; | ||
4253 | kfree(cmd); | 4255 | kfree(cmd); |
4254 | 4256 | ||
4255 | return rc ? rc : p->station_id; | 4257 | return rc; |
4256 | } | 4258 | } |
4257 | 4259 | ||
4258 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, | 4260 | static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig index 21b1bbb93a7e..b80bc4612581 100644 --- a/drivers/net/wireless/rtlwifi/Kconfig +++ b/drivers/net/wireless/rtlwifi/Kconfig | |||
@@ -57,12 +57,12 @@ config RTL8192CU | |||
57 | 57 | ||
58 | config RTLWIFI | 58 | config RTLWIFI |
59 | tristate | 59 | tristate |
60 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE | 60 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE |
61 | default m | 61 | default m |
62 | 62 | ||
63 | config RTLWIFI_DEBUG | 63 | config RTLWIFI_DEBUG |
64 | bool "Additional debugging output" | 64 | bool "Additional debugging output" |
65 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE | 65 | depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE |
66 | default y | 66 | default y |
67 | 67 | ||
68 | config RTL8192C_COMMON | 68 | config RTL8192C_COMMON |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 4494d130b37c..0f8b05185eda 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -1004,7 +1004,8 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1004 | is_tx ? "Tx" : "Rx"); | 1004 | is_tx ? "Tx" : "Rx"); |
1005 | 1005 | ||
1006 | if (is_tx) { | 1006 | if (is_tx) { |
1007 | rtl_lps_leave(hw); | 1007 | schedule_work(&rtlpriv-> |
1008 | works.lps_leave_work); | ||
1008 | ppsc->last_delaylps_stamp_jiffies = | 1009 | ppsc->last_delaylps_stamp_jiffies = |
1009 | jiffies; | 1010 | jiffies; |
1010 | } | 1011 | } |
@@ -1014,7 +1015,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1014 | } | 1015 | } |
1015 | } else if (ETH_P_ARP == ether_type) { | 1016 | } else if (ETH_P_ARP == ether_type) { |
1016 | if (is_tx) { | 1017 | if (is_tx) { |
1017 | rtl_lps_leave(hw); | 1018 | schedule_work(&rtlpriv->works.lps_leave_work); |
1018 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1019 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1019 | } | 1020 | } |
1020 | 1021 | ||
@@ -1024,7 +1025,7 @@ u8 rtl_is_special_data(struct ieee80211_hw *hw, struct sk_buff *skb, u8 is_tx) | |||
1024 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); | 1025 | "802.1X %s EAPOL pkt!!\n", is_tx ? "Tx" : "Rx"); |
1025 | 1026 | ||
1026 | if (is_tx) { | 1027 | if (is_tx) { |
1027 | rtl_lps_leave(hw); | 1028 | schedule_work(&rtlpriv->works.lps_leave_work); |
1028 | ppsc->last_delaylps_stamp_jiffies = jiffies; | 1029 | ppsc->last_delaylps_stamp_jiffies = jiffies; |
1029 | } | 1030 | } |
1030 | 1031 | ||
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c index 1d5d3604e3e0..246e5352f2e1 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c | |||
@@ -692,7 +692,7 @@ u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw) | |||
692 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | 692 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { |
693 | rtl92c_phy_sw_chnl_callback(hw); | 693 | rtl92c_phy_sw_chnl_callback(hw); |
694 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 694 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
695 | "sw_chnl_inprogress false schdule workitem\n"); | 695 | "sw_chnl_inprogress false schedule workitem\n"); |
696 | rtlphy->sw_chnl_inprogress = false; | 696 | rtlphy->sw_chnl_inprogress = false; |
697 | } else { | 697 | } else { |
698 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 698 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c index 39cc7938eedf..3d8536bb0d2b 100644 --- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c | |||
@@ -1106,7 +1106,7 @@ u8 rtl8723ae_phy_sw_chnl(struct ieee80211_hw *hw) | |||
1106 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { | 1106 | if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) { |
1107 | rtl8723ae_phy_sw_chnl_callback(hw); | 1107 | rtl8723ae_phy_sw_chnl_callback(hw); |
1108 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 1108 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
1109 | "sw_chnl_inprogress false schdule workitem\n"); | 1109 | "sw_chnl_inprogress false schedule workitem\n"); |
1110 | rtlphy->sw_chnl_inprogress = false; | 1110 | rtlphy->sw_chnl_inprogress = false; |
1111 | } else { | 1111 | } else { |
1112 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, | 1112 | RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD, |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index f2ecdeb3a90d..1535efda3d52 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -542,8 +542,8 @@ static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
542 | WARN_ON(skb_queue_empty(&rx_queue)); | 542 | WARN_ON(skb_queue_empty(&rx_queue)); |
543 | while (!skb_queue_empty(&rx_queue)) { | 543 | while (!skb_queue_empty(&rx_queue)) { |
544 | _skb = skb_dequeue(&rx_queue); | 544 | _skb = skb_dequeue(&rx_queue); |
545 | _rtl_usb_rx_process_agg(hw, skb); | 545 | _rtl_usb_rx_process_agg(hw, _skb); |
546 | ieee80211_rx_irqsafe(hw, skb); | 546 | ieee80211_rx_irqsafe(hw, _skb); |
547 | } | 547 | } |
548 | } | 548 | } |
549 | 549 | ||
diff --git a/drivers/net/wireless/ti/wl1251/ps.c b/drivers/net/wireless/ti/wl1251/ps.c index db719f7d2692..b9e27b98bbc9 100644 --- a/drivers/net/wireless/ti/wl1251/ps.c +++ b/drivers/net/wireless/ti/wl1251/ps.c | |||
@@ -68,8 +68,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl) | |||
68 | unsigned long timeout, start; | 68 | unsigned long timeout, start; |
69 | u32 elp_reg; | 69 | u32 elp_reg; |
70 | 70 | ||
71 | if (delayed_work_pending(&wl->elp_work)) | 71 | cancel_delayed_work(&wl->elp_work); |
72 | cancel_delayed_work(&wl->elp_work); | ||
73 | 72 | ||
74 | if (!wl->elp) | 73 | if (!wl->elp) |
75 | return 0; | 74 | return 0; |
diff --git a/drivers/net/xen-netback/common.h b/drivers/net/xen-netback/common.h index 94b79c3338c4..9d7f1723dd8f 100644 --- a/drivers/net/xen-netback/common.h +++ b/drivers/net/xen-netback/common.h | |||
@@ -151,6 +151,9 @@ void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb); | |||
151 | /* Notify xenvif that ring now has space to send an skb to the frontend */ | 151 | /* Notify xenvif that ring now has space to send an skb to the frontend */ |
152 | void xenvif_notify_tx_completion(struct xenvif *vif); | 152 | void xenvif_notify_tx_completion(struct xenvif *vif); |
153 | 153 | ||
154 | /* Prevent the device from generating any further traffic. */ | ||
155 | void xenvif_carrier_off(struct xenvif *vif); | ||
156 | |||
154 | /* Returns number of ring slots required to send an skb to the frontend */ | 157 | /* Returns number of ring slots required to send an skb to the frontend */ |
155 | unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); | 158 | unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb); |
156 | 159 | ||
diff --git a/drivers/net/xen-netback/interface.c b/drivers/net/xen-netback/interface.c index b7d41f8c338a..b8c5193bd420 100644 --- a/drivers/net/xen-netback/interface.c +++ b/drivers/net/xen-netback/interface.c | |||
@@ -343,17 +343,22 @@ err: | |||
343 | return err; | 343 | return err; |
344 | } | 344 | } |
345 | 345 | ||
346 | void xenvif_disconnect(struct xenvif *vif) | 346 | void xenvif_carrier_off(struct xenvif *vif) |
347 | { | 347 | { |
348 | struct net_device *dev = vif->dev; | 348 | struct net_device *dev = vif->dev; |
349 | if (netif_carrier_ok(dev)) { | 349 | |
350 | rtnl_lock(); | 350 | rtnl_lock(); |
351 | netif_carrier_off(dev); /* discard queued packets */ | 351 | netif_carrier_off(dev); /* discard queued packets */ |
352 | if (netif_running(dev)) | 352 | if (netif_running(dev)) |
353 | xenvif_down(vif); | 353 | xenvif_down(vif); |
354 | rtnl_unlock(); | 354 | rtnl_unlock(); |
355 | xenvif_put(vif); | 355 | xenvif_put(vif); |
356 | } | 356 | } |
357 | |||
358 | void xenvif_disconnect(struct xenvif *vif) | ||
359 | { | ||
360 | if (netif_carrier_ok(vif->dev)) | ||
361 | xenvif_carrier_off(vif); | ||
357 | 362 | ||
358 | atomic_dec(&vif->refcnt); | 363 | atomic_dec(&vif->refcnt); |
359 | wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); | 364 | wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0); |
diff --git a/drivers/net/xen-netback/netback.c b/drivers/net/xen-netback/netback.c index f2d6b78d901d..2b9520c46e97 100644 --- a/drivers/net/xen-netback/netback.c +++ b/drivers/net/xen-netback/netback.c | |||
@@ -147,7 +147,8 @@ void xen_netbk_remove_xenvif(struct xenvif *vif) | |||
147 | atomic_dec(&netbk->netfront_count); | 147 | atomic_dec(&netbk->netfront_count); |
148 | } | 148 | } |
149 | 149 | ||
150 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx); | 150 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, |
151 | u8 status); | ||
151 | static void make_tx_response(struct xenvif *vif, | 152 | static void make_tx_response(struct xenvif *vif, |
152 | struct xen_netif_tx_request *txp, | 153 | struct xen_netif_tx_request *txp, |
153 | s8 st); | 154 | s8 st); |
@@ -879,7 +880,7 @@ static void netbk_tx_err(struct xenvif *vif, | |||
879 | 880 | ||
880 | do { | 881 | do { |
881 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); | 882 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); |
882 | if (cons >= end) | 883 | if (cons == end) |
883 | break; | 884 | break; |
884 | txp = RING_GET_REQUEST(&vif->tx, cons++); | 885 | txp = RING_GET_REQUEST(&vif->tx, cons++); |
885 | } while (1); | 886 | } while (1); |
@@ -888,6 +889,13 @@ static void netbk_tx_err(struct xenvif *vif, | |||
888 | xenvif_put(vif); | 889 | xenvif_put(vif); |
889 | } | 890 | } |
890 | 891 | ||
892 | static void netbk_fatal_tx_err(struct xenvif *vif) | ||
893 | { | ||
894 | netdev_err(vif->dev, "fatal error; disabling device\n"); | ||
895 | xenvif_carrier_off(vif); | ||
896 | xenvif_put(vif); | ||
897 | } | ||
898 | |||
891 | static int netbk_count_requests(struct xenvif *vif, | 899 | static int netbk_count_requests(struct xenvif *vif, |
892 | struct xen_netif_tx_request *first, | 900 | struct xen_netif_tx_request *first, |
893 | struct xen_netif_tx_request *txp, | 901 | struct xen_netif_tx_request *txp, |
@@ -901,19 +909,22 @@ static int netbk_count_requests(struct xenvif *vif, | |||
901 | 909 | ||
902 | do { | 910 | do { |
903 | if (frags >= work_to_do) { | 911 | if (frags >= work_to_do) { |
904 | netdev_dbg(vif->dev, "Need more frags\n"); | 912 | netdev_err(vif->dev, "Need more frags\n"); |
913 | netbk_fatal_tx_err(vif); | ||
905 | return -frags; | 914 | return -frags; |
906 | } | 915 | } |
907 | 916 | ||
908 | if (unlikely(frags >= MAX_SKB_FRAGS)) { | 917 | if (unlikely(frags >= MAX_SKB_FRAGS)) { |
909 | netdev_dbg(vif->dev, "Too many frags\n"); | 918 | netdev_err(vif->dev, "Too many frags\n"); |
919 | netbk_fatal_tx_err(vif); | ||
910 | return -frags; | 920 | return -frags; |
911 | } | 921 | } |
912 | 922 | ||
913 | memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), | 923 | memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags), |
914 | sizeof(*txp)); | 924 | sizeof(*txp)); |
915 | if (txp->size > first->size) { | 925 | if (txp->size > first->size) { |
916 | netdev_dbg(vif->dev, "Frags galore\n"); | 926 | netdev_err(vif->dev, "Frag is bigger than frame.\n"); |
927 | netbk_fatal_tx_err(vif); | ||
917 | return -frags; | 928 | return -frags; |
918 | } | 929 | } |
919 | 930 | ||
@@ -921,8 +932,9 @@ static int netbk_count_requests(struct xenvif *vif, | |||
921 | frags++; | 932 | frags++; |
922 | 933 | ||
923 | if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { | 934 | if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) { |
924 | netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n", | 935 | netdev_err(vif->dev, "txp->offset: %x, size: %u\n", |
925 | txp->offset, txp->size); | 936 | txp->offset, txp->size); |
937 | netbk_fatal_tx_err(vif); | ||
926 | return -frags; | 938 | return -frags; |
927 | } | 939 | } |
928 | } while ((txp++)->flags & XEN_NETTXF_more_data); | 940 | } while ((txp++)->flags & XEN_NETTXF_more_data); |
@@ -966,7 +978,7 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, | |||
966 | pending_idx = netbk->pending_ring[index]; | 978 | pending_idx = netbk->pending_ring[index]; |
967 | page = xen_netbk_alloc_page(netbk, skb, pending_idx); | 979 | page = xen_netbk_alloc_page(netbk, skb, pending_idx); |
968 | if (!page) | 980 | if (!page) |
969 | return NULL; | 981 | goto err; |
970 | 982 | ||
971 | gop->source.u.ref = txp->gref; | 983 | gop->source.u.ref = txp->gref; |
972 | gop->source.domid = vif->domid; | 984 | gop->source.domid = vif->domid; |
@@ -988,6 +1000,17 @@ static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk, | |||
988 | } | 1000 | } |
989 | 1001 | ||
990 | return gop; | 1002 | return gop; |
1003 | err: | ||
1004 | /* Unwind, freeing all pages and sending error responses. */ | ||
1005 | while (i-- > start) { | ||
1006 | xen_netbk_idx_release(netbk, frag_get_pending_idx(&frags[i]), | ||
1007 | XEN_NETIF_RSP_ERROR); | ||
1008 | } | ||
1009 | /* The head too, if necessary. */ | ||
1010 | if (start) | ||
1011 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); | ||
1012 | |||
1013 | return NULL; | ||
991 | } | 1014 | } |
992 | 1015 | ||
993 | static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | 1016 | static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, |
@@ -996,30 +1019,20 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
996 | { | 1019 | { |
997 | struct gnttab_copy *gop = *gopp; | 1020 | struct gnttab_copy *gop = *gopp; |
998 | u16 pending_idx = *((u16 *)skb->data); | 1021 | u16 pending_idx = *((u16 *)skb->data); |
999 | struct pending_tx_info *pending_tx_info = netbk->pending_tx_info; | ||
1000 | struct xenvif *vif = pending_tx_info[pending_idx].vif; | ||
1001 | struct xen_netif_tx_request *txp; | ||
1002 | struct skb_shared_info *shinfo = skb_shinfo(skb); | 1022 | struct skb_shared_info *shinfo = skb_shinfo(skb); |
1003 | int nr_frags = shinfo->nr_frags; | 1023 | int nr_frags = shinfo->nr_frags; |
1004 | int i, err, start; | 1024 | int i, err, start; |
1005 | 1025 | ||
1006 | /* Check status of header. */ | 1026 | /* Check status of header. */ |
1007 | err = gop->status; | 1027 | err = gop->status; |
1008 | if (unlikely(err)) { | 1028 | if (unlikely(err)) |
1009 | pending_ring_idx_t index; | 1029 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); |
1010 | index = pending_index(netbk->pending_prod++); | ||
1011 | txp = &pending_tx_info[pending_idx].req; | ||
1012 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); | ||
1013 | netbk->pending_ring[index] = pending_idx; | ||
1014 | xenvif_put(vif); | ||
1015 | } | ||
1016 | 1030 | ||
1017 | /* Skip first skb fragment if it is on same page as header fragment. */ | 1031 | /* Skip first skb fragment if it is on same page as header fragment. */ |
1018 | start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); | 1032 | start = (frag_get_pending_idx(&shinfo->frags[0]) == pending_idx); |
1019 | 1033 | ||
1020 | for (i = start; i < nr_frags; i++) { | 1034 | for (i = start; i < nr_frags; i++) { |
1021 | int j, newerr; | 1035 | int j, newerr; |
1022 | pending_ring_idx_t index; | ||
1023 | 1036 | ||
1024 | pending_idx = frag_get_pending_idx(&shinfo->frags[i]); | 1037 | pending_idx = frag_get_pending_idx(&shinfo->frags[i]); |
1025 | 1038 | ||
@@ -1028,16 +1041,12 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
1028 | if (likely(!newerr)) { | 1041 | if (likely(!newerr)) { |
1029 | /* Had a previous error? Invalidate this fragment. */ | 1042 | /* Had a previous error? Invalidate this fragment. */ |
1030 | if (unlikely(err)) | 1043 | if (unlikely(err)) |
1031 | xen_netbk_idx_release(netbk, pending_idx); | 1044 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1032 | continue; | 1045 | continue; |
1033 | } | 1046 | } |
1034 | 1047 | ||
1035 | /* Error on this fragment: respond to client with an error. */ | 1048 | /* Error on this fragment: respond to client with an error. */ |
1036 | txp = &netbk->pending_tx_info[pending_idx].req; | 1049 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_ERROR); |
1037 | make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR); | ||
1038 | index = pending_index(netbk->pending_prod++); | ||
1039 | netbk->pending_ring[index] = pending_idx; | ||
1040 | xenvif_put(vif); | ||
1041 | 1050 | ||
1042 | /* Not the first error? Preceding frags already invalidated. */ | 1051 | /* Not the first error? Preceding frags already invalidated. */ |
1043 | if (err) | 1052 | if (err) |
@@ -1045,10 +1054,10 @@ static int xen_netbk_tx_check_gop(struct xen_netbk *netbk, | |||
1045 | 1054 | ||
1046 | /* First error: invalidate header and preceding fragments. */ | 1055 | /* First error: invalidate header and preceding fragments. */ |
1047 | pending_idx = *((u16 *)skb->data); | 1056 | pending_idx = *((u16 *)skb->data); |
1048 | xen_netbk_idx_release(netbk, pending_idx); | 1057 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1049 | for (j = start; j < i; j++) { | 1058 | for (j = start; j < i; j++) { |
1050 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); | 1059 | pending_idx = frag_get_pending_idx(&shinfo->frags[j]); |
1051 | xen_netbk_idx_release(netbk, pending_idx); | 1060 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1052 | } | 1061 | } |
1053 | 1062 | ||
1054 | /* Remember the error: invalidate all subsequent fragments. */ | 1063 | /* Remember the error: invalidate all subsequent fragments. */ |
@@ -1082,7 +1091,7 @@ static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb) | |||
1082 | 1091 | ||
1083 | /* Take an extra reference to offset xen_netbk_idx_release */ | 1092 | /* Take an extra reference to offset xen_netbk_idx_release */ |
1084 | get_page(netbk->mmap_pages[pending_idx]); | 1093 | get_page(netbk->mmap_pages[pending_idx]); |
1085 | xen_netbk_idx_release(netbk, pending_idx); | 1094 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1086 | } | 1095 | } |
1087 | } | 1096 | } |
1088 | 1097 | ||
@@ -1095,7 +1104,8 @@ static int xen_netbk_get_extras(struct xenvif *vif, | |||
1095 | 1104 | ||
1096 | do { | 1105 | do { |
1097 | if (unlikely(work_to_do-- <= 0)) { | 1106 | if (unlikely(work_to_do-- <= 0)) { |
1098 | netdev_dbg(vif->dev, "Missing extra info\n"); | 1107 | netdev_err(vif->dev, "Missing extra info\n"); |
1108 | netbk_fatal_tx_err(vif); | ||
1099 | return -EBADR; | 1109 | return -EBADR; |
1100 | } | 1110 | } |
1101 | 1111 | ||
@@ -1104,8 +1114,9 @@ static int xen_netbk_get_extras(struct xenvif *vif, | |||
1104 | if (unlikely(!extra.type || | 1114 | if (unlikely(!extra.type || |
1105 | extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { | 1115 | extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) { |
1106 | vif->tx.req_cons = ++cons; | 1116 | vif->tx.req_cons = ++cons; |
1107 | netdev_dbg(vif->dev, | 1117 | netdev_err(vif->dev, |
1108 | "Invalid extra type: %d\n", extra.type); | 1118 | "Invalid extra type: %d\n", extra.type); |
1119 | netbk_fatal_tx_err(vif); | ||
1109 | return -EINVAL; | 1120 | return -EINVAL; |
1110 | } | 1121 | } |
1111 | 1122 | ||
@@ -1121,13 +1132,15 @@ static int netbk_set_skb_gso(struct xenvif *vif, | |||
1121 | struct xen_netif_extra_info *gso) | 1132 | struct xen_netif_extra_info *gso) |
1122 | { | 1133 | { |
1123 | if (!gso->u.gso.size) { | 1134 | if (!gso->u.gso.size) { |
1124 | netdev_dbg(vif->dev, "GSO size must not be zero.\n"); | 1135 | netdev_err(vif->dev, "GSO size must not be zero.\n"); |
1136 | netbk_fatal_tx_err(vif); | ||
1125 | return -EINVAL; | 1137 | return -EINVAL; |
1126 | } | 1138 | } |
1127 | 1139 | ||
1128 | /* Currently only TCPv4 S.O. is supported. */ | 1140 | /* Currently only TCPv4 S.O. is supported. */ |
1129 | if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { | 1141 | if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) { |
1130 | netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); | 1142 | netdev_err(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type); |
1143 | netbk_fatal_tx_err(vif); | ||
1131 | return -EINVAL; | 1144 | return -EINVAL; |
1132 | } | 1145 | } |
1133 | 1146 | ||
@@ -1264,9 +1277,25 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1264 | 1277 | ||
1265 | /* Get a netif from the list with work to do. */ | 1278 | /* Get a netif from the list with work to do. */ |
1266 | vif = poll_net_schedule_list(netbk); | 1279 | vif = poll_net_schedule_list(netbk); |
1280 | /* This can sometimes happen because the test of | ||
1281 | * list_empty(net_schedule_list) at the top of the | ||
1282 | * loop is unlocked. Just go back and have another | ||
1283 | * look. | ||
1284 | */ | ||
1267 | if (!vif) | 1285 | if (!vif) |
1268 | continue; | 1286 | continue; |
1269 | 1287 | ||
1288 | if (vif->tx.sring->req_prod - vif->tx.req_cons > | ||
1289 | XEN_NETIF_TX_RING_SIZE) { | ||
1290 | netdev_err(vif->dev, | ||
1291 | "Impossible number of requests. " | ||
1292 | "req_prod %d, req_cons %d, size %ld\n", | ||
1293 | vif->tx.sring->req_prod, vif->tx.req_cons, | ||
1294 | XEN_NETIF_TX_RING_SIZE); | ||
1295 | netbk_fatal_tx_err(vif); | ||
1296 | continue; | ||
1297 | } | ||
1298 | |||
1270 | RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); | 1299 | RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do); |
1271 | if (!work_to_do) { | 1300 | if (!work_to_do) { |
1272 | xenvif_put(vif); | 1301 | xenvif_put(vif); |
@@ -1294,17 +1323,14 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1294 | work_to_do = xen_netbk_get_extras(vif, extras, | 1323 | work_to_do = xen_netbk_get_extras(vif, extras, |
1295 | work_to_do); | 1324 | work_to_do); |
1296 | idx = vif->tx.req_cons; | 1325 | idx = vif->tx.req_cons; |
1297 | if (unlikely(work_to_do < 0)) { | 1326 | if (unlikely(work_to_do < 0)) |
1298 | netbk_tx_err(vif, &txreq, idx); | ||
1299 | continue; | 1327 | continue; |
1300 | } | ||
1301 | } | 1328 | } |
1302 | 1329 | ||
1303 | ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); | 1330 | ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do); |
1304 | if (unlikely(ret < 0)) { | 1331 | if (unlikely(ret < 0)) |
1305 | netbk_tx_err(vif, &txreq, idx - ret); | ||
1306 | continue; | 1332 | continue; |
1307 | } | 1333 | |
1308 | idx += ret; | 1334 | idx += ret; |
1309 | 1335 | ||
1310 | if (unlikely(txreq.size < ETH_HLEN)) { | 1336 | if (unlikely(txreq.size < ETH_HLEN)) { |
@@ -1316,11 +1342,11 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1316 | 1342 | ||
1317 | /* No crossing a page as the payload mustn't fragment. */ | 1343 | /* No crossing a page as the payload mustn't fragment. */ |
1318 | if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { | 1344 | if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) { |
1319 | netdev_dbg(vif->dev, | 1345 | netdev_err(vif->dev, |
1320 | "txreq.offset: %x, size: %u, end: %lu\n", | 1346 | "txreq.offset: %x, size: %u, end: %lu\n", |
1321 | txreq.offset, txreq.size, | 1347 | txreq.offset, txreq.size, |
1322 | (txreq.offset&~PAGE_MASK) + txreq.size); | 1348 | (txreq.offset&~PAGE_MASK) + txreq.size); |
1323 | netbk_tx_err(vif, &txreq, idx); | 1349 | netbk_fatal_tx_err(vif); |
1324 | continue; | 1350 | continue; |
1325 | } | 1351 | } |
1326 | 1352 | ||
@@ -1348,8 +1374,8 @@ static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk) | |||
1348 | gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; | 1374 | gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1]; |
1349 | 1375 | ||
1350 | if (netbk_set_skb_gso(vif, skb, gso)) { | 1376 | if (netbk_set_skb_gso(vif, skb, gso)) { |
1377 | /* Failure in netbk_set_skb_gso is fatal. */ | ||
1351 | kfree_skb(skb); | 1378 | kfree_skb(skb); |
1352 | netbk_tx_err(vif, &txreq, idx); | ||
1353 | continue; | 1379 | continue; |
1354 | } | 1380 | } |
1355 | } | 1381 | } |
@@ -1448,7 +1474,7 @@ static void xen_netbk_tx_submit(struct xen_netbk *netbk) | |||
1448 | txp->size -= data_len; | 1474 | txp->size -= data_len; |
1449 | } else { | 1475 | } else { |
1450 | /* Schedule a response immediately. */ | 1476 | /* Schedule a response immediately. */ |
1451 | xen_netbk_idx_release(netbk, pending_idx); | 1477 | xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY); |
1452 | } | 1478 | } |
1453 | 1479 | ||
1454 | if (txp->flags & XEN_NETTXF_csum_blank) | 1480 | if (txp->flags & XEN_NETTXF_csum_blank) |
@@ -1500,7 +1526,8 @@ static void xen_netbk_tx_action(struct xen_netbk *netbk) | |||
1500 | xen_netbk_tx_submit(netbk); | 1526 | xen_netbk_tx_submit(netbk); |
1501 | } | 1527 | } |
1502 | 1528 | ||
1503 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) | 1529 | static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx, |
1530 | u8 status) | ||
1504 | { | 1531 | { |
1505 | struct xenvif *vif; | 1532 | struct xenvif *vif; |
1506 | struct pending_tx_info *pending_tx_info; | 1533 | struct pending_tx_info *pending_tx_info; |
@@ -1514,7 +1541,7 @@ static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx) | |||
1514 | 1541 | ||
1515 | vif = pending_tx_info->vif; | 1542 | vif = pending_tx_info->vif; |
1516 | 1543 | ||
1517 | make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY); | 1544 | make_tx_response(vif, &pending_tx_info->req, status); |
1518 | 1545 | ||
1519 | index = pending_index(netbk->pending_prod++); | 1546 | index = pending_index(netbk->pending_prod++); |
1520 | netbk->pending_ring[index] = pending_idx; | 1547 | netbk->pending_ring[index] = pending_idx; |
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h index 26ffd3e3fb74..2c113de94323 100644 --- a/drivers/pci/hotplug/pciehp.h +++ b/drivers/pci/hotplug/pciehp.h | |||
@@ -44,7 +44,6 @@ extern bool pciehp_poll_mode; | |||
44 | extern int pciehp_poll_time; | 44 | extern int pciehp_poll_time; |
45 | extern bool pciehp_debug; | 45 | extern bool pciehp_debug; |
46 | extern bool pciehp_force; | 46 | extern bool pciehp_force; |
47 | extern struct workqueue_struct *pciehp_wq; | ||
48 | 47 | ||
49 | #define dbg(format, arg...) \ | 48 | #define dbg(format, arg...) \ |
50 | do { \ | 49 | do { \ |
@@ -78,6 +77,7 @@ struct slot { | |||
78 | struct hotplug_slot *hotplug_slot; | 77 | struct hotplug_slot *hotplug_slot; |
79 | struct delayed_work work; /* work for button event */ | 78 | struct delayed_work work; /* work for button event */ |
80 | struct mutex lock; | 79 | struct mutex lock; |
80 | struct workqueue_struct *wq; | ||
81 | }; | 81 | }; |
82 | 82 | ||
83 | struct event_info { | 83 | struct event_info { |
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c index 916bf4f53aba..939bd1d4b5b1 100644 --- a/drivers/pci/hotplug/pciehp_core.c +++ b/drivers/pci/hotplug/pciehp_core.c | |||
@@ -42,7 +42,6 @@ bool pciehp_debug; | |||
42 | bool pciehp_poll_mode; | 42 | bool pciehp_poll_mode; |
43 | int pciehp_poll_time; | 43 | int pciehp_poll_time; |
44 | bool pciehp_force; | 44 | bool pciehp_force; |
45 | struct workqueue_struct *pciehp_wq; | ||
46 | 45 | ||
47 | #define DRIVER_VERSION "0.4" | 46 | #define DRIVER_VERSION "0.4" |
48 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 47 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -340,18 +339,13 @@ static int __init pcied_init(void) | |||
340 | { | 339 | { |
341 | int retval = 0; | 340 | int retval = 0; |
342 | 341 | ||
343 | pciehp_wq = alloc_workqueue("pciehp", 0, 0); | ||
344 | if (!pciehp_wq) | ||
345 | return -ENOMEM; | ||
346 | |||
347 | pciehp_firmware_init(); | 342 | pciehp_firmware_init(); |
348 | retval = pcie_port_service_register(&hpdriver_portdrv); | 343 | retval = pcie_port_service_register(&hpdriver_portdrv); |
349 | dbg("pcie_port_service_register = %d\n", retval); | 344 | dbg("pcie_port_service_register = %d\n", retval); |
350 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 345 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
351 | if (retval) { | 346 | if (retval) |
352 | destroy_workqueue(pciehp_wq); | ||
353 | dbg("Failure to register service\n"); | 347 | dbg("Failure to register service\n"); |
354 | } | 348 | |
355 | return retval; | 349 | return retval; |
356 | } | 350 | } |
357 | 351 | ||
@@ -359,7 +353,6 @@ static void __exit pcied_cleanup(void) | |||
359 | { | 353 | { |
360 | dbg("unload_pciehpd()\n"); | 354 | dbg("unload_pciehpd()\n"); |
361 | pcie_port_service_unregister(&hpdriver_portdrv); | 355 | pcie_port_service_unregister(&hpdriver_portdrv); |
362 | destroy_workqueue(pciehp_wq); | ||
363 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 356 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
364 | } | 357 | } |
365 | 358 | ||
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c index 27f44295a657..38f018679175 100644 --- a/drivers/pci/hotplug/pciehp_ctrl.c +++ b/drivers/pci/hotplug/pciehp_ctrl.c | |||
@@ -49,7 +49,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) | |||
49 | info->p_slot = p_slot; | 49 | info->p_slot = p_slot; |
50 | INIT_WORK(&info->work, interrupt_event_handler); | 50 | INIT_WORK(&info->work, interrupt_event_handler); |
51 | 51 | ||
52 | queue_work(pciehp_wq, &info->work); | 52 | queue_work(p_slot->wq, &info->work); |
53 | 53 | ||
54 | return 0; | 54 | return 0; |
55 | } | 55 | } |
@@ -344,7 +344,7 @@ void pciehp_queue_pushbutton_work(struct work_struct *work) | |||
344 | kfree(info); | 344 | kfree(info); |
345 | goto out; | 345 | goto out; |
346 | } | 346 | } |
347 | queue_work(pciehp_wq, &info->work); | 347 | queue_work(p_slot->wq, &info->work); |
348 | out: | 348 | out: |
349 | mutex_unlock(&p_slot->lock); | 349 | mutex_unlock(&p_slot->lock); |
350 | } | 350 | } |
@@ -377,7 +377,7 @@ static void handle_button_press_event(struct slot *p_slot) | |||
377 | if (ATTN_LED(ctrl)) | 377 | if (ATTN_LED(ctrl)) |
378 | pciehp_set_attention_status(p_slot, 0); | 378 | pciehp_set_attention_status(p_slot, 0); |
379 | 379 | ||
380 | queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ); | 380 | queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); |
381 | break; | 381 | break; |
382 | case BLINKINGOFF_STATE: | 382 | case BLINKINGOFF_STATE: |
383 | case BLINKINGON_STATE: | 383 | case BLINKINGON_STATE: |
@@ -439,7 +439,7 @@ static void handle_surprise_event(struct slot *p_slot) | |||
439 | else | 439 | else |
440 | p_slot->state = POWERON_STATE; | 440 | p_slot->state = POWERON_STATE; |
441 | 441 | ||
442 | queue_work(pciehp_wq, &info->work); | 442 | queue_work(p_slot->wq, &info->work); |
443 | } | 443 | } |
444 | 444 | ||
445 | static void interrupt_event_handler(struct work_struct *work) | 445 | static void interrupt_event_handler(struct work_struct *work) |
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c index 13b2eaf7ba43..5127f3f41821 100644 --- a/drivers/pci/hotplug/pciehp_hpc.c +++ b/drivers/pci/hotplug/pciehp_hpc.c | |||
@@ -773,23 +773,32 @@ static void pcie_shutdown_notification(struct controller *ctrl) | |||
773 | static int pcie_init_slot(struct controller *ctrl) | 773 | static int pcie_init_slot(struct controller *ctrl) |
774 | { | 774 | { |
775 | struct slot *slot; | 775 | struct slot *slot; |
776 | char name[32]; | ||
776 | 777 | ||
777 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); | 778 | slot = kzalloc(sizeof(*slot), GFP_KERNEL); |
778 | if (!slot) | 779 | if (!slot) |
779 | return -ENOMEM; | 780 | return -ENOMEM; |
780 | 781 | ||
782 | snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl)); | ||
783 | slot->wq = alloc_workqueue(name, 0, 0); | ||
784 | if (!slot->wq) | ||
785 | goto abort; | ||
786 | |||
781 | slot->ctrl = ctrl; | 787 | slot->ctrl = ctrl; |
782 | mutex_init(&slot->lock); | 788 | mutex_init(&slot->lock); |
783 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); | 789 | INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work); |
784 | ctrl->slot = slot; | 790 | ctrl->slot = slot; |
785 | return 0; | 791 | return 0; |
792 | abort: | ||
793 | kfree(slot); | ||
794 | return -ENOMEM; | ||
786 | } | 795 | } |
787 | 796 | ||
788 | static void pcie_cleanup_slot(struct controller *ctrl) | 797 | static void pcie_cleanup_slot(struct controller *ctrl) |
789 | { | 798 | { |
790 | struct slot *slot = ctrl->slot; | 799 | struct slot *slot = ctrl->slot; |
791 | cancel_delayed_work(&slot->work); | 800 | cancel_delayed_work(&slot->work); |
792 | flush_workqueue(pciehp_wq); | 801 | destroy_workqueue(slot->wq); |
793 | kfree(slot); | 802 | kfree(slot); |
794 | } | 803 | } |
795 | 804 | ||
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h index ca64932e658b..b849f995075a 100644 --- a/drivers/pci/hotplug/shpchp.h +++ b/drivers/pci/hotplug/shpchp.h | |||
@@ -46,8 +46,6 @@ | |||
46 | extern bool shpchp_poll_mode; | 46 | extern bool shpchp_poll_mode; |
47 | extern int shpchp_poll_time; | 47 | extern int shpchp_poll_time; |
48 | extern bool shpchp_debug; | 48 | extern bool shpchp_debug; |
49 | extern struct workqueue_struct *shpchp_wq; | ||
50 | extern struct workqueue_struct *shpchp_ordered_wq; | ||
51 | 49 | ||
52 | #define dbg(format, arg...) \ | 50 | #define dbg(format, arg...) \ |
53 | do { \ | 51 | do { \ |
@@ -91,6 +89,7 @@ struct slot { | |||
91 | struct list_head slot_list; | 89 | struct list_head slot_list; |
92 | struct delayed_work work; /* work for button event */ | 90 | struct delayed_work work; /* work for button event */ |
93 | struct mutex lock; | 91 | struct mutex lock; |
92 | struct workqueue_struct *wq; | ||
94 | u8 hp_slot; | 93 | u8 hp_slot; |
95 | }; | 94 | }; |
96 | 95 | ||
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c index b6de307248e4..3100c52c837c 100644 --- a/drivers/pci/hotplug/shpchp_core.c +++ b/drivers/pci/hotplug/shpchp_core.c | |||
@@ -39,8 +39,6 @@ | |||
39 | bool shpchp_debug; | 39 | bool shpchp_debug; |
40 | bool shpchp_poll_mode; | 40 | bool shpchp_poll_mode; |
41 | int shpchp_poll_time; | 41 | int shpchp_poll_time; |
42 | struct workqueue_struct *shpchp_wq; | ||
43 | struct workqueue_struct *shpchp_ordered_wq; | ||
44 | 42 | ||
45 | #define DRIVER_VERSION "0.4" | 43 | #define DRIVER_VERSION "0.4" |
46 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" | 44 | #define DRIVER_AUTHOR "Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>" |
@@ -129,6 +127,14 @@ static int init_slots(struct controller *ctrl) | |||
129 | slot->device = ctrl->slot_device_offset + i; | 127 | slot->device = ctrl->slot_device_offset + i; |
130 | slot->hpc_ops = ctrl->hpc_ops; | 128 | slot->hpc_ops = ctrl->hpc_ops; |
131 | slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); | 129 | slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i); |
130 | |||
131 | snprintf(name, sizeof(name), "shpchp-%d", slot->number); | ||
132 | slot->wq = alloc_workqueue(name, 0, 0); | ||
133 | if (!slot->wq) { | ||
134 | retval = -ENOMEM; | ||
135 | goto error_info; | ||
136 | } | ||
137 | |||
132 | mutex_init(&slot->lock); | 138 | mutex_init(&slot->lock); |
133 | INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); | 139 | INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work); |
134 | 140 | ||
@@ -148,7 +154,7 @@ static int init_slots(struct controller *ctrl) | |||
148 | if (retval) { | 154 | if (retval) { |
149 | ctrl_err(ctrl, "pci_hp_register failed with error %d\n", | 155 | ctrl_err(ctrl, "pci_hp_register failed with error %d\n", |
150 | retval); | 156 | retval); |
151 | goto error_info; | 157 | goto error_slotwq; |
152 | } | 158 | } |
153 | 159 | ||
154 | get_power_status(hotplug_slot, &info->power_status); | 160 | get_power_status(hotplug_slot, &info->power_status); |
@@ -160,6 +166,8 @@ static int init_slots(struct controller *ctrl) | |||
160 | } | 166 | } |
161 | 167 | ||
162 | return 0; | 168 | return 0; |
169 | error_slotwq: | ||
170 | destroy_workqueue(slot->wq); | ||
163 | error_info: | 171 | error_info: |
164 | kfree(info); | 172 | kfree(info); |
165 | error_hpslot: | 173 | error_hpslot: |
@@ -180,8 +188,7 @@ void cleanup_slots(struct controller *ctrl) | |||
180 | slot = list_entry(tmp, struct slot, slot_list); | 188 | slot = list_entry(tmp, struct slot, slot_list); |
181 | list_del(&slot->slot_list); | 189 | list_del(&slot->slot_list); |
182 | cancel_delayed_work(&slot->work); | 190 | cancel_delayed_work(&slot->work); |
183 | flush_workqueue(shpchp_wq); | 191 | destroy_workqueue(slot->wq); |
184 | flush_workqueue(shpchp_ordered_wq); | ||
185 | pci_hp_deregister(slot->hotplug_slot); | 192 | pci_hp_deregister(slot->hotplug_slot); |
186 | } | 193 | } |
187 | } | 194 | } |
@@ -364,25 +371,12 @@ static struct pci_driver shpc_driver = { | |||
364 | 371 | ||
365 | static int __init shpcd_init(void) | 372 | static int __init shpcd_init(void) |
366 | { | 373 | { |
367 | int retval = 0; | 374 | int retval; |
368 | |||
369 | shpchp_wq = alloc_ordered_workqueue("shpchp", 0); | ||
370 | if (!shpchp_wq) | ||
371 | return -ENOMEM; | ||
372 | |||
373 | shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0); | ||
374 | if (!shpchp_ordered_wq) { | ||
375 | destroy_workqueue(shpchp_wq); | ||
376 | return -ENOMEM; | ||
377 | } | ||
378 | 375 | ||
379 | retval = pci_register_driver(&shpc_driver); | 376 | retval = pci_register_driver(&shpc_driver); |
380 | dbg("%s: pci_register_driver = %d\n", __func__, retval); | 377 | dbg("%s: pci_register_driver = %d\n", __func__, retval); |
381 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); | 378 | info(DRIVER_DESC " version: " DRIVER_VERSION "\n"); |
382 | if (retval) { | 379 | |
383 | destroy_workqueue(shpchp_ordered_wq); | ||
384 | destroy_workqueue(shpchp_wq); | ||
385 | } | ||
386 | return retval; | 380 | return retval; |
387 | } | 381 | } |
388 | 382 | ||
@@ -390,8 +384,6 @@ static void __exit shpcd_cleanup(void) | |||
390 | { | 384 | { |
391 | dbg("unload_shpchpd()\n"); | 385 | dbg("unload_shpchpd()\n"); |
392 | pci_unregister_driver(&shpc_driver); | 386 | pci_unregister_driver(&shpc_driver); |
393 | destroy_workqueue(shpchp_ordered_wq); | ||
394 | destroy_workqueue(shpchp_wq); | ||
395 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); | 387 | info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n"); |
396 | } | 388 | } |
397 | 389 | ||
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c index f9b5a52e4115..58499277903a 100644 --- a/drivers/pci/hotplug/shpchp_ctrl.c +++ b/drivers/pci/hotplug/shpchp_ctrl.c | |||
@@ -51,7 +51,7 @@ static int queue_interrupt_event(struct slot *p_slot, u32 event_type) | |||
51 | info->p_slot = p_slot; | 51 | info->p_slot = p_slot; |
52 | INIT_WORK(&info->work, interrupt_event_handler); | 52 | INIT_WORK(&info->work, interrupt_event_handler); |
53 | 53 | ||
54 | queue_work(shpchp_wq, &info->work); | 54 | queue_work(p_slot->wq, &info->work); |
55 | 55 | ||
56 | return 0; | 56 | return 0; |
57 | } | 57 | } |
@@ -453,7 +453,7 @@ void shpchp_queue_pushbutton_work(struct work_struct *work) | |||
453 | kfree(info); | 453 | kfree(info); |
454 | goto out; | 454 | goto out; |
455 | } | 455 | } |
456 | queue_work(shpchp_ordered_wq, &info->work); | 456 | queue_work(p_slot->wq, &info->work); |
457 | out: | 457 | out: |
458 | mutex_unlock(&p_slot->lock); | 458 | mutex_unlock(&p_slot->lock); |
459 | } | 459 | } |
@@ -501,7 +501,7 @@ static void handle_button_press_event(struct slot *p_slot) | |||
501 | p_slot->hpc_ops->green_led_blink(p_slot); | 501 | p_slot->hpc_ops->green_led_blink(p_slot); |
502 | p_slot->hpc_ops->set_attention_status(p_slot, 0); | 502 | p_slot->hpc_ops->set_attention_status(p_slot, 0); |
503 | 503 | ||
504 | queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ); | 504 | queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ); |
505 | break; | 505 | break; |
506 | case BLINKINGOFF_STATE: | 506 | case BLINKINGOFF_STATE: |
507 | case BLINKINGON_STATE: | 507 | case BLINKINGON_STATE: |
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c index bafd2bbcaf65..c18e5bf444fa 100644 --- a/drivers/pci/iov.c +++ b/drivers/pci/iov.c | |||
@@ -739,7 +739,7 @@ EXPORT_SYMBOL_GPL(pci_num_vf); | |||
739 | /** | 739 | /** |
740 | * pci_sriov_set_totalvfs -- reduce the TotalVFs available | 740 | * pci_sriov_set_totalvfs -- reduce the TotalVFs available |
741 | * @dev: the PCI PF device | 741 | * @dev: the PCI PF device |
742 | * numvfs: number that should be used for TotalVFs supported | 742 | * @numvfs: number that should be used for TotalVFs supported |
743 | * | 743 | * |
744 | * Should be called from PF driver's probe routine with | 744 | * Should be called from PF driver's probe routine with |
745 | * device's mutex held. | 745 | * device's mutex held. |
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c index 5099636a6e5f..00cc78c7aa04 100644 --- a/drivers/pci/msi.c +++ b/drivers/pci/msi.c | |||
@@ -845,6 +845,32 @@ int pci_enable_msi_block(struct pci_dev *dev, unsigned int nvec) | |||
845 | } | 845 | } |
846 | EXPORT_SYMBOL(pci_enable_msi_block); | 846 | EXPORT_SYMBOL(pci_enable_msi_block); |
847 | 847 | ||
848 | int pci_enable_msi_block_auto(struct pci_dev *dev, unsigned int *maxvec) | ||
849 | { | ||
850 | int ret, pos, nvec; | ||
851 | u16 msgctl; | ||
852 | |||
853 | pos = pci_find_capability(dev, PCI_CAP_ID_MSI); | ||
854 | if (!pos) | ||
855 | return -EINVAL; | ||
856 | |||
857 | pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &msgctl); | ||
858 | ret = 1 << ((msgctl & PCI_MSI_FLAGS_QMASK) >> 1); | ||
859 | |||
860 | if (maxvec) | ||
861 | *maxvec = ret; | ||
862 | |||
863 | do { | ||
864 | nvec = ret; | ||
865 | ret = pci_enable_msi_block(dev, nvec); | ||
866 | } while (ret > 0); | ||
867 | |||
868 | if (ret < 0) | ||
869 | return ret; | ||
870 | return nvec; | ||
871 | } | ||
872 | EXPORT_SYMBOL(pci_enable_msi_block_auto); | ||
873 | |||
848 | void pci_msi_shutdown(struct pci_dev *dev) | 874 | void pci_msi_shutdown(struct pci_dev *dev) |
849 | { | 875 | { |
850 | struct msi_desc *desc; | 876 | struct msi_desc *desc; |
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig index 6c8bc5809787..fde4a32a0295 100644 --- a/drivers/pci/pcie/Kconfig +++ b/drivers/pci/pcie/Kconfig | |||
@@ -82,4 +82,4 @@ endchoice | |||
82 | 82 | ||
83 | config PCIE_PME | 83 | config PCIE_PME |
84 | def_bool y | 84 | def_bool y |
85 | depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI | 85 | depends on PCIEPORTBUS && PM_RUNTIME && ACPI |
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c index 421bbc5fee32..564d97f94b6c 100644 --- a/drivers/pci/pcie/aer/aerdrv_core.c +++ b/drivers/pci/pcie/aer/aerdrv_core.c | |||
@@ -630,6 +630,7 @@ static void aer_recover_work_func(struct work_struct *work) | |||
630 | continue; | 630 | continue; |
631 | } | 631 | } |
632 | do_recovery(pdev, entry.severity); | 632 | do_recovery(pdev, entry.severity); |
633 | pci_dev_put(pdev); | ||
633 | } | 634 | } |
634 | } | 635 | } |
635 | #endif | 636 | #endif |
diff --git a/drivers/pci/pcie/aer/aerdrv_errprint.c b/drivers/pci/pcie/aer/aerdrv_errprint.c index 3ea51736f18d..5ab14251839d 100644 --- a/drivers/pci/pcie/aer/aerdrv_errprint.c +++ b/drivers/pci/pcie/aer/aerdrv_errprint.c | |||
@@ -23,6 +23,9 @@ | |||
23 | 23 | ||
24 | #include "aerdrv.h" | 24 | #include "aerdrv.h" |
25 | 25 | ||
26 | #define CREATE_TRACE_POINTS | ||
27 | #include <trace/events/ras.h> | ||
28 | |||
26 | #define AER_AGENT_RECEIVER 0 | 29 | #define AER_AGENT_RECEIVER 0 |
27 | #define AER_AGENT_REQUESTER 1 | 30 | #define AER_AGENT_REQUESTER 1 |
28 | #define AER_AGENT_COMPLETER 2 | 31 | #define AER_AGENT_COMPLETER 2 |
@@ -121,12 +124,11 @@ static const char *aer_agent_string[] = { | |||
121 | "Transmitter ID" | 124 | "Transmitter ID" |
122 | }; | 125 | }; |
123 | 126 | ||
124 | static void __aer_print_error(const char *prefix, | 127 | static void __aer_print_error(struct pci_dev *dev, |
125 | struct aer_err_info *info) | 128 | struct aer_err_info *info) |
126 | { | 129 | { |
127 | int i, status; | 130 | int i, status; |
128 | const char *errmsg = NULL; | 131 | const char *errmsg = NULL; |
129 | |||
130 | status = (info->status & ~info->mask); | 132 | status = (info->status & ~info->mask); |
131 | 133 | ||
132 | for (i = 0; i < 32; i++) { | 134 | for (i = 0; i < 32; i++) { |
@@ -141,26 +143,22 @@ static void __aer_print_error(const char *prefix, | |||
141 | aer_uncorrectable_error_string[i] : NULL; | 143 | aer_uncorrectable_error_string[i] : NULL; |
142 | 144 | ||
143 | if (errmsg) | 145 | if (errmsg) |
144 | printk("%s"" [%2d] %-22s%s\n", prefix, i, errmsg, | 146 | dev_err(&dev->dev, " [%2d] %-22s%s\n", i, errmsg, |
145 | info->first_error == i ? " (First)" : ""); | 147 | info->first_error == i ? " (First)" : ""); |
146 | else | 148 | else |
147 | printk("%s"" [%2d] Unknown Error Bit%s\n", prefix, i, | 149 | dev_err(&dev->dev, " [%2d] Unknown Error Bit%s\n", |
148 | info->first_error == i ? " (First)" : ""); | 150 | i, info->first_error == i ? " (First)" : ""); |
149 | } | 151 | } |
150 | } | 152 | } |
151 | 153 | ||
152 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) | 154 | void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) |
153 | { | 155 | { |
154 | int id = ((dev->bus->number << 8) | dev->devfn); | 156 | int id = ((dev->bus->number << 8) | dev->devfn); |
155 | char prefix[44]; | ||
156 | |||
157 | snprintf(prefix, sizeof(prefix), "%s%s %s: ", | ||
158 | (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR, | ||
159 | dev_driver_string(&dev->dev), dev_name(&dev->dev)); | ||
160 | 157 | ||
161 | if (info->status == 0) { | 158 | if (info->status == 0) { |
162 | printk("%s""PCIe Bus Error: severity=%s, type=Unaccessible, " | 159 | dev_err(&dev->dev, |
163 | "id=%04x(Unregistered Agent ID)\n", prefix, | 160 | "PCIe Bus Error: severity=%s, type=Unaccessible, " |
161 | "id=%04x(Unregistered Agent ID)\n", | ||
164 | aer_error_severity_string[info->severity], id); | 162 | aer_error_severity_string[info->severity], id); |
165 | } else { | 163 | } else { |
166 | int layer, agent; | 164 | int layer, agent; |
@@ -168,22 +166,24 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) | |||
168 | layer = AER_GET_LAYER_ERROR(info->severity, info->status); | 166 | layer = AER_GET_LAYER_ERROR(info->severity, info->status); |
169 | agent = AER_GET_AGENT(info->severity, info->status); | 167 | agent = AER_GET_AGENT(info->severity, info->status); |
170 | 168 | ||
171 | printk("%s""PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", | 169 | dev_err(&dev->dev, |
172 | prefix, aer_error_severity_string[info->severity], | 170 | "PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n", |
171 | aer_error_severity_string[info->severity], | ||
173 | aer_error_layer[layer], id, aer_agent_string[agent]); | 172 | aer_error_layer[layer], id, aer_agent_string[agent]); |
174 | 173 | ||
175 | printk("%s"" device [%04x:%04x] error status/mask=%08x/%08x\n", | 174 | dev_err(&dev->dev, |
176 | prefix, dev->vendor, dev->device, | 175 | " device [%04x:%04x] error status/mask=%08x/%08x\n", |
176 | dev->vendor, dev->device, | ||
177 | info->status, info->mask); | 177 | info->status, info->mask); |
178 | 178 | ||
179 | __aer_print_error(prefix, info); | 179 | __aer_print_error(dev, info); |
180 | 180 | ||
181 | if (info->tlp_header_valid) { | 181 | if (info->tlp_header_valid) { |
182 | unsigned char *tlp = (unsigned char *) &info->tlp; | 182 | unsigned char *tlp = (unsigned char *) &info->tlp; |
183 | printk("%s"" TLP Header:" | 183 | dev_err(&dev->dev, " TLP Header:" |
184 | " %02x%02x%02x%02x %02x%02x%02x%02x" | 184 | " %02x%02x%02x%02x %02x%02x%02x%02x" |
185 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", | 185 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", |
186 | prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, | 186 | *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, |
187 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), | 187 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), |
188 | *(tlp + 11), *(tlp + 10), *(tlp + 9), | 188 | *(tlp + 11), *(tlp + 10), *(tlp + 9), |
189 | *(tlp + 8), *(tlp + 15), *(tlp + 14), | 189 | *(tlp + 8), *(tlp + 15), *(tlp + 14), |
@@ -192,8 +192,11 @@ void aer_print_error(struct pci_dev *dev, struct aer_err_info *info) | |||
192 | } | 192 | } |
193 | 193 | ||
194 | if (info->id && info->error_dev_num > 1 && info->id == id) | 194 | if (info->id && info->error_dev_num > 1 && info->id == id) |
195 | printk("%s"" Error of this Agent(%04x) is reported first\n", | 195 | dev_err(&dev->dev, |
196 | prefix, id); | 196 | " Error of this Agent(%04x) is reported first\n", |
197 | id); | ||
198 | trace_aer_event(dev_name(&dev->dev), (info->status & ~info->mask), | ||
199 | info->severity); | ||
197 | } | 200 | } |
198 | 201 | ||
199 | void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) | 202 | void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info) |
@@ -217,7 +220,7 @@ int cper_severity_to_aer(int cper_severity) | |||
217 | } | 220 | } |
218 | EXPORT_SYMBOL_GPL(cper_severity_to_aer); | 221 | EXPORT_SYMBOL_GPL(cper_severity_to_aer); |
219 | 222 | ||
220 | void cper_print_aer(const char *prefix, int cper_severity, | 223 | void cper_print_aer(const char *prefix, struct pci_dev *dev, int cper_severity, |
221 | struct aer_capability_regs *aer) | 224 | struct aer_capability_regs *aer) |
222 | { | 225 | { |
223 | int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; | 226 | int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0; |
@@ -239,25 +242,27 @@ void cper_print_aer(const char *prefix, int cper_severity, | |||
239 | } | 242 | } |
240 | layer = AER_GET_LAYER_ERROR(aer_severity, status); | 243 | layer = AER_GET_LAYER_ERROR(aer_severity, status); |
241 | agent = AER_GET_AGENT(aer_severity, status); | 244 | agent = AER_GET_AGENT(aer_severity, status); |
242 | printk("%s""aer_status: 0x%08x, aer_mask: 0x%08x\n", | 245 | dev_err(&dev->dev, "aer_status: 0x%08x, aer_mask: 0x%08x\n", |
243 | prefix, status, mask); | 246 | status, mask); |
244 | cper_print_bits(prefix, status, status_strs, status_strs_size); | 247 | cper_print_bits(prefix, status, status_strs, status_strs_size); |
245 | printk("%s""aer_layer=%s, aer_agent=%s\n", prefix, | 248 | dev_err(&dev->dev, "aer_layer=%s, aer_agent=%s\n", |
246 | aer_error_layer[layer], aer_agent_string[agent]); | 249 | aer_error_layer[layer], aer_agent_string[agent]); |
247 | if (aer_severity != AER_CORRECTABLE) | 250 | if (aer_severity != AER_CORRECTABLE) |
248 | printk("%s""aer_uncor_severity: 0x%08x\n", | 251 | dev_err(&dev->dev, "aer_uncor_severity: 0x%08x\n", |
249 | prefix, aer->uncor_severity); | 252 | aer->uncor_severity); |
250 | if (tlp_header_valid) { | 253 | if (tlp_header_valid) { |
251 | const unsigned char *tlp; | 254 | const unsigned char *tlp; |
252 | tlp = (const unsigned char *)&aer->header_log; | 255 | tlp = (const unsigned char *)&aer->header_log; |
253 | printk("%s""aer_tlp_header:" | 256 | dev_err(&dev->dev, "aer_tlp_header:" |
254 | " %02x%02x%02x%02x %02x%02x%02x%02x" | 257 | " %02x%02x%02x%02x %02x%02x%02x%02x" |
255 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", | 258 | " %02x%02x%02x%02x %02x%02x%02x%02x\n", |
256 | prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, | 259 | *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp, |
257 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), | 260 | *(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4), |
258 | *(tlp + 11), *(tlp + 10), *(tlp + 9), | 261 | *(tlp + 11), *(tlp + 10), *(tlp + 9), |
259 | *(tlp + 8), *(tlp + 15), *(tlp + 14), | 262 | *(tlp + 8), *(tlp + 15), *(tlp + 14), |
260 | *(tlp + 13), *(tlp + 12)); | 263 | *(tlp + 13), *(tlp + 12)); |
261 | } | 264 | } |
265 | trace_aer_event(dev_name(&dev->dev), (status & ~mask), | ||
266 | aer_severity); | ||
262 | } | 267 | } |
263 | #endif | 268 | #endif |
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c index b52630b8eada..8474b6a4fc9b 100644 --- a/drivers/pci/pcie/aspm.c +++ b/drivers/pci/pcie/aspm.c | |||
@@ -771,6 +771,9 @@ void pcie_clear_aspm(struct pci_bus *bus) | |||
771 | { | 771 | { |
772 | struct pci_dev *child; | 772 | struct pci_dev *child; |
773 | 773 | ||
774 | if (aspm_force) | ||
775 | return; | ||
776 | |||
774 | /* | 777 | /* |
775 | * Clear any ASPM setup that the firmware has carried out on this bus | 778 | * Clear any ASPM setup that the firmware has carried out on this bus |
776 | */ | 779 | */ |
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c index 7c0fd9252e6f..84954a726a94 100644 --- a/drivers/pci/remove.c +++ b/drivers/pci/remove.c | |||
@@ -19,6 +19,8 @@ static void pci_free_resources(struct pci_dev *dev) | |||
19 | 19 | ||
20 | static void pci_stop_dev(struct pci_dev *dev) | 20 | static void pci_stop_dev(struct pci_dev *dev) |
21 | { | 21 | { |
22 | pci_pme_active(dev, false); | ||
23 | |||
22 | if (dev->is_added) { | 24 | if (dev->is_added) { |
23 | pci_proc_detach_device(dev); | 25 | pci_proc_detach_device(dev); |
24 | pci_remove_sysfs_dev_files(dev); | 26 | pci_remove_sysfs_dev_files(dev); |
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index d186c5825133..393b0ecf4ca4 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig | |||
@@ -213,7 +213,6 @@ config PINCTRL_COH901 | |||
213 | 213 | ||
214 | config PINCTRL_SAMSUNG | 214 | config PINCTRL_SAMSUNG |
215 | bool | 215 | bool |
216 | depends on OF && GPIOLIB | ||
217 | select PINMUX | 216 | select PINMUX |
218 | select PINCONF | 217 | select PINCONF |
219 | 218 | ||
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c index 69aba3697287..428ea96a94d3 100644 --- a/drivers/pinctrl/mvebu/pinctrl-dove.c +++ b/drivers/pinctrl/mvebu/pinctrl-dove.c | |||
@@ -588,7 +588,7 @@ static int dove_pinctrl_probe(struct platform_device *pdev) | |||
588 | { | 588 | { |
589 | const struct of_device_id *match = | 589 | const struct of_device_id *match = |
590 | of_match_device(dove_pinctrl_of_match, &pdev->dev); | 590 | of_match_device(dove_pinctrl_of_match, &pdev->dev); |
591 | pdev->dev.platform_data = match->data; | 591 | pdev->dev.platform_data = (void *)match->data; |
592 | 592 | ||
593 | /* | 593 | /* |
594 | * General MPP Configuration Register is part of pdma registers. | 594 | * General MPP Configuration Register is part of pdma registers. |
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c index f12084e18057..cdd483df673e 100644 --- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c +++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c | |||
@@ -66,9 +66,9 @@ static struct mvebu_mpp_mode mv88f6xxx_mpp_modes[] = { | |||
66 | MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)), | 66 | MPP_VAR_FUNCTION(0x5, "sata0", "act", V(0, 1, 1, 1, 1, 0)), |
67 | MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))), | 67 | MPP_VAR_FUNCTION(0xb, "lcd", "vsync", V(0, 0, 0, 0, 1, 0))), |
68 | MPP_MODE(6, | 68 | MPP_MODE(6, |
69 | MPP_VAR_FUNCTION(0x0, "sysrst", "out", V(1, 1, 1, 1, 1, 1)), | 69 | MPP_VAR_FUNCTION(0x1, "sysrst", "out", V(1, 1, 1, 1, 1, 1)), |
70 | MPP_VAR_FUNCTION(0x1, "spi", "mosi", V(1, 1, 1, 1, 1, 1)), | 70 | MPP_VAR_FUNCTION(0x2, "spi", "mosi", V(1, 1, 1, 1, 1, 1)), |
71 | MPP_VAR_FUNCTION(0x2, "ptp", "trig", V(1, 1, 1, 1, 0, 0))), | 71 | MPP_VAR_FUNCTION(0x3, "ptp", "trig", V(1, 1, 1, 1, 0, 0))), |
72 | MPP_MODE(7, | 72 | MPP_MODE(7, |
73 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)), | 73 | MPP_VAR_FUNCTION(0x0, "gpo", NULL, V(1, 1, 1, 1, 1, 1)), |
74 | MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0, 1)), | 74 | MPP_VAR_FUNCTION(0x1, "pex", "rsto", V(1, 1, 1, 1, 0, 1)), |
@@ -458,7 +458,7 @@ static int kirkwood_pinctrl_probe(struct platform_device *pdev) | |||
458 | { | 458 | { |
459 | const struct of_device_id *match = | 459 | const struct of_device_id *match = |
460 | of_match_device(kirkwood_pinctrl_of_match, &pdev->dev); | 460 | of_match_device(kirkwood_pinctrl_of_match, &pdev->dev); |
461 | pdev->dev.platform_data = match->data; | 461 | pdev->dev.platform_data = (void *)match->data; |
462 | return mvebu_pinctrl_probe(pdev); | 462 | return mvebu_pinctrl_probe(pdev); |
463 | } | 463 | } |
464 | 464 | ||
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c index dd227d21dcf2..23af9f1f9c35 100644 --- a/drivers/pinctrl/pinctrl-mxs.c +++ b/drivers/pinctrl/pinctrl-mxs.c | |||
@@ -146,7 +146,7 @@ free: | |||
146 | static void mxs_dt_free_map(struct pinctrl_dev *pctldev, | 146 | static void mxs_dt_free_map(struct pinctrl_dev *pctldev, |
147 | struct pinctrl_map *map, unsigned num_maps) | 147 | struct pinctrl_map *map, unsigned num_maps) |
148 | { | 148 | { |
149 | int i; | 149 | u32 i; |
150 | 150 | ||
151 | for (i = 0; i < num_maps; i++) { | 151 | for (i = 0; i < num_maps; i++) { |
152 | if (map[i].type == PIN_MAP_TYPE_MUX_GROUP) | 152 | if (map[i].type == PIN_MAP_TYPE_MUX_GROUP) |
@@ -203,7 +203,7 @@ static int mxs_pinctrl_enable(struct pinctrl_dev *pctldev, unsigned selector, | |||
203 | void __iomem *reg; | 203 | void __iomem *reg; |
204 | u8 bank, shift; | 204 | u8 bank, shift; |
205 | u16 pin; | 205 | u16 pin; |
206 | int i; | 206 | u32 i; |
207 | 207 | ||
208 | for (i = 0; i < g->npins; i++) { | 208 | for (i = 0; i < g->npins; i++) { |
209 | bank = PINID_TO_BANK(g->pins[i]); | 209 | bank = PINID_TO_BANK(g->pins[i]); |
@@ -256,7 +256,7 @@ static int mxs_pinconf_group_set(struct pinctrl_dev *pctldev, | |||
256 | void __iomem *reg; | 256 | void __iomem *reg; |
257 | u8 ma, vol, pull, bank, shift; | 257 | u8 ma, vol, pull, bank, shift; |
258 | u16 pin; | 258 | u16 pin; |
259 | int i; | 259 | u32 i; |
260 | 260 | ||
261 | ma = CONFIG_TO_MA(config); | 261 | ma = CONFIG_TO_MA(config); |
262 | vol = CONFIG_TO_VOL(config); | 262 | vol = CONFIG_TO_VOL(config); |
@@ -345,8 +345,7 @@ static int mxs_pinctrl_parse_group(struct platform_device *pdev, | |||
345 | const char *propname = "fsl,pinmux-ids"; | 345 | const char *propname = "fsl,pinmux-ids"; |
346 | char *group; | 346 | char *group; |
347 | int length = strlen(np->name) + SUFFIX_LEN; | 347 | int length = strlen(np->name) + SUFFIX_LEN; |
348 | int i; | 348 | u32 val, i; |
349 | u32 val; | ||
350 | 349 | ||
351 | group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); | 350 | group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL); |
352 | if (!group) | 351 | if (!group) |
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c index b885c0911e83..de9e8519b803 100644 --- a/drivers/pinctrl/pinctrl-nomadik.c +++ b/drivers/pinctrl/pinctrl-nomadik.c | |||
@@ -678,7 +678,7 @@ int nmk_gpio_set_mode(int gpio, int gpio_mode) | |||
678 | } | 678 | } |
679 | EXPORT_SYMBOL(nmk_gpio_set_mode); | 679 | EXPORT_SYMBOL(nmk_gpio_set_mode); |
680 | 680 | ||
681 | static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) | 681 | static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio) |
682 | { | 682 | { |
683 | int i; | 683 | int i; |
684 | u16 reg; | 684 | u16 reg; |
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c index f6a360b86eb6..5c32e880bcb2 100644 --- a/drivers/pinctrl/pinctrl-single.c +++ b/drivers/pinctrl/pinctrl-single.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #define PCS_MUX_BITS_NAME "pinctrl-single,bits" | 30 | #define PCS_MUX_BITS_NAME "pinctrl-single,bits" |
31 | #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) | 31 | #define PCS_REG_NAME_LEN ((sizeof(unsigned long) * 2) + 1) |
32 | #define PCS_OFF_DISABLED ~0U | 32 | #define PCS_OFF_DISABLED ~0U |
33 | #define PCS_MAX_GPIO_VALUES 2 | ||
34 | 33 | ||
35 | /** | 34 | /** |
36 | * struct pcs_pingroup - pingroups for a function | 35 | * struct pcs_pingroup - pingroups for a function |
@@ -78,16 +77,6 @@ struct pcs_function { | |||
78 | }; | 77 | }; |
79 | 78 | ||
80 | /** | 79 | /** |
81 | * struct pcs_gpio_range - pinctrl gpio range | ||
82 | * @range: subrange of the GPIO number space | ||
83 | * @gpio_func: gpio function value in the pinmux register | ||
84 | */ | ||
85 | struct pcs_gpio_range { | ||
86 | struct pinctrl_gpio_range range; | ||
87 | int gpio_func; | ||
88 | }; | ||
89 | |||
90 | /** | ||
91 | * struct pcs_data - wrapper for data needed by pinctrl framework | 80 | * struct pcs_data - wrapper for data needed by pinctrl framework |
92 | * @pa: pindesc array | 81 | * @pa: pindesc array |
93 | * @cur: index to current element | 82 | * @cur: index to current element |
@@ -414,26 +403,9 @@ static void pcs_disable(struct pinctrl_dev *pctldev, unsigned fselector, | |||
414 | } | 403 | } |
415 | 404 | ||
416 | static int pcs_request_gpio(struct pinctrl_dev *pctldev, | 405 | static int pcs_request_gpio(struct pinctrl_dev *pctldev, |
417 | struct pinctrl_gpio_range *range, unsigned pin) | 406 | struct pinctrl_gpio_range *range, unsigned offset) |
418 | { | 407 | { |
419 | struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev); | 408 | return -ENOTSUPP; |
420 | struct pcs_gpio_range *gpio = NULL; | ||
421 | int end, mux_bytes; | ||
422 | unsigned data; | ||
423 | |||
424 | gpio = container_of(range, struct pcs_gpio_range, range); | ||
425 | end = range->pin_base + range->npins - 1; | ||
426 | if (pin < range->pin_base || pin > end) { | ||
427 | dev_err(pctldev->dev, | ||
428 | "pin %d isn't in the range of %d to %d\n", | ||
429 | pin, range->pin_base, end); | ||
430 | return -EINVAL; | ||
431 | } | ||
432 | mux_bytes = pcs->width / BITS_PER_BYTE; | ||
433 | data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask; | ||
434 | data |= gpio->gpio_func; | ||
435 | pcs->write(data, pcs->base + pin * mux_bytes); | ||
436 | return 0; | ||
437 | } | 409 | } |
438 | 410 | ||
439 | static struct pinmux_ops pcs_pinmux_ops = { | 411 | static struct pinmux_ops pcs_pinmux_ops = { |
@@ -907,49 +879,6 @@ static void pcs_free_resources(struct pcs_device *pcs) | |||
907 | 879 | ||
908 | static struct of_device_id pcs_of_match[]; | 880 | static struct of_device_id pcs_of_match[]; |
909 | 881 | ||
910 | static int pcs_add_gpio_range(struct device_node *node, struct pcs_device *pcs) | ||
911 | { | ||
912 | struct pcs_gpio_range *gpio; | ||
913 | struct device_node *child; | ||
914 | struct resource r; | ||
915 | const char name[] = "pinctrl-single"; | ||
916 | u32 gpiores[PCS_MAX_GPIO_VALUES]; | ||
917 | int ret, i = 0, mux_bytes = 0; | ||
918 | |||
919 | for_each_child_of_node(node, child) { | ||
920 | ret = of_address_to_resource(child, 0, &r); | ||
921 | if (ret < 0) | ||
922 | continue; | ||
923 | memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES); | ||
924 | ret = of_property_read_u32_array(child, "pinctrl-single,gpio", | ||
925 | gpiores, PCS_MAX_GPIO_VALUES); | ||
926 | if (ret < 0) | ||
927 | continue; | ||
928 | gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL); | ||
929 | if (!gpio) { | ||
930 | dev_err(pcs->dev, "failed to allocate pcs gpio\n"); | ||
931 | return -ENOMEM; | ||
932 | } | ||
933 | gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name), | ||
934 | GFP_KERNEL); | ||
935 | if (!gpio->range.name) { | ||
936 | dev_err(pcs->dev, "failed to allocate range name\n"); | ||
937 | return -ENOMEM; | ||
938 | } | ||
939 | memcpy((char *)gpio->range.name, name, sizeof(name)); | ||
940 | |||
941 | gpio->range.id = i++; | ||
942 | gpio->range.base = gpiores[0]; | ||
943 | gpio->gpio_func = gpiores[1]; | ||
944 | mux_bytes = pcs->width / BITS_PER_BYTE; | ||
945 | gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes; | ||
946 | gpio->range.npins = (r.end - r.start) / mux_bytes + 1; | ||
947 | |||
948 | pinctrl_add_gpio_range(pcs->pctl, &gpio->range); | ||
949 | } | ||
950 | return 0; | ||
951 | } | ||
952 | |||
953 | static int pcs_probe(struct platform_device *pdev) | 882 | static int pcs_probe(struct platform_device *pdev) |
954 | { | 883 | { |
955 | struct device_node *np = pdev->dev.of_node; | 884 | struct device_node *np = pdev->dev.of_node; |
@@ -1046,10 +975,6 @@ static int pcs_probe(struct platform_device *pdev) | |||
1046 | goto free; | 975 | goto free; |
1047 | } | 976 | } |
1048 | 977 | ||
1049 | ret = pcs_add_gpio_range(np, pcs); | ||
1050 | if (ret < 0) | ||
1051 | goto free; | ||
1052 | |||
1053 | dev_info(pcs->dev, "%i pins at pa %p size %u\n", | 978 | dev_info(pcs->dev, "%i pins at pa %p size %u\n", |
1054 | pcs->desc.npins, pcs->base, pcs->size); | 979 | pcs->desc.npins, pcs->base, pcs->size); |
1055 | 980 | ||
diff --git a/drivers/pinctrl/pinctrl-sirf.c b/drivers/pinctrl/pinctrl-sirf.c index 498b2ba905de..d02498b30c6e 100644 --- a/drivers/pinctrl/pinctrl-sirf.c +++ b/drivers/pinctrl/pinctrl-sirf.c | |||
@@ -1246,6 +1246,22 @@ static void __iomem *sirfsoc_rsc_of_iomap(void) | |||
1246 | return of_iomap(np, 0); | 1246 | return of_iomap(np, 0); |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | static int sirfsoc_gpio_of_xlate(struct gpio_chip *gc, | ||
1250 | const struct of_phandle_args *gpiospec, | ||
1251 | u32 *flags) | ||
1252 | { | ||
1253 | if (gpiospec->args[0] > SIRFSOC_GPIO_NO_OF_BANKS * SIRFSOC_GPIO_BANK_SIZE) | ||
1254 | return -EINVAL; | ||
1255 | |||
1256 | if (gc != &sgpio_bank[gpiospec->args[0] / SIRFSOC_GPIO_BANK_SIZE].chip.gc) | ||
1257 | return -EINVAL; | ||
1258 | |||
1259 | if (flags) | ||
1260 | *flags = gpiospec->args[1]; | ||
1261 | |||
1262 | return gpiospec->args[0] % SIRFSOC_GPIO_BANK_SIZE; | ||
1263 | } | ||
1264 | |||
1249 | static int sirfsoc_pinmux_probe(struct platform_device *pdev) | 1265 | static int sirfsoc_pinmux_probe(struct platform_device *pdev) |
1250 | { | 1266 | { |
1251 | int ret; | 1267 | int ret; |
@@ -1736,6 +1752,8 @@ static int sirfsoc_gpio_probe(struct device_node *np) | |||
1736 | bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE; | 1752 | bank->chip.gc.ngpio = SIRFSOC_GPIO_BANK_SIZE; |
1737 | bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL); | 1753 | bank->chip.gc.label = kstrdup(np->full_name, GFP_KERNEL); |
1738 | bank->chip.gc.of_node = np; | 1754 | bank->chip.gc.of_node = np; |
1755 | bank->chip.gc.of_xlate = sirfsoc_gpio_of_xlate; | ||
1756 | bank->chip.gc.of_gpio_n_cells = 2; | ||
1739 | bank->chip.regs = regs; | 1757 | bank->chip.regs = regs; |
1740 | bank->id = i; | 1758 | bank->id = i; |
1741 | bank->is_marco = is_marco; | 1759 | bank->is_marco = is_marco; |
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c index 06f4eb7ab87e..afed7018a2b5 100644 --- a/drivers/platform/x86/acer-wmi.c +++ b/drivers/platform/x86/acer-wmi.c | |||
@@ -125,8 +125,11 @@ static const struct key_entry acer_wmi_keymap[] = { | |||
125 | {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} }, | 125 | {KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} }, |
126 | {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ | 126 | {KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} }, /* Display Switch */ |
127 | {KE_IGNORE, 0x81, {KEY_SLEEP} }, | 127 | {KE_IGNORE, 0x81, {KEY_SLEEP} }, |
128 | {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad On/Off */ | 128 | {KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} }, /* Touch Pad Toggle */ |
129 | {KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} }, | ||
130 | {KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} }, | ||
129 | {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, | 131 | {KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} }, |
132 | {KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} }, | ||
130 | {KE_END, 0} | 133 | {KE_END, 0} |
131 | }; | 134 | }; |
132 | 135 | ||
@@ -147,6 +150,7 @@ struct event_return_value { | |||
147 | #define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ | 150 | #define ACER_WMID3_GDS_THREEG (1<<6) /* 3G */ |
148 | #define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */ | 151 | #define ACER_WMID3_GDS_WIMAX (1<<7) /* WiMAX */ |
149 | #define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ | 152 | #define ACER_WMID3_GDS_BLUETOOTH (1<<11) /* BT */ |
153 | #define ACER_WMID3_GDS_TOUCHPAD (1<<1) /* Touchpad */ | ||
150 | 154 | ||
151 | struct lm_input_params { | 155 | struct lm_input_params { |
152 | u8 function_num; /* Function Number */ | 156 | u8 function_num; /* Function Number */ |
@@ -875,7 +879,7 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out) | |||
875 | struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) }; | 879 | struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) }; |
876 | struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; | 880 | struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL }; |
877 | union acpi_object *obj; | 881 | union acpi_object *obj; |
878 | u32 tmp; | 882 | u32 tmp = 0; |
879 | acpi_status status; | 883 | acpi_status status; |
880 | 884 | ||
881 | status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result); | 885 | status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result); |
@@ -884,14 +888,14 @@ WMI_execute_u32(u32 method_id, u32 in, u32 *out) | |||
884 | return status; | 888 | return status; |
885 | 889 | ||
886 | obj = (union acpi_object *) result.pointer; | 890 | obj = (union acpi_object *) result.pointer; |
887 | if (obj && obj->type == ACPI_TYPE_BUFFER && | 891 | if (obj) { |
888 | (obj->buffer.length == sizeof(u32) || | 892 | if (obj->type == ACPI_TYPE_BUFFER && |
889 | obj->buffer.length == sizeof(u64))) { | 893 | (obj->buffer.length == sizeof(u32) || |
890 | tmp = *((u32 *) obj->buffer.pointer); | 894 | obj->buffer.length == sizeof(u64))) { |
891 | } else if (obj->type == ACPI_TYPE_INTEGER) { | 895 | tmp = *((u32 *) obj->buffer.pointer); |
892 | tmp = (u32) obj->integer.value; | 896 | } else if (obj->type == ACPI_TYPE_INTEGER) { |
893 | } else { | 897 | tmp = (u32) obj->integer.value; |
894 | tmp = 0; | 898 | } |
895 | } | 899 | } |
896 | 900 | ||
897 | if (out) | 901 | if (out) |
@@ -1193,12 +1197,14 @@ static acpi_status WMID_set_capabilities(void) | |||
1193 | return status; | 1197 | return status; |
1194 | 1198 | ||
1195 | obj = (union acpi_object *) out.pointer; | 1199 | obj = (union acpi_object *) out.pointer; |
1196 | if (obj && obj->type == ACPI_TYPE_BUFFER && | 1200 | if (obj) { |
1197 | (obj->buffer.length == sizeof(u32) || | 1201 | if (obj->type == ACPI_TYPE_BUFFER && |
1198 | obj->buffer.length == sizeof(u64))) { | 1202 | (obj->buffer.length == sizeof(u32) || |
1199 | devices = *((u32 *) obj->buffer.pointer); | 1203 | obj->buffer.length == sizeof(u64))) { |
1200 | } else if (obj->type == ACPI_TYPE_INTEGER) { | 1204 | devices = *((u32 *) obj->buffer.pointer); |
1201 | devices = (u32) obj->integer.value; | 1205 | } else if (obj->type == ACPI_TYPE_INTEGER) { |
1206 | devices = (u32) obj->integer.value; | ||
1207 | } | ||
1202 | } else { | 1208 | } else { |
1203 | kfree(out.pointer); | 1209 | kfree(out.pointer); |
1204 | return AE_ERROR; | 1210 | return AE_ERROR; |
@@ -1676,6 +1682,7 @@ static void acer_wmi_notify(u32 value, void *context) | |||
1676 | acpi_status status; | 1682 | acpi_status status; |
1677 | u16 device_state; | 1683 | u16 device_state; |
1678 | const struct key_entry *key; | 1684 | const struct key_entry *key; |
1685 | u32 scancode; | ||
1679 | 1686 | ||
1680 | status = wmi_get_event_data(value, &response); | 1687 | status = wmi_get_event_data(value, &response); |
1681 | if (status != AE_OK) { | 1688 | if (status != AE_OK) { |
@@ -1712,6 +1719,7 @@ static void acer_wmi_notify(u32 value, void *context) | |||
1712 | pr_warn("Unknown key number - 0x%x\n", | 1719 | pr_warn("Unknown key number - 0x%x\n", |
1713 | return_value.key_num); | 1720 | return_value.key_num); |
1714 | } else { | 1721 | } else { |
1722 | scancode = return_value.key_num; | ||
1715 | switch (key->keycode) { | 1723 | switch (key->keycode) { |
1716 | case KEY_WLAN: | 1724 | case KEY_WLAN: |
1717 | case KEY_BLUETOOTH: | 1725 | case KEY_BLUETOOTH: |
@@ -1725,9 +1733,11 @@ static void acer_wmi_notify(u32 value, void *context) | |||
1725 | rfkill_set_sw_state(bluetooth_rfkill, | 1733 | rfkill_set_sw_state(bluetooth_rfkill, |
1726 | !(device_state & ACER_WMID3_GDS_BLUETOOTH)); | 1734 | !(device_state & ACER_WMID3_GDS_BLUETOOTH)); |
1727 | break; | 1735 | break; |
1736 | case KEY_TOUCHPAD_TOGGLE: | ||
1737 | scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ? | ||
1738 | KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF; | ||
1728 | } | 1739 | } |
1729 | sparse_keymap_report_entry(acer_wmi_input_dev, key, | 1740 | sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true); |
1730 | 1, true); | ||
1731 | } | 1741 | } |
1732 | break; | 1742 | break; |
1733 | case WMID_ACCEL_EVENT: | 1743 | case WMID_ACCEL_EVENT: |
@@ -1946,12 +1956,14 @@ static u32 get_wmid_devices(void) | |||
1946 | return 0; | 1956 | return 0; |
1947 | 1957 | ||
1948 | obj = (union acpi_object *) out.pointer; | 1958 | obj = (union acpi_object *) out.pointer; |
1949 | if (obj && obj->type == ACPI_TYPE_BUFFER && | 1959 | if (obj) { |
1950 | (obj->buffer.length == sizeof(u32) || | 1960 | if (obj->type == ACPI_TYPE_BUFFER && |
1951 | obj->buffer.length == sizeof(u64))) { | 1961 | (obj->buffer.length == sizeof(u32) || |
1952 | devices = *((u32 *) obj->buffer.pointer); | 1962 | obj->buffer.length == sizeof(u64))) { |
1953 | } else if (obj->type == ACPI_TYPE_INTEGER) { | 1963 | devices = *((u32 *) obj->buffer.pointer); |
1954 | devices = (u32) obj->integer.value; | 1964 | } else if (obj->type == ACPI_TYPE_INTEGER) { |
1965 | devices = (u32) obj->integer.value; | ||
1966 | } | ||
1955 | } | 1967 | } |
1956 | 1968 | ||
1957 | kfree(out.pointer); | 1969 | kfree(out.pointer); |
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c index ec1d3bc2dbe2..fcde4e528819 100644 --- a/drivers/platform/x86/asus-laptop.c +++ b/drivers/platform/x86/asus-laptop.c | |||
@@ -860,8 +860,10 @@ static ssize_t show_infos(struct device *dev, | |||
860 | /* | 860 | /* |
861 | * The HWRS method return informations about the hardware. | 861 | * The HWRS method return informations about the hardware. |
862 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. | 862 | * 0x80 bit is for WLAN, 0x100 for Bluetooth. |
863 | * 0x40 for WWAN, 0x10 for WIMAX. | ||
863 | * The significance of others is yet to be found. | 864 | * The significance of others is yet to be found. |
864 | * If we don't find the method, we assume the device are present. | 865 | * We don't currently use this for device detection, and it |
866 | * takes several seconds to run on some systems. | ||
865 | */ | 867 | */ |
866 | rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); | 868 | rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp); |
867 | if (!ACPI_FAILURE(rv)) | 869 | if (!ACPI_FAILURE(rv)) |
@@ -1682,7 +1684,7 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1682 | { | 1684 | { |
1683 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 1685 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
1684 | union acpi_object *model = NULL; | 1686 | union acpi_object *model = NULL; |
1685 | unsigned long long bsts_result, hwrs_result; | 1687 | unsigned long long bsts_result; |
1686 | char *string = NULL; | 1688 | char *string = NULL; |
1687 | acpi_status status; | 1689 | acpi_status status; |
1688 | 1690 | ||
@@ -1741,20 +1743,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus) | |||
1741 | return -ENOMEM; | 1743 | return -ENOMEM; |
1742 | } | 1744 | } |
1743 | 1745 | ||
1744 | if (*string) | 1746 | if (string) |
1745 | pr_notice(" %s model detected\n", string); | 1747 | pr_notice(" %s model detected\n", string); |
1746 | 1748 | ||
1747 | /* | ||
1748 | * The HWRS method return informations about the hardware. | ||
1749 | * 0x80 bit is for WLAN, 0x100 for Bluetooth, | ||
1750 | * 0x40 for WWAN, 0x10 for WIMAX. | ||
1751 | * The significance of others is yet to be found. | ||
1752 | */ | ||
1753 | status = | ||
1754 | acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result); | ||
1755 | if (!ACPI_FAILURE(status)) | ||
1756 | pr_notice(" HWRS returned %x", (int)hwrs_result); | ||
1757 | |||
1758 | if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) | 1749 | if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL)) |
1759 | asus->have_rsts = true; | 1750 | asus->have_rsts = true; |
1760 | 1751 | ||
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c index 7481146a5b47..97c2be195efc 100644 --- a/drivers/platform/x86/ibm_rtl.c +++ b/drivers/platform/x86/ibm_rtl.c | |||
@@ -244,7 +244,7 @@ static int __init ibm_rtl_init(void) { | |||
244 | if (force) | 244 | if (force) |
245 | pr_warn("module loaded by force\n"); | 245 | pr_warn("module loaded by force\n"); |
246 | /* first ensure that we are running on IBM HW */ | 246 | /* first ensure that we are running on IBM HW */ |
247 | else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table)) | 247 | else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table)) |
248 | return -ENODEV; | 248 | return -ENODEV; |
249 | 249 | ||
250 | /* Get the address for the Extended BIOS Data Area */ | 250 | /* Get the address for the Extended BIOS Data Area */ |
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c index dd90d15f5210..d1f030053176 100644 --- a/drivers/platform/x86/samsung-laptop.c +++ b/drivers/platform/x86/samsung-laptop.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/seq_file.h> | 26 | #include <linux/seq_file.h> |
27 | #include <linux/debugfs.h> | 27 | #include <linux/debugfs.h> |
28 | #include <linux/ctype.h> | 28 | #include <linux/ctype.h> |
29 | #include <linux/efi.h> | ||
29 | #include <acpi/video.h> | 30 | #include <acpi/video.h> |
30 | 31 | ||
31 | /* | 32 | /* |
@@ -1523,6 +1524,16 @@ static struct dmi_system_id __initdata samsung_dmi_table[] = { | |||
1523 | }, | 1524 | }, |
1524 | .driver_data = &samsung_broken_acpi_video, | 1525 | .driver_data = &samsung_broken_acpi_video, |
1525 | }, | 1526 | }, |
1527 | { | ||
1528 | .callback = samsung_dmi_matched, | ||
1529 | .ident = "N250P", | ||
1530 | .matches = { | ||
1531 | DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."), | ||
1532 | DMI_MATCH(DMI_PRODUCT_NAME, "N250P"), | ||
1533 | DMI_MATCH(DMI_BOARD_NAME, "N250P"), | ||
1534 | }, | ||
1535 | .driver_data = &samsung_broken_acpi_video, | ||
1536 | }, | ||
1526 | { }, | 1537 | { }, |
1527 | }; | 1538 | }; |
1528 | MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); | 1539 | MODULE_DEVICE_TABLE(dmi, samsung_dmi_table); |
@@ -1534,6 +1545,9 @@ static int __init samsung_init(void) | |||
1534 | struct samsung_laptop *samsung; | 1545 | struct samsung_laptop *samsung; |
1535 | int ret; | 1546 | int ret; |
1536 | 1547 | ||
1548 | if (efi_enabled(EFI_BOOT)) | ||
1549 | return -ENODEV; | ||
1550 | |||
1537 | quirks = &samsung_unknown; | 1551 | quirks = &samsung_unknown; |
1538 | if (!force && !dmi_check_system(samsung_dmi_table)) | 1552 | if (!force && !dmi_check_system(samsung_dmi_table)) |
1539 | return -ENODEV; | 1553 | return -ENODEV; |
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c index daaddec68def..b8ad71f7863f 100644 --- a/drivers/platform/x86/sony-laptop.c +++ b/drivers/platform/x86/sony-laptop.c | |||
@@ -786,28 +786,29 @@ static int sony_nc_int_call(acpi_handle handle, char *name, int *value, | |||
786 | static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, | 786 | static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value, |
787 | void *buffer, size_t buflen) | 787 | void *buffer, size_t buflen) |
788 | { | 788 | { |
789 | int ret = 0; | ||
789 | size_t len = len; | 790 | size_t len = len; |
790 | union acpi_object *object = __call_snc_method(handle, name, value); | 791 | union acpi_object *object = __call_snc_method(handle, name, value); |
791 | 792 | ||
792 | if (!object) | 793 | if (!object) |
793 | return -EINVAL; | 794 | return -EINVAL; |
794 | 795 | ||
795 | if (object->type == ACPI_TYPE_BUFFER) | 796 | if (object->type == ACPI_TYPE_BUFFER) { |
796 | len = MIN(buflen, object->buffer.length); | 797 | len = MIN(buflen, object->buffer.length); |
798 | memcpy(buffer, object->buffer.pointer, len); | ||
797 | 799 | ||
798 | else if (object->type == ACPI_TYPE_INTEGER) | 800 | } else if (object->type == ACPI_TYPE_INTEGER) { |
799 | len = MIN(buflen, sizeof(object->integer.value)); | 801 | len = MIN(buflen, sizeof(object->integer.value)); |
802 | memcpy(buffer, &object->integer.value, len); | ||
800 | 803 | ||
801 | else { | 804 | } else { |
802 | pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", | 805 | pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n", |
803 | ACPI_TYPE_BUFFER, object->type); | 806 | ACPI_TYPE_BUFFER, object->type); |
804 | kfree(object); | 807 | ret = -EINVAL; |
805 | return -EINVAL; | ||
806 | } | 808 | } |
807 | 809 | ||
808 | memcpy(buffer, object->buffer.pointer, len); | ||
809 | kfree(object); | 810 | kfree(object); |
810 | return 0; | 811 | return ret; |
811 | } | 812 | } |
812 | 813 | ||
813 | struct sony_nc_handles { | 814 | struct sony_nc_handles { |
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c index f946ca7cb762..ebcb461bb2b0 100644 --- a/drivers/platform/x86/thinkpad_acpi.c +++ b/drivers/platform/x86/thinkpad_acpi.c | |||
@@ -4877,8 +4877,7 @@ static int __init light_init(struct ibm_init_struct *iibm) | |||
4877 | static void light_exit(void) | 4877 | static void light_exit(void) |
4878 | { | 4878 | { |
4879 | led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); | 4879 | led_classdev_unregister(&tpacpi_led_thinklight.led_classdev); |
4880 | if (work_pending(&tpacpi_led_thinklight.work)) | 4880 | flush_workqueue(tpacpi_wq); |
4881 | flush_workqueue(tpacpi_wq); | ||
4882 | } | 4881 | } |
4883 | 4882 | ||
4884 | static int light_read(struct seq_file *m) | 4883 | static int light_read(struct seq_file *m) |
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index 2b557119adad..c79ab843333e 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c | |||
@@ -30,8 +30,6 @@ struct pm8607_regulator_info { | |||
30 | unsigned int *vol_table; | 30 | unsigned int *vol_table; |
31 | unsigned int *vol_suspend; | 31 | unsigned int *vol_suspend; |
32 | 32 | ||
33 | int update_reg; | ||
34 | int update_bit; | ||
35 | int slope_double; | 33 | int slope_double; |
36 | }; | 34 | }; |
37 | 35 | ||
@@ -222,29 +220,6 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) | |||
222 | return ret; | 220 | return ret; |
223 | } | 221 | } |
224 | 222 | ||
225 | static int pm8607_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) | ||
226 | { | ||
227 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | ||
228 | uint8_t val; | ||
229 | int ret; | ||
230 | |||
231 | val = (uint8_t)(selector << (ffs(rdev->desc->vsel_mask) - 1)); | ||
232 | |||
233 | ret = pm860x_set_bits(info->i2c, rdev->desc->vsel_reg, | ||
234 | rdev->desc->vsel_mask, val); | ||
235 | if (ret) | ||
236 | return ret; | ||
237 | switch (info->desc.id) { | ||
238 | case PM8607_ID_BUCK1: | ||
239 | case PM8607_ID_BUCK3: | ||
240 | ret = pm860x_set_bits(info->i2c, info->update_reg, | ||
241 | 1 << info->update_bit, | ||
242 | 1 << info->update_bit); | ||
243 | break; | ||
244 | } | ||
245 | return ret; | ||
246 | } | ||
247 | |||
248 | static int pm8606_preg_enable(struct regulator_dev *rdev) | 223 | static int pm8606_preg_enable(struct regulator_dev *rdev) |
249 | { | 224 | { |
250 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); | 225 | struct pm8607_regulator_info *info = rdev_get_drvdata(rdev); |
@@ -276,7 +251,7 @@ static int pm8606_preg_is_enabled(struct regulator_dev *rdev) | |||
276 | 251 | ||
277 | static struct regulator_ops pm8607_regulator_ops = { | 252 | static struct regulator_ops pm8607_regulator_ops = { |
278 | .list_voltage = pm8607_list_voltage, | 253 | .list_voltage = pm8607_list_voltage, |
279 | .set_voltage_sel = pm8607_set_voltage_sel, | 254 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
280 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 255 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
281 | .enable = regulator_enable_regmap, | 256 | .enable = regulator_enable_regmap, |
282 | .disable = regulator_disable_regmap, | 257 | .disable = regulator_disable_regmap, |
@@ -313,11 +288,11 @@ static struct regulator_ops pm8606_preg_ops = { | |||
313 | .n_voltages = ARRAY_SIZE(vreg##_table), \ | 288 | .n_voltages = ARRAY_SIZE(vreg##_table), \ |
314 | .vsel_reg = PM8607_##vreg, \ | 289 | .vsel_reg = PM8607_##vreg, \ |
315 | .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ | 290 | .vsel_mask = ARRAY_SIZE(vreg##_table) - 1, \ |
291 | .apply_reg = PM8607_##ureg, \ | ||
292 | .apply_bit = (ubit), \ | ||
316 | .enable_reg = PM8607_##ereg, \ | 293 | .enable_reg = PM8607_##ereg, \ |
317 | .enable_mask = 1 << (ebit), \ | 294 | .enable_mask = 1 << (ebit), \ |
318 | }, \ | 295 | }, \ |
319 | .update_reg = PM8607_##ureg, \ | ||
320 | .update_bit = (ubit), \ | ||
321 | .slope_double = (0), \ | 296 | .slope_double = (0), \ |
322 | .vol_table = (unsigned int *)&vreg##_table, \ | 297 | .vol_table = (unsigned int *)&vreg##_table, \ |
323 | .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ | 298 | .vol_suspend = (unsigned int *)&vreg##_suspend_table, \ |
@@ -343,9 +318,9 @@ static struct regulator_ops pm8606_preg_ops = { | |||
343 | } | 318 | } |
344 | 319 | ||
345 | static struct pm8607_regulator_info pm8607_regulator_info[] = { | 320 | static struct pm8607_regulator_info pm8607_regulator_info[] = { |
346 | PM8607_DVC(BUCK1, GO, 0, SUPPLIES_EN11, 0), | 321 | PM8607_DVC(BUCK1, GO, BIT(0), SUPPLIES_EN11, 0), |
347 | PM8607_DVC(BUCK2, GO, 1, SUPPLIES_EN11, 1), | 322 | PM8607_DVC(BUCK2, GO, BIT(1), SUPPLIES_EN11, 1), |
348 | PM8607_DVC(BUCK3, GO, 2, SUPPLIES_EN11, 2), | 323 | PM8607_DVC(BUCK3, GO, BIT(2), SUPPLIES_EN11, 2), |
349 | 324 | ||
350 | PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3), | 325 | PM8607_LDO(1, LDO1, 0, SUPPLIES_EN11, 3), |
351 | PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4), | 326 | PM8607_LDO(2, LDO2, 0, SUPPLIES_EN11, 4), |
@@ -372,7 +347,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev, | |||
372 | struct regulator_config *config) | 347 | struct regulator_config *config) |
373 | { | 348 | { |
374 | struct device_node *nproot, *np; | 349 | struct device_node *nproot, *np; |
375 | nproot = pdev->dev.parent->of_node; | 350 | nproot = of_node_get(pdev->dev.parent->of_node); |
376 | if (!nproot) | 351 | if (!nproot) |
377 | return -ENODEV; | 352 | return -ENODEV; |
378 | nproot = of_find_node_by_name(nproot, "regulators"); | 353 | nproot = of_find_node_by_name(nproot, "regulators"); |
@@ -388,6 +363,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev, | |||
388 | break; | 363 | break; |
389 | } | 364 | } |
390 | } | 365 | } |
366 | of_node_put(nproot); | ||
391 | return 0; | 367 | return 0; |
392 | } | 368 | } |
393 | #else | 369 | #else |
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 551a22b07538..a5d97eaee99e 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig | |||
@@ -91,6 +91,7 @@ config REGULATOR_AAT2870 | |||
91 | config REGULATOR_ARIZONA | 91 | config REGULATOR_ARIZONA |
92 | tristate "Wolfson Arizona class devices" | 92 | tristate "Wolfson Arizona class devices" |
93 | depends on MFD_ARIZONA | 93 | depends on MFD_ARIZONA |
94 | depends on SND_SOC | ||
94 | help | 95 | help |
95 | Support for the regulators found on Wolfson Arizona class | 96 | Support for the regulators found on Wolfson Arizona class |
96 | devices. | 97 | devices. |
@@ -277,6 +278,15 @@ config REGULATOR_LP872X | |||
277 | help | 278 | help |
278 | This driver supports LP8720/LP8725 PMIC | 279 | This driver supports LP8720/LP8725 PMIC |
279 | 280 | ||
281 | config REGULATOR_LP8755 | ||
282 | tristate "TI LP8755 High Performance PMU driver" | ||
283 | depends on I2C | ||
284 | select REGMAP_I2C | ||
285 | help | ||
286 | This driver supports LP8755 High Performance PMU driver. This | ||
287 | chip contains six step-down DC/DC converters which can support | ||
288 | 9 mode multiphase configuration. | ||
289 | |||
280 | config REGULATOR_LP8788 | 290 | config REGULATOR_LP8788 |
281 | bool "TI LP8788 Power Regulators" | 291 | bool "TI LP8788 Power Regulators" |
282 | depends on MFD_LP8788 | 292 | depends on MFD_LP8788 |
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index b802b0c7fb02..6e8250382def 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile | |||
@@ -30,6 +30,7 @@ obj-$(CONFIG_REGULATOR_LP3972) += lp3972.o | |||
30 | obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o | 30 | obj-$(CONFIG_REGULATOR_LP872X) += lp872x.o |
31 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o | 31 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-buck.o |
32 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o | 32 | obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o |
33 | obj-$(CONFIG_REGULATOR_LP8755) += lp8755.o | ||
33 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o | 34 | obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o |
34 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o | 35 | obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o |
35 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o | 36 | obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o |
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 8f39cac661d2..0d4a8ccbb536 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c | |||
@@ -31,12 +31,18 @@ | |||
31 | #include <linux/regulator/driver.h> | 31 | #include <linux/regulator/driver.h> |
32 | #include <linux/regulator/of_regulator.h> | 32 | #include <linux/regulator/of_regulator.h> |
33 | 33 | ||
34 | #define LDO_RAMP_UP_UNIT_IN_CYCLES 64 /* 64 cycles per step */ | ||
35 | #define LDO_RAMP_UP_FREQ_IN_MHZ 24 /* cycle based on 24M OSC */ | ||
36 | |||
34 | struct anatop_regulator { | 37 | struct anatop_regulator { |
35 | const char *name; | 38 | const char *name; |
36 | u32 control_reg; | 39 | u32 control_reg; |
37 | struct regmap *anatop; | 40 | struct regmap *anatop; |
38 | int vol_bit_shift; | 41 | int vol_bit_shift; |
39 | int vol_bit_width; | 42 | int vol_bit_width; |
43 | u32 delay_reg; | ||
44 | int delay_bit_shift; | ||
45 | int delay_bit_width; | ||
40 | int min_bit_val; | 46 | int min_bit_val; |
41 | int min_voltage; | 47 | int min_voltage; |
42 | int max_voltage; | 48 | int max_voltage; |
@@ -55,6 +61,32 @@ static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg, | |||
55 | return regulator_set_voltage_sel_regmap(reg, selector); | 61 | return regulator_set_voltage_sel_regmap(reg, selector); |
56 | } | 62 | } |
57 | 63 | ||
64 | static int anatop_regmap_set_voltage_time_sel(struct regulator_dev *reg, | ||
65 | unsigned int old_sel, | ||
66 | unsigned int new_sel) | ||
67 | { | ||
68 | struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); | ||
69 | u32 val; | ||
70 | int ret = 0; | ||
71 | |||
72 | /* check whether need to care about LDO ramp up speed */ | ||
73 | if (anatop_reg->delay_bit_width && new_sel > old_sel) { | ||
74 | /* | ||
75 | * the delay for LDO ramp up time is | ||
76 | * based on the register setting, we need | ||
77 | * to calculate how many steps LDO need to | ||
78 | * ramp up, and how much delay needed. (us) | ||
79 | */ | ||
80 | regmap_read(anatop_reg->anatop, anatop_reg->delay_reg, &val); | ||
81 | val = (val >> anatop_reg->delay_bit_shift) & | ||
82 | ((1 << anatop_reg->delay_bit_width) - 1); | ||
83 | ret = (new_sel - old_sel) * (LDO_RAMP_UP_UNIT_IN_CYCLES << | ||
84 | val) / LDO_RAMP_UP_FREQ_IN_MHZ + 1; | ||
85 | } | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
58 | static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) | 90 | static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) |
59 | { | 91 | { |
60 | struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); | 92 | struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); |
@@ -67,6 +99,7 @@ static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) | |||
67 | 99 | ||
68 | static struct regulator_ops anatop_rops = { | 100 | static struct regulator_ops anatop_rops = { |
69 | .set_voltage_sel = anatop_regmap_set_voltage_sel, | 101 | .set_voltage_sel = anatop_regmap_set_voltage_sel, |
102 | .set_voltage_time_sel = anatop_regmap_set_voltage_time_sel, | ||
70 | .get_voltage_sel = anatop_regmap_get_voltage_sel, | 103 | .get_voltage_sel = anatop_regmap_get_voltage_sel, |
71 | .list_voltage = regulator_list_voltage_linear, | 104 | .list_voltage = regulator_list_voltage_linear, |
72 | .map_voltage = regulator_map_voltage_linear, | 105 | .map_voltage = regulator_map_voltage_linear, |
@@ -143,6 +176,14 @@ static int anatop_regulator_probe(struct platform_device *pdev) | |||
143 | goto anatop_probe_end; | 176 | goto anatop_probe_end; |
144 | } | 177 | } |
145 | 178 | ||
179 | /* read LDO ramp up setting, only for core reg */ | ||
180 | of_property_read_u32(np, "anatop-delay-reg-offset", | ||
181 | &sreg->delay_reg); | ||
182 | of_property_read_u32(np, "anatop-delay-bit-width", | ||
183 | &sreg->delay_bit_width); | ||
184 | of_property_read_u32(np, "anatop-delay-bit-shift", | ||
185 | &sreg->delay_bit_shift); | ||
186 | |||
146 | rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1 | 187 | rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1 |
147 | + sreg->min_bit_val; | 188 | + sreg->min_bit_val; |
148 | rdesc->min_uV = sreg->min_voltage; | 189 | rdesc->min_uV = sreg->min_voltage; |
diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index a6d040cbf8ac..e87536bf0bed 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
22 | #include <linux/gpio.h> | 22 | #include <linux/gpio.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/workqueue.h> | ||
25 | #include <sound/soc.h> | ||
24 | 26 | ||
25 | #include <linux/mfd/arizona/core.h> | 27 | #include <linux/mfd/arizona/core.h> |
26 | #include <linux/mfd/arizona/pdata.h> | 28 | #include <linux/mfd/arizona/pdata.h> |
@@ -34,6 +36,8 @@ struct arizona_micsupp { | |||
34 | 36 | ||
35 | struct regulator_consumer_supply supply; | 37 | struct regulator_consumer_supply supply; |
36 | struct regulator_init_data init_data; | 38 | struct regulator_init_data init_data; |
39 | |||
40 | struct work_struct check_cp_work; | ||
37 | }; | 41 | }; |
38 | 42 | ||
39 | static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, | 43 | static int arizona_micsupp_list_voltage(struct regulator_dev *rdev, |
@@ -72,9 +76,73 @@ static int arizona_micsupp_map_voltage(struct regulator_dev *rdev, | |||
72 | return selector; | 76 | return selector; |
73 | } | 77 | } |
74 | 78 | ||
79 | static void arizona_micsupp_check_cp(struct work_struct *work) | ||
80 | { | ||
81 | struct arizona_micsupp *micsupp = | ||
82 | container_of(work, struct arizona_micsupp, check_cp_work); | ||
83 | struct snd_soc_dapm_context *dapm = micsupp->arizona->dapm; | ||
84 | struct arizona *arizona = micsupp->arizona; | ||
85 | struct regmap *regmap = arizona->regmap; | ||
86 | unsigned int reg; | ||
87 | int ret; | ||
88 | |||
89 | ret = regmap_read(regmap, ARIZONA_MIC_CHARGE_PUMP_1, ®); | ||
90 | if (ret != 0) { | ||
91 | dev_err(arizona->dev, "Failed to read CP state: %d\n", ret); | ||
92 | return; | ||
93 | } | ||
94 | |||
95 | if (dapm) { | ||
96 | if ((reg & (ARIZONA_CPMIC_ENA | ARIZONA_CPMIC_BYPASS)) == | ||
97 | ARIZONA_CPMIC_ENA) | ||
98 | snd_soc_dapm_force_enable_pin(dapm, "MICSUPP"); | ||
99 | else | ||
100 | snd_soc_dapm_disable_pin(dapm, "MICSUPP"); | ||
101 | |||
102 | snd_soc_dapm_sync(dapm); | ||
103 | } | ||
104 | } | ||
105 | |||
106 | static int arizona_micsupp_enable(struct regulator_dev *rdev) | ||
107 | { | ||
108 | struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); | ||
109 | int ret; | ||
110 | |||
111 | ret = regulator_enable_regmap(rdev); | ||
112 | |||
113 | if (ret == 0) | ||
114 | schedule_work(&micsupp->check_cp_work); | ||
115 | |||
116 | return ret; | ||
117 | } | ||
118 | |||
119 | static int arizona_micsupp_disable(struct regulator_dev *rdev) | ||
120 | { | ||
121 | struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); | ||
122 | int ret; | ||
123 | |||
124 | ret = regulator_disable_regmap(rdev); | ||
125 | if (ret == 0) | ||
126 | schedule_work(&micsupp->check_cp_work); | ||
127 | |||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | static int arizona_micsupp_set_bypass(struct regulator_dev *rdev, bool ena) | ||
132 | { | ||
133 | struct arizona_micsupp *micsupp = rdev_get_drvdata(rdev); | ||
134 | int ret; | ||
135 | |||
136 | ret = regulator_set_bypass_regmap(rdev, ena); | ||
137 | if (ret == 0) | ||
138 | schedule_work(&micsupp->check_cp_work); | ||
139 | |||
140 | return ret; | ||
141 | } | ||
142 | |||
75 | static struct regulator_ops arizona_micsupp_ops = { | 143 | static struct regulator_ops arizona_micsupp_ops = { |
76 | .enable = regulator_enable_regmap, | 144 | .enable = arizona_micsupp_enable, |
77 | .disable = regulator_disable_regmap, | 145 | .disable = arizona_micsupp_disable, |
78 | .is_enabled = regulator_is_enabled_regmap, | 146 | .is_enabled = regulator_is_enabled_regmap, |
79 | 147 | ||
80 | .list_voltage = arizona_micsupp_list_voltage, | 148 | .list_voltage = arizona_micsupp_list_voltage, |
@@ -84,7 +152,7 @@ static struct regulator_ops arizona_micsupp_ops = { | |||
84 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | 152 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
85 | 153 | ||
86 | .get_bypass = regulator_get_bypass_regmap, | 154 | .get_bypass = regulator_get_bypass_regmap, |
87 | .set_bypass = regulator_set_bypass_regmap, | 155 | .set_bypass = arizona_micsupp_set_bypass, |
88 | }; | 156 | }; |
89 | 157 | ||
90 | static const struct regulator_desc arizona_micsupp = { | 158 | static const struct regulator_desc arizona_micsupp = { |
@@ -109,7 +177,8 @@ static const struct regulator_desc arizona_micsupp = { | |||
109 | static const struct regulator_init_data arizona_micsupp_default = { | 177 | static const struct regulator_init_data arizona_micsupp_default = { |
110 | .constraints = { | 178 | .constraints = { |
111 | .valid_ops_mask = REGULATOR_CHANGE_STATUS | | 179 | .valid_ops_mask = REGULATOR_CHANGE_STATUS | |
112 | REGULATOR_CHANGE_VOLTAGE, | 180 | REGULATOR_CHANGE_VOLTAGE | |
181 | REGULATOR_CHANGE_BYPASS, | ||
113 | .min_uV = 1700000, | 182 | .min_uV = 1700000, |
114 | .max_uV = 3300000, | 183 | .max_uV = 3300000, |
115 | }, | 184 | }, |
@@ -131,6 +200,7 @@ static int arizona_micsupp_probe(struct platform_device *pdev) | |||
131 | } | 200 | } |
132 | 201 | ||
133 | micsupp->arizona = arizona; | 202 | micsupp->arizona = arizona; |
203 | INIT_WORK(&micsupp->check_cp_work, arizona_micsupp_check_cp); | ||
134 | 204 | ||
135 | /* | 205 | /* |
136 | * Since the chip usually supplies itself we provide some | 206 | * Since the chip usually supplies itself we provide some |
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c index 2f1341db38a0..f0ba8c4eefa9 100644 --- a/drivers/regulator/as3711-regulator.c +++ b/drivers/regulator/as3711-regulator.c | |||
@@ -303,7 +303,7 @@ static int as3711_regulator_probe(struct platform_device *pdev) | |||
303 | reg_data = pdata ? pdata->init_data[id] : NULL; | 303 | reg_data = pdata ? pdata->init_data[id] : NULL; |
304 | 304 | ||
305 | /* No need to register if there is no regulator data */ | 305 | /* No need to register if there is no regulator data */ |
306 | if (!ri->desc.name) | 306 | if (!reg_data) |
307 | continue; | 307 | continue; |
308 | 308 | ||
309 | reg = ®s[id]; | 309 | reg = ®s[id]; |
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 0f65b246cc0c..da9782bd27d0 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c | |||
@@ -200,8 +200,8 @@ static int regulator_check_consumers(struct regulator_dev *rdev, | |||
200 | } | 200 | } |
201 | 201 | ||
202 | if (*min_uV > *max_uV) { | 202 | if (*min_uV > *max_uV) { |
203 | dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n", | 203 | rdev_err(rdev, "Restricting voltage, %u-%uuV\n", |
204 | regulator->min_uV, regulator->max_uV); | 204 | *min_uV, *max_uV); |
205 | return -EINVAL; | 205 | return -EINVAL; |
206 | } | 206 | } |
207 | 207 | ||
@@ -1885,9 +1885,15 @@ int regulator_can_change_voltage(struct regulator *regulator) | |||
1885 | struct regulator_dev *rdev = regulator->rdev; | 1885 | struct regulator_dev *rdev = regulator->rdev; |
1886 | 1886 | ||
1887 | if (rdev->constraints && | 1887 | if (rdev->constraints && |
1888 | rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE && | 1888 | (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) { |
1889 | (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1) | 1889 | if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1) |
1890 | return 1; | 1890 | return 1; |
1891 | |||
1892 | if (rdev->desc->continuous_voltage_range && | ||
1893 | rdev->constraints->min_uV && rdev->constraints->max_uV && | ||
1894 | rdev->constraints->min_uV != rdev->constraints->max_uV) | ||
1895 | return 1; | ||
1896 | } | ||
1891 | 1897 | ||
1892 | return 0; | 1898 | return 0; |
1893 | } | 1899 | } |
@@ -2074,10 +2080,20 @@ EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); | |||
2074 | */ | 2080 | */ |
2075 | int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) | 2081 | int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) |
2076 | { | 2082 | { |
2083 | int ret; | ||
2084 | |||
2077 | sel <<= ffs(rdev->desc->vsel_mask) - 1; | 2085 | sel <<= ffs(rdev->desc->vsel_mask) - 1; |
2078 | 2086 | ||
2079 | return regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, | 2087 | ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, |
2080 | rdev->desc->vsel_mask, sel); | 2088 | rdev->desc->vsel_mask, sel); |
2089 | if (ret) | ||
2090 | return ret; | ||
2091 | |||
2092 | if (rdev->desc->apply_bit) | ||
2093 | ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, | ||
2094 | rdev->desc->apply_bit, | ||
2095 | rdev->desc->apply_bit); | ||
2096 | return ret; | ||
2081 | } | 2097 | } |
2082 | EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); | 2098 | EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); |
2083 | 2099 | ||
@@ -2223,8 +2239,11 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, | |||
2223 | best_val = rdev->desc->ops->list_voltage(rdev, ret); | 2239 | best_val = rdev->desc->ops->list_voltage(rdev, ret); |
2224 | if (min_uV <= best_val && max_uV >= best_val) { | 2240 | if (min_uV <= best_val && max_uV >= best_val) { |
2225 | selector = ret; | 2241 | selector = ret; |
2226 | ret = rdev->desc->ops->set_voltage_sel(rdev, | 2242 | if (old_selector == selector) |
2227 | ret); | 2243 | ret = 0; |
2244 | else | ||
2245 | ret = rdev->desc->ops->set_voltage_sel( | ||
2246 | rdev, ret); | ||
2228 | } else { | 2247 | } else { |
2229 | ret = -EINVAL; | 2248 | ret = -EINVAL; |
2230 | } | 2249 | } |
@@ -2235,7 +2254,7 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, | |||
2235 | 2254 | ||
2236 | /* Call set_voltage_time_sel if successfully obtained old_selector */ | 2255 | /* Call set_voltage_time_sel if successfully obtained old_selector */ |
2237 | if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && | 2256 | if (ret == 0 && _regulator_is_enabled(rdev) && old_selector >= 0 && |
2238 | rdev->desc->ops->set_voltage_time_sel) { | 2257 | old_selector != selector && rdev->desc->ops->set_voltage_time_sel) { |
2239 | 2258 | ||
2240 | delay = rdev->desc->ops->set_voltage_time_sel(rdev, | 2259 | delay = rdev->desc->ops->set_voltage_time_sel(rdev, |
2241 | old_selector, selector); | 2260 | old_selector, selector); |
@@ -2288,6 +2307,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) | |||
2288 | { | 2307 | { |
2289 | struct regulator_dev *rdev = regulator->rdev; | 2308 | struct regulator_dev *rdev = regulator->rdev; |
2290 | int ret = 0; | 2309 | int ret = 0; |
2310 | int old_min_uV, old_max_uV; | ||
2291 | 2311 | ||
2292 | mutex_lock(&rdev->mutex); | 2312 | mutex_lock(&rdev->mutex); |
2293 | 2313 | ||
@@ -2309,18 +2329,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV) | |||
2309 | ret = regulator_check_voltage(rdev, &min_uV, &max_uV); | 2329 | ret = regulator_check_voltage(rdev, &min_uV, &max_uV); |
2310 | if (ret < 0) | 2330 | if (ret < 0) |
2311 | goto out; | 2331 | goto out; |
2332 | |||
2333 | /* restore original values in case of error */ | ||
2334 | old_min_uV = regulator->min_uV; | ||
2335 | old_max_uV = regulator->max_uV; | ||
2312 | regulator->min_uV = min_uV; | 2336 | regulator->min_uV = min_uV; |
2313 | regulator->max_uV = max_uV; | 2337 | regulator->max_uV = max_uV; |
2314 | 2338 | ||
2315 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV); | 2339 | ret = regulator_check_consumers(rdev, &min_uV, &max_uV); |
2316 | if (ret < 0) | 2340 | if (ret < 0) |
2317 | goto out; | 2341 | goto out2; |
2318 | 2342 | ||
2319 | ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); | 2343 | ret = _regulator_do_set_voltage(rdev, min_uV, max_uV); |
2320 | 2344 | if (ret < 0) | |
2345 | goto out2; | ||
2346 | |||
2321 | out: | 2347 | out: |
2322 | mutex_unlock(&rdev->mutex); | 2348 | mutex_unlock(&rdev->mutex); |
2323 | return ret; | 2349 | return ret; |
2350 | out2: | ||
2351 | regulator->min_uV = old_min_uV; | ||
2352 | regulator->max_uV = old_max_uV; | ||
2353 | mutex_unlock(&rdev->mutex); | ||
2354 | return ret; | ||
2324 | } | 2355 | } |
2325 | EXPORT_SYMBOL_GPL(regulator_set_voltage); | 2356 | EXPORT_SYMBOL_GPL(regulator_set_voltage); |
2326 | 2357 | ||
@@ -3202,7 +3233,7 @@ static int add_regulator_attributes(struct regulator_dev *rdev) | |||
3202 | if (status < 0) | 3233 | if (status < 0) |
3203 | return status; | 3234 | return status; |
3204 | } | 3235 | } |
3205 | if (ops->is_enabled) { | 3236 | if (rdev->ena_gpio || ops->is_enabled) { |
3206 | status = device_create_file(dev, &dev_attr_state); | 3237 | status = device_create_file(dev, &dev_attr_state); |
3207 | if (status < 0) | 3238 | if (status < 0) |
3208 | return status; | 3239 | return status; |
@@ -3315,7 +3346,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) | |||
3315 | * @config: runtime configuration for regulator | 3346 | * @config: runtime configuration for regulator |
3316 | * | 3347 | * |
3317 | * Called by regulator drivers to register a regulator. | 3348 | * Called by regulator drivers to register a regulator. |
3318 | * Returns 0 on success. | 3349 | * Returns a valid pointer to struct regulator_dev on success |
3350 | * or an ERR_PTR() on error. | ||
3319 | */ | 3351 | */ |
3320 | struct regulator_dev * | 3352 | struct regulator_dev * |
3321 | regulator_register(const struct regulator_desc *regulator_desc, | 3353 | regulator_register(const struct regulator_desc *regulator_desc, |
diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index d0963090442d..96b569abb46c 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c | |||
@@ -70,7 +70,6 @@ struct da9052_regulator_info { | |||
70 | int step_uV; | 70 | int step_uV; |
71 | int min_uV; | 71 | int min_uV; |
72 | int max_uV; | 72 | int max_uV; |
73 | unsigned char activate_bit; | ||
74 | }; | 73 | }; |
75 | 74 | ||
76 | struct da9052_regulator { | 75 | struct da9052_regulator { |
@@ -210,36 +209,6 @@ static int da9052_map_voltage(struct regulator_dev *rdev, | |||
210 | return sel; | 209 | return sel; |
211 | } | 210 | } |
212 | 211 | ||
213 | static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev, | ||
214 | unsigned int selector) | ||
215 | { | ||
216 | struct da9052_regulator *regulator = rdev_get_drvdata(rdev); | ||
217 | struct da9052_regulator_info *info = regulator->info; | ||
218 | int id = rdev_get_id(rdev); | ||
219 | int ret; | ||
220 | |||
221 | ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg, | ||
222 | rdev->desc->vsel_mask, selector); | ||
223 | if (ret < 0) | ||
224 | return ret; | ||
225 | |||
226 | /* Some LDOs and DCDCs are DVC controlled which requires enabling of | ||
227 | * the activate bit to implment the changes on the output. | ||
228 | */ | ||
229 | switch (id) { | ||
230 | case DA9052_ID_BUCK1: | ||
231 | case DA9052_ID_BUCK2: | ||
232 | case DA9052_ID_BUCK3: | ||
233 | case DA9052_ID_LDO2: | ||
234 | case DA9052_ID_LDO3: | ||
235 | ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG, | ||
236 | info->activate_bit, info->activate_bit); | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | return ret; | ||
241 | } | ||
242 | |||
243 | static struct regulator_ops da9052_dcdc_ops = { | 212 | static struct regulator_ops da9052_dcdc_ops = { |
244 | .get_current_limit = da9052_dcdc_get_current_limit, | 213 | .get_current_limit = da9052_dcdc_get_current_limit, |
245 | .set_current_limit = da9052_dcdc_set_current_limit, | 214 | .set_current_limit = da9052_dcdc_set_current_limit, |
@@ -247,7 +216,7 @@ static struct regulator_ops da9052_dcdc_ops = { | |||
247 | .list_voltage = da9052_list_voltage, | 216 | .list_voltage = da9052_list_voltage, |
248 | .map_voltage = da9052_map_voltage, | 217 | .map_voltage = da9052_map_voltage, |
249 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 218 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
250 | .set_voltage_sel = da9052_regulator_set_voltage_sel, | 219 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
251 | .is_enabled = regulator_is_enabled_regmap, | 220 | .is_enabled = regulator_is_enabled_regmap, |
252 | .enable = regulator_enable_regmap, | 221 | .enable = regulator_enable_regmap, |
253 | .disable = regulator_disable_regmap, | 222 | .disable = regulator_disable_regmap, |
@@ -257,7 +226,7 @@ static struct regulator_ops da9052_ldo_ops = { | |||
257 | .list_voltage = da9052_list_voltage, | 226 | .list_voltage = da9052_list_voltage, |
258 | .map_voltage = da9052_map_voltage, | 227 | .map_voltage = da9052_map_voltage, |
259 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 228 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
260 | .set_voltage_sel = da9052_regulator_set_voltage_sel, | 229 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
261 | .is_enabled = regulator_is_enabled_regmap, | 230 | .is_enabled = regulator_is_enabled_regmap, |
262 | .enable = regulator_enable_regmap, | 231 | .enable = regulator_enable_regmap, |
263 | .disable = regulator_disable_regmap, | 232 | .disable = regulator_disable_regmap, |
@@ -274,13 +243,14 @@ static struct regulator_ops da9052_ldo_ops = { | |||
274 | .owner = THIS_MODULE,\ | 243 | .owner = THIS_MODULE,\ |
275 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 244 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
276 | .vsel_mask = (1 << (sbits)) - 1,\ | 245 | .vsel_mask = (1 << (sbits)) - 1,\ |
246 | .apply_reg = DA9052_SUPPLY_REG, \ | ||
247 | .apply_bit = (abits), \ | ||
277 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 248 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
278 | .enable_mask = 1 << (ebits),\ | 249 | .enable_mask = 1 << (ebits),\ |
279 | },\ | 250 | },\ |
280 | .min_uV = (min) * 1000,\ | 251 | .min_uV = (min) * 1000,\ |
281 | .max_uV = (max) * 1000,\ | 252 | .max_uV = (max) * 1000,\ |
282 | .step_uV = (step) * 1000,\ | 253 | .step_uV = (step) * 1000,\ |
283 | .activate_bit = (abits),\ | ||
284 | } | 254 | } |
285 | 255 | ||
286 | #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ | 256 | #define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \ |
@@ -294,13 +264,14 @@ static struct regulator_ops da9052_ldo_ops = { | |||
294 | .owner = THIS_MODULE,\ | 264 | .owner = THIS_MODULE,\ |
295 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 265 | .vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
296 | .vsel_mask = (1 << (sbits)) - 1,\ | 266 | .vsel_mask = (1 << (sbits)) - 1,\ |
267 | .apply_reg = DA9052_SUPPLY_REG, \ | ||
268 | .apply_bit = (abits), \ | ||
297 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ | 269 | .enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \ |
298 | .enable_mask = 1 << (ebits),\ | 270 | .enable_mask = 1 << (ebits),\ |
299 | },\ | 271 | },\ |
300 | .min_uV = (min) * 1000,\ | 272 | .min_uV = (min) * 1000,\ |
301 | .max_uV = (max) * 1000,\ | 273 | .max_uV = (max) * 1000,\ |
302 | .step_uV = (step) * 1000,\ | 274 | .step_uV = (step) * 1000,\ |
303 | .activate_bit = (abits),\ | ||
304 | } | 275 | } |
305 | 276 | ||
306 | static struct da9052_regulator_info da9052_regulator_info[] = { | 277 | static struct da9052_regulator_info da9052_regulator_info[] = { |
@@ -395,9 +366,9 @@ static int da9052_regulator_probe(struct platform_device *pdev) | |||
395 | config.init_data = pdata->regulators[pdev->id]; | 366 | config.init_data = pdata->regulators[pdev->id]; |
396 | } else { | 367 | } else { |
397 | #ifdef CONFIG_OF | 368 | #ifdef CONFIG_OF |
398 | struct device_node *nproot = da9052->dev->of_node; | 369 | struct device_node *nproot, *np; |
399 | struct device_node *np; | ||
400 | 370 | ||
371 | nproot = of_node_get(da9052->dev->of_node); | ||
401 | if (!nproot) | 372 | if (!nproot) |
402 | return -ENODEV; | 373 | return -ENODEV; |
403 | 374 | ||
@@ -414,6 +385,7 @@ static int da9052_regulator_probe(struct platform_device *pdev) | |||
414 | break; | 385 | break; |
415 | } | 386 | } |
416 | } | 387 | } |
388 | of_node_put(nproot); | ||
417 | #endif | 389 | #endif |
418 | } | 390 | } |
419 | 391 | ||
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index 1a05ac66878f..30221099d09c 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c | |||
@@ -58,7 +58,6 @@ struct da9055_volt_reg { | |||
58 | int reg_b; | 58 | int reg_b; |
59 | int sl_shift; | 59 | int sl_shift; |
60 | int v_mask; | 60 | int v_mask; |
61 | int v_shift; | ||
62 | }; | 61 | }; |
63 | 62 | ||
64 | struct da9055_mode_reg { | 63 | struct da9055_mode_reg { |
@@ -388,7 +387,6 @@ static struct regulator_ops da9055_ldo_ops = { | |||
388 | .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ | 387 | .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ |
389 | .sl_shift = 7,\ | 388 | .sl_shift = 7,\ |
390 | .v_mask = (1 << (vbits)) - 1,\ | 389 | .v_mask = (1 << (vbits)) - 1,\ |
391 | .v_shift = (vbits),\ | ||
392 | },\ | 390 | },\ |
393 | } | 391 | } |
394 | 392 | ||
@@ -417,7 +415,6 @@ static struct regulator_ops da9055_ldo_ops = { | |||
417 | .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ | 415 | .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ |
418 | .sl_shift = 7,\ | 416 | .sl_shift = 7,\ |
419 | .v_mask = (1 << (vbits)) - 1,\ | 417 | .v_mask = (1 << (vbits)) - 1,\ |
420 | .v_shift = (vbits),\ | ||
421 | },\ | 418 | },\ |
422 | .mode = {\ | 419 | .mode = {\ |
423 | .reg = DA9055_REG_BCORE_MODE,\ | 420 | .reg = DA9055_REG_BCORE_MODE,\ |
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c index 261f3d2299bc..89bd2faaef8c 100644 --- a/drivers/regulator/dbx500-prcmu.c +++ b/drivers/regulator/dbx500-prcmu.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/debugfs.h> | 14 | #include <linux/debugfs.h> |
15 | #include <linux/seq_file.h> | 15 | #include <linux/seq_file.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/module.h> | ||
17 | 18 | ||
18 | #include "dbx500-prcmu.h" | 19 | #include "dbx500-prcmu.h" |
19 | 20 | ||
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index bae681ccd3ea..9d39eb4aafa3 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c | |||
@@ -132,7 +132,7 @@ static struct regulator_ops gpio_regulator_voltage_ops = { | |||
132 | .list_voltage = gpio_regulator_list_voltage, | 132 | .list_voltage = gpio_regulator_list_voltage, |
133 | }; | 133 | }; |
134 | 134 | ||
135 | struct gpio_regulator_config * | 135 | static struct gpio_regulator_config * |
136 | of_get_gpio_regulator_config(struct device *dev, struct device_node *np) | 136 | of_get_gpio_regulator_config(struct device *dev, struct device_node *np) |
137 | { | 137 | { |
138 | struct gpio_regulator_config *config; | 138 | struct gpio_regulator_config *config; |
@@ -163,10 +163,7 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np) | |||
163 | config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); | 163 | config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0); |
164 | 164 | ||
165 | /* Fetch GPIOs. */ | 165 | /* Fetch GPIOs. */ |
166 | for (i = 0; ; i++) | 166 | config->nr_gpios = of_gpio_count(np); |
167 | if (of_get_named_gpio(np, "gpios", i) < 0) | ||
168 | break; | ||
169 | config->nr_gpios = i; | ||
170 | 167 | ||
171 | config->gpios = devm_kzalloc(dev, | 168 | config->gpios = devm_kzalloc(dev, |
172 | sizeof(struct gpio) * config->nr_gpios, | 169 | sizeof(struct gpio) * config->nr_gpios, |
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c index 5f68ff11a298..9cb2c0f34515 100644 --- a/drivers/regulator/lp3971.c +++ b/drivers/regulator/lp3971.c | |||
@@ -73,8 +73,6 @@ static const unsigned int buck_voltage_map[] = { | |||
73 | }; | 73 | }; |
74 | 74 | ||
75 | #define BUCK_TARGET_VOL_MASK 0x3f | 75 | #define BUCK_TARGET_VOL_MASK 0x3f |
76 | #define BUCK_TARGET_VOL_MIN_IDX 0x01 | ||
77 | #define BUCK_TARGET_VOL_MAX_IDX 0x19 | ||
78 | 76 | ||
79 | #define LP3971_BUCK_RAMP_REG(x) (buck_base_addr[x]+2) | 77 | #define LP3971_BUCK_RAMP_REG(x) (buck_base_addr[x]+2) |
80 | 78 | ||
@@ -140,7 +138,7 @@ static int lp3971_ldo_disable(struct regulator_dev *dev) | |||
140 | return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0); | 138 | return lp3971_set_bits(lp3971, LP3971_LDO_ENABLE_REG, mask, 0); |
141 | } | 139 | } |
142 | 140 | ||
143 | static int lp3971_ldo_get_voltage(struct regulator_dev *dev) | 141 | static int lp3971_ldo_get_voltage_sel(struct regulator_dev *dev) |
144 | { | 142 | { |
145 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | 143 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); |
146 | int ldo = rdev_get_id(dev) - LP3971_LDO1; | 144 | int ldo = rdev_get_id(dev) - LP3971_LDO1; |
@@ -149,7 +147,7 @@ static int lp3971_ldo_get_voltage(struct regulator_dev *dev) | |||
149 | reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo)); | 147 | reg = lp3971_reg_read(lp3971, LP3971_LDO_VOL_CONTR_REG(ldo)); |
150 | val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK; | 148 | val = (reg >> LDO_VOL_CONTR_SHIFT(ldo)) & LDO_VOL_CONTR_MASK; |
151 | 149 | ||
152 | return dev->desc->volt_table[val]; | 150 | return val; |
153 | } | 151 | } |
154 | 152 | ||
155 | static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, | 153 | static int lp3971_ldo_set_voltage_sel(struct regulator_dev *dev, |
@@ -168,7 +166,7 @@ static struct regulator_ops lp3971_ldo_ops = { | |||
168 | .is_enabled = lp3971_ldo_is_enabled, | 166 | .is_enabled = lp3971_ldo_is_enabled, |
169 | .enable = lp3971_ldo_enable, | 167 | .enable = lp3971_ldo_enable, |
170 | .disable = lp3971_ldo_disable, | 168 | .disable = lp3971_ldo_disable, |
171 | .get_voltage = lp3971_ldo_get_voltage, | 169 | .get_voltage_sel = lp3971_ldo_get_voltage_sel, |
172 | .set_voltage_sel = lp3971_ldo_set_voltage_sel, | 170 | .set_voltage_sel = lp3971_ldo_set_voltage_sel, |
173 | }; | 171 | }; |
174 | 172 | ||
@@ -201,24 +199,16 @@ static int lp3971_dcdc_disable(struct regulator_dev *dev) | |||
201 | return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0); | 199 | return lp3971_set_bits(lp3971, LP3971_BUCK_VOL_ENABLE_REG, mask, 0); |
202 | } | 200 | } |
203 | 201 | ||
204 | static int lp3971_dcdc_get_voltage(struct regulator_dev *dev) | 202 | static int lp3971_dcdc_get_voltage_sel(struct regulator_dev *dev) |
205 | { | 203 | { |
206 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); | 204 | struct lp3971 *lp3971 = rdev_get_drvdata(dev); |
207 | int buck = rdev_get_id(dev) - LP3971_DCDC1; | 205 | int buck = rdev_get_id(dev) - LP3971_DCDC1; |
208 | u16 reg; | 206 | u16 reg; |
209 | int val; | ||
210 | 207 | ||
211 | reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck)); | 208 | reg = lp3971_reg_read(lp3971, LP3971_BUCK_TARGET_VOL1_REG(buck)); |
212 | reg &= BUCK_TARGET_VOL_MASK; | 209 | reg &= BUCK_TARGET_VOL_MASK; |
213 | 210 | ||
214 | if (reg <= BUCK_TARGET_VOL_MAX_IDX) | 211 | return reg; |
215 | val = buck_voltage_map[reg]; | ||
216 | else { | ||
217 | val = 0; | ||
218 | dev_warn(&dev->dev, "chip reported incorrect voltage value.\n"); | ||
219 | } | ||
220 | |||
221 | return val; | ||
222 | } | 212 | } |
223 | 213 | ||
224 | static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, | 214 | static int lp3971_dcdc_set_voltage_sel(struct regulator_dev *dev, |
@@ -249,7 +239,7 @@ static struct regulator_ops lp3971_dcdc_ops = { | |||
249 | .is_enabled = lp3971_dcdc_is_enabled, | 239 | .is_enabled = lp3971_dcdc_is_enabled, |
250 | .enable = lp3971_dcdc_enable, | 240 | .enable = lp3971_dcdc_enable, |
251 | .disable = lp3971_dcdc_disable, | 241 | .disable = lp3971_dcdc_disable, |
252 | .get_voltage = lp3971_dcdc_get_voltage, | 242 | .get_voltage_sel = lp3971_dcdc_get_voltage_sel, |
253 | .set_voltage_sel = lp3971_dcdc_set_voltage_sel, | 243 | .set_voltage_sel = lp3971_dcdc_set_voltage_sel, |
254 | }; | 244 | }; |
255 | 245 | ||
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c index 69c42c318b87..0baabcfb578a 100644 --- a/drivers/regulator/lp3972.c +++ b/drivers/regulator/lp3972.c | |||
@@ -165,8 +165,6 @@ static const int buck_base_addr[] = { | |||
165 | #define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x]) | 165 | #define LP3972_BUCK_VOL_ENABLE_REG(x) (buck_vol_enable_addr[x]) |
166 | #define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x]) | 166 | #define LP3972_BUCK_VOL1_REG(x) (buck_base_addr[x]) |
167 | #define LP3972_BUCK_VOL_MASK 0x1f | 167 | #define LP3972_BUCK_VOL_MASK 0x1f |
168 | #define LP3972_BUCK_VOL_MIN_IDX(x) ((x) ? 0x01 : 0x00) | ||
169 | #define LP3972_BUCK_VOL_MAX_IDX(x) ((x) ? 0x19 : 0x1f) | ||
170 | 168 | ||
171 | static int lp3972_i2c_read(struct i2c_client *i2c, char reg, int count, | 169 | static int lp3972_i2c_read(struct i2c_client *i2c, char reg, int count, |
172 | u16 *dest) | 170 | u16 *dest) |
@@ -257,7 +255,7 @@ static int lp3972_ldo_disable(struct regulator_dev *dev) | |||
257 | mask, 0); | 255 | mask, 0); |
258 | } | 256 | } |
259 | 257 | ||
260 | static int lp3972_ldo_get_voltage(struct regulator_dev *dev) | 258 | static int lp3972_ldo_get_voltage_sel(struct regulator_dev *dev) |
261 | { | 259 | { |
262 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); | 260 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); |
263 | int ldo = rdev_get_id(dev) - LP3972_LDO1; | 261 | int ldo = rdev_get_id(dev) - LP3972_LDO1; |
@@ -267,7 +265,7 @@ static int lp3972_ldo_get_voltage(struct regulator_dev *dev) | |||
267 | reg = lp3972_reg_read(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo)); | 265 | reg = lp3972_reg_read(lp3972, LP3972_LDO_VOL_CONTR_REG(ldo)); |
268 | val = (reg >> LP3972_LDO_VOL_CONTR_SHIFT(ldo)) & mask; | 266 | val = (reg >> LP3972_LDO_VOL_CONTR_SHIFT(ldo)) & mask; |
269 | 267 | ||
270 | return dev->desc->volt_table[val]; | 268 | return val; |
271 | } | 269 | } |
272 | 270 | ||
273 | static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, | 271 | static int lp3972_ldo_set_voltage_sel(struct regulator_dev *dev, |
@@ -314,7 +312,7 @@ static struct regulator_ops lp3972_ldo_ops = { | |||
314 | .is_enabled = lp3972_ldo_is_enabled, | 312 | .is_enabled = lp3972_ldo_is_enabled, |
315 | .enable = lp3972_ldo_enable, | 313 | .enable = lp3972_ldo_enable, |
316 | .disable = lp3972_ldo_disable, | 314 | .disable = lp3972_ldo_disable, |
317 | .get_voltage = lp3972_ldo_get_voltage, | 315 | .get_voltage_sel = lp3972_ldo_get_voltage_sel, |
318 | .set_voltage_sel = lp3972_ldo_set_voltage_sel, | 316 | .set_voltage_sel = lp3972_ldo_set_voltage_sel, |
319 | }; | 317 | }; |
320 | 318 | ||
@@ -353,24 +351,16 @@ static int lp3972_dcdc_disable(struct regulator_dev *dev) | |||
353 | return val; | 351 | return val; |
354 | } | 352 | } |
355 | 353 | ||
356 | static int lp3972_dcdc_get_voltage(struct regulator_dev *dev) | 354 | static int lp3972_dcdc_get_voltage_sel(struct regulator_dev *dev) |
357 | { | 355 | { |
358 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); | 356 | struct lp3972 *lp3972 = rdev_get_drvdata(dev); |
359 | int buck = rdev_get_id(dev) - LP3972_DCDC1; | 357 | int buck = rdev_get_id(dev) - LP3972_DCDC1; |
360 | u16 reg; | 358 | u16 reg; |
361 | int val; | ||
362 | 359 | ||
363 | reg = lp3972_reg_read(lp3972, LP3972_BUCK_VOL1_REG(buck)); | 360 | reg = lp3972_reg_read(lp3972, LP3972_BUCK_VOL1_REG(buck)); |
364 | reg &= LP3972_BUCK_VOL_MASK; | 361 | reg &= LP3972_BUCK_VOL_MASK; |
365 | if (reg <= LP3972_BUCK_VOL_MAX_IDX(buck)) | ||
366 | val = dev->desc->volt_table[reg]; | ||
367 | else { | ||
368 | val = 0; | ||
369 | dev_warn(&dev->dev, "chip reported incorrect voltage value." | ||
370 | " reg = %d\n", reg); | ||
371 | } | ||
372 | 362 | ||
373 | return val; | 363 | return reg; |
374 | } | 364 | } |
375 | 365 | ||
376 | static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev, | 366 | static int lp3972_dcdc_set_voltage_sel(struct regulator_dev *dev, |
@@ -402,7 +392,7 @@ static struct regulator_ops lp3972_dcdc_ops = { | |||
402 | .is_enabled = lp3972_dcdc_is_enabled, | 392 | .is_enabled = lp3972_dcdc_is_enabled, |
403 | .enable = lp3972_dcdc_enable, | 393 | .enable = lp3972_dcdc_enable, |
404 | .disable = lp3972_dcdc_disable, | 394 | .disable = lp3972_dcdc_disable, |
405 | .get_voltage = lp3972_dcdc_get_voltage, | 395 | .get_voltage_sel = lp3972_dcdc_get_voltage_sel, |
406 | .set_voltage_sel = lp3972_dcdc_set_voltage_sel, | 396 | .set_voltage_sel = lp3972_dcdc_set_voltage_sel, |
407 | }; | 397 | }; |
408 | 398 | ||
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c index 9289ead715ca..8e3c7ae0047f 100644 --- a/drivers/regulator/lp872x.c +++ b/drivers/regulator/lp872x.c | |||
@@ -181,20 +181,6 @@ static inline int lp872x_update_bits(struct lp872x *lp, u8 addr, | |||
181 | return regmap_update_bits(lp->regmap, addr, mask, data); | 181 | return regmap_update_bits(lp->regmap, addr, mask, data); |
182 | } | 182 | } |
183 | 183 | ||
184 | static int _rdev_to_offset(struct regulator_dev *rdev) | ||
185 | { | ||
186 | enum lp872x_regulator_id id = rdev_get_id(rdev); | ||
187 | |||
188 | switch (id) { | ||
189 | case LP8720_ID_LDO1 ... LP8720_ID_BUCK: | ||
190 | return id; | ||
191 | case LP8725_ID_LDO1 ... LP8725_ID_BUCK2: | ||
192 | return id - LP8725_ID_BASE; | ||
193 | default: | ||
194 | return -EINVAL; | ||
195 | } | ||
196 | } | ||
197 | |||
198 | static int lp872x_get_timestep_usec(struct lp872x *lp) | 184 | static int lp872x_get_timestep_usec(struct lp872x *lp) |
199 | { | 185 | { |
200 | enum lp872x_id chip = lp->chipid; | 186 | enum lp872x_id chip = lp->chipid; |
@@ -234,28 +220,20 @@ static int lp872x_get_timestep_usec(struct lp872x *lp) | |||
234 | static int lp872x_regulator_enable_time(struct regulator_dev *rdev) | 220 | static int lp872x_regulator_enable_time(struct regulator_dev *rdev) |
235 | { | 221 | { |
236 | struct lp872x *lp = rdev_get_drvdata(rdev); | 222 | struct lp872x *lp = rdev_get_drvdata(rdev); |
237 | enum lp872x_regulator_id regulator = rdev_get_id(rdev); | 223 | enum lp872x_regulator_id rid = rdev_get_id(rdev); |
238 | int time_step_us = lp872x_get_timestep_usec(lp); | 224 | int time_step_us = lp872x_get_timestep_usec(lp); |
239 | int ret, offset; | 225 | int ret; |
240 | u8 addr, val; | 226 | u8 addr, val; |
241 | 227 | ||
242 | if (time_step_us < 0) | 228 | if (time_step_us < 0) |
243 | return -EINVAL; | 229 | return -EINVAL; |
244 | 230 | ||
245 | switch (regulator) { | 231 | switch (rid) { |
246 | case LP8720_ID_LDO1 ... LP8720_ID_LDO5: | 232 | case LP8720_ID_LDO1 ... LP8720_ID_BUCK: |
247 | case LP8725_ID_LDO1 ... LP8725_ID_LILO2: | 233 | addr = LP872X_LDO1_VOUT + rid; |
248 | offset = _rdev_to_offset(rdev); | ||
249 | if (offset < 0) | ||
250 | return -EINVAL; | ||
251 | |||
252 | addr = LP872X_LDO1_VOUT + offset; | ||
253 | break; | ||
254 | case LP8720_ID_BUCK: | ||
255 | addr = LP8720_BUCK_VOUT1; | ||
256 | break; | 234 | break; |
257 | case LP8725_ID_BUCK1: | 235 | case LP8725_ID_LDO1 ... LP8725_ID_BUCK1: |
258 | addr = LP8725_BUCK1_VOUT1; | 236 | addr = LP872X_LDO1_VOUT + rid - LP8725_ID_BASE; |
259 | break; | 237 | break; |
260 | case LP8725_ID_BUCK2: | 238 | case LP8725_ID_BUCK2: |
261 | addr = LP8725_BUCK2_VOUT1; | 239 | addr = LP8725_BUCK2_VOUT1; |
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c new file mode 100644 index 000000000000..f0f6ea05065b --- /dev/null +++ b/drivers/regulator/lp8755.c | |||
@@ -0,0 +1,566 @@ | |||
1 | /* | ||
2 | * LP8755 High Performance Power Management Unit : System Interface Driver | ||
3 | * (based on rev. 0.26) | ||
4 | * Copyright 2012 Texas Instruments | ||
5 | * | ||
6 | * Author: Daniel(Geon Si) Jeong <daniel.jeong@ti.com> | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | ||
9 | * it under the terms of the GNU General Public License version 2 as | ||
10 | * published by the Free Software Foundation. | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/i2c.h> | ||
17 | #include <linux/err.h> | ||
18 | #include <linux/irq.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | #include <linux/gpio.h> | ||
21 | #include <linux/regmap.h> | ||
22 | #include <linux/delay.h> | ||
23 | #include <linux/uaccess.h> | ||
24 | #include <linux/regulator/driver.h> | ||
25 | #include <linux/regulator/machine.h> | ||
26 | #include <linux/platform_data/lp8755.h> | ||
27 | |||
28 | #define LP8755_REG_BUCK0 0x00 | ||
29 | #define LP8755_REG_BUCK1 0x03 | ||
30 | #define LP8755_REG_BUCK2 0x04 | ||
31 | #define LP8755_REG_BUCK3 0x01 | ||
32 | #define LP8755_REG_BUCK4 0x05 | ||
33 | #define LP8755_REG_BUCK5 0x02 | ||
34 | #define LP8755_REG_MAX 0xFF | ||
35 | |||
36 | #define LP8755_BUCK_EN_M BIT(7) | ||
37 | #define LP8755_BUCK_LINEAR_OUT_MAX 0x76 | ||
38 | #define LP8755_BUCK_VOUT_M 0x7F | ||
39 | |||
40 | struct lp8755_mphase { | ||
41 | int nreg; | ||
42 | int buck_num[LP8755_BUCK_MAX]; | ||
43 | }; | ||
44 | |||
45 | struct lp8755_chip { | ||
46 | struct device *dev; | ||
47 | struct regmap *regmap; | ||
48 | struct lp8755_platform_data *pdata; | ||
49 | |||
50 | int irq; | ||
51 | unsigned int irqmask; | ||
52 | |||
53 | int mphase; | ||
54 | struct regulator_dev *rdev[LP8755_BUCK_MAX]; | ||
55 | }; | ||
56 | |||
57 | /** | ||
58 | *lp8755_read : read a single register value from lp8755. | ||
59 | *@pchip : device to read from | ||
60 | *@reg : register to read from | ||
61 | *@val : pointer to store read value | ||
62 | */ | ||
63 | static int lp8755_read(struct lp8755_chip *pchip, unsigned int reg, | ||
64 | unsigned int *val) | ||
65 | { | ||
66 | return regmap_read(pchip->regmap, reg, val); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | *lp8755_write : write a single register value to lp8755. | ||
71 | *@pchip : device to write to | ||
72 | *@reg : register to write to | ||
73 | *@val : value to be written | ||
74 | */ | ||
75 | static int lp8755_write(struct lp8755_chip *pchip, unsigned int reg, | ||
76 | unsigned int val) | ||
77 | { | ||
78 | return regmap_write(pchip->regmap, reg, val); | ||
79 | } | ||
80 | |||
81 | /** | ||
82 | *lp8755_update_bits : set the values of bit fields in lp8755 register. | ||
83 | *@pchip : device to read from | ||
84 | *@reg : register to update | ||
85 | *@mask : bitmask to be changed | ||
86 | *@val : value for bitmask | ||
87 | */ | ||
88 | static int lp8755_update_bits(struct lp8755_chip *pchip, unsigned int reg, | ||
89 | unsigned int mask, unsigned int val) | ||
90 | { | ||
91 | return regmap_update_bits(pchip->regmap, reg, mask, val); | ||
92 | } | ||
93 | |||
94 | static int lp8755_buck_enable_time(struct regulator_dev *rdev) | ||
95 | { | ||
96 | int ret; | ||
97 | unsigned int regval; | ||
98 | enum lp8755_bucks id = rdev_get_id(rdev); | ||
99 | struct lp8755_chip *pchip = rdev_get_drvdata(rdev); | ||
100 | |||
101 | ret = lp8755_read(pchip, 0x12 + id, ®val); | ||
102 | if (ret < 0) { | ||
103 | dev_err(pchip->dev, "i2c acceess error %s\n", __func__); | ||
104 | return ret; | ||
105 | } | ||
106 | return (regval & 0xff) * 100; | ||
107 | } | ||
108 | |||
109 | static int lp8755_buck_set_mode(struct regulator_dev *rdev, unsigned int mode) | ||
110 | { | ||
111 | int ret; | ||
112 | unsigned int regbval = 0x0; | ||
113 | enum lp8755_bucks id = rdev_get_id(rdev); | ||
114 | struct lp8755_chip *pchip = rdev_get_drvdata(rdev); | ||
115 | |||
116 | switch (mode) { | ||
117 | case REGULATOR_MODE_FAST: | ||
118 | /* forced pwm mode */ | ||
119 | regbval = (0x01 << id); | ||
120 | break; | ||
121 | case REGULATOR_MODE_NORMAL: | ||
122 | /* enable automatic pwm/pfm mode */ | ||
123 | ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x00); | ||
124 | if (ret < 0) | ||
125 | goto err_i2c; | ||
126 | break; | ||
127 | case REGULATOR_MODE_IDLE: | ||
128 | /* enable automatic pwm/pfm/lppfm mode */ | ||
129 | ret = lp8755_update_bits(pchip, 0x08 + id, 0x20, 0x20); | ||
130 | if (ret < 0) | ||
131 | goto err_i2c; | ||
132 | |||
133 | ret = lp8755_update_bits(pchip, 0x10, 0x01, 0x01); | ||
134 | if (ret < 0) | ||
135 | goto err_i2c; | ||
136 | break; | ||
137 | default: | ||
138 | dev_err(pchip->dev, "Not supported buck mode %s\n", __func__); | ||
139 | /* forced pwm mode */ | ||
140 | regbval = (0x01 << id); | ||
141 | } | ||
142 | |||
143 | ret = lp8755_update_bits(pchip, 0x06, 0x01 << id, regbval); | ||
144 | if (ret < 0) | ||
145 | goto err_i2c; | ||
146 | return ret; | ||
147 | err_i2c: | ||
148 | dev_err(pchip->dev, "i2c acceess error %s\n", __func__); | ||
149 | return ret; | ||
150 | } | ||
151 | |||
152 | static unsigned int lp8755_buck_get_mode(struct regulator_dev *rdev) | ||
153 | { | ||
154 | int ret; | ||
155 | unsigned int regval; | ||
156 | enum lp8755_bucks id = rdev_get_id(rdev); | ||
157 | struct lp8755_chip *pchip = rdev_get_drvdata(rdev); | ||
158 | |||
159 | ret = lp8755_read(pchip, 0x06, ®val); | ||
160 | if (ret < 0) | ||
161 | goto err_i2c; | ||
162 | |||
163 | /* mode fast means forced pwm mode */ | ||
164 | if (regval & (0x01 << id)) | ||
165 | return REGULATOR_MODE_FAST; | ||
166 | |||
167 | ret = lp8755_read(pchip, 0x08 + id, ®val); | ||
168 | if (ret < 0) | ||
169 | goto err_i2c; | ||
170 | |||
171 | /* mode idle means automatic pwm/pfm/lppfm mode */ | ||
172 | if (regval & 0x20) | ||
173 | return REGULATOR_MODE_IDLE; | ||
174 | |||
175 | /* mode normal means automatic pwm/pfm mode */ | ||
176 | return REGULATOR_MODE_NORMAL; | ||
177 | |||
178 | err_i2c: | ||
179 | dev_err(pchip->dev, "i2c acceess error %s\n", __func__); | ||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int lp8755_buck_set_ramp(struct regulator_dev *rdev, int ramp) | ||
184 | { | ||
185 | int ret; | ||
186 | unsigned int regval = 0x00; | ||
187 | enum lp8755_bucks id = rdev_get_id(rdev); | ||
188 | struct lp8755_chip *pchip = rdev_get_drvdata(rdev); | ||
189 | |||
190 | /* uV/us */ | ||
191 | switch (ramp) { | ||
192 | case 0 ... 230: | ||
193 | regval = 0x07; | ||
194 | break; | ||
195 | case 231 ... 470: | ||
196 | regval = 0x06; | ||
197 | break; | ||
198 | case 471 ... 940: | ||
199 | regval = 0x05; | ||
200 | break; | ||
201 | case 941 ... 1900: | ||
202 | regval = 0x04; | ||
203 | break; | ||
204 | case 1901 ... 3800: | ||
205 | regval = 0x03; | ||
206 | break; | ||
207 | case 3801 ... 7500: | ||
208 | regval = 0x02; | ||
209 | break; | ||
210 | case 7501 ... 15000: | ||
211 | regval = 0x01; | ||
212 | break; | ||
213 | case 15001 ... 30000: | ||
214 | regval = 0x00; | ||
215 | break; | ||
216 | default: | ||
217 | dev_err(pchip->dev, | ||
218 | "Not supported ramp value %d %s\n", ramp, __func__); | ||
219 | return -EINVAL; | ||
220 | } | ||
221 | |||
222 | ret = lp8755_update_bits(pchip, 0x07 + id, 0x07, regval); | ||
223 | if (ret < 0) | ||
224 | goto err_i2c; | ||
225 | return ret; | ||
226 | err_i2c: | ||
227 | dev_err(pchip->dev, "i2c acceess error %s\n", __func__); | ||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static struct regulator_ops lp8755_buck_ops = { | ||
232 | .list_voltage = regulator_list_voltage_linear, | ||
233 | .set_voltage_sel = regulator_set_voltage_sel_regmap, | ||
234 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | ||
235 | .enable = regulator_enable_regmap, | ||
236 | .disable = regulator_disable_regmap, | ||
237 | .is_enabled = regulator_is_enabled_regmap, | ||
238 | .enable_time = lp8755_buck_enable_time, | ||
239 | .set_mode = lp8755_buck_set_mode, | ||
240 | .get_mode = lp8755_buck_get_mode, | ||
241 | .set_ramp_delay = lp8755_buck_set_ramp, | ||
242 | }; | ||
243 | |||
244 | #define lp8755_rail(_id) "lp8755_buck"#_id | ||
245 | #define lp8755_buck_init(_id)\ | ||
246 | {\ | ||
247 | .constraints = {\ | ||
248 | .name = lp8755_rail(_id),\ | ||
249 | .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,\ | ||
250 | .min_uV = 500000,\ | ||
251 | .max_uV = 1675000,\ | ||
252 | },\ | ||
253 | } | ||
254 | |||
255 | static struct regulator_init_data lp8755_reg_default[LP8755_BUCK_MAX] = { | ||
256 | [LP8755_BUCK0] = lp8755_buck_init(0), | ||
257 | [LP8755_BUCK1] = lp8755_buck_init(1), | ||
258 | [LP8755_BUCK2] = lp8755_buck_init(2), | ||
259 | [LP8755_BUCK3] = lp8755_buck_init(3), | ||
260 | [LP8755_BUCK4] = lp8755_buck_init(4), | ||
261 | [LP8755_BUCK5] = lp8755_buck_init(5), | ||
262 | }; | ||
263 | |||
264 | static const struct lp8755_mphase mphase_buck[MPHASE_CONF_MAX] = { | ||
265 | { 3, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK5 } }, | ||
266 | { 6, { LP8755_BUCK0, LP8755_BUCK1, LP8755_BUCK2, LP8755_BUCK3, | ||
267 | LP8755_BUCK4, LP8755_BUCK5 } }, | ||
268 | { 5, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK4, | ||
269 | LP8755_BUCK5} }, | ||
270 | { 4, { LP8755_BUCK0, LP8755_BUCK3, LP8755_BUCK4, LP8755_BUCK5} }, | ||
271 | { 3, { LP8755_BUCK0, LP8755_BUCK4, LP8755_BUCK5} }, | ||
272 | { 2, { LP8755_BUCK0, LP8755_BUCK5} }, | ||
273 | { 1, { LP8755_BUCK0} }, | ||
274 | { 2, { LP8755_BUCK0, LP8755_BUCK3} }, | ||
275 | { 4, { LP8755_BUCK0, LP8755_BUCK2, LP8755_BUCK3, LP8755_BUCK5} }, | ||
276 | }; | ||
277 | |||
278 | static int lp8755_init_data(struct lp8755_chip *pchip) | ||
279 | { | ||
280 | unsigned int regval; | ||
281 | int ret, icnt, buck_num; | ||
282 | struct lp8755_platform_data *pdata = pchip->pdata; | ||
283 | |||
284 | /* read back muti-phase configuration */ | ||
285 | ret = lp8755_read(pchip, 0x3D, ®val); | ||
286 | if (ret < 0) | ||
287 | goto out_i2c_error; | ||
288 | pchip->mphase = regval & 0x0F; | ||
289 | |||
290 | /* set default data based on multi-phase config */ | ||
291 | for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { | ||
292 | buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; | ||
293 | pdata->buck_data[buck_num] = &lp8755_reg_default[buck_num]; | ||
294 | } | ||
295 | return ret; | ||
296 | |||
297 | out_i2c_error: | ||
298 | dev_err(pchip->dev, "i2c acceess error %s\n", __func__); | ||
299 | return ret; | ||
300 | } | ||
301 | |||
302 | #define lp8755_buck_desc(_id)\ | ||
303 | {\ | ||
304 | .name = lp8755_rail(_id),\ | ||
305 | .id = LP8755_BUCK##_id,\ | ||
306 | .ops = &lp8755_buck_ops,\ | ||
307 | .n_voltages = LP8755_BUCK_LINEAR_OUT_MAX+1,\ | ||
308 | .uV_step = 10000,\ | ||
309 | .min_uV = 500000,\ | ||
310 | .type = REGULATOR_VOLTAGE,\ | ||
311 | .owner = THIS_MODULE,\ | ||
312 | .enable_reg = LP8755_REG_BUCK##_id,\ | ||
313 | .enable_mask = LP8755_BUCK_EN_M,\ | ||
314 | .vsel_reg = LP8755_REG_BUCK##_id,\ | ||
315 | .vsel_mask = LP8755_BUCK_VOUT_M,\ | ||
316 | } | ||
317 | |||
318 | static struct regulator_desc lp8755_regulators[] = { | ||
319 | lp8755_buck_desc(0), | ||
320 | lp8755_buck_desc(1), | ||
321 | lp8755_buck_desc(2), | ||
322 | lp8755_buck_desc(3), | ||
323 | lp8755_buck_desc(4), | ||
324 | lp8755_buck_desc(5), | ||
325 | }; | ||
326 | |||
327 | static int lp8755_regulator_init(struct lp8755_chip *pchip) | ||
328 | { | ||
329 | int ret, icnt, buck_num; | ||
330 | struct lp8755_platform_data *pdata = pchip->pdata; | ||
331 | struct regulator_config rconfig = { }; | ||
332 | |||
333 | rconfig.regmap = pchip->regmap; | ||
334 | rconfig.dev = pchip->dev; | ||
335 | rconfig.driver_data = pchip; | ||
336 | |||
337 | for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) { | ||
338 | buck_num = mphase_buck[pchip->mphase].buck_num[icnt]; | ||
339 | rconfig.init_data = pdata->buck_data[buck_num]; | ||
340 | rconfig.of_node = pchip->dev->of_node; | ||
341 | pchip->rdev[buck_num] = | ||
342 | regulator_register(&lp8755_regulators[buck_num], &rconfig); | ||
343 | if (IS_ERR(pchip->rdev[buck_num])) { | ||
344 | ret = PTR_ERR(pchip->rdev[buck_num]); | ||
345 | pchip->rdev[buck_num] = NULL; | ||
346 | dev_err(pchip->dev, "regulator init failed: buck %d\n", | ||
347 | buck_num); | ||
348 | goto err_buck; | ||
349 | } | ||
350 | } | ||
351 | |||
352 | return 0; | ||
353 | |||
354 | err_buck: | ||
355 | for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) | ||
356 | regulator_unregister(pchip->rdev[icnt]); | ||
357 | return ret; | ||
358 | } | ||
359 | |||
360 | static irqreturn_t lp8755_irq_handler(int irq, void *data) | ||
361 | { | ||
362 | int ret, icnt; | ||
363 | unsigned int flag0, flag1; | ||
364 | struct lp8755_chip *pchip = data; | ||
365 | |||
366 | /* read flag0 register */ | ||
367 | ret = lp8755_read(pchip, 0x0D, &flag0); | ||
368 | if (ret < 0) | ||
369 | goto err_i2c; | ||
370 | /* clear flag register to pull up int. pin */ | ||
371 | ret = lp8755_write(pchip, 0x0D, 0x00); | ||
372 | if (ret < 0) | ||
373 | goto err_i2c; | ||
374 | |||
375 | /* sent power fault detection event to specific regulator */ | ||
376 | for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) | ||
377 | if ((flag0 & (0x4 << icnt)) | ||
378 | && (pchip->irqmask & (0x04 << icnt)) | ||
379 | && (pchip->rdev[icnt] != NULL)) | ||
380 | regulator_notifier_call_chain(pchip->rdev[icnt], | ||
381 | LP8755_EVENT_PWR_FAULT, | ||
382 | NULL); | ||
383 | |||
384 | /* read flag1 register */ | ||
385 | ret = lp8755_read(pchip, 0x0E, &flag1); | ||
386 | if (ret < 0) | ||
387 | goto err_i2c; | ||
388 | /* clear flag register to pull up int. pin */ | ||
389 | ret = lp8755_write(pchip, 0x0E, 0x00); | ||
390 | if (ret < 0) | ||
391 | goto err_i2c; | ||
392 | |||
393 | /* send OCP event to all regualtor devices */ | ||
394 | if ((flag1 & 0x01) && (pchip->irqmask & 0x01)) | ||
395 | for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) | ||
396 | if (pchip->rdev[icnt] != NULL) | ||
397 | regulator_notifier_call_chain(pchip->rdev[icnt], | ||
398 | LP8755_EVENT_OCP, | ||
399 | NULL); | ||
400 | |||
401 | /* send OVP event to all regualtor devices */ | ||
402 | if ((flag1 & 0x02) && (pchip->irqmask & 0x02)) | ||
403 | for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) | ||
404 | if (pchip->rdev[icnt] != NULL) | ||
405 | regulator_notifier_call_chain(pchip->rdev[icnt], | ||
406 | LP8755_EVENT_OVP, | ||
407 | NULL); | ||
408 | return IRQ_HANDLED; | ||
409 | |||
410 | err_i2c: | ||
411 | dev_err(pchip->dev, "i2c acceess error %s\n", __func__); | ||
412 | return IRQ_NONE; | ||
413 | } | ||
414 | |||
415 | static int lp8755_int_config(struct lp8755_chip *pchip) | ||
416 | { | ||
417 | int ret; | ||
418 | unsigned int regval; | ||
419 | |||
420 | if (pchip->irq == 0) { | ||
421 | dev_warn(pchip->dev, "not use interrupt : %s\n", __func__); | ||
422 | return 0; | ||
423 | } | ||
424 | |||
425 | ret = lp8755_read(pchip, 0x0F, ®val); | ||
426 | if (ret < 0) | ||
427 | goto err_i2c; | ||
428 | pchip->irqmask = regval; | ||
429 | ret = request_threaded_irq(pchip->irq, NULL, lp8755_irq_handler, | ||
430 | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, | ||
431 | "lp8755-irq", pchip); | ||
432 | if (ret) | ||
433 | return ret; | ||
434 | |||
435 | return ret; | ||
436 | |||
437 | err_i2c: | ||
438 | dev_err(pchip->dev, "i2c acceess error %s\n", __func__); | ||
439 | return ret; | ||
440 | } | ||
441 | |||
442 | static const struct regmap_config lp8755_regmap = { | ||
443 | .reg_bits = 8, | ||
444 | .val_bits = 8, | ||
445 | .max_register = LP8755_REG_MAX, | ||
446 | }; | ||
447 | |||
448 | static int lp8755_probe(struct i2c_client *client, | ||
449 | const struct i2c_device_id *id) | ||
450 | { | ||
451 | int ret, icnt; | ||
452 | struct lp8755_chip *pchip; | ||
453 | struct lp8755_platform_data *pdata = client->dev.platform_data; | ||
454 | |||
455 | if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) { | ||
456 | dev_err(&client->dev, "i2c functionality check fail.\n"); | ||
457 | return -EOPNOTSUPP; | ||
458 | } | ||
459 | |||
460 | pchip = devm_kzalloc(&client->dev, | ||
461 | sizeof(struct lp8755_chip), GFP_KERNEL); | ||
462 | if (!pchip) | ||
463 | return -ENOMEM; | ||
464 | |||
465 | pchip->dev = &client->dev; | ||
466 | pchip->regmap = devm_regmap_init_i2c(client, &lp8755_regmap); | ||
467 | if (IS_ERR(pchip->regmap)) { | ||
468 | ret = PTR_ERR(pchip->regmap); | ||
469 | dev_err(&client->dev, "fail to allocate regmap %d\n", ret); | ||
470 | return ret; | ||
471 | } | ||
472 | i2c_set_clientdata(client, pchip); | ||
473 | |||
474 | if (pdata != NULL) { | ||
475 | pchip->pdata = pdata; | ||
476 | pchip->mphase = pdata->mphase; | ||
477 | } else { | ||
478 | pchip->pdata = devm_kzalloc(pchip->dev, | ||
479 | sizeof(struct lp8755_platform_data), | ||
480 | GFP_KERNEL); | ||
481 | if (!pchip->pdata) | ||
482 | return -ENOMEM; | ||
483 | ret = lp8755_init_data(pchip); | ||
484 | if (ret < 0) { | ||
485 | dev_err(&client->dev, "fail to initialize chip\n"); | ||
486 | return ret; | ||
487 | } | ||
488 | } | ||
489 | |||
490 | ret = lp8755_regulator_init(pchip); | ||
491 | if (ret < 0) { | ||
492 | dev_err(&client->dev, "fail to initialize regulators\n"); | ||
493 | goto err_regulator; | ||
494 | } | ||
495 | |||
496 | pchip->irq = client->irq; | ||
497 | ret = lp8755_int_config(pchip); | ||
498 | if (ret < 0) { | ||
499 | dev_err(&client->dev, "fail to irq config\n"); | ||
500 | goto err_irq; | ||
501 | } | ||
502 | |||
503 | return ret; | ||
504 | |||
505 | err_irq: | ||
506 | for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) | ||
507 | regulator_unregister(pchip->rdev[icnt]); | ||
508 | |||
509 | err_regulator: | ||
510 | /* output disable */ | ||
511 | for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) | ||
512 | lp8755_write(pchip, icnt, 0x00); | ||
513 | |||
514 | return ret; | ||
515 | } | ||
516 | |||
517 | static int lp8755_remove(struct i2c_client *client) | ||
518 | { | ||
519 | int icnt; | ||
520 | struct lp8755_chip *pchip = i2c_get_clientdata(client); | ||
521 | |||
522 | for (icnt = 0; icnt < mphase_buck[pchip->mphase].nreg; icnt++) | ||
523 | regulator_unregister(pchip->rdev[icnt]); | ||
524 | |||
525 | for (icnt = 0; icnt < LP8755_BUCK_MAX; icnt++) | ||
526 | lp8755_write(pchip, icnt, 0x00); | ||
527 | |||
528 | if (pchip->irq != 0) | ||
529 | free_irq(pchip->irq, pchip); | ||
530 | |||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static const struct i2c_device_id lp8755_id[] = { | ||
535 | {LP8755_NAME, 0}, | ||
536 | {} | ||
537 | }; | ||
538 | |||
539 | MODULE_DEVICE_TABLE(i2c, lp8755_id); | ||
540 | |||
541 | static struct i2c_driver lp8755_i2c_driver = { | ||
542 | .driver = { | ||
543 | .name = LP8755_NAME, | ||
544 | }, | ||
545 | .probe = lp8755_probe, | ||
546 | .remove = lp8755_remove, | ||
547 | .id_table = lp8755_id, | ||
548 | }; | ||
549 | |||
550 | static int __init lp8755_init(void) | ||
551 | { | ||
552 | return i2c_add_driver(&lp8755_i2c_driver); | ||
553 | } | ||
554 | |||
555 | subsys_initcall(lp8755_init); | ||
556 | |||
557 | static void __exit lp8755_exit(void) | ||
558 | { | ||
559 | i2c_del_driver(&lp8755_i2c_driver); | ||
560 | } | ||
561 | |||
562 | module_exit(lp8755_exit); | ||
563 | |||
564 | MODULE_DESCRIPTION("Texas Instruments lp8755 driver"); | ||
565 | MODULE_AUTHOR("Daniel Jeong <daniel.jeong@ti.com>"); | ||
566 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c index aef3f2b0c5ea..97891a7ea7b2 100644 --- a/drivers/regulator/lp8788-buck.c +++ b/drivers/regulator/lp8788-buck.c | |||
@@ -103,16 +103,6 @@ static const int lp8788_buck_vtbl[] = { | |||
103 | 1950000, 2000000, | 103 | 1950000, 2000000, |
104 | }; | 104 | }; |
105 | 105 | ||
106 | static const u8 buck1_vout_addr[] = { | ||
107 | LP8788_BUCK1_VOUT0, LP8788_BUCK1_VOUT1, | ||
108 | LP8788_BUCK1_VOUT2, LP8788_BUCK1_VOUT3, | ||
109 | }; | ||
110 | |||
111 | static const u8 buck2_vout_addr[] = { | ||
112 | LP8788_BUCK2_VOUT0, LP8788_BUCK2_VOUT1, | ||
113 | LP8788_BUCK2_VOUT2, LP8788_BUCK2_VOUT3, | ||
114 | }; | ||
115 | |||
116 | static void lp8788_buck1_set_dvs(struct lp8788_buck *buck) | 106 | static void lp8788_buck1_set_dvs(struct lp8788_buck *buck) |
117 | { | 107 | { |
118 | struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs; | 108 | struct lp8788_buck1_dvs *dvs = (struct lp8788_buck1_dvs *)buck->dvs; |
@@ -235,7 +225,7 @@ static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck, | |||
235 | lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); | 225 | lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); |
236 | idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S; | 226 | idx = (val & LP8788_BUCK1_DVS_M) >> LP8788_BUCK1_DVS_S; |
237 | } | 227 | } |
238 | addr = buck1_vout_addr[idx]; | 228 | addr = LP8788_BUCK1_VOUT0 + idx; |
239 | break; | 229 | break; |
240 | case BUCK2: | 230 | case BUCK2: |
241 | if (mode == EXTPIN) { | 231 | if (mode == EXTPIN) { |
@@ -258,7 +248,7 @@ static u8 lp8788_select_buck_vout_addr(struct lp8788_buck *buck, | |||
258 | lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); | 248 | lp8788_read_byte(buck->lp, LP8788_BUCK_DVS_SEL, &val); |
259 | idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S; | 249 | idx = (val & LP8788_BUCK2_DVS_M) >> LP8788_BUCK2_DVS_S; |
260 | } | 250 | } |
261 | addr = buck2_vout_addr[idx]; | 251 | addr = LP8788_BUCK2_VOUT0 + idx; |
262 | break; | 252 | break; |
263 | default: | 253 | default: |
264 | goto err; | 254 | goto err; |
@@ -429,7 +419,8 @@ static struct regulator_desc lp8788_buck_desc[] = { | |||
429 | }, | 419 | }, |
430 | }; | 420 | }; |
431 | 421 | ||
432 | static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, | 422 | static int lp8788_dvs_gpio_request(struct platform_device *pdev, |
423 | struct lp8788_buck *buck, | ||
433 | enum lp8788_buck_id id) | 424 | enum lp8788_buck_id id) |
434 | { | 425 | { |
435 | struct lp8788_platform_data *pdata = buck->lp->pdata; | 426 | struct lp8788_platform_data *pdata = buck->lp->pdata; |
@@ -440,7 +431,7 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, | |||
440 | switch (id) { | 431 | switch (id) { |
441 | case BUCK1: | 432 | case BUCK1: |
442 | gpio = pdata->buck1_dvs->gpio; | 433 | gpio = pdata->buck1_dvs->gpio; |
443 | ret = devm_gpio_request_one(buck->lp->dev, gpio, DVS_LOW, | 434 | ret = devm_gpio_request_one(&pdev->dev, gpio, DVS_LOW, |
444 | b1_name); | 435 | b1_name); |
445 | if (ret) | 436 | if (ret) |
446 | return ret; | 437 | return ret; |
@@ -448,9 +439,9 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, | |||
448 | buck->dvs = pdata->buck1_dvs; | 439 | buck->dvs = pdata->buck1_dvs; |
449 | break; | 440 | break; |
450 | case BUCK2: | 441 | case BUCK2: |
451 | for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) { | 442 | for (i = 0; i < LP8788_NUM_BUCK2_DVS; i++) { |
452 | gpio = pdata->buck2_dvs->gpio[i]; | 443 | gpio = pdata->buck2_dvs->gpio[i]; |
453 | ret = devm_gpio_request_one(buck->lp->dev, gpio, | 444 | ret = devm_gpio_request_one(&pdev->dev, gpio, |
454 | DVS_LOW, b2_name[i]); | 445 | DVS_LOW, b2_name[i]); |
455 | if (ret) | 446 | if (ret) |
456 | return ret; | 447 | return ret; |
@@ -464,7 +455,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck, | |||
464 | return 0; | 455 | return 0; |
465 | } | 456 | } |
466 | 457 | ||
467 | static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) | 458 | static int lp8788_init_dvs(struct platform_device *pdev, |
459 | struct lp8788_buck *buck, enum lp8788_buck_id id) | ||
468 | { | 460 | { |
469 | struct lp8788_platform_data *pdata = buck->lp->pdata; | 461 | struct lp8788_platform_data *pdata = buck->lp->pdata; |
470 | u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M }; | 462 | u8 mask[] = { LP8788_BUCK1_DVS_SEL_M, LP8788_BUCK2_DVS_SEL_M }; |
@@ -472,7 +464,7 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) | |||
472 | u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C }; | 464 | u8 default_dvs_mode[] = { LP8788_BUCK1_DVS_I2C, LP8788_BUCK2_DVS_I2C }; |
473 | 465 | ||
474 | /* no dvs for buck3, 4 */ | 466 | /* no dvs for buck3, 4 */ |
475 | if (id == BUCK3 || id == BUCK4) | 467 | if (id > BUCK2) |
476 | return 0; | 468 | return 0; |
477 | 469 | ||
478 | /* no dvs platform data, then dvs will be selected by I2C registers */ | 470 | /* no dvs platform data, then dvs will be selected by I2C registers */ |
@@ -483,7 +475,7 @@ static int lp8788_init_dvs(struct lp8788_buck *buck, enum lp8788_buck_id id) | |||
483 | (id == BUCK2 && !pdata->buck2_dvs)) | 475 | (id == BUCK2 && !pdata->buck2_dvs)) |
484 | goto set_default_dvs_mode; | 476 | goto set_default_dvs_mode; |
485 | 477 | ||
486 | if (lp8788_dvs_gpio_request(buck, id)) | 478 | if (lp8788_dvs_gpio_request(pdev, buck, id)) |
487 | goto set_default_dvs_mode; | 479 | goto set_default_dvs_mode; |
488 | 480 | ||
489 | return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], | 481 | return lp8788_update_bits(buck->lp, LP8788_BUCK_DVS_SEL, mask[id], |
@@ -503,17 +495,20 @@ static int lp8788_buck_probe(struct platform_device *pdev) | |||
503 | struct regulator_dev *rdev; | 495 | struct regulator_dev *rdev; |
504 | int ret; | 496 | int ret; |
505 | 497 | ||
506 | buck = devm_kzalloc(lp->dev, sizeof(struct lp8788_buck), GFP_KERNEL); | 498 | if (id >= LP8788_NUM_BUCKS) |
499 | return -EINVAL; | ||
500 | |||
501 | buck = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_buck), GFP_KERNEL); | ||
507 | if (!buck) | 502 | if (!buck) |
508 | return -ENOMEM; | 503 | return -ENOMEM; |
509 | 504 | ||
510 | buck->lp = lp; | 505 | buck->lp = lp; |
511 | 506 | ||
512 | ret = lp8788_init_dvs(buck, id); | 507 | ret = lp8788_init_dvs(pdev, buck, id); |
513 | if (ret) | 508 | if (ret) |
514 | return ret; | 509 | return ret; |
515 | 510 | ||
516 | cfg.dev = lp->dev; | 511 | cfg.dev = pdev->dev.parent; |
517 | cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL; | 512 | cfg.init_data = lp->pdata ? lp->pdata->buck_data[id] : NULL; |
518 | cfg.driver_data = buck; | 513 | cfg.driver_data = buck; |
519 | cfg.regmap = lp->regmap; | 514 | cfg.regmap = lp->regmap; |
@@ -521,7 +516,7 @@ static int lp8788_buck_probe(struct platform_device *pdev) | |||
521 | rdev = regulator_register(&lp8788_buck_desc[id], &cfg); | 516 | rdev = regulator_register(&lp8788_buck_desc[id], &cfg); |
522 | if (IS_ERR(rdev)) { | 517 | if (IS_ERR(rdev)) { |
523 | ret = PTR_ERR(rdev); | 518 | ret = PTR_ERR(rdev); |
524 | dev_err(lp->dev, "BUCK%d regulator register err = %d\n", | 519 | dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n", |
525 | id + 1, ret); | 520 | id + 1, ret); |
526 | return ret; | 521 | return ret; |
527 | } | 522 | } |
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c index 3792741708ce..cd5a14ad9263 100644 --- a/drivers/regulator/lp8788-ldo.c +++ b/drivers/regulator/lp8788-ldo.c | |||
@@ -88,11 +88,6 @@ | |||
88 | #define ENABLE GPIOF_OUT_INIT_HIGH | 88 | #define ENABLE GPIOF_OUT_INIT_HIGH |
89 | #define DISABLE GPIOF_OUT_INIT_LOW | 89 | #define DISABLE GPIOF_OUT_INIT_LOW |
90 | 90 | ||
91 | enum lp8788_enable_mode { | ||
92 | REGISTER, | ||
93 | EXTPIN, | ||
94 | }; | ||
95 | |||
96 | enum lp8788_ldo_id { | 91 | enum lp8788_ldo_id { |
97 | DLDO1, | 92 | DLDO1, |
98 | DLDO2, | 93 | DLDO2, |
@@ -189,114 +184,38 @@ static enum lp8788_ldo_id lp8788_aldo_id[] = { | |||
189 | ALDO10, | 184 | ALDO10, |
190 | }; | 185 | }; |
191 | 186 | ||
192 | /* DLDO 7, 9 and 11, ALDO 1 ~ 5 and 7 | ||
193 | : can be enabled either by external pin or by i2c register */ | ||
194 | static enum lp8788_enable_mode | ||
195 | lp8788_get_ldo_enable_mode(struct lp8788_ldo *ldo, enum lp8788_ldo_id id) | ||
196 | { | ||
197 | int ret; | ||
198 | u8 val, mask; | ||
199 | |||
200 | ret = lp8788_read_byte(ldo->lp, LP8788_EN_SEL, &val); | ||
201 | if (ret) | ||
202 | return ret; | ||
203 | |||
204 | switch (id) { | ||
205 | case DLDO7: | ||
206 | mask = LP8788_EN_SEL_DLDO7_M; | ||
207 | break; | ||
208 | case DLDO9: | ||
209 | case DLDO11: | ||
210 | mask = LP8788_EN_SEL_DLDO911_M; | ||
211 | break; | ||
212 | case ALDO1: | ||
213 | mask = LP8788_EN_SEL_ALDO1_M; | ||
214 | break; | ||
215 | case ALDO2 ... ALDO4: | ||
216 | mask = LP8788_EN_SEL_ALDO234_M; | ||
217 | break; | ||
218 | case ALDO5: | ||
219 | mask = LP8788_EN_SEL_ALDO5_M; | ||
220 | break; | ||
221 | case ALDO7: | ||
222 | mask = LP8788_EN_SEL_ALDO7_M; | ||
223 | break; | ||
224 | default: | ||
225 | return REGISTER; | ||
226 | } | ||
227 | |||
228 | return val & mask ? EXTPIN : REGISTER; | ||
229 | } | ||
230 | |||
231 | static int lp8788_ldo_ctrl_by_extern_pin(struct lp8788_ldo *ldo, int pinstate) | ||
232 | { | ||
233 | struct lp8788_ldo_enable_pin *pin = ldo->en_pin; | ||
234 | |||
235 | if (!pin) | ||
236 | return -EINVAL; | ||
237 | |||
238 | if (gpio_is_valid(pin->gpio)) | ||
239 | gpio_set_value(pin->gpio, pinstate); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static int lp8788_ldo_is_enabled_by_extern_pin(struct lp8788_ldo *ldo) | ||
245 | { | ||
246 | struct lp8788_ldo_enable_pin *pin = ldo->en_pin; | ||
247 | |||
248 | if (!pin) | ||
249 | return -EINVAL; | ||
250 | |||
251 | return gpio_get_value(pin->gpio) ? 1 : 0; | ||
252 | } | ||
253 | |||
254 | static int lp8788_ldo_enable(struct regulator_dev *rdev) | 187 | static int lp8788_ldo_enable(struct regulator_dev *rdev) |
255 | { | 188 | { |
256 | struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); | 189 | struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); |
257 | enum lp8788_ldo_id id = rdev_get_id(rdev); | ||
258 | enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); | ||
259 | 190 | ||
260 | switch (mode) { | 191 | if (ldo->en_pin) { |
261 | case EXTPIN: | 192 | gpio_set_value(ldo->en_pin->gpio, ENABLE); |
262 | return lp8788_ldo_ctrl_by_extern_pin(ldo, ENABLE); | 193 | return 0; |
263 | case REGISTER: | 194 | } else { |
264 | return regulator_enable_regmap(rdev); | 195 | return regulator_enable_regmap(rdev); |
265 | default: | ||
266 | return -EINVAL; | ||
267 | } | 196 | } |
268 | } | 197 | } |
269 | 198 | ||
270 | static int lp8788_ldo_disable(struct regulator_dev *rdev) | 199 | static int lp8788_ldo_disable(struct regulator_dev *rdev) |
271 | { | 200 | { |
272 | struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); | 201 | struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); |
273 | enum lp8788_ldo_id id = rdev_get_id(rdev); | ||
274 | enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); | ||
275 | 202 | ||
276 | switch (mode) { | 203 | if (ldo->en_pin) { |
277 | case EXTPIN: | 204 | gpio_set_value(ldo->en_pin->gpio, DISABLE); |
278 | return lp8788_ldo_ctrl_by_extern_pin(ldo, DISABLE); | 205 | return 0; |
279 | case REGISTER: | 206 | } else { |
280 | return regulator_disable_regmap(rdev); | 207 | return regulator_disable_regmap(rdev); |
281 | default: | ||
282 | return -EINVAL; | ||
283 | } | 208 | } |
284 | } | 209 | } |
285 | 210 | ||
286 | static int lp8788_ldo_is_enabled(struct regulator_dev *rdev) | 211 | static int lp8788_ldo_is_enabled(struct regulator_dev *rdev) |
287 | { | 212 | { |
288 | struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); | 213 | struct lp8788_ldo *ldo = rdev_get_drvdata(rdev); |
289 | enum lp8788_ldo_id id = rdev_get_id(rdev); | ||
290 | enum lp8788_enable_mode mode = lp8788_get_ldo_enable_mode(ldo, id); | ||
291 | 214 | ||
292 | switch (mode) { | 215 | if (ldo->en_pin) |
293 | case EXTPIN: | 216 | return gpio_get_value(ldo->en_pin->gpio) ? 1 : 0; |
294 | return lp8788_ldo_is_enabled_by_extern_pin(ldo); | 217 | else |
295 | case REGISTER: | ||
296 | return regulator_is_enabled_regmap(rdev); | 218 | return regulator_is_enabled_regmap(rdev); |
297 | default: | ||
298 | return -EINVAL; | ||
299 | } | ||
300 | } | 219 | } |
301 | 220 | ||
302 | static int lp8788_ldo_enable_time(struct regulator_dev *rdev) | 221 | static int lp8788_ldo_enable_time(struct regulator_dev *rdev) |
@@ -616,10 +535,11 @@ static struct regulator_desc lp8788_aldo_desc[] = { | |||
616 | }, | 535 | }, |
617 | }; | 536 | }; |
618 | 537 | ||
619 | static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo, | 538 | static int lp8788_gpio_request_ldo_en(struct platform_device *pdev, |
539 | struct lp8788_ldo *ldo, | ||
620 | enum lp8788_ext_ldo_en_id id) | 540 | enum lp8788_ext_ldo_en_id id) |
621 | { | 541 | { |
622 | struct device *dev = ldo->lp->dev; | 542 | struct device *dev = &pdev->dev; |
623 | struct lp8788_ldo_enable_pin *pin = ldo->en_pin; | 543 | struct lp8788_ldo_enable_pin *pin = ldo->en_pin; |
624 | int ret, gpio, pinstate; | 544 | int ret, gpio, pinstate; |
625 | char *name[] = { | 545 | char *name[] = { |
@@ -647,7 +567,8 @@ static int lp8788_gpio_request_ldo_en(struct lp8788_ldo *ldo, | |||
647 | return ret; | 567 | return ret; |
648 | } | 568 | } |
649 | 569 | ||
650 | static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo, | 570 | static int lp8788_config_ldo_enable_mode(struct platform_device *pdev, |
571 | struct lp8788_ldo *ldo, | ||
651 | enum lp8788_ldo_id id) | 572 | enum lp8788_ldo_id id) |
652 | { | 573 | { |
653 | int ret; | 574 | int ret; |
@@ -693,9 +614,11 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo, | |||
693 | 614 | ||
694 | ldo->en_pin = pdata->ldo_pin[enable_id]; | 615 | ldo->en_pin = pdata->ldo_pin[enable_id]; |
695 | 616 | ||
696 | ret = lp8788_gpio_request_ldo_en(ldo, enable_id); | 617 | ret = lp8788_gpio_request_ldo_en(pdev, ldo, enable_id); |
697 | if (ret) | 618 | if (ret) { |
619 | ldo->en_pin = NULL; | ||
698 | goto set_default_ldo_enable_mode; | 620 | goto set_default_ldo_enable_mode; |
621 | } | ||
699 | 622 | ||
700 | return ret; | 623 | return ret; |
701 | 624 | ||
@@ -712,16 +635,16 @@ static int lp8788_dldo_probe(struct platform_device *pdev) | |||
712 | struct regulator_dev *rdev; | 635 | struct regulator_dev *rdev; |
713 | int ret; | 636 | int ret; |
714 | 637 | ||
715 | ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); | 638 | ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); |
716 | if (!ldo) | 639 | if (!ldo) |
717 | return -ENOMEM; | 640 | return -ENOMEM; |
718 | 641 | ||
719 | ldo->lp = lp; | 642 | ldo->lp = lp; |
720 | ret = lp8788_config_ldo_enable_mode(ldo, lp8788_dldo_id[id]); | 643 | ret = lp8788_config_ldo_enable_mode(pdev, ldo, lp8788_dldo_id[id]); |
721 | if (ret) | 644 | if (ret) |
722 | return ret; | 645 | return ret; |
723 | 646 | ||
724 | cfg.dev = lp->dev; | 647 | cfg.dev = pdev->dev.parent; |
725 | cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL; | 648 | cfg.init_data = lp->pdata ? lp->pdata->dldo_data[id] : NULL; |
726 | cfg.driver_data = ldo; | 649 | cfg.driver_data = ldo; |
727 | cfg.regmap = lp->regmap; | 650 | cfg.regmap = lp->regmap; |
@@ -729,7 +652,7 @@ static int lp8788_dldo_probe(struct platform_device *pdev) | |||
729 | rdev = regulator_register(&lp8788_dldo_desc[id], &cfg); | 652 | rdev = regulator_register(&lp8788_dldo_desc[id], &cfg); |
730 | if (IS_ERR(rdev)) { | 653 | if (IS_ERR(rdev)) { |
731 | ret = PTR_ERR(rdev); | 654 | ret = PTR_ERR(rdev); |
732 | dev_err(lp->dev, "DLDO%d regulator register err = %d\n", | 655 | dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n", |
733 | id + 1, ret); | 656 | id + 1, ret); |
734 | return ret; | 657 | return ret; |
735 | } | 658 | } |
@@ -768,16 +691,16 @@ static int lp8788_aldo_probe(struct platform_device *pdev) | |||
768 | struct regulator_dev *rdev; | 691 | struct regulator_dev *rdev; |
769 | int ret; | 692 | int ret; |
770 | 693 | ||
771 | ldo = devm_kzalloc(lp->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); | 694 | ldo = devm_kzalloc(&pdev->dev, sizeof(struct lp8788_ldo), GFP_KERNEL); |
772 | if (!ldo) | 695 | if (!ldo) |
773 | return -ENOMEM; | 696 | return -ENOMEM; |
774 | 697 | ||
775 | ldo->lp = lp; | 698 | ldo->lp = lp; |
776 | ret = lp8788_config_ldo_enable_mode(ldo, lp8788_aldo_id[id]); | 699 | ret = lp8788_config_ldo_enable_mode(pdev, ldo, lp8788_aldo_id[id]); |
777 | if (ret) | 700 | if (ret) |
778 | return ret; | 701 | return ret; |
779 | 702 | ||
780 | cfg.dev = lp->dev; | 703 | cfg.dev = pdev->dev.parent; |
781 | cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL; | 704 | cfg.init_data = lp->pdata ? lp->pdata->aldo_data[id] : NULL; |
782 | cfg.driver_data = ldo; | 705 | cfg.driver_data = ldo; |
783 | cfg.regmap = lp->regmap; | 706 | cfg.regmap = lp->regmap; |
@@ -785,7 +708,7 @@ static int lp8788_aldo_probe(struct platform_device *pdev) | |||
785 | rdev = regulator_register(&lp8788_aldo_desc[id], &cfg); | 708 | rdev = regulator_register(&lp8788_aldo_desc[id], &cfg); |
786 | if (IS_ERR(rdev)) { | 709 | if (IS_ERR(rdev)) { |
787 | ret = PTR_ERR(rdev); | 710 | ret = PTR_ERR(rdev); |
788 | dev_err(lp->dev, "ALDO%d regulator register err = %d\n", | 711 | dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n", |
789 | id + 1, ret); | 712 | id + 1, ret); |
790 | return ret; | 713 | return ret; |
791 | } | 714 | } |
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c index b85040caaea3..e4586ee8858d 100644 --- a/drivers/regulator/max77686.c +++ b/drivers/regulator/max77686.c | |||
@@ -75,13 +75,14 @@ static int max77686_buck_set_suspend_disable(struct regulator_dev *rdev) | |||
75 | { | 75 | { |
76 | unsigned int val; | 76 | unsigned int val; |
77 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); | 77 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
78 | int id = rdev_get_id(rdev); | ||
78 | 79 | ||
79 | if (rdev->desc->id == MAX77686_BUCK1) | 80 | if (id == MAX77686_BUCK1) |
80 | val = 0x1; | 81 | val = 0x1; |
81 | else | 82 | else |
82 | val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT; | 83 | val = 0x1 << MAX77686_OPMODE_BUCK234_SHIFT; |
83 | 84 | ||
84 | max77686->opmode[rdev->desc->id] = val; | 85 | max77686->opmode[id] = val; |
85 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | 86 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
86 | rdev->desc->enable_mask, | 87 | rdev->desc->enable_mask, |
87 | val); | 88 | val); |
@@ -93,9 +94,10 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, | |||
93 | { | 94 | { |
94 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); | 95 | struct max77686_data *max77686 = rdev_get_drvdata(rdev); |
95 | unsigned int val; | 96 | unsigned int val; |
97 | int id = rdev_get_id(rdev); | ||
96 | 98 | ||
97 | /* BUCK[5-9] doesn't support this feature */ | 99 | /* BUCK[5-9] doesn't support this feature */ |
98 | if (rdev->desc->id >= MAX77686_BUCK5) | 100 | if (id >= MAX77686_BUCK5) |
99 | return 0; | 101 | return 0; |
100 | 102 | ||
101 | switch (mode) { | 103 | switch (mode) { |
@@ -111,7 +113,7 @@ static int max77686_set_suspend_mode(struct regulator_dev *rdev, | |||
111 | return -EINVAL; | 113 | return -EINVAL; |
112 | } | 114 | } |
113 | 115 | ||
114 | max77686->opmode[rdev->desc->id] = val; | 116 | max77686->opmode[id] = val; |
115 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | 117 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
116 | rdev->desc->enable_mask, | 118 | rdev->desc->enable_mask, |
117 | val); | 119 | val); |
@@ -140,7 +142,7 @@ static int max77686_ldo_set_suspend_mode(struct regulator_dev *rdev, | |||
140 | return -EINVAL; | 142 | return -EINVAL; |
141 | } | 143 | } |
142 | 144 | ||
143 | max77686->opmode[rdev->desc->id] = val; | 145 | max77686->opmode[rdev_get_id(rdev)] = val; |
144 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | 146 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
145 | rdev->desc->enable_mask, | 147 | rdev->desc->enable_mask, |
146 | val); | 148 | val); |
@@ -152,7 +154,7 @@ static int max77686_enable(struct regulator_dev *rdev) | |||
152 | 154 | ||
153 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | 155 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, |
154 | rdev->desc->enable_mask, | 156 | rdev->desc->enable_mask, |
155 | max77686->opmode[rdev->desc->id]); | 157 | max77686->opmode[rdev_get_id(rdev)]); |
156 | } | 158 | } |
157 | 159 | ||
158 | static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) | 160 | static int max77686_set_ramp_delay(struct regulator_dev *rdev, int ramp_delay) |
@@ -379,9 +381,10 @@ static struct regulator_desc regulators[] = { | |||
379 | }; | 381 | }; |
380 | 382 | ||
381 | #ifdef CONFIG_OF | 383 | #ifdef CONFIG_OF |
382 | static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, | 384 | static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, |
383 | struct max77686_platform_data *pdata) | 385 | struct max77686_platform_data *pdata) |
384 | { | 386 | { |
387 | struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
385 | struct device_node *pmic_np, *regulators_np; | 388 | struct device_node *pmic_np, *regulators_np; |
386 | struct max77686_regulator_data *rdata; | 389 | struct max77686_regulator_data *rdata; |
387 | struct of_regulator_match rmatch; | 390 | struct of_regulator_match rmatch; |
@@ -390,15 +393,15 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, | |||
390 | pmic_np = iodev->dev->of_node; | 393 | pmic_np = iodev->dev->of_node; |
391 | regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators"); | 394 | regulators_np = of_find_node_by_name(pmic_np, "voltage-regulators"); |
392 | if (!regulators_np) { | 395 | if (!regulators_np) { |
393 | dev_err(iodev->dev, "could not find regulators sub-node\n"); | 396 | dev_err(&pdev->dev, "could not find regulators sub-node\n"); |
394 | return -EINVAL; | 397 | return -EINVAL; |
395 | } | 398 | } |
396 | 399 | ||
397 | pdata->num_regulators = ARRAY_SIZE(regulators); | 400 | pdata->num_regulators = ARRAY_SIZE(regulators); |
398 | rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * | 401 | rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * |
399 | pdata->num_regulators, GFP_KERNEL); | 402 | pdata->num_regulators, GFP_KERNEL); |
400 | if (!rdata) { | 403 | if (!rdata) { |
401 | dev_err(iodev->dev, | 404 | dev_err(&pdev->dev, |
402 | "could not allocate memory for regulator data\n"); | 405 | "could not allocate memory for regulator data\n"); |
403 | return -ENOMEM; | 406 | return -ENOMEM; |
404 | } | 407 | } |
@@ -407,7 +410,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, | |||
407 | rmatch.name = regulators[i].name; | 410 | rmatch.name = regulators[i].name; |
408 | rmatch.init_data = NULL; | 411 | rmatch.init_data = NULL; |
409 | rmatch.of_node = NULL; | 412 | rmatch.of_node = NULL; |
410 | of_regulator_match(iodev->dev, regulators_np, &rmatch, 1); | 413 | of_regulator_match(&pdev->dev, regulators_np, &rmatch, 1); |
411 | rdata[i].initdata = rmatch.init_data; | 414 | rdata[i].initdata = rmatch.init_data; |
412 | rdata[i].of_node = rmatch.of_node; | 415 | rdata[i].of_node = rmatch.of_node; |
413 | } | 416 | } |
@@ -417,7 +420,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, | |||
417 | return 0; | 420 | return 0; |
418 | } | 421 | } |
419 | #else | 422 | #else |
420 | static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev, | 423 | static int max77686_pmic_dt_parse_pdata(struct platform_device *pdev, |
421 | struct max77686_platform_data *pdata) | 424 | struct max77686_platform_data *pdata) |
422 | { | 425 | { |
423 | return 0; | 426 | return 0; |
@@ -440,7 +443,7 @@ static int max77686_pmic_probe(struct platform_device *pdev) | |||
440 | } | 443 | } |
441 | 444 | ||
442 | if (iodev->dev->of_node) { | 445 | if (iodev->dev->of_node) { |
443 | ret = max77686_pmic_dt_parse_pdata(iodev, pdata); | 446 | ret = max77686_pmic_dt_parse_pdata(pdev, pdata); |
444 | if (ret) | 447 | if (ret) |
445 | return ret; | 448 | return ret; |
446 | } | 449 | } |
diff --git a/drivers/regulator/max8907-regulator.c b/drivers/regulator/max8907-regulator.c index d1a77512d83e..4568c15fa78d 100644 --- a/drivers/regulator/max8907-regulator.c +++ b/drivers/regulator/max8907-regulator.c | |||
@@ -224,11 +224,11 @@ static struct of_regulator_match max8907_matches[] = { | |||
224 | 224 | ||
225 | static int max8907_regulator_parse_dt(struct platform_device *pdev) | 225 | static int max8907_regulator_parse_dt(struct platform_device *pdev) |
226 | { | 226 | { |
227 | struct device_node *np = pdev->dev.parent->of_node; | 227 | struct device_node *np, *regulators; |
228 | struct device_node *regulators; | ||
229 | int ret; | 228 | int ret; |
230 | 229 | ||
231 | if (!pdev->dev.parent->of_node) | 230 | np = of_node_get(pdev->dev.parent->of_node); |
231 | if (!np) | ||
232 | return 0; | 232 | return 0; |
233 | 233 | ||
234 | regulators = of_find_node_by_name(np, "regulators"); | 234 | regulators = of_find_node_by_name(np, "regulators"); |
@@ -237,9 +237,9 @@ static int max8907_regulator_parse_dt(struct platform_device *pdev) | |||
237 | return -EINVAL; | 237 | return -EINVAL; |
238 | } | 238 | } |
239 | 239 | ||
240 | ret = of_regulator_match(pdev->dev.parent, regulators, | 240 | ret = of_regulator_match(&pdev->dev, regulators, max8907_matches, |
241 | max8907_matches, | ||
242 | ARRAY_SIZE(max8907_matches)); | 241 | ARRAY_SIZE(max8907_matches)); |
242 | of_node_put(regulators); | ||
243 | if (ret < 0) { | 243 | if (ret < 0) { |
244 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", | 244 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", |
245 | ret); | 245 | ret); |
diff --git a/drivers/regulator/max8925-regulator.c b/drivers/regulator/max8925-regulator.c index 446a85445553..0d5f64a805a0 100644 --- a/drivers/regulator/max8925-regulator.c +++ b/drivers/regulator/max8925-regulator.c | |||
@@ -252,7 +252,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev, | |||
252 | { | 252 | { |
253 | struct device_node *nproot, *np; | 253 | struct device_node *nproot, *np; |
254 | int rcount; | 254 | int rcount; |
255 | nproot = pdev->dev.parent->of_node; | 255 | nproot = of_node_get(pdev->dev.parent->of_node); |
256 | if (!nproot) | 256 | if (!nproot) |
257 | return -ENODEV; | 257 | return -ENODEV; |
258 | np = of_find_node_by_name(nproot, "regulators"); | 258 | np = of_find_node_by_name(nproot, "regulators"); |
@@ -263,6 +263,7 @@ static int max8925_regulator_dt_init(struct platform_device *pdev, | |||
263 | 263 | ||
264 | rcount = of_regulator_match(&pdev->dev, np, | 264 | rcount = of_regulator_match(&pdev->dev, np, |
265 | &max8925_regulator_matches[ridx], 1); | 265 | &max8925_regulator_matches[ridx], 1); |
266 | of_node_put(np); | ||
266 | if (rcount < 0) | 267 | if (rcount < 0) |
267 | return -ENODEV; | 268 | return -ENODEV; |
268 | config->init_data = max8925_regulator_matches[ridx].init_data; | 269 | config->init_data = max8925_regulator_matches[ridx].init_data; |
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c index df0eafb0dc7e..0ac7a87519b4 100644 --- a/drivers/regulator/max8997.c +++ b/drivers/regulator/max8997.c | |||
@@ -54,6 +54,13 @@ struct max8997_data { | |||
54 | u8 saved_states[MAX8997_REG_MAX]; | 54 | u8 saved_states[MAX8997_REG_MAX]; |
55 | }; | 55 | }; |
56 | 56 | ||
57 | static const unsigned int safeoutvolt[] = { | ||
58 | 4850000, | ||
59 | 4900000, | ||
60 | 4950000, | ||
61 | 3300000, | ||
62 | }; | ||
63 | |||
57 | static inline void max8997_set_gpio(struct max8997_data *max8997) | 64 | static inline void max8997_set_gpio(struct max8997_data *max8997) |
58 | { | 65 | { |
59 | int set3 = (max8997->buck125_gpioindex) & 0x1; | 66 | int set3 = (max8997->buck125_gpioindex) & 0x1; |
@@ -71,26 +78,26 @@ struct voltage_map_desc { | |||
71 | int step; | 78 | int step; |
72 | }; | 79 | }; |
73 | 80 | ||
74 | /* Voltage maps in mV */ | 81 | /* Voltage maps in uV */ |
75 | static const struct voltage_map_desc ldo_voltage_map_desc = { | 82 | static const struct voltage_map_desc ldo_voltage_map_desc = { |
76 | .min = 800, .max = 3950, .step = 50, | 83 | .min = 800000, .max = 3950000, .step = 50000, |
77 | }; /* LDO1 ~ 18, 21 all */ | 84 | }; /* LDO1 ~ 18, 21 all */ |
78 | 85 | ||
79 | static const struct voltage_map_desc buck1245_voltage_map_desc = { | 86 | static const struct voltage_map_desc buck1245_voltage_map_desc = { |
80 | .min = 650, .max = 2225, .step = 25, | 87 | .min = 650000, .max = 2225000, .step = 25000, |
81 | }; /* Buck1, 2, 4, 5 */ | 88 | }; /* Buck1, 2, 4, 5 */ |
82 | 89 | ||
83 | static const struct voltage_map_desc buck37_voltage_map_desc = { | 90 | static const struct voltage_map_desc buck37_voltage_map_desc = { |
84 | .min = 750, .max = 3900, .step = 50, | 91 | .min = 750000, .max = 3900000, .step = 50000, |
85 | }; /* Buck3, 7 */ | 92 | }; /* Buck3, 7 */ |
86 | 93 | ||
87 | /* current map in mA */ | 94 | /* current map in uA */ |
88 | static const struct voltage_map_desc charger_current_map_desc = { | 95 | static const struct voltage_map_desc charger_current_map_desc = { |
89 | .min = 200, .max = 950, .step = 50, | 96 | .min = 200000, .max = 950000, .step = 50000, |
90 | }; | 97 | }; |
91 | 98 | ||
92 | static const struct voltage_map_desc topoff_current_map_desc = { | 99 | static const struct voltage_map_desc topoff_current_map_desc = { |
93 | .min = 50, .max = 200, .step = 10, | 100 | .min = 50000, .max = 200000, .step = 10000, |
94 | }; | 101 | }; |
95 | 102 | ||
96 | static const struct voltage_map_desc *reg_voltage_map[] = { | 103 | static const struct voltage_map_desc *reg_voltage_map[] = { |
@@ -130,29 +137,6 @@ static const struct voltage_map_desc *reg_voltage_map[] = { | |||
130 | [MAX8997_CHARGER_TOPOFF] = &topoff_current_map_desc, | 137 | [MAX8997_CHARGER_TOPOFF] = &topoff_current_map_desc, |
131 | }; | 138 | }; |
132 | 139 | ||
133 | static int max8997_list_voltage_safeout(struct regulator_dev *rdev, | ||
134 | unsigned int selector) | ||
135 | { | ||
136 | int rid = rdev_get_id(rdev); | ||
137 | |||
138 | if (rid == MAX8997_ESAFEOUT1 || rid == MAX8997_ESAFEOUT2) { | ||
139 | switch (selector) { | ||
140 | case 0: | ||
141 | return 4850000; | ||
142 | case 1: | ||
143 | return 4900000; | ||
144 | case 2: | ||
145 | return 4950000; | ||
146 | case 3: | ||
147 | return 3300000; | ||
148 | default: | ||
149 | return -EINVAL; | ||
150 | } | ||
151 | } | ||
152 | |||
153 | return -EINVAL; | ||
154 | } | ||
155 | |||
156 | static int max8997_list_voltage_charger_cv(struct regulator_dev *rdev, | 140 | static int max8997_list_voltage_charger_cv(struct regulator_dev *rdev, |
157 | unsigned int selector) | 141 | unsigned int selector) |
158 | { | 142 | { |
@@ -194,7 +178,7 @@ static int max8997_list_voltage(struct regulator_dev *rdev, | |||
194 | if (val > desc->max) | 178 | if (val > desc->max) |
195 | return -EINVAL; | 179 | return -EINVAL; |
196 | 180 | ||
197 | return val * 1000; | 181 | return val; |
198 | } | 182 | } |
199 | 183 | ||
200 | static int max8997_get_enable_register(struct regulator_dev *rdev, | 184 | static int max8997_get_enable_register(struct regulator_dev *rdev, |
@@ -485,7 +469,6 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, | |||
485 | { | 469 | { |
486 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | 470 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); |
487 | struct i2c_client *i2c = max8997->iodev->i2c; | 471 | struct i2c_client *i2c = max8997->iodev->i2c; |
488 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
489 | const struct voltage_map_desc *desc; | 472 | const struct voltage_map_desc *desc; |
490 | int rid = rdev_get_id(rdev); | 473 | int rid = rdev_get_id(rdev); |
491 | int i, reg, shift, mask, ret; | 474 | int i, reg, shift, mask, ret; |
@@ -509,7 +492,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, | |||
509 | 492 | ||
510 | desc = reg_voltage_map[rid]; | 493 | desc = reg_voltage_map[rid]; |
511 | 494 | ||
512 | i = max8997_get_voltage_proper_val(desc, min_vol, max_vol); | 495 | i = max8997_get_voltage_proper_val(desc, min_uV, max_uV); |
513 | if (i < 0) | 496 | if (i < 0) |
514 | return i; | 497 | return i; |
515 | 498 | ||
@@ -523,7 +506,7 @@ static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev, | |||
523 | return ret; | 506 | return ret; |
524 | } | 507 | } |
525 | 508 | ||
526 | static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, | 509 | static int max8997_set_voltage_buck_time_sel(struct regulator_dev *rdev, |
527 | unsigned int old_selector, | 510 | unsigned int old_selector, |
528 | unsigned int new_selector) | 511 | unsigned int new_selector) |
529 | { | 512 | { |
@@ -557,7 +540,7 @@ static int max8997_set_voltage_ldobuck_time_sel(struct regulator_dev *rdev, | |||
557 | case MAX8997_BUCK4: | 540 | case MAX8997_BUCK4: |
558 | case MAX8997_BUCK5: | 541 | case MAX8997_BUCK5: |
559 | return DIV_ROUND_UP(desc->step * (new_selector - old_selector), | 542 | return DIV_ROUND_UP(desc->step * (new_selector - old_selector), |
560 | max8997->ramp_delay); | 543 | max8997->ramp_delay * 1000); |
561 | } | 544 | } |
562 | 545 | ||
563 | return 0; | 546 | return 0; |
@@ -656,7 +639,6 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, | |||
656 | const struct voltage_map_desc *desc; | 639 | const struct voltage_map_desc *desc; |
657 | int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; | 640 | int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg; |
658 | bool gpio_dvs_mode = false; | 641 | bool gpio_dvs_mode = false; |
659 | int min_vol = min_uV / 1000, max_vol = max_uV / 1000; | ||
660 | 642 | ||
661 | if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) | 643 | if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7) |
662 | return -EINVAL; | 644 | return -EINVAL; |
@@ -681,7 +663,7 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev, | |||
681 | selector); | 663 | selector); |
682 | 664 | ||
683 | desc = reg_voltage_map[rid]; | 665 | desc = reg_voltage_map[rid]; |
684 | new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol); | 666 | new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV); |
685 | if (new_val < 0) | 667 | if (new_val < 0) |
686 | return new_val; | 668 | return new_val; |
687 | 669 | ||
@@ -722,49 +704,23 @@ out: | |||
722 | return 0; | 704 | return 0; |
723 | } | 705 | } |
724 | 706 | ||
725 | static const int safeoutvolt[] = { | ||
726 | 3300000, | ||
727 | 4850000, | ||
728 | 4900000, | ||
729 | 4950000, | ||
730 | }; | ||
731 | |||
732 | /* For SAFEOUT1 and SAFEOUT2 */ | 707 | /* For SAFEOUT1 and SAFEOUT2 */ |
733 | static int max8997_set_voltage_safeout(struct regulator_dev *rdev, | 708 | static int max8997_set_voltage_safeout_sel(struct regulator_dev *rdev, |
734 | int min_uV, int max_uV, unsigned *selector) | 709 | unsigned selector) |
735 | { | 710 | { |
736 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); | 711 | struct max8997_data *max8997 = rdev_get_drvdata(rdev); |
737 | struct i2c_client *i2c = max8997->iodev->i2c; | 712 | struct i2c_client *i2c = max8997->iodev->i2c; |
738 | int rid = rdev_get_id(rdev); | 713 | int rid = rdev_get_id(rdev); |
739 | int reg, shift = 0, mask, ret; | 714 | int reg, shift = 0, mask, ret; |
740 | int i = 0; | ||
741 | u8 val; | ||
742 | 715 | ||
743 | if (rid != MAX8997_ESAFEOUT1 && rid != MAX8997_ESAFEOUT2) | 716 | if (rid != MAX8997_ESAFEOUT1 && rid != MAX8997_ESAFEOUT2) |
744 | return -EINVAL; | 717 | return -EINVAL; |
745 | 718 | ||
746 | for (i = 0; i < ARRAY_SIZE(safeoutvolt); i++) { | ||
747 | if (min_uV <= safeoutvolt[i] && | ||
748 | max_uV >= safeoutvolt[i]) | ||
749 | break; | ||
750 | } | ||
751 | |||
752 | if (i >= ARRAY_SIZE(safeoutvolt)) | ||
753 | return -EINVAL; | ||
754 | |||
755 | if (i == 0) | ||
756 | val = 0x3; | ||
757 | else | ||
758 | val = i - 1; | ||
759 | |||
760 | ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); | 719 | ret = max8997_get_voltage_register(rdev, ®, &shift, &mask); |
761 | if (ret) | 720 | if (ret) |
762 | return ret; | 721 | return ret; |
763 | 722 | ||
764 | ret = max8997_update_reg(i2c, reg, val << shift, mask << shift); | 723 | return max8997_update_reg(i2c, reg, selector << shift, mask << shift); |
765 | *selector = val; | ||
766 | |||
767 | return ret; | ||
768 | } | 724 | } |
769 | 725 | ||
770 | static int max8997_reg_disable_suspend(struct regulator_dev *rdev) | 726 | static int max8997_reg_disable_suspend(struct regulator_dev *rdev) |
@@ -801,7 +757,6 @@ static struct regulator_ops max8997_ldo_ops = { | |||
801 | .disable = max8997_reg_disable, | 757 | .disable = max8997_reg_disable, |
802 | .get_voltage_sel = max8997_get_voltage_sel, | 758 | .get_voltage_sel = max8997_get_voltage_sel, |
803 | .set_voltage = max8997_set_voltage_ldobuck, | 759 | .set_voltage = max8997_set_voltage_ldobuck, |
804 | .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, | ||
805 | .set_suspend_disable = max8997_reg_disable_suspend, | 760 | .set_suspend_disable = max8997_reg_disable_suspend, |
806 | }; | 761 | }; |
807 | 762 | ||
@@ -812,7 +767,7 @@ static struct regulator_ops max8997_buck_ops = { | |||
812 | .disable = max8997_reg_disable, | 767 | .disable = max8997_reg_disable, |
813 | .get_voltage_sel = max8997_get_voltage_sel, | 768 | .get_voltage_sel = max8997_get_voltage_sel, |
814 | .set_voltage = max8997_set_voltage_buck, | 769 | .set_voltage = max8997_set_voltage_buck, |
815 | .set_voltage_time_sel = max8997_set_voltage_ldobuck_time_sel, | 770 | .set_voltage_time_sel = max8997_set_voltage_buck_time_sel, |
816 | .set_suspend_disable = max8997_reg_disable_suspend, | 771 | .set_suspend_disable = max8997_reg_disable_suspend, |
817 | }; | 772 | }; |
818 | 773 | ||
@@ -825,12 +780,12 @@ static struct regulator_ops max8997_fixedvolt_ops = { | |||
825 | }; | 780 | }; |
826 | 781 | ||
827 | static struct regulator_ops max8997_safeout_ops = { | 782 | static struct regulator_ops max8997_safeout_ops = { |
828 | .list_voltage = max8997_list_voltage_safeout, | 783 | .list_voltage = regulator_list_voltage_table, |
829 | .is_enabled = max8997_reg_is_enabled, | 784 | .is_enabled = max8997_reg_is_enabled, |
830 | .enable = max8997_reg_enable, | 785 | .enable = max8997_reg_enable, |
831 | .disable = max8997_reg_disable, | 786 | .disable = max8997_reg_disable, |
832 | .get_voltage_sel = max8997_get_voltage_sel, | 787 | .get_voltage_sel = max8997_get_voltage_sel, |
833 | .set_voltage = max8997_set_voltage_safeout, | 788 | .set_voltage_sel = max8997_set_voltage_safeout_sel, |
834 | .set_suspend_disable = max8997_reg_disable_suspend, | 789 | .set_suspend_disable = max8997_reg_disable_suspend, |
835 | }; | 790 | }; |
836 | 791 | ||
@@ -936,7 +891,7 @@ static struct regulator_desc regulators[] = { | |||
936 | }; | 891 | }; |
937 | 892 | ||
938 | #ifdef CONFIG_OF | 893 | #ifdef CONFIG_OF |
939 | static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev, | 894 | static int max8997_pmic_dt_parse_dvs_gpio(struct platform_device *pdev, |
940 | struct max8997_platform_data *pdata, | 895 | struct max8997_platform_data *pdata, |
941 | struct device_node *pmic_np) | 896 | struct device_node *pmic_np) |
942 | { | 897 | { |
@@ -946,7 +901,7 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev, | |||
946 | gpio = of_get_named_gpio(pmic_np, | 901 | gpio = of_get_named_gpio(pmic_np, |
947 | "max8997,pmic-buck125-dvs-gpios", i); | 902 | "max8997,pmic-buck125-dvs-gpios", i); |
948 | if (!gpio_is_valid(gpio)) { | 903 | if (!gpio_is_valid(gpio)) { |
949 | dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); | 904 | dev_err(&pdev->dev, "invalid gpio[%d]: %d\n", i, gpio); |
950 | return -EINVAL; | 905 | return -EINVAL; |
951 | } | 906 | } |
952 | pdata->buck125_gpios[i] = gpio; | 907 | pdata->buck125_gpios[i] = gpio; |
@@ -954,35 +909,34 @@ static int max8997_pmic_dt_parse_dvs_gpio(struct max8997_dev *iodev, | |||
954 | return 0; | 909 | return 0; |
955 | } | 910 | } |
956 | 911 | ||
957 | static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, | 912 | static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, |
958 | struct max8997_platform_data *pdata) | 913 | struct max8997_platform_data *pdata) |
959 | { | 914 | { |
915 | struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
960 | struct device_node *pmic_np, *regulators_np, *reg_np; | 916 | struct device_node *pmic_np, *regulators_np, *reg_np; |
961 | struct max8997_regulator_data *rdata; | 917 | struct max8997_regulator_data *rdata; |
962 | unsigned int i, dvs_voltage_nr = 1, ret; | 918 | unsigned int i, dvs_voltage_nr = 1, ret; |
963 | 919 | ||
964 | pmic_np = iodev->dev->of_node; | 920 | pmic_np = of_node_get(iodev->dev->of_node); |
965 | if (!pmic_np) { | 921 | if (!pmic_np) { |
966 | dev_err(iodev->dev, "could not find pmic sub-node\n"); | 922 | dev_err(&pdev->dev, "could not find pmic sub-node\n"); |
967 | return -ENODEV; | 923 | return -ENODEV; |
968 | } | 924 | } |
969 | 925 | ||
970 | regulators_np = of_find_node_by_name(pmic_np, "regulators"); | 926 | regulators_np = of_find_node_by_name(pmic_np, "regulators"); |
971 | if (!regulators_np) { | 927 | if (!regulators_np) { |
972 | dev_err(iodev->dev, "could not find regulators sub-node\n"); | 928 | dev_err(&pdev->dev, "could not find regulators sub-node\n"); |
973 | return -EINVAL; | 929 | return -EINVAL; |
974 | } | 930 | } |
975 | 931 | ||
976 | /* count the number of regulators to be supported in pmic */ | 932 | /* count the number of regulators to be supported in pmic */ |
977 | pdata->num_regulators = 0; | 933 | pdata->num_regulators = of_get_child_count(regulators_np); |
978 | for_each_child_of_node(regulators_np, reg_np) | ||
979 | pdata->num_regulators++; | ||
980 | 934 | ||
981 | rdata = devm_kzalloc(iodev->dev, sizeof(*rdata) * | 935 | rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * |
982 | pdata->num_regulators, GFP_KERNEL); | 936 | pdata->num_regulators, GFP_KERNEL); |
983 | if (!rdata) { | 937 | if (!rdata) { |
984 | dev_err(iodev->dev, "could not allocate memory for " | 938 | of_node_put(regulators_np); |
985 | "regulator data\n"); | 939 | dev_err(&pdev->dev, "could not allocate memory for regulator data\n"); |
986 | return -ENOMEM; | 940 | return -ENOMEM; |
987 | } | 941 | } |
988 | 942 | ||
@@ -993,17 +947,18 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, | |||
993 | break; | 947 | break; |
994 | 948 | ||
995 | if (i == ARRAY_SIZE(regulators)) { | 949 | if (i == ARRAY_SIZE(regulators)) { |
996 | dev_warn(iodev->dev, "don't know how to configure " | 950 | dev_warn(&pdev->dev, "don't know how to configure regulator %s\n", |
997 | "regulator %s\n", reg_np->name); | 951 | reg_np->name); |
998 | continue; | 952 | continue; |
999 | } | 953 | } |
1000 | 954 | ||
1001 | rdata->id = i; | 955 | rdata->id = i; |
1002 | rdata->initdata = of_get_regulator_init_data( | 956 | rdata->initdata = of_get_regulator_init_data(&pdev->dev, |
1003 | iodev->dev, reg_np); | 957 | reg_np); |
1004 | rdata->reg_node = reg_np; | 958 | rdata->reg_node = reg_np; |
1005 | rdata++; | 959 | rdata++; |
1006 | } | 960 | } |
961 | of_node_put(regulators_np); | ||
1007 | 962 | ||
1008 | if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL)) | 963 | if (of_get_property(pmic_np, "max8997,pmic-buck1-uses-gpio-dvs", NULL)) |
1009 | pdata->buck1_gpiodvs = true; | 964 | pdata->buck1_gpiodvs = true; |
@@ -1016,7 +971,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, | |||
1016 | 971 | ||
1017 | if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs || | 972 | if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs || |
1018 | pdata->buck5_gpiodvs) { | 973 | pdata->buck5_gpiodvs) { |
1019 | ret = max8997_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); | 974 | ret = max8997_pmic_dt_parse_dvs_gpio(pdev, pdata, pmic_np); |
1020 | if (ret) | 975 | if (ret) |
1021 | return -EINVAL; | 976 | return -EINVAL; |
1022 | 977 | ||
@@ -1027,8 +982,7 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, | |||
1027 | } else { | 982 | } else { |
1028 | if (pdata->buck125_default_idx >= 8) { | 983 | if (pdata->buck125_default_idx >= 8) { |
1029 | pdata->buck125_default_idx = 0; | 984 | pdata->buck125_default_idx = 0; |
1030 | dev_info(iodev->dev, "invalid value for " | 985 | dev_info(&pdev->dev, "invalid value for default dvs index, using 0 instead\n"); |
1031 | "default dvs index, using 0 instead\n"); | ||
1032 | } | 986 | } |
1033 | } | 987 | } |
1034 | 988 | ||
@@ -1042,28 +996,28 @@ static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, | |||
1042 | if (of_property_read_u32_array(pmic_np, | 996 | if (of_property_read_u32_array(pmic_np, |
1043 | "max8997,pmic-buck1-dvs-voltage", | 997 | "max8997,pmic-buck1-dvs-voltage", |
1044 | pdata->buck1_voltage, dvs_voltage_nr)) { | 998 | pdata->buck1_voltage, dvs_voltage_nr)) { |
1045 | dev_err(iodev->dev, "buck1 voltages not specified\n"); | 999 | dev_err(&pdev->dev, "buck1 voltages not specified\n"); |
1046 | return -EINVAL; | 1000 | return -EINVAL; |
1047 | } | 1001 | } |
1048 | 1002 | ||
1049 | if (of_property_read_u32_array(pmic_np, | 1003 | if (of_property_read_u32_array(pmic_np, |
1050 | "max8997,pmic-buck2-dvs-voltage", | 1004 | "max8997,pmic-buck2-dvs-voltage", |
1051 | pdata->buck2_voltage, dvs_voltage_nr)) { | 1005 | pdata->buck2_voltage, dvs_voltage_nr)) { |
1052 | dev_err(iodev->dev, "buck2 voltages not specified\n"); | 1006 | dev_err(&pdev->dev, "buck2 voltages not specified\n"); |
1053 | return -EINVAL; | 1007 | return -EINVAL; |
1054 | } | 1008 | } |
1055 | 1009 | ||
1056 | if (of_property_read_u32_array(pmic_np, | 1010 | if (of_property_read_u32_array(pmic_np, |
1057 | "max8997,pmic-buck5-dvs-voltage", | 1011 | "max8997,pmic-buck5-dvs-voltage", |
1058 | pdata->buck5_voltage, dvs_voltage_nr)) { | 1012 | pdata->buck5_voltage, dvs_voltage_nr)) { |
1059 | dev_err(iodev->dev, "buck5 voltages not specified\n"); | 1013 | dev_err(&pdev->dev, "buck5 voltages not specified\n"); |
1060 | return -EINVAL; | 1014 | return -EINVAL; |
1061 | } | 1015 | } |
1062 | 1016 | ||
1063 | return 0; | 1017 | return 0; |
1064 | } | 1018 | } |
1065 | #else | 1019 | #else |
1066 | static int max8997_pmic_dt_parse_pdata(struct max8997_dev *iodev, | 1020 | static int max8997_pmic_dt_parse_pdata(struct platform_device *pdev, |
1067 | struct max8997_platform_data *pdata) | 1021 | struct max8997_platform_data *pdata) |
1068 | { | 1022 | { |
1069 | return 0; | 1023 | return 0; |
@@ -1087,7 +1041,7 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1087 | } | 1041 | } |
1088 | 1042 | ||
1089 | if (iodev->dev->of_node) { | 1043 | if (iodev->dev->of_node) { |
1090 | ret = max8997_pmic_dt_parse_pdata(iodev, pdata); | 1044 | ret = max8997_pmic_dt_parse_pdata(pdev, pdata); |
1091 | if (ret) | 1045 | if (ret) |
1092 | return ret; | 1046 | return ret; |
1093 | } | 1047 | } |
@@ -1123,8 +1077,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1123 | max8997->buck1_vol[i] = ret = | 1077 | max8997->buck1_vol[i] = ret = |
1124 | max8997_get_voltage_proper_val( | 1078 | max8997_get_voltage_proper_val( |
1125 | &buck1245_voltage_map_desc, | 1079 | &buck1245_voltage_map_desc, |
1126 | pdata->buck1_voltage[i] / 1000, | 1080 | pdata->buck1_voltage[i], |
1127 | pdata->buck1_voltage[i] / 1000 + | 1081 | pdata->buck1_voltage[i] + |
1128 | buck1245_voltage_map_desc.step); | 1082 | buck1245_voltage_map_desc.step); |
1129 | if (ret < 0) | 1083 | if (ret < 0) |
1130 | goto err_out; | 1084 | goto err_out; |
@@ -1132,8 +1086,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1132 | max8997->buck2_vol[i] = ret = | 1086 | max8997->buck2_vol[i] = ret = |
1133 | max8997_get_voltage_proper_val( | 1087 | max8997_get_voltage_proper_val( |
1134 | &buck1245_voltage_map_desc, | 1088 | &buck1245_voltage_map_desc, |
1135 | pdata->buck2_voltage[i] / 1000, | 1089 | pdata->buck2_voltage[i], |
1136 | pdata->buck2_voltage[i] / 1000 + | 1090 | pdata->buck2_voltage[i] + |
1137 | buck1245_voltage_map_desc.step); | 1091 | buck1245_voltage_map_desc.step); |
1138 | if (ret < 0) | 1092 | if (ret < 0) |
1139 | goto err_out; | 1093 | goto err_out; |
@@ -1141,8 +1095,8 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1141 | max8997->buck5_vol[i] = ret = | 1095 | max8997->buck5_vol[i] = ret = |
1142 | max8997_get_voltage_proper_val( | 1096 | max8997_get_voltage_proper_val( |
1143 | &buck1245_voltage_map_desc, | 1097 | &buck1245_voltage_map_desc, |
1144 | pdata->buck5_voltage[i] / 1000, | 1098 | pdata->buck5_voltage[i], |
1145 | pdata->buck5_voltage[i] / 1000 + | 1099 | pdata->buck5_voltage[i] + |
1146 | buck1245_voltage_map_desc.step); | 1100 | buck1245_voltage_map_desc.step); |
1147 | if (ret < 0) | 1101 | if (ret < 0) |
1148 | goto err_out; | 1102 | goto err_out; |
@@ -1236,13 +1190,15 @@ static int max8997_pmic_probe(struct platform_device *pdev) | |||
1236 | int id = pdata->regulators[i].id; | 1190 | int id = pdata->regulators[i].id; |
1237 | 1191 | ||
1238 | desc = reg_voltage_map[id]; | 1192 | desc = reg_voltage_map[id]; |
1239 | if (desc) | 1193 | if (desc) { |
1240 | regulators[id].n_voltages = | 1194 | regulators[id].n_voltages = |
1241 | (desc->max - desc->min) / desc->step + 1; | 1195 | (desc->max - desc->min) / desc->step + 1; |
1242 | else if (id == MAX8997_ESAFEOUT1 || id == MAX8997_ESAFEOUT2) | 1196 | } else if (id == MAX8997_ESAFEOUT1 || id == MAX8997_ESAFEOUT2) { |
1243 | regulators[id].n_voltages = 4; | 1197 | regulators[id].volt_table = safeoutvolt; |
1244 | else if (id == MAX8997_CHARGER_CV) | 1198 | regulators[id].n_voltages = ARRAY_SIZE(safeoutvolt); |
1199 | } else if (id == MAX8997_CHARGER_CV) { | ||
1245 | regulators[id].n_voltages = 16; | 1200 | regulators[id].n_voltages = 16; |
1201 | } | ||
1246 | 1202 | ||
1247 | config.dev = max8997->dev; | 1203 | config.dev = max8997->dev; |
1248 | config.init_data = pdata->regulators[i].initdata; | 1204 | config.init_data = pdata->regulators[i].initdata; |
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c index b821d08eb64a..b588f07c7cad 100644 --- a/drivers/regulator/max8998.c +++ b/drivers/regulator/max8998.c | |||
@@ -51,39 +51,39 @@ struct voltage_map_desc { | |||
51 | int step; | 51 | int step; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | /* Voltage maps */ | 54 | /* Voltage maps in uV*/ |
55 | static const struct voltage_map_desc ldo23_voltage_map_desc = { | 55 | static const struct voltage_map_desc ldo23_voltage_map_desc = { |
56 | .min = 800, .step = 50, .max = 1300, | 56 | .min = 800000, .step = 50000, .max = 1300000, |
57 | }; | 57 | }; |
58 | static const struct voltage_map_desc ldo456711_voltage_map_desc = { | 58 | static const struct voltage_map_desc ldo456711_voltage_map_desc = { |
59 | .min = 1600, .step = 100, .max = 3600, | 59 | .min = 1600000, .step = 100000, .max = 3600000, |
60 | }; | 60 | }; |
61 | static const struct voltage_map_desc ldo8_voltage_map_desc = { | 61 | static const struct voltage_map_desc ldo8_voltage_map_desc = { |
62 | .min = 3000, .step = 100, .max = 3600, | 62 | .min = 3000000, .step = 100000, .max = 3600000, |
63 | }; | 63 | }; |
64 | static const struct voltage_map_desc ldo9_voltage_map_desc = { | 64 | static const struct voltage_map_desc ldo9_voltage_map_desc = { |
65 | .min = 2800, .step = 100, .max = 3100, | 65 | .min = 2800000, .step = 100000, .max = 3100000, |
66 | }; | 66 | }; |
67 | static const struct voltage_map_desc ldo10_voltage_map_desc = { | 67 | static const struct voltage_map_desc ldo10_voltage_map_desc = { |
68 | .min = 950, .step = 50, .max = 1300, | 68 | .min = 950000, .step = 50000, .max = 1300000, |
69 | }; | 69 | }; |
70 | static const struct voltage_map_desc ldo1213_voltage_map_desc = { | 70 | static const struct voltage_map_desc ldo1213_voltage_map_desc = { |
71 | .min = 800, .step = 100, .max = 3300, | 71 | .min = 800000, .step = 100000, .max = 3300000, |
72 | }; | 72 | }; |
73 | static const struct voltage_map_desc ldo1415_voltage_map_desc = { | 73 | static const struct voltage_map_desc ldo1415_voltage_map_desc = { |
74 | .min = 1200, .step = 100, .max = 3300, | 74 | .min = 1200000, .step = 100000, .max = 3300000, |
75 | }; | 75 | }; |
76 | static const struct voltage_map_desc ldo1617_voltage_map_desc = { | 76 | static const struct voltage_map_desc ldo1617_voltage_map_desc = { |
77 | .min = 1600, .step = 100, .max = 3600, | 77 | .min = 1600000, .step = 100000, .max = 3600000, |
78 | }; | 78 | }; |
79 | static const struct voltage_map_desc buck12_voltage_map_desc = { | 79 | static const struct voltage_map_desc buck12_voltage_map_desc = { |
80 | .min = 750, .step = 25, .max = 1525, | 80 | .min = 750000, .step = 25000, .max = 1525000, |
81 | }; | 81 | }; |
82 | static const struct voltage_map_desc buck3_voltage_map_desc = { | 82 | static const struct voltage_map_desc buck3_voltage_map_desc = { |
83 | .min = 1600, .step = 100, .max = 3600, | 83 | .min = 1600000, .step = 100000, .max = 3600000, |
84 | }; | 84 | }; |
85 | static const struct voltage_map_desc buck4_voltage_map_desc = { | 85 | static const struct voltage_map_desc buck4_voltage_map_desc = { |
86 | .min = 800, .step = 100, .max = 2300, | 86 | .min = 800000, .step = 100000, .max = 2300000, |
87 | }; | 87 | }; |
88 | 88 | ||
89 | static const struct voltage_map_desc *ldo_voltage_map[] = { | 89 | static const struct voltage_map_desc *ldo_voltage_map[] = { |
@@ -311,25 +311,13 @@ static int max8998_set_voltage_buck_sel(struct regulator_dev *rdev, | |||
311 | dev_get_platdata(max8998->iodev->dev); | 311 | dev_get_platdata(max8998->iodev->dev); |
312 | struct i2c_client *i2c = max8998->iodev->i2c; | 312 | struct i2c_client *i2c = max8998->iodev->i2c; |
313 | int buck = rdev_get_id(rdev); | 313 | int buck = rdev_get_id(rdev); |
314 | int reg, shift = 0, mask, ret; | 314 | int reg, shift = 0, mask, ret, j; |
315 | int j, previous_sel; | ||
316 | static u8 buck1_last_val; | 315 | static u8 buck1_last_val; |
317 | 316 | ||
318 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); | 317 | ret = max8998_get_voltage_register(rdev, ®, &shift, &mask); |
319 | if (ret) | 318 | if (ret) |
320 | return ret; | 319 | return ret; |
321 | 320 | ||
322 | previous_sel = max8998_get_voltage_sel(rdev); | ||
323 | |||
324 | /* Check if voltage needs to be changed */ | ||
325 | /* if previous_voltage equal new voltage, return */ | ||
326 | if (previous_sel == selector) { | ||
327 | dev_dbg(max8998->dev, "No voltage change, old:%d, new:%d\n", | ||
328 | regulator_list_voltage_linear(rdev, previous_sel), | ||
329 | regulator_list_voltage_linear(rdev, selector)); | ||
330 | return ret; | ||
331 | } | ||
332 | |||
333 | switch (buck) { | 321 | switch (buck) { |
334 | case MAX8998_BUCK1: | 322 | case MAX8998_BUCK1: |
335 | dev_dbg(max8998->dev, | 323 | dev_dbg(max8998->dev, |
@@ -445,9 +433,9 @@ static int max8998_set_voltage_buck_time_sel(struct regulator_dev *rdev, | |||
445 | if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) | 433 | if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP)) |
446 | return 0; | 434 | return 0; |
447 | 435 | ||
448 | difference = (new_selector - old_selector) * desc->step; | 436 | difference = (new_selector - old_selector) * desc->step / 1000; |
449 | if (difference > 0) | 437 | if (difference > 0) |
450 | return difference / ((val & 0x0f) + 1); | 438 | return DIV_ROUND_UP(difference, (val & 0x0f) + 1); |
451 | 439 | ||
452 | return 0; | 440 | return 0; |
453 | } | 441 | } |
@@ -702,7 +690,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
702 | i = 0; | 690 | i = 0; |
703 | while (buck12_voltage_map_desc.min + | 691 | while (buck12_voltage_map_desc.min + |
704 | buck12_voltage_map_desc.step*i | 692 | buck12_voltage_map_desc.step*i |
705 | < (pdata->buck1_voltage1 / 1000)) | 693 | < pdata->buck1_voltage1) |
706 | i++; | 694 | i++; |
707 | max8998->buck1_vol[0] = i; | 695 | max8998->buck1_vol[0] = i; |
708 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); | 696 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i); |
@@ -713,7 +701,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
713 | i = 0; | 701 | i = 0; |
714 | while (buck12_voltage_map_desc.min + | 702 | while (buck12_voltage_map_desc.min + |
715 | buck12_voltage_map_desc.step*i | 703 | buck12_voltage_map_desc.step*i |
716 | < (pdata->buck1_voltage2 / 1000)) | 704 | < pdata->buck1_voltage2) |
717 | i++; | 705 | i++; |
718 | 706 | ||
719 | max8998->buck1_vol[1] = i; | 707 | max8998->buck1_vol[1] = i; |
@@ -725,7 +713,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
725 | i = 0; | 713 | i = 0; |
726 | while (buck12_voltage_map_desc.min + | 714 | while (buck12_voltage_map_desc.min + |
727 | buck12_voltage_map_desc.step*i | 715 | buck12_voltage_map_desc.step*i |
728 | < (pdata->buck1_voltage3 / 1000)) | 716 | < pdata->buck1_voltage3) |
729 | i++; | 717 | i++; |
730 | 718 | ||
731 | max8998->buck1_vol[2] = i; | 719 | max8998->buck1_vol[2] = i; |
@@ -737,7 +725,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
737 | i = 0; | 725 | i = 0; |
738 | while (buck12_voltage_map_desc.min + | 726 | while (buck12_voltage_map_desc.min + |
739 | buck12_voltage_map_desc.step*i | 727 | buck12_voltage_map_desc.step*i |
740 | < (pdata->buck1_voltage4 / 1000)) | 728 | < pdata->buck1_voltage4) |
741 | i++; | 729 | i++; |
742 | 730 | ||
743 | max8998->buck1_vol[3] = i; | 731 | max8998->buck1_vol[3] = i; |
@@ -763,7 +751,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
763 | i = 0; | 751 | i = 0; |
764 | while (buck12_voltage_map_desc.min + | 752 | while (buck12_voltage_map_desc.min + |
765 | buck12_voltage_map_desc.step*i | 753 | buck12_voltage_map_desc.step*i |
766 | < (pdata->buck2_voltage1 / 1000)) | 754 | < pdata->buck2_voltage1) |
767 | i++; | 755 | i++; |
768 | max8998->buck2_vol[0] = i; | 756 | max8998->buck2_vol[0] = i; |
769 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); | 757 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i); |
@@ -774,7 +762,7 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
774 | i = 0; | 762 | i = 0; |
775 | while (buck12_voltage_map_desc.min + | 763 | while (buck12_voltage_map_desc.min + |
776 | buck12_voltage_map_desc.step*i | 764 | buck12_voltage_map_desc.step*i |
777 | < (pdata->buck2_voltage2 / 1000)) | 765 | < pdata->buck2_voltage2) |
778 | i++; | 766 | i++; |
779 | max8998->buck2_vol[1] = i; | 767 | max8998->buck2_vol[1] = i; |
780 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); | 768 | ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i); |
@@ -792,8 +780,8 @@ static int max8998_pmic_probe(struct platform_device *pdev) | |||
792 | int count = (desc->max - desc->min) / desc->step + 1; | 780 | int count = (desc->max - desc->min) / desc->step + 1; |
793 | 781 | ||
794 | regulators[index].n_voltages = count; | 782 | regulators[index].n_voltages = count; |
795 | regulators[index].min_uV = desc->min * 1000; | 783 | regulators[index].min_uV = desc->min; |
796 | regulators[index].uV_step = desc->step * 1000; | 784 | regulators[index].uV_step = desc->step; |
797 | } | 785 | } |
798 | 786 | ||
799 | config.dev = max8998->dev; | 787 | config.dev = max8998->dev; |
diff --git a/drivers/regulator/mc13892-regulator.c b/drivers/regulator/mc13892-regulator.c index 0d84b1f33199..9891aec47b57 100644 --- a/drivers/regulator/mc13892-regulator.c +++ b/drivers/regulator/mc13892-regulator.c | |||
@@ -164,6 +164,14 @@ static const unsigned int mc13892_sw1[] = { | |||
164 | 1350000, 1375000 | 164 | 1350000, 1375000 |
165 | }; | 165 | }; |
166 | 166 | ||
167 | /* | ||
168 | * Note: this table is used to derive SWxVSEL by index into | ||
169 | * the array. Offset the values by the index of 1100000uV | ||
170 | * to get the actual register value for that voltage selector | ||
171 | * if the HI bit is to be set as well. | ||
172 | */ | ||
173 | #define MC13892_SWxHI_SEL_OFFSET 20 | ||
174 | |||
167 | static const unsigned int mc13892_sw[] = { | 175 | static const unsigned int mc13892_sw[] = { |
168 | 600000, 625000, 650000, 675000, 700000, 725000, | 176 | 600000, 625000, 650000, 675000, 700000, 725000, |
169 | 750000, 775000, 800000, 825000, 850000, 875000, | 177 | 750000, 775000, 800000, 825000, 850000, 875000, |
@@ -239,7 +247,6 @@ static const unsigned int mc13892_pwgtdrv[] = { | |||
239 | }; | 247 | }; |
240 | 248 | ||
241 | static struct regulator_ops mc13892_gpo_regulator_ops; | 249 | static struct regulator_ops mc13892_gpo_regulator_ops; |
242 | /* sw regulators need special care due to the "hi bit" */ | ||
243 | static struct regulator_ops mc13892_sw_regulator_ops; | 250 | static struct regulator_ops mc13892_sw_regulator_ops; |
244 | 251 | ||
245 | 252 | ||
@@ -396,7 +403,7 @@ static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) | |||
396 | { | 403 | { |
397 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); | 404 | struct mc13xxx_regulator_priv *priv = rdev_get_drvdata(rdev); |
398 | int ret, id = rdev_get_id(rdev); | 405 | int ret, id = rdev_get_id(rdev); |
399 | unsigned int val; | 406 | unsigned int val, selector; |
400 | 407 | ||
401 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); | 408 | dev_dbg(rdev_get_dev(rdev), "%s id: %d\n", __func__, id); |
402 | 409 | ||
@@ -407,12 +414,28 @@ static int mc13892_sw_regulator_get_voltage_sel(struct regulator_dev *rdev) | |||
407 | if (ret) | 414 | if (ret) |
408 | return ret; | 415 | return ret; |
409 | 416 | ||
410 | val = (val & mc13892_regulators[id].vsel_mask) | 417 | /* |
411 | >> mc13892_regulators[id].vsel_shift; | 418 | * Figure out if the HI bit is set inside the switcher mode register |
419 | * since this means the selector value we return is at a different | ||
420 | * offset into the selector table. | ||
421 | * | ||
422 | * According to the MC13892 documentation note 59 (Table 47) the SW1 | ||
423 | * buck switcher does not support output range programming therefore | ||
424 | * the HI bit must always remain 0. So do not do anything strange if | ||
425 | * our register is MC13892_SWITCHERS0. | ||
426 | */ | ||
427 | |||
428 | selector = val & mc13892_regulators[id].vsel_mask; | ||
429 | |||
430 | if ((mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) && | ||
431 | (val & MC13892_SWITCHERS0_SWxHI)) { | ||
432 | selector += MC13892_SWxHI_SEL_OFFSET; | ||
433 | } | ||
412 | 434 | ||
413 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: %d\n", __func__, id, val); | 435 | dev_dbg(rdev_get_dev(rdev), "%s id: %d val: 0x%08x selector: %d\n", |
436 | __func__, id, val, selector); | ||
414 | 437 | ||
415 | return val; | 438 | return selector; |
416 | } | 439 | } |
417 | 440 | ||
418 | static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, | 441 | static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, |
@@ -425,18 +448,35 @@ static int mc13892_sw_regulator_set_voltage_sel(struct regulator_dev *rdev, | |||
425 | 448 | ||
426 | volt = rdev->desc->volt_table[selector]; | 449 | volt = rdev->desc->volt_table[selector]; |
427 | mask = mc13892_regulators[id].vsel_mask; | 450 | mask = mc13892_regulators[id].vsel_mask; |
428 | reg_value = selector << mc13892_regulators[id].vsel_shift; | 451 | reg_value = selector; |
429 | 452 | ||
430 | if (volt > 1375000) { | 453 | /* |
431 | mask |= MC13892_SWITCHERS0_SWxHI; | 454 | * Don't mess with the HI bit or support HI voltage offsets for SW1. |
432 | reg_value |= MC13892_SWITCHERS0_SWxHI; | 455 | * |
433 | } else if (volt < 1100000) { | 456 | * Since the get_voltage_sel callback has given a fudged value for |
434 | mask |= MC13892_SWITCHERS0_SWxHI; | 457 | * the selector offset, we need to back out that offset if HI is |
435 | reg_value &= ~MC13892_SWITCHERS0_SWxHI; | 458 | * to be set so we write the correct value to the register. |
459 | * | ||
460 | * The HI bit addition and selector offset handling COULD be more | ||
461 | * complicated by shifting and masking off the voltage selector part | ||
462 | * of the register then logical OR it back in, but since the selector | ||
463 | * is at bits 4:0 there is very little point. This makes the whole | ||
464 | * thing more readable and we do far less work. | ||
465 | */ | ||
466 | |||
467 | if (mc13892_regulators[id].vsel_reg != MC13892_SWITCHERS0) { | ||
468 | if (volt > 1375000) { | ||
469 | reg_value -= MC13892_SWxHI_SEL_OFFSET; | ||
470 | reg_value |= MC13892_SWITCHERS0_SWxHI; | ||
471 | mask |= MC13892_SWITCHERS0_SWxHI; | ||
472 | } else if (volt < 1100000) { | ||
473 | reg_value &= ~MC13892_SWITCHERS0_SWxHI; | ||
474 | mask |= MC13892_SWITCHERS0_SWxHI; | ||
475 | } | ||
436 | } | 476 | } |
437 | 477 | ||
438 | mc13xxx_lock(priv->mc13xxx); | 478 | mc13xxx_lock(priv->mc13xxx); |
439 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].reg, mask, | 479 | ret = mc13xxx_reg_rmw(priv->mc13xxx, mc13892_regulators[id].vsel_reg, mask, |
440 | reg_value); | 480 | reg_value); |
441 | mc13xxx_unlock(priv->mc13xxx); | 481 | mc13xxx_unlock(priv->mc13xxx); |
442 | 482 | ||
@@ -495,15 +535,18 @@ static int mc13892_regulator_probe(struct platform_device *pdev) | |||
495 | struct mc13xxx_regulator_init_data *mc13xxx_data; | 535 | struct mc13xxx_regulator_init_data *mc13xxx_data; |
496 | struct regulator_config config = { }; | 536 | struct regulator_config config = { }; |
497 | int i, ret; | 537 | int i, ret; |
498 | int num_regulators = 0; | 538 | int num_regulators = 0, num_parsed; |
499 | u32 val; | 539 | u32 val; |
500 | 540 | ||
501 | num_regulators = mc13xxx_get_num_regulators_dt(pdev); | 541 | num_regulators = mc13xxx_get_num_regulators_dt(pdev); |
542 | |||
502 | if (num_regulators <= 0 && pdata) | 543 | if (num_regulators <= 0 && pdata) |
503 | num_regulators = pdata->num_regulators; | 544 | num_regulators = pdata->num_regulators; |
504 | if (num_regulators <= 0) | 545 | if (num_regulators <= 0) |
505 | return -EINVAL; | 546 | return -EINVAL; |
506 | 547 | ||
548 | num_parsed = num_regulators; | ||
549 | |||
507 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + | 550 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv) + |
508 | num_regulators * sizeof(priv->regulators[0]), | 551 | num_regulators * sizeof(priv->regulators[0]), |
509 | GFP_KERNEL); | 552 | GFP_KERNEL); |
@@ -520,7 +563,7 @@ static int mc13892_regulator_probe(struct platform_device *pdev) | |||
520 | if (ret) | 563 | if (ret) |
521 | goto err_unlock; | 564 | goto err_unlock; |
522 | 565 | ||
523 | /* enable switch auto mode */ | 566 | /* enable switch auto mode (on 2.0A silicon only) */ |
524 | if ((val & 0x0000FFFF) == 0x45d0) { | 567 | if ((val & 0x0000FFFF) == 0x45d0) { |
525 | ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4, | 568 | ret = mc13xxx_reg_rmw(mc13892, MC13892_SWITCHERS4, |
526 | MC13892_SWITCHERS4_SW1MODE_M | | 569 | MC13892_SWITCHERS4_SW1MODE_M | |
@@ -546,7 +589,39 @@ static int mc13892_regulator_probe(struct platform_device *pdev) | |||
546 | = mc13892_vcam_get_mode; | 589 | = mc13892_vcam_get_mode; |
547 | 590 | ||
548 | mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, | 591 | mc13xxx_data = mc13xxx_parse_regulators_dt(pdev, mc13892_regulators, |
549 | ARRAY_SIZE(mc13892_regulators)); | 592 | ARRAY_SIZE(mc13892_regulators), |
593 | &num_parsed); | ||
594 | |||
595 | /* | ||
596 | * Perform a little sanity check on the regulator tree - if we found | ||
597 | * a number of regulators from mc13xxx_get_num_regulators_dt and | ||
598 | * then parsed a smaller number in mc13xxx_parse_regulators_dt then | ||
599 | * there is a regulator defined in the regulators node which has | ||
600 | * not matched any usable regulator in the driver. In this case, | ||
601 | * there is one missing and what will happen is the first regulator | ||
602 | * will get registered again. | ||
603 | * | ||
604 | * Fix this by basically making our number of registerable regulators | ||
605 | * equal to the number of regulators we parsed. We are allocating | ||
606 | * too much memory for priv, but this is unavoidable at this point. | ||
607 | * | ||
608 | * As an example of how this can happen, try making a typo in your | ||
609 | * regulators node (vviohi {} instead of viohi {}) so that the name | ||
610 | * does not match.. | ||
611 | * | ||
612 | * The check will basically pass for platform data (non-DT) because | ||
613 | * mc13xxx_parse_regulators_dt for !CONFIG_OF will not touch num_parsed. | ||
614 | * | ||
615 | */ | ||
616 | if (num_parsed != num_regulators) { | ||
617 | dev_warn(&pdev->dev, | ||
618 | "parsed %d != regulators %d - check your device tree!\n", | ||
619 | num_parsed, num_regulators); | ||
620 | |||
621 | num_regulators = num_parsed; | ||
622 | priv->num_regulators = num_regulators; | ||
623 | } | ||
624 | |||
550 | for (i = 0; i < num_regulators; i++) { | 625 | for (i = 0; i < num_regulators; i++) { |
551 | struct regulator_init_data *init_data; | 626 | struct regulator_init_data *init_data; |
552 | struct regulator_desc *desc; | 627 | struct regulator_desc *desc; |
diff --git a/drivers/regulator/mc13xxx-regulator-core.c b/drivers/regulator/mc13xxx-regulator-core.c index 4ed89c654110..23cf9f9c383b 100644 --- a/drivers/regulator/mc13xxx-regulator-core.c +++ b/drivers/regulator/mc13xxx-regulator-core.c | |||
@@ -164,29 +164,30 @@ EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops); | |||
164 | #ifdef CONFIG_OF | 164 | #ifdef CONFIG_OF |
165 | int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) | 165 | int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) |
166 | { | 166 | { |
167 | struct device_node *parent, *child; | 167 | struct device_node *parent; |
168 | int num = 0; | 168 | int num; |
169 | 169 | ||
170 | of_node_get(pdev->dev.parent->of_node); | 170 | of_node_get(pdev->dev.parent->of_node); |
171 | parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); | 171 | parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); |
172 | if (!parent) | 172 | if (!parent) |
173 | return -ENODEV; | 173 | return -ENODEV; |
174 | 174 | ||
175 | for_each_child_of_node(parent, child) | 175 | num = of_get_child_count(parent); |
176 | num++; | 176 | of_node_put(parent); |
177 | |||
178 | return num; | 177 | return num; |
179 | } | 178 | } |
180 | EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt); | 179 | EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt); |
181 | 180 | ||
182 | struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( | 181 | struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( |
183 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, | 182 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, |
184 | int num_regulators) | 183 | int num_regulators, int *num_parsed) |
185 | { | 184 | { |
186 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); | 185 | struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev); |
187 | struct mc13xxx_regulator_init_data *data, *p; | 186 | struct mc13xxx_regulator_init_data *data, *p; |
188 | struct device_node *parent, *child; | 187 | struct device_node *parent, *child; |
189 | int i; | 188 | int i, parsed = 0; |
189 | |||
190 | *num_parsed = 0; | ||
190 | 191 | ||
191 | of_node_get(pdev->dev.parent->of_node); | 192 | of_node_get(pdev->dev.parent->of_node); |
192 | parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); | 193 | parent = of_find_node_by_name(pdev->dev.parent->of_node, "regulators"); |
@@ -195,24 +196,32 @@ struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( | |||
195 | 196 | ||
196 | data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, | 197 | data = devm_kzalloc(&pdev->dev, sizeof(*data) * priv->num_regulators, |
197 | GFP_KERNEL); | 198 | GFP_KERNEL); |
198 | if (!data) | 199 | if (!data) { |
200 | of_node_put(parent); | ||
199 | return NULL; | 201 | return NULL; |
202 | } | ||
203 | |||
200 | p = data; | 204 | p = data; |
201 | 205 | ||
202 | for_each_child_of_node(parent, child) { | 206 | for_each_child_of_node(parent, child) { |
203 | for (i = 0; i < num_regulators; i++) { | 207 | for (i = 0; i < num_regulators; i++) { |
204 | if (!of_node_cmp(child->name, | 208 | if (!of_node_cmp(child->name, |
205 | regulators[i].desc.name)) { | 209 | regulators[i].desc.name)) { |
210 | |||
206 | p->id = i; | 211 | p->id = i; |
207 | p->init_data = of_get_regulator_init_data( | 212 | p->init_data = of_get_regulator_init_data( |
208 | &pdev->dev, child); | 213 | &pdev->dev, child); |
209 | p->node = child; | 214 | p->node = child; |
210 | p++; | 215 | p++; |
216 | |||
217 | parsed++; | ||
211 | break; | 218 | break; |
212 | } | 219 | } |
213 | } | 220 | } |
214 | } | 221 | } |
222 | of_node_put(parent); | ||
215 | 223 | ||
224 | *num_parsed = parsed; | ||
216 | return data; | 225 | return data; |
217 | } | 226 | } |
218 | EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt); | 227 | EXPORT_SYMBOL_GPL(mc13xxx_parse_regulators_dt); |
diff --git a/drivers/regulator/mc13xxx.h b/drivers/regulator/mc13xxx.h index 06c8903f182a..007f83387fd6 100644 --- a/drivers/regulator/mc13xxx.h +++ b/drivers/regulator/mc13xxx.h | |||
@@ -39,7 +39,7 @@ extern int mc13xxx_fixed_regulator_set_voltage(struct regulator_dev *rdev, | |||
39 | extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev); | 39 | extern int mc13xxx_get_num_regulators_dt(struct platform_device *pdev); |
40 | extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( | 40 | extern struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( |
41 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, | 41 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, |
42 | int num_regulators); | 42 | int num_regulators, int *num_parsed); |
43 | #else | 43 | #else |
44 | static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) | 44 | static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) |
45 | { | 45 | { |
@@ -48,7 +48,7 @@ static inline int mc13xxx_get_num_regulators_dt(struct platform_device *pdev) | |||
48 | 48 | ||
49 | static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( | 49 | static inline struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt( |
50 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, | 50 | struct platform_device *pdev, struct mc13xxx_regulator *regulators, |
51 | int num_regulators) | 51 | int num_regulators, int *num_parsed) |
52 | { | 52 | { |
53 | return NULL; | 53 | return NULL; |
54 | } | 54 | } |
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c index 6f684916fd79..66ca769287ab 100644 --- a/drivers/regulator/of_regulator.c +++ b/drivers/regulator/of_regulator.c | |||
@@ -120,6 +120,12 @@ int of_regulator_match(struct device *dev, struct device_node *node, | |||
120 | if (!dev || !node) | 120 | if (!dev || !node) |
121 | return -EINVAL; | 121 | return -EINVAL; |
122 | 122 | ||
123 | for (i = 0; i < num_matches; i++) { | ||
124 | struct of_regulator_match *match = &matches[i]; | ||
125 | match->init_data = NULL; | ||
126 | match->of_node = NULL; | ||
127 | } | ||
128 | |||
123 | for_each_child_of_node(node, child) { | 129 | for_each_child_of_node(node, child) { |
124 | name = of_get_property(child, | 130 | name = of_get_property(child, |
125 | "regulator-compatible", NULL); | 131 | "regulator-compatible", NULL); |
diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index c9e912f583bc..cde13bb5a8fb 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c | |||
@@ -527,6 +527,7 @@ static void palmas_dt_to_pdata(struct device *dev, | |||
527 | u32 prop; | 527 | u32 prop; |
528 | int idx, ret; | 528 | int idx, ret; |
529 | 529 | ||
530 | node = of_node_get(node); | ||
530 | regulators = of_find_node_by_name(node, "regulators"); | 531 | regulators = of_find_node_by_name(node, "regulators"); |
531 | if (!regulators) { | 532 | if (!regulators) { |
532 | dev_info(dev, "regulator node not found\n"); | 533 | dev_info(dev, "regulator node not found\n"); |
@@ -535,6 +536,7 @@ static void palmas_dt_to_pdata(struct device *dev, | |||
535 | 536 | ||
536 | ret = of_regulator_match(dev, regulators, palmas_matches, | 537 | ret = of_regulator_match(dev, regulators, palmas_matches, |
537 | PALMAS_NUM_REGS); | 538 | PALMAS_NUM_REGS); |
539 | of_node_put(regulators); | ||
538 | if (ret < 0) { | 540 | if (ret < 0) { |
539 | dev_err(dev, "Error parsing regulator init data: %d\n", ret); | 541 | dev_err(dev, "Error parsing regulator init data: %d\n", ret); |
540 | return; | 542 | return; |
@@ -566,11 +568,6 @@ static void palmas_dt_to_pdata(struct device *dev, | |||
566 | pdata->reg_init[idx]->mode_sleep = prop; | 568 | pdata->reg_init[idx]->mode_sleep = prop; |
567 | 569 | ||
568 | ret = of_property_read_u32(palmas_matches[idx].of_node, | 570 | ret = of_property_read_u32(palmas_matches[idx].of_node, |
569 | "ti,warm_reset", &prop); | ||
570 | if (!ret) | ||
571 | pdata->reg_init[idx]->warm_reset = prop; | ||
572 | |||
573 | ret = of_property_read_u32(palmas_matches[idx].of_node, | ||
574 | "ti,tstep", &prop); | 571 | "ti,tstep", &prop); |
575 | if (!ret) | 572 | if (!ret) |
576 | pdata->reg_init[idx]->tstep = prop; | 573 | pdata->reg_init[idx]->tstep = prop; |
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c index bd062a2ffbe2..cd9ea2ea1826 100644 --- a/drivers/regulator/s2mps11.c +++ b/drivers/regulator/s2mps11.c | |||
@@ -174,9 +174,9 @@ static struct regulator_ops s2mps11_buck_ops = { | |||
174 | .min_uV = S2MPS11_BUCK_MIN2, \ | 174 | .min_uV = S2MPS11_BUCK_MIN2, \ |
175 | .uV_step = S2MPS11_BUCK_STEP2, \ | 175 | .uV_step = S2MPS11_BUCK_STEP2, \ |
176 | .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ | 176 | .n_voltages = S2MPS11_BUCK_N_VOLTAGES, \ |
177 | .vsel_reg = S2MPS11_REG_B9CTRL2, \ | 177 | .vsel_reg = S2MPS11_REG_B10CTRL2, \ |
178 | .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ | 178 | .vsel_mask = S2MPS11_BUCK_VSEL_MASK, \ |
179 | .enable_reg = S2MPS11_REG_B9CTRL1, \ | 179 | .enable_reg = S2MPS11_REG_B10CTRL1, \ |
180 | .enable_mask = S2MPS11_ENABLE_MASK \ | 180 | .enable_mask = S2MPS11_ENABLE_MASK \ |
181 | } | 181 | } |
182 | 182 | ||
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index 9f991f2c525a..8a831947c351 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/bug.h> | 14 | #include <linux/bug.h> |
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/gpio.h> | 16 | #include <linux/gpio.h> |
17 | #include <linux/of_gpio.h> | ||
17 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
18 | #include <linux/module.h> | 19 | #include <linux/module.h> |
19 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
@@ -21,6 +22,9 @@ | |||
21 | #include <linux/regulator/machine.h> | 22 | #include <linux/regulator/machine.h> |
22 | #include <linux/mfd/samsung/core.h> | 23 | #include <linux/mfd/samsung/core.h> |
23 | #include <linux/mfd/samsung/s5m8767.h> | 24 | #include <linux/mfd/samsung/s5m8767.h> |
25 | #include <linux/regulator/of_regulator.h> | ||
26 | |||
27 | #define S5M8767_OPMODE_NORMAL_MODE 0x1 | ||
24 | 28 | ||
25 | struct s5m8767_info { | 29 | struct s5m8767_info { |
26 | struct device *dev; | 30 | struct device *dev; |
@@ -214,7 +218,7 @@ static int s5m8767_reg_is_enabled(struct regulator_dev *rdev) | |||
214 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | 218 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); |
215 | int ret, reg; | 219 | int ret, reg; |
216 | int mask = 0xc0, enable_ctrl; | 220 | int mask = 0xc0, enable_ctrl; |
217 | u8 val; | 221 | unsigned int val; |
218 | 222 | ||
219 | ret = s5m8767_get_register(rdev, ®, &enable_ctrl); | 223 | ret = s5m8767_get_register(rdev, ®, &enable_ctrl); |
220 | if (ret == -EINVAL) | 224 | if (ret == -EINVAL) |
@@ -255,10 +259,8 @@ static int s5m8767_reg_disable(struct regulator_dev *rdev) | |||
255 | return sec_reg_update(s5m8767->iodev, reg, ~mask, mask); | 259 | return sec_reg_update(s5m8767->iodev, reg, ~mask, mask); |
256 | } | 260 | } |
257 | 261 | ||
258 | static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg) | 262 | static int s5m8767_get_vsel_reg(int reg_id, struct s5m8767_info *s5m8767) |
259 | { | 263 | { |
260 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | ||
261 | int reg_id = rdev_get_id(rdev); | ||
262 | int reg; | 264 | int reg; |
263 | 265 | ||
264 | switch (reg_id) { | 266 | switch (reg_id) { |
@@ -296,43 +298,18 @@ static int s5m8767_get_voltage_register(struct regulator_dev *rdev, int *_reg) | |||
296 | return -EINVAL; | 298 | return -EINVAL; |
297 | } | 299 | } |
298 | 300 | ||
299 | *_reg = reg; | 301 | return reg; |
300 | |||
301 | return 0; | ||
302 | } | 302 | } |
303 | 303 | ||
304 | static int s5m8767_get_voltage_sel(struct regulator_dev *rdev) | 304 | static int s5m8767_convert_voltage_to_sel(const struct sec_voltage_desc *desc, |
305 | { | 305 | int min_vol) |
306 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | ||
307 | int reg, mask, ret; | ||
308 | int reg_id = rdev_get_id(rdev); | ||
309 | u8 val; | ||
310 | |||
311 | ret = s5m8767_get_voltage_register(rdev, ®); | ||
312 | if (ret) | ||
313 | return ret; | ||
314 | |||
315 | mask = (reg_id < S5M8767_BUCK1) ? 0x3f : 0xff; | ||
316 | |||
317 | ret = sec_reg_read(s5m8767->iodev, reg, &val); | ||
318 | if (ret) | ||
319 | return ret; | ||
320 | |||
321 | val &= mask; | ||
322 | |||
323 | return val; | ||
324 | } | ||
325 | |||
326 | static int s5m8767_convert_voltage_to_sel( | ||
327 | const struct sec_voltage_desc *desc, | ||
328 | int min_vol, int max_vol) | ||
329 | { | 306 | { |
330 | int selector = 0; | 307 | int selector = 0; |
331 | 308 | ||
332 | if (desc == NULL) | 309 | if (desc == NULL) |
333 | return -EINVAL; | 310 | return -EINVAL; |
334 | 311 | ||
335 | if (max_vol < desc->min || min_vol > desc->max) | 312 | if (min_vol > desc->max) |
336 | return -EINVAL; | 313 | return -EINVAL; |
337 | 314 | ||
338 | if (min_vol < desc->min) | 315 | if (min_vol < desc->min) |
@@ -340,7 +317,7 @@ static int s5m8767_convert_voltage_to_sel( | |||
340 | 317 | ||
341 | selector = DIV_ROUND_UP(min_vol - desc->min, desc->step); | 318 | selector = DIV_ROUND_UP(min_vol - desc->min, desc->step); |
342 | 319 | ||
343 | if (desc->min + desc->step * selector > max_vol) | 320 | if (desc->min + desc->step * selector > desc->max) |
344 | return -EINVAL; | 321 | return -EINVAL; |
345 | 322 | ||
346 | return selector; | 323 | return selector; |
@@ -373,15 +350,13 @@ static int s5m8767_set_voltage_sel(struct regulator_dev *rdev, | |||
373 | { | 350 | { |
374 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); | 351 | struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); |
375 | int reg_id = rdev_get_id(rdev); | 352 | int reg_id = rdev_get_id(rdev); |
376 | int reg, mask, ret = 0, old_index, index = 0; | 353 | int old_index, index = 0; |
377 | u8 *buck234_vol = NULL; | 354 | u8 *buck234_vol = NULL; |
378 | 355 | ||
379 | switch (reg_id) { | 356 | switch (reg_id) { |
380 | case S5M8767_LDO1 ... S5M8767_LDO28: | 357 | case S5M8767_LDO1 ... S5M8767_LDO28: |
381 | mask = 0x3f; | ||
382 | break; | 358 | break; |
383 | case S5M8767_BUCK1 ... S5M8767_BUCK6: | 359 | case S5M8767_BUCK1 ... S5M8767_BUCK6: |
384 | mask = 0xff; | ||
385 | if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs) | 360 | if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs) |
386 | buck234_vol = &s5m8767->buck2_vol[0]; | 361 | buck234_vol = &s5m8767->buck2_vol[0]; |
387 | else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs) | 362 | else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs) |
@@ -392,7 +367,6 @@ static int s5m8767_set_voltage_sel(struct regulator_dev *rdev, | |||
392 | case S5M8767_BUCK7 ... S5M8767_BUCK8: | 367 | case S5M8767_BUCK7 ... S5M8767_BUCK8: |
393 | return -EINVAL; | 368 | return -EINVAL; |
394 | case S5M8767_BUCK9: | 369 | case S5M8767_BUCK9: |
395 | mask = 0xff; | ||
396 | break; | 370 | break; |
397 | default: | 371 | default: |
398 | return -EINVAL; | 372 | return -EINVAL; |
@@ -412,11 +386,7 @@ static int s5m8767_set_voltage_sel(struct regulator_dev *rdev, | |||
412 | else | 386 | else |
413 | return s5m8767_set_low(s5m8767); | 387 | return s5m8767_set_low(s5m8767); |
414 | } else { | 388 | } else { |
415 | ret = s5m8767_get_voltage_register(rdev, ®); | 389 | return regulator_set_voltage_sel_regmap(rdev, selector); |
416 | if (ret) | ||
417 | return ret; | ||
418 | |||
419 | return sec_reg_update(s5m8767->iodev, reg, selector, mask); | ||
420 | } | 390 | } |
421 | } | 391 | } |
422 | 392 | ||
@@ -441,7 +411,7 @@ static struct regulator_ops s5m8767_ops = { | |||
441 | .is_enabled = s5m8767_reg_is_enabled, | 411 | .is_enabled = s5m8767_reg_is_enabled, |
442 | .enable = s5m8767_reg_enable, | 412 | .enable = s5m8767_reg_enable, |
443 | .disable = s5m8767_reg_disable, | 413 | .disable = s5m8767_reg_disable, |
444 | .get_voltage_sel = s5m8767_get_voltage_sel, | 414 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
445 | .set_voltage_sel = s5m8767_set_voltage_sel, | 415 | .set_voltage_sel = s5m8767_set_voltage_sel, |
446 | .set_voltage_time_sel = s5m8767_set_voltage_time_sel, | 416 | .set_voltage_time_sel = s5m8767_set_voltage_time_sel, |
447 | }; | 417 | }; |
@@ -508,10 +478,182 @@ static struct regulator_desc regulators[] = { | |||
508 | s5m8767_regulator_desc(BUCK9), | 478 | s5m8767_regulator_desc(BUCK9), |
509 | }; | 479 | }; |
510 | 480 | ||
481 | #ifdef CONFIG_OF | ||
482 | static int s5m8767_pmic_dt_parse_dvs_gpio(struct sec_pmic_dev *iodev, | ||
483 | struct sec_platform_data *pdata, | ||
484 | struct device_node *pmic_np) | ||
485 | { | ||
486 | int i, gpio; | ||
487 | |||
488 | for (i = 0; i < 3; i++) { | ||
489 | gpio = of_get_named_gpio(pmic_np, | ||
490 | "s5m8767,pmic-buck-dvs-gpios", i); | ||
491 | if (!gpio_is_valid(gpio)) { | ||
492 | dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); | ||
493 | return -EINVAL; | ||
494 | } | ||
495 | pdata->buck_gpios[i] = gpio; | ||
496 | } | ||
497 | return 0; | ||
498 | } | ||
499 | |||
500 | static int s5m8767_pmic_dt_parse_ds_gpio(struct sec_pmic_dev *iodev, | ||
501 | struct sec_platform_data *pdata, | ||
502 | struct device_node *pmic_np) | ||
503 | { | ||
504 | int i, gpio; | ||
505 | |||
506 | for (i = 0; i < 3; i++) { | ||
507 | gpio = of_get_named_gpio(pmic_np, | ||
508 | "s5m8767,pmic-buck-ds-gpios", i); | ||
509 | if (!gpio_is_valid(gpio)) { | ||
510 | dev_err(iodev->dev, "invalid gpio[%d]: %d\n", i, gpio); | ||
511 | return -EINVAL; | ||
512 | } | ||
513 | pdata->buck_ds[i] = gpio; | ||
514 | } | ||
515 | return 0; | ||
516 | } | ||
517 | |||
518 | static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, | ||
519 | struct sec_platform_data *pdata) | ||
520 | { | ||
521 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); | ||
522 | struct device_node *pmic_np, *regulators_np, *reg_np; | ||
523 | struct sec_regulator_data *rdata; | ||
524 | struct sec_opmode_data *rmode; | ||
525 | unsigned int i, dvs_voltage_nr = 1, ret; | ||
526 | |||
527 | pmic_np = iodev->dev->of_node; | ||
528 | if (!pmic_np) { | ||
529 | dev_err(iodev->dev, "could not find pmic sub-node\n"); | ||
530 | return -ENODEV; | ||
531 | } | ||
532 | |||
533 | regulators_np = of_find_node_by_name(pmic_np, "regulators"); | ||
534 | if (!regulators_np) { | ||
535 | dev_err(iodev->dev, "could not find regulators sub-node\n"); | ||
536 | return -EINVAL; | ||
537 | } | ||
538 | |||
539 | /* count the number of regulators to be supported in pmic */ | ||
540 | pdata->num_regulators = of_get_child_count(regulators_np); | ||
541 | |||
542 | rdata = devm_kzalloc(&pdev->dev, sizeof(*rdata) * | ||
543 | pdata->num_regulators, GFP_KERNEL); | ||
544 | if (!rdata) { | ||
545 | dev_err(iodev->dev, | ||
546 | "could not allocate memory for regulator data\n"); | ||
547 | return -ENOMEM; | ||
548 | } | ||
549 | |||
550 | rmode = devm_kzalloc(&pdev->dev, sizeof(*rmode) * | ||
551 | pdata->num_regulators, GFP_KERNEL); | ||
552 | if (!rdata) { | ||
553 | dev_err(iodev->dev, | ||
554 | "could not allocate memory for regulator mode\n"); | ||
555 | return -ENOMEM; | ||
556 | } | ||
557 | |||
558 | pdata->regulators = rdata; | ||
559 | pdata->opmode = rmode; | ||
560 | for_each_child_of_node(regulators_np, reg_np) { | ||
561 | for (i = 0; i < ARRAY_SIZE(regulators); i++) | ||
562 | if (!of_node_cmp(reg_np->name, regulators[i].name)) | ||
563 | break; | ||
564 | |||
565 | if (i == ARRAY_SIZE(regulators)) { | ||
566 | dev_warn(iodev->dev, | ||
567 | "don't know how to configure regulator %s\n", | ||
568 | reg_np->name); | ||
569 | continue; | ||
570 | } | ||
571 | |||
572 | rdata->id = i; | ||
573 | rdata->initdata = of_get_regulator_init_data( | ||
574 | &pdev->dev, reg_np); | ||
575 | rdata->reg_node = reg_np; | ||
576 | rdata++; | ||
577 | rmode->id = i; | ||
578 | if (of_property_read_u32(reg_np, "op_mode", | ||
579 | &rmode->mode)) { | ||
580 | dev_warn(iodev->dev, | ||
581 | "no op_mode property property at %s\n", | ||
582 | reg_np->full_name); | ||
583 | |||
584 | rmode->mode = S5M8767_OPMODE_NORMAL_MODE; | ||
585 | } | ||
586 | rmode++; | ||
587 | } | ||
588 | |||
589 | if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) | ||
590 | pdata->buck2_gpiodvs = true; | ||
591 | |||
592 | if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL)) | ||
593 | pdata->buck3_gpiodvs = true; | ||
594 | |||
595 | if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL)) | ||
596 | pdata->buck4_gpiodvs = true; | ||
597 | |||
598 | if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs || | ||
599 | pdata->buck4_gpiodvs) { | ||
600 | ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np); | ||
601 | if (ret) | ||
602 | return -EINVAL; | ||
603 | |||
604 | if (of_property_read_u32(pmic_np, | ||
605 | "s5m8767,pmic-buck-default-dvs-idx", | ||
606 | &pdata->buck_default_idx)) { | ||
607 | pdata->buck_default_idx = 0; | ||
608 | } else { | ||
609 | if (pdata->buck_default_idx >= 8) { | ||
610 | pdata->buck_default_idx = 0; | ||
611 | dev_info(iodev->dev, | ||
612 | "invalid value for default dvs index, use 0\n"); | ||
613 | } | ||
614 | } | ||
615 | dvs_voltage_nr = 8; | ||
616 | } | ||
617 | |||
618 | ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np); | ||
619 | if (ret) | ||
620 | return -EINVAL; | ||
621 | |||
622 | if (of_property_read_u32_array(pmic_np, | ||
623 | "s5m8767,pmic-buck2-dvs-voltage", | ||
624 | pdata->buck2_voltage, dvs_voltage_nr)) { | ||
625 | dev_err(iodev->dev, "buck2 voltages not specified\n"); | ||
626 | return -EINVAL; | ||
627 | } | ||
628 | |||
629 | if (of_property_read_u32_array(pmic_np, | ||
630 | "s5m8767,pmic-buck3-dvs-voltage", | ||
631 | pdata->buck3_voltage, dvs_voltage_nr)) { | ||
632 | dev_err(iodev->dev, "buck3 voltages not specified\n"); | ||
633 | return -EINVAL; | ||
634 | } | ||
635 | |||
636 | if (of_property_read_u32_array(pmic_np, | ||
637 | "s5m8767,pmic-buck4-dvs-voltage", | ||
638 | pdata->buck4_voltage, dvs_voltage_nr)) { | ||
639 | dev_err(iodev->dev, "buck4 voltages not specified\n"); | ||
640 | return -EINVAL; | ||
641 | } | ||
642 | |||
643 | return 0; | ||
644 | } | ||
645 | #else | ||
646 | static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev, | ||
647 | struct sec_platform_data *pdata) | ||
648 | { | ||
649 | return 0; | ||
650 | } | ||
651 | #endif /* CONFIG_OF */ | ||
652 | |||
511 | static int s5m8767_pmic_probe(struct platform_device *pdev) | 653 | static int s5m8767_pmic_probe(struct platform_device *pdev) |
512 | { | 654 | { |
513 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); | 655 | struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent); |
514 | struct sec_platform_data *pdata = dev_get_platdata(iodev->dev); | 656 | struct sec_platform_data *pdata = iodev->pdata; |
515 | struct regulator_config config = { }; | 657 | struct regulator_config config = { }; |
516 | struct regulator_dev **rdev; | 658 | struct regulator_dev **rdev; |
517 | struct s5m8767_info *s5m8767; | 659 | struct s5m8767_info *s5m8767; |
@@ -522,6 +664,12 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
522 | return -ENODEV; | 664 | return -ENODEV; |
523 | } | 665 | } |
524 | 666 | ||
667 | if (iodev->dev->of_node) { | ||
668 | ret = s5m8767_pmic_dt_parse_pdata(pdev, pdata); | ||
669 | if (ret) | ||
670 | return ret; | ||
671 | } | ||
672 | |||
525 | if (pdata->buck2_gpiodvs) { | 673 | if (pdata->buck2_gpiodvs) { |
526 | if (pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) { | 674 | if (pdata->buck3_gpiodvs || pdata->buck4_gpiodvs) { |
527 | dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n"); | 675 | dev_err(&pdev->dev, "S5M8767 GPIO DVS NOT VALID\n"); |
@@ -577,23 +725,17 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
577 | s5m8767->opmode = pdata->opmode; | 725 | s5m8767->opmode = pdata->opmode; |
578 | 726 | ||
579 | buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, | 727 | buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, |
580 | pdata->buck2_init, | 728 | pdata->buck2_init); |
581 | pdata->buck2_init + | ||
582 | buck_voltage_val2.step); | ||
583 | 729 | ||
584 | sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init); | 730 | sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK2DVS2, buck_init); |
585 | 731 | ||
586 | buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, | 732 | buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, |
587 | pdata->buck3_init, | 733 | pdata->buck3_init); |
588 | pdata->buck3_init + | ||
589 | buck_voltage_val2.step); | ||
590 | 734 | ||
591 | sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init); | 735 | sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK3DVS2, buck_init); |
592 | 736 | ||
593 | buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, | 737 | buck_init = s5m8767_convert_voltage_to_sel(&buck_voltage_val2, |
594 | pdata->buck4_init, | 738 | pdata->buck4_init); |
595 | pdata->buck4_init + | ||
596 | buck_voltage_val2.step); | ||
597 | 739 | ||
598 | sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init); | 740 | sec_reg_write(s5m8767->iodev, S5M8767_REG_BUCK4DVS2, buck_init); |
599 | 741 | ||
@@ -602,27 +744,21 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
602 | s5m8767->buck2_vol[i] = | 744 | s5m8767->buck2_vol[i] = |
603 | s5m8767_convert_voltage_to_sel( | 745 | s5m8767_convert_voltage_to_sel( |
604 | &buck_voltage_val2, | 746 | &buck_voltage_val2, |
605 | pdata->buck2_voltage[i], | 747 | pdata->buck2_voltage[i]); |
606 | pdata->buck2_voltage[i] + | ||
607 | buck_voltage_val2.step); | ||
608 | } | 748 | } |
609 | 749 | ||
610 | if (s5m8767->buck3_gpiodvs) { | 750 | if (s5m8767->buck3_gpiodvs) { |
611 | s5m8767->buck3_vol[i] = | 751 | s5m8767->buck3_vol[i] = |
612 | s5m8767_convert_voltage_to_sel( | 752 | s5m8767_convert_voltage_to_sel( |
613 | &buck_voltage_val2, | 753 | &buck_voltage_val2, |
614 | pdata->buck3_voltage[i], | 754 | pdata->buck3_voltage[i]); |
615 | pdata->buck3_voltage[i] + | ||
616 | buck_voltage_val2.step); | ||
617 | } | 755 | } |
618 | 756 | ||
619 | if (s5m8767->buck4_gpiodvs) { | 757 | if (s5m8767->buck4_gpiodvs) { |
620 | s5m8767->buck4_vol[i] = | 758 | s5m8767->buck4_vol[i] = |
621 | s5m8767_convert_voltage_to_sel( | 759 | s5m8767_convert_voltage_to_sel( |
622 | &buck_voltage_val2, | 760 | &buck_voltage_val2, |
623 | pdata->buck4_voltage[i], | 761 | pdata->buck4_voltage[i]); |
624 | pdata->buck4_voltage[i] + | ||
625 | buck_voltage_val2.step); | ||
626 | } | 762 | } |
627 | } | 763 | } |
628 | 764 | ||
@@ -760,11 +896,19 @@ static int s5m8767_pmic_probe(struct platform_device *pdev) | |||
760 | (desc->max - desc->min) / desc->step + 1; | 896 | (desc->max - desc->min) / desc->step + 1; |
761 | regulators[id].min_uV = desc->min; | 897 | regulators[id].min_uV = desc->min; |
762 | regulators[id].uV_step = desc->step; | 898 | regulators[id].uV_step = desc->step; |
899 | regulators[id].vsel_reg = | ||
900 | s5m8767_get_vsel_reg(id, s5m8767); | ||
901 | if (id < S5M8767_BUCK1) | ||
902 | regulators[id].vsel_mask = 0x3f; | ||
903 | else | ||
904 | regulators[id].vsel_mask = 0xff; | ||
763 | } | 905 | } |
764 | 906 | ||
765 | config.dev = s5m8767->dev; | 907 | config.dev = s5m8767->dev; |
766 | config.init_data = pdata->regulators[i].initdata; | 908 | config.init_data = pdata->regulators[i].initdata; |
767 | config.driver_data = s5m8767; | 909 | config.driver_data = s5m8767; |
910 | config.regmap = iodev->regmap; | ||
911 | config.of_node = pdata->regulators[i].reg_node; | ||
768 | 912 | ||
769 | rdev[i] = regulator_register(®ulators[id], &config); | 913 | rdev[i] = regulator_register(®ulators[id], &config); |
770 | if (IS_ERR(rdev[i])) { | 914 | if (IS_ERR(rdev[i])) { |
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index ab21133e6784..6e67be75ea1b 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c | |||
@@ -28,10 +28,13 @@ | |||
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
30 | #include <linux/module.h> | 30 | #include <linux/module.h> |
31 | #include <linux/of.h> | ||
32 | #include <linux/of_device.h> | ||
31 | #include <linux/platform_device.h> | 33 | #include <linux/platform_device.h> |
32 | #include <linux/regmap.h> | 34 | #include <linux/regmap.h> |
33 | #include <linux/regulator/driver.h> | 35 | #include <linux/regulator/driver.h> |
34 | #include <linux/regulator/machine.h> | 36 | #include <linux/regulator/machine.h> |
37 | #include <linux/regulator/of_regulator.h> | ||
35 | #include <linux/regulator/tps51632-regulator.h> | 38 | #include <linux/regulator/tps51632-regulator.h> |
36 | #include <linux/slab.h> | 39 | #include <linux/slab.h> |
37 | 40 | ||
@@ -85,49 +88,8 @@ struct tps51632_chip { | |||
85 | struct regulator_desc desc; | 88 | struct regulator_desc desc; |
86 | struct regulator_dev *rdev; | 89 | struct regulator_dev *rdev; |
87 | struct regmap *regmap; | 90 | struct regmap *regmap; |
88 | bool enable_pwm_dvfs; | ||
89 | }; | 91 | }; |
90 | 92 | ||
91 | static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev) | ||
92 | { | ||
93 | struct tps51632_chip *tps = rdev_get_drvdata(rdev); | ||
94 | unsigned int data; | ||
95 | int ret; | ||
96 | unsigned int reg = TPS51632_VOLTAGE_SELECT_REG; | ||
97 | int vsel; | ||
98 | |||
99 | if (tps->enable_pwm_dvfs) | ||
100 | reg = TPS51632_VOLTAGE_BASE_REG; | ||
101 | |||
102 | ret = regmap_read(tps->regmap, reg, &data); | ||
103 | if (ret < 0) { | ||
104 | dev_err(tps->dev, "reg read failed, err %d\n", ret); | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | vsel = data & TPS51632_VOUT_MASK; | ||
109 | return vsel; | ||
110 | } | ||
111 | |||
112 | static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev, | ||
113 | unsigned selector) | ||
114 | { | ||
115 | struct tps51632_chip *tps = rdev_get_drvdata(rdev); | ||
116 | int ret; | ||
117 | unsigned int reg = TPS51632_VOLTAGE_SELECT_REG; | ||
118 | |||
119 | if (tps->enable_pwm_dvfs) | ||
120 | reg = TPS51632_VOLTAGE_BASE_REG; | ||
121 | |||
122 | if (selector > TPS51632_MAX_VSEL) | ||
123 | return -EINVAL; | ||
124 | |||
125 | ret = regmap_write(tps->regmap, reg, selector); | ||
126 | if (ret < 0) | ||
127 | dev_err(tps->dev, "reg write failed, err %d\n", ret); | ||
128 | return ret; | ||
129 | } | ||
130 | |||
131 | static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev, | 93 | static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev, |
132 | int ramp_delay) | 94 | int ramp_delay) |
133 | { | 95 | { |
@@ -144,8 +106,8 @@ static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev, | |||
144 | } | 106 | } |
145 | 107 | ||
146 | static struct regulator_ops tps51632_dcdc_ops = { | 108 | static struct regulator_ops tps51632_dcdc_ops = { |
147 | .get_voltage_sel = tps51632_dcdc_get_voltage_sel, | 109 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
148 | .set_voltage_sel = tps51632_dcdc_set_voltage_sel, | 110 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
149 | .list_voltage = regulator_list_voltage_linear, | 111 | .list_voltage = regulator_list_voltage_linear, |
150 | .set_voltage_time_sel = regulator_set_voltage_time_sel, | 112 | .set_voltage_time_sel = regulator_set_voltage_time_sel, |
151 | .set_ramp_delay = tps51632_dcdc_set_ramp_delay, | 113 | .set_ramp_delay = tps51632_dcdc_set_ramp_delay, |
@@ -162,7 +124,6 @@ static int tps51632_init_dcdc(struct tps51632_chip *tps, | |||
162 | goto skip_pwm_config; | 124 | goto skip_pwm_config; |
163 | 125 | ||
164 | control |= TPS51632_DVFS_PWMEN; | 126 | control |= TPS51632_DVFS_PWMEN; |
165 | tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs; | ||
166 | vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV); | 127 | vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV); |
167 | ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel); | 128 | ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel); |
168 | if (ret < 0) { | 129 | if (ret < 0) { |
@@ -205,22 +166,96 @@ skip_pwm_config: | |||
205 | return ret; | 166 | return ret; |
206 | } | 167 | } |
207 | 168 | ||
208 | static bool rd_wr_reg(struct device *dev, unsigned int reg) | 169 | static bool is_volatile_reg(struct device *dev, unsigned int reg) |
170 | { | ||
171 | switch (reg) { | ||
172 | case TPS51632_OFFSET_REG: | ||
173 | case TPS51632_FAULT_REG: | ||
174 | case TPS51632_IMON_REG: | ||
175 | return true; | ||
176 | default: | ||
177 | return false; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | static bool is_read_reg(struct device *dev, unsigned int reg) | ||
209 | { | 182 | { |
210 | if ((reg >= 0x8) && (reg <= 0x10)) | 183 | switch (reg) { |
184 | case 0x08 ... 0x0F: | ||
211 | return false; | 185 | return false; |
212 | return true; | 186 | default: |
187 | return true; | ||
188 | } | ||
189 | } | ||
190 | |||
191 | static bool is_write_reg(struct device *dev, unsigned int reg) | ||
192 | { | ||
193 | switch (reg) { | ||
194 | case TPS51632_VOLTAGE_SELECT_REG: | ||
195 | case TPS51632_VOLTAGE_BASE_REG: | ||
196 | case TPS51632_VMAX_REG: | ||
197 | case TPS51632_DVFS_CONTROL_REG: | ||
198 | case TPS51632_POWER_STATE_REG: | ||
199 | case TPS51632_SLEW_REGS: | ||
200 | return true; | ||
201 | default: | ||
202 | return false; | ||
203 | } | ||
213 | } | 204 | } |
214 | 205 | ||
215 | static const struct regmap_config tps51632_regmap_config = { | 206 | static const struct regmap_config tps51632_regmap_config = { |
216 | .reg_bits = 8, | 207 | .reg_bits = 8, |
217 | .val_bits = 8, | 208 | .val_bits = 8, |
218 | .writeable_reg = rd_wr_reg, | 209 | .writeable_reg = is_write_reg, |
219 | .readable_reg = rd_wr_reg, | 210 | .readable_reg = is_read_reg, |
211 | .volatile_reg = is_volatile_reg, | ||
220 | .max_register = TPS51632_MAX_REG - 1, | 212 | .max_register = TPS51632_MAX_REG - 1, |
221 | .cache_type = REGCACHE_RBTREE, | 213 | .cache_type = REGCACHE_RBTREE, |
222 | }; | 214 | }; |
223 | 215 | ||
216 | #if defined(CONFIG_OF) | ||
217 | static const struct of_device_id tps51632_of_match[] = { | ||
218 | { .compatible = "ti,tps51632",}, | ||
219 | {}, | ||
220 | }; | ||
221 | MODULE_DEVICE_TABLE(of, tps51632_of_match); | ||
222 | |||
223 | static struct tps51632_regulator_platform_data * | ||
224 | of_get_tps51632_platform_data(struct device *dev) | ||
225 | { | ||
226 | struct tps51632_regulator_platform_data *pdata; | ||
227 | struct device_node *np = dev->of_node; | ||
228 | |||
229 | pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); | ||
230 | if (!pdata) { | ||
231 | dev_err(dev, "Memory alloc failed for platform data\n"); | ||
232 | return NULL; | ||
233 | } | ||
234 | |||
235 | pdata->reg_init_data = of_get_regulator_init_data(dev, dev->of_node); | ||
236 | if (!pdata->reg_init_data) { | ||
237 | dev_err(dev, "Not able to get OF regulator init data\n"); | ||
238 | return NULL; | ||
239 | } | ||
240 | |||
241 | pdata->enable_pwm_dvfs = | ||
242 | of_property_read_bool(np, "ti,enable-pwm-dvfs"); | ||
243 | pdata->dvfs_step_20mV = of_property_read_bool(np, "ti,dvfs-step-20mV"); | ||
244 | |||
245 | pdata->base_voltage_uV = pdata->reg_init_data->constraints.min_uV ? : | ||
246 | TPS51632_MIN_VOLATGE; | ||
247 | pdata->max_voltage_uV = pdata->reg_init_data->constraints.max_uV ? : | ||
248 | TPS51632_MAX_VOLATGE; | ||
249 | return pdata; | ||
250 | } | ||
251 | #else | ||
252 | static struct tps51632_regulator_platform_data * | ||
253 | of_get_tps51632_platform_data(struct device *dev) | ||
254 | { | ||
255 | return NULL; | ||
256 | } | ||
257 | #endif | ||
258 | |||
224 | static int tps51632_probe(struct i2c_client *client, | 259 | static int tps51632_probe(struct i2c_client *client, |
225 | const struct i2c_device_id *id) | 260 | const struct i2c_device_id *id) |
226 | { | 261 | { |
@@ -230,7 +265,19 @@ static int tps51632_probe(struct i2c_client *client, | |||
230 | int ret; | 265 | int ret; |
231 | struct regulator_config config = { }; | 266 | struct regulator_config config = { }; |
232 | 267 | ||
268 | if (client->dev.of_node) { | ||
269 | const struct of_device_id *match; | ||
270 | match = of_match_device(of_match_ptr(tps51632_of_match), | ||
271 | &client->dev); | ||
272 | if (!match) { | ||
273 | dev_err(&client->dev, "Error: No device match found\n"); | ||
274 | return -ENODEV; | ||
275 | } | ||
276 | } | ||
277 | |||
233 | pdata = client->dev.platform_data; | 278 | pdata = client->dev.platform_data; |
279 | if (!pdata && client->dev.of_node) | ||
280 | pdata = of_get_tps51632_platform_data(&client->dev); | ||
234 | if (!pdata) { | 281 | if (!pdata) { |
235 | dev_err(&client->dev, "No Platform data\n"); | 282 | dev_err(&client->dev, "No Platform data\n"); |
236 | return -EINVAL; | 283 | return -EINVAL; |
@@ -269,6 +316,12 @@ static int tps51632_probe(struct i2c_client *client, | |||
269 | tps->desc.type = REGULATOR_VOLTAGE; | 316 | tps->desc.type = REGULATOR_VOLTAGE; |
270 | tps->desc.owner = THIS_MODULE; | 317 | tps->desc.owner = THIS_MODULE; |
271 | 318 | ||
319 | if (pdata->enable_pwm_dvfs) | ||
320 | tps->desc.vsel_reg = TPS51632_VOLTAGE_BASE_REG; | ||
321 | else | ||
322 | tps->desc.vsel_reg = TPS51632_VOLTAGE_SELECT_REG; | ||
323 | tps->desc.vsel_mask = TPS51632_VOUT_MASK; | ||
324 | |||
272 | tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config); | 325 | tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config); |
273 | if (IS_ERR(tps->regmap)) { | 326 | if (IS_ERR(tps->regmap)) { |
274 | ret = PTR_ERR(tps->regmap); | 327 | ret = PTR_ERR(tps->regmap); |
@@ -319,6 +372,7 @@ static struct i2c_driver tps51632_i2c_driver = { | |||
319 | .driver = { | 372 | .driver = { |
320 | .name = "tps51632", | 373 | .name = "tps51632", |
321 | .owner = THIS_MODULE, | 374 | .owner = THIS_MODULE, |
375 | .of_match_table = of_match_ptr(tps51632_of_match), | ||
322 | }, | 376 | }, |
323 | .probe = tps51632_probe, | 377 | .probe = tps51632_probe, |
324 | .remove = tps51632_remove, | 378 | .remove = tps51632_remove, |
diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index 0233cfb56560..54aa2da7283b 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c | |||
@@ -23,8 +23,10 @@ | |||
23 | #include <linux/regulator/driver.h> | 23 | #include <linux/regulator/driver.h> |
24 | #include <linux/regulator/machine.h> | 24 | #include <linux/regulator/machine.h> |
25 | #include <linux/regulator/tps6507x.h> | 25 | #include <linux/regulator/tps6507x.h> |
26 | #include <linux/of.h> | ||
26 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
27 | #include <linux/mfd/tps6507x.h> | 28 | #include <linux/mfd/tps6507x.h> |
29 | #include <linux/regulator/of_regulator.h> | ||
28 | 30 | ||
29 | /* DCDC's */ | 31 | /* DCDC's */ |
30 | #define TPS6507X_DCDC_1 0 | 32 | #define TPS6507X_DCDC_1 0 |
@@ -356,6 +358,80 @@ static struct regulator_ops tps6507x_pmic_ops = { | |||
356 | .list_voltage = regulator_list_voltage_table, | 358 | .list_voltage = regulator_list_voltage_table, |
357 | }; | 359 | }; |
358 | 360 | ||
361 | #ifdef CONFIG_OF | ||
362 | static struct of_regulator_match tps6507x_matches[] = { | ||
363 | { .name = "VDCDC1"}, | ||
364 | { .name = "VDCDC2"}, | ||
365 | { .name = "VDCDC3"}, | ||
366 | { .name = "LDO1"}, | ||
367 | { .name = "LDO2"}, | ||
368 | }; | ||
369 | |||
370 | static struct tps6507x_board *tps6507x_parse_dt_reg_data( | ||
371 | struct platform_device *pdev, | ||
372 | struct of_regulator_match **tps6507x_reg_matches) | ||
373 | { | ||
374 | struct tps6507x_board *tps_board; | ||
375 | struct device_node *np = pdev->dev.parent->of_node; | ||
376 | struct device_node *regulators; | ||
377 | struct of_regulator_match *matches; | ||
378 | static struct regulator_init_data *reg_data; | ||
379 | int idx = 0, count, ret; | ||
380 | |||
381 | tps_board = devm_kzalloc(&pdev->dev, sizeof(*tps_board), | ||
382 | GFP_KERNEL); | ||
383 | if (!tps_board) { | ||
384 | dev_err(&pdev->dev, "Failure to alloc pdata for regulators.\n"); | ||
385 | return NULL; | ||
386 | } | ||
387 | |||
388 | regulators = of_find_node_by_name(np, "regulators"); | ||
389 | if (!regulators) { | ||
390 | dev_err(&pdev->dev, "regulator node not found\n"); | ||
391 | return NULL; | ||
392 | } | ||
393 | |||
394 | count = ARRAY_SIZE(tps6507x_matches); | ||
395 | matches = tps6507x_matches; | ||
396 | |||
397 | ret = of_regulator_match(&pdev->dev, regulators, matches, count); | ||
398 | if (ret < 0) { | ||
399 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", | ||
400 | ret); | ||
401 | return NULL; | ||
402 | } | ||
403 | |||
404 | *tps6507x_reg_matches = matches; | ||
405 | |||
406 | reg_data = devm_kzalloc(&pdev->dev, (sizeof(struct regulator_init_data) | ||
407 | * TPS6507X_NUM_REGULATOR), GFP_KERNEL); | ||
408 | if (!reg_data) { | ||
409 | dev_err(&pdev->dev, "Failure to alloc init data for regulators.\n"); | ||
410 | return NULL; | ||
411 | } | ||
412 | |||
413 | tps_board->tps6507x_pmic_init_data = reg_data; | ||
414 | |||
415 | for (idx = 0; idx < count; idx++) { | ||
416 | if (!matches[idx].init_data || !matches[idx].of_node) | ||
417 | continue; | ||
418 | |||
419 | memcpy(®_data[idx], matches[idx].init_data, | ||
420 | sizeof(struct regulator_init_data)); | ||
421 | |||
422 | } | ||
423 | |||
424 | return tps_board; | ||
425 | } | ||
426 | #else | ||
427 | static inline struct tps6507x_board *tps6507x_parse_dt_reg_data( | ||
428 | struct platform_device *pdev, | ||
429 | struct of_regulator_match **tps6507x_reg_matches) | ||
430 | { | ||
431 | *tps6507x_reg_matches = NULL; | ||
432 | return NULL; | ||
433 | } | ||
434 | #endif | ||
359 | static int tps6507x_pmic_probe(struct platform_device *pdev) | 435 | static int tps6507x_pmic_probe(struct platform_device *pdev) |
360 | { | 436 | { |
361 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); | 437 | struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent); |
@@ -365,8 +441,10 @@ static int tps6507x_pmic_probe(struct platform_device *pdev) | |||
365 | struct regulator_dev *rdev; | 441 | struct regulator_dev *rdev; |
366 | struct tps6507x_pmic *tps; | 442 | struct tps6507x_pmic *tps; |
367 | struct tps6507x_board *tps_board; | 443 | struct tps6507x_board *tps_board; |
444 | struct of_regulator_match *tps6507x_reg_matches = NULL; | ||
368 | int i; | 445 | int i; |
369 | int error; | 446 | int error; |
447 | unsigned int prop; | ||
370 | 448 | ||
371 | /** | 449 | /** |
372 | * tps_board points to pmic related constants | 450 | * tps_board points to pmic related constants |
@@ -374,6 +452,9 @@ static int tps6507x_pmic_probe(struct platform_device *pdev) | |||
374 | */ | 452 | */ |
375 | 453 | ||
376 | tps_board = dev_get_platdata(tps6507x_dev->dev); | 454 | tps_board = dev_get_platdata(tps6507x_dev->dev); |
455 | if (!tps_board && tps6507x_dev->dev->of_node) | ||
456 | tps_board = tps6507x_parse_dt_reg_data(pdev, | ||
457 | &tps6507x_reg_matches); | ||
377 | if (!tps_board) | 458 | if (!tps_board) |
378 | return -EINVAL; | 459 | return -EINVAL; |
379 | 460 | ||
@@ -415,6 +496,17 @@ static int tps6507x_pmic_probe(struct platform_device *pdev) | |||
415 | config.init_data = init_data; | 496 | config.init_data = init_data; |
416 | config.driver_data = tps; | 497 | config.driver_data = tps; |
417 | 498 | ||
499 | if (tps6507x_reg_matches) { | ||
500 | error = of_property_read_u32( | ||
501 | tps6507x_reg_matches[i].of_node, | ||
502 | "ti,defdcdc_default", &prop); | ||
503 | |||
504 | if (!error) | ||
505 | tps->info[i]->defdcdc_default = prop; | ||
506 | |||
507 | config.of_node = tps6507x_reg_matches[i].of_node; | ||
508 | } | ||
509 | |||
418 | rdev = regulator_register(&tps->desc[i], &config); | 510 | rdev = regulator_register(&tps->desc[i], &config); |
419 | if (IS_ERR(rdev)) { | 511 | if (IS_ERR(rdev)) { |
420 | dev_err(tps6507x_dev->dev, | 512 | dev_err(tps6507x_dev->dev, |
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c index 41c391789c97..c8e70451df38 100644 --- a/drivers/regulator/tps65090-regulator.c +++ b/drivers/regulator/tps65090-regulator.c | |||
@@ -19,11 +19,13 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/gpio.h> | 21 | #include <linux/gpio.h> |
22 | #include <linux/of_gpio.h> | ||
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
23 | #include <linux/err.h> | 24 | #include <linux/err.h> |
24 | #include <linux/platform_device.h> | 25 | #include <linux/platform_device.h> |
25 | #include <linux/regulator/driver.h> | 26 | #include <linux/regulator/driver.h> |
26 | #include <linux/regulator/machine.h> | 27 | #include <linux/regulator/machine.h> |
28 | #include <linux/regulator/of_regulator.h> | ||
27 | #include <linux/mfd/tps65090.h> | 29 | #include <linux/mfd/tps65090.h> |
28 | 30 | ||
29 | struct tps65090_regulator { | 31 | struct tps65090_regulator { |
@@ -67,8 +69,8 @@ static struct regulator_desc tps65090_regulator_desc[] = { | |||
67 | tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops), | 69 | tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops), |
68 | tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops), | 70 | tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops), |
69 | tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops), | 71 | tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops), |
70 | tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops), | 72 | tps65090_REG_DESC(LDO1, "vsys-l1", 0, tps65090_ldo_ops), |
71 | tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops), | 73 | tps65090_REG_DESC(LDO2, "vsys-l2", 0, tps65090_ldo_ops), |
72 | }; | 74 | }; |
73 | 75 | ||
74 | static inline bool is_dcdc(int id) | 76 | static inline bool is_dcdc(int id) |
@@ -138,6 +140,92 @@ static void tps65090_configure_regulator_config( | |||
138 | } | 140 | } |
139 | } | 141 | } |
140 | 142 | ||
143 | #ifdef CONFIG_OF | ||
144 | static struct of_regulator_match tps65090_matches[] = { | ||
145 | { .name = "dcdc1", }, | ||
146 | { .name = "dcdc2", }, | ||
147 | { .name = "dcdc3", }, | ||
148 | { .name = "fet1", }, | ||
149 | { .name = "fet2", }, | ||
150 | { .name = "fet3", }, | ||
151 | { .name = "fet4", }, | ||
152 | { .name = "fet5", }, | ||
153 | { .name = "fet6", }, | ||
154 | { .name = "fet7", }, | ||
155 | { .name = "ldo1", }, | ||
156 | { .name = "ldo2", }, | ||
157 | }; | ||
158 | |||
159 | static struct tps65090_platform_data *tps65090_parse_dt_reg_data( | ||
160 | struct platform_device *pdev, | ||
161 | struct of_regulator_match **tps65090_reg_matches) | ||
162 | { | ||
163 | struct tps65090_platform_data *tps65090_pdata; | ||
164 | struct device_node *np = pdev->dev.parent->of_node; | ||
165 | struct device_node *regulators; | ||
166 | int idx = 0, ret; | ||
167 | struct tps65090_regulator_plat_data *reg_pdata; | ||
168 | |||
169 | tps65090_pdata = devm_kzalloc(&pdev->dev, sizeof(*tps65090_pdata), | ||
170 | GFP_KERNEL); | ||
171 | if (!tps65090_pdata) { | ||
172 | dev_err(&pdev->dev, "Memory alloc for tps65090_pdata failed\n"); | ||
173 | return ERR_PTR(-ENOMEM); | ||
174 | } | ||
175 | |||
176 | reg_pdata = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * | ||
177 | sizeof(*reg_pdata), GFP_KERNEL); | ||
178 | if (!reg_pdata) { | ||
179 | dev_err(&pdev->dev, "Memory alloc for reg_pdata failed\n"); | ||
180 | return ERR_PTR(-ENOMEM); | ||
181 | } | ||
182 | |||
183 | regulators = of_find_node_by_name(np, "regulators"); | ||
184 | if (!regulators) { | ||
185 | dev_err(&pdev->dev, "regulator node not found\n"); | ||
186 | return ERR_PTR(-ENODEV); | ||
187 | } | ||
188 | |||
189 | ret = of_regulator_match(&pdev->dev, regulators, tps65090_matches, | ||
190 | ARRAY_SIZE(tps65090_matches)); | ||
191 | if (ret < 0) { | ||
192 | dev_err(&pdev->dev, | ||
193 | "Error parsing regulator init data: %d\n", ret); | ||
194 | return ERR_PTR(ret); | ||
195 | } | ||
196 | |||
197 | *tps65090_reg_matches = tps65090_matches; | ||
198 | for (idx = 0; idx < ARRAY_SIZE(tps65090_matches); idx++) { | ||
199 | struct regulator_init_data *ri_data; | ||
200 | struct tps65090_regulator_plat_data *rpdata; | ||
201 | |||
202 | rpdata = ®_pdata[idx]; | ||
203 | ri_data = tps65090_matches[idx].init_data; | ||
204 | if (!ri_data || !tps65090_matches[idx].of_node) | ||
205 | continue; | ||
206 | |||
207 | rpdata->reg_init_data = ri_data; | ||
208 | rpdata->enable_ext_control = of_property_read_bool( | ||
209 | tps65090_matches[idx].of_node, | ||
210 | "ti,enable-ext-control"); | ||
211 | if (rpdata->enable_ext_control) | ||
212 | rpdata->gpio = of_get_named_gpio(np, | ||
213 | "dcdc-ext-control-gpios", 0); | ||
214 | |||
215 | tps65090_pdata->reg_pdata[idx] = rpdata; | ||
216 | } | ||
217 | return tps65090_pdata; | ||
218 | } | ||
219 | #else | ||
220 | static inline struct tps65090_platform_data *tps65090_parse_dt_reg_data( | ||
221 | struct platform_device *pdev, | ||
222 | struct of_regulator_match **tps65090_reg_matches) | ||
223 | { | ||
224 | *tps65090_reg_matches = NULL; | ||
225 | return NULL; | ||
226 | } | ||
227 | #endif | ||
228 | |||
141 | static int tps65090_regulator_probe(struct platform_device *pdev) | 229 | static int tps65090_regulator_probe(struct platform_device *pdev) |
142 | { | 230 | { |
143 | struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent); | 231 | struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent); |
@@ -147,15 +235,19 @@ static int tps65090_regulator_probe(struct platform_device *pdev) | |||
147 | struct tps65090_regulator_plat_data *tps_pdata; | 235 | struct tps65090_regulator_plat_data *tps_pdata; |
148 | struct tps65090_regulator *pmic; | 236 | struct tps65090_regulator *pmic; |
149 | struct tps65090_platform_data *tps65090_pdata; | 237 | struct tps65090_platform_data *tps65090_pdata; |
238 | struct of_regulator_match *tps65090_reg_matches = NULL; | ||
150 | int num; | 239 | int num; |
151 | int ret; | 240 | int ret; |
152 | 241 | ||
153 | dev_dbg(&pdev->dev, "Probing regulator\n"); | 242 | dev_dbg(&pdev->dev, "Probing regulator\n"); |
154 | 243 | ||
155 | tps65090_pdata = dev_get_platdata(pdev->dev.parent); | 244 | tps65090_pdata = dev_get_platdata(pdev->dev.parent); |
156 | if (!tps65090_pdata) { | 245 | if (!tps65090_pdata && tps65090_mfd->dev->of_node) |
246 | tps65090_pdata = tps65090_parse_dt_reg_data(pdev, | ||
247 | &tps65090_reg_matches); | ||
248 | if (IS_ERR_OR_NULL(tps65090_pdata)) { | ||
157 | dev_err(&pdev->dev, "Platform data missing\n"); | 249 | dev_err(&pdev->dev, "Platform data missing\n"); |
158 | return -EINVAL; | 250 | return tps65090_pdata ? PTR_ERR(tps65090_pdata) : -EINVAL; |
159 | } | 251 | } |
160 | 252 | ||
161 | pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic), | 253 | pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic), |
@@ -192,13 +284,17 @@ static int tps65090_regulator_probe(struct platform_device *pdev) | |||
192 | } | 284 | } |
193 | } | 285 | } |
194 | 286 | ||
195 | config.dev = &pdev->dev; | 287 | config.dev = pdev->dev.parent; |
196 | config.driver_data = ri; | 288 | config.driver_data = ri; |
197 | config.regmap = tps65090_mfd->rmap; | 289 | config.regmap = tps65090_mfd->rmap; |
198 | if (tps_pdata) | 290 | if (tps_pdata) |
199 | config.init_data = tps_pdata->reg_init_data; | 291 | config.init_data = tps_pdata->reg_init_data; |
200 | else | 292 | else |
201 | config.init_data = NULL; | 293 | config.init_data = NULL; |
294 | if (tps65090_reg_matches) | ||
295 | config.of_node = tps65090_reg_matches[num].of_node; | ||
296 | else | ||
297 | config.of_node = NULL; | ||
202 | 298 | ||
203 | rdev = regulator_register(ri->desc, &config); | 299 | rdev = regulator_register(ri->desc, &config); |
204 | if (IS_ERR(rdev)) { | 300 | if (IS_ERR(rdev)) { |
diff --git a/drivers/regulator/tps65217-regulator.c b/drivers/regulator/tps65217-regulator.c index 73dce7664126..df395187c063 100644 --- a/drivers/regulator/tps65217-regulator.c +++ b/drivers/regulator/tps65217-regulator.c | |||
@@ -305,8 +305,8 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev) | |||
305 | if (!regs) | 305 | if (!regs) |
306 | return NULL; | 306 | return NULL; |
307 | 307 | ||
308 | count = of_regulator_match(pdev->dev.parent, regs, | 308 | count = of_regulator_match(&pdev->dev, regs, reg_matches, |
309 | reg_matches, TPS65217_NUM_REGULATOR); | 309 | TPS65217_NUM_REGULATOR); |
310 | of_node_put(regs); | 310 | of_node_put(regs); |
311 | if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) | 311 | if ((count < 0) || (count > TPS65217_NUM_REGULATOR)) |
312 | return NULL; | 312 | return NULL; |
diff --git a/drivers/regulator/tps6586x-regulator.c b/drivers/regulator/tps6586x-regulator.c index f86da672c758..e68382d0e1ea 100644 --- a/drivers/regulator/tps6586x-regulator.c +++ b/drivers/regulator/tps6586x-regulator.c | |||
@@ -61,10 +61,6 @@ struct tps6586x_regulator { | |||
61 | 61 | ||
62 | int enable_bit[2]; | 62 | int enable_bit[2]; |
63 | int enable_reg[2]; | 63 | int enable_reg[2]; |
64 | |||
65 | /* for DVM regulators */ | ||
66 | int go_reg; | ||
67 | int go_bit; | ||
68 | }; | 64 | }; |
69 | 65 | ||
70 | static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) | 66 | static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) |
@@ -72,37 +68,10 @@ static inline struct device *to_tps6586x_dev(struct regulator_dev *rdev) | |||
72 | return rdev_get_dev(rdev)->parent; | 68 | return rdev_get_dev(rdev)->parent; |
73 | } | 69 | } |
74 | 70 | ||
75 | static int tps6586x_set_voltage_sel(struct regulator_dev *rdev, | ||
76 | unsigned selector) | ||
77 | { | ||
78 | struct tps6586x_regulator *ri = rdev_get_drvdata(rdev); | ||
79 | struct device *parent = to_tps6586x_dev(rdev); | ||
80 | int ret, val, rid = rdev_get_id(rdev); | ||
81 | uint8_t mask; | ||
82 | |||
83 | val = selector << (ffs(rdev->desc->vsel_mask) - 1); | ||
84 | mask = rdev->desc->vsel_mask; | ||
85 | |||
86 | ret = tps6586x_update(parent, rdev->desc->vsel_reg, val, mask); | ||
87 | if (ret) | ||
88 | return ret; | ||
89 | |||
90 | /* Update go bit for DVM regulators */ | ||
91 | switch (rid) { | ||
92 | case TPS6586X_ID_LDO_2: | ||
93 | case TPS6586X_ID_LDO_4: | ||
94 | case TPS6586X_ID_SM_0: | ||
95 | case TPS6586X_ID_SM_1: | ||
96 | ret = tps6586x_set_bits(parent, ri->go_reg, 1 << ri->go_bit); | ||
97 | break; | ||
98 | } | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | static struct regulator_ops tps6586x_regulator_ops = { | 71 | static struct regulator_ops tps6586x_regulator_ops = { |
103 | .list_voltage = regulator_list_voltage_table, | 72 | .list_voltage = regulator_list_voltage_table, |
104 | .get_voltage_sel = regulator_get_voltage_sel_regmap, | 73 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
105 | .set_voltage_sel = tps6586x_set_voltage_sel, | 74 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
106 | 75 | ||
107 | .is_enabled = regulator_is_enabled_regmap, | 76 | .is_enabled = regulator_is_enabled_regmap, |
108 | .enable = regulator_enable_regmap, | 77 | .enable = regulator_enable_regmap, |
@@ -142,7 +111,7 @@ static const unsigned int tps6586x_dvm_voltages[] = { | |||
142 | }; | 111 | }; |
143 | 112 | ||
144 | #define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \ | 113 | #define TPS6586X_REGULATOR(_id, _pin_name, vdata, vreg, shift, nbits, \ |
145 | ereg0, ebit0, ereg1, ebit1) \ | 114 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
146 | .desc = { \ | 115 | .desc = { \ |
147 | .supply_name = _pin_name, \ | 116 | .supply_name = _pin_name, \ |
148 | .name = "REG-" #_id, \ | 117 | .name = "REG-" #_id, \ |
@@ -156,29 +125,26 @@ static const unsigned int tps6586x_dvm_voltages[] = { | |||
156 | .enable_mask = 1 << (ebit0), \ | 125 | .enable_mask = 1 << (ebit0), \ |
157 | .vsel_reg = TPS6586X_##vreg, \ | 126 | .vsel_reg = TPS6586X_##vreg, \ |
158 | .vsel_mask = ((1 << (nbits)) - 1) << (shift), \ | 127 | .vsel_mask = ((1 << (nbits)) - 1) << (shift), \ |
128 | .apply_reg = (goreg), \ | ||
129 | .apply_bit = (gobit), \ | ||
159 | }, \ | 130 | }, \ |
160 | .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ | 131 | .enable_reg[0] = TPS6586X_SUPPLY##ereg0, \ |
161 | .enable_bit[0] = (ebit0), \ | 132 | .enable_bit[0] = (ebit0), \ |
162 | .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ | 133 | .enable_reg[1] = TPS6586X_SUPPLY##ereg1, \ |
163 | .enable_bit[1] = (ebit1), | 134 | .enable_bit[1] = (ebit1), |
164 | 135 | ||
165 | #define TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ | ||
166 | .go_reg = TPS6586X_##goreg, \ | ||
167 | .go_bit = (gobit), | ||
168 | |||
169 | #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ | 136 | #define TPS6586X_LDO(_id, _pname, vdata, vreg, shift, nbits, \ |
170 | ereg0, ebit0, ereg1, ebit1) \ | 137 | ereg0, ebit0, ereg1, ebit1) \ |
171 | { \ | 138 | { \ |
172 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ | 139 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ |
173 | ereg0, ebit0, ereg1, ebit1) \ | 140 | ereg0, ebit0, ereg1, ebit1, 0, 0) \ |
174 | } | 141 | } |
175 | 142 | ||
176 | #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ | 143 | #define TPS6586X_DVM(_id, _pname, vdata, vreg, shift, nbits, \ |
177 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ | 144 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
178 | { \ | 145 | { \ |
179 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ | 146 | TPS6586X_REGULATOR(_id, _pname, vdata, vreg, shift, nbits, \ |
180 | ereg0, ebit0, ereg1, ebit1) \ | 147 | ereg0, ebit0, ereg1, ebit1, goreg, gobit) \ |
181 | TPS6586X_REGULATOR_DVM_GOREG(goreg, gobit) \ | ||
182 | } | 148 | } |
183 | 149 | ||
184 | #define TPS6586X_SYS_REGULATOR() \ | 150 | #define TPS6586X_SYS_REGULATOR() \ |
@@ -207,13 +173,13 @@ static struct tps6586x_regulator tps6586x_regulator[] = { | |||
207 | TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), | 173 | TPS6586X_LDO(SM_2, "vin-sm2", sm2, SUPPLYV2, 0, 5, ENC, 7, END, 7), |
208 | 174 | ||
209 | TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3, | 175 | TPS6586X_DVM(LDO_2, "vinldo23", dvm, LDO2BV1, 0, 5, ENA, 3, |
210 | ENB, 3, VCC2, 6), | 176 | ENB, 3, TPS6586X_VCC2, BIT(6)), |
211 | TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3, | 177 | TPS6586X_DVM(LDO_4, "vinldo4", ldo4, LDO4V1, 0, 5, ENC, 3, |
212 | END, 3, VCC1, 6), | 178 | END, 3, TPS6586X_VCC1, BIT(6)), |
213 | TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1, | 179 | TPS6586X_DVM(SM_0, "vin-sm0", dvm, SM0V1, 0, 5, ENA, 1, |
214 | ENB, 1, VCC1, 2), | 180 | ENB, 1, TPS6586X_VCC1, BIT(2)), |
215 | TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0, | 181 | TPS6586X_DVM(SM_1, "vin-sm1", dvm, SM1V1, 0, 5, ENA, 0, |
216 | ENB, 0, VCC1, 0), | 182 | ENB, 0, TPS6586X_VCC1, BIT(0)), |
217 | }; | 183 | }; |
218 | 184 | ||
219 | /* | 185 | /* |
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c index 59c3770fa77d..6ba6931ac855 100644 --- a/drivers/regulator/tps65910-regulator.c +++ b/drivers/regulator/tps65910-regulator.c | |||
@@ -964,8 +964,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( | |||
964 | { | 964 | { |
965 | struct tps65910_board *pmic_plat_data; | 965 | struct tps65910_board *pmic_plat_data; |
966 | struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); | 966 | struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent); |
967 | struct device_node *np = pdev->dev.parent->of_node; | 967 | struct device_node *np, *regulators; |
968 | struct device_node *regulators; | ||
969 | struct of_regulator_match *matches; | 968 | struct of_regulator_match *matches; |
970 | unsigned int prop; | 969 | unsigned int prop; |
971 | int idx = 0, ret, count; | 970 | int idx = 0, ret, count; |
@@ -978,6 +977,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( | |||
978 | return NULL; | 977 | return NULL; |
979 | } | 978 | } |
980 | 979 | ||
980 | np = of_node_get(pdev->dev.parent->of_node); | ||
981 | regulators = of_find_node_by_name(np, "regulators"); | 981 | regulators = of_find_node_by_name(np, "regulators"); |
982 | if (!regulators) { | 982 | if (!regulators) { |
983 | dev_err(&pdev->dev, "regulator node not found\n"); | 983 | dev_err(&pdev->dev, "regulator node not found\n"); |
@@ -994,11 +994,13 @@ static struct tps65910_board *tps65910_parse_dt_reg_data( | |||
994 | matches = tps65911_matches; | 994 | matches = tps65911_matches; |
995 | break; | 995 | break; |
996 | default: | 996 | default: |
997 | of_node_put(regulators); | ||
997 | dev_err(&pdev->dev, "Invalid tps chip version\n"); | 998 | dev_err(&pdev->dev, "Invalid tps chip version\n"); |
998 | return NULL; | 999 | return NULL; |
999 | } | 1000 | } |
1000 | 1001 | ||
1001 | ret = of_regulator_match(pdev->dev.parent, regulators, matches, count); | 1002 | ret = of_regulator_match(&pdev->dev, regulators, matches, count); |
1003 | of_node_put(regulators); | ||
1002 | if (ret < 0) { | 1004 | if (ret < 0) { |
1003 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", | 1005 | dev_err(&pdev->dev, "Error parsing regulator init data: %d\n", |
1004 | ret); | 1006 | ret); |
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c index b15d711bc8c6..9019d0e7ecb6 100644 --- a/drivers/regulator/tps80031-regulator.c +++ b/drivers/regulator/tps80031-regulator.c | |||
@@ -728,7 +728,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev) | |||
728 | } | 728 | } |
729 | } | 729 | } |
730 | rdev = regulator_register(&ri->rinfo->desc, &config); | 730 | rdev = regulator_register(&ri->rinfo->desc, &config); |
731 | if (IS_ERR_OR_NULL(rdev)) { | 731 | if (IS_ERR(rdev)) { |
732 | dev_err(&pdev->dev, | 732 | dev_err(&pdev->dev, |
733 | "register regulator failed %s\n", | 733 | "register regulator failed %s\n", |
734 | ri->rinfo->desc.name); | 734 | ri->rinfo->desc.name); |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 923a9da9c829..5e44eaabf457 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -20,14 +20,24 @@ if RTC_CLASS | |||
20 | config RTC_HCTOSYS | 20 | config RTC_HCTOSYS |
21 | bool "Set system time from RTC on startup and resume" | 21 | bool "Set system time from RTC on startup and resume" |
22 | default y | 22 | default y |
23 | depends on !ALWAYS_USE_PERSISTENT_CLOCK | ||
23 | help | 24 | help |
24 | If you say yes here, the system time (wall clock) will be set using | 25 | If you say yes here, the system time (wall clock) will be set using |
25 | the value read from a specified RTC device. This is useful to avoid | 26 | the value read from a specified RTC device. This is useful to avoid |
26 | unnecessary fsck runs at boot time, and to network better. | 27 | unnecessary fsck runs at boot time, and to network better. |
27 | 28 | ||
29 | config RTC_SYSTOHC | ||
30 | bool "Set the RTC time based on NTP synchronization" | ||
31 | default y | ||
32 | depends on !ALWAYS_USE_PERSISTENT_CLOCK | ||
33 | help | ||
34 | If you say yes here, the system time (wall clock) will be stored | ||
35 | in the RTC specified by RTC_HCTOSYS_DEVICE approximately every 11 | ||
36 | minutes if userspace reports synchronized NTP status. | ||
37 | |||
28 | config RTC_HCTOSYS_DEVICE | 38 | config RTC_HCTOSYS_DEVICE |
29 | string "RTC used to set the system time" | 39 | string "RTC used to set the system time" |
30 | depends on RTC_HCTOSYS = y | 40 | depends on RTC_HCTOSYS = y || RTC_SYSTOHC = y |
31 | default "rtc0" | 41 | default "rtc0" |
32 | help | 42 | help |
33 | The RTC device that will be used to (re)initialize the system | 43 | The RTC device that will be used to (re)initialize the system |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 4418ef3f9ecc..ec2988b00a44 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -6,6 +6,7 @@ ccflags-$(CONFIG_RTC_DEBUG) := -DDEBUG | |||
6 | 6 | ||
7 | obj-$(CONFIG_RTC_LIB) += rtc-lib.o | 7 | obj-$(CONFIG_RTC_LIB) += rtc-lib.o |
8 | obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o | 8 | obj-$(CONFIG_RTC_HCTOSYS) += hctosys.o |
9 | obj-$(CONFIG_RTC_SYSTOHC) += systohc.o | ||
9 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o | 10 | obj-$(CONFIG_RTC_CLASS) += rtc-core.o |
10 | rtc-core-y := class.o interface.o | 11 | rtc-core-y := class.o interface.o |
11 | 12 | ||
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c index 5143629dedbd..26388f182594 100644 --- a/drivers/rtc/class.c +++ b/drivers/rtc/class.c | |||
@@ -50,6 +50,10 @@ static int rtc_suspend(struct device *dev, pm_message_t mesg) | |||
50 | struct rtc_device *rtc = to_rtc_device(dev); | 50 | struct rtc_device *rtc = to_rtc_device(dev); |
51 | struct rtc_time tm; | 51 | struct rtc_time tm; |
52 | struct timespec delta, delta_delta; | 52 | struct timespec delta, delta_delta; |
53 | |||
54 | if (has_persistent_clock()) | ||
55 | return 0; | ||
56 | |||
53 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 57 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
54 | return 0; | 58 | return 0; |
55 | 59 | ||
@@ -88,6 +92,9 @@ static int rtc_resume(struct device *dev) | |||
88 | struct timespec new_system, new_rtc; | 92 | struct timespec new_system, new_rtc; |
89 | struct timespec sleep_time; | 93 | struct timespec sleep_time; |
90 | 94 | ||
95 | if (has_persistent_clock()) | ||
96 | return 0; | ||
97 | |||
91 | rtc_hctosys_ret = -ENODEV; | 98 | rtc_hctosys_ret = -ENODEV; |
92 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) | 99 | if (strcmp(dev_name(&rtc->dev), CONFIG_RTC_HCTOSYS_DEVICE) != 0) |
93 | return 0; | 100 | return 0; |
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c index 96bafc5c3bf8..8f0dcfedb83c 100644 --- a/drivers/rtc/rtc-da9055.c +++ b/drivers/rtc/rtc-da9055.c | |||
@@ -227,7 +227,7 @@ static const struct rtc_class_ops da9055_rtc_ops = { | |||
227 | .alarm_irq_enable = da9055_rtc_alarm_irq_enable, | 227 | .alarm_irq_enable = da9055_rtc_alarm_irq_enable, |
228 | }; | 228 | }; |
229 | 229 | ||
230 | static int __init da9055_rtc_device_init(struct da9055 *da9055, | 230 | static int da9055_rtc_device_init(struct da9055 *da9055, |
231 | struct da9055_pdata *pdata) | 231 | struct da9055_pdata *pdata) |
232 | { | 232 | { |
233 | int ret; | 233 | int ret; |
diff --git a/drivers/rtc/rtc-isl1208.c b/drivers/rtc/rtc-isl1208.c index afb7cfa85ccc..c016ad81767a 100644 --- a/drivers/rtc/rtc-isl1208.c +++ b/drivers/rtc/rtc-isl1208.c | |||
@@ -506,6 +506,7 @@ isl1208_rtc_interrupt(int irq, void *data) | |||
506 | { | 506 | { |
507 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); | 507 | unsigned long timeout = jiffies + msecs_to_jiffies(1000); |
508 | struct i2c_client *client = data; | 508 | struct i2c_client *client = data; |
509 | struct rtc_device *rtc = i2c_get_clientdata(client); | ||
509 | int handled = 0, sr, err; | 510 | int handled = 0, sr, err; |
510 | 511 | ||
511 | /* | 512 | /* |
@@ -528,6 +529,8 @@ isl1208_rtc_interrupt(int irq, void *data) | |||
528 | if (sr & ISL1208_REG_SR_ALM) { | 529 | if (sr & ISL1208_REG_SR_ALM) { |
529 | dev_dbg(&client->dev, "alarm!\n"); | 530 | dev_dbg(&client->dev, "alarm!\n"); |
530 | 531 | ||
532 | rtc_update_irq(rtc, 1, RTC_IRQF | RTC_AF); | ||
533 | |||
531 | /* Clear the alarm */ | 534 | /* Clear the alarm */ |
532 | sr &= ~ISL1208_REG_SR_ALM; | 535 | sr &= ~ISL1208_REG_SR_ALM; |
533 | sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); | 536 | sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr); |
diff --git a/drivers/rtc/rtc-pl031.c b/drivers/rtc/rtc-pl031.c index 08378e3cc21c..81c5077feff3 100644 --- a/drivers/rtc/rtc-pl031.c +++ b/drivers/rtc/rtc-pl031.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #define RTC_YMR 0x34 /* Year match register */ | 44 | #define RTC_YMR 0x34 /* Year match register */ |
45 | #define RTC_YLR 0x38 /* Year data load register */ | 45 | #define RTC_YLR 0x38 /* Year data load register */ |
46 | 46 | ||
47 | #define RTC_CR_EN (1 << 0) /* counter enable bit */ | ||
47 | #define RTC_CR_CWEN (1 << 26) /* Clockwatch enable bit */ | 48 | #define RTC_CR_CWEN (1 << 26) /* Clockwatch enable bit */ |
48 | 49 | ||
49 | #define RTC_TCR_EN (1 << 1) /* Periodic timer enable bit */ | 50 | #define RTC_TCR_EN (1 << 1) /* Periodic timer enable bit */ |
@@ -320,7 +321,7 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) | |||
320 | struct pl031_local *ldata; | 321 | struct pl031_local *ldata; |
321 | struct pl031_vendor_data *vendor = id->data; | 322 | struct pl031_vendor_data *vendor = id->data; |
322 | struct rtc_class_ops *ops = &vendor->ops; | 323 | struct rtc_class_ops *ops = &vendor->ops; |
323 | unsigned long time; | 324 | unsigned long time, data; |
324 | 325 | ||
325 | ret = amba_request_regions(adev, NULL); | 326 | ret = amba_request_regions(adev, NULL); |
326 | if (ret) | 327 | if (ret) |
@@ -345,10 +346,13 @@ static int pl031_probe(struct amba_device *adev, const struct amba_id *id) | |||
345 | dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev)); | 346 | dev_dbg(&adev->dev, "designer ID = 0x%02x\n", amba_manf(adev)); |
346 | dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev)); | 347 | dev_dbg(&adev->dev, "revision = 0x%01x\n", amba_rev(adev)); |
347 | 348 | ||
349 | data = readl(ldata->base + RTC_CR); | ||
348 | /* Enable the clockwatch on ST Variants */ | 350 | /* Enable the clockwatch on ST Variants */ |
349 | if (vendor->clockwatch) | 351 | if (vendor->clockwatch) |
350 | writel(readl(ldata->base + RTC_CR) | RTC_CR_CWEN, | 352 | data |= RTC_CR_CWEN; |
351 | ldata->base + RTC_CR); | 353 | else |
354 | data |= RTC_CR_EN; | ||
355 | writel(data, ldata->base + RTC_CR); | ||
352 | 356 | ||
353 | /* | 357 | /* |
354 | * On ST PL031 variants, the RTC reset value does not provide correct | 358 | * On ST PL031 variants, the RTC reset value does not provide correct |
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c index 00c930f4b6f3..2730533e2d2d 100644 --- a/drivers/rtc/rtc-vt8500.c +++ b/drivers/rtc/rtc-vt8500.c | |||
@@ -137,7 +137,7 @@ static int vt8500_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
137 | return -EINVAL; | 137 | return -EINVAL; |
138 | } | 138 | } |
139 | 139 | ||
140 | writel((bin2bcd(tm->tm_year - 100) << DATE_YEAR_S) | 140 | writel((bin2bcd(tm->tm_year % 100) << DATE_YEAR_S) |
141 | | (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S) | 141 | | (bin2bcd(tm->tm_mon + 1) << DATE_MONTH_S) |
142 | | (bin2bcd(tm->tm_mday)) | 142 | | (bin2bcd(tm->tm_mday)) |
143 | | ((tm->tm_year >= 200) << DATE_CENTURY_S), | 143 | | ((tm->tm_year >= 200) << DATE_CENTURY_S), |
diff --git a/drivers/rtc/systohc.c b/drivers/rtc/systohc.c new file mode 100644 index 000000000000..bf3e242ccc5c --- /dev/null +++ b/drivers/rtc/systohc.c | |||
@@ -0,0 +1,44 @@ | |||
1 | /* | ||
2 | * This program is free software; you can redistribute it and/or modify it | ||
3 | * under the terms of the GNU General Public License version 2 as published by | ||
4 | * the Free Software Foundation. | ||
5 | * | ||
6 | */ | ||
7 | #include <linux/rtc.h> | ||
8 | #include <linux/time.h> | ||
9 | |||
10 | /** | ||
11 | * rtc_set_ntp_time - Save NTP synchronized time to the RTC | ||
12 | * @now: Current time of day | ||
13 | * | ||
14 | * Replacement for the NTP platform function update_persistent_clock | ||
15 | * that stores time for later retrieval by rtc_hctosys. | ||
16 | * | ||
17 | * Returns 0 on successful RTC update, -ENODEV if a RTC update is not | ||
18 | * possible at all, and various other -errno for specific temporary failure | ||
19 | * cases. | ||
20 | * | ||
21 | * If temporary failure is indicated the caller should try again 'soon' | ||
22 | */ | ||
23 | int rtc_set_ntp_time(struct timespec now) | ||
24 | { | ||
25 | struct rtc_device *rtc; | ||
26 | struct rtc_time tm; | ||
27 | int err = -ENODEV; | ||
28 | |||
29 | if (now.tv_nsec < (NSEC_PER_SEC >> 1)) | ||
30 | rtc_time_to_tm(now.tv_sec, &tm); | ||
31 | else | ||
32 | rtc_time_to_tm(now.tv_sec + 1, &tm); | ||
33 | |||
34 | rtc = rtc_class_open(CONFIG_RTC_HCTOSYS_DEVICE); | ||
35 | if (rtc) { | ||
36 | /* rtc_hctosys exclusively uses UTC, so we call set_time here, | ||
37 | * not set_mmss. */ | ||
38 | if (rtc->ops && (rtc->ops->set_time || rtc->ops->set_mmss)) | ||
39 | err = rtc_set_time(rtc, &tm); | ||
40 | rtc_class_close(rtc); | ||
41 | } | ||
42 | |||
43 | return err; | ||
44 | } | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index 9bd5da36f99e..704488d0f819 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
@@ -248,7 +248,7 @@ static void dasd_ext_handler(struct ext_code ext_code, | |||
248 | default: | 248 | default: |
249 | return; | 249 | return; |
250 | } | 250 | } |
251 | kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++; | 251 | inc_irq_stat(IRQEXT_DSD); |
252 | if (!ip) { /* no intparm: unsolicited interrupt */ | 252 | if (!ip) { /* no intparm: unsolicited interrupt */ |
253 | DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited " | 253 | DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited " |
254 | "interrupt"); | 254 | "interrupt"); |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index 806fe912d6e7..e37bc1620d14 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
@@ -4274,7 +4274,7 @@ static struct ccw_driver dasd_eckd_driver = { | |||
4274 | .thaw = dasd_generic_restore_device, | 4274 | .thaw = dasd_generic_restore_device, |
4275 | .restore = dasd_generic_restore_device, | 4275 | .restore = dasd_generic_restore_device, |
4276 | .uc_handler = dasd_generic_uc_handler, | 4276 | .uc_handler = dasd_generic_uc_handler, |
4277 | .int_class = IOINT_DAS, | 4277 | .int_class = IRQIO_DAS, |
4278 | }; | 4278 | }; |
4279 | 4279 | ||
4280 | /* | 4280 | /* |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index eb748507c7fa..414698584344 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
@@ -78,7 +78,7 @@ static struct ccw_driver dasd_fba_driver = { | |||
78 | .freeze = dasd_generic_pm_freeze, | 78 | .freeze = dasd_generic_pm_freeze, |
79 | .thaw = dasd_generic_restore_device, | 79 | .thaw = dasd_generic_restore_device, |
80 | .restore = dasd_generic_restore_device, | 80 | .restore = dasd_generic_restore_device, |
81 | .int_class = IOINT_DAS, | 81 | .int_class = IRQIO_DAS, |
82 | }; | 82 | }; |
83 | 83 | ||
84 | static void | 84 | static void |
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c index 40084501c31b..33b7141a182f 100644 --- a/drivers/s390/char/con3215.c +++ b/drivers/s390/char/con3215.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #define RAW3215_NR_CCWS 3 | 44 | #define RAW3215_NR_CCWS 3 |
45 | #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ | 45 | #define RAW3215_TIMEOUT HZ/10 /* time for delayed output */ |
46 | 46 | ||
47 | #define RAW3215_FIXED 1 /* 3215 console device is not be freed */ | ||
47 | #define RAW3215_WORKING 4 /* set if a request is being worked on */ | 48 | #define RAW3215_WORKING 4 /* set if a request is being worked on */ |
48 | #define RAW3215_THROTTLED 8 /* set if reading is disabled */ | 49 | #define RAW3215_THROTTLED 8 /* set if reading is disabled */ |
49 | #define RAW3215_STOPPED 16 /* set if writing is disabled */ | 50 | #define RAW3215_STOPPED 16 /* set if writing is disabled */ |
@@ -630,7 +631,8 @@ static void raw3215_shutdown(struct raw3215_info *raw) | |||
630 | DECLARE_WAITQUEUE(wait, current); | 631 | DECLARE_WAITQUEUE(wait, current); |
631 | unsigned long flags; | 632 | unsigned long flags; |
632 | 633 | ||
633 | if (!(raw->port.flags & ASYNC_INITIALIZED)) | 634 | if (!(raw->port.flags & ASYNC_INITIALIZED) || |
635 | (raw->flags & RAW3215_FIXED)) | ||
634 | return; | 636 | return; |
635 | /* Wait for outstanding requests, then free irq */ | 637 | /* Wait for outstanding requests, then free irq */ |
636 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); | 638 | spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags); |
@@ -805,7 +807,7 @@ static struct ccw_driver raw3215_ccw_driver = { | |||
805 | .freeze = &raw3215_pm_stop, | 807 | .freeze = &raw3215_pm_stop, |
806 | .thaw = &raw3215_pm_start, | 808 | .thaw = &raw3215_pm_start, |
807 | .restore = &raw3215_pm_start, | 809 | .restore = &raw3215_pm_start, |
808 | .int_class = IOINT_C15, | 810 | .int_class = IRQIO_C15, |
809 | }; | 811 | }; |
810 | 812 | ||
811 | #ifdef CONFIG_TN3215_CONSOLE | 813 | #ifdef CONFIG_TN3215_CONSOLE |
@@ -927,6 +929,8 @@ static int __init con3215_init(void) | |||
927 | dev_set_drvdata(&cdev->dev, raw); | 929 | dev_set_drvdata(&cdev->dev, raw); |
928 | cdev->handler = raw3215_irq; | 930 | cdev->handler = raw3215_irq; |
929 | 931 | ||
932 | raw->flags |= RAW3215_FIXED; | ||
933 | |||
930 | /* Request the console irq */ | 934 | /* Request the console irq */ |
931 | if (raw3215_startup(raw) != 0) { | 935 | if (raw3215_startup(raw) != 0) { |
932 | raw3215_free_info(raw); | 936 | raw3215_free_info(raw); |
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c index f3b8bb84faf2..9a6c140c5f07 100644 --- a/drivers/s390/char/raw3270.c +++ b/drivers/s390/char/raw3270.c | |||
@@ -1396,7 +1396,7 @@ static struct ccw_driver raw3270_ccw_driver = { | |||
1396 | .freeze = &raw3270_pm_stop, | 1396 | .freeze = &raw3270_pm_stop, |
1397 | .thaw = &raw3270_pm_start, | 1397 | .thaw = &raw3270_pm_start, |
1398 | .restore = &raw3270_pm_start, | 1398 | .restore = &raw3270_pm_start, |
1399 | .int_class = IOINT_C70, | 1399 | .int_class = IRQIO_C70, |
1400 | }; | 1400 | }; |
1401 | 1401 | ||
1402 | static int | 1402 | static int |
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c index 4fa21f7e2308..12c16a65dd25 100644 --- a/drivers/s390/char/sclp.c +++ b/drivers/s390/char/sclp.c | |||
@@ -400,7 +400,7 @@ static void sclp_interrupt_handler(struct ext_code ext_code, | |||
400 | u32 finished_sccb; | 400 | u32 finished_sccb; |
401 | u32 evbuf_pending; | 401 | u32 evbuf_pending; |
402 | 402 | ||
403 | kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++; | 403 | inc_irq_stat(IRQEXT_SCP); |
404 | spin_lock(&sclp_lock); | 404 | spin_lock(&sclp_lock); |
405 | finished_sccb = param32 & 0xfffffff8; | 405 | finished_sccb = param32 & 0xfffffff8; |
406 | evbuf_pending = param32 & 0x3; | 406 | evbuf_pending = param32 & 0x3; |
@@ -813,7 +813,7 @@ static void sclp_check_handler(struct ext_code ext_code, | |||
813 | { | 813 | { |
814 | u32 finished_sccb; | 814 | u32 finished_sccb; |
815 | 815 | ||
816 | kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++; | 816 | inc_irq_stat(IRQEXT_SCP); |
817 | finished_sccb = param32 & 0xfffffff8; | 817 | finished_sccb = param32 & 0xfffffff8; |
818 | /* Is this the interrupt we are waiting for? */ | 818 | /* Is this the interrupt we are waiting for? */ |
819 | if (finished_sccb == 0) | 819 | if (finished_sccb == 0) |
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 6ae929c024ae..9aa79702b370 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
@@ -1193,7 +1193,7 @@ static struct ccw_driver tape_34xx_driver = { | |||
1193 | .set_online = tape_34xx_online, | 1193 | .set_online = tape_34xx_online, |
1194 | .set_offline = tape_generic_offline, | 1194 | .set_offline = tape_generic_offline, |
1195 | .freeze = tape_generic_pm_suspend, | 1195 | .freeze = tape_generic_pm_suspend, |
1196 | .int_class = IOINT_TAP, | 1196 | .int_class = IRQIO_TAP, |
1197 | }; | 1197 | }; |
1198 | 1198 | ||
1199 | static int | 1199 | static int |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 1b0eb49f739c..327cb19ad0b0 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
@@ -1656,7 +1656,7 @@ static struct ccw_driver tape_3590_driver = { | |||
1656 | .set_offline = tape_generic_offline, | 1656 | .set_offline = tape_generic_offline, |
1657 | .set_online = tape_3590_online, | 1657 | .set_online = tape_3590_online, |
1658 | .freeze = tape_generic_pm_suspend, | 1658 | .freeze = tape_generic_pm_suspend, |
1659 | .int_class = IOINT_TAP, | 1659 | .int_class = IRQIO_TAP, |
1660 | }; | 1660 | }; |
1661 | 1661 | ||
1662 | /* | 1662 | /* |
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c index 73bef0bd394c..483f72ba030d 100644 --- a/drivers/s390/char/vmur.c +++ b/drivers/s390/char/vmur.c | |||
@@ -74,7 +74,7 @@ static struct ccw_driver ur_driver = { | |||
74 | .set_online = ur_set_online, | 74 | .set_online = ur_set_online, |
75 | .set_offline = ur_set_offline, | 75 | .set_offline = ur_set_offline, |
76 | .freeze = ur_pm_suspend, | 76 | .freeze = ur_pm_suspend, |
77 | .int_class = IOINT_VMR, | 77 | .int_class = IRQIO_VMR, |
78 | }; | 78 | }; |
79 | 79 | ||
80 | static DEFINE_MUTEX(vmur_mutex); | 80 | static DEFINE_MUTEX(vmur_mutex); |
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c index 68e80e2734a4..10729bbceced 100644 --- a/drivers/s390/cio/chsc.c +++ b/drivers/s390/cio/chsc.c | |||
@@ -283,7 +283,7 @@ struct chsc_sei_nt2_area { | |||
283 | u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ | 283 | u8 ccdf[PAGE_SIZE - 24 - 56]; /* content-code dependent field */ |
284 | } __packed; | 284 | } __packed; |
285 | 285 | ||
286 | #define CHSC_SEI_NT0 0ULL | 286 | #define CHSC_SEI_NT0 (1ULL << 63) |
287 | #define CHSC_SEI_NT2 (1ULL << 61) | 287 | #define CHSC_SEI_NT2 (1ULL << 61) |
288 | 288 | ||
289 | struct chsc_sei { | 289 | struct chsc_sei { |
@@ -291,7 +291,8 @@ struct chsc_sei { | |||
291 | u32 reserved1; | 291 | u32 reserved1; |
292 | u64 ntsm; /* notification type mask */ | 292 | u64 ntsm; /* notification type mask */ |
293 | struct chsc_header response; | 293 | struct chsc_header response; |
294 | u32 reserved2; | 294 | u32 :24; |
295 | u8 nt; | ||
295 | union { | 296 | union { |
296 | struct chsc_sei_nt0_area nt0_area; | 297 | struct chsc_sei_nt0_area nt0_area; |
297 | struct chsc_sei_nt2_area nt2_area; | 298 | struct chsc_sei_nt2_area nt2_area; |
@@ -496,17 +497,17 @@ static int __chsc_process_crw(struct chsc_sei *sei, u64 ntsm) | |||
496 | css_schedule_eval_all(); | 497 | css_schedule_eval_all(); |
497 | } | 498 | } |
498 | 499 | ||
499 | switch (sei->ntsm) { | 500 | switch (sei->nt) { |
500 | case CHSC_SEI_NT0: | 501 | case 0: |
501 | chsc_process_sei_nt0(&sei->u.nt0_area); | 502 | chsc_process_sei_nt0(&sei->u.nt0_area); |
502 | return 1; | 503 | break; |
503 | case CHSC_SEI_NT2: | 504 | case 2: |
504 | chsc_process_sei_nt2(&sei->u.nt2_area); | 505 | chsc_process_sei_nt2(&sei->u.nt2_area); |
505 | return 1; | 506 | break; |
506 | default: | 507 | default: |
507 | CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n", | 508 | CIO_CRW_EVENT(2, "chsc: unhandled nt=%d\n", |
508 | sei->ntsm); | 509 | sei->nt); |
509 | return 0; | 510 | break; |
510 | } | 511 | } |
511 | } else { | 512 | } else { |
512 | CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", | 513 | CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n", |
@@ -537,15 +538,7 @@ static void chsc_process_crw(struct crw *crw0, struct crw *crw1, int overflow) | |||
537 | sei = sei_page; | 538 | sei = sei_page; |
538 | 539 | ||
539 | CIO_TRACE_EVENT(2, "prcss"); | 540 | CIO_TRACE_EVENT(2, "prcss"); |
540 | 541 | __chsc_process_crw(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2); | |
541 | /* | ||
542 | * The ntsm does not allow to select NT0 and NT2 together. We need to | ||
543 | * first check for NT2, than additionally for NT0... | ||
544 | */ | ||
545 | #ifdef CONFIG_PCI | ||
546 | if (!__chsc_process_crw(sei, CHSC_SEI_NT2)) | ||
547 | #endif | ||
548 | __chsc_process_crw(sei, CHSC_SEI_NT0); | ||
549 | } | 542 | } |
550 | 543 | ||
551 | void chsc_chp_online(struct chp_id chpid) | 544 | void chsc_chp_online(struct chp_id chpid) |
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c index 8f9a1a384496..facdf809113f 100644 --- a/drivers/s390/cio/chsc_sch.c +++ b/drivers/s390/cio/chsc_sch.c | |||
@@ -58,7 +58,7 @@ static void chsc_subchannel_irq(struct subchannel *sch) | |||
58 | 58 | ||
59 | CHSC_LOG(4, "irb"); | 59 | CHSC_LOG(4, "irb"); |
60 | CHSC_LOG_HEX(4, irb, sizeof(*irb)); | 60 | CHSC_LOG_HEX(4, irb, sizeof(*irb)); |
61 | kstat_cpu(smp_processor_id()).irqs[IOINT_CSC]++; | 61 | inc_irq_stat(IRQIO_CSC); |
62 | 62 | ||
63 | /* Copy irb to provided request and set done. */ | 63 | /* Copy irb to provided request and set done. */ |
64 | if (!request) { | 64 | if (!request) { |
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c index 8e927b9f285f..c8faf6230b0f 100644 --- a/drivers/s390/cio/cio.c +++ b/drivers/s390/cio/cio.c | |||
@@ -611,7 +611,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
611 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; | 611 | tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id; |
612 | irb = (struct irb *)&S390_lowcore.irb; | 612 | irb = (struct irb *)&S390_lowcore.irb; |
613 | do { | 613 | do { |
614 | kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++; | 614 | kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL); |
615 | if (tpi_info->adapter_IO) { | 615 | if (tpi_info->adapter_IO) { |
616 | do_adapter_IO(tpi_info->isc); | 616 | do_adapter_IO(tpi_info->isc); |
617 | continue; | 617 | continue; |
@@ -619,7 +619,7 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
619 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; | 619 | sch = (struct subchannel *)(unsigned long)tpi_info->intparm; |
620 | if (!sch) { | 620 | if (!sch) { |
621 | /* Clear pending interrupt condition. */ | 621 | /* Clear pending interrupt condition. */ |
622 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 622 | inc_irq_stat(IRQIO_CIO); |
623 | tsch(tpi_info->schid, irb); | 623 | tsch(tpi_info->schid, irb); |
624 | continue; | 624 | continue; |
625 | } | 625 | } |
@@ -633,9 +633,9 @@ void __irq_entry do_IRQ(struct pt_regs *regs) | |||
633 | if (sch->driver && sch->driver->irq) | 633 | if (sch->driver && sch->driver->irq) |
634 | sch->driver->irq(sch); | 634 | sch->driver->irq(sch); |
635 | else | 635 | else |
636 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 636 | inc_irq_stat(IRQIO_CIO); |
637 | } else | 637 | } else |
638 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 638 | inc_irq_stat(IRQIO_CIO); |
639 | spin_unlock(sch->lock); | 639 | spin_unlock(sch->lock); |
640 | /* | 640 | /* |
641 | * Are more interrupts pending? | 641 | * Are more interrupts pending? |
@@ -678,7 +678,7 @@ static void cio_tsch(struct subchannel *sch) | |||
678 | if (sch->driver && sch->driver->irq) | 678 | if (sch->driver && sch->driver->irq) |
679 | sch->driver->irq(sch); | 679 | sch->driver->irq(sch); |
680 | else | 680 | else |
681 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 681 | inc_irq_stat(IRQIO_CIO); |
682 | if (!irq_context) { | 682 | if (!irq_context) { |
683 | irq_exit(); | 683 | irq_exit(); |
684 | _local_bh_enable(); | 684 | _local_bh_enable(); |
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c index 6995cff44636..7cd5c6812ac7 100644 --- a/drivers/s390/cio/device.c +++ b/drivers/s390/cio/device.c | |||
@@ -758,7 +758,7 @@ static int io_subchannel_initialize_dev(struct subchannel *sch, | |||
758 | struct ccw_device *cdev) | 758 | struct ccw_device *cdev) |
759 | { | 759 | { |
760 | cdev->private->cdev = cdev; | 760 | cdev->private->cdev = cdev; |
761 | cdev->private->int_class = IOINT_CIO; | 761 | cdev->private->int_class = IRQIO_CIO; |
762 | atomic_set(&cdev->private->onoff, 0); | 762 | atomic_set(&cdev->private->onoff, 0); |
763 | cdev->dev.parent = &sch->dev; | 763 | cdev->dev.parent = &sch->dev; |
764 | cdev->dev.release = ccw_device_release; | 764 | cdev->dev.release = ccw_device_release; |
@@ -1023,7 +1023,7 @@ static void io_subchannel_irq(struct subchannel *sch) | |||
1023 | if (cdev) | 1023 | if (cdev) |
1024 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); | 1024 | dev_fsm_event(cdev, DEV_EVENT_INTERRUPT); |
1025 | else | 1025 | else |
1026 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 1026 | inc_irq_stat(IRQIO_CIO); |
1027 | } | 1027 | } |
1028 | 1028 | ||
1029 | void io_subchannel_init_config(struct subchannel *sch) | 1029 | void io_subchannel_init_config(struct subchannel *sch) |
@@ -1634,7 +1634,7 @@ ccw_device_probe_console(void) | |||
1634 | memset(&console_private, 0, sizeof(struct ccw_device_private)); | 1634 | memset(&console_private, 0, sizeof(struct ccw_device_private)); |
1635 | console_cdev.private = &console_private; | 1635 | console_cdev.private = &console_private; |
1636 | console_private.cdev = &console_cdev; | 1636 | console_private.cdev = &console_cdev; |
1637 | console_private.int_class = IOINT_CIO; | 1637 | console_private.int_class = IRQIO_CIO; |
1638 | ret = ccw_device_console_enable(&console_cdev, sch); | 1638 | ret = ccw_device_console_enable(&console_cdev, sch); |
1639 | if (ret) { | 1639 | if (ret) { |
1640 | cio_release_console(); | 1640 | cio_release_console(); |
@@ -1715,13 +1715,13 @@ ccw_device_probe (struct device *dev) | |||
1715 | if (cdrv->int_class != 0) | 1715 | if (cdrv->int_class != 0) |
1716 | cdev->private->int_class = cdrv->int_class; | 1716 | cdev->private->int_class = cdrv->int_class; |
1717 | else | 1717 | else |
1718 | cdev->private->int_class = IOINT_CIO; | 1718 | cdev->private->int_class = IRQIO_CIO; |
1719 | 1719 | ||
1720 | ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; | 1720 | ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV; |
1721 | 1721 | ||
1722 | if (ret) { | 1722 | if (ret) { |
1723 | cdev->drv = NULL; | 1723 | cdev->drv = NULL; |
1724 | cdev->private->int_class = IOINT_CIO; | 1724 | cdev->private->int_class = IRQIO_CIO; |
1725 | return ret; | 1725 | return ret; |
1726 | } | 1726 | } |
1727 | 1727 | ||
@@ -1755,7 +1755,7 @@ ccw_device_remove (struct device *dev) | |||
1755 | } | 1755 | } |
1756 | ccw_device_set_timeout(cdev, 0); | 1756 | ccw_device_set_timeout(cdev, 0); |
1757 | cdev->drv = NULL; | 1757 | cdev->drv = NULL; |
1758 | cdev->private->int_class = IOINT_CIO; | 1758 | cdev->private->int_class = IRQIO_CIO; |
1759 | return 0; | 1759 | return 0; |
1760 | } | 1760 | } |
1761 | 1761 | ||
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h index 2e575cff9845..7d4ecb65db00 100644 --- a/drivers/s390/cio/device.h +++ b/drivers/s390/cio/device.h | |||
@@ -61,11 +61,10 @@ dev_fsm_event(struct ccw_device *cdev, enum dev_event dev_event) | |||
61 | 61 | ||
62 | if (dev_event == DEV_EVENT_INTERRUPT) { | 62 | if (dev_event == DEV_EVENT_INTERRUPT) { |
63 | if (state == DEV_STATE_ONLINE) | 63 | if (state == DEV_STATE_ONLINE) |
64 | kstat_cpu(smp_processor_id()). | 64 | inc_irq_stat(cdev->private->int_class); |
65 | irqs[cdev->private->int_class]++; | ||
66 | else if (state != DEV_STATE_CMFCHANGE && | 65 | else if (state != DEV_STATE_CMFCHANGE && |
67 | state != DEV_STATE_CMFUPDATE) | 66 | state != DEV_STATE_CMFUPDATE) |
68 | kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++; | 67 | inc_irq_stat(IRQIO_CIO); |
69 | } | 68 | } |
70 | dev_jumptable[state][dev_event](cdev, dev_event); | 69 | dev_jumptable[state][dev_event](cdev, dev_event); |
71 | } | 70 | } |
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c index 6c9673400464..d9eddcba7e88 100644 --- a/drivers/s390/cio/eadm_sch.c +++ b/drivers/s390/cio/eadm_sch.c | |||
@@ -139,7 +139,7 @@ static void eadm_subchannel_irq(struct subchannel *sch) | |||
139 | EADM_LOG(6, "irq"); | 139 | EADM_LOG(6, "irq"); |
140 | EADM_LOG_HEX(6, irb, sizeof(*irb)); | 140 | EADM_LOG_HEX(6, irb, sizeof(*irb)); |
141 | 141 | ||
142 | kstat_cpu(smp_processor_id()).irqs[IOINT_ADM]++; | 142 | inc_irq_stat(IRQIO_ADM); |
143 | 143 | ||
144 | if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) | 144 | if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND)) |
145 | && scsw->eswf == 1 && irb->esw.eadm.erw.r) | 145 | && scsw->eswf == 1 && irb->esw.eadm.erw.r) |
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c index bdb394b066fc..bde5255200dc 100644 --- a/drivers/s390/cio/qdio_thinint.c +++ b/drivers/s390/cio/qdio_thinint.c | |||
@@ -182,7 +182,7 @@ static void tiqdio_thinint_handler(void *alsi, void *data) | |||
182 | struct qdio_q *q; | 182 | struct qdio_q *q; |
183 | 183 | ||
184 | last_ai_time = S390_lowcore.int_clock; | 184 | last_ai_time = S390_lowcore.int_clock; |
185 | kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++; | 185 | inc_irq_stat(IRQIO_QAI); |
186 | 186 | ||
187 | /* protect tiq_list entries, only changed in activate or shutdown */ | 187 | /* protect tiq_list entries, only changed in activate or shutdown */ |
188 | rcu_read_lock(); | 188 | rcu_read_lock(); |
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c index 7b865a7300e6..b8b340ac5332 100644 --- a/drivers/s390/crypto/ap_bus.c +++ b/drivers/s390/crypto/ap_bus.c | |||
@@ -1272,7 +1272,7 @@ out: | |||
1272 | 1272 | ||
1273 | static void ap_interrupt_handler(void *unused1, void *unused2) | 1273 | static void ap_interrupt_handler(void *unused1, void *unused2) |
1274 | { | 1274 | { |
1275 | kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++; | 1275 | inc_irq_stat(IRQIO_APB); |
1276 | tasklet_schedule(&ap_tasklet); | 1276 | tasklet_schedule(&ap_tasklet); |
1277 | } | 1277 | } |
1278 | 1278 | ||
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c index 7dabef624da3..8491111aec12 100644 --- a/drivers/s390/kvm/kvm_virtio.c +++ b/drivers/s390/kvm/kvm_virtio.c | |||
@@ -392,7 +392,7 @@ static void kvm_extint_handler(struct ext_code ext_code, | |||
392 | 392 | ||
393 | if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64) | 393 | if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64) |
394 | return; | 394 | return; |
395 | kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++; | 395 | inc_irq_stat(IRQEXT_VRT); |
396 | 396 | ||
397 | /* The LSB might be overloaded, we have to mask it */ | 397 | /* The LSB might be overloaded, we have to mask it */ |
398 | vq = (struct virtqueue *)(param64 & ~1UL); | 398 | vq = (struct virtqueue *)(param64 & ~1UL); |
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c index 5c70a6599578..83bc9c5fa0c1 100644 --- a/drivers/s390/net/claw.c +++ b/drivers/s390/net/claw.c | |||
@@ -282,7 +282,7 @@ static struct ccw_driver claw_ccw_driver = { | |||
282 | .ids = claw_ids, | 282 | .ids = claw_ids, |
283 | .probe = ccwgroup_probe_ccwdev, | 283 | .probe = ccwgroup_probe_ccwdev, |
284 | .remove = ccwgroup_remove_ccwdev, | 284 | .remove = ccwgroup_remove_ccwdev, |
285 | .int_class = IOINT_CLW, | 285 | .int_class = IRQIO_CLW, |
286 | }; | 286 | }; |
287 | 287 | ||
288 | static ssize_t claw_driver_group_store(struct device_driver *ddrv, | 288 | static ssize_t claw_driver_group_store(struct device_driver *ddrv, |
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c index 817b68925ddd..676f12049a36 100644 --- a/drivers/s390/net/ctcm_main.c +++ b/drivers/s390/net/ctcm_main.c | |||
@@ -1755,7 +1755,7 @@ static struct ccw_driver ctcm_ccw_driver = { | |||
1755 | .ids = ctcm_ids, | 1755 | .ids = ctcm_ids, |
1756 | .probe = ccwgroup_probe_ccwdev, | 1756 | .probe = ccwgroup_probe_ccwdev, |
1757 | .remove = ccwgroup_remove_ccwdev, | 1757 | .remove = ccwgroup_remove_ccwdev, |
1758 | .int_class = IOINT_CTC, | 1758 | .int_class = IRQIO_CTC, |
1759 | }; | 1759 | }; |
1760 | 1760 | ||
1761 | static struct ccwgroup_driver ctcm_group_driver = { | 1761 | static struct ccwgroup_driver ctcm_group_driver = { |
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c index 2ca0f1dd7a00..c645dc9e98af 100644 --- a/drivers/s390/net/lcs.c +++ b/drivers/s390/net/lcs.c | |||
@@ -2384,7 +2384,7 @@ static struct ccw_driver lcs_ccw_driver = { | |||
2384 | .ids = lcs_ids, | 2384 | .ids = lcs_ids, |
2385 | .probe = ccwgroup_probe_ccwdev, | 2385 | .probe = ccwgroup_probe_ccwdev, |
2386 | .remove = ccwgroup_remove_ccwdev, | 2386 | .remove = ccwgroup_remove_ccwdev, |
2387 | .int_class = IOINT_LCS, | 2387 | .int_class = IRQIO_LCS, |
2388 | }; | 2388 | }; |
2389 | 2389 | ||
2390 | /** | 2390 | /** |
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c index d73fdcfeb45a..2839baa82a5a 100644 --- a/drivers/scsi/isci/init.c +++ b/drivers/scsi/isci/init.c | |||
@@ -633,7 +633,7 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) | |||
633 | return -ENOMEM; | 633 | return -ENOMEM; |
634 | pci_set_drvdata(pdev, pci_info); | 634 | pci_set_drvdata(pdev, pci_info); |
635 | 635 | ||
636 | if (efi_enabled) | 636 | if (efi_enabled(EFI_RUNTIME_SERVICES)) |
637 | orom = isci_get_efi_var(pdev); | 637 | orom = isci_get_efi_var(pdev); |
638 | 638 | ||
639 | if (!orom) | 639 | if (!orom) |
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c index 5aedcdf4ac5c..1ebe67cd1833 100644 --- a/drivers/sh/clk/cpg.c +++ b/drivers/sh/clk/cpg.c | |||
@@ -126,6 +126,12 @@ static int sh_clk_div_set_rate(struct clk *clk, unsigned long rate) | |||
126 | 126 | ||
127 | static int sh_clk_div_enable(struct clk *clk) | 127 | static int sh_clk_div_enable(struct clk *clk) |
128 | { | 128 | { |
129 | if (clk->div_mask == SH_CLK_DIV6_MSK) { | ||
130 | int ret = sh_clk_div_set_rate(clk, clk->rate); | ||
131 | if (ret < 0) | ||
132 | return ret; | ||
133 | } | ||
134 | |||
129 | sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); | 135 | sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk); |
130 | return 0; | 136 | return 0; |
131 | } | 137 | } |
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 19ee901577da..3a6083b386a1 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/of_gpio.h> | 33 | #include <linux/of_gpio.h> |
34 | #include <linux/pm_runtime.h> | 34 | #include <linux/pm_runtime.h> |
35 | #include <linux/export.h> | 35 | #include <linux/export.h> |
36 | #include <linux/sched.h> | 36 | #include <linux/sched/rt.h> |
37 | #include <linux/delay.h> | 37 | #include <linux/delay.h> |
38 | #include <linux/kthread.h> | 38 | #include <linux/kthread.h> |
39 | #include <linux/ioport.h> | 39 | #include <linux/ioport.h> |
diff --git a/drivers/ssb/driver_gpio.c b/drivers/ssb/driver_gpio.c index 97ac0a38e3d0..eb2753008ef0 100644 --- a/drivers/ssb/driver_gpio.c +++ b/drivers/ssb/driver_gpio.c | |||
@@ -174,3 +174,15 @@ int ssb_gpio_init(struct ssb_bus *bus) | |||
174 | 174 | ||
175 | return -1; | 175 | return -1; |
176 | } | 176 | } |
177 | |||
178 | int ssb_gpio_unregister(struct ssb_bus *bus) | ||
179 | { | ||
180 | if (ssb_chipco_available(&bus->chipco) || | ||
181 | ssb_extif_available(&bus->extif)) { | ||
182 | return gpiochip_remove(&bus->gpio); | ||
183 | } else { | ||
184 | SSB_WARN_ON(1); | ||
185 | } | ||
186 | |||
187 | return -1; | ||
188 | } | ||
diff --git a/drivers/ssb/main.c b/drivers/ssb/main.c index 772ad9b5c304..24dc331b4701 100644 --- a/drivers/ssb/main.c +++ b/drivers/ssb/main.c | |||
@@ -443,6 +443,15 @@ static void ssb_devices_unregister(struct ssb_bus *bus) | |||
443 | 443 | ||
444 | void ssb_bus_unregister(struct ssb_bus *bus) | 444 | void ssb_bus_unregister(struct ssb_bus *bus) |
445 | { | 445 | { |
446 | int err; | ||
447 | |||
448 | err = ssb_gpio_unregister(bus); | ||
449 | if (err == -EBUSY) | ||
450 | ssb_dprintk(KERN_ERR PFX "Some GPIOs are still in use.\n"); | ||
451 | else if (err) | ||
452 | ssb_dprintk(KERN_ERR PFX | ||
453 | "Can not unregister GPIO driver: %i\n", err); | ||
454 | |||
446 | ssb_buses_lock(); | 455 | ssb_buses_lock(); |
447 | ssb_devices_unregister(bus); | 456 | ssb_devices_unregister(bus); |
448 | list_del(&bus->list); | 457 | list_del(&bus->list); |
diff --git a/drivers/ssb/ssb_private.h b/drivers/ssb/ssb_private.h index 6c10b66c796c..da38305a2d22 100644 --- a/drivers/ssb/ssb_private.h +++ b/drivers/ssb/ssb_private.h | |||
@@ -252,11 +252,16 @@ static inline void ssb_extif_init(struct ssb_extif *extif) | |||
252 | 252 | ||
253 | #ifdef CONFIG_SSB_DRIVER_GPIO | 253 | #ifdef CONFIG_SSB_DRIVER_GPIO |
254 | extern int ssb_gpio_init(struct ssb_bus *bus); | 254 | extern int ssb_gpio_init(struct ssb_bus *bus); |
255 | extern int ssb_gpio_unregister(struct ssb_bus *bus); | ||
255 | #else /* CONFIG_SSB_DRIVER_GPIO */ | 256 | #else /* CONFIG_SSB_DRIVER_GPIO */ |
256 | static inline int ssb_gpio_init(struct ssb_bus *bus) | 257 | static inline int ssb_gpio_init(struct ssb_bus *bus) |
257 | { | 258 | { |
258 | return -ENOTSUPP; | 259 | return -ENOTSUPP; |
259 | } | 260 | } |
261 | static inline int ssb_gpio_unregister(struct ssb_bus *bus) | ||
262 | { | ||
263 | return 0; | ||
264 | } | ||
260 | #endif /* CONFIG_SSB_DRIVER_GPIO */ | 265 | #endif /* CONFIG_SSB_DRIVER_GPIO */ |
261 | 266 | ||
262 | #endif /* LINUX_SSB_PRIVATE_H_ */ | 267 | #endif /* LINUX_SSB_PRIVATE_H_ */ |
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig index 7de2a10213bd..36eec320569c 100644 --- a/drivers/staging/comedi/Kconfig +++ b/drivers/staging/comedi/Kconfig | |||
@@ -444,6 +444,7 @@ config COMEDI_ADQ12B | |||
444 | 444 | ||
445 | config COMEDI_NI_AT_A2150 | 445 | config COMEDI_NI_AT_A2150 |
446 | tristate "NI AT-A2150 ISA card support" | 446 | tristate "NI AT-A2150 ISA card support" |
447 | select COMEDI_FC | ||
447 | depends on VIRT_TO_BUS | 448 | depends on VIRT_TO_BUS |
448 | ---help--- | 449 | ---help--- |
449 | Enable support for National Instruments AT-A2150 cards | 450 | Enable support for National Instruments AT-A2150 cards |
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c index b7bba1790a20..9b038e4a7e71 100644 --- a/drivers/staging/comedi/comedi_fops.c +++ b/drivers/staging/comedi/comedi_fops.c | |||
@@ -1549,6 +1549,9 @@ static long comedi_unlocked_ioctl(struct file *file, unsigned int cmd, | |||
1549 | if (cmd == COMEDI_DEVCONFIG) { | 1549 | if (cmd == COMEDI_DEVCONFIG) { |
1550 | rc = do_devconfig_ioctl(dev, | 1550 | rc = do_devconfig_ioctl(dev, |
1551 | (struct comedi_devconfig __user *)arg); | 1551 | (struct comedi_devconfig __user *)arg); |
1552 | if (rc == 0) | ||
1553 | /* Evade comedi_auto_unconfig(). */ | ||
1554 | dev_file_info->hardware_device = NULL; | ||
1552 | goto done; | 1555 | goto done; |
1553 | } | 1556 | } |
1554 | 1557 | ||
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c index fb3d09323ba1..01de996239f1 100644 --- a/drivers/staging/comedi/drivers/comedi_test.c +++ b/drivers/staging/comedi/drivers/comedi_test.c | |||
@@ -345,7 +345,7 @@ static int waveform_ai_cancel(struct comedi_device *dev, | |||
345 | struct waveform_private *devpriv = dev->private; | 345 | struct waveform_private *devpriv = dev->private; |
346 | 346 | ||
347 | devpriv->timer_running = 0; | 347 | devpriv->timer_running = 0; |
348 | del_timer(&devpriv->timer); | 348 | del_timer_sync(&devpriv->timer); |
349 | return 0; | 349 | return 0; |
350 | } | 350 | } |
351 | 351 | ||
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c index aaac0b2cc9eb..fd1662b4175d 100644 --- a/drivers/staging/comedi/drivers/ni_pcimio.c +++ b/drivers/staging/comedi/drivers/ni_pcimio.c | |||
@@ -963,7 +963,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
963 | .ao_range_table = &range_ni_M_625x_ao, | 963 | .ao_range_table = &range_ni_M_625x_ao, |
964 | .reg_type = ni_reg_625x, | 964 | .reg_type = ni_reg_625x, |
965 | .ao_unipolar = 0, | 965 | .ao_unipolar = 0, |
966 | .ao_speed = 357, | 966 | .ao_speed = 350, |
967 | .num_p0_dio_channels = 8, | 967 | .num_p0_dio_channels = 8, |
968 | .caldac = {caldac_none}, | 968 | .caldac = {caldac_none}, |
969 | .has_8255 = 0, | 969 | .has_8255 = 0, |
@@ -982,7 +982,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
982 | .ao_range_table = &range_ni_M_625x_ao, | 982 | .ao_range_table = &range_ni_M_625x_ao, |
983 | .reg_type = ni_reg_625x, | 983 | .reg_type = ni_reg_625x, |
984 | .ao_unipolar = 0, | 984 | .ao_unipolar = 0, |
985 | .ao_speed = 357, | 985 | .ao_speed = 350, |
986 | .num_p0_dio_channels = 8, | 986 | .num_p0_dio_channels = 8, |
987 | .caldac = {caldac_none}, | 987 | .caldac = {caldac_none}, |
988 | .has_8255 = 0, | 988 | .has_8255 = 0, |
@@ -1001,7 +1001,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1001 | .ao_range_table = &range_ni_M_625x_ao, | 1001 | .ao_range_table = &range_ni_M_625x_ao, |
1002 | .reg_type = ni_reg_625x, | 1002 | .reg_type = ni_reg_625x, |
1003 | .ao_unipolar = 0, | 1003 | .ao_unipolar = 0, |
1004 | .ao_speed = 357, | 1004 | .ao_speed = 350, |
1005 | .num_p0_dio_channels = 8, | 1005 | .num_p0_dio_channels = 8, |
1006 | .caldac = {caldac_none}, | 1006 | .caldac = {caldac_none}, |
1007 | .has_8255 = 0, | 1007 | .has_8255 = 0, |
@@ -1037,7 +1037,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1037 | .ao_range_table = &range_ni_M_625x_ao, | 1037 | .ao_range_table = &range_ni_M_625x_ao, |
1038 | .reg_type = ni_reg_625x, | 1038 | .reg_type = ni_reg_625x, |
1039 | .ao_unipolar = 0, | 1039 | .ao_unipolar = 0, |
1040 | .ao_speed = 357, | 1040 | .ao_speed = 350, |
1041 | .num_p0_dio_channels = 32, | 1041 | .num_p0_dio_channels = 32, |
1042 | .caldac = {caldac_none}, | 1042 | .caldac = {caldac_none}, |
1043 | .has_8255 = 0, | 1043 | .has_8255 = 0, |
@@ -1056,7 +1056,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1056 | .ao_range_table = &range_ni_M_625x_ao, | 1056 | .ao_range_table = &range_ni_M_625x_ao, |
1057 | .reg_type = ni_reg_625x, | 1057 | .reg_type = ni_reg_625x, |
1058 | .ao_unipolar = 0, | 1058 | .ao_unipolar = 0, |
1059 | .ao_speed = 357, | 1059 | .ao_speed = 350, |
1060 | .num_p0_dio_channels = 32, | 1060 | .num_p0_dio_channels = 32, |
1061 | .caldac = {caldac_none}, | 1061 | .caldac = {caldac_none}, |
1062 | .has_8255 = 0, | 1062 | .has_8255 = 0, |
@@ -1092,7 +1092,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1092 | .ao_range_table = &range_ni_M_628x_ao, | 1092 | .ao_range_table = &range_ni_M_628x_ao, |
1093 | .reg_type = ni_reg_628x, | 1093 | .reg_type = ni_reg_628x, |
1094 | .ao_unipolar = 1, | 1094 | .ao_unipolar = 1, |
1095 | .ao_speed = 357, | 1095 | .ao_speed = 350, |
1096 | .num_p0_dio_channels = 8, | 1096 | .num_p0_dio_channels = 8, |
1097 | .caldac = {caldac_none}, | 1097 | .caldac = {caldac_none}, |
1098 | .has_8255 = 0, | 1098 | .has_8255 = 0, |
@@ -1111,7 +1111,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1111 | .ao_range_table = &range_ni_M_628x_ao, | 1111 | .ao_range_table = &range_ni_M_628x_ao, |
1112 | .reg_type = ni_reg_628x, | 1112 | .reg_type = ni_reg_628x, |
1113 | .ao_unipolar = 1, | 1113 | .ao_unipolar = 1, |
1114 | .ao_speed = 357, | 1114 | .ao_speed = 350, |
1115 | .num_p0_dio_channels = 8, | 1115 | .num_p0_dio_channels = 8, |
1116 | .caldac = {caldac_none}, | 1116 | .caldac = {caldac_none}, |
1117 | .has_8255 = 0, | 1117 | .has_8255 = 0, |
@@ -1147,7 +1147,7 @@ static const struct ni_board_struct ni_boards[] = { | |||
1147 | .ao_range_table = &range_ni_M_628x_ao, | 1147 | .ao_range_table = &range_ni_M_628x_ao, |
1148 | .reg_type = ni_reg_628x, | 1148 | .reg_type = ni_reg_628x, |
1149 | .ao_unipolar = 1, | 1149 | .ao_unipolar = 1, |
1150 | .ao_speed = 357, | 1150 | .ao_speed = 350, |
1151 | .num_p0_dio_channels = 32, | 1151 | .num_p0_dio_channels = 32, |
1152 | .caldac = {caldac_none}, | 1152 | .caldac = {caldac_none}, |
1153 | .has_8255 = 0, | 1153 | .has_8255 = 0, |
diff --git a/drivers/staging/csr/bh.c b/drivers/staging/csr/bh.c index 1a1f5c79822a..7b133597e923 100644 --- a/drivers/staging/csr/bh.c +++ b/drivers/staging/csr/bh.c | |||
@@ -15,7 +15,7 @@ | |||
15 | */ | 15 | */ |
16 | #include "csr_wifi_hip_unifi.h" | 16 | #include "csr_wifi_hip_unifi.h" |
17 | #include "unifi_priv.h" | 17 | #include "unifi_priv.h" |
18 | 18 | #include <linux/sched/rt.h> | |
19 | 19 | ||
20 | /* | 20 | /* |
21 | * --------------------------------------------------------------------------- | 21 | * --------------------------------------------------------------------------- |
diff --git a/drivers/staging/csr/unifi_sme.c b/drivers/staging/csr/unifi_sme.c index 7c6c4138fc76..49395da34b7f 100644 --- a/drivers/staging/csr/unifi_sme.c +++ b/drivers/staging/csr/unifi_sme.c | |||
@@ -15,7 +15,7 @@ | |||
15 | #include "unifi_priv.h" | 15 | #include "unifi_priv.h" |
16 | #include "csr_wifi_hip_unifi.h" | 16 | #include "csr_wifi_hip_unifi.h" |
17 | #include "csr_wifi_hip_conversions.h" | 17 | #include "csr_wifi_hip_conversions.h" |
18 | 18 | #include <linux/sched/rt.h> | |
19 | 19 | ||
20 | 20 | ||
21 | 21 | ||
diff --git a/drivers/staging/fwserial/Kconfig b/drivers/staging/fwserial/Kconfig index 580406cb1808..b2f8331e4acf 100644 --- a/drivers/staging/fwserial/Kconfig +++ b/drivers/staging/fwserial/Kconfig | |||
@@ -3,7 +3,9 @@ config FIREWIRE_SERIAL | |||
3 | depends on FIREWIRE | 3 | depends on FIREWIRE |
4 | help | 4 | help |
5 | This enables TTY over IEEE 1394, providing high-speed serial | 5 | This enables TTY over IEEE 1394, providing high-speed serial |
6 | connectivity to cabled peers. | 6 | connectivity to cabled peers. This driver implements a |
7 | ad-hoc transport protocol and is currently limited to | ||
8 | Linux-to-Linux communication. | ||
7 | 9 | ||
8 | To compile this driver as a module, say M here: the module will | 10 | To compile this driver as a module, say M here: the module will |
9 | be called firewire-serial. | 11 | be called firewire-serial. |
diff --git a/drivers/staging/fwserial/TODO b/drivers/staging/fwserial/TODO index 726900548eae..8dae8fb25223 100644 --- a/drivers/staging/fwserial/TODO +++ b/drivers/staging/fwserial/TODO | |||
@@ -1,5 +1,5 @@ | |||
1 | TODOs | 1 | TODOs prior to this driver moving out of staging |
2 | ----- | 2 | ------------------------------------------------ |
3 | 1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR | 3 | 1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR |
4 | - I/O is handled asynchronously which presents some issues when error | 4 | - I/O is handled asynchronously which presents some issues when error |
5 | conditions occur. | 5 | conditions occur. |
@@ -11,17 +11,9 @@ TODOs | |||
11 | -- Issues with firewire stack -- | 11 | -- Issues with firewire stack -- |
12 | 1. This driver uses the same unregistered vendor id that the firewire core does | 12 | 1. This driver uses the same unregistered vendor id that the firewire core does |
13 | (0xd00d1e). Perhaps this could be exposed as a define in | 13 | (0xd00d1e). Perhaps this could be exposed as a define in |
14 | firewire-constants.h? | 14 | firewire.h? |
15 | 2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci | ||
16 | - otherwise how will this driver know the max size of address window to | ||
17 | open for one packet write? | ||
18 | 3. Maybe device_max_receive() and link_speed_to_max_payload() should be | 15 | 3. Maybe device_max_receive() and link_speed_to_max_payload() should be |
19 | taken up by the firewire core? | 16 | taken up by the firewire core? |
20 | 4. To avoid dropping rx data while still limiting the maximum buffering, | ||
21 | the size of the AR context must be known. How to expose this to drivers? | ||
22 | 5. Explore if bigger AR context will reduce RCODE_BUSY responses | ||
23 | (or auto-grow to certain max size -- but this would require major surgery | ||
24 | as the current AR is contiguously mapped) | ||
25 | 17 | ||
26 | -- Issues with TTY core -- | 18 | -- Issues with TTY core -- |
27 | 1. Hack for alternate device name scheme | 19 | 1. Hack for alternate device name scheme |
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c index 61ee29083b26..d03a7f57e8d4 100644 --- a/drivers/staging/fwserial/fwserial.c +++ b/drivers/staging/fwserial/fwserial.c | |||
@@ -179,7 +179,7 @@ static void dump_profile(struct seq_file *m, struct stats *stats) | |||
179 | /* Returns the max receive packet size for the given card */ | 179 | /* Returns the max receive packet size for the given card */ |
180 | static inline int device_max_receive(struct fw_device *fw_device) | 180 | static inline int device_max_receive(struct fw_device *fw_device) |
181 | { | 181 | { |
182 | return 1 << (clamp_t(int, fw_device->max_rec, 8U, 13U) + 1); | 182 | return 1 << (clamp_t(int, fw_device->max_rec, 8U, 11U) + 1); |
183 | } | 183 | } |
184 | 184 | ||
185 | static void fwtty_log_tx_error(struct fwtty_port *port, int rcode) | 185 | static void fwtty_log_tx_error(struct fwtty_port *port, int rcode) |
diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h index 8b572edf9563..caa1c1ea82d5 100644 --- a/drivers/staging/fwserial/fwserial.h +++ b/drivers/staging/fwserial/fwserial.h | |||
@@ -374,10 +374,10 @@ static inline void fwtty_bind_console(struct fwtty_port *port, | |||
374 | */ | 374 | */ |
375 | static inline int link_speed_to_max_payload(unsigned speed) | 375 | static inline int link_speed_to_max_payload(unsigned speed) |
376 | { | 376 | { |
377 | static const int max_async[] = { 307, 614, 1229, 2458, 4916, 9832, }; | 377 | static const int max_async[] = { 307, 614, 1229, 2458, }; |
378 | BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_3200); | 378 | BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_800); |
379 | 379 | ||
380 | speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_3200); | 380 | speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_800); |
381 | if (limit_bw) | 381 | if (limit_bw) |
382 | return max_async[speed]; | 382 | return max_async[speed]; |
383 | else | 383 | else |
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c index fb31b457a56a..c5ceb9d90ea8 100644 --- a/drivers/staging/iio/adc/mxs-lradc.c +++ b/drivers/staging/iio/adc/mxs-lradc.c | |||
@@ -239,7 +239,7 @@ static irqreturn_t mxs_lradc_trigger_handler(int irq, void *p) | |||
239 | struct mxs_lradc *lradc = iio_priv(iio); | 239 | struct mxs_lradc *lradc = iio_priv(iio); |
240 | const uint32_t chan_value = LRADC_CH_ACCUMULATE | | 240 | const uint32_t chan_value = LRADC_CH_ACCUMULATE | |
241 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); | 241 | ((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET); |
242 | int i, j = 0; | 242 | unsigned int i, j = 0; |
243 | 243 | ||
244 | for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { | 244 | for_each_set_bit(i, iio->active_scan_mask, iio->masklength) { |
245 | lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); | 245 | lradc->buffer[j] = readl(lradc->base + LRADC_CH(j)); |
diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig index ea295b25308c..87979a0d03a9 100644 --- a/drivers/staging/iio/gyro/Kconfig +++ b/drivers/staging/iio/gyro/Kconfig | |||
@@ -27,8 +27,8 @@ config ADIS16130 | |||
27 | config ADIS16260 | 27 | config ADIS16260 |
28 | tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" | 28 | tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver" |
29 | depends on SPI | 29 | depends on SPI |
30 | select IIO_TRIGGER if IIO_BUFFER | 30 | select IIO_ADIS_LIB |
31 | select IIO_SW_RING if IIO_BUFFER | 31 | select IIO_ADIS_LIB_BUFFER if IIO_BUFFER |
32 | help | 32 | help |
33 | Say yes here to build support for Analog Devices ADIS16260 ADIS16265 | 33 | Say yes here to build support for Analog Devices ADIS16260 ADIS16265 |
34 | ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors. | 34 | ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors. |
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c index 3525a68d6a75..41d7350d030f 100644 --- a/drivers/staging/iio/gyro/adis16080_core.c +++ b/drivers/staging/iio/gyro/adis16080_core.c | |||
@@ -69,7 +69,7 @@ static int adis16080_spi_read(struct iio_dev *indio_dev, | |||
69 | ret = spi_read(st->us, st->buf, 2); | 69 | ret = spi_read(st->us, st->buf, 2); |
70 | 70 | ||
71 | if (ret == 0) | 71 | if (ret == 0) |
72 | *val = ((st->buf[0] & 0xF) << 8) | st->buf[1]; | 72 | *val = sign_extend32(((st->buf[0] & 0xF) << 8) | st->buf[1], 11); |
73 | mutex_unlock(&st->buf_lock); | 73 | mutex_unlock(&st->buf_lock); |
74 | 74 | ||
75 | return ret; | 75 | return ret; |
diff --git a/drivers/staging/iio/trigger/Kconfig b/drivers/staging/iio/trigger/Kconfig index 7d3207559265..d44d3ad26fa5 100644 --- a/drivers/staging/iio/trigger/Kconfig +++ b/drivers/staging/iio/trigger/Kconfig | |||
@@ -21,7 +21,6 @@ config IIO_GPIO_TRIGGER | |||
21 | config IIO_SYSFS_TRIGGER | 21 | config IIO_SYSFS_TRIGGER |
22 | tristate "SYSFS trigger" | 22 | tristate "SYSFS trigger" |
23 | depends on SYSFS | 23 | depends on SYSFS |
24 | depends on HAVE_IRQ_WORK | ||
25 | select IRQ_WORK | 24 | select IRQ_WORK |
26 | help | 25 | help |
27 | Provides support for using SYSFS entry as IIO triggers. | 26 | Provides support for using SYSFS entry as IIO triggers. |
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c index ecf0f44bc70e..cec19f1cf56c 100644 --- a/drivers/staging/imx-drm/imx-drm-core.c +++ b/drivers/staging/imx-drm/imx-drm-core.c | |||
@@ -584,7 +584,6 @@ int imx_drm_add_encoder(struct drm_encoder *encoder, | |||
584 | 584 | ||
585 | ret = imx_drm_encoder_register(imx_drm_encoder); | 585 | ret = imx_drm_encoder_register(imx_drm_encoder); |
586 | if (ret) { | 586 | if (ret) { |
587 | kfree(imx_drm_encoder); | ||
588 | ret = -ENOMEM; | 587 | ret = -ENOMEM; |
589 | goto err_register; | 588 | goto err_register; |
590 | } | 589 | } |
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c index 677e665ca86d..f7059cddd7fd 100644 --- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c +++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c | |||
@@ -1104,7 +1104,9 @@ static int ipu_probe(struct platform_device *pdev) | |||
1104 | if (ret) | 1104 | if (ret) |
1105 | goto out_failed_irq; | 1105 | goto out_failed_irq; |
1106 | 1106 | ||
1107 | ipu_reset(ipu); | 1107 | ret = ipu_reset(ipu); |
1108 | if (ret) | ||
1109 | goto out_failed_reset; | ||
1108 | 1110 | ||
1109 | /* Set MCU_T to divide MCU access window into 2 */ | 1111 | /* Set MCU_T to divide MCU access window into 2 */ |
1110 | ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), | 1112 | ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18), |
@@ -1129,6 +1131,7 @@ failed_add_clients: | |||
1129 | ipu_submodules_exit(ipu); | 1131 | ipu_submodules_exit(ipu); |
1130 | failed_submodules_init: | 1132 | failed_submodules_init: |
1131 | ipu_irq_exit(ipu); | 1133 | ipu_irq_exit(ipu); |
1134 | out_failed_reset: | ||
1132 | out_failed_irq: | 1135 | out_failed_irq: |
1133 | clk_disable_unprepare(ipu->clk); | 1136 | clk_disable_unprepare(ipu->clk); |
1134 | failed_clk_get: | 1137 | failed_clk_get: |
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c index 1892006526b5..4b3a019409b5 100644 --- a/drivers/staging/imx-drm/ipuv3-crtc.c +++ b/drivers/staging/imx-drm/ipuv3-crtc.c | |||
@@ -452,7 +452,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, | |||
452 | int ret; | 452 | int ret; |
453 | 453 | ||
454 | ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); | 454 | ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]); |
455 | if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) { | 455 | if (IS_ERR(ipu_crtc->ipu_ch)) { |
456 | ret = PTR_ERR(ipu_crtc->ipu_ch); | 456 | ret = PTR_ERR(ipu_crtc->ipu_ch); |
457 | goto err_out; | 457 | goto err_out; |
458 | } | 458 | } |
@@ -472,7 +472,7 @@ static int ipu_get_resources(struct ipu_crtc *ipu_crtc, | |||
472 | if (pdata->dp >= 0) { | 472 | if (pdata->dp >= 0) { |
473 | ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); | 473 | ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp); |
474 | if (IS_ERR(ipu_crtc->dp)) { | 474 | if (IS_ERR(ipu_crtc->dp)) { |
475 | ret = PTR_ERR(ipu_crtc->ipu_ch); | 475 | ret = PTR_ERR(ipu_crtc->dp); |
476 | goto err_out; | 476 | goto err_out; |
477 | } | 477 | } |
478 | } | 478 | } |
@@ -548,6 +548,8 @@ static int ipu_drm_probe(struct platform_device *pdev) | |||
548 | ipu_crtc->dev = &pdev->dev; | 548 | ipu_crtc->dev = &pdev->dev; |
549 | 549 | ||
550 | ret = ipu_crtc_init(ipu_crtc, pdata); | 550 | ret = ipu_crtc_init(ipu_crtc, pdata); |
551 | if (ret) | ||
552 | return ret; | ||
551 | 553 | ||
552 | platform_set_drvdata(pdev, ipu_crtc); | 554 | platform_set_drvdata(pdev, ipu_crtc); |
553 | 555 | ||
diff --git a/drivers/staging/omapdrm/Kconfig b/drivers/staging/omapdrm/Kconfig index b724a4131435..09f65dc3d2c8 100644 --- a/drivers/staging/omapdrm/Kconfig +++ b/drivers/staging/omapdrm/Kconfig | |||
@@ -3,8 +3,8 @@ config DRM_OMAP | |||
3 | tristate "OMAP DRM" | 3 | tristate "OMAP DRM" |
4 | depends on DRM && !CONFIG_FB_OMAP2 | 4 | depends on DRM && !CONFIG_FB_OMAP2 |
5 | depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM | 5 | depends on ARCH_OMAP2PLUS || ARCH_MULTIPLATFORM |
6 | depends on OMAP2_DSS | ||
6 | select DRM_KMS_HELPER | 7 | select DRM_KMS_HELPER |
7 | select OMAP2_DSS | ||
8 | select FB_SYS_FILLRECT | 8 | select FB_SYS_FILLRECT |
9 | select FB_SYS_COPYAREA | 9 | select FB_SYS_COPYAREA |
10 | select FB_SYS_IMAGEBLIT | 10 | select FB_SYS_IMAGEBLIT |
diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile index 1ca0e0016de4..d85e058f2845 100644 --- a/drivers/staging/omapdrm/Makefile +++ b/drivers/staging/omapdrm/Makefile | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | ccflags-y := -Iinclude/drm -Werror | 6 | ccflags-y := -Iinclude/drm -Werror |
7 | omapdrm-y := omap_drv.o \ | 7 | omapdrm-y := omap_drv.o \ |
8 | omap_irq.o \ | ||
8 | omap_debugfs.o \ | 9 | omap_debugfs.o \ |
9 | omap_crtc.o \ | 10 | omap_crtc.o \ |
10 | omap_plane.o \ | 11 | omap_plane.o \ |
diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO index 938c7888ca31..abeeb00aaa12 100644 --- a/drivers/staging/omapdrm/TODO +++ b/drivers/staging/omapdrm/TODO | |||
@@ -17,9 +17,6 @@ TODO | |||
17 | . Revisit GEM sync object infrastructure.. TTM has some framework for this | 17 | . Revisit GEM sync object infrastructure.. TTM has some framework for this |
18 | already. Possibly this could be refactored out and made more common? | 18 | already. Possibly this could be refactored out and made more common? |
19 | There should be some way to do this with less wheel-reinvention. | 19 | There should be some way to do this with less wheel-reinvention. |
20 | . Review DSS vs KMS mismatches. The omap_dss_device is sort of part encoder, | ||
21 | part connector. Which results in a bit of duct tape to fwd calls from | ||
22 | encoder to connector. Possibly this could be done a bit better. | ||
23 | . Solve PM sequencing on resume. DMM/TILER must be reloaded before any | 20 | . Solve PM sequencing on resume. DMM/TILER must be reloaded before any |
24 | access is made from any component in the system. Which means on suspend | 21 | access is made from any component in the system. Which means on suspend |
25 | CRTC's should be disabled, and on resume the LUT should be reprogrammed | 22 | CRTC's should be disabled, and on resume the LUT should be reprogrammed |
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c index 91edb3f96972..4cc9ee733c5f 100644 --- a/drivers/staging/omapdrm/omap_connector.c +++ b/drivers/staging/omapdrm/omap_connector.c | |||
@@ -31,9 +31,10 @@ | |||
31 | struct omap_connector { | 31 | struct omap_connector { |
32 | struct drm_connector base; | 32 | struct drm_connector base; |
33 | struct omap_dss_device *dssdev; | 33 | struct omap_dss_device *dssdev; |
34 | struct drm_encoder *encoder; | ||
34 | }; | 35 | }; |
35 | 36 | ||
36 | static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, | 37 | void copy_timings_omap_to_drm(struct drm_display_mode *mode, |
37 | struct omap_video_timings *timings) | 38 | struct omap_video_timings *timings) |
38 | { | 39 | { |
39 | mode->clock = timings->pixel_clock; | 40 | mode->clock = timings->pixel_clock; |
@@ -64,7 +65,7 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode, | |||
64 | mode->flags |= DRM_MODE_FLAG_NVSYNC; | 65 | mode->flags |= DRM_MODE_FLAG_NVSYNC; |
65 | } | 66 | } |
66 | 67 | ||
67 | static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, | 68 | void copy_timings_drm_to_omap(struct omap_video_timings *timings, |
68 | struct drm_display_mode *mode) | 69 | struct drm_display_mode *mode) |
69 | { | 70 | { |
70 | timings->pixel_clock = mode->clock; | 71 | timings->pixel_clock = mode->clock; |
@@ -96,48 +97,7 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings, | |||
96 | timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; | 97 | timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES; |
97 | } | 98 | } |
98 | 99 | ||
99 | static void omap_connector_dpms(struct drm_connector *connector, int mode) | 100 | static enum drm_connector_status omap_connector_detect( |
100 | { | ||
101 | struct omap_connector *omap_connector = to_omap_connector(connector); | ||
102 | struct omap_dss_device *dssdev = omap_connector->dssdev; | ||
103 | int old_dpms; | ||
104 | |||
105 | DBG("%s: %d", dssdev->name, mode); | ||
106 | |||
107 | old_dpms = connector->dpms; | ||
108 | |||
109 | /* from off to on, do from crtc to connector */ | ||
110 | if (mode < old_dpms) | ||
111 | drm_helper_connector_dpms(connector, mode); | ||
112 | |||
113 | if (mode == DRM_MODE_DPMS_ON) { | ||
114 | /* store resume info for suspended displays */ | ||
115 | switch (dssdev->state) { | ||
116 | case OMAP_DSS_DISPLAY_SUSPENDED: | ||
117 | dssdev->activate_after_resume = true; | ||
118 | break; | ||
119 | case OMAP_DSS_DISPLAY_DISABLED: { | ||
120 | int ret = dssdev->driver->enable(dssdev); | ||
121 | if (ret) { | ||
122 | DBG("%s: failed to enable: %d", | ||
123 | dssdev->name, ret); | ||
124 | dssdev->driver->disable(dssdev); | ||
125 | } | ||
126 | break; | ||
127 | } | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | } else { | ||
132 | /* TODO */ | ||
133 | } | ||
134 | |||
135 | /* from on to off, do from connector to crtc */ | ||
136 | if (mode > old_dpms) | ||
137 | drm_helper_connector_dpms(connector, mode); | ||
138 | } | ||
139 | |||
140 | enum drm_connector_status omap_connector_detect( | ||
141 | struct drm_connector *connector, bool force) | 101 | struct drm_connector *connector, bool force) |
142 | { | 102 | { |
143 | struct omap_connector *omap_connector = to_omap_connector(connector); | 103 | struct omap_connector *omap_connector = to_omap_connector(connector); |
@@ -164,8 +124,6 @@ static void omap_connector_destroy(struct drm_connector *connector) | |||
164 | struct omap_connector *omap_connector = to_omap_connector(connector); | 124 | struct omap_connector *omap_connector = to_omap_connector(connector); |
165 | struct omap_dss_device *dssdev = omap_connector->dssdev; | 125 | struct omap_dss_device *dssdev = omap_connector->dssdev; |
166 | 126 | ||
167 | dssdev->driver->disable(dssdev); | ||
168 | |||
169 | DBG("%s", omap_connector->dssdev->name); | 127 | DBG("%s", omap_connector->dssdev->name); |
170 | drm_sysfs_connector_remove(connector); | 128 | drm_sysfs_connector_remove(connector); |
171 | drm_connector_cleanup(connector); | 129 | drm_connector_cleanup(connector); |
@@ -261,36 +219,12 @@ static int omap_connector_mode_valid(struct drm_connector *connector, | |||
261 | struct drm_encoder *omap_connector_attached_encoder( | 219 | struct drm_encoder *omap_connector_attached_encoder( |
262 | struct drm_connector *connector) | 220 | struct drm_connector *connector) |
263 | { | 221 | { |
264 | int i; | ||
265 | struct omap_connector *omap_connector = to_omap_connector(connector); | 222 | struct omap_connector *omap_connector = to_omap_connector(connector); |
266 | 223 | return omap_connector->encoder; | |
267 | for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) { | ||
268 | struct drm_mode_object *obj; | ||
269 | |||
270 | if (connector->encoder_ids[i] == 0) | ||
271 | break; | ||
272 | |||
273 | obj = drm_mode_object_find(connector->dev, | ||
274 | connector->encoder_ids[i], | ||
275 | DRM_MODE_OBJECT_ENCODER); | ||
276 | |||
277 | if (obj) { | ||
278 | struct drm_encoder *encoder = obj_to_encoder(obj); | ||
279 | struct omap_overlay_manager *mgr = | ||
280 | omap_encoder_get_manager(encoder); | ||
281 | DBG("%s: found %s", omap_connector->dssdev->name, | ||
282 | mgr->name); | ||
283 | return encoder; | ||
284 | } | ||
285 | } | ||
286 | |||
287 | DBG("%s: no encoder", omap_connector->dssdev->name); | ||
288 | |||
289 | return NULL; | ||
290 | } | 224 | } |
291 | 225 | ||
292 | static const struct drm_connector_funcs omap_connector_funcs = { | 226 | static const struct drm_connector_funcs omap_connector_funcs = { |
293 | .dpms = omap_connector_dpms, | 227 | .dpms = drm_helper_connector_dpms, |
294 | .detect = omap_connector_detect, | 228 | .detect = omap_connector_detect, |
295 | .fill_modes = drm_helper_probe_single_connector_modes, | 229 | .fill_modes = drm_helper_probe_single_connector_modes, |
296 | .destroy = omap_connector_destroy, | 230 | .destroy = omap_connector_destroy, |
@@ -302,34 +236,6 @@ static const struct drm_connector_helper_funcs omap_connector_helper_funcs = { | |||
302 | .best_encoder = omap_connector_attached_encoder, | 236 | .best_encoder = omap_connector_attached_encoder, |
303 | }; | 237 | }; |
304 | 238 | ||
305 | /* called from encoder when mode is set, to propagate settings to the dssdev */ | ||
306 | void omap_connector_mode_set(struct drm_connector *connector, | ||
307 | struct drm_display_mode *mode) | ||
308 | { | ||
309 | struct drm_device *dev = connector->dev; | ||
310 | struct omap_connector *omap_connector = to_omap_connector(connector); | ||
311 | struct omap_dss_device *dssdev = omap_connector->dssdev; | ||
312 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
313 | struct omap_video_timings timings = {0}; | ||
314 | |||
315 | copy_timings_drm_to_omap(&timings, mode); | ||
316 | |||
317 | DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", | ||
318 | omap_connector->dssdev->name, | ||
319 | mode->base.id, mode->name, mode->vrefresh, mode->clock, | ||
320 | mode->hdisplay, mode->hsync_start, | ||
321 | mode->hsync_end, mode->htotal, | ||
322 | mode->vdisplay, mode->vsync_start, | ||
323 | mode->vsync_end, mode->vtotal, mode->type, mode->flags); | ||
324 | |||
325 | if (dssdrv->check_timings(dssdev, &timings)) { | ||
326 | dev_err(dev->dev, "could not set timings\n"); | ||
327 | return; | ||
328 | } | ||
329 | |||
330 | dssdrv->set_timings(dssdev, &timings); | ||
331 | } | ||
332 | |||
333 | /* flush an area of the framebuffer (in case of manual update display that | 239 | /* flush an area of the framebuffer (in case of manual update display that |
334 | * is not automatically flushed) | 240 | * is not automatically flushed) |
335 | */ | 241 | */ |
@@ -344,7 +250,8 @@ void omap_connector_flush(struct drm_connector *connector, | |||
344 | 250 | ||
345 | /* initialize connector */ | 251 | /* initialize connector */ |
346 | struct drm_connector *omap_connector_init(struct drm_device *dev, | 252 | struct drm_connector *omap_connector_init(struct drm_device *dev, |
347 | int connector_type, struct omap_dss_device *dssdev) | 253 | int connector_type, struct omap_dss_device *dssdev, |
254 | struct drm_encoder *encoder) | ||
348 | { | 255 | { |
349 | struct drm_connector *connector = NULL; | 256 | struct drm_connector *connector = NULL; |
350 | struct omap_connector *omap_connector; | 257 | struct omap_connector *omap_connector; |
@@ -360,6 +267,8 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, | |||
360 | } | 267 | } |
361 | 268 | ||
362 | omap_connector->dssdev = dssdev; | 269 | omap_connector->dssdev = dssdev; |
270 | omap_connector->encoder = encoder; | ||
271 | |||
363 | connector = &omap_connector->base; | 272 | connector = &omap_connector->base; |
364 | 273 | ||
365 | drm_connector_init(dev, connector, &omap_connector_funcs, | 274 | drm_connector_init(dev, connector, &omap_connector_funcs, |
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c index d87bd84257bd..5c6ed6040eff 100644 --- a/drivers/staging/omapdrm/omap_crtc.c +++ b/drivers/staging/omapdrm/omap_crtc.c | |||
@@ -28,19 +28,131 @@ | |||
28 | struct omap_crtc { | 28 | struct omap_crtc { |
29 | struct drm_crtc base; | 29 | struct drm_crtc base; |
30 | struct drm_plane *plane; | 30 | struct drm_plane *plane; |
31 | |||
31 | const char *name; | 32 | const char *name; |
32 | int id; | 33 | int pipe; |
34 | enum omap_channel channel; | ||
35 | struct omap_overlay_manager_info info; | ||
36 | |||
37 | /* | ||
38 | * Temporary: eventually this will go away, but it is needed | ||
39 | * for now to keep the output's happy. (They only need | ||
40 | * mgr->id.) Eventually this will be replaced w/ something | ||
41 | * more common-panel-framework-y | ||
42 | */ | ||
43 | struct omap_overlay_manager mgr; | ||
44 | |||
45 | struct omap_video_timings timings; | ||
46 | bool enabled; | ||
47 | bool full_update; | ||
48 | |||
49 | struct omap_drm_apply apply; | ||
50 | |||
51 | struct omap_drm_irq apply_irq; | ||
52 | struct omap_drm_irq error_irq; | ||
53 | |||
54 | /* list of in-progress apply's: */ | ||
55 | struct list_head pending_applies; | ||
56 | |||
57 | /* list of queued apply's: */ | ||
58 | struct list_head queued_applies; | ||
59 | |||
60 | /* for handling queued and in-progress applies: */ | ||
61 | struct work_struct apply_work; | ||
33 | 62 | ||
34 | /* if there is a pending flip, these will be non-null: */ | 63 | /* if there is a pending flip, these will be non-null: */ |
35 | struct drm_pending_vblank_event *event; | 64 | struct drm_pending_vblank_event *event; |
36 | struct drm_framebuffer *old_fb; | 65 | struct drm_framebuffer *old_fb; |
66 | |||
67 | /* for handling page flips without caring about what | ||
68 | * the callback is called from. Possibly we should just | ||
69 | * make omap_gem always call the cb from the worker so | ||
70 | * we don't have to care about this.. | ||
71 | * | ||
72 | * XXX maybe fold into apply_work?? | ||
73 | */ | ||
74 | struct work_struct page_flip_work; | ||
75 | }; | ||
76 | |||
77 | /* | ||
78 | * Manager-ops, callbacks from output when they need to configure | ||
79 | * the upstream part of the video pipe. | ||
80 | * | ||
81 | * Most of these we can ignore until we add support for command-mode | ||
82 | * panels.. for video-mode the crtc-helpers already do an adequate | ||
83 | * job of sequencing the setup of the video pipe in the proper order | ||
84 | */ | ||
85 | |||
86 | /* we can probably ignore these until we support command-mode panels: */ | ||
87 | static void omap_crtc_start_update(struct omap_overlay_manager *mgr) | ||
88 | { | ||
89 | } | ||
90 | |||
91 | static int omap_crtc_enable(struct omap_overlay_manager *mgr) | ||
92 | { | ||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static void omap_crtc_disable(struct omap_overlay_manager *mgr) | ||
97 | { | ||
98 | } | ||
99 | |||
100 | static void omap_crtc_set_timings(struct omap_overlay_manager *mgr, | ||
101 | const struct omap_video_timings *timings) | ||
102 | { | ||
103 | struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); | ||
104 | DBG("%s", omap_crtc->name); | ||
105 | omap_crtc->timings = *timings; | ||
106 | omap_crtc->full_update = true; | ||
107 | } | ||
108 | |||
109 | static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr, | ||
110 | const struct dss_lcd_mgr_config *config) | ||
111 | { | ||
112 | struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr); | ||
113 | DBG("%s", omap_crtc->name); | ||
114 | dispc_mgr_set_lcd_config(omap_crtc->channel, config); | ||
115 | } | ||
116 | |||
117 | static int omap_crtc_register_framedone_handler( | ||
118 | struct omap_overlay_manager *mgr, | ||
119 | void (*handler)(void *), void *data) | ||
120 | { | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static void omap_crtc_unregister_framedone_handler( | ||
125 | struct omap_overlay_manager *mgr, | ||
126 | void (*handler)(void *), void *data) | ||
127 | { | ||
128 | } | ||
129 | |||
130 | static const struct dss_mgr_ops mgr_ops = { | ||
131 | .start_update = omap_crtc_start_update, | ||
132 | .enable = omap_crtc_enable, | ||
133 | .disable = omap_crtc_disable, | ||
134 | .set_timings = omap_crtc_set_timings, | ||
135 | .set_lcd_config = omap_crtc_set_lcd_config, | ||
136 | .register_framedone_handler = omap_crtc_register_framedone_handler, | ||
137 | .unregister_framedone_handler = omap_crtc_unregister_framedone_handler, | ||
37 | }; | 138 | }; |
38 | 139 | ||
140 | /* | ||
141 | * CRTC funcs: | ||
142 | */ | ||
143 | |||
39 | static void omap_crtc_destroy(struct drm_crtc *crtc) | 144 | static void omap_crtc_destroy(struct drm_crtc *crtc) |
40 | { | 145 | { |
41 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 146 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
147 | |||
148 | DBG("%s", omap_crtc->name); | ||
149 | |||
150 | WARN_ON(omap_crtc->apply_irq.registered); | ||
151 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | ||
152 | |||
42 | omap_crtc->plane->funcs->destroy(omap_crtc->plane); | 153 | omap_crtc->plane->funcs->destroy(omap_crtc->plane); |
43 | drm_crtc_cleanup(crtc); | 154 | drm_crtc_cleanup(crtc); |
155 | |||
44 | kfree(omap_crtc); | 156 | kfree(omap_crtc); |
45 | } | 157 | } |
46 | 158 | ||
@@ -48,14 +160,25 @@ static void omap_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
48 | { | 160 | { |
49 | struct omap_drm_private *priv = crtc->dev->dev_private; | 161 | struct omap_drm_private *priv = crtc->dev->dev_private; |
50 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 162 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
163 | bool enabled = (mode == DRM_MODE_DPMS_ON); | ||
51 | int i; | 164 | int i; |
52 | 165 | ||
53 | WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); | 166 | DBG("%s: %d", omap_crtc->name, mode); |
167 | |||
168 | if (enabled != omap_crtc->enabled) { | ||
169 | omap_crtc->enabled = enabled; | ||
170 | omap_crtc->full_update = true; | ||
171 | omap_crtc_apply(crtc, &omap_crtc->apply); | ||
54 | 172 | ||
55 | for (i = 0; i < priv->num_planes; i++) { | 173 | /* also enable our private plane: */ |
56 | struct drm_plane *plane = priv->planes[i]; | 174 | WARN_ON(omap_plane_dpms(omap_crtc->plane, mode)); |
57 | if (plane->crtc == crtc) | 175 | |
58 | WARN_ON(omap_plane_dpms(plane, mode)); | 176 | /* and any attached overlay planes: */ |
177 | for (i = 0; i < priv->num_planes; i++) { | ||
178 | struct drm_plane *plane = priv->planes[i]; | ||
179 | if (plane->crtc == crtc) | ||
180 | WARN_ON(omap_plane_dpms(plane, mode)); | ||
181 | } | ||
59 | } | 182 | } |
60 | } | 183 | } |
61 | 184 | ||
@@ -73,12 +196,26 @@ static int omap_crtc_mode_set(struct drm_crtc *crtc, | |||
73 | struct drm_framebuffer *old_fb) | 196 | struct drm_framebuffer *old_fb) |
74 | { | 197 | { |
75 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 198 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
76 | struct drm_plane *plane = omap_crtc->plane; | ||
77 | 199 | ||
78 | return omap_plane_mode_set(plane, crtc, crtc->fb, | 200 | mode = adjusted_mode; |
201 | |||
202 | DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", | ||
203 | omap_crtc->name, mode->base.id, mode->name, | ||
204 | mode->vrefresh, mode->clock, | ||
205 | mode->hdisplay, mode->hsync_start, | ||
206 | mode->hsync_end, mode->htotal, | ||
207 | mode->vdisplay, mode->vsync_start, | ||
208 | mode->vsync_end, mode->vtotal, | ||
209 | mode->type, mode->flags); | ||
210 | |||
211 | copy_timings_drm_to_omap(&omap_crtc->timings, mode); | ||
212 | omap_crtc->full_update = true; | ||
213 | |||
214 | return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, | ||
79 | 0, 0, mode->hdisplay, mode->vdisplay, | 215 | 0, 0, mode->hdisplay, mode->vdisplay, |
80 | x << 16, y << 16, | 216 | x << 16, y << 16, |
81 | mode->hdisplay << 16, mode->vdisplay << 16); | 217 | mode->hdisplay << 16, mode->vdisplay << 16, |
218 | NULL, NULL); | ||
82 | } | 219 | } |
83 | 220 | ||
84 | static void omap_crtc_prepare(struct drm_crtc *crtc) | 221 | static void omap_crtc_prepare(struct drm_crtc *crtc) |
@@ -102,10 +239,11 @@ static int omap_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, | |||
102 | struct drm_plane *plane = omap_crtc->plane; | 239 | struct drm_plane *plane = omap_crtc->plane; |
103 | struct drm_display_mode *mode = &crtc->mode; | 240 | struct drm_display_mode *mode = &crtc->mode; |
104 | 241 | ||
105 | return plane->funcs->update_plane(plane, crtc, crtc->fb, | 242 | return omap_plane_mode_set(plane, crtc, crtc->fb, |
106 | 0, 0, mode->hdisplay, mode->vdisplay, | 243 | 0, 0, mode->hdisplay, mode->vdisplay, |
107 | x << 16, y << 16, | 244 | x << 16, y << 16, |
108 | mode->hdisplay << 16, mode->vdisplay << 16); | 245 | mode->hdisplay << 16, mode->vdisplay << 16, |
246 | NULL, NULL); | ||
109 | } | 247 | } |
110 | 248 | ||
111 | static void omap_crtc_load_lut(struct drm_crtc *crtc) | 249 | static void omap_crtc_load_lut(struct drm_crtc *crtc) |
@@ -114,63 +252,54 @@ static void omap_crtc_load_lut(struct drm_crtc *crtc) | |||
114 | 252 | ||
115 | static void vblank_cb(void *arg) | 253 | static void vblank_cb(void *arg) |
116 | { | 254 | { |
117 | static uint32_t sequence; | ||
118 | struct drm_crtc *crtc = arg; | 255 | struct drm_crtc *crtc = arg; |
119 | struct drm_device *dev = crtc->dev; | 256 | struct drm_device *dev = crtc->dev; |
120 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 257 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
121 | struct drm_pending_vblank_event *event = omap_crtc->event; | ||
122 | unsigned long flags; | 258 | unsigned long flags; |
123 | struct timeval now; | ||
124 | 259 | ||
125 | WARN_ON(!event); | 260 | spin_lock_irqsave(&dev->event_lock, flags); |
261 | |||
262 | /* wakeup userspace */ | ||
263 | if (omap_crtc->event) | ||
264 | drm_send_vblank_event(dev, omap_crtc->pipe, omap_crtc->event); | ||
126 | 265 | ||
127 | omap_crtc->event = NULL; | 266 | omap_crtc->event = NULL; |
267 | omap_crtc->old_fb = NULL; | ||
128 | 268 | ||
129 | /* wakeup userspace */ | 269 | spin_unlock_irqrestore(&dev->event_lock, flags); |
130 | if (event) { | ||
131 | do_gettimeofday(&now); | ||
132 | |||
133 | spin_lock_irqsave(&dev->event_lock, flags); | ||
134 | /* TODO: we can't yet use the vblank time accounting, | ||
135 | * because omapdss lower layer is the one that knows | ||
136 | * the irq # and registers the handler, which more or | ||
137 | * less defeats how drm_irq works.. for now just fake | ||
138 | * the sequence number and use gettimeofday.. | ||
139 | * | ||
140 | event->event.sequence = drm_vblank_count_and_time( | ||
141 | dev, omap_crtc->id, &now); | ||
142 | */ | ||
143 | event->event.sequence = sequence++; | ||
144 | event->event.tv_sec = now.tv_sec; | ||
145 | event->event.tv_usec = now.tv_usec; | ||
146 | list_add_tail(&event->base.link, | ||
147 | &event->base.file_priv->event_list); | ||
148 | wake_up_interruptible(&event->base.file_priv->event_wait); | ||
149 | spin_unlock_irqrestore(&dev->event_lock, flags); | ||
150 | } | ||
151 | } | 270 | } |
152 | 271 | ||
153 | static void page_flip_cb(void *arg) | 272 | static void page_flip_worker(struct work_struct *work) |
154 | { | 273 | { |
155 | struct drm_crtc *crtc = arg; | 274 | struct omap_crtc *omap_crtc = |
156 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 275 | container_of(work, struct omap_crtc, page_flip_work); |
157 | struct drm_framebuffer *old_fb = omap_crtc->old_fb; | 276 | struct drm_crtc *crtc = &omap_crtc->base; |
277 | struct drm_device *dev = crtc->dev; | ||
278 | struct drm_display_mode *mode = &crtc->mode; | ||
158 | struct drm_gem_object *bo; | 279 | struct drm_gem_object *bo; |
159 | 280 | ||
160 | omap_crtc->old_fb = NULL; | 281 | mutex_lock(&dev->mode_config.mutex); |
161 | 282 | omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb, | |
162 | omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb); | 283 | 0, 0, mode->hdisplay, mode->vdisplay, |
163 | 284 | crtc->x << 16, crtc->y << 16, | |
164 | /* really we'd like to setup the callback atomically w/ setting the | 285 | mode->hdisplay << 16, mode->vdisplay << 16, |
165 | * new scanout buffer to avoid getting stuck waiting an extra vblank | 286 | vblank_cb, crtc); |
166 | * cycle.. for now go for correctness and later figure out speed.. | 287 | mutex_unlock(&dev->mode_config.mutex); |
167 | */ | ||
168 | omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc); | ||
169 | 288 | ||
170 | bo = omap_framebuffer_bo(crtc->fb, 0); | 289 | bo = omap_framebuffer_bo(crtc->fb, 0); |
171 | drm_gem_object_unreference_unlocked(bo); | 290 | drm_gem_object_unreference_unlocked(bo); |
172 | } | 291 | } |
173 | 292 | ||
293 | static void page_flip_cb(void *arg) | ||
294 | { | ||
295 | struct drm_crtc *crtc = arg; | ||
296 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
297 | struct omap_drm_private *priv = crtc->dev->dev_private; | ||
298 | |||
299 | /* avoid assumptions about what ctxt we are called from: */ | ||
300 | queue_work(priv->wq, &omap_crtc->page_flip_work); | ||
301 | } | ||
302 | |||
174 | static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, | 303 | static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, |
175 | struct drm_framebuffer *fb, | 304 | struct drm_framebuffer *fb, |
176 | struct drm_pending_vblank_event *event) | 305 | struct drm_pending_vblank_event *event) |
@@ -179,14 +308,14 @@ static int omap_crtc_page_flip_locked(struct drm_crtc *crtc, | |||
179 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | 308 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); |
180 | struct drm_gem_object *bo; | 309 | struct drm_gem_object *bo; |
181 | 310 | ||
182 | DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id); | 311 | DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1, |
312 | fb->base.id, event); | ||
183 | 313 | ||
184 | if (omap_crtc->event) { | 314 | if (omap_crtc->old_fb) { |
185 | dev_err(dev->dev, "already a pending flip\n"); | 315 | dev_err(dev->dev, "already a pending flip\n"); |
186 | return -EINVAL; | 316 | return -EINVAL; |
187 | } | 317 | } |
188 | 318 | ||
189 | omap_crtc->old_fb = crtc->fb; | ||
190 | omap_crtc->event = event; | 319 | omap_crtc->event = event; |
191 | crtc->fb = fb; | 320 | crtc->fb = fb; |
192 | 321 | ||
@@ -234,14 +363,244 @@ static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { | |||
234 | .load_lut = omap_crtc_load_lut, | 363 | .load_lut = omap_crtc_load_lut, |
235 | }; | 364 | }; |
236 | 365 | ||
366 | const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc) | ||
367 | { | ||
368 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
369 | return &omap_crtc->timings; | ||
370 | } | ||
371 | |||
372 | enum omap_channel omap_crtc_channel(struct drm_crtc *crtc) | ||
373 | { | ||
374 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
375 | return omap_crtc->channel; | ||
376 | } | ||
377 | |||
378 | static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
379 | { | ||
380 | struct omap_crtc *omap_crtc = | ||
381 | container_of(irq, struct omap_crtc, error_irq); | ||
382 | struct drm_crtc *crtc = &omap_crtc->base; | ||
383 | DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus); | ||
384 | /* avoid getting in a flood, unregister the irq until next vblank */ | ||
385 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | ||
386 | } | ||
387 | |||
388 | static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
389 | { | ||
390 | struct omap_crtc *omap_crtc = | ||
391 | container_of(irq, struct omap_crtc, apply_irq); | ||
392 | struct drm_crtc *crtc = &omap_crtc->base; | ||
393 | |||
394 | if (!omap_crtc->error_irq.registered) | ||
395 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); | ||
396 | |||
397 | if (!dispc_mgr_go_busy(omap_crtc->channel)) { | ||
398 | struct omap_drm_private *priv = | ||
399 | crtc->dev->dev_private; | ||
400 | DBG("%s: apply done", omap_crtc->name); | ||
401 | omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq); | ||
402 | queue_work(priv->wq, &omap_crtc->apply_work); | ||
403 | } | ||
404 | } | ||
405 | |||
406 | static void apply_worker(struct work_struct *work) | ||
407 | { | ||
408 | struct omap_crtc *omap_crtc = | ||
409 | container_of(work, struct omap_crtc, apply_work); | ||
410 | struct drm_crtc *crtc = &omap_crtc->base; | ||
411 | struct drm_device *dev = crtc->dev; | ||
412 | struct omap_drm_apply *apply, *n; | ||
413 | bool need_apply; | ||
414 | |||
415 | /* | ||
416 | * Synchronize everything on mode_config.mutex, to keep | ||
417 | * the callbacks and list modification all serialized | ||
418 | * with respect to modesetting ioctls from userspace. | ||
419 | */ | ||
420 | mutex_lock(&dev->mode_config.mutex); | ||
421 | dispc_runtime_get(); | ||
422 | |||
423 | /* | ||
424 | * If we are still pending a previous update, wait.. when the | ||
425 | * pending update completes, we get kicked again. | ||
426 | */ | ||
427 | if (omap_crtc->apply_irq.registered) | ||
428 | goto out; | ||
429 | |||
430 | /* finish up previous apply's: */ | ||
431 | list_for_each_entry_safe(apply, n, | ||
432 | &omap_crtc->pending_applies, pending_node) { | ||
433 | apply->post_apply(apply); | ||
434 | list_del(&apply->pending_node); | ||
435 | } | ||
436 | |||
437 | need_apply = !list_empty(&omap_crtc->queued_applies); | ||
438 | |||
439 | /* then handle the next round of of queued apply's: */ | ||
440 | list_for_each_entry_safe(apply, n, | ||
441 | &omap_crtc->queued_applies, queued_node) { | ||
442 | apply->pre_apply(apply); | ||
443 | list_del(&apply->queued_node); | ||
444 | apply->queued = false; | ||
445 | list_add_tail(&apply->pending_node, | ||
446 | &omap_crtc->pending_applies); | ||
447 | } | ||
448 | |||
449 | if (need_apply) { | ||
450 | enum omap_channel channel = omap_crtc->channel; | ||
451 | |||
452 | DBG("%s: GO", omap_crtc->name); | ||
453 | |||
454 | if (dispc_mgr_is_enabled(channel)) { | ||
455 | omap_irq_register(dev, &omap_crtc->apply_irq); | ||
456 | dispc_mgr_go(channel); | ||
457 | } else { | ||
458 | struct omap_drm_private *priv = dev->dev_private; | ||
459 | queue_work(priv->wq, &omap_crtc->apply_work); | ||
460 | } | ||
461 | } | ||
462 | |||
463 | out: | ||
464 | dispc_runtime_put(); | ||
465 | mutex_unlock(&dev->mode_config.mutex); | ||
466 | } | ||
467 | |||
468 | int omap_crtc_apply(struct drm_crtc *crtc, | ||
469 | struct omap_drm_apply *apply) | ||
470 | { | ||
471 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
472 | struct drm_device *dev = crtc->dev; | ||
473 | |||
474 | WARN_ON(!mutex_is_locked(&dev->mode_config.mutex)); | ||
475 | |||
476 | /* no need to queue it again if it is already queued: */ | ||
477 | if (apply->queued) | ||
478 | return 0; | ||
479 | |||
480 | apply->queued = true; | ||
481 | list_add_tail(&apply->queued_node, &omap_crtc->queued_applies); | ||
482 | |||
483 | /* | ||
484 | * If there are no currently pending updates, then go ahead and | ||
485 | * kick the worker immediately, otherwise it will run again when | ||
486 | * the current update finishes. | ||
487 | */ | ||
488 | if (list_empty(&omap_crtc->pending_applies)) { | ||
489 | struct omap_drm_private *priv = crtc->dev->dev_private; | ||
490 | queue_work(priv->wq, &omap_crtc->apply_work); | ||
491 | } | ||
492 | |||
493 | return 0; | ||
494 | } | ||
495 | |||
496 | /* called only from apply */ | ||
497 | static void set_enabled(struct drm_crtc *crtc, bool enable) | ||
498 | { | ||
499 | struct drm_device *dev = crtc->dev; | ||
500 | struct omap_crtc *omap_crtc = to_omap_crtc(crtc); | ||
501 | enum omap_channel channel = omap_crtc->channel; | ||
502 | struct omap_irq_wait *wait = NULL; | ||
503 | |||
504 | if (dispc_mgr_is_enabled(channel) == enable) | ||
505 | return; | ||
506 | |||
507 | /* ignore sync-lost irqs during enable/disable */ | ||
508 | omap_irq_unregister(crtc->dev, &omap_crtc->error_irq); | ||
509 | |||
510 | if (dispc_mgr_get_framedone_irq(channel)) { | ||
511 | if (!enable) { | ||
512 | wait = omap_irq_wait_init(dev, | ||
513 | dispc_mgr_get_framedone_irq(channel), 1); | ||
514 | } | ||
515 | } else { | ||
516 | /* | ||
517 | * When we disable digit output, we need to wait until fields | ||
518 | * are done. Otherwise the DSS is still working, and turning | ||
519 | * off the clocks prevents DSS from going to OFF mode. And when | ||
520 | * enabling, we need to wait for the extra sync losts | ||
521 | */ | ||
522 | wait = omap_irq_wait_init(dev, | ||
523 | dispc_mgr_get_vsync_irq(channel), 2); | ||
524 | } | ||
525 | |||
526 | dispc_mgr_enable(channel, enable); | ||
527 | |||
528 | if (wait) { | ||
529 | int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); | ||
530 | if (ret) { | ||
531 | dev_err(dev->dev, "%s: timeout waiting for %s\n", | ||
532 | omap_crtc->name, enable ? "enable" : "disable"); | ||
533 | } | ||
534 | } | ||
535 | |||
536 | omap_irq_register(crtc->dev, &omap_crtc->error_irq); | ||
537 | } | ||
538 | |||
539 | static void omap_crtc_pre_apply(struct omap_drm_apply *apply) | ||
540 | { | ||
541 | struct omap_crtc *omap_crtc = | ||
542 | container_of(apply, struct omap_crtc, apply); | ||
543 | struct drm_crtc *crtc = &omap_crtc->base; | ||
544 | struct drm_encoder *encoder = NULL; | ||
545 | |||
546 | DBG("%s: enabled=%d, full=%d", omap_crtc->name, | ||
547 | omap_crtc->enabled, omap_crtc->full_update); | ||
548 | |||
549 | if (omap_crtc->full_update) { | ||
550 | struct omap_drm_private *priv = crtc->dev->dev_private; | ||
551 | int i; | ||
552 | for (i = 0; i < priv->num_encoders; i++) { | ||
553 | if (priv->encoders[i]->crtc == crtc) { | ||
554 | encoder = priv->encoders[i]; | ||
555 | break; | ||
556 | } | ||
557 | } | ||
558 | } | ||
559 | |||
560 | if (!omap_crtc->enabled) { | ||
561 | set_enabled(&omap_crtc->base, false); | ||
562 | if (encoder) | ||
563 | omap_encoder_set_enabled(encoder, false); | ||
564 | } else { | ||
565 | if (encoder) { | ||
566 | omap_encoder_set_enabled(encoder, false); | ||
567 | omap_encoder_update(encoder, &omap_crtc->mgr, | ||
568 | &omap_crtc->timings); | ||
569 | omap_encoder_set_enabled(encoder, true); | ||
570 | omap_crtc->full_update = false; | ||
571 | } | ||
572 | |||
573 | dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info); | ||
574 | dispc_mgr_set_timings(omap_crtc->channel, | ||
575 | &omap_crtc->timings); | ||
576 | set_enabled(&omap_crtc->base, true); | ||
577 | } | ||
578 | |||
579 | omap_crtc->full_update = false; | ||
580 | } | ||
581 | |||
582 | static void omap_crtc_post_apply(struct omap_drm_apply *apply) | ||
583 | { | ||
584 | /* nothing needed for post-apply */ | ||
585 | } | ||
586 | |||
587 | static const char *channel_names[] = { | ||
588 | [OMAP_DSS_CHANNEL_LCD] = "lcd", | ||
589 | [OMAP_DSS_CHANNEL_DIGIT] = "tv", | ||
590 | [OMAP_DSS_CHANNEL_LCD2] = "lcd2", | ||
591 | }; | ||
592 | |||
237 | /* initialize crtc */ | 593 | /* initialize crtc */ |
238 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 594 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
239 | struct omap_overlay *ovl, int id) | 595 | struct drm_plane *plane, enum omap_channel channel, int id) |
240 | { | 596 | { |
241 | struct drm_crtc *crtc = NULL; | 597 | struct drm_crtc *crtc = NULL; |
242 | struct omap_crtc *omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); | 598 | struct omap_crtc *omap_crtc; |
599 | struct omap_overlay_manager_info *info; | ||
600 | |||
601 | DBG("%s", channel_names[channel]); | ||
243 | 602 | ||
244 | DBG("%s", ovl->name); | 603 | omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); |
245 | 604 | ||
246 | if (!omap_crtc) { | 605 | if (!omap_crtc) { |
247 | dev_err(dev->dev, "could not allocate CRTC\n"); | 606 | dev_err(dev->dev, "could not allocate CRTC\n"); |
@@ -250,10 +609,40 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, | |||
250 | 609 | ||
251 | crtc = &omap_crtc->base; | 610 | crtc = &omap_crtc->base; |
252 | 611 | ||
253 | omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true); | 612 | INIT_WORK(&omap_crtc->page_flip_work, page_flip_worker); |
613 | INIT_WORK(&omap_crtc->apply_work, apply_worker); | ||
614 | |||
615 | INIT_LIST_HEAD(&omap_crtc->pending_applies); | ||
616 | INIT_LIST_HEAD(&omap_crtc->queued_applies); | ||
617 | |||
618 | omap_crtc->apply.pre_apply = omap_crtc_pre_apply; | ||
619 | omap_crtc->apply.post_apply = omap_crtc_post_apply; | ||
620 | |||
621 | omap_crtc->apply_irq.irqmask = pipe2vbl(id); | ||
622 | omap_crtc->apply_irq.irq = omap_crtc_apply_irq; | ||
623 | |||
624 | omap_crtc->error_irq.irqmask = | ||
625 | dispc_mgr_get_sync_lost_irq(channel); | ||
626 | omap_crtc->error_irq.irq = omap_crtc_error_irq; | ||
627 | omap_irq_register(dev, &omap_crtc->error_irq); | ||
628 | |||
629 | omap_crtc->channel = channel; | ||
630 | omap_crtc->plane = plane; | ||
254 | omap_crtc->plane->crtc = crtc; | 631 | omap_crtc->plane->crtc = crtc; |
255 | omap_crtc->name = ovl->name; | 632 | omap_crtc->name = channel_names[channel]; |
256 | omap_crtc->id = id; | 633 | omap_crtc->pipe = id; |
634 | |||
635 | /* temporary: */ | ||
636 | omap_crtc->mgr.id = channel; | ||
637 | |||
638 | dss_install_mgr_ops(&mgr_ops); | ||
639 | |||
640 | /* TODO: fix hard-coded setup.. add properties! */ | ||
641 | info = &omap_crtc->info; | ||
642 | info->default_color = 0x00000000; | ||
643 | info->trans_key = 0x00000000; | ||
644 | info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; | ||
645 | info->trans_enabled = false; | ||
257 | 646 | ||
258 | drm_crtc_init(dev, crtc, &omap_crtc_funcs); | 647 | drm_crtc_init(dev, crtc, &omap_crtc_funcs); |
259 | drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); | 648 | drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); |
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c index 84943e5ba1d6..ae5ecc2efbc7 100644 --- a/drivers/staging/omapdrm/omap_drv.c +++ b/drivers/staging/omapdrm/omap_drv.c | |||
@@ -74,320 +74,99 @@ static int get_connector_type(struct omap_dss_device *dssdev) | |||
74 | } | 74 | } |
75 | } | 75 | } |
76 | 76 | ||
77 | #if 0 /* enable when dss2 supports hotplug */ | 77 | static int omap_modeset_init(struct drm_device *dev) |
78 | static int omap_drm_notifier(struct notifier_block *nb, | ||
79 | unsigned long evt, void *arg) | ||
80 | { | ||
81 | switch (evt) { | ||
82 | case OMAP_DSS_SIZE_CHANGE: | ||
83 | case OMAP_DSS_HOTPLUG_CONNECT: | ||
84 | case OMAP_DSS_HOTPLUG_DISCONNECT: { | ||
85 | struct drm_device *dev = drm_device; | ||
86 | DBG("hotplug event: evt=%d, dev=%p", evt, dev); | ||
87 | if (dev) | ||
88 | drm_sysfs_hotplug_event(dev); | ||
89 | |||
90 | return NOTIFY_OK; | ||
91 | } | ||
92 | default: /* don't care about other events for now */ | ||
93 | return NOTIFY_DONE; | ||
94 | } | ||
95 | } | ||
96 | #endif | ||
97 | |||
98 | static void dump_video_chains(void) | ||
99 | { | ||
100 | int i; | ||
101 | |||
102 | DBG("dumping video chains: "); | ||
103 | for (i = 0; i < omap_dss_get_num_overlays(); i++) { | ||
104 | struct omap_overlay *ovl = omap_dss_get_overlay(i); | ||
105 | struct omap_overlay_manager *mgr = ovl->manager; | ||
106 | struct omap_dss_device *dssdev = mgr ? | ||
107 | mgr->get_device(mgr) : NULL; | ||
108 | if (dssdev) { | ||
109 | DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name, | ||
110 | dssdev->name); | ||
111 | } else if (mgr) { | ||
112 | DBG("%d: %s -> %s", i, ovl->name, mgr->name); | ||
113 | } else { | ||
114 | DBG("%d: %s", i, ovl->name); | ||
115 | } | ||
116 | } | ||
117 | } | ||
118 | |||
119 | /* create encoders for each manager */ | ||
120 | static int create_encoder(struct drm_device *dev, | ||
121 | struct omap_overlay_manager *mgr) | ||
122 | { | ||
123 | struct omap_drm_private *priv = dev->dev_private; | ||
124 | struct drm_encoder *encoder = omap_encoder_init(dev, mgr); | ||
125 | |||
126 | if (!encoder) { | ||
127 | dev_err(dev->dev, "could not create encoder: %s\n", | ||
128 | mgr->name); | ||
129 | return -ENOMEM; | ||
130 | } | ||
131 | |||
132 | BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); | ||
133 | |||
134 | priv->encoders[priv->num_encoders++] = encoder; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | /* create connectors for each display device */ | ||
140 | static int create_connector(struct drm_device *dev, | ||
141 | struct omap_dss_device *dssdev) | ||
142 | { | 78 | { |
143 | struct omap_drm_private *priv = dev->dev_private; | 79 | struct omap_drm_private *priv = dev->dev_private; |
144 | static struct notifier_block *notifier; | 80 | struct omap_dss_device *dssdev = NULL; |
145 | struct drm_connector *connector; | 81 | int num_ovls = dss_feat_get_num_ovls(); |
146 | int j; | 82 | int id; |
147 | |||
148 | if (!dssdev->driver) { | ||
149 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", | ||
150 | dssdev->name); | ||
151 | return 0; | ||
152 | } | ||
153 | 83 | ||
154 | if (!(dssdev->driver->get_timings || | 84 | drm_mode_config_init(dev); |
155 | dssdev->driver->read_edid)) { | ||
156 | dev_warn(dev->dev, "%s driver does not support " | ||
157 | "get_timings or read_edid.. skipping it!\n", | ||
158 | dssdev->name); | ||
159 | return 0; | ||
160 | } | ||
161 | 85 | ||
162 | connector = omap_connector_init(dev, | 86 | omap_drm_irq_install(dev); |
163 | get_connector_type(dssdev), dssdev); | ||
164 | 87 | ||
165 | if (!connector) { | 88 | /* |
166 | dev_err(dev->dev, "could not create connector: %s\n", | 89 | * Create private planes and CRTCs for the last NUM_CRTCs overlay |
167 | dssdev->name); | 90 | * plus manager: |
168 | return -ENOMEM; | 91 | */ |
169 | } | 92 | for (id = 0; id < min(num_crtc, num_ovls); id++) { |
170 | 93 | struct drm_plane *plane; | |
171 | BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); | 94 | struct drm_crtc *crtc; |
172 | 95 | ||
173 | priv->connectors[priv->num_connectors++] = connector; | 96 | plane = omap_plane_init(dev, id, true); |
97 | crtc = omap_crtc_init(dev, plane, pipe2chan(id), id); | ||
174 | 98 | ||
175 | #if 0 /* enable when dss2 supports hotplug */ | 99 | BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); |
176 | notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL); | 100 | priv->crtcs[id] = crtc; |
177 | notifier->notifier_call = omap_drm_notifier; | 101 | priv->num_crtcs++; |
178 | omap_dss_add_notify(dssdev, notifier); | ||
179 | #else | ||
180 | notifier = NULL; | ||
181 | #endif | ||
182 | 102 | ||
183 | for (j = 0; j < priv->num_encoders; j++) { | 103 | priv->planes[id] = plane; |
184 | struct omap_overlay_manager *mgr = | 104 | priv->num_planes++; |
185 | omap_encoder_get_manager(priv->encoders[j]); | ||
186 | if (mgr->get_device(mgr) == dssdev) { | ||
187 | drm_mode_connector_attach_encoder(connector, | ||
188 | priv->encoders[j]); | ||
189 | } | ||
190 | } | 105 | } |
191 | 106 | ||
192 | return 0; | 107 | /* |
193 | } | 108 | * Create normal planes for the remaining overlays: |
194 | |||
195 | /* create up to max_overlays CRTCs mapping to overlays.. by default, | ||
196 | * connect the overlays to different managers/encoders, giving priority | ||
197 | * to encoders connected to connectors with a detected connection | ||
198 | */ | ||
199 | static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl, | ||
200 | int *j, unsigned int connected_connectors) | ||
201 | { | ||
202 | struct omap_drm_private *priv = dev->dev_private; | ||
203 | struct omap_overlay_manager *mgr = NULL; | ||
204 | struct drm_crtc *crtc; | ||
205 | |||
206 | /* find next best connector, ones with detected connection first | ||
207 | */ | 109 | */ |
208 | while (*j < priv->num_connectors && !mgr) { | 110 | for (; id < num_ovls; id++) { |
209 | if (connected_connectors & (1 << *j)) { | 111 | struct drm_plane *plane = omap_plane_init(dev, id, false); |
210 | struct drm_encoder *encoder = | ||
211 | omap_connector_attached_encoder( | ||
212 | priv->connectors[*j]); | ||
213 | if (encoder) | ||
214 | mgr = omap_encoder_get_manager(encoder); | ||
215 | 112 | ||
216 | } | 113 | BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); |
217 | (*j)++; | 114 | priv->planes[priv->num_planes++] = plane; |
218 | } | 115 | } |
219 | 116 | ||
220 | /* if we couldn't find another connected connector, lets start | 117 | for_each_dss_dev(dssdev) { |
221 | * looking at the unconnected connectors: | 118 | struct drm_connector *connector; |
222 | * | 119 | struct drm_encoder *encoder; |
223 | * note: it might not be immediately apparent, but thanks to | ||
224 | * the !mgr check in both this loop and the one above, the only | ||
225 | * way to enter this loop is with *j == priv->num_connectors, | ||
226 | * so idx can never go negative. | ||
227 | */ | ||
228 | while (*j < 2 * priv->num_connectors && !mgr) { | ||
229 | int idx = *j - priv->num_connectors; | ||
230 | if (!(connected_connectors & (1 << idx))) { | ||
231 | struct drm_encoder *encoder = | ||
232 | omap_connector_attached_encoder( | ||
233 | priv->connectors[idx]); | ||
234 | if (encoder) | ||
235 | mgr = omap_encoder_get_manager(encoder); | ||
236 | 120 | ||
121 | if (!dssdev->driver) { | ||
122 | dev_warn(dev->dev, "%s has no driver.. skipping it\n", | ||
123 | dssdev->name); | ||
124 | return 0; | ||
237 | } | 125 | } |
238 | (*j)++; | ||
239 | } | ||
240 | |||
241 | crtc = omap_crtc_init(dev, ovl, priv->num_crtcs); | ||
242 | |||
243 | if (!crtc) { | ||
244 | dev_err(dev->dev, "could not create CRTC: %s\n", | ||
245 | ovl->name); | ||
246 | return -ENOMEM; | ||
247 | } | ||
248 | 126 | ||
249 | BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); | 127 | if (!(dssdev->driver->get_timings || |
250 | 128 | dssdev->driver->read_edid)) { | |
251 | priv->crtcs[priv->num_crtcs++] = crtc; | 129 | dev_warn(dev->dev, "%s driver does not support " |
252 | 130 | "get_timings or read_edid.. skipping it!\n", | |
253 | return 0; | 131 | dssdev->name); |
254 | } | 132 | return 0; |
255 | |||
256 | static int create_plane(struct drm_device *dev, struct omap_overlay *ovl, | ||
257 | unsigned int possible_crtcs) | ||
258 | { | ||
259 | struct omap_drm_private *priv = dev->dev_private; | ||
260 | struct drm_plane *plane = | ||
261 | omap_plane_init(dev, ovl, possible_crtcs, false); | ||
262 | |||
263 | if (!plane) { | ||
264 | dev_err(dev->dev, "could not create plane: %s\n", | ||
265 | ovl->name); | ||
266 | return -ENOMEM; | ||
267 | } | ||
268 | |||
269 | BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); | ||
270 | |||
271 | priv->planes[priv->num_planes++] = plane; | ||
272 | |||
273 | return 0; | ||
274 | } | ||
275 | |||
276 | static int match_dev_name(struct omap_dss_device *dssdev, void *data) | ||
277 | { | ||
278 | return !strcmp(dssdev->name, data); | ||
279 | } | ||
280 | |||
281 | static unsigned int detect_connectors(struct drm_device *dev) | ||
282 | { | ||
283 | struct omap_drm_private *priv = dev->dev_private; | ||
284 | unsigned int connected_connectors = 0; | ||
285 | int i; | ||
286 | |||
287 | for (i = 0; i < priv->num_connectors; i++) { | ||
288 | struct drm_connector *connector = priv->connectors[i]; | ||
289 | if (omap_connector_detect(connector, true) == | ||
290 | connector_status_connected) { | ||
291 | connected_connectors |= (1 << i); | ||
292 | } | 133 | } |
293 | } | ||
294 | |||
295 | return connected_connectors; | ||
296 | } | ||
297 | 134 | ||
298 | static int omap_modeset_init(struct drm_device *dev) | 135 | encoder = omap_encoder_init(dev, dssdev); |
299 | { | ||
300 | const struct omap_drm_platform_data *pdata = dev->dev->platform_data; | ||
301 | struct omap_kms_platform_data *kms_pdata = NULL; | ||
302 | struct omap_drm_private *priv = dev->dev_private; | ||
303 | struct omap_dss_device *dssdev = NULL; | ||
304 | int i, j; | ||
305 | unsigned int connected_connectors = 0; | ||
306 | 136 | ||
307 | drm_mode_config_init(dev); | 137 | if (!encoder) { |
308 | 138 | dev_err(dev->dev, "could not create encoder: %s\n", | |
309 | if (pdata && pdata->kms_pdata) { | 139 | dssdev->name); |
310 | kms_pdata = pdata->kms_pdata; | 140 | return -ENOMEM; |
311 | |||
312 | /* if platform data is provided by the board file, use it to | ||
313 | * control which overlays, managers, and devices we own. | ||
314 | */ | ||
315 | for (i = 0; i < kms_pdata->mgr_cnt; i++) { | ||
316 | struct omap_overlay_manager *mgr = | ||
317 | omap_dss_get_overlay_manager( | ||
318 | kms_pdata->mgr_ids[i]); | ||
319 | create_encoder(dev, mgr); | ||
320 | } | ||
321 | |||
322 | for (i = 0; i < kms_pdata->dev_cnt; i++) { | ||
323 | struct omap_dss_device *dssdev = | ||
324 | omap_dss_find_device( | ||
325 | (void *)kms_pdata->dev_names[i], | ||
326 | match_dev_name); | ||
327 | if (!dssdev) { | ||
328 | dev_warn(dev->dev, "no such dssdev: %s\n", | ||
329 | kms_pdata->dev_names[i]); | ||
330 | continue; | ||
331 | } | ||
332 | create_connector(dev, dssdev); | ||
333 | } | 141 | } |
334 | 142 | ||
335 | connected_connectors = detect_connectors(dev); | 143 | connector = omap_connector_init(dev, |
144 | get_connector_type(dssdev), dssdev, encoder); | ||
336 | 145 | ||
337 | j = 0; | 146 | if (!connector) { |
338 | for (i = 0; i < kms_pdata->ovl_cnt; i++) { | 147 | dev_err(dev->dev, "could not create connector: %s\n", |
339 | struct omap_overlay *ovl = | 148 | dssdev->name); |
340 | omap_dss_get_overlay(kms_pdata->ovl_ids[i]); | 149 | return -ENOMEM; |
341 | create_crtc(dev, ovl, &j, connected_connectors); | ||
342 | } | 150 | } |
343 | 151 | ||
344 | for (i = 0; i < kms_pdata->pln_cnt; i++) { | 152 | BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); |
345 | struct omap_overlay *ovl = | 153 | BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); |
346 | omap_dss_get_overlay(kms_pdata->pln_ids[i]); | ||
347 | create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); | ||
348 | } | ||
349 | } else { | ||
350 | /* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try | ||
351 | * to make educated guesses about everything else | ||
352 | */ | ||
353 | int max_overlays = min(omap_dss_get_num_overlays(), num_crtc); | ||
354 | 154 | ||
355 | for (i = 0; i < omap_dss_get_num_overlay_managers(); i++) | 155 | priv->encoders[priv->num_encoders++] = encoder; |
356 | create_encoder(dev, omap_dss_get_overlay_manager(i)); | 156 | priv->connectors[priv->num_connectors++] = connector; |
357 | |||
358 | for_each_dss_dev(dssdev) { | ||
359 | create_connector(dev, dssdev); | ||
360 | } | ||
361 | 157 | ||
362 | connected_connectors = detect_connectors(dev); | 158 | drm_mode_connector_attach_encoder(connector, encoder); |
363 | 159 | ||
364 | j = 0; | 160 | /* figure out which crtc's we can connect the encoder to: */ |
365 | for (i = 0; i < max_overlays; i++) { | 161 | encoder->possible_crtcs = 0; |
366 | create_crtc(dev, omap_dss_get_overlay(i), | 162 | for (id = 0; id < priv->num_crtcs; id++) { |
367 | &j, connected_connectors); | 163 | enum omap_dss_output_id supported_outputs = |
368 | } | 164 | dss_feat_get_supported_outputs(pipe2chan(id)); |
369 | 165 | if (supported_outputs & dssdev->output->id) | |
370 | /* use any remaining overlays as drm planes */ | 166 | encoder->possible_crtcs |= (1 << id); |
371 | for (; i < omap_dss_get_num_overlays(); i++) { | ||
372 | struct omap_overlay *ovl = omap_dss_get_overlay(i); | ||
373 | create_plane(dev, ovl, (1 << priv->num_crtcs) - 1); | ||
374 | } | 167 | } |
375 | } | 168 | } |
376 | 169 | ||
377 | /* for now keep the mapping of CRTCs and encoders static.. */ | ||
378 | for (i = 0; i < priv->num_encoders; i++) { | ||
379 | struct drm_encoder *encoder = priv->encoders[i]; | ||
380 | struct omap_overlay_manager *mgr = | ||
381 | omap_encoder_get_manager(encoder); | ||
382 | |||
383 | encoder->possible_crtcs = (1 << priv->num_crtcs) - 1; | ||
384 | |||
385 | DBG("%s: possible_crtcs=%08x", mgr->name, | ||
386 | encoder->possible_crtcs); | ||
387 | } | ||
388 | |||
389 | dump_video_chains(); | ||
390 | |||
391 | dev->mode_config.min_width = 32; | 170 | dev->mode_config.min_width = 32; |
392 | dev->mode_config.min_height = 32; | 171 | dev->mode_config.min_height = 32; |
393 | 172 | ||
@@ -450,7 +229,7 @@ static int ioctl_gem_new(struct drm_device *dev, void *data, | |||
450 | struct drm_file *file_priv) | 229 | struct drm_file *file_priv) |
451 | { | 230 | { |
452 | struct drm_omap_gem_new *args = data; | 231 | struct drm_omap_gem_new *args = data; |
453 | DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv, | 232 | VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv, |
454 | args->size.bytes, args->flags); | 233 | args->size.bytes, args->flags); |
455 | return omap_gem_new_handle(dev, file_priv, args->size, | 234 | return omap_gem_new_handle(dev, file_priv, args->size, |
456 | args->flags, &args->handle); | 235 | args->flags, &args->handle); |
@@ -510,7 +289,7 @@ static int ioctl_gem_info(struct drm_device *dev, void *data, | |||
510 | struct drm_gem_object *obj; | 289 | struct drm_gem_object *obj; |
511 | int ret = 0; | 290 | int ret = 0; |
512 | 291 | ||
513 | DBG("%p:%p: handle=%d", dev, file_priv, args->handle); | 292 | VERB("%p:%p: handle=%d", dev, file_priv, args->handle); |
514 | 293 | ||
515 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); | 294 | obj = drm_gem_object_lookup(dev, file_priv, args->handle); |
516 | if (!obj) | 295 | if (!obj) |
@@ -565,14 +344,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
565 | 344 | ||
566 | dev->dev_private = priv; | 345 | dev->dev_private = priv; |
567 | 346 | ||
568 | ret = omapdss_compat_init(); | ||
569 | if (ret) { | ||
570 | dev_err(dev->dev, "coult not init omapdss\n"); | ||
571 | dev->dev_private = NULL; | ||
572 | kfree(priv); | ||
573 | return ret; | ||
574 | } | ||
575 | |||
576 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); | 347 | priv->wq = alloc_ordered_workqueue("omapdrm", 0); |
577 | 348 | ||
578 | INIT_LIST_HEAD(&priv->obj_list); | 349 | INIT_LIST_HEAD(&priv->obj_list); |
@@ -584,10 +355,13 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
584 | dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); | 355 | dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret); |
585 | dev->dev_private = NULL; | 356 | dev->dev_private = NULL; |
586 | kfree(priv); | 357 | kfree(priv); |
587 | omapdss_compat_uninit(); | ||
588 | return ret; | 358 | return ret; |
589 | } | 359 | } |
590 | 360 | ||
361 | ret = drm_vblank_init(dev, priv->num_crtcs); | ||
362 | if (ret) | ||
363 | dev_warn(dev->dev, "could not init vblank\n"); | ||
364 | |||
591 | priv->fbdev = omap_fbdev_init(dev); | 365 | priv->fbdev = omap_fbdev_init(dev); |
592 | if (!priv->fbdev) { | 366 | if (!priv->fbdev) { |
593 | dev_warn(dev->dev, "omap_fbdev_init failed\n"); | 367 | dev_warn(dev->dev, "omap_fbdev_init failed\n"); |
@@ -596,10 +370,6 @@ static int dev_load(struct drm_device *dev, unsigned long flags) | |||
596 | 370 | ||
597 | drm_kms_helper_poll_init(dev); | 371 | drm_kms_helper_poll_init(dev); |
598 | 372 | ||
599 | ret = drm_vblank_init(dev, priv->num_crtcs); | ||
600 | if (ret) | ||
601 | dev_warn(dev->dev, "could not init vblank\n"); | ||
602 | |||
603 | return 0; | 373 | return 0; |
604 | } | 374 | } |
605 | 375 | ||
@@ -609,8 +379,9 @@ static int dev_unload(struct drm_device *dev) | |||
609 | 379 | ||
610 | DBG("unload: dev=%p", dev); | 380 | DBG("unload: dev=%p", dev); |
611 | 381 | ||
612 | drm_vblank_cleanup(dev); | ||
613 | drm_kms_helper_poll_fini(dev); | 382 | drm_kms_helper_poll_fini(dev); |
383 | drm_vblank_cleanup(dev); | ||
384 | omap_drm_irq_uninstall(dev); | ||
614 | 385 | ||
615 | omap_fbdev_free(dev); | 386 | omap_fbdev_free(dev); |
616 | omap_modeset_free(dev); | 387 | omap_modeset_free(dev); |
@@ -619,8 +390,6 @@ static int dev_unload(struct drm_device *dev) | |||
619 | flush_workqueue(priv->wq); | 390 | flush_workqueue(priv->wq); |
620 | destroy_workqueue(priv->wq); | 391 | destroy_workqueue(priv->wq); |
621 | 392 | ||
622 | omapdss_compat_uninit(); | ||
623 | |||
624 | kfree(dev->dev_private); | 393 | kfree(dev->dev_private); |
625 | dev->dev_private = NULL; | 394 | dev->dev_private = NULL; |
626 | 395 | ||
@@ -680,7 +449,9 @@ static void dev_lastclose(struct drm_device *dev) | |||
680 | } | 449 | } |
681 | } | 450 | } |
682 | 451 | ||
452 | mutex_lock(&dev->mode_config.mutex); | ||
683 | ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev); | 453 | ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev); |
454 | mutex_unlock(&dev->mode_config.mutex); | ||
684 | if (ret) | 455 | if (ret) |
685 | DBG("failed to restore crtc mode"); | 456 | DBG("failed to restore crtc mode"); |
686 | } | 457 | } |
@@ -695,60 +466,6 @@ static void dev_postclose(struct drm_device *dev, struct drm_file *file) | |||
695 | DBG("postclose: dev=%p, file=%p", dev, file); | 466 | DBG("postclose: dev=%p, file=%p", dev, file); |
696 | } | 467 | } |
697 | 468 | ||
698 | /** | ||
699 | * enable_vblank - enable vblank interrupt events | ||
700 | * @dev: DRM device | ||
701 | * @crtc: which irq to enable | ||
702 | * | ||
703 | * Enable vblank interrupts for @crtc. If the device doesn't have | ||
704 | * a hardware vblank counter, this routine should be a no-op, since | ||
705 | * interrupts will have to stay on to keep the count accurate. | ||
706 | * | ||
707 | * RETURNS | ||
708 | * Zero on success, appropriate errno if the given @crtc's vblank | ||
709 | * interrupt cannot be enabled. | ||
710 | */ | ||
711 | static int dev_enable_vblank(struct drm_device *dev, int crtc) | ||
712 | { | ||
713 | DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc); | ||
714 | return 0; | ||
715 | } | ||
716 | |||
717 | /** | ||
718 | * disable_vblank - disable vblank interrupt events | ||
719 | * @dev: DRM device | ||
720 | * @crtc: which irq to enable | ||
721 | * | ||
722 | * Disable vblank interrupts for @crtc. If the device doesn't have | ||
723 | * a hardware vblank counter, this routine should be a no-op, since | ||
724 | * interrupts will have to stay on to keep the count accurate. | ||
725 | */ | ||
726 | static void dev_disable_vblank(struct drm_device *dev, int crtc) | ||
727 | { | ||
728 | DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc); | ||
729 | } | ||
730 | |||
731 | static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS) | ||
732 | { | ||
733 | return IRQ_HANDLED; | ||
734 | } | ||
735 | |||
736 | static void dev_irq_preinstall(struct drm_device *dev) | ||
737 | { | ||
738 | DBG("irq_preinstall: dev=%p", dev); | ||
739 | } | ||
740 | |||
741 | static int dev_irq_postinstall(struct drm_device *dev) | ||
742 | { | ||
743 | DBG("irq_postinstall: dev=%p", dev); | ||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | static void dev_irq_uninstall(struct drm_device *dev) | ||
748 | { | ||
749 | DBG("irq_uninstall: dev=%p", dev); | ||
750 | } | ||
751 | |||
752 | static const struct vm_operations_struct omap_gem_vm_ops = { | 469 | static const struct vm_operations_struct omap_gem_vm_ops = { |
753 | .fault = omap_gem_fault, | 470 | .fault = omap_gem_fault, |
754 | .open = drm_gem_vm_open, | 471 | .open = drm_gem_vm_open, |
@@ -778,12 +495,12 @@ static struct drm_driver omap_drm_driver = { | |||
778 | .preclose = dev_preclose, | 495 | .preclose = dev_preclose, |
779 | .postclose = dev_postclose, | 496 | .postclose = dev_postclose, |
780 | .get_vblank_counter = drm_vblank_count, | 497 | .get_vblank_counter = drm_vblank_count, |
781 | .enable_vblank = dev_enable_vblank, | 498 | .enable_vblank = omap_irq_enable_vblank, |
782 | .disable_vblank = dev_disable_vblank, | 499 | .disable_vblank = omap_irq_disable_vblank, |
783 | .irq_preinstall = dev_irq_preinstall, | 500 | .irq_preinstall = omap_irq_preinstall, |
784 | .irq_postinstall = dev_irq_postinstall, | 501 | .irq_postinstall = omap_irq_postinstall, |
785 | .irq_uninstall = dev_irq_uninstall, | 502 | .irq_uninstall = omap_irq_uninstall, |
786 | .irq_handler = dev_irq_handler, | 503 | .irq_handler = omap_irq_handler, |
787 | #ifdef CONFIG_DEBUG_FS | 504 | #ifdef CONFIG_DEBUG_FS |
788 | .debugfs_init = omap_debugfs_init, | 505 | .debugfs_init = omap_debugfs_init, |
789 | .debugfs_cleanup = omap_debugfs_cleanup, | 506 | .debugfs_cleanup = omap_debugfs_cleanup, |
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h index 1d4aea53b75d..cd1f22b0b124 100644 --- a/drivers/staging/omapdrm/omap_drv.h +++ b/drivers/staging/omapdrm/omap_drv.h | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <linux/platform_data/omap_drm.h> | 28 | #include <linux/platform_data/omap_drm.h> |
29 | #include "omap_drm.h" | 29 | #include "omap_drm.h" |
30 | 30 | ||
31 | |||
31 | #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) | 32 | #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) |
32 | #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */ | 33 | #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */ |
33 | 34 | ||
@@ -39,6 +40,51 @@ | |||
39 | */ | 40 | */ |
40 | #define MAX_MAPPERS 2 | 41 | #define MAX_MAPPERS 2 |
41 | 42 | ||
43 | /* parameters which describe (unrotated) coordinates of scanout within a fb: */ | ||
44 | struct omap_drm_window { | ||
45 | uint32_t rotation; | ||
46 | int32_t crtc_x, crtc_y; /* signed because can be offscreen */ | ||
47 | uint32_t crtc_w, crtc_h; | ||
48 | uint32_t src_x, src_y; | ||
49 | uint32_t src_w, src_h; | ||
50 | }; | ||
51 | |||
52 | /* Once GO bit is set, we can't make further updates to shadowed registers | ||
53 | * until the GO bit is cleared. So various parts in the kms code that need | ||
54 | * to update shadowed registers queue up a pair of callbacks, pre_apply | ||
55 | * which is called before setting GO bit, and post_apply that is called | ||
56 | * after GO bit is cleared. The crtc manages the queuing, and everyone | ||
57 | * else goes thru omap_crtc_apply() using these callbacks so that the | ||
58 | * code which has to deal w/ GO bit state is centralized. | ||
59 | */ | ||
60 | struct omap_drm_apply { | ||
61 | struct list_head pending_node, queued_node; | ||
62 | bool queued; | ||
63 | void (*pre_apply)(struct omap_drm_apply *apply); | ||
64 | void (*post_apply)(struct omap_drm_apply *apply); | ||
65 | }; | ||
66 | |||
67 | /* For transiently registering for different DSS irqs that various parts | ||
68 | * of the KMS code need during setup/configuration. We these are not | ||
69 | * necessarily the same as what drm_vblank_get/put() are requesting, and | ||
70 | * the hysteresis in drm_vblank_put() is not necessarily desirable for | ||
71 | * internal housekeeping related irq usage. | ||
72 | */ | ||
73 | struct omap_drm_irq { | ||
74 | struct list_head node; | ||
75 | uint32_t irqmask; | ||
76 | bool registered; | ||
77 | void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus); | ||
78 | }; | ||
79 | |||
80 | /* For KMS code that needs to wait for a certain # of IRQs: | ||
81 | */ | ||
82 | struct omap_irq_wait; | ||
83 | struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, | ||
84 | uint32_t irqmask, int count); | ||
85 | int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, | ||
86 | unsigned long timeout); | ||
87 | |||
42 | struct omap_drm_private { | 88 | struct omap_drm_private { |
43 | uint32_t omaprev; | 89 | uint32_t omaprev; |
44 | 90 | ||
@@ -58,6 +104,7 @@ struct omap_drm_private { | |||
58 | 104 | ||
59 | struct workqueue_struct *wq; | 105 | struct workqueue_struct *wq; |
60 | 106 | ||
107 | /* list of GEM objects: */ | ||
61 | struct list_head obj_list; | 108 | struct list_head obj_list; |
62 | 109 | ||
63 | bool has_dmm; | 110 | bool has_dmm; |
@@ -65,6 +112,11 @@ struct omap_drm_private { | |||
65 | /* properties: */ | 112 | /* properties: */ |
66 | struct drm_property *rotation_prop; | 113 | struct drm_property *rotation_prop; |
67 | struct drm_property *zorder_prop; | 114 | struct drm_property *zorder_prop; |
115 | |||
116 | /* irq handling: */ | ||
117 | struct list_head irq_list; /* list of omap_drm_irq */ | ||
118 | uint32_t vblank_mask; /* irq bits set for userspace vblank */ | ||
119 | struct omap_drm_irq error_handler; | ||
68 | }; | 120 | }; |
69 | 121 | ||
70 | /* this should probably be in drm-core to standardize amongst drivers */ | 122 | /* this should probably be in drm-core to standardize amongst drivers */ |
@@ -75,15 +127,6 @@ struct omap_drm_private { | |||
75 | #define DRM_REFLECT_X 4 | 127 | #define DRM_REFLECT_X 4 |
76 | #define DRM_REFLECT_Y 5 | 128 | #define DRM_REFLECT_Y 5 |
77 | 129 | ||
78 | /* parameters which describe (unrotated) coordinates of scanout within a fb: */ | ||
79 | struct omap_drm_window { | ||
80 | uint32_t rotation; | ||
81 | int32_t crtc_x, crtc_y; /* signed because can be offscreen */ | ||
82 | uint32_t crtc_w, crtc_h; | ||
83 | uint32_t src_x, src_y; | ||
84 | uint32_t src_w, src_h; | ||
85 | }; | ||
86 | |||
87 | #ifdef CONFIG_DEBUG_FS | 130 | #ifdef CONFIG_DEBUG_FS |
88 | int omap_debugfs_init(struct drm_minor *minor); | 131 | int omap_debugfs_init(struct drm_minor *minor); |
89 | void omap_debugfs_cleanup(struct drm_minor *minor); | 132 | void omap_debugfs_cleanup(struct drm_minor *minor); |
@@ -92,23 +135,36 @@ void omap_gem_describe(struct drm_gem_object *obj, struct seq_file *m); | |||
92 | void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); | 135 | void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); |
93 | #endif | 136 | #endif |
94 | 137 | ||
138 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc); | ||
139 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc); | ||
140 | irqreturn_t omap_irq_handler(DRM_IRQ_ARGS); | ||
141 | void omap_irq_preinstall(struct drm_device *dev); | ||
142 | int omap_irq_postinstall(struct drm_device *dev); | ||
143 | void omap_irq_uninstall(struct drm_device *dev); | ||
144 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq); | ||
145 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq); | ||
146 | int omap_drm_irq_uninstall(struct drm_device *dev); | ||
147 | int omap_drm_irq_install(struct drm_device *dev); | ||
148 | |||
95 | struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); | 149 | struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev); |
96 | void omap_fbdev_free(struct drm_device *dev); | 150 | void omap_fbdev_free(struct drm_device *dev); |
97 | 151 | ||
152 | const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc); | ||
153 | enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); | ||
154 | int omap_crtc_apply(struct drm_crtc *crtc, | ||
155 | struct omap_drm_apply *apply); | ||
98 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, | 156 | struct drm_crtc *omap_crtc_init(struct drm_device *dev, |
99 | struct omap_overlay *ovl, int id); | 157 | struct drm_plane *plane, enum omap_channel channel, int id); |
100 | 158 | ||
101 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 159 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
102 | struct omap_overlay *ovl, unsigned int possible_crtcs, | 160 | int plane_id, bool private_plane); |
103 | bool priv); | ||
104 | int omap_plane_dpms(struct drm_plane *plane, int mode); | 161 | int omap_plane_dpms(struct drm_plane *plane, int mode); |
105 | int omap_plane_mode_set(struct drm_plane *plane, | 162 | int omap_plane_mode_set(struct drm_plane *plane, |
106 | struct drm_crtc *crtc, struct drm_framebuffer *fb, | 163 | struct drm_crtc *crtc, struct drm_framebuffer *fb, |
107 | int crtc_x, int crtc_y, | 164 | int crtc_x, int crtc_y, |
108 | unsigned int crtc_w, unsigned int crtc_h, | 165 | unsigned int crtc_w, unsigned int crtc_h, |
109 | uint32_t src_x, uint32_t src_y, | 166 | uint32_t src_x, uint32_t src_y, |
110 | uint32_t src_w, uint32_t src_h); | 167 | uint32_t src_w, uint32_t src_h, |
111 | void omap_plane_on_endwin(struct drm_plane *plane, | ||
112 | void (*fxn)(void *), void *arg); | 168 | void (*fxn)(void *), void *arg); |
113 | void omap_plane_install_properties(struct drm_plane *plane, | 169 | void omap_plane_install_properties(struct drm_plane *plane, |
114 | struct drm_mode_object *obj); | 170 | struct drm_mode_object *obj); |
@@ -116,21 +172,25 @@ int omap_plane_set_property(struct drm_plane *plane, | |||
116 | struct drm_property *property, uint64_t val); | 172 | struct drm_property *property, uint64_t val); |
117 | 173 | ||
118 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, | 174 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, |
119 | struct omap_overlay_manager *mgr); | 175 | struct omap_dss_device *dssdev); |
120 | struct omap_overlay_manager *omap_encoder_get_manager( | 176 | int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled); |
177 | int omap_encoder_update(struct drm_encoder *encoder, | ||
178 | struct omap_overlay_manager *mgr, | ||
179 | struct omap_video_timings *timings); | ||
180 | |||
181 | struct drm_connector *omap_connector_init(struct drm_device *dev, | ||
182 | int connector_type, struct omap_dss_device *dssdev, | ||
121 | struct drm_encoder *encoder); | 183 | struct drm_encoder *encoder); |
122 | struct drm_encoder *omap_connector_attached_encoder( | 184 | struct drm_encoder *omap_connector_attached_encoder( |
123 | struct drm_connector *connector); | 185 | struct drm_connector *connector); |
124 | enum drm_connector_status omap_connector_detect( | ||
125 | struct drm_connector *connector, bool force); | ||
126 | |||
127 | struct drm_connector *omap_connector_init(struct drm_device *dev, | ||
128 | int connector_type, struct omap_dss_device *dssdev); | ||
129 | void omap_connector_mode_set(struct drm_connector *connector, | ||
130 | struct drm_display_mode *mode); | ||
131 | void omap_connector_flush(struct drm_connector *connector, | 186 | void omap_connector_flush(struct drm_connector *connector, |
132 | int x, int y, int w, int h); | 187 | int x, int y, int w, int h); |
133 | 188 | ||
189 | void copy_timings_omap_to_drm(struct drm_display_mode *mode, | ||
190 | struct omap_video_timings *timings); | ||
191 | void copy_timings_drm_to_omap(struct omap_video_timings *timings, | ||
192 | struct drm_display_mode *mode); | ||
193 | |||
134 | uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats, | 194 | uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats, |
135 | uint32_t max_formats, enum omap_color_mode supported_modes); | 195 | uint32_t max_formats, enum omap_color_mode supported_modes); |
136 | struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, | 196 | struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev, |
@@ -207,6 +267,40 @@ static inline int align_pitch(int pitch, int width, int bpp) | |||
207 | return ALIGN(pitch, 8 * bytespp); | 267 | return ALIGN(pitch, 8 * bytespp); |
208 | } | 268 | } |
209 | 269 | ||
270 | static inline enum omap_channel pipe2chan(int pipe) | ||
271 | { | ||
272 | int num_mgrs = dss_feat_get_num_mgrs(); | ||
273 | |||
274 | /* | ||
275 | * We usually don't want to create a CRTC for each manager, | ||
276 | * at least not until we have a way to expose private planes | ||
277 | * to userspace. Otherwise there would not be enough video | ||
278 | * pipes left for drm planes. The higher #'d managers tend | ||
279 | * to have more features so start in reverse order. | ||
280 | */ | ||
281 | return num_mgrs - pipe - 1; | ||
282 | } | ||
283 | |||
284 | /* map crtc to vblank mask */ | ||
285 | static inline uint32_t pipe2vbl(int crtc) | ||
286 | { | ||
287 | enum omap_channel channel = pipe2chan(crtc); | ||
288 | return dispc_mgr_get_vsync_irq(channel); | ||
289 | } | ||
290 | |||
291 | static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc) | ||
292 | { | ||
293 | struct omap_drm_private *priv = dev->dev_private; | ||
294 | int i; | ||
295 | |||
296 | for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++) | ||
297 | if (priv->crtcs[i] == crtc) | ||
298 | return i; | ||
299 | |||
300 | BUG(); /* bogus CRTC ptr */ | ||
301 | return -1; | ||
302 | } | ||
303 | |||
210 | /* should these be made into common util helpers? | 304 | /* should these be made into common util helpers? |
211 | */ | 305 | */ |
212 | 306 | ||
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c index 5341d5e3e317..e053160d2db3 100644 --- a/drivers/staging/omapdrm/omap_encoder.c +++ b/drivers/staging/omapdrm/omap_encoder.c | |||
@@ -22,37 +22,56 @@ | |||
22 | #include "drm_crtc.h" | 22 | #include "drm_crtc.h" |
23 | #include "drm_crtc_helper.h" | 23 | #include "drm_crtc_helper.h" |
24 | 24 | ||
25 | #include <linux/list.h> | ||
26 | |||
27 | |||
25 | /* | 28 | /* |
26 | * encoder funcs | 29 | * encoder funcs |
27 | */ | 30 | */ |
28 | 31 | ||
29 | #define to_omap_encoder(x) container_of(x, struct omap_encoder, base) | 32 | #define to_omap_encoder(x) container_of(x, struct omap_encoder, base) |
30 | 33 | ||
34 | /* The encoder and connector both map to same dssdev.. the encoder | ||
35 | * handles the 'active' parts, ie. anything the modifies the state | ||
36 | * of the hw, and the connector handles the 'read-only' parts, like | ||
37 | * detecting connection and reading edid. | ||
38 | */ | ||
31 | struct omap_encoder { | 39 | struct omap_encoder { |
32 | struct drm_encoder base; | 40 | struct drm_encoder base; |
33 | struct omap_overlay_manager *mgr; | 41 | struct omap_dss_device *dssdev; |
34 | }; | 42 | }; |
35 | 43 | ||
36 | static void omap_encoder_destroy(struct drm_encoder *encoder) | 44 | static void omap_encoder_destroy(struct drm_encoder *encoder) |
37 | { | 45 | { |
38 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 46 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
39 | DBG("%s", omap_encoder->mgr->name); | ||
40 | drm_encoder_cleanup(encoder); | 47 | drm_encoder_cleanup(encoder); |
41 | kfree(omap_encoder); | 48 | kfree(omap_encoder); |
42 | } | 49 | } |
43 | 50 | ||
51 | static const struct drm_encoder_funcs omap_encoder_funcs = { | ||
52 | .destroy = omap_encoder_destroy, | ||
53 | }; | ||
54 | |||
55 | /* | ||
56 | * The CRTC drm_crtc_helper_set_mode() doesn't really give us the right | ||
57 | * order.. the easiest way to work around this for now is to make all | ||
58 | * the encoder-helper's no-op's and have the omap_crtc code take care | ||
59 | * of the sequencing and call us in the right points. | ||
60 | * | ||
61 | * Eventually to handle connecting CRTCs to different encoders properly, | ||
62 | * either the CRTC helpers need to change or we need to replace | ||
63 | * drm_crtc_helper_set_mode(), but lets wait until atomic-modeset for | ||
64 | * that. | ||
65 | */ | ||
66 | |||
44 | static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) | 67 | static void omap_encoder_dpms(struct drm_encoder *encoder, int mode) |
45 | { | 68 | { |
46 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
47 | DBG("%s: %d", omap_encoder->mgr->name, mode); | ||
48 | } | 69 | } |
49 | 70 | ||
50 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, | 71 | static bool omap_encoder_mode_fixup(struct drm_encoder *encoder, |
51 | const struct drm_display_mode *mode, | 72 | const struct drm_display_mode *mode, |
52 | struct drm_display_mode *adjusted_mode) | 73 | struct drm_display_mode *adjusted_mode) |
53 | { | 74 | { |
54 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
55 | DBG("%s", omap_encoder->mgr->name); | ||
56 | return true; | 75 | return true; |
57 | } | 76 | } |
58 | 77 | ||
@@ -60,47 +79,16 @@ static void omap_encoder_mode_set(struct drm_encoder *encoder, | |||
60 | struct drm_display_mode *mode, | 79 | struct drm_display_mode *mode, |
61 | struct drm_display_mode *adjusted_mode) | 80 | struct drm_display_mode *adjusted_mode) |
62 | { | 81 | { |
63 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
64 | struct drm_device *dev = encoder->dev; | ||
65 | struct omap_drm_private *priv = dev->dev_private; | ||
66 | int i; | ||
67 | |||
68 | mode = adjusted_mode; | ||
69 | |||
70 | DBG("%s: set mode: %dx%d", omap_encoder->mgr->name, | ||
71 | mode->hdisplay, mode->vdisplay); | ||
72 | |||
73 | for (i = 0; i < priv->num_connectors; i++) { | ||
74 | struct drm_connector *connector = priv->connectors[i]; | ||
75 | if (connector->encoder == encoder) | ||
76 | omap_connector_mode_set(connector, mode); | ||
77 | |||
78 | } | ||
79 | } | 82 | } |
80 | 83 | ||
81 | static void omap_encoder_prepare(struct drm_encoder *encoder) | 84 | static void omap_encoder_prepare(struct drm_encoder *encoder) |
82 | { | 85 | { |
83 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
84 | struct drm_encoder_helper_funcs *encoder_funcs = | ||
85 | encoder->helper_private; | ||
86 | DBG("%s", omap_encoder->mgr->name); | ||
87 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); | ||
88 | } | 86 | } |
89 | 87 | ||
90 | static void omap_encoder_commit(struct drm_encoder *encoder) | 88 | static void omap_encoder_commit(struct drm_encoder *encoder) |
91 | { | 89 | { |
92 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
93 | struct drm_encoder_helper_funcs *encoder_funcs = | ||
94 | encoder->helper_private; | ||
95 | DBG("%s", omap_encoder->mgr->name); | ||
96 | omap_encoder->mgr->apply(omap_encoder->mgr); | ||
97 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); | ||
98 | } | 90 | } |
99 | 91 | ||
100 | static const struct drm_encoder_funcs omap_encoder_funcs = { | ||
101 | .destroy = omap_encoder_destroy, | ||
102 | }; | ||
103 | |||
104 | static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { | 92 | static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { |
105 | .dpms = omap_encoder_dpms, | 93 | .dpms = omap_encoder_dpms, |
106 | .mode_fixup = omap_encoder_mode_fixup, | 94 | .mode_fixup = omap_encoder_mode_fixup, |
@@ -109,23 +97,54 @@ static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = { | |||
109 | .commit = omap_encoder_commit, | 97 | .commit = omap_encoder_commit, |
110 | }; | 98 | }; |
111 | 99 | ||
112 | struct omap_overlay_manager *omap_encoder_get_manager( | 100 | /* |
113 | struct drm_encoder *encoder) | 101 | * Instead of relying on the helpers for modeset, the omap_crtc code |
102 | * calls these functions in the proper sequence. | ||
103 | */ | ||
104 | |||
105 | int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled) | ||
114 | { | 106 | { |
115 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | 107 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); |
116 | return omap_encoder->mgr; | 108 | struct omap_dss_device *dssdev = omap_encoder->dssdev; |
109 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
110 | |||
111 | if (enabled) { | ||
112 | return dssdrv->enable(dssdev); | ||
113 | } else { | ||
114 | dssdrv->disable(dssdev); | ||
115 | return 0; | ||
116 | } | ||
117 | } | ||
118 | |||
119 | int omap_encoder_update(struct drm_encoder *encoder, | ||
120 | struct omap_overlay_manager *mgr, | ||
121 | struct omap_video_timings *timings) | ||
122 | { | ||
123 | struct drm_device *dev = encoder->dev; | ||
124 | struct omap_encoder *omap_encoder = to_omap_encoder(encoder); | ||
125 | struct omap_dss_device *dssdev = omap_encoder->dssdev; | ||
126 | struct omap_dss_driver *dssdrv = dssdev->driver; | ||
127 | int ret; | ||
128 | |||
129 | dssdev->output->manager = mgr; | ||
130 | |||
131 | ret = dssdrv->check_timings(dssdev, timings); | ||
132 | if (ret) { | ||
133 | dev_err(dev->dev, "could not set timings: %d\n", ret); | ||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | dssdrv->set_timings(dssdev, timings); | ||
138 | |||
139 | return 0; | ||
117 | } | 140 | } |
118 | 141 | ||
119 | /* initialize encoder */ | 142 | /* initialize encoder */ |
120 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, | 143 | struct drm_encoder *omap_encoder_init(struct drm_device *dev, |
121 | struct omap_overlay_manager *mgr) | 144 | struct omap_dss_device *dssdev) |
122 | { | 145 | { |
123 | struct drm_encoder *encoder = NULL; | 146 | struct drm_encoder *encoder = NULL; |
124 | struct omap_encoder *omap_encoder; | 147 | struct omap_encoder *omap_encoder; |
125 | struct omap_overlay_manager_info info; | ||
126 | int ret; | ||
127 | |||
128 | DBG("%s", mgr->name); | ||
129 | 148 | ||
130 | omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL); | 149 | omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL); |
131 | if (!omap_encoder) { | 150 | if (!omap_encoder) { |
@@ -133,33 +152,14 @@ struct drm_encoder *omap_encoder_init(struct drm_device *dev, | |||
133 | goto fail; | 152 | goto fail; |
134 | } | 153 | } |
135 | 154 | ||
136 | omap_encoder->mgr = mgr; | 155 | omap_encoder->dssdev = dssdev; |
156 | |||
137 | encoder = &omap_encoder->base; | 157 | encoder = &omap_encoder->base; |
138 | 158 | ||
139 | drm_encoder_init(dev, encoder, &omap_encoder_funcs, | 159 | drm_encoder_init(dev, encoder, &omap_encoder_funcs, |
140 | DRM_MODE_ENCODER_TMDS); | 160 | DRM_MODE_ENCODER_TMDS); |
141 | drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs); | 161 | drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs); |
142 | 162 | ||
143 | mgr->get_manager_info(mgr, &info); | ||
144 | |||
145 | /* TODO: fix hard-coded setup.. */ | ||
146 | info.default_color = 0x00000000; | ||
147 | info.trans_key = 0x00000000; | ||
148 | info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; | ||
149 | info.trans_enabled = false; | ||
150 | |||
151 | ret = mgr->set_manager_info(mgr, &info); | ||
152 | if (ret) { | ||
153 | dev_err(dev->dev, "could not set manager info\n"); | ||
154 | goto fail; | ||
155 | } | ||
156 | |||
157 | ret = mgr->apply(mgr); | ||
158 | if (ret) { | ||
159 | dev_err(dev->dev, "could not apply\n"); | ||
160 | goto fail; | ||
161 | } | ||
162 | |||
163 | return encoder; | 163 | return encoder; |
164 | 164 | ||
165 | fail: | 165 | fail: |
diff --git a/drivers/staging/omapdrm/omap_gem_dmabuf.c b/drivers/staging/omapdrm/omap_gem_dmabuf.c index ea3840038250..b6c5b5c6c8c5 100644 --- a/drivers/staging/omapdrm/omap_gem_dmabuf.c +++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c | |||
@@ -194,7 +194,7 @@ struct dma_buf_ops omap_dmabuf_ops = { | |||
194 | struct dma_buf *omap_gem_prime_export(struct drm_device *dev, | 194 | struct dma_buf *omap_gem_prime_export(struct drm_device *dev, |
195 | struct drm_gem_object *obj, int flags) | 195 | struct drm_gem_object *obj, int flags) |
196 | { | 196 | { |
197 | return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600); | 197 | return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags); |
198 | } | 198 | } |
199 | 199 | ||
200 | struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, | 200 | struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev, |
diff --git a/drivers/staging/omapdrm/omap_irq.c b/drivers/staging/omapdrm/omap_irq.c new file mode 100644 index 000000000000..2629ba7be6c8 --- /dev/null +++ b/drivers/staging/omapdrm/omap_irq.c | |||
@@ -0,0 +1,322 @@ | |||
1 | /* | ||
2 | * drivers/staging/omapdrm/omap_irq.c | ||
3 | * | ||
4 | * Copyright (C) 2012 Texas Instruments | ||
5 | * Author: Rob Clark <rob.clark@linaro.org> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms of the GNU General Public License version 2 as published by | ||
9 | * the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | */ | ||
19 | |||
20 | #include "omap_drv.h" | ||
21 | |||
22 | static DEFINE_SPINLOCK(list_lock); | ||
23 | |||
24 | static void omap_irq_error_handler(struct omap_drm_irq *irq, | ||
25 | uint32_t irqstatus) | ||
26 | { | ||
27 | DRM_ERROR("errors: %08x\n", irqstatus); | ||
28 | } | ||
29 | |||
30 | /* call with list_lock and dispc runtime held */ | ||
31 | static void omap_irq_update(struct drm_device *dev) | ||
32 | { | ||
33 | struct omap_drm_private *priv = dev->dev_private; | ||
34 | struct omap_drm_irq *irq; | ||
35 | uint32_t irqmask = priv->vblank_mask; | ||
36 | |||
37 | BUG_ON(!spin_is_locked(&list_lock)); | ||
38 | |||
39 | list_for_each_entry(irq, &priv->irq_list, node) | ||
40 | irqmask |= irq->irqmask; | ||
41 | |||
42 | DBG("irqmask=%08x", irqmask); | ||
43 | |||
44 | dispc_write_irqenable(irqmask); | ||
45 | dispc_read_irqenable(); /* flush posted write */ | ||
46 | } | ||
47 | |||
48 | void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq) | ||
49 | { | ||
50 | struct omap_drm_private *priv = dev->dev_private; | ||
51 | unsigned long flags; | ||
52 | |||
53 | dispc_runtime_get(); | ||
54 | spin_lock_irqsave(&list_lock, flags); | ||
55 | |||
56 | if (!WARN_ON(irq->registered)) { | ||
57 | irq->registered = true; | ||
58 | list_add(&irq->node, &priv->irq_list); | ||
59 | omap_irq_update(dev); | ||
60 | } | ||
61 | |||
62 | spin_unlock_irqrestore(&list_lock, flags); | ||
63 | dispc_runtime_put(); | ||
64 | } | ||
65 | |||
66 | void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq) | ||
67 | { | ||
68 | unsigned long flags; | ||
69 | |||
70 | dispc_runtime_get(); | ||
71 | spin_lock_irqsave(&list_lock, flags); | ||
72 | |||
73 | if (!WARN_ON(!irq->registered)) { | ||
74 | irq->registered = false; | ||
75 | list_del(&irq->node); | ||
76 | omap_irq_update(dev); | ||
77 | } | ||
78 | |||
79 | spin_unlock_irqrestore(&list_lock, flags); | ||
80 | dispc_runtime_put(); | ||
81 | } | ||
82 | |||
83 | struct omap_irq_wait { | ||
84 | struct omap_drm_irq irq; | ||
85 | int count; | ||
86 | }; | ||
87 | |||
88 | static DECLARE_WAIT_QUEUE_HEAD(wait_event); | ||
89 | |||
90 | static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
91 | { | ||
92 | struct omap_irq_wait *wait = | ||
93 | container_of(irq, struct omap_irq_wait, irq); | ||
94 | wait->count--; | ||
95 | wake_up_all(&wait_event); | ||
96 | } | ||
97 | |||
98 | struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev, | ||
99 | uint32_t irqmask, int count) | ||
100 | { | ||
101 | struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL); | ||
102 | wait->irq.irq = wait_irq; | ||
103 | wait->irq.irqmask = irqmask; | ||
104 | wait->count = count; | ||
105 | omap_irq_register(dev, &wait->irq); | ||
106 | return wait; | ||
107 | } | ||
108 | |||
109 | int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, | ||
110 | unsigned long timeout) | ||
111 | { | ||
112 | int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout); | ||
113 | omap_irq_unregister(dev, &wait->irq); | ||
114 | kfree(wait); | ||
115 | if (ret == 0) | ||
116 | return -1; | ||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | /** | ||
121 | * enable_vblank - enable vblank interrupt events | ||
122 | * @dev: DRM device | ||
123 | * @crtc: which irq to enable | ||
124 | * | ||
125 | * Enable vblank interrupts for @crtc. If the device doesn't have | ||
126 | * a hardware vblank counter, this routine should be a no-op, since | ||
127 | * interrupts will have to stay on to keep the count accurate. | ||
128 | * | ||
129 | * RETURNS | ||
130 | * Zero on success, appropriate errno if the given @crtc's vblank | ||
131 | * interrupt cannot be enabled. | ||
132 | */ | ||
133 | int omap_irq_enable_vblank(struct drm_device *dev, int crtc) | ||
134 | { | ||
135 | struct omap_drm_private *priv = dev->dev_private; | ||
136 | unsigned long flags; | ||
137 | |||
138 | DBG("dev=%p, crtc=%d", dev, crtc); | ||
139 | |||
140 | dispc_runtime_get(); | ||
141 | spin_lock_irqsave(&list_lock, flags); | ||
142 | priv->vblank_mask |= pipe2vbl(crtc); | ||
143 | omap_irq_update(dev); | ||
144 | spin_unlock_irqrestore(&list_lock, flags); | ||
145 | dispc_runtime_put(); | ||
146 | |||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | /** | ||
151 | * disable_vblank - disable vblank interrupt events | ||
152 | * @dev: DRM device | ||
153 | * @crtc: which irq to enable | ||
154 | * | ||
155 | * Disable vblank interrupts for @crtc. If the device doesn't have | ||
156 | * a hardware vblank counter, this routine should be a no-op, since | ||
157 | * interrupts will have to stay on to keep the count accurate. | ||
158 | */ | ||
159 | void omap_irq_disable_vblank(struct drm_device *dev, int crtc) | ||
160 | { | ||
161 | struct omap_drm_private *priv = dev->dev_private; | ||
162 | unsigned long flags; | ||
163 | |||
164 | DBG("dev=%p, crtc=%d", dev, crtc); | ||
165 | |||
166 | dispc_runtime_get(); | ||
167 | spin_lock_irqsave(&list_lock, flags); | ||
168 | priv->vblank_mask &= ~pipe2vbl(crtc); | ||
169 | omap_irq_update(dev); | ||
170 | spin_unlock_irqrestore(&list_lock, flags); | ||
171 | dispc_runtime_put(); | ||
172 | } | ||
173 | |||
174 | irqreturn_t omap_irq_handler(DRM_IRQ_ARGS) | ||
175 | { | ||
176 | struct drm_device *dev = (struct drm_device *) arg; | ||
177 | struct omap_drm_private *priv = dev->dev_private; | ||
178 | struct omap_drm_irq *handler, *n; | ||
179 | unsigned long flags; | ||
180 | unsigned int id; | ||
181 | u32 irqstatus; | ||
182 | |||
183 | irqstatus = dispc_read_irqstatus(); | ||
184 | dispc_clear_irqstatus(irqstatus); | ||
185 | dispc_read_irqstatus(); /* flush posted write */ | ||
186 | |||
187 | VERB("irqs: %08x", irqstatus); | ||
188 | |||
189 | for (id = 0; id < priv->num_crtcs; id++) | ||
190 | if (irqstatus & pipe2vbl(id)) | ||
191 | drm_handle_vblank(dev, id); | ||
192 | |||
193 | spin_lock_irqsave(&list_lock, flags); | ||
194 | list_for_each_entry_safe(handler, n, &priv->irq_list, node) { | ||
195 | if (handler->irqmask & irqstatus) { | ||
196 | spin_unlock_irqrestore(&list_lock, flags); | ||
197 | handler->irq(handler, handler->irqmask & irqstatus); | ||
198 | spin_lock_irqsave(&list_lock, flags); | ||
199 | } | ||
200 | } | ||
201 | spin_unlock_irqrestore(&list_lock, flags); | ||
202 | |||
203 | return IRQ_HANDLED; | ||
204 | } | ||
205 | |||
206 | void omap_irq_preinstall(struct drm_device *dev) | ||
207 | { | ||
208 | DBG("dev=%p", dev); | ||
209 | dispc_runtime_get(); | ||
210 | dispc_clear_irqstatus(0xffffffff); | ||
211 | dispc_runtime_put(); | ||
212 | } | ||
213 | |||
214 | int omap_irq_postinstall(struct drm_device *dev) | ||
215 | { | ||
216 | struct omap_drm_private *priv = dev->dev_private; | ||
217 | struct omap_drm_irq *error_handler = &priv->error_handler; | ||
218 | |||
219 | DBG("dev=%p", dev); | ||
220 | |||
221 | INIT_LIST_HEAD(&priv->irq_list); | ||
222 | |||
223 | error_handler->irq = omap_irq_error_handler; | ||
224 | error_handler->irqmask = DISPC_IRQ_OCP_ERR; | ||
225 | |||
226 | /* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think | ||
227 | * we just need to ignore it while enabling tv-out | ||
228 | */ | ||
229 | error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT; | ||
230 | |||
231 | omap_irq_register(dev, error_handler); | ||
232 | |||
233 | return 0; | ||
234 | } | ||
235 | |||
236 | void omap_irq_uninstall(struct drm_device *dev) | ||
237 | { | ||
238 | DBG("dev=%p", dev); | ||
239 | // TODO prolly need to call drm_irq_uninstall() somewhere too | ||
240 | } | ||
241 | |||
242 | /* | ||
243 | * We need a special version, instead of just using drm_irq_install(), | ||
244 | * because we need to register the irq via omapdss. Once omapdss and | ||
245 | * omapdrm are merged together we can assign the dispc hwmod data to | ||
246 | * ourselves and drop these and just use drm_irq_{install,uninstall}() | ||
247 | */ | ||
248 | |||
249 | int omap_drm_irq_install(struct drm_device *dev) | ||
250 | { | ||
251 | int ret; | ||
252 | |||
253 | mutex_lock(&dev->struct_mutex); | ||
254 | |||
255 | if (dev->irq_enabled) { | ||
256 | mutex_unlock(&dev->struct_mutex); | ||
257 | return -EBUSY; | ||
258 | } | ||
259 | dev->irq_enabled = 1; | ||
260 | mutex_unlock(&dev->struct_mutex); | ||
261 | |||
262 | /* Before installing handler */ | ||
263 | if (dev->driver->irq_preinstall) | ||
264 | dev->driver->irq_preinstall(dev); | ||
265 | |||
266 | ret = dispc_request_irq(dev->driver->irq_handler, dev); | ||
267 | |||
268 | if (ret < 0) { | ||
269 | mutex_lock(&dev->struct_mutex); | ||
270 | dev->irq_enabled = 0; | ||
271 | mutex_unlock(&dev->struct_mutex); | ||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | /* After installing handler */ | ||
276 | if (dev->driver->irq_postinstall) | ||
277 | ret = dev->driver->irq_postinstall(dev); | ||
278 | |||
279 | if (ret < 0) { | ||
280 | mutex_lock(&dev->struct_mutex); | ||
281 | dev->irq_enabled = 0; | ||
282 | mutex_unlock(&dev->struct_mutex); | ||
283 | dispc_free_irq(dev); | ||
284 | } | ||
285 | |||
286 | return ret; | ||
287 | } | ||
288 | |||
289 | int omap_drm_irq_uninstall(struct drm_device *dev) | ||
290 | { | ||
291 | unsigned long irqflags; | ||
292 | int irq_enabled, i; | ||
293 | |||
294 | mutex_lock(&dev->struct_mutex); | ||
295 | irq_enabled = dev->irq_enabled; | ||
296 | dev->irq_enabled = 0; | ||
297 | mutex_unlock(&dev->struct_mutex); | ||
298 | |||
299 | /* | ||
300 | * Wake up any waiters so they don't hang. | ||
301 | */ | ||
302 | if (dev->num_crtcs) { | ||
303 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | ||
304 | for (i = 0; i < dev->num_crtcs; i++) { | ||
305 | DRM_WAKEUP(&dev->vbl_queue[i]); | ||
306 | dev->vblank_enabled[i] = 0; | ||
307 | dev->last_vblank[i] = | ||
308 | dev->driver->get_vblank_counter(dev, i); | ||
309 | } | ||
310 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); | ||
311 | } | ||
312 | |||
313 | if (!irq_enabled) | ||
314 | return -EINVAL; | ||
315 | |||
316 | if (dev->driver->irq_uninstall) | ||
317 | dev->driver->irq_uninstall(dev); | ||
318 | |||
319 | dispc_free_irq(dev); | ||
320 | |||
321 | return 0; | ||
322 | } | ||
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c index 2a8e5bab49c9..bb989d7f026d 100644 --- a/drivers/staging/omapdrm/omap_plane.c +++ b/drivers/staging/omapdrm/omap_plane.c | |||
@@ -41,12 +41,14 @@ struct callback { | |||
41 | 41 | ||
42 | struct omap_plane { | 42 | struct omap_plane { |
43 | struct drm_plane base; | 43 | struct drm_plane base; |
44 | struct omap_overlay *ovl; | 44 | int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */ |
45 | const char *name; | ||
45 | struct omap_overlay_info info; | 46 | struct omap_overlay_info info; |
47 | struct omap_drm_apply apply; | ||
46 | 48 | ||
47 | /* position/orientation of scanout within the fb: */ | 49 | /* position/orientation of scanout within the fb: */ |
48 | struct omap_drm_window win; | 50 | struct omap_drm_window win; |
49 | 51 | bool enabled; | |
50 | 52 | ||
51 | /* last fb that we pinned: */ | 53 | /* last fb that we pinned: */ |
52 | struct drm_framebuffer *pinned_fb; | 54 | struct drm_framebuffer *pinned_fb; |
@@ -54,189 +56,15 @@ struct omap_plane { | |||
54 | uint32_t nformats; | 56 | uint32_t nformats; |
55 | uint32_t formats[32]; | 57 | uint32_t formats[32]; |
56 | 58 | ||
57 | /* for synchronizing access to unpins fifo */ | 59 | struct omap_drm_irq error_irq; |
58 | struct mutex unpin_mutex; | ||
59 | 60 | ||
60 | /* set of bo's pending unpin until next END_WIN irq */ | 61 | /* set of bo's pending unpin until next post_apply() */ |
61 | DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *); | 62 | DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *); |
62 | int num_unpins, pending_num_unpins; | ||
63 | |||
64 | /* for deferred unpin when we need to wait for scanout complete irq */ | ||
65 | struct work_struct work; | ||
66 | |||
67 | /* callback on next endwin irq */ | ||
68 | struct callback endwin; | ||
69 | }; | ||
70 | 63 | ||
71 | /* map from ovl->id to the irq we are interested in for scanout-done */ | 64 | // XXX maybe get rid of this and handle vblank in crtc too? |
72 | static const uint32_t id2irq[] = { | 65 | struct callback apply_done_cb; |
73 | [OMAP_DSS_GFX] = DISPC_IRQ_GFX_END_WIN, | ||
74 | [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_END_WIN, | ||
75 | [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_END_WIN, | ||
76 | [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_END_WIN, | ||
77 | }; | 66 | }; |
78 | 67 | ||
79 | static void dispc_isr(void *arg, uint32_t mask) | ||
80 | { | ||
81 | struct drm_plane *plane = arg; | ||
82 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
83 | struct omap_drm_private *priv = plane->dev->dev_private; | ||
84 | |||
85 | omap_dispc_unregister_isr(dispc_isr, plane, | ||
86 | id2irq[omap_plane->ovl->id]); | ||
87 | |||
88 | queue_work(priv->wq, &omap_plane->work); | ||
89 | } | ||
90 | |||
91 | static void unpin_worker(struct work_struct *work) | ||
92 | { | ||
93 | struct omap_plane *omap_plane = | ||
94 | container_of(work, struct omap_plane, work); | ||
95 | struct callback endwin; | ||
96 | |||
97 | mutex_lock(&omap_plane->unpin_mutex); | ||
98 | DBG("unpinning %d of %d", omap_plane->num_unpins, | ||
99 | omap_plane->num_unpins + omap_plane->pending_num_unpins); | ||
100 | while (omap_plane->num_unpins > 0) { | ||
101 | struct drm_gem_object *bo = NULL; | ||
102 | int ret = kfifo_get(&omap_plane->unpin_fifo, &bo); | ||
103 | WARN_ON(!ret); | ||
104 | omap_gem_put_paddr(bo); | ||
105 | drm_gem_object_unreference_unlocked(bo); | ||
106 | omap_plane->num_unpins--; | ||
107 | } | ||
108 | endwin = omap_plane->endwin; | ||
109 | omap_plane->endwin.fxn = NULL; | ||
110 | mutex_unlock(&omap_plane->unpin_mutex); | ||
111 | |||
112 | if (endwin.fxn) | ||
113 | endwin.fxn(endwin.arg); | ||
114 | } | ||
115 | |||
116 | static void install_irq(struct drm_plane *plane) | ||
117 | { | ||
118 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
119 | struct omap_overlay *ovl = omap_plane->ovl; | ||
120 | int ret; | ||
121 | |||
122 | ret = omap_dispc_register_isr(dispc_isr, plane, id2irq[ovl->id]); | ||
123 | |||
124 | /* | ||
125 | * omapdss has upper limit on # of registered irq handlers, | ||
126 | * which we shouldn't hit.. but if we do the limit should | ||
127 | * be raised or bad things happen: | ||
128 | */ | ||
129 | WARN_ON(ret == -EBUSY); | ||
130 | } | ||
131 | |||
132 | /* push changes down to dss2 */ | ||
133 | static int commit(struct drm_plane *plane) | ||
134 | { | ||
135 | struct drm_device *dev = plane->dev; | ||
136 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
137 | struct omap_overlay *ovl = omap_plane->ovl; | ||
138 | struct omap_overlay_info *info = &omap_plane->info; | ||
139 | int ret; | ||
140 | |||
141 | DBG("%s", ovl->name); | ||
142 | DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width, | ||
143 | info->out_height, info->screen_width); | ||
144 | DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, | ||
145 | info->paddr, info->p_uv_addr); | ||
146 | |||
147 | /* NOTE: do we want to do this at all here, or just wait | ||
148 | * for dpms(ON) since other CRTC's may not have their mode | ||
149 | * set yet, so fb dimensions may still change.. | ||
150 | */ | ||
151 | ret = ovl->set_overlay_info(ovl, info); | ||
152 | if (ret) { | ||
153 | dev_err(dev->dev, "could not set overlay info\n"); | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | mutex_lock(&omap_plane->unpin_mutex); | ||
158 | omap_plane->num_unpins += omap_plane->pending_num_unpins; | ||
159 | omap_plane->pending_num_unpins = 0; | ||
160 | mutex_unlock(&omap_plane->unpin_mutex); | ||
161 | |||
162 | /* our encoder doesn't necessarily get a commit() after this, in | ||
163 | * particular in the dpms() and mode_set_base() cases, so force the | ||
164 | * manager to update: | ||
165 | * | ||
166 | * could this be in the encoder somehow? | ||
167 | */ | ||
168 | if (ovl->manager) { | ||
169 | ret = ovl->manager->apply(ovl->manager); | ||
170 | if (ret) { | ||
171 | dev_err(dev->dev, "could not apply settings\n"); | ||
172 | return ret; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * NOTE: really this should be atomic w/ mgr->apply() but | ||
177 | * omapdss does not expose such an API | ||
178 | */ | ||
179 | if (omap_plane->num_unpins > 0) | ||
180 | install_irq(plane); | ||
181 | |||
182 | } else { | ||
183 | struct omap_drm_private *priv = dev->dev_private; | ||
184 | queue_work(priv->wq, &omap_plane->work); | ||
185 | } | ||
186 | |||
187 | |||
188 | if (ovl->is_enabled(ovl)) { | ||
189 | omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, | ||
190 | info->out_width, info->out_height); | ||
191 | } | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | /* when CRTC that we are attached to has potentially changed, this checks | ||
197 | * if we are attached to proper manager, and if necessary updates. | ||
198 | */ | ||
199 | static void update_manager(struct drm_plane *plane) | ||
200 | { | ||
201 | struct omap_drm_private *priv = plane->dev->dev_private; | ||
202 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
203 | struct omap_overlay *ovl = omap_plane->ovl; | ||
204 | struct omap_overlay_manager *mgr = NULL; | ||
205 | int i; | ||
206 | |||
207 | if (plane->crtc) { | ||
208 | for (i = 0; i < priv->num_encoders; i++) { | ||
209 | struct drm_encoder *encoder = priv->encoders[i]; | ||
210 | if (encoder->crtc == plane->crtc) { | ||
211 | mgr = omap_encoder_get_manager(encoder); | ||
212 | break; | ||
213 | } | ||
214 | } | ||
215 | } | ||
216 | |||
217 | if (ovl->manager != mgr) { | ||
218 | bool enabled = ovl->is_enabled(ovl); | ||
219 | |||
220 | /* don't switch things around with enabled overlays: */ | ||
221 | if (enabled) | ||
222 | omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); | ||
223 | |||
224 | if (ovl->manager) { | ||
225 | DBG("disconnecting %s from %s", ovl->name, | ||
226 | ovl->manager->name); | ||
227 | ovl->unset_manager(ovl); | ||
228 | } | ||
229 | |||
230 | if (mgr) { | ||
231 | DBG("connecting %s to %s", ovl->name, mgr->name); | ||
232 | ovl->set_manager(ovl, mgr); | ||
233 | } | ||
234 | |||
235 | if (enabled && mgr) | ||
236 | omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | ||
237 | } | ||
238 | } | ||
239 | |||
240 | static void unpin(void *arg, struct drm_gem_object *bo) | 68 | static void unpin(void *arg, struct drm_gem_object *bo) |
241 | { | 69 | { |
242 | struct drm_plane *plane = arg; | 70 | struct drm_plane *plane = arg; |
@@ -244,7 +72,6 @@ static void unpin(void *arg, struct drm_gem_object *bo) | |||
244 | 72 | ||
245 | if (kfifo_put(&omap_plane->unpin_fifo, | 73 | if (kfifo_put(&omap_plane->unpin_fifo, |
246 | (const struct drm_gem_object **)&bo)) { | 74 | (const struct drm_gem_object **)&bo)) { |
247 | omap_plane->pending_num_unpins++; | ||
248 | /* also hold a ref so it isn't free'd while pinned */ | 75 | /* also hold a ref so it isn't free'd while pinned */ |
249 | drm_gem_object_reference(bo); | 76 | drm_gem_object_reference(bo); |
250 | } else { | 77 | } else { |
@@ -264,13 +91,19 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) | |||
264 | 91 | ||
265 | DBG("%p -> %p", pinned_fb, fb); | 92 | DBG("%p -> %p", pinned_fb, fb); |
266 | 93 | ||
267 | mutex_lock(&omap_plane->unpin_mutex); | 94 | if (fb) |
95 | drm_framebuffer_reference(fb); | ||
96 | |||
268 | ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin); | 97 | ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin); |
269 | mutex_unlock(&omap_plane->unpin_mutex); | 98 | |
99 | if (pinned_fb) | ||
100 | drm_framebuffer_unreference(pinned_fb); | ||
270 | 101 | ||
271 | if (ret) { | 102 | if (ret) { |
272 | dev_err(plane->dev->dev, "could not swap %p -> %p\n", | 103 | dev_err(plane->dev->dev, "could not swap %p -> %p\n", |
273 | omap_plane->pinned_fb, fb); | 104 | omap_plane->pinned_fb, fb); |
105 | if (fb) | ||
106 | drm_framebuffer_unreference(fb); | ||
274 | omap_plane->pinned_fb = NULL; | 107 | omap_plane->pinned_fb = NULL; |
275 | return ret; | 108 | return ret; |
276 | } | 109 | } |
@@ -281,31 +114,90 @@ static int update_pin(struct drm_plane *plane, struct drm_framebuffer *fb) | |||
281 | return 0; | 114 | return 0; |
282 | } | 115 | } |
283 | 116 | ||
284 | /* update parameters that are dependent on the framebuffer dimensions and | 117 | static void omap_plane_pre_apply(struct omap_drm_apply *apply) |
285 | * position within the fb that this plane scans out from. This is called | ||
286 | * when framebuffer or x,y base may have changed. | ||
287 | */ | ||
288 | static void update_scanout(struct drm_plane *plane) | ||
289 | { | 118 | { |
290 | struct omap_plane *omap_plane = to_omap_plane(plane); | 119 | struct omap_plane *omap_plane = |
291 | struct omap_overlay_info *info = &omap_plane->info; | 120 | container_of(apply, struct omap_plane, apply); |
292 | struct omap_drm_window *win = &omap_plane->win; | 121 | struct omap_drm_window *win = &omap_plane->win; |
122 | struct drm_plane *plane = &omap_plane->base; | ||
123 | struct drm_device *dev = plane->dev; | ||
124 | struct omap_overlay_info *info = &omap_plane->info; | ||
125 | struct drm_crtc *crtc = plane->crtc; | ||
126 | enum omap_channel channel; | ||
127 | bool enabled = omap_plane->enabled && crtc; | ||
128 | bool ilace, replication; | ||
293 | int ret; | 129 | int ret; |
294 | 130 | ||
295 | ret = update_pin(plane, plane->fb); | 131 | DBG("%s, enabled=%d", omap_plane->name, enabled); |
296 | if (ret) { | 132 | |
297 | dev_err(plane->dev->dev, | 133 | /* if fb has changed, pin new fb: */ |
298 | "could not pin fb: %d\n", ret); | 134 | update_pin(plane, enabled ? plane->fb : NULL); |
299 | omap_plane_dpms(plane, DRM_MODE_DPMS_OFF); | 135 | |
136 | if (!enabled) { | ||
137 | dispc_ovl_enable(omap_plane->id, false); | ||
300 | return; | 138 | return; |
301 | } | 139 | } |
302 | 140 | ||
141 | channel = omap_crtc_channel(crtc); | ||
142 | |||
143 | /* update scanout: */ | ||
303 | omap_framebuffer_update_scanout(plane->fb, win, info); | 144 | omap_framebuffer_update_scanout(plane->fb, win, info); |
304 | 145 | ||
305 | DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name, | 146 | DBG("%dx%d -> %dx%d (%d)", info->width, info->height, |
306 | win->src_x, win->src_y, | 147 | info->out_width, info->out_height, |
307 | (u32)info->paddr, (u32)info->p_uv_addr, | ||
308 | info->screen_width); | 148 | info->screen_width); |
149 | DBG("%d,%d %08x %08x", info->pos_x, info->pos_y, | ||
150 | info->paddr, info->p_uv_addr); | ||
151 | |||
152 | /* TODO: */ | ||
153 | ilace = false; | ||
154 | replication = false; | ||
155 | |||
156 | /* and finally, update omapdss: */ | ||
157 | ret = dispc_ovl_setup(omap_plane->id, info, | ||
158 | replication, omap_crtc_timings(crtc), false); | ||
159 | if (ret) { | ||
160 | dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret); | ||
161 | return; | ||
162 | } | ||
163 | |||
164 | dispc_ovl_enable(omap_plane->id, true); | ||
165 | dispc_ovl_set_channel_out(omap_plane->id, channel); | ||
166 | } | ||
167 | |||
168 | static void omap_plane_post_apply(struct omap_drm_apply *apply) | ||
169 | { | ||
170 | struct omap_plane *omap_plane = | ||
171 | container_of(apply, struct omap_plane, apply); | ||
172 | struct drm_plane *plane = &omap_plane->base; | ||
173 | struct omap_overlay_info *info = &omap_plane->info; | ||
174 | struct drm_gem_object *bo = NULL; | ||
175 | struct callback cb; | ||
176 | |||
177 | cb = omap_plane->apply_done_cb; | ||
178 | omap_plane->apply_done_cb.fxn = NULL; | ||
179 | |||
180 | while (kfifo_get(&omap_plane->unpin_fifo, &bo)) { | ||
181 | omap_gem_put_paddr(bo); | ||
182 | drm_gem_object_unreference_unlocked(bo); | ||
183 | } | ||
184 | |||
185 | if (cb.fxn) | ||
186 | cb.fxn(cb.arg); | ||
187 | |||
188 | if (omap_plane->enabled) { | ||
189 | omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y, | ||
190 | info->out_width, info->out_height); | ||
191 | } | ||
192 | } | ||
193 | |||
194 | static int apply(struct drm_plane *plane) | ||
195 | { | ||
196 | if (plane->crtc) { | ||
197 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
198 | return omap_crtc_apply(plane->crtc, &omap_plane->apply); | ||
199 | } | ||
200 | return 0; | ||
309 | } | 201 | } |
310 | 202 | ||
311 | int omap_plane_mode_set(struct drm_plane *plane, | 203 | int omap_plane_mode_set(struct drm_plane *plane, |
@@ -313,7 +205,8 @@ int omap_plane_mode_set(struct drm_plane *plane, | |||
313 | int crtc_x, int crtc_y, | 205 | int crtc_x, int crtc_y, |
314 | unsigned int crtc_w, unsigned int crtc_h, | 206 | unsigned int crtc_w, unsigned int crtc_h, |
315 | uint32_t src_x, uint32_t src_y, | 207 | uint32_t src_x, uint32_t src_y, |
316 | uint32_t src_w, uint32_t src_h) | 208 | uint32_t src_w, uint32_t src_h, |
209 | void (*fxn)(void *), void *arg) | ||
317 | { | 210 | { |
318 | struct omap_plane *omap_plane = to_omap_plane(plane); | 211 | struct omap_plane *omap_plane = to_omap_plane(plane); |
319 | struct omap_drm_window *win = &omap_plane->win; | 212 | struct omap_drm_window *win = &omap_plane->win; |
@@ -329,17 +222,20 @@ int omap_plane_mode_set(struct drm_plane *plane, | |||
329 | win->src_w = src_w >> 16; | 222 | win->src_w = src_w >> 16; |
330 | win->src_h = src_h >> 16; | 223 | win->src_h = src_h >> 16; |
331 | 224 | ||
332 | /* note: this is done after this fxn returns.. but if we need | 225 | if (fxn) { |
333 | * to do a commit/update_scanout, etc before this returns we | 226 | /* omap_crtc should ensure that a new page flip |
334 | * need the current value. | 227 | * isn't permitted while there is one pending: |
335 | */ | 228 | */ |
229 | BUG_ON(omap_plane->apply_done_cb.fxn); | ||
230 | |||
231 | omap_plane->apply_done_cb.fxn = fxn; | ||
232 | omap_plane->apply_done_cb.arg = arg; | ||
233 | } | ||
234 | |||
336 | plane->fb = fb; | 235 | plane->fb = fb; |
337 | plane->crtc = crtc; | 236 | plane->crtc = crtc; |
338 | 237 | ||
339 | update_scanout(plane); | 238 | return apply(plane); |
340 | update_manager(plane); | ||
341 | |||
342 | return 0; | ||
343 | } | 239 | } |
344 | 240 | ||
345 | static int omap_plane_update(struct drm_plane *plane, | 241 | static int omap_plane_update(struct drm_plane *plane, |
@@ -349,9 +245,12 @@ static int omap_plane_update(struct drm_plane *plane, | |||
349 | uint32_t src_x, uint32_t src_y, | 245 | uint32_t src_x, uint32_t src_y, |
350 | uint32_t src_w, uint32_t src_h) | 246 | uint32_t src_w, uint32_t src_h) |
351 | { | 247 | { |
352 | omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h, | 248 | struct omap_plane *omap_plane = to_omap_plane(plane); |
353 | src_x, src_y, src_w, src_h); | 249 | omap_plane->enabled = true; |
354 | return omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | 250 | return omap_plane_mode_set(plane, crtc, fb, |
251 | crtc_x, crtc_y, crtc_w, crtc_h, | ||
252 | src_x, src_y, src_w, src_h, | ||
253 | NULL, NULL); | ||
355 | } | 254 | } |
356 | 255 | ||
357 | static int omap_plane_disable(struct drm_plane *plane) | 256 | static int omap_plane_disable(struct drm_plane *plane) |
@@ -364,48 +263,32 @@ static int omap_plane_disable(struct drm_plane *plane) | |||
364 | static void omap_plane_destroy(struct drm_plane *plane) | 263 | static void omap_plane_destroy(struct drm_plane *plane) |
365 | { | 264 | { |
366 | struct omap_plane *omap_plane = to_omap_plane(plane); | 265 | struct omap_plane *omap_plane = to_omap_plane(plane); |
367 | DBG("%s", omap_plane->ovl->name); | 266 | |
267 | DBG("%s", omap_plane->name); | ||
268 | |||
269 | omap_irq_unregister(plane->dev, &omap_plane->error_irq); | ||
270 | |||
368 | omap_plane_disable(plane); | 271 | omap_plane_disable(plane); |
369 | drm_plane_cleanup(plane); | 272 | drm_plane_cleanup(plane); |
370 | WARN_ON(omap_plane->pending_num_unpins + omap_plane->num_unpins > 0); | 273 | |
274 | WARN_ON(!kfifo_is_empty(&omap_plane->unpin_fifo)); | ||
371 | kfifo_free(&omap_plane->unpin_fifo); | 275 | kfifo_free(&omap_plane->unpin_fifo); |
276 | |||
372 | kfree(omap_plane); | 277 | kfree(omap_plane); |
373 | } | 278 | } |
374 | 279 | ||
375 | int omap_plane_dpms(struct drm_plane *plane, int mode) | 280 | int omap_plane_dpms(struct drm_plane *plane, int mode) |
376 | { | 281 | { |
377 | struct omap_plane *omap_plane = to_omap_plane(plane); | 282 | struct omap_plane *omap_plane = to_omap_plane(plane); |
378 | struct omap_overlay *ovl = omap_plane->ovl; | 283 | bool enabled = (mode == DRM_MODE_DPMS_ON); |
379 | int r; | 284 | int ret = 0; |
380 | 285 | ||
381 | DBG("%s: %d", omap_plane->ovl->name, mode); | 286 | if (enabled != omap_plane->enabled) { |
382 | 287 | omap_plane->enabled = enabled; | |
383 | if (mode == DRM_MODE_DPMS_ON) { | 288 | ret = apply(plane); |
384 | update_scanout(plane); | ||
385 | r = commit(plane); | ||
386 | if (!r) | ||
387 | r = ovl->enable(ovl); | ||
388 | } else { | ||
389 | struct omap_drm_private *priv = plane->dev->dev_private; | ||
390 | r = ovl->disable(ovl); | ||
391 | update_pin(plane, NULL); | ||
392 | queue_work(priv->wq, &omap_plane->work); | ||
393 | } | 289 | } |
394 | 290 | ||
395 | return r; | 291 | return ret; |
396 | } | ||
397 | |||
398 | void omap_plane_on_endwin(struct drm_plane *plane, | ||
399 | void (*fxn)(void *), void *arg) | ||
400 | { | ||
401 | struct omap_plane *omap_plane = to_omap_plane(plane); | ||
402 | |||
403 | mutex_lock(&omap_plane->unpin_mutex); | ||
404 | omap_plane->endwin.fxn = fxn; | ||
405 | omap_plane->endwin.arg = arg; | ||
406 | mutex_unlock(&omap_plane->unpin_mutex); | ||
407 | |||
408 | install_irq(plane); | ||
409 | } | 292 | } |
410 | 293 | ||
411 | /* helper to install properties which are common to planes and crtcs */ | 294 | /* helper to install properties which are common to planes and crtcs */ |
@@ -454,25 +337,13 @@ int omap_plane_set_property(struct drm_plane *plane, | |||
454 | int ret = -EINVAL; | 337 | int ret = -EINVAL; |
455 | 338 | ||
456 | if (property == priv->rotation_prop) { | 339 | if (property == priv->rotation_prop) { |
457 | struct omap_overlay *ovl = omap_plane->ovl; | 340 | DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val); |
458 | |||
459 | DBG("%s: rotation: %02x", ovl->name, (uint32_t)val); | ||
460 | omap_plane->win.rotation = val; | 341 | omap_plane->win.rotation = val; |
461 | 342 | ret = apply(plane); | |
462 | if (ovl->is_enabled(ovl)) | ||
463 | ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | ||
464 | else | ||
465 | ret = 0; | ||
466 | } else if (property == priv->zorder_prop) { | 343 | } else if (property == priv->zorder_prop) { |
467 | struct omap_overlay *ovl = omap_plane->ovl; | 344 | DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val); |
468 | |||
469 | DBG("%s: zorder: %d", ovl->name, (uint32_t)val); | ||
470 | omap_plane->info.zorder = val; | 345 | omap_plane->info.zorder = val; |
471 | 346 | ret = apply(plane); | |
472 | if (ovl->is_enabled(ovl)) | ||
473 | ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON); | ||
474 | else | ||
475 | ret = 0; | ||
476 | } | 347 | } |
477 | 348 | ||
478 | return ret; | 349 | return ret; |
@@ -485,20 +356,38 @@ static const struct drm_plane_funcs omap_plane_funcs = { | |||
485 | .set_property = omap_plane_set_property, | 356 | .set_property = omap_plane_set_property, |
486 | }; | 357 | }; |
487 | 358 | ||
359 | static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus) | ||
360 | { | ||
361 | struct omap_plane *omap_plane = | ||
362 | container_of(irq, struct omap_plane, error_irq); | ||
363 | DRM_ERROR("%s: errors: %08x\n", omap_plane->name, irqstatus); | ||
364 | } | ||
365 | |||
366 | static const char *plane_names[] = { | ||
367 | [OMAP_DSS_GFX] = "gfx", | ||
368 | [OMAP_DSS_VIDEO1] = "vid1", | ||
369 | [OMAP_DSS_VIDEO2] = "vid2", | ||
370 | [OMAP_DSS_VIDEO3] = "vid3", | ||
371 | }; | ||
372 | |||
373 | static const uint32_t error_irqs[] = { | ||
374 | [OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW, | ||
375 | [OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW, | ||
376 | [OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW, | ||
377 | [OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW, | ||
378 | }; | ||
379 | |||
488 | /* initialize plane */ | 380 | /* initialize plane */ |
489 | struct drm_plane *omap_plane_init(struct drm_device *dev, | 381 | struct drm_plane *omap_plane_init(struct drm_device *dev, |
490 | struct omap_overlay *ovl, unsigned int possible_crtcs, | 382 | int id, bool private_plane) |
491 | bool priv) | ||
492 | { | 383 | { |
384 | struct omap_drm_private *priv = dev->dev_private; | ||
493 | struct drm_plane *plane = NULL; | 385 | struct drm_plane *plane = NULL; |
494 | struct omap_plane *omap_plane; | 386 | struct omap_plane *omap_plane; |
387 | struct omap_overlay_info *info; | ||
495 | int ret; | 388 | int ret; |
496 | 389 | ||
497 | DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name, | 390 | DBG("%s: priv=%d", plane_names[id], private_plane); |
498 | possible_crtcs, priv); | ||
499 | |||
500 | /* friendly reminder to update table for future hw: */ | ||
501 | WARN_ON(ovl->id >= ARRAY_SIZE(id2irq)); | ||
502 | 391 | ||
503 | omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); | 392 | omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); |
504 | if (!omap_plane) { | 393 | if (!omap_plane) { |
@@ -506,47 +395,50 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, | |||
506 | goto fail; | 395 | goto fail; |
507 | } | 396 | } |
508 | 397 | ||
509 | mutex_init(&omap_plane->unpin_mutex); | ||
510 | |||
511 | ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL); | 398 | ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL); |
512 | if (ret) { | 399 | if (ret) { |
513 | dev_err(dev->dev, "could not allocate unpin FIFO\n"); | 400 | dev_err(dev->dev, "could not allocate unpin FIFO\n"); |
514 | goto fail; | 401 | goto fail; |
515 | } | 402 | } |
516 | 403 | ||
517 | INIT_WORK(&omap_plane->work, unpin_worker); | ||
518 | |||
519 | omap_plane->nformats = omap_framebuffer_get_formats( | 404 | omap_plane->nformats = omap_framebuffer_get_formats( |
520 | omap_plane->formats, ARRAY_SIZE(omap_plane->formats), | 405 | omap_plane->formats, ARRAY_SIZE(omap_plane->formats), |
521 | ovl->supported_modes); | 406 | dss_feat_get_supported_color_modes(id)); |
522 | omap_plane->ovl = ovl; | 407 | omap_plane->id = id; |
408 | omap_plane->name = plane_names[id]; | ||
409 | |||
523 | plane = &omap_plane->base; | 410 | plane = &omap_plane->base; |
524 | 411 | ||
525 | drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs, | 412 | omap_plane->apply.pre_apply = omap_plane_pre_apply; |
526 | omap_plane->formats, omap_plane->nformats, priv); | 413 | omap_plane->apply.post_apply = omap_plane_post_apply; |
414 | |||
415 | omap_plane->error_irq.irqmask = error_irqs[id]; | ||
416 | omap_plane->error_irq.irq = omap_plane_error_irq; | ||
417 | omap_irq_register(dev, &omap_plane->error_irq); | ||
418 | |||
419 | drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs, | ||
420 | omap_plane->formats, omap_plane->nformats, private_plane); | ||
527 | 421 | ||
528 | omap_plane_install_properties(plane, &plane->base); | 422 | omap_plane_install_properties(plane, &plane->base); |
529 | 423 | ||
530 | /* get our starting configuration, set defaults for parameters | 424 | /* get our starting configuration, set defaults for parameters |
531 | * we don't currently use, etc: | 425 | * we don't currently use, etc: |
532 | */ | 426 | */ |
533 | ovl->get_overlay_info(ovl, &omap_plane->info); | 427 | info = &omap_plane->info; |
534 | omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA; | 428 | info->rotation_type = OMAP_DSS_ROT_DMA; |
535 | omap_plane->info.rotation = OMAP_DSS_ROT_0; | 429 | info->rotation = OMAP_DSS_ROT_0; |
536 | omap_plane->info.global_alpha = 0xff; | 430 | info->global_alpha = 0xff; |
537 | omap_plane->info.mirror = 0; | 431 | info->mirror = 0; |
538 | 432 | ||
539 | /* Set defaults depending on whether we are a CRTC or overlay | 433 | /* Set defaults depending on whether we are a CRTC or overlay |
540 | * layer. | 434 | * layer. |
541 | * TODO add ioctl to give userspace an API to change this.. this | 435 | * TODO add ioctl to give userspace an API to change this.. this |
542 | * will come in a subsequent patch. | 436 | * will come in a subsequent patch. |
543 | */ | 437 | */ |
544 | if (priv) | 438 | if (private_plane) |
545 | omap_plane->info.zorder = 0; | 439 | omap_plane->info.zorder = 0; |
546 | else | 440 | else |
547 | omap_plane->info.zorder = ovl->id; | 441 | omap_plane->info.zorder = id; |
548 | |||
549 | update_manager(plane); | ||
550 | 442 | ||
551 | return plane; | 443 | return plane; |
552 | 444 | ||
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c index ae38475854b5..d10d75e8a33f 100644 --- a/drivers/staging/rtl8187se/r8180_core.c +++ b/drivers/staging/rtl8187se/r8180_core.c | |||
@@ -937,7 +937,8 @@ short alloc_rx_desc_ring(struct net_device *dev, u16 bufsize, int count) | |||
937 | 937 | ||
938 | dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8), | 938 | dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8), |
939 | PCI_DMA_FROMDEVICE); | 939 | PCI_DMA_FROMDEVICE); |
940 | 940 | if (pci_dma_mapping_error(pdev, dma_tmp)) | |
941 | return -1; | ||
941 | if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp, | 942 | if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp, |
942 | &(priv->rxbufferhead))) { | 943 | &(priv->rxbufferhead))) { |
943 | DMESGE("Unable to allocate mem RX buf"); | 944 | DMESGE("Unable to allocate mem RX buf"); |
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c index 808aab6fa5ef..a9d78e9651c6 100644 --- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c +++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c | |||
@@ -1183,6 +1183,8 @@ void rtl8192_tx_fill_desc(struct net_device *dev, struct tx_desc *pdesc, | |||
1183 | pTxFwInfo->TxRate, | 1183 | pTxFwInfo->TxRate, |
1184 | cb_desc); | 1184 | cb_desc); |
1185 | 1185 | ||
1186 | if (pci_dma_mapping_error(priv->pdev, mapping)) | ||
1187 | RT_TRACE(COMP_ERR, "DMA Mapping error\n");; | ||
1186 | if (cb_desc->bAMPDUEnable) { | 1188 | if (cb_desc->bAMPDUEnable) { |
1187 | pTxFwInfo->AllowAggregation = 1; | 1189 | pTxFwInfo->AllowAggregation = 1; |
1188 | pTxFwInfo->RxMF = cb_desc->ampdu_factor; | 1190 | pTxFwInfo->RxMF = cb_desc->ampdu_factor; |
@@ -1280,6 +1282,8 @@ void rtl8192_tx_fill_cmd_desc(struct net_device *dev, | |||
1280 | dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, | 1282 | dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len, |
1281 | PCI_DMA_TODEVICE); | 1283 | PCI_DMA_TODEVICE); |
1282 | 1284 | ||
1285 | if (pci_dma_mapping_error(priv->pdev, mapping)) | ||
1286 | RT_TRACE(COMP_ERR, "DMA Mapping error\n");; | ||
1283 | memset(entry, 0, 12); | 1287 | memset(entry, 0, 12); |
1284 | entry->LINIP = cb_desc->bLastIniPkt; | 1288 | entry->LINIP = cb_desc->bLastIniPkt; |
1285 | entry->FirstSeg = 1; | 1289 | entry->FirstSeg = 1; |
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c index 1a70f324552f..4ebf99b30975 100644 --- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c +++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c | |||
@@ -2104,7 +2104,10 @@ static short rtl8192_alloc_rx_desc_ring(struct net_device *dev) | |||
2104 | skb_tail_pointer_rsl(skb), | 2104 | skb_tail_pointer_rsl(skb), |
2105 | priv->rxbuffersize, | 2105 | priv->rxbuffersize, |
2106 | PCI_DMA_FROMDEVICE); | 2106 | PCI_DMA_FROMDEVICE); |
2107 | 2107 | if (pci_dma_mapping_error(priv->pdev, *mapping)) { | |
2108 | dev_kfree_skb_any(skb); | ||
2109 | return -1; | ||
2110 | } | ||
2108 | entry->BufferAddress = cpu_to_le32(*mapping); | 2111 | entry->BufferAddress = cpu_to_le32(*mapping); |
2109 | 2112 | ||
2110 | entry->Length = priv->rxbuffersize; | 2113 | entry->Length = priv->rxbuffersize; |
@@ -2397,7 +2400,11 @@ static void rtl8192_rx_normal(struct net_device *dev) | |||
2397 | skb_tail_pointer_rsl(skb), | 2400 | skb_tail_pointer_rsl(skb), |
2398 | priv->rxbuffersize, | 2401 | priv->rxbuffersize, |
2399 | PCI_DMA_FROMDEVICE); | 2402 | PCI_DMA_FROMDEVICE); |
2400 | 2403 | if (pci_dma_mapping_error(priv->pdev, | |
2404 | *((dma_addr_t *)skb->cb))) { | ||
2405 | dev_kfree_skb_any(skb); | ||
2406 | return; | ||
2407 | } | ||
2401 | } | 2408 | } |
2402 | done: | 2409 | done: |
2403 | pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); | 2410 | pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb)); |
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c index 6b73843e580a..a96cd06d69dd 100644 --- a/drivers/staging/rtl8712/usb_intf.c +++ b/drivers/staging/rtl8712/usb_intf.c | |||
@@ -63,6 +63,8 @@ static struct usb_device_id rtl871x_usb_id_tbl[] = { | |||
63 | {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ | 63 | {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */ |
64 | /* Belkin */ | 64 | /* Belkin */ |
65 | {USB_DEVICE(0x050D, 0x945A)}, | 65 | {USB_DEVICE(0x050D, 0x945A)}, |
66 | /* ISY IWL - Belkin clone */ | ||
67 | {USB_DEVICE(0x050D, 0x11F1)}, | ||
66 | /* Corega */ | 68 | /* Corega */ |
67 | {USB_DEVICE(0x07AA, 0x0047)}, | 69 | {USB_DEVICE(0x07AA, 0x0047)}, |
68 | /* D-Link */ | 70 | /* D-Link */ |
diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig index ac87c5e38dee..1facad625554 100644 --- a/drivers/staging/sb105x/Kconfig +++ b/drivers/staging/sb105x/Kconfig | |||
@@ -2,6 +2,7 @@ config SB105X | |||
2 | tristate "SystemBase PCI Multiport UART" | 2 | tristate "SystemBase PCI Multiport UART" |
3 | select SERIAL_CORE | 3 | select SERIAL_CORE |
4 | depends on PCI | 4 | depends on PCI |
5 | depends on X86 | ||
5 | help | 6 | help |
6 | A driver for the SystemBase Multi-2/PCI serial card | 7 | A driver for the SystemBase Multi-2/PCI serial card |
7 | 8 | ||
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c index edb2a85b9d52..9464f3874346 100644 --- a/drivers/staging/sb105x/sb_pci_mp.c +++ b/drivers/staging/sb105x/sb_pci_mp.c | |||
@@ -3054,6 +3054,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd) | |||
3054 | sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16); | 3054 | sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16); |
3055 | } | 3055 | } |
3056 | break; | 3056 | break; |
3057 | #ifdef CONFIG_PARPORT_PC | ||
3057 | case PCI_DEVICE_ID_MP2S1P : | 3058 | case PCI_DEVICE_ID_MP2S1P : |
3058 | sbdev->nr_ports = 2; | 3059 | sbdev->nr_ports = 2; |
3059 | 3060 | ||
@@ -3073,6 +3074,7 @@ static int init_mp_dev(struct pci_dev *pcidev, mppcibrd_t brd) | |||
3073 | /* add PC compatible parallel port */ | 3074 | /* add PC compatible parallel port */ |
3074 | parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0); | 3075 | parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0); |
3075 | break; | 3076 | break; |
3077 | #endif | ||
3076 | } | 3078 | } |
3077 | 3079 | ||
3078 | ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name); | 3080 | ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name); |
diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c index df9533798095..7616f058a00b 100644 --- a/drivers/staging/speakup/synth.c +++ b/drivers/staging/speakup/synth.c | |||
@@ -342,7 +342,7 @@ int synth_init(char *synth_name) | |||
342 | 342 | ||
343 | mutex_lock(&spk_mutex); | 343 | mutex_lock(&spk_mutex); |
344 | /* First, check if we already have it loaded. */ | 344 | /* First, check if we already have it loaded. */ |
345 | for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) | 345 | for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) |
346 | if (strcmp(synths[i]->name, synth_name) == 0) | 346 | if (strcmp(synths[i]->name, synth_name) == 0) |
347 | synth = synths[i]; | 347 | synth = synths[i]; |
348 | 348 | ||
@@ -423,7 +423,7 @@ int synth_add(struct spk_synth *in_synth) | |||
423 | int i; | 423 | int i; |
424 | int status = 0; | 424 | int status = 0; |
425 | mutex_lock(&spk_mutex); | 425 | mutex_lock(&spk_mutex); |
426 | for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++) | 426 | for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++) |
427 | /* synth_remove() is responsible for rotating the array down */ | 427 | /* synth_remove() is responsible for rotating the array down */ |
428 | if (in_synth == synths[i]) { | 428 | if (in_synth == synths[i]) { |
429 | mutex_unlock(&spk_mutex); | 429 | mutex_unlock(&spk_mutex); |
diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h index 543a127c7d4d..b783bfa59b1c 100644 --- a/drivers/staging/tidspbridge/core/_tiomap.h +++ b/drivers/staging/tidspbridge/core/_tiomap.h | |||
@@ -31,7 +31,7 @@ | |||
31 | * driver should read or write to PRM/CM registers directly; they | 31 | * driver should read or write to PRM/CM registers directly; they |
32 | * should rely on OMAP core code to do this. | 32 | * should rely on OMAP core code to do this. |
33 | */ | 33 | */ |
34 | #include <mach-omap2/cm2xxx_3xxx.h> | 34 | #include <mach-omap2/cm3xxx.h> |
35 | #include <mach-omap2/prm-regbits-34xx.h> | 35 | #include <mach-omap2/prm-regbits-34xx.h> |
36 | #include <mach-omap2/cm-regbits-34xx.h> | 36 | #include <mach-omap2/cm-regbits-34xx.h> |
37 | #include <dspbridge/devdefs.h> | 37 | #include <dspbridge/devdefs.h> |
diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c index b647207928b1..2f084e181d39 100644 --- a/drivers/staging/tidspbridge/core/dsp-clock.c +++ b/drivers/staging/tidspbridge/core/dsp-clock.c | |||
@@ -121,9 +121,13 @@ void dsp_clk_exit(void) | |||
121 | for (i = 0; i < DM_TIMER_CLOCKS; i++) | 121 | for (i = 0; i < DM_TIMER_CLOCKS; i++) |
122 | omap_dm_timer_free(timer[i]); | 122 | omap_dm_timer_free(timer[i]); |
123 | 123 | ||
124 | clk_unprepare(iva2_clk); | ||
124 | clk_put(iva2_clk); | 125 | clk_put(iva2_clk); |
126 | clk_unprepare(ssi.sst_fck); | ||
125 | clk_put(ssi.sst_fck); | 127 | clk_put(ssi.sst_fck); |
128 | clk_unprepare(ssi.ssr_fck); | ||
126 | clk_put(ssi.ssr_fck); | 129 | clk_put(ssi.ssr_fck); |
130 | clk_unprepare(ssi.ick); | ||
127 | clk_put(ssi.ick); | 131 | clk_put(ssi.ick); |
128 | } | 132 | } |
129 | 133 | ||
@@ -145,14 +149,21 @@ void dsp_clk_init(void) | |||
145 | iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck"); | 149 | iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck"); |
146 | if (IS_ERR(iva2_clk)) | 150 | if (IS_ERR(iva2_clk)) |
147 | dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk); | 151 | dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk); |
152 | else | ||
153 | clk_prepare(iva2_clk); | ||
148 | 154 | ||
149 | ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck"); | 155 | ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck"); |
150 | ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck"); | 156 | ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck"); |
151 | ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick"); | 157 | ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick"); |
152 | 158 | ||
153 | if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) | 159 | if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) { |
154 | dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n", | 160 | dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n", |
155 | ssi.sst_fck, ssi.ssr_fck, ssi.ick); | 161 | ssi.sst_fck, ssi.ssr_fck, ssi.ick); |
162 | } else { | ||
163 | clk_prepare(ssi.sst_fck); | ||
164 | clk_prepare(ssi.ssr_fck); | ||
165 | clk_prepare(ssi.ick); | ||
166 | } | ||
156 | } | 167 | } |
157 | 168 | ||
158 | /** | 169 | /** |
diff --git a/drivers/staging/tidspbridge/core/wdt.c b/drivers/staging/tidspbridge/core/wdt.c index 1dce36fb828f..7ff0e6c98039 100644 --- a/drivers/staging/tidspbridge/core/wdt.c +++ b/drivers/staging/tidspbridge/core/wdt.c | |||
@@ -63,11 +63,15 @@ int dsp_wdt_init(void) | |||
63 | dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); | 63 | dsp_wdt.fclk = clk_get(NULL, "wdt3_fck"); |
64 | 64 | ||
65 | if (!IS_ERR(dsp_wdt.fclk)) { | 65 | if (!IS_ERR(dsp_wdt.fclk)) { |
66 | clk_prepare(dsp_wdt.fclk); | ||
67 | |||
66 | dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); | 68 | dsp_wdt.iclk = clk_get(NULL, "wdt3_ick"); |
67 | if (IS_ERR(dsp_wdt.iclk)) { | 69 | if (IS_ERR(dsp_wdt.iclk)) { |
68 | clk_put(dsp_wdt.fclk); | 70 | clk_put(dsp_wdt.fclk); |
69 | dsp_wdt.fclk = NULL; | 71 | dsp_wdt.fclk = NULL; |
70 | ret = -EFAULT; | 72 | ret = -EFAULT; |
73 | } else { | ||
74 | clk_prepare(dsp_wdt.iclk); | ||
71 | } | 75 | } |
72 | } else | 76 | } else |
73 | ret = -EFAULT; | 77 | ret = -EFAULT; |
@@ -95,10 +99,14 @@ void dsp_wdt_exit(void) | |||
95 | free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt); | 99 | free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt); |
96 | tasklet_kill(&dsp_wdt.wdt3_tasklet); | 100 | tasklet_kill(&dsp_wdt.wdt3_tasklet); |
97 | 101 | ||
98 | if (dsp_wdt.fclk) | 102 | if (dsp_wdt.fclk) { |
103 | clk_unprepare(dsp_wdt.fclk); | ||
99 | clk_put(dsp_wdt.fclk); | 104 | clk_put(dsp_wdt.fclk); |
100 | if (dsp_wdt.iclk) | 105 | } |
106 | if (dsp_wdt.iclk) { | ||
107 | clk_unprepare(dsp_wdt.iclk); | ||
101 | clk_put(dsp_wdt.iclk); | 108 | clk_put(dsp_wdt.iclk); |
109 | } | ||
102 | 110 | ||
103 | dsp_wdt.fclk = NULL; | 111 | dsp_wdt.fclk = NULL; |
104 | dsp_wdt.iclk = NULL; | 112 | dsp_wdt.iclk = NULL; |
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c index 0331178ca3b3..bf73ba26e88a 100644 --- a/drivers/staging/vme/devices/vme_pio2_core.c +++ b/drivers/staging/vme/devices/vme_pio2_core.c | |||
@@ -162,11 +162,9 @@ static struct vme_driver pio2_driver = { | |||
162 | 162 | ||
163 | static int __init pio2_init(void) | 163 | static int __init pio2_init(void) |
164 | { | 164 | { |
165 | int retval = 0; | ||
166 | |||
167 | if (bus_num == 0) { | 165 | if (bus_num == 0) { |
168 | pr_err("No cards, skipping registration\n"); | 166 | pr_err("No cards, skipping registration\n"); |
169 | goto err_nocard; | 167 | return -ENODEV; |
170 | } | 168 | } |
171 | 169 | ||
172 | if (bus_num > PIO2_CARDS_MAX) { | 170 | if (bus_num > PIO2_CARDS_MAX) { |
@@ -176,15 +174,7 @@ static int __init pio2_init(void) | |||
176 | } | 174 | } |
177 | 175 | ||
178 | /* Register the PIO2 driver */ | 176 | /* Register the PIO2 driver */ |
179 | retval = vme_register_driver(&pio2_driver, bus_num); | 177 | return vme_register_driver(&pio2_driver, bus_num); |
180 | if (retval != 0) | ||
181 | goto err_reg; | ||
182 | |||
183 | return retval; | ||
184 | |||
185 | err_reg: | ||
186 | err_nocard: | ||
187 | return retval; | ||
188 | } | 178 | } |
189 | 179 | ||
190 | static int pio2_match(struct vme_dev *vdev) | 180 | static int pio2_match(struct vme_dev *vdev) |
diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h index 6b2ec390e775..806cbf72fb59 100644 --- a/drivers/staging/vt6656/bssdb.h +++ b/drivers/staging/vt6656/bssdb.h | |||
@@ -90,7 +90,6 @@ typedef struct tagSRSNCapObject { | |||
90 | } SRSNCapObject, *PSRSNCapObject; | 90 | } SRSNCapObject, *PSRSNCapObject; |
91 | 91 | ||
92 | // BSS info(AP) | 92 | // BSS info(AP) |
93 | #pragma pack(1) | ||
94 | typedef struct tagKnownBSS { | 93 | typedef struct tagKnownBSS { |
95 | // BSS info | 94 | // BSS info |
96 | BOOL bActive; | 95 | BOOL bActive; |
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h index 5d8faf9f96ec..e0d2b07ba608 100644 --- a/drivers/staging/vt6656/int.h +++ b/drivers/staging/vt6656/int.h | |||
@@ -34,7 +34,6 @@ | |||
34 | #include "device.h" | 34 | #include "device.h" |
35 | 35 | ||
36 | /*--------------------- Export Definitions -------------------------*/ | 36 | /*--------------------- Export Definitions -------------------------*/ |
37 | #pragma pack(1) | ||
38 | typedef struct tagSINTData { | 37 | typedef struct tagSINTData { |
39 | BYTE byTSR0; | 38 | BYTE byTSR0; |
40 | BYTE byPkt0; | 39 | BYTE byPkt0; |
diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h index 22710cef751d..ae6e2d237b20 100644 --- a/drivers/staging/vt6656/iocmd.h +++ b/drivers/staging/vt6656/iocmd.h | |||
@@ -95,13 +95,12 @@ typedef enum tagWZONETYPE { | |||
95 | // Ioctl interface structure | 95 | // Ioctl interface structure |
96 | // Command structure | 96 | // Command structure |
97 | // | 97 | // |
98 | #pragma pack(1) | ||
99 | typedef struct tagSCmdRequest { | 98 | typedef struct tagSCmdRequest { |
100 | u8 name[16]; | 99 | u8 name[16]; |
101 | void *data; | 100 | void *data; |
102 | u16 wResult; | 101 | u16 wResult; |
103 | u16 wCmdCode; | 102 | u16 wCmdCode; |
104 | } SCmdRequest, *PSCmdRequest; | 103 | } __packed SCmdRequest, *PSCmdRequest; |
105 | 104 | ||
106 | // | 105 | // |
107 | // Scan | 106 | // Scan |
@@ -111,7 +110,7 @@ typedef struct tagSCmdScan { | |||
111 | 110 | ||
112 | u8 ssid[SSID_MAXLEN + 2]; | 111 | u8 ssid[SSID_MAXLEN + 2]; |
113 | 112 | ||
114 | } SCmdScan, *PSCmdScan; | 113 | } __packed SCmdScan, *PSCmdScan; |
115 | 114 | ||
116 | // | 115 | // |
117 | // BSS Join | 116 | // BSS Join |
@@ -126,7 +125,7 @@ typedef struct tagSCmdBSSJoin { | |||
126 | BOOL bPSEnable; | 125 | BOOL bPSEnable; |
127 | BOOL bShareKeyAuth; | 126 | BOOL bShareKeyAuth; |
128 | 127 | ||
129 | } SCmdBSSJoin, *PSCmdBSSJoin; | 128 | } __packed SCmdBSSJoin, *PSCmdBSSJoin; |
130 | 129 | ||
131 | // | 130 | // |
132 | // Zonetype Setting | 131 | // Zonetype Setting |
@@ -137,7 +136,7 @@ typedef struct tagSCmdZoneTypeSet { | |||
137 | BOOL bWrite; | 136 | BOOL bWrite; |
138 | WZONETYPE ZoneType; | 137 | WZONETYPE ZoneType; |
139 | 138 | ||
140 | } SCmdZoneTypeSet, *PSCmdZoneTypeSet; | 139 | } __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet; |
141 | 140 | ||
142 | typedef struct tagSWPAResult { | 141 | typedef struct tagSWPAResult { |
143 | char ifname[100]; | 142 | char ifname[100]; |
@@ -145,7 +144,7 @@ typedef struct tagSWPAResult { | |||
145 | u8 key_mgmt; | 144 | u8 key_mgmt; |
146 | u8 eap_type; | 145 | u8 eap_type; |
147 | BOOL authenticated; | 146 | BOOL authenticated; |
148 | } SWPAResult, *PSWPAResult; | 147 | } __packed SWPAResult, *PSWPAResult; |
149 | 148 | ||
150 | typedef struct tagSCmdStartAP { | 149 | typedef struct tagSCmdStartAP { |
151 | 150 | ||
@@ -157,7 +156,7 @@ typedef struct tagSCmdStartAP { | |||
157 | BOOL bShareKeyAuth; | 156 | BOOL bShareKeyAuth; |
158 | u8 byBasicRate; | 157 | u8 byBasicRate; |
159 | 158 | ||
160 | } SCmdStartAP, *PSCmdStartAP; | 159 | } __packed SCmdStartAP, *PSCmdStartAP; |
161 | 160 | ||
162 | typedef struct tagSCmdSetWEP { | 161 | typedef struct tagSCmdSetWEP { |
163 | 162 | ||
@@ -167,7 +166,7 @@ typedef struct tagSCmdSetWEP { | |||
167 | BOOL bWepKeyAvailable[WEP_NKEYS]; | 166 | BOOL bWepKeyAvailable[WEP_NKEYS]; |
168 | u32 auWepKeyLength[WEP_NKEYS]; | 167 | u32 auWepKeyLength[WEP_NKEYS]; |
169 | 168 | ||
170 | } SCmdSetWEP, *PSCmdSetWEP; | 169 | } __packed SCmdSetWEP, *PSCmdSetWEP; |
171 | 170 | ||
172 | typedef struct tagSBSSIDItem { | 171 | typedef struct tagSBSSIDItem { |
173 | 172 | ||
@@ -180,14 +179,14 @@ typedef struct tagSBSSIDItem { | |||
180 | BOOL bWEPOn; | 179 | BOOL bWEPOn; |
181 | u32 uRSSI; | 180 | u32 uRSSI; |
182 | 181 | ||
183 | } SBSSIDItem; | 182 | } __packed SBSSIDItem; |
184 | 183 | ||
185 | 184 | ||
186 | typedef struct tagSBSSIDList { | 185 | typedef struct tagSBSSIDList { |
187 | 186 | ||
188 | u32 uItem; | 187 | u32 uItem; |
189 | SBSSIDItem sBSSIDList[0]; | 188 | SBSSIDItem sBSSIDList[0]; |
190 | } SBSSIDList, *PSBSSIDList; | 189 | } __packed SBSSIDList, *PSBSSIDList; |
191 | 190 | ||
192 | 191 | ||
193 | typedef struct tagSNodeItem { | 192 | typedef struct tagSNodeItem { |
@@ -208,7 +207,7 @@ typedef struct tagSNodeItem { | |||
208 | u32 uTxAttempts; | 207 | u32 uTxAttempts; |
209 | u16 wFailureRatio; | 208 | u16 wFailureRatio; |
210 | 209 | ||
211 | } SNodeItem; | 210 | } __packed SNodeItem; |
212 | 211 | ||
213 | 212 | ||
214 | typedef struct tagSNodeList { | 213 | typedef struct tagSNodeList { |
@@ -216,7 +215,7 @@ typedef struct tagSNodeList { | |||
216 | u32 uItem; | 215 | u32 uItem; |
217 | SNodeItem sNodeList[0]; | 216 | SNodeItem sNodeList[0]; |
218 | 217 | ||
219 | } SNodeList, *PSNodeList; | 218 | } __packed SNodeList, *PSNodeList; |
220 | 219 | ||
221 | 220 | ||
222 | typedef struct tagSCmdLinkStatus { | 221 | typedef struct tagSCmdLinkStatus { |
@@ -229,7 +228,7 @@ typedef struct tagSCmdLinkStatus { | |||
229 | u32 uChannel; | 228 | u32 uChannel; |
230 | u32 uLinkRate; | 229 | u32 uLinkRate; |
231 | 230 | ||
232 | } SCmdLinkStatus, *PSCmdLinkStatus; | 231 | } __packed SCmdLinkStatus, *PSCmdLinkStatus; |
233 | 232 | ||
234 | // | 233 | // |
235 | // 802.11 counter | 234 | // 802.11 counter |
@@ -247,7 +246,7 @@ typedef struct tagSDot11MIBCount { | |||
247 | u32 ReceivedFragmentCount; | 246 | u32 ReceivedFragmentCount; |
248 | u32 MulticastReceivedFrameCount; | 247 | u32 MulticastReceivedFrameCount; |
249 | u32 FCSErrorCount; | 248 | u32 FCSErrorCount; |
250 | } SDot11MIBCount, *PSDot11MIBCount; | 249 | } __packed SDot11MIBCount, *PSDot11MIBCount; |
251 | 250 | ||
252 | 251 | ||
253 | 252 | ||
@@ -355,13 +354,13 @@ typedef struct tagSStatMIBCount { | |||
355 | u32 ullTxBroadcastBytes[2]; | 354 | u32 ullTxBroadcastBytes[2]; |
356 | u32 ullTxMulticastBytes[2]; | 355 | u32 ullTxMulticastBytes[2]; |
357 | u32 ullTxDirectedBytes[2]; | 356 | u32 ullTxDirectedBytes[2]; |
358 | } SStatMIBCount, *PSStatMIBCount; | 357 | } __packed SStatMIBCount, *PSStatMIBCount; |
359 | 358 | ||
360 | typedef struct tagSCmdValue { | 359 | typedef struct tagSCmdValue { |
361 | 360 | ||
362 | u32 dwValue; | 361 | u32 dwValue; |
363 | 362 | ||
364 | } SCmdValue, *PSCmdValue; | 363 | } __packed SCmdValue, *PSCmdValue; |
365 | 364 | ||
366 | // | 365 | // |
367 | // hostapd & viawget ioctl related | 366 | // hostapd & viawget ioctl related |
@@ -431,7 +430,7 @@ struct viawget_hostapd_param { | |||
431 | u8 ssid[32]; | 430 | u8 ssid[32]; |
432 | } scan_req; | 431 | } scan_req; |
433 | } u; | 432 | } u; |
434 | }; | 433 | } __packed; |
435 | 434 | ||
436 | /*--------------------- Export Classes ----------------------------*/ | 435 | /*--------------------- Export Classes ----------------------------*/ |
437 | 436 | ||
diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h index 959c8868f6e2..2522ddec718d 100644 --- a/drivers/staging/vt6656/iowpa.h +++ b/drivers/staging/vt6656/iowpa.h | |||
@@ -67,12 +67,11 @@ enum { | |||
67 | 67 | ||
68 | 68 | ||
69 | 69 | ||
70 | #pragma pack(1) | ||
71 | typedef struct viawget_wpa_header { | 70 | typedef struct viawget_wpa_header { |
72 | u8 type; | 71 | u8 type; |
73 | u16 req_ie_len; | 72 | u16 req_ie_len; |
74 | u16 resp_ie_len; | 73 | u16 resp_ie_len; |
75 | } viawget_wpa_header; | 74 | } __packed viawget_wpa_header; |
76 | 75 | ||
77 | struct viawget_wpa_param { | 76 | struct viawget_wpa_param { |
78 | u32 cmd; | 77 | u32 cmd; |
@@ -113,9 +112,8 @@ struct viawget_wpa_param { | |||
113 | u8 *buf; | 112 | u8 *buf; |
114 | } scan_results; | 113 | } scan_results; |
115 | } u; | 114 | } u; |
116 | }; | 115 | } __packed; |
117 | 116 | ||
118 | #pragma pack(1) | ||
119 | struct viawget_scan_result { | 117 | struct viawget_scan_result { |
120 | u8 bssid[6]; | 118 | u8 bssid[6]; |
121 | u8 ssid[32]; | 119 | u8 ssid[32]; |
@@ -130,7 +128,7 @@ struct viawget_scan_result { | |||
130 | int noise; | 128 | int noise; |
131 | int level; | 129 | int level; |
132 | int maxrate; | 130 | int maxrate; |
133 | }; | 131 | } __packed; |
134 | 132 | ||
135 | /*--------------------- Export Classes ----------------------------*/ | 133 | /*--------------------- Export Classes ----------------------------*/ |
136 | 134 | ||
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c index 18c06a59c091..1d31eab19d16 100644 --- a/drivers/staging/wlan-ng/cfg80211.c +++ b/drivers/staging/wlan-ng/cfg80211.c | |||
@@ -638,8 +638,8 @@ int prism2_leave_ibss(struct wiphy *wiphy, struct net_device *dev) | |||
638 | } | 638 | } |
639 | 639 | ||
640 | 640 | ||
641 | int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, | 641 | int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, |
642 | int mbm) | 642 | enum nl80211_tx_power_setting type, int mbm) |
643 | { | 643 | { |
644 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); | 644 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); |
645 | wlandevice_t *wlandev = priv->wlandev; | 645 | wlandevice_t *wlandev = priv->wlandev; |
@@ -665,7 +665,8 @@ exit: | |||
665 | return err; | 665 | return err; |
666 | } | 666 | } |
667 | 667 | ||
668 | int prism2_get_tx_power(struct wiphy *wiphy, int *dbm) | 668 | int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev, |
669 | int *dbm) | ||
669 | { | 670 | { |
670 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); | 671 | struct prism2_wiphy_private *priv = wiphy_priv(wiphy); |
671 | wlandevice_t *wlandev = priv->wlandev; | 672 | wlandevice_t *wlandev = priv->wlandev; |
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c index 4efa9bc0fcf0..89bfd858bb28 100644 --- a/drivers/staging/wlan-ng/prism2mgmt.c +++ b/drivers/staging/wlan-ng/prism2mgmt.c | |||
@@ -406,7 +406,7 @@ int prism2mgmt_scan_results(wlandevice_t *wlandev, void *msgp) | |||
406 | /* SSID */ | 406 | /* SSID */ |
407 | req->ssid.status = P80211ENUM_msgitem_status_data_ok; | 407 | req->ssid.status = P80211ENUM_msgitem_status_data_ok; |
408 | req->ssid.data.len = le16_to_cpu(item->ssid.len); | 408 | req->ssid.data.len = le16_to_cpu(item->ssid.len); |
409 | req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN); | 409 | req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN); |
410 | memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); | 410 | memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len); |
411 | 411 | ||
412 | /* supported rates */ | 412 | /* supported rates */ |
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c index fb4a7c94aed3..f2a73bd739fb 100644 --- a/drivers/staging/zram/zram_drv.c +++ b/drivers/staging/zram/zram_drv.c | |||
@@ -265,7 +265,7 @@ out_cleanup: | |||
265 | static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | 265 | static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, |
266 | int offset) | 266 | int offset) |
267 | { | 267 | { |
268 | int ret; | 268 | int ret = 0; |
269 | size_t clen; | 269 | size_t clen; |
270 | unsigned long handle; | 270 | unsigned long handle; |
271 | struct page *page; | 271 | struct page *page; |
@@ -286,10 +286,8 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
286 | goto out; | 286 | goto out; |
287 | } | 287 | } |
288 | ret = zram_decompress_page(zram, uncmem, index); | 288 | ret = zram_decompress_page(zram, uncmem, index); |
289 | if (ret) { | 289 | if (ret) |
290 | kfree(uncmem); | ||
291 | goto out; | 290 | goto out; |
292 | } | ||
293 | } | 291 | } |
294 | 292 | ||
295 | /* | 293 | /* |
@@ -302,16 +300,18 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
302 | 300 | ||
303 | user_mem = kmap_atomic(page); | 301 | user_mem = kmap_atomic(page); |
304 | 302 | ||
305 | if (is_partial_io(bvec)) | 303 | if (is_partial_io(bvec)) { |
306 | memcpy(uncmem + offset, user_mem + bvec->bv_offset, | 304 | memcpy(uncmem + offset, user_mem + bvec->bv_offset, |
307 | bvec->bv_len); | 305 | bvec->bv_len); |
308 | else | 306 | kunmap_atomic(user_mem); |
307 | user_mem = NULL; | ||
308 | } else { | ||
309 | uncmem = user_mem; | 309 | uncmem = user_mem; |
310 | } | ||
310 | 311 | ||
311 | if (page_zero_filled(uncmem)) { | 312 | if (page_zero_filled(uncmem)) { |
312 | kunmap_atomic(user_mem); | 313 | if (!is_partial_io(bvec)) |
313 | if (is_partial_io(bvec)) | 314 | kunmap_atomic(user_mem); |
314 | kfree(uncmem); | ||
315 | zram_stat_inc(&zram->stats.pages_zero); | 315 | zram_stat_inc(&zram->stats.pages_zero); |
316 | zram_set_flag(zram, index, ZRAM_ZERO); | 316 | zram_set_flag(zram, index, ZRAM_ZERO); |
317 | ret = 0; | 317 | ret = 0; |
@@ -321,9 +321,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
321 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, | 321 | ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen, |
322 | zram->compress_workmem); | 322 | zram->compress_workmem); |
323 | 323 | ||
324 | kunmap_atomic(user_mem); | 324 | if (!is_partial_io(bvec)) { |
325 | if (is_partial_io(bvec)) | 325 | kunmap_atomic(user_mem); |
326 | kfree(uncmem); | 326 | user_mem = NULL; |
327 | uncmem = NULL; | ||
328 | } | ||
327 | 329 | ||
328 | if (unlikely(ret != LZO_E_OK)) { | 330 | if (unlikely(ret != LZO_E_OK)) { |
329 | pr_err("Compression failed! err=%d\n", ret); | 331 | pr_err("Compression failed! err=%d\n", ret); |
@@ -332,8 +334,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
332 | 334 | ||
333 | if (unlikely(clen > max_zpage_size)) { | 335 | if (unlikely(clen > max_zpage_size)) { |
334 | zram_stat_inc(&zram->stats.bad_compress); | 336 | zram_stat_inc(&zram->stats.bad_compress); |
335 | src = uncmem; | ||
336 | clen = PAGE_SIZE; | 337 | clen = PAGE_SIZE; |
338 | src = NULL; | ||
339 | if (is_partial_io(bvec)) | ||
340 | src = uncmem; | ||
337 | } | 341 | } |
338 | 342 | ||
339 | handle = zs_malloc(zram->mem_pool, clen); | 343 | handle = zs_malloc(zram->mem_pool, clen); |
@@ -345,7 +349,11 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
345 | } | 349 | } |
346 | cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); | 350 | cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO); |
347 | 351 | ||
352 | if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) | ||
353 | src = kmap_atomic(page); | ||
348 | memcpy(cmem, src, clen); | 354 | memcpy(cmem, src, clen); |
355 | if ((clen == PAGE_SIZE) && !is_partial_io(bvec)) | ||
356 | kunmap_atomic(src); | ||
349 | 357 | ||
350 | zs_unmap_object(zram->mem_pool, handle); | 358 | zs_unmap_object(zram->mem_pool, handle); |
351 | 359 | ||
@@ -358,9 +366,10 @@ static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index, | |||
358 | if (clen <= PAGE_SIZE / 2) | 366 | if (clen <= PAGE_SIZE / 2) |
359 | zram_stat_inc(&zram->stats.good_compress); | 367 | zram_stat_inc(&zram->stats.good_compress); |
360 | 368 | ||
361 | return 0; | ||
362 | |||
363 | out: | 369 | out: |
370 | if (is_partial_io(bvec)) | ||
371 | kfree(uncmem); | ||
372 | |||
364 | if (ret) | 373 | if (ret) |
365 | zram_stat64_inc(zram, &zram->stats.failed_writes); | 374 | zram_stat64_inc(zram, &zram->stats.failed_writes); |
366 | return ret; | 375 | return ret; |
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c index 9ac4c151eae4..ba6091bf93fc 100644 --- a/drivers/target/iscsi/iscsi_target_erl2.c +++ b/drivers/target/iscsi/iscsi_target_erl2.c | |||
@@ -372,7 +372,7 @@ int iscsit_prepare_cmds_for_realligance(struct iscsi_conn *conn) | |||
372 | * made generic here. | 372 | * made generic here. |
373 | */ | 373 | */ |
374 | if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && | 374 | if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd && |
375 | iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) { | 375 | iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) { |
376 | list_del(&cmd->i_conn_node); | 376 | list_del(&cmd->i_conn_node); |
377 | spin_unlock_bh(&conn->cmd_lock); | 377 | spin_unlock_bh(&conn->cmd_lock); |
378 | iscsit_free_cmd(cmd); | 378 | iscsit_free_cmd(cmd); |
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c index 85140f7dde1e..7d4ec02e29a9 100644 --- a/drivers/target/target_core_alua.c +++ b/drivers/target/target_core_alua.c | |||
@@ -212,7 +212,7 @@ target_emulate_set_target_port_groups(struct se_cmd *cmd) | |||
212 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; | 212 | struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem; |
213 | unsigned char *buf; | 213 | unsigned char *buf; |
214 | unsigned char *ptr; | 214 | unsigned char *ptr; |
215 | sense_reason_t rc; | 215 | sense_reason_t rc = TCM_NO_SENSE; |
216 | u32 len = 4; /* Skip over RESERVED area in header */ | 216 | u32 len = 4; /* Skip over RESERVED area in header */ |
217 | int alua_access_state, primary = 0; | 217 | int alua_access_state, primary = 0; |
218 | u16 tg_pt_id, rtpi; | 218 | u16 tg_pt_id, rtpi; |
diff --git a/drivers/target/target_core_device.c b/drivers/target/target_core_device.c index e2695101bb99..f2aa7543d20a 100644 --- a/drivers/target/target_core_device.c +++ b/drivers/target/target_core_device.c | |||
@@ -941,6 +941,8 @@ int se_dev_set_queue_depth(struct se_device *dev, u32 queue_depth) | |||
941 | 941 | ||
942 | int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) | 942 | int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) |
943 | { | 943 | { |
944 | int block_size = dev->dev_attrib.block_size; | ||
945 | |||
944 | if (dev->export_count) { | 946 | if (dev->export_count) { |
945 | pr_err("dev[%p]: Unable to change SE Device" | 947 | pr_err("dev[%p]: Unable to change SE Device" |
946 | " fabric_max_sectors while export_count is %d\n", | 948 | " fabric_max_sectors while export_count is %d\n", |
@@ -978,8 +980,12 @@ int se_dev_set_fabric_max_sectors(struct se_device *dev, u32 fabric_max_sectors) | |||
978 | /* | 980 | /* |
979 | * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() | 981 | * Align max_sectors down to PAGE_SIZE to follow transport_allocate_data_tasks() |
980 | */ | 982 | */ |
983 | if (!block_size) { | ||
984 | block_size = 512; | ||
985 | pr_warn("Defaulting to 512 for zero block_size\n"); | ||
986 | } | ||
981 | fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, | 987 | fabric_max_sectors = se_dev_align_max_sectors(fabric_max_sectors, |
982 | dev->dev_attrib.block_size); | 988 | block_size); |
983 | 989 | ||
984 | dev->dev_attrib.fabric_max_sectors = fabric_max_sectors; | 990 | dev->dev_attrib.fabric_max_sectors = fabric_max_sectors; |
985 | pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", | 991 | pr_debug("dev[%p]: SE Device max_sectors changed to %u\n", |
diff --git a/drivers/target/target_core_fabric_configfs.c b/drivers/target/target_core_fabric_configfs.c index 810263dfa4a1..c57bbbc7a7d1 100644 --- a/drivers/target/target_core_fabric_configfs.c +++ b/drivers/target/target_core_fabric_configfs.c | |||
@@ -754,6 +754,11 @@ static int target_fabric_port_link( | |||
754 | return -EFAULT; | 754 | return -EFAULT; |
755 | } | 755 | } |
756 | 756 | ||
757 | if (!(dev->dev_flags & DF_CONFIGURED)) { | ||
758 | pr_err("se_device not configured yet, cannot port link\n"); | ||
759 | return -ENODEV; | ||
760 | } | ||
761 | |||
757 | tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; | 762 | tpg_ci = &lun_ci->ci_parent->ci_group->cg_item; |
758 | se_tpg = container_of(to_config_group(tpg_ci), | 763 | se_tpg = container_of(to_config_group(tpg_ci), |
759 | struct se_portal_group, tpg_group); | 764 | struct se_portal_group, tpg_group); |
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c index e35dbf85841f..8e0290b38e43 100644 --- a/drivers/target/target_core_pr.c +++ b/drivers/target/target_core_pr.c | |||
@@ -2053,7 +2053,7 @@ core_scsi3_emulate_pro_register(struct se_cmd *cmd, u64 res_key, u64 sa_res_key, | |||
2053 | /* Used for APTPL metadata w/ UNREGISTER */ | 2053 | /* Used for APTPL metadata w/ UNREGISTER */ |
2054 | unsigned char *pr_aptpl_buf = NULL; | 2054 | unsigned char *pr_aptpl_buf = NULL; |
2055 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; | 2055 | unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL; |
2056 | sense_reason_t ret; | 2056 | sense_reason_t ret = TCM_NO_SENSE; |
2057 | int pr_holder = 0, type; | 2057 | int pr_holder = 0, type; |
2058 | 2058 | ||
2059 | if (!se_sess || !se_lun) { | 2059 | if (!se_sess || !se_lun) { |
diff --git a/drivers/target/target_core_sbc.c b/drivers/target/target_core_sbc.c index 26a6d183ccb1..a664c664a31a 100644 --- a/drivers/target/target_core_sbc.c +++ b/drivers/target/target_core_sbc.c | |||
@@ -58,11 +58,10 @@ sbc_emulate_readcapacity(struct se_cmd *cmd) | |||
58 | buf[7] = dev->dev_attrib.block_size & 0xff; | 58 | buf[7] = dev->dev_attrib.block_size & 0xff; |
59 | 59 | ||
60 | rbuf = transport_kmap_data_sg(cmd); | 60 | rbuf = transport_kmap_data_sg(cmd); |
61 | if (!rbuf) | 61 | if (rbuf) { |
62 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 62 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
63 | 63 | transport_kunmap_data_sg(cmd); | |
64 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 64 | } |
65 | transport_kunmap_data_sg(cmd); | ||
66 | 65 | ||
67 | target_complete_cmd(cmd, GOOD); | 66 | target_complete_cmd(cmd, GOOD); |
68 | return 0; | 67 | return 0; |
@@ -97,11 +96,10 @@ sbc_emulate_readcapacity_16(struct se_cmd *cmd) | |||
97 | buf[14] = 0x80; | 96 | buf[14] = 0x80; |
98 | 97 | ||
99 | rbuf = transport_kmap_data_sg(cmd); | 98 | rbuf = transport_kmap_data_sg(cmd); |
100 | if (!rbuf) | 99 | if (rbuf) { |
101 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 100 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
102 | 101 | transport_kunmap_data_sg(cmd); | |
103 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 102 | } |
104 | transport_kunmap_data_sg(cmd); | ||
105 | 103 | ||
106 | target_complete_cmd(cmd, GOOD); | 104 | target_complete_cmd(cmd, GOOD); |
107 | return 0; | 105 | return 0; |
diff --git a/drivers/target/target_core_spc.c b/drivers/target/target_core_spc.c index 84f9e96e8ace..2d88f087d961 100644 --- a/drivers/target/target_core_spc.c +++ b/drivers/target/target_core_spc.c | |||
@@ -641,11 +641,10 @@ spc_emulate_inquiry(struct se_cmd *cmd) | |||
641 | 641 | ||
642 | out: | 642 | out: |
643 | rbuf = transport_kmap_data_sg(cmd); | 643 | rbuf = transport_kmap_data_sg(cmd); |
644 | if (!rbuf) | 644 | if (rbuf) { |
645 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | 645 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); |
646 | 646 | transport_kunmap_data_sg(cmd); | |
647 | memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length)); | 647 | } |
648 | transport_kunmap_data_sg(cmd); | ||
649 | 648 | ||
650 | if (!ret) | 649 | if (!ret) |
651 | target_complete_cmd(cmd, GOOD); | 650 | target_complete_cmd(cmd, GOOD); |
@@ -851,7 +850,7 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
851 | { | 850 | { |
852 | struct se_device *dev = cmd->se_dev; | 851 | struct se_device *dev = cmd->se_dev; |
853 | char *cdb = cmd->t_task_cdb; | 852 | char *cdb = cmd->t_task_cdb; |
854 | unsigned char *buf, *map_buf; | 853 | unsigned char buf[SE_MODE_PAGE_BUF], *rbuf; |
855 | int type = dev->transport->get_device_type(dev); | 854 | int type = dev->transport->get_device_type(dev); |
856 | int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); | 855 | int ten = (cmd->t_task_cdb[0] == MODE_SENSE_10); |
857 | bool dbd = !!(cdb[1] & 0x08); | 856 | bool dbd = !!(cdb[1] & 0x08); |
@@ -863,26 +862,8 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
863 | int ret; | 862 | int ret; |
864 | int i; | 863 | int i; |
865 | 864 | ||
866 | map_buf = transport_kmap_data_sg(cmd); | 865 | memset(buf, 0, SE_MODE_PAGE_BUF); |
867 | if (!map_buf) | 866 | |
868 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
869 | /* | ||
870 | * If SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC is not set, then we | ||
871 | * know we actually allocated a full page. Otherwise, if the | ||
872 | * data buffer is too small, allocate a temporary buffer so we | ||
873 | * don't have to worry about overruns in all our INQUIRY | ||
874 | * emulation handling. | ||
875 | */ | ||
876 | if (cmd->data_length < SE_MODE_PAGE_BUF && | ||
877 | (cmd->se_cmd_flags & SCF_PASSTHROUGH_SG_TO_MEM_NOALLOC)) { | ||
878 | buf = kzalloc(SE_MODE_PAGE_BUF, GFP_KERNEL); | ||
879 | if (!buf) { | ||
880 | transport_kunmap_data_sg(cmd); | ||
881 | return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE; | ||
882 | } | ||
883 | } else { | ||
884 | buf = map_buf; | ||
885 | } | ||
886 | /* | 867 | /* |
887 | * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for | 868 | * Skip over MODE DATA LENGTH + MEDIUM TYPE fields to byte 3 for |
888 | * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). | 869 | * MODE_SENSE_10 and byte 2 for MODE_SENSE (6). |
@@ -934,8 +915,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
934 | if (page == 0x3f) { | 915 | if (page == 0x3f) { |
935 | if (subpage != 0x00 && subpage != 0xff) { | 916 | if (subpage != 0x00 && subpage != 0xff) { |
936 | pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); | 917 | pr_warn("MODE_SENSE: Invalid subpage code: 0x%02x\n", subpage); |
937 | kfree(buf); | ||
938 | transport_kunmap_data_sg(cmd); | ||
939 | return TCM_INVALID_CDB_FIELD; | 918 | return TCM_INVALID_CDB_FIELD; |
940 | } | 919 | } |
941 | 920 | ||
@@ -972,7 +951,6 @@ static sense_reason_t spc_emulate_modesense(struct se_cmd *cmd) | |||
972 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", | 951 | pr_err("MODE SENSE: unimplemented page/subpage: 0x%02x/0x%02x\n", |
973 | page, subpage); | 952 | page, subpage); |
974 | 953 | ||
975 | transport_kunmap_data_sg(cmd); | ||
976 | return TCM_UNKNOWN_MODE_PAGE; | 954 | return TCM_UNKNOWN_MODE_PAGE; |
977 | 955 | ||
978 | set_length: | 956 | set_length: |
@@ -981,12 +959,12 @@ set_length: | |||
981 | else | 959 | else |
982 | buf[0] = length - 1; | 960 | buf[0] = length - 1; |
983 | 961 | ||
984 | if (buf != map_buf) { | 962 | rbuf = transport_kmap_data_sg(cmd); |
985 | memcpy(map_buf, buf, cmd->data_length); | 963 | if (rbuf) { |
986 | kfree(buf); | 964 | memcpy(rbuf, buf, min_t(u32, SE_MODE_PAGE_BUF, cmd->data_length)); |
965 | transport_kunmap_data_sg(cmd); | ||
987 | } | 966 | } |
988 | 967 | ||
989 | transport_kunmap_data_sg(cmd); | ||
990 | target_complete_cmd(cmd, GOOD); | 968 | target_complete_cmd(cmd, GOOD); |
991 | return 0; | 969 | return 0; |
992 | } | 970 | } |
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c index c23c76ccef65..bd587b70661a 100644 --- a/drivers/target/target_core_transport.c +++ b/drivers/target/target_core_transport.c | |||
@@ -541,9 +541,6 @@ static void transport_lun_remove_cmd(struct se_cmd *cmd) | |||
541 | 541 | ||
542 | void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) | 542 | void transport_cmd_finish_abort(struct se_cmd *cmd, int remove) |
543 | { | 543 | { |
544 | if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB)) | ||
545 | transport_lun_remove_cmd(cmd); | ||
546 | |||
547 | if (transport_cmd_check_stop_to_fabric(cmd)) | 544 | if (transport_cmd_check_stop_to_fabric(cmd)) |
548 | return; | 545 | return; |
549 | if (remove) | 546 | if (remove) |
@@ -1396,6 +1393,8 @@ static void target_complete_tmr_failure(struct work_struct *work) | |||
1396 | 1393 | ||
1397 | se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; | 1394 | se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST; |
1398 | se_cmd->se_tfo->queue_tm_rsp(se_cmd); | 1395 | se_cmd->se_tfo->queue_tm_rsp(se_cmd); |
1396 | |||
1397 | transport_cmd_check_stop_to_fabric(se_cmd); | ||
1399 | } | 1398 | } |
1400 | 1399 | ||
1401 | /** | 1400 | /** |
@@ -1688,6 +1687,7 @@ void target_execute_cmd(struct se_cmd *cmd) | |||
1688 | } | 1687 | } |
1689 | 1688 | ||
1690 | cmd->t_state = TRANSPORT_PROCESSING; | 1689 | cmd->t_state = TRANSPORT_PROCESSING; |
1690 | cmd->transport_state |= CMD_T_ACTIVE; | ||
1691 | spin_unlock_irq(&cmd->t_state_lock); | 1691 | spin_unlock_irq(&cmd->t_state_lock); |
1692 | 1692 | ||
1693 | if (!target_handle_task_attr(cmd)) | 1693 | if (!target_handle_task_attr(cmd)) |
@@ -2597,6 +2597,16 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, | |||
2597 | * SENSE KEY values from include/scsi/scsi.h | 2597 | * SENSE KEY values from include/scsi/scsi.h |
2598 | */ | 2598 | */ |
2599 | switch (reason) { | 2599 | switch (reason) { |
2600 | case TCM_NO_SENSE: | ||
2601 | /* CURRENT ERROR */ | ||
2602 | buffer[0] = 0x70; | ||
2603 | buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10; | ||
2604 | /* Not Ready */ | ||
2605 | buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY; | ||
2606 | /* NO ADDITIONAL SENSE INFORMATION */ | ||
2607 | buffer[SPC_ASC_KEY_OFFSET] = 0; | ||
2608 | buffer[SPC_ASCQ_KEY_OFFSET] = 0; | ||
2609 | break; | ||
2600 | case TCM_NON_EXISTENT_LUN: | 2610 | case TCM_NON_EXISTENT_LUN: |
2601 | /* CURRENT ERROR */ | 2611 | /* CURRENT ERROR */ |
2602 | buffer[0] = 0x70; | 2612 | buffer[0] = 0x70; |
@@ -2743,7 +2753,7 @@ transport_send_check_condition_and_sense(struct se_cmd *cmd, | |||
2743 | /* ILLEGAL REQUEST */ | 2753 | /* ILLEGAL REQUEST */ |
2744 | buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; | 2754 | buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST; |
2745 | /* LOGICAL UNIT COMMUNICATION FAILURE */ | 2755 | /* LOGICAL UNIT COMMUNICATION FAILURE */ |
2746 | buffer[SPC_ASC_KEY_OFFSET] = 0x80; | 2756 | buffer[SPC_ASC_KEY_OFFSET] = 0x08; |
2747 | break; | 2757 | break; |
2748 | } | 2758 | } |
2749 | /* | 2759 | /* |
@@ -2804,6 +2814,8 @@ void transport_send_task_abort(struct se_cmd *cmd) | |||
2804 | } | 2814 | } |
2805 | cmd->scsi_status = SAM_STAT_TASK_ABORTED; | 2815 | cmd->scsi_status = SAM_STAT_TASK_ABORTED; |
2806 | 2816 | ||
2817 | transport_lun_remove_cmd(cmd); | ||
2818 | |||
2807 | pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x," | 2819 | pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x," |
2808 | " ITT: 0x%08x\n", cmd->t_task_cdb[0], | 2820 | " ITT: 0x%08x\n", cmd->t_task_cdb[0], |
2809 | cmd->se_tfo->get_task_tag(cmd)); | 2821 | cmd->se_tfo->get_task_tag(cmd)); |
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c index 12d6fa21e5e1..6659dd36e806 100644 --- a/drivers/target/tcm_fc/tfc_sess.c +++ b/drivers/target/tcm_fc/tfc_sess.c | |||
@@ -355,11 +355,11 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, | |||
355 | 355 | ||
356 | tport = ft_tport_create(rdata->local_port); | 356 | tport = ft_tport_create(rdata->local_port); |
357 | if (!tport) | 357 | if (!tport) |
358 | return 0; /* not a target for this local port */ | 358 | goto not_target; /* not a target for this local port */ |
359 | 359 | ||
360 | acl = ft_acl_get(tport->tpg, rdata); | 360 | acl = ft_acl_get(tport->tpg, rdata); |
361 | if (!acl) | 361 | if (!acl) |
362 | return 0; | 362 | goto not_target; /* no target for this remote */ |
363 | 363 | ||
364 | if (!rspp) | 364 | if (!rspp) |
365 | goto fill; | 365 | goto fill; |
@@ -396,12 +396,18 @@ static int ft_prli_locked(struct fc_rport_priv *rdata, u32 spp_len, | |||
396 | 396 | ||
397 | /* | 397 | /* |
398 | * OR in our service parameters with other provider (initiator), if any. | 398 | * OR in our service parameters with other provider (initiator), if any. |
399 | * TBD XXX - indicate RETRY capability? | ||
400 | */ | 399 | */ |
401 | fill: | 400 | fill: |
402 | fcp_parm = ntohl(spp->spp_params); | 401 | fcp_parm = ntohl(spp->spp_params); |
402 | fcp_parm &= ~FCP_SPPF_RETRY; | ||
403 | spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); | 403 | spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN); |
404 | return FC_SPP_RESP_ACK; | 404 | return FC_SPP_RESP_ACK; |
405 | |||
406 | not_target: | ||
407 | fcp_parm = ntohl(spp->spp_params); | ||
408 | fcp_parm &= ~FCP_SPPF_TARG_FCN; | ||
409 | spp->spp_params = htonl(fcp_parm); | ||
410 | return 0; | ||
405 | } | 411 | } |
406 | 412 | ||
407 | /** | 413 | /** |
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c index be6a373601b7..79ff3a5e925d 100644 --- a/drivers/tty/pty.c +++ b/drivers/tty/pty.c | |||
@@ -441,6 +441,8 @@ static int pty_bsd_ioctl(struct tty_struct *tty, | |||
441 | return pty_get_pktmode(tty, (int __user *)arg); | 441 | return pty_get_pktmode(tty, (int __user *)arg); |
442 | case TIOCSIG: /* Send signal to other side of pty */ | 442 | case TIOCSIG: /* Send signal to other side of pty */ |
443 | return pty_signal(tty, (int) arg); | 443 | return pty_signal(tty, (int) arg); |
444 | case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */ | ||
445 | return -EINVAL; | ||
444 | } | 446 | } |
445 | return -ENOIOCTLCMD; | 447 | return -ENOIOCTLCMD; |
446 | } | 448 | } |
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c index d085e3a8ec06..f9320437a649 100644 --- a/drivers/tty/serial/8250/8250.c +++ b/drivers/tty/serial/8250/8250.c | |||
@@ -300,6 +300,12 @@ static const struct serial8250_config uart_config[] = { | |||
300 | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, | 300 | UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00, |
301 | .flags = UART_CAP_FIFO, | 301 | .flags = UART_CAP_FIFO, |
302 | }, | 302 | }, |
303 | [PORT_BRCM_TRUMANAGE] = { | ||
304 | .name = "TruManage", | ||
305 | .fifo_size = 1, | ||
306 | .tx_loadsz = 1024, | ||
307 | .flags = UART_CAP_HFIFO, | ||
308 | }, | ||
303 | [PORT_8250_CIR] = { | 309 | [PORT_8250_CIR] = { |
304 | .name = "CIR port" | 310 | .name = "CIR port" |
305 | } | 311 | } |
@@ -1490,6 +1496,11 @@ void serial8250_tx_chars(struct uart_8250_port *up) | |||
1490 | port->icount.tx++; | 1496 | port->icount.tx++; |
1491 | if (uart_circ_empty(xmit)) | 1497 | if (uart_circ_empty(xmit)) |
1492 | break; | 1498 | break; |
1499 | if (up->capabilities & UART_CAP_HFIFO) { | ||
1500 | if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) != | ||
1501 | BOTH_EMPTY) | ||
1502 | break; | ||
1503 | } | ||
1493 | } while (--count > 0); | 1504 | } while (--count > 0); |
1494 | 1505 | ||
1495 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 1506 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h index 3b4ea84898c2..12caa1292b75 100644 --- a/drivers/tty/serial/8250/8250.h +++ b/drivers/tty/serial/8250/8250.h | |||
@@ -40,6 +40,7 @@ struct serial8250_config { | |||
40 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ | 40 | #define UART_CAP_AFE (1 << 11) /* MCR-based hw flow control */ |
41 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ | 41 | #define UART_CAP_UUE (1 << 12) /* UART needs IER bit 6 set (Xscale) */ |
42 | #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ | 42 | #define UART_CAP_RTOIE (1 << 13) /* UART needs IER bit 4 set (Xscale, Tegra) */ |
43 | #define UART_CAP_HFIFO (1 << 14) /* UART has a "hidden" FIFO */ | ||
43 | 44 | ||
44 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ | 45 | #define UART_BUG_QUOT (1 << 0) /* UART has buggy quot LSB */ |
45 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ | 46 | #define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */ |
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c index 1d0dba2d562d..096d2ef48b32 100644 --- a/drivers/tty/serial/8250/8250_dw.c +++ b/drivers/tty/serial/8250/8250_dw.c | |||
@@ -79,7 +79,7 @@ static int dw8250_handle_irq(struct uart_port *p) | |||
79 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { | 79 | } else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) { |
80 | /* Clear the USR and write the LCR again. */ | 80 | /* Clear the USR and write the LCR again. */ |
81 | (void)p->serial_in(p, UART_USR); | 81 | (void)p->serial_in(p, UART_USR); |
82 | p->serial_out(p, d->last_lcr, UART_LCR); | 82 | p->serial_out(p, UART_LCR, d->last_lcr); |
83 | 83 | ||
84 | return 1; | 84 | return 1; |
85 | } | 85 | } |
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 26b9dc012ed0..a27a98e1b066 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c | |||
@@ -1085,6 +1085,18 @@ pci_omegapci_setup(struct serial_private *priv, | |||
1085 | return setup_port(priv, port, 2, idx * 8, 0); | 1085 | return setup_port(priv, port, 2, idx * 8, 0); |
1086 | } | 1086 | } |
1087 | 1087 | ||
1088 | static int | ||
1089 | pci_brcm_trumanage_setup(struct serial_private *priv, | ||
1090 | const struct pciserial_board *board, | ||
1091 | struct uart_8250_port *port, int idx) | ||
1092 | { | ||
1093 | int ret = pci_default_setup(priv, board, port, idx); | ||
1094 | |||
1095 | port->port.type = PORT_BRCM_TRUMANAGE; | ||
1096 | port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE); | ||
1097 | return ret; | ||
1098 | } | ||
1099 | |||
1088 | static int skip_tx_en_setup(struct serial_private *priv, | 1100 | static int skip_tx_en_setup(struct serial_private *priv, |
1089 | const struct pciserial_board *board, | 1101 | const struct pciserial_board *board, |
1090 | struct uart_8250_port *port, int idx) | 1102 | struct uart_8250_port *port, int idx) |
@@ -1301,9 +1313,10 @@ pci_wch_ch353_setup(struct serial_private *priv, | |||
1301 | #define PCI_VENDOR_ID_AGESTAR 0x5372 | 1313 | #define PCI_VENDOR_ID_AGESTAR 0x5372 |
1302 | #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 | 1314 | #define PCI_DEVICE_ID_AGESTAR_9375 0x6872 |
1303 | #define PCI_VENDOR_ID_ASIX 0x9710 | 1315 | #define PCI_VENDOR_ID_ASIX 0x9710 |
1304 | #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019 | ||
1305 | #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 | 1316 | #define PCI_DEVICE_ID_COMMTECH_4224PCIE 0x0020 |
1306 | #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 | 1317 | #define PCI_DEVICE_ID_COMMTECH_4228PCIE 0x0021 |
1318 | #define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0022 | ||
1319 | #define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a | ||
1307 | 1320 | ||
1308 | 1321 | ||
1309 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ | 1322 | /* Unknown vendors/cards - this should not be in linux/pci_ids.h */ |
@@ -1954,6 +1967,17 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = { | |||
1954 | .setup = pci_xr17v35x_setup, | 1967 | .setup = pci_xr17v35x_setup, |
1955 | }, | 1968 | }, |
1956 | /* | 1969 | /* |
1970 | * Broadcom TruManage (NetXtreme) | ||
1971 | */ | ||
1972 | { | ||
1973 | .vendor = PCI_VENDOR_ID_BROADCOM, | ||
1974 | .device = PCI_DEVICE_ID_BROADCOM_TRUMANAGE, | ||
1975 | .subvendor = PCI_ANY_ID, | ||
1976 | .subdevice = PCI_ANY_ID, | ||
1977 | .setup = pci_brcm_trumanage_setup, | ||
1978 | }, | ||
1979 | |||
1980 | /* | ||
1957 | * Default "match everything" terminator entry | 1981 | * Default "match everything" terminator entry |
1958 | */ | 1982 | */ |
1959 | { | 1983 | { |
@@ -2148,6 +2172,7 @@ enum pci_board_num_t { | |||
2148 | pbn_ce4100_1_115200, | 2172 | pbn_ce4100_1_115200, |
2149 | pbn_omegapci, | 2173 | pbn_omegapci, |
2150 | pbn_NETMOS9900_2s_115200, | 2174 | pbn_NETMOS9900_2s_115200, |
2175 | pbn_brcm_trumanage, | ||
2151 | }; | 2176 | }; |
2152 | 2177 | ||
2153 | /* | 2178 | /* |
@@ -2246,7 +2271,7 @@ static struct pciserial_board pci_boards[] = { | |||
2246 | 2271 | ||
2247 | [pbn_b0_8_1152000_200] = { | 2272 | [pbn_b0_8_1152000_200] = { |
2248 | .flags = FL_BASE0, | 2273 | .flags = FL_BASE0, |
2249 | .num_ports = 2, | 2274 | .num_ports = 8, |
2250 | .base_baud = 1152000, | 2275 | .base_baud = 1152000, |
2251 | .uart_offset = 0x200, | 2276 | .uart_offset = 0x200, |
2252 | }, | 2277 | }, |
@@ -2892,6 +2917,12 @@ static struct pciserial_board pci_boards[] = { | |||
2892 | .num_ports = 2, | 2917 | .num_ports = 2, |
2893 | .base_baud = 115200, | 2918 | .base_baud = 115200, |
2894 | }, | 2919 | }, |
2920 | [pbn_brcm_trumanage] = { | ||
2921 | .flags = FL_BASE0, | ||
2922 | .num_ports = 1, | ||
2923 | .reg_shift = 2, | ||
2924 | .base_baud = 115200, | ||
2925 | }, | ||
2895 | }; | 2926 | }; |
2896 | 2927 | ||
2897 | static const struct pci_device_id blacklist[] = { | 2928 | static const struct pci_device_id blacklist[] = { |
@@ -4471,6 +4502,13 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
4471 | pbn_omegapci }, | 4502 | pbn_omegapci }, |
4472 | 4503 | ||
4473 | /* | 4504 | /* |
4505 | * Broadcom TruManage | ||
4506 | */ | ||
4507 | { PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE, | ||
4508 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | ||
4509 | pbn_brcm_trumanage }, | ||
4510 | |||
4511 | /* | ||
4474 | * AgeStar as-prs2-009 | 4512 | * AgeStar as-prs2-009 |
4475 | */ | 4513 | */ |
4476 | { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, | 4514 | { PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375, |
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c index 675d94ab0aff..8cb6d8d66a13 100644 --- a/drivers/tty/serial/ifx6x60.c +++ b/drivers/tty/serial/ifx6x60.c | |||
@@ -637,6 +637,7 @@ static void ifx_port_shutdown(struct tty_port *port) | |||
637 | 637 | ||
638 | clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); | 638 | clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags); |
639 | mrdy_set_low(ifx_dev); | 639 | mrdy_set_low(ifx_dev); |
640 | del_timer(&ifx_dev->spi_timer); | ||
640 | clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); | 641 | clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags); |
641 | tasklet_kill(&ifx_dev->io_work_tasklet); | 642 | tasklet_kill(&ifx_dev->io_work_tasklet); |
642 | } | 643 | } |
@@ -810,7 +811,8 @@ static void ifx_spi_io(unsigned long data) | |||
810 | ifx_dev->spi_xfer.cs_change = 0; | 811 | ifx_dev->spi_xfer.cs_change = 0; |
811 | ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; | 812 | ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz; |
812 | /* ifx_dev->spi_xfer.speed_hz = 390625; */ | 813 | /* ifx_dev->spi_xfer.speed_hz = 390625; */ |
813 | ifx_dev->spi_xfer.bits_per_word = spi_bpw; | 814 | ifx_dev->spi_xfer.bits_per_word = |
815 | ifx_dev->spi_dev->bits_per_word; | ||
814 | 816 | ||
815 | ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; | 817 | ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer; |
816 | ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; | 818 | ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer; |
diff --git a/drivers/tty/serial/max3100.c b/drivers/tty/serial/max3100.c index 7ce3197087bb..dd6277eb5a38 100644 --- a/drivers/tty/serial/max3100.c +++ b/drivers/tty/serial/max3100.c | |||
@@ -179,8 +179,7 @@ static void max3100_work(struct work_struct *w); | |||
179 | 179 | ||
180 | static void max3100_dowork(struct max3100_port *s) | 180 | static void max3100_dowork(struct max3100_port *s) |
181 | { | 181 | { |
182 | if (!s->force_end_work && !work_pending(&s->work) && | 182 | if (!s->force_end_work && !freezing(current) && !s->suspending) |
183 | !freezing(current) && !s->suspending) | ||
184 | queue_work(s->workqueue, &s->work); | 183 | queue_work(s->workqueue, &s->work); |
185 | } | 184 | } |
186 | 185 | ||
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c index 6db23b035efe..e55615eb34ad 100644 --- a/drivers/tty/serial/mxs-auart.c +++ b/drivers/tty/serial/mxs-auart.c | |||
@@ -253,7 +253,7 @@ static void mxs_auart_tx_chars(struct mxs_auart_port *s) | |||
253 | struct circ_buf *xmit = &s->port.state->xmit; | 253 | struct circ_buf *xmit = &s->port.state->xmit; |
254 | 254 | ||
255 | if (auart_dma_enabled(s)) { | 255 | if (auart_dma_enabled(s)) { |
256 | int i = 0; | 256 | u32 i = 0; |
257 | int size; | 257 | int size; |
258 | void *buffer = s->tx_dma_buf; | 258 | void *buffer = s->tx_dma_buf; |
259 | 259 | ||
@@ -412,10 +412,12 @@ static void mxs_auart_set_mctrl(struct uart_port *u, unsigned mctrl) | |||
412 | 412 | ||
413 | u32 ctrl = readl(u->membase + AUART_CTRL2); | 413 | u32 ctrl = readl(u->membase + AUART_CTRL2); |
414 | 414 | ||
415 | ctrl &= ~AUART_CTRL2_RTSEN; | 415 | ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS); |
416 | if (mctrl & TIOCM_RTS) { | 416 | if (mctrl & TIOCM_RTS) { |
417 | if (tty_port_cts_enabled(&u->state->port)) | 417 | if (tty_port_cts_enabled(&u->state->port)) |
418 | ctrl |= AUART_CTRL2_RTSEN; | 418 | ctrl |= AUART_CTRL2_RTSEN; |
419 | else | ||
420 | ctrl |= AUART_CTRL2_RTS; | ||
419 | } | 421 | } |
420 | 422 | ||
421 | s->ctrl = mctrl; | 423 | s->ctrl = mctrl; |
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c index 12e5249d053e..e514b3a4dc57 100644 --- a/drivers/tty/serial/samsung.c +++ b/drivers/tty/serial/samsung.c | |||
@@ -1006,7 +1006,6 @@ static void s3c24xx_serial_resetport(struct uart_port *port, | |||
1006 | 1006 | ||
1007 | ucon &= ucon_mask; | 1007 | ucon &= ucon_mask; |
1008 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); | 1008 | wr_regl(port, S3C2410_UCON, ucon | cfg->ucon); |
1009 | wr_regl(port, S3C2410_ULCON, cfg->ulcon); | ||
1010 | 1009 | ||
1011 | /* reset both fifos */ | 1010 | /* reset both fifos */ |
1012 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); | 1011 | wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH); |
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c index 8fd181436a6b..d5ed9f613005 100644 --- a/drivers/tty/serial/vt8500_serial.c +++ b/drivers/tty/serial/vt8500_serial.c | |||
@@ -604,7 +604,7 @@ static int vt8500_serial_probe(struct platform_device *pdev) | |||
604 | vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; | 604 | vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF; |
605 | 605 | ||
606 | vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); | 606 | vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0); |
607 | if (vt8500_port->clk) { | 607 | if (!IS_ERR(vt8500_port->clk)) { |
608 | vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); | 608 | vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk); |
609 | } else { | 609 | } else { |
610 | /* use the default of 24Mhz if not specified and warn */ | 610 | /* use the default of 24Mhz if not specified and warn */ |
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index b3c4a250ff86..40e5b3919e27 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 15 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
16 | 16 | ||
17 | #include <linux/sched.h> | 17 | #include <linux/sched.h> |
18 | #include <linux/sched/rt.h> | ||
18 | #include <linux/interrupt.h> | 19 | #include <linux/interrupt.h> |
19 | #include <linux/mm.h> | 20 | #include <linux/mm.h> |
20 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig index 4c90b510d016..640ae6c6d2d2 100644 --- a/drivers/usb/Kconfig +++ b/drivers/usb/Kconfig | |||
@@ -37,6 +37,7 @@ config USB_ARCH_HAS_EHCI | |||
37 | default y if ARCH_W90X900 | 37 | default y if ARCH_W90X900 |
38 | default y if ARCH_AT91 | 38 | default y if ARCH_AT91 |
39 | default y if ARCH_MXC | 39 | default y if ARCH_MXC |
40 | default y if ARCH_MXS | ||
40 | default y if ARCH_OMAP3 | 41 | default y if ARCH_OMAP3 |
41 | default y if ARCH_CNS3XXX | 42 | default y if ARCH_CNS3XXX |
42 | default y if ARCH_VT8500 | 43 | default y if ARCH_VT8500 |
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c index caecad9213f5..8e9d31277c43 100644 --- a/drivers/usb/chipidea/host.c +++ b/drivers/usb/chipidea/host.c | |||
@@ -70,6 +70,9 @@ static int host_start(struct ci13xxx *ci) | |||
70 | else | 70 | else |
71 | ci->hcd = hcd; | 71 | ci->hcd = hcd; |
72 | 72 | ||
73 | if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING) | ||
74 | hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS); | ||
75 | |||
73 | return ret; | 76 | return ret; |
74 | } | 77 | } |
75 | 78 | ||
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 8d809a811e16..2d92cce260d7 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
@@ -1602,6 +1602,9 @@ static const struct usb_device_id acm_ids[] = { | |||
1602 | { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ | 1602 | { USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */ |
1603 | .driver_info = NO_UNION_NORMAL, | 1603 | .driver_info = NO_UNION_NORMAL, |
1604 | }, | 1604 | }, |
1605 | { USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */ | ||
1606 | .driver_info = NO_UNION_NORMAL, | ||
1607 | }, | ||
1605 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ | 1608 | { USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */ |
1606 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ | 1609 | .driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */ |
1607 | }, | 1610 | }, |
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index 4225d5e72131..8e64adf8e4d5 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c | |||
@@ -39,6 +39,7 @@ | |||
39 | #include <asm/unaligned.h> | 39 | #include <asm/unaligned.h> |
40 | #include <linux/platform_device.h> | 40 | #include <linux/platform_device.h> |
41 | #include <linux/workqueue.h> | 41 | #include <linux/workqueue.h> |
42 | #include <linux/pm_runtime.h> | ||
42 | 43 | ||
43 | #include <linux/usb.h> | 44 | #include <linux/usb.h> |
44 | #include <linux/usb/hcd.h> | 45 | #include <linux/usb/hcd.h> |
@@ -1025,6 +1026,49 @@ static int register_root_hub(struct usb_hcd *hcd) | |||
1025 | return retval; | 1026 | return retval; |
1026 | } | 1027 | } |
1027 | 1028 | ||
1029 | /* | ||
1030 | * usb_hcd_start_port_resume - a root-hub port is sending a resume signal | ||
1031 | * @bus: the bus which the root hub belongs to | ||
1032 | * @portnum: the port which is being resumed | ||
1033 | * | ||
1034 | * HCDs should call this function when they know that a resume signal is | ||
1035 | * being sent to a root-hub port. The root hub will be prevented from | ||
1036 | * going into autosuspend until usb_hcd_end_port_resume() is called. | ||
1037 | * | ||
1038 | * The bus's private lock must be held by the caller. | ||
1039 | */ | ||
1040 | void usb_hcd_start_port_resume(struct usb_bus *bus, int portnum) | ||
1041 | { | ||
1042 | unsigned bit = 1 << portnum; | ||
1043 | |||
1044 | if (!(bus->resuming_ports & bit)) { | ||
1045 | bus->resuming_ports |= bit; | ||
1046 | pm_runtime_get_noresume(&bus->root_hub->dev); | ||
1047 | } | ||
1048 | } | ||
1049 | EXPORT_SYMBOL_GPL(usb_hcd_start_port_resume); | ||
1050 | |||
1051 | /* | ||
1052 | * usb_hcd_end_port_resume - a root-hub port has stopped sending a resume signal | ||
1053 | * @bus: the bus which the root hub belongs to | ||
1054 | * @portnum: the port which is being resumed | ||
1055 | * | ||
1056 | * HCDs should call this function when they know that a resume signal has | ||
1057 | * stopped being sent to a root-hub port. The root hub will be allowed to | ||
1058 | * autosuspend again. | ||
1059 | * | ||
1060 | * The bus's private lock must be held by the caller. | ||
1061 | */ | ||
1062 | void usb_hcd_end_port_resume(struct usb_bus *bus, int portnum) | ||
1063 | { | ||
1064 | unsigned bit = 1 << portnum; | ||
1065 | |||
1066 | if (bus->resuming_ports & bit) { | ||
1067 | bus->resuming_ports &= ~bit; | ||
1068 | pm_runtime_put_noidle(&bus->root_hub->dev); | ||
1069 | } | ||
1070 | } | ||
1071 | EXPORT_SYMBOL_GPL(usb_hcd_end_port_resume); | ||
1028 | 1072 | ||
1029 | /*-------------------------------------------------------------------------*/ | 1073 | /*-------------------------------------------------------------------------*/ |
1030 | 1074 | ||
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a815fd2cc5e7..cbf7168e3ce7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c | |||
@@ -877,6 +877,60 @@ static int hub_hub_status(struct usb_hub *hub, | |||
877 | return ret; | 877 | return ret; |
878 | } | 878 | } |
879 | 879 | ||
880 | static int hub_set_port_link_state(struct usb_hub *hub, int port1, | ||
881 | unsigned int link_status) | ||
882 | { | ||
883 | return set_port_feature(hub->hdev, | ||
884 | port1 | (link_status << 3), | ||
885 | USB_PORT_FEAT_LINK_STATE); | ||
886 | } | ||
887 | |||
888 | /* | ||
889 | * If USB 3.0 ports are placed into the Disabled state, they will no longer | ||
890 | * detect any device connects or disconnects. This is generally not what the | ||
891 | * USB core wants, since it expects a disabled port to produce a port status | ||
892 | * change event when a new device connects. | ||
893 | * | ||
894 | * Instead, set the link state to Disabled, wait for the link to settle into | ||
895 | * that state, clear any change bits, and then put the port into the RxDetect | ||
896 | * state. | ||
897 | */ | ||
898 | static int hub_usb3_port_disable(struct usb_hub *hub, int port1) | ||
899 | { | ||
900 | int ret; | ||
901 | int total_time; | ||
902 | u16 portchange, portstatus; | ||
903 | |||
904 | if (!hub_is_superspeed(hub->hdev)) | ||
905 | return -EINVAL; | ||
906 | |||
907 | ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED); | ||
908 | if (ret) { | ||
909 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", | ||
910 | port1, ret); | ||
911 | return ret; | ||
912 | } | ||
913 | |||
914 | /* Wait for the link to enter the disabled state. */ | ||
915 | for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) { | ||
916 | ret = hub_port_status(hub, port1, &portstatus, &portchange); | ||
917 | if (ret < 0) | ||
918 | return ret; | ||
919 | |||
920 | if ((portstatus & USB_PORT_STAT_LINK_STATE) == | ||
921 | USB_SS_PORT_LS_SS_DISABLED) | ||
922 | break; | ||
923 | if (total_time >= HUB_DEBOUNCE_TIMEOUT) | ||
924 | break; | ||
925 | msleep(HUB_DEBOUNCE_STEP); | ||
926 | } | ||
927 | if (total_time >= HUB_DEBOUNCE_TIMEOUT) | ||
928 | dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n", | ||
929 | port1, total_time); | ||
930 | |||
931 | return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT); | ||
932 | } | ||
933 | |||
880 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | 934 | static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) |
881 | { | 935 | { |
882 | struct usb_device *hdev = hub->hdev; | 936 | struct usb_device *hdev = hub->hdev; |
@@ -885,8 +939,13 @@ static int hub_port_disable(struct usb_hub *hub, int port1, int set_state) | |||
885 | if (hub->ports[port1 - 1]->child && set_state) | 939 | if (hub->ports[port1 - 1]->child && set_state) |
886 | usb_set_device_state(hub->ports[port1 - 1]->child, | 940 | usb_set_device_state(hub->ports[port1 - 1]->child, |
887 | USB_STATE_NOTATTACHED); | 941 | USB_STATE_NOTATTACHED); |
888 | if (!hub->error && !hub_is_superspeed(hub->hdev)) | 942 | if (!hub->error) { |
889 | ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE); | 943 | if (hub_is_superspeed(hub->hdev)) |
944 | ret = hub_usb3_port_disable(hub, port1); | ||
945 | else | ||
946 | ret = clear_port_feature(hdev, port1, | ||
947 | USB_PORT_FEAT_ENABLE); | ||
948 | } | ||
890 | if (ret) | 949 | if (ret) |
891 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", | 950 | dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n", |
892 | port1, ret); | 951 | port1, ret); |
@@ -2440,7 +2499,7 @@ static unsigned hub_is_wusb(struct usb_hub *hub) | |||
2440 | #define HUB_SHORT_RESET_TIME 10 | 2499 | #define HUB_SHORT_RESET_TIME 10 |
2441 | #define HUB_BH_RESET_TIME 50 | 2500 | #define HUB_BH_RESET_TIME 50 |
2442 | #define HUB_LONG_RESET_TIME 200 | 2501 | #define HUB_LONG_RESET_TIME 200 |
2443 | #define HUB_RESET_TIMEOUT 500 | 2502 | #define HUB_RESET_TIMEOUT 800 |
2444 | 2503 | ||
2445 | static int hub_port_reset(struct usb_hub *hub, int port1, | 2504 | static int hub_port_reset(struct usb_hub *hub, int port1, |
2446 | struct usb_device *udev, unsigned int delay, bool warm); | 2505 | struct usb_device *udev, unsigned int delay, bool warm); |
@@ -2475,6 +2534,10 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2475 | if (ret < 0) | 2534 | if (ret < 0) |
2476 | return ret; | 2535 | return ret; |
2477 | 2536 | ||
2537 | /* The port state is unknown until the reset completes. */ | ||
2538 | if ((portstatus & USB_PORT_STAT_RESET)) | ||
2539 | goto delay; | ||
2540 | |||
2478 | /* | 2541 | /* |
2479 | * Some buggy devices require a warm reset to be issued even | 2542 | * Some buggy devices require a warm reset to be issued even |
2480 | * when the port appears not to be connected. | 2543 | * when the port appears not to be connected. |
@@ -2520,11 +2583,7 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2520 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) | 2583 | if ((portchange & USB_PORT_STAT_C_CONNECTION)) |
2521 | return -ENOTCONN; | 2584 | return -ENOTCONN; |
2522 | 2585 | ||
2523 | /* if we`ve finished resetting, then break out of | 2586 | if ((portstatus & USB_PORT_STAT_ENABLE)) { |
2524 | * the loop | ||
2525 | */ | ||
2526 | if (!(portstatus & USB_PORT_STAT_RESET) && | ||
2527 | (portstatus & USB_PORT_STAT_ENABLE)) { | ||
2528 | if (hub_is_wusb(hub)) | 2587 | if (hub_is_wusb(hub)) |
2529 | udev->speed = USB_SPEED_WIRELESS; | 2588 | udev->speed = USB_SPEED_WIRELESS; |
2530 | else if (hub_is_superspeed(hub->hdev)) | 2589 | else if (hub_is_superspeed(hub->hdev)) |
@@ -2538,10 +2597,15 @@ static int hub_port_wait_reset(struct usb_hub *hub, int port1, | |||
2538 | return 0; | 2597 | return 0; |
2539 | } | 2598 | } |
2540 | } else { | 2599 | } else { |
2541 | if (portchange & USB_PORT_STAT_C_BH_RESET) | 2600 | if (!(portstatus & USB_PORT_STAT_CONNECTION) || |
2542 | return 0; | 2601 | hub_port_warm_reset_required(hub, |
2602 | portstatus)) | ||
2603 | return -ENOTCONN; | ||
2604 | |||
2605 | return 0; | ||
2543 | } | 2606 | } |
2544 | 2607 | ||
2608 | delay: | ||
2545 | /* switch to the long delay after two short delay failures */ | 2609 | /* switch to the long delay after two short delay failures */ |
2546 | if (delay_time >= 2 * HUB_SHORT_RESET_TIME) | 2610 | if (delay_time >= 2 * HUB_SHORT_RESET_TIME) |
2547 | delay = HUB_LONG_RESET_TIME; | 2611 | delay = HUB_LONG_RESET_TIME; |
@@ -2565,14 +2629,11 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, | |||
2565 | msleep(10 + 40); | 2629 | msleep(10 + 40); |
2566 | update_devnum(udev, 0); | 2630 | update_devnum(udev, 0); |
2567 | hcd = bus_to_hcd(udev->bus); | 2631 | hcd = bus_to_hcd(udev->bus); |
2568 | if (hcd->driver->reset_device) { | 2632 | /* The xHC may think the device is already reset, |
2569 | *status = hcd->driver->reset_device(hcd, udev); | 2633 | * so ignore the status. |
2570 | if (*status < 0) { | 2634 | */ |
2571 | dev_err(&udev->dev, "Cannot reset " | 2635 | if (hcd->driver->reset_device) |
2572 | "HCD device state\n"); | 2636 | hcd->driver->reset_device(hcd, udev); |
2573 | break; | ||
2574 | } | ||
2575 | } | ||
2576 | } | 2637 | } |
2577 | /* FALL THROUGH */ | 2638 | /* FALL THROUGH */ |
2578 | case -ENOTCONN: | 2639 | case -ENOTCONN: |
@@ -2580,16 +2641,16 @@ static void hub_port_finish_reset(struct usb_hub *hub, int port1, | |||
2580 | clear_port_feature(hub->hdev, | 2641 | clear_port_feature(hub->hdev, |
2581 | port1, USB_PORT_FEAT_C_RESET); | 2642 | port1, USB_PORT_FEAT_C_RESET); |
2582 | /* FIXME need disconnect() for NOTATTACHED device */ | 2643 | /* FIXME need disconnect() for NOTATTACHED device */ |
2583 | if (warm) { | 2644 | if (hub_is_superspeed(hub->hdev)) { |
2584 | clear_port_feature(hub->hdev, port1, | 2645 | clear_port_feature(hub->hdev, port1, |
2585 | USB_PORT_FEAT_C_BH_PORT_RESET); | 2646 | USB_PORT_FEAT_C_BH_PORT_RESET); |
2586 | clear_port_feature(hub->hdev, port1, | 2647 | clear_port_feature(hub->hdev, port1, |
2587 | USB_PORT_FEAT_C_PORT_LINK_STATE); | 2648 | USB_PORT_FEAT_C_PORT_LINK_STATE); |
2588 | } else { | 2649 | } |
2650 | if (!warm) | ||
2589 | usb_set_device_state(udev, *status | 2651 | usb_set_device_state(udev, *status |
2590 | ? USB_STATE_NOTATTACHED | 2652 | ? USB_STATE_NOTATTACHED |
2591 | : USB_STATE_DEFAULT); | 2653 | : USB_STATE_DEFAULT); |
2592 | } | ||
2593 | break; | 2654 | break; |
2594 | } | 2655 | } |
2595 | } | 2656 | } |
@@ -2777,6 +2838,23 @@ void usb_enable_ltm(struct usb_device *udev) | |||
2777 | EXPORT_SYMBOL_GPL(usb_enable_ltm); | 2838 | EXPORT_SYMBOL_GPL(usb_enable_ltm); |
2778 | 2839 | ||
2779 | #ifdef CONFIG_USB_SUSPEND | 2840 | #ifdef CONFIG_USB_SUSPEND |
2841 | /* | ||
2842 | * usb_disable_function_remotewakeup - disable usb3.0 | ||
2843 | * device's function remote wakeup | ||
2844 | * @udev: target device | ||
2845 | * | ||
2846 | * Assume there's only one function on the USB 3.0 | ||
2847 | * device and disable remote wake for the first | ||
2848 | * interface. FIXME if the interface association | ||
2849 | * descriptor shows there's more than one function. | ||
2850 | */ | ||
2851 | static int usb_disable_function_remotewakeup(struct usb_device *udev) | ||
2852 | { | ||
2853 | return usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | ||
2854 | USB_REQ_CLEAR_FEATURE, USB_RECIP_INTERFACE, | ||
2855 | USB_INTRF_FUNC_SUSPEND, 0, NULL, 0, | ||
2856 | USB_CTRL_SET_TIMEOUT); | ||
2857 | } | ||
2780 | 2858 | ||
2781 | /* | 2859 | /* |
2782 | * usb_port_suspend - suspend a usb device's upstream port | 2860 | * usb_port_suspend - suspend a usb device's upstream port |
@@ -2894,12 +2972,19 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2894 | dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", | 2972 | dev_dbg(hub->intfdev, "can't suspend port %d, status %d\n", |
2895 | port1, status); | 2973 | port1, status); |
2896 | /* paranoia: "should not happen" */ | 2974 | /* paranoia: "should not happen" */ |
2897 | if (udev->do_remote_wakeup) | 2975 | if (udev->do_remote_wakeup) { |
2898 | (void) usb_control_msg(udev, usb_sndctrlpipe(udev, 0), | 2976 | if (!hub_is_superspeed(hub->hdev)) { |
2899 | USB_REQ_CLEAR_FEATURE, USB_RECIP_DEVICE, | 2977 | (void) usb_control_msg(udev, |
2900 | USB_DEVICE_REMOTE_WAKEUP, 0, | 2978 | usb_sndctrlpipe(udev, 0), |
2901 | NULL, 0, | 2979 | USB_REQ_CLEAR_FEATURE, |
2902 | USB_CTRL_SET_TIMEOUT); | 2980 | USB_RECIP_DEVICE, |
2981 | USB_DEVICE_REMOTE_WAKEUP, 0, | ||
2982 | NULL, 0, | ||
2983 | USB_CTRL_SET_TIMEOUT); | ||
2984 | } else | ||
2985 | (void) usb_disable_function_remotewakeup(udev); | ||
2986 | |||
2987 | } | ||
2903 | 2988 | ||
2904 | /* Try to enable USB2 hardware LPM again */ | 2989 | /* Try to enable USB2 hardware LPM again */ |
2905 | if (udev->usb2_hw_lpm_capable == 1) | 2990 | if (udev->usb2_hw_lpm_capable == 1) |
@@ -2939,7 +3024,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) | |||
2939 | static int finish_port_resume(struct usb_device *udev) | 3024 | static int finish_port_resume(struct usb_device *udev) |
2940 | { | 3025 | { |
2941 | int status = 0; | 3026 | int status = 0; |
2942 | u16 devstatus; | 3027 | u16 devstatus = 0; |
2943 | 3028 | ||
2944 | /* caller owns the udev device lock */ | 3029 | /* caller owns the udev device lock */ |
2945 | dev_dbg(&udev->dev, "%s\n", | 3030 | dev_dbg(&udev->dev, "%s\n", |
@@ -2984,21 +3069,37 @@ static int finish_port_resume(struct usb_device *udev) | |||
2984 | if (status) { | 3069 | if (status) { |
2985 | dev_dbg(&udev->dev, "gone after usb resume? status %d\n", | 3070 | dev_dbg(&udev->dev, "gone after usb resume? status %d\n", |
2986 | status); | 3071 | status); |
2987 | } else if (udev->actconfig) { | 3072 | /* |
2988 | le16_to_cpus(&devstatus); | 3073 | * There are a few quirky devices which violate the standard |
2989 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) { | 3074 | * by claiming to have remote wakeup enabled after a reset, |
2990 | status = usb_control_msg(udev, | 3075 | * which crash if the feature is cleared, hence check for |
2991 | usb_sndctrlpipe(udev, 0), | 3076 | * udev->reset_resume |
2992 | USB_REQ_CLEAR_FEATURE, | 3077 | */ |
3078 | } else if (udev->actconfig && !udev->reset_resume) { | ||
3079 | if (!hub_is_superspeed(udev->parent)) { | ||
3080 | le16_to_cpus(&devstatus); | ||
3081 | if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) | ||
3082 | status = usb_control_msg(udev, | ||
3083 | usb_sndctrlpipe(udev, 0), | ||
3084 | USB_REQ_CLEAR_FEATURE, | ||
2993 | USB_RECIP_DEVICE, | 3085 | USB_RECIP_DEVICE, |
2994 | USB_DEVICE_REMOTE_WAKEUP, 0, | 3086 | USB_DEVICE_REMOTE_WAKEUP, 0, |
2995 | NULL, 0, | 3087 | NULL, 0, |
2996 | USB_CTRL_SET_TIMEOUT); | 3088 | USB_CTRL_SET_TIMEOUT); |
2997 | if (status) | 3089 | } else { |
2998 | dev_dbg(&udev->dev, | 3090 | status = usb_get_status(udev, USB_RECIP_INTERFACE, 0, |
2999 | "disable remote wakeup, status %d\n", | 3091 | &devstatus); |
3000 | status); | 3092 | le16_to_cpus(&devstatus); |
3093 | if (!status && devstatus & (USB_INTRF_STAT_FUNC_RW_CAP | ||
3094 | | USB_INTRF_STAT_FUNC_RW)) | ||
3095 | status = | ||
3096 | usb_disable_function_remotewakeup(udev); | ||
3001 | } | 3097 | } |
3098 | |||
3099 | if (status) | ||
3100 | dev_dbg(&udev->dev, | ||
3101 | "disable remote wakeup, status %d\n", | ||
3102 | status); | ||
3002 | status = 0; | 3103 | status = 0; |
3003 | } | 3104 | } |
3004 | return status; | 3105 | return status; |
@@ -4638,9 +4739,14 @@ static void hub_events(void) | |||
4638 | * SS.Inactive state. | 4739 | * SS.Inactive state. |
4639 | */ | 4740 | */ |
4640 | if (hub_port_warm_reset_required(hub, portstatus)) { | 4741 | if (hub_port_warm_reset_required(hub, portstatus)) { |
4742 | int status; | ||
4743 | |||
4641 | dev_dbg(hub_dev, "warm reset port %d\n", i); | 4744 | dev_dbg(hub_dev, "warm reset port %d\n", i); |
4642 | hub_port_reset(hub, i, NULL, | 4745 | status = hub_port_reset(hub, i, NULL, |
4643 | HUB_BH_RESET_TIME, true); | 4746 | HUB_BH_RESET_TIME, true); |
4747 | if (status < 0) | ||
4748 | hub_port_disable(hub, i, 1); | ||
4749 | connect_change = 0; | ||
4644 | } | 4750 | } |
4645 | 4751 | ||
4646 | if (connect_change) | 4752 | if (connect_change) |
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index fdefd9c7f7af..3113c1d71442 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c | |||
@@ -43,6 +43,9 @@ static const struct usb_device_id usb_quirk_list[] = { | |||
43 | /* Creative SB Audigy 2 NX */ | 43 | /* Creative SB Audigy 2 NX */ |
44 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, | 44 | { USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME }, |
45 | 45 | ||
46 | /* Microsoft LifeCam-VX700 v2.0 */ | ||
47 | { USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME }, | ||
48 | |||
46 | /* Logitech Quickcam Fusion */ | 49 | /* Logitech Quickcam Fusion */ |
47 | { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, | 50 | { USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME }, |
48 | 51 | ||
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c index 92604b4f9712..5945aadaa1c9 100644 --- a/drivers/usb/dwc3/debugfs.c +++ b/drivers/usb/dwc3/debugfs.c | |||
@@ -56,7 +56,7 @@ | |||
56 | #define dump_register(nm) \ | 56 | #define dump_register(nm) \ |
57 | { \ | 57 | { \ |
58 | .name = __stringify(nm), \ | 58 | .name = __stringify(nm), \ |
59 | .offset = DWC3_ ##nm, \ | 59 | .offset = DWC3_ ##nm - DWC3_GLOBALS_REGS_START, \ |
60 | } | 60 | } |
61 | 61 | ||
62 | static const struct debugfs_reg32 dwc3_regs[] = { | 62 | static const struct debugfs_reg32 dwc3_regs[] = { |
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 2e43b332aae8..2fdd767f8fe8 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -1605,6 +1605,7 @@ static int dwc3_gadget_init_endpoints(struct dwc3 *dwc) | |||
1605 | 1605 | ||
1606 | if (epnum == 0 || epnum == 1) { | 1606 | if (epnum == 0 || epnum == 1) { |
1607 | dep->endpoint.maxpacket = 512; | 1607 | dep->endpoint.maxpacket = 512; |
1608 | dep->endpoint.maxburst = 1; | ||
1608 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; | 1609 | dep->endpoint.ops = &dwc3_gadget_ep0_ops; |
1609 | if (!epnum) | 1610 | if (!epnum) |
1610 | dwc->gadget.ep0 = &dep->endpoint; | 1611 | dwc->gadget.ep0 = &dep->endpoint; |
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c index fc0ec5e0d58e..d9f6b9372491 100644 --- a/drivers/usb/gadget/amd5536udc.c +++ b/drivers/usb/gadget/amd5536udc.c | |||
@@ -3231,7 +3231,7 @@ static int udc_pci_probe( | |||
3231 | } | 3231 | } |
3232 | 3232 | ||
3233 | if (!pdev->irq) { | 3233 | if (!pdev->irq) { |
3234 | dev_err(&dev->pdev->dev, "irq not set\n"); | 3234 | dev_err(&pdev->dev, "irq not set\n"); |
3235 | kfree(dev); | 3235 | kfree(dev); |
3236 | dev = NULL; | 3236 | dev = NULL; |
3237 | retval = -ENODEV; | 3237 | retval = -ENODEV; |
@@ -3250,7 +3250,7 @@ static int udc_pci_probe( | |||
3250 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); | 3250 | dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR); |
3251 | 3251 | ||
3252 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { | 3252 | if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) { |
3253 | dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq); | 3253 | dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq); |
3254 | kfree(dev); | 3254 | kfree(dev); |
3255 | dev = NULL; | 3255 | dev = NULL; |
3256 | retval = -EBUSY; | 3256 | retval = -EBUSY; |
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c index 95d584dbed13..8cf0c0f6fa1f 100644 --- a/drivers/usb/gadget/dummy_hcd.c +++ b/drivers/usb/gadget/dummy_hcd.c | |||
@@ -130,10 +130,7 @@ static const char ep0name[] = "ep0"; | |||
130 | static const char *const ep_name[] = { | 130 | static const char *const ep_name[] = { |
131 | ep0name, /* everyone has ep0 */ | 131 | ep0name, /* everyone has ep0 */ |
132 | 132 | ||
133 | /* act like a net2280: high speed, six configurable endpoints */ | 133 | /* act like a pxa250: fifteen fixed function endpoints */ |
134 | "ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f", | ||
135 | |||
136 | /* or like pxa250: fifteen fixed function endpoints */ | ||
137 | "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", | 134 | "ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int", |
138 | "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", | 135 | "ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int", |
139 | "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", | 136 | "ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso", |
@@ -141,6 +138,10 @@ static const char *const ep_name[] = { | |||
141 | 138 | ||
142 | /* or like sa1100: two fixed function endpoints */ | 139 | /* or like sa1100: two fixed function endpoints */ |
143 | "ep1out-bulk", "ep2in-bulk", | 140 | "ep1out-bulk", "ep2in-bulk", |
141 | |||
142 | /* and now some generic EPs so we have enough in multi config */ | ||
143 | "ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in", | ||
144 | "ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out", | ||
144 | }; | 145 | }; |
145 | #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) | 146 | #define DUMMY_ENDPOINTS ARRAY_SIZE(ep_name) |
146 | 147 | ||
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c index 4a6961c517f2..8c2f25121149 100644 --- a/drivers/usb/gadget/f_fs.c +++ b/drivers/usb/gadget/f_fs.c | |||
@@ -1153,15 +1153,15 @@ static int ffs_fs_parse_opts(struct ffs_sb_fill_data *data, char *opts) | |||
1153 | pr_err("%s: unmapped value: %lu\n", opts, value); | 1153 | pr_err("%s: unmapped value: %lu\n", opts, value); |
1154 | return -EINVAL; | 1154 | return -EINVAL; |
1155 | } | 1155 | } |
1156 | } | 1156 | } else if (!memcmp(opts, "gid", 3)) { |
1157 | else if (!memcmp(opts, "gid", 3)) | ||
1158 | data->perms.gid = make_kgid(current_user_ns(), value); | 1157 | data->perms.gid = make_kgid(current_user_ns(), value); |
1159 | if (!gid_valid(data->perms.gid)) { | 1158 | if (!gid_valid(data->perms.gid)) { |
1160 | pr_err("%s: unmapped value: %lu\n", opts, value); | 1159 | pr_err("%s: unmapped value: %lu\n", opts, value); |
1161 | return -EINVAL; | 1160 | return -EINVAL; |
1162 | } | 1161 | } |
1163 | else | 1162 | } else { |
1164 | goto invalid; | 1163 | goto invalid; |
1164 | } | ||
1165 | break; | 1165 | break; |
1166 | 1166 | ||
1167 | default: | 1167 | default: |
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c index 1b0f086426bd..d3bd7b095ba3 100644 --- a/drivers/usb/gadget/fsl_mxc_udc.c +++ b/drivers/usb/gadget/fsl_mxc_udc.c | |||
@@ -18,14 +18,13 @@ | |||
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | 20 | ||
21 | #include <mach/hardware.h> | ||
22 | |||
23 | static struct clk *mxc_ahb_clk; | 21 | static struct clk *mxc_ahb_clk; |
24 | static struct clk *mxc_per_clk; | 22 | static struct clk *mxc_per_clk; |
25 | static struct clk *mxc_ipg_clk; | 23 | static struct clk *mxc_ipg_clk; |
26 | 24 | ||
27 | /* workaround ENGcm09152 for i.MX35 */ | 25 | /* workaround ENGcm09152 for i.MX35 */ |
28 | #define USBPHYCTRL_OTGBASE_OFFSET 0x608 | 26 | #define MX35_USBPHYCTRL_OFFSET 0x600 |
27 | #define USBPHYCTRL_OTGBASE_OFFSET 0x8 | ||
29 | #define USBPHYCTRL_EVDO (1 << 23) | 28 | #define USBPHYCTRL_EVDO (1 << 23) |
30 | 29 | ||
31 | int fsl_udc_clk_init(struct platform_device *pdev) | 30 | int fsl_udc_clk_init(struct platform_device *pdev) |
@@ -59,7 +58,7 @@ int fsl_udc_clk_init(struct platform_device *pdev) | |||
59 | clk_prepare_enable(mxc_per_clk); | 58 | clk_prepare_enable(mxc_per_clk); |
60 | 59 | ||
61 | /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ | 60 | /* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */ |
62 | if (!cpu_is_mx51()) { | 61 | if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) { |
63 | freq = clk_get_rate(mxc_per_clk); | 62 | freq = clk_get_rate(mxc_per_clk); |
64 | if (pdata->phy_mode != FSL_USB2_PHY_ULPI && | 63 | if (pdata->phy_mode != FSL_USB2_PHY_ULPI && |
65 | (freq < 59999000 || freq > 60001000)) { | 64 | (freq < 59999000 || freq > 60001000)) { |
@@ -79,27 +78,40 @@ eclkrate: | |||
79 | return ret; | 78 | return ret; |
80 | } | 79 | } |
81 | 80 | ||
82 | void fsl_udc_clk_finalize(struct platform_device *pdev) | 81 | int fsl_udc_clk_finalize(struct platform_device *pdev) |
83 | { | 82 | { |
84 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; | 83 | struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data; |
85 | if (cpu_is_mx35()) { | 84 | int ret = 0; |
86 | unsigned int v; | ||
87 | 85 | ||
88 | /* workaround ENGcm09152 for i.MX35 */ | 86 | /* workaround ENGcm09152 for i.MX35 */ |
89 | if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { | 87 | if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) { |
90 | v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + | 88 | unsigned int v; |
91 | USBPHYCTRL_OTGBASE_OFFSET)); | 89 | struct resource *res = platform_get_resource |
92 | writel(v | USBPHYCTRL_EVDO, | 90 | (pdev, IORESOURCE_MEM, 0); |
93 | MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + | 91 | void __iomem *phy_regs = ioremap(res->start + |
94 | USBPHYCTRL_OTGBASE_OFFSET)); | 92 | MX35_USBPHYCTRL_OFFSET, 512); |
93 | if (!phy_regs) { | ||
94 | dev_err(&pdev->dev, "ioremap for phy address fails\n"); | ||
95 | ret = -EINVAL; | ||
96 | goto ioremap_err; | ||
95 | } | 97 | } |
98 | |||
99 | v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET); | ||
100 | writel(v | USBPHYCTRL_EVDO, | ||
101 | phy_regs + USBPHYCTRL_OTGBASE_OFFSET); | ||
102 | |||
103 | iounmap(phy_regs); | ||
96 | } | 104 | } |
97 | 105 | ||
106 | |||
107 | ioremap_err: | ||
98 | /* ULPI transceivers don't need usbpll */ | 108 | /* ULPI transceivers don't need usbpll */ |
99 | if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { | 109 | if (pdata->phy_mode == FSL_USB2_PHY_ULPI) { |
100 | clk_disable_unprepare(mxc_per_clk); | 110 | clk_disable_unprepare(mxc_per_clk); |
101 | mxc_per_clk = NULL; | 111 | mxc_per_clk = NULL; |
102 | } | 112 | } |
113 | |||
114 | return ret; | ||
103 | } | 115 | } |
104 | 116 | ||
105 | void fsl_udc_clk_release(void) | 117 | void fsl_udc_clk_release(void) |
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c index c19f7f13790b..667275cb7bad 100644 --- a/drivers/usb/gadget/fsl_udc_core.c +++ b/drivers/usb/gadget/fsl_udc_core.c | |||
@@ -41,6 +41,7 @@ | |||
41 | #include <linux/fsl_devices.h> | 41 | #include <linux/fsl_devices.h> |
42 | #include <linux/dmapool.h> | 42 | #include <linux/dmapool.h> |
43 | #include <linux/delay.h> | 43 | #include <linux/delay.h> |
44 | #include <linux/of_device.h> | ||
44 | 45 | ||
45 | #include <asm/byteorder.h> | 46 | #include <asm/byteorder.h> |
46 | #include <asm/io.h> | 47 | #include <asm/io.h> |
@@ -2438,11 +2439,6 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2438 | unsigned int i; | 2439 | unsigned int i; |
2439 | u32 dccparams; | 2440 | u32 dccparams; |
2440 | 2441 | ||
2441 | if (strcmp(pdev->name, driver_name)) { | ||
2442 | VDBG("Wrong device"); | ||
2443 | return -ENODEV; | ||
2444 | } | ||
2445 | |||
2446 | udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); | 2442 | udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL); |
2447 | if (udc_controller == NULL) { | 2443 | if (udc_controller == NULL) { |
2448 | ERR("malloc udc failed\n"); | 2444 | ERR("malloc udc failed\n"); |
@@ -2547,7 +2543,9 @@ static int __init fsl_udc_probe(struct platform_device *pdev) | |||
2547 | dr_controller_setup(udc_controller); | 2543 | dr_controller_setup(udc_controller); |
2548 | } | 2544 | } |
2549 | 2545 | ||
2550 | fsl_udc_clk_finalize(pdev); | 2546 | ret = fsl_udc_clk_finalize(pdev); |
2547 | if (ret) | ||
2548 | goto err_free_irq; | ||
2551 | 2549 | ||
2552 | /* Setup gadget structure */ | 2550 | /* Setup gadget structure */ |
2553 | udc_controller->gadget.ops = &fsl_gadget_ops; | 2551 | udc_controller->gadget.ops = &fsl_gadget_ops; |
@@ -2756,22 +2754,32 @@ static int fsl_udc_otg_resume(struct device *dev) | |||
2756 | 2754 | ||
2757 | return fsl_udc_resume(NULL); | 2755 | return fsl_udc_resume(NULL); |
2758 | } | 2756 | } |
2759 | |||
2760 | /*------------------------------------------------------------------------- | 2757 | /*------------------------------------------------------------------------- |
2761 | Register entry point for the peripheral controller driver | 2758 | Register entry point for the peripheral controller driver |
2762 | --------------------------------------------------------------------------*/ | 2759 | --------------------------------------------------------------------------*/ |
2763 | 2760 | static const struct platform_device_id fsl_udc_devtype[] = { | |
2761 | { | ||
2762 | .name = "imx-udc-mx27", | ||
2763 | }, { | ||
2764 | .name = "imx-udc-mx51", | ||
2765 | }, { | ||
2766 | /* sentinel */ | ||
2767 | } | ||
2768 | }; | ||
2769 | MODULE_DEVICE_TABLE(platform, fsl_udc_devtype); | ||
2764 | static struct platform_driver udc_driver = { | 2770 | static struct platform_driver udc_driver = { |
2765 | .remove = __exit_p(fsl_udc_remove), | 2771 | .remove = __exit_p(fsl_udc_remove), |
2772 | /* Just for FSL i.mx SoC currently */ | ||
2773 | .id_table = fsl_udc_devtype, | ||
2766 | /* these suspend and resume are not usb suspend and resume */ | 2774 | /* these suspend and resume are not usb suspend and resume */ |
2767 | .suspend = fsl_udc_suspend, | 2775 | .suspend = fsl_udc_suspend, |
2768 | .resume = fsl_udc_resume, | 2776 | .resume = fsl_udc_resume, |
2769 | .driver = { | 2777 | .driver = { |
2770 | .name = (char *)driver_name, | 2778 | .name = (char *)driver_name, |
2771 | .owner = THIS_MODULE, | 2779 | .owner = THIS_MODULE, |
2772 | /* udc suspend/resume called from OTG driver */ | 2780 | /* udc suspend/resume called from OTG driver */ |
2773 | .suspend = fsl_udc_otg_suspend, | 2781 | .suspend = fsl_udc_otg_suspend, |
2774 | .resume = fsl_udc_otg_resume, | 2782 | .resume = fsl_udc_otg_resume, |
2775 | }, | 2783 | }, |
2776 | }; | 2784 | }; |
2777 | 2785 | ||
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h index f61a967f7082..c6703bb07b23 100644 --- a/drivers/usb/gadget/fsl_usb2_udc.h +++ b/drivers/usb/gadget/fsl_usb2_udc.h | |||
@@ -592,15 +592,16 @@ static inline struct ep_queue_head *get_qh_by_ep(struct fsl_ep *ep) | |||
592 | struct platform_device; | 592 | struct platform_device; |
593 | #ifdef CONFIG_ARCH_MXC | 593 | #ifdef CONFIG_ARCH_MXC |
594 | int fsl_udc_clk_init(struct platform_device *pdev); | 594 | int fsl_udc_clk_init(struct platform_device *pdev); |
595 | void fsl_udc_clk_finalize(struct platform_device *pdev); | 595 | int fsl_udc_clk_finalize(struct platform_device *pdev); |
596 | void fsl_udc_clk_release(void); | 596 | void fsl_udc_clk_release(void); |
597 | #else | 597 | #else |
598 | static inline int fsl_udc_clk_init(struct platform_device *pdev) | 598 | static inline int fsl_udc_clk_init(struct platform_device *pdev) |
599 | { | 599 | { |
600 | return 0; | 600 | return 0; |
601 | } | 601 | } |
602 | static inline void fsl_udc_clk_finalize(struct platform_device *pdev) | 602 | static inline int fsl_udc_clk_finalize(struct platform_device *pdev) |
603 | { | 603 | { |
604 | return 0; | ||
604 | } | 605 | } |
605 | static inline void fsl_udc_clk_release(void) | 606 | static inline void fsl_udc_clk_release(void) |
606 | { | 607 | { |
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c index 379aac7b82fc..6e8b1272ebce 100644 --- a/drivers/usb/gadget/mv_udc_core.c +++ b/drivers/usb/gadget/mv_udc_core.c | |||
@@ -1012,7 +1012,7 @@ static void udc_clock_enable(struct mv_udc *udc) | |||
1012 | unsigned int i; | 1012 | unsigned int i; |
1013 | 1013 | ||
1014 | for (i = 0; i < udc->clknum; i++) | 1014 | for (i = 0; i < udc->clknum; i++) |
1015 | clk_enable(udc->clk[i]); | 1015 | clk_prepare_enable(udc->clk[i]); |
1016 | } | 1016 | } |
1017 | 1017 | ||
1018 | static void udc_clock_disable(struct mv_udc *udc) | 1018 | static void udc_clock_disable(struct mv_udc *udc) |
@@ -1020,7 +1020,7 @@ static void udc_clock_disable(struct mv_udc *udc) | |||
1020 | unsigned int i; | 1020 | unsigned int i; |
1021 | 1021 | ||
1022 | for (i = 0; i < udc->clknum; i++) | 1022 | for (i = 0; i < udc->clknum; i++) |
1023 | clk_disable(udc->clk[i]); | 1023 | clk_disable_unprepare(udc->clk[i]); |
1024 | } | 1024 | } |
1025 | 1025 | ||
1026 | static void udc_stop(struct mv_udc *udc) | 1026 | static void udc_stop(struct mv_udc *udc) |
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c index 141971d9051e..439c3f972f8c 100644 --- a/drivers/usb/gadget/s3c-hsotg.c +++ b/drivers/usb/gadget/s3c-hsotg.c | |||
@@ -3477,12 +3477,11 @@ static void s3c_hsotg_delete_debug(struct s3c_hsotg *hsotg) | |||
3477 | /** | 3477 | /** |
3478 | * s3c_hsotg_release - release callback for hsotg device | 3478 | * s3c_hsotg_release - release callback for hsotg device |
3479 | * @dev: Device to for which release is called | 3479 | * @dev: Device to for which release is called |
3480 | * | ||
3481 | * Nothing to do as the resource is allocated using devm_ API. | ||
3480 | */ | 3482 | */ |
3481 | static void s3c_hsotg_release(struct device *dev) | 3483 | static void s3c_hsotg_release(struct device *dev) |
3482 | { | 3484 | { |
3483 | struct s3c_hsotg *hsotg = dev_get_drvdata(dev); | ||
3484 | |||
3485 | kfree(hsotg); | ||
3486 | } | 3485 | } |
3487 | 3486 | ||
3488 | /** | 3487 | /** |
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c index 4f7f76f00c74..7cacd6ae818e 100644 --- a/drivers/usb/gadget/tcm_usb_gadget.c +++ b/drivers/usb/gadget/tcm_usb_gadget.c | |||
@@ -1794,9 +1794,10 @@ static int tcm_usbg_drop_nexus(struct usbg_tpg *tpg) | |||
1794 | tpg->tpg_nexus = NULL; | 1794 | tpg->tpg_nexus = NULL; |
1795 | 1795 | ||
1796 | kfree(tv_nexus); | 1796 | kfree(tv_nexus); |
1797 | ret = 0; | ||
1797 | out: | 1798 | out: |
1798 | mutex_unlock(&tpg->tpg_mutex); | 1799 | mutex_unlock(&tpg->tpg_mutex); |
1799 | return 0; | 1800 | return ret; |
1800 | } | 1801 | } |
1801 | 1802 | ||
1802 | static ssize_t tcm_usbg_tpg_store_nexus( | 1803 | static ssize_t tcm_usbg_tpg_store_nexus( |
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c index d0f95482f40e..598dcc1212f0 100644 --- a/drivers/usb/gadget/u_serial.c +++ b/drivers/usb/gadget/u_serial.c | |||
@@ -887,7 +887,7 @@ static void gs_close(struct tty_struct *tty, struct file *file) | |||
887 | pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", | 887 | pr_debug("gs_close: ttyGS%d (%p,%p) done!\n", |
888 | port->port_num, tty, file); | 888 | port->port_num, tty, file); |
889 | 889 | ||
890 | wake_up_interruptible(&port->port.close_wait); | 890 | wake_up(&port->port.close_wait); |
891 | exit: | 891 | exit: |
892 | spin_unlock_irq(&port->port_lock); | 892 | spin_unlock_irq(&port->port_lock); |
893 | } | 893 | } |
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig index d6bb128ce21e..3a21c5d683c0 100644 --- a/drivers/usb/host/Kconfig +++ b/drivers/usb/host/Kconfig | |||
@@ -148,7 +148,7 @@ config USB_EHCI_FSL | |||
148 | Variation of ARC USB block used in some Freescale chips. | 148 | Variation of ARC USB block used in some Freescale chips. |
149 | 149 | ||
150 | config USB_EHCI_MXC | 150 | config USB_EHCI_MXC |
151 | bool "Support for Freescale i.MX on-chip EHCI USB controller" | 151 | tristate "Support for Freescale i.MX on-chip EHCI USB controller" |
152 | depends on USB_EHCI_HCD && ARCH_MXC | 152 | depends on USB_EHCI_HCD && ARCH_MXC |
153 | select USB_EHCI_ROOT_HUB_TT | 153 | select USB_EHCI_ROOT_HUB_TT |
154 | ---help--- | 154 | ---help--- |
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile index 1eb4c3006e9e..001fbff2fdef 100644 --- a/drivers/usb/host/Makefile +++ b/drivers/usb/host/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_PCI) += pci-quirks.o | |||
26 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o | 26 | obj-$(CONFIG_USB_EHCI_HCD) += ehci-hcd.o |
27 | obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o | 27 | obj-$(CONFIG_USB_EHCI_PCI) += ehci-pci.o |
28 | obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o | 28 | obj-$(CONFIG_USB_EHCI_HCD_PLATFORM) += ehci-platform.o |
29 | obj-$(CONFIG_USB_EHCI_MXC) += ehci-mxc.o | ||
29 | 30 | ||
30 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o | 31 | obj-$(CONFIG_USB_OXU210HP_HCD) += oxu210hp-hcd.o |
31 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o | 32 | obj-$(CONFIG_USB_ISP116X_HCD) += isp116x-hcd.o |
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c index fd9b5424b860..d81d2fcbff18 100644 --- a/drivers/usb/host/ehci-fsl.c +++ b/drivers/usb/host/ehci-fsl.c | |||
@@ -230,7 +230,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
230 | 230 | ||
231 | switch (phy_mode) { | 231 | switch (phy_mode) { |
232 | case FSL_USB2_PHY_ULPI: | 232 | case FSL_USB2_PHY_ULPI: |
233 | if (pdata->controller_ver) { | 233 | if (pdata->have_sysif_regs && pdata->controller_ver) { |
234 | /* controller version 1.6 or above */ | 234 | /* controller version 1.6 or above */ |
235 | setbits32(non_ehci + FSL_SOC_USB_CTRL, | 235 | setbits32(non_ehci + FSL_SOC_USB_CTRL, |
236 | ULPI_PHY_CLK_SEL); | 236 | ULPI_PHY_CLK_SEL); |
@@ -251,7 +251,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
251 | portsc |= PORT_PTS_PTW; | 251 | portsc |= PORT_PTS_PTW; |
252 | /* fall through */ | 252 | /* fall through */ |
253 | case FSL_USB2_PHY_UTMI: | 253 | case FSL_USB2_PHY_UTMI: |
254 | if (pdata->controller_ver) { | 254 | if (pdata->have_sysif_regs && pdata->controller_ver) { |
255 | /* controller version 1.6 or above */ | 255 | /* controller version 1.6 or above */ |
256 | setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); | 256 | setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN); |
257 | mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to | 257 | mdelay(FSL_UTMI_PHY_DLY); /* Delay for UTMI PHY CLK to |
@@ -267,7 +267,8 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
267 | break; | 267 | break; |
268 | } | 268 | } |
269 | 269 | ||
270 | if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) { | 270 | if (pdata->have_sysif_regs && pdata->controller_ver && |
271 | (phy_mode == FSL_USB2_PHY_ULPI)) { | ||
271 | /* check PHY_CLK_VALID to get phy clk valid */ | 272 | /* check PHY_CLK_VALID to get phy clk valid */ |
272 | if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & | 273 | if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) & |
273 | PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { | 274 | PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) { |
@@ -278,7 +279,7 @@ static int ehci_fsl_setup_phy(struct usb_hcd *hcd, | |||
278 | 279 | ||
279 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); | 280 | ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]); |
280 | 281 | ||
281 | if (phy_mode != FSL_USB2_PHY_ULPI) | 282 | if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs) |
282 | setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); | 283 | setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN); |
283 | 284 | ||
284 | return 0; | 285 | return 0; |
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c index c97503bb0b0e..b416a3fc9959 100644 --- a/drivers/usb/host/ehci-hcd.c +++ b/drivers/usb/host/ehci-hcd.c | |||
@@ -74,10 +74,6 @@ static const char hcd_name [] = "ehci_hcd"; | |||
74 | #undef VERBOSE_DEBUG | 74 | #undef VERBOSE_DEBUG |
75 | #undef EHCI_URB_TRACE | 75 | #undef EHCI_URB_TRACE |
76 | 76 | ||
77 | #ifdef DEBUG | ||
78 | #define EHCI_STATS | ||
79 | #endif | ||
80 | |||
81 | /* magic numbers that can affect system performance */ | 77 | /* magic numbers that can affect system performance */ |
82 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ | 78 | #define EHCI_TUNE_CERR 3 /* 0-3 qtd retries; 0 == don't stop */ |
83 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ | 79 | #define EHCI_TUNE_RL_HS 4 /* nak throttle; see 4.9 */ |
@@ -801,6 +797,7 @@ static irqreturn_t ehci_irq (struct usb_hcd *hcd) | |||
801 | ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); | 797 | ehci->reset_done[i] = jiffies + msecs_to_jiffies(25); |
802 | set_bit(i, &ehci->resuming_ports); | 798 | set_bit(i, &ehci->resuming_ports); |
803 | ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); | 799 | ehci_dbg (ehci, "port %d remote wakeup\n", i + 1); |
800 | usb_hcd_start_port_resume(&hcd->self, i); | ||
804 | mod_timer(&hcd->rh_timer, ehci->reset_done[i]); | 801 | mod_timer(&hcd->rh_timer, ehci->reset_done[i]); |
805 | } | 802 | } |
806 | } | 803 | } |
@@ -1250,11 +1247,6 @@ MODULE_LICENSE ("GPL"); | |||
1250 | #define PLATFORM_DRIVER ehci_fsl_driver | 1247 | #define PLATFORM_DRIVER ehci_fsl_driver |
1251 | #endif | 1248 | #endif |
1252 | 1249 | ||
1253 | #ifdef CONFIG_USB_EHCI_MXC | ||
1254 | #include "ehci-mxc.c" | ||
1255 | #define PLATFORM_DRIVER ehci_mxc_driver | ||
1256 | #endif | ||
1257 | |||
1258 | #ifdef CONFIG_USB_EHCI_SH | 1250 | #ifdef CONFIG_USB_EHCI_SH |
1259 | #include "ehci-sh.c" | 1251 | #include "ehci-sh.c" |
1260 | #define PLATFORM_DRIVER ehci_hcd_sh_driver | 1252 | #define PLATFORM_DRIVER ehci_hcd_sh_driver |
@@ -1352,7 +1344,8 @@ MODULE_LICENSE ("GPL"); | |||
1352 | 1344 | ||
1353 | #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ | 1345 | #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \ |
1354 | !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ | 1346 | !IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \ |
1355 | !defined(CONFIG_USB_CHIPIDEA_HOST) && \ | 1347 | !IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \ |
1348 | !IS_ENABLED(CONFIG_USB_EHCI_MXC) && \ | ||
1356 | !defined(PLATFORM_DRIVER) && \ | 1349 | !defined(PLATFORM_DRIVER) && \ |
1357 | !defined(PS3_SYSTEM_BUS_DRIVER) && \ | 1350 | !defined(PS3_SYSTEM_BUS_DRIVER) && \ |
1358 | !defined(OF_PLATFORM_DRIVER) && \ | 1351 | !defined(OF_PLATFORM_DRIVER) && \ |
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 4ccb97c0678f..4d3b294f203e 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -649,7 +649,11 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf) | |||
649 | status = STS_PCD; | 649 | status = STS_PCD; |
650 | } | 650 | } |
651 | } | 651 | } |
652 | /* FIXME autosuspend idle root hubs */ | 652 | |
653 | /* If a resume is in progress, make sure it can finish */ | ||
654 | if (ehci->resuming_ports) | ||
655 | mod_timer(&hcd->rh_timer, jiffies + msecs_to_jiffies(25)); | ||
656 | |||
653 | spin_unlock_irqrestore (&ehci->lock, flags); | 657 | spin_unlock_irqrestore (&ehci->lock, flags); |
654 | return status ? retval : 0; | 658 | return status ? retval : 0; |
655 | } | 659 | } |
@@ -851,6 +855,7 @@ static int ehci_hub_control ( | |||
851 | /* resume signaling for 20 msec */ | 855 | /* resume signaling for 20 msec */ |
852 | ehci->reset_done[wIndex] = jiffies | 856 | ehci->reset_done[wIndex] = jiffies |
853 | + msecs_to_jiffies(20); | 857 | + msecs_to_jiffies(20); |
858 | usb_hcd_start_port_resume(&hcd->self, wIndex); | ||
854 | /* check the port again */ | 859 | /* check the port again */ |
855 | mod_timer(&ehci_to_hcd(ehci)->rh_timer, | 860 | mod_timer(&ehci_to_hcd(ehci)->rh_timer, |
856 | ehci->reset_done[wIndex]); | 861 | ehci->reset_done[wIndex]); |
@@ -862,6 +867,7 @@ static int ehci_hub_control ( | |||
862 | clear_bit(wIndex, &ehci->suspended_ports); | 867 | clear_bit(wIndex, &ehci->suspended_ports); |
863 | set_bit(wIndex, &ehci->port_c_suspend); | 868 | set_bit(wIndex, &ehci->port_c_suspend); |
864 | ehci->reset_done[wIndex] = 0; | 869 | ehci->reset_done[wIndex] = 0; |
870 | usb_hcd_end_port_resume(&hcd->self, wIndex); | ||
865 | 871 | ||
866 | /* stop resume signaling */ | 872 | /* stop resume signaling */ |
867 | temp = ehci_readl(ehci, status_reg); | 873 | temp = ehci_readl(ehci, status_reg); |
@@ -950,6 +956,7 @@ static int ehci_hub_control ( | |||
950 | ehci->reset_done[wIndex] = 0; | 956 | ehci->reset_done[wIndex] = 0; |
951 | if (temp & PORT_PE) | 957 | if (temp & PORT_PE) |
952 | set_bit(wIndex, &ehci->port_c_suspend); | 958 | set_bit(wIndex, &ehci->port_c_suspend); |
959 | usb_hcd_end_port_resume(&hcd->self, wIndex); | ||
953 | } | 960 | } |
954 | 961 | ||
955 | if (temp & PORT_OC) | 962 | if (temp & PORT_OC) |
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c index f7bfc0b898b9..6c56297ea16b 100644 --- a/drivers/usb/host/ehci-mv.c +++ b/drivers/usb/host/ehci-mv.c | |||
@@ -43,7 +43,7 @@ static void ehci_clock_enable(struct ehci_hcd_mv *ehci_mv) | |||
43 | unsigned int i; | 43 | unsigned int i; |
44 | 44 | ||
45 | for (i = 0; i < ehci_mv->clknum; i++) | 45 | for (i = 0; i < ehci_mv->clknum; i++) |
46 | clk_enable(ehci_mv->clk[i]); | 46 | clk_prepare_enable(ehci_mv->clk[i]); |
47 | } | 47 | } |
48 | 48 | ||
49 | static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) | 49 | static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) |
@@ -51,7 +51,7 @@ static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv) | |||
51 | unsigned int i; | 51 | unsigned int i; |
52 | 52 | ||
53 | for (i = 0; i < ehci_mv->clknum; i++) | 53 | for (i = 0; i < ehci_mv->clknum; i++) |
54 | clk_disable(ehci_mv->clk[i]); | 54 | clk_disable_unprepare(ehci_mv->clk[i]); |
55 | } | 55 | } |
56 | 56 | ||
57 | static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) | 57 | static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv) |
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c index ec7f5d2c90de..dedb80bb8d40 100644 --- a/drivers/usb/host/ehci-mxc.c +++ b/drivers/usb/host/ehci-mxc.c | |||
@@ -17,75 +17,38 @@ | |||
17 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | 17 | * Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
18 | */ | 18 | */ |
19 | 19 | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/module.h> | ||
22 | #include <linux/io.h> | ||
20 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
21 | #include <linux/clk.h> | 24 | #include <linux/clk.h> |
22 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
23 | #include <linux/usb/otg.h> | 26 | #include <linux/usb/otg.h> |
24 | #include <linux/usb/ulpi.h> | 27 | #include <linux/usb/ulpi.h> |
25 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/usb.h> | ||
30 | #include <linux/usb/hcd.h> | ||
26 | 31 | ||
27 | #include <linux/platform_data/usb-ehci-mxc.h> | 32 | #include <linux/platform_data/usb-ehci-mxc.h> |
28 | 33 | ||
29 | #include <asm/mach-types.h> | 34 | #include <asm/mach-types.h> |
30 | 35 | ||
36 | #include "ehci.h" | ||
37 | |||
38 | #define DRIVER_DESC "Freescale On-Chip EHCI Host driver" | ||
39 | |||
40 | static const char hcd_name[] = "ehci-mxc"; | ||
41 | |||
31 | #define ULPI_VIEWPORT_OFFSET 0x170 | 42 | #define ULPI_VIEWPORT_OFFSET 0x170 |
32 | 43 | ||
33 | struct ehci_mxc_priv { | 44 | struct ehci_mxc_priv { |
34 | struct clk *usbclk, *ahbclk, *phyclk; | 45 | struct clk *usbclk, *ahbclk, *phyclk; |
35 | struct usb_hcd *hcd; | ||
36 | }; | 46 | }; |
37 | 47 | ||
38 | /* called during probe() after chip reset completes */ | 48 | static struct hc_driver __read_mostly ehci_mxc_hc_driver; |
39 | static int ehci_mxc_setup(struct usb_hcd *hcd) | ||
40 | { | ||
41 | hcd->has_tt = 1; | ||
42 | |||
43 | return ehci_setup(hcd); | ||
44 | } | ||
45 | 49 | ||
46 | static const struct hc_driver ehci_mxc_hc_driver = { | 50 | static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = { |
47 | .description = hcd_name, | 51 | .extra_priv_size = sizeof(struct ehci_mxc_priv), |
48 | .product_desc = "Freescale On-Chip EHCI Host Controller", | ||
49 | .hcd_priv_size = sizeof(struct ehci_hcd), | ||
50 | |||
51 | /* | ||
52 | * generic hardware linkage | ||
53 | */ | ||
54 | .irq = ehci_irq, | ||
55 | .flags = HCD_USB2 | HCD_MEMORY, | ||
56 | |||
57 | /* | ||
58 | * basic lifecycle operations | ||
59 | */ | ||
60 | .reset = ehci_mxc_setup, | ||
61 | .start = ehci_run, | ||
62 | .stop = ehci_stop, | ||
63 | .shutdown = ehci_shutdown, | ||
64 | |||
65 | /* | ||
66 | * managing i/o requests and associated device resources | ||
67 | */ | ||
68 | .urb_enqueue = ehci_urb_enqueue, | ||
69 | .urb_dequeue = ehci_urb_dequeue, | ||
70 | .endpoint_disable = ehci_endpoint_disable, | ||
71 | .endpoint_reset = ehci_endpoint_reset, | ||
72 | |||
73 | /* | ||
74 | * scheduling support | ||
75 | */ | ||
76 | .get_frame_number = ehci_get_frame, | ||
77 | |||
78 | /* | ||
79 | * root hub support | ||
80 | */ | ||
81 | .hub_status_data = ehci_hub_status_data, | ||
82 | .hub_control = ehci_hub_control, | ||
83 | .bus_suspend = ehci_bus_suspend, | ||
84 | .bus_resume = ehci_bus_resume, | ||
85 | .relinquish_port = ehci_relinquish_port, | ||
86 | .port_handed_over = ehci_port_handed_over, | ||
87 | |||
88 | .clear_tt_buffer_complete = ehci_clear_tt_buffer_complete, | ||
89 | }; | 52 | }; |
90 | 53 | ||
91 | static int ehci_mxc_drv_probe(struct platform_device *pdev) | 54 | static int ehci_mxc_drv_probe(struct platform_device *pdev) |
@@ -112,12 +75,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
112 | if (!hcd) | 75 | if (!hcd) |
113 | return -ENOMEM; | 76 | return -ENOMEM; |
114 | 77 | ||
115 | priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); | ||
116 | if (!priv) { | ||
117 | ret = -ENOMEM; | ||
118 | goto err_alloc; | ||
119 | } | ||
120 | |||
121 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 78 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
122 | if (!res) { | 79 | if (!res) { |
123 | dev_err(dev, "Found HC with no register addr. Check setup!\n"); | 80 | dev_err(dev, "Found HC with no register addr. Check setup!\n"); |
@@ -135,6 +92,10 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
135 | goto err_alloc; | 92 | goto err_alloc; |
136 | } | 93 | } |
137 | 94 | ||
95 | hcd->has_tt = 1; | ||
96 | ehci = hcd_to_ehci(hcd); | ||
97 | priv = (struct ehci_mxc_priv *) ehci->priv; | ||
98 | |||
138 | /* enable clocks */ | 99 | /* enable clocks */ |
139 | priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); | 100 | priv->usbclk = devm_clk_get(&pdev->dev, "ipg"); |
140 | if (IS_ERR(priv->usbclk)) { | 101 | if (IS_ERR(priv->usbclk)) { |
@@ -169,8 +130,6 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
169 | mdelay(10); | 130 | mdelay(10); |
170 | } | 131 | } |
171 | 132 | ||
172 | ehci = hcd_to_ehci(hcd); | ||
173 | |||
174 | /* EHCI registers start at offset 0x100 */ | 133 | /* EHCI registers start at offset 0x100 */ |
175 | ehci->caps = hcd->regs + 0x100; | 134 | ehci->caps = hcd->regs + 0x100; |
176 | ehci->regs = hcd->regs + 0x100 + | 135 | ehci->regs = hcd->regs + 0x100 + |
@@ -198,8 +157,7 @@ static int ehci_mxc_drv_probe(struct platform_device *pdev) | |||
198 | } | 157 | } |
199 | } | 158 | } |
200 | 159 | ||
201 | priv->hcd = hcd; | 160 | platform_set_drvdata(pdev, hcd); |
202 | platform_set_drvdata(pdev, priv); | ||
203 | 161 | ||
204 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); | 162 | ret = usb_add_hcd(hcd, irq, IRQF_SHARED); |
205 | if (ret) | 163 | if (ret) |
@@ -244,8 +202,11 @@ err_alloc: | |||
244 | static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) | 202 | static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) |
245 | { | 203 | { |
246 | struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; | 204 | struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data; |
247 | struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); | 205 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
248 | struct usb_hcd *hcd = priv->hcd; | 206 | struct ehci_hcd *ehci = hcd_to_ehci(hcd); |
207 | struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv; | ||
208 | |||
209 | usb_remove_hcd(hcd); | ||
249 | 210 | ||
250 | if (pdata && pdata->exit) | 211 | if (pdata && pdata->exit) |
251 | pdata->exit(pdev); | 212 | pdata->exit(pdev); |
@@ -253,23 +214,20 @@ static int __exit ehci_mxc_drv_remove(struct platform_device *pdev) | |||
253 | if (pdata->otg) | 214 | if (pdata->otg) |
254 | usb_phy_shutdown(pdata->otg); | 215 | usb_phy_shutdown(pdata->otg); |
255 | 216 | ||
256 | usb_remove_hcd(hcd); | ||
257 | usb_put_hcd(hcd); | ||
258 | platform_set_drvdata(pdev, NULL); | ||
259 | |||
260 | clk_disable_unprepare(priv->usbclk); | 217 | clk_disable_unprepare(priv->usbclk); |
261 | clk_disable_unprepare(priv->ahbclk); | 218 | clk_disable_unprepare(priv->ahbclk); |
262 | 219 | ||
263 | if (priv->phyclk) | 220 | if (priv->phyclk) |
264 | clk_disable_unprepare(priv->phyclk); | 221 | clk_disable_unprepare(priv->phyclk); |
265 | 222 | ||
223 | usb_put_hcd(hcd); | ||
224 | platform_set_drvdata(pdev, NULL); | ||
266 | return 0; | 225 | return 0; |
267 | } | 226 | } |
268 | 227 | ||
269 | static void ehci_mxc_drv_shutdown(struct platform_device *pdev) | 228 | static void ehci_mxc_drv_shutdown(struct platform_device *pdev) |
270 | { | 229 | { |
271 | struct ehci_mxc_priv *priv = platform_get_drvdata(pdev); | 230 | struct usb_hcd *hcd = platform_get_drvdata(pdev); |
272 | struct usb_hcd *hcd = priv->hcd; | ||
273 | 231 | ||
274 | if (hcd->driver->shutdown) | 232 | if (hcd->driver->shutdown) |
275 | hcd->driver->shutdown(hcd); | 233 | hcd->driver->shutdown(hcd); |
@@ -279,9 +237,31 @@ MODULE_ALIAS("platform:mxc-ehci"); | |||
279 | 237 | ||
280 | static struct platform_driver ehci_mxc_driver = { | 238 | static struct platform_driver ehci_mxc_driver = { |
281 | .probe = ehci_mxc_drv_probe, | 239 | .probe = ehci_mxc_drv_probe, |
282 | .remove = __exit_p(ehci_mxc_drv_remove), | 240 | .remove = ehci_mxc_drv_remove, |
283 | .shutdown = ehci_mxc_drv_shutdown, | 241 | .shutdown = ehci_mxc_drv_shutdown, |
284 | .driver = { | 242 | .driver = { |
285 | .name = "mxc-ehci", | 243 | .name = "mxc-ehci", |
286 | }, | 244 | }, |
287 | }; | 245 | }; |
246 | |||
247 | static int __init ehci_mxc_init(void) | ||
248 | { | ||
249 | if (usb_disabled()) | ||
250 | return -ENODEV; | ||
251 | |||
252 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); | ||
253 | |||
254 | ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides); | ||
255 | return platform_driver_register(&ehci_mxc_driver); | ||
256 | } | ||
257 | module_init(ehci_mxc_init); | ||
258 | |||
259 | static void __exit ehci_mxc_cleanup(void) | ||
260 | { | ||
261 | platform_driver_unregister(&ehci_mxc_driver); | ||
262 | } | ||
263 | module_exit(ehci_mxc_cleanup); | ||
264 | |||
265 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
266 | MODULE_AUTHOR("Sascha Hauer"); | ||
267 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c index dabb20494826..170b9399e09f 100644 --- a/drivers/usb/host/ehci-pci.c +++ b/drivers/usb/host/ehci-pci.c | |||
@@ -200,6 +200,26 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
200 | break; | 200 | break; |
201 | } | 201 | } |
202 | 202 | ||
203 | /* optional debug port, normally in the first BAR */ | ||
204 | temp = pci_find_capability(pdev, PCI_CAP_ID_DBG); | ||
205 | if (temp) { | ||
206 | pci_read_config_dword(pdev, temp, &temp); | ||
207 | temp >>= 16; | ||
208 | if (((temp >> 13) & 7) == 1) { | ||
209 | u32 hcs_params = ehci_readl(ehci, | ||
210 | &ehci->caps->hcs_params); | ||
211 | |||
212 | temp &= 0x1fff; | ||
213 | ehci->debug = hcd->regs + temp; | ||
214 | temp = ehci_readl(ehci, &ehci->debug->control); | ||
215 | ehci_info(ehci, "debug port %d%s\n", | ||
216 | HCS_DEBUG_PORT(hcs_params), | ||
217 | (temp & DBGP_ENABLED) ? " IN USE" : ""); | ||
218 | if (!(temp & DBGP_ENABLED)) | ||
219 | ehci->debug = NULL; | ||
220 | } | ||
221 | } | ||
222 | |||
203 | retval = ehci_setup(hcd); | 223 | retval = ehci_setup(hcd); |
204 | if (retval) | 224 | if (retval) |
205 | return retval; | 225 | return retval; |
@@ -228,25 +248,6 @@ static int ehci_pci_setup(struct usb_hcd *hcd) | |||
228 | break; | 248 | break; |
229 | } | 249 | } |
230 | 250 | ||
231 | /* optional debug port, normally in the first BAR */ | ||
232 | temp = pci_find_capability(pdev, 0x0a); | ||
233 | if (temp) { | ||
234 | pci_read_config_dword(pdev, temp, &temp); | ||
235 | temp >>= 16; | ||
236 | if ((temp & (3 << 13)) == (1 << 13)) { | ||
237 | temp &= 0x1fff; | ||
238 | ehci->debug = hcd->regs + temp; | ||
239 | temp = ehci_readl(ehci, &ehci->debug->control); | ||
240 | ehci_info(ehci, "debug port %d%s\n", | ||
241 | HCS_DEBUG_PORT(ehci->hcs_params), | ||
242 | (temp & DBGP_ENABLED) | ||
243 | ? " IN USE" | ||
244 | : ""); | ||
245 | if (!(temp & DBGP_ENABLED)) | ||
246 | ehci->debug = NULL; | ||
247 | } | ||
248 | } | ||
249 | |||
250 | /* at least the Genesys GL880S needs fixup here */ | 251 | /* at least the Genesys GL880S needs fixup here */ |
251 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); | 252 | temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params); |
252 | temp &= 0x0f; | 253 | temp &= 0x0f; |
diff --git a/drivers/usb/host/ehci-q.c b/drivers/usb/host/ehci-q.c index 3d989028c836..fd252f0cfb3a 100644 --- a/drivers/usb/host/ehci-q.c +++ b/drivers/usb/host/ehci-q.c | |||
@@ -1197,17 +1197,26 @@ static void start_iaa_cycle(struct ehci_hcd *ehci, bool nested) | |||
1197 | if (ehci->async_iaa || ehci->async_unlinking) | 1197 | if (ehci->async_iaa || ehci->async_unlinking) |
1198 | return; | 1198 | return; |
1199 | 1199 | ||
1200 | /* Do all the waiting QHs at once */ | ||
1201 | ehci->async_iaa = ehci->async_unlink; | ||
1202 | ehci->async_unlink = NULL; | ||
1203 | |||
1204 | /* If the controller isn't running, we don't have to wait for it */ | 1200 | /* If the controller isn't running, we don't have to wait for it */ |
1205 | if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { | 1201 | if (unlikely(ehci->rh_state < EHCI_RH_RUNNING)) { |
1202 | |||
1203 | /* Do all the waiting QHs */ | ||
1204 | ehci->async_iaa = ehci->async_unlink; | ||
1205 | ehci->async_unlink = NULL; | ||
1206 | |||
1206 | if (!nested) /* Avoid recursion */ | 1207 | if (!nested) /* Avoid recursion */ |
1207 | end_unlink_async(ehci); | 1208 | end_unlink_async(ehci); |
1208 | 1209 | ||
1209 | /* Otherwise start a new IAA cycle */ | 1210 | /* Otherwise start a new IAA cycle */ |
1210 | } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { | 1211 | } else if (likely(ehci->rh_state == EHCI_RH_RUNNING)) { |
1212 | struct ehci_qh *qh; | ||
1213 | |||
1214 | /* Do only the first waiting QH (nVidia bug?) */ | ||
1215 | qh = ehci->async_unlink; | ||
1216 | ehci->async_iaa = qh; | ||
1217 | ehci->async_unlink = qh->unlink_next; | ||
1218 | qh->unlink_next = NULL; | ||
1219 | |||
1211 | /* Make sure the unlinks are all visible to the hardware */ | 1220 | /* Make sure the unlinks are all visible to the hardware */ |
1212 | wmb(); | 1221 | wmb(); |
1213 | 1222 | ||
@@ -1255,34 +1264,35 @@ static void end_unlink_async(struct ehci_hcd *ehci) | |||
1255 | } | 1264 | } |
1256 | } | 1265 | } |
1257 | 1266 | ||
1267 | static void start_unlink_async(struct ehci_hcd *ehci, struct ehci_qh *qh); | ||
1268 | |||
1258 | static void unlink_empty_async(struct ehci_hcd *ehci) | 1269 | static void unlink_empty_async(struct ehci_hcd *ehci) |
1259 | { | 1270 | { |
1260 | struct ehci_qh *qh, *next; | 1271 | struct ehci_qh *qh; |
1261 | bool stopped = (ehci->rh_state < EHCI_RH_RUNNING); | 1272 | struct ehci_qh *qh_to_unlink = NULL; |
1262 | bool check_unlinks_later = false; | 1273 | bool check_unlinks_later = false; |
1274 | int count = 0; | ||
1263 | 1275 | ||
1264 | /* Unlink all the async QHs that have been empty for a timer cycle */ | 1276 | /* Find the last async QH which has been empty for a timer cycle */ |
1265 | next = ehci->async->qh_next.qh; | 1277 | for (qh = ehci->async->qh_next.qh; qh; qh = qh->qh_next.qh) { |
1266 | while (next) { | ||
1267 | qh = next; | ||
1268 | next = qh->qh_next.qh; | ||
1269 | |||
1270 | if (list_empty(&qh->qtd_list) && | 1278 | if (list_empty(&qh->qtd_list) && |
1271 | qh->qh_state == QH_STATE_LINKED) { | 1279 | qh->qh_state == QH_STATE_LINKED) { |
1272 | if (!stopped && qh->unlink_cycle == | 1280 | ++count; |
1273 | ehci->async_unlink_cycle) | 1281 | if (qh->unlink_cycle == ehci->async_unlink_cycle) |
1274 | check_unlinks_later = true; | 1282 | check_unlinks_later = true; |
1275 | else | 1283 | else |
1276 | single_unlink_async(ehci, qh); | 1284 | qh_to_unlink = qh; |
1277 | } | 1285 | } |
1278 | } | 1286 | } |
1279 | 1287 | ||
1280 | /* Start a new IAA cycle if any QHs are waiting for it */ | 1288 | /* If nothing else is being unlinked, unlink the last empty QH */ |
1281 | if (ehci->async_unlink) | 1289 | if (!ehci->async_iaa && !ehci->async_unlink && qh_to_unlink) { |
1282 | start_iaa_cycle(ehci, false); | 1290 | start_unlink_async(ehci, qh_to_unlink); |
1291 | --count; | ||
1292 | } | ||
1283 | 1293 | ||
1284 | /* QHs that haven't been empty for long enough will be handled later */ | 1294 | /* Other QHs will be handled later */ |
1285 | if (check_unlinks_later) { | 1295 | if (count > 0) { |
1286 | ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); | 1296 | ehci_enable_event(ehci, EHCI_HRTIMER_ASYNC_UNLINKS, true); |
1287 | ++ehci->async_unlink_cycle; | 1297 | ++ehci->async_unlink_cycle; |
1288 | } | 1298 | } |
diff --git a/drivers/usb/host/ehci-sched.c b/drivers/usb/host/ehci-sched.c index 69ebee73c0c1..b476daf49f6f 100644 --- a/drivers/usb/host/ehci-sched.c +++ b/drivers/usb/host/ehci-sched.c | |||
@@ -213,7 +213,7 @@ static inline unsigned char tt_start_uframe(struct ehci_hcd *ehci, __hc32 mask) | |||
213 | } | 213 | } |
214 | 214 | ||
215 | static const unsigned char | 215 | static const unsigned char |
216 | max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 30, 0 }; | 216 | max_tt_usecs[] = { 125, 125, 125, 125, 125, 125, 125, 25 }; |
217 | 217 | ||
218 | /* carryover low/fullspeed bandwidth that crosses uframe boundries */ | 218 | /* carryover low/fullspeed bandwidth that crosses uframe boundries */ |
219 | static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) | 219 | static inline void carryover_tt_bandwidth(unsigned short tt_usecs[8]) |
@@ -2212,11 +2212,11 @@ static void scan_isoc(struct ehci_hcd *ehci) | |||
2212 | } | 2212 | } |
2213 | ehci->now_frame = now_frame; | 2213 | ehci->now_frame = now_frame; |
2214 | 2214 | ||
2215 | frame = ehci->last_iso_frame; | ||
2215 | for (;;) { | 2216 | for (;;) { |
2216 | union ehci_shadow q, *q_p; | 2217 | union ehci_shadow q, *q_p; |
2217 | __hc32 type, *hw_p; | 2218 | __hc32 type, *hw_p; |
2218 | 2219 | ||
2219 | frame = ehci->last_iso_frame; | ||
2220 | restart: | 2220 | restart: |
2221 | /* scan each element in frame's queue for completions */ | 2221 | /* scan each element in frame's queue for completions */ |
2222 | q_p = &ehci->pshadow [frame]; | 2222 | q_p = &ehci->pshadow [frame]; |
@@ -2321,6 +2321,9 @@ restart: | |||
2321 | /* Stop when we have reached the current frame */ | 2321 | /* Stop when we have reached the current frame */ |
2322 | if (frame == now_frame) | 2322 | if (frame == now_frame) |
2323 | break; | 2323 | break; |
2324 | ehci->last_iso_frame = (frame + 1) & fmask; | 2324 | |
2325 | /* The last frame may still have active siTDs */ | ||
2326 | ehci->last_iso_frame = frame; | ||
2327 | frame = (frame + 1) & fmask; | ||
2325 | } | 2328 | } |
2326 | } | 2329 | } |
diff --git a/drivers/usb/host/ehci-timer.c b/drivers/usb/host/ehci-timer.c index 20dbdcbe9b0f..f904071d70df 100644 --- a/drivers/usb/host/ehci-timer.c +++ b/drivers/usb/host/ehci-timer.c | |||
@@ -113,14 +113,15 @@ static void ehci_poll_ASS(struct ehci_hcd *ehci) | |||
113 | 113 | ||
114 | if (want != actual) { | 114 | if (want != actual) { |
115 | 115 | ||
116 | /* Poll again later, but give up after about 20 ms */ | 116 | /* Poll again later */ |
117 | if (ehci->ASS_poll_count++ < 20) { | 117 | ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); |
118 | ehci_enable_event(ehci, EHCI_HRTIMER_POLL_ASS, true); | 118 | ++ehci->ASS_poll_count; |
119 | return; | 119 | return; |
120 | } | ||
121 | ehci_dbg(ehci, "Waited too long for the async schedule status (%x/%x), giving up\n", | ||
122 | want, actual); | ||
123 | } | 120 | } |
121 | |||
122 | if (ehci->ASS_poll_count > 20) | ||
123 | ehci_dbg(ehci, "ASS poll count reached %d\n", | ||
124 | ehci->ASS_poll_count); | ||
124 | ehci->ASS_poll_count = 0; | 125 | ehci->ASS_poll_count = 0; |
125 | 126 | ||
126 | /* The status is up-to-date; restart or stop the schedule as needed */ | 127 | /* The status is up-to-date; restart or stop the schedule as needed */ |
@@ -159,14 +160,14 @@ static void ehci_poll_PSS(struct ehci_hcd *ehci) | |||
159 | 160 | ||
160 | if (want != actual) { | 161 | if (want != actual) { |
161 | 162 | ||
162 | /* Poll again later, but give up after about 20 ms */ | 163 | /* Poll again later */ |
163 | if (ehci->PSS_poll_count++ < 20) { | 164 | ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); |
164 | ehci_enable_event(ehci, EHCI_HRTIMER_POLL_PSS, true); | 165 | return; |
165 | return; | ||
166 | } | ||
167 | ehci_dbg(ehci, "Waited too long for the periodic schedule status (%x/%x), giving up\n", | ||
168 | want, actual); | ||
169 | } | 166 | } |
167 | |||
168 | if (ehci->PSS_poll_count > 20) | ||
169 | ehci_dbg(ehci, "PSS poll count reached %d\n", | ||
170 | ehci->PSS_poll_count); | ||
170 | ehci->PSS_poll_count = 0; | 171 | ehci->PSS_poll_count = 0; |
171 | 172 | ||
172 | /* The status is up-to-date; restart or stop the schedule as needed */ | 173 | /* The status is up-to-date; restart or stop the schedule as needed */ |
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h index 9dadc7118d68..36c3a8210595 100644 --- a/drivers/usb/host/ehci.h +++ b/drivers/usb/host/ehci.h | |||
@@ -38,6 +38,10 @@ typedef __u16 __bitwise __hc16; | |||
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | /* statistics can be kept for tuning/monitoring */ | 40 | /* statistics can be kept for tuning/monitoring */ |
41 | #ifdef DEBUG | ||
42 | #define EHCI_STATS | ||
43 | #endif | ||
44 | |||
41 | struct ehci_stats { | 45 | struct ehci_stats { |
42 | /* irq usage */ | 46 | /* irq usage */ |
43 | unsigned long normal; | 47 | unsigned long normal; |
@@ -221,6 +225,9 @@ struct ehci_hcd { /* one per controller */ | |||
221 | #ifdef DEBUG | 225 | #ifdef DEBUG |
222 | struct dentry *debug_dir; | 226 | struct dentry *debug_dir; |
223 | #endif | 227 | #endif |
228 | |||
229 | /* platform-specific data -- must come last */ | ||
230 | unsigned long priv[0] __aligned(sizeof(s64)); | ||
224 | }; | 231 | }; |
225 | 232 | ||
226 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ | 233 | /* convert between an HCD pointer and the corresponding EHCI_HCD */ |
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c index 5105127c1d4b..11e0b79ff9d5 100644 --- a/drivers/usb/host/fsl-mph-dr-of.c +++ b/drivers/usb/host/fsl-mph-dr-of.c | |||
@@ -142,6 +142,9 @@ static int usb_get_ver_info(struct device_node *np) | |||
142 | return ver; | 142 | return ver; |
143 | } | 143 | } |
144 | 144 | ||
145 | if (of_device_is_compatible(np, "fsl,mpc5121-usb2-dr")) | ||
146 | return FSL_USB_VER_OLD; | ||
147 | |||
145 | if (of_device_is_compatible(np, "fsl-usb2-mph")) { | 148 | if (of_device_is_compatible(np, "fsl-usb2-mph")) { |
146 | if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) | 149 | if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6")) |
147 | ver = FSL_USB_VER_1_6; | 150 | ver = FSL_USB_VER_1_6; |
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c index bd6a7447ccc9..f0ebe8e7c58b 100644 --- a/drivers/usb/host/imx21-hcd.c +++ b/drivers/usb/host/imx21-hcd.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/usb.h> | 58 | #include <linux/usb.h> |
59 | #include <linux/usb/hcd.h> | 59 | #include <linux/usb/hcd.h> |
60 | #include <linux/dma-mapping.h> | 60 | #include <linux/dma-mapping.h> |
61 | #include <linux/module.h> | ||
61 | 62 | ||
62 | #include "imx21-hcd.h" | 63 | #include "imx21-hcd.h" |
63 | 64 | ||
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c index d370245a4ee2..5e3a6deb62b1 100644 --- a/drivers/usb/host/ohci-tmio.c +++ b/drivers/usb/host/ohci-tmio.c | |||
@@ -128,7 +128,8 @@ static void tmio_start_hc(struct platform_device *dev) | |||
128 | tmio_iowrite8(2, tmio->ccr + CCR_INTC); | 128 | tmio_iowrite8(2, tmio->ccr + CCR_INTC); |
129 | 129 | ||
130 | dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n", | 130 | dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n", |
131 | tmio_ioread8(tmio->ccr + CCR_REVID), hcd->rsrc_start, hcd->irq); | 131 | tmio_ioread8(tmio->ccr + CCR_REVID), |
132 | (u64) hcd->rsrc_start, hcd->irq); | ||
132 | } | 133 | } |
133 | 134 | ||
134 | static int ohci_tmio_start(struct usb_hcd *hcd) | 135 | static int ohci_tmio_start(struct usb_hcd *hcd) |
diff --git a/drivers/usb/host/pci-quirks.c b/drivers/usb/host/pci-quirks.c index a3b6d7104ae2..4c338ec03a07 100644 --- a/drivers/usb/host/pci-quirks.c +++ b/drivers/usb/host/pci-quirks.c | |||
@@ -780,6 +780,7 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev) | |||
780 | "defaulting to EHCI.\n"); | 780 | "defaulting to EHCI.\n"); |
781 | dev_warn(&xhci_pdev->dev, | 781 | dev_warn(&xhci_pdev->dev, |
782 | "USB 3.0 devices will work at USB 2.0 speeds.\n"); | 782 | "USB 3.0 devices will work at USB 2.0 speeds.\n"); |
783 | usb_disable_xhci_ports(xhci_pdev); | ||
783 | return; | 784 | return; |
784 | } | 785 | } |
785 | 786 | ||
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c index 4b9e9aba2665..4f64d24eebc8 100644 --- a/drivers/usb/host/uhci-hcd.c +++ b/drivers/usb/host/uhci-hcd.c | |||
@@ -447,6 +447,10 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) | |||
447 | return IRQ_NONE; | 447 | return IRQ_NONE; |
448 | uhci_writew(uhci, status, USBSTS); /* Clear it */ | 448 | uhci_writew(uhci, status, USBSTS); /* Clear it */ |
449 | 449 | ||
450 | spin_lock(&uhci->lock); | ||
451 | if (unlikely(!uhci->is_initialized)) /* not yet configured */ | ||
452 | goto done; | ||
453 | |||
450 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { | 454 | if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) { |
451 | if (status & USBSTS_HSE) | 455 | if (status & USBSTS_HSE) |
452 | dev_err(uhci_dev(uhci), "host system error, " | 456 | dev_err(uhci_dev(uhci), "host system error, " |
@@ -455,7 +459,6 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) | |||
455 | dev_err(uhci_dev(uhci), "host controller process " | 459 | dev_err(uhci_dev(uhci), "host controller process " |
456 | "error, something bad happened!\n"); | 460 | "error, something bad happened!\n"); |
457 | if (status & USBSTS_HCH) { | 461 | if (status & USBSTS_HCH) { |
458 | spin_lock(&uhci->lock); | ||
459 | if (uhci->rh_state >= UHCI_RH_RUNNING) { | 462 | if (uhci->rh_state >= UHCI_RH_RUNNING) { |
460 | dev_err(uhci_dev(uhci), | 463 | dev_err(uhci_dev(uhci), |
461 | "host controller halted, " | 464 | "host controller halted, " |
@@ -473,15 +476,15 @@ static irqreturn_t uhci_irq(struct usb_hcd *hcd) | |||
473 | * pending unlinks */ | 476 | * pending unlinks */ |
474 | mod_timer(&hcd->rh_timer, jiffies); | 477 | mod_timer(&hcd->rh_timer, jiffies); |
475 | } | 478 | } |
476 | spin_unlock(&uhci->lock); | ||
477 | } | 479 | } |
478 | } | 480 | } |
479 | 481 | ||
480 | if (status & USBSTS_RD) | 482 | if (status & USBSTS_RD) { |
483 | spin_unlock(&uhci->lock); | ||
481 | usb_hcd_poll_rh_status(hcd); | 484 | usb_hcd_poll_rh_status(hcd); |
482 | else { | 485 | } else { |
483 | spin_lock(&uhci->lock); | ||
484 | uhci_scan_schedule(uhci); | 486 | uhci_scan_schedule(uhci); |
487 | done: | ||
485 | spin_unlock(&uhci->lock); | 488 | spin_unlock(&uhci->lock); |
486 | } | 489 | } |
487 | 490 | ||
@@ -662,9 +665,9 @@ static int uhci_start(struct usb_hcd *hcd) | |||
662 | */ | 665 | */ |
663 | mb(); | 666 | mb(); |
664 | 667 | ||
668 | spin_lock_irq(&uhci->lock); | ||
665 | configure_hc(uhci); | 669 | configure_hc(uhci); |
666 | uhci->is_initialized = 1; | 670 | uhci->is_initialized = 1; |
667 | spin_lock_irq(&uhci->lock); | ||
668 | start_rh(uhci); | 671 | start_rh(uhci); |
669 | spin_unlock_irq(&uhci->lock); | 672 | spin_unlock_irq(&uhci->lock); |
670 | return 0; | 673 | return 0; |
diff --git a/drivers/usb/host/uhci-hub.c b/drivers/usb/host/uhci-hub.c index 768d54295a20..15d13229ddbb 100644 --- a/drivers/usb/host/uhci-hub.c +++ b/drivers/usb/host/uhci-hub.c | |||
@@ -116,6 +116,7 @@ static void uhci_finish_suspend(struct uhci_hcd *uhci, int port, | |||
116 | } | 116 | } |
117 | } | 117 | } |
118 | clear_bit(port, &uhci->resuming_ports); | 118 | clear_bit(port, &uhci->resuming_ports); |
119 | usb_hcd_end_port_resume(&uhci_to_hcd(uhci)->self, port); | ||
119 | } | 120 | } |
120 | 121 | ||
121 | /* Wait for the UHCI controller in HP's iLO2 server management chip. | 122 | /* Wait for the UHCI controller in HP's iLO2 server management chip. |
@@ -167,6 +168,8 @@ static void uhci_check_ports(struct uhci_hcd *uhci) | |||
167 | set_bit(port, &uhci->resuming_ports); | 168 | set_bit(port, &uhci->resuming_ports); |
168 | uhci->ports_timeout = jiffies + | 169 | uhci->ports_timeout = jiffies + |
169 | msecs_to_jiffies(25); | 170 | msecs_to_jiffies(25); |
171 | usb_hcd_start_port_resume( | ||
172 | &uhci_to_hcd(uhci)->self, port); | ||
170 | 173 | ||
171 | /* Make sure we see the port again | 174 | /* Make sure we see the port again |
172 | * after the resuming period is over. */ | 175 | * after the resuming period is over. */ |
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c index a686cf4905bb..68914429482f 100644 --- a/drivers/usb/host/xhci-hub.c +++ b/drivers/usb/host/xhci-hub.c | |||
@@ -761,12 +761,39 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, | |||
761 | break; | 761 | break; |
762 | case USB_PORT_FEAT_LINK_STATE: | 762 | case USB_PORT_FEAT_LINK_STATE: |
763 | temp = xhci_readl(xhci, port_array[wIndex]); | 763 | temp = xhci_readl(xhci, port_array[wIndex]); |
764 | |||
765 | /* Disable port */ | ||
766 | if (link_state == USB_SS_PORT_LS_SS_DISABLED) { | ||
767 | xhci_dbg(xhci, "Disable port %d\n", wIndex); | ||
768 | temp = xhci_port_state_to_neutral(temp); | ||
769 | /* | ||
770 | * Clear all change bits, so that we get a new | ||
771 | * connection event. | ||
772 | */ | ||
773 | temp |= PORT_CSC | PORT_PEC | PORT_WRC | | ||
774 | PORT_OCC | PORT_RC | PORT_PLC | | ||
775 | PORT_CEC; | ||
776 | xhci_writel(xhci, temp | PORT_PE, | ||
777 | port_array[wIndex]); | ||
778 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
779 | break; | ||
780 | } | ||
781 | |||
782 | /* Put link in RxDetect (enable port) */ | ||
783 | if (link_state == USB_SS_PORT_LS_RX_DETECT) { | ||
784 | xhci_dbg(xhci, "Enable port %d\n", wIndex); | ||
785 | xhci_set_link_state(xhci, port_array, wIndex, | ||
786 | link_state); | ||
787 | temp = xhci_readl(xhci, port_array[wIndex]); | ||
788 | break; | ||
789 | } | ||
790 | |||
764 | /* Software should not attempt to set | 791 | /* Software should not attempt to set |
765 | * port link state above '5' (Rx.Detect) and the port | 792 | * port link state above '3' (U3) and the port |
766 | * must be enabled. | 793 | * must be enabled. |
767 | */ | 794 | */ |
768 | if ((temp & PORT_PE) == 0 || | 795 | if ((temp & PORT_PE) == 0 || |
769 | (link_state > USB_SS_PORT_LS_RX_DETECT)) { | 796 | (link_state > USB_SS_PORT_LS_U3)) { |
770 | xhci_warn(xhci, "Cannot set link state.\n"); | 797 | xhci_warn(xhci, "Cannot set link state.\n"); |
771 | goto error; | 798 | goto error; |
772 | } | 799 | } |
@@ -957,6 +984,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
957 | int max_ports; | 984 | int max_ports; |
958 | __le32 __iomem **port_array; | 985 | __le32 __iomem **port_array; |
959 | struct xhci_bus_state *bus_state; | 986 | struct xhci_bus_state *bus_state; |
987 | bool reset_change = false; | ||
960 | 988 | ||
961 | max_ports = xhci_get_ports(hcd, &port_array); | 989 | max_ports = xhci_get_ports(hcd, &port_array); |
962 | bus_state = &xhci->bus_state[hcd_index(hcd)]; | 990 | bus_state = &xhci->bus_state[hcd_index(hcd)]; |
@@ -988,6 +1016,12 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf) | |||
988 | buf[(i + 1) / 8] |= 1 << (i + 1) % 8; | 1016 | buf[(i + 1) / 8] |= 1 << (i + 1) % 8; |
989 | status = 1; | 1017 | status = 1; |
990 | } | 1018 | } |
1019 | if ((temp & PORT_RC)) | ||
1020 | reset_change = true; | ||
1021 | } | ||
1022 | if (!status && !reset_change) { | ||
1023 | xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); | ||
1024 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
991 | } | 1025 | } |
992 | spin_unlock_irqrestore(&xhci->lock, flags); | 1026 | spin_unlock_irqrestore(&xhci->lock, flags); |
993 | return status ? retval : 0; | 1027 | return status ? retval : 0; |
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c index fb51c7085ad0..35616ffbe3ae 100644 --- a/drivers/usb/host/xhci-mem.c +++ b/drivers/usb/host/xhci-mem.c | |||
@@ -1250,6 +1250,8 @@ static unsigned int xhci_microframes_to_exponent(struct usb_device *udev, | |||
1250 | static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, | 1250 | static unsigned int xhci_parse_microframe_interval(struct usb_device *udev, |
1251 | struct usb_host_endpoint *ep) | 1251 | struct usb_host_endpoint *ep) |
1252 | { | 1252 | { |
1253 | if (ep->desc.bInterval == 0) | ||
1254 | return 0; | ||
1253 | return xhci_microframes_to_exponent(udev, ep, | 1255 | return xhci_microframes_to_exponent(udev, ep, |
1254 | ep->desc.bInterval, 0, 15); | 1256 | ep->desc.bInterval, 0, 15); |
1255 | } | 1257 | } |
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c index cbb44b7b9d65..7f76a49e90d3 100644 --- a/drivers/usb/host/xhci-ring.c +++ b/drivers/usb/host/xhci-ring.c | |||
@@ -1698,7 +1698,7 @@ static void handle_port_status(struct xhci_hcd *xhci, | |||
1698 | faked_port_index + 1); | 1698 | faked_port_index + 1); |
1699 | if (slot_id && xhci->devs[slot_id]) | 1699 | if (slot_id && xhci->devs[slot_id]) |
1700 | xhci_ring_device(xhci, slot_id); | 1700 | xhci_ring_device(xhci, slot_id); |
1701 | if (bus_state->port_remote_wakeup && (1 << faked_port_index)) { | 1701 | if (bus_state->port_remote_wakeup & (1 << faked_port_index)) { |
1702 | bus_state->port_remote_wakeup &= | 1702 | bus_state->port_remote_wakeup &= |
1703 | ~(1 << faked_port_index); | 1703 | ~(1 << faked_port_index); |
1704 | xhci_test_and_clear_bit(xhci, port_array, | 1704 | xhci_test_and_clear_bit(xhci, port_array, |
@@ -1725,6 +1725,15 @@ cleanup: | |||
1725 | if (bogus_port_status) | 1725 | if (bogus_port_status) |
1726 | return; | 1726 | return; |
1727 | 1727 | ||
1728 | /* | ||
1729 | * xHCI port-status-change events occur when the "or" of all the | ||
1730 | * status-change bits in the portsc register changes from 0 to 1. | ||
1731 | * New status changes won't cause an event if any other change | ||
1732 | * bits are still set. When an event occurs, switch over to | ||
1733 | * polling to avoid losing status changes. | ||
1734 | */ | ||
1735 | xhci_dbg(xhci, "%s: starting port polling.\n", __func__); | ||
1736 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
1728 | spin_unlock(&xhci->lock); | 1737 | spin_unlock(&xhci->lock); |
1729 | /* Pass this up to the core */ | 1738 | /* Pass this up to the core */ |
1730 | usb_hcd_poll_rh_status(hcd); | 1739 | usb_hcd_poll_rh_status(hcd); |
@@ -2580,6 +2589,8 @@ cleanup: | |||
2580 | (trb_comp_code != COMP_STALL && | 2589 | (trb_comp_code != COMP_STALL && |
2581 | trb_comp_code != COMP_BABBLE)) | 2590 | trb_comp_code != COMP_BABBLE)) |
2582 | xhci_urb_free_priv(xhci, urb_priv); | 2591 | xhci_urb_free_priv(xhci, urb_priv); |
2592 | else | ||
2593 | kfree(urb_priv); | ||
2583 | 2594 | ||
2584 | usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); | 2595 | usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb); |
2585 | if ((urb->actual_length != urb->transfer_buffer_length && | 2596 | if ((urb->actual_length != urb->transfer_buffer_length && |
@@ -3099,7 +3110,7 @@ static u32 xhci_v1_0_td_remainder(int running_total, int trb_buff_len, | |||
3099 | * running_total. | 3110 | * running_total. |
3100 | */ | 3111 | */ |
3101 | packets_transferred = (running_total + trb_buff_len) / | 3112 | packets_transferred = (running_total + trb_buff_len) / |
3102 | usb_endpoint_maxp(&urb->ep->desc); | 3113 | GET_MAX_PACKET(usb_endpoint_maxp(&urb->ep->desc)); |
3103 | 3114 | ||
3104 | if ((total_packet_count - packets_transferred) > 31) | 3115 | if ((total_packet_count - packets_transferred) > 31) |
3105 | return 31 << 17; | 3116 | return 31 << 17; |
@@ -3633,7 +3644,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
3633 | td_len = urb->iso_frame_desc[i].length; | 3644 | td_len = urb->iso_frame_desc[i].length; |
3634 | td_remain_len = td_len; | 3645 | td_remain_len = td_len; |
3635 | total_packet_count = DIV_ROUND_UP(td_len, | 3646 | total_packet_count = DIV_ROUND_UP(td_len, |
3636 | usb_endpoint_maxp(&urb->ep->desc)); | 3647 | GET_MAX_PACKET( |
3648 | usb_endpoint_maxp(&urb->ep->desc))); | ||
3637 | /* A zero-length transfer still involves at least one packet. */ | 3649 | /* A zero-length transfer still involves at least one packet. */ |
3638 | if (total_packet_count == 0) | 3650 | if (total_packet_count == 0) |
3639 | total_packet_count++; | 3651 | total_packet_count++; |
@@ -3655,9 +3667,11 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags, | |||
3655 | td = urb_priv->td[i]; | 3667 | td = urb_priv->td[i]; |
3656 | for (j = 0; j < trbs_per_td; j++) { | 3668 | for (j = 0; j < trbs_per_td; j++) { |
3657 | u32 remainder = 0; | 3669 | u32 remainder = 0; |
3658 | field = TRB_TBC(burst_count) | TRB_TLBPC(residue); | 3670 | field = 0; |
3659 | 3671 | ||
3660 | if (first_trb) { | 3672 | if (first_trb) { |
3673 | field = TRB_TBC(burst_count) | | ||
3674 | TRB_TLBPC(residue); | ||
3661 | /* Queue the isoc TRB */ | 3675 | /* Queue the isoc TRB */ |
3662 | field |= TRB_TYPE(TRB_ISOC); | 3676 | field |= TRB_TYPE(TRB_ISOC); |
3663 | /* Assume URB_ISO_ASAP is set */ | 3677 | /* Assume URB_ISO_ASAP is set */ |
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 5c72c431bab1..f1f01a834ba7 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c | |||
@@ -884,6 +884,11 @@ int xhci_suspend(struct xhci_hcd *xhci) | |||
884 | xhci->shared_hcd->state != HC_STATE_SUSPENDED) | 884 | xhci->shared_hcd->state != HC_STATE_SUSPENDED) |
885 | return -EINVAL; | 885 | return -EINVAL; |
886 | 886 | ||
887 | /* Don't poll the roothubs on bus suspend. */ | ||
888 | xhci_dbg(xhci, "%s: stopping port polling.\n", __func__); | ||
889 | clear_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
890 | del_timer_sync(&hcd->rh_timer); | ||
891 | |||
887 | spin_lock_irq(&xhci->lock); | 892 | spin_lock_irq(&xhci->lock); |
888 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); | 893 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); |
889 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); | 894 | clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); |
@@ -1069,6 +1074,11 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated) | |||
1069 | if (xhci->quirks & XHCI_COMP_MODE_QUIRK) | 1074 | if (xhci->quirks & XHCI_COMP_MODE_QUIRK) |
1070 | compliance_mode_recovery_timer_init(xhci); | 1075 | compliance_mode_recovery_timer_init(xhci); |
1071 | 1076 | ||
1077 | /* Re-enable port polling. */ | ||
1078 | xhci_dbg(xhci, "%s: starting port polling.\n", __func__); | ||
1079 | set_bit(HCD_FLAG_POLL_RH, &hcd->flags); | ||
1080 | usb_hcd_poll_rh_status(hcd); | ||
1081 | |||
1072 | return retval; | 1082 | return retval; |
1073 | } | 1083 | } |
1074 | #endif /* CONFIG_PM */ | 1084 | #endif /* CONFIG_PM */ |
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c index 7667b12f2ff5..268148de9714 100644 --- a/drivers/usb/misc/usbtest.c +++ b/drivers/usb/misc/usbtest.c | |||
@@ -2179,7 +2179,7 @@ usbtest_ioctl(struct usb_interface *intf, unsigned int code, void *buf) | |||
2179 | if (dev->out_pipe == 0 || !param->length || param->sglen < 4) | 2179 | if (dev->out_pipe == 0 || !param->length || param->sglen < 4) |
2180 | break; | 2180 | break; |
2181 | retval = 0; | 2181 | retval = 0; |
2182 | dev_info(&intf->dev, "TEST 17: unlink from %d queues of " | 2182 | dev_info(&intf->dev, "TEST 24: unlink from %d queues of " |
2183 | "%d %d-byte writes\n", | 2183 | "%d %d-byte writes\n", |
2184 | param->iterations, param->sglen, param->length); | 2184 | param->iterations, param->sglen, param->length); |
2185 | for (i = param->iterations; retval == 0 && i > 0; --i) { | 2185 | for (i = param->iterations; retval == 0 && i > 0; --i) { |
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c index 0968dd7a859d..f522000e8f06 100644 --- a/drivers/usb/musb/cppi_dma.c +++ b/drivers/usb/musb/cppi_dma.c | |||
@@ -105,7 +105,7 @@ static void cppi_reset_tx(struct cppi_tx_stateram __iomem *tx, u32 ptr) | |||
105 | musb_writel(&tx->tx_complete, 0, ptr); | 105 | musb_writel(&tx->tx_complete, 0, ptr); |
106 | } | 106 | } |
107 | 107 | ||
108 | static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) | 108 | static void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c) |
109 | { | 109 | { |
110 | int j; | 110 | int j; |
111 | 111 | ||
@@ -150,7 +150,7 @@ static void cppi_pool_free(struct cppi_channel *c) | |||
150 | c->last_processed = NULL; | 150 | c->last_processed = NULL; |
151 | } | 151 | } |
152 | 152 | ||
153 | static int __init cppi_controller_start(struct dma_controller *c) | 153 | static int cppi_controller_start(struct dma_controller *c) |
154 | { | 154 | { |
155 | struct cppi *controller; | 155 | struct cppi *controller; |
156 | void __iomem *tibase; | 156 | void __iomem *tibase; |
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index f1c6c5470b92..fd3486745e64 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c | |||
@@ -2298,10 +2298,7 @@ static int __init musb_init(void) | |||
2298 | if (usb_disabled()) | 2298 | if (usb_disabled()) |
2299 | return 0; | 2299 | return 0; |
2300 | 2300 | ||
2301 | pr_info("%s: version " MUSB_VERSION ", " | 2301 | pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n", |
2302 | "?dma?" | ||
2303 | ", " | ||
2304 | "otg (peripheral+host)", | ||
2305 | musb_driver_name); | 2302 | musb_driver_name); |
2306 | return platform_driver_register(&musb_driver); | 2303 | return platform_driver_register(&musb_driver); |
2307 | } | 2304 | } |
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c index e6f2ae8368bb..f7d764de6fda 100644 --- a/drivers/usb/musb/musb_dsps.c +++ b/drivers/usb/musb/musb_dsps.c | |||
@@ -134,6 +134,11 @@ static const resource_size_t dsps_control_module_phys[] = { | |||
134 | DSPS_AM33XX_CONTROL_MODULE_PHYS_1, | 134 | DSPS_AM33XX_CONTROL_MODULE_PHYS_1, |
135 | }; | 135 | }; |
136 | 136 | ||
137 | #define USBPHY_CM_PWRDN (1 << 0) | ||
138 | #define USBPHY_OTG_PWRDN (1 << 1) | ||
139 | #define USBPHY_OTGVDET_EN (1 << 19) | ||
140 | #define USBPHY_OTGSESSEND_EN (1 << 20) | ||
141 | |||
137 | /** | 142 | /** |
138 | * musb_dsps_phy_control - phy on/off | 143 | * musb_dsps_phy_control - phy on/off |
139 | * @glue: struct dsps_glue * | 144 | * @glue: struct dsps_glue * |
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig index 6223062d5d1b..37962c99ff1e 100644 --- a/drivers/usb/otg/Kconfig +++ b/drivers/usb/otg/Kconfig | |||
@@ -110,7 +110,7 @@ config AB8500_USB | |||
110 | 110 | ||
111 | config FSL_USB2_OTG | 111 | config FSL_USB2_OTG |
112 | bool "Freescale USB OTG Transceiver Driver" | 112 | bool "Freescale USB OTG Transceiver Driver" |
113 | depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND | 113 | depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND |
114 | select USB_OTG | 114 | select USB_OTG |
115 | select USB_OTG_UTILS | 115 | select USB_OTG_UTILS |
116 | help | 116 | help |
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c index 1dd57504186d..eace975991a8 100644 --- a/drivers/usb/otg/mv_otg.c +++ b/drivers/usb/otg/mv_otg.c | |||
@@ -240,7 +240,7 @@ static void otg_clock_enable(struct mv_otg *mvotg) | |||
240 | unsigned int i; | 240 | unsigned int i; |
241 | 241 | ||
242 | for (i = 0; i < mvotg->clknum; i++) | 242 | for (i = 0; i < mvotg->clknum; i++) |
243 | clk_enable(mvotg->clk[i]); | 243 | clk_prepare_enable(mvotg->clk[i]); |
244 | } | 244 | } |
245 | 245 | ||
246 | static void otg_clock_disable(struct mv_otg *mvotg) | 246 | static void otg_clock_disable(struct mv_otg *mvotg) |
@@ -248,7 +248,7 @@ static void otg_clock_disable(struct mv_otg *mvotg) | |||
248 | unsigned int i; | 248 | unsigned int i; |
249 | 249 | ||
250 | for (i = 0; i < mvotg->clknum; i++) | 250 | for (i = 0; i < mvotg->clknum; i++) |
251 | clk_disable(mvotg->clk[i]); | 251 | clk_disable_unprepare(mvotg->clk[i]); |
252 | } | 252 | } |
253 | 253 | ||
254 | static int mv_otg_enable_internal(struct mv_otg *mvotg) | 254 | static int mv_otg_enable_internal(struct mv_otg *mvotg) |
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c index dd41f61893ef..f2985cd88021 100644 --- a/drivers/usb/renesas_usbhs/mod_gadget.c +++ b/drivers/usb/renesas_usbhs/mod_gadget.c | |||
@@ -545,15 +545,6 @@ static int usbhsg_pipe_disable(struct usbhsg_uep *uep) | |||
545 | return 0; | 545 | return 0; |
546 | } | 546 | } |
547 | 547 | ||
548 | static void usbhsg_uep_init(struct usbhsg_gpriv *gpriv) | ||
549 | { | ||
550 | int i; | ||
551 | struct usbhsg_uep *uep; | ||
552 | |||
553 | usbhsg_for_each_uep_with_dcp(uep, gpriv, i) | ||
554 | uep->pipe = NULL; | ||
555 | } | ||
556 | |||
557 | /* | 548 | /* |
558 | * | 549 | * |
559 | * usb_ep_ops | 550 | * usb_ep_ops |
@@ -610,7 +601,12 @@ static int usbhsg_ep_disable(struct usb_ep *ep) | |||
610 | { | 601 | { |
611 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); | 602 | struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep); |
612 | 603 | ||
613 | return usbhsg_pipe_disable(uep); | 604 | usbhsg_pipe_disable(uep); |
605 | |||
606 | uep->pipe->mod_private = NULL; | ||
607 | uep->pipe = NULL; | ||
608 | |||
609 | return 0; | ||
614 | } | 610 | } |
615 | 611 | ||
616 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, | 612 | static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep, |
@@ -761,9 +757,8 @@ static int usbhsg_try_start(struct usbhs_priv *priv, u32 status) | |||
761 | usbhs_pipe_init(priv, | 757 | usbhs_pipe_init(priv, |
762 | usbhsg_dma_map_ctrl); | 758 | usbhsg_dma_map_ctrl); |
763 | usbhs_fifo_init(priv); | 759 | usbhs_fifo_init(priv); |
764 | usbhsg_uep_init(gpriv); | ||
765 | 760 | ||
766 | /* dcp init */ | 761 | /* dcp init instead of usbhsg_ep_enable() */ |
767 | dcp->pipe = usbhs_dcp_malloc(priv); | 762 | dcp->pipe = usbhs_dcp_malloc(priv); |
768 | dcp->pipe->mod_private = dcp; | 763 | dcp->pipe->mod_private = dcp; |
769 | usbhs_pipe_config_update(dcp->pipe, 0, 0, 64); | 764 | usbhs_pipe_config_update(dcp->pipe, 0, 0, 64); |
@@ -825,7 +820,7 @@ static int usbhsg_try_stop(struct usbhs_priv *priv, u32 status) | |||
825 | usbhs_sys_set_test_mode(priv, 0); | 820 | usbhs_sys_set_test_mode(priv, 0); |
826 | usbhs_sys_function_ctrl(priv, 0); | 821 | usbhs_sys_function_ctrl(priv, 0); |
827 | 822 | ||
828 | usbhsg_pipe_disable(dcp); | 823 | usbhsg_ep_disable(&dcp->ep); |
829 | 824 | ||
830 | dev_dbg(dev, "stop gadget\n"); | 825 | dev_dbg(dev, "stop gadget\n"); |
831 | 826 | ||
@@ -998,6 +993,7 @@ int usbhs_mod_gadget_probe(struct usbhs_priv *priv) | |||
998 | */ | 993 | */ |
999 | usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { | 994 | usbhsg_for_each_uep_with_dcp(uep, gpriv, i) { |
1000 | uep->gpriv = gpriv; | 995 | uep->gpriv = gpriv; |
996 | uep->pipe = NULL; | ||
1001 | snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); | 997 | snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i); |
1002 | 998 | ||
1003 | uep->ep.name = uep->ep_name; | 999 | uep->ep.name = uep->ep_name; |
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c index 3d3cd6ca2689..b86815421c8d 100644 --- a/drivers/usb/renesas_usbhs/mod_host.c +++ b/drivers/usb/renesas_usbhs/mod_host.c | |||
@@ -661,9 +661,10 @@ static void usbhsh_queue_done(struct usbhs_priv *priv, struct usbhs_pkt *pkt) | |||
661 | status = -ESHUTDOWN; | 661 | status = -ESHUTDOWN; |
662 | 662 | ||
663 | urb->actual_length = pkt->actual; | 663 | urb->actual_length = pkt->actual; |
664 | usbhsh_ureq_free(hpriv, ureq); | ||
665 | 664 | ||
666 | usbhsh_endpoint_sequence_save(hpriv, urb, pkt); | 665 | usbhsh_endpoint_sequence_save(hpriv, urb, pkt); |
666 | usbhsh_ureq_free(hpriv, ureq); | ||
667 | |||
667 | usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep)); | 668 | usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep)); |
668 | 669 | ||
669 | usb_hcd_unlink_urb_from_ep(hcd, urb); | 670 | usb_hcd_unlink_urb_from_ep(hcd, urb); |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index f14736f647ff..edc0f0dcad83 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
@@ -60,6 +60,7 @@ static const struct usb_device_id id_table[] = { | |||
60 | { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ | 60 | { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ |
61 | { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ | 61 | { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ |
62 | { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ | 62 | { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ |
63 | { USB_DEVICE(0x0FDE, 0xCA05) }, /* OWL Wireless Electricity Monitor CM-160 */ | ||
63 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ | 64 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ |
64 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 65 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
65 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ | 66 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ |
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index 0a373b3ae96a..90ceef1776c3 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
@@ -584,6 +584,7 @@ static struct usb_device_id id_table_combined [] = { | |||
584 | /* | 584 | /* |
585 | * ELV devices: | 585 | * ELV devices: |
586 | */ | 586 | */ |
587 | { USB_DEVICE(FTDI_ELV_VID, FTDI_ELV_WS300_PID) }, | ||
587 | { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, | 588 | { USB_DEVICE(FTDI_VID, FTDI_ELV_USR_PID) }, |
588 | { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, | 589 | { USB_DEVICE(FTDI_VID, FTDI_ELV_MSM1_PID) }, |
589 | { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, | 590 | { USB_DEVICE(FTDI_VID, FTDI_ELV_KL100_PID) }, |
@@ -670,6 +671,7 @@ static struct usb_device_id id_table_combined [] = { | |||
670 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, | 671 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_5_PID) }, |
671 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, | 672 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_6_PID) }, |
672 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, | 673 | { USB_DEVICE(FTDI_VID, XSENS_CONVERTER_7_PID) }, |
674 | { USB_DEVICE(FTDI_VID, FTDI_OMNI1509) }, | ||
673 | { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, | 675 | { USB_DEVICE(MOBILITY_VID, MOBILITY_USB_SERIAL_PID) }, |
674 | { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, | 676 | { USB_DEVICE(FTDI_VID, FTDI_ACTIVE_ROBOTS_PID) }, |
675 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, | 677 | { USB_DEVICE(FTDI_VID, FTDI_MHAM_KW_PID) }, |
@@ -875,6 +877,8 @@ static struct usb_device_id id_table_combined [] = { | |||
875 | { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), | 877 | { USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID), |
876 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, | 878 | .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk }, |
877 | { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, | 879 | { USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) }, |
880 | /* Crucible Devices */ | ||
881 | { USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) }, | ||
878 | { }, /* Optional parameter entry */ | 882 | { }, /* Optional parameter entry */ |
879 | { } /* Terminating entry */ | 883 | { } /* Terminating entry */ |
880 | }; | 884 | }; |
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h index 049b6e715fa4..9d359e189a64 100644 --- a/drivers/usb/serial/ftdi_sio_ids.h +++ b/drivers/usb/serial/ftdi_sio_ids.h | |||
@@ -147,6 +147,11 @@ | |||
147 | #define XSENS_CONVERTER_6_PID 0xD38E | 147 | #define XSENS_CONVERTER_6_PID 0xD38E |
148 | #define XSENS_CONVERTER_7_PID 0xD38F | 148 | #define XSENS_CONVERTER_7_PID 0xD38F |
149 | 149 | ||
150 | /** | ||
151 | * Zolix (www.zolix.com.cb) product ids | ||
152 | */ | ||
153 | #define FTDI_OMNI1509 0xD491 /* Omni1509 embedded USB-serial */ | ||
154 | |||
150 | /* | 155 | /* |
151 | * NDI (www.ndigital.com) product ids | 156 | * NDI (www.ndigital.com) product ids |
152 | */ | 157 | */ |
@@ -204,7 +209,7 @@ | |||
204 | 209 | ||
205 | /* | 210 | /* |
206 | * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). | 211 | * ELV USB devices submitted by Christian Abt of ELV (www.elv.de). |
207 | * All of these devices use FTDI's vendor ID (0x0403). | 212 | * Almost all of these devices use FTDI's vendor ID (0x0403). |
208 | * Further IDs taken from ELV Windows .inf file. | 213 | * Further IDs taken from ELV Windows .inf file. |
209 | * | 214 | * |
210 | * The previously included PID for the UO 100 module was incorrect. | 215 | * The previously included PID for the UO 100 module was incorrect. |
@@ -212,6 +217,8 @@ | |||
212 | * | 217 | * |
213 | * Armin Laeuger originally sent the PID for the UM 100 module. | 218 | * Armin Laeuger originally sent the PID for the UM 100 module. |
214 | */ | 219 | */ |
220 | #define FTDI_ELV_VID 0x1B1F /* ELV AG */ | ||
221 | #define FTDI_ELV_WS300_PID 0xC006 /* eQ3 WS 300 PC II */ | ||
215 | #define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */ | 222 | #define FTDI_ELV_USR_PID 0xE000 /* ELV Universal-Sound-Recorder */ |
216 | #define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */ | 223 | #define FTDI_ELV_MSM1_PID 0xE001 /* ELV Mini-Sound-Modul */ |
217 | #define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */ | 224 | #define FTDI_ELV_KL100_PID 0xE002 /* ELV Kfz-Leistungsmesser KL 100 */ |
@@ -1259,3 +1266,9 @@ | |||
1259 | * ATI command output: Cinterion MC55i | 1266 | * ATI command output: Cinterion MC55i |
1260 | */ | 1267 | */ |
1261 | #define FTDI_CINTERION_MC55I_PID 0xA951 | 1268 | #define FTDI_CINTERION_MC55I_PID 0xA951 |
1269 | |||
1270 | /* | ||
1271 | * Product: Comet Caller ID decoder | ||
1272 | * Manufacturer: Crucible Technologies | ||
1273 | */ | ||
1274 | #define FTDI_CT_COMET_PID 0x8e08 | ||
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 58184f3de686..82afc4d6a327 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
@@ -530,6 +530,9 @@ static void chase_port(struct edgeport_port *port, unsigned long timeout, | |||
530 | wait_queue_t wait; | 530 | wait_queue_t wait; |
531 | unsigned long flags; | 531 | unsigned long flags; |
532 | 532 | ||
533 | if (!tty) | ||
534 | return; | ||
535 | |||
533 | if (!timeout) | 536 | if (!timeout) |
534 | timeout = (HZ * EDGE_CLOSING_WAIT)/100; | 537 | timeout = (HZ * EDGE_CLOSING_WAIT)/100; |
535 | 538 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index e6f87b76c715..567bc77d6397 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
@@ -242,6 +242,7 @@ static void option_instat_callback(struct urb *urb); | |||
242 | #define TELIT_PRODUCT_CC864_DUAL 0x1005 | 242 | #define TELIT_PRODUCT_CC864_DUAL 0x1005 |
243 | #define TELIT_PRODUCT_CC864_SINGLE 0x1006 | 243 | #define TELIT_PRODUCT_CC864_SINGLE 0x1006 |
244 | #define TELIT_PRODUCT_DE910_DUAL 0x1010 | 244 | #define TELIT_PRODUCT_DE910_DUAL 0x1010 |
245 | #define TELIT_PRODUCT_LE920 0x1200 | ||
245 | 246 | ||
246 | /* ZTE PRODUCTS */ | 247 | /* ZTE PRODUCTS */ |
247 | #define ZTE_VENDOR_ID 0x19d2 | 248 | #define ZTE_VENDOR_ID 0x19d2 |
@@ -288,6 +289,7 @@ static void option_instat_callback(struct urb *urb); | |||
288 | #define ALCATEL_VENDOR_ID 0x1bbb | 289 | #define ALCATEL_VENDOR_ID 0x1bbb |
289 | #define ALCATEL_PRODUCT_X060S_X200 0x0000 | 290 | #define ALCATEL_PRODUCT_X060S_X200 0x0000 |
290 | #define ALCATEL_PRODUCT_X220_X500D 0x0017 | 291 | #define ALCATEL_PRODUCT_X220_X500D 0x0017 |
292 | #define ALCATEL_PRODUCT_L100V 0x011e | ||
291 | 293 | ||
292 | #define PIRELLI_VENDOR_ID 0x1266 | 294 | #define PIRELLI_VENDOR_ID 0x1266 |
293 | #define PIRELLI_PRODUCT_C100_1 0x1002 | 295 | #define PIRELLI_PRODUCT_C100_1 0x1002 |
@@ -429,9 +431,12 @@ static void option_instat_callback(struct urb *urb); | |||
429 | #define MEDIATEK_VENDOR_ID 0x0e8d | 431 | #define MEDIATEK_VENDOR_ID 0x0e8d |
430 | #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 | 432 | #define MEDIATEK_PRODUCT_DC_1COM 0x00a0 |
431 | #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 | 433 | #define MEDIATEK_PRODUCT_DC_4COM 0x00a5 |
434 | #define MEDIATEK_PRODUCT_DC_4COM2 0x00a7 | ||
432 | #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 | 435 | #define MEDIATEK_PRODUCT_DC_5COM 0x00a4 |
433 | #define MEDIATEK_PRODUCT_7208_1COM 0x7101 | 436 | #define MEDIATEK_PRODUCT_7208_1COM 0x7101 |
434 | #define MEDIATEK_PRODUCT_7208_2COM 0x7102 | 437 | #define MEDIATEK_PRODUCT_7208_2COM 0x7102 |
438 | #define MEDIATEK_PRODUCT_7103_2COM 0x7103 | ||
439 | #define MEDIATEK_PRODUCT_7106_2COM 0x7106 | ||
435 | #define MEDIATEK_PRODUCT_FP_1COM 0x0003 | 440 | #define MEDIATEK_PRODUCT_FP_1COM 0x0003 |
436 | #define MEDIATEK_PRODUCT_FP_2COM 0x0023 | 441 | #define MEDIATEK_PRODUCT_FP_2COM 0x0023 |
437 | #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 | 442 | #define MEDIATEK_PRODUCT_FPDC_1COM 0x0043 |
@@ -441,6 +446,18 @@ static void option_instat_callback(struct urb *urb); | |||
441 | #define CELLIENT_VENDOR_ID 0x2692 | 446 | #define CELLIENT_VENDOR_ID 0x2692 |
442 | #define CELLIENT_PRODUCT_MEN200 0x9005 | 447 | #define CELLIENT_PRODUCT_MEN200 0x9005 |
443 | 448 | ||
449 | /* Hyundai Petatel Inc. products */ | ||
450 | #define PETATEL_VENDOR_ID 0x1ff4 | ||
451 | #define PETATEL_PRODUCT_NP10T 0x600e | ||
452 | |||
453 | /* TP-LINK Incorporated products */ | ||
454 | #define TPLINK_VENDOR_ID 0x2357 | ||
455 | #define TPLINK_PRODUCT_MA180 0x0201 | ||
456 | |||
457 | /* Changhong products */ | ||
458 | #define CHANGHONG_VENDOR_ID 0x2077 | ||
459 | #define CHANGHONG_PRODUCT_CH690 0x7001 | ||
460 | |||
444 | /* some devices interfaces need special handling due to a number of reasons */ | 461 | /* some devices interfaces need special handling due to a number of reasons */ |
445 | enum option_blacklist_reason { | 462 | enum option_blacklist_reason { |
446 | OPTION_BLACKLIST_NONE = 0, | 463 | OPTION_BLACKLIST_NONE = 0, |
@@ -522,6 +539,11 @@ static const struct option_blacklist_info zte_1255_blacklist = { | |||
522 | .reserved = BIT(3) | BIT(4), | 539 | .reserved = BIT(3) | BIT(4), |
523 | }; | 540 | }; |
524 | 541 | ||
542 | static const struct option_blacklist_info telit_le920_blacklist = { | ||
543 | .sendsetup = BIT(0), | ||
544 | .reserved = BIT(1) | BIT(5), | ||
545 | }; | ||
546 | |||
525 | static const struct usb_device_id option_ids[] = { | 547 | static const struct usb_device_id option_ids[] = { |
526 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, | 548 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) }, |
527 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, | 549 | { USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) }, |
@@ -772,6 +794,8 @@ static const struct usb_device_id option_ids[] = { | |||
772 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, | 794 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_DUAL) }, |
773 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, | 795 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) }, |
774 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, | 796 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) }, |
797 | { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920), | ||
798 | .driver_info = (kernel_ulong_t)&telit_le920_blacklist }, | ||
775 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ | 799 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MF622, 0xff, 0xff, 0xff) }, /* ZTE WCDMA products */ |
776 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), | 800 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0002, 0xff, 0xff, 0xff), |
777 | .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, | 801 | .driver_info = (kernel_ulong_t)&net_intf1_blacklist }, |
@@ -922,8 +946,10 @@ static const struct usb_device_id option_ids[] = { | |||
922 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, | 946 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) }, |
923 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ | 947 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */ |
924 | .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, | 948 | .driver_info = (kernel_ulong_t)&net_intf3_blacklist }, |
925 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) }, | 949 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */ |
926 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) }, | 950 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, |
951 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */ | ||
952 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | ||
927 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, | 953 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) }, |
928 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), | 954 | { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff), |
929 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | 955 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, |
@@ -1190,6 +1216,8 @@ static const struct usb_device_id option_ids[] = { | |||
1190 | .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist | 1216 | .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist |
1191 | }, | 1217 | }, |
1192 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, | 1218 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) }, |
1219 | { USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V), | ||
1220 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | ||
1193 | { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, | 1221 | { USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) }, |
1194 | { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, | 1222 | { USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) }, |
1195 | { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), | 1223 | { USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14), |
@@ -1294,7 +1322,15 @@ static const struct usb_device_id option_ids[] = { | |||
1294 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, | 1322 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) }, |
1295 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, | 1323 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) }, |
1296 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, | 1324 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) }, |
1325 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) }, | ||
1326 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) }, | ||
1327 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) }, | ||
1328 | { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) }, | ||
1297 | { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, | 1329 | { USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) }, |
1330 | { USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) }, | ||
1331 | { USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180), | ||
1332 | .driver_info = (kernel_ulong_t)&net_intf4_blacklist }, | ||
1333 | { USB_DEVICE(CHANGHONG_VENDOR_ID, CHANGHONG_PRODUCT_CH690) }, | ||
1298 | { } /* Terminating entry */ | 1334 | { } /* Terminating entry */ |
1299 | }; | 1335 | }; |
1300 | MODULE_DEVICE_TABLE(usb, option_ids); | 1336 | MODULE_DEVICE_TABLE(usb, option_ids); |
diff --git a/drivers/usb/serial/qcserial.c b/drivers/usb/serial/qcserial.c index aa148c21ea40..24662547dc5b 100644 --- a/drivers/usb/serial/qcserial.c +++ b/drivers/usb/serial/qcserial.c | |||
@@ -53,6 +53,7 @@ static const struct usb_device_id id_table[] = { | |||
53 | {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ | 53 | {DEVICE_G1K(0x05c6, 0x9221)}, /* Generic Gobi QDL device */ |
54 | {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ | 54 | {DEVICE_G1K(0x05c6, 0x9231)}, /* Generic Gobi QDL device */ |
55 | {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ | 55 | {DEVICE_G1K(0x1f45, 0x0001)}, /* Unknown Gobi QDL device */ |
56 | {DEVICE_G1K(0x1bc7, 0x900e)}, /* Telit Gobi QDL device */ | ||
56 | 57 | ||
57 | /* Gobi 2000 devices */ | 58 | /* Gobi 2000 devices */ |
58 | {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ | 59 | {USB_DEVICE(0x1410, 0xa010)}, /* Novatel Gobi 2000 QDL device */ |
diff --git a/drivers/usb/storage/initializers.c b/drivers/usb/storage/initializers.c index 105d900150c1..16b0bf055eeb 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 E220 devices in multi-port mode */ | 95 | /* This places the HUAWEI usb dongles in multi-port mode */ |
96 | int usb_stor_huawei_e220_init(struct us_data *us) | 96 | static int usb_stor_huawei_feature_init(struct us_data *us) |
97 | { | 97 | { |
98 | int result; | 98 | int result; |
99 | 99 | ||
@@ -104,3 +104,75 @@ int usb_stor_huawei_e220_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 = 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 (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 529327fbb06b..5376d4fc76f0 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 E220 devices in multi-port mode */ | 49 | /* This places the HUAWEI usb dongles in multi-port mode */ |
50 | int usb_stor_huawei_e220_init(struct us_data *us); | 50 | int usb_stor_huawei_init(struct us_data *us); |
diff --git a/drivers/usb/storage/unusual_devs.h b/drivers/usb/storage/unusual_devs.h index d305a5aa3a5d..72923b56bbf6 100644 --- a/drivers/usb/storage/unusual_devs.h +++ b/drivers/usb/storage/unusual_devs.h | |||
@@ -1527,335 +1527,10 @@ UNUSUAL_DEV( 0x1210, 0x0003, 0x0100, 0x0100, | |||
1527 | /* Reported by fangxiaozhi <huananhu@huawei.com> | 1527 | /* Reported by fangxiaozhi <huananhu@huawei.com> |
1528 | * This brings the HUAWEI data card devices into multi-port mode | 1528 | * This brings the HUAWEI data card devices into multi-port mode |
1529 | */ | 1529 | */ |
1530 | UNUSUAL_DEV( 0x12d1, 0x1001, 0x0000, 0x0000, | 1530 | UNUSUAL_VENDOR_INTF(0x12d1, 0x08, 0x06, 0x50, |
1531 | "HUAWEI MOBILE", | 1531 | "HUAWEI MOBILE", |
1532 | "Mass Storage", | 1532 | "Mass Storage", |
1533 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | 1533 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_init, |
1534 | 0), | ||
1535 | UNUSUAL_DEV( 0x12d1, 0x1003, 0x0000, 0x0000, | ||
1536 | "HUAWEI MOBILE", | ||
1537 | "Mass Storage", | ||
1538 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1539 | 0), | ||
1540 | UNUSUAL_DEV( 0x12d1, 0x1004, 0x0000, 0x0000, | ||
1541 | "HUAWEI MOBILE", | ||
1542 | "Mass Storage", | ||
1543 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1544 | 0), | ||
1545 | UNUSUAL_DEV( 0x12d1, 0x1401, 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, 0x1402, 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, 0x1403, 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, 0x1404, 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, 0x1405, 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, 0x1406, 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, 0x1407, 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, 0x1408, 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, 0x1409, 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, 0x140A, 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, 0x140B, 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, 0x140C, 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, 0x140D, 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, 0x140E, 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, 0x140F, 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, 0x1410, 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, 0x1411, 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, 0x1412, 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, 0x1413, 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, 0x1414, 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, 0x1415, 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, 0x1416, 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, 0x1417, 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, 0x1418, 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, 0x1419, 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, 0x141A, 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, 0x141B, 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, 0x141C, 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, 0x141D, 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, 0x141E, 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, 0x141F, 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, 0x1420, 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, 0x1421, 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, 0x1422, 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, 0x1423, 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, 0x1424, 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, 0x1425, 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, 0x1426, 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, 0x1427, 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, 0x1428, 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, 0x1429, 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, 0x142A, 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, 0x142B, 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, 0x142C, 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, 0x142D, 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, 0x142E, 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, 0x142F, 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, 0x1430, 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, 0x1431, 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, 0x1432, 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, 0x1433, 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, 0x1434, 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, 0x1435, 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, 0x1436, 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, 0x1437, 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, 0x1438, 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, 0x1439, 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, 0x143A, 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, 0x143B, 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, 0x143C, 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, 0x143D, 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, 0x143E, 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, 0x143F, 0x0000, 0x0000, | ||
1856 | "HUAWEI MOBILE", | ||
1857 | "Mass Storage", | ||
1858 | USB_SC_DEVICE, USB_PR_DEVICE, usb_stor_huawei_e220_init, | ||
1859 | 0), | 1534 | 0), |
1860 | 1535 | ||
1861 | /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ | 1536 | /* Reported by Vilius Bilinkevicius <vilisas AT xxx DOT lt) */ |
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c index 31b3e1a61bbd..cf09b6ba71ff 100644 --- a/drivers/usb/storage/usb.c +++ b/drivers/usb/storage/usb.c | |||
@@ -120,6 +120,17 @@ MODULE_PARM_DESC(quirks, "supplemental list of device IDs and their quirks"); | |||
120 | .useTransport = use_transport, \ | 120 | .useTransport = use_transport, \ |
121 | } | 121 | } |
122 | 122 | ||
123 | #define UNUSUAL_VENDOR_INTF(idVendor, cl, sc, pr, \ | ||
124 | vendor_name, product_name, use_protocol, use_transport, \ | ||
125 | init_function, Flags) \ | ||
126 | { \ | ||
127 | .vendorName = vendor_name, \ | ||
128 | .productName = product_name, \ | ||
129 | .useProtocol = use_protocol, \ | ||
130 | .useTransport = use_transport, \ | ||
131 | .initFunction = init_function, \ | ||
132 | } | ||
133 | |||
123 | static struct us_unusual_dev us_unusual_dev_list[] = { | 134 | static struct us_unusual_dev us_unusual_dev_list[] = { |
124 | # include "unusual_devs.h" | 135 | # include "unusual_devs.h" |
125 | { } /* Terminating entry */ | 136 | { } /* Terminating entry */ |
@@ -131,6 +142,7 @@ static struct us_unusual_dev for_dynamic_ids = | |||
131 | #undef UNUSUAL_DEV | 142 | #undef UNUSUAL_DEV |
132 | #undef COMPLIANT_DEV | 143 | #undef COMPLIANT_DEV |
133 | #undef USUAL_DEV | 144 | #undef USUAL_DEV |
145 | #undef UNUSUAL_VENDOR_INTF | ||
134 | 146 | ||
135 | #ifdef CONFIG_LOCKDEP | 147 | #ifdef CONFIG_LOCKDEP |
136 | 148 | ||
diff --git a/drivers/usb/storage/usual-tables.c b/drivers/usb/storage/usual-tables.c index b78a526910fb..5ef8ce74aae4 100644 --- a/drivers/usb/storage/usual-tables.c +++ b/drivers/usb/storage/usual-tables.c | |||
@@ -41,6 +41,20 @@ | |||
41 | #define USUAL_DEV(useProto, useTrans) \ | 41 | #define USUAL_DEV(useProto, useTrans) \ |
42 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) } | 42 | { USB_INTERFACE_INFO(USB_CLASS_MASS_STORAGE, useProto, useTrans) } |
43 | 43 | ||
44 | /* Define the device is matched with Vendor ID and interface descriptors */ | ||
45 | #define UNUSUAL_VENDOR_INTF(id_vendor, cl, sc, pr, \ | ||
46 | vendorName, productName, useProtocol, useTransport, \ | ||
47 | initFunction, flags) \ | ||
48 | { \ | ||
49 | .match_flags = USB_DEVICE_ID_MATCH_INT_INFO \ | ||
50 | | USB_DEVICE_ID_MATCH_VENDOR, \ | ||
51 | .idVendor = (id_vendor), \ | ||
52 | .bInterfaceClass = (cl), \ | ||
53 | .bInterfaceSubClass = (sc), \ | ||
54 | .bInterfaceProtocol = (pr), \ | ||
55 | .driver_info = (flags) \ | ||
56 | } | ||
57 | |||
44 | struct usb_device_id usb_storage_usb_ids[] = { | 58 | struct usb_device_id usb_storage_usb_ids[] = { |
45 | # include "unusual_devs.h" | 59 | # include "unusual_devs.h" |
46 | { } /* Terminating entry */ | 60 | { } /* Terminating entry */ |
@@ -50,6 +64,7 @@ MODULE_DEVICE_TABLE(usb, usb_storage_usb_ids); | |||
50 | #undef UNUSUAL_DEV | 64 | #undef UNUSUAL_DEV |
51 | #undef COMPLIANT_DEV | 65 | #undef COMPLIANT_DEV |
52 | #undef USUAL_DEV | 66 | #undef USUAL_DEV |
67 | #undef UNUSUAL_VENDOR_INTF | ||
53 | 68 | ||
54 | /* | 69 | /* |
55 | * The table of devices to ignore | 70 | * The table of devices to ignore |
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 4362d9e7baa3..f72323ef618f 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c | |||
@@ -240,17 +240,17 @@ ssize_t vfio_pci_mem_readwrite(struct vfio_pci_device *vdev, char __user *buf, | |||
240 | filled = 1; | 240 | filled = 1; |
241 | } else { | 241 | } else { |
242 | /* Drop writes, fill reads with FF */ | 242 | /* Drop writes, fill reads with FF */ |
243 | filled = min((size_t)(x_end - pos), count); | ||
243 | if (!iswrite) { | 244 | if (!iswrite) { |
244 | char val = 0xFF; | 245 | char val = 0xFF; |
245 | size_t i; | 246 | size_t i; |
246 | 247 | ||
247 | for (i = 0; i < x_end - pos; i++) { | 248 | for (i = 0; i < filled; i++) { |
248 | if (put_user(val, buf + i)) | 249 | if (put_user(val, buf + i)) |
249 | goto out; | 250 | goto out; |
250 | } | 251 | } |
251 | } | 252 | } |
252 | 253 | ||
253 | filled = x_end - pos; | ||
254 | } | 254 | } |
255 | 255 | ||
256 | count -= filled; | 256 | count -= filled; |
diff --git a/drivers/vhost/net.c b/drivers/vhost/net.c index ebd08b21b234..959b1cd89e6a 100644 --- a/drivers/vhost/net.c +++ b/drivers/vhost/net.c | |||
@@ -165,12 +165,16 @@ static void tx_poll_stop(struct vhost_net *net) | |||
165 | } | 165 | } |
166 | 166 | ||
167 | /* Caller must have TX VQ lock */ | 167 | /* Caller must have TX VQ lock */ |
168 | static void tx_poll_start(struct vhost_net *net, struct socket *sock) | 168 | static int tx_poll_start(struct vhost_net *net, struct socket *sock) |
169 | { | 169 | { |
170 | int ret; | ||
171 | |||
170 | if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED)) | 172 | if (unlikely(net->tx_poll_state != VHOST_NET_POLL_STOPPED)) |
171 | return; | 173 | return 0; |
172 | vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file); | 174 | ret = vhost_poll_start(net->poll + VHOST_NET_VQ_TX, sock->file); |
173 | net->tx_poll_state = VHOST_NET_POLL_STARTED; | 175 | if (!ret) |
176 | net->tx_poll_state = VHOST_NET_POLL_STARTED; | ||
177 | return ret; | ||
174 | } | 178 | } |
175 | 179 | ||
176 | /* In case of DMA done not in order in lower device driver for some reason. | 180 | /* In case of DMA done not in order in lower device driver for some reason. |
@@ -642,20 +646,23 @@ static void vhost_net_disable_vq(struct vhost_net *n, | |||
642 | vhost_poll_stop(n->poll + VHOST_NET_VQ_RX); | 646 | vhost_poll_stop(n->poll + VHOST_NET_VQ_RX); |
643 | } | 647 | } |
644 | 648 | ||
645 | static void vhost_net_enable_vq(struct vhost_net *n, | 649 | static int vhost_net_enable_vq(struct vhost_net *n, |
646 | struct vhost_virtqueue *vq) | 650 | struct vhost_virtqueue *vq) |
647 | { | 651 | { |
648 | struct socket *sock; | 652 | struct socket *sock; |
653 | int ret; | ||
649 | 654 | ||
650 | sock = rcu_dereference_protected(vq->private_data, | 655 | sock = rcu_dereference_protected(vq->private_data, |
651 | lockdep_is_held(&vq->mutex)); | 656 | lockdep_is_held(&vq->mutex)); |
652 | if (!sock) | 657 | if (!sock) |
653 | return; | 658 | return 0; |
654 | if (vq == n->vqs + VHOST_NET_VQ_TX) { | 659 | if (vq == n->vqs + VHOST_NET_VQ_TX) { |
655 | n->tx_poll_state = VHOST_NET_POLL_STOPPED; | 660 | n->tx_poll_state = VHOST_NET_POLL_STOPPED; |
656 | tx_poll_start(n, sock); | 661 | ret = tx_poll_start(n, sock); |
657 | } else | 662 | } else |
658 | vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file); | 663 | ret = vhost_poll_start(n->poll + VHOST_NET_VQ_RX, sock->file); |
664 | |||
665 | return ret; | ||
659 | } | 666 | } |
660 | 667 | ||
661 | static struct socket *vhost_net_stop_vq(struct vhost_net *n, | 668 | static struct socket *vhost_net_stop_vq(struct vhost_net *n, |
@@ -827,15 +834,18 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
827 | r = PTR_ERR(ubufs); | 834 | r = PTR_ERR(ubufs); |
828 | goto err_ubufs; | 835 | goto err_ubufs; |
829 | } | 836 | } |
830 | oldubufs = vq->ubufs; | 837 | |
831 | vq->ubufs = ubufs; | ||
832 | vhost_net_disable_vq(n, vq); | 838 | vhost_net_disable_vq(n, vq); |
833 | rcu_assign_pointer(vq->private_data, sock); | 839 | rcu_assign_pointer(vq->private_data, sock); |
834 | vhost_net_enable_vq(n, vq); | ||
835 | |||
836 | r = vhost_init_used(vq); | 840 | r = vhost_init_used(vq); |
837 | if (r) | 841 | if (r) |
838 | goto err_vq; | 842 | goto err_used; |
843 | r = vhost_net_enable_vq(n, vq); | ||
844 | if (r) | ||
845 | goto err_used; | ||
846 | |||
847 | oldubufs = vq->ubufs; | ||
848 | vq->ubufs = ubufs; | ||
839 | 849 | ||
840 | n->tx_packets = 0; | 850 | n->tx_packets = 0; |
841 | n->tx_zcopy_err = 0; | 851 | n->tx_zcopy_err = 0; |
@@ -859,6 +869,11 @@ static long vhost_net_set_backend(struct vhost_net *n, unsigned index, int fd) | |||
859 | mutex_unlock(&n->dev.mutex); | 869 | mutex_unlock(&n->dev.mutex); |
860 | return 0; | 870 | return 0; |
861 | 871 | ||
872 | err_used: | ||
873 | rcu_assign_pointer(vq->private_data, oldsock); | ||
874 | vhost_net_enable_vq(n, vq); | ||
875 | if (ubufs) | ||
876 | vhost_ubuf_put_and_wait(ubufs); | ||
862 | err_ubufs: | 877 | err_ubufs: |
863 | fput(sock->file); | 878 | fput(sock->file); |
864 | err_vq: | 879 | err_vq: |
diff --git a/drivers/vhost/tcm_vhost.c b/drivers/vhost/tcm_vhost.c index b20df5c829f5..22321cf84fbe 100644 --- a/drivers/vhost/tcm_vhost.c +++ b/drivers/vhost/tcm_vhost.c | |||
@@ -575,10 +575,8 @@ static void vhost_scsi_handle_vq(struct vhost_scsi *vs) | |||
575 | 575 | ||
576 | /* Must use ioctl VHOST_SCSI_SET_ENDPOINT */ | 576 | /* Must use ioctl VHOST_SCSI_SET_ENDPOINT */ |
577 | tv_tpg = vs->vs_tpg; | 577 | tv_tpg = vs->vs_tpg; |
578 | if (unlikely(!tv_tpg)) { | 578 | if (unlikely(!tv_tpg)) |
579 | pr_err("%s endpoint not set\n", __func__); | ||
580 | return; | 579 | return; |
581 | } | ||
582 | 580 | ||
583 | mutex_lock(&vq->mutex); | 581 | mutex_lock(&vq->mutex); |
584 | vhost_disable_notify(&vs->dev, vq); | 582 | vhost_disable_notify(&vs->dev, vq); |
diff --git a/drivers/vhost/vhost.c b/drivers/vhost/vhost.c index 34389f75fe65..9759249e6d90 100644 --- a/drivers/vhost/vhost.c +++ b/drivers/vhost/vhost.c | |||
@@ -77,26 +77,38 @@ void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, | |||
77 | init_poll_funcptr(&poll->table, vhost_poll_func); | 77 | init_poll_funcptr(&poll->table, vhost_poll_func); |
78 | poll->mask = mask; | 78 | poll->mask = mask; |
79 | poll->dev = dev; | 79 | poll->dev = dev; |
80 | poll->wqh = NULL; | ||
80 | 81 | ||
81 | vhost_work_init(&poll->work, fn); | 82 | vhost_work_init(&poll->work, fn); |
82 | } | 83 | } |
83 | 84 | ||
84 | /* Start polling a file. We add ourselves to file's wait queue. The caller must | 85 | /* Start polling a file. We add ourselves to file's wait queue. The caller must |
85 | * keep a reference to a file until after vhost_poll_stop is called. */ | 86 | * keep a reference to a file until after vhost_poll_stop is called. */ |
86 | void vhost_poll_start(struct vhost_poll *poll, struct file *file) | 87 | int vhost_poll_start(struct vhost_poll *poll, struct file *file) |
87 | { | 88 | { |
88 | unsigned long mask; | 89 | unsigned long mask; |
90 | int ret = 0; | ||
89 | 91 | ||
90 | mask = file->f_op->poll(file, &poll->table); | 92 | mask = file->f_op->poll(file, &poll->table); |
91 | if (mask) | 93 | if (mask) |
92 | vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); | 94 | vhost_poll_wakeup(&poll->wait, 0, 0, (void *)mask); |
95 | if (mask & POLLERR) { | ||
96 | if (poll->wqh) | ||
97 | remove_wait_queue(poll->wqh, &poll->wait); | ||
98 | ret = -EINVAL; | ||
99 | } | ||
100 | |||
101 | return ret; | ||
93 | } | 102 | } |
94 | 103 | ||
95 | /* Stop polling a file. After this function returns, it becomes safe to drop the | 104 | /* Stop polling a file. After this function returns, it becomes safe to drop the |
96 | * file reference. You must also flush afterwards. */ | 105 | * file reference. You must also flush afterwards. */ |
97 | void vhost_poll_stop(struct vhost_poll *poll) | 106 | void vhost_poll_stop(struct vhost_poll *poll) |
98 | { | 107 | { |
99 | remove_wait_queue(poll->wqh, &poll->wait); | 108 | if (poll->wqh) { |
109 | remove_wait_queue(poll->wqh, &poll->wait); | ||
110 | poll->wqh = NULL; | ||
111 | } | ||
100 | } | 112 | } |
101 | 113 | ||
102 | static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, | 114 | static bool vhost_work_seq_done(struct vhost_dev *dev, struct vhost_work *work, |
@@ -792,7 +804,7 @@ long vhost_vring_ioctl(struct vhost_dev *d, int ioctl, void __user *argp) | |||
792 | fput(filep); | 804 | fput(filep); |
793 | 805 | ||
794 | if (pollstart && vq->handle_kick) | 806 | if (pollstart && vq->handle_kick) |
795 | vhost_poll_start(&vq->poll, vq->kick); | 807 | r = vhost_poll_start(&vq->poll, vq->kick); |
796 | 808 | ||
797 | mutex_unlock(&vq->mutex); | 809 | mutex_unlock(&vq->mutex); |
798 | 810 | ||
diff --git a/drivers/vhost/vhost.h b/drivers/vhost/vhost.h index 2639c58b23ab..17261e277c02 100644 --- a/drivers/vhost/vhost.h +++ b/drivers/vhost/vhost.h | |||
@@ -42,7 +42,7 @@ void vhost_work_queue(struct vhost_dev *dev, struct vhost_work *work); | |||
42 | 42 | ||
43 | void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, | 43 | void vhost_poll_init(struct vhost_poll *poll, vhost_work_fn_t fn, |
44 | unsigned long mask, struct vhost_dev *dev); | 44 | unsigned long mask, struct vhost_dev *dev); |
45 | void vhost_poll_start(struct vhost_poll *poll, struct file *file); | 45 | int vhost_poll_start(struct vhost_poll *poll, struct file *file); |
46 | void vhost_poll_stop(struct vhost_poll *poll); | 46 | void vhost_poll_stop(struct vhost_poll *poll); |
47 | void vhost_poll_flush(struct vhost_poll *poll); | 47 | void vhost_poll_flush(struct vhost_poll *poll); |
48 | void vhost_poll_queue(struct vhost_poll *poll); | 48 | void vhost_poll_queue(struct vhost_poll *poll); |
diff --git a/drivers/video/exynos/exynos_dp_core.c b/drivers/video/exynos/exynos_dp_core.c index 4ef18e2e90cc..2d0d144add1b 100644 --- a/drivers/video/exynos/exynos_dp_core.c +++ b/drivers/video/exynos/exynos_dp_core.c | |||
@@ -1121,8 +1121,7 @@ static int exynos_dp_remove(struct platform_device *pdev) | |||
1121 | 1121 | ||
1122 | disable_irq(dp->irq); | 1122 | disable_irq(dp->irq); |
1123 | 1123 | ||
1124 | if (work_pending(&dp->hotplug_work)) | 1124 | flush_work(&dp->hotplug_work); |
1125 | flush_work(&dp->hotplug_work); | ||
1126 | 1125 | ||
1127 | if (pdev->dev.of_node) { | 1126 | if (pdev->dev.of_node) { |
1128 | if (dp->phy_addr) | 1127 | if (dp->phy_addr) |
@@ -1144,8 +1143,7 @@ static int exynos_dp_suspend(struct device *dev) | |||
1144 | struct exynos_dp_platdata *pdata = dev->platform_data; | 1143 | struct exynos_dp_platdata *pdata = dev->platform_data; |
1145 | struct exynos_dp_device *dp = dev_get_drvdata(dev); | 1144 | struct exynos_dp_device *dp = dev_get_drvdata(dev); |
1146 | 1145 | ||
1147 | if (work_pending(&dp->hotplug_work)) | 1146 | flush_work(&dp->hotplug_work); |
1148 | flush_work(&dp->hotplug_work); | ||
1149 | 1147 | ||
1150 | if (dev->of_node) { | 1148 | if (dev->of_node) { |
1151 | if (dp->phy_addr) | 1149 | if (dp->phy_addr) |
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c index 12526787a7c7..0abf2bf20836 100644 --- a/drivers/video/imxfb.c +++ b/drivers/video/imxfb.c | |||
@@ -139,6 +139,7 @@ struct imxfb_info { | |||
139 | struct clk *clk_ahb; | 139 | struct clk *clk_ahb; |
140 | struct clk *clk_per; | 140 | struct clk *clk_per; |
141 | enum imxfb_type devtype; | 141 | enum imxfb_type devtype; |
142 | bool enabled; | ||
142 | 143 | ||
143 | /* | 144 | /* |
144 | * These are the addresses we mapped | 145 | * These are the addresses we mapped |
@@ -536,6 +537,10 @@ static void imxfb_exit_backlight(struct imxfb_info *fbi) | |||
536 | 537 | ||
537 | static void imxfb_enable_controller(struct imxfb_info *fbi) | 538 | static void imxfb_enable_controller(struct imxfb_info *fbi) |
538 | { | 539 | { |
540 | |||
541 | if (fbi->enabled) | ||
542 | return; | ||
543 | |||
539 | pr_debug("Enabling LCD controller\n"); | 544 | pr_debug("Enabling LCD controller\n"); |
540 | 545 | ||
541 | writel(fbi->screen_dma, fbi->regs + LCDC_SSA); | 546 | writel(fbi->screen_dma, fbi->regs + LCDC_SSA); |
@@ -556,6 +561,7 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
556 | clk_prepare_enable(fbi->clk_ipg); | 561 | clk_prepare_enable(fbi->clk_ipg); |
557 | clk_prepare_enable(fbi->clk_ahb); | 562 | clk_prepare_enable(fbi->clk_ahb); |
558 | clk_prepare_enable(fbi->clk_per); | 563 | clk_prepare_enable(fbi->clk_per); |
564 | fbi->enabled = true; | ||
559 | 565 | ||
560 | if (fbi->backlight_power) | 566 | if (fbi->backlight_power) |
561 | fbi->backlight_power(1); | 567 | fbi->backlight_power(1); |
@@ -565,6 +571,9 @@ static void imxfb_enable_controller(struct imxfb_info *fbi) | |||
565 | 571 | ||
566 | static void imxfb_disable_controller(struct imxfb_info *fbi) | 572 | static void imxfb_disable_controller(struct imxfb_info *fbi) |
567 | { | 573 | { |
574 | if (!fbi->enabled) | ||
575 | return; | ||
576 | |||
568 | pr_debug("Disabling LCD controller\n"); | 577 | pr_debug("Disabling LCD controller\n"); |
569 | 578 | ||
570 | if (fbi->backlight_power) | 579 | if (fbi->backlight_power) |
@@ -575,6 +584,7 @@ static void imxfb_disable_controller(struct imxfb_info *fbi) | |||
575 | clk_disable_unprepare(fbi->clk_per); | 584 | clk_disable_unprepare(fbi->clk_per); |
576 | clk_disable_unprepare(fbi->clk_ipg); | 585 | clk_disable_unprepare(fbi->clk_ipg); |
577 | clk_disable_unprepare(fbi->clk_ahb); | 586 | clk_disable_unprepare(fbi->clk_ahb); |
587 | fbi->enabled = false; | ||
578 | 588 | ||
579 | writel(0, fbi->regs + LCDC_RMCR); | 589 | writel(0, fbi->regs + LCDC_RMCR); |
580 | } | 590 | } |
@@ -729,6 +739,8 @@ static int __init imxfb_init_fbinfo(struct platform_device *pdev) | |||
729 | 739 | ||
730 | memset(fbi, 0, sizeof(struct imxfb_info)); | 740 | memset(fbi, 0, sizeof(struct imxfb_info)); |
731 | 741 | ||
742 | fbi->devtype = pdev->id_entry->driver_data; | ||
743 | |||
732 | strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); | 744 | strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id)); |
733 | 745 | ||
734 | info->fix.type = FB_TYPE_PACKED_PIXELS; | 746 | info->fix.type = FB_TYPE_PACKED_PIXELS; |
@@ -789,7 +801,6 @@ static int __init imxfb_probe(struct platform_device *pdev) | |||
789 | return -ENOMEM; | 801 | return -ENOMEM; |
790 | 802 | ||
791 | fbi = info->par; | 803 | fbi = info->par; |
792 | fbi->devtype = pdev->id_entry->driver_data; | ||
793 | 804 | ||
794 | if (!fb_mode) | 805 | if (!fb_mode) |
795 | fb_mode = pdata->mode[0].mode.name; | 806 | fb_mode = pdata->mode[0].mode.name; |
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 18688c12e30d..d7d66ef5cb58 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -538,6 +538,7 @@ static const enum dss_feat_id omap3630_dss_feat_list[] = { | |||
538 | FEAT_ALPHA_FIXED_ZORDER, | 538 | FEAT_ALPHA_FIXED_ZORDER, |
539 | FEAT_FIFO_MERGE, | 539 | FEAT_FIFO_MERGE, |
540 | FEAT_OMAP3_DSI_FIFO_BUG, | 540 | FEAT_OMAP3_DSI_FIFO_BUG, |
541 | FEAT_DPI_USES_VDDS_DSI, | ||
541 | }; | 542 | }; |
542 | 543 | ||
543 | static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = { | 544 | static const enum dss_feat_id omap4430_es1_0_dss_feat_list[] = { |
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c index 4d99dd7a6831..395cb6a8d8f3 100644 --- a/drivers/video/ssd1307fb.c +++ b/drivers/video/ssd1307fb.c | |||
@@ -145,8 +145,8 @@ static void ssd1307fb_update_display(struct ssd1307fb_par *par) | |||
145 | u32 page_length = SSD1307FB_WIDTH * i; | 145 | u32 page_length = SSD1307FB_WIDTH * i; |
146 | u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8; | 146 | u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8; |
147 | u8 byte = *(vmem + index); | 147 | u8 byte = *(vmem + index); |
148 | u8 bit = byte & (1 << (7 - (j % 8))); | 148 | u8 bit = byte & (1 << (j % 8)); |
149 | bit = bit >> (7 - (j % 8)); | 149 | bit = bit >> (j % 8); |
150 | buf |= bit << k; | 150 | buf |= bit << k; |
151 | } | 151 | } |
152 | ssd1307fb_write_data(par->client, buf); | 152 | ssd1307fb_write_data(par->client, buf); |
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c index 4dcfced107f5..084041d42c9a 100644 --- a/drivers/xen/cpu_hotplug.c +++ b/drivers/xen/cpu_hotplug.c | |||
@@ -25,10 +25,10 @@ static void disable_hotplug_cpu(int cpu) | |||
25 | static int vcpu_online(unsigned int cpu) | 25 | static int vcpu_online(unsigned int cpu) |
26 | { | 26 | { |
27 | int err; | 27 | int err; |
28 | char dir[32], state[32]; | 28 | char dir[16], state[16]; |
29 | 29 | ||
30 | sprintf(dir, "cpu/%u", cpu); | 30 | sprintf(dir, "cpu/%u", cpu); |
31 | err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state); | 31 | err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state); |
32 | if (err != 1) { | 32 | if (err != 1) { |
33 | if (!xen_initial_domain()) | 33 | if (!xen_initial_domain()) |
34 | printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); | 34 | printk(KERN_ERR "XENBUS: Unable to read cpu state\n"); |
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 0be4df39e953..22f77c5f6012 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
@@ -840,7 +840,7 @@ int bind_evtchn_to_irq(unsigned int evtchn) | |||
840 | 840 | ||
841 | if (irq == -1) { | 841 | if (irq == -1) { |
842 | irq = xen_allocate_irq_dynamic(); | 842 | irq = xen_allocate_irq_dynamic(); |
843 | if (irq == -1) | 843 | if (irq < 0) |
844 | goto out; | 844 | goto out; |
845 | 845 | ||
846 | irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, | 846 | irq_set_chip_and_handler_name(irq, &xen_dynamic_chip, |
@@ -944,7 +944,7 @@ int bind_virq_to_irq(unsigned int virq, unsigned int cpu) | |||
944 | 944 | ||
945 | if (irq == -1) { | 945 | if (irq == -1) { |
946 | irq = xen_allocate_irq_dynamic(); | 946 | irq = xen_allocate_irq_dynamic(); |
947 | if (irq == -1) | 947 | if (irq < 0) |
948 | goto out; | 948 | goto out; |
949 | 949 | ||
950 | irq_set_chip_and_handler_name(irq, &xen_percpu_chip, | 950 | irq_set_chip_and_handler_name(irq, &xen_percpu_chip, |
@@ -1787,7 +1787,7 @@ void xen_callback_vector(void) | |||
1787 | int rc; | 1787 | int rc; |
1788 | uint64_t callback_via; | 1788 | uint64_t callback_via; |
1789 | if (xen_have_vector_callback) { | 1789 | if (xen_have_vector_callback) { |
1790 | callback_via = HVM_CALLBACK_VECTOR(XEN_HVM_EVTCHN_CALLBACK); | 1790 | callback_via = HVM_CALLBACK_VECTOR(HYPERVISOR_CALLBACK_VECTOR); |
1791 | rc = xen_set_callback_via(callback_via); | 1791 | rc = xen_set_callback_via(callback_via); |
1792 | if (rc) { | 1792 | if (rc) { |
1793 | printk(KERN_ERR "Request for Xen HVM callback vector" | 1793 | printk(KERN_ERR "Request for Xen HVM callback vector" |
@@ -1798,8 +1798,9 @@ void xen_callback_vector(void) | |||
1798 | printk(KERN_INFO "Xen HVM callback vector for event delivery is " | 1798 | printk(KERN_INFO "Xen HVM callback vector for event delivery is " |
1799 | "enabled\n"); | 1799 | "enabled\n"); |
1800 | /* in the restore case the vector has already been allocated */ | 1800 | /* in the restore case the vector has already been allocated */ |
1801 | if (!test_bit(XEN_HVM_EVTCHN_CALLBACK, used_vectors)) | 1801 | if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) |
1802 | alloc_intr_gate(XEN_HVM_EVTCHN_CALLBACK, xen_hvm_callback_vector); | 1802 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, |
1803 | xen_hvm_callback_vector); | ||
1803 | } | 1804 | } |
1804 | } | 1805 | } |
1805 | #else | 1806 | #else |
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c index 2e22df2f7a3f..3c8803feba26 100644 --- a/drivers/xen/gntdev.c +++ b/drivers/xen/gntdev.c | |||
@@ -56,10 +56,15 @@ MODULE_PARM_DESC(limit, "Maximum number of grants that may be mapped by " | |||
56 | static atomic_t pages_mapped = ATOMIC_INIT(0); | 56 | static atomic_t pages_mapped = ATOMIC_INIT(0); |
57 | 57 | ||
58 | static int use_ptemod; | 58 | static int use_ptemod; |
59 | #define populate_freeable_maps use_ptemod | ||
59 | 60 | ||
60 | struct gntdev_priv { | 61 | struct gntdev_priv { |
62 | /* maps with visible offsets in the file descriptor */ | ||
61 | struct list_head maps; | 63 | struct list_head maps; |
62 | /* lock protects maps from concurrent changes */ | 64 | /* maps that are not visible; will be freed on munmap. |
65 | * Only populated if populate_freeable_maps == 1 */ | ||
66 | struct list_head freeable_maps; | ||
67 | /* lock protects maps and freeable_maps */ | ||
63 | spinlock_t lock; | 68 | spinlock_t lock; |
64 | struct mm_struct *mm; | 69 | struct mm_struct *mm; |
65 | struct mmu_notifier mn; | 70 | struct mmu_notifier mn; |
@@ -193,7 +198,7 @@ static struct grant_map *gntdev_find_map_index(struct gntdev_priv *priv, | |||
193 | return NULL; | 198 | return NULL; |
194 | } | 199 | } |
195 | 200 | ||
196 | static void gntdev_put_map(struct grant_map *map) | 201 | static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map) |
197 | { | 202 | { |
198 | if (!map) | 203 | if (!map) |
199 | return; | 204 | return; |
@@ -208,6 +213,12 @@ static void gntdev_put_map(struct grant_map *map) | |||
208 | evtchn_put(map->notify.event); | 213 | evtchn_put(map->notify.event); |
209 | } | 214 | } |
210 | 215 | ||
216 | if (populate_freeable_maps && priv) { | ||
217 | spin_lock(&priv->lock); | ||
218 | list_del(&map->next); | ||
219 | spin_unlock(&priv->lock); | ||
220 | } | ||
221 | |||
211 | if (map->pages && !use_ptemod) | 222 | if (map->pages && !use_ptemod) |
212 | unmap_grant_pages(map, 0, map->count); | 223 | unmap_grant_pages(map, 0, map->count); |
213 | gntdev_free_map(map); | 224 | gntdev_free_map(map); |
@@ -301,17 +312,10 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages) | |||
301 | 312 | ||
302 | if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { | 313 | if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) { |
303 | int pgno = (map->notify.addr >> PAGE_SHIFT); | 314 | int pgno = (map->notify.addr >> PAGE_SHIFT); |
304 | if (pgno >= offset && pgno < offset + pages && use_ptemod) { | 315 | if (pgno >= offset && pgno < offset + pages) { |
305 | void __user *tmp = (void __user *) | 316 | /* No need for kmap, pages are in lowmem */ |
306 | map->vma->vm_start + map->notify.addr; | 317 | uint8_t *tmp = pfn_to_kaddr(page_to_pfn(map->pages[pgno])); |
307 | err = copy_to_user(tmp, &err, 1); | ||
308 | if (err) | ||
309 | return -EFAULT; | ||
310 | map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; | ||
311 | } else if (pgno >= offset && pgno < offset + pages) { | ||
312 | uint8_t *tmp = kmap(map->pages[pgno]); | ||
313 | tmp[map->notify.addr & (PAGE_SIZE-1)] = 0; | 318 | tmp[map->notify.addr & (PAGE_SIZE-1)] = 0; |
314 | kunmap(map->pages[pgno]); | ||
315 | map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; | 319 | map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE; |
316 | } | 320 | } |
317 | } | 321 | } |
@@ -376,11 +380,24 @@ static void gntdev_vma_open(struct vm_area_struct *vma) | |||
376 | static void gntdev_vma_close(struct vm_area_struct *vma) | 380 | static void gntdev_vma_close(struct vm_area_struct *vma) |
377 | { | 381 | { |
378 | struct grant_map *map = vma->vm_private_data; | 382 | struct grant_map *map = vma->vm_private_data; |
383 | struct file *file = vma->vm_file; | ||
384 | struct gntdev_priv *priv = file->private_data; | ||
379 | 385 | ||
380 | pr_debug("gntdev_vma_close %p\n", vma); | 386 | pr_debug("gntdev_vma_close %p\n", vma); |
381 | map->vma = NULL; | 387 | if (use_ptemod) { |
388 | /* It is possible that an mmu notifier could be running | ||
389 | * concurrently, so take priv->lock to ensure that the vma won't | ||
390 | * vanishing during the unmap_grant_pages call, since we will | ||
391 | * spin here until that completes. Such a concurrent call will | ||
392 | * not do any unmapping, since that has been done prior to | ||
393 | * closing the vma, but it may still iterate the unmap_ops list. | ||
394 | */ | ||
395 | spin_lock(&priv->lock); | ||
396 | map->vma = NULL; | ||
397 | spin_unlock(&priv->lock); | ||
398 | } | ||
382 | vma->vm_private_data = NULL; | 399 | vma->vm_private_data = NULL; |
383 | gntdev_put_map(map); | 400 | gntdev_put_map(priv, map); |
384 | } | 401 | } |
385 | 402 | ||
386 | static struct vm_operations_struct gntdev_vmops = { | 403 | static struct vm_operations_struct gntdev_vmops = { |
@@ -390,33 +407,43 @@ static struct vm_operations_struct gntdev_vmops = { | |||
390 | 407 | ||
391 | /* ------------------------------------------------------------------ */ | 408 | /* ------------------------------------------------------------------ */ |
392 | 409 | ||
410 | static void unmap_if_in_range(struct grant_map *map, | ||
411 | unsigned long start, unsigned long end) | ||
412 | { | ||
413 | unsigned long mstart, mend; | ||
414 | int err; | ||
415 | |||
416 | if (!map->vma) | ||
417 | return; | ||
418 | if (map->vma->vm_start >= end) | ||
419 | return; | ||
420 | if (map->vma->vm_end <= start) | ||
421 | return; | ||
422 | mstart = max(start, map->vma->vm_start); | ||
423 | mend = min(end, map->vma->vm_end); | ||
424 | pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", | ||
425 | map->index, map->count, | ||
426 | map->vma->vm_start, map->vma->vm_end, | ||
427 | start, end, mstart, mend); | ||
428 | err = unmap_grant_pages(map, | ||
429 | (mstart - map->vma->vm_start) >> PAGE_SHIFT, | ||
430 | (mend - mstart) >> PAGE_SHIFT); | ||
431 | WARN_ON(err); | ||
432 | } | ||
433 | |||
393 | static void mn_invl_range_start(struct mmu_notifier *mn, | 434 | static void mn_invl_range_start(struct mmu_notifier *mn, |
394 | struct mm_struct *mm, | 435 | struct mm_struct *mm, |
395 | unsigned long start, unsigned long end) | 436 | unsigned long start, unsigned long end) |
396 | { | 437 | { |
397 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); | 438 | struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn); |
398 | struct grant_map *map; | 439 | struct grant_map *map; |
399 | unsigned long mstart, mend; | ||
400 | int err; | ||
401 | 440 | ||
402 | spin_lock(&priv->lock); | 441 | spin_lock(&priv->lock); |
403 | list_for_each_entry(map, &priv->maps, next) { | 442 | list_for_each_entry(map, &priv->maps, next) { |
404 | if (!map->vma) | 443 | unmap_if_in_range(map, start, end); |
405 | continue; | 444 | } |
406 | if (map->vma->vm_start >= end) | 445 | list_for_each_entry(map, &priv->freeable_maps, next) { |
407 | continue; | 446 | unmap_if_in_range(map, start, end); |
408 | if (map->vma->vm_end <= start) | ||
409 | continue; | ||
410 | mstart = max(start, map->vma->vm_start); | ||
411 | mend = min(end, map->vma->vm_end); | ||
412 | pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n", | ||
413 | map->index, map->count, | ||
414 | map->vma->vm_start, map->vma->vm_end, | ||
415 | start, end, mstart, mend); | ||
416 | err = unmap_grant_pages(map, | ||
417 | (mstart - map->vma->vm_start) >> PAGE_SHIFT, | ||
418 | (mend - mstart) >> PAGE_SHIFT); | ||
419 | WARN_ON(err); | ||
420 | } | 447 | } |
421 | spin_unlock(&priv->lock); | 448 | spin_unlock(&priv->lock); |
422 | } | 449 | } |
@@ -445,6 +472,15 @@ static void mn_release(struct mmu_notifier *mn, | |||
445 | err = unmap_grant_pages(map, /* offset */ 0, map->count); | 472 | err = unmap_grant_pages(map, /* offset */ 0, map->count); |
446 | WARN_ON(err); | 473 | WARN_ON(err); |
447 | } | 474 | } |
475 | list_for_each_entry(map, &priv->freeable_maps, next) { | ||
476 | if (!map->vma) | ||
477 | continue; | ||
478 | pr_debug("map %d+%d (%lx %lx)\n", | ||
479 | map->index, map->count, | ||
480 | map->vma->vm_start, map->vma->vm_end); | ||
481 | err = unmap_grant_pages(map, /* offset */ 0, map->count); | ||
482 | WARN_ON(err); | ||
483 | } | ||
448 | spin_unlock(&priv->lock); | 484 | spin_unlock(&priv->lock); |
449 | } | 485 | } |
450 | 486 | ||
@@ -466,6 +502,7 @@ static int gntdev_open(struct inode *inode, struct file *flip) | |||
466 | return -ENOMEM; | 502 | return -ENOMEM; |
467 | 503 | ||
468 | INIT_LIST_HEAD(&priv->maps); | 504 | INIT_LIST_HEAD(&priv->maps); |
505 | INIT_LIST_HEAD(&priv->freeable_maps); | ||
469 | spin_lock_init(&priv->lock); | 506 | spin_lock_init(&priv->lock); |
470 | 507 | ||
471 | if (use_ptemod) { | 508 | if (use_ptemod) { |
@@ -500,8 +537,9 @@ static int gntdev_release(struct inode *inode, struct file *flip) | |||
500 | while (!list_empty(&priv->maps)) { | 537 | while (!list_empty(&priv->maps)) { |
501 | map = list_entry(priv->maps.next, struct grant_map, next); | 538 | map = list_entry(priv->maps.next, struct grant_map, next); |
502 | list_del(&map->next); | 539 | list_del(&map->next); |
503 | gntdev_put_map(map); | 540 | gntdev_put_map(NULL /* already removed */, map); |
504 | } | 541 | } |
542 | WARN_ON(!list_empty(&priv->freeable_maps)); | ||
505 | 543 | ||
506 | if (use_ptemod) | 544 | if (use_ptemod) |
507 | mmu_notifier_unregister(&priv->mn, priv->mm); | 545 | mmu_notifier_unregister(&priv->mn, priv->mm); |
@@ -529,14 +567,14 @@ static long gntdev_ioctl_map_grant_ref(struct gntdev_priv *priv, | |||
529 | 567 | ||
530 | if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { | 568 | if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) { |
531 | pr_debug("can't map: over limit\n"); | 569 | pr_debug("can't map: over limit\n"); |
532 | gntdev_put_map(map); | 570 | gntdev_put_map(NULL, map); |
533 | return err; | 571 | return err; |
534 | } | 572 | } |
535 | 573 | ||
536 | if (copy_from_user(map->grants, &u->refs, | 574 | if (copy_from_user(map->grants, &u->refs, |
537 | sizeof(map->grants[0]) * op.count) != 0) { | 575 | sizeof(map->grants[0]) * op.count) != 0) { |
538 | gntdev_put_map(map); | 576 | gntdev_put_map(NULL, map); |
539 | return err; | 577 | return -EFAULT; |
540 | } | 578 | } |
541 | 579 | ||
542 | spin_lock(&priv->lock); | 580 | spin_lock(&priv->lock); |
@@ -565,11 +603,13 @@ static long gntdev_ioctl_unmap_grant_ref(struct gntdev_priv *priv, | |||
565 | map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); | 603 | map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count); |
566 | if (map) { | 604 | if (map) { |
567 | list_del(&map->next); | 605 | list_del(&map->next); |
606 | if (populate_freeable_maps) | ||
607 | list_add_tail(&map->next, &priv->freeable_maps); | ||
568 | err = 0; | 608 | err = 0; |
569 | } | 609 | } |
570 | spin_unlock(&priv->lock); | 610 | spin_unlock(&priv->lock); |
571 | if (map) | 611 | if (map) |
572 | gntdev_put_map(map); | 612 | gntdev_put_map(priv, map); |
573 | return err; | 613 | return err; |
574 | } | 614 | } |
575 | 615 | ||
@@ -579,25 +619,31 @@ static long gntdev_ioctl_get_offset_for_vaddr(struct gntdev_priv *priv, | |||
579 | struct ioctl_gntdev_get_offset_for_vaddr op; | 619 | struct ioctl_gntdev_get_offset_for_vaddr op; |
580 | struct vm_area_struct *vma; | 620 | struct vm_area_struct *vma; |
581 | struct grant_map *map; | 621 | struct grant_map *map; |
622 | int rv = -EINVAL; | ||
582 | 623 | ||
583 | if (copy_from_user(&op, u, sizeof(op)) != 0) | 624 | if (copy_from_user(&op, u, sizeof(op)) != 0) |
584 | return -EFAULT; | 625 | return -EFAULT; |
585 | pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr); | 626 | pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr); |
586 | 627 | ||
628 | down_read(¤t->mm->mmap_sem); | ||
587 | vma = find_vma(current->mm, op.vaddr); | 629 | vma = find_vma(current->mm, op.vaddr); |
588 | if (!vma || vma->vm_ops != &gntdev_vmops) | 630 | if (!vma || vma->vm_ops != &gntdev_vmops) |
589 | return -EINVAL; | 631 | goto out_unlock; |
590 | 632 | ||
591 | map = vma->vm_private_data; | 633 | map = vma->vm_private_data; |
592 | if (!map) | 634 | if (!map) |
593 | return -EINVAL; | 635 | goto out_unlock; |
594 | 636 | ||
595 | op.offset = map->index << PAGE_SHIFT; | 637 | op.offset = map->index << PAGE_SHIFT; |
596 | op.count = map->count; | 638 | op.count = map->count; |
639 | rv = 0; | ||
597 | 640 | ||
598 | if (copy_to_user(u, &op, sizeof(op)) != 0) | 641 | out_unlock: |
642 | up_read(¤t->mm->mmap_sem); | ||
643 | |||
644 | if (rv == 0 && copy_to_user(u, &op, sizeof(op)) != 0) | ||
599 | return -EFAULT; | 645 | return -EFAULT; |
600 | return 0; | 646 | return rv; |
601 | } | 647 | } |
602 | 648 | ||
603 | static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) | 649 | static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u) |
@@ -778,7 +824,7 @@ out_unlock_put: | |||
778 | out_put_map: | 824 | out_put_map: |
779 | if (use_ptemod) | 825 | if (use_ptemod) |
780 | map->vma = NULL; | 826 | map->vma = NULL; |
781 | gntdev_put_map(map); | 827 | gntdev_put_map(priv, map); |
782 | return err; | 828 | return err; |
783 | } | 829 | } |
784 | 830 | ||
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c index 7038de53652b..157c0ccda3ef 100644 --- a/drivers/xen/grant-table.c +++ b/drivers/xen/grant-table.c | |||
@@ -56,10 +56,6 @@ | |||
56 | /* External tools reserve first few grant table entries. */ | 56 | /* External tools reserve first few grant table entries. */ |
57 | #define NR_RESERVED_ENTRIES 8 | 57 | #define NR_RESERVED_ENTRIES 8 |
58 | #define GNTTAB_LIST_END 0xffffffff | 58 | #define GNTTAB_LIST_END 0xffffffff |
59 | #define GREFS_PER_GRANT_FRAME \ | ||
60 | (grant_table_version == 1 ? \ | ||
61 | (PAGE_SIZE / sizeof(struct grant_entry_v1)) : \ | ||
62 | (PAGE_SIZE / sizeof(union grant_entry_v2))) | ||
63 | 59 | ||
64 | static grant_ref_t **gnttab_list; | 60 | static grant_ref_t **gnttab_list; |
65 | static unsigned int nr_grant_frames; | 61 | static unsigned int nr_grant_frames; |
@@ -154,6 +150,7 @@ static struct gnttab_ops *gnttab_interface; | |||
154 | static grant_status_t *grstatus; | 150 | static grant_status_t *grstatus; |
155 | 151 | ||
156 | static int grant_table_version; | 152 | static int grant_table_version; |
153 | static int grefs_per_grant_frame; | ||
157 | 154 | ||
158 | static struct gnttab_free_callback *gnttab_free_callback_list; | 155 | static struct gnttab_free_callback *gnttab_free_callback_list; |
159 | 156 | ||
@@ -767,12 +764,14 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
767 | unsigned int new_nr_grant_frames, extra_entries, i; | 764 | unsigned int new_nr_grant_frames, extra_entries, i; |
768 | unsigned int nr_glist_frames, new_nr_glist_frames; | 765 | unsigned int nr_glist_frames, new_nr_glist_frames; |
769 | 766 | ||
767 | BUG_ON(grefs_per_grant_frame == 0); | ||
768 | |||
770 | new_nr_grant_frames = nr_grant_frames + more_frames; | 769 | new_nr_grant_frames = nr_grant_frames + more_frames; |
771 | extra_entries = more_frames * GREFS_PER_GRANT_FRAME; | 770 | extra_entries = more_frames * grefs_per_grant_frame; |
772 | 771 | ||
773 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 772 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
774 | new_nr_glist_frames = | 773 | new_nr_glist_frames = |
775 | (new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 774 | (new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
776 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { | 775 | for (i = nr_glist_frames; i < new_nr_glist_frames; i++) { |
777 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); | 776 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC); |
778 | if (!gnttab_list[i]) | 777 | if (!gnttab_list[i]) |
@@ -780,12 +779,12 @@ static int grow_gnttab_list(unsigned int more_frames) | |||
780 | } | 779 | } |
781 | 780 | ||
782 | 781 | ||
783 | for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 782 | for (i = grefs_per_grant_frame * nr_grant_frames; |
784 | i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++) | 783 | i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++) |
785 | gnttab_entry(i) = i + 1; | 784 | gnttab_entry(i) = i + 1; |
786 | 785 | ||
787 | gnttab_entry(i) = gnttab_free_head; | 786 | gnttab_entry(i) = gnttab_free_head; |
788 | gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames; | 787 | gnttab_free_head = grefs_per_grant_frame * nr_grant_frames; |
789 | gnttab_free_count += extra_entries; | 788 | gnttab_free_count += extra_entries; |
790 | 789 | ||
791 | nr_grant_frames = new_nr_grant_frames; | 790 | nr_grant_frames = new_nr_grant_frames; |
@@ -957,7 +956,8 @@ EXPORT_SYMBOL_GPL(gnttab_unmap_refs); | |||
957 | 956 | ||
958 | static unsigned nr_status_frames(unsigned nr_grant_frames) | 957 | static unsigned nr_status_frames(unsigned nr_grant_frames) |
959 | { | 958 | { |
960 | return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP; | 959 | BUG_ON(grefs_per_grant_frame == 0); |
960 | return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP; | ||
961 | } | 961 | } |
962 | 962 | ||
963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) | 963 | static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes) |
@@ -1115,6 +1115,7 @@ static void gnttab_request_version(void) | |||
1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); | 1115 | rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1); |
1116 | if (rc == 0 && gsv.version == 2) { | 1116 | if (rc == 0 && gsv.version == 2) { |
1117 | grant_table_version = 2; | 1117 | grant_table_version = 2; |
1118 | grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2); | ||
1118 | gnttab_interface = &gnttab_v2_ops; | 1119 | gnttab_interface = &gnttab_v2_ops; |
1119 | } else if (grant_table_version == 2) { | 1120 | } else if (grant_table_version == 2) { |
1120 | /* | 1121 | /* |
@@ -1127,17 +1128,17 @@ static void gnttab_request_version(void) | |||
1127 | panic("we need grant tables version 2, but only version 1 is available"); | 1128 | panic("we need grant tables version 2, but only version 1 is available"); |
1128 | } else { | 1129 | } else { |
1129 | grant_table_version = 1; | 1130 | grant_table_version = 1; |
1131 | grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1); | ||
1130 | gnttab_interface = &gnttab_v1_ops; | 1132 | gnttab_interface = &gnttab_v1_ops; |
1131 | } | 1133 | } |
1132 | printk(KERN_INFO "Grant tables using version %d layout.\n", | 1134 | printk(KERN_INFO "Grant tables using version %d layout.\n", |
1133 | grant_table_version); | 1135 | grant_table_version); |
1134 | } | 1136 | } |
1135 | 1137 | ||
1136 | int gnttab_resume(void) | 1138 | static int gnttab_setup(void) |
1137 | { | 1139 | { |
1138 | unsigned int max_nr_gframes; | 1140 | unsigned int max_nr_gframes; |
1139 | 1141 | ||
1140 | gnttab_request_version(); | ||
1141 | max_nr_gframes = gnttab_max_grant_frames(); | 1142 | max_nr_gframes = gnttab_max_grant_frames(); |
1142 | if (max_nr_gframes < nr_grant_frames) | 1143 | if (max_nr_gframes < nr_grant_frames) |
1143 | return -ENOSYS; | 1144 | return -ENOSYS; |
@@ -1160,6 +1161,12 @@ int gnttab_resume(void) | |||
1160 | return 0; | 1161 | return 0; |
1161 | } | 1162 | } |
1162 | 1163 | ||
1164 | int gnttab_resume(void) | ||
1165 | { | ||
1166 | gnttab_request_version(); | ||
1167 | return gnttab_setup(); | ||
1168 | } | ||
1169 | |||
1163 | int gnttab_suspend(void) | 1170 | int gnttab_suspend(void) |
1164 | { | 1171 | { |
1165 | gnttab_interface->unmap_frames(); | 1172 | gnttab_interface->unmap_frames(); |
@@ -1171,9 +1178,10 @@ static int gnttab_expand(unsigned int req_entries) | |||
1171 | int rc; | 1178 | int rc; |
1172 | unsigned int cur, extra; | 1179 | unsigned int cur, extra; |
1173 | 1180 | ||
1181 | BUG_ON(grefs_per_grant_frame == 0); | ||
1174 | cur = nr_grant_frames; | 1182 | cur = nr_grant_frames; |
1175 | extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) / | 1183 | extra = ((req_entries + (grefs_per_grant_frame-1)) / |
1176 | GREFS_PER_GRANT_FRAME); | 1184 | grefs_per_grant_frame); |
1177 | if (cur + extra > gnttab_max_grant_frames()) | 1185 | if (cur + extra > gnttab_max_grant_frames()) |
1178 | return -ENOSPC; | 1186 | return -ENOSPC; |
1179 | 1187 | ||
@@ -1191,21 +1199,23 @@ int gnttab_init(void) | |||
1191 | unsigned int nr_init_grefs; | 1199 | unsigned int nr_init_grefs; |
1192 | int ret; | 1200 | int ret; |
1193 | 1201 | ||
1202 | gnttab_request_version(); | ||
1194 | nr_grant_frames = 1; | 1203 | nr_grant_frames = 1; |
1195 | boot_max_nr_grant_frames = __max_nr_grant_frames(); | 1204 | boot_max_nr_grant_frames = __max_nr_grant_frames(); |
1196 | 1205 | ||
1197 | /* Determine the maximum number of frames required for the | 1206 | /* Determine the maximum number of frames required for the |
1198 | * grant reference free list on the current hypervisor. | 1207 | * grant reference free list on the current hypervisor. |
1199 | */ | 1208 | */ |
1209 | BUG_ON(grefs_per_grant_frame == 0); | ||
1200 | max_nr_glist_frames = (boot_max_nr_grant_frames * | 1210 | max_nr_glist_frames = (boot_max_nr_grant_frames * |
1201 | GREFS_PER_GRANT_FRAME / RPP); | 1211 | grefs_per_grant_frame / RPP); |
1202 | 1212 | ||
1203 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), | 1213 | gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *), |
1204 | GFP_KERNEL); | 1214 | GFP_KERNEL); |
1205 | if (gnttab_list == NULL) | 1215 | if (gnttab_list == NULL) |
1206 | return -ENOMEM; | 1216 | return -ENOMEM; |
1207 | 1217 | ||
1208 | nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP; | 1218 | nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP; |
1209 | for (i = 0; i < nr_glist_frames; i++) { | 1219 | for (i = 0; i < nr_glist_frames; i++) { |
1210 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); | 1220 | gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL); |
1211 | if (gnttab_list[i] == NULL) { | 1221 | if (gnttab_list[i] == NULL) { |
@@ -1214,12 +1224,12 @@ int gnttab_init(void) | |||
1214 | } | 1224 | } |
1215 | } | 1225 | } |
1216 | 1226 | ||
1217 | if (gnttab_resume() < 0) { | 1227 | if (gnttab_setup() < 0) { |
1218 | ret = -ENODEV; | 1228 | ret = -ENODEV; |
1219 | goto ini_nomem; | 1229 | goto ini_nomem; |
1220 | } | 1230 | } |
1221 | 1231 | ||
1222 | nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME; | 1232 | nr_init_grefs = nr_grant_frames * grefs_per_grant_frame; |
1223 | 1233 | ||
1224 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) | 1234 | for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++) |
1225 | gnttab_entry(i) = i + 1; | 1235 | gnttab_entry(i) = i + 1; |
diff --git a/drivers/xen/pcpu.c b/drivers/xen/pcpu.c index 067fcfa1723e..5a27a4599a4a 100644 --- a/drivers/xen/pcpu.c +++ b/drivers/xen/pcpu.c | |||
@@ -278,8 +278,7 @@ static int sync_pcpu(uint32_t cpu, uint32_t *max_cpu) | |||
278 | * Only those at cpu present map has its sys interface. | 278 | * Only those at cpu present map has its sys interface. |
279 | */ | 279 | */ |
280 | if (info->flags & XEN_PCPU_FLAGS_INVALID) { | 280 | if (info->flags & XEN_PCPU_FLAGS_INVALID) { |
281 | if (pcpu) | 281 | unregister_and_remove_pcpu(pcpu); |
282 | unregister_and_remove_pcpu(pcpu); | ||
283 | return 0; | 282 | return 0; |
284 | } | 283 | } |
285 | 284 | ||
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c index 0bbbccbb1f12..ca2b00e9d558 100644 --- a/drivers/xen/privcmd.c +++ b/drivers/xen/privcmd.c | |||
@@ -199,9 +199,6 @@ static long privcmd_ioctl_mmap(void __user *udata) | |||
199 | LIST_HEAD(pagelist); | 199 | LIST_HEAD(pagelist); |
200 | struct mmap_mfn_state state; | 200 | struct mmap_mfn_state state; |
201 | 201 | ||
202 | if (!xen_initial_domain()) | ||
203 | return -EPERM; | ||
204 | |||
205 | /* We only support privcmd_ioctl_mmap_batch for auto translated. */ | 202 | /* We only support privcmd_ioctl_mmap_batch for auto translated. */ |
206 | if (xen_feature(XENFEAT_auto_translated_physmap)) | 203 | if (xen_feature(XENFEAT_auto_translated_physmap)) |
207 | return -ENOSYS; | 204 | return -ENOSYS; |
@@ -261,11 +258,12 @@ struct mmap_batch_state { | |||
261 | * -ENOENT if at least 1 -ENOENT has happened. | 258 | * -ENOENT if at least 1 -ENOENT has happened. |
262 | */ | 259 | */ |
263 | int global_error; | 260 | int global_error; |
264 | /* An array for individual errors */ | 261 | int version; |
265 | int *err; | ||
266 | 262 | ||
267 | /* User-space mfn array to store errors in the second pass for V1. */ | 263 | /* User-space mfn array to store errors in the second pass for V1. */ |
268 | xen_pfn_t __user *user_mfn; | 264 | xen_pfn_t __user *user_mfn; |
265 | /* User-space int array to store errors in the second pass for V2. */ | ||
266 | int __user *user_err; | ||
269 | }; | 267 | }; |
270 | 268 | ||
271 | /* auto translated dom0 note: if domU being created is PV, then mfn is | 269 | /* auto translated dom0 note: if domU being created is PV, then mfn is |
@@ -288,7 +286,19 @@ static int mmap_batch_fn(void *data, void *state) | |||
288 | &cur_page); | 286 | &cur_page); |
289 | 287 | ||
290 | /* Store error code for second pass. */ | 288 | /* Store error code for second pass. */ |
291 | *(st->err++) = ret; | 289 | if (st->version == 1) { |
290 | if (ret < 0) { | ||
291 | /* | ||
292 | * V1 encodes the error codes in the 32bit top nibble of the | ||
293 | * mfn (with its known limitations vis-a-vis 64 bit callers). | ||
294 | */ | ||
295 | *mfnp |= (ret == -ENOENT) ? | ||
296 | PRIVCMD_MMAPBATCH_PAGED_ERROR : | ||
297 | PRIVCMD_MMAPBATCH_MFN_ERROR; | ||
298 | } | ||
299 | } else { /* st->version == 2 */ | ||
300 | *((int *) mfnp) = ret; | ||
301 | } | ||
292 | 302 | ||
293 | /* And see if it affects the global_error. */ | 303 | /* And see if it affects the global_error. */ |
294 | if (ret < 0) { | 304 | if (ret < 0) { |
@@ -305,20 +315,25 @@ static int mmap_batch_fn(void *data, void *state) | |||
305 | return 0; | 315 | return 0; |
306 | } | 316 | } |
307 | 317 | ||
308 | static int mmap_return_errors_v1(void *data, void *state) | 318 | static int mmap_return_errors(void *data, void *state) |
309 | { | 319 | { |
310 | xen_pfn_t *mfnp = data; | ||
311 | struct mmap_batch_state *st = state; | 320 | struct mmap_batch_state *st = state; |
312 | int err = *(st->err++); | ||
313 | 321 | ||
314 | /* | 322 | if (st->version == 1) { |
315 | * V1 encodes the error codes in the 32bit top nibble of the | 323 | xen_pfn_t mfnp = *((xen_pfn_t *) data); |
316 | * mfn (with its known limitations vis-a-vis 64 bit callers). | 324 | if (mfnp & PRIVCMD_MMAPBATCH_MFN_ERROR) |
317 | */ | 325 | return __put_user(mfnp, st->user_mfn++); |
318 | *mfnp |= (err == -ENOENT) ? | 326 | else |
319 | PRIVCMD_MMAPBATCH_PAGED_ERROR : | 327 | st->user_mfn++; |
320 | PRIVCMD_MMAPBATCH_MFN_ERROR; | 328 | } else { /* st->version == 2 */ |
321 | return __put_user(*mfnp, st->user_mfn++); | 329 | int err = *((int *) data); |
330 | if (err) | ||
331 | return __put_user(err, st->user_err++); | ||
332 | else | ||
333 | st->user_err++; | ||
334 | } | ||
335 | |||
336 | return 0; | ||
322 | } | 337 | } |
323 | 338 | ||
324 | /* Allocate pfns that are then mapped with gmfns from foreign domid. Update | 339 | /* Allocate pfns that are then mapped with gmfns from foreign domid. Update |
@@ -357,12 +372,8 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
357 | struct vm_area_struct *vma; | 372 | struct vm_area_struct *vma; |
358 | unsigned long nr_pages; | 373 | unsigned long nr_pages; |
359 | LIST_HEAD(pagelist); | 374 | LIST_HEAD(pagelist); |
360 | int *err_array = NULL; | ||
361 | struct mmap_batch_state state; | 375 | struct mmap_batch_state state; |
362 | 376 | ||
363 | if (!xen_initial_domain()) | ||
364 | return -EPERM; | ||
365 | |||
366 | switch (version) { | 377 | switch (version) { |
367 | case 1: | 378 | case 1: |
368 | if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) | 379 | if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch))) |
@@ -396,10 +407,12 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
396 | goto out; | 407 | goto out; |
397 | } | 408 | } |
398 | 409 | ||
399 | err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL); | 410 | if (version == 2) { |
400 | if (err_array == NULL) { | 411 | /* Zero error array now to only copy back actual errors. */ |
401 | ret = -ENOMEM; | 412 | if (clear_user(m.err, sizeof(int) * m.num)) { |
402 | goto out; | 413 | ret = -EFAULT; |
414 | goto out; | ||
415 | } | ||
403 | } | 416 | } |
404 | 417 | ||
405 | down_write(&mm->mmap_sem); | 418 | down_write(&mm->mmap_sem); |
@@ -427,7 +440,7 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
427 | state.va = m.addr; | 440 | state.va = m.addr; |
428 | state.index = 0; | 441 | state.index = 0; |
429 | state.global_error = 0; | 442 | state.global_error = 0; |
430 | state.err = err_array; | 443 | state.version = version; |
431 | 444 | ||
432 | /* mmap_batch_fn guarantees ret == 0 */ | 445 | /* mmap_batch_fn guarantees ret == 0 */ |
433 | BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), | 446 | BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t), |
@@ -435,21 +448,14 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
435 | 448 | ||
436 | up_write(&mm->mmap_sem); | 449 | up_write(&mm->mmap_sem); |
437 | 450 | ||
438 | if (version == 1) { | 451 | if (state.global_error) { |
439 | if (state.global_error) { | 452 | /* Write back errors in second pass. */ |
440 | /* Write back errors in second pass. */ | 453 | state.user_mfn = (xen_pfn_t *)m.arr; |
441 | state.user_mfn = (xen_pfn_t *)m.arr; | 454 | state.user_err = m.err; |
442 | state.err = err_array; | 455 | ret = traverse_pages(m.num, sizeof(xen_pfn_t), |
443 | ret = traverse_pages(m.num, sizeof(xen_pfn_t), | 456 | &pagelist, mmap_return_errors, &state); |
444 | &pagelist, mmap_return_errors_v1, &state); | 457 | } else |
445 | } else | 458 | ret = 0; |
446 | ret = 0; | ||
447 | |||
448 | } else if (version == 2) { | ||
449 | ret = __copy_to_user(m.err, err_array, m.num * sizeof(int)); | ||
450 | if (ret) | ||
451 | ret = -EFAULT; | ||
452 | } | ||
453 | 459 | ||
454 | /* If we have not had any EFAULT-like global errors then set the global | 460 | /* If we have not had any EFAULT-like global errors then set the global |
455 | * error to -ENOENT if necessary. */ | 461 | * error to -ENOENT if necessary. */ |
@@ -457,7 +463,6 @@ static long privcmd_ioctl_mmap_batch(void __user *udata, int version) | |||
457 | ret = -ENOENT; | 463 | ret = -ENOENT; |
458 | 464 | ||
459 | out: | 465 | out: |
460 | kfree(err_array); | ||
461 | free_page_list(&pagelist); | 466 | free_page_list(&pagelist); |
462 | 467 | ||
463 | return ret; | 468 | return ret; |
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h index a7def010eba3..f72af87640e0 100644 --- a/drivers/xen/xen-pciback/pciback.h +++ b/drivers/xen/xen-pciback/pciback.h | |||
@@ -124,7 +124,7 @@ static inline int xen_pcibk_add_pci_dev(struct xen_pcibk_device *pdev, | |||
124 | static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, | 124 | static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev, |
125 | struct pci_dev *dev) | 125 | struct pci_dev *dev) |
126 | { | 126 | { |
127 | if (xen_pcibk_backend && xen_pcibk_backend->free) | 127 | if (xen_pcibk_backend && xen_pcibk_backend->release) |
128 | return xen_pcibk_backend->release(pdev, dev); | 128 | return xen_pcibk_backend->release(pdev, dev); |
129 | } | 129 | } |
130 | 130 | ||
diff --git a/drivers/xen/xen-pciback/pciback_ops.c b/drivers/xen/xen-pciback/pciback_ops.c index 97f5d264c31e..37c1f825f513 100644 --- a/drivers/xen/xen-pciback/pciback_ops.c +++ b/drivers/xen/xen-pciback/pciback_ops.c | |||
@@ -135,7 +135,6 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev, | |||
135 | struct pci_dev *dev, struct xen_pci_op *op) | 135 | struct pci_dev *dev, struct xen_pci_op *op) |
136 | { | 136 | { |
137 | struct xen_pcibk_dev_data *dev_data; | 137 | struct xen_pcibk_dev_data *dev_data; |
138 | int otherend = pdev->xdev->otherend_id; | ||
139 | int status; | 138 | int status; |
140 | 139 | ||
141 | if (unlikely(verbose_request)) | 140 | if (unlikely(verbose_request)) |
@@ -144,8 +143,9 @@ int xen_pcibk_enable_msi(struct xen_pcibk_device *pdev, | |||
144 | status = pci_enable_msi(dev); | 143 | status = pci_enable_msi(dev); |
145 | 144 | ||
146 | if (status) { | 145 | if (status) { |
147 | printk(KERN_ERR "error enable msi for guest %x status %x\n", | 146 | pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI for guest %u: err %d\n", |
148 | otherend, status); | 147 | pci_name(dev), pdev->xdev->otherend_id, |
148 | status); | ||
149 | op->value = 0; | 149 | op->value = 0; |
150 | return XEN_PCI_ERR_op_failed; | 150 | return XEN_PCI_ERR_op_failed; |
151 | } | 151 | } |
@@ -223,10 +223,10 @@ int xen_pcibk_enable_msix(struct xen_pcibk_device *pdev, | |||
223 | pci_name(dev), i, | 223 | pci_name(dev), i, |
224 | op->msix_entries[i].vector); | 224 | op->msix_entries[i].vector); |
225 | } | 225 | } |
226 | } else { | 226 | } else |
227 | printk(KERN_WARNING DRV_NAME ": %s: failed to enable MSI-X: err %d!\n", | 227 | pr_warn_ratelimited(DRV_NAME ": %s: error enabling MSI-X for guest %u: err %d!\n", |
228 | pci_name(dev), result); | 228 | pci_name(dev), pdev->xdev->otherend_id, |
229 | } | 229 | result); |
230 | kfree(entries); | 230 | kfree(entries); |
231 | 231 | ||
232 | op->value = result; | 232 | op->value = result; |