diff options
| author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-12 02:53:38 -0400 |
|---|---|---|
| committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2009-06-12 02:53:38 -0400 |
| commit | bc47ab0241c7c86da4f5e5f82fbca7d45387c18d (patch) | |
| tree | b9c33ae8b6de43e44cc5fcbaa3e4a15f18a5ed42 /drivers | |
| parent | 37f9ef553bed630957e025504cdcbc76f5de49d5 (diff) | |
| parent | 8ebf975608aaebd7feb33d77f07ba21a6380e086 (diff) | |
Merge commit 'origin/master' into next
Manual merge of:
arch/powerpc/kernel/asm-offsets.c
Diffstat (limited to 'drivers')
309 files changed, 14385 insertions, 5819 deletions
diff --git a/drivers/acpi/pci_bind.c b/drivers/acpi/pci_bind.c index 95650f83ce2e..bc46de3d967f 100644 --- a/drivers/acpi/pci_bind.c +++ b/drivers/acpi/pci_bind.c | |||
| @@ -116,9 +116,6 @@ int acpi_pci_bind(struct acpi_device *device) | |||
| 116 | struct acpi_pci_data *pdata; | 116 | struct acpi_pci_data *pdata; |
| 117 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; | 117 | struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; |
| 118 | acpi_handle handle; | 118 | acpi_handle handle; |
| 119 | struct pci_dev *dev; | ||
| 120 | struct pci_bus *bus; | ||
| 121 | |||
| 122 | 119 | ||
| 123 | if (!device || !device->parent) | 120 | if (!device || !device->parent) |
| 124 | return -EINVAL; | 121 | return -EINVAL; |
| @@ -176,20 +173,9 @@ int acpi_pci_bind(struct acpi_device *device) | |||
| 176 | * Locate matching device in PCI namespace. If it doesn't exist | 173 | * Locate matching device in PCI namespace. If it doesn't exist |
| 177 | * this typically means that the device isn't currently inserted | 174 | * this typically means that the device isn't currently inserted |
| 178 | * (e.g. docking station, port replicator, etc.). | 175 | * (e.g. docking station, port replicator, etc.). |
| 179 | * We cannot simply search the global pci device list, since | ||
| 180 | * PCI devices are added to the global pci list when the root | ||
| 181 | * bridge start ops are run, which may not have happened yet. | ||
| 182 | */ | 176 | */ |
| 183 | bus = pci_find_bus(data->id.segment, data->id.bus); | 177 | data->dev = pci_get_slot(pdata->bus, |
| 184 | if (bus) { | 178 | PCI_DEVFN(data->id.device, data->id.function)); |
| 185 | list_for_each_entry(dev, &bus->devices, bus_list) { | ||
| 186 | if (dev->devfn == PCI_DEVFN(data->id.device, | ||
| 187 | data->id.function)) { | ||
| 188 | data->dev = dev; | ||
| 189 | break; | ||
| 190 | } | ||
| 191 | } | ||
| 192 | } | ||
| 193 | if (!data->dev) { | 179 | if (!data->dev) { |
| 194 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 180 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
| 195 | "Device %04x:%02x:%02x.%d not present in PCI namespace\n", | 181 | "Device %04x:%02x:%02x.%d not present in PCI namespace\n", |
| @@ -259,9 +245,10 @@ int acpi_pci_bind(struct acpi_device *device) | |||
| 259 | 245 | ||
| 260 | end: | 246 | end: |
| 261 | kfree(buffer.pointer); | 247 | kfree(buffer.pointer); |
| 262 | if (result) | 248 | if (result) { |
| 249 | pci_dev_put(data->dev); | ||
| 263 | kfree(data); | 250 | kfree(data); |
| 264 | 251 | } | |
| 265 | return result; | 252 | return result; |
| 266 | } | 253 | } |
| 267 | 254 | ||
| @@ -303,6 +290,7 @@ static int acpi_pci_unbind(struct acpi_device *device) | |||
| 303 | if (data->dev->subordinate) { | 290 | if (data->dev->subordinate) { |
| 304 | acpi_pci_irq_del_prt(data->id.segment, data->bus->number); | 291 | acpi_pci_irq_del_prt(data->id.segment, data->bus->number); |
| 305 | } | 292 | } |
| 293 | pci_dev_put(data->dev); | ||
| 306 | kfree(data); | 294 | kfree(data); |
| 307 | 295 | ||
| 308 | end: | 296 | end: |
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c index 51b9f8280f88..2faa9e2ac893 100644 --- a/drivers/acpi/pci_irq.c +++ b/drivers/acpi/pci_irq.c | |||
| @@ -401,7 +401,8 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
| 401 | /* Interrupt Line values above 0xF are forbidden */ | 401 | /* Interrupt Line values above 0xF are forbidden */ |
| 402 | if (dev->irq > 0 && (dev->irq <= 0xF)) { | 402 | if (dev->irq > 0 && (dev->irq <= 0xF)) { |
| 403 | printk(" - using IRQ %d\n", dev->irq); | 403 | printk(" - using IRQ %d\n", dev->irq); |
| 404 | acpi_register_gsi(dev->irq, ACPI_LEVEL_SENSITIVE, | 404 | acpi_register_gsi(&dev->dev, dev->irq, |
| 405 | ACPI_LEVEL_SENSITIVE, | ||
| 405 | ACPI_ACTIVE_LOW); | 406 | ACPI_ACTIVE_LOW); |
| 406 | return 0; | 407 | return 0; |
| 407 | } else { | 408 | } else { |
| @@ -410,7 +411,7 @@ int acpi_pci_irq_enable(struct pci_dev *dev) | |||
| 410 | } | 411 | } |
| 411 | } | 412 | } |
| 412 | 413 | ||
| 413 | rc = acpi_register_gsi(gsi, triggering, polarity); | 414 | rc = acpi_register_gsi(&dev->dev, gsi, triggering, polarity); |
| 414 | if (rc < 0) { | 415 | if (rc < 0) { |
| 415 | dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", | 416 | dev_warn(&dev->dev, "PCI INT %c: failed to register GSI\n", |
| 416 | pin_name(pin)); | 417 | pin_name(pin)); |
diff --git a/drivers/acpi/processor_core.c b/drivers/acpi/processor_core.c index 45ad3288c5ff..23f0fb84f1c1 100644 --- a/drivers/acpi/processor_core.c +++ b/drivers/acpi/processor_core.c | |||
| @@ -844,7 +844,7 @@ static int acpi_processor_add(struct acpi_device *device) | |||
| 844 | if (!pr) | 844 | if (!pr) |
| 845 | return -ENOMEM; | 845 | return -ENOMEM; |
| 846 | 846 | ||
| 847 | if (!alloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { | 847 | if (!zalloc_cpumask_var(&pr->throttling.shared_cpu_map, GFP_KERNEL)) { |
| 848 | kfree(pr); | 848 | kfree(pr); |
| 849 | return -ENOMEM; | 849 | return -ENOMEM; |
| 850 | } | 850 | } |
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 72069ba5f1ed..10a2d913635a 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c | |||
| @@ -148,6 +148,9 @@ static void acpi_timer_check_state(int state, struct acpi_processor *pr, | |||
| 148 | if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) | 148 | if (cpu_has(&cpu_data(pr->id), X86_FEATURE_ARAT)) |
| 149 | return; | 149 | return; |
| 150 | 150 | ||
| 151 | if (boot_cpu_has(X86_FEATURE_AMDC1E)) | ||
| 152 | type = ACPI_STATE_C1; | ||
| 153 | |||
| 151 | /* | 154 | /* |
| 152 | * Check, if one of the previous states already marked the lapic | 155 | * Check, if one of the previous states already marked the lapic |
| 153 | * unstable | 156 | * unstable |
| @@ -611,6 +614,7 @@ static int acpi_processor_power_verify(struct acpi_processor *pr) | |||
| 611 | switch (cx->type) { | 614 | switch (cx->type) { |
| 612 | case ACPI_STATE_C1: | 615 | case ACPI_STATE_C1: |
| 613 | cx->valid = 1; | 616 | cx->valid = 1; |
| 617 | acpi_timer_check_state(i, pr, cx); | ||
| 614 | break; | 618 | break; |
| 615 | 619 | ||
| 616 | case ACPI_STATE_C2: | 620 | case ACPI_STATE_C2: |
| @@ -830,11 +834,12 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
| 830 | 834 | ||
| 831 | /* Do not access any ACPI IO ports in suspend path */ | 835 | /* Do not access any ACPI IO ports in suspend path */ |
| 832 | if (acpi_idle_suspend) { | 836 | if (acpi_idle_suspend) { |
| 833 | acpi_safe_halt(); | ||
| 834 | local_irq_enable(); | 837 | local_irq_enable(); |
| 838 | cpu_relax(); | ||
| 835 | return 0; | 839 | return 0; |
| 836 | } | 840 | } |
| 837 | 841 | ||
| 842 | acpi_state_timer_broadcast(pr, cx, 1); | ||
| 838 | kt1 = ktime_get_real(); | 843 | kt1 = ktime_get_real(); |
| 839 | acpi_idle_do_entry(cx); | 844 | acpi_idle_do_entry(cx); |
| 840 | kt2 = ktime_get_real(); | 845 | kt2 = ktime_get_real(); |
| @@ -842,6 +847,7 @@ static int acpi_idle_enter_c1(struct cpuidle_device *dev, | |||
| 842 | 847 | ||
| 843 | local_irq_enable(); | 848 | local_irq_enable(); |
| 844 | cx->usage++; | 849 | cx->usage++; |
| 850 | acpi_state_timer_broadcast(pr, cx, 0); | ||
| 845 | 851 | ||
| 846 | return idle_time; | 852 | return idle_time; |
| 847 | } | 853 | } |
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index cafb41000f6b..60e543d3234e 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c | |||
| @@ -309,9 +309,15 @@ static int acpi_processor_get_performance_states(struct acpi_processor *pr) | |||
| 309 | (u32) px->bus_master_latency, | 309 | (u32) px->bus_master_latency, |
| 310 | (u32) px->control, (u32) px->status)); | 310 | (u32) px->control, (u32) px->status)); |
| 311 | 311 | ||
| 312 | if (!px->core_frequency) { | 312 | /* |
| 313 | printk(KERN_ERR PREFIX | 313 | * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq |
| 314 | "Invalid _PSS data: freq is zero\n"); | 314 | */ |
| 315 | if (!px->core_frequency || | ||
| 316 | ((u32)(px->core_frequency * 1000) != | ||
| 317 | (px->core_frequency * 1000))) { | ||
| 318 | printk(KERN_ERR FW_BUG PREFIX | ||
| 319 | "Invalid BIOS _PSS frequency: 0x%llx MHz\n", | ||
| 320 | px->core_frequency); | ||
| 315 | result = -EFAULT; | 321 | result = -EFAULT; |
| 316 | kfree(pr->performance->states); | 322 | kfree(pr->performance->states); |
| 317 | goto end; | 323 | goto end; |
diff --git a/drivers/acpi/processor_throttling.c b/drivers/acpi/processor_throttling.c index 7f16f5f8e7d3..227543789ba9 100644 --- a/drivers/acpi/processor_throttling.c +++ b/drivers/acpi/processor_throttling.c | |||
| @@ -840,7 +840,7 @@ static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) | |||
| 840 | state = acpi_get_throttling_state(pr, value); | 840 | state = acpi_get_throttling_state(pr, value); |
| 841 | if (state == -1) { | 841 | if (state == -1) { |
| 842 | ACPI_WARNING((AE_INFO, | 842 | ACPI_WARNING((AE_INFO, |
| 843 | "Invalid throttling state, reset\n")); | 843 | "Invalid throttling state, reset")); |
| 844 | state = 0; | 844 | state = 0; |
| 845 | ret = acpi_processor_set_throttling(pr, state); | 845 | ret = acpi_processor_set_throttling(pr, state); |
| 846 | if (ret) | 846 | if (ret) |
diff --git a/drivers/acpi/video.c b/drivers/acpi/video.c index 810cca90ca7f..1bdfb37377e3 100644 --- a/drivers/acpi/video.c +++ b/drivers/acpi/video.c | |||
| @@ -570,6 +570,22 @@ static struct dmi_system_id video_dmi_table[] __initdata = { | |||
| 570 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710Z"), | 570 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5710Z"), |
| 571 | }, | 571 | }, |
| 572 | }, | 572 | }, |
| 573 | { | ||
| 574 | .callback = video_set_bqc_offset, | ||
| 575 | .ident = "eMachines E510", | ||
| 576 | .matches = { | ||
| 577 | DMI_MATCH(DMI_BOARD_VENDOR, "EMACHINES"), | ||
| 578 | DMI_MATCH(DMI_PRODUCT_NAME, "eMachines E510"), | ||
| 579 | }, | ||
| 580 | }, | ||
| 581 | { | ||
| 582 | .callback = video_set_bqc_offset, | ||
| 583 | .ident = "Acer Aspire 5315", | ||
| 584 | .matches = { | ||
| 585 | DMI_MATCH(DMI_BOARD_VENDOR, "Acer"), | ||
| 586 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire 5315"), | ||
| 587 | }, | ||
| 588 | }, | ||
| 573 | {} | 589 | {} |
| 574 | }; | 590 | }; |
| 575 | 591 | ||
| @@ -2334,7 +2350,7 @@ static int __init acpi_video_init(void) | |||
| 2334 | return acpi_video_register(); | 2350 | return acpi_video_register(); |
| 2335 | } | 2351 | } |
| 2336 | 2352 | ||
| 2337 | void __exit acpi_video_exit(void) | 2353 | void acpi_video_exit(void) |
| 2338 | { | 2354 | { |
| 2339 | 2355 | ||
| 2340 | acpi_bus_unregister_driver(&acpi_video_bus); | 2356 | acpi_bus_unregister_driver(&acpi_video_bus); |
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c index 08186ecbaf8d..15a23031833f 100644 --- a/drivers/ata/ahci.c +++ b/drivers/ata/ahci.c | |||
| @@ -77,8 +77,6 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, | |||
| 77 | size_t size); | 77 | size_t size); |
| 78 | static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, | 78 | static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, |
| 79 | ssize_t size); | 79 | ssize_t size); |
| 80 | #define MAX_SLOTS 8 | ||
| 81 | #define MAX_RETRY 15 | ||
| 82 | 80 | ||
| 83 | enum { | 81 | enum { |
| 84 | AHCI_PCI_BAR = 5, | 82 | AHCI_PCI_BAR = 5, |
| @@ -220,6 +218,7 @@ enum { | |||
| 220 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ | 218 | AHCI_HFLAG_NO_HOTPLUG = (1 << 7), /* ignore PxSERR.DIAG.N */ |
| 221 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ | 219 | AHCI_HFLAG_SECT255 = (1 << 8), /* max 255 sectors */ |
| 222 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ | 220 | AHCI_HFLAG_YES_NCQ = (1 << 9), /* force NCQ cap on */ |
| 221 | AHCI_HFLAG_NO_SUSPEND = (1 << 10), /* don't suspend */ | ||
| 223 | 222 | ||
| 224 | /* ap->flags bits */ | 223 | /* ap->flags bits */ |
| 225 | 224 | ||
| @@ -230,6 +229,10 @@ enum { | |||
| 230 | 229 | ||
| 231 | ICH_MAP = 0x90, /* ICH MAP register */ | 230 | ICH_MAP = 0x90, /* ICH MAP register */ |
| 232 | 231 | ||
| 232 | /* em constants */ | ||
| 233 | EM_MAX_SLOTS = 8, | ||
| 234 | EM_MAX_RETRY = 5, | ||
| 235 | |||
| 233 | /* em_ctl bits */ | 236 | /* em_ctl bits */ |
| 234 | EM_CTL_RST = (1 << 9), /* Reset */ | 237 | EM_CTL_RST = (1 << 9), /* Reset */ |
| 235 | EM_CTL_TM = (1 << 8), /* Transmit Message */ | 238 | EM_CTL_TM = (1 << 8), /* Transmit Message */ |
| @@ -281,8 +284,8 @@ struct ahci_port_priv { | |||
| 281 | unsigned int ncq_saw_dmas:1; | 284 | unsigned int ncq_saw_dmas:1; |
| 282 | unsigned int ncq_saw_sdb:1; | 285 | unsigned int ncq_saw_sdb:1; |
| 283 | u32 intr_mask; /* interrupts to enable */ | 286 | u32 intr_mask; /* interrupts to enable */ |
| 284 | struct ahci_em_priv em_priv[MAX_SLOTS];/* enclosure management info | 287 | /* enclosure management info per PM slot */ |
| 285 | * per PM slot */ | 288 | struct ahci_em_priv em_priv[EM_MAX_SLOTS]; |
| 286 | }; | 289 | }; |
| 287 | 290 | ||
| 288 | static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); | 291 | static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); |
| @@ -312,7 +315,6 @@ static void ahci_error_handler(struct ata_port *ap); | |||
| 312 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); | 315 | static void ahci_post_internal_cmd(struct ata_queued_cmd *qc); |
| 313 | static int ahci_port_resume(struct ata_port *ap); | 316 | static int ahci_port_resume(struct ata_port *ap); |
| 314 | static void ahci_dev_config(struct ata_device *dev); | 317 | static void ahci_dev_config(struct ata_device *dev); |
| 315 | static unsigned int ahci_fill_sg(struct ata_queued_cmd *qc, void *cmd_tbl); | ||
| 316 | static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, | 318 | static void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag, |
| 317 | u32 opts); | 319 | u32 opts); |
| 318 | #ifdef CONFIG_PM | 320 | #ifdef CONFIG_PM |
| @@ -403,14 +405,14 @@ static struct ata_port_operations ahci_sb600_ops = { | |||
| 403 | #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) | 405 | #define AHCI_HFLAGS(flags) .private_data = (void *)(flags) |
| 404 | 406 | ||
| 405 | static const struct ata_port_info ahci_port_info[] = { | 407 | static const struct ata_port_info ahci_port_info[] = { |
| 406 | /* board_ahci */ | 408 | [board_ahci] = |
| 407 | { | 409 | { |
| 408 | .flags = AHCI_FLAG_COMMON, | 410 | .flags = AHCI_FLAG_COMMON, |
| 409 | .pio_mask = ATA_PIO4, | 411 | .pio_mask = ATA_PIO4, |
| 410 | .udma_mask = ATA_UDMA6, | 412 | .udma_mask = ATA_UDMA6, |
| 411 | .port_ops = &ahci_ops, | 413 | .port_ops = &ahci_ops, |
| 412 | }, | 414 | }, |
| 413 | /* board_ahci_vt8251 */ | 415 | [board_ahci_vt8251] = |
| 414 | { | 416 | { |
| 415 | AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), | 417 | AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_PMP), |
| 416 | .flags = AHCI_FLAG_COMMON, | 418 | .flags = AHCI_FLAG_COMMON, |
| @@ -418,7 +420,7 @@ static const struct ata_port_info ahci_port_info[] = { | |||
| 418 | .udma_mask = ATA_UDMA6, | 420 | .udma_mask = ATA_UDMA6, |
| 419 | .port_ops = &ahci_vt8251_ops, | 421 | .port_ops = &ahci_vt8251_ops, |
| 420 | }, | 422 | }, |
| 421 | /* board_ahci_ign_iferr */ | 423 | [board_ahci_ign_iferr] = |
| 422 | { | 424 | { |
| 423 | AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), | 425 | AHCI_HFLAGS (AHCI_HFLAG_IGN_IRQ_IF_ERR), |
| 424 | .flags = AHCI_FLAG_COMMON, | 426 | .flags = AHCI_FLAG_COMMON, |
| @@ -426,17 +428,16 @@ static const struct ata_port_info ahci_port_info[] = { | |||
| 426 | .udma_mask = ATA_UDMA6, | 428 | .udma_mask = ATA_UDMA6, |
| 427 | .port_ops = &ahci_ops, | 429 | .port_ops = &ahci_ops, |
| 428 | }, | 430 | }, |
| 429 | /* board_ahci_sb600 */ | 431 | [board_ahci_sb600] = |
| 430 | { | 432 | { |
| 431 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | | 433 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL | |
| 432 | AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI | | 434 | AHCI_HFLAG_NO_MSI | AHCI_HFLAG_SECT255), |
| 433 | AHCI_HFLAG_SECT255), | ||
| 434 | .flags = AHCI_FLAG_COMMON, | 435 | .flags = AHCI_FLAG_COMMON, |
| 435 | .pio_mask = ATA_PIO4, | 436 | .pio_mask = ATA_PIO4, |
| 436 | .udma_mask = ATA_UDMA6, | 437 | .udma_mask = ATA_UDMA6, |
| 437 | .port_ops = &ahci_sb600_ops, | 438 | .port_ops = &ahci_sb600_ops, |
| 438 | }, | 439 | }, |
| 439 | /* board_ahci_mv */ | 440 | [board_ahci_mv] = |
| 440 | { | 441 | { |
| 441 | AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | | 442 | AHCI_HFLAGS (AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI | |
| 442 | AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), | 443 | AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP), |
| @@ -446,7 +447,7 @@ static const struct ata_port_info ahci_port_info[] = { | |||
| 446 | .udma_mask = ATA_UDMA6, | 447 | .udma_mask = ATA_UDMA6, |
| 447 | .port_ops = &ahci_ops, | 448 | .port_ops = &ahci_ops, |
| 448 | }, | 449 | }, |
| 449 | /* board_ahci_sb700, for SB700 and SB800 */ | 450 | [board_ahci_sb700] = /* for SB700 and SB800 */ |
| 450 | { | 451 | { |
| 451 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), | 452 | AHCI_HFLAGS (AHCI_HFLAG_IGN_SERR_INTERNAL), |
| 452 | .flags = AHCI_FLAG_COMMON, | 453 | .flags = AHCI_FLAG_COMMON, |
| @@ -454,7 +455,7 @@ static const struct ata_port_info ahci_port_info[] = { | |||
| 454 | .udma_mask = ATA_UDMA6, | 455 | .udma_mask = ATA_UDMA6, |
| 455 | .port_ops = &ahci_sb600_ops, | 456 | .port_ops = &ahci_sb600_ops, |
| 456 | }, | 457 | }, |
| 457 | /* board_ahci_mcp65 */ | 458 | [board_ahci_mcp65] = |
| 458 | { | 459 | { |
| 459 | AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), | 460 | AHCI_HFLAGS (AHCI_HFLAG_YES_NCQ), |
| 460 | .flags = AHCI_FLAG_COMMON, | 461 | .flags = AHCI_FLAG_COMMON, |
| @@ -462,7 +463,7 @@ static const struct ata_port_info ahci_port_info[] = { | |||
| 462 | .udma_mask = ATA_UDMA6, | 463 | .udma_mask = ATA_UDMA6, |
| 463 | .port_ops = &ahci_ops, | 464 | .port_ops = &ahci_ops, |
| 464 | }, | 465 | }, |
| 465 | /* board_ahci_nopmp */ | 466 | [board_ahci_nopmp] = |
| 466 | { | 467 | { |
| 467 | AHCI_HFLAGS (AHCI_HFLAG_NO_PMP), | 468 | AHCI_HFLAGS (AHCI_HFLAG_NO_PMP), |
| 468 | .flags = AHCI_FLAG_COMMON, | 469 | .flags = AHCI_FLAG_COMMON, |
| @@ -1140,12 +1141,12 @@ static void ahci_start_port(struct ata_port *ap) | |||
| 1140 | emp = &pp->em_priv[link->pmp]; | 1141 | emp = &pp->em_priv[link->pmp]; |
| 1141 | 1142 | ||
| 1142 | /* EM Transmit bit maybe busy during init */ | 1143 | /* EM Transmit bit maybe busy during init */ |
| 1143 | for (i = 0; i < MAX_RETRY; i++) { | 1144 | for (i = 0; i < EM_MAX_RETRY; i++) { |
| 1144 | rc = ahci_transmit_led_message(ap, | 1145 | rc = ahci_transmit_led_message(ap, |
| 1145 | emp->led_state, | 1146 | emp->led_state, |
| 1146 | 4); | 1147 | 4); |
| 1147 | if (rc == -EBUSY) | 1148 | if (rc == -EBUSY) |
| 1148 | udelay(100); | 1149 | msleep(1); |
| 1149 | else | 1150 | else |
| 1150 | break; | 1151 | break; |
| 1151 | } | 1152 | } |
| @@ -1339,7 +1340,7 @@ static ssize_t ahci_transmit_led_message(struct ata_port *ap, u32 state, | |||
| 1339 | 1340 | ||
| 1340 | /* get the slot number from the message */ | 1341 | /* get the slot number from the message */ |
| 1341 | pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; | 1342 | pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; |
| 1342 | if (pmp < MAX_SLOTS) | 1343 | if (pmp < EM_MAX_SLOTS) |
| 1343 | emp = &pp->em_priv[pmp]; | 1344 | emp = &pp->em_priv[pmp]; |
| 1344 | else | 1345 | else |
| 1345 | return -EINVAL; | 1346 | return -EINVAL; |
| @@ -1407,7 +1408,7 @@ static ssize_t ahci_led_store(struct ata_port *ap, const char *buf, | |||
| 1407 | 1408 | ||
| 1408 | /* get the slot number from the message */ | 1409 | /* get the slot number from the message */ |
| 1409 | pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; | 1410 | pmp = (state & EM_MSG_LED_PMP_SLOT) >> 8; |
| 1410 | if (pmp < MAX_SLOTS) | 1411 | if (pmp < EM_MAX_SLOTS) |
| 1411 | emp = &pp->em_priv[pmp]; | 1412 | emp = &pp->em_priv[pmp]; |
| 1412 | else | 1413 | else |
| 1413 | return -EINVAL; | 1414 | return -EINVAL; |
| @@ -2316,9 +2317,17 @@ static int ahci_port_suspend(struct ata_port *ap, pm_message_t mesg) | |||
| 2316 | static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) | 2317 | static int ahci_pci_device_suspend(struct pci_dev *pdev, pm_message_t mesg) |
| 2317 | { | 2318 | { |
| 2318 | struct ata_host *host = dev_get_drvdata(&pdev->dev); | 2319 | struct ata_host *host = dev_get_drvdata(&pdev->dev); |
| 2320 | struct ahci_host_priv *hpriv = host->private_data; | ||
| 2319 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; | 2321 | void __iomem *mmio = host->iomap[AHCI_PCI_BAR]; |
| 2320 | u32 ctl; | 2322 | u32 ctl; |
| 2321 | 2323 | ||
| 2324 | if (mesg.event & PM_EVENT_SUSPEND && | ||
| 2325 | hpriv->flags & AHCI_HFLAG_NO_SUSPEND) { | ||
| 2326 | dev_printk(KERN_ERR, &pdev->dev, | ||
| 2327 | "BIOS update required for suspend/resume\n"); | ||
| 2328 | return -EIO; | ||
| 2329 | } | ||
| 2330 | |||
| 2322 | if (mesg.event & PM_EVENT_SLEEP) { | 2331 | if (mesg.event & PM_EVENT_SLEEP) { |
| 2323 | /* AHCI spec rev1.1 section 8.3.3: | 2332 | /* AHCI spec rev1.1 section 8.3.3: |
| 2324 | * Software must disable interrupts prior to requesting a | 2333 | * Software must disable interrupts prior to requesting a |
| @@ -2575,6 +2584,51 @@ static void ahci_p5wdh_workaround(struct ata_host *host) | |||
| 2575 | } | 2584 | } |
| 2576 | } | 2585 | } |
| 2577 | 2586 | ||
| 2587 | /* | ||
| 2588 | * SB600 ahci controller on ASUS M2A-VM can't do 64bit DMA with older | ||
| 2589 | * BIOS. The oldest version known to be broken is 0901 and working is | ||
| 2590 | * 1501 which was released on 2007-10-26. Force 32bit DMA on anything | ||
| 2591 | * older than 1501. Please read bko#9412 for more info. | ||
| 2592 | */ | ||
| 2593 | static bool ahci_asus_m2a_vm_32bit_only(struct pci_dev *pdev) | ||
| 2594 | { | ||
| 2595 | static const struct dmi_system_id sysids[] = { | ||
| 2596 | { | ||
| 2597 | .ident = "ASUS M2A-VM", | ||
| 2598 | .matches = { | ||
| 2599 | DMI_MATCH(DMI_BOARD_VENDOR, | ||
| 2600 | "ASUSTeK Computer INC."), | ||
| 2601 | DMI_MATCH(DMI_BOARD_NAME, "M2A-VM"), | ||
| 2602 | }, | ||
| 2603 | }, | ||
| 2604 | { } | ||
| 2605 | }; | ||
| 2606 | const char *cutoff_mmdd = "10/26"; | ||
| 2607 | const char *date; | ||
| 2608 | int year; | ||
| 2609 | |||
| 2610 | if (pdev->bus->number != 0 || pdev->devfn != PCI_DEVFN(0x12, 0) || | ||
| 2611 | !dmi_check_system(sysids)) | ||
| 2612 | return false; | ||
| 2613 | |||
| 2614 | /* | ||
| 2615 | * Argh.... both version and date are free form strings. | ||
| 2616 | * Let's hope they're using the same date format across | ||
| 2617 | * different versions. | ||
| 2618 | */ | ||
| 2619 | date = dmi_get_system_info(DMI_BIOS_DATE); | ||
| 2620 | year = dmi_get_year(DMI_BIOS_DATE); | ||
| 2621 | if (date && strlen(date) >= 10 && date[2] == '/' && date[5] == '/' && | ||
| 2622 | (year > 2007 || | ||
| 2623 | (year == 2007 && strncmp(date, cutoff_mmdd, 5) >= 0))) | ||
| 2624 | return false; | ||
| 2625 | |||
| 2626 | dev_printk(KERN_WARNING, &pdev->dev, "ASUS M2A-VM: BIOS too old, " | ||
| 2627 | "forcing 32bit DMA, update BIOS\n"); | ||
| 2628 | |||
| 2629 | return true; | ||
| 2630 | } | ||
| 2631 | |||
| 2578 | static bool ahci_broken_system_poweroff(struct pci_dev *pdev) | 2632 | static bool ahci_broken_system_poweroff(struct pci_dev *pdev) |
| 2579 | { | 2633 | { |
| 2580 | static const struct dmi_system_id broken_systems[] = { | 2634 | static const struct dmi_system_id broken_systems[] = { |
| @@ -2610,6 +2664,63 @@ static bool ahci_broken_system_poweroff(struct pci_dev *pdev) | |||
| 2610 | return false; | 2664 | return false; |
| 2611 | } | 2665 | } |
| 2612 | 2666 | ||
| 2667 | static bool ahci_broken_suspend(struct pci_dev *pdev) | ||
| 2668 | { | ||
| 2669 | static const struct dmi_system_id sysids[] = { | ||
| 2670 | /* | ||
| 2671 | * On HP dv[4-6] and HDX18 with earlier BIOSen, link | ||
| 2672 | * to the harddisk doesn't become online after | ||
| 2673 | * resuming from STR. Warn and fail suspend. | ||
| 2674 | */ | ||
| 2675 | { | ||
| 2676 | .ident = "dv4", | ||
| 2677 | .matches = { | ||
| 2678 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2679 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2680 | "HP Pavilion dv4 Notebook PC"), | ||
| 2681 | }, | ||
| 2682 | .driver_data = "F.30", /* cutoff BIOS version */ | ||
| 2683 | }, | ||
| 2684 | { | ||
| 2685 | .ident = "dv5", | ||
| 2686 | .matches = { | ||
| 2687 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2688 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2689 | "HP Pavilion dv5 Notebook PC"), | ||
| 2690 | }, | ||
| 2691 | .driver_data = "F.16", /* cutoff BIOS version */ | ||
| 2692 | }, | ||
| 2693 | { | ||
| 2694 | .ident = "dv6", | ||
| 2695 | .matches = { | ||
| 2696 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2697 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2698 | "HP Pavilion dv6 Notebook PC"), | ||
| 2699 | }, | ||
| 2700 | .driver_data = "F.21", /* cutoff BIOS version */ | ||
| 2701 | }, | ||
| 2702 | { | ||
| 2703 | .ident = "HDX18", | ||
| 2704 | .matches = { | ||
| 2705 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 2706 | DMI_MATCH(DMI_PRODUCT_NAME, | ||
| 2707 | "HP HDX18 Notebook PC"), | ||
| 2708 | }, | ||
| 2709 | .driver_data = "F.23", /* cutoff BIOS version */ | ||
| 2710 | }, | ||
| 2711 | { } /* terminate list */ | ||
| 2712 | }; | ||
| 2713 | const struct dmi_system_id *dmi = dmi_first_match(sysids); | ||
| 2714 | const char *ver; | ||
| 2715 | |||
| 2716 | if (!dmi || pdev->bus->number || pdev->devfn != PCI_DEVFN(0x1f, 2)) | ||
| 2717 | return false; | ||
| 2718 | |||
| 2719 | ver = dmi_get_system_info(DMI_BIOS_VERSION); | ||
| 2720 | |||
| 2721 | return !ver || strcmp(ver, dmi->driver_data) < 0; | ||
| 2722 | } | ||
| 2723 | |||
| 2613 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | 2724 | static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) |
| 2614 | { | 2725 | { |
| 2615 | static int printed_version; | 2726 | static int printed_version; |
| @@ -2678,6 +2789,10 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2678 | if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) | 2789 | if (board_id == board_ahci_sb700 && pdev->revision >= 0x40) |
| 2679 | hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; | 2790 | hpriv->flags &= ~AHCI_HFLAG_IGN_SERR_INTERNAL; |
| 2680 | 2791 | ||
| 2792 | /* apply ASUS M2A_VM quirk */ | ||
| 2793 | if (ahci_asus_m2a_vm_32bit_only(pdev)) | ||
| 2794 | hpriv->flags |= AHCI_HFLAG_32BIT_ONLY; | ||
| 2795 | |||
| 2681 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) | 2796 | if (!(hpriv->flags & AHCI_HFLAG_NO_MSI)) |
| 2682 | pci_enable_msi(pdev); | 2797 | pci_enable_msi(pdev); |
| 2683 | 2798 | ||
| @@ -2715,6 +2830,12 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) | |||
| 2715 | "quirky BIOS, skipping spindown on poweroff\n"); | 2830 | "quirky BIOS, skipping spindown on poweroff\n"); |
| 2716 | } | 2831 | } |
| 2717 | 2832 | ||
| 2833 | if (ahci_broken_suspend(pdev)) { | ||
| 2834 | hpriv->flags |= AHCI_HFLAG_NO_SUSPEND; | ||
| 2835 | dev_printk(KERN_WARNING, &pdev->dev, | ||
| 2836 | "BIOS update required for suspend/resume\n"); | ||
| 2837 | } | ||
| 2838 | |||
| 2718 | /* CAP.NP sometimes indicate the index of the last enabled | 2839 | /* CAP.NP sometimes indicate the index of the last enabled |
| 2719 | * port, at other times, that of the last possible port, so | 2840 | * port, at other times, that of the last possible port, so |
| 2720 | * determining the maximum port number requires looking at | 2841 | * determining the maximum port number requires looking at |
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c index d51a17c0f59b..d0a14cf2bd74 100644 --- a/drivers/ata/ata_piix.c +++ b/drivers/ata/ata_piix.c | |||
| @@ -223,10 +223,8 @@ static const struct pci_device_id piix_pci_tbl[] = { | |||
| 223 | /* ICH8 Mobile PATA Controller */ | 223 | /* ICH8 Mobile PATA Controller */ |
| 224 | { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, | 224 | { 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 }, |
| 225 | 225 | ||
| 226 | /* NOTE: The following PCI ids must be kept in sync with the | 226 | /* SATA ports */ |
| 227 | * list in drivers/pci/quirks.c. | 227 | |
| 228 | */ | ||
| 229 | |||
| 230 | /* 82801EB (ICH5) */ | 228 | /* 82801EB (ICH5) */ |
| 231 | { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, | 229 | { 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata }, |
| 232 | /* 82801EB (ICH5) */ | 230 | /* 82801EB (ICH5) */ |
| @@ -1455,6 +1453,15 @@ static bool piix_broken_system_poweroff(struct pci_dev *pdev) | |||
| 1455 | /* PCI slot number of the controller */ | 1453 | /* PCI slot number of the controller */ |
| 1456 | .driver_data = (void *)0x1FUL, | 1454 | .driver_data = (void *)0x1FUL, |
| 1457 | }, | 1455 | }, |
| 1456 | { | ||
| 1457 | .ident = "HP Compaq nc6000", | ||
| 1458 | .matches = { | ||
| 1459 | DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"), | ||
| 1460 | DMI_MATCH(DMI_PRODUCT_NAME, "HP Compaq nc6000"), | ||
| 1461 | }, | ||
| 1462 | /* PCI slot number of the controller */ | ||
| 1463 | .driver_data = (void *)0x1FUL, | ||
| 1464 | }, | ||
| 1458 | 1465 | ||
| 1459 | { } /* terminate list */ | 1466 | { } /* terminate list */ |
| 1460 | }; | 1467 | }; |
| @@ -1500,8 +1507,8 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
| 1500 | dev_printk(KERN_DEBUG, &pdev->dev, | 1507 | dev_printk(KERN_DEBUG, &pdev->dev, |
| 1501 | "version " DRV_VERSION "\n"); | 1508 | "version " DRV_VERSION "\n"); |
| 1502 | 1509 | ||
| 1503 | /* no hotplugging support (FIXME) */ | 1510 | /* no hotplugging support for later devices (FIXME) */ |
| 1504 | if (!in_module_init) | 1511 | if (!in_module_init && ent->driver_data >= ich5_sata) |
| 1505 | return -ENODEV; | 1512 | return -ENODEV; |
| 1506 | 1513 | ||
| 1507 | if (piix_broken_system_poweroff(pdev)) { | 1514 | if (piix_broken_system_poweroff(pdev)) { |
| @@ -1582,6 +1589,7 @@ static int __devinit piix_init_one(struct pci_dev *pdev, | |||
| 1582 | host->ports[1]->mwdma_mask = 0; | 1589 | host->ports[1]->mwdma_mask = 0; |
| 1583 | host->ports[1]->udma_mask = 0; | 1590 | host->ports[1]->udma_mask = 0; |
| 1584 | } | 1591 | } |
| 1592 | host->flags |= ATA_HOST_PARALLEL_SCAN; | ||
| 1585 | 1593 | ||
| 1586 | pci_set_master(pdev); | 1594 | pci_set_master(pdev); |
| 1587 | return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht); | 1595 | return ata_pci_sff_activate_host(host, ata_sff_interrupt, &piix_sht); |
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index c9242301cfa1..ca4d208ddf3b 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
| @@ -5031,7 +5031,6 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active) | |||
| 5031 | { | 5031 | { |
| 5032 | int nr_done = 0; | 5032 | int nr_done = 0; |
| 5033 | u32 done_mask; | 5033 | u32 done_mask; |
| 5034 | int i; | ||
| 5035 | 5034 | ||
| 5036 | done_mask = ap->qc_active ^ qc_active; | 5035 | done_mask = ap->qc_active ^ qc_active; |
| 5037 | 5036 | ||
| @@ -5041,16 +5040,16 @@ int ata_qc_complete_multiple(struct ata_port *ap, u32 qc_active) | |||
| 5041 | return -EINVAL; | 5040 | return -EINVAL; |
| 5042 | } | 5041 | } |
| 5043 | 5042 | ||
| 5044 | for (i = 0; i < ATA_MAX_QUEUE; i++) { | 5043 | while (done_mask) { |
| 5045 | struct ata_queued_cmd *qc; | 5044 | struct ata_queued_cmd *qc; |
| 5045 | unsigned int tag = __ffs(done_mask); | ||
| 5046 | 5046 | ||
| 5047 | if (!(done_mask & (1 << i))) | 5047 | qc = ata_qc_from_tag(ap, tag); |
| 5048 | continue; | 5048 | if (qc) { |
| 5049 | |||
| 5050 | if ((qc = ata_qc_from_tag(ap, i))) { | ||
| 5051 | ata_qc_complete(qc); | 5049 | ata_qc_complete(qc); |
| 5052 | nr_done++; | 5050 | nr_done++; |
| 5053 | } | 5051 | } |
| 5052 | done_mask &= ~(1 << tag); | ||
| 5054 | } | 5053 | } |
| 5055 | 5054 | ||
| 5056 | return nr_done; | 5055 | return nr_done; |
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c index 342316064e9f..d0dfeef55db5 100644 --- a/drivers/ata/libata-scsi.c +++ b/drivers/ata/libata-scsi.c | |||
| @@ -1084,7 +1084,7 @@ static int atapi_drain_needed(struct request *rq) | |||
| 1084 | if (likely(!blk_pc_request(rq))) | 1084 | if (likely(!blk_pc_request(rq))) |
| 1085 | return 0; | 1085 | return 0; |
| 1086 | 1086 | ||
| 1087 | if (!rq->data_len || (rq->cmd_flags & REQ_RW)) | 1087 | if (!blk_rq_bytes(rq) || (rq->cmd_flags & REQ_RW)) |
| 1088 | return 0; | 1088 | return 0; |
| 1089 | 1089 | ||
| 1090 | return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC; | 1090 | return atapi_cmd_type(rq->cmd[0]) == ATAPI_MISC; |
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index bb18415d3d63..bbbb1fab1755 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c | |||
| @@ -727,17 +727,23 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf, | |||
| 727 | else | 727 | else |
| 728 | iowrite16_rep(data_addr, buf, words); | 728 | iowrite16_rep(data_addr, buf, words); |
| 729 | 729 | ||
| 730 | /* Transfer trailing 1 byte, if any. */ | 730 | /* Transfer trailing byte, if any. */ |
| 731 | if (unlikely(buflen & 0x01)) { | 731 | if (unlikely(buflen & 0x01)) { |
| 732 | __le16 align_buf[1] = { 0 }; | 732 | unsigned char pad[2]; |
| 733 | unsigned char *trailing_buf = buf + buflen - 1; | ||
| 734 | 733 | ||
| 734 | /* Point buf to the tail of buffer */ | ||
| 735 | buf += buflen - 1; | ||
| 736 | |||
| 737 | /* | ||
| 738 | * Use io*16_rep() accessors here as well to avoid pointlessly | ||
| 739 | * swapping bytes to and fro on the big endian machines... | ||
| 740 | */ | ||
| 735 | if (rw == READ) { | 741 | if (rw == READ) { |
| 736 | align_buf[0] = cpu_to_le16(ioread16(data_addr)); | 742 | ioread16_rep(data_addr, pad, 1); |
| 737 | memcpy(trailing_buf, align_buf, 1); | 743 | *buf = pad[0]; |
| 738 | } else { | 744 | } else { |
| 739 | memcpy(align_buf, trailing_buf, 1); | 745 | pad[0] = *buf; |
| 740 | iowrite16(le16_to_cpu(align_buf[0]), data_addr); | 746 | iowrite16_rep(data_addr, pad, 1); |
| 741 | } | 747 | } |
| 742 | words++; | 748 | words++; |
| 743 | } | 749 | } |
diff --git a/drivers/ata/pata_ali.c b/drivers/ata/pata_ali.c index 751b7ea4816c..fc9c5d6d7d80 100644 --- a/drivers/ata/pata_ali.c +++ b/drivers/ata/pata_ali.c | |||
| @@ -497,14 +497,16 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 497 | }; | 497 | }; |
| 498 | /* Revision 0x20 added DMA */ | 498 | /* Revision 0x20 added DMA */ |
| 499 | static const struct ata_port_info info_20 = { | 499 | static const struct ata_port_info info_20 = { |
| 500 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, | 500 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 | |
| 501 | ATA_FLAG_IGN_SIMPLEX, | ||
| 501 | .pio_mask = ATA_PIO4, | 502 | .pio_mask = ATA_PIO4, |
| 502 | .mwdma_mask = ATA_MWDMA2, | 503 | .mwdma_mask = ATA_MWDMA2, |
| 503 | .port_ops = &ali_20_port_ops | 504 | .port_ops = &ali_20_port_ops |
| 504 | }; | 505 | }; |
| 505 | /* Revision 0x20 with support logic added UDMA */ | 506 | /* Revision 0x20 with support logic added UDMA */ |
| 506 | static const struct ata_port_info info_20_udma = { | 507 | static const struct ata_port_info info_20_udma = { |
| 507 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, | 508 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 | |
| 509 | ATA_FLAG_IGN_SIMPLEX, | ||
| 508 | .pio_mask = ATA_PIO4, | 510 | .pio_mask = ATA_PIO4, |
| 509 | .mwdma_mask = ATA_MWDMA2, | 511 | .mwdma_mask = ATA_MWDMA2, |
| 510 | .udma_mask = ATA_UDMA2, | 512 | .udma_mask = ATA_UDMA2, |
| @@ -512,7 +514,8 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 512 | }; | 514 | }; |
| 513 | /* Revision 0xC2 adds UDMA66 */ | 515 | /* Revision 0xC2 adds UDMA66 */ |
| 514 | static const struct ata_port_info info_c2 = { | 516 | static const struct ata_port_info info_c2 = { |
| 515 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, | 517 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 | |
| 518 | ATA_FLAG_IGN_SIMPLEX, | ||
| 516 | .pio_mask = ATA_PIO4, | 519 | .pio_mask = ATA_PIO4, |
| 517 | .mwdma_mask = ATA_MWDMA2, | 520 | .mwdma_mask = ATA_MWDMA2, |
| 518 | .udma_mask = ATA_UDMA4, | 521 | .udma_mask = ATA_UDMA4, |
| @@ -520,7 +523,8 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 520 | }; | 523 | }; |
| 521 | /* Revision 0xC3 is UDMA66 for now */ | 524 | /* Revision 0xC3 is UDMA66 for now */ |
| 522 | static const struct ata_port_info info_c3 = { | 525 | static const struct ata_port_info info_c3 = { |
| 523 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, | 526 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 | |
| 527 | ATA_FLAG_IGN_SIMPLEX, | ||
| 524 | .pio_mask = ATA_PIO4, | 528 | .pio_mask = ATA_PIO4, |
| 525 | .mwdma_mask = ATA_MWDMA2, | 529 | .mwdma_mask = ATA_MWDMA2, |
| 526 | .udma_mask = ATA_UDMA4, | 530 | .udma_mask = ATA_UDMA4, |
| @@ -528,7 +532,8 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 528 | }; | 532 | }; |
| 529 | /* Revision 0xC4 is UDMA100 */ | 533 | /* Revision 0xC4 is UDMA100 */ |
| 530 | static const struct ata_port_info info_c4 = { | 534 | static const struct ata_port_info info_c4 = { |
| 531 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48, | 535 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_LBA48 | |
| 536 | ATA_FLAG_IGN_SIMPLEX, | ||
| 532 | .pio_mask = ATA_PIO4, | 537 | .pio_mask = ATA_PIO4, |
| 533 | .mwdma_mask = ATA_MWDMA2, | 538 | .mwdma_mask = ATA_MWDMA2, |
| 534 | .udma_mask = ATA_UDMA5, | 539 | .udma_mask = ATA_UDMA5, |
| @@ -536,7 +541,7 @@ static int ali_init_one(struct pci_dev *pdev, const struct pci_device_id *id) | |||
| 536 | }; | 541 | }; |
| 537 | /* Revision 0xC5 is UDMA133 with LBA48 DMA */ | 542 | /* Revision 0xC5 is UDMA133 with LBA48 DMA */ |
| 538 | static const struct ata_port_info info_c5 = { | 543 | static const struct ata_port_info info_c5 = { |
| 539 | .flags = ATA_FLAG_SLAVE_POSS, | 544 | .flags = ATA_FLAG_SLAVE_POSS | ATA_FLAG_IGN_SIMPLEX, |
| 540 | .pio_mask = ATA_PIO4, | 545 | .pio_mask = ATA_PIO4, |
| 541 | .mwdma_mask = ATA_MWDMA2, | 546 | .mwdma_mask = ATA_MWDMA2, |
| 542 | .udma_mask = ATA_UDMA6, | 547 | .udma_mask = ATA_UDMA6, |
diff --git a/drivers/ata/pata_efar.c b/drivers/ata/pata_efar.c index 2085e0a3a05a..2a6412f5d117 100644 --- a/drivers/ata/pata_efar.c +++ b/drivers/ata/pata_efar.c | |||
| @@ -22,7 +22,7 @@ | |||
| 22 | #include <linux/ata.h> | 22 | #include <linux/ata.h> |
| 23 | 23 | ||
| 24 | #define DRV_NAME "pata_efar" | 24 | #define DRV_NAME "pata_efar" |
| 25 | #define DRV_VERSION "0.4.4" | 25 | #define DRV_VERSION "0.4.5" |
| 26 | 26 | ||
| 27 | /** | 27 | /** |
| 28 | * efar_pre_reset - Enable bits | 28 | * efar_pre_reset - Enable bits |
| @@ -98,18 +98,17 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
| 98 | { 2, 1 }, | 98 | { 2, 1 }, |
| 99 | { 2, 3 }, }; | 99 | { 2, 3 }, }; |
| 100 | 100 | ||
| 101 | if (pio > 2) | 101 | if (pio > 1) |
| 102 | control |= 1; /* TIME1 enable */ | 102 | control |= 1; /* TIME */ |
| 103 | if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ | 103 | if (ata_pio_need_iordy(adev)) /* PIO 3/4 require IORDY */ |
| 104 | control |= 2; /* IE enable */ | 104 | control |= 2; /* IE */ |
| 105 | /* Intel specifies that the PPE functionality is for disk only */ | 105 | /* Intel specifies that the prefetch/posting is for disk only */ |
| 106 | if (adev->class == ATA_DEV_ATA) | 106 | if (adev->class == ATA_DEV_ATA) |
| 107 | control |= 4; /* PPE enable */ | 107 | control |= 4; /* PPE */ |
| 108 | 108 | ||
| 109 | pci_read_config_word(dev, idetm_port, &idetm_data); | 109 | pci_read_config_word(dev, idetm_port, &idetm_data); |
| 110 | 110 | ||
| 111 | /* Enable PPE, IE and TIME as appropriate */ | 111 | /* Set PPE, IE, and TIME as appropriate */ |
| 112 | |||
| 113 | if (adev->devno == 0) { | 112 | if (adev->devno == 0) { |
| 114 | idetm_data &= 0xCCF0; | 113 | idetm_data &= 0xCCF0; |
| 115 | idetm_data |= control; | 114 | idetm_data |= control; |
| @@ -129,7 +128,7 @@ static void efar_set_piomode (struct ata_port *ap, struct ata_device *adev) | |||
| 129 | pci_write_config_byte(dev, 0x44, slave_data); | 128 | pci_write_config_byte(dev, 0x44, slave_data); |
| 130 | } | 129 | } |
| 131 | 130 | ||
| 132 | idetm_data |= 0x4000; /* Ensure SITRE is enabled */ | 131 | idetm_data |= 0x4000; /* Ensure SITRE is set */ |
| 133 | pci_write_config_word(dev, idetm_port, idetm_data); | 132 | pci_write_config_word(dev, idetm_port, idetm_data); |
| 134 | } | 133 | } |
| 135 | 134 | ||
diff --git a/drivers/ata/pata_legacy.c b/drivers/ata/pata_legacy.c index f72c6c5b820f..6932e56d179c 100644 --- a/drivers/ata/pata_legacy.c +++ b/drivers/ata/pata_legacy.c | |||
| @@ -48,6 +48,7 @@ | |||
| 48 | * | 48 | * |
| 49 | */ | 49 | */ |
| 50 | 50 | ||
| 51 | #include <linux/async.h> | ||
| 51 | #include <linux/kernel.h> | 52 | #include <linux/kernel.h> |
| 52 | #include <linux/module.h> | 53 | #include <linux/module.h> |
| 53 | #include <linux/pci.h> | 54 | #include <linux/pci.h> |
| @@ -1028,6 +1029,7 @@ static __init int legacy_init_one(struct legacy_probe *probe) | |||
| 1028 | &legacy_sht); | 1029 | &legacy_sht); |
| 1029 | if (ret) | 1030 | if (ret) |
| 1030 | goto fail; | 1031 | goto fail; |
| 1032 | async_synchronize_full(); | ||
| 1031 | ld->platform_dev = pdev; | 1033 | ld->platform_dev = pdev; |
| 1032 | 1034 | ||
| 1033 | /* Nothing found means we drop the port as its probably not there */ | 1035 | /* Nothing found means we drop the port as its probably not there */ |
diff --git a/drivers/ata/pata_netcell.c b/drivers/ata/pata_netcell.c index bdb236957cb9..f0d52f72f5bb 100644 --- a/drivers/ata/pata_netcell.c +++ b/drivers/ata/pata_netcell.c | |||
| @@ -20,13 +20,24 @@ | |||
| 20 | 20 | ||
| 21 | /* No PIO or DMA methods needed for this device */ | 21 | /* No PIO or DMA methods needed for this device */ |
| 22 | 22 | ||
| 23 | static unsigned int netcell_read_id(struct ata_device *adev, | ||
| 24 | struct ata_taskfile *tf, u16 *id) | ||
| 25 | { | ||
| 26 | unsigned int err_mask = ata_do_dev_read_id(adev, tf, id); | ||
| 27 | /* Firmware forgets to mark words 85-87 valid */ | ||
| 28 | if (err_mask == 0) | ||
| 29 | id[ATA_ID_CSF_DEFAULT] |= 0x4000; | ||
| 30 | return err_mask; | ||
| 31 | } | ||
| 32 | |||
| 23 | static struct scsi_host_template netcell_sht = { | 33 | static struct scsi_host_template netcell_sht = { |
| 24 | ATA_BMDMA_SHT(DRV_NAME), | 34 | ATA_BMDMA_SHT(DRV_NAME), |
| 25 | }; | 35 | }; |
| 26 | 36 | ||
| 27 | static struct ata_port_operations netcell_ops = { | 37 | static struct ata_port_operations netcell_ops = { |
| 28 | .inherits = &ata_bmdma_port_ops, | 38 | .inherits = &ata_bmdma_port_ops, |
| 29 | .cable_detect = ata_cable_80wire, | 39 | .cable_detect = ata_cable_80wire, |
| 40 | .read_id = netcell_read_id, | ||
| 30 | }; | 41 | }; |
| 31 | 42 | ||
| 32 | 43 | ||
diff --git a/drivers/ata/sata_nv.c b/drivers/ata/sata_nv.c index 6cda12ba8122..b2d11f300c39 100644 --- a/drivers/ata/sata_nv.c +++ b/drivers/ata/sata_nv.c | |||
| @@ -305,8 +305,8 @@ static irqreturn_t nv_ck804_interrupt(int irq, void *dev_instance); | |||
| 305 | static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); | 305 | static int nv_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val); |
| 306 | static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); | 306 | static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val); |
| 307 | 307 | ||
| 308 | static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class, | 308 | static int nv_hardreset(struct ata_link *link, unsigned int *class, |
| 309 | unsigned long deadline); | 309 | unsigned long deadline); |
| 310 | static void nv_nf2_freeze(struct ata_port *ap); | 310 | static void nv_nf2_freeze(struct ata_port *ap); |
| 311 | static void nv_nf2_thaw(struct ata_port *ap); | 311 | static void nv_nf2_thaw(struct ata_port *ap); |
| 312 | static void nv_ck804_freeze(struct ata_port *ap); | 312 | static void nv_ck804_freeze(struct ata_port *ap); |
| @@ -406,49 +406,82 @@ static struct scsi_host_template nv_swncq_sht = { | |||
| 406 | .slave_configure = nv_swncq_slave_config, | 406 | .slave_configure = nv_swncq_slave_config, |
| 407 | }; | 407 | }; |
| 408 | 408 | ||
| 409 | static struct ata_port_operations nv_common_ops = { | 409 | /* |
| 410 | * NV SATA controllers have various different problems with hardreset | ||
| 411 | * protocol depending on the specific controller and device. | ||
| 412 | * | ||
| 413 | * GENERIC: | ||
| 414 | * | ||
| 415 | * bko11195 reports that link doesn't come online after hardreset on | ||
| 416 | * generic nv's and there have been several other similar reports on | ||
| 417 | * linux-ide. | ||
| 418 | * | ||
| 419 | * bko12351#c23 reports that warmplug on MCP61 doesn't work with | ||
| 420 | * softreset. | ||
| 421 | * | ||
| 422 | * NF2/3: | ||
| 423 | * | ||
| 424 | * bko3352 reports nf2/3 controllers can't determine device signature | ||
| 425 | * reliably after hardreset. The following thread reports detection | ||
| 426 | * failure on cold boot with the standard debouncing timing. | ||
| 427 | * | ||
| 428 | * http://thread.gmane.org/gmane.linux.ide/34098 | ||
| 429 | * | ||
| 430 | * bko12176 reports that hardreset fails to bring up the link during | ||
| 431 | * boot on nf2. | ||
| 432 | * | ||
| 433 | * CK804: | ||
| 434 | * | ||
| 435 | * For initial probing after boot and hot plugging, hardreset mostly | ||
| 436 | * works fine on CK804 but curiously, reprobing on the initial port | ||
| 437 | * by rescanning or rmmod/insmod fails to acquire the initial D2H Reg | ||
| 438 | * FIS in somewhat undeterministic way. | ||
| 439 | * | ||
| 440 | * SWNCQ: | ||
| 441 | * | ||
| 442 | * bko12351 reports that when SWNCQ is enabled, for hotplug to work, | ||
| 443 | * hardreset should be used and hardreset can't report proper | ||
| 444 | * signature, which suggests that mcp5x is closer to nf2 as long as | ||
| 445 | * reset quirkiness is concerned. | ||
| 446 | * | ||
| 447 | * bko12703 reports that boot probing fails for intel SSD with | ||
| 448 | * hardreset. Link fails to come online. Softreset works fine. | ||
| 449 | * | ||
| 450 | * The failures are varied but the following patterns seem true for | ||
| 451 | * all flavors. | ||
| 452 | * | ||
| 453 | * - Softreset during boot always works. | ||
| 454 | * | ||
| 455 | * - Hardreset during boot sometimes fails to bring up the link on | ||
| 456 | * certain comibnations and device signature acquisition is | ||
| 457 | * unreliable. | ||
| 458 | * | ||
| 459 | * - Hardreset is often necessary after hotplug. | ||
| 460 | * | ||
| 461 | * So, preferring softreset for boot probing and error handling (as | ||
| 462 | * hardreset might bring down the link) but using hardreset for | ||
| 463 | * post-boot probing should work around the above issues in most | ||
| 464 | * cases. Define nv_hardreset() which only kicks in for post-boot | ||
| 465 | * probing and use it for all variants. | ||
| 466 | */ | ||
| 467 | static struct ata_port_operations nv_generic_ops = { | ||
| 410 | .inherits = &ata_bmdma_port_ops, | 468 | .inherits = &ata_bmdma_port_ops, |
| 411 | .lost_interrupt = ATA_OP_NULL, | 469 | .lost_interrupt = ATA_OP_NULL, |
| 412 | .scr_read = nv_scr_read, | 470 | .scr_read = nv_scr_read, |
| 413 | .scr_write = nv_scr_write, | 471 | .scr_write = nv_scr_write, |
| 472 | .hardreset = nv_hardreset, | ||
| 414 | }; | 473 | }; |
| 415 | 474 | ||
| 416 | /* OSDL bz11195 reports that link doesn't come online after hardreset | ||
| 417 | * on generic nv's and there have been several other similar reports | ||
| 418 | * on linux-ide. Disable hardreset for generic nv's. | ||
| 419 | */ | ||
| 420 | static struct ata_port_operations nv_generic_ops = { | ||
| 421 | .inherits = &nv_common_ops, | ||
| 422 | .hardreset = ATA_OP_NULL, | ||
| 423 | }; | ||
| 424 | |||
| 425 | /* nf2 is ripe with hardreset related problems. | ||
| 426 | * | ||
| 427 | * kernel bz#3352 reports nf2/3 controllers can't determine device | ||
| 428 | * signature reliably. The following thread reports detection failure | ||
| 429 | * on cold boot with the standard debouncing timing. | ||
| 430 | * | ||
| 431 | * http://thread.gmane.org/gmane.linux.ide/34098 | ||
| 432 | * | ||
| 433 | * And bz#12176 reports that hardreset simply doesn't work on nf2. | ||
| 434 | * Give up on it and just don't do hardreset. | ||
| 435 | */ | ||
| 436 | static struct ata_port_operations nv_nf2_ops = { | 475 | static struct ata_port_operations nv_nf2_ops = { |
| 437 | .inherits = &nv_generic_ops, | 476 | .inherits = &nv_generic_ops, |
| 438 | .freeze = nv_nf2_freeze, | 477 | .freeze = nv_nf2_freeze, |
| 439 | .thaw = nv_nf2_thaw, | 478 | .thaw = nv_nf2_thaw, |
| 440 | }; | 479 | }; |
| 441 | 480 | ||
| 442 | /* For initial probing after boot and hot plugging, hardreset mostly | ||
| 443 | * works fine on CK804 but curiously, reprobing on the initial port by | ||
| 444 | * rescanning or rmmod/insmod fails to acquire the initial D2H Reg FIS | ||
| 445 | * in somewhat undeterministic way. Use noclassify hardreset. | ||
| 446 | */ | ||
| 447 | static struct ata_port_operations nv_ck804_ops = { | 481 | static struct ata_port_operations nv_ck804_ops = { |
| 448 | .inherits = &nv_common_ops, | 482 | .inherits = &nv_generic_ops, |
| 449 | .freeze = nv_ck804_freeze, | 483 | .freeze = nv_ck804_freeze, |
| 450 | .thaw = nv_ck804_thaw, | 484 | .thaw = nv_ck804_thaw, |
| 451 | .hardreset = nv_noclassify_hardreset, | ||
| 452 | .host_stop = nv_ck804_host_stop, | 485 | .host_stop = nv_ck804_host_stop, |
| 453 | }; | 486 | }; |
| 454 | 487 | ||
| @@ -476,19 +509,8 @@ static struct ata_port_operations nv_adma_ops = { | |||
| 476 | .host_stop = nv_adma_host_stop, | 509 | .host_stop = nv_adma_host_stop, |
| 477 | }; | 510 | }; |
| 478 | 511 | ||
| 479 | /* Kernel bz#12351 reports that when SWNCQ is enabled, for hotplug to | ||
| 480 | * work, hardreset should be used and hardreset can't report proper | ||
| 481 | * signature, which suggests that mcp5x is closer to nf2 as long as | ||
| 482 | * reset quirkiness is concerned. Define separate ops for mcp5x with | ||
| 483 | * nv_noclassify_hardreset(). | ||
| 484 | */ | ||
| 485 | static struct ata_port_operations nv_mcp5x_ops = { | ||
| 486 | .inherits = &nv_common_ops, | ||
| 487 | .hardreset = nv_noclassify_hardreset, | ||
| 488 | }; | ||
| 489 | |||
| 490 | static struct ata_port_operations nv_swncq_ops = { | 512 | static struct ata_port_operations nv_swncq_ops = { |
| 491 | .inherits = &nv_mcp5x_ops, | 513 | .inherits = &nv_generic_ops, |
| 492 | 514 | ||
| 493 | .qc_defer = ata_std_qc_defer, | 515 | .qc_defer = ata_std_qc_defer, |
| 494 | .qc_prep = nv_swncq_qc_prep, | 516 | .qc_prep = nv_swncq_qc_prep, |
| @@ -557,7 +579,7 @@ static const struct ata_port_info nv_port_info[] = { | |||
| 557 | .pio_mask = NV_PIO_MASK, | 579 | .pio_mask = NV_PIO_MASK, |
| 558 | .mwdma_mask = NV_MWDMA_MASK, | 580 | .mwdma_mask = NV_MWDMA_MASK, |
| 559 | .udma_mask = NV_UDMA_MASK, | 581 | .udma_mask = NV_UDMA_MASK, |
| 560 | .port_ops = &nv_mcp5x_ops, | 582 | .port_ops = &nv_generic_ops, |
| 561 | .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht), | 583 | .private_data = NV_PI_PRIV(nv_generic_interrupt, &nv_sht), |
| 562 | }, | 584 | }, |
| 563 | /* SWNCQ */ | 585 | /* SWNCQ */ |
| @@ -1559,15 +1581,24 @@ static int nv_scr_write(struct ata_link *link, unsigned int sc_reg, u32 val) | |||
| 1559 | return 0; | 1581 | return 0; |
| 1560 | } | 1582 | } |
| 1561 | 1583 | ||
| 1562 | static int nv_noclassify_hardreset(struct ata_link *link, unsigned int *class, | 1584 | static int nv_hardreset(struct ata_link *link, unsigned int *class, |
| 1563 | unsigned long deadline) | 1585 | unsigned long deadline) |
| 1564 | { | 1586 | { |
| 1565 | bool online; | 1587 | struct ata_eh_context *ehc = &link->eh_context; |
| 1566 | int rc; | ||
| 1567 | 1588 | ||
| 1568 | rc = sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, | 1589 | /* Do hardreset iff it's post-boot probing, please read the |
| 1569 | &online, NULL); | 1590 | * comment above port ops for details. |
| 1570 | return online ? -EAGAIN : rc; | 1591 | */ |
| 1592 | if (!(link->ap->pflags & ATA_PFLAG_LOADING) && | ||
| 1593 | !ata_dev_enabled(link->device)) | ||
| 1594 | sata_link_hardreset(link, sata_deb_timing_hotplug, deadline, | ||
| 1595 | NULL, NULL); | ||
| 1596 | else if (!(ehc->i.flags & ATA_EHI_QUIET)) | ||
| 1597 | ata_link_printk(link, KERN_INFO, | ||
| 1598 | "nv: skipping hardreset on occupied port\n"); | ||
| 1599 | |||
| 1600 | /* device signature acquisition is unreliable */ | ||
| 1601 | return -EAGAIN; | ||
| 1571 | } | 1602 | } |
| 1572 | 1603 | ||
| 1573 | static void nv_nf2_freeze(struct ata_port *ap) | 1604 | static void nv_nf2_freeze(struct ata_port *ap) |
diff --git a/drivers/ata/sata_sil.c b/drivers/ata/sata_sil.c index e67ce8e5caa5..030ec079b184 100644 --- a/drivers/ata/sata_sil.c +++ b/drivers/ata/sata_sil.c | |||
| @@ -183,7 +183,7 @@ static struct scsi_host_template sil_sht = { | |||
| 183 | }; | 183 | }; |
| 184 | 184 | ||
| 185 | static struct ata_port_operations sil_ops = { | 185 | static struct ata_port_operations sil_ops = { |
| 186 | .inherits = &ata_bmdma_port_ops, | 186 | .inherits = &ata_bmdma32_port_ops, |
| 187 | .dev_config = sil_dev_config, | 187 | .dev_config = sil_dev_config, |
| 188 | .set_mode = sil_set_mode, | 188 | .set_mode = sil_set_mode, |
| 189 | .bmdma_setup = sil_bmdma_setup, | 189 | .bmdma_setup = sil_bmdma_setup, |
diff --git a/drivers/ata/sata_sx4.c b/drivers/ata/sata_sx4.c index eb05a3c82a9e..bbcf970068ad 100644 --- a/drivers/ata/sata_sx4.c +++ b/drivers/ata/sata_sx4.c | |||
| @@ -193,6 +193,7 @@ enum { | |||
| 193 | PDC_TIMER_MASK_INT, | 193 | PDC_TIMER_MASK_INT, |
| 194 | }; | 194 | }; |
| 195 | 195 | ||
| 196 | #define ECC_ERASE_BUF_SZ (128 * 1024) | ||
| 196 | 197 | ||
| 197 | struct pdc_port_priv { | 198 | struct pdc_port_priv { |
| 198 | u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512]; | 199 | u8 dimm_buf[(ATA_PRD_SZ * ATA_MAX_PRD) + 512]; |
| @@ -1280,7 +1281,6 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) | |||
| 1280 | { | 1281 | { |
| 1281 | int speed, size, length; | 1282 | int speed, size, length; |
| 1282 | u32 addr, spd0, pci_status; | 1283 | u32 addr, spd0, pci_status; |
| 1283 | u32 tmp = 0; | ||
| 1284 | u32 time_period = 0; | 1284 | u32 time_period = 0; |
| 1285 | u32 tcount = 0; | 1285 | u32 tcount = 0; |
| 1286 | u32 ticks = 0; | 1286 | u32 ticks = 0; |
| @@ -1395,14 +1395,17 @@ static unsigned int pdc20621_dimm_init(struct ata_host *host) | |||
| 1395 | pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, | 1395 | pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS, |
| 1396 | PDC_DIMM_SPD_TYPE, &spd0); | 1396 | PDC_DIMM_SPD_TYPE, &spd0); |
| 1397 | if (spd0 == 0x02) { | 1397 | if (spd0 == 0x02) { |
| 1398 | void *buf; | ||
| 1398 | VPRINTK("Start ECC initialization\n"); | 1399 | VPRINTK("Start ECC initialization\n"); |
| 1399 | addr = 0; | 1400 | addr = 0; |
| 1400 | length = size * 1024 * 1024; | 1401 | length = size * 1024 * 1024; |
| 1402 | buf = kzalloc(ECC_ERASE_BUF_SZ, GFP_KERNEL); | ||
| 1401 | while (addr < length) { | 1403 | while (addr < length) { |
| 1402 | pdc20621_put_to_dimm(host, (void *) &tmp, addr, | 1404 | pdc20621_put_to_dimm(host, buf, addr, |
| 1403 | sizeof(u32)); | 1405 | ECC_ERASE_BUF_SZ); |
| 1404 | addr += sizeof(u32); | 1406 | addr += ECC_ERASE_BUF_SZ; |
| 1405 | } | 1407 | } |
| 1408 | kfree(buf); | ||
| 1406 | VPRINTK("Finish ECC initialization\n"); | 1409 | VPRINTK("Finish ECC initialization\n"); |
| 1407 | } | 1410 | } |
| 1408 | return 0; | 1411 | return 0; |
diff --git a/drivers/base/bus.c b/drivers/base/bus.c index dc030f1f00f1..c6599618523e 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c | |||
| @@ -700,8 +700,10 @@ int bus_add_driver(struct device_driver *drv) | |||
| 700 | } | 700 | } |
| 701 | 701 | ||
| 702 | kobject_uevent(&priv->kobj, KOBJ_ADD); | 702 | kobject_uevent(&priv->kobj, KOBJ_ADD); |
| 703 | return error; | 703 | return 0; |
| 704 | out_unregister: | 704 | out_unregister: |
| 705 | kfree(drv->p); | ||
| 706 | drv->p = NULL; | ||
| 705 | kobject_put(&priv->kobj); | 707 | kobject_put(&priv->kobj); |
| 706 | out_put_bus: | 708 | out_put_bus: |
| 707 | bus_put(bus); | 709 | bus_put(bus); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index 4aa527b8a913..1977d4beb89e 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
| @@ -879,7 +879,7 @@ int device_add(struct device *dev) | |||
| 879 | } | 879 | } |
| 880 | 880 | ||
| 881 | if (!dev_name(dev)) | 881 | if (!dev_name(dev)) |
| 882 | goto done; | 882 | goto name_error; |
| 883 | 883 | ||
| 884 | pr_debug("device: '%s': %s\n", dev_name(dev), __func__); | 884 | pr_debug("device: '%s': %s\n", dev_name(dev), __func__); |
| 885 | 885 | ||
| @@ -978,6 +978,9 @@ done: | |||
| 978 | cleanup_device_parent(dev); | 978 | cleanup_device_parent(dev); |
| 979 | if (parent) | 979 | if (parent) |
| 980 | put_device(parent); | 980 | put_device(parent); |
| 981 | name_error: | ||
| 982 | kfree(dev->p); | ||
| 983 | dev->p = NULL; | ||
| 981 | goto done; | 984 | goto done; |
| 982 | } | 985 | } |
| 983 | 986 | ||
diff --git a/drivers/base/driver.c b/drivers/base/driver.c index c51f11bb29ae..8ae0f63602e0 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c | |||
| @@ -257,6 +257,10 @@ EXPORT_SYMBOL_GPL(driver_register); | |||
| 257 | */ | 257 | */ |
| 258 | void driver_unregister(struct device_driver *drv) | 258 | void driver_unregister(struct device_driver *drv) |
| 259 | { | 259 | { |
| 260 | if (!drv || !drv->p) { | ||
| 261 | WARN(1, "Unexpected driver unregister!\n"); | ||
| 262 | return; | ||
| 263 | } | ||
| 260 | driver_remove_groups(drv, drv->groups); | 264 | driver_remove_groups(drv, drv->groups); |
| 261 | bus_remove_driver(drv); | 265 | bus_remove_driver(drv); |
| 262 | } | 266 | } |
diff --git a/drivers/block/DAC960.c b/drivers/block/DAC960.c index f22ed6cc69f2..668dc234b8e2 100644 --- a/drivers/block/DAC960.c +++ b/drivers/block/DAC960.c | |||
| @@ -3321,7 +3321,7 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_ | |||
| 3321 | DAC960_Command_T *Command; | 3321 | DAC960_Command_T *Command; |
| 3322 | 3322 | ||
| 3323 | while(1) { | 3323 | while(1) { |
| 3324 | Request = elv_next_request(req_q); | 3324 | Request = blk_peek_request(req_q); |
| 3325 | if (!Request) | 3325 | if (!Request) |
| 3326 | return 1; | 3326 | return 1; |
| 3327 | 3327 | ||
| @@ -3338,10 +3338,10 @@ static int DAC960_process_queue(DAC960_Controller_T *Controller, struct request_ | |||
| 3338 | } | 3338 | } |
| 3339 | Command->Completion = Request->end_io_data; | 3339 | Command->Completion = Request->end_io_data; |
| 3340 | Command->LogicalDriveNumber = (long)Request->rq_disk->private_data; | 3340 | Command->LogicalDriveNumber = (long)Request->rq_disk->private_data; |
| 3341 | Command->BlockNumber = Request->sector; | 3341 | Command->BlockNumber = blk_rq_pos(Request); |
| 3342 | Command->BlockCount = Request->nr_sectors; | 3342 | Command->BlockCount = blk_rq_sectors(Request); |
| 3343 | Command->Request = Request; | 3343 | Command->Request = Request; |
| 3344 | blkdev_dequeue_request(Request); | 3344 | blk_start_request(Request); |
| 3345 | Command->SegmentCount = blk_rq_map_sg(req_q, | 3345 | Command->SegmentCount = blk_rq_map_sg(req_q, |
| 3346 | Command->Request, Command->cmd_sglist); | 3346 | Command->Request, Command->cmd_sglist); |
| 3347 | /* pci_map_sg MAY change the value of SegCount */ | 3347 | /* pci_map_sg MAY change the value of SegCount */ |
| @@ -3431,7 +3431,7 @@ static void DAC960_queue_partial_rw(DAC960_Command_T *Command) | |||
| 3431 | * successfully as possible. | 3431 | * successfully as possible. |
| 3432 | */ | 3432 | */ |
| 3433 | Command->SegmentCount = 1; | 3433 | Command->SegmentCount = 1; |
| 3434 | Command->BlockNumber = Request->sector; | 3434 | Command->BlockNumber = blk_rq_pos(Request); |
| 3435 | Command->BlockCount = 1; | 3435 | Command->BlockCount = 1; |
| 3436 | DAC960_QueueReadWriteCommand(Command); | 3436 | DAC960_QueueReadWriteCommand(Command); |
| 3437 | return; | 3437 | return; |
diff --git a/drivers/block/Kconfig b/drivers/block/Kconfig index ddea8e485cc9..f42fa50d3550 100644 --- a/drivers/block/Kconfig +++ b/drivers/block/Kconfig | |||
| @@ -412,7 +412,7 @@ config ATA_OVER_ETH | |||
| 412 | 412 | ||
| 413 | config MG_DISK | 413 | config MG_DISK |
| 414 | tristate "mGine mflash, gflash support" | 414 | tristate "mGine mflash, gflash support" |
| 415 | depends on ARM && ATA && GPIOLIB | 415 | depends on ARM && GPIOLIB |
| 416 | help | 416 | help |
| 417 | mGine mFlash(gFlash) block device driver | 417 | mGine mFlash(gFlash) block device driver |
| 418 | 418 | ||
diff --git a/drivers/block/amiflop.c b/drivers/block/amiflop.c index 8df436ff7068..9c6e5b0fe894 100644 --- a/drivers/block/amiflop.c +++ b/drivers/block/amiflop.c | |||
| @@ -112,8 +112,6 @@ module_param(fd_def_df0, ulong, 0); | |||
| 112 | MODULE_LICENSE("GPL"); | 112 | MODULE_LICENSE("GPL"); |
| 113 | 113 | ||
| 114 | static struct request_queue *floppy_queue; | 114 | static struct request_queue *floppy_queue; |
| 115 | #define QUEUE (floppy_queue) | ||
| 116 | #define CURRENT elv_next_request(floppy_queue) | ||
| 117 | 115 | ||
| 118 | /* | 116 | /* |
| 119 | * Macros | 117 | * Macros |
| @@ -1335,64 +1333,60 @@ static int get_track(int drive, int track) | |||
| 1335 | 1333 | ||
| 1336 | static void redo_fd_request(void) | 1334 | static void redo_fd_request(void) |
| 1337 | { | 1335 | { |
| 1336 | struct request *rq; | ||
| 1338 | unsigned int cnt, block, track, sector; | 1337 | unsigned int cnt, block, track, sector; |
| 1339 | int drive; | 1338 | int drive; |
| 1340 | struct amiga_floppy_struct *floppy; | 1339 | struct amiga_floppy_struct *floppy; |
| 1341 | char *data; | 1340 | char *data; |
| 1342 | unsigned long flags; | 1341 | unsigned long flags; |
| 1342 | int err; | ||
| 1343 | 1343 | ||
| 1344 | repeat: | 1344 | next_req: |
| 1345 | if (!CURRENT) { | 1345 | rq = blk_fetch_request(floppy_queue); |
| 1346 | if (!rq) { | ||
| 1346 | /* Nothing left to do */ | 1347 | /* Nothing left to do */ |
| 1347 | return; | 1348 | return; |
| 1348 | } | 1349 | } |
| 1349 | 1350 | ||
| 1350 | floppy = CURRENT->rq_disk->private_data; | 1351 | floppy = rq->rq_disk->private_data; |
| 1351 | drive = floppy - unit; | 1352 | drive = floppy - unit; |
| 1352 | 1353 | ||
| 1354 | next_segment: | ||
| 1353 | /* Here someone could investigate to be more efficient */ | 1355 | /* Here someone could investigate to be more efficient */ |
| 1354 | for (cnt = 0; cnt < CURRENT->current_nr_sectors; cnt++) { | 1356 | for (cnt = 0, err = 0; cnt < blk_rq_cur_sectors(rq); cnt++) { |
| 1355 | #ifdef DEBUG | 1357 | #ifdef DEBUG |
| 1356 | printk("fd: sector %ld + %d requested for %s\n", | 1358 | printk("fd: sector %ld + %d requested for %s\n", |
| 1357 | CURRENT->sector,cnt, | 1359 | blk_rq_pos(rq), cnt, |
| 1358 | (rq_data_dir(CURRENT) == READ) ? "read" : "write"); | 1360 | (rq_data_dir(rq) == READ) ? "read" : "write"); |
| 1359 | #endif | 1361 | #endif |
| 1360 | block = CURRENT->sector + cnt; | 1362 | block = blk_rq_pos(rq) + cnt; |
| 1361 | if ((int)block > floppy->blocks) { | 1363 | if ((int)block > floppy->blocks) { |
| 1362 | end_request(CURRENT, 0); | 1364 | err = -EIO; |
| 1363 | goto repeat; | 1365 | break; |
| 1364 | } | 1366 | } |
| 1365 | 1367 | ||
| 1366 | track = block / (floppy->dtype->sects * floppy->type->sect_mult); | 1368 | track = block / (floppy->dtype->sects * floppy->type->sect_mult); |
| 1367 | sector = block % (floppy->dtype->sects * floppy->type->sect_mult); | 1369 | sector = block % (floppy->dtype->sects * floppy->type->sect_mult); |
| 1368 | data = CURRENT->buffer + 512 * cnt; | 1370 | data = rq->buffer + 512 * cnt; |
| 1369 | #ifdef DEBUG | 1371 | #ifdef DEBUG |
| 1370 | printk("access to track %d, sector %d, with buffer at " | 1372 | printk("access to track %d, sector %d, with buffer at " |
| 1371 | "0x%08lx\n", track, sector, data); | 1373 | "0x%08lx\n", track, sector, data); |
| 1372 | #endif | 1374 | #endif |
| 1373 | 1375 | ||
| 1374 | if ((rq_data_dir(CURRENT) != READ) && (rq_data_dir(CURRENT) != WRITE)) { | ||
| 1375 | printk(KERN_WARNING "do_fd_request: unknown command\n"); | ||
| 1376 | end_request(CURRENT, 0); | ||
| 1377 | goto repeat; | ||
| 1378 | } | ||
| 1379 | if (get_track(drive, track) == -1) { | 1376 | if (get_track(drive, track) == -1) { |
| 1380 | end_request(CURRENT, 0); | 1377 | err = -EIO; |
| 1381 | goto repeat; | 1378 | break; |
| 1382 | } | 1379 | } |
| 1383 | 1380 | ||
| 1384 | switch (rq_data_dir(CURRENT)) { | 1381 | if (rq_data_dir(rq) == READ) { |
| 1385 | case READ: | ||
| 1386 | memcpy(data, floppy->trackbuf + sector * 512, 512); | 1382 | memcpy(data, floppy->trackbuf + sector * 512, 512); |
| 1387 | break; | 1383 | } else { |
| 1388 | |||
| 1389 | case WRITE: | ||
| 1390 | memcpy(floppy->trackbuf + sector * 512, data, 512); | 1384 | memcpy(floppy->trackbuf + sector * 512, data, 512); |
| 1391 | 1385 | ||
| 1392 | /* keep the drive spinning while writes are scheduled */ | 1386 | /* keep the drive spinning while writes are scheduled */ |
| 1393 | if (!fd_motor_on(drive)) { | 1387 | if (!fd_motor_on(drive)) { |
| 1394 | end_request(CURRENT, 0); | 1388 | err = -EIO; |
| 1395 | goto repeat; | 1389 | break; |
| 1396 | } | 1390 | } |
| 1397 | /* | 1391 | /* |
| 1398 | * setup a callback to write the track buffer | 1392 | * setup a callback to write the track buffer |
| @@ -1404,14 +1398,12 @@ static void redo_fd_request(void) | |||
| 1404 | /* reset the timer */ | 1398 | /* reset the timer */ |
| 1405 | mod_timer (flush_track_timer + drive, jiffies + 1); | 1399 | mod_timer (flush_track_timer + drive, jiffies + 1); |
| 1406 | local_irq_restore(flags); | 1400 | local_irq_restore(flags); |
| 1407 | break; | ||
| 1408 | } | 1401 | } |
| 1409 | } | 1402 | } |
| 1410 | CURRENT->nr_sectors -= CURRENT->current_nr_sectors; | ||
| 1411 | CURRENT->sector += CURRENT->current_nr_sectors; | ||
| 1412 | 1403 | ||
| 1413 | end_request(CURRENT, 1); | 1404 | if (__blk_end_request_cur(rq, err)) |
| 1414 | goto repeat; | 1405 | goto next_segment; |
| 1406 | goto next_req; | ||
| 1415 | } | 1407 | } |
| 1416 | 1408 | ||
| 1417 | static void do_fd_request(struct request_queue * q) | 1409 | static void do_fd_request(struct request_queue * q) |
diff --git a/drivers/block/ataflop.c b/drivers/block/ataflop.c index 4234c11c1e4c..f5e7180d7f47 100644 --- a/drivers/block/ataflop.c +++ b/drivers/block/ataflop.c | |||
| @@ -79,9 +79,7 @@ | |||
| 79 | #undef DEBUG | 79 | #undef DEBUG |
| 80 | 80 | ||
| 81 | static struct request_queue *floppy_queue; | 81 | static struct request_queue *floppy_queue; |
| 82 | 82 | static struct request *fd_request; | |
| 83 | #define QUEUE (floppy_queue) | ||
| 84 | #define CURRENT elv_next_request(floppy_queue) | ||
| 85 | 83 | ||
| 86 | /* Disk types: DD, HD, ED */ | 84 | /* Disk types: DD, HD, ED */ |
| 87 | static struct atari_disk_type { | 85 | static struct atari_disk_type { |
| @@ -376,6 +374,12 @@ static DEFINE_TIMER(readtrack_timer, fd_readtrack_check, 0, 0); | |||
| 376 | static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0); | 374 | static DEFINE_TIMER(timeout_timer, fd_times_out, 0, 0); |
| 377 | static DEFINE_TIMER(fd_timer, check_change, 0, 0); | 375 | static DEFINE_TIMER(fd_timer, check_change, 0, 0); |
| 378 | 376 | ||
| 377 | static void fd_end_request_cur(int err) | ||
| 378 | { | ||
| 379 | if (!__blk_end_request_cur(fd_request, err)) | ||
| 380 | fd_request = NULL; | ||
| 381 | } | ||
| 382 | |||
| 379 | static inline void start_motor_off_timer(void) | 383 | static inline void start_motor_off_timer(void) |
| 380 | { | 384 | { |
| 381 | mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY); | 385 | mod_timer(&motor_off_timer, jiffies + FD_MOTOR_OFF_DELAY); |
| @@ -606,15 +610,15 @@ static void fd_error( void ) | |||
| 606 | return; | 610 | return; |
| 607 | } | 611 | } |
| 608 | 612 | ||
| 609 | if (!CURRENT) | 613 | if (!fd_request) |
| 610 | return; | 614 | return; |
| 611 | 615 | ||
| 612 | CURRENT->errors++; | 616 | fd_request->errors++; |
| 613 | if (CURRENT->errors >= MAX_ERRORS) { | 617 | if (fd_request->errors >= MAX_ERRORS) { |
| 614 | printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive ); | 618 | printk(KERN_ERR "fd%d: too many errors.\n", SelectedDrive ); |
| 615 | end_request(CURRENT, 0); | 619 | fd_end_request_cur(-EIO); |
| 616 | } | 620 | } |
| 617 | else if (CURRENT->errors == RECALIBRATE_ERRORS) { | 621 | else if (fd_request->errors == RECALIBRATE_ERRORS) { |
| 618 | printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive ); | 622 | printk(KERN_WARNING "fd%d: recalibrating\n", SelectedDrive ); |
| 619 | if (SelectedDrive != -1) | 623 | if (SelectedDrive != -1) |
| 620 | SUD.track = -1; | 624 | SUD.track = -1; |
| @@ -725,16 +729,14 @@ static void do_fd_action( int drive ) | |||
| 725 | if (IS_BUFFERED( drive, ReqSide, ReqTrack )) { | 729 | if (IS_BUFFERED( drive, ReqSide, ReqTrack )) { |
| 726 | if (ReqCmd == READ) { | 730 | if (ReqCmd == READ) { |
| 727 | copy_buffer( SECTOR_BUFFER(ReqSector), ReqData ); | 731 | copy_buffer( SECTOR_BUFFER(ReqSector), ReqData ); |
| 728 | if (++ReqCnt < CURRENT->current_nr_sectors) { | 732 | if (++ReqCnt < blk_rq_cur_sectors(fd_request)) { |
| 729 | /* read next sector */ | 733 | /* read next sector */ |
| 730 | setup_req_params( drive ); | 734 | setup_req_params( drive ); |
| 731 | goto repeat; | 735 | goto repeat; |
| 732 | } | 736 | } |
| 733 | else { | 737 | else { |
| 734 | /* all sectors finished */ | 738 | /* all sectors finished */ |
| 735 | CURRENT->nr_sectors -= CURRENT->current_nr_sectors; | 739 | fd_end_request_cur(0); |
| 736 | CURRENT->sector += CURRENT->current_nr_sectors; | ||
| 737 | end_request(CURRENT, 1); | ||
| 738 | redo_fd_request(); | 740 | redo_fd_request(); |
| 739 | return; | 741 | return; |
| 740 | } | 742 | } |
| @@ -1132,16 +1134,14 @@ static void fd_rwsec_done1(int status) | |||
| 1132 | } | 1134 | } |
| 1133 | } | 1135 | } |
| 1134 | 1136 | ||
| 1135 | if (++ReqCnt < CURRENT->current_nr_sectors) { | 1137 | if (++ReqCnt < blk_rq_cur_sectors(fd_request)) { |
| 1136 | /* read next sector */ | 1138 | /* read next sector */ |
| 1137 | setup_req_params( SelectedDrive ); | 1139 | setup_req_params( SelectedDrive ); |
| 1138 | do_fd_action( SelectedDrive ); | 1140 | do_fd_action( SelectedDrive ); |
| 1139 | } | 1141 | } |
| 1140 | else { | 1142 | else { |
| 1141 | /* all sectors finished */ | 1143 | /* all sectors finished */ |
| 1142 | CURRENT->nr_sectors -= CURRENT->current_nr_sectors; | 1144 | fd_end_request_cur(0); |
| 1143 | CURRENT->sector += CURRENT->current_nr_sectors; | ||
| 1144 | end_request(CURRENT, 1); | ||
| 1145 | redo_fd_request(); | 1145 | redo_fd_request(); |
| 1146 | } | 1146 | } |
| 1147 | return; | 1147 | return; |
| @@ -1382,7 +1382,7 @@ static void setup_req_params( int drive ) | |||
| 1382 | ReqData = ReqBuffer + 512 * ReqCnt; | 1382 | ReqData = ReqBuffer + 512 * ReqCnt; |
| 1383 | 1383 | ||
| 1384 | if (UseTrackbuffer) | 1384 | if (UseTrackbuffer) |
| 1385 | read_track = (ReqCmd == READ && CURRENT->errors == 0); | 1385 | read_track = (ReqCmd == READ && fd_request->errors == 0); |
| 1386 | else | 1386 | else |
| 1387 | read_track = 0; | 1387 | read_track = 0; |
| 1388 | 1388 | ||
| @@ -1396,25 +1396,27 @@ static void redo_fd_request(void) | |||
| 1396 | int drive, type; | 1396 | int drive, type; |
| 1397 | struct atari_floppy_struct *floppy; | 1397 | struct atari_floppy_struct *floppy; |
| 1398 | 1398 | ||
| 1399 | DPRINT(("redo_fd_request: CURRENT=%p dev=%s CURRENT->sector=%ld\n", | 1399 | DPRINT(("redo_fd_request: fd_request=%p dev=%s fd_request->sector=%ld\n", |
| 1400 | CURRENT, CURRENT ? CURRENT->rq_disk->disk_name : "", | 1400 | fd_request, fd_request ? fd_request->rq_disk->disk_name : "", |
| 1401 | CURRENT ? CURRENT->sector : 0 )); | 1401 | fd_request ? blk_rq_pos(fd_request) : 0 )); |
| 1402 | 1402 | ||
| 1403 | IsFormatting = 0; | 1403 | IsFormatting = 0; |
| 1404 | 1404 | ||
| 1405 | repeat: | 1405 | repeat: |
| 1406 | if (!fd_request) { | ||
| 1407 | fd_request = blk_fetch_request(floppy_queue); | ||
| 1408 | if (!fd_request) | ||
| 1409 | goto the_end; | ||
| 1410 | } | ||
| 1406 | 1411 | ||
| 1407 | if (!CURRENT) | 1412 | floppy = fd_request->rq_disk->private_data; |
| 1408 | goto the_end; | ||
| 1409 | |||
| 1410 | floppy = CURRENT->rq_disk->private_data; | ||
| 1411 | drive = floppy - unit; | 1413 | drive = floppy - unit; |
| 1412 | type = floppy->type; | 1414 | type = floppy->type; |
| 1413 | 1415 | ||
| 1414 | if (!UD.connected) { | 1416 | if (!UD.connected) { |
| 1415 | /* drive not connected */ | 1417 | /* drive not connected */ |
| 1416 | printk(KERN_ERR "Unknown Device: fd%d\n", drive ); | 1418 | printk(KERN_ERR "Unknown Device: fd%d\n", drive ); |
| 1417 | end_request(CURRENT, 0); | 1419 | fd_end_request_cur(-EIO); |
| 1418 | goto repeat; | 1420 | goto repeat; |
| 1419 | } | 1421 | } |
| 1420 | 1422 | ||
| @@ -1430,12 +1432,12 @@ repeat: | |||
| 1430 | /* user supplied disk type */ | 1432 | /* user supplied disk type */ |
| 1431 | if (--type >= NUM_DISK_MINORS) { | 1433 | if (--type >= NUM_DISK_MINORS) { |
| 1432 | printk(KERN_WARNING "fd%d: invalid disk format", drive ); | 1434 | printk(KERN_WARNING "fd%d: invalid disk format", drive ); |
| 1433 | end_request(CURRENT, 0); | 1435 | fd_end_request_cur(-EIO); |
| 1434 | goto repeat; | 1436 | goto repeat; |
| 1435 | } | 1437 | } |
| 1436 | if (minor2disktype[type].drive_types > DriveType) { | 1438 | if (minor2disktype[type].drive_types > DriveType) { |
| 1437 | printk(KERN_WARNING "fd%d: unsupported disk format", drive ); | 1439 | printk(KERN_WARNING "fd%d: unsupported disk format", drive ); |
| 1438 | end_request(CURRENT, 0); | 1440 | fd_end_request_cur(-EIO); |
| 1439 | goto repeat; | 1441 | goto repeat; |
| 1440 | } | 1442 | } |
| 1441 | type = minor2disktype[type].index; | 1443 | type = minor2disktype[type].index; |
| @@ -1444,8 +1446,8 @@ repeat: | |||
| 1444 | UD.autoprobe = 0; | 1446 | UD.autoprobe = 0; |
| 1445 | } | 1447 | } |
| 1446 | 1448 | ||
| 1447 | if (CURRENT->sector + 1 > UDT->blocks) { | 1449 | if (blk_rq_pos(fd_request) + 1 > UDT->blocks) { |
| 1448 | end_request(CURRENT, 0); | 1450 | fd_end_request_cur(-EIO); |
| 1449 | goto repeat; | 1451 | goto repeat; |
| 1450 | } | 1452 | } |
| 1451 | 1453 | ||
| @@ -1453,9 +1455,9 @@ repeat: | |||
| 1453 | del_timer( &motor_off_timer ); | 1455 | del_timer( &motor_off_timer ); |
| 1454 | 1456 | ||
| 1455 | ReqCnt = 0; | 1457 | ReqCnt = 0; |
| 1456 | ReqCmd = rq_data_dir(CURRENT); | 1458 | ReqCmd = rq_data_dir(fd_request); |
| 1457 | ReqBlock = CURRENT->sector; | 1459 | ReqBlock = blk_rq_pos(fd_request); |
| 1458 | ReqBuffer = CURRENT->buffer; | 1460 | ReqBuffer = fd_request->buffer; |
| 1459 | setup_req_params( drive ); | 1461 | setup_req_params( drive ); |
| 1460 | do_fd_action( drive ); | 1462 | do_fd_action( drive ); |
| 1461 | 1463 | ||
diff --git a/drivers/block/brd.c b/drivers/block/brd.c index 5f7e64ba87e5..4bf8705b3ace 100644 --- a/drivers/block/brd.c +++ b/drivers/block/brd.c | |||
| @@ -407,12 +407,7 @@ static int __init ramdisk_size(char *str) | |||
| 407 | rd_size = simple_strtol(str, NULL, 0); | 407 | rd_size = simple_strtol(str, NULL, 0); |
| 408 | return 1; | 408 | return 1; |
| 409 | } | 409 | } |
| 410 | static int __init ramdisk_size2(char *str) | 410 | __setup("ramdisk_size=", ramdisk_size); |
| 411 | { | ||
| 412 | return ramdisk_size(str); | ||
| 413 | } | ||
| 414 | __setup("ramdisk=", ramdisk_size); | ||
| 415 | __setup("ramdisk_size=", ramdisk_size2); | ||
| 416 | #endif | 411 | #endif |
| 417 | 412 | ||
| 418 | /* | 413 | /* |
diff --git a/drivers/block/cciss.c b/drivers/block/cciss.c index 4d4d5e0d3fa6..b22cec97ea19 100644 --- a/drivers/block/cciss.c +++ b/drivers/block/cciss.c | |||
| @@ -180,11 +180,13 @@ static void __devinit cciss_interrupt_mode(ctlr_info_t *, struct pci_dev *, | |||
| 180 | __u32); | 180 | __u32); |
| 181 | static void start_io(ctlr_info_t *h); | 181 | static void start_io(ctlr_info_t *h); |
| 182 | static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, | 182 | static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, |
| 183 | unsigned int use_unit_num, unsigned int log_unit, | ||
| 184 | __u8 page_code, unsigned char *scsi3addr, int cmd_type); | 183 | __u8 page_code, unsigned char *scsi3addr, int cmd_type); |
| 185 | static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, | 184 | static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, |
| 186 | unsigned int use_unit_num, unsigned int log_unit, | 185 | __u8 page_code, unsigned char scsi3addr[], |
| 187 | __u8 page_code, int cmd_type); | 186 | int cmd_type); |
| 187 | static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c, | ||
| 188 | int attempt_retry); | ||
| 189 | static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c); | ||
| 188 | 190 | ||
| 189 | static void fail_all_cmds(unsigned long ctlr); | 191 | static void fail_all_cmds(unsigned long ctlr); |
| 190 | static int scan_thread(void *data); | 192 | static int scan_thread(void *data); |
| @@ -437,6 +439,194 @@ static void __devinit cciss_procinit(int i) | |||
| 437 | } | 439 | } |
| 438 | #endif /* CONFIG_PROC_FS */ | 440 | #endif /* CONFIG_PROC_FS */ |
| 439 | 441 | ||
| 442 | #define MAX_PRODUCT_NAME_LEN 19 | ||
| 443 | |||
| 444 | #define to_hba(n) container_of(n, struct ctlr_info, dev) | ||
| 445 | #define to_drv(n) container_of(n, drive_info_struct, dev) | ||
| 446 | |||
| 447 | static struct device_type cciss_host_type = { | ||
| 448 | .name = "cciss_host", | ||
| 449 | }; | ||
| 450 | |||
| 451 | static ssize_t dev_show_unique_id(struct device *dev, | ||
| 452 | struct device_attribute *attr, | ||
| 453 | char *buf) | ||
| 454 | { | ||
| 455 | drive_info_struct *drv = to_drv(dev); | ||
| 456 | struct ctlr_info *h = to_hba(drv->dev.parent); | ||
| 457 | __u8 sn[16]; | ||
| 458 | unsigned long flags; | ||
| 459 | int ret = 0; | ||
| 460 | |||
| 461 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
| 462 | if (h->busy_configuring) | ||
| 463 | ret = -EBUSY; | ||
| 464 | else | ||
| 465 | memcpy(sn, drv->serial_no, sizeof(sn)); | ||
| 466 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 467 | |||
| 468 | if (ret) | ||
| 469 | return ret; | ||
| 470 | else | ||
| 471 | return snprintf(buf, 16 * 2 + 2, | ||
| 472 | "%02X%02X%02X%02X%02X%02X%02X%02X" | ||
| 473 | "%02X%02X%02X%02X%02X%02X%02X%02X\n", | ||
| 474 | sn[0], sn[1], sn[2], sn[3], | ||
| 475 | sn[4], sn[5], sn[6], sn[7], | ||
| 476 | sn[8], sn[9], sn[10], sn[11], | ||
| 477 | sn[12], sn[13], sn[14], sn[15]); | ||
| 478 | } | ||
| 479 | DEVICE_ATTR(unique_id, S_IRUGO, dev_show_unique_id, NULL); | ||
| 480 | |||
| 481 | static ssize_t dev_show_vendor(struct device *dev, | ||
| 482 | struct device_attribute *attr, | ||
| 483 | char *buf) | ||
| 484 | { | ||
| 485 | drive_info_struct *drv = to_drv(dev); | ||
| 486 | struct ctlr_info *h = to_hba(drv->dev.parent); | ||
| 487 | char vendor[VENDOR_LEN + 1]; | ||
| 488 | unsigned long flags; | ||
| 489 | int ret = 0; | ||
| 490 | |||
| 491 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
| 492 | if (h->busy_configuring) | ||
| 493 | ret = -EBUSY; | ||
| 494 | else | ||
| 495 | memcpy(vendor, drv->vendor, VENDOR_LEN + 1); | ||
| 496 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 497 | |||
| 498 | if (ret) | ||
| 499 | return ret; | ||
| 500 | else | ||
| 501 | return snprintf(buf, sizeof(vendor) + 1, "%s\n", drv->vendor); | ||
| 502 | } | ||
| 503 | DEVICE_ATTR(vendor, S_IRUGO, dev_show_vendor, NULL); | ||
| 504 | |||
| 505 | static ssize_t dev_show_model(struct device *dev, | ||
| 506 | struct device_attribute *attr, | ||
| 507 | char *buf) | ||
| 508 | { | ||
| 509 | drive_info_struct *drv = to_drv(dev); | ||
| 510 | struct ctlr_info *h = to_hba(drv->dev.parent); | ||
| 511 | char model[MODEL_LEN + 1]; | ||
| 512 | unsigned long flags; | ||
| 513 | int ret = 0; | ||
| 514 | |||
| 515 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
| 516 | if (h->busy_configuring) | ||
| 517 | ret = -EBUSY; | ||
| 518 | else | ||
| 519 | memcpy(model, drv->model, MODEL_LEN + 1); | ||
| 520 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 521 | |||
| 522 | if (ret) | ||
| 523 | return ret; | ||
| 524 | else | ||
| 525 | return snprintf(buf, sizeof(model) + 1, "%s\n", drv->model); | ||
| 526 | } | ||
| 527 | DEVICE_ATTR(model, S_IRUGO, dev_show_model, NULL); | ||
| 528 | |||
| 529 | static ssize_t dev_show_rev(struct device *dev, | ||
| 530 | struct device_attribute *attr, | ||
| 531 | char *buf) | ||
| 532 | { | ||
| 533 | drive_info_struct *drv = to_drv(dev); | ||
| 534 | struct ctlr_info *h = to_hba(drv->dev.parent); | ||
| 535 | char rev[REV_LEN + 1]; | ||
| 536 | unsigned long flags; | ||
| 537 | int ret = 0; | ||
| 538 | |||
| 539 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); | ||
| 540 | if (h->busy_configuring) | ||
| 541 | ret = -EBUSY; | ||
| 542 | else | ||
| 543 | memcpy(rev, drv->rev, REV_LEN + 1); | ||
| 544 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | ||
| 545 | |||
| 546 | if (ret) | ||
| 547 | return ret; | ||
| 548 | else | ||
| 549 | return snprintf(buf, sizeof(rev) + 1, "%s\n", drv->rev); | ||
| 550 | } | ||
| 551 | DEVICE_ATTR(rev, S_IRUGO, dev_show_rev, NULL); | ||
| 552 | |||
| 553 | static struct attribute *cciss_dev_attrs[] = { | ||
| 554 | &dev_attr_unique_id.attr, | ||
| 555 | &dev_attr_model.attr, | ||
| 556 | &dev_attr_vendor.attr, | ||
| 557 | &dev_attr_rev.attr, | ||
| 558 | NULL | ||
| 559 | }; | ||
| 560 | |||
| 561 | static struct attribute_group cciss_dev_attr_group = { | ||
| 562 | .attrs = cciss_dev_attrs, | ||
| 563 | }; | ||
| 564 | |||
| 565 | static struct attribute_group *cciss_dev_attr_groups[] = { | ||
| 566 | &cciss_dev_attr_group, | ||
| 567 | NULL | ||
| 568 | }; | ||
| 569 | |||
| 570 | static struct device_type cciss_dev_type = { | ||
| 571 | .name = "cciss_device", | ||
| 572 | .groups = cciss_dev_attr_groups, | ||
| 573 | }; | ||
| 574 | |||
| 575 | static struct bus_type cciss_bus_type = { | ||
| 576 | .name = "cciss", | ||
| 577 | }; | ||
| 578 | |||
| 579 | |||
| 580 | /* | ||
| 581 | * Initialize sysfs entry for each controller. This sets up and registers | ||
| 582 | * the 'cciss#' directory for each individual controller under | ||
| 583 | * /sys/bus/pci/devices/<dev>/. | ||
| 584 | */ | ||
| 585 | static int cciss_create_hba_sysfs_entry(struct ctlr_info *h) | ||
| 586 | { | ||
| 587 | device_initialize(&h->dev); | ||
| 588 | h->dev.type = &cciss_host_type; | ||
| 589 | h->dev.bus = &cciss_bus_type; | ||
| 590 | dev_set_name(&h->dev, "%s", h->devname); | ||
| 591 | h->dev.parent = &h->pdev->dev; | ||
| 592 | |||
| 593 | return device_add(&h->dev); | ||
| 594 | } | ||
| 595 | |||
| 596 | /* | ||
| 597 | * Remove sysfs entries for an hba. | ||
| 598 | */ | ||
| 599 | static void cciss_destroy_hba_sysfs_entry(struct ctlr_info *h) | ||
| 600 | { | ||
| 601 | device_del(&h->dev); | ||
| 602 | } | ||
| 603 | |||
| 604 | /* | ||
| 605 | * Initialize sysfs for each logical drive. This sets up and registers | ||
| 606 | * the 'c#d#' directory for each individual logical drive under | ||
| 607 | * /sys/bus/pci/devices/<dev/ccis#/. We also create a link from | ||
| 608 | * /sys/block/cciss!c#d# to this entry. | ||
| 609 | */ | ||
| 610 | static int cciss_create_ld_sysfs_entry(struct ctlr_info *h, | ||
| 611 | drive_info_struct *drv, | ||
| 612 | int drv_index) | ||
| 613 | { | ||
| 614 | device_initialize(&drv->dev); | ||
| 615 | drv->dev.type = &cciss_dev_type; | ||
| 616 | drv->dev.bus = &cciss_bus_type; | ||
| 617 | dev_set_name(&drv->dev, "c%dd%d", h->ctlr, drv_index); | ||
| 618 | drv->dev.parent = &h->dev; | ||
| 619 | return device_add(&drv->dev); | ||
| 620 | } | ||
| 621 | |||
| 622 | /* | ||
| 623 | * Remove sysfs entries for a logical drive. | ||
| 624 | */ | ||
| 625 | static void cciss_destroy_ld_sysfs_entry(drive_info_struct *drv) | ||
| 626 | { | ||
| 627 | device_del(&drv->dev); | ||
| 628 | } | ||
| 629 | |||
| 440 | /* | 630 | /* |
| 441 | * For operations that cannot sleep, a command block is allocated at init, | 631 | * For operations that cannot sleep, a command block is allocated at init, |
| 442 | * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track | 632 | * and managed by cmd_alloc() and cmd_free() using a simple bitmap to track |
| @@ -1299,7 +1489,6 @@ static void cciss_softirq_done(struct request *rq) | |||
| 1299 | { | 1489 | { |
| 1300 | CommandList_struct *cmd = rq->completion_data; | 1490 | CommandList_struct *cmd = rq->completion_data; |
| 1301 | ctlr_info_t *h = hba[cmd->ctlr]; | 1491 | ctlr_info_t *h = hba[cmd->ctlr]; |
| 1302 | unsigned int nr_bytes; | ||
| 1303 | unsigned long flags; | 1492 | unsigned long flags; |
| 1304 | u64bit temp64; | 1493 | u64bit temp64; |
| 1305 | int i, ddir; | 1494 | int i, ddir; |
| @@ -1321,15 +1510,11 @@ static void cciss_softirq_done(struct request *rq) | |||
| 1321 | printk("Done with %p\n", rq); | 1510 | printk("Done with %p\n", rq); |
| 1322 | #endif /* CCISS_DEBUG */ | 1511 | #endif /* CCISS_DEBUG */ |
| 1323 | 1512 | ||
| 1324 | /* | 1513 | /* set the residual count for pc requests */ |
| 1325 | * Store the full size and set the residual count for pc requests | ||
| 1326 | */ | ||
| 1327 | nr_bytes = blk_rq_bytes(rq); | ||
| 1328 | if (blk_pc_request(rq)) | 1514 | if (blk_pc_request(rq)) |
| 1329 | rq->data_len = cmd->err_info->ResidualCnt; | 1515 | rq->resid_len = cmd->err_info->ResidualCnt; |
| 1330 | 1516 | ||
| 1331 | if (blk_end_request(rq, (rq->errors == 0) ? 0 : -EIO, nr_bytes)) | 1517 | blk_end_request_all(rq, (rq->errors == 0) ? 0 : -EIO); |
| 1332 | BUG(); | ||
| 1333 | 1518 | ||
| 1334 | spin_lock_irqsave(&h->lock, flags); | 1519 | spin_lock_irqsave(&h->lock, flags); |
| 1335 | cmd_free(h, cmd, 1); | 1520 | cmd_free(h, cmd, 1); |
| @@ -1337,6 +1522,56 @@ static void cciss_softirq_done(struct request *rq) | |||
| 1337 | spin_unlock_irqrestore(&h->lock, flags); | 1522 | spin_unlock_irqrestore(&h->lock, flags); |
| 1338 | } | 1523 | } |
| 1339 | 1524 | ||
| 1525 | static void log_unit_to_scsi3addr(ctlr_info_t *h, unsigned char scsi3addr[], | ||
| 1526 | uint32_t log_unit) | ||
| 1527 | { | ||
| 1528 | log_unit = h->drv[log_unit].LunID & 0x03fff; | ||
| 1529 | memset(&scsi3addr[4], 0, 4); | ||
| 1530 | memcpy(&scsi3addr[0], &log_unit, 4); | ||
| 1531 | scsi3addr[3] |= 0x40; | ||
| 1532 | } | ||
| 1533 | |||
| 1534 | /* This function gets the SCSI vendor, model, and revision of a logical drive | ||
| 1535 | * via the inquiry page 0. Model, vendor, and rev are set to empty strings if | ||
| 1536 | * they cannot be read. | ||
| 1537 | */ | ||
| 1538 | static void cciss_get_device_descr(int ctlr, int logvol, int withirq, | ||
| 1539 | char *vendor, char *model, char *rev) | ||
| 1540 | { | ||
| 1541 | int rc; | ||
| 1542 | InquiryData_struct *inq_buf; | ||
| 1543 | unsigned char scsi3addr[8]; | ||
| 1544 | |||
| 1545 | *vendor = '\0'; | ||
| 1546 | *model = '\0'; | ||
| 1547 | *rev = '\0'; | ||
| 1548 | |||
| 1549 | inq_buf = kzalloc(sizeof(InquiryData_struct), GFP_KERNEL); | ||
| 1550 | if (!inq_buf) | ||
| 1551 | return; | ||
| 1552 | |||
| 1553 | log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol); | ||
| 1554 | if (withirq) | ||
| 1555 | rc = sendcmd_withirq(CISS_INQUIRY, ctlr, inq_buf, | ||
| 1556 | sizeof(InquiryData_struct), 0, | ||
| 1557 | scsi3addr, TYPE_CMD); | ||
| 1558 | else | ||
| 1559 | rc = sendcmd(CISS_INQUIRY, ctlr, inq_buf, | ||
| 1560 | sizeof(InquiryData_struct), 0, | ||
| 1561 | scsi3addr, TYPE_CMD); | ||
| 1562 | if (rc == IO_OK) { | ||
| 1563 | memcpy(vendor, &inq_buf->data_byte[8], VENDOR_LEN); | ||
| 1564 | vendor[VENDOR_LEN] = '\0'; | ||
| 1565 | memcpy(model, &inq_buf->data_byte[16], MODEL_LEN); | ||
| 1566 | model[MODEL_LEN] = '\0'; | ||
| 1567 | memcpy(rev, &inq_buf->data_byte[32], REV_LEN); | ||
| 1568 | rev[REV_LEN] = '\0'; | ||
| 1569 | } | ||
| 1570 | |||
| 1571 | kfree(inq_buf); | ||
| 1572 | return; | ||
| 1573 | } | ||
| 1574 | |||
| 1340 | /* This function gets the serial number of a logical drive via | 1575 | /* This function gets the serial number of a logical drive via |
| 1341 | * inquiry page 0x83. Serial no. is 16 bytes. If the serial | 1576 | * inquiry page 0x83. Serial no. is 16 bytes. If the serial |
| 1342 | * number cannot be had, for whatever reason, 16 bytes of 0xff | 1577 | * number cannot be had, for whatever reason, 16 bytes of 0xff |
| @@ -1348,6 +1583,7 @@ static void cciss_get_serial_no(int ctlr, int logvol, int withirq, | |||
| 1348 | #define PAGE_83_INQ_BYTES 64 | 1583 | #define PAGE_83_INQ_BYTES 64 |
| 1349 | int rc; | 1584 | int rc; |
| 1350 | unsigned char *buf; | 1585 | unsigned char *buf; |
| 1586 | unsigned char scsi3addr[8]; | ||
| 1351 | 1587 | ||
| 1352 | if (buflen > 16) | 1588 | if (buflen > 16) |
| 1353 | buflen = 16; | 1589 | buflen = 16; |
| @@ -1356,12 +1592,13 @@ static void cciss_get_serial_no(int ctlr, int logvol, int withirq, | |||
| 1356 | if (!buf) | 1592 | if (!buf) |
| 1357 | return; | 1593 | return; |
| 1358 | memset(serial_no, 0, buflen); | 1594 | memset(serial_no, 0, buflen); |
| 1595 | log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol); | ||
| 1359 | if (withirq) | 1596 | if (withirq) |
| 1360 | rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf, | 1597 | rc = sendcmd_withirq(CISS_INQUIRY, ctlr, buf, |
| 1361 | PAGE_83_INQ_BYTES, 1, logvol, 0x83, TYPE_CMD); | 1598 | PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD); |
| 1362 | else | 1599 | else |
| 1363 | rc = sendcmd(CISS_INQUIRY, ctlr, buf, | 1600 | rc = sendcmd(CISS_INQUIRY, ctlr, buf, |
| 1364 | PAGE_83_INQ_BYTES, 1, logvol, 0x83, NULL, TYPE_CMD); | 1601 | PAGE_83_INQ_BYTES, 0x83, scsi3addr, TYPE_CMD); |
| 1365 | if (rc == IO_OK) | 1602 | if (rc == IO_OK) |
| 1366 | memcpy(serial_no, &buf[8], buflen); | 1603 | memcpy(serial_no, &buf[8], buflen); |
| 1367 | kfree(buf); | 1604 | kfree(buf); |
| @@ -1377,7 +1614,7 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
| 1377 | disk->first_minor = drv_index << NWD_SHIFT; | 1614 | disk->first_minor = drv_index << NWD_SHIFT; |
| 1378 | disk->fops = &cciss_fops; | 1615 | disk->fops = &cciss_fops; |
| 1379 | disk->private_data = &h->drv[drv_index]; | 1616 | disk->private_data = &h->drv[drv_index]; |
| 1380 | disk->driverfs_dev = &h->pdev->dev; | 1617 | disk->driverfs_dev = &h->drv[drv_index].dev; |
| 1381 | 1618 | ||
| 1382 | /* Set up queue information */ | 1619 | /* Set up queue information */ |
| 1383 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); | 1620 | blk_queue_bounce_limit(disk->queue, h->pdev->dma_mask); |
| @@ -1394,8 +1631,8 @@ static void cciss_add_disk(ctlr_info_t *h, struct gendisk *disk, | |||
| 1394 | 1631 | ||
| 1395 | disk->queue->queuedata = h; | 1632 | disk->queue->queuedata = h; |
| 1396 | 1633 | ||
| 1397 | blk_queue_hardsect_size(disk->queue, | 1634 | blk_queue_logical_block_size(disk->queue, |
| 1398 | h->drv[drv_index].block_size); | 1635 | h->drv[drv_index].block_size); |
| 1399 | 1636 | ||
| 1400 | /* Make sure all queue data is written out before */ | 1637 | /* Make sure all queue data is written out before */ |
| 1401 | /* setting h->drv[drv_index].queue, as setting this */ | 1638 | /* setting h->drv[drv_index].queue, as setting this */ |
| @@ -1468,6 +1705,8 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
| 1468 | drvinfo->block_size = block_size; | 1705 | drvinfo->block_size = block_size; |
| 1469 | drvinfo->nr_blocks = total_size + 1; | 1706 | drvinfo->nr_blocks = total_size + 1; |
| 1470 | 1707 | ||
| 1708 | cciss_get_device_descr(ctlr, drv_index, 1, drvinfo->vendor, | ||
| 1709 | drvinfo->model, drvinfo->rev); | ||
| 1471 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, | 1710 | cciss_get_serial_no(ctlr, drv_index, 1, drvinfo->serial_no, |
| 1472 | sizeof(drvinfo->serial_no)); | 1711 | sizeof(drvinfo->serial_no)); |
| 1473 | 1712 | ||
| @@ -1517,6 +1756,9 @@ static void cciss_update_drive_info(int ctlr, int drv_index, int first_time) | |||
| 1517 | h->drv[drv_index].cylinders = drvinfo->cylinders; | 1756 | h->drv[drv_index].cylinders = drvinfo->cylinders; |
| 1518 | h->drv[drv_index].raid_level = drvinfo->raid_level; | 1757 | h->drv[drv_index].raid_level = drvinfo->raid_level; |
| 1519 | memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16); | 1758 | memcpy(h->drv[drv_index].serial_no, drvinfo->serial_no, 16); |
| 1759 | memcpy(h->drv[drv_index].vendor, drvinfo->vendor, VENDOR_LEN + 1); | ||
| 1760 | memcpy(h->drv[drv_index].model, drvinfo->model, MODEL_LEN + 1); | ||
| 1761 | memcpy(h->drv[drv_index].rev, drvinfo->rev, REV_LEN + 1); | ||
| 1520 | 1762 | ||
| 1521 | ++h->num_luns; | 1763 | ++h->num_luns; |
| 1522 | disk = h->gendisk[drv_index]; | 1764 | disk = h->gendisk[drv_index]; |
| @@ -1591,6 +1833,8 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node) | |||
| 1591 | } | 1833 | } |
| 1592 | } | 1834 | } |
| 1593 | h->drv[drv_index].LunID = lunid; | 1835 | h->drv[drv_index].LunID = lunid; |
| 1836 | if (cciss_create_ld_sysfs_entry(h, &h->drv[drv_index], drv_index)) | ||
| 1837 | goto err_free_disk; | ||
| 1594 | 1838 | ||
| 1595 | /* Don't need to mark this busy because nobody */ | 1839 | /* Don't need to mark this busy because nobody */ |
| 1596 | /* else knows about this disk yet to contend */ | 1840 | /* else knows about this disk yet to contend */ |
| @@ -1598,6 +1842,11 @@ static int cciss_add_gendisk(ctlr_info_t *h, __u32 lunid, int controller_node) | |||
| 1598 | h->drv[drv_index].busy_configuring = 0; | 1842 | h->drv[drv_index].busy_configuring = 0; |
| 1599 | wmb(); | 1843 | wmb(); |
| 1600 | return drv_index; | 1844 | return drv_index; |
| 1845 | |||
| 1846 | err_free_disk: | ||
| 1847 | put_disk(h->gendisk[drv_index]); | ||
| 1848 | h->gendisk[drv_index] = NULL; | ||
| 1849 | return -1; | ||
| 1601 | } | 1850 | } |
| 1602 | 1851 | ||
| 1603 | /* This is for the special case of a controller which | 1852 | /* This is for the special case of a controller which |
| @@ -1668,8 +1917,8 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
| 1668 | goto mem_msg; | 1917 | goto mem_msg; |
| 1669 | 1918 | ||
| 1670 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, | 1919 | return_code = sendcmd_withirq(CISS_REPORT_LOG, ctlr, ld_buff, |
| 1671 | sizeof(ReportLunData_struct), 0, | 1920 | sizeof(ReportLunData_struct), |
| 1672 | 0, 0, TYPE_CMD); | 1921 | 0, CTLR_LUNID, TYPE_CMD); |
| 1673 | 1922 | ||
| 1674 | if (return_code == IO_OK) | 1923 | if (return_code == IO_OK) |
| 1675 | listlength = be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); | 1924 | listlength = be32_to_cpu(*(__be32 *) ld_buff->LUNListLength); |
| @@ -1718,6 +1967,7 @@ static int rebuild_lun_table(ctlr_info_t *h, int first_time) | |||
| 1718 | h->drv[i].busy_configuring = 1; | 1967 | h->drv[i].busy_configuring = 1; |
| 1719 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); | 1968 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
| 1720 | return_code = deregister_disk(h, i, 1); | 1969 | return_code = deregister_disk(h, i, 1); |
| 1970 | cciss_destroy_ld_sysfs_entry(&h->drv[i]); | ||
| 1721 | h->drv[i].busy_configuring = 0; | 1971 | h->drv[i].busy_configuring = 0; |
| 1722 | } | 1972 | } |
| 1723 | } | 1973 | } |
| @@ -1877,11 +2127,9 @@ static int deregister_disk(ctlr_info_t *h, int drv_index, | |||
| 1877 | return 0; | 2127 | return 0; |
| 1878 | } | 2128 | } |
| 1879 | 2129 | ||
| 1880 | static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller, | 2130 | static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, |
| 1881 | 1: address logical volume log_unit, | 2131 | size_t size, __u8 page_code, unsigned char *scsi3addr, |
| 1882 | 2: periph device address is scsi3addr */ | 2132 | int cmd_type) |
| 1883 | unsigned int log_unit, __u8 page_code, | ||
| 1884 | unsigned char *scsi3addr, int cmd_type) | ||
| 1885 | { | 2133 | { |
| 1886 | ctlr_info_t *h = hba[ctlr]; | 2134 | ctlr_info_t *h = hba[ctlr]; |
| 1887 | u64bit buff_dma_handle; | 2135 | u64bit buff_dma_handle; |
| @@ -1897,27 +2145,12 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
| 1897 | c->Header.SGTotal = 0; | 2145 | c->Header.SGTotal = 0; |
| 1898 | } | 2146 | } |
| 1899 | c->Header.Tag.lower = c->busaddr; | 2147 | c->Header.Tag.lower = c->busaddr; |
| 2148 | memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, 8); | ||
| 1900 | 2149 | ||
| 1901 | c->Request.Type.Type = cmd_type; | 2150 | c->Request.Type.Type = cmd_type; |
| 1902 | if (cmd_type == TYPE_CMD) { | 2151 | if (cmd_type == TYPE_CMD) { |
| 1903 | switch (cmd) { | 2152 | switch (cmd) { |
| 1904 | case CISS_INQUIRY: | 2153 | case CISS_INQUIRY: |
| 1905 | /* If the logical unit number is 0 then, this is going | ||
| 1906 | to controller so It's a physical command | ||
| 1907 | mode = 0 target = 0. So we have nothing to write. | ||
| 1908 | otherwise, if use_unit_num == 1, | ||
| 1909 | mode = 1(volume set addressing) target = LUNID | ||
| 1910 | otherwise, if use_unit_num == 2, | ||
| 1911 | mode = 0(periph dev addr) target = scsi3addr */ | ||
| 1912 | if (use_unit_num == 1) { | ||
| 1913 | c->Header.LUN.LogDev.VolId = | ||
| 1914 | h->drv[log_unit].LunID; | ||
| 1915 | c->Header.LUN.LogDev.Mode = 1; | ||
| 1916 | } else if (use_unit_num == 2) { | ||
| 1917 | memcpy(c->Header.LUN.LunAddrBytes, scsi3addr, | ||
| 1918 | 8); | ||
| 1919 | c->Header.LUN.LogDev.Mode = 0; | ||
| 1920 | } | ||
| 1921 | /* are we trying to read a vital product page */ | 2154 | /* are we trying to read a vital product page */ |
| 1922 | if (page_code != 0) { | 2155 | if (page_code != 0) { |
| 1923 | c->Request.CDB[1] = 0x01; | 2156 | c->Request.CDB[1] = 0x01; |
| @@ -1947,8 +2180,6 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
| 1947 | break; | 2180 | break; |
| 1948 | 2181 | ||
| 1949 | case CCISS_READ_CAPACITY: | 2182 | case CCISS_READ_CAPACITY: |
| 1950 | c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID; | ||
| 1951 | c->Header.LUN.LogDev.Mode = 1; | ||
| 1952 | c->Request.CDBLen = 10; | 2183 | c->Request.CDBLen = 10; |
| 1953 | c->Request.Type.Attribute = ATTR_SIMPLE; | 2184 | c->Request.Type.Attribute = ATTR_SIMPLE; |
| 1954 | c->Request.Type.Direction = XFER_READ; | 2185 | c->Request.Type.Direction = XFER_READ; |
| @@ -1956,8 +2187,6 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
| 1956 | c->Request.CDB[0] = cmd; | 2187 | c->Request.CDB[0] = cmd; |
| 1957 | break; | 2188 | break; |
| 1958 | case CCISS_READ_CAPACITY_16: | 2189 | case CCISS_READ_CAPACITY_16: |
| 1959 | c->Header.LUN.LogDev.VolId = h->drv[log_unit].LunID; | ||
| 1960 | c->Header.LUN.LogDev.Mode = 1; | ||
| 1961 | c->Request.CDBLen = 16; | 2190 | c->Request.CDBLen = 16; |
| 1962 | c->Request.Type.Attribute = ATTR_SIMPLE; | 2191 | c->Request.Type.Attribute = ATTR_SIMPLE; |
| 1963 | c->Request.Type.Direction = XFER_READ; | 2192 | c->Request.Type.Direction = XFER_READ; |
| @@ -1979,6 +2208,12 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
| 1979 | c->Request.CDB[0] = BMIC_WRITE; | 2208 | c->Request.CDB[0] = BMIC_WRITE; |
| 1980 | c->Request.CDB[6] = BMIC_CACHE_FLUSH; | 2209 | c->Request.CDB[6] = BMIC_CACHE_FLUSH; |
| 1981 | break; | 2210 | break; |
| 2211 | case TEST_UNIT_READY: | ||
| 2212 | c->Request.CDBLen = 6; | ||
| 2213 | c->Request.Type.Attribute = ATTR_SIMPLE; | ||
| 2214 | c->Request.Type.Direction = XFER_NONE; | ||
| 2215 | c->Request.Timeout = 0; | ||
| 2216 | break; | ||
| 1982 | default: | 2217 | default: |
| 1983 | printk(KERN_WARNING | 2218 | printk(KERN_WARNING |
| 1984 | "cciss%d: Unknown Command 0x%c\n", ctlr, cmd); | 2219 | "cciss%d: Unknown Command 0x%c\n", ctlr, cmd); |
| @@ -1997,13 +2232,13 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
| 1997 | memcpy(&c->Request.CDB[4], buff, 8); | 2232 | memcpy(&c->Request.CDB[4], buff, 8); |
| 1998 | break; | 2233 | break; |
| 1999 | case 1: /* RESET message */ | 2234 | case 1: /* RESET message */ |
| 2000 | c->Request.CDBLen = 12; | 2235 | c->Request.CDBLen = 16; |
| 2001 | c->Request.Type.Attribute = ATTR_SIMPLE; | 2236 | c->Request.Type.Attribute = ATTR_SIMPLE; |
| 2002 | c->Request.Type.Direction = XFER_WRITE; | 2237 | c->Request.Type.Direction = XFER_NONE; |
| 2003 | c->Request.Timeout = 0; | 2238 | c->Request.Timeout = 0; |
| 2004 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); | 2239 | memset(&c->Request.CDB[0], 0, sizeof(c->Request.CDB)); |
| 2005 | c->Request.CDB[0] = cmd; /* reset */ | 2240 | c->Request.CDB[0] = cmd; /* reset */ |
| 2006 | c->Request.CDB[1] = 0x04; /* reset a LUN */ | 2241 | c->Request.CDB[1] = 0x03; /* reset a target */ |
| 2007 | break; | 2242 | break; |
| 2008 | case 3: /* No-Op message */ | 2243 | case 3: /* No-Op message */ |
| 2009 | c->Request.CDBLen = 1; | 2244 | c->Request.CDBLen = 1; |
| @@ -2035,114 +2270,152 @@ static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, size_ | |||
| 2035 | return status; | 2270 | return status; |
| 2036 | } | 2271 | } |
| 2037 | 2272 | ||
| 2038 | static int sendcmd_withirq(__u8 cmd, | 2273 | static int check_target_status(ctlr_info_t *h, CommandList_struct *c) |
| 2039 | int ctlr, | ||
| 2040 | void *buff, | ||
| 2041 | size_t size, | ||
| 2042 | unsigned int use_unit_num, | ||
| 2043 | unsigned int log_unit, __u8 page_code, int cmd_type) | ||
| 2044 | { | 2274 | { |
| 2045 | ctlr_info_t *h = hba[ctlr]; | 2275 | switch (c->err_info->ScsiStatus) { |
| 2046 | CommandList_struct *c; | 2276 | case SAM_STAT_GOOD: |
| 2277 | return IO_OK; | ||
| 2278 | case SAM_STAT_CHECK_CONDITION: | ||
| 2279 | switch (0xf & c->err_info->SenseInfo[2]) { | ||
| 2280 | case 0: return IO_OK; /* no sense */ | ||
| 2281 | case 1: return IO_OK; /* recovered error */ | ||
| 2282 | default: | ||
| 2283 | printk(KERN_WARNING "cciss%d: cmd 0x%02x " | ||
| 2284 | "check condition, sense key = 0x%02x\n", | ||
| 2285 | h->ctlr, c->Request.CDB[0], | ||
| 2286 | c->err_info->SenseInfo[2]); | ||
| 2287 | } | ||
| 2288 | break; | ||
| 2289 | default: | ||
| 2290 | printk(KERN_WARNING "cciss%d: cmd 0x%02x" | ||
| 2291 | "scsi status = 0x%02x\n", h->ctlr, | ||
| 2292 | c->Request.CDB[0], c->err_info->ScsiStatus); | ||
| 2293 | break; | ||
| 2294 | } | ||
| 2295 | return IO_ERROR; | ||
| 2296 | } | ||
| 2297 | |||
| 2298 | static int process_sendcmd_error(ctlr_info_t *h, CommandList_struct *c) | ||
| 2299 | { | ||
| 2300 | int return_status = IO_OK; | ||
| 2301 | |||
| 2302 | if (c->err_info->CommandStatus == CMD_SUCCESS) | ||
| 2303 | return IO_OK; | ||
| 2304 | |||
| 2305 | switch (c->err_info->CommandStatus) { | ||
| 2306 | case CMD_TARGET_STATUS: | ||
| 2307 | return_status = check_target_status(h, c); | ||
| 2308 | break; | ||
| 2309 | case CMD_DATA_UNDERRUN: | ||
| 2310 | case CMD_DATA_OVERRUN: | ||
| 2311 | /* expected for inquiry and report lun commands */ | ||
| 2312 | break; | ||
| 2313 | case CMD_INVALID: | ||
| 2314 | printk(KERN_WARNING "cciss: cmd 0x%02x is " | ||
| 2315 | "reported invalid\n", c->Request.CDB[0]); | ||
| 2316 | return_status = IO_ERROR; | ||
| 2317 | break; | ||
| 2318 | case CMD_PROTOCOL_ERR: | ||
| 2319 | printk(KERN_WARNING "cciss: cmd 0x%02x has " | ||
| 2320 | "protocol error \n", c->Request.CDB[0]); | ||
| 2321 | return_status = IO_ERROR; | ||
| 2322 | break; | ||
| 2323 | case CMD_HARDWARE_ERR: | ||
| 2324 | printk(KERN_WARNING "cciss: cmd 0x%02x had " | ||
| 2325 | " hardware error\n", c->Request.CDB[0]); | ||
| 2326 | return_status = IO_ERROR; | ||
| 2327 | break; | ||
| 2328 | case CMD_CONNECTION_LOST: | ||
| 2329 | printk(KERN_WARNING "cciss: cmd 0x%02x had " | ||
| 2330 | "connection lost\n", c->Request.CDB[0]); | ||
| 2331 | return_status = IO_ERROR; | ||
| 2332 | break; | ||
| 2333 | case CMD_ABORTED: | ||
| 2334 | printk(KERN_WARNING "cciss: cmd 0x%02x was " | ||
| 2335 | "aborted\n", c->Request.CDB[0]); | ||
| 2336 | return_status = IO_ERROR; | ||
| 2337 | break; | ||
| 2338 | case CMD_ABORT_FAILED: | ||
| 2339 | printk(KERN_WARNING "cciss: cmd 0x%02x reports " | ||
| 2340 | "abort failed\n", c->Request.CDB[0]); | ||
| 2341 | return_status = IO_ERROR; | ||
| 2342 | break; | ||
| 2343 | case CMD_UNSOLICITED_ABORT: | ||
| 2344 | printk(KERN_WARNING | ||
| 2345 | "cciss%d: unsolicited abort 0x%02x\n", h->ctlr, | ||
| 2346 | c->Request.CDB[0]); | ||
| 2347 | return_status = IO_NEEDS_RETRY; | ||
| 2348 | break; | ||
| 2349 | default: | ||
| 2350 | printk(KERN_WARNING "cciss: cmd 0x%02x returned " | ||
| 2351 | "unknown status %x\n", c->Request.CDB[0], | ||
| 2352 | c->err_info->CommandStatus); | ||
| 2353 | return_status = IO_ERROR; | ||
| 2354 | } | ||
| 2355 | return return_status; | ||
| 2356 | } | ||
| 2357 | |||
| 2358 | static int sendcmd_withirq_core(ctlr_info_t *h, CommandList_struct *c, | ||
| 2359 | int attempt_retry) | ||
| 2360 | { | ||
| 2361 | DECLARE_COMPLETION_ONSTACK(wait); | ||
| 2047 | u64bit buff_dma_handle; | 2362 | u64bit buff_dma_handle; |
| 2048 | unsigned long flags; | 2363 | unsigned long flags; |
| 2049 | int return_status; | 2364 | int return_status = IO_OK; |
| 2050 | DECLARE_COMPLETION_ONSTACK(wait); | ||
| 2051 | 2365 | ||
| 2052 | if ((c = cmd_alloc(h, 0)) == NULL) | 2366 | resend_cmd2: |
| 2053 | return -ENOMEM; | ||
| 2054 | return_status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num, | ||
| 2055 | log_unit, page_code, NULL, cmd_type); | ||
| 2056 | if (return_status != IO_OK) { | ||
| 2057 | cmd_free(h, c, 0); | ||
| 2058 | return return_status; | ||
| 2059 | } | ||
| 2060 | resend_cmd2: | ||
| 2061 | c->waiting = &wait; | 2367 | c->waiting = &wait; |
| 2062 | |||
| 2063 | /* Put the request on the tail of the queue and send it */ | 2368 | /* Put the request on the tail of the queue and send it */ |
| 2064 | spin_lock_irqsave(CCISS_LOCK(ctlr), flags); | 2369 | spin_lock_irqsave(CCISS_LOCK(h->ctlr), flags); |
| 2065 | addQ(&h->reqQ, c); | 2370 | addQ(&h->reqQ, c); |
| 2066 | h->Qdepth++; | 2371 | h->Qdepth++; |
| 2067 | start_io(h); | 2372 | start_io(h); |
| 2068 | spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); | 2373 | spin_unlock_irqrestore(CCISS_LOCK(h->ctlr), flags); |
| 2069 | 2374 | ||
| 2070 | wait_for_completion(&wait); | 2375 | wait_for_completion(&wait); |
| 2071 | 2376 | ||
| 2072 | if (c->err_info->CommandStatus != 0) { /* an error has occurred */ | 2377 | if (c->err_info->CommandStatus == 0 || !attempt_retry) |
| 2073 | switch (c->err_info->CommandStatus) { | 2378 | goto command_done; |
| 2074 | case CMD_TARGET_STATUS: | ||
| 2075 | printk(KERN_WARNING "cciss: cmd %p has " | ||
| 2076 | " completed with errors\n", c); | ||
| 2077 | if (c->err_info->ScsiStatus) { | ||
| 2078 | printk(KERN_WARNING "cciss: cmd %p " | ||
| 2079 | "has SCSI Status = %x\n", | ||
| 2080 | c, c->err_info->ScsiStatus); | ||
| 2081 | } | ||
| 2082 | 2379 | ||
| 2083 | break; | 2380 | return_status = process_sendcmd_error(h, c); |
| 2084 | case CMD_DATA_UNDERRUN: | 2381 | |
| 2085 | case CMD_DATA_OVERRUN: | 2382 | if (return_status == IO_NEEDS_RETRY && |
| 2086 | /* expected for inquire and report lun commands */ | 2383 | c->retry_count < MAX_CMD_RETRIES) { |
| 2087 | break; | 2384 | printk(KERN_WARNING "cciss%d: retrying 0x%02x\n", h->ctlr, |
| 2088 | case CMD_INVALID: | 2385 | c->Request.CDB[0]); |
| 2089 | printk(KERN_WARNING "cciss: Cmd %p is " | 2386 | c->retry_count++; |
| 2090 | "reported invalid\n", c); | 2387 | /* erase the old error information */ |
| 2091 | return_status = IO_ERROR; | 2388 | memset(c->err_info, 0, sizeof(ErrorInfo_struct)); |
| 2092 | break; | 2389 | return_status = IO_OK; |
| 2093 | case CMD_PROTOCOL_ERR: | 2390 | INIT_COMPLETION(wait); |
| 2094 | printk(KERN_WARNING "cciss: cmd %p has " | 2391 | goto resend_cmd2; |
| 2095 | "protocol error \n", c); | ||
| 2096 | return_status = IO_ERROR; | ||
| 2097 | break; | ||
| 2098 | case CMD_HARDWARE_ERR: | ||
| 2099 | printk(KERN_WARNING "cciss: cmd %p had " | ||
| 2100 | " hardware error\n", c); | ||
| 2101 | return_status = IO_ERROR; | ||
| 2102 | break; | ||
| 2103 | case CMD_CONNECTION_LOST: | ||
| 2104 | printk(KERN_WARNING "cciss: cmd %p had " | ||
| 2105 | "connection lost\n", c); | ||
| 2106 | return_status = IO_ERROR; | ||
| 2107 | break; | ||
| 2108 | case CMD_ABORTED: | ||
| 2109 | printk(KERN_WARNING "cciss: cmd %p was " | ||
| 2110 | "aborted\n", c); | ||
| 2111 | return_status = IO_ERROR; | ||
| 2112 | break; | ||
| 2113 | case CMD_ABORT_FAILED: | ||
| 2114 | printk(KERN_WARNING "cciss: cmd %p reports " | ||
| 2115 | "abort failed\n", c); | ||
| 2116 | return_status = IO_ERROR; | ||
| 2117 | break; | ||
| 2118 | case CMD_UNSOLICITED_ABORT: | ||
| 2119 | printk(KERN_WARNING | ||
| 2120 | "cciss%d: unsolicited abort %p\n", ctlr, c); | ||
| 2121 | if (c->retry_count < MAX_CMD_RETRIES) { | ||
| 2122 | printk(KERN_WARNING | ||
| 2123 | "cciss%d: retrying %p\n", ctlr, c); | ||
| 2124 | c->retry_count++; | ||
| 2125 | /* erase the old error information */ | ||
| 2126 | memset(c->err_info, 0, | ||
| 2127 | sizeof(ErrorInfo_struct)); | ||
| 2128 | return_status = IO_OK; | ||
| 2129 | INIT_COMPLETION(wait); | ||
| 2130 | goto resend_cmd2; | ||
| 2131 | } | ||
| 2132 | return_status = IO_ERROR; | ||
| 2133 | break; | ||
| 2134 | default: | ||
| 2135 | printk(KERN_WARNING "cciss: cmd %p returned " | ||
| 2136 | "unknown status %x\n", c, | ||
| 2137 | c->err_info->CommandStatus); | ||
| 2138 | return_status = IO_ERROR; | ||
| 2139 | } | ||
| 2140 | } | 2392 | } |
| 2393 | |||
| 2394 | command_done: | ||
| 2141 | /* unlock the buffers from DMA */ | 2395 | /* unlock the buffers from DMA */ |
| 2142 | buff_dma_handle.val32.lower = c->SG[0].Addr.lower; | 2396 | buff_dma_handle.val32.lower = c->SG[0].Addr.lower; |
| 2143 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; | 2397 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; |
| 2144 | pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val, | 2398 | pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val, |
| 2145 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); | 2399 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); |
| 2400 | return return_status; | ||
| 2401 | } | ||
| 2402 | |||
| 2403 | static int sendcmd_withirq(__u8 cmd, int ctlr, void *buff, size_t size, | ||
| 2404 | __u8 page_code, unsigned char scsi3addr[], | ||
| 2405 | int cmd_type) | ||
| 2406 | { | ||
| 2407 | ctlr_info_t *h = hba[ctlr]; | ||
| 2408 | CommandList_struct *c; | ||
| 2409 | int return_status; | ||
| 2410 | |||
| 2411 | c = cmd_alloc(h, 0); | ||
| 2412 | if (!c) | ||
| 2413 | return -ENOMEM; | ||
| 2414 | return_status = fill_cmd(c, cmd, ctlr, buff, size, page_code, | ||
| 2415 | scsi3addr, cmd_type); | ||
| 2416 | if (return_status == IO_OK) | ||
| 2417 | return_status = sendcmd_withirq_core(h, c, 1); | ||
| 2418 | |||
| 2146 | cmd_free(h, c, 0); | 2419 | cmd_free(h, c, 0); |
| 2147 | return return_status; | 2420 | return return_status; |
| 2148 | } | 2421 | } |
| @@ -2155,15 +2428,17 @@ static void cciss_geometry_inquiry(int ctlr, int logvol, | |||
| 2155 | { | 2428 | { |
| 2156 | int return_code; | 2429 | int return_code; |
| 2157 | unsigned long t; | 2430 | unsigned long t; |
| 2431 | unsigned char scsi3addr[8]; | ||
| 2158 | 2432 | ||
| 2159 | memset(inq_buff, 0, sizeof(InquiryData_struct)); | 2433 | memset(inq_buff, 0, sizeof(InquiryData_struct)); |
| 2434 | log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol); | ||
| 2160 | if (withirq) | 2435 | if (withirq) |
| 2161 | return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, | 2436 | return_code = sendcmd_withirq(CISS_INQUIRY, ctlr, |
| 2162 | inq_buff, sizeof(*inq_buff), 1, | 2437 | inq_buff, sizeof(*inq_buff), |
| 2163 | logvol, 0xC1, TYPE_CMD); | 2438 | 0xC1, scsi3addr, TYPE_CMD); |
| 2164 | else | 2439 | else |
| 2165 | return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff, | 2440 | return_code = sendcmd(CISS_INQUIRY, ctlr, inq_buff, |
| 2166 | sizeof(*inq_buff), 1, logvol, 0xC1, NULL, | 2441 | sizeof(*inq_buff), 0xC1, scsi3addr, |
| 2167 | TYPE_CMD); | 2442 | TYPE_CMD); |
| 2168 | if (return_code == IO_OK) { | 2443 | if (return_code == IO_OK) { |
| 2169 | if (inq_buff->data_byte[8] == 0xFF) { | 2444 | if (inq_buff->data_byte[8] == 0xFF) { |
| @@ -2204,6 +2479,7 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, | |||
| 2204 | { | 2479 | { |
| 2205 | ReadCapdata_struct *buf; | 2480 | ReadCapdata_struct *buf; |
| 2206 | int return_code; | 2481 | int return_code; |
| 2482 | unsigned char scsi3addr[8]; | ||
| 2207 | 2483 | ||
| 2208 | buf = kzalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); | 2484 | buf = kzalloc(sizeof(ReadCapdata_struct), GFP_KERNEL); |
| 2209 | if (!buf) { | 2485 | if (!buf) { |
| @@ -2211,14 +2487,15 @@ cciss_read_capacity(int ctlr, int logvol, int withirq, sector_t *total_size, | |||
| 2211 | return; | 2487 | return; |
| 2212 | } | 2488 | } |
| 2213 | 2489 | ||
| 2490 | log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol); | ||
| 2214 | if (withirq) | 2491 | if (withirq) |
| 2215 | return_code = sendcmd_withirq(CCISS_READ_CAPACITY, | 2492 | return_code = sendcmd_withirq(CCISS_READ_CAPACITY, |
| 2216 | ctlr, buf, sizeof(ReadCapdata_struct), | 2493 | ctlr, buf, sizeof(ReadCapdata_struct), |
| 2217 | 1, logvol, 0, TYPE_CMD); | 2494 | 0, scsi3addr, TYPE_CMD); |
| 2218 | else | 2495 | else |
| 2219 | return_code = sendcmd(CCISS_READ_CAPACITY, | 2496 | return_code = sendcmd(CCISS_READ_CAPACITY, |
| 2220 | ctlr, buf, sizeof(ReadCapdata_struct), | 2497 | ctlr, buf, sizeof(ReadCapdata_struct), |
| 2221 | 1, logvol, 0, NULL, TYPE_CMD); | 2498 | 0, scsi3addr, TYPE_CMD); |
| 2222 | if (return_code == IO_OK) { | 2499 | if (return_code == IO_OK) { |
| 2223 | *total_size = be32_to_cpu(*(__be32 *) buf->total_size); | 2500 | *total_size = be32_to_cpu(*(__be32 *) buf->total_size); |
| 2224 | *block_size = be32_to_cpu(*(__be32 *) buf->block_size); | 2501 | *block_size = be32_to_cpu(*(__be32 *) buf->block_size); |
| @@ -2238,6 +2515,7 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, | |||
| 2238 | { | 2515 | { |
| 2239 | ReadCapdata_struct_16 *buf; | 2516 | ReadCapdata_struct_16 *buf; |
| 2240 | int return_code; | 2517 | int return_code; |
| 2518 | unsigned char scsi3addr[8]; | ||
| 2241 | 2519 | ||
| 2242 | buf = kzalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL); | 2520 | buf = kzalloc(sizeof(ReadCapdata_struct_16), GFP_KERNEL); |
| 2243 | if (!buf) { | 2521 | if (!buf) { |
| @@ -2245,15 +2523,16 @@ cciss_read_capacity_16(int ctlr, int logvol, int withirq, sector_t *total_size, | |||
| 2245 | return; | 2523 | return; |
| 2246 | } | 2524 | } |
| 2247 | 2525 | ||
| 2526 | log_unit_to_scsi3addr(hba[ctlr], scsi3addr, logvol); | ||
| 2248 | if (withirq) { | 2527 | if (withirq) { |
| 2249 | return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16, | 2528 | return_code = sendcmd_withirq(CCISS_READ_CAPACITY_16, |
| 2250 | ctlr, buf, sizeof(ReadCapdata_struct_16), | 2529 | ctlr, buf, sizeof(ReadCapdata_struct_16), |
| 2251 | 1, logvol, 0, TYPE_CMD); | 2530 | 0, scsi3addr, TYPE_CMD); |
| 2252 | } | 2531 | } |
| 2253 | else { | 2532 | else { |
| 2254 | return_code = sendcmd(CCISS_READ_CAPACITY_16, | 2533 | return_code = sendcmd(CCISS_READ_CAPACITY_16, |
| 2255 | ctlr, buf, sizeof(ReadCapdata_struct_16), | 2534 | ctlr, buf, sizeof(ReadCapdata_struct_16), |
| 2256 | 1, logvol, 0, NULL, TYPE_CMD); | 2535 | 0, scsi3addr, TYPE_CMD); |
| 2257 | } | 2536 | } |
| 2258 | if (return_code == IO_OK) { | 2537 | if (return_code == IO_OK) { |
| 2259 | *total_size = be64_to_cpu(*(__be64 *) buf->total_size); | 2538 | *total_size = be64_to_cpu(*(__be64 *) buf->total_size); |
| @@ -2303,7 +2582,7 @@ static int cciss_revalidate(struct gendisk *disk) | |||
| 2303 | cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, | 2582 | cciss_geometry_inquiry(h->ctlr, logvol, 1, total_size, block_size, |
| 2304 | inq_buff, drv); | 2583 | inq_buff, drv); |
| 2305 | 2584 | ||
| 2306 | blk_queue_hardsect_size(drv->queue, drv->block_size); | 2585 | blk_queue_logical_block_size(drv->queue, drv->block_size); |
| 2307 | set_capacity(disk, drv->nr_blocks); | 2586 | set_capacity(disk, drv->nr_blocks); |
| 2308 | 2587 | ||
| 2309 | kfree(inq_buff); | 2588 | kfree(inq_buff); |
| @@ -2333,86 +2612,21 @@ static unsigned long pollcomplete(int ctlr) | |||
| 2333 | return 1; | 2612 | return 1; |
| 2334 | } | 2613 | } |
| 2335 | 2614 | ||
| 2336 | static int add_sendcmd_reject(__u8 cmd, int ctlr, unsigned long complete) | 2615 | /* Send command c to controller h and poll for it to complete. |
| 2337 | { | 2616 | * Turns interrupts off on the board. Used at driver init time |
| 2338 | /* We get in here if sendcmd() is polling for completions | 2617 | * and during SCSI error recovery. |
| 2339 | and gets some command back that it wasn't expecting -- | ||
| 2340 | something other than that which it just sent down. | ||
| 2341 | Ordinarily, that shouldn't happen, but it can happen when | ||
| 2342 | the scsi tape stuff gets into error handling mode, and | ||
| 2343 | starts using sendcmd() to try to abort commands and | ||
| 2344 | reset tape drives. In that case, sendcmd may pick up | ||
| 2345 | completions of commands that were sent to logical drives | ||
| 2346 | through the block i/o system, or cciss ioctls completing, etc. | ||
| 2347 | In that case, we need to save those completions for later | ||
| 2348 | processing by the interrupt handler. | ||
| 2349 | */ | ||
| 2350 | |||
| 2351 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 2352 | struct sendcmd_reject_list *srl = &hba[ctlr]->scsi_rejects; | ||
| 2353 | |||
| 2354 | /* If it's not the scsi tape stuff doing error handling, (abort */ | ||
| 2355 | /* or reset) then we don't expect anything weird. */ | ||
| 2356 | if (cmd != CCISS_RESET_MSG && cmd != CCISS_ABORT_MSG) { | ||
| 2357 | #endif | ||
| 2358 | printk(KERN_WARNING "cciss cciss%d: SendCmd " | ||
| 2359 | "Invalid command list address returned! (%lx)\n", | ||
| 2360 | ctlr, complete); | ||
| 2361 | /* not much we can do. */ | ||
| 2362 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 2363 | return 1; | ||
| 2364 | } | ||
| 2365 | |||
| 2366 | /* We've sent down an abort or reset, but something else | ||
| 2367 | has completed */ | ||
| 2368 | if (srl->ncompletions >= (hba[ctlr]->nr_cmds + 2)) { | ||
| 2369 | /* Uh oh. No room to save it for later... */ | ||
| 2370 | printk(KERN_WARNING "cciss%d: Sendcmd: Invalid command addr, " | ||
| 2371 | "reject list overflow, command lost!\n", ctlr); | ||
| 2372 | return 1; | ||
| 2373 | } | ||
| 2374 | /* Save it for later */ | ||
| 2375 | srl->complete[srl->ncompletions] = complete; | ||
| 2376 | srl->ncompletions++; | ||
| 2377 | #endif | ||
| 2378 | return 0; | ||
| 2379 | } | ||
| 2380 | |||
| 2381 | /* | ||
| 2382 | * Send a command to the controller, and wait for it to complete. | ||
| 2383 | * Only used at init time. | ||
| 2384 | */ | 2618 | */ |
| 2385 | static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use_unit_num, /* 0: address the controller, | 2619 | static int sendcmd_core(ctlr_info_t *h, CommandList_struct *c) |
| 2386 | 1: address logical volume log_unit, | ||
| 2387 | 2: periph device address is scsi3addr */ | ||
| 2388 | unsigned int log_unit, | ||
| 2389 | __u8 page_code, unsigned char *scsi3addr, int cmd_type) | ||
| 2390 | { | 2620 | { |
| 2391 | CommandList_struct *c; | ||
| 2392 | int i; | 2621 | int i; |
| 2393 | unsigned long complete; | 2622 | unsigned long complete; |
| 2394 | ctlr_info_t *info_p = hba[ctlr]; | 2623 | int status = IO_ERROR; |
| 2395 | u64bit buff_dma_handle; | 2624 | u64bit buff_dma_handle; |
| 2396 | int status, done = 0; | ||
| 2397 | 2625 | ||
| 2398 | if ((c = cmd_alloc(info_p, 1)) == NULL) { | 2626 | resend_cmd1: |
| 2399 | printk(KERN_WARNING "cciss: unable to get memory"); | 2627 | |
| 2400 | return IO_ERROR; | 2628 | /* Disable interrupt on the board. */ |
| 2401 | } | 2629 | h->access.set_intr_mask(h, CCISS_INTR_OFF); |
| 2402 | status = fill_cmd(c, cmd, ctlr, buff, size, use_unit_num, | ||
| 2403 | log_unit, page_code, scsi3addr, cmd_type); | ||
| 2404 | if (status != IO_OK) { | ||
| 2405 | cmd_free(info_p, c, 1); | ||
| 2406 | return status; | ||
| 2407 | } | ||
| 2408 | resend_cmd1: | ||
| 2409 | /* | ||
| 2410 | * Disable interrupt | ||
| 2411 | */ | ||
| 2412 | #ifdef CCISS_DEBUG | ||
| 2413 | printk(KERN_DEBUG "cciss: turning intr off\n"); | ||
| 2414 | #endif /* CCISS_DEBUG */ | ||
| 2415 | info_p->access.set_intr_mask(info_p, CCISS_INTR_OFF); | ||
| 2416 | 2630 | ||
| 2417 | /* Make sure there is room in the command FIFO */ | 2631 | /* Make sure there is room in the command FIFO */ |
| 2418 | /* Actually it should be completely empty at this time */ | 2632 | /* Actually it should be completely empty at this time */ |
| @@ -2420,21 +2634,15 @@ static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use | |||
| 2420 | /* tape side of the driver. */ | 2634 | /* tape side of the driver. */ |
| 2421 | for (i = 200000; i > 0; i--) { | 2635 | for (i = 200000; i > 0; i--) { |
| 2422 | /* if fifo isn't full go */ | 2636 | /* if fifo isn't full go */ |
| 2423 | if (!(info_p->access.fifo_full(info_p))) { | 2637 | if (!(h->access.fifo_full(h))) |
| 2424 | |||
| 2425 | break; | 2638 | break; |
| 2426 | } | ||
| 2427 | udelay(10); | 2639 | udelay(10); |
| 2428 | printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full," | 2640 | printk(KERN_WARNING "cciss cciss%d: SendCmd FIFO full," |
| 2429 | " waiting!\n", ctlr); | 2641 | " waiting!\n", h->ctlr); |
| 2430 | } | 2642 | } |
| 2431 | /* | 2643 | h->access.submit_command(h, c); /* Send the cmd */ |
| 2432 | * Send the cmd | ||
| 2433 | */ | ||
| 2434 | info_p->access.submit_command(info_p, c); | ||
| 2435 | done = 0; | ||
| 2436 | do { | 2644 | do { |
| 2437 | complete = pollcomplete(ctlr); | 2645 | complete = pollcomplete(h->ctlr); |
| 2438 | 2646 | ||
| 2439 | #ifdef CCISS_DEBUG | 2647 | #ifdef CCISS_DEBUG |
| 2440 | printk(KERN_DEBUG "cciss: command completed\n"); | 2648 | printk(KERN_DEBUG "cciss: command completed\n"); |
| @@ -2443,97 +2651,102 @@ static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, unsigned int use | |||
| 2443 | if (complete == 1) { | 2651 | if (complete == 1) { |
| 2444 | printk(KERN_WARNING | 2652 | printk(KERN_WARNING |
| 2445 | "cciss cciss%d: SendCmd Timeout out, " | 2653 | "cciss cciss%d: SendCmd Timeout out, " |
| 2446 | "No command list address returned!\n", ctlr); | 2654 | "No command list address returned!\n", h->ctlr); |
| 2447 | status = IO_ERROR; | 2655 | status = IO_ERROR; |
| 2448 | done = 1; | ||
| 2449 | break; | 2656 | break; |
| 2450 | } | 2657 | } |
| 2451 | 2658 | ||
| 2452 | /* This will need to change for direct lookup completions */ | 2659 | /* Make sure it's the command we're expecting. */ |
| 2453 | if ((complete & CISS_ERROR_BIT) | 2660 | if ((complete & ~CISS_ERROR_BIT) != c->busaddr) { |
| 2454 | && (complete & ~CISS_ERROR_BIT) == c->busaddr) { | 2661 | printk(KERN_WARNING "cciss%d: Unexpected command " |
| 2455 | /* if data overrun or underun on Report command | 2662 | "completion.\n", h->ctlr); |
| 2456 | ignore it | 2663 | continue; |
| 2457 | */ | 2664 | } |
| 2458 | if (((c->Request.CDB[0] == CISS_REPORT_LOG) || | 2665 | |
| 2459 | (c->Request.CDB[0] == CISS_REPORT_PHYS) || | 2666 | /* It is our command. If no error, we're done. */ |
| 2460 | (c->Request.CDB[0] == CISS_INQUIRY)) && | 2667 | if (!(complete & CISS_ERROR_BIT)) { |
| 2461 | ((c->err_info->CommandStatus == | 2668 | status = IO_OK; |
| 2462 | CMD_DATA_OVERRUN) || | 2669 | break; |
| 2463 | (c->err_info->CommandStatus == CMD_DATA_UNDERRUN) | ||
| 2464 | )) { | ||
| 2465 | complete = c->busaddr; | ||
| 2466 | } else { | ||
| 2467 | if (c->err_info->CommandStatus == | ||
| 2468 | CMD_UNSOLICITED_ABORT) { | ||
| 2469 | printk(KERN_WARNING "cciss%d: " | ||
| 2470 | "unsolicited abort %p\n", | ||
| 2471 | ctlr, c); | ||
| 2472 | if (c->retry_count < MAX_CMD_RETRIES) { | ||
| 2473 | printk(KERN_WARNING | ||
| 2474 | "cciss%d: retrying %p\n", | ||
| 2475 | ctlr, c); | ||
| 2476 | c->retry_count++; | ||
| 2477 | /* erase the old error */ | ||
| 2478 | /* information */ | ||
| 2479 | memset(c->err_info, 0, | ||
| 2480 | sizeof | ||
| 2481 | (ErrorInfo_struct)); | ||
| 2482 | goto resend_cmd1; | ||
| 2483 | } else { | ||
| 2484 | printk(KERN_WARNING | ||
| 2485 | "cciss%d: retried %p too " | ||
| 2486 | "many times\n", ctlr, c); | ||
| 2487 | status = IO_ERROR; | ||
| 2488 | goto cleanup1; | ||
| 2489 | } | ||
| 2490 | } else if (c->err_info->CommandStatus == | ||
| 2491 | CMD_UNABORTABLE) { | ||
| 2492 | printk(KERN_WARNING | ||
| 2493 | "cciss%d: command could not be aborted.\n", | ||
| 2494 | ctlr); | ||
| 2495 | status = IO_ERROR; | ||
| 2496 | goto cleanup1; | ||
| 2497 | } | ||
| 2498 | printk(KERN_WARNING "ciss ciss%d: sendcmd" | ||
| 2499 | " Error %x \n", ctlr, | ||
| 2500 | c->err_info->CommandStatus); | ||
| 2501 | printk(KERN_WARNING "ciss ciss%d: sendcmd" | ||
| 2502 | " offensive info\n" | ||
| 2503 | " size %x\n num %x value %x\n", | ||
| 2504 | ctlr, | ||
| 2505 | c->err_info->MoreErrInfo.Invalid_Cmd. | ||
| 2506 | offense_size, | ||
| 2507 | c->err_info->MoreErrInfo.Invalid_Cmd. | ||
| 2508 | offense_num, | ||
| 2509 | c->err_info->MoreErrInfo.Invalid_Cmd. | ||
| 2510 | offense_value); | ||
| 2511 | status = IO_ERROR; | ||
| 2512 | goto cleanup1; | ||
| 2513 | } | ||
| 2514 | } | 2670 | } |
| 2515 | /* This will need changing for direct lookup completions */ | 2671 | |
| 2516 | if (complete != c->busaddr) { | 2672 | /* There is an error... */ |
| 2517 | if (add_sendcmd_reject(cmd, ctlr, complete) != 0) { | 2673 | |
| 2518 | BUG(); /* we are pretty much hosed if we get here. */ | 2674 | /* if data overrun or underun on Report command ignore it */ |
| 2675 | if (((c->Request.CDB[0] == CISS_REPORT_LOG) || | ||
| 2676 | (c->Request.CDB[0] == CISS_REPORT_PHYS) || | ||
| 2677 | (c->Request.CDB[0] == CISS_INQUIRY)) && | ||
| 2678 | ((c->err_info->CommandStatus == CMD_DATA_OVERRUN) || | ||
| 2679 | (c->err_info->CommandStatus == CMD_DATA_UNDERRUN))) { | ||
| 2680 | complete = c->busaddr; | ||
| 2681 | status = IO_OK; | ||
| 2682 | break; | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | if (c->err_info->CommandStatus == CMD_UNSOLICITED_ABORT) { | ||
| 2686 | printk(KERN_WARNING "cciss%d: unsolicited abort %p\n", | ||
| 2687 | h->ctlr, c); | ||
| 2688 | if (c->retry_count < MAX_CMD_RETRIES) { | ||
| 2689 | printk(KERN_WARNING "cciss%d: retrying %p\n", | ||
| 2690 | h->ctlr, c); | ||
| 2691 | c->retry_count++; | ||
| 2692 | /* erase the old error information */ | ||
| 2693 | memset(c->err_info, 0, sizeof(c->err_info)); | ||
| 2694 | goto resend_cmd1; | ||
| 2519 | } | 2695 | } |
| 2520 | continue; | 2696 | printk(KERN_WARNING "cciss%d: retried %p too many " |
| 2521 | } else | 2697 | "times\n", h->ctlr, c); |
| 2522 | done = 1; | 2698 | status = IO_ERROR; |
| 2523 | } while (!done); | 2699 | break; |
| 2700 | } | ||
| 2701 | |||
| 2702 | if (c->err_info->CommandStatus == CMD_UNABORTABLE) { | ||
| 2703 | printk(KERN_WARNING "cciss%d: command could not be " | ||
| 2704 | "aborted.\n", h->ctlr); | ||
| 2705 | status = IO_ERROR; | ||
| 2706 | break; | ||
| 2707 | } | ||
| 2708 | |||
| 2709 | if (c->err_info->CommandStatus == CMD_TARGET_STATUS) { | ||
| 2710 | status = check_target_status(h, c); | ||
| 2711 | break; | ||
| 2712 | } | ||
| 2713 | |||
| 2714 | printk(KERN_WARNING "cciss%d: sendcmd error\n", h->ctlr); | ||
| 2715 | printk(KERN_WARNING "cmd = 0x%02x, CommandStatus = 0x%02x\n", | ||
| 2716 | c->Request.CDB[0], c->err_info->CommandStatus); | ||
| 2717 | status = IO_ERROR; | ||
| 2718 | break; | ||
| 2719 | |||
| 2720 | } while (1); | ||
| 2524 | 2721 | ||
| 2525 | cleanup1: | ||
| 2526 | /* unlock the data buffer from DMA */ | 2722 | /* unlock the data buffer from DMA */ |
| 2527 | buff_dma_handle.val32.lower = c->SG[0].Addr.lower; | 2723 | buff_dma_handle.val32.lower = c->SG[0].Addr.lower; |
| 2528 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; | 2724 | buff_dma_handle.val32.upper = c->SG[0].Addr.upper; |
| 2529 | pci_unmap_single(info_p->pdev, (dma_addr_t) buff_dma_handle.val, | 2725 | pci_unmap_single(h->pdev, (dma_addr_t) buff_dma_handle.val, |
| 2530 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); | 2726 | c->SG[0].Len, PCI_DMA_BIDIRECTIONAL); |
| 2531 | #ifdef CONFIG_CISS_SCSI_TAPE | 2727 | return status; |
| 2532 | /* if we saved some commands for later, process them now. */ | 2728 | } |
| 2533 | if (info_p->scsi_rejects.ncompletions > 0) | 2729 | |
| 2534 | do_cciss_intr(0, info_p); | 2730 | /* |
| 2535 | #endif | 2731 | * Send a command to the controller, and wait for it to complete. |
| 2536 | cmd_free(info_p, c, 1); | 2732 | * Used at init time, and during SCSI error recovery. |
| 2733 | */ | ||
| 2734 | static int sendcmd(__u8 cmd, int ctlr, void *buff, size_t size, | ||
| 2735 | __u8 page_code, unsigned char *scsi3addr, int cmd_type) | ||
| 2736 | { | ||
| 2737 | CommandList_struct *c; | ||
| 2738 | int status; | ||
| 2739 | |||
| 2740 | c = cmd_alloc(hba[ctlr], 1); | ||
| 2741 | if (!c) { | ||
| 2742 | printk(KERN_WARNING "cciss: unable to get memory"); | ||
| 2743 | return IO_ERROR; | ||
| 2744 | } | ||
| 2745 | status = fill_cmd(c, cmd, ctlr, buff, size, page_code, | ||
| 2746 | scsi3addr, cmd_type); | ||
| 2747 | if (status == IO_OK) | ||
| 2748 | status = sendcmd_core(hba[ctlr], c); | ||
| 2749 | cmd_free(hba[ctlr], c, 1); | ||
| 2537 | return status; | 2750 | return status; |
| 2538 | } | 2751 | } |
| 2539 | 2752 | ||
| @@ -2691,7 +2904,7 @@ static inline void complete_command(ctlr_info_t *h, CommandList_struct *cmd, | |||
| 2691 | printk(KERN_WARNING "cciss: cmd %p has" | 2904 | printk(KERN_WARNING "cciss: cmd %p has" |
| 2692 | " completed with data underrun " | 2905 | " completed with data underrun " |
| 2693 | "reported\n", cmd); | 2906 | "reported\n", cmd); |
| 2694 | cmd->rq->data_len = cmd->err_info->ResidualCnt; | 2907 | cmd->rq->resid_len = cmd->err_info->ResidualCnt; |
| 2695 | } | 2908 | } |
| 2696 | break; | 2909 | break; |
| 2697 | case CMD_DATA_OVERRUN: | 2910 | case CMD_DATA_OVERRUN: |
| @@ -2806,7 +3019,7 @@ static void do_cciss_request(struct request_queue *q) | |||
| 2806 | goto startio; | 3019 | goto startio; |
| 2807 | 3020 | ||
| 2808 | queue: | 3021 | queue: |
| 2809 | creq = elv_next_request(q); | 3022 | creq = blk_peek_request(q); |
| 2810 | if (!creq) | 3023 | if (!creq) |
| 2811 | goto startio; | 3024 | goto startio; |
| 2812 | 3025 | ||
| @@ -2815,7 +3028,7 @@ static void do_cciss_request(struct request_queue *q) | |||
| 2815 | if ((c = cmd_alloc(h, 1)) == NULL) | 3028 | if ((c = cmd_alloc(h, 1)) == NULL) |
| 2816 | goto full; | 3029 | goto full; |
| 2817 | 3030 | ||
| 2818 | blkdev_dequeue_request(creq); | 3031 | blk_start_request(creq); |
| 2819 | 3032 | ||
| 2820 | spin_unlock_irq(q->queue_lock); | 3033 | spin_unlock_irq(q->queue_lock); |
| 2821 | 3034 | ||
| @@ -2840,10 +3053,10 @@ static void do_cciss_request(struct request_queue *q) | |||
| 2840 | c->Request.Timeout = 0; // Don't time out | 3053 | c->Request.Timeout = 0; // Don't time out |
| 2841 | c->Request.CDB[0] = | 3054 | c->Request.CDB[0] = |
| 2842 | (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write; | 3055 | (rq_data_dir(creq) == READ) ? h->cciss_read : h->cciss_write; |
| 2843 | start_blk = creq->sector; | 3056 | start_blk = blk_rq_pos(creq); |
| 2844 | #ifdef CCISS_DEBUG | 3057 | #ifdef CCISS_DEBUG |
| 2845 | printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", (int)creq->sector, | 3058 | printk(KERN_DEBUG "ciss: sector =%d nr_sectors=%d\n", |
| 2846 | (int)creq->nr_sectors); | 3059 | (int)blk_rq_pos(creq), (int)blk_rq_sectors(creq)); |
| 2847 | #endif /* CCISS_DEBUG */ | 3060 | #endif /* CCISS_DEBUG */ |
| 2848 | 3061 | ||
| 2849 | sg_init_table(tmp_sg, MAXSGENTRIES); | 3062 | sg_init_table(tmp_sg, MAXSGENTRIES); |
| @@ -2869,8 +3082,8 @@ static void do_cciss_request(struct request_queue *q) | |||
| 2869 | h->maxSG = seg; | 3082 | h->maxSG = seg; |
| 2870 | 3083 | ||
| 2871 | #ifdef CCISS_DEBUG | 3084 | #ifdef CCISS_DEBUG |
| 2872 | printk(KERN_DEBUG "cciss: Submitting %lu sectors in %d segments\n", | 3085 | printk(KERN_DEBUG "cciss: Submitting %u sectors in %d segments\n", |
| 2873 | creq->nr_sectors, seg); | 3086 | blk_rq_sectors(creq), seg); |
| 2874 | #endif /* CCISS_DEBUG */ | 3087 | #endif /* CCISS_DEBUG */ |
| 2875 | 3088 | ||
| 2876 | c->Header.SGList = c->Header.SGTotal = seg; | 3089 | c->Header.SGList = c->Header.SGTotal = seg; |
| @@ -2882,8 +3095,8 @@ static void do_cciss_request(struct request_queue *q) | |||
| 2882 | c->Request.CDB[4] = (start_blk >> 8) & 0xff; | 3095 | c->Request.CDB[4] = (start_blk >> 8) & 0xff; |
| 2883 | c->Request.CDB[5] = start_blk & 0xff; | 3096 | c->Request.CDB[5] = start_blk & 0xff; |
| 2884 | c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB | 3097 | c->Request.CDB[6] = 0; // (sect >> 24) & 0xff; MSB |
| 2885 | c->Request.CDB[7] = (creq->nr_sectors >> 8) & 0xff; | 3098 | c->Request.CDB[7] = (blk_rq_sectors(creq) >> 8) & 0xff; |
| 2886 | c->Request.CDB[8] = creq->nr_sectors & 0xff; | 3099 | c->Request.CDB[8] = blk_rq_sectors(creq) & 0xff; |
| 2887 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; | 3100 | c->Request.CDB[9] = c->Request.CDB[11] = c->Request.CDB[12] = 0; |
| 2888 | } else { | 3101 | } else { |
| 2889 | u32 upper32 = upper_32_bits(start_blk); | 3102 | u32 upper32 = upper_32_bits(start_blk); |
| @@ -2898,10 +3111,10 @@ static void do_cciss_request(struct request_queue *q) | |||
| 2898 | c->Request.CDB[7]= (start_blk >> 16) & 0xff; | 3111 | c->Request.CDB[7]= (start_blk >> 16) & 0xff; |
| 2899 | c->Request.CDB[8]= (start_blk >> 8) & 0xff; | 3112 | c->Request.CDB[8]= (start_blk >> 8) & 0xff; |
| 2900 | c->Request.CDB[9]= start_blk & 0xff; | 3113 | c->Request.CDB[9]= start_blk & 0xff; |
| 2901 | c->Request.CDB[10]= (creq->nr_sectors >> 24) & 0xff; | 3114 | c->Request.CDB[10]= (blk_rq_sectors(creq) >> 24) & 0xff; |
| 2902 | c->Request.CDB[11]= (creq->nr_sectors >> 16) & 0xff; | 3115 | c->Request.CDB[11]= (blk_rq_sectors(creq) >> 16) & 0xff; |
| 2903 | c->Request.CDB[12]= (creq->nr_sectors >> 8) & 0xff; | 3116 | c->Request.CDB[12]= (blk_rq_sectors(creq) >> 8) & 0xff; |
| 2904 | c->Request.CDB[13]= creq->nr_sectors & 0xff; | 3117 | c->Request.CDB[13]= blk_rq_sectors(creq) & 0xff; |
| 2905 | c->Request.CDB[14] = c->Request.CDB[15] = 0; | 3118 | c->Request.CDB[14] = c->Request.CDB[15] = 0; |
| 2906 | } | 3119 | } |
| 2907 | } else if (blk_pc_request(creq)) { | 3120 | } else if (blk_pc_request(creq)) { |
| @@ -2931,44 +3144,18 @@ startio: | |||
| 2931 | 3144 | ||
| 2932 | static inline unsigned long get_next_completion(ctlr_info_t *h) | 3145 | static inline unsigned long get_next_completion(ctlr_info_t *h) |
| 2933 | { | 3146 | { |
| 2934 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 2935 | /* Any rejects from sendcmd() lying around? Process them first */ | ||
| 2936 | if (h->scsi_rejects.ncompletions == 0) | ||
| 2937 | return h->access.command_completed(h); | ||
| 2938 | else { | ||
| 2939 | struct sendcmd_reject_list *srl; | ||
| 2940 | int n; | ||
| 2941 | srl = &h->scsi_rejects; | ||
| 2942 | n = --srl->ncompletions; | ||
| 2943 | /* printk("cciss%d: processing saved reject\n", h->ctlr); */ | ||
| 2944 | printk("p"); | ||
| 2945 | return srl->complete[n]; | ||
| 2946 | } | ||
| 2947 | #else | ||
| 2948 | return h->access.command_completed(h); | 3147 | return h->access.command_completed(h); |
| 2949 | #endif | ||
| 2950 | } | 3148 | } |
| 2951 | 3149 | ||
| 2952 | static inline int interrupt_pending(ctlr_info_t *h) | 3150 | static inline int interrupt_pending(ctlr_info_t *h) |
| 2953 | { | 3151 | { |
| 2954 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 2955 | return (h->access.intr_pending(h) | ||
| 2956 | || (h->scsi_rejects.ncompletions > 0)); | ||
| 2957 | #else | ||
| 2958 | return h->access.intr_pending(h); | 3152 | return h->access.intr_pending(h); |
| 2959 | #endif | ||
| 2960 | } | 3153 | } |
| 2961 | 3154 | ||
| 2962 | static inline long interrupt_not_for_us(ctlr_info_t *h) | 3155 | static inline long interrupt_not_for_us(ctlr_info_t *h) |
| 2963 | { | 3156 | { |
| 2964 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 2965 | return (((h->access.intr_pending(h) == 0) || | ||
| 2966 | (h->interrupts_enabled == 0)) | ||
| 2967 | && (h->scsi_rejects.ncompletions == 0)); | ||
| 2968 | #else | ||
| 2969 | return (((h->access.intr_pending(h) == 0) || | 3157 | return (((h->access.intr_pending(h) == 0) || |
| 2970 | (h->interrupts_enabled == 0))); | 3158 | (h->interrupts_enabled == 0))); |
| 2971 | #endif | ||
| 2972 | } | 3159 | } |
| 2973 | 3160 | ||
| 2974 | static irqreturn_t do_cciss_intr(int irq, void *dev_id) | 3161 | static irqreturn_t do_cciss_intr(int irq, void *dev_id) |
| @@ -3723,12 +3910,15 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 3723 | INIT_HLIST_HEAD(&hba[i]->reqQ); | 3910 | INIT_HLIST_HEAD(&hba[i]->reqQ); |
| 3724 | 3911 | ||
| 3725 | if (cciss_pci_init(hba[i], pdev) != 0) | 3912 | if (cciss_pci_init(hba[i], pdev) != 0) |
| 3726 | goto clean1; | 3913 | goto clean0; |
| 3727 | 3914 | ||
| 3728 | sprintf(hba[i]->devname, "cciss%d", i); | 3915 | sprintf(hba[i]->devname, "cciss%d", i); |
| 3729 | hba[i]->ctlr = i; | 3916 | hba[i]->ctlr = i; |
| 3730 | hba[i]->pdev = pdev; | 3917 | hba[i]->pdev = pdev; |
| 3731 | 3918 | ||
| 3919 | if (cciss_create_hba_sysfs_entry(hba[i])) | ||
| 3920 | goto clean0; | ||
| 3921 | |||
| 3732 | /* configure PCI DMA stuff */ | 3922 | /* configure PCI DMA stuff */ |
| 3733 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) | 3923 | if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) |
| 3734 | dac = 1; | 3924 | dac = 1; |
| @@ -3787,15 +3977,6 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 3787 | printk(KERN_ERR "cciss: out of memory"); | 3977 | printk(KERN_ERR "cciss: out of memory"); |
| 3788 | goto clean4; | 3978 | goto clean4; |
| 3789 | } | 3979 | } |
| 3790 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 3791 | hba[i]->scsi_rejects.complete = | ||
| 3792 | kmalloc(sizeof(hba[i]->scsi_rejects.complete[0]) * | ||
| 3793 | (hba[i]->nr_cmds + 5), GFP_KERNEL); | ||
| 3794 | if (hba[i]->scsi_rejects.complete == NULL) { | ||
| 3795 | printk(KERN_ERR "cciss: out of memory"); | ||
| 3796 | goto clean4; | ||
| 3797 | } | ||
| 3798 | #endif | ||
| 3799 | spin_lock_init(&hba[i]->lock); | 3980 | spin_lock_init(&hba[i]->lock); |
| 3800 | 3981 | ||
| 3801 | /* Initialize the pdev driver private data. | 3982 | /* Initialize the pdev driver private data. |
| @@ -3828,7 +4009,7 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 3828 | } | 4009 | } |
| 3829 | 4010 | ||
| 3830 | return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff, | 4011 | return_code = sendcmd_withirq(CISS_INQUIRY, i, inq_buff, |
| 3831 | sizeof(InquiryData_struct), 0, 0 , 0, TYPE_CMD); | 4012 | sizeof(InquiryData_struct), 0, CTLR_LUNID, TYPE_CMD); |
| 3832 | if (return_code == IO_OK) { | 4013 | if (return_code == IO_OK) { |
| 3833 | hba[i]->firm_ver[0] = inq_buff->data_byte[32]; | 4014 | hba[i]->firm_ver[0] = inq_buff->data_byte[32]; |
| 3834 | hba[i]->firm_ver[1] = inq_buff->data_byte[33]; | 4015 | hba[i]->firm_ver[1] = inq_buff->data_byte[33]; |
| @@ -3855,9 +4036,6 @@ static int __devinit cciss_init_one(struct pci_dev *pdev, | |||
| 3855 | 4036 | ||
| 3856 | clean4: | 4037 | clean4: |
| 3857 | kfree(inq_buff); | 4038 | kfree(inq_buff); |
| 3858 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 3859 | kfree(hba[i]->scsi_rejects.complete); | ||
| 3860 | #endif | ||
| 3861 | kfree(hba[i]->cmd_pool_bits); | 4039 | kfree(hba[i]->cmd_pool_bits); |
| 3862 | if (hba[i]->cmd_pool) | 4040 | if (hba[i]->cmd_pool) |
| 3863 | pci_free_consistent(hba[i]->pdev, | 4041 | pci_free_consistent(hba[i]->pdev, |
| @@ -3872,6 +4050,8 @@ clean4: | |||
| 3872 | clean2: | 4050 | clean2: |
| 3873 | unregister_blkdev(hba[i]->major, hba[i]->devname); | 4051 | unregister_blkdev(hba[i]->major, hba[i]->devname); |
| 3874 | clean1: | 4052 | clean1: |
| 4053 | cciss_destroy_hba_sysfs_entry(hba[i]); | ||
| 4054 | clean0: | ||
| 3875 | hba[i]->busy_initializing = 0; | 4055 | hba[i]->busy_initializing = 0; |
| 3876 | /* cleanup any queues that may have been initialized */ | 4056 | /* cleanup any queues that may have been initialized */ |
| 3877 | for (j=0; j <= hba[i]->highest_lun; j++){ | 4057 | for (j=0; j <= hba[i]->highest_lun; j++){ |
| @@ -3907,8 +4087,8 @@ static void cciss_shutdown(struct pci_dev *pdev) | |||
| 3907 | /* sendcmd will turn off interrupt, and send the flush... | 4087 | /* sendcmd will turn off interrupt, and send the flush... |
| 3908 | * To write all data in the battery backed cache to disks */ | 4088 | * To write all data in the battery backed cache to disks */ |
| 3909 | memset(flush_buf, 0, 4); | 4089 | memset(flush_buf, 0, 4); |
| 3910 | return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, 0, 0, NULL, | 4090 | return_code = sendcmd(CCISS_CACHE_FLUSH, i, flush_buf, 4, 0, |
| 3911 | TYPE_CMD); | 4091 | CTLR_LUNID, TYPE_CMD); |
| 3912 | if (return_code == IO_OK) { | 4092 | if (return_code == IO_OK) { |
| 3913 | printk(KERN_INFO "Completed flushing cache on controller %d\n", i); | 4093 | printk(KERN_INFO "Completed flushing cache on controller %d\n", i); |
| 3914 | } else { | 4094 | } else { |
| @@ -3973,15 +4153,13 @@ static void __devexit cciss_remove_one(struct pci_dev *pdev) | |||
| 3973 | pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct), | 4153 | pci_free_consistent(hba[i]->pdev, hba[i]->nr_cmds * sizeof(ErrorInfo_struct), |
| 3974 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); | 4154 | hba[i]->errinfo_pool, hba[i]->errinfo_pool_dhandle); |
| 3975 | kfree(hba[i]->cmd_pool_bits); | 4155 | kfree(hba[i]->cmd_pool_bits); |
| 3976 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 3977 | kfree(hba[i]->scsi_rejects.complete); | ||
| 3978 | #endif | ||
| 3979 | /* | 4156 | /* |
| 3980 | * Deliberately omit pci_disable_device(): it does something nasty to | 4157 | * Deliberately omit pci_disable_device(): it does something nasty to |
| 3981 | * Smart Array controllers that pci_enable_device does not undo | 4158 | * Smart Array controllers that pci_enable_device does not undo |
| 3982 | */ | 4159 | */ |
| 3983 | pci_release_regions(pdev); | 4160 | pci_release_regions(pdev); |
| 3984 | pci_set_drvdata(pdev, NULL); | 4161 | pci_set_drvdata(pdev, NULL); |
| 4162 | cciss_destroy_hba_sysfs_entry(hba[i]); | ||
| 3985 | free_hba(i); | 4163 | free_hba(i); |
| 3986 | } | 4164 | } |
| 3987 | 4165 | ||
| @@ -3999,6 +4177,8 @@ static struct pci_driver cciss_pci_driver = { | |||
| 3999 | */ | 4177 | */ |
| 4000 | static int __init cciss_init(void) | 4178 | static int __init cciss_init(void) |
| 4001 | { | 4179 | { |
| 4180 | int err; | ||
| 4181 | |||
| 4002 | /* | 4182 | /* |
| 4003 | * The hardware requires that commands are aligned on a 64-bit | 4183 | * The hardware requires that commands are aligned on a 64-bit |
| 4004 | * boundary. Given that we use pci_alloc_consistent() to allocate an | 4184 | * boundary. Given that we use pci_alloc_consistent() to allocate an |
| @@ -4008,8 +4188,20 @@ static int __init cciss_init(void) | |||
| 4008 | 4188 | ||
| 4009 | printk(KERN_INFO DRIVER_NAME "\n"); | 4189 | printk(KERN_INFO DRIVER_NAME "\n"); |
| 4010 | 4190 | ||
| 4191 | err = bus_register(&cciss_bus_type); | ||
| 4192 | if (err) | ||
| 4193 | return err; | ||
| 4194 | |||
| 4011 | /* Register for our PCI devices */ | 4195 | /* Register for our PCI devices */ |
| 4012 | return pci_register_driver(&cciss_pci_driver); | 4196 | err = pci_register_driver(&cciss_pci_driver); |
| 4197 | if (err) | ||
| 4198 | goto err_bus_register; | ||
| 4199 | |||
| 4200 | return 0; | ||
| 4201 | |||
| 4202 | err_bus_register: | ||
| 4203 | bus_unregister(&cciss_bus_type); | ||
| 4204 | return err; | ||
| 4013 | } | 4205 | } |
| 4014 | 4206 | ||
| 4015 | static void __exit cciss_cleanup(void) | 4207 | static void __exit cciss_cleanup(void) |
| @@ -4026,6 +4218,7 @@ static void __exit cciss_cleanup(void) | |||
| 4026 | } | 4218 | } |
| 4027 | } | 4219 | } |
| 4028 | remove_proc_entry("driver/cciss", NULL); | 4220 | remove_proc_entry("driver/cciss", NULL); |
| 4221 | bus_unregister(&cciss_bus_type); | ||
| 4029 | } | 4222 | } |
| 4030 | 4223 | ||
| 4031 | static void fail_all_cmds(unsigned long ctlr) | 4224 | static void fail_all_cmds(unsigned long ctlr) |
diff --git a/drivers/block/cciss.h b/drivers/block/cciss.h index 703e08038fb9..06a5db25b298 100644 --- a/drivers/block/cciss.h +++ b/drivers/block/cciss.h | |||
| @@ -11,6 +11,11 @@ | |||
| 11 | 11 | ||
| 12 | #define IO_OK 0 | 12 | #define IO_OK 0 |
| 13 | #define IO_ERROR 1 | 13 | #define IO_ERROR 1 |
| 14 | #define IO_NEEDS_RETRY 3 | ||
| 15 | |||
| 16 | #define VENDOR_LEN 8 | ||
| 17 | #define MODEL_LEN 16 | ||
| 18 | #define REV_LEN 4 | ||
| 14 | 19 | ||
| 15 | struct ctlr_info; | 20 | struct ctlr_info; |
| 16 | typedef struct ctlr_info ctlr_info_t; | 21 | typedef struct ctlr_info ctlr_info_t; |
| @@ -34,23 +39,20 @@ typedef struct _drive_info_struct | |||
| 34 | int cylinders; | 39 | int cylinders; |
| 35 | int raid_level; /* set to -1 to indicate that | 40 | int raid_level; /* set to -1 to indicate that |
| 36 | * the drive is not in use/configured | 41 | * the drive is not in use/configured |
| 37 | */ | 42 | */ |
| 38 | int busy_configuring; /*This is set when the drive is being removed | 43 | int busy_configuring; /* This is set when a drive is being removed |
| 39 | *to prevent it from being opened or it's queue | 44 | * to prevent it from being opened or it's |
| 40 | *from being started. | 45 | * queue from being started. |
| 41 | */ | 46 | */ |
| 42 | __u8 serial_no[16]; /* from inquiry page 0x83, */ | 47 | struct device dev; |
| 43 | /* not necc. null terminated. */ | 48 | __u8 serial_no[16]; /* from inquiry page 0x83, |
| 49 | * not necc. null terminated. | ||
| 50 | */ | ||
| 51 | char vendor[VENDOR_LEN + 1]; /* SCSI vendor string */ | ||
| 52 | char model[MODEL_LEN + 1]; /* SCSI model string */ | ||
| 53 | char rev[REV_LEN + 1]; /* SCSI revision string */ | ||
| 44 | } drive_info_struct; | 54 | } drive_info_struct; |
| 45 | 55 | ||
| 46 | #ifdef CONFIG_CISS_SCSI_TAPE | ||
| 47 | |||
| 48 | struct sendcmd_reject_list { | ||
| 49 | int ncompletions; | ||
| 50 | unsigned long *complete; /* array of NR_CMDS tags */ | ||
| 51 | }; | ||
| 52 | |||
| 53 | #endif | ||
| 54 | struct ctlr_info | 56 | struct ctlr_info |
| 55 | { | 57 | { |
| 56 | int ctlr; | 58 | int ctlr; |
| @@ -118,11 +120,11 @@ struct ctlr_info | |||
| 118 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ | 120 | void *scsi_ctlr; /* ptr to structure containing scsi related stuff */ |
| 119 | /* list of block side commands the scsi error handling sucked up */ | 121 | /* list of block side commands the scsi error handling sucked up */ |
| 120 | /* and saved for later processing */ | 122 | /* and saved for later processing */ |
| 121 | struct sendcmd_reject_list scsi_rejects; | ||
| 122 | #endif | 123 | #endif |
| 123 | unsigned char alive; | 124 | unsigned char alive; |
| 124 | struct completion *rescan_wait; | 125 | struct completion *rescan_wait; |
| 125 | struct task_struct *cciss_scan_thread; | 126 | struct task_struct *cciss_scan_thread; |
| 127 | struct device dev; | ||
| 126 | }; | 128 | }; |
| 127 | 129 | ||
| 128 | /* Defining the diffent access_menthods */ | 130 | /* Defining the diffent access_menthods */ |
diff --git a/drivers/block/cciss_cmd.h b/drivers/block/cciss_cmd.h index 40b1b92dae7f..cd665b00c7c5 100644 --- a/drivers/block/cciss_cmd.h +++ b/drivers/block/cciss_cmd.h | |||
| @@ -217,6 +217,8 @@ typedef union _LUNAddr_struct { | |||
| 217 | LogDevAddr_struct LogDev; | 217 | LogDevAddr_struct LogDev; |
| 218 | } LUNAddr_struct; | 218 | } LUNAddr_struct; |
| 219 | 219 | ||
| 220 | #define CTLR_LUNID "\0\0\0\0\0\0\0\0" | ||
| 221 | |||
| 220 | typedef struct _CommandListHeader_struct { | 222 | typedef struct _CommandListHeader_struct { |
| 221 | BYTE ReplyQueue; | 223 | BYTE ReplyQueue; |
| 222 | BYTE SGList; | 224 | BYTE SGList; |
diff --git a/drivers/block/cciss_scsi.c b/drivers/block/cciss_scsi.c index a3fd87b41444..3315268b4ec7 100644 --- a/drivers/block/cciss_scsi.c +++ b/drivers/block/cciss_scsi.c | |||
| @@ -44,20 +44,13 @@ | |||
| 44 | #define CCISS_ABORT_MSG 0x00 | 44 | #define CCISS_ABORT_MSG 0x00 |
| 45 | #define CCISS_RESET_MSG 0x01 | 45 | #define CCISS_RESET_MSG 0x01 |
| 46 | 46 | ||
| 47 | /* some prototypes... */ | 47 | static int fill_cmd(CommandList_struct *c, __u8 cmd, int ctlr, void *buff, |
| 48 | static int sendcmd( | 48 | size_t size, |
| 49 | __u8 cmd, | 49 | __u8 page_code, unsigned char *scsi3addr, |
| 50 | int ctlr, | ||
| 51 | void *buff, | ||
| 52 | size_t size, | ||
| 53 | unsigned int use_unit_num, /* 0: address the controller, | ||
| 54 | 1: address logical volume log_unit, | ||
| 55 | 2: address is in scsi3addr */ | ||
| 56 | unsigned int log_unit, | ||
| 57 | __u8 page_code, | ||
| 58 | unsigned char *scsi3addr, | ||
| 59 | int cmd_type); | 50 | int cmd_type); |
| 60 | 51 | ||
| 52 | static CommandList_struct *cmd_alloc(ctlr_info_t *h, int get_from_pool); | ||
| 53 | static void cmd_free(ctlr_info_t *h, CommandList_struct *c, int got_from_pool); | ||
| 61 | 54 | ||
| 62 | static int cciss_scsi_proc_info( | 55 | static int cciss_scsi_proc_info( |
| 63 | struct Scsi_Host *sh, | 56 | struct Scsi_Host *sh, |
| @@ -1575,6 +1568,75 @@ cciss_seq_tape_report(struct seq_file *seq, int ctlr) | |||
| 1575 | CPQ_TAPE_UNLOCK(ctlr, flags); | 1568 | CPQ_TAPE_UNLOCK(ctlr, flags); |
| 1576 | } | 1569 | } |
| 1577 | 1570 | ||
| 1571 | static int wait_for_device_to_become_ready(ctlr_info_t *h, | ||
| 1572 | unsigned char lunaddr[]) | ||
| 1573 | { | ||
| 1574 | int rc; | ||
| 1575 | int count = 0; | ||
| 1576 | int waittime = HZ; | ||
| 1577 | CommandList_struct *c; | ||
| 1578 | |||
| 1579 | c = cmd_alloc(h, 1); | ||
| 1580 | if (!c) { | ||
| 1581 | printk(KERN_WARNING "cciss%d: out of memory in " | ||
| 1582 | "wait_for_device_to_become_ready.\n", h->ctlr); | ||
| 1583 | return IO_ERROR; | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | /* Send test unit ready until device ready, or give up. */ | ||
| 1587 | while (count < 20) { | ||
| 1588 | |||
| 1589 | /* Wait for a bit. do this first, because if we send | ||
| 1590 | * the TUR right away, the reset will just abort it. | ||
| 1591 | */ | ||
| 1592 | schedule_timeout_uninterruptible(waittime); | ||
| 1593 | count++; | ||
| 1594 | |||
| 1595 | /* Increase wait time with each try, up to a point. */ | ||
| 1596 | if (waittime < (HZ * 30)) | ||
| 1597 | waittime = waittime * 2; | ||
| 1598 | |||
| 1599 | /* Send the Test Unit Ready */ | ||
| 1600 | rc = fill_cmd(c, TEST_UNIT_READY, h->ctlr, NULL, 0, 0, | ||
| 1601 | lunaddr, TYPE_CMD); | ||
| 1602 | if (rc == 0) | ||
| 1603 | rc = sendcmd_withirq_core(h, c, 0); | ||
| 1604 | |||
| 1605 | (void) process_sendcmd_error(h, c); | ||
| 1606 | |||
| 1607 | if (rc != 0) | ||
| 1608 | goto retry_tur; | ||
| 1609 | |||
| 1610 | if (c->err_info->CommandStatus == CMD_SUCCESS) | ||
| 1611 | break; | ||
| 1612 | |||
| 1613 | if (c->err_info->CommandStatus == CMD_TARGET_STATUS && | ||
| 1614 | c->err_info->ScsiStatus == SAM_STAT_CHECK_CONDITION) { | ||
| 1615 | if (c->err_info->SenseInfo[2] == NO_SENSE) | ||
| 1616 | break; | ||
| 1617 | if (c->err_info->SenseInfo[2] == UNIT_ATTENTION) { | ||
| 1618 | unsigned char asc; | ||
| 1619 | asc = c->err_info->SenseInfo[12]; | ||
| 1620 | check_for_unit_attention(h, c); | ||
| 1621 | if (asc == POWER_OR_RESET) | ||
| 1622 | break; | ||
| 1623 | } | ||
| 1624 | } | ||
| 1625 | retry_tur: | ||
| 1626 | printk(KERN_WARNING "cciss%d: Waiting %d secs " | ||
| 1627 | "for device to become ready.\n", | ||
| 1628 | h->ctlr, waittime / HZ); | ||
| 1629 | rc = 1; /* device not ready. */ | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | if (rc) | ||
| 1633 | printk("cciss%d: giving up on device.\n", h->ctlr); | ||
| 1634 | else | ||
| 1635 | printk(KERN_WARNING "cciss%d: device is ready.\n", h->ctlr); | ||
| 1636 | |||
| 1637 | cmd_free(h, c, 1); | ||
| 1638 | return rc; | ||
| 1639 | } | ||
| 1578 | 1640 | ||
| 1579 | /* Need at least one of these error handlers to keep ../scsi/hosts.c from | 1641 | /* Need at least one of these error handlers to keep ../scsi/hosts.c from |
| 1580 | * complaining. Doing a host- or bus-reset can't do anything good here. | 1642 | * complaining. Doing a host- or bus-reset can't do anything good here. |
| @@ -1591,6 +1653,7 @@ static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd) | |||
| 1591 | { | 1653 | { |
| 1592 | int rc; | 1654 | int rc; |
| 1593 | CommandList_struct *cmd_in_trouble; | 1655 | CommandList_struct *cmd_in_trouble; |
| 1656 | unsigned char lunaddr[8]; | ||
| 1594 | ctlr_info_t **c; | 1657 | ctlr_info_t **c; |
| 1595 | int ctlr; | 1658 | int ctlr; |
| 1596 | 1659 | ||
| @@ -1600,19 +1663,15 @@ static int cciss_eh_device_reset_handler(struct scsi_cmnd *scsicmd) | |||
| 1600 | return FAILED; | 1663 | return FAILED; |
| 1601 | ctlr = (*c)->ctlr; | 1664 | ctlr = (*c)->ctlr; |
| 1602 | printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr); | 1665 | printk(KERN_WARNING "cciss%d: resetting tape drive or medium changer.\n", ctlr); |
| 1603 | |||
| 1604 | /* find the command that's giving us trouble */ | 1666 | /* find the command that's giving us trouble */ |
| 1605 | cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble; | 1667 | cmd_in_trouble = (CommandList_struct *) scsicmd->host_scribble; |
| 1606 | if (cmd_in_trouble == NULL) { /* paranoia */ | 1668 | if (cmd_in_trouble == NULL) /* paranoia */ |
| 1607 | return FAILED; | 1669 | return FAILED; |
| 1608 | } | 1670 | memcpy(lunaddr, &cmd_in_trouble->Header.LUN.LunAddrBytes[0], 8); |
| 1609 | /* send a reset to the SCSI LUN which the command was sent to */ | 1671 | /* send a reset to the SCSI LUN which the command was sent to */ |
| 1610 | rc = sendcmd(CCISS_RESET_MSG, ctlr, NULL, 0, 2, 0, 0, | 1672 | rc = sendcmd_withirq(CCISS_RESET_MSG, ctlr, NULL, 0, 0, lunaddr, |
| 1611 | (unsigned char *) &cmd_in_trouble->Header.LUN.LunAddrBytes[0], | ||
| 1612 | TYPE_MSG); | 1673 | TYPE_MSG); |
| 1613 | /* sendcmd turned off interrupts on the board, turn 'em back on. */ | 1674 | if (rc == 0 && wait_for_device_to_become_ready(*c, lunaddr) == 0) |
| 1614 | (*c)->access.set_intr_mask(*c, CCISS_INTR_ON); | ||
| 1615 | if (rc == 0) | ||
| 1616 | return SUCCESS; | 1675 | return SUCCESS; |
| 1617 | printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr); | 1676 | printk(KERN_WARNING "cciss%d: resetting device failed.\n", ctlr); |
| 1618 | return FAILED; | 1677 | return FAILED; |
| @@ -1622,6 +1681,7 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd) | |||
| 1622 | { | 1681 | { |
| 1623 | int rc; | 1682 | int rc; |
| 1624 | CommandList_struct *cmd_to_abort; | 1683 | CommandList_struct *cmd_to_abort; |
| 1684 | unsigned char lunaddr[8]; | ||
| 1625 | ctlr_info_t **c; | 1685 | ctlr_info_t **c; |
| 1626 | int ctlr; | 1686 | int ctlr; |
| 1627 | 1687 | ||
| @@ -1636,12 +1696,9 @@ static int cciss_eh_abort_handler(struct scsi_cmnd *scsicmd) | |||
| 1636 | cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble; | 1696 | cmd_to_abort = (CommandList_struct *) scsicmd->host_scribble; |
| 1637 | if (cmd_to_abort == NULL) /* paranoia */ | 1697 | if (cmd_to_abort == NULL) /* paranoia */ |
| 1638 | return FAILED; | 1698 | return FAILED; |
| 1639 | rc = sendcmd(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag, | 1699 | memcpy(lunaddr, &cmd_to_abort->Header.LUN.LunAddrBytes[0], 8); |
| 1640 | 0, 2, 0, 0, | 1700 | rc = sendcmd_withirq(CCISS_ABORT_MSG, ctlr, &cmd_to_abort->Header.Tag, |
| 1641 | (unsigned char *) &cmd_to_abort->Header.LUN.LunAddrBytes[0], | 1701 | 0, 0, lunaddr, TYPE_MSG); |
| 1642 | TYPE_MSG); | ||
| 1643 | /* sendcmd turned off interrupts on the board, turn 'em back on. */ | ||
| 1644 | (*c)->access.set_intr_mask(*c, CCISS_INTR_ON); | ||
| 1645 | if (rc == 0) | 1702 | if (rc == 0) |
| 1646 | return SUCCESS; | 1703 | return SUCCESS; |
| 1647 | return FAILED; | 1704 | return FAILED; |
diff --git a/drivers/block/cpqarray.c b/drivers/block/cpqarray.c index ca268ca11159..44fa2018f6b0 100644 --- a/drivers/block/cpqarray.c +++ b/drivers/block/cpqarray.c | |||
| @@ -474,7 +474,7 @@ static int __init cpqarray_register_ctlr( int i, struct pci_dev *pdev) | |||
| 474 | disk->fops = &ida_fops; | 474 | disk->fops = &ida_fops; |
| 475 | if (j && !drv->nr_blks) | 475 | if (j && !drv->nr_blks) |
| 476 | continue; | 476 | continue; |
| 477 | blk_queue_hardsect_size(hba[i]->queue, drv->blk_size); | 477 | blk_queue_logical_block_size(hba[i]->queue, drv->blk_size); |
| 478 | set_capacity(disk, drv->nr_blks); | 478 | set_capacity(disk, drv->nr_blks); |
| 479 | disk->queue = hba[i]->queue; | 479 | disk->queue = hba[i]->queue; |
| 480 | disk->private_data = drv; | 480 | disk->private_data = drv; |
| @@ -903,7 +903,7 @@ static void do_ida_request(struct request_queue *q) | |||
| 903 | goto startio; | 903 | goto startio; |
| 904 | 904 | ||
| 905 | queue_next: | 905 | queue_next: |
| 906 | creq = elv_next_request(q); | 906 | creq = blk_peek_request(q); |
| 907 | if (!creq) | 907 | if (!creq) |
| 908 | goto startio; | 908 | goto startio; |
| 909 | 909 | ||
| @@ -912,17 +912,18 @@ queue_next: | |||
| 912 | if ((c = cmd_alloc(h,1)) == NULL) | 912 | if ((c = cmd_alloc(h,1)) == NULL) |
| 913 | goto startio; | 913 | goto startio; |
| 914 | 914 | ||
| 915 | blkdev_dequeue_request(creq); | 915 | blk_start_request(creq); |
| 916 | 916 | ||
| 917 | c->ctlr = h->ctlr; | 917 | c->ctlr = h->ctlr; |
| 918 | c->hdr.unit = (drv_info_t *)(creq->rq_disk->private_data) - h->drv; | 918 | c->hdr.unit = (drv_info_t *)(creq->rq_disk->private_data) - h->drv; |
| 919 | c->hdr.size = sizeof(rblk_t) >> 2; | 919 | c->hdr.size = sizeof(rblk_t) >> 2; |
| 920 | c->size += sizeof(rblk_t); | 920 | c->size += sizeof(rblk_t); |
| 921 | 921 | ||
| 922 | c->req.hdr.blk = creq->sector; | 922 | c->req.hdr.blk = blk_rq_pos(creq); |
| 923 | c->rq = creq; | 923 | c->rq = creq; |
| 924 | DBGPX( | 924 | DBGPX( |
| 925 | printk("sector=%d, nr_sectors=%d\n", creq->sector, creq->nr_sectors); | 925 | printk("sector=%d, nr_sectors=%u\n", |
| 926 | blk_rq_pos(creq), blk_rq_sectors(creq)); | ||
| 926 | ); | 927 | ); |
| 927 | sg_init_table(tmp_sg, SG_MAX); | 928 | sg_init_table(tmp_sg, SG_MAX); |
| 928 | seg = blk_rq_map_sg(q, creq, tmp_sg); | 929 | seg = blk_rq_map_sg(q, creq, tmp_sg); |
| @@ -940,9 +941,9 @@ DBGPX( | |||
| 940 | tmp_sg[i].offset, | 941 | tmp_sg[i].offset, |
| 941 | tmp_sg[i].length, dir); | 942 | tmp_sg[i].length, dir); |
| 942 | } | 943 | } |
| 943 | DBGPX( printk("Submitting %d sectors in %d segments\n", creq->nr_sectors, seg); ); | 944 | DBGPX( printk("Submitting %u sectors in %d segments\n", blk_rq_sectors(creq), seg); ); |
| 944 | c->req.hdr.sg_cnt = seg; | 945 | c->req.hdr.sg_cnt = seg; |
| 945 | c->req.hdr.blk_cnt = creq->nr_sectors; | 946 | c->req.hdr.blk_cnt = blk_rq_sectors(creq); |
| 946 | c->req.hdr.cmd = (rq_data_dir(creq) == READ) ? IDA_READ : IDA_WRITE; | 947 | c->req.hdr.cmd = (rq_data_dir(creq) == READ) ? IDA_READ : IDA_WRITE; |
| 947 | c->type = CMD_RWREQ; | 948 | c->type = CMD_RWREQ; |
| 948 | 949 | ||
| @@ -1024,8 +1025,7 @@ static inline void complete_command(cmdlist_t *cmd, int timeout) | |||
| 1024 | cmd->req.sg[i].size, ddir); | 1025 | cmd->req.sg[i].size, ddir); |
| 1025 | 1026 | ||
| 1026 | DBGPX(printk("Done with %p\n", rq);); | 1027 | DBGPX(printk("Done with %p\n", rq);); |
| 1027 | if (__blk_end_request(rq, error, blk_rq_bytes(rq))) | 1028 | __blk_end_request_all(rq, error); |
| 1028 | BUG(); | ||
| 1029 | } | 1029 | } |
| 1030 | 1030 | ||
| 1031 | /* | 1031 | /* |
| @@ -1546,7 +1546,7 @@ static int revalidate_allvol(ctlr_info_t *host) | |||
| 1546 | drv_info_t *drv = &host->drv[i]; | 1546 | drv_info_t *drv = &host->drv[i]; |
| 1547 | if (i && !drv->nr_blks) | 1547 | if (i && !drv->nr_blks) |
| 1548 | continue; | 1548 | continue; |
| 1549 | blk_queue_hardsect_size(host->queue, drv->blk_size); | 1549 | blk_queue_logical_block_size(host->queue, drv->blk_size); |
| 1550 | set_capacity(disk, drv->nr_blks); | 1550 | set_capacity(disk, drv->nr_blks); |
| 1551 | disk->queue = host->queue; | 1551 | disk->queue = host->queue; |
| 1552 | disk->private_data = drv; | 1552 | disk->private_data = drv; |
diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index 1300df6f1642..862b40c90181 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c | |||
| @@ -931,7 +931,7 @@ static inline void unlock_fdc(void) | |||
| 931 | del_timer(&fd_timeout); | 931 | del_timer(&fd_timeout); |
| 932 | cont = NULL; | 932 | cont = NULL; |
| 933 | clear_bit(0, &fdc_busy); | 933 | clear_bit(0, &fdc_busy); |
| 934 | if (elv_next_request(floppy_queue)) | 934 | if (current_req || blk_peek_request(floppy_queue)) |
| 935 | do_fd_request(floppy_queue); | 935 | do_fd_request(floppy_queue); |
| 936 | spin_unlock_irqrestore(&floppy_lock, flags); | 936 | spin_unlock_irqrestore(&floppy_lock, flags); |
| 937 | wake_up(&fdc_wait); | 937 | wake_up(&fdc_wait); |
| @@ -2303,7 +2303,7 @@ static void floppy_end_request(struct request *req, int error) | |||
| 2303 | 2303 | ||
| 2304 | /* current_count_sectors can be zero if transfer failed */ | 2304 | /* current_count_sectors can be zero if transfer failed */ |
| 2305 | if (error) | 2305 | if (error) |
| 2306 | nr_sectors = req->current_nr_sectors; | 2306 | nr_sectors = blk_rq_cur_sectors(req); |
| 2307 | if (__blk_end_request(req, error, nr_sectors << 9)) | 2307 | if (__blk_end_request(req, error, nr_sectors << 9)) |
| 2308 | return; | 2308 | return; |
| 2309 | 2309 | ||
| @@ -2332,7 +2332,7 @@ static void request_done(int uptodate) | |||
| 2332 | if (uptodate) { | 2332 | if (uptodate) { |
| 2333 | /* maintain values for invalidation on geometry | 2333 | /* maintain values for invalidation on geometry |
| 2334 | * change */ | 2334 | * change */ |
| 2335 | block = current_count_sectors + req->sector; | 2335 | block = current_count_sectors + blk_rq_pos(req); |
| 2336 | INFBOUND(DRS->maxblock, block); | 2336 | INFBOUND(DRS->maxblock, block); |
| 2337 | if (block > _floppy->sect) | 2337 | if (block > _floppy->sect) |
| 2338 | DRS->maxtrack = 1; | 2338 | DRS->maxtrack = 1; |
| @@ -2346,10 +2346,10 @@ static void request_done(int uptodate) | |||
| 2346 | /* record write error information */ | 2346 | /* record write error information */ |
| 2347 | DRWE->write_errors++; | 2347 | DRWE->write_errors++; |
| 2348 | if (DRWE->write_errors == 1) { | 2348 | if (DRWE->write_errors == 1) { |
| 2349 | DRWE->first_error_sector = req->sector; | 2349 | DRWE->first_error_sector = blk_rq_pos(req); |
| 2350 | DRWE->first_error_generation = DRS->generation; | 2350 | DRWE->first_error_generation = DRS->generation; |
| 2351 | } | 2351 | } |
| 2352 | DRWE->last_error_sector = req->sector; | 2352 | DRWE->last_error_sector = blk_rq_pos(req); |
| 2353 | DRWE->last_error_generation = DRS->generation; | 2353 | DRWE->last_error_generation = DRS->generation; |
| 2354 | } | 2354 | } |
| 2355 | spin_lock_irqsave(q->queue_lock, flags); | 2355 | spin_lock_irqsave(q->queue_lock, flags); |
| @@ -2503,24 +2503,23 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) | |||
| 2503 | 2503 | ||
| 2504 | max_sector = transfer_size(ssize, | 2504 | max_sector = transfer_size(ssize, |
| 2505 | min(max_sector, max_sector_2), | 2505 | min(max_sector, max_sector_2), |
| 2506 | current_req->nr_sectors); | 2506 | blk_rq_sectors(current_req)); |
| 2507 | 2507 | ||
| 2508 | if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE && | 2508 | if (current_count_sectors <= 0 && CT(COMMAND) == FD_WRITE && |
| 2509 | buffer_max > fsector_t + current_req->nr_sectors) | 2509 | buffer_max > fsector_t + blk_rq_sectors(current_req)) |
| 2510 | current_count_sectors = min_t(int, buffer_max - fsector_t, | 2510 | current_count_sectors = min_t(int, buffer_max - fsector_t, |
| 2511 | current_req->nr_sectors); | 2511 | blk_rq_sectors(current_req)); |
| 2512 | 2512 | ||
| 2513 | remaining = current_count_sectors << 9; | 2513 | remaining = current_count_sectors << 9; |
| 2514 | #ifdef FLOPPY_SANITY_CHECK | 2514 | #ifdef FLOPPY_SANITY_CHECK |
| 2515 | if ((remaining >> 9) > current_req->nr_sectors && | 2515 | if (remaining > blk_rq_bytes(current_req) && CT(COMMAND) == FD_WRITE) { |
| 2516 | CT(COMMAND) == FD_WRITE) { | ||
| 2517 | DPRINT("in copy buffer\n"); | 2516 | DPRINT("in copy buffer\n"); |
| 2518 | printk("current_count_sectors=%ld\n", current_count_sectors); | 2517 | printk("current_count_sectors=%ld\n", current_count_sectors); |
| 2519 | printk("remaining=%d\n", remaining >> 9); | 2518 | printk("remaining=%d\n", remaining >> 9); |
| 2520 | printk("current_req->nr_sectors=%ld\n", | 2519 | printk("current_req->nr_sectors=%u\n", |
| 2521 | current_req->nr_sectors); | 2520 | blk_rq_sectors(current_req)); |
| 2522 | printk("current_req->current_nr_sectors=%u\n", | 2521 | printk("current_req->current_nr_sectors=%u\n", |
| 2523 | current_req->current_nr_sectors); | 2522 | blk_rq_cur_sectors(current_req)); |
| 2524 | printk("max_sector=%d\n", max_sector); | 2523 | printk("max_sector=%d\n", max_sector); |
| 2525 | printk("ssize=%d\n", ssize); | 2524 | printk("ssize=%d\n", ssize); |
| 2526 | } | 2525 | } |
| @@ -2530,7 +2529,7 @@ static void copy_buffer(int ssize, int max_sector, int max_sector_2) | |||
| 2530 | 2529 | ||
| 2531 | dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9); | 2530 | dma_buffer = floppy_track_buffer + ((fsector_t - buffer_min) << 9); |
| 2532 | 2531 | ||
| 2533 | size = current_req->current_nr_sectors << 9; | 2532 | size = blk_rq_cur_bytes(current_req); |
| 2534 | 2533 | ||
| 2535 | rq_for_each_segment(bv, current_req, iter) { | 2534 | rq_for_each_segment(bv, current_req, iter) { |
| 2536 | if (!remaining) | 2535 | if (!remaining) |
| @@ -2648,10 +2647,10 @@ static int make_raw_rw_request(void) | |||
| 2648 | 2647 | ||
| 2649 | max_sector = _floppy->sect * _floppy->head; | 2648 | max_sector = _floppy->sect * _floppy->head; |
| 2650 | 2649 | ||
| 2651 | TRACK = (int)current_req->sector / max_sector; | 2650 | TRACK = (int)blk_rq_pos(current_req) / max_sector; |
| 2652 | fsector_t = (int)current_req->sector % max_sector; | 2651 | fsector_t = (int)blk_rq_pos(current_req) % max_sector; |
| 2653 | if (_floppy->track && TRACK >= _floppy->track) { | 2652 | if (_floppy->track && TRACK >= _floppy->track) { |
| 2654 | if (current_req->current_nr_sectors & 1) { | 2653 | if (blk_rq_cur_sectors(current_req) & 1) { |
| 2655 | current_count_sectors = 1; | 2654 | current_count_sectors = 1; |
| 2656 | return 1; | 2655 | return 1; |
| 2657 | } else | 2656 | } else |
| @@ -2669,7 +2668,7 @@ static int make_raw_rw_request(void) | |||
| 2669 | if (fsector_t >= max_sector) { | 2668 | if (fsector_t >= max_sector) { |
| 2670 | current_count_sectors = | 2669 | current_count_sectors = |
| 2671 | min_t(int, _floppy->sect - fsector_t, | 2670 | min_t(int, _floppy->sect - fsector_t, |
| 2672 | current_req->nr_sectors); | 2671 | blk_rq_sectors(current_req)); |
| 2673 | return 1; | 2672 | return 1; |
| 2674 | } | 2673 | } |
| 2675 | SIZECODE = 2; | 2674 | SIZECODE = 2; |
| @@ -2720,7 +2719,7 @@ static int make_raw_rw_request(void) | |||
| 2720 | 2719 | ||
| 2721 | in_sector_offset = (fsector_t % _floppy->sect) % ssize; | 2720 | in_sector_offset = (fsector_t % _floppy->sect) % ssize; |
| 2722 | aligned_sector_t = fsector_t - in_sector_offset; | 2721 | aligned_sector_t = fsector_t - in_sector_offset; |
| 2723 | max_size = current_req->nr_sectors; | 2722 | max_size = blk_rq_sectors(current_req); |
| 2724 | if ((raw_cmd->track == buffer_track) && | 2723 | if ((raw_cmd->track == buffer_track) && |
| 2725 | (current_drive == buffer_drive) && | 2724 | (current_drive == buffer_drive) && |
| 2726 | (fsector_t >= buffer_min) && (fsector_t < buffer_max)) { | 2725 | (fsector_t >= buffer_min) && (fsector_t < buffer_max)) { |
| @@ -2729,10 +2728,10 @@ static int make_raw_rw_request(void) | |||
| 2729 | copy_buffer(1, max_sector, buffer_max); | 2728 | copy_buffer(1, max_sector, buffer_max); |
| 2730 | return 1; | 2729 | return 1; |
| 2731 | } | 2730 | } |
| 2732 | } else if (in_sector_offset || current_req->nr_sectors < ssize) { | 2731 | } else if (in_sector_offset || blk_rq_sectors(current_req) < ssize) { |
| 2733 | if (CT(COMMAND) == FD_WRITE) { | 2732 | if (CT(COMMAND) == FD_WRITE) { |
| 2734 | if (fsector_t + current_req->nr_sectors > ssize && | 2733 | if (fsector_t + blk_rq_sectors(current_req) > ssize && |
| 2735 | fsector_t + current_req->nr_sectors < ssize + ssize) | 2734 | fsector_t + blk_rq_sectors(current_req) < ssize + ssize) |
| 2736 | max_size = ssize + ssize; | 2735 | max_size = ssize + ssize; |
| 2737 | else | 2736 | else |
| 2738 | max_size = ssize; | 2737 | max_size = ssize; |
| @@ -2776,7 +2775,7 @@ static int make_raw_rw_request(void) | |||
| 2776 | (indirect * 2 > direct * 3 && | 2775 | (indirect * 2 > direct * 3 && |
| 2777 | *errors < DP->max_errors.read_track && ((!probing | 2776 | *errors < DP->max_errors.read_track && ((!probing |
| 2778 | || (DP->read_track & (1 << DRS->probed_format)))))) { | 2777 | || (DP->read_track & (1 << DRS->probed_format)))))) { |
| 2779 | max_size = current_req->nr_sectors; | 2778 | max_size = blk_rq_sectors(current_req); |
| 2780 | } else { | 2779 | } else { |
| 2781 | raw_cmd->kernel_data = current_req->buffer; | 2780 | raw_cmd->kernel_data = current_req->buffer; |
| 2782 | raw_cmd->length = current_count_sectors << 9; | 2781 | raw_cmd->length = current_count_sectors << 9; |
| @@ -2801,7 +2800,7 @@ static int make_raw_rw_request(void) | |||
| 2801 | fsector_t > buffer_max || | 2800 | fsector_t > buffer_max || |
| 2802 | fsector_t < buffer_min || | 2801 | fsector_t < buffer_min || |
| 2803 | ((CT(COMMAND) == FD_READ || | 2802 | ((CT(COMMAND) == FD_READ || |
| 2804 | (!in_sector_offset && current_req->nr_sectors >= ssize)) && | 2803 | (!in_sector_offset && blk_rq_sectors(current_req) >= ssize)) && |
| 2805 | max_sector > 2 * max_buffer_sectors + buffer_min && | 2804 | max_sector > 2 * max_buffer_sectors + buffer_min && |
| 2806 | max_size + fsector_t > 2 * max_buffer_sectors + buffer_min) | 2805 | max_size + fsector_t > 2 * max_buffer_sectors + buffer_min) |
| 2807 | /* not enough space */ | 2806 | /* not enough space */ |
| @@ -2879,8 +2878,8 @@ static int make_raw_rw_request(void) | |||
| 2879 | printk("write\n"); | 2878 | printk("write\n"); |
| 2880 | return 0; | 2879 | return 0; |
| 2881 | } | 2880 | } |
| 2882 | } else if (raw_cmd->length > current_req->nr_sectors << 9 || | 2881 | } else if (raw_cmd->length > blk_rq_bytes(current_req) || |
| 2883 | current_count_sectors > current_req->nr_sectors) { | 2882 | current_count_sectors > blk_rq_sectors(current_req)) { |
| 2884 | DPRINT("buffer overrun in direct transfer\n"); | 2883 | DPRINT("buffer overrun in direct transfer\n"); |
| 2885 | return 0; | 2884 | return 0; |
| 2886 | } else if (raw_cmd->length < current_count_sectors << 9) { | 2885 | } else if (raw_cmd->length < current_count_sectors << 9) { |
| @@ -2913,7 +2912,7 @@ static void redo_fd_request(void) | |||
| 2913 | struct request *req; | 2912 | struct request *req; |
| 2914 | 2913 | ||
| 2915 | spin_lock_irq(floppy_queue->queue_lock); | 2914 | spin_lock_irq(floppy_queue->queue_lock); |
| 2916 | req = elv_next_request(floppy_queue); | 2915 | req = blk_fetch_request(floppy_queue); |
| 2917 | spin_unlock_irq(floppy_queue->queue_lock); | 2916 | spin_unlock_irq(floppy_queue->queue_lock); |
| 2918 | if (!req) { | 2917 | if (!req) { |
| 2919 | do_floppy = NULL; | 2918 | do_floppy = NULL; |
| @@ -2990,8 +2989,9 @@ static void do_fd_request(struct request_queue * q) | |||
| 2990 | if (usage_count == 0) { | 2989 | if (usage_count == 0) { |
| 2991 | printk("warning: usage count=0, current_req=%p exiting\n", | 2990 | printk("warning: usage count=0, current_req=%p exiting\n", |
| 2992 | current_req); | 2991 | current_req); |
| 2993 | printk("sect=%ld type=%x flags=%x\n", (long)current_req->sector, | 2992 | printk("sect=%ld type=%x flags=%x\n", |
| 2994 | current_req->cmd_type, current_req->cmd_flags); | 2993 | (long)blk_rq_pos(current_req), current_req->cmd_type, |
| 2994 | current_req->cmd_flags); | ||
| 2995 | return; | 2995 | return; |
| 2996 | } | 2996 | } |
| 2997 | if (test_bit(0, &fdc_busy)) { | 2997 | if (test_bit(0, &fdc_busy)) { |
| @@ -4148,6 +4148,24 @@ static void floppy_device_release(struct device *dev) | |||
| 4148 | { | 4148 | { |
| 4149 | } | 4149 | } |
| 4150 | 4150 | ||
| 4151 | static int floppy_resume(struct platform_device *dev) | ||
| 4152 | { | ||
| 4153 | int fdc; | ||
| 4154 | |||
| 4155 | for (fdc = 0; fdc < N_FDC; fdc++) | ||
| 4156 | if (FDCS->address != -1) | ||
| 4157 | user_reset_fdc(-1, FD_RESET_ALWAYS, 0); | ||
| 4158 | |||
| 4159 | return 0; | ||
| 4160 | } | ||
| 4161 | |||
| 4162 | static struct platform_driver floppy_driver = { | ||
| 4163 | .resume = floppy_resume, | ||
| 4164 | .driver = { | ||
| 4165 | .name = "floppy", | ||
| 4166 | }, | ||
| 4167 | }; | ||
| 4168 | |||
| 4151 | static struct platform_device floppy_device[N_DRIVE]; | 4169 | static struct platform_device floppy_device[N_DRIVE]; |
| 4152 | 4170 | ||
| 4153 | static struct kobject *floppy_find(dev_t dev, int *part, void *data) | 4171 | static struct kobject *floppy_find(dev_t dev, int *part, void *data) |
| @@ -4196,10 +4214,14 @@ static int __init floppy_init(void) | |||
| 4196 | if (err) | 4214 | if (err) |
| 4197 | goto out_put_disk; | 4215 | goto out_put_disk; |
| 4198 | 4216 | ||
| 4217 | err = platform_driver_register(&floppy_driver); | ||
| 4218 | if (err) | ||
| 4219 | goto out_unreg_blkdev; | ||
| 4220 | |||
| 4199 | floppy_queue = blk_init_queue(do_fd_request, &floppy_lock); | 4221 | floppy_queue = blk_init_queue(do_fd_request, &floppy_lock); |
| 4200 | if (!floppy_queue) { | 4222 | if (!floppy_queue) { |
| 4201 | err = -ENOMEM; | 4223 | err = -ENOMEM; |
| 4202 | goto out_unreg_blkdev; | 4224 | goto out_unreg_driver; |
| 4203 | } | 4225 | } |
| 4204 | blk_queue_max_sectors(floppy_queue, 64); | 4226 | blk_queue_max_sectors(floppy_queue, 64); |
| 4205 | 4227 | ||
| @@ -4346,6 +4368,8 @@ out_flush_work: | |||
| 4346 | out_unreg_region: | 4368 | out_unreg_region: |
| 4347 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); | 4369 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); |
| 4348 | blk_cleanup_queue(floppy_queue); | 4370 | blk_cleanup_queue(floppy_queue); |
| 4371 | out_unreg_driver: | ||
| 4372 | platform_driver_unregister(&floppy_driver); | ||
| 4349 | out_unreg_blkdev: | 4373 | out_unreg_blkdev: |
| 4350 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 4374 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
| 4351 | out_put_disk: | 4375 | out_put_disk: |
| @@ -4566,6 +4590,7 @@ static void __exit floppy_module_exit(void) | |||
| 4566 | 4590 | ||
| 4567 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); | 4591 | blk_unregister_region(MKDEV(FLOPPY_MAJOR, 0), 256); |
| 4568 | unregister_blkdev(FLOPPY_MAJOR, "fd"); | 4592 | unregister_blkdev(FLOPPY_MAJOR, "fd"); |
| 4593 | platform_driver_unregister(&floppy_driver); | ||
| 4569 | 4594 | ||
| 4570 | for (drive = 0; drive < N_DRIVE; drive++) { | 4595 | for (drive = 0; drive < N_DRIVE; drive++) { |
| 4571 | del_timer_sync(&motor_off_timer[drive]); | 4596 | del_timer_sync(&motor_off_timer[drive]); |
diff --git a/drivers/block/hd.c b/drivers/block/hd.c index baaa9e486e50..f65b3f369eb0 100644 --- a/drivers/block/hd.c +++ b/drivers/block/hd.c | |||
| @@ -98,10 +98,9 @@ | |||
| 98 | 98 | ||
| 99 | static DEFINE_SPINLOCK(hd_lock); | 99 | static DEFINE_SPINLOCK(hd_lock); |
| 100 | static struct request_queue *hd_queue; | 100 | static struct request_queue *hd_queue; |
| 101 | static struct request *hd_req; | ||
| 101 | 102 | ||
| 102 | #define MAJOR_NR HD_MAJOR | 103 | #define MAJOR_NR HD_MAJOR |
| 103 | #define QUEUE (hd_queue) | ||
| 104 | #define CURRENT elv_next_request(hd_queue) | ||
| 105 | 104 | ||
| 106 | #define TIMEOUT_VALUE (6*HZ) | 105 | #define TIMEOUT_VALUE (6*HZ) |
| 107 | #define HD_DELAY 0 | 106 | #define HD_DELAY 0 |
| @@ -195,11 +194,24 @@ static void __init hd_setup(char *str, int *ints) | |||
| 195 | NR_HD = hdind+1; | 194 | NR_HD = hdind+1; |
| 196 | } | 195 | } |
| 197 | 196 | ||
| 197 | static bool hd_end_request(int err, unsigned int bytes) | ||
| 198 | { | ||
| 199 | if (__blk_end_request(hd_req, err, bytes)) | ||
| 200 | return true; | ||
| 201 | hd_req = NULL; | ||
| 202 | return false; | ||
| 203 | } | ||
| 204 | |||
| 205 | static bool hd_end_request_cur(int err) | ||
| 206 | { | ||
| 207 | return hd_end_request(err, blk_rq_cur_bytes(hd_req)); | ||
| 208 | } | ||
| 209 | |||
| 198 | static void dump_status(const char *msg, unsigned int stat) | 210 | static void dump_status(const char *msg, unsigned int stat) |
| 199 | { | 211 | { |
| 200 | char *name = "hd?"; | 212 | char *name = "hd?"; |
| 201 | if (CURRENT) | 213 | if (hd_req) |
| 202 | name = CURRENT->rq_disk->disk_name; | 214 | name = hd_req->rq_disk->disk_name; |
| 203 | 215 | ||
| 204 | #ifdef VERBOSE_ERRORS | 216 | #ifdef VERBOSE_ERRORS |
| 205 | printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); | 217 | printk("%s: %s: status=0x%02x { ", name, msg, stat & 0xff); |
| @@ -227,8 +239,8 @@ static void dump_status(const char *msg, unsigned int stat) | |||
| 227 | if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { | 239 | if (hd_error & (BBD_ERR|ECC_ERR|ID_ERR|MARK_ERR)) { |
| 228 | printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), | 240 | printk(", CHS=%d/%d/%d", (inb(HD_HCYL)<<8) + inb(HD_LCYL), |
| 229 | inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); | 241 | inb(HD_CURRENT) & 0xf, inb(HD_SECTOR)); |
| 230 | if (CURRENT) | 242 | if (hd_req) |
| 231 | printk(", sector=%ld", CURRENT->sector); | 243 | printk(", sector=%ld", blk_rq_pos(hd_req)); |
| 232 | } | 244 | } |
| 233 | printk("\n"); | 245 | printk("\n"); |
| 234 | } | 246 | } |
| @@ -406,11 +418,12 @@ static void unexpected_hd_interrupt(void) | |||
| 406 | */ | 418 | */ |
| 407 | static void bad_rw_intr(void) | 419 | static void bad_rw_intr(void) |
| 408 | { | 420 | { |
| 409 | struct request *req = CURRENT; | 421 | struct request *req = hd_req; |
| 422 | |||
| 410 | if (req != NULL) { | 423 | if (req != NULL) { |
| 411 | struct hd_i_struct *disk = req->rq_disk->private_data; | 424 | struct hd_i_struct *disk = req->rq_disk->private_data; |
| 412 | if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { | 425 | if (++req->errors >= MAX_ERRORS || (hd_error & BBD_ERR)) { |
| 413 | end_request(req, 0); | 426 | hd_end_request_cur(-EIO); |
| 414 | disk->special_op = disk->recalibrate = 1; | 427 | disk->special_op = disk->recalibrate = 1; |
| 415 | } else if (req->errors % RESET_FREQ == 0) | 428 | } else if (req->errors % RESET_FREQ == 0) |
| 416 | reset = 1; | 429 | reset = 1; |
| @@ -452,37 +465,30 @@ static void read_intr(void) | |||
| 452 | bad_rw_intr(); | 465 | bad_rw_intr(); |
| 453 | hd_request(); | 466 | hd_request(); |
| 454 | return; | 467 | return; |
| 468 | |||
| 455 | ok_to_read: | 469 | ok_to_read: |
| 456 | req = CURRENT; | 470 | req = hd_req; |
| 457 | insw(HD_DATA, req->buffer, 256); | 471 | insw(HD_DATA, req->buffer, 256); |
| 458 | req->sector++; | ||
| 459 | req->buffer += 512; | ||
| 460 | req->errors = 0; | ||
| 461 | i = --req->nr_sectors; | ||
| 462 | --req->current_nr_sectors; | ||
| 463 | #ifdef DEBUG | 472 | #ifdef DEBUG |
| 464 | printk("%s: read: sector %ld, remaining = %ld, buffer=%p\n", | 473 | printk("%s: read: sector %ld, remaining = %u, buffer=%p\n", |
| 465 | req->rq_disk->disk_name, req->sector, req->nr_sectors, | 474 | req->rq_disk->disk_name, blk_rq_pos(req) + 1, |
| 466 | req->buffer+512); | 475 | blk_rq_sectors(req) - 1, req->buffer+512); |
| 467 | #endif | 476 | #endif |
| 468 | if (req->current_nr_sectors <= 0) | 477 | if (hd_end_request(0, 512)) { |
| 469 | end_request(req, 1); | ||
| 470 | if (i > 0) { | ||
| 471 | SET_HANDLER(&read_intr); | 478 | SET_HANDLER(&read_intr); |
| 472 | return; | 479 | return; |
| 473 | } | 480 | } |
| 481 | |||
| 474 | (void) inb_p(HD_STATUS); | 482 | (void) inb_p(HD_STATUS); |
| 475 | #if (HD_DELAY > 0) | 483 | #if (HD_DELAY > 0) |
| 476 | last_req = read_timer(); | 484 | last_req = read_timer(); |
| 477 | #endif | 485 | #endif |
| 478 | if (elv_next_request(QUEUE)) | 486 | hd_request(); |
| 479 | hd_request(); | ||
| 480 | return; | ||
| 481 | } | 487 | } |
| 482 | 488 | ||
| 483 | static void write_intr(void) | 489 | static void write_intr(void) |
| 484 | { | 490 | { |
| 485 | struct request *req = CURRENT; | 491 | struct request *req = hd_req; |
| 486 | int i; | 492 | int i; |
| 487 | int retries = 100000; | 493 | int retries = 100000; |
| 488 | 494 | ||
| @@ -492,30 +498,25 @@ static void write_intr(void) | |||
| 492 | continue; | 498 | continue; |
| 493 | if (!OK_STATUS(i)) | 499 | if (!OK_STATUS(i)) |
| 494 | break; | 500 | break; |
| 495 | if ((req->nr_sectors <= 1) || (i & DRQ_STAT)) | 501 | if ((blk_rq_sectors(req) <= 1) || (i & DRQ_STAT)) |
| 496 | goto ok_to_write; | 502 | goto ok_to_write; |
| 497 | } while (--retries > 0); | 503 | } while (--retries > 0); |
| 498 | dump_status("write_intr", i); | 504 | dump_status("write_intr", i); |
| 499 | bad_rw_intr(); | 505 | bad_rw_intr(); |
| 500 | hd_request(); | 506 | hd_request(); |
| 501 | return; | 507 | return; |
| 508 | |||
| 502 | ok_to_write: | 509 | ok_to_write: |
| 503 | req->sector++; | 510 | if (hd_end_request(0, 512)) { |
| 504 | i = --req->nr_sectors; | ||
| 505 | --req->current_nr_sectors; | ||
| 506 | req->buffer += 512; | ||
| 507 | if (!i || (req->bio && req->current_nr_sectors <= 0)) | ||
| 508 | end_request(req, 1); | ||
| 509 | if (i > 0) { | ||
| 510 | SET_HANDLER(&write_intr); | 511 | SET_HANDLER(&write_intr); |
| 511 | outsw(HD_DATA, req->buffer, 256); | 512 | outsw(HD_DATA, req->buffer, 256); |
| 512 | } else { | 513 | return; |
| 514 | } | ||
| 515 | |||
| 513 | #if (HD_DELAY > 0) | 516 | #if (HD_DELAY > 0) |
| 514 | last_req = read_timer(); | 517 | last_req = read_timer(); |
| 515 | #endif | 518 | #endif |
| 516 | hd_request(); | 519 | hd_request(); |
| 517 | } | ||
| 518 | return; | ||
| 519 | } | 520 | } |
| 520 | 521 | ||
| 521 | static void recal_intr(void) | 522 | static void recal_intr(void) |
| @@ -537,18 +538,18 @@ static void hd_times_out(unsigned long dummy) | |||
| 537 | 538 | ||
| 538 | do_hd = NULL; | 539 | do_hd = NULL; |
| 539 | 540 | ||
| 540 | if (!CURRENT) | 541 | if (!hd_req) |
| 541 | return; | 542 | return; |
| 542 | 543 | ||
| 543 | spin_lock_irq(hd_queue->queue_lock); | 544 | spin_lock_irq(hd_queue->queue_lock); |
| 544 | reset = 1; | 545 | reset = 1; |
| 545 | name = CURRENT->rq_disk->disk_name; | 546 | name = hd_req->rq_disk->disk_name; |
| 546 | printk("%s: timeout\n", name); | 547 | printk("%s: timeout\n", name); |
| 547 | if (++CURRENT->errors >= MAX_ERRORS) { | 548 | if (++hd_req->errors >= MAX_ERRORS) { |
| 548 | #ifdef DEBUG | 549 | #ifdef DEBUG |
| 549 | printk("%s: too many errors\n", name); | 550 | printk("%s: too many errors\n", name); |
| 550 | #endif | 551 | #endif |
| 551 | end_request(CURRENT, 0); | 552 | hd_end_request_cur(-EIO); |
| 552 | } | 553 | } |
| 553 | hd_request(); | 554 | hd_request(); |
| 554 | spin_unlock_irq(hd_queue->queue_lock); | 555 | spin_unlock_irq(hd_queue->queue_lock); |
| @@ -563,7 +564,7 @@ static int do_special_op(struct hd_i_struct *disk, struct request *req) | |||
| 563 | } | 564 | } |
| 564 | if (disk->head > 16) { | 565 | if (disk->head > 16) { |
| 565 | printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); | 566 | printk("%s: cannot handle device with more than 16 heads - giving up\n", req->rq_disk->disk_name); |
| 566 | end_request(req, 0); | 567 | hd_end_request_cur(-EIO); |
| 567 | } | 568 | } |
| 568 | disk->special_op = 0; | 569 | disk->special_op = 0; |
| 569 | return 1; | 570 | return 1; |
| @@ -590,24 +591,27 @@ static void hd_request(void) | |||
| 590 | repeat: | 591 | repeat: |
| 591 | del_timer(&device_timer); | 592 | del_timer(&device_timer); |
| 592 | 593 | ||
| 593 | req = CURRENT; | 594 | if (!hd_req) { |
| 594 | if (!req) { | 595 | hd_req = blk_fetch_request(hd_queue); |
| 595 | do_hd = NULL; | 596 | if (!hd_req) { |
| 596 | return; | 597 | do_hd = NULL; |
| 598 | return; | ||
| 599 | } | ||
| 597 | } | 600 | } |
| 601 | req = hd_req; | ||
| 598 | 602 | ||
| 599 | if (reset) { | 603 | if (reset) { |
| 600 | reset_hd(); | 604 | reset_hd(); |
| 601 | return; | 605 | return; |
| 602 | } | 606 | } |
| 603 | disk = req->rq_disk->private_data; | 607 | disk = req->rq_disk->private_data; |
| 604 | block = req->sector; | 608 | block = blk_rq_pos(req); |
| 605 | nsect = req->nr_sectors; | 609 | nsect = blk_rq_sectors(req); |
| 606 | if (block >= get_capacity(req->rq_disk) || | 610 | if (block >= get_capacity(req->rq_disk) || |
| 607 | ((block+nsect) > get_capacity(req->rq_disk))) { | 611 | ((block+nsect) > get_capacity(req->rq_disk))) { |
| 608 | printk("%s: bad access: block=%d, count=%d\n", | 612 | printk("%s: bad access: block=%d, count=%d\n", |
| 609 | req->rq_disk->disk_name, block, nsect); | 613 | req->rq_disk->disk_name, block, nsect); |
| 610 | end_request(req, 0); | 614 | hd_end_request_cur(-EIO); |
| 611 | goto repeat; | 615 | goto repeat; |
| 612 | } | 616 | } |
| 613 | 617 | ||
| @@ -647,7 +651,7 @@ repeat: | |||
| 647 | break; | 651 | break; |
| 648 | default: | 652 | default: |
| 649 | printk("unknown hd-command\n"); | 653 | printk("unknown hd-command\n"); |
| 650 | end_request(req, 0); | 654 | hd_end_request_cur(-EIO); |
| 651 | break; | 655 | break; |
| 652 | } | 656 | } |
| 653 | } | 657 | } |
| @@ -720,7 +724,7 @@ static int __init hd_init(void) | |||
| 720 | blk_queue_max_sectors(hd_queue, 255); | 724 | blk_queue_max_sectors(hd_queue, 255); |
| 721 | init_timer(&device_timer); | 725 | init_timer(&device_timer); |
| 722 | device_timer.function = hd_times_out; | 726 | device_timer.function = hd_times_out; |
| 723 | blk_queue_hardsect_size(hd_queue, 512); | 727 | blk_queue_logical_block_size(hd_queue, 512); |
| 724 | 728 | ||
| 725 | if (!NR_HD) { | 729 | if (!NR_HD) { |
| 726 | /* | 730 | /* |
diff --git a/drivers/block/loop.c b/drivers/block/loop.c index ddae80825899..801f4ab83302 100644 --- a/drivers/block/loop.c +++ b/drivers/block/loop.c | |||
| @@ -511,11 +511,7 @@ out: | |||
| 511 | */ | 511 | */ |
| 512 | static void loop_add_bio(struct loop_device *lo, struct bio *bio) | 512 | static void loop_add_bio(struct loop_device *lo, struct bio *bio) |
| 513 | { | 513 | { |
| 514 | if (lo->lo_biotail) { | 514 | bio_list_add(&lo->lo_bio_list, bio); |
| 515 | lo->lo_biotail->bi_next = bio; | ||
| 516 | lo->lo_biotail = bio; | ||
| 517 | } else | ||
| 518 | lo->lo_bio = lo->lo_biotail = bio; | ||
| 519 | } | 515 | } |
| 520 | 516 | ||
| 521 | /* | 517 | /* |
| @@ -523,16 +519,7 @@ static void loop_add_bio(struct loop_device *lo, struct bio *bio) | |||
| 523 | */ | 519 | */ |
| 524 | static struct bio *loop_get_bio(struct loop_device *lo) | 520 | static struct bio *loop_get_bio(struct loop_device *lo) |
| 525 | { | 521 | { |
| 526 | struct bio *bio; | 522 | return bio_list_pop(&lo->lo_bio_list); |
| 527 | |||
| 528 | if ((bio = lo->lo_bio)) { | ||
| 529 | if (bio == lo->lo_biotail) | ||
| 530 | lo->lo_biotail = NULL; | ||
| 531 | lo->lo_bio = bio->bi_next; | ||
| 532 | bio->bi_next = NULL; | ||
| 533 | } | ||
| 534 | |||
| 535 | return bio; | ||
| 536 | } | 523 | } |
| 537 | 524 | ||
| 538 | static int loop_make_request(struct request_queue *q, struct bio *old_bio) | 525 | static int loop_make_request(struct request_queue *q, struct bio *old_bio) |
| @@ -609,12 +596,13 @@ static int loop_thread(void *data) | |||
| 609 | 596 | ||
| 610 | set_user_nice(current, -20); | 597 | set_user_nice(current, -20); |
| 611 | 598 | ||
| 612 | while (!kthread_should_stop() || lo->lo_bio) { | 599 | while (!kthread_should_stop() || !bio_list_empty(&lo->lo_bio_list)) { |
| 613 | 600 | ||
| 614 | wait_event_interruptible(lo->lo_event, | 601 | wait_event_interruptible(lo->lo_event, |
| 615 | lo->lo_bio || kthread_should_stop()); | 602 | !bio_list_empty(&lo->lo_bio_list) || |
| 603 | kthread_should_stop()); | ||
| 616 | 604 | ||
| 617 | if (!lo->lo_bio) | 605 | if (bio_list_empty(&lo->lo_bio_list)) |
| 618 | continue; | 606 | continue; |
| 619 | spin_lock_irq(&lo->lo_lock); | 607 | spin_lock_irq(&lo->lo_lock); |
| 620 | bio = loop_get_bio(lo); | 608 | bio = loop_get_bio(lo); |
| @@ -721,10 +709,6 @@ static int loop_change_fd(struct loop_device *lo, struct block_device *bdev, | |||
| 721 | if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) | 709 | if (!S_ISREG(inode->i_mode) && !S_ISBLK(inode->i_mode)) |
| 722 | goto out_putf; | 710 | goto out_putf; |
| 723 | 711 | ||
| 724 | /* new backing store needs to support loop (eg splice_read) */ | ||
| 725 | if (!inode->i_fop->splice_read) | ||
| 726 | goto out_putf; | ||
| 727 | |||
| 728 | /* size of the new backing store needs to be the same */ | 712 | /* size of the new backing store needs to be the same */ |
| 729 | if (get_loop_size(lo, file) != get_loop_size(lo, old_file)) | 713 | if (get_loop_size(lo, file) != get_loop_size(lo, old_file)) |
| 730 | goto out_putf; | 714 | goto out_putf; |
| @@ -800,12 +784,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, | |||
| 800 | error = -EINVAL; | 784 | error = -EINVAL; |
| 801 | if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) { | 785 | if (S_ISREG(inode->i_mode) || S_ISBLK(inode->i_mode)) { |
| 802 | const struct address_space_operations *aops = mapping->a_ops; | 786 | const struct address_space_operations *aops = mapping->a_ops; |
| 803 | /* | 787 | |
| 804 | * If we can't read - sorry. If we only can't write - well, | ||
| 805 | * it's going to be read-only. | ||
| 806 | */ | ||
| 807 | if (!file->f_op->splice_read) | ||
| 808 | goto out_putf; | ||
| 809 | if (aops->write_begin) | 788 | if (aops->write_begin) |
| 810 | lo_flags |= LO_FLAGS_USE_AOPS; | 789 | lo_flags |= LO_FLAGS_USE_AOPS; |
| 811 | if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write) | 790 | if (!(lo_flags & LO_FLAGS_USE_AOPS) && !file->f_op->write) |
| @@ -841,7 +820,7 @@ static int loop_set_fd(struct loop_device *lo, fmode_t mode, | |||
| 841 | lo->old_gfp_mask = mapping_gfp_mask(mapping); | 820 | lo->old_gfp_mask = mapping_gfp_mask(mapping); |
| 842 | mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); | 821 | mapping_set_gfp_mask(mapping, lo->old_gfp_mask & ~(__GFP_IO|__GFP_FS)); |
| 843 | 822 | ||
| 844 | lo->lo_bio = lo->lo_biotail = NULL; | 823 | bio_list_init(&lo->lo_bio_list); |
| 845 | 824 | ||
| 846 | /* | 825 | /* |
| 847 | * set queue make_request_fn, and add limits based on lower level | 826 | * set queue make_request_fn, and add limits based on lower level |
diff --git a/drivers/block/mg_disk.c b/drivers/block/mg_disk.c index f3898353d0a8..60de5a01e71e 100644 --- a/drivers/block/mg_disk.c +++ b/drivers/block/mg_disk.c | |||
| @@ -17,71 +17,220 @@ | |||
| 17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
| 18 | #include <linux/blkdev.h> | 18 | #include <linux/blkdev.h> |
| 19 | #include <linux/hdreg.h> | 19 | #include <linux/hdreg.h> |
| 20 | #include <linux/libata.h> | 20 | #include <linux/ata.h> |
| 21 | #include <linux/interrupt.h> | 21 | #include <linux/interrupt.h> |
| 22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
| 23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
| 24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
| 25 | #include <linux/mg_disk.h> | ||
| 26 | 25 | ||
| 27 | #define MG_RES_SEC (CONFIG_MG_DISK_RES << 1) | 26 | #define MG_RES_SEC (CONFIG_MG_DISK_RES << 1) |
| 28 | 27 | ||
| 28 | /* name for block device */ | ||
| 29 | #define MG_DISK_NAME "mgd" | ||
| 30 | /* name for platform device */ | ||
| 31 | #define MG_DEV_NAME "mg_disk" | ||
| 32 | |||
| 33 | #define MG_DISK_MAJ 0 | ||
| 34 | #define MG_DISK_MAX_PART 16 | ||
| 35 | #define MG_SECTOR_SIZE 512 | ||
| 36 | #define MG_MAX_SECTS 256 | ||
| 37 | |||
| 38 | /* Register offsets */ | ||
| 39 | #define MG_BUFF_OFFSET 0x8000 | ||
| 40 | #define MG_STORAGE_BUFFER_SIZE 0x200 | ||
| 41 | #define MG_REG_OFFSET 0xC000 | ||
| 42 | #define MG_REG_FEATURE (MG_REG_OFFSET + 2) /* write case */ | ||
| 43 | #define MG_REG_ERROR (MG_REG_OFFSET + 2) /* read case */ | ||
| 44 | #define MG_REG_SECT_CNT (MG_REG_OFFSET + 4) | ||
| 45 | #define MG_REG_SECT_NUM (MG_REG_OFFSET + 6) | ||
| 46 | #define MG_REG_CYL_LOW (MG_REG_OFFSET + 8) | ||
| 47 | #define MG_REG_CYL_HIGH (MG_REG_OFFSET + 0xA) | ||
| 48 | #define MG_REG_DRV_HEAD (MG_REG_OFFSET + 0xC) | ||
| 49 | #define MG_REG_COMMAND (MG_REG_OFFSET + 0xE) /* write case */ | ||
| 50 | #define MG_REG_STATUS (MG_REG_OFFSET + 0xE) /* read case */ | ||
| 51 | #define MG_REG_DRV_CTRL (MG_REG_OFFSET + 0x10) | ||
| 52 | #define MG_REG_BURST_CTRL (MG_REG_OFFSET + 0x12) | ||
| 53 | |||
| 54 | /* handy status */ | ||
| 55 | #define MG_STAT_READY (ATA_DRDY | ATA_DSC) | ||
| 56 | #define MG_READY_OK(s) (((s) & (MG_STAT_READY | (ATA_BUSY | ATA_DF | \ | ||
| 57 | ATA_ERR))) == MG_STAT_READY) | ||
| 58 | |||
| 59 | /* error code for others */ | ||
| 60 | #define MG_ERR_NONE 0 | ||
| 61 | #define MG_ERR_TIMEOUT 0x100 | ||
| 62 | #define MG_ERR_INIT_STAT 0x101 | ||
| 63 | #define MG_ERR_TRANSLATION 0x102 | ||
| 64 | #define MG_ERR_CTRL_RST 0x103 | ||
| 65 | #define MG_ERR_INV_STAT 0x104 | ||
| 66 | #define MG_ERR_RSTOUT 0x105 | ||
| 67 | |||
| 68 | #define MG_MAX_ERRORS 6 /* Max read/write errors */ | ||
| 69 | |||
| 70 | /* command */ | ||
| 71 | #define MG_CMD_RD 0x20 | ||
| 72 | #define MG_CMD_WR 0x30 | ||
| 73 | #define MG_CMD_SLEEP 0x99 | ||
| 74 | #define MG_CMD_WAKEUP 0xC3 | ||
| 75 | #define MG_CMD_ID 0xEC | ||
| 76 | #define MG_CMD_WR_CONF 0x3C | ||
| 77 | #define MG_CMD_RD_CONF 0x40 | ||
| 78 | |||
| 79 | /* operation mode */ | ||
| 80 | #define MG_OP_CASCADE (1 << 0) | ||
| 81 | #define MG_OP_CASCADE_SYNC_RD (1 << 1) | ||
| 82 | #define MG_OP_CASCADE_SYNC_WR (1 << 2) | ||
| 83 | #define MG_OP_INTERLEAVE (1 << 3) | ||
| 84 | |||
| 85 | /* synchronous */ | ||
| 86 | #define MG_BURST_LAT_4 (3 << 4) | ||
| 87 | #define MG_BURST_LAT_5 (4 << 4) | ||
| 88 | #define MG_BURST_LAT_6 (5 << 4) | ||
| 89 | #define MG_BURST_LAT_7 (6 << 4) | ||
| 90 | #define MG_BURST_LAT_8 (7 << 4) | ||
| 91 | #define MG_BURST_LEN_4 (1 << 1) | ||
| 92 | #define MG_BURST_LEN_8 (2 << 1) | ||
| 93 | #define MG_BURST_LEN_16 (3 << 1) | ||
| 94 | #define MG_BURST_LEN_32 (4 << 1) | ||
| 95 | #define MG_BURST_LEN_CONT (0 << 1) | ||
| 96 | |||
| 97 | /* timeout value (unit: ms) */ | ||
| 98 | #define MG_TMAX_CONF_TO_CMD 1 | ||
| 99 | #define MG_TMAX_WAIT_RD_DRQ 10 | ||
| 100 | #define MG_TMAX_WAIT_WR_DRQ 500 | ||
| 101 | #define MG_TMAX_RST_TO_BUSY 10 | ||
| 102 | #define MG_TMAX_HDRST_TO_RDY 500 | ||
| 103 | #define MG_TMAX_SWRST_TO_RDY 500 | ||
| 104 | #define MG_TMAX_RSTOUT 3000 | ||
| 105 | |||
| 106 | /* device attribution */ | ||
| 107 | /* use mflash as boot device */ | ||
| 108 | #define MG_BOOT_DEV (1 << 0) | ||
| 109 | /* use mflash as storage device */ | ||
| 110 | #define MG_STORAGE_DEV (1 << 1) | ||
| 111 | /* same as MG_STORAGE_DEV, but bootloader already done reset sequence */ | ||
| 112 | #define MG_STORAGE_DEV_SKIP_RST (1 << 2) | ||
| 113 | |||
| 114 | #define MG_DEV_MASK (MG_BOOT_DEV | MG_STORAGE_DEV | MG_STORAGE_DEV_SKIP_RST) | ||
| 115 | |||
| 116 | /* names of GPIO resource */ | ||
| 117 | #define MG_RST_PIN "mg_rst" | ||
| 118 | /* except MG_BOOT_DEV, reset-out pin should be assigned */ | ||
| 119 | #define MG_RSTOUT_PIN "mg_rstout" | ||
| 120 | |||
| 121 | /* private driver data */ | ||
| 122 | struct mg_drv_data { | ||
| 123 | /* disk resource */ | ||
| 124 | u32 use_polling; | ||
| 125 | |||
| 126 | /* device attribution */ | ||
| 127 | u32 dev_attr; | ||
| 128 | |||
| 129 | /* internally used */ | ||
| 130 | struct mg_host *host; | ||
| 131 | }; | ||
| 132 | |||
| 133 | /* main structure for mflash driver */ | ||
| 134 | struct mg_host { | ||
| 135 | struct device *dev; | ||
| 136 | |||
| 137 | struct request_queue *breq; | ||
| 138 | struct request *req; | ||
| 139 | spinlock_t lock; | ||
| 140 | struct gendisk *gd; | ||
| 141 | |||
| 142 | struct timer_list timer; | ||
| 143 | void (*mg_do_intr) (struct mg_host *); | ||
| 144 | |||
| 145 | u16 id[ATA_ID_WORDS]; | ||
| 146 | |||
| 147 | u16 cyls; | ||
| 148 | u16 heads; | ||
| 149 | u16 sectors; | ||
| 150 | u32 n_sectors; | ||
| 151 | u32 nres_sectors; | ||
| 152 | |||
| 153 | void __iomem *dev_base; | ||
| 154 | unsigned int irq; | ||
| 155 | unsigned int rst; | ||
| 156 | unsigned int rstout; | ||
| 157 | |||
| 158 | u32 major; | ||
| 159 | u32 error; | ||
| 160 | }; | ||
| 161 | |||
| 162 | /* | ||
| 163 | * Debugging macro and defines | ||
| 164 | */ | ||
| 165 | #undef DO_MG_DEBUG | ||
| 166 | #ifdef DO_MG_DEBUG | ||
| 167 | # define MG_DBG(fmt, args...) \ | ||
| 168 | printk(KERN_DEBUG "%s:%d "fmt, __func__, __LINE__, ##args) | ||
| 169 | #else /* CONFIG_MG_DEBUG */ | ||
| 170 | # define MG_DBG(fmt, args...) do { } while (0) | ||
| 171 | #endif /* CONFIG_MG_DEBUG */ | ||
| 172 | |||
| 29 | static void mg_request(struct request_queue *); | 173 | static void mg_request(struct request_queue *); |
| 30 | 174 | ||
| 175 | static bool mg_end_request(struct mg_host *host, int err, unsigned int nr_bytes) | ||
| 176 | { | ||
| 177 | if (__blk_end_request(host->req, err, nr_bytes)) | ||
| 178 | return true; | ||
| 179 | |||
| 180 | host->req = NULL; | ||
| 181 | return false; | ||
| 182 | } | ||
| 183 | |||
| 184 | static bool mg_end_request_cur(struct mg_host *host, int err) | ||
| 185 | { | ||
| 186 | return mg_end_request(host, err, blk_rq_cur_bytes(host->req)); | ||
| 187 | } | ||
| 188 | |||
| 31 | static void mg_dump_status(const char *msg, unsigned int stat, | 189 | static void mg_dump_status(const char *msg, unsigned int stat, |
| 32 | struct mg_host *host) | 190 | struct mg_host *host) |
| 33 | { | 191 | { |
| 34 | char *name = MG_DISK_NAME; | 192 | char *name = MG_DISK_NAME; |
| 35 | struct request *req; | ||
| 36 | 193 | ||
| 37 | if (host->breq) { | 194 | if (host->req) |
| 38 | req = elv_next_request(host->breq); | 195 | name = host->req->rq_disk->disk_name; |
| 39 | if (req) | ||
| 40 | name = req->rq_disk->disk_name; | ||
| 41 | } | ||
| 42 | 196 | ||
| 43 | printk(KERN_ERR "%s: %s: status=0x%02x { ", name, msg, stat & 0xff); | 197 | printk(KERN_ERR "%s: %s: status=0x%02x { ", name, msg, stat & 0xff); |
| 44 | if (stat & MG_REG_STATUS_BIT_BUSY) | 198 | if (stat & ATA_BUSY) |
| 45 | printk("Busy "); | 199 | printk("Busy "); |
| 46 | if (stat & MG_REG_STATUS_BIT_READY) | 200 | if (stat & ATA_DRDY) |
| 47 | printk("DriveReady "); | 201 | printk("DriveReady "); |
| 48 | if (stat & MG_REG_STATUS_BIT_WRITE_FAULT) | 202 | if (stat & ATA_DF) |
| 49 | printk("WriteFault "); | 203 | printk("WriteFault "); |
| 50 | if (stat & MG_REG_STATUS_BIT_SEEK_DONE) | 204 | if (stat & ATA_DSC) |
| 51 | printk("SeekComplete "); | 205 | printk("SeekComplete "); |
| 52 | if (stat & MG_REG_STATUS_BIT_DATA_REQ) | 206 | if (stat & ATA_DRQ) |
| 53 | printk("DataRequest "); | 207 | printk("DataRequest "); |
| 54 | if (stat & MG_REG_STATUS_BIT_CORRECTED_ERROR) | 208 | if (stat & ATA_CORR) |
| 55 | printk("CorrectedError "); | 209 | printk("CorrectedError "); |
| 56 | if (stat & MG_REG_STATUS_BIT_ERROR) | 210 | if (stat & ATA_ERR) |
| 57 | printk("Error "); | 211 | printk("Error "); |
| 58 | printk("}\n"); | 212 | printk("}\n"); |
| 59 | if ((stat & MG_REG_STATUS_BIT_ERROR) == 0) { | 213 | if ((stat & ATA_ERR) == 0) { |
| 60 | host->error = 0; | 214 | host->error = 0; |
| 61 | } else { | 215 | } else { |
| 62 | host->error = inb((unsigned long)host->dev_base + MG_REG_ERROR); | 216 | host->error = inb((unsigned long)host->dev_base + MG_REG_ERROR); |
| 63 | printk(KERN_ERR "%s: %s: error=0x%02x { ", name, msg, | 217 | printk(KERN_ERR "%s: %s: error=0x%02x { ", name, msg, |
| 64 | host->error & 0xff); | 218 | host->error & 0xff); |
| 65 | if (host->error & MG_REG_ERR_BBK) | 219 | if (host->error & ATA_BBK) |
| 66 | printk("BadSector "); | 220 | printk("BadSector "); |
| 67 | if (host->error & MG_REG_ERR_UNC) | 221 | if (host->error & ATA_UNC) |
| 68 | printk("UncorrectableError "); | 222 | printk("UncorrectableError "); |
| 69 | if (host->error & MG_REG_ERR_IDNF) | 223 | if (host->error & ATA_IDNF) |
| 70 | printk("SectorIdNotFound "); | 224 | printk("SectorIdNotFound "); |
| 71 | if (host->error & MG_REG_ERR_ABRT) | 225 | if (host->error & ATA_ABORTED) |
| 72 | printk("DriveStatusError "); | 226 | printk("DriveStatusError "); |
| 73 | if (host->error & MG_REG_ERR_AMNF) | 227 | if (host->error & ATA_AMNF) |
| 74 | printk("AddrMarkNotFound "); | 228 | printk("AddrMarkNotFound "); |
| 75 | printk("}"); | 229 | printk("}"); |
| 76 | if (host->error & | 230 | if (host->error & (ATA_BBK | ATA_UNC | ATA_IDNF | ATA_AMNF)) { |
| 77 | (MG_REG_ERR_BBK | MG_REG_ERR_UNC | | 231 | if (host->req) |
| 78 | MG_REG_ERR_IDNF | MG_REG_ERR_AMNF)) { | 232 | printk(", sector=%u", |
| 79 | if (host->breq) { | 233 | (unsigned int)blk_rq_pos(host->req)); |
| 80 | req = elv_next_request(host->breq); | ||
| 81 | if (req) | ||
| 82 | printk(", sector=%u", (u32)req->sector); | ||
| 83 | } | ||
| 84 | |||
| 85 | } | 234 | } |
| 86 | printk("\n"); | 235 | printk("\n"); |
| 87 | } | 236 | } |
| @@ -100,12 +249,12 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec) | |||
| 100 | 249 | ||
| 101 | do { | 250 | do { |
| 102 | cur_jiffies = jiffies; | 251 | cur_jiffies = jiffies; |
| 103 | if (status & MG_REG_STATUS_BIT_BUSY) { | 252 | if (status & ATA_BUSY) { |
| 104 | if (expect == MG_REG_STATUS_BIT_BUSY) | 253 | if (expect == ATA_BUSY) |
| 105 | break; | 254 | break; |
| 106 | } else { | 255 | } else { |
| 107 | /* Check the error condition! */ | 256 | /* Check the error condition! */ |
| 108 | if (status & MG_REG_STATUS_BIT_ERROR) { | 257 | if (status & ATA_ERR) { |
| 109 | mg_dump_status("mg_wait", status, host); | 258 | mg_dump_status("mg_wait", status, host); |
| 110 | break; | 259 | break; |
| 111 | } | 260 | } |
| @@ -114,8 +263,8 @@ static unsigned int mg_wait(struct mg_host *host, u32 expect, u32 msec) | |||
| 114 | if (MG_READY_OK(status)) | 263 | if (MG_READY_OK(status)) |
| 115 | break; | 264 | break; |
| 116 | 265 | ||
| 117 | if (expect == MG_REG_STATUS_BIT_DATA_REQ) | 266 | if (expect == ATA_DRQ) |
| 118 | if (status & MG_REG_STATUS_BIT_DATA_REQ) | 267 | if (status & ATA_DRQ) |
| 119 | break; | 268 | break; |
| 120 | } | 269 | } |
| 121 | if (!msec) { | 270 | if (!msec) { |
| @@ -173,6 +322,42 @@ static irqreturn_t mg_irq(int irq, void *dev_id) | |||
| 173 | return IRQ_HANDLED; | 322 | return IRQ_HANDLED; |
| 174 | } | 323 | } |
| 175 | 324 | ||
| 325 | /* local copy of ata_id_string() */ | ||
| 326 | static void mg_id_string(const u16 *id, unsigned char *s, | ||
| 327 | unsigned int ofs, unsigned int len) | ||
| 328 | { | ||
| 329 | unsigned int c; | ||
| 330 | |||
| 331 | BUG_ON(len & 1); | ||
| 332 | |||
| 333 | while (len > 0) { | ||
| 334 | c = id[ofs] >> 8; | ||
| 335 | *s = c; | ||
| 336 | s++; | ||
| 337 | |||
| 338 | c = id[ofs] & 0xff; | ||
| 339 | *s = c; | ||
| 340 | s++; | ||
| 341 | |||
| 342 | ofs++; | ||
| 343 | len -= 2; | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | /* local copy of ata_id_c_string() */ | ||
| 348 | static void mg_id_c_string(const u16 *id, unsigned char *s, | ||
| 349 | unsigned int ofs, unsigned int len) | ||
| 350 | { | ||
| 351 | unsigned char *p; | ||
| 352 | |||
| 353 | mg_id_string(id, s, ofs, len - 1); | ||
| 354 | |||
| 355 | p = s + strnlen(s, len - 1); | ||
| 356 | while (p > s && p[-1] == ' ') | ||
| 357 | p--; | ||
| 358 | *p = '\0'; | ||
| 359 | } | ||
| 360 | |||
| 176 | static int mg_get_disk_id(struct mg_host *host) | 361 | static int mg_get_disk_id(struct mg_host *host) |
| 177 | { | 362 | { |
| 178 | u32 i; | 363 | u32 i; |
| @@ -184,12 +369,10 @@ static int mg_get_disk_id(struct mg_host *host) | |||
| 184 | char serial[ATA_ID_SERNO_LEN + 1]; | 369 | char serial[ATA_ID_SERNO_LEN + 1]; |
| 185 | 370 | ||
| 186 | if (!prv_data->use_polling) | 371 | if (!prv_data->use_polling) |
| 187 | outb(MG_REG_CTRL_INTR_DISABLE, | 372 | outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 188 | (unsigned long)host->dev_base + | ||
| 189 | MG_REG_DRV_CTRL); | ||
| 190 | 373 | ||
| 191 | outb(MG_CMD_ID, (unsigned long)host->dev_base + MG_REG_COMMAND); | 374 | outb(MG_CMD_ID, (unsigned long)host->dev_base + MG_REG_COMMAND); |
| 192 | err = mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, MG_TMAX_WAIT_RD_DRQ); | 375 | err = mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_RD_DRQ); |
| 193 | if (err) | 376 | if (err) |
| 194 | return err; | 377 | return err; |
| 195 | 378 | ||
| @@ -219,9 +402,9 @@ static int mg_get_disk_id(struct mg_host *host) | |||
| 219 | host->n_sectors -= host->nres_sectors; | 402 | host->n_sectors -= host->nres_sectors; |
| 220 | } | 403 | } |
| 221 | 404 | ||
| 222 | ata_id_c_string(id, fwrev, ATA_ID_FW_REV, sizeof(fwrev)); | 405 | mg_id_c_string(id, fwrev, ATA_ID_FW_REV, sizeof(fwrev)); |
| 223 | ata_id_c_string(id, model, ATA_ID_PROD, sizeof(model)); | 406 | mg_id_c_string(id, model, ATA_ID_PROD, sizeof(model)); |
| 224 | ata_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); | 407 | mg_id_c_string(id, serial, ATA_ID_SERNO, sizeof(serial)); |
| 225 | printk(KERN_INFO "mg_disk: model: %s\n", model); | 408 | printk(KERN_INFO "mg_disk: model: %s\n", model); |
| 226 | printk(KERN_INFO "mg_disk: firm: %.8s\n", fwrev); | 409 | printk(KERN_INFO "mg_disk: firm: %.8s\n", fwrev); |
| 227 | printk(KERN_INFO "mg_disk: serial: %s\n", serial); | 410 | printk(KERN_INFO "mg_disk: serial: %s\n", serial); |
| @@ -229,8 +412,7 @@ static int mg_get_disk_id(struct mg_host *host) | |||
| 229 | host->n_sectors, host->nres_sectors); | 412 | host->n_sectors, host->nres_sectors); |
| 230 | 413 | ||
| 231 | if (!prv_data->use_polling) | 414 | if (!prv_data->use_polling) |
| 232 | outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base + | 415 | outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 233 | MG_REG_DRV_CTRL); | ||
| 234 | 416 | ||
| 235 | return err; | 417 | return err; |
| 236 | } | 418 | } |
| @@ -244,7 +426,7 @@ static int mg_disk_init(struct mg_host *host) | |||
| 244 | 426 | ||
| 245 | /* hdd rst low */ | 427 | /* hdd rst low */ |
| 246 | gpio_set_value(host->rst, 0); | 428 | gpio_set_value(host->rst, 0); |
| 247 | err = mg_wait(host, MG_REG_STATUS_BIT_BUSY, MG_TMAX_RST_TO_BUSY); | 429 | err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY); |
| 248 | if (err) | 430 | if (err) |
| 249 | return err; | 431 | return err; |
| 250 | 432 | ||
| @@ -255,17 +437,14 @@ static int mg_disk_init(struct mg_host *host) | |||
| 255 | return err; | 437 | return err; |
| 256 | 438 | ||
| 257 | /* soft reset on */ | 439 | /* soft reset on */ |
| 258 | outb(MG_REG_CTRL_RESET | | 440 | outb(ATA_SRST | (prv_data->use_polling ? ATA_NIEN : 0), |
| 259 | (prv_data->use_polling ? MG_REG_CTRL_INTR_DISABLE : | ||
| 260 | MG_REG_CTRL_INTR_ENABLE), | ||
| 261 | (unsigned long)host->dev_base + MG_REG_DRV_CTRL); | 441 | (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 262 | err = mg_wait(host, MG_REG_STATUS_BIT_BUSY, MG_TMAX_RST_TO_BUSY); | 442 | err = mg_wait(host, ATA_BUSY, MG_TMAX_RST_TO_BUSY); |
| 263 | if (err) | 443 | if (err) |
| 264 | return err; | 444 | return err; |
| 265 | 445 | ||
| 266 | /* soft reset off */ | 446 | /* soft reset off */ |
| 267 | outb(prv_data->use_polling ? MG_REG_CTRL_INTR_DISABLE : | 447 | outb(prv_data->use_polling ? ATA_NIEN : 0, |
| 268 | MG_REG_CTRL_INTR_ENABLE, | ||
| 269 | (unsigned long)host->dev_base + MG_REG_DRV_CTRL); | 448 | (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 270 | err = mg_wait(host, MG_STAT_READY, MG_TMAX_SWRST_TO_RDY); | 449 | err = mg_wait(host, MG_STAT_READY, MG_TMAX_SWRST_TO_RDY); |
| 271 | if (err) | 450 | if (err) |
| @@ -281,11 +460,10 @@ static int mg_disk_init(struct mg_host *host) | |||
| 281 | 460 | ||
| 282 | static void mg_bad_rw_intr(struct mg_host *host) | 461 | static void mg_bad_rw_intr(struct mg_host *host) |
| 283 | { | 462 | { |
| 284 | struct request *req = elv_next_request(host->breq); | 463 | if (host->req) |
| 285 | if (req != NULL) | 464 | if (++host->req->errors >= MG_MAX_ERRORS || |
| 286 | if (++req->errors >= MG_MAX_ERRORS || | 465 | host->error == MG_ERR_TIMEOUT) |
| 287 | host->error == MG_ERR_TIMEOUT) | 466 | mg_end_request_cur(host, -EIO); |
| 288 | end_request(req, 0); | ||
| 289 | } | 467 | } |
| 290 | 468 | ||
| 291 | static unsigned int mg_out(struct mg_host *host, | 469 | static unsigned int mg_out(struct mg_host *host, |
| @@ -311,7 +489,7 @@ static unsigned int mg_out(struct mg_host *host, | |||
| 311 | MG_REG_CYL_LOW); | 489 | MG_REG_CYL_LOW); |
| 312 | outb((u8)(sect_num >> 16), (unsigned long)host->dev_base + | 490 | outb((u8)(sect_num >> 16), (unsigned long)host->dev_base + |
| 313 | MG_REG_CYL_HIGH); | 491 | MG_REG_CYL_HIGH); |
| 314 | outb((u8)((sect_num >> 24) | MG_REG_HEAD_LBA_MODE), | 492 | outb((u8)((sect_num >> 24) | ATA_LBA | ATA_DEVICE_OBS), |
| 315 | (unsigned long)host->dev_base + MG_REG_DRV_HEAD); | 493 | (unsigned long)host->dev_base + MG_REG_DRV_HEAD); |
| 316 | outb(cmd, (unsigned long)host->dev_base + MG_REG_COMMAND); | 494 | outb(cmd, (unsigned long)host->dev_base + MG_REG_COMMAND); |
| 317 | return MG_ERR_NONE; | 495 | return MG_ERR_NONE; |
| @@ -319,105 +497,77 @@ static unsigned int mg_out(struct mg_host *host, | |||
| 319 | 497 | ||
| 320 | static void mg_read(struct request *req) | 498 | static void mg_read(struct request *req) |
| 321 | { | 499 | { |
| 322 | u32 remains, j; | 500 | u32 j; |
| 323 | struct mg_host *host = req->rq_disk->private_data; | 501 | struct mg_host *host = req->rq_disk->private_data; |
| 324 | 502 | ||
| 325 | remains = req->nr_sectors; | 503 | if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req), |
| 326 | 504 | MG_CMD_RD, NULL) != MG_ERR_NONE) | |
| 327 | if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_RD, NULL) != | ||
| 328 | MG_ERR_NONE) | ||
| 329 | mg_bad_rw_intr(host); | 505 | mg_bad_rw_intr(host); |
| 330 | 506 | ||
| 331 | MG_DBG("requested %d sects (from %ld), buffer=0x%p\n", | 507 | MG_DBG("requested %d sects (from %ld), buffer=0x%p\n", |
| 332 | remains, req->sector, req->buffer); | 508 | blk_rq_sectors(req), blk_rq_pos(req), req->buffer); |
| 509 | |||
| 510 | do { | ||
| 511 | u16 *buff = (u16 *)req->buffer; | ||
| 333 | 512 | ||
| 334 | while (remains) { | 513 | if (mg_wait(host, ATA_DRQ, |
| 335 | if (mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, | 514 | MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) { |
| 336 | MG_TMAX_WAIT_RD_DRQ) != MG_ERR_NONE) { | ||
| 337 | mg_bad_rw_intr(host); | 515 | mg_bad_rw_intr(host); |
| 338 | return; | 516 | return; |
| 339 | } | 517 | } |
| 340 | for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) { | 518 | for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) |
| 341 | *(u16 *)req->buffer = | 519 | *buff++ = inw((unsigned long)host->dev_base + |
| 342 | inw((unsigned long)host->dev_base + | 520 | MG_BUFF_OFFSET + (j << 1)); |
| 343 | MG_BUFF_OFFSET + (j << 1)); | ||
| 344 | req->buffer += 2; | ||
| 345 | } | ||
| 346 | |||
| 347 | req->sector++; | ||
| 348 | req->errors = 0; | ||
| 349 | remains = --req->nr_sectors; | ||
| 350 | --req->current_nr_sectors; | ||
| 351 | |||
| 352 | if (req->current_nr_sectors <= 0) { | ||
| 353 | MG_DBG("remain : %d sects\n", remains); | ||
| 354 | end_request(req, 1); | ||
| 355 | if (remains > 0) | ||
| 356 | req = elv_next_request(host->breq); | ||
| 357 | } | ||
| 358 | 521 | ||
| 359 | outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + | 522 | outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + |
| 360 | MG_REG_COMMAND); | 523 | MG_REG_COMMAND); |
| 361 | } | 524 | } while (mg_end_request(host, 0, MG_SECTOR_SIZE)); |
| 362 | } | 525 | } |
| 363 | 526 | ||
| 364 | static void mg_write(struct request *req) | 527 | static void mg_write(struct request *req) |
| 365 | { | 528 | { |
| 366 | u32 remains, j; | 529 | u32 j; |
| 367 | struct mg_host *host = req->rq_disk->private_data; | 530 | struct mg_host *host = req->rq_disk->private_data; |
| 368 | 531 | ||
| 369 | remains = req->nr_sectors; | 532 | if (mg_out(host, blk_rq_pos(req), blk_rq_sectors(req), |
| 370 | 533 | MG_CMD_WR, NULL) != MG_ERR_NONE) { | |
| 371 | if (mg_out(host, req->sector, req->nr_sectors, MG_CMD_WR, NULL) != | ||
| 372 | MG_ERR_NONE) { | ||
| 373 | mg_bad_rw_intr(host); | 534 | mg_bad_rw_intr(host); |
| 374 | return; | 535 | return; |
| 375 | } | 536 | } |
| 376 | 537 | ||
| 377 | |||
| 378 | MG_DBG("requested %d sects (from %ld), buffer=0x%p\n", | 538 | MG_DBG("requested %d sects (from %ld), buffer=0x%p\n", |
| 379 | remains, req->sector, req->buffer); | 539 | blk_rq_sectors(req), blk_rq_pos(req), req->buffer); |
| 380 | while (remains) { | 540 | |
| 381 | if (mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, | 541 | do { |
| 382 | MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) { | 542 | u16 *buff = (u16 *)req->buffer; |
| 543 | |||
| 544 | if (mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ) != MG_ERR_NONE) { | ||
| 383 | mg_bad_rw_intr(host); | 545 | mg_bad_rw_intr(host); |
| 384 | return; | 546 | return; |
| 385 | } | 547 | } |
| 386 | for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) { | 548 | for (j = 0; j < MG_SECTOR_SIZE >> 1; j++) |
| 387 | outw(*(u16 *)req->buffer, | 549 | outw(*buff++, (unsigned long)host->dev_base + |
| 388 | (unsigned long)host->dev_base + | 550 | MG_BUFF_OFFSET + (j << 1)); |
| 389 | MG_BUFF_OFFSET + (j << 1)); | ||
| 390 | req->buffer += 2; | ||
| 391 | } | ||
| 392 | req->sector++; | ||
| 393 | remains = --req->nr_sectors; | ||
| 394 | --req->current_nr_sectors; | ||
| 395 | |||
| 396 | if (req->current_nr_sectors <= 0) { | ||
| 397 | MG_DBG("remain : %d sects\n", remains); | ||
| 398 | end_request(req, 1); | ||
| 399 | if (remains > 0) | ||
| 400 | req = elv_next_request(host->breq); | ||
| 401 | } | ||
| 402 | 551 | ||
| 403 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + | 552 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + |
| 404 | MG_REG_COMMAND); | 553 | MG_REG_COMMAND); |
| 405 | } | 554 | } while (mg_end_request(host, 0, MG_SECTOR_SIZE)); |
| 406 | } | 555 | } |
| 407 | 556 | ||
| 408 | static void mg_read_intr(struct mg_host *host) | 557 | static void mg_read_intr(struct mg_host *host) |
| 409 | { | 558 | { |
| 559 | struct request *req = host->req; | ||
| 410 | u32 i; | 560 | u32 i; |
| 411 | struct request *req; | 561 | u16 *buff; |
| 412 | 562 | ||
| 413 | /* check status */ | 563 | /* check status */ |
| 414 | do { | 564 | do { |
| 415 | i = inb((unsigned long)host->dev_base + MG_REG_STATUS); | 565 | i = inb((unsigned long)host->dev_base + MG_REG_STATUS); |
| 416 | if (i & MG_REG_STATUS_BIT_BUSY) | 566 | if (i & ATA_BUSY) |
| 417 | break; | 567 | break; |
| 418 | if (!MG_READY_OK(i)) | 568 | if (!MG_READY_OK(i)) |
| 419 | break; | 569 | break; |
| 420 | if (i & MG_REG_STATUS_BIT_DATA_REQ) | 570 | if (i & ATA_DRQ) |
| 421 | goto ok_to_read; | 571 | goto ok_to_read; |
| 422 | } while (0); | 572 | } while (0); |
| 423 | mg_dump_status("mg_read_intr", i, host); | 573 | mg_dump_status("mg_read_intr", i, host); |
| @@ -427,60 +577,42 @@ static void mg_read_intr(struct mg_host *host) | |||
| 427 | 577 | ||
| 428 | ok_to_read: | 578 | ok_to_read: |
| 429 | /* get current segment of request */ | 579 | /* get current segment of request */ |
| 430 | req = elv_next_request(host->breq); | 580 | buff = (u16 *)req->buffer; |
| 431 | 581 | ||
| 432 | /* read 1 sector */ | 582 | /* read 1 sector */ |
| 433 | for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) { | 583 | for (i = 0; i < MG_SECTOR_SIZE >> 1; i++) |
| 434 | *(u16 *)req->buffer = | 584 | *buff++ = inw((unsigned long)host->dev_base + MG_BUFF_OFFSET + |
| 435 | inw((unsigned long)host->dev_base + MG_BUFF_OFFSET + | 585 | (i << 1)); |
| 436 | (i << 1)); | ||
| 437 | req->buffer += 2; | ||
| 438 | } | ||
| 439 | 586 | ||
| 440 | /* manipulate request */ | ||
| 441 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", | 587 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", |
| 442 | req->sector, req->nr_sectors - 1, req->buffer); | 588 | blk_rq_pos(req), blk_rq_sectors(req) - 1, req->buffer); |
| 443 | |||
| 444 | req->sector++; | ||
| 445 | req->errors = 0; | ||
| 446 | i = --req->nr_sectors; | ||
| 447 | --req->current_nr_sectors; | ||
| 448 | |||
| 449 | /* let know if current segment done */ | ||
| 450 | if (req->current_nr_sectors <= 0) | ||
| 451 | end_request(req, 1); | ||
| 452 | |||
| 453 | /* set handler if read remains */ | ||
| 454 | if (i > 0) { | ||
| 455 | host->mg_do_intr = mg_read_intr; | ||
| 456 | mod_timer(&host->timer, jiffies + 3 * HZ); | ||
| 457 | } | ||
| 458 | 589 | ||
| 459 | /* send read confirm */ | 590 | /* send read confirm */ |
| 460 | outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND); | 591 | outb(MG_CMD_RD_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND); |
| 461 | 592 | ||
| 462 | /* goto next request */ | 593 | if (mg_end_request(host, 0, MG_SECTOR_SIZE)) { |
| 463 | if (!i) | 594 | /* set handler if read remains */ |
| 595 | host->mg_do_intr = mg_read_intr; | ||
| 596 | mod_timer(&host->timer, jiffies + 3 * HZ); | ||
| 597 | } else /* goto next request */ | ||
| 464 | mg_request(host->breq); | 598 | mg_request(host->breq); |
| 465 | } | 599 | } |
| 466 | 600 | ||
| 467 | static void mg_write_intr(struct mg_host *host) | 601 | static void mg_write_intr(struct mg_host *host) |
| 468 | { | 602 | { |
| 603 | struct request *req = host->req; | ||
| 469 | u32 i, j; | 604 | u32 i, j; |
| 470 | u16 *buff; | 605 | u16 *buff; |
| 471 | struct request *req; | 606 | bool rem; |
| 472 | |||
| 473 | /* get current segment of request */ | ||
| 474 | req = elv_next_request(host->breq); | ||
| 475 | 607 | ||
| 476 | /* check status */ | 608 | /* check status */ |
| 477 | do { | 609 | do { |
| 478 | i = inb((unsigned long)host->dev_base + MG_REG_STATUS); | 610 | i = inb((unsigned long)host->dev_base + MG_REG_STATUS); |
| 479 | if (i & MG_REG_STATUS_BIT_BUSY) | 611 | if (i & ATA_BUSY) |
| 480 | break; | 612 | break; |
| 481 | if (!MG_READY_OK(i)) | 613 | if (!MG_READY_OK(i)) |
| 482 | break; | 614 | break; |
| 483 | if ((req->nr_sectors <= 1) || (i & MG_REG_STATUS_BIT_DATA_REQ)) | 615 | if ((blk_rq_sectors(req) <= 1) || (i & ATA_DRQ)) |
| 484 | goto ok_to_write; | 616 | goto ok_to_write; |
| 485 | } while (0); | 617 | } while (0); |
| 486 | mg_dump_status("mg_write_intr", i, host); | 618 | mg_dump_status("mg_write_intr", i, host); |
| @@ -489,18 +621,8 @@ static void mg_write_intr(struct mg_host *host) | |||
| 489 | return; | 621 | return; |
| 490 | 622 | ||
| 491 | ok_to_write: | 623 | ok_to_write: |
| 492 | /* manipulate request */ | 624 | if ((rem = mg_end_request(host, 0, MG_SECTOR_SIZE))) { |
| 493 | req->sector++; | 625 | /* write 1 sector and set handler if remains */ |
| 494 | i = --req->nr_sectors; | ||
| 495 | --req->current_nr_sectors; | ||
| 496 | req->buffer += MG_SECTOR_SIZE; | ||
| 497 | |||
| 498 | /* let know if current segment or all done */ | ||
| 499 | if (!i || (req->bio && req->current_nr_sectors <= 0)) | ||
| 500 | end_request(req, 1); | ||
| 501 | |||
| 502 | /* write 1 sector and set handler if remains */ | ||
| 503 | if (i > 0) { | ||
| 504 | buff = (u16 *)req->buffer; | 626 | buff = (u16 *)req->buffer; |
| 505 | for (j = 0; j < MG_STORAGE_BUFFER_SIZE >> 1; j++) { | 627 | for (j = 0; j < MG_STORAGE_BUFFER_SIZE >> 1; j++) { |
| 506 | outw(*buff, (unsigned long)host->dev_base + | 628 | outw(*buff, (unsigned long)host->dev_base + |
| @@ -508,7 +630,7 @@ ok_to_write: | |||
| 508 | buff++; | 630 | buff++; |
| 509 | } | 631 | } |
| 510 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", | 632 | MG_DBG("sector %ld, remaining=%ld, buffer=0x%p\n", |
| 511 | req->sector, req->nr_sectors, req->buffer); | 633 | blk_rq_pos(req), blk_rq_sectors(req), req->buffer); |
| 512 | host->mg_do_intr = mg_write_intr; | 634 | host->mg_do_intr = mg_write_intr; |
| 513 | mod_timer(&host->timer, jiffies + 3 * HZ); | 635 | mod_timer(&host->timer, jiffies + 3 * HZ); |
| 514 | } | 636 | } |
| @@ -516,7 +638,7 @@ ok_to_write: | |||
| 516 | /* send write confirm */ | 638 | /* send write confirm */ |
| 517 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND); | 639 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + MG_REG_COMMAND); |
| 518 | 640 | ||
| 519 | if (!i) | 641 | if (!rem) |
| 520 | mg_request(host->breq); | 642 | mg_request(host->breq); |
| 521 | } | 643 | } |
| 522 | 644 | ||
| @@ -524,49 +646,45 @@ void mg_times_out(unsigned long data) | |||
| 524 | { | 646 | { |
| 525 | struct mg_host *host = (struct mg_host *)data; | 647 | struct mg_host *host = (struct mg_host *)data; |
| 526 | char *name; | 648 | char *name; |
| 527 | struct request *req; | ||
| 528 | 649 | ||
| 529 | spin_lock_irq(&host->lock); | 650 | spin_lock_irq(&host->lock); |
| 530 | 651 | ||
| 531 | req = elv_next_request(host->breq); | 652 | if (!host->req) |
| 532 | if (!req) | ||
| 533 | goto out_unlock; | 653 | goto out_unlock; |
| 534 | 654 | ||
| 535 | host->mg_do_intr = NULL; | 655 | host->mg_do_intr = NULL; |
| 536 | 656 | ||
| 537 | name = req->rq_disk->disk_name; | 657 | name = host->req->rq_disk->disk_name; |
| 538 | printk(KERN_DEBUG "%s: timeout\n", name); | 658 | printk(KERN_DEBUG "%s: timeout\n", name); |
| 539 | 659 | ||
| 540 | host->error = MG_ERR_TIMEOUT; | 660 | host->error = MG_ERR_TIMEOUT; |
| 541 | mg_bad_rw_intr(host); | 661 | mg_bad_rw_intr(host); |
| 542 | 662 | ||
| 543 | mg_request(host->breq); | ||
| 544 | out_unlock: | 663 | out_unlock: |
| 664 | mg_request(host->breq); | ||
| 545 | spin_unlock_irq(&host->lock); | 665 | spin_unlock_irq(&host->lock); |
| 546 | } | 666 | } |
| 547 | 667 | ||
| 548 | static void mg_request_poll(struct request_queue *q) | 668 | static void mg_request_poll(struct request_queue *q) |
| 549 | { | 669 | { |
| 550 | struct request *req; | 670 | struct mg_host *host = q->queuedata; |
| 551 | struct mg_host *host; | ||
| 552 | 671 | ||
| 553 | while ((req = elv_next_request(q)) != NULL) { | 672 | while (1) { |
| 554 | host = req->rq_disk->private_data; | 673 | if (!host->req) { |
| 555 | if (blk_fs_request(req)) { | 674 | host->req = blk_fetch_request(q); |
| 556 | switch (rq_data_dir(req)) { | 675 | if (!host->req) |
| 557 | case READ: | ||
| 558 | mg_read(req); | ||
| 559 | break; | ||
| 560 | case WRITE: | ||
| 561 | mg_write(req); | ||
| 562 | break; | ||
| 563 | default: | ||
| 564 | printk(KERN_WARNING "%s:%d unknown command\n", | ||
| 565 | __func__, __LINE__); | ||
| 566 | end_request(req, 0); | ||
| 567 | break; | 676 | break; |
| 568 | } | ||
| 569 | } | 677 | } |
| 678 | |||
| 679 | if (unlikely(!blk_fs_request(host->req))) { | ||
| 680 | mg_end_request_cur(host, -EIO); | ||
| 681 | continue; | ||
| 682 | } | ||
| 683 | |||
| 684 | if (rq_data_dir(host->req) == READ) | ||
| 685 | mg_read(host->req); | ||
| 686 | else | ||
| 687 | mg_write(host->req); | ||
| 570 | } | 688 | } |
| 571 | } | 689 | } |
| 572 | 690 | ||
| @@ -588,18 +706,15 @@ static unsigned int mg_issue_req(struct request *req, | |||
| 588 | break; | 706 | break; |
| 589 | case WRITE: | 707 | case WRITE: |
| 590 | /* TODO : handler */ | 708 | /* TODO : handler */ |
| 591 | outb(MG_REG_CTRL_INTR_DISABLE, | 709 | outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 592 | (unsigned long)host->dev_base + | ||
| 593 | MG_REG_DRV_CTRL); | ||
| 594 | if (mg_out(host, sect_num, sect_cnt, MG_CMD_WR, &mg_write_intr) | 710 | if (mg_out(host, sect_num, sect_cnt, MG_CMD_WR, &mg_write_intr) |
| 595 | != MG_ERR_NONE) { | 711 | != MG_ERR_NONE) { |
| 596 | mg_bad_rw_intr(host); | 712 | mg_bad_rw_intr(host); |
| 597 | return host->error; | 713 | return host->error; |
| 598 | } | 714 | } |
| 599 | del_timer(&host->timer); | 715 | del_timer(&host->timer); |
| 600 | mg_wait(host, MG_REG_STATUS_BIT_DATA_REQ, MG_TMAX_WAIT_WR_DRQ); | 716 | mg_wait(host, ATA_DRQ, MG_TMAX_WAIT_WR_DRQ); |
| 601 | outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base + | 717 | outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 602 | MG_REG_DRV_CTRL); | ||
| 603 | if (host->error) { | 718 | if (host->error) { |
| 604 | mg_bad_rw_intr(host); | 719 | mg_bad_rw_intr(host); |
| 605 | return host->error; | 720 | return host->error; |
| @@ -614,11 +729,6 @@ static unsigned int mg_issue_req(struct request *req, | |||
| 614 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + | 729 | outb(MG_CMD_WR_CONF, (unsigned long)host->dev_base + |
| 615 | MG_REG_COMMAND); | 730 | MG_REG_COMMAND); |
| 616 | break; | 731 | break; |
| 617 | default: | ||
| 618 | printk(KERN_WARNING "%s:%d unknown command\n", | ||
| 619 | __func__, __LINE__); | ||
| 620 | end_request(req, 0); | ||
| 621 | break; | ||
| 622 | } | 732 | } |
| 623 | return MG_ERR_NONE; | 733 | return MG_ERR_NONE; |
| 624 | } | 734 | } |
| @@ -626,16 +736,17 @@ static unsigned int mg_issue_req(struct request *req, | |||
| 626 | /* This function also called from IRQ context */ | 736 | /* This function also called from IRQ context */ |
| 627 | static void mg_request(struct request_queue *q) | 737 | static void mg_request(struct request_queue *q) |
| 628 | { | 738 | { |
| 739 | struct mg_host *host = q->queuedata; | ||
| 629 | struct request *req; | 740 | struct request *req; |
| 630 | struct mg_host *host; | ||
| 631 | u32 sect_num, sect_cnt; | 741 | u32 sect_num, sect_cnt; |
| 632 | 742 | ||
| 633 | while (1) { | 743 | while (1) { |
| 634 | req = elv_next_request(q); | 744 | if (!host->req) { |
| 635 | if (!req) | 745 | host->req = blk_fetch_request(q); |
| 636 | return; | 746 | if (!host->req) |
| 637 | 747 | break; | |
| 638 | host = req->rq_disk->private_data; | 748 | } |
| 749 | req = host->req; | ||
| 639 | 750 | ||
| 640 | /* check unwanted request call */ | 751 | /* check unwanted request call */ |
| 641 | if (host->mg_do_intr) | 752 | if (host->mg_do_intr) |
| @@ -643,9 +754,9 @@ static void mg_request(struct request_queue *q) | |||
| 643 | 754 | ||
| 644 | del_timer(&host->timer); | 755 | del_timer(&host->timer); |
| 645 | 756 | ||
| 646 | sect_num = req->sector; | 757 | sect_num = blk_rq_pos(req); |
| 647 | /* deal whole segments */ | 758 | /* deal whole segments */ |
| 648 | sect_cnt = req->nr_sectors; | 759 | sect_cnt = blk_rq_sectors(req); |
| 649 | 760 | ||
| 650 | /* sanity check */ | 761 | /* sanity check */ |
| 651 | if (sect_num >= get_capacity(req->rq_disk) || | 762 | if (sect_num >= get_capacity(req->rq_disk) || |
| @@ -655,12 +766,14 @@ static void mg_request(struct request_queue *q) | |||
| 655 | "%s: bad access: sector=%d, count=%d\n", | 766 | "%s: bad access: sector=%d, count=%d\n", |
| 656 | req->rq_disk->disk_name, | 767 | req->rq_disk->disk_name, |
| 657 | sect_num, sect_cnt); | 768 | sect_num, sect_cnt); |
| 658 | end_request(req, 0); | 769 | mg_end_request_cur(host, -EIO); |
| 659 | continue; | 770 | continue; |
| 660 | } | 771 | } |
| 661 | 772 | ||
| 662 | if (!blk_fs_request(req)) | 773 | if (unlikely(!blk_fs_request(req))) { |
| 663 | return; | 774 | mg_end_request_cur(host, -EIO); |
| 775 | continue; | ||
| 776 | } | ||
| 664 | 777 | ||
| 665 | if (!mg_issue_req(req, host, sect_num, sect_cnt)) | 778 | if (!mg_issue_req(req, host, sect_num, sect_cnt)) |
| 666 | return; | 779 | return; |
| @@ -690,9 +803,7 @@ static int mg_suspend(struct platform_device *plat_dev, pm_message_t state) | |||
| 690 | return -EIO; | 803 | return -EIO; |
| 691 | 804 | ||
| 692 | if (!prv_data->use_polling) | 805 | if (!prv_data->use_polling) |
| 693 | outb(MG_REG_CTRL_INTR_DISABLE, | 806 | outb(ATA_NIEN, (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 694 | (unsigned long)host->dev_base + | ||
| 695 | MG_REG_DRV_CTRL); | ||
| 696 | 807 | ||
| 697 | outb(MG_CMD_SLEEP, (unsigned long)host->dev_base + MG_REG_COMMAND); | 808 | outb(MG_CMD_SLEEP, (unsigned long)host->dev_base + MG_REG_COMMAND); |
| 698 | /* wait until mflash deep sleep */ | 809 | /* wait until mflash deep sleep */ |
| @@ -700,9 +811,7 @@ static int mg_suspend(struct platform_device *plat_dev, pm_message_t state) | |||
| 700 | 811 | ||
| 701 | if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD)) { | 812 | if (mg_wait(host, MG_STAT_READY, MG_TMAX_CONF_TO_CMD)) { |
| 702 | if (!prv_data->use_polling) | 813 | if (!prv_data->use_polling) |
| 703 | outb(MG_REG_CTRL_INTR_ENABLE, | 814 | outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 704 | (unsigned long)host->dev_base + | ||
| 705 | MG_REG_DRV_CTRL); | ||
| 706 | return -EIO; | 815 | return -EIO; |
| 707 | } | 816 | } |
| 708 | 817 | ||
| @@ -725,8 +834,7 @@ static int mg_resume(struct platform_device *plat_dev) | |||
| 725 | return -EIO; | 834 | return -EIO; |
| 726 | 835 | ||
| 727 | if (!prv_data->use_polling) | 836 | if (!prv_data->use_polling) |
| 728 | outb(MG_REG_CTRL_INTR_ENABLE, (unsigned long)host->dev_base + | 837 | outb(0, (unsigned long)host->dev_base + MG_REG_DRV_CTRL); |
| 729 | MG_REG_DRV_CTRL); | ||
| 730 | 838 | ||
| 731 | return 0; | 839 | return 0; |
| 732 | } | 840 | } |
| @@ -877,6 +985,7 @@ static int mg_probe(struct platform_device *plat_dev) | |||
| 877 | __func__, __LINE__); | 985 | __func__, __LINE__); |
| 878 | goto probe_err_5; | 986 | goto probe_err_5; |
| 879 | } | 987 | } |
| 988 | host->breq->queuedata = host; | ||
| 880 | 989 | ||
| 881 | /* mflash is random device, thanx for the noop */ | 990 | /* mflash is random device, thanx for the noop */ |
| 882 | elevator_exit(host->breq->elevator); | 991 | elevator_exit(host->breq->elevator); |
| @@ -887,7 +996,7 @@ static int mg_probe(struct platform_device *plat_dev) | |||
| 887 | goto probe_err_6; | 996 | goto probe_err_6; |
| 888 | } | 997 | } |
| 889 | blk_queue_max_sectors(host->breq, MG_MAX_SECTS); | 998 | blk_queue_max_sectors(host->breq, MG_MAX_SECTS); |
| 890 | blk_queue_hardsect_size(host->breq, MG_SECTOR_SIZE); | 999 | blk_queue_logical_block_size(host->breq, MG_SECTOR_SIZE); |
| 891 | 1000 | ||
| 892 | init_timer(&host->timer); | 1001 | init_timer(&host->timer); |
| 893 | host->timer.function = mg_times_out; | 1002 | host->timer.function = mg_times_out; |
diff --git a/drivers/block/nbd.c b/drivers/block/nbd.c index 4d6de4f15ccb..5d23ffad7c77 100644 --- a/drivers/block/nbd.c +++ b/drivers/block/nbd.c | |||
| @@ -110,7 +110,7 @@ static void nbd_end_request(struct request *req) | |||
| 110 | req, error ? "failed" : "done"); | 110 | req, error ? "failed" : "done"); |
| 111 | 111 | ||
| 112 | spin_lock_irqsave(q->queue_lock, flags); | 112 | spin_lock_irqsave(q->queue_lock, flags); |
| 113 | __blk_end_request(req, error, req->nr_sectors << 9); | 113 | __blk_end_request_all(req, error); |
| 114 | spin_unlock_irqrestore(q->queue_lock, flags); | 114 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| @@ -231,19 +231,19 @@ static int nbd_send_req(struct nbd_device *lo, struct request *req) | |||
| 231 | { | 231 | { |
| 232 | int result, flags; | 232 | int result, flags; |
| 233 | struct nbd_request request; | 233 | struct nbd_request request; |
| 234 | unsigned long size = req->nr_sectors << 9; | 234 | unsigned long size = blk_rq_bytes(req); |
| 235 | 235 | ||
| 236 | request.magic = htonl(NBD_REQUEST_MAGIC); | 236 | request.magic = htonl(NBD_REQUEST_MAGIC); |
| 237 | request.type = htonl(nbd_cmd(req)); | 237 | request.type = htonl(nbd_cmd(req)); |
| 238 | request.from = cpu_to_be64((u64) req->sector << 9); | 238 | request.from = cpu_to_be64((u64)blk_rq_pos(req) << 9); |
| 239 | request.len = htonl(size); | 239 | request.len = htonl(size); |
| 240 | memcpy(request.handle, &req, sizeof(req)); | 240 | memcpy(request.handle, &req, sizeof(req)); |
| 241 | 241 | ||
| 242 | dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%luB)\n", | 242 | dprintk(DBG_TX, "%s: request %p: sending control (%s@%llu,%uB)\n", |
| 243 | lo->disk->disk_name, req, | 243 | lo->disk->disk_name, req, |
| 244 | nbdcmd_to_ascii(nbd_cmd(req)), | 244 | nbdcmd_to_ascii(nbd_cmd(req)), |
| 245 | (unsigned long long)req->sector << 9, | 245 | (unsigned long long)blk_rq_pos(req) << 9, |
| 246 | req->nr_sectors << 9); | 246 | blk_rq_bytes(req)); |
| 247 | result = sock_xmit(lo, 1, &request, sizeof(request), | 247 | result = sock_xmit(lo, 1, &request, sizeof(request), |
| 248 | (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0); | 248 | (nbd_cmd(req) == NBD_CMD_WRITE) ? MSG_MORE : 0); |
| 249 | if (result <= 0) { | 249 | if (result <= 0) { |
| @@ -533,11 +533,9 @@ static void do_nbd_request(struct request_queue *q) | |||
| 533 | { | 533 | { |
| 534 | struct request *req; | 534 | struct request *req; |
| 535 | 535 | ||
| 536 | while ((req = elv_next_request(q)) != NULL) { | 536 | while ((req = blk_fetch_request(q)) != NULL) { |
| 537 | struct nbd_device *lo; | 537 | struct nbd_device *lo; |
| 538 | 538 | ||
| 539 | blkdev_dequeue_request(req); | ||
| 540 | |||
| 541 | spin_unlock_irq(q->queue_lock); | 539 | spin_unlock_irq(q->queue_lock); |
| 542 | 540 | ||
| 543 | dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", | 541 | dprintk(DBG_BLKDEV, "%s: request %p: dequeued (flags=%x)\n", |
| @@ -580,13 +578,6 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *lo, | |||
| 580 | blk_rq_init(NULL, &sreq); | 578 | blk_rq_init(NULL, &sreq); |
| 581 | sreq.cmd_type = REQ_TYPE_SPECIAL; | 579 | sreq.cmd_type = REQ_TYPE_SPECIAL; |
| 582 | nbd_cmd(&sreq) = NBD_CMD_DISC; | 580 | nbd_cmd(&sreq) = NBD_CMD_DISC; |
| 583 | /* | ||
| 584 | * Set these to sane values in case server implementation | ||
| 585 | * fails to check the request type first and also to keep | ||
| 586 | * debugging output cleaner. | ||
| 587 | */ | ||
| 588 | sreq.sector = 0; | ||
| 589 | sreq.nr_sectors = 0; | ||
| 590 | if (!lo->sock) | 581 | if (!lo->sock) |
| 591 | return -EINVAL; | 582 | return -EINVAL; |
| 592 | nbd_send_req(lo, &sreq); | 583 | nbd_send_req(lo, &sreq); |
diff --git a/drivers/block/paride/pcd.c b/drivers/block/paride/pcd.c index e91d4b4b014f..911dfd98d813 100644 --- a/drivers/block/paride/pcd.c +++ b/drivers/block/paride/pcd.c | |||
| @@ -719,32 +719,37 @@ static void do_pcd_request(struct request_queue * q) | |||
| 719 | if (pcd_busy) | 719 | if (pcd_busy) |
| 720 | return; | 720 | return; |
| 721 | while (1) { | 721 | while (1) { |
| 722 | pcd_req = elv_next_request(q); | 722 | if (!pcd_req) { |
| 723 | if (!pcd_req) | 723 | pcd_req = blk_fetch_request(q); |
| 724 | return; | 724 | if (!pcd_req) |
| 725 | return; | ||
| 726 | } | ||
| 725 | 727 | ||
| 726 | if (rq_data_dir(pcd_req) == READ) { | 728 | if (rq_data_dir(pcd_req) == READ) { |
| 727 | struct pcd_unit *cd = pcd_req->rq_disk->private_data; | 729 | struct pcd_unit *cd = pcd_req->rq_disk->private_data; |
| 728 | if (cd != pcd_current) | 730 | if (cd != pcd_current) |
| 729 | pcd_bufblk = -1; | 731 | pcd_bufblk = -1; |
| 730 | pcd_current = cd; | 732 | pcd_current = cd; |
| 731 | pcd_sector = pcd_req->sector; | 733 | pcd_sector = blk_rq_pos(pcd_req); |
| 732 | pcd_count = pcd_req->current_nr_sectors; | 734 | pcd_count = blk_rq_cur_sectors(pcd_req); |
| 733 | pcd_buf = pcd_req->buffer; | 735 | pcd_buf = pcd_req->buffer; |
| 734 | pcd_busy = 1; | 736 | pcd_busy = 1; |
| 735 | ps_set_intr(do_pcd_read, NULL, 0, nice); | 737 | ps_set_intr(do_pcd_read, NULL, 0, nice); |
| 736 | return; | 738 | return; |
| 737 | } else | 739 | } else { |
| 738 | end_request(pcd_req, 0); | 740 | __blk_end_request_all(pcd_req, -EIO); |
| 741 | pcd_req = NULL; | ||
| 742 | } | ||
| 739 | } | 743 | } |
| 740 | } | 744 | } |
| 741 | 745 | ||
| 742 | static inline void next_request(int success) | 746 | static inline void next_request(int err) |
| 743 | { | 747 | { |
| 744 | unsigned long saved_flags; | 748 | unsigned long saved_flags; |
| 745 | 749 | ||
| 746 | spin_lock_irqsave(&pcd_lock, saved_flags); | 750 | spin_lock_irqsave(&pcd_lock, saved_flags); |
| 747 | end_request(pcd_req, success); | 751 | if (!__blk_end_request_cur(pcd_req, err)) |
| 752 | pcd_req = NULL; | ||
| 748 | pcd_busy = 0; | 753 | pcd_busy = 0; |
| 749 | do_pcd_request(pcd_queue); | 754 | do_pcd_request(pcd_queue); |
| 750 | spin_unlock_irqrestore(&pcd_lock, saved_flags); | 755 | spin_unlock_irqrestore(&pcd_lock, saved_flags); |
| @@ -781,7 +786,7 @@ static void pcd_start(void) | |||
| 781 | 786 | ||
| 782 | if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) { | 787 | if (pcd_command(pcd_current, rd_cmd, 2048, "read block")) { |
| 783 | pcd_bufblk = -1; | 788 | pcd_bufblk = -1; |
| 784 | next_request(0); | 789 | next_request(-EIO); |
| 785 | return; | 790 | return; |
| 786 | } | 791 | } |
| 787 | 792 | ||
| @@ -796,7 +801,7 @@ static void do_pcd_read(void) | |||
| 796 | pcd_retries = 0; | 801 | pcd_retries = 0; |
| 797 | pcd_transfer(); | 802 | pcd_transfer(); |
| 798 | if (!pcd_count) { | 803 | if (!pcd_count) { |
| 799 | next_request(1); | 804 | next_request(0); |
| 800 | return; | 805 | return; |
| 801 | } | 806 | } |
| 802 | 807 | ||
| @@ -815,7 +820,7 @@ static void do_pcd_read_drq(void) | |||
| 815 | return; | 820 | return; |
| 816 | } | 821 | } |
| 817 | pcd_bufblk = -1; | 822 | pcd_bufblk = -1; |
| 818 | next_request(0); | 823 | next_request(-EIO); |
| 819 | return; | 824 | return; |
| 820 | } | 825 | } |
| 821 | 826 | ||
diff --git a/drivers/block/paride/pd.c b/drivers/block/paride/pd.c index 9299455b0af6..bf5955b3d873 100644 --- a/drivers/block/paride/pd.c +++ b/drivers/block/paride/pd.c | |||
| @@ -410,10 +410,12 @@ static void run_fsm(void) | |||
| 410 | pd_claimed = 0; | 410 | pd_claimed = 0; |
| 411 | phase = NULL; | 411 | phase = NULL; |
| 412 | spin_lock_irqsave(&pd_lock, saved_flags); | 412 | spin_lock_irqsave(&pd_lock, saved_flags); |
| 413 | end_request(pd_req, res); | 413 | if (!__blk_end_request_cur(pd_req, |
| 414 | pd_req = elv_next_request(pd_queue); | 414 | res == Ok ? 0 : -EIO)) { |
| 415 | if (!pd_req) | 415 | pd_req = blk_fetch_request(pd_queue); |
| 416 | stop = 1; | 416 | if (!pd_req) |
| 417 | stop = 1; | ||
| 418 | } | ||
| 417 | spin_unlock_irqrestore(&pd_lock, saved_flags); | 419 | spin_unlock_irqrestore(&pd_lock, saved_flags); |
| 418 | if (stop) | 420 | if (stop) |
| 419 | return; | 421 | return; |
| @@ -443,11 +445,11 @@ static enum action do_pd_io_start(void) | |||
| 443 | 445 | ||
| 444 | pd_cmd = rq_data_dir(pd_req); | 446 | pd_cmd = rq_data_dir(pd_req); |
| 445 | if (pd_cmd == READ || pd_cmd == WRITE) { | 447 | if (pd_cmd == READ || pd_cmd == WRITE) { |
| 446 | pd_block = pd_req->sector; | 448 | pd_block = blk_rq_pos(pd_req); |
| 447 | pd_count = pd_req->current_nr_sectors; | 449 | pd_count = blk_rq_cur_sectors(pd_req); |
| 448 | if (pd_block + pd_count > get_capacity(pd_req->rq_disk)) | 450 | if (pd_block + pd_count > get_capacity(pd_req->rq_disk)) |
| 449 | return Fail; | 451 | return Fail; |
| 450 | pd_run = pd_req->nr_sectors; | 452 | pd_run = blk_rq_sectors(pd_req); |
| 451 | pd_buf = pd_req->buffer; | 453 | pd_buf = pd_req->buffer; |
| 452 | pd_retries = 0; | 454 | pd_retries = 0; |
| 453 | if (pd_cmd == READ) | 455 | if (pd_cmd == READ) |
| @@ -477,8 +479,8 @@ static int pd_next_buf(void) | |||
| 477 | if (pd_count) | 479 | if (pd_count) |
| 478 | return 0; | 480 | return 0; |
| 479 | spin_lock_irqsave(&pd_lock, saved_flags); | 481 | spin_lock_irqsave(&pd_lock, saved_flags); |
| 480 | end_request(pd_req, 1); | 482 | __blk_end_request_cur(pd_req, 0); |
| 481 | pd_count = pd_req->current_nr_sectors; | 483 | pd_count = blk_rq_cur_sectors(pd_req); |
| 482 | pd_buf = pd_req->buffer; | 484 | pd_buf = pd_req->buffer; |
| 483 | spin_unlock_irqrestore(&pd_lock, saved_flags); | 485 | spin_unlock_irqrestore(&pd_lock, saved_flags); |
| 484 | return 0; | 486 | return 0; |
| @@ -702,7 +704,7 @@ static void do_pd_request(struct request_queue * q) | |||
| 702 | { | 704 | { |
| 703 | if (pd_req) | 705 | if (pd_req) |
| 704 | return; | 706 | return; |
| 705 | pd_req = elv_next_request(q); | 707 | pd_req = blk_fetch_request(q); |
| 706 | if (!pd_req) | 708 | if (!pd_req) |
| 707 | return; | 709 | return; |
| 708 | 710 | ||
diff --git a/drivers/block/paride/pf.c b/drivers/block/paride/pf.c index bef3b997ba3e..68a90834e993 100644 --- a/drivers/block/paride/pf.c +++ b/drivers/block/paride/pf.c | |||
| @@ -750,12 +750,10 @@ static int pf_ready(void) | |||
| 750 | 750 | ||
| 751 | static struct request_queue *pf_queue; | 751 | static struct request_queue *pf_queue; |
| 752 | 752 | ||
| 753 | static void pf_end_request(int uptodate) | 753 | static void pf_end_request(int err) |
| 754 | { | 754 | { |
| 755 | if (pf_req) { | 755 | if (pf_req && !__blk_end_request_cur(pf_req, err)) |
| 756 | end_request(pf_req, uptodate); | ||
| 757 | pf_req = NULL; | 756 | pf_req = NULL; |
| 758 | } | ||
| 759 | } | 757 | } |
| 760 | 758 | ||
| 761 | static void do_pf_request(struct request_queue * q) | 759 | static void do_pf_request(struct request_queue * q) |
| @@ -763,17 +761,19 @@ static void do_pf_request(struct request_queue * q) | |||
| 763 | if (pf_busy) | 761 | if (pf_busy) |
| 764 | return; | 762 | return; |
| 765 | repeat: | 763 | repeat: |
| 766 | pf_req = elv_next_request(q); | 764 | if (!pf_req) { |
| 767 | if (!pf_req) | 765 | pf_req = blk_fetch_request(q); |
| 768 | return; | 766 | if (!pf_req) |
| 767 | return; | ||
| 768 | } | ||
| 769 | 769 | ||
| 770 | pf_current = pf_req->rq_disk->private_data; | 770 | pf_current = pf_req->rq_disk->private_data; |
| 771 | pf_block = pf_req->sector; | 771 | pf_block = blk_rq_pos(pf_req); |
| 772 | pf_run = pf_req->nr_sectors; | 772 | pf_run = blk_rq_sectors(pf_req); |
| 773 | pf_count = pf_req->current_nr_sectors; | 773 | pf_count = blk_rq_cur_sectors(pf_req); |
| 774 | 774 | ||
| 775 | if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { | 775 | if (pf_block + pf_count > get_capacity(pf_req->rq_disk)) { |
| 776 | pf_end_request(0); | 776 | pf_end_request(-EIO); |
| 777 | goto repeat; | 777 | goto repeat; |
| 778 | } | 778 | } |
| 779 | 779 | ||
| @@ -788,7 +788,7 @@ repeat: | |||
| 788 | pi_do_claimed(pf_current->pi, do_pf_write); | 788 | pi_do_claimed(pf_current->pi, do_pf_write); |
| 789 | else { | 789 | else { |
| 790 | pf_busy = 0; | 790 | pf_busy = 0; |
| 791 | pf_end_request(0); | 791 | pf_end_request(-EIO); |
| 792 | goto repeat; | 792 | goto repeat; |
| 793 | } | 793 | } |
| 794 | } | 794 | } |
| @@ -805,23 +805,22 @@ static int pf_next_buf(void) | |||
| 805 | return 1; | 805 | return 1; |
| 806 | if (!pf_count) { | 806 | if (!pf_count) { |
| 807 | spin_lock_irqsave(&pf_spin_lock, saved_flags); | 807 | spin_lock_irqsave(&pf_spin_lock, saved_flags); |
| 808 | pf_end_request(1); | 808 | pf_end_request(0); |
| 809 | pf_req = elv_next_request(pf_queue); | ||
| 810 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); | 809 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); |
| 811 | if (!pf_req) | 810 | if (!pf_req) |
| 812 | return 1; | 811 | return 1; |
| 813 | pf_count = pf_req->current_nr_sectors; | 812 | pf_count = blk_rq_cur_sectors(pf_req); |
| 814 | pf_buf = pf_req->buffer; | 813 | pf_buf = pf_req->buffer; |
| 815 | } | 814 | } |
| 816 | return 0; | 815 | return 0; |
| 817 | } | 816 | } |
| 818 | 817 | ||
| 819 | static inline void next_request(int success) | 818 | static inline void next_request(int err) |
| 820 | { | 819 | { |
| 821 | unsigned long saved_flags; | 820 | unsigned long saved_flags; |
| 822 | 821 | ||
| 823 | spin_lock_irqsave(&pf_spin_lock, saved_flags); | 822 | spin_lock_irqsave(&pf_spin_lock, saved_flags); |
| 824 | pf_end_request(success); | 823 | pf_end_request(err); |
| 825 | pf_busy = 0; | 824 | pf_busy = 0; |
| 826 | do_pf_request(pf_queue); | 825 | do_pf_request(pf_queue); |
| 827 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); | 826 | spin_unlock_irqrestore(&pf_spin_lock, saved_flags); |
| @@ -844,7 +843,7 @@ static void do_pf_read_start(void) | |||
| 844 | pi_do_claimed(pf_current->pi, do_pf_read_start); | 843 | pi_do_claimed(pf_current->pi, do_pf_read_start); |
| 845 | return; | 844 | return; |
| 846 | } | 845 | } |
| 847 | next_request(0); | 846 | next_request(-EIO); |
| 848 | return; | 847 | return; |
| 849 | } | 848 | } |
| 850 | pf_mask = STAT_DRQ; | 849 | pf_mask = STAT_DRQ; |
| @@ -863,7 +862,7 @@ static void do_pf_read_drq(void) | |||
| 863 | pi_do_claimed(pf_current->pi, do_pf_read_start); | 862 | pi_do_claimed(pf_current->pi, do_pf_read_start); |
| 864 | return; | 863 | return; |
| 865 | } | 864 | } |
| 866 | next_request(0); | 865 | next_request(-EIO); |
| 867 | return; | 866 | return; |
| 868 | } | 867 | } |
| 869 | pi_read_block(pf_current->pi, pf_buf, 512); | 868 | pi_read_block(pf_current->pi, pf_buf, 512); |
| @@ -871,7 +870,7 @@ static void do_pf_read_drq(void) | |||
| 871 | break; | 870 | break; |
| 872 | } | 871 | } |
| 873 | pi_disconnect(pf_current->pi); | 872 | pi_disconnect(pf_current->pi); |
| 874 | next_request(1); | 873 | next_request(0); |
| 875 | } | 874 | } |
| 876 | 875 | ||
| 877 | static void do_pf_write(void) | 876 | static void do_pf_write(void) |
| @@ -890,7 +889,7 @@ static void do_pf_write_start(void) | |||
| 890 | pi_do_claimed(pf_current->pi, do_pf_write_start); | 889 | pi_do_claimed(pf_current->pi, do_pf_write_start); |
| 891 | return; | 890 | return; |
| 892 | } | 891 | } |
| 893 | next_request(0); | 892 | next_request(-EIO); |
| 894 | return; | 893 | return; |
| 895 | } | 894 | } |
| 896 | 895 | ||
| @@ -903,7 +902,7 @@ static void do_pf_write_start(void) | |||
| 903 | pi_do_claimed(pf_current->pi, do_pf_write_start); | 902 | pi_do_claimed(pf_current->pi, do_pf_write_start); |
| 904 | return; | 903 | return; |
| 905 | } | 904 | } |
| 906 | next_request(0); | 905 | next_request(-EIO); |
| 907 | return; | 906 | return; |
| 908 | } | 907 | } |
| 909 | pi_write_block(pf_current->pi, pf_buf, 512); | 908 | pi_write_block(pf_current->pi, pf_buf, 512); |
| @@ -923,11 +922,11 @@ static void do_pf_write_done(void) | |||
| 923 | pi_do_claimed(pf_current->pi, do_pf_write_start); | 922 | pi_do_claimed(pf_current->pi, do_pf_write_start); |
| 924 | return; | 923 | return; |
| 925 | } | 924 | } |
| 926 | next_request(0); | 925 | next_request(-EIO); |
| 927 | return; | 926 | return; |
| 928 | } | 927 | } |
| 929 | pi_disconnect(pf_current->pi); | 928 | pi_disconnect(pf_current->pi); |
| 930 | next_request(1); | 929 | next_request(0); |
| 931 | } | 930 | } |
| 932 | 931 | ||
| 933 | static int __init pf_init(void) | 932 | static int __init pf_init(void) |
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c index dc7a8c352da2..d57f11759480 100644 --- a/drivers/block/pktcdvd.c +++ b/drivers/block/pktcdvd.c | |||
| @@ -991,13 +991,15 @@ static void pkt_iosched_process_queue(struct pktcdvd_device *pd) | |||
| 991 | */ | 991 | */ |
| 992 | static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q) | 992 | static int pkt_set_segment_merging(struct pktcdvd_device *pd, struct request_queue *q) |
| 993 | { | 993 | { |
| 994 | if ((pd->settings.size << 9) / CD_FRAMESIZE <= q->max_phys_segments) { | 994 | if ((pd->settings.size << 9) / CD_FRAMESIZE |
| 995 | <= queue_max_phys_segments(q)) { | ||
| 995 | /* | 996 | /* |
| 996 | * The cdrom device can handle one segment/frame | 997 | * The cdrom device can handle one segment/frame |
| 997 | */ | 998 | */ |
| 998 | clear_bit(PACKET_MERGE_SEGS, &pd->flags); | 999 | clear_bit(PACKET_MERGE_SEGS, &pd->flags); |
| 999 | return 0; | 1000 | return 0; |
| 1000 | } else if ((pd->settings.size << 9) / PAGE_SIZE <= q->max_phys_segments) { | 1001 | } else if ((pd->settings.size << 9) / PAGE_SIZE |
| 1002 | <= queue_max_phys_segments(q)) { | ||
| 1001 | /* | 1003 | /* |
| 1002 | * We can handle this case at the expense of some extra memory | 1004 | * We can handle this case at the expense of some extra memory |
| 1003 | * copies during write operations | 1005 | * copies during write operations |
| @@ -2657,7 +2659,7 @@ static void pkt_init_queue(struct pktcdvd_device *pd) | |||
| 2657 | struct request_queue *q = pd->disk->queue; | 2659 | struct request_queue *q = pd->disk->queue; |
| 2658 | 2660 | ||
| 2659 | blk_queue_make_request(q, pkt_make_request); | 2661 | blk_queue_make_request(q, pkt_make_request); |
| 2660 | blk_queue_hardsect_size(q, CD_FRAMESIZE); | 2662 | blk_queue_logical_block_size(q, CD_FRAMESIZE); |
| 2661 | blk_queue_max_sectors(q, PACKET_MAX_SECTORS); | 2663 | blk_queue_max_sectors(q, PACKET_MAX_SECTORS); |
| 2662 | blk_queue_merge_bvec(q, pkt_merge_bvec); | 2664 | blk_queue_merge_bvec(q, pkt_merge_bvec); |
| 2663 | q->queuedata = pd; | 2665 | q->queuedata = pd; |
diff --git a/drivers/block/ps3disk.c b/drivers/block/ps3disk.c index bccc42bb9212..aaeeb544228a 100644 --- a/drivers/block/ps3disk.c +++ b/drivers/block/ps3disk.c | |||
| @@ -134,13 +134,12 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, | |||
| 134 | rq_for_each_segment(bv, req, iter) | 134 | rq_for_each_segment(bv, req, iter) |
| 135 | n++; | 135 | n++; |
| 136 | dev_dbg(&dev->sbd.core, | 136 | dev_dbg(&dev->sbd.core, |
| 137 | "%s:%u: %s req has %u bvecs for %lu sectors %lu hard sectors\n", | 137 | "%s:%u: %s req has %u bvecs for %u sectors\n", |
| 138 | __func__, __LINE__, op, n, req->nr_sectors, | 138 | __func__, __LINE__, op, n, blk_rq_sectors(req)); |
| 139 | req->hard_nr_sectors); | ||
| 140 | #endif | 139 | #endif |
| 141 | 140 | ||
| 142 | start_sector = req->sector * priv->blocking_factor; | 141 | start_sector = blk_rq_pos(req) * priv->blocking_factor; |
| 143 | sectors = req->nr_sectors * priv->blocking_factor; | 142 | sectors = blk_rq_sectors(req) * priv->blocking_factor; |
| 144 | dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n", | 143 | dev_dbg(&dev->sbd.core, "%s:%u: %s %llu sectors starting at %llu\n", |
| 145 | __func__, __LINE__, op, sectors, start_sector); | 144 | __func__, __LINE__, op, sectors, start_sector); |
| 146 | 145 | ||
| @@ -158,7 +157,7 @@ static int ps3disk_submit_request_sg(struct ps3_storage_device *dev, | |||
| 158 | if (res) { | 157 | if (res) { |
| 159 | dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, | 158 | dev_err(&dev->sbd.core, "%s:%u: %s failed %d\n", __func__, |
| 160 | __LINE__, op, res); | 159 | __LINE__, op, res); |
| 161 | end_request(req, 0); | 160 | __blk_end_request_all(req, -EIO); |
| 162 | return 0; | 161 | return 0; |
| 163 | } | 162 | } |
| 164 | 163 | ||
| @@ -180,7 +179,7 @@ static int ps3disk_submit_flush_request(struct ps3_storage_device *dev, | |||
| 180 | if (res) { | 179 | if (res) { |
| 181 | dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n", | 180 | dev_err(&dev->sbd.core, "%s:%u: sync cache failed 0x%llx\n", |
| 182 | __func__, __LINE__, res); | 181 | __func__, __LINE__, res); |
| 183 | end_request(req, 0); | 182 | __blk_end_request_all(req, -EIO); |
| 184 | return 0; | 183 | return 0; |
| 185 | } | 184 | } |
| 186 | 185 | ||
| @@ -195,7 +194,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, | |||
| 195 | 194 | ||
| 196 | dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); | 195 | dev_dbg(&dev->sbd.core, "%s:%u\n", __func__, __LINE__); |
| 197 | 196 | ||
| 198 | while ((req = elv_next_request(q))) { | 197 | while ((req = blk_fetch_request(q))) { |
| 199 | if (blk_fs_request(req)) { | 198 | if (blk_fs_request(req)) { |
| 200 | if (ps3disk_submit_request_sg(dev, req)) | 199 | if (ps3disk_submit_request_sg(dev, req)) |
| 201 | break; | 200 | break; |
| @@ -205,7 +204,7 @@ static void ps3disk_do_request(struct ps3_storage_device *dev, | |||
| 205 | break; | 204 | break; |
| 206 | } else { | 205 | } else { |
| 207 | blk_dump_rq_flags(req, DEVICE_NAME " bad request"); | 206 | blk_dump_rq_flags(req, DEVICE_NAME " bad request"); |
| 208 | end_request(req, 0); | 207 | __blk_end_request_all(req, -EIO); |
| 209 | continue; | 208 | continue; |
| 210 | } | 209 | } |
| 211 | } | 210 | } |
| @@ -231,7 +230,6 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) | |||
| 231 | struct request *req; | 230 | struct request *req; |
| 232 | int res, read, error; | 231 | int res, read, error; |
| 233 | u64 tag, status; | 232 | u64 tag, status; |
| 234 | unsigned long num_sectors; | ||
| 235 | const char *op; | 233 | const char *op; |
| 236 | 234 | ||
| 237 | res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); | 235 | res = lv1_storage_get_async_status(dev->sbd.dev_id, &tag, &status); |
| @@ -261,11 +259,9 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) | |||
| 261 | if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && | 259 | if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && |
| 262 | req->cmd[0] == REQ_LB_OP_FLUSH) { | 260 | req->cmd[0] == REQ_LB_OP_FLUSH) { |
| 263 | read = 0; | 261 | read = 0; |
| 264 | num_sectors = req->hard_cur_sectors; | ||
| 265 | op = "flush"; | 262 | op = "flush"; |
| 266 | } else { | 263 | } else { |
| 267 | read = !rq_data_dir(req); | 264 | read = !rq_data_dir(req); |
| 268 | num_sectors = req->nr_sectors; | ||
| 269 | op = read ? "read" : "write"; | 265 | op = read ? "read" : "write"; |
| 270 | } | 266 | } |
| 271 | if (status) { | 267 | if (status) { |
| @@ -281,7 +277,7 @@ static irqreturn_t ps3disk_interrupt(int irq, void *data) | |||
| 281 | } | 277 | } |
| 282 | 278 | ||
| 283 | spin_lock(&priv->lock); | 279 | spin_lock(&priv->lock); |
| 284 | __blk_end_request(req, error, num_sectors << 9); | 280 | __blk_end_request_all(req, error); |
| 285 | priv->req = NULL; | 281 | priv->req = NULL; |
| 286 | ps3disk_do_request(dev, priv->queue); | 282 | ps3disk_do_request(dev, priv->queue); |
| 287 | spin_unlock(&priv->lock); | 283 | spin_unlock(&priv->lock); |
| @@ -481,7 +477,7 @@ static int __devinit ps3disk_probe(struct ps3_system_bus_device *_dev) | |||
| 481 | blk_queue_max_sectors(queue, dev->bounce_size >> 9); | 477 | blk_queue_max_sectors(queue, dev->bounce_size >> 9); |
| 482 | blk_queue_segment_boundary(queue, -1UL); | 478 | blk_queue_segment_boundary(queue, -1UL); |
| 483 | blk_queue_dma_alignment(queue, dev->blk_size-1); | 479 | blk_queue_dma_alignment(queue, dev->blk_size-1); |
| 484 | blk_queue_hardsect_size(queue, dev->blk_size); | 480 | blk_queue_logical_block_size(queue, dev->blk_size); |
| 485 | 481 | ||
| 486 | blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH, | 482 | blk_queue_ordered(queue, QUEUE_ORDERED_DRAIN_FLUSH, |
| 487 | ps3disk_prepare_flush); | 483 | ps3disk_prepare_flush); |
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index 5861e33efe63..cbfd9c0aef03 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c | |||
| @@ -212,11 +212,6 @@ static void vdc_end_special(struct vdc_port *port, struct vio_disk_desc *desc) | |||
| 212 | vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD); | 212 | vdc_finish(&port->vio, -err, WAITING_FOR_GEN_CMD); |
| 213 | } | 213 | } |
| 214 | 214 | ||
| 215 | static void vdc_end_request(struct request *req, int error, int num_sectors) | ||
| 216 | { | ||
| 217 | __blk_end_request(req, error, num_sectors << 9); | ||
| 218 | } | ||
| 219 | |||
| 220 | static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, | 215 | static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, |
| 221 | unsigned int index) | 216 | unsigned int index) |
| 222 | { | 217 | { |
| @@ -239,7 +234,7 @@ static void vdc_end_one(struct vdc_port *port, struct vio_dring_state *dr, | |||
| 239 | 234 | ||
| 240 | rqe->req = NULL; | 235 | rqe->req = NULL; |
| 241 | 236 | ||
| 242 | vdc_end_request(req, (desc->status ? -EIO : 0), desc->size >> 9); | 237 | __blk_end_request(req, (desc->status ? -EIO : 0), desc->size); |
| 243 | 238 | ||
| 244 | if (blk_queue_stopped(port->disk->queue)) | 239 | if (blk_queue_stopped(port->disk->queue)) |
| 245 | blk_start_queue(port->disk->queue); | 240 | blk_start_queue(port->disk->queue); |
| @@ -421,7 +416,7 @@ static int __send_request(struct request *req) | |||
| 421 | desc->slice = 0; | 416 | desc->slice = 0; |
| 422 | } | 417 | } |
| 423 | desc->status = ~0; | 418 | desc->status = ~0; |
| 424 | desc->offset = (req->sector << 9) / port->vdisk_block_size; | 419 | desc->offset = (blk_rq_pos(req) << 9) / port->vdisk_block_size; |
| 425 | desc->size = len; | 420 | desc->size = len; |
| 426 | desc->ncookies = err; | 421 | desc->ncookies = err; |
| 427 | 422 | ||
| @@ -446,14 +441,13 @@ out: | |||
| 446 | static void do_vdc_request(struct request_queue *q) | 441 | static void do_vdc_request(struct request_queue *q) |
| 447 | { | 442 | { |
| 448 | while (1) { | 443 | while (1) { |
| 449 | struct request *req = elv_next_request(q); | 444 | struct request *req = blk_fetch_request(q); |
| 450 | 445 | ||
| 451 | if (!req) | 446 | if (!req) |
| 452 | break; | 447 | break; |
| 453 | 448 | ||
| 454 | blkdev_dequeue_request(req); | ||
| 455 | if (__send_request(req) < 0) | 449 | if (__send_request(req) < 0) |
| 456 | vdc_end_request(req, -EIO, req->hard_nr_sectors); | 450 | __blk_end_request_all(req, -EIO); |
| 457 | } | 451 | } |
| 458 | } | 452 | } |
| 459 | 453 | ||
diff --git a/drivers/block/swim.c b/drivers/block/swim.c index d22cc3856937..cf7877fb8a7d 100644 --- a/drivers/block/swim.c +++ b/drivers/block/swim.c | |||
| @@ -514,7 +514,7 @@ static int floppy_read_sectors(struct floppy_state *fs, | |||
| 514 | ret = swim_read_sector(fs, side, track, sector, | 514 | ret = swim_read_sector(fs, side, track, sector, |
| 515 | buffer); | 515 | buffer); |
| 516 | if (try-- == 0) | 516 | if (try-- == 0) |
| 517 | return -1; | 517 | return -EIO; |
| 518 | } while (ret != 512); | 518 | } while (ret != 512); |
| 519 | 519 | ||
| 520 | buffer += ret; | 520 | buffer += ret; |
| @@ -528,45 +528,31 @@ static void redo_fd_request(struct request_queue *q) | |||
| 528 | struct request *req; | 528 | struct request *req; |
| 529 | struct floppy_state *fs; | 529 | struct floppy_state *fs; |
| 530 | 530 | ||
| 531 | while ((req = elv_next_request(q))) { | 531 | req = blk_fetch_request(q); |
| 532 | while (req) { | ||
| 533 | int err = -EIO; | ||
| 532 | 534 | ||
| 533 | fs = req->rq_disk->private_data; | 535 | fs = req->rq_disk->private_data; |
| 534 | if (req->sector < 0 || req->sector >= fs->total_secs) { | 536 | if (blk_rq_pos(req) >= fs->total_secs) |
| 535 | end_request(req, 0); | 537 | goto done; |
| 536 | continue; | 538 | if (!fs->disk_in) |
| 537 | } | 539 | goto done; |
| 538 | if (req->current_nr_sectors == 0) { | 540 | if (rq_data_dir(req) == WRITE && fs->write_protected) |
| 539 | end_request(req, 1); | 541 | goto done; |
| 540 | continue; | 542 | |
| 541 | } | ||
| 542 | if (!fs->disk_in) { | ||
| 543 | end_request(req, 0); | ||
| 544 | continue; | ||
| 545 | } | ||
| 546 | if (rq_data_dir(req) == WRITE) { | ||
| 547 | if (fs->write_protected) { | ||
| 548 | end_request(req, 0); | ||
| 549 | continue; | ||
| 550 | } | ||
| 551 | } | ||
| 552 | switch (rq_data_dir(req)) { | 543 | switch (rq_data_dir(req)) { |
| 553 | case WRITE: | 544 | case WRITE: |
| 554 | /* NOT IMPLEMENTED */ | 545 | /* NOT IMPLEMENTED */ |
| 555 | end_request(req, 0); | ||
| 556 | break; | 546 | break; |
| 557 | case READ: | 547 | case READ: |
| 558 | if (floppy_read_sectors(fs, req->sector, | 548 | err = floppy_read_sectors(fs, blk_rq_pos(req), |
| 559 | req->current_nr_sectors, | 549 | blk_rq_cur_sectors(req), |
| 560 | req->buffer)) { | 550 | req->buffer); |
| 561 | end_request(req, 0); | ||
| 562 | continue; | ||
| 563 | } | ||
| 564 | req->nr_sectors -= req->current_nr_sectors; | ||
| 565 | req->sector += req->current_nr_sectors; | ||
| 566 | req->buffer += req->current_nr_sectors * 512; | ||
| 567 | end_request(req, 1); | ||
| 568 | break; | 551 | break; |
| 569 | } | 552 | } |
| 553 | done: | ||
| 554 | if (!__blk_end_request_cur(req, err)) | ||
| 555 | req = blk_fetch_request(q); | ||
| 570 | } | 556 | } |
| 571 | } | 557 | } |
| 572 | 558 | ||
diff --git a/drivers/block/swim3.c b/drivers/block/swim3.c index 612965307ba0..80df93e3cdd0 100644 --- a/drivers/block/swim3.c +++ b/drivers/block/swim3.c | |||
| @@ -251,6 +251,20 @@ static int floppy_release(struct gendisk *disk, fmode_t mode); | |||
| 251 | static int floppy_check_change(struct gendisk *disk); | 251 | static int floppy_check_change(struct gendisk *disk); |
| 252 | static int floppy_revalidate(struct gendisk *disk); | 252 | static int floppy_revalidate(struct gendisk *disk); |
| 253 | 253 | ||
| 254 | static bool swim3_end_request(int err, unsigned int nr_bytes) | ||
| 255 | { | ||
| 256 | if (__blk_end_request(fd_req, err, nr_bytes)) | ||
| 257 | return true; | ||
| 258 | |||
| 259 | fd_req = NULL; | ||
| 260 | return false; | ||
| 261 | } | ||
| 262 | |||
| 263 | static bool swim3_end_request_cur(int err) | ||
| 264 | { | ||
| 265 | return swim3_end_request(err, blk_rq_cur_bytes(fd_req)); | ||
| 266 | } | ||
| 267 | |||
| 254 | static void swim3_select(struct floppy_state *fs, int sel) | 268 | static void swim3_select(struct floppy_state *fs, int sel) |
| 255 | { | 269 | { |
| 256 | struct swim3 __iomem *sw = fs->swim3; | 270 | struct swim3 __iomem *sw = fs->swim3; |
| @@ -310,25 +324,27 @@ static void start_request(struct floppy_state *fs) | |||
| 310 | wake_up(&fs->wait); | 324 | wake_up(&fs->wait); |
| 311 | return; | 325 | return; |
| 312 | } | 326 | } |
| 313 | while (fs->state == idle && (req = elv_next_request(swim3_queue))) { | 327 | while (fs->state == idle) { |
| 328 | if (!fd_req) { | ||
| 329 | fd_req = blk_fetch_request(swim3_queue); | ||
| 330 | if (!fd_req) | ||
| 331 | break; | ||
| 332 | } | ||
| 333 | req = fd_req; | ||
| 314 | #if 0 | 334 | #if 0 |
| 315 | printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%ld buf=%p\n", | 335 | printk("do_fd_req: dev=%s cmd=%d sec=%ld nr_sec=%u buf=%p\n", |
| 316 | req->rq_disk->disk_name, req->cmd, | 336 | req->rq_disk->disk_name, req->cmd, |
| 317 | (long)req->sector, req->nr_sectors, req->buffer); | 337 | (long)blk_rq_pos(req), blk_rq_sectors(req), req->buffer); |
| 318 | printk(" errors=%d current_nr_sectors=%ld\n", | 338 | printk(" errors=%d current_nr_sectors=%u\n", |
| 319 | req->errors, req->current_nr_sectors); | 339 | req->errors, blk_rq_cur_sectors(req)); |
| 320 | #endif | 340 | #endif |
| 321 | 341 | ||
| 322 | if (req->sector < 0 || req->sector >= fs->total_secs) { | 342 | if (blk_rq_pos(req) >= fs->total_secs) { |
| 323 | end_request(req, 0); | 343 | swim3_end_request_cur(-EIO); |
| 324 | continue; | ||
| 325 | } | ||
| 326 | if (req->current_nr_sectors == 0) { | ||
| 327 | end_request(req, 1); | ||
| 328 | continue; | 344 | continue; |
| 329 | } | 345 | } |
| 330 | if (fs->ejected) { | 346 | if (fs->ejected) { |
| 331 | end_request(req, 0); | 347 | swim3_end_request_cur(-EIO); |
| 332 | continue; | 348 | continue; |
| 333 | } | 349 | } |
| 334 | 350 | ||
| @@ -336,18 +352,19 @@ static void start_request(struct floppy_state *fs) | |||
| 336 | if (fs->write_prot < 0) | 352 | if (fs->write_prot < 0) |
| 337 | fs->write_prot = swim3_readbit(fs, WRITE_PROT); | 353 | fs->write_prot = swim3_readbit(fs, WRITE_PROT); |
| 338 | if (fs->write_prot) { | 354 | if (fs->write_prot) { |
| 339 | end_request(req, 0); | 355 | swim3_end_request_cur(-EIO); |
| 340 | continue; | 356 | continue; |
| 341 | } | 357 | } |
| 342 | } | 358 | } |
| 343 | 359 | ||
| 344 | /* Do not remove the cast. req->sector is now a sector_t and | 360 | /* Do not remove the cast. blk_rq_pos(req) is now a |
| 345 | * can be 64 bits, but it will never go past 32 bits for this | 361 | * sector_t and can be 64 bits, but it will never go |
| 346 | * driver anyway, so we can safely cast it down and not have | 362 | * past 32 bits for this driver anyway, so we can |
| 347 | * to do a 64/32 division | 363 | * safely cast it down and not have to do a 64/32 |
| 364 | * division | ||
| 348 | */ | 365 | */ |
| 349 | fs->req_cyl = ((long)req->sector) / fs->secpercyl; | 366 | fs->req_cyl = ((long)blk_rq_pos(req)) / fs->secpercyl; |
| 350 | x = ((long)req->sector) % fs->secpercyl; | 367 | x = ((long)blk_rq_pos(req)) % fs->secpercyl; |
| 351 | fs->head = x / fs->secpertrack; | 368 | fs->head = x / fs->secpertrack; |
| 352 | fs->req_sector = x % fs->secpertrack + 1; | 369 | fs->req_sector = x % fs->secpertrack + 1; |
| 353 | fd_req = req; | 370 | fd_req = req; |
| @@ -424,7 +441,7 @@ static inline void setup_transfer(struct floppy_state *fs) | |||
| 424 | struct dbdma_cmd *cp = fs->dma_cmd; | 441 | struct dbdma_cmd *cp = fs->dma_cmd; |
| 425 | struct dbdma_regs __iomem *dr = fs->dma; | 442 | struct dbdma_regs __iomem *dr = fs->dma; |
| 426 | 443 | ||
| 427 | if (fd_req->current_nr_sectors <= 0) { | 444 | if (blk_rq_cur_sectors(fd_req) <= 0) { |
| 428 | printk(KERN_ERR "swim3: transfer 0 sectors?\n"); | 445 | printk(KERN_ERR "swim3: transfer 0 sectors?\n"); |
| 429 | return; | 446 | return; |
| 430 | } | 447 | } |
| @@ -432,8 +449,8 @@ static inline void setup_transfer(struct floppy_state *fs) | |||
| 432 | n = 1; | 449 | n = 1; |
| 433 | else { | 450 | else { |
| 434 | n = fs->secpertrack - fs->req_sector + 1; | 451 | n = fs->secpertrack - fs->req_sector + 1; |
| 435 | if (n > fd_req->current_nr_sectors) | 452 | if (n > blk_rq_cur_sectors(fd_req)) |
| 436 | n = fd_req->current_nr_sectors; | 453 | n = blk_rq_cur_sectors(fd_req); |
| 437 | } | 454 | } |
| 438 | fs->scount = n; | 455 | fs->scount = n; |
| 439 | swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); | 456 | swim3_select(fs, fs->head? READ_DATA_1: READ_DATA_0); |
| @@ -508,7 +525,7 @@ static void act(struct floppy_state *fs) | |||
| 508 | case do_transfer: | 525 | case do_transfer: |
| 509 | if (fs->cur_cyl != fs->req_cyl) { | 526 | if (fs->cur_cyl != fs->req_cyl) { |
| 510 | if (fs->retries > 5) { | 527 | if (fs->retries > 5) { |
| 511 | end_request(fd_req, 0); | 528 | swim3_end_request_cur(-EIO); |
| 512 | fs->state = idle; | 529 | fs->state = idle; |
| 513 | return; | 530 | return; |
| 514 | } | 531 | } |
| @@ -540,7 +557,7 @@ static void scan_timeout(unsigned long data) | |||
| 540 | out_8(&sw->intr_enable, 0); | 557 | out_8(&sw->intr_enable, 0); |
| 541 | fs->cur_cyl = -1; | 558 | fs->cur_cyl = -1; |
| 542 | if (fs->retries > 5) { | 559 | if (fs->retries > 5) { |
| 543 | end_request(fd_req, 0); | 560 | swim3_end_request_cur(-EIO); |
| 544 | fs->state = idle; | 561 | fs->state = idle; |
| 545 | start_request(fs); | 562 | start_request(fs); |
| 546 | } else { | 563 | } else { |
| @@ -559,7 +576,7 @@ static void seek_timeout(unsigned long data) | |||
| 559 | out_8(&sw->select, RELAX); | 576 | out_8(&sw->select, RELAX); |
| 560 | out_8(&sw->intr_enable, 0); | 577 | out_8(&sw->intr_enable, 0); |
| 561 | printk(KERN_ERR "swim3: seek timeout\n"); | 578 | printk(KERN_ERR "swim3: seek timeout\n"); |
| 562 | end_request(fd_req, 0); | 579 | swim3_end_request_cur(-EIO); |
| 563 | fs->state = idle; | 580 | fs->state = idle; |
| 564 | start_request(fs); | 581 | start_request(fs); |
| 565 | } | 582 | } |
| @@ -583,7 +600,7 @@ static void settle_timeout(unsigned long data) | |||
| 583 | return; | 600 | return; |
| 584 | } | 601 | } |
| 585 | printk(KERN_ERR "swim3: seek settle timeout\n"); | 602 | printk(KERN_ERR "swim3: seek settle timeout\n"); |
| 586 | end_request(fd_req, 0); | 603 | swim3_end_request_cur(-EIO); |
| 587 | fs->state = idle; | 604 | fs->state = idle; |
| 588 | start_request(fs); | 605 | start_request(fs); |
| 589 | } | 606 | } |
| @@ -593,8 +610,6 @@ static void xfer_timeout(unsigned long data) | |||
| 593 | struct floppy_state *fs = (struct floppy_state *) data; | 610 | struct floppy_state *fs = (struct floppy_state *) data; |
| 594 | struct swim3 __iomem *sw = fs->swim3; | 611 | struct swim3 __iomem *sw = fs->swim3; |
| 595 | struct dbdma_regs __iomem *dr = fs->dma; | 612 | struct dbdma_regs __iomem *dr = fs->dma; |
| 596 | struct dbdma_cmd *cp = fs->dma_cmd; | ||
| 597 | unsigned long s; | ||
| 598 | int n; | 613 | int n; |
| 599 | 614 | ||
| 600 | fs->timeout_pending = 0; | 615 | fs->timeout_pending = 0; |
| @@ -605,17 +620,10 @@ static void xfer_timeout(unsigned long data) | |||
| 605 | out_8(&sw->intr_enable, 0); | 620 | out_8(&sw->intr_enable, 0); |
| 606 | out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); | 621 | out_8(&sw->control_bic, WRITE_SECTORS | DO_ACTION); |
| 607 | out_8(&sw->select, RELAX); | 622 | out_8(&sw->select, RELAX); |
| 608 | if (rq_data_dir(fd_req) == WRITE) | ||
| 609 | ++cp; | ||
| 610 | if (ld_le16(&cp->xfer_status) != 0) | ||
| 611 | s = fs->scount - ((ld_le16(&cp->res_count) + 511) >> 9); | ||
| 612 | else | ||
| 613 | s = 0; | ||
| 614 | fd_req->sector += s; | ||
| 615 | fd_req->current_nr_sectors -= s; | ||
| 616 | printk(KERN_ERR "swim3: timeout %sing sector %ld\n", | 623 | printk(KERN_ERR "swim3: timeout %sing sector %ld\n", |
| 617 | (rq_data_dir(fd_req)==WRITE? "writ": "read"), (long)fd_req->sector); | 624 | (rq_data_dir(fd_req)==WRITE? "writ": "read"), |
| 618 | end_request(fd_req, 0); | 625 | (long)blk_rq_pos(fd_req)); |
| 626 | swim3_end_request_cur(-EIO); | ||
| 619 | fs->state = idle; | 627 | fs->state = idle; |
| 620 | start_request(fs); | 628 | start_request(fs); |
| 621 | } | 629 | } |
| @@ -646,7 +654,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) | |||
| 646 | printk(KERN_ERR "swim3: seen sector but cyl=ff?\n"); | 654 | printk(KERN_ERR "swim3: seen sector but cyl=ff?\n"); |
| 647 | fs->cur_cyl = -1; | 655 | fs->cur_cyl = -1; |
| 648 | if (fs->retries > 5) { | 656 | if (fs->retries > 5) { |
| 649 | end_request(fd_req, 0); | 657 | swim3_end_request_cur(-EIO); |
| 650 | fs->state = idle; | 658 | fs->state = idle; |
| 651 | start_request(fs); | 659 | start_request(fs); |
| 652 | } else { | 660 | } else { |
| @@ -719,9 +727,7 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) | |||
| 719 | if (intr & ERROR_INTR) { | 727 | if (intr & ERROR_INTR) { |
| 720 | n = fs->scount - 1 - resid / 512; | 728 | n = fs->scount - 1 - resid / 512; |
| 721 | if (n > 0) { | 729 | if (n > 0) { |
| 722 | fd_req->sector += n; | 730 | blk_update_request(fd_req, 0, n << 9); |
| 723 | fd_req->current_nr_sectors -= n; | ||
| 724 | fd_req->buffer += n * 512; | ||
| 725 | fs->req_sector += n; | 731 | fs->req_sector += n; |
| 726 | } | 732 | } |
| 727 | if (fs->retries < 5) { | 733 | if (fs->retries < 5) { |
| @@ -730,8 +736,8 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) | |||
| 730 | } else { | 736 | } else { |
| 731 | printk("swim3: error %sing block %ld (err=%x)\n", | 737 | printk("swim3: error %sing block %ld (err=%x)\n", |
| 732 | rq_data_dir(fd_req) == WRITE? "writ": "read", | 738 | rq_data_dir(fd_req) == WRITE? "writ": "read", |
| 733 | (long)fd_req->sector, err); | 739 | (long)blk_rq_pos(fd_req), err); |
| 734 | end_request(fd_req, 0); | 740 | swim3_end_request_cur(-EIO); |
| 735 | fs->state = idle; | 741 | fs->state = idle; |
| 736 | } | 742 | } |
| 737 | } else { | 743 | } else { |
| @@ -740,18 +746,12 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) | |||
| 740 | printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid); | 746 | printk(KERN_ERR "swim3: fd dma: stat=%x resid=%d\n", stat, resid); |
| 741 | printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n", | 747 | printk(KERN_ERR " state=%d, dir=%x, intr=%x, err=%x\n", |
| 742 | fs->state, rq_data_dir(fd_req), intr, err); | 748 | fs->state, rq_data_dir(fd_req), intr, err); |
| 743 | end_request(fd_req, 0); | 749 | swim3_end_request_cur(-EIO); |
| 744 | fs->state = idle; | 750 | fs->state = idle; |
| 745 | start_request(fs); | 751 | start_request(fs); |
| 746 | break; | 752 | break; |
| 747 | } | 753 | } |
| 748 | fd_req->sector += fs->scount; | 754 | if (swim3_end_request(0, fs->scount << 9)) { |
| 749 | fd_req->current_nr_sectors -= fs->scount; | ||
| 750 | fd_req->buffer += fs->scount * 512; | ||
| 751 | if (fd_req->current_nr_sectors <= 0) { | ||
| 752 | end_request(fd_req, 1); | ||
| 753 | fs->state = idle; | ||
| 754 | } else { | ||
| 755 | fs->req_sector += fs->scount; | 755 | fs->req_sector += fs->scount; |
| 756 | if (fs->req_sector > fs->secpertrack) { | 756 | if (fs->req_sector > fs->secpertrack) { |
| 757 | fs->req_sector -= fs->secpertrack; | 757 | fs->req_sector -= fs->secpertrack; |
| @@ -761,7 +761,8 @@ static irqreturn_t swim3_interrupt(int irq, void *dev_id) | |||
| 761 | } | 761 | } |
| 762 | } | 762 | } |
| 763 | act(fs); | 763 | act(fs); |
| 764 | } | 764 | } else |
| 765 | fs->state = idle; | ||
| 765 | } | 766 | } |
| 766 | if (fs->state == idle) | 767 | if (fs->state == idle) |
| 767 | start_request(fs); | 768 | start_request(fs); |
diff --git a/drivers/block/sx8.c b/drivers/block/sx8.c index ff0448e4bf03..da403b6a7f43 100644 --- a/drivers/block/sx8.c +++ b/drivers/block/sx8.c | |||
| @@ -749,8 +749,7 @@ static inline void carm_end_request_queued(struct carm_host *host, | |||
| 749 | struct request *req = crq->rq; | 749 | struct request *req = crq->rq; |
| 750 | int rc; | 750 | int rc; |
| 751 | 751 | ||
| 752 | rc = __blk_end_request(req, error, blk_rq_bytes(req)); | 752 | __blk_end_request_all(req, error); |
| 753 | assert(rc == 0); | ||
| 754 | 753 | ||
| 755 | rc = carm_put_request(host, crq); | 754 | rc = carm_put_request(host, crq); |
| 756 | assert(rc == 0); | 755 | assert(rc == 0); |
| @@ -811,12 +810,10 @@ static void carm_oob_rq_fn(struct request_queue *q) | |||
| 811 | 810 | ||
| 812 | while (1) { | 811 | while (1) { |
| 813 | DPRINTK("get req\n"); | 812 | DPRINTK("get req\n"); |
| 814 | rq = elv_next_request(q); | 813 | rq = blk_fetch_request(q); |
| 815 | if (!rq) | 814 | if (!rq) |
| 816 | break; | 815 | break; |
| 817 | 816 | ||
| 818 | blkdev_dequeue_request(rq); | ||
| 819 | |||
| 820 | crq = rq->special; | 817 | crq = rq->special; |
| 821 | assert(crq != NULL); | 818 | assert(crq != NULL); |
| 822 | assert(crq->rq == rq); | 819 | assert(crq->rq == rq); |
| @@ -847,7 +844,7 @@ static void carm_rq_fn(struct request_queue *q) | |||
| 847 | 844 | ||
| 848 | queue_one_request: | 845 | queue_one_request: |
| 849 | VPRINTK("get req\n"); | 846 | VPRINTK("get req\n"); |
| 850 | rq = elv_next_request(q); | 847 | rq = blk_peek_request(q); |
| 851 | if (!rq) | 848 | if (!rq) |
| 852 | return; | 849 | return; |
| 853 | 850 | ||
| @@ -858,7 +855,7 @@ queue_one_request: | |||
| 858 | } | 855 | } |
| 859 | crq->rq = rq; | 856 | crq->rq = rq; |
| 860 | 857 | ||
| 861 | blkdev_dequeue_request(rq); | 858 | blk_start_request(rq); |
| 862 | 859 | ||
| 863 | if (rq_data_dir(rq) == WRITE) { | 860 | if (rq_data_dir(rq) == WRITE) { |
| 864 | writing = 1; | 861 | writing = 1; |
| @@ -904,10 +901,10 @@ queue_one_request: | |||
| 904 | msg->sg_count = n_elem; | 901 | msg->sg_count = n_elem; |
| 905 | msg->sg_type = SGT_32BIT; | 902 | msg->sg_type = SGT_32BIT; |
| 906 | msg->handle = cpu_to_le32(TAG_ENCODE(crq->tag)); | 903 | msg->handle = cpu_to_le32(TAG_ENCODE(crq->tag)); |
| 907 | msg->lba = cpu_to_le32(rq->sector & 0xffffffff); | 904 | msg->lba = cpu_to_le32(blk_rq_pos(rq) & 0xffffffff); |
| 908 | tmp = (rq->sector >> 16) >> 16; | 905 | tmp = (blk_rq_pos(rq) >> 16) >> 16; |
| 909 | msg->lba_high = cpu_to_le16( (u16) tmp ); | 906 | msg->lba_high = cpu_to_le16( (u16) tmp ); |
| 910 | msg->lba_count = cpu_to_le16(rq->nr_sectors); | 907 | msg->lba_count = cpu_to_le16(blk_rq_sectors(rq)); |
| 911 | 908 | ||
| 912 | msg_size = sizeof(struct carm_msg_rw) - sizeof(msg->sg); | 909 | msg_size = sizeof(struct carm_msg_rw) - sizeof(msg->sg); |
| 913 | for (i = 0; i < n_elem; i++) { | 910 | for (i = 0; i < n_elem; i++) { |
diff --git a/drivers/block/ub.c b/drivers/block/ub.c index 689cd27ac890..cc54473b8e77 100644 --- a/drivers/block/ub.c +++ b/drivers/block/ub.c | |||
| @@ -360,8 +360,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | |||
| 360 | static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, | 360 | static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, |
| 361 | struct ub_scsi_cmd *cmd, struct ub_request *urq); | 361 | struct ub_scsi_cmd *cmd, struct ub_request *urq); |
| 362 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 362 | static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
| 363 | static void ub_end_rq(struct request *rq, unsigned int status, | 363 | static void ub_end_rq(struct request *rq, unsigned int status); |
| 364 | unsigned int cmd_len); | ||
| 365 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, | 364 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, |
| 366 | struct ub_request *urq, struct ub_scsi_cmd *cmd); | 365 | struct ub_request *urq, struct ub_scsi_cmd *cmd); |
| 367 | static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); | 366 | static int ub_submit_scsi(struct ub_dev *sc, struct ub_scsi_cmd *cmd); |
| @@ -627,7 +626,7 @@ static void ub_request_fn(struct request_queue *q) | |||
| 627 | struct ub_lun *lun = q->queuedata; | 626 | struct ub_lun *lun = q->queuedata; |
| 628 | struct request *rq; | 627 | struct request *rq; |
| 629 | 628 | ||
| 630 | while ((rq = elv_next_request(q)) != NULL) { | 629 | while ((rq = blk_peek_request(q)) != NULL) { |
| 631 | if (ub_request_fn_1(lun, rq) != 0) { | 630 | if (ub_request_fn_1(lun, rq) != 0) { |
| 632 | blk_stop_queue(q); | 631 | blk_stop_queue(q); |
| 633 | break; | 632 | break; |
| @@ -643,14 +642,14 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) | |||
| 643 | int n_elem; | 642 | int n_elem; |
| 644 | 643 | ||
| 645 | if (atomic_read(&sc->poison)) { | 644 | if (atomic_read(&sc->poison)) { |
| 646 | blkdev_dequeue_request(rq); | 645 | blk_start_request(rq); |
| 647 | ub_end_rq(rq, DID_NO_CONNECT << 16, blk_rq_bytes(rq)); | 646 | ub_end_rq(rq, DID_NO_CONNECT << 16); |
| 648 | return 0; | 647 | return 0; |
| 649 | } | 648 | } |
| 650 | 649 | ||
| 651 | if (lun->changed && !blk_pc_request(rq)) { | 650 | if (lun->changed && !blk_pc_request(rq)) { |
| 652 | blkdev_dequeue_request(rq); | 651 | blk_start_request(rq); |
| 653 | ub_end_rq(rq, SAM_STAT_CHECK_CONDITION, blk_rq_bytes(rq)); | 652 | ub_end_rq(rq, SAM_STAT_CHECK_CONDITION); |
| 654 | return 0; | 653 | return 0; |
| 655 | } | 654 | } |
| 656 | 655 | ||
| @@ -660,7 +659,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) | |||
| 660 | return -1; | 659 | return -1; |
| 661 | memset(cmd, 0, sizeof(struct ub_scsi_cmd)); | 660 | memset(cmd, 0, sizeof(struct ub_scsi_cmd)); |
| 662 | 661 | ||
| 663 | blkdev_dequeue_request(rq); | 662 | blk_start_request(rq); |
| 664 | 663 | ||
| 665 | urq = &lun->urq; | 664 | urq = &lun->urq; |
| 666 | memset(urq, 0, sizeof(struct ub_request)); | 665 | memset(urq, 0, sizeof(struct ub_request)); |
| @@ -702,7 +701,7 @@ static int ub_request_fn_1(struct ub_lun *lun, struct request *rq) | |||
| 702 | 701 | ||
| 703 | drop: | 702 | drop: |
| 704 | ub_put_cmd(lun, cmd); | 703 | ub_put_cmd(lun, cmd); |
| 705 | ub_end_rq(rq, DID_ERROR << 16, blk_rq_bytes(rq)); | 704 | ub_end_rq(rq, DID_ERROR << 16); |
| 706 | return 0; | 705 | return 0; |
| 707 | } | 706 | } |
| 708 | 707 | ||
| @@ -723,11 +722,11 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | |||
| 723 | /* | 722 | /* |
| 724 | * build the command | 723 | * build the command |
| 725 | * | 724 | * |
| 726 | * The call to blk_queue_hardsect_size() guarantees that request | 725 | * The call to blk_queue_logical_block_size() guarantees that request |
| 727 | * is aligned, but it is given in terms of 512 byte units, always. | 726 | * is aligned, but it is given in terms of 512 byte units, always. |
| 728 | */ | 727 | */ |
| 729 | block = rq->sector >> lun->capacity.bshift; | 728 | block = blk_rq_pos(rq) >> lun->capacity.bshift; |
| 730 | nblks = rq->nr_sectors >> lun->capacity.bshift; | 729 | nblks = blk_rq_sectors(rq) >> lun->capacity.bshift; |
| 731 | 730 | ||
| 732 | cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10; | 731 | cmd->cdb[0] = (cmd->dir == UB_DIR_READ)? READ_10: WRITE_10; |
| 733 | /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */ | 732 | /* 10-byte uses 4 bytes of LBA: 2147483648KB, 2097152MB, 2048GB */ |
| @@ -739,7 +738,7 @@ static void ub_cmd_build_block(struct ub_dev *sc, struct ub_lun *lun, | |||
| 739 | cmd->cdb[8] = nblks; | 738 | cmd->cdb[8] = nblks; |
| 740 | cmd->cdb_len = 10; | 739 | cmd->cdb_len = 10; |
| 741 | 740 | ||
| 742 | cmd->len = rq->nr_sectors * 512; | 741 | cmd->len = blk_rq_bytes(rq); |
| 743 | } | 742 | } |
| 744 | 743 | ||
| 745 | static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, | 744 | static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, |
| @@ -747,7 +746,7 @@ static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, | |||
| 747 | { | 746 | { |
| 748 | struct request *rq = urq->rq; | 747 | struct request *rq = urq->rq; |
| 749 | 748 | ||
| 750 | if (rq->data_len == 0) { | 749 | if (blk_rq_bytes(rq) == 0) { |
| 751 | cmd->dir = UB_DIR_NONE; | 750 | cmd->dir = UB_DIR_NONE; |
| 752 | } else { | 751 | } else { |
| 753 | if (rq_data_dir(rq) == WRITE) | 752 | if (rq_data_dir(rq) == WRITE) |
| @@ -762,7 +761,7 @@ static void ub_cmd_build_packet(struct ub_dev *sc, struct ub_lun *lun, | |||
| 762 | memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); | 761 | memcpy(&cmd->cdb, rq->cmd, rq->cmd_len); |
| 763 | cmd->cdb_len = rq->cmd_len; | 762 | cmd->cdb_len = rq->cmd_len; |
| 764 | 763 | ||
| 765 | cmd->len = rq->data_len; | 764 | cmd->len = blk_rq_bytes(rq); |
| 766 | 765 | ||
| 767 | /* | 766 | /* |
| 768 | * To reapply this to every URB is not as incorrect as it looks. | 767 | * To reapply this to every URB is not as incorrect as it looks. |
| @@ -777,16 +776,15 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
| 777 | struct ub_request *urq = cmd->back; | 776 | struct ub_request *urq = cmd->back; |
| 778 | struct request *rq; | 777 | struct request *rq; |
| 779 | unsigned int scsi_status; | 778 | unsigned int scsi_status; |
| 780 | unsigned int cmd_len; | ||
| 781 | 779 | ||
| 782 | rq = urq->rq; | 780 | rq = urq->rq; |
| 783 | 781 | ||
| 784 | if (cmd->error == 0) { | 782 | if (cmd->error == 0) { |
| 785 | if (blk_pc_request(rq)) { | 783 | if (blk_pc_request(rq)) { |
| 786 | if (cmd->act_len >= rq->data_len) | 784 | if (cmd->act_len >= rq->resid_len) |
| 787 | rq->data_len = 0; | 785 | rq->resid_len = 0; |
| 788 | else | 786 | else |
| 789 | rq->data_len -= cmd->act_len; | 787 | rq->resid_len -= cmd->act_len; |
| 790 | scsi_status = 0; | 788 | scsi_status = 0; |
| 791 | } else { | 789 | } else { |
| 792 | if (cmd->act_len != cmd->len) { | 790 | if (cmd->act_len != cmd->len) { |
| @@ -818,17 +816,14 @@ static void ub_rw_cmd_done(struct ub_dev *sc, struct ub_scsi_cmd *cmd) | |||
| 818 | 816 | ||
| 819 | urq->rq = NULL; | 817 | urq->rq = NULL; |
| 820 | 818 | ||
| 821 | cmd_len = cmd->len; | ||
| 822 | ub_put_cmd(lun, cmd); | 819 | ub_put_cmd(lun, cmd); |
| 823 | ub_end_rq(rq, scsi_status, cmd_len); | 820 | ub_end_rq(rq, scsi_status); |
| 824 | blk_start_queue(lun->disk->queue); | 821 | blk_start_queue(lun->disk->queue); |
| 825 | } | 822 | } |
| 826 | 823 | ||
| 827 | static void ub_end_rq(struct request *rq, unsigned int scsi_status, | 824 | static void ub_end_rq(struct request *rq, unsigned int scsi_status) |
| 828 | unsigned int cmd_len) | ||
| 829 | { | 825 | { |
| 830 | int error; | 826 | int error; |
| 831 | long rqlen; | ||
| 832 | 827 | ||
| 833 | if (scsi_status == 0) { | 828 | if (scsi_status == 0) { |
| 834 | error = 0; | 829 | error = 0; |
| @@ -836,12 +831,7 @@ static void ub_end_rq(struct request *rq, unsigned int scsi_status, | |||
| 836 | error = -EIO; | 831 | error = -EIO; |
| 837 | rq->errors = scsi_status; | 832 | rq->errors = scsi_status; |
| 838 | } | 833 | } |
| 839 | rqlen = blk_rq_bytes(rq); /* Oddly enough, this is the residue. */ | 834 | __blk_end_request_all(rq, error); |
| 840 | if (__blk_end_request(rq, error, cmd_len)) { | ||
| 841 | printk(KERN_WARNING DRV_NAME | ||
| 842 | ": __blk_end_request blew, %s-cmd total %u rqlen %ld\n", | ||
| 843 | blk_pc_request(rq)? "pc": "fs", cmd_len, rqlen); | ||
| 844 | } | ||
| 845 | } | 835 | } |
| 846 | 836 | ||
| 847 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, | 837 | static int ub_rw_cmd_retry(struct ub_dev *sc, struct ub_lun *lun, |
| @@ -1759,7 +1749,7 @@ static int ub_bd_revalidate(struct gendisk *disk) | |||
| 1759 | ub_revalidate(lun->udev, lun); | 1749 | ub_revalidate(lun->udev, lun); |
| 1760 | 1750 | ||
| 1761 | /* XXX Support sector size switching like in sr.c */ | 1751 | /* XXX Support sector size switching like in sr.c */ |
| 1762 | blk_queue_hardsect_size(disk->queue, lun->capacity.bsize); | 1752 | blk_queue_logical_block_size(disk->queue, lun->capacity.bsize); |
| 1763 | set_capacity(disk, lun->capacity.nsec); | 1753 | set_capacity(disk, lun->capacity.nsec); |
| 1764 | // set_disk_ro(sdkp->disk, lun->readonly); | 1754 | // set_disk_ro(sdkp->disk, lun->readonly); |
| 1765 | 1755 | ||
| @@ -2334,7 +2324,7 @@ static int ub_probe_lun(struct ub_dev *sc, int lnum) | |||
| 2334 | blk_queue_max_phys_segments(q, UB_MAX_REQ_SG); | 2324 | blk_queue_max_phys_segments(q, UB_MAX_REQ_SG); |
| 2335 | blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */ | 2325 | blk_queue_segment_boundary(q, 0xffffffff); /* Dubious. */ |
| 2336 | blk_queue_max_sectors(q, UB_MAX_SECTORS); | 2326 | blk_queue_max_sectors(q, UB_MAX_SECTORS); |
| 2337 | blk_queue_hardsect_size(q, lun->capacity.bsize); | 2327 | blk_queue_logical_block_size(q, lun->capacity.bsize); |
| 2338 | 2328 | ||
| 2339 | lun->disk = disk; | 2329 | lun->disk = disk; |
| 2340 | q->queuedata = lun; | 2330 | q->queuedata = lun; |
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c index ecccf65dce2f..390d69bb7c48 100644 --- a/drivers/block/viodasd.c +++ b/drivers/block/viodasd.c | |||
| @@ -252,7 +252,7 @@ static int send_request(struct request *req) | |||
| 252 | struct viodasd_device *d; | 252 | struct viodasd_device *d; |
| 253 | unsigned long flags; | 253 | unsigned long flags; |
| 254 | 254 | ||
| 255 | start = (u64)req->sector << 9; | 255 | start = (u64)blk_rq_pos(req) << 9; |
| 256 | 256 | ||
| 257 | if (rq_data_dir(req) == READ) { | 257 | if (rq_data_dir(req) == READ) { |
| 258 | direction = DMA_FROM_DEVICE; | 258 | direction = DMA_FROM_DEVICE; |
| @@ -361,19 +361,17 @@ static void do_viodasd_request(struct request_queue *q) | |||
| 361 | * back later. | 361 | * back later. |
| 362 | */ | 362 | */ |
| 363 | while (num_req_outstanding < VIOMAXREQ) { | 363 | while (num_req_outstanding < VIOMAXREQ) { |
| 364 | req = elv_next_request(q); | 364 | req = blk_fetch_request(q); |
| 365 | if (req == NULL) | 365 | if (req == NULL) |
| 366 | return; | 366 | return; |
| 367 | /* dequeue the current request from the queue */ | ||
| 368 | blkdev_dequeue_request(req); | ||
| 369 | /* check that request contains a valid command */ | 367 | /* check that request contains a valid command */ |
| 370 | if (!blk_fs_request(req)) { | 368 | if (!blk_fs_request(req)) { |
| 371 | viodasd_end_request(req, -EIO, req->hard_nr_sectors); | 369 | viodasd_end_request(req, -EIO, blk_rq_sectors(req)); |
| 372 | continue; | 370 | continue; |
| 373 | } | 371 | } |
| 374 | /* Try sending the request */ | 372 | /* Try sending the request */ |
| 375 | if (send_request(req) != 0) | 373 | if (send_request(req) != 0) |
| 376 | viodasd_end_request(req, -EIO, req->hard_nr_sectors); | 374 | viodasd_end_request(req, -EIO, blk_rq_sectors(req)); |
| 377 | } | 375 | } |
| 378 | } | 376 | } |
| 379 | 377 | ||
| @@ -590,7 +588,7 @@ static int viodasd_handle_read_write(struct vioblocklpevent *bevent) | |||
| 590 | err = vio_lookup_rc(viodasd_err_table, bevent->sub_result); | 588 | err = vio_lookup_rc(viodasd_err_table, bevent->sub_result); |
| 591 | printk(VIOD_KERN_WARNING "read/write error %d:0x%04x (%s)\n", | 589 | printk(VIOD_KERN_WARNING "read/write error %d:0x%04x (%s)\n", |
| 592 | event->xRc, bevent->sub_result, err->msg); | 590 | event->xRc, bevent->sub_result, err->msg); |
| 593 | num_sect = req->hard_nr_sectors; | 591 | num_sect = blk_rq_sectors(req); |
| 594 | } | 592 | } |
| 595 | qlock = req->q->queue_lock; | 593 | qlock = req->q->queue_lock; |
| 596 | spin_lock_irqsave(qlock, irq_flags); | 594 | spin_lock_irqsave(qlock, irq_flags); |
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c index 5d34764c8a87..c0facaa55cf4 100644 --- a/drivers/block/virtio_blk.c +++ b/drivers/block/virtio_blk.c | |||
| @@ -37,6 +37,7 @@ struct virtblk_req | |||
| 37 | struct list_head list; | 37 | struct list_head list; |
| 38 | struct request *req; | 38 | struct request *req; |
| 39 | struct virtio_blk_outhdr out_hdr; | 39 | struct virtio_blk_outhdr out_hdr; |
| 40 | struct virtio_scsi_inhdr in_hdr; | ||
| 40 | u8 status; | 41 | u8 status; |
| 41 | }; | 42 | }; |
| 42 | 43 | ||
| @@ -50,6 +51,7 @@ static void blk_done(struct virtqueue *vq) | |||
| 50 | spin_lock_irqsave(&vblk->lock, flags); | 51 | spin_lock_irqsave(&vblk->lock, flags); |
| 51 | while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) { | 52 | while ((vbr = vblk->vq->vq_ops->get_buf(vblk->vq, &len)) != NULL) { |
| 52 | int error; | 53 | int error; |
| 54 | |||
| 53 | switch (vbr->status) { | 55 | switch (vbr->status) { |
| 54 | case VIRTIO_BLK_S_OK: | 56 | case VIRTIO_BLK_S_OK: |
| 55 | error = 0; | 57 | error = 0; |
| @@ -62,7 +64,13 @@ static void blk_done(struct virtqueue *vq) | |||
| 62 | break; | 64 | break; |
| 63 | } | 65 | } |
| 64 | 66 | ||
| 65 | __blk_end_request(vbr->req, error, blk_rq_bytes(vbr->req)); | 67 | if (blk_pc_request(vbr->req)) { |
| 68 | vbr->req->resid_len = vbr->in_hdr.residual; | ||
| 69 | vbr->req->sense_len = vbr->in_hdr.sense_len; | ||
| 70 | vbr->req->errors = vbr->in_hdr.errors; | ||
| 71 | } | ||
| 72 | |||
| 73 | __blk_end_request_all(vbr->req, error); | ||
| 66 | list_del(&vbr->list); | 74 | list_del(&vbr->list); |
| 67 | mempool_free(vbr, vblk->pool); | 75 | mempool_free(vbr, vblk->pool); |
| 68 | } | 76 | } |
| @@ -74,7 +82,7 @@ static void blk_done(struct virtqueue *vq) | |||
| 74 | static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | 82 | static bool do_req(struct request_queue *q, struct virtio_blk *vblk, |
| 75 | struct request *req) | 83 | struct request *req) |
| 76 | { | 84 | { |
| 77 | unsigned long num, out, in; | 85 | unsigned long num, out = 0, in = 0; |
| 78 | struct virtblk_req *vbr; | 86 | struct virtblk_req *vbr; |
| 79 | 87 | ||
| 80 | vbr = mempool_alloc(vblk->pool, GFP_ATOMIC); | 88 | vbr = mempool_alloc(vblk->pool, GFP_ATOMIC); |
| @@ -85,7 +93,7 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
| 85 | vbr->req = req; | 93 | vbr->req = req; |
| 86 | if (blk_fs_request(vbr->req)) { | 94 | if (blk_fs_request(vbr->req)) { |
| 87 | vbr->out_hdr.type = 0; | 95 | vbr->out_hdr.type = 0; |
| 88 | vbr->out_hdr.sector = vbr->req->sector; | 96 | vbr->out_hdr.sector = blk_rq_pos(vbr->req); |
| 89 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); | 97 | vbr->out_hdr.ioprio = req_get_ioprio(vbr->req); |
| 90 | } else if (blk_pc_request(vbr->req)) { | 98 | } else if (blk_pc_request(vbr->req)) { |
| 91 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; | 99 | vbr->out_hdr.type = VIRTIO_BLK_T_SCSI_CMD; |
| @@ -99,18 +107,36 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
| 99 | if (blk_barrier_rq(vbr->req)) | 107 | if (blk_barrier_rq(vbr->req)) |
| 100 | vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; | 108 | vbr->out_hdr.type |= VIRTIO_BLK_T_BARRIER; |
| 101 | 109 | ||
| 102 | sg_set_buf(&vblk->sg[0], &vbr->out_hdr, sizeof(vbr->out_hdr)); | 110 | sg_set_buf(&vblk->sg[out++], &vbr->out_hdr, sizeof(vbr->out_hdr)); |
| 103 | num = blk_rq_map_sg(q, vbr->req, vblk->sg+1); | ||
| 104 | sg_set_buf(&vblk->sg[num+1], &vbr->status, sizeof(vbr->status)); | ||
| 105 | 111 | ||
| 106 | if (rq_data_dir(vbr->req) == WRITE) { | 112 | /* |
| 107 | vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; | 113 | * If this is a packet command we need a couple of additional headers. |
| 108 | out = 1 + num; | 114 | * Behind the normal outhdr we put a segment with the scsi command |
| 109 | in = 1; | 115 | * block, and before the normal inhdr we put the sense data and the |
| 110 | } else { | 116 | * inhdr with additional status information before the normal inhdr. |
| 111 | vbr->out_hdr.type |= VIRTIO_BLK_T_IN; | 117 | */ |
| 112 | out = 1; | 118 | if (blk_pc_request(vbr->req)) |
| 113 | in = 1 + num; | 119 | sg_set_buf(&vblk->sg[out++], vbr->req->cmd, vbr->req->cmd_len); |
| 120 | |||
| 121 | num = blk_rq_map_sg(q, vbr->req, vblk->sg + out); | ||
| 122 | |||
| 123 | if (blk_pc_request(vbr->req)) { | ||
| 124 | sg_set_buf(&vblk->sg[num + out + in++], vbr->req->sense, 96); | ||
| 125 | sg_set_buf(&vblk->sg[num + out + in++], &vbr->in_hdr, | ||
| 126 | sizeof(vbr->in_hdr)); | ||
| 127 | } | ||
| 128 | |||
| 129 | sg_set_buf(&vblk->sg[num + out + in++], &vbr->status, | ||
| 130 | sizeof(vbr->status)); | ||
| 131 | |||
| 132 | if (num) { | ||
| 133 | if (rq_data_dir(vbr->req) == WRITE) { | ||
| 134 | vbr->out_hdr.type |= VIRTIO_BLK_T_OUT; | ||
| 135 | out += num; | ||
| 136 | } else { | ||
| 137 | vbr->out_hdr.type |= VIRTIO_BLK_T_IN; | ||
| 138 | in += num; | ||
| 139 | } | ||
| 114 | } | 140 | } |
| 115 | 141 | ||
| 116 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) { | 142 | if (vblk->vq->vq_ops->add_buf(vblk->vq, vblk->sg, out, in, vbr)) { |
| @@ -124,12 +150,11 @@ static bool do_req(struct request_queue *q, struct virtio_blk *vblk, | |||
| 124 | 150 | ||
| 125 | static void do_virtblk_request(struct request_queue *q) | 151 | static void do_virtblk_request(struct request_queue *q) |
| 126 | { | 152 | { |
| 127 | struct virtio_blk *vblk = NULL; | 153 | struct virtio_blk *vblk = q->queuedata; |
| 128 | struct request *req; | 154 | struct request *req; |
| 129 | unsigned int issued = 0; | 155 | unsigned int issued = 0; |
| 130 | 156 | ||
| 131 | while ((req = elv_next_request(q)) != NULL) { | 157 | while ((req = blk_peek_request(q)) != NULL) { |
| 132 | vblk = req->rq_disk->private_data; | ||
| 133 | BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); | 158 | BUG_ON(req->nr_phys_segments + 2 > vblk->sg_elems); |
| 134 | 159 | ||
| 135 | /* If this request fails, stop queue and wait for something to | 160 | /* If this request fails, stop queue and wait for something to |
| @@ -138,7 +163,7 @@ static void do_virtblk_request(struct request_queue *q) | |||
| 138 | blk_stop_queue(q); | 163 | blk_stop_queue(q); |
| 139 | break; | 164 | break; |
| 140 | } | 165 | } |
| 141 | blkdev_dequeue_request(req); | 166 | blk_start_request(req); |
| 142 | issued++; | 167 | issued++; |
| 143 | } | 168 | } |
| 144 | 169 | ||
| @@ -146,12 +171,51 @@ static void do_virtblk_request(struct request_queue *q) | |||
| 146 | vblk->vq->vq_ops->kick(vblk->vq); | 171 | vblk->vq->vq_ops->kick(vblk->vq); |
| 147 | } | 172 | } |
| 148 | 173 | ||
| 174 | /* return ATA identify data | ||
| 175 | */ | ||
| 176 | static int virtblk_identify(struct gendisk *disk, void *argp) | ||
| 177 | { | ||
| 178 | struct virtio_blk *vblk = disk->private_data; | ||
| 179 | void *opaque; | ||
| 180 | int err = -ENOMEM; | ||
| 181 | |||
| 182 | opaque = kmalloc(VIRTIO_BLK_ID_BYTES, GFP_KERNEL); | ||
| 183 | if (!opaque) | ||
| 184 | goto out; | ||
| 185 | |||
| 186 | err = virtio_config_buf(vblk->vdev, VIRTIO_BLK_F_IDENTIFY, | ||
| 187 | offsetof(struct virtio_blk_config, identify), opaque, | ||
| 188 | VIRTIO_BLK_ID_BYTES); | ||
| 189 | |||
| 190 | if (err) | ||
| 191 | goto out_kfree; | ||
| 192 | |||
| 193 | if (copy_to_user(argp, opaque, VIRTIO_BLK_ID_BYTES)) | ||
| 194 | err = -EFAULT; | ||
| 195 | |||
| 196 | out_kfree: | ||
| 197 | kfree(opaque); | ||
| 198 | out: | ||
| 199 | return err; | ||
| 200 | } | ||
| 201 | |||
| 149 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, | 202 | static int virtblk_ioctl(struct block_device *bdev, fmode_t mode, |
| 150 | unsigned cmd, unsigned long data) | 203 | unsigned cmd, unsigned long data) |
| 151 | { | 204 | { |
| 152 | return scsi_cmd_ioctl(bdev->bd_disk->queue, | 205 | struct gendisk *disk = bdev->bd_disk; |
| 153 | bdev->bd_disk, mode, cmd, | 206 | struct virtio_blk *vblk = disk->private_data; |
| 154 | (void __user *)data); | 207 | void __user *argp = (void __user *)data; |
| 208 | |||
| 209 | if (cmd == HDIO_GET_IDENTITY) | ||
| 210 | return virtblk_identify(disk, argp); | ||
| 211 | |||
| 212 | /* | ||
| 213 | * Only allow the generic SCSI ioctls if the host can support it. | ||
| 214 | */ | ||
| 215 | if (!virtio_has_feature(vblk->vdev, VIRTIO_BLK_F_SCSI)) | ||
| 216 | return -ENOIOCTLCMD; | ||
| 217 | |||
| 218 | return scsi_cmd_ioctl(disk->queue, disk, mode, cmd, argp); | ||
| 155 | } | 219 | } |
| 156 | 220 | ||
| 157 | /* We provide getgeo only to please some old bootloader/partitioning tools */ | 221 | /* We provide getgeo only to please some old bootloader/partitioning tools */ |
| @@ -249,6 +313,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 249 | goto out_put_disk; | 313 | goto out_put_disk; |
| 250 | } | 314 | } |
| 251 | 315 | ||
| 316 | vblk->disk->queue->queuedata = vblk; | ||
| 252 | queue_flag_set_unlocked(QUEUE_FLAG_VIRT, vblk->disk->queue); | 317 | queue_flag_set_unlocked(QUEUE_FLAG_VIRT, vblk->disk->queue); |
| 253 | 318 | ||
| 254 | if (index < 26) { | 319 | if (index < 26) { |
| @@ -313,7 +378,7 @@ static int virtblk_probe(struct virtio_device *vdev) | |||
| 313 | offsetof(struct virtio_blk_config, blk_size), | 378 | offsetof(struct virtio_blk_config, blk_size), |
| 314 | &blk_size); | 379 | &blk_size); |
| 315 | if (!err) | 380 | if (!err) |
| 316 | blk_queue_hardsect_size(vblk->disk->queue, blk_size); | 381 | blk_queue_logical_block_size(vblk->disk->queue, blk_size); |
| 317 | 382 | ||
| 318 | add_disk(vblk->disk); | 383 | add_disk(vblk->disk); |
| 319 | return 0; | 384 | return 0; |
| @@ -356,6 +421,7 @@ static struct virtio_device_id id_table[] = { | |||
| 356 | static unsigned int features[] = { | 421 | static unsigned int features[] = { |
| 357 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, | 422 | VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, |
| 358 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, | 423 | VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE, |
| 424 | VIRTIO_BLK_F_SCSI, VIRTIO_BLK_F_IDENTIFY | ||
| 359 | }; | 425 | }; |
| 360 | 426 | ||
| 361 | static struct virtio_driver virtio_blk = { | 427 | static struct virtio_driver virtio_blk = { |
diff --git a/drivers/block/xd.c b/drivers/block/xd.c index 64b496fce98b..ce2429219925 100644 --- a/drivers/block/xd.c +++ b/drivers/block/xd.c | |||
| @@ -305,30 +305,25 @@ static void do_xd_request (struct request_queue * q) | |||
| 305 | if (xdc_busy) | 305 | if (xdc_busy) |
| 306 | return; | 306 | return; |
| 307 | 307 | ||
| 308 | while ((req = elv_next_request(q)) != NULL) { | 308 | req = blk_fetch_request(q); |
| 309 | unsigned block = req->sector; | 309 | while (req) { |
| 310 | unsigned count = req->nr_sectors; | 310 | unsigned block = blk_rq_pos(req); |
| 311 | int rw = rq_data_dir(req); | 311 | unsigned count = blk_rq_cur_sectors(req); |
| 312 | XD_INFO *disk = req->rq_disk->private_data; | 312 | XD_INFO *disk = req->rq_disk->private_data; |
| 313 | int res = 0; | 313 | int res = -EIO; |
| 314 | int retry; | 314 | int retry; |
| 315 | 315 | ||
| 316 | if (!blk_fs_request(req)) { | 316 | if (!blk_fs_request(req)) |
| 317 | end_request(req, 0); | 317 | goto done; |
| 318 | continue; | 318 | if (block + count > get_capacity(req->rq_disk)) |
| 319 | } | 319 | goto done; |
| 320 | if (block + count > get_capacity(req->rq_disk)) { | ||
| 321 | end_request(req, 0); | ||
| 322 | continue; | ||
| 323 | } | ||
| 324 | if (rw != READ && rw != WRITE) { | ||
| 325 | printk("do_xd_request: unknown request\n"); | ||
| 326 | end_request(req, 0); | ||
| 327 | continue; | ||
| 328 | } | ||
| 329 | for (retry = 0; (retry < XD_RETRIES) && !res; retry++) | 320 | for (retry = 0; (retry < XD_RETRIES) && !res; retry++) |
| 330 | res = xd_readwrite(rw, disk, req->buffer, block, count); | 321 | res = xd_readwrite(rq_data_dir(req), disk, req->buffer, |
| 331 | end_request(req, res); /* wrap up, 0 = fail, 1 = success */ | 322 | block, count); |
| 323 | done: | ||
| 324 | /* wrap up, 0 = success, -errno = fail */ | ||
| 325 | if (!__blk_end_request_cur(req, res)) | ||
| 326 | req = blk_fetch_request(q); | ||
| 332 | } | 327 | } |
| 333 | } | 328 | } |
| 334 | 329 | ||
| @@ -418,7 +413,7 @@ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_ | |||
| 418 | printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write")); | 413 | printk("xd%c: %s timeout, recalibrating drive\n",'a'+drive,(operation == READ ? "read" : "write")); |
| 419 | xd_recalibrate(drive); | 414 | xd_recalibrate(drive); |
| 420 | spin_lock_irq(&xd_lock); | 415 | spin_lock_irq(&xd_lock); |
| 421 | return (0); | 416 | return -EIO; |
| 422 | case 2: | 417 | case 2: |
| 423 | if (sense[0] & 0x30) { | 418 | if (sense[0] & 0x30) { |
| 424 | printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing")); | 419 | printk("xd%c: %s - ",'a'+drive,(operation == READ ? "reading" : "writing")); |
| @@ -439,7 +434,7 @@ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_ | |||
| 439 | else | 434 | else |
| 440 | printk(" - no valid disk address\n"); | 435 | printk(" - no valid disk address\n"); |
| 441 | spin_lock_irq(&xd_lock); | 436 | spin_lock_irq(&xd_lock); |
| 442 | return (0); | 437 | return -EIO; |
| 443 | } | 438 | } |
| 444 | if (xd_dma_buffer) | 439 | if (xd_dma_buffer) |
| 445 | for (i=0; i < (temp * 0x200); i++) | 440 | for (i=0; i < (temp * 0x200); i++) |
| @@ -448,7 +443,7 @@ static int xd_readwrite (u_char operation,XD_INFO *p,char *buffer,u_int block,u_ | |||
| 448 | count -= temp, buffer += temp * 0x200, block += temp; | 443 | count -= temp, buffer += temp * 0x200, block += temp; |
| 449 | } | 444 | } |
| 450 | spin_lock_irq(&xd_lock); | 445 | spin_lock_irq(&xd_lock); |
| 451 | return (1); | 446 | return 0; |
| 452 | } | 447 | } |
| 453 | 448 | ||
| 454 | /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */ | 449 | /* xd_recalibrate: recalibrate a given drive and reset controller if necessary */ |
diff --git a/drivers/block/xen-blkfront.c b/drivers/block/xen-blkfront.c index a6cbf7b808e6..c1996829d5ec 100644 --- a/drivers/block/xen-blkfront.c +++ b/drivers/block/xen-blkfront.c | |||
| @@ -122,7 +122,7 @@ static DEFINE_SPINLOCK(blkif_io_lock); | |||
| 122 | static int get_id_from_freelist(struct blkfront_info *info) | 122 | static int get_id_from_freelist(struct blkfront_info *info) |
| 123 | { | 123 | { |
| 124 | unsigned long free = info->shadow_free; | 124 | unsigned long free = info->shadow_free; |
| 125 | BUG_ON(free > BLK_RING_SIZE); | 125 | BUG_ON(free >= BLK_RING_SIZE); |
| 126 | info->shadow_free = info->shadow[free].req.id; | 126 | info->shadow_free = info->shadow[free].req.id; |
| 127 | info->shadow[free].req.id = 0x0fffffee; /* debug */ | 127 | info->shadow[free].req.id = 0x0fffffee; /* debug */ |
| 128 | return free; | 128 | return free; |
| @@ -231,7 +231,7 @@ static int blkif_queue_request(struct request *req) | |||
| 231 | info->shadow[id].request = (unsigned long)req; | 231 | info->shadow[id].request = (unsigned long)req; |
| 232 | 232 | ||
| 233 | ring_req->id = id; | 233 | ring_req->id = id; |
| 234 | ring_req->sector_number = (blkif_sector_t)req->sector; | 234 | ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req); |
| 235 | ring_req->handle = info->handle; | 235 | ring_req->handle = info->handle; |
| 236 | 236 | ||
| 237 | ring_req->operation = rq_data_dir(req) ? | 237 | ring_req->operation = rq_data_dir(req) ? |
| @@ -299,25 +299,25 @@ static void do_blkif_request(struct request_queue *rq) | |||
| 299 | 299 | ||
| 300 | queued = 0; | 300 | queued = 0; |
| 301 | 301 | ||
| 302 | while ((req = elv_next_request(rq)) != NULL) { | 302 | while ((req = blk_peek_request(rq)) != NULL) { |
| 303 | info = req->rq_disk->private_data; | 303 | info = req->rq_disk->private_data; |
| 304 | if (!blk_fs_request(req)) { | ||
| 305 | end_request(req, 0); | ||
| 306 | continue; | ||
| 307 | } | ||
| 308 | 304 | ||
| 309 | if (RING_FULL(&info->ring)) | 305 | if (RING_FULL(&info->ring)) |
| 310 | goto wait; | 306 | goto wait; |
| 311 | 307 | ||
| 312 | pr_debug("do_blk_req %p: cmd %p, sec %lx, " | 308 | blk_start_request(req); |
| 313 | "(%u/%li) buffer:%p [%s]\n", | ||
| 314 | req, req->cmd, (unsigned long)req->sector, | ||
| 315 | req->current_nr_sectors, | ||
| 316 | req->nr_sectors, req->buffer, | ||
| 317 | rq_data_dir(req) ? "write" : "read"); | ||
| 318 | 309 | ||
| 310 | if (!blk_fs_request(req)) { | ||
| 311 | __blk_end_request_all(req, -EIO); | ||
| 312 | continue; | ||
| 313 | } | ||
| 314 | |||
| 315 | pr_debug("do_blk_req %p: cmd %p, sec %lx, " | ||
| 316 | "(%u/%u) buffer:%p [%s]\n", | ||
| 317 | req, req->cmd, (unsigned long)blk_rq_pos(req), | ||
| 318 | blk_rq_cur_sectors(req), blk_rq_sectors(req), | ||
| 319 | req->buffer, rq_data_dir(req) ? "write" : "read"); | ||
| 319 | 320 | ||
| 320 | blkdev_dequeue_request(req); | ||
| 321 | if (blkif_queue_request(req)) { | 321 | if (blkif_queue_request(req)) { |
| 322 | blk_requeue_request(rq, req); | 322 | blk_requeue_request(rq, req); |
| 323 | wait: | 323 | wait: |
| @@ -344,7 +344,7 @@ static int xlvbd_init_blk_queue(struct gendisk *gd, u16 sector_size) | |||
| 344 | queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq); | 344 | queue_flag_set_unlocked(QUEUE_FLAG_VIRT, rq); |
| 345 | 345 | ||
| 346 | /* Hard sector size and max sectors impersonate the equiv. hardware. */ | 346 | /* Hard sector size and max sectors impersonate the equiv. hardware. */ |
| 347 | blk_queue_hardsect_size(rq, sector_size); | 347 | blk_queue_logical_block_size(rq, sector_size); |
| 348 | blk_queue_max_sectors(rq, 512); | 348 | blk_queue_max_sectors(rq, 512); |
| 349 | 349 | ||
| 350 | /* Each segment in a request is up to an aligned page in size. */ | 350 | /* Each segment in a request is up to an aligned page in size. */ |
| @@ -551,7 +551,6 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
| 551 | 551 | ||
| 552 | for (i = info->ring.rsp_cons; i != rp; i++) { | 552 | for (i = info->ring.rsp_cons; i != rp; i++) { |
| 553 | unsigned long id; | 553 | unsigned long id; |
| 554 | int ret; | ||
| 555 | 554 | ||
| 556 | bret = RING_GET_RESPONSE(&info->ring, i); | 555 | bret = RING_GET_RESPONSE(&info->ring, i); |
| 557 | id = bret->id; | 556 | id = bret->id; |
| @@ -578,8 +577,7 @@ static irqreturn_t blkif_interrupt(int irq, void *dev_id) | |||
| 578 | dev_dbg(&info->xbdev->dev, "Bad return from blkdev data " | 577 | dev_dbg(&info->xbdev->dev, "Bad return from blkdev data " |
| 579 | "request: %x\n", bret->status); | 578 | "request: %x\n", bret->status); |
| 580 | 579 | ||
| 581 | ret = __blk_end_request(req, error, blk_rq_bytes(req)); | 580 | __blk_end_request_all(req, error); |
| 582 | BUG_ON(ret); | ||
| 583 | break; | 581 | break; |
| 584 | default: | 582 | default: |
| 585 | BUG(); | 583 | BUG(); |
diff --git a/drivers/block/xsysace.c b/drivers/block/xsysace.c index 4aecf5dc6a93..f08491a3a813 100644 --- a/drivers/block/xsysace.c +++ b/drivers/block/xsysace.c | |||
| @@ -463,10 +463,11 @@ struct request *ace_get_next_request(struct request_queue * q) | |||
| 463 | { | 463 | { |
| 464 | struct request *req; | 464 | struct request *req; |
| 465 | 465 | ||
| 466 | while ((req = elv_next_request(q)) != NULL) { | 466 | while ((req = blk_peek_request(q)) != NULL) { |
| 467 | if (blk_fs_request(req)) | 467 | if (blk_fs_request(req)) |
| 468 | break; | 468 | break; |
| 469 | end_request(req, 0); | 469 | blk_start_request(req); |
| 470 | __blk_end_request_all(req, -EIO); | ||
| 470 | } | 471 | } |
| 471 | return req; | 472 | return req; |
| 472 | } | 473 | } |
| @@ -492,9 +493,13 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
| 492 | set_capacity(ace->gd, 0); | 493 | set_capacity(ace->gd, 0); |
| 493 | dev_info(ace->dev, "No CF in slot\n"); | 494 | dev_info(ace->dev, "No CF in slot\n"); |
| 494 | 495 | ||
| 495 | /* Drop all pending requests */ | 496 | /* Drop all in-flight and pending requests */ |
| 496 | while ((req = elv_next_request(ace->queue)) != NULL) | 497 | if (ace->req) { |
| 497 | end_request(req, 0); | 498 | __blk_end_request_all(ace->req, -EIO); |
| 499 | ace->req = NULL; | ||
| 500 | } | ||
| 501 | while ((req = blk_fetch_request(ace->queue)) != NULL) | ||
| 502 | __blk_end_request_all(req, -EIO); | ||
| 498 | 503 | ||
| 499 | /* Drop back to IDLE state and notify waiters */ | 504 | /* Drop back to IDLE state and notify waiters */ |
| 500 | ace->fsm_state = ACE_FSM_STATE_IDLE; | 505 | ace->fsm_state = ACE_FSM_STATE_IDLE; |
| @@ -642,19 +647,21 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
| 642 | ace->fsm_state = ACE_FSM_STATE_IDLE; | 647 | ace->fsm_state = ACE_FSM_STATE_IDLE; |
| 643 | break; | 648 | break; |
| 644 | } | 649 | } |
| 650 | blk_start_request(req); | ||
| 645 | 651 | ||
| 646 | /* Okay, it's a data request, set it up for transfer */ | 652 | /* Okay, it's a data request, set it up for transfer */ |
| 647 | dev_dbg(ace->dev, | 653 | dev_dbg(ace->dev, |
| 648 | "request: sec=%llx hcnt=%lx, ccnt=%x, dir=%i\n", | 654 | "request: sec=%llx hcnt=%x, ccnt=%x, dir=%i\n", |
| 649 | (unsigned long long) req->sector, req->hard_nr_sectors, | 655 | (unsigned long long)blk_rq_pos(req), |
| 650 | req->current_nr_sectors, rq_data_dir(req)); | 656 | blk_rq_sectors(req), blk_rq_cur_sectors(req), |
| 657 | rq_data_dir(req)); | ||
| 651 | 658 | ||
| 652 | ace->req = req; | 659 | ace->req = req; |
| 653 | ace->data_ptr = req->buffer; | 660 | ace->data_ptr = req->buffer; |
| 654 | ace->data_count = req->current_nr_sectors * ACE_BUF_PER_SECTOR; | 661 | ace->data_count = blk_rq_cur_sectors(req) * ACE_BUF_PER_SECTOR; |
| 655 | ace_out32(ace, ACE_MPULBA, req->sector & 0x0FFFFFFF); | 662 | ace_out32(ace, ACE_MPULBA, blk_rq_pos(req) & 0x0FFFFFFF); |
| 656 | 663 | ||
| 657 | count = req->hard_nr_sectors; | 664 | count = blk_rq_sectors(req); |
| 658 | if (rq_data_dir(req)) { | 665 | if (rq_data_dir(req)) { |
| 659 | /* Kick off write request */ | 666 | /* Kick off write request */ |
| 660 | dev_dbg(ace->dev, "write data\n"); | 667 | dev_dbg(ace->dev, "write data\n"); |
| @@ -688,7 +695,7 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
| 688 | dev_dbg(ace->dev, | 695 | dev_dbg(ace->dev, |
| 689 | "CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n", | 696 | "CFBSY set; t=%i iter=%i c=%i dc=%i irq=%i\n", |
| 690 | ace->fsm_task, ace->fsm_iter_num, | 697 | ace->fsm_task, ace->fsm_iter_num, |
| 691 | ace->req->current_nr_sectors * 16, | 698 | blk_rq_cur_sectors(ace->req) * 16, |
| 692 | ace->data_count, ace->in_irq); | 699 | ace->data_count, ace->in_irq); |
| 693 | ace_fsm_yield(ace); /* need to poll CFBSY bit */ | 700 | ace_fsm_yield(ace); /* need to poll CFBSY bit */ |
| 694 | break; | 701 | break; |
| @@ -697,7 +704,7 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
| 697 | dev_dbg(ace->dev, | 704 | dev_dbg(ace->dev, |
| 698 | "DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n", | 705 | "DATABUF not set; t=%i iter=%i c=%i dc=%i irq=%i\n", |
| 699 | ace->fsm_task, ace->fsm_iter_num, | 706 | ace->fsm_task, ace->fsm_iter_num, |
| 700 | ace->req->current_nr_sectors * 16, | 707 | blk_rq_cur_sectors(ace->req) * 16, |
| 701 | ace->data_count, ace->in_irq); | 708 | ace->data_count, ace->in_irq); |
| 702 | ace_fsm_yieldirq(ace); | 709 | ace_fsm_yieldirq(ace); |
| 703 | break; | 710 | break; |
| @@ -717,14 +724,13 @@ static void ace_fsm_dostate(struct ace_device *ace) | |||
| 717 | } | 724 | } |
| 718 | 725 | ||
| 719 | /* bio finished; is there another one? */ | 726 | /* bio finished; is there another one? */ |
| 720 | if (__blk_end_request(ace->req, 0, | 727 | if (__blk_end_request_cur(ace->req, 0)) { |
| 721 | blk_rq_cur_bytes(ace->req))) { | 728 | /* dev_dbg(ace->dev, "next block; h=%u c=%u\n", |
| 722 | /* dev_dbg(ace->dev, "next block; h=%li c=%i\n", | 729 | * blk_rq_sectors(ace->req), |
| 723 | * ace->req->hard_nr_sectors, | 730 | * blk_rq_cur_sectors(ace->req)); |
| 724 | * ace->req->current_nr_sectors); | ||
| 725 | */ | 731 | */ |
| 726 | ace->data_ptr = ace->req->buffer; | 732 | ace->data_ptr = ace->req->buffer; |
| 727 | ace->data_count = ace->req->current_nr_sectors * 16; | 733 | ace->data_count = blk_rq_cur_sectors(ace->req) * 16; |
| 728 | ace_fsm_yieldirq(ace); | 734 | ace_fsm_yieldirq(ace); |
| 729 | break; | 735 | break; |
| 730 | } | 736 | } |
| @@ -978,7 +984,7 @@ static int __devinit ace_setup(struct ace_device *ace) | |||
| 978 | ace->queue = blk_init_queue(ace_request, &ace->lock); | 984 | ace->queue = blk_init_queue(ace_request, &ace->lock); |
| 979 | if (ace->queue == NULL) | 985 | if (ace->queue == NULL) |
| 980 | goto err_blk_initq; | 986 | goto err_blk_initq; |
| 981 | blk_queue_hardsect_size(ace->queue, 512); | 987 | blk_queue_logical_block_size(ace->queue, 512); |
| 982 | 988 | ||
| 983 | /* | 989 | /* |
| 984 | * Allocate and initialize GD structure | 990 | * Allocate and initialize GD structure |
diff --git a/drivers/block/z2ram.c b/drivers/block/z2ram.c index 80754cdd3119..4575171e5beb 100644 --- a/drivers/block/z2ram.c +++ b/drivers/block/z2ram.c | |||
| @@ -70,15 +70,18 @@ static struct gendisk *z2ram_gendisk; | |||
| 70 | static void do_z2_request(struct request_queue *q) | 70 | static void do_z2_request(struct request_queue *q) |
| 71 | { | 71 | { |
| 72 | struct request *req; | 72 | struct request *req; |
| 73 | while ((req = elv_next_request(q)) != NULL) { | 73 | |
| 74 | unsigned long start = req->sector << 9; | 74 | req = blk_fetch_request(q); |
| 75 | unsigned long len = req->current_nr_sectors << 9; | 75 | while (req) { |
| 76 | unsigned long start = blk_rq_pos(req) << 9; | ||
| 77 | unsigned long len = blk_rq_cur_bytes(req); | ||
| 78 | int err = 0; | ||
| 76 | 79 | ||
| 77 | if (start + len > z2ram_size) { | 80 | if (start + len > z2ram_size) { |
| 78 | printk( KERN_ERR DEVICE_NAME ": bad access: block=%lu, count=%u\n", | 81 | printk( KERN_ERR DEVICE_NAME ": bad access: block=%lu, count=%u\n", |
| 79 | req->sector, req->current_nr_sectors); | 82 | blk_rq_pos(req), blk_rq_cur_sectors(req)); |
| 80 | end_request(req, 0); | 83 | err = -EIO; |
| 81 | continue; | 84 | goto done; |
| 82 | } | 85 | } |
| 83 | while (len) { | 86 | while (len) { |
| 84 | unsigned long addr = start & Z2RAM_CHUNKMASK; | 87 | unsigned long addr = start & Z2RAM_CHUNKMASK; |
| @@ -93,7 +96,9 @@ static void do_z2_request(struct request_queue *q) | |||
| 93 | start += size; | 96 | start += size; |
| 94 | len -= size; | 97 | len -= size; |
| 95 | } | 98 | } |
| 96 | end_request(req, 1); | 99 | done: |
| 100 | if (!__blk_end_request_cur(req, err)) | ||
| 101 | req = blk_fetch_request(q); | ||
| 97 | } | 102 | } |
| 98 | } | 103 | } |
| 99 | 104 | ||
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c index af761dc434f6..4895f0e05322 100644 --- a/drivers/bluetooth/hci_ldisc.c +++ b/drivers/bluetooth/hci_ldisc.c | |||
| @@ -277,8 +277,8 @@ static int hci_uart_tty_open(struct tty_struct *tty) | |||
| 277 | /* FIXME: why is this needed. Note don't use ldisc_ref here as the | 277 | /* FIXME: why is this needed. Note don't use ldisc_ref here as the |
| 278 | open path is before the ldisc is referencable */ | 278 | open path is before the ldisc is referencable */ |
| 279 | 279 | ||
| 280 | if (tty->ldisc.ops->flush_buffer) | 280 | if (tty->ldisc->ops->flush_buffer) |
| 281 | tty->ldisc.ops->flush_buffer(tty); | 281 | tty->ldisc->ops->flush_buffer(tty); |
| 282 | tty_driver_flush_buffer(tty); | 282 | tty_driver_flush_buffer(tty); |
| 283 | 283 | ||
| 284 | return 0; | 284 | return 0; |
| @@ -463,7 +463,6 @@ static int hci_uart_tty_ioctl(struct tty_struct *tty, struct file * file, | |||
| 463 | clear_bit(HCI_UART_PROTO_SET, &hu->flags); | 463 | clear_bit(HCI_UART_PROTO_SET, &hu->flags); |
| 464 | return err; | 464 | return err; |
| 465 | } | 465 | } |
| 466 | tty->low_latency = 1; | ||
| 467 | } else | 466 | } else |
| 468 | return -EBUSY; | 467 | return -EBUSY; |
| 469 | break; | 468 | break; |
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c index cceace61ef28..71d1b9bab70b 100644 --- a/drivers/cdrom/cdrom.c +++ b/drivers/cdrom/cdrom.c | |||
| @@ -2101,8 +2101,8 @@ static int cdrom_read_cdda_bpc(struct cdrom_device_info *cdi, __u8 __user *ubuf, | |||
| 2101 | nr = nframes; | 2101 | nr = nframes; |
| 2102 | if (cdi->cdda_method == CDDA_BPC_SINGLE) | 2102 | if (cdi->cdda_method == CDDA_BPC_SINGLE) |
| 2103 | nr = 1; | 2103 | nr = 1; |
| 2104 | if (nr * CD_FRAMESIZE_RAW > (q->max_sectors << 9)) | 2104 | if (nr * CD_FRAMESIZE_RAW > (queue_max_sectors(q) << 9)) |
| 2105 | nr = (q->max_sectors << 9) / CD_FRAMESIZE_RAW; | 2105 | nr = (queue_max_sectors(q) << 9) / CD_FRAMESIZE_RAW; |
| 2106 | 2106 | ||
| 2107 | len = nr * CD_FRAMESIZE_RAW; | 2107 | len = nr * CD_FRAMESIZE_RAW; |
| 2108 | 2108 | ||
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c index 2eecb779437b..b5621f27c4be 100644 --- a/drivers/cdrom/gdrom.c +++ b/drivers/cdrom/gdrom.c | |||
| @@ -584,8 +584,8 @@ static void gdrom_readdisk_dma(struct work_struct *work) | |||
| 584 | list_for_each_safe(elem, next, &gdrom_deferred) { | 584 | list_for_each_safe(elem, next, &gdrom_deferred) { |
| 585 | req = list_entry(elem, struct request, queuelist); | 585 | req = list_entry(elem, struct request, queuelist); |
| 586 | spin_unlock(&gdrom_lock); | 586 | spin_unlock(&gdrom_lock); |
| 587 | block = req->sector/GD_TO_BLK + GD_SESSION_OFFSET; | 587 | block = blk_rq_pos(req)/GD_TO_BLK + GD_SESSION_OFFSET; |
| 588 | block_cnt = req->nr_sectors/GD_TO_BLK; | 588 | block_cnt = blk_rq_sectors(req)/GD_TO_BLK; |
| 589 | ctrl_outl(PHYSADDR(req->buffer), GDROM_DMA_STARTADDR_REG); | 589 | ctrl_outl(PHYSADDR(req->buffer), GDROM_DMA_STARTADDR_REG); |
| 590 | ctrl_outl(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); | 590 | ctrl_outl(block_cnt * GDROM_HARD_SECTOR, GDROM_DMA_LENGTH_REG); |
| 591 | ctrl_outl(1, GDROM_DMA_DIRECTION_REG); | 591 | ctrl_outl(1, GDROM_DMA_DIRECTION_REG); |
| @@ -632,39 +632,35 @@ static void gdrom_readdisk_dma(struct work_struct *work) | |||
| 632 | * before handling ending the request */ | 632 | * before handling ending the request */ |
| 633 | spin_lock(&gdrom_lock); | 633 | spin_lock(&gdrom_lock); |
| 634 | list_del_init(&req->queuelist); | 634 | list_del_init(&req->queuelist); |
| 635 | __blk_end_request(req, err, blk_rq_bytes(req)); | 635 | __blk_end_request_all(req, err); |
| 636 | } | 636 | } |
| 637 | spin_unlock(&gdrom_lock); | 637 | spin_unlock(&gdrom_lock); |
| 638 | kfree(read_command); | 638 | kfree(read_command); |
| 639 | } | 639 | } |
| 640 | 640 | ||
| 641 | static void gdrom_request_handler_dma(struct request *req) | ||
| 642 | { | ||
| 643 | /* dequeue, add to list of deferred work | ||
| 644 | * and then schedule workqueue */ | ||
| 645 | blkdev_dequeue_request(req); | ||
| 646 | list_add_tail(&req->queuelist, &gdrom_deferred); | ||
| 647 | schedule_work(&work); | ||
| 648 | } | ||
| 649 | |||
| 650 | static void gdrom_request(struct request_queue *rq) | 641 | static void gdrom_request(struct request_queue *rq) |
| 651 | { | 642 | { |
| 652 | struct request *req; | 643 | struct request *req; |
| 653 | 644 | ||
| 654 | while ((req = elv_next_request(rq)) != NULL) { | 645 | while ((req = blk_fetch_request(rq)) != NULL) { |
| 655 | if (!blk_fs_request(req)) { | 646 | if (!blk_fs_request(req)) { |
| 656 | printk(KERN_DEBUG "GDROM: Non-fs request ignored\n"); | 647 | printk(KERN_DEBUG "GDROM: Non-fs request ignored\n"); |
| 657 | end_request(req, 0); | 648 | __blk_end_request_all(req, -EIO); |
| 649 | continue; | ||
| 658 | } | 650 | } |
| 659 | if (rq_data_dir(req) != READ) { | 651 | if (rq_data_dir(req) != READ) { |
| 660 | printk(KERN_NOTICE "GDROM: Read only device -"); | 652 | printk(KERN_NOTICE "GDROM: Read only device -"); |
| 661 | printk(" write request ignored\n"); | 653 | printk(" write request ignored\n"); |
| 662 | end_request(req, 0); | 654 | __blk_end_request_all(req, -EIO); |
| 655 | continue; | ||
| 663 | } | 656 | } |
| 664 | if (req->nr_sectors) | 657 | |
| 665 | gdrom_request_handler_dma(req); | 658 | /* |
| 666 | else | 659 | * Add to list of deferred work and then schedule |
| 667 | end_request(req, 0); | 660 | * workqueue. |
| 661 | */ | ||
| 662 | list_add_tail(&req->queuelist, &gdrom_deferred); | ||
| 663 | schedule_work(&work); | ||
| 668 | } | 664 | } |
| 669 | } | 665 | } |
| 670 | 666 | ||
| @@ -743,7 +739,7 @@ static void __devinit probe_gdrom_setupdisk(void) | |||
| 743 | 739 | ||
| 744 | static int __devinit probe_gdrom_setupqueue(void) | 740 | static int __devinit probe_gdrom_setupqueue(void) |
| 745 | { | 741 | { |
| 746 | blk_queue_hardsect_size(gd.gdrom_rq, GDROM_HARD_SECTOR); | 742 | blk_queue_logical_block_size(gd.gdrom_rq, GDROM_HARD_SECTOR); |
| 747 | /* using DMA so memory will need to be contiguous */ | 743 | /* using DMA so memory will need to be contiguous */ |
| 748 | blk_queue_max_hw_segments(gd.gdrom_rq, 1); | 744 | blk_queue_max_hw_segments(gd.gdrom_rq, 1); |
| 749 | /* set a large max size to get most from DMA */ | 745 | /* set a large max size to get most from DMA */ |
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c index 9b1624e0ddeb..0fff646cc2f0 100644 --- a/drivers/cdrom/viocd.c +++ b/drivers/cdrom/viocd.c | |||
| @@ -282,7 +282,7 @@ static int send_request(struct request *req) | |||
| 282 | viopath_targetinst(viopath_hostLp), | 282 | viopath_targetinst(viopath_hostLp), |
| 283 | (u64)req, VIOVERSION << 16, | 283 | (u64)req, VIOVERSION << 16, |
| 284 | ((u64)DEVICE_NR(diskinfo) << 48) | dmaaddr, | 284 | ((u64)DEVICE_NR(diskinfo) << 48) | dmaaddr, |
| 285 | (u64)req->sector * 512, len, 0); | 285 | (u64)blk_rq_pos(req) * 512, len, 0); |
| 286 | if (hvrc != HvLpEvent_Rc_Good) { | 286 | if (hvrc != HvLpEvent_Rc_Good) { |
| 287 | printk(VIOCD_KERN_WARNING "hv error on op %d\n", (int)hvrc); | 287 | printk(VIOCD_KERN_WARNING "hv error on op %d\n", (int)hvrc); |
| 288 | return -1; | 288 | return -1; |
| @@ -291,36 +291,19 @@ static int send_request(struct request *req) | |||
| 291 | return 0; | 291 | return 0; |
| 292 | } | 292 | } |
| 293 | 293 | ||
| 294 | static void viocd_end_request(struct request *req, int error) | ||
| 295 | { | ||
| 296 | int nsectors = req->hard_nr_sectors; | ||
| 297 | |||
| 298 | /* | ||
| 299 | * Make sure it's fully ended, and ensure that we process | ||
| 300 | * at least one sector. | ||
| 301 | */ | ||
| 302 | if (blk_pc_request(req)) | ||
| 303 | nsectors = (req->data_len + 511) >> 9; | ||
| 304 | if (!nsectors) | ||
| 305 | nsectors = 1; | ||
| 306 | |||
| 307 | if (__blk_end_request(req, error, nsectors << 9)) | ||
| 308 | BUG(); | ||
| 309 | } | ||
| 310 | |||
| 311 | static int rwreq; | 294 | static int rwreq; |
| 312 | 295 | ||
| 313 | static void do_viocd_request(struct request_queue *q) | 296 | static void do_viocd_request(struct request_queue *q) |
| 314 | { | 297 | { |
| 315 | struct request *req; | 298 | struct request *req; |
| 316 | 299 | ||
| 317 | while ((rwreq == 0) && ((req = elv_next_request(q)) != NULL)) { | 300 | while ((rwreq == 0) && ((req = blk_fetch_request(q)) != NULL)) { |
| 318 | if (!blk_fs_request(req)) | 301 | if (!blk_fs_request(req)) |
| 319 | viocd_end_request(req, -EIO); | 302 | __blk_end_request_all(req, -EIO); |
| 320 | else if (send_request(req) < 0) { | 303 | else if (send_request(req) < 0) { |
| 321 | printk(VIOCD_KERN_WARNING | 304 | printk(VIOCD_KERN_WARNING |
| 322 | "unable to send message to OS/400!"); | 305 | "unable to send message to OS/400!"); |
| 323 | viocd_end_request(req, -EIO); | 306 | __blk_end_request_all(req, -EIO); |
| 324 | } else | 307 | } else |
| 325 | rwreq++; | 308 | rwreq++; |
| 326 | } | 309 | } |
| @@ -486,8 +469,8 @@ static void vio_handle_cd_event(struct HvLpEvent *event) | |||
| 486 | case viocdopen: | 469 | case viocdopen: |
| 487 | if (event->xRc == 0) { | 470 | if (event->xRc == 0) { |
| 488 | di = &viocd_diskinfo[bevent->disk]; | 471 | di = &viocd_diskinfo[bevent->disk]; |
| 489 | blk_queue_hardsect_size(di->viocd_disk->queue, | 472 | blk_queue_logical_block_size(di->viocd_disk->queue, |
| 490 | bevent->block_size); | 473 | bevent->block_size); |
| 491 | set_capacity(di->viocd_disk, | 474 | set_capacity(di->viocd_disk, |
| 492 | bevent->media_size * | 475 | bevent->media_size * |
| 493 | bevent->block_size / 512); | 476 | bevent->block_size / 512); |
| @@ -531,9 +514,9 @@ return_complete: | |||
| 531 | "with rc %d:0x%04X: %s\n", | 514 | "with rc %d:0x%04X: %s\n", |
| 532 | req, event->xRc, | 515 | req, event->xRc, |
| 533 | bevent->sub_result, err->msg); | 516 | bevent->sub_result, err->msg); |
| 534 | viocd_end_request(req, -EIO); | 517 | __blk_end_request_all(req, -EIO); |
| 535 | } else | 518 | } else |
| 536 | viocd_end_request(req, 0); | 519 | __blk_end_request_all(req, 0); |
| 537 | 520 | ||
| 538 | /* restart handling of incoming requests */ | 521 | /* restart handling of incoming requests */ |
| 539 | spin_unlock_irqrestore(&viocd_reqlock, flags); | 522 | spin_unlock_irqrestore(&viocd_reqlock, flags); |
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig index 735bbe2be51a..02ecfd5fa61c 100644 --- a/drivers/char/Kconfig +++ b/drivers/char/Kconfig | |||
| @@ -97,6 +97,19 @@ config DEVKMEM | |||
| 97 | kind of kernel debugging operations. | 97 | kind of kernel debugging operations. |
| 98 | When in doubt, say "N". | 98 | When in doubt, say "N". |
| 99 | 99 | ||
| 100 | config BFIN_JTAG_COMM | ||
| 101 | tristate "Blackfin JTAG Communication" | ||
| 102 | depends on BLACKFIN | ||
| 103 | help | ||
| 104 | Add support for emulating a TTY device over the Blackfin JTAG. | ||
| 105 | |||
| 106 | To compile this driver as a module, choose M here: the | ||
| 107 | module will be called bfin_jtag_comm. | ||
| 108 | |||
| 109 | config BFIN_JTAG_COMM_CONSOLE | ||
| 110 | bool "Console on Blackfin JTAG" | ||
| 111 | depends on BFIN_JTAG_COMM=y | ||
| 112 | |||
| 100 | config SERIAL_NONSTANDARD | 113 | config SERIAL_NONSTANDARD |
| 101 | bool "Non-standard serial port support" | 114 | bool "Non-standard serial port support" |
| 102 | depends on HAS_IOMEM | 115 | depends on HAS_IOMEM |
diff --git a/drivers/char/Makefile b/drivers/char/Makefile index 9caf5b5ad1c0..189efcff08ce 100644 --- a/drivers/char/Makefile +++ b/drivers/char/Makefile | |||
| @@ -13,6 +13,7 @@ obj-$(CONFIG_LEGACY_PTYS) += pty.o | |||
| 13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o | 13 | obj-$(CONFIG_UNIX98_PTYS) += pty.o |
| 14 | obj-y += misc.o | 14 | obj-y += misc.o |
| 15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o | 15 | obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o |
| 16 | obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o | ||
| 16 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o | 17 | obj-$(CONFIG_CONSOLE_TRANSLATIONS) += consolemap.o consolemap_deftbl.o |
| 17 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o | 18 | obj-$(CONFIG_HW_CONSOLE) += vt.o defkeymap.o |
| 18 | obj-$(CONFIG_AUDIT) += tty_audit.o | 19 | obj-$(CONFIG_AUDIT) += tty_audit.o |
diff --git a/drivers/char/bfin_jtag_comm.c b/drivers/char/bfin_jtag_comm.c new file mode 100644 index 000000000000..44c113d56045 --- /dev/null +++ b/drivers/char/bfin_jtag_comm.c | |||
| @@ -0,0 +1,365 @@ | |||
| 1 | /* | ||
| 2 | * TTY over Blackfin JTAG Communication | ||
| 3 | * | ||
| 4 | * Copyright 2008-2009 Analog Devices Inc. | ||
| 5 | * | ||
| 6 | * Enter bugs at http://blackfin.uclinux.org/ | ||
| 7 | * | ||
| 8 | * Licensed under the GPL-2 or later. | ||
| 9 | */ | ||
| 10 | |||
| 11 | #include <linux/circ_buf.h> | ||
| 12 | #include <linux/console.h> | ||
| 13 | #include <linux/delay.h> | ||
| 14 | #include <linux/err.h> | ||
| 15 | #include <linux/kernel.h> | ||
| 16 | #include <linux/kthread.h> | ||
| 17 | #include <linux/module.h> | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/sched.h> | ||
| 20 | #include <linux/tty.h> | ||
| 21 | #include <linux/tty_driver.h> | ||
| 22 | #include <linux/tty_flip.h> | ||
| 23 | #include <asm/atomic.h> | ||
| 24 | |||
| 25 | /* See the Debug/Emulation chapter in the HRM */ | ||
| 26 | #define EMUDOF 0x00000001 /* EMUDAT_OUT full & valid */ | ||
| 27 | #define EMUDIF 0x00000002 /* EMUDAT_IN full & valid */ | ||
| 28 | #define EMUDOOVF 0x00000004 /* EMUDAT_OUT overflow */ | ||
| 29 | #define EMUDIOVF 0x00000008 /* EMUDAT_IN overflow */ | ||
| 30 | |||
| 31 | #define DRV_NAME "bfin-jtag-comm" | ||
| 32 | #define DEV_NAME "ttyBFJC" | ||
| 33 | |||
| 34 | #define pr_init(fmt, args...) ({ static const __initdata char __fmt[] = fmt; printk(__fmt, ## args); }) | ||
| 35 | #define debug(fmt, args...) pr_debug(DRV_NAME ": " fmt, ## args) | ||
| 36 | |||
| 37 | static inline uint32_t bfin_write_emudat(uint32_t emudat) | ||
| 38 | { | ||
| 39 | __asm__ __volatile__("emudat = %0;" : : "d"(emudat)); | ||
| 40 | return emudat; | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline uint32_t bfin_read_emudat(void) | ||
| 44 | { | ||
| 45 | uint32_t emudat; | ||
| 46 | __asm__ __volatile__("%0 = emudat;" : "=d"(emudat)); | ||
| 47 | return emudat; | ||
| 48 | } | ||
| 49 | |||
| 50 | static inline uint32_t bfin_write_emudat_chars(char a, char b, char c, char d) | ||
| 51 | { | ||
| 52 | return bfin_write_emudat((a << 0) | (b << 8) | (c << 16) | (d << 24)); | ||
| 53 | } | ||
| 54 | |||
| 55 | #define CIRC_SIZE 2048 /* see comment in tty_io.c:do_tty_write() */ | ||
| 56 | #define CIRC_MASK (CIRC_SIZE - 1) | ||
| 57 | #define circ_empty(circ) ((circ)->head == (circ)->tail) | ||
| 58 | #define circ_free(circ) CIRC_SPACE((circ)->head, (circ)->tail, CIRC_SIZE) | ||
| 59 | #define circ_cnt(circ) CIRC_CNT((circ)->head, (circ)->tail, CIRC_SIZE) | ||
| 60 | #define circ_byte(circ, idx) ((circ)->buf[(idx) & CIRC_MASK]) | ||
| 61 | |||
| 62 | static struct tty_driver *bfin_jc_driver; | ||
| 63 | static struct task_struct *bfin_jc_kthread; | ||
| 64 | static struct tty_struct * volatile bfin_jc_tty; | ||
| 65 | static unsigned long bfin_jc_count; | ||
| 66 | static DEFINE_MUTEX(bfin_jc_tty_mutex); | ||
| 67 | static volatile struct circ_buf bfin_jc_write_buf; | ||
| 68 | |||
| 69 | static int | ||
| 70 | bfin_jc_emudat_manager(void *arg) | ||
| 71 | { | ||
| 72 | uint32_t inbound_len = 0, outbound_len = 0; | ||
| 73 | |||
| 74 | while (!kthread_should_stop()) { | ||
| 75 | /* no one left to give data to, so sleep */ | ||
| 76 | if (bfin_jc_tty == NULL && circ_empty(&bfin_jc_write_buf)) { | ||
| 77 | debug("waiting for readers\n"); | ||
| 78 | __set_current_state(TASK_UNINTERRUPTIBLE); | ||
| 79 | schedule(); | ||
| 80 | __set_current_state(TASK_RUNNING); | ||
| 81 | } | ||
| 82 | |||
| 83 | /* no data available, so just chill */ | ||
| 84 | if (!(bfin_read_DBGSTAT() & EMUDIF) && circ_empty(&bfin_jc_write_buf)) { | ||
| 85 | debug("waiting for data (in_len = %i) (circ: %i %i)\n", | ||
| 86 | inbound_len, bfin_jc_write_buf.tail, bfin_jc_write_buf.head); | ||
| 87 | if (inbound_len) | ||
| 88 | schedule(); | ||
| 89 | else | ||
| 90 | schedule_timeout_interruptible(HZ); | ||
| 91 | continue; | ||
| 92 | } | ||
| 93 | |||
| 94 | /* if incoming data is ready, eat it */ | ||
| 95 | if (bfin_read_DBGSTAT() & EMUDIF) { | ||
| 96 | struct tty_struct *tty; | ||
| 97 | mutex_lock(&bfin_jc_tty_mutex); | ||
| 98 | tty = (struct tty_struct *)bfin_jc_tty; | ||
| 99 | if (tty != NULL) { | ||
| 100 | uint32_t emudat = bfin_read_emudat(); | ||
| 101 | if (inbound_len == 0) { | ||
| 102 | debug("incoming length: 0x%08x\n", emudat); | ||
| 103 | inbound_len = emudat; | ||
| 104 | } else { | ||
| 105 | size_t num_chars = (4 <= inbound_len ? 4 : inbound_len); | ||
| 106 | debug(" incoming data: 0x%08x (pushing %zu)\n", emudat, num_chars); | ||
| 107 | inbound_len -= num_chars; | ||
| 108 | tty_insert_flip_string(tty, (unsigned char *)&emudat, num_chars); | ||
| 109 | tty_flip_buffer_push(tty); | ||
| 110 | } | ||
| 111 | } | ||
| 112 | mutex_unlock(&bfin_jc_tty_mutex); | ||
| 113 | } | ||
| 114 | |||
| 115 | /* if outgoing data is ready, post it */ | ||
| 116 | if (!(bfin_read_DBGSTAT() & EMUDOF) && !circ_empty(&bfin_jc_write_buf)) { | ||
| 117 | if (outbound_len == 0) { | ||
| 118 | outbound_len = circ_cnt(&bfin_jc_write_buf); | ||
| 119 | bfin_write_emudat(outbound_len); | ||
| 120 | debug("outgoing length: 0x%08x\n", outbound_len); | ||
| 121 | } else { | ||
| 122 | struct tty_struct *tty; | ||
| 123 | int tail = bfin_jc_write_buf.tail; | ||
| 124 | size_t ate = (4 <= outbound_len ? 4 : outbound_len); | ||
| 125 | uint32_t emudat = | ||
| 126 | bfin_write_emudat_chars( | ||
| 127 | circ_byte(&bfin_jc_write_buf, tail + 0), | ||
| 128 | circ_byte(&bfin_jc_write_buf, tail + 1), | ||
| 129 | circ_byte(&bfin_jc_write_buf, tail + 2), | ||
| 130 | circ_byte(&bfin_jc_write_buf, tail + 3) | ||
| 131 | ); | ||
| 132 | bfin_jc_write_buf.tail += ate; | ||
| 133 | outbound_len -= ate; | ||
| 134 | mutex_lock(&bfin_jc_tty_mutex); | ||
| 135 | tty = (struct tty_struct *)bfin_jc_tty; | ||
| 136 | if (tty) | ||
| 137 | tty_wakeup(tty); | ||
| 138 | mutex_unlock(&bfin_jc_tty_mutex); | ||
| 139 | debug(" outgoing data: 0x%08x (pushing %zu)\n", emudat, ate); | ||
| 140 | } | ||
| 141 | } | ||
| 142 | } | ||
| 143 | |||
| 144 | __set_current_state(TASK_RUNNING); | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int | ||
| 149 | bfin_jc_open(struct tty_struct *tty, struct file *filp) | ||
| 150 | { | ||
| 151 | mutex_lock(&bfin_jc_tty_mutex); | ||
| 152 | debug("open %lu\n", bfin_jc_count); | ||
| 153 | ++bfin_jc_count; | ||
| 154 | bfin_jc_tty = tty; | ||
| 155 | wake_up_process(bfin_jc_kthread); | ||
| 156 | mutex_unlock(&bfin_jc_tty_mutex); | ||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static void | ||
| 161 | bfin_jc_close(struct tty_struct *tty, struct file *filp) | ||
| 162 | { | ||
| 163 | mutex_lock(&bfin_jc_tty_mutex); | ||
| 164 | debug("close %lu\n", bfin_jc_count); | ||
| 165 | if (--bfin_jc_count == 0) | ||
| 166 | bfin_jc_tty = NULL; | ||
| 167 | wake_up_process(bfin_jc_kthread); | ||
| 168 | mutex_unlock(&bfin_jc_tty_mutex); | ||
| 169 | } | ||
| 170 | |||
| 171 | /* XXX: we dont handle the put_char() case where we must handle count = 1 */ | ||
| 172 | static int | ||
| 173 | bfin_jc_circ_write(const unsigned char *buf, int count) | ||
| 174 | { | ||
| 175 | int i; | ||
| 176 | count = min(count, circ_free(&bfin_jc_write_buf)); | ||
| 177 | debug("going to write chunk of %i bytes\n", count); | ||
| 178 | for (i = 0; i < count; ++i) | ||
| 179 | circ_byte(&bfin_jc_write_buf, bfin_jc_write_buf.head + i) = buf[i]; | ||
| 180 | bfin_jc_write_buf.head += i; | ||
| 181 | return i; | ||
| 182 | } | ||
| 183 | |||
| 184 | #ifndef CONFIG_BFIN_JTAG_COMM_CONSOLE | ||
| 185 | # define acquire_console_sem() | ||
| 186 | # define release_console_sem() | ||
| 187 | #endif | ||
| 188 | static int | ||
| 189 | bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count) | ||
| 190 | { | ||
| 191 | int i; | ||
| 192 | acquire_console_sem(); | ||
| 193 | i = bfin_jc_circ_write(buf, count); | ||
| 194 | release_console_sem(); | ||
| 195 | wake_up_process(bfin_jc_kthread); | ||
| 196 | return i; | ||
| 197 | } | ||
| 198 | |||
| 199 | static void | ||
| 200 | bfin_jc_flush_chars(struct tty_struct *tty) | ||
| 201 | { | ||
| 202 | wake_up_process(bfin_jc_kthread); | ||
| 203 | } | ||
| 204 | |||
| 205 | static int | ||
| 206 | bfin_jc_write_room(struct tty_struct *tty) | ||
| 207 | { | ||
| 208 | return circ_free(&bfin_jc_write_buf); | ||
| 209 | } | ||
| 210 | |||
| 211 | static int | ||
| 212 | bfin_jc_chars_in_buffer(struct tty_struct *tty) | ||
| 213 | { | ||
| 214 | return circ_cnt(&bfin_jc_write_buf); | ||
| 215 | } | ||
| 216 | |||
| 217 | static void | ||
| 218 | bfin_jc_wait_until_sent(struct tty_struct *tty, int timeout) | ||
| 219 | { | ||
| 220 | unsigned long expire = jiffies + timeout; | ||
| 221 | while (!circ_empty(&bfin_jc_write_buf)) { | ||
| 222 | if (signal_pending(current)) | ||
| 223 | break; | ||
| 224 | if (time_after(jiffies, expire)) | ||
| 225 | break; | ||
| 226 | } | ||
| 227 | } | ||
| 228 | |||
| 229 | static struct tty_operations bfin_jc_ops = { | ||
| 230 | .open = bfin_jc_open, | ||
| 231 | .close = bfin_jc_close, | ||
| 232 | .write = bfin_jc_write, | ||
| 233 | /*.put_char = bfin_jc_put_char,*/ | ||
| 234 | .flush_chars = bfin_jc_flush_chars, | ||
| 235 | .write_room = bfin_jc_write_room, | ||
| 236 | .chars_in_buffer = bfin_jc_chars_in_buffer, | ||
| 237 | .wait_until_sent = bfin_jc_wait_until_sent, | ||
| 238 | }; | ||
| 239 | |||
| 240 | static int __init bfin_jc_init(void) | ||
| 241 | { | ||
| 242 | int ret; | ||
| 243 | |||
| 244 | bfin_jc_kthread = kthread_create(bfin_jc_emudat_manager, NULL, DRV_NAME); | ||
| 245 | if (IS_ERR(bfin_jc_kthread)) | ||
| 246 | return PTR_ERR(bfin_jc_kthread); | ||
| 247 | |||
| 248 | ret = -ENOMEM; | ||
| 249 | |||
| 250 | bfin_jc_write_buf.head = bfin_jc_write_buf.tail = 0; | ||
| 251 | bfin_jc_write_buf.buf = kmalloc(CIRC_SIZE, GFP_KERNEL); | ||
| 252 | if (!bfin_jc_write_buf.buf) | ||
| 253 | goto err; | ||
| 254 | |||
| 255 | bfin_jc_driver = alloc_tty_driver(1); | ||
| 256 | if (!bfin_jc_driver) | ||
| 257 | goto err; | ||
| 258 | |||
| 259 | bfin_jc_driver->owner = THIS_MODULE; | ||
| 260 | bfin_jc_driver->driver_name = DRV_NAME; | ||
| 261 | bfin_jc_driver->name = DEV_NAME; | ||
| 262 | bfin_jc_driver->type = TTY_DRIVER_TYPE_SERIAL; | ||
| 263 | bfin_jc_driver->subtype = SERIAL_TYPE_NORMAL; | ||
| 264 | bfin_jc_driver->init_termios = tty_std_termios; | ||
| 265 | tty_set_operations(bfin_jc_driver, &bfin_jc_ops); | ||
| 266 | |||
| 267 | ret = tty_register_driver(bfin_jc_driver); | ||
| 268 | if (ret) | ||
| 269 | goto err; | ||
| 270 | |||
| 271 | pr_init(KERN_INFO DRV_NAME ": initialized\n"); | ||
| 272 | |||
| 273 | return 0; | ||
| 274 | |||
| 275 | err: | ||
| 276 | put_tty_driver(bfin_jc_driver); | ||
| 277 | kfree(bfin_jc_write_buf.buf); | ||
| 278 | kthread_stop(bfin_jc_kthread); | ||
| 279 | return ret; | ||
| 280 | } | ||
| 281 | module_init(bfin_jc_init); | ||
| 282 | |||
| 283 | static void __exit bfin_jc_exit(void) | ||
| 284 | { | ||
| 285 | kthread_stop(bfin_jc_kthread); | ||
| 286 | kfree(bfin_jc_write_buf.buf); | ||
| 287 | tty_unregister_driver(bfin_jc_driver); | ||
| 288 | put_tty_driver(bfin_jc_driver); | ||
| 289 | } | ||
| 290 | module_exit(bfin_jc_exit); | ||
| 291 | |||
| 292 | #if defined(CONFIG_BFIN_JTAG_COMM_CONSOLE) || defined(CONFIG_EARLY_PRINTK) | ||
| 293 | static void | ||
| 294 | bfin_jc_straight_buffer_write(const char *buf, unsigned count) | ||
| 295 | { | ||
| 296 | unsigned ate = 0; | ||
| 297 | while (bfin_read_DBGSTAT() & EMUDOF) | ||
| 298 | continue; | ||
| 299 | bfin_write_emudat(count); | ||
| 300 | while (ate < count) { | ||
| 301 | while (bfin_read_DBGSTAT() & EMUDOF) | ||
| 302 | continue; | ||
| 303 | bfin_write_emudat_chars(buf[ate], buf[ate+1], buf[ate+2], buf[ate+3]); | ||
| 304 | ate += 4; | ||
| 305 | } | ||
| 306 | } | ||
| 307 | #endif | ||
| 308 | |||
| 309 | #ifdef CONFIG_BFIN_JTAG_COMM_CONSOLE | ||
| 310 | static void | ||
| 311 | bfin_jc_console_write(struct console *co, const char *buf, unsigned count) | ||
| 312 | { | ||
| 313 | if (bfin_jc_kthread == NULL) | ||
| 314 | bfin_jc_straight_buffer_write(buf, count); | ||
| 315 | else | ||
| 316 | bfin_jc_circ_write(buf, count); | ||
| 317 | } | ||
| 318 | |||
| 319 | static struct tty_driver * | ||
| 320 | bfin_jc_console_device(struct console *co, int *index) | ||
| 321 | { | ||
| 322 | *index = co->index; | ||
| 323 | return bfin_jc_driver; | ||
| 324 | } | ||
| 325 | |||
| 326 | static struct console bfin_jc_console = { | ||
| 327 | .name = DEV_NAME, | ||
| 328 | .write = bfin_jc_console_write, | ||
| 329 | .device = bfin_jc_console_device, | ||
| 330 | .flags = CON_ANYTIME | CON_PRINTBUFFER, | ||
| 331 | .index = -1, | ||
| 332 | }; | ||
| 333 | |||
| 334 | static int __init bfin_jc_console_init(void) | ||
| 335 | { | ||
| 336 | register_console(&bfin_jc_console); | ||
| 337 | return 0; | ||
| 338 | } | ||
| 339 | console_initcall(bfin_jc_console_init); | ||
| 340 | #endif | ||
| 341 | |||
| 342 | #ifdef CONFIG_EARLY_PRINTK | ||
| 343 | static void __init | ||
| 344 | bfin_jc_early_write(struct console *co, const char *buf, unsigned int count) | ||
| 345 | { | ||
| 346 | bfin_jc_straight_buffer_write(buf, count); | ||
| 347 | } | ||
| 348 | |||
| 349 | static struct __initdata console bfin_jc_early_console = { | ||
| 350 | .name = "early_BFJC", | ||
| 351 | .write = bfin_jc_early_write, | ||
| 352 | .flags = CON_ANYTIME | CON_PRINTBUFFER, | ||
| 353 | .index = -1, | ||
| 354 | }; | ||
| 355 | |||
| 356 | struct console * __init | ||
| 357 | bfin_jc_early_init(unsigned int port, unsigned int cflag) | ||
| 358 | { | ||
| 359 | return &bfin_jc_early_console; | ||
| 360 | } | ||
| 361 | #endif | ||
| 362 | |||
| 363 | MODULE_AUTHOR("Mike Frysinger <vapier@gentoo.org>"); | ||
| 364 | MODULE_DESCRIPTION("TTY over Blackfin JTAG Communication"); | ||
| 365 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c index 1fdb9f657d8f..f3366d3f06cf 100644 --- a/drivers/char/cyclades.c +++ b/drivers/char/cyclades.c | |||
| @@ -604,7 +604,6 @@ | |||
| 604 | 604 | ||
| 605 | #define NR_PORTS 256 | 605 | #define NR_PORTS 256 |
| 606 | 606 | ||
| 607 | #define ZE_V1_NPORTS 64 | ||
| 608 | #define ZO_V1 0 | 607 | #define ZO_V1 0 |
| 609 | #define ZO_V2 1 | 608 | #define ZO_V2 1 |
| 610 | #define ZE_V1 2 | 609 | #define ZE_V1 2 |
| @@ -663,18 +662,6 @@ | |||
| 663 | static void cy_throttle(struct tty_struct *tty); | 662 | static void cy_throttle(struct tty_struct *tty); |
| 664 | static void cy_send_xchar(struct tty_struct *tty, char ch); | 663 | static void cy_send_xchar(struct tty_struct *tty, char ch); |
| 665 | 664 | ||
| 666 | #define IS_CYC_Z(card) ((card).num_chips == (unsigned int)-1) | ||
| 667 | |||
| 668 | #define Z_FPGA_CHECK(card) \ | ||
| 669 | ((readl(&((struct RUNTIME_9060 __iomem *) \ | ||
| 670 | ((card).ctl_addr))->init_ctrl) & (1<<17)) != 0) | ||
| 671 | |||
| 672 | #define ISZLOADED(card) (((ZO_V1 == readl(&((struct RUNTIME_9060 __iomem *) \ | ||
| 673 | ((card).ctl_addr))->mail_box_0)) || \ | ||
| 674 | Z_FPGA_CHECK(card)) && \ | ||
| 675 | (ZFIRM_ID == readl(&((struct FIRM_ID __iomem *) \ | ||
| 676 | ((card).base_addr+ID_ADDRESS))->signature))) | ||
| 677 | |||
| 678 | #ifndef SERIAL_XMIT_SIZE | 665 | #ifndef SERIAL_XMIT_SIZE |
| 679 | #define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) | 666 | #define SERIAL_XMIT_SIZE (min(PAGE_SIZE, 4096)) |
| 680 | #endif | 667 | #endif |
| @@ -687,8 +674,6 @@ static void cy_send_xchar(struct tty_struct *tty, char ch); | |||
| 687 | #define DRIVER_VERSION 0x02010203 | 674 | #define DRIVER_VERSION 0x02010203 |
| 688 | #define RAM_SIZE 0x80000 | 675 | #define RAM_SIZE 0x80000 |
| 689 | 676 | ||
| 690 | #define Z_FPGA_LOADED(X) ((readl(&(X)->init_ctrl) & (1<<17)) != 0) | ||
| 691 | |||
| 692 | enum zblock_type { | 677 | enum zblock_type { |
| 693 | ZBLOCK_PRG = 0, | 678 | ZBLOCK_PRG = 0, |
| 694 | ZBLOCK_FPGA = 1 | 679 | ZBLOCK_FPGA = 1 |
| @@ -883,6 +868,29 @@ static void cyz_rx_restart(unsigned long); | |||
| 883 | static struct timer_list cyz_rx_full_timer[NR_PORTS]; | 868 | static struct timer_list cyz_rx_full_timer[NR_PORTS]; |
| 884 | #endif /* CONFIG_CYZ_INTR */ | 869 | #endif /* CONFIG_CYZ_INTR */ |
| 885 | 870 | ||
| 871 | static inline bool cy_is_Z(struct cyclades_card *card) | ||
| 872 | { | ||
| 873 | return card->num_chips == (unsigned int)-1; | ||
| 874 | } | ||
| 875 | |||
| 876 | static inline bool __cyz_fpga_loaded(struct RUNTIME_9060 __iomem *ctl_addr) | ||
| 877 | { | ||
| 878 | return readl(&ctl_addr->init_ctrl) & (1 << 17); | ||
| 879 | } | ||
| 880 | |||
| 881 | static inline bool cyz_fpga_loaded(struct cyclades_card *card) | ||
| 882 | { | ||
| 883 | return __cyz_fpga_loaded(card->ctl_addr.p9060); | ||
| 884 | } | ||
| 885 | |||
| 886 | static inline bool cyz_is_loaded(struct cyclades_card *card) | ||
| 887 | { | ||
| 888 | struct FIRM_ID __iomem *fw_id = card->base_addr + ID_ADDRESS; | ||
| 889 | |||
| 890 | return (card->hw_ver == ZO_V1 || cyz_fpga_loaded(card)) && | ||
| 891 | readl(&fw_id->signature) == ZFIRM_ID; | ||
| 892 | } | ||
| 893 | |||
| 886 | static inline int serial_paranoia_check(struct cyclades_port *info, | 894 | static inline int serial_paranoia_check(struct cyclades_port *info, |
| 887 | char *name, const char *routine) | 895 | char *name, const char *routine) |
| 888 | { | 896 | { |
| @@ -1395,19 +1403,15 @@ cyz_fetch_msg(struct cyclades_card *cinfo, | |||
| 1395 | unsigned long loc_doorbell; | 1403 | unsigned long loc_doorbell; |
| 1396 | 1404 | ||
| 1397 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1405 | firm_id = cinfo->base_addr + ID_ADDRESS; |
| 1398 | if (!ISZLOADED(*cinfo)) | ||
| 1399 | return -1; | ||
| 1400 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1406 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
| 1401 | board_ctrl = &zfw_ctrl->board_ctrl; | 1407 | board_ctrl = &zfw_ctrl->board_ctrl; |
| 1402 | 1408 | ||
| 1403 | loc_doorbell = readl(&((struct RUNTIME_9060 __iomem *) | 1409 | loc_doorbell = readl(&cinfo->ctl_addr.p9060->loc_doorbell); |
| 1404 | (cinfo->ctl_addr))->loc_doorbell); | ||
| 1405 | if (loc_doorbell) { | 1410 | if (loc_doorbell) { |
| 1406 | *cmd = (char)(0xff & loc_doorbell); | 1411 | *cmd = (char)(0xff & loc_doorbell); |
| 1407 | *channel = readl(&board_ctrl->fwcmd_channel); | 1412 | *channel = readl(&board_ctrl->fwcmd_channel); |
| 1408 | *param = (__u32) readl(&board_ctrl->fwcmd_param); | 1413 | *param = (__u32) readl(&board_ctrl->fwcmd_param); |
| 1409 | cy_writel(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> | 1414 | cy_writel(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff); |
| 1410 | loc_doorbell, 0xffffffff); | ||
| 1411 | return 1; | 1415 | return 1; |
| 1412 | } | 1416 | } |
| 1413 | return 0; | 1417 | return 0; |
| @@ -1424,15 +1428,14 @@ cyz_issue_cmd(struct cyclades_card *cinfo, | |||
| 1424 | unsigned int index; | 1428 | unsigned int index; |
| 1425 | 1429 | ||
| 1426 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1430 | firm_id = cinfo->base_addr + ID_ADDRESS; |
| 1427 | if (!ISZLOADED(*cinfo)) | 1431 | if (!cyz_is_loaded(cinfo)) |
| 1428 | return -1; | 1432 | return -1; |
| 1429 | 1433 | ||
| 1430 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1434 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
| 1431 | board_ctrl = &zfw_ctrl->board_ctrl; | 1435 | board_ctrl = &zfw_ctrl->board_ctrl; |
| 1432 | 1436 | ||
| 1433 | index = 0; | 1437 | index = 0; |
| 1434 | pci_doorbell = | 1438 | pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell; |
| 1435 | &((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))->pci_doorbell; | ||
| 1436 | while ((readl(pci_doorbell) & 0xff) != 0) { | 1439 | while ((readl(pci_doorbell) & 0xff) != 0) { |
| 1437 | if (index++ == 1000) | 1440 | if (index++ == 1000) |
| 1438 | return (int)(readl(pci_doorbell) & 0xff); | 1441 | return (int)(readl(pci_doorbell) & 0xff); |
| @@ -1624,10 +1627,8 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
| 1624 | static struct BOARD_CTRL __iomem *board_ctrl; | 1627 | static struct BOARD_CTRL __iomem *board_ctrl; |
| 1625 | static struct CH_CTRL __iomem *ch_ctrl; | 1628 | static struct CH_CTRL __iomem *ch_ctrl; |
| 1626 | static struct BUF_CTRL __iomem *buf_ctrl; | 1629 | static struct BUF_CTRL __iomem *buf_ctrl; |
| 1627 | __u32 channel; | 1630 | __u32 channel, param, fw_ver; |
| 1628 | __u8 cmd; | 1631 | __u8 cmd; |
| 1629 | __u32 param; | ||
| 1630 | __u32 hw_ver, fw_ver; | ||
| 1631 | int special_count; | 1632 | int special_count; |
| 1632 | int delta_count; | 1633 | int delta_count; |
| 1633 | 1634 | ||
| @@ -1635,8 +1636,6 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo) | |||
| 1635 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1636 | zfw_ctrl = cinfo->base_addr + (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
| 1636 | board_ctrl = &zfw_ctrl->board_ctrl; | 1637 | board_ctrl = &zfw_ctrl->board_ctrl; |
| 1637 | fw_ver = readl(&board_ctrl->fw_version); | 1638 | fw_ver = readl(&board_ctrl->fw_version); |
| 1638 | hw_ver = readl(&((struct RUNTIME_9060 __iomem *)(cinfo->ctl_addr))-> | ||
| 1639 | mail_box_0); | ||
| 1640 | 1639 | ||
| 1641 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { | 1640 | while (cyz_fetch_msg(cinfo, &channel, &cmd, ¶m) == 1) { |
| 1642 | special_count = 0; | 1641 | special_count = 0; |
| @@ -1737,15 +1736,7 @@ static irqreturn_t cyz_interrupt(int irq, void *dev_id) | |||
| 1737 | { | 1736 | { |
| 1738 | struct cyclades_card *cinfo = dev_id; | 1737 | struct cyclades_card *cinfo = dev_id; |
| 1739 | 1738 | ||
| 1740 | if (unlikely(cinfo == NULL)) { | 1739 | if (unlikely(!cyz_is_loaded(cinfo))) { |
| 1741 | #ifdef CY_DEBUG_INTERRUPTS | ||
| 1742 | printk(KERN_DEBUG "cyz_interrupt: spurious interrupt %d\n", | ||
| 1743 | irq); | ||
| 1744 | #endif | ||
| 1745 | return IRQ_NONE; /* spurious interrupt */ | ||
| 1746 | } | ||
| 1747 | |||
| 1748 | if (unlikely(!ISZLOADED(*cinfo))) { | ||
| 1749 | #ifdef CY_DEBUG_INTERRUPTS | 1740 | #ifdef CY_DEBUG_INTERRUPTS |
| 1750 | printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " | 1741 | printk(KERN_DEBUG "cyz_interrupt: board not yet loaded " |
| 1751 | "(IRQ%d).\n", irq); | 1742 | "(IRQ%d).\n", irq); |
| @@ -1785,7 +1776,6 @@ static void cyz_poll(unsigned long arg) | |||
| 1785 | struct tty_struct *tty; | 1776 | struct tty_struct *tty; |
| 1786 | struct FIRM_ID __iomem *firm_id; | 1777 | struct FIRM_ID __iomem *firm_id; |
| 1787 | struct ZFW_CTRL __iomem *zfw_ctrl; | 1778 | struct ZFW_CTRL __iomem *zfw_ctrl; |
| 1788 | struct BOARD_CTRL __iomem *board_ctrl; | ||
| 1789 | struct BUF_CTRL __iomem *buf_ctrl; | 1779 | struct BUF_CTRL __iomem *buf_ctrl; |
| 1790 | unsigned long expires = jiffies + HZ; | 1780 | unsigned long expires = jiffies + HZ; |
| 1791 | unsigned int port, card; | 1781 | unsigned int port, card; |
| @@ -1793,19 +1783,17 @@ static void cyz_poll(unsigned long arg) | |||
| 1793 | for (card = 0; card < NR_CARDS; card++) { | 1783 | for (card = 0; card < NR_CARDS; card++) { |
| 1794 | cinfo = &cy_card[card]; | 1784 | cinfo = &cy_card[card]; |
| 1795 | 1785 | ||
| 1796 | if (!IS_CYC_Z(*cinfo)) | 1786 | if (!cy_is_Z(cinfo)) |
| 1797 | continue; | 1787 | continue; |
| 1798 | if (!ISZLOADED(*cinfo)) | 1788 | if (!cyz_is_loaded(cinfo)) |
| 1799 | continue; | 1789 | continue; |
| 1800 | 1790 | ||
| 1801 | firm_id = cinfo->base_addr + ID_ADDRESS; | 1791 | firm_id = cinfo->base_addr + ID_ADDRESS; |
| 1802 | zfw_ctrl = cinfo->base_addr + | 1792 | zfw_ctrl = cinfo->base_addr + |
| 1803 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 1793 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
| 1804 | board_ctrl = &(zfw_ctrl->board_ctrl); | ||
| 1805 | 1794 | ||
| 1806 | /* Skip first polling cycle to avoid racing conditions with the FW */ | 1795 | /* Skip first polling cycle to avoid racing conditions with the FW */ |
| 1807 | if (!cinfo->intr_enabled) { | 1796 | if (!cinfo->intr_enabled) { |
| 1808 | cinfo->nports = (int)readl(&board_ctrl->n_channel); | ||
| 1809 | cinfo->intr_enabled = 1; | 1797 | cinfo->intr_enabled = 1; |
| 1810 | continue; | 1798 | continue; |
| 1811 | } | 1799 | } |
| @@ -1874,7 +1862,7 @@ static int startup(struct cyclades_port *info) | |||
| 1874 | 1862 | ||
| 1875 | set_line_char(info); | 1863 | set_line_char(info); |
| 1876 | 1864 | ||
| 1877 | if (!IS_CYC_Z(*card)) { | 1865 | if (!cy_is_Z(card)) { |
| 1878 | chip = channel >> 2; | 1866 | chip = channel >> 2; |
| 1879 | channel &= 0x03; | 1867 | channel &= 0x03; |
| 1880 | index = card->bus_index; | 1868 | index = card->bus_index; |
| @@ -1931,7 +1919,7 @@ static int startup(struct cyclades_port *info) | |||
| 1931 | base_addr = card->base_addr; | 1919 | base_addr = card->base_addr; |
| 1932 | 1920 | ||
| 1933 | firm_id = base_addr + ID_ADDRESS; | 1921 | firm_id = base_addr + ID_ADDRESS; |
| 1934 | if (!ISZLOADED(*card)) | 1922 | if (!cyz_is_loaded(card)) |
| 1935 | return -ENODEV; | 1923 | return -ENODEV; |
| 1936 | 1924 | ||
| 1937 | zfw_ctrl = card->base_addr + | 1925 | zfw_ctrl = card->base_addr + |
| @@ -2026,7 +2014,7 @@ static void start_xmit(struct cyclades_port *info) | |||
| 2026 | 2014 | ||
| 2027 | card = info->card; | 2015 | card = info->card; |
| 2028 | channel = info->line - card->first_line; | 2016 | channel = info->line - card->first_line; |
| 2029 | if (!IS_CYC_Z(*card)) { | 2017 | if (!cy_is_Z(card)) { |
| 2030 | chip = channel >> 2; | 2018 | chip = channel >> 2; |
| 2031 | channel &= 0x03; | 2019 | channel &= 0x03; |
| 2032 | index = card->bus_index; | 2020 | index = card->bus_index; |
| @@ -2070,7 +2058,7 @@ static void shutdown(struct cyclades_port *info) | |||
| 2070 | 2058 | ||
| 2071 | card = info->card; | 2059 | card = info->card; |
| 2072 | channel = info->line - card->first_line; | 2060 | channel = info->line - card->first_line; |
| 2073 | if (!IS_CYC_Z(*card)) { | 2061 | if (!cy_is_Z(card)) { |
| 2074 | chip = channel >> 2; | 2062 | chip = channel >> 2; |
| 2075 | channel &= 0x03; | 2063 | channel &= 0x03; |
| 2076 | index = card->bus_index; | 2064 | index = card->bus_index; |
| @@ -2126,7 +2114,7 @@ static void shutdown(struct cyclades_port *info) | |||
| 2126 | #endif | 2114 | #endif |
| 2127 | 2115 | ||
| 2128 | firm_id = base_addr + ID_ADDRESS; | 2116 | firm_id = base_addr + ID_ADDRESS; |
| 2129 | if (!ISZLOADED(*card)) | 2117 | if (!cyz_is_loaded(card)) |
| 2130 | return; | 2118 | return; |
| 2131 | 2119 | ||
| 2132 | zfw_ctrl = card->base_addr + | 2120 | zfw_ctrl = card->base_addr + |
| @@ -2233,7 +2221,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
| 2233 | #endif | 2221 | #endif |
| 2234 | info->port.blocked_open++; | 2222 | info->port.blocked_open++; |
| 2235 | 2223 | ||
| 2236 | if (!IS_CYC_Z(*cinfo)) { | 2224 | if (!cy_is_Z(cinfo)) { |
| 2237 | chip = channel >> 2; | 2225 | chip = channel >> 2; |
| 2238 | channel &= 0x03; | 2226 | channel &= 0x03; |
| 2239 | index = cinfo->bus_index; | 2227 | index = cinfo->bus_index; |
| @@ -2296,7 +2284,7 @@ block_til_ready(struct tty_struct *tty, struct file *filp, | |||
| 2296 | 2284 | ||
| 2297 | base_addr = cinfo->base_addr; | 2285 | base_addr = cinfo->base_addr; |
| 2298 | firm_id = base_addr + ID_ADDRESS; | 2286 | firm_id = base_addr + ID_ADDRESS; |
| 2299 | if (!ISZLOADED(*cinfo)) { | 2287 | if (!cyz_is_loaded(cinfo)) { |
| 2300 | __set_current_state(TASK_RUNNING); | 2288 | __set_current_state(TASK_RUNNING); |
| 2301 | remove_wait_queue(&info->port.open_wait, &wait); | 2289 | remove_wait_queue(&info->port.open_wait, &wait); |
| 2302 | return -EINVAL; | 2290 | return -EINVAL; |
| @@ -2397,16 +2385,14 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
| 2397 | treat it as absent from the system. This | 2385 | treat it as absent from the system. This |
| 2398 | will make the user pay attention. | 2386 | will make the user pay attention. |
| 2399 | */ | 2387 | */ |
| 2400 | if (IS_CYC_Z(*info->card)) { | 2388 | if (cy_is_Z(info->card)) { |
| 2401 | struct cyclades_card *cinfo = info->card; | 2389 | struct cyclades_card *cinfo = info->card; |
| 2402 | struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; | 2390 | struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS; |
| 2403 | 2391 | ||
| 2404 | if (!ISZLOADED(*cinfo)) { | 2392 | if (!cyz_is_loaded(cinfo)) { |
| 2405 | if (((ZE_V1 == readl(&((struct RUNTIME_9060 __iomem *) | 2393 | if (cinfo->hw_ver == ZE_V1 && cyz_fpga_loaded(cinfo) && |
| 2406 | (cinfo->ctl_addr))->mail_box_0)) && | 2394 | readl(&firm_id->signature) == |
| 2407 | Z_FPGA_CHECK(*cinfo)) && | 2395 | ZFIRM_HLT) { |
| 2408 | (ZFIRM_HLT == readl( | ||
| 2409 | &firm_id->signature))) { | ||
| 2410 | printk(KERN_ERR "cyc:Cyclades-Z Error: you " | 2396 | printk(KERN_ERR "cyc:Cyclades-Z Error: you " |
| 2411 | "need an external power supply for " | 2397 | "need an external power supply for " |
| 2412 | "this number of ports.\nFirmware " | 2398 | "this number of ports.\nFirmware " |
| @@ -2423,18 +2409,13 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
| 2423 | interrupts should be enabled as soon as the first open | 2409 | interrupts should be enabled as soon as the first open |
| 2424 | happens to one of its ports. */ | 2410 | happens to one of its ports. */ |
| 2425 | if (!cinfo->intr_enabled) { | 2411 | if (!cinfo->intr_enabled) { |
| 2426 | struct ZFW_CTRL __iomem *zfw_ctrl; | 2412 | u16 intr; |
| 2427 | struct BOARD_CTRL __iomem *board_ctrl; | ||
| 2428 | |||
| 2429 | zfw_ctrl = cinfo->base_addr + | ||
| 2430 | (readl(&firm_id->zfwctrl_addr) & | ||
| 2431 | 0xfffff); | ||
| 2432 | |||
| 2433 | board_ctrl = &zfw_ctrl->board_ctrl; | ||
| 2434 | 2413 | ||
| 2435 | /* Enable interrupts on the PLX chip */ | 2414 | /* Enable interrupts on the PLX chip */ |
| 2436 | cy_writew(cinfo->ctl_addr + 0x68, | 2415 | intr = readw(&cinfo->ctl_addr.p9060-> |
| 2437 | readw(cinfo->ctl_addr + 0x68) | 0x0900); | 2416 | intr_ctrl_stat) | 0x0900; |
| 2417 | cy_writew(&cinfo->ctl_addr.p9060-> | ||
| 2418 | intr_ctrl_stat, intr); | ||
| 2438 | /* Enable interrupts on the FW */ | 2419 | /* Enable interrupts on the FW */ |
| 2439 | retval = cyz_issue_cmd(cinfo, 0, | 2420 | retval = cyz_issue_cmd(cinfo, 0, |
| 2440 | C_CM_IRQ_ENBL, 0L); | 2421 | C_CM_IRQ_ENBL, 0L); |
| @@ -2442,8 +2423,6 @@ static int cy_open(struct tty_struct *tty, struct file *filp) | |||
| 2442 | printk(KERN_ERR "cyc:IRQ enable retval " | 2423 | printk(KERN_ERR "cyc:IRQ enable retval " |
| 2443 | "was %x\n", retval); | 2424 | "was %x\n", retval); |
| 2444 | } | 2425 | } |
| 2445 | cinfo->nports = | ||
| 2446 | (int)readl(&board_ctrl->n_channel); | ||
| 2447 | cinfo->intr_enabled = 1; | 2426 | cinfo->intr_enabled = 1; |
| 2448 | } | 2427 | } |
| 2449 | } | 2428 | } |
| @@ -2556,7 +2535,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout) | |||
| 2556 | #endif | 2535 | #endif |
| 2557 | card = info->card; | 2536 | card = info->card; |
| 2558 | channel = (info->line) - (card->first_line); | 2537 | channel = (info->line) - (card->first_line); |
| 2559 | if (!IS_CYC_Z(*card)) { | 2538 | if (!cy_is_Z(card)) { |
| 2560 | chip = channel >> 2; | 2539 | chip = channel >> 2; |
| 2561 | channel &= 0x03; | 2540 | channel &= 0x03; |
| 2562 | index = card->bus_index; | 2541 | index = card->bus_index; |
| @@ -2601,7 +2580,7 @@ static void cy_flush_buffer(struct tty_struct *tty) | |||
| 2601 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; | 2580 | info->xmit_cnt = info->xmit_head = info->xmit_tail = 0; |
| 2602 | spin_unlock_irqrestore(&card->card_lock, flags); | 2581 | spin_unlock_irqrestore(&card->card_lock, flags); |
| 2603 | 2582 | ||
| 2604 | if (IS_CYC_Z(*card)) { /* If it is a Z card, flush the on-board | 2583 | if (cy_is_Z(card)) { /* If it is a Z card, flush the on-board |
| 2605 | buffers as well */ | 2584 | buffers as well */ |
| 2606 | spin_lock_irqsave(&card->card_lock, flags); | 2585 | spin_lock_irqsave(&card->card_lock, flags); |
| 2607 | retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); | 2586 | retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L); |
| @@ -2682,7 +2661,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp) | |||
| 2682 | 2661 | ||
| 2683 | spin_lock_irqsave(&card->card_lock, flags); | 2662 | spin_lock_irqsave(&card->card_lock, flags); |
| 2684 | 2663 | ||
| 2685 | if (!IS_CYC_Z(*card)) { | 2664 | if (!cy_is_Z(card)) { |
| 2686 | int channel = info->line - card->first_line; | 2665 | int channel = info->line - card->first_line; |
| 2687 | int index = card->bus_index; | 2666 | int index = card->bus_index; |
| 2688 | void __iomem *base_addr = card->base_addr + | 2667 | void __iomem *base_addr = card->base_addr + |
| @@ -2902,7 +2881,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty) | |||
| 2902 | channel = (info->line) - (card->first_line); | 2881 | channel = (info->line) - (card->first_line); |
| 2903 | 2882 | ||
| 2904 | #ifdef Z_EXT_CHARS_IN_BUFFER | 2883 | #ifdef Z_EXT_CHARS_IN_BUFFER |
| 2905 | if (!IS_CYC_Z(cy_card[card])) { | 2884 | if (!cy_is_Z(card)) { |
| 2906 | #endif /* Z_EXT_CHARS_IN_BUFFER */ | 2885 | #endif /* Z_EXT_CHARS_IN_BUFFER */ |
| 2907 | #ifdef CY_DEBUG_IO | 2886 | #ifdef CY_DEBUG_IO |
| 2908 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", | 2887 | printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n", |
| @@ -2984,7 +2963,6 @@ static void set_line_char(struct cyclades_port *info) | |||
| 2984 | void __iomem *base_addr; | 2963 | void __iomem *base_addr; |
| 2985 | int chip, channel, index; | 2964 | int chip, channel, index; |
| 2986 | unsigned cflag, iflag; | 2965 | unsigned cflag, iflag; |
| 2987 | unsigned short chip_number; | ||
| 2988 | int baud, baud_rate = 0; | 2966 | int baud, baud_rate = 0; |
| 2989 | int i; | 2967 | int i; |
| 2990 | 2968 | ||
| @@ -3013,9 +2991,8 @@ static void set_line_char(struct cyclades_port *info) | |||
| 3013 | 2991 | ||
| 3014 | card = info->card; | 2992 | card = info->card; |
| 3015 | channel = info->line - card->first_line; | 2993 | channel = info->line - card->first_line; |
| 3016 | chip_number = channel / 4; | ||
| 3017 | 2994 | ||
| 3018 | if (!IS_CYC_Z(*card)) { | 2995 | if (!cy_is_Z(card)) { |
| 3019 | 2996 | ||
| 3020 | index = card->bus_index; | 2997 | index = card->bus_index; |
| 3021 | 2998 | ||
| @@ -3233,21 +3210,17 @@ static void set_line_char(struct cyclades_port *info) | |||
| 3233 | } else { | 3210 | } else { |
| 3234 | struct FIRM_ID __iomem *firm_id; | 3211 | struct FIRM_ID __iomem *firm_id; |
| 3235 | struct ZFW_CTRL __iomem *zfw_ctrl; | 3212 | struct ZFW_CTRL __iomem *zfw_ctrl; |
| 3236 | struct BOARD_CTRL __iomem *board_ctrl; | ||
| 3237 | struct CH_CTRL __iomem *ch_ctrl; | 3213 | struct CH_CTRL __iomem *ch_ctrl; |
| 3238 | struct BUF_CTRL __iomem *buf_ctrl; | ||
| 3239 | __u32 sw_flow; | 3214 | __u32 sw_flow; |
| 3240 | int retval; | 3215 | int retval; |
| 3241 | 3216 | ||
| 3242 | firm_id = card->base_addr + ID_ADDRESS; | 3217 | firm_id = card->base_addr + ID_ADDRESS; |
| 3243 | if (!ISZLOADED(*card)) | 3218 | if (!cyz_is_loaded(card)) |
| 3244 | return; | 3219 | return; |
| 3245 | 3220 | ||
| 3246 | zfw_ctrl = card->base_addr + | 3221 | zfw_ctrl = card->base_addr + |
| 3247 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3222 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
| 3248 | board_ctrl = &zfw_ctrl->board_ctrl; | ||
| 3249 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); | 3223 | ch_ctrl = &(zfw_ctrl->ch_ctrl[channel]); |
| 3250 | buf_ctrl = &zfw_ctrl->buf_ctrl[channel]; | ||
| 3251 | 3224 | ||
| 3252 | /* baud rate */ | 3225 | /* baud rate */ |
| 3253 | baud = tty_get_baud_rate(info->port.tty); | 3226 | baud = tty_get_baud_rate(info->port.tty); |
| @@ -3457,7 +3430,7 @@ static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value) | |||
| 3457 | 3430 | ||
| 3458 | card = info->card; | 3431 | card = info->card; |
| 3459 | channel = (info->line) - (card->first_line); | 3432 | channel = (info->line) - (card->first_line); |
| 3460 | if (!IS_CYC_Z(*card)) { | 3433 | if (!cy_is_Z(card)) { |
| 3461 | chip = channel >> 2; | 3434 | chip = channel >> 2; |
| 3462 | channel &= 0x03; | 3435 | channel &= 0x03; |
| 3463 | index = card->bus_index; | 3436 | index = card->bus_index; |
| @@ -3497,7 +3470,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 3497 | 3470 | ||
| 3498 | card = info->card; | 3471 | card = info->card; |
| 3499 | channel = info->line - card->first_line; | 3472 | channel = info->line - card->first_line; |
| 3500 | if (!IS_CYC_Z(*card)) { | 3473 | if (!cy_is_Z(card)) { |
| 3501 | chip = channel >> 2; | 3474 | chip = channel >> 2; |
| 3502 | channel &= 0x03; | 3475 | channel &= 0x03; |
| 3503 | index = card->bus_index; | 3476 | index = card->bus_index; |
| @@ -3523,7 +3496,7 @@ static int cy_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 3523 | } else { | 3496 | } else { |
| 3524 | base_addr = card->base_addr; | 3497 | base_addr = card->base_addr; |
| 3525 | firm_id = card->base_addr + ID_ADDRESS; | 3498 | firm_id = card->base_addr + ID_ADDRESS; |
| 3526 | if (ISZLOADED(*card)) { | 3499 | if (cyz_is_loaded(card)) { |
| 3527 | zfw_ctrl = card->base_addr + | 3500 | zfw_ctrl = card->base_addr + |
| 3528 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3501 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
| 3529 | board_ctrl = &zfw_ctrl->board_ctrl; | 3502 | board_ctrl = &zfw_ctrl->board_ctrl; |
| @@ -3566,7 +3539,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 3566 | 3539 | ||
| 3567 | card = info->card; | 3540 | card = info->card; |
| 3568 | channel = (info->line) - (card->first_line); | 3541 | channel = (info->line) - (card->first_line); |
| 3569 | if (!IS_CYC_Z(*card)) { | 3542 | if (!cy_is_Z(card)) { |
| 3570 | chip = channel >> 2; | 3543 | chip = channel >> 2; |
| 3571 | channel &= 0x03; | 3544 | channel &= 0x03; |
| 3572 | index = card->bus_index; | 3545 | index = card->bus_index; |
| @@ -3641,7 +3614,7 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 3641 | base_addr = card->base_addr; | 3614 | base_addr = card->base_addr; |
| 3642 | 3615 | ||
| 3643 | firm_id = card->base_addr + ID_ADDRESS; | 3616 | firm_id = card->base_addr + ID_ADDRESS; |
| 3644 | if (ISZLOADED(*card)) { | 3617 | if (cyz_is_loaded(card)) { |
| 3645 | zfw_ctrl = card->base_addr + | 3618 | zfw_ctrl = card->base_addr + |
| 3646 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); | 3619 | (readl(&firm_id->zfwctrl_addr) & 0xfffff); |
| 3647 | board_ctrl = &zfw_ctrl->board_ctrl; | 3620 | board_ctrl = &zfw_ctrl->board_ctrl; |
| @@ -3713,7 +3686,7 @@ static int cy_break(struct tty_struct *tty, int break_state) | |||
| 3713 | card = info->card; | 3686 | card = info->card; |
| 3714 | 3687 | ||
| 3715 | spin_lock_irqsave(&card->card_lock, flags); | 3688 | spin_lock_irqsave(&card->card_lock, flags); |
| 3716 | if (!IS_CYC_Z(*card)) { | 3689 | if (!cy_is_Z(card)) { |
| 3717 | /* Let the transmit ISR take care of this (since it | 3690 | /* Let the transmit ISR take care of this (since it |
| 3718 | requires stuffing characters into the output stream). | 3691 | requires stuffing characters into the output stream). |
| 3719 | */ | 3692 | */ |
| @@ -3782,7 +3755,7 @@ static int set_threshold(struct cyclades_port *info, unsigned long value) | |||
| 3782 | 3755 | ||
| 3783 | card = info->card; | 3756 | card = info->card; |
| 3784 | channel = info->line - card->first_line; | 3757 | channel = info->line - card->first_line; |
| 3785 | if (!IS_CYC_Z(*card)) { | 3758 | if (!cy_is_Z(card)) { |
| 3786 | chip = channel >> 2; | 3759 | chip = channel >> 2; |
| 3787 | channel &= 0x03; | 3760 | channel &= 0x03; |
| 3788 | index = card->bus_index; | 3761 | index = card->bus_index; |
| @@ -3810,7 +3783,7 @@ static int get_threshold(struct cyclades_port *info, | |||
| 3810 | 3783 | ||
| 3811 | card = info->card; | 3784 | card = info->card; |
| 3812 | channel = info->line - card->first_line; | 3785 | channel = info->line - card->first_line; |
| 3813 | if (!IS_CYC_Z(*card)) { | 3786 | if (!cy_is_Z(card)) { |
| 3814 | chip = channel >> 2; | 3787 | chip = channel >> 2; |
| 3815 | channel &= 0x03; | 3788 | channel &= 0x03; |
| 3816 | index = card->bus_index; | 3789 | index = card->bus_index; |
| @@ -3844,7 +3817,7 @@ static int set_timeout(struct cyclades_port *info, unsigned long value) | |||
| 3844 | 3817 | ||
| 3845 | card = info->card; | 3818 | card = info->card; |
| 3846 | channel = info->line - card->first_line; | 3819 | channel = info->line - card->first_line; |
| 3847 | if (!IS_CYC_Z(*card)) { | 3820 | if (!cy_is_Z(card)) { |
| 3848 | chip = channel >> 2; | 3821 | chip = channel >> 2; |
| 3849 | channel &= 0x03; | 3822 | channel &= 0x03; |
| 3850 | index = card->bus_index; | 3823 | index = card->bus_index; |
| @@ -3867,7 +3840,7 @@ static int get_timeout(struct cyclades_port *info, | |||
| 3867 | 3840 | ||
| 3868 | card = info->card; | 3841 | card = info->card; |
| 3869 | channel = info->line - card->first_line; | 3842 | channel = info->line - card->first_line; |
| 3870 | if (!IS_CYC_Z(*card)) { | 3843 | if (!cy_is_Z(card)) { |
| 3871 | chip = channel >> 2; | 3844 | chip = channel >> 2; |
| 3872 | channel &= 0x03; | 3845 | channel &= 0x03; |
| 3873 | index = card->bus_index; | 3846 | index = card->bus_index; |
| @@ -4121,7 +4094,7 @@ static void cy_send_xchar(struct tty_struct *tty, char ch) | |||
| 4121 | card = info->card; | 4094 | card = info->card; |
| 4122 | channel = info->line - card->first_line; | 4095 | channel = info->line - card->first_line; |
| 4123 | 4096 | ||
| 4124 | if (IS_CYC_Z(*card)) { | 4097 | if (cy_is_Z(card)) { |
| 4125 | if (ch == STOP_CHAR(tty)) | 4098 | if (ch == STOP_CHAR(tty)) |
| 4126 | cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); | 4099 | cyz_issue_cmd(card, channel, C_CM_SENDXOFF, 0L); |
| 4127 | else if (ch == START_CHAR(tty)) | 4100 | else if (ch == START_CHAR(tty)) |
| @@ -4154,7 +4127,7 @@ static void cy_throttle(struct tty_struct *tty) | |||
| 4154 | card = info->card; | 4127 | card = info->card; |
| 4155 | 4128 | ||
| 4156 | if (I_IXOFF(tty)) { | 4129 | if (I_IXOFF(tty)) { |
| 4157 | if (!IS_CYC_Z(*card)) | 4130 | if (!cy_is_Z(card)) |
| 4158 | cy_send_xchar(tty, STOP_CHAR(tty)); | 4131 | cy_send_xchar(tty, STOP_CHAR(tty)); |
| 4159 | else | 4132 | else |
| 4160 | info->throttle = 1; | 4133 | info->throttle = 1; |
| @@ -4162,7 +4135,7 @@ static void cy_throttle(struct tty_struct *tty) | |||
| 4162 | 4135 | ||
| 4163 | if (tty->termios->c_cflag & CRTSCTS) { | 4136 | if (tty->termios->c_cflag & CRTSCTS) { |
| 4164 | channel = info->line - card->first_line; | 4137 | channel = info->line - card->first_line; |
| 4165 | if (!IS_CYC_Z(*card)) { | 4138 | if (!cy_is_Z(card)) { |
| 4166 | chip = channel >> 2; | 4139 | chip = channel >> 2; |
| 4167 | channel &= 0x03; | 4140 | channel &= 0x03; |
| 4168 | index = card->bus_index; | 4141 | index = card->bus_index; |
| @@ -4219,7 +4192,7 @@ static void cy_unthrottle(struct tty_struct *tty) | |||
| 4219 | if (tty->termios->c_cflag & CRTSCTS) { | 4192 | if (tty->termios->c_cflag & CRTSCTS) { |
| 4220 | card = info->card; | 4193 | card = info->card; |
| 4221 | channel = info->line - card->first_line; | 4194 | channel = info->line - card->first_line; |
| 4222 | if (!IS_CYC_Z(*card)) { | 4195 | if (!cy_is_Z(card)) { |
| 4223 | chip = channel >> 2; | 4196 | chip = channel >> 2; |
| 4224 | channel &= 0x03; | 4197 | channel &= 0x03; |
| 4225 | index = card->bus_index; | 4198 | index = card->bus_index; |
| @@ -4263,7 +4236,7 @@ static void cy_stop(struct tty_struct *tty) | |||
| 4263 | 4236 | ||
| 4264 | cinfo = info->card; | 4237 | cinfo = info->card; |
| 4265 | channel = info->line - cinfo->first_line; | 4238 | channel = info->line - cinfo->first_line; |
| 4266 | if (!IS_CYC_Z(*cinfo)) { | 4239 | if (!cy_is_Z(cinfo)) { |
| 4267 | index = cinfo->bus_index; | 4240 | index = cinfo->bus_index; |
| 4268 | chip = channel >> 2; | 4241 | chip = channel >> 2; |
| 4269 | channel &= 0x03; | 4242 | channel &= 0x03; |
| @@ -4296,7 +4269,7 @@ static void cy_start(struct tty_struct *tty) | |||
| 4296 | cinfo = info->card; | 4269 | cinfo = info->card; |
| 4297 | channel = info->line - cinfo->first_line; | 4270 | channel = info->line - cinfo->first_line; |
| 4298 | index = cinfo->bus_index; | 4271 | index = cinfo->bus_index; |
| 4299 | if (!IS_CYC_Z(*cinfo)) { | 4272 | if (!cy_is_Z(cinfo)) { |
| 4300 | chip = channel >> 2; | 4273 | chip = channel >> 2; |
| 4301 | channel &= 0x03; | 4274 | channel &= 0x03; |
| 4302 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); | 4275 | base_addr = cinfo->base_addr + (cy_chip_offset[chip] << index); |
| @@ -4347,33 +4320,20 @@ static void cy_hangup(struct tty_struct *tty) | |||
| 4347 | static int __devinit cy_init_card(struct cyclades_card *cinfo) | 4320 | static int __devinit cy_init_card(struct cyclades_card *cinfo) |
| 4348 | { | 4321 | { |
| 4349 | struct cyclades_port *info; | 4322 | struct cyclades_port *info; |
| 4350 | u32 uninitialized_var(mailbox); | 4323 | unsigned int port; |
| 4351 | unsigned int nports, port; | ||
| 4352 | unsigned short chip_number; | 4324 | unsigned short chip_number; |
| 4353 | int uninitialized_var(index); | ||
| 4354 | 4325 | ||
| 4355 | spin_lock_init(&cinfo->card_lock); | 4326 | spin_lock_init(&cinfo->card_lock); |
| 4327 | cinfo->intr_enabled = 0; | ||
| 4356 | 4328 | ||
| 4357 | if (IS_CYC_Z(*cinfo)) { /* Cyclades-Z */ | 4329 | cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports), |
| 4358 | mailbox = readl(&((struct RUNTIME_9060 __iomem *) | 4330 | GFP_KERNEL); |
| 4359 | cinfo->ctl_addr)->mail_box_0); | ||
| 4360 | nports = (mailbox == ZE_V1) ? ZE_V1_NPORTS : 8; | ||
| 4361 | cinfo->intr_enabled = 0; | ||
| 4362 | cinfo->nports = 0; /* Will be correctly set later, after | ||
| 4363 | Z FW is loaded */ | ||
| 4364 | } else { | ||
| 4365 | index = cinfo->bus_index; | ||
| 4366 | nports = cinfo->nports = CyPORTS_PER_CHIP * cinfo->num_chips; | ||
| 4367 | } | ||
| 4368 | |||
| 4369 | cinfo->ports = kzalloc(sizeof(*cinfo->ports) * nports, GFP_KERNEL); | ||
| 4370 | if (cinfo->ports == NULL) { | 4331 | if (cinfo->ports == NULL) { |
| 4371 | printk(KERN_ERR "Cyclades: cannot allocate ports\n"); | 4332 | printk(KERN_ERR "Cyclades: cannot allocate ports\n"); |
| 4372 | cinfo->nports = 0; | ||
| 4373 | return -ENOMEM; | 4333 | return -ENOMEM; |
| 4374 | } | 4334 | } |
| 4375 | 4335 | ||
| 4376 | for (port = cinfo->first_line; port < cinfo->first_line + nports; | 4336 | for (port = cinfo->first_line; port < cinfo->first_line + cinfo->nports; |
| 4377 | port++) { | 4337 | port++) { |
| 4378 | info = &cinfo->ports[port - cinfo->first_line]; | 4338 | info = &cinfo->ports[port - cinfo->first_line]; |
| 4379 | tty_port_init(&info->port); | 4339 | tty_port_init(&info->port); |
| @@ -4387,9 +4347,9 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
| 4387 | init_completion(&info->shutdown_wait); | 4347 | init_completion(&info->shutdown_wait); |
| 4388 | init_waitqueue_head(&info->delta_msr_wait); | 4348 | init_waitqueue_head(&info->delta_msr_wait); |
| 4389 | 4349 | ||
| 4390 | if (IS_CYC_Z(*cinfo)) { | 4350 | if (cy_is_Z(cinfo)) { |
| 4391 | info->type = PORT_STARTECH; | 4351 | info->type = PORT_STARTECH; |
| 4392 | if (mailbox == ZO_V1) | 4352 | if (cinfo->hw_ver == ZO_V1) |
| 4393 | info->xmit_fifo_size = CYZ_FIFO_SIZE; | 4353 | info->xmit_fifo_size = CYZ_FIFO_SIZE; |
| 4394 | else | 4354 | else |
| 4395 | info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; | 4355 | info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE; |
| @@ -4398,6 +4358,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
| 4398 | cyz_rx_restart, (unsigned long)info); | 4358 | cyz_rx_restart, (unsigned long)info); |
| 4399 | #endif | 4359 | #endif |
| 4400 | } else { | 4360 | } else { |
| 4361 | int index = cinfo->bus_index; | ||
| 4401 | info->type = PORT_CIRRUS; | 4362 | info->type = PORT_CIRRUS; |
| 4402 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; | 4363 | info->xmit_fifo_size = CyMAX_CHAR_FIFO; |
| 4403 | info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; | 4364 | info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS; |
| @@ -4430,7 +4391,7 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo) | |||
| 4430 | } | 4391 | } |
| 4431 | 4392 | ||
| 4432 | #ifndef CONFIG_CYZ_INTR | 4393 | #ifndef CONFIG_CYZ_INTR |
| 4433 | if (IS_CYC_Z(*cinfo) && !timer_pending(&cyz_timerlist)) { | 4394 | if (cy_is_Z(cinfo) && !timer_pending(&cyz_timerlist)) { |
| 4434 | mod_timer(&cyz_timerlist, jiffies + 1); | 4395 | mod_timer(&cyz_timerlist, jiffies + 1); |
| 4435 | #ifdef CY_PCI_DEBUG | 4396 | #ifdef CY_PCI_DEBUG |
| 4436 | printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); | 4397 | printk(KERN_DEBUG "Cyclades-Z polling initialized\n"); |
| @@ -4621,11 +4582,12 @@ static int __init cy_detect_isa(void) | |||
| 4621 | 4582 | ||
| 4622 | /* set cy_card */ | 4583 | /* set cy_card */ |
| 4623 | cy_card[j].base_addr = cy_isa_address; | 4584 | cy_card[j].base_addr = cy_isa_address; |
| 4624 | cy_card[j].ctl_addr = NULL; | 4585 | cy_card[j].ctl_addr.p9050 = NULL; |
| 4625 | cy_card[j].irq = (int)cy_isa_irq; | 4586 | cy_card[j].irq = (int)cy_isa_irq; |
| 4626 | cy_card[j].bus_index = 0; | 4587 | cy_card[j].bus_index = 0; |
| 4627 | cy_card[j].first_line = cy_next_channel; | 4588 | cy_card[j].first_line = cy_next_channel; |
| 4628 | cy_card[j].num_chips = cy_isa_nchan / 4; | 4589 | cy_card[j].num_chips = cy_isa_nchan / CyPORTS_PER_CHIP; |
| 4590 | cy_card[j].nports = cy_isa_nchan; | ||
| 4629 | if (cy_init_card(&cy_card[j])) { | 4591 | if (cy_init_card(&cy_card[j])) { |
| 4630 | cy_card[j].base_addr = NULL; | 4592 | cy_card[j].base_addr = NULL; |
| 4631 | free_irq(cy_isa_irq, &cy_card[j]); | 4593 | free_irq(cy_isa_irq, &cy_card[j]); |
| @@ -4781,7 +4743,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
| 4781 | struct CUSTOM_REG __iomem *cust = base_addr; | 4743 | struct CUSTOM_REG __iomem *cust = base_addr; |
| 4782 | struct ZFW_CTRL __iomem *pt_zfwctrl; | 4744 | struct ZFW_CTRL __iomem *pt_zfwctrl; |
| 4783 | void __iomem *tmp; | 4745 | void __iomem *tmp; |
| 4784 | u32 mailbox, status; | 4746 | u32 mailbox, status, nchan; |
| 4785 | unsigned int i; | 4747 | unsigned int i; |
| 4786 | int retval; | 4748 | int retval; |
| 4787 | 4749 | ||
| @@ -4793,7 +4755,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
| 4793 | 4755 | ||
| 4794 | /* Check whether the firmware is already loaded and running. If | 4756 | /* Check whether the firmware is already loaded and running. If |
| 4795 | positive, skip this board */ | 4757 | positive, skip this board */ |
| 4796 | if (Z_FPGA_LOADED(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { | 4758 | if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) { |
| 4797 | u32 cntval = readl(base_addr + 0x190); | 4759 | u32 cntval = readl(base_addr + 0x190); |
| 4798 | 4760 | ||
| 4799 | udelay(100); | 4761 | udelay(100); |
| @@ -4812,7 +4774,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
| 4812 | 4774 | ||
| 4813 | mailbox = readl(&ctl_addr->mail_box_0); | 4775 | mailbox = readl(&ctl_addr->mail_box_0); |
| 4814 | 4776 | ||
| 4815 | if (mailbox == 0 || Z_FPGA_LOADED(ctl_addr)) { | 4777 | if (mailbox == 0 || __cyz_fpga_loaded(ctl_addr)) { |
| 4816 | /* stops CPU and set window to beginning of RAM */ | 4778 | /* stops CPU and set window to beginning of RAM */ |
| 4817 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); | 4779 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); |
| 4818 | cy_writel(&cust->cpu_stop, 0); | 4780 | cy_writel(&cust->cpu_stop, 0); |
| @@ -4828,7 +4790,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
| 4828 | base_addr); | 4790 | base_addr); |
| 4829 | if (retval) | 4791 | if (retval) |
| 4830 | goto err_rel; | 4792 | goto err_rel; |
| 4831 | if (!Z_FPGA_LOADED(ctl_addr)) { | 4793 | if (!__cyz_fpga_loaded(ctl_addr)) { |
| 4832 | dev_err(&pdev->dev, "fw upload successful, but fw is " | 4794 | dev_err(&pdev->dev, "fw upload successful, but fw is " |
| 4833 | "not loaded\n"); | 4795 | "not loaded\n"); |
| 4834 | goto err_rel; | 4796 | goto err_rel; |
| @@ -4887,7 +4849,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
| 4887 | "system before loading the new FW to the " | 4849 | "system before loading the new FW to the " |
| 4888 | "Cyclades-Z.\n"); | 4850 | "Cyclades-Z.\n"); |
| 4889 | 4851 | ||
| 4890 | if (Z_FPGA_LOADED(ctl_addr)) | 4852 | if (__cyz_fpga_loaded(ctl_addr)) |
| 4891 | plx_init(pdev, irq, ctl_addr); | 4853 | plx_init(pdev, irq, ctl_addr); |
| 4892 | 4854 | ||
| 4893 | retval = -EIO; | 4855 | retval = -EIO; |
| @@ -4902,16 +4864,16 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
| 4902 | base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), | 4864 | base_addr + ID_ADDRESS, readl(&fid->zfwctrl_addr), |
| 4903 | base_addr + readl(&fid->zfwctrl_addr)); | 4865 | base_addr + readl(&fid->zfwctrl_addr)); |
| 4904 | 4866 | ||
| 4867 | nchan = readl(&pt_zfwctrl->board_ctrl.n_channel); | ||
| 4905 | dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", | 4868 | dev_info(&pdev->dev, "Cyclades-Z FW loaded: version = %x, ports = %u\n", |
| 4906 | readl(&pt_zfwctrl->board_ctrl.fw_version), | 4869 | readl(&pt_zfwctrl->board_ctrl.fw_version), nchan); |
| 4907 | readl(&pt_zfwctrl->board_ctrl.n_channel)); | ||
| 4908 | 4870 | ||
| 4909 | if (readl(&pt_zfwctrl->board_ctrl.n_channel) == 0) { | 4871 | if (nchan == 0) { |
| 4910 | dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " | 4872 | dev_warn(&pdev->dev, "no Cyclades-Z ports were found. Please " |
| 4911 | "check the connection between the Z host card and the " | 4873 | "check the connection between the Z host card and the " |
| 4912 | "serial expanders.\n"); | 4874 | "serial expanders.\n"); |
| 4913 | 4875 | ||
| 4914 | if (Z_FPGA_LOADED(ctl_addr)) | 4876 | if (__cyz_fpga_loaded(ctl_addr)) |
| 4915 | plx_init(pdev, irq, ctl_addr); | 4877 | plx_init(pdev, irq, ctl_addr); |
| 4916 | 4878 | ||
| 4917 | dev_info(&pdev->dev, "Null number of ports detected. Board " | 4879 | dev_info(&pdev->dev, "Null number of ports detected. Board " |
| @@ -4932,9 +4894,7 @@ static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr, | |||
| 4932 | cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | | 4894 | cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) | |
| 4933 | 0x00030800UL); | 4895 | 0x00030800UL); |
| 4934 | 4896 | ||
| 4935 | plx_init(pdev, irq, ctl_addr); | 4897 | return nchan; |
| 4936 | |||
| 4937 | return 0; | ||
| 4938 | err_rel: | 4898 | err_rel: |
| 4939 | release_firmware(fw); | 4899 | release_firmware(fw); |
| 4940 | err: | 4900 | err: |
| @@ -4946,7 +4906,7 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
| 4946 | { | 4906 | { |
| 4947 | void __iomem *addr0 = NULL, *addr2 = NULL; | 4907 | void __iomem *addr0 = NULL, *addr2 = NULL; |
| 4948 | char *card_name = NULL; | 4908 | char *card_name = NULL; |
| 4949 | u32 mailbox; | 4909 | u32 uninitialized_var(mailbox); |
| 4950 | unsigned int device_id, nchan = 0, card_no, i; | 4910 | unsigned int device_id, nchan = 0, card_no, i; |
| 4951 | unsigned char plx_ver; | 4911 | unsigned char plx_ver; |
| 4952 | int retval, irq; | 4912 | int retval, irq; |
| @@ -5023,11 +4983,12 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
| 5023 | } | 4983 | } |
| 5024 | 4984 | ||
| 5025 | /* Disable interrupts on the PLX before resetting it */ | 4985 | /* Disable interrupts on the PLX before resetting it */ |
| 5026 | cy_writew(addr0 + 0x68, readw(addr0 + 0x68) & ~0x0900); | 4986 | cy_writew(&ctl_addr->intr_ctrl_stat, |
| 4987 | readw(&ctl_addr->intr_ctrl_stat) & ~0x0900); | ||
| 5027 | 4988 | ||
| 5028 | plx_init(pdev, irq, addr0); | 4989 | plx_init(pdev, irq, addr0); |
| 5029 | 4990 | ||
| 5030 | mailbox = (u32)readl(&ctl_addr->mail_box_0); | 4991 | mailbox = readl(&ctl_addr->mail_box_0); |
| 5031 | 4992 | ||
| 5032 | addr2 = ioremap_nocache(pci_resource_start(pdev, 2), | 4993 | addr2 = ioremap_nocache(pci_resource_start(pdev, 2), |
| 5033 | mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); | 4994 | mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin); |
| @@ -5038,12 +4999,8 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
| 5038 | 4999 | ||
| 5039 | if (mailbox == ZE_V1) { | 5000 | if (mailbox == ZE_V1) { |
| 5040 | card_name = "Cyclades-Ze"; | 5001 | card_name = "Cyclades-Ze"; |
| 5041 | |||
| 5042 | readl(&ctl_addr->mail_box_0); | ||
| 5043 | nchan = ZE_V1_NPORTS; | ||
| 5044 | } else { | 5002 | } else { |
| 5045 | card_name = "Cyclades-8Zo"; | 5003 | card_name = "Cyclades-8Zo"; |
| 5046 | |||
| 5047 | #ifdef CY_PCI_DEBUG | 5004 | #ifdef CY_PCI_DEBUG |
| 5048 | if (mailbox == ZO_V1) { | 5005 | if (mailbox == ZO_V1) { |
| 5049 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); | 5006 | cy_writel(&ctl_addr->loc_addr_base, WIN_CREG); |
| @@ -5065,15 +5022,12 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
| 5065 | */ | 5022 | */ |
| 5066 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) | 5023 | if ((mailbox == ZO_V1) || (mailbox == ZO_V2)) |
| 5067 | cy_writel(addr2 + ID_ADDRESS, 0L); | 5024 | cy_writel(addr2 + ID_ADDRESS, 0L); |
| 5068 | |||
| 5069 | retval = cyz_load_fw(pdev, addr2, addr0, irq); | ||
| 5070 | if (retval) | ||
| 5071 | goto err_unmap; | ||
| 5072 | /* This must be a Cyclades-8Zo/PCI. The extendable | ||
| 5073 | version will have a different device_id and will | ||
| 5074 | be allocated its maximum number of ports. */ | ||
| 5075 | nchan = 8; | ||
| 5076 | } | 5025 | } |
| 5026 | |||
| 5027 | retval = cyz_load_fw(pdev, addr2, addr0, irq); | ||
| 5028 | if (retval <= 0) | ||
| 5029 | goto err_unmap; | ||
| 5030 | nchan = retval; | ||
| 5077 | } | 5031 | } |
| 5078 | 5032 | ||
| 5079 | if ((cy_next_channel + nchan) > NR_PORTS) { | 5033 | if ((cy_next_channel + nchan) > NR_PORTS) { |
| @@ -5103,8 +5057,10 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
| 5103 | dev_err(&pdev->dev, "could not allocate IRQ\n"); | 5057 | dev_err(&pdev->dev, "could not allocate IRQ\n"); |
| 5104 | goto err_unmap; | 5058 | goto err_unmap; |
| 5105 | } | 5059 | } |
| 5106 | cy_card[card_no].num_chips = nchan / 4; | 5060 | cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP; |
| 5107 | } else { | 5061 | } else { |
| 5062 | cy_card[card_no].hw_ver = mailbox; | ||
| 5063 | cy_card[card_no].num_chips = (unsigned int)-1; | ||
| 5108 | #ifdef CONFIG_CYZ_INTR | 5064 | #ifdef CONFIG_CYZ_INTR |
| 5109 | /* allocate IRQ only if board has an IRQ */ | 5065 | /* allocate IRQ only if board has an IRQ */ |
| 5110 | if (irq != 0 && irq != 255) { | 5066 | if (irq != 0 && irq != 255) { |
| @@ -5117,15 +5073,15 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
| 5117 | } | 5073 | } |
| 5118 | } | 5074 | } |
| 5119 | #endif /* CONFIG_CYZ_INTR */ | 5075 | #endif /* CONFIG_CYZ_INTR */ |
| 5120 | cy_card[card_no].num_chips = (unsigned int)-1; | ||
| 5121 | } | 5076 | } |
| 5122 | 5077 | ||
| 5123 | /* set cy_card */ | 5078 | /* set cy_card */ |
| 5124 | cy_card[card_no].base_addr = addr2; | 5079 | cy_card[card_no].base_addr = addr2; |
| 5125 | cy_card[card_no].ctl_addr = addr0; | 5080 | cy_card[card_no].ctl_addr.p9050 = addr0; |
| 5126 | cy_card[card_no].irq = irq; | 5081 | cy_card[card_no].irq = irq; |
| 5127 | cy_card[card_no].bus_index = 1; | 5082 | cy_card[card_no].bus_index = 1; |
| 5128 | cy_card[card_no].first_line = cy_next_channel; | 5083 | cy_card[card_no].first_line = cy_next_channel; |
| 5084 | cy_card[card_no].nports = nchan; | ||
| 5129 | retval = cy_init_card(&cy_card[card_no]); | 5085 | retval = cy_init_card(&cy_card[card_no]); |
| 5130 | if (retval) | 5086 | if (retval) |
| 5131 | goto err_null; | 5087 | goto err_null; |
| @@ -5138,17 +5094,20 @@ static int __devinit cy_pci_probe(struct pci_dev *pdev, | |||
| 5138 | plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; | 5094 | plx_ver = readb(addr2 + CyPLX_VER) & 0x0f; |
| 5139 | switch (plx_ver) { | 5095 | switch (plx_ver) { |
| 5140 | case PLX_9050: | 5096 | case PLX_9050: |
| 5141 | |||
| 5142 | cy_writeb(addr0 + 0x4c, 0x43); | 5097 | cy_writeb(addr0 + 0x4c, 0x43); |
| 5143 | break; | 5098 | break; |
| 5144 | 5099 | ||
| 5145 | case PLX_9060: | 5100 | case PLX_9060: |
| 5146 | case PLX_9080: | 5101 | case PLX_9080: |
| 5147 | default: /* Old boards, use PLX_9060 */ | 5102 | default: /* Old boards, use PLX_9060 */ |
| 5148 | plx_init(pdev, irq, addr0); | 5103 | { |
| 5149 | cy_writew(addr0 + 0x68, readw(addr0 + 0x68) | 0x0900); | 5104 | struct RUNTIME_9060 __iomem *ctl_addr = addr0; |
| 5105 | plx_init(pdev, irq, ctl_addr); | ||
| 5106 | cy_writew(&ctl_addr->intr_ctrl_stat, | ||
| 5107 | readw(&ctl_addr->intr_ctrl_stat) | 0x0900); | ||
| 5150 | break; | 5108 | break; |
| 5151 | } | 5109 | } |
| 5110 | } | ||
| 5152 | } | 5111 | } |
| 5153 | 5112 | ||
| 5154 | dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " | 5113 | dev_info(&pdev->dev, "%s/PCI #%d found: %d channels starting from " |
| @@ -5179,22 +5138,23 @@ static void __devexit cy_pci_remove(struct pci_dev *pdev) | |||
| 5179 | unsigned int i; | 5138 | unsigned int i; |
| 5180 | 5139 | ||
| 5181 | /* non-Z with old PLX */ | 5140 | /* non-Z with old PLX */ |
| 5182 | if (!IS_CYC_Z(*cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == | 5141 | if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) == |
| 5183 | PLX_9050) | 5142 | PLX_9050) |
| 5184 | cy_writeb(cinfo->ctl_addr + 0x4c, 0); | 5143 | cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0); |
| 5185 | else | 5144 | else |
| 5186 | #ifndef CONFIG_CYZ_INTR | 5145 | #ifndef CONFIG_CYZ_INTR |
| 5187 | if (!IS_CYC_Z(*cinfo)) | 5146 | if (!cy_is_Z(cinfo)) |
| 5188 | #endif | 5147 | #endif |
| 5189 | cy_writew(cinfo->ctl_addr + 0x68, | 5148 | cy_writew(&cinfo->ctl_addr.p9060->intr_ctrl_stat, |
| 5190 | readw(cinfo->ctl_addr + 0x68) & ~0x0900); | 5149 | readw(&cinfo->ctl_addr.p9060->intr_ctrl_stat) & |
| 5150 | ~0x0900); | ||
| 5191 | 5151 | ||
| 5192 | iounmap(cinfo->base_addr); | 5152 | iounmap(cinfo->base_addr); |
| 5193 | if (cinfo->ctl_addr) | 5153 | if (cinfo->ctl_addr.p9050) |
| 5194 | iounmap(cinfo->ctl_addr); | 5154 | iounmap(cinfo->ctl_addr.p9050); |
| 5195 | if (cinfo->irq | 5155 | if (cinfo->irq |
| 5196 | #ifndef CONFIG_CYZ_INTR | 5156 | #ifndef CONFIG_CYZ_INTR |
| 5197 | && !IS_CYC_Z(*cinfo) | 5157 | && !cy_is_Z(cinfo) |
| 5198 | #endif /* CONFIG_CYZ_INTR */ | 5158 | #endif /* CONFIG_CYZ_INTR */ |
| 5199 | ) | 5159 | ) |
| 5200 | free_irq(cinfo->irq, cinfo); | 5160 | free_irq(cinfo->irq, cinfo); |
| @@ -5240,7 +5200,7 @@ static int cyclades_proc_show(struct seq_file *m, void *v) | |||
| 5240 | (cur_jifs - info->idle_stats.recv_idle)/ | 5200 | (cur_jifs - info->idle_stats.recv_idle)/ |
| 5241 | HZ, info->idle_stats.overruns, | 5201 | HZ, info->idle_stats.overruns, |
| 5242 | /* FIXME: double check locking */ | 5202 | /* FIXME: double check locking */ |
| 5243 | (long)info->port.tty->ldisc.ops->num); | 5203 | (long)info->port.tty->ldisc->ops->num); |
| 5244 | else | 5204 | else |
| 5245 | seq_printf(m, "%3d %8lu %10lu %8lu " | 5205 | seq_printf(m, "%3d %8lu %10lu %8lu " |
| 5246 | "%10lu %8lu %9lu %6ld\n", | 5206 | "%10lu %8lu %9lu %6ld\n", |
| @@ -5386,11 +5346,11 @@ static void __exit cy_cleanup_module(void) | |||
| 5386 | /* clear interrupt */ | 5346 | /* clear interrupt */ |
| 5387 | cy_writeb(card->base_addr + Cy_ClrIntr, 0); | 5347 | cy_writeb(card->base_addr + Cy_ClrIntr, 0); |
| 5388 | iounmap(card->base_addr); | 5348 | iounmap(card->base_addr); |
| 5389 | if (card->ctl_addr) | 5349 | if (card->ctl_addr.p9050) |
| 5390 | iounmap(card->ctl_addr); | 5350 | iounmap(card->ctl_addr.p9050); |
| 5391 | if (card->irq | 5351 | if (card->irq |
| 5392 | #ifndef CONFIG_CYZ_INTR | 5352 | #ifndef CONFIG_CYZ_INTR |
| 5393 | && !IS_CYC_Z(*card) | 5353 | && !cy_is_Z(card) |
| 5394 | #endif /* CONFIG_CYZ_INTR */ | 5354 | #endif /* CONFIG_CYZ_INTR */ |
| 5395 | ) | 5355 | ) |
| 5396 | free_irq(card->irq, card); | 5356 | free_irq(card->irq, card); |
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index af7c13ca9493..abef1f7d84fe 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c | |||
| @@ -745,7 +745,7 @@ static int epca_carrier_raised(struct tty_port *port) | |||
| 745 | return 0; | 745 | return 0; |
| 746 | } | 746 | } |
| 747 | 747 | ||
| 748 | static void epca_raise_dtr_rts(struct tty_port *port) | 748 | static void epca_dtr_rts(struct tty_port *port, int onoff) |
| 749 | { | 749 | { |
| 750 | } | 750 | } |
| 751 | 751 | ||
| @@ -925,7 +925,7 @@ static const struct tty_operations pc_ops = { | |||
| 925 | 925 | ||
| 926 | static const struct tty_port_operations epca_port_ops = { | 926 | static const struct tty_port_operations epca_port_ops = { |
| 927 | .carrier_raised = epca_carrier_raised, | 927 | .carrier_raised = epca_carrier_raised, |
| 928 | .raise_dtr_rts = epca_raise_dtr_rts, | 928 | .dtr_rts = epca_dtr_rts, |
| 929 | }; | 929 | }; |
| 930 | 930 | ||
| 931 | static int info_open(struct tty_struct *tty, struct file *filp) | 931 | static int info_open(struct tty_struct *tty, struct file *filp) |
| @@ -1518,7 +1518,7 @@ static void doevent(int crd) | |||
| 1518 | if (event & MODEMCHG_IND) { | 1518 | if (event & MODEMCHG_IND) { |
| 1519 | /* A modem signal change has been indicated */ | 1519 | /* A modem signal change has been indicated */ |
| 1520 | ch->imodem = mstat; | 1520 | ch->imodem = mstat; |
| 1521 | if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) { | 1521 | if (test_bit(ASYNCB_CHECK_CD, &ch->port.flags)) { |
| 1522 | /* We are now receiving dcd */ | 1522 | /* We are now receiving dcd */ |
| 1523 | if (mstat & ch->dcd) | 1523 | if (mstat & ch->dcd) |
| 1524 | wake_up_interruptible(&ch->port.open_wait); | 1524 | wake_up_interruptible(&ch->port.open_wait); |
| @@ -1765,9 +1765,9 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) | |||
| 1765 | * that the driver will wait on carrier detect. | 1765 | * that the driver will wait on carrier detect. |
| 1766 | */ | 1766 | */ |
| 1767 | if (ts->c_cflag & CLOCAL) | 1767 | if (ts->c_cflag & CLOCAL) |
| 1768 | clear_bit(ASYNC_CHECK_CD, &ch->port.flags); | 1768 | clear_bit(ASYNCB_CHECK_CD, &ch->port.flags); |
| 1769 | else | 1769 | else |
| 1770 | set_bit(ASYNC_CHECK_CD, &ch->port.flags); | 1770 | set_bit(ASYNCB_CHECK_CD, &ch->port.flags); |
| 1771 | mval = ch->m_dtr | ch->m_rts; | 1771 | mval = ch->m_dtr | ch->m_rts; |
| 1772 | } /* End CBAUD not detected */ | 1772 | } /* End CBAUD not detected */ |
| 1773 | iflag = termios2digi_i(ch, ts->c_iflag); | 1773 | iflag = termios2digi_i(ch, ts->c_iflag); |
| @@ -2114,8 +2114,8 @@ static int pc_ioctl(struct tty_struct *tty, struct file *file, | |||
| 2114 | tty_wait_until_sent(tty, 0); | 2114 | tty_wait_until_sent(tty, 0); |
| 2115 | } else { | 2115 | } else { |
| 2116 | /* ldisc lock already held in ioctl */ | 2116 | /* ldisc lock already held in ioctl */ |
| 2117 | if (tty->ldisc.ops->flush_buffer) | 2117 | if (tty->ldisc->ops->flush_buffer) |
| 2118 | tty->ldisc.ops->flush_buffer(tty); | 2118 | tty->ldisc->ops->flush_buffer(tty); |
| 2119 | } | 2119 | } |
| 2120 | unlock_kernel(); | 2120 | unlock_kernel(); |
| 2121 | /* Fall Thru */ | 2121 | /* Fall Thru */ |
| @@ -2244,7 +2244,8 @@ static void do_softint(struct work_struct *work) | |||
| 2244 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { | 2244 | if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { |
| 2245 | tty_hangup(tty); | 2245 | tty_hangup(tty); |
| 2246 | wake_up_interruptible(&ch->port.open_wait); | 2246 | wake_up_interruptible(&ch->port.open_wait); |
| 2247 | clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags); | 2247 | clear_bit(ASYNCB_NORMAL_ACTIVE, |
| 2248 | &ch->port.flags); | ||
| 2248 | } | 2249 | } |
| 2249 | } | 2250 | } |
| 2250 | tty_kref_put(tty); | 2251 | tty_kref_put(tty); |
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index 340ba4f9dc54..4a9f3492b921 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
| @@ -224,7 +224,7 @@ static void hpet_timer_set_irq(struct hpet_dev *devp) | |||
| 224 | break; | 224 | break; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | gsi = acpi_register_gsi(irq, ACPI_LEVEL_SENSITIVE, | 227 | gsi = acpi_register_gsi(NULL, irq, ACPI_LEVEL_SENSITIVE, |
| 228 | ACPI_ACTIVE_LOW); | 228 | ACPI_ACTIVE_LOW); |
| 229 | if (gsi > 0) | 229 | if (gsi > 0) |
| 230 | break; | 230 | break; |
| @@ -939,7 +939,7 @@ static acpi_status hpet_resources(struct acpi_resource *res, void *data) | |||
| 939 | irqp = &res->data.extended_irq; | 939 | irqp = &res->data.extended_irq; |
| 940 | 940 | ||
| 941 | for (i = 0; i < irqp->interrupt_count; i++) { | 941 | for (i = 0; i < irqp->interrupt_count; i++) { |
| 942 | irq = acpi_register_gsi(irqp->interrupts[i], | 942 | irq = acpi_register_gsi(NULL, irqp->interrupts[i], |
| 943 | irqp->triggering, irqp->polarity); | 943 | irqp->triggering, irqp->polarity); |
| 944 | if (irq < 0) | 944 | if (irq < 0) |
| 945 | return AE_ERROR; | 945 | return AE_ERROR; |
diff --git a/drivers/char/ip2/i2lib.c b/drivers/char/ip2/i2lib.c index 0061e18aff60..0d10b89218ed 100644 --- a/drivers/char/ip2/i2lib.c +++ b/drivers/char/ip2/i2lib.c | |||
| @@ -868,11 +868,11 @@ i2Input(i2ChanStrPtr pCh) | |||
| 868 | amountToMove = count; | 868 | amountToMove = count; |
| 869 | } | 869 | } |
| 870 | // Move the first block | 870 | // Move the first block |
| 871 | pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, | 871 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, |
| 872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); | 872 | &(pCh->Ibuf[stripIndex]), NULL, amountToMove ); |
| 873 | // If we needed to wrap, do the second data move | 873 | // If we needed to wrap, do the second data move |
| 874 | if (count > amountToMove) { | 874 | if (count > amountToMove) { |
| 875 | pCh->pTTY->ldisc.ops->receive_buf( pCh->pTTY, | 875 | pCh->pTTY->ldisc->ops->receive_buf( pCh->pTTY, |
| 876 | pCh->Ibuf, NULL, count - amountToMove ); | 876 | pCh->Ibuf, NULL, count - amountToMove ); |
| 877 | } | 877 | } |
| 878 | // Bump and wrap the stripIndex all at once by the amount of data read. This | 878 | // Bump and wrap the stripIndex all at once by the amount of data read. This |
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c index afd9247cf082..517271c762e6 100644 --- a/drivers/char/ip2/ip2main.c +++ b/drivers/char/ip2/ip2main.c | |||
| @@ -1315,8 +1315,8 @@ static inline void isig(int sig, struct tty_struct *tty, int flush) | |||
| 1315 | if (tty->pgrp) | 1315 | if (tty->pgrp) |
| 1316 | kill_pgrp(tty->pgrp, sig, 1); | 1316 | kill_pgrp(tty->pgrp, sig, 1); |
| 1317 | if (flush || !L_NOFLSH(tty)) { | 1317 | if (flush || !L_NOFLSH(tty)) { |
| 1318 | if ( tty->ldisc.ops->flush_buffer ) | 1318 | if ( tty->ldisc->ops->flush_buffer ) |
| 1319 | tty->ldisc.ops->flush_buffer(tty); | 1319 | tty->ldisc->ops->flush_buffer(tty); |
| 1320 | i2InputFlush( tty->driver_data ); | 1320 | i2InputFlush( tty->driver_data ); |
| 1321 | } | 1321 | } |
| 1322 | } | 1322 | } |
diff --git a/drivers/char/isicom.c b/drivers/char/isicom.c index a59eac584d16..4d745a89504f 100644 --- a/drivers/char/isicom.c +++ b/drivers/char/isicom.c | |||
| @@ -329,7 +329,7 @@ static inline void drop_rts(struct isi_port *port) | |||
| 329 | 329 | ||
| 330 | /* card->lock MUST NOT be held */ | 330 | /* card->lock MUST NOT be held */ |
| 331 | 331 | ||
| 332 | static void isicom_raise_dtr_rts(struct tty_port *port) | 332 | static void isicom_dtr_rts(struct tty_port *port, int on) |
| 333 | { | 333 | { |
| 334 | struct isi_port *ip = container_of(port, struct isi_port, port); | 334 | struct isi_port *ip = container_of(port, struct isi_port, port); |
| 335 | struct isi_board *card = ip->card; | 335 | struct isi_board *card = ip->card; |
| @@ -339,10 +339,17 @@ static void isicom_raise_dtr_rts(struct tty_port *port) | |||
| 339 | if (!lock_card(card)) | 339 | if (!lock_card(card)) |
| 340 | return; | 340 | return; |
| 341 | 341 | ||
| 342 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | 342 | if (on) { |
| 343 | outw(0x0f04, base); | 343 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); |
| 344 | InterruptTheCard(base); | 344 | outw(0x0f04, base); |
| 345 | ip->status |= (ISI_DTR | ISI_RTS); | 345 | InterruptTheCard(base); |
| 346 | ip->status |= (ISI_DTR | ISI_RTS); | ||
| 347 | } else { | ||
| 348 | outw(0x8000 | (channel << card->shift_count) | 0x02, base); | ||
| 349 | outw(0x0C04, base); | ||
| 350 | InterruptTheCard(base); | ||
| 351 | ip->status &= ~(ISI_DTR | ISI_RTS); | ||
| 352 | } | ||
| 346 | unlock_card(card); | 353 | unlock_card(card); |
| 347 | } | 354 | } |
| 348 | 355 | ||
| @@ -1339,7 +1346,7 @@ static const struct tty_operations isicom_ops = { | |||
| 1339 | 1346 | ||
| 1340 | static const struct tty_port_operations isicom_port_ops = { | 1347 | static const struct tty_port_operations isicom_port_ops = { |
| 1341 | .carrier_raised = isicom_carrier_raised, | 1348 | .carrier_raised = isicom_carrier_raised, |
| 1342 | .raise_dtr_rts = isicom_raise_dtr_rts, | 1349 | .dtr_rts = isicom_dtr_rts, |
| 1343 | }; | 1350 | }; |
| 1344 | 1351 | ||
| 1345 | static int __devinit reset_card(struct pci_dev *pdev, | 1352 | static int __devinit reset_card(struct pci_dev *pdev, |
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c index fff19f7e29d2..e18800c400b1 100644 --- a/drivers/char/istallion.c +++ b/drivers/char/istallion.c | |||
| @@ -1140,14 +1140,14 @@ static int stli_carrier_raised(struct tty_port *port) | |||
| 1140 | return (portp->sigs & TIOCM_CD) ? 1 : 0; | 1140 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
| 1141 | } | 1141 | } |
| 1142 | 1142 | ||
| 1143 | static void stli_raise_dtr_rts(struct tty_port *port) | 1143 | static void stli_dtr_rts(struct tty_port *port, int on) |
| 1144 | { | 1144 | { |
| 1145 | struct stliport *portp = container_of(port, struct stliport, port); | 1145 | struct stliport *portp = container_of(port, struct stliport, port); |
| 1146 | struct stlibrd *brdp = stli_brds[portp->brdnr]; | 1146 | struct stlibrd *brdp = stli_brds[portp->brdnr]; |
| 1147 | stli_mkasysigs(&portp->asig, 1, 1); | 1147 | stli_mkasysigs(&portp->asig, on, on); |
| 1148 | if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, | 1148 | if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig, |
| 1149 | sizeof(asysigs_t), 0) < 0) | 1149 | sizeof(asysigs_t), 0) < 0) |
| 1150 | printk(KERN_WARNING "istallion: dtr raise failed.\n"); | 1150 | printk(KERN_WARNING "istallion: dtr set failed.\n"); |
| 1151 | } | 1151 | } |
| 1152 | 1152 | ||
| 1153 | 1153 | ||
| @@ -4417,7 +4417,7 @@ static const struct tty_operations stli_ops = { | |||
| 4417 | 4417 | ||
| 4418 | static const struct tty_port_operations stli_port_ops = { | 4418 | static const struct tty_port_operations stli_port_ops = { |
| 4419 | .carrier_raised = stli_carrier_raised, | 4419 | .carrier_raised = stli_carrier_raised, |
| 4420 | .raise_dtr_rts = stli_raise_dtr_rts, | 4420 | .dtr_rts = stli_dtr_rts, |
| 4421 | }; | 4421 | }; |
| 4422 | 4422 | ||
| 4423 | /*****************************************************************************/ | 4423 | /*****************************************************************************/ |
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 8f05c38c2f06..f96d0bef855e 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
| @@ -694,6 +694,8 @@ static ssize_t read_zero(struct file * file, char __user * buf, | |||
| 694 | written += chunk - unwritten; | 694 | written += chunk - unwritten; |
| 695 | if (unwritten) | 695 | if (unwritten) |
| 696 | break; | 696 | break; |
| 697 | if (signal_pending(current)) | ||
| 698 | return written ? written : -ERESTARTSYS; | ||
| 697 | buf += chunk; | 699 | buf += chunk; |
| 698 | count -= chunk; | 700 | count -= chunk; |
| 699 | cond_resched(); | 701 | cond_resched(); |
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c index 4a4cab73d0be..65b6ff2442c6 100644 --- a/drivers/char/moxa.c +++ b/drivers/char/moxa.c | |||
| @@ -1184,6 +1184,11 @@ static int moxa_open(struct tty_struct *tty, struct file *filp) | |||
| 1184 | return -ENODEV; | 1184 | return -ENODEV; |
| 1185 | } | 1185 | } |
| 1186 | 1186 | ||
| 1187 | if (port % MAX_PORTS_PER_BOARD >= brd->numPorts) { | ||
| 1188 | mutex_unlock(&moxa_openlock); | ||
| 1189 | return -ENODEV; | ||
| 1190 | } | ||
| 1191 | |||
| 1187 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; | 1192 | ch = &brd->ports[port % MAX_PORTS_PER_BOARD]; |
| 1188 | ch->port.count++; | 1193 | ch->port.count++; |
| 1189 | tty->driver_data = ch; | 1194 | tty->driver_data = ch; |
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c index a420e8d437dd..9533f43a30bb 100644 --- a/drivers/char/mxser.c +++ b/drivers/char/mxser.c | |||
| @@ -547,14 +547,18 @@ static int mxser_carrier_raised(struct tty_port *port) | |||
| 547 | return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; | 547 | return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0; |
| 548 | } | 548 | } |
| 549 | 549 | ||
| 550 | static void mxser_raise_dtr_rts(struct tty_port *port) | 550 | static void mxser_dtr_rts(struct tty_port *port, int on) |
| 551 | { | 551 | { |
| 552 | struct mxser_port *mp = container_of(port, struct mxser_port, port); | 552 | struct mxser_port *mp = container_of(port, struct mxser_port, port); |
| 553 | unsigned long flags; | 553 | unsigned long flags; |
| 554 | 554 | ||
| 555 | spin_lock_irqsave(&mp->slock, flags); | 555 | spin_lock_irqsave(&mp->slock, flags); |
| 556 | outb(inb(mp->ioaddr + UART_MCR) | | 556 | if (on) |
| 557 | UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); | 557 | outb(inb(mp->ioaddr + UART_MCR) | |
| 558 | UART_MCR_DTR | UART_MCR_RTS, mp->ioaddr + UART_MCR); | ||
| 559 | else | ||
| 560 | outb(inb(mp->ioaddr + UART_MCR)&~(UART_MCR_DTR | UART_MCR_RTS), | ||
| 561 | mp->ioaddr + UART_MCR); | ||
| 558 | spin_unlock_irqrestore(&mp->slock, flags); | 562 | spin_unlock_irqrestore(&mp->slock, flags); |
| 559 | } | 563 | } |
| 560 | 564 | ||
| @@ -2356,7 +2360,7 @@ static const struct tty_operations mxser_ops = { | |||
| 2356 | 2360 | ||
| 2357 | struct tty_port_operations mxser_port_ops = { | 2361 | struct tty_port_operations mxser_port_ops = { |
| 2358 | .carrier_raised = mxser_carrier_raised, | 2362 | .carrier_raised = mxser_carrier_raised, |
| 2359 | .raise_dtr_rts = mxser_raise_dtr_rts, | 2363 | .dtr_rts = mxser_dtr_rts, |
| 2360 | }; | 2364 | }; |
| 2361 | 2365 | ||
| 2362 | /* | 2366 | /* |
| @@ -2711,7 +2715,7 @@ static int __init mxser_module_init(void) | |||
| 2711 | continue; | 2715 | continue; |
| 2712 | 2716 | ||
| 2713 | brd = &mxser_boards[m]; | 2717 | brd = &mxser_boards[m]; |
| 2714 | retval = mxser_get_ISA_conf(!ioaddr[b], brd); | 2718 | retval = mxser_get_ISA_conf(ioaddr[b], brd); |
| 2715 | if (retval <= 0) { | 2719 | if (retval <= 0) { |
| 2716 | brd->info = NULL; | 2720 | brd->info = NULL; |
| 2717 | continue; | 2721 | continue; |
diff --git a/drivers/char/n_hdlc.c b/drivers/char/n_hdlc.c index bacb3e2872ae..461ece591a5b 100644 --- a/drivers/char/n_hdlc.c +++ b/drivers/char/n_hdlc.c | |||
| @@ -342,8 +342,8 @@ static int n_hdlc_tty_open (struct tty_struct *tty) | |||
| 342 | #endif | 342 | #endif |
| 343 | 343 | ||
| 344 | /* Flush any pending characters in the driver and discipline. */ | 344 | /* Flush any pending characters in the driver and discipline. */ |
| 345 | if (tty->ldisc.ops->flush_buffer) | 345 | if (tty->ldisc->ops->flush_buffer) |
| 346 | tty->ldisc.ops->flush_buffer(tty); | 346 | tty->ldisc->ops->flush_buffer(tty); |
| 347 | 347 | ||
| 348 | tty_driver_flush_buffer(tty); | 348 | tty_driver_flush_buffer(tty); |
| 349 | 349 | ||
diff --git a/drivers/char/n_tty.c b/drivers/char/n_tty.c index f6f0e4ec2b51..94a5d5020abc 100644 --- a/drivers/char/n_tty.c +++ b/drivers/char/n_tty.c | |||
| @@ -73,24 +73,6 @@ | |||
| 73 | #define ECHO_OP_SET_CANON_COL 0x81 | 73 | #define ECHO_OP_SET_CANON_COL 0x81 |
| 74 | #define ECHO_OP_ERASE_TAB 0x82 | 74 | #define ECHO_OP_ERASE_TAB 0x82 |
| 75 | 75 | ||
| 76 | static inline unsigned char *alloc_buf(void) | ||
| 77 | { | ||
| 78 | gfp_t prio = in_interrupt() ? GFP_ATOMIC : GFP_KERNEL; | ||
| 79 | |||
| 80 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | ||
| 81 | return kmalloc(N_TTY_BUF_SIZE, prio); | ||
| 82 | else | ||
| 83 | return (unsigned char *)__get_free_page(prio); | ||
| 84 | } | ||
| 85 | |||
| 86 | static inline void free_buf(unsigned char *buf) | ||
| 87 | { | ||
| 88 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | ||
| 89 | kfree(buf); | ||
| 90 | else | ||
| 91 | free_page((unsigned long) buf); | ||
| 92 | } | ||
| 93 | |||
| 94 | static inline int tty_put_user(struct tty_struct *tty, unsigned char x, | 76 | static inline int tty_put_user(struct tty_struct *tty, unsigned char x, |
| 95 | unsigned char __user *ptr) | 77 | unsigned char __user *ptr) |
| 96 | { | 78 | { |
| @@ -1558,11 +1540,11 @@ static void n_tty_close(struct tty_struct *tty) | |||
| 1558 | { | 1540 | { |
| 1559 | n_tty_flush_buffer(tty); | 1541 | n_tty_flush_buffer(tty); |
| 1560 | if (tty->read_buf) { | 1542 | if (tty->read_buf) { |
| 1561 | free_buf(tty->read_buf); | 1543 | kfree(tty->read_buf); |
| 1562 | tty->read_buf = NULL; | 1544 | tty->read_buf = NULL; |
| 1563 | } | 1545 | } |
| 1564 | if (tty->echo_buf) { | 1546 | if (tty->echo_buf) { |
| 1565 | free_buf(tty->echo_buf); | 1547 | kfree(tty->echo_buf); |
| 1566 | tty->echo_buf = NULL; | 1548 | tty->echo_buf = NULL; |
| 1567 | } | 1549 | } |
| 1568 | } | 1550 | } |
| @@ -1584,17 +1566,16 @@ static int n_tty_open(struct tty_struct *tty) | |||
| 1584 | 1566 | ||
| 1585 | /* These are ugly. Currently a malloc failure here can panic */ | 1567 | /* These are ugly. Currently a malloc failure here can panic */ |
| 1586 | if (!tty->read_buf) { | 1568 | if (!tty->read_buf) { |
| 1587 | tty->read_buf = alloc_buf(); | 1569 | tty->read_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); |
| 1588 | if (!tty->read_buf) | 1570 | if (!tty->read_buf) |
| 1589 | return -ENOMEM; | 1571 | return -ENOMEM; |
| 1590 | } | 1572 | } |
| 1591 | if (!tty->echo_buf) { | 1573 | if (!tty->echo_buf) { |
| 1592 | tty->echo_buf = alloc_buf(); | 1574 | tty->echo_buf = kzalloc(N_TTY_BUF_SIZE, GFP_KERNEL); |
| 1575 | |||
| 1593 | if (!tty->echo_buf) | 1576 | if (!tty->echo_buf) |
| 1594 | return -ENOMEM; | 1577 | return -ENOMEM; |
| 1595 | } | 1578 | } |
| 1596 | memset(tty->read_buf, 0, N_TTY_BUF_SIZE); | ||
| 1597 | memset(tty->echo_buf, 0, N_TTY_BUF_SIZE); | ||
| 1598 | reset_buffer_flags(tty); | 1579 | reset_buffer_flags(tty); |
| 1599 | tty->column = 0; | 1580 | tty->column = 0; |
| 1600 | n_tty_set_termios(tty, NULL); | 1581 | n_tty_set_termios(tty, NULL); |
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c index 19d79fc54461..77b364889224 100644 --- a/drivers/char/pcmcia/synclink_cs.c +++ b/drivers/char/pcmcia/synclink_cs.c | |||
| @@ -383,7 +383,7 @@ static void async_mode(MGSLPC_INFO *info); | |||
| 383 | static void tx_timeout(unsigned long context); | 383 | static void tx_timeout(unsigned long context); |
| 384 | 384 | ||
| 385 | static int carrier_raised(struct tty_port *port); | 385 | static int carrier_raised(struct tty_port *port); |
| 386 | static void raise_dtr_rts(struct tty_port *port); | 386 | static void dtr_rts(struct tty_port *port, int onoff); |
| 387 | 387 | ||
| 388 | #if SYNCLINK_GENERIC_HDLC | 388 | #if SYNCLINK_GENERIC_HDLC |
| 389 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) | 389 | #define dev_to_port(D) (dev_to_hdlc(D)->priv) |
| @@ -513,7 +513,7 @@ static void ldisc_receive_buf(struct tty_struct *tty, | |||
| 513 | 513 | ||
| 514 | static const struct tty_port_operations mgslpc_port_ops = { | 514 | static const struct tty_port_operations mgslpc_port_ops = { |
| 515 | .carrier_raised = carrier_raised, | 515 | .carrier_raised = carrier_raised, |
| 516 | .raise_dtr_rts = raise_dtr_rts | 516 | .dtr_rts = dtr_rts |
| 517 | }; | 517 | }; |
| 518 | 518 | ||
| 519 | static int mgslpc_probe(struct pcmcia_device *link) | 519 | static int mgslpc_probe(struct pcmcia_device *link) |
| @@ -2528,13 +2528,16 @@ static int carrier_raised(struct tty_port *port) | |||
| 2528 | return 0; | 2528 | return 0; |
| 2529 | } | 2529 | } |
| 2530 | 2530 | ||
| 2531 | static void raise_dtr_rts(struct tty_port *port) | 2531 | static void dtr_rts(struct tty_port *port, int onoff) |
| 2532 | { | 2532 | { |
| 2533 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); | 2533 | MGSLPC_INFO *info = container_of(port, MGSLPC_INFO, port); |
| 2534 | unsigned long flags; | 2534 | unsigned long flags; |
| 2535 | 2535 | ||
| 2536 | spin_lock_irqsave(&info->lock,flags); | 2536 | spin_lock_irqsave(&info->lock,flags); |
| 2537 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 2537 | if (onoff) |
| 2538 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
| 2539 | else | ||
| 2540 | info->serial_signals &= ~SerialSignal_RTS + SerialSignal_DTR; | ||
| 2538 | set_signals(info); | 2541 | set_signals(info); |
| 2539 | spin_unlock_irqrestore(&info->lock,flags); | 2542 | spin_unlock_irqrestore(&info->lock,flags); |
| 2540 | } | 2543 | } |
diff --git a/drivers/char/pty.c b/drivers/char/pty.c index 31038a0052a2..5acd29e6e043 100644 --- a/drivers/char/pty.c +++ b/drivers/char/pty.c | |||
| @@ -30,7 +30,6 @@ | |||
| 30 | 30 | ||
| 31 | #include <asm/system.h> | 31 | #include <asm/system.h> |
| 32 | 32 | ||
| 33 | /* These are global because they are accessed in tty_io.c */ | ||
| 34 | #ifdef CONFIG_UNIX98_PTYS | 33 | #ifdef CONFIG_UNIX98_PTYS |
| 35 | static struct tty_driver *ptm_driver; | 34 | static struct tty_driver *ptm_driver; |
| 36 | static struct tty_driver *pts_driver; | 35 | static struct tty_driver *pts_driver; |
| @@ -111,7 +110,7 @@ static int pty_write(struct tty_struct *tty, const unsigned char *buf, | |||
| 111 | c = to->receive_room; | 110 | c = to->receive_room; |
| 112 | if (c > count) | 111 | if (c > count) |
| 113 | c = count; | 112 | c = count; |
| 114 | to->ldisc.ops->receive_buf(to, buf, NULL, c); | 113 | to->ldisc->ops->receive_buf(to, buf, NULL, c); |
| 115 | 114 | ||
| 116 | return c; | 115 | return c; |
| 117 | } | 116 | } |
| @@ -149,11 +148,11 @@ static int pty_chars_in_buffer(struct tty_struct *tty) | |||
| 149 | int count; | 148 | int count; |
| 150 | 149 | ||
| 151 | /* We should get the line discipline lock for "tty->link" */ | 150 | /* We should get the line discipline lock for "tty->link" */ |
| 152 | if (!to || !to->ldisc.ops->chars_in_buffer) | 151 | if (!to || !to->ldisc->ops->chars_in_buffer) |
| 153 | return 0; | 152 | return 0; |
| 154 | 153 | ||
| 155 | /* The ldisc must report 0 if no characters available to be read */ | 154 | /* The ldisc must report 0 if no characters available to be read */ |
| 156 | count = to->ldisc.ops->chars_in_buffer(to); | 155 | count = to->ldisc->ops->chars_in_buffer(to); |
| 157 | 156 | ||
| 158 | if (tty->driver->subtype == PTY_TYPE_SLAVE) | 157 | if (tty->driver->subtype == PTY_TYPE_SLAVE) |
| 159 | return count; | 158 | return count; |
| @@ -187,8 +186,8 @@ static void pty_flush_buffer(struct tty_struct *tty) | |||
| 187 | if (!to) | 186 | if (!to) |
| 188 | return; | 187 | return; |
| 189 | 188 | ||
| 190 | if (to->ldisc.ops->flush_buffer) | 189 | if (to->ldisc->ops->flush_buffer) |
| 191 | to->ldisc.ops->flush_buffer(to); | 190 | to->ldisc->ops->flush_buffer(to); |
| 192 | 191 | ||
| 193 | if (to->packet) { | 192 | if (to->packet) { |
| 194 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 193 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
diff --git a/drivers/char/raw.c b/drivers/char/raw.c index 20d90e6a6e50..db32f0e4c7dd 100644 --- a/drivers/char/raw.c +++ b/drivers/char/raw.c | |||
| @@ -71,7 +71,7 @@ static int raw_open(struct inode *inode, struct file *filp) | |||
| 71 | err = bd_claim(bdev, raw_open); | 71 | err = bd_claim(bdev, raw_open); |
| 72 | if (err) | 72 | if (err) |
| 73 | goto out1; | 73 | goto out1; |
| 74 | err = set_blocksize(bdev, bdev_hardsect_size(bdev)); | 74 | err = set_blocksize(bdev, bdev_logical_block_size(bdev)); |
| 75 | if (err) | 75 | if (err) |
| 76 | goto out2; | 76 | goto out2; |
| 77 | filp->f_flags |= O_DIRECT; | 77 | filp->f_flags |= O_DIRECT; |
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c index f59fc5cea067..63d5b628477a 100644 --- a/drivers/char/rocket.c +++ b/drivers/char/rocket.c | |||
| @@ -872,11 +872,16 @@ static int carrier_raised(struct tty_port *port) | |||
| 872 | return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; | 872 | return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0; |
| 873 | } | 873 | } |
| 874 | 874 | ||
| 875 | static void raise_dtr_rts(struct tty_port *port) | 875 | static void dtr_rts(struct tty_port *port, int on) |
| 876 | { | 876 | { |
| 877 | struct r_port *info = container_of(port, struct r_port, port); | 877 | struct r_port *info = container_of(port, struct r_port, port); |
| 878 | sSetDTR(&info->channel); | 878 | if (on) { |
| 879 | sSetRTS(&info->channel); | 879 | sSetDTR(&info->channel); |
| 880 | sSetRTS(&info->channel); | ||
| 881 | } else { | ||
| 882 | sClrDTR(&info->channel); | ||
| 883 | sClrRTS(&info->channel); | ||
| 884 | } | ||
| 880 | } | 885 | } |
| 881 | 886 | ||
| 882 | /* | 887 | /* |
| @@ -934,7 +939,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
| 934 | /* | 939 | /* |
| 935 | * Info->count is now 1; so it's safe to sleep now. | 940 | * Info->count is now 1; so it's safe to sleep now. |
| 936 | */ | 941 | */ |
| 937 | if (!test_bit(ASYNC_INITIALIZED, &port->flags)) { | 942 | if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) { |
| 938 | cp = &info->channel; | 943 | cp = &info->channel; |
| 939 | sSetRxTrigger(cp, TRIG_1); | 944 | sSetRxTrigger(cp, TRIG_1); |
| 940 | if (sGetChanStatus(cp) & CD_ACT) | 945 | if (sGetChanStatus(cp) & CD_ACT) |
| @@ -958,7 +963,7 @@ static int rp_open(struct tty_struct *tty, struct file *filp) | |||
| 958 | sEnRxFIFO(cp); | 963 | sEnRxFIFO(cp); |
| 959 | sEnTransmit(cp); | 964 | sEnTransmit(cp); |
| 960 | 965 | ||
| 961 | set_bit(ASYNC_INITIALIZED, &info->port.flags); | 966 | set_bit(ASYNCB_INITIALIZED, &info->port.flags); |
| 962 | 967 | ||
| 963 | /* | 968 | /* |
| 964 | * Set up the tty->alt_speed kludge | 969 | * Set up the tty->alt_speed kludge |
| @@ -1641,7 +1646,7 @@ static int rp_write(struct tty_struct *tty, | |||
| 1641 | /* Write remaining data into the port's xmit_buf */ | 1646 | /* Write remaining data into the port's xmit_buf */ |
| 1642 | while (1) { | 1647 | while (1) { |
| 1643 | /* Hung up ? */ | 1648 | /* Hung up ? */ |
| 1644 | if (!test_bit(ASYNC_NORMAL_ACTIVE, &info->port.flags)) | 1649 | if (!test_bit(ASYNCB_NORMAL_ACTIVE, &info->port.flags)) |
| 1645 | goto end; | 1650 | goto end; |
| 1646 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); | 1651 | c = min(count, XMIT_BUF_SIZE - info->xmit_cnt - 1); |
| 1647 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); | 1652 | c = min(c, XMIT_BUF_SIZE - info->xmit_head); |
| @@ -2250,7 +2255,7 @@ static const struct tty_operations rocket_ops = { | |||
| 2250 | 2255 | ||
| 2251 | static const struct tty_port_operations rocket_port_ops = { | 2256 | static const struct tty_port_operations rocket_port_ops = { |
| 2252 | .carrier_raised = carrier_raised, | 2257 | .carrier_raised = carrier_raised, |
| 2253 | .raise_dtr_rts = raise_dtr_rts, | 2258 | .dtr_rts = dtr_rts, |
| 2254 | }; | 2259 | }; |
| 2255 | 2260 | ||
| 2256 | /* | 2261 | /* |
diff --git a/drivers/char/selection.c b/drivers/char/selection.c index cb8ca5698963..f97b9e848064 100644 --- a/drivers/char/selection.c +++ b/drivers/char/selection.c | |||
| @@ -327,7 +327,7 @@ int paste_selection(struct tty_struct *tty) | |||
| 327 | } | 327 | } |
| 328 | count = sel_buffer_lth - pasted; | 328 | count = sel_buffer_lth - pasted; |
| 329 | count = min(count, tty->receive_room); | 329 | count = min(count, tty->receive_room); |
| 330 | tty->ldisc.ops->receive_buf(tty, sel_buffer + pasted, | 330 | tty->ldisc->ops->receive_buf(tty, sel_buffer + pasted, |
| 331 | NULL, count); | 331 | NULL, count); |
| 332 | pasted += count; | 332 | pasted += count; |
| 333 | } | 333 | } |
diff --git a/drivers/char/stallion.c b/drivers/char/stallion.c index 2ad813a801dc..53e504f41b20 100644 --- a/drivers/char/stallion.c +++ b/drivers/char/stallion.c | |||
| @@ -772,11 +772,11 @@ static int stl_carrier_raised(struct tty_port *port) | |||
| 772 | return (portp->sigs & TIOCM_CD) ? 1 : 0; | 772 | return (portp->sigs & TIOCM_CD) ? 1 : 0; |
| 773 | } | 773 | } |
| 774 | 774 | ||
| 775 | static void stl_raise_dtr_rts(struct tty_port *port) | 775 | static void stl_dtr_rts(struct tty_port *port, int on) |
| 776 | { | 776 | { |
| 777 | struct stlport *portp = container_of(port, struct stlport, port); | 777 | struct stlport *portp = container_of(port, struct stlport, port); |
| 778 | /* Takes brd_lock internally */ | 778 | /* Takes brd_lock internally */ |
| 779 | stl_setsignals(portp, 1, 1); | 779 | stl_setsignals(portp, on, on); |
| 780 | } | 780 | } |
| 781 | 781 | ||
| 782 | /*****************************************************************************/ | 782 | /*****************************************************************************/ |
| @@ -2547,7 +2547,7 @@ static const struct tty_operations stl_ops = { | |||
| 2547 | 2547 | ||
| 2548 | static const struct tty_port_operations stl_port_ops = { | 2548 | static const struct tty_port_operations stl_port_ops = { |
| 2549 | .carrier_raised = stl_carrier_raised, | 2549 | .carrier_raised = stl_carrier_raised, |
| 2550 | .raise_dtr_rts = stl_raise_dtr_rts, | 2550 | .dtr_rts = stl_dtr_rts, |
| 2551 | }; | 2551 | }; |
| 2552 | 2552 | ||
| 2553 | /*****************************************************************************/ | 2553 | /*****************************************************************************/ |
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c index afd0b26ca056..afded3a2379c 100644 --- a/drivers/char/synclink.c +++ b/drivers/char/synclink.c | |||
| @@ -3247,13 +3247,16 @@ static int carrier_raised(struct tty_port *port) | |||
| 3247 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; | 3247 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; |
| 3248 | } | 3248 | } |
| 3249 | 3249 | ||
| 3250 | static void raise_dtr_rts(struct tty_port *port) | 3250 | static void dtr_rts(struct tty_port *port, int on) |
| 3251 | { | 3251 | { |
| 3252 | struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); | 3252 | struct mgsl_struct *info = container_of(port, struct mgsl_struct, port); |
| 3253 | unsigned long flags; | 3253 | unsigned long flags; |
| 3254 | 3254 | ||
| 3255 | spin_lock_irqsave(&info->irq_spinlock,flags); | 3255 | spin_lock_irqsave(&info->irq_spinlock,flags); |
| 3256 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 3256 | if (on) |
| 3257 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
| 3258 | else | ||
| 3259 | info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
| 3257 | usc_set_serial_signals(info); | 3260 | usc_set_serial_signals(info); |
| 3258 | spin_unlock_irqrestore(&info->irq_spinlock,flags); | 3261 | spin_unlock_irqrestore(&info->irq_spinlock,flags); |
| 3259 | } | 3262 | } |
| @@ -4258,7 +4261,7 @@ static void mgsl_add_device( struct mgsl_struct *info ) | |||
| 4258 | 4261 | ||
| 4259 | static const struct tty_port_operations mgsl_port_ops = { | 4262 | static const struct tty_port_operations mgsl_port_ops = { |
| 4260 | .carrier_raised = carrier_raised, | 4263 | .carrier_raised = carrier_raised, |
| 4261 | .raise_dtr_rts = raise_dtr_rts, | 4264 | .dtr_rts = dtr_rts, |
| 4262 | }; | 4265 | }; |
| 4263 | 4266 | ||
| 4264 | 4267 | ||
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c index 5e256494686a..1386625fc4ca 100644 --- a/drivers/char/synclink_gt.c +++ b/drivers/char/synclink_gt.c | |||
| @@ -214,6 +214,7 @@ struct slgt_desc | |||
| 214 | #define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) | 214 | #define set_desc_next(a,b) (a).next = cpu_to_le32((unsigned int)(b)) |
| 215 | #define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) | 215 | #define set_desc_count(a,b)(a).count = cpu_to_le16((unsigned short)(b)) |
| 216 | #define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) | 216 | #define set_desc_eof(a,b) (a).status = cpu_to_le16((b) ? (le16_to_cpu((a).status) | BIT0) : (le16_to_cpu((a).status) & ~BIT0)) |
| 217 | #define set_desc_status(a, b) (a).status = cpu_to_le16((unsigned short)(b)) | ||
| 217 | #define desc_count(a) (le16_to_cpu((a).count)) | 218 | #define desc_count(a) (le16_to_cpu((a).count)) |
| 218 | #define desc_status(a) (le16_to_cpu((a).status)) | 219 | #define desc_status(a) (le16_to_cpu((a).status)) |
| 219 | #define desc_complete(a) (le16_to_cpu((a).status) & BIT15) | 220 | #define desc_complete(a) (le16_to_cpu((a).status) & BIT15) |
| @@ -297,6 +298,7 @@ struct slgt_info { | |||
| 297 | u32 max_frame_size; /* as set by device config */ | 298 | u32 max_frame_size; /* as set by device config */ |
| 298 | 299 | ||
| 299 | unsigned int rbuf_fill_level; | 300 | unsigned int rbuf_fill_level; |
| 301 | unsigned int rx_pio; | ||
| 300 | unsigned int if_mode; | 302 | unsigned int if_mode; |
| 301 | unsigned int base_clock; | 303 | unsigned int base_clock; |
| 302 | 304 | ||
| @@ -331,6 +333,8 @@ struct slgt_info { | |||
| 331 | struct slgt_desc *rbufs; | 333 | struct slgt_desc *rbufs; |
| 332 | unsigned int rbuf_current; | 334 | unsigned int rbuf_current; |
| 333 | unsigned int rbuf_index; | 335 | unsigned int rbuf_index; |
| 336 | unsigned int rbuf_fill_index; | ||
| 337 | unsigned short rbuf_fill_count; | ||
| 334 | 338 | ||
| 335 | unsigned int tbuf_count; | 339 | unsigned int tbuf_count; |
| 336 | struct slgt_desc *tbufs; | 340 | struct slgt_desc *tbufs; |
| @@ -2110,6 +2114,40 @@ static void ri_change(struct slgt_info *info, unsigned short status) | |||
| 2110 | info->pending_bh |= BH_STATUS; | 2114 | info->pending_bh |= BH_STATUS; |
| 2111 | } | 2115 | } |
| 2112 | 2116 | ||
| 2117 | static void isr_rxdata(struct slgt_info *info) | ||
| 2118 | { | ||
| 2119 | unsigned int count = info->rbuf_fill_count; | ||
| 2120 | unsigned int i = info->rbuf_fill_index; | ||
| 2121 | unsigned short reg; | ||
| 2122 | |||
| 2123 | while (rd_reg16(info, SSR) & IRQ_RXDATA) { | ||
| 2124 | reg = rd_reg16(info, RDR); | ||
| 2125 | DBGISR(("isr_rxdata %s RDR=%04X\n", info->device_name, reg)); | ||
| 2126 | if (desc_complete(info->rbufs[i])) { | ||
| 2127 | /* all buffers full */ | ||
| 2128 | rx_stop(info); | ||
| 2129 | info->rx_restart = 1; | ||
| 2130 | continue; | ||
| 2131 | } | ||
| 2132 | info->rbufs[i].buf[count++] = (unsigned char)reg; | ||
| 2133 | /* async mode saves status byte to buffer for each data byte */ | ||
| 2134 | if (info->params.mode == MGSL_MODE_ASYNC) | ||
| 2135 | info->rbufs[i].buf[count++] = (unsigned char)(reg >> 8); | ||
| 2136 | if (count == info->rbuf_fill_level || (reg & BIT10)) { | ||
| 2137 | /* buffer full or end of frame */ | ||
| 2138 | set_desc_count(info->rbufs[i], count); | ||
| 2139 | set_desc_status(info->rbufs[i], BIT15 | (reg >> 8)); | ||
| 2140 | info->rbuf_fill_count = count = 0; | ||
| 2141 | if (++i == info->rbuf_count) | ||
| 2142 | i = 0; | ||
| 2143 | info->pending_bh |= BH_RECEIVE; | ||
| 2144 | } | ||
| 2145 | } | ||
| 2146 | |||
| 2147 | info->rbuf_fill_index = i; | ||
| 2148 | info->rbuf_fill_count = count; | ||
| 2149 | } | ||
| 2150 | |||
| 2113 | static void isr_serial(struct slgt_info *info) | 2151 | static void isr_serial(struct slgt_info *info) |
| 2114 | { | 2152 | { |
| 2115 | unsigned short status = rd_reg16(info, SSR); | 2153 | unsigned short status = rd_reg16(info, SSR); |
| @@ -2125,6 +2163,8 @@ static void isr_serial(struct slgt_info *info) | |||
| 2125 | if (info->tx_count) | 2163 | if (info->tx_count) |
| 2126 | isr_txeom(info, status); | 2164 | isr_txeom(info, status); |
| 2127 | } | 2165 | } |
| 2166 | if (info->rx_pio && (status & IRQ_RXDATA)) | ||
| 2167 | isr_rxdata(info); | ||
| 2128 | if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { | 2168 | if ((status & IRQ_RXBREAK) && (status & RXBREAK)) { |
| 2129 | info->icount.brk++; | 2169 | info->icount.brk++; |
| 2130 | /* process break detection if tty control allows */ | 2170 | /* process break detection if tty control allows */ |
| @@ -2141,7 +2181,8 @@ static void isr_serial(struct slgt_info *info) | |||
| 2141 | } else { | 2181 | } else { |
| 2142 | if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) | 2182 | if (status & (IRQ_TXIDLE + IRQ_TXUNDER)) |
| 2143 | isr_txeom(info, status); | 2183 | isr_txeom(info, status); |
| 2144 | 2184 | if (info->rx_pio && (status & IRQ_RXDATA)) | |
| 2185 | isr_rxdata(info); | ||
| 2145 | if (status & IRQ_RXIDLE) { | 2186 | if (status & IRQ_RXIDLE) { |
| 2146 | if (status & RXIDLE) | 2187 | if (status & RXIDLE) |
| 2147 | info->icount.rxidle++; | 2188 | info->icount.rxidle++; |
| @@ -2642,6 +2683,10 @@ static int rx_enable(struct slgt_info *info, int enable) | |||
| 2642 | return -EINVAL; | 2683 | return -EINVAL; |
| 2643 | } | 2684 | } |
| 2644 | info->rbuf_fill_level = rbuf_fill_level; | 2685 | info->rbuf_fill_level = rbuf_fill_level; |
| 2686 | if (rbuf_fill_level < 128) | ||
| 2687 | info->rx_pio = 1; /* PIO mode */ | ||
| 2688 | else | ||
| 2689 | info->rx_pio = 0; /* DMA mode */ | ||
| 2645 | rx_stop(info); /* restart receiver to use new fill level */ | 2690 | rx_stop(info); /* restart receiver to use new fill level */ |
| 2646 | } | 2691 | } |
| 2647 | 2692 | ||
| @@ -3099,13 +3144,16 @@ static int carrier_raised(struct tty_port *port) | |||
| 3099 | return (info->signals & SerialSignal_DCD) ? 1 : 0; | 3144 | return (info->signals & SerialSignal_DCD) ? 1 : 0; |
| 3100 | } | 3145 | } |
| 3101 | 3146 | ||
| 3102 | static void raise_dtr_rts(struct tty_port *port) | 3147 | static void dtr_rts(struct tty_port *port, int on) |
| 3103 | { | 3148 | { |
| 3104 | unsigned long flags; | 3149 | unsigned long flags; |
| 3105 | struct slgt_info *info = container_of(port, struct slgt_info, port); | 3150 | struct slgt_info *info = container_of(port, struct slgt_info, port); |
| 3106 | 3151 | ||
| 3107 | spin_lock_irqsave(&info->lock,flags); | 3152 | spin_lock_irqsave(&info->lock,flags); |
| 3108 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | 3153 | if (on) |
| 3154 | info->signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
| 3155 | else | ||
| 3156 | info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
| 3109 | set_signals(info); | 3157 | set_signals(info); |
| 3110 | spin_unlock_irqrestore(&info->lock,flags); | 3158 | spin_unlock_irqrestore(&info->lock,flags); |
| 3111 | } | 3159 | } |
| @@ -3419,7 +3467,7 @@ static void add_device(struct slgt_info *info) | |||
| 3419 | 3467 | ||
| 3420 | static const struct tty_port_operations slgt_port_ops = { | 3468 | static const struct tty_port_operations slgt_port_ops = { |
| 3421 | .carrier_raised = carrier_raised, | 3469 | .carrier_raised = carrier_raised, |
| 3422 | .raise_dtr_rts = raise_dtr_rts, | 3470 | .dtr_rts = dtr_rts, |
| 3423 | }; | 3471 | }; |
| 3424 | 3472 | ||
| 3425 | /* | 3473 | /* |
| @@ -3841,15 +3889,27 @@ static void rx_start(struct slgt_info *info) | |||
| 3841 | rdma_reset(info); | 3889 | rdma_reset(info); |
| 3842 | reset_rbufs(info); | 3890 | reset_rbufs(info); |
| 3843 | 3891 | ||
| 3844 | /* set 1st descriptor address */ | 3892 | if (info->rx_pio) { |
| 3845 | wr_reg32(info, RDDAR, info->rbufs[0].pdesc); | 3893 | /* rx request when rx FIFO not empty */ |
| 3846 | 3894 | wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) & ~BIT14)); | |
| 3847 | if (info->params.mode != MGSL_MODE_ASYNC) { | 3895 | slgt_irq_on(info, IRQ_RXDATA); |
| 3848 | /* enable rx DMA and DMA interrupt */ | 3896 | if (info->params.mode == MGSL_MODE_ASYNC) { |
| 3849 | wr_reg32(info, RDCSR, (BIT2 + BIT0)); | 3897 | /* enable saving of rx status */ |
| 3898 | wr_reg32(info, RDCSR, BIT6); | ||
| 3899 | } | ||
| 3850 | } else { | 3900 | } else { |
| 3851 | /* enable saving of rx status, rx DMA and DMA interrupt */ | 3901 | /* rx request when rx FIFO half full */ |
| 3852 | wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); | 3902 | wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT14)); |
| 3903 | /* set 1st descriptor address */ | ||
| 3904 | wr_reg32(info, RDDAR, info->rbufs[0].pdesc); | ||
| 3905 | |||
| 3906 | if (info->params.mode != MGSL_MODE_ASYNC) { | ||
| 3907 | /* enable rx DMA and DMA interrupt */ | ||
| 3908 | wr_reg32(info, RDCSR, (BIT2 + BIT0)); | ||
| 3909 | } else { | ||
| 3910 | /* enable saving of rx status, rx DMA and DMA interrupt */ | ||
| 3911 | wr_reg32(info, RDCSR, (BIT6 + BIT2 + BIT0)); | ||
| 3912 | } | ||
| 3853 | } | 3913 | } |
| 3854 | 3914 | ||
| 3855 | slgt_irq_on(info, IRQ_RXOVER); | 3915 | slgt_irq_on(info, IRQ_RXOVER); |
| @@ -4467,6 +4527,8 @@ static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last | |||
| 4467 | static void reset_rbufs(struct slgt_info *info) | 4527 | static void reset_rbufs(struct slgt_info *info) |
| 4468 | { | 4528 | { |
| 4469 | free_rbufs(info, 0, info->rbuf_count - 1); | 4529 | free_rbufs(info, 0, info->rbuf_count - 1); |
| 4530 | info->rbuf_fill_index = 0; | ||
| 4531 | info->rbuf_fill_count = 0; | ||
| 4470 | } | 4532 | } |
| 4471 | 4533 | ||
| 4472 | /* | 4534 | /* |
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c index 26de60efe4b2..6f727e3c53ad 100644 --- a/drivers/char/synclinkmp.c +++ b/drivers/char/synclinkmp.c | |||
| @@ -3277,13 +3277,16 @@ static int carrier_raised(struct tty_port *port) | |||
| 3277 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; | 3277 | return (info->serial_signals & SerialSignal_DCD) ? 1 : 0; |
| 3278 | } | 3278 | } |
| 3279 | 3279 | ||
| 3280 | static void raise_dtr_rts(struct tty_port *port) | 3280 | static void dtr_rts(struct tty_port *port, int on) |
| 3281 | { | 3281 | { |
| 3282 | SLMP_INFO *info = container_of(port, SLMP_INFO, port); | 3282 | SLMP_INFO *info = container_of(port, SLMP_INFO, port); |
| 3283 | unsigned long flags; | 3283 | unsigned long flags; |
| 3284 | 3284 | ||
| 3285 | spin_lock_irqsave(&info->lock,flags); | 3285 | spin_lock_irqsave(&info->lock,flags); |
| 3286 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | 3286 | if (on) |
| 3287 | info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR; | ||
| 3288 | else | ||
| 3289 | info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR); | ||
| 3287 | set_signals(info); | 3290 | set_signals(info); |
| 3288 | spin_unlock_irqrestore(&info->lock,flags); | 3291 | spin_unlock_irqrestore(&info->lock,flags); |
| 3289 | } | 3292 | } |
| @@ -3746,7 +3749,7 @@ static void add_device(SLMP_INFO *info) | |||
| 3746 | 3749 | ||
| 3747 | static const struct tty_port_operations port_ops = { | 3750 | static const struct tty_port_operations port_ops = { |
| 3748 | .carrier_raised = carrier_raised, | 3751 | .carrier_raised = carrier_raised, |
| 3749 | .raise_dtr_rts = raise_dtr_rts, | 3752 | .dtr_rts = dtr_rts, |
| 3750 | }; | 3753 | }; |
| 3751 | 3754 | ||
| 3752 | /* Allocate and initialize a device instance structure | 3755 | /* Allocate and initialize a device instance structure |
diff --git a/drivers/char/sysrq.c b/drivers/char/sysrq.c index d6a807f4077d..39a05b5fa9cb 100644 --- a/drivers/char/sysrq.c +++ b/drivers/char/sysrq.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <linux/kbd_kern.h> | 25 | #include <linux/kbd_kern.h> |
| 26 | #include <linux/proc_fs.h> | 26 | #include <linux/proc_fs.h> |
| 27 | #include <linux/quotaops.h> | 27 | #include <linux/quotaops.h> |
| 28 | #include <linux/perf_counter.h> | ||
| 28 | #include <linux/kernel.h> | 29 | #include <linux/kernel.h> |
| 29 | #include <linux/module.h> | 30 | #include <linux/module.h> |
| 30 | #include <linux/suspend.h> | 31 | #include <linux/suspend.h> |
| @@ -243,6 +244,7 @@ static void sysrq_handle_showregs(int key, struct tty_struct *tty) | |||
| 243 | struct pt_regs *regs = get_irq_regs(); | 244 | struct pt_regs *regs = get_irq_regs(); |
| 244 | if (regs) | 245 | if (regs) |
| 245 | show_regs(regs); | 246 | show_regs(regs); |
| 247 | perf_counter_print_debug(); | ||
| 246 | } | 248 | } |
| 247 | static struct sysrq_key_op sysrq_showregs_op = { | 249 | static struct sysrq_key_op sysrq_showregs_op = { |
| 248 | .handler = sysrq_handle_showregs, | 250 | .handler = sysrq_handle_showregs, |
diff --git a/drivers/char/tty_audit.c b/drivers/char/tty_audit.c index 55ba6f142883..ac16fbec72d0 100644 --- a/drivers/char/tty_audit.c +++ b/drivers/char/tty_audit.c | |||
| @@ -29,10 +29,7 @@ static struct tty_audit_buf *tty_audit_buf_alloc(int major, int minor, | |||
| 29 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); | 29 | buf = kmalloc(sizeof(*buf), GFP_KERNEL); |
| 30 | if (!buf) | 30 | if (!buf) |
| 31 | goto err; | 31 | goto err; |
| 32 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | 32 | buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); |
| 33 | buf->data = kmalloc(N_TTY_BUF_SIZE, GFP_KERNEL); | ||
| 34 | else | ||
| 35 | buf->data = (unsigned char *)__get_free_page(GFP_KERNEL); | ||
| 36 | if (!buf->data) | 33 | if (!buf->data) |
| 37 | goto err_buf; | 34 | goto err_buf; |
| 38 | atomic_set(&buf->count, 1); | 35 | atomic_set(&buf->count, 1); |
| @@ -52,10 +49,7 @@ err: | |||
| 52 | static void tty_audit_buf_free(struct tty_audit_buf *buf) | 49 | static void tty_audit_buf_free(struct tty_audit_buf *buf) |
| 53 | { | 50 | { |
| 54 | WARN_ON(buf->valid != 0); | 51 | WARN_ON(buf->valid != 0); |
| 55 | if (PAGE_SIZE != N_TTY_BUF_SIZE) | 52 | kfree(buf->data); |
| 56 | kfree(buf->data); | ||
| 57 | else | ||
| 58 | free_page((unsigned long)buf->data); | ||
| 59 | kfree(buf); | 53 | kfree(buf); |
| 60 | } | 54 | } |
| 61 | 55 | ||
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index 66b99a2049e3..939e198d7670 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -295,7 +295,7 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
| 295 | struct tty_driver *p, *res = NULL; | 295 | struct tty_driver *p, *res = NULL; |
| 296 | int tty_line = 0; | 296 | int tty_line = 0; |
| 297 | int len; | 297 | int len; |
| 298 | char *str; | 298 | char *str, *stp; |
| 299 | 299 | ||
| 300 | for (str = name; *str; str++) | 300 | for (str = name; *str; str++) |
| 301 | if ((*str >= '0' && *str <= '9') || *str == ',') | 301 | if ((*str >= '0' && *str <= '9') || *str == ',') |
| @@ -311,13 +311,14 @@ struct tty_driver *tty_find_polling_driver(char *name, int *line) | |||
| 311 | list_for_each_entry(p, &tty_drivers, tty_drivers) { | 311 | list_for_each_entry(p, &tty_drivers, tty_drivers) { |
| 312 | if (strncmp(name, p->name, len) != 0) | 312 | if (strncmp(name, p->name, len) != 0) |
| 313 | continue; | 313 | continue; |
| 314 | if (*str == ',') | 314 | stp = str; |
| 315 | str++; | 315 | if (*stp == ',') |
| 316 | if (*str == '\0') | 316 | stp++; |
| 317 | str = NULL; | 317 | if (*stp == '\0') |
| 318 | stp = NULL; | ||
| 318 | 319 | ||
| 319 | if (tty_line >= 0 && tty_line <= p->num && p->ops && | 320 | if (tty_line >= 0 && tty_line <= p->num && p->ops && |
| 320 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, str)) { | 321 | p->ops->poll_init && !p->ops->poll_init(p, tty_line, stp)) { |
| 321 | res = tty_driver_kref_get(p); | 322 | res = tty_driver_kref_get(p); |
| 322 | *line = tty_line; | 323 | *line = tty_line; |
| 323 | break; | 324 | break; |
| @@ -470,43 +471,6 @@ void tty_wakeup(struct tty_struct *tty) | |||
| 470 | EXPORT_SYMBOL_GPL(tty_wakeup); | 471 | EXPORT_SYMBOL_GPL(tty_wakeup); |
| 471 | 472 | ||
| 472 | /** | 473 | /** |
| 473 | * tty_ldisc_flush - flush line discipline queue | ||
| 474 | * @tty: tty | ||
| 475 | * | ||
| 476 | * Flush the line discipline queue (if any) for this tty. If there | ||
| 477 | * is no line discipline active this is a no-op. | ||
| 478 | */ | ||
| 479 | |||
| 480 | void tty_ldisc_flush(struct tty_struct *tty) | ||
| 481 | { | ||
| 482 | struct tty_ldisc *ld = tty_ldisc_ref(tty); | ||
| 483 | if (ld) { | ||
| 484 | if (ld->ops->flush_buffer) | ||
| 485 | ld->ops->flush_buffer(tty); | ||
| 486 | tty_ldisc_deref(ld); | ||
| 487 | } | ||
| 488 | tty_buffer_flush(tty); | ||
| 489 | } | ||
| 490 | |||
| 491 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); | ||
| 492 | |||
| 493 | /** | ||
| 494 | * tty_reset_termios - reset terminal state | ||
| 495 | * @tty: tty to reset | ||
| 496 | * | ||
| 497 | * Restore a terminal to the driver default state | ||
| 498 | */ | ||
| 499 | |||
| 500 | static void tty_reset_termios(struct tty_struct *tty) | ||
| 501 | { | ||
| 502 | mutex_lock(&tty->termios_mutex); | ||
| 503 | *tty->termios = tty->driver->init_termios; | ||
| 504 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
| 505 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
| 506 | mutex_unlock(&tty->termios_mutex); | ||
| 507 | } | ||
| 508 | |||
| 509 | /** | ||
| 510 | * do_tty_hangup - actual handler for hangup events | 474 | * do_tty_hangup - actual handler for hangup events |
| 511 | * @work: tty device | 475 | * @work: tty device |
| 512 | * | 476 | * |
| @@ -535,7 +499,6 @@ static void do_tty_hangup(struct work_struct *work) | |||
| 535 | struct file *cons_filp = NULL; | 499 | struct file *cons_filp = NULL; |
| 536 | struct file *filp, *f = NULL; | 500 | struct file *filp, *f = NULL; |
| 537 | struct task_struct *p; | 501 | struct task_struct *p; |
| 538 | struct tty_ldisc *ld; | ||
| 539 | int closecount = 0, n; | 502 | int closecount = 0, n; |
| 540 | unsigned long flags; | 503 | unsigned long flags; |
| 541 | int refs = 0; | 504 | int refs = 0; |
| @@ -566,40 +529,8 @@ static void do_tty_hangup(struct work_struct *work) | |||
| 566 | filp->f_op = &hung_up_tty_fops; | 529 | filp->f_op = &hung_up_tty_fops; |
| 567 | } | 530 | } |
| 568 | file_list_unlock(); | 531 | file_list_unlock(); |
| 569 | /* | ||
| 570 | * FIXME! What are the locking issues here? This may me overdoing | ||
| 571 | * things... This question is especially important now that we've | ||
| 572 | * removed the irqlock. | ||
| 573 | */ | ||
| 574 | ld = tty_ldisc_ref(tty); | ||
| 575 | if (ld != NULL) { | ||
| 576 | /* We may have no line discipline at this point */ | ||
| 577 | if (ld->ops->flush_buffer) | ||
| 578 | ld->ops->flush_buffer(tty); | ||
| 579 | tty_driver_flush_buffer(tty); | ||
| 580 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | ||
| 581 | ld->ops->write_wakeup) | ||
| 582 | ld->ops->write_wakeup(tty); | ||
| 583 | if (ld->ops->hangup) | ||
| 584 | ld->ops->hangup(tty); | ||
| 585 | } | ||
| 586 | /* | ||
| 587 | * FIXME: Once we trust the LDISC code better we can wait here for | ||
| 588 | * ldisc completion and fix the driver call race | ||
| 589 | */ | ||
| 590 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | ||
| 591 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | ||
| 592 | /* | ||
| 593 | * Shutdown the current line discipline, and reset it to | ||
| 594 | * N_TTY. | ||
| 595 | */ | ||
| 596 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) | ||
| 597 | tty_reset_termios(tty); | ||
| 598 | /* Defer ldisc switch */ | ||
| 599 | /* tty_deferred_ldisc_switch(N_TTY); | ||
| 600 | 532 | ||
| 601 | This should get done automatically when the port closes and | 533 | tty_ldisc_hangup(tty); |
| 602 | tty_release is called */ | ||
| 603 | 534 | ||
| 604 | read_lock(&tasklist_lock); | 535 | read_lock(&tasklist_lock); |
| 605 | if (tty->session) { | 536 | if (tty->session) { |
| @@ -628,12 +559,15 @@ static void do_tty_hangup(struct work_struct *work) | |||
| 628 | read_unlock(&tasklist_lock); | 559 | read_unlock(&tasklist_lock); |
| 629 | 560 | ||
| 630 | spin_lock_irqsave(&tty->ctrl_lock, flags); | 561 | spin_lock_irqsave(&tty->ctrl_lock, flags); |
| 631 | tty->flags = 0; | 562 | clear_bit(TTY_THROTTLED, &tty->flags); |
| 563 | clear_bit(TTY_PUSH, &tty->flags); | ||
| 564 | clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags); | ||
| 632 | put_pid(tty->session); | 565 | put_pid(tty->session); |
| 633 | put_pid(tty->pgrp); | 566 | put_pid(tty->pgrp); |
| 634 | tty->session = NULL; | 567 | tty->session = NULL; |
| 635 | tty->pgrp = NULL; | 568 | tty->pgrp = NULL; |
| 636 | tty->ctrl_status = 0; | 569 | tty->ctrl_status = 0; |
| 570 | set_bit(TTY_HUPPED, &tty->flags); | ||
| 637 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); | 571 | spin_unlock_irqrestore(&tty->ctrl_lock, flags); |
| 638 | 572 | ||
| 639 | /* Account for the p->signal references we killed */ | 573 | /* Account for the p->signal references we killed */ |
| @@ -659,10 +593,7 @@ static void do_tty_hangup(struct work_struct *work) | |||
| 659 | * can't yet guarantee all that. | 593 | * can't yet guarantee all that. |
| 660 | */ | 594 | */ |
| 661 | set_bit(TTY_HUPPED, &tty->flags); | 595 | set_bit(TTY_HUPPED, &tty->flags); |
| 662 | if (ld) { | 596 | tty_ldisc_enable(tty); |
| 663 | tty_ldisc_enable(tty); | ||
| 664 | tty_ldisc_deref(ld); | ||
| 665 | } | ||
| 666 | unlock_kernel(); | 597 | unlock_kernel(); |
| 667 | if (f) | 598 | if (f) |
| 668 | fput(f); | 599 | fput(f); |
| @@ -2480,6 +2411,24 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int | |||
| 2480 | return tty->ops->tiocmset(tty, file, set, clear); | 2411 | return tty->ops->tiocmset(tty, file, set, clear); |
| 2481 | } | 2412 | } |
| 2482 | 2413 | ||
| 2414 | struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) | ||
| 2415 | { | ||
| 2416 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
| 2417 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
| 2418 | tty = tty->link; | ||
| 2419 | return tty; | ||
| 2420 | } | ||
| 2421 | EXPORT_SYMBOL(tty_pair_get_tty); | ||
| 2422 | |||
| 2423 | struct tty_struct *tty_pair_get_pty(struct tty_struct *tty) | ||
| 2424 | { | ||
| 2425 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
| 2426 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
| 2427 | return tty; | ||
| 2428 | return tty->link; | ||
| 2429 | } | ||
| 2430 | EXPORT_SYMBOL(tty_pair_get_pty); | ||
| 2431 | |||
| 2483 | /* | 2432 | /* |
| 2484 | * Split this up, as gcc can choke on it otherwise.. | 2433 | * Split this up, as gcc can choke on it otherwise.. |
| 2485 | */ | 2434 | */ |
| @@ -2495,11 +2444,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 2495 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) | 2444 | if (tty_paranoia_check(tty, inode, "tty_ioctl")) |
| 2496 | return -EINVAL; | 2445 | return -EINVAL; |
| 2497 | 2446 | ||
| 2498 | real_tty = tty; | 2447 | real_tty = tty_pair_get_tty(tty); |
| 2499 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | ||
| 2500 | tty->driver->subtype == PTY_TYPE_MASTER) | ||
| 2501 | real_tty = tty->link; | ||
| 2502 | |||
| 2503 | 2448 | ||
| 2504 | /* | 2449 | /* |
| 2505 | * Factor out some common prep work | 2450 | * Factor out some common prep work |
| @@ -2555,7 +2500,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
| 2555 | case TIOCGSID: | 2500 | case TIOCGSID: |
| 2556 | return tiocgsid(tty, real_tty, p); | 2501 | return tiocgsid(tty, real_tty, p); |
| 2557 | case TIOCGETD: | 2502 | case TIOCGETD: |
| 2558 | return put_user(tty->ldisc.ops->num, (int __user *)p); | 2503 | return put_user(tty->ldisc->ops->num, (int __user *)p); |
| 2559 | case TIOCSETD: | 2504 | case TIOCSETD: |
| 2560 | return tiocsetd(tty, p); | 2505 | return tiocsetd(tty, p); |
| 2561 | /* | 2506 | /* |
| @@ -2770,6 +2715,7 @@ void initialize_tty_struct(struct tty_struct *tty, | |||
| 2770 | tty->buf.head = tty->buf.tail = NULL; | 2715 | tty->buf.head = tty->buf.tail = NULL; |
| 2771 | tty_buffer_init(tty); | 2716 | tty_buffer_init(tty); |
| 2772 | mutex_init(&tty->termios_mutex); | 2717 | mutex_init(&tty->termios_mutex); |
| 2718 | mutex_init(&tty->ldisc_mutex); | ||
| 2773 | init_waitqueue_head(&tty->write_wait); | 2719 | init_waitqueue_head(&tty->write_wait); |
| 2774 | init_waitqueue_head(&tty->read_wait); | 2720 | init_waitqueue_head(&tty->read_wait); |
| 2775 | INIT_WORK(&tty->hangup_work, do_tty_hangup); | 2721 | INIT_WORK(&tty->hangup_work, do_tty_hangup); |
diff --git a/drivers/char/tty_ioctl.c b/drivers/char/tty_ioctl.c index 6f4c7d0a53bf..8116bb1c8f80 100644 --- a/drivers/char/tty_ioctl.c +++ b/drivers/char/tty_ioctl.c | |||
| @@ -97,14 +97,19 @@ EXPORT_SYMBOL(tty_driver_flush_buffer); | |||
| 97 | * @tty: terminal | 97 | * @tty: terminal |
| 98 | * | 98 | * |
| 99 | * Indicate that a tty should stop transmitting data down the stack. | 99 | * Indicate that a tty should stop transmitting data down the stack. |
| 100 | * Takes the termios mutex to protect against parallel throttle/unthrottle | ||
| 101 | * and also to ensure the driver can consistently reference its own | ||
| 102 | * termios data at this point when implementing software flow control. | ||
| 100 | */ | 103 | */ |
| 101 | 104 | ||
| 102 | void tty_throttle(struct tty_struct *tty) | 105 | void tty_throttle(struct tty_struct *tty) |
| 103 | { | 106 | { |
| 107 | mutex_lock(&tty->termios_mutex); | ||
| 104 | /* check TTY_THROTTLED first so it indicates our state */ | 108 | /* check TTY_THROTTLED first so it indicates our state */ |
| 105 | if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && | 109 | if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) && |
| 106 | tty->ops->throttle) | 110 | tty->ops->throttle) |
| 107 | tty->ops->throttle(tty); | 111 | tty->ops->throttle(tty); |
| 112 | mutex_unlock(&tty->termios_mutex); | ||
| 108 | } | 113 | } |
| 109 | EXPORT_SYMBOL(tty_throttle); | 114 | EXPORT_SYMBOL(tty_throttle); |
| 110 | 115 | ||
| @@ -113,13 +118,21 @@ EXPORT_SYMBOL(tty_throttle); | |||
| 113 | * @tty: terminal | 118 | * @tty: terminal |
| 114 | * | 119 | * |
| 115 | * Indicate that a tty may continue transmitting data down the stack. | 120 | * Indicate that a tty may continue transmitting data down the stack. |
| 121 | * Takes the termios mutex to protect against parallel throttle/unthrottle | ||
| 122 | * and also to ensure the driver can consistently reference its own | ||
| 123 | * termios data at this point when implementing software flow control. | ||
| 124 | * | ||
| 125 | * Drivers should however remember that the stack can issue a throttle, | ||
| 126 | * then change flow control method, then unthrottle. | ||
| 116 | */ | 127 | */ |
| 117 | 128 | ||
| 118 | void tty_unthrottle(struct tty_struct *tty) | 129 | void tty_unthrottle(struct tty_struct *tty) |
| 119 | { | 130 | { |
| 131 | mutex_lock(&tty->termios_mutex); | ||
| 120 | if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && | 132 | if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) && |
| 121 | tty->ops->unthrottle) | 133 | tty->ops->unthrottle) |
| 122 | tty->ops->unthrottle(tty); | 134 | tty->ops->unthrottle(tty); |
| 135 | mutex_unlock(&tty->termios_mutex); | ||
| 123 | } | 136 | } |
| 124 | EXPORT_SYMBOL(tty_unthrottle); | 137 | EXPORT_SYMBOL(tty_unthrottle); |
| 125 | 138 | ||
| @@ -613,9 +626,25 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt) | |||
| 613 | return 0; | 626 | return 0; |
| 614 | } | 627 | } |
| 615 | 628 | ||
| 629 | static void copy_termios(struct tty_struct *tty, struct ktermios *kterm) | ||
| 630 | { | ||
| 631 | mutex_lock(&tty->termios_mutex); | ||
| 632 | memcpy(kterm, tty->termios, sizeof(struct ktermios)); | ||
| 633 | mutex_unlock(&tty->termios_mutex); | ||
| 634 | } | ||
| 635 | |||
| 636 | static void copy_termios_locked(struct tty_struct *tty, struct ktermios *kterm) | ||
| 637 | { | ||
| 638 | mutex_lock(&tty->termios_mutex); | ||
| 639 | memcpy(kterm, tty->termios_locked, sizeof(struct ktermios)); | ||
| 640 | mutex_unlock(&tty->termios_mutex); | ||
| 641 | } | ||
| 642 | |||
| 616 | static int get_termio(struct tty_struct *tty, struct termio __user *termio) | 643 | static int get_termio(struct tty_struct *tty, struct termio __user *termio) |
| 617 | { | 644 | { |
| 618 | if (kernel_termios_to_user_termio(termio, tty->termios)) | 645 | struct ktermios kterm; |
| 646 | copy_termios(tty, &kterm); | ||
| 647 | if (kernel_termios_to_user_termio(termio, &kterm)) | ||
| 619 | return -EFAULT; | 648 | return -EFAULT; |
| 620 | return 0; | 649 | return 0; |
| 621 | } | 650 | } |
| @@ -917,6 +946,8 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
| 917 | struct tty_struct *real_tty; | 946 | struct tty_struct *real_tty; |
| 918 | void __user *p = (void __user *)arg; | 947 | void __user *p = (void __user *)arg; |
| 919 | int ret = 0; | 948 | int ret = 0; |
| 949 | struct ktermios kterm; | ||
| 950 | struct termiox ktermx; | ||
| 920 | 951 | ||
| 921 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && | 952 | if (tty->driver->type == TTY_DRIVER_TYPE_PTY && |
| 922 | tty->driver->subtype == PTY_TYPE_MASTER) | 953 | tty->driver->subtype == PTY_TYPE_MASTER) |
| @@ -952,23 +983,20 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
| 952 | return set_termios(real_tty, p, TERMIOS_OLD); | 983 | return set_termios(real_tty, p, TERMIOS_OLD); |
| 953 | #ifndef TCGETS2 | 984 | #ifndef TCGETS2 |
| 954 | case TCGETS: | 985 | case TCGETS: |
| 955 | mutex_lock(&real_tty->termios_mutex); | 986 | copy_termios(real_tty, &kterm); |
| 956 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios)) | 987 | if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm)) |
| 957 | ret = -EFAULT; | 988 | ret = -EFAULT; |
| 958 | mutex_unlock(&real_tty->termios_mutex); | ||
| 959 | return ret; | 989 | return ret; |
| 960 | #else | 990 | #else |
| 961 | case TCGETS: | 991 | case TCGETS: |
| 962 | mutex_lock(&real_tty->termios_mutex); | 992 | copy_termios(real_tty, &kterm); |
| 963 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios)) | 993 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm)) |
| 964 | ret = -EFAULT; | 994 | ret = -EFAULT; |
| 965 | mutex_unlock(&real_tty->termios_mutex); | ||
| 966 | return ret; | 995 | return ret; |
| 967 | case TCGETS2: | 996 | case TCGETS2: |
| 968 | mutex_lock(&real_tty->termios_mutex); | 997 | copy_termios(real_tty, &kterm); |
| 969 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, real_tty->termios)) | 998 | if (kernel_termios_to_user_termios((struct termios2 __user *)arg, &kterm)) |
| 970 | ret = -EFAULT; | 999 | ret = -EFAULT; |
| 971 | mutex_unlock(&real_tty->termios_mutex); | ||
| 972 | return ret; | 1000 | return ret; |
| 973 | case TCSETSF2: | 1001 | case TCSETSF2: |
| 974 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); | 1002 | return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT); |
| @@ -987,34 +1015,36 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
| 987 | return set_termios(real_tty, p, TERMIOS_TERMIO); | 1015 | return set_termios(real_tty, p, TERMIOS_TERMIO); |
| 988 | #ifndef TCGETS2 | 1016 | #ifndef TCGETS2 |
| 989 | case TIOCGLCKTRMIOS: | 1017 | case TIOCGLCKTRMIOS: |
| 990 | mutex_lock(&real_tty->termios_mutex); | 1018 | copy_termios_locked(real_tty, &kterm); |
| 991 | if (kernel_termios_to_user_termios((struct termios __user *)arg, real_tty->termios_locked)) | 1019 | if (kernel_termios_to_user_termios((struct termios __user *)arg, &kterm)) |
| 992 | ret = -EFAULT; | 1020 | ret = -EFAULT; |
| 993 | mutex_unlock(&real_tty->termios_mutex); | ||
| 994 | return ret; | 1021 | return ret; |
| 995 | case TIOCSLCKTRMIOS: | 1022 | case TIOCSLCKTRMIOS: |
| 996 | if (!capable(CAP_SYS_ADMIN)) | 1023 | if (!capable(CAP_SYS_ADMIN)) |
| 997 | return -EPERM; | 1024 | return -EPERM; |
| 998 | mutex_lock(&real_tty->termios_mutex); | 1025 | copy_termios_locked(real_tty, &kterm); |
| 999 | if (user_termios_to_kernel_termios(real_tty->termios_locked, | 1026 | if (user_termios_to_kernel_termios(&kterm, |
| 1000 | (struct termios __user *) arg)) | 1027 | (struct termios __user *) arg)) |
| 1001 | ret = -EFAULT; | 1028 | return -EFAULT; |
| 1029 | mutex_lock(&real_tty->termios_mutex); | ||
| 1030 | memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios)); | ||
| 1002 | mutex_unlock(&real_tty->termios_mutex); | 1031 | mutex_unlock(&real_tty->termios_mutex); |
| 1003 | return ret; | 1032 | return 0; |
| 1004 | #else | 1033 | #else |
| 1005 | case TIOCGLCKTRMIOS: | 1034 | case TIOCGLCKTRMIOS: |
| 1006 | mutex_lock(&real_tty->termios_mutex); | 1035 | copy_termios_locked(real_tty, &kterm); |
| 1007 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, real_tty->termios_locked)) | 1036 | if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &kterm)) |
| 1008 | ret = -EFAULT; | 1037 | ret = -EFAULT; |
| 1009 | mutex_unlock(&real_tty->termios_mutex); | ||
| 1010 | return ret; | 1038 | return ret; |
| 1011 | case TIOCSLCKTRMIOS: | 1039 | case TIOCSLCKTRMIOS: |
| 1012 | if (!capable(CAP_SYS_ADMIN)) | 1040 | if (!capable(CAP_SYS_ADMIN)) |
| 1013 | ret = -EPERM; | 1041 | return -EPERM; |
| 1014 | mutex_lock(&real_tty->termios_mutex); | 1042 | copy_termios_locked(real_tty, &kterm); |
| 1015 | if (user_termios_to_kernel_termios_1(real_tty->termios_locked, | 1043 | if (user_termios_to_kernel_termios_1(&kterm, |
| 1016 | (struct termios __user *) arg)) | 1044 | (struct termios __user *) arg)) |
| 1017 | ret = -EFAULT; | 1045 | return -EFAULT; |
| 1046 | mutex_lock(&real_tty->termios_mutex); | ||
| 1047 | memcpy(real_tty->termios_locked, &kterm, sizeof(struct ktermios)); | ||
| 1018 | mutex_unlock(&real_tty->termios_mutex); | 1048 | mutex_unlock(&real_tty->termios_mutex); |
| 1019 | return ret; | 1049 | return ret; |
| 1020 | #endif | 1050 | #endif |
| @@ -1023,9 +1053,10 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1023 | if (real_tty->termiox == NULL) | 1053 | if (real_tty->termiox == NULL) |
| 1024 | return -EINVAL; | 1054 | return -EINVAL; |
| 1025 | mutex_lock(&real_tty->termios_mutex); | 1055 | mutex_lock(&real_tty->termios_mutex); |
| 1026 | if (copy_to_user(p, real_tty->termiox, sizeof(struct termiox))) | 1056 | memcpy(&ktermx, real_tty->termiox, sizeof(struct termiox)); |
| 1027 | ret = -EFAULT; | ||
| 1028 | mutex_unlock(&real_tty->termios_mutex); | 1057 | mutex_unlock(&real_tty->termios_mutex); |
| 1058 | if (copy_to_user(p, &ktermx, sizeof(struct termiox))) | ||
| 1059 | ret = -EFAULT; | ||
| 1029 | return ret; | 1060 | return ret; |
| 1030 | case TCSETX: | 1061 | case TCSETX: |
| 1031 | return set_termiox(real_tty, p, 0); | 1062 | return set_termiox(real_tty, p, 0); |
| @@ -1035,10 +1066,9 @@ int tty_mode_ioctl(struct tty_struct *tty, struct file *file, | |||
| 1035 | return set_termiox(real_tty, p, TERMIOS_FLUSH); | 1066 | return set_termiox(real_tty, p, TERMIOS_FLUSH); |
| 1036 | #endif | 1067 | #endif |
| 1037 | case TIOCGSOFTCAR: | 1068 | case TIOCGSOFTCAR: |
| 1038 | mutex_lock(&real_tty->termios_mutex); | 1069 | copy_termios(real_tty, &kterm); |
| 1039 | ret = put_user(C_CLOCAL(real_tty) ? 1 : 0, | 1070 | ret = put_user((kterm.c_cflag & CLOCAL) ? 1 : 0, |
| 1040 | (int __user *)arg); | 1071 | (int __user *)arg); |
| 1041 | mutex_unlock(&real_tty->termios_mutex); | ||
| 1042 | return ret; | 1072 | return ret; |
| 1043 | case TIOCSSOFTCAR: | 1073 | case TIOCSSOFTCAR: |
| 1044 | if (get_user(arg, (unsigned int __user *) arg)) | 1074 | if (get_user(arg, (unsigned int __user *) arg)) |
diff --git a/drivers/char/tty_ldisc.c b/drivers/char/tty_ldisc.c index f78f5b0127a8..39c8f86dedd4 100644 --- a/drivers/char/tty_ldisc.c +++ b/drivers/char/tty_ldisc.c | |||
| @@ -115,19 +115,22 @@ EXPORT_SYMBOL(tty_unregister_ldisc); | |||
| 115 | /** | 115 | /** |
| 116 | * tty_ldisc_try_get - try and reference an ldisc | 116 | * tty_ldisc_try_get - try and reference an ldisc |
| 117 | * @disc: ldisc number | 117 | * @disc: ldisc number |
| 118 | * @ld: tty ldisc structure to complete | ||
| 119 | * | 118 | * |
| 120 | * Attempt to open and lock a line discipline into place. Return | 119 | * Attempt to open and lock a line discipline into place. Return |
| 121 | * the line discipline refcounted and assigned in ld. On an error | 120 | * the line discipline refcounted or an error. |
| 122 | * report the error code back | ||
| 123 | */ | 121 | */ |
| 124 | 122 | ||
| 125 | static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | 123 | static struct tty_ldisc *tty_ldisc_try_get(int disc) |
| 126 | { | 124 | { |
| 127 | unsigned long flags; | 125 | unsigned long flags; |
| 126 | struct tty_ldisc *ld; | ||
| 128 | struct tty_ldisc_ops *ldops; | 127 | struct tty_ldisc_ops *ldops; |
| 129 | int err = -EINVAL; | 128 | int err = -EINVAL; |
| 130 | 129 | ||
| 130 | ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL); | ||
| 131 | if (ld == NULL) | ||
| 132 | return ERR_PTR(-ENOMEM); | ||
| 133 | |||
| 131 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 134 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
| 132 | ld->ops = NULL; | 135 | ld->ops = NULL; |
| 133 | ldops = tty_ldiscs[disc]; | 136 | ldops = tty_ldiscs[disc]; |
| @@ -140,17 +143,19 @@ static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | |||
| 140 | /* lock it */ | 143 | /* lock it */ |
| 141 | ldops->refcount++; | 144 | ldops->refcount++; |
| 142 | ld->ops = ldops; | 145 | ld->ops = ldops; |
| 146 | ld->refcount = 0; | ||
| 143 | err = 0; | 147 | err = 0; |
| 144 | } | 148 | } |
| 145 | } | 149 | } |
| 146 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 150 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
| 147 | return err; | 151 | if (err) |
| 152 | return ERR_PTR(err); | ||
| 153 | return ld; | ||
| 148 | } | 154 | } |
| 149 | 155 | ||
| 150 | /** | 156 | /** |
| 151 | * tty_ldisc_get - take a reference to an ldisc | 157 | * tty_ldisc_get - take a reference to an ldisc |
| 152 | * @disc: ldisc number | 158 | * @disc: ldisc number |
| 153 | * @ld: tty line discipline structure to use | ||
| 154 | * | 159 | * |
| 155 | * Takes a reference to a line discipline. Deals with refcounts and | 160 | * Takes a reference to a line discipline. Deals with refcounts and |
| 156 | * module locking counts. Returns NULL if the discipline is not available. | 161 | * module locking counts. Returns NULL if the discipline is not available. |
| @@ -161,52 +166,54 @@ static int tty_ldisc_try_get(int disc, struct tty_ldisc *ld) | |||
| 161 | * takes tty_ldisc_lock to guard against ldisc races | 166 | * takes tty_ldisc_lock to guard against ldisc races |
| 162 | */ | 167 | */ |
| 163 | 168 | ||
| 164 | static int tty_ldisc_get(int disc, struct tty_ldisc *ld) | 169 | static struct tty_ldisc *tty_ldisc_get(int disc) |
| 165 | { | 170 | { |
| 166 | int err; | 171 | struct tty_ldisc *ld; |
| 167 | 172 | ||
| 168 | if (disc < N_TTY || disc >= NR_LDISCS) | 173 | if (disc < N_TTY || disc >= NR_LDISCS) |
| 169 | return -EINVAL; | 174 | return ERR_PTR(-EINVAL); |
| 170 | err = tty_ldisc_try_get(disc, ld); | 175 | ld = tty_ldisc_try_get(disc); |
| 171 | if (err < 0) { | 176 | if (IS_ERR(ld)) { |
| 172 | request_module("tty-ldisc-%d", disc); | 177 | request_module("tty-ldisc-%d", disc); |
| 173 | err = tty_ldisc_try_get(disc, ld); | 178 | ld = tty_ldisc_try_get(disc); |
| 174 | } | 179 | } |
| 175 | return err; | 180 | return ld; |
| 176 | } | 181 | } |
| 177 | 182 | ||
| 178 | /** | 183 | /** |
| 179 | * tty_ldisc_put - drop ldisc reference | 184 | * tty_ldisc_put - drop ldisc reference |
| 180 | * @disc: ldisc number | 185 | * @ld: ldisc |
| 181 | * | 186 | * |
| 182 | * Drop a reference to a line discipline. Manage refcounts and | 187 | * Drop a reference to a line discipline. Manage refcounts and |
| 183 | * module usage counts | 188 | * module usage counts. Free the ldisc once the recount hits zero. |
| 184 | * | 189 | * |
| 185 | * Locking: | 190 | * Locking: |
| 186 | * takes tty_ldisc_lock to guard against ldisc races | 191 | * takes tty_ldisc_lock to guard against ldisc races |
| 187 | */ | 192 | */ |
| 188 | 193 | ||
| 189 | static void tty_ldisc_put(struct tty_ldisc_ops *ld) | 194 | static void tty_ldisc_put(struct tty_ldisc *ld) |
| 190 | { | 195 | { |
| 191 | unsigned long flags; | 196 | unsigned long flags; |
| 192 | int disc = ld->num; | 197 | int disc = ld->ops->num; |
| 198 | struct tty_ldisc_ops *ldo; | ||
| 193 | 199 | ||
| 194 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); | 200 | BUG_ON(disc < N_TTY || disc >= NR_LDISCS); |
| 195 | 201 | ||
| 196 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 202 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
| 197 | ld = tty_ldiscs[disc]; | 203 | ldo = tty_ldiscs[disc]; |
| 198 | BUG_ON(ld->refcount == 0); | 204 | BUG_ON(ldo->refcount == 0); |
| 199 | ld->refcount--; | 205 | ldo->refcount--; |
| 200 | module_put(ld->owner); | 206 | module_put(ldo->owner); |
| 201 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 207 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
| 208 | kfree(ld); | ||
| 202 | } | 209 | } |
| 203 | 210 | ||
| 204 | static void * tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) | 211 | static void *tty_ldiscs_seq_start(struct seq_file *m, loff_t *pos) |
| 205 | { | 212 | { |
| 206 | return (*pos < NR_LDISCS) ? pos : NULL; | 213 | return (*pos < NR_LDISCS) ? pos : NULL; |
| 207 | } | 214 | } |
| 208 | 215 | ||
| 209 | static void * tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) | 216 | static void *tty_ldiscs_seq_next(struct seq_file *m, void *v, loff_t *pos) |
| 210 | { | 217 | { |
| 211 | (*pos)++; | 218 | (*pos)++; |
| 212 | return (*pos < NR_LDISCS) ? pos : NULL; | 219 | return (*pos < NR_LDISCS) ? pos : NULL; |
| @@ -219,12 +226,13 @@ static void tty_ldiscs_seq_stop(struct seq_file *m, void *v) | |||
| 219 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) | 226 | static int tty_ldiscs_seq_show(struct seq_file *m, void *v) |
| 220 | { | 227 | { |
| 221 | int i = *(loff_t *)v; | 228 | int i = *(loff_t *)v; |
| 222 | struct tty_ldisc ld; | 229 | struct tty_ldisc *ld; |
| 223 | 230 | ||
| 224 | if (tty_ldisc_get(i, &ld) < 0) | 231 | ld = tty_ldisc_try_get(i); |
| 232 | if (IS_ERR(ld)) | ||
| 225 | return 0; | 233 | return 0; |
| 226 | seq_printf(m, "%-10s %2d\n", ld.ops->name ? ld.ops->name : "???", i); | 234 | seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i); |
| 227 | tty_ldisc_put(ld.ops); | 235 | tty_ldisc_put(ld); |
| 228 | return 0; | 236 | return 0; |
| 229 | } | 237 | } |
| 230 | 238 | ||
| @@ -263,8 +271,7 @@ const struct file_operations tty_ldiscs_proc_fops = { | |||
| 263 | 271 | ||
| 264 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) | 272 | static void tty_ldisc_assign(struct tty_struct *tty, struct tty_ldisc *ld) |
| 265 | { | 273 | { |
| 266 | ld->refcount = 0; | 274 | tty->ldisc = ld; |
| 267 | tty->ldisc = *ld; | ||
| 268 | } | 275 | } |
| 269 | 276 | ||
| 270 | /** | 277 | /** |
| @@ -286,7 +293,7 @@ static int tty_ldisc_try(struct tty_struct *tty) | |||
| 286 | int ret = 0; | 293 | int ret = 0; |
| 287 | 294 | ||
| 288 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 295 | spin_lock_irqsave(&tty_ldisc_lock, flags); |
| 289 | ld = &tty->ldisc; | 296 | ld = tty->ldisc; |
| 290 | if (test_bit(TTY_LDISC, &tty->flags)) { | 297 | if (test_bit(TTY_LDISC, &tty->flags)) { |
| 291 | ld->refcount++; | 298 | ld->refcount++; |
| 292 | ret = 1; | 299 | ret = 1; |
| @@ -315,10 +322,9 @@ struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *tty) | |||
| 315 | { | 322 | { |
| 316 | /* wait_event is a macro */ | 323 | /* wait_event is a macro */ |
| 317 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); | 324 | wait_event(tty_ldisc_wait, tty_ldisc_try(tty)); |
| 318 | WARN_ON(tty->ldisc.refcount == 0); | 325 | WARN_ON(tty->ldisc->refcount == 0); |
| 319 | return &tty->ldisc; | 326 | return tty->ldisc; |
| 320 | } | 327 | } |
| 321 | |||
| 322 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | 328 | EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); |
| 323 | 329 | ||
| 324 | /** | 330 | /** |
| @@ -335,10 +341,9 @@ EXPORT_SYMBOL_GPL(tty_ldisc_ref_wait); | |||
| 335 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) | 341 | struct tty_ldisc *tty_ldisc_ref(struct tty_struct *tty) |
| 336 | { | 342 | { |
| 337 | if (tty_ldisc_try(tty)) | 343 | if (tty_ldisc_try(tty)) |
| 338 | return &tty->ldisc; | 344 | return tty->ldisc; |
| 339 | return NULL; | 345 | return NULL; |
| 340 | } | 346 | } |
| 341 | |||
| 342 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); | 347 | EXPORT_SYMBOL_GPL(tty_ldisc_ref); |
| 343 | 348 | ||
| 344 | /** | 349 | /** |
| @@ -366,7 +371,6 @@ void tty_ldisc_deref(struct tty_ldisc *ld) | |||
| 366 | wake_up(&tty_ldisc_wait); | 371 | wake_up(&tty_ldisc_wait); |
| 367 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 372 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); |
| 368 | } | 373 | } |
| 369 | |||
| 370 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); | 374 | EXPORT_SYMBOL_GPL(tty_ldisc_deref); |
| 371 | 375 | ||
| 372 | /** | 376 | /** |
| @@ -389,6 +393,26 @@ void tty_ldisc_enable(struct tty_struct *tty) | |||
| 389 | } | 393 | } |
| 390 | 394 | ||
| 391 | /** | 395 | /** |
| 396 | * tty_ldisc_flush - flush line discipline queue | ||
| 397 | * @tty: tty | ||
| 398 | * | ||
| 399 | * Flush the line discipline queue (if any) for this tty. If there | ||
| 400 | * is no line discipline active this is a no-op. | ||
| 401 | */ | ||
| 402 | |||
| 403 | void tty_ldisc_flush(struct tty_struct *tty) | ||
| 404 | { | ||
| 405 | struct tty_ldisc *ld = tty_ldisc_ref(tty); | ||
| 406 | if (ld) { | ||
| 407 | if (ld->ops->flush_buffer) | ||
| 408 | ld->ops->flush_buffer(tty); | ||
| 409 | tty_ldisc_deref(ld); | ||
| 410 | } | ||
| 411 | tty_buffer_flush(tty); | ||
| 412 | } | ||
| 413 | EXPORT_SYMBOL_GPL(tty_ldisc_flush); | ||
| 414 | |||
| 415 | /** | ||
| 392 | * tty_set_termios_ldisc - set ldisc field | 416 | * tty_set_termios_ldisc - set ldisc field |
| 393 | * @tty: tty structure | 417 | * @tty: tty structure |
| 394 | * @num: line discipline number | 418 | * @num: line discipline number |
| @@ -407,6 +431,39 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
| 407 | mutex_unlock(&tty->termios_mutex); | 431 | mutex_unlock(&tty->termios_mutex); |
| 408 | } | 432 | } |
| 409 | 433 | ||
| 434 | /** | ||
| 435 | * tty_ldisc_open - open a line discipline | ||
| 436 | * @tty: tty we are opening the ldisc on | ||
| 437 | * @ld: discipline to open | ||
| 438 | * | ||
| 439 | * A helper opening method. Also a convenient debugging and check | ||
| 440 | * point. | ||
| 441 | */ | ||
| 442 | |||
| 443 | static int tty_ldisc_open(struct tty_struct *tty, struct tty_ldisc *ld) | ||
| 444 | { | ||
| 445 | WARN_ON(test_and_set_bit(TTY_LDISC_OPEN, &tty->flags)); | ||
| 446 | if (ld->ops->open) | ||
| 447 | return ld->ops->open(tty); | ||
| 448 | return 0; | ||
| 449 | } | ||
| 450 | |||
| 451 | /** | ||
| 452 | * tty_ldisc_close - close a line discipline | ||
| 453 | * @tty: tty we are opening the ldisc on | ||
| 454 | * @ld: discipline to close | ||
| 455 | * | ||
| 456 | * A helper close method. Also a convenient debugging and check | ||
| 457 | * point. | ||
| 458 | */ | ||
| 459 | |||
| 460 | static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld) | ||
| 461 | { | ||
| 462 | WARN_ON(!test_bit(TTY_LDISC_OPEN, &tty->flags)); | ||
| 463 | clear_bit(TTY_LDISC_OPEN, &tty->flags); | ||
| 464 | if (ld->ops->close) | ||
| 465 | ld->ops->close(tty); | ||
| 466 | } | ||
| 410 | 467 | ||
| 411 | /** | 468 | /** |
| 412 | * tty_ldisc_restore - helper for tty ldisc change | 469 | * tty_ldisc_restore - helper for tty ldisc change |
| @@ -420,66 +477,136 @@ static void tty_set_termios_ldisc(struct tty_struct *tty, int num) | |||
| 420 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) | 477 | static void tty_ldisc_restore(struct tty_struct *tty, struct tty_ldisc *old) |
| 421 | { | 478 | { |
| 422 | char buf[64]; | 479 | char buf[64]; |
| 423 | struct tty_ldisc new_ldisc; | 480 | struct tty_ldisc *new_ldisc; |
| 481 | int r; | ||
| 424 | 482 | ||
| 425 | /* There is an outstanding reference here so this is safe */ | 483 | /* There is an outstanding reference here so this is safe */ |
| 426 | tty_ldisc_get(old->ops->num, old); | 484 | old = tty_ldisc_get(old->ops->num); |
| 485 | WARN_ON(IS_ERR(old)); | ||
| 427 | tty_ldisc_assign(tty, old); | 486 | tty_ldisc_assign(tty, old); |
| 428 | tty_set_termios_ldisc(tty, old->ops->num); | 487 | tty_set_termios_ldisc(tty, old->ops->num); |
| 429 | if (old->ops->open && (old->ops->open(tty) < 0)) { | 488 | if (tty_ldisc_open(tty, old) < 0) { |
| 430 | tty_ldisc_put(old->ops); | 489 | tty_ldisc_put(old); |
| 431 | /* This driver is always present */ | 490 | /* This driver is always present */ |
| 432 | if (tty_ldisc_get(N_TTY, &new_ldisc) < 0) | 491 | new_ldisc = tty_ldisc_get(N_TTY); |
| 492 | if (IS_ERR(new_ldisc)) | ||
| 433 | panic("n_tty: get"); | 493 | panic("n_tty: get"); |
| 434 | tty_ldisc_assign(tty, &new_ldisc); | 494 | tty_ldisc_assign(tty, new_ldisc); |
| 435 | tty_set_termios_ldisc(tty, N_TTY); | 495 | tty_set_termios_ldisc(tty, N_TTY); |
| 436 | if (new_ldisc.ops->open) { | 496 | r = tty_ldisc_open(tty, new_ldisc); |
| 437 | int r = new_ldisc.ops->open(tty); | 497 | if (r < 0) |
| 438 | if (r < 0) | 498 | panic("Couldn't open N_TTY ldisc for " |
| 439 | panic("Couldn't open N_TTY ldisc for " | 499 | "%s --- error %d.", |
| 440 | "%s --- error %d.", | 500 | tty_name(tty, buf), r); |
| 441 | tty_name(tty, buf), r); | ||
| 442 | } | ||
| 443 | } | 501 | } |
| 444 | } | 502 | } |
| 445 | 503 | ||
| 446 | /** | 504 | /** |
| 505 | * tty_ldisc_halt - shut down the line discipline | ||
| 506 | * @tty: tty device | ||
| 507 | * | ||
| 508 | * Shut down the line discipline and work queue for this tty device. | ||
| 509 | * The TTY_LDISC flag being cleared ensures no further references can | ||
| 510 | * be obtained while the delayed work queue halt ensures that no more | ||
| 511 | * data is fed to the ldisc. | ||
| 512 | * | ||
| 513 | * In order to wait for any existing references to complete see | ||
| 514 | * tty_ldisc_wait_idle. | ||
| 515 | */ | ||
| 516 | |||
| 517 | static int tty_ldisc_halt(struct tty_struct *tty) | ||
| 518 | { | ||
| 519 | clear_bit(TTY_LDISC, &tty->flags); | ||
| 520 | return cancel_delayed_work(&tty->buf.work); | ||
| 521 | } | ||
| 522 | |||
| 523 | /** | ||
| 524 | * tty_ldisc_wait_idle - wait for the ldisc to become idle | ||
| 525 | * @tty: tty to wait for | ||
| 526 | * | ||
| 527 | * Wait for the line discipline to become idle. The discipline must | ||
| 528 | * have been halted for this to guarantee it remains idle. | ||
| 529 | * | ||
| 530 | * tty_ldisc_lock protects the ref counts currently. | ||
| 531 | */ | ||
| 532 | |||
| 533 | static int tty_ldisc_wait_idle(struct tty_struct *tty) | ||
| 534 | { | ||
| 535 | unsigned long flags; | ||
| 536 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
| 537 | while (tty->ldisc->refcount) { | ||
| 538 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 539 | if (wait_event_timeout(tty_ldisc_wait, | ||
| 540 | tty->ldisc->refcount == 0, 5 * HZ) == 0) | ||
| 541 | return -EBUSY; | ||
| 542 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
| 543 | } | ||
| 544 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 545 | return 0; | ||
| 546 | } | ||
| 547 | |||
| 548 | /** | ||
| 447 | * tty_set_ldisc - set line discipline | 549 | * tty_set_ldisc - set line discipline |
| 448 | * @tty: the terminal to set | 550 | * @tty: the terminal to set |
| 449 | * @ldisc: the line discipline | 551 | * @ldisc: the line discipline |
| 450 | * | 552 | * |
| 451 | * Set the discipline of a tty line. Must be called from a process | 553 | * Set the discipline of a tty line. Must be called from a process |
| 452 | * context. | 554 | * context. The ldisc change logic has to protect itself against any |
| 555 | * overlapping ldisc change (including on the other end of pty pairs), | ||
| 556 | * the close of one side of a tty/pty pair, and eventually hangup. | ||
| 453 | * | 557 | * |
| 454 | * Locking: takes tty_ldisc_lock. | 558 | * Locking: takes tty_ldisc_lock, termios_mutex |
| 455 | * called functions take termios_mutex | ||
| 456 | */ | 559 | */ |
| 457 | 560 | ||
| 458 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) | 561 | int tty_set_ldisc(struct tty_struct *tty, int ldisc) |
| 459 | { | 562 | { |
| 460 | int retval; | 563 | int retval; |
| 461 | struct tty_ldisc o_ldisc, new_ldisc; | 564 | struct tty_ldisc *o_ldisc, *new_ldisc; |
| 462 | int work; | 565 | int work, o_work = 0; |
| 463 | unsigned long flags; | ||
| 464 | struct tty_struct *o_tty; | 566 | struct tty_struct *o_tty; |
| 465 | 567 | ||
| 466 | restart: | 568 | new_ldisc = tty_ldisc_get(ldisc); |
| 467 | /* This is a bit ugly for now but means we can break the 'ldisc | 569 | if (IS_ERR(new_ldisc)) |
| 468 | is part of the tty struct' assumption later */ | 570 | return PTR_ERR(new_ldisc); |
| 469 | retval = tty_ldisc_get(ldisc, &new_ldisc); | 571 | |
| 470 | if (retval) | 572 | /* |
| 471 | return retval; | 573 | * We need to look at the tty locking here for pty/tty pairs |
| 574 | * when both sides try to change in parallel. | ||
| 575 | */ | ||
| 576 | |||
| 577 | o_tty = tty->link; /* o_tty is the pty side or NULL */ | ||
| 578 | |||
| 579 | |||
| 580 | /* | ||
| 581 | * Check the no-op case | ||
| 582 | */ | ||
| 583 | |||
| 584 | if (tty->ldisc->ops->num == ldisc) { | ||
| 585 | tty_ldisc_put(new_ldisc); | ||
| 586 | return 0; | ||
| 587 | } | ||
| 472 | 588 | ||
| 473 | /* | 589 | /* |
| 474 | * Problem: What do we do if this blocks ? | 590 | * Problem: What do we do if this blocks ? |
| 591 | * We could deadlock here | ||
| 475 | */ | 592 | */ |
| 476 | 593 | ||
| 477 | tty_wait_until_sent(tty, 0); | 594 | tty_wait_until_sent(tty, 0); |
| 478 | 595 | ||
| 479 | if (tty->ldisc.ops->num == ldisc) { | 596 | mutex_lock(&tty->ldisc_mutex); |
| 480 | tty_ldisc_put(new_ldisc.ops); | 597 | |
| 481 | return 0; | 598 | /* |
| 599 | * We could be midstream of another ldisc change which has | ||
| 600 | * dropped the lock during processing. If so we need to wait. | ||
| 601 | */ | ||
| 602 | |||
| 603 | while (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | ||
| 604 | mutex_unlock(&tty->ldisc_mutex); | ||
| 605 | wait_event(tty_ldisc_wait, | ||
| 606 | test_bit(TTY_LDISC_CHANGING, &tty->flags) == 0); | ||
| 607 | mutex_lock(&tty->ldisc_mutex); | ||
| 482 | } | 608 | } |
| 609 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
| 483 | 610 | ||
| 484 | /* | 611 | /* |
| 485 | * No more input please, we are switching. The new ldisc | 612 | * No more input please, we are switching. The new ldisc |
| @@ -489,8 +616,6 @@ restart: | |||
| 489 | tty->receive_room = 0; | 616 | tty->receive_room = 0; |
| 490 | 617 | ||
| 491 | o_ldisc = tty->ldisc; | 618 | o_ldisc = tty->ldisc; |
| 492 | o_tty = tty->link; | ||
| 493 | |||
| 494 | /* | 619 | /* |
| 495 | * Make sure we don't change while someone holds a | 620 | * Make sure we don't change while someone holds a |
| 496 | * reference to the line discipline. The TTY_LDISC bit | 621 | * reference to the line discipline. The TTY_LDISC bit |
| @@ -501,108 +626,181 @@ restart: | |||
| 501 | * with a userspace app continually trying to use the tty in | 626 | * with a userspace app continually trying to use the tty in |
| 502 | * parallel to the change and re-referencing the tty. | 627 | * parallel to the change and re-referencing the tty. |
| 503 | */ | 628 | */ |
| 504 | clear_bit(TTY_LDISC, &tty->flags); | ||
| 505 | if (o_tty) | ||
| 506 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
| 507 | 629 | ||
| 508 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 630 | work = tty_ldisc_halt(tty); |
| 509 | if (tty->ldisc.refcount || (o_tty && o_tty->ldisc.refcount)) { | ||
| 510 | if (tty->ldisc.refcount) { | ||
| 511 | /* Free the new ldisc we grabbed. Must drop the lock | ||
| 512 | first. */ | ||
| 513 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 514 | tty_ldisc_put(o_ldisc.ops); | ||
| 515 | /* | ||
| 516 | * There are several reasons we may be busy, including | ||
| 517 | * random momentary I/O traffic. We must therefore | ||
| 518 | * retry. We could distinguish between blocking ops | ||
| 519 | * and retries if we made tty_ldisc_wait() smarter. | ||
| 520 | * That is up for discussion. | ||
| 521 | */ | ||
| 522 | if (wait_event_interruptible(tty_ldisc_wait, tty->ldisc.refcount == 0) < 0) | ||
| 523 | return -ERESTARTSYS; | ||
| 524 | goto restart; | ||
| 525 | } | ||
| 526 | if (o_tty && o_tty->ldisc.refcount) { | ||
| 527 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 528 | tty_ldisc_put(o_tty->ldisc.ops); | ||
| 529 | if (wait_event_interruptible(tty_ldisc_wait, o_tty->ldisc.refcount == 0) < 0) | ||
| 530 | return -ERESTARTSYS; | ||
| 531 | goto restart; | ||
| 532 | } | ||
| 533 | } | ||
| 534 | /* | ||
| 535 | * If the TTY_LDISC bit is set, then we are racing against | ||
| 536 | * another ldisc change | ||
| 537 | */ | ||
| 538 | if (test_bit(TTY_LDISC_CHANGING, &tty->flags)) { | ||
| 539 | struct tty_ldisc *ld; | ||
| 540 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 541 | tty_ldisc_put(new_ldisc.ops); | ||
| 542 | ld = tty_ldisc_ref_wait(tty); | ||
| 543 | tty_ldisc_deref(ld); | ||
| 544 | goto restart; | ||
| 545 | } | ||
| 546 | /* | ||
| 547 | * This flag is used to avoid two parallel ldisc changes. Once | ||
| 548 | * open and close are fine grained locked this may work better | ||
| 549 | * as a mutex shared with the open/close/hup paths | ||
| 550 | */ | ||
| 551 | set_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
| 552 | if (o_tty) | 631 | if (o_tty) |
| 553 | set_bit(TTY_LDISC_CHANGING, &o_tty->flags); | 632 | o_work = tty_ldisc_halt(o_tty); |
| 554 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 555 | |||
| 556 | /* | ||
| 557 | * From this point on we know nobody has an ldisc | ||
| 558 | * usage reference, nor can they obtain one until | ||
| 559 | * we say so later on. | ||
| 560 | */ | ||
| 561 | 633 | ||
| 562 | work = cancel_delayed_work(&tty->buf.work); | ||
| 563 | /* | 634 | /* |
| 564 | * Wait for ->hangup_work and ->buf.work handlers to terminate | 635 | * Wait for ->hangup_work and ->buf.work handlers to terminate. |
| 565 | * MUST NOT hold locks here. | 636 | * We must drop the mutex here in case a hangup is also in process. |
| 566 | */ | 637 | */ |
| 638 | |||
| 639 | mutex_unlock(&tty->ldisc_mutex); | ||
| 640 | |||
| 567 | flush_scheduled_work(); | 641 | flush_scheduled_work(); |
| 642 | |||
| 643 | /* Let any existing reference holders finish */ | ||
| 644 | retval = tty_ldisc_wait_idle(tty); | ||
| 645 | if (retval < 0) { | ||
| 646 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
| 647 | tty_ldisc_put(new_ldisc); | ||
| 648 | return retval; | ||
| 649 | } | ||
| 650 | |||
| 651 | mutex_lock(&tty->ldisc_mutex); | ||
| 652 | if (test_bit(TTY_HUPPED, &tty->flags)) { | ||
| 653 | /* We were raced by the hangup method. It will have stomped | ||
| 654 | the ldisc data and closed the ldisc down */ | ||
| 655 | clear_bit(TTY_LDISC_CHANGING, &tty->flags); | ||
| 656 | mutex_unlock(&tty->ldisc_mutex); | ||
| 657 | tty_ldisc_put(new_ldisc); | ||
| 658 | return -EIO; | ||
| 659 | } | ||
| 660 | |||
| 568 | /* Shutdown the current discipline. */ | 661 | /* Shutdown the current discipline. */ |
| 569 | if (o_ldisc.ops->close) | 662 | tty_ldisc_close(tty, o_ldisc); |
| 570 | (o_ldisc.ops->close)(tty); | ||
| 571 | 663 | ||
| 572 | /* Now set up the new line discipline. */ | 664 | /* Now set up the new line discipline. */ |
| 573 | tty_ldisc_assign(tty, &new_ldisc); | 665 | tty_ldisc_assign(tty, new_ldisc); |
| 574 | tty_set_termios_ldisc(tty, ldisc); | 666 | tty_set_termios_ldisc(tty, ldisc); |
| 575 | if (new_ldisc.ops->open) | 667 | |
| 576 | retval = (new_ldisc.ops->open)(tty); | 668 | retval = tty_ldisc_open(tty, new_ldisc); |
| 577 | if (retval < 0) { | 669 | if (retval < 0) { |
| 578 | tty_ldisc_put(new_ldisc.ops); | 670 | /* Back to the old one or N_TTY if we can't */ |
| 579 | tty_ldisc_restore(tty, &o_ldisc); | 671 | tty_ldisc_put(new_ldisc); |
| 672 | tty_ldisc_restore(tty, o_ldisc); | ||
| 580 | } | 673 | } |
| 674 | |||
| 581 | /* At this point we hold a reference to the new ldisc and a | 675 | /* At this point we hold a reference to the new ldisc and a |
| 582 | a reference to the old ldisc. If we ended up flipping back | 676 | a reference to the old ldisc. If we ended up flipping back |
| 583 | to the existing ldisc we have two references to it */ | 677 | to the existing ldisc we have two references to it */ |
| 584 | 678 | ||
| 585 | if (tty->ldisc.ops->num != o_ldisc.ops->num && tty->ops->set_ldisc) | 679 | if (tty->ldisc->ops->num != o_ldisc->ops->num && tty->ops->set_ldisc) |
| 586 | tty->ops->set_ldisc(tty); | 680 | tty->ops->set_ldisc(tty); |
| 587 | 681 | ||
| 588 | tty_ldisc_put(o_ldisc.ops); | 682 | tty_ldisc_put(o_ldisc); |
| 589 | 683 | ||
| 590 | /* | 684 | /* |
| 591 | * Allow ldisc referencing to occur as soon as the driver | 685 | * Allow ldisc referencing to occur again |
| 592 | * ldisc callback completes. | ||
| 593 | */ | 686 | */ |
| 594 | 687 | ||
| 595 | tty_ldisc_enable(tty); | 688 | tty_ldisc_enable(tty); |
| 596 | if (o_tty) | 689 | if (o_tty) |
| 597 | tty_ldisc_enable(o_tty); | 690 | tty_ldisc_enable(o_tty); |
| 598 | 691 | ||
| 599 | /* Restart it in case no characters kick it off. Safe if | 692 | /* Restart the work queue in case no characters kick it off. Safe if |
| 600 | already running */ | 693 | already running */ |
| 601 | if (work) | 694 | if (work) |
| 602 | schedule_delayed_work(&tty->buf.work, 1); | 695 | schedule_delayed_work(&tty->buf.work, 1); |
| 696 | if (o_work) | ||
| 697 | schedule_delayed_work(&o_tty->buf.work, 1); | ||
| 698 | mutex_unlock(&tty->ldisc_mutex); | ||
| 603 | return retval; | 699 | return retval; |
| 604 | } | 700 | } |
| 605 | 701 | ||
| 702 | /** | ||
| 703 | * tty_reset_termios - reset terminal state | ||
| 704 | * @tty: tty to reset | ||
| 705 | * | ||
| 706 | * Restore a terminal to the driver default state. | ||
| 707 | */ | ||
| 708 | |||
| 709 | static void tty_reset_termios(struct tty_struct *tty) | ||
| 710 | { | ||
| 711 | mutex_lock(&tty->termios_mutex); | ||
| 712 | *tty->termios = tty->driver->init_termios; | ||
| 713 | tty->termios->c_ispeed = tty_termios_input_baud_rate(tty->termios); | ||
| 714 | tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios); | ||
| 715 | mutex_unlock(&tty->termios_mutex); | ||
| 716 | } | ||
| 717 | |||
| 718 | |||
| 719 | /** | ||
| 720 | * tty_ldisc_reinit - reinitialise the tty ldisc | ||
| 721 | * @tty: tty to reinit | ||
| 722 | * | ||
| 723 | * Switch the tty back to N_TTY line discipline and leave the | ||
| 724 | * ldisc state closed | ||
| 725 | */ | ||
| 726 | |||
| 727 | static void tty_ldisc_reinit(struct tty_struct *tty) | ||
| 728 | { | ||
| 729 | struct tty_ldisc *ld; | ||
| 730 | |||
| 731 | tty_ldisc_close(tty, tty->ldisc); | ||
| 732 | tty_ldisc_put(tty->ldisc); | ||
| 733 | tty->ldisc = NULL; | ||
| 734 | /* | ||
| 735 | * Switch the line discipline back | ||
| 736 | */ | ||
| 737 | ld = tty_ldisc_get(N_TTY); | ||
| 738 | BUG_ON(IS_ERR(ld)); | ||
| 739 | tty_ldisc_assign(tty, ld); | ||
| 740 | tty_set_termios_ldisc(tty, N_TTY); | ||
| 741 | } | ||
| 742 | |||
| 743 | /** | ||
| 744 | * tty_ldisc_hangup - hangup ldisc reset | ||
| 745 | * @tty: tty being hung up | ||
| 746 | * | ||
| 747 | * Some tty devices reset their termios when they receive a hangup | ||
| 748 | * event. In that situation we must also switch back to N_TTY properly | ||
| 749 | * before we reset the termios data. | ||
| 750 | * | ||
| 751 | * Locking: We can take the ldisc mutex as the rest of the code is | ||
| 752 | * careful to allow for this. | ||
| 753 | * | ||
| 754 | * In the pty pair case this occurs in the close() path of the | ||
| 755 | * tty itself so we must be careful about locking rules. | ||
| 756 | */ | ||
| 757 | |||
| 758 | void tty_ldisc_hangup(struct tty_struct *tty) | ||
| 759 | { | ||
| 760 | struct tty_ldisc *ld; | ||
| 761 | |||
| 762 | /* | ||
| 763 | * FIXME! What are the locking issues here? This may me overdoing | ||
| 764 | * things... This question is especially important now that we've | ||
| 765 | * removed the irqlock. | ||
| 766 | */ | ||
| 767 | ld = tty_ldisc_ref(tty); | ||
| 768 | if (ld != NULL) { | ||
| 769 | /* We may have no line discipline at this point */ | ||
| 770 | if (ld->ops->flush_buffer) | ||
| 771 | ld->ops->flush_buffer(tty); | ||
| 772 | tty_driver_flush_buffer(tty); | ||
| 773 | if ((test_bit(TTY_DO_WRITE_WAKEUP, &tty->flags)) && | ||
| 774 | ld->ops->write_wakeup) | ||
| 775 | ld->ops->write_wakeup(tty); | ||
| 776 | if (ld->ops->hangup) | ||
| 777 | ld->ops->hangup(tty); | ||
| 778 | tty_ldisc_deref(ld); | ||
| 779 | } | ||
| 780 | /* | ||
| 781 | * FIXME: Once we trust the LDISC code better we can wait here for | ||
| 782 | * ldisc completion and fix the driver call race | ||
| 783 | */ | ||
| 784 | wake_up_interruptible_poll(&tty->write_wait, POLLOUT); | ||
| 785 | wake_up_interruptible_poll(&tty->read_wait, POLLIN); | ||
| 786 | /* | ||
| 787 | * Shutdown the current line discipline, and reset it to | ||
| 788 | * N_TTY. | ||
| 789 | */ | ||
| 790 | if (tty->driver->flags & TTY_DRIVER_RESET_TERMIOS) { | ||
| 791 | /* Avoid racing set_ldisc */ | ||
| 792 | mutex_lock(&tty->ldisc_mutex); | ||
| 793 | /* Switch back to N_TTY */ | ||
| 794 | tty_ldisc_reinit(tty); | ||
| 795 | /* At this point we have a closed ldisc and we want to | ||
| 796 | reopen it. We could defer this to the next open but | ||
| 797 | it means auditing a lot of other paths so this is a FIXME */ | ||
| 798 | WARN_ON(tty_ldisc_open(tty, tty->ldisc)); | ||
| 799 | tty_ldisc_enable(tty); | ||
| 800 | mutex_unlock(&tty->ldisc_mutex); | ||
| 801 | tty_reset_termios(tty); | ||
| 802 | } | ||
| 803 | } | ||
| 606 | 804 | ||
| 607 | /** | 805 | /** |
| 608 | * tty_ldisc_setup - open line discipline | 806 | * tty_ldisc_setup - open line discipline |
| @@ -610,24 +808,23 @@ restart: | |||
| 610 | * @o_tty: pair tty for pty/tty pairs | 808 | * @o_tty: pair tty for pty/tty pairs |
| 611 | * | 809 | * |
| 612 | * Called during the initial open of a tty/pty pair in order to set up the | 810 | * Called during the initial open of a tty/pty pair in order to set up the |
| 613 | * line discplines and bind them to the tty. | 811 | * line disciplines and bind them to the tty. This has no locking issues |
| 812 | * as the device isn't yet active. | ||
| 614 | */ | 813 | */ |
| 615 | 814 | ||
| 616 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | 815 | int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) |
| 617 | { | 816 | { |
| 618 | struct tty_ldisc *ld = &tty->ldisc; | 817 | struct tty_ldisc *ld = tty->ldisc; |
| 619 | int retval; | 818 | int retval; |
| 620 | 819 | ||
| 621 | if (ld->ops->open) { | 820 | retval = tty_ldisc_open(tty, ld); |
| 622 | retval = (ld->ops->open)(tty); | 821 | if (retval) |
| 623 | if (retval) | 822 | return retval; |
| 624 | return retval; | 823 | |
| 625 | } | 824 | if (o_tty) { |
| 626 | if (o_tty && o_tty->ldisc.ops->open) { | 825 | retval = tty_ldisc_open(o_tty, o_tty->ldisc); |
| 627 | retval = (o_tty->ldisc.ops->open)(o_tty); | ||
| 628 | if (retval) { | 826 | if (retval) { |
| 629 | if (ld->ops->close) | 827 | tty_ldisc_close(tty, ld); |
| 630 | (ld->ops->close)(tty); | ||
| 631 | return retval; | 828 | return retval; |
| 632 | } | 829 | } |
| 633 | tty_ldisc_enable(o_tty); | 830 | tty_ldisc_enable(o_tty); |
| @@ -635,32 +832,25 @@ int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty) | |||
| 635 | tty_ldisc_enable(tty); | 832 | tty_ldisc_enable(tty); |
| 636 | return 0; | 833 | return 0; |
| 637 | } | 834 | } |
| 638 | |||
| 639 | /** | 835 | /** |
| 640 | * tty_ldisc_release - release line discipline | 836 | * tty_ldisc_release - release line discipline |
| 641 | * @tty: tty being shut down | 837 | * @tty: tty being shut down |
| 642 | * @o_tty: pair tty for pty/tty pairs | 838 | * @o_tty: pair tty for pty/tty pairs |
| 643 | * | 839 | * |
| 644 | * Called during the final close of a tty/pty pair in order to shut down the | 840 | * Called during the final close of a tty/pty pair in order to shut down |
| 645 | * line discpline layer. | 841 | * the line discpline layer. On exit the ldisc assigned is N_TTY and the |
| 842 | * ldisc has not been opened. | ||
| 646 | */ | 843 | */ |
| 647 | 844 | ||
| 648 | void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | 845 | void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) |
| 649 | { | 846 | { |
| 650 | unsigned long flags; | ||
| 651 | struct tty_ldisc ld; | ||
| 652 | /* | 847 | /* |
| 653 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then | 848 | * Prevent flush_to_ldisc() from rescheduling the work for later. Then |
| 654 | * kill any delayed work. As this is the final close it does not | 849 | * kill any delayed work. As this is the final close it does not |
| 655 | * race with the set_ldisc code path. | 850 | * race with the set_ldisc code path. |
| 656 | */ | 851 | */ |
| 657 | clear_bit(TTY_LDISC, &tty->flags); | ||
| 658 | cancel_delayed_work(&tty->buf.work); | ||
| 659 | |||
| 660 | /* | ||
| 661 | * Wait for ->hangup_work and ->buf.work handlers to terminate | ||
| 662 | */ | ||
| 663 | 852 | ||
| 853 | tty_ldisc_halt(tty); | ||
| 664 | flush_scheduled_work(); | 854 | flush_scheduled_work(); |
| 665 | 855 | ||
| 666 | /* | 856 | /* |
| @@ -668,38 +858,19 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
| 668 | * side waiters as the file is closing so user count on the file | 858 | * side waiters as the file is closing so user count on the file |
| 669 | * side is zero. | 859 | * side is zero. |
| 670 | */ | 860 | */ |
| 671 | spin_lock_irqsave(&tty_ldisc_lock, flags); | 861 | |
| 672 | while (tty->ldisc.refcount) { | 862 | tty_ldisc_wait_idle(tty); |
| 673 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | 863 | |
| 674 | wait_event(tty_ldisc_wait, tty->ldisc.refcount == 0); | ||
| 675 | spin_lock_irqsave(&tty_ldisc_lock, flags); | ||
| 676 | } | ||
| 677 | spin_unlock_irqrestore(&tty_ldisc_lock, flags); | ||
| 678 | /* | 864 | /* |
| 679 | * Shutdown the current line discipline, and reset it to N_TTY. | 865 | * Shutdown the current line discipline, and reset it to N_TTY. |
| 680 | * | 866 | * |
| 681 | * FIXME: this MUST get fixed for the new reflocking | 867 | * FIXME: this MUST get fixed for the new reflocking |
| 682 | */ | 868 | */ |
| 683 | if (tty->ldisc.ops->close) | ||
| 684 | (tty->ldisc.ops->close)(tty); | ||
| 685 | tty_ldisc_put(tty->ldisc.ops); | ||
| 686 | 869 | ||
| 687 | /* | 870 | tty_ldisc_reinit(tty); |
| 688 | * Switch the line discipline back | 871 | /* This will need doing differently if we need to lock */ |
| 689 | */ | 872 | if (o_tty) |
| 690 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | 873 | tty_ldisc_release(o_tty, NULL); |
| 691 | tty_ldisc_assign(tty, &ld); | ||
| 692 | tty_set_termios_ldisc(tty, N_TTY); | ||
| 693 | if (o_tty) { | ||
| 694 | /* FIXME: could o_tty be in setldisc here ? */ | ||
| 695 | clear_bit(TTY_LDISC, &o_tty->flags); | ||
| 696 | if (o_tty->ldisc.ops->close) | ||
| 697 | (o_tty->ldisc.ops->close)(o_tty); | ||
| 698 | tty_ldisc_put(o_tty->ldisc.ops); | ||
| 699 | WARN_ON(tty_ldisc_get(N_TTY, &ld)); | ||
| 700 | tty_ldisc_assign(o_tty, &ld); | ||
| 701 | tty_set_termios_ldisc(o_tty, N_TTY); | ||
| 702 | } | ||
| 703 | } | 874 | } |
| 704 | 875 | ||
| 705 | /** | 876 | /** |
| @@ -712,10 +883,10 @@ void tty_ldisc_release(struct tty_struct *tty, struct tty_struct *o_tty) | |||
| 712 | 883 | ||
| 713 | void tty_ldisc_init(struct tty_struct *tty) | 884 | void tty_ldisc_init(struct tty_struct *tty) |
| 714 | { | 885 | { |
| 715 | struct tty_ldisc ld; | 886 | struct tty_ldisc *ld = tty_ldisc_get(N_TTY); |
| 716 | if (tty_ldisc_get(N_TTY, &ld) < 0) | 887 | if (IS_ERR(ld)) |
| 717 | panic("n_tty: init_tty"); | 888 | panic("n_tty: init_tty"); |
| 718 | tty_ldisc_assign(tty, &ld); | 889 | tty_ldisc_assign(tty, ld); |
| 719 | } | 890 | } |
| 720 | 891 | ||
| 721 | void tty_ldisc_begin(void) | 892 | void tty_ldisc_begin(void) |
diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index 9b8004c72686..62dadfc95e34 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c | |||
| @@ -137,7 +137,7 @@ int tty_port_carrier_raised(struct tty_port *port) | |||
| 137 | EXPORT_SYMBOL(tty_port_carrier_raised); | 137 | EXPORT_SYMBOL(tty_port_carrier_raised); |
| 138 | 138 | ||
| 139 | /** | 139 | /** |
| 140 | * tty_port_raise_dtr_rts - Riase DTR/RTS | 140 | * tty_port_raise_dtr_rts - Raise DTR/RTS |
| 141 | * @port: tty port | 141 | * @port: tty port |
| 142 | * | 142 | * |
| 143 | * Wrapper for the DTR/RTS raise logic. For the moment this is used | 143 | * Wrapper for the DTR/RTS raise logic. For the moment this is used |
| @@ -147,12 +147,28 @@ EXPORT_SYMBOL(tty_port_carrier_raised); | |||
| 147 | 147 | ||
| 148 | void tty_port_raise_dtr_rts(struct tty_port *port) | 148 | void tty_port_raise_dtr_rts(struct tty_port *port) |
| 149 | { | 149 | { |
| 150 | if (port->ops->raise_dtr_rts) | 150 | if (port->ops->dtr_rts) |
| 151 | port->ops->raise_dtr_rts(port); | 151 | port->ops->dtr_rts(port, 1); |
| 152 | } | 152 | } |
| 153 | EXPORT_SYMBOL(tty_port_raise_dtr_rts); | 153 | EXPORT_SYMBOL(tty_port_raise_dtr_rts); |
| 154 | 154 | ||
| 155 | /** | 155 | /** |
| 156 | * tty_port_lower_dtr_rts - Lower DTR/RTS | ||
| 157 | * @port: tty port | ||
| 158 | * | ||
| 159 | * Wrapper for the DTR/RTS raise logic. For the moment this is used | ||
| 160 | * to hide some internal details. This will eventually become entirely | ||
| 161 | * internal to the tty port. | ||
| 162 | */ | ||
| 163 | |||
| 164 | void tty_port_lower_dtr_rts(struct tty_port *port) | ||
| 165 | { | ||
| 166 | if (port->ops->dtr_rts) | ||
| 167 | port->ops->dtr_rts(port, 0); | ||
| 168 | } | ||
| 169 | EXPORT_SYMBOL(tty_port_lower_dtr_rts); | ||
| 170 | |||
| 171 | /** | ||
| 156 | * tty_port_block_til_ready - Waiting logic for tty open | 172 | * tty_port_block_til_ready - Waiting logic for tty open |
| 157 | * @port: the tty port being opened | 173 | * @port: the tty port being opened |
| 158 | * @tty: the tty device being bound | 174 | * @tty: the tty device being bound |
| @@ -167,7 +183,7 @@ EXPORT_SYMBOL(tty_port_raise_dtr_rts); | |||
| 167 | * - port flags and counts | 183 | * - port flags and counts |
| 168 | * | 184 | * |
| 169 | * The passed tty_port must implement the carrier_raised method if it can | 185 | * The passed tty_port must implement the carrier_raised method if it can |
| 170 | * do carrier detect and the raise_dtr_rts method if it supports software | 186 | * do carrier detect and the dtr_rts method if it supports software |
| 171 | * management of these lines. Note that the dtr/rts raise is done each | 187 | * management of these lines. Note that the dtr/rts raise is done each |
| 172 | * iteration as a hangup may have previously dropped them while we wait. | 188 | * iteration as a hangup may have previously dropped them while we wait. |
| 173 | */ | 189 | */ |
| @@ -182,7 +198,8 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 182 | 198 | ||
| 183 | /* block if port is in the process of being closed */ | 199 | /* block if port is in the process of being closed */ |
| 184 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { | 200 | if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) { |
| 185 | interruptible_sleep_on(&port->close_wait); | 201 | wait_event_interruptible(port->close_wait, |
| 202 | !(port->flags & ASYNC_CLOSING)); | ||
| 186 | if (port->flags & ASYNC_HUP_NOTIFY) | 203 | if (port->flags & ASYNC_HUP_NOTIFY) |
| 187 | return -EAGAIN; | 204 | return -EAGAIN; |
| 188 | else | 205 | else |
| @@ -205,7 +222,6 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 205 | before the next open may complete */ | 222 | before the next open may complete */ |
| 206 | 223 | ||
| 207 | retval = 0; | 224 | retval = 0; |
| 208 | add_wait_queue(&port->open_wait, &wait); | ||
| 209 | 225 | ||
| 210 | /* The port lock protects the port counts */ | 226 | /* The port lock protects the port counts */ |
| 211 | spin_lock_irqsave(&port->lock, flags); | 227 | spin_lock_irqsave(&port->lock, flags); |
| @@ -219,7 +235,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 219 | if (tty->termios->c_cflag & CBAUD) | 235 | if (tty->termios->c_cflag & CBAUD) |
| 220 | tty_port_raise_dtr_rts(port); | 236 | tty_port_raise_dtr_rts(port); |
| 221 | 237 | ||
| 222 | set_current_state(TASK_INTERRUPTIBLE); | 238 | prepare_to_wait(&port->open_wait, &wait, TASK_INTERRUPTIBLE); |
| 223 | /* Check for a hangup or uninitialised port. Return accordingly */ | 239 | /* Check for a hangup or uninitialised port. Return accordingly */ |
| 224 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { | 240 | if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)) { |
| 225 | if (port->flags & ASYNC_HUP_NOTIFY) | 241 | if (port->flags & ASYNC_HUP_NOTIFY) |
| @@ -240,8 +256,7 @@ int tty_port_block_til_ready(struct tty_port *port, | |||
| 240 | } | 256 | } |
| 241 | schedule(); | 257 | schedule(); |
| 242 | } | 258 | } |
| 243 | set_current_state(TASK_RUNNING); | 259 | finish_wait(&port->open_wait, &wait); |
| 244 | remove_wait_queue(&port->open_wait, &wait); | ||
| 245 | 260 | ||
| 246 | /* Update counts. A parallel hangup will have set count to zero and | 261 | /* Update counts. A parallel hangup will have set count to zero and |
| 247 | we must not mess that up further */ | 262 | we must not mess that up further */ |
| @@ -292,6 +307,17 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f | |||
| 292 | if (port->flags & ASYNC_INITIALIZED && | 307 | if (port->flags & ASYNC_INITIALIZED && |
| 293 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) | 308 | port->closing_wait != ASYNC_CLOSING_WAIT_NONE) |
| 294 | tty_wait_until_sent(tty, port->closing_wait); | 309 | tty_wait_until_sent(tty, port->closing_wait); |
| 310 | if (port->drain_delay) { | ||
| 311 | unsigned int bps = tty_get_baud_rate(tty); | ||
| 312 | long timeout; | ||
| 313 | |||
| 314 | if (bps > 1200) | ||
| 315 | timeout = max_t(long, (HZ * 10 * port->drain_delay) / bps, | ||
| 316 | HZ / 10); | ||
| 317 | else | ||
| 318 | timeout = 2 * HZ; | ||
| 319 | schedule_timeout_interruptible(timeout); | ||
| 320 | } | ||
| 295 | return 1; | 321 | return 1; |
| 296 | } | 322 | } |
| 297 | EXPORT_SYMBOL(tty_port_close_start); | 323 | EXPORT_SYMBOL(tty_port_close_start); |
| @@ -302,6 +328,9 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty) | |||
| 302 | 328 | ||
| 303 | tty_ldisc_flush(tty); | 329 | tty_ldisc_flush(tty); |
| 304 | 330 | ||
| 331 | if (tty->termios->c_cflag & HUPCL) | ||
| 332 | tty_port_lower_dtr_rts(port); | ||
| 333 | |||
| 305 | spin_lock_irqsave(&port->lock, flags); | 334 | spin_lock_irqsave(&port->lock, flags); |
| 306 | tty->closing = 0; | 335 | tty->closing = 0; |
| 307 | 336 | ||
diff --git a/drivers/char/vt.c b/drivers/char/vt.c index 08151d4de489..de9ebee8657b 100644 --- a/drivers/char/vt.c +++ b/drivers/char/vt.c | |||
| @@ -95,7 +95,6 @@ | |||
| 95 | #include <linux/timer.h> | 95 | #include <linux/timer.h> |
| 96 | #include <linux/interrupt.h> | 96 | #include <linux/interrupt.h> |
| 97 | #include <linux/workqueue.h> | 97 | #include <linux/workqueue.h> |
| 98 | #include <linux/bootmem.h> | ||
| 99 | #include <linux/pm.h> | 98 | #include <linux/pm.h> |
| 100 | #include <linux/font.h> | 99 | #include <linux/font.h> |
| 101 | #include <linux/bitops.h> | 100 | #include <linux/bitops.h> |
| @@ -104,6 +103,7 @@ | |||
| 104 | #include <linux/io.h> | 103 | #include <linux/io.h> |
| 105 | #include <asm/system.h> | 104 | #include <asm/system.h> |
| 106 | #include <linux/uaccess.h> | 105 | #include <linux/uaccess.h> |
| 106 | #include <linux/kmemleak.h> | ||
| 107 | 107 | ||
| 108 | #define MAX_NR_CON_DRIVER 16 | 108 | #define MAX_NR_CON_DRIVER 16 |
| 109 | 109 | ||
| @@ -2875,14 +2875,11 @@ static int __init con_init(void) | |||
| 2875 | mod_timer(&console_timer, jiffies + blankinterval); | 2875 | mod_timer(&console_timer, jiffies + blankinterval); |
| 2876 | } | 2876 | } |
| 2877 | 2877 | ||
| 2878 | /* | ||
| 2879 | * kmalloc is not running yet - we use the bootmem allocator. | ||
| 2880 | */ | ||
| 2881 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { | 2878 | for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { |
| 2882 | vc_cons[currcons].d = vc = alloc_bootmem(sizeof(struct vc_data)); | 2879 | vc_cons[currcons].d = vc = kzalloc(sizeof(struct vc_data), GFP_NOWAIT); |
| 2883 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); | 2880 | INIT_WORK(&vc_cons[currcons].SAK_work, vc_SAK); |
| 2884 | visual_init(vc, currcons, 1); | 2881 | visual_init(vc, currcons, 1); |
| 2885 | vc->vc_screenbuf = (unsigned short *)alloc_bootmem(vc->vc_screenbuf_size); | 2882 | vc->vc_screenbuf = kzalloc(vc->vc_screenbuf_size, GFP_NOWAIT); |
| 2886 | vc->vc_kmalloced = 0; | 2883 | vc->vc_kmalloced = 0; |
| 2887 | vc_init(vc, vc->vc_rows, vc->vc_cols, | 2884 | vc_init(vc, vc->vc_rows, vc->vc_cols, |
| 2888 | currcons || !vc->vc_sw->con_save_screen); | 2885 | currcons || !vc->vc_sw->con_save_screen); |
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index 1efb2879a94f..eef216f7f61d 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile | |||
| @@ -3,3 +3,5 @@ obj-$(CONFIG_X86_CYCLONE_TIMER) += cyclone.o | |||
| 3 | obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o | 3 | obj-$(CONFIG_X86_PM_TIMER) += acpi_pm.o |
| 4 | obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o | 4 | obj-$(CONFIG_SCx200HR_TIMER) += scx200_hrt.o |
| 5 | obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o | 5 | obj-$(CONFIG_SH_TIMER_CMT) += sh_cmt.o |
| 6 | obj-$(CONFIG_SH_TIMER_MTU2) += sh_mtu2.o | ||
| 7 | obj-$(CONFIG_SH_TIMER_TMU) += sh_tmu.o | ||
diff --git a/drivers/clocksource/sh_cmt.c b/drivers/clocksource/sh_cmt.c index 1c92c39a53aa..cf56a2af5fe1 100644 --- a/drivers/clocksource/sh_cmt.c +++ b/drivers/clocksource/sh_cmt.c | |||
| @@ -18,7 +18,6 @@ | |||
| 18 | */ | 18 | */ |
| 19 | 19 | ||
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <linux/bootmem.h> | ||
| 22 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
| 23 | #include <linux/spinlock.h> | 22 | #include <linux/spinlock.h> |
| 24 | #include <linux/interrupt.h> | 23 | #include <linux/interrupt.h> |
| @@ -29,7 +28,7 @@ | |||
| 29 | #include <linux/err.h> | 28 | #include <linux/err.h> |
| 30 | #include <linux/clocksource.h> | 29 | #include <linux/clocksource.h> |
| 31 | #include <linux/clockchips.h> | 30 | #include <linux/clockchips.h> |
| 32 | #include <linux/sh_cmt.h> | 31 | #include <linux/sh_timer.h> |
| 33 | 32 | ||
| 34 | struct sh_cmt_priv { | 33 | struct sh_cmt_priv { |
| 35 | void __iomem *mapbase; | 34 | void __iomem *mapbase; |
| @@ -47,6 +46,7 @@ struct sh_cmt_priv { | |||
| 47 | unsigned long rate; | 46 | unsigned long rate; |
| 48 | spinlock_t lock; | 47 | spinlock_t lock; |
| 49 | struct clock_event_device ced; | 48 | struct clock_event_device ced; |
| 49 | struct clocksource cs; | ||
| 50 | unsigned long total_cycles; | 50 | unsigned long total_cycles; |
| 51 | }; | 51 | }; |
| 52 | 52 | ||
| @@ -59,7 +59,7 @@ static DEFINE_SPINLOCK(sh_cmt_lock); | |||
| 59 | 59 | ||
| 60 | static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr) | 60 | static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr) |
| 61 | { | 61 | { |
| 62 | struct sh_cmt_config *cfg = p->pdev->dev.platform_data; | 62 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
| 63 | void __iomem *base = p->mapbase; | 63 | void __iomem *base = p->mapbase; |
| 64 | unsigned long offs; | 64 | unsigned long offs; |
| 65 | 65 | ||
| @@ -83,7 +83,7 @@ static inline unsigned long sh_cmt_read(struct sh_cmt_priv *p, int reg_nr) | |||
| 83 | static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr, | 83 | static inline void sh_cmt_write(struct sh_cmt_priv *p, int reg_nr, |
| 84 | unsigned long value) | 84 | unsigned long value) |
| 85 | { | 85 | { |
| 86 | struct sh_cmt_config *cfg = p->pdev->dev.platform_data; | 86 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
| 87 | void __iomem *base = p->mapbase; | 87 | void __iomem *base = p->mapbase; |
| 88 | unsigned long offs; | 88 | unsigned long offs; |
| 89 | 89 | ||
| @@ -110,23 +110,28 @@ static unsigned long sh_cmt_get_counter(struct sh_cmt_priv *p, | |||
| 110 | int *has_wrapped) | 110 | int *has_wrapped) |
| 111 | { | 111 | { |
| 112 | unsigned long v1, v2, v3; | 112 | unsigned long v1, v2, v3; |
| 113 | int o1, o2; | ||
| 114 | |||
| 115 | o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit; | ||
| 113 | 116 | ||
| 114 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ | 117 | /* Make sure the timer value is stable. Stolen from acpi_pm.c */ |
| 115 | do { | 118 | do { |
| 119 | o2 = o1; | ||
| 116 | v1 = sh_cmt_read(p, CMCNT); | 120 | v1 = sh_cmt_read(p, CMCNT); |
| 117 | v2 = sh_cmt_read(p, CMCNT); | 121 | v2 = sh_cmt_read(p, CMCNT); |
| 118 | v3 = sh_cmt_read(p, CMCNT); | 122 | v3 = sh_cmt_read(p, CMCNT); |
| 119 | } while (unlikely((v1 > v2 && v1 < v3) || (v2 > v3 && v2 < v1) | 123 | o1 = sh_cmt_read(p, CMCSR) & p->overflow_bit; |
| 120 | || (v3 > v1 && v3 < v2))); | 124 | } while (unlikely((o1 != o2) || (v1 > v2 && v1 < v3) |
| 125 | || (v2 > v3 && v2 < v1) || (v3 > v1 && v3 < v2))); | ||
| 121 | 126 | ||
| 122 | *has_wrapped = sh_cmt_read(p, CMCSR) & p->overflow_bit; | 127 | *has_wrapped = o1; |
| 123 | return v2; | 128 | return v2; |
| 124 | } | 129 | } |
| 125 | 130 | ||
| 126 | 131 | ||
| 127 | static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | 132 | static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) |
| 128 | { | 133 | { |
| 129 | struct sh_cmt_config *cfg = p->pdev->dev.platform_data; | 134 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
| 130 | unsigned long flags, value; | 135 | unsigned long flags, value; |
| 131 | 136 | ||
| 132 | /* start stop register shared by multiple timer channels */ | 137 | /* start stop register shared by multiple timer channels */ |
| @@ -144,7 +149,7 @@ static void sh_cmt_start_stop_ch(struct sh_cmt_priv *p, int start) | |||
| 144 | 149 | ||
| 145 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | 150 | static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) |
| 146 | { | 151 | { |
| 147 | struct sh_cmt_config *cfg = p->pdev->dev.platform_data; | 152 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; |
| 148 | int ret; | 153 | int ret; |
| 149 | 154 | ||
| 150 | /* enable clock */ | 155 | /* enable clock */ |
| @@ -153,16 +158,18 @@ static int sh_cmt_enable(struct sh_cmt_priv *p, unsigned long *rate) | |||
| 153 | pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); | 158 | pr_err("sh_cmt: cannot enable clock \"%s\"\n", cfg->clk); |
| 154 | return ret; | 159 | return ret; |
| 155 | } | 160 | } |
| 156 | *rate = clk_get_rate(p->clk) / 8; | ||
| 157 | 161 | ||
| 158 | /* make sure channel is disabled */ | 162 | /* make sure channel is disabled */ |
| 159 | sh_cmt_start_stop_ch(p, 0); | 163 | sh_cmt_start_stop_ch(p, 0); |
| 160 | 164 | ||
| 161 | /* configure channel, periodic mode and maximum timeout */ | 165 | /* configure channel, periodic mode and maximum timeout */ |
| 162 | if (p->width == 16) | 166 | if (p->width == 16) { |
| 163 | sh_cmt_write(p, CMCSR, 0); | 167 | *rate = clk_get_rate(p->clk) / 512; |
| 164 | else | 168 | sh_cmt_write(p, CMCSR, 0x43); |
| 169 | } else { | ||
| 170 | *rate = clk_get_rate(p->clk) / 8; | ||
| 165 | sh_cmt_write(p, CMCSR, 0x01a4); | 171 | sh_cmt_write(p, CMCSR, 0x01a4); |
| 172 | } | ||
| 166 | 173 | ||
| 167 | sh_cmt_write(p, CMCOR, 0xffffffff); | 174 | sh_cmt_write(p, CMCOR, 0xffffffff); |
| 168 | sh_cmt_write(p, CMCNT, 0); | 175 | sh_cmt_write(p, CMCNT, 0); |
| @@ -376,6 +383,68 @@ static void sh_cmt_stop(struct sh_cmt_priv *p, unsigned long flag) | |||
| 376 | spin_unlock_irqrestore(&p->lock, flags); | 383 | spin_unlock_irqrestore(&p->lock, flags); |
| 377 | } | 384 | } |
| 378 | 385 | ||
| 386 | static struct sh_cmt_priv *cs_to_sh_cmt(struct clocksource *cs) | ||
| 387 | { | ||
| 388 | return container_of(cs, struct sh_cmt_priv, cs); | ||
| 389 | } | ||
| 390 | |||
| 391 | static cycle_t sh_cmt_clocksource_read(struct clocksource *cs) | ||
| 392 | { | ||
| 393 | struct sh_cmt_priv *p = cs_to_sh_cmt(cs); | ||
| 394 | unsigned long flags, raw; | ||
| 395 | unsigned long value; | ||
| 396 | int has_wrapped; | ||
| 397 | |||
| 398 | spin_lock_irqsave(&p->lock, flags); | ||
| 399 | value = p->total_cycles; | ||
| 400 | raw = sh_cmt_get_counter(p, &has_wrapped); | ||
| 401 | |||
| 402 | if (unlikely(has_wrapped)) | ||
| 403 | raw += p->match_value; | ||
| 404 | spin_unlock_irqrestore(&p->lock, flags); | ||
| 405 | |||
| 406 | return value + raw; | ||
| 407 | } | ||
| 408 | |||
| 409 | static int sh_cmt_clocksource_enable(struct clocksource *cs) | ||
| 410 | { | ||
| 411 | struct sh_cmt_priv *p = cs_to_sh_cmt(cs); | ||
| 412 | int ret; | ||
| 413 | |||
| 414 | p->total_cycles = 0; | ||
| 415 | |||
| 416 | ret = sh_cmt_start(p, FLAG_CLOCKSOURCE); | ||
| 417 | if (ret) | ||
| 418 | return ret; | ||
| 419 | |||
| 420 | /* TODO: calculate good shift from rate and counter bit width */ | ||
| 421 | cs->shift = 0; | ||
| 422 | cs->mult = clocksource_hz2mult(p->rate, cs->shift); | ||
| 423 | return 0; | ||
| 424 | } | ||
| 425 | |||
| 426 | static void sh_cmt_clocksource_disable(struct clocksource *cs) | ||
| 427 | { | ||
| 428 | sh_cmt_stop(cs_to_sh_cmt(cs), FLAG_CLOCKSOURCE); | ||
| 429 | } | ||
| 430 | |||
| 431 | static int sh_cmt_register_clocksource(struct sh_cmt_priv *p, | ||
| 432 | char *name, unsigned long rating) | ||
| 433 | { | ||
| 434 | struct clocksource *cs = &p->cs; | ||
| 435 | |||
| 436 | cs->name = name; | ||
| 437 | cs->rating = rating; | ||
| 438 | cs->read = sh_cmt_clocksource_read; | ||
| 439 | cs->enable = sh_cmt_clocksource_enable; | ||
| 440 | cs->disable = sh_cmt_clocksource_disable; | ||
| 441 | cs->mask = CLOCKSOURCE_MASK(sizeof(unsigned long) * 8); | ||
| 442 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
| 443 | pr_info("sh_cmt: %s used as clock source\n", cs->name); | ||
| 444 | clocksource_register(cs); | ||
| 445 | return 0; | ||
| 446 | } | ||
| 447 | |||
| 379 | static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced) | 448 | static struct sh_cmt_priv *ced_to_sh_cmt(struct clock_event_device *ced) |
| 380 | { | 449 | { |
| 381 | return container_of(ced, struct sh_cmt_priv, ced); | 450 | return container_of(ced, struct sh_cmt_priv, ced); |
| @@ -468,9 +537,9 @@ static void sh_cmt_register_clockevent(struct sh_cmt_priv *p, | |||
| 468 | clockevents_register_device(ced); | 537 | clockevents_register_device(ced); |
| 469 | } | 538 | } |
| 470 | 539 | ||
| 471 | int sh_cmt_register(struct sh_cmt_priv *p, char *name, | 540 | static int sh_cmt_register(struct sh_cmt_priv *p, char *name, |
| 472 | unsigned long clockevent_rating, | 541 | unsigned long clockevent_rating, |
| 473 | unsigned long clocksource_rating) | 542 | unsigned long clocksource_rating) |
| 474 | { | 543 | { |
| 475 | if (p->width == (sizeof(p->max_match_value) * 8)) | 544 | if (p->width == (sizeof(p->max_match_value) * 8)) |
| 476 | p->max_match_value = ~0; | 545 | p->max_match_value = ~0; |
| @@ -483,12 +552,15 @@ int sh_cmt_register(struct sh_cmt_priv *p, char *name, | |||
| 483 | if (clockevent_rating) | 552 | if (clockevent_rating) |
| 484 | sh_cmt_register_clockevent(p, name, clockevent_rating); | 553 | sh_cmt_register_clockevent(p, name, clockevent_rating); |
| 485 | 554 | ||
| 555 | if (clocksource_rating) | ||
| 556 | sh_cmt_register_clocksource(p, name, clocksource_rating); | ||
| 557 | |||
| 486 | return 0; | 558 | return 0; |
| 487 | } | 559 | } |
| 488 | 560 | ||
| 489 | static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | 561 | static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) |
| 490 | { | 562 | { |
| 491 | struct sh_cmt_config *cfg = pdev->dev.platform_data; | 563 | struct sh_timer_config *cfg = pdev->dev.platform_data; |
| 492 | struct resource *res; | 564 | struct resource *res; |
| 493 | int irq, ret; | 565 | int irq, ret; |
| 494 | ret = -ENXIO; | 566 | ret = -ENXIO; |
| @@ -545,7 +617,7 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
| 545 | if (resource_size(res) == 6) { | 617 | if (resource_size(res) == 6) { |
| 546 | p->width = 16; | 618 | p->width = 16; |
| 547 | p->overflow_bit = 0x80; | 619 | p->overflow_bit = 0x80; |
| 548 | p->clear_bits = ~0xc0; | 620 | p->clear_bits = ~0x80; |
| 549 | } else { | 621 | } else { |
| 550 | p->width = 32; | 622 | p->width = 32; |
| 551 | p->overflow_bit = 0x8000; | 623 | p->overflow_bit = 0x8000; |
| @@ -566,8 +638,14 @@ static int sh_cmt_setup(struct sh_cmt_priv *p, struct platform_device *pdev) | |||
| 566 | static int __devinit sh_cmt_probe(struct platform_device *pdev) | 638 | static int __devinit sh_cmt_probe(struct platform_device *pdev) |
| 567 | { | 639 | { |
| 568 | struct sh_cmt_priv *p = platform_get_drvdata(pdev); | 640 | struct sh_cmt_priv *p = platform_get_drvdata(pdev); |
| 641 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 569 | int ret; | 642 | int ret; |
| 570 | 643 | ||
| 644 | if (p) { | ||
| 645 | pr_info("sh_cmt: %s kept as earlytimer\n", cfg->name); | ||
| 646 | return 0; | ||
| 647 | } | ||
| 648 | |||
| 571 | p = kmalloc(sizeof(*p), GFP_KERNEL); | 649 | p = kmalloc(sizeof(*p), GFP_KERNEL); |
| 572 | if (p == NULL) { | 650 | if (p == NULL) { |
| 573 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | 651 | dev_err(&pdev->dev, "failed to allocate driver data\n"); |
| @@ -577,7 +655,6 @@ static int __devinit sh_cmt_probe(struct platform_device *pdev) | |||
| 577 | ret = sh_cmt_setup(p, pdev); | 655 | ret = sh_cmt_setup(p, pdev); |
| 578 | if (ret) { | 656 | if (ret) { |
| 579 | kfree(p); | 657 | kfree(p); |
| 580 | |||
| 581 | platform_set_drvdata(pdev, NULL); | 658 | platform_set_drvdata(pdev, NULL); |
| 582 | } | 659 | } |
| 583 | return ret; | 660 | return ret; |
| @@ -606,6 +683,7 @@ static void __exit sh_cmt_exit(void) | |||
| 606 | platform_driver_unregister(&sh_cmt_device_driver); | 683 | platform_driver_unregister(&sh_cmt_device_driver); |
| 607 | } | 684 | } |
| 608 | 685 | ||
| 686 | early_platform_init("earlytimer", &sh_cmt_device_driver); | ||
| 609 | module_init(sh_cmt_init); | 687 | module_init(sh_cmt_init); |
| 610 | module_exit(sh_cmt_exit); | 688 | module_exit(sh_cmt_exit); |
| 611 | 689 | ||
diff --git a/drivers/clocksource/sh_mtu2.c b/drivers/clocksource/sh_mtu2.c new file mode 100644 index 000000000000..d1ae75454d10 --- /dev/null +++ b/drivers/clocksource/sh_mtu2.c | |||
| @@ -0,0 +1,357 @@ | |||
| 1 | /* | ||
| 2 | * SuperH Timer Support - MTU2 | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Magnus Damm | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/clk.h> | ||
| 28 | #include <linux/irq.h> | ||
| 29 | #include <linux/err.h> | ||
| 30 | #include <linux/clockchips.h> | ||
| 31 | #include <linux/sh_timer.h> | ||
| 32 | |||
| 33 | struct sh_mtu2_priv { | ||
| 34 | void __iomem *mapbase; | ||
| 35 | struct clk *clk; | ||
| 36 | struct irqaction irqaction; | ||
| 37 | struct platform_device *pdev; | ||
| 38 | unsigned long rate; | ||
| 39 | unsigned long periodic; | ||
| 40 | struct clock_event_device ced; | ||
| 41 | }; | ||
| 42 | |||
| 43 | static DEFINE_SPINLOCK(sh_mtu2_lock); | ||
| 44 | |||
| 45 | #define TSTR -1 /* shared register */ | ||
| 46 | #define TCR 0 /* channel register */ | ||
| 47 | #define TMDR 1 /* channel register */ | ||
| 48 | #define TIOR 2 /* channel register */ | ||
| 49 | #define TIER 3 /* channel register */ | ||
| 50 | #define TSR 4 /* channel register */ | ||
| 51 | #define TCNT 5 /* channel register */ | ||
| 52 | #define TGR 6 /* channel register */ | ||
| 53 | |||
| 54 | static unsigned long mtu2_reg_offs[] = { | ||
| 55 | [TCR] = 0, | ||
| 56 | [TMDR] = 1, | ||
| 57 | [TIOR] = 2, | ||
| 58 | [TIER] = 4, | ||
| 59 | [TSR] = 5, | ||
| 60 | [TCNT] = 6, | ||
| 61 | [TGR] = 8, | ||
| 62 | }; | ||
| 63 | |||
| 64 | static inline unsigned long sh_mtu2_read(struct sh_mtu2_priv *p, int reg_nr) | ||
| 65 | { | ||
| 66 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 67 | void __iomem *base = p->mapbase; | ||
| 68 | unsigned long offs; | ||
| 69 | |||
| 70 | if (reg_nr == TSTR) | ||
| 71 | return ioread8(base + cfg->channel_offset); | ||
| 72 | |||
| 73 | offs = mtu2_reg_offs[reg_nr]; | ||
| 74 | |||
| 75 | if ((reg_nr == TCNT) || (reg_nr == TGR)) | ||
| 76 | return ioread16(base + offs); | ||
| 77 | else | ||
| 78 | return ioread8(base + offs); | ||
| 79 | } | ||
| 80 | |||
| 81 | static inline void sh_mtu2_write(struct sh_mtu2_priv *p, int reg_nr, | ||
| 82 | unsigned long value) | ||
| 83 | { | ||
| 84 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 85 | void __iomem *base = p->mapbase; | ||
| 86 | unsigned long offs; | ||
| 87 | |||
| 88 | if (reg_nr == TSTR) { | ||
| 89 | iowrite8(value, base + cfg->channel_offset); | ||
| 90 | return; | ||
| 91 | } | ||
| 92 | |||
| 93 | offs = mtu2_reg_offs[reg_nr]; | ||
| 94 | |||
| 95 | if ((reg_nr == TCNT) || (reg_nr == TGR)) | ||
| 96 | iowrite16(value, base + offs); | ||
| 97 | else | ||
| 98 | iowrite8(value, base + offs); | ||
| 99 | } | ||
| 100 | |||
| 101 | static void sh_mtu2_start_stop_ch(struct sh_mtu2_priv *p, int start) | ||
| 102 | { | ||
| 103 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 104 | unsigned long flags, value; | ||
| 105 | |||
| 106 | /* start stop register shared by multiple timer channels */ | ||
| 107 | spin_lock_irqsave(&sh_mtu2_lock, flags); | ||
| 108 | value = sh_mtu2_read(p, TSTR); | ||
| 109 | |||
| 110 | if (start) | ||
| 111 | value |= 1 << cfg->timer_bit; | ||
| 112 | else | ||
| 113 | value &= ~(1 << cfg->timer_bit); | ||
| 114 | |||
| 115 | sh_mtu2_write(p, TSTR, value); | ||
| 116 | spin_unlock_irqrestore(&sh_mtu2_lock, flags); | ||
| 117 | } | ||
| 118 | |||
| 119 | static int sh_mtu2_enable(struct sh_mtu2_priv *p) | ||
| 120 | { | ||
| 121 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 122 | int ret; | ||
| 123 | |||
| 124 | /* enable clock */ | ||
| 125 | ret = clk_enable(p->clk); | ||
| 126 | if (ret) { | ||
| 127 | pr_err("sh_mtu2: cannot enable clock \"%s\"\n", cfg->clk); | ||
| 128 | return ret; | ||
| 129 | } | ||
| 130 | |||
| 131 | /* make sure channel is disabled */ | ||
| 132 | sh_mtu2_start_stop_ch(p, 0); | ||
| 133 | |||
| 134 | p->rate = clk_get_rate(p->clk) / 64; | ||
| 135 | p->periodic = (p->rate + HZ/2) / HZ; | ||
| 136 | |||
| 137 | /* "Periodic Counter Operation" */ | ||
| 138 | sh_mtu2_write(p, TCR, 0x23); /* TGRA clear, divide clock by 64 */ | ||
| 139 | sh_mtu2_write(p, TIOR, 0); | ||
| 140 | sh_mtu2_write(p, TGR, p->periodic); | ||
| 141 | sh_mtu2_write(p, TCNT, 0); | ||
| 142 | sh_mtu2_write(p, TMDR, 0); | ||
| 143 | sh_mtu2_write(p, TIER, 0x01); | ||
| 144 | |||
| 145 | /* enable channel */ | ||
| 146 | sh_mtu2_start_stop_ch(p, 1); | ||
| 147 | |||
| 148 | return 0; | ||
| 149 | } | ||
| 150 | |||
| 151 | static void sh_mtu2_disable(struct sh_mtu2_priv *p) | ||
| 152 | { | ||
| 153 | /* disable channel */ | ||
| 154 | sh_mtu2_start_stop_ch(p, 0); | ||
| 155 | |||
| 156 | /* stop clock */ | ||
| 157 | clk_disable(p->clk); | ||
| 158 | } | ||
| 159 | |||
| 160 | static irqreturn_t sh_mtu2_interrupt(int irq, void *dev_id) | ||
| 161 | { | ||
| 162 | struct sh_mtu2_priv *p = dev_id; | ||
| 163 | |||
| 164 | /* acknowledge interrupt */ | ||
| 165 | sh_mtu2_read(p, TSR); | ||
| 166 | sh_mtu2_write(p, TSR, 0xfe); | ||
| 167 | |||
| 168 | /* notify clockevent layer */ | ||
| 169 | p->ced.event_handler(&p->ced); | ||
| 170 | return IRQ_HANDLED; | ||
| 171 | } | ||
| 172 | |||
| 173 | static struct sh_mtu2_priv *ced_to_sh_mtu2(struct clock_event_device *ced) | ||
| 174 | { | ||
| 175 | return container_of(ced, struct sh_mtu2_priv, ced); | ||
| 176 | } | ||
| 177 | |||
| 178 | static void sh_mtu2_clock_event_mode(enum clock_event_mode mode, | ||
| 179 | struct clock_event_device *ced) | ||
| 180 | { | ||
| 181 | struct sh_mtu2_priv *p = ced_to_sh_mtu2(ced); | ||
| 182 | int disabled = 0; | ||
| 183 | |||
| 184 | /* deal with old setting first */ | ||
| 185 | switch (ced->mode) { | ||
| 186 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 187 | sh_mtu2_disable(p); | ||
| 188 | disabled = 1; | ||
| 189 | break; | ||
| 190 | default: | ||
| 191 | break; | ||
| 192 | } | ||
| 193 | |||
| 194 | switch (mode) { | ||
| 195 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 196 | pr_info("sh_mtu2: %s used for periodic clock events\n", | ||
| 197 | ced->name); | ||
| 198 | sh_mtu2_enable(p); | ||
| 199 | break; | ||
| 200 | case CLOCK_EVT_MODE_UNUSED: | ||
| 201 | if (!disabled) | ||
| 202 | sh_mtu2_disable(p); | ||
| 203 | break; | ||
| 204 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 205 | default: | ||
| 206 | break; | ||
| 207 | } | ||
| 208 | } | ||
| 209 | |||
| 210 | static void sh_mtu2_register_clockevent(struct sh_mtu2_priv *p, | ||
| 211 | char *name, unsigned long rating) | ||
| 212 | { | ||
| 213 | struct clock_event_device *ced = &p->ced; | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | memset(ced, 0, sizeof(*ced)); | ||
| 217 | |||
| 218 | ced->name = name; | ||
| 219 | ced->features = CLOCK_EVT_FEAT_PERIODIC; | ||
| 220 | ced->rating = rating; | ||
| 221 | ced->cpumask = cpumask_of(0); | ||
| 222 | ced->set_mode = sh_mtu2_clock_event_mode; | ||
| 223 | |||
| 224 | ret = setup_irq(p->irqaction.irq, &p->irqaction); | ||
| 225 | if (ret) { | ||
| 226 | pr_err("sh_mtu2: failed to request irq %d\n", | ||
| 227 | p->irqaction.irq); | ||
| 228 | return; | ||
| 229 | } | ||
| 230 | |||
| 231 | pr_info("sh_mtu2: %s used for clock events\n", ced->name); | ||
| 232 | clockevents_register_device(ced); | ||
| 233 | } | ||
| 234 | |||
| 235 | static int sh_mtu2_register(struct sh_mtu2_priv *p, char *name, | ||
| 236 | unsigned long clockevent_rating) | ||
| 237 | { | ||
| 238 | if (clockevent_rating) | ||
| 239 | sh_mtu2_register_clockevent(p, name, clockevent_rating); | ||
| 240 | |||
| 241 | return 0; | ||
| 242 | } | ||
| 243 | |||
| 244 | static int sh_mtu2_setup(struct sh_mtu2_priv *p, struct platform_device *pdev) | ||
| 245 | { | ||
| 246 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 247 | struct resource *res; | ||
| 248 | int irq, ret; | ||
| 249 | ret = -ENXIO; | ||
| 250 | |||
| 251 | memset(p, 0, sizeof(*p)); | ||
| 252 | p->pdev = pdev; | ||
| 253 | |||
| 254 | if (!cfg) { | ||
| 255 | dev_err(&p->pdev->dev, "missing platform data\n"); | ||
| 256 | goto err0; | ||
| 257 | } | ||
| 258 | |||
| 259 | platform_set_drvdata(pdev, p); | ||
| 260 | |||
| 261 | res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); | ||
| 262 | if (!res) { | ||
| 263 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); | ||
| 264 | goto err0; | ||
| 265 | } | ||
| 266 | |||
| 267 | irq = platform_get_irq(p->pdev, 0); | ||
| 268 | if (irq < 0) { | ||
| 269 | dev_err(&p->pdev->dev, "failed to get irq\n"); | ||
| 270 | goto err0; | ||
| 271 | } | ||
| 272 | |||
| 273 | /* map memory, let mapbase point to our channel */ | ||
| 274 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | ||
| 275 | if (p->mapbase == NULL) { | ||
| 276 | pr_err("sh_mtu2: failed to remap I/O memory\n"); | ||
| 277 | goto err0; | ||
| 278 | } | ||
| 279 | |||
| 280 | /* setup data for setup_irq() (too early for request_irq()) */ | ||
| 281 | p->irqaction.name = cfg->name; | ||
| 282 | p->irqaction.handler = sh_mtu2_interrupt; | ||
| 283 | p->irqaction.dev_id = p; | ||
| 284 | p->irqaction.irq = irq; | ||
| 285 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | ||
| 286 | p->irqaction.mask = CPU_MASK_NONE; | ||
| 287 | |||
| 288 | /* get hold of clock */ | ||
| 289 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | ||
| 290 | if (IS_ERR(p->clk)) { | ||
| 291 | pr_err("sh_mtu2: cannot get clock \"%s\"\n", cfg->clk); | ||
| 292 | ret = PTR_ERR(p->clk); | ||
| 293 | goto err1; | ||
| 294 | } | ||
| 295 | |||
| 296 | return sh_mtu2_register(p, cfg->name, cfg->clockevent_rating); | ||
| 297 | err1: | ||
| 298 | iounmap(p->mapbase); | ||
| 299 | err0: | ||
| 300 | return ret; | ||
| 301 | } | ||
| 302 | |||
| 303 | static int __devinit sh_mtu2_probe(struct platform_device *pdev) | ||
| 304 | { | ||
| 305 | struct sh_mtu2_priv *p = platform_get_drvdata(pdev); | ||
| 306 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 307 | int ret; | ||
| 308 | |||
| 309 | if (p) { | ||
| 310 | pr_info("sh_mtu2: %s kept as earlytimer\n", cfg->name); | ||
| 311 | return 0; | ||
| 312 | } | ||
| 313 | |||
| 314 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
| 315 | if (p == NULL) { | ||
| 316 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 317 | return -ENOMEM; | ||
| 318 | } | ||
| 319 | |||
| 320 | ret = sh_mtu2_setup(p, pdev); | ||
| 321 | if (ret) { | ||
| 322 | kfree(p); | ||
| 323 | platform_set_drvdata(pdev, NULL); | ||
| 324 | } | ||
| 325 | return ret; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int __devexit sh_mtu2_remove(struct platform_device *pdev) | ||
| 329 | { | ||
| 330 | return -EBUSY; /* cannot unregister clockevent */ | ||
| 331 | } | ||
| 332 | |||
| 333 | static struct platform_driver sh_mtu2_device_driver = { | ||
| 334 | .probe = sh_mtu2_probe, | ||
| 335 | .remove = __devexit_p(sh_mtu2_remove), | ||
| 336 | .driver = { | ||
| 337 | .name = "sh_mtu2", | ||
| 338 | } | ||
| 339 | }; | ||
| 340 | |||
| 341 | static int __init sh_mtu2_init(void) | ||
| 342 | { | ||
| 343 | return platform_driver_register(&sh_mtu2_device_driver); | ||
| 344 | } | ||
| 345 | |||
| 346 | static void __exit sh_mtu2_exit(void) | ||
| 347 | { | ||
| 348 | platform_driver_unregister(&sh_mtu2_device_driver); | ||
| 349 | } | ||
| 350 | |||
| 351 | early_platform_init("earlytimer", &sh_mtu2_device_driver); | ||
| 352 | module_init(sh_mtu2_init); | ||
| 353 | module_exit(sh_mtu2_exit); | ||
| 354 | |||
| 355 | MODULE_AUTHOR("Magnus Damm"); | ||
| 356 | MODULE_DESCRIPTION("SuperH MTU2 Timer Driver"); | ||
| 357 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/clocksource/sh_tmu.c b/drivers/clocksource/sh_tmu.c new file mode 100644 index 000000000000..d6ea4398bf62 --- /dev/null +++ b/drivers/clocksource/sh_tmu.c | |||
| @@ -0,0 +1,461 @@ | |||
| 1 | /* | ||
| 2 | * SuperH Timer Support - TMU | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Magnus Damm | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or modify | ||
| 7 | * it under the terms of the GNU General Public License as published by | ||
| 8 | * the Free Software Foundation; either version 2 of the License | ||
| 9 | * | ||
| 10 | * This program is distributed in the hope that it will be useful, | ||
| 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 13 | * GNU General Public License for more details. | ||
| 14 | * | ||
| 15 | * You should have received a copy of the GNU General Public License | ||
| 16 | * along with this program; if not, write to the Free Software | ||
| 17 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 18 | */ | ||
| 19 | |||
| 20 | #include <linux/init.h> | ||
| 21 | #include <linux/platform_device.h> | ||
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <linux/interrupt.h> | ||
| 24 | #include <linux/ioport.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/io.h> | ||
| 27 | #include <linux/clk.h> | ||
| 28 | #include <linux/irq.h> | ||
| 29 | #include <linux/err.h> | ||
| 30 | #include <linux/clocksource.h> | ||
| 31 | #include <linux/clockchips.h> | ||
| 32 | #include <linux/sh_timer.h> | ||
| 33 | |||
| 34 | struct sh_tmu_priv { | ||
| 35 | void __iomem *mapbase; | ||
| 36 | struct clk *clk; | ||
| 37 | struct irqaction irqaction; | ||
| 38 | struct platform_device *pdev; | ||
| 39 | unsigned long rate; | ||
| 40 | unsigned long periodic; | ||
| 41 | struct clock_event_device ced; | ||
| 42 | struct clocksource cs; | ||
| 43 | }; | ||
| 44 | |||
| 45 | static DEFINE_SPINLOCK(sh_tmu_lock); | ||
| 46 | |||
| 47 | #define TSTR -1 /* shared register */ | ||
| 48 | #define TCOR 0 /* channel register */ | ||
| 49 | #define TCNT 1 /* channel register */ | ||
| 50 | #define TCR 2 /* channel register */ | ||
| 51 | |||
| 52 | static inline unsigned long sh_tmu_read(struct sh_tmu_priv *p, int reg_nr) | ||
| 53 | { | ||
| 54 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 55 | void __iomem *base = p->mapbase; | ||
| 56 | unsigned long offs; | ||
| 57 | |||
| 58 | if (reg_nr == TSTR) | ||
| 59 | return ioread8(base - cfg->channel_offset); | ||
| 60 | |||
| 61 | offs = reg_nr << 2; | ||
| 62 | |||
| 63 | if (reg_nr == TCR) | ||
| 64 | return ioread16(base + offs); | ||
| 65 | else | ||
| 66 | return ioread32(base + offs); | ||
| 67 | } | ||
| 68 | |||
| 69 | static inline void sh_tmu_write(struct sh_tmu_priv *p, int reg_nr, | ||
| 70 | unsigned long value) | ||
| 71 | { | ||
| 72 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 73 | void __iomem *base = p->mapbase; | ||
| 74 | unsigned long offs; | ||
| 75 | |||
| 76 | if (reg_nr == TSTR) { | ||
| 77 | iowrite8(value, base - cfg->channel_offset); | ||
| 78 | return; | ||
| 79 | } | ||
| 80 | |||
| 81 | offs = reg_nr << 2; | ||
| 82 | |||
| 83 | if (reg_nr == TCR) | ||
| 84 | iowrite16(value, base + offs); | ||
| 85 | else | ||
| 86 | iowrite32(value, base + offs); | ||
| 87 | } | ||
| 88 | |||
| 89 | static void sh_tmu_start_stop_ch(struct sh_tmu_priv *p, int start) | ||
| 90 | { | ||
| 91 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 92 | unsigned long flags, value; | ||
| 93 | |||
| 94 | /* start stop register shared by multiple timer channels */ | ||
| 95 | spin_lock_irqsave(&sh_tmu_lock, flags); | ||
| 96 | value = sh_tmu_read(p, TSTR); | ||
| 97 | |||
| 98 | if (start) | ||
| 99 | value |= 1 << cfg->timer_bit; | ||
| 100 | else | ||
| 101 | value &= ~(1 << cfg->timer_bit); | ||
| 102 | |||
| 103 | sh_tmu_write(p, TSTR, value); | ||
| 104 | spin_unlock_irqrestore(&sh_tmu_lock, flags); | ||
| 105 | } | ||
| 106 | |||
| 107 | static int sh_tmu_enable(struct sh_tmu_priv *p) | ||
| 108 | { | ||
| 109 | struct sh_timer_config *cfg = p->pdev->dev.platform_data; | ||
| 110 | int ret; | ||
| 111 | |||
| 112 | /* enable clock */ | ||
| 113 | ret = clk_enable(p->clk); | ||
| 114 | if (ret) { | ||
| 115 | pr_err("sh_tmu: cannot enable clock \"%s\"\n", cfg->clk); | ||
| 116 | return ret; | ||
| 117 | } | ||
| 118 | |||
| 119 | /* make sure channel is disabled */ | ||
| 120 | sh_tmu_start_stop_ch(p, 0); | ||
| 121 | |||
| 122 | /* maximum timeout */ | ||
| 123 | sh_tmu_write(p, TCOR, 0xffffffff); | ||
| 124 | sh_tmu_write(p, TCNT, 0xffffffff); | ||
| 125 | |||
| 126 | /* configure channel to parent clock / 4, irq off */ | ||
| 127 | p->rate = clk_get_rate(p->clk) / 4; | ||
| 128 | sh_tmu_write(p, TCR, 0x0000); | ||
| 129 | |||
| 130 | /* enable channel */ | ||
| 131 | sh_tmu_start_stop_ch(p, 1); | ||
| 132 | |||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static void sh_tmu_disable(struct sh_tmu_priv *p) | ||
| 137 | { | ||
| 138 | /* disable channel */ | ||
| 139 | sh_tmu_start_stop_ch(p, 0); | ||
| 140 | |||
| 141 | /* stop clock */ | ||
| 142 | clk_disable(p->clk); | ||
| 143 | } | ||
| 144 | |||
| 145 | static void sh_tmu_set_next(struct sh_tmu_priv *p, unsigned long delta, | ||
| 146 | int periodic) | ||
| 147 | { | ||
| 148 | /* stop timer */ | ||
| 149 | sh_tmu_start_stop_ch(p, 0); | ||
| 150 | |||
| 151 | /* acknowledge interrupt */ | ||
| 152 | sh_tmu_read(p, TCR); | ||
| 153 | |||
| 154 | /* enable interrupt */ | ||
| 155 | sh_tmu_write(p, TCR, 0x0020); | ||
| 156 | |||
| 157 | /* reload delta value in case of periodic timer */ | ||
| 158 | if (periodic) | ||
| 159 | sh_tmu_write(p, TCOR, delta); | ||
| 160 | else | ||
| 161 | sh_tmu_write(p, TCOR, 0); | ||
| 162 | |||
| 163 | sh_tmu_write(p, TCNT, delta); | ||
| 164 | |||
| 165 | /* start timer */ | ||
| 166 | sh_tmu_start_stop_ch(p, 1); | ||
| 167 | } | ||
| 168 | |||
| 169 | static irqreturn_t sh_tmu_interrupt(int irq, void *dev_id) | ||
| 170 | { | ||
| 171 | struct sh_tmu_priv *p = dev_id; | ||
| 172 | |||
| 173 | /* disable or acknowledge interrupt */ | ||
| 174 | if (p->ced.mode == CLOCK_EVT_MODE_ONESHOT) | ||
| 175 | sh_tmu_write(p, TCR, 0x0000); | ||
| 176 | else | ||
| 177 | sh_tmu_write(p, TCR, 0x0020); | ||
| 178 | |||
| 179 | /* notify clockevent layer */ | ||
| 180 | p->ced.event_handler(&p->ced); | ||
| 181 | return IRQ_HANDLED; | ||
| 182 | } | ||
| 183 | |||
| 184 | static struct sh_tmu_priv *cs_to_sh_tmu(struct clocksource *cs) | ||
| 185 | { | ||
| 186 | return container_of(cs, struct sh_tmu_priv, cs); | ||
| 187 | } | ||
| 188 | |||
| 189 | static cycle_t sh_tmu_clocksource_read(struct clocksource *cs) | ||
| 190 | { | ||
| 191 | struct sh_tmu_priv *p = cs_to_sh_tmu(cs); | ||
| 192 | |||
| 193 | return sh_tmu_read(p, TCNT) ^ 0xffffffff; | ||
| 194 | } | ||
| 195 | |||
| 196 | static int sh_tmu_clocksource_enable(struct clocksource *cs) | ||
| 197 | { | ||
| 198 | struct sh_tmu_priv *p = cs_to_sh_tmu(cs); | ||
| 199 | int ret; | ||
| 200 | |||
| 201 | ret = sh_tmu_enable(p); | ||
| 202 | if (ret) | ||
| 203 | return ret; | ||
| 204 | |||
| 205 | /* TODO: calculate good shift from rate and counter bit width */ | ||
| 206 | cs->shift = 10; | ||
| 207 | cs->mult = clocksource_hz2mult(p->rate, cs->shift); | ||
| 208 | return 0; | ||
| 209 | } | ||
| 210 | |||
| 211 | static void sh_tmu_clocksource_disable(struct clocksource *cs) | ||
| 212 | { | ||
| 213 | sh_tmu_disable(cs_to_sh_tmu(cs)); | ||
| 214 | } | ||
| 215 | |||
| 216 | static int sh_tmu_register_clocksource(struct sh_tmu_priv *p, | ||
| 217 | char *name, unsigned long rating) | ||
| 218 | { | ||
| 219 | struct clocksource *cs = &p->cs; | ||
| 220 | |||
| 221 | cs->name = name; | ||
| 222 | cs->rating = rating; | ||
| 223 | cs->read = sh_tmu_clocksource_read; | ||
| 224 | cs->enable = sh_tmu_clocksource_enable; | ||
| 225 | cs->disable = sh_tmu_clocksource_disable; | ||
| 226 | cs->mask = CLOCKSOURCE_MASK(32); | ||
| 227 | cs->flags = CLOCK_SOURCE_IS_CONTINUOUS; | ||
| 228 | pr_info("sh_tmu: %s used as clock source\n", cs->name); | ||
| 229 | clocksource_register(cs); | ||
| 230 | return 0; | ||
| 231 | } | ||
| 232 | |||
| 233 | static struct sh_tmu_priv *ced_to_sh_tmu(struct clock_event_device *ced) | ||
| 234 | { | ||
| 235 | return container_of(ced, struct sh_tmu_priv, ced); | ||
| 236 | } | ||
| 237 | |||
| 238 | static void sh_tmu_clock_event_start(struct sh_tmu_priv *p, int periodic) | ||
| 239 | { | ||
| 240 | struct clock_event_device *ced = &p->ced; | ||
| 241 | |||
| 242 | sh_tmu_enable(p); | ||
| 243 | |||
| 244 | /* TODO: calculate good shift from rate and counter bit width */ | ||
| 245 | |||
| 246 | ced->shift = 32; | ||
| 247 | ced->mult = div_sc(p->rate, NSEC_PER_SEC, ced->shift); | ||
| 248 | ced->max_delta_ns = clockevent_delta2ns(0xffffffff, ced); | ||
| 249 | ced->min_delta_ns = 5000; | ||
| 250 | |||
| 251 | if (periodic) { | ||
| 252 | p->periodic = (p->rate + HZ/2) / HZ; | ||
| 253 | sh_tmu_set_next(p, p->periodic, 1); | ||
| 254 | } | ||
| 255 | } | ||
| 256 | |||
| 257 | static void sh_tmu_clock_event_mode(enum clock_event_mode mode, | ||
| 258 | struct clock_event_device *ced) | ||
| 259 | { | ||
| 260 | struct sh_tmu_priv *p = ced_to_sh_tmu(ced); | ||
| 261 | int disabled = 0; | ||
| 262 | |||
| 263 | /* deal with old setting first */ | ||
| 264 | switch (ced->mode) { | ||
| 265 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 266 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 267 | sh_tmu_disable(p); | ||
| 268 | disabled = 1; | ||
| 269 | break; | ||
| 270 | default: | ||
| 271 | break; | ||
| 272 | } | ||
| 273 | |||
| 274 | switch (mode) { | ||
| 275 | case CLOCK_EVT_MODE_PERIODIC: | ||
| 276 | pr_info("sh_tmu: %s used for periodic clock events\n", | ||
| 277 | ced->name); | ||
| 278 | sh_tmu_clock_event_start(p, 1); | ||
| 279 | break; | ||
| 280 | case CLOCK_EVT_MODE_ONESHOT: | ||
| 281 | pr_info("sh_tmu: %s used for oneshot clock events\n", | ||
| 282 | ced->name); | ||
| 283 | sh_tmu_clock_event_start(p, 0); | ||
| 284 | break; | ||
| 285 | case CLOCK_EVT_MODE_UNUSED: | ||
| 286 | if (!disabled) | ||
| 287 | sh_tmu_disable(p); | ||
| 288 | break; | ||
| 289 | case CLOCK_EVT_MODE_SHUTDOWN: | ||
| 290 | default: | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | } | ||
| 294 | |||
| 295 | static int sh_tmu_clock_event_next(unsigned long delta, | ||
| 296 | struct clock_event_device *ced) | ||
| 297 | { | ||
| 298 | struct sh_tmu_priv *p = ced_to_sh_tmu(ced); | ||
| 299 | |||
| 300 | BUG_ON(ced->mode != CLOCK_EVT_MODE_ONESHOT); | ||
| 301 | |||
| 302 | /* program new delta value */ | ||
| 303 | sh_tmu_set_next(p, delta, 0); | ||
| 304 | return 0; | ||
| 305 | } | ||
| 306 | |||
| 307 | static void sh_tmu_register_clockevent(struct sh_tmu_priv *p, | ||
| 308 | char *name, unsigned long rating) | ||
| 309 | { | ||
| 310 | struct clock_event_device *ced = &p->ced; | ||
| 311 | int ret; | ||
| 312 | |||
| 313 | memset(ced, 0, sizeof(*ced)); | ||
| 314 | |||
| 315 | ced->name = name; | ||
| 316 | ced->features = CLOCK_EVT_FEAT_PERIODIC; | ||
| 317 | ced->features |= CLOCK_EVT_FEAT_ONESHOT; | ||
| 318 | ced->rating = rating; | ||
| 319 | ced->cpumask = cpumask_of(0); | ||
| 320 | ced->set_next_event = sh_tmu_clock_event_next; | ||
| 321 | ced->set_mode = sh_tmu_clock_event_mode; | ||
| 322 | |||
| 323 | ret = setup_irq(p->irqaction.irq, &p->irqaction); | ||
| 324 | if (ret) { | ||
| 325 | pr_err("sh_tmu: failed to request irq %d\n", | ||
| 326 | p->irqaction.irq); | ||
| 327 | return; | ||
| 328 | } | ||
| 329 | |||
| 330 | pr_info("sh_tmu: %s used for clock events\n", ced->name); | ||
| 331 | clockevents_register_device(ced); | ||
| 332 | } | ||
| 333 | |||
| 334 | static int sh_tmu_register(struct sh_tmu_priv *p, char *name, | ||
| 335 | unsigned long clockevent_rating, | ||
| 336 | unsigned long clocksource_rating) | ||
| 337 | { | ||
| 338 | if (clockevent_rating) | ||
| 339 | sh_tmu_register_clockevent(p, name, clockevent_rating); | ||
| 340 | else if (clocksource_rating) | ||
| 341 | sh_tmu_register_clocksource(p, name, clocksource_rating); | ||
| 342 | |||
| 343 | return 0; | ||
| 344 | } | ||
| 345 | |||
| 346 | static int sh_tmu_setup(struct sh_tmu_priv *p, struct platform_device *pdev) | ||
| 347 | { | ||
| 348 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 349 | struct resource *res; | ||
| 350 | int irq, ret; | ||
| 351 | ret = -ENXIO; | ||
| 352 | |||
| 353 | memset(p, 0, sizeof(*p)); | ||
| 354 | p->pdev = pdev; | ||
| 355 | |||
| 356 | if (!cfg) { | ||
| 357 | dev_err(&p->pdev->dev, "missing platform data\n"); | ||
| 358 | goto err0; | ||
| 359 | } | ||
| 360 | |||
| 361 | platform_set_drvdata(pdev, p); | ||
| 362 | |||
| 363 | res = platform_get_resource(p->pdev, IORESOURCE_MEM, 0); | ||
| 364 | if (!res) { | ||
| 365 | dev_err(&p->pdev->dev, "failed to get I/O memory\n"); | ||
| 366 | goto err0; | ||
| 367 | } | ||
| 368 | |||
| 369 | irq = platform_get_irq(p->pdev, 0); | ||
| 370 | if (irq < 0) { | ||
| 371 | dev_err(&p->pdev->dev, "failed to get irq\n"); | ||
| 372 | goto err0; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* map memory, let mapbase point to our channel */ | ||
| 376 | p->mapbase = ioremap_nocache(res->start, resource_size(res)); | ||
| 377 | if (p->mapbase == NULL) { | ||
| 378 | pr_err("sh_tmu: failed to remap I/O memory\n"); | ||
| 379 | goto err0; | ||
| 380 | } | ||
| 381 | |||
| 382 | /* setup data for setup_irq() (too early for request_irq()) */ | ||
| 383 | p->irqaction.name = cfg->name; | ||
| 384 | p->irqaction.handler = sh_tmu_interrupt; | ||
| 385 | p->irqaction.dev_id = p; | ||
| 386 | p->irqaction.irq = irq; | ||
| 387 | p->irqaction.flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL; | ||
| 388 | p->irqaction.mask = CPU_MASK_NONE; | ||
| 389 | |||
| 390 | /* get hold of clock */ | ||
| 391 | p->clk = clk_get(&p->pdev->dev, cfg->clk); | ||
| 392 | if (IS_ERR(p->clk)) { | ||
| 393 | pr_err("sh_tmu: cannot get clock \"%s\"\n", cfg->clk); | ||
| 394 | ret = PTR_ERR(p->clk); | ||
| 395 | goto err1; | ||
| 396 | } | ||
| 397 | |||
| 398 | return sh_tmu_register(p, cfg->name, | ||
| 399 | cfg->clockevent_rating, | ||
| 400 | cfg->clocksource_rating); | ||
| 401 | err1: | ||
| 402 | iounmap(p->mapbase); | ||
| 403 | err0: | ||
| 404 | return ret; | ||
| 405 | } | ||
| 406 | |||
| 407 | static int __devinit sh_tmu_probe(struct platform_device *pdev) | ||
| 408 | { | ||
| 409 | struct sh_tmu_priv *p = platform_get_drvdata(pdev); | ||
| 410 | struct sh_timer_config *cfg = pdev->dev.platform_data; | ||
| 411 | int ret; | ||
| 412 | |||
| 413 | if (p) { | ||
| 414 | pr_info("sh_tmu: %s kept as earlytimer\n", cfg->name); | ||
| 415 | return 0; | ||
| 416 | } | ||
| 417 | |||
| 418 | p = kmalloc(sizeof(*p), GFP_KERNEL); | ||
| 419 | if (p == NULL) { | ||
| 420 | dev_err(&pdev->dev, "failed to allocate driver data\n"); | ||
| 421 | return -ENOMEM; | ||
| 422 | } | ||
| 423 | |||
| 424 | ret = sh_tmu_setup(p, pdev); | ||
| 425 | if (ret) { | ||
| 426 | kfree(p); | ||
| 427 | platform_set_drvdata(pdev, NULL); | ||
| 428 | } | ||
| 429 | return ret; | ||
| 430 | } | ||
| 431 | |||
| 432 | static int __devexit sh_tmu_remove(struct platform_device *pdev) | ||
| 433 | { | ||
| 434 | return -EBUSY; /* cannot unregister clockevent and clocksource */ | ||
| 435 | } | ||
| 436 | |||
| 437 | static struct platform_driver sh_tmu_device_driver = { | ||
| 438 | .probe = sh_tmu_probe, | ||
| 439 | .remove = __devexit_p(sh_tmu_remove), | ||
| 440 | .driver = { | ||
| 441 | .name = "sh_tmu", | ||
| 442 | } | ||
| 443 | }; | ||
| 444 | |||
| 445 | static int __init sh_tmu_init(void) | ||
| 446 | { | ||
| 447 | return platform_driver_register(&sh_tmu_device_driver); | ||
| 448 | } | ||
| 449 | |||
| 450 | static void __exit sh_tmu_exit(void) | ||
| 451 | { | ||
| 452 | platform_driver_unregister(&sh_tmu_device_driver); | ||
| 453 | } | ||
| 454 | |||
| 455 | early_platform_init("earlytimer", &sh_tmu_device_driver); | ||
| 456 | module_init(sh_tmu_init); | ||
| 457 | module_exit(sh_tmu_exit); | ||
| 458 | |||
| 459 | MODULE_AUTHOR("Magnus Damm"); | ||
| 460 | MODULE_DESCRIPTION("SuperH TMU Timer Driver"); | ||
| 461 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 47d2ad0ae079..6e2ec0b18948 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c | |||
| @@ -808,7 +808,7 @@ static int cpufreq_add_dev(struct sys_device *sys_dev) | |||
| 808 | ret = -ENOMEM; | 808 | ret = -ENOMEM; |
| 809 | goto nomem_out; | 809 | goto nomem_out; |
| 810 | } | 810 | } |
| 811 | if (!alloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { | 811 | if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) { |
| 812 | free_cpumask_var(policy->cpus); | 812 | free_cpumask_var(policy->cpus); |
| 813 | kfree(policy); | 813 | kfree(policy); |
| 814 | ret = -ENOMEM; | 814 | ret = -ENOMEM; |
diff --git a/drivers/dma/fsldma.c b/drivers/dma/fsldma.c index 66a7687cca73..f18d1bde0439 100644 --- a/drivers/dma/fsldma.c +++ b/drivers/dma/fsldma.c | |||
| @@ -179,9 +179,14 @@ static void dma_halt(struct fsl_dma_chan *fsl_chan) | |||
| 179 | static void set_ld_eol(struct fsl_dma_chan *fsl_chan, | 179 | static void set_ld_eol(struct fsl_dma_chan *fsl_chan, |
| 180 | struct fsl_desc_sw *desc) | 180 | struct fsl_desc_sw *desc) |
| 181 | { | 181 | { |
| 182 | u64 snoop_bits; | ||
| 183 | |||
| 184 | snoop_bits = ((fsl_chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX) | ||
| 185 | ? FSL_DMA_SNEN : 0; | ||
| 186 | |||
| 182 | desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan, | 187 | desc->hw.next_ln_addr = CPU_TO_DMA(fsl_chan, |
| 183 | DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL, | 188 | DMA_TO_CPU(fsl_chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL |
| 184 | 64); | 189 | | snoop_bits, 64); |
| 185 | } | 190 | } |
| 186 | 191 | ||
| 187 | static void append_ld_queue(struct fsl_dma_chan *fsl_chan, | 192 | static void append_ld_queue(struct fsl_dma_chan *fsl_chan, |
| @@ -313,8 +318,8 @@ static void fsl_chan_toggle_ext_start(struct fsl_dma_chan *fsl_chan, int enable) | |||
| 313 | 318 | ||
| 314 | static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx) | 319 | static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx) |
| 315 | { | 320 | { |
| 316 | struct fsl_desc_sw *desc = tx_to_fsl_desc(tx); | ||
| 317 | struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan); | 321 | struct fsl_dma_chan *fsl_chan = to_fsl_chan(tx->chan); |
| 322 | struct fsl_desc_sw *desc; | ||
| 318 | unsigned long flags; | 323 | unsigned long flags; |
| 319 | dma_cookie_t cookie; | 324 | dma_cookie_t cookie; |
| 320 | 325 | ||
| @@ -322,14 +327,17 @@ static dma_cookie_t fsl_dma_tx_submit(struct dma_async_tx_descriptor *tx) | |||
| 322 | spin_lock_irqsave(&fsl_chan->desc_lock, flags); | 327 | spin_lock_irqsave(&fsl_chan->desc_lock, flags); |
| 323 | 328 | ||
| 324 | cookie = fsl_chan->common.cookie; | 329 | cookie = fsl_chan->common.cookie; |
| 325 | cookie++; | 330 | list_for_each_entry(desc, &tx->tx_list, node) { |
| 326 | if (cookie < 0) | 331 | cookie++; |
| 327 | cookie = 1; | 332 | if (cookie < 0) |
| 328 | desc->async_tx.cookie = cookie; | 333 | cookie = 1; |
| 329 | fsl_chan->common.cookie = desc->async_tx.cookie; | ||
| 330 | 334 | ||
| 331 | append_ld_queue(fsl_chan, desc); | 335 | desc->async_tx.cookie = cookie; |
| 332 | list_splice_init(&desc->async_tx.tx_list, fsl_chan->ld_queue.prev); | 336 | } |
| 337 | |||
| 338 | fsl_chan->common.cookie = cookie; | ||
| 339 | append_ld_queue(fsl_chan, tx_to_fsl_desc(tx)); | ||
| 340 | list_splice_init(&tx->tx_list, fsl_chan->ld_queue.prev); | ||
| 333 | 341 | ||
| 334 | spin_unlock_irqrestore(&fsl_chan->desc_lock, flags); | 342 | spin_unlock_irqrestore(&fsl_chan->desc_lock, flags); |
| 335 | 343 | ||
| @@ -454,8 +462,8 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( | |||
| 454 | { | 462 | { |
| 455 | struct fsl_dma_chan *fsl_chan; | 463 | struct fsl_dma_chan *fsl_chan; |
| 456 | struct fsl_desc_sw *first = NULL, *prev = NULL, *new; | 464 | struct fsl_desc_sw *first = NULL, *prev = NULL, *new; |
| 465 | struct list_head *list; | ||
| 457 | size_t copy; | 466 | size_t copy; |
| 458 | LIST_HEAD(link_chain); | ||
| 459 | 467 | ||
| 460 | if (!chan) | 468 | if (!chan) |
| 461 | return NULL; | 469 | return NULL; |
| @@ -472,7 +480,7 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( | |||
| 472 | if (!new) { | 480 | if (!new) { |
| 473 | dev_err(fsl_chan->dev, | 481 | dev_err(fsl_chan->dev, |
| 474 | "No free memory for link descriptor\n"); | 482 | "No free memory for link descriptor\n"); |
| 475 | return NULL; | 483 | goto fail; |
| 476 | } | 484 | } |
| 477 | #ifdef FSL_DMA_LD_DEBUG | 485 | #ifdef FSL_DMA_LD_DEBUG |
| 478 | dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new); | 486 | dev_dbg(fsl_chan->dev, "new link desc alloc %p\n", new); |
| @@ -507,7 +515,19 @@ static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy( | |||
| 507 | /* Set End-of-link to the last link descriptor of new list*/ | 515 | /* Set End-of-link to the last link descriptor of new list*/ |
| 508 | set_ld_eol(fsl_chan, new); | 516 | set_ld_eol(fsl_chan, new); |
| 509 | 517 | ||
| 510 | return first ? &first->async_tx : NULL; | 518 | return &first->async_tx; |
| 519 | |||
| 520 | fail: | ||
| 521 | if (!first) | ||
| 522 | return NULL; | ||
| 523 | |||
| 524 | list = &first->async_tx.tx_list; | ||
| 525 | list_for_each_entry_safe_reverse(new, prev, list, node) { | ||
| 526 | list_del(&new->node); | ||
| 527 | dma_pool_free(fsl_chan->desc_pool, new, new->async_tx.phys); | ||
| 528 | } | ||
| 529 | |||
| 530 | return NULL; | ||
| 511 | } | 531 | } |
| 512 | 532 | ||
| 513 | /** | 533 | /** |
| @@ -598,15 +618,16 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan) | |||
| 598 | dma_addr_t next_dest_addr; | 618 | dma_addr_t next_dest_addr; |
| 599 | unsigned long flags; | 619 | unsigned long flags; |
| 600 | 620 | ||
| 621 | spin_lock_irqsave(&fsl_chan->desc_lock, flags); | ||
| 622 | |||
| 601 | if (!dma_is_idle(fsl_chan)) | 623 | if (!dma_is_idle(fsl_chan)) |
| 602 | return; | 624 | goto out_unlock; |
| 603 | 625 | ||
| 604 | dma_halt(fsl_chan); | 626 | dma_halt(fsl_chan); |
| 605 | 627 | ||
| 606 | /* If there are some link descriptors | 628 | /* If there are some link descriptors |
| 607 | * not transfered in queue. We need to start it. | 629 | * not transfered in queue. We need to start it. |
| 608 | */ | 630 | */ |
| 609 | spin_lock_irqsave(&fsl_chan->desc_lock, flags); | ||
| 610 | 631 | ||
| 611 | /* Find the first un-transfer desciptor */ | 632 | /* Find the first un-transfer desciptor */ |
| 612 | for (ld_node = fsl_chan->ld_queue.next; | 633 | for (ld_node = fsl_chan->ld_queue.next; |
| @@ -617,8 +638,6 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan) | |||
| 617 | fsl_chan->common.cookie) == DMA_SUCCESS); | 638 | fsl_chan->common.cookie) == DMA_SUCCESS); |
| 618 | ld_node = ld_node->next); | 639 | ld_node = ld_node->next); |
| 619 | 640 | ||
| 620 | spin_unlock_irqrestore(&fsl_chan->desc_lock, flags); | ||
| 621 | |||
| 622 | if (ld_node != &fsl_chan->ld_queue) { | 641 | if (ld_node != &fsl_chan->ld_queue) { |
| 623 | /* Get the ld start address from ld_queue */ | 642 | /* Get the ld start address from ld_queue */ |
| 624 | next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys; | 643 | next_dest_addr = to_fsl_desc(ld_node)->async_tx.phys; |
| @@ -630,6 +649,9 @@ static void fsl_chan_xfer_ld_queue(struct fsl_dma_chan *fsl_chan) | |||
| 630 | set_cdar(fsl_chan, 0); | 649 | set_cdar(fsl_chan, 0); |
| 631 | set_ndar(fsl_chan, 0); | 650 | set_ndar(fsl_chan, 0); |
| 632 | } | 651 | } |
| 652 | |||
| 653 | out_unlock: | ||
| 654 | spin_unlock_irqrestore(&fsl_chan->desc_lock, flags); | ||
| 633 | } | 655 | } |
| 634 | 656 | ||
| 635 | /** | 657 | /** |
| @@ -831,7 +853,7 @@ static int __devinit fsl_dma_chan_probe(struct fsl_dma_device *fdev, | |||
| 831 | new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1); | 853 | new_fsl_chan->reg.end - new_fsl_chan->reg.start + 1); |
| 832 | 854 | ||
| 833 | new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7; | 855 | new_fsl_chan->id = ((new_fsl_chan->reg.start - 0x100) & 0xfff) >> 7; |
| 834 | if (new_fsl_chan->id > FSL_DMA_MAX_CHANS_PER_DEVICE) { | 856 | if (new_fsl_chan->id >= FSL_DMA_MAX_CHANS_PER_DEVICE) { |
| 835 | dev_err(fdev->dev, "There is no %d channel!\n", | 857 | dev_err(fdev->dev, "There is no %d channel!\n", |
| 836 | new_fsl_chan->id); | 858 | new_fsl_chan->id); |
| 837 | err = -EINVAL; | 859 | err = -EINVAL; |
diff --git a/drivers/dma/ioat_dma.c b/drivers/dma/ioat_dma.c index 1955ee8d6d20..a600fc0f7962 100644 --- a/drivers/dma/ioat_dma.c +++ b/drivers/dma/ioat_dma.c | |||
| @@ -173,7 +173,7 @@ static int ioat_dma_enumerate_channels(struct ioatdma_device *device) | |||
| 173 | xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale)); | 173 | xfercap = (xfercap_scale == 0 ? -1 : (1UL << xfercap_scale)); |
| 174 | 174 | ||
| 175 | #ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL | 175 | #ifdef CONFIG_I7300_IDLE_IOAT_CHANNEL |
| 176 | if (i7300_idle_platform_probe(NULL, NULL) == 0) { | 176 | if (i7300_idle_platform_probe(NULL, NULL, 1) == 0) { |
| 177 | device->common.chancnt--; | 177 | device->common.chancnt--; |
| 178 | } | 178 | } |
| 179 | #endif | 179 | #endif |
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index e5f5c5a8ba6c..ab4f3592a11c 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
| @@ -49,7 +49,6 @@ config EDAC_DEBUG_VERBOSE | |||
| 49 | 49 | ||
| 50 | config EDAC_MM_EDAC | 50 | config EDAC_MM_EDAC |
| 51 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" | 51 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" |
| 52 | default y | ||
| 53 | help | 52 | help |
| 54 | Some systems are able to detect and correct errors in main | 53 | Some systems are able to detect and correct errors in main |
| 55 | memory. EDAC can report statistics on memory error | 54 | memory. EDAC can report statistics on memory error |
| @@ -58,6 +57,31 @@ config EDAC_MM_EDAC | |||
| 58 | occurred so that a particular failing memory module can be | 57 | occurred so that a particular failing memory module can be |
| 59 | replaced. If unsure, select 'Y'. | 58 | replaced. If unsure, select 'Y'. |
| 60 | 59 | ||
| 60 | config EDAC_AMD64 | ||
| 61 | tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" | ||
| 62 | depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI | ||
| 63 | help | ||
| 64 | Support for error detection and correction on the AMD 64 | ||
| 65 | Families of Memory Controllers (K8, F10h and F11h) | ||
| 66 | |||
| 67 | config EDAC_AMD64_ERROR_INJECTION | ||
| 68 | bool "Sysfs Error Injection facilities" | ||
| 69 | depends on EDAC_AMD64 | ||
| 70 | help | ||
| 71 | Recent Opterons (Family 10h and later) provide for Memory Error | ||
| 72 | Injection into the ECC detection circuits. The amd64_edac module | ||
| 73 | allows the operator/user to inject Uncorrectable and Correctable | ||
| 74 | errors into DRAM. | ||
| 75 | |||
| 76 | When enabled, in each of the respective memory controller directories | ||
| 77 | (/sys/devices/system/edac/mc/mcX), there are 3 input files: | ||
| 78 | |||
| 79 | - inject_section (0..3, 16-byte section of 64-byte cacheline), | ||
| 80 | - inject_word (0..8, 16-bit word of 16-byte section), | ||
| 81 | - inject_ecc_vector (hex ecc vector: select bits of inject word) | ||
| 82 | |||
| 83 | In addition, there are two control files, inject_read and inject_write, | ||
| 84 | which trigger the DRAM ECC Read and Write respectively. | ||
| 61 | 85 | ||
| 62 | config EDAC_AMD76X | 86 | config EDAC_AMD76X |
| 63 | tristate "AMD 76x (760, 762, 768)" | 87 | tristate "AMD 76x (760, 762, 768)" |
| @@ -192,16 +216,20 @@ config EDAC_PPC4XX | |||
| 192 | 216 | ||
| 193 | config EDAC_AMD8131 | 217 | config EDAC_AMD8131 |
| 194 | tristate "AMD8131 HyperTransport PCI-X Tunnel" | 218 | tristate "AMD8131 HyperTransport PCI-X Tunnel" |
| 195 | depends on EDAC_MM_EDAC && PCI | 219 | depends on EDAC_MM_EDAC && PCI && PPC_MAPLE |
| 196 | help | 220 | help |
| 197 | Support for error detection and correction on the | 221 | Support for error detection and correction on the |
| 198 | AMD8131 HyperTransport PCI-X Tunnel chip. | 222 | AMD8131 HyperTransport PCI-X Tunnel chip. |
| 223 | Note, add more Kconfig dependency if it's adopted | ||
| 224 | on some machine other than Maple. | ||
| 199 | 225 | ||
| 200 | config EDAC_AMD8111 | 226 | config EDAC_AMD8111 |
| 201 | tristate "AMD8111 HyperTransport I/O Hub" | 227 | tristate "AMD8111 HyperTransport I/O Hub" |
| 202 | depends on EDAC_MM_EDAC && PCI | 228 | depends on EDAC_MM_EDAC && PCI && PPC_MAPLE |
| 203 | help | 229 | help |
| 204 | Support for error detection and correction on the | 230 | Support for error detection and correction on the |
| 205 | AMD8111 HyperTransport I/O Hub chip. | 231 | AMD8111 HyperTransport I/O Hub chip. |
| 232 | Note, add more Kconfig dependency if it's adopted | ||
| 233 | on some machine other than Maple. | ||
| 206 | 234 | ||
| 207 | endif # EDAC | 235 | endif # EDAC |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index a5fdcf02f591..633dc5604ee3 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
| @@ -30,8 +30,17 @@ obj-$(CONFIG_EDAC_I3000) += i3000_edac.o | |||
| 30 | obj-$(CONFIG_EDAC_X38) += x38_edac.o | 30 | obj-$(CONFIG_EDAC_X38) += x38_edac.o |
| 31 | obj-$(CONFIG_EDAC_I82860) += i82860_edac.o | 31 | obj-$(CONFIG_EDAC_I82860) += i82860_edac.o |
| 32 | obj-$(CONFIG_EDAC_R82600) += r82600_edac.o | 32 | obj-$(CONFIG_EDAC_R82600) += r82600_edac.o |
| 33 | |||
| 34 | amd64_edac_mod-y := amd64_edac_err_types.o amd64_edac.o | ||
| 35 | amd64_edac_mod-$(CONFIG_EDAC_DEBUG) += amd64_edac_dbg.o | ||
| 36 | amd64_edac_mod-$(CONFIG_EDAC_AMD64_ERROR_INJECTION) += amd64_edac_inj.o | ||
| 37 | |||
| 38 | obj-$(CONFIG_EDAC_AMD64) += amd64_edac_mod.o | ||
| 39 | |||
| 33 | obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o | 40 | obj-$(CONFIG_EDAC_PASEMI) += pasemi_edac.o |
| 34 | obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac.o | 41 | obj-$(CONFIG_EDAC_MPC85XX) += mpc85xx_edac.o |
| 35 | obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o | 42 | obj-$(CONFIG_EDAC_MV64X60) += mv64x60_edac.o |
| 36 | obj-$(CONFIG_EDAC_CELL) += cell_edac.o | 43 | obj-$(CONFIG_EDAC_CELL) += cell_edac.o |
| 37 | obj-$(CONFIG_EDAC_PPC4XX) += ppc4xx_edac.o | 44 | obj-$(CONFIG_EDAC_PPC4XX) += ppc4xx_edac.o |
| 45 | obj-$(CONFIG_EDAC_AMD8111) += amd8111_edac.o | ||
| 46 | obj-$(CONFIG_EDAC_AMD8131) += amd8131_edac.o | ||
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c new file mode 100644 index 000000000000..c36bf40568cf --- /dev/null +++ b/drivers/edac/amd64_edac.c | |||
| @@ -0,0 +1,3354 @@ | |||
| 1 | #include "amd64_edac.h" | ||
| 2 | #include <asm/k8.h> | ||
| 3 | |||
| 4 | static struct edac_pci_ctl_info *amd64_ctl_pci; | ||
| 5 | |||
| 6 | static int report_gart_errors; | ||
| 7 | module_param(report_gart_errors, int, 0644); | ||
| 8 | |||
| 9 | /* | ||
| 10 | * Set by command line parameter. If BIOS has enabled the ECC, this override is | ||
| 11 | * cleared to prevent re-enabling the hardware by this driver. | ||
| 12 | */ | ||
| 13 | static int ecc_enable_override; | ||
| 14 | module_param(ecc_enable_override, int, 0644); | ||
| 15 | |||
| 16 | /* Lookup table for all possible MC control instances */ | ||
| 17 | struct amd64_pvt; | ||
| 18 | static struct mem_ctl_info *mci_lookup[MAX_NUMNODES]; | ||
| 19 | static struct amd64_pvt *pvt_lookup[MAX_NUMNODES]; | ||
| 20 | |||
| 21 | /* | ||
| 22 | * Memory scrubber control interface. For K8, memory scrubbing is handled by | ||
| 23 | * hardware and can involve L2 cache, dcache as well as the main memory. With | ||
| 24 | * F10, this is extended to L3 cache scrubbing on CPU models sporting that | ||
| 25 | * functionality. | ||
| 26 | * | ||
| 27 | * This causes the "units" for the scrubbing speed to vary from 64 byte blocks | ||
| 28 | * (dram) over to cache lines. This is nasty, so we will use bandwidth in | ||
| 29 | * bytes/sec for the setting. | ||
| 30 | * | ||
| 31 | * Currently, we only do dram scrubbing. If the scrubbing is done in software on | ||
| 32 | * other archs, we might not have access to the caches directly. | ||
| 33 | */ | ||
| 34 | |||
| 35 | /* | ||
| 36 | * scan the scrub rate mapping table for a close or matching bandwidth value to | ||
| 37 | * issue. If requested is too big, then use last maximum value found. | ||
| 38 | */ | ||
| 39 | static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, | ||
| 40 | u32 min_scrubrate) | ||
| 41 | { | ||
| 42 | u32 scrubval; | ||
| 43 | int i; | ||
| 44 | |||
| 45 | /* | ||
| 46 | * map the configured rate (new_bw) to a value specific to the AMD64 | ||
| 47 | * memory controller and apply to register. Search for the first | ||
| 48 | * bandwidth entry that is greater or equal than the setting requested | ||
| 49 | * and program that. If at last entry, turn off DRAM scrubbing. | ||
| 50 | */ | ||
| 51 | for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { | ||
| 52 | /* | ||
| 53 | * skip scrub rates which aren't recommended | ||
| 54 | * (see F10 BKDG, F3x58) | ||
| 55 | */ | ||
| 56 | if (scrubrates[i].scrubval < min_scrubrate) | ||
| 57 | continue; | ||
| 58 | |||
| 59 | if (scrubrates[i].bandwidth <= new_bw) | ||
| 60 | break; | ||
| 61 | |||
| 62 | /* | ||
| 63 | * if no suitable bandwidth found, turn off DRAM scrubbing | ||
| 64 | * entirely by falling back to the last element in the | ||
| 65 | * scrubrates array. | ||
| 66 | */ | ||
| 67 | } | ||
| 68 | |||
| 69 | scrubval = scrubrates[i].scrubval; | ||
| 70 | if (scrubval) | ||
| 71 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
| 72 | "Setting scrub rate bandwidth: %u\n", | ||
| 73 | scrubrates[i].bandwidth); | ||
| 74 | else | ||
| 75 | edac_printk(KERN_DEBUG, EDAC_MC, "Turning scrubbing off.\n"); | ||
| 76 | |||
| 77 | pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F); | ||
| 78 | |||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | |||
| 82 | static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 *bandwidth) | ||
| 83 | { | ||
| 84 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 85 | u32 min_scrubrate = 0x0; | ||
| 86 | |||
| 87 | switch (boot_cpu_data.x86) { | ||
| 88 | case 0xf: | ||
| 89 | min_scrubrate = K8_MIN_SCRUB_RATE_BITS; | ||
| 90 | break; | ||
| 91 | case 0x10: | ||
| 92 | min_scrubrate = F10_MIN_SCRUB_RATE_BITS; | ||
| 93 | break; | ||
| 94 | case 0x11: | ||
| 95 | min_scrubrate = F11_MIN_SCRUB_RATE_BITS; | ||
| 96 | break; | ||
| 97 | |||
| 98 | default: | ||
| 99 | amd64_printk(KERN_ERR, "Unsupported family!\n"); | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, *bandwidth, | ||
| 103 | min_scrubrate); | ||
| 104 | } | ||
| 105 | |||
| 106 | static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | ||
| 107 | { | ||
| 108 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 109 | u32 scrubval = 0; | ||
| 110 | int status = -1, i, ret = 0; | ||
| 111 | |||
| 112 | ret = pci_read_config_dword(pvt->misc_f3_ctl, K8_SCRCTRL, &scrubval); | ||
| 113 | if (ret) | ||
| 114 | debugf0("Reading K8_SCRCTRL failed\n"); | ||
| 115 | |||
| 116 | scrubval = scrubval & 0x001F; | ||
| 117 | |||
| 118 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
| 119 | "pci-read, sdram scrub control value: %d \n", scrubval); | ||
| 120 | |||
| 121 | for (i = 0; ARRAY_SIZE(scrubrates); i++) { | ||
| 122 | if (scrubrates[i].scrubval == scrubval) { | ||
| 123 | *bw = scrubrates[i].bandwidth; | ||
| 124 | status = 0; | ||
| 125 | break; | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | return status; | ||
| 130 | } | ||
| 131 | |||
| 132 | /* Map from a CSROW entry to the mask entry that operates on it */ | ||
| 133 | static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow) | ||
| 134 | { | ||
| 135 | return csrow >> (pvt->num_dcsm >> 3); | ||
| 136 | } | ||
| 137 | |||
| 138 | /* return the 'base' address the i'th CS entry of the 'dct' DRAM controller */ | ||
| 139 | static u32 amd64_get_dct_base(struct amd64_pvt *pvt, int dct, int csrow) | ||
| 140 | { | ||
| 141 | if (dct == 0) | ||
| 142 | return pvt->dcsb0[csrow]; | ||
| 143 | else | ||
| 144 | return pvt->dcsb1[csrow]; | ||
| 145 | } | ||
| 146 | |||
| 147 | /* | ||
| 148 | * Return the 'mask' address the i'th CS entry. This function is needed because | ||
| 149 | * there number of DCSM registers on Rev E and prior vs Rev F and later is | ||
| 150 | * different. | ||
| 151 | */ | ||
| 152 | static u32 amd64_get_dct_mask(struct amd64_pvt *pvt, int dct, int csrow) | ||
| 153 | { | ||
| 154 | if (dct == 0) | ||
| 155 | return pvt->dcsm0[amd64_map_to_dcs_mask(pvt, csrow)]; | ||
| 156 | else | ||
| 157 | return pvt->dcsm1[amd64_map_to_dcs_mask(pvt, csrow)]; | ||
| 158 | } | ||
| 159 | |||
| 160 | |||
| 161 | /* | ||
| 162 | * In *base and *limit, pass back the full 40-bit base and limit physical | ||
| 163 | * addresses for the node given by node_id. This information is obtained from | ||
| 164 | * DRAM Base (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers. The | ||
| 165 | * base and limit addresses are of type SysAddr, as defined at the start of | ||
| 166 | * section 3.4.4 (p. 70). They are the lowest and highest physical addresses | ||
| 167 | * in the address range they represent. | ||
| 168 | */ | ||
| 169 | static void amd64_get_base_and_limit(struct amd64_pvt *pvt, int node_id, | ||
| 170 | u64 *base, u64 *limit) | ||
| 171 | { | ||
| 172 | *base = pvt->dram_base[node_id]; | ||
| 173 | *limit = pvt->dram_limit[node_id]; | ||
| 174 | } | ||
| 175 | |||
| 176 | /* | ||
| 177 | * Return 1 if the SysAddr given by sys_addr matches the base/limit associated | ||
| 178 | * with node_id | ||
| 179 | */ | ||
| 180 | static int amd64_base_limit_match(struct amd64_pvt *pvt, | ||
| 181 | u64 sys_addr, int node_id) | ||
| 182 | { | ||
| 183 | u64 base, limit, addr; | ||
| 184 | |||
| 185 | amd64_get_base_and_limit(pvt, node_id, &base, &limit); | ||
| 186 | |||
| 187 | /* The K8 treats this as a 40-bit value. However, bits 63-40 will be | ||
| 188 | * all ones if the most significant implemented address bit is 1. | ||
| 189 | * Here we discard bits 63-40. See section 3.4.2 of AMD publication | ||
| 190 | * 24592: AMD x86-64 Architecture Programmer's Manual Volume 1 | ||
| 191 | * Application Programming. | ||
| 192 | */ | ||
| 193 | addr = sys_addr & 0x000000ffffffffffull; | ||
| 194 | |||
| 195 | return (addr >= base) && (addr <= limit); | ||
| 196 | } | ||
| 197 | |||
| 198 | /* | ||
| 199 | * Attempt to map a SysAddr to a node. On success, return a pointer to the | ||
| 200 | * mem_ctl_info structure for the node that the SysAddr maps to. | ||
| 201 | * | ||
| 202 | * On failure, return NULL. | ||
| 203 | */ | ||
| 204 | static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | ||
| 205 | u64 sys_addr) | ||
| 206 | { | ||
| 207 | struct amd64_pvt *pvt; | ||
| 208 | int node_id; | ||
| 209 | u32 intlv_en, bits; | ||
| 210 | |||
| 211 | /* | ||
| 212 | * Here we use the DRAM Base (section 3.4.4.1) and DRAM Limit (section | ||
| 213 | * 3.4.4.2) registers to map the SysAddr to a node ID. | ||
| 214 | */ | ||
| 215 | pvt = mci->pvt_info; | ||
| 216 | |||
| 217 | /* | ||
| 218 | * The value of this field should be the same for all DRAM Base | ||
| 219 | * registers. Therefore we arbitrarily choose to read it from the | ||
| 220 | * register for node 0. | ||
| 221 | */ | ||
| 222 | intlv_en = pvt->dram_IntlvEn[0]; | ||
| 223 | |||
| 224 | if (intlv_en == 0) { | ||
| 225 | for (node_id = 0; ; ) { | ||
| 226 | if (amd64_base_limit_match(pvt, sys_addr, node_id)) | ||
| 227 | break; | ||
| 228 | |||
| 229 | if (++node_id >= DRAM_REG_COUNT) | ||
| 230 | goto err_no_match; | ||
| 231 | } | ||
| 232 | goto found; | ||
| 233 | } | ||
| 234 | |||
| 235 | if (unlikely((intlv_en != (0x01 << 8)) && | ||
| 236 | (intlv_en != (0x03 << 8)) && | ||
| 237 | (intlv_en != (0x07 << 8)))) { | ||
| 238 | amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from " | ||
| 239 | "IntlvEn field of DRAM Base Register for node 0: " | ||
| 240 | "This probably indicates a BIOS bug.\n", intlv_en); | ||
| 241 | return NULL; | ||
| 242 | } | ||
| 243 | |||
| 244 | bits = (((u32) sys_addr) >> 12) & intlv_en; | ||
| 245 | |||
| 246 | for (node_id = 0; ; ) { | ||
| 247 | if ((pvt->dram_limit[node_id] & intlv_en) == bits) | ||
| 248 | break; /* intlv_sel field matches */ | ||
| 249 | |||
| 250 | if (++node_id >= DRAM_REG_COUNT) | ||
| 251 | goto err_no_match; | ||
| 252 | } | ||
| 253 | |||
| 254 | /* sanity test for sys_addr */ | ||
| 255 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { | ||
| 256 | amd64_printk(KERN_WARNING, | ||
| 257 | "%s(): sys_addr 0x%lx falls outside base/limit " | ||
| 258 | "address range for node %d with node interleaving " | ||
| 259 | "enabled.\n", __func__, (unsigned long)sys_addr, | ||
| 260 | node_id); | ||
| 261 | return NULL; | ||
| 262 | } | ||
| 263 | |||
| 264 | found: | ||
| 265 | return edac_mc_find(node_id); | ||
| 266 | |||
| 267 | err_no_match: | ||
| 268 | debugf2("sys_addr 0x%lx doesn't match any node\n", | ||
| 269 | (unsigned long)sys_addr); | ||
| 270 | |||
| 271 | return NULL; | ||
| 272 | } | ||
| 273 | |||
| 274 | /* | ||
| 275 | * Extract the DRAM CS base address from selected csrow register. | ||
| 276 | */ | ||
| 277 | static u64 base_from_dct_base(struct amd64_pvt *pvt, int csrow) | ||
| 278 | { | ||
| 279 | return ((u64) (amd64_get_dct_base(pvt, 0, csrow) & pvt->dcsb_base)) << | ||
| 280 | pvt->dcs_shift; | ||
| 281 | } | ||
| 282 | |||
| 283 | /* | ||
| 284 | * Extract the mask from the dcsb0[csrow] entry in a CPU revision-specific way. | ||
| 285 | */ | ||
| 286 | static u64 mask_from_dct_mask(struct amd64_pvt *pvt, int csrow) | ||
| 287 | { | ||
| 288 | u64 dcsm_bits, other_bits; | ||
| 289 | u64 mask; | ||
| 290 | |||
| 291 | /* Extract bits from DRAM CS Mask. */ | ||
| 292 | dcsm_bits = amd64_get_dct_mask(pvt, 0, csrow) & pvt->dcsm_mask; | ||
| 293 | |||
| 294 | other_bits = pvt->dcsm_mask; | ||
| 295 | other_bits = ~(other_bits << pvt->dcs_shift); | ||
| 296 | |||
| 297 | /* | ||
| 298 | * The extracted bits from DCSM belong in the spaces represented by | ||
| 299 | * the cleared bits in other_bits. | ||
| 300 | */ | ||
| 301 | mask = (dcsm_bits << pvt->dcs_shift) | other_bits; | ||
| 302 | |||
| 303 | return mask; | ||
| 304 | } | ||
| 305 | |||
| 306 | /* | ||
| 307 | * @input_addr is an InputAddr associated with the node given by mci. Return the | ||
| 308 | * csrow that input_addr maps to, or -1 on failure (no csrow claims input_addr). | ||
| 309 | */ | ||
| 310 | static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr) | ||
| 311 | { | ||
| 312 | struct amd64_pvt *pvt; | ||
| 313 | int csrow; | ||
| 314 | u64 base, mask; | ||
| 315 | |||
| 316 | pvt = mci->pvt_info; | ||
| 317 | |||
| 318 | /* | ||
| 319 | * Here we use the DRAM CS Base and DRAM CS Mask registers. For each CS | ||
| 320 | * base/mask register pair, test the condition shown near the start of | ||
| 321 | * section 3.5.4 (p. 84, BKDG #26094, K8, revA-E). | ||
| 322 | */ | ||
| 323 | for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) { | ||
| 324 | |||
| 325 | /* This DRAM chip select is disabled on this node */ | ||
| 326 | if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0) | ||
| 327 | continue; | ||
| 328 | |||
| 329 | base = base_from_dct_base(pvt, csrow); | ||
| 330 | mask = ~mask_from_dct_mask(pvt, csrow); | ||
| 331 | |||
| 332 | if ((input_addr & mask) == (base & mask)) { | ||
| 333 | debugf2("InputAddr 0x%lx matches csrow %d (node %d)\n", | ||
| 334 | (unsigned long)input_addr, csrow, | ||
| 335 | pvt->mc_node_id); | ||
| 336 | |||
| 337 | return csrow; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | debugf2("no matching csrow for InputAddr 0x%lx (MC node %d)\n", | ||
| 342 | (unsigned long)input_addr, pvt->mc_node_id); | ||
| 343 | |||
| 344 | return -1; | ||
| 345 | } | ||
| 346 | |||
| 347 | /* | ||
| 348 | * Return the base value defined by the DRAM Base register for the node | ||
| 349 | * represented by mci. This function returns the full 40-bit value despite the | ||
| 350 | * fact that the register only stores bits 39-24 of the value. See section | ||
| 351 | * 3.4.4.1 (BKDG #26094, K8, revA-E) | ||
| 352 | */ | ||
| 353 | static inline u64 get_dram_base(struct mem_ctl_info *mci) | ||
| 354 | { | ||
| 355 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 356 | |||
| 357 | return pvt->dram_base[pvt->mc_node_id]; | ||
| 358 | } | ||
| 359 | |||
| 360 | /* | ||
| 361 | * Obtain info from the DRAM Hole Address Register (section 3.4.8, pub #26094) | ||
| 362 | * for the node represented by mci. Info is passed back in *hole_base, | ||
| 363 | * *hole_offset, and *hole_size. Function returns 0 if info is valid or 1 if | ||
| 364 | * info is invalid. Info may be invalid for either of the following reasons: | ||
| 365 | * | ||
| 366 | * - The revision of the node is not E or greater. In this case, the DRAM Hole | ||
| 367 | * Address Register does not exist. | ||
| 368 | * | ||
| 369 | * - The DramHoleValid bit is cleared in the DRAM Hole Address Register, | ||
| 370 | * indicating that its contents are not valid. | ||
| 371 | * | ||
| 372 | * The values passed back in *hole_base, *hole_offset, and *hole_size are | ||
| 373 | * complete 32-bit values despite the fact that the bitfields in the DHAR | ||
| 374 | * only represent bits 31-24 of the base and offset values. | ||
| 375 | */ | ||
| 376 | int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, | ||
| 377 | u64 *hole_offset, u64 *hole_size) | ||
| 378 | { | ||
| 379 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 380 | u64 base; | ||
| 381 | |||
| 382 | /* only revE and later have the DRAM Hole Address Register */ | ||
| 383 | if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_E) { | ||
| 384 | debugf1(" revision %d for node %d does not support DHAR\n", | ||
| 385 | pvt->ext_model, pvt->mc_node_id); | ||
| 386 | return 1; | ||
| 387 | } | ||
| 388 | |||
| 389 | /* only valid for Fam10h */ | ||
| 390 | if (boot_cpu_data.x86 == 0x10 && | ||
| 391 | (pvt->dhar & F10_DRAM_MEM_HOIST_VALID) == 0) { | ||
| 392 | debugf1(" Dram Memory Hoisting is DISABLED on this system\n"); | ||
| 393 | return 1; | ||
| 394 | } | ||
| 395 | |||
| 396 | if ((pvt->dhar & DHAR_VALID) == 0) { | ||
| 397 | debugf1(" Dram Memory Hoisting is DISABLED on this node %d\n", | ||
| 398 | pvt->mc_node_id); | ||
| 399 | return 1; | ||
| 400 | } | ||
| 401 | |||
| 402 | /* This node has Memory Hoisting */ | ||
| 403 | |||
| 404 | /* +------------------+--------------------+--------------------+----- | ||
| 405 | * | memory | DRAM hole | relocated | | ||
| 406 | * | [0, (x - 1)] | [x, 0xffffffff] | addresses from | | ||
| 407 | * | | | DRAM hole | | ||
| 408 | * | | | [0x100000000, | | ||
| 409 | * | | | (0x100000000+ | | ||
| 410 | * | | | (0xffffffff-x))] | | ||
| 411 | * +------------------+--------------------+--------------------+----- | ||
| 412 | * | ||
| 413 | * Above is a diagram of physical memory showing the DRAM hole and the | ||
| 414 | * relocated addresses from the DRAM hole. As shown, the DRAM hole | ||
| 415 | * starts at address x (the base address) and extends through address | ||
| 416 | * 0xffffffff. The DRAM Hole Address Register (DHAR) relocates the | ||
| 417 | * addresses in the hole so that they start at 0x100000000. | ||
| 418 | */ | ||
| 419 | |||
| 420 | base = dhar_base(pvt->dhar); | ||
| 421 | |||
| 422 | *hole_base = base; | ||
| 423 | *hole_size = (0x1ull << 32) - base; | ||
| 424 | |||
| 425 | if (boot_cpu_data.x86 > 0xf) | ||
| 426 | *hole_offset = f10_dhar_offset(pvt->dhar); | ||
| 427 | else | ||
| 428 | *hole_offset = k8_dhar_offset(pvt->dhar); | ||
| 429 | |||
| 430 | debugf1(" DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n", | ||
| 431 | pvt->mc_node_id, (unsigned long)*hole_base, | ||
| 432 | (unsigned long)*hole_offset, (unsigned long)*hole_size); | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | } | ||
| 436 | EXPORT_SYMBOL_GPL(amd64_get_dram_hole_info); | ||
| 437 | |||
| 438 | /* | ||
| 439 | * Return the DramAddr that the SysAddr given by @sys_addr maps to. It is | ||
| 440 | * assumed that sys_addr maps to the node given by mci. | ||
| 441 | * | ||
| 442 | * The first part of section 3.4.4 (p. 70) shows how the DRAM Base (section | ||
| 443 | * 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers are used to translate a | ||
| 444 | * SysAddr to a DramAddr. If the DRAM Hole Address Register (DHAR) is enabled, | ||
| 445 | * then it is also involved in translating a SysAddr to a DramAddr. Sections | ||
| 446 | * 3.4.8 and 3.5.8.2 describe the DHAR and how it is used for memory hoisting. | ||
| 447 | * These parts of the documentation are unclear. I interpret them as follows: | ||
| 448 | * | ||
| 449 | * When node n receives a SysAddr, it processes the SysAddr as follows: | ||
| 450 | * | ||
| 451 | * 1. It extracts the DRAMBase and DRAMLimit values from the DRAM Base and DRAM | ||
| 452 | * Limit registers for node n. If the SysAddr is not within the range | ||
| 453 | * specified by the base and limit values, then node n ignores the Sysaddr | ||
| 454 | * (since it does not map to node n). Otherwise continue to step 2 below. | ||
| 455 | * | ||
| 456 | * 2. If the DramHoleValid bit of the DHAR for node n is clear, the DHAR is | ||
| 457 | * disabled so skip to step 3 below. Otherwise see if the SysAddr is within | ||
| 458 | * the range of relocated addresses (starting at 0x100000000) from the DRAM | ||
| 459 | * hole. If not, skip to step 3 below. Else get the value of the | ||
| 460 | * DramHoleOffset field from the DHAR. To obtain the DramAddr, subtract the | ||
| 461 | * offset defined by this value from the SysAddr. | ||
| 462 | * | ||
| 463 | * 3. Obtain the base address for node n from the DRAMBase field of the DRAM | ||
| 464 | * Base register for node n. To obtain the DramAddr, subtract the base | ||
| 465 | * address from the SysAddr, as shown near the start of section 3.4.4 (p.70). | ||
| 466 | */ | ||
| 467 | static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) | ||
| 468 | { | ||
| 469 | u64 dram_base, hole_base, hole_offset, hole_size, dram_addr; | ||
| 470 | int ret = 0; | ||
| 471 | |||
| 472 | dram_base = get_dram_base(mci); | ||
| 473 | |||
| 474 | ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, | ||
| 475 | &hole_size); | ||
| 476 | if (!ret) { | ||
| 477 | if ((sys_addr >= (1ull << 32)) && | ||
| 478 | (sys_addr < ((1ull << 32) + hole_size))) { | ||
| 479 | /* use DHAR to translate SysAddr to DramAddr */ | ||
| 480 | dram_addr = sys_addr - hole_offset; | ||
| 481 | |||
| 482 | debugf2("using DHAR to translate SysAddr 0x%lx to " | ||
| 483 | "DramAddr 0x%lx\n", | ||
| 484 | (unsigned long)sys_addr, | ||
| 485 | (unsigned long)dram_addr); | ||
| 486 | |||
| 487 | return dram_addr; | ||
| 488 | } | ||
| 489 | } | ||
| 490 | |||
| 491 | /* | ||
| 492 | * Translate the SysAddr to a DramAddr as shown near the start of | ||
| 493 | * section 3.4.4 (p. 70). Although sys_addr is a 64-bit value, the k8 | ||
| 494 | * only deals with 40-bit values. Therefore we discard bits 63-40 of | ||
| 495 | * sys_addr below. If bit 39 of sys_addr is 1 then the bits we | ||
| 496 | * discard are all 1s. Otherwise the bits we discard are all 0s. See | ||
| 497 | * section 3.4.2 of AMD publication 24592: AMD x86-64 Architecture | ||
| 498 | * Programmer's Manual Volume 1 Application Programming. | ||
| 499 | */ | ||
| 500 | dram_addr = (sys_addr & 0xffffffffffull) - dram_base; | ||
| 501 | |||
| 502 | debugf2("using DRAM Base register to translate SysAddr 0x%lx to " | ||
| 503 | "DramAddr 0x%lx\n", (unsigned long)sys_addr, | ||
| 504 | (unsigned long)dram_addr); | ||
| 505 | return dram_addr; | ||
| 506 | } | ||
| 507 | |||
| 508 | /* | ||
| 509 | * @intlv_en is the value of the IntlvEn field from a DRAM Base register | ||
| 510 | * (section 3.4.4.1). Return the number of bits from a SysAddr that are used | ||
| 511 | * for node interleaving. | ||
| 512 | */ | ||
| 513 | static int num_node_interleave_bits(unsigned intlv_en) | ||
| 514 | { | ||
| 515 | static const int intlv_shift_table[] = { 0, 1, 0, 2, 0, 0, 0, 3 }; | ||
| 516 | int n; | ||
| 517 | |||
| 518 | BUG_ON(intlv_en > 7); | ||
| 519 | n = intlv_shift_table[intlv_en]; | ||
| 520 | return n; | ||
| 521 | } | ||
| 522 | |||
| 523 | /* Translate the DramAddr given by @dram_addr to an InputAddr. */ | ||
| 524 | static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr) | ||
| 525 | { | ||
| 526 | struct amd64_pvt *pvt; | ||
| 527 | int intlv_shift; | ||
| 528 | u64 input_addr; | ||
| 529 | |||
| 530 | pvt = mci->pvt_info; | ||
| 531 | |||
| 532 | /* | ||
| 533 | * See the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E) | ||
| 534 | * concerning translating a DramAddr to an InputAddr. | ||
| 535 | */ | ||
| 536 | intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]); | ||
| 537 | input_addr = ((dram_addr >> intlv_shift) & 0xffffff000ull) + | ||
| 538 | (dram_addr & 0xfff); | ||
| 539 | |||
| 540 | debugf2(" Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n", | ||
| 541 | intlv_shift, (unsigned long)dram_addr, | ||
| 542 | (unsigned long)input_addr); | ||
| 543 | |||
| 544 | return input_addr; | ||
| 545 | } | ||
| 546 | |||
| 547 | /* | ||
| 548 | * Translate the SysAddr represented by @sys_addr to an InputAddr. It is | ||
| 549 | * assumed that @sys_addr maps to the node given by mci. | ||
| 550 | */ | ||
| 551 | static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr) | ||
| 552 | { | ||
| 553 | u64 input_addr; | ||
| 554 | |||
| 555 | input_addr = | ||
| 556 | dram_addr_to_input_addr(mci, sys_addr_to_dram_addr(mci, sys_addr)); | ||
| 557 | |||
| 558 | debugf2("SysAdddr 0x%lx translates to InputAddr 0x%lx\n", | ||
| 559 | (unsigned long)sys_addr, (unsigned long)input_addr); | ||
| 560 | |||
| 561 | return input_addr; | ||
| 562 | } | ||
| 563 | |||
| 564 | |||
| 565 | /* | ||
| 566 | * @input_addr is an InputAddr associated with the node represented by mci. | ||
| 567 | * Translate @input_addr to a DramAddr and return the result. | ||
| 568 | */ | ||
| 569 | static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) | ||
| 570 | { | ||
| 571 | struct amd64_pvt *pvt; | ||
| 572 | int node_id, intlv_shift; | ||
| 573 | u64 bits, dram_addr; | ||
| 574 | u32 intlv_sel; | ||
| 575 | |||
| 576 | /* | ||
| 577 | * Near the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E) | ||
| 578 | * shows how to translate a DramAddr to an InputAddr. Here we reverse | ||
| 579 | * this procedure. When translating from a DramAddr to an InputAddr, the | ||
| 580 | * bits used for node interleaving are discarded. Here we recover these | ||
| 581 | * bits from the IntlvSel field of the DRAM Limit register (section | ||
| 582 | * 3.4.4.2) for the node that input_addr is associated with. | ||
| 583 | */ | ||
| 584 | pvt = mci->pvt_info; | ||
| 585 | node_id = pvt->mc_node_id; | ||
| 586 | BUG_ON((node_id < 0) || (node_id > 7)); | ||
| 587 | |||
| 588 | intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]); | ||
| 589 | |||
| 590 | if (intlv_shift == 0) { | ||
| 591 | debugf1(" InputAddr 0x%lx translates to DramAddr of " | ||
| 592 | "same value\n", (unsigned long)input_addr); | ||
| 593 | |||
| 594 | return input_addr; | ||
| 595 | } | ||
| 596 | |||
| 597 | bits = ((input_addr & 0xffffff000ull) << intlv_shift) + | ||
| 598 | (input_addr & 0xfff); | ||
| 599 | |||
| 600 | intlv_sel = pvt->dram_IntlvSel[node_id] & ((1 << intlv_shift) - 1); | ||
| 601 | dram_addr = bits + (intlv_sel << 12); | ||
| 602 | |||
| 603 | debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx " | ||
| 604 | "(%d node interleave bits)\n", (unsigned long)input_addr, | ||
| 605 | (unsigned long)dram_addr, intlv_shift); | ||
| 606 | |||
| 607 | return dram_addr; | ||
| 608 | } | ||
| 609 | |||
| 610 | /* | ||
| 611 | * @dram_addr is a DramAddr that maps to the node represented by mci. Convert | ||
| 612 | * @dram_addr to a SysAddr. | ||
| 613 | */ | ||
| 614 | static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) | ||
| 615 | { | ||
| 616 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 617 | u64 hole_base, hole_offset, hole_size, base, limit, sys_addr; | ||
| 618 | int ret = 0; | ||
| 619 | |||
| 620 | ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, | ||
| 621 | &hole_size); | ||
| 622 | if (!ret) { | ||
| 623 | if ((dram_addr >= hole_base) && | ||
| 624 | (dram_addr < (hole_base + hole_size))) { | ||
| 625 | sys_addr = dram_addr + hole_offset; | ||
| 626 | |||
| 627 | debugf1("using DHAR to translate DramAddr 0x%lx to " | ||
| 628 | "SysAddr 0x%lx\n", (unsigned long)dram_addr, | ||
| 629 | (unsigned long)sys_addr); | ||
| 630 | |||
| 631 | return sys_addr; | ||
| 632 | } | ||
| 633 | } | ||
| 634 | |||
| 635 | amd64_get_base_and_limit(pvt, pvt->mc_node_id, &base, &limit); | ||
| 636 | sys_addr = dram_addr + base; | ||
| 637 | |||
| 638 | /* | ||
| 639 | * The sys_addr we have computed up to this point is a 40-bit value | ||
| 640 | * because the k8 deals with 40-bit values. However, the value we are | ||
| 641 | * supposed to return is a full 64-bit physical address. The AMD | ||
| 642 | * x86-64 architecture specifies that the most significant implemented | ||
| 643 | * address bit through bit 63 of a physical address must be either all | ||
| 644 | * 0s or all 1s. Therefore we sign-extend the 40-bit sys_addr to a | ||
| 645 | * 64-bit value below. See section 3.4.2 of AMD publication 24592: | ||
| 646 | * AMD x86-64 Architecture Programmer's Manual Volume 1 Application | ||
| 647 | * Programming. | ||
| 648 | */ | ||
| 649 | sys_addr |= ~((sys_addr & (1ull << 39)) - 1); | ||
| 650 | |||
| 651 | debugf1(" Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n", | ||
| 652 | pvt->mc_node_id, (unsigned long)dram_addr, | ||
| 653 | (unsigned long)sys_addr); | ||
| 654 | |||
| 655 | return sys_addr; | ||
| 656 | } | ||
| 657 | |||
| 658 | /* | ||
| 659 | * @input_addr is an InputAddr associated with the node given by mci. Translate | ||
| 660 | * @input_addr to a SysAddr. | ||
| 661 | */ | ||
| 662 | static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci, | ||
| 663 | u64 input_addr) | ||
| 664 | { | ||
| 665 | return dram_addr_to_sys_addr(mci, | ||
| 666 | input_addr_to_dram_addr(mci, input_addr)); | ||
| 667 | } | ||
| 668 | |||
| 669 | /* | ||
| 670 | * Find the minimum and maximum InputAddr values that map to the given @csrow. | ||
| 671 | * Pass back these values in *input_addr_min and *input_addr_max. | ||
| 672 | */ | ||
| 673 | static void find_csrow_limits(struct mem_ctl_info *mci, int csrow, | ||
| 674 | u64 *input_addr_min, u64 *input_addr_max) | ||
| 675 | { | ||
| 676 | struct amd64_pvt *pvt; | ||
| 677 | u64 base, mask; | ||
| 678 | |||
| 679 | pvt = mci->pvt_info; | ||
| 680 | BUG_ON((csrow < 0) || (csrow >= CHIPSELECT_COUNT)); | ||
| 681 | |||
| 682 | base = base_from_dct_base(pvt, csrow); | ||
| 683 | mask = mask_from_dct_mask(pvt, csrow); | ||
| 684 | |||
| 685 | *input_addr_min = base & ~mask; | ||
| 686 | *input_addr_max = base | mask | pvt->dcs_mask_notused; | ||
| 687 | } | ||
| 688 | |||
| 689 | /* | ||
| 690 | * Extract error address from MCA NB Address Low (section 3.6.4.5) and MCA NB | ||
| 691 | * Address High (section 3.6.4.6) register values and return the result. Address | ||
| 692 | * is located in the info structure (nbeah and nbeal), the encoding is device | ||
| 693 | * specific. | ||
| 694 | */ | ||
| 695 | static u64 extract_error_address(struct mem_ctl_info *mci, | ||
| 696 | struct amd64_error_info_regs *info) | ||
| 697 | { | ||
| 698 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 699 | |||
| 700 | return pvt->ops->get_error_address(mci, info); | ||
| 701 | } | ||
| 702 | |||
| 703 | |||
| 704 | /* Map the Error address to a PAGE and PAGE OFFSET. */ | ||
| 705 | static inline void error_address_to_page_and_offset(u64 error_address, | ||
| 706 | u32 *page, u32 *offset) | ||
| 707 | { | ||
| 708 | *page = (u32) (error_address >> PAGE_SHIFT); | ||
| 709 | *offset = ((u32) error_address) & ~PAGE_MASK; | ||
| 710 | } | ||
| 711 | |||
| 712 | /* | ||
| 713 | * @sys_addr is an error address (a SysAddr) extracted from the MCA NB Address | ||
| 714 | * Low (section 3.6.4.5) and MCA NB Address High (section 3.6.4.6) registers | ||
| 715 | * of a node that detected an ECC memory error. mci represents the node that | ||
| 716 | * the error address maps to (possibly different from the node that detected | ||
| 717 | * the error). Return the number of the csrow that sys_addr maps to, or -1 on | ||
| 718 | * error. | ||
| 719 | */ | ||
| 720 | static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) | ||
| 721 | { | ||
| 722 | int csrow; | ||
| 723 | |||
| 724 | csrow = input_addr_to_csrow(mci, sys_addr_to_input_addr(mci, sys_addr)); | ||
| 725 | |||
| 726 | if (csrow == -1) | ||
| 727 | amd64_mc_printk(mci, KERN_ERR, | ||
| 728 | "Failed to translate InputAddr to csrow for " | ||
| 729 | "address 0x%lx\n", (unsigned long)sys_addr); | ||
| 730 | return csrow; | ||
| 731 | } | ||
| 732 | |||
| 733 | static int get_channel_from_ecc_syndrome(unsigned short syndrome); | ||
| 734 | |||
| 735 | static void amd64_cpu_display_info(struct amd64_pvt *pvt) | ||
| 736 | { | ||
| 737 | if (boot_cpu_data.x86 == 0x11) | ||
| 738 | edac_printk(KERN_DEBUG, EDAC_MC, "F11h CPU detected\n"); | ||
| 739 | else if (boot_cpu_data.x86 == 0x10) | ||
| 740 | edac_printk(KERN_DEBUG, EDAC_MC, "F10h CPU detected\n"); | ||
| 741 | else if (boot_cpu_data.x86 == 0xf) | ||
| 742 | edac_printk(KERN_DEBUG, EDAC_MC, "%s detected\n", | ||
| 743 | (pvt->ext_model >= OPTERON_CPU_REV_F) ? | ||
| 744 | "Rev F or later" : "Rev E or earlier"); | ||
| 745 | else | ||
| 746 | /* we'll hardly ever ever get here */ | ||
| 747 | edac_printk(KERN_ERR, EDAC_MC, "Unknown cpu!\n"); | ||
| 748 | } | ||
| 749 | |||
| 750 | /* | ||
| 751 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs | ||
| 752 | * are ECC capable. | ||
| 753 | */ | ||
| 754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) | ||
| 755 | { | ||
| 756 | int bit; | ||
| 757 | enum dev_type edac_cap = EDAC_NONE; | ||
| 758 | |||
| 759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= OPTERON_CPU_REV_F) | ||
| 760 | ? 19 | ||
| 761 | : 17; | ||
| 762 | |||
| 763 | if (pvt->dclr0 >> BIT(bit)) | ||
| 764 | edac_cap = EDAC_FLAG_SECDED; | ||
| 765 | |||
| 766 | return edac_cap; | ||
| 767 | } | ||
| 768 | |||
| 769 | |||
| 770 | static void f10_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt, | ||
| 771 | int ganged); | ||
| 772 | |||
| 773 | /* Display and decode various NB registers for debug purposes. */ | ||
| 774 | static void amd64_dump_misc_regs(struct amd64_pvt *pvt) | ||
| 775 | { | ||
| 776 | int ganged; | ||
| 777 | |||
| 778 | debugf1(" nbcap:0x%8.08x DctDualCap=%s DualNode=%s 8-Node=%s\n", | ||
| 779 | pvt->nbcap, | ||
| 780 | (pvt->nbcap & K8_NBCAP_DCT_DUAL) ? "True" : "False", | ||
| 781 | (pvt->nbcap & K8_NBCAP_DUAL_NODE) ? "True" : "False", | ||
| 782 | (pvt->nbcap & K8_NBCAP_8_NODE) ? "True" : "False"); | ||
| 783 | debugf1(" ECC Capable=%s ChipKill Capable=%s\n", | ||
| 784 | (pvt->nbcap & K8_NBCAP_SECDED) ? "True" : "False", | ||
| 785 | (pvt->nbcap & K8_NBCAP_CHIPKILL) ? "True" : "False"); | ||
| 786 | debugf1(" DramCfg0-low=0x%08x DIMM-ECC=%s Parity=%s Width=%s\n", | ||
| 787 | pvt->dclr0, | ||
| 788 | (pvt->dclr0 & BIT(19)) ? "Enabled" : "Disabled", | ||
| 789 | (pvt->dclr0 & BIT(8)) ? "Enabled" : "Disabled", | ||
| 790 | (pvt->dclr0 & BIT(11)) ? "128b" : "64b"); | ||
| 791 | debugf1(" DIMM x4 Present: L0=%s L1=%s L2=%s L3=%s DIMM Type=%s\n", | ||
| 792 | (pvt->dclr0 & BIT(12)) ? "Y" : "N", | ||
| 793 | (pvt->dclr0 & BIT(13)) ? "Y" : "N", | ||
| 794 | (pvt->dclr0 & BIT(14)) ? "Y" : "N", | ||
| 795 | (pvt->dclr0 & BIT(15)) ? "Y" : "N", | ||
| 796 | (pvt->dclr0 & BIT(16)) ? "UN-Buffered" : "Buffered"); | ||
| 797 | |||
| 798 | |||
| 799 | debugf1(" online-spare: 0x%8.08x\n", pvt->online_spare); | ||
| 800 | |||
| 801 | if (boot_cpu_data.x86 == 0xf) { | ||
| 802 | debugf1(" dhar: 0x%8.08x Base=0x%08x Offset=0x%08x\n", | ||
| 803 | pvt->dhar, dhar_base(pvt->dhar), | ||
| 804 | k8_dhar_offset(pvt->dhar)); | ||
| 805 | debugf1(" DramHoleValid=%s\n", | ||
| 806 | (pvt->dhar & DHAR_VALID) ? "True" : "False"); | ||
| 807 | |||
| 808 | debugf1(" dbam-dkt: 0x%8.08x\n", pvt->dbam0); | ||
| 809 | |||
| 810 | /* everything below this point is Fam10h and above */ | ||
| 811 | return; | ||
| 812 | |||
| 813 | } else { | ||
| 814 | debugf1(" dhar: 0x%8.08x Base=0x%08x Offset=0x%08x\n", | ||
| 815 | pvt->dhar, dhar_base(pvt->dhar), | ||
| 816 | f10_dhar_offset(pvt->dhar)); | ||
| 817 | debugf1(" DramMemHoistValid=%s DramHoleValid=%s\n", | ||
| 818 | (pvt->dhar & F10_DRAM_MEM_HOIST_VALID) ? | ||
| 819 | "True" : "False", | ||
| 820 | (pvt->dhar & DHAR_VALID) ? | ||
| 821 | "True" : "False"); | ||
| 822 | } | ||
| 823 | |||
| 824 | /* Only if NOT ganged does dcl1 have valid info */ | ||
| 825 | if (!dct_ganging_enabled(pvt)) { | ||
| 826 | debugf1(" DramCfg1-low=0x%08x DIMM-ECC=%s Parity=%s " | ||
| 827 | "Width=%s\n", pvt->dclr1, | ||
| 828 | (pvt->dclr1 & BIT(19)) ? "Enabled" : "Disabled", | ||
| 829 | (pvt->dclr1 & BIT(8)) ? "Enabled" : "Disabled", | ||
| 830 | (pvt->dclr1 & BIT(11)) ? "128b" : "64b"); | ||
| 831 | debugf1(" DIMM x4 Present: L0=%s L1=%s L2=%s L3=%s " | ||
| 832 | "DIMM Type=%s\n", | ||
| 833 | (pvt->dclr1 & BIT(12)) ? "Y" : "N", | ||
| 834 | (pvt->dclr1 & BIT(13)) ? "Y" : "N", | ||
| 835 | (pvt->dclr1 & BIT(14)) ? "Y" : "N", | ||
| 836 | (pvt->dclr1 & BIT(15)) ? "Y" : "N", | ||
| 837 | (pvt->dclr1 & BIT(16)) ? "UN-Buffered" : "Buffered"); | ||
| 838 | } | ||
| 839 | |||
| 840 | /* | ||
| 841 | * Determine if ganged and then dump memory sizes for first controller, | ||
| 842 | * and if NOT ganged dump info for 2nd controller. | ||
| 843 | */ | ||
| 844 | ganged = dct_ganging_enabled(pvt); | ||
| 845 | |||
| 846 | f10_debug_display_dimm_sizes(0, pvt, ganged); | ||
| 847 | |||
| 848 | if (!ganged) | ||
| 849 | f10_debug_display_dimm_sizes(1, pvt, ganged); | ||
| 850 | } | ||
| 851 | |||
| 852 | /* Read in both of DBAM registers */ | ||
| 853 | static void amd64_read_dbam_reg(struct amd64_pvt *pvt) | ||
| 854 | { | ||
| 855 | int err = 0; | ||
| 856 | unsigned int reg; | ||
| 857 | |||
| 858 | reg = DBAM0; | ||
| 859 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, &pvt->dbam0); | ||
| 860 | if (err) | ||
| 861 | goto err_reg; | ||
| 862 | |||
| 863 | if (boot_cpu_data.x86 >= 0x10) { | ||
| 864 | reg = DBAM1; | ||
| 865 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, &pvt->dbam1); | ||
| 866 | |||
| 867 | if (err) | ||
| 868 | goto err_reg; | ||
| 869 | } | ||
| 870 | |||
| 871 | err_reg: | ||
| 872 | debugf0("Error reading F2x%03x.\n", reg); | ||
| 873 | } | ||
| 874 | |||
| 875 | /* | ||
| 876 | * NOTE: CPU Revision Dependent code: Rev E and Rev F | ||
| 877 | * | ||
| 878 | * Set the DCSB and DCSM mask values depending on the CPU revision value. Also | ||
| 879 | * set the shift factor for the DCSB and DCSM values. | ||
| 880 | * | ||
| 881 | * ->dcs_mask_notused, RevE: | ||
| 882 | * | ||
| 883 | * To find the max InputAddr for the csrow, start with the base address and set | ||
| 884 | * all bits that are "don't care" bits in the test at the start of section | ||
| 885 | * 3.5.4 (p. 84). | ||
| 886 | * | ||
| 887 | * The "don't care" bits are all set bits in the mask and all bits in the gaps | ||
| 888 | * between bit ranges [35:25] and [19:13]. The value REV_E_DCS_NOTUSED_BITS | ||
| 889 | * represents bits [24:20] and [12:0], which are all bits in the above-mentioned | ||
| 890 | * gaps. | ||
| 891 | * | ||
| 892 | * ->dcs_mask_notused, RevF and later: | ||
| 893 | * | ||
| 894 | * To find the max InputAddr for the csrow, start with the base address and set | ||
| 895 | * all bits that are "don't care" bits in the test at the start of NPT section | ||
| 896 | * 4.5.4 (p. 87). | ||
| 897 | * | ||
| 898 | * The "don't care" bits are all set bits in the mask and all bits in the gaps | ||
| 899 | * between bit ranges [36:27] and [21:13]. | ||
| 900 | * | ||
| 901 | * The value REV_F_F1Xh_DCS_NOTUSED_BITS represents bits [26:22] and [12:0], | ||
| 902 | * which are all bits in the above-mentioned gaps. | ||
| 903 | */ | ||
| 904 | static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) | ||
| 905 | { | ||
| 906 | if (pvt->ext_model >= OPTERON_CPU_REV_F) { | ||
| 907 | pvt->dcsb_base = REV_F_F1Xh_DCSB_BASE_BITS; | ||
| 908 | pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; | ||
| 909 | pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; | ||
| 910 | pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; | ||
| 911 | |||
| 912 | switch (boot_cpu_data.x86) { | ||
| 913 | case 0xf: | ||
| 914 | pvt->num_dcsm = REV_F_DCSM_COUNT; | ||
| 915 | break; | ||
| 916 | |||
| 917 | case 0x10: | ||
| 918 | pvt->num_dcsm = F10_DCSM_COUNT; | ||
| 919 | break; | ||
| 920 | |||
| 921 | case 0x11: | ||
| 922 | pvt->num_dcsm = F11_DCSM_COUNT; | ||
| 923 | break; | ||
| 924 | |||
| 925 | default: | ||
| 926 | amd64_printk(KERN_ERR, "Unsupported family!\n"); | ||
| 927 | break; | ||
| 928 | } | ||
| 929 | } else { | ||
| 930 | pvt->dcsb_base = REV_E_DCSB_BASE_BITS; | ||
| 931 | pvt->dcsm_mask = REV_E_DCSM_MASK_BITS; | ||
| 932 | pvt->dcs_mask_notused = REV_E_DCS_NOTUSED_BITS; | ||
| 933 | pvt->dcs_shift = REV_E_DCS_SHIFT; | ||
| 934 | pvt->num_dcsm = REV_E_DCSM_COUNT; | ||
| 935 | } | ||
| 936 | } | ||
| 937 | |||
| 938 | /* | ||
| 939 | * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask hw registers | ||
| 940 | */ | ||
| 941 | static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | ||
| 942 | { | ||
| 943 | int cs, reg, err = 0; | ||
| 944 | |||
| 945 | amd64_set_dct_base_and_mask(pvt); | ||
| 946 | |||
| 947 | for (cs = 0; cs < CHIPSELECT_COUNT; cs++) { | ||
| 948 | reg = K8_DCSB0 + (cs * 4); | ||
| 949 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, | ||
| 950 | &pvt->dcsb0[cs]); | ||
| 951 | if (unlikely(err)) | ||
| 952 | debugf0("Reading K8_DCSB0[%d] failed\n", cs); | ||
| 953 | else | ||
| 954 | debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", | ||
| 955 | cs, pvt->dcsb0[cs], reg); | ||
| 956 | |||
| 957 | /* If DCT are NOT ganged, then read in DCT1's base */ | ||
| 958 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { | ||
| 959 | reg = F10_DCSB1 + (cs * 4); | ||
| 960 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, | ||
| 961 | &pvt->dcsb1[cs]); | ||
| 962 | if (unlikely(err)) | ||
| 963 | debugf0("Reading F10_DCSB1[%d] failed\n", cs); | ||
| 964 | else | ||
| 965 | debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", | ||
| 966 | cs, pvt->dcsb1[cs], reg); | ||
| 967 | } else { | ||
| 968 | pvt->dcsb1[cs] = 0; | ||
| 969 | } | ||
| 970 | } | ||
| 971 | |||
| 972 | for (cs = 0; cs < pvt->num_dcsm; cs++) { | ||
| 973 | reg = K8_DCSB0 + (cs * 4); | ||
| 974 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, | ||
| 975 | &pvt->dcsm0[cs]); | ||
| 976 | if (unlikely(err)) | ||
| 977 | debugf0("Reading K8_DCSM0 failed\n"); | ||
| 978 | else | ||
| 979 | debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", | ||
| 980 | cs, pvt->dcsm0[cs], reg); | ||
| 981 | |||
| 982 | /* If DCT are NOT ganged, then read in DCT1's mask */ | ||
| 983 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { | ||
| 984 | reg = F10_DCSM1 + (cs * 4); | ||
| 985 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, | ||
| 986 | &pvt->dcsm1[cs]); | ||
| 987 | if (unlikely(err)) | ||
| 988 | debugf0("Reading F10_DCSM1[%d] failed\n", cs); | ||
| 989 | else | ||
| 990 | debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", | ||
| 991 | cs, pvt->dcsm1[cs], reg); | ||
| 992 | } else | ||
| 993 | pvt->dcsm1[cs] = 0; | ||
| 994 | } | ||
| 995 | } | ||
| 996 | |||
| 997 | static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt) | ||
| 998 | { | ||
| 999 | enum mem_type type; | ||
| 1000 | |||
| 1001 | if (boot_cpu_data.x86 >= 0x10 || pvt->ext_model >= OPTERON_CPU_REV_F) { | ||
| 1002 | /* Rev F and later */ | ||
| 1003 | type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2; | ||
| 1004 | } else { | ||
| 1005 | /* Rev E and earlier */ | ||
| 1006 | type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | debugf1(" Memory type is: %s\n", | ||
| 1010 | (type == MEM_DDR2) ? "MEM_DDR2" : | ||
| 1011 | (type == MEM_RDDR2) ? "MEM_RDDR2" : | ||
| 1012 | (type == MEM_DDR) ? "MEM_DDR" : "MEM_RDDR"); | ||
| 1013 | |||
| 1014 | return type; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | /* | ||
| 1018 | * Read the DRAM Configuration Low register. It differs between CG, D & E revs | ||
| 1019 | * and the later RevF memory controllers (DDR vs DDR2) | ||
| 1020 | * | ||
| 1021 | * Return: | ||
| 1022 | * number of memory channels in operation | ||
| 1023 | * Pass back: | ||
| 1024 | * contents of the DCL0_LOW register | ||
| 1025 | */ | ||
| 1026 | static int k8_early_channel_count(struct amd64_pvt *pvt) | ||
| 1027 | { | ||
| 1028 | int flag, err = 0; | ||
| 1029 | |||
| 1030 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | ||
| 1031 | if (err) | ||
| 1032 | return err; | ||
| 1033 | |||
| 1034 | if ((boot_cpu_data.x86_model >> 4) >= OPTERON_CPU_REV_F) { | ||
| 1035 | /* RevF (NPT) and later */ | ||
| 1036 | flag = pvt->dclr0 & F10_WIDTH_128; | ||
| 1037 | } else { | ||
| 1038 | /* RevE and earlier */ | ||
| 1039 | flag = pvt->dclr0 & REVE_WIDTH_128; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | /* not used */ | ||
| 1043 | pvt->dclr1 = 0; | ||
| 1044 | |||
| 1045 | return (flag) ? 2 : 1; | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | /* extract the ERROR ADDRESS for the K8 CPUs */ | ||
| 1049 | static u64 k8_get_error_address(struct mem_ctl_info *mci, | ||
| 1050 | struct amd64_error_info_regs *info) | ||
| 1051 | { | ||
| 1052 | return (((u64) (info->nbeah & 0xff)) << 32) + | ||
| 1053 | (info->nbeal & ~0x03); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | /* | ||
| 1057 | * Read the Base and Limit registers for K8 based Memory controllers; extract | ||
| 1058 | * fields from the 'raw' reg into separate data fields | ||
| 1059 | * | ||
| 1060 | * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN | ||
| 1061 | */ | ||
| 1062 | static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | ||
| 1063 | { | ||
| 1064 | u32 low; | ||
| 1065 | u32 off = dram << 3; /* 8 bytes between DRAM entries */ | ||
| 1066 | int err; | ||
| 1067 | |||
| 1068 | err = pci_read_config_dword(pvt->addr_f1_ctl, | ||
| 1069 | K8_DRAM_BASE_LOW + off, &low); | ||
| 1070 | if (err) | ||
| 1071 | debugf0("Reading K8_DRAM_BASE_LOW failed\n"); | ||
| 1072 | |||
| 1073 | /* Extract parts into separate data entries */ | ||
| 1074 | pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; | ||
| 1075 | pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; | ||
| 1076 | pvt->dram_rw_en[dram] = (low & 0x3); | ||
| 1077 | |||
| 1078 | err = pci_read_config_dword(pvt->addr_f1_ctl, | ||
| 1079 | K8_DRAM_LIMIT_LOW + off, &low); | ||
| 1080 | if (err) | ||
| 1081 | debugf0("Reading K8_DRAM_LIMIT_LOW failed\n"); | ||
| 1082 | |||
| 1083 | /* | ||
| 1084 | * Extract parts into separate data entries. Limit is the HIGHEST memory | ||
| 1085 | * location of the region, so lower 24 bits need to be all ones | ||
| 1086 | */ | ||
| 1087 | pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 8) | 0x00FFFFFF; | ||
| 1088 | pvt->dram_IntlvSel[dram] = (low >> 8) & 0x7; | ||
| 1089 | pvt->dram_DstNode[dram] = (low & 0x7); | ||
| 1090 | } | ||
| 1091 | |||
| 1092 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | ||
| 1093 | struct amd64_error_info_regs *info, | ||
| 1094 | u64 SystemAddress) | ||
| 1095 | { | ||
| 1096 | struct mem_ctl_info *src_mci; | ||
| 1097 | unsigned short syndrome; | ||
| 1098 | int channel, csrow; | ||
| 1099 | u32 page, offset; | ||
| 1100 | |||
| 1101 | /* Extract the syndrome parts and form a 16-bit syndrome */ | ||
| 1102 | syndrome = EXTRACT_HIGH_SYNDROME(info->nbsl) << 8; | ||
| 1103 | syndrome |= EXTRACT_LOW_SYNDROME(info->nbsh); | ||
| 1104 | |||
| 1105 | /* CHIPKILL enabled */ | ||
| 1106 | if (info->nbcfg & K8_NBCFG_CHIPKILL) { | ||
| 1107 | channel = get_channel_from_ecc_syndrome(syndrome); | ||
| 1108 | if (channel < 0) { | ||
| 1109 | /* | ||
| 1110 | * Syndrome didn't map, so we don't know which of the | ||
| 1111 | * 2 DIMMs is in error. So we need to ID 'both' of them | ||
| 1112 | * as suspect. | ||
| 1113 | */ | ||
| 1114 | amd64_mc_printk(mci, KERN_WARNING, | ||
| 1115 | "unknown syndrome 0x%x - possible error " | ||
| 1116 | "reporting race\n", syndrome); | ||
| 1117 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | ||
| 1118 | return; | ||
| 1119 | } | ||
| 1120 | } else { | ||
| 1121 | /* | ||
| 1122 | * non-chipkill ecc mode | ||
| 1123 | * | ||
| 1124 | * The k8 documentation is unclear about how to determine the | ||
| 1125 | * channel number when using non-chipkill memory. This method | ||
| 1126 | * was obtained from email communication with someone at AMD. | ||
| 1127 | * (Wish the email was placed in this comment - norsk) | ||
| 1128 | */ | ||
| 1129 | channel = ((SystemAddress & BIT(3)) != 0); | ||
| 1130 | } | ||
| 1131 | |||
| 1132 | /* | ||
| 1133 | * Find out which node the error address belongs to. This may be | ||
| 1134 | * different from the node that detected the error. | ||
| 1135 | */ | ||
| 1136 | src_mci = find_mc_by_sys_addr(mci, SystemAddress); | ||
| 1137 | if (src_mci) { | ||
| 1138 | amd64_mc_printk(mci, KERN_ERR, | ||
| 1139 | "failed to map error address 0x%lx to a node\n", | ||
| 1140 | (unsigned long)SystemAddress); | ||
| 1141 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | ||
| 1142 | return; | ||
| 1143 | } | ||
| 1144 | |||
| 1145 | /* Now map the SystemAddress to a CSROW */ | ||
| 1146 | csrow = sys_addr_to_csrow(src_mci, SystemAddress); | ||
| 1147 | if (csrow < 0) { | ||
| 1148 | edac_mc_handle_ce_no_info(src_mci, EDAC_MOD_STR); | ||
| 1149 | } else { | ||
| 1150 | error_address_to_page_and_offset(SystemAddress, &page, &offset); | ||
| 1151 | |||
| 1152 | edac_mc_handle_ce(src_mci, page, offset, syndrome, csrow, | ||
| 1153 | channel, EDAC_MOD_STR); | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | |||
| 1157 | /* | ||
| 1158 | * determrine the number of PAGES in for this DIMM's size based on its DRAM | ||
| 1159 | * Address Mapping. | ||
| 1160 | * | ||
| 1161 | * First step is to calc the number of bits to shift a value of 1 left to | ||
| 1162 | * indicate show many pages. Start with the DBAM value as the starting bits, | ||
| 1163 | * then proceed to adjust those shift bits, based on CPU rev and the table. | ||
| 1164 | * See BKDG on the DBAM | ||
| 1165 | */ | ||
| 1166 | static int k8_dbam_map_to_pages(struct amd64_pvt *pvt, int dram_map) | ||
| 1167 | { | ||
| 1168 | int nr_pages; | ||
| 1169 | |||
| 1170 | if (pvt->ext_model >= OPTERON_CPU_REV_F) { | ||
| 1171 | nr_pages = 1 << (revf_quad_ddr2_shift[dram_map] - PAGE_SHIFT); | ||
| 1172 | } else { | ||
| 1173 | /* | ||
| 1174 | * RevE and less section; this line is tricky. It collapses the | ||
| 1175 | * table used by RevD and later to one that matches revisions CG | ||
| 1176 | * and earlier. | ||
| 1177 | */ | ||
| 1178 | dram_map -= (pvt->ext_model >= OPTERON_CPU_REV_D) ? | ||
| 1179 | (dram_map > 8 ? 4 : (dram_map > 5 ? | ||
| 1180 | 3 : (dram_map > 2 ? 1 : 0))) : 0; | ||
| 1181 | |||
| 1182 | /* 25 shift is 32MiB minimum DIMM size in RevE and prior */ | ||
| 1183 | nr_pages = 1 << (dram_map + 25 - PAGE_SHIFT); | ||
| 1184 | } | ||
| 1185 | |||
| 1186 | return nr_pages; | ||
| 1187 | } | ||
| 1188 | |||
| 1189 | /* | ||
| 1190 | * Get the number of DCT channels in use. | ||
| 1191 | * | ||
| 1192 | * Return: | ||
| 1193 | * number of Memory Channels in operation | ||
| 1194 | * Pass back: | ||
| 1195 | * contents of the DCL0_LOW register | ||
| 1196 | */ | ||
| 1197 | static int f10_early_channel_count(struct amd64_pvt *pvt) | ||
| 1198 | { | ||
| 1199 | int err = 0, channels = 0; | ||
| 1200 | u32 dbam; | ||
| 1201 | |||
| 1202 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | ||
| 1203 | if (err) | ||
| 1204 | goto err_reg; | ||
| 1205 | |||
| 1206 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); | ||
| 1207 | if (err) | ||
| 1208 | goto err_reg; | ||
| 1209 | |||
| 1210 | /* If we are in 128 bit mode, then we are using 2 channels */ | ||
| 1211 | if (pvt->dclr0 & F10_WIDTH_128) { | ||
| 1212 | debugf0("Data WIDTH is 128 bits - 2 channels\n"); | ||
| 1213 | channels = 2; | ||
| 1214 | return channels; | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | /* | ||
| 1218 | * Need to check if in UN-ganged mode: In such, there are 2 channels, | ||
| 1219 | * but they are NOT in 128 bit mode and thus the above 'dcl0' status bit | ||
| 1220 | * will be OFF. | ||
| 1221 | * | ||
| 1222 | * Need to check DCT0[0] and DCT1[0] to see if only one of them has | ||
| 1223 | * their CSEnable bit on. If so, then SINGLE DIMM case. | ||
| 1224 | */ | ||
| 1225 | debugf0("Data WIDTH is NOT 128 bits - need more decoding\n"); | ||
| 1226 | |||
| 1227 | /* | ||
| 1228 | * Check DRAM Bank Address Mapping values for each DIMM to see if there | ||
| 1229 | * is more than just one DIMM present in unganged mode. Need to check | ||
| 1230 | * both controllers since DIMMs can be placed in either one. | ||
| 1231 | */ | ||
| 1232 | channels = 0; | ||
| 1233 | err = pci_read_config_dword(pvt->dram_f2_ctl, DBAM0, &dbam); | ||
| 1234 | if (err) | ||
| 1235 | goto err_reg; | ||
| 1236 | |||
| 1237 | if (DBAM_DIMM(0, dbam) > 0) | ||
| 1238 | channels++; | ||
| 1239 | if (DBAM_DIMM(1, dbam) > 0) | ||
| 1240 | channels++; | ||
| 1241 | if (DBAM_DIMM(2, dbam) > 0) | ||
| 1242 | channels++; | ||
| 1243 | if (DBAM_DIMM(3, dbam) > 0) | ||
| 1244 | channels++; | ||
| 1245 | |||
| 1246 | /* If more than 2 DIMMs are present, then we have 2 channels */ | ||
| 1247 | if (channels > 2) | ||
| 1248 | channels = 2; | ||
| 1249 | else if (channels == 0) { | ||
| 1250 | /* No DIMMs on DCT0, so look at DCT1 */ | ||
| 1251 | err = pci_read_config_dword(pvt->dram_f2_ctl, DBAM1, &dbam); | ||
| 1252 | if (err) | ||
| 1253 | goto err_reg; | ||
| 1254 | |||
| 1255 | if (DBAM_DIMM(0, dbam) > 0) | ||
| 1256 | channels++; | ||
| 1257 | if (DBAM_DIMM(1, dbam) > 0) | ||
| 1258 | channels++; | ||
| 1259 | if (DBAM_DIMM(2, dbam) > 0) | ||
| 1260 | channels++; | ||
| 1261 | if (DBAM_DIMM(3, dbam) > 0) | ||
| 1262 | channels++; | ||
| 1263 | |||
| 1264 | if (channels > 2) | ||
| 1265 | channels = 2; | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | /* If we found ALL 0 values, then assume just ONE DIMM-ONE Channel */ | ||
| 1269 | if (channels == 0) | ||
| 1270 | channels = 1; | ||
| 1271 | |||
| 1272 | debugf0("DIMM count= %d\n", channels); | ||
| 1273 | |||
| 1274 | return channels; | ||
| 1275 | |||
| 1276 | err_reg: | ||
| 1277 | return -1; | ||
| 1278 | |||
| 1279 | } | ||
| 1280 | |||
| 1281 | static int f10_dbam_map_to_pages(struct amd64_pvt *pvt, int dram_map) | ||
| 1282 | { | ||
| 1283 | return 1 << (revf_quad_ddr2_shift[dram_map] - PAGE_SHIFT); | ||
| 1284 | } | ||
| 1285 | |||
| 1286 | /* Enable extended configuration access via 0xCF8 feature */ | ||
| 1287 | static void amd64_setup(struct amd64_pvt *pvt) | ||
| 1288 | { | ||
| 1289 | u32 reg; | ||
| 1290 | |||
| 1291 | pci_read_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); | ||
| 1292 | |||
| 1293 | pvt->flags.cf8_extcfg = !!(reg & F10_NB_CFG_LOW_ENABLE_EXT_CFG); | ||
| 1294 | reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
| 1295 | pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg); | ||
| 1296 | } | ||
| 1297 | |||
| 1298 | /* Restore the extended configuration access via 0xCF8 feature */ | ||
| 1299 | static void amd64_teardown(struct amd64_pvt *pvt) | ||
| 1300 | { | ||
| 1301 | u32 reg; | ||
| 1302 | |||
| 1303 | pci_read_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); | ||
| 1304 | |||
| 1305 | reg &= ~F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
| 1306 | if (pvt->flags.cf8_extcfg) | ||
| 1307 | reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
| 1308 | pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg); | ||
| 1309 | } | ||
| 1310 | |||
| 1311 | static u64 f10_get_error_address(struct mem_ctl_info *mci, | ||
| 1312 | struct amd64_error_info_regs *info) | ||
| 1313 | { | ||
| 1314 | return (((u64) (info->nbeah & 0xffff)) << 32) + | ||
| 1315 | (info->nbeal & ~0x01); | ||
| 1316 | } | ||
| 1317 | |||
| 1318 | /* | ||
| 1319 | * Read the Base and Limit registers for F10 based Memory controllers. Extract | ||
| 1320 | * fields from the 'raw' reg into separate data fields. | ||
| 1321 | * | ||
| 1322 | * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN. | ||
| 1323 | */ | ||
| 1324 | static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | ||
| 1325 | { | ||
| 1326 | u32 high_offset, low_offset, high_base, low_base, high_limit, low_limit; | ||
| 1327 | |||
| 1328 | low_offset = K8_DRAM_BASE_LOW + (dram << 3); | ||
| 1329 | high_offset = F10_DRAM_BASE_HIGH + (dram << 3); | ||
| 1330 | |||
| 1331 | /* read the 'raw' DRAM BASE Address register */ | ||
| 1332 | pci_read_config_dword(pvt->addr_f1_ctl, low_offset, &low_base); | ||
| 1333 | |||
| 1334 | /* Read from the ECS data register */ | ||
| 1335 | pci_read_config_dword(pvt->addr_f1_ctl, high_offset, &high_base); | ||
| 1336 | |||
| 1337 | /* Extract parts into separate data entries */ | ||
| 1338 | pvt->dram_rw_en[dram] = (low_base & 0x3); | ||
| 1339 | |||
| 1340 | if (pvt->dram_rw_en[dram] == 0) | ||
| 1341 | return; | ||
| 1342 | |||
| 1343 | pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7; | ||
| 1344 | |||
| 1345 | pvt->dram_base[dram] = (((((u64) high_base & 0x000000FF) << 32) | | ||
| 1346 | ((u64) low_base & 0xFFFF0000))) << 8; | ||
| 1347 | |||
| 1348 | low_offset = K8_DRAM_LIMIT_LOW + (dram << 3); | ||
| 1349 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); | ||
| 1350 | |||
| 1351 | /* read the 'raw' LIMIT registers */ | ||
| 1352 | pci_read_config_dword(pvt->addr_f1_ctl, low_offset, &low_limit); | ||
| 1353 | |||
| 1354 | /* Read from the ECS data register for the HIGH portion */ | ||
| 1355 | pci_read_config_dword(pvt->addr_f1_ctl, high_offset, &high_limit); | ||
| 1356 | |||
| 1357 | debugf0(" HW Regs: BASE=0x%08x-%08x LIMIT= 0x%08x-%08x\n", | ||
| 1358 | high_base, low_base, high_limit, low_limit); | ||
| 1359 | |||
| 1360 | pvt->dram_DstNode[dram] = (low_limit & 0x7); | ||
| 1361 | pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7; | ||
| 1362 | |||
| 1363 | /* | ||
| 1364 | * Extract address values and form a LIMIT address. Limit is the HIGHEST | ||
| 1365 | * memory location of the region, so low 24 bits need to be all ones. | ||
| 1366 | */ | ||
| 1367 | low_limit |= 0x0000FFFF; | ||
| 1368 | pvt->dram_limit[dram] = | ||
| 1369 | ((((u64) high_limit << 32) + (u64) low_limit) << 8) | (0xFF); | ||
| 1370 | } | ||
| 1371 | |||
| 1372 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | ||
| 1373 | { | ||
| 1374 | int err = 0; | ||
| 1375 | |||
| 1376 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCTL_SEL_LOW, | ||
| 1377 | &pvt->dram_ctl_select_low); | ||
| 1378 | if (err) { | ||
| 1379 | debugf0("Reading F10_DCTL_SEL_LOW failed\n"); | ||
| 1380 | } else { | ||
| 1381 | debugf0("DRAM_DCTL_SEL_LOW=0x%x DctSelBaseAddr=0x%x\n", | ||
| 1382 | pvt->dram_ctl_select_low, dct_sel_baseaddr(pvt)); | ||
| 1383 | |||
| 1384 | debugf0(" DRAM DCTs are=%s DRAM Is=%s DRAM-Ctl-" | ||
| 1385 | "sel-hi-range=%s\n", | ||
| 1386 | (dct_ganging_enabled(pvt) ? "GANGED" : "NOT GANGED"), | ||
| 1387 | (dct_dram_enabled(pvt) ? "Enabled" : "Disabled"), | ||
| 1388 | (dct_high_range_enabled(pvt) ? "Enabled" : "Disabled")); | ||
| 1389 | |||
| 1390 | debugf0(" DctDatIntLv=%s MemCleared=%s DctSelIntLvAddr=0x%x\n", | ||
| 1391 | (dct_data_intlv_enabled(pvt) ? "Enabled" : "Disabled"), | ||
| 1392 | (dct_memory_cleared(pvt) ? "True " : "False "), | ||
| 1393 | dct_sel_interleave_addr(pvt)); | ||
| 1394 | } | ||
| 1395 | |||
| 1396 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCTL_SEL_HIGH, | ||
| 1397 | &pvt->dram_ctl_select_high); | ||
| 1398 | if (err) | ||
| 1399 | debugf0("Reading F10_DCTL_SEL_HIGH failed\n"); | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | /* | ||
| 1403 | * determine channel based on the interleaving mode: F10h BKDG, 2.8.9 Memory | ||
| 1404 | * Interleaving Modes. | ||
| 1405 | */ | ||
| 1406 | static u32 f10_determine_channel(struct amd64_pvt *pvt, u64 sys_addr, | ||
| 1407 | int hi_range_sel, u32 intlv_en) | ||
| 1408 | { | ||
| 1409 | u32 cs, temp, dct_sel_high = (pvt->dram_ctl_select_low >> 1) & 1; | ||
| 1410 | |||
| 1411 | if (dct_ganging_enabled(pvt)) | ||
| 1412 | cs = 0; | ||
| 1413 | else if (hi_range_sel) | ||
| 1414 | cs = dct_sel_high; | ||
| 1415 | else if (dct_interleave_enabled(pvt)) { | ||
| 1416 | /* | ||
| 1417 | * see F2x110[DctSelIntLvAddr] - channel interleave mode | ||
| 1418 | */ | ||
| 1419 | if (dct_sel_interleave_addr(pvt) == 0) | ||
| 1420 | cs = sys_addr >> 6 & 1; | ||
| 1421 | else if ((dct_sel_interleave_addr(pvt) >> 1) & 1) { | ||
| 1422 | temp = hweight_long((u32) ((sys_addr >> 16) & 0x1F)) % 2; | ||
| 1423 | |||
| 1424 | if (dct_sel_interleave_addr(pvt) & 1) | ||
| 1425 | cs = (sys_addr >> 9 & 1) ^ temp; | ||
| 1426 | else | ||
| 1427 | cs = (sys_addr >> 6 & 1) ^ temp; | ||
| 1428 | } else if (intlv_en & 4) | ||
| 1429 | cs = sys_addr >> 15 & 1; | ||
| 1430 | else if (intlv_en & 2) | ||
| 1431 | cs = sys_addr >> 14 & 1; | ||
| 1432 | else if (intlv_en & 1) | ||
| 1433 | cs = sys_addr >> 13 & 1; | ||
| 1434 | else | ||
| 1435 | cs = sys_addr >> 12 & 1; | ||
| 1436 | } else if (dct_high_range_enabled(pvt) && !dct_ganging_enabled(pvt)) | ||
| 1437 | cs = ~dct_sel_high & 1; | ||
| 1438 | else | ||
| 1439 | cs = 0; | ||
| 1440 | |||
| 1441 | return cs; | ||
| 1442 | } | ||
| 1443 | |||
| 1444 | static inline u32 f10_map_intlv_en_to_shift(u32 intlv_en) | ||
| 1445 | { | ||
| 1446 | if (intlv_en == 1) | ||
| 1447 | return 1; | ||
| 1448 | else if (intlv_en == 3) | ||
| 1449 | return 2; | ||
| 1450 | else if (intlv_en == 7) | ||
| 1451 | return 3; | ||
| 1452 | |||
| 1453 | return 0; | ||
| 1454 | } | ||
| 1455 | |||
| 1456 | /* See F10h BKDG, 2.8.10.2 DctSelBaseOffset Programming */ | ||
| 1457 | static inline u64 f10_get_base_addr_offset(u64 sys_addr, int hi_range_sel, | ||
| 1458 | u32 dct_sel_base_addr, | ||
| 1459 | u64 dct_sel_base_off, | ||
| 1460 | u32 hole_valid, u32 hole_off, | ||
| 1461 | u64 dram_base) | ||
| 1462 | { | ||
| 1463 | u64 chan_off; | ||
| 1464 | |||
| 1465 | if (hi_range_sel) { | ||
| 1466 | if (!(dct_sel_base_addr & 0xFFFFF800) && | ||
| 1467 | hole_valid && (sys_addr >= 0x100000000ULL)) | ||
| 1468 | chan_off = hole_off << 16; | ||
| 1469 | else | ||
| 1470 | chan_off = dct_sel_base_off; | ||
| 1471 | } else { | ||
| 1472 | if (hole_valid && (sys_addr >= 0x100000000ULL)) | ||
| 1473 | chan_off = hole_off << 16; | ||
| 1474 | else | ||
| 1475 | chan_off = dram_base & 0xFFFFF8000000ULL; | ||
| 1476 | } | ||
| 1477 | |||
| 1478 | return (sys_addr & 0x0000FFFFFFFFFFC0ULL) - | ||
| 1479 | (chan_off & 0x0000FFFFFF800000ULL); | ||
| 1480 | } | ||
| 1481 | |||
| 1482 | /* Hack for the time being - Can we get this from BIOS?? */ | ||
| 1483 | #define CH0SPARE_RANK 0 | ||
| 1484 | #define CH1SPARE_RANK 1 | ||
| 1485 | |||
| 1486 | /* | ||
| 1487 | * checks if the csrow passed in is marked as SPARED, if so returns the new | ||
| 1488 | * spare row | ||
| 1489 | */ | ||
| 1490 | static inline int f10_process_possible_spare(int csrow, | ||
| 1491 | u32 cs, struct amd64_pvt *pvt) | ||
| 1492 | { | ||
| 1493 | u32 swap_done; | ||
| 1494 | u32 bad_dram_cs; | ||
| 1495 | |||
| 1496 | /* Depending on channel, isolate respective SPARING info */ | ||
| 1497 | if (cs) { | ||
| 1498 | swap_done = F10_ONLINE_SPARE_SWAPDONE1(pvt->online_spare); | ||
| 1499 | bad_dram_cs = F10_ONLINE_SPARE_BADDRAM_CS1(pvt->online_spare); | ||
| 1500 | if (swap_done && (csrow == bad_dram_cs)) | ||
| 1501 | csrow = CH1SPARE_RANK; | ||
| 1502 | } else { | ||
| 1503 | swap_done = F10_ONLINE_SPARE_SWAPDONE0(pvt->online_spare); | ||
| 1504 | bad_dram_cs = F10_ONLINE_SPARE_BADDRAM_CS0(pvt->online_spare); | ||
| 1505 | if (swap_done && (csrow == bad_dram_cs)) | ||
| 1506 | csrow = CH0SPARE_RANK; | ||
| 1507 | } | ||
| 1508 | return csrow; | ||
| 1509 | } | ||
| 1510 | |||
| 1511 | /* | ||
| 1512 | * Iterate over the DRAM DCT "base" and "mask" registers looking for a | ||
| 1513 | * SystemAddr match on the specified 'ChannelSelect' and 'NodeID' | ||
| 1514 | * | ||
| 1515 | * Return: | ||
| 1516 | * -EINVAL: NOT FOUND | ||
| 1517 | * 0..csrow = Chip-Select Row | ||
| 1518 | */ | ||
| 1519 | static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs) | ||
| 1520 | { | ||
| 1521 | struct mem_ctl_info *mci; | ||
| 1522 | struct amd64_pvt *pvt; | ||
| 1523 | u32 cs_base, cs_mask; | ||
| 1524 | int cs_found = -EINVAL; | ||
| 1525 | int csrow; | ||
| 1526 | |||
| 1527 | mci = mci_lookup[nid]; | ||
| 1528 | if (!mci) | ||
| 1529 | return cs_found; | ||
| 1530 | |||
| 1531 | pvt = mci->pvt_info; | ||
| 1532 | |||
| 1533 | debugf1("InputAddr=0x%x channelselect=%d\n", in_addr, cs); | ||
| 1534 | |||
| 1535 | for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) { | ||
| 1536 | |||
| 1537 | cs_base = amd64_get_dct_base(pvt, cs, csrow); | ||
| 1538 | if (!(cs_base & K8_DCSB_CS_ENABLE)) | ||
| 1539 | continue; | ||
| 1540 | |||
| 1541 | /* | ||
| 1542 | * We have an ENABLED CSROW, Isolate just the MASK bits of the | ||
| 1543 | * target: [28:19] and [13:5], which map to [36:27] and [21:13] | ||
| 1544 | * of the actual address. | ||
| 1545 | */ | ||
| 1546 | cs_base &= REV_F_F1Xh_DCSB_BASE_BITS; | ||
| 1547 | |||
| 1548 | /* | ||
| 1549 | * Get the DCT Mask, and ENABLE the reserved bits: [18:16] and | ||
| 1550 | * [4:0] to become ON. Then mask off bits [28:0] ([36:8]) | ||
| 1551 | */ | ||
| 1552 | cs_mask = amd64_get_dct_mask(pvt, cs, csrow); | ||
| 1553 | |||
| 1554 | debugf1(" CSROW=%d CSBase=0x%x RAW CSMask=0x%x\n", | ||
| 1555 | csrow, cs_base, cs_mask); | ||
| 1556 | |||
| 1557 | cs_mask = (cs_mask | 0x0007C01F) & 0x1FFFFFFF; | ||
| 1558 | |||
| 1559 | debugf1(" Final CSMask=0x%x\n", cs_mask); | ||
| 1560 | debugf1(" (InputAddr & ~CSMask)=0x%x " | ||
| 1561 | "(CSBase & ~CSMask)=0x%x\n", | ||
| 1562 | (in_addr & ~cs_mask), (cs_base & ~cs_mask)); | ||
| 1563 | |||
| 1564 | if ((in_addr & ~cs_mask) == (cs_base & ~cs_mask)) { | ||
| 1565 | cs_found = f10_process_possible_spare(csrow, cs, pvt); | ||
| 1566 | |||
| 1567 | debugf1(" MATCH csrow=%d\n", cs_found); | ||
| 1568 | break; | ||
| 1569 | } | ||
| 1570 | } | ||
| 1571 | return cs_found; | ||
| 1572 | } | ||
| 1573 | |||
| 1574 | /* For a given @dram_range, check if @sys_addr falls within it. */ | ||
| 1575 | static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range, | ||
| 1576 | u64 sys_addr, int *nid, int *chan_sel) | ||
| 1577 | { | ||
| 1578 | int node_id, cs_found = -EINVAL, high_range = 0; | ||
| 1579 | u32 intlv_en, intlv_sel, intlv_shift, hole_off; | ||
| 1580 | u32 hole_valid, tmp, dct_sel_base, channel; | ||
| 1581 | u64 dram_base, chan_addr, dct_sel_base_off; | ||
| 1582 | |||
| 1583 | dram_base = pvt->dram_base[dram_range]; | ||
| 1584 | intlv_en = pvt->dram_IntlvEn[dram_range]; | ||
| 1585 | |||
| 1586 | node_id = pvt->dram_DstNode[dram_range]; | ||
| 1587 | intlv_sel = pvt->dram_IntlvSel[dram_range]; | ||
| 1588 | |||
| 1589 | debugf1("(dram=%d) Base=0x%llx SystemAddr= 0x%llx Limit=0x%llx\n", | ||
| 1590 | dram_range, dram_base, sys_addr, pvt->dram_limit[dram_range]); | ||
| 1591 | |||
| 1592 | /* | ||
| 1593 | * This assumes that one node's DHAR is the same as all the other | ||
| 1594 | * nodes' DHAR. | ||
| 1595 | */ | ||
| 1596 | hole_off = (pvt->dhar & 0x0000FF80); | ||
| 1597 | hole_valid = (pvt->dhar & 0x1); | ||
| 1598 | dct_sel_base_off = (pvt->dram_ctl_select_high & 0xFFFFFC00) << 16; | ||
| 1599 | |||
| 1600 | debugf1(" HoleOffset=0x%x HoleValid=0x%x IntlvSel=0x%x\n", | ||
| 1601 | hole_off, hole_valid, intlv_sel); | ||
| 1602 | |||
| 1603 | if (intlv_en || | ||
| 1604 | (intlv_sel != ((sys_addr >> 12) & intlv_en))) | ||
| 1605 | return -EINVAL; | ||
| 1606 | |||
| 1607 | dct_sel_base = dct_sel_baseaddr(pvt); | ||
| 1608 | |||
| 1609 | /* | ||
| 1610 | * check whether addresses >= DctSelBaseAddr[47:27] are to be used to | ||
| 1611 | * select between DCT0 and DCT1. | ||
| 1612 | */ | ||
| 1613 | if (dct_high_range_enabled(pvt) && | ||
| 1614 | !dct_ganging_enabled(pvt) && | ||
| 1615 | ((sys_addr >> 27) >= (dct_sel_base >> 11))) | ||
| 1616 | high_range = 1; | ||
| 1617 | |||
| 1618 | channel = f10_determine_channel(pvt, sys_addr, high_range, intlv_en); | ||
| 1619 | |||
| 1620 | chan_addr = f10_get_base_addr_offset(sys_addr, high_range, dct_sel_base, | ||
| 1621 | dct_sel_base_off, hole_valid, | ||
| 1622 | hole_off, dram_base); | ||
| 1623 | |||
| 1624 | intlv_shift = f10_map_intlv_en_to_shift(intlv_en); | ||
| 1625 | |||
| 1626 | /* remove Node ID (in case of memory interleaving) */ | ||
| 1627 | tmp = chan_addr & 0xFC0; | ||
| 1628 | |||
| 1629 | chan_addr = ((chan_addr >> intlv_shift) & 0xFFFFFFFFF000ULL) | tmp; | ||
| 1630 | |||
| 1631 | /* remove channel interleave and hash */ | ||
| 1632 | if (dct_interleave_enabled(pvt) && | ||
| 1633 | !dct_high_range_enabled(pvt) && | ||
| 1634 | !dct_ganging_enabled(pvt)) { | ||
| 1635 | if (dct_sel_interleave_addr(pvt) != 1) | ||
| 1636 | chan_addr = (chan_addr >> 1) & 0xFFFFFFFFFFFFFFC0ULL; | ||
| 1637 | else { | ||
| 1638 | tmp = chan_addr & 0xFC0; | ||
| 1639 | chan_addr = ((chan_addr & 0xFFFFFFFFFFFFC000ULL) >> 1) | ||
| 1640 | | tmp; | ||
| 1641 | } | ||
| 1642 | } | ||
| 1643 | |||
| 1644 | debugf1(" (ChannelAddrLong=0x%llx) >> 8 becomes InputAddr=0x%x\n", | ||
| 1645 | chan_addr, (u32)(chan_addr >> 8)); | ||
| 1646 | |||
| 1647 | cs_found = f10_lookup_addr_in_dct(chan_addr >> 8, node_id, channel); | ||
| 1648 | |||
| 1649 | if (cs_found >= 0) { | ||
| 1650 | *nid = node_id; | ||
| 1651 | *chan_sel = channel; | ||
| 1652 | } | ||
| 1653 | return cs_found; | ||
| 1654 | } | ||
| 1655 | |||
| 1656 | static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr, | ||
| 1657 | int *node, int *chan_sel) | ||
| 1658 | { | ||
| 1659 | int dram_range, cs_found = -EINVAL; | ||
| 1660 | u64 dram_base, dram_limit; | ||
| 1661 | |||
| 1662 | for (dram_range = 0; dram_range < DRAM_REG_COUNT; dram_range++) { | ||
| 1663 | |||
| 1664 | if (!pvt->dram_rw_en[dram_range]) | ||
| 1665 | continue; | ||
| 1666 | |||
| 1667 | dram_base = pvt->dram_base[dram_range]; | ||
| 1668 | dram_limit = pvt->dram_limit[dram_range]; | ||
| 1669 | |||
| 1670 | if ((dram_base <= sys_addr) && (sys_addr <= dram_limit)) { | ||
| 1671 | |||
| 1672 | cs_found = f10_match_to_this_node(pvt, dram_range, | ||
| 1673 | sys_addr, node, | ||
| 1674 | chan_sel); | ||
| 1675 | if (cs_found >= 0) | ||
| 1676 | break; | ||
| 1677 | } | ||
| 1678 | } | ||
| 1679 | return cs_found; | ||
| 1680 | } | ||
| 1681 | |||
| 1682 | /* | ||
| 1683 | * This the F10h reference code from AMD to map a @sys_addr to NodeID, | ||
| 1684 | * CSROW, Channel. | ||
| 1685 | * | ||
| 1686 | * The @sys_addr is usually an error address received from the hardware. | ||
| 1687 | */ | ||
| 1688 | static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | ||
| 1689 | struct amd64_error_info_regs *info, | ||
| 1690 | u64 sys_addr) | ||
| 1691 | { | ||
| 1692 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 1693 | u32 page, offset; | ||
| 1694 | unsigned short syndrome; | ||
| 1695 | int nid, csrow, chan = 0; | ||
| 1696 | |||
| 1697 | csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); | ||
| 1698 | |||
| 1699 | if (csrow >= 0) { | ||
| 1700 | error_address_to_page_and_offset(sys_addr, &page, &offset); | ||
| 1701 | |||
| 1702 | syndrome = EXTRACT_HIGH_SYNDROME(info->nbsl) << 8; | ||
| 1703 | syndrome |= EXTRACT_LOW_SYNDROME(info->nbsh); | ||
| 1704 | |||
| 1705 | /* | ||
| 1706 | * Is CHIPKILL on? If so, then we can attempt to use the | ||
| 1707 | * syndrome to isolate which channel the error was on. | ||
| 1708 | */ | ||
| 1709 | if (pvt->nbcfg & K8_NBCFG_CHIPKILL) | ||
| 1710 | chan = get_channel_from_ecc_syndrome(syndrome); | ||
| 1711 | |||
| 1712 | if (chan >= 0) { | ||
| 1713 | edac_mc_handle_ce(mci, page, offset, syndrome, | ||
| 1714 | csrow, chan, EDAC_MOD_STR); | ||
| 1715 | } else { | ||
| 1716 | /* | ||
| 1717 | * Channel unknown, report all channels on this | ||
| 1718 | * CSROW as failed. | ||
| 1719 | */ | ||
| 1720 | for (chan = 0; chan < mci->csrows[csrow].nr_channels; | ||
| 1721 | chan++) { | ||
| 1722 | edac_mc_handle_ce(mci, page, offset, | ||
| 1723 | syndrome, | ||
| 1724 | csrow, chan, | ||
| 1725 | EDAC_MOD_STR); | ||
| 1726 | } | ||
| 1727 | } | ||
| 1728 | |||
| 1729 | } else { | ||
| 1730 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | ||
| 1731 | } | ||
| 1732 | } | ||
| 1733 | |||
| 1734 | /* | ||
| 1735 | * Input (@index) is the DBAM DIMM value (1 of 4) used as an index into a shift | ||
| 1736 | * table (revf_quad_ddr2_shift) which starts at 128MB DIMM size. Index of 0 | ||
| 1737 | * indicates an empty DIMM slot, as reported by Hardware on empty slots. | ||
| 1738 | * | ||
| 1739 | * Normalize to 128MB by subracting 27 bit shift. | ||
| 1740 | */ | ||
| 1741 | static int map_dbam_to_csrow_size(int index) | ||
| 1742 | { | ||
| 1743 | int mega_bytes = 0; | ||
| 1744 | |||
| 1745 | if (index > 0 && index <= DBAM_MAX_VALUE) | ||
| 1746 | mega_bytes = ((128 << (revf_quad_ddr2_shift[index]-27))); | ||
| 1747 | |||
| 1748 | return mega_bytes; | ||
| 1749 | } | ||
| 1750 | |||
| 1751 | /* | ||
| 1752 | * debug routine to display the memory sizes of a DIMM (ganged or not) and it | ||
| 1753 | * CSROWs as well | ||
| 1754 | */ | ||
| 1755 | static void f10_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt, | ||
| 1756 | int ganged) | ||
| 1757 | { | ||
| 1758 | int dimm, size0, size1; | ||
| 1759 | u32 dbam; | ||
| 1760 | u32 *dcsb; | ||
| 1761 | |||
| 1762 | debugf1(" dbam%d: 0x%8.08x CSROW is %s\n", ctrl, | ||
| 1763 | ctrl ? pvt->dbam1 : pvt->dbam0, | ||
| 1764 | ganged ? "GANGED - dbam1 not used" : "NON-GANGED"); | ||
| 1765 | |||
| 1766 | dbam = ctrl ? pvt->dbam1 : pvt->dbam0; | ||
| 1767 | dcsb = ctrl ? pvt->dcsb1 : pvt->dcsb0; | ||
| 1768 | |||
| 1769 | /* Dump memory sizes for DIMM and its CSROWs */ | ||
| 1770 | for (dimm = 0; dimm < 4; dimm++) { | ||
| 1771 | |||
| 1772 | size0 = 0; | ||
| 1773 | if (dcsb[dimm*2] & K8_DCSB_CS_ENABLE) | ||
| 1774 | size0 = map_dbam_to_csrow_size(DBAM_DIMM(dimm, dbam)); | ||
| 1775 | |||
| 1776 | size1 = 0; | ||
| 1777 | if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE) | ||
| 1778 | size1 = map_dbam_to_csrow_size(DBAM_DIMM(dimm, dbam)); | ||
| 1779 | |||
| 1780 | debugf1(" CTRL-%d DIMM-%d=%5dMB CSROW-%d=%5dMB " | ||
| 1781 | "CSROW-%d=%5dMB\n", | ||
| 1782 | ctrl, | ||
| 1783 | dimm, | ||
| 1784 | size0 + size1, | ||
| 1785 | dimm * 2, | ||
| 1786 | size0, | ||
| 1787 | dimm * 2 + 1, | ||
| 1788 | size1); | ||
| 1789 | } | ||
| 1790 | } | ||
| 1791 | |||
| 1792 | /* | ||
| 1793 | * Very early hardware probe on pci_probe thread to determine if this module | ||
| 1794 | * supports the hardware. | ||
| 1795 | * | ||
| 1796 | * Return: | ||
| 1797 | * 0 for OK | ||
| 1798 | * 1 for error | ||
| 1799 | */ | ||
| 1800 | static int f10_probe_valid_hardware(struct amd64_pvt *pvt) | ||
| 1801 | { | ||
| 1802 | int ret = 0; | ||
| 1803 | |||
| 1804 | /* | ||
| 1805 | * If we are on a DDR3 machine, we don't know yet if | ||
| 1806 | * we support that properly at this time | ||
| 1807 | */ | ||
| 1808 | if ((pvt->dchr0 & F10_DCHR_Ddr3Mode) || | ||
| 1809 | (pvt->dchr1 & F10_DCHR_Ddr3Mode)) { | ||
| 1810 | |||
| 1811 | amd64_printk(KERN_WARNING, | ||
| 1812 | "%s() This machine is running with DDR3 memory. " | ||
| 1813 | "This is not currently supported. " | ||
| 1814 | "DCHR0=0x%x DCHR1=0x%x\n", | ||
| 1815 | __func__, pvt->dchr0, pvt->dchr1); | ||
| 1816 | |||
| 1817 | amd64_printk(KERN_WARNING, | ||
| 1818 | " Contact '%s' module MAINTAINER to help add" | ||
| 1819 | " support.\n", | ||
| 1820 | EDAC_MOD_STR); | ||
| 1821 | |||
| 1822 | ret = 1; | ||
| 1823 | |||
| 1824 | } | ||
| 1825 | return ret; | ||
| 1826 | } | ||
| 1827 | |||
| 1828 | /* | ||
| 1829 | * There currently are 3 types type of MC devices for AMD Athlon/Opterons | ||
| 1830 | * (as per PCI DEVICE_IDs): | ||
| 1831 | * | ||
| 1832 | * Family K8: That is the Athlon64 and Opteron CPUs. They all have the same PCI | ||
| 1833 | * DEVICE ID, even though there is differences between the different Revisions | ||
| 1834 | * (CG,D,E,F). | ||
| 1835 | * | ||
| 1836 | * Family F10h and F11h. | ||
| 1837 | * | ||
| 1838 | */ | ||
| 1839 | static struct amd64_family_type amd64_family_types[] = { | ||
| 1840 | [K8_CPUS] = { | ||
| 1841 | .ctl_name = "RevF", | ||
| 1842 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, | ||
| 1843 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_K8_NB_MISC, | ||
| 1844 | .ops = { | ||
| 1845 | .early_channel_count = k8_early_channel_count, | ||
| 1846 | .get_error_address = k8_get_error_address, | ||
| 1847 | .read_dram_base_limit = k8_read_dram_base_limit, | ||
| 1848 | .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, | ||
| 1849 | .dbam_map_to_pages = k8_dbam_map_to_pages, | ||
| 1850 | } | ||
| 1851 | }, | ||
| 1852 | [F10_CPUS] = { | ||
| 1853 | .ctl_name = "Family 10h", | ||
| 1854 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_10H_NB_MAP, | ||
| 1855 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_10H_NB_MISC, | ||
| 1856 | .ops = { | ||
| 1857 | .probe_valid_hardware = f10_probe_valid_hardware, | ||
| 1858 | .early_channel_count = f10_early_channel_count, | ||
| 1859 | .get_error_address = f10_get_error_address, | ||
| 1860 | .read_dram_base_limit = f10_read_dram_base_limit, | ||
| 1861 | .read_dram_ctl_register = f10_read_dram_ctl_register, | ||
| 1862 | .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, | ||
| 1863 | .dbam_map_to_pages = f10_dbam_map_to_pages, | ||
| 1864 | } | ||
| 1865 | }, | ||
| 1866 | [F11_CPUS] = { | ||
| 1867 | .ctl_name = "Family 11h", | ||
| 1868 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_11H_NB_MAP, | ||
| 1869 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_11H_NB_MISC, | ||
| 1870 | .ops = { | ||
| 1871 | .probe_valid_hardware = f10_probe_valid_hardware, | ||
| 1872 | .early_channel_count = f10_early_channel_count, | ||
| 1873 | .get_error_address = f10_get_error_address, | ||
| 1874 | .read_dram_base_limit = f10_read_dram_base_limit, | ||
| 1875 | .read_dram_ctl_register = f10_read_dram_ctl_register, | ||
| 1876 | .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, | ||
| 1877 | .dbam_map_to_pages = f10_dbam_map_to_pages, | ||
| 1878 | } | ||
| 1879 | }, | ||
| 1880 | }; | ||
| 1881 | |||
| 1882 | static struct pci_dev *pci_get_related_function(unsigned int vendor, | ||
| 1883 | unsigned int device, | ||
| 1884 | struct pci_dev *related) | ||
| 1885 | { | ||
| 1886 | struct pci_dev *dev = NULL; | ||
| 1887 | |||
| 1888 | dev = pci_get_device(vendor, device, dev); | ||
| 1889 | while (dev) { | ||
| 1890 | if ((dev->bus->number == related->bus->number) && | ||
| 1891 | (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn))) | ||
| 1892 | break; | ||
| 1893 | dev = pci_get_device(vendor, device, dev); | ||
| 1894 | } | ||
| 1895 | |||
| 1896 | return dev; | ||
| 1897 | } | ||
| 1898 | |||
| 1899 | /* | ||
| 1900 | * syndrome mapping table for ECC ChipKill devices | ||
| 1901 | * | ||
| 1902 | * The comment in each row is the token (nibble) number that is in error. | ||
| 1903 | * The least significant nibble of the syndrome is the mask for the bits | ||
| 1904 | * that are in error (need to be toggled) for the particular nibble. | ||
| 1905 | * | ||
| 1906 | * Each row contains 16 entries. | ||
| 1907 | * The first entry (0th) is the channel number for that row of syndromes. | ||
| 1908 | * The remaining 15 entries are the syndromes for the respective Error | ||
| 1909 | * bit mask index. | ||
| 1910 | * | ||
| 1911 | * 1st index entry is 0x0001 mask, indicating that the rightmost bit is the | ||
| 1912 | * bit in error. | ||
| 1913 | * The 2nd index entry is 0x0010 that the second bit is damaged. | ||
| 1914 | * The 3rd index entry is 0x0011 indicating that the rightmost 2 bits | ||
| 1915 | * are damaged. | ||
| 1916 | * Thus so on until index 15, 0x1111, whose entry has the syndrome | ||
| 1917 | * indicating that all 4 bits are damaged. | ||
| 1918 | * | ||
| 1919 | * A search is performed on this table looking for a given syndrome. | ||
| 1920 | * | ||
| 1921 | * See the AMD documentation for ECC syndromes. This ECC table is valid | ||
| 1922 | * across all the versions of the AMD64 processors. | ||
| 1923 | * | ||
| 1924 | * A fast lookup is to use the LAST four bits of the 16-bit syndrome as a | ||
| 1925 | * COLUMN index, then search all ROWS of that column, looking for a match | ||
| 1926 | * with the input syndrome. The ROW value will be the token number. | ||
| 1927 | * | ||
| 1928 | * The 0'th entry on that row, can be returned as the CHANNEL (0 or 1) of this | ||
| 1929 | * error. | ||
| 1930 | */ | ||
| 1931 | #define NUMBER_ECC_ROWS 36 | ||
| 1932 | static const unsigned short ecc_chipkill_syndromes[NUMBER_ECC_ROWS][16] = { | ||
| 1933 | /* Channel 0 syndromes */ | ||
| 1934 | {/*0*/ 0, 0xe821, 0x7c32, 0x9413, 0xbb44, 0x5365, 0xc776, 0x2f57, | ||
| 1935 | 0xdd88, 0x35a9, 0xa1ba, 0x499b, 0x66cc, 0x8eed, 0x1afe, 0xf2df }, | ||
| 1936 | {/*1*/ 0, 0x5d31, 0xa612, 0xfb23, 0x9584, 0xc8b5, 0x3396, 0x6ea7, | ||
| 1937 | 0xeac8, 0xb7f9, 0x4cda, 0x11eb, 0x7f4c, 0x227d, 0xd95e, 0x846f }, | ||
| 1938 | {/*2*/ 0, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007, | ||
| 1939 | 0x0008, 0x0009, 0x000a, 0x000b, 0x000c, 0x000d, 0x000e, 0x000f }, | ||
| 1940 | {/*3*/ 0, 0x2021, 0x3032, 0x1013, 0x4044, 0x6065, 0x7076, 0x5057, | ||
| 1941 | 0x8088, 0xa0a9, 0xb0ba, 0x909b, 0xc0cc, 0xe0ed, 0xf0fe, 0xd0df }, | ||
| 1942 | {/*4*/ 0, 0x5041, 0xa082, 0xf0c3, 0x9054, 0xc015, 0x30d6, 0x6097, | ||
| 1943 | 0xe0a8, 0xb0e9, 0x402a, 0x106b, 0x70fc, 0x20bd, 0xd07e, 0x803f }, | ||
| 1944 | {/*5*/ 0, 0xbe21, 0xd732, 0x6913, 0x2144, 0x9f65, 0xf676, 0x4857, | ||
| 1945 | 0x3288, 0x8ca9, 0xe5ba, 0x5b9b, 0x13cc, 0xaded, 0xc4fe, 0x7adf }, | ||
| 1946 | {/*6*/ 0, 0x4951, 0x8ea2, 0xc7f3, 0x5394, 0x1ac5, 0xdd36, 0x9467, | ||
| 1947 | 0xa1e8, 0xe8b9, 0x2f4a, 0x661b, 0xf27c, 0xbb2d, 0x7cde, 0x358f }, | ||
| 1948 | {/*7*/ 0, 0x74e1, 0x9872, 0xec93, 0xd6b4, 0xa255, 0x4ec6, 0x3a27, | ||
| 1949 | 0x6bd8, 0x1f39, 0xf3aa, 0x874b, 0xbd6c, 0xc98d, 0x251e, 0x51ff }, | ||
| 1950 | {/*8*/ 0, 0x15c1, 0x2a42, 0x3f83, 0xcef4, 0xdb35, 0xe4b6, 0xf177, | ||
| 1951 | 0x4758, 0x5299, 0x6d1a, 0x78db, 0x89ac, 0x9c6d, 0xa3ee, 0xb62f }, | ||
| 1952 | {/*9*/ 0, 0x3d01, 0x1602, 0x2b03, 0x8504, 0xb805, 0x9306, 0xae07, | ||
| 1953 | 0xca08, 0xf709, 0xdc0a, 0xe10b, 0x4f0c, 0x720d, 0x590e, 0x640f }, | ||
| 1954 | {/*a*/ 0, 0x9801, 0xec02, 0x7403, 0x6b04, 0xf305, 0x8706, 0x1f07, | ||
| 1955 | 0xbd08, 0x2509, 0x510a, 0xc90b, 0xd60c, 0x4e0d, 0x3a0e, 0xa20f }, | ||
| 1956 | {/*b*/ 0, 0xd131, 0x6212, 0xb323, 0x3884, 0xe9b5, 0x5a96, 0x8ba7, | ||
| 1957 | 0x1cc8, 0xcdf9, 0x7eda, 0xafeb, 0x244c, 0xf57d, 0x465e, 0x976f }, | ||
| 1958 | {/*c*/ 0, 0xe1d1, 0x7262, 0x93b3, 0xb834, 0x59e5, 0xca56, 0x2b87, | ||
| 1959 | 0xdc18, 0x3dc9, 0xae7a, 0x4fab, 0x542c, 0x85fd, 0x164e, 0xf79f }, | ||
| 1960 | {/*d*/ 0, 0x6051, 0xb0a2, 0xd0f3, 0x1094, 0x70c5, 0xa036, 0xc067, | ||
| 1961 | 0x20e8, 0x40b9, 0x904a, 0x601b, 0x307c, 0x502d, 0x80de, 0xe08f }, | ||
| 1962 | {/*e*/ 0, 0xa4c1, 0xf842, 0x5c83, 0xe6f4, 0x4235, 0x1eb6, 0xba77, | ||
| 1963 | 0x7b58, 0xdf99, 0x831a, 0x27db, 0x9dac, 0x396d, 0x65ee, 0xc12f }, | ||
| 1964 | {/*f*/ 0, 0x11c1, 0x2242, 0x3383, 0xc8f4, 0xd935, 0xeab6, 0xfb77, | ||
| 1965 | 0x4c58, 0x5d99, 0x6e1a, 0x7fdb, 0x84ac, 0x956d, 0xa6ee, 0xb72f }, | ||
| 1966 | |||
| 1967 | /* Channel 1 syndromes */ | ||
| 1968 | {/*10*/ 1, 0x45d1, 0x8a62, 0xcfb3, 0x5e34, 0x1be5, 0xd456, 0x9187, | ||
| 1969 | 0xa718, 0xe2c9, 0x2d7a, 0x68ab, 0xf92c, 0xbcfd, 0x734e, 0x369f }, | ||
| 1970 | {/*11*/ 1, 0x63e1, 0xb172, 0xd293, 0x14b4, 0x7755, 0xa5c6, 0xc627, | ||
| 1971 | 0x28d8, 0x4b39, 0x99aa, 0xfa4b, 0x3c6c, 0x5f8d, 0x8d1e, 0xeeff }, | ||
| 1972 | {/*12*/ 1, 0xb741, 0xd982, 0x6ec3, 0x2254, 0x9515, 0xfbd6, 0x4c97, | ||
| 1973 | 0x33a8, 0x84e9, 0xea2a, 0x5d6b, 0x11fc, 0xa6bd, 0xc87e, 0x7f3f }, | ||
| 1974 | {/*13*/ 1, 0xdd41, 0x6682, 0xbbc3, 0x3554, 0xe815, 0x53d6, 0xce97, | ||
| 1975 | 0x1aa8, 0xc7e9, 0x7c2a, 0xa1fb, 0x2ffc, 0xf2bd, 0x497e, 0x943f }, | ||
| 1976 | {/*14*/ 1, 0x2bd1, 0x3d62, 0x16b3, 0x4f34, 0x64e5, 0x7256, 0x5987, | ||
| 1977 | 0x8518, 0xaec9, 0xb87a, 0x93ab, 0xca2c, 0xe1fd, 0xf74e, 0xdc9f }, | ||
| 1978 | {/*15*/ 1, 0x83c1, 0xc142, 0x4283, 0xa4f4, 0x2735, 0x65b6, 0xe677, | ||
| 1979 | 0xf858, 0x7b99, 0x391a, 0xbadb, 0x5cac, 0xdf6d, 0x9dee, 0x1e2f }, | ||
| 1980 | {/*16*/ 1, 0x8fd1, 0xc562, 0x4ab3, 0xa934, 0x26e5, 0x6c56, 0xe387, | ||
| 1981 | 0xfe18, 0x71c9, 0x3b7a, 0xb4ab, 0x572c, 0xd8fd, 0x924e, 0x1d9f }, | ||
| 1982 | {/*17*/ 1, 0x4791, 0x89e2, 0xce73, 0x5264, 0x15f5, 0xdb86, 0x9c17, | ||
| 1983 | 0xa3b8, 0xe429, 0x2a5a, 0x6dcb, 0xf1dc, 0xb64d, 0x783e, 0x3faf }, | ||
| 1984 | {/*18*/ 1, 0x5781, 0xa9c2, 0xfe43, 0x92a4, 0xc525, 0x3b66, 0x6ce7, | ||
| 1985 | 0xe3f8, 0xb479, 0x4a3a, 0x1dbb, 0x715c, 0x26dd, 0xd89e, 0x8f1f }, | ||
| 1986 | {/*19*/ 1, 0xbf41, 0xd582, 0x6ac3, 0x2954, 0x9615, 0xfcd6, 0x4397, | ||
| 1987 | 0x3ea8, 0x81e9, 0xeb2a, 0x546b, 0x17fc, 0xa8bd, 0xc27e, 0x7d3f }, | ||
| 1988 | {/*1a*/ 1, 0x9891, 0xe1e2, 0x7273, 0x6464, 0xf7f5, 0x8586, 0x1617, | ||
| 1989 | 0xb8b8, 0x2b29, 0x595a, 0xcacb, 0xdcdc, 0x4f4d, 0x3d3e, 0xaeaf }, | ||
| 1990 | {/*1b*/ 1, 0xcce1, 0x4472, 0x8893, 0xfdb4, 0x3f55, 0xb9c6, 0x7527, | ||
| 1991 | 0x56d8, 0x9a39, 0x12aa, 0xde4b, 0xab6c, 0x678d, 0xef1e, 0x23ff }, | ||
| 1992 | {/*1c*/ 1, 0xa761, 0xf9b2, 0x5ed3, 0xe214, 0x4575, 0x1ba6, 0xbcc7, | ||
| 1993 | 0x7328, 0xd449, 0x8a9a, 0x2dfb, 0x913c, 0x365d, 0x688e, 0xcfef }, | ||
| 1994 | {/*1d*/ 1, 0xff61, 0x55b2, 0xaad3, 0x7914, 0x8675, 0x2ca6, 0xd3c7, | ||
| 1995 | 0x9e28, 0x6149, 0xcb9a, 0x34fb, 0xe73c, 0x185d, 0xb28e, 0x4def }, | ||
| 1996 | {/*1e*/ 1, 0x5451, 0xa8a2, 0xfcf3, 0x9694, 0xc2c5, 0x3e36, 0x6a67, | ||
| 1997 | 0xebe8, 0xbfb9, 0x434a, 0x171b, 0x7d7c, 0x292d, 0xd5de, 0x818f }, | ||
| 1998 | {/*1f*/ 1, 0x6fc1, 0xb542, 0xda83, 0x19f4, 0x7635, 0xacb6, 0xc377, | ||
| 1999 | 0x2e58, 0x4199, 0x9b1a, 0xf4db, 0x37ac, 0x586d, 0x82ee, 0xed2f }, | ||
| 2000 | |||
| 2001 | /* ECC bits are also in the set of tokens and they too can go bad | ||
| 2002 | * first 2 cover channel 0, while the second 2 cover channel 1 | ||
| 2003 | */ | ||
| 2004 | {/*20*/ 0, 0xbe01, 0xd702, 0x6903, 0x2104, 0x9f05, 0xf606, 0x4807, | ||
| 2005 | 0x3208, 0x8c09, 0xe50a, 0x5b0b, 0x130c, 0xad0d, 0xc40e, 0x7a0f }, | ||
| 2006 | {/*21*/ 0, 0x4101, 0x8202, 0xc303, 0x5804, 0x1905, 0xda06, 0x9b07, | ||
| 2007 | 0xac08, 0xed09, 0x2e0a, 0x6f0b, 0x640c, 0xb50d, 0x760e, 0x370f }, | ||
| 2008 | {/*22*/ 1, 0xc441, 0x4882, 0x8cc3, 0xf654, 0x3215, 0xbed6, 0x7a97, | ||
| 2009 | 0x5ba8, 0x9fe9, 0x132a, 0xd76b, 0xadfc, 0x69bd, 0xe57e, 0x213f }, | ||
| 2010 | {/*23*/ 1, 0x7621, 0x9b32, 0xed13, 0xda44, 0xac65, 0x4176, 0x3757, | ||
| 2011 | 0x6f88, 0x19a9, 0xf4ba, 0x829b, 0xb5cc, 0xc3ed, 0x2efe, 0x58df } | ||
| 2012 | }; | ||
| 2013 | |||
| 2014 | /* | ||
| 2015 | * Given the syndrome argument, scan each of the channel tables for a syndrome | ||
| 2016 | * match. Depending on which table it is found, return the channel number. | ||
| 2017 | */ | ||
| 2018 | static int get_channel_from_ecc_syndrome(unsigned short syndrome) | ||
| 2019 | { | ||
| 2020 | int row; | ||
| 2021 | int column; | ||
| 2022 | |||
| 2023 | /* Determine column to scan */ | ||
| 2024 | column = syndrome & 0xF; | ||
| 2025 | |||
| 2026 | /* Scan all rows, looking for syndrome, or end of table */ | ||
| 2027 | for (row = 0; row < NUMBER_ECC_ROWS; row++) { | ||
| 2028 | if (ecc_chipkill_syndromes[row][column] == syndrome) | ||
| 2029 | return ecc_chipkill_syndromes[row][0]; | ||
| 2030 | } | ||
| 2031 | |||
| 2032 | debugf0("syndrome(%x) not found\n", syndrome); | ||
| 2033 | return -1; | ||
| 2034 | } | ||
| 2035 | |||
| 2036 | /* | ||
| 2037 | * Check for valid error in the NB Status High register. If so, proceed to read | ||
| 2038 | * NB Status Low, NB Address Low and NB Address High registers and store data | ||
| 2039 | * into error structure. | ||
| 2040 | * | ||
| 2041 | * Returns: | ||
| 2042 | * - 1: if hardware regs contains valid error info | ||
| 2043 | * - 0: if no valid error is indicated | ||
| 2044 | */ | ||
| 2045 | static int amd64_get_error_info_regs(struct mem_ctl_info *mci, | ||
| 2046 | struct amd64_error_info_regs *regs) | ||
| 2047 | { | ||
| 2048 | struct amd64_pvt *pvt; | ||
| 2049 | struct pci_dev *misc_f3_ctl; | ||
| 2050 | int err = 0; | ||
| 2051 | |||
| 2052 | pvt = mci->pvt_info; | ||
| 2053 | misc_f3_ctl = pvt->misc_f3_ctl; | ||
| 2054 | |||
| 2055 | err = pci_read_config_dword(misc_f3_ctl, K8_NBSH, ®s->nbsh); | ||
| 2056 | if (err) | ||
| 2057 | goto err_reg; | ||
| 2058 | |||
| 2059 | if (!(regs->nbsh & K8_NBSH_VALID_BIT)) | ||
| 2060 | return 0; | ||
| 2061 | |||
| 2062 | /* valid error, read remaining error information registers */ | ||
| 2063 | err = pci_read_config_dword(misc_f3_ctl, K8_NBSL, ®s->nbsl); | ||
| 2064 | if (err) | ||
| 2065 | goto err_reg; | ||
| 2066 | |||
| 2067 | err = pci_read_config_dword(misc_f3_ctl, K8_NBEAL, ®s->nbeal); | ||
| 2068 | if (err) | ||
| 2069 | goto err_reg; | ||
| 2070 | |||
| 2071 | err = pci_read_config_dword(misc_f3_ctl, K8_NBEAH, ®s->nbeah); | ||
| 2072 | if (err) | ||
| 2073 | goto err_reg; | ||
| 2074 | |||
| 2075 | err = pci_read_config_dword(misc_f3_ctl, K8_NBCFG, ®s->nbcfg); | ||
| 2076 | if (err) | ||
| 2077 | goto err_reg; | ||
| 2078 | |||
| 2079 | return 1; | ||
| 2080 | |||
| 2081 | err_reg: | ||
| 2082 | debugf0("Reading error info register failed\n"); | ||
| 2083 | return 0; | ||
| 2084 | } | ||
| 2085 | |||
| 2086 | /* | ||
| 2087 | * This function is called to retrieve the error data from hardware and store it | ||
| 2088 | * in the info structure. | ||
| 2089 | * | ||
| 2090 | * Returns: | ||
| 2091 | * - 1: if a valid error is found | ||
| 2092 | * - 0: if no error is found | ||
| 2093 | */ | ||
| 2094 | static int amd64_get_error_info(struct mem_ctl_info *mci, | ||
| 2095 | struct amd64_error_info_regs *info) | ||
| 2096 | { | ||
| 2097 | struct amd64_pvt *pvt; | ||
| 2098 | struct amd64_error_info_regs regs; | ||
| 2099 | |||
| 2100 | pvt = mci->pvt_info; | ||
| 2101 | |||
| 2102 | if (!amd64_get_error_info_regs(mci, info)) | ||
| 2103 | return 0; | ||
| 2104 | |||
| 2105 | /* | ||
| 2106 | * Here's the problem with the K8's EDAC reporting: There are four | ||
| 2107 | * registers which report pieces of error information. They are shared | ||
| 2108 | * between CEs and UEs. Furthermore, contrary to what is stated in the | ||
| 2109 | * BKDG, the overflow bit is never used! Every error always updates the | ||
| 2110 | * reporting registers. | ||
| 2111 | * | ||
| 2112 | * Can you see the race condition? All four error reporting registers | ||
| 2113 | * must be read before a new error updates them! There is no way to read | ||
| 2114 | * all four registers atomically. The best than can be done is to detect | ||
| 2115 | * that a race has occured and then report the error without any kind of | ||
| 2116 | * precision. | ||
| 2117 | * | ||
| 2118 | * What is still positive is that errors are still reported and thus | ||
| 2119 | * problems can still be detected - just not localized because the | ||
| 2120 | * syndrome and address are spread out across registers. | ||
| 2121 | * | ||
| 2122 | * Grrrrr!!!!! Here's hoping that AMD fixes this in some future K8 rev. | ||
| 2123 | * UEs and CEs should have separate register sets with proper overflow | ||
| 2124 | * bits that are used! At very least the problem can be fixed by | ||
| 2125 | * honoring the ErrValid bit in 'nbsh' and not updating registers - just | ||
| 2126 | * set the overflow bit - unless the current error is CE and the new | ||
| 2127 | * error is UE which would be the only situation for overwriting the | ||
| 2128 | * current values. | ||
| 2129 | */ | ||
| 2130 | |||
| 2131 | regs = *info; | ||
| 2132 | |||
| 2133 | /* Use info from the second read - most current */ | ||
| 2134 | if (unlikely(!amd64_get_error_info_regs(mci, info))) | ||
| 2135 | return 0; | ||
| 2136 | |||
| 2137 | /* clear the error bits in hardware */ | ||
| 2138 | pci_write_bits32(pvt->misc_f3_ctl, K8_NBSH, 0, K8_NBSH_VALID_BIT); | ||
| 2139 | |||
| 2140 | /* Check for the possible race condition */ | ||
| 2141 | if ((regs.nbsh != info->nbsh) || | ||
| 2142 | (regs.nbsl != info->nbsl) || | ||
| 2143 | (regs.nbeah != info->nbeah) || | ||
| 2144 | (regs.nbeal != info->nbeal)) { | ||
| 2145 | amd64_mc_printk(mci, KERN_WARNING, | ||
| 2146 | "hardware STATUS read access race condition " | ||
| 2147 | "detected!\n"); | ||
| 2148 | return 0; | ||
| 2149 | } | ||
| 2150 | return 1; | ||
| 2151 | } | ||
| 2152 | |||
| 2153 | static inline void amd64_decode_gart_tlb_error(struct mem_ctl_info *mci, | ||
| 2154 | struct amd64_error_info_regs *info) | ||
| 2155 | { | ||
| 2156 | u32 err_code; | ||
| 2157 | u32 ec_tt; /* error code transaction type (2b) */ | ||
| 2158 | u32 ec_ll; /* error code cache level (2b) */ | ||
| 2159 | |||
| 2160 | err_code = EXTRACT_ERROR_CODE(info->nbsl); | ||
| 2161 | ec_ll = EXTRACT_LL_CODE(err_code); | ||
| 2162 | ec_tt = EXTRACT_TT_CODE(err_code); | ||
| 2163 | |||
| 2164 | amd64_mc_printk(mci, KERN_ERR, | ||
| 2165 | "GART TLB event: transaction type(%s), " | ||
| 2166 | "cache level(%s)\n", tt_msgs[ec_tt], ll_msgs[ec_ll]); | ||
| 2167 | } | ||
| 2168 | |||
| 2169 | static inline void amd64_decode_mem_cache_error(struct mem_ctl_info *mci, | ||
| 2170 | struct amd64_error_info_regs *info) | ||
| 2171 | { | ||
| 2172 | u32 err_code; | ||
| 2173 | u32 ec_rrrr; /* error code memory transaction (4b) */ | ||
| 2174 | u32 ec_tt; /* error code transaction type (2b) */ | ||
| 2175 | u32 ec_ll; /* error code cache level (2b) */ | ||
| 2176 | |||
| 2177 | err_code = EXTRACT_ERROR_CODE(info->nbsl); | ||
| 2178 | ec_ll = EXTRACT_LL_CODE(err_code); | ||
| 2179 | ec_tt = EXTRACT_TT_CODE(err_code); | ||
| 2180 | ec_rrrr = EXTRACT_RRRR_CODE(err_code); | ||
| 2181 | |||
| 2182 | amd64_mc_printk(mci, KERN_ERR, | ||
| 2183 | "cache hierarchy error: memory transaction type(%s), " | ||
| 2184 | "transaction type(%s), cache level(%s)\n", | ||
| 2185 | rrrr_msgs[ec_rrrr], tt_msgs[ec_tt], ll_msgs[ec_ll]); | ||
| 2186 | } | ||
| 2187 | |||
| 2188 | |||
| 2189 | /* | ||
| 2190 | * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR | ||
| 2191 | * ADDRESS and process. | ||
| 2192 | */ | ||
| 2193 | static void amd64_handle_ce(struct mem_ctl_info *mci, | ||
| 2194 | struct amd64_error_info_regs *info) | ||
| 2195 | { | ||
| 2196 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 2197 | u64 SystemAddress; | ||
| 2198 | |||
| 2199 | /* Ensure that the Error Address is VALID */ | ||
| 2200 | if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) { | ||
| 2201 | amd64_mc_printk(mci, KERN_ERR, | ||
| 2202 | "HW has no ERROR_ADDRESS available\n"); | ||
| 2203 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | ||
| 2204 | return; | ||
| 2205 | } | ||
| 2206 | |||
| 2207 | SystemAddress = extract_error_address(mci, info); | ||
| 2208 | |||
| 2209 | amd64_mc_printk(mci, KERN_ERR, | ||
| 2210 | "CE ERROR_ADDRESS= 0x%llx\n", SystemAddress); | ||
| 2211 | |||
| 2212 | pvt->ops->map_sysaddr_to_csrow(mci, info, SystemAddress); | ||
| 2213 | } | ||
| 2214 | |||
| 2215 | /* Handle any Un-correctable Errors (UEs) */ | ||
| 2216 | static void amd64_handle_ue(struct mem_ctl_info *mci, | ||
| 2217 | struct amd64_error_info_regs *info) | ||
| 2218 | { | ||
| 2219 | int csrow; | ||
| 2220 | u64 SystemAddress; | ||
| 2221 | u32 page, offset; | ||
| 2222 | struct mem_ctl_info *log_mci, *src_mci = NULL; | ||
| 2223 | |||
| 2224 | log_mci = mci; | ||
| 2225 | |||
| 2226 | if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) { | ||
| 2227 | amd64_mc_printk(mci, KERN_CRIT, | ||
| 2228 | "HW has no ERROR_ADDRESS available\n"); | ||
| 2229 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | ||
| 2230 | return; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | SystemAddress = extract_error_address(mci, info); | ||
| 2234 | |||
| 2235 | /* | ||
| 2236 | * Find out which node the error address belongs to. This may be | ||
| 2237 | * different from the node that detected the error. | ||
| 2238 | */ | ||
| 2239 | src_mci = find_mc_by_sys_addr(mci, SystemAddress); | ||
| 2240 | if (!src_mci) { | ||
| 2241 | amd64_mc_printk(mci, KERN_CRIT, | ||
| 2242 | "ERROR ADDRESS (0x%lx) value NOT mapped to a MC\n", | ||
| 2243 | (unsigned long)SystemAddress); | ||
| 2244 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | ||
| 2245 | return; | ||
| 2246 | } | ||
| 2247 | |||
| 2248 | log_mci = src_mci; | ||
| 2249 | |||
| 2250 | csrow = sys_addr_to_csrow(log_mci, SystemAddress); | ||
| 2251 | if (csrow < 0) { | ||
| 2252 | amd64_mc_printk(mci, KERN_CRIT, | ||
| 2253 | "ERROR_ADDRESS (0x%lx) value NOT mapped to 'csrow'\n", | ||
| 2254 | (unsigned long)SystemAddress); | ||
| 2255 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | ||
| 2256 | } else { | ||
| 2257 | error_address_to_page_and_offset(SystemAddress, &page, &offset); | ||
| 2258 | edac_mc_handle_ue(log_mci, page, offset, csrow, EDAC_MOD_STR); | ||
| 2259 | } | ||
| 2260 | } | ||
| 2261 | |||
| 2262 | static void amd64_decode_bus_error(struct mem_ctl_info *mci, | ||
| 2263 | struct amd64_error_info_regs *info) | ||
| 2264 | { | ||
| 2265 | u32 err_code, ext_ec; | ||
| 2266 | u32 ec_pp; /* error code participating processor (2p) */ | ||
| 2267 | u32 ec_to; /* error code timed out (1b) */ | ||
| 2268 | u32 ec_rrrr; /* error code memory transaction (4b) */ | ||
| 2269 | u32 ec_ii; /* error code memory or I/O (2b) */ | ||
| 2270 | u32 ec_ll; /* error code cache level (2b) */ | ||
| 2271 | |||
| 2272 | ext_ec = EXTRACT_EXT_ERROR_CODE(info->nbsl); | ||
| 2273 | err_code = EXTRACT_ERROR_CODE(info->nbsl); | ||
| 2274 | |||
| 2275 | ec_ll = EXTRACT_LL_CODE(err_code); | ||
| 2276 | ec_ii = EXTRACT_II_CODE(err_code); | ||
| 2277 | ec_rrrr = EXTRACT_RRRR_CODE(err_code); | ||
| 2278 | ec_to = EXTRACT_TO_CODE(err_code); | ||
| 2279 | ec_pp = EXTRACT_PP_CODE(err_code); | ||
| 2280 | |||
| 2281 | amd64_mc_printk(mci, KERN_ERR, | ||
| 2282 | "BUS ERROR:\n" | ||
| 2283 | " time-out(%s) mem or i/o(%s)\n" | ||
| 2284 | " participating processor(%s)\n" | ||
| 2285 | " memory transaction type(%s)\n" | ||
| 2286 | " cache level(%s) Error Found by: %s\n", | ||
| 2287 | to_msgs[ec_to], | ||
| 2288 | ii_msgs[ec_ii], | ||
| 2289 | pp_msgs[ec_pp], | ||
| 2290 | rrrr_msgs[ec_rrrr], | ||
| 2291 | ll_msgs[ec_ll], | ||
| 2292 | (info->nbsh & K8_NBSH_ERR_SCRUBER) ? | ||
| 2293 | "Scrubber" : "Normal Operation"); | ||
| 2294 | |||
| 2295 | /* If this was an 'observed' error, early out */ | ||
| 2296 | if (ec_pp == K8_NBSL_PP_OBS) | ||
| 2297 | return; /* We aren't the node involved */ | ||
| 2298 | |||
| 2299 | /* Parse out the extended error code for ECC events */ | ||
| 2300 | switch (ext_ec) { | ||
| 2301 | /* F10 changed to one Extended ECC error code */ | ||
| 2302 | case F10_NBSL_EXT_ERR_RES: /* Reserved field */ | ||
| 2303 | case F10_NBSL_EXT_ERR_ECC: /* F10 ECC ext err code */ | ||
| 2304 | break; | ||
| 2305 | |||
| 2306 | default: | ||
| 2307 | amd64_mc_printk(mci, KERN_ERR, "NOT ECC: no special error " | ||
| 2308 | "handling for this error\n"); | ||
| 2309 | return; | ||
| 2310 | } | ||
| 2311 | |||
| 2312 | if (info->nbsh & K8_NBSH_CECC) | ||
| 2313 | amd64_handle_ce(mci, info); | ||
| 2314 | else if (info->nbsh & K8_NBSH_UECC) | ||
| 2315 | amd64_handle_ue(mci, info); | ||
| 2316 | |||
| 2317 | /* | ||
| 2318 | * If main error is CE then overflow must be CE. If main error is UE | ||
| 2319 | * then overflow is unknown. We'll call the overflow a CE - if | ||
| 2320 | * panic_on_ue is set then we're already panic'ed and won't arrive | ||
| 2321 | * here. Else, then apparently someone doesn't think that UE's are | ||
| 2322 | * catastrophic. | ||
| 2323 | */ | ||
| 2324 | if (info->nbsh & K8_NBSH_OVERFLOW) | ||
| 2325 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR | ||
| 2326 | "Error Overflow set"); | ||
| 2327 | } | ||
| 2328 | |||
| 2329 | int amd64_process_error_info(struct mem_ctl_info *mci, | ||
| 2330 | struct amd64_error_info_regs *info, | ||
| 2331 | int handle_errors) | ||
| 2332 | { | ||
| 2333 | struct amd64_pvt *pvt; | ||
| 2334 | struct amd64_error_info_regs *regs; | ||
| 2335 | u32 err_code, ext_ec; | ||
| 2336 | int gart_tlb_error = 0; | ||
| 2337 | |||
| 2338 | pvt = mci->pvt_info; | ||
| 2339 | |||
| 2340 | /* If caller doesn't want us to process the error, return */ | ||
| 2341 | if (!handle_errors) | ||
| 2342 | return 1; | ||
| 2343 | |||
| 2344 | regs = info; | ||
| 2345 | |||
| 2346 | debugf1("NorthBridge ERROR: mci(0x%p)\n", mci); | ||
| 2347 | debugf1(" MC node(%d) Error-Address(0x%.8x-%.8x)\n", | ||
| 2348 | pvt->mc_node_id, regs->nbeah, regs->nbeal); | ||
| 2349 | debugf1(" nbsh(0x%.8x) nbsl(0x%.8x)\n", | ||
| 2350 | regs->nbsh, regs->nbsl); | ||
| 2351 | debugf1(" Valid Error=%s Overflow=%s\n", | ||
| 2352 | (regs->nbsh & K8_NBSH_VALID_BIT) ? "True" : "False", | ||
| 2353 | (regs->nbsh & K8_NBSH_OVERFLOW) ? "True" : "False"); | ||
| 2354 | debugf1(" Err Uncorrected=%s MCA Error Reporting=%s\n", | ||
| 2355 | (regs->nbsh & K8_NBSH_UNCORRECTED_ERR) ? | ||
| 2356 | "True" : "False", | ||
| 2357 | (regs->nbsh & K8_NBSH_ERR_ENABLE) ? | ||
| 2358 | "True" : "False"); | ||
| 2359 | debugf1(" MiscErr Valid=%s ErrAddr Valid=%s PCC=%s\n", | ||
| 2360 | (regs->nbsh & K8_NBSH_MISC_ERR_VALID) ? | ||
| 2361 | "True" : "False", | ||
| 2362 | (regs->nbsh & K8_NBSH_VALID_ERROR_ADDR) ? | ||
| 2363 | "True" : "False", | ||
| 2364 | (regs->nbsh & K8_NBSH_PCC) ? | ||
| 2365 | "True" : "False"); | ||
| 2366 | debugf1(" CECC=%s UECC=%s Found by Scruber=%s\n", | ||
| 2367 | (regs->nbsh & K8_NBSH_CECC) ? | ||
| 2368 | "True" : "False", | ||
| 2369 | (regs->nbsh & K8_NBSH_UECC) ? | ||
| 2370 | "True" : "False", | ||
| 2371 | (regs->nbsh & K8_NBSH_ERR_SCRUBER) ? | ||
| 2372 | "True" : "False"); | ||
| 2373 | debugf1(" CORE0=%s CORE1=%s CORE2=%s CORE3=%s\n", | ||
| 2374 | (regs->nbsh & K8_NBSH_CORE0) ? "True" : "False", | ||
| 2375 | (regs->nbsh & K8_NBSH_CORE1) ? "True" : "False", | ||
| 2376 | (regs->nbsh & K8_NBSH_CORE2) ? "True" : "False", | ||
| 2377 | (regs->nbsh & K8_NBSH_CORE3) ? "True" : "False"); | ||
| 2378 | |||
| 2379 | |||
| 2380 | err_code = EXTRACT_ERROR_CODE(regs->nbsl); | ||
| 2381 | |||
| 2382 | /* Determine which error type: | ||
| 2383 | * 1) GART errors - non-fatal, developmental events | ||
| 2384 | * 2) MEMORY errors | ||
| 2385 | * 3) BUS errors | ||
| 2386 | * 4) Unknown error | ||
| 2387 | */ | ||
| 2388 | if (TEST_TLB_ERROR(err_code)) { | ||
| 2389 | /* | ||
| 2390 | * GART errors are intended to help graphics driver developers | ||
| 2391 | * to detect bad GART PTEs. It is recommended by AMD to disable | ||
| 2392 | * GART table walk error reporting by default[1] (currently | ||
| 2393 | * being disabled in mce_cpu_quirks()) and according to the | ||
| 2394 | * comment in mce_cpu_quirks(), such GART errors can be | ||
| 2395 | * incorrectly triggered. We may see these errors anyway and | ||
| 2396 | * unless requested by the user, they won't be reported. | ||
| 2397 | * | ||
| 2398 | * [1] section 13.10.1 on BIOS and Kernel Developers Guide for | ||
| 2399 | * AMD NPT family 0Fh processors | ||
| 2400 | */ | ||
| 2401 | if (report_gart_errors == 0) | ||
| 2402 | return 1; | ||
| 2403 | |||
| 2404 | /* | ||
| 2405 | * Only if GART error reporting is requested should we generate | ||
| 2406 | * any logs. | ||
| 2407 | */ | ||
| 2408 | gart_tlb_error = 1; | ||
| 2409 | |||
| 2410 | debugf1("GART TLB error\n"); | ||
| 2411 | amd64_decode_gart_tlb_error(mci, info); | ||
| 2412 | } else if (TEST_MEM_ERROR(err_code)) { | ||
| 2413 | debugf1("Memory/Cache error\n"); | ||
| 2414 | amd64_decode_mem_cache_error(mci, info); | ||
| 2415 | } else if (TEST_BUS_ERROR(err_code)) { | ||
| 2416 | debugf1("Bus (Link/DRAM) error\n"); | ||
| 2417 | amd64_decode_bus_error(mci, info); | ||
| 2418 | } else { | ||
| 2419 | /* shouldn't reach here! */ | ||
| 2420 | amd64_mc_printk(mci, KERN_WARNING, | ||
| 2421 | "%s(): unknown MCE error 0x%x\n", __func__, | ||
| 2422 | err_code); | ||
| 2423 | } | ||
| 2424 | |||
| 2425 | ext_ec = EXTRACT_EXT_ERROR_CODE(regs->nbsl); | ||
| 2426 | amd64_mc_printk(mci, KERN_ERR, | ||
| 2427 | "ExtErr=(0x%x) %s\n", ext_ec, ext_msgs[ext_ec]); | ||
| 2428 | |||
| 2429 | if (((ext_ec >= F10_NBSL_EXT_ERR_CRC && | ||
| 2430 | ext_ec <= F10_NBSL_EXT_ERR_TGT) || | ||
| 2431 | (ext_ec == F10_NBSL_EXT_ERR_RMW)) && | ||
| 2432 | EXTRACT_LDT_LINK(info->nbsh)) { | ||
| 2433 | |||
| 2434 | amd64_mc_printk(mci, KERN_ERR, | ||
| 2435 | "Error on hypertransport link: %s\n", | ||
| 2436 | htlink_msgs[ | ||
| 2437 | EXTRACT_LDT_LINK(info->nbsh)]); | ||
| 2438 | } | ||
| 2439 | |||
| 2440 | /* | ||
| 2441 | * Check the UE bit of the NB status high register, if set generate some | ||
| 2442 | * logs. If NOT a GART error, then process the event as a NO-INFO event. | ||
| 2443 | * If it was a GART error, skip that process. | ||
| 2444 | */ | ||
| 2445 | if (regs->nbsh & K8_NBSH_UNCORRECTED_ERR) { | ||
| 2446 | amd64_mc_printk(mci, KERN_CRIT, "uncorrected error\n"); | ||
| 2447 | if (!gart_tlb_error) | ||
| 2448 | edac_mc_handle_ue_no_info(mci, "UE bit is set\n"); | ||
| 2449 | } | ||
| 2450 | |||
| 2451 | if (regs->nbsh & K8_NBSH_PCC) | ||
| 2452 | amd64_mc_printk(mci, KERN_CRIT, | ||
| 2453 | "PCC (processor context corrupt) set\n"); | ||
| 2454 | |||
| 2455 | return 1; | ||
| 2456 | } | ||
| 2457 | EXPORT_SYMBOL_GPL(amd64_process_error_info); | ||
| 2458 | |||
| 2459 | /* | ||
| 2460 | * The main polling 'check' function, called FROM the edac core to perform the | ||
| 2461 | * error checking and if an error is encountered, error processing. | ||
| 2462 | */ | ||
| 2463 | static void amd64_check(struct mem_ctl_info *mci) | ||
| 2464 | { | ||
| 2465 | struct amd64_error_info_regs info; | ||
| 2466 | |||
| 2467 | if (amd64_get_error_info(mci, &info)) | ||
| 2468 | amd64_process_error_info(mci, &info, 1); | ||
| 2469 | } | ||
| 2470 | |||
| 2471 | /* | ||
| 2472 | * Input: | ||
| 2473 | * 1) struct amd64_pvt which contains pvt->dram_f2_ctl pointer | ||
| 2474 | * 2) AMD Family index value | ||
| 2475 | * | ||
| 2476 | * Ouput: | ||
| 2477 | * Upon return of 0, the following filled in: | ||
| 2478 | * | ||
| 2479 | * struct pvt->addr_f1_ctl | ||
| 2480 | * struct pvt->misc_f3_ctl | ||
| 2481 | * | ||
| 2482 | * Filled in with related device funcitions of 'dram_f2_ctl' | ||
| 2483 | * These devices are "reserved" via the pci_get_device() | ||
| 2484 | * | ||
| 2485 | * Upon return of 1 (error status): | ||
| 2486 | * | ||
| 2487 | * Nothing reserved | ||
| 2488 | */ | ||
| 2489 | static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, int mc_idx) | ||
| 2490 | { | ||
| 2491 | const struct amd64_family_type *amd64_dev = &amd64_family_types[mc_idx]; | ||
| 2492 | |||
| 2493 | /* Reserve the ADDRESS MAP Device */ | ||
| 2494 | pvt->addr_f1_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor, | ||
| 2495 | amd64_dev->addr_f1_ctl, | ||
| 2496 | pvt->dram_f2_ctl); | ||
| 2497 | |||
| 2498 | if (!pvt->addr_f1_ctl) { | ||
| 2499 | amd64_printk(KERN_ERR, "error address map device not found: " | ||
| 2500 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
| 2501 | PCI_VENDOR_ID_AMD, amd64_dev->addr_f1_ctl); | ||
| 2502 | return 1; | ||
| 2503 | } | ||
| 2504 | |||
| 2505 | /* Reserve the MISC Device */ | ||
| 2506 | pvt->misc_f3_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor, | ||
| 2507 | amd64_dev->misc_f3_ctl, | ||
| 2508 | pvt->dram_f2_ctl); | ||
| 2509 | |||
| 2510 | if (!pvt->misc_f3_ctl) { | ||
| 2511 | pci_dev_put(pvt->addr_f1_ctl); | ||
| 2512 | pvt->addr_f1_ctl = NULL; | ||
| 2513 | |||
| 2514 | amd64_printk(KERN_ERR, "error miscellaneous device not found: " | ||
| 2515 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
| 2516 | PCI_VENDOR_ID_AMD, amd64_dev->misc_f3_ctl); | ||
| 2517 | return 1; | ||
| 2518 | } | ||
| 2519 | |||
| 2520 | debugf1(" Addr Map device PCI Bus ID:\t%s\n", | ||
| 2521 | pci_name(pvt->addr_f1_ctl)); | ||
| 2522 | debugf1(" DRAM MEM-CTL PCI Bus ID:\t%s\n", | ||
| 2523 | pci_name(pvt->dram_f2_ctl)); | ||
| 2524 | debugf1(" Misc device PCI Bus ID:\t%s\n", | ||
| 2525 | pci_name(pvt->misc_f3_ctl)); | ||
| 2526 | |||
| 2527 | return 0; | ||
| 2528 | } | ||
| 2529 | |||
| 2530 | static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt) | ||
| 2531 | { | ||
| 2532 | pci_dev_put(pvt->addr_f1_ctl); | ||
| 2533 | pci_dev_put(pvt->misc_f3_ctl); | ||
| 2534 | } | ||
| 2535 | |||
| 2536 | /* | ||
| 2537 | * Retrieve the hardware registers of the memory controller (this includes the | ||
| 2538 | * 'Address Map' and 'Misc' device regs) | ||
| 2539 | */ | ||
| 2540 | static void amd64_read_mc_registers(struct amd64_pvt *pvt) | ||
| 2541 | { | ||
| 2542 | u64 msr_val; | ||
| 2543 | int dram, err = 0; | ||
| 2544 | |||
| 2545 | /* | ||
| 2546 | * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since | ||
| 2547 | * those are Read-As-Zero | ||
| 2548 | */ | ||
| 2549 | rdmsrl(MSR_K8_TOP_MEM1, msr_val); | ||
| 2550 | pvt->top_mem = msr_val >> 23; | ||
| 2551 | debugf0(" TOP_MEM=0x%08llx\n", pvt->top_mem); | ||
| 2552 | |||
| 2553 | /* check first whether TOP_MEM2 is enabled */ | ||
| 2554 | rdmsrl(MSR_K8_SYSCFG, msr_val); | ||
| 2555 | if (msr_val & (1U << 21)) { | ||
| 2556 | rdmsrl(MSR_K8_TOP_MEM2, msr_val); | ||
| 2557 | pvt->top_mem2 = msr_val >> 23; | ||
| 2558 | debugf0(" TOP_MEM2=0x%08llx\n", pvt->top_mem2); | ||
| 2559 | } else | ||
| 2560 | debugf0(" TOP_MEM2 disabled.\n"); | ||
| 2561 | |||
| 2562 | amd64_cpu_display_info(pvt); | ||
| 2563 | |||
| 2564 | err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap); | ||
| 2565 | if (err) | ||
| 2566 | goto err_reg; | ||
| 2567 | |||
| 2568 | if (pvt->ops->read_dram_ctl_register) | ||
| 2569 | pvt->ops->read_dram_ctl_register(pvt); | ||
| 2570 | |||
| 2571 | for (dram = 0; dram < DRAM_REG_COUNT; dram++) { | ||
| 2572 | /* | ||
| 2573 | * Call CPU specific READ function to get the DRAM Base and | ||
| 2574 | * Limit values from the DCT. | ||
| 2575 | */ | ||
| 2576 | pvt->ops->read_dram_base_limit(pvt, dram); | ||
| 2577 | |||
| 2578 | /* | ||
| 2579 | * Only print out debug info on rows with both R and W Enabled. | ||
| 2580 | * Normal processing, compiler should optimize this whole 'if' | ||
| 2581 | * debug output block away. | ||
| 2582 | */ | ||
| 2583 | if (pvt->dram_rw_en[dram] != 0) { | ||
| 2584 | debugf1(" DRAM_BASE[%d]: 0x%8.08x-%8.08x " | ||
| 2585 | "DRAM_LIMIT: 0x%8.08x-%8.08x\n", | ||
| 2586 | dram, | ||
| 2587 | (u32)(pvt->dram_base[dram] >> 32), | ||
| 2588 | (u32)(pvt->dram_base[dram] & 0xFFFFFFFF), | ||
| 2589 | (u32)(pvt->dram_limit[dram] >> 32), | ||
| 2590 | (u32)(pvt->dram_limit[dram] & 0xFFFFFFFF)); | ||
| 2591 | debugf1(" IntlvEn=%s %s %s " | ||
| 2592 | "IntlvSel=%d DstNode=%d\n", | ||
| 2593 | pvt->dram_IntlvEn[dram] ? | ||
| 2594 | "Enabled" : "Disabled", | ||
| 2595 | (pvt->dram_rw_en[dram] & 0x2) ? "W" : "!W", | ||
| 2596 | (pvt->dram_rw_en[dram] & 0x1) ? "R" : "!R", | ||
| 2597 | pvt->dram_IntlvSel[dram], | ||
| 2598 | pvt->dram_DstNode[dram]); | ||
| 2599 | } | ||
| 2600 | } | ||
| 2601 | |||
| 2602 | amd64_read_dct_base_mask(pvt); | ||
| 2603 | |||
| 2604 | err = pci_read_config_dword(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar); | ||
| 2605 | if (err) | ||
| 2606 | goto err_reg; | ||
| 2607 | |||
| 2608 | amd64_read_dbam_reg(pvt); | ||
| 2609 | |||
| 2610 | err = pci_read_config_dword(pvt->misc_f3_ctl, | ||
| 2611 | F10_ONLINE_SPARE, &pvt->online_spare); | ||
| 2612 | if (err) | ||
| 2613 | goto err_reg; | ||
| 2614 | |||
| 2615 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | ||
| 2616 | if (err) | ||
| 2617 | goto err_reg; | ||
| 2618 | |||
| 2619 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); | ||
| 2620 | if (err) | ||
| 2621 | goto err_reg; | ||
| 2622 | |||
| 2623 | if (!dct_ganging_enabled(pvt)) { | ||
| 2624 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCLR_1, | ||
| 2625 | &pvt->dclr1); | ||
| 2626 | if (err) | ||
| 2627 | goto err_reg; | ||
| 2628 | |||
| 2629 | err = pci_read_config_dword(pvt->dram_f2_ctl, F10_DCHR_1, | ||
| 2630 | &pvt->dchr1); | ||
| 2631 | if (err) | ||
| 2632 | goto err_reg; | ||
| 2633 | } | ||
| 2634 | |||
| 2635 | amd64_dump_misc_regs(pvt); | ||
| 2636 | |||
| 2637 | err_reg: | ||
| 2638 | debugf0("Reading an MC register failed\n"); | ||
| 2639 | |||
| 2640 | } | ||
| 2641 | |||
| 2642 | /* | ||
| 2643 | * NOTE: CPU Revision Dependent code | ||
| 2644 | * | ||
| 2645 | * Input: | ||
| 2646 | * @csrow_nr ChipSelect Row Number (0..CHIPSELECT_COUNT-1) | ||
| 2647 | * k8 private pointer to --> | ||
| 2648 | * DRAM Bank Address mapping register | ||
| 2649 | * node_id | ||
| 2650 | * DCL register where dual_channel_active is | ||
| 2651 | * | ||
| 2652 | * The DBAM register consists of 4 sets of 4 bits each definitions: | ||
| 2653 | * | ||
| 2654 | * Bits: CSROWs | ||
| 2655 | * 0-3 CSROWs 0 and 1 | ||
| 2656 | * 4-7 CSROWs 2 and 3 | ||
| 2657 | * 8-11 CSROWs 4 and 5 | ||
| 2658 | * 12-15 CSROWs 6 and 7 | ||
| 2659 | * | ||
| 2660 | * Values range from: 0 to 15 | ||
| 2661 | * The meaning of the values depends on CPU revision and dual-channel state, | ||
| 2662 | * see relevant BKDG more info. | ||
| 2663 | * | ||
| 2664 | * The memory controller provides for total of only 8 CSROWs in its current | ||
| 2665 | * architecture. Each "pair" of CSROWs normally represents just one DIMM in | ||
| 2666 | * single channel or two (2) DIMMs in dual channel mode. | ||
| 2667 | * | ||
| 2668 | * The following code logic collapses the various tables for CSROW based on CPU | ||
| 2669 | * revision. | ||
| 2670 | * | ||
| 2671 | * Returns: | ||
| 2672 | * The number of PAGE_SIZE pages on the specified CSROW number it | ||
| 2673 | * encompasses | ||
| 2674 | * | ||
| 2675 | */ | ||
| 2676 | static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) | ||
| 2677 | { | ||
| 2678 | u32 dram_map, nr_pages; | ||
| 2679 | |||
| 2680 | /* | ||
| 2681 | * The math on this doesn't look right on the surface because x/2*4 can | ||
| 2682 | * be simplified to x*2 but this expression makes use of the fact that | ||
| 2683 | * it is integral math where 1/2=0. This intermediate value becomes the | ||
| 2684 | * number of bits to shift the DBAM register to extract the proper CSROW | ||
| 2685 | * field. | ||
| 2686 | */ | ||
| 2687 | dram_map = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF; | ||
| 2688 | |||
| 2689 | nr_pages = pvt->ops->dbam_map_to_pages(pvt, dram_map); | ||
| 2690 | |||
| 2691 | /* | ||
| 2692 | * If dual channel then double the memory size of single channel. | ||
| 2693 | * Channel count is 1 or 2 | ||
| 2694 | */ | ||
| 2695 | nr_pages <<= (pvt->channel_count - 1); | ||
| 2696 | |||
| 2697 | debugf0(" (csrow=%d) DBAM map index= %d\n", csrow_nr, dram_map); | ||
| 2698 | debugf0(" nr_pages= %u channel-count = %d\n", | ||
| 2699 | nr_pages, pvt->channel_count); | ||
| 2700 | |||
| 2701 | return nr_pages; | ||
| 2702 | } | ||
| 2703 | |||
| 2704 | /* | ||
| 2705 | * Initialize the array of csrow attribute instances, based on the values | ||
| 2706 | * from pci config hardware registers. | ||
| 2707 | */ | ||
| 2708 | static int amd64_init_csrows(struct mem_ctl_info *mci) | ||
| 2709 | { | ||
| 2710 | struct csrow_info *csrow; | ||
| 2711 | struct amd64_pvt *pvt; | ||
| 2712 | u64 input_addr_min, input_addr_max, sys_addr; | ||
| 2713 | int i, err = 0, empty = 1; | ||
| 2714 | |||
| 2715 | pvt = mci->pvt_info; | ||
| 2716 | |||
| 2717 | err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg); | ||
| 2718 | if (err) | ||
| 2719 | debugf0("Reading K8_NBCFG failed\n"); | ||
| 2720 | |||
| 2721 | debugf0("NBCFG= 0x%x CHIPKILL= %s DRAM ECC= %s\n", pvt->nbcfg, | ||
| 2722 | (pvt->nbcfg & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | ||
| 2723 | (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled" | ||
| 2724 | ); | ||
| 2725 | |||
| 2726 | for (i = 0; i < CHIPSELECT_COUNT; i++) { | ||
| 2727 | csrow = &mci->csrows[i]; | ||
| 2728 | |||
| 2729 | if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) { | ||
| 2730 | debugf1("----CSROW %d EMPTY for node %d\n", i, | ||
| 2731 | pvt->mc_node_id); | ||
| 2732 | continue; | ||
| 2733 | } | ||
| 2734 | |||
| 2735 | debugf1("----CSROW %d VALID for MC node %d\n", | ||
| 2736 | i, pvt->mc_node_id); | ||
| 2737 | |||
| 2738 | empty = 0; | ||
| 2739 | csrow->nr_pages = amd64_csrow_nr_pages(i, pvt); | ||
| 2740 | find_csrow_limits(mci, i, &input_addr_min, &input_addr_max); | ||
| 2741 | sys_addr = input_addr_to_sys_addr(mci, input_addr_min); | ||
| 2742 | csrow->first_page = (u32) (sys_addr >> PAGE_SHIFT); | ||
| 2743 | sys_addr = input_addr_to_sys_addr(mci, input_addr_max); | ||
| 2744 | csrow->last_page = (u32) (sys_addr >> PAGE_SHIFT); | ||
| 2745 | csrow->page_mask = ~mask_from_dct_mask(pvt, i); | ||
| 2746 | /* 8 bytes of resolution */ | ||
| 2747 | |||
| 2748 | csrow->mtype = amd64_determine_memory_type(pvt); | ||
| 2749 | |||
| 2750 | debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); | ||
| 2751 | debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n", | ||
| 2752 | (unsigned long)input_addr_min, | ||
| 2753 | (unsigned long)input_addr_max); | ||
| 2754 | debugf1(" sys_addr: 0x%lx page_mask: 0x%lx\n", | ||
| 2755 | (unsigned long)sys_addr, csrow->page_mask); | ||
| 2756 | debugf1(" nr_pages: %u first_page: 0x%lx " | ||
| 2757 | "last_page: 0x%lx\n", | ||
| 2758 | (unsigned)csrow->nr_pages, | ||
| 2759 | csrow->first_page, csrow->last_page); | ||
| 2760 | |||
| 2761 | /* | ||
| 2762 | * determine whether CHIPKILL or JUST ECC or NO ECC is operating | ||
| 2763 | */ | ||
| 2764 | if (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) | ||
| 2765 | csrow->edac_mode = | ||
| 2766 | (pvt->nbcfg & K8_NBCFG_CHIPKILL) ? | ||
| 2767 | EDAC_S4ECD4ED : EDAC_SECDED; | ||
| 2768 | else | ||
| 2769 | csrow->edac_mode = EDAC_NONE; | ||
| 2770 | } | ||
| 2771 | |||
| 2772 | return empty; | ||
| 2773 | } | ||
| 2774 | |||
| 2775 | /* | ||
| 2776 | * Only if 'ecc_enable_override' is set AND BIOS had ECC disabled, do "we" | ||
| 2777 | * enable it. | ||
| 2778 | */ | ||
| 2779 | static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) | ||
| 2780 | { | ||
| 2781 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 2782 | const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id); | ||
| 2783 | int cpu, idx = 0, err = 0; | ||
| 2784 | struct msr msrs[cpumask_weight(cpumask)]; | ||
| 2785 | u32 value; | ||
| 2786 | u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; | ||
| 2787 | |||
| 2788 | if (!ecc_enable_override) | ||
| 2789 | return; | ||
| 2790 | |||
| 2791 | memset(msrs, 0, sizeof(msrs)); | ||
| 2792 | |||
| 2793 | amd64_printk(KERN_WARNING, | ||
| 2794 | "'ecc_enable_override' parameter is active, " | ||
| 2795 | "Enabling AMD ECC hardware now: CAUTION\n"); | ||
| 2796 | |||
| 2797 | err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); | ||
| 2798 | if (err) | ||
| 2799 | debugf0("Reading K8_NBCTL failed\n"); | ||
| 2800 | |||
| 2801 | /* turn on UECCn and CECCEn bits */ | ||
| 2802 | pvt->old_nbctl = value & mask; | ||
| 2803 | pvt->nbctl_mcgctl_saved = 1; | ||
| 2804 | |||
| 2805 | value |= mask; | ||
| 2806 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); | ||
| 2807 | |||
| 2808 | rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); | ||
| 2809 | |||
| 2810 | for_each_cpu(cpu, cpumask) { | ||
| 2811 | if (msrs[idx].l & K8_MSR_MCGCTL_NBE) | ||
| 2812 | set_bit(idx, &pvt->old_mcgctl); | ||
| 2813 | |||
| 2814 | msrs[idx].l |= K8_MSR_MCGCTL_NBE; | ||
| 2815 | idx++; | ||
| 2816 | } | ||
| 2817 | wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); | ||
| 2818 | |||
| 2819 | err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); | ||
| 2820 | if (err) | ||
| 2821 | debugf0("Reading K8_NBCFG failed\n"); | ||
| 2822 | |||
| 2823 | debugf0("NBCFG(1)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, | ||
| 2824 | (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | ||
| 2825 | (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); | ||
| 2826 | |||
| 2827 | if (!(value & K8_NBCFG_ECC_ENABLE)) { | ||
| 2828 | amd64_printk(KERN_WARNING, | ||
| 2829 | "This node reports that DRAM ECC is " | ||
| 2830 | "currently Disabled; ENABLING now\n"); | ||
| 2831 | |||
| 2832 | /* Attempt to turn on DRAM ECC Enable */ | ||
| 2833 | value |= K8_NBCFG_ECC_ENABLE; | ||
| 2834 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); | ||
| 2835 | |||
| 2836 | err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); | ||
| 2837 | if (err) | ||
| 2838 | debugf0("Reading K8_NBCFG failed\n"); | ||
| 2839 | |||
| 2840 | if (!(value & K8_NBCFG_ECC_ENABLE)) { | ||
| 2841 | amd64_printk(KERN_WARNING, | ||
| 2842 | "Hardware rejects Enabling DRAM ECC checking\n" | ||
| 2843 | "Check memory DIMM configuration\n"); | ||
| 2844 | } else { | ||
| 2845 | amd64_printk(KERN_DEBUG, | ||
| 2846 | "Hardware accepted DRAM ECC Enable\n"); | ||
| 2847 | } | ||
| 2848 | } | ||
| 2849 | debugf0("NBCFG(2)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, | ||
| 2850 | (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | ||
| 2851 | (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); | ||
| 2852 | |||
| 2853 | pvt->ctl_error_info.nbcfg = value; | ||
| 2854 | } | ||
| 2855 | |||
| 2856 | static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) | ||
| 2857 | { | ||
| 2858 | const cpumask_t *cpumask = cpumask_of_node(pvt->mc_node_id); | ||
| 2859 | int cpu, idx = 0, err = 0; | ||
| 2860 | struct msr msrs[cpumask_weight(cpumask)]; | ||
| 2861 | u32 value; | ||
| 2862 | u32 mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; | ||
| 2863 | |||
| 2864 | if (!pvt->nbctl_mcgctl_saved) | ||
| 2865 | return; | ||
| 2866 | |||
| 2867 | memset(msrs, 0, sizeof(msrs)); | ||
| 2868 | |||
| 2869 | err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCTL, &value); | ||
| 2870 | if (err) | ||
| 2871 | debugf0("Reading K8_NBCTL failed\n"); | ||
| 2872 | value &= ~mask; | ||
| 2873 | value |= pvt->old_nbctl; | ||
| 2874 | |||
| 2875 | /* restore the NB Enable MCGCTL bit */ | ||
| 2876 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); | ||
| 2877 | |||
| 2878 | rdmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); | ||
| 2879 | |||
| 2880 | for_each_cpu(cpu, cpumask) { | ||
| 2881 | msrs[idx].l &= ~K8_MSR_MCGCTL_NBE; | ||
| 2882 | msrs[idx].l |= | ||
| 2883 | test_bit(idx, &pvt->old_mcgctl) << K8_MSR_MCGCTL_NBE; | ||
| 2884 | idx++; | ||
| 2885 | } | ||
| 2886 | |||
| 2887 | wrmsr_on_cpus(cpumask, K8_MSR_MCGCTL, msrs); | ||
| 2888 | } | ||
| 2889 | |||
| 2890 | static void check_mcg_ctl(void *ret) | ||
| 2891 | { | ||
| 2892 | u64 msr_val = 0; | ||
| 2893 | u8 nbe; | ||
| 2894 | |||
| 2895 | rdmsrl(MSR_IA32_MCG_CTL, msr_val); | ||
| 2896 | nbe = msr_val & K8_MSR_MCGCTL_NBE; | ||
| 2897 | |||
| 2898 | debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n", | ||
| 2899 | raw_smp_processor_id(), msr_val, | ||
| 2900 | (nbe ? "enabled" : "disabled")); | ||
| 2901 | |||
| 2902 | if (!nbe) | ||
| 2903 | *(int *)ret = 0; | ||
| 2904 | } | ||
| 2905 | |||
| 2906 | /* check MCG_CTL on all the cpus on this node */ | ||
| 2907 | static int amd64_mcg_ctl_enabled_on_cpus(const cpumask_t *mask) | ||
| 2908 | { | ||
| 2909 | int ret = 1; | ||
| 2910 | preempt_disable(); | ||
| 2911 | smp_call_function_many(mask, check_mcg_ctl, &ret, 1); | ||
| 2912 | preempt_enable(); | ||
| 2913 | |||
| 2914 | return ret; | ||
| 2915 | } | ||
| 2916 | |||
| 2917 | /* | ||
| 2918 | * EDAC requires that the BIOS have ECC enabled before taking over the | ||
| 2919 | * processing of ECC errors. This is because the BIOS can properly initialize | ||
| 2920 | * the memory system completely. A command line option allows to force-enable | ||
| 2921 | * hardware ECC later in amd64_enable_ecc_error_reporting(). | ||
| 2922 | */ | ||
| 2923 | static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) | ||
| 2924 | { | ||
| 2925 | u32 value; | ||
| 2926 | int err = 0, ret = 0; | ||
| 2927 | u8 ecc_enabled = 0; | ||
| 2928 | |||
| 2929 | err = pci_read_config_dword(pvt->misc_f3_ctl, K8_NBCFG, &value); | ||
| 2930 | if (err) | ||
| 2931 | debugf0("Reading K8_NBCTL failed\n"); | ||
| 2932 | |||
| 2933 | ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE); | ||
| 2934 | |||
| 2935 | ret = amd64_mcg_ctl_enabled_on_cpus(cpumask_of_node(pvt->mc_node_id)); | ||
| 2936 | |||
| 2937 | debugf0("K8_NBCFG=0x%x, DRAM ECC is %s\n", value, | ||
| 2938 | (value & K8_NBCFG_ECC_ENABLE ? "enabled" : "disabled")); | ||
| 2939 | |||
| 2940 | if (!ecc_enabled || !ret) { | ||
| 2941 | if (!ecc_enabled) { | ||
| 2942 | amd64_printk(KERN_WARNING, "This node reports that " | ||
| 2943 | "Memory ECC is currently " | ||
| 2944 | "disabled.\n"); | ||
| 2945 | |||
| 2946 | amd64_printk(KERN_WARNING, "bit 0x%lx in register " | ||
| 2947 | "F3x%x of the MISC_CONTROL device (%s) " | ||
| 2948 | "should be enabled\n", K8_NBCFG_ECC_ENABLE, | ||
| 2949 | K8_NBCFG, pci_name(pvt->misc_f3_ctl)); | ||
| 2950 | } | ||
| 2951 | if (!ret) { | ||
| 2952 | amd64_printk(KERN_WARNING, "bit 0x%016lx in MSR 0x%08x " | ||
| 2953 | "of node %d should be enabled\n", | ||
| 2954 | K8_MSR_MCGCTL_NBE, MSR_IA32_MCG_CTL, | ||
| 2955 | pvt->mc_node_id); | ||
| 2956 | } | ||
| 2957 | if (!ecc_enable_override) { | ||
| 2958 | amd64_printk(KERN_WARNING, "WARNING: ECC is NOT " | ||
| 2959 | "currently enabled by the BIOS. Module " | ||
| 2960 | "will NOT be loaded.\n" | ||
| 2961 | " Either Enable ECC in the BIOS, " | ||
| 2962 | "or use the 'ecc_enable_override' " | ||
| 2963 | "parameter.\n" | ||
| 2964 | " Might be a BIOS bug, if BIOS says " | ||
| 2965 | "ECC is enabled\n" | ||
| 2966 | " Use of the override can cause " | ||
| 2967 | "unknown side effects.\n"); | ||
| 2968 | ret = -ENODEV; | ||
| 2969 | } | ||
| 2970 | } else { | ||
| 2971 | amd64_printk(KERN_INFO, | ||
| 2972 | "ECC is enabled by BIOS, Proceeding " | ||
| 2973 | "with EDAC module initialization\n"); | ||
| 2974 | |||
| 2975 | /* CLEAR the override, since BIOS controlled it */ | ||
| 2976 | ecc_enable_override = 0; | ||
| 2977 | } | ||
| 2978 | |||
| 2979 | return ret; | ||
| 2980 | } | ||
| 2981 | |||
| 2982 | struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + | ||
| 2983 | ARRAY_SIZE(amd64_inj_attrs) + | ||
| 2984 | 1]; | ||
| 2985 | |||
| 2986 | struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; | ||
| 2987 | |||
| 2988 | static void amd64_set_mc_sysfs_attributes(struct mem_ctl_info *mci) | ||
| 2989 | { | ||
| 2990 | unsigned int i = 0, j = 0; | ||
| 2991 | |||
| 2992 | for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++) | ||
| 2993 | sysfs_attrs[i] = amd64_dbg_attrs[i]; | ||
| 2994 | |||
| 2995 | for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++) | ||
| 2996 | sysfs_attrs[i] = amd64_inj_attrs[j]; | ||
| 2997 | |||
| 2998 | sysfs_attrs[i] = terminator; | ||
| 2999 | |||
| 3000 | mci->mc_driver_sysfs_attributes = sysfs_attrs; | ||
| 3001 | } | ||
| 3002 | |||
| 3003 | static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | ||
| 3004 | { | ||
| 3005 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 3006 | |||
| 3007 | mci->mtype_cap = MEM_FLAG_DDR2 | MEM_FLAG_RDDR2; | ||
| 3008 | mci->edac_ctl_cap = EDAC_FLAG_NONE; | ||
| 3009 | mci->edac_cap = EDAC_FLAG_NONE; | ||
| 3010 | |||
| 3011 | if (pvt->nbcap & K8_NBCAP_SECDED) | ||
| 3012 | mci->edac_ctl_cap |= EDAC_FLAG_SECDED; | ||
| 3013 | |||
| 3014 | if (pvt->nbcap & K8_NBCAP_CHIPKILL) | ||
| 3015 | mci->edac_ctl_cap |= EDAC_FLAG_S4ECD4ED; | ||
| 3016 | |||
| 3017 | mci->edac_cap = amd64_determine_edac_cap(pvt); | ||
| 3018 | mci->mod_name = EDAC_MOD_STR; | ||
| 3019 | mci->mod_ver = EDAC_AMD64_VERSION; | ||
| 3020 | mci->ctl_name = get_amd_family_name(pvt->mc_type_index); | ||
| 3021 | mci->dev_name = pci_name(pvt->dram_f2_ctl); | ||
| 3022 | mci->ctl_page_to_phys = NULL; | ||
| 3023 | |||
| 3024 | /* IMPORTANT: Set the polling 'check' function in this module */ | ||
| 3025 | mci->edac_check = amd64_check; | ||
| 3026 | |||
| 3027 | /* memory scrubber interface */ | ||
| 3028 | mci->set_sdram_scrub_rate = amd64_set_scrub_rate; | ||
| 3029 | mci->get_sdram_scrub_rate = amd64_get_scrub_rate; | ||
| 3030 | } | ||
| 3031 | |||
| 3032 | /* | ||
| 3033 | * Init stuff for this DRAM Controller device. | ||
| 3034 | * | ||
| 3035 | * Due to a hardware feature on Fam10h CPUs, the Enable Extended Configuration | ||
| 3036 | * Space feature MUST be enabled on ALL Processors prior to actually reading | ||
| 3037 | * from the ECS registers. Since the loading of the module can occur on any | ||
| 3038 | * 'core', and cores don't 'see' all the other processors ECS data when the | ||
| 3039 | * others are NOT enabled. Our solution is to first enable ECS access in this | ||
| 3040 | * routine on all processors, gather some data in a amd64_pvt structure and | ||
| 3041 | * later come back in a finish-setup function to perform that final | ||
| 3042 | * initialization. See also amd64_init_2nd_stage() for that. | ||
| 3043 | */ | ||
| 3044 | static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, | ||
| 3045 | int mc_type_index) | ||
| 3046 | { | ||
| 3047 | struct amd64_pvt *pvt = NULL; | ||
| 3048 | int err = 0, ret; | ||
| 3049 | |||
| 3050 | ret = -ENOMEM; | ||
| 3051 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); | ||
| 3052 | if (!pvt) | ||
| 3053 | goto err_exit; | ||
| 3054 | |||
| 3055 | pvt->mc_node_id = get_mc_node_id_from_pdev(dram_f2_ctl); | ||
| 3056 | |||
| 3057 | pvt->dram_f2_ctl = dram_f2_ctl; | ||
| 3058 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | ||
| 3059 | pvt->mc_type_index = mc_type_index; | ||
| 3060 | pvt->ops = family_ops(mc_type_index); | ||
| 3061 | pvt->old_mcgctl = 0; | ||
| 3062 | |||
| 3063 | /* | ||
| 3064 | * We have the dram_f2_ctl device as an argument, now go reserve its | ||
| 3065 | * sibling devices from the PCI system. | ||
| 3066 | */ | ||
| 3067 | ret = -ENODEV; | ||
| 3068 | err = amd64_reserve_mc_sibling_devices(pvt, mc_type_index); | ||
| 3069 | if (err) | ||
| 3070 | goto err_free; | ||
| 3071 | |||
| 3072 | ret = -EINVAL; | ||
| 3073 | err = amd64_check_ecc_enabled(pvt); | ||
| 3074 | if (err) | ||
| 3075 | goto err_put; | ||
| 3076 | |||
| 3077 | /* | ||
| 3078 | * Key operation here: setup of HW prior to performing ops on it. Some | ||
| 3079 | * setup is required to access ECS data. After this is performed, the | ||
| 3080 | * 'teardown' function must be called upon error and normal exit paths. | ||
| 3081 | */ | ||
| 3082 | if (boot_cpu_data.x86 >= 0x10) | ||
| 3083 | amd64_setup(pvt); | ||
| 3084 | |||
| 3085 | /* | ||
| 3086 | * Save the pointer to the private data for use in 2nd initialization | ||
| 3087 | * stage | ||
| 3088 | */ | ||
| 3089 | pvt_lookup[pvt->mc_node_id] = pvt; | ||
| 3090 | |||
| 3091 | return 0; | ||
| 3092 | |||
| 3093 | err_put: | ||
| 3094 | amd64_free_mc_sibling_devices(pvt); | ||
| 3095 | |||
| 3096 | err_free: | ||
| 3097 | kfree(pvt); | ||
| 3098 | |||
| 3099 | err_exit: | ||
| 3100 | return ret; | ||
| 3101 | } | ||
| 3102 | |||
| 3103 | /* | ||
| 3104 | * This is the finishing stage of the init code. Needs to be performed after all | ||
| 3105 | * MCs' hardware have been prepped for accessing extended config space. | ||
| 3106 | */ | ||
| 3107 | static int amd64_init_2nd_stage(struct amd64_pvt *pvt) | ||
| 3108 | { | ||
| 3109 | int node_id = pvt->mc_node_id; | ||
| 3110 | struct mem_ctl_info *mci; | ||
| 3111 | int ret, err = 0; | ||
| 3112 | |||
| 3113 | amd64_read_mc_registers(pvt); | ||
| 3114 | |||
| 3115 | ret = -ENODEV; | ||
| 3116 | if (pvt->ops->probe_valid_hardware) { | ||
| 3117 | err = pvt->ops->probe_valid_hardware(pvt); | ||
| 3118 | if (err) | ||
| 3119 | goto err_exit; | ||
| 3120 | } | ||
| 3121 | |||
| 3122 | /* | ||
| 3123 | * We need to determine how many memory channels there are. Then use | ||
| 3124 | * that information for calculating the size of the dynamic instance | ||
| 3125 | * tables in the 'mci' structure | ||
| 3126 | */ | ||
| 3127 | pvt->channel_count = pvt->ops->early_channel_count(pvt); | ||
| 3128 | if (pvt->channel_count < 0) | ||
| 3129 | goto err_exit; | ||
| 3130 | |||
| 3131 | ret = -ENOMEM; | ||
| 3132 | mci = edac_mc_alloc(0, CHIPSELECT_COUNT, pvt->channel_count, node_id); | ||
| 3133 | if (!mci) | ||
| 3134 | goto err_exit; | ||
| 3135 | |||
| 3136 | mci->pvt_info = pvt; | ||
| 3137 | |||
| 3138 | mci->dev = &pvt->dram_f2_ctl->dev; | ||
| 3139 | amd64_setup_mci_misc_attributes(mci); | ||
| 3140 | |||
| 3141 | if (amd64_init_csrows(mci)) | ||
| 3142 | mci->edac_cap = EDAC_FLAG_NONE; | ||
| 3143 | |||
| 3144 | amd64_enable_ecc_error_reporting(mci); | ||
| 3145 | amd64_set_mc_sysfs_attributes(mci); | ||
| 3146 | |||
| 3147 | ret = -ENODEV; | ||
| 3148 | if (edac_mc_add_mc(mci)) { | ||
| 3149 | debugf1("failed edac_mc_add_mc()\n"); | ||
| 3150 | goto err_add_mc; | ||
| 3151 | } | ||
| 3152 | |||
| 3153 | mci_lookup[node_id] = mci; | ||
| 3154 | pvt_lookup[node_id] = NULL; | ||
| 3155 | return 0; | ||
| 3156 | |||
| 3157 | err_add_mc: | ||
| 3158 | edac_mc_free(mci); | ||
| 3159 | |||
| 3160 | err_exit: | ||
| 3161 | debugf0("failure to init 2nd stage: ret=%d\n", ret); | ||
| 3162 | |||
| 3163 | amd64_restore_ecc_error_reporting(pvt); | ||
| 3164 | |||
| 3165 | if (boot_cpu_data.x86 > 0xf) | ||
| 3166 | amd64_teardown(pvt); | ||
| 3167 | |||
| 3168 | amd64_free_mc_sibling_devices(pvt); | ||
| 3169 | |||
| 3170 | kfree(pvt_lookup[pvt->mc_node_id]); | ||
| 3171 | pvt_lookup[node_id] = NULL; | ||
| 3172 | |||
| 3173 | return ret; | ||
| 3174 | } | ||
| 3175 | |||
| 3176 | |||
| 3177 | static int __devinit amd64_init_one_instance(struct pci_dev *pdev, | ||
| 3178 | const struct pci_device_id *mc_type) | ||
| 3179 | { | ||
| 3180 | int ret = 0; | ||
| 3181 | |||
| 3182 | debugf0("(MC node=%d,mc_type='%s')\n", | ||
| 3183 | get_mc_node_id_from_pdev(pdev), | ||
| 3184 | get_amd_family_name(mc_type->driver_data)); | ||
| 3185 | |||
| 3186 | ret = pci_enable_device(pdev); | ||
| 3187 | if (ret < 0) | ||
| 3188 | ret = -EIO; | ||
| 3189 | else | ||
| 3190 | ret = amd64_probe_one_instance(pdev, mc_type->driver_data); | ||
| 3191 | |||
| 3192 | if (ret < 0) | ||
| 3193 | debugf0("ret=%d\n", ret); | ||
| 3194 | |||
| 3195 | return ret; | ||
| 3196 | } | ||
| 3197 | |||
| 3198 | static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) | ||
| 3199 | { | ||
| 3200 | struct mem_ctl_info *mci; | ||
| 3201 | struct amd64_pvt *pvt; | ||
| 3202 | |||
| 3203 | /* Remove from EDAC CORE tracking list */ | ||
| 3204 | mci = edac_mc_del_mc(&pdev->dev); | ||
| 3205 | if (!mci) | ||
| 3206 | return; | ||
| 3207 | |||
| 3208 | pvt = mci->pvt_info; | ||
| 3209 | |||
| 3210 | amd64_restore_ecc_error_reporting(pvt); | ||
| 3211 | |||
| 3212 | if (boot_cpu_data.x86 > 0xf) | ||
| 3213 | amd64_teardown(pvt); | ||
| 3214 | |||
| 3215 | amd64_free_mc_sibling_devices(pvt); | ||
| 3216 | |||
| 3217 | kfree(pvt); | ||
| 3218 | mci->pvt_info = NULL; | ||
| 3219 | |||
| 3220 | mci_lookup[pvt->mc_node_id] = NULL; | ||
| 3221 | |||
| 3222 | /* Free the EDAC CORE resources */ | ||
| 3223 | edac_mc_free(mci); | ||
| 3224 | } | ||
| 3225 | |||
| 3226 | /* | ||
| 3227 | * This table is part of the interface for loading drivers for PCI devices. The | ||
| 3228 | * PCI core identifies what devices are on a system during boot, and then | ||
| 3229 | * inquiry this table to see if this driver is for a given device found. | ||
| 3230 | */ | ||
| 3231 | static const struct pci_device_id amd64_pci_table[] __devinitdata = { | ||
| 3232 | { | ||
| 3233 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 3234 | .device = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, | ||
| 3235 | .subvendor = PCI_ANY_ID, | ||
| 3236 | .subdevice = PCI_ANY_ID, | ||
| 3237 | .class = 0, | ||
| 3238 | .class_mask = 0, | ||
| 3239 | .driver_data = K8_CPUS | ||
| 3240 | }, | ||
| 3241 | { | ||
| 3242 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 3243 | .device = PCI_DEVICE_ID_AMD_10H_NB_DRAM, | ||
| 3244 | .subvendor = PCI_ANY_ID, | ||
| 3245 | .subdevice = PCI_ANY_ID, | ||
| 3246 | .class = 0, | ||
| 3247 | .class_mask = 0, | ||
| 3248 | .driver_data = F10_CPUS | ||
| 3249 | }, | ||
| 3250 | { | ||
| 3251 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 3252 | .device = PCI_DEVICE_ID_AMD_11H_NB_DRAM, | ||
| 3253 | .subvendor = PCI_ANY_ID, | ||
| 3254 | .subdevice = PCI_ANY_ID, | ||
| 3255 | .class = 0, | ||
| 3256 | .class_mask = 0, | ||
| 3257 | .driver_data = F11_CPUS | ||
| 3258 | }, | ||
| 3259 | {0, } | ||
| 3260 | }; | ||
| 3261 | MODULE_DEVICE_TABLE(pci, amd64_pci_table); | ||
| 3262 | |||
| 3263 | static struct pci_driver amd64_pci_driver = { | ||
| 3264 | .name = EDAC_MOD_STR, | ||
| 3265 | .probe = amd64_init_one_instance, | ||
| 3266 | .remove = __devexit_p(amd64_remove_one_instance), | ||
| 3267 | .id_table = amd64_pci_table, | ||
| 3268 | }; | ||
| 3269 | |||
| 3270 | static void amd64_setup_pci_device(void) | ||
| 3271 | { | ||
| 3272 | struct mem_ctl_info *mci; | ||
| 3273 | struct amd64_pvt *pvt; | ||
| 3274 | |||
| 3275 | if (amd64_ctl_pci) | ||
| 3276 | return; | ||
| 3277 | |||
| 3278 | mci = mci_lookup[0]; | ||
| 3279 | if (mci) { | ||
| 3280 | |||
| 3281 | pvt = mci->pvt_info; | ||
| 3282 | amd64_ctl_pci = | ||
| 3283 | edac_pci_create_generic_ctl(&pvt->dram_f2_ctl->dev, | ||
| 3284 | EDAC_MOD_STR); | ||
| 3285 | |||
| 3286 | if (!amd64_ctl_pci) { | ||
| 3287 | pr_warning("%s(): Unable to create PCI control\n", | ||
| 3288 | __func__); | ||
| 3289 | |||
| 3290 | pr_warning("%s(): PCI error report via EDAC not set\n", | ||
| 3291 | __func__); | ||
| 3292 | } | ||
| 3293 | } | ||
| 3294 | } | ||
| 3295 | |||
| 3296 | static int __init amd64_edac_init(void) | ||
| 3297 | { | ||
| 3298 | int nb, err = -ENODEV; | ||
| 3299 | |||
| 3300 | edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); | ||
| 3301 | |||
| 3302 | opstate_init(); | ||
| 3303 | |||
| 3304 | if (cache_k8_northbridges() < 0) | ||
| 3305 | goto err_exit; | ||
| 3306 | |||
| 3307 | err = pci_register_driver(&amd64_pci_driver); | ||
| 3308 | if (err) | ||
| 3309 | return err; | ||
| 3310 | |||
| 3311 | /* | ||
| 3312 | * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd | ||
| 3313 | * amd64_pvt structs. These will be used in the 2nd stage init function | ||
| 3314 | * to finish initialization of the MC instances. | ||
| 3315 | */ | ||
| 3316 | for (nb = 0; nb < num_k8_northbridges; nb++) { | ||
| 3317 | if (!pvt_lookup[nb]) | ||
| 3318 | continue; | ||
| 3319 | |||
| 3320 | err = amd64_init_2nd_stage(pvt_lookup[nb]); | ||
| 3321 | if (err) | ||
| 3322 | goto err_exit; | ||
| 3323 | } | ||
| 3324 | |||
| 3325 | amd64_setup_pci_device(); | ||
| 3326 | |||
| 3327 | return 0; | ||
| 3328 | |||
| 3329 | err_exit: | ||
| 3330 | debugf0("'finish_setup' stage failed\n"); | ||
| 3331 | pci_unregister_driver(&amd64_pci_driver); | ||
| 3332 | |||
| 3333 | return err; | ||
| 3334 | } | ||
| 3335 | |||
| 3336 | static void __exit amd64_edac_exit(void) | ||
| 3337 | { | ||
| 3338 | if (amd64_ctl_pci) | ||
| 3339 | edac_pci_release_generic_ctl(amd64_ctl_pci); | ||
| 3340 | |||
| 3341 | pci_unregister_driver(&amd64_pci_driver); | ||
| 3342 | } | ||
| 3343 | |||
| 3344 | module_init(amd64_edac_init); | ||
| 3345 | module_exit(amd64_edac_exit); | ||
| 3346 | |||
| 3347 | MODULE_LICENSE("GPL"); | ||
| 3348 | MODULE_AUTHOR("SoftwareBitMaker: Doug Thompson, " | ||
| 3349 | "Dave Peterson, Thayne Harbaugh"); | ||
| 3350 | MODULE_DESCRIPTION("MC support for AMD64 memory controllers - " | ||
| 3351 | EDAC_AMD64_VERSION); | ||
| 3352 | |||
| 3353 | module_param(edac_op_state, int, 0444); | ||
| 3354 | MODULE_PARM_DESC(edac_op_state, "EDAC Error Reporting state: 0=Poll,1=NMI"); | ||
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h new file mode 100644 index 000000000000..a159957e167b --- /dev/null +++ b/drivers/edac/amd64_edac.h | |||
| @@ -0,0 +1,644 @@ | |||
| 1 | /* | ||
| 2 | * AMD64 class Memory Controller kernel module | ||
| 3 | * | ||
| 4 | * Copyright (c) 2009 SoftwareBitMaker. | ||
| 5 | * Copyright (c) 2009 Advanced Micro Devices, Inc. | ||
| 6 | * | ||
| 7 | * This file may be distributed under the terms of the | ||
| 8 | * GNU General Public License. | ||
| 9 | * | ||
| 10 | * Originally Written by Thayne Harbaugh | ||
| 11 | * | ||
| 12 | * Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>: | ||
| 13 | * - K8 CPU Revision D and greater support | ||
| 14 | * | ||
| 15 | * Changes by Dave Peterson <dsp@llnl.gov> <dave_peterson@pobox.com>: | ||
| 16 | * - Module largely rewritten, with new (and hopefully correct) | ||
| 17 | * code for dealing with node and chip select interleaving, | ||
| 18 | * various code cleanup, and bug fixes | ||
| 19 | * - Added support for memory hoisting using DRAM hole address | ||
| 20 | * register | ||
| 21 | * | ||
| 22 | * Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>: | ||
| 23 | * -K8 Rev (1207) revision support added, required Revision | ||
| 24 | * specific mini-driver code to support Rev F as well as | ||
| 25 | * prior revisions | ||
| 26 | * | ||
| 27 | * Changes by Douglas "norsk" Thompson <dougthompson@xmission.com>: | ||
| 28 | * -Family 10h revision support added. New PCI Device IDs, | ||
| 29 | * indicating new changes. Actual registers modified | ||
| 30 | * were slight, less than the Rev E to Rev F transition | ||
| 31 | * but changing the PCI Device ID was the proper thing to | ||
| 32 | * do, as it provides for almost automactic family | ||
| 33 | * detection. The mods to Rev F required more family | ||
| 34 | * information detection. | ||
| 35 | * | ||
| 36 | * Changes/Fixes by Borislav Petkov <borislav.petkov@amd.com>: | ||
| 37 | * - misc fixes and code cleanups | ||
| 38 | * | ||
| 39 | * This module is based on the following documents | ||
| 40 | * (available from http://www.amd.com/): | ||
| 41 | * | ||
| 42 | * Title: BIOS and Kernel Developer's Guide for AMD Athlon 64 and AMD | ||
| 43 | * Opteron Processors | ||
| 44 | * AMD publication #: 26094 | ||
| 45 | *` Revision: 3.26 | ||
| 46 | * | ||
| 47 | * Title: BIOS and Kernel Developer's Guide for AMD NPT Family 0Fh | ||
| 48 | * Processors | ||
| 49 | * AMD publication #: 32559 | ||
| 50 | * Revision: 3.00 | ||
| 51 | * Issue Date: May 2006 | ||
| 52 | * | ||
| 53 | * Title: BIOS and Kernel Developer's Guide (BKDG) For AMD Family 10h | ||
| 54 | * Processors | ||
| 55 | * AMD publication #: 31116 | ||
| 56 | * Revision: 3.00 | ||
| 57 | * Issue Date: September 07, 2007 | ||
| 58 | * | ||
| 59 | * Sections in the first 2 documents are no longer in sync with each other. | ||
| 60 | * The Family 10h BKDG was totally re-written from scratch with a new | ||
| 61 | * presentation model. | ||
| 62 | * Therefore, comments that refer to a Document section might be off. | ||
| 63 | */ | ||
| 64 | |||
| 65 | #include <linux/module.h> | ||
| 66 | #include <linux/ctype.h> | ||
| 67 | #include <linux/init.h> | ||
| 68 | #include <linux/pci.h> | ||
| 69 | #include <linux/pci_ids.h> | ||
| 70 | #include <linux/slab.h> | ||
| 71 | #include <linux/mmzone.h> | ||
| 72 | #include <linux/edac.h> | ||
| 73 | #include <asm/msr.h> | ||
| 74 | #include "edac_core.h" | ||
| 75 | |||
| 76 | #define amd64_printk(level, fmt, arg...) \ | ||
| 77 | edac_printk(level, "amd64", fmt, ##arg) | ||
| 78 | |||
| 79 | #define amd64_mc_printk(mci, level, fmt, arg...) \ | ||
| 80 | edac_mc_chipset_printk(mci, level, "amd64", fmt, ##arg) | ||
| 81 | |||
| 82 | /* | ||
| 83 | * Throughout the comments in this code, the following terms are used: | ||
| 84 | * | ||
| 85 | * SysAddr, DramAddr, and InputAddr | ||
| 86 | * | ||
| 87 | * These terms come directly from the amd64 documentation | ||
| 88 | * (AMD publication #26094). They are defined as follows: | ||
| 89 | * | ||
| 90 | * SysAddr: | ||
| 91 | * This is a physical address generated by a CPU core or a device | ||
| 92 | * doing DMA. If generated by a CPU core, a SysAddr is the result of | ||
| 93 | * a virtual to physical address translation by the CPU core's address | ||
| 94 | * translation mechanism (MMU). | ||
| 95 | * | ||
| 96 | * DramAddr: | ||
| 97 | * A DramAddr is derived from a SysAddr by subtracting an offset that | ||
| 98 | * depends on which node the SysAddr maps to and whether the SysAddr | ||
| 99 | * is within a range affected by memory hoisting. The DRAM Base | ||
| 100 | * (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers | ||
| 101 | * determine which node a SysAddr maps to. | ||
| 102 | * | ||
| 103 | * If the DRAM Hole Address Register (DHAR) is enabled and the SysAddr | ||
| 104 | * is within the range of addresses specified by this register, then | ||
| 105 | * a value x from the DHAR is subtracted from the SysAddr to produce a | ||
| 106 | * DramAddr. Here, x represents the base address for the node that | ||
| 107 | * the SysAddr maps to plus an offset due to memory hoisting. See | ||
| 108 | * section 3.4.8 and the comments in amd64_get_dram_hole_info() and | ||
| 109 | * sys_addr_to_dram_addr() below for more information. | ||
| 110 | * | ||
| 111 | * If the SysAddr is not affected by the DHAR then a value y is | ||
| 112 | * subtracted from the SysAddr to produce a DramAddr. Here, y is the | ||
| 113 | * base address for the node that the SysAddr maps to. See section | ||
| 114 | * 3.4.4 and the comments in sys_addr_to_dram_addr() below for more | ||
| 115 | * information. | ||
| 116 | * | ||
| 117 | * InputAddr: | ||
| 118 | * A DramAddr is translated to an InputAddr before being passed to the | ||
| 119 | * memory controller for the node that the DramAddr is associated | ||
| 120 | * with. The memory controller then maps the InputAddr to a csrow. | ||
| 121 | * If node interleaving is not in use, then the InputAddr has the same | ||
| 122 | * value as the DramAddr. Otherwise, the InputAddr is produced by | ||
| 123 | * discarding the bits used for node interleaving from the DramAddr. | ||
| 124 | * See section 3.4.4 for more information. | ||
| 125 | * | ||
| 126 | * The memory controller for a given node uses its DRAM CS Base and | ||
| 127 | * DRAM CS Mask registers to map an InputAddr to a csrow. See | ||
| 128 | * sections 3.5.4 and 3.5.5 for more information. | ||
| 129 | */ | ||
| 130 | |||
| 131 | #define EDAC_AMD64_VERSION " Ver: 3.2.0 " __DATE__ | ||
| 132 | #define EDAC_MOD_STR "amd64_edac" | ||
| 133 | |||
| 134 | /* Extended Model from CPUID, for CPU Revision numbers */ | ||
| 135 | #define OPTERON_CPU_LE_REV_C 0 | ||
| 136 | #define OPTERON_CPU_REV_D 1 | ||
| 137 | #define OPTERON_CPU_REV_E 2 | ||
| 138 | |||
| 139 | /* NPT processors have the following Extended Models */ | ||
| 140 | #define OPTERON_CPU_REV_F 4 | ||
| 141 | #define OPTERON_CPU_REV_FA 5 | ||
| 142 | |||
| 143 | /* Hardware limit on ChipSelect rows per MC and processors per system */ | ||
| 144 | #define CHIPSELECT_COUNT 8 | ||
| 145 | #define DRAM_REG_COUNT 8 | ||
| 146 | |||
| 147 | |||
| 148 | /* | ||
| 149 | * PCI-defined configuration space registers | ||
| 150 | */ | ||
| 151 | |||
| 152 | |||
| 153 | /* | ||
| 154 | * Function 1 - Address Map | ||
| 155 | */ | ||
| 156 | #define K8_DRAM_BASE_LOW 0x40 | ||
| 157 | #define K8_DRAM_LIMIT_LOW 0x44 | ||
| 158 | #define K8_DHAR 0xf0 | ||
| 159 | |||
| 160 | #define DHAR_VALID BIT(0) | ||
| 161 | #define F10_DRAM_MEM_HOIST_VALID BIT(1) | ||
| 162 | |||
| 163 | #define DHAR_BASE_MASK 0xff000000 | ||
| 164 | #define dhar_base(dhar) (dhar & DHAR_BASE_MASK) | ||
| 165 | |||
| 166 | #define K8_DHAR_OFFSET_MASK 0x0000ff00 | ||
| 167 | #define k8_dhar_offset(dhar) ((dhar & K8_DHAR_OFFSET_MASK) << 16) | ||
| 168 | |||
| 169 | #define F10_DHAR_OFFSET_MASK 0x0000ff80 | ||
| 170 | /* NOTE: Extra mask bit vs K8 */ | ||
| 171 | #define f10_dhar_offset(dhar) ((dhar & F10_DHAR_OFFSET_MASK) << 16) | ||
| 172 | |||
| 173 | |||
| 174 | /* F10 High BASE/LIMIT registers */ | ||
| 175 | #define F10_DRAM_BASE_HIGH 0x140 | ||
| 176 | #define F10_DRAM_LIMIT_HIGH 0x144 | ||
| 177 | |||
| 178 | |||
| 179 | /* | ||
| 180 | * Function 2 - DRAM controller | ||
| 181 | */ | ||
| 182 | #define K8_DCSB0 0x40 | ||
| 183 | #define F10_DCSB1 0x140 | ||
| 184 | |||
| 185 | #define K8_DCSB_CS_ENABLE BIT(0) | ||
| 186 | #define K8_DCSB_NPT_SPARE BIT(1) | ||
| 187 | #define K8_DCSB_NPT_TESTFAIL BIT(2) | ||
| 188 | |||
| 189 | /* | ||
| 190 | * REV E: select [31:21] and [15:9] from DCSB and the shift amount to form | ||
| 191 | * the address | ||
| 192 | */ | ||
| 193 | #define REV_E_DCSB_BASE_BITS (0xFFE0FE00ULL) | ||
| 194 | #define REV_E_DCS_SHIFT 4 | ||
| 195 | #define REV_E_DCSM_COUNT 8 | ||
| 196 | |||
| 197 | #define REV_F_F1Xh_DCSB_BASE_BITS (0x1FF83FE0ULL) | ||
| 198 | #define REV_F_F1Xh_DCS_SHIFT 8 | ||
| 199 | |||
| 200 | /* | ||
| 201 | * REV F and later: selects [28:19] and [13:5] from DCSB and the shift amount | ||
| 202 | * to form the address | ||
| 203 | */ | ||
| 204 | #define REV_F_DCSB_BASE_BITS (0x1FF83FE0ULL) | ||
| 205 | #define REV_F_DCS_SHIFT 8 | ||
| 206 | #define REV_F_DCSM_COUNT 4 | ||
| 207 | #define F10_DCSM_COUNT 4 | ||
| 208 | #define F11_DCSM_COUNT 2 | ||
| 209 | |||
| 210 | /* DRAM CS Mask Registers */ | ||
| 211 | #define K8_DCSM0 0x60 | ||
| 212 | #define F10_DCSM1 0x160 | ||
| 213 | |||
| 214 | /* REV E: select [29:21] and [15:9] from DCSM */ | ||
| 215 | #define REV_E_DCSM_MASK_BITS 0x3FE0FE00 | ||
| 216 | |||
| 217 | /* unused bits [24:20] and [12:0] */ | ||
| 218 | #define REV_E_DCS_NOTUSED_BITS 0x01F01FFF | ||
| 219 | |||
| 220 | /* REV F and later: select [28:19] and [13:5] from DCSM */ | ||
| 221 | #define REV_F_F1Xh_DCSM_MASK_BITS 0x1FF83FE0 | ||
| 222 | |||
| 223 | /* unused bits [26:22] and [12:0] */ | ||
| 224 | #define REV_F_F1Xh_DCS_NOTUSED_BITS 0x07C01FFF | ||
| 225 | |||
| 226 | #define DBAM0 0x80 | ||
| 227 | #define DBAM1 0x180 | ||
| 228 | |||
| 229 | /* Extract the DIMM 'type' on the i'th DIMM from the DBAM reg value passed */ | ||
| 230 | #define DBAM_DIMM(i, reg) ((((reg) >> (4*i))) & 0xF) | ||
| 231 | |||
| 232 | #define DBAM_MAX_VALUE 11 | ||
| 233 | |||
| 234 | |||
| 235 | #define F10_DCLR_0 0x90 | ||
| 236 | #define F10_DCLR_1 0x190 | ||
| 237 | #define REVE_WIDTH_128 BIT(16) | ||
| 238 | #define F10_WIDTH_128 BIT(11) | ||
| 239 | |||
| 240 | |||
| 241 | #define F10_DCHR_0 0x94 | ||
| 242 | #define F10_DCHR_1 0x194 | ||
| 243 | |||
| 244 | #define F10_DCHR_FOUR_RANK_DIMM BIT(18) | ||
| 245 | #define F10_DCHR_Ddr3Mode BIT(8) | ||
| 246 | #define F10_DCHR_MblMode BIT(6) | ||
| 247 | |||
| 248 | |||
| 249 | #define F10_DCTL_SEL_LOW 0x110 | ||
| 250 | |||
| 251 | #define dct_sel_baseaddr(pvt) \ | ||
| 252 | ((pvt->dram_ctl_select_low) & 0xFFFFF800) | ||
| 253 | |||
| 254 | #define dct_sel_interleave_addr(pvt) \ | ||
| 255 | (((pvt->dram_ctl_select_low) >> 6) & 0x3) | ||
| 256 | |||
| 257 | enum { | ||
| 258 | F10_DCTL_SEL_LOW_DctSelHiRngEn = BIT(0), | ||
| 259 | F10_DCTL_SEL_LOW_DctSelIntLvEn = BIT(2), | ||
| 260 | F10_DCTL_SEL_LOW_DctGangEn = BIT(4), | ||
| 261 | F10_DCTL_SEL_LOW_DctDatIntLv = BIT(5), | ||
| 262 | F10_DCTL_SEL_LOW_DramEnable = BIT(8), | ||
| 263 | F10_DCTL_SEL_LOW_MemCleared = BIT(10), | ||
| 264 | }; | ||
| 265 | |||
| 266 | #define dct_high_range_enabled(pvt) \ | ||
| 267 | (pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctSelHiRngEn) | ||
| 268 | |||
| 269 | #define dct_interleave_enabled(pvt) \ | ||
| 270 | (pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctSelIntLvEn) | ||
| 271 | |||
| 272 | #define dct_ganging_enabled(pvt) \ | ||
| 273 | (pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctGangEn) | ||
| 274 | |||
| 275 | #define dct_data_intlv_enabled(pvt) \ | ||
| 276 | (pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DctDatIntLv) | ||
| 277 | |||
| 278 | #define dct_dram_enabled(pvt) \ | ||
| 279 | (pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_DramEnable) | ||
| 280 | |||
| 281 | #define dct_memory_cleared(pvt) \ | ||
| 282 | (pvt->dram_ctl_select_low & F10_DCTL_SEL_LOW_MemCleared) | ||
| 283 | |||
| 284 | |||
| 285 | #define F10_DCTL_SEL_HIGH 0x114 | ||
| 286 | |||
| 287 | |||
| 288 | /* | ||
| 289 | * Function 3 - Misc Control | ||
| 290 | */ | ||
| 291 | #define K8_NBCTL 0x40 | ||
| 292 | |||
| 293 | /* Correctable ECC error reporting enable */ | ||
| 294 | #define K8_NBCTL_CECCEn BIT(0) | ||
| 295 | |||
| 296 | /* UnCorrectable ECC error reporting enable */ | ||
| 297 | #define K8_NBCTL_UECCEn BIT(1) | ||
| 298 | |||
| 299 | #define K8_NBCFG 0x44 | ||
| 300 | #define K8_NBCFG_CHIPKILL BIT(23) | ||
| 301 | #define K8_NBCFG_ECC_ENABLE BIT(22) | ||
| 302 | |||
| 303 | #define K8_NBSL 0x48 | ||
| 304 | |||
| 305 | |||
| 306 | #define EXTRACT_HIGH_SYNDROME(x) (((x) >> 24) & 0xff) | ||
| 307 | #define EXTRACT_EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f) | ||
| 308 | |||
| 309 | /* Family F10h: Normalized Extended Error Codes */ | ||
| 310 | #define F10_NBSL_EXT_ERR_RES 0x0 | ||
| 311 | #define F10_NBSL_EXT_ERR_CRC 0x1 | ||
| 312 | #define F10_NBSL_EXT_ERR_SYNC 0x2 | ||
| 313 | #define F10_NBSL_EXT_ERR_MST 0x3 | ||
| 314 | #define F10_NBSL_EXT_ERR_TGT 0x4 | ||
| 315 | #define F10_NBSL_EXT_ERR_GART 0x5 | ||
| 316 | #define F10_NBSL_EXT_ERR_RMW 0x6 | ||
| 317 | #define F10_NBSL_EXT_ERR_WDT 0x7 | ||
| 318 | #define F10_NBSL_EXT_ERR_ECC 0x8 | ||
| 319 | #define F10_NBSL_EXT_ERR_DEV 0x9 | ||
| 320 | #define F10_NBSL_EXT_ERR_LINK_DATA 0xA | ||
| 321 | |||
| 322 | /* Next two are overloaded values */ | ||
| 323 | #define F10_NBSL_EXT_ERR_LINK_PROTO 0xB | ||
| 324 | #define F10_NBSL_EXT_ERR_L3_PROTO 0xB | ||
| 325 | |||
| 326 | #define F10_NBSL_EXT_ERR_NB_ARRAY 0xC | ||
| 327 | #define F10_NBSL_EXT_ERR_DRAM_PARITY 0xD | ||
| 328 | #define F10_NBSL_EXT_ERR_LINK_RETRY 0xE | ||
| 329 | |||
| 330 | /* Next two are overloaded values */ | ||
| 331 | #define F10_NBSL_EXT_ERR_GART_WALK 0xF | ||
| 332 | #define F10_NBSL_EXT_ERR_DEV_WALK 0xF | ||
| 333 | |||
| 334 | /* 0x10 to 0x1B: Reserved */ | ||
| 335 | #define F10_NBSL_EXT_ERR_L3_DATA 0x1C | ||
| 336 | #define F10_NBSL_EXT_ERR_L3_TAG 0x1D | ||
| 337 | #define F10_NBSL_EXT_ERR_L3_LRU 0x1E | ||
| 338 | |||
| 339 | /* K8: Normalized Extended Error Codes */ | ||
| 340 | #define K8_NBSL_EXT_ERR_ECC 0x0 | ||
| 341 | #define K8_NBSL_EXT_ERR_CRC 0x1 | ||
| 342 | #define K8_NBSL_EXT_ERR_SYNC 0x2 | ||
| 343 | #define K8_NBSL_EXT_ERR_MST 0x3 | ||
| 344 | #define K8_NBSL_EXT_ERR_TGT 0x4 | ||
| 345 | #define K8_NBSL_EXT_ERR_GART 0x5 | ||
| 346 | #define K8_NBSL_EXT_ERR_RMW 0x6 | ||
| 347 | #define K8_NBSL_EXT_ERR_WDT 0x7 | ||
| 348 | #define K8_NBSL_EXT_ERR_CHIPKILL_ECC 0x8 | ||
| 349 | #define K8_NBSL_EXT_ERR_DRAM_PARITY 0xD | ||
| 350 | |||
| 351 | #define EXTRACT_ERROR_CODE(x) ((x) & 0xffff) | ||
| 352 | #define TEST_TLB_ERROR(x) (((x) & 0xFFF0) == 0x0010) | ||
| 353 | #define TEST_MEM_ERROR(x) (((x) & 0xFF00) == 0x0100) | ||
| 354 | #define TEST_BUS_ERROR(x) (((x) & 0xF800) == 0x0800) | ||
| 355 | #define EXTRACT_TT_CODE(x) (((x) >> 2) & 0x3) | ||
| 356 | #define EXTRACT_II_CODE(x) (((x) >> 2) & 0x3) | ||
| 357 | #define EXTRACT_LL_CODE(x) (((x) >> 0) & 0x3) | ||
| 358 | #define EXTRACT_RRRR_CODE(x) (((x) >> 4) & 0xf) | ||
| 359 | #define EXTRACT_TO_CODE(x) (((x) >> 8) & 0x1) | ||
| 360 | #define EXTRACT_PP_CODE(x) (((x) >> 9) & 0x3) | ||
| 361 | |||
| 362 | /* | ||
| 363 | * The following are for BUS type errors AFTER values have been normalized by | ||
| 364 | * shifting right | ||
| 365 | */ | ||
| 366 | #define K8_NBSL_PP_SRC 0x0 | ||
| 367 | #define K8_NBSL_PP_RES 0x1 | ||
| 368 | #define K8_NBSL_PP_OBS 0x2 | ||
| 369 | #define K8_NBSL_PP_GENERIC 0x3 | ||
| 370 | |||
| 371 | |||
| 372 | #define K8_NBSH 0x4C | ||
| 373 | |||
| 374 | #define K8_NBSH_VALID_BIT BIT(31) | ||
| 375 | #define K8_NBSH_OVERFLOW BIT(30) | ||
| 376 | #define K8_NBSH_UNCORRECTED_ERR BIT(29) | ||
| 377 | #define K8_NBSH_ERR_ENABLE BIT(28) | ||
| 378 | #define K8_NBSH_MISC_ERR_VALID BIT(27) | ||
| 379 | #define K8_NBSH_VALID_ERROR_ADDR BIT(26) | ||
| 380 | #define K8_NBSH_PCC BIT(25) | ||
| 381 | #define K8_NBSH_CECC BIT(14) | ||
| 382 | #define K8_NBSH_UECC BIT(13) | ||
| 383 | #define K8_NBSH_ERR_SCRUBER BIT(8) | ||
| 384 | #define K8_NBSH_CORE3 BIT(3) | ||
| 385 | #define K8_NBSH_CORE2 BIT(2) | ||
| 386 | #define K8_NBSH_CORE1 BIT(1) | ||
| 387 | #define K8_NBSH_CORE0 BIT(0) | ||
| 388 | |||
| 389 | #define EXTRACT_LDT_LINK(x) (((x) >> 4) & 0x7) | ||
| 390 | #define EXTRACT_ERR_CPU_MAP(x) ((x) & 0xF) | ||
| 391 | #define EXTRACT_LOW_SYNDROME(x) (((x) >> 15) & 0xff) | ||
| 392 | |||
| 393 | |||
| 394 | #define K8_NBEAL 0x50 | ||
| 395 | #define K8_NBEAH 0x54 | ||
| 396 | #define K8_SCRCTRL 0x58 | ||
| 397 | |||
| 398 | #define F10_NB_CFG_LOW 0x88 | ||
| 399 | #define F10_NB_CFG_LOW_ENABLE_EXT_CFG BIT(14) | ||
| 400 | |||
| 401 | #define F10_NB_CFG_HIGH 0x8C | ||
| 402 | |||
| 403 | #define F10_ONLINE_SPARE 0xB0 | ||
| 404 | #define F10_ONLINE_SPARE_SWAPDONE0(x) ((x) & BIT(1)) | ||
| 405 | #define F10_ONLINE_SPARE_SWAPDONE1(x) ((x) & BIT(3)) | ||
| 406 | #define F10_ONLINE_SPARE_BADDRAM_CS0(x) (((x) >> 4) & 0x00000007) | ||
| 407 | #define F10_ONLINE_SPARE_BADDRAM_CS1(x) (((x) >> 8) & 0x00000007) | ||
| 408 | |||
| 409 | #define F10_NB_ARRAY_ADDR 0xB8 | ||
| 410 | |||
| 411 | #define F10_NB_ARRAY_DRAM_ECC 0x80000000 | ||
| 412 | |||
| 413 | /* Bits [2:1] are used to select 16-byte section within a 64-byte cacheline */ | ||
| 414 | #define SET_NB_ARRAY_ADDRESS(section) (((section) & 0x3) << 1) | ||
| 415 | |||
| 416 | #define F10_NB_ARRAY_DATA 0xBC | ||
| 417 | |||
| 418 | #define SET_NB_DRAM_INJECTION_WRITE(word, bits) \ | ||
| 419 | (BIT(((word) & 0xF) + 20) | \ | ||
| 420 | BIT(17) | \ | ||
| 421 | ((bits) & 0xF)) | ||
| 422 | |||
| 423 | #define SET_NB_DRAM_INJECTION_READ(word, bits) \ | ||
| 424 | (BIT(((word) & 0xF) + 20) | \ | ||
| 425 | BIT(16) | \ | ||
| 426 | ((bits) & 0xF)) | ||
| 427 | |||
| 428 | #define K8_NBCAP 0xE8 | ||
| 429 | #define K8_NBCAP_CORES (BIT(12)|BIT(13)) | ||
| 430 | #define K8_NBCAP_CHIPKILL BIT(4) | ||
| 431 | #define K8_NBCAP_SECDED BIT(3) | ||
| 432 | #define K8_NBCAP_8_NODE BIT(2) | ||
| 433 | #define K8_NBCAP_DUAL_NODE BIT(1) | ||
| 434 | #define K8_NBCAP_DCT_DUAL BIT(0) | ||
| 435 | |||
| 436 | /* | ||
| 437 | * MSR Regs | ||
| 438 | */ | ||
| 439 | #define K8_MSR_MCGCTL 0x017b | ||
| 440 | #define K8_MSR_MCGCTL_NBE BIT(4) | ||
| 441 | |||
| 442 | #define K8_MSR_MC4CTL 0x0410 | ||
| 443 | #define K8_MSR_MC4STAT 0x0411 | ||
| 444 | #define K8_MSR_MC4ADDR 0x0412 | ||
| 445 | |||
| 446 | /* AMD sets the first MC device at device ID 0x18. */ | ||
| 447 | static inline int get_mc_node_id_from_pdev(struct pci_dev *pdev) | ||
| 448 | { | ||
| 449 | return PCI_SLOT(pdev->devfn) - 0x18; | ||
| 450 | } | ||
| 451 | |||
| 452 | enum amd64_chipset_families { | ||
| 453 | K8_CPUS = 0, | ||
| 454 | F10_CPUS, | ||
| 455 | F11_CPUS, | ||
| 456 | }; | ||
| 457 | |||
| 458 | /* | ||
| 459 | * Structure to hold: | ||
| 460 | * | ||
| 461 | * 1) dynamically read status and error address HW registers | ||
| 462 | * 2) sysfs entered values | ||
| 463 | * 3) MCE values | ||
| 464 | * | ||
| 465 | * Depends on entry into the modules | ||
| 466 | */ | ||
| 467 | struct amd64_error_info_regs { | ||
| 468 | u32 nbcfg; | ||
| 469 | u32 nbsh; | ||
| 470 | u32 nbsl; | ||
| 471 | u32 nbeah; | ||
| 472 | u32 nbeal; | ||
| 473 | }; | ||
| 474 | |||
| 475 | /* Error injection control structure */ | ||
| 476 | struct error_injection { | ||
| 477 | u32 section; | ||
| 478 | u32 word; | ||
| 479 | u32 bit_map; | ||
| 480 | }; | ||
| 481 | |||
| 482 | struct amd64_pvt { | ||
| 483 | /* pci_device handles which we utilize */ | ||
| 484 | struct pci_dev *addr_f1_ctl; | ||
| 485 | struct pci_dev *dram_f2_ctl; | ||
| 486 | struct pci_dev *misc_f3_ctl; | ||
| 487 | |||
| 488 | int mc_node_id; /* MC index of this MC node */ | ||
| 489 | int ext_model; /* extended model value of this node */ | ||
| 490 | |||
| 491 | struct low_ops *ops; /* pointer to per PCI Device ID func table */ | ||
| 492 | |||
| 493 | int channel_count; | ||
| 494 | |||
| 495 | /* Raw registers */ | ||
| 496 | u32 dclr0; /* DRAM Configuration Low DCT0 reg */ | ||
| 497 | u32 dclr1; /* DRAM Configuration Low DCT1 reg */ | ||
| 498 | u32 dchr0; /* DRAM Configuration High DCT0 reg */ | ||
| 499 | u32 dchr1; /* DRAM Configuration High DCT1 reg */ | ||
| 500 | u32 nbcap; /* North Bridge Capabilities */ | ||
| 501 | u32 nbcfg; /* F10 North Bridge Configuration */ | ||
| 502 | u32 ext_nbcfg; /* Extended F10 North Bridge Configuration */ | ||
| 503 | u32 dhar; /* DRAM Hoist reg */ | ||
| 504 | u32 dbam0; /* DRAM Base Address Mapping reg for DCT0 */ | ||
| 505 | u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */ | ||
| 506 | |||
| 507 | /* DRAM CS Base Address Registers F2x[1,0][5C:40] */ | ||
| 508 | u32 dcsb0[CHIPSELECT_COUNT]; | ||
| 509 | u32 dcsb1[CHIPSELECT_COUNT]; | ||
| 510 | |||
| 511 | /* DRAM CS Mask Registers F2x[1,0][6C:60] */ | ||
| 512 | u32 dcsm0[CHIPSELECT_COUNT]; | ||
| 513 | u32 dcsm1[CHIPSELECT_COUNT]; | ||
| 514 | |||
| 515 | /* | ||
| 516 | * Decoded parts of DRAM BASE and LIMIT Registers | ||
| 517 | * F1x[78,70,68,60,58,50,48,40] | ||
| 518 | */ | ||
| 519 | u64 dram_base[DRAM_REG_COUNT]; | ||
| 520 | u64 dram_limit[DRAM_REG_COUNT]; | ||
| 521 | u8 dram_IntlvSel[DRAM_REG_COUNT]; | ||
| 522 | u8 dram_IntlvEn[DRAM_REG_COUNT]; | ||
| 523 | u8 dram_DstNode[DRAM_REG_COUNT]; | ||
| 524 | u8 dram_rw_en[DRAM_REG_COUNT]; | ||
| 525 | |||
| 526 | /* | ||
| 527 | * The following fields are set at (load) run time, after CPU revision | ||
| 528 | * has been determined, since the dct_base and dct_mask registers vary | ||
| 529 | * based on revision | ||
| 530 | */ | ||
| 531 | u32 dcsb_base; /* DCSB base bits */ | ||
| 532 | u32 dcsm_mask; /* DCSM mask bits */ | ||
| 533 | u32 num_dcsm; /* Number of DCSM registers */ | ||
| 534 | u32 dcs_mask_notused; /* DCSM notused mask bits */ | ||
| 535 | u32 dcs_shift; /* DCSB and DCSM shift value */ | ||
| 536 | |||
| 537 | u64 top_mem; /* top of memory below 4GB */ | ||
| 538 | u64 top_mem2; /* top of memory above 4GB */ | ||
| 539 | |||
| 540 | u32 dram_ctl_select_low; /* DRAM Controller Select Low Reg */ | ||
| 541 | u32 dram_ctl_select_high; /* DRAM Controller Select High Reg */ | ||
| 542 | u32 online_spare; /* On-Line spare Reg */ | ||
| 543 | |||
| 544 | /* temp storage for when input is received from sysfs */ | ||
| 545 | struct amd64_error_info_regs ctl_error_info; | ||
| 546 | |||
| 547 | /* place to store error injection parameters prior to issue */ | ||
| 548 | struct error_injection injection; | ||
| 549 | |||
| 550 | /* Save old hw registers' values before we modified them */ | ||
| 551 | u32 nbctl_mcgctl_saved; /* When true, following 2 are valid */ | ||
| 552 | u32 old_nbctl; | ||
| 553 | unsigned long old_mcgctl; /* per core on this node */ | ||
| 554 | |||
| 555 | /* MC Type Index value: socket F vs Family 10h */ | ||
| 556 | u32 mc_type_index; | ||
| 557 | |||
| 558 | /* misc settings */ | ||
| 559 | struct flags { | ||
| 560 | unsigned long cf8_extcfg:1; | ||
| 561 | } flags; | ||
| 562 | }; | ||
| 563 | |||
| 564 | struct scrubrate { | ||
| 565 | u32 scrubval; /* bit pattern for scrub rate */ | ||
| 566 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ | ||
| 567 | }; | ||
| 568 | |||
| 569 | extern struct scrubrate scrubrates[23]; | ||
| 570 | extern u32 revf_quad_ddr2_shift[16]; | ||
| 571 | extern const char *tt_msgs[4]; | ||
| 572 | extern const char *ll_msgs[4]; | ||
| 573 | extern const char *rrrr_msgs[16]; | ||
| 574 | extern const char *to_msgs[2]; | ||
| 575 | extern const char *pp_msgs[4]; | ||
| 576 | extern const char *ii_msgs[4]; | ||
| 577 | extern const char *ext_msgs[32]; | ||
| 578 | extern const char *htlink_msgs[8]; | ||
| 579 | |||
| 580 | #ifdef CONFIG_EDAC_DEBUG | ||
| 581 | #define NUM_DBG_ATTRS 9 | ||
| 582 | #else | ||
| 583 | #define NUM_DBG_ATTRS 0 | ||
| 584 | #endif | ||
| 585 | |||
| 586 | #ifdef CONFIG_EDAC_AMD64_ERROR_INJECTION | ||
| 587 | #define NUM_INJ_ATTRS 5 | ||
| 588 | #else | ||
| 589 | #define NUM_INJ_ATTRS 0 | ||
| 590 | #endif | ||
| 591 | |||
| 592 | extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS], | ||
| 593 | amd64_inj_attrs[NUM_INJ_ATTRS]; | ||
| 594 | |||
| 595 | /* | ||
| 596 | * Each of the PCI Device IDs types have their own set of hardware accessor | ||
| 597 | * functions and per device encoding/decoding logic. | ||
| 598 | */ | ||
| 599 | struct low_ops { | ||
| 600 | int (*probe_valid_hardware)(struct amd64_pvt *pvt); | ||
| 601 | int (*early_channel_count)(struct amd64_pvt *pvt); | ||
| 602 | |||
| 603 | u64 (*get_error_address)(struct mem_ctl_info *mci, | ||
| 604 | struct amd64_error_info_regs *info); | ||
| 605 | void (*read_dram_base_limit)(struct amd64_pvt *pvt, int dram); | ||
| 606 | void (*read_dram_ctl_register)(struct amd64_pvt *pvt); | ||
| 607 | void (*map_sysaddr_to_csrow)(struct mem_ctl_info *mci, | ||
| 608 | struct amd64_error_info_regs *info, | ||
| 609 | u64 SystemAddr); | ||
| 610 | int (*dbam_map_to_pages)(struct amd64_pvt *pvt, int dram_map); | ||
| 611 | }; | ||
| 612 | |||
| 613 | struct amd64_family_type { | ||
| 614 | const char *ctl_name; | ||
| 615 | u16 addr_f1_ctl; | ||
| 616 | u16 misc_f3_ctl; | ||
| 617 | struct low_ops ops; | ||
| 618 | }; | ||
| 619 | |||
| 620 | static struct amd64_family_type amd64_family_types[]; | ||
| 621 | |||
| 622 | static inline const char *get_amd_family_name(int index) | ||
| 623 | { | ||
| 624 | return amd64_family_types[index].ctl_name; | ||
| 625 | } | ||
| 626 | |||
| 627 | static inline struct low_ops *family_ops(int index) | ||
| 628 | { | ||
| 629 | return &amd64_family_types[index].ops; | ||
| 630 | } | ||
| 631 | |||
| 632 | /* | ||
| 633 | * For future CPU versions, verify the following as new 'slow' rates appear and | ||
| 634 | * modify the necessary skip values for the supported CPU. | ||
| 635 | */ | ||
| 636 | #define K8_MIN_SCRUB_RATE_BITS 0x0 | ||
| 637 | #define F10_MIN_SCRUB_RATE_BITS 0x5 | ||
| 638 | #define F11_MIN_SCRUB_RATE_BITS 0x6 | ||
| 639 | |||
| 640 | int amd64_process_error_info(struct mem_ctl_info *mci, | ||
| 641 | struct amd64_error_info_regs *info, | ||
| 642 | int handle_errors); | ||
| 643 | int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, | ||
| 644 | u64 *hole_offset, u64 *hole_size); | ||
diff --git a/drivers/edac/amd64_edac_dbg.c b/drivers/edac/amd64_edac_dbg.c new file mode 100644 index 000000000000..0a41b248a4ad --- /dev/null +++ b/drivers/edac/amd64_edac_dbg.c | |||
| @@ -0,0 +1,255 @@ | |||
| 1 | #include "amd64_edac.h" | ||
| 2 | |||
| 3 | /* | ||
| 4 | * accept a hex value and store it into the virtual error register file, field: | ||
| 5 | * nbeal and nbeah. Assume virtual error values have already been set for: NBSL, | ||
| 6 | * NBSH and NBCFG. Then proceed to map the error values to a MC, CSROW and | ||
| 7 | * CHANNEL | ||
| 8 | */ | ||
| 9 | static ssize_t amd64_nbea_store(struct mem_ctl_info *mci, const char *data, | ||
| 10 | size_t count) | ||
| 11 | { | ||
| 12 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 13 | unsigned long long value; | ||
| 14 | int ret = 0; | ||
| 15 | |||
| 16 | ret = strict_strtoull(data, 16, &value); | ||
| 17 | if (ret != -EINVAL) { | ||
| 18 | debugf0("received NBEA= 0x%llx\n", value); | ||
| 19 | |||
| 20 | /* place the value into the virtual error packet */ | ||
| 21 | pvt->ctl_error_info.nbeal = (u32) value; | ||
| 22 | value >>= 32; | ||
| 23 | pvt->ctl_error_info.nbeah = (u32) value; | ||
| 24 | |||
| 25 | /* Process the Mapping request */ | ||
| 26 | /* TODO: Add race prevention */ | ||
| 27 | amd64_process_error_info(mci, &pvt->ctl_error_info, 1); | ||
| 28 | |||
| 29 | return count; | ||
| 30 | } | ||
| 31 | return ret; | ||
| 32 | } | ||
| 33 | |||
| 34 | /* display back what the last NBEA (MCA NB Address (MC4_ADDR)) was written */ | ||
| 35 | static ssize_t amd64_nbea_show(struct mem_ctl_info *mci, char *data) | ||
| 36 | { | ||
| 37 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 38 | u64 value; | ||
| 39 | |||
| 40 | value = pvt->ctl_error_info.nbeah; | ||
| 41 | value <<= 32; | ||
| 42 | value |= pvt->ctl_error_info.nbeal; | ||
| 43 | |||
| 44 | return sprintf(data, "%llx\n", value); | ||
| 45 | } | ||
| 46 | |||
| 47 | /* store the NBSL (MCA NB Status Low (MC4_STATUS)) value user desires */ | ||
| 48 | static ssize_t amd64_nbsl_store(struct mem_ctl_info *mci, const char *data, | ||
| 49 | size_t count) | ||
| 50 | { | ||
| 51 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 52 | unsigned long value; | ||
| 53 | int ret = 0; | ||
| 54 | |||
| 55 | ret = strict_strtoul(data, 16, &value); | ||
| 56 | if (ret != -EINVAL) { | ||
| 57 | debugf0("received NBSL= 0x%lx\n", value); | ||
| 58 | |||
| 59 | pvt->ctl_error_info.nbsl = (u32) value; | ||
| 60 | |||
| 61 | return count; | ||
| 62 | } | ||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | /* display back what the last NBSL value written */ | ||
| 67 | static ssize_t amd64_nbsl_show(struct mem_ctl_info *mci, char *data) | ||
| 68 | { | ||
| 69 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 70 | u32 value; | ||
| 71 | |||
| 72 | value = pvt->ctl_error_info.nbsl; | ||
| 73 | |||
| 74 | return sprintf(data, "%x\n", value); | ||
| 75 | } | ||
| 76 | |||
| 77 | /* store the NBSH (MCA NB Status High) value user desires */ | ||
| 78 | static ssize_t amd64_nbsh_store(struct mem_ctl_info *mci, const char *data, | ||
| 79 | size_t count) | ||
| 80 | { | ||
| 81 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 82 | unsigned long value; | ||
| 83 | int ret = 0; | ||
| 84 | |||
| 85 | ret = strict_strtoul(data, 16, &value); | ||
| 86 | if (ret != -EINVAL) { | ||
| 87 | debugf0("received NBSH= 0x%lx\n", value); | ||
| 88 | |||
| 89 | pvt->ctl_error_info.nbsh = (u32) value; | ||
| 90 | |||
| 91 | return count; | ||
| 92 | } | ||
| 93 | return ret; | ||
| 94 | } | ||
| 95 | |||
| 96 | /* display back what the last NBSH value written */ | ||
| 97 | static ssize_t amd64_nbsh_show(struct mem_ctl_info *mci, char *data) | ||
| 98 | { | ||
| 99 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 100 | u32 value; | ||
| 101 | |||
| 102 | value = pvt->ctl_error_info.nbsh; | ||
| 103 | |||
| 104 | return sprintf(data, "%x\n", value); | ||
| 105 | } | ||
| 106 | |||
| 107 | /* accept and store the NBCFG (MCA NB Configuration) value user desires */ | ||
| 108 | static ssize_t amd64_nbcfg_store(struct mem_ctl_info *mci, | ||
| 109 | const char *data, size_t count) | ||
| 110 | { | ||
| 111 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 112 | unsigned long value; | ||
| 113 | int ret = 0; | ||
| 114 | |||
| 115 | ret = strict_strtoul(data, 16, &value); | ||
| 116 | if (ret != -EINVAL) { | ||
| 117 | debugf0("received NBCFG= 0x%lx\n", value); | ||
| 118 | |||
| 119 | pvt->ctl_error_info.nbcfg = (u32) value; | ||
| 120 | |||
| 121 | return count; | ||
| 122 | } | ||
| 123 | return ret; | ||
| 124 | } | ||
| 125 | |||
| 126 | /* various show routines for the controls of a MCI */ | ||
| 127 | static ssize_t amd64_nbcfg_show(struct mem_ctl_info *mci, char *data) | ||
| 128 | { | ||
| 129 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 130 | |||
| 131 | return sprintf(data, "%x\n", pvt->ctl_error_info.nbcfg); | ||
| 132 | } | ||
| 133 | |||
| 134 | |||
| 135 | static ssize_t amd64_dhar_show(struct mem_ctl_info *mci, char *data) | ||
| 136 | { | ||
| 137 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 138 | |||
| 139 | return sprintf(data, "%x\n", pvt->dhar); | ||
| 140 | } | ||
| 141 | |||
| 142 | |||
| 143 | static ssize_t amd64_dbam_show(struct mem_ctl_info *mci, char *data) | ||
| 144 | { | ||
| 145 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 146 | |||
| 147 | return sprintf(data, "%x\n", pvt->dbam0); | ||
| 148 | } | ||
| 149 | |||
| 150 | |||
| 151 | static ssize_t amd64_topmem_show(struct mem_ctl_info *mci, char *data) | ||
| 152 | { | ||
| 153 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 154 | |||
| 155 | return sprintf(data, "%llx\n", pvt->top_mem); | ||
| 156 | } | ||
| 157 | |||
| 158 | |||
| 159 | static ssize_t amd64_topmem2_show(struct mem_ctl_info *mci, char *data) | ||
| 160 | { | ||
| 161 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 162 | |||
| 163 | return sprintf(data, "%llx\n", pvt->top_mem2); | ||
| 164 | } | ||
| 165 | |||
| 166 | static ssize_t amd64_hole_show(struct mem_ctl_info *mci, char *data) | ||
| 167 | { | ||
| 168 | u64 hole_base = 0; | ||
| 169 | u64 hole_offset = 0; | ||
| 170 | u64 hole_size = 0; | ||
| 171 | |||
| 172 | amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, &hole_size); | ||
| 173 | |||
| 174 | return sprintf(data, "%llx %llx %llx\n", hole_base, hole_offset, | ||
| 175 | hole_size); | ||
| 176 | } | ||
| 177 | |||
| 178 | /* | ||
| 179 | * update NUM_DBG_ATTRS in case you add new members | ||
| 180 | */ | ||
| 181 | struct mcidev_sysfs_attribute amd64_dbg_attrs[] = { | ||
| 182 | |||
| 183 | { | ||
| 184 | .attr = { | ||
| 185 | .name = "nbea_ctl", | ||
| 186 | .mode = (S_IRUGO | S_IWUSR) | ||
| 187 | }, | ||
| 188 | .show = amd64_nbea_show, | ||
| 189 | .store = amd64_nbea_store, | ||
| 190 | }, | ||
| 191 | { | ||
| 192 | .attr = { | ||
| 193 | .name = "nbsl_ctl", | ||
| 194 | .mode = (S_IRUGO | S_IWUSR) | ||
| 195 | }, | ||
| 196 | .show = amd64_nbsl_show, | ||
| 197 | .store = amd64_nbsl_store, | ||
| 198 | }, | ||
| 199 | { | ||
| 200 | .attr = { | ||
| 201 | .name = "nbsh_ctl", | ||
| 202 | .mode = (S_IRUGO | S_IWUSR) | ||
| 203 | }, | ||
| 204 | .show = amd64_nbsh_show, | ||
| 205 | .store = amd64_nbsh_store, | ||
| 206 | }, | ||
| 207 | { | ||
| 208 | .attr = { | ||
| 209 | .name = "nbcfg_ctl", | ||
| 210 | .mode = (S_IRUGO | S_IWUSR) | ||
| 211 | }, | ||
| 212 | .show = amd64_nbcfg_show, | ||
| 213 | .store = amd64_nbcfg_store, | ||
| 214 | }, | ||
| 215 | { | ||
| 216 | .attr = { | ||
| 217 | .name = "dhar", | ||
| 218 | .mode = (S_IRUGO) | ||
| 219 | }, | ||
| 220 | .show = amd64_dhar_show, | ||
| 221 | .store = NULL, | ||
| 222 | }, | ||
| 223 | { | ||
| 224 | .attr = { | ||
| 225 | .name = "dbam", | ||
| 226 | .mode = (S_IRUGO) | ||
| 227 | }, | ||
| 228 | .show = amd64_dbam_show, | ||
| 229 | .store = NULL, | ||
| 230 | }, | ||
| 231 | { | ||
| 232 | .attr = { | ||
| 233 | .name = "topmem", | ||
| 234 | .mode = (S_IRUGO) | ||
| 235 | }, | ||
| 236 | .show = amd64_topmem_show, | ||
| 237 | .store = NULL, | ||
| 238 | }, | ||
| 239 | { | ||
| 240 | .attr = { | ||
| 241 | .name = "topmem2", | ||
| 242 | .mode = (S_IRUGO) | ||
| 243 | }, | ||
| 244 | .show = amd64_topmem2_show, | ||
| 245 | .store = NULL, | ||
| 246 | }, | ||
| 247 | { | ||
| 248 | .attr = { | ||
| 249 | .name = "dram_hole", | ||
| 250 | .mode = (S_IRUGO) | ||
| 251 | }, | ||
| 252 | .show = amd64_hole_show, | ||
| 253 | .store = NULL, | ||
| 254 | }, | ||
| 255 | }; | ||
diff --git a/drivers/edac/amd64_edac_err_types.c b/drivers/edac/amd64_edac_err_types.c new file mode 100644 index 000000000000..f212ff12a9d8 --- /dev/null +++ b/drivers/edac/amd64_edac_err_types.c | |||
| @@ -0,0 +1,161 @@ | |||
| 1 | #include "amd64_edac.h" | ||
| 2 | |||
| 3 | /* | ||
| 4 | * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only | ||
| 5 | * for DDR2 DRAM mapping. | ||
| 6 | */ | ||
| 7 | u32 revf_quad_ddr2_shift[] = { | ||
| 8 | 0, /* 0000b NULL DIMM (128mb) */ | ||
| 9 | 28, /* 0001b 256mb */ | ||
| 10 | 29, /* 0010b 512mb */ | ||
| 11 | 29, /* 0011b 512mb */ | ||
| 12 | 29, /* 0100b 512mb */ | ||
| 13 | 30, /* 0101b 1gb */ | ||
| 14 | 30, /* 0110b 1gb */ | ||
| 15 | 31, /* 0111b 2gb */ | ||
| 16 | 31, /* 1000b 2gb */ | ||
| 17 | 32, /* 1001b 4gb */ | ||
| 18 | 32, /* 1010b 4gb */ | ||
| 19 | 33, /* 1011b 8gb */ | ||
| 20 | 0, /* 1100b future */ | ||
| 21 | 0, /* 1101b future */ | ||
| 22 | 0, /* 1110b future */ | ||
| 23 | 0 /* 1111b future */ | ||
| 24 | }; | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Valid scrub rates for the K8 hardware memory scrubber. We map the scrubbing | ||
| 28 | * bandwidth to a valid bit pattern. The 'set' operation finds the 'matching- | ||
| 29 | * or higher value'. | ||
| 30 | * | ||
| 31 | *FIXME: Produce a better mapping/linearisation. | ||
| 32 | */ | ||
| 33 | |||
| 34 | struct scrubrate scrubrates[] = { | ||
| 35 | { 0x01, 1600000000UL}, | ||
| 36 | { 0x02, 800000000UL}, | ||
| 37 | { 0x03, 400000000UL}, | ||
| 38 | { 0x04, 200000000UL}, | ||
| 39 | { 0x05, 100000000UL}, | ||
| 40 | { 0x06, 50000000UL}, | ||
| 41 | { 0x07, 25000000UL}, | ||
| 42 | { 0x08, 12284069UL}, | ||
| 43 | { 0x09, 6274509UL}, | ||
| 44 | { 0x0A, 3121951UL}, | ||
| 45 | { 0x0B, 1560975UL}, | ||
| 46 | { 0x0C, 781440UL}, | ||
| 47 | { 0x0D, 390720UL}, | ||
| 48 | { 0x0E, 195300UL}, | ||
| 49 | { 0x0F, 97650UL}, | ||
| 50 | { 0x10, 48854UL}, | ||
| 51 | { 0x11, 24427UL}, | ||
| 52 | { 0x12, 12213UL}, | ||
| 53 | { 0x13, 6101UL}, | ||
| 54 | { 0x14, 3051UL}, | ||
| 55 | { 0x15, 1523UL}, | ||
| 56 | { 0x16, 761UL}, | ||
| 57 | { 0x00, 0UL}, /* scrubbing off */ | ||
| 58 | }; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * string representation for the different MCA reported error types, see F3x48 | ||
| 62 | * or MSR0000_0411. | ||
| 63 | */ | ||
| 64 | const char *tt_msgs[] = { /* transaction type */ | ||
| 65 | "instruction", | ||
| 66 | "data", | ||
| 67 | "generic", | ||
| 68 | "reserved" | ||
| 69 | }; | ||
| 70 | |||
| 71 | const char *ll_msgs[] = { /* cache level */ | ||
| 72 | "L0", | ||
| 73 | "L1", | ||
| 74 | "L2", | ||
| 75 | "L3/generic" | ||
| 76 | }; | ||
| 77 | |||
| 78 | const char *rrrr_msgs[] = { | ||
| 79 | "generic", | ||
| 80 | "generic read", | ||
| 81 | "generic write", | ||
| 82 | "data read", | ||
| 83 | "data write", | ||
| 84 | "inst fetch", | ||
| 85 | "prefetch", | ||
| 86 | "evict", | ||
| 87 | "snoop", | ||
| 88 | "reserved RRRR= 9", | ||
| 89 | "reserved RRRR= 10", | ||
| 90 | "reserved RRRR= 11", | ||
| 91 | "reserved RRRR= 12", | ||
| 92 | "reserved RRRR= 13", | ||
| 93 | "reserved RRRR= 14", | ||
| 94 | "reserved RRRR= 15" | ||
| 95 | }; | ||
| 96 | |||
| 97 | const char *pp_msgs[] = { /* participating processor */ | ||
| 98 | "local node originated (SRC)", | ||
| 99 | "local node responded to request (RES)", | ||
| 100 | "local node observed as 3rd party (OBS)", | ||
| 101 | "generic" | ||
| 102 | }; | ||
| 103 | |||
| 104 | const char *to_msgs[] = { | ||
| 105 | "no timeout", | ||
| 106 | "timed out" | ||
| 107 | }; | ||
| 108 | |||
| 109 | const char *ii_msgs[] = { /* memory or i/o */ | ||
| 110 | "mem access", | ||
| 111 | "reserved", | ||
| 112 | "i/o access", | ||
| 113 | "generic" | ||
| 114 | }; | ||
| 115 | |||
| 116 | /* Map the 5 bits of Extended Error code to the string table. */ | ||
| 117 | const char *ext_msgs[] = { /* extended error */ | ||
| 118 | "K8 ECC error/F10 reserved", /* 0_0000b */ | ||
| 119 | "CRC error", /* 0_0001b */ | ||
| 120 | "sync error", /* 0_0010b */ | ||
| 121 | "mst abort", /* 0_0011b */ | ||
| 122 | "tgt abort", /* 0_0100b */ | ||
| 123 | "GART error", /* 0_0101b */ | ||
| 124 | "RMW error", /* 0_0110b */ | ||
| 125 | "Wdog timer error", /* 0_0111b */ | ||
| 126 | "F10-ECC/K8-Chipkill error", /* 0_1000b */ | ||
| 127 | "DEV Error", /* 0_1001b */ | ||
| 128 | "Link Data error", /* 0_1010b */ | ||
| 129 | "Link or L3 Protocol error", /* 0_1011b */ | ||
| 130 | "NB Array error", /* 0_1100b */ | ||
| 131 | "DRAM Parity error", /* 0_1101b */ | ||
| 132 | "Link Retry/GART Table Walk/DEV Table Walk error", /* 0_1110b */ | ||
| 133 | "Res 0x0ff error", /* 0_1111b */ | ||
| 134 | "Res 0x100 error", /* 1_0000b */ | ||
| 135 | "Res 0x101 error", /* 1_0001b */ | ||
| 136 | "Res 0x102 error", /* 1_0010b */ | ||
| 137 | "Res 0x103 error", /* 1_0011b */ | ||
| 138 | "Res 0x104 error", /* 1_0100b */ | ||
| 139 | "Res 0x105 error", /* 1_0101b */ | ||
| 140 | "Res 0x106 error", /* 1_0110b */ | ||
| 141 | "Res 0x107 error", /* 1_0111b */ | ||
| 142 | "Res 0x108 error", /* 1_1000b */ | ||
| 143 | "Res 0x109 error", /* 1_1001b */ | ||
| 144 | "Res 0x10A error", /* 1_1010b */ | ||
| 145 | "Res 0x10B error", /* 1_1011b */ | ||
| 146 | "L3 Cache Data error", /* 1_1100b */ | ||
| 147 | "L3 CacheTag error", /* 1_1101b */ | ||
| 148 | "L3 Cache LRU error", /* 1_1110b */ | ||
| 149 | "Res 0x1FF error" /* 1_1111b */ | ||
| 150 | }; | ||
| 151 | |||
| 152 | const char *htlink_msgs[] = { | ||
| 153 | "none", | ||
| 154 | "1", | ||
| 155 | "2", | ||
| 156 | "1 2", | ||
| 157 | "3", | ||
| 158 | "1 3", | ||
| 159 | "2 3", | ||
| 160 | "1 2 3" | ||
| 161 | }; | ||
diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c new file mode 100644 index 000000000000..d3675b76b3a7 --- /dev/null +++ b/drivers/edac/amd64_edac_inj.c | |||
| @@ -0,0 +1,185 @@ | |||
| 1 | #include "amd64_edac.h" | ||
| 2 | |||
| 3 | /* | ||
| 4 | * store error injection section value which refers to one of 4 16-byte sections | ||
| 5 | * within a 64-byte cacheline | ||
| 6 | * | ||
| 7 | * range: 0..3 | ||
| 8 | */ | ||
| 9 | static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, | ||
| 10 | const char *data, size_t count) | ||
| 11 | { | ||
| 12 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 13 | unsigned long value; | ||
| 14 | int ret = 0; | ||
| 15 | |||
| 16 | ret = strict_strtoul(data, 10, &value); | ||
| 17 | if (ret != -EINVAL) { | ||
| 18 | pvt->injection.section = (u32) value; | ||
| 19 | return count; | ||
| 20 | } | ||
| 21 | return ret; | ||
| 22 | } | ||
| 23 | |||
| 24 | /* | ||
| 25 | * store error injection word value which refers to one of 9 16-bit word of the | ||
| 26 | * 16-byte (128-bit + ECC bits) section | ||
| 27 | * | ||
| 28 | * range: 0..8 | ||
| 29 | */ | ||
| 30 | static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, | ||
| 31 | const char *data, size_t count) | ||
| 32 | { | ||
| 33 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 34 | unsigned long value; | ||
| 35 | int ret = 0; | ||
| 36 | |||
| 37 | ret = strict_strtoul(data, 10, &value); | ||
| 38 | if (ret != -EINVAL) { | ||
| 39 | |||
| 40 | value = (value <= 8) ? value : 0; | ||
| 41 | pvt->injection.word = (u32) value; | ||
| 42 | |||
| 43 | return count; | ||
| 44 | } | ||
| 45 | return ret; | ||
| 46 | } | ||
| 47 | |||
| 48 | /* | ||
| 49 | * store 16 bit error injection vector which enables injecting errors to the | ||
| 50 | * corresponding bit within the error injection word above. When used during a | ||
| 51 | * DRAM ECC read, it holds the contents of the of the DRAM ECC bits. | ||
| 52 | */ | ||
| 53 | static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, | ||
| 54 | const char *data, size_t count) | ||
| 55 | { | ||
| 56 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 57 | unsigned long value; | ||
| 58 | int ret = 0; | ||
| 59 | |||
| 60 | ret = strict_strtoul(data, 16, &value); | ||
| 61 | if (ret != -EINVAL) { | ||
| 62 | |||
| 63 | pvt->injection.bit_map = (u32) value & 0xFFFF; | ||
| 64 | |||
| 65 | return count; | ||
| 66 | } | ||
| 67 | return ret; | ||
| 68 | } | ||
| 69 | |||
| 70 | /* | ||
| 71 | * Do a DRAM ECC read. Assemble staged values in the pvt area, format into | ||
| 72 | * fields needed by the injection registers and read the NB Array Data Port. | ||
| 73 | */ | ||
| 74 | static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, | ||
| 75 | const char *data, size_t count) | ||
| 76 | { | ||
| 77 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 78 | unsigned long value; | ||
| 79 | u32 section, word_bits; | ||
| 80 | int ret = 0; | ||
| 81 | |||
| 82 | ret = strict_strtoul(data, 10, &value); | ||
| 83 | if (ret != -EINVAL) { | ||
| 84 | |||
| 85 | /* Form value to choose 16-byte section of cacheline */ | ||
| 86 | section = F10_NB_ARRAY_DRAM_ECC | | ||
| 87 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); | ||
| 88 | pci_write_config_dword(pvt->misc_f3_ctl, | ||
| 89 | F10_NB_ARRAY_ADDR, section); | ||
| 90 | |||
| 91 | word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word, | ||
| 92 | pvt->injection.bit_map); | ||
| 93 | |||
| 94 | /* Issue 'word' and 'bit' along with the READ request */ | ||
| 95 | pci_write_config_dword(pvt->misc_f3_ctl, | ||
| 96 | F10_NB_ARRAY_DATA, word_bits); | ||
| 97 | |||
| 98 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); | ||
| 99 | |||
| 100 | return count; | ||
| 101 | } | ||
| 102 | return ret; | ||
| 103 | } | ||
| 104 | |||
| 105 | /* | ||
| 106 | * Do a DRAM ECC write. Assemble staged values in the pvt area and format into | ||
| 107 | * fields needed by the injection registers. | ||
| 108 | */ | ||
| 109 | static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, | ||
| 110 | const char *data, size_t count) | ||
| 111 | { | ||
| 112 | struct amd64_pvt *pvt = mci->pvt_info; | ||
| 113 | unsigned long value; | ||
| 114 | u32 section, word_bits; | ||
| 115 | int ret = 0; | ||
| 116 | |||
| 117 | ret = strict_strtoul(data, 10, &value); | ||
| 118 | if (ret != -EINVAL) { | ||
| 119 | |||
| 120 | /* Form value to choose 16-byte section of cacheline */ | ||
| 121 | section = F10_NB_ARRAY_DRAM_ECC | | ||
| 122 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); | ||
| 123 | pci_write_config_dword(pvt->misc_f3_ctl, | ||
| 124 | F10_NB_ARRAY_ADDR, section); | ||
| 125 | |||
| 126 | word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word, | ||
| 127 | pvt->injection.bit_map); | ||
| 128 | |||
| 129 | /* Issue 'word' and 'bit' along with the READ request */ | ||
| 130 | pci_write_config_dword(pvt->misc_f3_ctl, | ||
| 131 | F10_NB_ARRAY_DATA, word_bits); | ||
| 132 | |||
| 133 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); | ||
| 134 | |||
| 135 | return count; | ||
| 136 | } | ||
| 137 | return ret; | ||
| 138 | } | ||
| 139 | |||
| 140 | /* | ||
| 141 | * update NUM_INJ_ATTRS in case you add new members | ||
| 142 | */ | ||
| 143 | struct mcidev_sysfs_attribute amd64_inj_attrs[] = { | ||
| 144 | |||
| 145 | { | ||
| 146 | .attr = { | ||
| 147 | .name = "inject_section", | ||
| 148 | .mode = (S_IRUGO | S_IWUSR) | ||
| 149 | }, | ||
| 150 | .show = NULL, | ||
| 151 | .store = amd64_inject_section_store, | ||
| 152 | }, | ||
| 153 | { | ||
| 154 | .attr = { | ||
| 155 | .name = "inject_word", | ||
| 156 | .mode = (S_IRUGO | S_IWUSR) | ||
| 157 | }, | ||
| 158 | .show = NULL, | ||
| 159 | .store = amd64_inject_word_store, | ||
| 160 | }, | ||
| 161 | { | ||
| 162 | .attr = { | ||
| 163 | .name = "inject_ecc_vector", | ||
| 164 | .mode = (S_IRUGO | S_IWUSR) | ||
| 165 | }, | ||
| 166 | .show = NULL, | ||
| 167 | .store = amd64_inject_ecc_vector_store, | ||
| 168 | }, | ||
| 169 | { | ||
| 170 | .attr = { | ||
| 171 | .name = "inject_write", | ||
| 172 | .mode = (S_IRUGO | S_IWUSR) | ||
| 173 | }, | ||
| 174 | .show = NULL, | ||
| 175 | .store = amd64_inject_write_store, | ||
| 176 | }, | ||
| 177 | { | ||
| 178 | .attr = { | ||
| 179 | .name = "inject_read", | ||
| 180 | .mode = (S_IRUGO | S_IWUSR) | ||
| 181 | }, | ||
| 182 | .show = NULL, | ||
| 183 | .store = amd64_inject_read_store, | ||
| 184 | }, | ||
| 185 | }; | ||
diff --git a/drivers/edac/amd8111_edac.c b/drivers/edac/amd8111_edac.c index 614692181120..2cb58ef743e0 100644 --- a/drivers/edac/amd8111_edac.c +++ b/drivers/edac/amd8111_edac.c | |||
| @@ -389,7 +389,7 @@ static int amd8111_dev_probe(struct pci_dev *dev, | |||
| 389 | dev_info->edac_dev->dev = &dev_info->dev->dev; | 389 | dev_info->edac_dev->dev = &dev_info->dev->dev; |
| 390 | dev_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR; | 390 | dev_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR; |
| 391 | dev_info->edac_dev->ctl_name = dev_info->ctl_name; | 391 | dev_info->edac_dev->ctl_name = dev_info->ctl_name; |
| 392 | dev_info->edac_dev->dev_name = dev_info->dev->dev.bus_id; | 392 | dev_info->edac_dev->dev_name = dev_name(&dev_info->dev->dev); |
| 393 | 393 | ||
| 394 | if (edac_op_state == EDAC_OPSTATE_POLL) | 394 | if (edac_op_state == EDAC_OPSTATE_POLL) |
| 395 | dev_info->edac_dev->edac_check = dev_info->check; | 395 | dev_info->edac_dev->edac_check = dev_info->check; |
| @@ -473,7 +473,7 @@ static int amd8111_pci_probe(struct pci_dev *dev, | |||
| 473 | pci_info->edac_dev->dev = &pci_info->dev->dev; | 473 | pci_info->edac_dev->dev = &pci_info->dev->dev; |
| 474 | pci_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR; | 474 | pci_info->edac_dev->mod_name = AMD8111_EDAC_MOD_STR; |
| 475 | pci_info->edac_dev->ctl_name = pci_info->ctl_name; | 475 | pci_info->edac_dev->ctl_name = pci_info->ctl_name; |
| 476 | pci_info->edac_dev->dev_name = pci_info->dev->dev.bus_id; | 476 | pci_info->edac_dev->dev_name = dev_name(&pci_info->dev->dev); |
| 477 | 477 | ||
| 478 | if (edac_op_state == EDAC_OPSTATE_POLL) | 478 | if (edac_op_state == EDAC_OPSTATE_POLL) |
| 479 | pci_info->edac_dev->edac_check = pci_info->check; | 479 | pci_info->edac_dev->edac_check = pci_info->check; |
diff --git a/drivers/edac/amd8131_edac.c b/drivers/edac/amd8131_edac.c index c083b31cac5a..b432d60c622a 100644 --- a/drivers/edac/amd8131_edac.c +++ b/drivers/edac/amd8131_edac.c | |||
| @@ -287,7 +287,7 @@ static int amd8131_probe(struct pci_dev *dev, const struct pci_device_id *id) | |||
| 287 | dev_info->edac_dev->dev = &dev_info->dev->dev; | 287 | dev_info->edac_dev->dev = &dev_info->dev->dev; |
| 288 | dev_info->edac_dev->mod_name = AMD8131_EDAC_MOD_STR; | 288 | dev_info->edac_dev->mod_name = AMD8131_EDAC_MOD_STR; |
| 289 | dev_info->edac_dev->ctl_name = dev_info->ctl_name; | 289 | dev_info->edac_dev->ctl_name = dev_info->ctl_name; |
| 290 | dev_info->edac_dev->dev_name = dev_info->dev->dev.bus_id; | 290 | dev_info->edac_dev->dev_name = dev_name(&dev_info->dev->dev); |
| 291 | 291 | ||
| 292 | if (edac_op_state == EDAC_OPSTATE_POLL) | 292 | if (edac_op_state == EDAC_OPSTATE_POLL) |
| 293 | dev_info->edac_dev->edac_check = amd8131_chipset.check; | 293 | dev_info->edac_dev->edac_check = amd8131_chipset.check; |
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 6ad95c8d6363..48d3b1409834 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
| @@ -76,10 +76,11 @@ | |||
| 76 | extern int edac_debug_level; | 76 | extern int edac_debug_level; |
| 77 | 77 | ||
| 78 | #ifndef CONFIG_EDAC_DEBUG_VERBOSE | 78 | #ifndef CONFIG_EDAC_DEBUG_VERBOSE |
| 79 | #define edac_debug_printk(level, fmt, arg...) \ | 79 | #define edac_debug_printk(level, fmt, arg...) \ |
| 80 | do { \ | 80 | do { \ |
| 81 | if (level <= edac_debug_level) \ | 81 | if (level <= edac_debug_level) \ |
| 82 | edac_printk(KERN_DEBUG, EDAC_DEBUG, fmt, ##arg); \ | 82 | edac_printk(KERN_DEBUG, EDAC_DEBUG, \ |
| 83 | "%s: " fmt, __func__, ##arg); \ | ||
| 83 | } while (0) | 84 | } while (0) |
| 84 | #else /* CONFIG_EDAC_DEBUG_VERBOSE */ | 85 | #else /* CONFIG_EDAC_DEBUG_VERBOSE */ |
| 85 | #define edac_debug_printk(level, fmt, arg...) \ | 86 | #define edac_debug_printk(level, fmt, arg...) \ |
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index 5f1b5400d96a..24c84ae81527 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c | |||
| @@ -596,6 +596,7 @@ int dmi_get_year(int field) | |||
| 596 | 596 | ||
| 597 | return year; | 597 | return year; |
| 598 | } | 598 | } |
| 599 | EXPORT_SYMBOL(dmi_get_year); | ||
| 599 | 600 | ||
| 600 | /** | 601 | /** |
| 601 | * dmi_walk - Walk the DMI table and get called back for every record | 602 | * dmi_walk - Walk the DMI table and get called back for every record |
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index 4cd35d8fd799..f5d46e7199d4 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig | |||
| @@ -67,12 +67,18 @@ config DRM_I830 | |||
| 67 | will load the correct one. | 67 | will load the correct one. |
| 68 | 68 | ||
| 69 | config DRM_I915 | 69 | config DRM_I915 |
| 70 | tristate "i915 driver" | ||
| 70 | select FB_CFB_FILLRECT | 71 | select FB_CFB_FILLRECT |
| 71 | select FB_CFB_COPYAREA | 72 | select FB_CFB_COPYAREA |
| 72 | select FB_CFB_IMAGEBLIT | 73 | select FB_CFB_IMAGEBLIT |
| 73 | select FB | 74 | select FB |
| 74 | select FRAMEBUFFER_CONSOLE if !EMBEDDED | 75 | select FRAMEBUFFER_CONSOLE if !EMBEDDED |
| 75 | tristate "i915 driver" | 76 | # i915 depends on ACPI_VIDEO when ACPI is enabled |
| 77 | # but for select to work, need to select ACPI_VIDEO's dependencies, ick | ||
| 78 | select VIDEO_OUTPUT_CONTROL if ACPI | ||
| 79 | select BACKLIGHT_CLASS_DEVICE if ACPI | ||
| 80 | select INPUT if ACPI | ||
| 81 | select ACPI_VIDEO if ACPI | ||
| 76 | help | 82 | help |
| 77 | Choose this option if you have a system that has Intel 830M, 845G, | 83 | Choose this option if you have a system that has Intel 830M, 845G, |
| 78 | 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the | 84 | 852GM, 855GM 865G or 915G integrated graphics. If M is selected, the |
| @@ -84,12 +90,6 @@ config DRM_I915 | |||
| 84 | config DRM_I915_KMS | 90 | config DRM_I915_KMS |
| 85 | bool "Enable modesetting on intel by default" | 91 | bool "Enable modesetting on intel by default" |
| 86 | depends on DRM_I915 | 92 | depends on DRM_I915 |
| 87 | # i915 KMS depends on ACPI_VIDEO when ACPI is enabled | ||
| 88 | # but for select to work, need to select ACPI_VIDEO's dependencies, ick | ||
| 89 | select VIDEO_OUTPUT_CONTROL if ACPI | ||
| 90 | select BACKLIGHT_CLASS_DEVICE if ACPI | ||
| 91 | select INPUT if ACPI | ||
| 92 | select ACPI_VIDEO if ACPI | ||
| 93 | help | 93 | help |
| 94 | Choose this option if you want kernel modesetting enabled by default, | 94 | Choose this option if you want kernel modesetting enabled by default, |
| 95 | and you have a new enough userspace to support this. Running old | 95 | and you have a new enough userspace to support this. Running old |
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 94a768871734..8fab7890a363 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
| @@ -2294,7 +2294,12 @@ int drm_mode_connector_property_set_ioctl(struct drm_device *dev, | |||
| 2294 | } | 2294 | } |
| 2295 | } | 2295 | } |
| 2296 | 2296 | ||
| 2297 | if (connector->funcs->set_property) | 2297 | /* Do DPMS ourselves */ |
| 2298 | if (property == connector->dev->mode_config.dpms_property) { | ||
| 2299 | if (connector->funcs->dpms) | ||
| 2300 | (*connector->funcs->dpms)(connector, (int) out_resp->value); | ||
| 2301 | ret = 0; | ||
| 2302 | } else if (connector->funcs->set_property) | ||
| 2298 | ret = connector->funcs->set_property(connector, property, out_resp->value); | 2303 | ret = connector->funcs->set_property(connector, property, out_resp->value); |
| 2299 | 2304 | ||
| 2300 | /* store the property value if succesful */ | 2305 | /* store the property value if succesful */ |
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c index 45890447feec..a6f73f1e99d9 100644 --- a/drivers/gpu/drm/drm_crtc_helper.c +++ b/drivers/gpu/drm/drm_crtc_helper.c | |||
| @@ -199,6 +199,29 @@ static void drm_helper_add_std_modes(struct drm_device *dev, | |||
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | /** | 201 | /** |
| 202 | * drm_helper_encoder_in_use - check if a given encoder is in use | ||
| 203 | * @encoder: encoder to check | ||
| 204 | * | ||
| 205 | * LOCKING: | ||
| 206 | * Caller must hold mode config lock. | ||
| 207 | * | ||
| 208 | * Walk @encoders's DRM device's mode_config and see if it's in use. | ||
| 209 | * | ||
| 210 | * RETURNS: | ||
| 211 | * True if @encoder is part of the mode_config, false otherwise. | ||
| 212 | */ | ||
| 213 | bool drm_helper_encoder_in_use(struct drm_encoder *encoder) | ||
| 214 | { | ||
| 215 | struct drm_connector *connector; | ||
| 216 | struct drm_device *dev = encoder->dev; | ||
| 217 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
| 218 | if (connector->encoder == encoder) | ||
| 219 | return true; | ||
| 220 | return false; | ||
| 221 | } | ||
| 222 | EXPORT_SYMBOL(drm_helper_encoder_in_use); | ||
| 223 | |||
| 224 | /** | ||
| 202 | * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config | 225 | * drm_helper_crtc_in_use - check if a given CRTC is in a mode_config |
| 203 | * @crtc: CRTC to check | 226 | * @crtc: CRTC to check |
| 204 | * | 227 | * |
| @@ -216,7 +239,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc) | |||
| 216 | struct drm_device *dev = crtc->dev; | 239 | struct drm_device *dev = crtc->dev; |
| 217 | /* FIXME: Locking around list access? */ | 240 | /* FIXME: Locking around list access? */ |
| 218 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) | 241 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) |
| 219 | if (encoder->crtc == crtc) | 242 | if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder)) |
| 220 | return true; | 243 | return true; |
| 221 | return false; | 244 | return false; |
| 222 | } | 245 | } |
| @@ -240,7 +263,7 @@ void drm_helper_disable_unused_functions(struct drm_device *dev) | |||
| 240 | 263 | ||
| 241 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 264 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
| 242 | encoder_funcs = encoder->helper_private; | 265 | encoder_funcs = encoder->helper_private; |
| 243 | if (!encoder->crtc) | 266 | if (!drm_helper_encoder_in_use(encoder)) |
| 244 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); | 267 | (*encoder_funcs->dpms)(encoder, DRM_MODE_DPMS_OFF); |
| 245 | } | 268 | } |
| 246 | 269 | ||
| @@ -935,6 +958,88 @@ bool drm_helper_initial_config(struct drm_device *dev) | |||
| 935 | } | 958 | } |
| 936 | EXPORT_SYMBOL(drm_helper_initial_config); | 959 | EXPORT_SYMBOL(drm_helper_initial_config); |
| 937 | 960 | ||
| 961 | static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder) | ||
| 962 | { | ||
| 963 | int dpms = DRM_MODE_DPMS_OFF; | ||
| 964 | struct drm_connector *connector; | ||
| 965 | struct drm_device *dev = encoder->dev; | ||
| 966 | |||
| 967 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
| 968 | if (connector->encoder == encoder) | ||
| 969 | if (connector->dpms < dpms) | ||
| 970 | dpms = connector->dpms; | ||
| 971 | return dpms; | ||
| 972 | } | ||
| 973 | |||
| 974 | static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc) | ||
| 975 | { | ||
| 976 | int dpms = DRM_MODE_DPMS_OFF; | ||
| 977 | struct drm_connector *connector; | ||
| 978 | struct drm_device *dev = crtc->dev; | ||
| 979 | |||
| 980 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
| 981 | if (connector->encoder && connector->encoder->crtc == crtc) | ||
| 982 | if (connector->dpms < dpms) | ||
| 983 | dpms = connector->dpms; | ||
| 984 | return dpms; | ||
| 985 | } | ||
| 986 | |||
| 987 | /** | ||
| 988 | * drm_helper_connector_dpms | ||
| 989 | * @connector affected connector | ||
| 990 | * @mode DPMS mode | ||
| 991 | * | ||
| 992 | * Calls the low-level connector DPMS function, then | ||
| 993 | * calls appropriate encoder and crtc DPMS functions as well | ||
| 994 | */ | ||
| 995 | void drm_helper_connector_dpms(struct drm_connector *connector, int mode) | ||
| 996 | { | ||
| 997 | struct drm_encoder *encoder = connector->encoder; | ||
| 998 | struct drm_crtc *crtc = encoder ? encoder->crtc : NULL; | ||
| 999 | int old_dpms; | ||
| 1000 | |||
| 1001 | if (mode == connector->dpms) | ||
| 1002 | return; | ||
| 1003 | |||
| 1004 | old_dpms = connector->dpms; | ||
| 1005 | connector->dpms = mode; | ||
| 1006 | |||
| 1007 | /* from off to on, do crtc then encoder */ | ||
| 1008 | if (mode < old_dpms) { | ||
| 1009 | if (crtc) { | ||
| 1010 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
| 1011 | if (crtc_funcs->dpms) | ||
| 1012 | (*crtc_funcs->dpms) (crtc, | ||
| 1013 | drm_helper_choose_crtc_dpms(crtc)); | ||
| 1014 | } | ||
| 1015 | if (encoder) { | ||
| 1016 | struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | ||
| 1017 | if (encoder_funcs->dpms) | ||
| 1018 | (*encoder_funcs->dpms) (encoder, | ||
| 1019 | drm_helper_choose_encoder_dpms(encoder)); | ||
| 1020 | } | ||
| 1021 | } | ||
| 1022 | |||
| 1023 | /* from on to off, do encoder then crtc */ | ||
| 1024 | if (mode > old_dpms) { | ||
| 1025 | if (encoder) { | ||
| 1026 | struct drm_encoder_helper_funcs *encoder_funcs = encoder->helper_private; | ||
| 1027 | if (encoder_funcs->dpms) | ||
| 1028 | (*encoder_funcs->dpms) (encoder, | ||
| 1029 | drm_helper_choose_encoder_dpms(encoder)); | ||
| 1030 | } | ||
| 1031 | if (crtc) { | ||
| 1032 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
| 1033 | if (crtc_funcs->dpms) | ||
| 1034 | (*crtc_funcs->dpms) (crtc, | ||
| 1035 | drm_helper_choose_crtc_dpms(crtc)); | ||
| 1036 | } | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | return; | ||
| 1040 | } | ||
| 1041 | EXPORT_SYMBOL(drm_helper_connector_dpms); | ||
| 1042 | |||
| 938 | /** | 1043 | /** |
| 939 | * drm_hotplug_stage_two | 1044 | * drm_hotplug_stage_two |
| 940 | * @dev DRM device | 1045 | * @dev DRM device |
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index ca9c61656714..6f6b26479d82 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
| @@ -289,6 +289,11 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
| 289 | struct drm_display_mode *mode; | 289 | struct drm_display_mode *mode; |
| 290 | struct detailed_pixel_timing *pt = &timing->data.pixel_data; | 290 | struct detailed_pixel_timing *pt = &timing->data.pixel_data; |
| 291 | 291 | ||
| 292 | /* ignore tiny modes */ | ||
| 293 | if (((pt->hactive_hi << 8) | pt->hactive_lo) < 64 || | ||
| 294 | ((pt->vactive_hi << 8) | pt->hactive_lo) < 64) | ||
| 295 | return NULL; | ||
| 296 | |||
| 292 | if (pt->stereo) { | 297 | if (pt->stereo) { |
| 293 | printk(KERN_WARNING "stereo mode not supported\n"); | 298 | printk(KERN_WARNING "stereo mode not supported\n"); |
| 294 | return NULL; | 299 | return NULL; |
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 93e677a481f5..fc8e5acd9d9a 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
| @@ -196,6 +196,7 @@ int drm_irq_install(struct drm_device *dev) | |||
| 196 | { | 196 | { |
| 197 | int ret = 0; | 197 | int ret = 0; |
| 198 | unsigned long sh_flags = 0; | 198 | unsigned long sh_flags = 0; |
| 199 | char *irqname; | ||
| 199 | 200 | ||
| 200 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) | 201 | if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ)) |
| 201 | return -EINVAL; | 202 | return -EINVAL; |
| @@ -227,8 +228,13 @@ int drm_irq_install(struct drm_device *dev) | |||
| 227 | if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED)) | 228 | if (drm_core_check_feature(dev, DRIVER_IRQ_SHARED)) |
| 228 | sh_flags = IRQF_SHARED; | 229 | sh_flags = IRQF_SHARED; |
| 229 | 230 | ||
| 231 | if (dev->devname) | ||
| 232 | irqname = dev->devname; | ||
| 233 | else | ||
| 234 | irqname = dev->driver->name; | ||
| 235 | |||
| 230 | ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler, | 236 | ret = request_irq(drm_dev_to_irq(dev), dev->driver->irq_handler, |
| 231 | sh_flags, dev->devname, dev); | 237 | sh_flags, irqname, dev); |
| 232 | 238 | ||
| 233 | if (ret < 0) { | 239 | if (ret < 0) { |
| 234 | mutex_lock(&dev->struct_mutex); | 240 | mutex_lock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c index 8f9372921f82..9987ab880835 100644 --- a/drivers/gpu/drm/drm_sysfs.c +++ b/drivers/gpu/drm/drm_sysfs.c | |||
| @@ -147,7 +147,7 @@ static ssize_t status_show(struct device *device, | |||
| 147 | enum drm_connector_status status; | 147 | enum drm_connector_status status; |
| 148 | 148 | ||
| 149 | status = connector->funcs->detect(connector); | 149 | status = connector->funcs->detect(connector); |
| 150 | return snprintf(buf, PAGE_SIZE, "%s", | 150 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 151 | drm_get_connector_status_name(status)); | 151 | drm_get_connector_status_name(status)); |
| 152 | } | 152 | } |
| 153 | 153 | ||
| @@ -166,7 +166,7 @@ static ssize_t dpms_show(struct device *device, | |||
| 166 | if (ret) | 166 | if (ret) |
| 167 | return 0; | 167 | return 0; |
| 168 | 168 | ||
| 169 | return snprintf(buf, PAGE_SIZE, "%s", | 169 | return snprintf(buf, PAGE_SIZE, "%s\n", |
| 170 | drm_get_dpms_name((int)dpms_status)); | 170 | drm_get_dpms_name((int)dpms_status)); |
| 171 | } | 171 | } |
| 172 | 172 | ||
| @@ -176,7 +176,7 @@ static ssize_t enabled_show(struct device *device, | |||
| 176 | { | 176 | { |
| 177 | struct drm_connector *connector = to_drm_connector(device); | 177 | struct drm_connector *connector = to_drm_connector(device); |
| 178 | 178 | ||
| 179 | return snprintf(buf, PAGE_SIZE, connector->encoder ? "enabled" : | 179 | return snprintf(buf, PAGE_SIZE, "%s\n", connector->encoder ? "enabled" : |
| 180 | "disabled"); | 180 | "disabled"); |
| 181 | } | 181 | } |
| 182 | 182 | ||
| @@ -317,6 +317,7 @@ static struct device_attribute connector_attrs_opt1[] = { | |||
| 317 | 317 | ||
| 318 | static struct bin_attribute edid_attr = { | 318 | static struct bin_attribute edid_attr = { |
| 319 | .attr.name = "edid", | 319 | .attr.name = "edid", |
| 320 | .attr.mode = 0444, | ||
| 320 | .size = 128, | 321 | .size = 128, |
| 321 | .read = edid_show, | 322 | .read = edid_show, |
| 322 | }; | 323 | }; |
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 53d544552625..0ccb63ee50ee 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
| @@ -987,12 +987,6 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
| 987 | int fb_bar = IS_I9XX(dev) ? 2 : 0; | 987 | int fb_bar = IS_I9XX(dev) ? 2 : 0; |
| 988 | int ret = 0; | 988 | int ret = 0; |
| 989 | 989 | ||
| 990 | dev->devname = kstrdup(DRIVER_NAME, GFP_KERNEL); | ||
| 991 | if (!dev->devname) { | ||
| 992 | ret = -ENOMEM; | ||
| 993 | goto out; | ||
| 994 | } | ||
| 995 | |||
| 996 | dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) & | 990 | dev->mode_config.fb_base = drm_get_resource_start(dev, fb_bar) & |
| 997 | 0xff000000; | 991 | 0xff000000; |
| 998 | 992 | ||
| @@ -1006,7 +1000,7 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
| 1006 | 1000 | ||
| 1007 | ret = i915_probe_agp(dev, &agp_size, &prealloc_size); | 1001 | ret = i915_probe_agp(dev, &agp_size, &prealloc_size); |
| 1008 | if (ret) | 1002 | if (ret) |
| 1009 | goto kfree_devname; | 1003 | goto out; |
| 1010 | 1004 | ||
| 1011 | /* Basic memrange allocator for stolen space (aka vram) */ | 1005 | /* Basic memrange allocator for stolen space (aka vram) */ |
| 1012 | drm_mm_init(&dev_priv->vram, 0, prealloc_size); | 1006 | drm_mm_init(&dev_priv->vram, 0, prealloc_size); |
| @@ -1024,7 +1018,7 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
| 1024 | 1018 | ||
| 1025 | ret = i915_gem_init_ringbuffer(dev); | 1019 | ret = i915_gem_init_ringbuffer(dev); |
| 1026 | if (ret) | 1020 | if (ret) |
| 1027 | goto kfree_devname; | 1021 | goto out; |
| 1028 | 1022 | ||
| 1029 | /* Allow hardware batchbuffers unless told otherwise. | 1023 | /* Allow hardware batchbuffers unless told otherwise. |
| 1030 | */ | 1024 | */ |
| @@ -1056,8 +1050,6 @@ static int i915_load_modeset_init(struct drm_device *dev) | |||
| 1056 | 1050 | ||
| 1057 | destroy_ringbuffer: | 1051 | destroy_ringbuffer: |
| 1058 | i915_gem_cleanup_ringbuffer(dev); | 1052 | i915_gem_cleanup_ringbuffer(dev); |
| 1059 | kfree_devname: | ||
| 1060 | kfree(dev->devname); | ||
| 1061 | out: | 1053 | out: |
| 1062 | return ret; | 1054 | return ret; |
| 1063 | } | 1055 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index 717b6a854bcd..39f5c658ef5e 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
| @@ -1145,6 +1145,13 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | |||
| 1145 | mutex_unlock(&dev->struct_mutex); | 1145 | mutex_unlock(&dev->struct_mutex); |
| 1146 | return VM_FAULT_SIGBUS; | 1146 | return VM_FAULT_SIGBUS; |
| 1147 | } | 1147 | } |
| 1148 | |||
| 1149 | ret = i915_gem_object_set_to_gtt_domain(obj, write); | ||
| 1150 | if (ret) { | ||
| 1151 | mutex_unlock(&dev->struct_mutex); | ||
| 1152 | return VM_FAULT_SIGBUS; | ||
| 1153 | } | ||
| 1154 | |||
| 1148 | list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 1155 | list_add_tail(&obj_priv->list, &dev_priv->mm.inactive_list); |
| 1149 | } | 1156 | } |
| 1150 | 1157 | ||
| @@ -2128,8 +2135,10 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) | |||
| 2128 | return; | 2135 | return; |
| 2129 | } | 2136 | } |
| 2130 | 2137 | ||
| 2131 | pitch_val = (obj_priv->stride / 128) - 1; | 2138 | pitch_val = obj_priv->stride / 128; |
| 2132 | WARN_ON(pitch_val & ~0x0000000f); | 2139 | pitch_val = ffs(pitch_val) - 1; |
| 2140 | WARN_ON(pitch_val > I830_FENCE_MAX_PITCH_VAL); | ||
| 2141 | |||
| 2133 | val = obj_priv->gtt_offset; | 2142 | val = obj_priv->gtt_offset; |
| 2134 | if (obj_priv->tiling_mode == I915_TILING_Y) | 2143 | if (obj_priv->tiling_mode == I915_TILING_Y) |
| 2135 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; | 2144 | val |= 1 << I830_FENCE_TILING_Y_SHIFT; |
| @@ -2251,9 +2260,6 @@ try_again: | |||
| 2251 | goto try_again; | 2260 | goto try_again; |
| 2252 | } | 2261 | } |
| 2253 | 2262 | ||
| 2254 | BUG_ON(old_obj_priv->active || | ||
| 2255 | (reg->obj->write_domain & I915_GEM_GPU_DOMAINS)); | ||
| 2256 | |||
| 2257 | /* | 2263 | /* |
| 2258 | * Zap this virtual mapping so we can set up a fence again | 2264 | * Zap this virtual mapping so we can set up a fence again |
| 2259 | * for this object next time we need it. | 2265 | * for this object next time we need it. |
| @@ -2421,6 +2427,16 @@ i915_gem_clflush_object(struct drm_gem_object *obj) | |||
| 2421 | if (obj_priv->pages == NULL) | 2427 | if (obj_priv->pages == NULL) |
| 2422 | return; | 2428 | return; |
| 2423 | 2429 | ||
| 2430 | /* XXX: The 865 in particular appears to be weird in how it handles | ||
| 2431 | * cache flushing. We haven't figured it out, but the | ||
| 2432 | * clflush+agp_chipset_flush doesn't appear to successfully get the | ||
| 2433 | * data visible to the PGU, while wbinvd + agp_chipset_flush does. | ||
| 2434 | */ | ||
| 2435 | if (IS_I865G(obj->dev)) { | ||
| 2436 | wbinvd(); | ||
| 2437 | return; | ||
| 2438 | } | ||
| 2439 | |||
| 2424 | drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); | 2440 | drm_clflush_pages(obj_priv->pages, obj->size / PAGE_SIZE); |
| 2425 | } | 2441 | } |
| 2426 | 2442 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c index 52a059354e83..540dd336e6ec 100644 --- a/drivers/gpu/drm/i915/i915_gem_tiling.c +++ b/drivers/gpu/drm/i915/i915_gem_tiling.c | |||
| @@ -213,7 +213,8 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | |||
| 213 | if (tiling_mode == I915_TILING_NONE) | 213 | if (tiling_mode == I915_TILING_NONE) |
| 214 | return true; | 214 | return true; |
| 215 | 215 | ||
| 216 | if (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev)) | 216 | if (!IS_I9XX(dev) || |
| 217 | (tiling_mode == I915_TILING_Y && HAS_128_BYTE_Y_TILING(dev))) | ||
| 217 | tile_width = 128; | 218 | tile_width = 128; |
| 218 | else | 219 | else |
| 219 | tile_width = 512; | 220 | tile_width = 512; |
| @@ -225,11 +226,18 @@ i915_tiling_ok(struct drm_device *dev, int stride, int size, int tiling_mode) | |||
| 225 | if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) | 226 | if (stride / 128 > I965_FENCE_MAX_PITCH_VAL) |
| 226 | return false; | 227 | return false; |
| 227 | } else if (IS_I9XX(dev)) { | 228 | } else if (IS_I9XX(dev)) { |
| 228 | if (stride / tile_width > I830_FENCE_MAX_PITCH_VAL || | 229 | uint32_t pitch_val = ffs(stride / tile_width) - 1; |
| 230 | |||
| 231 | /* XXX: For Y tiling, FENCE_MAX_PITCH_VAL is actually 6 (8KB) | ||
| 232 | * instead of 4 (2KB) on 945s. | ||
| 233 | */ | ||
| 234 | if (pitch_val > I915_FENCE_MAX_PITCH_VAL || | ||
| 229 | size > (I830_FENCE_MAX_SIZE_VAL << 20)) | 235 | size > (I830_FENCE_MAX_SIZE_VAL << 20)) |
| 230 | return false; | 236 | return false; |
| 231 | } else { | 237 | } else { |
| 232 | if (stride / 128 > I830_FENCE_MAX_PITCH_VAL || | 238 | uint32_t pitch_val = ffs(stride / tile_width) - 1; |
| 239 | |||
| 240 | if (pitch_val > I830_FENCE_MAX_PITCH_VAL || | ||
| 233 | size > (I830_FENCE_MAX_SIZE_VAL << 19)) | 241 | size > (I830_FENCE_MAX_SIZE_VAL << 19)) |
| 234 | return false; | 242 | return false; |
| 235 | } | 243 | } |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 9668cc0d7f4e..375569d01d01 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -190,7 +190,8 @@ | |||
| 190 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) | 190 | #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8) |
| 191 | #define I830_FENCE_PITCH_SHIFT 4 | 191 | #define I830_FENCE_PITCH_SHIFT 4 |
| 192 | #define I830_FENCE_REG_VALID (1<<0) | 192 | #define I830_FENCE_REG_VALID (1<<0) |
| 193 | #define I830_FENCE_MAX_PITCH_VAL 0x10 | 193 | #define I915_FENCE_MAX_PITCH_VAL 0x10 |
| 194 | #define I830_FENCE_MAX_PITCH_VAL 6 | ||
| 194 | #define I830_FENCE_MAX_SIZE_VAL (1<<8) | 195 | #define I830_FENCE_MAX_SIZE_VAL (1<<8) |
| 195 | 196 | ||
| 196 | #define I915_FENCE_START_MASK 0x0ff00000 | 197 | #define I915_FENCE_START_MASK 0x0ff00000 |
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 640f5158effc..79acc4f4c1f8 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
| @@ -381,11 +381,6 @@ static int intel_crt_set_property(struct drm_connector *connector, | |||
| 381 | struct drm_property *property, | 381 | struct drm_property *property, |
| 382 | uint64_t value) | 382 | uint64_t value) |
| 383 | { | 383 | { |
| 384 | struct drm_device *dev = connector->dev; | ||
| 385 | |||
| 386 | if (property == dev->mode_config.dpms_property && connector->encoder) | ||
| 387 | intel_crt_dpms(connector->encoder, (uint32_t)(value & 0xf)); | ||
| 388 | |||
| 389 | return 0; | 384 | return 0; |
| 390 | } | 385 | } |
| 391 | 386 | ||
| @@ -402,6 +397,7 @@ static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = { | |||
| 402 | }; | 397 | }; |
| 403 | 398 | ||
| 404 | static const struct drm_connector_funcs intel_crt_connector_funcs = { | 399 | static const struct drm_connector_funcs intel_crt_connector_funcs = { |
| 400 | .dpms = drm_helper_connector_dpms, | ||
| 405 | .detect = intel_crt_detect, | 401 | .detect = intel_crt_detect, |
| 406 | .fill_modes = drm_helper_probe_single_connector_modes, | 402 | .fill_modes = drm_helper_probe_single_connector_modes, |
| 407 | .destroy = intel_crt_destroy, | 403 | .destroy = intel_crt_destroy, |
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c index 8b8d6e65cd3f..1ee3007d6ec0 100644 --- a/drivers/gpu/drm/i915/intel_dvo.c +++ b/drivers/gpu/drm/i915/intel_dvo.c | |||
| @@ -316,6 +316,7 @@ static const struct drm_encoder_helper_funcs intel_dvo_helper_funcs = { | |||
| 316 | }; | 316 | }; |
| 317 | 317 | ||
| 318 | static const struct drm_connector_funcs intel_dvo_connector_funcs = { | 318 | static const struct drm_connector_funcs intel_dvo_connector_funcs = { |
| 319 | .dpms = drm_helper_connector_dpms, | ||
| 319 | .save = intel_dvo_save, | 320 | .save = intel_dvo_save, |
| 320 | .restore = intel_dvo_restore, | 321 | .restore = intel_dvo_restore, |
| 321 | .detect = intel_dvo_detect, | 322 | .detect = intel_dvo_detect, |
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c index d0983bb93a18..7d6bdd705326 100644 --- a/drivers/gpu/drm/i915/intel_hdmi.c +++ b/drivers/gpu/drm/i915/intel_hdmi.c | |||
| @@ -219,6 +219,7 @@ static const struct drm_encoder_helper_funcs intel_hdmi_helper_funcs = { | |||
| 219 | }; | 219 | }; |
| 220 | 220 | ||
| 221 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { | 221 | static const struct drm_connector_funcs intel_hdmi_connector_funcs = { |
| 222 | .dpms = drm_helper_connector_dpms, | ||
| 222 | .save = intel_hdmi_save, | 223 | .save = intel_hdmi_save, |
| 223 | .restore = intel_hdmi_restore, | 224 | .restore = intel_hdmi_restore, |
| 224 | .detect = intel_hdmi_detect, | 225 | .detect = intel_hdmi_detect, |
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 53731f0ffcb5..53cccfa58b95 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
| @@ -343,11 +343,6 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
| 343 | struct drm_property *property, | 343 | struct drm_property *property, |
| 344 | uint64_t value) | 344 | uint64_t value) |
| 345 | { | 345 | { |
| 346 | struct drm_device *dev = connector->dev; | ||
| 347 | |||
| 348 | if (property == dev->mode_config.dpms_property && connector->encoder) | ||
| 349 | intel_lvds_dpms(connector->encoder, (uint32_t)(value & 0xf)); | ||
| 350 | |||
| 351 | return 0; | 346 | return 0; |
| 352 | } | 347 | } |
| 353 | 348 | ||
| @@ -366,6 +361,7 @@ static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs | |||
| 366 | }; | 361 | }; |
| 367 | 362 | ||
| 368 | static const struct drm_connector_funcs intel_lvds_connector_funcs = { | 363 | static const struct drm_connector_funcs intel_lvds_connector_funcs = { |
| 364 | .dpms = drm_helper_connector_dpms, | ||
| 369 | .save = intel_lvds_save, | 365 | .save = intel_lvds_save, |
| 370 | .restore = intel_lvds_restore, | 366 | .restore = intel_lvds_restore, |
| 371 | .detect = intel_lvds_detect, | 367 | .detect = intel_lvds_detect, |
| @@ -391,7 +387,7 @@ static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) | |||
| 391 | } | 387 | } |
| 392 | 388 | ||
| 393 | /* These systems claim to have LVDS, but really don't */ | 389 | /* These systems claim to have LVDS, but really don't */ |
| 394 | static const struct dmi_system_id __initdata intel_no_lvds[] = { | 390 | static const struct dmi_system_id intel_no_lvds[] = { |
| 395 | { | 391 | { |
| 396 | .callback = intel_no_lvds_dmi_callback, | 392 | .callback = intel_no_lvds_dmi_callback, |
| 397 | .ident = "Apple Mac Mini (Core series)", | 393 | .ident = "Apple Mac Mini (Core series)", |
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c index f3ef6bfd8ffc..3093b4d4a4dd 100644 --- a/drivers/gpu/drm/i915/intel_sdvo.c +++ b/drivers/gpu/drm/i915/intel_sdvo.c | |||
| @@ -1616,6 +1616,7 @@ static const struct drm_encoder_helper_funcs intel_sdvo_helper_funcs = { | |||
| 1616 | }; | 1616 | }; |
| 1617 | 1617 | ||
| 1618 | static const struct drm_connector_funcs intel_sdvo_connector_funcs = { | 1618 | static const struct drm_connector_funcs intel_sdvo_connector_funcs = { |
| 1619 | .dpms = drm_helper_connector_dpms, | ||
| 1619 | .save = intel_sdvo_save, | 1620 | .save = intel_sdvo_save, |
| 1620 | .restore = intel_sdvo_restore, | 1621 | .restore = intel_sdvo_restore, |
| 1621 | .detect = intel_sdvo_detect, | 1622 | .detect = intel_sdvo_detect, |
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c index d2c32983242d..98ac0546b7bd 100644 --- a/drivers/gpu/drm/i915/intel_tv.c +++ b/drivers/gpu/drm/i915/intel_tv.c | |||
| @@ -1626,6 +1626,7 @@ static const struct drm_encoder_helper_funcs intel_tv_helper_funcs = { | |||
| 1626 | }; | 1626 | }; |
| 1627 | 1627 | ||
| 1628 | static const struct drm_connector_funcs intel_tv_connector_funcs = { | 1628 | static const struct drm_connector_funcs intel_tv_connector_funcs = { |
| 1629 | .dpms = drm_helper_connector_dpms, | ||
| 1629 | .save = intel_tv_save, | 1630 | .save = intel_tv_save, |
| 1630 | .restore = intel_tv_restore, | 1631 | .restore = intel_tv_restore, |
| 1631 | .detect = intel_tv_detect, | 1632 | .detect = intel_tv_detect, |
diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index 77a7a4d84650..aff90bb96488 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c | |||
| @@ -2185,9 +2185,9 @@ void radeon_commit_ring(drm_radeon_private_t *dev_priv) | |||
| 2185 | 2185 | ||
| 2186 | /* check if the ring is padded out to 16-dword alignment */ | 2186 | /* check if the ring is padded out to 16-dword alignment */ |
| 2187 | 2187 | ||
| 2188 | tail_aligned = dev_priv->ring.tail & 0xf; | 2188 | tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1); |
| 2189 | if (tail_aligned) { | 2189 | if (tail_aligned) { |
| 2190 | int num_p2 = 16 - tail_aligned; | 2190 | int num_p2 = RADEON_RING_ALIGN - tail_aligned; |
| 2191 | 2191 | ||
| 2192 | ring = dev_priv->ring.start; | 2192 | ring = dev_priv->ring.start; |
| 2193 | /* pad with some CP_PACKET2 */ | 2193 | /* pad with some CP_PACKET2 */ |
diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 8071d965f142..0c6bfc1de153 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h | |||
| @@ -1964,11 +1964,14 @@ do { \ | |||
| 1964 | 1964 | ||
| 1965 | #define RING_LOCALS int write, _nr, _align_nr; unsigned int mask; u32 *ring; | 1965 | #define RING_LOCALS int write, _nr, _align_nr; unsigned int mask; u32 *ring; |
| 1966 | 1966 | ||
| 1967 | #define RADEON_RING_ALIGN 16 | ||
| 1968 | |||
| 1967 | #define BEGIN_RING( n ) do { \ | 1969 | #define BEGIN_RING( n ) do { \ |
| 1968 | if ( RADEON_VERBOSE ) { \ | 1970 | if ( RADEON_VERBOSE ) { \ |
| 1969 | DRM_INFO( "BEGIN_RING( %d )\n", (n)); \ | 1971 | DRM_INFO( "BEGIN_RING( %d )\n", (n)); \ |
| 1970 | } \ | 1972 | } \ |
| 1971 | _align_nr = (n + 0xf) & ~0xf; \ | 1973 | _align_nr = RADEON_RING_ALIGN - ((dev_priv->ring.tail + n) & (RADEON_RING_ALIGN-1)); \ |
| 1974 | _align_nr += n; \ | ||
| 1972 | if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) { \ | 1975 | if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) { \ |
| 1973 | COMMIT_RING(); \ | 1976 | COMMIT_RING(); \ |
| 1974 | radeon_wait_ring( dev_priv, _align_nr * sizeof(u32)); \ | 1977 | radeon_wait_ring( dev_priv, _align_nr * sizeof(u32)); \ |
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c index b5e3b2851698..a1787fdf5b9f 100644 --- a/drivers/hwmon/lm78.c +++ b/drivers/hwmon/lm78.c | |||
| @@ -182,7 +182,7 @@ static struct platform_driver lm78_isa_driver = { | |||
| 182 | .name = "lm78", | 182 | .name = "lm78", |
| 183 | }, | 183 | }, |
| 184 | .probe = lm78_isa_probe, | 184 | .probe = lm78_isa_probe, |
| 185 | .remove = lm78_isa_remove, | 185 | .remove = __devexit_p(lm78_isa_remove), |
| 186 | }; | 186 | }; |
| 187 | 187 | ||
| 188 | 188 | ||
diff --git a/drivers/i2c/busses/i2c-sh7760.c b/drivers/i2c/busses/i2c-sh7760.c index baa28b73ae42..b9680f50f541 100644 --- a/drivers/i2c/busses/i2c-sh7760.c +++ b/drivers/i2c/busses/i2c-sh7760.c | |||
| @@ -396,7 +396,7 @@ static int __devinit calc_CCR(unsigned long scl_hz) | |||
| 396 | signed char cdf, cdfm; | 396 | signed char cdf, cdfm; |
| 397 | int scgd, scgdm, scgds; | 397 | int scgd, scgdm, scgds; |
| 398 | 398 | ||
| 399 | mclk = clk_get(NULL, "module_clk"); | 399 | mclk = clk_get(NULL, "peripheral_clk"); |
| 400 | if (IS_ERR(mclk)) { | 400 | if (IS_ERR(mclk)) { |
| 401 | return PTR_ERR(mclk); | 401 | return PTR_ERR(mclk); |
| 402 | } else { | 402 | } else { |
diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index 537da1cde16d..e59b6dee9ae2 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c | |||
| @@ -402,27 +402,23 @@ static u8 ali_cable_detect(ide_hwif_t *hwif) | |||
| 402 | return cbl; | 402 | return cbl; |
| 403 | } | 403 | } |
| 404 | 404 | ||
| 405 | #if !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) | 405 | #ifndef CONFIG_SPARC64 |
| 406 | /** | 406 | /** |
| 407 | * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff | 407 | * init_hwif_ali15x3 - Initialize the ALI IDE x86 stuff |
| 408 | * @hwif: interface to configure | 408 | * @hwif: interface to configure |
| 409 | * | 409 | * |
| 410 | * Obtain the IRQ tables for an ALi based IDE solution on the PC | 410 | * Obtain the IRQ tables for an ALi based IDE solution on the PC |
| 411 | * class platforms. This part of the code isn't applicable to the | 411 | * class platforms. This part of the code isn't applicable to the |
| 412 | * Sparc and PowerPC systems. | 412 | * Sparc systems. |
| 413 | */ | 413 | */ |
| 414 | 414 | ||
| 415 | static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) | 415 | static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) |
| 416 | { | 416 | { |
| 417 | struct pci_dev *dev = to_pci_dev(hwif->dev); | ||
| 418 | u8 ideic, inmir; | 417 | u8 ideic, inmir; |
| 419 | s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, | 418 | s8 irq_routing_table[] = { -1, 9, 3, 10, 4, 5, 7, 6, |
| 420 | 1, 11, 0, 12, 0, 14, 0, 15 }; | 419 | 1, 11, 0, 12, 0, 14, 0, 15 }; |
| 421 | int irq = -1; | 420 | int irq = -1; |
| 422 | 421 | ||
| 423 | if (dev->device == PCI_DEVICE_ID_AL_M5229) | ||
| 424 | hwif->irq = hwif->channel ? 15 : 14; | ||
| 425 | |||
| 426 | if (isa_dev) { | 422 | if (isa_dev) { |
| 427 | /* | 423 | /* |
| 428 | * read IDE interface control | 424 | * read IDE interface control |
| @@ -455,7 +451,7 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) | |||
| 455 | } | 451 | } |
| 456 | #else | 452 | #else |
| 457 | #define init_hwif_ali15x3 NULL | 453 | #define init_hwif_ali15x3 NULL |
| 458 | #endif /* !defined(CONFIG_SPARC64) && !defined(CONFIG_PPC) */ | 454 | #endif /* CONFIG_SPARC64 */ |
| 459 | 455 | ||
| 460 | /** | 456 | /** |
| 461 | * init_dma_ali15x3 - set up DMA on ALi15x3 | 457 | * init_dma_ali15x3 - set up DMA on ALi15x3 |
diff --git a/drivers/ide/ide-atapi.c b/drivers/ide/ide-atapi.c index 7201b176d75b..757e5956b132 100644 --- a/drivers/ide/ide-atapi.c +++ b/drivers/ide/ide-atapi.c | |||
| @@ -80,34 +80,6 @@ void ide_init_pc(struct ide_atapi_pc *pc) | |||
| 80 | EXPORT_SYMBOL_GPL(ide_init_pc); | 80 | EXPORT_SYMBOL_GPL(ide_init_pc); |
| 81 | 81 | ||
| 82 | /* | 82 | /* |
| 83 | * Generate a new packet command request in front of the request queue, before | ||
| 84 | * the current request, so that it will be processed immediately, on the next | ||
| 85 | * pass through the driver. | ||
| 86 | */ | ||
| 87 | static void ide_queue_pc_head(ide_drive_t *drive, struct gendisk *disk, | ||
| 88 | struct ide_atapi_pc *pc, struct request *rq) | ||
| 89 | { | ||
| 90 | blk_rq_init(NULL, rq); | ||
| 91 | rq->cmd_type = REQ_TYPE_SPECIAL; | ||
| 92 | rq->cmd_flags |= REQ_PREEMPT; | ||
| 93 | rq->buffer = (char *)pc; | ||
| 94 | rq->rq_disk = disk; | ||
| 95 | |||
| 96 | if (pc->req_xfer) { | ||
| 97 | rq->data = pc->buf; | ||
| 98 | rq->data_len = pc->req_xfer; | ||
| 99 | } | ||
| 100 | |||
| 101 | memcpy(rq->cmd, pc->c, 12); | ||
| 102 | if (drive->media == ide_tape) | ||
| 103 | rq->cmd[13] = REQ_IDETAPE_PC1; | ||
| 104 | |||
| 105 | drive->hwif->rq = NULL; | ||
| 106 | |||
| 107 | elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); | ||
| 108 | } | ||
| 109 | |||
| 110 | /* | ||
| 111 | * Add a special packet command request to the tail of the request queue, | 83 | * Add a special packet command request to the tail of the request queue, |
| 112 | * and wait for it to be serviced. | 84 | * and wait for it to be serviced. |
| 113 | */ | 85 | */ |
| @@ -119,19 +91,21 @@ int ide_queue_pc_tail(ide_drive_t *drive, struct gendisk *disk, | |||
| 119 | 91 | ||
| 120 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 92 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
| 121 | rq->cmd_type = REQ_TYPE_SPECIAL; | 93 | rq->cmd_type = REQ_TYPE_SPECIAL; |
| 122 | rq->buffer = (char *)pc; | 94 | rq->special = (char *)pc; |
| 123 | 95 | ||
| 124 | if (pc->req_xfer) { | 96 | if (pc->req_xfer) { |
| 125 | rq->data = pc->buf; | 97 | error = blk_rq_map_kern(drive->queue, rq, pc->buf, pc->req_xfer, |
| 126 | rq->data_len = pc->req_xfer; | 98 | GFP_NOIO); |
| 99 | if (error) | ||
| 100 | goto put_req; | ||
| 127 | } | 101 | } |
| 128 | 102 | ||
| 129 | memcpy(rq->cmd, pc->c, 12); | 103 | memcpy(rq->cmd, pc->c, 12); |
| 130 | if (drive->media == ide_tape) | 104 | if (drive->media == ide_tape) |
| 131 | rq->cmd[13] = REQ_IDETAPE_PC1; | 105 | rq->cmd[13] = REQ_IDETAPE_PC1; |
| 132 | error = blk_execute_rq(drive->queue, disk, rq, 0); | 106 | error = blk_execute_rq(drive->queue, disk, rq, 0); |
| 107 | put_req: | ||
| 133 | blk_put_request(rq); | 108 | blk_put_request(rq); |
| 134 | |||
| 135 | return error; | 109 | return error; |
| 136 | } | 110 | } |
| 137 | EXPORT_SYMBOL_GPL(ide_queue_pc_tail); | 111 | EXPORT_SYMBOL_GPL(ide_queue_pc_tail); |
| @@ -191,20 +165,113 @@ void ide_create_request_sense_cmd(ide_drive_t *drive, struct ide_atapi_pc *pc) | |||
| 191 | } | 165 | } |
| 192 | EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd); | 166 | EXPORT_SYMBOL_GPL(ide_create_request_sense_cmd); |
| 193 | 167 | ||
| 168 | void ide_prep_sense(ide_drive_t *drive, struct request *rq) | ||
| 169 | { | ||
| 170 | struct request_sense *sense = &drive->sense_data; | ||
| 171 | struct request *sense_rq = &drive->sense_rq; | ||
| 172 | unsigned int cmd_len, sense_len; | ||
| 173 | int err; | ||
| 174 | |||
| 175 | debug_log("%s: enter\n", __func__); | ||
| 176 | |||
| 177 | switch (drive->media) { | ||
| 178 | case ide_floppy: | ||
| 179 | cmd_len = 255; | ||
| 180 | sense_len = 18; | ||
| 181 | break; | ||
| 182 | case ide_tape: | ||
| 183 | cmd_len = 20; | ||
| 184 | sense_len = 20; | ||
| 185 | break; | ||
| 186 | default: | ||
| 187 | cmd_len = 18; | ||
| 188 | sense_len = 18; | ||
| 189 | } | ||
| 190 | |||
| 191 | BUG_ON(sense_len > sizeof(*sense)); | ||
| 192 | |||
| 193 | if (blk_sense_request(rq) || drive->sense_rq_armed) | ||
| 194 | return; | ||
| 195 | |||
| 196 | memset(sense, 0, sizeof(*sense)); | ||
| 197 | |||
| 198 | blk_rq_init(rq->q, sense_rq); | ||
| 199 | |||
| 200 | err = blk_rq_map_kern(drive->queue, sense_rq, sense, sense_len, | ||
| 201 | GFP_NOIO); | ||
| 202 | if (unlikely(err)) { | ||
| 203 | if (printk_ratelimit()) | ||
| 204 | printk(KERN_WARNING "%s: failed to map sense buffer\n", | ||
| 205 | drive->name); | ||
| 206 | return; | ||
| 207 | } | ||
| 208 | |||
| 209 | sense_rq->rq_disk = rq->rq_disk; | ||
| 210 | sense_rq->cmd[0] = GPCMD_REQUEST_SENSE; | ||
| 211 | sense_rq->cmd[4] = cmd_len; | ||
| 212 | sense_rq->cmd_type = REQ_TYPE_SENSE; | ||
| 213 | sense_rq->cmd_flags |= REQ_PREEMPT; | ||
| 214 | |||
| 215 | if (drive->media == ide_tape) | ||
| 216 | sense_rq->cmd[13] = REQ_IDETAPE_PC1; | ||
| 217 | |||
| 218 | drive->sense_rq_armed = true; | ||
| 219 | } | ||
| 220 | EXPORT_SYMBOL_GPL(ide_prep_sense); | ||
| 221 | |||
| 222 | int ide_queue_sense_rq(ide_drive_t *drive, void *special) | ||
| 223 | { | ||
| 224 | /* deferred failure from ide_prep_sense() */ | ||
| 225 | if (!drive->sense_rq_armed) { | ||
| 226 | printk(KERN_WARNING "%s: failed queue sense request\n", | ||
| 227 | drive->name); | ||
| 228 | return -ENOMEM; | ||
| 229 | } | ||
| 230 | |||
| 231 | drive->sense_rq.special = special; | ||
| 232 | drive->sense_rq_armed = false; | ||
| 233 | |||
| 234 | drive->hwif->rq = NULL; | ||
| 235 | |||
| 236 | elv_add_request(drive->queue, &drive->sense_rq, | ||
| 237 | ELEVATOR_INSERT_FRONT, 0); | ||
| 238 | return 0; | ||
| 239 | } | ||
| 240 | EXPORT_SYMBOL_GPL(ide_queue_sense_rq); | ||
| 241 | |||
| 194 | /* | 242 | /* |
| 195 | * Called when an error was detected during the last packet command. | 243 | * Called when an error was detected during the last packet command. |
| 196 | * We queue a request sense packet command in the head of the request list. | 244 | * We queue a request sense packet command at the head of the request |
| 245 | * queue. | ||
| 197 | */ | 246 | */ |
| 198 | void ide_retry_pc(ide_drive_t *drive, struct gendisk *disk) | 247 | void ide_retry_pc(ide_drive_t *drive) |
| 199 | { | 248 | { |
| 200 | struct request *rq = &drive->request_sense_rq; | 249 | struct request *failed_rq = drive->hwif->rq; |
| 250 | struct request *sense_rq = &drive->sense_rq; | ||
| 201 | struct ide_atapi_pc *pc = &drive->request_sense_pc; | 251 | struct ide_atapi_pc *pc = &drive->request_sense_pc; |
| 202 | 252 | ||
| 203 | (void)ide_read_error(drive); | 253 | (void)ide_read_error(drive); |
| 204 | ide_create_request_sense_cmd(drive, pc); | 254 | |
| 255 | /* init pc from sense_rq */ | ||
| 256 | ide_init_pc(pc); | ||
| 257 | memcpy(pc->c, sense_rq->cmd, 12); | ||
| 258 | pc->buf = bio_data(sense_rq->bio); /* pointer to mapped address */ | ||
| 259 | pc->req_xfer = blk_rq_bytes(sense_rq); | ||
| 260 | |||
| 205 | if (drive->media == ide_tape) | 261 | if (drive->media == ide_tape) |
| 206 | set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); | 262 | set_bit(IDE_AFLAG_IGNORE_DSC, &drive->atapi_flags); |
| 207 | ide_queue_pc_head(drive, disk, pc, rq); | 263 | |
| 264 | /* | ||
| 265 | * Push back the failed request and put request sense on top | ||
| 266 | * of it. The failed command will be retried after sense data | ||
| 267 | * is acquired. | ||
| 268 | */ | ||
| 269 | blk_requeue_request(failed_rq->q, failed_rq); | ||
| 270 | drive->hwif->rq = NULL; | ||
| 271 | if (ide_queue_sense_rq(drive, pc)) { | ||
| 272 | blk_start_request(failed_rq); | ||
| 273 | ide_complete_rq(drive, -EIO, blk_rq_bytes(failed_rq)); | ||
| 274 | } | ||
| 208 | } | 275 | } |
| 209 | EXPORT_SYMBOL_GPL(ide_retry_pc); | 276 | EXPORT_SYMBOL_GPL(ide_retry_pc); |
| 210 | 277 | ||
| @@ -246,7 +313,7 @@ int ide_cd_get_xferlen(struct request *rq) | |||
| 246 | return 32768; | 313 | return 32768; |
| 247 | else if (blk_sense_request(rq) || blk_pc_request(rq) || | 314 | else if (blk_sense_request(rq) || blk_pc_request(rq) || |
| 248 | rq->cmd_type == REQ_TYPE_ATA_PC) | 315 | rq->cmd_type == REQ_TYPE_ATA_PC) |
| 249 | return rq->data_len; | 316 | return blk_rq_bytes(rq); |
| 250 | else | 317 | else |
| 251 | return 0; | 318 | return 0; |
| 252 | } | 319 | } |
| @@ -276,7 +343,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
| 276 | struct ide_cmd *cmd = &hwif->cmd; | 343 | struct ide_cmd *cmd = &hwif->cmd; |
| 277 | struct request *rq = hwif->rq; | 344 | struct request *rq = hwif->rq; |
| 278 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; | 345 | const struct ide_tp_ops *tp_ops = hwif->tp_ops; |
| 279 | xfer_func_t *xferfunc; | ||
| 280 | unsigned int timeout, done; | 346 | unsigned int timeout, done; |
| 281 | u16 bcount; | 347 | u16 bcount; |
| 282 | u8 stat, ireason, dsc = 0; | 348 | u8 stat, ireason, dsc = 0; |
| @@ -303,18 +369,14 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
| 303 | drive->name, rq_data_dir(pc->rq) | 369 | drive->name, rq_data_dir(pc->rq) |
| 304 | ? "write" : "read"); | 370 | ? "write" : "read"); |
| 305 | pc->flags |= PC_FLAG_DMA_ERROR; | 371 | pc->flags |= PC_FLAG_DMA_ERROR; |
| 306 | } else { | 372 | } else |
| 307 | pc->xferred = pc->req_xfer; | 373 | pc->xferred = pc->req_xfer; |
| 308 | if (drive->pc_update_buffers) | ||
| 309 | drive->pc_update_buffers(drive, pc); | ||
| 310 | } | ||
| 311 | debug_log("%s: DMA finished\n", drive->name); | 374 | debug_log("%s: DMA finished\n", drive->name); |
| 312 | } | 375 | } |
| 313 | 376 | ||
| 314 | /* No more interrupts */ | 377 | /* No more interrupts */ |
| 315 | if ((stat & ATA_DRQ) == 0) { | 378 | if ((stat & ATA_DRQ) == 0) { |
| 316 | int uptodate, error; | 379 | int uptodate, error; |
| 317 | unsigned int done; | ||
| 318 | 380 | ||
| 319 | debug_log("Packet command completed, %d bytes transferred\n", | 381 | debug_log("Packet command completed, %d bytes transferred\n", |
| 320 | pc->xferred); | 382 | pc->xferred); |
| @@ -343,7 +405,7 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
| 343 | debug_log("[cmd %x]: check condition\n", rq->cmd[0]); | 405 | debug_log("[cmd %x]: check condition\n", rq->cmd[0]); |
| 344 | 406 | ||
| 345 | /* Retry operation */ | 407 | /* Retry operation */ |
| 346 | ide_retry_pc(drive, rq->rq_disk); | 408 | ide_retry_pc(drive); |
| 347 | 409 | ||
| 348 | /* queued, but not started */ | 410 | /* queued, but not started */ |
| 349 | return ide_stopped; | 411 | return ide_stopped; |
| @@ -353,6 +415,12 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
| 353 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) | 415 | if ((pc->flags & PC_FLAG_WAIT_FOR_DSC) && (stat & ATA_DSC) == 0) |
| 354 | dsc = 1; | 416 | dsc = 1; |
| 355 | 417 | ||
| 418 | /* | ||
| 419 | * ->pc_callback() might change rq->data_len for | ||
| 420 | * residual count, cache total length. | ||
| 421 | */ | ||
| 422 | done = blk_rq_bytes(rq); | ||
| 423 | |||
| 356 | /* Command finished - Call the callback function */ | 424 | /* Command finished - Call the callback function */ |
| 357 | uptodate = drive->pc_callback(drive, dsc); | 425 | uptodate = drive->pc_callback(drive, dsc); |
| 358 | 426 | ||
| @@ -361,7 +429,6 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
| 361 | 429 | ||
| 362 | if (blk_special_request(rq)) { | 430 | if (blk_special_request(rq)) { |
| 363 | rq->errors = 0; | 431 | rq->errors = 0; |
| 364 | done = blk_rq_bytes(rq); | ||
| 365 | error = 0; | 432 | error = 0; |
| 366 | } else { | 433 | } else { |
| 367 | 434 | ||
| @@ -370,15 +437,10 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
| 370 | rq->errors = -EIO; | 437 | rq->errors = -EIO; |
| 371 | } | 438 | } |
| 372 | 439 | ||
| 373 | if (drive->media == ide_tape) | ||
| 374 | done = ide_rq_bytes(rq); /* FIXME */ | ||
| 375 | else | ||
| 376 | done = blk_rq_bytes(rq); | ||
| 377 | |||
| 378 | error = uptodate ? 0 : -EIO; | 440 | error = uptodate ? 0 : -EIO; |
| 379 | } | 441 | } |
| 380 | 442 | ||
| 381 | ide_complete_rq(drive, error, done); | 443 | ide_complete_rq(drive, error, blk_rq_bytes(rq)); |
| 382 | return ide_stopped; | 444 | return ide_stopped; |
| 383 | } | 445 | } |
| 384 | 446 | ||
| @@ -407,21 +469,11 @@ static ide_startstop_t ide_pc_intr(ide_drive_t *drive) | |||
| 407 | return ide_do_reset(drive); | 469 | return ide_do_reset(drive); |
| 408 | } | 470 | } |
| 409 | 471 | ||
| 410 | xferfunc = write ? tp_ops->output_data : tp_ops->input_data; | 472 | done = min_t(unsigned int, bcount, cmd->nleft); |
| 411 | 473 | ide_pio_bytes(drive, cmd, write, done); | |
| 412 | if (drive->media == ide_floppy && pc->buf == NULL) { | ||
| 413 | done = min_t(unsigned int, bcount, cmd->nleft); | ||
| 414 | ide_pio_bytes(drive, cmd, write, done); | ||
| 415 | } else if (drive->media == ide_tape && pc->bh) { | ||
| 416 | done = drive->pc_io_buffers(drive, pc, bcount, write); | ||
| 417 | } else { | ||
| 418 | done = min_t(unsigned int, bcount, pc->req_xfer - pc->xferred); | ||
| 419 | xferfunc(drive, NULL, pc->cur_pos, done); | ||
| 420 | } | ||
| 421 | 474 | ||
| 422 | /* Update the current position */ | 475 | /* Update transferred byte count */ |
| 423 | pc->xferred += done; | 476 | pc->xferred += done; |
| 424 | pc->cur_pos += done; | ||
| 425 | 477 | ||
| 426 | bcount -= done; | 478 | bcount -= done; |
| 427 | 479 | ||
| @@ -599,7 +651,6 @@ ide_startstop_t ide_issue_pc(ide_drive_t *drive, struct ide_cmd *cmd) | |||
| 599 | 651 | ||
| 600 | /* We haven't transferred any data yet */ | 652 | /* We haven't transferred any data yet */ |
| 601 | pc->xferred = 0; | 653 | pc->xferred = 0; |
| 602 | pc->cur_pos = pc->buf; | ||
| 603 | 654 | ||
| 604 | valid_tf = IDE_VALID_DEVICE; | 655 | valid_tf = IDE_VALID_DEVICE; |
| 605 | bcount = ((drive->media == ide_tape) ? | 656 | bcount = ((drive->media == ide_tape) ? |
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 925eb9e245d1..424140c6c400 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c | |||
| @@ -182,7 +182,7 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, | |||
| 182 | (sense->information[2] << 8) | | 182 | (sense->information[2] << 8) | |
| 183 | (sense->information[3]); | 183 | (sense->information[3]); |
| 184 | 184 | ||
| 185 | if (drive->queue->hardsect_size == 2048) | 185 | if (queue_logical_block_size(drive->queue) == 2048) |
| 186 | /* device sector size is 2K */ | 186 | /* device sector size is 2K */ |
| 187 | sector <<= 2; | 187 | sector <<= 2; |
| 188 | 188 | ||
| @@ -206,54 +206,25 @@ static void cdrom_analyze_sense_data(ide_drive_t *drive, | |||
| 206 | ide_cd_log_error(drive->name, failed_command, sense); | 206 | ide_cd_log_error(drive->name, failed_command, sense); |
| 207 | } | 207 | } |
| 208 | 208 | ||
| 209 | static void cdrom_queue_request_sense(ide_drive_t *drive, void *sense, | ||
| 210 | struct request *failed_command) | ||
| 211 | { | ||
| 212 | struct cdrom_info *info = drive->driver_data; | ||
| 213 | struct request *rq = &drive->request_sense_rq; | ||
| 214 | |||
| 215 | ide_debug_log(IDE_DBG_SENSE, "enter"); | ||
| 216 | |||
| 217 | if (sense == NULL) | ||
| 218 | sense = &info->sense_data; | ||
| 219 | |||
| 220 | /* stuff the sense request in front of our current request */ | ||
| 221 | blk_rq_init(NULL, rq); | ||
| 222 | rq->cmd_type = REQ_TYPE_ATA_PC; | ||
| 223 | rq->rq_disk = info->disk; | ||
| 224 | |||
| 225 | rq->data = sense; | ||
| 226 | rq->cmd[0] = GPCMD_REQUEST_SENSE; | ||
| 227 | rq->cmd[4] = 18; | ||
| 228 | rq->data_len = 18; | ||
| 229 | |||
| 230 | rq->cmd_type = REQ_TYPE_SENSE; | ||
| 231 | rq->cmd_flags |= REQ_PREEMPT; | ||
| 232 | |||
| 233 | /* NOTE! Save the failed command in "rq->buffer" */ | ||
| 234 | rq->buffer = (void *) failed_command; | ||
| 235 | |||
| 236 | if (failed_command) | ||
| 237 | ide_debug_log(IDE_DBG_SENSE, "failed_cmd: 0x%x", | ||
| 238 | failed_command->cmd[0]); | ||
| 239 | |||
| 240 | drive->hwif->rq = NULL; | ||
| 241 | |||
| 242 | elv_add_request(drive->queue, rq, ELEVATOR_INSERT_FRONT, 0); | ||
| 243 | } | ||
| 244 | |||
| 245 | static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq) | 209 | static void ide_cd_complete_failed_rq(ide_drive_t *drive, struct request *rq) |
| 246 | { | 210 | { |
| 247 | /* | 211 | /* |
| 248 | * For REQ_TYPE_SENSE, "rq->buffer" points to the original | 212 | * For REQ_TYPE_SENSE, "rq->special" points to the original |
| 249 | * failed request | 213 | * failed request. Also, the sense data should be read |
| 214 | * directly from rq which might be different from the original | ||
| 215 | * sense buffer if it got copied during mapping. | ||
| 250 | */ | 216 | */ |
| 251 | struct request *failed = (struct request *)rq->buffer; | 217 | struct request *failed = (struct request *)rq->special; |
| 252 | struct cdrom_info *info = drive->driver_data; | 218 | void *sense = bio_data(rq->bio); |
| 253 | void *sense = &info->sense_data; | ||
| 254 | 219 | ||
| 255 | if (failed) { | 220 | if (failed) { |
| 256 | if (failed->sense) { | 221 | if (failed->sense) { |
| 222 | /* | ||
| 223 | * Sense is always read into drive->sense_data. | ||
| 224 | * Copy back if the failed request has its | ||
| 225 | * sense pointer set. | ||
| 226 | */ | ||
| 227 | memcpy(failed->sense, sense, 18); | ||
| 257 | sense = failed->sense; | 228 | sense = failed->sense; |
| 258 | failed->sense_len = rq->sense_len; | 229 | failed->sense_len = rq->sense_len; |
| 259 | } | 230 | } |
| @@ -428,22 +399,13 @@ static int cdrom_decode_status(ide_drive_t *drive, u8 stat) | |||
| 428 | 399 | ||
| 429 | /* if we got a CHECK_CONDITION status, queue a request sense command */ | 400 | /* if we got a CHECK_CONDITION status, queue a request sense command */ |
| 430 | if (stat & ATA_ERR) | 401 | if (stat & ATA_ERR) |
| 431 | cdrom_queue_request_sense(drive, NULL, NULL); | 402 | return ide_queue_sense_rq(drive, NULL) ? 2 : 1; |
| 432 | return 1; | 403 | return 1; |
| 433 | 404 | ||
| 434 | end_request: | 405 | end_request: |
| 435 | if (stat & ATA_ERR) { | 406 | if (stat & ATA_ERR) { |
| 436 | struct request_queue *q = drive->queue; | ||
| 437 | unsigned long flags; | ||
| 438 | |||
| 439 | spin_lock_irqsave(q->queue_lock, flags); | ||
| 440 | blkdev_dequeue_request(rq); | ||
| 441 | spin_unlock_irqrestore(q->queue_lock, flags); | ||
| 442 | |||
| 443 | hwif->rq = NULL; | 407 | hwif->rq = NULL; |
| 444 | 408 | return ide_queue_sense_rq(drive, rq) ? 2 : 1; | |
| 445 | cdrom_queue_request_sense(drive, rq->sense, rq); | ||
| 446 | return 1; | ||
| 447 | } else | 409 | } else |
| 448 | return 2; | 410 | return 2; |
| 449 | } | 411 | } |
| @@ -503,14 +465,8 @@ static void ide_cd_request_sense_fixup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
| 503 | * and some drives don't send them. Sigh. | 465 | * and some drives don't send them. Sigh. |
| 504 | */ | 466 | */ |
| 505 | if (rq->cmd[0] == GPCMD_REQUEST_SENSE && | 467 | if (rq->cmd[0] == GPCMD_REQUEST_SENSE && |
| 506 | cmd->nleft > 0 && cmd->nleft <= 5) { | 468 | cmd->nleft > 0 && cmd->nleft <= 5) |
| 507 | unsigned int ofs = cmd->nbytes - cmd->nleft; | 469 | cmd->nleft = 0; |
| 508 | |||
| 509 | while (cmd->nleft > 0) { | ||
| 510 | *((u8 *)rq->data + ofs++) = 0; | ||
| 511 | cmd->nleft--; | ||
| 512 | } | ||
| 513 | } | ||
| 514 | } | 470 | } |
| 515 | 471 | ||
| 516 | int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, | 472 | int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, |
| @@ -543,14 +499,18 @@ int ide_cd_queue_pc(ide_drive_t *drive, const unsigned char *cmd, | |||
| 543 | rq->cmd_flags |= cmd_flags; | 499 | rq->cmd_flags |= cmd_flags; |
| 544 | rq->timeout = timeout; | 500 | rq->timeout = timeout; |
| 545 | if (buffer) { | 501 | if (buffer) { |
| 546 | rq->data = buffer; | 502 | error = blk_rq_map_kern(drive->queue, rq, buffer, |
| 547 | rq->data_len = *bufflen; | 503 | *bufflen, GFP_NOIO); |
| 504 | if (error) { | ||
| 505 | blk_put_request(rq); | ||
| 506 | return error; | ||
| 507 | } | ||
| 548 | } | 508 | } |
| 549 | 509 | ||
| 550 | error = blk_execute_rq(drive->queue, info->disk, rq, 0); | 510 | error = blk_execute_rq(drive->queue, info->disk, rq, 0); |
| 551 | 511 | ||
| 552 | if (buffer) | 512 | if (buffer) |
| 553 | *bufflen = rq->data_len; | 513 | *bufflen = rq->resid_len; |
| 554 | 514 | ||
| 555 | flags = rq->cmd_flags; | 515 | flags = rq->cmd_flags; |
| 556 | blk_put_request(rq); | 516 | blk_put_request(rq); |
| @@ -608,7 +568,7 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
| 608 | struct request *rq = hwif->rq; | 568 | struct request *rq = hwif->rq; |
| 609 | ide_expiry_t *expiry = NULL; | 569 | ide_expiry_t *expiry = NULL; |
| 610 | int dma_error = 0, dma, thislen, uptodate = 0; | 570 | int dma_error = 0, dma, thislen, uptodate = 0; |
| 611 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0, nsectors; | 571 | int write = (rq_data_dir(rq) == WRITE) ? 1 : 0, rc = 0; |
| 612 | int sense = blk_sense_request(rq); | 572 | int sense = blk_sense_request(rq); |
| 613 | unsigned int timeout; | 573 | unsigned int timeout; |
| 614 | u16 len; | 574 | u16 len; |
| @@ -738,13 +698,8 @@ static ide_startstop_t cdrom_newpc_intr(ide_drive_t *drive) | |||
| 738 | 698 | ||
| 739 | out_end: | 699 | out_end: |
| 740 | if (blk_pc_request(rq) && rc == 0) { | 700 | if (blk_pc_request(rq) && rc == 0) { |
| 741 | unsigned int dlen = rq->data_len; | 701 | rq->resid_len = 0; |
| 742 | 702 | blk_end_request_all(rq, 0); | |
| 743 | rq->data_len = 0; | ||
| 744 | |||
| 745 | if (blk_end_request(rq, 0, dlen)) | ||
| 746 | BUG(); | ||
| 747 | |||
| 748 | hwif->rq = NULL; | 703 | hwif->rq = NULL; |
| 749 | } else { | 704 | } else { |
| 750 | if (sense && uptodate) | 705 | if (sense && uptodate) |
| @@ -762,21 +717,13 @@ out_end: | |||
| 762 | ide_cd_error_cmd(drive, cmd); | 717 | ide_cd_error_cmd(drive, cmd); |
| 763 | 718 | ||
| 764 | /* make sure it's fully ended */ | 719 | /* make sure it's fully ended */ |
| 765 | if (blk_pc_request(rq)) | ||
| 766 | nsectors = (rq->data_len + 511) >> 9; | ||
| 767 | else | ||
| 768 | nsectors = rq->hard_nr_sectors; | ||
| 769 | |||
| 770 | if (nsectors == 0) | ||
| 771 | nsectors = 1; | ||
| 772 | |||
| 773 | if (blk_fs_request(rq) == 0) { | 720 | if (blk_fs_request(rq) == 0) { |
| 774 | rq->data_len -= (cmd->nbytes - cmd->nleft); | 721 | rq->resid_len -= cmd->nbytes - cmd->nleft; |
| 775 | if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE)) | 722 | if (uptodate == 0 && (cmd->tf_flags & IDE_TFLAG_WRITE)) |
| 776 | rq->data_len += cmd->last_xfer_len; | 723 | rq->resid_len += cmd->last_xfer_len; |
| 777 | } | 724 | } |
| 778 | 725 | ||
| 779 | ide_complete_rq(drive, uptodate ? 0 : -EIO, nsectors << 9); | 726 | ide_complete_rq(drive, uptodate ? 0 : -EIO, blk_rq_bytes(rq)); |
| 780 | 727 | ||
| 781 | if (sense && rc == 2) | 728 | if (sense && rc == 2) |
| 782 | ide_error(drive, "request sense failure", stat); | 729 | ide_error(drive, "request sense failure", stat); |
| @@ -790,7 +737,7 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | |||
| 790 | struct request_queue *q = drive->queue; | 737 | struct request_queue *q = drive->queue; |
| 791 | int write = rq_data_dir(rq) == WRITE; | 738 | int write = rq_data_dir(rq) == WRITE; |
| 792 | unsigned short sectors_per_frame = | 739 | unsigned short sectors_per_frame = |
| 793 | queue_hardsect_size(q) >> SECTOR_BITS; | 740 | queue_logical_block_size(q) >> SECTOR_BITS; |
| 794 | 741 | ||
| 795 | ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, " | 742 | ide_debug_log(IDE_DBG_RQ, "rq->cmd[0]: 0x%x, rq->cmd_flags: 0x%x, " |
| 796 | "secs_per_frame: %u", | 743 | "secs_per_frame: %u", |
| @@ -809,8 +756,8 @@ static ide_startstop_t cdrom_start_rw(ide_drive_t *drive, struct request *rq) | |||
| 809 | } | 756 | } |
| 810 | 757 | ||
| 811 | /* fs requests *must* be hardware frame aligned */ | 758 | /* fs requests *must* be hardware frame aligned */ |
| 812 | if ((rq->nr_sectors & (sectors_per_frame - 1)) || | 759 | if ((blk_rq_sectors(rq) & (sectors_per_frame - 1)) || |
| 813 | (rq->sector & (sectors_per_frame - 1))) | 760 | (blk_rq_pos(rq) & (sectors_per_frame - 1))) |
| 814 | return ide_stopped; | 761 | return ide_stopped; |
| 815 | 762 | ||
| 816 | /* use DMA, if possible */ | 763 | /* use DMA, if possible */ |
| @@ -838,15 +785,10 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | |||
| 838 | drive->dma = 0; | 785 | drive->dma = 0; |
| 839 | 786 | ||
| 840 | /* sg request */ | 787 | /* sg request */ |
| 841 | if (rq->bio || ((rq->cmd_type == REQ_TYPE_ATA_PC) && rq->data_len)) { | 788 | if (rq->bio) { |
| 842 | struct request_queue *q = drive->queue; | 789 | struct request_queue *q = drive->queue; |
| 790 | char *buf = bio_data(rq->bio); | ||
| 843 | unsigned int alignment; | 791 | unsigned int alignment; |
| 844 | char *buf; | ||
| 845 | |||
| 846 | if (rq->bio) | ||
| 847 | buf = bio_data(rq->bio); | ||
| 848 | else | ||
| 849 | buf = rq->data; | ||
| 850 | 792 | ||
| 851 | drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); | 793 | drive->dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); |
| 852 | 794 | ||
| @@ -858,7 +800,7 @@ static void cdrom_do_block_pc(ide_drive_t *drive, struct request *rq) | |||
| 858 | */ | 800 | */ |
| 859 | alignment = queue_dma_alignment(q) | q->dma_pad_mask; | 801 | alignment = queue_dma_alignment(q) | q->dma_pad_mask; |
| 860 | if ((unsigned long)buf & alignment | 802 | if ((unsigned long)buf & alignment |
| 861 | || rq->data_len & q->dma_pad_mask | 803 | || blk_rq_bytes(rq) & q->dma_pad_mask |
| 862 | || object_is_on_stack(buf)) | 804 | || object_is_on_stack(buf)) |
| 863 | drive->dma = 0; | 805 | drive->dma = 0; |
| 864 | } | 806 | } |
| @@ -896,6 +838,9 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
| 896 | goto out_end; | 838 | goto out_end; |
| 897 | } | 839 | } |
| 898 | 840 | ||
| 841 | /* prepare sense request for this command */ | ||
| 842 | ide_prep_sense(drive, rq); | ||
| 843 | |||
| 899 | memset(&cmd, 0, sizeof(cmd)); | 844 | memset(&cmd, 0, sizeof(cmd)); |
| 900 | 845 | ||
| 901 | if (rq_data_dir(rq)) | 846 | if (rq_data_dir(rq)) |
| @@ -903,15 +848,14 @@ static ide_startstop_t ide_cd_do_request(ide_drive_t *drive, struct request *rq, | |||
| 903 | 848 | ||
| 904 | cmd.rq = rq; | 849 | cmd.rq = rq; |
| 905 | 850 | ||
| 906 | if (blk_fs_request(rq) || rq->data_len) { | 851 | if (blk_fs_request(rq) || blk_rq_bytes(rq)) { |
| 907 | ide_init_sg_cmd(&cmd, blk_fs_request(rq) ? (rq->nr_sectors << 9) | 852 | ide_init_sg_cmd(&cmd, blk_rq_bytes(rq)); |
| 908 | : rq->data_len); | ||
| 909 | ide_map_sg(drive, &cmd); | 853 | ide_map_sg(drive, &cmd); |
| 910 | } | 854 | } |
| 911 | 855 | ||
| 912 | return ide_issue_pc(drive, &cmd); | 856 | return ide_issue_pc(drive, &cmd); |
| 913 | out_end: | 857 | out_end: |
| 914 | nsectors = rq->hard_nr_sectors; | 858 | nsectors = blk_rq_sectors(rq); |
| 915 | 859 | ||
| 916 | if (nsectors == 0) | 860 | if (nsectors == 0) |
| 917 | nsectors = 1; | 861 | nsectors = 1; |
| @@ -1077,8 +1021,8 @@ int ide_cd_read_toc(ide_drive_t *drive, struct request_sense *sense) | |||
| 1077 | /* save a private copy of the TOC capacity for error handling */ | 1021 | /* save a private copy of the TOC capacity for error handling */ |
| 1078 | drive->probed_capacity = toc->capacity * sectors_per_frame; | 1022 | drive->probed_capacity = toc->capacity * sectors_per_frame; |
| 1079 | 1023 | ||
| 1080 | blk_queue_hardsect_size(drive->queue, | 1024 | blk_queue_logical_block_size(drive->queue, |
| 1081 | sectors_per_frame << SECTOR_BITS); | 1025 | sectors_per_frame << SECTOR_BITS); |
| 1082 | 1026 | ||
| 1083 | /* first read just the header, so we know how long the TOC is */ | 1027 | /* first read just the header, so we know how long the TOC is */ |
| 1084 | stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, | 1028 | stat = cdrom_read_tocentry(drive, 0, 1, 0, (char *) &toc->hdr, |
| @@ -1394,9 +1338,9 @@ static int ide_cdrom_probe_capabilities(ide_drive_t *drive) | |||
| 1394 | /* standard prep_rq_fn that builds 10 byte cmds */ | 1338 | /* standard prep_rq_fn that builds 10 byte cmds */ |
| 1395 | static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) | 1339 | static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq) |
| 1396 | { | 1340 | { |
| 1397 | int hard_sect = queue_hardsect_size(q); | 1341 | int hard_sect = queue_logical_block_size(q); |
| 1398 | long block = (long)rq->hard_sector / (hard_sect >> 9); | 1342 | long block = (long)blk_rq_pos(rq) / (hard_sect >> 9); |
| 1399 | unsigned long blocks = rq->hard_nr_sectors / (hard_sect >> 9); | 1343 | unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9); |
| 1400 | 1344 | ||
| 1401 | memset(rq->cmd, 0, BLK_MAX_CDB); | 1345 | memset(rq->cmd, 0, BLK_MAX_CDB); |
| 1402 | 1346 | ||
| @@ -1599,7 +1543,7 @@ static int ide_cdrom_setup(ide_drive_t *drive) | |||
| 1599 | 1543 | ||
| 1600 | nslots = ide_cdrom_probe_capabilities(drive); | 1544 | nslots = ide_cdrom_probe_capabilities(drive); |
| 1601 | 1545 | ||
| 1602 | blk_queue_hardsect_size(q, CD_FRAMESIZE); | 1546 | blk_queue_logical_block_size(q, CD_FRAMESIZE); |
| 1603 | 1547 | ||
| 1604 | if (ide_cdrom_register(drive, nslots)) { | 1548 | if (ide_cdrom_register(drive, nslots)) { |
| 1605 | printk(KERN_ERR PFX "%s: %s failed to register device with the" | 1549 | printk(KERN_ERR PFX "%s: %s failed to register device with the" |
diff --git a/drivers/ide/ide-cd.h b/drivers/ide/ide-cd.h index 1d97101099ce..93a3cf1b0f3f 100644 --- a/drivers/ide/ide-cd.h +++ b/drivers/ide/ide-cd.h | |||
| @@ -87,10 +87,6 @@ struct cdrom_info { | |||
| 87 | 87 | ||
| 88 | struct atapi_toc *toc; | 88 | struct atapi_toc *toc; |
| 89 | 89 | ||
| 90 | /* The result of the last successful request sense command | ||
| 91 | on this device. */ | ||
| 92 | struct request_sense sense_data; | ||
| 93 | |||
| 94 | u8 max_speed; /* Max speed of the drive. */ | 90 | u8 max_speed; /* Max speed of the drive. */ |
| 95 | u8 current_speed; /* Current speed of the drive. */ | 91 | u8 current_speed; /* Current speed of the drive. */ |
| 96 | 92 | ||
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index a9fbe2c31210..c6f7fcfb9d67 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c | |||
| @@ -82,7 +82,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
| 82 | sector_t block) | 82 | sector_t block) |
| 83 | { | 83 | { |
| 84 | ide_hwif_t *hwif = drive->hwif; | 84 | ide_hwif_t *hwif = drive->hwif; |
| 85 | u16 nsectors = (u16)rq->nr_sectors; | 85 | u16 nsectors = (u16)blk_rq_sectors(rq); |
| 86 | u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); | 86 | u8 lba48 = !!(drive->dev_flags & IDE_DFLAG_LBA48); |
| 87 | u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); | 87 | u8 dma = !!(drive->dev_flags & IDE_DFLAG_USING_DMA); |
| 88 | struct ide_cmd cmd; | 88 | struct ide_cmd cmd; |
| @@ -90,7 +90,7 @@ static ide_startstop_t __ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
| 90 | ide_startstop_t rc; | 90 | ide_startstop_t rc; |
| 91 | 91 | ||
| 92 | if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) { | 92 | if ((hwif->host_flags & IDE_HFLAG_NO_LBA48_DMA) && lba48 && dma) { |
| 93 | if (block + rq->nr_sectors > 1ULL << 28) | 93 | if (block + blk_rq_sectors(rq) > 1ULL << 28) |
| 94 | dma = 0; | 94 | dma = 0; |
| 95 | else | 95 | else |
| 96 | lba48 = 0; | 96 | lba48 = 0; |
| @@ -195,9 +195,9 @@ static ide_startstop_t ide_do_rw_disk(ide_drive_t *drive, struct request *rq, | |||
| 195 | 195 | ||
| 196 | ledtrig_ide_activity(); | 196 | ledtrig_ide_activity(); |
| 197 | 197 | ||
| 198 | pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", | 198 | pr_debug("%s: %sing: block=%llu, sectors=%u, buffer=0x%08lx\n", |
| 199 | drive->name, rq_data_dir(rq) == READ ? "read" : "writ", | 199 | drive->name, rq_data_dir(rq) == READ ? "read" : "writ", |
| 200 | (unsigned long long)block, rq->nr_sectors, | 200 | (unsigned long long)block, blk_rq_sectors(rq), |
| 201 | (unsigned long)rq->buffer); | 201 | (unsigned long)rq->buffer); |
| 202 | 202 | ||
| 203 | if (hwif->rw_disk) | 203 | if (hwif->rw_disk) |
| @@ -411,7 +411,6 @@ static void idedisk_prepare_flush(struct request_queue *q, struct request *rq) | |||
| 411 | cmd->protocol = ATA_PROT_NODATA; | 411 | cmd->protocol = ATA_PROT_NODATA; |
| 412 | 412 | ||
| 413 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 413 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; |
| 414 | rq->cmd_flags |= REQ_SOFTBARRIER; | ||
| 415 | rq->special = cmd; | 414 | rq->special = cmd; |
| 416 | } | 415 | } |
| 417 | 416 | ||
| @@ -640,7 +639,7 @@ static void ide_disk_setup(ide_drive_t *drive) | |||
| 640 | } | 639 | } |
| 641 | 640 | ||
| 642 | printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, | 641 | printk(KERN_INFO "%s: max request size: %dKiB\n", drive->name, |
| 643 | q->max_sectors / 2); | 642 | queue_max_sectors(q) / 2); |
| 644 | 643 | ||
| 645 | if (ata_id_is_ssd(id)) | 644 | if (ata_id_is_ssd(id)) |
| 646 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); | 645 | queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q); |
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c index a0b8cab1d9a6..001f68f0bb28 100644 --- a/drivers/ide/ide-dma.c +++ b/drivers/ide/ide-dma.c | |||
| @@ -103,7 +103,7 @@ ide_startstop_t ide_dma_intr(ide_drive_t *drive) | |||
| 103 | ide_finish_cmd(drive, cmd, stat); | 103 | ide_finish_cmd(drive, cmd, stat); |
| 104 | else | 104 | else |
| 105 | ide_complete_rq(drive, 0, | 105 | ide_complete_rq(drive, 0, |
| 106 | cmd->rq->nr_sectors << 9); | 106 | blk_rq_sectors(cmd->rq) << 9); |
| 107 | return ide_stopped; | 107 | return ide_stopped; |
| 108 | } | 108 | } |
| 109 | printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n", | 109 | printk(KERN_ERR "%s: %s: bad DMA status (0x%02x)\n", |
| @@ -510,23 +510,11 @@ ide_startstop_t ide_dma_timeout_retry(ide_drive_t *drive, int error) | |||
| 510 | /* | 510 | /* |
| 511 | * un-busy drive etc and make sure request is sane | 511 | * un-busy drive etc and make sure request is sane |
| 512 | */ | 512 | */ |
| 513 | |||
| 514 | rq = hwif->rq; | 513 | rq = hwif->rq; |
| 515 | if (!rq) | 514 | if (rq) { |
| 516 | goto out; | 515 | hwif->rq = NULL; |
| 517 | 516 | rq->errors = 0; | |
| 518 | hwif->rq = NULL; | 517 | } |
| 519 | |||
| 520 | rq->errors = 0; | ||
| 521 | |||
| 522 | if (!rq->bio) | ||
| 523 | goto out; | ||
| 524 | |||
| 525 | rq->sector = rq->bio->bi_sector; | ||
| 526 | rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9; | ||
| 527 | rq->hard_cur_sectors = rq->current_nr_sectors; | ||
| 528 | rq->buffer = bio_data(rq->bio); | ||
| 529 | out: | ||
| 530 | return ret; | 518 | return ret; |
| 531 | } | 519 | } |
| 532 | 520 | ||
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 2b4868d95f8b..650981758f15 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c | |||
| @@ -134,13 +134,17 @@ static ide_startstop_t ide_floppy_issue_pc(ide_drive_t *drive, | |||
| 134 | drive->pc = pc; | 134 | drive->pc = pc; |
| 135 | 135 | ||
| 136 | if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { | 136 | if (pc->retries > IDEFLOPPY_MAX_PC_RETRIES) { |
| 137 | unsigned int done = blk_rq_bytes(drive->hwif->rq); | ||
| 138 | |||
| 137 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) | 139 | if (!(pc->flags & PC_FLAG_SUPPRESS_ERROR)) |
| 138 | ide_floppy_report_error(floppy, pc); | 140 | ide_floppy_report_error(floppy, pc); |
| 141 | |||
| 139 | /* Giving up */ | 142 | /* Giving up */ |
| 140 | pc->error = IDE_DRV_ERROR_GENERAL; | 143 | pc->error = IDE_DRV_ERROR_GENERAL; |
| 141 | 144 | ||
| 142 | drive->failed_pc = NULL; | 145 | drive->failed_pc = NULL; |
| 143 | drive->pc_callback(drive, 0); | 146 | drive->pc_callback(drive, 0); |
| 147 | ide_complete_rq(drive, -EIO, done); | ||
| 144 | return ide_stopped; | 148 | return ide_stopped; |
| 145 | } | 149 | } |
| 146 | 150 | ||
| @@ -190,7 +194,7 @@ static void idefloppy_create_rw_cmd(ide_drive_t *drive, | |||
| 190 | { | 194 | { |
| 191 | struct ide_disk_obj *floppy = drive->driver_data; | 195 | struct ide_disk_obj *floppy = drive->driver_data; |
| 192 | int block = sector / floppy->bs_factor; | 196 | int block = sector / floppy->bs_factor; |
| 193 | int blocks = rq->nr_sectors / floppy->bs_factor; | 197 | int blocks = blk_rq_sectors(rq) / floppy->bs_factor; |
| 194 | int cmd = rq_data_dir(rq); | 198 | int cmd = rq_data_dir(rq); |
| 195 | 199 | ||
| 196 | ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks); | 200 | ide_debug_log(IDE_DBG_FUNC, "block: %d, blocks: %d", block, blocks); |
| @@ -216,16 +220,14 @@ static void idefloppy_blockpc_cmd(struct ide_disk_obj *floppy, | |||
| 216 | ide_init_pc(pc); | 220 | ide_init_pc(pc); |
| 217 | memcpy(pc->c, rq->cmd, sizeof(pc->c)); | 221 | memcpy(pc->c, rq->cmd, sizeof(pc->c)); |
| 218 | pc->rq = rq; | 222 | pc->rq = rq; |
| 219 | if (rq->data_len && rq_data_dir(rq) == WRITE) | 223 | if (blk_rq_bytes(rq)) { |
| 220 | pc->flags |= PC_FLAG_WRITING; | ||
| 221 | pc->buf = rq->data; | ||
| 222 | if (rq->bio) | ||
| 223 | pc->flags |= PC_FLAG_DMA_OK; | 224 | pc->flags |= PC_FLAG_DMA_OK; |
| 224 | /* | 225 | if (rq_data_dir(rq) == WRITE) |
| 225 | * possibly problematic, doesn't look like ide-floppy correctly | 226 | pc->flags |= PC_FLAG_WRITING; |
| 226 | * handled scattered requests if dma fails... | 227 | } |
| 227 | */ | 228 | /* pio will be performed by ide_pio_bytes() which handles sg fine */ |
| 228 | pc->req_xfer = pc->buf_size = rq->data_len; | 229 | pc->buf = NULL; |
| 230 | pc->req_xfer = pc->buf_size = blk_rq_bytes(rq); | ||
| 229 | } | 231 | } |
| 230 | 232 | ||
| 231 | static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | 233 | static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, |
| @@ -257,16 +259,16 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | |||
| 257 | goto out_end; | 259 | goto out_end; |
| 258 | } | 260 | } |
| 259 | if (blk_fs_request(rq)) { | 261 | if (blk_fs_request(rq)) { |
| 260 | if (((long)rq->sector % floppy->bs_factor) || | 262 | if (((long)blk_rq_pos(rq) % floppy->bs_factor) || |
| 261 | (rq->nr_sectors % floppy->bs_factor)) { | 263 | (blk_rq_sectors(rq) % floppy->bs_factor)) { |
| 262 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", | 264 | printk(KERN_ERR PFX "%s: unsupported r/w rq size\n", |
| 263 | drive->name); | 265 | drive->name); |
| 264 | goto out_end; | 266 | goto out_end; |
| 265 | } | 267 | } |
| 266 | pc = &floppy->queued_pc; | 268 | pc = &floppy->queued_pc; |
| 267 | idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); | 269 | idefloppy_create_rw_cmd(drive, pc, rq, (unsigned long)block); |
| 268 | } else if (blk_special_request(rq)) { | 270 | } else if (blk_special_request(rq) || blk_sense_request(rq)) { |
| 269 | pc = (struct ide_atapi_pc *) rq->buffer; | 271 | pc = (struct ide_atapi_pc *)rq->special; |
| 270 | } else if (blk_pc_request(rq)) { | 272 | } else if (blk_pc_request(rq)) { |
| 271 | pc = &floppy->queued_pc; | 273 | pc = &floppy->queued_pc; |
| 272 | idefloppy_blockpc_cmd(floppy, pc, rq); | 274 | idefloppy_blockpc_cmd(floppy, pc, rq); |
| @@ -275,6 +277,8 @@ static ide_startstop_t ide_floppy_do_request(ide_drive_t *drive, | |||
| 275 | goto out_end; | 277 | goto out_end; |
| 276 | } | 278 | } |
| 277 | 279 | ||
| 280 | ide_prep_sense(drive, rq); | ||
| 281 | |||
| 278 | memset(&cmd, 0, sizeof(cmd)); | 282 | memset(&cmd, 0, sizeof(cmd)); |
| 279 | 283 | ||
| 280 | if (rq_data_dir(rq)) | 284 | if (rq_data_dir(rq)) |
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c index 6415a2e2ba87..bba4297f2f03 100644 --- a/drivers/ide/ide-io.c +++ b/drivers/ide/ide-io.c | |||
| @@ -116,9 +116,9 @@ void ide_complete_cmd(ide_drive_t *drive, struct ide_cmd *cmd, u8 stat, u8 err) | |||
| 116 | unsigned int ide_rq_bytes(struct request *rq) | 116 | unsigned int ide_rq_bytes(struct request *rq) |
| 117 | { | 117 | { |
| 118 | if (blk_pc_request(rq)) | 118 | if (blk_pc_request(rq)) |
| 119 | return rq->data_len; | 119 | return blk_rq_bytes(rq); |
| 120 | else | 120 | else |
| 121 | return rq->hard_cur_sectors << 9; | 121 | return blk_rq_cur_sectors(rq) << 9; |
| 122 | } | 122 | } |
| 123 | EXPORT_SYMBOL_GPL(ide_rq_bytes); | 123 | EXPORT_SYMBOL_GPL(ide_rq_bytes); |
| 124 | 124 | ||
| @@ -133,7 +133,7 @@ int ide_complete_rq(ide_drive_t *drive, int error, unsigned int nr_bytes) | |||
| 133 | * and complete the whole request right now | 133 | * and complete the whole request right now |
| 134 | */ | 134 | */ |
| 135 | if (blk_noretry_request(rq) && error <= 0) | 135 | if (blk_noretry_request(rq) && error <= 0) |
| 136 | nr_bytes = rq->hard_nr_sectors << 9; | 136 | nr_bytes = blk_rq_sectors(rq) << 9; |
| 137 | 137 | ||
| 138 | rc = ide_end_rq(drive, rq, error, nr_bytes); | 138 | rc = ide_end_rq(drive, rq, error, nr_bytes); |
| 139 | if (rc == 0) | 139 | if (rc == 0) |
| @@ -248,14 +248,7 @@ void ide_map_sg(ide_drive_t *drive, struct ide_cmd *cmd) | |||
| 248 | struct scatterlist *sg = hwif->sg_table; | 248 | struct scatterlist *sg = hwif->sg_table; |
| 249 | struct request *rq = cmd->rq; | 249 | struct request *rq = cmd->rq; |
| 250 | 250 | ||
| 251 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) { | 251 | cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); |
| 252 | sg_init_one(sg, rq->buffer, rq->nr_sectors * SECTOR_SIZE); | ||
| 253 | cmd->sg_nents = 1; | ||
| 254 | } else if (!rq->bio) { | ||
| 255 | sg_init_one(sg, rq->data, rq->data_len); | ||
| 256 | cmd->sg_nents = 1; | ||
| 257 | } else | ||
| 258 | cmd->sg_nents = blk_rq_map_sg(drive->queue, rq, sg); | ||
| 259 | } | 252 | } |
| 260 | EXPORT_SYMBOL_GPL(ide_map_sg); | 253 | EXPORT_SYMBOL_GPL(ide_map_sg); |
| 261 | 254 | ||
| @@ -286,7 +279,7 @@ static ide_startstop_t execute_drive_cmd (ide_drive_t *drive, | |||
| 286 | 279 | ||
| 287 | if (cmd) { | 280 | if (cmd) { |
| 288 | if (cmd->protocol == ATA_PROT_PIO) { | 281 | if (cmd->protocol == ATA_PROT_PIO) { |
| 289 | ide_init_sg_cmd(cmd, rq->nr_sectors << 9); | 282 | ide_init_sg_cmd(cmd, blk_rq_sectors(rq) << 9); |
| 290 | ide_map_sg(drive, cmd); | 283 | ide_map_sg(drive, cmd); |
| 291 | } | 284 | } |
| 292 | 285 | ||
| @@ -371,7 +364,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
| 371 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) | 364 | if (rq->cmd_type == REQ_TYPE_ATA_TASKFILE) |
| 372 | return execute_drive_cmd(drive, rq); | 365 | return execute_drive_cmd(drive, rq); |
| 373 | else if (blk_pm_request(rq)) { | 366 | else if (blk_pm_request(rq)) { |
| 374 | struct request_pm_state *pm = rq->data; | 367 | struct request_pm_state *pm = rq->special; |
| 375 | #ifdef DEBUG_PM | 368 | #ifdef DEBUG_PM |
| 376 | printk("%s: start_power_step(step: %d)\n", | 369 | printk("%s: start_power_step(step: %d)\n", |
| 377 | drive->name, pm->pm_step); | 370 | drive->name, pm->pm_step); |
| @@ -394,7 +387,7 @@ static ide_startstop_t start_request (ide_drive_t *drive, struct request *rq) | |||
| 394 | 387 | ||
| 395 | drv = *(struct ide_driver **)rq->rq_disk->private_data; | 388 | drv = *(struct ide_driver **)rq->rq_disk->private_data; |
| 396 | 389 | ||
| 397 | return drv->do_request(drive, rq, rq->sector); | 390 | return drv->do_request(drive, rq, blk_rq_pos(rq)); |
| 398 | } | 391 | } |
| 399 | return do_special(drive); | 392 | return do_special(drive); |
| 400 | kill_rq: | 393 | kill_rq: |
| @@ -484,6 +477,9 @@ void do_ide_request(struct request_queue *q) | |||
| 484 | 477 | ||
| 485 | spin_unlock_irq(q->queue_lock); | 478 | spin_unlock_irq(q->queue_lock); |
| 486 | 479 | ||
| 480 | /* HLD do_request() callback might sleep, make sure it's okay */ | ||
| 481 | might_sleep(); | ||
| 482 | |||
| 487 | if (ide_lock_host(host, hwif)) | 483 | if (ide_lock_host(host, hwif)) |
| 488 | goto plug_device_2; | 484 | goto plug_device_2; |
| 489 | 485 | ||
| @@ -491,10 +487,10 @@ void do_ide_request(struct request_queue *q) | |||
| 491 | 487 | ||
| 492 | if (!ide_lock_port(hwif)) { | 488 | if (!ide_lock_port(hwif)) { |
| 493 | ide_hwif_t *prev_port; | 489 | ide_hwif_t *prev_port; |
| 490 | |||
| 491 | WARN_ON_ONCE(hwif->rq); | ||
| 494 | repeat: | 492 | repeat: |
| 495 | prev_port = hwif->host->cur_port; | 493 | prev_port = hwif->host->cur_port; |
| 496 | hwif->rq = NULL; | ||
| 497 | |||
| 498 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && | 494 | if (drive->dev_flags & IDE_DFLAG_SLEEPING && |
| 499 | time_after(drive->sleep, jiffies)) { | 495 | time_after(drive->sleep, jiffies)) { |
| 500 | ide_unlock_port(hwif); | 496 | ide_unlock_port(hwif); |
| @@ -523,7 +519,9 @@ repeat: | |||
| 523 | * we know that the queue isn't empty, but this can happen | 519 | * we know that the queue isn't empty, but this can happen |
| 524 | * if the q->prep_rq_fn() decides to kill a request | 520 | * if the q->prep_rq_fn() decides to kill a request |
| 525 | */ | 521 | */ |
| 526 | rq = elv_next_request(drive->queue); | 522 | if (!rq) |
| 523 | rq = blk_fetch_request(drive->queue); | ||
| 524 | |||
| 527 | spin_unlock_irq(q->queue_lock); | 525 | spin_unlock_irq(q->queue_lock); |
| 528 | spin_lock_irq(&hwif->lock); | 526 | spin_lock_irq(&hwif->lock); |
| 529 | 527 | ||
| @@ -535,7 +533,7 @@ repeat: | |||
| 535 | /* | 533 | /* |
| 536 | * Sanity: don't accept a request that isn't a PM request | 534 | * Sanity: don't accept a request that isn't a PM request |
| 537 | * if we are currently power managed. This is very important as | 535 | * if we are currently power managed. This is very important as |
| 538 | * blk_stop_queue() doesn't prevent the elv_next_request() | 536 | * blk_stop_queue() doesn't prevent the blk_fetch_request() |
| 539 | * above to return us whatever is in the queue. Since we call | 537 | * above to return us whatever is in the queue. Since we call |
| 540 | * ide_do_request() ourselves, we end up taking requests while | 538 | * ide_do_request() ourselves, we end up taking requests while |
| 541 | * the queue is blocked... | 539 | * the queue is blocked... |
| @@ -559,8 +557,11 @@ repeat: | |||
| 559 | startstop = start_request(drive, rq); | 557 | startstop = start_request(drive, rq); |
| 560 | spin_lock_irq(&hwif->lock); | 558 | spin_lock_irq(&hwif->lock); |
| 561 | 559 | ||
| 562 | if (startstop == ide_stopped) | 560 | if (startstop == ide_stopped) { |
| 561 | rq = hwif->rq; | ||
| 562 | hwif->rq = NULL; | ||
| 563 | goto repeat; | 563 | goto repeat; |
| 564 | } | ||
| 564 | } else | 565 | } else |
| 565 | goto plug_device; | 566 | goto plug_device; |
| 566 | out: | 567 | out: |
| @@ -576,18 +577,24 @@ plug_device: | |||
| 576 | plug_device_2: | 577 | plug_device_2: |
| 577 | spin_lock_irq(q->queue_lock); | 578 | spin_lock_irq(q->queue_lock); |
| 578 | 579 | ||
| 580 | if (rq) | ||
| 581 | blk_requeue_request(q, rq); | ||
| 579 | if (!elv_queue_empty(q)) | 582 | if (!elv_queue_empty(q)) |
| 580 | blk_plug_device(q); | 583 | blk_plug_device(q); |
| 581 | } | 584 | } |
| 582 | 585 | ||
| 583 | static void ide_plug_device(ide_drive_t *drive) | 586 | static void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq) |
| 584 | { | 587 | { |
| 585 | struct request_queue *q = drive->queue; | 588 | struct request_queue *q = drive->queue; |
| 586 | unsigned long flags; | 589 | unsigned long flags; |
| 587 | 590 | ||
| 588 | spin_lock_irqsave(q->queue_lock, flags); | 591 | spin_lock_irqsave(q->queue_lock, flags); |
| 592 | |||
| 593 | if (rq) | ||
| 594 | blk_requeue_request(q, rq); | ||
| 589 | if (!elv_queue_empty(q)) | 595 | if (!elv_queue_empty(q)) |
| 590 | blk_plug_device(q); | 596 | blk_plug_device(q); |
| 597 | |||
| 591 | spin_unlock_irqrestore(q->queue_lock, flags); | 598 | spin_unlock_irqrestore(q->queue_lock, flags); |
| 592 | } | 599 | } |
| 593 | 600 | ||
| @@ -636,6 +643,7 @@ void ide_timer_expiry (unsigned long data) | |||
| 636 | unsigned long flags; | 643 | unsigned long flags; |
| 637 | int wait = -1; | 644 | int wait = -1; |
| 638 | int plug_device = 0; | 645 | int plug_device = 0; |
| 646 | struct request *uninitialized_var(rq_in_flight); | ||
| 639 | 647 | ||
| 640 | spin_lock_irqsave(&hwif->lock, flags); | 648 | spin_lock_irqsave(&hwif->lock, flags); |
| 641 | 649 | ||
| @@ -697,6 +705,8 @@ void ide_timer_expiry (unsigned long data) | |||
| 697 | spin_lock_irq(&hwif->lock); | 705 | spin_lock_irq(&hwif->lock); |
| 698 | enable_irq(hwif->irq); | 706 | enable_irq(hwif->irq); |
| 699 | if (startstop == ide_stopped && hwif->polling == 0) { | 707 | if (startstop == ide_stopped && hwif->polling == 0) { |
| 708 | rq_in_flight = hwif->rq; | ||
| 709 | hwif->rq = NULL; | ||
| 700 | ide_unlock_port(hwif); | 710 | ide_unlock_port(hwif); |
| 701 | plug_device = 1; | 711 | plug_device = 1; |
| 702 | } | 712 | } |
| @@ -705,7 +715,7 @@ void ide_timer_expiry (unsigned long data) | |||
| 705 | 715 | ||
| 706 | if (plug_device) { | 716 | if (plug_device) { |
| 707 | ide_unlock_host(hwif->host); | 717 | ide_unlock_host(hwif->host); |
| 708 | ide_plug_device(drive); | 718 | ide_requeue_and_plug(drive, rq_in_flight); |
| 709 | } | 719 | } |
| 710 | } | 720 | } |
| 711 | 721 | ||
| @@ -791,6 +801,7 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
| 791 | ide_startstop_t startstop; | 801 | ide_startstop_t startstop; |
| 792 | irqreturn_t irq_ret = IRQ_NONE; | 802 | irqreturn_t irq_ret = IRQ_NONE; |
| 793 | int plug_device = 0; | 803 | int plug_device = 0; |
| 804 | struct request *uninitialized_var(rq_in_flight); | ||
| 794 | 805 | ||
| 795 | if (host->host_flags & IDE_HFLAG_SERIALIZE) { | 806 | if (host->host_flags & IDE_HFLAG_SERIALIZE) { |
| 796 | if (hwif != host->cur_port) | 807 | if (hwif != host->cur_port) |
| @@ -870,6 +881,8 @@ irqreturn_t ide_intr (int irq, void *dev_id) | |||
| 870 | */ | 881 | */ |
| 871 | if (startstop == ide_stopped && hwif->polling == 0) { | 882 | if (startstop == ide_stopped && hwif->polling == 0) { |
| 872 | BUG_ON(hwif->handler); | 883 | BUG_ON(hwif->handler); |
| 884 | rq_in_flight = hwif->rq; | ||
| 885 | hwif->rq = NULL; | ||
| 873 | ide_unlock_port(hwif); | 886 | ide_unlock_port(hwif); |
| 874 | plug_device = 1; | 887 | plug_device = 1; |
| 875 | } | 888 | } |
| @@ -879,7 +892,7 @@ out: | |||
| 879 | out_early: | 892 | out_early: |
| 880 | if (plug_device) { | 893 | if (plug_device) { |
| 881 | ide_unlock_host(hwif->host); | 894 | ide_unlock_host(hwif->host); |
| 882 | ide_plug_device(drive); | 895 | ide_requeue_and_plug(drive, rq_in_flight); |
| 883 | } | 896 | } |
| 884 | 897 | ||
| 885 | return irq_ret; | 898 | return irq_ret; |
diff --git a/drivers/ide/ide-ioctls.c b/drivers/ide/ide-ioctls.c index c1c25ebbaa1f..5991b23793f2 100644 --- a/drivers/ide/ide-ioctls.c +++ b/drivers/ide/ide-ioctls.c | |||
| @@ -231,7 +231,6 @@ static int generic_drive_reset(ide_drive_t *drive) | |||
| 231 | rq->cmd_type = REQ_TYPE_SPECIAL; | 231 | rq->cmd_type = REQ_TYPE_SPECIAL; |
| 232 | rq->cmd_len = 1; | 232 | rq->cmd_len = 1; |
| 233 | rq->cmd[0] = REQ_DRIVE_RESET; | 233 | rq->cmd[0] = REQ_DRIVE_RESET; |
| 234 | rq->cmd_flags |= REQ_SOFTBARRIER; | ||
| 235 | if (blk_execute_rq(drive->queue, NULL, rq, 1)) | 234 | if (blk_execute_rq(drive->queue, NULL, rq, 1)) |
| 236 | ret = rq->errors; | 235 | ret = rq->errors; |
| 237 | blk_put_request(rq); | 236 | blk_put_request(rq); |
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c index 2148df836ce7..e386a32dc9ba 100644 --- a/drivers/ide/ide-lib.c +++ b/drivers/ide/ide-lib.c | |||
| @@ -96,7 +96,7 @@ static void ide_dump_ata_error(ide_drive_t *drive, u8 err) | |||
| 96 | 96 | ||
| 97 | if (rq) | 97 | if (rq) |
| 98 | printk(KERN_CONT ", sector=%llu", | 98 | printk(KERN_CONT ", sector=%llu", |
| 99 | (unsigned long long)rq->sector); | 99 | (unsigned long long)blk_rq_pos(rq)); |
| 100 | } | 100 | } |
| 101 | printk(KERN_CONT "\n"); | 101 | printk(KERN_CONT "\n"); |
| 102 | } | 102 | } |
diff --git a/drivers/ide/ide-park.c b/drivers/ide/ide-park.c index 310d03f2b5b7..a914023d6d03 100644 --- a/drivers/ide/ide-park.c +++ b/drivers/ide/ide-park.c | |||
| @@ -24,11 +24,8 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout) | |||
| 24 | start_queue = 1; | 24 | start_queue = 1; |
| 25 | spin_unlock_irq(&hwif->lock); | 25 | spin_unlock_irq(&hwif->lock); |
| 26 | 26 | ||
| 27 | if (start_queue) { | 27 | if (start_queue) |
| 28 | spin_lock_irq(q->queue_lock); | 28 | blk_run_queue(q); |
| 29 | blk_start_queueing(q); | ||
| 30 | spin_unlock_irq(q->queue_lock); | ||
| 31 | } | ||
| 32 | return; | 29 | return; |
| 33 | } | 30 | } |
| 34 | spin_unlock_irq(&hwif->lock); | 31 | spin_unlock_irq(&hwif->lock); |
diff --git a/drivers/ide/ide-pci-generic.c b/drivers/ide/ide-pci-generic.c index 61111fd27130..39d4e01f5c9c 100644 --- a/drivers/ide/ide-pci-generic.c +++ b/drivers/ide/ide-pci-generic.c | |||
| @@ -33,6 +33,16 @@ static int ide_generic_all; /* Set to claim all devices */ | |||
| 33 | module_param_named(all_generic_ide, ide_generic_all, bool, 0444); | 33 | module_param_named(all_generic_ide, ide_generic_all, bool, 0444); |
| 34 | MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); | 34 | MODULE_PARM_DESC(all_generic_ide, "IDE generic will claim all unknown PCI IDE storage controllers."); |
| 35 | 35 | ||
| 36 | static void netcell_quirkproc(ide_drive_t *drive) | ||
| 37 | { | ||
| 38 | /* mark words 85-87 as valid */ | ||
| 39 | drive->id[ATA_ID_CSF_DEFAULT] |= 0x4000; | ||
| 40 | } | ||
| 41 | |||
| 42 | static const struct ide_port_ops netcell_port_ops = { | ||
| 43 | .quirkproc = netcell_quirkproc, | ||
| 44 | }; | ||
| 45 | |||
| 36 | #define DECLARE_GENERIC_PCI_DEV(extra_flags) \ | 46 | #define DECLARE_GENERIC_PCI_DEV(extra_flags) \ |
| 37 | { \ | 47 | { \ |
| 38 | .name = DRV_NAME, \ | 48 | .name = DRV_NAME, \ |
| @@ -74,6 +84,7 @@ static const struct ide_port_info generic_chipsets[] __devinitdata = { | |||
| 74 | 84 | ||
| 75 | { /* 6: Revolution */ | 85 | { /* 6: Revolution */ |
| 76 | .name = DRV_NAME, | 86 | .name = DRV_NAME, |
| 87 | .port_ops = &netcell_port_ops, | ||
| 77 | .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | | 88 | .host_flags = IDE_HFLAG_CLEAR_SIMPLEX | |
| 78 | IDE_HFLAG_TRUST_BIOS_FOR_DMA | | 89 | IDE_HFLAG_TRUST_BIOS_FOR_DMA | |
| 79 | IDE_HFLAG_OFF_BOARD, | 90 | IDE_HFLAG_OFF_BOARD, |
diff --git a/drivers/ide/ide-pm.c b/drivers/ide/ide-pm.c index 0d8a151c0a01..ba1488bd8430 100644 --- a/drivers/ide/ide-pm.c +++ b/drivers/ide/ide-pm.c | |||
| @@ -7,7 +7,6 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
| 7 | ide_hwif_t *hwif = drive->hwif; | 7 | ide_hwif_t *hwif = drive->hwif; |
| 8 | struct request *rq; | 8 | struct request *rq; |
| 9 | struct request_pm_state rqpm; | 9 | struct request_pm_state rqpm; |
| 10 | struct ide_cmd cmd; | ||
| 11 | int ret; | 10 | int ret; |
| 12 | 11 | ||
| 13 | /* call ACPI _GTM only once */ | 12 | /* call ACPI _GTM only once */ |
| @@ -15,11 +14,9 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg) | |||
| 15 | ide_acpi_get_timing(hwif); | 14 | ide_acpi_get_timing(hwif); |
| 16 | 15 | ||
| 17 | memset(&rqpm, 0, sizeof(rqpm)); | 16 | memset(&rqpm, 0, sizeof(rqpm)); |
| 18 | memset(&cmd, 0, sizeof(cmd)); | ||
| 19 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 17 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
| 20 | rq->cmd_type = REQ_TYPE_PM_SUSPEND; | 18 | rq->cmd_type = REQ_TYPE_PM_SUSPEND; |
| 21 | rq->special = &cmd; | 19 | rq->special = &rqpm; |
| 22 | rq->data = &rqpm; | ||
| 23 | rqpm.pm_step = IDE_PM_START_SUSPEND; | 20 | rqpm.pm_step = IDE_PM_START_SUSPEND; |
| 24 | if (mesg.event == PM_EVENT_PRETHAW) | 21 | if (mesg.event == PM_EVENT_PRETHAW) |
| 25 | mesg.event = PM_EVENT_FREEZE; | 22 | mesg.event = PM_EVENT_FREEZE; |
| @@ -41,7 +38,6 @@ int generic_ide_resume(struct device *dev) | |||
| 41 | ide_hwif_t *hwif = drive->hwif; | 38 | ide_hwif_t *hwif = drive->hwif; |
| 42 | struct request *rq; | 39 | struct request *rq; |
| 43 | struct request_pm_state rqpm; | 40 | struct request_pm_state rqpm; |
| 44 | struct ide_cmd cmd; | ||
| 45 | int err; | 41 | int err; |
| 46 | 42 | ||
| 47 | /* call ACPI _PS0 / _STM only once */ | 43 | /* call ACPI _PS0 / _STM only once */ |
| @@ -53,12 +49,10 @@ int generic_ide_resume(struct device *dev) | |||
| 53 | ide_acpi_exec_tfs(drive); | 49 | ide_acpi_exec_tfs(drive); |
| 54 | 50 | ||
| 55 | memset(&rqpm, 0, sizeof(rqpm)); | 51 | memset(&rqpm, 0, sizeof(rqpm)); |
| 56 | memset(&cmd, 0, sizeof(cmd)); | ||
| 57 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 52 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
| 58 | rq->cmd_type = REQ_TYPE_PM_RESUME; | 53 | rq->cmd_type = REQ_TYPE_PM_RESUME; |
| 59 | rq->cmd_flags |= REQ_PREEMPT; | 54 | rq->cmd_flags |= REQ_PREEMPT; |
| 60 | rq->special = &cmd; | 55 | rq->special = &rqpm; |
| 61 | rq->data = &rqpm; | ||
| 62 | rqpm.pm_step = IDE_PM_START_RESUME; | 56 | rqpm.pm_step = IDE_PM_START_RESUME; |
| 63 | rqpm.pm_state = PM_EVENT_ON; | 57 | rqpm.pm_state = PM_EVENT_ON; |
| 64 | 58 | ||
| @@ -77,7 +71,7 @@ int generic_ide_resume(struct device *dev) | |||
| 77 | 71 | ||
| 78 | void ide_complete_power_step(ide_drive_t *drive, struct request *rq) | 72 | void ide_complete_power_step(ide_drive_t *drive, struct request *rq) |
| 79 | { | 73 | { |
| 80 | struct request_pm_state *pm = rq->data; | 74 | struct request_pm_state *pm = rq->special; |
| 81 | 75 | ||
| 82 | #ifdef DEBUG_PM | 76 | #ifdef DEBUG_PM |
| 83 | printk(KERN_INFO "%s: complete_power_step(step: %d)\n", | 77 | printk(KERN_INFO "%s: complete_power_step(step: %d)\n", |
| @@ -107,10 +101,8 @@ void ide_complete_power_step(ide_drive_t *drive, struct request *rq) | |||
| 107 | 101 | ||
| 108 | ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | 102 | ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) |
| 109 | { | 103 | { |
| 110 | struct request_pm_state *pm = rq->data; | 104 | struct request_pm_state *pm = rq->special; |
| 111 | struct ide_cmd *cmd = rq->special; | 105 | struct ide_cmd cmd = { }; |
| 112 | |||
| 113 | memset(cmd, 0, sizeof(*cmd)); | ||
| 114 | 106 | ||
| 115 | switch (pm->pm_step) { | 107 | switch (pm->pm_step) { |
| 116 | case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ | 108 | case IDE_PM_FLUSH_CACHE: /* Suspend step 1 (flush cache) */ |
| @@ -123,12 +115,12 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | |||
| 123 | return ide_stopped; | 115 | return ide_stopped; |
| 124 | } | 116 | } |
| 125 | if (ata_id_flush_ext_enabled(drive->id)) | 117 | if (ata_id_flush_ext_enabled(drive->id)) |
| 126 | cmd->tf.command = ATA_CMD_FLUSH_EXT; | 118 | cmd.tf.command = ATA_CMD_FLUSH_EXT; |
| 127 | else | 119 | else |
| 128 | cmd->tf.command = ATA_CMD_FLUSH; | 120 | cmd.tf.command = ATA_CMD_FLUSH; |
| 129 | goto out_do_tf; | 121 | goto out_do_tf; |
| 130 | case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ | 122 | case IDE_PM_STANDBY: /* Suspend step 2 (standby) */ |
| 131 | cmd->tf.command = ATA_CMD_STANDBYNOW1; | 123 | cmd.tf.command = ATA_CMD_STANDBYNOW1; |
| 132 | goto out_do_tf; | 124 | goto out_do_tf; |
| 133 | case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ | 125 | case IDE_PM_RESTORE_PIO: /* Resume step 1 (restore PIO) */ |
| 134 | ide_set_max_pio(drive); | 126 | ide_set_max_pio(drive); |
| @@ -141,7 +133,7 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | |||
| 141 | ide_complete_power_step(drive, rq); | 133 | ide_complete_power_step(drive, rq); |
| 142 | return ide_stopped; | 134 | return ide_stopped; |
| 143 | case IDE_PM_IDLE: /* Resume step 2 (idle) */ | 135 | case IDE_PM_IDLE: /* Resume step 2 (idle) */ |
| 144 | cmd->tf.command = ATA_CMD_IDLEIMMEDIATE; | 136 | cmd.tf.command = ATA_CMD_IDLEIMMEDIATE; |
| 145 | goto out_do_tf; | 137 | goto out_do_tf; |
| 146 | case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ | 138 | case IDE_PM_RESTORE_DMA: /* Resume step 3 (restore DMA) */ |
| 147 | /* | 139 | /* |
| @@ -163,11 +155,11 @@ ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *rq) | |||
| 163 | return ide_stopped; | 155 | return ide_stopped; |
| 164 | 156 | ||
| 165 | out_do_tf: | 157 | out_do_tf: |
| 166 | cmd->valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; | 158 | cmd.valid.out.tf = IDE_VALID_OUT_TF | IDE_VALID_DEVICE; |
| 167 | cmd->valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; | 159 | cmd.valid.in.tf = IDE_VALID_IN_TF | IDE_VALID_DEVICE; |
| 168 | cmd->protocol = ATA_PROT_NODATA; | 160 | cmd.protocol = ATA_PROT_NODATA; |
| 169 | 161 | ||
| 170 | return do_rw_taskfile(drive, cmd); | 162 | return do_rw_taskfile(drive, &cmd); |
| 171 | } | 163 | } |
| 172 | 164 | ||
| 173 | /** | 165 | /** |
| @@ -181,7 +173,7 @@ out_do_tf: | |||
| 181 | void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) | 173 | void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) |
| 182 | { | 174 | { |
| 183 | struct request_queue *q = drive->queue; | 175 | struct request_queue *q = drive->queue; |
| 184 | struct request_pm_state *pm = rq->data; | 176 | struct request_pm_state *pm = rq->special; |
| 185 | unsigned long flags; | 177 | unsigned long flags; |
| 186 | 178 | ||
| 187 | ide_complete_power_step(drive, rq); | 179 | ide_complete_power_step(drive, rq); |
| @@ -207,7 +199,7 @@ void ide_complete_pm_rq(ide_drive_t *drive, struct request *rq) | |||
| 207 | 199 | ||
| 208 | void ide_check_pm_state(ide_drive_t *drive, struct request *rq) | 200 | void ide_check_pm_state(ide_drive_t *drive, struct request *rq) |
| 209 | { | 201 | { |
| 210 | struct request_pm_state *pm = rq->data; | 202 | struct request_pm_state *pm = rq->special; |
| 211 | 203 | ||
| 212 | if (blk_pm_suspend_request(rq) && | 204 | if (blk_pm_suspend_request(rq) && |
| 213 | pm->pm_step == IDE_PM_START_SUSPEND) | 205 | pm->pm_step == IDE_PM_START_SUSPEND) |
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 3a53e0834cf7..d9764f0bc82f 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c | |||
| @@ -131,13 +131,6 @@ enum { | |||
| 131 | IDETAPE_DIR_WRITE = (1 << 2), | 131 | IDETAPE_DIR_WRITE = (1 << 2), |
| 132 | }; | 132 | }; |
| 133 | 133 | ||
| 134 | struct idetape_bh { | ||
| 135 | u32 b_size; | ||
| 136 | atomic_t b_count; | ||
| 137 | struct idetape_bh *b_reqnext; | ||
| 138 | char *b_data; | ||
| 139 | }; | ||
| 140 | |||
| 141 | /* Tape door status */ | 134 | /* Tape door status */ |
| 142 | #define DOOR_UNLOCKED 0 | 135 | #define DOOR_UNLOCKED 0 |
| 143 | #define DOOR_LOCKED 1 | 136 | #define DOOR_LOCKED 1 |
| @@ -219,18 +212,12 @@ typedef struct ide_tape_obj { | |||
| 219 | 212 | ||
| 220 | /* Data buffer size chosen based on the tape's recommendation */ | 213 | /* Data buffer size chosen based on the tape's recommendation */ |
| 221 | int buffer_size; | 214 | int buffer_size; |
| 222 | /* merge buffer */ | 215 | /* Staging buffer of buffer_size bytes */ |
| 223 | struct idetape_bh *merge_bh; | 216 | void *buf; |
| 224 | /* size of the merge buffer */ | 217 | /* The read/write cursor */ |
| 225 | int merge_bh_size; | 218 | void *cur; |
| 226 | /* pointer to current buffer head within the merge buffer */ | 219 | /* The number of valid bytes in buf */ |
| 227 | struct idetape_bh *bh; | 220 | size_t valid; |
| 228 | char *b_data; | ||
| 229 | int b_count; | ||
| 230 | |||
| 231 | int pages_per_buffer; | ||
| 232 | /* Wasted space in each stage */ | ||
| 233 | int excess_bh_size; | ||
| 234 | 221 | ||
| 235 | /* Measures average tape speed */ | 222 | /* Measures average tape speed */ |
| 236 | unsigned long avg_time; | 223 | unsigned long avg_time; |
| @@ -297,84 +284,6 @@ static struct ide_tape_obj *ide_tape_chrdev_get(unsigned int i) | |||
| 297 | return tape; | 284 | return tape; |
| 298 | } | 285 | } |
| 299 | 286 | ||
| 300 | static int idetape_input_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
| 301 | unsigned int bcount) | ||
| 302 | { | ||
| 303 | struct idetape_bh *bh = pc->bh; | ||
| 304 | int count; | ||
| 305 | |||
| 306 | while (bcount) { | ||
| 307 | if (bh == NULL) | ||
| 308 | break; | ||
| 309 | count = min( | ||
| 310 | (unsigned int)(bh->b_size - atomic_read(&bh->b_count)), | ||
| 311 | bcount); | ||
| 312 | drive->hwif->tp_ops->input_data(drive, NULL, bh->b_data + | ||
| 313 | atomic_read(&bh->b_count), count); | ||
| 314 | bcount -= count; | ||
| 315 | atomic_add(count, &bh->b_count); | ||
| 316 | if (atomic_read(&bh->b_count) == bh->b_size) { | ||
| 317 | bh = bh->b_reqnext; | ||
| 318 | if (bh) | ||
| 319 | atomic_set(&bh->b_count, 0); | ||
| 320 | } | ||
| 321 | } | ||
| 322 | |||
| 323 | pc->bh = bh; | ||
| 324 | |||
| 325 | return bcount; | ||
| 326 | } | ||
| 327 | |||
| 328 | static int idetape_output_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
| 329 | unsigned int bcount) | ||
| 330 | { | ||
| 331 | struct idetape_bh *bh = pc->bh; | ||
| 332 | int count; | ||
| 333 | |||
| 334 | while (bcount) { | ||
| 335 | if (bh == NULL) | ||
| 336 | break; | ||
| 337 | count = min((unsigned int)pc->b_count, (unsigned int)bcount); | ||
| 338 | drive->hwif->tp_ops->output_data(drive, NULL, pc->b_data, count); | ||
| 339 | bcount -= count; | ||
| 340 | pc->b_data += count; | ||
| 341 | pc->b_count -= count; | ||
| 342 | if (!pc->b_count) { | ||
| 343 | bh = bh->b_reqnext; | ||
| 344 | pc->bh = bh; | ||
| 345 | if (bh) { | ||
| 346 | pc->b_data = bh->b_data; | ||
| 347 | pc->b_count = atomic_read(&bh->b_count); | ||
| 348 | } | ||
| 349 | } | ||
| 350 | } | ||
| 351 | |||
| 352 | return bcount; | ||
| 353 | } | ||
| 354 | |||
| 355 | static void idetape_update_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc) | ||
| 356 | { | ||
| 357 | struct idetape_bh *bh = pc->bh; | ||
| 358 | int count; | ||
| 359 | unsigned int bcount = pc->xferred; | ||
| 360 | |||
| 361 | if (pc->flags & PC_FLAG_WRITING) | ||
| 362 | return; | ||
| 363 | while (bcount) { | ||
| 364 | if (bh == NULL) { | ||
| 365 | printk(KERN_ERR "ide-tape: bh == NULL in %s\n", | ||
| 366 | __func__); | ||
| 367 | return; | ||
| 368 | } | ||
| 369 | count = min((unsigned int)bh->b_size, (unsigned int)bcount); | ||
| 370 | atomic_set(&bh->b_count, count); | ||
| 371 | if (atomic_read(&bh->b_count) == bh->b_size) | ||
| 372 | bh = bh->b_reqnext; | ||
| 373 | bcount -= count; | ||
| 374 | } | ||
| 375 | pc->bh = bh; | ||
| 376 | } | ||
| 377 | |||
| 378 | /* | 287 | /* |
| 379 | * called on each failed packet command retry to analyze the request sense. We | 288 | * called on each failed packet command retry to analyze the request sense. We |
| 380 | * currently do not utilize this information. | 289 | * currently do not utilize this information. |
| @@ -392,12 +301,10 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) | |||
| 392 | pc->c[0], tape->sense_key, tape->asc, tape->ascq); | 301 | pc->c[0], tape->sense_key, tape->asc, tape->ascq); |
| 393 | 302 | ||
| 394 | /* Correct pc->xferred by asking the tape. */ | 303 | /* Correct pc->xferred by asking the tape. */ |
| 395 | if (pc->flags & PC_FLAG_DMA_ERROR) { | 304 | if (pc->flags & PC_FLAG_DMA_ERROR) |
| 396 | pc->xferred = pc->req_xfer - | 305 | pc->xferred = pc->req_xfer - |
| 397 | tape->blk_size * | 306 | tape->blk_size * |
| 398 | get_unaligned_be32(&sense[3]); | 307 | get_unaligned_be32(&sense[3]); |
| 399 | idetape_update_buffers(drive, pc); | ||
| 400 | } | ||
| 401 | 308 | ||
| 402 | /* | 309 | /* |
| 403 | * If error was the result of a zero-length read or write command, | 310 | * If error was the result of a zero-length read or write command, |
| @@ -436,29 +343,6 @@ static void idetape_analyze_error(ide_drive_t *drive, u8 *sense) | |||
| 436 | } | 343 | } |
| 437 | } | 344 | } |
| 438 | 345 | ||
| 439 | /* Free data buffers completely. */ | ||
| 440 | static void ide_tape_kfree_buffer(idetape_tape_t *tape) | ||
| 441 | { | ||
| 442 | struct idetape_bh *prev_bh, *bh = tape->merge_bh; | ||
| 443 | |||
| 444 | while (bh) { | ||
| 445 | u32 size = bh->b_size; | ||
| 446 | |||
| 447 | while (size) { | ||
| 448 | unsigned int order = fls(size >> PAGE_SHIFT)-1; | ||
| 449 | |||
| 450 | if (bh->b_data) | ||
| 451 | free_pages((unsigned long)bh->b_data, order); | ||
| 452 | |||
| 453 | size &= (order-1); | ||
| 454 | bh->b_data += (1 << order) * PAGE_SIZE; | ||
| 455 | } | ||
| 456 | prev_bh = bh; | ||
| 457 | bh = bh->b_reqnext; | ||
| 458 | kfree(prev_bh); | ||
| 459 | } | ||
| 460 | } | ||
| 461 | |||
| 462 | static void ide_tape_handle_dsc(ide_drive_t *); | 346 | static void ide_tape_handle_dsc(ide_drive_t *); |
| 463 | 347 | ||
| 464 | static int ide_tape_callback(ide_drive_t *drive, int dsc) | 348 | static int ide_tape_callback(ide_drive_t *drive, int dsc) |
| @@ -496,7 +380,7 @@ static int ide_tape_callback(ide_drive_t *drive, int dsc) | |||
| 496 | } | 380 | } |
| 497 | 381 | ||
| 498 | tape->first_frame += blocks; | 382 | tape->first_frame += blocks; |
| 499 | rq->current_nr_sectors -= blocks; | 383 | rq->resid_len -= blocks * tape->blk_size; |
| 500 | 384 | ||
| 501 | if (pc->error) { | 385 | if (pc->error) { |
| 502 | uptodate = 0; | 386 | uptodate = 0; |
| @@ -558,19 +442,6 @@ static void ide_tape_handle_dsc(ide_drive_t *drive) | |||
| 558 | idetape_postpone_request(drive); | 442 | idetape_postpone_request(drive); |
| 559 | } | 443 | } |
| 560 | 444 | ||
| 561 | static int ide_tape_io_buffers(ide_drive_t *drive, struct ide_atapi_pc *pc, | ||
| 562 | unsigned int bcount, int write) | ||
| 563 | { | ||
| 564 | unsigned int bleft; | ||
| 565 | |||
| 566 | if (write) | ||
| 567 | bleft = idetape_output_buffers(drive, pc, bcount); | ||
| 568 | else | ||
| 569 | bleft = idetape_input_buffers(drive, pc, bcount); | ||
| 570 | |||
| 571 | return bcount - bleft; | ||
| 572 | } | ||
| 573 | |||
| 574 | /* | 445 | /* |
| 575 | * Packet Command Interface | 446 | * Packet Command Interface |
| 576 | * | 447 | * |
| @@ -622,6 +493,8 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive, | |||
| 622 | 493 | ||
| 623 | if (pc->retries > IDETAPE_MAX_PC_RETRIES || | 494 | if (pc->retries > IDETAPE_MAX_PC_RETRIES || |
| 624 | (pc->flags & PC_FLAG_ABORT)) { | 495 | (pc->flags & PC_FLAG_ABORT)) { |
| 496 | unsigned int done = blk_rq_bytes(drive->hwif->rq); | ||
| 497 | |||
| 625 | /* | 498 | /* |
| 626 | * We will "abort" retrying a packet command in case legitimate | 499 | * We will "abort" retrying a packet command in case legitimate |
| 627 | * error code was received (crossing a filemark, or end of the | 500 | * error code was received (crossing a filemark, or end of the |
| @@ -641,8 +514,10 @@ static ide_startstop_t ide_tape_issue_pc(ide_drive_t *drive, | |||
| 641 | /* Giving up */ | 514 | /* Giving up */ |
| 642 | pc->error = IDE_DRV_ERROR_GENERAL; | 515 | pc->error = IDE_DRV_ERROR_GENERAL; |
| 643 | } | 516 | } |
| 517 | |||
| 644 | drive->failed_pc = NULL; | 518 | drive->failed_pc = NULL; |
| 645 | drive->pc_callback(drive, 0); | 519 | drive->pc_callback(drive, 0); |
| 520 | ide_complete_rq(drive, -EIO, done); | ||
| 646 | return ide_stopped; | 521 | return ide_stopped; |
| 647 | } | 522 | } |
| 648 | debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]); | 523 | debug_log(DBG_SENSE, "Retry #%d, cmd = %02X\n", pc->retries, pc->c[0]); |
| @@ -695,7 +570,7 @@ static ide_startstop_t idetape_media_access_finished(ide_drive_t *drive) | |||
| 695 | printk(KERN_ERR "ide-tape: %s: I/O error, ", | 570 | printk(KERN_ERR "ide-tape: %s: I/O error, ", |
| 696 | tape->name); | 571 | tape->name); |
| 697 | /* Retry operation */ | 572 | /* Retry operation */ |
| 698 | ide_retry_pc(drive, tape->disk); | 573 | ide_retry_pc(drive); |
| 699 | return ide_stopped; | 574 | return ide_stopped; |
| 700 | } | 575 | } |
| 701 | pc->error = 0; | 576 | pc->error = 0; |
| @@ -711,27 +586,22 @@ static void ide_tape_create_rw_cmd(idetape_tape_t *tape, | |||
| 711 | struct ide_atapi_pc *pc, struct request *rq, | 586 | struct ide_atapi_pc *pc, struct request *rq, |
| 712 | u8 opcode) | 587 | u8 opcode) |
| 713 | { | 588 | { |
| 714 | struct idetape_bh *bh = (struct idetape_bh *)rq->special; | 589 | unsigned int length = blk_rq_sectors(rq); |
| 715 | unsigned int length = rq->current_nr_sectors; | ||
| 716 | 590 | ||
| 717 | ide_init_pc(pc); | 591 | ide_init_pc(pc); |
| 718 | put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); | 592 | put_unaligned(cpu_to_be32(length), (unsigned int *) &pc->c[1]); |
| 719 | pc->c[1] = 1; | 593 | pc->c[1] = 1; |
| 720 | pc->bh = bh; | ||
| 721 | pc->buf = NULL; | 594 | pc->buf = NULL; |
| 722 | pc->buf_size = length * tape->blk_size; | 595 | pc->buf_size = length * tape->blk_size; |
| 723 | pc->req_xfer = pc->buf_size; | 596 | pc->req_xfer = pc->buf_size; |
| 724 | if (pc->req_xfer == tape->buffer_size) | 597 | if (pc->req_xfer == tape->buffer_size) |
| 725 | pc->flags |= PC_FLAG_DMA_OK; | 598 | pc->flags |= PC_FLAG_DMA_OK; |
| 726 | 599 | ||
| 727 | if (opcode == READ_6) { | 600 | if (opcode == READ_6) |
| 728 | pc->c[0] = READ_6; | 601 | pc->c[0] = READ_6; |
| 729 | atomic_set(&bh->b_count, 0); | 602 | else if (opcode == WRITE_6) { |
| 730 | } else if (opcode == WRITE_6) { | ||
| 731 | pc->c[0] = WRITE_6; | 603 | pc->c[0] = WRITE_6; |
| 732 | pc->flags |= PC_FLAG_WRITING; | 604 | pc->flags |= PC_FLAG_WRITING; |
| 733 | pc->b_data = bh->b_data; | ||
| 734 | pc->b_count = atomic_read(&bh->b_count); | ||
| 735 | } | 605 | } |
| 736 | 606 | ||
| 737 | memcpy(rq->cmd, pc->c, 12); | 607 | memcpy(rq->cmd, pc->c, 12); |
| @@ -747,12 +617,10 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
| 747 | struct ide_cmd cmd; | 617 | struct ide_cmd cmd; |
| 748 | u8 stat; | 618 | u8 stat; |
| 749 | 619 | ||
| 750 | debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %lu," | 620 | debug_log(DBG_SENSE, "sector: %llu, nr_sectors: %u\n" |
| 751 | " current_nr_sectors: %u\n", | 621 | (unsigned long long)blk_rq_pos(rq), blk_rq_sectors(rq)); |
| 752 | (unsigned long long)rq->sector, rq->nr_sectors, | ||
| 753 | rq->current_nr_sectors); | ||
| 754 | 622 | ||
| 755 | if (!blk_special_request(rq)) { | 623 | if (!(blk_special_request(rq) || blk_sense_request(rq))) { |
| 756 | /* We do not support buffer cache originated requests. */ | 624 | /* We do not support buffer cache originated requests. */ |
| 757 | printk(KERN_NOTICE "ide-tape: %s: Unsupported request in " | 625 | printk(KERN_NOTICE "ide-tape: %s: Unsupported request in " |
| 758 | "request queue (%d)\n", drive->name, rq->cmd_type); | 626 | "request queue (%d)\n", drive->name, rq->cmd_type); |
| @@ -828,7 +696,7 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
| 828 | goto out; | 696 | goto out; |
| 829 | } | 697 | } |
| 830 | if (rq->cmd[13] & REQ_IDETAPE_PC1) { | 698 | if (rq->cmd[13] & REQ_IDETAPE_PC1) { |
| 831 | pc = (struct ide_atapi_pc *) rq->buffer; | 699 | pc = (struct ide_atapi_pc *)rq->special; |
| 832 | rq->cmd[13] &= ~(REQ_IDETAPE_PC1); | 700 | rq->cmd[13] &= ~(REQ_IDETAPE_PC1); |
| 833 | rq->cmd[13] |= REQ_IDETAPE_PC2; | 701 | rq->cmd[13] |= REQ_IDETAPE_PC2; |
| 834 | goto out; | 702 | goto out; |
| @@ -840,6 +708,9 @@ static ide_startstop_t idetape_do_request(ide_drive_t *drive, | |||
| 840 | BUG(); | 708 | BUG(); |
| 841 | 709 | ||
| 842 | out: | 710 | out: |
| 711 | /* prepare sense request for this command */ | ||
| 712 | ide_prep_sense(drive, rq); | ||
| 713 | |||
| 843 | memset(&cmd, 0, sizeof(cmd)); | 714 | memset(&cmd, 0, sizeof(cmd)); |
| 844 | 715 | ||
| 845 | if (rq_data_dir(rq)) | 716 | if (rq_data_dir(rq)) |
| @@ -847,167 +718,10 @@ out: | |||
| 847 | 718 | ||
| 848 | cmd.rq = rq; | 719 | cmd.rq = rq; |
| 849 | 720 | ||
| 850 | return ide_tape_issue_pc(drive, &cmd, pc); | 721 | ide_init_sg_cmd(&cmd, pc->req_xfer); |
| 851 | } | 722 | ide_map_sg(drive, &cmd); |
| 852 | |||
| 853 | /* | ||
| 854 | * The function below uses __get_free_pages to allocate a data buffer of size | ||
| 855 | * tape->buffer_size (or a bit more). We attempt to combine sequential pages as | ||
| 856 | * much as possible. | ||
| 857 | * | ||
| 858 | * It returns a pointer to the newly allocated buffer, or NULL in case of | ||
| 859 | * failure. | ||
| 860 | */ | ||
| 861 | static struct idetape_bh *ide_tape_kmalloc_buffer(idetape_tape_t *tape, | ||
| 862 | int full, int clear) | ||
| 863 | { | ||
| 864 | struct idetape_bh *prev_bh, *bh, *merge_bh; | ||
| 865 | int pages = tape->pages_per_buffer; | ||
| 866 | unsigned int order, b_allocd; | ||
| 867 | char *b_data = NULL; | ||
| 868 | |||
| 869 | merge_bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); | ||
| 870 | bh = merge_bh; | ||
| 871 | if (bh == NULL) | ||
| 872 | goto abort; | ||
| 873 | |||
| 874 | order = fls(pages) - 1; | ||
| 875 | bh->b_data = (char *) __get_free_pages(GFP_KERNEL, order); | ||
| 876 | if (!bh->b_data) | ||
| 877 | goto abort; | ||
| 878 | b_allocd = (1 << order) * PAGE_SIZE; | ||
| 879 | pages &= (order-1); | ||
| 880 | |||
| 881 | if (clear) | ||
| 882 | memset(bh->b_data, 0, b_allocd); | ||
| 883 | bh->b_reqnext = NULL; | ||
| 884 | bh->b_size = b_allocd; | ||
| 885 | atomic_set(&bh->b_count, full ? bh->b_size : 0); | ||
| 886 | |||
| 887 | while (pages) { | ||
| 888 | order = fls(pages) - 1; | ||
| 889 | b_data = (char *) __get_free_pages(GFP_KERNEL, order); | ||
| 890 | if (!b_data) | ||
| 891 | goto abort; | ||
| 892 | b_allocd = (1 << order) * PAGE_SIZE; | ||
| 893 | |||
| 894 | if (clear) | ||
| 895 | memset(b_data, 0, b_allocd); | ||
| 896 | |||
| 897 | /* newly allocated page frames below buffer header or ...*/ | ||
| 898 | if (bh->b_data == b_data + b_allocd) { | ||
| 899 | bh->b_size += b_allocd; | ||
| 900 | bh->b_data -= b_allocd; | ||
| 901 | if (full) | ||
| 902 | atomic_add(b_allocd, &bh->b_count); | ||
| 903 | continue; | ||
| 904 | } | ||
| 905 | /* they are above the header */ | ||
| 906 | if (b_data == bh->b_data + bh->b_size) { | ||
| 907 | bh->b_size += b_allocd; | ||
| 908 | if (full) | ||
| 909 | atomic_add(b_allocd, &bh->b_count); | ||
| 910 | continue; | ||
| 911 | } | ||
| 912 | prev_bh = bh; | ||
| 913 | bh = kmalloc(sizeof(struct idetape_bh), GFP_KERNEL); | ||
| 914 | if (!bh) { | ||
| 915 | free_pages((unsigned long) b_data, order); | ||
| 916 | goto abort; | ||
| 917 | } | ||
| 918 | bh->b_reqnext = NULL; | ||
| 919 | bh->b_data = b_data; | ||
| 920 | bh->b_size = b_allocd; | ||
| 921 | atomic_set(&bh->b_count, full ? bh->b_size : 0); | ||
| 922 | prev_bh->b_reqnext = bh; | ||
| 923 | |||
| 924 | pages &= (order-1); | ||
| 925 | } | ||
| 926 | |||
| 927 | bh->b_size -= tape->excess_bh_size; | ||
| 928 | if (full) | ||
| 929 | atomic_sub(tape->excess_bh_size, &bh->b_count); | ||
| 930 | return merge_bh; | ||
| 931 | abort: | ||
| 932 | ide_tape_kfree_buffer(tape); | ||
| 933 | return NULL; | ||
| 934 | } | ||
| 935 | 723 | ||
| 936 | static int idetape_copy_stage_from_user(idetape_tape_t *tape, | 724 | return ide_tape_issue_pc(drive, &cmd, pc); |
| 937 | const char __user *buf, int n) | ||
| 938 | { | ||
| 939 | struct idetape_bh *bh = tape->bh; | ||
| 940 | int count; | ||
| 941 | int ret = 0; | ||
| 942 | |||
| 943 | while (n) { | ||
| 944 | if (bh == NULL) { | ||
| 945 | printk(KERN_ERR "ide-tape: bh == NULL in %s\n", | ||
| 946 | __func__); | ||
| 947 | return 1; | ||
| 948 | } | ||
| 949 | count = min((unsigned int) | ||
| 950 | (bh->b_size - atomic_read(&bh->b_count)), | ||
| 951 | (unsigned int)n); | ||
| 952 | if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, | ||
| 953 | count)) | ||
| 954 | ret = 1; | ||
| 955 | n -= count; | ||
| 956 | atomic_add(count, &bh->b_count); | ||
| 957 | buf += count; | ||
| 958 | if (atomic_read(&bh->b_count) == bh->b_size) { | ||
| 959 | bh = bh->b_reqnext; | ||
| 960 | if (bh) | ||
| 961 | atomic_set(&bh->b_count, 0); | ||
| 962 | } | ||
| 963 | } | ||
| 964 | tape->bh = bh; | ||
| 965 | return ret; | ||
| 966 | } | ||
| 967 | |||
| 968 | static int idetape_copy_stage_to_user(idetape_tape_t *tape, char __user *buf, | ||
| 969 | int n) | ||
| 970 | { | ||
| 971 | struct idetape_bh *bh = tape->bh; | ||
| 972 | int count; | ||
| 973 | int ret = 0; | ||
| 974 | |||
| 975 | while (n) { | ||
| 976 | if (bh == NULL) { | ||
| 977 | printk(KERN_ERR "ide-tape: bh == NULL in %s\n", | ||
| 978 | __func__); | ||
| 979 | return 1; | ||
| 980 | } | ||
| 981 | count = min(tape->b_count, n); | ||
| 982 | if (copy_to_user(buf, tape->b_data, count)) | ||
| 983 | ret = 1; | ||
| 984 | n -= count; | ||
| 985 | tape->b_data += count; | ||
| 986 | tape->b_count -= count; | ||
| 987 | buf += count; | ||
| 988 | if (!tape->b_count) { | ||
| 989 | bh = bh->b_reqnext; | ||
| 990 | tape->bh = bh; | ||
| 991 | if (bh) { | ||
| 992 | tape->b_data = bh->b_data; | ||
| 993 | tape->b_count = atomic_read(&bh->b_count); | ||
| 994 | } | ||
| 995 | } | ||
| 996 | } | ||
| 997 | return ret; | ||
| 998 | } | ||
| 999 | |||
| 1000 | static void idetape_init_merge_buffer(idetape_tape_t *tape) | ||
| 1001 | { | ||
| 1002 | struct idetape_bh *bh = tape->merge_bh; | ||
| 1003 | tape->bh = tape->merge_bh; | ||
| 1004 | |||
| 1005 | if (tape->chrdev_dir == IDETAPE_DIR_WRITE) | ||
| 1006 | atomic_set(&bh->b_count, 0); | ||
| 1007 | else { | ||
| 1008 | tape->b_data = bh->b_data; | ||
| 1009 | tape->b_count = atomic_read(&bh->b_count); | ||
| 1010 | } | ||
| 1011 | } | 725 | } |
| 1012 | 726 | ||
| 1013 | /* | 727 | /* |
| @@ -1107,10 +821,10 @@ static void __ide_tape_discard_merge_buffer(ide_drive_t *drive) | |||
| 1107 | return; | 821 | return; |
| 1108 | 822 | ||
| 1109 | clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags); | 823 | clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags); |
| 1110 | tape->merge_bh_size = 0; | 824 | tape->valid = 0; |
| 1111 | if (tape->merge_bh != NULL) { | 825 | if (tape->buf != NULL) { |
| 1112 | ide_tape_kfree_buffer(tape); | 826 | kfree(tape->buf); |
| 1113 | tape->merge_bh = NULL; | 827 | tape->buf = NULL; |
| 1114 | } | 828 | } |
| 1115 | 829 | ||
| 1116 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 830 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
| @@ -1164,36 +878,44 @@ static void ide_tape_discard_merge_buffer(ide_drive_t *drive, | |||
| 1164 | * Generate a read/write request for the block device interface and wait for it | 878 | * Generate a read/write request for the block device interface and wait for it |
| 1165 | * to be serviced. | 879 | * to be serviced. |
| 1166 | */ | 880 | */ |
| 1167 | static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int blocks, | 881 | static int idetape_queue_rw_tail(ide_drive_t *drive, int cmd, int size) |
| 1168 | struct idetape_bh *bh) | ||
| 1169 | { | 882 | { |
| 1170 | idetape_tape_t *tape = drive->driver_data; | 883 | idetape_tape_t *tape = drive->driver_data; |
| 1171 | struct request *rq; | 884 | struct request *rq; |
| 1172 | int ret, errors; | 885 | int ret; |
| 1173 | 886 | ||
| 1174 | debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd); | 887 | debug_log(DBG_SENSE, "%s: cmd=%d\n", __func__, cmd); |
| 888 | BUG_ON(cmd != REQ_IDETAPE_READ && cmd != REQ_IDETAPE_WRITE); | ||
| 889 | BUG_ON(size < 0 || size % tape->blk_size); | ||
| 1175 | 890 | ||
| 1176 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 891 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
| 1177 | rq->cmd_type = REQ_TYPE_SPECIAL; | 892 | rq->cmd_type = REQ_TYPE_SPECIAL; |
| 1178 | rq->cmd[13] = cmd; | 893 | rq->cmd[13] = cmd; |
| 1179 | rq->rq_disk = tape->disk; | 894 | rq->rq_disk = tape->disk; |
| 1180 | rq->special = (void *)bh; | 895 | rq->__sector = tape->first_frame; |
| 1181 | rq->sector = tape->first_frame; | ||
| 1182 | rq->nr_sectors = blocks; | ||
| 1183 | rq->current_nr_sectors = blocks; | ||
| 1184 | blk_execute_rq(drive->queue, tape->disk, rq, 0); | ||
| 1185 | 896 | ||
| 1186 | errors = rq->errors; | 897 | if (size) { |
| 1187 | ret = tape->blk_size * (blocks - rq->current_nr_sectors); | 898 | ret = blk_rq_map_kern(drive->queue, rq, tape->buf, size, |
| 1188 | blk_put_request(rq); | 899 | __GFP_WAIT); |
| 900 | if (ret) | ||
| 901 | goto out_put; | ||
| 902 | } | ||
| 1189 | 903 | ||
| 1190 | if ((cmd & (REQ_IDETAPE_READ | REQ_IDETAPE_WRITE)) == 0) | 904 | blk_execute_rq(drive->queue, tape->disk, rq, 0); |
| 1191 | return 0; | ||
| 1192 | 905 | ||
| 1193 | if (tape->merge_bh) | 906 | /* calculate the number of transferred bytes and update buffer state */ |
| 1194 | idetape_init_merge_buffer(tape); | 907 | size -= rq->resid_len; |
| 1195 | if (errors == IDE_DRV_ERROR_GENERAL) | 908 | tape->cur = tape->buf; |
| 1196 | return -EIO; | 909 | if (cmd == REQ_IDETAPE_READ) |
| 910 | tape->valid = size; | ||
| 911 | else | ||
| 912 | tape->valid = 0; | ||
| 913 | |||
| 914 | ret = size; | ||
| 915 | if (rq->errors == IDE_DRV_ERROR_GENERAL) | ||
| 916 | ret = -EIO; | ||
| 917 | out_put: | ||
| 918 | blk_put_request(rq); | ||
| 1197 | return ret; | 919 | return ret; |
| 1198 | } | 920 | } |
| 1199 | 921 | ||
| @@ -1230,153 +952,87 @@ static void idetape_create_space_cmd(struct ide_atapi_pc *pc, int count, u8 cmd) | |||
| 1230 | pc->flags |= PC_FLAG_WAIT_FOR_DSC; | 952 | pc->flags |= PC_FLAG_WAIT_FOR_DSC; |
| 1231 | } | 953 | } |
| 1232 | 954 | ||
| 1233 | /* Queue up a character device originated write request. */ | ||
| 1234 | static int idetape_add_chrdev_write_request(ide_drive_t *drive, int blocks) | ||
| 1235 | { | ||
| 1236 | idetape_tape_t *tape = drive->driver_data; | ||
| 1237 | |||
| 1238 | debug_log(DBG_CHRDEV, "Enter %s\n", __func__); | ||
| 1239 | |||
| 1240 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, | ||
| 1241 | blocks, tape->merge_bh); | ||
| 1242 | } | ||
| 1243 | |||
| 1244 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) | 955 | static void ide_tape_flush_merge_buffer(ide_drive_t *drive) |
| 1245 | { | 956 | { |
| 1246 | idetape_tape_t *tape = drive->driver_data; | 957 | idetape_tape_t *tape = drive->driver_data; |
| 1247 | int blocks, min; | ||
| 1248 | struct idetape_bh *bh; | ||
| 1249 | 958 | ||
| 1250 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { | 959 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { |
| 1251 | printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer" | 960 | printk(KERN_ERR "ide-tape: bug: Trying to empty merge buffer" |
| 1252 | " but we are not writing.\n"); | 961 | " but we are not writing.\n"); |
| 1253 | return; | 962 | return; |
| 1254 | } | 963 | } |
| 1255 | if (tape->merge_bh_size > tape->buffer_size) { | 964 | if (tape->buf) { |
| 1256 | printk(KERN_ERR "ide-tape: bug: merge_buffer too big\n"); | 965 | size_t aligned = roundup(tape->valid, tape->blk_size); |
| 1257 | tape->merge_bh_size = tape->buffer_size; | 966 | |
| 1258 | } | 967 | memset(tape->cur, 0, aligned - tape->valid); |
| 1259 | if (tape->merge_bh_size) { | 968 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, aligned); |
| 1260 | blocks = tape->merge_bh_size / tape->blk_size; | 969 | kfree(tape->buf); |
| 1261 | if (tape->merge_bh_size % tape->blk_size) { | 970 | tape->buf = NULL; |
| 1262 | unsigned int i; | ||
| 1263 | |||
| 1264 | blocks++; | ||
| 1265 | i = tape->blk_size - tape->merge_bh_size % | ||
| 1266 | tape->blk_size; | ||
| 1267 | bh = tape->bh->b_reqnext; | ||
| 1268 | while (bh) { | ||
| 1269 | atomic_set(&bh->b_count, 0); | ||
| 1270 | bh = bh->b_reqnext; | ||
| 1271 | } | ||
| 1272 | bh = tape->bh; | ||
| 1273 | while (i) { | ||
| 1274 | if (bh == NULL) { | ||
| 1275 | printk(KERN_INFO "ide-tape: bug," | ||
| 1276 | " bh NULL\n"); | ||
| 1277 | break; | ||
| 1278 | } | ||
| 1279 | min = min(i, (unsigned int)(bh->b_size - | ||
| 1280 | atomic_read(&bh->b_count))); | ||
| 1281 | memset(bh->b_data + atomic_read(&bh->b_count), | ||
| 1282 | 0, min); | ||
| 1283 | atomic_add(min, &bh->b_count); | ||
| 1284 | i -= min; | ||
| 1285 | bh = bh->b_reqnext; | ||
| 1286 | } | ||
| 1287 | } | ||
| 1288 | (void) idetape_add_chrdev_write_request(drive, blocks); | ||
| 1289 | tape->merge_bh_size = 0; | ||
| 1290 | } | ||
| 1291 | if (tape->merge_bh != NULL) { | ||
| 1292 | ide_tape_kfree_buffer(tape); | ||
| 1293 | tape->merge_bh = NULL; | ||
| 1294 | } | 971 | } |
| 1295 | tape->chrdev_dir = IDETAPE_DIR_NONE; | 972 | tape->chrdev_dir = IDETAPE_DIR_NONE; |
| 1296 | } | 973 | } |
| 1297 | 974 | ||
| 1298 | static int idetape_init_read(ide_drive_t *drive) | 975 | static int idetape_init_rw(ide_drive_t *drive, int dir) |
| 1299 | { | 976 | { |
| 1300 | idetape_tape_t *tape = drive->driver_data; | 977 | idetape_tape_t *tape = drive->driver_data; |
| 1301 | int bytes_read; | 978 | int rc; |
| 1302 | 979 | ||
| 1303 | /* Initialize read operation */ | 980 | BUG_ON(dir != IDETAPE_DIR_READ && dir != IDETAPE_DIR_WRITE); |
| 1304 | if (tape->chrdev_dir != IDETAPE_DIR_READ) { | ||
| 1305 | if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { | ||
| 1306 | ide_tape_flush_merge_buffer(drive); | ||
| 1307 | idetape_flush_tape_buffers(drive); | ||
| 1308 | } | ||
| 1309 | if (tape->merge_bh || tape->merge_bh_size) { | ||
| 1310 | printk(KERN_ERR "ide-tape: merge_bh_size should be" | ||
| 1311 | " 0 now\n"); | ||
| 1312 | tape->merge_bh_size = 0; | ||
| 1313 | } | ||
| 1314 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); | ||
| 1315 | if (!tape->merge_bh) | ||
| 1316 | return -ENOMEM; | ||
| 1317 | tape->chrdev_dir = IDETAPE_DIR_READ; | ||
| 1318 | 981 | ||
| 1319 | /* | 982 | if (tape->chrdev_dir == dir) |
| 1320 | * Issue a read 0 command to ensure that DSC handshake is | 983 | return 0; |
| 1321 | * switched from completion mode to buffer available mode. | ||
| 1322 | * No point in issuing this if DSC overlap isn't supported, some | ||
| 1323 | * drives (Seagate STT3401A) will return an error. | ||
| 1324 | */ | ||
| 1325 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | ||
| 1326 | bytes_read = idetape_queue_rw_tail(drive, | ||
| 1327 | REQ_IDETAPE_READ, 0, | ||
| 1328 | tape->merge_bh); | ||
| 1329 | if (bytes_read < 0) { | ||
| 1330 | ide_tape_kfree_buffer(tape); | ||
| 1331 | tape->merge_bh = NULL; | ||
| 1332 | tape->chrdev_dir = IDETAPE_DIR_NONE; | ||
| 1333 | return bytes_read; | ||
| 1334 | } | ||
| 1335 | } | ||
| 1336 | } | ||
| 1337 | 984 | ||
| 1338 | return 0; | 985 | if (tape->chrdev_dir == IDETAPE_DIR_READ) |
| 1339 | } | 986 | ide_tape_discard_merge_buffer(drive, 1); |
| 987 | else if (tape->chrdev_dir == IDETAPE_DIR_WRITE) { | ||
| 988 | ide_tape_flush_merge_buffer(drive); | ||
| 989 | idetape_flush_tape_buffers(drive); | ||
| 990 | } | ||
| 1340 | 991 | ||
| 1341 | /* called from idetape_chrdev_read() to service a chrdev read request. */ | 992 | if (tape->buf || tape->valid) { |
| 1342 | static int idetape_add_chrdev_read_request(ide_drive_t *drive, int blocks) | 993 | printk(KERN_ERR "ide-tape: valid should be 0 now\n"); |
| 1343 | { | 994 | tape->valid = 0; |
| 1344 | idetape_tape_t *tape = drive->driver_data; | 995 | } |
| 1345 | 996 | ||
| 1346 | debug_log(DBG_PROCS, "Enter %s, %d blocks\n", __func__, blocks); | 997 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); |
| 998 | if (!tape->buf) | ||
| 999 | return -ENOMEM; | ||
| 1000 | tape->chrdev_dir = dir; | ||
| 1001 | tape->cur = tape->buf; | ||
| 1347 | 1002 | ||
| 1348 | /* If we are at a filemark, return a read length of 0 */ | 1003 | /* |
| 1349 | if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) | 1004 | * Issue a 0 rw command to ensure that DSC handshake is |
| 1350 | return 0; | 1005 | * switched from completion mode to buffer available mode. No |
| 1351 | 1006 | * point in issuing this if DSC overlap isn't supported, some | |
| 1352 | idetape_init_read(drive); | 1007 | * drives (Seagate STT3401A) will return an error. |
| 1008 | */ | ||
| 1009 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | ||
| 1010 | int cmd = dir == IDETAPE_DIR_READ ? REQ_IDETAPE_READ | ||
| 1011 | : REQ_IDETAPE_WRITE; | ||
| 1012 | |||
| 1013 | rc = idetape_queue_rw_tail(drive, cmd, 0); | ||
| 1014 | if (rc < 0) { | ||
| 1015 | kfree(tape->buf); | ||
| 1016 | tape->buf = NULL; | ||
| 1017 | tape->chrdev_dir = IDETAPE_DIR_NONE; | ||
| 1018 | return rc; | ||
| 1019 | } | ||
| 1020 | } | ||
| 1353 | 1021 | ||
| 1354 | return idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, blocks, | 1022 | return 0; |
| 1355 | tape->merge_bh); | ||
| 1356 | } | 1023 | } |
| 1357 | 1024 | ||
| 1358 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) | 1025 | static void idetape_pad_zeros(ide_drive_t *drive, int bcount) |
| 1359 | { | 1026 | { |
| 1360 | idetape_tape_t *tape = drive->driver_data; | 1027 | idetape_tape_t *tape = drive->driver_data; |
| 1361 | struct idetape_bh *bh; | 1028 | |
| 1362 | int blocks; | 1029 | memset(tape->buf, 0, tape->buffer_size); |
| 1363 | 1030 | ||
| 1364 | while (bcount) { | 1031 | while (bcount) { |
| 1365 | unsigned int count; | 1032 | unsigned int count = min(tape->buffer_size, bcount); |
| 1366 | 1033 | ||
| 1367 | bh = tape->merge_bh; | 1034 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, count); |
| 1368 | count = min(tape->buffer_size, bcount); | ||
| 1369 | bcount -= count; | 1035 | bcount -= count; |
| 1370 | blocks = count / tape->blk_size; | ||
| 1371 | while (count) { | ||
| 1372 | atomic_set(&bh->b_count, | ||
| 1373 | min(count, (unsigned int)bh->b_size)); | ||
| 1374 | memset(bh->b_data, 0, atomic_read(&bh->b_count)); | ||
| 1375 | count -= atomic_read(&bh->b_count); | ||
| 1376 | bh = bh->b_reqnext; | ||
| 1377 | } | ||
| 1378 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, blocks, | ||
| 1379 | tape->merge_bh); | ||
| 1380 | } | 1036 | } |
| 1381 | } | 1037 | } |
| 1382 | 1038 | ||
| @@ -1456,7 +1112,7 @@ static int idetape_space_over_filemarks(ide_drive_t *drive, short mt_op, | |||
| 1456 | } | 1112 | } |
| 1457 | 1113 | ||
| 1458 | if (tape->chrdev_dir == IDETAPE_DIR_READ) { | 1114 | if (tape->chrdev_dir == IDETAPE_DIR_READ) { |
| 1459 | tape->merge_bh_size = 0; | 1115 | tape->valid = 0; |
| 1460 | if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) | 1116 | if (test_and_clear_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) |
| 1461 | ++count; | 1117 | ++count; |
| 1462 | ide_tape_discard_merge_buffer(drive, 0); | 1118 | ide_tape_discard_merge_buffer(drive, 0); |
| @@ -1505,9 +1161,9 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
| 1505 | { | 1161 | { |
| 1506 | struct ide_tape_obj *tape = file->private_data; | 1162 | struct ide_tape_obj *tape = file->private_data; |
| 1507 | ide_drive_t *drive = tape->drive; | 1163 | ide_drive_t *drive = tape->drive; |
| 1508 | ssize_t bytes_read, temp, actually_read = 0, rc; | 1164 | size_t done = 0; |
| 1509 | ssize_t ret = 0; | 1165 | ssize_t ret = 0; |
| 1510 | u16 ctl = *(u16 *)&tape->caps[12]; | 1166 | int rc; |
| 1511 | 1167 | ||
| 1512 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); | 1168 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); |
| 1513 | 1169 | ||
| @@ -1517,49 +1173,43 @@ static ssize_t idetape_chrdev_read(struct file *file, char __user *buf, | |||
| 1517 | (count % tape->blk_size) == 0) | 1173 | (count % tape->blk_size) == 0) |
| 1518 | tape->user_bs_factor = count / tape->blk_size; | 1174 | tape->user_bs_factor = count / tape->blk_size; |
| 1519 | } | 1175 | } |
| 1520 | rc = idetape_init_read(drive); | 1176 | |
| 1177 | rc = idetape_init_rw(drive, IDETAPE_DIR_READ); | ||
| 1521 | if (rc < 0) | 1178 | if (rc < 0) |
| 1522 | return rc; | 1179 | return rc; |
| 1523 | if (count == 0) | 1180 | |
| 1524 | return (0); | 1181 | while (done < count) { |
| 1525 | if (tape->merge_bh_size) { | 1182 | size_t todo; |
| 1526 | actually_read = min((unsigned int)(tape->merge_bh_size), | 1183 | |
| 1527 | (unsigned int)count); | 1184 | /* refill if staging buffer is empty */ |
| 1528 | if (idetape_copy_stage_to_user(tape, buf, actually_read)) | 1185 | if (!tape->valid) { |
| 1529 | ret = -EFAULT; | 1186 | /* If we are at a filemark, nothing more to read */ |
| 1530 | buf += actually_read; | 1187 | if (test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) |
| 1531 | tape->merge_bh_size -= actually_read; | 1188 | break; |
| 1532 | count -= actually_read; | 1189 | /* read */ |
| 1533 | } | 1190 | if (idetape_queue_rw_tail(drive, REQ_IDETAPE_READ, |
| 1534 | while (count >= tape->buffer_size) { | 1191 | tape->buffer_size) <= 0) |
| 1535 | bytes_read = idetape_add_chrdev_read_request(drive, ctl); | 1192 | break; |
| 1536 | if (bytes_read <= 0) | 1193 | } |
| 1537 | goto finish; | 1194 | |
| 1538 | if (idetape_copy_stage_to_user(tape, buf, bytes_read)) | 1195 | /* copy out */ |
| 1539 | ret = -EFAULT; | 1196 | todo = min_t(size_t, count - done, tape->valid); |
| 1540 | buf += bytes_read; | 1197 | if (copy_to_user(buf + done, tape->cur, todo)) |
| 1541 | count -= bytes_read; | ||
| 1542 | actually_read += bytes_read; | ||
| 1543 | } | ||
| 1544 | if (count) { | ||
| 1545 | bytes_read = idetape_add_chrdev_read_request(drive, ctl); | ||
| 1546 | if (bytes_read <= 0) | ||
| 1547 | goto finish; | ||
| 1548 | temp = min((unsigned long)count, (unsigned long)bytes_read); | ||
| 1549 | if (idetape_copy_stage_to_user(tape, buf, temp)) | ||
| 1550 | ret = -EFAULT; | 1198 | ret = -EFAULT; |
| 1551 | actually_read += temp; | 1199 | |
| 1552 | tape->merge_bh_size = bytes_read-temp; | 1200 | tape->cur += todo; |
| 1201 | tape->valid -= todo; | ||
| 1202 | done += todo; | ||
| 1553 | } | 1203 | } |
| 1554 | finish: | 1204 | |
| 1555 | if (!actually_read && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { | 1205 | if (!done && test_bit(IDE_AFLAG_FILEMARK, &drive->atapi_flags)) { |
| 1556 | debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); | 1206 | debug_log(DBG_SENSE, "%s: spacing over filemark\n", tape->name); |
| 1557 | 1207 | ||
| 1558 | idetape_space_over_filemarks(drive, MTFSF, 1); | 1208 | idetape_space_over_filemarks(drive, MTFSF, 1); |
| 1559 | return 0; | 1209 | return 0; |
| 1560 | } | 1210 | } |
| 1561 | 1211 | ||
| 1562 | return ret ? ret : actually_read; | 1212 | return ret ? ret : done; |
| 1563 | } | 1213 | } |
| 1564 | 1214 | ||
| 1565 | static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | 1215 | static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, |
| @@ -1567,9 +1217,9 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
| 1567 | { | 1217 | { |
| 1568 | struct ide_tape_obj *tape = file->private_data; | 1218 | struct ide_tape_obj *tape = file->private_data; |
| 1569 | ide_drive_t *drive = tape->drive; | 1219 | ide_drive_t *drive = tape->drive; |
| 1570 | ssize_t actually_written = 0; | 1220 | size_t done = 0; |
| 1571 | ssize_t ret = 0; | 1221 | ssize_t ret = 0; |
| 1572 | u16 ctl = *(u16 *)&tape->caps[12]; | 1222 | int rc; |
| 1573 | 1223 | ||
| 1574 | /* The drive is write protected. */ | 1224 | /* The drive is write protected. */ |
| 1575 | if (tape->write_prot) | 1225 | if (tape->write_prot) |
| @@ -1578,80 +1228,31 @@ static ssize_t idetape_chrdev_write(struct file *file, const char __user *buf, | |||
| 1578 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); | 1228 | debug_log(DBG_CHRDEV, "Enter %s, count %Zd\n", __func__, count); |
| 1579 | 1229 | ||
| 1580 | /* Initialize write operation */ | 1230 | /* Initialize write operation */ |
| 1581 | if (tape->chrdev_dir != IDETAPE_DIR_WRITE) { | 1231 | rc = idetape_init_rw(drive, IDETAPE_DIR_WRITE); |
| 1582 | if (tape->chrdev_dir == IDETAPE_DIR_READ) | 1232 | if (rc < 0) |
| 1583 | ide_tape_discard_merge_buffer(drive, 1); | 1233 | return rc; |
| 1584 | if (tape->merge_bh || tape->merge_bh_size) { | ||
| 1585 | printk(KERN_ERR "ide-tape: merge_bh_size " | ||
| 1586 | "should be 0 now\n"); | ||
| 1587 | tape->merge_bh_size = 0; | ||
| 1588 | } | ||
| 1589 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 0, 0); | ||
| 1590 | if (!tape->merge_bh) | ||
| 1591 | return -ENOMEM; | ||
| 1592 | tape->chrdev_dir = IDETAPE_DIR_WRITE; | ||
| 1593 | idetape_init_merge_buffer(tape); | ||
| 1594 | 1234 | ||
| 1595 | /* | 1235 | while (done < count) { |
| 1596 | * Issue a write 0 command to ensure that DSC handshake is | 1236 | size_t todo; |
| 1597 | * switched from completion mode to buffer available mode. No | 1237 | |
| 1598 | * point in issuing this if DSC overlap isn't supported, some | 1238 | /* flush if staging buffer is full */ |
| 1599 | * drives (Seagate STT3401A) will return an error. | 1239 | if (tape->valid == tape->buffer_size && |
| 1600 | */ | 1240 | idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, |
| 1601 | if (drive->dev_flags & IDE_DFLAG_DSC_OVERLAP) { | 1241 | tape->buffer_size) <= 0) |
| 1602 | ssize_t retval = idetape_queue_rw_tail(drive, | 1242 | return rc; |
| 1603 | REQ_IDETAPE_WRITE, 0, | 1243 | |
| 1604 | tape->merge_bh); | 1244 | /* copy in */ |
| 1605 | if (retval < 0) { | 1245 | todo = min_t(size_t, count - done, |
| 1606 | ide_tape_kfree_buffer(tape); | 1246 | tape->buffer_size - tape->valid); |
| 1607 | tape->merge_bh = NULL; | 1247 | if (copy_from_user(tape->cur, buf + done, todo)) |
| 1608 | tape->chrdev_dir = IDETAPE_DIR_NONE; | ||
| 1609 | return retval; | ||
| 1610 | } | ||
| 1611 | } | ||
| 1612 | } | ||
| 1613 | if (count == 0) | ||
| 1614 | return (0); | ||
| 1615 | if (tape->merge_bh_size) { | ||
| 1616 | if (tape->merge_bh_size >= tape->buffer_size) { | ||
| 1617 | printk(KERN_ERR "ide-tape: bug: merge buf too big\n"); | ||
| 1618 | tape->merge_bh_size = 0; | ||
| 1619 | } | ||
| 1620 | actually_written = min((unsigned int) | ||
| 1621 | (tape->buffer_size - tape->merge_bh_size), | ||
| 1622 | (unsigned int)count); | ||
| 1623 | if (idetape_copy_stage_from_user(tape, buf, actually_written)) | ||
| 1624 | ret = -EFAULT; | ||
| 1625 | buf += actually_written; | ||
| 1626 | tape->merge_bh_size += actually_written; | ||
| 1627 | count -= actually_written; | ||
| 1628 | |||
| 1629 | if (tape->merge_bh_size == tape->buffer_size) { | ||
| 1630 | ssize_t retval; | ||
| 1631 | tape->merge_bh_size = 0; | ||
| 1632 | retval = idetape_add_chrdev_write_request(drive, ctl); | ||
| 1633 | if (retval <= 0) | ||
| 1634 | return (retval); | ||
| 1635 | } | ||
| 1636 | } | ||
| 1637 | while (count >= tape->buffer_size) { | ||
| 1638 | ssize_t retval; | ||
| 1639 | if (idetape_copy_stage_from_user(tape, buf, tape->buffer_size)) | ||
| 1640 | ret = -EFAULT; | ||
| 1641 | buf += tape->buffer_size; | ||
| 1642 | count -= tape->buffer_size; | ||
| 1643 | retval = idetape_add_chrdev_write_request(drive, ctl); | ||
| 1644 | actually_written += tape->buffer_size; | ||
| 1645 | if (retval <= 0) | ||
| 1646 | return (retval); | ||
| 1647 | } | ||
| 1648 | if (count) { | ||
| 1649 | actually_written += count; | ||
| 1650 | if (idetape_copy_stage_from_user(tape, buf, count)) | ||
| 1651 | ret = -EFAULT; | 1248 | ret = -EFAULT; |
| 1652 | tape->merge_bh_size += count; | 1249 | |
| 1250 | tape->cur += todo; | ||
| 1251 | tape->valid += todo; | ||
| 1252 | done += todo; | ||
| 1653 | } | 1253 | } |
| 1654 | return ret ? ret : actually_written; | 1254 | |
| 1255 | return ret ? ret : done; | ||
| 1655 | } | 1256 | } |
| 1656 | 1257 | ||
| 1657 | static int idetape_write_filemark(ide_drive_t *drive) | 1258 | static int idetape_write_filemark(ide_drive_t *drive) |
| @@ -1812,7 +1413,7 @@ static int idetape_chrdev_ioctl(struct inode *inode, struct file *file, | |||
| 1812 | idetape_flush_tape_buffers(drive); | 1413 | idetape_flush_tape_buffers(drive); |
| 1813 | } | 1414 | } |
| 1814 | if (cmd == MTIOCGET || cmd == MTIOCPOS) { | 1415 | if (cmd == MTIOCGET || cmd == MTIOCPOS) { |
| 1815 | block_offset = tape->merge_bh_size / | 1416 | block_offset = tape->valid / |
| 1816 | (tape->blk_size * tape->user_bs_factor); | 1417 | (tape->blk_size * tape->user_bs_factor); |
| 1817 | position = idetape_read_position(drive); | 1418 | position = idetape_read_position(drive); |
| 1818 | if (position < 0) | 1419 | if (position < 0) |
| @@ -1960,12 +1561,12 @@ static void idetape_write_release(ide_drive_t *drive, unsigned int minor) | |||
| 1960 | idetape_tape_t *tape = drive->driver_data; | 1561 | idetape_tape_t *tape = drive->driver_data; |
| 1961 | 1562 | ||
| 1962 | ide_tape_flush_merge_buffer(drive); | 1563 | ide_tape_flush_merge_buffer(drive); |
| 1963 | tape->merge_bh = ide_tape_kmalloc_buffer(tape, 1, 0); | 1564 | tape->buf = kmalloc(tape->buffer_size, GFP_KERNEL); |
| 1964 | if (tape->merge_bh != NULL) { | 1565 | if (tape->buf != NULL) { |
| 1965 | idetape_pad_zeros(drive, tape->blk_size * | 1566 | idetape_pad_zeros(drive, tape->blk_size * |
| 1966 | (tape->user_bs_factor - 1)); | 1567 | (tape->user_bs_factor - 1)); |
| 1967 | ide_tape_kfree_buffer(tape); | 1568 | kfree(tape->buf); |
| 1968 | tape->merge_bh = NULL; | 1569 | tape->buf = NULL; |
| 1969 | } | 1570 | } |
| 1970 | idetape_write_filemark(drive); | 1571 | idetape_write_filemark(drive); |
| 1971 | idetape_flush_tape_buffers(drive); | 1572 | idetape_flush_tape_buffers(drive); |
| @@ -2159,8 +1760,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) | |||
| 2159 | u16 *ctl = (u16 *)&tape->caps[12]; | 1760 | u16 *ctl = (u16 *)&tape->caps[12]; |
| 2160 | 1761 | ||
| 2161 | drive->pc_callback = ide_tape_callback; | 1762 | drive->pc_callback = ide_tape_callback; |
| 2162 | drive->pc_update_buffers = idetape_update_buffers; | ||
| 2163 | drive->pc_io_buffers = ide_tape_io_buffers; | ||
| 2164 | 1763 | ||
| 2165 | drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP; | 1764 | drive->dev_flags |= IDE_DFLAG_DSC_OVERLAP; |
| 2166 | 1765 | ||
| @@ -2191,11 +1790,6 @@ static void idetape_setup(ide_drive_t *drive, idetape_tape_t *tape, int minor) | |||
| 2191 | tape->buffer_size = *ctl * tape->blk_size; | 1790 | tape->buffer_size = *ctl * tape->blk_size; |
| 2192 | } | 1791 | } |
| 2193 | buffer_size = tape->buffer_size; | 1792 | buffer_size = tape->buffer_size; |
| 2194 | tape->pages_per_buffer = buffer_size / PAGE_SIZE; | ||
| 2195 | if (buffer_size % PAGE_SIZE) { | ||
| 2196 | tape->pages_per_buffer++; | ||
| 2197 | tape->excess_bh_size = PAGE_SIZE - buffer_size % PAGE_SIZE; | ||
| 2198 | } | ||
| 2199 | 1793 | ||
| 2200 | /* select the "best" DSC read/write polling freq */ | 1794 | /* select the "best" DSC read/write polling freq */ |
| 2201 | speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]); | 1795 | speed = max(*(u16 *)&tape->caps[14], *(u16 *)&tape->caps[8]); |
| @@ -2238,7 +1832,7 @@ static void ide_tape_release(struct device *dev) | |||
| 2238 | ide_drive_t *drive = tape->drive; | 1832 | ide_drive_t *drive = tape->drive; |
| 2239 | struct gendisk *g = tape->disk; | 1833 | struct gendisk *g = tape->disk; |
| 2240 | 1834 | ||
| 2241 | BUG_ON(tape->merge_bh_size); | 1835 | BUG_ON(tape->valid); |
| 2242 | 1836 | ||
| 2243 | drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; | 1837 | drive->dev_flags &= ~IDE_DFLAG_DSC_OVERLAP; |
| 2244 | drive->driver_data = NULL; | 1838 | drive->driver_data = NULL; |
diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 4aa6223c11be..a0c3e1b2f73c 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c | |||
| @@ -385,7 +385,7 @@ out_end: | |||
| 385 | if ((cmd->tf_flags & IDE_TFLAG_FS) == 0) | 385 | if ((cmd->tf_flags & IDE_TFLAG_FS) == 0) |
| 386 | ide_finish_cmd(drive, cmd, stat); | 386 | ide_finish_cmd(drive, cmd, stat); |
| 387 | else | 387 | else |
| 388 | ide_complete_rq(drive, 0, cmd->rq->nr_sectors << 9); | 388 | ide_complete_rq(drive, 0, blk_rq_sectors(cmd->rq) << 9); |
| 389 | return ide_stopped; | 389 | return ide_stopped; |
| 390 | out_err: | 390 | out_err: |
| 391 | ide_error_cmd(drive, cmd); | 391 | ide_error_cmd(drive, cmd); |
| @@ -424,7 +424,9 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf, | |||
| 424 | 424 | ||
| 425 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); | 425 | rq = blk_get_request(drive->queue, READ, __GFP_WAIT); |
| 426 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; | 426 | rq->cmd_type = REQ_TYPE_ATA_TASKFILE; |
| 427 | rq->buffer = buf; | 427 | |
| 428 | if (cmd->tf_flags & IDE_TFLAG_WRITE) | ||
| 429 | rq->cmd_flags |= REQ_RW; | ||
| 428 | 430 | ||
| 429 | /* | 431 | /* |
| 430 | * (ks) We transfer currently only whole sectors. | 432 | * (ks) We transfer currently only whole sectors. |
| @@ -432,18 +434,20 @@ int ide_raw_taskfile(ide_drive_t *drive, struct ide_cmd *cmd, u8 *buf, | |||
| 432 | * if we would find a solution to transfer any size. | 434 | * if we would find a solution to transfer any size. |
| 433 | * To support special commands like READ LONG. | 435 | * To support special commands like READ LONG. |
| 434 | */ | 436 | */ |
| 435 | rq->hard_nr_sectors = rq->nr_sectors = nsect; | 437 | if (nsect) { |
| 436 | rq->hard_cur_sectors = rq->current_nr_sectors = nsect; | 438 | error = blk_rq_map_kern(drive->queue, rq, buf, |
| 437 | 439 | nsect * SECTOR_SIZE, __GFP_WAIT); | |
| 438 | if (cmd->tf_flags & IDE_TFLAG_WRITE) | 440 | if (error) |
| 439 | rq->cmd_flags |= REQ_RW; | 441 | goto put_req; |
| 442 | } | ||
| 440 | 443 | ||
| 441 | rq->special = cmd; | 444 | rq->special = cmd; |
| 442 | cmd->rq = rq; | 445 | cmd->rq = rq; |
| 443 | 446 | ||
| 444 | error = blk_execute_rq(drive->queue, NULL, rq, 0); | 447 | error = blk_execute_rq(drive->queue, NULL, rq, 0); |
| 445 | blk_put_request(rq); | ||
| 446 | 448 | ||
| 449 | put_req: | ||
| 450 | blk_put_request(rq); | ||
| 447 | return error; | 451 | return error; |
| 448 | } | 452 | } |
| 449 | 453 | ||
diff --git a/drivers/ide/pdc202xx_old.c b/drivers/ide/pdc202xx_old.c index 248a54bd2386..e24ecc87a9b1 100644 --- a/drivers/ide/pdc202xx_old.c +++ b/drivers/ide/pdc202xx_old.c | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> | 2 | * Copyright (C) 1998-2002 Andre Hedrick <andre@linux-ide.org> |
| 3 | * Copyright (C) 2006-2007 MontaVista Software, Inc. | 3 | * Copyright (C) 2006-2007, 2009 MontaVista Software, Inc. |
| 4 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz | 4 | * Copyright (C) 2007 Bartlomiej Zolnierkiewicz |
| 5 | * | 5 | * |
| 6 | * Portions Copyright (C) 1999 Promise Technology, Inc. | 6 | * Portions Copyright (C) 1999 Promise Technology, Inc. |
| @@ -177,7 +177,7 @@ static void pdc202xx_dma_start(ide_drive_t *drive) | |||
| 177 | u8 clock = inb(high_16 + 0x11); | 177 | u8 clock = inb(high_16 + 0x11); |
| 178 | 178 | ||
| 179 | outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11); | 179 | outb(clock | (hwif->channel ? 0x08 : 0x02), high_16 + 0x11); |
| 180 | word_count = (rq->nr_sectors << 8); | 180 | word_count = (blk_rq_sectors(rq) << 8); |
| 181 | word_count = (rq_data_dir(rq) == READ) ? | 181 | word_count = (rq_data_dir(rq) == READ) ? |
| 182 | word_count | 0x05000000 : | 182 | word_count | 0x05000000 : |
| 183 | word_count | 0x06000000; | 183 | word_count | 0x06000000; |
| @@ -227,28 +227,19 @@ somebody_else: | |||
| 227 | return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ | 227 | return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ |
| 228 | } | 228 | } |
| 229 | 229 | ||
| 230 | static void pdc202xx_reset_host (ide_hwif_t *hwif) | 230 | static void pdc202xx_reset(ide_drive_t *drive) |
| 231 | { | 231 | { |
| 232 | ide_hwif_t *hwif = drive->hwif; | ||
| 232 | unsigned long high_16 = hwif->extra_base - 16; | 233 | unsigned long high_16 = hwif->extra_base - 16; |
| 233 | u8 udma_speed_flag = inb(high_16 | 0x001f); | 234 | u8 udma_speed_flag = inb(high_16 | 0x001f); |
| 234 | 235 | ||
| 236 | printk(KERN_WARNING "PDC202xx: software reset...\n"); | ||
| 237 | |||
| 235 | outb(udma_speed_flag | 0x10, high_16 | 0x001f); | 238 | outb(udma_speed_flag | 0x10, high_16 | 0x001f); |
| 236 | mdelay(100); | 239 | mdelay(100); |
| 237 | outb(udma_speed_flag & ~0x10, high_16 | 0x001f); | 240 | outb(udma_speed_flag & ~0x10, high_16 | 0x001f); |
| 238 | mdelay(2000); /* 2 seconds ?! */ | 241 | mdelay(2000); /* 2 seconds ?! */ |
| 239 | 242 | ||
| 240 | printk(KERN_WARNING "PDC202XX: %s channel reset.\n", | ||
| 241 | hwif->channel ? "Secondary" : "Primary"); | ||
| 242 | } | ||
| 243 | |||
| 244 | static void pdc202xx_reset (ide_drive_t *drive) | ||
| 245 | { | ||
| 246 | ide_hwif_t *hwif = drive->hwif; | ||
| 247 | ide_hwif_t *mate = hwif->mate; | ||
| 248 | |||
| 249 | pdc202xx_reset_host(hwif); | ||
| 250 | pdc202xx_reset_host(mate); | ||
| 251 | |||
| 252 | ide_set_max_pio(drive); | 243 | ide_set_max_pio(drive); |
| 253 | } | 244 | } |
| 254 | 245 | ||
| @@ -328,9 +319,8 @@ static const struct ide_dma_ops pdc20246_dma_ops = { | |||
| 328 | .dma_start = ide_dma_start, | 319 | .dma_start = ide_dma_start, |
| 329 | .dma_end = ide_dma_end, | 320 | .dma_end = ide_dma_end, |
| 330 | .dma_test_irq = pdc202xx_dma_test_irq, | 321 | .dma_test_irq = pdc202xx_dma_test_irq, |
| 331 | .dma_lost_irq = pdc202xx_dma_lost_irq, | 322 | .dma_lost_irq = ide_dma_lost_irq, |
| 332 | .dma_timer_expiry = ide_dma_sff_timer_expiry, | 323 | .dma_timer_expiry = ide_dma_sff_timer_expiry, |
| 333 | .dma_clear = pdc202xx_reset, | ||
| 334 | .dma_sff_read_status = ide_dma_sff_read_status, | 324 | .dma_sff_read_status = ide_dma_sff_read_status, |
| 335 | }; | 325 | }; |
| 336 | 326 | ||
diff --git a/drivers/ide/tc86c001.c b/drivers/ide/tc86c001.c index b4cf42dc8a6f..05a93d6baecc 100644 --- a/drivers/ide/tc86c001.c +++ b/drivers/ide/tc86c001.c | |||
| @@ -112,7 +112,7 @@ static void tc86c001_dma_start(ide_drive_t *drive) | |||
| 112 | ide_hwif_t *hwif = drive->hwif; | 112 | ide_hwif_t *hwif = drive->hwif; |
| 113 | unsigned long sc_base = hwif->config_data; | 113 | unsigned long sc_base = hwif->config_data; |
| 114 | unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); | 114 | unsigned long twcr_port = sc_base + (drive->dn ? 0x06 : 0x04); |
| 115 | unsigned long nsectors = hwif->rq->nr_sectors; | 115 | unsigned long nsectors = blk_rq_sectors(hwif->rq); |
| 116 | 116 | ||
| 117 | /* | 117 | /* |
| 118 | * We have to manually load the sector count and size into | 118 | * We have to manually load the sector count and size into |
diff --git a/drivers/ide/tx4939ide.c b/drivers/ide/tx4939ide.c index 564422d23976..5ca76224f6d1 100644 --- a/drivers/ide/tx4939ide.c +++ b/drivers/ide/tx4939ide.c | |||
| @@ -307,7 +307,7 @@ static int tx4939ide_dma_setup(ide_drive_t *drive, struct ide_cmd *cmd) | |||
| 307 | tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ? | 307 | tx4939ide_writew(SECTOR_SIZE / 2, base, drive->dn ? |
| 308 | TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1); | 308 | TX4939IDE_Xfer_Cnt_2 : TX4939IDE_Xfer_Cnt_1); |
| 309 | 309 | ||
| 310 | tx4939ide_writew(cmd->rq->nr_sectors, base, TX4939IDE_Sec_Cnt); | 310 | tx4939ide_writew(blk_rq_sectors(cmd->rq), base, TX4939IDE_Sec_Cnt); |
| 311 | 311 | ||
| 312 | return 0; | 312 | return 0; |
| 313 | } | 313 | } |
diff --git a/drivers/idle/i7300_idle.c b/drivers/idle/i7300_idle.c index bf740394d704..949c97ff57e3 100644 --- a/drivers/idle/i7300_idle.c +++ b/drivers/idle/i7300_idle.c | |||
| @@ -41,6 +41,10 @@ static int debug; | |||
| 41 | module_param_named(debug, debug, uint, 0644); | 41 | module_param_named(debug, debug, uint, 0644); |
| 42 | MODULE_PARM_DESC(debug, "Enable debug printks in this driver"); | 42 | MODULE_PARM_DESC(debug, "Enable debug printks in this driver"); |
| 43 | 43 | ||
| 44 | static int forceload; | ||
| 45 | module_param_named(forceload, forceload, uint, 0644); | ||
| 46 | MODULE_PARM_DESC(debug, "Enable driver testing on unvalidated i5000"); | ||
| 47 | |||
| 44 | #define dprintk(fmt, arg...) \ | 48 | #define dprintk(fmt, arg...) \ |
| 45 | do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0) | 49 | do { if (debug) printk(KERN_INFO I7300_PRINT fmt, ##arg); } while (0) |
| 46 | 50 | ||
| @@ -552,7 +556,7 @@ static int __init i7300_idle_init(void) | |||
| 552 | cpus_clear(idle_cpumask); | 556 | cpus_clear(idle_cpumask); |
| 553 | total_us = 0; | 557 | total_us = 0; |
| 554 | 558 | ||
| 555 | if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev)) | 559 | if (i7300_idle_platform_probe(&fbd_dev, &ioat_dev, forceload)) |
| 556 | return -ENODEV; | 560 | return -ENODEV; |
| 557 | 561 | ||
| 558 | if (i7300_idle_thrt_save()) | 562 | if (i7300_idle_thrt_save()) |
diff --git a/drivers/ieee1394/dv1394.c b/drivers/ieee1394/dv1394.c index 823a6297a1af..2cd00b5b45b4 100644 --- a/drivers/ieee1394/dv1394.c +++ b/drivers/ieee1394/dv1394.c | |||
| @@ -1789,12 +1789,13 @@ static int dv1394_open(struct inode *inode, struct file *file) | |||
| 1789 | } else { | 1789 | } else { |
| 1790 | /* look up the card by ID */ | 1790 | /* look up the card by ID */ |
| 1791 | unsigned long flags; | 1791 | unsigned long flags; |
| 1792 | int idx = ieee1394_file_to_instance(file); | ||
| 1792 | 1793 | ||
| 1793 | spin_lock_irqsave(&dv1394_cards_lock, flags); | 1794 | spin_lock_irqsave(&dv1394_cards_lock, flags); |
| 1794 | if (!list_empty(&dv1394_cards)) { | 1795 | if (!list_empty(&dv1394_cards)) { |
| 1795 | struct video_card *p; | 1796 | struct video_card *p; |
| 1796 | list_for_each_entry(p, &dv1394_cards, list) { | 1797 | list_for_each_entry(p, &dv1394_cards, list) { |
| 1797 | if ((p->id) == ieee1394_file_to_instance(file)) { | 1798 | if ((p->id) == idx) { |
| 1798 | video = p; | 1799 | video = p; |
| 1799 | break; | 1800 | break; |
| 1800 | } | 1801 | } |
| @@ -1803,7 +1804,7 @@ static int dv1394_open(struct inode *inode, struct file *file) | |||
| 1803 | spin_unlock_irqrestore(&dv1394_cards_lock, flags); | 1804 | spin_unlock_irqrestore(&dv1394_cards_lock, flags); |
| 1804 | 1805 | ||
| 1805 | if (!video) { | 1806 | if (!video) { |
| 1806 | debug_printk("dv1394: OHCI card %d not found", ieee1394_file_to_instance(file)); | 1807 | debug_printk("dv1394: OHCI card %d not found", idx); |
| 1807 | return -ENODEV; | 1808 | return -ENODEV; |
| 1808 | } | 1809 | } |
| 1809 | 1810 | ||
diff --git a/drivers/ieee1394/ieee1394_core.h b/drivers/ieee1394/ieee1394_core.h index 21d50f73a210..28b9f58bafd2 100644 --- a/drivers/ieee1394/ieee1394_core.h +++ b/drivers/ieee1394/ieee1394_core.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | #include <linux/fs.h> | 5 | #include <linux/fs.h> |
| 6 | #include <linux/list.h> | 6 | #include <linux/list.h> |
| 7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
| 8 | #include <linux/cdev.h> | ||
| 8 | #include <asm/atomic.h> | 9 | #include <asm/atomic.h> |
| 9 | 10 | ||
| 10 | #include "hosts.h" | 11 | #include "hosts.h" |
| @@ -155,7 +156,10 @@ void hpsb_packet_received(struct hpsb_host *host, quadlet_t *data, size_t size, | |||
| 155 | */ | 156 | */ |
| 156 | static inline unsigned char ieee1394_file_to_instance(struct file *file) | 157 | static inline unsigned char ieee1394_file_to_instance(struct file *file) |
| 157 | { | 158 | { |
| 158 | return file->f_path.dentry->d_inode->i_cindex; | 159 | int idx = cdev_index(file->f_path.dentry->d_inode); |
| 160 | if (idx < 0) | ||
| 161 | idx = 0; | ||
| 162 | return idx; | ||
| 159 | } | 163 | } |
| 160 | 164 | ||
| 161 | extern int hpsb_disable_irm; | 165 | extern int hpsb_disable_irm; |
diff --git a/drivers/input/input.c b/drivers/input/input.c index e54e002665b0..5d445f48789b 100644 --- a/drivers/input/input.c +++ b/drivers/input/input.c | |||
| @@ -42,6 +42,7 @@ static unsigned int input_abs_bypass_init_data[] __initdata = { | |||
| 42 | ABS_MT_POSITION_Y, | 42 | ABS_MT_POSITION_Y, |
| 43 | ABS_MT_TOOL_TYPE, | 43 | ABS_MT_TOOL_TYPE, |
| 44 | ABS_MT_BLOB_ID, | 44 | ABS_MT_BLOB_ID, |
| 45 | ABS_MT_TRACKING_ID, | ||
| 45 | 0 | 46 | 0 |
| 46 | }; | 47 | }; |
| 47 | static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)]; | 48 | static unsigned long input_abs_bypass[BITS_TO_LONGS(ABS_CNT)]; |
diff --git a/drivers/input/serio/libps2.c b/drivers/input/serio/libps2.c index 67248c31e19a..be5bbbb8ae4e 100644 --- a/drivers/input/serio/libps2.c +++ b/drivers/input/serio/libps2.c | |||
| @@ -210,7 +210,7 @@ int ps2_command(struct ps2dev *ps2dev, unsigned char *param, int command) | |||
| 210 | timeout = wait_event_timeout(ps2dev->wait, | 210 | timeout = wait_event_timeout(ps2dev->wait, |
| 211 | !(ps2dev->flags & PS2_FLAG_CMD1), timeout); | 211 | !(ps2dev->flags & PS2_FLAG_CMD1), timeout); |
| 212 | 212 | ||
| 213 | if (ps2dev->cmdcnt && timeout > 0) { | 213 | if (ps2dev->cmdcnt && !(ps2dev->flags & PS2_FLAG_CMD1)) { |
| 214 | 214 | ||
| 215 | timeout = ps2_adjust_timeout(ps2dev, command, timeout); | 215 | timeout = ps2_adjust_timeout(ps2dev, command, timeout); |
| 216 | wait_event_timeout(ps2dev->wait, | 216 | wait_event_timeout(ps2dev->wait, |
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c index f100c7f4c1db..6954f5500108 100644 --- a/drivers/input/touchscreen/ucb1400_ts.c +++ b/drivers/input/touchscreen/ucb1400_ts.c | |||
| @@ -419,7 +419,7 @@ static int ucb1400_ts_remove(struct platform_device *dev) | |||
| 419 | #ifdef CONFIG_PM | 419 | #ifdef CONFIG_PM |
| 420 | static int ucb1400_ts_resume(struct platform_device *dev) | 420 | static int ucb1400_ts_resume(struct platform_device *dev) |
| 421 | { | 421 | { |
| 422 | struct ucb1400_ts *ucb = platform_get_drvdata(dev); | 422 | struct ucb1400_ts *ucb = dev->dev.platform_data; |
| 423 | 423 | ||
| 424 | if (ucb->ts_task) { | 424 | if (ucb->ts_task) { |
| 425 | /* | 425 | /* |
diff --git a/drivers/md/bitmap.c b/drivers/md/bitmap.c index 56df1cee8fb3..3319c2fec28e 100644 --- a/drivers/md/bitmap.c +++ b/drivers/md/bitmap.c | |||
| @@ -232,7 +232,7 @@ static struct page *read_sb_page(mddev_t *mddev, long offset, | |||
| 232 | target = rdev->sb_start + offset + index * (PAGE_SIZE/512); | 232 | target = rdev->sb_start + offset + index * (PAGE_SIZE/512); |
| 233 | 233 | ||
| 234 | if (sync_page_io(rdev->bdev, target, | 234 | if (sync_page_io(rdev->bdev, target, |
| 235 | roundup(size, bdev_hardsect_size(rdev->bdev)), | 235 | roundup(size, bdev_logical_block_size(rdev->bdev)), |
| 236 | page, READ)) { | 236 | page, READ)) { |
| 237 | page->index = index; | 237 | page->index = index; |
| 238 | attach_page_buffers(page, NULL); /* so that free_buffer will | 238 | attach_page_buffers(page, NULL); /* so that free_buffer will |
| @@ -287,7 +287,7 @@ static int write_sb_page(struct bitmap *bitmap, struct page *page, int wait) | |||
| 287 | int size = PAGE_SIZE; | 287 | int size = PAGE_SIZE; |
| 288 | if (page->index == bitmap->file_pages-1) | 288 | if (page->index == bitmap->file_pages-1) |
| 289 | size = roundup(bitmap->last_page_size, | 289 | size = roundup(bitmap->last_page_size, |
| 290 | bdev_hardsect_size(rdev->bdev)); | 290 | bdev_logical_block_size(rdev->bdev)); |
| 291 | /* Just make sure we aren't corrupting data or | 291 | /* Just make sure we aren't corrupting data or |
| 292 | * metadata | 292 | * metadata |
| 293 | */ | 293 | */ |
diff --git a/drivers/md/dm-exception-store.c b/drivers/md/dm-exception-store.c index a2e26c242141..75d8081a9041 100644 --- a/drivers/md/dm-exception-store.c +++ b/drivers/md/dm-exception-store.c | |||
| @@ -178,7 +178,7 @@ static int set_chunk_size(struct dm_exception_store *store, | |||
| 178 | } | 178 | } |
| 179 | 179 | ||
| 180 | /* Validate the chunk size against the device block size */ | 180 | /* Validate the chunk size against the device block size */ |
| 181 | if (chunk_size_ulong % (bdev_hardsect_size(store->cow->bdev) >> 9)) { | 181 | if (chunk_size_ulong % (bdev_logical_block_size(store->cow->bdev) >> 9)) { |
| 182 | *error = "Chunk size is not a multiple of device blocksize"; | 182 | *error = "Chunk size is not a multiple of device blocksize"; |
| 183 | return -EINVAL; | 183 | return -EINVAL; |
| 184 | } | 184 | } |
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index be233bc4d917..6fa8ccf91c70 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
| @@ -413,7 +413,8 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
| 413 | * Buffer holds both header and bitset. | 413 | * Buffer holds both header and bitset. |
| 414 | */ | 414 | */ |
| 415 | buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + | 415 | buf_size = dm_round_up((LOG_OFFSET << SECTOR_SHIFT) + |
| 416 | bitset_size, ti->limits.hardsect_size); | 416 | bitset_size, |
| 417 | ti->limits.logical_block_size); | ||
| 417 | 418 | ||
| 418 | if (buf_size > dev->bdev->bd_inode->i_size) { | 419 | if (buf_size > dev->bdev->bd_inode->i_size) { |
| 419 | DMWARN("log device %s too small: need %llu bytes", | 420 | DMWARN("log device %s too small: need %llu bytes", |
diff --git a/drivers/md/dm-snap-persistent.c b/drivers/md/dm-snap-persistent.c index e75c6dd76a9a..2662a41337e7 100644 --- a/drivers/md/dm-snap-persistent.c +++ b/drivers/md/dm-snap-persistent.c | |||
| @@ -282,7 +282,7 @@ static int read_header(struct pstore *ps, int *new_snapshot) | |||
| 282 | */ | 282 | */ |
| 283 | if (!ps->store->chunk_size) { | 283 | if (!ps->store->chunk_size) { |
| 284 | ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS, | 284 | ps->store->chunk_size = max(DM_CHUNK_SIZE_DEFAULT_SECTORS, |
| 285 | bdev_hardsect_size(ps->store->cow->bdev) >> 9); | 285 | bdev_logical_block_size(ps->store->cow->bdev) >> 9); |
| 286 | ps->store->chunk_mask = ps->store->chunk_size - 1; | 286 | ps->store->chunk_mask = ps->store->chunk_size - 1; |
| 287 | ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1; | 287 | ps->store->chunk_shift = ffs(ps->store->chunk_size) - 1; |
| 288 | chunk_size_supplied = 0; | 288 | chunk_size_supplied = 0; |
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c index 429b50b975d5..e9a73bb242b0 100644 --- a/drivers/md/dm-table.c +++ b/drivers/md/dm-table.c | |||
| @@ -108,7 +108,8 @@ static void combine_restrictions_low(struct io_restrictions *lhs, | |||
| 108 | lhs->max_hw_segments = | 108 | lhs->max_hw_segments = |
| 109 | min_not_zero(lhs->max_hw_segments, rhs->max_hw_segments); | 109 | min_not_zero(lhs->max_hw_segments, rhs->max_hw_segments); |
| 110 | 110 | ||
| 111 | lhs->hardsect_size = max(lhs->hardsect_size, rhs->hardsect_size); | 111 | lhs->logical_block_size = max(lhs->logical_block_size, |
| 112 | rhs->logical_block_size); | ||
| 112 | 113 | ||
| 113 | lhs->max_segment_size = | 114 | lhs->max_segment_size = |
| 114 | min_not_zero(lhs->max_segment_size, rhs->max_segment_size); | 115 | min_not_zero(lhs->max_segment_size, rhs->max_segment_size); |
| @@ -509,7 +510,7 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) | |||
| 509 | * combine_restrictions_low() | 510 | * combine_restrictions_low() |
| 510 | */ | 511 | */ |
| 511 | rs->max_sectors = | 512 | rs->max_sectors = |
| 512 | min_not_zero(rs->max_sectors, q->max_sectors); | 513 | min_not_zero(rs->max_sectors, queue_max_sectors(q)); |
| 513 | 514 | ||
| 514 | /* | 515 | /* |
| 515 | * Check if merge fn is supported. | 516 | * Check if merge fn is supported. |
| @@ -524,24 +525,25 @@ void dm_set_device_limits(struct dm_target *ti, struct block_device *bdev) | |||
| 524 | 525 | ||
| 525 | rs->max_phys_segments = | 526 | rs->max_phys_segments = |
| 526 | min_not_zero(rs->max_phys_segments, | 527 | min_not_zero(rs->max_phys_segments, |
| 527 | q->max_phys_segments); | 528 | queue_max_phys_segments(q)); |
| 528 | 529 | ||
| 529 | rs->max_hw_segments = | 530 | rs->max_hw_segments = |
| 530 | min_not_zero(rs->max_hw_segments, q->max_hw_segments); | 531 | min_not_zero(rs->max_hw_segments, queue_max_hw_segments(q)); |
| 531 | 532 | ||
| 532 | rs->hardsect_size = max(rs->hardsect_size, q->hardsect_size); | 533 | rs->logical_block_size = max(rs->logical_block_size, |
| 534 | queue_logical_block_size(q)); | ||
| 533 | 535 | ||
| 534 | rs->max_segment_size = | 536 | rs->max_segment_size = |
| 535 | min_not_zero(rs->max_segment_size, q->max_segment_size); | 537 | min_not_zero(rs->max_segment_size, queue_max_segment_size(q)); |
| 536 | 538 | ||
| 537 | rs->max_hw_sectors = | 539 | rs->max_hw_sectors = |
| 538 | min_not_zero(rs->max_hw_sectors, q->max_hw_sectors); | 540 | min_not_zero(rs->max_hw_sectors, queue_max_hw_sectors(q)); |
| 539 | 541 | ||
| 540 | rs->seg_boundary_mask = | 542 | rs->seg_boundary_mask = |
| 541 | min_not_zero(rs->seg_boundary_mask, | 543 | min_not_zero(rs->seg_boundary_mask, |
| 542 | q->seg_boundary_mask); | 544 | queue_segment_boundary(q)); |
| 543 | 545 | ||
| 544 | rs->bounce_pfn = min_not_zero(rs->bounce_pfn, q->bounce_pfn); | 546 | rs->bounce_pfn = min_not_zero(rs->bounce_pfn, queue_bounce_pfn(q)); |
| 545 | 547 | ||
| 546 | rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); | 548 | rs->no_cluster |= !test_bit(QUEUE_FLAG_CLUSTER, &q->queue_flags); |
| 547 | } | 549 | } |
| @@ -683,8 +685,8 @@ static void check_for_valid_limits(struct io_restrictions *rs) | |||
| 683 | rs->max_phys_segments = MAX_PHYS_SEGMENTS; | 685 | rs->max_phys_segments = MAX_PHYS_SEGMENTS; |
| 684 | if (!rs->max_hw_segments) | 686 | if (!rs->max_hw_segments) |
| 685 | rs->max_hw_segments = MAX_HW_SEGMENTS; | 687 | rs->max_hw_segments = MAX_HW_SEGMENTS; |
| 686 | if (!rs->hardsect_size) | 688 | if (!rs->logical_block_size) |
| 687 | rs->hardsect_size = 1 << SECTOR_SHIFT; | 689 | rs->logical_block_size = 1 << SECTOR_SHIFT; |
| 688 | if (!rs->max_segment_size) | 690 | if (!rs->max_segment_size) |
| 689 | rs->max_segment_size = MAX_SEGMENT_SIZE; | 691 | rs->max_segment_size = MAX_SEGMENT_SIZE; |
| 690 | if (!rs->seg_boundary_mask) | 692 | if (!rs->seg_boundary_mask) |
| @@ -912,13 +914,13 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q) | |||
| 912 | * restrictions. | 914 | * restrictions. |
| 913 | */ | 915 | */ |
| 914 | blk_queue_max_sectors(q, t->limits.max_sectors); | 916 | blk_queue_max_sectors(q, t->limits.max_sectors); |
| 915 | q->max_phys_segments = t->limits.max_phys_segments; | 917 | blk_queue_max_phys_segments(q, t->limits.max_phys_segments); |
| 916 | q->max_hw_segments = t->limits.max_hw_segments; | 918 | blk_queue_max_hw_segments(q, t->limits.max_hw_segments); |
| 917 | q->hardsect_size = t->limits.hardsect_size; | 919 | blk_queue_logical_block_size(q, t->limits.logical_block_size); |
| 918 | q->max_segment_size = t->limits.max_segment_size; | 920 | blk_queue_max_segment_size(q, t->limits.max_segment_size); |
| 919 | q->max_hw_sectors = t->limits.max_hw_sectors; | 921 | blk_queue_max_hw_sectors(q, t->limits.max_hw_sectors); |
| 920 | q->seg_boundary_mask = t->limits.seg_boundary_mask; | 922 | blk_queue_segment_boundary(q, t->limits.seg_boundary_mask); |
| 921 | q->bounce_pfn = t->limits.bounce_pfn; | 923 | blk_queue_bounce_limit(q, t->limits.bounce_pfn); |
| 922 | 924 | ||
| 923 | if (t->limits.no_cluster) | 925 | if (t->limits.no_cluster) |
| 924 | queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); | 926 | queue_flag_clear_unlocked(QUEUE_FLAG_CLUSTER, q); |
diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 424f7b048c30..3fd8b1e65483 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c | |||
| @@ -20,7 +20,8 @@ | |||
| 20 | #include <linux/idr.h> | 20 | #include <linux/idr.h> |
| 21 | #include <linux/hdreg.h> | 21 | #include <linux/hdreg.h> |
| 22 | #include <linux/blktrace_api.h> | 22 | #include <linux/blktrace_api.h> |
| 23 | #include <trace/block.h> | 23 | |
| 24 | #include <trace/events/block.h> | ||
| 24 | 25 | ||
| 25 | #define DM_MSG_PREFIX "core" | 26 | #define DM_MSG_PREFIX "core" |
| 26 | 27 | ||
| @@ -53,8 +54,6 @@ struct dm_target_io { | |||
| 53 | union map_info info; | 54 | union map_info info; |
| 54 | }; | 55 | }; |
| 55 | 56 | ||
| 56 | DEFINE_TRACE(block_bio_complete); | ||
| 57 | |||
| 58 | /* | 57 | /* |
| 59 | * For request-based dm. | 58 | * For request-based dm. |
| 60 | * One of these is allocated per request. | 59 | * One of these is allocated per request. |
| @@ -656,8 +655,7 @@ static void __map_bio(struct dm_target *ti, struct bio *clone, | |||
| 656 | /* the bio has been remapped so dispatch it */ | 655 | /* the bio has been remapped so dispatch it */ |
| 657 | 656 | ||
| 658 | trace_block_remap(bdev_get_queue(clone->bi_bdev), clone, | 657 | trace_block_remap(bdev_get_queue(clone->bi_bdev), clone, |
| 659 | tio->io->bio->bi_bdev->bd_dev, | 658 | tio->io->bio->bi_bdev->bd_dev, sector); |
| 660 | clone->bi_sector, sector); | ||
| 661 | 659 | ||
| 662 | generic_make_request(clone); | 660 | generic_make_request(clone); |
| 663 | } else if (r < 0 || r == DM_MAPIO_REQUEUE) { | 661 | } else if (r < 0 || r == DM_MAPIO_REQUEUE) { |
diff --git a/drivers/md/linear.c b/drivers/md/linear.c index 7a36e38393a1..64f1f3e046e0 100644 --- a/drivers/md/linear.c +++ b/drivers/md/linear.c | |||
| @@ -146,7 +146,7 @@ static linear_conf_t *linear_conf(mddev_t *mddev, int raid_disks) | |||
| 146 | * a one page request is never in violation. | 146 | * a one page request is never in violation. |
| 147 | */ | 147 | */ |
| 148 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && | 148 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && |
| 149 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 149 | queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) |
| 150 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); | 150 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 151 | 151 | ||
| 152 | disk->num_sectors = rdev->sectors; | 152 | disk->num_sectors = rdev->sectors; |
diff --git a/drivers/md/md.c b/drivers/md/md.c index 641b211fe3fe..20f6ac338349 100644 --- a/drivers/md/md.c +++ b/drivers/md/md.c | |||
| @@ -1202,7 +1202,7 @@ static int super_1_load(mdk_rdev_t *rdev, mdk_rdev_t *refdev, int minor_version) | |||
| 1202 | atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); | 1202 | atomic_set(&rdev->corrected_errors, le32_to_cpu(sb->cnt_corrected_read)); |
| 1203 | 1203 | ||
| 1204 | rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256; | 1204 | rdev->sb_size = le32_to_cpu(sb->max_dev) * 2 + 256; |
| 1205 | bmask = queue_hardsect_size(rdev->bdev->bd_disk->queue)-1; | 1205 | bmask = queue_logical_block_size(rdev->bdev->bd_disk->queue)-1; |
| 1206 | if (rdev->sb_size & bmask) | 1206 | if (rdev->sb_size & bmask) |
| 1207 | rdev->sb_size = (rdev->sb_size | bmask) + 1; | 1207 | rdev->sb_size = (rdev->sb_size | bmask) + 1; |
| 1208 | 1208 | ||
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c index 41ced0cbe823..4ee31aa13c40 100644 --- a/drivers/md/multipath.c +++ b/drivers/md/multipath.c | |||
| @@ -303,7 +303,7 @@ static int multipath_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 303 | * merge_bvec_fn will be involved in multipath.) | 303 | * merge_bvec_fn will be involved in multipath.) |
| 304 | */ | 304 | */ |
| 305 | if (q->merge_bvec_fn && | 305 | if (q->merge_bvec_fn && |
| 306 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 306 | queue_max_sectors(q) > (PAGE_SIZE>>9)) |
| 307 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); | 307 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 308 | 308 | ||
| 309 | conf->working_disks++; | 309 | conf->working_disks++; |
| @@ -467,7 +467,7 @@ static int multipath_run (mddev_t *mddev) | |||
| 467 | * violating it, not that we ever expect a device with | 467 | * violating it, not that we ever expect a device with |
| 468 | * a merge_bvec_fn to be involved in multipath */ | 468 | * a merge_bvec_fn to be involved in multipath */ |
| 469 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && | 469 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && |
| 470 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 470 | queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) |
| 471 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); | 471 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 472 | 472 | ||
| 473 | if (!test_bit(Faulty, &rdev->flags)) | 473 | if (!test_bit(Faulty, &rdev->flags)) |
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c index c08d7559be55..925507e7d673 100644 --- a/drivers/md/raid0.c +++ b/drivers/md/raid0.c | |||
| @@ -144,7 +144,7 @@ static int create_strip_zones (mddev_t *mddev) | |||
| 144 | */ | 144 | */ |
| 145 | 145 | ||
| 146 | if (rdev1->bdev->bd_disk->queue->merge_bvec_fn && | 146 | if (rdev1->bdev->bd_disk->queue->merge_bvec_fn && |
| 147 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 147 | queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) |
| 148 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); | 148 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 149 | 149 | ||
| 150 | if (!smallest || (rdev1->sectors < smallest->sectors)) | 150 | if (!smallest || (rdev1->sectors < smallest->sectors)) |
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c index 36df9109cde1..e23758b4a34e 100644 --- a/drivers/md/raid1.c +++ b/drivers/md/raid1.c | |||
| @@ -1130,7 +1130,7 @@ static int raid1_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1130 | * a one page request is never in violation. | 1130 | * a one page request is never in violation. |
| 1131 | */ | 1131 | */ |
| 1132 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && | 1132 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && |
| 1133 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 1133 | queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) |
| 1134 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); | 1134 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 1135 | 1135 | ||
| 1136 | p->head_position = 0; | 1136 | p->head_position = 0; |
| @@ -1996,7 +1996,7 @@ static int run(mddev_t *mddev) | |||
| 1996 | * a one page request is never in violation. | 1996 | * a one page request is never in violation. |
| 1997 | */ | 1997 | */ |
| 1998 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && | 1998 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && |
| 1999 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 1999 | queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) |
| 2000 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); | 2000 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 2001 | 2001 | ||
| 2002 | disk->head_position = 0; | 2002 | disk->head_position = 0; |
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c index 499620afb44b..750550c1166f 100644 --- a/drivers/md/raid10.c +++ b/drivers/md/raid10.c | |||
| @@ -1158,8 +1158,8 @@ static int raid10_add_disk(mddev_t *mddev, mdk_rdev_t *rdev) | |||
| 1158 | * a one page request is never in violation. | 1158 | * a one page request is never in violation. |
| 1159 | */ | 1159 | */ |
| 1160 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && | 1160 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && |
| 1161 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 1161 | queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) |
| 1162 | mddev->queue->max_sectors = (PAGE_SIZE>>9); | 1162 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 1163 | 1163 | ||
| 1164 | p->head_position = 0; | 1164 | p->head_position = 0; |
| 1165 | rdev->raid_disk = mirror; | 1165 | rdev->raid_disk = mirror; |
| @@ -2145,8 +2145,8 @@ static int run(mddev_t *mddev) | |||
| 2145 | * a one page request is never in violation. | 2145 | * a one page request is never in violation. |
| 2146 | */ | 2146 | */ |
| 2147 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && | 2147 | if (rdev->bdev->bd_disk->queue->merge_bvec_fn && |
| 2148 | mddev->queue->max_sectors > (PAGE_SIZE>>9)) | 2148 | queue_max_sectors(mddev->queue) > (PAGE_SIZE>>9)) |
| 2149 | mddev->queue->max_sectors = (PAGE_SIZE>>9); | 2149 | blk_queue_max_sectors(mddev->queue, PAGE_SIZE>>9); |
| 2150 | 2150 | ||
| 2151 | disk->head_position = 0; | 2151 | disk->head_position = 0; |
| 2152 | } | 2152 | } |
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c index 5d400aef8d9b..bef876698232 100644 --- a/drivers/md/raid5.c +++ b/drivers/md/raid5.c | |||
| @@ -362,7 +362,7 @@ static void raid5_unplug_device(struct request_queue *q); | |||
| 362 | 362 | ||
| 363 | static struct stripe_head * | 363 | static struct stripe_head * |
| 364 | get_active_stripe(raid5_conf_t *conf, sector_t sector, | 364 | get_active_stripe(raid5_conf_t *conf, sector_t sector, |
| 365 | int previous, int noblock) | 365 | int previous, int noblock, int noquiesce) |
| 366 | { | 366 | { |
| 367 | struct stripe_head *sh; | 367 | struct stripe_head *sh; |
| 368 | 368 | ||
| @@ -372,7 +372,7 @@ get_active_stripe(raid5_conf_t *conf, sector_t sector, | |||
| 372 | 372 | ||
| 373 | do { | 373 | do { |
| 374 | wait_event_lock_irq(conf->wait_for_stripe, | 374 | wait_event_lock_irq(conf->wait_for_stripe, |
| 375 | conf->quiesce == 0, | 375 | conf->quiesce == 0 || noquiesce, |
| 376 | conf->device_lock, /* nothing */); | 376 | conf->device_lock, /* nothing */); |
| 377 | sh = __find_stripe(conf, sector, conf->generation - previous); | 377 | sh = __find_stripe(conf, sector, conf->generation - previous); |
| 378 | if (!sh) { | 378 | if (!sh) { |
| @@ -2671,7 +2671,7 @@ static void handle_stripe_expansion(raid5_conf_t *conf, struct stripe_head *sh, | |||
| 2671 | sector_t bn = compute_blocknr(sh, i, 1); | 2671 | sector_t bn = compute_blocknr(sh, i, 1); |
| 2672 | sector_t s = raid5_compute_sector(conf, bn, 0, | 2672 | sector_t s = raid5_compute_sector(conf, bn, 0, |
| 2673 | &dd_idx, NULL); | 2673 | &dd_idx, NULL); |
| 2674 | sh2 = get_active_stripe(conf, s, 0, 1); | 2674 | sh2 = get_active_stripe(conf, s, 0, 1, 1); |
| 2675 | if (sh2 == NULL) | 2675 | if (sh2 == NULL) |
| 2676 | /* so far only the early blocks of this stripe | 2676 | /* so far only the early blocks of this stripe |
| 2677 | * have been requested. When later blocks | 2677 | * have been requested. When later blocks |
| @@ -2944,7 +2944,7 @@ static bool handle_stripe5(struct stripe_head *sh) | |||
| 2944 | /* Finish reconstruct operations initiated by the expansion process */ | 2944 | /* Finish reconstruct operations initiated by the expansion process */ |
| 2945 | if (sh->reconstruct_state == reconstruct_state_result) { | 2945 | if (sh->reconstruct_state == reconstruct_state_result) { |
| 2946 | struct stripe_head *sh2 | 2946 | struct stripe_head *sh2 |
| 2947 | = get_active_stripe(conf, sh->sector, 1, 1); | 2947 | = get_active_stripe(conf, sh->sector, 1, 1, 1); |
| 2948 | if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) { | 2948 | if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) { |
| 2949 | /* sh cannot be written until sh2 has been read. | 2949 | /* sh cannot be written until sh2 has been read. |
| 2950 | * so arrange for sh to be delayed a little | 2950 | * so arrange for sh to be delayed a little |
| @@ -3189,7 +3189,7 @@ static bool handle_stripe6(struct stripe_head *sh, struct page *tmp_page) | |||
| 3189 | 3189 | ||
| 3190 | if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { | 3190 | if (s.expanded && test_bit(STRIPE_EXPANDING, &sh->state)) { |
| 3191 | struct stripe_head *sh2 | 3191 | struct stripe_head *sh2 |
| 3192 | = get_active_stripe(conf, sh->sector, 1, 1); | 3192 | = get_active_stripe(conf, sh->sector, 1, 1, 1); |
| 3193 | if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) { | 3193 | if (sh2 && test_bit(STRIPE_EXPAND_SOURCE, &sh2->state)) { |
| 3194 | /* sh cannot be written until sh2 has been read. | 3194 | /* sh cannot be written until sh2 has been read. |
| 3195 | * so arrange for sh to be delayed a little | 3195 | * so arrange for sh to be delayed a little |
| @@ -3288,7 +3288,7 @@ static void unplug_slaves(mddev_t *mddev) | |||
| 3288 | int i; | 3288 | int i; |
| 3289 | 3289 | ||
| 3290 | rcu_read_lock(); | 3290 | rcu_read_lock(); |
| 3291 | for (i=0; i<mddev->raid_disks; i++) { | 3291 | for (i = 0; i < conf->raid_disks; i++) { |
| 3292 | mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); | 3292 | mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev); |
| 3293 | if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { | 3293 | if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) { |
| 3294 | struct request_queue *r_queue = bdev_get_queue(rdev->bdev); | 3294 | struct request_queue *r_queue = bdev_get_queue(rdev->bdev); |
| @@ -3463,10 +3463,10 @@ static int bio_fits_rdev(struct bio *bi) | |||
| 3463 | { | 3463 | { |
| 3464 | struct request_queue *q = bdev_get_queue(bi->bi_bdev); | 3464 | struct request_queue *q = bdev_get_queue(bi->bi_bdev); |
| 3465 | 3465 | ||
| 3466 | if ((bi->bi_size>>9) > q->max_sectors) | 3466 | if ((bi->bi_size>>9) > queue_max_sectors(q)) |
| 3467 | return 0; | 3467 | return 0; |
| 3468 | blk_recount_segments(q, bi); | 3468 | blk_recount_segments(q, bi); |
| 3469 | if (bi->bi_phys_segments > q->max_phys_segments) | 3469 | if (bi->bi_phys_segments > queue_max_phys_segments(q)) |
| 3470 | return 0; | 3470 | return 0; |
| 3471 | 3471 | ||
| 3472 | if (q->merge_bvec_fn) | 3472 | if (q->merge_bvec_fn) |
| @@ -3675,7 +3675,7 @@ static int make_request(struct request_queue *q, struct bio * bi) | |||
| 3675 | (unsigned long long)logical_sector); | 3675 | (unsigned long long)logical_sector); |
| 3676 | 3676 | ||
| 3677 | sh = get_active_stripe(conf, new_sector, previous, | 3677 | sh = get_active_stripe(conf, new_sector, previous, |
| 3678 | (bi->bi_rw&RWA_MASK)); | 3678 | (bi->bi_rw&RWA_MASK), 0); |
| 3679 | if (sh) { | 3679 | if (sh) { |
| 3680 | if (unlikely(previous)) { | 3680 | if (unlikely(previous)) { |
| 3681 | /* expansion might have moved on while waiting for a | 3681 | /* expansion might have moved on while waiting for a |
| @@ -3873,7 +3873,7 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
| 3873 | for (i = 0; i < reshape_sectors; i += STRIPE_SECTORS) { | 3873 | for (i = 0; i < reshape_sectors; i += STRIPE_SECTORS) { |
| 3874 | int j; | 3874 | int j; |
| 3875 | int skipped = 0; | 3875 | int skipped = 0; |
| 3876 | sh = get_active_stripe(conf, stripe_addr+i, 0, 0); | 3876 | sh = get_active_stripe(conf, stripe_addr+i, 0, 0, 1); |
| 3877 | set_bit(STRIPE_EXPANDING, &sh->state); | 3877 | set_bit(STRIPE_EXPANDING, &sh->state); |
| 3878 | atomic_inc(&conf->reshape_stripes); | 3878 | atomic_inc(&conf->reshape_stripes); |
| 3879 | /* If any of this stripe is beyond the end of the old | 3879 | /* If any of this stripe is beyond the end of the old |
| @@ -3916,13 +3916,13 @@ static sector_t reshape_request(mddev_t *mddev, sector_t sector_nr, int *skipped | |||
| 3916 | raid5_compute_sector(conf, stripe_addr*(new_data_disks), | 3916 | raid5_compute_sector(conf, stripe_addr*(new_data_disks), |
| 3917 | 1, &dd_idx, NULL); | 3917 | 1, &dd_idx, NULL); |
| 3918 | last_sector = | 3918 | last_sector = |
| 3919 | raid5_compute_sector(conf, ((stripe_addr+conf->chunk_size/512) | 3919 | raid5_compute_sector(conf, ((stripe_addr+reshape_sectors) |
| 3920 | *(new_data_disks) - 1), | 3920 | *(new_data_disks) - 1), |
| 3921 | 1, &dd_idx, NULL); | 3921 | 1, &dd_idx, NULL); |
| 3922 | if (last_sector >= mddev->dev_sectors) | 3922 | if (last_sector >= mddev->dev_sectors) |
| 3923 | last_sector = mddev->dev_sectors - 1; | 3923 | last_sector = mddev->dev_sectors - 1; |
| 3924 | while (first_sector <= last_sector) { | 3924 | while (first_sector <= last_sector) { |
| 3925 | sh = get_active_stripe(conf, first_sector, 1, 0); | 3925 | sh = get_active_stripe(conf, first_sector, 1, 0, 1); |
| 3926 | set_bit(STRIPE_EXPAND_SOURCE, &sh->state); | 3926 | set_bit(STRIPE_EXPAND_SOURCE, &sh->state); |
| 3927 | set_bit(STRIPE_HANDLE, &sh->state); | 3927 | set_bit(STRIPE_HANDLE, &sh->state); |
| 3928 | release_stripe(sh); | 3928 | release_stripe(sh); |
| @@ -4022,9 +4022,9 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
| 4022 | 4022 | ||
| 4023 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); | 4023 | bitmap_cond_end_sync(mddev->bitmap, sector_nr); |
| 4024 | 4024 | ||
| 4025 | sh = get_active_stripe(conf, sector_nr, 0, 1); | 4025 | sh = get_active_stripe(conf, sector_nr, 0, 1, 0); |
| 4026 | if (sh == NULL) { | 4026 | if (sh == NULL) { |
| 4027 | sh = get_active_stripe(conf, sector_nr, 0, 0); | 4027 | sh = get_active_stripe(conf, sector_nr, 0, 0, 0); |
| 4028 | /* make sure we don't swamp the stripe cache if someone else | 4028 | /* make sure we don't swamp the stripe cache if someone else |
| 4029 | * is trying to get access | 4029 | * is trying to get access |
| 4030 | */ | 4030 | */ |
| @@ -4034,7 +4034,7 @@ static inline sector_t sync_request(mddev_t *mddev, sector_t sector_nr, int *ski | |||
| 4034 | * We don't need to check the 'failed' flag as when that gets set, | 4034 | * We don't need to check the 'failed' flag as when that gets set, |
| 4035 | * recovery aborts. | 4035 | * recovery aborts. |
| 4036 | */ | 4036 | */ |
| 4037 | for (i=0; i<mddev->raid_disks; i++) | 4037 | for (i = 0; i < conf->raid_disks; i++) |
| 4038 | if (conf->disks[i].rdev == NULL) | 4038 | if (conf->disks[i].rdev == NULL) |
| 4039 | still_degraded = 1; | 4039 | still_degraded = 1; |
| 4040 | 4040 | ||
| @@ -4086,7 +4086,7 @@ static int retry_aligned_read(raid5_conf_t *conf, struct bio *raid_bio) | |||
| 4086 | /* already done this stripe */ | 4086 | /* already done this stripe */ |
| 4087 | continue; | 4087 | continue; |
| 4088 | 4088 | ||
| 4089 | sh = get_active_stripe(conf, sector, 0, 1); | 4089 | sh = get_active_stripe(conf, sector, 0, 1, 0); |
| 4090 | 4090 | ||
| 4091 | if (!sh) { | 4091 | if (!sh) { |
| 4092 | /* failed to get a stripe - must wait */ | 4092 | /* failed to get a stripe - must wait */ |
diff --git a/drivers/media/video/ivtv/ivtv-queue.c b/drivers/media/video/ivtv/ivtv-queue.c index ff7b7deded4f..7fde36e6d227 100644 --- a/drivers/media/video/ivtv/ivtv-queue.c +++ b/drivers/media/video/ivtv/ivtv-queue.c | |||
| @@ -230,7 +230,8 @@ int ivtv_stream_alloc(struct ivtv_stream *s) | |||
| 230 | return -ENOMEM; | 230 | return -ENOMEM; |
| 231 | } | 231 | } |
| 232 | if (ivtv_might_use_dma(s)) { | 232 | if (ivtv_might_use_dma(s)) { |
| 233 | s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, sizeof(struct ivtv_sg_element), s->dma); | 233 | s->sg_handle = pci_map_single(itv->pdev, s->sg_dma, |
| 234 | sizeof(struct ivtv_sg_element), PCI_DMA_TODEVICE); | ||
| 234 | ivtv_stream_sync_for_cpu(s); | 235 | ivtv_stream_sync_for_cpu(s); |
| 235 | } | 236 | } |
| 236 | 237 | ||
diff --git a/drivers/memstick/core/mspro_block.c b/drivers/memstick/core/mspro_block.c index de143deb06f0..7847bbc1440d 100644 --- a/drivers/memstick/core/mspro_block.c +++ b/drivers/memstick/core/mspro_block.c | |||
| @@ -672,15 +672,14 @@ try_again: | |||
| 672 | msb->req_sg); | 672 | msb->req_sg); |
| 673 | 673 | ||
| 674 | if (!msb->seg_count) { | 674 | if (!msb->seg_count) { |
| 675 | chunk = __blk_end_request(msb->block_req, -ENOMEM, | 675 | chunk = __blk_end_request_cur(msb->block_req, -ENOMEM); |
| 676 | blk_rq_cur_bytes(msb->block_req)); | ||
| 677 | continue; | 676 | continue; |
| 678 | } | 677 | } |
| 679 | 678 | ||
| 680 | t_sec = msb->block_req->sector << 9; | 679 | t_sec = blk_rq_pos(msb->block_req) << 9; |
| 681 | sector_div(t_sec, msb->page_size); | 680 | sector_div(t_sec, msb->page_size); |
| 682 | 681 | ||
| 683 | count = msb->block_req->nr_sectors << 9; | 682 | count = blk_rq_bytes(msb->block_req); |
| 684 | count /= msb->page_size; | 683 | count /= msb->page_size; |
| 685 | 684 | ||
| 686 | param.system = msb->system; | 685 | param.system = msb->system; |
| @@ -705,8 +704,8 @@ try_again: | |||
| 705 | return 0; | 704 | return 0; |
| 706 | } | 705 | } |
| 707 | 706 | ||
| 708 | dev_dbg(&card->dev, "elv_next\n"); | 707 | dev_dbg(&card->dev, "blk_fetch\n"); |
| 709 | msb->block_req = elv_next_request(msb->queue); | 708 | msb->block_req = blk_fetch_request(msb->queue); |
| 710 | if (!msb->block_req) { | 709 | if (!msb->block_req) { |
| 711 | dev_dbg(&card->dev, "issue end\n"); | 710 | dev_dbg(&card->dev, "issue end\n"); |
| 712 | return -EAGAIN; | 711 | return -EAGAIN; |
| @@ -745,7 +744,7 @@ static int mspro_block_complete_req(struct memstick_dev *card, int error) | |||
| 745 | t_len *= msb->page_size; | 744 | t_len *= msb->page_size; |
| 746 | } | 745 | } |
| 747 | } else | 746 | } else |
| 748 | t_len = msb->block_req->nr_sectors << 9; | 747 | t_len = blk_rq_bytes(msb->block_req); |
| 749 | 748 | ||
| 750 | dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error); | 749 | dev_dbg(&card->dev, "transferred %x (%d)\n", t_len, error); |
| 751 | 750 | ||
| @@ -825,8 +824,8 @@ static void mspro_block_submit_req(struct request_queue *q) | |||
| 825 | return; | 824 | return; |
| 826 | 825 | ||
| 827 | if (msb->eject) { | 826 | if (msb->eject) { |
| 828 | while ((req = elv_next_request(q)) != NULL) | 827 | while ((req = blk_fetch_request(q)) != NULL) |
| 829 | __blk_end_request(req, -ENODEV, blk_rq_bytes(req)); | 828 | __blk_end_request_all(req, -ENODEV); |
| 830 | 829 | ||
| 831 | return; | 830 | return; |
| 832 | } | 831 | } |
| @@ -1243,7 +1242,7 @@ static int mspro_block_init_disk(struct memstick_dev *card) | |||
| 1243 | 1242 | ||
| 1244 | sprintf(msb->disk->disk_name, "mspblk%d", disk_id); | 1243 | sprintf(msb->disk->disk_name, "mspblk%d", disk_id); |
| 1245 | 1244 | ||
| 1246 | blk_queue_hardsect_size(msb->queue, msb->page_size); | 1245 | blk_queue_logical_block_size(msb->queue, msb->page_size); |
| 1247 | 1246 | ||
| 1248 | capacity = be16_to_cpu(sys_info->user_block_count); | 1247 | capacity = be16_to_cpu(sys_info->user_block_count); |
| 1249 | capacity *= be16_to_cpu(sys_info->block_size); | 1248 | capacity *= be16_to_cpu(sys_info->block_size); |
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c index a9019f081b97..79f5433359f9 100644 --- a/drivers/message/fusion/mptsas.c +++ b/drivers/message/fusion/mptsas.c | |||
| @@ -1277,8 +1277,8 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1277 | /* do we need to support multiple segments? */ | 1277 | /* do we need to support multiple segments? */ |
| 1278 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { | 1278 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { |
| 1279 | printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", | 1279 | printk(MYIOC_s_ERR_FMT "%s: multiple segments req %u %u, rsp %u %u\n", |
| 1280 | ioc->name, __func__, req->bio->bi_vcnt, req->data_len, | 1280 | ioc->name, __func__, req->bio->bi_vcnt, blk_rq_bytes(req), |
| 1281 | rsp->bio->bi_vcnt, rsp->data_len); | 1281 | rsp->bio->bi_vcnt, blk_rq_bytes(rsp)); |
| 1282 | return -EINVAL; | 1282 | return -EINVAL; |
| 1283 | } | 1283 | } |
| 1284 | 1284 | ||
| @@ -1295,7 +1295,7 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1295 | smpreq = (SmpPassthroughRequest_t *)mf; | 1295 | smpreq = (SmpPassthroughRequest_t *)mf; |
| 1296 | memset(smpreq, 0, sizeof(*smpreq)); | 1296 | memset(smpreq, 0, sizeof(*smpreq)); |
| 1297 | 1297 | ||
| 1298 | smpreq->RequestDataLength = cpu_to_le16(req->data_len - 4); | 1298 | smpreq->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); |
| 1299 | smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH; | 1299 | smpreq->Function = MPI_FUNCTION_SMP_PASSTHROUGH; |
| 1300 | 1300 | ||
| 1301 | if (rphy) | 1301 | if (rphy) |
| @@ -1321,10 +1321,10 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1321 | MPI_SGE_FLAGS_END_OF_BUFFER | | 1321 | MPI_SGE_FLAGS_END_OF_BUFFER | |
| 1322 | MPI_SGE_FLAGS_DIRECTION | | 1322 | MPI_SGE_FLAGS_DIRECTION | |
| 1323 | mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT; | 1323 | mpt_addr_size()) << MPI_SGE_FLAGS_SHIFT; |
| 1324 | flagsLength |= (req->data_len - 4); | 1324 | flagsLength |= (blk_rq_bytes(req) - 4); |
| 1325 | 1325 | ||
| 1326 | dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio), | 1326 | dma_addr_out = pci_map_single(ioc->pcidev, bio_data(req->bio), |
| 1327 | req->data_len, PCI_DMA_BIDIRECTIONAL); | 1327 | blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); |
| 1328 | if (!dma_addr_out) | 1328 | if (!dma_addr_out) |
| 1329 | goto put_mf; | 1329 | goto put_mf; |
| 1330 | mpt_add_sge(psge, flagsLength, dma_addr_out); | 1330 | mpt_add_sge(psge, flagsLength, dma_addr_out); |
| @@ -1332,9 +1332,9 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1332 | 1332 | ||
| 1333 | /* response */ | 1333 | /* response */ |
| 1334 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; | 1334 | flagsLength = MPT_SGE_FLAGS_SSIMPLE_READ; |
| 1335 | flagsLength |= rsp->data_len + 4; | 1335 | flagsLength |= blk_rq_bytes(rsp) + 4; |
| 1336 | dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio), | 1336 | dma_addr_in = pci_map_single(ioc->pcidev, bio_data(rsp->bio), |
| 1337 | rsp->data_len, PCI_DMA_BIDIRECTIONAL); | 1337 | blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); |
| 1338 | if (!dma_addr_in) | 1338 | if (!dma_addr_in) |
| 1339 | goto unmap; | 1339 | goto unmap; |
| 1340 | mpt_add_sge(psge, flagsLength, dma_addr_in); | 1340 | mpt_add_sge(psge, flagsLength, dma_addr_in); |
| @@ -1357,8 +1357,8 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1357 | smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply; | 1357 | smprep = (SmpPassthroughReply_t *)ioc->sas_mgmt.reply; |
| 1358 | memcpy(req->sense, smprep, sizeof(*smprep)); | 1358 | memcpy(req->sense, smprep, sizeof(*smprep)); |
| 1359 | req->sense_len = sizeof(*smprep); | 1359 | req->sense_len = sizeof(*smprep); |
| 1360 | req->data_len = 0; | 1360 | req->resid_len = 0; |
| 1361 | rsp->data_len -= smprep->ResponseDataLength; | 1361 | rsp->resid_len -= smprep->ResponseDataLength; |
| 1362 | } else { | 1362 | } else { |
| 1363 | printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n", | 1363 | printk(MYIOC_s_ERR_FMT "%s: smp passthru reply failed to be returned\n", |
| 1364 | ioc->name, __func__); | 1364 | ioc->name, __func__); |
| @@ -1366,10 +1366,10 @@ static int mptsas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1366 | } | 1366 | } |
| 1367 | unmap: | 1367 | unmap: |
| 1368 | if (dma_addr_out) | 1368 | if (dma_addr_out) |
| 1369 | pci_unmap_single(ioc->pcidev, dma_addr_out, req->data_len, | 1369 | pci_unmap_single(ioc->pcidev, dma_addr_out, blk_rq_bytes(req), |
| 1370 | PCI_DMA_BIDIRECTIONAL); | 1370 | PCI_DMA_BIDIRECTIONAL); |
| 1371 | if (dma_addr_in) | 1371 | if (dma_addr_in) |
| 1372 | pci_unmap_single(ioc->pcidev, dma_addr_in, rsp->data_len, | 1372 | pci_unmap_single(ioc->pcidev, dma_addr_in, blk_rq_bytes(rsp), |
| 1373 | PCI_DMA_BIDIRECTIONAL); | 1373 | PCI_DMA_BIDIRECTIONAL); |
| 1374 | put_mf: | 1374 | put_mf: |
| 1375 | if (mf) | 1375 | if (mf) |
diff --git a/drivers/message/i2o/i2o_block.c b/drivers/message/i2o/i2o_block.c index a443e136dc41..335d4c78a775 100644 --- a/drivers/message/i2o/i2o_block.c +++ b/drivers/message/i2o/i2o_block.c | |||
| @@ -426,15 +426,9 @@ static void i2o_block_end_request(struct request *req, int error, | |||
| 426 | struct request_queue *q = req->q; | 426 | struct request_queue *q = req->q; |
| 427 | unsigned long flags; | 427 | unsigned long flags; |
| 428 | 428 | ||
| 429 | if (blk_end_request(req, error, nr_bytes)) { | 429 | if (blk_end_request(req, error, nr_bytes)) |
| 430 | int leftover = (req->hard_nr_sectors << KERNEL_SECTOR_SHIFT); | ||
| 431 | |||
| 432 | if (blk_pc_request(req)) | ||
| 433 | leftover = req->data_len; | ||
| 434 | |||
| 435 | if (error) | 430 | if (error) |
| 436 | blk_end_request(req, -EIO, leftover); | 431 | blk_end_request_all(req, -EIO); |
| 437 | } | ||
| 438 | 432 | ||
| 439 | spin_lock_irqsave(q->queue_lock, flags); | 433 | spin_lock_irqsave(q->queue_lock, flags); |
| 440 | 434 | ||
| @@ -761,7 +755,7 @@ static int i2o_block_transfer(struct request *req) | |||
| 761 | break; | 755 | break; |
| 762 | 756 | ||
| 763 | case CACHE_SMARTFETCH: | 757 | case CACHE_SMARTFETCH: |
| 764 | if (req->nr_sectors > 16) | 758 | if (blk_rq_sectors(req) > 16) |
| 765 | ctl_flags = 0x201F0008; | 759 | ctl_flags = 0x201F0008; |
| 766 | else | 760 | else |
| 767 | ctl_flags = 0x001F0000; | 761 | ctl_flags = 0x001F0000; |
| @@ -781,13 +775,13 @@ static int i2o_block_transfer(struct request *req) | |||
| 781 | ctl_flags = 0x001F0010; | 775 | ctl_flags = 0x001F0010; |
| 782 | break; | 776 | break; |
| 783 | case CACHE_SMARTBACK: | 777 | case CACHE_SMARTBACK: |
| 784 | if (req->nr_sectors > 16) | 778 | if (blk_rq_sectors(req) > 16) |
| 785 | ctl_flags = 0x001F0004; | 779 | ctl_flags = 0x001F0004; |
| 786 | else | 780 | else |
| 787 | ctl_flags = 0x001F0010; | 781 | ctl_flags = 0x001F0010; |
| 788 | break; | 782 | break; |
| 789 | case CACHE_SMARTTHROUGH: | 783 | case CACHE_SMARTTHROUGH: |
| 790 | if (req->nr_sectors > 16) | 784 | if (blk_rq_sectors(req) > 16) |
| 791 | ctl_flags = 0x001F0004; | 785 | ctl_flags = 0x001F0004; |
| 792 | else | 786 | else |
| 793 | ctl_flags = 0x001F0010; | 787 | ctl_flags = 0x001F0010; |
| @@ -800,8 +794,9 @@ static int i2o_block_transfer(struct request *req) | |||
| 800 | if (c->adaptec) { | 794 | if (c->adaptec) { |
| 801 | u8 cmd[10]; | 795 | u8 cmd[10]; |
| 802 | u32 scsi_flags; | 796 | u32 scsi_flags; |
| 803 | u16 hwsec = queue_hardsect_size(req->q) >> KERNEL_SECTOR_SHIFT; | 797 | u16 hwsec; |
| 804 | 798 | ||
| 799 | hwsec = queue_logical_block_size(req->q) >> KERNEL_SECTOR_SHIFT; | ||
| 805 | memset(cmd, 0, 10); | 800 | memset(cmd, 0, 10); |
| 806 | 801 | ||
| 807 | sgl_offset = SGL_OFFSET_12; | 802 | sgl_offset = SGL_OFFSET_12; |
| @@ -827,22 +822,22 @@ static int i2o_block_transfer(struct request *req) | |||
| 827 | 822 | ||
| 828 | *mptr++ = cpu_to_le32(scsi_flags); | 823 | *mptr++ = cpu_to_le32(scsi_flags); |
| 829 | 824 | ||
| 830 | *((u32 *) & cmd[2]) = cpu_to_be32(req->sector * hwsec); | 825 | *((u32 *) & cmd[2]) = cpu_to_be32(blk_rq_pos(req) * hwsec); |
| 831 | *((u16 *) & cmd[7]) = cpu_to_be16(req->nr_sectors * hwsec); | 826 | *((u16 *) & cmd[7]) = cpu_to_be16(blk_rq_sectors(req) * hwsec); |
| 832 | 827 | ||
| 833 | memcpy(mptr, cmd, 10); | 828 | memcpy(mptr, cmd, 10); |
| 834 | mptr += 4; | 829 | mptr += 4; |
| 835 | *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT); | 830 | *mptr++ = cpu_to_le32(blk_rq_bytes(req)); |
| 836 | } else | 831 | } else |
| 837 | #endif | 832 | #endif |
| 838 | { | 833 | { |
| 839 | msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); | 834 | msg->u.head[1] = cpu_to_le32(cmd | HOST_TID << 12 | tid); |
| 840 | *mptr++ = cpu_to_le32(ctl_flags); | 835 | *mptr++ = cpu_to_le32(ctl_flags); |
| 841 | *mptr++ = cpu_to_le32(req->nr_sectors << KERNEL_SECTOR_SHIFT); | 836 | *mptr++ = cpu_to_le32(blk_rq_bytes(req)); |
| 842 | *mptr++ = | 837 | *mptr++ = |
| 843 | cpu_to_le32((u32) (req->sector << KERNEL_SECTOR_SHIFT)); | 838 | cpu_to_le32((u32) (blk_rq_pos(req) << KERNEL_SECTOR_SHIFT)); |
| 844 | *mptr++ = | 839 | *mptr++ = |
| 845 | cpu_to_le32(req->sector >> (32 - KERNEL_SECTOR_SHIFT)); | 840 | cpu_to_le32(blk_rq_pos(req) >> (32 - KERNEL_SECTOR_SHIFT)); |
| 846 | } | 841 | } |
| 847 | 842 | ||
| 848 | if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { | 843 | if (!i2o_block_sglist_alloc(c, ireq, &mptr)) { |
| @@ -883,7 +878,7 @@ static void i2o_block_request_fn(struct request_queue *q) | |||
| 883 | struct request *req; | 878 | struct request *req; |
| 884 | 879 | ||
| 885 | while (!blk_queue_plugged(q)) { | 880 | while (!blk_queue_plugged(q)) { |
| 886 | req = elv_next_request(q); | 881 | req = blk_peek_request(q); |
| 887 | if (!req) | 882 | if (!req) |
| 888 | break; | 883 | break; |
| 889 | 884 | ||
| @@ -896,7 +891,7 @@ static void i2o_block_request_fn(struct request_queue *q) | |||
| 896 | 891 | ||
| 897 | if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { | 892 | if (queue_depth < I2O_BLOCK_MAX_OPEN_REQUESTS) { |
| 898 | if (!i2o_block_transfer(req)) { | 893 | if (!i2o_block_transfer(req)) { |
| 899 | blkdev_dequeue_request(req); | 894 | blk_start_request(req); |
| 900 | continue; | 895 | continue; |
| 901 | } else | 896 | } else |
| 902 | osm_info("transfer error\n"); | 897 | osm_info("transfer error\n"); |
| @@ -922,8 +917,10 @@ static void i2o_block_request_fn(struct request_queue *q) | |||
| 922 | blk_stop_queue(q); | 917 | blk_stop_queue(q); |
| 923 | break; | 918 | break; |
| 924 | } | 919 | } |
| 925 | } else | 920 | } else { |
| 926 | end_request(req, 0); | 921 | blk_start_request(req); |
| 922 | __blk_end_request_all(req, -EIO); | ||
| 923 | } | ||
| 927 | } | 924 | } |
| 928 | }; | 925 | }; |
| 929 | 926 | ||
| @@ -1082,7 +1079,7 @@ static int i2o_block_probe(struct device *dev) | |||
| 1082 | */ | 1079 | */ |
| 1083 | if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || | 1080 | if (!i2o_parm_field_get(i2o_dev, 0x0004, 1, &blocksize, 4) || |
| 1084 | !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { | 1081 | !i2o_parm_field_get(i2o_dev, 0x0000, 3, &blocksize, 4)) { |
| 1085 | blk_queue_hardsect_size(queue, le32_to_cpu(blocksize)); | 1082 | blk_queue_logical_block_size(queue, le32_to_cpu(blocksize)); |
| 1086 | } else | 1083 | } else |
| 1087 | osm_warn("unable to get blocksize of %s\n", gd->disk_name); | 1084 | osm_warn("unable to get blocksize of %s\n", gd->disk_name); |
| 1088 | 1085 | ||
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index b25e9b6516ae..98ffc41eaf2c 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
| @@ -243,7 +243,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 243 | brq.mrq.cmd = &brq.cmd; | 243 | brq.mrq.cmd = &brq.cmd; |
| 244 | brq.mrq.data = &brq.data; | 244 | brq.mrq.data = &brq.data; |
| 245 | 245 | ||
| 246 | brq.cmd.arg = req->sector; | 246 | brq.cmd.arg = blk_rq_pos(req); |
| 247 | if (!mmc_card_blockaddr(card)) | 247 | if (!mmc_card_blockaddr(card)) |
| 248 | brq.cmd.arg <<= 9; | 248 | brq.cmd.arg <<= 9; |
| 249 | brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; | 249 | brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
| @@ -251,7 +251,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 251 | brq.stop.opcode = MMC_STOP_TRANSMISSION; | 251 | brq.stop.opcode = MMC_STOP_TRANSMISSION; |
| 252 | brq.stop.arg = 0; | 252 | brq.stop.arg = 0; |
| 253 | brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | 253 | brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; |
| 254 | brq.data.blocks = req->nr_sectors; | 254 | brq.data.blocks = blk_rq_sectors(req); |
| 255 | 255 | ||
| 256 | /* | 256 | /* |
| 257 | * The block layer doesn't support all sector count | 257 | * The block layer doesn't support all sector count |
| @@ -301,7 +301,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 301 | * Adjust the sg list so it is the same size as the | 301 | * Adjust the sg list so it is the same size as the |
| 302 | * request. | 302 | * request. |
| 303 | */ | 303 | */ |
| 304 | if (brq.data.blocks != req->nr_sectors) { | 304 | if (brq.data.blocks != blk_rq_sectors(req)) { |
| 305 | int i, data_size = brq.data.blocks << 9; | 305 | int i, data_size = brq.data.blocks << 9; |
| 306 | struct scatterlist *sg; | 306 | struct scatterlist *sg; |
| 307 | 307 | ||
| @@ -352,8 +352,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
| 352 | printk(KERN_ERR "%s: error %d transferring data," | 352 | printk(KERN_ERR "%s: error %d transferring data," |
| 353 | " sector %u, nr %u, card status %#x\n", | 353 | " sector %u, nr %u, card status %#x\n", |
| 354 | req->rq_disk->disk_name, brq.data.error, | 354 | req->rq_disk->disk_name, brq.data.error, |
| 355 | (unsigned)req->sector, | 355 | (unsigned)blk_rq_pos(req), |
| 356 | (unsigned)req->nr_sectors, status); | 356 | (unsigned)blk_rq_sectors(req), status); |
| 357 | } | 357 | } |
| 358 | 358 | ||
| 359 | if (brq.stop.error) { | 359 | if (brq.stop.error) { |
| @@ -521,7 +521,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
| 521 | 521 | ||
| 522 | sprintf(md->disk->disk_name, "mmcblk%d", devidx); | 522 | sprintf(md->disk->disk_name, "mmcblk%d", devidx); |
| 523 | 523 | ||
| 524 | blk_queue_hardsect_size(md->queue.queue, 512); | 524 | blk_queue_logical_block_size(md->queue.queue, 512); |
| 525 | 525 | ||
| 526 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { | 526 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { |
| 527 | /* | 527 | /* |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 7a72e75d5c67..49e582356c65 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
| @@ -55,7 +55,7 @@ static int mmc_queue_thread(void *d) | |||
| 55 | spin_lock_irq(q->queue_lock); | 55 | spin_lock_irq(q->queue_lock); |
| 56 | set_current_state(TASK_INTERRUPTIBLE); | 56 | set_current_state(TASK_INTERRUPTIBLE); |
| 57 | if (!blk_queue_plugged(q)) | 57 | if (!blk_queue_plugged(q)) |
| 58 | req = elv_next_request(q); | 58 | req = blk_fetch_request(q); |
| 59 | mq->req = req; | 59 | mq->req = req; |
| 60 | spin_unlock_irq(q->queue_lock); | 60 | spin_unlock_irq(q->queue_lock); |
| 61 | 61 | ||
| @@ -88,16 +88,11 @@ static void mmc_request(struct request_queue *q) | |||
| 88 | { | 88 | { |
| 89 | struct mmc_queue *mq = q->queuedata; | 89 | struct mmc_queue *mq = q->queuedata; |
| 90 | struct request *req; | 90 | struct request *req; |
| 91 | int ret; | ||
| 92 | 91 | ||
| 93 | if (!mq) { | 92 | if (!mq) { |
| 94 | printk(KERN_ERR "MMC: killing requests for dead queue\n"); | 93 | printk(KERN_ERR "MMC: killing requests for dead queue\n"); |
| 95 | while ((req = elv_next_request(q)) != NULL) { | 94 | while ((req = blk_fetch_request(q)) != NULL) |
| 96 | do { | 95 | __blk_end_request_all(req, -EIO); |
| 97 | ret = __blk_end_request(req, -EIO, | ||
| 98 | blk_rq_cur_bytes(req)); | ||
| 99 | } while (ret); | ||
| 100 | } | ||
| 101 | return; | 96 | return; |
| 102 | } | 97 | } |
| 103 | 98 | ||
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c index c643d0fe118f..b56d72ff06e9 100644 --- a/drivers/mmc/host/mvsdio.c +++ b/drivers/mmc/host/mvsdio.c | |||
| @@ -64,6 +64,31 @@ static int mvsd_setup_data(struct mvsd_host *host, struct mmc_data *data) | |||
| 64 | unsigned int tmout; | 64 | unsigned int tmout; |
| 65 | int tmout_index; | 65 | int tmout_index; |
| 66 | 66 | ||
| 67 | /* | ||
| 68 | * Hardware weirdness. The FIFO_EMPTY bit of the HW_STATE | ||
| 69 | * register is sometimes not set before a while when some | ||
| 70 | * "unusual" data block sizes are used (such as with the SWITCH | ||
| 71 | * command), even despite the fact that the XFER_DONE interrupt | ||
| 72 | * was raised. And if another data transfer starts before | ||
| 73 | * this bit comes to good sense (which eventually happens by | ||
| 74 | * itself) then the new transfer simply fails with a timeout. | ||
| 75 | */ | ||
| 76 | if (!(mvsd_read(MVSD_HW_STATE) & (1 << 13))) { | ||
| 77 | unsigned long t = jiffies + HZ; | ||
| 78 | unsigned int hw_state, count = 0; | ||
| 79 | do { | ||
| 80 | if (time_after(jiffies, t)) { | ||
| 81 | dev_warn(host->dev, "FIFO_EMPTY bit missing\n"); | ||
| 82 | break; | ||
| 83 | } | ||
| 84 | hw_state = mvsd_read(MVSD_HW_STATE); | ||
| 85 | count++; | ||
| 86 | } while (!(hw_state & (1 << 13))); | ||
| 87 | dev_dbg(host->dev, "*** wait for FIFO_EMPTY bit " | ||
| 88 | "(hw=0x%04x, count=%d, jiffies=%ld)\n", | ||
| 89 | hw_state, count, jiffies - (t - HZ)); | ||
| 90 | } | ||
| 91 | |||
| 67 | /* If timeout=0 then maximum timeout index is used. */ | 92 | /* If timeout=0 then maximum timeout index is used. */ |
| 68 | tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk); | 93 | tmout = DIV_ROUND_UP(data->timeout_ns, host->ns_per_clk); |
| 69 | tmout += data->timeout_clks; | 94 | tmout += data->timeout_clks; |
| @@ -620,9 +645,18 @@ static void mvsd_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
| 620 | if (ios->bus_width == MMC_BUS_WIDTH_4) | 645 | if (ios->bus_width == MMC_BUS_WIDTH_4) |
| 621 | ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS; | 646 | ctrl_reg |= MVSD_HOST_CTRL_DATA_WIDTH_4_BITS; |
| 622 | 647 | ||
| 648 | /* | ||
| 649 | * The HI_SPEED_EN bit is causing trouble with many (but not all) | ||
| 650 | * high speed SD, SDHC and SDIO cards. Not enabling that bit | ||
| 651 | * makes all cards work. So let's just ignore that bit for now | ||
| 652 | * and revisit this issue if problems for not enabling this bit | ||
| 653 | * are ever reported. | ||
| 654 | */ | ||
| 655 | #if 0 | ||
| 623 | if (ios->timing == MMC_TIMING_MMC_HS || | 656 | if (ios->timing == MMC_TIMING_MMC_HS || |
| 624 | ios->timing == MMC_TIMING_SD_HS) | 657 | ios->timing == MMC_TIMING_SD_HS) |
| 625 | ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN; | 658 | ctrl_reg |= MVSD_HOST_CTRL_HI_SPEED_EN; |
| 659 | #endif | ||
| 626 | 660 | ||
| 627 | host->ctrl = ctrl_reg; | 661 | host->ctrl = ctrl_reg; |
| 628 | mvsd_write(MVSD_HOST_CTRL, ctrl_reg); | 662 | mvsd_write(MVSD_HOST_CTRL, ctrl_reg); |
| @@ -882,3 +916,4 @@ module_param(nodma, int, 0); | |||
| 882 | MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre"); | 916 | MODULE_AUTHOR("Maen Suleiman, Nicolas Pitre"); |
| 883 | MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver"); | 917 | MODULE_DESCRIPTION("Marvell MMC,SD,SDIO Host Controller driver"); |
| 884 | MODULE_LICENSE("GPL"); | 918 | MODULE_LICENSE("GPL"); |
| 919 | MODULE_ALIAS("platform:mvsdio"); | ||
diff --git a/drivers/mmc/host/mxcmmc.c b/drivers/mmc/host/mxcmmc.c index b4a615c55f28..f4cbe473670e 100644 --- a/drivers/mmc/host/mxcmmc.c +++ b/drivers/mmc/host/mxcmmc.c | |||
| @@ -140,6 +140,8 @@ struct mxcmci_host { | |||
| 140 | struct work_struct datawork; | 140 | struct work_struct datawork; |
| 141 | }; | 141 | }; |
| 142 | 142 | ||
| 143 | static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios); | ||
| 144 | |||
| 143 | static inline int mxcmci_use_dma(struct mxcmci_host *host) | 145 | static inline int mxcmci_use_dma(struct mxcmci_host *host) |
| 144 | { | 146 | { |
| 145 | return host->do_dma; | 147 | return host->do_dma; |
| @@ -160,7 +162,7 @@ static void mxcmci_softreset(struct mxcmci_host *host) | |||
| 160 | writew(0xff, host->base + MMC_REG_RES_TO); | 162 | writew(0xff, host->base + MMC_REG_RES_TO); |
| 161 | } | 163 | } |
| 162 | 164 | ||
| 163 | static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | 165 | static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) |
| 164 | { | 166 | { |
| 165 | unsigned int nob = data->blocks; | 167 | unsigned int nob = data->blocks; |
| 166 | unsigned int blksz = data->blksz; | 168 | unsigned int blksz = data->blksz; |
| @@ -168,6 +170,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
| 168 | #ifdef HAS_DMA | 170 | #ifdef HAS_DMA |
| 169 | struct scatterlist *sg; | 171 | struct scatterlist *sg; |
| 170 | int i; | 172 | int i; |
| 173 | int ret; | ||
| 171 | #endif | 174 | #endif |
| 172 | if (data->flags & MMC_DATA_STREAM) | 175 | if (data->flags & MMC_DATA_STREAM) |
| 173 | nob = 0xffff; | 176 | nob = 0xffff; |
| @@ -183,7 +186,7 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
| 183 | for_each_sg(data->sg, sg, data->sg_len, i) { | 186 | for_each_sg(data->sg, sg, data->sg_len, i) { |
| 184 | if (sg->offset & 3 || sg->length & 3) { | 187 | if (sg->offset & 3 || sg->length & 3) { |
| 185 | host->do_dma = 0; | 188 | host->do_dma = 0; |
| 186 | return; | 189 | return 0; |
| 187 | } | 190 | } |
| 188 | } | 191 | } |
| 189 | 192 | ||
| @@ -192,23 +195,30 @@ static void mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data) | |||
| 192 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, | 195 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, |
| 193 | data->sg_len, host->dma_dir); | 196 | data->sg_len, host->dma_dir); |
| 194 | 197 | ||
| 195 | imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, | 198 | ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, |
| 196 | host->res->start + MMC_REG_BUFFER_ACCESS, | 199 | datasize, |
| 197 | DMA_MODE_READ); | 200 | host->res->start + MMC_REG_BUFFER_ACCESS, |
| 201 | DMA_MODE_READ); | ||
| 198 | } else { | 202 | } else { |
| 199 | host->dma_dir = DMA_TO_DEVICE; | 203 | host->dma_dir = DMA_TO_DEVICE; |
| 200 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, | 204 | host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg, |
| 201 | data->sg_len, host->dma_dir); | 205 | data->sg_len, host->dma_dir); |
| 202 | 206 | ||
| 203 | imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, datasize, | 207 | ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents, |
| 204 | host->res->start + MMC_REG_BUFFER_ACCESS, | 208 | datasize, |
| 205 | DMA_MODE_WRITE); | 209 | host->res->start + MMC_REG_BUFFER_ACCESS, |
| 210 | DMA_MODE_WRITE); | ||
| 206 | } | 211 | } |
| 207 | 212 | ||
| 213 | if (ret) { | ||
| 214 | dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret); | ||
| 215 | return ret; | ||
| 216 | } | ||
| 208 | wmb(); | 217 | wmb(); |
| 209 | 218 | ||
| 210 | imx_dma_enable(host->dma); | 219 | imx_dma_enable(host->dma); |
| 211 | #endif /* HAS_DMA */ | 220 | #endif /* HAS_DMA */ |
| 221 | return 0; | ||
| 212 | } | 222 | } |
| 213 | 223 | ||
| 214 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, | 224 | static int mxcmci_start_cmd(struct mxcmci_host *host, struct mmc_command *cmd, |
| @@ -345,8 +355,11 @@ static int mxcmci_poll_status(struct mxcmci_host *host, u32 mask) | |||
| 345 | stat = readl(host->base + MMC_REG_STATUS); | 355 | stat = readl(host->base + MMC_REG_STATUS); |
| 346 | if (stat & STATUS_ERR_MASK) | 356 | if (stat & STATUS_ERR_MASK) |
| 347 | return stat; | 357 | return stat; |
| 348 | if (time_after(jiffies, timeout)) | 358 | if (time_after(jiffies, timeout)) { |
| 359 | mxcmci_softreset(host); | ||
| 360 | mxcmci_set_clk_rate(host, host->clock); | ||
| 349 | return STATUS_TIME_OUT_READ; | 361 | return STATUS_TIME_OUT_READ; |
| 362 | } | ||
| 350 | if (stat & mask) | 363 | if (stat & mask) |
| 351 | return 0; | 364 | return 0; |
| 352 | cpu_relax(); | 365 | cpu_relax(); |
| @@ -531,6 +544,7 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) | |||
| 531 | { | 544 | { |
| 532 | struct mxcmci_host *host = mmc_priv(mmc); | 545 | struct mxcmci_host *host = mmc_priv(mmc); |
| 533 | unsigned int cmdat = host->cmdat; | 546 | unsigned int cmdat = host->cmdat; |
| 547 | int error; | ||
| 534 | 548 | ||
| 535 | WARN_ON(host->req != NULL); | 549 | WARN_ON(host->req != NULL); |
| 536 | 550 | ||
| @@ -540,7 +554,12 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) | |||
| 540 | host->do_dma = 1; | 554 | host->do_dma = 1; |
| 541 | #endif | 555 | #endif |
| 542 | if (req->data) { | 556 | if (req->data) { |
| 543 | mxcmci_setup_data(host, req->data); | 557 | error = mxcmci_setup_data(host, req->data); |
| 558 | if (error) { | ||
| 559 | req->cmd->error = error; | ||
| 560 | goto out; | ||
| 561 | } | ||
| 562 | |||
| 544 | 563 | ||
| 545 | cmdat |= CMD_DAT_CONT_DATA_ENABLE; | 564 | cmdat |= CMD_DAT_CONT_DATA_ENABLE; |
| 546 | 565 | ||
| @@ -548,7 +567,9 @@ static void mxcmci_request(struct mmc_host *mmc, struct mmc_request *req) | |||
| 548 | cmdat |= CMD_DAT_CONT_WRITE; | 567 | cmdat |= CMD_DAT_CONT_WRITE; |
| 549 | } | 568 | } |
| 550 | 569 | ||
| 551 | if (mxcmci_start_cmd(host, req->cmd, cmdat)) | 570 | error = mxcmci_start_cmd(host, req->cmd, cmdat); |
| 571 | out: | ||
| 572 | if (error) | ||
| 552 | mxcmci_finish_request(host, req); | 573 | mxcmci_finish_request(host, req); |
| 553 | } | 574 | } |
| 554 | 575 | ||
| @@ -724,7 +745,9 @@ static int mxcmci_probe(struct platform_device *pdev) | |||
| 724 | goto out_clk_put; | 745 | goto out_clk_put; |
| 725 | } | 746 | } |
| 726 | 747 | ||
| 727 | mmc->f_min = clk_get_rate(host->clk) >> 7; | 748 | mmc->f_min = clk_get_rate(host->clk) >> 16; |
| 749 | if (mmc->f_min < 400000) | ||
| 750 | mmc->f_min = 400000; | ||
| 728 | mmc->f_max = clk_get_rate(host->clk) >> 1; | 751 | mmc->f_max = clk_get_rate(host->clk) >> 1; |
| 729 | 752 | ||
| 730 | /* recommended in data sheet */ | 753 | /* recommended in data sheet */ |
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c index bfa25c01c872..dceb5ee3bda0 100644 --- a/drivers/mmc/host/omap.c +++ b/drivers/mmc/host/omap.c | |||
| @@ -822,7 +822,7 @@ static irqreturn_t mmc_omap_irq(int irq, void *dev_id) | |||
| 822 | del_timer(&host->cmd_abort_timer); | 822 | del_timer(&host->cmd_abort_timer); |
| 823 | host->abort = 1; | 823 | host->abort = 1; |
| 824 | OMAP_MMC_WRITE(host, IE, 0); | 824 | OMAP_MMC_WRITE(host, IE, 0); |
| 825 | disable_irq(host->irq); | 825 | disable_irq_nosync(host->irq); |
| 826 | schedule_work(&host->cmd_abort_work); | 826 | schedule_work(&host->cmd_abort_work); |
| 827 | return IRQ_HANDLED; | 827 | return IRQ_HANDLED; |
| 828 | } | 828 | } |
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c index e62a22a7f00c..c40cb96255a2 100644 --- a/drivers/mmc/host/omap_hsmmc.c +++ b/drivers/mmc/host/omap_hsmmc.c | |||
| @@ -680,7 +680,7 @@ static void mmc_omap_dma_cb(int lch, u16 ch_status, void *data) | |||
| 680 | host->dma_ch = -1; | 680 | host->dma_ch = -1; |
| 681 | /* | 681 | /* |
| 682 | * DMA Callback: run in interrupt context. | 682 | * DMA Callback: run in interrupt context. |
| 683 | * mutex_unlock will through a kernel warning if used. | 683 | * mutex_unlock will throw a kernel warning if used. |
| 684 | */ | 684 | */ |
| 685 | up(&host->sem); | 685 | up(&host->sem); |
| 686 | } | 686 | } |
diff --git a/drivers/mmc/host/sdhci-of.c b/drivers/mmc/host/sdhci-of.c index 3ff4ac3abe8b..128c614d11aa 100644 --- a/drivers/mmc/host/sdhci-of.c +++ b/drivers/mmc/host/sdhci-of.c | |||
| @@ -55,7 +55,13 @@ static u32 esdhc_readl(struct sdhci_host *host, int reg) | |||
| 55 | 55 | ||
| 56 | static u16 esdhc_readw(struct sdhci_host *host, int reg) | 56 | static u16 esdhc_readw(struct sdhci_host *host, int reg) |
| 57 | { | 57 | { |
| 58 | return in_be16(host->ioaddr + (reg ^ 0x2)); | 58 | u16 ret; |
| 59 | |||
| 60 | if (unlikely(reg == SDHCI_HOST_VERSION)) | ||
| 61 | ret = in_be16(host->ioaddr + reg); | ||
| 62 | else | ||
| 63 | ret = in_be16(host->ioaddr + (reg ^ 0x2)); | ||
| 64 | return ret; | ||
| 59 | } | 65 | } |
| 60 | 66 | ||
| 61 | static u8 esdhc_readb(struct sdhci_host *host, int reg) | 67 | static u8 esdhc_readb(struct sdhci_host *host, int reg) |
| @@ -277,6 +283,7 @@ static int __devexit sdhci_of_remove(struct of_device *ofdev) | |||
| 277 | static const struct of_device_id sdhci_of_match[] = { | 283 | static const struct of_device_id sdhci_of_match[] = { |
| 278 | { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, }, | 284 | { .compatible = "fsl,mpc8379-esdhc", .data = &sdhci_esdhc, }, |
| 279 | { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, }, | 285 | { .compatible = "fsl,mpc8536-esdhc", .data = &sdhci_esdhc, }, |
| 286 | { .compatible = "fsl,esdhc", .data = &sdhci_esdhc, }, | ||
| 280 | { .compatible = "generic-sdhci", }, | 287 | { .compatible = "generic-sdhci", }, |
| 281 | {}, | 288 | {}, |
| 282 | }; | 289 | }; |
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index a49a9c8f2cb1..aaac3b6800b7 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
| @@ -47,40 +47,41 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, | |||
| 47 | unsigned long block, nsect; | 47 | unsigned long block, nsect; |
| 48 | char *buf; | 48 | char *buf; |
| 49 | 49 | ||
| 50 | block = req->sector << 9 >> tr->blkshift; | 50 | block = blk_rq_pos(req) << 9 >> tr->blkshift; |
| 51 | nsect = req->current_nr_sectors << 9 >> tr->blkshift; | 51 | nsect = blk_rq_cur_bytes(req) >> tr->blkshift; |
| 52 | 52 | ||
| 53 | buf = req->buffer; | 53 | buf = req->buffer; |
| 54 | 54 | ||
| 55 | if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && | 55 | if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && |
| 56 | req->cmd[0] == REQ_LB_OP_DISCARD) | 56 | req->cmd[0] == REQ_LB_OP_DISCARD) |
| 57 | return !tr->discard(dev, block, nsect); | 57 | return tr->discard(dev, block, nsect); |
| 58 | 58 | ||
| 59 | if (!blk_fs_request(req)) | 59 | if (!blk_fs_request(req)) |
| 60 | return 0; | 60 | return -EIO; |
| 61 | 61 | ||
| 62 | if (req->sector + req->current_nr_sectors > get_capacity(req->rq_disk)) | 62 | if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > |
| 63 | return 0; | 63 | get_capacity(req->rq_disk)) |
| 64 | return -EIO; | ||
| 64 | 65 | ||
| 65 | switch(rq_data_dir(req)) { | 66 | switch(rq_data_dir(req)) { |
| 66 | case READ: | 67 | case READ: |
| 67 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) | 68 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) |
| 68 | if (tr->readsect(dev, block, buf)) | 69 | if (tr->readsect(dev, block, buf)) |
| 69 | return 0; | 70 | return -EIO; |
| 70 | return 1; | 71 | return 0; |
| 71 | 72 | ||
| 72 | case WRITE: | 73 | case WRITE: |
| 73 | if (!tr->writesect) | 74 | if (!tr->writesect) |
| 74 | return 0; | 75 | return -EIO; |
| 75 | 76 | ||
| 76 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) | 77 | for (; nsect > 0; nsect--, block++, buf += tr->blksize) |
| 77 | if (tr->writesect(dev, block, buf)) | 78 | if (tr->writesect(dev, block, buf)) |
| 78 | return 0; | 79 | return -EIO; |
| 79 | return 1; | 80 | return 0; |
| 80 | 81 | ||
| 81 | default: | 82 | default: |
| 82 | printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); | 83 | printk(KERN_NOTICE "Unknown request %u\n", rq_data_dir(req)); |
| 83 | return 0; | 84 | return -EIO; |
| 84 | } | 85 | } |
| 85 | } | 86 | } |
| 86 | 87 | ||
| @@ -88,19 +89,18 @@ static int mtd_blktrans_thread(void *arg) | |||
| 88 | { | 89 | { |
| 89 | struct mtd_blktrans_ops *tr = arg; | 90 | struct mtd_blktrans_ops *tr = arg; |
| 90 | struct request_queue *rq = tr->blkcore_priv->rq; | 91 | struct request_queue *rq = tr->blkcore_priv->rq; |
| 92 | struct request *req = NULL; | ||
| 91 | 93 | ||
| 92 | /* we might get involved when memory gets low, so use PF_MEMALLOC */ | 94 | /* we might get involved when memory gets low, so use PF_MEMALLOC */ |
| 93 | current->flags |= PF_MEMALLOC; | 95 | current->flags |= PF_MEMALLOC; |
| 94 | 96 | ||
| 95 | spin_lock_irq(rq->queue_lock); | 97 | spin_lock_irq(rq->queue_lock); |
| 98 | |||
| 96 | while (!kthread_should_stop()) { | 99 | while (!kthread_should_stop()) { |
| 97 | struct request *req; | ||
| 98 | struct mtd_blktrans_dev *dev; | 100 | struct mtd_blktrans_dev *dev; |
| 99 | int res = 0; | 101 | int res; |
| 100 | |||
| 101 | req = elv_next_request(rq); | ||
| 102 | 102 | ||
| 103 | if (!req) { | 103 | if (!req && !(req = blk_fetch_request(rq))) { |
| 104 | set_current_state(TASK_INTERRUPTIBLE); | 104 | set_current_state(TASK_INTERRUPTIBLE); |
| 105 | spin_unlock_irq(rq->queue_lock); | 105 | spin_unlock_irq(rq->queue_lock); |
| 106 | schedule(); | 106 | schedule(); |
| @@ -119,8 +119,13 @@ static int mtd_blktrans_thread(void *arg) | |||
| 119 | 119 | ||
| 120 | spin_lock_irq(rq->queue_lock); | 120 | spin_lock_irq(rq->queue_lock); |
| 121 | 121 | ||
| 122 | end_request(req, res); | 122 | if (!__blk_end_request_cur(req, res)) |
| 123 | req = NULL; | ||
| 123 | } | 124 | } |
| 125 | |||
| 126 | if (req) | ||
| 127 | __blk_end_request_all(req, -EIO); | ||
| 128 | |||
| 124 | spin_unlock_irq(rq->queue_lock); | 129 | spin_unlock_irq(rq->queue_lock); |
| 125 | 130 | ||
| 126 | return 0; | 131 | return 0; |
| @@ -373,7 +378,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
| 373 | } | 378 | } |
| 374 | 379 | ||
| 375 | tr->blkcore_priv->rq->queuedata = tr; | 380 | tr->blkcore_priv->rq->queuedata = tr; |
| 376 | blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); | 381 | blk_queue_logical_block_size(tr->blkcore_priv->rq, tr->blksize); |
| 377 | if (tr->discard) | 382 | if (tr->discard) |
| 378 | blk_queue_set_discard(tr->blkcore_priv->rq, | 383 | blk_queue_set_discard(tr->blkcore_priv->rq, |
| 379 | blktrans_discard_request); | 384 | blktrans_discard_request); |
diff --git a/drivers/mtd/nand/davinci_nand.c b/drivers/mtd/nand/davinci_nand.c index 0119220de7d0..02700f769b8a 100644 --- a/drivers/mtd/nand/davinci_nand.c +++ b/drivers/mtd/nand/davinci_nand.c | |||
| @@ -407,16 +407,17 @@ static int __init nand_davinci_probe(struct platform_device *pdev) | |||
| 407 | } | 407 | } |
| 408 | info->chip.ecc.mode = ecc_mode; | 408 | info->chip.ecc.mode = ecc_mode; |
| 409 | 409 | ||
| 410 | info->clk = clk_get(&pdev->dev, "AEMIFCLK"); | 410 | info->clk = clk_get(&pdev->dev, "aemif"); |
| 411 | if (IS_ERR(info->clk)) { | 411 | if (IS_ERR(info->clk)) { |
| 412 | ret = PTR_ERR(info->clk); | 412 | ret = PTR_ERR(info->clk); |
| 413 | dev_dbg(&pdev->dev, "unable to get AEMIFCLK, err %d\n", ret); | 413 | dev_dbg(&pdev->dev, "unable to get AEMIF clock, err %d\n", ret); |
| 414 | goto err_clk; | 414 | goto err_clk; |
| 415 | } | 415 | } |
| 416 | 416 | ||
| 417 | ret = clk_enable(info->clk); | 417 | ret = clk_enable(info->clk); |
| 418 | if (ret < 0) { | 418 | if (ret < 0) { |
| 419 | dev_dbg(&pdev->dev, "unable to enable AEMIFCLK, err %d\n", ret); | 419 | dev_dbg(&pdev->dev, "unable to enable AEMIF clock, err %d\n", |
| 420 | ret); | ||
| 420 | goto err_clk_enable; | 421 | goto err_clk_enable; |
| 421 | } | 422 | } |
| 422 | 423 | ||
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c index f3548d048014..40c26080ecda 100644 --- a/drivers/mtd/nand/mxc_nand.c +++ b/drivers/mtd/nand/mxc_nand.c | |||
| @@ -831,6 +831,7 @@ static void mxc_nand_command(struct mtd_info *mtd, unsigned command, | |||
| 831 | break; | 831 | break; |
| 832 | 832 | ||
| 833 | case NAND_CMD_READID: | 833 | case NAND_CMD_READID: |
| 834 | host->col_addr = 0; | ||
| 834 | send_read_id(host); | 835 | send_read_id(host); |
| 835 | break; | 836 | break; |
| 836 | 837 | ||
| @@ -867,6 +868,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
| 867 | mtd->priv = this; | 868 | mtd->priv = this; |
| 868 | mtd->owner = THIS_MODULE; | 869 | mtd->owner = THIS_MODULE; |
| 869 | mtd->dev.parent = &pdev->dev; | 870 | mtd->dev.parent = &pdev->dev; |
| 871 | mtd->name = "mxc_nand"; | ||
| 870 | 872 | ||
| 871 | /* 50 us command delay time */ | 873 | /* 50 us command delay time */ |
| 872 | this->chip_delay = 5; | 874 | this->chip_delay = 5; |
| @@ -882,8 +884,10 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
| 882 | this->verify_buf = mxc_nand_verify_buf; | 884 | this->verify_buf = mxc_nand_verify_buf; |
| 883 | 885 | ||
| 884 | host->clk = clk_get(&pdev->dev, "nfc"); | 886 | host->clk = clk_get(&pdev->dev, "nfc"); |
| 885 | if (IS_ERR(host->clk)) | 887 | if (IS_ERR(host->clk)) { |
| 888 | err = PTR_ERR(host->clk); | ||
| 886 | goto eclk; | 889 | goto eclk; |
| 890 | } | ||
| 887 | 891 | ||
| 888 | clk_enable(host->clk); | 892 | clk_enable(host->clk); |
| 889 | host->clk_act = 1; | 893 | host->clk_act = 1; |
| @@ -896,7 +900,7 @@ static int __init mxcnd_probe(struct platform_device *pdev) | |||
| 896 | 900 | ||
| 897 | host->regs = ioremap(res->start, res->end - res->start + 1); | 901 | host->regs = ioremap(res->start, res->end - res->start + 1); |
| 898 | if (!host->regs) { | 902 | if (!host->regs) { |
| 899 | err = -EIO; | 903 | err = -ENOMEM; |
| 900 | goto eres; | 904 | goto eres; |
| 901 | } | 905 | } |
| 902 | 906 | ||
| @@ -1011,30 +1015,35 @@ static int __devexit mxcnd_remove(struct platform_device *pdev) | |||
| 1011 | #ifdef CONFIG_PM | 1015 | #ifdef CONFIG_PM |
| 1012 | static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) | 1016 | static int mxcnd_suspend(struct platform_device *pdev, pm_message_t state) |
| 1013 | { | 1017 | { |
| 1014 | struct mtd_info *info = platform_get_drvdata(pdev); | 1018 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
| 1019 | struct nand_chip *nand_chip = mtd->priv; | ||
| 1020 | struct mxc_nand_host *host = nand_chip->priv; | ||
| 1015 | int ret = 0; | 1021 | int ret = 0; |
| 1016 | 1022 | ||
| 1017 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n"); | 1023 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND suspend\n"); |
| 1018 | if (info) | 1024 | if (mtd) { |
| 1019 | ret = info->suspend(info); | 1025 | ret = mtd->suspend(mtd); |
| 1020 | 1026 | /* Disable the NFC clock */ | |
| 1021 | /* Disable the NFC clock */ | 1027 | clk_disable(host->clk); |
| 1022 | clk_disable(nfc_clk); /* FIXME */ | 1028 | } |
| 1023 | 1029 | ||
| 1024 | return ret; | 1030 | return ret; |
| 1025 | } | 1031 | } |
| 1026 | 1032 | ||
| 1027 | static int mxcnd_resume(struct platform_device *pdev) | 1033 | static int mxcnd_resume(struct platform_device *pdev) |
| 1028 | { | 1034 | { |
| 1029 | struct mtd_info *info = platform_get_drvdata(pdev); | 1035 | struct mtd_info *mtd = platform_get_drvdata(pdev); |
| 1036 | struct nand_chip *nand_chip = mtd->priv; | ||
| 1037 | struct mxc_nand_host *host = nand_chip->priv; | ||
| 1030 | int ret = 0; | 1038 | int ret = 0; |
| 1031 | 1039 | ||
| 1032 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n"); | 1040 | DEBUG(MTD_DEBUG_LEVEL0, "MXC_ND : NAND resume\n"); |
| 1033 | /* Enable the NFC clock */ | ||
| 1034 | clk_enable(nfc_clk); /* FIXME */ | ||
| 1035 | 1041 | ||
| 1036 | if (info) | 1042 | if (mtd) { |
| 1037 | info->resume(info); | 1043 | /* Enable the NFC clock */ |
| 1044 | clk_enable(host->clk); | ||
| 1045 | mtd->resume(mtd); | ||
| 1046 | } | ||
| 1038 | 1047 | ||
| 1039 | return ret; | 1048 | return ret; |
| 1040 | } | 1049 | } |
| @@ -1055,13 +1064,7 @@ static struct platform_driver mxcnd_driver = { | |||
| 1055 | 1064 | ||
| 1056 | static int __init mxc_nd_init(void) | 1065 | static int __init mxc_nd_init(void) |
| 1057 | { | 1066 | { |
| 1058 | /* Register the device driver structure. */ | 1067 | return platform_driver_probe(&mxcnd_driver, mxcnd_probe); |
| 1059 | pr_info("MXC MTD nand Driver\n"); | ||
| 1060 | if (platform_driver_probe(&mxcnd_driver, mxcnd_probe) != 0) { | ||
| 1061 | printk(KERN_ERR "Driver register failed for mxcnd_driver\n"); | ||
| 1062 | return -ENODEV; | ||
| 1063 | } | ||
| 1064 | return 0; | ||
| 1065 | } | 1068 | } |
| 1066 | 1069 | ||
| 1067 | static void __exit mxc_nd_cleanup(void) | 1070 | static void __exit mxc_nd_cleanup(void) |
diff --git a/drivers/net/3c509.c b/drivers/net/3c509.c index fbb371921991..682aad897081 100644 --- a/drivers/net/3c509.c +++ b/drivers/net/3c509.c | |||
| @@ -480,9 +480,13 @@ static int pnp_registered; | |||
| 480 | 480 | ||
| 481 | #ifdef CONFIG_EISA | 481 | #ifdef CONFIG_EISA |
| 482 | static struct eisa_device_id el3_eisa_ids[] = { | 482 | static struct eisa_device_id el3_eisa_ids[] = { |
| 483 | { "TCM5090" }, | ||
| 484 | { "TCM5091" }, | ||
| 483 | { "TCM5092" }, | 485 | { "TCM5092" }, |
| 484 | { "TCM5093" }, | 486 | { "TCM5093" }, |
| 487 | { "TCM5094" }, | ||
| 485 | { "TCM5095" }, | 488 | { "TCM5095" }, |
| 489 | { "TCM5098" }, | ||
| 486 | { "" } | 490 | { "" } |
| 487 | }; | 491 | }; |
| 488 | MODULE_DEVICE_TABLE(eisa, el3_eisa_ids); | 492 | MODULE_DEVICE_TABLE(eisa, el3_eisa_ids); |
diff --git a/drivers/net/atl1e/atl1e_main.c b/drivers/net/atl1e/atl1e_main.c index fb57b750866b..1342418fb209 100644 --- a/drivers/net/atl1e/atl1e_main.c +++ b/drivers/net/atl1e/atl1e_main.c | |||
| @@ -37,6 +37,7 @@ char atl1e_driver_version[] = DRV_VERSION; | |||
| 37 | */ | 37 | */ |
| 38 | static struct pci_device_id atl1e_pci_tbl[] = { | 38 | static struct pci_device_id atl1e_pci_tbl[] = { |
| 39 | {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)}, | 39 | {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, PCI_DEVICE_ID_ATTANSIC_L1E)}, |
| 40 | {PCI_DEVICE(PCI_VENDOR_ID_ATTANSIC, 0x1066)}, | ||
| 40 | /* required last entry */ | 41 | /* required last entry */ |
| 41 | { 0 } | 42 | { 0 } |
| 42 | }; | 43 | }; |
diff --git a/drivers/net/atlx/atl1.c b/drivers/net/atlx/atl1.c index 0ab22540bf59..4e817126e280 100644 --- a/drivers/net/atlx/atl1.c +++ b/drivers/net/atlx/atl1.c | |||
| @@ -82,6 +82,12 @@ | |||
| 82 | 82 | ||
| 83 | #include "atl1.h" | 83 | #include "atl1.h" |
| 84 | 84 | ||
| 85 | #define ATLX_DRIVER_VERSION "2.1.3" | ||
| 86 | MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, \ | ||
| 87 | Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>"); | ||
| 88 | MODULE_LICENSE("GPL"); | ||
| 89 | MODULE_VERSION(ATLX_DRIVER_VERSION); | ||
| 90 | |||
| 85 | /* Temporary hack for merging atl1 and atl2 */ | 91 | /* Temporary hack for merging atl1 and atl2 */ |
| 86 | #include "atlx.c" | 92 | #include "atlx.c" |
| 87 | 93 | ||
diff --git a/drivers/net/atlx/atlx.h b/drivers/net/atlx/atlx.h index 297a03da6b7f..14054b75aa62 100644 --- a/drivers/net/atlx/atlx.h +++ b/drivers/net/atlx/atlx.h | |||
| @@ -29,12 +29,6 @@ | |||
| 29 | #include <linux/module.h> | 29 | #include <linux/module.h> |
| 30 | #include <linux/types.h> | 30 | #include <linux/types.h> |
| 31 | 31 | ||
| 32 | #define ATLX_DRIVER_VERSION "2.1.3" | ||
| 33 | MODULE_AUTHOR("Xiong Huang <xiong.huang@atheros.com>, \ | ||
| 34 | Chris Snook <csnook@redhat.com>, Jay Cliburn <jcliburn@gmail.com>"); | ||
| 35 | MODULE_LICENSE("GPL"); | ||
| 36 | MODULE_VERSION(ATLX_DRIVER_VERSION); | ||
| 37 | |||
| 38 | #define ATLX_ERR_PHY 2 | 32 | #define ATLX_ERR_PHY 2 |
| 39 | #define ATLX_ERR_PHY_SPEED 7 | 33 | #define ATLX_ERR_PHY_SPEED 7 |
| 40 | #define ATLX_ERR_PHY_RES 8 | 34 | #define ATLX_ERR_PHY_RES 8 |
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index 9f971ed6b58d..b4da18213324 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
| @@ -979,22 +979,7 @@ static int bfin_mac_open(struct net_device *dev) | |||
| 979 | return 0; | 979 | return 0; |
| 980 | } | 980 | } |
| 981 | 981 | ||
| 982 | static const struct net_device_ops bfin_mac_netdev_ops = { | ||
| 983 | .ndo_open = bfin_mac_open, | ||
| 984 | .ndo_stop = bfin_mac_close, | ||
| 985 | .ndo_start_xmit = bfin_mac_hard_start_xmit, | ||
| 986 | .ndo_set_mac_address = bfin_mac_set_mac_address, | ||
| 987 | .ndo_tx_timeout = bfin_mac_timeout, | ||
| 988 | .ndo_set_multicast_list = bfin_mac_set_multicast_list, | ||
| 989 | .ndo_validate_addr = eth_validate_addr, | ||
| 990 | .ndo_change_mtu = eth_change_mtu, | ||
| 991 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 992 | .ndo_poll_controller = bfin_mac_poll, | ||
| 993 | #endif | ||
| 994 | }; | ||
| 995 | |||
| 996 | /* | 982 | /* |
| 997 | * | ||
| 998 | * this makes the board clean up everything that it can | 983 | * this makes the board clean up everything that it can |
| 999 | * and not talk to the outside world. Caused by | 984 | * and not talk to the outside world. Caused by |
| 1000 | * an 'ifconfig ethX down' | 985 | * an 'ifconfig ethX down' |
| @@ -1019,6 +1004,20 @@ static int bfin_mac_close(struct net_device *dev) | |||
| 1019 | return 0; | 1004 | return 0; |
| 1020 | } | 1005 | } |
| 1021 | 1006 | ||
| 1007 | static const struct net_device_ops bfin_mac_netdev_ops = { | ||
| 1008 | .ndo_open = bfin_mac_open, | ||
| 1009 | .ndo_stop = bfin_mac_close, | ||
| 1010 | .ndo_start_xmit = bfin_mac_hard_start_xmit, | ||
| 1011 | .ndo_set_mac_address = bfin_mac_set_mac_address, | ||
| 1012 | .ndo_tx_timeout = bfin_mac_timeout, | ||
| 1013 | .ndo_set_multicast_list = bfin_mac_set_multicast_list, | ||
| 1014 | .ndo_validate_addr = eth_validate_addr, | ||
| 1015 | .ndo_change_mtu = eth_change_mtu, | ||
| 1016 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
| 1017 | .ndo_poll_controller = bfin_mac_poll, | ||
| 1018 | #endif | ||
| 1019 | }; | ||
| 1020 | |||
| 1022 | static int __devinit bfin_mac_probe(struct platform_device *pdev) | 1021 | static int __devinit bfin_mac_probe(struct platform_device *pdev) |
| 1023 | { | 1022 | { |
| 1024 | struct net_device *ndev; | 1023 | struct net_device *ndev; |
diff --git a/drivers/net/cxgb3/adapter.h b/drivers/net/cxgb3/adapter.h index 714df2b675e6..c888e97c9671 100644 --- a/drivers/net/cxgb3/adapter.h +++ b/drivers/net/cxgb3/adapter.h | |||
| @@ -85,8 +85,8 @@ struct fl_pg_chunk { | |||
| 85 | struct page *page; | 85 | struct page *page; |
| 86 | void *va; | 86 | void *va; |
| 87 | unsigned int offset; | 87 | unsigned int offset; |
| 88 | u64 *p_cnt; | 88 | unsigned long *p_cnt; |
| 89 | DECLARE_PCI_UNMAP_ADDR(mapping); | 89 | dma_addr_t mapping; |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | struct rx_desc; | 92 | struct rx_desc; |
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c index 7ea48414c6cb..17858b9a5830 100644 --- a/drivers/net/cxgb3/cxgb3_main.c +++ b/drivers/net/cxgb3/cxgb3_main.c | |||
| @@ -2496,14 +2496,16 @@ static void check_link_status(struct adapter *adapter) | |||
| 2496 | for_each_port(adapter, i) { | 2496 | for_each_port(adapter, i) { |
| 2497 | struct net_device *dev = adapter->port[i]; | 2497 | struct net_device *dev = adapter->port[i]; |
| 2498 | struct port_info *p = netdev_priv(dev); | 2498 | struct port_info *p = netdev_priv(dev); |
| 2499 | int link_fault; | ||
| 2499 | 2500 | ||
| 2500 | spin_lock_irq(&adapter->work_lock); | 2501 | spin_lock_irq(&adapter->work_lock); |
| 2501 | if (p->link_fault) { | 2502 | link_fault = p->link_fault; |
| 2503 | spin_unlock_irq(&adapter->work_lock); | ||
| 2504 | |||
| 2505 | if (link_fault) { | ||
| 2502 | t3_link_fault(adapter, i); | 2506 | t3_link_fault(adapter, i); |
| 2503 | spin_unlock_irq(&adapter->work_lock); | ||
| 2504 | continue; | 2507 | continue; |
| 2505 | } | 2508 | } |
| 2506 | spin_unlock_irq(&adapter->work_lock); | ||
| 2507 | 2509 | ||
| 2508 | if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) { | 2510 | if (!(p->phy.caps & SUPPORTED_IRQ) && netif_running(dev)) { |
| 2509 | t3_xgm_intr_disable(adapter, i); | 2511 | t3_xgm_intr_disable(adapter, i); |
diff --git a/drivers/net/cxgb3/sge.c b/drivers/net/cxgb3/sge.c index 26d3587f3399..b3ee2bc1a005 100644 --- a/drivers/net/cxgb3/sge.c +++ b/drivers/net/cxgb3/sge.c | |||
| @@ -355,7 +355,7 @@ static void clear_rx_desc(struct pci_dev *pdev, const struct sge_fl *q, | |||
| 355 | (*d->pg_chunk.p_cnt)--; | 355 | (*d->pg_chunk.p_cnt)--; |
| 356 | if (!*d->pg_chunk.p_cnt) | 356 | if (!*d->pg_chunk.p_cnt) |
| 357 | pci_unmap_page(pdev, | 357 | pci_unmap_page(pdev, |
| 358 | pci_unmap_addr(&d->pg_chunk, mapping), | 358 | d->pg_chunk.mapping, |
| 359 | q->alloc_size, PCI_DMA_FROMDEVICE); | 359 | q->alloc_size, PCI_DMA_FROMDEVICE); |
| 360 | 360 | ||
| 361 | put_page(d->pg_chunk.page); | 361 | put_page(d->pg_chunk.page); |
| @@ -454,7 +454,7 @@ static int alloc_pg_chunk(struct adapter *adapter, struct sge_fl *q, | |||
| 454 | q->pg_chunk.offset = 0; | 454 | q->pg_chunk.offset = 0; |
| 455 | mapping = pci_map_page(adapter->pdev, q->pg_chunk.page, | 455 | mapping = pci_map_page(adapter->pdev, q->pg_chunk.page, |
| 456 | 0, q->alloc_size, PCI_DMA_FROMDEVICE); | 456 | 0, q->alloc_size, PCI_DMA_FROMDEVICE); |
| 457 | pci_unmap_addr_set(&q->pg_chunk, mapping, mapping); | 457 | q->pg_chunk.mapping = mapping; |
| 458 | } | 458 | } |
| 459 | sd->pg_chunk = q->pg_chunk; | 459 | sd->pg_chunk = q->pg_chunk; |
| 460 | 460 | ||
| @@ -511,8 +511,7 @@ static int refill_fl(struct adapter *adap, struct sge_fl *q, int n, gfp_t gfp) | |||
| 511 | nomem: q->alloc_failed++; | 511 | nomem: q->alloc_failed++; |
| 512 | break; | 512 | break; |
| 513 | } | 513 | } |
| 514 | mapping = pci_unmap_addr(&sd->pg_chunk, mapping) + | 514 | mapping = sd->pg_chunk.mapping + sd->pg_chunk.offset; |
| 515 | sd->pg_chunk.offset; | ||
| 516 | pci_unmap_addr_set(sd, dma_addr, mapping); | 515 | pci_unmap_addr_set(sd, dma_addr, mapping); |
| 517 | 516 | ||
| 518 | add_one_rx_chunk(mapping, d, q->gen); | 517 | add_one_rx_chunk(mapping, d, q->gen); |
| @@ -881,7 +880,7 @@ recycle: | |||
| 881 | (*sd->pg_chunk.p_cnt)--; | 880 | (*sd->pg_chunk.p_cnt)--; |
| 882 | if (!*sd->pg_chunk.p_cnt) | 881 | if (!*sd->pg_chunk.p_cnt) |
| 883 | pci_unmap_page(adap->pdev, | 882 | pci_unmap_page(adap->pdev, |
| 884 | pci_unmap_addr(&sd->pg_chunk, mapping), | 883 | sd->pg_chunk.mapping, |
| 885 | fl->alloc_size, | 884 | fl->alloc_size, |
| 886 | PCI_DMA_FROMDEVICE); | 885 | PCI_DMA_FROMDEVICE); |
| 887 | if (!skb) { | 886 | if (!skb) { |
| @@ -2096,7 +2095,7 @@ static void lro_add_page(struct adapter *adap, struct sge_qset *qs, | |||
| 2096 | (*sd->pg_chunk.p_cnt)--; | 2095 | (*sd->pg_chunk.p_cnt)--; |
| 2097 | if (!*sd->pg_chunk.p_cnt) | 2096 | if (!*sd->pg_chunk.p_cnt) |
| 2098 | pci_unmap_page(adap->pdev, | 2097 | pci_unmap_page(adap->pdev, |
| 2099 | pci_unmap_addr(&sd->pg_chunk, mapping), | 2098 | sd->pg_chunk.mapping, |
| 2100 | fl->alloc_size, | 2099 | fl->alloc_size, |
| 2101 | PCI_DMA_FROMDEVICE); | 2100 | PCI_DMA_FROMDEVICE); |
| 2102 | 2101 | ||
diff --git a/drivers/net/cxgb3/t3_hw.c b/drivers/net/cxgb3/t3_hw.c index 4f68aeb2679a..4950d5d789ae 100644 --- a/drivers/net/cxgb3/t3_hw.c +++ b/drivers/net/cxgb3/t3_hw.c | |||
| @@ -1274,6 +1274,11 @@ void t3_link_fault(struct adapter *adapter, int port_id) | |||
| 1274 | A_XGM_INT_STATUS + mac->offset); | 1274 | A_XGM_INT_STATUS + mac->offset); |
| 1275 | link_fault &= F_LINKFAULTCHANGE; | 1275 | link_fault &= F_LINKFAULTCHANGE; |
| 1276 | 1276 | ||
| 1277 | link_ok = lc->link_ok; | ||
| 1278 | speed = lc->speed; | ||
| 1279 | duplex = lc->duplex; | ||
| 1280 | fc = lc->fc; | ||
| 1281 | |||
| 1277 | phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); | 1282 | phy->ops->get_link_status(phy, &link_ok, &speed, &duplex, &fc); |
| 1278 | 1283 | ||
| 1279 | if (link_fault) { | 1284 | if (link_fault) { |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index b1419e21b46b..fffb006b7d95 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
| @@ -4027,8 +4027,9 @@ static bool e1000_clean_rx_irq(struct e1000_adapter *adapter, | |||
| 4027 | PCI_DMA_FROMDEVICE); | 4027 | PCI_DMA_FROMDEVICE); |
| 4028 | 4028 | ||
| 4029 | length = le16_to_cpu(rx_desc->length); | 4029 | length = le16_to_cpu(rx_desc->length); |
| 4030 | 4030 | /* !EOP means multiple descriptors were used to store a single | |
| 4031 | if (unlikely(!(status & E1000_RXD_STAT_EOP))) { | 4031 | * packet, also make sure the frame isn't just CRC only */ |
| 4032 | if (unlikely(!(status & E1000_RXD_STAT_EOP) || (length <= 4))) { | ||
| 4032 | /* All receives must fit into a single buffer */ | 4033 | /* All receives must fit into a single buffer */ |
| 4033 | E1000_DBG("%s: Receive packet consumed multiple" | 4034 | E1000_DBG("%s: Receive packet consumed multiple" |
| 4034 | " buffers\n", netdev->name); | 4035 | " buffers\n", netdev->name); |
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index f9a846b1b92f..9f6a68fb7b45 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -897,6 +897,12 @@ enum { | |||
| 897 | }; | 897 | }; |
| 898 | static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED; | 898 | static int phy_cross = NV_CROSSOVER_DETECTION_DISABLED; |
| 899 | 899 | ||
| 900 | /* | ||
| 901 | * Power down phy when interface is down (persists through reboot; | ||
| 902 | * older Linux and other OSes may not power it up again) | ||
| 903 | */ | ||
| 904 | static int phy_power_down = 0; | ||
| 905 | |||
| 900 | static inline struct fe_priv *get_nvpriv(struct net_device *dev) | 906 | static inline struct fe_priv *get_nvpriv(struct net_device *dev) |
| 901 | { | 907 | { |
| 902 | return netdev_priv(dev); | 908 | return netdev_priv(dev); |
| @@ -1485,7 +1491,10 @@ static int phy_init(struct net_device *dev) | |||
| 1485 | 1491 | ||
| 1486 | /* restart auto negotiation, power down phy */ | 1492 | /* restart auto negotiation, power down phy */ |
| 1487 | mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); | 1493 | mii_control = mii_rw(dev, np->phyaddr, MII_BMCR, MII_READ); |
| 1488 | mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE | BMCR_PDOWN); | 1494 | mii_control |= (BMCR_ANRESTART | BMCR_ANENABLE); |
| 1495 | if (phy_power_down) { | ||
| 1496 | mii_control |= BMCR_PDOWN; | ||
| 1497 | } | ||
| 1489 | if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) { | 1498 | if (mii_rw(dev, np->phyaddr, MII_BMCR, mii_control)) { |
| 1490 | return PHY_ERROR; | 1499 | return PHY_ERROR; |
| 1491 | } | 1500 | } |
| @@ -5513,7 +5522,7 @@ static int nv_close(struct net_device *dev) | |||
| 5513 | 5522 | ||
| 5514 | nv_drain_rxtx(dev); | 5523 | nv_drain_rxtx(dev); |
| 5515 | 5524 | ||
| 5516 | if (np->wolenabled) { | 5525 | if (np->wolenabled || !phy_power_down) { |
| 5517 | writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); | 5526 | writel(NVREG_PFF_ALWAYS|NVREG_PFF_MYADDR, base + NvRegPacketFilterFlags); |
| 5518 | nv_start_rx(dev); | 5527 | nv_start_rx(dev); |
| 5519 | } else { | 5528 | } else { |
| @@ -6367,6 +6376,8 @@ module_param(dma_64bit, int, 0); | |||
| 6367 | MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0."); | 6376 | MODULE_PARM_DESC(dma_64bit, "High DMA is enabled by setting to 1 and disabled by setting to 0."); |
| 6368 | module_param(phy_cross, int, 0); | 6377 | module_param(phy_cross, int, 0); |
| 6369 | MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0."); | 6378 | MODULE_PARM_DESC(phy_cross, "Phy crossover detection for Realtek 8201 phy is enabled by setting to 1 and disabled by setting to 0."); |
| 6379 | module_param(phy_power_down, int, 0); | ||
| 6380 | MODULE_PARM_DESC(phy_power_down, "Power down phy and disable link when interface is down (1), or leave phy powered up (0)."); | ||
| 6370 | 6381 | ||
| 6371 | MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>"); | 6382 | MODULE_AUTHOR("Manfred Spraul <manfred@colorfullife.com>"); |
| 6372 | MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); | 6383 | MODULE_DESCRIPTION("Reverse Engineered nForce ethernet driver"); |
diff --git a/drivers/net/gianfar.h b/drivers/net/gianfar.h index 0642d52aef5c..cf352961ae9b 100644 --- a/drivers/net/gianfar.h +++ b/drivers/net/gianfar.h | |||
| @@ -259,7 +259,7 @@ extern const char gfar_driver_version[]; | |||
| 259 | (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ | 259 | (IEVENT_RXC | IEVENT_BSY | IEVENT_EBERR | IEVENT_MSRO | \ |
| 260 | IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ | 260 | IEVENT_BABT | IEVENT_TXC | IEVENT_TXE | IEVENT_LC \ |
| 261 | | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \ | 261 | | IEVENT_CRL | IEVENT_XFUN | IEVENT_DPE | IEVENT_PERR \ |
| 262 | | IEVENT_MAG) | 262 | | IEVENT_MAG | IEVENT_BABR) |
| 263 | 263 | ||
| 264 | #define IMASK_INIT_CLEAR 0x00000000 | 264 | #define IMASK_INIT_CLEAR 0x00000000 |
| 265 | #define IMASK_BABR 0x80000000 | 265 | #define IMASK_BABR 0x80000000 |
diff --git a/drivers/net/mac8390.c b/drivers/net/mac8390.c index f26667d5eaae..22e74a0e0361 100644 --- a/drivers/net/mac8390.c +++ b/drivers/net/mac8390.c | |||
| @@ -489,7 +489,7 @@ static const struct net_device_ops mac8390_netdev_ops = { | |||
| 489 | .ndo_set_mac_address = eth_mac_addr, | 489 | .ndo_set_mac_address = eth_mac_addr, |
| 490 | .ndo_change_mtu = eth_change_mtu, | 490 | .ndo_change_mtu = eth_change_mtu, |
| 491 | #ifdef CONFIG_NET_POLL_CONTROLLER | 491 | #ifdef CONFIG_NET_POLL_CONTROLLER |
| 492 | .ndo_poll_controller = ei_poll, | 492 | .ndo_poll_controller = __ei_poll, |
| 493 | #endif | 493 | #endif |
| 494 | }; | 494 | }; |
| 495 | 495 | ||
diff --git a/drivers/net/mlx4/en_tx.c b/drivers/net/mlx4/en_tx.c index ac6fc499b280..e5c98a98ad37 100644 --- a/drivers/net/mlx4/en_tx.c +++ b/drivers/net/mlx4/en_tx.c | |||
| @@ -426,7 +426,7 @@ void mlx4_en_poll_tx_cq(unsigned long data) | |||
| 426 | 426 | ||
| 427 | INC_PERF_COUNTER(priv->pstats.tx_poll); | 427 | INC_PERF_COUNTER(priv->pstats.tx_poll); |
| 428 | 428 | ||
| 429 | if (!spin_trylock(&ring->comp_lock)) { | 429 | if (!spin_trylock_irq(&ring->comp_lock)) { |
| 430 | mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); | 430 | mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); |
| 431 | return; | 431 | return; |
| 432 | } | 432 | } |
| @@ -439,7 +439,7 @@ void mlx4_en_poll_tx_cq(unsigned long data) | |||
| 439 | if (inflight && priv->port_up) | 439 | if (inflight && priv->port_up) |
| 440 | mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); | 440 | mod_timer(&cq->timer, jiffies + MLX4_EN_TX_POLL_TIMEOUT); |
| 441 | 441 | ||
| 442 | spin_unlock(&ring->comp_lock); | 442 | spin_unlock_irq(&ring->comp_lock); |
| 443 | } | 443 | } |
| 444 | 444 | ||
| 445 | static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv, | 445 | static struct mlx4_en_tx_desc *mlx4_en_bounce_to_desc(struct mlx4_en_priv *priv, |
| @@ -482,9 +482,9 @@ static inline void mlx4_en_xmit_poll(struct mlx4_en_priv *priv, int tx_ind) | |||
| 482 | 482 | ||
| 483 | /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */ | 483 | /* Poll the CQ every mlx4_en_TX_MODER_POLL packets */ |
| 484 | if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0) | 484 | if ((++ring->poll_cnt & (MLX4_EN_TX_POLL_MODER - 1)) == 0) |
| 485 | if (spin_trylock(&ring->comp_lock)) { | 485 | if (spin_trylock_irq(&ring->comp_lock)) { |
| 486 | mlx4_en_process_tx_cq(priv->dev, cq); | 486 | mlx4_en_process_tx_cq(priv->dev, cq); |
| 487 | spin_unlock(&ring->comp_lock); | 487 | spin_unlock_irq(&ring->comp_lock); |
| 488 | } | 488 | } |
| 489 | } | 489 | } |
| 490 | 490 | ||
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c index 8247a945a1d9..3b19e0ce290f 100644 --- a/drivers/net/r8169.c +++ b/drivers/net/r8169.c | |||
| @@ -66,7 +66,6 @@ static const int multicast_filter_limit = 32; | |||
| 66 | #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ | 66 | #define RX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ |
| 67 | #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ | 67 | #define TX_DMA_BURST 6 /* Maximum PCI burst, '6' is 1024 */ |
| 68 | #define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ | 68 | #define EarlyTxThld 0x3F /* 0x3F means NO early transmit */ |
| 69 | #define RxPacketMaxSize 0x3FE8 /* 16K - 1 - ETH_HLEN - VLAN - CRC... */ | ||
| 70 | #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ | 69 | #define SafeMtu 0x1c20 /* ... actually life sucks beyond ~7k */ |
| 71 | #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ | 70 | #define InterFrameGap 0x03 /* 3 means InterFrameGap = the shortest one */ |
| 72 | 71 | ||
| @@ -2357,10 +2356,10 @@ static u16 rtl_rw_cpluscmd(void __iomem *ioaddr) | |||
| 2357 | return cmd; | 2356 | return cmd; |
| 2358 | } | 2357 | } |
| 2359 | 2358 | ||
| 2360 | static void rtl_set_rx_max_size(void __iomem *ioaddr) | 2359 | static void rtl_set_rx_max_size(void __iomem *ioaddr, unsigned int rx_buf_sz) |
| 2361 | { | 2360 | { |
| 2362 | /* Low hurts. Let's disable the filtering. */ | 2361 | /* Low hurts. Let's disable the filtering. */ |
| 2363 | RTL_W16(RxMaxSize, 16383); | 2362 | RTL_W16(RxMaxSize, rx_buf_sz); |
| 2364 | } | 2363 | } |
| 2365 | 2364 | ||
| 2366 | static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) | 2365 | static void rtl8169_set_magic_reg(void __iomem *ioaddr, unsigned mac_version) |
| @@ -2407,7 +2406,7 @@ static void rtl_hw_start_8169(struct net_device *dev) | |||
| 2407 | 2406 | ||
| 2408 | RTL_W8(EarlyTxThres, EarlyTxThld); | 2407 | RTL_W8(EarlyTxThres, EarlyTxThld); |
| 2409 | 2408 | ||
| 2410 | rtl_set_rx_max_size(ioaddr); | 2409 | rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); |
| 2411 | 2410 | ||
| 2412 | if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || | 2411 | if ((tp->mac_version == RTL_GIGA_MAC_VER_01) || |
| 2413 | (tp->mac_version == RTL_GIGA_MAC_VER_02) || | 2412 | (tp->mac_version == RTL_GIGA_MAC_VER_02) || |
| @@ -2668,7 +2667,7 @@ static void rtl_hw_start_8168(struct net_device *dev) | |||
| 2668 | 2667 | ||
| 2669 | RTL_W8(EarlyTxThres, EarlyTxThld); | 2668 | RTL_W8(EarlyTxThres, EarlyTxThld); |
| 2670 | 2669 | ||
| 2671 | rtl_set_rx_max_size(ioaddr); | 2670 | rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); |
| 2672 | 2671 | ||
| 2673 | tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; | 2672 | tp->cp_cmd |= RTL_R16(CPlusCmd) | PktCntrDisable | INTT_1; |
| 2674 | 2673 | ||
| @@ -2846,7 +2845,7 @@ static void rtl_hw_start_8101(struct net_device *dev) | |||
| 2846 | 2845 | ||
| 2847 | RTL_W8(EarlyTxThres, EarlyTxThld); | 2846 | RTL_W8(EarlyTxThres, EarlyTxThld); |
| 2848 | 2847 | ||
| 2849 | rtl_set_rx_max_size(ioaddr); | 2848 | rtl_set_rx_max_size(ioaddr, tp->rx_buf_sz); |
| 2850 | 2849 | ||
| 2851 | tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; | 2850 | tp->cp_cmd |= rtl_rw_cpluscmd(ioaddr) | PCIMulRW; |
| 2852 | 2851 | ||
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig index 8a0823588c51..3d94e7dfea69 100644 --- a/drivers/net/wireless/Kconfig +++ b/drivers/net/wireless/Kconfig | |||
| @@ -430,6 +430,7 @@ config RTL8187 | |||
| 430 | ASUS P5B Deluxe | 430 | ASUS P5B Deluxe |
| 431 | Toshiba Satellite Pro series of laptops | 431 | Toshiba Satellite Pro series of laptops |
| 432 | Asus Wireless Link | 432 | Asus Wireless Link |
| 433 | Linksys WUSB54GC-EU | ||
| 433 | 434 | ||
| 434 | Thanks to Realtek for their support! | 435 | Thanks to Realtek for their support! |
| 435 | 436 | ||
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c index 744f4f4dd3d1..8d93ca4651b9 100644 --- a/drivers/net/wireless/at76c50x-usb.c +++ b/drivers/net/wireless/at76c50x-usb.c | |||
| @@ -1873,18 +1873,18 @@ static void at76_dwork_hw_scan(struct work_struct *work) | |||
| 1873 | if (ret != CMD_STATUS_COMPLETE) { | 1873 | if (ret != CMD_STATUS_COMPLETE) { |
| 1874 | queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan, | 1874 | queue_delayed_work(priv->hw->workqueue, &priv->dwork_hw_scan, |
| 1875 | SCAN_POLL_INTERVAL); | 1875 | SCAN_POLL_INTERVAL); |
| 1876 | goto exit; | 1876 | mutex_unlock(&priv->mtx); |
| 1877 | return; | ||
| 1877 | } | 1878 | } |
| 1878 | 1879 | ||
| 1879 | ieee80211_scan_completed(priv->hw, false); | ||
| 1880 | |||
| 1881 | if (is_valid_ether_addr(priv->bssid)) | 1880 | if (is_valid_ether_addr(priv->bssid)) |
| 1882 | at76_join(priv); | 1881 | at76_join(priv); |
| 1883 | 1882 | ||
| 1884 | ieee80211_wake_queues(priv->hw); | ||
| 1885 | |||
| 1886 | exit: | ||
| 1887 | mutex_unlock(&priv->mtx); | 1883 | mutex_unlock(&priv->mtx); |
| 1884 | |||
| 1885 | ieee80211_scan_completed(priv->hw, false); | ||
| 1886 | |||
| 1887 | ieee80211_wake_queues(priv->hw); | ||
| 1888 | } | 1888 | } |
| 1889 | 1889 | ||
| 1890 | static int at76_hw_scan(struct ieee80211_hw *hw, | 1890 | static int at76_hw_scan(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index bac6cfba6abd..d51ba0a88c23 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
| @@ -71,6 +71,8 @@ static struct usb_device_id rtl8187_table[] __devinitdata = { | |||
| 71 | {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, | 71 | {USB_DEVICE(0x18E8, 0x6232), .driver_info = DEVICE_RTL8187}, |
| 72 | /* AirLive */ | 72 | /* AirLive */ |
| 73 | {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, | 73 | {USB_DEVICE(0x1b75, 0x8187), .driver_info = DEVICE_RTL8187}, |
| 74 | /* Linksys */ | ||
| 75 | {USB_DEVICE(0x1737, 0x0073), .driver_info = DEVICE_RTL8187B}, | ||
| 74 | {} | 76 | {} |
| 75 | }; | 77 | }; |
| 76 | 78 | ||
diff --git a/drivers/parisc/iosapic.c b/drivers/parisc/iosapic.c index 73348c4047e9..4a9cc92d4d18 100644 --- a/drivers/parisc/iosapic.c +++ b/drivers/parisc/iosapic.c | |||
| @@ -702,7 +702,7 @@ static unsigned int iosapic_startup_irq(unsigned int irq) | |||
| 702 | } | 702 | } |
| 703 | 703 | ||
| 704 | #ifdef CONFIG_SMP | 704 | #ifdef CONFIG_SMP |
| 705 | static void iosapic_set_affinity_irq(unsigned int irq, | 705 | static int iosapic_set_affinity_irq(unsigned int irq, |
| 706 | const struct cpumask *dest) | 706 | const struct cpumask *dest) |
| 707 | { | 707 | { |
| 708 | struct vector_info *vi = iosapic_get_vector(irq); | 708 | struct vector_info *vi = iosapic_get_vector(irq); |
| @@ -712,7 +712,7 @@ static void iosapic_set_affinity_irq(unsigned int irq, | |||
| 712 | 712 | ||
| 713 | dest_cpu = cpu_check_affinity(irq, dest); | 713 | dest_cpu = cpu_check_affinity(irq, dest); |
| 714 | if (dest_cpu < 0) | 714 | if (dest_cpu < 0) |
| 715 | return; | 715 | return -1; |
| 716 | 716 | ||
| 717 | cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu)); | 717 | cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu)); |
| 718 | vi->txn_addr = txn_affinity_addr(irq, dest_cpu); | 718 | vi->txn_addr = txn_affinity_addr(irq, dest_cpu); |
| @@ -724,6 +724,8 @@ static void iosapic_set_affinity_irq(unsigned int irq, | |||
| 724 | iosapic_set_irt_data(vi, &dummy_d0, &d1); | 724 | iosapic_set_irt_data(vi, &dummy_d0, &d1); |
| 725 | iosapic_wr_irt_entry(vi, d0, d1); | 725 | iosapic_wr_irt_entry(vi, d0, d1); |
| 726 | spin_unlock_irqrestore(&iosapic_lock, flags); | 726 | spin_unlock_irqrestore(&iosapic_lock, flags); |
| 727 | |||
| 728 | return 0; | ||
| 727 | } | 729 | } |
| 728 | #endif | 730 | #endif |
| 729 | 731 | ||
diff --git a/drivers/parport/parport_gsc.c b/drivers/parport/parport_gsc.c index e6a7e847ee80..ea31a452b153 100644 --- a/drivers/parport/parport_gsc.c +++ b/drivers/parport/parport_gsc.c | |||
| @@ -352,8 +352,8 @@ static int __devinit parport_init_chip(struct parisc_device *dev) | |||
| 352 | unsigned long port; | 352 | unsigned long port; |
| 353 | 353 | ||
| 354 | if (!dev->irq) { | 354 | if (!dev->irq) { |
| 355 | printk(KERN_WARNING "IRQ not found for parallel device at 0x%lx\n", | 355 | printk(KERN_WARNING "IRQ not found for parallel device at 0x%llx\n", |
| 356 | dev->hpa.start); | 356 | (unsigned long long)dev->hpa.start); |
| 357 | return -ENODEV; | 357 | return -ENODEV; |
| 358 | } | 358 | } |
| 359 | 359 | ||
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 4e63cc9e2778..151bf5bc8afe 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* Low-level parallel-port routines for 8255-based PC-style hardware. | 1 | /* Low-level parallel-port routines for 8255-based PC-style hardware. |
| 2 | * | 2 | * |
| 3 | * Authors: Phil Blundell <philb@gnu.org> | 3 | * Authors: Phil Blundell <philb@gnu.org> |
| 4 | * Tim Waugh <tim@cyberelk.demon.co.uk> | 4 | * Tim Waugh <tim@cyberelk.demon.co.uk> |
| 5 | * Jose Renau <renau@acm.org> | 5 | * Jose Renau <renau@acm.org> |
| @@ -11,7 +11,7 @@ | |||
| 11 | * Cleaned up include files - Russell King <linux@arm.uk.linux.org> | 11 | * Cleaned up include files - Russell King <linux@arm.uk.linux.org> |
| 12 | * DMA support - Bert De Jonghe <bert@sophis.be> | 12 | * DMA support - Bert De Jonghe <bert@sophis.be> |
| 13 | * Many ECP bugs fixed. Fred Barnes & Jamie Lokier, 1999 | 13 | * Many ECP bugs fixed. Fred Barnes & Jamie Lokier, 1999 |
| 14 | * More PCI support now conditional on CONFIG_PCI, 03/2001, Paul G. | 14 | * More PCI support now conditional on CONFIG_PCI, 03/2001, Paul G. |
| 15 | * Various hacks, Fred Barnes, 04/2001 | 15 | * Various hacks, Fred Barnes, 04/2001 |
| 16 | * Updated probing logic - Adam Belay <ambx1@neo.rr.com> | 16 | * Updated probing logic - Adam Belay <ambx1@neo.rr.com> |
| 17 | */ | 17 | */ |
| @@ -56,10 +56,10 @@ | |||
| 56 | #include <linux/pnp.h> | 56 | #include <linux/pnp.h> |
| 57 | #include <linux/platform_device.h> | 57 | #include <linux/platform_device.h> |
| 58 | #include <linux/sysctl.h> | 58 | #include <linux/sysctl.h> |
| 59 | #include <linux/io.h> | ||
| 60 | #include <linux/uaccess.h> | ||
| 59 | 61 | ||
| 60 | #include <asm/io.h> | ||
| 61 | #include <asm/dma.h> | 62 | #include <asm/dma.h> |
| 62 | #include <asm/uaccess.h> | ||
| 63 | 63 | ||
| 64 | #include <linux/parport.h> | 64 | #include <linux/parport.h> |
| 65 | #include <linux/parport_pc.h> | 65 | #include <linux/parport_pc.h> |
| @@ -82,7 +82,7 @@ | |||
| 82 | #define ECR_TST 06 | 82 | #define ECR_TST 06 |
| 83 | #define ECR_CNF 07 | 83 | #define ECR_CNF 07 |
| 84 | #define ECR_MODE_MASK 0xe0 | 84 | #define ECR_MODE_MASK 0xe0 |
| 85 | #define ECR_WRITE(p,v) frob_econtrol((p),0xff,(v)) | 85 | #define ECR_WRITE(p, v) frob_econtrol((p), 0xff, (v)) |
| 86 | 86 | ||
| 87 | #undef DEBUG | 87 | #undef DEBUG |
| 88 | 88 | ||
| @@ -109,27 +109,27 @@ static int pci_registered_parport; | |||
| 109 | static int pnp_registered_parport; | 109 | static int pnp_registered_parport; |
| 110 | 110 | ||
| 111 | /* frob_control, but for ECR */ | 111 | /* frob_control, but for ECR */ |
| 112 | static void frob_econtrol (struct parport *pb, unsigned char m, | 112 | static void frob_econtrol(struct parport *pb, unsigned char m, |
| 113 | unsigned char v) | 113 | unsigned char v) |
| 114 | { | 114 | { |
| 115 | unsigned char ectr = 0; | 115 | unsigned char ectr = 0; |
| 116 | 116 | ||
| 117 | if (m != 0xff) | 117 | if (m != 0xff) |
| 118 | ectr = inb (ECONTROL (pb)); | 118 | ectr = inb(ECONTROL(pb)); |
| 119 | 119 | ||
| 120 | DPRINTK (KERN_DEBUG "frob_econtrol(%02x,%02x): %02x -> %02x\n", | 120 | DPRINTK(KERN_DEBUG "frob_econtrol(%02x,%02x): %02x -> %02x\n", |
| 121 | m, v, ectr, (ectr & ~m) ^ v); | 121 | m, v, ectr, (ectr & ~m) ^ v); |
| 122 | 122 | ||
| 123 | outb ((ectr & ~m) ^ v, ECONTROL (pb)); | 123 | outb((ectr & ~m) ^ v, ECONTROL(pb)); |
| 124 | } | 124 | } |
| 125 | 125 | ||
| 126 | static __inline__ void frob_set_mode (struct parport *p, int mode) | 126 | static inline void frob_set_mode(struct parport *p, int mode) |
| 127 | { | 127 | { |
| 128 | frob_econtrol (p, ECR_MODE_MASK, mode << 5); | 128 | frob_econtrol(p, ECR_MODE_MASK, mode << 5); |
| 129 | } | 129 | } |
| 130 | 130 | ||
| 131 | #ifdef CONFIG_PARPORT_PC_FIFO | 131 | #ifdef CONFIG_PARPORT_PC_FIFO |
| 132 | /* Safely change the mode bits in the ECR | 132 | /* Safely change the mode bits in the ECR |
| 133 | Returns: | 133 | Returns: |
| 134 | 0 : Success | 134 | 0 : Success |
| 135 | -EBUSY: Could not drain FIFO in some finite amount of time, | 135 | -EBUSY: Could not drain FIFO in some finite amount of time, |
| @@ -141,17 +141,18 @@ static int change_mode(struct parport *p, int m) | |||
| 141 | unsigned char oecr; | 141 | unsigned char oecr; |
| 142 | int mode; | 142 | int mode; |
| 143 | 143 | ||
| 144 | DPRINTK(KERN_INFO "parport change_mode ECP-ISA to mode 0x%02x\n",m); | 144 | DPRINTK(KERN_INFO "parport change_mode ECP-ISA to mode 0x%02x\n", m); |
| 145 | 145 | ||
| 146 | if (!priv->ecr) { | 146 | if (!priv->ecr) { |
| 147 | printk (KERN_DEBUG "change_mode: but there's no ECR!\n"); | 147 | printk(KERN_DEBUG "change_mode: but there's no ECR!\n"); |
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | /* Bits <7:5> contain the mode. */ | 151 | /* Bits <7:5> contain the mode. */ |
| 152 | oecr = inb (ECONTROL (p)); | 152 | oecr = inb(ECONTROL(p)); |
| 153 | mode = (oecr >> 5) & 0x7; | 153 | mode = (oecr >> 5) & 0x7; |
| 154 | if (mode == m) return 0; | 154 | if (mode == m) |
| 155 | return 0; | ||
| 155 | 156 | ||
| 156 | if (mode >= 2 && !(priv->ctr & 0x20)) { | 157 | if (mode >= 2 && !(priv->ctr & 0x20)) { |
| 157 | /* This mode resets the FIFO, so we may | 158 | /* This mode resets the FIFO, so we may |
| @@ -163,19 +164,21 @@ static int change_mode(struct parport *p, int m) | |||
| 163 | case ECR_ECP: /* ECP Parallel Port mode */ | 164 | case ECR_ECP: /* ECP Parallel Port mode */ |
| 164 | /* Busy wait for 200us */ | 165 | /* Busy wait for 200us */ |
| 165 | for (counter = 0; counter < 40; counter++) { | 166 | for (counter = 0; counter < 40; counter++) { |
| 166 | if (inb (ECONTROL (p)) & 0x01) | 167 | if (inb(ECONTROL(p)) & 0x01) |
| 168 | break; | ||
| 169 | if (signal_pending(current)) | ||
| 167 | break; | 170 | break; |
| 168 | if (signal_pending (current)) break; | 171 | udelay(5); |
| 169 | udelay (5); | ||
| 170 | } | 172 | } |
| 171 | 173 | ||
| 172 | /* Poll slowly. */ | 174 | /* Poll slowly. */ |
| 173 | while (!(inb (ECONTROL (p)) & 0x01)) { | 175 | while (!(inb(ECONTROL(p)) & 0x01)) { |
| 174 | if (time_after_eq (jiffies, expire)) | 176 | if (time_after_eq(jiffies, expire)) |
| 175 | /* The FIFO is stuck. */ | 177 | /* The FIFO is stuck. */ |
| 176 | return -EBUSY; | 178 | return -EBUSY; |
| 177 | schedule_timeout_interruptible(msecs_to_jiffies(10)); | 179 | schedule_timeout_interruptible( |
| 178 | if (signal_pending (current)) | 180 | msecs_to_jiffies(10)); |
| 181 | if (signal_pending(current)) | ||
| 179 | break; | 182 | break; |
| 180 | } | 183 | } |
| 181 | } | 184 | } |
| @@ -185,20 +188,20 @@ static int change_mode(struct parport *p, int m) | |||
| 185 | /* We have to go through mode 001 */ | 188 | /* We have to go through mode 001 */ |
| 186 | oecr &= ~(7 << 5); | 189 | oecr &= ~(7 << 5); |
| 187 | oecr |= ECR_PS2 << 5; | 190 | oecr |= ECR_PS2 << 5; |
| 188 | ECR_WRITE (p, oecr); | 191 | ECR_WRITE(p, oecr); |
| 189 | } | 192 | } |
| 190 | 193 | ||
| 191 | /* Set the mode. */ | 194 | /* Set the mode. */ |
| 192 | oecr &= ~(7 << 5); | 195 | oecr &= ~(7 << 5); |
| 193 | oecr |= m << 5; | 196 | oecr |= m << 5; |
| 194 | ECR_WRITE (p, oecr); | 197 | ECR_WRITE(p, oecr); |
| 195 | return 0; | 198 | return 0; |
| 196 | } | 199 | } |
| 197 | 200 | ||
| 198 | #ifdef CONFIG_PARPORT_1284 | 201 | #ifdef CONFIG_PARPORT_1284 |
| 199 | /* Find FIFO lossage; FIFO is reset */ | 202 | /* Find FIFO lossage; FIFO is reset */ |
| 200 | #if 0 | 203 | #if 0 |
| 201 | static int get_fifo_residue (struct parport *p) | 204 | static int get_fifo_residue(struct parport *p) |
| 202 | { | 205 | { |
| 203 | int residue; | 206 | int residue; |
| 204 | int cnfga; | 207 | int cnfga; |
| @@ -206,26 +209,26 @@ static int get_fifo_residue (struct parport *p) | |||
| 206 | 209 | ||
| 207 | /* Adjust for the contents of the FIFO. */ | 210 | /* Adjust for the contents of the FIFO. */ |
| 208 | for (residue = priv->fifo_depth; ; residue--) { | 211 | for (residue = priv->fifo_depth; ; residue--) { |
| 209 | if (inb (ECONTROL (p)) & 0x2) | 212 | if (inb(ECONTROL(p)) & 0x2) |
| 210 | /* Full up. */ | 213 | /* Full up. */ |
| 211 | break; | 214 | break; |
| 212 | 215 | ||
| 213 | outb (0, FIFO (p)); | 216 | outb(0, FIFO(p)); |
| 214 | } | 217 | } |
| 215 | 218 | ||
| 216 | printk (KERN_DEBUG "%s: %d PWords were left in FIFO\n", p->name, | 219 | printk(KERN_DEBUG "%s: %d PWords were left in FIFO\n", p->name, |
| 217 | residue); | 220 | residue); |
| 218 | 221 | ||
| 219 | /* Reset the FIFO. */ | 222 | /* Reset the FIFO. */ |
| 220 | frob_set_mode (p, ECR_PS2); | 223 | frob_set_mode(p, ECR_PS2); |
| 221 | 224 | ||
| 222 | /* Now change to config mode and clean up. FIXME */ | 225 | /* Now change to config mode and clean up. FIXME */ |
| 223 | frob_set_mode (p, ECR_CNF); | 226 | frob_set_mode(p, ECR_CNF); |
| 224 | cnfga = inb (CONFIGA (p)); | 227 | cnfga = inb(CONFIGA(p)); |
| 225 | printk (KERN_DEBUG "%s: cnfgA contains 0x%02x\n", p->name, cnfga); | 228 | printk(KERN_DEBUG "%s: cnfgA contains 0x%02x\n", p->name, cnfga); |
| 226 | 229 | ||
| 227 | if (!(cnfga & (1<<2))) { | 230 | if (!(cnfga & (1<<2))) { |
| 228 | printk (KERN_DEBUG "%s: Accounting for extra byte\n", p->name); | 231 | printk(KERN_DEBUG "%s: Accounting for extra byte\n", p->name); |
| 229 | residue++; | 232 | residue++; |
| 230 | } | 233 | } |
| 231 | 234 | ||
| @@ -233,9 +236,11 @@ static int get_fifo_residue (struct parport *p) | |||
| 233 | * PWord != 1 byte. */ | 236 | * PWord != 1 byte. */ |
| 234 | 237 | ||
| 235 | /* Back to PS2 mode. */ | 238 | /* Back to PS2 mode. */ |
| 236 | frob_set_mode (p, ECR_PS2); | 239 | frob_set_mode(p, ECR_PS2); |
| 237 | 240 | ||
| 238 | DPRINTK (KERN_DEBUG "*** get_fifo_residue: done residue collecting (ecr = 0x%2.2x)\n", inb (ECONTROL (p))); | 241 | DPRINTK(KERN_DEBUG |
| 242 | "*** get_fifo_residue: done residue collecting (ecr = 0x%2.2x)\n", | ||
| 243 | inb(ECONTROL(p))); | ||
| 239 | return residue; | 244 | return residue; |
| 240 | } | 245 | } |
| 241 | #endif /* 0 */ | 246 | #endif /* 0 */ |
| @@ -257,8 +262,8 @@ static int clear_epp_timeout(struct parport *pb) | |||
| 257 | /* To clear timeout some chips require double read */ | 262 | /* To clear timeout some chips require double read */ |
| 258 | parport_pc_read_status(pb); | 263 | parport_pc_read_status(pb); |
| 259 | r = parport_pc_read_status(pb); | 264 | r = parport_pc_read_status(pb); |
| 260 | outb (r | 0x01, STATUS (pb)); /* Some reset by writing 1 */ | 265 | outb(r | 0x01, STATUS(pb)); /* Some reset by writing 1 */ |
| 261 | outb (r & 0xfe, STATUS (pb)); /* Others by writing 0 */ | 266 | outb(r & 0xfe, STATUS(pb)); /* Others by writing 0 */ |
| 262 | r = parport_pc_read_status(pb); | 267 | r = parport_pc_read_status(pb); |
| 263 | 268 | ||
| 264 | return !(r & 0x01); | 269 | return !(r & 0x01); |
| @@ -272,7 +277,8 @@ static int clear_epp_timeout(struct parport *pb) | |||
| 272 | * of these are in parport_pc.h. | 277 | * of these are in parport_pc.h. |
| 273 | */ | 278 | */ |
| 274 | 279 | ||
| 275 | static void parport_pc_init_state(struct pardevice *dev, struct parport_state *s) | 280 | static void parport_pc_init_state(struct pardevice *dev, |
| 281 | struct parport_state *s) | ||
| 276 | { | 282 | { |
| 277 | s->u.pc.ctr = 0xc; | 283 | s->u.pc.ctr = 0xc; |
| 278 | if (dev->irq_func && | 284 | if (dev->irq_func && |
| @@ -289,22 +295,23 @@ static void parport_pc_save_state(struct parport *p, struct parport_state *s) | |||
| 289 | const struct parport_pc_private *priv = p->physport->private_data; | 295 | const struct parport_pc_private *priv = p->physport->private_data; |
| 290 | s->u.pc.ctr = priv->ctr; | 296 | s->u.pc.ctr = priv->ctr; |
| 291 | if (priv->ecr) | 297 | if (priv->ecr) |
| 292 | s->u.pc.ecr = inb (ECONTROL (p)); | 298 | s->u.pc.ecr = inb(ECONTROL(p)); |
| 293 | } | 299 | } |
| 294 | 300 | ||
| 295 | static void parport_pc_restore_state(struct parport *p, struct parport_state *s) | 301 | static void parport_pc_restore_state(struct parport *p, |
| 302 | struct parport_state *s) | ||
| 296 | { | 303 | { |
| 297 | struct parport_pc_private *priv = p->physport->private_data; | 304 | struct parport_pc_private *priv = p->physport->private_data; |
| 298 | register unsigned char c = s->u.pc.ctr & priv->ctr_writable; | 305 | register unsigned char c = s->u.pc.ctr & priv->ctr_writable; |
| 299 | outb (c, CONTROL (p)); | 306 | outb(c, CONTROL(p)); |
| 300 | priv->ctr = c; | 307 | priv->ctr = c; |
| 301 | if (priv->ecr) | 308 | if (priv->ecr) |
| 302 | ECR_WRITE (p, s->u.pc.ecr); | 309 | ECR_WRITE(p, s->u.pc.ecr); |
| 303 | } | 310 | } |
| 304 | 311 | ||
| 305 | #ifdef CONFIG_PARPORT_1284 | 312 | #ifdef CONFIG_PARPORT_1284 |
| 306 | static size_t parport_pc_epp_read_data (struct parport *port, void *buf, | 313 | static size_t parport_pc_epp_read_data(struct parport *port, void *buf, |
| 307 | size_t length, int flags) | 314 | size_t length, int flags) |
| 308 | { | 315 | { |
| 309 | size_t got = 0; | 316 | size_t got = 0; |
| 310 | 317 | ||
| @@ -316,54 +323,52 @@ static size_t parport_pc_epp_read_data (struct parport *port, void *buf, | |||
| 316 | * nFault is 0 if there is at least 1 byte in the Warp's FIFO | 323 | * nFault is 0 if there is at least 1 byte in the Warp's FIFO |
| 317 | * pError is 1 if there are 16 bytes in the Warp's FIFO | 324 | * pError is 1 if there are 16 bytes in the Warp's FIFO |
| 318 | */ | 325 | */ |
| 319 | status = inb (STATUS (port)); | 326 | status = inb(STATUS(port)); |
| 320 | 327 | ||
| 321 | while (!(status & 0x08) && (got < length)) { | 328 | while (!(status & 0x08) && got < length) { |
| 322 | if ((left >= 16) && (status & 0x20) && !(status & 0x08)) { | 329 | if (left >= 16 && (status & 0x20) && !(status & 0x08)) { |
| 323 | /* can grab 16 bytes from warp fifo */ | 330 | /* can grab 16 bytes from warp fifo */ |
| 324 | if (!((long)buf & 0x03)) { | 331 | if (!((long)buf & 0x03)) |
| 325 | insl (EPPDATA (port), buf, 4); | 332 | insl(EPPDATA(port), buf, 4); |
| 326 | } else { | 333 | else |
| 327 | insb (EPPDATA (port), buf, 16); | 334 | insb(EPPDATA(port), buf, 16); |
| 328 | } | ||
| 329 | buf += 16; | 335 | buf += 16; |
| 330 | got += 16; | 336 | got += 16; |
| 331 | left -= 16; | 337 | left -= 16; |
| 332 | } else { | 338 | } else { |
| 333 | /* grab single byte from the warp fifo */ | 339 | /* grab single byte from the warp fifo */ |
| 334 | *((char *)buf) = inb (EPPDATA (port)); | 340 | *((char *)buf) = inb(EPPDATA(port)); |
| 335 | buf++; | 341 | buf++; |
| 336 | got++; | 342 | got++; |
| 337 | left--; | 343 | left--; |
| 338 | } | 344 | } |
| 339 | status = inb (STATUS (port)); | 345 | status = inb(STATUS(port)); |
| 340 | if (status & 0x01) { | 346 | if (status & 0x01) { |
| 341 | /* EPP timeout should never occur... */ | 347 | /* EPP timeout should never occur... */ |
| 342 | printk (KERN_DEBUG "%s: EPP timeout occurred while talking to " | 348 | printk(KERN_DEBUG |
| 343 | "w91284pic (should not have done)\n", port->name); | 349 | "%s: EPP timeout occurred while talking to w91284pic (should not have done)\n", port->name); |
| 344 | clear_epp_timeout (port); | 350 | clear_epp_timeout(port); |
| 345 | } | 351 | } |
| 346 | } | 352 | } |
| 347 | return got; | 353 | return got; |
| 348 | } | 354 | } |
| 349 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { | 355 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { |
| 350 | if (!(((long)buf | length) & 0x03)) { | 356 | if (!(((long)buf | length) & 0x03)) |
| 351 | insl (EPPDATA (port), buf, (length >> 2)); | 357 | insl(EPPDATA(port), buf, (length >> 2)); |
| 352 | } else { | 358 | else |
| 353 | insb (EPPDATA (port), buf, length); | 359 | insb(EPPDATA(port), buf, length); |
| 354 | } | 360 | if (inb(STATUS(port)) & 0x01) { |
| 355 | if (inb (STATUS (port)) & 0x01) { | 361 | clear_epp_timeout(port); |
| 356 | clear_epp_timeout (port); | ||
| 357 | return -EIO; | 362 | return -EIO; |
| 358 | } | 363 | } |
| 359 | return length; | 364 | return length; |
| 360 | } | 365 | } |
| 361 | for (; got < length; got++) { | 366 | for (; got < length; got++) { |
| 362 | *((char*)buf) = inb (EPPDATA(port)); | 367 | *((char *)buf) = inb(EPPDATA(port)); |
| 363 | buf++; | 368 | buf++; |
| 364 | if (inb (STATUS (port)) & 0x01) { | 369 | if (inb(STATUS(port)) & 0x01) { |
| 365 | /* EPP timeout */ | 370 | /* EPP timeout */ |
| 366 | clear_epp_timeout (port); | 371 | clear_epp_timeout(port); |
| 367 | break; | 372 | break; |
| 368 | } | 373 | } |
| 369 | } | 374 | } |
| @@ -371,28 +376,27 @@ static size_t parport_pc_epp_read_data (struct parport *port, void *buf, | |||
| 371 | return got; | 376 | return got; |
| 372 | } | 377 | } |
| 373 | 378 | ||
| 374 | static size_t parport_pc_epp_write_data (struct parport *port, const void *buf, | 379 | static size_t parport_pc_epp_write_data(struct parport *port, const void *buf, |
| 375 | size_t length, int flags) | 380 | size_t length, int flags) |
| 376 | { | 381 | { |
| 377 | size_t written = 0; | 382 | size_t written = 0; |
| 378 | 383 | ||
| 379 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { | 384 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { |
| 380 | if (!(((long)buf | length) & 0x03)) { | 385 | if (!(((long)buf | length) & 0x03)) |
| 381 | outsl (EPPDATA (port), buf, (length >> 2)); | 386 | outsl(EPPDATA(port), buf, (length >> 2)); |
| 382 | } else { | 387 | else |
| 383 | outsb (EPPDATA (port), buf, length); | 388 | outsb(EPPDATA(port), buf, length); |
| 384 | } | 389 | if (inb(STATUS(port)) & 0x01) { |
| 385 | if (inb (STATUS (port)) & 0x01) { | 390 | clear_epp_timeout(port); |
| 386 | clear_epp_timeout (port); | ||
| 387 | return -EIO; | 391 | return -EIO; |
| 388 | } | 392 | } |
| 389 | return length; | 393 | return length; |
| 390 | } | 394 | } |
| 391 | for (; written < length; written++) { | 395 | for (; written < length; written++) { |
| 392 | outb (*((char*)buf), EPPDATA(port)); | 396 | outb(*((char *)buf), EPPDATA(port)); |
| 393 | buf++; | 397 | buf++; |
| 394 | if (inb (STATUS(port)) & 0x01) { | 398 | if (inb(STATUS(port)) & 0x01) { |
| 395 | clear_epp_timeout (port); | 399 | clear_epp_timeout(port); |
| 396 | break; | 400 | break; |
| 397 | } | 401 | } |
| 398 | } | 402 | } |
| @@ -400,24 +404,24 @@ static size_t parport_pc_epp_write_data (struct parport *port, const void *buf, | |||
| 400 | return written; | 404 | return written; |
| 401 | } | 405 | } |
| 402 | 406 | ||
| 403 | static size_t parport_pc_epp_read_addr (struct parport *port, void *buf, | 407 | static size_t parport_pc_epp_read_addr(struct parport *port, void *buf, |
| 404 | size_t length, int flags) | 408 | size_t length, int flags) |
| 405 | { | 409 | { |
| 406 | size_t got = 0; | 410 | size_t got = 0; |
| 407 | 411 | ||
| 408 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { | 412 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { |
| 409 | insb (EPPADDR (port), buf, length); | 413 | insb(EPPADDR(port), buf, length); |
| 410 | if (inb (STATUS (port)) & 0x01) { | 414 | if (inb(STATUS(port)) & 0x01) { |
| 411 | clear_epp_timeout (port); | 415 | clear_epp_timeout(port); |
| 412 | return -EIO; | 416 | return -EIO; |
| 413 | } | 417 | } |
| 414 | return length; | 418 | return length; |
| 415 | } | 419 | } |
| 416 | for (; got < length; got++) { | 420 | for (; got < length; got++) { |
| 417 | *((char*)buf) = inb (EPPADDR (port)); | 421 | *((char *)buf) = inb(EPPADDR(port)); |
| 418 | buf++; | 422 | buf++; |
| 419 | if (inb (STATUS (port)) & 0x01) { | 423 | if (inb(STATUS(port)) & 0x01) { |
| 420 | clear_epp_timeout (port); | 424 | clear_epp_timeout(port); |
| 421 | break; | 425 | break; |
| 422 | } | 426 | } |
| 423 | } | 427 | } |
| @@ -425,25 +429,25 @@ static size_t parport_pc_epp_read_addr (struct parport *port, void *buf, | |||
| 425 | return got; | 429 | return got; |
| 426 | } | 430 | } |
| 427 | 431 | ||
| 428 | static size_t parport_pc_epp_write_addr (struct parport *port, | 432 | static size_t parport_pc_epp_write_addr(struct parport *port, |
| 429 | const void *buf, size_t length, | 433 | const void *buf, size_t length, |
| 430 | int flags) | 434 | int flags) |
| 431 | { | 435 | { |
| 432 | size_t written = 0; | 436 | size_t written = 0; |
| 433 | 437 | ||
| 434 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { | 438 | if ((flags & PARPORT_EPP_FAST) && (length > 1)) { |
| 435 | outsb (EPPADDR (port), buf, length); | 439 | outsb(EPPADDR(port), buf, length); |
| 436 | if (inb (STATUS (port)) & 0x01) { | 440 | if (inb(STATUS(port)) & 0x01) { |
| 437 | clear_epp_timeout (port); | 441 | clear_epp_timeout(port); |
| 438 | return -EIO; | 442 | return -EIO; |
| 439 | } | 443 | } |
| 440 | return length; | 444 | return length; |
| 441 | } | 445 | } |
| 442 | for (; written < length; written++) { | 446 | for (; written < length; written++) { |
| 443 | outb (*((char*)buf), EPPADDR (port)); | 447 | outb(*((char *)buf), EPPADDR(port)); |
| 444 | buf++; | 448 | buf++; |
| 445 | if (inb (STATUS (port)) & 0x01) { | 449 | if (inb(STATUS(port)) & 0x01) { |
| 446 | clear_epp_timeout (port); | 450 | clear_epp_timeout(port); |
| 447 | break; | 451 | break; |
| 448 | } | 452 | } |
| 449 | } | 453 | } |
| @@ -451,74 +455,74 @@ static size_t parport_pc_epp_write_addr (struct parport *port, | |||
| 451 | return written; | 455 | return written; |
| 452 | } | 456 | } |
| 453 | 457 | ||
| 454 | static size_t parport_pc_ecpepp_read_data (struct parport *port, void *buf, | 458 | static size_t parport_pc_ecpepp_read_data(struct parport *port, void *buf, |
| 455 | size_t length, int flags) | 459 | size_t length, int flags) |
| 456 | { | 460 | { |
| 457 | size_t got; | 461 | size_t got; |
| 458 | 462 | ||
| 459 | frob_set_mode (port, ECR_EPP); | 463 | frob_set_mode(port, ECR_EPP); |
| 460 | parport_pc_data_reverse (port); | 464 | parport_pc_data_reverse(port); |
| 461 | parport_pc_write_control (port, 0x4); | 465 | parport_pc_write_control(port, 0x4); |
| 462 | got = parport_pc_epp_read_data (port, buf, length, flags); | 466 | got = parport_pc_epp_read_data(port, buf, length, flags); |
| 463 | frob_set_mode (port, ECR_PS2); | 467 | frob_set_mode(port, ECR_PS2); |
| 464 | 468 | ||
| 465 | return got; | 469 | return got; |
| 466 | } | 470 | } |
| 467 | 471 | ||
| 468 | static size_t parport_pc_ecpepp_write_data (struct parport *port, | 472 | static size_t parport_pc_ecpepp_write_data(struct parport *port, |
| 469 | const void *buf, size_t length, | 473 | const void *buf, size_t length, |
| 470 | int flags) | 474 | int flags) |
| 471 | { | 475 | { |
| 472 | size_t written; | 476 | size_t written; |
| 473 | 477 | ||
| 474 | frob_set_mode (port, ECR_EPP); | 478 | frob_set_mode(port, ECR_EPP); |
| 475 | parport_pc_write_control (port, 0x4); | 479 | parport_pc_write_control(port, 0x4); |
| 476 | parport_pc_data_forward (port); | 480 | parport_pc_data_forward(port); |
| 477 | written = parport_pc_epp_write_data (port, buf, length, flags); | 481 | written = parport_pc_epp_write_data(port, buf, length, flags); |
| 478 | frob_set_mode (port, ECR_PS2); | 482 | frob_set_mode(port, ECR_PS2); |
| 479 | 483 | ||
| 480 | return written; | 484 | return written; |
| 481 | } | 485 | } |
| 482 | 486 | ||
| 483 | static size_t parport_pc_ecpepp_read_addr (struct parport *port, void *buf, | 487 | static size_t parport_pc_ecpepp_read_addr(struct parport *port, void *buf, |
| 484 | size_t length, int flags) | 488 | size_t length, int flags) |
| 485 | { | 489 | { |
| 486 | size_t got; | 490 | size_t got; |
| 487 | 491 | ||
| 488 | frob_set_mode (port, ECR_EPP); | 492 | frob_set_mode(port, ECR_EPP); |
| 489 | parport_pc_data_reverse (port); | 493 | parport_pc_data_reverse(port); |
| 490 | parport_pc_write_control (port, 0x4); | 494 | parport_pc_write_control(port, 0x4); |
| 491 | got = parport_pc_epp_read_addr (port, buf, length, flags); | 495 | got = parport_pc_epp_read_addr(port, buf, length, flags); |
| 492 | frob_set_mode (port, ECR_PS2); | 496 | frob_set_mode(port, ECR_PS2); |
| 493 | 497 | ||
| 494 | return got; | 498 | return got; |
| 495 | } | 499 | } |
| 496 | 500 | ||
| 497 | static size_t parport_pc_ecpepp_write_addr (struct parport *port, | 501 | static size_t parport_pc_ecpepp_write_addr(struct parport *port, |
| 498 | const void *buf, size_t length, | 502 | const void *buf, size_t length, |
| 499 | int flags) | 503 | int flags) |
| 500 | { | 504 | { |
| 501 | size_t written; | 505 | size_t written; |
| 502 | 506 | ||
| 503 | frob_set_mode (port, ECR_EPP); | 507 | frob_set_mode(port, ECR_EPP); |
| 504 | parport_pc_write_control (port, 0x4); | 508 | parport_pc_write_control(port, 0x4); |
| 505 | parport_pc_data_forward (port); | 509 | parport_pc_data_forward(port); |
| 506 | written = parport_pc_epp_write_addr (port, buf, length, flags); | 510 | written = parport_pc_epp_write_addr(port, buf, length, flags); |
| 507 | frob_set_mode (port, ECR_PS2); | 511 | frob_set_mode(port, ECR_PS2); |
| 508 | 512 | ||
| 509 | return written; | 513 | return written; |
| 510 | } | 514 | } |
| 511 | #endif /* IEEE 1284 support */ | 515 | #endif /* IEEE 1284 support */ |
| 512 | 516 | ||
| 513 | #ifdef CONFIG_PARPORT_PC_FIFO | 517 | #ifdef CONFIG_PARPORT_PC_FIFO |
| 514 | static size_t parport_pc_fifo_write_block_pio (struct parport *port, | 518 | static size_t parport_pc_fifo_write_block_pio(struct parport *port, |
| 515 | const void *buf, size_t length) | 519 | const void *buf, size_t length) |
| 516 | { | 520 | { |
| 517 | int ret = 0; | 521 | int ret = 0; |
| 518 | const unsigned char *bufp = buf; | 522 | const unsigned char *bufp = buf; |
| 519 | size_t left = length; | 523 | size_t left = length; |
| 520 | unsigned long expire = jiffies + port->physport->cad->timeout; | 524 | unsigned long expire = jiffies + port->physport->cad->timeout; |
| 521 | const int fifo = FIFO (port); | 525 | const int fifo = FIFO(port); |
| 522 | int poll_for = 8; /* 80 usecs */ | 526 | int poll_for = 8; /* 80 usecs */ |
| 523 | const struct parport_pc_private *priv = port->physport->private_data; | 527 | const struct parport_pc_private *priv = port->physport->private_data; |
| 524 | const int fifo_depth = priv->fifo_depth; | 528 | const int fifo_depth = priv->fifo_depth; |
| @@ -526,25 +530,25 @@ static size_t parport_pc_fifo_write_block_pio (struct parport *port, | |||
| 526 | port = port->physport; | 530 | port = port->physport; |
| 527 | 531 | ||
| 528 | /* We don't want to be interrupted every character. */ | 532 | /* We don't want to be interrupted every character. */ |
| 529 | parport_pc_disable_irq (port); | 533 | parport_pc_disable_irq(port); |
| 530 | /* set nErrIntrEn and serviceIntr */ | 534 | /* set nErrIntrEn and serviceIntr */ |
| 531 | frob_econtrol (port, (1<<4) | (1<<2), (1<<4) | (1<<2)); | 535 | frob_econtrol(port, (1<<4) | (1<<2), (1<<4) | (1<<2)); |
| 532 | 536 | ||
| 533 | /* Forward mode. */ | 537 | /* Forward mode. */ |
| 534 | parport_pc_data_forward (port); /* Must be in PS2 mode */ | 538 | parport_pc_data_forward(port); /* Must be in PS2 mode */ |
| 535 | 539 | ||
| 536 | while (left) { | 540 | while (left) { |
| 537 | unsigned char byte; | 541 | unsigned char byte; |
| 538 | unsigned char ecrval = inb (ECONTROL (port)); | 542 | unsigned char ecrval = inb(ECONTROL(port)); |
| 539 | int i = 0; | 543 | int i = 0; |
| 540 | 544 | ||
| 541 | if (need_resched() && time_before (jiffies, expire)) | 545 | if (need_resched() && time_before(jiffies, expire)) |
| 542 | /* Can't yield the port. */ | 546 | /* Can't yield the port. */ |
| 543 | schedule (); | 547 | schedule(); |
| 544 | 548 | ||
| 545 | /* Anyone else waiting for the port? */ | 549 | /* Anyone else waiting for the port? */ |
| 546 | if (port->waithead) { | 550 | if (port->waithead) { |
| 547 | printk (KERN_DEBUG "Somebody wants the port\n"); | 551 | printk(KERN_DEBUG "Somebody wants the port\n"); |
| 548 | break; | 552 | break; |
| 549 | } | 553 | } |
| 550 | 554 | ||
| @@ -552,21 +556,22 @@ static size_t parport_pc_fifo_write_block_pio (struct parport *port, | |||
| 552 | /* FIFO is full. Wait for interrupt. */ | 556 | /* FIFO is full. Wait for interrupt. */ |
| 553 | 557 | ||
| 554 | /* Clear serviceIntr */ | 558 | /* Clear serviceIntr */ |
| 555 | ECR_WRITE (port, ecrval & ~(1<<2)); | 559 | ECR_WRITE(port, ecrval & ~(1<<2)); |
| 556 | false_alarm: | 560 | false_alarm: |
| 557 | ret = parport_wait_event (port, HZ); | 561 | ret = parport_wait_event(port, HZ); |
| 558 | if (ret < 0) break; | 562 | if (ret < 0) |
| 563 | break; | ||
| 559 | ret = 0; | 564 | ret = 0; |
| 560 | if (!time_before (jiffies, expire)) { | 565 | if (!time_before(jiffies, expire)) { |
| 561 | /* Timed out. */ | 566 | /* Timed out. */ |
| 562 | printk (KERN_DEBUG "FIFO write timed out\n"); | 567 | printk(KERN_DEBUG "FIFO write timed out\n"); |
| 563 | break; | 568 | break; |
| 564 | } | 569 | } |
| 565 | ecrval = inb (ECONTROL (port)); | 570 | ecrval = inb(ECONTROL(port)); |
| 566 | if (!(ecrval & (1<<2))) { | 571 | if (!(ecrval & (1<<2))) { |
| 567 | if (need_resched() && | 572 | if (need_resched() && |
| 568 | time_before (jiffies, expire)) | 573 | time_before(jiffies, expire)) |
| 569 | schedule (); | 574 | schedule(); |
| 570 | 575 | ||
| 571 | goto false_alarm; | 576 | goto false_alarm; |
| 572 | } | 577 | } |
| @@ -577,38 +582,38 @@ static size_t parport_pc_fifo_write_block_pio (struct parport *port, | |||
| 577 | /* Can't fail now. */ | 582 | /* Can't fail now. */ |
| 578 | expire = jiffies + port->cad->timeout; | 583 | expire = jiffies + port->cad->timeout; |
| 579 | 584 | ||
| 580 | poll: | 585 | poll: |
| 581 | if (signal_pending (current)) | 586 | if (signal_pending(current)) |
| 582 | break; | 587 | break; |
| 583 | 588 | ||
| 584 | if (ecrval & 0x01) { | 589 | if (ecrval & 0x01) { |
| 585 | /* FIFO is empty. Blast it full. */ | 590 | /* FIFO is empty. Blast it full. */ |
| 586 | const int n = left < fifo_depth ? left : fifo_depth; | 591 | const int n = left < fifo_depth ? left : fifo_depth; |
| 587 | outsb (fifo, bufp, n); | 592 | outsb(fifo, bufp, n); |
| 588 | bufp += n; | 593 | bufp += n; |
| 589 | left -= n; | 594 | left -= n; |
| 590 | 595 | ||
| 591 | /* Adjust the poll time. */ | 596 | /* Adjust the poll time. */ |
| 592 | if (i < (poll_for - 2)) poll_for--; | 597 | if (i < (poll_for - 2)) |
| 598 | poll_for--; | ||
| 593 | continue; | 599 | continue; |
| 594 | } else if (i++ < poll_for) { | 600 | } else if (i++ < poll_for) { |
| 595 | udelay (10); | 601 | udelay(10); |
| 596 | ecrval = inb (ECONTROL (port)); | 602 | ecrval = inb(ECONTROL(port)); |
| 597 | goto poll; | 603 | goto poll; |
| 598 | } | 604 | } |
| 599 | 605 | ||
| 600 | /* Half-full (call me an optimist) */ | 606 | /* Half-full(call me an optimist) */ |
| 601 | byte = *bufp++; | 607 | byte = *bufp++; |
| 602 | outb (byte, fifo); | 608 | outb(byte, fifo); |
| 603 | left--; | 609 | left--; |
| 604 | } | 610 | } |
| 605 | 611 | dump_parport_state("leave fifo_write_block_pio", port); | |
| 606 | dump_parport_state ("leave fifo_write_block_pio", port); | ||
| 607 | return length - left; | 612 | return length - left; |
| 608 | } | 613 | } |
| 609 | 614 | ||
| 610 | #ifdef HAS_DMA | 615 | #ifdef HAS_DMA |
| 611 | static size_t parport_pc_fifo_write_block_dma (struct parport *port, | 616 | static size_t parport_pc_fifo_write_block_dma(struct parport *port, |
| 612 | const void *buf, size_t length) | 617 | const void *buf, size_t length) |
| 613 | { | 618 | { |
| 614 | int ret = 0; | 619 | int ret = 0; |
| @@ -621,7 +626,7 @@ static size_t parport_pc_fifo_write_block_dma (struct parport *port, | |||
| 621 | unsigned long start = (unsigned long) buf; | 626 | unsigned long start = (unsigned long) buf; |
| 622 | unsigned long end = (unsigned long) buf + length - 1; | 627 | unsigned long end = (unsigned long) buf + length - 1; |
| 623 | 628 | ||
| 624 | dump_parport_state ("enter fifo_write_block_dma", port); | 629 | dump_parport_state("enter fifo_write_block_dma", port); |
| 625 | if (end < MAX_DMA_ADDRESS) { | 630 | if (end < MAX_DMA_ADDRESS) { |
| 626 | /* If it would cross a 64k boundary, cap it at the end. */ | 631 | /* If it would cross a 64k boundary, cap it at the end. */ |
| 627 | if ((start ^ end) & ~0xffffUL) | 632 | if ((start ^ end) & ~0xffffUL) |
| @@ -629,8 +634,9 @@ dump_parport_state ("enter fifo_write_block_dma", port); | |||
| 629 | 634 | ||
| 630 | dma_addr = dma_handle = dma_map_single(dev, (void *)buf, length, | 635 | dma_addr = dma_handle = dma_map_single(dev, (void *)buf, length, |
| 631 | DMA_TO_DEVICE); | 636 | DMA_TO_DEVICE); |
| 632 | } else { | 637 | } else { |
| 633 | /* above 16 MB we use a bounce buffer as ISA-DMA is not possible */ | 638 | /* above 16 MB we use a bounce buffer as ISA-DMA |
| 639 | is not possible */ | ||
| 634 | maxlen = PAGE_SIZE; /* sizeof(priv->dma_buf) */ | 640 | maxlen = PAGE_SIZE; /* sizeof(priv->dma_buf) */ |
| 635 | dma_addr = priv->dma_handle; | 641 | dma_addr = priv->dma_handle; |
| 636 | dma_handle = 0; | 642 | dma_handle = 0; |
| @@ -639,12 +645,12 @@ dump_parport_state ("enter fifo_write_block_dma", port); | |||
| 639 | port = port->physport; | 645 | port = port->physport; |
| 640 | 646 | ||
| 641 | /* We don't want to be interrupted every character. */ | 647 | /* We don't want to be interrupted every character. */ |
| 642 | parport_pc_disable_irq (port); | 648 | parport_pc_disable_irq(port); |
| 643 | /* set nErrIntrEn and serviceIntr */ | 649 | /* set nErrIntrEn and serviceIntr */ |
| 644 | frob_econtrol (port, (1<<4) | (1<<2), (1<<4) | (1<<2)); | 650 | frob_econtrol(port, (1<<4) | (1<<2), (1<<4) | (1<<2)); |
| 645 | 651 | ||
| 646 | /* Forward mode. */ | 652 | /* Forward mode. */ |
| 647 | parport_pc_data_forward (port); /* Must be in PS2 mode */ | 653 | parport_pc_data_forward(port); /* Must be in PS2 mode */ |
| 648 | 654 | ||
| 649 | while (left) { | 655 | while (left) { |
| 650 | unsigned long expire = jiffies + port->physport->cad->timeout; | 656 | unsigned long expire = jiffies + port->physport->cad->timeout; |
| @@ -665,10 +671,10 @@ dump_parport_state ("enter fifo_write_block_dma", port); | |||
| 665 | set_dma_count(port->dma, count); | 671 | set_dma_count(port->dma, count); |
| 666 | 672 | ||
| 667 | /* Set DMA mode */ | 673 | /* Set DMA mode */ |
| 668 | frob_econtrol (port, 1<<3, 1<<3); | 674 | frob_econtrol(port, 1<<3, 1<<3); |
| 669 | 675 | ||
| 670 | /* Clear serviceIntr */ | 676 | /* Clear serviceIntr */ |
| 671 | frob_econtrol (port, 1<<2, 0); | 677 | frob_econtrol(port, 1<<2, 0); |
| 672 | 678 | ||
| 673 | enable_dma(port->dma); | 679 | enable_dma(port->dma); |
| 674 | release_dma_lock(dmaflag); | 680 | release_dma_lock(dmaflag); |
| @@ -676,20 +682,22 @@ dump_parport_state ("enter fifo_write_block_dma", port); | |||
| 676 | /* assume DMA will be successful */ | 682 | /* assume DMA will be successful */ |
| 677 | left -= count; | 683 | left -= count; |
| 678 | buf += count; | 684 | buf += count; |
| 679 | if (dma_handle) dma_addr += count; | 685 | if (dma_handle) |
| 686 | dma_addr += count; | ||
| 680 | 687 | ||
| 681 | /* Wait for interrupt. */ | 688 | /* Wait for interrupt. */ |
| 682 | false_alarm: | 689 | false_alarm: |
| 683 | ret = parport_wait_event (port, HZ); | 690 | ret = parport_wait_event(port, HZ); |
| 684 | if (ret < 0) break; | 691 | if (ret < 0) |
| 692 | break; | ||
| 685 | ret = 0; | 693 | ret = 0; |
| 686 | if (!time_before (jiffies, expire)) { | 694 | if (!time_before(jiffies, expire)) { |
| 687 | /* Timed out. */ | 695 | /* Timed out. */ |
| 688 | printk (KERN_DEBUG "DMA write timed out\n"); | 696 | printk(KERN_DEBUG "DMA write timed out\n"); |
| 689 | break; | 697 | break; |
| 690 | } | 698 | } |
| 691 | /* Is serviceIntr set? */ | 699 | /* Is serviceIntr set? */ |
| 692 | if (!(inb (ECONTROL (port)) & (1<<2))) { | 700 | if (!(inb(ECONTROL(port)) & (1<<2))) { |
| 693 | cond_resched(); | 701 | cond_resched(); |
| 694 | 702 | ||
| 695 | goto false_alarm; | 703 | goto false_alarm; |
| @@ -705,14 +713,15 @@ dump_parport_state ("enter fifo_write_block_dma", port); | |||
| 705 | 713 | ||
| 706 | /* Anyone else waiting for the port? */ | 714 | /* Anyone else waiting for the port? */ |
| 707 | if (port->waithead) { | 715 | if (port->waithead) { |
| 708 | printk (KERN_DEBUG "Somebody wants the port\n"); | 716 | printk(KERN_DEBUG "Somebody wants the port\n"); |
| 709 | break; | 717 | break; |
| 710 | } | 718 | } |
| 711 | 719 | ||
| 712 | /* update for possible DMA residue ! */ | 720 | /* update for possible DMA residue ! */ |
| 713 | buf -= count; | 721 | buf -= count; |
| 714 | left += count; | 722 | left += count; |
| 715 | if (dma_handle) dma_addr -= count; | 723 | if (dma_handle) |
| 724 | dma_addr -= count; | ||
| 716 | } | 725 | } |
| 717 | 726 | ||
| 718 | /* Maybe got here through break, so adjust for DMA residue! */ | 727 | /* Maybe got here through break, so adjust for DMA residue! */ |
| @@ -723,12 +732,12 @@ dump_parport_state ("enter fifo_write_block_dma", port); | |||
| 723 | release_dma_lock(dmaflag); | 732 | release_dma_lock(dmaflag); |
| 724 | 733 | ||
| 725 | /* Turn off DMA mode */ | 734 | /* Turn off DMA mode */ |
| 726 | frob_econtrol (port, 1<<3, 0); | 735 | frob_econtrol(port, 1<<3, 0); |
| 727 | 736 | ||
| 728 | if (dma_handle) | 737 | if (dma_handle) |
| 729 | dma_unmap_single(dev, dma_handle, length, DMA_TO_DEVICE); | 738 | dma_unmap_single(dev, dma_handle, length, DMA_TO_DEVICE); |
| 730 | 739 | ||
| 731 | dump_parport_state ("leave fifo_write_block_dma", port); | 740 | dump_parport_state("leave fifo_write_block_dma", port); |
| 732 | return length - left; | 741 | return length - left; |
| 733 | } | 742 | } |
| 734 | #endif | 743 | #endif |
| @@ -738,13 +747,13 @@ static inline size_t parport_pc_fifo_write_block(struct parport *port, | |||
| 738 | { | 747 | { |
| 739 | #ifdef HAS_DMA | 748 | #ifdef HAS_DMA |
| 740 | if (port->dma != PARPORT_DMA_NONE) | 749 | if (port->dma != PARPORT_DMA_NONE) |
| 741 | return parport_pc_fifo_write_block_dma (port, buf, length); | 750 | return parport_pc_fifo_write_block_dma(port, buf, length); |
| 742 | #endif | 751 | #endif |
| 743 | return parport_pc_fifo_write_block_pio (port, buf, length); | 752 | return parport_pc_fifo_write_block_pio(port, buf, length); |
| 744 | } | 753 | } |
| 745 | 754 | ||
| 746 | /* Parallel Port FIFO mode (ECP chipsets) */ | 755 | /* Parallel Port FIFO mode (ECP chipsets) */ |
| 747 | static size_t parport_pc_compat_write_block_pio (struct parport *port, | 756 | static size_t parport_pc_compat_write_block_pio(struct parport *port, |
| 748 | const void *buf, size_t length, | 757 | const void *buf, size_t length, |
| 749 | int flags) | 758 | int flags) |
| 750 | { | 759 | { |
| @@ -756,14 +765,16 @@ static size_t parport_pc_compat_write_block_pio (struct parport *port, | |||
| 756 | /* Special case: a timeout of zero means we cannot call schedule(). | 765 | /* Special case: a timeout of zero means we cannot call schedule(). |
| 757 | * Also if O_NONBLOCK is set then use the default implementation. */ | 766 | * Also if O_NONBLOCK is set then use the default implementation. */ |
| 758 | if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) | 767 | if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) |
| 759 | return parport_ieee1284_write_compat (port, buf, | 768 | return parport_ieee1284_write_compat(port, buf, |
| 760 | length, flags); | 769 | length, flags); |
| 761 | 770 | ||
| 762 | /* Set up parallel port FIFO mode.*/ | 771 | /* Set up parallel port FIFO mode.*/ |
| 763 | parport_pc_data_forward (port); /* Must be in PS2 mode */ | 772 | parport_pc_data_forward(port); /* Must be in PS2 mode */ |
| 764 | parport_pc_frob_control (port, PARPORT_CONTROL_STROBE, 0); | 773 | parport_pc_frob_control(port, PARPORT_CONTROL_STROBE, 0); |
| 765 | r = change_mode (port, ECR_PPF); /* Parallel port FIFO */ | 774 | r = change_mode(port, ECR_PPF); /* Parallel port FIFO */ |
| 766 | if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_PPF failed\n", port->name); | 775 | if (r) |
| 776 | printk(KERN_DEBUG "%s: Warning change_mode ECR_PPF failed\n", | ||
| 777 | port->name); | ||
| 767 | 778 | ||
| 768 | port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; | 779 | port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; |
| 769 | 780 | ||
| @@ -775,40 +786,39 @@ static size_t parport_pc_compat_write_block_pio (struct parport *port, | |||
| 775 | * the FIFO is empty, so allow 4 seconds for each position | 786 | * the FIFO is empty, so allow 4 seconds for each position |
| 776 | * in the fifo. | 787 | * in the fifo. |
| 777 | */ | 788 | */ |
| 778 | expire = jiffies + (priv->fifo_depth * HZ * 4); | 789 | expire = jiffies + (priv->fifo_depth * HZ * 4); |
| 779 | do { | 790 | do { |
| 780 | /* Wait for the FIFO to empty */ | 791 | /* Wait for the FIFO to empty */ |
| 781 | r = change_mode (port, ECR_PS2); | 792 | r = change_mode(port, ECR_PS2); |
| 782 | if (r != -EBUSY) { | 793 | if (r != -EBUSY) |
| 783 | break; | 794 | break; |
| 784 | } | 795 | } while (time_before(jiffies, expire)); |
| 785 | } while (time_before (jiffies, expire)); | ||
| 786 | if (r == -EBUSY) { | 796 | if (r == -EBUSY) { |
| 787 | 797 | ||
| 788 | printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name); | 798 | printk(KERN_DEBUG "%s: FIFO is stuck\n", port->name); |
| 789 | 799 | ||
| 790 | /* Prevent further data transfer. */ | 800 | /* Prevent further data transfer. */ |
| 791 | frob_set_mode (port, ECR_TST); | 801 | frob_set_mode(port, ECR_TST); |
| 792 | 802 | ||
| 793 | /* Adjust for the contents of the FIFO. */ | 803 | /* Adjust for the contents of the FIFO. */ |
| 794 | for (written -= priv->fifo_depth; ; written++) { | 804 | for (written -= priv->fifo_depth; ; written++) { |
| 795 | if (inb (ECONTROL (port)) & 0x2) { | 805 | if (inb(ECONTROL(port)) & 0x2) { |
| 796 | /* Full up. */ | 806 | /* Full up. */ |
| 797 | break; | 807 | break; |
| 798 | } | 808 | } |
| 799 | outb (0, FIFO (port)); | 809 | outb(0, FIFO(port)); |
| 800 | } | 810 | } |
| 801 | 811 | ||
| 802 | /* Reset the FIFO and return to PS2 mode. */ | 812 | /* Reset the FIFO and return to PS2 mode. */ |
| 803 | frob_set_mode (port, ECR_PS2); | 813 | frob_set_mode(port, ECR_PS2); |
| 804 | } | 814 | } |
| 805 | 815 | ||
| 806 | r = parport_wait_peripheral (port, | 816 | r = parport_wait_peripheral(port, |
| 807 | PARPORT_STATUS_BUSY, | 817 | PARPORT_STATUS_BUSY, |
| 808 | PARPORT_STATUS_BUSY); | 818 | PARPORT_STATUS_BUSY); |
| 809 | if (r) | 819 | if (r) |
| 810 | printk (KERN_DEBUG | 820 | printk(KERN_DEBUG |
| 811 | "%s: BUSY timeout (%d) in compat_write_block_pio\n", | 821 | "%s: BUSY timeout (%d) in compat_write_block_pio\n", |
| 812 | port->name, r); | 822 | port->name, r); |
| 813 | 823 | ||
| 814 | port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; | 824 | port->physport->ieee1284.phase = IEEE1284_PH_FWD_IDLE; |
| @@ -818,7 +828,7 @@ static size_t parport_pc_compat_write_block_pio (struct parport *port, | |||
| 818 | 828 | ||
| 819 | /* ECP */ | 829 | /* ECP */ |
| 820 | #ifdef CONFIG_PARPORT_1284 | 830 | #ifdef CONFIG_PARPORT_1284 |
| 821 | static size_t parport_pc_ecp_write_block_pio (struct parport *port, | 831 | static size_t parport_pc_ecp_write_block_pio(struct parport *port, |
| 822 | const void *buf, size_t length, | 832 | const void *buf, size_t length, |
| 823 | int flags) | 833 | int flags) |
| 824 | { | 834 | { |
| @@ -830,36 +840,38 @@ static size_t parport_pc_ecp_write_block_pio (struct parport *port, | |||
| 830 | /* Special case: a timeout of zero means we cannot call schedule(). | 840 | /* Special case: a timeout of zero means we cannot call schedule(). |
| 831 | * Also if O_NONBLOCK is set then use the default implementation. */ | 841 | * Also if O_NONBLOCK is set then use the default implementation. */ |
| 832 | if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) | 842 | if (port->physport->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) |
| 833 | return parport_ieee1284_ecp_write_data (port, buf, | 843 | return parport_ieee1284_ecp_write_data(port, buf, |
| 834 | length, flags); | 844 | length, flags); |
| 835 | 845 | ||
| 836 | /* Switch to forward mode if necessary. */ | 846 | /* Switch to forward mode if necessary. */ |
| 837 | if (port->physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { | 847 | if (port->physport->ieee1284.phase != IEEE1284_PH_FWD_IDLE) { |
| 838 | /* Event 47: Set nInit high. */ | 848 | /* Event 47: Set nInit high. */ |
| 839 | parport_frob_control (port, | 849 | parport_frob_control(port, |
| 840 | PARPORT_CONTROL_INIT | 850 | PARPORT_CONTROL_INIT |
| 841 | | PARPORT_CONTROL_AUTOFD, | 851 | | PARPORT_CONTROL_AUTOFD, |
| 842 | PARPORT_CONTROL_INIT | 852 | PARPORT_CONTROL_INIT |
| 843 | | PARPORT_CONTROL_AUTOFD); | 853 | | PARPORT_CONTROL_AUTOFD); |
| 844 | 854 | ||
| 845 | /* Event 49: PError goes high. */ | 855 | /* Event 49: PError goes high. */ |
| 846 | r = parport_wait_peripheral (port, | 856 | r = parport_wait_peripheral(port, |
| 847 | PARPORT_STATUS_PAPEROUT, | 857 | PARPORT_STATUS_PAPEROUT, |
| 848 | PARPORT_STATUS_PAPEROUT); | 858 | PARPORT_STATUS_PAPEROUT); |
| 849 | if (r) { | 859 | if (r) { |
| 850 | printk (KERN_DEBUG "%s: PError timeout (%d) " | 860 | printk(KERN_DEBUG "%s: PError timeout (%d) " |
| 851 | "in ecp_write_block_pio\n", port->name, r); | 861 | "in ecp_write_block_pio\n", port->name, r); |
| 852 | } | 862 | } |
| 853 | } | 863 | } |
| 854 | 864 | ||
| 855 | /* Set up ECP parallel port mode.*/ | 865 | /* Set up ECP parallel port mode.*/ |
| 856 | parport_pc_data_forward (port); /* Must be in PS2 mode */ | 866 | parport_pc_data_forward(port); /* Must be in PS2 mode */ |
| 857 | parport_pc_frob_control (port, | 867 | parport_pc_frob_control(port, |
| 858 | PARPORT_CONTROL_STROBE | | 868 | PARPORT_CONTROL_STROBE | |
| 859 | PARPORT_CONTROL_AUTOFD, | 869 | PARPORT_CONTROL_AUTOFD, |
| 860 | 0); | 870 | 0); |
| 861 | r = change_mode (port, ECR_ECP); /* ECP FIFO */ | 871 | r = change_mode(port, ECR_ECP); /* ECP FIFO */ |
| 862 | if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name); | 872 | if (r) |
| 873 | printk(KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", | ||
| 874 | port->name); | ||
| 863 | port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; | 875 | port->physport->ieee1284.phase = IEEE1284_PH_FWD_DATA; |
| 864 | 876 | ||
| 865 | /* Write the data to the FIFO. */ | 877 | /* Write the data to the FIFO. */ |
| @@ -873,55 +885,54 @@ static size_t parport_pc_ecp_write_block_pio (struct parport *port, | |||
| 873 | expire = jiffies + (priv->fifo_depth * (HZ * 4)); | 885 | expire = jiffies + (priv->fifo_depth * (HZ * 4)); |
| 874 | do { | 886 | do { |
| 875 | /* Wait for the FIFO to empty */ | 887 | /* Wait for the FIFO to empty */ |
| 876 | r = change_mode (port, ECR_PS2); | 888 | r = change_mode(port, ECR_PS2); |
| 877 | if (r != -EBUSY) { | 889 | if (r != -EBUSY) |
| 878 | break; | 890 | break; |
| 879 | } | 891 | } while (time_before(jiffies, expire)); |
| 880 | } while (time_before (jiffies, expire)); | ||
| 881 | if (r == -EBUSY) { | 892 | if (r == -EBUSY) { |
| 882 | 893 | ||
| 883 | printk (KERN_DEBUG "%s: FIFO is stuck\n", port->name); | 894 | printk(KERN_DEBUG "%s: FIFO is stuck\n", port->name); |
| 884 | 895 | ||
| 885 | /* Prevent further data transfer. */ | 896 | /* Prevent further data transfer. */ |
| 886 | frob_set_mode (port, ECR_TST); | 897 | frob_set_mode(port, ECR_TST); |
| 887 | 898 | ||
| 888 | /* Adjust for the contents of the FIFO. */ | 899 | /* Adjust for the contents of the FIFO. */ |
| 889 | for (written -= priv->fifo_depth; ; written++) { | 900 | for (written -= priv->fifo_depth; ; written++) { |
| 890 | if (inb (ECONTROL (port)) & 0x2) { | 901 | if (inb(ECONTROL(port)) & 0x2) { |
| 891 | /* Full up. */ | 902 | /* Full up. */ |
| 892 | break; | 903 | break; |
| 893 | } | 904 | } |
| 894 | outb (0, FIFO (port)); | 905 | outb(0, FIFO(port)); |
| 895 | } | 906 | } |
| 896 | 907 | ||
| 897 | /* Reset the FIFO and return to PS2 mode. */ | 908 | /* Reset the FIFO and return to PS2 mode. */ |
| 898 | frob_set_mode (port, ECR_PS2); | 909 | frob_set_mode(port, ECR_PS2); |
| 899 | 910 | ||
| 900 | /* Host transfer recovery. */ | 911 | /* Host transfer recovery. */ |
| 901 | parport_pc_data_reverse (port); /* Must be in PS2 mode */ | 912 | parport_pc_data_reverse(port); /* Must be in PS2 mode */ |
| 902 | udelay (5); | 913 | udelay(5); |
| 903 | parport_frob_control (port, PARPORT_CONTROL_INIT, 0); | 914 | parport_frob_control(port, PARPORT_CONTROL_INIT, 0); |
| 904 | r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); | 915 | r = parport_wait_peripheral(port, PARPORT_STATUS_PAPEROUT, 0); |
| 905 | if (r) | 916 | if (r) |
| 906 | printk (KERN_DEBUG "%s: PE,1 timeout (%d) " | 917 | printk(KERN_DEBUG "%s: PE,1 timeout (%d) " |
| 907 | "in ecp_write_block_pio\n", port->name, r); | 918 | "in ecp_write_block_pio\n", port->name, r); |
| 908 | 919 | ||
| 909 | parport_frob_control (port, | 920 | parport_frob_control(port, |
| 910 | PARPORT_CONTROL_INIT, | 921 | PARPORT_CONTROL_INIT, |
| 911 | PARPORT_CONTROL_INIT); | 922 | PARPORT_CONTROL_INIT); |
| 912 | r = parport_wait_peripheral (port, | 923 | r = parport_wait_peripheral(port, |
| 913 | PARPORT_STATUS_PAPEROUT, | 924 | PARPORT_STATUS_PAPEROUT, |
| 914 | PARPORT_STATUS_PAPEROUT); | 925 | PARPORT_STATUS_PAPEROUT); |
| 915 | if (r) | 926 | if (r) |
| 916 | printk (KERN_DEBUG "%s: PE,2 timeout (%d) " | 927 | printk(KERN_DEBUG "%s: PE,2 timeout (%d) " |
| 917 | "in ecp_write_block_pio\n", port->name, r); | 928 | "in ecp_write_block_pio\n", port->name, r); |
| 918 | } | 929 | } |
| 919 | 930 | ||
| 920 | r = parport_wait_peripheral (port, | 931 | r = parport_wait_peripheral(port, |
| 921 | PARPORT_STATUS_BUSY, | 932 | PARPORT_STATUS_BUSY, |
| 922 | PARPORT_STATUS_BUSY); | 933 | PARPORT_STATUS_BUSY); |
| 923 | if(r) | 934 | if (r) |
| 924 | printk (KERN_DEBUG | 935 | printk(KERN_DEBUG |
| 925 | "%s: BUSY timeout (%d) in ecp_write_block_pio\n", | 936 | "%s: BUSY timeout (%d) in ecp_write_block_pio\n", |
| 926 | port->name, r); | 937 | port->name, r); |
| 927 | 938 | ||
| @@ -931,7 +942,7 @@ static size_t parport_pc_ecp_write_block_pio (struct parport *port, | |||
| 931 | } | 942 | } |
| 932 | 943 | ||
| 933 | #if 0 | 944 | #if 0 |
| 934 | static size_t parport_pc_ecp_read_block_pio (struct parport *port, | 945 | static size_t parport_pc_ecp_read_block_pio(struct parport *port, |
| 935 | void *buf, size_t length, | 946 | void *buf, size_t length, |
| 936 | int flags) | 947 | int flags) |
| 937 | { | 948 | { |
| @@ -944,13 +955,13 @@ static size_t parport_pc_ecp_read_block_pio (struct parport *port, | |||
| 944 | char *bufp = buf; | 955 | char *bufp = buf; |
| 945 | 956 | ||
| 946 | port = port->physport; | 957 | port = port->physport; |
| 947 | DPRINTK (KERN_DEBUG "parport_pc: parport_pc_ecp_read_block_pio\n"); | 958 | DPRINTK(KERN_DEBUG "parport_pc: parport_pc_ecp_read_block_pio\n"); |
| 948 | dump_parport_state ("enter fcn", port); | 959 | dump_parport_state("enter fcn", port); |
| 949 | 960 | ||
| 950 | /* Special case: a timeout of zero means we cannot call schedule(). | 961 | /* Special case: a timeout of zero means we cannot call schedule(). |
| 951 | * Also if O_NONBLOCK is set then use the default implementation. */ | 962 | * Also if O_NONBLOCK is set then use the default implementation. */ |
| 952 | if (port->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) | 963 | if (port->cad->timeout <= PARPORT_INACTIVITY_O_NONBLOCK) |
| 953 | return parport_ieee1284_ecp_read_data (port, buf, | 964 | return parport_ieee1284_ecp_read_data(port, buf, |
| 954 | length, flags); | 965 | length, flags); |
| 955 | 966 | ||
| 956 | if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE) { | 967 | if (port->ieee1284.mode == IEEE1284_MODE_ECPRLE) { |
| @@ -966,173 +977,178 @@ dump_parport_state ("enter fcn", port); | |||
| 966 | * go through software emulation. Otherwise we may have to throw | 977 | * go through software emulation. Otherwise we may have to throw |
| 967 | * away data. */ | 978 | * away data. */ |
| 968 | if (length < fifofull) | 979 | if (length < fifofull) |
| 969 | return parport_ieee1284_ecp_read_data (port, buf, | 980 | return parport_ieee1284_ecp_read_data(port, buf, |
| 970 | length, flags); | 981 | length, flags); |
| 971 | 982 | ||
| 972 | if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) { | 983 | if (port->ieee1284.phase != IEEE1284_PH_REV_IDLE) { |
| 973 | /* change to reverse-idle phase (must be in forward-idle) */ | 984 | /* change to reverse-idle phase (must be in forward-idle) */ |
| 974 | 985 | ||
| 975 | /* Event 38: Set nAutoFd low (also make sure nStrobe is high) */ | 986 | /* Event 38: Set nAutoFd low (also make sure nStrobe is high) */ |
| 976 | parport_frob_control (port, | 987 | parport_frob_control(port, |
| 977 | PARPORT_CONTROL_AUTOFD | 988 | PARPORT_CONTROL_AUTOFD |
| 978 | | PARPORT_CONTROL_STROBE, | 989 | | PARPORT_CONTROL_STROBE, |
| 979 | PARPORT_CONTROL_AUTOFD); | 990 | PARPORT_CONTROL_AUTOFD); |
| 980 | parport_pc_data_reverse (port); /* Must be in PS2 mode */ | 991 | parport_pc_data_reverse(port); /* Must be in PS2 mode */ |
| 981 | udelay (5); | 992 | udelay(5); |
| 982 | /* Event 39: Set nInit low to initiate bus reversal */ | 993 | /* Event 39: Set nInit low to initiate bus reversal */ |
| 983 | parport_frob_control (port, | 994 | parport_frob_control(port, |
| 984 | PARPORT_CONTROL_INIT, | 995 | PARPORT_CONTROL_INIT, |
| 985 | 0); | 996 | 0); |
| 986 | /* Event 40: Wait for nAckReverse (PError) to go low */ | 997 | /* Event 40: Wait for nAckReverse (PError) to go low */ |
| 987 | r = parport_wait_peripheral (port, PARPORT_STATUS_PAPEROUT, 0); | 998 | r = parport_wait_peripheral(port, PARPORT_STATUS_PAPEROUT, 0); |
| 988 | if (r) { | 999 | if (r) { |
| 989 | printk (KERN_DEBUG "%s: PE timeout Event 40 (%d) " | 1000 | printk(KERN_DEBUG "%s: PE timeout Event 40 (%d) " |
| 990 | "in ecp_read_block_pio\n", port->name, r); | 1001 | "in ecp_read_block_pio\n", port->name, r); |
| 991 | return 0; | 1002 | return 0; |
| 992 | } | 1003 | } |
| 993 | } | 1004 | } |
| 994 | 1005 | ||
| 995 | /* Set up ECP FIFO mode.*/ | 1006 | /* Set up ECP FIFO mode.*/ |
| 996 | /* parport_pc_frob_control (port, | 1007 | /* parport_pc_frob_control(port, |
| 997 | PARPORT_CONTROL_STROBE | | 1008 | PARPORT_CONTROL_STROBE | |
| 998 | PARPORT_CONTROL_AUTOFD, | 1009 | PARPORT_CONTROL_AUTOFD, |
| 999 | PARPORT_CONTROL_AUTOFD); */ | 1010 | PARPORT_CONTROL_AUTOFD); */ |
| 1000 | r = change_mode (port, ECR_ECP); /* ECP FIFO */ | 1011 | r = change_mode(port, ECR_ECP); /* ECP FIFO */ |
| 1001 | if (r) printk (KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", port->name); | 1012 | if (r) |
| 1013 | printk(KERN_DEBUG "%s: Warning change_mode ECR_ECP failed\n", | ||
| 1014 | port->name); | ||
| 1002 | 1015 | ||
| 1003 | port->ieee1284.phase = IEEE1284_PH_REV_DATA; | 1016 | port->ieee1284.phase = IEEE1284_PH_REV_DATA; |
| 1004 | 1017 | ||
| 1005 | /* the first byte must be collected manually */ | 1018 | /* the first byte must be collected manually */ |
| 1006 | dump_parport_state ("pre 43", port); | 1019 | dump_parport_state("pre 43", port); |
| 1007 | /* Event 43: Wait for nAck to go low */ | 1020 | /* Event 43: Wait for nAck to go low */ |
| 1008 | r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, 0); | 1021 | r = parport_wait_peripheral(port, PARPORT_STATUS_ACK, 0); |
| 1009 | if (r) { | 1022 | if (r) { |
| 1010 | /* timed out while reading -- no data */ | 1023 | /* timed out while reading -- no data */ |
| 1011 | printk (KERN_DEBUG "PIO read timed out (initial byte)\n"); | 1024 | printk(KERN_DEBUG "PIO read timed out (initial byte)\n"); |
| 1012 | goto out_no_data; | 1025 | goto out_no_data; |
| 1013 | } | 1026 | } |
| 1014 | /* read byte */ | 1027 | /* read byte */ |
| 1015 | *bufp++ = inb (DATA (port)); | 1028 | *bufp++ = inb(DATA(port)); |
| 1016 | left--; | 1029 | left--; |
| 1017 | dump_parport_state ("43-44", port); | 1030 | dump_parport_state("43-44", port); |
| 1018 | /* Event 44: nAutoFd (HostAck) goes high to acknowledge */ | 1031 | /* Event 44: nAutoFd (HostAck) goes high to acknowledge */ |
| 1019 | parport_pc_frob_control (port, | 1032 | parport_pc_frob_control(port, |
| 1020 | PARPORT_CONTROL_AUTOFD, | 1033 | PARPORT_CONTROL_AUTOFD, |
| 1021 | 0); | 1034 | 0); |
| 1022 | dump_parport_state ("pre 45", port); | 1035 | dump_parport_state("pre 45", port); |
| 1023 | /* Event 45: Wait for nAck to go high */ | 1036 | /* Event 45: Wait for nAck to go high */ |
| 1024 | /* r = parport_wait_peripheral (port, PARPORT_STATUS_ACK, PARPORT_STATUS_ACK); */ | 1037 | /* r = parport_wait_peripheral(port, PARPORT_STATUS_ACK, |
| 1025 | dump_parport_state ("post 45", port); | 1038 | PARPORT_STATUS_ACK); */ |
| 1026 | r = 0; | 1039 | dump_parport_state("post 45", port); |
| 1040 | r = 0; | ||
| 1027 | if (r) { | 1041 | if (r) { |
| 1028 | /* timed out while waiting for peripheral to respond to ack */ | 1042 | /* timed out while waiting for peripheral to respond to ack */ |
| 1029 | printk (KERN_DEBUG "ECP PIO read timed out (waiting for nAck)\n"); | 1043 | printk(KERN_DEBUG "ECP PIO read timed out (waiting for nAck)\n"); |
| 1030 | 1044 | ||
| 1031 | /* keep hold of the byte we've got already */ | 1045 | /* keep hold of the byte we've got already */ |
| 1032 | goto out_no_data; | 1046 | goto out_no_data; |
| 1033 | } | 1047 | } |
| 1034 | /* Event 46: nAutoFd (HostAck) goes low to accept more data */ | 1048 | /* Event 46: nAutoFd (HostAck) goes low to accept more data */ |
| 1035 | parport_pc_frob_control (port, | 1049 | parport_pc_frob_control(port, |
| 1036 | PARPORT_CONTROL_AUTOFD, | 1050 | PARPORT_CONTROL_AUTOFD, |
| 1037 | PARPORT_CONTROL_AUTOFD); | 1051 | PARPORT_CONTROL_AUTOFD); |
| 1038 | 1052 | ||
| 1039 | 1053 | ||
| 1040 | dump_parport_state ("rev idle", port); | 1054 | dump_parport_state("rev idle", port); |
| 1041 | /* Do the transfer. */ | 1055 | /* Do the transfer. */ |
| 1042 | while (left > fifofull) { | 1056 | while (left > fifofull) { |
| 1043 | int ret; | 1057 | int ret; |
| 1044 | unsigned long expire = jiffies + port->cad->timeout; | 1058 | unsigned long expire = jiffies + port->cad->timeout; |
| 1045 | unsigned char ecrval = inb (ECONTROL (port)); | 1059 | unsigned char ecrval = inb(ECONTROL(port)); |
| 1046 | 1060 | ||
| 1047 | if (need_resched() && time_before (jiffies, expire)) | 1061 | if (need_resched() && time_before(jiffies, expire)) |
| 1048 | /* Can't yield the port. */ | 1062 | /* Can't yield the port. */ |
| 1049 | schedule (); | 1063 | schedule(); |
| 1050 | 1064 | ||
| 1051 | /* At this point, the FIFO may already be full. In | 1065 | /* At this point, the FIFO may already be full. In |
| 1052 | * that case ECP is already holding back the | 1066 | * that case ECP is already holding back the |
| 1053 | * peripheral (assuming proper design) with a delayed | 1067 | * peripheral (assuming proper design) with a delayed |
| 1054 | * handshake. Work fast to avoid a peripheral | 1068 | * handshake. Work fast to avoid a peripheral |
| 1055 | * timeout. */ | 1069 | * timeout. */ |
| 1056 | 1070 | ||
| 1057 | if (ecrval & 0x01) { | 1071 | if (ecrval & 0x01) { |
| 1058 | /* FIFO is empty. Wait for interrupt. */ | 1072 | /* FIFO is empty. Wait for interrupt. */ |
| 1059 | dump_parport_state ("FIFO empty", port); | 1073 | dump_parport_state("FIFO empty", port); |
| 1060 | 1074 | ||
| 1061 | /* Anyone else waiting for the port? */ | 1075 | /* Anyone else waiting for the port? */ |
| 1062 | if (port->waithead) { | 1076 | if (port->waithead) { |
| 1063 | printk (KERN_DEBUG "Somebody wants the port\n"); | 1077 | printk(KERN_DEBUG "Somebody wants the port\n"); |
| 1064 | break; | 1078 | break; |
| 1065 | } | 1079 | } |
| 1066 | 1080 | ||
| 1067 | /* Clear serviceIntr */ | 1081 | /* Clear serviceIntr */ |
| 1068 | ECR_WRITE (port, ecrval & ~(1<<2)); | 1082 | ECR_WRITE(port, ecrval & ~(1<<2)); |
| 1069 | false_alarm: | 1083 | false_alarm: |
| 1070 | dump_parport_state ("waiting", port); | 1084 | dump_parport_state("waiting", port); |
| 1071 | ret = parport_wait_event (port, HZ); | 1085 | ret = parport_wait_event(port, HZ); |
| 1072 | DPRINTK (KERN_DEBUG "parport_wait_event returned %d\n", ret); | 1086 | DPRINTK(KERN_DEBUG "parport_wait_event returned %d\n", |
| 1087 | ret); | ||
| 1073 | if (ret < 0) | 1088 | if (ret < 0) |
| 1074 | break; | 1089 | break; |
| 1075 | ret = 0; | 1090 | ret = 0; |
| 1076 | if (!time_before (jiffies, expire)) { | 1091 | if (!time_before(jiffies, expire)) { |
| 1077 | /* Timed out. */ | 1092 | /* Timed out. */ |
| 1078 | dump_parport_state ("timeout", port); | 1093 | dump_parport_state("timeout", port); |
| 1079 | printk (KERN_DEBUG "PIO read timed out\n"); | 1094 | printk(KERN_DEBUG "PIO read timed out\n"); |
| 1080 | break; | 1095 | break; |
| 1081 | } | 1096 | } |
| 1082 | ecrval = inb (ECONTROL (port)); | 1097 | ecrval = inb(ECONTROL(port)); |
| 1083 | if (!(ecrval & (1<<2))) { | 1098 | if (!(ecrval & (1<<2))) { |
| 1084 | if (need_resched() && | 1099 | if (need_resched() && |
| 1085 | time_before (jiffies, expire)) { | 1100 | time_before(jiffies, expire)) { |
| 1086 | schedule (); | 1101 | schedule(); |
| 1087 | } | 1102 | } |
| 1088 | goto false_alarm; | 1103 | goto false_alarm; |
| 1089 | } | 1104 | } |
| 1090 | 1105 | ||
| 1091 | /* Depending on how the FIFO threshold was | 1106 | /* Depending on how the FIFO threshold was |
| 1092 | * set, how long interrupt service took, and | 1107 | * set, how long interrupt service took, and |
| 1093 | * how fast the peripheral is, we might be | 1108 | * how fast the peripheral is, we might be |
| 1094 | * lucky and have a just filled FIFO. */ | 1109 | * lucky and have a just filled FIFO. */ |
| 1095 | continue; | 1110 | continue; |
| 1096 | } | 1111 | } |
| 1097 | 1112 | ||
| 1098 | if (ecrval & 0x02) { | 1113 | if (ecrval & 0x02) { |
| 1099 | /* FIFO is full. */ | 1114 | /* FIFO is full. */ |
| 1100 | dump_parport_state ("FIFO full", port); | 1115 | dump_parport_state("FIFO full", port); |
| 1101 | insb (fifo, bufp, fifo_depth); | 1116 | insb(fifo, bufp, fifo_depth); |
| 1102 | bufp += fifo_depth; | 1117 | bufp += fifo_depth; |
| 1103 | left -= fifo_depth; | 1118 | left -= fifo_depth; |
| 1104 | continue; | 1119 | continue; |
| 1105 | } | 1120 | } |
| 1106 | 1121 | ||
| 1107 | DPRINTK (KERN_DEBUG "*** ecp_read_block_pio: reading one byte from the FIFO\n"); | 1122 | DPRINTK(KERN_DEBUG |
| 1123 | "*** ecp_read_block_pio: reading one byte from the FIFO\n"); | ||
| 1108 | 1124 | ||
| 1109 | /* FIFO not filled. We will cycle this loop for a while | 1125 | /* FIFO not filled. We will cycle this loop for a while |
| 1110 | * and either the peripheral will fill it faster, | 1126 | * and either the peripheral will fill it faster, |
| 1111 | * tripping a fast empty with insb, or we empty it. */ | 1127 | * tripping a fast empty with insb, or we empty it. */ |
| 1112 | *bufp++ = inb (fifo); | 1128 | *bufp++ = inb(fifo); |
| 1113 | left--; | 1129 | left--; |
| 1114 | } | 1130 | } |
| 1115 | 1131 | ||
| 1116 | /* scoop up anything left in the FIFO */ | 1132 | /* scoop up anything left in the FIFO */ |
| 1117 | while (left && !(inb (ECONTROL (port) & 0x01))) { | 1133 | while (left && !(inb(ECONTROL(port) & 0x01))) { |
| 1118 | *bufp++ = inb (fifo); | 1134 | *bufp++ = inb(fifo); |
| 1119 | left--; | 1135 | left--; |
| 1120 | } | 1136 | } |
| 1121 | 1137 | ||
| 1122 | port->ieee1284.phase = IEEE1284_PH_REV_IDLE; | 1138 | port->ieee1284.phase = IEEE1284_PH_REV_IDLE; |
| 1123 | dump_parport_state ("rev idle2", port); | 1139 | dump_parport_state("rev idle2", port); |
| 1124 | 1140 | ||
| 1125 | out_no_data: | 1141 | out_no_data: |
| 1126 | 1142 | ||
| 1127 | /* Go to forward idle mode to shut the peripheral up (event 47). */ | 1143 | /* Go to forward idle mode to shut the peripheral up (event 47). */ |
| 1128 | parport_frob_control (port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); | 1144 | parport_frob_control(port, PARPORT_CONTROL_INIT, PARPORT_CONTROL_INIT); |
| 1129 | 1145 | ||
| 1130 | /* event 49: PError goes high */ | 1146 | /* event 49: PError goes high */ |
| 1131 | r = parport_wait_peripheral (port, | 1147 | r = parport_wait_peripheral(port, |
| 1132 | PARPORT_STATUS_PAPEROUT, | 1148 | PARPORT_STATUS_PAPEROUT, |
| 1133 | PARPORT_STATUS_PAPEROUT); | 1149 | PARPORT_STATUS_PAPEROUT); |
| 1134 | if (r) { | 1150 | if (r) { |
| 1135 | printk (KERN_DEBUG | 1151 | printk(KERN_DEBUG |
| 1136 | "%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n", | 1152 | "%s: PE timeout FWDIDLE (%d) in ecp_read_block_pio\n", |
| 1137 | port->name, r); | 1153 | port->name, r); |
| 1138 | } | 1154 | } |
| @@ -1141,14 +1157,14 @@ out_no_data: | |||
| 1141 | 1157 | ||
| 1142 | /* Finish up. */ | 1158 | /* Finish up. */ |
| 1143 | { | 1159 | { |
| 1144 | int lost = get_fifo_residue (port); | 1160 | int lost = get_fifo_residue(port); |
| 1145 | if (lost) | 1161 | if (lost) |
| 1146 | /* Shouldn't happen with compliant peripherals. */ | 1162 | /* Shouldn't happen with compliant peripherals. */ |
| 1147 | printk (KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", | 1163 | printk(KERN_DEBUG "%s: DATA LOSS (%d bytes)!\n", |
| 1148 | port->name, lost); | 1164 | port->name, lost); |
| 1149 | } | 1165 | } |
| 1150 | 1166 | ||
| 1151 | dump_parport_state ("fwd idle", port); | 1167 | dump_parport_state("fwd idle", port); |
| 1152 | return length - left; | 1168 | return length - left; |
| 1153 | } | 1169 | } |
| 1154 | #endif /* 0 */ | 1170 | #endif /* 0 */ |
| @@ -1164,8 +1180,7 @@ dump_parport_state ("fwd idle", port); | |||
| 1164 | 1180 | ||
| 1165 | /* GCC is not inlining extern inline function later overwriten to non-inline, | 1181 | /* GCC is not inlining extern inline function later overwriten to non-inline, |
| 1166 | so we use outlined_ variants here. */ | 1182 | so we use outlined_ variants here. */ |
| 1167 | static const struct parport_operations parport_pc_ops = | 1183 | static const struct parport_operations parport_pc_ops = { |
| 1168 | { | ||
| 1169 | .write_data = parport_pc_write_data, | 1184 | .write_data = parport_pc_write_data, |
| 1170 | .read_data = parport_pc_read_data, | 1185 | .read_data = parport_pc_read_data, |
| 1171 | 1186 | ||
| @@ -1202,88 +1217,107 @@ static const struct parport_operations parport_pc_ops = | |||
| 1202 | }; | 1217 | }; |
| 1203 | 1218 | ||
| 1204 | #ifdef CONFIG_PARPORT_PC_SUPERIO | 1219 | #ifdef CONFIG_PARPORT_PC_SUPERIO |
| 1220 | |||
| 1221 | static struct superio_struct *find_free_superio(void) | ||
| 1222 | { | ||
| 1223 | int i; | ||
| 1224 | for (i = 0; i < NR_SUPERIOS; i++) | ||
| 1225 | if (superios[i].io == 0) | ||
| 1226 | return &superios[i]; | ||
| 1227 | return NULL; | ||
| 1228 | } | ||
| 1229 | |||
| 1230 | |||
| 1205 | /* Super-IO chipset detection, Winbond, SMSC */ | 1231 | /* Super-IO chipset detection, Winbond, SMSC */ |
| 1206 | static void __devinit show_parconfig_smsc37c669(int io, int key) | 1232 | static void __devinit show_parconfig_smsc37c669(int io, int key) |
| 1207 | { | 1233 | { |
| 1208 | int cr1,cr4,cra,cr23,cr26,cr27,i=0; | 1234 | int cr1, cr4, cra, cr23, cr26, cr27; |
| 1209 | static const char *const modes[]={ | 1235 | struct superio_struct *s; |
| 1236 | |||
| 1237 | static const char *const modes[] = { | ||
| 1210 | "SPP and Bidirectional (PS/2)", | 1238 | "SPP and Bidirectional (PS/2)", |
| 1211 | "EPP and SPP", | 1239 | "EPP and SPP", |
| 1212 | "ECP", | 1240 | "ECP", |
| 1213 | "ECP and EPP" }; | 1241 | "ECP and EPP" }; |
| 1214 | 1242 | ||
| 1215 | outb(key,io); | 1243 | outb(key, io); |
| 1216 | outb(key,io); | 1244 | outb(key, io); |
| 1217 | outb(1,io); | 1245 | outb(1, io); |
| 1218 | cr1=inb(io+1); | 1246 | cr1 = inb(io + 1); |
| 1219 | outb(4,io); | 1247 | outb(4, io); |
| 1220 | cr4=inb(io+1); | 1248 | cr4 = inb(io + 1); |
| 1221 | outb(0x0a,io); | 1249 | outb(0x0a, io); |
| 1222 | cra=inb(io+1); | 1250 | cra = inb(io + 1); |
| 1223 | outb(0x23,io); | 1251 | outb(0x23, io); |
| 1224 | cr23=inb(io+1); | 1252 | cr23 = inb(io + 1); |
| 1225 | outb(0x26,io); | 1253 | outb(0x26, io); |
| 1226 | cr26=inb(io+1); | 1254 | cr26 = inb(io + 1); |
| 1227 | outb(0x27,io); | 1255 | outb(0x27, io); |
| 1228 | cr27=inb(io+1); | 1256 | cr27 = inb(io + 1); |
| 1229 | outb(0xaa,io); | 1257 | outb(0xaa, io); |
| 1230 | 1258 | ||
| 1231 | if (verbose_probing) { | 1259 | if (verbose_probing) { |
| 1232 | printk (KERN_INFO "SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, " | 1260 | printk(KERN_INFO |
| 1261 | "SMSC 37c669 LPT Config: cr_1=0x%02x, 4=0x%02x, " | ||
| 1233 | "A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n", | 1262 | "A=0x%2x, 23=0x%02x, 26=0x%02x, 27=0x%02x\n", |
| 1234 | cr1,cr4,cra,cr23,cr26,cr27); | 1263 | cr1, cr4, cra, cr23, cr26, cr27); |
| 1235 | 1264 | ||
| 1236 | /* The documentation calls DMA and IRQ-Lines by letters, so | 1265 | /* The documentation calls DMA and IRQ-Lines by letters, so |
| 1237 | the board maker can/will wire them | 1266 | the board maker can/will wire them |
| 1238 | appropriately/randomly... G=reserved H=IDE-irq, */ | 1267 | appropriately/randomly... G=reserved H=IDE-irq, */ |
| 1239 | printk (KERN_INFO "SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, " | 1268 | printk(KERN_INFO |
| 1240 | "fifo threshold=%d\n", cr23*4, | 1269 | "SMSC LPT Config: io=0x%04x, irq=%c, dma=%c, fifo threshold=%d\n", |
| 1241 | (cr27 &0x0f) ? 'A'-1+(cr27 &0x0f): '-', | 1270 | cr23 * 4, |
| 1242 | (cr26 &0x0f) ? 'A'-1+(cr26 &0x0f): '-', cra & 0x0f); | 1271 | (cr27 & 0x0f) ? 'A' - 1 + (cr27 & 0x0f) : '-', |
| 1272 | (cr26 & 0x0f) ? 'A' - 1 + (cr26 & 0x0f) : '-', | ||
| 1273 | cra & 0x0f); | ||
| 1243 | printk(KERN_INFO "SMSC LPT Config: enabled=%s power=%s\n", | 1274 | printk(KERN_INFO "SMSC LPT Config: enabled=%s power=%s\n", |
| 1244 | (cr23*4 >=0x100) ?"yes":"no", (cr1 & 4) ? "yes" : "no"); | 1275 | (cr23 * 4 >= 0x100) ? "yes" : "no", |
| 1245 | printk(KERN_INFO "SMSC LPT Config: Port mode=%s, EPP version =%s\n", | 1276 | (cr1 & 4) ? "yes" : "no"); |
| 1246 | (cr1 & 0x08 ) ? "Standard mode only (SPP)" : modes[cr4 & 0x03], | 1277 | printk(KERN_INFO |
| 1247 | (cr4 & 0x40) ? "1.7" : "1.9"); | 1278 | "SMSC LPT Config: Port mode=%s, EPP version =%s\n", |
| 1279 | (cr1 & 0x08) ? "Standard mode only (SPP)" | ||
| 1280 | : modes[cr4 & 0x03], | ||
| 1281 | (cr4 & 0x40) ? "1.7" : "1.9"); | ||
| 1248 | } | 1282 | } |
| 1249 | 1283 | ||
| 1250 | /* Heuristics ! BIOS setup for this mainboard device limits | 1284 | /* Heuristics ! BIOS setup for this mainboard device limits |
| 1251 | the choices to standard settings, i.e. io-address and IRQ | 1285 | the choices to standard settings, i.e. io-address and IRQ |
| 1252 | are related, however DMA can be 1 or 3, assume DMA_A=DMA1, | 1286 | are related, however DMA can be 1 or 3, assume DMA_A=DMA1, |
| 1253 | DMA_C=DMA3 (this is true e.g. for TYAN 1564D Tomcat IV) */ | 1287 | DMA_C=DMA3 (this is true e.g. for TYAN 1564D Tomcat IV) */ |
| 1254 | if(cr23*4 >=0x100) { /* if active */ | 1288 | if (cr23 * 4 >= 0x100) { /* if active */ |
| 1255 | while((superios[i].io!= 0) && (i<NR_SUPERIOS)) | 1289 | s = find_free_superio(); |
| 1256 | i++; | 1290 | if (s == NULL) |
| 1257 | if(i==NR_SUPERIOS) | ||
| 1258 | printk(KERN_INFO "Super-IO: too many chips!\n"); | 1291 | printk(KERN_INFO "Super-IO: too many chips!\n"); |
| 1259 | else { | 1292 | else { |
| 1260 | int d; | 1293 | int d; |
| 1261 | switch (cr23*4) { | 1294 | switch (cr23 * 4) { |
| 1262 | case 0x3bc: | 1295 | case 0x3bc: |
| 1263 | superios[i].io = 0x3bc; | 1296 | s->io = 0x3bc; |
| 1264 | superios[i].irq = 7; | 1297 | s->irq = 7; |
| 1265 | break; | 1298 | break; |
| 1266 | case 0x378: | 1299 | case 0x378: |
| 1267 | superios[i].io = 0x378; | 1300 | s->io = 0x378; |
| 1268 | superios[i].irq = 7; | 1301 | s->irq = 7; |
| 1269 | break; | 1302 | break; |
| 1270 | case 0x278: | 1303 | case 0x278: |
| 1271 | superios[i].io = 0x278; | 1304 | s->io = 0x278; |
| 1272 | superios[i].irq = 5; | 1305 | s->irq = 5; |
| 1273 | } | 1306 | } |
| 1274 | d=(cr26 &0x0f); | 1307 | d = (cr26 & 0x0f); |
| 1275 | if((d==1) || (d==3)) | 1308 | if (d == 1 || d == 3) |
| 1276 | superios[i].dma= d; | 1309 | s->dma = d; |
| 1277 | else | 1310 | else |
| 1278 | superios[i].dma= PARPORT_DMA_NONE; | 1311 | s->dma = PARPORT_DMA_NONE; |
| 1279 | } | 1312 | } |
| 1280 | } | 1313 | } |
| 1281 | } | 1314 | } |
| 1282 | 1315 | ||
| 1283 | 1316 | ||
| 1284 | static void __devinit show_parconfig_winbond(int io, int key) | 1317 | static void __devinit show_parconfig_winbond(int io, int key) |
| 1285 | { | 1318 | { |
| 1286 | int cr30,cr60,cr61,cr70,cr74,crf0,i=0; | 1319 | int cr30, cr60, cr61, cr70, cr74, crf0; |
| 1320 | struct superio_struct *s; | ||
| 1287 | static const char *const modes[] = { | 1321 | static const char *const modes[] = { |
| 1288 | "Standard (SPP) and Bidirectional(PS/2)", /* 0 */ | 1322 | "Standard (SPP) and Bidirectional(PS/2)", /* 0 */ |
| 1289 | "EPP-1.9 and SPP", | 1323 | "EPP-1.9 and SPP", |
| @@ -1296,110 +1330,134 @@ static void __devinit show_parconfig_winbond(int io, int key) | |||
| 1296 | static char *const irqtypes[] = { | 1330 | static char *const irqtypes[] = { |
| 1297 | "pulsed low, high-Z", | 1331 | "pulsed low, high-Z", |
| 1298 | "follows nACK" }; | 1332 | "follows nACK" }; |
| 1299 | 1333 | ||
| 1300 | /* The registers are called compatible-PnP because the | 1334 | /* The registers are called compatible-PnP because the |
| 1301 | register layout is modelled after ISA-PnP, the access | 1335 | register layout is modelled after ISA-PnP, the access |
| 1302 | method is just another ... */ | 1336 | method is just another ... */ |
| 1303 | outb(key,io); | 1337 | outb(key, io); |
| 1304 | outb(key,io); | 1338 | outb(key, io); |
| 1305 | outb(0x07,io); /* Register 7: Select Logical Device */ | 1339 | outb(0x07, io); /* Register 7: Select Logical Device */ |
| 1306 | outb(0x01,io+1); /* LD1 is Parallel Port */ | 1340 | outb(0x01, io + 1); /* LD1 is Parallel Port */ |
| 1307 | outb(0x30,io); | 1341 | outb(0x30, io); |
| 1308 | cr30=inb(io+1); | 1342 | cr30 = inb(io + 1); |
| 1309 | outb(0x60,io); | 1343 | outb(0x60, io); |
| 1310 | cr60=inb(io+1); | 1344 | cr60 = inb(io + 1); |
| 1311 | outb(0x61,io); | 1345 | outb(0x61, io); |
| 1312 | cr61=inb(io+1); | 1346 | cr61 = inb(io + 1); |
| 1313 | outb(0x70,io); | 1347 | outb(0x70, io); |
| 1314 | cr70=inb(io+1); | 1348 | cr70 = inb(io + 1); |
| 1315 | outb(0x74,io); | 1349 | outb(0x74, io); |
| 1316 | cr74=inb(io+1); | 1350 | cr74 = inb(io + 1); |
| 1317 | outb(0xf0,io); | 1351 | outb(0xf0, io); |
| 1318 | crf0=inb(io+1); | 1352 | crf0 = inb(io + 1); |
| 1319 | outb(0xaa,io); | 1353 | outb(0xaa, io); |
| 1320 | 1354 | ||
| 1321 | if (verbose_probing) { | 1355 | if (verbose_probing) { |
| 1322 | printk(KERN_INFO "Winbond LPT Config: cr_30=%02x 60,61=%02x%02x " | 1356 | printk(KERN_INFO |
| 1323 | "70=%02x 74=%02x, f0=%02x\n", cr30,cr60,cr61,cr70,cr74,crf0); | 1357 | "Winbond LPT Config: cr_30=%02x 60,61=%02x%02x 70=%02x 74=%02x, f0=%02x\n", |
| 1324 | printk(KERN_INFO "Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", | 1358 | cr30, cr60, cr61, cr70, cr74, crf0); |
| 1325 | (cr30 & 0x01) ? "yes":"no", cr60,cr61,cr70&0x0f ); | 1359 | printk(KERN_INFO "Winbond LPT Config: active=%s, io=0x%02x%02x irq=%d, ", |
| 1360 | (cr30 & 0x01) ? "yes" : "no", cr60, cr61, cr70 & 0x0f); | ||
| 1326 | if ((cr74 & 0x07) > 3) | 1361 | if ((cr74 & 0x07) > 3) |
| 1327 | printk("dma=none\n"); | 1362 | printk("dma=none\n"); |
| 1328 | else | 1363 | else |
| 1329 | printk("dma=%d\n",cr74 & 0x07); | 1364 | printk("dma=%d\n", cr74 & 0x07); |
| 1330 | printk(KERN_INFO "Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n", | 1365 | printk(KERN_INFO |
| 1331 | irqtypes[crf0>>7], (crf0>>3)&0x0f); | 1366 | "Winbond LPT Config: irqtype=%s, ECP fifo threshold=%d\n", |
| 1332 | printk(KERN_INFO "Winbond LPT Config: Port mode=%s\n", modes[crf0 & 0x07]); | 1367 | irqtypes[crf0>>7], (crf0>>3)&0x0f); |
| 1368 | printk(KERN_INFO "Winbond LPT Config: Port mode=%s\n", | ||
| 1369 | modes[crf0 & 0x07]); | ||
| 1333 | } | 1370 | } |
| 1334 | 1371 | ||
| 1335 | if(cr30 & 0x01) { /* the settings can be interrogated later ... */ | 1372 | if (cr30 & 0x01) { /* the settings can be interrogated later ... */ |
| 1336 | while((superios[i].io!= 0) && (i<NR_SUPERIOS)) | 1373 | s = find_free_superio(); |
| 1337 | i++; | 1374 | if (s == NULL) |
| 1338 | if(i==NR_SUPERIOS) | ||
| 1339 | printk(KERN_INFO "Super-IO: too many chips!\n"); | 1375 | printk(KERN_INFO "Super-IO: too many chips!\n"); |
| 1340 | else { | 1376 | else { |
| 1341 | superios[i].io = (cr60<<8)|cr61; | 1377 | s->io = (cr60 << 8) | cr61; |
| 1342 | superios[i].irq = cr70&0x0f; | 1378 | s->irq = cr70 & 0x0f; |
| 1343 | superios[i].dma = (((cr74 & 0x07) > 3) ? | 1379 | s->dma = (((cr74 & 0x07) > 3) ? |
| 1344 | PARPORT_DMA_NONE : (cr74 & 0x07)); | 1380 | PARPORT_DMA_NONE : (cr74 & 0x07)); |
| 1345 | } | 1381 | } |
| 1346 | } | 1382 | } |
| 1347 | } | 1383 | } |
| 1348 | 1384 | ||
| 1349 | static void __devinit decode_winbond(int efer, int key, int devid, int devrev, int oldid) | 1385 | static void __devinit decode_winbond(int efer, int key, int devid, |
| 1386 | int devrev, int oldid) | ||
| 1350 | { | 1387 | { |
| 1351 | const char *type = "unknown"; | 1388 | const char *type = "unknown"; |
| 1352 | int id,progif=2; | 1389 | int id, progif = 2; |
| 1353 | 1390 | ||
| 1354 | if (devid == devrev) | 1391 | if (devid == devrev) |
| 1355 | /* simple heuristics, we happened to read some | 1392 | /* simple heuristics, we happened to read some |
| 1356 | non-winbond register */ | 1393 | non-winbond register */ |
| 1357 | return; | 1394 | return; |
| 1358 | 1395 | ||
| 1359 | id=(devid<<8) | devrev; | 1396 | id = (devid << 8) | devrev; |
| 1360 | 1397 | ||
| 1361 | /* Values are from public data sheets pdf files, I can just | 1398 | /* Values are from public data sheets pdf files, I can just |
| 1362 | confirm 83977TF is correct :-) */ | 1399 | confirm 83977TF is correct :-) */ |
| 1363 | if (id == 0x9771) type="83977F/AF"; | 1400 | if (id == 0x9771) |
| 1364 | else if (id == 0x9773) type="83977TF / SMSC 97w33x/97w34x"; | 1401 | type = "83977F/AF"; |
| 1365 | else if (id == 0x9774) type="83977ATF"; | 1402 | else if (id == 0x9773) |
| 1366 | else if ((id & ~0x0f) == 0x5270) type="83977CTF / SMSC 97w36x"; | 1403 | type = "83977TF / SMSC 97w33x/97w34x"; |
| 1367 | else if ((id & ~0x0f) == 0x52f0) type="83977EF / SMSC 97w35x"; | 1404 | else if (id == 0x9774) |
| 1368 | else if ((id & ~0x0f) == 0x5210) type="83627"; | 1405 | type = "83977ATF"; |
| 1369 | else if ((id & ~0x0f) == 0x6010) type="83697HF"; | 1406 | else if ((id & ~0x0f) == 0x5270) |
| 1370 | else if ((oldid &0x0f ) == 0x0a) { type="83877F"; progif=1;} | 1407 | type = "83977CTF / SMSC 97w36x"; |
| 1371 | else if ((oldid &0x0f ) == 0x0b) { type="83877AF"; progif=1;} | 1408 | else if ((id & ~0x0f) == 0x52f0) |
| 1372 | else if ((oldid &0x0f ) == 0x0c) { type="83877TF"; progif=1;} | 1409 | type = "83977EF / SMSC 97w35x"; |
| 1373 | else if ((oldid &0x0f ) == 0x0d) { type="83877ATF"; progif=1;} | 1410 | else if ((id & ~0x0f) == 0x5210) |
| 1374 | else progif=0; | 1411 | type = "83627"; |
| 1412 | else if ((id & ~0x0f) == 0x6010) | ||
| 1413 | type = "83697HF"; | ||
| 1414 | else if ((oldid & 0x0f) == 0x0a) { | ||
| 1415 | type = "83877F"; | ||
| 1416 | progif = 1; | ||
| 1417 | } else if ((oldid & 0x0f) == 0x0b) { | ||
| 1418 | type = "83877AF"; | ||
| 1419 | progif = 1; | ||
| 1420 | } else if ((oldid & 0x0f) == 0x0c) { | ||
| 1421 | type = "83877TF"; | ||
| 1422 | progif = 1; | ||
| 1423 | } else if ((oldid & 0x0f) == 0x0d) { | ||
| 1424 | type = "83877ATF"; | ||
| 1425 | progif = 1; | ||
| 1426 | } else | ||
| 1427 | progif = 0; | ||
| 1375 | 1428 | ||
| 1376 | if (verbose_probing) | 1429 | if (verbose_probing) |
| 1377 | printk(KERN_INFO "Winbond chip at EFER=0x%x key=0x%02x " | 1430 | printk(KERN_INFO "Winbond chip at EFER=0x%x key=0x%02x " |
| 1378 | "devid=%02x devrev=%02x oldid=%02x type=%s\n", | 1431 | "devid=%02x devrev=%02x oldid=%02x type=%s\n", |
| 1379 | efer, key, devid, devrev, oldid, type); | 1432 | efer, key, devid, devrev, oldid, type); |
| 1380 | 1433 | ||
| 1381 | if (progif == 2) | 1434 | if (progif == 2) |
| 1382 | show_parconfig_winbond(efer,key); | 1435 | show_parconfig_winbond(efer, key); |
| 1383 | } | 1436 | } |
| 1384 | 1437 | ||
| 1385 | static void __devinit decode_smsc(int efer, int key, int devid, int devrev) | 1438 | static void __devinit decode_smsc(int efer, int key, int devid, int devrev) |
| 1386 | { | 1439 | { |
| 1387 | const char *type = "unknown"; | 1440 | const char *type = "unknown"; |
| 1388 | void (*func)(int io, int key); | 1441 | void (*func)(int io, int key); |
| 1389 | int id; | 1442 | int id; |
| 1390 | 1443 | ||
| 1391 | if (devid == devrev) | 1444 | if (devid == devrev) |
| 1392 | /* simple heuristics, we happened to read some | 1445 | /* simple heuristics, we happened to read some |
| 1393 | non-smsc register */ | 1446 | non-smsc register */ |
| 1394 | return; | 1447 | return; |
| 1395 | 1448 | ||
| 1396 | func=NULL; | 1449 | func = NULL; |
| 1397 | id=(devid<<8) | devrev; | 1450 | id = (devid << 8) | devrev; |
| 1398 | 1451 | ||
| 1399 | if (id==0x0302) {type="37c669"; func=show_parconfig_smsc37c669;} | 1452 | if (id == 0x0302) { |
| 1400 | else if (id==0x6582) type="37c665IR"; | 1453 | type = "37c669"; |
| 1401 | else if (devid==0x65) type="37c665GT"; | 1454 | func = show_parconfig_smsc37c669; |
| 1402 | else if (devid==0x66) type="37c666GT"; | 1455 | } else if (id == 0x6582) |
| 1456 | type = "37c665IR"; | ||
| 1457 | else if (devid == 0x65) | ||
| 1458 | type = "37c665GT"; | ||
| 1459 | else if (devid == 0x66) | ||
| 1460 | type = "37c666GT"; | ||
| 1403 | 1461 | ||
| 1404 | if (verbose_probing) | 1462 | if (verbose_probing) |
| 1405 | printk(KERN_INFO "SMSC chip at EFER=0x%x " | 1463 | printk(KERN_INFO "SMSC chip at EFER=0x%x " |
| @@ -1407,138 +1465,138 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) | |||
| 1407 | efer, key, devid, devrev, type); | 1465 | efer, key, devid, devrev, type); |
| 1408 | 1466 | ||
| 1409 | if (func) | 1467 | if (func) |
| 1410 | func(efer,key); | 1468 | func(efer, key); |
| 1411 | } | 1469 | } |
| 1412 | 1470 | ||
| 1413 | 1471 | ||
| 1414 | static void __devinit winbond_check(int io, int key) | 1472 | static void __devinit winbond_check(int io, int key) |
| 1415 | { | 1473 | { |
| 1416 | int devid,devrev,oldid,x_devid,x_devrev,x_oldid; | 1474 | int devid, devrev, oldid, x_devid, x_devrev, x_oldid; |
| 1417 | 1475 | ||
| 1418 | if (!request_region(io, 3, __func__)) | 1476 | if (!request_region(io, 3, __func__)) |
| 1419 | return; | 1477 | return; |
| 1420 | 1478 | ||
| 1421 | /* First probe without key */ | 1479 | /* First probe without key */ |
| 1422 | outb(0x20,io); | 1480 | outb(0x20, io); |
| 1423 | x_devid=inb(io+1); | 1481 | x_devid = inb(io + 1); |
| 1424 | outb(0x21,io); | 1482 | outb(0x21, io); |
| 1425 | x_devrev=inb(io+1); | 1483 | x_devrev = inb(io + 1); |
| 1426 | outb(0x09,io); | 1484 | outb(0x09, io); |
| 1427 | x_oldid=inb(io+1); | 1485 | x_oldid = inb(io + 1); |
| 1428 | 1486 | ||
| 1429 | outb(key,io); | 1487 | outb(key, io); |
| 1430 | outb(key,io); /* Write Magic Sequence to EFER, extended | 1488 | outb(key, io); /* Write Magic Sequence to EFER, extended |
| 1431 | funtion enable register */ | 1489 | funtion enable register */ |
| 1432 | outb(0x20,io); /* Write EFIR, extended function index register */ | 1490 | outb(0x20, io); /* Write EFIR, extended function index register */ |
| 1433 | devid=inb(io+1); /* Read EFDR, extended function data register */ | 1491 | devid = inb(io + 1); /* Read EFDR, extended function data register */ |
| 1434 | outb(0x21,io); | 1492 | outb(0x21, io); |
| 1435 | devrev=inb(io+1); | 1493 | devrev = inb(io + 1); |
| 1436 | outb(0x09,io); | 1494 | outb(0x09, io); |
| 1437 | oldid=inb(io+1); | 1495 | oldid = inb(io + 1); |
| 1438 | outb(0xaa,io); /* Magic Seal */ | 1496 | outb(0xaa, io); /* Magic Seal */ |
| 1439 | 1497 | ||
| 1440 | if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) | 1498 | if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) |
| 1441 | goto out; /* protection against false positives */ | 1499 | goto out; /* protection against false positives */ |
| 1442 | 1500 | ||
| 1443 | decode_winbond(io,key,devid,devrev,oldid); | 1501 | decode_winbond(io, key, devid, devrev, oldid); |
| 1444 | out: | 1502 | out: |
| 1445 | release_region(io, 3); | 1503 | release_region(io, 3); |
| 1446 | } | 1504 | } |
| 1447 | 1505 | ||
| 1448 | static void __devinit winbond_check2(int io,int key) | 1506 | static void __devinit winbond_check2(int io, int key) |
| 1449 | { | 1507 | { |
| 1450 | int devid,devrev,oldid,x_devid,x_devrev,x_oldid; | 1508 | int devid, devrev, oldid, x_devid, x_devrev, x_oldid; |
| 1451 | 1509 | ||
| 1452 | if (!request_region(io, 3, __func__)) | 1510 | if (!request_region(io, 3, __func__)) |
| 1453 | return; | 1511 | return; |
| 1454 | 1512 | ||
| 1455 | /* First probe without the key */ | 1513 | /* First probe without the key */ |
| 1456 | outb(0x20,io+2); | 1514 | outb(0x20, io + 2); |
| 1457 | x_devid=inb(io+2); | 1515 | x_devid = inb(io + 2); |
| 1458 | outb(0x21,io+1); | 1516 | outb(0x21, io + 1); |
| 1459 | x_devrev=inb(io+2); | 1517 | x_devrev = inb(io + 2); |
| 1460 | outb(0x09,io+1); | 1518 | outb(0x09, io + 1); |
| 1461 | x_oldid=inb(io+2); | 1519 | x_oldid = inb(io + 2); |
| 1462 | 1520 | ||
| 1463 | outb(key,io); /* Write Magic Byte to EFER, extended | 1521 | outb(key, io); /* Write Magic Byte to EFER, extended |
| 1464 | funtion enable register */ | 1522 | funtion enable register */ |
| 1465 | outb(0x20,io+2); /* Write EFIR, extended function index register */ | 1523 | outb(0x20, io + 2); /* Write EFIR, extended function index register */ |
| 1466 | devid=inb(io+2); /* Read EFDR, extended function data register */ | 1524 | devid = inb(io + 2); /* Read EFDR, extended function data register */ |
| 1467 | outb(0x21,io+1); | 1525 | outb(0x21, io + 1); |
| 1468 | devrev=inb(io+2); | 1526 | devrev = inb(io + 2); |
| 1469 | outb(0x09,io+1); | 1527 | outb(0x09, io + 1); |
| 1470 | oldid=inb(io+2); | 1528 | oldid = inb(io + 2); |
| 1471 | outb(0xaa,io); /* Magic Seal */ | 1529 | outb(0xaa, io); /* Magic Seal */ |
| 1472 | 1530 | ||
| 1473 | if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) | 1531 | if (x_devid == devid && x_devrev == devrev && x_oldid == oldid) |
| 1474 | goto out; /* protection against false positives */ | 1532 | goto out; /* protection against false positives */ |
| 1475 | 1533 | ||
| 1476 | decode_winbond(io,key,devid,devrev,oldid); | 1534 | decode_winbond(io, key, devid, devrev, oldid); |
| 1477 | out: | 1535 | out: |
| 1478 | release_region(io, 3); | 1536 | release_region(io, 3); |
| 1479 | } | 1537 | } |
| 1480 | 1538 | ||
| 1481 | static void __devinit smsc_check(int io, int key) | 1539 | static void __devinit smsc_check(int io, int key) |
| 1482 | { | 1540 | { |
| 1483 | int id,rev,oldid,oldrev,x_id,x_rev,x_oldid,x_oldrev; | 1541 | int id, rev, oldid, oldrev, x_id, x_rev, x_oldid, x_oldrev; |
| 1484 | 1542 | ||
| 1485 | if (!request_region(io, 3, __func__)) | 1543 | if (!request_region(io, 3, __func__)) |
| 1486 | return; | 1544 | return; |
| 1487 | 1545 | ||
| 1488 | /* First probe without the key */ | 1546 | /* First probe without the key */ |
| 1489 | outb(0x0d,io); | 1547 | outb(0x0d, io); |
| 1490 | x_oldid=inb(io+1); | 1548 | x_oldid = inb(io + 1); |
| 1491 | outb(0x0e,io); | 1549 | outb(0x0e, io); |
| 1492 | x_oldrev=inb(io+1); | 1550 | x_oldrev = inb(io + 1); |
| 1493 | outb(0x20,io); | 1551 | outb(0x20, io); |
| 1494 | x_id=inb(io+1); | 1552 | x_id = inb(io + 1); |
| 1495 | outb(0x21,io); | 1553 | outb(0x21, io); |
| 1496 | x_rev=inb(io+1); | 1554 | x_rev = inb(io + 1); |
| 1497 | 1555 | ||
| 1498 | outb(key,io); | 1556 | outb(key, io); |
| 1499 | outb(key,io); /* Write Magic Sequence to EFER, extended | 1557 | outb(key, io); /* Write Magic Sequence to EFER, extended |
| 1500 | funtion enable register */ | 1558 | funtion enable register */ |
| 1501 | outb(0x0d,io); /* Write EFIR, extended function index register */ | 1559 | outb(0x0d, io); /* Write EFIR, extended function index register */ |
| 1502 | oldid=inb(io+1); /* Read EFDR, extended function data register */ | 1560 | oldid = inb(io + 1); /* Read EFDR, extended function data register */ |
| 1503 | outb(0x0e,io); | 1561 | outb(0x0e, io); |
| 1504 | oldrev=inb(io+1); | 1562 | oldrev = inb(io + 1); |
| 1505 | outb(0x20,io); | 1563 | outb(0x20, io); |
| 1506 | id=inb(io+1); | 1564 | id = inb(io + 1); |
| 1507 | outb(0x21,io); | 1565 | outb(0x21, io); |
| 1508 | rev=inb(io+1); | 1566 | rev = inb(io + 1); |
| 1509 | outb(0xaa,io); /* Magic Seal */ | 1567 | outb(0xaa, io); /* Magic Seal */ |
| 1510 | 1568 | ||
| 1511 | if ((x_id == id) && (x_oldrev == oldrev) && | 1569 | if (x_id == id && x_oldrev == oldrev && |
| 1512 | (x_oldid == oldid) && (x_rev == rev)) | 1570 | x_oldid == oldid && x_rev == rev) |
| 1513 | goto out; /* protection against false positives */ | 1571 | goto out; /* protection against false positives */ |
| 1514 | 1572 | ||
| 1515 | decode_smsc(io,key,oldid,oldrev); | 1573 | decode_smsc(io, key, oldid, oldrev); |
| 1516 | out: | 1574 | out: |
| 1517 | release_region(io, 3); | 1575 | release_region(io, 3); |
| 1518 | } | 1576 | } |
| 1519 | 1577 | ||
| 1520 | 1578 | ||
| 1521 | static void __devinit detect_and_report_winbond (void) | 1579 | static void __devinit detect_and_report_winbond(void) |
| 1522 | { | 1580 | { |
| 1523 | if (verbose_probing) | 1581 | if (verbose_probing) |
| 1524 | printk(KERN_DEBUG "Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n"); | 1582 | printk(KERN_DEBUG "Winbond Super-IO detection, now testing ports 3F0,370,250,4E,2E ...\n"); |
| 1525 | winbond_check(0x3f0,0x87); | 1583 | winbond_check(0x3f0, 0x87); |
| 1526 | winbond_check(0x370,0x87); | 1584 | winbond_check(0x370, 0x87); |
| 1527 | winbond_check(0x2e ,0x87); | 1585 | winbond_check(0x2e , 0x87); |
| 1528 | winbond_check(0x4e ,0x87); | 1586 | winbond_check(0x4e , 0x87); |
| 1529 | winbond_check(0x3f0,0x86); | 1587 | winbond_check(0x3f0, 0x86); |
| 1530 | winbond_check2(0x250,0x88); | 1588 | winbond_check2(0x250, 0x88); |
| 1531 | winbond_check2(0x250,0x89); | 1589 | winbond_check2(0x250, 0x89); |
| 1532 | } | 1590 | } |
| 1533 | 1591 | ||
| 1534 | static void __devinit detect_and_report_smsc (void) | 1592 | static void __devinit detect_and_report_smsc(void) |
| 1535 | { | 1593 | { |
| 1536 | if (verbose_probing) | 1594 | if (verbose_probing) |
| 1537 | printk(KERN_DEBUG "SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n"); | 1595 | printk(KERN_DEBUG "SMSC Super-IO detection, now testing Ports 2F0, 370 ...\n"); |
| 1538 | smsc_check(0x3f0,0x55); | 1596 | smsc_check(0x3f0, 0x55); |
| 1539 | smsc_check(0x370,0x55); | 1597 | smsc_check(0x370, 0x55); |
| 1540 | smsc_check(0x3f0,0x44); | 1598 | smsc_check(0x3f0, 0x44); |
| 1541 | smsc_check(0x370,0x44); | 1599 | smsc_check(0x370, 0x44); |
| 1542 | } | 1600 | } |
| 1543 | 1601 | ||
| 1544 | static void __devinit detect_and_report_it87(void) | 1602 | static void __devinit detect_and_report_it87(void) |
| @@ -1573,34 +1631,39 @@ static void __devinit detect_and_report_it87(void) | |||
| 1573 | } | 1631 | } |
| 1574 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ | 1632 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ |
| 1575 | 1633 | ||
| 1576 | static int get_superio_dma (struct parport *p) | 1634 | static struct superio_struct *find_superio(struct parport *p) |
| 1577 | { | 1635 | { |
| 1578 | int i=0; | 1636 | int i; |
| 1579 | while( (superios[i].io != p->base) && (i<NR_SUPERIOS)) | 1637 | for (i = 0; i < NR_SUPERIOS; i++) |
| 1580 | i++; | 1638 | if (superios[i].io != p->base) |
| 1581 | if (i!=NR_SUPERIOS) | 1639 | return &superios[i]; |
| 1582 | return superios[i].dma; | 1640 | return NULL; |
| 1641 | } | ||
| 1642 | |||
| 1643 | static int get_superio_dma(struct parport *p) | ||
| 1644 | { | ||
| 1645 | struct superio_struct *s = find_superio(p); | ||
| 1646 | if (s) | ||
| 1647 | return s->dma; | ||
| 1583 | return PARPORT_DMA_NONE; | 1648 | return PARPORT_DMA_NONE; |
| 1584 | } | 1649 | } |
| 1585 | 1650 | ||
| 1586 | static int get_superio_irq (struct parport *p) | 1651 | static int get_superio_irq(struct parport *p) |
| 1587 | { | 1652 | { |
| 1588 | int i=0; | 1653 | struct superio_struct *s = find_superio(p); |
| 1589 | while( (superios[i].io != p->base) && (i<NR_SUPERIOS)) | 1654 | if (s) |
| 1590 | i++; | 1655 | return s->irq; |
| 1591 | if (i!=NR_SUPERIOS) | 1656 | return PARPORT_IRQ_NONE; |
| 1592 | return superios[i].irq; | ||
| 1593 | return PARPORT_IRQ_NONE; | ||
| 1594 | } | 1657 | } |
| 1595 | 1658 | ||
| 1596 | 1659 | ||
| 1597 | /* --- Mode detection ------------------------------------- */ | 1660 | /* --- Mode detection ------------------------------------- */ |
| 1598 | 1661 | ||
| 1599 | /* | 1662 | /* |
| 1600 | * Checks for port existence, all ports support SPP MODE | 1663 | * Checks for port existence, all ports support SPP MODE |
| 1601 | * Returns: | 1664 | * Returns: |
| 1602 | * 0 : No parallel port at this address | 1665 | * 0 : No parallel port at this address |
| 1603 | * PARPORT_MODE_PCSPP : SPP port detected | 1666 | * PARPORT_MODE_PCSPP : SPP port detected |
| 1604 | * (if the user specified an ioport himself, | 1667 | * (if the user specified an ioport himself, |
| 1605 | * this shall always be the case!) | 1668 | * this shall always be the case!) |
| 1606 | * | 1669 | * |
| @@ -1610,7 +1673,7 @@ static int parport_SPP_supported(struct parport *pb) | |||
| 1610 | unsigned char r, w; | 1673 | unsigned char r, w; |
| 1611 | 1674 | ||
| 1612 | /* | 1675 | /* |
| 1613 | * first clear an eventually pending EPP timeout | 1676 | * first clear an eventually pending EPP timeout |
| 1614 | * I (sailer@ife.ee.ethz.ch) have an SMSC chipset | 1677 | * I (sailer@ife.ee.ethz.ch) have an SMSC chipset |
| 1615 | * that does not even respond to SPP cycles if an EPP | 1678 | * that does not even respond to SPP cycles if an EPP |
| 1616 | * timeout is pending | 1679 | * timeout is pending |
| @@ -1619,19 +1682,19 @@ static int parport_SPP_supported(struct parport *pb) | |||
| 1619 | 1682 | ||
| 1620 | /* Do a simple read-write test to make sure the port exists. */ | 1683 | /* Do a simple read-write test to make sure the port exists. */ |
| 1621 | w = 0xc; | 1684 | w = 0xc; |
| 1622 | outb (w, CONTROL (pb)); | 1685 | outb(w, CONTROL(pb)); |
| 1623 | 1686 | ||
| 1624 | /* Is there a control register that we can read from? Some | 1687 | /* Is there a control register that we can read from? Some |
| 1625 | * ports don't allow reads, so read_control just returns a | 1688 | * ports don't allow reads, so read_control just returns a |
| 1626 | * software copy. Some ports _do_ allow reads, so bypass the | 1689 | * software copy. Some ports _do_ allow reads, so bypass the |
| 1627 | * software copy here. In addition, some bits aren't | 1690 | * software copy here. In addition, some bits aren't |
| 1628 | * writable. */ | 1691 | * writable. */ |
| 1629 | r = inb (CONTROL (pb)); | 1692 | r = inb(CONTROL(pb)); |
| 1630 | if ((r & 0xf) == w) { | 1693 | if ((r & 0xf) == w) { |
| 1631 | w = 0xe; | 1694 | w = 0xe; |
| 1632 | outb (w, CONTROL (pb)); | 1695 | outb(w, CONTROL(pb)); |
| 1633 | r = inb (CONTROL (pb)); | 1696 | r = inb(CONTROL(pb)); |
| 1634 | outb (0xc, CONTROL (pb)); | 1697 | outb(0xc, CONTROL(pb)); |
| 1635 | if ((r & 0xf) == w) | 1698 | if ((r & 0xf) == w) |
| 1636 | return PARPORT_MODE_PCSPP; | 1699 | return PARPORT_MODE_PCSPP; |
| 1637 | } | 1700 | } |
| @@ -1639,18 +1702,18 @@ static int parport_SPP_supported(struct parport *pb) | |||
| 1639 | if (user_specified) | 1702 | if (user_specified) |
| 1640 | /* That didn't work, but the user thinks there's a | 1703 | /* That didn't work, but the user thinks there's a |
| 1641 | * port here. */ | 1704 | * port here. */ |
| 1642 | printk (KERN_INFO "parport 0x%lx (WARNING): CTR: " | 1705 | printk(KERN_INFO "parport 0x%lx (WARNING): CTR: " |
| 1643 | "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); | 1706 | "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); |
| 1644 | 1707 | ||
| 1645 | /* Try the data register. The data lines aren't tri-stated at | 1708 | /* Try the data register. The data lines aren't tri-stated at |
| 1646 | * this stage, so we expect back what we wrote. */ | 1709 | * this stage, so we expect back what we wrote. */ |
| 1647 | w = 0xaa; | 1710 | w = 0xaa; |
| 1648 | parport_pc_write_data (pb, w); | 1711 | parport_pc_write_data(pb, w); |
| 1649 | r = parport_pc_read_data (pb); | 1712 | r = parport_pc_read_data(pb); |
| 1650 | if (r == w) { | 1713 | if (r == w) { |
| 1651 | w = 0x55; | 1714 | w = 0x55; |
| 1652 | parport_pc_write_data (pb, w); | 1715 | parport_pc_write_data(pb, w); |
| 1653 | r = parport_pc_read_data (pb); | 1716 | r = parport_pc_read_data(pb); |
| 1654 | if (r == w) | 1717 | if (r == w) |
| 1655 | return PARPORT_MODE_PCSPP; | 1718 | return PARPORT_MODE_PCSPP; |
| 1656 | } | 1719 | } |
| @@ -1658,9 +1721,9 @@ static int parport_SPP_supported(struct parport *pb) | |||
| 1658 | if (user_specified) { | 1721 | if (user_specified) { |
| 1659 | /* Didn't work, but the user is convinced this is the | 1722 | /* Didn't work, but the user is convinced this is the |
| 1660 | * place. */ | 1723 | * place. */ |
| 1661 | printk (KERN_INFO "parport 0x%lx (WARNING): DATA: " | 1724 | printk(KERN_INFO "parport 0x%lx (WARNING): DATA: " |
| 1662 | "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); | 1725 | "wrote 0x%02x, read 0x%02x\n", pb->base, w, r); |
| 1663 | printk (KERN_INFO "parport 0x%lx: You gave this address, " | 1726 | printk(KERN_INFO "parport 0x%lx: You gave this address, " |
| 1664 | "but there is probably no parallel port there!\n", | 1727 | "but there is probably no parallel port there!\n", |
| 1665 | pb->base); | 1728 | pb->base); |
| 1666 | } | 1729 | } |
| @@ -1691,33 +1754,33 @@ static int parport_ECR_present(struct parport *pb) | |||
| 1691 | struct parport_pc_private *priv = pb->private_data; | 1754 | struct parport_pc_private *priv = pb->private_data; |
| 1692 | unsigned char r = 0xc; | 1755 | unsigned char r = 0xc; |
| 1693 | 1756 | ||
| 1694 | outb (r, CONTROL (pb)); | 1757 | outb(r, CONTROL(pb)); |
| 1695 | if ((inb (ECONTROL (pb)) & 0x3) == (r & 0x3)) { | 1758 | if ((inb(ECONTROL(pb)) & 0x3) == (r & 0x3)) { |
| 1696 | outb (r ^ 0x2, CONTROL (pb)); /* Toggle bit 1 */ | 1759 | outb(r ^ 0x2, CONTROL(pb)); /* Toggle bit 1 */ |
| 1697 | 1760 | ||
| 1698 | r = inb (CONTROL (pb)); | 1761 | r = inb(CONTROL(pb)); |
| 1699 | if ((inb (ECONTROL (pb)) & 0x2) == (r & 0x2)) | 1762 | if ((inb(ECONTROL(pb)) & 0x2) == (r & 0x2)) |
| 1700 | goto no_reg; /* Sure that no ECR register exists */ | 1763 | goto no_reg; /* Sure that no ECR register exists */ |
| 1701 | } | 1764 | } |
| 1702 | 1765 | ||
| 1703 | if ((inb (ECONTROL (pb)) & 0x3 ) != 0x1) | 1766 | if ((inb(ECONTROL(pb)) & 0x3) != 0x1) |
| 1704 | goto no_reg; | 1767 | goto no_reg; |
| 1705 | 1768 | ||
| 1706 | ECR_WRITE (pb, 0x34); | 1769 | ECR_WRITE(pb, 0x34); |
| 1707 | if (inb (ECONTROL (pb)) != 0x35) | 1770 | if (inb(ECONTROL(pb)) != 0x35) |
| 1708 | goto no_reg; | 1771 | goto no_reg; |
| 1709 | 1772 | ||
| 1710 | priv->ecr = 1; | 1773 | priv->ecr = 1; |
| 1711 | outb (0xc, CONTROL (pb)); | 1774 | outb(0xc, CONTROL(pb)); |
| 1712 | 1775 | ||
| 1713 | /* Go to mode 000 */ | 1776 | /* Go to mode 000 */ |
| 1714 | frob_set_mode (pb, ECR_SPP); | 1777 | frob_set_mode(pb, ECR_SPP); |
| 1715 | 1778 | ||
| 1716 | return 1; | 1779 | return 1; |
| 1717 | 1780 | ||
| 1718 | no_reg: | 1781 | no_reg: |
| 1719 | outb (0xc, CONTROL (pb)); | 1782 | outb(0xc, CONTROL(pb)); |
| 1720 | return 0; | 1783 | return 0; |
| 1721 | } | 1784 | } |
| 1722 | 1785 | ||
| 1723 | #ifdef CONFIG_PARPORT_1284 | 1786 | #ifdef CONFIG_PARPORT_1284 |
| @@ -1727,7 +1790,7 @@ static int parport_ECR_present(struct parport *pb) | |||
| 1727 | * allows us to read data from the data lines. In theory we would get back | 1790 | * allows us to read data from the data lines. In theory we would get back |
| 1728 | * 0xff but any peripheral attached to the port may drag some or all of the | 1791 | * 0xff but any peripheral attached to the port may drag some or all of the |
| 1729 | * lines down to zero. So if we get back anything that isn't the contents | 1792 | * lines down to zero. So if we get back anything that isn't the contents |
| 1730 | * of the data register we deem PS/2 support to be present. | 1793 | * of the data register we deem PS/2 support to be present. |
| 1731 | * | 1794 | * |
| 1732 | * Some SPP ports have "half PS/2" ability - you can't turn off the line | 1795 | * Some SPP ports have "half PS/2" ability - you can't turn off the line |
| 1733 | * drivers, but an external peripheral with sufficiently beefy drivers of | 1796 | * drivers, but an external peripheral with sufficiently beefy drivers of |
| @@ -1735,26 +1798,28 @@ static int parport_ECR_present(struct parport *pb) | |||
| 1735 | * where they can then be read back as normal. Ports with this property | 1798 | * where they can then be read back as normal. Ports with this property |
| 1736 | * and the right type of device attached are likely to fail the SPP test, | 1799 | * and the right type of device attached are likely to fail the SPP test, |
| 1737 | * (as they will appear to have stuck bits) and so the fact that they might | 1800 | * (as they will appear to have stuck bits) and so the fact that they might |
| 1738 | * be misdetected here is rather academic. | 1801 | * be misdetected here is rather academic. |
| 1739 | */ | 1802 | */ |
| 1740 | 1803 | ||
| 1741 | static int parport_PS2_supported(struct parport *pb) | 1804 | static int parport_PS2_supported(struct parport *pb) |
| 1742 | { | 1805 | { |
| 1743 | int ok = 0; | 1806 | int ok = 0; |
| 1744 | 1807 | ||
| 1745 | clear_epp_timeout(pb); | 1808 | clear_epp_timeout(pb); |
| 1746 | 1809 | ||
| 1747 | /* try to tri-state the buffer */ | 1810 | /* try to tri-state the buffer */ |
| 1748 | parport_pc_data_reverse (pb); | 1811 | parport_pc_data_reverse(pb); |
| 1749 | 1812 | ||
| 1750 | parport_pc_write_data(pb, 0x55); | 1813 | parport_pc_write_data(pb, 0x55); |
| 1751 | if (parport_pc_read_data(pb) != 0x55) ok++; | 1814 | if (parport_pc_read_data(pb) != 0x55) |
| 1815 | ok++; | ||
| 1752 | 1816 | ||
| 1753 | parport_pc_write_data(pb, 0xaa); | 1817 | parport_pc_write_data(pb, 0xaa); |
| 1754 | if (parport_pc_read_data(pb) != 0xaa) ok++; | 1818 | if (parport_pc_read_data(pb) != 0xaa) |
| 1819 | ok++; | ||
| 1755 | 1820 | ||
| 1756 | /* cancel input mode */ | 1821 | /* cancel input mode */ |
| 1757 | parport_pc_data_forward (pb); | 1822 | parport_pc_data_forward(pb); |
| 1758 | 1823 | ||
| 1759 | if (ok) { | 1824 | if (ok) { |
| 1760 | pb->modes |= PARPORT_MODE_TRISTATE; | 1825 | pb->modes |= PARPORT_MODE_TRISTATE; |
| @@ -1773,68 +1838,68 @@ static int parport_ECP_supported(struct parport *pb) | |||
| 1773 | int config, configb; | 1838 | int config, configb; |
| 1774 | int pword; | 1839 | int pword; |
| 1775 | struct parport_pc_private *priv = pb->private_data; | 1840 | struct parport_pc_private *priv = pb->private_data; |
| 1776 | /* Translate ECP intrLine to ISA irq value */ | 1841 | /* Translate ECP intrLine to ISA irq value */ |
| 1777 | static const int intrline[]= { 0, 7, 9, 10, 11, 14, 15, 5 }; | 1842 | static const int intrline[] = { 0, 7, 9, 10, 11, 14, 15, 5 }; |
| 1778 | 1843 | ||
| 1779 | /* If there is no ECR, we have no hope of supporting ECP. */ | 1844 | /* If there is no ECR, we have no hope of supporting ECP. */ |
| 1780 | if (!priv->ecr) | 1845 | if (!priv->ecr) |
| 1781 | return 0; | 1846 | return 0; |
| 1782 | 1847 | ||
| 1783 | /* Find out FIFO depth */ | 1848 | /* Find out FIFO depth */ |
| 1784 | ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */ | 1849 | ECR_WRITE(pb, ECR_SPP << 5); /* Reset FIFO */ |
| 1785 | ECR_WRITE (pb, ECR_TST << 5); /* TEST FIFO */ | 1850 | ECR_WRITE(pb, ECR_TST << 5); /* TEST FIFO */ |
| 1786 | for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02); i++) | 1851 | for (i = 0; i < 1024 && !(inb(ECONTROL(pb)) & 0x02); i++) |
| 1787 | outb (0xaa, FIFO (pb)); | 1852 | outb(0xaa, FIFO(pb)); |
| 1788 | 1853 | ||
| 1789 | /* | 1854 | /* |
| 1790 | * Using LGS chipset it uses ECR register, but | 1855 | * Using LGS chipset it uses ECR register, but |
| 1791 | * it doesn't support ECP or FIFO MODE | 1856 | * it doesn't support ECP or FIFO MODE |
| 1792 | */ | 1857 | */ |
| 1793 | if (i == 1024) { | 1858 | if (i == 1024) { |
| 1794 | ECR_WRITE (pb, ECR_SPP << 5); | 1859 | ECR_WRITE(pb, ECR_SPP << 5); |
| 1795 | return 0; | 1860 | return 0; |
| 1796 | } | 1861 | } |
| 1797 | 1862 | ||
| 1798 | priv->fifo_depth = i; | 1863 | priv->fifo_depth = i; |
| 1799 | if (verbose_probing) | 1864 | if (verbose_probing) |
| 1800 | printk (KERN_DEBUG "0x%lx: FIFO is %d bytes\n", pb->base, i); | 1865 | printk(KERN_DEBUG "0x%lx: FIFO is %d bytes\n", pb->base, i); |
| 1801 | 1866 | ||
| 1802 | /* Find out writeIntrThreshold */ | 1867 | /* Find out writeIntrThreshold */ |
| 1803 | frob_econtrol (pb, 1<<2, 1<<2); | 1868 | frob_econtrol(pb, 1<<2, 1<<2); |
| 1804 | frob_econtrol (pb, 1<<2, 0); | 1869 | frob_econtrol(pb, 1<<2, 0); |
| 1805 | for (i = 1; i <= priv->fifo_depth; i++) { | 1870 | for (i = 1; i <= priv->fifo_depth; i++) { |
| 1806 | inb (FIFO (pb)); | 1871 | inb(FIFO(pb)); |
| 1807 | udelay (50); | 1872 | udelay(50); |
| 1808 | if (inb (ECONTROL (pb)) & (1<<2)) | 1873 | if (inb(ECONTROL(pb)) & (1<<2)) |
| 1809 | break; | 1874 | break; |
| 1810 | } | 1875 | } |
| 1811 | 1876 | ||
| 1812 | if (i <= priv->fifo_depth) { | 1877 | if (i <= priv->fifo_depth) { |
| 1813 | if (verbose_probing) | 1878 | if (verbose_probing) |
| 1814 | printk (KERN_DEBUG "0x%lx: writeIntrThreshold is %d\n", | 1879 | printk(KERN_DEBUG "0x%lx: writeIntrThreshold is %d\n", |
| 1815 | pb->base, i); | 1880 | pb->base, i); |
| 1816 | } else | 1881 | } else |
| 1817 | /* Number of bytes we know we can write if we get an | 1882 | /* Number of bytes we know we can write if we get an |
| 1818 | interrupt. */ | 1883 | interrupt. */ |
| 1819 | i = 0; | 1884 | i = 0; |
| 1820 | 1885 | ||
| 1821 | priv->writeIntrThreshold = i; | 1886 | priv->writeIntrThreshold = i; |
| 1822 | 1887 | ||
| 1823 | /* Find out readIntrThreshold */ | 1888 | /* Find out readIntrThreshold */ |
| 1824 | frob_set_mode (pb, ECR_PS2); /* Reset FIFO and enable PS2 */ | 1889 | frob_set_mode(pb, ECR_PS2); /* Reset FIFO and enable PS2 */ |
| 1825 | parport_pc_data_reverse (pb); /* Must be in PS2 mode */ | 1890 | parport_pc_data_reverse(pb); /* Must be in PS2 mode */ |
| 1826 | frob_set_mode (pb, ECR_TST); /* Test FIFO */ | 1891 | frob_set_mode(pb, ECR_TST); /* Test FIFO */ |
| 1827 | frob_econtrol (pb, 1<<2, 1<<2); | 1892 | frob_econtrol(pb, 1<<2, 1<<2); |
| 1828 | frob_econtrol (pb, 1<<2, 0); | 1893 | frob_econtrol(pb, 1<<2, 0); |
| 1829 | for (i = 1; i <= priv->fifo_depth; i++) { | 1894 | for (i = 1; i <= priv->fifo_depth; i++) { |
| 1830 | outb (0xaa, FIFO (pb)); | 1895 | outb(0xaa, FIFO(pb)); |
| 1831 | if (inb (ECONTROL (pb)) & (1<<2)) | 1896 | if (inb(ECONTROL(pb)) & (1<<2)) |
| 1832 | break; | 1897 | break; |
| 1833 | } | 1898 | } |
| 1834 | 1899 | ||
| 1835 | if (i <= priv->fifo_depth) { | 1900 | if (i <= priv->fifo_depth) { |
| 1836 | if (verbose_probing) | 1901 | if (verbose_probing) |
| 1837 | printk (KERN_INFO "0x%lx: readIntrThreshold is %d\n", | 1902 | printk(KERN_INFO "0x%lx: readIntrThreshold is %d\n", |
| 1838 | pb->base, i); | 1903 | pb->base, i); |
| 1839 | } else | 1904 | } else |
| 1840 | /* Number of bytes we can read if we get an interrupt. */ | 1905 | /* Number of bytes we can read if we get an interrupt. */ |
| @@ -1842,23 +1907,23 @@ static int parport_ECP_supported(struct parport *pb) | |||
| 1842 | 1907 | ||
| 1843 | priv->readIntrThreshold = i; | 1908 | priv->readIntrThreshold = i; |
| 1844 | 1909 | ||
| 1845 | ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */ | 1910 | ECR_WRITE(pb, ECR_SPP << 5); /* Reset FIFO */ |
| 1846 | ECR_WRITE (pb, 0xf4); /* Configuration mode */ | 1911 | ECR_WRITE(pb, 0xf4); /* Configuration mode */ |
| 1847 | config = inb (CONFIGA (pb)); | 1912 | config = inb(CONFIGA(pb)); |
| 1848 | pword = (config >> 4) & 0x7; | 1913 | pword = (config >> 4) & 0x7; |
| 1849 | switch (pword) { | 1914 | switch (pword) { |
| 1850 | case 0: | 1915 | case 0: |
| 1851 | pword = 2; | 1916 | pword = 2; |
| 1852 | printk (KERN_WARNING "0x%lx: Unsupported pword size!\n", | 1917 | printk(KERN_WARNING "0x%lx: Unsupported pword size!\n", |
| 1853 | pb->base); | 1918 | pb->base); |
| 1854 | break; | 1919 | break; |
| 1855 | case 2: | 1920 | case 2: |
| 1856 | pword = 4; | 1921 | pword = 4; |
| 1857 | printk (KERN_WARNING "0x%lx: Unsupported pword size!\n", | 1922 | printk(KERN_WARNING "0x%lx: Unsupported pword size!\n", |
| 1858 | pb->base); | 1923 | pb->base); |
| 1859 | break; | 1924 | break; |
| 1860 | default: | 1925 | default: |
| 1861 | printk (KERN_WARNING "0x%lx: Unknown implementation ID\n", | 1926 | printk(KERN_WARNING "0x%lx: Unknown implementation ID\n", |
| 1862 | pb->base); | 1927 | pb->base); |
| 1863 | /* Assume 1 */ | 1928 | /* Assume 1 */ |
| 1864 | case 1: | 1929 | case 1: |
| @@ -1867,28 +1932,29 @@ static int parport_ECP_supported(struct parport *pb) | |||
| 1867 | priv->pword = pword; | 1932 | priv->pword = pword; |
| 1868 | 1933 | ||
| 1869 | if (verbose_probing) { | 1934 | if (verbose_probing) { |
| 1870 | printk (KERN_DEBUG "0x%lx: PWord is %d bits\n", pb->base, 8 * pword); | 1935 | printk(KERN_DEBUG "0x%lx: PWord is %d bits\n", |
| 1871 | 1936 | pb->base, 8 * pword); | |
| 1872 | printk (KERN_DEBUG "0x%lx: Interrupts are ISA-%s\n", pb->base, | 1937 | |
| 1938 | printk(KERN_DEBUG "0x%lx: Interrupts are ISA-%s\n", pb->base, | ||
| 1873 | config & 0x80 ? "Level" : "Pulses"); | 1939 | config & 0x80 ? "Level" : "Pulses"); |
| 1874 | 1940 | ||
| 1875 | configb = inb (CONFIGB (pb)); | 1941 | configb = inb(CONFIGB(pb)); |
| 1876 | printk (KERN_DEBUG "0x%lx: ECP port cfgA=0x%02x cfgB=0x%02x\n", | 1942 | printk(KERN_DEBUG "0x%lx: ECP port cfgA=0x%02x cfgB=0x%02x\n", |
| 1877 | pb->base, config, configb); | 1943 | pb->base, config, configb); |
| 1878 | printk (KERN_DEBUG "0x%lx: ECP settings irq=", pb->base); | 1944 | printk(KERN_DEBUG "0x%lx: ECP settings irq=", pb->base); |
| 1879 | if ((configb >>3) & 0x07) | 1945 | if ((configb >> 3) & 0x07) |
| 1880 | printk("%d",intrline[(configb >>3) & 0x07]); | 1946 | printk("%d", intrline[(configb >> 3) & 0x07]); |
| 1881 | else | 1947 | else |
| 1882 | printk("<none or set by other means>"); | 1948 | printk("<none or set by other means>"); |
| 1883 | printk (" dma="); | 1949 | printk(" dma="); |
| 1884 | if( (configb & 0x03 ) == 0x00) | 1950 | if ((configb & 0x03) == 0x00) |
| 1885 | printk("<none or set by other means>\n"); | 1951 | printk("<none or set by other means>\n"); |
| 1886 | else | 1952 | else |
| 1887 | printk("%d\n",configb & 0x07); | 1953 | printk("%d\n", configb & 0x07); |
| 1888 | } | 1954 | } |
| 1889 | 1955 | ||
| 1890 | /* Go back to mode 000 */ | 1956 | /* Go back to mode 000 */ |
| 1891 | frob_set_mode (pb, ECR_SPP); | 1957 | frob_set_mode(pb, ECR_SPP); |
| 1892 | 1958 | ||
| 1893 | return 1; | 1959 | return 1; |
| 1894 | } | 1960 | } |
| @@ -1903,10 +1969,10 @@ static int parport_ECPPS2_supported(struct parport *pb) | |||
| 1903 | if (!priv->ecr) | 1969 | if (!priv->ecr) |
| 1904 | return 0; | 1970 | return 0; |
| 1905 | 1971 | ||
| 1906 | oecr = inb (ECONTROL (pb)); | 1972 | oecr = inb(ECONTROL(pb)); |
| 1907 | ECR_WRITE (pb, ECR_PS2 << 5); | 1973 | ECR_WRITE(pb, ECR_PS2 << 5); |
| 1908 | result = parport_PS2_supported(pb); | 1974 | result = parport_PS2_supported(pb); |
| 1909 | ECR_WRITE (pb, oecr); | 1975 | ECR_WRITE(pb, oecr); |
| 1910 | return result; | 1976 | return result; |
| 1911 | } | 1977 | } |
| 1912 | 1978 | ||
| @@ -1930,16 +1996,15 @@ static int parport_EPP_supported(struct parport *pb) | |||
| 1930 | */ | 1996 | */ |
| 1931 | 1997 | ||
| 1932 | /* If EPP timeout bit clear then EPP available */ | 1998 | /* If EPP timeout bit clear then EPP available */ |
| 1933 | if (!clear_epp_timeout(pb)) { | 1999 | if (!clear_epp_timeout(pb)) |
| 1934 | return 0; /* No way to clear timeout */ | 2000 | return 0; /* No way to clear timeout */ |
| 1935 | } | ||
| 1936 | 2001 | ||
| 1937 | /* Check for Intel bug. */ | 2002 | /* Check for Intel bug. */ |
| 1938 | if (priv->ecr) { | 2003 | if (priv->ecr) { |
| 1939 | unsigned char i; | 2004 | unsigned char i; |
| 1940 | for (i = 0x00; i < 0x80; i += 0x20) { | 2005 | for (i = 0x00; i < 0x80; i += 0x20) { |
| 1941 | ECR_WRITE (pb, i); | 2006 | ECR_WRITE(pb, i); |
| 1942 | if (clear_epp_timeout (pb)) { | 2007 | if (clear_epp_timeout(pb)) { |
| 1943 | /* Phony EPP in ECP. */ | 2008 | /* Phony EPP in ECP. */ |
| 1944 | return 0; | 2009 | return 0; |
| 1945 | } | 2010 | } |
| @@ -1963,17 +2028,16 @@ static int parport_ECPEPP_supported(struct parport *pb) | |||
| 1963 | int result; | 2028 | int result; |
| 1964 | unsigned char oecr; | 2029 | unsigned char oecr; |
| 1965 | 2030 | ||
| 1966 | if (!priv->ecr) { | 2031 | if (!priv->ecr) |
| 1967 | return 0; | 2032 | return 0; |
| 1968 | } | ||
| 1969 | 2033 | ||
| 1970 | oecr = inb (ECONTROL (pb)); | 2034 | oecr = inb(ECONTROL(pb)); |
| 1971 | /* Search for SMC style EPP+ECP mode */ | 2035 | /* Search for SMC style EPP+ECP mode */ |
| 1972 | ECR_WRITE (pb, 0x80); | 2036 | ECR_WRITE(pb, 0x80); |
| 1973 | outb (0x04, CONTROL (pb)); | 2037 | outb(0x04, CONTROL(pb)); |
| 1974 | result = parport_EPP_supported(pb); | 2038 | result = parport_EPP_supported(pb); |
| 1975 | 2039 | ||
| 1976 | ECR_WRITE (pb, oecr); | 2040 | ECR_WRITE(pb, oecr); |
| 1977 | 2041 | ||
| 1978 | if (result) { | 2042 | if (result) { |
| 1979 | /* Set up access functions to use ECP+EPP hardware. */ | 2043 | /* Set up access functions to use ECP+EPP hardware. */ |
| @@ -1991,11 +2055,25 @@ static int parport_ECPEPP_supported(struct parport *pb) | |||
| 1991 | /* Don't bother probing for modes we know we won't use. */ | 2055 | /* Don't bother probing for modes we know we won't use. */ |
| 1992 | static int __devinit parport_PS2_supported(struct parport *pb) { return 0; } | 2056 | static int __devinit parport_PS2_supported(struct parport *pb) { return 0; } |
| 1993 | #ifdef CONFIG_PARPORT_PC_FIFO | 2057 | #ifdef CONFIG_PARPORT_PC_FIFO |
| 1994 | static int parport_ECP_supported(struct parport *pb) { return 0; } | 2058 | static int parport_ECP_supported(struct parport *pb) |
| 2059 | { | ||
| 2060 | return 0; | ||
| 2061 | } | ||
| 1995 | #endif | 2062 | #endif |
| 1996 | static int __devinit parport_EPP_supported(struct parport *pb) { return 0; } | 2063 | static int __devinit parport_EPP_supported(struct parport *pb) |
| 1997 | static int __devinit parport_ECPEPP_supported(struct parport *pb){return 0;} | 2064 | { |
| 1998 | static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;} | 2065 | return 0; |
| 2066 | } | ||
| 2067 | |||
| 2068 | static int __devinit parport_ECPEPP_supported(struct parport *pb) | ||
| 2069 | { | ||
| 2070 | return 0; | ||
| 2071 | } | ||
| 2072 | |||
| 2073 | static int __devinit parport_ECPPS2_supported(struct parport *pb) | ||
| 2074 | { | ||
| 2075 | return 0; | ||
| 2076 | } | ||
| 1999 | 2077 | ||
| 2000 | #endif /* No IEEE 1284 support */ | 2078 | #endif /* No IEEE 1284 support */ |
| 2001 | 2079 | ||
| @@ -2005,17 +2083,17 @@ static int __devinit parport_ECPPS2_supported(struct parport *pb){return 0;} | |||
| 2005 | static int programmable_irq_support(struct parport *pb) | 2083 | static int programmable_irq_support(struct parport *pb) |
| 2006 | { | 2084 | { |
| 2007 | int irq, intrLine; | 2085 | int irq, intrLine; |
| 2008 | unsigned char oecr = inb (ECONTROL (pb)); | 2086 | unsigned char oecr = inb(ECONTROL(pb)); |
| 2009 | static const int lookup[8] = { | 2087 | static const int lookup[8] = { |
| 2010 | PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5 | 2088 | PARPORT_IRQ_NONE, 7, 9, 10, 11, 14, 15, 5 |
| 2011 | }; | 2089 | }; |
| 2012 | 2090 | ||
| 2013 | ECR_WRITE (pb, ECR_CNF << 5); /* Configuration MODE */ | 2091 | ECR_WRITE(pb, ECR_CNF << 5); /* Configuration MODE */ |
| 2014 | 2092 | ||
| 2015 | intrLine = (inb (CONFIGB (pb)) >> 3) & 0x07; | 2093 | intrLine = (inb(CONFIGB(pb)) >> 3) & 0x07; |
| 2016 | irq = lookup[intrLine]; | 2094 | irq = lookup[intrLine]; |
| 2017 | 2095 | ||
| 2018 | ECR_WRITE (pb, oecr); | 2096 | ECR_WRITE(pb, oecr); |
| 2019 | return irq; | 2097 | return irq; |
| 2020 | } | 2098 | } |
| 2021 | 2099 | ||
| @@ -2025,17 +2103,17 @@ static int irq_probe_ECP(struct parport *pb) | |||
| 2025 | unsigned long irqs; | 2103 | unsigned long irqs; |
| 2026 | 2104 | ||
| 2027 | irqs = probe_irq_on(); | 2105 | irqs = probe_irq_on(); |
| 2028 | 2106 | ||
| 2029 | ECR_WRITE (pb, ECR_SPP << 5); /* Reset FIFO */ | 2107 | ECR_WRITE(pb, ECR_SPP << 5); /* Reset FIFO */ |
| 2030 | ECR_WRITE (pb, (ECR_TST << 5) | 0x04); | 2108 | ECR_WRITE(pb, (ECR_TST << 5) | 0x04); |
| 2031 | ECR_WRITE (pb, ECR_TST << 5); | 2109 | ECR_WRITE(pb, ECR_TST << 5); |
| 2032 | 2110 | ||
| 2033 | /* If Full FIFO sure that writeIntrThreshold is generated */ | 2111 | /* If Full FIFO sure that writeIntrThreshold is generated */ |
| 2034 | for (i=0; i < 1024 && !(inb (ECONTROL (pb)) & 0x02) ; i++) | 2112 | for (i = 0; i < 1024 && !(inb(ECONTROL(pb)) & 0x02) ; i++) |
| 2035 | outb (0xaa, FIFO (pb)); | 2113 | outb(0xaa, FIFO(pb)); |
| 2036 | 2114 | ||
| 2037 | pb->irq = probe_irq_off(irqs); | 2115 | pb->irq = probe_irq_off(irqs); |
| 2038 | ECR_WRITE (pb, ECR_SPP << 5); | 2116 | ECR_WRITE(pb, ECR_SPP << 5); |
| 2039 | 2117 | ||
| 2040 | if (pb->irq <= 0) | 2118 | if (pb->irq <= 0) |
| 2041 | pb->irq = PARPORT_IRQ_NONE; | 2119 | pb->irq = PARPORT_IRQ_NONE; |
| @@ -2045,7 +2123,7 @@ static int irq_probe_ECP(struct parport *pb) | |||
| 2045 | 2123 | ||
| 2046 | /* | 2124 | /* |
| 2047 | * This detection seems that only works in National Semiconductors | 2125 | * This detection seems that only works in National Semiconductors |
| 2048 | * This doesn't work in SMC, LGS, and Winbond | 2126 | * This doesn't work in SMC, LGS, and Winbond |
| 2049 | */ | 2127 | */ |
| 2050 | static int irq_probe_EPP(struct parport *pb) | 2128 | static int irq_probe_EPP(struct parport *pb) |
| 2051 | { | 2129 | { |
| @@ -2056,16 +2134,16 @@ static int irq_probe_EPP(struct parport *pb) | |||
| 2056 | unsigned char oecr; | 2134 | unsigned char oecr; |
| 2057 | 2135 | ||
| 2058 | if (pb->modes & PARPORT_MODE_PCECR) | 2136 | if (pb->modes & PARPORT_MODE_PCECR) |
| 2059 | oecr = inb (ECONTROL (pb)); | 2137 | oecr = inb(ECONTROL(pb)); |
| 2060 | 2138 | ||
| 2061 | irqs = probe_irq_on(); | 2139 | irqs = probe_irq_on(); |
| 2062 | 2140 | ||
| 2063 | if (pb->modes & PARPORT_MODE_PCECR) | 2141 | if (pb->modes & PARPORT_MODE_PCECR) |
| 2064 | frob_econtrol (pb, 0x10, 0x10); | 2142 | frob_econtrol(pb, 0x10, 0x10); |
| 2065 | 2143 | ||
| 2066 | clear_epp_timeout(pb); | 2144 | clear_epp_timeout(pb); |
| 2067 | parport_pc_frob_control (pb, 0x20, 0x20); | 2145 | parport_pc_frob_control(pb, 0x20, 0x20); |
| 2068 | parport_pc_frob_control (pb, 0x10, 0x10); | 2146 | parport_pc_frob_control(pb, 0x10, 0x10); |
| 2069 | clear_epp_timeout(pb); | 2147 | clear_epp_timeout(pb); |
| 2070 | 2148 | ||
| 2071 | /* Device isn't expecting an EPP read | 2149 | /* Device isn't expecting an EPP read |
| @@ -2074,9 +2152,9 @@ static int irq_probe_EPP(struct parport *pb) | |||
| 2074 | parport_pc_read_epp(pb); | 2152 | parport_pc_read_epp(pb); |
| 2075 | udelay(20); | 2153 | udelay(20); |
| 2076 | 2154 | ||
| 2077 | pb->irq = probe_irq_off (irqs); | 2155 | pb->irq = probe_irq_off(irqs); |
| 2078 | if (pb->modes & PARPORT_MODE_PCECR) | 2156 | if (pb->modes & PARPORT_MODE_PCECR) |
| 2079 | ECR_WRITE (pb, oecr); | 2157 | ECR_WRITE(pb, oecr); |
| 2080 | parport_pc_write_control(pb, 0xc); | 2158 | parport_pc_write_control(pb, 0xc); |
| 2081 | 2159 | ||
| 2082 | if (pb->irq <= 0) | 2160 | if (pb->irq <= 0) |
| @@ -2133,28 +2211,28 @@ static int parport_irq_probe(struct parport *pb) | |||
| 2133 | /* --- DMA detection -------------------------------------- */ | 2211 | /* --- DMA detection -------------------------------------- */ |
| 2134 | 2212 | ||
| 2135 | /* Only if chipset conforms to ECP ISA Interface Standard */ | 2213 | /* Only if chipset conforms to ECP ISA Interface Standard */ |
| 2136 | static int programmable_dma_support (struct parport *p) | 2214 | static int programmable_dma_support(struct parport *p) |
| 2137 | { | 2215 | { |
| 2138 | unsigned char oecr = inb (ECONTROL (p)); | 2216 | unsigned char oecr = inb(ECONTROL(p)); |
| 2139 | int dma; | 2217 | int dma; |
| 2140 | 2218 | ||
| 2141 | frob_set_mode (p, ECR_CNF); | 2219 | frob_set_mode(p, ECR_CNF); |
| 2142 | 2220 | ||
| 2143 | dma = inb (CONFIGB(p)) & 0x07; | 2221 | dma = inb(CONFIGB(p)) & 0x07; |
| 2144 | /* 000: Indicates jumpered 8-bit DMA if read-only. | 2222 | /* 000: Indicates jumpered 8-bit DMA if read-only. |
| 2145 | 100: Indicates jumpered 16-bit DMA if read-only. */ | 2223 | 100: Indicates jumpered 16-bit DMA if read-only. */ |
| 2146 | if ((dma & 0x03) == 0) | 2224 | if ((dma & 0x03) == 0) |
| 2147 | dma = PARPORT_DMA_NONE; | 2225 | dma = PARPORT_DMA_NONE; |
| 2148 | 2226 | ||
| 2149 | ECR_WRITE (p, oecr); | 2227 | ECR_WRITE(p, oecr); |
| 2150 | return dma; | 2228 | return dma; |
| 2151 | } | 2229 | } |
| 2152 | 2230 | ||
| 2153 | static int parport_dma_probe (struct parport *p) | 2231 | static int parport_dma_probe(struct parport *p) |
| 2154 | { | 2232 | { |
| 2155 | const struct parport_pc_private *priv = p->private_data; | 2233 | const struct parport_pc_private *priv = p->private_data; |
| 2156 | if (priv->ecr) | 2234 | if (priv->ecr) /* ask ECP chipset first */ |
| 2157 | p->dma = programmable_dma_support(p); /* ask ECP chipset first */ | 2235 | p->dma = programmable_dma_support(p); |
| 2158 | if (p->dma == PARPORT_DMA_NONE) { | 2236 | if (p->dma == PARPORT_DMA_NONE) { |
| 2159 | /* ask known Super-IO chips proper, although these | 2237 | /* ask known Super-IO chips proper, although these |
| 2160 | claim ECP compatible, some don't report their DMA | 2238 | claim ECP compatible, some don't report their DMA |
| @@ -2212,7 +2290,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2212 | if (!base_res) | 2290 | if (!base_res) |
| 2213 | goto out4; | 2291 | goto out4; |
| 2214 | 2292 | ||
| 2215 | memcpy(ops, &parport_pc_ops, sizeof (struct parport_operations)); | 2293 | memcpy(ops, &parport_pc_ops, sizeof(struct parport_operations)); |
| 2216 | priv->ctr = 0xc; | 2294 | priv->ctr = 0xc; |
| 2217 | priv->ctr_writable = ~0x10; | 2295 | priv->ctr_writable = ~0x10; |
| 2218 | priv->ecr = 0; | 2296 | priv->ecr = 0; |
| @@ -2239,7 +2317,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2239 | if (!parport_EPP_supported(p)) | 2317 | if (!parport_EPP_supported(p)) |
| 2240 | parport_ECPEPP_supported(p); | 2318 | parport_ECPEPP_supported(p); |
| 2241 | } | 2319 | } |
| 2242 | if (!parport_SPP_supported (p)) | 2320 | if (!parport_SPP_supported(p)) |
| 2243 | /* No port. */ | 2321 | /* No port. */ |
| 2244 | goto out5; | 2322 | goto out5; |
| 2245 | if (priv->ecr) | 2323 | if (priv->ecr) |
| @@ -2247,7 +2325,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2247 | else | 2325 | else |
| 2248 | parport_PS2_supported(p); | 2326 | parport_PS2_supported(p); |
| 2249 | 2327 | ||
| 2250 | p->size = (p->modes & PARPORT_MODE_EPP)?8:3; | 2328 | p->size = (p->modes & PARPORT_MODE_EPP) ? 8 : 3; |
| 2251 | 2329 | ||
| 2252 | printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); | 2330 | printk(KERN_INFO "%s: PC-style at 0x%lx", p->name, p->base); |
| 2253 | if (p->base_hi && priv->ecr) | 2331 | if (p->base_hi && priv->ecr) |
| @@ -2271,7 +2349,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2271 | } | 2349 | } |
| 2272 | } | 2350 | } |
| 2273 | if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq | 2351 | if (p->dma == PARPORT_DMA_AUTO) /* To use DMA, giving the irq |
| 2274 | is mandatory (see above) */ | 2352 | is mandatory (see above) */ |
| 2275 | p->dma = PARPORT_DMA_NONE; | 2353 | p->dma = PARPORT_DMA_NONE; |
| 2276 | 2354 | ||
| 2277 | #ifdef CONFIG_PARPORT_PC_FIFO | 2355 | #ifdef CONFIG_PARPORT_PC_FIFO |
| @@ -2288,16 +2366,23 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2288 | if (p->dma != PARPORT_DMA_NONE) { | 2366 | if (p->dma != PARPORT_DMA_NONE) { |
| 2289 | printk(", dma %d", p->dma); | 2367 | printk(", dma %d", p->dma); |
| 2290 | p->modes |= PARPORT_MODE_DMA; | 2368 | p->modes |= PARPORT_MODE_DMA; |
| 2291 | } | 2369 | } else |
| 2292 | else printk(", using FIFO"); | 2370 | printk(", using FIFO"); |
| 2293 | } | 2371 | } else |
| 2294 | else | ||
| 2295 | /* We can't use the DMA channel after all. */ | 2372 | /* We can't use the DMA channel after all. */ |
| 2296 | p->dma = PARPORT_DMA_NONE; | 2373 | p->dma = PARPORT_DMA_NONE; |
| 2297 | #endif /* Allowed to use FIFO/DMA */ | 2374 | #endif /* Allowed to use FIFO/DMA */ |
| 2298 | 2375 | ||
| 2299 | printk(" ["); | 2376 | printk(" ["); |
| 2300 | #define printmode(x) {if(p->modes&PARPORT_MODE_##x){printk("%s%s",f?",":"",#x);f++;}} | 2377 | |
| 2378 | #define printmode(x) \ | ||
| 2379 | {\ | ||
| 2380 | if (p->modes & PARPORT_MODE_##x) {\ | ||
| 2381 | printk("%s%s", f ? "," : "", #x);\ | ||
| 2382 | f++;\ | ||
| 2383 | } \ | ||
| 2384 | } | ||
| 2385 | |||
| 2301 | { | 2386 | { |
| 2302 | int f = 0; | 2387 | int f = 0; |
| 2303 | printmode(PCSPP); | 2388 | printmode(PCSPP); |
| @@ -2309,10 +2394,10 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2309 | } | 2394 | } |
| 2310 | #undef printmode | 2395 | #undef printmode |
| 2311 | #ifndef CONFIG_PARPORT_1284 | 2396 | #ifndef CONFIG_PARPORT_1284 |
| 2312 | printk ("(,...)"); | 2397 | printk("(,...)"); |
| 2313 | #endif /* CONFIG_PARPORT_1284 */ | 2398 | #endif /* CONFIG_PARPORT_1284 */ |
| 2314 | printk("]\n"); | 2399 | printk("]\n"); |
| 2315 | if (probedirq != PARPORT_IRQ_NONE) | 2400 | if (probedirq != PARPORT_IRQ_NONE) |
| 2316 | printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); | 2401 | printk(KERN_INFO "%s: irq %d detected\n", p->name, probedirq); |
| 2317 | 2402 | ||
| 2318 | /* If No ECP release the ports grabbed above. */ | 2403 | /* If No ECP release the ports grabbed above. */ |
| @@ -2328,7 +2413,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2328 | if (p->irq != PARPORT_IRQ_NONE) { | 2413 | if (p->irq != PARPORT_IRQ_NONE) { |
| 2329 | if (request_irq(p->irq, parport_irq_handler, | 2414 | if (request_irq(p->irq, parport_irq_handler, |
| 2330 | irqflags, p->name, p)) { | 2415 | irqflags, p->name, p)) { |
| 2331 | printk (KERN_WARNING "%s: irq %d in use, " | 2416 | printk(KERN_WARNING "%s: irq %d in use, " |
| 2332 | "resorting to polled operation\n", | 2417 | "resorting to polled operation\n", |
| 2333 | p->name, p->irq); | 2418 | p->name, p->irq); |
| 2334 | p->irq = PARPORT_IRQ_NONE; | 2419 | p->irq = PARPORT_IRQ_NONE; |
| @@ -2338,8 +2423,8 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2338 | #ifdef CONFIG_PARPORT_PC_FIFO | 2423 | #ifdef CONFIG_PARPORT_PC_FIFO |
| 2339 | #ifdef HAS_DMA | 2424 | #ifdef HAS_DMA |
| 2340 | if (p->dma != PARPORT_DMA_NONE) { | 2425 | if (p->dma != PARPORT_DMA_NONE) { |
| 2341 | if (request_dma (p->dma, p->name)) { | 2426 | if (request_dma(p->dma, p->name)) { |
| 2342 | printk (KERN_WARNING "%s: dma %d in use, " | 2427 | printk(KERN_WARNING "%s: dma %d in use, " |
| 2343 | "resorting to PIO operation\n", | 2428 | "resorting to PIO operation\n", |
| 2344 | p->name, p->dma); | 2429 | p->name, p->dma); |
| 2345 | p->dma = PARPORT_DMA_NONE; | 2430 | p->dma = PARPORT_DMA_NONE; |
| @@ -2349,8 +2434,8 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2349 | PAGE_SIZE, | 2434 | PAGE_SIZE, |
| 2350 | &priv->dma_handle, | 2435 | &priv->dma_handle, |
| 2351 | GFP_KERNEL); | 2436 | GFP_KERNEL); |
| 2352 | if (! priv->dma_buf) { | 2437 | if (!priv->dma_buf) { |
| 2353 | printk (KERN_WARNING "%s: " | 2438 | printk(KERN_WARNING "%s: " |
| 2354 | "cannot get buffer for DMA, " | 2439 | "cannot get buffer for DMA, " |
| 2355 | "resorting to PIO operation\n", | 2440 | "resorting to PIO operation\n", |
| 2356 | p->name); | 2441 | p->name); |
| @@ -2369,10 +2454,10 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2369 | * Put the ECP detected port in PS2 mode. | 2454 | * Put the ECP detected port in PS2 mode. |
| 2370 | * Do this also for ports that have ECR but don't do ECP. | 2455 | * Do this also for ports that have ECR but don't do ECP. |
| 2371 | */ | 2456 | */ |
| 2372 | ECR_WRITE (p, 0x34); | 2457 | ECR_WRITE(p, 0x34); |
| 2373 | 2458 | ||
| 2374 | parport_pc_write_data(p, 0); | 2459 | parport_pc_write_data(p, 0); |
| 2375 | parport_pc_data_forward (p); | 2460 | parport_pc_data_forward(p); |
| 2376 | 2461 | ||
| 2377 | /* Now that we've told the sharing engine about the port, and | 2462 | /* Now that we've told the sharing engine about the port, and |
| 2378 | found out its characteristics, let the high-level drivers | 2463 | found out its characteristics, let the high-level drivers |
| @@ -2380,7 +2465,7 @@ struct parport *parport_pc_probe_port(unsigned long int base, | |||
| 2380 | spin_lock(&ports_lock); | 2465 | spin_lock(&ports_lock); |
| 2381 | list_add(&priv->list, &ports_list); | 2466 | list_add(&priv->list, &ports_list); |
| 2382 | spin_unlock(&ports_lock); | 2467 | spin_unlock(&ports_lock); |
| 2383 | parport_announce_port (p); | 2468 | parport_announce_port(p); |
| 2384 | 2469 | ||
| 2385 | return p; | 2470 | return p; |
| 2386 | 2471 | ||
| @@ -2393,18 +2478,17 @@ out5: | |||
| 2393 | out4: | 2478 | out4: |
| 2394 | parport_put_port(p); | 2479 | parport_put_port(p); |
| 2395 | out3: | 2480 | out3: |
| 2396 | kfree (priv); | 2481 | kfree(priv); |
| 2397 | out2: | 2482 | out2: |
| 2398 | kfree (ops); | 2483 | kfree(ops); |
| 2399 | out1: | 2484 | out1: |
| 2400 | if (pdev) | 2485 | if (pdev) |
| 2401 | platform_device_unregister(pdev); | 2486 | platform_device_unregister(pdev); |
| 2402 | return NULL; | 2487 | return NULL; |
| 2403 | } | 2488 | } |
| 2489 | EXPORT_SYMBOL(parport_pc_probe_port); | ||
| 2404 | 2490 | ||
| 2405 | EXPORT_SYMBOL (parport_pc_probe_port); | 2491 | void parport_pc_unregister_port(struct parport *p) |
| 2406 | |||
| 2407 | void parport_pc_unregister_port (struct parport *p) | ||
| 2408 | { | 2492 | { |
| 2409 | struct parport_pc_private *priv = p->private_data; | 2493 | struct parport_pc_private *priv = p->private_data; |
| 2410 | struct parport_operations *ops = p->ops; | 2494 | struct parport_operations *ops = p->ops; |
| @@ -2430,17 +2514,16 @@ void parport_pc_unregister_port (struct parport *p) | |||
| 2430 | priv->dma_buf, | 2514 | priv->dma_buf, |
| 2431 | priv->dma_handle); | 2515 | priv->dma_handle); |
| 2432 | #endif | 2516 | #endif |
| 2433 | kfree (p->private_data); | 2517 | kfree(p->private_data); |
| 2434 | parport_put_port(p); | 2518 | parport_put_port(p); |
| 2435 | kfree (ops); /* hope no-one cached it */ | 2519 | kfree(ops); /* hope no-one cached it */ |
| 2436 | } | 2520 | } |
| 2437 | 2521 | EXPORT_SYMBOL(parport_pc_unregister_port); | |
| 2438 | EXPORT_SYMBOL (parport_pc_unregister_port); | ||
| 2439 | 2522 | ||
| 2440 | #ifdef CONFIG_PCI | 2523 | #ifdef CONFIG_PCI |
| 2441 | 2524 | ||
| 2442 | /* ITE support maintained by Rich Liu <richliu@poorman.org> */ | 2525 | /* ITE support maintained by Rich Liu <richliu@poorman.org> */ |
| 2443 | static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, | 2526 | static int __devinit sio_ite_8872_probe(struct pci_dev *pdev, int autoirq, |
| 2444 | int autodma, | 2527 | int autodma, |
| 2445 | const struct parport_pc_via_data *via) | 2528 | const struct parport_pc_via_data *via) |
| 2446 | { | 2529 | { |
| @@ -2452,73 +2535,74 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, | |||
| 2452 | int irq; | 2535 | int irq; |
| 2453 | int i; | 2536 | int i; |
| 2454 | 2537 | ||
| 2455 | DPRINTK (KERN_DEBUG "sio_ite_8872_probe()\n"); | 2538 | DPRINTK(KERN_DEBUG "sio_ite_8872_probe()\n"); |
| 2456 | 2539 | ||
| 2457 | // make sure which one chip | 2540 | /* make sure which one chip */ |
| 2458 | for(i = 0; i < 5; i++) { | 2541 | for (i = 0; i < 5; i++) { |
| 2459 | base_res = request_region(inta_addr[i], 32, "it887x"); | 2542 | base_res = request_region(inta_addr[i], 32, "it887x"); |
| 2460 | if (base_res) { | 2543 | if (base_res) { |
| 2461 | int test; | 2544 | int test; |
| 2462 | pci_write_config_dword (pdev, 0x60, | 2545 | pci_write_config_dword(pdev, 0x60, |
| 2463 | 0xe5000000 | inta_addr[i]); | 2546 | 0xe5000000 | inta_addr[i]); |
| 2464 | pci_write_config_dword (pdev, 0x78, | 2547 | pci_write_config_dword(pdev, 0x78, |
| 2465 | 0x00000000 | inta_addr[i]); | 2548 | 0x00000000 | inta_addr[i]); |
| 2466 | test = inb (inta_addr[i]); | 2549 | test = inb(inta_addr[i]); |
| 2467 | if (test != 0xff) break; | 2550 | if (test != 0xff) |
| 2551 | break; | ||
| 2468 | release_region(inta_addr[i], 0x8); | 2552 | release_region(inta_addr[i], 0x8); |
| 2469 | } | 2553 | } |
| 2470 | } | 2554 | } |
| 2471 | if(i >= 5) { | 2555 | if (i >= 5) { |
| 2472 | printk (KERN_INFO "parport_pc: cannot find ITE8872 INTA\n"); | 2556 | printk(KERN_INFO "parport_pc: cannot find ITE8872 INTA\n"); |
| 2473 | return 0; | 2557 | return 0; |
| 2474 | } | 2558 | } |
| 2475 | 2559 | ||
| 2476 | type = inb (inta_addr[i] + 0x18); | 2560 | type = inb(inta_addr[i] + 0x18); |
| 2477 | type &= 0x0f; | 2561 | type &= 0x0f; |
| 2478 | 2562 | ||
| 2479 | switch (type) { | 2563 | switch (type) { |
| 2480 | case 0x2: | 2564 | case 0x2: |
| 2481 | printk (KERN_INFO "parport_pc: ITE8871 found (1P)\n"); | 2565 | printk(KERN_INFO "parport_pc: ITE8871 found (1P)\n"); |
| 2482 | ite8872set = 0x64200000; | 2566 | ite8872set = 0x64200000; |
| 2483 | break; | 2567 | break; |
| 2484 | case 0xa: | 2568 | case 0xa: |
| 2485 | printk (KERN_INFO "parport_pc: ITE8875 found (1P)\n"); | 2569 | printk(KERN_INFO "parport_pc: ITE8875 found (1P)\n"); |
| 2486 | ite8872set = 0x64200000; | 2570 | ite8872set = 0x64200000; |
| 2487 | break; | 2571 | break; |
| 2488 | case 0xe: | 2572 | case 0xe: |
| 2489 | printk (KERN_INFO "parport_pc: ITE8872 found (2S1P)\n"); | 2573 | printk(KERN_INFO "parport_pc: ITE8872 found (2S1P)\n"); |
| 2490 | ite8872set = 0x64e00000; | 2574 | ite8872set = 0x64e00000; |
| 2491 | break; | 2575 | break; |
| 2492 | case 0x6: | 2576 | case 0x6: |
| 2493 | printk (KERN_INFO "parport_pc: ITE8873 found (1S)\n"); | 2577 | printk(KERN_INFO "parport_pc: ITE8873 found (1S)\n"); |
| 2494 | return 0; | 2578 | return 0; |
| 2495 | case 0x8: | 2579 | case 0x8: |
| 2496 | DPRINTK (KERN_DEBUG "parport_pc: ITE8874 found (2S)\n"); | 2580 | DPRINTK(KERN_DEBUG "parport_pc: ITE8874 found (2S)\n"); |
| 2497 | return 0; | 2581 | return 0; |
| 2498 | default: | 2582 | default: |
| 2499 | printk (KERN_INFO "parport_pc: unknown ITE887x\n"); | 2583 | printk(KERN_INFO "parport_pc: unknown ITE887x\n"); |
| 2500 | printk (KERN_INFO "parport_pc: please mail 'lspci -nvv' " | 2584 | printk(KERN_INFO "parport_pc: please mail 'lspci -nvv' " |
| 2501 | "output to Rich.Liu@ite.com.tw\n"); | 2585 | "output to Rich.Liu@ite.com.tw\n"); |
| 2502 | return 0; | 2586 | return 0; |
| 2503 | } | 2587 | } |
| 2504 | 2588 | ||
| 2505 | pci_read_config_byte (pdev, 0x3c, &ite8872_irq); | 2589 | pci_read_config_byte(pdev, 0x3c, &ite8872_irq); |
| 2506 | pci_read_config_dword (pdev, 0x1c, &ite8872_lpt); | 2590 | pci_read_config_dword(pdev, 0x1c, &ite8872_lpt); |
| 2507 | ite8872_lpt &= 0x0000ff00; | 2591 | ite8872_lpt &= 0x0000ff00; |
| 2508 | pci_read_config_dword (pdev, 0x20, &ite8872_lpthi); | 2592 | pci_read_config_dword(pdev, 0x20, &ite8872_lpthi); |
| 2509 | ite8872_lpthi &= 0x0000ff00; | 2593 | ite8872_lpthi &= 0x0000ff00; |
| 2510 | pci_write_config_dword (pdev, 0x6c, 0xe3000000 | ite8872_lpt); | 2594 | pci_write_config_dword(pdev, 0x6c, 0xe3000000 | ite8872_lpt); |
| 2511 | pci_write_config_dword (pdev, 0x70, 0xe3000000 | ite8872_lpthi); | 2595 | pci_write_config_dword(pdev, 0x70, 0xe3000000 | ite8872_lpthi); |
| 2512 | pci_write_config_dword (pdev, 0x80, (ite8872_lpthi<<16) | ite8872_lpt); | 2596 | pci_write_config_dword(pdev, 0x80, (ite8872_lpthi<<16) | ite8872_lpt); |
| 2513 | // SET SPP&EPP , Parallel Port NO DMA , Enable All Function | 2597 | /* SET SPP&EPP , Parallel Port NO DMA , Enable All Function */ |
| 2514 | // SET Parallel IRQ | 2598 | /* SET Parallel IRQ */ |
| 2515 | pci_write_config_dword (pdev, 0x9c, | 2599 | pci_write_config_dword(pdev, 0x9c, |
| 2516 | ite8872set | (ite8872_irq * 0x11111)); | 2600 | ite8872set | (ite8872_irq * 0x11111)); |
| 2517 | 2601 | ||
| 2518 | DPRINTK (KERN_DEBUG "ITE887x: The IRQ is %d.\n", ite8872_irq); | 2602 | DPRINTK(KERN_DEBUG "ITE887x: The IRQ is %d.\n", ite8872_irq); |
| 2519 | DPRINTK (KERN_DEBUG "ITE887x: The PARALLEL I/O port is 0x%x.\n", | 2603 | DPRINTK(KERN_DEBUG "ITE887x: The PARALLEL I/O port is 0x%x.\n", |
| 2520 | ite8872_lpt); | 2604 | ite8872_lpt); |
| 2521 | DPRINTK (KERN_DEBUG "ITE887x: The PARALLEL I/O porthi is 0x%x.\n", | 2605 | DPRINTK(KERN_DEBUG "ITE887x: The PARALLEL I/O porthi is 0x%x.\n", |
| 2522 | ite8872_lpthi); | 2606 | ite8872_lpthi); |
| 2523 | 2607 | ||
| 2524 | /* Let the user (or defaults) steer us away from interrupts */ | 2608 | /* Let the user (or defaults) steer us away from interrupts */ |
| @@ -2530,14 +2614,14 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, | |||
| 2530 | * Release the resource so that parport_pc_probe_port can get it. | 2614 | * Release the resource so that parport_pc_probe_port can get it. |
| 2531 | */ | 2615 | */ |
| 2532 | release_resource(base_res); | 2616 | release_resource(base_res); |
| 2533 | if (parport_pc_probe_port (ite8872_lpt, ite8872_lpthi, | 2617 | if (parport_pc_probe_port(ite8872_lpt, ite8872_lpthi, |
| 2534 | irq, PARPORT_DMA_NONE, &pdev->dev, 0)) { | 2618 | irq, PARPORT_DMA_NONE, &pdev->dev, 0)) { |
| 2535 | printk (KERN_INFO | 2619 | printk(KERN_INFO |
| 2536 | "parport_pc: ITE 8872 parallel port: io=0x%X", | 2620 | "parport_pc: ITE 8872 parallel port: io=0x%X", |
| 2537 | ite8872_lpt); | 2621 | ite8872_lpt); |
| 2538 | if (irq != PARPORT_IRQ_NONE) | 2622 | if (irq != PARPORT_IRQ_NONE) |
| 2539 | printk (", irq=%d", irq); | 2623 | printk(", irq=%d", irq); |
| 2540 | printk ("\n"); | 2624 | printk("\n"); |
| 2541 | return 1; | 2625 | return 1; |
| 2542 | } | 2626 | } |
| 2543 | 2627 | ||
| @@ -2546,7 +2630,7 @@ static int __devinit sio_ite_8872_probe (struct pci_dev *pdev, int autoirq, | |||
| 2546 | 2630 | ||
| 2547 | /* VIA 8231 support by Pavel Fedin <sonic_amiga@rambler.ru> | 2631 | /* VIA 8231 support by Pavel Fedin <sonic_amiga@rambler.ru> |
| 2548 | based on VIA 686a support code by Jeff Garzik <jgarzik@pobox.com> */ | 2632 | based on VIA 686a support code by Jeff Garzik <jgarzik@pobox.com> */ |
| 2549 | static int __devinitdata parport_init_mode = 0; | 2633 | static int __devinitdata parport_init_mode; |
| 2550 | 2634 | ||
| 2551 | /* Data for two known VIA chips */ | 2635 | /* Data for two known VIA chips */ |
| 2552 | static struct parport_pc_via_data via_686a_data __devinitdata = { | 2636 | static struct parport_pc_via_data via_686a_data __devinitdata = { |
| @@ -2568,7 +2652,7 @@ static struct parport_pc_via_data via_8231_data __devinitdata = { | |||
| 2568 | 0xF6 | 2652 | 0xF6 |
| 2569 | }; | 2653 | }; |
| 2570 | 2654 | ||
| 2571 | static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, | 2655 | static int __devinit sio_via_probe(struct pci_dev *pdev, int autoirq, |
| 2572 | int autodma, | 2656 | int autodma, |
| 2573 | const struct parport_pc_via_data *via) | 2657 | const struct parport_pc_via_data *via) |
| 2574 | { | 2658 | { |
| @@ -2580,38 +2664,38 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, | |||
| 2580 | 2664 | ||
| 2581 | printk(KERN_DEBUG "parport_pc: VIA 686A/8231 detected\n"); | 2665 | printk(KERN_DEBUG "parport_pc: VIA 686A/8231 detected\n"); |
| 2582 | 2666 | ||
| 2583 | switch(parport_init_mode) | 2667 | switch (parport_init_mode) { |
| 2584 | { | ||
| 2585 | case 1: | 2668 | case 1: |
| 2586 | printk(KERN_DEBUG "parport_pc: setting SPP mode\n"); | 2669 | printk(KERN_DEBUG "parport_pc: setting SPP mode\n"); |
| 2587 | siofunc = VIA_FUNCTION_PARPORT_SPP; | 2670 | siofunc = VIA_FUNCTION_PARPORT_SPP; |
| 2588 | break; | 2671 | break; |
| 2589 | case 2: | 2672 | case 2: |
| 2590 | printk(KERN_DEBUG "parport_pc: setting PS/2 mode\n"); | 2673 | printk(KERN_DEBUG "parport_pc: setting PS/2 mode\n"); |
| 2591 | siofunc = VIA_FUNCTION_PARPORT_SPP; | 2674 | siofunc = VIA_FUNCTION_PARPORT_SPP; |
| 2592 | ppcontrol = VIA_PARPORT_BIDIR; | 2675 | ppcontrol = VIA_PARPORT_BIDIR; |
| 2593 | break; | 2676 | break; |
| 2594 | case 3: | 2677 | case 3: |
| 2595 | printk(KERN_DEBUG "parport_pc: setting EPP mode\n"); | 2678 | printk(KERN_DEBUG "parport_pc: setting EPP mode\n"); |
| 2596 | siofunc = VIA_FUNCTION_PARPORT_EPP; | 2679 | siofunc = VIA_FUNCTION_PARPORT_EPP; |
| 2597 | ppcontrol = VIA_PARPORT_BIDIR; | 2680 | ppcontrol = VIA_PARPORT_BIDIR; |
| 2598 | have_epp = 1; | 2681 | have_epp = 1; |
| 2599 | break; | 2682 | break; |
| 2600 | case 4: | 2683 | case 4: |
| 2601 | printk(KERN_DEBUG "parport_pc: setting ECP mode\n"); | 2684 | printk(KERN_DEBUG "parport_pc: setting ECP mode\n"); |
| 2602 | siofunc = VIA_FUNCTION_PARPORT_ECP; | 2685 | siofunc = VIA_FUNCTION_PARPORT_ECP; |
| 2603 | ppcontrol = VIA_PARPORT_BIDIR; | 2686 | ppcontrol = VIA_PARPORT_BIDIR; |
| 2604 | break; | 2687 | break; |
| 2605 | case 5: | 2688 | case 5: |
| 2606 | printk(KERN_DEBUG "parport_pc: setting EPP+ECP mode\n"); | 2689 | printk(KERN_DEBUG "parport_pc: setting EPP+ECP mode\n"); |
| 2607 | siofunc = VIA_FUNCTION_PARPORT_ECP; | 2690 | siofunc = VIA_FUNCTION_PARPORT_ECP; |
| 2608 | ppcontrol = VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP; | 2691 | ppcontrol = VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP; |
| 2609 | have_epp = 1; | 2692 | have_epp = 1; |
| 2610 | break; | 2693 | break; |
| 2611 | default: | 2694 | default: |
| 2612 | printk(KERN_DEBUG "parport_pc: probing current configuration\n"); | 2695 | printk(KERN_DEBUG |
| 2613 | siofunc = VIA_FUNCTION_PROBE; | 2696 | "parport_pc: probing current configuration\n"); |
| 2614 | break; | 2697 | siofunc = VIA_FUNCTION_PROBE; |
| 2698 | break; | ||
| 2615 | } | 2699 | } |
| 2616 | /* | 2700 | /* |
| 2617 | * unlock super i/o configuration | 2701 | * unlock super i/o configuration |
| @@ -2622,38 +2706,36 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, | |||
| 2622 | 2706 | ||
| 2623 | /* Bits 1-0: Parallel Port Mode / Enable */ | 2707 | /* Bits 1-0: Parallel Port Mode / Enable */ |
| 2624 | outb(via->viacfg_function, VIA_CONFIG_INDEX); | 2708 | outb(via->viacfg_function, VIA_CONFIG_INDEX); |
| 2625 | tmp = inb (VIA_CONFIG_DATA); | 2709 | tmp = inb(VIA_CONFIG_DATA); |
| 2626 | /* Bit 5: EPP+ECP enable; bit 7: PS/2 bidirectional port enable */ | 2710 | /* Bit 5: EPP+ECP enable; bit 7: PS/2 bidirectional port enable */ |
| 2627 | outb(via->viacfg_parport_control, VIA_CONFIG_INDEX); | 2711 | outb(via->viacfg_parport_control, VIA_CONFIG_INDEX); |
| 2628 | tmp2 = inb (VIA_CONFIG_DATA); | 2712 | tmp2 = inb(VIA_CONFIG_DATA); |
| 2629 | if (siofunc == VIA_FUNCTION_PROBE) | 2713 | if (siofunc == VIA_FUNCTION_PROBE) { |
| 2630 | { | 2714 | siofunc = tmp & VIA_FUNCTION_PARPORT_DISABLE; |
| 2631 | siofunc = tmp & VIA_FUNCTION_PARPORT_DISABLE; | 2715 | ppcontrol = tmp2; |
| 2632 | ppcontrol = tmp2; | 2716 | } else { |
| 2717 | tmp &= ~VIA_FUNCTION_PARPORT_DISABLE; | ||
| 2718 | tmp |= siofunc; | ||
| 2719 | outb(via->viacfg_function, VIA_CONFIG_INDEX); | ||
| 2720 | outb(tmp, VIA_CONFIG_DATA); | ||
| 2721 | tmp2 &= ~(VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP); | ||
| 2722 | tmp2 |= ppcontrol; | ||
| 2723 | outb(via->viacfg_parport_control, VIA_CONFIG_INDEX); | ||
| 2724 | outb(tmp2, VIA_CONFIG_DATA); | ||
| 2633 | } | 2725 | } |
| 2634 | else | 2726 | |
| 2635 | { | ||
| 2636 | tmp &= ~VIA_FUNCTION_PARPORT_DISABLE; | ||
| 2637 | tmp |= siofunc; | ||
| 2638 | outb(via->viacfg_function, VIA_CONFIG_INDEX); | ||
| 2639 | outb(tmp, VIA_CONFIG_DATA); | ||
| 2640 | tmp2 &= ~(VIA_PARPORT_BIDIR|VIA_PARPORT_ECPEPP); | ||
| 2641 | tmp2 |= ppcontrol; | ||
| 2642 | outb(via->viacfg_parport_control, VIA_CONFIG_INDEX); | ||
| 2643 | outb(tmp2, VIA_CONFIG_DATA); | ||
| 2644 | } | ||
| 2645 | |||
| 2646 | /* Parallel Port I/O Base Address, bits 9-2 */ | 2727 | /* Parallel Port I/O Base Address, bits 9-2 */ |
| 2647 | outb(via->viacfg_parport_base, VIA_CONFIG_INDEX); | 2728 | outb(via->viacfg_parport_base, VIA_CONFIG_INDEX); |
| 2648 | port1 = inb(VIA_CONFIG_DATA) << 2; | 2729 | port1 = inb(VIA_CONFIG_DATA) << 2; |
| 2649 | 2730 | ||
| 2650 | printk (KERN_DEBUG "parport_pc: Current parallel port base: 0x%X\n",port1); | 2731 | printk(KERN_DEBUG "parport_pc: Current parallel port base: 0x%X\n", |
| 2651 | if ((port1 == 0x3BC) && have_epp) | 2732 | port1); |
| 2652 | { | 2733 | if (port1 == 0x3BC && have_epp) { |
| 2653 | outb(via->viacfg_parport_base, VIA_CONFIG_INDEX); | 2734 | outb(via->viacfg_parport_base, VIA_CONFIG_INDEX); |
| 2654 | outb((0x378 >> 2), VIA_CONFIG_DATA); | 2735 | outb((0x378 >> 2), VIA_CONFIG_DATA); |
| 2655 | printk(KERN_DEBUG "parport_pc: Parallel port base changed to 0x378\n"); | 2736 | printk(KERN_DEBUG |
| 2656 | port1 = 0x378; | 2737 | "parport_pc: Parallel port base changed to 0x378\n"); |
| 2738 | port1 = 0x378; | ||
| 2657 | } | 2739 | } |
| 2658 | 2740 | ||
| 2659 | /* | 2741 | /* |
| @@ -2667,36 +2749,39 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, | |||
| 2667 | printk(KERN_INFO "parport_pc: VIA parallel port disabled in BIOS\n"); | 2749 | printk(KERN_INFO "parport_pc: VIA parallel port disabled in BIOS\n"); |
| 2668 | return 0; | 2750 | return 0; |
| 2669 | } | 2751 | } |
| 2670 | 2752 | ||
| 2671 | /* Bits 7-4: PnP Routing for Parallel Port IRQ */ | 2753 | /* Bits 7-4: PnP Routing for Parallel Port IRQ */ |
| 2672 | pci_read_config_byte(pdev, via->via_pci_parport_irq_reg, &tmp); | 2754 | pci_read_config_byte(pdev, via->via_pci_parport_irq_reg, &tmp); |
| 2673 | irq = ((tmp & VIA_IRQCONTROL_PARALLEL) >> 4); | 2755 | irq = ((tmp & VIA_IRQCONTROL_PARALLEL) >> 4); |
| 2674 | 2756 | ||
| 2675 | if (siofunc == VIA_FUNCTION_PARPORT_ECP) | 2757 | if (siofunc == VIA_FUNCTION_PARPORT_ECP) { |
| 2676 | { | 2758 | /* Bits 3-2: PnP Routing for Parallel Port DMA */ |
| 2677 | /* Bits 3-2: PnP Routing for Parallel Port DMA */ | 2759 | pci_read_config_byte(pdev, via->via_pci_parport_dma_reg, &tmp); |
| 2678 | pci_read_config_byte(pdev, via->via_pci_parport_dma_reg, &tmp); | 2760 | dma = ((tmp & VIA_DMACONTROL_PARALLEL) >> 2); |
| 2679 | dma = ((tmp & VIA_DMACONTROL_PARALLEL) >> 2); | 2761 | } else |
| 2680 | } | 2762 | /* if ECP not enabled, DMA is not enabled, assumed |
| 2681 | else | 2763 | bogus 'dma' value */ |
| 2682 | /* if ECP not enabled, DMA is not enabled, assumed bogus 'dma' value */ | 2764 | dma = PARPORT_DMA_NONE; |
| 2683 | dma = PARPORT_DMA_NONE; | ||
| 2684 | 2765 | ||
| 2685 | /* Let the user (or defaults) steer us away from interrupts and DMA */ | 2766 | /* Let the user (or defaults) steer us away from interrupts and DMA */ |
| 2686 | if (autoirq == PARPORT_IRQ_NONE) { | 2767 | if (autoirq == PARPORT_IRQ_NONE) { |
| 2687 | irq = PARPORT_IRQ_NONE; | 2768 | irq = PARPORT_IRQ_NONE; |
| 2688 | dma = PARPORT_DMA_NONE; | 2769 | dma = PARPORT_DMA_NONE; |
| 2689 | } | 2770 | } |
| 2690 | if (autodma == PARPORT_DMA_NONE) | 2771 | if (autodma == PARPORT_DMA_NONE) |
| 2691 | dma = PARPORT_DMA_NONE; | 2772 | dma = PARPORT_DMA_NONE; |
| 2692 | 2773 | ||
| 2693 | switch (port1) { | 2774 | switch (port1) { |
| 2694 | case 0x3bc: port2 = 0x7bc; break; | 2775 | case 0x3bc: |
| 2695 | case 0x378: port2 = 0x778; break; | 2776 | port2 = 0x7bc; break; |
| 2696 | case 0x278: port2 = 0x678; break; | 2777 | case 0x378: |
| 2778 | port2 = 0x778; break; | ||
| 2779 | case 0x278: | ||
| 2780 | port2 = 0x678; break; | ||
| 2697 | default: | 2781 | default: |
| 2698 | printk(KERN_INFO "parport_pc: Weird VIA parport base 0x%X, ignoring\n", | 2782 | printk(KERN_INFO |
| 2699 | port1); | 2783 | "parport_pc: Weird VIA parport base 0x%X, ignoring\n", |
| 2784 | port1); | ||
| 2700 | return 0; | 2785 | return 0; |
| 2701 | } | 2786 | } |
| 2702 | 2787 | ||
| @@ -2714,17 +2799,17 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, | |||
| 2714 | } | 2799 | } |
| 2715 | 2800 | ||
| 2716 | /* finally, do the probe with values obtained */ | 2801 | /* finally, do the probe with values obtained */ |
| 2717 | if (parport_pc_probe_port (port1, port2, irq, dma, &pdev->dev, 0)) { | 2802 | if (parport_pc_probe_port(port1, port2, irq, dma, &pdev->dev, 0)) { |
| 2718 | printk (KERN_INFO | 2803 | printk(KERN_INFO |
| 2719 | "parport_pc: VIA parallel port: io=0x%X", port1); | 2804 | "parport_pc: VIA parallel port: io=0x%X", port1); |
| 2720 | if (irq != PARPORT_IRQ_NONE) | 2805 | if (irq != PARPORT_IRQ_NONE) |
| 2721 | printk (", irq=%d", irq); | 2806 | printk(", irq=%d", irq); |
| 2722 | if (dma != PARPORT_DMA_NONE) | 2807 | if (dma != PARPORT_DMA_NONE) |
| 2723 | printk (", dma=%d", dma); | 2808 | printk(", dma=%d", dma); |
| 2724 | printk ("\n"); | 2809 | printk("\n"); |
| 2725 | return 1; | 2810 | return 1; |
| 2726 | } | 2811 | } |
| 2727 | 2812 | ||
| 2728 | printk(KERN_WARNING "parport_pc: Strange, can't probe VIA parallel port: io=0x%X, irq=%d, dma=%d\n", | 2813 | printk(KERN_WARNING "parport_pc: Strange, can't probe VIA parallel port: io=0x%X, irq=%d, dma=%d\n", |
| 2729 | port1, irq, dma); | 2814 | port1, irq, dma); |
| 2730 | return 0; | 2815 | return 0; |
| @@ -2732,8 +2817,8 @@ static int __devinit sio_via_probe (struct pci_dev *pdev, int autoirq, | |||
| 2732 | 2817 | ||
| 2733 | 2818 | ||
| 2734 | enum parport_pc_sio_types { | 2819 | enum parport_pc_sio_types { |
| 2735 | sio_via_686a = 0, /* Via VT82C686A motherboard Super I/O */ | 2820 | sio_via_686a = 0, /* Via VT82C686A motherboard Super I/O */ |
| 2736 | sio_via_8231, /* Via VT8231 south bridge integrated Super IO */ | 2821 | sio_via_8231, /* Via VT8231 south bridge integrated Super IO */ |
| 2737 | sio_ite_8872, | 2822 | sio_ite_8872, |
| 2738 | last_sio | 2823 | last_sio |
| 2739 | }; | 2824 | }; |
| @@ -2804,15 +2889,15 @@ enum parport_pc_pci_cards { | |||
| 2804 | }; | 2889 | }; |
| 2805 | 2890 | ||
| 2806 | 2891 | ||
| 2807 | /* each element directly indexed from enum list, above | 2892 | /* each element directly indexed from enum list, above |
| 2808 | * (but offset by last_sio) */ | 2893 | * (but offset by last_sio) */ |
| 2809 | static struct parport_pc_pci { | 2894 | static struct parport_pc_pci { |
| 2810 | int numports; | 2895 | int numports; |
| 2811 | struct { /* BAR (base address registers) numbers in the config | 2896 | struct { /* BAR (base address registers) numbers in the config |
| 2812 | space header */ | 2897 | space header */ |
| 2813 | int lo; | 2898 | int lo; |
| 2814 | int hi; /* -1 if not there, >6 for offset-method (max | 2899 | int hi; |
| 2815 | BAR is 6) */ | 2900 | /* -1 if not there, >6 for offset-method (max BAR is 6) */ |
| 2816 | } addr[4]; | 2901 | } addr[4]; |
| 2817 | 2902 | ||
| 2818 | /* If set, this is called immediately after pci_enable_device. | 2903 | /* If set, this is called immediately after pci_enable_device. |
| @@ -2857,7 +2942,7 @@ static struct parport_pc_pci { | |||
| 2857 | /* timedia_4018 */ { 2, { { 0, 1 }, { 2, 3 }, } }, | 2942 | /* timedia_4018 */ { 2, { { 0, 1 }, { 2, 3 }, } }, |
| 2858 | /* timedia_9018a */ { 2, { { 0, 1 }, { 2, 3 }, } }, | 2943 | /* timedia_9018a */ { 2, { { 0, 1 }, { 2, 3 }, } }, |
| 2859 | /* SYBA uses fixed offsets in | 2944 | /* SYBA uses fixed offsets in |
| 2860 | a 1K io window */ | 2945 | a 1K io window */ |
| 2861 | /* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, | 2946 | /* syba_2p_epp AP138B */ { 2, { { 0, 0x078 }, { 0, 0x178 }, } }, |
| 2862 | /* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } }, | 2947 | /* syba_1p_ecp W83787 */ { 1, { { 0, 0x078 }, } }, |
| 2863 | /* titan_010l */ { 1, { { 3, -1 }, } }, | 2948 | /* titan_010l */ { 1, { { 3, -1 }, } }, |
| @@ -2873,11 +2958,14 @@ static struct parport_pc_pci { | |||
| 2873 | /* oxsemi_pcie_pport */ { 1, { { 0, 1 }, } }, | 2958 | /* oxsemi_pcie_pport */ { 1, { { 0, 1 }, } }, |
| 2874 | /* aks_0100 */ { 1, { { 0, -1 }, } }, | 2959 | /* aks_0100 */ { 1, { { 0, -1 }, } }, |
| 2875 | /* mobility_pp */ { 1, { { 0, 1 }, } }, | 2960 | /* mobility_pp */ { 1, { { 0, 1 }, } }, |
| 2876 | /* netmos_9705 */ { 1, { { 0, -1 }, } }, /* untested */ | 2961 | |
| 2877 | /* netmos_9715 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ | 2962 | /* The netmos entries below are untested */ |
| 2878 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, /* untested */ | 2963 | /* netmos_9705 */ { 1, { { 0, -1 }, } }, |
| 2879 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, /* untested */ | 2964 | /* netmos_9715 */ { 2, { { 0, 1 }, { 2, 3 },} }, |
| 2880 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, /* untested */ | 2965 | /* netmos_9755 */ { 2, { { 0, 1 }, { 2, 3 },} }, |
| 2966 | /* netmos_9805 */ { 1, { { 0, -1 }, } }, | ||
| 2967 | /* netmos_9815 */ { 2, { { 0, -1 }, { 2, -1 }, } }, | ||
| 2968 | |||
| 2881 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, | 2969 | /* quatech_sppxp100 */ { 1, { { 0, 1 }, } }, |
| 2882 | }; | 2970 | }; |
| 2883 | 2971 | ||
| @@ -2906,7 +2994,7 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
| 2906 | { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_BOCA_IOPPAR, | 2994 | { PCI_VENDOR_ID_LAVA, PCI_DEVICE_ID_LAVA_BOCA_IOPPAR, |
| 2907 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, boca_ioppar }, | 2995 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, boca_ioppar }, |
| 2908 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, | 2996 | { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, |
| 2909 | PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0,0, plx_9050 }, | 2997 | PCI_SUBVENDOR_ID_EXSYS, PCI_SUBDEVICE_ID_EXSYS_4014, 0, 0, plx_9050 }, |
| 2910 | /* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/ | 2998 | /* PCI_VENDOR_ID_TIMEDIA/SUNIX has many differing cards ...*/ |
| 2911 | { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a }, | 2999 | { 0x1409, 0x7168, 0x1409, 0x4078, 0, 0, timedia_4078a }, |
| 2912 | { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h }, | 3000 | { 0x1409, 0x7168, 0x1409, 0x4079, 0, 0, timedia_4079h }, |
| @@ -2940,7 +3028,8 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
| 2940 | { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 }, | 3028 | { 0x9710, 0x9805, 0x1000, 0x0010, 0, 0, titan_1284p1 }, |
| 2941 | { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 }, | 3029 | { 0x9710, 0x9815, 0x1000, 0x0020, 0, 0, titan_1284p2 }, |
| 2942 | /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ | 3030 | /* PCI_VENDOR_ID_AVLAB/Intek21 has another bunch of cards ...*/ |
| 2943 | { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, /* AFAVLAB_TK9902 */ | 3031 | /* AFAVLAB_TK9902 */ |
| 3032 | { 0x14db, 0x2120, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_1p}, | ||
| 2944 | { 0x14db, 0x2121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2p}, | 3033 | { 0x14db, 0x2121, PCI_ANY_ID, PCI_ANY_ID, 0, 0, avlab_2p}, |
| 2945 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952PP, | 3034 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI952PP, |
| 2946 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_952 }, | 3035 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, oxsemi_952 }, |
| @@ -2983,14 +3072,14 @@ static const struct pci_device_id parport_pc_pci_tbl[] = { | |||
| 2983 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, | 3072 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, quatech_sppxp100 }, |
| 2984 | { 0, } /* terminate list */ | 3073 | { 0, } /* terminate list */ |
| 2985 | }; | 3074 | }; |
| 2986 | MODULE_DEVICE_TABLE(pci,parport_pc_pci_tbl); | 3075 | MODULE_DEVICE_TABLE(pci, parport_pc_pci_tbl); |
| 2987 | 3076 | ||
| 2988 | struct pci_parport_data { | 3077 | struct pci_parport_data { |
| 2989 | int num; | 3078 | int num; |
| 2990 | struct parport *ports[2]; | 3079 | struct parport *ports[2]; |
| 2991 | }; | 3080 | }; |
| 2992 | 3081 | ||
| 2993 | static int parport_pc_pci_probe (struct pci_dev *dev, | 3082 | static int parport_pc_pci_probe(struct pci_dev *dev, |
| 2994 | const struct pci_device_id *id) | 3083 | const struct pci_device_id *id) |
| 2995 | { | 3084 | { |
| 2996 | int err, count, n, i = id->driver_data; | 3085 | int err, count, n, i = id->driver_data; |
| @@ -3003,7 +3092,8 @@ static int parport_pc_pci_probe (struct pci_dev *dev, | |||
| 3003 | /* This is a PCI card */ | 3092 | /* This is a PCI card */ |
| 3004 | i -= last_sio; | 3093 | i -= last_sio; |
| 3005 | count = 0; | 3094 | count = 0; |
| 3006 | if ((err = pci_enable_device (dev)) != 0) | 3095 | err = pci_enable_device(dev); |
| 3096 | if (err) | ||
| 3007 | return err; | 3097 | return err; |
| 3008 | 3098 | ||
| 3009 | data = kmalloc(sizeof(struct pci_parport_data), GFP_KERNEL); | 3099 | data = kmalloc(sizeof(struct pci_parport_data), GFP_KERNEL); |
| @@ -3011,7 +3101,7 @@ static int parport_pc_pci_probe (struct pci_dev *dev, | |||
| 3011 | return -ENOMEM; | 3101 | return -ENOMEM; |
| 3012 | 3102 | ||
| 3013 | if (cards[i].preinit_hook && | 3103 | if (cards[i].preinit_hook && |
| 3014 | cards[i].preinit_hook (dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE)) { | 3104 | cards[i].preinit_hook(dev, PARPORT_IRQ_NONE, PARPORT_DMA_NONE)) { |
| 3015 | kfree(data); | 3105 | kfree(data); |
| 3016 | return -ENODEV; | 3106 | return -ENODEV; |
| 3017 | } | 3107 | } |
| @@ -3021,25 +3111,25 @@ static int parport_pc_pci_probe (struct pci_dev *dev, | |||
| 3021 | int hi = cards[i].addr[n].hi; | 3111 | int hi = cards[i].addr[n].hi; |
| 3022 | int irq; | 3112 | int irq; |
| 3023 | unsigned long io_lo, io_hi; | 3113 | unsigned long io_lo, io_hi; |
| 3024 | io_lo = pci_resource_start (dev, lo); | 3114 | io_lo = pci_resource_start(dev, lo); |
| 3025 | io_hi = 0; | 3115 | io_hi = 0; |
| 3026 | if ((hi >= 0) && (hi <= 6)) | 3116 | if ((hi >= 0) && (hi <= 6)) |
| 3027 | io_hi = pci_resource_start (dev, hi); | 3117 | io_hi = pci_resource_start(dev, hi); |
| 3028 | else if (hi > 6) | 3118 | else if (hi > 6) |
| 3029 | io_lo += hi; /* Reinterpret the meaning of | 3119 | io_lo += hi; /* Reinterpret the meaning of |
| 3030 | "hi" as an offset (see SYBA | 3120 | "hi" as an offset (see SYBA |
| 3031 | def.) */ | 3121 | def.) */ |
| 3032 | /* TODO: test if sharing interrupts works */ | 3122 | /* TODO: test if sharing interrupts works */ |
| 3033 | irq = dev->irq; | 3123 | irq = dev->irq; |
| 3034 | if (irq == IRQ_NONE) { | 3124 | if (irq == IRQ_NONE) { |
| 3035 | printk (KERN_DEBUG | 3125 | printk(KERN_DEBUG |
| 3036 | "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx)\n", | 3126 | "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx)\n", |
| 3037 | parport_pc_pci_tbl[i + last_sio].vendor, | 3127 | parport_pc_pci_tbl[i + last_sio].vendor, |
| 3038 | parport_pc_pci_tbl[i + last_sio].device, | 3128 | parport_pc_pci_tbl[i + last_sio].device, |
| 3039 | io_lo, io_hi); | 3129 | io_lo, io_hi); |
| 3040 | irq = PARPORT_IRQ_NONE; | 3130 | irq = PARPORT_IRQ_NONE; |
| 3041 | } else { | 3131 | } else { |
| 3042 | printk (KERN_DEBUG | 3132 | printk(KERN_DEBUG |
| 3043 | "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx), IRQ %d\n", | 3133 | "PCI parallel port detected: %04x:%04x, I/O at %#lx(%#lx), IRQ %d\n", |
| 3044 | parport_pc_pci_tbl[i + last_sio].vendor, | 3134 | parport_pc_pci_tbl[i + last_sio].vendor, |
| 3045 | parport_pc_pci_tbl[i + last_sio].device, | 3135 | parport_pc_pci_tbl[i + last_sio].device, |
| @@ -3056,7 +3146,7 @@ static int parport_pc_pci_probe (struct pci_dev *dev, | |||
| 3056 | data->num = count; | 3146 | data->num = count; |
| 3057 | 3147 | ||
| 3058 | if (cards[i].postinit_hook) | 3148 | if (cards[i].postinit_hook) |
| 3059 | cards[i].postinit_hook (dev, count == 0); | 3149 | cards[i].postinit_hook(dev, count == 0); |
| 3060 | 3150 | ||
| 3061 | if (count) { | 3151 | if (count) { |
| 3062 | pci_set_drvdata(dev, data); | 3152 | pci_set_drvdata(dev, data); |
| @@ -3090,7 +3180,7 @@ static struct pci_driver parport_pc_pci_driver = { | |||
| 3090 | .remove = __devexit_p(parport_pc_pci_remove), | 3180 | .remove = __devexit_p(parport_pc_pci_remove), |
| 3091 | }; | 3181 | }; |
| 3092 | 3182 | ||
| 3093 | static int __init parport_pc_init_superio (int autoirq, int autodma) | 3183 | static int __init parport_pc_init_superio(int autoirq, int autodma) |
| 3094 | { | 3184 | { |
| 3095 | const struct pci_device_id *id; | 3185 | const struct pci_device_id *id; |
| 3096 | struct pci_dev *pdev = NULL; | 3186 | struct pci_dev *pdev = NULL; |
| @@ -3101,8 +3191,9 @@ static int __init parport_pc_init_superio (int autoirq, int autodma) | |||
| 3101 | if (id == NULL || id->driver_data >= last_sio) | 3191 | if (id == NULL || id->driver_data >= last_sio) |
| 3102 | continue; | 3192 | continue; |
| 3103 | 3193 | ||
| 3104 | if (parport_pc_superio_info[id->driver_data].probe | 3194 | if (parport_pc_superio_info[id->driver_data].probe( |
| 3105 | (pdev, autoirq, autodma,parport_pc_superio_info[id->driver_data].via)) { | 3195 | pdev, autoirq, autodma, |
| 3196 | parport_pc_superio_info[id->driver_data].via)) { | ||
| 3106 | ret++; | 3197 | ret++; |
| 3107 | } | 3198 | } |
| 3108 | } | 3199 | } |
| @@ -3111,7 +3202,10 @@ static int __init parport_pc_init_superio (int autoirq, int autodma) | |||
| 3111 | } | 3202 | } |
| 3112 | #else | 3203 | #else |
| 3113 | static struct pci_driver parport_pc_pci_driver; | 3204 | static struct pci_driver parport_pc_pci_driver; |
| 3114 | static int __init parport_pc_init_superio(int autoirq, int autodma) {return 0;} | 3205 | static int __init parport_pc_init_superio(int autoirq, int autodma) |
| 3206 | { | ||
| 3207 | return 0; | ||
| 3208 | } | ||
| 3115 | #endif /* CONFIG_PCI */ | 3209 | #endif /* CONFIG_PCI */ |
| 3116 | 3210 | ||
| 3117 | #ifdef CONFIG_PNP | 3211 | #ifdef CONFIG_PNP |
| @@ -3124,44 +3218,45 @@ static const struct pnp_device_id parport_pc_pnp_tbl[] = { | |||
| 3124 | { } | 3218 | { } |
| 3125 | }; | 3219 | }; |
| 3126 | 3220 | ||
| 3127 | MODULE_DEVICE_TABLE(pnp,parport_pc_pnp_tbl); | 3221 | MODULE_DEVICE_TABLE(pnp, parport_pc_pnp_tbl); |
| 3128 | 3222 | ||
| 3129 | static int parport_pc_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *id) | 3223 | static int parport_pc_pnp_probe(struct pnp_dev *dev, |
| 3224 | const struct pnp_device_id *id) | ||
| 3130 | { | 3225 | { |
| 3131 | struct parport *pdata; | 3226 | struct parport *pdata; |
| 3132 | unsigned long io_lo, io_hi; | 3227 | unsigned long io_lo, io_hi; |
| 3133 | int dma, irq; | 3228 | int dma, irq; |
| 3134 | 3229 | ||
| 3135 | if (pnp_port_valid(dev,0) && | 3230 | if (pnp_port_valid(dev, 0) && |
| 3136 | !(pnp_port_flags(dev,0) & IORESOURCE_DISABLED)) { | 3231 | !(pnp_port_flags(dev, 0) & IORESOURCE_DISABLED)) { |
| 3137 | io_lo = pnp_port_start(dev,0); | 3232 | io_lo = pnp_port_start(dev, 0); |
| 3138 | } else | 3233 | } else |
| 3139 | return -EINVAL; | 3234 | return -EINVAL; |
| 3140 | 3235 | ||
| 3141 | if (pnp_port_valid(dev,1) && | 3236 | if (pnp_port_valid(dev, 1) && |
| 3142 | !(pnp_port_flags(dev,1) & IORESOURCE_DISABLED)) { | 3237 | !(pnp_port_flags(dev, 1) & IORESOURCE_DISABLED)) { |
| 3143 | io_hi = pnp_port_start(dev,1); | 3238 | io_hi = pnp_port_start(dev, 1); |
| 3144 | } else | 3239 | } else |
| 3145 | io_hi = 0; | 3240 | io_hi = 0; |
| 3146 | 3241 | ||
| 3147 | if (pnp_irq_valid(dev,0) && | 3242 | if (pnp_irq_valid(dev, 0) && |
| 3148 | !(pnp_irq_flags(dev,0) & IORESOURCE_DISABLED)) { | 3243 | !(pnp_irq_flags(dev, 0) & IORESOURCE_DISABLED)) { |
| 3149 | irq = pnp_irq(dev,0); | 3244 | irq = pnp_irq(dev, 0); |
| 3150 | } else | 3245 | } else |
| 3151 | irq = PARPORT_IRQ_NONE; | 3246 | irq = PARPORT_IRQ_NONE; |
| 3152 | 3247 | ||
| 3153 | if (pnp_dma_valid(dev,0) && | 3248 | if (pnp_dma_valid(dev, 0) && |
| 3154 | !(pnp_dma_flags(dev,0) & IORESOURCE_DISABLED)) { | 3249 | !(pnp_dma_flags(dev, 0) & IORESOURCE_DISABLED)) { |
| 3155 | dma = pnp_dma(dev,0); | 3250 | dma = pnp_dma(dev, 0); |
| 3156 | } else | 3251 | } else |
| 3157 | dma = PARPORT_DMA_NONE; | 3252 | dma = PARPORT_DMA_NONE; |
| 3158 | 3253 | ||
| 3159 | dev_info(&dev->dev, "reported by %s\n", dev->protocol->name); | 3254 | dev_info(&dev->dev, "reported by %s\n", dev->protocol->name); |
| 3160 | if (!(pdata = parport_pc_probe_port(io_lo, io_hi, | 3255 | pdata = parport_pc_probe_port(io_lo, io_hi, irq, dma, &dev->dev, 0); |
| 3161 | irq, dma, &dev->dev, 0))) | 3256 | if (pdata == NULL) |
| 3162 | return -ENODEV; | 3257 | return -ENODEV; |
| 3163 | 3258 | ||
| 3164 | pnp_set_drvdata(dev,pdata); | 3259 | pnp_set_drvdata(dev, pdata); |
| 3165 | return 0; | 3260 | return 0; |
| 3166 | } | 3261 | } |
| 3167 | 3262 | ||
| @@ -3203,7 +3298,7 @@ static struct platform_driver parport_pc_platform_driver = { | |||
| 3203 | 3298 | ||
| 3204 | /* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */ | 3299 | /* This is called by parport_pc_find_nonpci_ports (in asm/parport.h) */ |
| 3205 | static int __devinit __attribute__((unused)) | 3300 | static int __devinit __attribute__((unused)) |
| 3206 | parport_pc_find_isa_ports (int autoirq, int autodma) | 3301 | parport_pc_find_isa_ports(int autoirq, int autodma) |
| 3207 | { | 3302 | { |
| 3208 | int count = 0; | 3303 | int count = 0; |
| 3209 | 3304 | ||
| @@ -3227,7 +3322,7 @@ parport_pc_find_isa_ports (int autoirq, int autodma) | |||
| 3227 | * autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY | 3322 | * autoirq is PARPORT_IRQ_NONE, PARPORT_IRQ_AUTO, or PARPORT_IRQ_PROBEONLY |
| 3228 | * autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO | 3323 | * autodma is PARPORT_DMA_NONE or PARPORT_DMA_AUTO |
| 3229 | */ | 3324 | */ |
| 3230 | static void __init parport_pc_find_ports (int autoirq, int autodma) | 3325 | static void __init parport_pc_find_ports(int autoirq, int autodma) |
| 3231 | { | 3326 | { |
| 3232 | int count = 0, err; | 3327 | int count = 0, err; |
| 3233 | 3328 | ||
| @@ -3261,11 +3356,18 @@ static void __init parport_pc_find_ports (int autoirq, int autodma) | |||
| 3261 | * syntax and keep in mind that code below is a cleaned up version. | 3356 | * syntax and keep in mind that code below is a cleaned up version. |
| 3262 | */ | 3357 | */ |
| 3263 | 3358 | ||
| 3264 | static int __initdata io[PARPORT_PC_MAX_PORTS+1] = { [0 ... PARPORT_PC_MAX_PORTS] = 0 }; | 3359 | static int __initdata io[PARPORT_PC_MAX_PORTS+1] = { |
| 3265 | static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] = | 3360 | [0 ... PARPORT_PC_MAX_PORTS] = 0 |
| 3266 | { [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO }; | 3361 | }; |
| 3267 | static int __initdata dmaval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE }; | 3362 | static int __initdata io_hi[PARPORT_PC_MAX_PORTS+1] = { |
| 3268 | static int __initdata irqval[PARPORT_PC_MAX_PORTS] = { [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY }; | 3363 | [0 ... PARPORT_PC_MAX_PORTS] = PARPORT_IOHI_AUTO |
| 3364 | }; | ||
| 3365 | static int __initdata dmaval[PARPORT_PC_MAX_PORTS] = { | ||
| 3366 | [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_DMA_NONE | ||
| 3367 | }; | ||
| 3368 | static int __initdata irqval[PARPORT_PC_MAX_PORTS] = { | ||
| 3369 | [0 ... PARPORT_PC_MAX_PORTS-1] = PARPORT_IRQ_PROBEONLY | ||
| 3370 | }; | ||
| 3269 | 3371 | ||
| 3270 | static int __init parport_parse_param(const char *s, int *val, | 3372 | static int __init parport_parse_param(const char *s, int *val, |
| 3271 | int automatic, int none, int nofifo) | 3373 | int automatic, int none, int nofifo) |
| @@ -3306,18 +3408,19 @@ static int __init parport_parse_dma(const char *dmastr, int *val) | |||
| 3306 | #ifdef CONFIG_PCI | 3408 | #ifdef CONFIG_PCI |
| 3307 | static int __init parport_init_mode_setup(char *str) | 3409 | static int __init parport_init_mode_setup(char *str) |
| 3308 | { | 3410 | { |
| 3309 | printk(KERN_DEBUG "parport_pc.c: Specified parameter parport_init_mode=%s\n", str); | 3411 | printk(KERN_DEBUG |
| 3310 | 3412 | "parport_pc.c: Specified parameter parport_init_mode=%s\n", str); | |
| 3311 | if (!strcmp (str, "spp")) | 3413 | |
| 3312 | parport_init_mode=1; | 3414 | if (!strcmp(str, "spp")) |
| 3313 | if (!strcmp (str, "ps2")) | 3415 | parport_init_mode = 1; |
| 3314 | parport_init_mode=2; | 3416 | if (!strcmp(str, "ps2")) |
| 3315 | if (!strcmp (str, "epp")) | 3417 | parport_init_mode = 2; |
| 3316 | parport_init_mode=3; | 3418 | if (!strcmp(str, "epp")) |
| 3317 | if (!strcmp (str, "ecp")) | 3419 | parport_init_mode = 3; |
| 3318 | parport_init_mode=4; | 3420 | if (!strcmp(str, "ecp")) |
| 3319 | if (!strcmp (str, "ecpepp")) | 3421 | parport_init_mode = 4; |
| 3320 | parport_init_mode=5; | 3422 | if (!strcmp(str, "ecpepp")) |
| 3423 | parport_init_mode = 5; | ||
| 3321 | return 1; | 3424 | return 1; |
| 3322 | } | 3425 | } |
| 3323 | #endif | 3426 | #endif |
| @@ -3341,7 +3444,8 @@ module_param(verbose_probing, int, 0644); | |||
| 3341 | #endif | 3444 | #endif |
| 3342 | #ifdef CONFIG_PCI | 3445 | #ifdef CONFIG_PCI |
| 3343 | static char *init_mode; | 3446 | static char *init_mode; |
| 3344 | MODULE_PARM_DESC(init_mode, "Initialise mode for VIA VT8231 port (spp, ps2, epp, ecp or ecpepp)"); | 3447 | MODULE_PARM_DESC(init_mode, |
| 3448 | "Initialise mode for VIA VT8231 port (spp, ps2, epp, ecp or ecpepp)"); | ||
| 3345 | module_param(init_mode, charp, 0); | 3449 | module_param(init_mode, charp, 0); |
| 3346 | #endif | 3450 | #endif |
| 3347 | 3451 | ||
| @@ -3372,7 +3476,7 @@ static int __init parse_parport_params(void) | |||
| 3372 | irqval[0] = val; | 3476 | irqval[0] = val; |
| 3373 | break; | 3477 | break; |
| 3374 | default: | 3478 | default: |
| 3375 | printk (KERN_WARNING | 3479 | printk(KERN_WARNING |
| 3376 | "parport_pc: irq specified " | 3480 | "parport_pc: irq specified " |
| 3377 | "without base address. Use 'io=' " | 3481 | "without base address. Use 'io=' " |
| 3378 | "to specify one\n"); | 3482 | "to specify one\n"); |
| @@ -3385,7 +3489,7 @@ static int __init parse_parport_params(void) | |||
| 3385 | dmaval[0] = val; | 3489 | dmaval[0] = val; |
| 3386 | break; | 3490 | break; |
| 3387 | default: | 3491 | default: |
| 3388 | printk (KERN_WARNING | 3492 | printk(KERN_WARNING |
| 3389 | "parport_pc: dma specified " | 3493 | "parport_pc: dma specified " |
| 3390 | "without base address. Use 'io=' " | 3494 | "without base address. Use 'io=' " |
| 3391 | "to specify one\n"); | 3495 | "to specify one\n"); |
| @@ -3396,7 +3500,7 @@ static int __init parse_parport_params(void) | |||
| 3396 | 3500 | ||
| 3397 | #else | 3501 | #else |
| 3398 | 3502 | ||
| 3399 | static int parport_setup_ptr __initdata = 0; | 3503 | static int parport_setup_ptr __initdata; |
| 3400 | 3504 | ||
| 3401 | /* | 3505 | /* |
| 3402 | * Acceptable parameters: | 3506 | * Acceptable parameters: |
| @@ -3407,7 +3511,7 @@ static int parport_setup_ptr __initdata = 0; | |||
| 3407 | * | 3511 | * |
| 3408 | * IRQ/DMA may be numeric or 'auto' or 'none' | 3512 | * IRQ/DMA may be numeric or 'auto' or 'none' |
| 3409 | */ | 3513 | */ |
| 3410 | static int __init parport_setup (char *str) | 3514 | static int __init parport_setup(char *str) |
| 3411 | { | 3515 | { |
| 3412 | char *endptr; | 3516 | char *endptr; |
| 3413 | char *sep; | 3517 | char *sep; |
| @@ -3419,15 +3523,15 @@ static int __init parport_setup (char *str) | |||
| 3419 | return 1; | 3523 | return 1; |
| 3420 | } | 3524 | } |
| 3421 | 3525 | ||
| 3422 | if (!strncmp (str, "auto", 4)) { | 3526 | if (!strncmp(str, "auto", 4)) { |
| 3423 | irqval[0] = PARPORT_IRQ_AUTO; | 3527 | irqval[0] = PARPORT_IRQ_AUTO; |
| 3424 | dmaval[0] = PARPORT_DMA_AUTO; | 3528 | dmaval[0] = PARPORT_DMA_AUTO; |
| 3425 | return 1; | 3529 | return 1; |
| 3426 | } | 3530 | } |
| 3427 | 3531 | ||
| 3428 | val = simple_strtoul (str, &endptr, 0); | 3532 | val = simple_strtoul(str, &endptr, 0); |
| 3429 | if (endptr == str) { | 3533 | if (endptr == str) { |
| 3430 | printk (KERN_WARNING "parport=%s not understood\n", str); | 3534 | printk(KERN_WARNING "parport=%s not understood\n", str); |
| 3431 | return 1; | 3535 | return 1; |
| 3432 | } | 3536 | } |
| 3433 | 3537 | ||
| @@ -3461,7 +3565,7 @@ static int __init parse_parport_params(void) | |||
| 3461 | return io[0] == PARPORT_DISABLE; | 3565 | return io[0] == PARPORT_DISABLE; |
| 3462 | } | 3566 | } |
| 3463 | 3567 | ||
| 3464 | __setup ("parport=", parport_setup); | 3568 | __setup("parport=", parport_setup); |
| 3465 | 3569 | ||
| 3466 | /* | 3570 | /* |
| 3467 | * Acceptable parameters: | 3571 | * Acceptable parameters: |
| @@ -3469,7 +3573,7 @@ __setup ("parport=", parport_setup); | |||
| 3469 | * parport_init_mode=[spp|ps2|epp|ecp|ecpepp] | 3573 | * parport_init_mode=[spp|ps2|epp|ecp|ecpepp] |
| 3470 | */ | 3574 | */ |
| 3471 | #ifdef CONFIG_PCI | 3575 | #ifdef CONFIG_PCI |
| 3472 | __setup("parport_init_mode=",parport_init_mode_setup); | 3576 | __setup("parport_init_mode=", parport_init_mode_setup); |
| 3473 | #endif | 3577 | #endif |
| 3474 | #endif | 3578 | #endif |
| 3475 | 3579 | ||
| @@ -3493,13 +3597,13 @@ static int __init parport_pc_init(void) | |||
| 3493 | for (i = 0; i < PARPORT_PC_MAX_PORTS; i++) { | 3597 | for (i = 0; i < PARPORT_PC_MAX_PORTS; i++) { |
| 3494 | if (!io[i]) | 3598 | if (!io[i]) |
| 3495 | break; | 3599 | break; |
| 3496 | if ((io_hi[i]) == PARPORT_IOHI_AUTO) | 3600 | if (io_hi[i] == PARPORT_IOHI_AUTO) |
| 3497 | io_hi[i] = 0x400 + io[i]; | 3601 | io_hi[i] = 0x400 + io[i]; |
| 3498 | parport_pc_probe_port(io[i], io_hi[i], | 3602 | parport_pc_probe_port(io[i], io_hi[i], |
| 3499 | irqval[i], dmaval[i], NULL, 0); | 3603 | irqval[i], dmaval[i], NULL, 0); |
| 3500 | } | 3604 | } |
| 3501 | } else | 3605 | } else |
| 3502 | parport_pc_find_ports (irqval[0], dmaval[0]); | 3606 | parport_pc_find_ports(irqval[0], dmaval[0]); |
| 3503 | 3607 | ||
| 3504 | return 0; | 3608 | return 0; |
| 3505 | } | 3609 | } |
| @@ -3507,9 +3611,9 @@ static int __init parport_pc_init(void) | |||
| 3507 | static void __exit parport_pc_exit(void) | 3611 | static void __exit parport_pc_exit(void) |
| 3508 | { | 3612 | { |
| 3509 | if (pci_registered_parport) | 3613 | if (pci_registered_parport) |
| 3510 | pci_unregister_driver (&parport_pc_pci_driver); | 3614 | pci_unregister_driver(&parport_pc_pci_driver); |
| 3511 | if (pnp_registered_parport) | 3615 | if (pnp_registered_parport) |
| 3512 | pnp_unregister_driver (&parport_pc_pnp_driver); | 3616 | pnp_unregister_driver(&parport_pc_pnp_driver); |
| 3513 | platform_driver_unregister(&parport_pc_platform_driver); | 3617 | platform_driver_unregister(&parport_pc_platform_driver); |
| 3514 | 3618 | ||
| 3515 | while (!list_empty(&ports_list)) { | 3619 | while (!list_empty(&ports_list)) { |
diff --git a/drivers/parport/share.c b/drivers/parport/share.c index 0ebca450ed29..dffa5d4fb298 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c | |||
| @@ -614,7 +614,10 @@ parport_register_device(struct parport *port, const char *name, | |||
| 614 | * pardevice fields. -arca | 614 | * pardevice fields. -arca |
| 615 | */ | 615 | */ |
| 616 | port->ops->init_state(tmp, tmp->state); | 616 | port->ops->init_state(tmp, tmp->state); |
| 617 | parport_device_proc_register(tmp); | 617 | if (!test_and_set_bit(PARPORT_DEVPROC_REGISTERED, &port->devflags)) { |
| 618 | port->proc_device = tmp; | ||
| 619 | parport_device_proc_register(tmp); | ||
| 620 | } | ||
| 618 | return tmp; | 621 | return tmp; |
| 619 | 622 | ||
| 620 | out_free_all: | 623 | out_free_all: |
| @@ -646,10 +649,14 @@ void parport_unregister_device(struct pardevice *dev) | |||
| 646 | } | 649 | } |
| 647 | #endif | 650 | #endif |
| 648 | 651 | ||
| 649 | parport_device_proc_unregister(dev); | ||
| 650 | |||
| 651 | port = dev->port->physport; | 652 | port = dev->port->physport; |
| 652 | 653 | ||
| 654 | if (port->proc_device == dev) { | ||
| 655 | port->proc_device = NULL; | ||
| 656 | clear_bit(PARPORT_DEVPROC_REGISTERED, &port->devflags); | ||
| 657 | parport_device_proc_unregister(dev); | ||
| 658 | } | ||
| 659 | |||
| 653 | if (port->cad == dev) { | 660 | if (port->cad == dev) { |
| 654 | printk(KERN_DEBUG "%s: %s forgot to release port\n", | 661 | printk(KERN_DEBUG "%s: %s forgot to release port\n", |
| 655 | port->name, dev->name); | 662 | port->name, dev->name); |
diff --git a/drivers/pci/hotplug/acpiphp.h b/drivers/pci/hotplug/acpiphp.h index 4fc168b70095..e68d5f20ffb3 100644 --- a/drivers/pci/hotplug/acpiphp.h +++ b/drivers/pci/hotplug/acpiphp.h | |||
| @@ -129,7 +129,6 @@ struct acpiphp_func { | |||
| 129 | struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ | 129 | struct acpiphp_bridge *bridge; /* Ejectable PCI-to-PCI bridge */ |
| 130 | 130 | ||
| 131 | struct list_head sibling; | 131 | struct list_head sibling; |
| 132 | struct pci_dev *pci_dev; | ||
| 133 | struct notifier_block nb; | 132 | struct notifier_block nb; |
| 134 | acpi_handle handle; | 133 | acpi_handle handle; |
| 135 | 134 | ||
diff --git a/drivers/pci/hotplug/acpiphp_glue.c b/drivers/pci/hotplug/acpiphp_glue.c index a33794d9e0dc..3a6064bce561 100644 --- a/drivers/pci/hotplug/acpiphp_glue.c +++ b/drivers/pci/hotplug/acpiphp_glue.c | |||
| @@ -32,9 +32,6 @@ | |||
| 32 | 32 | ||
| 33 | /* | 33 | /* |
| 34 | * Lifetime rules for pci_dev: | 34 | * Lifetime rules for pci_dev: |
| 35 | * - The one in acpiphp_func has its refcount elevated by pci_get_slot() | ||
| 36 | * when the driver is loaded or when an insertion event occurs. It loses | ||
| 37 | * a refcount when its ejected or the driver unloads. | ||
| 38 | * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() | 35 | * - The one in acpiphp_bridge has its refcount elevated by pci_get_slot() |
| 39 | * when the bridge is scanned and it loses a refcount when the bridge | 36 | * when the bridge is scanned and it loses a refcount when the bridge |
| 40 | * is removed. | 37 | * is removed. |
| @@ -130,6 +127,7 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 130 | unsigned long long adr, sun; | 127 | unsigned long long adr, sun; |
| 131 | int device, function, retval; | 128 | int device, function, retval; |
| 132 | struct pci_bus *pbus = bridge->pci_bus; | 129 | struct pci_bus *pbus = bridge->pci_bus; |
| 130 | struct pci_dev *pdev; | ||
| 133 | 131 | ||
| 134 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) | 132 | if (!acpi_pci_check_ejectable(pbus, handle) && !is_dock_device(handle)) |
| 135 | return AE_OK; | 133 | return AE_OK; |
| @@ -213,10 +211,10 @@ register_slot(acpi_handle handle, u32 lvl, void *context, void **rv) | |||
| 213 | newfunc->slot = slot; | 211 | newfunc->slot = slot; |
| 214 | list_add_tail(&newfunc->sibling, &slot->funcs); | 212 | list_add_tail(&newfunc->sibling, &slot->funcs); |
| 215 | 213 | ||
| 216 | /* associate corresponding pci_dev */ | 214 | pdev = pci_get_slot(pbus, PCI_DEVFN(device, function)); |
| 217 | newfunc->pci_dev = pci_get_slot(pbus, PCI_DEVFN(device, function)); | 215 | if (pdev) { |
| 218 | if (newfunc->pci_dev) { | ||
| 219 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); | 216 | slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON); |
| 217 | pci_dev_put(pdev); | ||
| 220 | } | 218 | } |
| 221 | 219 | ||
| 222 | if (is_dock_device(handle)) { | 220 | if (is_dock_device(handle)) { |
| @@ -617,7 +615,6 @@ static void cleanup_bridge(struct acpiphp_bridge *bridge) | |||
| 617 | if (ACPI_FAILURE(status)) | 615 | if (ACPI_FAILURE(status)) |
| 618 | err("failed to remove notify handler\n"); | 616 | err("failed to remove notify handler\n"); |
| 619 | } | 617 | } |
| 620 | pci_dev_put(func->pci_dev); | ||
| 621 | list_del(list); | 618 | list_del(list); |
| 622 | kfree(func); | 619 | kfree(func); |
| 623 | } | 620 | } |
| @@ -1101,22 +1098,24 @@ static int __ref enable_device(struct acpiphp_slot *slot) | |||
| 1101 | pci_enable_bridges(bus); | 1098 | pci_enable_bridges(bus); |
| 1102 | pci_bus_add_devices(bus); | 1099 | pci_bus_add_devices(bus); |
| 1103 | 1100 | ||
| 1104 | /* associate pci_dev to our representation */ | ||
| 1105 | list_for_each (l, &slot->funcs) { | 1101 | list_for_each (l, &slot->funcs) { |
| 1106 | func = list_entry(l, struct acpiphp_func, sibling); | 1102 | func = list_entry(l, struct acpiphp_func, sibling); |
| 1107 | func->pci_dev = pci_get_slot(bus, PCI_DEVFN(slot->device, | 1103 | dev = pci_get_slot(bus, PCI_DEVFN(slot->device, |
| 1108 | func->function)); | 1104 | func->function)); |
| 1109 | if (!func->pci_dev) | 1105 | if (!dev) |
| 1110 | continue; | 1106 | continue; |
| 1111 | 1107 | ||
| 1112 | if (func->pci_dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && | 1108 | if (dev->hdr_type != PCI_HEADER_TYPE_BRIDGE && |
| 1113 | func->pci_dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) | 1109 | dev->hdr_type != PCI_HEADER_TYPE_CARDBUS) { |
| 1110 | pci_dev_put(dev); | ||
| 1114 | continue; | 1111 | continue; |
| 1112 | } | ||
| 1115 | 1113 | ||
| 1116 | status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); | 1114 | status = find_p2p_bridge(func->handle, (u32)1, bus, NULL); |
| 1117 | if (ACPI_FAILURE(status)) | 1115 | if (ACPI_FAILURE(status)) |
| 1118 | warn("find_p2p_bridge failed (error code = 0x%x)\n", | 1116 | warn("find_p2p_bridge failed (error code = 0x%x)\n", |
| 1119 | status); | 1117 | status); |
| 1118 | pci_dev_put(dev); | ||
| 1120 | } | 1119 | } |
| 1121 | 1120 | ||
| 1122 | slot->flags |= SLOT_ENABLED; | 1121 | slot->flags |= SLOT_ENABLED; |
| @@ -1142,17 +1141,14 @@ static void disable_bridges(struct pci_bus *bus) | |||
| 1142 | */ | 1141 | */ |
| 1143 | static int disable_device(struct acpiphp_slot *slot) | 1142 | static int disable_device(struct acpiphp_slot *slot) |
| 1144 | { | 1143 | { |
| 1145 | int retval = 0; | ||
| 1146 | struct acpiphp_func *func; | 1144 | struct acpiphp_func *func; |
| 1147 | struct list_head *l; | 1145 | struct pci_dev *pdev; |
| 1148 | 1146 | ||
| 1149 | /* is this slot already disabled? */ | 1147 | /* is this slot already disabled? */ |
| 1150 | if (!(slot->flags & SLOT_ENABLED)) | 1148 | if (!(slot->flags & SLOT_ENABLED)) |
| 1151 | goto err_exit; | 1149 | goto err_exit; |
| 1152 | 1150 | ||
| 1153 | list_for_each (l, &slot->funcs) { | 1151 | list_for_each_entry(func, &slot->funcs, sibling) { |
| 1154 | func = list_entry(l, struct acpiphp_func, sibling); | ||
| 1155 | |||
| 1156 | if (func->bridge) { | 1152 | if (func->bridge) { |
| 1157 | /* cleanup p2p bridges under this P2P bridge */ | 1153 | /* cleanup p2p bridges under this P2P bridge */ |
| 1158 | cleanup_p2p_bridge(func->bridge->handle, | 1154 | cleanup_p2p_bridge(func->bridge->handle, |
| @@ -1160,35 +1156,28 @@ static int disable_device(struct acpiphp_slot *slot) | |||
| 1160 | func->bridge = NULL; | 1156 | func->bridge = NULL; |
| 1161 | } | 1157 | } |
| 1162 | 1158 | ||
| 1163 | if (func->pci_dev) { | 1159 | pdev = pci_get_slot(slot->bridge->pci_bus, |
| 1164 | pci_stop_bus_device(func->pci_dev); | 1160 | PCI_DEVFN(slot->device, func->function)); |
| 1165 | if (func->pci_dev->subordinate) { | 1161 | if (pdev) { |
| 1166 | disable_bridges(func->pci_dev->subordinate); | 1162 | pci_stop_bus_device(pdev); |
| 1167 | pci_disable_device(func->pci_dev); | 1163 | if (pdev->subordinate) { |
| 1164 | disable_bridges(pdev->subordinate); | ||
| 1165 | pci_disable_device(pdev); | ||
| 1168 | } | 1166 | } |
| 1167 | pci_remove_bus_device(pdev); | ||
| 1168 | pci_dev_put(pdev); | ||
| 1169 | } | 1169 | } |
| 1170 | } | 1170 | } |
| 1171 | 1171 | ||
| 1172 | list_for_each (l, &slot->funcs) { | 1172 | list_for_each_entry(func, &slot->funcs, sibling) { |
| 1173 | func = list_entry(l, struct acpiphp_func, sibling); | ||
| 1174 | |||
| 1175 | acpiphp_unconfigure_ioapics(func->handle); | 1173 | acpiphp_unconfigure_ioapics(func->handle); |
| 1176 | acpiphp_bus_trim(func->handle); | 1174 | acpiphp_bus_trim(func->handle); |
| 1177 | /* try to remove anyway. | ||
| 1178 | * acpiphp_bus_add might have been failed */ | ||
| 1179 | |||
| 1180 | if (!func->pci_dev) | ||
| 1181 | continue; | ||
| 1182 | |||
| 1183 | pci_remove_bus_device(func->pci_dev); | ||
| 1184 | pci_dev_put(func->pci_dev); | ||
| 1185 | func->pci_dev = NULL; | ||
| 1186 | } | 1175 | } |
| 1187 | 1176 | ||
| 1188 | slot->flags &= (~SLOT_ENABLED); | 1177 | slot->flags &= (~SLOT_ENABLED); |
| 1189 | 1178 | ||
| 1190 | err_exit: | 1179 | err_exit: |
| 1191 | return retval; | 1180 | return 0; |
| 1192 | } | 1181 | } |
| 1193 | 1182 | ||
| 1194 | 1183 | ||
diff --git a/drivers/pci/hotplug/ibmphp_core.c b/drivers/pci/hotplug/ibmphp_core.c index dd18f857dfb0..42e4260c3b12 100644 --- a/drivers/pci/hotplug/ibmphp_core.c +++ b/drivers/pci/hotplug/ibmphp_core.c | |||
| @@ -153,45 +153,47 @@ int ibmphp_init_devno(struct slot **cur_slot) | |||
| 153 | return -1; | 153 | return -1; |
| 154 | } | 154 | } |
| 155 | for (loop = 0; loop < len; loop++) { | 155 | for (loop = 0; loop < len; loop++) { |
| 156 | if ((*cur_slot)->number == rtable->slots[loop].slot) { | 156 | if ((*cur_slot)->number == rtable->slots[loop].slot && |
| 157 | if ((*cur_slot)->bus == rtable->slots[loop].bus) { | 157 | (*cur_slot)->bus == rtable->slots[loop].bus) { |
| 158 | struct io_apic_irq_attr irq_attr; | ||
| 159 | |||
| 158 | (*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn); | 160 | (*cur_slot)->device = PCI_SLOT(rtable->slots[loop].devfn); |
| 159 | for (i = 0; i < 4; i++) | 161 | for (i = 0; i < 4; i++) |
| 160 | (*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus, | 162 | (*cur_slot)->irq[i] = IO_APIC_get_PCI_irq_vector((int) (*cur_slot)->bus, |
| 161 | (int) (*cur_slot)->device, i); | 163 | (int) (*cur_slot)->device, i, |
| 162 | 164 | &irq_attr); | |
| 163 | debug("(*cur_slot)->irq[0] = %x\n", | 165 | |
| 164 | (*cur_slot)->irq[0]); | 166 | debug("(*cur_slot)->irq[0] = %x\n", |
| 165 | debug("(*cur_slot)->irq[1] = %x\n", | 167 | (*cur_slot)->irq[0]); |
| 166 | (*cur_slot)->irq[1]); | 168 | debug("(*cur_slot)->irq[1] = %x\n", |
| 167 | debug("(*cur_slot)->irq[2] = %x\n", | 169 | (*cur_slot)->irq[1]); |
| 168 | (*cur_slot)->irq[2]); | 170 | debug("(*cur_slot)->irq[2] = %x\n", |
| 169 | debug("(*cur_slot)->irq[3] = %x\n", | 171 | (*cur_slot)->irq[2]); |
| 170 | (*cur_slot)->irq[3]); | 172 | debug("(*cur_slot)->irq[3] = %x\n", |
| 171 | 173 | (*cur_slot)->irq[3]); | |
| 172 | debug("rtable->exlusive_irqs = %x\n", | 174 | |
| 175 | debug("rtable->exlusive_irqs = %x\n", | ||
| 173 | rtable->exclusive_irqs); | 176 | rtable->exclusive_irqs); |
| 174 | debug("rtable->slots[loop].irq[0].bitmap = %x\n", | 177 | debug("rtable->slots[loop].irq[0].bitmap = %x\n", |
| 175 | rtable->slots[loop].irq[0].bitmap); | 178 | rtable->slots[loop].irq[0].bitmap); |
| 176 | debug("rtable->slots[loop].irq[1].bitmap = %x\n", | 179 | debug("rtable->slots[loop].irq[1].bitmap = %x\n", |
| 177 | rtable->slots[loop].irq[1].bitmap); | 180 | rtable->slots[loop].irq[1].bitmap); |
| 178 | debug("rtable->slots[loop].irq[2].bitmap = %x\n", | 181 | debug("rtable->slots[loop].irq[2].bitmap = %x\n", |
| 179 | rtable->slots[loop].irq[2].bitmap); | 182 | rtable->slots[loop].irq[2].bitmap); |
| 180 | debug("rtable->slots[loop].irq[3].bitmap = %x\n", | 183 | debug("rtable->slots[loop].irq[3].bitmap = %x\n", |
| 181 | rtable->slots[loop].irq[3].bitmap); | 184 | rtable->slots[loop].irq[3].bitmap); |
| 182 | 185 | ||
| 183 | debug("rtable->slots[loop].irq[0].link = %x\n", | 186 | debug("rtable->slots[loop].irq[0].link = %x\n", |
| 184 | rtable->slots[loop].irq[0].link); | 187 | rtable->slots[loop].irq[0].link); |
| 185 | debug("rtable->slots[loop].irq[1].link = %x\n", | 188 | debug("rtable->slots[loop].irq[1].link = %x\n", |
| 186 | rtable->slots[loop].irq[1].link); | 189 | rtable->slots[loop].irq[1].link); |
| 187 | debug("rtable->slots[loop].irq[2].link = %x\n", | 190 | debug("rtable->slots[loop].irq[2].link = %x\n", |
| 188 | rtable->slots[loop].irq[2].link); | 191 | rtable->slots[loop].irq[2].link); |
| 189 | debug("rtable->slots[loop].irq[3].link = %x\n", | 192 | debug("rtable->slots[loop].irq[3].link = %x\n", |
| 190 | rtable->slots[loop].irq[3].link); | 193 | rtable->slots[loop].irq[3].link); |
| 191 | debug("end of init_devno\n"); | 194 | debug("end of init_devno\n"); |
| 192 | kfree(rtable); | 195 | kfree(rtable); |
| 193 | return 0; | 196 | return 0; |
| 194 | } | ||
| 195 | } | 197 | } |
| 196 | } | 198 | } |
| 197 | 199 | ||
diff --git a/drivers/pci/htirq.c b/drivers/pci/htirq.c index 6808d8333ecc..737a1c44b07a 100644 --- a/drivers/pci/htirq.c +++ b/drivers/pci/htirq.c | |||
| @@ -98,6 +98,7 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) | |||
| 98 | int max_irq; | 98 | int max_irq; |
| 99 | int pos; | 99 | int pos; |
| 100 | int irq; | 100 | int irq; |
| 101 | int node; | ||
| 101 | 102 | ||
| 102 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); | 103 | pos = pci_find_ht_capability(dev, HT_CAPTYPE_IRQ); |
| 103 | if (!pos) | 104 | if (!pos) |
| @@ -125,7 +126,8 @@ int __ht_create_irq(struct pci_dev *dev, int idx, ht_irq_update_t *update) | |||
| 125 | cfg->msg.address_lo = 0xffffffff; | 126 | cfg->msg.address_lo = 0xffffffff; |
| 126 | cfg->msg.address_hi = 0xffffffff; | 127 | cfg->msg.address_hi = 0xffffffff; |
| 127 | 128 | ||
| 128 | irq = create_irq(); | 129 | node = dev_to_node(&dev->dev); |
| 130 | irq = create_irq_nr(0, node); | ||
| 129 | 131 | ||
| 130 | if (irq <= 0) { | 132 | if (irq <= 0) { |
| 131 | kfree(cfg); | 133 | kfree(cfg); |
diff --git a/drivers/pci/intel-iommu.c b/drivers/pci/intel-iommu.c index a563fbe559d0..cd389162735f 100644 --- a/drivers/pci/intel-iommu.c +++ b/drivers/pci/intel-iommu.c | |||
| @@ -1972,15 +1972,6 @@ static int __init init_dmars(void) | |||
| 1972 | } | 1972 | } |
| 1973 | } | 1973 | } |
| 1974 | 1974 | ||
| 1975 | #ifdef CONFIG_INTR_REMAP | ||
| 1976 | if (!intr_remapping_enabled) { | ||
| 1977 | ret = enable_intr_remapping(0); | ||
| 1978 | if (ret) | ||
| 1979 | printk(KERN_ERR | ||
| 1980 | "IOMMU: enable interrupt remapping failed\n"); | ||
| 1981 | } | ||
| 1982 | #endif | ||
| 1983 | |||
| 1984 | /* | 1975 | /* |
| 1985 | * For each rmrr | 1976 | * For each rmrr |
| 1986 | * for each dev attached to rmrr | 1977 | * for each dev attached to rmrr |
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c index f5e0ea724a6f..3a0cb0bb0593 100644 --- a/drivers/pci/intr_remapping.c +++ b/drivers/pci/intr_remapping.c | |||
| @@ -15,6 +15,14 @@ static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; | |||
| 15 | static int ir_ioapic_num; | 15 | static int ir_ioapic_num; |
| 16 | int intr_remapping_enabled; | 16 | int intr_remapping_enabled; |
| 17 | 17 | ||
| 18 | static int disable_intremap; | ||
| 19 | static __init int setup_nointremap(char *str) | ||
| 20 | { | ||
| 21 | disable_intremap = 1; | ||
| 22 | return 0; | ||
| 23 | } | ||
| 24 | early_param("nointremap", setup_nointremap); | ||
| 25 | |||
| 18 | struct irq_2_iommu { | 26 | struct irq_2_iommu { |
| 19 | struct intel_iommu *iommu; | 27 | struct intel_iommu *iommu; |
| 20 | u16 irte_index; | 28 | u16 irte_index; |
| @@ -23,15 +31,12 @@ struct irq_2_iommu { | |||
| 23 | }; | 31 | }; |
| 24 | 32 | ||
| 25 | #ifdef CONFIG_GENERIC_HARDIRQS | 33 | #ifdef CONFIG_GENERIC_HARDIRQS |
| 26 | static struct irq_2_iommu *get_one_free_irq_2_iommu(int cpu) | 34 | static struct irq_2_iommu *get_one_free_irq_2_iommu(int node) |
| 27 | { | 35 | { |
| 28 | struct irq_2_iommu *iommu; | 36 | struct irq_2_iommu *iommu; |
| 29 | int node; | ||
| 30 | |||
| 31 | node = cpu_to_node(cpu); | ||
| 32 | 37 | ||
| 33 | iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node); | 38 | iommu = kzalloc_node(sizeof(*iommu), GFP_ATOMIC, node); |
| 34 | printk(KERN_DEBUG "alloc irq_2_iommu on cpu %d node %d\n", cpu, node); | 39 | printk(KERN_DEBUG "alloc irq_2_iommu on node %d\n", node); |
| 35 | 40 | ||
| 36 | return iommu; | 41 | return iommu; |
| 37 | } | 42 | } |
| @@ -48,7 +53,7 @@ static struct irq_2_iommu *irq_2_iommu(unsigned int irq) | |||
| 48 | return desc->irq_2_iommu; | 53 | return desc->irq_2_iommu; |
| 49 | } | 54 | } |
| 50 | 55 | ||
| 51 | static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu) | 56 | static struct irq_2_iommu *irq_2_iommu_alloc_node(unsigned int irq, int node) |
| 52 | { | 57 | { |
| 53 | struct irq_desc *desc; | 58 | struct irq_desc *desc; |
| 54 | struct irq_2_iommu *irq_iommu; | 59 | struct irq_2_iommu *irq_iommu; |
| @@ -56,7 +61,7 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu) | |||
| 56 | /* | 61 | /* |
| 57 | * alloc irq desc if not allocated already. | 62 | * alloc irq desc if not allocated already. |
| 58 | */ | 63 | */ |
| 59 | desc = irq_to_desc_alloc_cpu(irq, cpu); | 64 | desc = irq_to_desc_alloc_node(irq, node); |
| 60 | if (!desc) { | 65 | if (!desc) { |
| 61 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | 66 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); |
| 62 | return NULL; | 67 | return NULL; |
| @@ -65,14 +70,14 @@ static struct irq_2_iommu *irq_2_iommu_alloc_cpu(unsigned int irq, int cpu) | |||
| 65 | irq_iommu = desc->irq_2_iommu; | 70 | irq_iommu = desc->irq_2_iommu; |
| 66 | 71 | ||
| 67 | if (!irq_iommu) | 72 | if (!irq_iommu) |
| 68 | desc->irq_2_iommu = get_one_free_irq_2_iommu(cpu); | 73 | desc->irq_2_iommu = get_one_free_irq_2_iommu(node); |
| 69 | 74 | ||
| 70 | return desc->irq_2_iommu; | 75 | return desc->irq_2_iommu; |
| 71 | } | 76 | } |
| 72 | 77 | ||
| 73 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) | 78 | static struct irq_2_iommu *irq_2_iommu_alloc(unsigned int irq) |
| 74 | { | 79 | { |
| 75 | return irq_2_iommu_alloc_cpu(irq, boot_cpu_id); | 80 | return irq_2_iommu_alloc_node(irq, cpu_to_node(boot_cpu_id)); |
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | #else /* !CONFIG_SPARSE_IRQ */ | 83 | #else /* !CONFIG_SPARSE_IRQ */ |
| @@ -423,20 +428,6 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) | |||
| 423 | readl, (sts & DMA_GSTS_IRTPS), sts); | 428 | readl, (sts & DMA_GSTS_IRTPS), sts); |
| 424 | spin_unlock_irqrestore(&iommu->register_lock, flags); | 429 | spin_unlock_irqrestore(&iommu->register_lock, flags); |
| 425 | 430 | ||
| 426 | if (mode == 0) { | ||
| 427 | spin_lock_irqsave(&iommu->register_lock, flags); | ||
| 428 | |||
| 429 | /* enable comaptiblity format interrupt pass through */ | ||
| 430 | cmd = iommu->gcmd | DMA_GCMD_CFI; | ||
| 431 | iommu->gcmd |= DMA_GCMD_CFI; | ||
| 432 | writel(cmd, iommu->reg + DMAR_GCMD_REG); | ||
| 433 | |||
| 434 | IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, | ||
| 435 | readl, (sts & DMA_GSTS_CFIS), sts); | ||
| 436 | |||
| 437 | spin_unlock_irqrestore(&iommu->register_lock, flags); | ||
| 438 | } | ||
| 439 | |||
| 440 | /* | 431 | /* |
| 441 | * global invalidation of interrupt entry cache before enabling | 432 | * global invalidation of interrupt entry cache before enabling |
| 442 | * interrupt-remapping. | 433 | * interrupt-remapping. |
| @@ -516,6 +507,23 @@ end: | |||
| 516 | spin_unlock_irqrestore(&iommu->register_lock, flags); | 507 | spin_unlock_irqrestore(&iommu->register_lock, flags); |
| 517 | } | 508 | } |
| 518 | 509 | ||
| 510 | int __init intr_remapping_supported(void) | ||
| 511 | { | ||
| 512 | struct dmar_drhd_unit *drhd; | ||
| 513 | |||
| 514 | if (disable_intremap) | ||
| 515 | return 0; | ||
| 516 | |||
| 517 | for_each_drhd_unit(drhd) { | ||
| 518 | struct intel_iommu *iommu = drhd->iommu; | ||
| 519 | |||
| 520 | if (!ecap_ir_support(iommu->ecap)) | ||
| 521 | return 0; | ||
| 522 | } | ||
| 523 | |||
| 524 | return 1; | ||
| 525 | } | ||
| 526 | |||
| 519 | int __init enable_intr_remapping(int eim) | 527 | int __init enable_intr_remapping(int eim) |
| 520 | { | 528 | { |
| 521 | struct dmar_drhd_unit *drhd; | 529 | struct dmar_drhd_unit *drhd; |
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c index e3c3e081b834..f1ae2475ffff 100644 --- a/drivers/pci/probe.c +++ b/drivers/pci/probe.c | |||
| @@ -745,6 +745,8 @@ int pci_setup_device(struct pci_dev *dev) | |||
| 745 | 745 | ||
| 746 | /* Early fixups, before probing the BARs */ | 746 | /* Early fixups, before probing the BARs */ |
| 747 | pci_fixup_device(pci_fixup_early, dev); | 747 | pci_fixup_device(pci_fixup_early, dev); |
| 748 | /* device class may be changed after fixup */ | ||
| 749 | class = dev->class >> 8; | ||
| 748 | 750 | ||
| 749 | switch (dev->hdr_type) { /* header type */ | 751 | switch (dev->hdr_type) { /* header type */ |
| 750 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ | 752 | case PCI_HEADER_TYPE_NORMAL: /* standard header */ |
diff --git a/drivers/pnp/pnpacpi/rsparser.c b/drivers/pnp/pnpacpi/rsparser.c index adf17856bacc..7f207f335bec 100644 --- a/drivers/pnp/pnpacpi/rsparser.c +++ b/drivers/pnp/pnpacpi/rsparser.c | |||
| @@ -123,7 +123,7 @@ static void pnpacpi_parse_allocated_irqresource(struct pnp_dev *dev, | |||
| 123 | } | 123 | } |
| 124 | 124 | ||
| 125 | flags = irq_flags(triggering, polarity, shareable); | 125 | flags = irq_flags(triggering, polarity, shareable); |
| 126 | irq = acpi_register_gsi(gsi, triggering, polarity); | 126 | irq = acpi_register_gsi(&dev->dev, gsi, triggering, polarity); |
| 127 | if (irq >= 0) | 127 | if (irq >= 0) |
| 128 | pcibios_penalize_isa_irq(irq, 1); | 128 | pcibios_penalize_isa_irq(irq, 1); |
| 129 | else | 129 | else |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 4e9851fc1746..277d35d232fa 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
| @@ -692,7 +692,7 @@ config RTC_DRV_GENERIC | |||
| 692 | tristate "Generic RTC support" | 692 | tristate "Generic RTC support" |
| 693 | # Please consider writing a new RTC driver instead of using the generic | 693 | # Please consider writing a new RTC driver instead of using the generic |
| 694 | # RTC abstraction | 694 | # RTC abstraction |
| 695 | depends on PARISC || M68K || PPC | 695 | depends on PARISC || M68K || PPC || SUPERH32 |
| 696 | help | 696 | help |
| 697 | Say Y or M here to enable RTC support on systems using the generic | 697 | Say Y or M here to enable RTC support on systems using the generic |
| 698 | RTC abstraction. If you do not know what you are doing, you should | 698 | RTC abstraction. If you do not know what you are doing, you should |
diff --git a/drivers/s390/block/dasd.c b/drivers/s390/block/dasd.c index d1815272c435..27a1be0cd4d4 100644 --- a/drivers/s390/block/dasd.c +++ b/drivers/s390/block/dasd.c | |||
| @@ -603,7 +603,7 @@ static void dasd_profile_end(struct dasd_block *block, | |||
| 603 | if (dasd_profile_level != DASD_PROFILE_ON) | 603 | if (dasd_profile_level != DASD_PROFILE_ON) |
| 604 | return; | 604 | return; |
| 605 | 605 | ||
| 606 | sectors = req->nr_sectors; | 606 | sectors = blk_rq_sectors(req); |
| 607 | if (!cqr->buildclk || !cqr->startclk || | 607 | if (!cqr->buildclk || !cqr->startclk || |
| 608 | !cqr->stopclk || !cqr->endclk || | 608 | !cqr->stopclk || !cqr->endclk || |
| 609 | !sectors) | 609 | !sectors) |
| @@ -1614,15 +1614,6 @@ void dasd_block_clear_timer(struct dasd_block *block) | |||
| 1614 | } | 1614 | } |
| 1615 | 1615 | ||
| 1616 | /* | 1616 | /* |
| 1617 | * posts the buffer_cache about a finalized request | ||
| 1618 | */ | ||
| 1619 | static inline void dasd_end_request(struct request *req, int error) | ||
| 1620 | { | ||
| 1621 | if (__blk_end_request(req, error, blk_rq_bytes(req))) | ||
| 1622 | BUG(); | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | /* | ||
| 1626 | * Process finished error recovery ccw. | 1617 | * Process finished error recovery ccw. |
| 1627 | */ | 1618 | */ |
| 1628 | static inline void __dasd_block_process_erp(struct dasd_block *block, | 1619 | static inline void __dasd_block_process_erp(struct dasd_block *block, |
| @@ -1665,18 +1656,14 @@ static void __dasd_process_request_queue(struct dasd_block *block) | |||
| 1665 | if (basedev->state < DASD_STATE_READY) | 1656 | if (basedev->state < DASD_STATE_READY) |
| 1666 | return; | 1657 | return; |
| 1667 | /* Now we try to fetch requests from the request queue */ | 1658 | /* Now we try to fetch requests from the request queue */ |
| 1668 | while (!blk_queue_plugged(queue) && | 1659 | while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) { |
| 1669 | elv_next_request(queue)) { | ||
| 1670 | |||
| 1671 | req = elv_next_request(queue); | ||
| 1672 | |||
| 1673 | if (basedev->features & DASD_FEATURE_READONLY && | 1660 | if (basedev->features & DASD_FEATURE_READONLY && |
| 1674 | rq_data_dir(req) == WRITE) { | 1661 | rq_data_dir(req) == WRITE) { |
| 1675 | DBF_DEV_EVENT(DBF_ERR, basedev, | 1662 | DBF_DEV_EVENT(DBF_ERR, basedev, |
| 1676 | "Rejecting write request %p", | 1663 | "Rejecting write request %p", |
| 1677 | req); | 1664 | req); |
| 1678 | blkdev_dequeue_request(req); | 1665 | blk_start_request(req); |
| 1679 | dasd_end_request(req, -EIO); | 1666 | __blk_end_request_all(req, -EIO); |
| 1680 | continue; | 1667 | continue; |
| 1681 | } | 1668 | } |
| 1682 | cqr = basedev->discipline->build_cp(basedev, block, req); | 1669 | cqr = basedev->discipline->build_cp(basedev, block, req); |
| @@ -1704,8 +1691,8 @@ static void __dasd_process_request_queue(struct dasd_block *block) | |||
| 1704 | "CCW creation failed (rc=%ld) " | 1691 | "CCW creation failed (rc=%ld) " |
| 1705 | "on request %p", | 1692 | "on request %p", |
| 1706 | PTR_ERR(cqr), req); | 1693 | PTR_ERR(cqr), req); |
| 1707 | blkdev_dequeue_request(req); | 1694 | blk_start_request(req); |
| 1708 | dasd_end_request(req, -EIO); | 1695 | __blk_end_request_all(req, -EIO); |
| 1709 | continue; | 1696 | continue; |
| 1710 | } | 1697 | } |
| 1711 | /* | 1698 | /* |
| @@ -1714,7 +1701,7 @@ static void __dasd_process_request_queue(struct dasd_block *block) | |||
| 1714 | */ | 1701 | */ |
| 1715 | cqr->callback_data = (void *) req; | 1702 | cqr->callback_data = (void *) req; |
| 1716 | cqr->status = DASD_CQR_FILLED; | 1703 | cqr->status = DASD_CQR_FILLED; |
| 1717 | blkdev_dequeue_request(req); | 1704 | blk_start_request(req); |
| 1718 | list_add_tail(&cqr->blocklist, &block->ccw_queue); | 1705 | list_add_tail(&cqr->blocklist, &block->ccw_queue); |
| 1719 | dasd_profile_start(block, cqr, req); | 1706 | dasd_profile_start(block, cqr, req); |
| 1720 | } | 1707 | } |
| @@ -1731,7 +1718,7 @@ static void __dasd_cleanup_cqr(struct dasd_ccw_req *cqr) | |||
| 1731 | status = cqr->block->base->discipline->free_cp(cqr, req); | 1718 | status = cqr->block->base->discipline->free_cp(cqr, req); |
| 1732 | if (status <= 0) | 1719 | if (status <= 0) |
| 1733 | error = status ? status : -EIO; | 1720 | error = status ? status : -EIO; |
| 1734 | dasd_end_request(req, error); | 1721 | __blk_end_request_all(req, error); |
| 1735 | } | 1722 | } |
| 1736 | 1723 | ||
| 1737 | /* | 1724 | /* |
| @@ -2003,7 +1990,7 @@ static void dasd_setup_queue(struct dasd_block *block) | |||
| 2003 | { | 1990 | { |
| 2004 | int max; | 1991 | int max; |
| 2005 | 1992 | ||
| 2006 | blk_queue_hardsect_size(block->request_queue, block->bp_block); | 1993 | blk_queue_logical_block_size(block->request_queue, block->bp_block); |
| 2007 | max = block->base->discipline->max_blocks << block->s2b_shift; | 1994 | max = block->base->discipline->max_blocks << block->s2b_shift; |
| 2008 | blk_queue_max_sectors(block->request_queue, max); | 1995 | blk_queue_max_sectors(block->request_queue, max); |
| 2009 | blk_queue_max_phys_segments(block->request_queue, -1L); | 1996 | blk_queue_max_phys_segments(block->request_queue, -1L); |
| @@ -2038,10 +2025,8 @@ static void dasd_flush_request_queue(struct dasd_block *block) | |||
| 2038 | return; | 2025 | return; |
| 2039 | 2026 | ||
| 2040 | spin_lock_irq(&block->request_queue_lock); | 2027 | spin_lock_irq(&block->request_queue_lock); |
| 2041 | while ((req = elv_next_request(block->request_queue))) { | 2028 | while ((req = blk_fetch_request(block->request_queue))) |
| 2042 | blkdev_dequeue_request(req); | 2029 | __blk_end_request_all(req, -EIO); |
| 2043 | dasd_end_request(req, -EIO); | ||
| 2044 | } | ||
| 2045 | spin_unlock_irq(&block->request_queue_lock); | 2030 | spin_unlock_irq(&block->request_queue_lock); |
| 2046 | } | 2031 | } |
| 2047 | 2032 | ||
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index b9a7f7733446..2efaddfae560 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
| @@ -505,8 +505,9 @@ static struct dasd_ccw_req *dasd_diag_build_cp(struct dasd_device *memdev, | |||
| 505 | return ERR_PTR(-EINVAL); | 505 | return ERR_PTR(-EINVAL); |
| 506 | blksize = block->bp_block; | 506 | blksize = block->bp_block; |
| 507 | /* Calculate record id of first and last block. */ | 507 | /* Calculate record id of first and last block. */ |
| 508 | first_rec = req->sector >> block->s2b_shift; | 508 | first_rec = blk_rq_pos(req) >> block->s2b_shift; |
| 509 | last_rec = (req->sector + req->nr_sectors - 1) >> block->s2b_shift; | 509 | last_rec = |
| 510 | (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift; | ||
| 510 | /* Check struct bio and count the number of blocks for the request. */ | 511 | /* Check struct bio and count the number of blocks for the request. */ |
| 511 | count = 0; | 512 | count = 0; |
| 512 | rq_for_each_segment(bv, req, iter) { | 513 | rq_for_each_segment(bv, req, iter) { |
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c index cb52da033f06..a41c94053e64 100644 --- a/drivers/s390/block/dasd_eckd.c +++ b/drivers/s390/block/dasd_eckd.c | |||
| @@ -2354,10 +2354,10 @@ static struct dasd_ccw_req *dasd_eckd_build_cp(struct dasd_device *startdev, | |||
| 2354 | blksize = block->bp_block; | 2354 | blksize = block->bp_block; |
| 2355 | blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); | 2355 | blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); |
| 2356 | /* Calculate record id of first and last block. */ | 2356 | /* Calculate record id of first and last block. */ |
| 2357 | first_rec = first_trk = req->sector >> block->s2b_shift; | 2357 | first_rec = first_trk = blk_rq_pos(req) >> block->s2b_shift; |
| 2358 | first_offs = sector_div(first_trk, blk_per_trk); | 2358 | first_offs = sector_div(first_trk, blk_per_trk); |
| 2359 | last_rec = last_trk = | 2359 | last_rec = last_trk = |
| 2360 | (req->sector + req->nr_sectors - 1) >> block->s2b_shift; | 2360 | (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift; |
| 2361 | last_offs = sector_div(last_trk, blk_per_trk); | 2361 | last_offs = sector_div(last_trk, blk_per_trk); |
| 2362 | cdlspecial = (private->uses_cdl && first_rec < 2*blk_per_trk); | 2362 | cdlspecial = (private->uses_cdl && first_rec < 2*blk_per_trk); |
| 2363 | 2363 | ||
| @@ -2420,7 +2420,7 @@ dasd_eckd_free_cp(struct dasd_ccw_req *cqr, struct request *req) | |||
| 2420 | private = (struct dasd_eckd_private *) cqr->block->base->private; | 2420 | private = (struct dasd_eckd_private *) cqr->block->base->private; |
| 2421 | blksize = cqr->block->bp_block; | 2421 | blksize = cqr->block->bp_block; |
| 2422 | blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); | 2422 | blk_per_trk = recs_per_track(&private->rdc_data, 0, blksize); |
| 2423 | recid = req->sector >> cqr->block->s2b_shift; | 2423 | recid = blk_rq_pos(req) >> cqr->block->s2b_shift; |
| 2424 | ccw = cqr->cpaddr; | 2424 | ccw = cqr->cpaddr; |
| 2425 | /* Skip over define extent & locate record. */ | 2425 | /* Skip over define extent & locate record. */ |
| 2426 | ccw++; | 2426 | ccw++; |
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c index a3eb6fd14673..8912358daa2f 100644 --- a/drivers/s390/block/dasd_fba.c +++ b/drivers/s390/block/dasd_fba.c | |||
| @@ -270,8 +270,9 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, | |||
| 270 | return ERR_PTR(-EINVAL); | 270 | return ERR_PTR(-EINVAL); |
| 271 | blksize = block->bp_block; | 271 | blksize = block->bp_block; |
| 272 | /* Calculate record id of first and last block. */ | 272 | /* Calculate record id of first and last block. */ |
| 273 | first_rec = req->sector >> block->s2b_shift; | 273 | first_rec = blk_rq_pos(req) >> block->s2b_shift; |
| 274 | last_rec = (req->sector + req->nr_sectors - 1) >> block->s2b_shift; | 274 | last_rec = |
| 275 | (blk_rq_pos(req) + blk_rq_sectors(req) - 1) >> block->s2b_shift; | ||
| 275 | /* Check struct bio and count the number of blocks for the request. */ | 276 | /* Check struct bio and count the number of blocks for the request. */ |
| 276 | count = 0; | 277 | count = 0; |
| 277 | cidaw = 0; | 278 | cidaw = 0; |
| @@ -309,7 +310,7 @@ static struct dasd_ccw_req *dasd_fba_build_cp(struct dasd_device * memdev, | |||
| 309 | ccw = cqr->cpaddr; | 310 | ccw = cqr->cpaddr; |
| 310 | /* First ccw is define extent. */ | 311 | /* First ccw is define extent. */ |
| 311 | define_extent(ccw++, cqr->data, rq_data_dir(req), | 312 | define_extent(ccw++, cqr->data, rq_data_dir(req), |
| 312 | block->bp_block, req->sector, req->nr_sectors); | 313 | block->bp_block, blk_rq_pos(req), blk_rq_sectors(req)); |
| 313 | /* Build locate_record + read/write ccws. */ | 314 | /* Build locate_record + read/write ccws. */ |
| 314 | idaws = (unsigned long *) (cqr->data + sizeof(struct DE_fba_data)); | 315 | idaws = (unsigned long *) (cqr->data + sizeof(struct DE_fba_data)); |
| 315 | LO_data = (struct LO_fba_data *) (idaws + cidaw); | 316 | LO_data = (struct LO_fba_data *) (idaws + cidaw); |
diff --git a/drivers/s390/block/dcssblk.c b/drivers/s390/block/dcssblk.c index cfdcf1aed33c..a4c7ffcd9987 100644 --- a/drivers/s390/block/dcssblk.c +++ b/drivers/s390/block/dcssblk.c | |||
| @@ -602,7 +602,7 @@ dcssblk_add_store(struct device *dev, struct device_attribute *attr, const char | |||
| 602 | dev_info->gd->private_data = dev_info; | 602 | dev_info->gd->private_data = dev_info; |
| 603 | dev_info->gd->driverfs_dev = &dev_info->dev; | 603 | dev_info->gd->driverfs_dev = &dev_info->dev; |
| 604 | blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request); | 604 | blk_queue_make_request(dev_info->dcssblk_queue, dcssblk_make_request); |
| 605 | blk_queue_hardsect_size(dev_info->dcssblk_queue, 4096); | 605 | blk_queue_logical_block_size(dev_info->dcssblk_queue, 4096); |
| 606 | 606 | ||
| 607 | seg_byte_size = (dev_info->end - dev_info->start + 1); | 607 | seg_byte_size = (dev_info->end - dev_info->start + 1); |
| 608 | set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors | 608 | set_capacity(dev_info->gd, seg_byte_size >> 9); // size in sectors |
diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 76814f3e898a..0ae0c83ef879 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c | |||
| @@ -343,7 +343,7 @@ static int __init xpram_setup_blkdev(void) | |||
| 343 | goto out; | 343 | goto out; |
| 344 | } | 344 | } |
| 345 | blk_queue_make_request(xpram_queues[i], xpram_make_request); | 345 | blk_queue_make_request(xpram_queues[i], xpram_make_request); |
| 346 | blk_queue_hardsect_size(xpram_queues[i], 4096); | 346 | blk_queue_logical_block_size(xpram_queues[i], 4096); |
| 347 | } | 347 | } |
| 348 | 348 | ||
| 349 | /* | 349 | /* |
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c index 5f8e8ef43dd3..2d00a383a475 100644 --- a/drivers/s390/char/tape_34xx.c +++ b/drivers/s390/char/tape_34xx.c | |||
| @@ -1134,7 +1134,7 @@ tape_34xx_bread(struct tape_device *device, struct request *req) | |||
| 1134 | /* Setup ccws. */ | 1134 | /* Setup ccws. */ |
| 1135 | request->op = TO_BLOCK; | 1135 | request->op = TO_BLOCK; |
| 1136 | start_block = (struct tape_34xx_block_id *) request->cpdata; | 1136 | start_block = (struct tape_34xx_block_id *) request->cpdata; |
| 1137 | start_block->block = req->sector >> TAPEBLOCK_HSEC_S2B; | 1137 | start_block->block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B; |
| 1138 | DBF_EVENT(6, "start_block = %i\n", start_block->block); | 1138 | DBF_EVENT(6, "start_block = %i\n", start_block->block); |
| 1139 | 1139 | ||
| 1140 | ccw = request->cpaddr; | 1140 | ccw = request->cpaddr; |
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c index 823b05bd0dd7..c453b2f3e9f4 100644 --- a/drivers/s390/char/tape_3590.c +++ b/drivers/s390/char/tape_3590.c | |||
| @@ -633,7 +633,7 @@ tape_3590_bread(struct tape_device *device, struct request *req) | |||
| 633 | struct req_iterator iter; | 633 | struct req_iterator iter; |
| 634 | 634 | ||
| 635 | DBF_EVENT(6, "xBREDid:"); | 635 | DBF_EVENT(6, "xBREDid:"); |
| 636 | start_block = req->sector >> TAPEBLOCK_HSEC_S2B; | 636 | start_block = blk_rq_pos(req) >> TAPEBLOCK_HSEC_S2B; |
| 637 | DBF_EVENT(6, "start_block = %i\n", start_block); | 637 | DBF_EVENT(6, "start_block = %i\n", start_block); |
| 638 | 638 | ||
| 639 | rq_for_each_segment(bv, req, iter) | 639 | rq_for_each_segment(bv, req, iter) |
diff --git a/drivers/s390/char/tape_block.c b/drivers/s390/char/tape_block.c index f32e89e7c4f2..47ff695255ea 100644 --- a/drivers/s390/char/tape_block.c +++ b/drivers/s390/char/tape_block.c | |||
| @@ -74,13 +74,6 @@ tapeblock_trigger_requeue(struct tape_device *device) | |||
| 74 | * Post finished request. | 74 | * Post finished request. |
| 75 | */ | 75 | */ |
| 76 | static void | 76 | static void |
| 77 | tapeblock_end_request(struct request *req, int error) | ||
| 78 | { | ||
| 79 | if (blk_end_request(req, error, blk_rq_bytes(req))) | ||
| 80 | BUG(); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void | ||
| 84 | __tapeblock_end_request(struct tape_request *ccw_req, void *data) | 77 | __tapeblock_end_request(struct tape_request *ccw_req, void *data) |
| 85 | { | 78 | { |
| 86 | struct tape_device *device; | 79 | struct tape_device *device; |
| @@ -90,17 +83,17 @@ __tapeblock_end_request(struct tape_request *ccw_req, void *data) | |||
| 90 | 83 | ||
| 91 | device = ccw_req->device; | 84 | device = ccw_req->device; |
| 92 | req = (struct request *) data; | 85 | req = (struct request *) data; |
| 93 | tapeblock_end_request(req, (ccw_req->rc == 0) ? 0 : -EIO); | 86 | blk_end_request_all(req, (ccw_req->rc == 0) ? 0 : -EIO); |
| 94 | if (ccw_req->rc == 0) | 87 | if (ccw_req->rc == 0) |
| 95 | /* Update position. */ | 88 | /* Update position. */ |
| 96 | device->blk_data.block_position = | 89 | device->blk_data.block_position = |
| 97 | (req->sector + req->nr_sectors) >> TAPEBLOCK_HSEC_S2B; | 90 | (blk_rq_pos(req) + blk_rq_sectors(req)) >> TAPEBLOCK_HSEC_S2B; |
| 98 | else | 91 | else |
| 99 | /* We lost the position information due to an error. */ | 92 | /* We lost the position information due to an error. */ |
| 100 | device->blk_data.block_position = -1; | 93 | device->blk_data.block_position = -1; |
| 101 | device->discipline->free_bread(ccw_req); | 94 | device->discipline->free_bread(ccw_req); |
| 102 | if (!list_empty(&device->req_queue) || | 95 | if (!list_empty(&device->req_queue) || |
| 103 | elv_next_request(device->blk_data.request_queue)) | 96 | blk_peek_request(device->blk_data.request_queue)) |
| 104 | tapeblock_trigger_requeue(device); | 97 | tapeblock_trigger_requeue(device); |
| 105 | } | 98 | } |
| 106 | 99 | ||
| @@ -118,7 +111,7 @@ tapeblock_start_request(struct tape_device *device, struct request *req) | |||
| 118 | ccw_req = device->discipline->bread(device, req); | 111 | ccw_req = device->discipline->bread(device, req); |
| 119 | if (IS_ERR(ccw_req)) { | 112 | if (IS_ERR(ccw_req)) { |
| 120 | DBF_EVENT(1, "TBLOCK: bread failed\n"); | 113 | DBF_EVENT(1, "TBLOCK: bread failed\n"); |
| 121 | tapeblock_end_request(req, -EIO); | 114 | blk_end_request_all(req, -EIO); |
| 122 | return PTR_ERR(ccw_req); | 115 | return PTR_ERR(ccw_req); |
| 123 | } | 116 | } |
| 124 | ccw_req->callback = __tapeblock_end_request; | 117 | ccw_req->callback = __tapeblock_end_request; |
| @@ -131,7 +124,7 @@ tapeblock_start_request(struct tape_device *device, struct request *req) | |||
| 131 | * Start/enqueueing failed. No retries in | 124 | * Start/enqueueing failed. No retries in |
| 132 | * this case. | 125 | * this case. |
| 133 | */ | 126 | */ |
| 134 | tapeblock_end_request(req, -EIO); | 127 | blk_end_request_all(req, -EIO); |
| 135 | device->discipline->free_bread(ccw_req); | 128 | device->discipline->free_bread(ccw_req); |
| 136 | } | 129 | } |
| 137 | 130 | ||
| @@ -169,19 +162,16 @@ tapeblock_requeue(struct work_struct *work) { | |||
| 169 | spin_lock_irq(&device->blk_data.request_queue_lock); | 162 | spin_lock_irq(&device->blk_data.request_queue_lock); |
| 170 | while ( | 163 | while ( |
| 171 | !blk_queue_plugged(queue) && | 164 | !blk_queue_plugged(queue) && |
| 172 | elv_next_request(queue) && | 165 | (req = blk_fetch_request(queue)) && |
| 173 | nr_queued < TAPEBLOCK_MIN_REQUEUE | 166 | nr_queued < TAPEBLOCK_MIN_REQUEUE |
| 174 | ) { | 167 | ) { |
| 175 | req = elv_next_request(queue); | ||
| 176 | if (rq_data_dir(req) == WRITE) { | 168 | if (rq_data_dir(req) == WRITE) { |
| 177 | DBF_EVENT(1, "TBLOCK: Rejecting write request\n"); | 169 | DBF_EVENT(1, "TBLOCK: Rejecting write request\n"); |
| 178 | blkdev_dequeue_request(req); | ||
| 179 | spin_unlock_irq(&device->blk_data.request_queue_lock); | 170 | spin_unlock_irq(&device->blk_data.request_queue_lock); |
| 180 | tapeblock_end_request(req, -EIO); | 171 | blk_end_request_all(req, -EIO); |
| 181 | spin_lock_irq(&device->blk_data.request_queue_lock); | 172 | spin_lock_irq(&device->blk_data.request_queue_lock); |
| 182 | continue; | 173 | continue; |
| 183 | } | 174 | } |
| 184 | blkdev_dequeue_request(req); | ||
| 185 | nr_queued++; | 175 | nr_queued++; |
| 186 | spin_unlock_irq(&device->blk_data.request_queue_lock); | 176 | spin_unlock_irq(&device->blk_data.request_queue_lock); |
| 187 | rc = tapeblock_start_request(device, req); | 177 | rc = tapeblock_start_request(device, req); |
| @@ -232,7 +222,7 @@ tapeblock_setup_device(struct tape_device * device) | |||
| 232 | if (rc) | 222 | if (rc) |
| 233 | goto cleanup_queue; | 223 | goto cleanup_queue; |
| 234 | 224 | ||
| 235 | blk_queue_hardsect_size(blkdat->request_queue, TAPEBLOCK_HSEC_SIZE); | 225 | blk_queue_logical_block_size(blkdat->request_queue, TAPEBLOCK_HSEC_SIZE); |
| 236 | blk_queue_max_sectors(blkdat->request_queue, TAPEBLOCK_MAX_SEC); | 226 | blk_queue_max_sectors(blkdat->request_queue, TAPEBLOCK_MAX_SEC); |
| 237 | blk_queue_max_phys_segments(blkdat->request_queue, -1L); | 227 | blk_queue_max_phys_segments(blkdat->request_queue, -1L); |
| 238 | blk_queue_max_hw_segments(blkdat->request_queue, -1L); | 228 | blk_queue_max_hw_segments(blkdat->request_queue, -1L); |
diff --git a/drivers/sbus/char/jsflash.c b/drivers/sbus/char/jsflash.c index a85ad05e8548..6d4651684688 100644 --- a/drivers/sbus/char/jsflash.c +++ b/drivers/sbus/char/jsflash.c | |||
| @@ -186,31 +186,31 @@ static void jsfd_do_request(struct request_queue *q) | |||
| 186 | { | 186 | { |
| 187 | struct request *req; | 187 | struct request *req; |
| 188 | 188 | ||
| 189 | while ((req = elv_next_request(q)) != NULL) { | 189 | req = blk_fetch_request(q); |
| 190 | while (req) { | ||
| 190 | struct jsfd_part *jdp = req->rq_disk->private_data; | 191 | struct jsfd_part *jdp = req->rq_disk->private_data; |
| 191 | unsigned long offset = req->sector << 9; | 192 | unsigned long offset = blk_rq_pos(req) << 9; |
| 192 | size_t len = req->current_nr_sectors << 9; | 193 | size_t len = blk_rq_cur_bytes(req); |
| 194 | int err = -EIO; | ||
| 193 | 195 | ||
| 194 | if ((offset + len) > jdp->dsize) { | 196 | if ((offset + len) > jdp->dsize) |
| 195 | end_request(req, 0); | 197 | goto end; |
| 196 | continue; | ||
| 197 | } | ||
| 198 | 198 | ||
| 199 | if (rq_data_dir(req) != READ) { | 199 | if (rq_data_dir(req) != READ) { |
| 200 | printk(KERN_ERR "jsfd: write\n"); | 200 | printk(KERN_ERR "jsfd: write\n"); |
| 201 | end_request(req, 0); | 201 | goto end; |
| 202 | continue; | ||
| 203 | } | 202 | } |
| 204 | 203 | ||
| 205 | if ((jdp->dbase & 0xff000000) != 0x20000000) { | 204 | if ((jdp->dbase & 0xff000000) != 0x20000000) { |
| 206 | printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase); | 205 | printk(KERN_ERR "jsfd: bad base %x\n", (int)jdp->dbase); |
| 207 | end_request(req, 0); | 206 | goto end; |
| 208 | continue; | ||
| 209 | } | 207 | } |
| 210 | 208 | ||
| 211 | jsfd_read(req->buffer, jdp->dbase + offset, len); | 209 | jsfd_read(req->buffer, jdp->dbase + offset, len); |
| 212 | 210 | err = 0; | |
| 213 | end_request(req, 1); | 211 | end: |
| 212 | if (!__blk_end_request_cur(req, err)) | ||
| 213 | req = blk_fetch_request(q); | ||
| 214 | } | 214 | } |
| 215 | } | 215 | } |
| 216 | 216 | ||
diff --git a/drivers/scsi/eata.c b/drivers/scsi/eata.c index be5099dd94b5..c7076ce25e21 100644 --- a/drivers/scsi/eata.c +++ b/drivers/scsi/eata.c | |||
| @@ -1825,7 +1825,7 @@ static int eata2x_queuecommand(struct scsi_cmnd *SCpnt, | |||
| 1825 | if (linked_comm && SCpnt->device->queue_depth > 2 | 1825 | if (linked_comm && SCpnt->device->queue_depth > 2 |
| 1826 | && TLDEV(SCpnt->device->type)) { | 1826 | && TLDEV(SCpnt->device->type)) { |
| 1827 | ha->cp_stat[i] = READY; | 1827 | ha->cp_stat[i] = READY; |
| 1828 | flush_dev(SCpnt->device, SCpnt->request->sector, ha, 0); | 1828 | flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), ha, 0); |
| 1829 | return 0; | 1829 | return 0; |
| 1830 | } | 1830 | } |
| 1831 | 1831 | ||
| @@ -2144,13 +2144,13 @@ static int reorder(struct hostdata *ha, unsigned long cursec, | |||
| 2144 | if (!cpp->din) | 2144 | if (!cpp->din) |
| 2145 | input_only = 0; | 2145 | input_only = 0; |
| 2146 | 2146 | ||
| 2147 | if (SCpnt->request->sector < minsec) | 2147 | if (blk_rq_pos(SCpnt->request) < minsec) |
| 2148 | minsec = SCpnt->request->sector; | 2148 | minsec = blk_rq_pos(SCpnt->request); |
| 2149 | if (SCpnt->request->sector > maxsec) | 2149 | if (blk_rq_pos(SCpnt->request) > maxsec) |
| 2150 | maxsec = SCpnt->request->sector; | 2150 | maxsec = blk_rq_pos(SCpnt->request); |
| 2151 | 2151 | ||
| 2152 | sl[n] = SCpnt->request->sector; | 2152 | sl[n] = blk_rq_pos(SCpnt->request); |
| 2153 | ioseek += SCpnt->request->nr_sectors; | 2153 | ioseek += blk_rq_sectors(SCpnt->request); |
| 2154 | 2154 | ||
| 2155 | if (!n) | 2155 | if (!n) |
| 2156 | continue; | 2156 | continue; |
| @@ -2190,7 +2190,7 @@ static int reorder(struct hostdata *ha, unsigned long cursec, | |||
| 2190 | k = il[n]; | 2190 | k = il[n]; |
| 2191 | cpp = &ha->cp[k]; | 2191 | cpp = &ha->cp[k]; |
| 2192 | SCpnt = cpp->SCpnt; | 2192 | SCpnt = cpp->SCpnt; |
| 2193 | ll[n] = SCpnt->request->nr_sectors; | 2193 | ll[n] = blk_rq_sectors(SCpnt->request); |
| 2194 | pl[n] = SCpnt->serial_number; | 2194 | pl[n] = SCpnt->serial_number; |
| 2195 | 2195 | ||
| 2196 | if (!n) | 2196 | if (!n) |
| @@ -2236,12 +2236,12 @@ static int reorder(struct hostdata *ha, unsigned long cursec, | |||
| 2236 | cpp = &ha->cp[k]; | 2236 | cpp = &ha->cp[k]; |
| 2237 | SCpnt = cpp->SCpnt; | 2237 | SCpnt = cpp->SCpnt; |
| 2238 | scmd_printk(KERN_INFO, SCpnt, | 2238 | scmd_printk(KERN_INFO, SCpnt, |
| 2239 | "%s pid %ld mb %d fc %d nr %d sec %ld ns %ld" | 2239 | "%s pid %ld mb %d fc %d nr %d sec %ld ns %u" |
| 2240 | " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", | 2240 | " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", |
| 2241 | (ihdlr ? "ihdlr" : "qcomm"), | 2241 | (ihdlr ? "ihdlr" : "qcomm"), |
| 2242 | SCpnt->serial_number, k, flushcount, | 2242 | SCpnt->serial_number, k, flushcount, |
| 2243 | n_ready, SCpnt->request->sector, | 2243 | n_ready, blk_rq_pos(SCpnt->request), |
| 2244 | SCpnt->request->nr_sectors, cursec, YESNO(s), | 2244 | blk_rq_sectors(SCpnt->request), cursec, YESNO(s), |
| 2245 | YESNO(r), YESNO(rev), YESNO(input_only), | 2245 | YESNO(r), YESNO(rev), YESNO(input_only), |
| 2246 | YESNO(overlap), cpp->din); | 2246 | YESNO(overlap), cpp->din); |
| 2247 | } | 2247 | } |
| @@ -2408,7 +2408,7 @@ static irqreturn_t ihdlr(struct Scsi_Host *shost) | |||
| 2408 | 2408 | ||
| 2409 | if (linked_comm && SCpnt->device->queue_depth > 2 | 2409 | if (linked_comm && SCpnt->device->queue_depth > 2 |
| 2410 | && TLDEV(SCpnt->device->type)) | 2410 | && TLDEV(SCpnt->device->type)) |
| 2411 | flush_dev(SCpnt->device, SCpnt->request->sector, ha, 1); | 2411 | flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), ha, 1); |
| 2412 | 2412 | ||
| 2413 | tstatus = status_byte(spp->target_status); | 2413 | tstatus = status_byte(spp->target_status); |
| 2414 | 2414 | ||
diff --git a/drivers/scsi/libsas/sas_expander.c b/drivers/scsi/libsas/sas_expander.c index 3da02e436788..54fa1e42dc4d 100644 --- a/drivers/scsi/libsas/sas_expander.c +++ b/drivers/scsi/libsas/sas_expander.c | |||
| @@ -1927,21 +1927,21 @@ int sas_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1927 | /* do we need to support multiple segments? */ | 1927 | /* do we need to support multiple segments? */ |
| 1928 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { | 1928 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { |
| 1929 | printk("%s: multiple segments req %u %u, rsp %u %u\n", | 1929 | printk("%s: multiple segments req %u %u, rsp %u %u\n", |
| 1930 | __func__, req->bio->bi_vcnt, req->data_len, | 1930 | __func__, req->bio->bi_vcnt, blk_rq_bytes(req), |
| 1931 | rsp->bio->bi_vcnt, rsp->data_len); | 1931 | rsp->bio->bi_vcnt, blk_rq_bytes(rsp)); |
| 1932 | return -EINVAL; | 1932 | return -EINVAL; |
| 1933 | } | 1933 | } |
| 1934 | 1934 | ||
| 1935 | ret = smp_execute_task(dev, bio_data(req->bio), req->data_len, | 1935 | ret = smp_execute_task(dev, bio_data(req->bio), blk_rq_bytes(req), |
| 1936 | bio_data(rsp->bio), rsp->data_len); | 1936 | bio_data(rsp->bio), blk_rq_bytes(rsp)); |
| 1937 | if (ret > 0) { | 1937 | if (ret > 0) { |
| 1938 | /* positive number is the untransferred residual */ | 1938 | /* positive number is the untransferred residual */ |
| 1939 | rsp->data_len = ret; | 1939 | rsp->resid_len = ret; |
| 1940 | req->data_len = 0; | 1940 | req->resid_len = 0; |
| 1941 | ret = 0; | 1941 | ret = 0; |
| 1942 | } else if (ret == 0) { | 1942 | } else if (ret == 0) { |
| 1943 | rsp->data_len = 0; | 1943 | rsp->resid_len = 0; |
| 1944 | req->data_len = 0; | 1944 | req->resid_len = 0; |
| 1945 | } | 1945 | } |
| 1946 | 1946 | ||
| 1947 | return ret; | 1947 | return ret; |
diff --git a/drivers/scsi/libsas/sas_host_smp.c b/drivers/scsi/libsas/sas_host_smp.c index d110a366c48a..1bc3b7567994 100644 --- a/drivers/scsi/libsas/sas_host_smp.c +++ b/drivers/scsi/libsas/sas_host_smp.c | |||
| @@ -134,24 +134,24 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
| 134 | { | 134 | { |
| 135 | u8 *req_data = NULL, *resp_data = NULL, *buf; | 135 | u8 *req_data = NULL, *resp_data = NULL, *buf; |
| 136 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); | 136 | struct sas_ha_struct *sas_ha = SHOST_TO_SAS_HA(shost); |
| 137 | int error = -EINVAL, resp_data_len = rsp->data_len; | 137 | int error = -EINVAL; |
| 138 | 138 | ||
| 139 | /* eight is the minimum size for request and response frames */ | 139 | /* eight is the minimum size for request and response frames */ |
| 140 | if (req->data_len < 8 || rsp->data_len < 8) | 140 | if (blk_rq_bytes(req) < 8 || blk_rq_bytes(rsp) < 8) |
| 141 | goto out; | 141 | goto out; |
| 142 | 142 | ||
| 143 | if (bio_offset(req->bio) + req->data_len > PAGE_SIZE || | 143 | if (bio_offset(req->bio) + blk_rq_bytes(req) > PAGE_SIZE || |
| 144 | bio_offset(rsp->bio) + rsp->data_len > PAGE_SIZE) { | 144 | bio_offset(rsp->bio) + blk_rq_bytes(rsp) > PAGE_SIZE) { |
| 145 | shost_printk(KERN_ERR, shost, | 145 | shost_printk(KERN_ERR, shost, |
| 146 | "SMP request/response frame crosses page boundary"); | 146 | "SMP request/response frame crosses page boundary"); |
| 147 | goto out; | 147 | goto out; |
| 148 | } | 148 | } |
| 149 | 149 | ||
| 150 | req_data = kzalloc(req->data_len, GFP_KERNEL); | 150 | req_data = kzalloc(blk_rq_bytes(req), GFP_KERNEL); |
| 151 | 151 | ||
| 152 | /* make sure frame can always be built ... we copy | 152 | /* make sure frame can always be built ... we copy |
| 153 | * back only the requested length */ | 153 | * back only the requested length */ |
| 154 | resp_data = kzalloc(max(rsp->data_len, 128U), GFP_KERNEL); | 154 | resp_data = kzalloc(max(blk_rq_bytes(rsp), 128U), GFP_KERNEL); |
| 155 | 155 | ||
| 156 | if (!req_data || !resp_data) { | 156 | if (!req_data || !resp_data) { |
| 157 | error = -ENOMEM; | 157 | error = -ENOMEM; |
| @@ -160,7 +160,7 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
| 160 | 160 | ||
| 161 | local_irq_disable(); | 161 | local_irq_disable(); |
| 162 | buf = kmap_atomic(bio_page(req->bio), KM_USER0) + bio_offset(req->bio); | 162 | buf = kmap_atomic(bio_page(req->bio), KM_USER0) + bio_offset(req->bio); |
| 163 | memcpy(req_data, buf, req->data_len); | 163 | memcpy(req_data, buf, blk_rq_bytes(req)); |
| 164 | kunmap_atomic(buf - bio_offset(req->bio), KM_USER0); | 164 | kunmap_atomic(buf - bio_offset(req->bio), KM_USER0); |
| 165 | local_irq_enable(); | 165 | local_irq_enable(); |
| 166 | 166 | ||
| @@ -178,15 +178,15 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
| 178 | 178 | ||
| 179 | switch (req_data[1]) { | 179 | switch (req_data[1]) { |
| 180 | case SMP_REPORT_GENERAL: | 180 | case SMP_REPORT_GENERAL: |
| 181 | req->data_len -= 8; | 181 | req->resid_len -= 8; |
| 182 | resp_data_len -= 32; | 182 | rsp->resid_len -= 32; |
| 183 | resp_data[2] = SMP_RESP_FUNC_ACC; | 183 | resp_data[2] = SMP_RESP_FUNC_ACC; |
| 184 | resp_data[9] = sas_ha->num_phys; | 184 | resp_data[9] = sas_ha->num_phys; |
| 185 | break; | 185 | break; |
| 186 | 186 | ||
| 187 | case SMP_REPORT_MANUF_INFO: | 187 | case SMP_REPORT_MANUF_INFO: |
| 188 | req->data_len -= 8; | 188 | req->resid_len -= 8; |
| 189 | resp_data_len -= 64; | 189 | rsp->resid_len -= 64; |
| 190 | resp_data[2] = SMP_RESP_FUNC_ACC; | 190 | resp_data[2] = SMP_RESP_FUNC_ACC; |
| 191 | memcpy(resp_data + 12, shost->hostt->name, | 191 | memcpy(resp_data + 12, shost->hostt->name, |
| 192 | SAS_EXPANDER_VENDOR_ID_LEN); | 192 | SAS_EXPANDER_VENDOR_ID_LEN); |
| @@ -199,13 +199,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
| 199 | break; | 199 | break; |
| 200 | 200 | ||
| 201 | case SMP_DISCOVER: | 201 | case SMP_DISCOVER: |
| 202 | req->data_len -= 16; | 202 | req->resid_len -= 16; |
| 203 | if ((int)req->data_len < 0) { | 203 | if ((int)req->resid_len < 0) { |
| 204 | req->data_len = 0; | 204 | req->resid_len = 0; |
| 205 | error = -EINVAL; | 205 | error = -EINVAL; |
| 206 | goto out; | 206 | goto out; |
| 207 | } | 207 | } |
| 208 | resp_data_len -= 56; | 208 | rsp->resid_len -= 56; |
| 209 | sas_host_smp_discover(sas_ha, resp_data, req_data[9]); | 209 | sas_host_smp_discover(sas_ha, resp_data, req_data[9]); |
| 210 | break; | 210 | break; |
| 211 | 211 | ||
| @@ -215,13 +215,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
| 215 | break; | 215 | break; |
| 216 | 216 | ||
| 217 | case SMP_REPORT_PHY_SATA: | 217 | case SMP_REPORT_PHY_SATA: |
| 218 | req->data_len -= 16; | 218 | req->resid_len -= 16; |
| 219 | if ((int)req->data_len < 0) { | 219 | if ((int)req->resid_len < 0) { |
| 220 | req->data_len = 0; | 220 | req->resid_len = 0; |
| 221 | error = -EINVAL; | 221 | error = -EINVAL; |
| 222 | goto out; | 222 | goto out; |
| 223 | } | 223 | } |
| 224 | resp_data_len -= 60; | 224 | rsp->resid_len -= 60; |
| 225 | sas_report_phy_sata(sas_ha, resp_data, req_data[9]); | 225 | sas_report_phy_sata(sas_ha, resp_data, req_data[9]); |
| 226 | break; | 226 | break; |
| 227 | 227 | ||
| @@ -238,13 +238,13 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
| 238 | break; | 238 | break; |
| 239 | 239 | ||
| 240 | case SMP_PHY_CONTROL: | 240 | case SMP_PHY_CONTROL: |
| 241 | req->data_len -= 44; | 241 | req->resid_len -= 44; |
| 242 | if ((int)req->data_len < 0) { | 242 | if ((int)req->resid_len < 0) { |
| 243 | req->data_len = 0; | 243 | req->resid_len = 0; |
| 244 | error = -EINVAL; | 244 | error = -EINVAL; |
| 245 | goto out; | 245 | goto out; |
| 246 | } | 246 | } |
| 247 | resp_data_len -= 8; | 247 | rsp->resid_len -= 8; |
| 248 | sas_phy_control(sas_ha, req_data[9], req_data[10], | 248 | sas_phy_control(sas_ha, req_data[9], req_data[10], |
| 249 | req_data[32] >> 4, req_data[33] >> 4, | 249 | req_data[32] >> 4, req_data[33] >> 4, |
| 250 | resp_data); | 250 | resp_data); |
| @@ -261,11 +261,10 @@ int sas_smp_host_handler(struct Scsi_Host *shost, struct request *req, | |||
| 261 | 261 | ||
| 262 | local_irq_disable(); | 262 | local_irq_disable(); |
| 263 | buf = kmap_atomic(bio_page(rsp->bio), KM_USER0) + bio_offset(rsp->bio); | 263 | buf = kmap_atomic(bio_page(rsp->bio), KM_USER0) + bio_offset(rsp->bio); |
| 264 | memcpy(buf, resp_data, rsp->data_len); | 264 | memcpy(buf, resp_data, blk_rq_bytes(rsp)); |
| 265 | flush_kernel_dcache_page(bio_page(rsp->bio)); | 265 | flush_kernel_dcache_page(bio_page(rsp->bio)); |
| 266 | kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0); | 266 | kunmap_atomic(buf - bio_offset(rsp->bio), KM_USER0); |
| 267 | local_irq_enable(); | 267 | local_irq_enable(); |
| 268 | rsp->data_len = resp_data_len; | ||
| 269 | 268 | ||
| 270 | out: | 269 | out: |
| 271 | kfree(req_data); | 270 | kfree(req_data); |
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c index 167b66dd34c7..8032c5adb6a9 100644 --- a/drivers/scsi/lpfc/lpfc_scsi.c +++ b/drivers/scsi/lpfc/lpfc_scsi.c | |||
| @@ -1312,10 +1312,10 @@ lpfc_parse_bg_err(struct lpfc_hba *phba, struct lpfc_scsi_buf *lpfc_cmd, | |||
| 1312 | uint32_t bgstat = bgf->bgstat; | 1312 | uint32_t bgstat = bgf->bgstat; |
| 1313 | uint64_t failing_sector = 0; | 1313 | uint64_t failing_sector = 0; |
| 1314 | 1314 | ||
| 1315 | printk(KERN_ERR "BG ERROR in cmd 0x%x lba 0x%llx blk cnt 0x%lx " | 1315 | printk(KERN_ERR "BG ERROR in cmd 0x%x lba 0x%llx blk cnt 0x%x " |
| 1316 | "bgstat=0x%x bghm=0x%x\n", | 1316 | "bgstat=0x%x bghm=0x%x\n", |
| 1317 | cmd->cmnd[0], (unsigned long long)scsi_get_lba(cmd), | 1317 | cmd->cmnd[0], (unsigned long long)scsi_get_lba(cmd), |
| 1318 | cmd->request->nr_sectors, bgstat, bghm); | 1318 | blk_rq_sectors(cmd->request), bgstat, bghm); |
| 1319 | 1319 | ||
| 1320 | spin_lock(&_dump_buf_lock); | 1320 | spin_lock(&_dump_buf_lock); |
| 1321 | if (!_dump_buf_done) { | 1321 | if (!_dump_buf_done) { |
| @@ -2378,15 +2378,15 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
| 2378 | if (cmnd->cmnd[0] == READ_10) | 2378 | if (cmnd->cmnd[0] == READ_10) |
| 2379 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | 2379 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, |
| 2380 | "9035 BLKGRD: READ @ sector %llu, " | 2380 | "9035 BLKGRD: READ @ sector %llu, " |
| 2381 | "count %lu\n", | 2381 | "count %u\n", |
| 2382 | (unsigned long long)scsi_get_lba(cmnd), | 2382 | (unsigned long long)scsi_get_lba(cmnd), |
| 2383 | cmnd->request->nr_sectors); | 2383 | blk_rq_sectors(cmnd->request)); |
| 2384 | else if (cmnd->cmnd[0] == WRITE_10) | 2384 | else if (cmnd->cmnd[0] == WRITE_10) |
| 2385 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | 2385 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, |
| 2386 | "9036 BLKGRD: WRITE @ sector %llu, " | 2386 | "9036 BLKGRD: WRITE @ sector %llu, " |
| 2387 | "count %lu cmd=%p\n", | 2387 | "count %u cmd=%p\n", |
| 2388 | (unsigned long long)scsi_get_lba(cmnd), | 2388 | (unsigned long long)scsi_get_lba(cmnd), |
| 2389 | cmnd->request->nr_sectors, | 2389 | blk_rq_sectors(cmnd->request), |
| 2390 | cmnd); | 2390 | cmnd); |
| 2391 | 2391 | ||
| 2392 | err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); | 2392 | err = lpfc_bg_scsi_prep_dma_buf(phba, lpfc_cmd); |
| @@ -2406,15 +2406,15 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *)) | |||
| 2406 | if (cmnd->cmnd[0] == READ_10) | 2406 | if (cmnd->cmnd[0] == READ_10) |
| 2407 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | 2407 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, |
| 2408 | "9040 dbg: READ @ sector %llu, " | 2408 | "9040 dbg: READ @ sector %llu, " |
| 2409 | "count %lu\n", | 2409 | "count %u\n", |
| 2410 | (unsigned long long)scsi_get_lba(cmnd), | 2410 | (unsigned long long)scsi_get_lba(cmnd), |
| 2411 | cmnd->request->nr_sectors); | 2411 | blk_rq_sectors(cmnd->request)); |
| 2412 | else if (cmnd->cmnd[0] == WRITE_10) | 2412 | else if (cmnd->cmnd[0] == WRITE_10) |
| 2413 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | 2413 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, |
| 2414 | "9041 dbg: WRITE @ sector %llu, " | 2414 | "9041 dbg: WRITE @ sector %llu, " |
| 2415 | "count %lu cmd=%p\n", | 2415 | "count %u cmd=%p\n", |
| 2416 | (unsigned long long)scsi_get_lba(cmnd), | 2416 | (unsigned long long)scsi_get_lba(cmnd), |
| 2417 | cmnd->request->nr_sectors, cmnd); | 2417 | blk_rq_sectors(cmnd->request), cmnd); |
| 2418 | else | 2418 | else |
| 2419 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, | 2419 | lpfc_printf_vlog(vport, KERN_WARNING, LOG_BG, |
| 2420 | "9042 dbg: parser not implemented\n"); | 2420 | "9042 dbg: parser not implemented\n"); |
diff --git a/drivers/scsi/mpt2sas/mpt2sas_transport.c b/drivers/scsi/mpt2sas/mpt2sas_transport.c index e03dc0b1e1a0..5c65da519e39 100644 --- a/drivers/scsi/mpt2sas/mpt2sas_transport.c +++ b/drivers/scsi/mpt2sas/mpt2sas_transport.c | |||
| @@ -1041,7 +1041,7 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1041 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { | 1041 | if (req->bio->bi_vcnt > 1 || rsp->bio->bi_vcnt > 1) { |
| 1042 | printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, " | 1042 | printk(MPT2SAS_ERR_FMT "%s: multiple segments req %u %u, " |
| 1043 | "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt, | 1043 | "rsp %u %u\n", ioc->name, __func__, req->bio->bi_vcnt, |
| 1044 | req->data_len, rsp->bio->bi_vcnt, rsp->data_len); | 1044 | blk_rq_bytes(req), rsp->bio->bi_vcnt, blk_rq_bytes(rsp)); |
| 1045 | return -EINVAL; | 1045 | return -EINVAL; |
| 1046 | } | 1046 | } |
| 1047 | 1047 | ||
| @@ -1104,7 +1104,7 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1104 | *((u64 *)&mpi_request->SASAddress) = (rphy) ? | 1104 | *((u64 *)&mpi_request->SASAddress) = (rphy) ? |
| 1105 | cpu_to_le64(rphy->identify.sas_address) : | 1105 | cpu_to_le64(rphy->identify.sas_address) : |
| 1106 | cpu_to_le64(ioc->sas_hba.sas_address); | 1106 | cpu_to_le64(ioc->sas_hba.sas_address); |
| 1107 | mpi_request->RequestDataLength = cpu_to_le16(req->data_len - 4); | 1107 | mpi_request->RequestDataLength = cpu_to_le16(blk_rq_bytes(req) - 4); |
| 1108 | psge = &mpi_request->SGL; | 1108 | psge = &mpi_request->SGL; |
| 1109 | 1109 | ||
| 1110 | /* WRITE sgel first */ | 1110 | /* WRITE sgel first */ |
| @@ -1112,13 +1112,13 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1112 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); | 1112 | MPI2_SGE_FLAGS_END_OF_BUFFER | MPI2_SGE_FLAGS_HOST_TO_IOC); |
| 1113 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | 1113 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; |
| 1114 | dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), | 1114 | dma_addr_out = pci_map_single(ioc->pdev, bio_data(req->bio), |
| 1115 | req->data_len, PCI_DMA_BIDIRECTIONAL); | 1115 | blk_rq_bytes(req), PCI_DMA_BIDIRECTIONAL); |
| 1116 | if (!dma_addr_out) { | 1116 | if (!dma_addr_out) { |
| 1117 | mpt2sas_base_free_smid(ioc, le16_to_cpu(smid)); | 1117 | mpt2sas_base_free_smid(ioc, le16_to_cpu(smid)); |
| 1118 | goto unmap; | 1118 | goto unmap; |
| 1119 | } | 1119 | } |
| 1120 | 1120 | ||
| 1121 | ioc->base_add_sg_single(psge, sgl_flags | (req->data_len - 4), | 1121 | ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(req) - 4), |
| 1122 | dma_addr_out); | 1122 | dma_addr_out); |
| 1123 | 1123 | ||
| 1124 | /* incr sgel */ | 1124 | /* incr sgel */ |
| @@ -1129,14 +1129,14 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1129 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | | 1129 | MPI2_SGE_FLAGS_LAST_ELEMENT | MPI2_SGE_FLAGS_END_OF_BUFFER | |
| 1130 | MPI2_SGE_FLAGS_END_OF_LIST); | 1130 | MPI2_SGE_FLAGS_END_OF_LIST); |
| 1131 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; | 1131 | sgl_flags = sgl_flags << MPI2_SGE_FLAGS_SHIFT; |
| 1132 | dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), | 1132 | dma_addr_in = pci_map_single(ioc->pdev, bio_data(rsp->bio), |
| 1133 | rsp->data_len, PCI_DMA_BIDIRECTIONAL); | 1133 | blk_rq_bytes(rsp), PCI_DMA_BIDIRECTIONAL); |
| 1134 | if (!dma_addr_in) { | 1134 | if (!dma_addr_in) { |
| 1135 | mpt2sas_base_free_smid(ioc, le16_to_cpu(smid)); | 1135 | mpt2sas_base_free_smid(ioc, le16_to_cpu(smid)); |
| 1136 | goto unmap; | 1136 | goto unmap; |
| 1137 | } | 1137 | } |
| 1138 | 1138 | ||
| 1139 | ioc->base_add_sg_single(psge, sgl_flags | (rsp->data_len + 4), | 1139 | ioc->base_add_sg_single(psge, sgl_flags | (blk_rq_bytes(rsp) + 4), |
| 1140 | dma_addr_in); | 1140 | dma_addr_in); |
| 1141 | 1141 | ||
| 1142 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " | 1142 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT "%s - " |
| @@ -1170,9 +1170,8 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1170 | 1170 | ||
| 1171 | memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); | 1171 | memcpy(req->sense, mpi_reply, sizeof(*mpi_reply)); |
| 1172 | req->sense_len = sizeof(*mpi_reply); | 1172 | req->sense_len = sizeof(*mpi_reply); |
| 1173 | req->data_len = 0; | 1173 | req->resid_len = 0; |
| 1174 | rsp->data_len -= mpi_reply->ResponseDataLength; | 1174 | rsp->resid_len -= mpi_reply->ResponseDataLength; |
| 1175 | |||
| 1176 | } else { | 1175 | } else { |
| 1177 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT | 1176 | dtransportprintk(ioc, printk(MPT2SAS_DEBUG_FMT |
| 1178 | "%s - no reply\n", ioc->name, __func__)); | 1177 | "%s - no reply\n", ioc->name, __func__)); |
| @@ -1188,10 +1187,10 @@ transport_smp_handler(struct Scsi_Host *shost, struct sas_rphy *rphy, | |||
| 1188 | 1187 | ||
| 1189 | unmap: | 1188 | unmap: |
| 1190 | if (dma_addr_out) | 1189 | if (dma_addr_out) |
| 1191 | pci_unmap_single(ioc->pdev, dma_addr_out, req->data_len, | 1190 | pci_unmap_single(ioc->pdev, dma_addr_out, blk_rq_bytes(req), |
| 1192 | PCI_DMA_BIDIRECTIONAL); | 1191 | PCI_DMA_BIDIRECTIONAL); |
| 1193 | if (dma_addr_in) | 1192 | if (dma_addr_in) |
| 1194 | pci_unmap_single(ioc->pdev, dma_addr_in, rsp->data_len, | 1193 | pci_unmap_single(ioc->pdev, dma_addr_in, blk_rq_bytes(rsp), |
| 1195 | PCI_DMA_BIDIRECTIONAL); | 1194 | PCI_DMA_BIDIRECTIONAL); |
| 1196 | 1195 | ||
| 1197 | out: | 1196 | out: |
diff --git a/drivers/scsi/osd/osd_initiator.c b/drivers/scsi/osd/osd_initiator.c index 1ce6b24abab2..5776b2ab6b12 100644 --- a/drivers/scsi/osd/osd_initiator.c +++ b/drivers/scsi/osd/osd_initiator.c | |||
| @@ -889,26 +889,6 @@ int osd_req_add_set_attr_list(struct osd_request *or, | |||
| 889 | } | 889 | } |
| 890 | EXPORT_SYMBOL(osd_req_add_set_attr_list); | 890 | EXPORT_SYMBOL(osd_req_add_set_attr_list); |
| 891 | 891 | ||
| 892 | static int _append_map_kern(struct request *req, | ||
| 893 | void *buff, unsigned len, gfp_t flags) | ||
| 894 | { | ||
| 895 | struct bio *bio; | ||
| 896 | int ret; | ||
| 897 | |||
| 898 | bio = bio_map_kern(req->q, buff, len, flags); | ||
| 899 | if (IS_ERR(bio)) { | ||
| 900 | OSD_ERR("Failed bio_map_kern(%p, %d) => %ld\n", buff, len, | ||
| 901 | PTR_ERR(bio)); | ||
| 902 | return PTR_ERR(bio); | ||
| 903 | } | ||
| 904 | ret = blk_rq_append_bio(req->q, req, bio); | ||
| 905 | if (ret) { | ||
| 906 | OSD_ERR("Failed blk_rq_append_bio(%p) => %d\n", bio, ret); | ||
| 907 | bio_put(bio); | ||
| 908 | } | ||
| 909 | return ret; | ||
| 910 | } | ||
| 911 | |||
| 912 | static int _req_append_segment(struct osd_request *or, | 892 | static int _req_append_segment(struct osd_request *or, |
| 913 | unsigned padding, struct _osd_req_data_segment *seg, | 893 | unsigned padding, struct _osd_req_data_segment *seg, |
| 914 | struct _osd_req_data_segment *last_seg, struct _osd_io_info *io) | 894 | struct _osd_req_data_segment *last_seg, struct _osd_io_info *io) |
| @@ -924,14 +904,14 @@ static int _req_append_segment(struct osd_request *or, | |||
| 924 | else | 904 | else |
| 925 | pad_buff = io->pad_buff; | 905 | pad_buff = io->pad_buff; |
| 926 | 906 | ||
| 927 | ret = _append_map_kern(io->req, pad_buff, padding, | 907 | ret = blk_rq_map_kern(io->req->q, io->req, pad_buff, padding, |
| 928 | or->alloc_flags); | 908 | or->alloc_flags); |
| 929 | if (ret) | 909 | if (ret) |
| 930 | return ret; | 910 | return ret; |
| 931 | io->total_bytes += padding; | 911 | io->total_bytes += padding; |
| 932 | } | 912 | } |
| 933 | 913 | ||
| 934 | ret = _append_map_kern(io->req, seg->buff, seg->total_bytes, | 914 | ret = blk_rq_map_kern(io->req->q, io->req, seg->buff, seg->total_bytes, |
| 935 | or->alloc_flags); | 915 | or->alloc_flags); |
| 936 | if (ret) | 916 | if (ret) |
| 937 | return ret; | 917 | return ret; |
| @@ -1293,6 +1273,21 @@ static int _osd_req_finalize_data_integrity(struct osd_request *or, | |||
| 1293 | /* | 1273 | /* |
| 1294 | * osd_finalize_request and helpers | 1274 | * osd_finalize_request and helpers |
| 1295 | */ | 1275 | */ |
| 1276 | static struct request *_make_request(struct request_queue *q, bool has_write, | ||
| 1277 | struct _osd_io_info *oii, gfp_t flags) | ||
| 1278 | { | ||
| 1279 | if (oii->bio) | ||
| 1280 | return blk_make_request(q, oii->bio, flags); | ||
| 1281 | else { | ||
| 1282 | struct request *req; | ||
| 1283 | |||
| 1284 | req = blk_get_request(q, has_write ? WRITE : READ, flags); | ||
| 1285 | if (unlikely(!req)) | ||
| 1286 | return ERR_PTR(-ENOMEM); | ||
| 1287 | |||
| 1288 | return req; | ||
| 1289 | } | ||
| 1290 | } | ||
| 1296 | 1291 | ||
| 1297 | static int _init_blk_request(struct osd_request *or, | 1292 | static int _init_blk_request(struct osd_request *or, |
| 1298 | bool has_in, bool has_out) | 1293 | bool has_in, bool has_out) |
| @@ -1301,11 +1296,13 @@ static int _init_blk_request(struct osd_request *or, | |||
| 1301 | struct scsi_device *scsi_device = or->osd_dev->scsi_device; | 1296 | struct scsi_device *scsi_device = or->osd_dev->scsi_device; |
| 1302 | struct request_queue *q = scsi_device->request_queue; | 1297 | struct request_queue *q = scsi_device->request_queue; |
| 1303 | struct request *req; | 1298 | struct request *req; |
| 1304 | int ret = -ENOMEM; | 1299 | int ret; |
| 1305 | 1300 | ||
| 1306 | req = blk_get_request(q, has_out, flags); | 1301 | req = _make_request(q, has_out, has_out ? &or->out : &or->in, flags); |
| 1307 | if (!req) | 1302 | if (IS_ERR(req)) { |
| 1303 | ret = PTR_ERR(req); | ||
| 1308 | goto out; | 1304 | goto out; |
| 1305 | } | ||
| 1309 | 1306 | ||
| 1310 | or->request = req; | 1307 | or->request = req; |
| 1311 | req->cmd_type = REQ_TYPE_BLOCK_PC; | 1308 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
| @@ -1318,9 +1315,10 @@ static int _init_blk_request(struct osd_request *or, | |||
| 1318 | or->out.req = req; | 1315 | or->out.req = req; |
| 1319 | if (has_in) { | 1316 | if (has_in) { |
| 1320 | /* allocate bidi request */ | 1317 | /* allocate bidi request */ |
| 1321 | req = blk_get_request(q, READ, flags); | 1318 | req = _make_request(q, false, &or->in, flags); |
| 1322 | if (!req) { | 1319 | if (IS_ERR(req)) { |
| 1323 | OSD_DEBUG("blk_get_request for bidi failed\n"); | 1320 | OSD_DEBUG("blk_get_request for bidi failed\n"); |
| 1321 | ret = PTR_ERR(req); | ||
| 1324 | goto out; | 1322 | goto out; |
| 1325 | } | 1323 | } |
| 1326 | req->cmd_type = REQ_TYPE_BLOCK_PC; | 1324 | req->cmd_type = REQ_TYPE_BLOCK_PC; |
| @@ -1364,26 +1362,6 @@ int osd_finalize_request(struct osd_request *or, | |||
| 1364 | return ret; | 1362 | return ret; |
| 1365 | } | 1363 | } |
| 1366 | 1364 | ||
| 1367 | if (or->out.bio) { | ||
| 1368 | ret = blk_rq_append_bio(or->request->q, or->out.req, | ||
| 1369 | or->out.bio); | ||
| 1370 | if (ret) { | ||
| 1371 | OSD_DEBUG("blk_rq_append_bio out failed\n"); | ||
| 1372 | return ret; | ||
| 1373 | } | ||
| 1374 | OSD_DEBUG("out bytes=%llu (bytes_req=%u)\n", | ||
| 1375 | _LLU(or->out.total_bytes), or->out.req->data_len); | ||
| 1376 | } | ||
| 1377 | if (or->in.bio) { | ||
| 1378 | ret = blk_rq_append_bio(or->request->q, or->in.req, or->in.bio); | ||
| 1379 | if (ret) { | ||
| 1380 | OSD_DEBUG("blk_rq_append_bio in failed\n"); | ||
| 1381 | return ret; | ||
| 1382 | } | ||
| 1383 | OSD_DEBUG("in bytes=%llu (bytes_req=%u)\n", | ||
| 1384 | _LLU(or->in.total_bytes), or->in.req->data_len); | ||
| 1385 | } | ||
| 1386 | |||
| 1387 | or->out.pad_buff = sg_out_pad_buffer; | 1365 | or->out.pad_buff = sg_out_pad_buffer; |
| 1388 | or->in.pad_buff = sg_in_pad_buffer; | 1366 | or->in.pad_buff = sg_in_pad_buffer; |
| 1389 | 1367 | ||
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c index bb218c8b6e98..dd3f9d2b99fd 100644 --- a/drivers/scsi/scsi_lib.c +++ b/drivers/scsi/scsi_lib.c | |||
| @@ -240,11 +240,11 @@ int scsi_execute(struct scsi_device *sdev, const unsigned char *cmd, | |||
| 240 | * is invalid. Prevent the garbage from being misinterpreted | 240 | * is invalid. Prevent the garbage from being misinterpreted |
| 241 | * and prevent security leaks by zeroing out the excess data. | 241 | * and prevent security leaks by zeroing out the excess data. |
| 242 | */ | 242 | */ |
| 243 | if (unlikely(req->data_len > 0 && req->data_len <= bufflen)) | 243 | if (unlikely(req->resid_len > 0 && req->resid_len <= bufflen)) |
| 244 | memset(buffer + (bufflen - req->data_len), 0, req->data_len); | 244 | memset(buffer + (bufflen - req->resid_len), 0, req->resid_len); |
| 245 | 245 | ||
| 246 | if (resid) | 246 | if (resid) |
| 247 | *resid = req->data_len; | 247 | *resid = req->resid_len; |
| 248 | ret = req->errors; | 248 | ret = req->errors; |
| 249 | out: | 249 | out: |
| 250 | blk_put_request(req); | 250 | blk_put_request(req); |
| @@ -546,14 +546,9 @@ static struct scsi_cmnd *scsi_end_request(struct scsi_cmnd *cmd, int error, | |||
| 546 | * to queue the remainder of them. | 546 | * to queue the remainder of them. |
| 547 | */ | 547 | */ |
| 548 | if (blk_end_request(req, error, bytes)) { | 548 | if (blk_end_request(req, error, bytes)) { |
| 549 | int leftover = (req->hard_nr_sectors << 9); | ||
| 550 | |||
| 551 | if (blk_pc_request(req)) | ||
| 552 | leftover = req->data_len; | ||
| 553 | |||
| 554 | /* kill remainder if no retrys */ | 549 | /* kill remainder if no retrys */ |
| 555 | if (error && scsi_noretry_cmd(cmd)) | 550 | if (error && scsi_noretry_cmd(cmd)) |
| 556 | blk_end_request(req, error, leftover); | 551 | blk_end_request_all(req, error); |
| 557 | else { | 552 | else { |
| 558 | if (requeue) { | 553 | if (requeue) { |
| 559 | /* | 554 | /* |
| @@ -673,34 +668,6 @@ void scsi_release_buffers(struct scsi_cmnd *cmd) | |||
| 673 | EXPORT_SYMBOL(scsi_release_buffers); | 668 | EXPORT_SYMBOL(scsi_release_buffers); |
| 674 | 669 | ||
| 675 | /* | 670 | /* |
| 676 | * Bidi commands Must be complete as a whole, both sides at once. | ||
| 677 | * If part of the bytes were written and lld returned | ||
| 678 | * scsi_in()->resid and/or scsi_out()->resid this information will be left | ||
| 679 | * in req->data_len and req->next_rq->data_len. The upper-layer driver can | ||
| 680 | * decide what to do with this information. | ||
| 681 | */ | ||
| 682 | static void scsi_end_bidi_request(struct scsi_cmnd *cmd) | ||
| 683 | { | ||
| 684 | struct request *req = cmd->request; | ||
| 685 | unsigned int dlen = req->data_len; | ||
| 686 | unsigned int next_dlen = req->next_rq->data_len; | ||
| 687 | |||
| 688 | req->data_len = scsi_out(cmd)->resid; | ||
| 689 | req->next_rq->data_len = scsi_in(cmd)->resid; | ||
| 690 | |||
| 691 | /* The req and req->next_rq have not been completed */ | ||
| 692 | BUG_ON(blk_end_bidi_request(req, 0, dlen, next_dlen)); | ||
| 693 | |||
| 694 | scsi_release_buffers(cmd); | ||
| 695 | |||
| 696 | /* | ||
| 697 | * This will goose the queue request function at the end, so we don't | ||
| 698 | * need to worry about launching another command. | ||
| 699 | */ | ||
| 700 | scsi_next_command(cmd); | ||
| 701 | } | ||
| 702 | |||
| 703 | /* | ||
| 704 | * Function: scsi_io_completion() | 671 | * Function: scsi_io_completion() |
| 705 | * | 672 | * |
| 706 | * Purpose: Completion processing for block device I/O requests. | 673 | * Purpose: Completion processing for block device I/O requests. |
| @@ -739,7 +706,6 @@ static void scsi_end_bidi_request(struct scsi_cmnd *cmd) | |||
| 739 | void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | 706 | void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) |
| 740 | { | 707 | { |
| 741 | int result = cmd->result; | 708 | int result = cmd->result; |
| 742 | int this_count; | ||
| 743 | struct request_queue *q = cmd->device->request_queue; | 709 | struct request_queue *q = cmd->device->request_queue; |
| 744 | struct request *req = cmd->request; | 710 | struct request *req = cmd->request; |
| 745 | int error = 0; | 711 | int error = 0; |
| @@ -773,12 +739,22 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 773 | if (!sense_deferred) | 739 | if (!sense_deferred) |
| 774 | error = -EIO; | 740 | error = -EIO; |
| 775 | } | 741 | } |
| 742 | |||
| 743 | req->resid_len = scsi_get_resid(cmd); | ||
| 744 | |||
| 776 | if (scsi_bidi_cmnd(cmd)) { | 745 | if (scsi_bidi_cmnd(cmd)) { |
| 777 | /* will also release_buffers */ | 746 | /* |
| 778 | scsi_end_bidi_request(cmd); | 747 | * Bidi commands Must be complete as a whole, |
| 748 | * both sides at once. | ||
| 749 | */ | ||
| 750 | req->next_rq->resid_len = scsi_in(cmd)->resid; | ||
| 751 | |||
| 752 | blk_end_request_all(req, 0); | ||
| 753 | |||
| 754 | scsi_release_buffers(cmd); | ||
| 755 | scsi_next_command(cmd); | ||
| 779 | return; | 756 | return; |
| 780 | } | 757 | } |
| 781 | req->data_len = scsi_get_resid(cmd); | ||
| 782 | } | 758 | } |
| 783 | 759 | ||
| 784 | BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ | 760 | BUG_ON(blk_bidi_rq(req)); /* bidi not support for !blk_pc_request yet */ |
| @@ -787,9 +763,9 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 787 | * Next deal with any sectors which we were able to correctly | 763 | * Next deal with any sectors which we were able to correctly |
| 788 | * handle. | 764 | * handle. |
| 789 | */ | 765 | */ |
| 790 | SCSI_LOG_HLCOMPLETE(1, printk("%ld sectors total, " | 766 | SCSI_LOG_HLCOMPLETE(1, printk("%u sectors total, " |
| 791 | "%d bytes done.\n", | 767 | "%d bytes done.\n", |
| 792 | req->nr_sectors, good_bytes)); | 768 | blk_rq_sectors(req), good_bytes)); |
| 793 | 769 | ||
| 794 | /* | 770 | /* |
| 795 | * Recovered errors need reporting, but they're always treated | 771 | * Recovered errors need reporting, but they're always treated |
| @@ -812,7 +788,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 812 | */ | 788 | */ |
| 813 | if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) | 789 | if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL) |
| 814 | return; | 790 | return; |
| 815 | this_count = blk_rq_bytes(req); | ||
| 816 | 791 | ||
| 817 | error = -EIO; | 792 | error = -EIO; |
| 818 | 793 | ||
| @@ -922,7 +897,7 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes) | |||
| 922 | if (driver_byte(result) & DRIVER_SENSE) | 897 | if (driver_byte(result) & DRIVER_SENSE) |
| 923 | scsi_print_sense("", cmd); | 898 | scsi_print_sense("", cmd); |
| 924 | } | 899 | } |
| 925 | blk_end_request(req, -EIO, blk_rq_bytes(req)); | 900 | blk_end_request_all(req, -EIO); |
| 926 | scsi_next_command(cmd); | 901 | scsi_next_command(cmd); |
| 927 | break; | 902 | break; |
| 928 | case ACTION_REPREP: | 903 | case ACTION_REPREP: |
| @@ -965,10 +940,7 @@ static int scsi_init_sgtable(struct request *req, struct scsi_data_buffer *sdb, | |||
| 965 | count = blk_rq_map_sg(req->q, req, sdb->table.sgl); | 940 | count = blk_rq_map_sg(req->q, req, sdb->table.sgl); |
| 966 | BUG_ON(count > sdb->table.nents); | 941 | BUG_ON(count > sdb->table.nents); |
| 967 | sdb->table.nents = count; | 942 | sdb->table.nents = count; |
| 968 | if (blk_pc_request(req)) | 943 | sdb->length = blk_rq_bytes(req); |
| 969 | sdb->length = req->data_len; | ||
| 970 | else | ||
| 971 | sdb->length = req->nr_sectors << 9; | ||
| 972 | return BLKPREP_OK; | 944 | return BLKPREP_OK; |
| 973 | } | 945 | } |
| 974 | 946 | ||
| @@ -1087,22 +1059,21 @@ int scsi_setup_blk_pc_cmnd(struct scsi_device *sdev, struct request *req) | |||
| 1087 | if (unlikely(ret)) | 1059 | if (unlikely(ret)) |
| 1088 | return ret; | 1060 | return ret; |
| 1089 | } else { | 1061 | } else { |
| 1090 | BUG_ON(req->data_len); | 1062 | BUG_ON(blk_rq_bytes(req)); |
| 1091 | BUG_ON(req->data); | ||
| 1092 | 1063 | ||
| 1093 | memset(&cmd->sdb, 0, sizeof(cmd->sdb)); | 1064 | memset(&cmd->sdb, 0, sizeof(cmd->sdb)); |
| 1094 | req->buffer = NULL; | 1065 | req->buffer = NULL; |
| 1095 | } | 1066 | } |
| 1096 | 1067 | ||
| 1097 | cmd->cmd_len = req->cmd_len; | 1068 | cmd->cmd_len = req->cmd_len; |
| 1098 | if (!req->data_len) | 1069 | if (!blk_rq_bytes(req)) |
| 1099 | cmd->sc_data_direction = DMA_NONE; | 1070 | cmd->sc_data_direction = DMA_NONE; |
| 1100 | else if (rq_data_dir(req) == WRITE) | 1071 | else if (rq_data_dir(req) == WRITE) |
| 1101 | cmd->sc_data_direction = DMA_TO_DEVICE; | 1072 | cmd->sc_data_direction = DMA_TO_DEVICE; |
| 1102 | else | 1073 | else |
| 1103 | cmd->sc_data_direction = DMA_FROM_DEVICE; | 1074 | cmd->sc_data_direction = DMA_FROM_DEVICE; |
| 1104 | 1075 | ||
| 1105 | cmd->transfersize = req->data_len; | 1076 | cmd->transfersize = blk_rq_bytes(req); |
| 1106 | cmd->allowed = req->retries; | 1077 | cmd->allowed = req->retries; |
| 1107 | return BLKPREP_OK; | 1078 | return BLKPREP_OK; |
| 1108 | } | 1079 | } |
| @@ -1212,7 +1183,7 @@ int scsi_prep_return(struct request_queue *q, struct request *req, int ret) | |||
| 1212 | break; | 1183 | break; |
| 1213 | case BLKPREP_DEFER: | 1184 | case BLKPREP_DEFER: |
| 1214 | /* | 1185 | /* |
| 1215 | * If we defer, the elv_next_request() returns NULL, but the | 1186 | * If we defer, the blk_peek_request() returns NULL, but the |
| 1216 | * queue must be restarted, so we plug here if no returning | 1187 | * queue must be restarted, so we plug here if no returning |
| 1217 | * command will automatically do that. | 1188 | * command will automatically do that. |
| 1218 | */ | 1189 | */ |
| @@ -1388,7 +1359,7 @@ static void scsi_kill_request(struct request *req, struct request_queue *q) | |||
| 1388 | struct scsi_target *starget = scsi_target(sdev); | 1359 | struct scsi_target *starget = scsi_target(sdev); |
| 1389 | struct Scsi_Host *shost = sdev->host; | 1360 | struct Scsi_Host *shost = sdev->host; |
| 1390 | 1361 | ||
| 1391 | blkdev_dequeue_request(req); | 1362 | blk_start_request(req); |
| 1392 | 1363 | ||
| 1393 | if (unlikely(cmd == NULL)) { | 1364 | if (unlikely(cmd == NULL)) { |
| 1394 | printk(KERN_CRIT "impossible request in %s.\n", | 1365 | printk(KERN_CRIT "impossible request in %s.\n", |
| @@ -1480,7 +1451,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
| 1480 | 1451 | ||
| 1481 | if (!sdev) { | 1452 | if (!sdev) { |
| 1482 | printk("scsi: killing requests for dead queue\n"); | 1453 | printk("scsi: killing requests for dead queue\n"); |
| 1483 | while ((req = elv_next_request(q)) != NULL) | 1454 | while ((req = blk_peek_request(q)) != NULL) |
| 1484 | scsi_kill_request(req, q); | 1455 | scsi_kill_request(req, q); |
| 1485 | return; | 1456 | return; |
| 1486 | } | 1457 | } |
| @@ -1501,7 +1472,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
| 1501 | * that the request is fully prepared even if we cannot | 1472 | * that the request is fully prepared even if we cannot |
| 1502 | * accept it. | 1473 | * accept it. |
| 1503 | */ | 1474 | */ |
| 1504 | req = elv_next_request(q); | 1475 | req = blk_peek_request(q); |
| 1505 | if (!req || !scsi_dev_queue_ready(q, sdev)) | 1476 | if (!req || !scsi_dev_queue_ready(q, sdev)) |
| 1506 | break; | 1477 | break; |
| 1507 | 1478 | ||
| @@ -1517,7 +1488,7 @@ static void scsi_request_fn(struct request_queue *q) | |||
| 1517 | * Remove the request from the request list. | 1488 | * Remove the request from the request list. |
| 1518 | */ | 1489 | */ |
| 1519 | if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req))) | 1490 | if (!(blk_queue_tagged(q) && !blk_queue_start_tag(q, req))) |
| 1520 | blkdev_dequeue_request(req); | 1491 | blk_start_request(req); |
| 1521 | sdev->device_busy++; | 1492 | sdev->device_busy++; |
| 1522 | 1493 | ||
| 1523 | spin_unlock(q->queue_lock); | 1494 | spin_unlock(q->queue_lock); |
diff --git a/drivers/scsi/scsi_tgt_lib.c b/drivers/scsi/scsi_tgt_lib.c index 48ba413f7f6a..10303272ba45 100644 --- a/drivers/scsi/scsi_tgt_lib.c +++ b/drivers/scsi/scsi_tgt_lib.c | |||
| @@ -387,7 +387,7 @@ static int scsi_map_user_pages(struct scsi_tgt_cmd *tcmd, struct scsi_cmnd *cmd, | |||
| 387 | * we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn't set the | 387 | * we use REQ_TYPE_BLOCK_PC so scsi_init_io doesn't set the |
| 388 | * length for us. | 388 | * length for us. |
| 389 | */ | 389 | */ |
| 390 | cmd->sdb.length = rq->data_len; | 390 | cmd->sdb.length = blk_rq_bytes(rq); |
| 391 | 391 | ||
| 392 | return 0; | 392 | return 0; |
| 393 | 393 | ||
diff --git a/drivers/scsi/scsi_transport_sas.c b/drivers/scsi/scsi_transport_sas.c index 50988cbf7b2d..d606452297cf 100644 --- a/drivers/scsi/scsi_transport_sas.c +++ b/drivers/scsi/scsi_transport_sas.c | |||
| @@ -163,12 +163,10 @@ static void sas_smp_request(struct request_queue *q, struct Scsi_Host *shost, | |||
| 163 | int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); | 163 | int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *); |
| 164 | 164 | ||
| 165 | while (!blk_queue_plugged(q)) { | 165 | while (!blk_queue_plugged(q)) { |
| 166 | req = elv_next_request(q); | 166 | req = blk_fetch_request(q); |
| 167 | if (!req) | 167 | if (!req) |
| 168 | break; | 168 | break; |
| 169 | 169 | ||
| 170 | blkdev_dequeue_request(req); | ||
| 171 | |||
| 172 | spin_unlock_irq(q->queue_lock); | 170 | spin_unlock_irq(q->queue_lock); |
| 173 | 171 | ||
| 174 | handler = to_sas_internal(shost->transportt)->f->smp_handler; | 172 | handler = to_sas_internal(shost->transportt)->f->smp_handler; |
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 84044233b637..bcf3bd40bbd5 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c | |||
| @@ -384,9 +384,9 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 384 | struct scsi_device *sdp = q->queuedata; | 384 | struct scsi_device *sdp = q->queuedata; |
| 385 | struct gendisk *disk = rq->rq_disk; | 385 | struct gendisk *disk = rq->rq_disk; |
| 386 | struct scsi_disk *sdkp; | 386 | struct scsi_disk *sdkp; |
| 387 | sector_t block = rq->sector; | 387 | sector_t block = blk_rq_pos(rq); |
| 388 | sector_t threshold; | 388 | sector_t threshold; |
| 389 | unsigned int this_count = rq->nr_sectors; | 389 | unsigned int this_count = blk_rq_sectors(rq); |
| 390 | int ret, host_dif; | 390 | int ret, host_dif; |
| 391 | 391 | ||
| 392 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { | 392 | if (rq->cmd_type == REQ_TYPE_BLOCK_PC) { |
| @@ -413,10 +413,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 413 | this_count)); | 413 | this_count)); |
| 414 | 414 | ||
| 415 | if (!sdp || !scsi_device_online(sdp) || | 415 | if (!sdp || !scsi_device_online(sdp) || |
| 416 | block + rq->nr_sectors > get_capacity(disk)) { | 416 | block + blk_rq_sectors(rq) > get_capacity(disk)) { |
| 417 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, | 417 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, |
| 418 | "Finishing %ld sectors\n", | 418 | "Finishing %u sectors\n", |
| 419 | rq->nr_sectors)); | 419 | blk_rq_sectors(rq))); |
| 420 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, | 420 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, |
| 421 | "Retry with 0x%p\n", SCpnt)); | 421 | "Retry with 0x%p\n", SCpnt)); |
| 422 | goto out; | 422 | goto out; |
| @@ -463,7 +463,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 463 | * for this. | 463 | * for this. |
| 464 | */ | 464 | */ |
| 465 | if (sdp->sector_size == 1024) { | 465 | if (sdp->sector_size == 1024) { |
| 466 | if ((block & 1) || (rq->nr_sectors & 1)) { | 466 | if ((block & 1) || (blk_rq_sectors(rq) & 1)) { |
| 467 | scmd_printk(KERN_ERR, SCpnt, | 467 | scmd_printk(KERN_ERR, SCpnt, |
| 468 | "Bad block number requested\n"); | 468 | "Bad block number requested\n"); |
| 469 | goto out; | 469 | goto out; |
| @@ -473,7 +473,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 473 | } | 473 | } |
| 474 | } | 474 | } |
| 475 | if (sdp->sector_size == 2048) { | 475 | if (sdp->sector_size == 2048) { |
| 476 | if ((block & 3) || (rq->nr_sectors & 3)) { | 476 | if ((block & 3) || (blk_rq_sectors(rq) & 3)) { |
| 477 | scmd_printk(KERN_ERR, SCpnt, | 477 | scmd_printk(KERN_ERR, SCpnt, |
| 478 | "Bad block number requested\n"); | 478 | "Bad block number requested\n"); |
| 479 | goto out; | 479 | goto out; |
| @@ -483,7 +483,7 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 483 | } | 483 | } |
| 484 | } | 484 | } |
| 485 | if (sdp->sector_size == 4096) { | 485 | if (sdp->sector_size == 4096) { |
| 486 | if ((block & 7) || (rq->nr_sectors & 7)) { | 486 | if ((block & 7) || (blk_rq_sectors(rq) & 7)) { |
| 487 | scmd_printk(KERN_ERR, SCpnt, | 487 | scmd_printk(KERN_ERR, SCpnt, |
| 488 | "Bad block number requested\n"); | 488 | "Bad block number requested\n"); |
| 489 | goto out; | 489 | goto out; |
| @@ -512,10 +512,10 @@ static int sd_prep_fn(struct request_queue *q, struct request *rq) | |||
| 512 | } | 512 | } |
| 513 | 513 | ||
| 514 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, | 514 | SCSI_LOG_HLQUEUE(2, scmd_printk(KERN_INFO, SCpnt, |
| 515 | "%s %d/%ld 512 byte blocks.\n", | 515 | "%s %d/%u 512 byte blocks.\n", |
| 516 | (rq_data_dir(rq) == WRITE) ? | 516 | (rq_data_dir(rq) == WRITE) ? |
| 517 | "writing" : "reading", this_count, | 517 | "writing" : "reading", this_count, |
| 518 | rq->nr_sectors)); | 518 | blk_rq_sectors(rq))); |
| 519 | 519 | ||
| 520 | /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */ | 520 | /* Set RDPROTECT/WRPROTECT if disk is formatted with DIF */ |
| 521 | host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); | 521 | host_dif = scsi_host_dif_capable(sdp->host, sdkp->protection_type); |
| @@ -971,8 +971,8 @@ static struct block_device_operations sd_fops = { | |||
| 971 | 971 | ||
| 972 | static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) | 972 | static unsigned int sd_completed_bytes(struct scsi_cmnd *scmd) |
| 973 | { | 973 | { |
| 974 | u64 start_lba = scmd->request->sector; | 974 | u64 start_lba = blk_rq_pos(scmd->request); |
| 975 | u64 end_lba = scmd->request->sector + (scsi_bufflen(scmd) / 512); | 975 | u64 end_lba = blk_rq_pos(scmd->request) + (scsi_bufflen(scmd) / 512); |
| 976 | u64 bad_lba; | 976 | u64 bad_lba; |
| 977 | int info_valid; | 977 | int info_valid; |
| 978 | 978 | ||
| @@ -1510,7 +1510,7 @@ got_data: | |||
| 1510 | */ | 1510 | */ |
| 1511 | sector_size = 512; | 1511 | sector_size = 512; |
| 1512 | } | 1512 | } |
| 1513 | blk_queue_hardsect_size(sdp->request_queue, sector_size); | 1513 | blk_queue_logical_block_size(sdp->request_queue, sector_size); |
| 1514 | 1514 | ||
| 1515 | { | 1515 | { |
| 1516 | char cap_str_2[10], cap_str_10[10]; | 1516 | char cap_str_2[10], cap_str_10[10]; |
diff --git a/drivers/scsi/sd_dif.c b/drivers/scsi/sd_dif.c index 184dff492797..82f14a9482d0 100644 --- a/drivers/scsi/sd_dif.c +++ b/drivers/scsi/sd_dif.c | |||
| @@ -507,7 +507,7 @@ void sd_dif_complete(struct scsi_cmnd *scmd, unsigned int good_bytes) | |||
| 507 | sector_sz = scmd->device->sector_size; | 507 | sector_sz = scmd->device->sector_size; |
| 508 | sectors = good_bytes / sector_sz; | 508 | sectors = good_bytes / sector_sz; |
| 509 | 509 | ||
| 510 | phys = scmd->request->sector & 0xffffffff; | 510 | phys = blk_rq_pos(scmd->request) & 0xffffffff; |
| 511 | if (sector_sz == 4096) | 511 | if (sector_sz == 4096) |
| 512 | phys >>= 3; | 512 | phys >>= 3; |
| 513 | 513 | ||
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c index e1716f14cd47..8201387b4daa 100644 --- a/drivers/scsi/sg.c +++ b/drivers/scsi/sg.c | |||
| @@ -289,8 +289,8 @@ sg_open(struct inode *inode, struct file *filp) | |||
| 289 | if (list_empty(&sdp->sfds)) { /* no existing opens on this device */ | 289 | if (list_empty(&sdp->sfds)) { /* no existing opens on this device */ |
| 290 | sdp->sgdebug = 0; | 290 | sdp->sgdebug = 0; |
| 291 | q = sdp->device->request_queue; | 291 | q = sdp->device->request_queue; |
| 292 | sdp->sg_tablesize = min(q->max_hw_segments, | 292 | sdp->sg_tablesize = min(queue_max_hw_segments(q), |
| 293 | q->max_phys_segments); | 293 | queue_max_phys_segments(q)); |
| 294 | } | 294 | } |
| 295 | if ((sfp = sg_add_sfp(sdp, dev))) | 295 | if ((sfp = sg_add_sfp(sdp, dev))) |
| 296 | filp->private_data = sfp; | 296 | filp->private_data = sfp; |
| @@ -909,7 +909,7 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
| 909 | if (val < 0) | 909 | if (val < 0) |
| 910 | return -EINVAL; | 910 | return -EINVAL; |
| 911 | val = min_t(int, val, | 911 | val = min_t(int, val, |
| 912 | sdp->device->request_queue->max_sectors * 512); | 912 | queue_max_sectors(sdp->device->request_queue) * 512); |
| 913 | if (val != sfp->reserve.bufflen) { | 913 | if (val != sfp->reserve.bufflen) { |
| 914 | if (sg_res_in_use(sfp) || sfp->mmap_called) | 914 | if (sg_res_in_use(sfp) || sfp->mmap_called) |
| 915 | return -EBUSY; | 915 | return -EBUSY; |
| @@ -919,7 +919,7 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
| 919 | return 0; | 919 | return 0; |
| 920 | case SG_GET_RESERVED_SIZE: | 920 | case SG_GET_RESERVED_SIZE: |
| 921 | val = min_t(int, sfp->reserve.bufflen, | 921 | val = min_t(int, sfp->reserve.bufflen, |
| 922 | sdp->device->request_queue->max_sectors * 512); | 922 | queue_max_sectors(sdp->device->request_queue) * 512); |
| 923 | return put_user(val, ip); | 923 | return put_user(val, ip); |
| 924 | case SG_SET_COMMAND_Q: | 924 | case SG_SET_COMMAND_Q: |
| 925 | result = get_user(val, ip); | 925 | result = get_user(val, ip); |
| @@ -1059,12 +1059,13 @@ sg_ioctl(struct inode *inode, struct file *filp, | |||
| 1059 | return -ENODEV; | 1059 | return -ENODEV; |
| 1060 | return scsi_ioctl(sdp->device, cmd_in, p); | 1060 | return scsi_ioctl(sdp->device, cmd_in, p); |
| 1061 | case BLKSECTGET: | 1061 | case BLKSECTGET: |
| 1062 | return put_user(sdp->device->request_queue->max_sectors * 512, | 1062 | return put_user(queue_max_sectors(sdp->device->request_queue) * 512, |
| 1063 | ip); | 1063 | ip); |
| 1064 | case BLKTRACESETUP: | 1064 | case BLKTRACESETUP: |
| 1065 | return blk_trace_setup(sdp->device->request_queue, | 1065 | return blk_trace_setup(sdp->device->request_queue, |
| 1066 | sdp->disk->disk_name, | 1066 | sdp->disk->disk_name, |
| 1067 | MKDEV(SCSI_GENERIC_MAJOR, sdp->index), | 1067 | MKDEV(SCSI_GENERIC_MAJOR, sdp->index), |
| 1068 | NULL, | ||
| 1068 | (char *)arg); | 1069 | (char *)arg); |
| 1069 | case BLKTRACESTART: | 1070 | case BLKTRACESTART: |
| 1070 | return blk_trace_startstop(sdp->device->request_queue, 1); | 1071 | return blk_trace_startstop(sdp->device->request_queue, 1); |
| @@ -1260,7 +1261,7 @@ static void sg_rq_end_io(struct request *rq, int uptodate) | |||
| 1260 | 1261 | ||
| 1261 | sense = rq->sense; | 1262 | sense = rq->sense; |
| 1262 | result = rq->errors; | 1263 | result = rq->errors; |
| 1263 | resid = rq->data_len; | 1264 | resid = rq->resid_len; |
| 1264 | 1265 | ||
| 1265 | SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", | 1266 | SCSI_LOG_TIMEOUT(4, printk("sg_cmd_done: %s, pack_id=%d, res=0x%x\n", |
| 1266 | sdp->disk->disk_name, srp->header.pack_id, result)); | 1267 | sdp->disk->disk_name, srp->header.pack_id, result)); |
| @@ -1377,7 +1378,8 @@ static Sg_device *sg_alloc(struct gendisk *disk, struct scsi_device *scsidp) | |||
| 1377 | sdp->device = scsidp; | 1378 | sdp->device = scsidp; |
| 1378 | INIT_LIST_HEAD(&sdp->sfds); | 1379 | INIT_LIST_HEAD(&sdp->sfds); |
| 1379 | init_waitqueue_head(&sdp->o_excl_wait); | 1380 | init_waitqueue_head(&sdp->o_excl_wait); |
| 1380 | sdp->sg_tablesize = min(q->max_hw_segments, q->max_phys_segments); | 1381 | sdp->sg_tablesize = min(queue_max_hw_segments(q), |
| 1382 | queue_max_phys_segments(q)); | ||
| 1381 | sdp->index = k; | 1383 | sdp->index = k; |
| 1382 | kref_init(&sdp->d_ref); | 1384 | kref_init(&sdp->d_ref); |
| 1383 | 1385 | ||
| @@ -2055,7 +2057,7 @@ sg_add_sfp(Sg_device * sdp, int dev) | |||
| 2055 | sg_big_buff = def_reserved_size; | 2057 | sg_big_buff = def_reserved_size; |
| 2056 | 2058 | ||
| 2057 | bufflen = min_t(int, sg_big_buff, | 2059 | bufflen = min_t(int, sg_big_buff, |
| 2058 | sdp->device->request_queue->max_sectors * 512); | 2060 | queue_max_sectors(sdp->device->request_queue) * 512); |
| 2059 | sg_build_reserve(sfp, bufflen); | 2061 | sg_build_reserve(sfp, bufflen); |
| 2060 | SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n", | 2062 | SCSI_LOG_TIMEOUT(3, printk("sg_add_sfp: bufflen=%d, k_use_sg=%d\n", |
| 2061 | sfp->reserve.bufflen, sfp->reserve.k_use_sg)); | 2063 | sfp->reserve.bufflen, sfp->reserve.k_use_sg)); |
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c index 0e1a0f2d2ad5..cd350dfc1216 100644 --- a/drivers/scsi/sr.c +++ b/drivers/scsi/sr.c | |||
| @@ -292,7 +292,8 @@ static int sr_done(struct scsi_cmnd *SCpnt) | |||
| 292 | if (cd->device->sector_size == 2048) | 292 | if (cd->device->sector_size == 2048) |
| 293 | error_sector <<= 2; | 293 | error_sector <<= 2; |
| 294 | error_sector &= ~(block_sectors - 1); | 294 | error_sector &= ~(block_sectors - 1); |
| 295 | good_bytes = (error_sector - SCpnt->request->sector) << 9; | 295 | good_bytes = (error_sector - |
| 296 | blk_rq_pos(SCpnt->request)) << 9; | ||
| 296 | if (good_bytes < 0 || good_bytes >= this_count) | 297 | if (good_bytes < 0 || good_bytes >= this_count) |
| 297 | good_bytes = 0; | 298 | good_bytes = 0; |
| 298 | /* | 299 | /* |
| @@ -349,8 +350,8 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) | |||
| 349 | cd->disk->disk_name, block)); | 350 | cd->disk->disk_name, block)); |
| 350 | 351 | ||
| 351 | if (!cd->device || !scsi_device_online(cd->device)) { | 352 | if (!cd->device || !scsi_device_online(cd->device)) { |
| 352 | SCSI_LOG_HLQUEUE(2, printk("Finishing %ld sectors\n", | 353 | SCSI_LOG_HLQUEUE(2, printk("Finishing %u sectors\n", |
| 353 | rq->nr_sectors)); | 354 | blk_rq_sectors(rq))); |
| 354 | SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); | 355 | SCSI_LOG_HLQUEUE(2, printk("Retry with 0x%p\n", SCpnt)); |
| 355 | goto out; | 356 | goto out; |
| 356 | } | 357 | } |
| @@ -413,7 +414,7 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) | |||
| 413 | /* | 414 | /* |
| 414 | * request doesn't start on hw block boundary, add scatter pads | 415 | * request doesn't start on hw block boundary, add scatter pads |
| 415 | */ | 416 | */ |
| 416 | if (((unsigned int)rq->sector % (s_size >> 9)) || | 417 | if (((unsigned int)blk_rq_pos(rq) % (s_size >> 9)) || |
| 417 | (scsi_bufflen(SCpnt) % s_size)) { | 418 | (scsi_bufflen(SCpnt) % s_size)) { |
| 418 | scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n"); | 419 | scmd_printk(KERN_NOTICE, SCpnt, "unaligned transfer\n"); |
| 419 | goto out; | 420 | goto out; |
| @@ -422,14 +423,14 @@ static int sr_prep_fn(struct request_queue *q, struct request *rq) | |||
| 422 | this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9); | 423 | this_count = (scsi_bufflen(SCpnt) >> 9) / (s_size >> 9); |
| 423 | 424 | ||
| 424 | 425 | ||
| 425 | SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%ld 512 byte blocks.\n", | 426 | SCSI_LOG_HLQUEUE(2, printk("%s : %s %d/%u 512 byte blocks.\n", |
| 426 | cd->cdi.name, | 427 | cd->cdi.name, |
| 427 | (rq_data_dir(rq) == WRITE) ? | 428 | (rq_data_dir(rq) == WRITE) ? |
| 428 | "writing" : "reading", | 429 | "writing" : "reading", |
| 429 | this_count, rq->nr_sectors)); | 430 | this_count, blk_rq_sectors(rq))); |
| 430 | 431 | ||
| 431 | SCpnt->cmnd[1] = 0; | 432 | SCpnt->cmnd[1] = 0; |
| 432 | block = (unsigned int)rq->sector / (s_size >> 9); | 433 | block = (unsigned int)blk_rq_pos(rq) / (s_size >> 9); |
| 433 | 434 | ||
| 434 | if (this_count > 0xffff) { | 435 | if (this_count > 0xffff) { |
| 435 | this_count = 0xffff; | 436 | this_count = 0xffff; |
| @@ -726,7 +727,7 @@ static void get_sectorsize(struct scsi_cd *cd) | |||
| 726 | } | 727 | } |
| 727 | 728 | ||
| 728 | queue = cd->device->request_queue; | 729 | queue = cd->device->request_queue; |
| 729 | blk_queue_hardsect_size(queue, sector_size); | 730 | blk_queue_logical_block_size(queue, sector_size); |
| 730 | 731 | ||
| 731 | return; | 732 | return; |
| 732 | } | 733 | } |
diff --git a/drivers/scsi/st.c b/drivers/scsi/st.c index eb24efea8f14..89bd438e1fe3 100644 --- a/drivers/scsi/st.c +++ b/drivers/scsi/st.c | |||
| @@ -463,7 +463,7 @@ static void st_scsi_execute_end(struct request *req, int uptodate) | |||
| 463 | struct scsi_tape *STp = SRpnt->stp; | 463 | struct scsi_tape *STp = SRpnt->stp; |
| 464 | 464 | ||
| 465 | STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; | 465 | STp->buffer->cmdstat.midlevel_result = SRpnt->result = req->errors; |
| 466 | STp->buffer->cmdstat.residual = req->data_len; | 466 | STp->buffer->cmdstat.residual = req->resid_len; |
| 467 | 467 | ||
| 468 | if (SRpnt->waiting) | 468 | if (SRpnt->waiting) |
| 469 | complete(SRpnt->waiting); | 469 | complete(SRpnt->waiting); |
| @@ -3983,8 +3983,8 @@ static int st_probe(struct device *dev) | |||
| 3983 | return -ENODEV; | 3983 | return -ENODEV; |
| 3984 | } | 3984 | } |
| 3985 | 3985 | ||
| 3986 | i = min(SDp->request_queue->max_hw_segments, | 3986 | i = min(queue_max_hw_segments(SDp->request_queue), |
| 3987 | SDp->request_queue->max_phys_segments); | 3987 | queue_max_phys_segments(SDp->request_queue)); |
| 3988 | if (st_max_sg_segs < i) | 3988 | if (st_max_sg_segs < i) |
| 3989 | i = st_max_sg_segs; | 3989 | i = st_max_sg_segs; |
| 3990 | buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i); | 3990 | buffer = new_tape_buffer((SDp->host)->unchecked_isa_dma, i); |
diff --git a/drivers/scsi/u14-34f.c b/drivers/scsi/u14-34f.c index 601e95141cbe..54023d41fd15 100644 --- a/drivers/scsi/u14-34f.c +++ b/drivers/scsi/u14-34f.c | |||
| @@ -1306,7 +1306,7 @@ static int u14_34f_queuecommand(struct scsi_cmnd *SCpnt, void (*done)(struct scs | |||
| 1306 | if (linked_comm && SCpnt->device->queue_depth > 2 | 1306 | if (linked_comm && SCpnt->device->queue_depth > 2 |
| 1307 | && TLDEV(SCpnt->device->type)) { | 1307 | && TLDEV(SCpnt->device->type)) { |
| 1308 | HD(j)->cp_stat[i] = READY; | 1308 | HD(j)->cp_stat[i] = READY; |
| 1309 | flush_dev(SCpnt->device, SCpnt->request->sector, j, FALSE); | 1309 | flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), j, FALSE); |
| 1310 | return 0; | 1310 | return 0; |
| 1311 | } | 1311 | } |
| 1312 | 1312 | ||
| @@ -1610,11 +1610,13 @@ static int reorder(unsigned int j, unsigned long cursec, | |||
| 1610 | 1610 | ||
| 1611 | if (!(cpp->xdir == DTD_IN)) input_only = FALSE; | 1611 | if (!(cpp->xdir == DTD_IN)) input_only = FALSE; |
| 1612 | 1612 | ||
| 1613 | if (SCpnt->request->sector < minsec) minsec = SCpnt->request->sector; | 1613 | if (blk_rq_pos(SCpnt->request) < minsec) |
| 1614 | if (SCpnt->request->sector > maxsec) maxsec = SCpnt->request->sector; | 1614 | minsec = blk_rq_pos(SCpnt->request); |
| 1615 | if (blk_rq_pos(SCpnt->request) > maxsec) | ||
| 1616 | maxsec = blk_rq_pos(SCpnt->request); | ||
| 1615 | 1617 | ||
| 1616 | sl[n] = SCpnt->request->sector; | 1618 | sl[n] = blk_rq_pos(SCpnt->request); |
| 1617 | ioseek += SCpnt->request->nr_sectors; | 1619 | ioseek += blk_rq_sectors(SCpnt->request); |
| 1618 | 1620 | ||
| 1619 | if (!n) continue; | 1621 | if (!n) continue; |
| 1620 | 1622 | ||
| @@ -1642,7 +1644,7 @@ static int reorder(unsigned int j, unsigned long cursec, | |||
| 1642 | 1644 | ||
| 1643 | if (!input_only) for (n = 0; n < n_ready; n++) { | 1645 | if (!input_only) for (n = 0; n < n_ready; n++) { |
| 1644 | k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; | 1646 | k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; |
| 1645 | ll[n] = SCpnt->request->nr_sectors; pl[n] = SCpnt->serial_number; | 1647 | ll[n] = blk_rq_sectors(SCpnt->request); pl[n] = SCpnt->serial_number; |
| 1646 | 1648 | ||
| 1647 | if (!n) continue; | 1649 | if (!n) continue; |
| 1648 | 1650 | ||
| @@ -1666,12 +1668,12 @@ static int reorder(unsigned int j, unsigned long cursec, | |||
| 1666 | if (link_statistics && (overlap || !(flushcount % link_statistics))) | 1668 | if (link_statistics && (overlap || !(flushcount % link_statistics))) |
| 1667 | for (n = 0; n < n_ready; n++) { | 1669 | for (n = 0; n < n_ready; n++) { |
| 1668 | k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; | 1670 | k = il[n]; cpp = &HD(j)->cp[k]; SCpnt = cpp->SCpnt; |
| 1669 | printk("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %ld"\ | 1671 | printk("%s %d.%d:%d pid %ld mb %d fc %d nr %d sec %ld ns %u"\ |
| 1670 | " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", | 1672 | " cur %ld s:%c r:%c rev:%c in:%c ov:%c xd %d.\n", |
| 1671 | (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, | 1673 | (ihdlr ? "ihdlr" : "qcomm"), SCpnt->channel, SCpnt->target, |
| 1672 | SCpnt->lun, SCpnt->serial_number, k, flushcount, n_ready, | 1674 | SCpnt->lun, SCpnt->serial_number, k, flushcount, n_ready, |
| 1673 | SCpnt->request->sector, SCpnt->request->nr_sectors, cursec, | 1675 | blk_rq_pos(SCpnt->request), blk_rq_sectors(SCpnt->request), |
| 1674 | YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), | 1676 | cursec, YESNO(s), YESNO(r), YESNO(rev), YESNO(input_only), |
| 1675 | YESNO(overlap), cpp->xdir); | 1677 | YESNO(overlap), cpp->xdir); |
| 1676 | } | 1678 | } |
| 1677 | #endif | 1679 | #endif |
| @@ -1799,7 +1801,7 @@ static irqreturn_t ihdlr(unsigned int j) | |||
| 1799 | 1801 | ||
| 1800 | if (linked_comm && SCpnt->device->queue_depth > 2 | 1802 | if (linked_comm && SCpnt->device->queue_depth > 2 |
| 1801 | && TLDEV(SCpnt->device->type)) | 1803 | && TLDEV(SCpnt->device->type)) |
| 1802 | flush_dev(SCpnt->device, SCpnt->request->sector, j, TRUE); | 1804 | flush_dev(SCpnt->device, blk_rq_pos(SCpnt->request), j, TRUE); |
| 1803 | 1805 | ||
| 1804 | tstatus = status_byte(spp->target_status); | 1806 | tstatus = status_byte(spp->target_status); |
| 1805 | 1807 | ||
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c index b4b39811b445..fb867a9f55e9 100644 --- a/drivers/serial/8250.c +++ b/drivers/serial/8250.c | |||
| @@ -137,6 +137,7 @@ struct uart_8250_port { | |||
| 137 | unsigned char mcr; | 137 | unsigned char mcr; |
| 138 | unsigned char mcr_mask; /* mask of user bits */ | 138 | unsigned char mcr_mask; /* mask of user bits */ |
| 139 | unsigned char mcr_force; /* mask of forced bits */ | 139 | unsigned char mcr_force; /* mask of forced bits */ |
| 140 | unsigned char cur_iotype; /* Running I/O type */ | ||
| 140 | 141 | ||
| 141 | /* | 142 | /* |
| 142 | * Some bits in registers are cleared on a read, so they must | 143 | * Some bits in registers are cleared on a read, so they must |
| @@ -286,6 +287,13 @@ static const struct serial8250_config uart_config[] = { | |||
| 286 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, | 287 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10, |
| 287 | .flags = UART_CAP_FIFO, | 288 | .flags = UART_CAP_FIFO, |
| 288 | }, | 289 | }, |
| 290 | [PORT_AR7] = { | ||
| 291 | .name = "AR7", | ||
| 292 | .fifo_size = 16, | ||
| 293 | .tx_loadsz = 16, | ||
| 294 | .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_00, | ||
| 295 | .flags = UART_CAP_FIFO | UART_CAP_AFE, | ||
| 296 | }, | ||
| 289 | }; | 297 | }; |
| 290 | 298 | ||
| 291 | #if defined (CONFIG_SERIAL_8250_AU1X00) | 299 | #if defined (CONFIG_SERIAL_8250_AU1X00) |
| @@ -471,6 +479,7 @@ static void io_serial_out(struct uart_port *p, int offset, int value) | |||
| 471 | 479 | ||
| 472 | static void set_io_from_upio(struct uart_port *p) | 480 | static void set_io_from_upio(struct uart_port *p) |
| 473 | { | 481 | { |
| 482 | struct uart_8250_port *up = (struct uart_8250_port *)p; | ||
| 474 | switch (p->iotype) { | 483 | switch (p->iotype) { |
| 475 | case UPIO_HUB6: | 484 | case UPIO_HUB6: |
| 476 | p->serial_in = hub6_serial_in; | 485 | p->serial_in = hub6_serial_in; |
| @@ -509,6 +518,8 @@ static void set_io_from_upio(struct uart_port *p) | |||
| 509 | p->serial_out = io_serial_out; | 518 | p->serial_out = io_serial_out; |
| 510 | break; | 519 | break; |
| 511 | } | 520 | } |
| 521 | /* Remember loaded iotype */ | ||
| 522 | up->cur_iotype = p->iotype; | ||
| 512 | } | 523 | } |
| 513 | 524 | ||
| 514 | static void | 525 | static void |
| @@ -1937,6 +1948,9 @@ static int serial8250_startup(struct uart_port *port) | |||
| 1937 | up->capabilities = uart_config[up->port.type].flags; | 1948 | up->capabilities = uart_config[up->port.type].flags; |
| 1938 | up->mcr = 0; | 1949 | up->mcr = 0; |
| 1939 | 1950 | ||
| 1951 | if (up->port.iotype != up->cur_iotype) | ||
| 1952 | set_io_from_upio(port); | ||
| 1953 | |||
| 1940 | if (up->port.type == PORT_16C950) { | 1954 | if (up->port.type == PORT_16C950) { |
| 1941 | /* Wake up and initialize UART */ | 1955 | /* Wake up and initialize UART */ |
| 1942 | up->acr = 0; | 1956 | up->acr = 0; |
| @@ -2563,6 +2577,9 @@ static void serial8250_config_port(struct uart_port *port, int flags) | |||
| 2563 | if (ret < 0) | 2577 | if (ret < 0) |
| 2564 | probeflags &= ~PROBE_RSA; | 2578 | probeflags &= ~PROBE_RSA; |
| 2565 | 2579 | ||
| 2580 | if (up->port.iotype != up->cur_iotype) | ||
| 2581 | set_io_from_upio(port); | ||
| 2582 | |||
| 2566 | if (flags & UART_CONFIG_TYPE) | 2583 | if (flags & UART_CONFIG_TYPE) |
| 2567 | autoconfig(up, probeflags); | 2584 | autoconfig(up, probeflags); |
| 2568 | if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) | 2585 | if (up->port.type != PORT_UNKNOWN && flags & UART_CONFIG_IRQ) |
| @@ -2671,6 +2688,11 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) | |||
| 2671 | { | 2688 | { |
| 2672 | int i; | 2689 | int i; |
| 2673 | 2690 | ||
| 2691 | for (i = 0; i < nr_uarts; i++) { | ||
| 2692 | struct uart_8250_port *up = &serial8250_ports[i]; | ||
| 2693 | up->cur_iotype = 0xFF; | ||
| 2694 | } | ||
| 2695 | |||
| 2674 | serial8250_isa_init_ports(); | 2696 | serial8250_isa_init_ports(); |
| 2675 | 2697 | ||
| 2676 | for (i = 0; i < nr_uarts; i++) { | 2698 | for (i = 0; i < nr_uarts; i++) { |
diff --git a/drivers/serial/8250_gsc.c b/drivers/serial/8250_gsc.c index 418b4fe9a0a1..33149d982e82 100644 --- a/drivers/serial/8250_gsc.c +++ b/drivers/serial/8250_gsc.c | |||
| @@ -39,9 +39,9 @@ static int __init serial_init_chip(struct parisc_device *dev) | |||
| 39 | */ | 39 | */ |
| 40 | if (parisc_parent(dev)->id.hw_type != HPHW_IOA) | 40 | if (parisc_parent(dev)->id.hw_type != HPHW_IOA) |
| 41 | printk(KERN_INFO | 41 | printk(KERN_INFO |
| 42 | "Serial: device 0x%lx not configured.\n" | 42 | "Serial: device 0x%llx not configured.\n" |
| 43 | "Enable support for Wax, Lasi, Asp or Dino.\n", | 43 | "Enable support for Wax, Lasi, Asp or Dino.\n", |
| 44 | dev->hpa.start); | 44 | (unsigned long long)dev->hpa.start); |
| 45 | return -ENODEV; | 45 | return -ENODEV; |
| 46 | } | 46 | } |
| 47 | 47 | ||
diff --git a/drivers/serial/8250_pci.c b/drivers/serial/8250_pci.c index 938bc1b6c3fa..e371a9c15341 100644 --- a/drivers/serial/8250_pci.c +++ b/drivers/serial/8250_pci.c | |||
| @@ -2776,6 +2776,9 @@ static struct pci_device_id serial_pci_tbl[] = { | |||
| 2776 | { PCI_VENDOR_ID_OXSEMI, 0x950a, | 2776 | { PCI_VENDOR_ID_OXSEMI, 0x950a, |
| 2777 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2777 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
| 2778 | pbn_b0_2_1130000 }, | 2778 | pbn_b0_2_1130000 }, |
| 2779 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_C950, | ||
| 2780 | PCI_VENDOR_ID_OXSEMI, PCI_SUBDEVICE_ID_OXSEMI_C950, 0, 0, | ||
| 2781 | pbn_b0_1_921600 }, | ||
| 2779 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, | 2782 | { PCI_VENDOR_ID_OXSEMI, PCI_DEVICE_ID_OXSEMI_16PCI954, |
| 2780 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, | 2783 | PCI_ANY_ID, PCI_ANY_ID, 0, 0, |
| 2781 | pbn_b0_4_115200 }, | 2784 | pbn_b0_4_115200 }, |
diff --git a/drivers/serial/Kconfig b/drivers/serial/Kconfig index 343e3a35b6a3..641e800ed693 100644 --- a/drivers/serial/Kconfig +++ b/drivers/serial/Kconfig | |||
| @@ -833,6 +833,7 @@ config SERIAL_IMX | |||
| 833 | bool "IMX serial port support" | 833 | bool "IMX serial port support" |
| 834 | depends on ARM && (ARCH_IMX || ARCH_MXC) | 834 | depends on ARM && (ARCH_IMX || ARCH_MXC) |
| 835 | select SERIAL_CORE | 835 | select SERIAL_CORE |
| 836 | select RATIONAL | ||
| 836 | help | 837 | help |
| 837 | If you have a machine based on a Motorola IMX CPU you | 838 | If you have a machine based on a Motorola IMX CPU you |
| 838 | can enable its onboard serial port by enabling this option. | 839 | can enable its onboard serial port by enabling this option. |
| @@ -1433,4 +1434,11 @@ config SPORT_BAUD_RATE | |||
| 1433 | default 19200 if (SERIAL_SPORT_BAUD_RATE_19200) | 1434 | default 19200 if (SERIAL_SPORT_BAUD_RATE_19200) |
| 1434 | default 9600 if (SERIAL_SPORT_BAUD_RATE_9600) | 1435 | default 9600 if (SERIAL_SPORT_BAUD_RATE_9600) |
| 1435 | 1436 | ||
| 1437 | config SERIAL_TIMBERDALE | ||
| 1438 | tristate "Support for timberdale UART" | ||
| 1439 | depends on MFD_TIMBERDALE | ||
| 1440 | select SERIAL_CORE | ||
| 1441 | ---help--- | ||
| 1442 | Add support for UART controller on timberdale. | ||
| 1443 | |||
| 1436 | endmenu | 1444 | endmenu |
diff --git a/drivers/serial/Makefile b/drivers/serial/Makefile index d438eb2a73de..45a8658f54d5 100644 --- a/drivers/serial/Makefile +++ b/drivers/serial/Makefile | |||
| @@ -77,3 +77,4 @@ obj-$(CONFIG_SERIAL_OF_PLATFORM_NWPSERIAL) += nwpserial.o | |||
| 77 | obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o | 77 | obj-$(CONFIG_SERIAL_KS8695) += serial_ks8695.o |
| 78 | obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o | 78 | obj-$(CONFIG_KGDB_SERIAL_CONSOLE) += kgdboc.o |
| 79 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o | 79 | obj-$(CONFIG_SERIAL_QE) += ucc_uart.o |
| 80 | obj-$(CONFIG_SERIAL_TIMBERDALE) += timbuart.o | ||
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index d86123e03391..e2f6b1bfac98 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
| @@ -330,6 +330,11 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart) | |||
| 330 | /* Clear TFI bit */ | 330 | /* Clear TFI bit */ |
| 331 | UART_PUT_LSR(uart, TFI); | 331 | UART_PUT_LSR(uart, TFI); |
| 332 | #endif | 332 | #endif |
| 333 | /* Anomaly notes: | ||
| 334 | * 05000215 - we always clear ETBEI within last UART TX | ||
| 335 | * interrupt to end a string. It is always set | ||
| 336 | * when start a new tx. | ||
| 337 | */ | ||
| 333 | UART_CLEAR_IER(uart, ETBEI); | 338 | UART_CLEAR_IER(uart, ETBEI); |
| 334 | return; | 339 | return; |
| 335 | } | 340 | } |
| @@ -415,6 +420,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) | |||
| 415 | set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); | 420 | set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail)); |
| 416 | set_dma_x_count(uart->tx_dma_channel, uart->tx_count); | 421 | set_dma_x_count(uart->tx_dma_channel, uart->tx_count); |
| 417 | set_dma_x_modify(uart->tx_dma_channel, 1); | 422 | set_dma_x_modify(uart->tx_dma_channel, 1); |
| 423 | SSYNC(); | ||
| 418 | enable_dma(uart->tx_dma_channel); | 424 | enable_dma(uart->tx_dma_channel); |
| 419 | 425 | ||
| 420 | UART_SET_IER(uart, ETBEI); | 426 | UART_SET_IER(uart, ETBEI); |
| @@ -473,27 +479,41 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | |||
| 473 | void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | 479 | void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) |
| 474 | { | 480 | { |
| 475 | int x_pos, pos; | 481 | int x_pos, pos; |
| 476 | unsigned long flags; | ||
| 477 | |||
| 478 | spin_lock_irqsave(&uart->port.lock, flags); | ||
| 479 | 482 | ||
| 483 | dma_disable_irq(uart->rx_dma_channel); | ||
| 484 | spin_lock_bh(&uart->port.lock); | ||
| 485 | |||
| 486 | /* 2D DMA RX buffer ring is used. Because curr_y_count and | ||
| 487 | * curr_x_count can't be read as an atomic operation, | ||
| 488 | * curr_y_count should be read before curr_x_count. When | ||
| 489 | * curr_x_count is read, curr_y_count may already indicate | ||
| 490 | * next buffer line. But, the position calculated here is | ||
| 491 | * still indicate the old line. The wrong position data may | ||
| 492 | * be smaller than current buffer tail, which cause garbages | ||
| 493 | * are received if it is not prohibit. | ||
| 494 | */ | ||
| 480 | uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); | 495 | uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); |
| 481 | x_pos = get_dma_curr_xcount(uart->rx_dma_channel); | 496 | x_pos = get_dma_curr_xcount(uart->rx_dma_channel); |
| 482 | uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; | 497 | uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; |
| 483 | if (uart->rx_dma_nrows == DMA_RX_YCOUNT) | 498 | if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) |
| 484 | uart->rx_dma_nrows = 0; | 499 | uart->rx_dma_nrows = 0; |
| 485 | x_pos = DMA_RX_XCOUNT - x_pos; | 500 | x_pos = DMA_RX_XCOUNT - x_pos; |
| 486 | if (x_pos == DMA_RX_XCOUNT) | 501 | if (x_pos == DMA_RX_XCOUNT) |
| 487 | x_pos = 0; | 502 | x_pos = 0; |
| 488 | 503 | ||
| 489 | pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; | 504 | pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; |
| 490 | if (pos != uart->rx_dma_buf.tail) { | 505 | /* Ignore receiving data if new position is in the same line of |
| 506 | * current buffer tail and small. | ||
| 507 | */ | ||
| 508 | if (pos > uart->rx_dma_buf.tail || | ||
| 509 | uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) { | ||
| 491 | uart->rx_dma_buf.head = pos; | 510 | uart->rx_dma_buf.head = pos; |
| 492 | bfin_serial_dma_rx_chars(uart); | 511 | bfin_serial_dma_rx_chars(uart); |
| 493 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; | 512 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; |
| 494 | } | 513 | } |
| 495 | 514 | ||
| 496 | spin_unlock_irqrestore(&uart->port.lock, flags); | 515 | spin_unlock_bh(&uart->port.lock); |
| 516 | dma_enable_irq(uart->rx_dma_channel); | ||
| 497 | 517 | ||
| 498 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); | 518 | mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES); |
| 499 | } | 519 | } |
| @@ -514,6 +534,11 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) | |||
| 514 | if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { | 534 | if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { |
| 515 | disable_dma(uart->tx_dma_channel); | 535 | disable_dma(uart->tx_dma_channel); |
| 516 | clear_dma_irqstat(uart->tx_dma_channel); | 536 | clear_dma_irqstat(uart->tx_dma_channel); |
| 537 | /* Anomaly notes: | ||
| 538 | * 05000215 - we always clear ETBEI within last UART TX | ||
| 539 | * interrupt to end a string. It is always set | ||
| 540 | * when start a new tx. | ||
| 541 | */ | ||
| 517 | UART_CLEAR_IER(uart, ETBEI); | 542 | UART_CLEAR_IER(uart, ETBEI); |
| 518 | xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); | 543 | xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); |
| 519 | uart->port.icount.tx += uart->tx_count; | 544 | uart->port.icount.tx += uart->tx_count; |
| @@ -532,11 +557,26 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id) | |||
| 532 | { | 557 | { |
| 533 | struct bfin_serial_port *uart = dev_id; | 558 | struct bfin_serial_port *uart = dev_id; |
| 534 | unsigned short irqstat; | 559 | unsigned short irqstat; |
| 560 | int x_pos, pos; | ||
| 535 | 561 | ||
| 536 | spin_lock(&uart->port.lock); | 562 | spin_lock(&uart->port.lock); |
| 537 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); | 563 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); |
| 538 | clear_dma_irqstat(uart->rx_dma_channel); | 564 | clear_dma_irqstat(uart->rx_dma_channel); |
| 539 | bfin_serial_dma_rx_chars(uart); | 565 | |
| 566 | uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); | ||
| 567 | x_pos = get_dma_curr_xcount(uart->rx_dma_channel); | ||
| 568 | uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; | ||
| 569 | if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0) | ||
| 570 | uart->rx_dma_nrows = 0; | ||
| 571 | |||
| 572 | pos = uart->rx_dma_nrows * DMA_RX_XCOUNT; | ||
| 573 | if (pos > uart->rx_dma_buf.tail || | ||
| 574 | uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) { | ||
| 575 | uart->rx_dma_buf.head = pos; | ||
| 576 | bfin_serial_dma_rx_chars(uart); | ||
| 577 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; | ||
| 578 | } | ||
| 579 | |||
| 540 | spin_unlock(&uart->port.lock); | 580 | spin_unlock(&uart->port.lock); |
| 541 | 581 | ||
| 542 | return IRQ_HANDLED; | 582 | return IRQ_HANDLED; |
| @@ -789,8 +829,16 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 789 | __func__); | 829 | __func__); |
| 790 | } | 830 | } |
| 791 | 831 | ||
| 792 | if (termios->c_cflag & CSTOPB) | 832 | /* Anomaly notes: |
| 793 | lcr |= STB; | 833 | * 05000231 - STOP bit is always set to 1 whatever the user is set. |
| 834 | */ | ||
| 835 | if (termios->c_cflag & CSTOPB) { | ||
| 836 | if (ANOMALY_05000231) | ||
| 837 | printk(KERN_WARNING "STOP bits other than 1 is not " | ||
| 838 | "supported in case of anomaly 05000231.\n"); | ||
| 839 | else | ||
| 840 | lcr |= STB; | ||
| 841 | } | ||
| 794 | if (termios->c_cflag & PARENB) | 842 | if (termios->c_cflag & PARENB) |
| 795 | lcr |= PEN; | 843 | lcr |= PEN; |
| 796 | if (!(termios->c_cflag & PARODD)) | 844 | if (!(termios->c_cflag & PARODD)) |
| @@ -940,6 +988,10 @@ static void bfin_serial_reset_irda(struct uart_port *port) | |||
| 940 | } | 988 | } |
| 941 | 989 | ||
| 942 | #ifdef CONFIG_CONSOLE_POLL | 990 | #ifdef CONFIG_CONSOLE_POLL |
| 991 | /* Anomaly notes: | ||
| 992 | * 05000099 - Because we only use THRE in poll_put and DR in poll_get, | ||
| 993 | * losing other bits of UART_LSR is not a problem here. | ||
| 994 | */ | ||
| 943 | static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr) | 995 | static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr) |
| 944 | { | 996 | { |
| 945 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 997 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
| @@ -1245,12 +1297,17 @@ static __init void early_serial_write(struct console *con, const char *s, | |||
| 1245 | } | 1297 | } |
| 1246 | } | 1298 | } |
| 1247 | 1299 | ||
| 1300 | /* | ||
| 1301 | * This should have a .setup or .early_setup in it, but then things get called | ||
| 1302 | * without the command line options, and the baud rate gets messed up - so | ||
| 1303 | * don't let the common infrastructure play with things. (see calls to setup | ||
| 1304 | * & earlysetup in ./kernel/printk.c:register_console() | ||
| 1305 | */ | ||
| 1248 | static struct __initdata console bfin_early_serial_console = { | 1306 | static struct __initdata console bfin_early_serial_console = { |
| 1249 | .name = "early_BFuart", | 1307 | .name = "early_BFuart", |
| 1250 | .write = early_serial_write, | 1308 | .write = early_serial_write, |
| 1251 | .device = uart_console_device, | 1309 | .device = uart_console_device, |
| 1252 | .flags = CON_PRINTBUFFER, | 1310 | .flags = CON_PRINTBUFFER, |
| 1253 | .setup = bfin_serial_console_setup, | ||
| 1254 | .index = -1, | 1311 | .index = -1, |
| 1255 | .data = &bfin_serial_reg, | 1312 | .data = &bfin_serial_reg, |
| 1256 | }; | 1313 | }; |
diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c index 529c0ff7952c..34b4ae0fe760 100644 --- a/drivers/serial/bfin_sport_uart.c +++ b/drivers/serial/bfin_sport_uart.c | |||
| @@ -101,15 +101,16 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) | |||
| 101 | { | 101 | { |
| 102 | pr_debug("%s value:%x\n", __func__, value); | 102 | pr_debug("%s value:%x\n", __func__, value); |
| 103 | /* Place a Start and Stop bit */ | 103 | /* Place a Start and Stop bit */ |
| 104 | __asm__ volatile ( | 104 | __asm__ __volatile__ ( |
| 105 | "R2 = b#01111111100;\n\t" | 105 | "R2 = b#01111111100;" |
| 106 | "R3 = b#10000000001;\n\t" | 106 | "R3 = b#10000000001;" |
| 107 | "%0 <<= 2;\n\t" | 107 | "%0 <<= 2;" |
| 108 | "%0 = %0 & R2;\n\t" | 108 | "%0 = %0 & R2;" |
| 109 | "%0 = %0 | R3;\n\t" | 109 | "%0 = %0 | R3;" |
| 110 | :"=r"(value) | 110 | : "=d"(value) |
| 111 | :"0"(value) | 111 | : "d"(value) |
| 112 | :"R2", "R3"); | 112 | : "ASTAT", "R2", "R3" |
| 113 | ); | ||
| 113 | pr_debug("%s value:%x\n", __func__, value); | 114 | pr_debug("%s value:%x\n", __func__, value); |
| 114 | 115 | ||
| 115 | SPORT_PUT_TX(up, value); | 116 | SPORT_PUT_TX(up, value); |
| @@ -118,27 +119,30 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value) | |||
| 118 | static inline unsigned int rx_one_byte(struct sport_uart_port *up) | 119 | static inline unsigned int rx_one_byte(struct sport_uart_port *up) |
| 119 | { | 120 | { |
| 120 | unsigned int value, extract; | 121 | unsigned int value, extract; |
| 122 | u32 tmp_mask1, tmp_mask2, tmp_shift, tmp; | ||
| 121 | 123 | ||
| 122 | value = SPORT_GET_RX32(up); | 124 | value = SPORT_GET_RX32(up); |
| 123 | pr_debug("%s value:%x\n", __func__, value); | 125 | pr_debug("%s value:%x\n", __func__, value); |
| 124 | 126 | ||
| 125 | /* Extract 8 bits data */ | 127 | /* Extract 8 bits data */ |
| 126 | __asm__ volatile ( | 128 | __asm__ __volatile__ ( |
| 127 | "R5 = 0;\n\t" | 129 | "%[extr] = 0;" |
| 128 | "P0 = 8;\n\t" | 130 | "%[mask1] = 0x1801(Z);" |
| 129 | "R1 = 0x1801(Z);\n\t" | 131 | "%[mask2] = 0x0300(Z);" |
| 130 | "R3 = 0x0300(Z);\n\t" | 132 | "%[shift] = 0;" |
| 131 | "R4 = 0;\n\t" | 133 | "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];" |
| 132 | "LSETUP(loop_s, loop_e) LC0 = P0;\nloop_s:\t" | 134 | ".Lloop_s:" |
| 133 | "R2 = extract(%1, R1.L)(Z);\n\t" | 135 | "%[tmp] = extract(%[val], %[mask1].L)(Z);" |
| 134 | "R2 <<= R4;\n\t" | 136 | "%[tmp] <<= %[shift];" |
| 135 | "R5 = R5 | R2;\n\t" | 137 | "%[extr] = %[extr] | %[tmp];" |
| 136 | "R1 = R1 - R3;\nloop_e:\t" | 138 | "%[mask1] = %[mask1] - %[mask2];" |
| 137 | "R4 += 1;\n\t" | 139 | ".Lloop_e:" |
| 138 | "%0 = R5;\n\t" | 140 | "%[shift] += 1;" |
| 139 | :"=r"(extract) | 141 | : [val]"=d"(value), [extr]"=d"(extract), [shift]"=d"(tmp_shift), [tmp]"=d"(tmp), |
| 140 | :"r"(value) | 142 | [mask1]"=d"(tmp_mask1), [mask2]"=d"(tmp_mask2) |
| 141 | :"P0", "R1", "R2","R3","R4", "R5"); | 143 | : "d"(value), [lc]"a"(8) |
| 144 | : "ASTAT", "LB0", "LC0", "LT0" | ||
| 145 | ); | ||
| 142 | 146 | ||
| 143 | pr_debug(" extract:%x\n", extract); | 147 | pr_debug(" extract:%x\n", extract); |
| 144 | return extract; | 148 | return extract; |
| @@ -149,7 +153,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate) | |||
| 149 | int tclkdiv, tfsdiv, rclkdiv; | 153 | int tclkdiv, tfsdiv, rclkdiv; |
| 150 | 154 | ||
| 151 | /* Set TCR1 and TCR2 */ | 155 | /* Set TCR1 and TCR2 */ |
| 152 | SPORT_PUT_TCR1(up, (LTFS | ITFS | TFSR | TLSBIT | ITCLK)); | 156 | SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK)); |
| 153 | SPORT_PUT_TCR2(up, 10); | 157 | SPORT_PUT_TCR2(up, 10); |
| 154 | pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); | 158 | pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up)); |
| 155 | 159 | ||
| @@ -419,7 +423,7 @@ static void sport_shutdown(struct uart_port *port) | |||
| 419 | } | 423 | } |
| 420 | 424 | ||
| 421 | static void sport_set_termios(struct uart_port *port, | 425 | static void sport_set_termios(struct uart_port *port, |
| 422 | struct termios *termios, struct termios *old) | 426 | struct ktermios *termios, struct ktermios *old) |
| 423 | { | 427 | { |
| 424 | pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); | 428 | pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag); |
| 425 | uart_update_timeout(port, CS8 ,port->uartclk); | 429 | uart_update_timeout(port, CS8 ,port->uartclk); |
diff --git a/drivers/serial/icom.c b/drivers/serial/icom.c index a461b3b2c72d..9f2891c2c4a2 100644 --- a/drivers/serial/icom.c +++ b/drivers/serial/icom.c | |||
| @@ -137,7 +137,12 @@ static LIST_HEAD(icom_adapter_head); | |||
| 137 | static spinlock_t icom_lock; | 137 | static spinlock_t icom_lock; |
| 138 | 138 | ||
| 139 | #ifdef ICOM_TRACE | 139 | #ifdef ICOM_TRACE |
| 140 | static inline void trace(struct icom_port *, char *, unsigned long) {}; | 140 | static inline void trace(struct icom_port *icom_port, char *trace_pt, |
| 141 | unsigned long trace_data) | ||
| 142 | { | ||
| 143 | dev_info(&icom_port->adapter->pci_dev->dev, ":%d:%s - %lx\n", | ||
| 144 | icom_port->port, trace_pt, trace_data); | ||
| 145 | } | ||
| 141 | #else | 146 | #else |
| 142 | static inline void trace(struct icom_port *icom_port, char *trace_pt, unsigned long trace_data) {}; | 147 | static inline void trace(struct icom_port *icom_port, char *trace_pt, unsigned long trace_data) {}; |
| 143 | #endif | 148 | #endif |
| @@ -408,7 +413,7 @@ static void load_code(struct icom_port *icom_port) | |||
| 408 | release_firmware(fw); | 413 | release_firmware(fw); |
| 409 | 414 | ||
| 410 | /* Set Hardware level */ | 415 | /* Set Hardware level */ |
| 411 | if ((icom_port->adapter->version | ADAPTER_V2) == ADAPTER_V2) | 416 | if (icom_port->adapter->version == ADAPTER_V2) |
| 412 | writeb(V2_HARDWARE, &(icom_port->dram->misc_flags)); | 417 | writeb(V2_HARDWARE, &(icom_port->dram->misc_flags)); |
| 413 | 418 | ||
| 414 | /* Start the processor in Adapter */ | 419 | /* Start the processor in Adapter */ |
| @@ -861,7 +866,7 @@ static irqreturn_t icom_interrupt(int irq, void *dev_id) | |||
| 861 | /* find icom_port for this interrupt */ | 866 | /* find icom_port for this interrupt */ |
| 862 | icom_adapter = (struct icom_adapter *) dev_id; | 867 | icom_adapter = (struct icom_adapter *) dev_id; |
| 863 | 868 | ||
| 864 | if ((icom_adapter->version | ADAPTER_V2) == ADAPTER_V2) { | 869 | if (icom_adapter->version == ADAPTER_V2) { |
| 865 | int_reg = icom_adapter->base_addr + 0x8024; | 870 | int_reg = icom_adapter->base_addr + 0x8024; |
| 866 | 871 | ||
| 867 | adapter_interrupts = readl(int_reg); | 872 | adapter_interrupts = readl(int_reg); |
| @@ -1647,15 +1652,6 @@ static void __exit icom_exit(void) | |||
| 1647 | module_init(icom_init); | 1652 | module_init(icom_init); |
| 1648 | module_exit(icom_exit); | 1653 | module_exit(icom_exit); |
| 1649 | 1654 | ||
| 1650 | #ifdef ICOM_TRACE | ||
| 1651 | static inline void trace(struct icom_port *icom_port, char *trace_pt, | ||
| 1652 | unsigned long trace_data) | ||
| 1653 | { | ||
| 1654 | dev_info(&icom_port->adapter->pci_dev->dev, ":%d:%s - %lx\n", | ||
| 1655 | icom_port->port, trace_pt, trace_data); | ||
| 1656 | } | ||
| 1657 | #endif | ||
| 1658 | |||
| 1659 | MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>"); | 1655 | MODULE_AUTHOR("Michael Anderson <mjanders@us.ibm.com>"); |
| 1660 | MODULE_DESCRIPTION("IBM iSeries Serial IOA driver"); | 1656 | MODULE_DESCRIPTION("IBM iSeries Serial IOA driver"); |
| 1661 | MODULE_SUPPORTED_DEVICE | 1657 | MODULE_SUPPORTED_DEVICE |
diff --git a/drivers/serial/imx.c b/drivers/serial/imx.c index 9f460b175c50..7b5d1de9cfe3 100644 --- a/drivers/serial/imx.c +++ b/drivers/serial/imx.c | |||
| @@ -8,6 +8,9 @@ | |||
| 8 | * Author: Sascha Hauer <sascha@saschahauer.de> | 8 | * Author: Sascha Hauer <sascha@saschahauer.de> |
| 9 | * Copyright (C) 2004 Pengutronix | 9 | * Copyright (C) 2004 Pengutronix |
| 10 | * | 10 | * |
| 11 | * Copyright (C) 2009 emlix GmbH | ||
| 12 | * Author: Fabian Godehardt (added IrDA support for iMX) | ||
| 13 | * | ||
| 11 | * This program is free software; you can redistribute it and/or modify | 14 | * This program is free software; you can redistribute it and/or modify |
| 12 | * it under the terms of the GNU General Public License as published by | 15 | * it under the terms of the GNU General Public License as published by |
| 13 | * the Free Software Foundation; either version 2 of the License, or | 16 | * the Free Software Foundation; either version 2 of the License, or |
| @@ -41,6 +44,8 @@ | |||
| 41 | #include <linux/serial_core.h> | 44 | #include <linux/serial_core.h> |
| 42 | #include <linux/serial.h> | 45 | #include <linux/serial.h> |
| 43 | #include <linux/clk.h> | 46 | #include <linux/clk.h> |
| 47 | #include <linux/delay.h> | ||
| 48 | #include <linux/rational.h> | ||
| 44 | 49 | ||
| 45 | #include <asm/io.h> | 50 | #include <asm/io.h> |
| 46 | #include <asm/irq.h> | 51 | #include <asm/irq.h> |
| @@ -148,6 +153,7 @@ | |||
| 148 | #define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ | 153 | #define UCR4_DREN (1<<0) /* Recv data ready interrupt enable */ |
| 149 | #define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ | 154 | #define UFCR_RXTL_SHF 0 /* Receiver trigger level shift */ |
| 150 | #define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ | 155 | #define UFCR_RFDIV (7<<7) /* Reference freq divider mask */ |
| 156 | #define UFCR_RFDIV_REG(x) (((x) < 7 ? 6 - (x) : 6) << 7) | ||
| 151 | #define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ | 157 | #define UFCR_TXTL_SHF 10 /* Transmitter trigger level shift */ |
| 152 | #define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ | 158 | #define USR1_PARITYERR (1<<15) /* Parity error interrupt flag */ |
| 153 | #define USR1_RTSS (1<<14) /* RTS pin status */ | 159 | #define USR1_RTSS (1<<14) /* RTS pin status */ |
| @@ -211,10 +217,20 @@ struct imx_port { | |||
| 211 | struct timer_list timer; | 217 | struct timer_list timer; |
| 212 | unsigned int old_status; | 218 | unsigned int old_status; |
| 213 | int txirq,rxirq,rtsirq; | 219 | int txirq,rxirq,rtsirq; |
| 214 | int have_rtscts:1; | 220 | unsigned int have_rtscts:1; |
| 221 | unsigned int use_irda:1; | ||
| 222 | unsigned int irda_inv_rx:1; | ||
| 223 | unsigned int irda_inv_tx:1; | ||
| 224 | unsigned short trcv_delay; /* transceiver delay */ | ||
| 215 | struct clk *clk; | 225 | struct clk *clk; |
| 216 | }; | 226 | }; |
| 217 | 227 | ||
| 228 | #ifdef CONFIG_IRDA | ||
| 229 | #define USE_IRDA(sport) ((sport)->use_irda) | ||
| 230 | #else | ||
| 231 | #define USE_IRDA(sport) (0) | ||
| 232 | #endif | ||
| 233 | |||
| 218 | /* | 234 | /* |
| 219 | * Handle any change of modem status signal since we were last called. | 235 | * Handle any change of modem status signal since we were last called. |
| 220 | */ | 236 | */ |
| @@ -268,6 +284,48 @@ static void imx_stop_tx(struct uart_port *port) | |||
| 268 | struct imx_port *sport = (struct imx_port *)port; | 284 | struct imx_port *sport = (struct imx_port *)port; |
| 269 | unsigned long temp; | 285 | unsigned long temp; |
| 270 | 286 | ||
| 287 | if (USE_IRDA(sport)) { | ||
| 288 | /* half duplex - wait for end of transmission */ | ||
| 289 | int n = 256; | ||
| 290 | while ((--n > 0) && | ||
| 291 | !(readl(sport->port.membase + USR2) & USR2_TXDC)) { | ||
| 292 | udelay(5); | ||
| 293 | barrier(); | ||
| 294 | } | ||
| 295 | /* | ||
| 296 | * irda transceiver - wait a bit more to avoid | ||
| 297 | * cutoff, hardware dependent | ||
| 298 | */ | ||
| 299 | udelay(sport->trcv_delay); | ||
| 300 | |||
| 301 | /* | ||
| 302 | * half duplex - reactivate receive mode, | ||
| 303 | * flush receive pipe echo crap | ||
| 304 | */ | ||
| 305 | if (readl(sport->port.membase + USR2) & USR2_TXDC) { | ||
| 306 | temp = readl(sport->port.membase + UCR1); | ||
| 307 | temp &= ~(UCR1_TXMPTYEN | UCR1_TRDYEN); | ||
| 308 | writel(temp, sport->port.membase + UCR1); | ||
| 309 | |||
| 310 | temp = readl(sport->port.membase + UCR4); | ||
| 311 | temp &= ~(UCR4_TCEN); | ||
| 312 | writel(temp, sport->port.membase + UCR4); | ||
| 313 | |||
| 314 | while (readl(sport->port.membase + URXD0) & | ||
| 315 | URXD_CHARRDY) | ||
| 316 | barrier(); | ||
| 317 | |||
| 318 | temp = readl(sport->port.membase + UCR1); | ||
| 319 | temp |= UCR1_RRDYEN; | ||
| 320 | writel(temp, sport->port.membase + UCR1); | ||
| 321 | |||
| 322 | temp = readl(sport->port.membase + UCR4); | ||
| 323 | temp |= UCR4_DREN; | ||
| 324 | writel(temp, sport->port.membase + UCR4); | ||
| 325 | } | ||
| 326 | return; | ||
| 327 | } | ||
| 328 | |||
| 271 | temp = readl(sport->port.membase + UCR1); | 329 | temp = readl(sport->port.membase + UCR1); |
| 272 | writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1); | 330 | writel(temp & ~UCR1_TXMPTYEN, sport->port.membase + UCR1); |
| 273 | } | 331 | } |
| @@ -302,13 +360,15 @@ static inline void imx_transmit_buffer(struct imx_port *sport) | |||
| 302 | /* send xmit->buf[xmit->tail] | 360 | /* send xmit->buf[xmit->tail] |
| 303 | * out the port here */ | 361 | * out the port here */ |
| 304 | writel(xmit->buf[xmit->tail], sport->port.membase + URTX0); | 362 | writel(xmit->buf[xmit->tail], sport->port.membase + URTX0); |
| 305 | xmit->tail = (xmit->tail + 1) & | 363 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
| 306 | (UART_XMIT_SIZE - 1); | ||
| 307 | sport->port.icount.tx++; | 364 | sport->port.icount.tx++; |
| 308 | if (uart_circ_empty(xmit)) | 365 | if (uart_circ_empty(xmit)) |
| 309 | break; | 366 | break; |
| 310 | } | 367 | } |
| 311 | 368 | ||
| 369 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 370 | uart_write_wakeup(&sport->port); | ||
| 371 | |||
| 312 | if (uart_circ_empty(xmit)) | 372 | if (uart_circ_empty(xmit)) |
| 313 | imx_stop_tx(&sport->port); | 373 | imx_stop_tx(&sport->port); |
| 314 | } | 374 | } |
| @@ -321,9 +381,30 @@ static void imx_start_tx(struct uart_port *port) | |||
| 321 | struct imx_port *sport = (struct imx_port *)port; | 381 | struct imx_port *sport = (struct imx_port *)port; |
| 322 | unsigned long temp; | 382 | unsigned long temp; |
| 323 | 383 | ||
| 384 | if (USE_IRDA(sport)) { | ||
| 385 | /* half duplex in IrDA mode; have to disable receive mode */ | ||
| 386 | temp = readl(sport->port.membase + UCR4); | ||
| 387 | temp &= ~(UCR4_DREN); | ||
| 388 | writel(temp, sport->port.membase + UCR4); | ||
| 389 | |||
| 390 | temp = readl(sport->port.membase + UCR1); | ||
| 391 | temp &= ~(UCR1_RRDYEN); | ||
| 392 | writel(temp, sport->port.membase + UCR1); | ||
| 393 | } | ||
| 394 | |||
| 324 | temp = readl(sport->port.membase + UCR1); | 395 | temp = readl(sport->port.membase + UCR1); |
| 325 | writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); | 396 | writel(temp | UCR1_TXMPTYEN, sport->port.membase + UCR1); |
| 326 | 397 | ||
| 398 | if (USE_IRDA(sport)) { | ||
| 399 | temp = readl(sport->port.membase + UCR1); | ||
| 400 | temp |= UCR1_TRDYEN; | ||
| 401 | writel(temp, sport->port.membase + UCR1); | ||
| 402 | |||
| 403 | temp = readl(sport->port.membase + UCR4); | ||
| 404 | temp |= UCR4_TCEN; | ||
| 405 | writel(temp, sport->port.membase + UCR4); | ||
| 406 | } | ||
| 407 | |||
| 327 | if (readl(sport->port.membase + UTS) & UTS_TXEMPTY) | 408 | if (readl(sport->port.membase + UTS) & UTS_TXEMPTY) |
| 328 | imx_transmit_buffer(sport); | 409 | imx_transmit_buffer(sport); |
| 329 | } | 410 | } |
| @@ -395,8 +476,7 @@ static irqreturn_t imx_rxint(int irq, void *dev_id) | |||
| 395 | continue; | 476 | continue; |
| 396 | } | 477 | } |
| 397 | 478 | ||
| 398 | if (uart_handle_sysrq_char | 479 | if (uart_handle_sysrq_char(&sport->port, (unsigned char)rx)) |
| 399 | (&sport->port, (unsigned char)rx)) | ||
| 400 | continue; | 480 | continue; |
| 401 | 481 | ||
| 402 | if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) { | 482 | if (rx & (URXD_PRERR | URXD_OVRRUN | URXD_FRMERR) ) { |
| @@ -471,26 +551,26 @@ static unsigned int imx_tx_empty(struct uart_port *port) | |||
| 471 | */ | 551 | */ |
| 472 | static unsigned int imx_get_mctrl(struct uart_port *port) | 552 | static unsigned int imx_get_mctrl(struct uart_port *port) |
| 473 | { | 553 | { |
| 474 | struct imx_port *sport = (struct imx_port *)port; | 554 | struct imx_port *sport = (struct imx_port *)port; |
| 475 | unsigned int tmp = TIOCM_DSR | TIOCM_CAR; | 555 | unsigned int tmp = TIOCM_DSR | TIOCM_CAR; |
| 476 | 556 | ||
| 477 | if (readl(sport->port.membase + USR1) & USR1_RTSS) | 557 | if (readl(sport->port.membase + USR1) & USR1_RTSS) |
| 478 | tmp |= TIOCM_CTS; | 558 | tmp |= TIOCM_CTS; |
| 479 | 559 | ||
| 480 | if (readl(sport->port.membase + UCR2) & UCR2_CTS) | 560 | if (readl(sport->port.membase + UCR2) & UCR2_CTS) |
| 481 | tmp |= TIOCM_RTS; | 561 | tmp |= TIOCM_RTS; |
| 482 | 562 | ||
| 483 | return tmp; | 563 | return tmp; |
| 484 | } | 564 | } |
| 485 | 565 | ||
| 486 | static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) | 566 | static void imx_set_mctrl(struct uart_port *port, unsigned int mctrl) |
| 487 | { | 567 | { |
| 488 | struct imx_port *sport = (struct imx_port *)port; | 568 | struct imx_port *sport = (struct imx_port *)port; |
| 489 | unsigned long temp; | 569 | unsigned long temp; |
| 490 | 570 | ||
| 491 | temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS; | 571 | temp = readl(sport->port.membase + UCR2) & ~UCR2_CTS; |
| 492 | 572 | ||
| 493 | if (mctrl & TIOCM_RTS) | 573 | if (mctrl & TIOCM_RTS) |
| 494 | temp |= UCR2_CTS; | 574 | temp |= UCR2_CTS; |
| 495 | 575 | ||
| 496 | writel(temp, sport->port.membase + UCR2); | 576 | writel(temp, sport->port.membase + UCR2); |
| @@ -534,12 +614,7 @@ static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode) | |||
| 534 | if(!ufcr_rfdiv) | 614 | if(!ufcr_rfdiv) |
| 535 | ufcr_rfdiv = 1; | 615 | ufcr_rfdiv = 1; |
| 536 | 616 | ||
| 537 | if(ufcr_rfdiv >= 7) | 617 | val |= UFCR_RFDIV_REG(ufcr_rfdiv); |
| 538 | ufcr_rfdiv = 6; | ||
| 539 | else | ||
| 540 | ufcr_rfdiv = 6 - ufcr_rfdiv; | ||
| 541 | |||
| 542 | val |= UFCR_RFDIV & (ufcr_rfdiv << 7); | ||
| 543 | 618 | ||
| 544 | writel(val, sport->port.membase + UFCR); | 619 | writel(val, sport->port.membase + UFCR); |
| 545 | 620 | ||
| @@ -558,8 +633,24 @@ static int imx_startup(struct uart_port *port) | |||
| 558 | * requesting IRQs | 633 | * requesting IRQs |
| 559 | */ | 634 | */ |
| 560 | temp = readl(sport->port.membase + UCR4); | 635 | temp = readl(sport->port.membase + UCR4); |
| 636 | |||
| 637 | if (USE_IRDA(sport)) | ||
| 638 | temp |= UCR4_IRSC; | ||
| 639 | |||
| 561 | writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); | 640 | writel(temp & ~UCR4_DREN, sport->port.membase + UCR4); |
| 562 | 641 | ||
| 642 | if (USE_IRDA(sport)) { | ||
| 643 | /* reset fifo's and state machines */ | ||
| 644 | int i = 100; | ||
| 645 | temp = readl(sport->port.membase + UCR2); | ||
| 646 | temp &= ~UCR2_SRST; | ||
| 647 | writel(temp, sport->port.membase + UCR2); | ||
| 648 | while (!(readl(sport->port.membase + UCR2) & UCR2_SRST) && | ||
| 649 | (--i > 0)) { | ||
| 650 | udelay(1); | ||
| 651 | } | ||
| 652 | } | ||
| 653 | |||
| 563 | /* | 654 | /* |
| 564 | * Allocate the IRQ(s) i.MX1 has three interrupts whereas later | 655 | * Allocate the IRQ(s) i.MX1 has three interrupts whereas later |
| 565 | * chips only have one interrupt. | 656 | * chips only have one interrupt. |
| @@ -575,12 +666,16 @@ static int imx_startup(struct uart_port *port) | |||
| 575 | if (retval) | 666 | if (retval) |
| 576 | goto error_out2; | 667 | goto error_out2; |
| 577 | 668 | ||
| 578 | retval = request_irq(sport->rtsirq, imx_rtsint, | 669 | /* do not use RTS IRQ on IrDA */ |
| 579 | (sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 : | 670 | if (!USE_IRDA(sport)) { |
| 580 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 671 | retval = request_irq(sport->rtsirq, imx_rtsint, |
| 581 | DRIVER_NAME, sport); | 672 | (sport->rtsirq < MAX_INTERNAL_IRQ) ? 0 : |
| 582 | if (retval) | 673 | IRQF_TRIGGER_FALLING | |
| 583 | goto error_out3; | 674 | IRQF_TRIGGER_RISING, |
| 675 | DRIVER_NAME, sport); | ||
| 676 | if (retval) | ||
| 677 | goto error_out3; | ||
| 678 | } | ||
| 584 | } else { | 679 | } else { |
| 585 | retval = request_irq(sport->port.irq, imx_int, 0, | 680 | retval = request_irq(sport->port.irq, imx_int, 0, |
| 586 | DRIVER_NAME, sport); | 681 | DRIVER_NAME, sport); |
| @@ -597,18 +692,49 @@ static int imx_startup(struct uart_port *port) | |||
| 597 | 692 | ||
| 598 | temp = readl(sport->port.membase + UCR1); | 693 | temp = readl(sport->port.membase + UCR1); |
| 599 | temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN; | 694 | temp |= UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN; |
| 695 | |||
| 696 | if (USE_IRDA(sport)) { | ||
| 697 | temp |= UCR1_IREN; | ||
| 698 | temp &= ~(UCR1_RTSDEN); | ||
| 699 | } | ||
| 700 | |||
| 600 | writel(temp, sport->port.membase + UCR1); | 701 | writel(temp, sport->port.membase + UCR1); |
| 601 | 702 | ||
| 602 | temp = readl(sport->port.membase + UCR2); | 703 | temp = readl(sport->port.membase + UCR2); |
| 603 | temp |= (UCR2_RXEN | UCR2_TXEN); | 704 | temp |= (UCR2_RXEN | UCR2_TXEN); |
| 604 | writel(temp, sport->port.membase + UCR2); | 705 | writel(temp, sport->port.membase + UCR2); |
| 605 | 706 | ||
| 707 | if (USE_IRDA(sport)) { | ||
| 708 | /* clear RX-FIFO */ | ||
| 709 | int i = 64; | ||
| 710 | while ((--i > 0) && | ||
| 711 | (readl(sport->port.membase + URXD0) & URXD_CHARRDY)) { | ||
| 712 | barrier(); | ||
| 713 | } | ||
| 714 | } | ||
| 715 | |||
| 606 | #if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3 | 716 | #if defined CONFIG_ARCH_MX2 || defined CONFIG_ARCH_MX3 |
| 607 | temp = readl(sport->port.membase + UCR3); | 717 | temp = readl(sport->port.membase + UCR3); |
| 608 | temp |= UCR3_RXDMUXSEL; | 718 | temp |= UCR3_RXDMUXSEL; |
| 609 | writel(temp, sport->port.membase + UCR3); | 719 | writel(temp, sport->port.membase + UCR3); |
| 610 | #endif | 720 | #endif |
| 611 | 721 | ||
| 722 | if (USE_IRDA(sport)) { | ||
| 723 | temp = readl(sport->port.membase + UCR4); | ||
| 724 | if (sport->irda_inv_rx) | ||
| 725 | temp |= UCR4_INVR; | ||
| 726 | else | ||
| 727 | temp &= ~(UCR4_INVR); | ||
| 728 | writel(temp | UCR4_DREN, sport->port.membase + UCR4); | ||
| 729 | |||
| 730 | temp = readl(sport->port.membase + UCR3); | ||
| 731 | if (sport->irda_inv_tx) | ||
| 732 | temp |= UCR3_INVT; | ||
| 733 | else | ||
| 734 | temp &= ~(UCR3_INVT); | ||
| 735 | writel(temp, sport->port.membase + UCR3); | ||
| 736 | } | ||
| 737 | |||
| 612 | /* | 738 | /* |
| 613 | * Enable modem status interrupts | 739 | * Enable modem status interrupts |
| 614 | */ | 740 | */ |
| @@ -616,6 +742,16 @@ static int imx_startup(struct uart_port *port) | |||
| 616 | imx_enable_ms(&sport->port); | 742 | imx_enable_ms(&sport->port); |
| 617 | spin_unlock_irqrestore(&sport->port.lock,flags); | 743 | spin_unlock_irqrestore(&sport->port.lock,flags); |
| 618 | 744 | ||
| 745 | if (USE_IRDA(sport)) { | ||
| 746 | struct imxuart_platform_data *pdata; | ||
| 747 | pdata = sport->port.dev->platform_data; | ||
| 748 | sport->irda_inv_rx = pdata->irda_inv_rx; | ||
| 749 | sport->irda_inv_tx = pdata->irda_inv_tx; | ||
| 750 | sport->trcv_delay = pdata->transceiver_delay; | ||
| 751 | if (pdata->irda_enable) | ||
| 752 | pdata->irda_enable(1); | ||
| 753 | } | ||
| 754 | |||
| 619 | return 0; | 755 | return 0; |
| 620 | 756 | ||
| 621 | error_out3: | 757 | error_out3: |
| @@ -633,6 +769,17 @@ static void imx_shutdown(struct uart_port *port) | |||
| 633 | struct imx_port *sport = (struct imx_port *)port; | 769 | struct imx_port *sport = (struct imx_port *)port; |
| 634 | unsigned long temp; | 770 | unsigned long temp; |
| 635 | 771 | ||
| 772 | temp = readl(sport->port.membase + UCR2); | ||
| 773 | temp &= ~(UCR2_TXEN); | ||
| 774 | writel(temp, sport->port.membase + UCR2); | ||
| 775 | |||
| 776 | if (USE_IRDA(sport)) { | ||
| 777 | struct imxuart_platform_data *pdata; | ||
| 778 | pdata = sport->port.dev->platform_data; | ||
| 779 | if (pdata->irda_enable) | ||
| 780 | pdata->irda_enable(0); | ||
| 781 | } | ||
| 782 | |||
| 636 | /* | 783 | /* |
| 637 | * Stop our timer. | 784 | * Stop our timer. |
| 638 | */ | 785 | */ |
| @@ -642,7 +789,8 @@ static void imx_shutdown(struct uart_port *port) | |||
| 642 | * Free the interrupts | 789 | * Free the interrupts |
| 643 | */ | 790 | */ |
| 644 | if (sport->txirq > 0) { | 791 | if (sport->txirq > 0) { |
| 645 | free_irq(sport->rtsirq, sport); | 792 | if (!USE_IRDA(sport)) |
| 793 | free_irq(sport->rtsirq, sport); | ||
| 646 | free_irq(sport->txirq, sport); | 794 | free_irq(sport->txirq, sport); |
| 647 | free_irq(sport->rxirq, sport); | 795 | free_irq(sport->rxirq, sport); |
| 648 | } else | 796 | } else |
| @@ -654,6 +802,9 @@ static void imx_shutdown(struct uart_port *port) | |||
| 654 | 802 | ||
| 655 | temp = readl(sport->port.membase + UCR1); | 803 | temp = readl(sport->port.membase + UCR1); |
| 656 | temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); | 804 | temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN); |
| 805 | if (USE_IRDA(sport)) | ||
| 806 | temp &= ~(UCR1_IREN); | ||
| 807 | |||
| 657 | writel(temp, sport->port.membase + UCR1); | 808 | writel(temp, sport->port.membase + UCR1); |
| 658 | } | 809 | } |
| 659 | 810 | ||
| @@ -665,7 +816,9 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 665 | unsigned long flags; | 816 | unsigned long flags; |
| 666 | unsigned int ucr2, old_ucr1, old_txrxen, baud, quot; | 817 | unsigned int ucr2, old_ucr1, old_txrxen, baud, quot; |
| 667 | unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; | 818 | unsigned int old_csize = old ? old->c_cflag & CSIZE : CS8; |
| 668 | unsigned int div, num, denom, ufcr; | 819 | unsigned int div, ufcr; |
| 820 | unsigned long num, denom; | ||
| 821 | uint64_t tdiv64; | ||
| 669 | 822 | ||
| 670 | /* | 823 | /* |
| 671 | * If we don't support modem control lines, don't allow | 824 | * If we don't support modem control lines, don't allow |
| @@ -761,38 +914,39 @@ imx_set_termios(struct uart_port *port, struct ktermios *termios, | |||
| 761 | sport->port.membase + UCR2); | 914 | sport->port.membase + UCR2); |
| 762 | old_txrxen &= (UCR2_TXEN | UCR2_RXEN); | 915 | old_txrxen &= (UCR2_TXEN | UCR2_RXEN); |
| 763 | 916 | ||
| 764 | div = sport->port.uartclk / (baud * 16); | 917 | if (USE_IRDA(sport)) { |
| 765 | if (div > 7) | 918 | /* |
| 766 | div = 7; | 919 | * use maximum available submodule frequency to |
| 767 | if (!div) | 920 | * avoid missing short pulses due to low sampling rate |
| 921 | */ | ||
| 768 | div = 1; | 922 | div = 1; |
| 769 | 923 | } else { | |
| 770 | num = baud; | 924 | div = sport->port.uartclk / (baud * 16); |
| 771 | denom = port->uartclk / div / 16; | 925 | if (div > 7) |
| 772 | 926 | div = 7; | |
| 773 | /* shift num and denom right until they fit into 16 bits */ | 927 | if (!div) |
| 774 | while (num > 0x10000 || denom > 0x10000) { | 928 | div = 1; |
| 775 | num >>= 1; | ||
| 776 | denom >>= 1; | ||
| 777 | } | 929 | } |
| 778 | if (num > 0) | ||
| 779 | num -= 1; | ||
| 780 | if (denom > 0) | ||
| 781 | denom -= 1; | ||
| 782 | 930 | ||
| 783 | writel(num, sport->port.membase + UBIR); | 931 | rational_best_approximation(16 * div * baud, sport->port.uartclk, |
| 784 | writel(denom, sport->port.membase + UBMR); | 932 | 1 << 16, 1 << 16, &num, &denom); |
| 785 | 933 | ||
| 786 | if (div == 7) | 934 | tdiv64 = sport->port.uartclk; |
| 787 | div = 6; /* 6 in RFDIV means divide by 7 */ | 935 | tdiv64 *= num; |
| 788 | else | 936 | do_div(tdiv64, denom * 16 * div); |
| 789 | div = 6 - div; | 937 | tty_encode_baud_rate(sport->port.info->port.tty, |
| 938 | (speed_t)tdiv64, (speed_t)tdiv64); | ||
| 939 | |||
| 940 | num -= 1; | ||
| 941 | denom -= 1; | ||
| 790 | 942 | ||
| 791 | ufcr = readl(sport->port.membase + UFCR); | 943 | ufcr = readl(sport->port.membase + UFCR); |
| 792 | ufcr = (ufcr & (~UFCR_RFDIV)) | | 944 | ufcr = (ufcr & (~UFCR_RFDIV)) | UFCR_RFDIV_REG(div); |
| 793 | (div << 7); | ||
| 794 | writel(ufcr, sport->port.membase + UFCR); | 945 | writel(ufcr, sport->port.membase + UFCR); |
| 795 | 946 | ||
| 947 | writel(num, sport->port.membase + UBIR); | ||
| 948 | writel(denom, sport->port.membase + UBMR); | ||
| 949 | |||
| 796 | #ifdef ONEMS | 950 | #ifdef ONEMS |
| 797 | writel(sport->port.uartclk / div / 1000, sport->port.membase + ONEMS); | 951 | writel(sport->port.uartclk / div / 1000, sport->port.membase + ONEMS); |
| 798 | #endif | 952 | #endif |
| @@ -1031,6 +1185,8 @@ imx_console_setup(struct console *co, char *options) | |||
| 1031 | if (co->index == -1 || co->index >= ARRAY_SIZE(imx_ports)) | 1185 | if (co->index == -1 || co->index >= ARRAY_SIZE(imx_ports)) |
| 1032 | co->index = 0; | 1186 | co->index = 0; |
| 1033 | sport = imx_ports[co->index]; | 1187 | sport = imx_ports[co->index]; |
| 1188 | if(sport == NULL) | ||
| 1189 | return -ENODEV; | ||
| 1034 | 1190 | ||
| 1035 | if (options) | 1191 | if (options) |
| 1036 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1192 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
| @@ -1070,22 +1226,22 @@ static struct uart_driver imx_reg = { | |||
| 1070 | 1226 | ||
| 1071 | static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) | 1227 | static int serial_imx_suspend(struct platform_device *dev, pm_message_t state) |
| 1072 | { | 1228 | { |
| 1073 | struct imx_port *sport = platform_get_drvdata(dev); | 1229 | struct imx_port *sport = platform_get_drvdata(dev); |
| 1074 | 1230 | ||
| 1075 | if (sport) | 1231 | if (sport) |
| 1076 | uart_suspend_port(&imx_reg, &sport->port); | 1232 | uart_suspend_port(&imx_reg, &sport->port); |
| 1077 | 1233 | ||
| 1078 | return 0; | 1234 | return 0; |
| 1079 | } | 1235 | } |
| 1080 | 1236 | ||
| 1081 | static int serial_imx_resume(struct platform_device *dev) | 1237 | static int serial_imx_resume(struct platform_device *dev) |
| 1082 | { | 1238 | { |
| 1083 | struct imx_port *sport = platform_get_drvdata(dev); | 1239 | struct imx_port *sport = platform_get_drvdata(dev); |
| 1084 | 1240 | ||
| 1085 | if (sport) | 1241 | if (sport) |
| 1086 | uart_resume_port(&imx_reg, &sport->port); | 1242 | uart_resume_port(&imx_reg, &sport->port); |
| 1087 | 1243 | ||
| 1088 | return 0; | 1244 | return 0; |
| 1089 | } | 1245 | } |
| 1090 | 1246 | ||
| 1091 | static int serial_imx_probe(struct platform_device *pdev) | 1247 | static int serial_imx_probe(struct platform_device *pdev) |
| @@ -1141,19 +1297,29 @@ static int serial_imx_probe(struct platform_device *pdev) | |||
| 1141 | imx_ports[pdev->id] = sport; | 1297 | imx_ports[pdev->id] = sport; |
| 1142 | 1298 | ||
| 1143 | pdata = pdev->dev.platform_data; | 1299 | pdata = pdev->dev.platform_data; |
| 1144 | if(pdata && (pdata->flags & IMXUART_HAVE_RTSCTS)) | 1300 | if (pdata && (pdata->flags & IMXUART_HAVE_RTSCTS)) |
| 1145 | sport->have_rtscts = 1; | 1301 | sport->have_rtscts = 1; |
| 1146 | 1302 | ||
| 1303 | #ifdef CONFIG_IRDA | ||
| 1304 | if (pdata && (pdata->flags & IMXUART_IRDA)) | ||
| 1305 | sport->use_irda = 1; | ||
| 1306 | #endif | ||
| 1307 | |||
| 1147 | if (pdata->init) { | 1308 | if (pdata->init) { |
| 1148 | ret = pdata->init(pdev); | 1309 | ret = pdata->init(pdev); |
| 1149 | if (ret) | 1310 | if (ret) |
| 1150 | goto clkput; | 1311 | goto clkput; |
| 1151 | } | 1312 | } |
| 1152 | 1313 | ||
| 1153 | uart_add_one_port(&imx_reg, &sport->port); | 1314 | ret = uart_add_one_port(&imx_reg, &sport->port); |
| 1315 | if (ret) | ||
| 1316 | goto deinit; | ||
| 1154 | platform_set_drvdata(pdev, &sport->port); | 1317 | platform_set_drvdata(pdev, &sport->port); |
| 1155 | 1318 | ||
| 1156 | return 0; | 1319 | return 0; |
| 1320 | deinit: | ||
| 1321 | if (pdata->exit) | ||
| 1322 | pdata->exit(pdev); | ||
| 1157 | clkput: | 1323 | clkput: |
| 1158 | clk_put(sport->clk); | 1324 | clk_put(sport->clk); |
| 1159 | clk_disable(sport->clk); | 1325 | clk_disable(sport->clk); |
| @@ -1191,13 +1357,13 @@ static int serial_imx_remove(struct platform_device *pdev) | |||
| 1191 | } | 1357 | } |
| 1192 | 1358 | ||
| 1193 | static struct platform_driver serial_imx_driver = { | 1359 | static struct platform_driver serial_imx_driver = { |
| 1194 | .probe = serial_imx_probe, | 1360 | .probe = serial_imx_probe, |
| 1195 | .remove = serial_imx_remove, | 1361 | .remove = serial_imx_remove, |
| 1196 | 1362 | ||
| 1197 | .suspend = serial_imx_suspend, | 1363 | .suspend = serial_imx_suspend, |
| 1198 | .resume = serial_imx_resume, | 1364 | .resume = serial_imx_resume, |
| 1199 | .driver = { | 1365 | .driver = { |
| 1200 | .name = "imx-uart", | 1366 | .name = "imx-uart", |
| 1201 | .owner = THIS_MODULE, | 1367 | .owner = THIS_MODULE, |
| 1202 | }, | 1368 | }, |
| 1203 | }; | 1369 | }; |
diff --git a/drivers/serial/jsm/jsm.h b/drivers/serial/jsm/jsm.h index c0a3e2734e24..4e5f3bde0461 100644 --- a/drivers/serial/jsm/jsm.h +++ b/drivers/serial/jsm/jsm.h | |||
| @@ -61,6 +61,7 @@ enum { | |||
| 61 | if ((DBG_##nlevel & jsm_debug)) \ | 61 | if ((DBG_##nlevel & jsm_debug)) \ |
| 62 | dev_printk(KERN_##klevel, pdev->dev, fmt, ## args) | 62 | dev_printk(KERN_##klevel, pdev->dev, fmt, ## args) |
| 63 | 63 | ||
| 64 | #define MAXLINES 256 | ||
| 64 | #define MAXPORTS 8 | 65 | #define MAXPORTS 8 |
| 65 | #define MAX_STOPS_SENT 5 | 66 | #define MAX_STOPS_SENT 5 |
| 66 | 67 | ||
diff --git a/drivers/serial/jsm/jsm_tty.c b/drivers/serial/jsm/jsm_tty.c index 31496dc0a0d1..107ce2e187b8 100644 --- a/drivers/serial/jsm/jsm_tty.c +++ b/drivers/serial/jsm/jsm_tty.c | |||
| @@ -33,6 +33,8 @@ | |||
| 33 | 33 | ||
| 34 | #include "jsm.h" | 34 | #include "jsm.h" |
| 35 | 35 | ||
| 36 | static DECLARE_BITMAP(linemap, MAXLINES); | ||
| 37 | |||
| 36 | static void jsm_carrier(struct jsm_channel *ch); | 38 | static void jsm_carrier(struct jsm_channel *ch); |
| 37 | 39 | ||
| 38 | static inline int jsm_get_mstat(struct jsm_channel *ch) | 40 | static inline int jsm_get_mstat(struct jsm_channel *ch) |
| @@ -433,6 +435,7 @@ int __devinit jsm_tty_init(struct jsm_board *brd) | |||
| 433 | int __devinit jsm_uart_port_init(struct jsm_board *brd) | 435 | int __devinit jsm_uart_port_init(struct jsm_board *brd) |
| 434 | { | 436 | { |
| 435 | int i; | 437 | int i; |
| 438 | unsigned int line; | ||
| 436 | struct jsm_channel *ch; | 439 | struct jsm_channel *ch; |
| 437 | 440 | ||
| 438 | if (!brd) | 441 | if (!brd) |
| @@ -459,9 +462,15 @@ int __devinit jsm_uart_port_init(struct jsm_board *brd) | |||
| 459 | brd->channels[i]->uart_port.membase = brd->re_map_membase; | 462 | brd->channels[i]->uart_port.membase = brd->re_map_membase; |
| 460 | brd->channels[i]->uart_port.fifosize = 16; | 463 | brd->channels[i]->uart_port.fifosize = 16; |
| 461 | brd->channels[i]->uart_port.ops = &jsm_ops; | 464 | brd->channels[i]->uart_port.ops = &jsm_ops; |
| 462 | brd->channels[i]->uart_port.line = brd->channels[i]->ch_portnum + brd->boardnum * 2; | 465 | line = find_first_zero_bit(linemap, MAXLINES); |
| 466 | if (line >= MAXLINES) { | ||
| 467 | printk(KERN_INFO "jsm: linemap is full, added device failed\n"); | ||
| 468 | continue; | ||
| 469 | } else | ||
| 470 | set_bit((int)line, linemap); | ||
| 471 | brd->channels[i]->uart_port.line = line; | ||
| 463 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) | 472 | if (uart_add_one_port (&jsm_uart_driver, &brd->channels[i]->uart_port)) |
| 464 | printk(KERN_INFO "Added device failed\n"); | 473 | printk(KERN_INFO "jsm: add device failed\n"); |
| 465 | else | 474 | else |
| 466 | printk(KERN_INFO "Added device \n"); | 475 | printk(KERN_INFO "Added device \n"); |
| 467 | } | 476 | } |
| @@ -494,6 +503,7 @@ int jsm_remove_uart_port(struct jsm_board *brd) | |||
| 494 | 503 | ||
| 495 | ch = brd->channels[i]; | 504 | ch = brd->channels[i]; |
| 496 | 505 | ||
| 506 | clear_bit((int)(ch->uart_port.line), linemap); | ||
| 497 | uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port); | 507 | uart_remove_one_port(&jsm_uart_driver, &brd->channels[i]->uart_port); |
| 498 | } | 508 | } |
| 499 | 509 | ||
diff --git a/drivers/serial/mpc52xx_uart.c b/drivers/serial/mpc52xx_uart.c index 7f72f8ceaa6f..b3feb6198d57 100644 --- a/drivers/serial/mpc52xx_uart.c +++ b/drivers/serial/mpc52xx_uart.c | |||
| @@ -988,7 +988,7 @@ mpc52xx_console_setup(struct console *co, char *options) | |||
| 988 | pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n", | 988 | pr_debug("mpc52xx_console_setup co=%p, co->index=%i, options=%s\n", |
| 989 | co, co->index, options); | 989 | co, co->index, options); |
| 990 | 990 | ||
| 991 | if ((co->index < 0) || (co->index > MPC52xx_PSC_MAXNUM)) { | 991 | if ((co->index < 0) || (co->index >= MPC52xx_PSC_MAXNUM)) { |
| 992 | pr_debug("PSC%x out of range\n", co->index); | 992 | pr_debug("PSC%x out of range\n", co->index); |
| 993 | return -EINVAL; | 993 | return -EINVAL; |
| 994 | } | 994 | } |
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index dbf5357a77b3..a4cf1079b312 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
| @@ -47,12 +47,17 @@ | |||
| 47 | #include <linux/clk.h> | 47 | #include <linux/clk.h> |
| 48 | #include <linux/ctype.h> | 48 | #include <linux/ctype.h> |
| 49 | #include <linux/err.h> | 49 | #include <linux/err.h> |
| 50 | #include <linux/list.h> | ||
| 50 | 51 | ||
| 51 | #ifdef CONFIG_SUPERH | 52 | #ifdef CONFIG_SUPERH |
| 52 | #include <asm/clock.h> | 53 | #include <asm/clock.h> |
| 53 | #include <asm/sh_bios.h> | 54 | #include <asm/sh_bios.h> |
| 54 | #endif | 55 | #endif |
| 55 | 56 | ||
| 57 | #ifdef CONFIG_H8300 | ||
| 58 | #include <asm/gpio.h> | ||
| 59 | #endif | ||
| 60 | |||
| 56 | #include "sh-sci.h" | 61 | #include "sh-sci.h" |
| 57 | 62 | ||
| 58 | struct sci_port { | 63 | struct sci_port { |
| @@ -75,14 +80,22 @@ struct sci_port { | |||
| 75 | int break_flag; | 80 | int break_flag; |
| 76 | 81 | ||
| 77 | #ifdef CONFIG_HAVE_CLK | 82 | #ifdef CONFIG_HAVE_CLK |
| 78 | /* Port clock */ | 83 | /* Interface clock */ |
| 79 | struct clk *clk; | 84 | struct clk *iclk; |
| 85 | /* Data clock */ | ||
| 86 | struct clk *dclk; | ||
| 80 | #endif | 87 | #endif |
| 88 | struct list_head node; | ||
| 81 | }; | 89 | }; |
| 82 | 90 | ||
| 83 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 91 | struct sh_sci_priv { |
| 84 | static struct sci_port *serial_console_port; | 92 | spinlock_t lock; |
| 93 | struct list_head ports; | ||
| 94 | |||
| 95 | #ifdef CONFIG_HAVE_CLK | ||
| 96 | struct notifier_block clk_nb; | ||
| 85 | #endif | 97 | #endif |
| 98 | }; | ||
| 86 | 99 | ||
| 87 | /* Function prototypes */ | 100 | /* Function prototypes */ |
| 88 | static void sci_stop_tx(struct uart_port *port); | 101 | static void sci_stop_tx(struct uart_port *port); |
| @@ -138,9 +151,8 @@ static void sci_poll_put_char(struct uart_port *port, unsigned char c) | |||
| 138 | status = sci_in(port, SCxSR); | 151 | status = sci_in(port, SCxSR); |
| 139 | } while (!(status & SCxSR_TDxE(port))); | 152 | } while (!(status & SCxSR_TDxE(port))); |
| 140 | 153 | ||
| 141 | sci_in(port, SCxSR); /* Dummy read */ | ||
| 142 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); | ||
| 143 | sci_out(port, SCxTDR, c); | 154 | sci_out(port, SCxTDR, c); |
| 155 | sci_out(port, SCxSR, SCxSR_TDxE_CLEAR(port) & ~SCxSR_TEND(port)); | ||
| 144 | } | 156 | } |
| 145 | #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ | 157 | #endif /* CONFIG_CONSOLE_POLL || CONFIG_SERIAL_SH_SCI_CONSOLE */ |
| 146 | 158 | ||
| @@ -159,12 +171,12 @@ static void h8300_sci_config(struct uart_port *port, unsigned int ctrl) | |||
| 159 | *mstpcrl &= ~mask; | 171 | *mstpcrl &= ~mask; |
| 160 | } | 172 | } |
| 161 | 173 | ||
| 162 | static inline void h8300_sci_enable(struct uart_port *port) | 174 | static void h8300_sci_enable(struct uart_port *port) |
| 163 | { | 175 | { |
| 164 | h8300_sci_config(port, sci_enable); | 176 | h8300_sci_config(port, sci_enable); |
| 165 | } | 177 | } |
| 166 | 178 | ||
| 167 | static inline void h8300_sci_disable(struct uart_port *port) | 179 | static void h8300_sci_disable(struct uart_port *port) |
| 168 | { | 180 | { |
| 169 | h8300_sci_config(port, sci_disable); | 181 | h8300_sci_config(port, sci_disable); |
| 170 | } | 182 | } |
| @@ -611,7 +623,7 @@ static inline int sci_handle_breaks(struct uart_port *port) | |||
| 611 | int copied = 0; | 623 | int copied = 0; |
| 612 | unsigned short status = sci_in(port, SCxSR); | 624 | unsigned short status = sci_in(port, SCxSR); |
| 613 | struct tty_struct *tty = port->info->port.tty; | 625 | struct tty_struct *tty = port->info->port.tty; |
| 614 | struct sci_port *s = &sci_ports[port->line]; | 626 | struct sci_port *s = to_sci_port(port); |
| 615 | 627 | ||
| 616 | if (uart_handle_break(port)) | 628 | if (uart_handle_break(port)) |
| 617 | return 0; | 629 | return 0; |
| @@ -726,19 +738,43 @@ static irqreturn_t sci_mpxed_interrupt(int irq, void *ptr) | |||
| 726 | static int sci_notifier(struct notifier_block *self, | 738 | static int sci_notifier(struct notifier_block *self, |
| 727 | unsigned long phase, void *p) | 739 | unsigned long phase, void *p) |
| 728 | { | 740 | { |
| 729 | int i; | 741 | struct sh_sci_priv *priv = container_of(self, |
| 742 | struct sh_sci_priv, clk_nb); | ||
| 743 | struct sci_port *sci_port; | ||
| 744 | unsigned long flags; | ||
| 730 | 745 | ||
| 731 | if ((phase == CPUFREQ_POSTCHANGE) || | 746 | if ((phase == CPUFREQ_POSTCHANGE) || |
| 732 | (phase == CPUFREQ_RESUMECHANGE)) | 747 | (phase == CPUFREQ_RESUMECHANGE)) { |
| 733 | for (i = 0; i < SCI_NPORTS; i++) { | 748 | spin_lock_irqsave(&priv->lock, flags); |
| 734 | struct sci_port *s = &sci_ports[i]; | 749 | list_for_each_entry(sci_port, &priv->ports, node) |
| 735 | s->port.uartclk = clk_get_rate(s->clk); | 750 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); |
| 736 | } | 751 | |
| 752 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 753 | } | ||
| 737 | 754 | ||
| 738 | return NOTIFY_OK; | 755 | return NOTIFY_OK; |
| 739 | } | 756 | } |
| 740 | 757 | ||
| 741 | static struct notifier_block sci_nb = { &sci_notifier, NULL, 0 }; | 758 | static void sci_clk_enable(struct uart_port *port) |
| 759 | { | ||
| 760 | struct sci_port *sci_port = to_sci_port(port); | ||
| 761 | |||
| 762 | clk_enable(sci_port->dclk); | ||
| 763 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | ||
| 764 | |||
| 765 | if (sci_port->iclk) | ||
| 766 | clk_enable(sci_port->iclk); | ||
| 767 | } | ||
| 768 | |||
| 769 | static void sci_clk_disable(struct uart_port *port) | ||
| 770 | { | ||
| 771 | struct sci_port *sci_port = to_sci_port(port); | ||
| 772 | |||
| 773 | if (sci_port->iclk) | ||
| 774 | clk_disable(sci_port->iclk); | ||
| 775 | |||
| 776 | clk_disable(sci_port->dclk); | ||
| 777 | } | ||
| 742 | #endif | 778 | #endif |
| 743 | 779 | ||
| 744 | static int sci_request_irq(struct sci_port *port) | 780 | static int sci_request_irq(struct sci_port *port) |
| @@ -865,15 +901,11 @@ static void sci_break_ctl(struct uart_port *port, int break_state) | |||
| 865 | 901 | ||
| 866 | static int sci_startup(struct uart_port *port) | 902 | static int sci_startup(struct uart_port *port) |
| 867 | { | 903 | { |
| 868 | struct sci_port *s = &sci_ports[port->line]; | 904 | struct sci_port *s = to_sci_port(port); |
| 869 | 905 | ||
| 870 | if (s->enable) | 906 | if (s->enable) |
| 871 | s->enable(port); | 907 | s->enable(port); |
| 872 | 908 | ||
| 873 | #ifdef CONFIG_HAVE_CLK | ||
| 874 | s->clk = clk_get(NULL, "module_clk"); | ||
| 875 | #endif | ||
| 876 | |||
| 877 | sci_request_irq(s); | 909 | sci_request_irq(s); |
| 878 | sci_start_tx(port); | 910 | sci_start_tx(port); |
| 879 | sci_start_rx(port, 1); | 911 | sci_start_rx(port, 1); |
| @@ -883,7 +915,7 @@ static int sci_startup(struct uart_port *port) | |||
| 883 | 915 | ||
| 884 | static void sci_shutdown(struct uart_port *port) | 916 | static void sci_shutdown(struct uart_port *port) |
| 885 | { | 917 | { |
| 886 | struct sci_port *s = &sci_ports[port->line]; | 918 | struct sci_port *s = to_sci_port(port); |
| 887 | 919 | ||
| 888 | sci_stop_rx(port); | 920 | sci_stop_rx(port); |
| 889 | sci_stop_tx(port); | 921 | sci_stop_tx(port); |
| @@ -891,11 +923,6 @@ static void sci_shutdown(struct uart_port *port) | |||
| 891 | 923 | ||
| 892 | if (s->disable) | 924 | if (s->disable) |
| 893 | s->disable(port); | 925 | s->disable(port); |
| 894 | |||
| 895 | #ifdef CONFIG_HAVE_CLK | ||
| 896 | clk_put(s->clk); | ||
| 897 | s->clk = NULL; | ||
| 898 | #endif | ||
| 899 | } | 926 | } |
| 900 | 927 | ||
| 901 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, | 928 | static void sci_set_termios(struct uart_port *port, struct ktermios *termios, |
| @@ -980,25 +1007,31 @@ static int sci_request_port(struct uart_port *port) | |||
| 980 | 1007 | ||
| 981 | static void sci_config_port(struct uart_port *port, int flags) | 1008 | static void sci_config_port(struct uart_port *port, int flags) |
| 982 | { | 1009 | { |
| 983 | struct sci_port *s = &sci_ports[port->line]; | 1010 | struct sci_port *s = to_sci_port(port); |
| 984 | 1011 | ||
| 985 | port->type = s->type; | 1012 | port->type = s->type; |
| 986 | 1013 | ||
| 987 | if (port->flags & UPF_IOREMAP && !port->membase) { | 1014 | if (port->membase) |
| 988 | #if defined(CONFIG_SUPERH64) | 1015 | return; |
| 989 | port->mapbase = onchip_remap(SCIF_ADDR_SH5, 1024, "SCIF"); | 1016 | |
| 990 | port->membase = (void __iomem *)port->mapbase; | 1017 | if (port->flags & UPF_IOREMAP) { |
| 991 | #else | ||
| 992 | port->membase = ioremap_nocache(port->mapbase, 0x40); | 1018 | port->membase = ioremap_nocache(port->mapbase, 0x40); |
| 993 | #endif | ||
| 994 | 1019 | ||
| 995 | dev_err(port->dev, "can't remap port#%d\n", port->line); | 1020 | if (IS_ERR(port->membase)) |
| 1021 | dev_err(port->dev, "can't remap port#%d\n", port->line); | ||
| 1022 | } else { | ||
| 1023 | /* | ||
| 1024 | * For the simple (and majority of) cases where we don't | ||
| 1025 | * need to do any remapping, just cast the cookie | ||
| 1026 | * directly. | ||
| 1027 | */ | ||
| 1028 | port->membase = (void __iomem *)port->mapbase; | ||
| 996 | } | 1029 | } |
| 997 | } | 1030 | } |
| 998 | 1031 | ||
| 999 | static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) | 1032 | static int sci_verify_port(struct uart_port *port, struct serial_struct *ser) |
| 1000 | { | 1033 | { |
| 1001 | struct sci_port *s = &sci_ports[port->line]; | 1034 | struct sci_port *s = to_sci_port(port); |
| 1002 | 1035 | ||
| 1003 | if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs) | 1036 | if (ser->irq != s->irqs[SCIx_TXI_IRQ] || ser->irq > nr_irqs) |
| 1004 | return -EINVAL; | 1037 | return -EINVAL; |
| @@ -1032,63 +1065,60 @@ static struct uart_ops sci_uart_ops = { | |||
| 1032 | #endif | 1065 | #endif |
| 1033 | }; | 1066 | }; |
| 1034 | 1067 | ||
| 1035 | static void __init sci_init_ports(void) | 1068 | static void __devinit sci_init_single(struct platform_device *dev, |
| 1069 | struct sci_port *sci_port, | ||
| 1070 | unsigned int index, | ||
| 1071 | struct plat_sci_port *p) | ||
| 1036 | { | 1072 | { |
| 1037 | static int first = 1; | 1073 | sci_port->port.ops = &sci_uart_ops; |
| 1038 | int i; | 1074 | sci_port->port.iotype = UPIO_MEM; |
| 1039 | 1075 | sci_port->port.line = index; | |
| 1040 | if (!first) | 1076 | sci_port->port.fifosize = 1; |
| 1041 | return; | ||
| 1042 | |||
| 1043 | first = 0; | ||
| 1044 | |||
| 1045 | for (i = 0; i < SCI_NPORTS; i++) { | ||
| 1046 | sci_ports[i].port.ops = &sci_uart_ops; | ||
| 1047 | sci_ports[i].port.iotype = UPIO_MEM; | ||
| 1048 | sci_ports[i].port.line = i; | ||
| 1049 | sci_ports[i].port.fifosize = 1; | ||
| 1050 | 1077 | ||
| 1051 | #if defined(__H8300H__) || defined(__H8300S__) | 1078 | #if defined(__H8300H__) || defined(__H8300S__) |
| 1052 | #ifdef __H8300S__ | 1079 | #ifdef __H8300S__ |
| 1053 | sci_ports[i].enable = h8300_sci_enable; | 1080 | sci_port->enable = h8300_sci_enable; |
| 1054 | sci_ports[i].disable = h8300_sci_disable; | 1081 | sci_port->disable = h8300_sci_disable; |
| 1055 | #endif | 1082 | #endif |
| 1056 | sci_ports[i].port.uartclk = CONFIG_CPU_CLOCK; | 1083 | sci_port->port.uartclk = CONFIG_CPU_CLOCK; |
| 1057 | #elif defined(CONFIG_HAVE_CLK) | 1084 | #elif defined(CONFIG_HAVE_CLK) |
| 1058 | /* | 1085 | sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; |
| 1059 | * XXX: We should use a proper SCI/SCIF clock | 1086 | sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); |
| 1060 | */ | 1087 | sci_port->enable = sci_clk_enable; |
| 1061 | { | 1088 | sci_port->disable = sci_clk_disable; |
| 1062 | struct clk *clk = clk_get(NULL, "module_clk"); | ||
| 1063 | sci_ports[i].port.uartclk = clk_get_rate(clk); | ||
| 1064 | clk_put(clk); | ||
| 1065 | } | ||
| 1066 | #else | 1089 | #else |
| 1067 | #error "Need a valid uartclk" | 1090 | #error "Need a valid uartclk" |
| 1068 | #endif | 1091 | #endif |
| 1069 | 1092 | ||
| 1070 | sci_ports[i].break_timer.data = (unsigned long)&sci_ports[i]; | 1093 | sci_port->break_timer.data = (unsigned long)sci_port; |
| 1071 | sci_ports[i].break_timer.function = sci_break_timer; | 1094 | sci_port->break_timer.function = sci_break_timer; |
| 1095 | init_timer(&sci_port->break_timer); | ||
| 1072 | 1096 | ||
| 1073 | init_timer(&sci_ports[i].break_timer); | 1097 | sci_port->port.mapbase = p->mapbase; |
| 1074 | } | 1098 | sci_port->port.membase = p->membase; |
| 1075 | } | ||
| 1076 | |||
| 1077 | int __init early_sci_setup(struct uart_port *port) | ||
| 1078 | { | ||
| 1079 | if (unlikely(port->line > SCI_NPORTS)) | ||
| 1080 | return -ENODEV; | ||
| 1081 | 1099 | ||
| 1082 | sci_init_ports(); | 1100 | sci_port->port.irq = p->irqs[SCIx_TXI_IRQ]; |
| 1101 | sci_port->port.flags = p->flags; | ||
| 1102 | sci_port->port.dev = &dev->dev; | ||
| 1103 | sci_port->type = sci_port->port.type = p->type; | ||
| 1083 | 1104 | ||
| 1084 | sci_ports[port->line].port.membase = port->membase; | 1105 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); |
| 1085 | sci_ports[port->line].port.mapbase = port->mapbase; | ||
| 1086 | sci_ports[port->line].port.type = port->type; | ||
| 1087 | 1106 | ||
| 1088 | return 0; | ||
| 1089 | } | 1107 | } |
| 1090 | 1108 | ||
| 1091 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 1109 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE |
| 1110 | static struct tty_driver *serial_console_device(struct console *co, int *index) | ||
| 1111 | { | ||
| 1112 | struct uart_driver *p = &sci_uart_driver; | ||
| 1113 | *index = co->index; | ||
| 1114 | return p->tty_driver; | ||
| 1115 | } | ||
| 1116 | |||
| 1117 | static void serial_console_putchar(struct uart_port *port, int ch) | ||
| 1118 | { | ||
| 1119 | sci_poll_put_char(port, ch); | ||
| 1120 | } | ||
| 1121 | |||
| 1092 | /* | 1122 | /* |
| 1093 | * Print a string to the serial port trying not to disturb | 1123 | * Print a string to the serial port trying not to disturb |
| 1094 | * any possible real use of the port... | 1124 | * any possible real use of the port... |
| @@ -1096,25 +1126,27 @@ int __init early_sci_setup(struct uart_port *port) | |||
| 1096 | static void serial_console_write(struct console *co, const char *s, | 1126 | static void serial_console_write(struct console *co, const char *s, |
| 1097 | unsigned count) | 1127 | unsigned count) |
| 1098 | { | 1128 | { |
| 1099 | struct uart_port *port = &serial_console_port->port; | 1129 | struct uart_port *port = co->data; |
| 1130 | struct sci_port *sci_port = to_sci_port(port); | ||
| 1100 | unsigned short bits; | 1131 | unsigned short bits; |
| 1101 | int i; | ||
| 1102 | 1132 | ||
| 1103 | for (i = 0; i < count; i++) { | 1133 | if (sci_port->enable) |
| 1104 | if (*s == 10) | 1134 | sci_port->enable(port); |
| 1105 | sci_poll_put_char(port, '\r'); | ||
| 1106 | 1135 | ||
| 1107 | sci_poll_put_char(port, *s++); | 1136 | uart_console_write(port, s, count, serial_console_putchar); |
| 1108 | } | ||
| 1109 | 1137 | ||
| 1110 | /* wait until fifo is empty and last bit has been transmitted */ | 1138 | /* wait until fifo is empty and last bit has been transmitted */ |
| 1111 | bits = SCxSR_TDxE(port) | SCxSR_TEND(port); | 1139 | bits = SCxSR_TDxE(port) | SCxSR_TEND(port); |
| 1112 | while ((sci_in(port, SCxSR) & bits) != bits) | 1140 | while ((sci_in(port, SCxSR) & bits) != bits) |
| 1113 | cpu_relax(); | 1141 | cpu_relax(); |
| 1142 | |||
| 1143 | if (sci_port->disable); | ||
| 1144 | sci_port->disable(port); | ||
| 1114 | } | 1145 | } |
| 1115 | 1146 | ||
| 1116 | static int __init serial_console_setup(struct console *co, char *options) | 1147 | static int __init serial_console_setup(struct console *co, char *options) |
| 1117 | { | 1148 | { |
| 1149 | struct sci_port *sci_port; | ||
| 1118 | struct uart_port *port; | 1150 | struct uart_port *port; |
| 1119 | int baud = 115200; | 1151 | int baud = 115200; |
| 1120 | int bits = 8; | 1152 | int bits = 8; |
| @@ -1130,8 +1162,9 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
| 1130 | if (co->index >= SCI_NPORTS) | 1162 | if (co->index >= SCI_NPORTS) |
| 1131 | co->index = 0; | 1163 | co->index = 0; |
| 1132 | 1164 | ||
| 1133 | serial_console_port = &sci_ports[co->index]; | 1165 | sci_port = &sci_ports[co->index]; |
| 1134 | port = &serial_console_port->port; | 1166 | port = &sci_port->port; |
| 1167 | co->data = port; | ||
| 1135 | 1168 | ||
| 1136 | /* | 1169 | /* |
| 1137 | * Also need to check port->type, we don't actually have any | 1170 | * Also need to check port->type, we don't actually have any |
| @@ -1141,21 +1174,11 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
| 1141 | */ | 1174 | */ |
| 1142 | if (!port->type) | 1175 | if (!port->type) |
| 1143 | return -ENODEV; | 1176 | return -ENODEV; |
| 1144 | if (!port->membase || !port->mapbase) | ||
| 1145 | return -ENODEV; | ||
| 1146 | |||
| 1147 | port->type = serial_console_port->type; | ||
| 1148 | |||
| 1149 | #ifdef CONFIG_HAVE_CLK | ||
| 1150 | if (!serial_console_port->clk) | ||
| 1151 | serial_console_port->clk = clk_get(NULL, "module_clk"); | ||
| 1152 | #endif | ||
| 1153 | 1177 | ||
| 1154 | if (port->flags & UPF_IOREMAP) | 1178 | sci_config_port(port, 0); |
| 1155 | sci_config_port(port, 0); | ||
| 1156 | 1179 | ||
| 1157 | if (serial_console_port->enable) | 1180 | if (sci_port->enable) |
| 1158 | serial_console_port->enable(port); | 1181 | sci_port->enable(port); |
| 1159 | 1182 | ||
| 1160 | if (options) | 1183 | if (options) |
| 1161 | uart_parse_options(options, &baud, &parity, &bits, &flow); | 1184 | uart_parse_options(options, &baud, &parity, &bits, &flow); |
| @@ -1166,22 +1189,21 @@ static int __init serial_console_setup(struct console *co, char *options) | |||
| 1166 | if (ret == 0) | 1189 | if (ret == 0) |
| 1167 | sci_stop_rx(port); | 1190 | sci_stop_rx(port); |
| 1168 | #endif | 1191 | #endif |
| 1192 | /* TODO: disable clock */ | ||
| 1169 | return ret; | 1193 | return ret; |
| 1170 | } | 1194 | } |
| 1171 | 1195 | ||
| 1172 | static struct console serial_console = { | 1196 | static struct console serial_console = { |
| 1173 | .name = "ttySC", | 1197 | .name = "ttySC", |
| 1174 | .device = uart_console_device, | 1198 | .device = serial_console_device, |
| 1175 | .write = serial_console_write, | 1199 | .write = serial_console_write, |
| 1176 | .setup = serial_console_setup, | 1200 | .setup = serial_console_setup, |
| 1177 | .flags = CON_PRINTBUFFER, | 1201 | .flags = CON_PRINTBUFFER, |
| 1178 | .index = -1, | 1202 | .index = -1, |
| 1179 | .data = &sci_uart_driver, | ||
| 1180 | }; | 1203 | }; |
| 1181 | 1204 | ||
| 1182 | static int __init sci_console_init(void) | 1205 | static int __init sci_console_init(void) |
| 1183 | { | 1206 | { |
| 1184 | sci_init_ports(); | ||
| 1185 | register_console(&serial_console); | 1207 | register_console(&serial_console); |
| 1186 | return 0; | 1208 | return 0; |
| 1187 | } | 1209 | } |
| @@ -1207,6 +1229,61 @@ static struct uart_driver sci_uart_driver = { | |||
| 1207 | .cons = SCI_CONSOLE, | 1229 | .cons = SCI_CONSOLE, |
| 1208 | }; | 1230 | }; |
| 1209 | 1231 | ||
| 1232 | |||
| 1233 | static int sci_remove(struct platform_device *dev) | ||
| 1234 | { | ||
| 1235 | struct sh_sci_priv *priv = platform_get_drvdata(dev); | ||
| 1236 | struct sci_port *p; | ||
| 1237 | unsigned long flags; | ||
| 1238 | |||
| 1239 | #ifdef CONFIG_HAVE_CLK | ||
| 1240 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
| 1241 | #endif | ||
| 1242 | |||
| 1243 | spin_lock_irqsave(&priv->lock, flags); | ||
| 1244 | list_for_each_entry(p, &priv->ports, node) | ||
| 1245 | uart_remove_one_port(&sci_uart_driver, &p->port); | ||
| 1246 | |||
| 1247 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 1248 | |||
| 1249 | kfree(priv); | ||
| 1250 | return 0; | ||
| 1251 | } | ||
| 1252 | |||
| 1253 | static int __devinit sci_probe_single(struct platform_device *dev, | ||
| 1254 | unsigned int index, | ||
| 1255 | struct plat_sci_port *p, | ||
| 1256 | struct sci_port *sciport) | ||
| 1257 | { | ||
| 1258 | struct sh_sci_priv *priv = platform_get_drvdata(dev); | ||
| 1259 | unsigned long flags; | ||
| 1260 | int ret; | ||
| 1261 | |||
| 1262 | /* Sanity check */ | ||
| 1263 | if (unlikely(index >= SCI_NPORTS)) { | ||
| 1264 | dev_notice(&dev->dev, "Attempting to register port " | ||
| 1265 | "%d when only %d are available.\n", | ||
| 1266 | index+1, SCI_NPORTS); | ||
| 1267 | dev_notice(&dev->dev, "Consider bumping " | ||
| 1268 | "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); | ||
| 1269 | return 0; | ||
| 1270 | } | ||
| 1271 | |||
| 1272 | sci_init_single(dev, sciport, index, p); | ||
| 1273 | |||
| 1274 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); | ||
| 1275 | if (ret) | ||
| 1276 | return ret; | ||
| 1277 | |||
| 1278 | INIT_LIST_HEAD(&sciport->node); | ||
| 1279 | |||
| 1280 | spin_lock_irqsave(&priv->lock, flags); | ||
| 1281 | list_add(&sciport->node, &priv->ports); | ||
| 1282 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 1283 | |||
| 1284 | return 0; | ||
| 1285 | } | ||
| 1286 | |||
| 1210 | /* | 1287 | /* |
| 1211 | * Register a set of serial devices attached to a platform device. The | 1288 | * Register a set of serial devices attached to a platform device. The |
| 1212 | * list is terminated with a zero flags entry, which means we expect | 1289 | * list is terminated with a zero flags entry, which means we expect |
| @@ -1216,57 +1293,34 @@ static struct uart_driver sci_uart_driver = { | |||
| 1216 | static int __devinit sci_probe(struct platform_device *dev) | 1293 | static int __devinit sci_probe(struct platform_device *dev) |
| 1217 | { | 1294 | { |
| 1218 | struct plat_sci_port *p = dev->dev.platform_data; | 1295 | struct plat_sci_port *p = dev->dev.platform_data; |
| 1296 | struct sh_sci_priv *priv; | ||
| 1219 | int i, ret = -EINVAL; | 1297 | int i, ret = -EINVAL; |
| 1220 | 1298 | ||
| 1221 | for (i = 0; p && p->flags != 0; p++, i++) { | 1299 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
| 1222 | struct sci_port *sciport = &sci_ports[i]; | 1300 | if (!priv) |
| 1301 | return -ENOMEM; | ||
| 1223 | 1302 | ||
| 1224 | /* Sanity check */ | 1303 | INIT_LIST_HEAD(&priv->ports); |
| 1225 | if (unlikely(i == SCI_NPORTS)) { | 1304 | spin_lock_init(&priv->lock); |
| 1226 | dev_notice(&dev->dev, "Attempting to register port " | 1305 | platform_set_drvdata(dev, priv); |
| 1227 | "%d when only %d are available.\n", | ||
| 1228 | i+1, SCI_NPORTS); | ||
| 1229 | dev_notice(&dev->dev, "Consider bumping " | ||
| 1230 | "CONFIG_SERIAL_SH_SCI_NR_UARTS!\n"); | ||
| 1231 | break; | ||
| 1232 | } | ||
| 1233 | 1306 | ||
| 1234 | sciport->port.mapbase = p->mapbase; | 1307 | #ifdef CONFIG_HAVE_CLK |
| 1308 | priv->clk_nb.notifier_call = sci_notifier; | ||
| 1309 | cpufreq_register_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
| 1310 | #endif | ||
| 1235 | 1311 | ||
| 1236 | if (p->mapbase && !p->membase) { | 1312 | if (dev->id != -1) { |
| 1237 | if (p->flags & UPF_IOREMAP) { | 1313 | ret = sci_probe_single(dev, dev->id, p, &sci_ports[dev->id]); |
| 1238 | p->membase = ioremap_nocache(p->mapbase, 0x40); | 1314 | if (ret) |
| 1239 | if (IS_ERR(p->membase)) { | 1315 | goto err_unreg; |
| 1240 | ret = PTR_ERR(p->membase); | 1316 | } else { |
| 1241 | goto err_unreg; | 1317 | for (i = 0; p && p->flags != 0; p++, i++) { |
| 1242 | } | 1318 | ret = sci_probe_single(dev, i, p, &sci_ports[i]); |
| 1243 | } else { | 1319 | if (ret) |
| 1244 | /* | 1320 | goto err_unreg; |
| 1245 | * For the simple (and majority of) cases | ||
| 1246 | * where we don't need to do any remapping, | ||
| 1247 | * just cast the cookie directly. | ||
| 1248 | */ | ||
| 1249 | p->membase = (void __iomem *)p->mapbase; | ||
| 1250 | } | ||
| 1251 | } | 1321 | } |
| 1252 | |||
| 1253 | sciport->port.membase = p->membase; | ||
| 1254 | |||
| 1255 | sciport->port.irq = p->irqs[SCIx_TXI_IRQ]; | ||
| 1256 | sciport->port.flags = p->flags; | ||
| 1257 | sciport->port.dev = &dev->dev; | ||
| 1258 | |||
| 1259 | sciport->type = sciport->port.type = p->type; | ||
| 1260 | |||
| 1261 | memcpy(&sciport->irqs, &p->irqs, sizeof(p->irqs)); | ||
| 1262 | |||
| 1263 | uart_add_one_port(&sci_uart_driver, &sciport->port); | ||
| 1264 | } | 1322 | } |
| 1265 | 1323 | ||
| 1266 | #ifdef CONFIG_HAVE_CLK | ||
| 1267 | cpufreq_register_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
| 1268 | #endif | ||
| 1269 | |||
| 1270 | #ifdef CONFIG_SH_STANDARD_BIOS | 1324 | #ifdef CONFIG_SH_STANDARD_BIOS |
| 1271 | sh_bios_gdb_detach(); | 1325 | sh_bios_gdb_detach(); |
| 1272 | #endif | 1326 | #endif |
| @@ -1274,50 +1328,36 @@ static int __devinit sci_probe(struct platform_device *dev) | |||
| 1274 | return 0; | 1328 | return 0; |
| 1275 | 1329 | ||
| 1276 | err_unreg: | 1330 | err_unreg: |
| 1277 | for (i = i - 1; i >= 0; i--) | 1331 | sci_remove(dev); |
| 1278 | uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port); | ||
| 1279 | |||
| 1280 | return ret; | 1332 | return ret; |
| 1281 | } | 1333 | } |
| 1282 | 1334 | ||
| 1283 | static int __devexit sci_remove(struct platform_device *dev) | ||
| 1284 | { | ||
| 1285 | int i; | ||
| 1286 | |||
| 1287 | #ifdef CONFIG_HAVE_CLK | ||
| 1288 | cpufreq_unregister_notifier(&sci_nb, CPUFREQ_TRANSITION_NOTIFIER); | ||
| 1289 | #endif | ||
| 1290 | |||
| 1291 | for (i = 0; i < SCI_NPORTS; i++) | ||
| 1292 | uart_remove_one_port(&sci_uart_driver, &sci_ports[i].port); | ||
| 1293 | |||
| 1294 | return 0; | ||
| 1295 | } | ||
| 1296 | |||
| 1297 | static int sci_suspend(struct platform_device *dev, pm_message_t state) | 1335 | static int sci_suspend(struct platform_device *dev, pm_message_t state) |
| 1298 | { | 1336 | { |
| 1299 | int i; | 1337 | struct sh_sci_priv *priv = platform_get_drvdata(dev); |
| 1338 | struct sci_port *p; | ||
| 1339 | unsigned long flags; | ||
| 1300 | 1340 | ||
| 1301 | for (i = 0; i < SCI_NPORTS; i++) { | 1341 | spin_lock_irqsave(&priv->lock, flags); |
| 1302 | struct sci_port *p = &sci_ports[i]; | 1342 | list_for_each_entry(p, &priv->ports, node) |
| 1343 | uart_suspend_port(&sci_uart_driver, &p->port); | ||
| 1303 | 1344 | ||
| 1304 | if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev) | 1345 | spin_unlock_irqrestore(&priv->lock, flags); |
| 1305 | uart_suspend_port(&sci_uart_driver, &p->port); | ||
| 1306 | } | ||
| 1307 | 1346 | ||
| 1308 | return 0; | 1347 | return 0; |
| 1309 | } | 1348 | } |
| 1310 | 1349 | ||
| 1311 | static int sci_resume(struct platform_device *dev) | 1350 | static int sci_resume(struct platform_device *dev) |
| 1312 | { | 1351 | { |
| 1313 | int i; | 1352 | struct sh_sci_priv *priv = platform_get_drvdata(dev); |
| 1353 | struct sci_port *p; | ||
| 1354 | unsigned long flags; | ||
| 1314 | 1355 | ||
| 1315 | for (i = 0; i < SCI_NPORTS; i++) { | 1356 | spin_lock_irqsave(&priv->lock, flags); |
| 1316 | struct sci_port *p = &sci_ports[i]; | 1357 | list_for_each_entry(p, &priv->ports, node) |
| 1358 | uart_resume_port(&sci_uart_driver, &p->port); | ||
| 1317 | 1359 | ||
| 1318 | if (p->type != PORT_UNKNOWN && p->port.dev == &dev->dev) | 1360 | spin_unlock_irqrestore(&priv->lock, flags); |
| 1319 | uart_resume_port(&sci_uart_driver, &p->port); | ||
| 1320 | } | ||
| 1321 | 1361 | ||
| 1322 | return 0; | 1362 | return 0; |
| 1323 | } | 1363 | } |
| @@ -1339,8 +1379,6 @@ static int __init sci_init(void) | |||
| 1339 | 1379 | ||
| 1340 | printk(banner); | 1380 | printk(banner); |
| 1341 | 1381 | ||
| 1342 | sci_init_ports(); | ||
| 1343 | |||
| 1344 | ret = uart_register_driver(&sci_uart_driver); | 1382 | ret = uart_register_driver(&sci_uart_driver); |
| 1345 | if (likely(ret == 0)) { | 1383 | if (likely(ret == 0)) { |
| 1346 | ret = platform_driver_register(&sci_driver); | 1384 | ret = platform_driver_register(&sci_driver); |
diff --git a/drivers/serial/sh-sci.h b/drivers/serial/sh-sci.h index d0aa82d7fce0..38072c15b845 100644 --- a/drivers/serial/sh-sci.h +++ b/drivers/serial/sh-sci.h | |||
| @@ -91,6 +91,9 @@ | |||
| 91 | # define SCSPTR5 0xa4050128 | 91 | # define SCSPTR5 0xa4050128 |
| 92 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 92 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
| 93 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | 93 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ |
| 94 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
| 95 | # define SCIF_ORER 0x0001 /* overrun error bit */ | ||
| 96 | # define SCSCR_INIT(port) 0x0038 /* TIE=0,RIE=0,TE=1,RE=1,REIE=1 */ | ||
| 94 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) | 97 | #elif defined(CONFIG_CPU_SUBTYPE_SH4_202) |
| 95 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ | 98 | # define SCSPTR2 0xffe80020 /* 16 bit SCIF */ |
| 96 | # define SCIF_ORER 0x0001 /* overrun error bit */ | 99 | # define SCIF_ORER 0x0001 /* overrun error bit */ |
| @@ -314,7 +317,18 @@ | |||
| 314 | } \ | 317 | } \ |
| 315 | } | 318 | } |
| 316 | 319 | ||
| 317 | #define CPU_SCIF_FNS(name, scif_offset, scif_size) \ | 320 | #ifdef CONFIG_H8300 |
| 321 | /* h8300 don't have SCIF */ | ||
| 322 | #define CPU_SCIF_FNS(name) \ | ||
| 323 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ | ||
| 324 | { \ | ||
| 325 | return 0; \ | ||
| 326 | } \ | ||
| 327 | static inline void sci_##name##_out(struct uart_port *port, unsigned int value) \ | ||
| 328 | { \ | ||
| 329 | } | ||
| 330 | #else | ||
| 331 | #define CPU_SCIF_FNS(name, scif_offset, scif_size) \ | ||
| 318 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ | 332 | static inline unsigned int sci_##name##_in(struct uart_port *port) \ |
| 319 | { \ | 333 | { \ |
| 320 | SCI_IN(scif_size, scif_offset); \ | 334 | SCI_IN(scif_size, scif_offset); \ |
| @@ -323,6 +337,7 @@ | |||
| 323 | { \ | 337 | { \ |
| 324 | SCI_OUT(scif_size, scif_offset, value); \ | 338 | SCI_OUT(scif_size, scif_offset, value); \ |
| 325 | } | 339 | } |
| 340 | #endif | ||
| 326 | 341 | ||
| 327 | #define CPU_SCI_FNS(name, sci_offset, sci_size) \ | 342 | #define CPU_SCI_FNS(name, sci_offset, sci_size) \ |
| 328 | static inline unsigned int sci_##name##_in(struct uart_port* port) \ | 343 | static inline unsigned int sci_##name##_in(struct uart_port* port) \ |
| @@ -360,8 +375,10 @@ | |||
| 360 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ | 375 | sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size, \ |
| 361 | h8_sci_offset, h8_sci_size) \ | 376 | h8_sci_offset, h8_sci_size) \ |
| 362 | CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) | 377 | CPU_SCI_FNS(name, h8_sci_offset, h8_sci_size) |
| 363 | #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) | 378 | #define SCIF_FNS(name, sh3_scif_offset, sh3_scif_size, sh4_scif_offset, sh4_scif_size) \ |
| 364 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | 379 | CPU_SCIF_FNS(name) |
| 380 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ | ||
| 381 | defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
| 365 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \ | 382 | #define SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) \ |
| 366 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) | 383 | CPU_SCIx_FNS(name, sh4_scifa_offset, sh4_scifa_size, sh4_scif_offset, sh4_scif_size) |
| 367 | #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ | 384 | #define SCIF_FNS(name, sh4_scif_offset, sh4_scif_size) \ |
| @@ -390,7 +407,8 @@ SCIF_FNS(SCFDR, 0x1c, 16) | |||
| 390 | SCIF_FNS(SCxTDR, 0x20, 8) | 407 | SCIF_FNS(SCxTDR, 0x20, 8) |
| 391 | SCIF_FNS(SCxRDR, 0x24, 8) | 408 | SCIF_FNS(SCxRDR, 0x24, 8) |
| 392 | SCIF_FNS(SCLSR, 0x24, 16) | 409 | SCIF_FNS(SCLSR, 0x24, 16) |
| 393 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | 410 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
| 411 | defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
| 394 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) | 412 | SCIx_FNS(SCSMR, 0x00, 16, 0x00, 16) |
| 395 | SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8) | 413 | SCIx_FNS(SCBRR, 0x04, 8, 0x04, 8) |
| 396 | SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16) | 414 | SCIx_FNS(SCSCR, 0x08, 16, 0x08, 16) |
| @@ -604,10 +622,21 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
| 604 | return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ | 622 | return ctrl_inb(SCSPTR5) & 0x0008 ? 1 : 0; /* SCIF5 */ |
| 605 | return 1; | 623 | return 1; |
| 606 | } | 624 | } |
| 625 | #elif defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
| 626 | # define SCFSR 0x0010 | ||
| 627 | # define SCASSR 0x0014 | ||
| 628 | static inline int sci_rxd_in(struct uart_port *port) | ||
| 629 | { | ||
| 630 | if (port->type == PORT_SCIF) | ||
| 631 | return ctrl_inw((port->mapbase + SCFSR)) & SCIF_BRK ? 1 : 0; | ||
| 632 | if (port->type == PORT_SCIFA) | ||
| 633 | return ctrl_inw((port->mapbase + SCASSR)) & SCIF_BRK ? 1 : 0; | ||
| 634 | return 1; | ||
| 635 | } | ||
| 607 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) | 636 | #elif defined(CONFIG_CPU_SUBTYPE_SH5_101) || defined(CONFIG_CPU_SUBTYPE_SH5_103) |
| 608 | static inline int sci_rxd_in(struct uart_port *port) | 637 | static inline int sci_rxd_in(struct uart_port *port) |
| 609 | { | 638 | { |
| 610 | return sci_in(port, SCSPTR2)&0x0001 ? 1 : 0; /* SCIF */ | 639 | return sci_in(port, SCSPTR)&0x0001 ? 1 : 0; /* SCIF */ |
| 611 | } | 640 | } |
| 612 | #elif defined(__H8300H__) || defined(__H8300S__) | 641 | #elif defined(__H8300H__) || defined(__H8300S__) |
| 613 | static inline int sci_rxd_in(struct uart_port *port) | 642 | static inline int sci_rxd_in(struct uart_port *port) |
| @@ -757,7 +786,8 @@ static inline int sci_rxd_in(struct uart_port *port) | |||
| 757 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ | 786 | defined(CONFIG_CPU_SUBTYPE_SH7720) || \ |
| 758 | defined(CONFIG_CPU_SUBTYPE_SH7721) | 787 | defined(CONFIG_CPU_SUBTYPE_SH7721) |
| 759 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) | 788 | #define SCBRR_VALUE(bps, clk) (((clk*2)+16*bps)/(32*bps)-1) |
| 760 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) | 789 | #elif defined(CONFIG_CPU_SUBTYPE_SH7723) ||\ |
| 790 | defined(CONFIG_CPU_SUBTYPE_SH7724) | ||
| 761 | static inline int scbrr_calc(struct uart_port *port, int bps, int clk) | 791 | static inline int scbrr_calc(struct uart_port *port, int bps, int clk) |
| 762 | { | 792 | { |
| 763 | if (port->type == PORT_SCIF) | 793 | if (port->type == PORT_SCIF) |
diff --git a/drivers/serial/timbuart.c b/drivers/serial/timbuart.c new file mode 100644 index 000000000000..ac9e5d5f742e --- /dev/null +++ b/drivers/serial/timbuart.c | |||
| @@ -0,0 +1,526 @@ | |||
| 1 | /* | ||
| 2 | * timbuart.c timberdale FPGA UART driver | ||
| 3 | * Copyright (c) 2009 Intel Corporation | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* Supports: | ||
| 20 | * Timberdale FPGA UART | ||
| 21 | */ | ||
| 22 | |||
| 23 | #include <linux/pci.h> | ||
| 24 | #include <linux/interrupt.h> | ||
| 25 | #include <linux/serial_core.h> | ||
| 26 | #include <linux/kernel.h> | ||
| 27 | #include <linux/platform_device.h> | ||
| 28 | #include <linux/ioport.h> | ||
| 29 | |||
| 30 | #include "timbuart.h" | ||
| 31 | |||
| 32 | struct timbuart_port { | ||
| 33 | struct uart_port port; | ||
| 34 | struct tasklet_struct tasklet; | ||
| 35 | int usedma; | ||
| 36 | u8 last_ier; | ||
| 37 | struct platform_device *dev; | ||
| 38 | }; | ||
| 39 | |||
| 40 | static int baudrates[] = {9600, 19200, 38400, 57600, 115200, 230400, 460800, | ||
| 41 | 921600, 1843200, 3250000}; | ||
| 42 | |||
| 43 | static void timbuart_mctrl_check(struct uart_port *port, u8 isr, u8 *ier); | ||
| 44 | |||
| 45 | static irqreturn_t timbuart_handleinterrupt(int irq, void *devid); | ||
| 46 | |||
| 47 | static void timbuart_stop_rx(struct uart_port *port) | ||
| 48 | { | ||
| 49 | /* spin lock held by upper layer, disable all RX interrupts */ | ||
| 50 | u8 ier = ioread8(port->membase + TIMBUART_IER) & ~RXFLAGS; | ||
| 51 | iowrite8(ier, port->membase + TIMBUART_IER); | ||
| 52 | } | ||
| 53 | |||
| 54 | static void timbuart_stop_tx(struct uart_port *port) | ||
| 55 | { | ||
| 56 | /* spinlock held by upper layer, disable TX interrupt */ | ||
| 57 | u8 ier = ioread8(port->membase + TIMBUART_IER) & ~TXBAE; | ||
| 58 | iowrite8(ier, port->membase + TIMBUART_IER); | ||
| 59 | } | ||
| 60 | |||
| 61 | static void timbuart_start_tx(struct uart_port *port) | ||
| 62 | { | ||
| 63 | struct timbuart_port *uart = | ||
| 64 | container_of(port, struct timbuart_port, port); | ||
| 65 | |||
| 66 | /* do not transfer anything here -> fire off the tasklet */ | ||
| 67 | tasklet_schedule(&uart->tasklet); | ||
| 68 | } | ||
| 69 | |||
| 70 | static void timbuart_flush_buffer(struct uart_port *port) | ||
| 71 | { | ||
| 72 | u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | TIMBUART_CTRL_FLSHTX; | ||
| 73 | |||
| 74 | iowrite8(ctl, port->membase + TIMBUART_CTRL); | ||
| 75 | iowrite8(TXBF, port->membase + TIMBUART_ISR); | ||
| 76 | } | ||
| 77 | |||
| 78 | static void timbuart_rx_chars(struct uart_port *port) | ||
| 79 | { | ||
| 80 | struct tty_struct *tty = port->info->port.tty; | ||
| 81 | |||
| 82 | while (ioread8(port->membase + TIMBUART_ISR) & RXDP) { | ||
| 83 | u8 ch = ioread8(port->membase + TIMBUART_RXFIFO); | ||
| 84 | port->icount.rx++; | ||
| 85 | tty_insert_flip_char(tty, ch, TTY_NORMAL); | ||
| 86 | } | ||
| 87 | |||
| 88 | spin_unlock(&port->lock); | ||
| 89 | tty_flip_buffer_push(port->info->port.tty); | ||
| 90 | spin_lock(&port->lock); | ||
| 91 | |||
| 92 | dev_dbg(port->dev, "%s - total read %d bytes\n", | ||
| 93 | __func__, port->icount.rx); | ||
| 94 | } | ||
| 95 | |||
| 96 | static void timbuart_tx_chars(struct uart_port *port) | ||
| 97 | { | ||
| 98 | struct circ_buf *xmit = &port->info->xmit; | ||
| 99 | |||
| 100 | while (!(ioread8(port->membase + TIMBUART_ISR) & TXBF) && | ||
| 101 | !uart_circ_empty(xmit)) { | ||
| 102 | iowrite8(xmit->buf[xmit->tail], | ||
| 103 | port->membase + TIMBUART_TXFIFO); | ||
| 104 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | ||
| 105 | port->icount.tx++; | ||
| 106 | } | ||
| 107 | |||
| 108 | dev_dbg(port->dev, | ||
| 109 | "%s - total written %d bytes, CTL: %x, RTS: %x, baud: %x\n", | ||
| 110 | __func__, | ||
| 111 | port->icount.tx, | ||
| 112 | ioread8(port->membase + TIMBUART_CTRL), | ||
| 113 | port->mctrl & TIOCM_RTS, | ||
| 114 | ioread8(port->membase + TIMBUART_BAUDRATE)); | ||
| 115 | } | ||
| 116 | |||
| 117 | static void timbuart_handle_tx_port(struct uart_port *port, u8 isr, u8 *ier) | ||
| 118 | { | ||
| 119 | struct timbuart_port *uart = | ||
| 120 | container_of(port, struct timbuart_port, port); | ||
| 121 | struct circ_buf *xmit = &port->info->xmit; | ||
| 122 | |||
| 123 | if (uart_circ_empty(xmit) || uart_tx_stopped(port)) | ||
| 124 | return; | ||
| 125 | |||
| 126 | if (port->x_char) | ||
| 127 | return; | ||
| 128 | |||
| 129 | if (isr & TXFLAGS) { | ||
| 130 | timbuart_tx_chars(port); | ||
| 131 | /* clear all TX interrupts */ | ||
| 132 | iowrite8(TXFLAGS, port->membase + TIMBUART_ISR); | ||
| 133 | |||
| 134 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 135 | uart_write_wakeup(port); | ||
| 136 | } else | ||
| 137 | /* Re-enable any tx interrupt */ | ||
| 138 | *ier |= uart->last_ier & TXFLAGS; | ||
| 139 | |||
| 140 | /* enable interrupts if there are chars in the transmit buffer, | ||
| 141 | * Or if we delivered some bytes and want the almost empty interrupt | ||
| 142 | * we wake up the upper layer later when we got the interrupt | ||
| 143 | * to give it some time to go out... | ||
| 144 | */ | ||
| 145 | if (!uart_circ_empty(xmit)) | ||
| 146 | *ier |= TXBAE; | ||
| 147 | |||
| 148 | dev_dbg(port->dev, "%s - leaving\n", __func__); | ||
| 149 | } | ||
| 150 | |||
| 151 | void timbuart_handle_rx_port(struct uart_port *port, u8 isr, u8 *ier) | ||
| 152 | { | ||
| 153 | if (isr & RXFLAGS) { | ||
| 154 | /* Some RX status is set */ | ||
| 155 | if (isr & RXBF) { | ||
| 156 | u8 ctl = ioread8(port->membase + TIMBUART_CTRL) | | ||
| 157 | TIMBUART_CTRL_FLSHRX; | ||
| 158 | iowrite8(ctl, port->membase + TIMBUART_CTRL); | ||
| 159 | port->icount.overrun++; | ||
| 160 | } else if (isr & (RXDP)) | ||
| 161 | timbuart_rx_chars(port); | ||
| 162 | |||
| 163 | /* ack all RX interrupts */ | ||
| 164 | iowrite8(RXFLAGS, port->membase + TIMBUART_ISR); | ||
| 165 | } | ||
| 166 | |||
| 167 | /* always have the RX interrupts enabled */ | ||
| 168 | *ier |= RXBAF | RXBF | RXTT; | ||
| 169 | |||
| 170 | dev_dbg(port->dev, "%s - leaving\n", __func__); | ||
| 171 | } | ||
| 172 | |||
| 173 | void timbuart_tasklet(unsigned long arg) | ||
| 174 | { | ||
| 175 | struct timbuart_port *uart = (struct timbuart_port *)arg; | ||
| 176 | u8 isr, ier = 0; | ||
| 177 | |||
| 178 | spin_lock(&uart->port.lock); | ||
| 179 | |||
| 180 | isr = ioread8(uart->port.membase + TIMBUART_ISR); | ||
| 181 | dev_dbg(uart->port.dev, "%s ISR: %x\n", __func__, isr); | ||
| 182 | |||
| 183 | if (!uart->usedma) | ||
| 184 | timbuart_handle_tx_port(&uart->port, isr, &ier); | ||
| 185 | |||
| 186 | timbuart_mctrl_check(&uart->port, isr, &ier); | ||
| 187 | |||
| 188 | if (!uart->usedma) | ||
| 189 | timbuart_handle_rx_port(&uart->port, isr, &ier); | ||
| 190 | |||
| 191 | iowrite8(ier, uart->port.membase + TIMBUART_IER); | ||
| 192 | |||
| 193 | spin_unlock(&uart->port.lock); | ||
| 194 | dev_dbg(uart->port.dev, "%s leaving\n", __func__); | ||
| 195 | } | ||
| 196 | |||
| 197 | static unsigned int timbuart_tx_empty(struct uart_port *port) | ||
| 198 | { | ||
| 199 | u8 isr = ioread8(port->membase + TIMBUART_ISR); | ||
| 200 | |||
| 201 | return (isr & TXBAE) ? TIOCSER_TEMT : 0; | ||
| 202 | } | ||
| 203 | |||
| 204 | static unsigned int timbuart_get_mctrl(struct uart_port *port) | ||
| 205 | { | ||
| 206 | u8 cts = ioread8(port->membase + TIMBUART_CTRL); | ||
| 207 | dev_dbg(port->dev, "%s - cts %x\n", __func__, cts); | ||
| 208 | |||
| 209 | if (cts & TIMBUART_CTRL_CTS) | ||
| 210 | return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; | ||
| 211 | else | ||
| 212 | return TIOCM_DSR | TIOCM_CAR; | ||
| 213 | } | ||
| 214 | |||
| 215 | static void timbuart_set_mctrl(struct uart_port *port, unsigned int mctrl) | ||
| 216 | { | ||
| 217 | dev_dbg(port->dev, "%s - %x\n", __func__, mctrl); | ||
| 218 | |||
| 219 | if (mctrl & TIOCM_RTS) | ||
| 220 | iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL); | ||
| 221 | else | ||
| 222 | iowrite8(TIMBUART_CTRL_RTS, port->membase + TIMBUART_CTRL); | ||
| 223 | } | ||
| 224 | |||
| 225 | static void timbuart_mctrl_check(struct uart_port *port, u8 isr, u8 *ier) | ||
| 226 | { | ||
| 227 | unsigned int cts; | ||
| 228 | |||
| 229 | if (isr & CTS_DELTA) { | ||
| 230 | /* ack */ | ||
| 231 | iowrite8(CTS_DELTA, port->membase + TIMBUART_ISR); | ||
| 232 | cts = timbuart_get_mctrl(port); | ||
| 233 | uart_handle_cts_change(port, cts & TIOCM_CTS); | ||
| 234 | wake_up_interruptible(&port->info->delta_msr_wait); | ||
| 235 | } | ||
| 236 | |||
| 237 | *ier |= CTS_DELTA; | ||
| 238 | } | ||
| 239 | |||
| 240 | static void timbuart_enable_ms(struct uart_port *port) | ||
| 241 | { | ||
| 242 | /* N/A */ | ||
| 243 | } | ||
| 244 | |||
| 245 | static void timbuart_break_ctl(struct uart_port *port, int ctl) | ||
| 246 | { | ||
| 247 | /* N/A */ | ||
| 248 | } | ||
| 249 | |||
| 250 | static int timbuart_startup(struct uart_port *port) | ||
| 251 | { | ||
| 252 | struct timbuart_port *uart = | ||
| 253 | container_of(port, struct timbuart_port, port); | ||
| 254 | |||
| 255 | dev_dbg(port->dev, "%s\n", __func__); | ||
| 256 | |||
| 257 | iowrite8(TIMBUART_CTRL_FLSHRX, port->membase + TIMBUART_CTRL); | ||
| 258 | iowrite8(0xff, port->membase + TIMBUART_ISR); | ||
| 259 | /* Enable all but TX interrupts */ | ||
| 260 | iowrite8(RXBAF | RXBF | RXTT | CTS_DELTA, | ||
| 261 | port->membase + TIMBUART_IER); | ||
| 262 | |||
| 263 | return request_irq(port->irq, timbuart_handleinterrupt, IRQF_SHARED, | ||
| 264 | "timb-uart", uart); | ||
| 265 | } | ||
| 266 | |||
| 267 | static void timbuart_shutdown(struct uart_port *port) | ||
| 268 | { | ||
| 269 | struct timbuart_port *uart = | ||
| 270 | container_of(port, struct timbuart_port, port); | ||
| 271 | dev_dbg(port->dev, "%s\n", __func__); | ||
| 272 | free_irq(port->irq, uart); | ||
| 273 | iowrite8(0, port->membase + TIMBUART_IER); | ||
| 274 | } | ||
| 275 | |||
| 276 | static int get_bindex(int baud) | ||
| 277 | { | ||
| 278 | int i; | ||
| 279 | |||
| 280 | for (i = 0; i < ARRAY_SIZE(baudrates); i++) | ||
| 281 | if (baud <= baudrates[i]) | ||
| 282 | return i; | ||
| 283 | |||
| 284 | return -1; | ||
| 285 | } | ||
| 286 | |||
| 287 | static void timbuart_set_termios(struct uart_port *port, | ||
| 288 | struct ktermios *termios, | ||
| 289 | struct ktermios *old) | ||
| 290 | { | ||
| 291 | unsigned int baud; | ||
| 292 | short bindex; | ||
| 293 | unsigned long flags; | ||
| 294 | |||
| 295 | baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk / 16); | ||
| 296 | bindex = get_bindex(baud); | ||
| 297 | dev_dbg(port->dev, "%s - bindex %d\n", __func__, bindex); | ||
| 298 | |||
| 299 | if (bindex < 0) | ||
| 300 | bindex = 0; | ||
| 301 | baud = baudrates[bindex]; | ||
| 302 | |||
| 303 | /* The serial layer calls into this once with old = NULL when setting | ||
| 304 | up initially */ | ||
| 305 | if (old) | ||
| 306 | tty_termios_copy_hw(termios, old); | ||
| 307 | tty_termios_encode_baud_rate(termios, baud, baud); | ||
| 308 | |||
| 309 | spin_lock_irqsave(&port->lock, flags); | ||
| 310 | iowrite8((u8)bindex, port->membase + TIMBUART_BAUDRATE); | ||
| 311 | uart_update_timeout(port, termios->c_cflag, baud); | ||
| 312 | spin_unlock_irqrestore(&port->lock, flags); | ||
| 313 | } | ||
| 314 | |||
| 315 | static const char *timbuart_type(struct uart_port *port) | ||
| 316 | { | ||
| 317 | return port->type == PORT_UNKNOWN ? "timbuart" : NULL; | ||
| 318 | } | ||
| 319 | |||
| 320 | /* We do not request/release mappings of the registers here, | ||
| 321 | * currently it's done in the proble function. | ||
| 322 | */ | ||
| 323 | static void timbuart_release_port(struct uart_port *port) | ||
| 324 | { | ||
| 325 | struct platform_device *pdev = to_platform_device(port->dev); | ||
| 326 | int size = | ||
| 327 | resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); | ||
| 328 | |||
| 329 | if (port->flags & UPF_IOREMAP) { | ||
| 330 | iounmap(port->membase); | ||
| 331 | port->membase = NULL; | ||
| 332 | } | ||
| 333 | |||
| 334 | release_mem_region(port->mapbase, size); | ||
| 335 | } | ||
| 336 | |||
| 337 | static int timbuart_request_port(struct uart_port *port) | ||
| 338 | { | ||
| 339 | struct platform_device *pdev = to_platform_device(port->dev); | ||
| 340 | int size = | ||
| 341 | resource_size(platform_get_resource(pdev, IORESOURCE_MEM, 0)); | ||
| 342 | |||
| 343 | if (!request_mem_region(port->mapbase, size, "timb-uart")) | ||
| 344 | return -EBUSY; | ||
| 345 | |||
| 346 | if (port->flags & UPF_IOREMAP) { | ||
| 347 | port->membase = ioremap(port->mapbase, size); | ||
| 348 | if (port->membase == NULL) { | ||
| 349 | release_mem_region(port->mapbase, size); | ||
| 350 | return -ENOMEM; | ||
| 351 | } | ||
| 352 | } | ||
| 353 | |||
| 354 | return 0; | ||
| 355 | } | ||
| 356 | |||
| 357 | static irqreturn_t timbuart_handleinterrupt(int irq, void *devid) | ||
| 358 | { | ||
| 359 | struct timbuart_port *uart = (struct timbuart_port *)devid; | ||
| 360 | |||
| 361 | if (ioread8(uart->port.membase + TIMBUART_IPR)) { | ||
| 362 | uart->last_ier = ioread8(uart->port.membase + TIMBUART_IER); | ||
| 363 | |||
| 364 | /* disable interrupts, the tasklet enables them again */ | ||
| 365 | iowrite8(0, uart->port.membase + TIMBUART_IER); | ||
| 366 | |||
| 367 | /* fire off bottom half */ | ||
| 368 | tasklet_schedule(&uart->tasklet); | ||
| 369 | |||
| 370 | return IRQ_HANDLED; | ||
| 371 | } else | ||
| 372 | return IRQ_NONE; | ||
| 373 | } | ||
| 374 | |||
| 375 | /* | ||
| 376 | * Configure/autoconfigure the port. | ||
| 377 | */ | ||
| 378 | static void timbuart_config_port(struct uart_port *port, int flags) | ||
| 379 | { | ||
| 380 | if (flags & UART_CONFIG_TYPE) { | ||
| 381 | port->type = PORT_TIMBUART; | ||
| 382 | timbuart_request_port(port); | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | static int timbuart_verify_port(struct uart_port *port, | ||
| 387 | struct serial_struct *ser) | ||
| 388 | { | ||
| 389 | /* we don't want the core code to modify any port params */ | ||
| 390 | return -EINVAL; | ||
| 391 | } | ||
| 392 | |||
| 393 | static struct uart_ops timbuart_ops = { | ||
| 394 | .tx_empty = timbuart_tx_empty, | ||
| 395 | .set_mctrl = timbuart_set_mctrl, | ||
| 396 | .get_mctrl = timbuart_get_mctrl, | ||
| 397 | .stop_tx = timbuart_stop_tx, | ||
| 398 | .start_tx = timbuart_start_tx, | ||
| 399 | .flush_buffer = timbuart_flush_buffer, | ||
| 400 | .stop_rx = timbuart_stop_rx, | ||
| 401 | .enable_ms = timbuart_enable_ms, | ||
| 402 | .break_ctl = timbuart_break_ctl, | ||
| 403 | .startup = timbuart_startup, | ||
| 404 | .shutdown = timbuart_shutdown, | ||
| 405 | .set_termios = timbuart_set_termios, | ||
| 406 | .type = timbuart_type, | ||
| 407 | .release_port = timbuart_release_port, | ||
| 408 | .request_port = timbuart_request_port, | ||
| 409 | .config_port = timbuart_config_port, | ||
| 410 | .verify_port = timbuart_verify_port | ||
| 411 | }; | ||
| 412 | |||
| 413 | static struct uart_driver timbuart_driver = { | ||
| 414 | .owner = THIS_MODULE, | ||
| 415 | .driver_name = "timberdale_uart", | ||
| 416 | .dev_name = "ttyTU", | ||
| 417 | .major = TIMBUART_MAJOR, | ||
| 418 | .minor = TIMBUART_MINOR, | ||
| 419 | .nr = 1 | ||
| 420 | }; | ||
| 421 | |||
| 422 | static int timbuart_probe(struct platform_device *dev) | ||
| 423 | { | ||
| 424 | int err; | ||
| 425 | struct timbuart_port *uart; | ||
| 426 | struct resource *iomem; | ||
| 427 | |||
| 428 | dev_dbg(&dev->dev, "%s\n", __func__); | ||
| 429 | |||
| 430 | uart = kzalloc(sizeof(*uart), GFP_KERNEL); | ||
| 431 | if (!uart) { | ||
| 432 | err = -EINVAL; | ||
| 433 | goto err_mem; | ||
| 434 | } | ||
| 435 | |||
| 436 | uart->usedma = 0; | ||
| 437 | |||
| 438 | uart->port.uartclk = 3250000 * 16; | ||
| 439 | uart->port.fifosize = TIMBUART_FIFO_SIZE; | ||
| 440 | uart->port.regshift = 2; | ||
| 441 | uart->port.iotype = UPIO_MEM; | ||
| 442 | uart->port.ops = &timbuart_ops; | ||
| 443 | uart->port.irq = 0; | ||
| 444 | uart->port.flags = UPF_BOOT_AUTOCONF | UPF_IOREMAP; | ||
| 445 | uart->port.line = 0; | ||
| 446 | uart->port.dev = &dev->dev; | ||
| 447 | |||
| 448 | iomem = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
| 449 | if (!iomem) { | ||
| 450 | err = -ENOMEM; | ||
| 451 | goto err_register; | ||
| 452 | } | ||
| 453 | uart->port.mapbase = iomem->start; | ||
| 454 | uart->port.membase = NULL; | ||
| 455 | |||
| 456 | uart->port.irq = platform_get_irq(dev, 0); | ||
| 457 | if (uart->port.irq < 0) { | ||
| 458 | err = -EINVAL; | ||
| 459 | goto err_register; | ||
| 460 | } | ||
| 461 | |||
| 462 | tasklet_init(&uart->tasklet, timbuart_tasklet, (unsigned long)uart); | ||
| 463 | |||
| 464 | err = uart_register_driver(&timbuart_driver); | ||
| 465 | if (err) | ||
| 466 | goto err_register; | ||
| 467 | |||
| 468 | err = uart_add_one_port(&timbuart_driver, &uart->port); | ||
| 469 | if (err) | ||
| 470 | goto err_add_port; | ||
| 471 | |||
| 472 | platform_set_drvdata(dev, uart); | ||
| 473 | |||
| 474 | return 0; | ||
| 475 | |||
| 476 | err_add_port: | ||
| 477 | uart_unregister_driver(&timbuart_driver); | ||
| 478 | err_register: | ||
| 479 | kfree(uart); | ||
| 480 | err_mem: | ||
| 481 | printk(KERN_ERR "timberdale: Failed to register Timberdale UART: %d\n", | ||
| 482 | err); | ||
| 483 | |||
| 484 | return err; | ||
| 485 | } | ||
| 486 | |||
| 487 | static int timbuart_remove(struct platform_device *dev) | ||
| 488 | { | ||
| 489 | struct timbuart_port *uart = platform_get_drvdata(dev); | ||
| 490 | |||
| 491 | tasklet_kill(&uart->tasklet); | ||
| 492 | uart_remove_one_port(&timbuart_driver, &uart->port); | ||
| 493 | uart_unregister_driver(&timbuart_driver); | ||
| 494 | kfree(uart); | ||
| 495 | |||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | static struct platform_driver timbuart_platform_driver = { | ||
| 500 | .driver = { | ||
| 501 | .name = "timb-uart", | ||
| 502 | .owner = THIS_MODULE, | ||
| 503 | }, | ||
| 504 | .probe = timbuart_probe, | ||
| 505 | .remove = timbuart_remove, | ||
| 506 | }; | ||
| 507 | |||
| 508 | /*--------------------------------------------------------------------------*/ | ||
| 509 | |||
| 510 | static int __init timbuart_init(void) | ||
| 511 | { | ||
| 512 | return platform_driver_register(&timbuart_platform_driver); | ||
| 513 | } | ||
| 514 | |||
| 515 | static void __exit timbuart_exit(void) | ||
| 516 | { | ||
| 517 | platform_driver_unregister(&timbuart_platform_driver); | ||
| 518 | } | ||
| 519 | |||
| 520 | module_init(timbuart_init); | ||
| 521 | module_exit(timbuart_exit); | ||
| 522 | |||
| 523 | MODULE_DESCRIPTION("Timberdale UART driver"); | ||
| 524 | MODULE_LICENSE("GPL v2"); | ||
| 525 | MODULE_ALIAS("platform:timb-uart"); | ||
| 526 | |||
diff --git a/drivers/serial/timbuart.h b/drivers/serial/timbuart.h new file mode 100644 index 000000000000..7e566766bc43 --- /dev/null +++ b/drivers/serial/timbuart.h | |||
| @@ -0,0 +1,58 @@ | |||
| 1 | /* | ||
| 2 | * timbuart.c timberdale FPGA GPIO driver | ||
| 3 | * Copyright (c) 2009 Intel Corporation | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, | ||
| 10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 12 | * GNU General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, write to the Free Software | ||
| 16 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 17 | */ | ||
| 18 | |||
| 19 | /* Supports: | ||
| 20 | * Timberdale FPGA UART | ||
| 21 | */ | ||
| 22 | |||
| 23 | #ifndef _TIMBUART_H | ||
| 24 | #define _TIMBUART_H | ||
| 25 | |||
| 26 | #define TIMBUART_FIFO_SIZE 2048 | ||
| 27 | |||
| 28 | #define TIMBUART_RXFIFO 0x08 | ||
| 29 | #define TIMBUART_TXFIFO 0x0c | ||
| 30 | #define TIMBUART_IER 0x10 | ||
| 31 | #define TIMBUART_IPR 0x14 | ||
| 32 | #define TIMBUART_ISR 0x18 | ||
| 33 | #define TIMBUART_CTRL 0x1c | ||
| 34 | #define TIMBUART_BAUDRATE 0x20 | ||
| 35 | |||
| 36 | #define TIMBUART_CTRL_RTS 0x01 | ||
| 37 | #define TIMBUART_CTRL_CTS 0x02 | ||
| 38 | #define TIMBUART_CTRL_FLSHTX 0x40 | ||
| 39 | #define TIMBUART_CTRL_FLSHRX 0x80 | ||
| 40 | |||
| 41 | #define TXBF 0x01 | ||
| 42 | #define TXBAE 0x02 | ||
| 43 | #define CTS_DELTA 0x04 | ||
| 44 | #define RXDP 0x08 | ||
| 45 | #define RXBAF 0x10 | ||
| 46 | #define RXBF 0x20 | ||
| 47 | #define RXTT 0x40 | ||
| 48 | #define RXBNAE 0x80 | ||
| 49 | #define TXBE 0x100 | ||
| 50 | |||
| 51 | #define RXFLAGS (RXDP | RXBAF | RXBF | RXTT | RXBNAE) | ||
| 52 | #define TXFLAGS (TXBF | TXBAE) | ||
| 53 | |||
| 54 | #define TIMBUART_MAJOR 204 | ||
| 55 | #define TIMBUART_MINOR 192 | ||
| 56 | |||
| 57 | #endif /* _TIMBUART_H */ | ||
| 58 | |||
diff --git a/drivers/sh/intc.c b/drivers/sh/intc.c index 12d13d99b6f0..d687a9b93d03 100644 --- a/drivers/sh/intc.c +++ b/drivers/sh/intc.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/sh_intc.h> | 24 | #include <linux/sh_intc.h> |
| 25 | #include <linux/sysdev.h> | 25 | #include <linux/sysdev.h> |
| 26 | #include <linux/list.h> | 26 | #include <linux/list.h> |
| 27 | #include <linux/topology.h> | ||
| 27 | 28 | ||
| 28 | #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ | 29 | #define _INTC_MK(fn, mode, addr_e, addr_d, width, shift) \ |
| 29 | ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ | 30 | ((shift) | ((width) << 5) | ((fn) << 9) | ((mode) << 13) | \ |
| @@ -770,11 +771,19 @@ void __init register_intc_controller(struct intc_desc *desc) | |||
| 770 | /* register the vectors one by one */ | 771 | /* register the vectors one by one */ |
| 771 | for (i = 0; i < desc->nr_vectors; i++) { | 772 | for (i = 0; i < desc->nr_vectors; i++) { |
| 772 | struct intc_vect *vect = desc->vectors + i; | 773 | struct intc_vect *vect = desc->vectors + i; |
| 774 | unsigned int irq = evt2irq(vect->vect); | ||
| 775 | struct irq_desc *irq_desc; | ||
| 773 | 776 | ||
| 774 | if (!vect->enum_id) | 777 | if (!vect->enum_id) |
| 775 | continue; | 778 | continue; |
| 776 | 779 | ||
| 777 | intc_register_irq(desc, d, vect->enum_id, evt2irq(vect->vect)); | 780 | irq_desc = irq_to_desc_alloc_node(irq, numa_node_id()); |
| 781 | if (unlikely(!irq_desc)) { | ||
| 782 | printk(KERN_INFO "can not get irq_desc for %d\n", irq); | ||
| 783 | continue; | ||
| 784 | } | ||
| 785 | |||
| 786 | intc_register_irq(desc, d, vect->enum_id, irq); | ||
| 778 | } | 787 | } |
| 779 | } | 788 | } |
| 780 | 789 | ||
diff --git a/drivers/ssb/embedded.c b/drivers/ssb/embedded.c index 7dc3a6b41397..a0e0d246b592 100644 --- a/drivers/ssb/embedded.c +++ b/drivers/ssb/embedded.c | |||
| @@ -29,6 +29,7 @@ int ssb_watchdog_timer_set(struct ssb_bus *bus, u32 ticks) | |||
| 29 | } | 29 | } |
| 30 | return -ENODEV; | 30 | return -ENODEV; |
| 31 | } | 31 | } |
| 32 | EXPORT_SYMBOL(ssb_watchdog_timer_set); | ||
| 32 | 33 | ||
| 33 | u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) | 34 | u32 ssb_gpio_in(struct ssb_bus *bus, u32 mask) |
| 34 | { | 35 | { |
diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile index 0716cdb44cd8..0a3dc5ece634 100644 --- a/drivers/usb/Makefile +++ b/drivers/usb/Makefile | |||
| @@ -11,7 +11,6 @@ obj-$(CONFIG_USB_MON) += mon/ | |||
| 11 | obj-$(CONFIG_PCI) += host/ | 11 | obj-$(CONFIG_PCI) += host/ |
| 12 | obj-$(CONFIG_USB_EHCI_HCD) += host/ | 12 | obj-$(CONFIG_USB_EHCI_HCD) += host/ |
| 13 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ | 13 | obj-$(CONFIG_USB_ISP116X_HCD) += host/ |
| 14 | obj-$(CONFIG_USB_ISP1760_HCD) += host/ | ||
| 15 | obj-$(CONFIG_USB_OHCI_HCD) += host/ | 14 | obj-$(CONFIG_USB_OHCI_HCD) += host/ |
| 16 | obj-$(CONFIG_USB_UHCI_HCD) += host/ | 15 | obj-$(CONFIG_USB_UHCI_HCD) += host/ |
| 17 | obj-$(CONFIG_USB_FHCI_HCD) += host/ | 16 | obj-$(CONFIG_USB_FHCI_HCD) += host/ |
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 0a69c0977e3f..ddeb69192537 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c | |||
| @@ -16,7 +16,8 @@ | |||
| 16 | * v0.9 - thorough cleaning, URBification, almost a rewrite | 16 | * v0.9 - thorough cleaning, URBification, almost a rewrite |
| 17 | * v0.10 - some more cleanups | 17 | * v0.10 - some more cleanups |
| 18 | * v0.11 - fixed flow control, read error doesn't stop reads | 18 | * v0.11 - fixed flow control, read error doesn't stop reads |
| 19 | * v0.12 - added TIOCM ioctls, added break handling, made struct acm kmalloced | 19 | * v0.12 - added TIOCM ioctls, added break handling, made struct acm |
| 20 | * kmalloced | ||
| 20 | * v0.13 - added termios, added hangup | 21 | * v0.13 - added termios, added hangup |
| 21 | * v0.14 - sized down struct acm | 22 | * v0.14 - sized down struct acm |
| 22 | * v0.15 - fixed flow control again - characters could be lost | 23 | * v0.15 - fixed flow control again - characters could be lost |
| @@ -62,7 +63,7 @@ | |||
| 62 | #include <linux/tty_flip.h> | 63 | #include <linux/tty_flip.h> |
| 63 | #include <linux/module.h> | 64 | #include <linux/module.h> |
| 64 | #include <linux/mutex.h> | 65 | #include <linux/mutex.h> |
| 65 | #include <asm/uaccess.h> | 66 | #include <linux/uaccess.h> |
| 66 | #include <linux/usb.h> | 67 | #include <linux/usb.h> |
| 67 | #include <linux/usb/cdc.h> | 68 | #include <linux/usb/cdc.h> |
| 68 | #include <asm/byteorder.h> | 69 | #include <asm/byteorder.h> |
| @@ -87,7 +88,10 @@ static struct acm *acm_table[ACM_TTY_MINORS]; | |||
| 87 | 88 | ||
| 88 | static DEFINE_MUTEX(open_mutex); | 89 | static DEFINE_MUTEX(open_mutex); |
| 89 | 90 | ||
| 90 | #define ACM_READY(acm) (acm && acm->dev && acm->used) | 91 | #define ACM_READY(acm) (acm && acm->dev && acm->port.count) |
| 92 | |||
| 93 | static const struct tty_port_operations acm_port_ops = { | ||
| 94 | }; | ||
| 91 | 95 | ||
| 92 | #ifdef VERBOSE_DEBUG | 96 | #ifdef VERBOSE_DEBUG |
| 93 | #define verbose 1 | 97 | #define verbose 1 |
| @@ -99,13 +103,15 @@ static DEFINE_MUTEX(open_mutex); | |||
| 99 | * Functions for ACM control messages. | 103 | * Functions for ACM control messages. |
| 100 | */ | 104 | */ |
| 101 | 105 | ||
| 102 | static int acm_ctrl_msg(struct acm *acm, int request, int value, void *buf, int len) | 106 | static int acm_ctrl_msg(struct acm *acm, int request, int value, |
| 107 | void *buf, int len) | ||
| 103 | { | 108 | { |
| 104 | int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), | 109 | int retval = usb_control_msg(acm->dev, usb_sndctrlpipe(acm->dev, 0), |
| 105 | request, USB_RT_ACM, value, | 110 | request, USB_RT_ACM, value, |
| 106 | acm->control->altsetting[0].desc.bInterfaceNumber, | 111 | acm->control->altsetting[0].desc.bInterfaceNumber, |
| 107 | buf, len, 5000); | 112 | buf, len, 5000); |
| 108 | dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", request, value, len, retval); | 113 | dbg("acm_control_msg: rq: 0x%02x val: %#x len: %#x result: %d", |
| 114 | request, value, len, retval); | ||
| 109 | return retval < 0 ? retval : 0; | 115 | return retval < 0 ? retval : 0; |
| 110 | } | 116 | } |
| 111 | 117 | ||
| @@ -150,9 +156,8 @@ static int acm_wb_is_avail(struct acm *acm) | |||
| 150 | 156 | ||
| 151 | n = ACM_NW; | 157 | n = ACM_NW; |
| 152 | spin_lock_irqsave(&acm->write_lock, flags); | 158 | spin_lock_irqsave(&acm->write_lock, flags); |
| 153 | for (i = 0; i < ACM_NW; i++) { | 159 | for (i = 0; i < ACM_NW; i++) |
| 154 | n -= acm->wb[i].use; | 160 | n -= acm->wb[i].use; |
| 155 | } | ||
| 156 | spin_unlock_irqrestore(&acm->write_lock, flags); | 161 | spin_unlock_irqrestore(&acm->write_lock, flags); |
| 157 | return n; | 162 | return n; |
| 158 | } | 163 | } |
| @@ -183,7 +188,8 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) | |||
| 183 | wb->urb->transfer_buffer_length = wb->len; | 188 | wb->urb->transfer_buffer_length = wb->len; |
| 184 | wb->urb->dev = acm->dev; | 189 | wb->urb->dev = acm->dev; |
| 185 | 190 | ||
| 186 | if ((rc = usb_submit_urb(wb->urb, GFP_ATOMIC)) < 0) { | 191 | rc = usb_submit_urb(wb->urb, GFP_ATOMIC); |
| 192 | if (rc < 0) { | ||
| 187 | dbg("usb_submit_urb(write bulk) failed: %d", rc); | 193 | dbg("usb_submit_urb(write bulk) failed: %d", rc); |
| 188 | acm_write_done(acm, wb); | 194 | acm_write_done(acm, wb); |
| 189 | } | 195 | } |
| @@ -262,6 +268,7 @@ static void acm_ctrl_irq(struct urb *urb) | |||
| 262 | { | 268 | { |
| 263 | struct acm *acm = urb->context; | 269 | struct acm *acm = urb->context; |
| 264 | struct usb_cdc_notification *dr = urb->transfer_buffer; | 270 | struct usb_cdc_notification *dr = urb->transfer_buffer; |
| 271 | struct tty_struct *tty; | ||
| 265 | unsigned char *data; | 272 | unsigned char *data; |
| 266 | int newctrl; | 273 | int newctrl; |
| 267 | int retval; | 274 | int retval; |
| @@ -287,40 +294,45 @@ static void acm_ctrl_irq(struct urb *urb) | |||
| 287 | 294 | ||
| 288 | data = (unsigned char *)(dr + 1); | 295 | data = (unsigned char *)(dr + 1); |
| 289 | switch (dr->bNotificationType) { | 296 | switch (dr->bNotificationType) { |
| 297 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | ||
| 298 | dbg("%s network", dr->wValue ? | ||
| 299 | "connected to" : "disconnected from"); | ||
| 300 | break; | ||
| 290 | 301 | ||
| 291 | case USB_CDC_NOTIFY_NETWORK_CONNECTION: | 302 | case USB_CDC_NOTIFY_SERIAL_STATE: |
| 292 | 303 | tty = tty_port_tty_get(&acm->port); | |
| 293 | dbg("%s network", dr->wValue ? "connected to" : "disconnected from"); | 304 | newctrl = get_unaligned_le16(data); |
| 294 | break; | ||
| 295 | |||
| 296 | case USB_CDC_NOTIFY_SERIAL_STATE: | ||
| 297 | |||
| 298 | newctrl = get_unaligned_le16(data); | ||
| 299 | 305 | ||
| 300 | if (acm->tty && !acm->clocal && (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { | 306 | if (tty) { |
| 307 | if (!acm->clocal && | ||
| 308 | (acm->ctrlin & ~newctrl & ACM_CTRL_DCD)) { | ||
| 301 | dbg("calling hangup"); | 309 | dbg("calling hangup"); |
| 302 | tty_hangup(acm->tty); | 310 | tty_hangup(tty); |
| 303 | } | 311 | } |
| 312 | tty_kref_put(tty); | ||
| 313 | } | ||
| 304 | 314 | ||
| 305 | acm->ctrlin = newctrl; | 315 | acm->ctrlin = newctrl; |
| 306 | |||
| 307 | dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c", | ||
| 308 | acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', | ||
| 309 | acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', acm->ctrlin & ACM_CTRL_RI ? '+' : '-', | ||
| 310 | acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', | ||
| 311 | acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); | ||
| 312 | 316 | ||
| 317 | dbg("input control lines: dcd%c dsr%c break%c ring%c framing%c parity%c overrun%c", | ||
| 318 | acm->ctrlin & ACM_CTRL_DCD ? '+' : '-', | ||
| 319 | acm->ctrlin & ACM_CTRL_DSR ? '+' : '-', | ||
| 320 | acm->ctrlin & ACM_CTRL_BRK ? '+' : '-', | ||
| 321 | acm->ctrlin & ACM_CTRL_RI ? '+' : '-', | ||
| 322 | acm->ctrlin & ACM_CTRL_FRAMING ? '+' : '-', | ||
| 323 | acm->ctrlin & ACM_CTRL_PARITY ? '+' : '-', | ||
| 324 | acm->ctrlin & ACM_CTRL_OVERRUN ? '+' : '-'); | ||
| 313 | break; | 325 | break; |
| 314 | 326 | ||
| 315 | default: | 327 | default: |
| 316 | dbg("unknown notification %d received: index %d len %d data0 %d data1 %d", | 328 | dbg("unknown notification %d received: index %d len %d data0 %d data1 %d", |
| 317 | dr->bNotificationType, dr->wIndex, | 329 | dr->bNotificationType, dr->wIndex, |
| 318 | dr->wLength, data[0], data[1]); | 330 | dr->wLength, data[0], data[1]); |
| 319 | break; | 331 | break; |
| 320 | } | 332 | } |
| 321 | exit: | 333 | exit: |
| 322 | usb_mark_last_busy(acm->dev); | 334 | usb_mark_last_busy(acm->dev); |
| 323 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 335 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
| 324 | if (retval) | 336 | if (retval) |
| 325 | dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " | 337 | dev_err(&urb->dev->dev, "%s - usb_submit_urb failed with " |
| 326 | "result %d", __func__, retval); | 338 | "result %d", __func__, retval); |
| @@ -371,15 +383,14 @@ static void acm_rx_tasklet(unsigned long _acm) | |||
| 371 | { | 383 | { |
| 372 | struct acm *acm = (void *)_acm; | 384 | struct acm *acm = (void *)_acm; |
| 373 | struct acm_rb *buf; | 385 | struct acm_rb *buf; |
| 374 | struct tty_struct *tty = acm->tty; | 386 | struct tty_struct *tty; |
| 375 | struct acm_ru *rcv; | 387 | struct acm_ru *rcv; |
| 376 | unsigned long flags; | 388 | unsigned long flags; |
| 377 | unsigned char throttled; | 389 | unsigned char throttled; |
| 378 | 390 | ||
| 379 | dbg("Entering acm_rx_tasklet"); | 391 | dbg("Entering acm_rx_tasklet"); |
| 380 | 392 | ||
| 381 | if (!ACM_READY(acm)) | 393 | if (!ACM_READY(acm)) { |
| 382 | { | ||
| 383 | dbg("acm_rx_tasklet: ACM not ready"); | 394 | dbg("acm_rx_tasklet: ACM not ready"); |
| 384 | return; | 395 | return; |
| 385 | } | 396 | } |
| @@ -387,12 +398,13 @@ static void acm_rx_tasklet(unsigned long _acm) | |||
| 387 | spin_lock_irqsave(&acm->throttle_lock, flags); | 398 | spin_lock_irqsave(&acm->throttle_lock, flags); |
| 388 | throttled = acm->throttle; | 399 | throttled = acm->throttle; |
| 389 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | 400 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
| 390 | if (throttled) | 401 | if (throttled) { |
| 391 | { | ||
| 392 | dbg("acm_rx_tasklet: throttled"); | 402 | dbg("acm_rx_tasklet: throttled"); |
| 393 | return; | 403 | return; |
| 394 | } | 404 | } |
| 395 | 405 | ||
| 406 | tty = tty_port_tty_get(&acm->port); | ||
| 407 | |||
| 396 | next_buffer: | 408 | next_buffer: |
| 397 | spin_lock_irqsave(&acm->read_lock, flags); | 409 | spin_lock_irqsave(&acm->read_lock, flags); |
| 398 | if (list_empty(&acm->filled_read_bufs)) { | 410 | if (list_empty(&acm->filled_read_bufs)) { |
| @@ -406,20 +418,22 @@ next_buffer: | |||
| 406 | 418 | ||
| 407 | dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); | 419 | dbg("acm_rx_tasklet: procesing buf 0x%p, size = %d", buf, buf->size); |
| 408 | 420 | ||
| 409 | tty_buffer_request_room(tty, buf->size); | 421 | if (tty) { |
| 410 | spin_lock_irqsave(&acm->throttle_lock, flags); | 422 | spin_lock_irqsave(&acm->throttle_lock, flags); |
| 411 | throttled = acm->throttle; | 423 | throttled = acm->throttle; |
| 412 | spin_unlock_irqrestore(&acm->throttle_lock, flags); | 424 | spin_unlock_irqrestore(&acm->throttle_lock, flags); |
| 413 | if (!throttled) | 425 | if (!throttled) { |
| 414 | tty_insert_flip_string(tty, buf->base, buf->size); | 426 | tty_buffer_request_room(tty, buf->size); |
| 415 | tty_flip_buffer_push(tty); | 427 | tty_insert_flip_string(tty, buf->base, buf->size); |
| 416 | 428 | tty_flip_buffer_push(tty); | |
| 417 | if (throttled) { | 429 | } else { |
| 418 | dbg("Throttling noticed"); | 430 | tty_kref_put(tty); |
| 419 | spin_lock_irqsave(&acm->read_lock, flags); | 431 | dbg("Throttling noticed"); |
| 420 | list_add(&buf->list, &acm->filled_read_bufs); | 432 | spin_lock_irqsave(&acm->read_lock, flags); |
| 421 | spin_unlock_irqrestore(&acm->read_lock, flags); | 433 | list_add(&buf->list, &acm->filled_read_bufs); |
| 422 | return; | 434 | spin_unlock_irqrestore(&acm->read_lock, flags); |
| 435 | return; | ||
| 436 | } | ||
| 423 | } | 437 | } |
| 424 | 438 | ||
| 425 | spin_lock_irqsave(&acm->read_lock, flags); | 439 | spin_lock_irqsave(&acm->read_lock, flags); |
| @@ -428,6 +442,8 @@ next_buffer: | |||
| 428 | goto next_buffer; | 442 | goto next_buffer; |
| 429 | 443 | ||
| 430 | urbs: | 444 | urbs: |
| 445 | tty_kref_put(tty); | ||
| 446 | |||
| 431 | while (!list_empty(&acm->spare_read_bufs)) { | 447 | while (!list_empty(&acm->spare_read_bufs)) { |
| 432 | spin_lock_irqsave(&acm->read_lock, flags); | 448 | spin_lock_irqsave(&acm->read_lock, flags); |
| 433 | if (list_empty(&acm->spare_read_urbs)) { | 449 | if (list_empty(&acm->spare_read_urbs)) { |
| @@ -454,10 +470,11 @@ urbs: | |||
| 454 | rcv->urb->transfer_dma = buf->dma; | 470 | rcv->urb->transfer_dma = buf->dma; |
| 455 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 471 | rcv->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 456 | 472 | ||
| 457 | /* This shouldn't kill the driver as unsuccessful URBs are returned to the | 473 | /* This shouldn't kill the driver as unsuccessful URBs are |
| 458 | free-urbs-pool and resubmited ASAP */ | 474 | returned to the free-urbs-pool and resubmited ASAP */ |
| 459 | spin_lock_irqsave(&acm->read_lock, flags); | 475 | spin_lock_irqsave(&acm->read_lock, flags); |
| 460 | if (acm->susp_count || usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { | 476 | if (acm->susp_count || |
| 477 | usb_submit_urb(rcv->urb, GFP_ATOMIC) < 0) { | ||
| 461 | list_add(&buf->list, &acm->spare_read_bufs); | 478 | list_add(&buf->list, &acm->spare_read_bufs); |
| 462 | list_add(&rcv->list, &acm->spare_read_urbs); | 479 | list_add(&rcv->list, &acm->spare_read_urbs); |
| 463 | acm->processing = 0; | 480 | acm->processing = 0; |
| @@ -499,11 +516,14 @@ static void acm_write_bulk(struct urb *urb) | |||
| 499 | static void acm_softint(struct work_struct *work) | 516 | static void acm_softint(struct work_struct *work) |
| 500 | { | 517 | { |
| 501 | struct acm *acm = container_of(work, struct acm, work); | 518 | struct acm *acm = container_of(work, struct acm, work); |
| 519 | struct tty_struct *tty; | ||
| 502 | 520 | ||
| 503 | dev_vdbg(&acm->data->dev, "tx work\n"); | 521 | dev_vdbg(&acm->data->dev, "tx work\n"); |
| 504 | if (!ACM_READY(acm)) | 522 | if (!ACM_READY(acm)) |
| 505 | return; | 523 | return; |
| 506 | tty_wakeup(acm->tty); | 524 | tty = tty_port_tty_get(&acm->port); |
| 525 | tty_wakeup(tty); | ||
| 526 | tty_kref_put(tty); | ||
| 507 | } | 527 | } |
| 508 | 528 | ||
| 509 | static void acm_waker(struct work_struct *waker) | 529 | static void acm_waker(struct work_struct *waker) |
| @@ -543,8 +563,9 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
| 543 | rv = 0; | 563 | rv = 0; |
| 544 | 564 | ||
| 545 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); | 565 | set_bit(TTY_NO_WRITE_SPLIT, &tty->flags); |
| 566 | |||
| 546 | tty->driver_data = acm; | 567 | tty->driver_data = acm; |
| 547 | acm->tty = tty; | 568 | tty_port_tty_set(&acm->port, tty); |
| 548 | 569 | ||
| 549 | if (usb_autopm_get_interface(acm->control) < 0) | 570 | if (usb_autopm_get_interface(acm->control) < 0) |
| 550 | goto early_bail; | 571 | goto early_bail; |
| @@ -552,11 +573,10 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
| 552 | acm->control->needs_remote_wakeup = 1; | 573 | acm->control->needs_remote_wakeup = 1; |
| 553 | 574 | ||
| 554 | mutex_lock(&acm->mutex); | 575 | mutex_lock(&acm->mutex); |
| 555 | if (acm->used++) { | 576 | if (acm->port.count++) { |
| 556 | usb_autopm_put_interface(acm->control); | 577 | usb_autopm_put_interface(acm->control); |
| 557 | goto done; | 578 | goto done; |
| 558 | } | 579 | } |
| 559 | |||
| 560 | 580 | ||
| 561 | acm->ctrlurb->dev = acm->dev; | 581 | acm->ctrlurb->dev = acm->dev; |
| 562 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { | 582 | if (usb_submit_urb(acm->ctrlurb, GFP_KERNEL)) { |
| @@ -567,22 +587,22 @@ static int acm_tty_open(struct tty_struct *tty, struct file *filp) | |||
| 567 | if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && | 587 | if (0 > acm_set_control(acm, acm->ctrlout = ACM_CTRL_DTR | ACM_CTRL_RTS) && |
| 568 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) | 588 | (acm->ctrl_caps & USB_CDC_CAP_LINE)) |
| 569 | goto full_bailout; | 589 | goto full_bailout; |
| 590 | |||
| 570 | usb_autopm_put_interface(acm->control); | 591 | usb_autopm_put_interface(acm->control); |
| 571 | 592 | ||
| 572 | INIT_LIST_HEAD(&acm->spare_read_urbs); | 593 | INIT_LIST_HEAD(&acm->spare_read_urbs); |
| 573 | INIT_LIST_HEAD(&acm->spare_read_bufs); | 594 | INIT_LIST_HEAD(&acm->spare_read_bufs); |
| 574 | INIT_LIST_HEAD(&acm->filled_read_bufs); | 595 | INIT_LIST_HEAD(&acm->filled_read_bufs); |
| 575 | for (i = 0; i < acm->rx_buflimit; i++) { | 596 | |
| 597 | for (i = 0; i < acm->rx_buflimit; i++) | ||
| 576 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); | 598 | list_add(&(acm->ru[i].list), &acm->spare_read_urbs); |
| 577 | } | 599 | for (i = 0; i < acm->rx_buflimit; i++) |
| 578 | for (i = 0; i < acm->rx_buflimit; i++) { | ||
| 579 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); | 600 | list_add(&(acm->rb[i].list), &acm->spare_read_bufs); |
| 580 | } | ||
| 581 | 601 | ||
| 582 | acm->throttle = 0; | 602 | acm->throttle = 0; |
| 583 | 603 | ||
| 584 | tasklet_schedule(&acm->urb_task); | 604 | tasklet_schedule(&acm->urb_task); |
| 585 | 605 | rv = tty_port_block_til_ready(&acm->port, tty, filp); | |
| 586 | done: | 606 | done: |
| 587 | mutex_unlock(&acm->mutex); | 607 | mutex_unlock(&acm->mutex); |
| 588 | err_out: | 608 | err_out: |
| @@ -593,16 +613,17 @@ full_bailout: | |||
| 593 | usb_kill_urb(acm->ctrlurb); | 613 | usb_kill_urb(acm->ctrlurb); |
| 594 | bail_out: | 614 | bail_out: |
| 595 | usb_autopm_put_interface(acm->control); | 615 | usb_autopm_put_interface(acm->control); |
| 596 | acm->used--; | 616 | acm->port.count--; |
| 597 | mutex_unlock(&acm->mutex); | 617 | mutex_unlock(&acm->mutex); |
| 598 | early_bail: | 618 | early_bail: |
| 599 | mutex_unlock(&open_mutex); | 619 | mutex_unlock(&open_mutex); |
| 620 | tty_port_tty_set(&acm->port, NULL); | ||
| 600 | return -EIO; | 621 | return -EIO; |
| 601 | } | 622 | } |
| 602 | 623 | ||
| 603 | static void acm_tty_unregister(struct acm *acm) | 624 | static void acm_tty_unregister(struct acm *acm) |
| 604 | { | 625 | { |
| 605 | int i,nr; | 626 | int i, nr; |
| 606 | 627 | ||
| 607 | nr = acm->rx_buflimit; | 628 | nr = acm->rx_buflimit; |
| 608 | tty_unregister_device(acm_tty_driver, acm->minor); | 629 | tty_unregister_device(acm_tty_driver, acm->minor); |
| @@ -619,41 +640,56 @@ static void acm_tty_unregister(struct acm *acm) | |||
| 619 | 640 | ||
| 620 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); | 641 | static int acm_tty_chars_in_buffer(struct tty_struct *tty); |
| 621 | 642 | ||
| 643 | static void acm_port_down(struct acm *acm, int drain) | ||
| 644 | { | ||
| 645 | int i, nr = acm->rx_buflimit; | ||
| 646 | mutex_lock(&open_mutex); | ||
| 647 | if (acm->dev) { | ||
| 648 | usb_autopm_get_interface(acm->control); | ||
| 649 | acm_set_control(acm, acm->ctrlout = 0); | ||
| 650 | /* try letting the last writes drain naturally */ | ||
| 651 | if (drain) { | ||
| 652 | wait_event_interruptible_timeout(acm->drain_wait, | ||
| 653 | (ACM_NW == acm_wb_is_avail(acm)) || !acm->dev, | ||
| 654 | ACM_CLOSE_TIMEOUT * HZ); | ||
| 655 | } | ||
| 656 | usb_kill_urb(acm->ctrlurb); | ||
| 657 | for (i = 0; i < ACM_NW; i++) | ||
| 658 | usb_kill_urb(acm->wb[i].urb); | ||
| 659 | for (i = 0; i < nr; i++) | ||
| 660 | usb_kill_urb(acm->ru[i].urb); | ||
| 661 | acm->control->needs_remote_wakeup = 0; | ||
| 662 | usb_autopm_put_interface(acm->control); | ||
| 663 | } | ||
| 664 | mutex_unlock(&open_mutex); | ||
| 665 | } | ||
| 666 | |||
| 667 | static void acm_tty_hangup(struct tty_struct *tty) | ||
| 668 | { | ||
| 669 | struct acm *acm = tty->driver_data; | ||
| 670 | tty_port_hangup(&acm->port); | ||
| 671 | acm_port_down(acm, 0); | ||
| 672 | } | ||
| 673 | |||
| 622 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) | 674 | static void acm_tty_close(struct tty_struct *tty, struct file *filp) |
| 623 | { | 675 | { |
| 624 | struct acm *acm = tty->driver_data; | 676 | struct acm *acm = tty->driver_data; |
| 625 | int i,nr; | ||
| 626 | 677 | ||
| 627 | if (!acm || !acm->used) | 678 | /* Perform the closing process and see if we need to do the hardware |
| 679 | shutdown */ | ||
| 680 | if (tty_port_close_start(&acm->port, tty, filp) == 0) | ||
| 628 | return; | 681 | return; |
| 629 | 682 | acm_port_down(acm, 0); | |
| 630 | nr = acm->rx_buflimit; | 683 | tty_port_close_end(&acm->port, tty); |
| 631 | mutex_lock(&open_mutex); | 684 | mutex_lock(&open_mutex); |
| 632 | if (!--acm->used) { | 685 | tty_port_tty_set(&acm->port, NULL); |
| 633 | if (acm->dev) { | 686 | if (!acm->dev) |
| 634 | usb_autopm_get_interface(acm->control); | 687 | acm_tty_unregister(acm); |
| 635 | acm_set_control(acm, acm->ctrlout = 0); | ||
| 636 | |||
| 637 | /* try letting the last writes drain naturally */ | ||
| 638 | wait_event_interruptible_timeout(acm->drain_wait, | ||
| 639 | (ACM_NW == acm_wb_is_avail(acm)) | ||
| 640 | || !acm->dev, | ||
| 641 | ACM_CLOSE_TIMEOUT * HZ); | ||
| 642 | |||
| 643 | usb_kill_urb(acm->ctrlurb); | ||
| 644 | for (i = 0; i < ACM_NW; i++) | ||
| 645 | usb_kill_urb(acm->wb[i].urb); | ||
| 646 | for (i = 0; i < nr; i++) | ||
| 647 | usb_kill_urb(acm->ru[i].urb); | ||
| 648 | acm->control->needs_remote_wakeup = 0; | ||
| 649 | usb_autopm_put_interface(acm->control); | ||
| 650 | } else | ||
| 651 | acm_tty_unregister(acm); | ||
| 652 | } | ||
| 653 | mutex_unlock(&open_mutex); | 688 | mutex_unlock(&open_mutex); |
| 654 | } | 689 | } |
| 655 | 690 | ||
| 656 | static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int count) | 691 | static int acm_tty_write(struct tty_struct *tty, |
| 692 | const unsigned char *buf, int count) | ||
| 657 | { | 693 | { |
| 658 | struct acm *acm = tty->driver_data; | 694 | struct acm *acm = tty->driver_data; |
| 659 | int stat; | 695 | int stat; |
| @@ -669,7 +705,8 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c | |||
| 669 | return 0; | 705 | return 0; |
| 670 | 706 | ||
| 671 | spin_lock_irqsave(&acm->write_lock, flags); | 707 | spin_lock_irqsave(&acm->write_lock, flags); |
| 672 | if ((wbn = acm_wb_alloc(acm)) < 0) { | 708 | wbn = acm_wb_alloc(acm); |
| 709 | if (wbn < 0) { | ||
| 673 | spin_unlock_irqrestore(&acm->write_lock, flags); | 710 | spin_unlock_irqrestore(&acm->write_lock, flags); |
| 674 | return 0; | 711 | return 0; |
| 675 | } | 712 | } |
| @@ -681,7 +718,8 @@ static int acm_tty_write(struct tty_struct *tty, const unsigned char *buf, int c | |||
| 681 | wb->len = count; | 718 | wb->len = count; |
| 682 | spin_unlock_irqrestore(&acm->write_lock, flags); | 719 | spin_unlock_irqrestore(&acm->write_lock, flags); |
| 683 | 720 | ||
| 684 | if ((stat = acm_write_start(acm, wbn)) < 0) | 721 | stat = acm_write_start(acm, wbn); |
| 722 | if (stat < 0) | ||
| 685 | return stat; | 723 | return stat; |
| 686 | return count; | 724 | return count; |
| 687 | } | 725 | } |
| @@ -767,8 +805,10 @@ static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 767 | return -EINVAL; | 805 | return -EINVAL; |
| 768 | 806 | ||
| 769 | newctrl = acm->ctrlout; | 807 | newctrl = acm->ctrlout; |
| 770 | set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); | 808 | set = (set & TIOCM_DTR ? ACM_CTRL_DTR : 0) | |
| 771 | clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0); | 809 | (set & TIOCM_RTS ? ACM_CTRL_RTS : 0); |
| 810 | clear = (clear & TIOCM_DTR ? ACM_CTRL_DTR : 0) | | ||
| 811 | (clear & TIOCM_RTS ? ACM_CTRL_RTS : 0); | ||
| 772 | 812 | ||
| 773 | newctrl = (newctrl & ~clear) | set; | 813 | newctrl = (newctrl & ~clear) | set; |
| 774 | 814 | ||
| @@ -777,7 +817,8 @@ static int acm_tty_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 777 | return acm_set_control(acm, acm->ctrlout = newctrl); | 817 | return acm_set_control(acm, acm->ctrlout = newctrl); |
| 778 | } | 818 | } |
| 779 | 819 | ||
| 780 | static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg) | 820 | static int acm_tty_ioctl(struct tty_struct *tty, struct file *file, |
| 821 | unsigned int cmd, unsigned long arg) | ||
| 781 | { | 822 | { |
| 782 | struct acm *acm = tty->driver_data; | 823 | struct acm *acm = tty->driver_data; |
| 783 | 824 | ||
| @@ -799,7 +840,8 @@ static const __u8 acm_tty_size[] = { | |||
| 799 | 5, 6, 7, 8 | 840 | 5, 6, 7, 8 |
| 800 | }; | 841 | }; |
| 801 | 842 | ||
| 802 | static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios_old) | 843 | static void acm_tty_set_termios(struct tty_struct *tty, |
| 844 | struct ktermios *termios_old) | ||
| 803 | { | 845 | { |
| 804 | struct acm *acm = tty->driver_data; | 846 | struct acm *acm = tty->driver_data; |
| 805 | struct ktermios *termios = tty->termios; | 847 | struct ktermios *termios = tty->termios; |
| @@ -809,19 +851,23 @@ static void acm_tty_set_termios(struct tty_struct *tty, struct ktermios *termios | |||
| 809 | if (!ACM_READY(acm)) | 851 | if (!ACM_READY(acm)) |
| 810 | return; | 852 | return; |
| 811 | 853 | ||
| 854 | /* FIXME: Needs to support the tty_baud interface */ | ||
| 855 | /* FIXME: Broken on sparc */ | ||
| 812 | newline.dwDTERate = cpu_to_le32p(acm_tty_speed + | 856 | newline.dwDTERate = cpu_to_le32p(acm_tty_speed + |
| 813 | (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0)); | 857 | (termios->c_cflag & CBAUD & ~CBAUDEX) + (termios->c_cflag & CBAUDEX ? 15 : 0)); |
| 814 | newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; | 858 | newline.bCharFormat = termios->c_cflag & CSTOPB ? 2 : 0; |
| 815 | newline.bParityType = termios->c_cflag & PARENB ? | 859 | newline.bParityType = termios->c_cflag & PARENB ? |
| 816 | (termios->c_cflag & PARODD ? 1 : 2) + (termios->c_cflag & CMSPAR ? 2 : 0) : 0; | 860 | (termios->c_cflag & PARODD ? 1 : 2) + |
| 861 | (termios->c_cflag & CMSPAR ? 2 : 0) : 0; | ||
| 817 | newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; | 862 | newline.bDataBits = acm_tty_size[(termios->c_cflag & CSIZE) >> 4]; |
| 818 | 863 | /* FIXME: Needs to clear unsupported bits in the termios */ | |
| 819 | acm->clocal = ((termios->c_cflag & CLOCAL) != 0); | 864 | acm->clocal = ((termios->c_cflag & CLOCAL) != 0); |
| 820 | 865 | ||
| 821 | if (!newline.dwDTERate) { | 866 | if (!newline.dwDTERate) { |
| 822 | newline.dwDTERate = acm->line.dwDTERate; | 867 | newline.dwDTERate = acm->line.dwDTERate; |
| 823 | newctrl &= ~ACM_CTRL_DTR; | 868 | newctrl &= ~ACM_CTRL_DTR; |
| 824 | } else newctrl |= ACM_CTRL_DTR; | 869 | } else |
| 870 | newctrl |= ACM_CTRL_DTR; | ||
| 825 | 871 | ||
| 826 | if (newctrl != acm->ctrlout) | 872 | if (newctrl != acm->ctrlout) |
| 827 | acm_set_control(acm, acm->ctrlout = newctrl); | 873 | acm_set_control(acm, acm->ctrlout = newctrl); |
| @@ -846,9 +892,8 @@ static void acm_write_buffers_free(struct acm *acm) | |||
| 846 | struct acm_wb *wb; | 892 | struct acm_wb *wb; |
| 847 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); | 893 | struct usb_device *usb_dev = interface_to_usbdev(acm->control); |
| 848 | 894 | ||
| 849 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) { | 895 | for (wb = &acm->wb[0], i = 0; i < ACM_NW; i++, wb++) |
| 850 | usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah); | 896 | usb_buffer_free(usb_dev, acm->writesize, wb->buf, wb->dmah); |
| 851 | } | ||
| 852 | } | 897 | } |
| 853 | 898 | ||
| 854 | static void acm_read_buffers_free(struct acm *acm) | 899 | static void acm_read_buffers_free(struct acm *acm) |
| @@ -857,7 +902,8 @@ static void acm_read_buffers_free(struct acm *acm) | |||
| 857 | int i, n = acm->rx_buflimit; | 902 | int i, n = acm->rx_buflimit; |
| 858 | 903 | ||
| 859 | for (i = 0; i < n; i++) | 904 | for (i = 0; i < n; i++) |
| 860 | usb_buffer_free(usb_dev, acm->readsize, acm->rb[i].base, acm->rb[i].dma); | 905 | usb_buffer_free(usb_dev, acm->readsize, |
| 906 | acm->rb[i].base, acm->rb[i].dma); | ||
| 861 | } | 907 | } |
| 862 | 908 | ||
| 863 | /* Little helper: write buffers allocate */ | 909 | /* Little helper: write buffers allocate */ |
| @@ -882,8 +928,8 @@ static int acm_write_buffers_alloc(struct acm *acm) | |||
| 882 | return 0; | 928 | return 0; |
| 883 | } | 929 | } |
| 884 | 930 | ||
| 885 | static int acm_probe (struct usb_interface *intf, | 931 | static int acm_probe(struct usb_interface *intf, |
| 886 | const struct usb_device_id *id) | 932 | const struct usb_device_id *id) |
| 887 | { | 933 | { |
| 888 | struct usb_cdc_union_desc *union_header = NULL; | 934 | struct usb_cdc_union_desc *union_header = NULL; |
| 889 | struct usb_cdc_country_functional_desc *cfd = NULL; | 935 | struct usb_cdc_country_functional_desc *cfd = NULL; |
| @@ -897,7 +943,7 @@ static int acm_probe (struct usb_interface *intf, | |||
| 897 | struct usb_device *usb_dev = interface_to_usbdev(intf); | 943 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
| 898 | struct acm *acm; | 944 | struct acm *acm; |
| 899 | int minor; | 945 | int minor; |
| 900 | int ctrlsize,readsize; | 946 | int ctrlsize, readsize; |
| 901 | u8 *buf; | 947 | u8 *buf; |
| 902 | u8 ac_management_function = 0; | 948 | u8 ac_management_function = 0; |
| 903 | u8 call_management_function = 0; | 949 | u8 call_management_function = 0; |
| @@ -917,7 +963,7 @@ static int acm_probe (struct usb_interface *intf, | |||
| 917 | control_interface = usb_ifnum_to_if(usb_dev, 0); | 963 | control_interface = usb_ifnum_to_if(usb_dev, 0); |
| 918 | goto skip_normal_probe; | 964 | goto skip_normal_probe; |
| 919 | } | 965 | } |
| 920 | 966 | ||
| 921 | /* normal probing*/ | 967 | /* normal probing*/ |
| 922 | if (!buffer) { | 968 | if (!buffer) { |
| 923 | dev_err(&intf->dev, "Weird descriptor references\n"); | 969 | dev_err(&intf->dev, "Weird descriptor references\n"); |
| @@ -925,8 +971,10 @@ static int acm_probe (struct usb_interface *intf, | |||
| 925 | } | 971 | } |
| 926 | 972 | ||
| 927 | if (!buflen) { | 973 | if (!buflen) { |
| 928 | if (intf->cur_altsetting->endpoint->extralen && intf->cur_altsetting->endpoint->extra) { | 974 | if (intf->cur_altsetting->endpoint->extralen && |
| 929 | dev_dbg(&intf->dev,"Seeking extra descriptors on endpoint\n"); | 975 | intf->cur_altsetting->endpoint->extra) { |
| 976 | dev_dbg(&intf->dev, | ||
| 977 | "Seeking extra descriptors on endpoint\n"); | ||
| 930 | buflen = intf->cur_altsetting->endpoint->extralen; | 978 | buflen = intf->cur_altsetting->endpoint->extralen; |
| 931 | buffer = intf->cur_altsetting->endpoint->extra; | 979 | buffer = intf->cur_altsetting->endpoint->extra; |
| 932 | } else { | 980 | } else { |
| @@ -937,47 +985,43 @@ static int acm_probe (struct usb_interface *intf, | |||
| 937 | } | 985 | } |
| 938 | 986 | ||
| 939 | while (buflen > 0) { | 987 | while (buflen > 0) { |
| 940 | if (buffer [1] != USB_DT_CS_INTERFACE) { | 988 | if (buffer[1] != USB_DT_CS_INTERFACE) { |
| 941 | dev_err(&intf->dev, "skipping garbage\n"); | 989 | dev_err(&intf->dev, "skipping garbage\n"); |
| 942 | goto next_desc; | 990 | goto next_desc; |
| 943 | } | 991 | } |
| 944 | 992 | ||
| 945 | switch (buffer [2]) { | 993 | switch (buffer[2]) { |
| 946 | case USB_CDC_UNION_TYPE: /* we've found it */ | 994 | case USB_CDC_UNION_TYPE: /* we've found it */ |
| 947 | if (union_header) { | 995 | if (union_header) { |
| 948 | dev_err(&intf->dev, "More than one " | 996 | dev_err(&intf->dev, "More than one " |
| 949 | "union descriptor, " | 997 | "union descriptor, skipping ...\n"); |
| 950 | "skipping ...\n"); | 998 | goto next_desc; |
| 951 | goto next_desc; | ||
| 952 | } | ||
| 953 | union_header = (struct usb_cdc_union_desc *) | ||
| 954 | buffer; | ||
| 955 | break; | ||
| 956 | case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/ | ||
| 957 | cfd = (struct usb_cdc_country_functional_desc *)buffer; | ||
| 958 | break; | ||
| 959 | case USB_CDC_HEADER_TYPE: /* maybe check version */ | ||
| 960 | break; /* for now we ignore it */ | ||
| 961 | case USB_CDC_ACM_TYPE: | ||
| 962 | ac_management_function = buffer[3]; | ||
| 963 | break; | ||
| 964 | case USB_CDC_CALL_MANAGEMENT_TYPE: | ||
| 965 | call_management_function = buffer[3]; | ||
| 966 | call_interface_num = buffer[4]; | ||
| 967 | if ((call_management_function & 3) != 3) | ||
| 968 | dev_err(&intf->dev, "This device " | ||
| 969 | "cannot do calls on its own. " | ||
| 970 | "It is no modem.\n"); | ||
| 971 | break; | ||
| 972 | default: | ||
| 973 | /* there are LOTS more CDC descriptors that | ||
| 974 | * could legitimately be found here. | ||
| 975 | */ | ||
| 976 | dev_dbg(&intf->dev, "Ignoring descriptor: " | ||
| 977 | "type %02x, length %d\n", | ||
| 978 | buffer[2], buffer[0]); | ||
| 979 | break; | ||
| 980 | } | 999 | } |
| 1000 | union_header = (struct usb_cdc_union_desc *)buffer; | ||
| 1001 | break; | ||
| 1002 | case USB_CDC_COUNTRY_TYPE: /* export through sysfs*/ | ||
| 1003 | cfd = (struct usb_cdc_country_functional_desc *)buffer; | ||
| 1004 | break; | ||
| 1005 | case USB_CDC_HEADER_TYPE: /* maybe check version */ | ||
| 1006 | break; /* for now we ignore it */ | ||
| 1007 | case USB_CDC_ACM_TYPE: | ||
| 1008 | ac_management_function = buffer[3]; | ||
| 1009 | break; | ||
| 1010 | case USB_CDC_CALL_MANAGEMENT_TYPE: | ||
| 1011 | call_management_function = buffer[3]; | ||
| 1012 | call_interface_num = buffer[4]; | ||
| 1013 | if ((call_management_function & 3) != 3) | ||
| 1014 | dev_err(&intf->dev, "This device cannot do calls on its own. It is not a modem.\n"); | ||
| 1015 | break; | ||
| 1016 | default: | ||
| 1017 | /* there are LOTS more CDC descriptors that | ||
| 1018 | * could legitimately be found here. | ||
| 1019 | */ | ||
| 1020 | dev_dbg(&intf->dev, "Ignoring descriptor: " | ||
| 1021 | "type %02x, length %d\n", | ||
| 1022 | buffer[2], buffer[0]); | ||
| 1023 | break; | ||
| 1024 | } | ||
| 981 | next_desc: | 1025 | next_desc: |
| 982 | buflen -= buffer[0]; | 1026 | buflen -= buffer[0]; |
| 983 | buffer += buffer[0]; | 1027 | buffer += buffer[0]; |
| @@ -985,33 +1029,36 @@ next_desc: | |||
| 985 | 1029 | ||
| 986 | if (!union_header) { | 1030 | if (!union_header) { |
| 987 | if (call_interface_num > 0) { | 1031 | if (call_interface_num > 0) { |
| 988 | dev_dbg(&intf->dev,"No union descriptor, using call management descriptor\n"); | 1032 | dev_dbg(&intf->dev, "No union descriptor, using call management descriptor\n"); |
| 989 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); | 1033 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = call_interface_num)); |
| 990 | control_interface = intf; | 1034 | control_interface = intf; |
| 991 | } else { | 1035 | } else { |
| 992 | dev_dbg(&intf->dev,"No union descriptor, giving up\n"); | 1036 | dev_dbg(&intf->dev, |
| 1037 | "No union descriptor, giving up\n"); | ||
| 993 | return -ENODEV; | 1038 | return -ENODEV; |
| 994 | } | 1039 | } |
| 995 | } else { | 1040 | } else { |
| 996 | control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); | 1041 | control_interface = usb_ifnum_to_if(usb_dev, union_header->bMasterInterface0); |
| 997 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); | 1042 | data_interface = usb_ifnum_to_if(usb_dev, (data_interface_num = union_header->bSlaveInterface0)); |
| 998 | if (!control_interface || !data_interface) { | 1043 | if (!control_interface || !data_interface) { |
| 999 | dev_dbg(&intf->dev,"no interfaces\n"); | 1044 | dev_dbg(&intf->dev, "no interfaces\n"); |
| 1000 | return -ENODEV; | 1045 | return -ENODEV; |
| 1001 | } | 1046 | } |
| 1002 | } | 1047 | } |
| 1003 | 1048 | ||
| 1004 | if (data_interface_num != call_interface_num) | 1049 | if (data_interface_num != call_interface_num) |
| 1005 | dev_dbg(&intf->dev,"Separate call control interface. That is not fully supported.\n"); | 1050 | dev_dbg(&intf->dev, "Separate call control interface. That is not fully supported.\n"); |
| 1006 | 1051 | ||
| 1007 | skip_normal_probe: | 1052 | skip_normal_probe: |
| 1008 | 1053 | ||
| 1009 | /*workaround for switched interfaces */ | 1054 | /*workaround for switched interfaces */ |
| 1010 | if (data_interface->cur_altsetting->desc.bInterfaceClass != CDC_DATA_INTERFACE_TYPE) { | 1055 | if (data_interface->cur_altsetting->desc.bInterfaceClass |
| 1011 | if (control_interface->cur_altsetting->desc.bInterfaceClass == CDC_DATA_INTERFACE_TYPE) { | 1056 | != CDC_DATA_INTERFACE_TYPE) { |
| 1057 | if (control_interface->cur_altsetting->desc.bInterfaceClass | ||
| 1058 | == CDC_DATA_INTERFACE_TYPE) { | ||
| 1012 | struct usb_interface *t; | 1059 | struct usb_interface *t; |
| 1013 | dev_dbg(&intf->dev,"Your device has switched interfaces.\n"); | 1060 | dev_dbg(&intf->dev, |
| 1014 | 1061 | "Your device has switched interfaces.\n"); | |
| 1015 | t = control_interface; | 1062 | t = control_interface; |
| 1016 | control_interface = data_interface; | 1063 | control_interface = data_interface; |
| 1017 | data_interface = t; | 1064 | data_interface = t; |
| @@ -1023,9 +1070,9 @@ skip_normal_probe: | |||
| 1023 | /* Accept probe requests only for the control interface */ | 1070 | /* Accept probe requests only for the control interface */ |
| 1024 | if (intf != control_interface) | 1071 | if (intf != control_interface) |
| 1025 | return -ENODEV; | 1072 | return -ENODEV; |
| 1026 | 1073 | ||
| 1027 | if (usb_interface_claimed(data_interface)) { /* valid in this context */ | 1074 | if (usb_interface_claimed(data_interface)) { /* valid in this context */ |
| 1028 | dev_dbg(&intf->dev,"The data interface isn't available\n"); | 1075 | dev_dbg(&intf->dev, "The data interface isn't available\n"); |
| 1029 | return -EBUSY; | 1076 | return -EBUSY; |
| 1030 | } | 1077 | } |
| 1031 | 1078 | ||
| @@ -1042,8 +1089,8 @@ skip_normal_probe: | |||
| 1042 | if (!usb_endpoint_dir_in(epread)) { | 1089 | if (!usb_endpoint_dir_in(epread)) { |
| 1043 | /* descriptors are swapped */ | 1090 | /* descriptors are swapped */ |
| 1044 | struct usb_endpoint_descriptor *t; | 1091 | struct usb_endpoint_descriptor *t; |
| 1045 | dev_dbg(&intf->dev,"The data interface has switched endpoints\n"); | 1092 | dev_dbg(&intf->dev, |
| 1046 | 1093 | "The data interface has switched endpoints\n"); | |
| 1047 | t = epread; | 1094 | t = epread; |
| 1048 | epread = epwrite; | 1095 | epread = epwrite; |
| 1049 | epwrite = t; | 1096 | epwrite = t; |
| @@ -1056,13 +1103,15 @@ skip_normal_probe: | |||
| 1056 | return -ENODEV; | 1103 | return -ENODEV; |
| 1057 | } | 1104 | } |
| 1058 | 1105 | ||
| 1059 | if (!(acm = kzalloc(sizeof(struct acm), GFP_KERNEL))) { | 1106 | acm = kzalloc(sizeof(struct acm), GFP_KERNEL); |
| 1107 | if (acm == NULL) { | ||
| 1060 | dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n"); | 1108 | dev_dbg(&intf->dev, "out of memory (acm kzalloc)\n"); |
| 1061 | goto alloc_fail; | 1109 | goto alloc_fail; |
| 1062 | } | 1110 | } |
| 1063 | 1111 | ||
| 1064 | ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); | 1112 | ctrlsize = le16_to_cpu(epctrl->wMaxPacketSize); |
| 1065 | readsize = le16_to_cpu(epread->wMaxPacketSize)* ( quirks == SINGLE_RX_URB ? 1 : 2); | 1113 | readsize = le16_to_cpu(epread->wMaxPacketSize) * |
| 1114 | (quirks == SINGLE_RX_URB ? 1 : 2); | ||
| 1066 | acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20; | 1115 | acm->writesize = le16_to_cpu(epwrite->wMaxPacketSize) * 20; |
| 1067 | acm->control = control_interface; | 1116 | acm->control = control_interface; |
| 1068 | acm->data = data_interface; | 1117 | acm->data = data_interface; |
| @@ -1082,6 +1131,8 @@ skip_normal_probe: | |||
| 1082 | spin_lock_init(&acm->read_lock); | 1131 | spin_lock_init(&acm->read_lock); |
| 1083 | mutex_init(&acm->mutex); | 1132 | mutex_init(&acm->mutex); |
| 1084 | acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); | 1133 | acm->rx_endpoint = usb_rcvbulkpipe(usb_dev, epread->bEndpointAddress); |
| 1134 | tty_port_init(&acm->port); | ||
| 1135 | acm->port.ops = &acm_port_ops; | ||
| 1085 | 1136 | ||
| 1086 | buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); | 1137 | buf = usb_buffer_alloc(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); |
| 1087 | if (!buf) { | 1138 | if (!buf) { |
| @@ -1103,8 +1154,10 @@ skip_normal_probe: | |||
| 1103 | for (i = 0; i < num_rx_buf; i++) { | 1154 | for (i = 0; i < num_rx_buf; i++) { |
| 1104 | struct acm_ru *rcv = &(acm->ru[i]); | 1155 | struct acm_ru *rcv = &(acm->ru[i]); |
| 1105 | 1156 | ||
| 1106 | if (!(rcv->urb = usb_alloc_urb(0, GFP_KERNEL))) { | 1157 | rcv->urb = usb_alloc_urb(0, GFP_KERNEL); |
| 1107 | dev_dbg(&intf->dev, "out of memory (read urbs usb_alloc_urb)\n"); | 1158 | if (rcv->urb == NULL) { |
| 1159 | dev_dbg(&intf->dev, | ||
| 1160 | "out of memory (read urbs usb_alloc_urb)\n"); | ||
| 1108 | goto alloc_fail7; | 1161 | goto alloc_fail7; |
| 1109 | } | 1162 | } |
| 1110 | 1163 | ||
| @@ -1117,26 +1170,29 @@ skip_normal_probe: | |||
| 1117 | rb->base = usb_buffer_alloc(acm->dev, readsize, | 1170 | rb->base = usb_buffer_alloc(acm->dev, readsize, |
| 1118 | GFP_KERNEL, &rb->dma); | 1171 | GFP_KERNEL, &rb->dma); |
| 1119 | if (!rb->base) { | 1172 | if (!rb->base) { |
| 1120 | dev_dbg(&intf->dev, "out of memory (read bufs usb_buffer_alloc)\n"); | 1173 | dev_dbg(&intf->dev, |
| 1174 | "out of memory (read bufs usb_buffer_alloc)\n"); | ||
| 1121 | goto alloc_fail7; | 1175 | goto alloc_fail7; |
| 1122 | } | 1176 | } |
| 1123 | } | 1177 | } |
| 1124 | for(i = 0; i < ACM_NW; i++) | 1178 | for (i = 0; i < ACM_NW; i++) { |
| 1125 | { | ||
| 1126 | struct acm_wb *snd = &(acm->wb[i]); | 1179 | struct acm_wb *snd = &(acm->wb[i]); |
| 1127 | 1180 | ||
| 1128 | if (!(snd->urb = usb_alloc_urb(0, GFP_KERNEL))) { | 1181 | snd->urb = usb_alloc_urb(0, GFP_KERNEL); |
| 1129 | dev_dbg(&intf->dev, "out of memory (write urbs usb_alloc_urb)"); | 1182 | if (snd->urb == NULL) { |
| 1183 | dev_dbg(&intf->dev, | ||
| 1184 | "out of memory (write urbs usb_alloc_urb)"); | ||
| 1130 | goto alloc_fail7; | 1185 | goto alloc_fail7; |
| 1131 | } | 1186 | } |
| 1132 | 1187 | ||
| 1133 | usb_fill_bulk_urb(snd->urb, usb_dev, usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), | 1188 | usb_fill_bulk_urb(snd->urb, usb_dev, |
| 1134 | NULL, acm->writesize, acm_write_bulk, snd); | 1189 | usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress), |
| 1190 | NULL, acm->writesize, acm_write_bulk, snd); | ||
| 1135 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1191 | snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 1136 | snd->instance = acm; | 1192 | snd->instance = acm; |
| 1137 | } | 1193 | } |
| 1138 | 1194 | ||
| 1139 | usb_set_intfdata (intf, acm); | 1195 | usb_set_intfdata(intf, acm); |
| 1140 | 1196 | ||
| 1141 | i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); | 1197 | i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); |
| 1142 | if (i < 0) | 1198 | if (i < 0) |
| @@ -1147,7 +1203,8 @@ skip_normal_probe: | |||
| 1147 | if (!acm->country_codes) | 1203 | if (!acm->country_codes) |
| 1148 | goto skip_countries; | 1204 | goto skip_countries; |
| 1149 | acm->country_code_size = cfd->bLength - 4; | 1205 | acm->country_code_size = cfd->bLength - 4; |
| 1150 | memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, cfd->bLength - 4); | 1206 | memcpy(acm->country_codes, (u8 *)&cfd->wCountyCode0, |
| 1207 | cfd->bLength - 4); | ||
| 1151 | acm->country_rel_date = cfd->iCountryCodeRelDate; | 1208 | acm->country_rel_date = cfd->iCountryCodeRelDate; |
| 1152 | 1209 | ||
| 1153 | i = device_create_file(&intf->dev, &dev_attr_wCountryCodes); | 1210 | i = device_create_file(&intf->dev, &dev_attr_wCountryCodes); |
| @@ -1156,7 +1213,8 @@ skip_normal_probe: | |||
| 1156 | goto skip_countries; | 1213 | goto skip_countries; |
| 1157 | } | 1214 | } |
| 1158 | 1215 | ||
| 1159 | i = device_create_file(&intf->dev, &dev_attr_iCountryCodeRelDate); | 1216 | i = device_create_file(&intf->dev, |
| 1217 | &dev_attr_iCountryCodeRelDate); | ||
| 1160 | if (i < 0) { | 1218 | if (i < 0) { |
| 1161 | kfree(acm->country_codes); | 1219 | kfree(acm->country_codes); |
| 1162 | goto skip_countries; | 1220 | goto skip_countries; |
| @@ -1164,8 +1222,10 @@ skip_normal_probe: | |||
| 1164 | } | 1222 | } |
| 1165 | 1223 | ||
| 1166 | skip_countries: | 1224 | skip_countries: |
| 1167 | usb_fill_int_urb(acm->ctrlurb, usb_dev, usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), | 1225 | usb_fill_int_urb(acm->ctrlurb, usb_dev, |
| 1168 | acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, epctrl->bInterval); | 1226 | usb_rcvintpipe(usb_dev, epctrl->bEndpointAddress), |
| 1227 | acm->ctrl_buffer, ctrlsize, acm_ctrl_irq, acm, | ||
| 1228 | epctrl->bInterval); | ||
| 1169 | acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; | 1229 | acm->ctrlurb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; |
| 1170 | acm->ctrlurb->transfer_dma = acm->ctrl_dma; | 1230 | acm->ctrlurb->transfer_dma = acm->ctrl_dma; |
| 1171 | 1231 | ||
| @@ -1212,7 +1272,7 @@ static void stop_data_traffic(struct acm *acm) | |||
| 1212 | tasklet_disable(&acm->urb_task); | 1272 | tasklet_disable(&acm->urb_task); |
| 1213 | 1273 | ||
| 1214 | usb_kill_urb(acm->ctrlurb); | 1274 | usb_kill_urb(acm->ctrlurb); |
| 1215 | for(i = 0; i < ACM_NW; i++) | 1275 | for (i = 0; i < ACM_NW; i++) |
| 1216 | usb_kill_urb(acm->wb[i].urb); | 1276 | usb_kill_urb(acm->wb[i].urb); |
| 1217 | for (i = 0; i < acm->rx_buflimit; i++) | 1277 | for (i = 0; i < acm->rx_buflimit; i++) |
| 1218 | usb_kill_urb(acm->ru[i].urb); | 1278 | usb_kill_urb(acm->ru[i].urb); |
| @@ -1227,13 +1287,14 @@ static void acm_disconnect(struct usb_interface *intf) | |||
| 1227 | { | 1287 | { |
| 1228 | struct acm *acm = usb_get_intfdata(intf); | 1288 | struct acm *acm = usb_get_intfdata(intf); |
| 1229 | struct usb_device *usb_dev = interface_to_usbdev(intf); | 1289 | struct usb_device *usb_dev = interface_to_usbdev(intf); |
| 1290 | struct tty_struct *tty; | ||
| 1230 | 1291 | ||
| 1231 | /* sibling interface is already cleaning up */ | 1292 | /* sibling interface is already cleaning up */ |
| 1232 | if (!acm) | 1293 | if (!acm) |
| 1233 | return; | 1294 | return; |
| 1234 | 1295 | ||
| 1235 | mutex_lock(&open_mutex); | 1296 | mutex_lock(&open_mutex); |
| 1236 | if (acm->country_codes){ | 1297 | if (acm->country_codes) { |
| 1237 | device_remove_file(&acm->control->dev, | 1298 | device_remove_file(&acm->control->dev, |
| 1238 | &dev_attr_wCountryCodes); | 1299 | &dev_attr_wCountryCodes); |
| 1239 | device_remove_file(&acm->control->dev, | 1300 | device_remove_file(&acm->control->dev, |
| @@ -1247,22 +1308,25 @@ static void acm_disconnect(struct usb_interface *intf) | |||
| 1247 | stop_data_traffic(acm); | 1308 | stop_data_traffic(acm); |
| 1248 | 1309 | ||
| 1249 | acm_write_buffers_free(acm); | 1310 | acm_write_buffers_free(acm); |
| 1250 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); | 1311 | usb_buffer_free(usb_dev, acm->ctrlsize, acm->ctrl_buffer, |
| 1312 | acm->ctrl_dma); | ||
| 1251 | acm_read_buffers_free(acm); | 1313 | acm_read_buffers_free(acm); |
| 1252 | 1314 | ||
| 1253 | usb_driver_release_interface(&acm_driver, intf == acm->control ? | 1315 | usb_driver_release_interface(&acm_driver, intf == acm->control ? |
| 1254 | acm->data : acm->control); | 1316 | acm->data : acm->control); |
| 1255 | 1317 | ||
| 1256 | if (!acm->used) { | 1318 | if (acm->port.count == 0) { |
| 1257 | acm_tty_unregister(acm); | 1319 | acm_tty_unregister(acm); |
| 1258 | mutex_unlock(&open_mutex); | 1320 | mutex_unlock(&open_mutex); |
| 1259 | return; | 1321 | return; |
| 1260 | } | 1322 | } |
| 1261 | 1323 | ||
| 1262 | mutex_unlock(&open_mutex); | 1324 | mutex_unlock(&open_mutex); |
| 1263 | 1325 | tty = tty_port_tty_get(&acm->port); | |
| 1264 | if (acm->tty) | 1326 | if (tty) { |
| 1265 | tty_hangup(acm->tty); | 1327 | tty_hangup(tty); |
| 1328 | tty_kref_put(tty); | ||
| 1329 | } | ||
| 1266 | } | 1330 | } |
| 1267 | 1331 | ||
| 1268 | #ifdef CONFIG_PM | 1332 | #ifdef CONFIG_PM |
| @@ -1297,7 +1361,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) | |||
| 1297 | */ | 1361 | */ |
| 1298 | mutex_lock(&acm->mutex); | 1362 | mutex_lock(&acm->mutex); |
| 1299 | 1363 | ||
| 1300 | if (acm->used) | 1364 | if (acm->port.count) |
| 1301 | stop_data_traffic(acm); | 1365 | stop_data_traffic(acm); |
| 1302 | 1366 | ||
| 1303 | mutex_unlock(&acm->mutex); | 1367 | mutex_unlock(&acm->mutex); |
| @@ -1319,7 +1383,7 @@ static int acm_resume(struct usb_interface *intf) | |||
| 1319 | return 0; | 1383 | return 0; |
| 1320 | 1384 | ||
| 1321 | mutex_lock(&acm->mutex); | 1385 | mutex_lock(&acm->mutex); |
| 1322 | if (acm->used) { | 1386 | if (acm->port.count) { |
| 1323 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); | 1387 | rv = usb_submit_urb(acm->ctrlurb, GFP_NOIO); |
| 1324 | if (rv < 0) | 1388 | if (rv < 0) |
| 1325 | goto err_out; | 1389 | goto err_out; |
| @@ -1375,6 +1439,9 @@ static struct usb_device_id acm_ids[] = { | |||
| 1375 | { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ | 1439 | { USB_DEVICE(0x0572, 0x1324), /* Conexant USB MODEM RD02-D400 */ |
| 1376 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | 1440 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ |
| 1377 | }, | 1441 | }, |
| 1442 | { USB_DEVICE(0x0572, 0x1328), /* Shiro / Aztech USB MODEM UM-3100 */ | ||
| 1443 | .driver_info = NO_UNION_NORMAL, /* has no union descriptor */ | ||
| 1444 | }, | ||
| 1378 | { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ | 1445 | { USB_DEVICE(0x22b8, 0x6425), /* Motorola MOTOMAGX phones */ |
| 1379 | }, | 1446 | }, |
| 1380 | { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ | 1447 | { USB_DEVICE(0x0572, 0x1329), /* Hummingbird huc56s (Conexant) */ |
| @@ -1395,7 +1462,7 @@ static struct usb_device_id acm_ids[] = { | |||
| 1395 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1462 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
| 1396 | USB_CDC_ACM_PROTO_AT_GSM) }, | 1463 | USB_CDC_ACM_PROTO_AT_GSM) }, |
| 1397 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1464 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
| 1398 | USB_CDC_ACM_PROTO_AT_3G ) }, | 1465 | USB_CDC_ACM_PROTO_AT_3G) }, |
| 1399 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, | 1466 | { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM, |
| 1400 | USB_CDC_ACM_PROTO_AT_CDMA) }, | 1467 | USB_CDC_ACM_PROTO_AT_CDMA) }, |
| 1401 | 1468 | ||
| @@ -1403,7 +1470,7 @@ static struct usb_device_id acm_ids[] = { | |||
| 1403 | { } | 1470 | { } |
| 1404 | }; | 1471 | }; |
| 1405 | 1472 | ||
| 1406 | MODULE_DEVICE_TABLE (usb, acm_ids); | 1473 | MODULE_DEVICE_TABLE(usb, acm_ids); |
| 1407 | 1474 | ||
| 1408 | static struct usb_driver acm_driver = { | 1475 | static struct usb_driver acm_driver = { |
| 1409 | .name = "cdc_acm", | 1476 | .name = "cdc_acm", |
| @@ -1426,6 +1493,7 @@ static struct usb_driver acm_driver = { | |||
| 1426 | static const struct tty_operations acm_ops = { | 1493 | static const struct tty_operations acm_ops = { |
| 1427 | .open = acm_tty_open, | 1494 | .open = acm_tty_open, |
| 1428 | .close = acm_tty_close, | 1495 | .close = acm_tty_close, |
| 1496 | .hangup = acm_tty_hangup, | ||
| 1429 | .write = acm_tty_write, | 1497 | .write = acm_tty_write, |
| 1430 | .write_room = acm_tty_write_room, | 1498 | .write_room = acm_tty_write_room, |
| 1431 | .ioctl = acm_tty_ioctl, | 1499 | .ioctl = acm_tty_ioctl, |
| @@ -1457,7 +1525,8 @@ static int __init acm_init(void) | |||
| 1457 | acm_tty_driver->subtype = SERIAL_TYPE_NORMAL, | 1525 | acm_tty_driver->subtype = SERIAL_TYPE_NORMAL, |
| 1458 | acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 1526 | acm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
| 1459 | acm_tty_driver->init_termios = tty_std_termios; | 1527 | acm_tty_driver->init_termios = tty_std_termios; |
| 1460 | acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 1528 | acm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | |
| 1529 | HUPCL | CLOCAL; | ||
| 1461 | tty_set_operations(acm_tty_driver, &acm_ops); | 1530 | tty_set_operations(acm_tty_driver, &acm_ops); |
| 1462 | 1531 | ||
| 1463 | retval = tty_register_driver(acm_tty_driver); | 1532 | retval = tty_register_driver(acm_tty_driver); |
| @@ -1489,7 +1558,7 @@ static void __exit acm_exit(void) | |||
| 1489 | module_init(acm_init); | 1558 | module_init(acm_init); |
| 1490 | module_exit(acm_exit); | 1559 | module_exit(acm_exit); |
| 1491 | 1560 | ||
| 1492 | MODULE_AUTHOR( DRIVER_AUTHOR ); | 1561 | MODULE_AUTHOR(DRIVER_AUTHOR); |
| 1493 | MODULE_DESCRIPTION( DRIVER_DESC ); | 1562 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 1494 | MODULE_LICENSE("GPL"); | 1563 | MODULE_LICENSE("GPL"); |
| 1495 | MODULE_ALIAS_CHARDEV_MAJOR(ACM_TTY_MAJOR); | 1564 | MODULE_ALIAS_CHARDEV_MAJOR(ACM_TTY_MAJOR); |
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h index 1f95e7aa1b66..4c3856420add 100644 --- a/drivers/usb/class/cdc-acm.h +++ b/drivers/usb/class/cdc-acm.h | |||
| @@ -89,8 +89,8 @@ struct acm { | |||
| 89 | struct usb_device *dev; /* the corresponding usb device */ | 89 | struct usb_device *dev; /* the corresponding usb device */ |
| 90 | struct usb_interface *control; /* control interface */ | 90 | struct usb_interface *control; /* control interface */ |
| 91 | struct usb_interface *data; /* data interface */ | 91 | struct usb_interface *data; /* data interface */ |
| 92 | struct tty_struct *tty; /* the corresponding tty */ | 92 | struct tty_port port; /* our tty port data */ |
| 93 | struct urb *ctrlurb; /* urbs */ | 93 | struct urb *ctrlurb; /* urbs */ |
| 94 | u8 *ctrl_buffer; /* buffers of urbs */ | 94 | u8 *ctrl_buffer; /* buffers of urbs */ |
| 95 | dma_addr_t ctrl_dma; /* dma handles of buffers */ | 95 | dma_addr_t ctrl_dma; /* dma handles of buffers */ |
| 96 | u8 *country_codes; /* country codes from device */ | 96 | u8 *country_codes; /* country codes from device */ |
| @@ -120,7 +120,6 @@ struct acm { | |||
| 120 | unsigned int ctrlout; /* output control lines (DTR, RTS) */ | 120 | unsigned int ctrlout; /* output control lines (DTR, RTS) */ |
| 121 | unsigned int writesize; /* max packet size for the output bulk endpoint */ | 121 | unsigned int writesize; /* max packet size for the output bulk endpoint */ |
| 122 | unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ | 122 | unsigned int readsize,ctrlsize; /* buffer sizes for freeing */ |
| 123 | unsigned int used; /* someone has this acm's device open */ | ||
| 124 | unsigned int minor; /* acm minor number */ | 123 | unsigned int minor; /* acm minor number */ |
| 125 | unsigned char throttle; /* throttled by tty layer */ | 124 | unsigned char throttle; /* throttled by tty layer */ |
| 126 | unsigned char clocal; /* termios CLOCAL */ | 125 | unsigned char clocal; /* termios CLOCAL */ |
diff --git a/drivers/usb/core/inode.c b/drivers/usb/core/inode.c index dff5760a37f6..ffe75e83787c 100644 --- a/drivers/usb/core/inode.c +++ b/drivers/usb/core/inode.c | |||
| @@ -39,6 +39,7 @@ | |||
| 39 | #include <linux/parser.h> | 39 | #include <linux/parser.h> |
| 40 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
| 41 | #include <linux/seq_file.h> | 41 | #include <linux/seq_file.h> |
| 42 | #include <linux/smp_lock.h> | ||
| 42 | #include <asm/byteorder.h> | 43 | #include <asm/byteorder.h> |
| 43 | #include "usb.h" | 44 | #include "usb.h" |
| 44 | #include "hcd.h" | 45 | #include "hcd.h" |
| @@ -265,9 +266,13 @@ static int remount(struct super_block *sb, int *flags, char *data) | |||
| 265 | return -EINVAL; | 266 | return -EINVAL; |
| 266 | } | 267 | } |
| 267 | 268 | ||
| 269 | lock_kernel(); | ||
| 270 | |||
| 268 | if (usbfs_mount && usbfs_mount->mnt_sb) | 271 | if (usbfs_mount && usbfs_mount->mnt_sb) |
| 269 | update_sb(usbfs_mount->mnt_sb); | 272 | update_sb(usbfs_mount->mnt_sb); |
| 270 | 273 | ||
| 274 | unlock_kernel(); | ||
| 275 | |||
| 271 | return 0; | 276 | return 0; |
| 272 | } | 277 | } |
| 273 | 278 | ||
diff --git a/drivers/usb/gadget/atmel_usba_udc.c b/drivers/usb/gadget/atmel_usba_udc.c index 563d57275448..05c913cc3658 100644 --- a/drivers/usb/gadget/atmel_usba_udc.c +++ b/drivers/usb/gadget/atmel_usba_udc.c | |||
| @@ -794,7 +794,8 @@ usba_ep_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) | |||
| 794 | if (ep->desc) { | 794 | if (ep->desc) { |
| 795 | list_add_tail(&req->queue, &ep->queue); | 795 | list_add_tail(&req->queue, &ep->queue); |
| 796 | 796 | ||
| 797 | if (ep->is_in || (ep_is_control(ep) | 797 | if ((!ep_is_control(ep) && ep->is_in) || |
| 798 | (ep_is_control(ep) | ||
| 798 | && (ep->state == DATA_STAGE_IN | 799 | && (ep->state == DATA_STAGE_IN |
| 799 | || ep->state == STATUS_STAGE_IN))) | 800 | || ep->state == STATUS_STAGE_IN))) |
| 800 | usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); | 801 | usba_ep_writel(ep, CTL_ENB, USBA_TX_PK_RDY); |
| @@ -1940,7 +1941,7 @@ static int __init usba_udc_probe(struct platform_device *pdev) | |||
| 1940 | usba_writel(udc, CTRL, USBA_DISABLE_MASK); | 1941 | usba_writel(udc, CTRL, USBA_DISABLE_MASK); |
| 1941 | clk_disable(pclk); | 1942 | clk_disable(pclk); |
| 1942 | 1943 | ||
| 1943 | usba_ep = kmalloc(sizeof(struct usba_ep) * pdata->num_ep, | 1944 | usba_ep = kzalloc(sizeof(struct usba_ep) * pdata->num_ep, |
| 1944 | GFP_KERNEL); | 1945 | GFP_KERNEL); |
| 1945 | if (!usba_ep) | 1946 | if (!usba_ep) |
| 1946 | goto err_alloc_ep; | 1947 | goto err_alloc_ep; |
diff --git a/drivers/usb/host/isp1760-hcd.c b/drivers/usb/host/isp1760-hcd.c index cd07ea3f0c63..15438469f21a 100644 --- a/drivers/usb/host/isp1760-hcd.c +++ b/drivers/usb/host/isp1760-hcd.c | |||
| @@ -1658,6 +1658,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
| 1658 | u32 reg_base, or_reg, skip_reg; | 1658 | u32 reg_base, or_reg, skip_reg; |
| 1659 | unsigned long flags; | 1659 | unsigned long flags; |
| 1660 | struct ptd ptd; | 1660 | struct ptd ptd; |
| 1661 | packet_enqueue *pe; | ||
| 1661 | 1662 | ||
| 1662 | switch (usb_pipetype(urb->pipe)) { | 1663 | switch (usb_pipetype(urb->pipe)) { |
| 1663 | case PIPE_ISOCHRONOUS: | 1664 | case PIPE_ISOCHRONOUS: |
| @@ -1669,6 +1670,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
| 1669 | reg_base = INT_REGS_OFFSET; | 1670 | reg_base = INT_REGS_OFFSET; |
| 1670 | or_reg = HC_INT_IRQ_MASK_OR_REG; | 1671 | or_reg = HC_INT_IRQ_MASK_OR_REG; |
| 1671 | skip_reg = HC_INT_PTD_SKIPMAP_REG; | 1672 | skip_reg = HC_INT_PTD_SKIPMAP_REG; |
| 1673 | pe = enqueue_an_INT_packet; | ||
| 1672 | break; | 1674 | break; |
| 1673 | 1675 | ||
| 1674 | default: | 1676 | default: |
| @@ -1676,6 +1678,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
| 1676 | reg_base = ATL_REGS_OFFSET; | 1678 | reg_base = ATL_REGS_OFFSET; |
| 1677 | or_reg = HC_ATL_IRQ_MASK_OR_REG; | 1679 | or_reg = HC_ATL_IRQ_MASK_OR_REG; |
| 1678 | skip_reg = HC_ATL_PTD_SKIPMAP_REG; | 1680 | skip_reg = HC_ATL_PTD_SKIPMAP_REG; |
| 1681 | pe = enqueue_an_ATL_packet; | ||
| 1679 | break; | 1682 | break; |
| 1680 | } | 1683 | } |
| 1681 | 1684 | ||
| @@ -1687,6 +1690,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
| 1687 | u32 skip_map; | 1690 | u32 skip_map; |
| 1688 | u32 or_map; | 1691 | u32 or_map; |
| 1689 | struct isp1760_qtd *qtd; | 1692 | struct isp1760_qtd *qtd; |
| 1693 | struct isp1760_qh *qh = ints->qh; | ||
| 1690 | 1694 | ||
| 1691 | skip_map = isp1760_readl(hcd->regs + skip_reg); | 1695 | skip_map = isp1760_readl(hcd->regs + skip_reg); |
| 1692 | skip_map |= 1 << i; | 1696 | skip_map |= 1 << i; |
| @@ -1699,8 +1703,7 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
| 1699 | priv_write_copy(priv, (u32 *)&ptd, hcd->regs + reg_base | 1703 | priv_write_copy(priv, (u32 *)&ptd, hcd->regs + reg_base |
| 1700 | + i * sizeof(ptd), sizeof(ptd)); | 1704 | + i * sizeof(ptd), sizeof(ptd)); |
| 1701 | qtd = ints->qtd; | 1705 | qtd = ints->qtd; |
| 1702 | 1706 | qtd = clean_up_qtdlist(qtd); | |
| 1703 | clean_up_qtdlist(qtd); | ||
| 1704 | 1707 | ||
| 1705 | free_mem(priv, ints->payload); | 1708 | free_mem(priv, ints->payload); |
| 1706 | 1709 | ||
| @@ -1711,7 +1714,24 @@ static int isp1760_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, | |||
| 1711 | ints->payload = 0; | 1714 | ints->payload = 0; |
| 1712 | 1715 | ||
| 1713 | isp1760_urb_done(priv, urb, status); | 1716 | isp1760_urb_done(priv, urb, status); |
| 1717 | if (qtd) | ||
| 1718 | pe(hcd, qh, qtd); | ||
| 1714 | break; | 1719 | break; |
| 1720 | |||
| 1721 | } else if (ints->qtd) { | ||
| 1722 | struct isp1760_qtd *qtd, *prev_qtd = ints->qtd; | ||
| 1723 | |||
| 1724 | for (qtd = ints->qtd->hw_next; qtd; qtd = qtd->hw_next) { | ||
| 1725 | if (qtd->urb == urb) { | ||
| 1726 | prev_qtd->hw_next = clean_up_qtdlist(qtd); | ||
| 1727 | isp1760_urb_done(priv, urb, status); | ||
| 1728 | break; | ||
| 1729 | } | ||
| 1730 | prev_qtd = qtd; | ||
| 1731 | } | ||
| 1732 | /* we found the urb before the end of the list */ | ||
| 1733 | if (qtd) | ||
| 1734 | break; | ||
| 1715 | } | 1735 | } |
| 1716 | ints++; | 1736 | ints++; |
| 1717 | } | 1737 | } |
diff --git a/drivers/usb/serial/belkin_sa.c b/drivers/usb/serial/belkin_sa.c index b7eacad4d48c..2bfd6dd85b5a 100644 --- a/drivers/usb/serial/belkin_sa.c +++ b/drivers/usb/serial/belkin_sa.c | |||
| @@ -93,8 +93,7 @@ static int belkin_sa_startup(struct usb_serial *serial); | |||
| 93 | static void belkin_sa_shutdown(struct usb_serial *serial); | 93 | static void belkin_sa_shutdown(struct usb_serial *serial); |
| 94 | static int belkin_sa_open(struct tty_struct *tty, | 94 | static int belkin_sa_open(struct tty_struct *tty, |
| 95 | struct usb_serial_port *port, struct file *filp); | 95 | struct usb_serial_port *port, struct file *filp); |
| 96 | static void belkin_sa_close(struct tty_struct *tty, | 96 | static void belkin_sa_close(struct usb_serial_port *port); |
| 97 | struct usb_serial_port *port, struct file *filp); | ||
| 98 | static void belkin_sa_read_int_callback(struct urb *urb); | 97 | static void belkin_sa_read_int_callback(struct urb *urb); |
| 99 | static void belkin_sa_set_termios(struct tty_struct *tty, | 98 | static void belkin_sa_set_termios(struct tty_struct *tty, |
| 100 | struct usb_serial_port *port, struct ktermios * old); | 99 | struct usb_serial_port *port, struct ktermios * old); |
| @@ -244,8 +243,7 @@ exit: | |||
| 244 | } /* belkin_sa_open */ | 243 | } /* belkin_sa_open */ |
| 245 | 244 | ||
| 246 | 245 | ||
| 247 | static void belkin_sa_close(struct tty_struct *tty, | 246 | static void belkin_sa_close(struct usb_serial_port *port) |
| 248 | struct usb_serial_port *port, struct file *filp) | ||
| 249 | { | 247 | { |
| 250 | dbg("%s port %d", __func__, port->number); | 248 | dbg("%s port %d", __func__, port->number); |
| 251 | 249 | ||
diff --git a/drivers/usb/serial/ch341.c b/drivers/usb/serial/ch341.c index ab4cc277aa65..2830766f5b39 100644 --- a/drivers/usb/serial/ch341.c +++ b/drivers/usb/serial/ch341.c | |||
| @@ -262,32 +262,40 @@ error: kfree(priv); | |||
| 262 | return r; | 262 | return r; |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | static void ch341_close(struct tty_struct *tty, struct usb_serial_port *port, | 265 | static int ch341_carrier_raised(struct usb_serial_port *port) |
| 266 | struct file *filp) | 266 | { |
| 267 | struct ch341_private *priv = usb_get_serial_port_data(port); | ||
| 268 | if (priv->line_status & CH341_BIT_DCD) | ||
| 269 | return 1; | ||
| 270 | return 0; | ||
| 271 | } | ||
| 272 | |||
| 273 | static void ch341_dtr_rts(struct usb_serial_port *port, int on) | ||
| 267 | { | 274 | { |
| 268 | struct ch341_private *priv = usb_get_serial_port_data(port); | 275 | struct ch341_private *priv = usb_get_serial_port_data(port); |
| 269 | unsigned long flags; | 276 | unsigned long flags; |
| 270 | unsigned int c_cflag; | ||
| 271 | 277 | ||
| 272 | dbg("%s - port %d", __func__, port->number); | 278 | dbg("%s - port %d", __func__, port->number); |
| 279 | /* drop DTR and RTS */ | ||
| 280 | spin_lock_irqsave(&priv->lock, flags); | ||
| 281 | if (on) | ||
| 282 | priv->line_control |= CH341_BIT_RTS | CH341_BIT_DTR; | ||
| 283 | else | ||
| 284 | priv->line_control &= ~(CH341_BIT_RTS | CH341_BIT_DTR); | ||
| 285 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 286 | ch341_set_handshake(port->serial->dev, priv->line_control); | ||
| 287 | wake_up_interruptible(&priv->delta_msr_wait); | ||
| 288 | } | ||
| 289 | |||
| 290 | static void ch341_close(struct usb_serial_port *port) | ||
| 291 | { | ||
| 292 | dbg("%s - port %d", __func__, port->number); | ||
| 273 | 293 | ||
| 274 | /* shutdown our urbs */ | 294 | /* shutdown our urbs */ |
| 275 | dbg("%s - shutting down urbs", __func__); | 295 | dbg("%s - shutting down urbs", __func__); |
| 276 | usb_kill_urb(port->write_urb); | 296 | usb_kill_urb(port->write_urb); |
| 277 | usb_kill_urb(port->read_urb); | 297 | usb_kill_urb(port->read_urb); |
| 278 | usb_kill_urb(port->interrupt_in_urb); | 298 | usb_kill_urb(port->interrupt_in_urb); |
| 279 | |||
| 280 | if (tty) { | ||
| 281 | c_cflag = tty->termios->c_cflag; | ||
| 282 | if (c_cflag & HUPCL) { | ||
| 283 | /* drop DTR and RTS */ | ||
| 284 | spin_lock_irqsave(&priv->lock, flags); | ||
| 285 | priv->line_control = 0; | ||
| 286 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 287 | ch341_set_handshake(port->serial->dev, 0); | ||
| 288 | } | ||
| 289 | } | ||
| 290 | wake_up_interruptible(&priv->delta_msr_wait); | ||
| 291 | } | 299 | } |
| 292 | 300 | ||
| 293 | 301 | ||
| @@ -302,7 +310,6 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 302 | dbg("ch341_open()"); | 310 | dbg("ch341_open()"); |
| 303 | 311 | ||
| 304 | priv->baud_rate = DEFAULT_BAUD_RATE; | 312 | priv->baud_rate = DEFAULT_BAUD_RATE; |
| 305 | priv->line_control = CH341_BIT_RTS | CH341_BIT_DTR; | ||
| 306 | 313 | ||
| 307 | r = ch341_configure(serial->dev, priv); | 314 | r = ch341_configure(serial->dev, priv); |
| 308 | if (r) | 315 | if (r) |
| @@ -322,7 +329,7 @@ static int ch341_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 322 | if (r) { | 329 | if (r) { |
| 323 | dev_err(&port->dev, "%s - failed submitting interrupt urb," | 330 | dev_err(&port->dev, "%s - failed submitting interrupt urb," |
| 324 | " error %d\n", __func__, r); | 331 | " error %d\n", __func__, r); |
| 325 | ch341_close(tty, port, NULL); | 332 | ch341_close(port); |
| 326 | return -EPROTO; | 333 | return -EPROTO; |
| 327 | } | 334 | } |
| 328 | 335 | ||
| @@ -343,9 +350,6 @@ static void ch341_set_termios(struct tty_struct *tty, | |||
| 343 | 350 | ||
| 344 | dbg("ch341_set_termios()"); | 351 | dbg("ch341_set_termios()"); |
| 345 | 352 | ||
| 346 | if (!tty || !tty->termios) | ||
| 347 | return; | ||
| 348 | |||
| 349 | baud_rate = tty_get_baud_rate(tty); | 353 | baud_rate = tty_get_baud_rate(tty); |
| 350 | 354 | ||
| 351 | priv->baud_rate = baud_rate; | 355 | priv->baud_rate = baud_rate; |
| @@ -568,6 +572,8 @@ static struct usb_serial_driver ch341_device = { | |||
| 568 | .usb_driver = &ch341_driver, | 572 | .usb_driver = &ch341_driver, |
| 569 | .num_ports = 1, | 573 | .num_ports = 1, |
| 570 | .open = ch341_open, | 574 | .open = ch341_open, |
| 575 | .dtr_rts = ch341_dtr_rts, | ||
| 576 | .carrier_raised = ch341_carrier_raised, | ||
| 571 | .close = ch341_close, | 577 | .close = ch341_close, |
| 572 | .ioctl = ch341_ioctl, | 578 | .ioctl = ch341_ioctl, |
| 573 | .set_termios = ch341_set_termios, | 579 | .set_termios = ch341_set_termios, |
diff --git a/drivers/usb/serial/console.c b/drivers/usb/serial/console.c index 19e24045b137..247b61bfb7f4 100644 --- a/drivers/usb/serial/console.c +++ b/drivers/usb/serial/console.c | |||
| @@ -169,7 +169,9 @@ static int usb_console_setup(struct console *co, char *options) | |||
| 169 | kfree(tty); | 169 | kfree(tty); |
| 170 | } | 170 | } |
| 171 | } | 171 | } |
| 172 | 172 | /* So we know not to kill the hardware on a hangup on this | |
| 173 | port. We have also bumped the use count by one so it won't go | ||
| 174 | idle */ | ||
| 173 | port->console = 1; | 175 | port->console = 1; |
| 174 | retval = 0; | 176 | retval = 0; |
| 175 | 177 | ||
| @@ -182,7 +184,7 @@ free_tty: | |||
| 182 | kfree(tty); | 184 | kfree(tty); |
| 183 | reset_open_count: | 185 | reset_open_count: |
| 184 | port->port.count = 0; | 186 | port->port.count = 0; |
| 185 | goto out; | 187 | goto out; |
| 186 | } | 188 | } |
| 187 | 189 | ||
| 188 | static void usb_console_write(struct console *co, | 190 | static void usb_console_write(struct console *co, |
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c index e8d5133ce9c8..16a154d3b2fe 100644 --- a/drivers/usb/serial/cp210x.c +++ b/drivers/usb/serial/cp210x.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Silicon Laboratories CP2101/CP2102 USB to RS232 serial adaptor driver | 2 | * Silicon Laboratories CP210x USB to RS232 serial adaptor driver |
| 3 | * | 3 | * |
| 4 | * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) | 4 | * Copyright (C) 2005 Craig Shelley (craig@microtron.org.uk) |
| 5 | * | 5 | * |
| @@ -27,44 +27,46 @@ | |||
| 27 | /* | 27 | /* |
| 28 | * Version Information | 28 | * Version Information |
| 29 | */ | 29 | */ |
| 30 | #define DRIVER_VERSION "v0.08" | 30 | #define DRIVER_VERSION "v0.09" |
| 31 | #define DRIVER_DESC "Silicon Labs CP2101/CP2102 RS232 serial adaptor driver" | 31 | #define DRIVER_DESC "Silicon Labs CP210x RS232 serial adaptor driver" |
| 32 | 32 | ||
| 33 | /* | 33 | /* |
| 34 | * Function Prototypes | 34 | * Function Prototypes |
| 35 | */ | 35 | */ |
| 36 | static int cp2101_open(struct tty_struct *, struct usb_serial_port *, | 36 | static int cp210x_open(struct tty_struct *, struct usb_serial_port *, |
| 37 | struct file *); | 37 | struct file *); |
| 38 | static void cp2101_cleanup(struct usb_serial_port *); | 38 | static void cp210x_cleanup(struct usb_serial_port *); |
| 39 | static void cp2101_close(struct tty_struct *, struct usb_serial_port *, | 39 | static void cp210x_close(struct usb_serial_port *); |
| 40 | struct file*); | 40 | static void cp210x_get_termios(struct tty_struct *, |
| 41 | static void cp2101_get_termios(struct tty_struct *, | ||
| 42 | struct usb_serial_port *port); | 41 | struct usb_serial_port *port); |
| 43 | static void cp2101_get_termios_port(struct usb_serial_port *port, | 42 | static void cp210x_get_termios_port(struct usb_serial_port *port, |
| 44 | unsigned int *cflagp, unsigned int *baudp); | 43 | unsigned int *cflagp, unsigned int *baudp); |
| 45 | static void cp2101_set_termios(struct tty_struct *, struct usb_serial_port *, | 44 | static void cp210x_set_termios(struct tty_struct *, struct usb_serial_port *, |
| 46 | struct ktermios*); | 45 | struct ktermios*); |
| 47 | static int cp2101_tiocmget(struct tty_struct *, struct file *); | 46 | static int cp210x_tiocmget(struct tty_struct *, struct file *); |
| 48 | static int cp2101_tiocmset(struct tty_struct *, struct file *, | 47 | static int cp210x_tiocmset(struct tty_struct *, struct file *, |
| 49 | unsigned int, unsigned int); | 48 | unsigned int, unsigned int); |
| 50 | static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *, | 49 | static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *, |
| 51 | unsigned int, unsigned int); | 50 | unsigned int, unsigned int); |
| 52 | static void cp2101_break_ctl(struct tty_struct *, int); | 51 | static void cp210x_break_ctl(struct tty_struct *, int); |
| 53 | static int cp2101_startup(struct usb_serial *); | 52 | static int cp210x_startup(struct usb_serial *); |
| 54 | static void cp2101_shutdown(struct usb_serial *); | 53 | static void cp210x_shutdown(struct usb_serial *); |
| 55 | 54 | ||
| 56 | static int debug; | 55 | static int debug; |
| 57 | 56 | ||
| 58 | static struct usb_device_id id_table [] = { | 57 | static struct usb_device_id id_table [] = { |
| 59 | { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ | 58 | { USB_DEVICE(0x0471, 0x066A) }, /* AKTAKOM ACE-1001 cable */ |
| 60 | { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ | 59 | { USB_DEVICE(0x0489, 0xE000) }, /* Pirelli Broadband S.p.A, DP-L10 SIP/GSM Mobile */ |
| 60 | { USB_DEVICE(0x0745, 0x1000) }, /* CipherLab USB CCD Barcode Scanner 1000 */ | ||
| 61 | { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ | 61 | { USB_DEVICE(0x08e6, 0x5501) }, /* Gemalto Prox-PU/CU contactless smartcard reader */ |
| 62 | { USB_DEVICE(0x08FD, 0x000A) }, /* Digianswer A/S , ZigBee/802.15.4 MAC Device */ | ||
| 62 | { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ | 63 | { USB_DEVICE(0x0FCF, 0x1003) }, /* Dynastream ANT development board */ |
| 63 | { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ | 64 | { USB_DEVICE(0x0FCF, 0x1004) }, /* Dynastream ANT2USB */ |
| 64 | { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ | 65 | { USB_DEVICE(0x0FCF, 0x1006) }, /* Dynastream ANT development board */ |
| 65 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ | 66 | { USB_DEVICE(0x10A6, 0xAA26) }, /* Knock-off DCU-11 cable */ |
| 66 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ | 67 | { USB_DEVICE(0x10AB, 0x10C5) }, /* Siemens MC60 Cable */ |
| 67 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ | 68 | { USB_DEVICE(0x10B5, 0xAC70) }, /* Nokia CA-42 USB */ |
| 69 | { USB_DEVICE(0x10C4, 0x0F91) }, /* Vstabi */ | ||
| 68 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ | 70 | { USB_DEVICE(0x10C4, 0x800A) }, /* SPORTident BSM7-D-USB main station */ |
| 69 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ | 71 | { USB_DEVICE(0x10C4, 0x803B) }, /* Pololu USB-serial converter */ |
| 70 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ | 72 | { USB_DEVICE(0x10C4, 0x8053) }, /* Enfora EDG1228 */ |
| @@ -85,10 +87,12 @@ static struct usb_device_id id_table [] = { | |||
| 85 | { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ | 87 | { USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */ |
| 86 | { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ | 88 | { USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */ |
| 87 | { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ | 89 | { USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */ |
| 90 | { USB_DEVICE(0x10C4, 0x81F2) }, /* C1007 HF band RFID controller */ | ||
| 88 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ | 91 | { USB_DEVICE(0x10C4, 0x8218) }, /* Lipowsky Industrie Elektronik GmbH, HARP-1 */ |
| 89 | { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ | 92 | { USB_DEVICE(0x10C4, 0x822B) }, /* Modem EDGE(GSM) Comander 2 */ |
| 90 | { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ | 93 | { USB_DEVICE(0x10C4, 0x826B) }, /* Cygnal Integrated Products, Inc., Fasttrax GPS demostration module */ |
| 91 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ | 94 | { USB_DEVICE(0x10c4, 0x8293) }, /* Telegesys ETRX2USB */ |
| 95 | { USB_DEVICE(0x10C4, 0x82F9) }, /* Procyon AVS */ | ||
| 92 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ | 96 | { USB_DEVICE(0x10C4, 0x8341) }, /* Siemens MC35PU GPRS Modem */ |
| 93 | { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ | 97 | { USB_DEVICE(0x10C4, 0x83A8) }, /* Amber Wireless AMB2560 */ |
| 94 | { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ | 98 | { USB_DEVICE(0x10C4, 0x846E) }, /* BEI USB Sensor Interface (VCP) */ |
| @@ -99,7 +103,9 @@ static struct usb_device_id id_table [] = { | |||
| 99 | { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ | 103 | { USB_DEVICE(0x10C4, 0xF003) }, /* Elan Digital Systems USBpulse100 */ |
| 100 | { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ | 104 | { USB_DEVICE(0x10C4, 0xF004) }, /* Elan Digital Systems USBcount50 */ |
| 101 | { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ | 105 | { USB_DEVICE(0x10C5, 0xEA61) }, /* Silicon Labs MobiData GPRS USB Modem */ |
| 106 | { USB_DEVICE(0x10CE, 0xEA6A) }, /* Silicon Labs MobiData GPRS USB Modem 100EU */ | ||
| 102 | { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ | 107 | { USB_DEVICE(0x13AD, 0x9999) }, /* Baltech card reader */ |
| 108 | { USB_DEVICE(0x1555, 0x0004) }, /* Owen AC4 USB-RS485 Converter */ | ||
| 103 | { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ | 109 | { USB_DEVICE(0x166A, 0x0303) }, /* Clipsal 5500PCU C-Bus USB interface */ |
| 104 | { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ | 110 | { USB_DEVICE(0x16D6, 0x0001) }, /* Jablotron serial interface */ |
| 105 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ | 111 | { USB_DEVICE(0x18EF, 0xE00F) }, /* ELV USB-I2C-Interface */ |
| @@ -108,53 +114,70 @@ static struct usb_device_id id_table [] = { | |||
| 108 | 114 | ||
| 109 | MODULE_DEVICE_TABLE(usb, id_table); | 115 | MODULE_DEVICE_TABLE(usb, id_table); |
| 110 | 116 | ||
| 111 | static struct usb_driver cp2101_driver = { | 117 | static struct usb_driver cp210x_driver = { |
| 112 | .name = "cp2101", | 118 | .name = "cp210x", |
| 113 | .probe = usb_serial_probe, | 119 | .probe = usb_serial_probe, |
| 114 | .disconnect = usb_serial_disconnect, | 120 | .disconnect = usb_serial_disconnect, |
| 115 | .id_table = id_table, | 121 | .id_table = id_table, |
| 116 | .no_dynamic_id = 1, | 122 | .no_dynamic_id = 1, |
| 117 | }; | 123 | }; |
| 118 | 124 | ||
| 119 | static struct usb_serial_driver cp2101_device = { | 125 | static struct usb_serial_driver cp210x_device = { |
| 120 | .driver = { | 126 | .driver = { |
| 121 | .owner = THIS_MODULE, | 127 | .owner = THIS_MODULE, |
| 122 | .name = "cp2101", | 128 | .name = "cp210x", |
| 123 | }, | 129 | }, |
| 124 | .usb_driver = &cp2101_driver, | 130 | .usb_driver = &cp210x_driver, |
| 125 | .id_table = id_table, | 131 | .id_table = id_table, |
| 126 | .num_ports = 1, | 132 | .num_ports = 1, |
| 127 | .open = cp2101_open, | 133 | .open = cp210x_open, |
| 128 | .close = cp2101_close, | 134 | .close = cp210x_close, |
| 129 | .break_ctl = cp2101_break_ctl, | 135 | .break_ctl = cp210x_break_ctl, |
| 130 | .set_termios = cp2101_set_termios, | 136 | .set_termios = cp210x_set_termios, |
| 131 | .tiocmget = cp2101_tiocmget, | 137 | .tiocmget = cp210x_tiocmget, |
| 132 | .tiocmset = cp2101_tiocmset, | 138 | .tiocmset = cp210x_tiocmset, |
| 133 | .attach = cp2101_startup, | 139 | .attach = cp210x_startup, |
| 134 | .shutdown = cp2101_shutdown, | 140 | .shutdown = cp210x_shutdown, |
| 135 | }; | 141 | }; |
| 136 | 142 | ||
| 137 | /* Config request types */ | 143 | /* Config request types */ |
| 138 | #define REQTYPE_HOST_TO_DEVICE 0x41 | 144 | #define REQTYPE_HOST_TO_DEVICE 0x41 |
| 139 | #define REQTYPE_DEVICE_TO_HOST 0xc1 | 145 | #define REQTYPE_DEVICE_TO_HOST 0xc1 |
| 140 | 146 | ||
| 141 | /* Config SET requests. To GET, add 1 to the request number */ | 147 | /* Config request codes */ |
| 142 | #define CP2101_UART 0x00 /* Enable / Disable */ | 148 | #define CP210X_IFC_ENABLE 0x00 |
| 143 | #define CP2101_BAUDRATE 0x01 /* (BAUD_RATE_GEN_FREQ / baudrate) */ | 149 | #define CP210X_SET_BAUDDIV 0x01 |
| 144 | #define CP2101_BITS 0x03 /* 0x(0)(databits)(parity)(stopbits) */ | 150 | #define CP210X_GET_BAUDDIV 0x02 |
| 145 | #define CP2101_BREAK 0x05 /* On / Off */ | 151 | #define CP210X_SET_LINE_CTL 0x03 |
| 146 | #define CP2101_CONTROL 0x07 /* Flow control line states */ | 152 | #define CP210X_GET_LINE_CTL 0x04 |
| 147 | #define CP2101_MODEMCTL 0x13 /* Modem controls */ | 153 | #define CP210X_SET_BREAK 0x05 |
| 148 | #define CP2101_CONFIG_6 0x19 /* 6 bytes of config data ??? */ | 154 | #define CP210X_IMM_CHAR 0x06 |
| 149 | 155 | #define CP210X_SET_MHS 0x07 | |
| 150 | /* CP2101_UART */ | 156 | #define CP210X_GET_MDMSTS 0x08 |
| 157 | #define CP210X_SET_XON 0x09 | ||
| 158 | #define CP210X_SET_XOFF 0x0A | ||
| 159 | #define CP210X_SET_EVENTMASK 0x0B | ||
| 160 | #define CP210X_GET_EVENTMASK 0x0C | ||
| 161 | #define CP210X_SET_CHAR 0x0D | ||
| 162 | #define CP210X_GET_CHARS 0x0E | ||
| 163 | #define CP210X_GET_PROPS 0x0F | ||
| 164 | #define CP210X_GET_COMM_STATUS 0x10 | ||
| 165 | #define CP210X_RESET 0x11 | ||
| 166 | #define CP210X_PURGE 0x12 | ||
| 167 | #define CP210X_SET_FLOW 0x13 | ||
| 168 | #define CP210X_GET_FLOW 0x14 | ||
| 169 | #define CP210X_EMBED_EVENTS 0x15 | ||
| 170 | #define CP210X_GET_EVENTSTATE 0x16 | ||
| 171 | #define CP210X_SET_CHARS 0x19 | ||
| 172 | |||
| 173 | /* CP210X_IFC_ENABLE */ | ||
| 151 | #define UART_ENABLE 0x0001 | 174 | #define UART_ENABLE 0x0001 |
| 152 | #define UART_DISABLE 0x0000 | 175 | #define UART_DISABLE 0x0000 |
| 153 | 176 | ||
| 154 | /* CP2101_BAUDRATE */ | 177 | /* CP210X_(SET|GET)_BAUDDIV */ |
| 155 | #define BAUD_RATE_GEN_FREQ 0x384000 | 178 | #define BAUD_RATE_GEN_FREQ 0x384000 |
| 156 | 179 | ||
| 157 | /* CP2101_BITS */ | 180 | /* CP210X_(SET|GET)_LINE_CTL */ |
| 158 | #define BITS_DATA_MASK 0X0f00 | 181 | #define BITS_DATA_MASK 0X0f00 |
| 159 | #define BITS_DATA_5 0X0500 | 182 | #define BITS_DATA_5 0X0500 |
| 160 | #define BITS_DATA_6 0X0600 | 183 | #define BITS_DATA_6 0X0600 |
| @@ -174,11 +197,11 @@ static struct usb_serial_driver cp2101_device = { | |||
| 174 | #define BITS_STOP_1_5 0x0001 | 197 | #define BITS_STOP_1_5 0x0001 |
| 175 | #define BITS_STOP_2 0x0002 | 198 | #define BITS_STOP_2 0x0002 |
| 176 | 199 | ||
| 177 | /* CP2101_BREAK */ | 200 | /* CP210X_SET_BREAK */ |
| 178 | #define BREAK_ON 0x0000 | 201 | #define BREAK_ON 0x0000 |
| 179 | #define BREAK_OFF 0x0001 | 202 | #define BREAK_OFF 0x0001 |
| 180 | 203 | ||
| 181 | /* CP2101_CONTROL */ | 204 | /* CP210X_(SET_MHS|GET_MDMSTS) */ |
| 182 | #define CONTROL_DTR 0x0001 | 205 | #define CONTROL_DTR 0x0001 |
| 183 | #define CONTROL_RTS 0x0002 | 206 | #define CONTROL_RTS 0x0002 |
| 184 | #define CONTROL_CTS 0x0010 | 207 | #define CONTROL_CTS 0x0010 |
| @@ -189,13 +212,13 @@ static struct usb_serial_driver cp2101_device = { | |||
| 189 | #define CONTROL_WRITE_RTS 0x0200 | 212 | #define CONTROL_WRITE_RTS 0x0200 |
| 190 | 213 | ||
| 191 | /* | 214 | /* |
| 192 | * cp2101_get_config | 215 | * cp210x_get_config |
| 193 | * Reads from the CP2101 configuration registers | 216 | * Reads from the CP210x configuration registers |
| 194 | * 'size' is specified in bytes. | 217 | * 'size' is specified in bytes. |
| 195 | * 'data' is a pointer to a pre-allocated array of integers large | 218 | * 'data' is a pointer to a pre-allocated array of integers large |
| 196 | * enough to hold 'size' bytes (with 4 bytes to each integer) | 219 | * enough to hold 'size' bytes (with 4 bytes to each integer) |
| 197 | */ | 220 | */ |
| 198 | static int cp2101_get_config(struct usb_serial_port *port, u8 request, | 221 | static int cp210x_get_config(struct usb_serial_port *port, u8 request, |
| 199 | unsigned int *data, int size) | 222 | unsigned int *data, int size) |
| 200 | { | 223 | { |
| 201 | struct usb_serial *serial = port->serial; | 224 | struct usb_serial *serial = port->serial; |
| @@ -211,9 +234,6 @@ static int cp2101_get_config(struct usb_serial_port *port, u8 request, | |||
| 211 | return -ENOMEM; | 234 | return -ENOMEM; |
| 212 | } | 235 | } |
| 213 | 236 | ||
| 214 | /* For get requests, the request number must be incremented */ | ||
| 215 | request++; | ||
| 216 | |||
| 217 | /* Issue the request, attempting to read 'size' bytes */ | 237 | /* Issue the request, attempting to read 'size' bytes */ |
| 218 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), | 238 | result = usb_control_msg(serial->dev, usb_rcvctrlpipe(serial->dev, 0), |
| 219 | request, REQTYPE_DEVICE_TO_HOST, 0x0000, | 239 | request, REQTYPE_DEVICE_TO_HOST, 0x0000, |
| @@ -236,12 +256,12 @@ static int cp2101_get_config(struct usb_serial_port *port, u8 request, | |||
| 236 | } | 256 | } |
| 237 | 257 | ||
| 238 | /* | 258 | /* |
| 239 | * cp2101_set_config | 259 | * cp210x_set_config |
| 240 | * Writes to the CP2101 configuration registers | 260 | * Writes to the CP210x configuration registers |
| 241 | * Values less than 16 bits wide are sent directly | 261 | * Values less than 16 bits wide are sent directly |
| 242 | * 'size' is specified in bytes. | 262 | * 'size' is specified in bytes. |
| 243 | */ | 263 | */ |
| 244 | static int cp2101_set_config(struct usb_serial_port *port, u8 request, | 264 | static int cp210x_set_config(struct usb_serial_port *port, u8 request, |
| 245 | unsigned int *data, int size) | 265 | unsigned int *data, int size) |
| 246 | { | 266 | { |
| 247 | struct usb_serial *serial = port->serial; | 267 | struct usb_serial *serial = port->serial; |
| @@ -292,21 +312,21 @@ static int cp2101_set_config(struct usb_serial_port *port, u8 request, | |||
| 292 | } | 312 | } |
| 293 | 313 | ||
| 294 | /* | 314 | /* |
| 295 | * cp2101_set_config_single | 315 | * cp210x_set_config_single |
| 296 | * Convenience function for calling cp2101_set_config on single data values | 316 | * Convenience function for calling cp210x_set_config on single data values |
| 297 | * without requiring an integer pointer | 317 | * without requiring an integer pointer |
| 298 | */ | 318 | */ |
| 299 | static inline int cp2101_set_config_single(struct usb_serial_port *port, | 319 | static inline int cp210x_set_config_single(struct usb_serial_port *port, |
| 300 | u8 request, unsigned int data) | 320 | u8 request, unsigned int data) |
| 301 | { | 321 | { |
| 302 | return cp2101_set_config(port, request, &data, 2); | 322 | return cp210x_set_config(port, request, &data, 2); |
| 303 | } | 323 | } |
| 304 | 324 | ||
| 305 | /* | 325 | /* |
| 306 | * cp2101_quantise_baudrate | 326 | * cp210x_quantise_baudrate |
| 307 | * Quantises the baud rate as per AN205 Table 1 | 327 | * Quantises the baud rate as per AN205 Table 1 |
| 308 | */ | 328 | */ |
| 309 | static unsigned int cp2101_quantise_baudrate(unsigned int baud) { | 329 | static unsigned int cp210x_quantise_baudrate(unsigned int baud) { |
| 310 | if (baud <= 56) baud = 0; | 330 | if (baud <= 56) baud = 0; |
| 311 | else if (baud <= 300) baud = 300; | 331 | else if (baud <= 300) baud = 300; |
| 312 | else if (baud <= 600) baud = 600; | 332 | else if (baud <= 600) baud = 600; |
| @@ -343,7 +363,7 @@ static unsigned int cp2101_quantise_baudrate(unsigned int baud) { | |||
| 343 | return baud; | 363 | return baud; |
| 344 | } | 364 | } |
| 345 | 365 | ||
| 346 | static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, | 366 | static int cp210x_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 347 | struct file *filp) | 367 | struct file *filp) |
| 348 | { | 368 | { |
| 349 | struct usb_serial *serial = port->serial; | 369 | struct usb_serial *serial = port->serial; |
| @@ -351,7 +371,7 @@ static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 351 | 371 | ||
| 352 | dbg("%s - port %d", __func__, port->number); | 372 | dbg("%s - port %d", __func__, port->number); |
| 353 | 373 | ||
| 354 | if (cp2101_set_config_single(port, CP2101_UART, UART_ENABLE)) { | 374 | if (cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_ENABLE)) { |
| 355 | dev_err(&port->dev, "%s - Unable to enable UART\n", | 375 | dev_err(&port->dev, "%s - Unable to enable UART\n", |
| 356 | __func__); | 376 | __func__); |
| 357 | return -EPROTO; | 377 | return -EPROTO; |
| @@ -373,17 +393,17 @@ static int cp2101_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 373 | } | 393 | } |
| 374 | 394 | ||
| 375 | /* Configure the termios structure */ | 395 | /* Configure the termios structure */ |
| 376 | cp2101_get_termios(tty, port); | 396 | cp210x_get_termios(tty, port); |
| 377 | 397 | ||
| 378 | /* Set the DTR and RTS pins low */ | 398 | /* Set the DTR and RTS pins low */ |
| 379 | cp2101_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data | 399 | cp210x_tiocmset_port(tty ? (struct usb_serial_port *) tty->driver_data |
| 380 | : port, | 400 | : port, |
| 381 | NULL, TIOCM_DTR | TIOCM_RTS, 0); | 401 | NULL, TIOCM_DTR | TIOCM_RTS, 0); |
| 382 | 402 | ||
| 383 | return 0; | 403 | return 0; |
| 384 | } | 404 | } |
| 385 | 405 | ||
| 386 | static void cp2101_cleanup(struct usb_serial_port *port) | 406 | static void cp210x_cleanup(struct usb_serial_port *port) |
| 387 | { | 407 | { |
| 388 | struct usb_serial *serial = port->serial; | 408 | struct usb_serial *serial = port->serial; |
| 389 | 409 | ||
| @@ -398,8 +418,7 @@ static void cp2101_cleanup(struct usb_serial_port *port) | |||
| 398 | } | 418 | } |
| 399 | } | 419 | } |
| 400 | 420 | ||
| 401 | static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, | 421 | static void cp210x_close(struct usb_serial_port *port) |
| 402 | struct file *filp) | ||
| 403 | { | 422 | { |
| 404 | dbg("%s - port %d", __func__, port->number); | 423 | dbg("%s - port %d", __func__, port->number); |
| 405 | 424 | ||
| @@ -410,23 +429,23 @@ static void cp2101_close(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 410 | 429 | ||
| 411 | mutex_lock(&port->serial->disc_mutex); | 430 | mutex_lock(&port->serial->disc_mutex); |
| 412 | if (!port->serial->disconnected) | 431 | if (!port->serial->disconnected) |
| 413 | cp2101_set_config_single(port, CP2101_UART, UART_DISABLE); | 432 | cp210x_set_config_single(port, CP210X_IFC_ENABLE, UART_DISABLE); |
| 414 | mutex_unlock(&port->serial->disc_mutex); | 433 | mutex_unlock(&port->serial->disc_mutex); |
| 415 | } | 434 | } |
| 416 | 435 | ||
| 417 | /* | 436 | /* |
| 418 | * cp2101_get_termios | 437 | * cp210x_get_termios |
| 419 | * Reads the baud rate, data bits, parity, stop bits and flow control mode | 438 | * Reads the baud rate, data bits, parity, stop bits and flow control mode |
| 420 | * from the device, corrects any unsupported values, and configures the | 439 | * from the device, corrects any unsupported values, and configures the |
| 421 | * termios structure to reflect the state of the device | 440 | * termios structure to reflect the state of the device |
| 422 | */ | 441 | */ |
| 423 | static void cp2101_get_termios(struct tty_struct *tty, | 442 | static void cp210x_get_termios(struct tty_struct *tty, |
| 424 | struct usb_serial_port *port) | 443 | struct usb_serial_port *port) |
| 425 | { | 444 | { |
| 426 | unsigned int baud; | 445 | unsigned int baud; |
| 427 | 446 | ||
| 428 | if (tty) { | 447 | if (tty) { |
| 429 | cp2101_get_termios_port(tty->driver_data, | 448 | cp210x_get_termios_port(tty->driver_data, |
| 430 | &tty->termios->c_cflag, &baud); | 449 | &tty->termios->c_cflag, &baud); |
| 431 | tty_encode_baud_rate(tty, baud, baud); | 450 | tty_encode_baud_rate(tty, baud, baud); |
| 432 | } | 451 | } |
| @@ -434,15 +453,15 @@ static void cp2101_get_termios(struct tty_struct *tty, | |||
| 434 | else { | 453 | else { |
| 435 | unsigned int cflag; | 454 | unsigned int cflag; |
| 436 | cflag = 0; | 455 | cflag = 0; |
| 437 | cp2101_get_termios_port(port, &cflag, &baud); | 456 | cp210x_get_termios_port(port, &cflag, &baud); |
| 438 | } | 457 | } |
| 439 | } | 458 | } |
| 440 | 459 | ||
| 441 | /* | 460 | /* |
| 442 | * cp2101_get_termios_port | 461 | * cp210x_get_termios_port |
| 443 | * This is the heart of cp2101_get_termios which always uses a &usb_serial_port. | 462 | * This is the heart of cp210x_get_termios which always uses a &usb_serial_port. |
| 444 | */ | 463 | */ |
| 445 | static void cp2101_get_termios_port(struct usb_serial_port *port, | 464 | static void cp210x_get_termios_port(struct usb_serial_port *port, |
| 446 | unsigned int *cflagp, unsigned int *baudp) | 465 | unsigned int *cflagp, unsigned int *baudp) |
| 447 | { | 466 | { |
| 448 | unsigned int cflag, modem_ctl[4]; | 467 | unsigned int cflag, modem_ctl[4]; |
| @@ -451,17 +470,17 @@ static void cp2101_get_termios_port(struct usb_serial_port *port, | |||
| 451 | 470 | ||
| 452 | dbg("%s - port %d", __func__, port->number); | 471 | dbg("%s - port %d", __func__, port->number); |
| 453 | 472 | ||
| 454 | cp2101_get_config(port, CP2101_BAUDRATE, &baud, 2); | 473 | cp210x_get_config(port, CP210X_GET_BAUDDIV, &baud, 2); |
| 455 | /* Convert to baudrate */ | 474 | /* Convert to baudrate */ |
| 456 | if (baud) | 475 | if (baud) |
| 457 | baud = cp2101_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); | 476 | baud = cp210x_quantise_baudrate((BAUD_RATE_GEN_FREQ + baud/2)/ baud); |
| 458 | 477 | ||
| 459 | dbg("%s - baud rate = %d", __func__, baud); | 478 | dbg("%s - baud rate = %d", __func__, baud); |
| 460 | *baudp = baud; | 479 | *baudp = baud; |
| 461 | 480 | ||
| 462 | cflag = *cflagp; | 481 | cflag = *cflagp; |
| 463 | 482 | ||
| 464 | cp2101_get_config(port, CP2101_BITS, &bits, 2); | 483 | cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); |
| 465 | cflag &= ~CSIZE; | 484 | cflag &= ~CSIZE; |
| 466 | switch (bits & BITS_DATA_MASK) { | 485 | switch (bits & BITS_DATA_MASK) { |
| 467 | case BITS_DATA_5: | 486 | case BITS_DATA_5: |
| @@ -486,14 +505,14 @@ static void cp2101_get_termios_port(struct usb_serial_port *port, | |||
| 486 | cflag |= CS8; | 505 | cflag |= CS8; |
| 487 | bits &= ~BITS_DATA_MASK; | 506 | bits &= ~BITS_DATA_MASK; |
| 488 | bits |= BITS_DATA_8; | 507 | bits |= BITS_DATA_8; |
| 489 | cp2101_set_config(port, CP2101_BITS, &bits, 2); | 508 | cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); |
| 490 | break; | 509 | break; |
| 491 | default: | 510 | default: |
| 492 | dbg("%s - Unknown number of data bits, using 8", __func__); | 511 | dbg("%s - Unknown number of data bits, using 8", __func__); |
| 493 | cflag |= CS8; | 512 | cflag |= CS8; |
| 494 | bits &= ~BITS_DATA_MASK; | 513 | bits &= ~BITS_DATA_MASK; |
| 495 | bits |= BITS_DATA_8; | 514 | bits |= BITS_DATA_8; |
| 496 | cp2101_set_config(port, CP2101_BITS, &bits, 2); | 515 | cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); |
| 497 | break; | 516 | break; |
| 498 | } | 517 | } |
| 499 | 518 | ||
| @@ -516,20 +535,20 @@ static void cp2101_get_termios_port(struct usb_serial_port *port, | |||
| 516 | __func__); | 535 | __func__); |
| 517 | cflag &= ~PARENB; | 536 | cflag &= ~PARENB; |
| 518 | bits &= ~BITS_PARITY_MASK; | 537 | bits &= ~BITS_PARITY_MASK; |
| 519 | cp2101_set_config(port, CP2101_BITS, &bits, 2); | 538 | cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); |
| 520 | break; | 539 | break; |
| 521 | case BITS_PARITY_SPACE: | 540 | case BITS_PARITY_SPACE: |
| 522 | dbg("%s - parity = SPACE (not supported, disabling parity)", | 541 | dbg("%s - parity = SPACE (not supported, disabling parity)", |
| 523 | __func__); | 542 | __func__); |
| 524 | cflag &= ~PARENB; | 543 | cflag &= ~PARENB; |
| 525 | bits &= ~BITS_PARITY_MASK; | 544 | bits &= ~BITS_PARITY_MASK; |
| 526 | cp2101_set_config(port, CP2101_BITS, &bits, 2); | 545 | cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); |
| 527 | break; | 546 | break; |
| 528 | default: | 547 | default: |
| 529 | dbg("%s - Unknown parity mode, disabling parity", __func__); | 548 | dbg("%s - Unknown parity mode, disabling parity", __func__); |
| 530 | cflag &= ~PARENB; | 549 | cflag &= ~PARENB; |
| 531 | bits &= ~BITS_PARITY_MASK; | 550 | bits &= ~BITS_PARITY_MASK; |
| 532 | cp2101_set_config(port, CP2101_BITS, &bits, 2); | 551 | cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); |
| 533 | break; | 552 | break; |
| 534 | } | 553 | } |
| 535 | 554 | ||
| @@ -542,7 +561,7 @@ static void cp2101_get_termios_port(struct usb_serial_port *port, | |||
| 542 | dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", | 561 | dbg("%s - stop bits = 1.5 (not supported, using 1 stop bit)", |
| 543 | __func__); | 562 | __func__); |
| 544 | bits &= ~BITS_STOP_MASK; | 563 | bits &= ~BITS_STOP_MASK; |
| 545 | cp2101_set_config(port, CP2101_BITS, &bits, 2); | 564 | cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); |
| 546 | break; | 565 | break; |
| 547 | case BITS_STOP_2: | 566 | case BITS_STOP_2: |
| 548 | dbg("%s - stop bits = 2", __func__); | 567 | dbg("%s - stop bits = 2", __func__); |
| @@ -552,11 +571,11 @@ static void cp2101_get_termios_port(struct usb_serial_port *port, | |||
| 552 | dbg("%s - Unknown number of stop bits, using 1 stop bit", | 571 | dbg("%s - Unknown number of stop bits, using 1 stop bit", |
| 553 | __func__); | 572 | __func__); |
| 554 | bits &= ~BITS_STOP_MASK; | 573 | bits &= ~BITS_STOP_MASK; |
| 555 | cp2101_set_config(port, CP2101_BITS, &bits, 2); | 574 | cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2); |
| 556 | break; | 575 | break; |
| 557 | } | 576 | } |
| 558 | 577 | ||
| 559 | cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); | 578 | cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16); |
| 560 | if (modem_ctl[0] & 0x0008) { | 579 | if (modem_ctl[0] & 0x0008) { |
| 561 | dbg("%s - flow control = CRTSCTS", __func__); | 580 | dbg("%s - flow control = CRTSCTS", __func__); |
| 562 | cflag |= CRTSCTS; | 581 | cflag |= CRTSCTS; |
| @@ -568,7 +587,7 @@ static void cp2101_get_termios_port(struct usb_serial_port *port, | |||
| 568 | *cflagp = cflag; | 587 | *cflagp = cflag; |
| 569 | } | 588 | } |
| 570 | 589 | ||
| 571 | static void cp2101_set_termios(struct tty_struct *tty, | 590 | static void cp210x_set_termios(struct tty_struct *tty, |
| 572 | struct usb_serial_port *port, struct ktermios *old_termios) | 591 | struct usb_serial_port *port, struct ktermios *old_termios) |
| 573 | { | 592 | { |
| 574 | unsigned int cflag, old_cflag; | 593 | unsigned int cflag, old_cflag; |
| @@ -583,13 +602,13 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
| 583 | tty->termios->c_cflag &= ~CMSPAR; | 602 | tty->termios->c_cflag &= ~CMSPAR; |
| 584 | cflag = tty->termios->c_cflag; | 603 | cflag = tty->termios->c_cflag; |
| 585 | old_cflag = old_termios->c_cflag; | 604 | old_cflag = old_termios->c_cflag; |
| 586 | baud = cp2101_quantise_baudrate(tty_get_baud_rate(tty)); | 605 | baud = cp210x_quantise_baudrate(tty_get_baud_rate(tty)); |
| 587 | 606 | ||
| 588 | /* If the baud rate is to be updated*/ | 607 | /* If the baud rate is to be updated*/ |
| 589 | if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { | 608 | if (baud != tty_termios_baud_rate(old_termios) && baud != 0) { |
| 590 | dbg("%s - Setting baud rate to %d baud", __func__, | 609 | dbg("%s - Setting baud rate to %d baud", __func__, |
| 591 | baud); | 610 | baud); |
| 592 | if (cp2101_set_config_single(port, CP2101_BAUDRATE, | 611 | if (cp210x_set_config_single(port, CP210X_SET_BAUDDIV, |
| 593 | ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { | 612 | ((BAUD_RATE_GEN_FREQ + baud/2) / baud))) { |
| 594 | dbg("Baud rate requested not supported by device\n"); | 613 | dbg("Baud rate requested not supported by device\n"); |
| 595 | baud = tty_termios_baud_rate(old_termios); | 614 | baud = tty_termios_baud_rate(old_termios); |
| @@ -600,7 +619,7 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
| 600 | 619 | ||
| 601 | /* If the number of data bits is to be updated */ | 620 | /* If the number of data bits is to be updated */ |
| 602 | if ((cflag & CSIZE) != (old_cflag & CSIZE)) { | 621 | if ((cflag & CSIZE) != (old_cflag & CSIZE)) { |
| 603 | cp2101_get_config(port, CP2101_BITS, &bits, 2); | 622 | cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); |
| 604 | bits &= ~BITS_DATA_MASK; | 623 | bits &= ~BITS_DATA_MASK; |
| 605 | switch (cflag & CSIZE) { | 624 | switch (cflag & CSIZE) { |
| 606 | case CS5: | 625 | case CS5: |
| @@ -624,19 +643,19 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
| 624 | dbg("%s - data bits = 9", __func__); | 643 | dbg("%s - data bits = 9", __func__); |
| 625 | break;*/ | 644 | break;*/ |
| 626 | default: | 645 | default: |
| 627 | dbg("cp2101 driver does not " | 646 | dbg("cp210x driver does not " |
| 628 | "support the number of bits requested," | 647 | "support the number of bits requested," |
| 629 | " using 8 bit mode\n"); | 648 | " using 8 bit mode\n"); |
| 630 | bits |= BITS_DATA_8; | 649 | bits |= BITS_DATA_8; |
| 631 | break; | 650 | break; |
| 632 | } | 651 | } |
| 633 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) | 652 | if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) |
| 634 | dbg("Number of data bits requested " | 653 | dbg("Number of data bits requested " |
| 635 | "not supported by device\n"); | 654 | "not supported by device\n"); |
| 636 | } | 655 | } |
| 637 | 656 | ||
| 638 | if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { | 657 | if ((cflag & (PARENB|PARODD)) != (old_cflag & (PARENB|PARODD))) { |
| 639 | cp2101_get_config(port, CP2101_BITS, &bits, 2); | 658 | cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); |
| 640 | bits &= ~BITS_PARITY_MASK; | 659 | bits &= ~BITS_PARITY_MASK; |
| 641 | if (cflag & PARENB) { | 660 | if (cflag & PARENB) { |
| 642 | if (cflag & PARODD) { | 661 | if (cflag & PARODD) { |
| @@ -647,13 +666,13 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
| 647 | dbg("%s - parity = EVEN", __func__); | 666 | dbg("%s - parity = EVEN", __func__); |
| 648 | } | 667 | } |
| 649 | } | 668 | } |
| 650 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) | 669 | if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) |
| 651 | dbg("Parity mode not supported " | 670 | dbg("Parity mode not supported " |
| 652 | "by device\n"); | 671 | "by device\n"); |
| 653 | } | 672 | } |
| 654 | 673 | ||
| 655 | if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { | 674 | if ((cflag & CSTOPB) != (old_cflag & CSTOPB)) { |
| 656 | cp2101_get_config(port, CP2101_BITS, &bits, 2); | 675 | cp210x_get_config(port, CP210X_GET_LINE_CTL, &bits, 2); |
| 657 | bits &= ~BITS_STOP_MASK; | 676 | bits &= ~BITS_STOP_MASK; |
| 658 | if (cflag & CSTOPB) { | 677 | if (cflag & CSTOPB) { |
| 659 | bits |= BITS_STOP_2; | 678 | bits |= BITS_STOP_2; |
| @@ -662,13 +681,13 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
| 662 | bits |= BITS_STOP_1; | 681 | bits |= BITS_STOP_1; |
| 663 | dbg("%s - stop bits = 1", __func__); | 682 | dbg("%s - stop bits = 1", __func__); |
| 664 | } | 683 | } |
| 665 | if (cp2101_set_config(port, CP2101_BITS, &bits, 2)) | 684 | if (cp210x_set_config(port, CP210X_SET_LINE_CTL, &bits, 2)) |
| 666 | dbg("Number of stop bits requested " | 685 | dbg("Number of stop bits requested " |
| 667 | "not supported by device\n"); | 686 | "not supported by device\n"); |
| 668 | } | 687 | } |
| 669 | 688 | ||
| 670 | if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { | 689 | if ((cflag & CRTSCTS) != (old_cflag & CRTSCTS)) { |
| 671 | cp2101_get_config(port, CP2101_MODEMCTL, modem_ctl, 16); | 690 | cp210x_get_config(port, CP210X_GET_FLOW, modem_ctl, 16); |
| 672 | dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", | 691 | dbg("%s - read modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", |
| 673 | __func__, modem_ctl[0], modem_ctl[1], | 692 | __func__, modem_ctl[0], modem_ctl[1], |
| 674 | modem_ctl[2], modem_ctl[3]); | 693 | modem_ctl[2], modem_ctl[3]); |
| @@ -688,19 +707,19 @@ static void cp2101_set_termios(struct tty_struct *tty, | |||
| 688 | dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", | 707 | dbg("%s - write modem controls = 0x%.4x 0x%.4x 0x%.4x 0x%.4x", |
| 689 | __func__, modem_ctl[0], modem_ctl[1], | 708 | __func__, modem_ctl[0], modem_ctl[1], |
| 690 | modem_ctl[2], modem_ctl[3]); | 709 | modem_ctl[2], modem_ctl[3]); |
| 691 | cp2101_set_config(port, CP2101_MODEMCTL, modem_ctl, 16); | 710 | cp210x_set_config(port, CP210X_SET_FLOW, modem_ctl, 16); |
| 692 | } | 711 | } |
| 693 | 712 | ||
| 694 | } | 713 | } |
| 695 | 714 | ||
| 696 | static int cp2101_tiocmset (struct tty_struct *tty, struct file *file, | 715 | static int cp210x_tiocmset (struct tty_struct *tty, struct file *file, |
| 697 | unsigned int set, unsigned int clear) | 716 | unsigned int set, unsigned int clear) |
| 698 | { | 717 | { |
| 699 | struct usb_serial_port *port = tty->driver_data; | 718 | struct usb_serial_port *port = tty->driver_data; |
| 700 | return cp2101_tiocmset_port(port, file, set, clear); | 719 | return cp210x_tiocmset_port(port, file, set, clear); |
| 701 | } | 720 | } |
| 702 | 721 | ||
| 703 | static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file, | 722 | static int cp210x_tiocmset_port(struct usb_serial_port *port, struct file *file, |
| 704 | unsigned int set, unsigned int clear) | 723 | unsigned int set, unsigned int clear) |
| 705 | { | 724 | { |
| 706 | unsigned int control = 0; | 725 | unsigned int control = 0; |
| @@ -726,10 +745,10 @@ static int cp2101_tiocmset_port(struct usb_serial_port *port, struct file *file, | |||
| 726 | 745 | ||
| 727 | dbg("%s - control = 0x%.4x", __func__, control); | 746 | dbg("%s - control = 0x%.4x", __func__, control); |
| 728 | 747 | ||
| 729 | return cp2101_set_config(port, CP2101_CONTROL, &control, 2); | 748 | return cp210x_set_config(port, CP210X_SET_MHS, &control, 2); |
| 730 | } | 749 | } |
| 731 | 750 | ||
| 732 | static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) | 751 | static int cp210x_tiocmget (struct tty_struct *tty, struct file *file) |
| 733 | { | 752 | { |
| 734 | struct usb_serial_port *port = tty->driver_data; | 753 | struct usb_serial_port *port = tty->driver_data; |
| 735 | unsigned int control; | 754 | unsigned int control; |
| @@ -737,7 +756,7 @@ static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) | |||
| 737 | 756 | ||
| 738 | dbg("%s - port %d", __func__, port->number); | 757 | dbg("%s - port %d", __func__, port->number); |
| 739 | 758 | ||
| 740 | cp2101_get_config(port, CP2101_CONTROL, &control, 1); | 759 | cp210x_get_config(port, CP210X_GET_MDMSTS, &control, 1); |
| 741 | 760 | ||
| 742 | result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) | 761 | result = ((control & CONTROL_DTR) ? TIOCM_DTR : 0) |
| 743 | |((control & CONTROL_RTS) ? TIOCM_RTS : 0) | 762 | |((control & CONTROL_RTS) ? TIOCM_RTS : 0) |
| @@ -751,7 +770,7 @@ static int cp2101_tiocmget (struct tty_struct *tty, struct file *file) | |||
| 751 | return result; | 770 | return result; |
| 752 | } | 771 | } |
| 753 | 772 | ||
| 754 | static void cp2101_break_ctl (struct tty_struct *tty, int break_state) | 773 | static void cp210x_break_ctl (struct tty_struct *tty, int break_state) |
| 755 | { | 774 | { |
| 756 | struct usb_serial_port *port = tty->driver_data; | 775 | struct usb_serial_port *port = tty->driver_data; |
| 757 | unsigned int state; | 776 | unsigned int state; |
| @@ -763,17 +782,17 @@ static void cp2101_break_ctl (struct tty_struct *tty, int break_state) | |||
| 763 | state = BREAK_ON; | 782 | state = BREAK_ON; |
| 764 | dbg("%s - turning break %s", __func__, | 783 | dbg("%s - turning break %s", __func__, |
| 765 | state == BREAK_OFF ? "off" : "on"); | 784 | state == BREAK_OFF ? "off" : "on"); |
| 766 | cp2101_set_config(port, CP2101_BREAK, &state, 2); | 785 | cp210x_set_config(port, CP210X_SET_BREAK, &state, 2); |
| 767 | } | 786 | } |
| 768 | 787 | ||
| 769 | static int cp2101_startup(struct usb_serial *serial) | 788 | static int cp210x_startup(struct usb_serial *serial) |
| 770 | { | 789 | { |
| 771 | /* CP2101 buffers behave strangely unless device is reset */ | 790 | /* cp210x buffers behave strangely unless device is reset */ |
| 772 | usb_reset_device(serial->dev); | 791 | usb_reset_device(serial->dev); |
| 773 | return 0; | 792 | return 0; |
| 774 | } | 793 | } |
| 775 | 794 | ||
| 776 | static void cp2101_shutdown(struct usb_serial *serial) | 795 | static void cp210x_shutdown(struct usb_serial *serial) |
| 777 | { | 796 | { |
| 778 | int i; | 797 | int i; |
| 779 | 798 | ||
| @@ -781,21 +800,21 @@ static void cp2101_shutdown(struct usb_serial *serial) | |||
| 781 | 800 | ||
| 782 | /* Stop reads and writes on all ports */ | 801 | /* Stop reads and writes on all ports */ |
| 783 | for (i = 0; i < serial->num_ports; ++i) | 802 | for (i = 0; i < serial->num_ports; ++i) |
| 784 | cp2101_cleanup(serial->port[i]); | 803 | cp210x_cleanup(serial->port[i]); |
| 785 | } | 804 | } |
| 786 | 805 | ||
| 787 | static int __init cp2101_init(void) | 806 | static int __init cp210x_init(void) |
| 788 | { | 807 | { |
| 789 | int retval; | 808 | int retval; |
| 790 | 809 | ||
| 791 | retval = usb_serial_register(&cp2101_device); | 810 | retval = usb_serial_register(&cp210x_device); |
| 792 | if (retval) | 811 | if (retval) |
| 793 | return retval; /* Failed to register */ | 812 | return retval; /* Failed to register */ |
| 794 | 813 | ||
| 795 | retval = usb_register(&cp2101_driver); | 814 | retval = usb_register(&cp210x_driver); |
| 796 | if (retval) { | 815 | if (retval) { |
| 797 | /* Failed to register */ | 816 | /* Failed to register */ |
| 798 | usb_serial_deregister(&cp2101_device); | 817 | usb_serial_deregister(&cp210x_device); |
| 799 | return retval; | 818 | return retval; |
| 800 | } | 819 | } |
| 801 | 820 | ||
| @@ -805,14 +824,14 @@ static int __init cp2101_init(void) | |||
| 805 | return 0; | 824 | return 0; |
| 806 | } | 825 | } |
| 807 | 826 | ||
| 808 | static void __exit cp2101_exit(void) | 827 | static void __exit cp210x_exit(void) |
| 809 | { | 828 | { |
| 810 | usb_deregister(&cp2101_driver); | 829 | usb_deregister(&cp210x_driver); |
| 811 | usb_serial_deregister(&cp2101_device); | 830 | usb_serial_deregister(&cp210x_device); |
| 812 | } | 831 | } |
| 813 | 832 | ||
| 814 | module_init(cp2101_init); | 833 | module_init(cp210x_init); |
| 815 | module_exit(cp2101_exit); | 834 | module_exit(cp210x_exit); |
| 816 | 835 | ||
| 817 | MODULE_DESCRIPTION(DRIVER_DESC); | 836 | MODULE_DESCRIPTION(DRIVER_DESC); |
| 818 | MODULE_VERSION(DRIVER_VERSION); | 837 | MODULE_VERSION(DRIVER_VERSION); |
diff --git a/drivers/usb/serial/cyberjack.c b/drivers/usb/serial/cyberjack.c index dd501bb63ed6..933ba913e66c 100644 --- a/drivers/usb/serial/cyberjack.c +++ b/drivers/usb/serial/cyberjack.c | |||
| @@ -61,8 +61,7 @@ static int cyberjack_startup(struct usb_serial *serial); | |||
| 61 | static void cyberjack_shutdown(struct usb_serial *serial); | 61 | static void cyberjack_shutdown(struct usb_serial *serial); |
| 62 | static int cyberjack_open(struct tty_struct *tty, | 62 | static int cyberjack_open(struct tty_struct *tty, |
| 63 | struct usb_serial_port *port, struct file *filp); | 63 | struct usb_serial_port *port, struct file *filp); |
| 64 | static void cyberjack_close(struct tty_struct *tty, | 64 | static void cyberjack_close(struct usb_serial_port *port); |
| 65 | struct usb_serial_port *port, struct file *filp); | ||
| 66 | static int cyberjack_write(struct tty_struct *tty, | 65 | static int cyberjack_write(struct tty_struct *tty, |
| 67 | struct usb_serial_port *port, const unsigned char *buf, int count); | 66 | struct usb_serial_port *port, const unsigned char *buf, int count); |
| 68 | static int cyberjack_write_room(struct tty_struct *tty); | 67 | static int cyberjack_write_room(struct tty_struct *tty); |
| @@ -185,8 +184,7 @@ static int cyberjack_open(struct tty_struct *tty, | |||
| 185 | return result; | 184 | return result; |
| 186 | } | 185 | } |
| 187 | 186 | ||
| 188 | static void cyberjack_close(struct tty_struct *tty, | 187 | static void cyberjack_close(struct usb_serial_port *port) |
| 189 | struct usb_serial_port *port, struct file *filp) | ||
| 190 | { | 188 | { |
| 191 | dbg("%s - port %d", __func__, port->number); | 189 | dbg("%s - port %d", __func__, port->number); |
| 192 | 190 | ||
diff --git a/drivers/usb/serial/cypress_m8.c b/drivers/usb/serial/cypress_m8.c index e568710b263f..669f93848539 100644 --- a/drivers/usb/serial/cypress_m8.c +++ b/drivers/usb/serial/cypress_m8.c | |||
| @@ -174,8 +174,8 @@ static int cypress_ca42v2_startup(struct usb_serial *serial); | |||
| 174 | static void cypress_shutdown(struct usb_serial *serial); | 174 | static void cypress_shutdown(struct usb_serial *serial); |
| 175 | static int cypress_open(struct tty_struct *tty, | 175 | static int cypress_open(struct tty_struct *tty, |
| 176 | struct usb_serial_port *port, struct file *filp); | 176 | struct usb_serial_port *port, struct file *filp); |
| 177 | static void cypress_close(struct tty_struct *tty, | 177 | static void cypress_close(struct usb_serial_port *port); |
| 178 | struct usb_serial_port *port, struct file *filp); | 178 | static void cypress_dtr_rts(struct usb_serial_port *port, int on); |
| 179 | static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, | 179 | static int cypress_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 180 | const unsigned char *buf, int count); | 180 | const unsigned char *buf, int count); |
| 181 | static void cypress_send(struct usb_serial_port *port); | 181 | static void cypress_send(struct usb_serial_port *port); |
| @@ -218,6 +218,7 @@ static struct usb_serial_driver cypress_earthmate_device = { | |||
| 218 | .shutdown = cypress_shutdown, | 218 | .shutdown = cypress_shutdown, |
| 219 | .open = cypress_open, | 219 | .open = cypress_open, |
| 220 | .close = cypress_close, | 220 | .close = cypress_close, |
| 221 | .dtr_rts = cypress_dtr_rts, | ||
| 221 | .write = cypress_write, | 222 | .write = cypress_write, |
| 222 | .write_room = cypress_write_room, | 223 | .write_room = cypress_write_room, |
| 223 | .ioctl = cypress_ioctl, | 224 | .ioctl = cypress_ioctl, |
| @@ -244,6 +245,7 @@ static struct usb_serial_driver cypress_hidcom_device = { | |||
| 244 | .shutdown = cypress_shutdown, | 245 | .shutdown = cypress_shutdown, |
| 245 | .open = cypress_open, | 246 | .open = cypress_open, |
| 246 | .close = cypress_close, | 247 | .close = cypress_close, |
| 248 | .dtr_rts = cypress_dtr_rts, | ||
| 247 | .write = cypress_write, | 249 | .write = cypress_write, |
| 248 | .write_room = cypress_write_room, | 250 | .write_room = cypress_write_room, |
| 249 | .ioctl = cypress_ioctl, | 251 | .ioctl = cypress_ioctl, |
| @@ -270,6 +272,7 @@ static struct usb_serial_driver cypress_ca42v2_device = { | |||
| 270 | .shutdown = cypress_shutdown, | 272 | .shutdown = cypress_shutdown, |
| 271 | .open = cypress_open, | 273 | .open = cypress_open, |
| 272 | .close = cypress_close, | 274 | .close = cypress_close, |
| 275 | .dtr_rts = cypress_dtr_rts, | ||
| 273 | .write = cypress_write, | 276 | .write = cypress_write, |
| 274 | .write_room = cypress_write_room, | 277 | .write_room = cypress_write_room, |
| 275 | .ioctl = cypress_ioctl, | 278 | .ioctl = cypress_ioctl, |
| @@ -656,11 +659,7 @@ static int cypress_open(struct tty_struct *tty, | |||
| 656 | priv->rx_flags = 0; | 659 | priv->rx_flags = 0; |
| 657 | spin_unlock_irqrestore(&priv->lock, flags); | 660 | spin_unlock_irqrestore(&priv->lock, flags); |
| 658 | 661 | ||
| 659 | /* raise both lines and set termios */ | 662 | /* Set termios */ |
| 660 | spin_lock_irqsave(&priv->lock, flags); | ||
| 661 | priv->line_control = CONTROL_DTR | CONTROL_RTS; | ||
| 662 | priv->cmd_ctrl = 1; | ||
| 663 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 664 | result = cypress_write(tty, port, NULL, 0); | 663 | result = cypress_write(tty, port, NULL, 0); |
| 665 | 664 | ||
| 666 | if (result) { | 665 | if (result) { |
| @@ -694,76 +693,42 @@ static int cypress_open(struct tty_struct *tty, | |||
| 694 | __func__, result); | 693 | __func__, result); |
| 695 | cypress_set_dead(port); | 694 | cypress_set_dead(port); |
| 696 | } | 695 | } |
| 697 | 696 | port->port.drain_delay = 256; | |
| 698 | return result; | 697 | return result; |
| 699 | } /* cypress_open */ | 698 | } /* cypress_open */ |
| 700 | 699 | ||
| 700 | static void cypress_dtr_rts(struct usb_serial_port *port, int on) | ||
| 701 | { | ||
| 702 | struct cypress_private *priv = usb_get_serial_port_data(port); | ||
| 703 | /* drop dtr and rts */ | ||
| 704 | priv = usb_get_serial_port_data(port); | ||
| 705 | spin_lock_irq(&priv->lock); | ||
| 706 | if (on == 0) | ||
| 707 | priv->line_control = 0; | ||
| 708 | else | ||
| 709 | priv->line_control = CONTROL_DTR | CONTROL_RTS; | ||
| 710 | priv->cmd_ctrl = 1; | ||
| 711 | spin_unlock_irq(&priv->lock); | ||
| 712 | cypress_write(NULL, port, NULL, 0); | ||
| 713 | } | ||
| 701 | 714 | ||
| 702 | static void cypress_close(struct tty_struct *tty, | 715 | static void cypress_close(struct usb_serial_port *port) |
| 703 | struct usb_serial_port *port, struct file *filp) | ||
| 704 | { | 716 | { |
| 705 | struct cypress_private *priv = usb_get_serial_port_data(port); | 717 | struct cypress_private *priv = usb_get_serial_port_data(port); |
| 706 | unsigned int c_cflag; | ||
| 707 | int bps; | ||
| 708 | long timeout; | ||
| 709 | wait_queue_t wait; | ||
| 710 | 718 | ||
| 711 | dbg("%s - port %d", __func__, port->number); | 719 | dbg("%s - port %d", __func__, port->number); |
| 712 | 720 | ||
| 713 | /* wait for data to drain from buffer */ | ||
| 714 | spin_lock_irq(&priv->lock); | ||
| 715 | timeout = CYPRESS_CLOSING_WAIT; | ||
| 716 | init_waitqueue_entry(&wait, current); | ||
| 717 | add_wait_queue(&tty->write_wait, &wait); | ||
| 718 | for (;;) { | ||
| 719 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 720 | if (cypress_buf_data_avail(priv->buf) == 0 | ||
| 721 | || timeout == 0 || signal_pending(current) | ||
| 722 | /* without mutex, allowed due to harmless failure mode */ | ||
| 723 | || port->serial->disconnected) | ||
| 724 | break; | ||
| 725 | spin_unlock_irq(&priv->lock); | ||
| 726 | timeout = schedule_timeout(timeout); | ||
| 727 | spin_lock_irq(&priv->lock); | ||
| 728 | } | ||
| 729 | set_current_state(TASK_RUNNING); | ||
| 730 | remove_wait_queue(&tty->write_wait, &wait); | ||
| 731 | /* clear out any remaining data in the buffer */ | ||
| 732 | cypress_buf_clear(priv->buf); | ||
| 733 | spin_unlock_irq(&priv->lock); | ||
| 734 | |||
| 735 | /* writing is potentially harmful, lock must be taken */ | 721 | /* writing is potentially harmful, lock must be taken */ |
| 736 | mutex_lock(&port->serial->disc_mutex); | 722 | mutex_lock(&port->serial->disc_mutex); |
| 737 | if (port->serial->disconnected) { | 723 | if (port->serial->disconnected) { |
| 738 | mutex_unlock(&port->serial->disc_mutex); | 724 | mutex_unlock(&port->serial->disc_mutex); |
| 739 | return; | 725 | return; |
| 740 | } | 726 | } |
| 741 | /* wait for characters to drain from device */ | 727 | cypress_buf_clear(priv->buf); |
| 742 | if (tty) { | ||
| 743 | bps = tty_get_baud_rate(tty); | ||
| 744 | if (bps > 1200) | ||
| 745 | timeout = max((HZ * 2560) / bps, HZ / 10); | ||
| 746 | else | ||
| 747 | timeout = 2 * HZ; | ||
| 748 | schedule_timeout_interruptible(timeout); | ||
| 749 | } | ||
| 750 | |||
| 751 | dbg("%s - stopping urbs", __func__); | 728 | dbg("%s - stopping urbs", __func__); |
| 752 | usb_kill_urb(port->interrupt_in_urb); | 729 | usb_kill_urb(port->interrupt_in_urb); |
| 753 | usb_kill_urb(port->interrupt_out_urb); | 730 | usb_kill_urb(port->interrupt_out_urb); |
| 754 | 731 | ||
| 755 | if (tty) { | ||
| 756 | c_cflag = tty->termios->c_cflag; | ||
| 757 | if (c_cflag & HUPCL) { | ||
| 758 | /* drop dtr and rts */ | ||
| 759 | priv = usb_get_serial_port_data(port); | ||
| 760 | spin_lock_irq(&priv->lock); | ||
| 761 | priv->line_control = 0; | ||
| 762 | priv->cmd_ctrl = 1; | ||
| 763 | spin_unlock_irq(&priv->lock); | ||
| 764 | cypress_write(tty, port, NULL, 0); | ||
| 765 | } | ||
| 766 | } | ||
| 767 | 732 | ||
| 768 | if (stats) | 733 | if (stats) |
| 769 | dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", | 734 | dev_info(&port->dev, "Statistics: %d Bytes In | %d Bytes Out | %d Commands Issued\n", |
diff --git a/drivers/usb/serial/digi_acceleport.c b/drivers/usb/serial/digi_acceleport.c index 38ba4ea8b6bf..30f5140eff03 100644 --- a/drivers/usb/serial/digi_acceleport.c +++ b/drivers/usb/serial/digi_acceleport.c | |||
| @@ -422,7 +422,6 @@ struct digi_port { | |||
| 422 | int dp_throttled; | 422 | int dp_throttled; |
| 423 | int dp_throttle_restart; | 423 | int dp_throttle_restart; |
| 424 | wait_queue_head_t dp_flush_wait; | 424 | wait_queue_head_t dp_flush_wait; |
| 425 | int dp_in_close; /* close in progress */ | ||
| 426 | wait_queue_head_t dp_close_wait; /* wait queue for close */ | 425 | wait_queue_head_t dp_close_wait; /* wait queue for close */ |
| 427 | struct work_struct dp_wakeup_work; | 426 | struct work_struct dp_wakeup_work; |
| 428 | struct usb_serial_port *dp_port; | 427 | struct usb_serial_port *dp_port; |
| @@ -456,8 +455,9 @@ static int digi_write_room(struct tty_struct *tty); | |||
| 456 | static int digi_chars_in_buffer(struct tty_struct *tty); | 455 | static int digi_chars_in_buffer(struct tty_struct *tty); |
| 457 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | 456 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 458 | struct file *filp); | 457 | struct file *filp); |
| 459 | static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | 458 | static void digi_close(struct usb_serial_port *port); |
| 460 | struct file *filp); | 459 | static int digi_carrier_raised(struct usb_serial_port *port); |
| 460 | static void digi_dtr_rts(struct usb_serial_port *port, int on); | ||
| 461 | static int digi_startup_device(struct usb_serial *serial); | 461 | static int digi_startup_device(struct usb_serial *serial); |
| 462 | static int digi_startup(struct usb_serial *serial); | 462 | static int digi_startup(struct usb_serial *serial); |
| 463 | static void digi_shutdown(struct usb_serial *serial); | 463 | static void digi_shutdown(struct usb_serial *serial); |
| @@ -510,6 +510,8 @@ static struct usb_serial_driver digi_acceleport_2_device = { | |||
| 510 | .num_ports = 3, | 510 | .num_ports = 3, |
| 511 | .open = digi_open, | 511 | .open = digi_open, |
| 512 | .close = digi_close, | 512 | .close = digi_close, |
| 513 | .dtr_rts = digi_dtr_rts, | ||
| 514 | .carrier_raised = digi_carrier_raised, | ||
| 513 | .write = digi_write, | 515 | .write = digi_write, |
| 514 | .write_room = digi_write_room, | 516 | .write_room = digi_write_room, |
| 515 | .write_bulk_callback = digi_write_bulk_callback, | 517 | .write_bulk_callback = digi_write_bulk_callback, |
| @@ -1328,6 +1330,19 @@ static int digi_chars_in_buffer(struct tty_struct *tty) | |||
| 1328 | 1330 | ||
| 1329 | } | 1331 | } |
| 1330 | 1332 | ||
| 1333 | static void digi_dtr_rts(struct usb_serial_port *port, int on) | ||
| 1334 | { | ||
| 1335 | /* Adjust DTR and RTS */ | ||
| 1336 | digi_set_modem_signals(port, on * (TIOCM_DTR|TIOCM_RTS), 1); | ||
| 1337 | } | ||
| 1338 | |||
| 1339 | static int digi_carrier_raised(struct usb_serial_port *port) | ||
| 1340 | { | ||
| 1341 | struct digi_port *priv = usb_get_serial_port_data(port); | ||
| 1342 | if (priv->dp_modem_signals & TIOCM_CD) | ||
| 1343 | return 1; | ||
| 1344 | return 0; | ||
| 1345 | } | ||
| 1331 | 1346 | ||
| 1332 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | 1347 | static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 1333 | struct file *filp) | 1348 | struct file *filp) |
| @@ -1336,7 +1351,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 1336 | unsigned char buf[32]; | 1351 | unsigned char buf[32]; |
| 1337 | struct digi_port *priv = usb_get_serial_port_data(port); | 1352 | struct digi_port *priv = usb_get_serial_port_data(port); |
| 1338 | struct ktermios not_termios; | 1353 | struct ktermios not_termios; |
| 1339 | unsigned long flags = 0; | ||
| 1340 | 1354 | ||
| 1341 | dbg("digi_open: TOP: port=%d, open_count=%d", | 1355 | dbg("digi_open: TOP: port=%d, open_count=%d", |
| 1342 | priv->dp_port_num, port->port.count); | 1356 | priv->dp_port_num, port->port.count); |
| @@ -1345,26 +1359,6 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 1345 | if (digi_startup_device(port->serial) != 0) | 1359 | if (digi_startup_device(port->serial) != 0) |
| 1346 | return -ENXIO; | 1360 | return -ENXIO; |
| 1347 | 1361 | ||
| 1348 | spin_lock_irqsave(&priv->dp_port_lock, flags); | ||
| 1349 | |||
| 1350 | /* don't wait on a close in progress for non-blocking opens */ | ||
| 1351 | if (priv->dp_in_close && (filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) { | ||
| 1352 | spin_unlock_irqrestore(&priv->dp_port_lock, flags); | ||
| 1353 | return -EAGAIN; | ||
| 1354 | } | ||
| 1355 | |||
| 1356 | /* wait for a close in progress to finish */ | ||
| 1357 | while (priv->dp_in_close) { | ||
| 1358 | cond_wait_interruptible_timeout_irqrestore( | ||
| 1359 | &priv->dp_close_wait, DIGI_RETRY_TIMEOUT, | ||
| 1360 | &priv->dp_port_lock, flags); | ||
| 1361 | if (signal_pending(current)) | ||
| 1362 | return -EINTR; | ||
| 1363 | spin_lock_irqsave(&priv->dp_port_lock, flags); | ||
| 1364 | } | ||
| 1365 | |||
| 1366 | spin_unlock_irqrestore(&priv->dp_port_lock, flags); | ||
| 1367 | |||
| 1368 | /* read modem signals automatically whenever they change */ | 1362 | /* read modem signals automatically whenever they change */ |
| 1369 | buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; | 1363 | buf[0] = DIGI_CMD_READ_INPUT_SIGNALS; |
| 1370 | buf[1] = priv->dp_port_num; | 1364 | buf[1] = priv->dp_port_num; |
| @@ -1387,16 +1381,11 @@ static int digi_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 1387 | not_termios.c_iflag = ~tty->termios->c_iflag; | 1381 | not_termios.c_iflag = ~tty->termios->c_iflag; |
| 1388 | digi_set_termios(tty, port, ¬_termios); | 1382 | digi_set_termios(tty, port, ¬_termios); |
| 1389 | } | 1383 | } |
| 1390 | |||
| 1391 | /* set DTR and RTS */ | ||
| 1392 | digi_set_modem_signals(port, TIOCM_DTR|TIOCM_RTS, 1); | ||
| 1393 | |||
| 1394 | return 0; | 1384 | return 0; |
| 1395 | } | 1385 | } |
| 1396 | 1386 | ||
| 1397 | 1387 | ||
| 1398 | static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | 1388 | static void digi_close(struct usb_serial_port *port) |
| 1399 | struct file *filp) | ||
| 1400 | { | 1389 | { |
| 1401 | DEFINE_WAIT(wait); | 1390 | DEFINE_WAIT(wait); |
| 1402 | int ret; | 1391 | int ret; |
| @@ -1411,28 +1400,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 1411 | if (port->serial->disconnected) | 1400 | if (port->serial->disconnected) |
| 1412 | goto exit; | 1401 | goto exit; |
| 1413 | 1402 | ||
| 1414 | /* do cleanup only after final close on this port */ | ||
| 1415 | spin_lock_irq(&priv->dp_port_lock); | ||
| 1416 | priv->dp_in_close = 1; | ||
| 1417 | spin_unlock_irq(&priv->dp_port_lock); | ||
| 1418 | |||
| 1419 | /* tell line discipline to process only XON/XOFF */ | ||
| 1420 | tty->closing = 1; | ||
| 1421 | |||
| 1422 | /* wait for output to drain */ | ||
| 1423 | if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) | ||
| 1424 | tty_wait_until_sent(tty, DIGI_CLOSE_TIMEOUT); | ||
| 1425 | |||
| 1426 | /* flush driver and line discipline buffers */ | ||
| 1427 | tty_driver_flush_buffer(tty); | ||
| 1428 | tty_ldisc_flush(tty); | ||
| 1429 | |||
| 1430 | if (port->serial->dev) { | 1403 | if (port->serial->dev) { |
| 1431 | /* wait for transmit idle */ | 1404 | /* FIXME: Transmit idle belongs in the wait_unti_sent path */ |
| 1432 | if ((filp->f_flags&(O_NDELAY|O_NONBLOCK)) == 0) | 1405 | digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); |
| 1433 | digi_transmit_idle(port, DIGI_CLOSE_TIMEOUT); | ||
| 1434 | /* drop DTR and RTS */ | ||
| 1435 | digi_set_modem_signals(port, 0, 0); | ||
| 1436 | 1406 | ||
| 1437 | /* disable input flow control */ | 1407 | /* disable input flow control */ |
| 1438 | buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; | 1408 | buf[0] = DIGI_CMD_SET_INPUT_FLOW_CONTROL; |
| @@ -1477,11 +1447,9 @@ static void digi_close(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 1477 | /* shutdown any outstanding bulk writes */ | 1447 | /* shutdown any outstanding bulk writes */ |
| 1478 | usb_kill_urb(port->write_urb); | 1448 | usb_kill_urb(port->write_urb); |
| 1479 | } | 1449 | } |
| 1480 | tty->closing = 0; | ||
| 1481 | exit: | 1450 | exit: |
| 1482 | spin_lock_irq(&priv->dp_port_lock); | 1451 | spin_lock_irq(&priv->dp_port_lock); |
| 1483 | priv->dp_write_urb_in_use = 0; | 1452 | priv->dp_write_urb_in_use = 0; |
| 1484 | priv->dp_in_close = 0; | ||
| 1485 | wake_up_interruptible(&priv->dp_close_wait); | 1453 | wake_up_interruptible(&priv->dp_close_wait); |
| 1486 | spin_unlock_irq(&priv->dp_port_lock); | 1454 | spin_unlock_irq(&priv->dp_port_lock); |
| 1487 | mutex_unlock(&port->serial->disc_mutex); | 1455 | mutex_unlock(&port->serial->disc_mutex); |
| @@ -1560,7 +1528,6 @@ static int digi_startup(struct usb_serial *serial) | |||
| 1560 | priv->dp_throttled = 0; | 1528 | priv->dp_throttled = 0; |
| 1561 | priv->dp_throttle_restart = 0; | 1529 | priv->dp_throttle_restart = 0; |
| 1562 | init_waitqueue_head(&priv->dp_flush_wait); | 1530 | init_waitqueue_head(&priv->dp_flush_wait); |
| 1563 | priv->dp_in_close = 0; | ||
| 1564 | init_waitqueue_head(&priv->dp_close_wait); | 1531 | init_waitqueue_head(&priv->dp_close_wait); |
| 1565 | INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); | 1532 | INIT_WORK(&priv->dp_wakeup_work, digi_wakeup_write_lock); |
| 1566 | priv->dp_port = serial->port[i]; | 1533 | priv->dp_port = serial->port[i]; |
diff --git a/drivers/usb/serial/empeg.c b/drivers/usb/serial/empeg.c index c709ec474a80..2b141ccb0cd9 100644 --- a/drivers/usb/serial/empeg.c +++ b/drivers/usb/serial/empeg.c | |||
| @@ -81,8 +81,7 @@ static int debug; | |||
| 81 | /* function prototypes for an empeg-car player */ | 81 | /* function prototypes for an empeg-car player */ |
| 82 | static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port, | 82 | static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 83 | struct file *filp); | 83 | struct file *filp); |
| 84 | static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port, | 84 | static void empeg_close(struct usb_serial_port *port); |
| 85 | struct file *filp); | ||
| 86 | static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port, | 85 | static int empeg_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 87 | const unsigned char *buf, | 86 | const unsigned char *buf, |
| 88 | int count); | 87 | int count); |
| @@ -181,8 +180,7 @@ static int empeg_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 181 | } | 180 | } |
| 182 | 181 | ||
| 183 | 182 | ||
| 184 | static void empeg_close(struct tty_struct *tty, struct usb_serial_port *port, | 183 | static void empeg_close(struct usb_serial_port *port) |
| 185 | struct file *filp) | ||
| 186 | { | 184 | { |
| 187 | dbg("%s - port %d", __func__, port->number); | 185 | dbg("%s - port %d", __func__, port->number); |
| 188 | 186 | ||
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c index d9fcdaedf389..683304d60615 100644 --- a/drivers/usb/serial/ftdi_sio.c +++ b/drivers/usb/serial/ftdi_sio.c | |||
| @@ -89,6 +89,7 @@ struct ftdi_private { | |||
| 89 | int force_rtscts; /* if non-zero, force RTS-CTS to always | 89 | int force_rtscts; /* if non-zero, force RTS-CTS to always |
| 90 | be enabled */ | 90 | be enabled */ |
| 91 | 91 | ||
| 92 | unsigned int latency; /* latency setting in use */ | ||
| 92 | spinlock_t tx_lock; /* spinlock for transmit state */ | 93 | spinlock_t tx_lock; /* spinlock for transmit state */ |
| 93 | unsigned long tx_bytes; | 94 | unsigned long tx_bytes; |
| 94 | unsigned long tx_outstanding_bytes; | 95 | unsigned long tx_outstanding_bytes; |
| @@ -719,8 +720,8 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port); | |||
| 719 | static int ftdi_sio_port_remove(struct usb_serial_port *port); | 720 | static int ftdi_sio_port_remove(struct usb_serial_port *port); |
| 720 | static int ftdi_open(struct tty_struct *tty, | 721 | static int ftdi_open(struct tty_struct *tty, |
| 721 | struct usb_serial_port *port, struct file *filp); | 722 | struct usb_serial_port *port, struct file *filp); |
| 722 | static void ftdi_close(struct tty_struct *tty, | 723 | static void ftdi_close(struct usb_serial_port *port); |
| 723 | struct usb_serial_port *port, struct file *filp); | 724 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on); |
| 724 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, | 725 | static int ftdi_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 725 | const unsigned char *buf, int count); | 726 | const unsigned char *buf, int count); |
| 726 | static int ftdi_write_room(struct tty_struct *tty); | 727 | static int ftdi_write_room(struct tty_struct *tty); |
| @@ -758,6 +759,7 @@ static struct usb_serial_driver ftdi_sio_device = { | |||
| 758 | .port_remove = ftdi_sio_port_remove, | 759 | .port_remove = ftdi_sio_port_remove, |
| 759 | .open = ftdi_open, | 760 | .open = ftdi_open, |
| 760 | .close = ftdi_close, | 761 | .close = ftdi_close, |
| 762 | .dtr_rts = ftdi_dtr_rts, | ||
| 761 | .throttle = ftdi_throttle, | 763 | .throttle = ftdi_throttle, |
| 762 | .unthrottle = ftdi_unthrottle, | 764 | .unthrottle = ftdi_unthrottle, |
| 763 | .write = ftdi_write, | 765 | .write = ftdi_write, |
| @@ -1037,7 +1039,54 @@ static int change_speed(struct tty_struct *tty, struct usb_serial_port *port) | |||
| 1037 | return rv; | 1039 | return rv; |
| 1038 | } | 1040 | } |
| 1039 | 1041 | ||
| 1042 | static int write_latency_timer(struct usb_serial_port *port) | ||
| 1043 | { | ||
| 1044 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
| 1045 | struct usb_device *udev = port->serial->dev; | ||
| 1046 | char buf[1]; | ||
| 1047 | int rv = 0; | ||
| 1048 | int l = priv->latency; | ||
| 1049 | |||
| 1050 | if (priv->flags & ASYNC_LOW_LATENCY) | ||
| 1051 | l = 1; | ||
| 1052 | |||
| 1053 | dbg("%s: setting latency timer = %i", __func__, l); | ||
| 1054 | |||
| 1055 | rv = usb_control_msg(udev, | ||
| 1056 | usb_sndctrlpipe(udev, 0), | ||
| 1057 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | ||
| 1058 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | ||
| 1059 | l, priv->interface, | ||
| 1060 | buf, 0, WDR_TIMEOUT); | ||
| 1061 | |||
| 1062 | if (rv < 0) | ||
| 1063 | dev_err(&port->dev, "Unable to write latency timer: %i\n", rv); | ||
| 1064 | return rv; | ||
| 1065 | } | ||
| 1066 | |||
| 1067 | static int read_latency_timer(struct usb_serial_port *port) | ||
| 1068 | { | ||
| 1069 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
| 1070 | struct usb_device *udev = port->serial->dev; | ||
| 1071 | unsigned short latency = 0; | ||
| 1072 | int rv = 0; | ||
| 1073 | |||
| 1040 | 1074 | ||
| 1075 | dbg("%s", __func__); | ||
| 1076 | |||
| 1077 | rv = usb_control_msg(udev, | ||
| 1078 | usb_rcvctrlpipe(udev, 0), | ||
| 1079 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST, | ||
| 1080 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, | ||
| 1081 | 0, priv->interface, | ||
| 1082 | (char *) &latency, 1, WDR_TIMEOUT); | ||
| 1083 | |||
| 1084 | if (rv < 0) { | ||
| 1085 | dev_err(&port->dev, "Unable to read latency timer: %i\n", rv); | ||
| 1086 | return -EIO; | ||
| 1087 | } | ||
| 1088 | return latency; | ||
| 1089 | } | ||
| 1041 | 1090 | ||
| 1042 | static int get_serial_info(struct usb_serial_port *port, | 1091 | static int get_serial_info(struct usb_serial_port *port, |
| 1043 | struct serial_struct __user *retinfo) | 1092 | struct serial_struct __user *retinfo) |
| @@ -1097,6 +1146,7 @@ static int set_serial_info(struct tty_struct *tty, | |||
| 1097 | priv->custom_divisor = new_serial.custom_divisor; | 1146 | priv->custom_divisor = new_serial.custom_divisor; |
| 1098 | 1147 | ||
| 1099 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1148 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
| 1149 | write_latency_timer(port); | ||
| 1100 | 1150 | ||
| 1101 | check_and_exit: | 1151 | check_and_exit: |
| 1102 | if ((old_priv.flags & ASYNC_SPD_MASK) != | 1152 | if ((old_priv.flags & ASYNC_SPD_MASK) != |
| @@ -1192,27 +1242,13 @@ static ssize_t show_latency_timer(struct device *dev, | |||
| 1192 | { | 1242 | { |
| 1193 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1243 | struct usb_serial_port *port = to_usb_serial_port(dev); |
| 1194 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1244 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1195 | struct usb_device *udev = port->serial->dev; | 1245 | if (priv->flags & ASYNC_LOW_LATENCY) |
| 1196 | unsigned short latency = 0; | 1246 | return sprintf(buf, "1\n"); |
| 1197 | int rv = 0; | 1247 | else |
| 1198 | 1248 | return sprintf(buf, "%i\n", priv->latency); | |
| 1199 | |||
| 1200 | dbg("%s", __func__); | ||
| 1201 | |||
| 1202 | rv = usb_control_msg(udev, | ||
| 1203 | usb_rcvctrlpipe(udev, 0), | ||
| 1204 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST, | ||
| 1205 | FTDI_SIO_GET_LATENCY_TIMER_REQUEST_TYPE, | ||
| 1206 | 0, priv->interface, | ||
| 1207 | (char *) &latency, 1, WDR_TIMEOUT); | ||
| 1208 | |||
| 1209 | if (rv < 0) { | ||
| 1210 | dev_err(dev, "Unable to read latency timer: %i\n", rv); | ||
| 1211 | return -EIO; | ||
| 1212 | } | ||
| 1213 | return sprintf(buf, "%i\n", latency); | ||
| 1214 | } | 1249 | } |
| 1215 | 1250 | ||
| 1251 | |||
| 1216 | /* Write a new value of the latency timer, in units of milliseconds. */ | 1252 | /* Write a new value of the latency timer, in units of milliseconds. */ |
| 1217 | static ssize_t store_latency_timer(struct device *dev, | 1253 | static ssize_t store_latency_timer(struct device *dev, |
| 1218 | struct device_attribute *attr, const char *valbuf, | 1254 | struct device_attribute *attr, const char *valbuf, |
| @@ -1220,25 +1256,13 @@ static ssize_t store_latency_timer(struct device *dev, | |||
| 1220 | { | 1256 | { |
| 1221 | struct usb_serial_port *port = to_usb_serial_port(dev); | 1257 | struct usb_serial_port *port = to_usb_serial_port(dev); |
| 1222 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1258 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1223 | struct usb_device *udev = port->serial->dev; | ||
| 1224 | char buf[1]; | ||
| 1225 | int v = simple_strtoul(valbuf, NULL, 10); | 1259 | int v = simple_strtoul(valbuf, NULL, 10); |
| 1226 | int rv = 0; | 1260 | int rv = 0; |
| 1227 | 1261 | ||
| 1228 | dbg("%s: setting latency timer = %i", __func__, v); | 1262 | priv->latency = v; |
| 1229 | 1263 | rv = write_latency_timer(port); | |
| 1230 | rv = usb_control_msg(udev, | 1264 | if (rv < 0) |
| 1231 | usb_sndctrlpipe(udev, 0), | ||
| 1232 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST, | ||
| 1233 | FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE, | ||
| 1234 | v, priv->interface, | ||
| 1235 | buf, 0, WDR_TIMEOUT); | ||
| 1236 | |||
| 1237 | if (rv < 0) { | ||
| 1238 | dev_err(dev, "Unable to write latency timer: %i\n", rv); | ||
| 1239 | return -EIO; | 1265 | return -EIO; |
| 1240 | } | ||
| 1241 | |||
| 1242 | return count; | 1266 | return count; |
| 1243 | } | 1267 | } |
| 1244 | 1268 | ||
| @@ -1392,6 +1416,7 @@ static int ftdi_sio_port_probe(struct usb_serial_port *port) | |||
| 1392 | usb_set_serial_port_data(port, priv); | 1416 | usb_set_serial_port_data(port, priv); |
| 1393 | 1417 | ||
| 1394 | ftdi_determine_type(port); | 1418 | ftdi_determine_type(port); |
| 1419 | read_latency_timer(port); | ||
| 1395 | create_sysfs_attrs(port); | 1420 | create_sysfs_attrs(port); |
| 1396 | return 0; | 1421 | return 0; |
| 1397 | } | 1422 | } |
| @@ -1514,6 +1539,8 @@ static int ftdi_open(struct tty_struct *tty, | |||
| 1514 | if (tty) | 1539 | if (tty) |
| 1515 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; | 1540 | tty->low_latency = (priv->flags & ASYNC_LOW_LATENCY) ? 1 : 0; |
| 1516 | 1541 | ||
| 1542 | write_latency_timer(port); | ||
| 1543 | |||
| 1517 | /* No error checking for this (will get errors later anyway) */ | 1544 | /* No error checking for this (will get errors later anyway) */ |
| 1518 | /* See ftdi_sio.h for description of what is reset */ | 1545 | /* See ftdi_sio.h for description of what is reset */ |
| 1519 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 1546 | usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| @@ -1529,11 +1556,6 @@ static int ftdi_open(struct tty_struct *tty, | |||
| 1529 | if (tty) | 1556 | if (tty) |
| 1530 | ftdi_set_termios(tty, port, tty->termios); | 1557 | ftdi_set_termios(tty, port, tty->termios); |
| 1531 | 1558 | ||
| 1532 | /* FIXME: Flow control might be enabled, so it should be checked - | ||
| 1533 | we have no control of defaults! */ | ||
| 1534 | /* Turn on RTS and DTR since we are not flow controlling by default */ | ||
| 1535 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
| 1536 | |||
| 1537 | /* Not throttled */ | 1559 | /* Not throttled */ |
| 1538 | spin_lock_irqsave(&priv->rx_lock, flags); | 1560 | spin_lock_irqsave(&priv->rx_lock, flags); |
| 1539 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); | 1561 | priv->rx_flags &= ~(THROTTLED | ACTUALLY_THROTTLED); |
| @@ -1558,6 +1580,30 @@ static int ftdi_open(struct tty_struct *tty, | |||
| 1558 | } /* ftdi_open */ | 1580 | } /* ftdi_open */ |
| 1559 | 1581 | ||
| 1560 | 1582 | ||
| 1583 | static void ftdi_dtr_rts(struct usb_serial_port *port, int on) | ||
| 1584 | { | ||
| 1585 | struct ftdi_private *priv = usb_get_serial_port_data(port); | ||
| 1586 | char buf[1]; | ||
| 1587 | |||
| 1588 | mutex_lock(&port->serial->disc_mutex); | ||
| 1589 | if (!port->serial->disconnected) { | ||
| 1590 | /* Disable flow control */ | ||
| 1591 | if (!on && usb_control_msg(port->serial->dev, | ||
| 1592 | usb_sndctrlpipe(port->serial->dev, 0), | ||
| 1593 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
| 1594 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
| 1595 | 0, priv->interface, buf, 0, | ||
| 1596 | WDR_TIMEOUT) < 0) { | ||
| 1597 | dev_err(&port->dev, "error from flowcontrol urb\n"); | ||
| 1598 | } | ||
| 1599 | /* drop RTS and DTR */ | ||
| 1600 | if (on) | ||
| 1601 | set_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
| 1602 | else | ||
| 1603 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
| 1604 | } | ||
| 1605 | mutex_unlock(&port->serial->disc_mutex); | ||
| 1606 | } | ||
| 1561 | 1607 | ||
| 1562 | /* | 1608 | /* |
| 1563 | * usbserial:__serial_close only calls ftdi_close if the point is open | 1609 | * usbserial:__serial_close only calls ftdi_close if the point is open |
| @@ -1567,31 +1613,12 @@ static int ftdi_open(struct tty_struct *tty, | |||
| 1567 | * | 1613 | * |
| 1568 | */ | 1614 | */ |
| 1569 | 1615 | ||
| 1570 | static void ftdi_close(struct tty_struct *tty, | 1616 | static void ftdi_close(struct usb_serial_port *port) |
| 1571 | struct usb_serial_port *port, struct file *filp) | ||
| 1572 | { /* ftdi_close */ | 1617 | { /* ftdi_close */ |
| 1573 | unsigned int c_cflag = tty->termios->c_cflag; | ||
| 1574 | struct ftdi_private *priv = usb_get_serial_port_data(port); | 1618 | struct ftdi_private *priv = usb_get_serial_port_data(port); |
| 1575 | char buf[1]; | ||
| 1576 | 1619 | ||
| 1577 | dbg("%s", __func__); | 1620 | dbg("%s", __func__); |
| 1578 | 1621 | ||
| 1579 | mutex_lock(&port->serial->disc_mutex); | ||
| 1580 | if (c_cflag & HUPCL && !port->serial->disconnected) { | ||
| 1581 | /* Disable flow control */ | ||
| 1582 | if (usb_control_msg(port->serial->dev, | ||
| 1583 | usb_sndctrlpipe(port->serial->dev, 0), | ||
| 1584 | FTDI_SIO_SET_FLOW_CTRL_REQUEST, | ||
| 1585 | FTDI_SIO_SET_FLOW_CTRL_REQUEST_TYPE, | ||
| 1586 | 0, priv->interface, buf, 0, | ||
| 1587 | WDR_TIMEOUT) < 0) { | ||
| 1588 | dev_err(&port->dev, "error from flowcontrol urb\n"); | ||
| 1589 | } | ||
| 1590 | |||
| 1591 | /* drop RTS and DTR */ | ||
| 1592 | clear_mctrl(port, TIOCM_DTR | TIOCM_RTS); | ||
| 1593 | } /* Note change no line if hupcl is off */ | ||
| 1594 | mutex_unlock(&port->serial->disc_mutex); | ||
| 1595 | 1622 | ||
| 1596 | /* cancel any scheduled reading */ | 1623 | /* cancel any scheduled reading */ |
| 1597 | cancel_delayed_work_sync(&priv->rx_work); | 1624 | cancel_delayed_work_sync(&priv->rx_work); |
diff --git a/drivers/usb/serial/garmin_gps.c b/drivers/usb/serial/garmin_gps.c index 586d30ff450b..ee25a3fe3b09 100644 --- a/drivers/usb/serial/garmin_gps.c +++ b/drivers/usb/serial/garmin_gps.c | |||
| @@ -993,8 +993,7 @@ static int garmin_open(struct tty_struct *tty, | |||
| 993 | } | 993 | } |
| 994 | 994 | ||
| 995 | 995 | ||
| 996 | static void garmin_close(struct tty_struct *tty, | 996 | static void garmin_close(struct usb_serial_port *port) |
| 997 | struct usb_serial_port *port, struct file *filp) | ||
| 998 | { | 997 | { |
| 999 | struct usb_serial *serial = port->serial; | 998 | struct usb_serial *serial = port->serial; |
| 1000 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); | 999 | struct garmin_data *garmin_data_p = usb_get_serial_port_data(port); |
diff --git a/drivers/usb/serial/generic.c b/drivers/usb/serial/generic.c index 4cec9906ccf3..be82ea956720 100644 --- a/drivers/usb/serial/generic.c +++ b/drivers/usb/serial/generic.c | |||
| @@ -184,8 +184,7 @@ int usb_serial_generic_resume(struct usb_serial *serial) | |||
| 184 | } | 184 | } |
| 185 | EXPORT_SYMBOL_GPL(usb_serial_generic_resume); | 185 | EXPORT_SYMBOL_GPL(usb_serial_generic_resume); |
| 186 | 186 | ||
| 187 | void usb_serial_generic_close(struct tty_struct *tty, | 187 | void usb_serial_generic_close(struct usb_serial_port *port) |
| 188 | struct usb_serial_port *port, struct file *filp) | ||
| 189 | { | 188 | { |
| 190 | dbg("%s - port %d", __func__, port->number); | 189 | dbg("%s - port %d", __func__, port->number); |
| 191 | generic_cleanup(port); | 190 | generic_cleanup(port); |
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c index fb4a73d090f6..53ef5996e33d 100644 --- a/drivers/usb/serial/io_edgeport.c +++ b/drivers/usb/serial/io_edgeport.c | |||
| @@ -207,8 +207,7 @@ static void edge_bulk_out_cmd_callback(struct urb *urb); | |||
| 207 | /* function prototypes for the usbserial callbacks */ | 207 | /* function prototypes for the usbserial callbacks */ |
| 208 | static int edge_open(struct tty_struct *tty, struct usb_serial_port *port, | 208 | static int edge_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 209 | struct file *filp); | 209 | struct file *filp); |
| 210 | static void edge_close(struct tty_struct *tty, struct usb_serial_port *port, | 210 | static void edge_close(struct usb_serial_port *port); |
| 211 | struct file *filp); | ||
| 212 | static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, | 211 | static int edge_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 213 | const unsigned char *buf, int count); | 212 | const unsigned char *buf, int count); |
| 214 | static int edge_write_room(struct tty_struct *tty); | 213 | static int edge_write_room(struct tty_struct *tty); |
| @@ -965,7 +964,7 @@ static int edge_open(struct tty_struct *tty, | |||
| 965 | 964 | ||
| 966 | if (!edge_port->txfifo.fifo) { | 965 | if (!edge_port->txfifo.fifo) { |
| 967 | dbg("%s - no memory", __func__); | 966 | dbg("%s - no memory", __func__); |
| 968 | edge_close(tty, port, filp); | 967 | edge_close(port); |
| 969 | return -ENOMEM; | 968 | return -ENOMEM; |
| 970 | } | 969 | } |
| 971 | 970 | ||
| @@ -975,7 +974,7 @@ static int edge_open(struct tty_struct *tty, | |||
| 975 | 974 | ||
| 976 | if (!edge_port->write_urb) { | 975 | if (!edge_port->write_urb) { |
| 977 | dbg("%s - no memory", __func__); | 976 | dbg("%s - no memory", __func__); |
| 978 | edge_close(tty, port, filp); | 977 | edge_close(port); |
| 979 | return -ENOMEM; | 978 | return -ENOMEM; |
| 980 | } | 979 | } |
| 981 | 980 | ||
| @@ -1099,8 +1098,7 @@ static void block_until_tx_empty(struct edgeport_port *edge_port) | |||
| 1099 | * edge_close | 1098 | * edge_close |
| 1100 | * this function is called by the tty driver when a port is closed | 1099 | * this function is called by the tty driver when a port is closed |
| 1101 | *****************************************************************************/ | 1100 | *****************************************************************************/ |
| 1102 | static void edge_close(struct tty_struct *tty, | 1101 | static void edge_close(struct usb_serial_port *port) |
| 1103 | struct usb_serial_port *port, struct file *filp) | ||
| 1104 | { | 1102 | { |
| 1105 | struct edgeport_serial *edge_serial; | 1103 | struct edgeport_serial *edge_serial; |
| 1106 | struct edgeport_port *edge_port; | 1104 | struct edgeport_port *edge_port; |
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c index 513b25e044c1..eabf20eeb370 100644 --- a/drivers/usb/serial/io_ti.c +++ b/drivers/usb/serial/io_ti.c | |||
| @@ -2009,8 +2009,7 @@ release_es_lock: | |||
| 2009 | return status; | 2009 | return status; |
| 2010 | } | 2010 | } |
| 2011 | 2011 | ||
| 2012 | static void edge_close(struct tty_struct *tty, | 2012 | static void edge_close(struct usb_serial_port *port) |
| 2013 | struct usb_serial_port *port, struct file *filp) | ||
| 2014 | { | 2013 | { |
| 2015 | struct edgeport_serial *edge_serial; | 2014 | struct edgeport_serial *edge_serial; |
| 2016 | struct edgeport_port *edge_port; | 2015 | struct edgeport_port *edge_port; |
diff --git a/drivers/usb/serial/ipaq.c b/drivers/usb/serial/ipaq.c index cd62825a9ac3..c610a99fa477 100644 --- a/drivers/usb/serial/ipaq.c +++ b/drivers/usb/serial/ipaq.c | |||
| @@ -76,8 +76,7 @@ static int initial_wait; | |||
| 76 | /* Function prototypes for an ipaq */ | 76 | /* Function prototypes for an ipaq */ |
| 77 | static int ipaq_open(struct tty_struct *tty, | 77 | static int ipaq_open(struct tty_struct *tty, |
| 78 | struct usb_serial_port *port, struct file *filp); | 78 | struct usb_serial_port *port, struct file *filp); |
| 79 | static void ipaq_close(struct tty_struct *tty, | 79 | static void ipaq_close(struct usb_serial_port *port); |
| 80 | struct usb_serial_port *port, struct file *filp); | ||
| 81 | static int ipaq_calc_num_ports(struct usb_serial *serial); | 80 | static int ipaq_calc_num_ports(struct usb_serial *serial); |
| 82 | static int ipaq_startup(struct usb_serial *serial); | 81 | static int ipaq_startup(struct usb_serial *serial); |
| 83 | static void ipaq_shutdown(struct usb_serial *serial); | 82 | static void ipaq_shutdown(struct usb_serial *serial); |
| @@ -714,8 +713,7 @@ error: | |||
| 714 | } | 713 | } |
| 715 | 714 | ||
| 716 | 715 | ||
| 717 | static void ipaq_close(struct tty_struct *tty, | 716 | static void ipaq_close(struct usb_serial_port *port) |
| 718 | struct usb_serial_port *port, struct file *filp) | ||
| 719 | { | 717 | { |
| 720 | struct ipaq_private *priv = usb_get_serial_port_data(port); | 718 | struct ipaq_private *priv = usb_get_serial_port_data(port); |
| 721 | 719 | ||
diff --git a/drivers/usb/serial/ipw.c b/drivers/usb/serial/ipw.c index da2a2b46644a..29ad038b9c8d 100644 --- a/drivers/usb/serial/ipw.c +++ b/drivers/usb/serial/ipw.c | |||
| @@ -302,23 +302,17 @@ static int ipw_open(struct tty_struct *tty, | |||
| 302 | return 0; | 302 | return 0; |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | static void ipw_close(struct tty_struct *tty, | 305 | static void ipw_dtr_rts(struct usb_serial_port *port, int on) |
| 306 | struct usb_serial_port *port, struct file *filp) | ||
| 307 | { | 306 | { |
| 308 | struct usb_device *dev = port->serial->dev; | 307 | struct usb_device *dev = port->serial->dev; |
| 309 | int result; | 308 | int result; |
| 310 | 309 | ||
| 311 | if (tty_hung_up_p(filp)) { | ||
| 312 | dbg("%s: tty_hung_up_p ...", __func__); | ||
| 313 | return; | ||
| 314 | } | ||
| 315 | |||
| 316 | /*--1: drop the dtr */ | 310 | /*--1: drop the dtr */ |
| 317 | dbg("%s:dropping dtr", __func__); | 311 | dbg("%s:dropping dtr", __func__); |
| 318 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 312 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| 319 | IPW_SIO_SET_PIN, | 313 | IPW_SIO_SET_PIN, |
| 320 | USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, | 314 | USB_TYPE_VENDOR | USB_RECIP_INTERFACE | USB_DIR_OUT, |
| 321 | IPW_PIN_CLRDTR, | 315 | on ? IPW_PIN_SETDTR : IPW_PIN_CLRDTR, |
| 322 | 0, | 316 | 0, |
| 323 | NULL, | 317 | NULL, |
| 324 | 0, | 318 | 0, |
| @@ -332,7 +326,7 @@ static void ipw_close(struct tty_struct *tty, | |||
| 332 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), | 326 | result = usb_control_msg(dev, usb_sndctrlpipe(dev, 0), |
| 333 | IPW_SIO_SET_PIN, USB_TYPE_VENDOR | | 327 | IPW_SIO_SET_PIN, USB_TYPE_VENDOR | |
| 334 | USB_RECIP_INTERFACE | USB_DIR_OUT, | 328 | USB_RECIP_INTERFACE | USB_DIR_OUT, |
| 335 | IPW_PIN_CLRRTS, | 329 | on ? IPW_PIN_SETRTS : IPW_PIN_CLRRTS, |
| 336 | 0, | 330 | 0, |
| 337 | NULL, | 331 | NULL, |
| 338 | 0, | 332 | 0, |
| @@ -340,7 +334,12 @@ static void ipw_close(struct tty_struct *tty, | |||
| 340 | if (result < 0) | 334 | if (result < 0) |
| 341 | dev_err(&port->dev, | 335 | dev_err(&port->dev, |
| 342 | "dropping rts failed (error = %d)\n", result); | 336 | "dropping rts failed (error = %d)\n", result); |
| 337 | } | ||
| 343 | 338 | ||
| 339 | static void ipw_close(struct usb_serial_port *port) | ||
| 340 | { | ||
| 341 | struct usb_device *dev = port->serial->dev; | ||
| 342 | int result; | ||
| 344 | 343 | ||
| 345 | /*--3: purge */ | 344 | /*--3: purge */ |
| 346 | dbg("%s:sending purge", __func__); | 345 | dbg("%s:sending purge", __func__); |
| @@ -461,6 +460,7 @@ static struct usb_serial_driver ipw_device = { | |||
| 461 | .num_ports = 1, | 460 | .num_ports = 1, |
| 462 | .open = ipw_open, | 461 | .open = ipw_open, |
| 463 | .close = ipw_close, | 462 | .close = ipw_close, |
| 463 | .dtr_rts = ipw_dtr_rts, | ||
| 464 | .port_probe = ipw_probe, | 464 | .port_probe = ipw_probe, |
| 465 | .port_remove = ipw_disconnect, | 465 | .port_remove = ipw_disconnect, |
| 466 | .write = ipw_write, | 466 | .write = ipw_write, |
diff --git a/drivers/usb/serial/ir-usb.c b/drivers/usb/serial/ir-usb.c index 4e2cda93da59..66009b6b763a 100644 --- a/drivers/usb/serial/ir-usb.c +++ b/drivers/usb/serial/ir-usb.c | |||
| @@ -88,8 +88,7 @@ static int xbof = -1; | |||
| 88 | static int ir_startup (struct usb_serial *serial); | 88 | static int ir_startup (struct usb_serial *serial); |
| 89 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port, | 89 | static int ir_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 90 | struct file *filep); | 90 | struct file *filep); |
| 91 | static void ir_close(struct tty_struct *tty, struct usb_serial_port *port, | 91 | static void ir_close(struct usb_serial_port *port); |
| 92 | struct file *filep); | ||
| 93 | static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, | 92 | static int ir_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 94 | const unsigned char *buf, int count); | 93 | const unsigned char *buf, int count); |
| 95 | static void ir_write_bulk_callback (struct urb *urb); | 94 | static void ir_write_bulk_callback (struct urb *urb); |
| @@ -346,8 +345,7 @@ static int ir_open(struct tty_struct *tty, | |||
| 346 | return result; | 345 | return result; |
| 347 | } | 346 | } |
| 348 | 347 | ||
| 349 | static void ir_close(struct tty_struct *tty, | 348 | static void ir_close(struct usb_serial_port *port) |
| 350 | struct usb_serial_port *port, struct file * filp) | ||
| 351 | { | 349 | { |
| 352 | dbg("%s - port %d", __func__, port->number); | 350 | dbg("%s - port %d", __func__, port->number); |
| 353 | 351 | ||
diff --git a/drivers/usb/serial/iuu_phoenix.c b/drivers/usb/serial/iuu_phoenix.c index 4473d442b2aa..76a3cc327bb9 100644 --- a/drivers/usb/serial/iuu_phoenix.c +++ b/drivers/usb/serial/iuu_phoenix.c | |||
| @@ -40,7 +40,7 @@ static int debug; | |||
| 40 | /* | 40 | /* |
| 41 | * Version Information | 41 | * Version Information |
| 42 | */ | 42 | */ |
| 43 | #define DRIVER_VERSION "v0.5" | 43 | #define DRIVER_VERSION "v0.10" |
| 44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" | 44 | #define DRIVER_DESC "Infinity USB Unlimited Phoenix driver" |
| 45 | 45 | ||
| 46 | static struct usb_device_id id_table[] = { | 46 | static struct usb_device_id id_table[] = { |
| @@ -70,7 +70,6 @@ static void read_rxcmd_callback(struct urb *urb); | |||
| 70 | struct iuu_private { | 70 | struct iuu_private { |
| 71 | spinlock_t lock; /* store irq state */ | 71 | spinlock_t lock; /* store irq state */ |
| 72 | wait_queue_head_t delta_msr_wait; | 72 | wait_queue_head_t delta_msr_wait; |
| 73 | u8 line_control; | ||
| 74 | u8 line_status; | 73 | u8 line_status; |
| 75 | u8 termios_initialized; | 74 | u8 termios_initialized; |
| 76 | int tiostatus; /* store IUART SIGNAL for tiocmget call */ | 75 | int tiostatus; /* store IUART SIGNAL for tiocmget call */ |
| @@ -651,32 +650,33 @@ static int iuu_bulk_write(struct usb_serial_port *port) | |||
| 651 | unsigned long flags; | 650 | unsigned long flags; |
| 652 | int result; | 651 | int result; |
| 653 | int i; | 652 | int i; |
| 653 | int buf_len; | ||
| 654 | char *buf_ptr = port->write_urb->transfer_buffer; | 654 | char *buf_ptr = port->write_urb->transfer_buffer; |
| 655 | dbg("%s - enter", __func__); | 655 | dbg("%s - enter", __func__); |
| 656 | 656 | ||
| 657 | spin_lock_irqsave(&priv->lock, flags); | ||
| 657 | *buf_ptr++ = IUU_UART_ESC; | 658 | *buf_ptr++ = IUU_UART_ESC; |
| 658 | *buf_ptr++ = IUU_UART_TX; | 659 | *buf_ptr++ = IUU_UART_TX; |
| 659 | *buf_ptr++ = priv->writelen; | 660 | *buf_ptr++ = priv->writelen; |
| 660 | 661 | ||
| 661 | memcpy(buf_ptr, priv->writebuf, | 662 | memcpy(buf_ptr, priv->writebuf, priv->writelen); |
| 662 | priv->writelen); | 663 | buf_len = priv->writelen; |
| 664 | priv->writelen = 0; | ||
| 665 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 663 | if (debug == 1) { | 666 | if (debug == 1) { |
| 664 | for (i = 0; i < priv->writelen; i++) | 667 | for (i = 0; i < buf_len; i++) |
| 665 | sprintf(priv->dbgbuf + i*2 , | 668 | sprintf(priv->dbgbuf + i*2 , |
| 666 | "%02X", priv->writebuf[i]); | 669 | "%02X", priv->writebuf[i]); |
| 667 | priv->dbgbuf[priv->writelen+i*2] = 0; | 670 | priv->dbgbuf[buf_len+i*2] = 0; |
| 668 | dbg("%s - writing %i chars : %s", __func__, | 671 | dbg("%s - writing %i chars : %s", __func__, |
| 669 | priv->writelen, priv->dbgbuf); | 672 | buf_len, priv->dbgbuf); |
| 670 | } | 673 | } |
| 671 | usb_fill_bulk_urb(port->write_urb, port->serial->dev, | 674 | usb_fill_bulk_urb(port->write_urb, port->serial->dev, |
| 672 | usb_sndbulkpipe(port->serial->dev, | 675 | usb_sndbulkpipe(port->serial->dev, |
| 673 | port->bulk_out_endpointAddress), | 676 | port->bulk_out_endpointAddress), |
| 674 | port->write_urb->transfer_buffer, priv->writelen + 3, | 677 | port->write_urb->transfer_buffer, buf_len + 3, |
| 675 | iuu_rxcmd, port); | 678 | iuu_rxcmd, port); |
| 676 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); | 679 | result = usb_submit_urb(port->write_urb, GFP_ATOMIC); |
| 677 | spin_lock_irqsave(&priv->lock, flags); | ||
| 678 | priv->writelen = 0; | ||
| 679 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 680 | usb_serial_port_softint(port); | 680 | usb_serial_port_softint(port); |
| 681 | return result; | 681 | return result; |
| 682 | } | 682 | } |
| @@ -770,14 +770,10 @@ static int iuu_uart_write(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 770 | return -ENOMEM; | 770 | return -ENOMEM; |
| 771 | 771 | ||
| 772 | spin_lock_irqsave(&priv->lock, flags); | 772 | spin_lock_irqsave(&priv->lock, flags); |
| 773 | if (priv->writelen > 0) { | 773 | |
| 774 | /* buffer already filled but not commited */ | ||
| 775 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 776 | return 0; | ||
| 777 | } | ||
| 778 | /* fill the buffer */ | 774 | /* fill the buffer */ |
| 779 | memcpy(priv->writebuf, buf, count); | 775 | memcpy(priv->writebuf + priv->writelen, buf, count); |
| 780 | priv->writelen = count; | 776 | priv->writelen += count; |
| 781 | spin_unlock_irqrestore(&priv->lock, flags); | 777 | spin_unlock_irqrestore(&priv->lock, flags); |
| 782 | 778 | ||
| 783 | return count; | 779 | return count; |
| @@ -819,7 +815,7 @@ static int iuu_uart_on(struct usb_serial_port *port) | |||
| 819 | buf[0] = IUU_UART_ENABLE; | 815 | buf[0] = IUU_UART_ENABLE; |
| 820 | buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF); | 816 | buf[1] = (u8) ((IUU_BAUD_9600 >> 8) & 0x00FF); |
| 821 | buf[2] = (u8) (0x00FF & IUU_BAUD_9600); | 817 | buf[2] = (u8) (0x00FF & IUU_BAUD_9600); |
| 822 | buf[3] = (u8) (0x0F0 & IUU_TWO_STOP_BITS) | (0x07 & IUU_PARITY_EVEN); | 818 | buf[3] = (u8) (0x0F0 & IUU_ONE_STOP_BIT) | (0x07 & IUU_PARITY_EVEN); |
| 823 | 819 | ||
| 824 | status = bulk_immediate(port, buf, 4); | 820 | status = bulk_immediate(port, buf, 4); |
| 825 | if (status != IUU_OPERATION_OK) { | 821 | if (status != IUU_OPERATION_OK) { |
| @@ -946,19 +942,59 @@ static int iuu_uart_baud(struct usb_serial_port *port, u32 baud, | |||
| 946 | return status; | 942 | return status; |
| 947 | } | 943 | } |
| 948 | 944 | ||
| 949 | static int set_control_lines(struct usb_device *dev, u8 value) | 945 | static void iuu_set_termios(struct tty_struct *tty, |
| 946 | struct usb_serial_port *port, struct ktermios *old_termios) | ||
| 950 | { | 947 | { |
| 951 | return 0; | 948 | const u32 supported_mask = CMSPAR|PARENB|PARODD; |
| 949 | |||
| 950 | unsigned int cflag = tty->termios->c_cflag; | ||
| 951 | int status; | ||
| 952 | u32 actual; | ||
| 953 | u32 parity; | ||
| 954 | int csize = CS7; | ||
| 955 | int baud = 9600; /* Fixed for the moment */ | ||
| 956 | u32 newval = cflag & supported_mask; | ||
| 957 | |||
| 958 | /* compute the parity parameter */ | ||
| 959 | parity = 0; | ||
| 960 | if (cflag & CMSPAR) { /* Using mark space */ | ||
| 961 | if (cflag & PARODD) | ||
| 962 | parity |= IUU_PARITY_SPACE; | ||
| 963 | else | ||
| 964 | parity |= IUU_PARITY_MARK; | ||
| 965 | } else if (!(cflag & PARENB)) { | ||
| 966 | parity |= IUU_PARITY_NONE; | ||
| 967 | csize = CS8; | ||
| 968 | } else if (cflag & PARODD) | ||
| 969 | parity |= IUU_PARITY_ODD; | ||
| 970 | else | ||
| 971 | parity |= IUU_PARITY_EVEN; | ||
| 972 | |||
| 973 | parity |= (cflag & CSTOPB ? IUU_TWO_STOP_BITS : IUU_ONE_STOP_BIT); | ||
| 974 | |||
| 975 | /* set it */ | ||
| 976 | status = iuu_uart_baud(port, | ||
| 977 | (clockmode == 2) ? 16457 : 9600 * boost / 100, | ||
| 978 | &actual, parity); | ||
| 979 | |||
| 980 | /* set the termios value to the real one, so the user now what has | ||
| 981 | * changed. We support few fields so its easies to copy the old hw | ||
| 982 | * settings back over and then adjust them | ||
| 983 | */ | ||
| 984 | if (old_termios) | ||
| 985 | tty_termios_copy_hw(tty->termios, old_termios); | ||
| 986 | if (status != 0) /* Set failed - return old bits */ | ||
| 987 | return; | ||
| 988 | /* Re-encode speed, parity and csize */ | ||
| 989 | tty_encode_baud_rate(tty, baud, baud); | ||
| 990 | tty->termios->c_cflag &= ~(supported_mask|CSIZE); | ||
| 991 | tty->termios->c_cflag |= newval | csize; | ||
| 952 | } | 992 | } |
| 953 | 993 | ||
| 954 | static void iuu_close(struct tty_struct *tty, | 994 | static void iuu_close(struct usb_serial_port *port) |
| 955 | struct usb_serial_port *port, struct file *filp) | ||
| 956 | { | 995 | { |
| 957 | /* iuu_led (port,255,0,0,0); */ | 996 | /* iuu_led (port,255,0,0,0); */ |
| 958 | struct usb_serial *serial; | 997 | struct usb_serial *serial; |
| 959 | struct iuu_private *priv = usb_get_serial_port_data(port); | ||
| 960 | unsigned long flags; | ||
| 961 | unsigned int c_cflag; | ||
| 962 | 998 | ||
| 963 | serial = port->serial; | 999 | serial = port->serial; |
| 964 | if (!serial) | 1000 | if (!serial) |
| @@ -968,17 +1004,6 @@ static void iuu_close(struct tty_struct *tty, | |||
| 968 | 1004 | ||
| 969 | iuu_uart_off(port); | 1005 | iuu_uart_off(port); |
| 970 | if (serial->dev) { | 1006 | if (serial->dev) { |
| 971 | if (tty) { | ||
| 972 | c_cflag = tty->termios->c_cflag; | ||
| 973 | if (c_cflag & HUPCL) { | ||
| 974 | /* drop DTR and RTS */ | ||
| 975 | priv = usb_get_serial_port_data(port); | ||
| 976 | spin_lock_irqsave(&priv->lock, flags); | ||
| 977 | priv->line_control = 0; | ||
| 978 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 979 | set_control_lines(port->serial->dev, 0); | ||
| 980 | } | ||
| 981 | } | ||
| 982 | /* free writebuf */ | 1007 | /* free writebuf */ |
| 983 | /* shutdown our urbs */ | 1008 | /* shutdown our urbs */ |
| 984 | dbg("%s - shutting down urbs", __func__); | 1009 | dbg("%s - shutting down urbs", __func__); |
| @@ -1154,7 +1179,7 @@ static int iuu_open(struct tty_struct *tty, | |||
| 1154 | if (result) { | 1179 | if (result) { |
| 1155 | dev_err(&port->dev, "%s - failed submitting read urb," | 1180 | dev_err(&port->dev, "%s - failed submitting read urb," |
| 1156 | " error %d\n", __func__, result); | 1181 | " error %d\n", __func__, result); |
| 1157 | iuu_close(tty, port, NULL); | 1182 | iuu_close(port); |
| 1158 | return -EPROTO; | 1183 | return -EPROTO; |
| 1159 | } else { | 1184 | } else { |
| 1160 | dbg("%s - rxcmd OK", __func__); | 1185 | dbg("%s - rxcmd OK", __func__); |
| @@ -1175,6 +1200,7 @@ static struct usb_serial_driver iuu_device = { | |||
| 1175 | .read_bulk_callback = iuu_uart_read_callback, | 1200 | .read_bulk_callback = iuu_uart_read_callback, |
| 1176 | .tiocmget = iuu_tiocmget, | 1201 | .tiocmget = iuu_tiocmget, |
| 1177 | .tiocmset = iuu_tiocmset, | 1202 | .tiocmset = iuu_tiocmset, |
| 1203 | .set_termios = iuu_set_termios, | ||
| 1178 | .attach = iuu_startup, | 1204 | .attach = iuu_startup, |
| 1179 | .shutdown = iuu_shutdown, | 1205 | .shutdown = iuu_shutdown, |
| 1180 | }; | 1206 | }; |
diff --git a/drivers/usb/serial/keyspan.c b/drivers/usb/serial/keyspan.c index 00daa8f7759a..f1195a98f316 100644 --- a/drivers/usb/serial/keyspan.c +++ b/drivers/usb/serial/keyspan.c | |||
| @@ -1298,8 +1298,16 @@ static inline void stop_urb(struct urb *urb) | |||
| 1298 | usb_kill_urb(urb); | 1298 | usb_kill_urb(urb); |
| 1299 | } | 1299 | } |
| 1300 | 1300 | ||
| 1301 | static void keyspan_close(struct tty_struct *tty, | 1301 | static void keyspan_dtr_rts(struct usb_serial_port *port, int on) |
| 1302 | struct usb_serial_port *port, struct file *filp) | 1302 | { |
| 1303 | struct keyspan_port_private *p_priv = usb_get_serial_port_data(port); | ||
| 1304 | |||
| 1305 | p_priv->rts_state = on; | ||
| 1306 | p_priv->dtr_state = on; | ||
| 1307 | keyspan_send_setup(port, 0); | ||
| 1308 | } | ||
| 1309 | |||
| 1310 | static void keyspan_close(struct usb_serial_port *port) | ||
| 1303 | { | 1311 | { |
| 1304 | int i; | 1312 | int i; |
| 1305 | struct usb_serial *serial = port->serial; | 1313 | struct usb_serial *serial = port->serial; |
| @@ -1336,7 +1344,6 @@ static void keyspan_close(struct tty_struct *tty, | |||
| 1336 | stop_urb(p_priv->out_urbs[i]); | 1344 | stop_urb(p_priv->out_urbs[i]); |
| 1337 | } | 1345 | } |
| 1338 | } | 1346 | } |
| 1339 | tty_port_tty_set(&port->port, NULL); | ||
| 1340 | } | 1347 | } |
| 1341 | 1348 | ||
| 1342 | /* download the firmware to a pre-renumeration device */ | 1349 | /* download the firmware to a pre-renumeration device */ |
diff --git a/drivers/usb/serial/keyspan.h b/drivers/usb/serial/keyspan.h index 38b4582e0734..0d4569b60768 100644 --- a/drivers/usb/serial/keyspan.h +++ b/drivers/usb/serial/keyspan.h | |||
| @@ -38,9 +38,8 @@ | |||
| 38 | static int keyspan_open (struct tty_struct *tty, | 38 | static int keyspan_open (struct tty_struct *tty, |
| 39 | struct usb_serial_port *port, | 39 | struct usb_serial_port *port, |
| 40 | struct file *filp); | 40 | struct file *filp); |
| 41 | static void keyspan_close (struct tty_struct *tty, | 41 | static void keyspan_close (struct usb_serial_port *port); |
| 42 | struct usb_serial_port *port, | 42 | static void keyspan_dtr_rts (struct usb_serial_port *port, int on); |
| 43 | struct file *filp); | ||
| 44 | static int keyspan_startup (struct usb_serial *serial); | 43 | static int keyspan_startup (struct usb_serial *serial); |
| 45 | static void keyspan_shutdown (struct usb_serial *serial); | 44 | static void keyspan_shutdown (struct usb_serial *serial); |
| 46 | static int keyspan_write_room (struct tty_struct *tty); | 45 | static int keyspan_write_room (struct tty_struct *tty); |
| @@ -562,6 +561,7 @@ static struct usb_serial_driver keyspan_1port_device = { | |||
| 562 | .num_ports = 1, | 561 | .num_ports = 1, |
| 563 | .open = keyspan_open, | 562 | .open = keyspan_open, |
| 564 | .close = keyspan_close, | 563 | .close = keyspan_close, |
| 564 | .dtr_rts = keyspan_dtr_rts, | ||
| 565 | .write = keyspan_write, | 565 | .write = keyspan_write, |
| 566 | .write_room = keyspan_write_room, | 566 | .write_room = keyspan_write_room, |
| 567 | .set_termios = keyspan_set_termios, | 567 | .set_termios = keyspan_set_termios, |
| @@ -582,6 +582,7 @@ static struct usb_serial_driver keyspan_2port_device = { | |||
| 582 | .num_ports = 2, | 582 | .num_ports = 2, |
| 583 | .open = keyspan_open, | 583 | .open = keyspan_open, |
| 584 | .close = keyspan_close, | 584 | .close = keyspan_close, |
| 585 | .dtr_rts = keyspan_dtr_rts, | ||
| 585 | .write = keyspan_write, | 586 | .write = keyspan_write, |
| 586 | .write_room = keyspan_write_room, | 587 | .write_room = keyspan_write_room, |
| 587 | .set_termios = keyspan_set_termios, | 588 | .set_termios = keyspan_set_termios, |
| @@ -602,6 +603,7 @@ static struct usb_serial_driver keyspan_4port_device = { | |||
| 602 | .num_ports = 4, | 603 | .num_ports = 4, |
| 603 | .open = keyspan_open, | 604 | .open = keyspan_open, |
| 604 | .close = keyspan_close, | 605 | .close = keyspan_close, |
| 606 | .dtr_rts = keyspan_dtr_rts, | ||
| 605 | .write = keyspan_write, | 607 | .write = keyspan_write, |
| 606 | .write_room = keyspan_write_room, | 608 | .write_room = keyspan_write_room, |
| 607 | .set_termios = keyspan_set_termios, | 609 | .set_termios = keyspan_set_termios, |
diff --git a/drivers/usb/serial/keyspan_pda.c b/drivers/usb/serial/keyspan_pda.c index bf1ae247da66..ab769dbea1b3 100644 --- a/drivers/usb/serial/keyspan_pda.c +++ b/drivers/usb/serial/keyspan_pda.c | |||
| @@ -651,6 +651,35 @@ static int keyspan_pda_chars_in_buffer(struct tty_struct *tty) | |||
| 651 | } | 651 | } |
| 652 | 652 | ||
| 653 | 653 | ||
| 654 | static void keyspan_pda_dtr_rts(struct usb_serial_port *port, int on) | ||
| 655 | { | ||
| 656 | struct usb_serial *serial = port->serial; | ||
| 657 | |||
| 658 | if (serial->dev) { | ||
| 659 | if (on) | ||
| 660 | keyspan_pda_set_modem_info(serial, (1<<7) | (1<< 2)); | ||
| 661 | else | ||
| 662 | keyspan_pda_set_modem_info(serial, 0); | ||
| 663 | } | ||
| 664 | } | ||
| 665 | |||
| 666 | static int keyspan_pda_carrier_raised(struct usb_serial_port *port) | ||
| 667 | { | ||
| 668 | struct usb_serial *serial = port->serial; | ||
| 669 | unsigned char modembits; | ||
| 670 | |||
| 671 | /* If we can read the modem status and the DCD is low then | ||
| 672 | carrier is not raised yet */ | ||
| 673 | if (keyspan_pda_get_modem_info(serial, &modembits) >= 0) { | ||
| 674 | if (!(modembits & (1>>6))) | ||
| 675 | return 0; | ||
| 676 | } | ||
| 677 | /* Carrier raised, or we failed (eg disconnected) so | ||
| 678 | progress accordingly */ | ||
| 679 | return 1; | ||
| 680 | } | ||
| 681 | |||
| 682 | |||
| 654 | static int keyspan_pda_open(struct tty_struct *tty, | 683 | static int keyspan_pda_open(struct tty_struct *tty, |
| 655 | struct usb_serial_port *port, struct file *filp) | 684 | struct usb_serial_port *port, struct file *filp) |
| 656 | { | 685 | { |
| @@ -682,13 +711,6 @@ static int keyspan_pda_open(struct tty_struct *tty, | |||
| 682 | priv->tx_room = room; | 711 | priv->tx_room = room; |
| 683 | priv->tx_throttled = room ? 0 : 1; | 712 | priv->tx_throttled = room ? 0 : 1; |
| 684 | 713 | ||
| 685 | /* the normal serial device seems to always turn on DTR and RTS here, | ||
| 686 | so do the same */ | ||
| 687 | if (tty && (tty->termios->c_cflag & CBAUD)) | ||
| 688 | keyspan_pda_set_modem_info(serial, (1<<7) | (1<<2)); | ||
| 689 | else | ||
| 690 | keyspan_pda_set_modem_info(serial, 0); | ||
| 691 | |||
| 692 | /*Start reading from the device*/ | 714 | /*Start reading from the device*/ |
| 693 | port->interrupt_in_urb->dev = serial->dev; | 715 | port->interrupt_in_urb->dev = serial->dev; |
| 694 | rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 716 | rc = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); |
| @@ -700,19 +722,11 @@ static int keyspan_pda_open(struct tty_struct *tty, | |||
| 700 | error: | 722 | error: |
| 701 | return rc; | 723 | return rc; |
| 702 | } | 724 | } |
| 703 | 725 | static void keyspan_pda_close(struct usb_serial_port *port) | |
| 704 | |||
| 705 | static void keyspan_pda_close(struct tty_struct *tty, | ||
| 706 | struct usb_serial_port *port, struct file *filp) | ||
| 707 | { | 726 | { |
| 708 | struct usb_serial *serial = port->serial; | 727 | struct usb_serial *serial = port->serial; |
| 709 | 728 | ||
| 710 | if (serial->dev) { | 729 | if (serial->dev) { |
| 711 | /* the normal serial device seems to always shut | ||
| 712 | off DTR and RTS now */ | ||
| 713 | if (tty->termios->c_cflag & HUPCL) | ||
| 714 | keyspan_pda_set_modem_info(serial, 0); | ||
| 715 | |||
| 716 | /* shutdown our bulk reads and writes */ | 730 | /* shutdown our bulk reads and writes */ |
| 717 | usb_kill_urb(port->write_urb); | 731 | usb_kill_urb(port->write_urb); |
| 718 | usb_kill_urb(port->interrupt_in_urb); | 732 | usb_kill_urb(port->interrupt_in_urb); |
| @@ -839,6 +853,8 @@ static struct usb_serial_driver keyspan_pda_device = { | |||
| 839 | .usb_driver = &keyspan_pda_driver, | 853 | .usb_driver = &keyspan_pda_driver, |
| 840 | .id_table = id_table_std, | 854 | .id_table = id_table_std, |
| 841 | .num_ports = 1, | 855 | .num_ports = 1, |
| 856 | .dtr_rts = keyspan_pda_dtr_rts, | ||
| 857 | .carrier_raised = keyspan_pda_carrier_raised, | ||
| 842 | .open = keyspan_pda_open, | 858 | .open = keyspan_pda_open, |
| 843 | .close = keyspan_pda_close, | 859 | .close = keyspan_pda_close, |
| 844 | .write = keyspan_pda_write, | 860 | .write = keyspan_pda_write, |
diff --git a/drivers/usb/serial/kl5kusb105.c b/drivers/usb/serial/kl5kusb105.c index fcd9082f3e7f..fa817c66b3e8 100644 --- a/drivers/usb/serial/kl5kusb105.c +++ b/drivers/usb/serial/kl5kusb105.c | |||
| @@ -76,8 +76,7 @@ static int klsi_105_startup(struct usb_serial *serial); | |||
| 76 | static void klsi_105_shutdown(struct usb_serial *serial); | 76 | static void klsi_105_shutdown(struct usb_serial *serial); |
| 77 | static int klsi_105_open(struct tty_struct *tty, | 77 | static int klsi_105_open(struct tty_struct *tty, |
| 78 | struct usb_serial_port *port, struct file *filp); | 78 | struct usb_serial_port *port, struct file *filp); |
| 79 | static void klsi_105_close(struct tty_struct *tty, | 79 | static void klsi_105_close(struct usb_serial_port *port); |
| 80 | struct usb_serial_port *port, struct file *filp); | ||
| 81 | static int klsi_105_write(struct tty_struct *tty, | 80 | static int klsi_105_write(struct tty_struct *tty, |
| 82 | struct usb_serial_port *port, const unsigned char *buf, int count); | 81 | struct usb_serial_port *port, const unsigned char *buf, int count); |
| 83 | static void klsi_105_write_bulk_callback(struct urb *urb); | 82 | static void klsi_105_write_bulk_callback(struct urb *urb); |
| @@ -447,8 +446,7 @@ exit: | |||
| 447 | } /* klsi_105_open */ | 446 | } /* klsi_105_open */ |
| 448 | 447 | ||
| 449 | 448 | ||
| 450 | static void klsi_105_close(struct tty_struct *tty, | 449 | static void klsi_105_close(struct usb_serial_port *port) |
| 451 | struct usb_serial_port *port, struct file *filp) | ||
| 452 | { | 450 | { |
| 453 | struct klsi_105_private *priv = usb_get_serial_port_data(port); | 451 | struct klsi_105_private *priv = usb_get_serial_port_data(port); |
| 454 | int rc; | 452 | int rc; |
diff --git a/drivers/usb/serial/kobil_sct.c b/drivers/usb/serial/kobil_sct.c index c148544953b3..6b570498287f 100644 --- a/drivers/usb/serial/kobil_sct.c +++ b/drivers/usb/serial/kobil_sct.c | |||
| @@ -72,8 +72,7 @@ static int kobil_startup(struct usb_serial *serial); | |||
| 72 | static void kobil_shutdown(struct usb_serial *serial); | 72 | static void kobil_shutdown(struct usb_serial *serial); |
| 73 | static int kobil_open(struct tty_struct *tty, | 73 | static int kobil_open(struct tty_struct *tty, |
| 74 | struct usb_serial_port *port, struct file *filp); | 74 | struct usb_serial_port *port, struct file *filp); |
| 75 | static void kobil_close(struct tty_struct *tty, struct usb_serial_port *port, | 75 | static void kobil_close(struct usb_serial_port *port); |
| 76 | struct file *filp); | ||
| 77 | static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, | 76 | static int kobil_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 78 | const unsigned char *buf, int count); | 77 | const unsigned char *buf, int count); |
| 79 | static int kobil_write_room(struct tty_struct *tty); | 78 | static int kobil_write_room(struct tty_struct *tty); |
| @@ -209,7 +208,7 @@ static void kobil_shutdown(struct usb_serial *serial) | |||
| 209 | 208 | ||
| 210 | for (i = 0; i < serial->num_ports; ++i) { | 209 | for (i = 0; i < serial->num_ports; ++i) { |
| 211 | while (serial->port[i]->port.count > 0) | 210 | while (serial->port[i]->port.count > 0) |
| 212 | kobil_close(NULL, serial->port[i], NULL); | 211 | kobil_close(serial->port[i]); |
| 213 | kfree(usb_get_serial_port_data(serial->port[i])); | 212 | kfree(usb_get_serial_port_data(serial->port[i])); |
| 214 | usb_set_serial_port_data(serial->port[i], NULL); | 213 | usb_set_serial_port_data(serial->port[i], NULL); |
| 215 | } | 214 | } |
| @@ -346,11 +345,11 @@ static int kobil_open(struct tty_struct *tty, | |||
| 346 | } | 345 | } |
| 347 | 346 | ||
| 348 | 347 | ||
| 349 | static void kobil_close(struct tty_struct *tty, | 348 | static void kobil_close(struct usb_serial_port *port) |
| 350 | struct usb_serial_port *port, struct file *filp) | ||
| 351 | { | 349 | { |
| 352 | dbg("%s - port %d", __func__, port->number); | 350 | dbg("%s - port %d", __func__, port->number); |
| 353 | 351 | ||
| 352 | /* FIXME: Add rts/dtr methods */ | ||
| 354 | if (port->write_urb) { | 353 | if (port->write_urb) { |
| 355 | usb_kill_urb(port->write_urb); | 354 | usb_kill_urb(port->write_urb); |
| 356 | usb_free_urb(port->write_urb); | 355 | usb_free_urb(port->write_urb); |
diff --git a/drivers/usb/serial/mct_u232.c b/drivers/usb/serial/mct_u232.c index 82930a7d5093..873795548fc0 100644 --- a/drivers/usb/serial/mct_u232.c +++ b/drivers/usb/serial/mct_u232.c | |||
| @@ -95,8 +95,8 @@ static int mct_u232_startup(struct usb_serial *serial); | |||
| 95 | static void mct_u232_shutdown(struct usb_serial *serial); | 95 | static void mct_u232_shutdown(struct usb_serial *serial); |
| 96 | static int mct_u232_open(struct tty_struct *tty, | 96 | static int mct_u232_open(struct tty_struct *tty, |
| 97 | struct usb_serial_port *port, struct file *filp); | 97 | struct usb_serial_port *port, struct file *filp); |
| 98 | static void mct_u232_close(struct tty_struct *tty, | 98 | static void mct_u232_close(struct usb_serial_port *port); |
| 99 | struct usb_serial_port *port, struct file *filp); | 99 | static void mct_u232_dtr_rts(struct usb_serial_port *port, int on); |
| 100 | static void mct_u232_read_int_callback(struct urb *urb); | 100 | static void mct_u232_read_int_callback(struct urb *urb); |
| 101 | static void mct_u232_set_termios(struct tty_struct *tty, | 101 | static void mct_u232_set_termios(struct tty_struct *tty, |
| 102 | struct usb_serial_port *port, struct ktermios *old); | 102 | struct usb_serial_port *port, struct ktermios *old); |
| @@ -140,6 +140,7 @@ static struct usb_serial_driver mct_u232_device = { | |||
| 140 | .num_ports = 1, | 140 | .num_ports = 1, |
| 141 | .open = mct_u232_open, | 141 | .open = mct_u232_open, |
| 142 | .close = mct_u232_close, | 142 | .close = mct_u232_close, |
| 143 | .dtr_rts = mct_u232_dtr_rts, | ||
| 143 | .throttle = mct_u232_throttle, | 144 | .throttle = mct_u232_throttle, |
| 144 | .unthrottle = mct_u232_unthrottle, | 145 | .unthrottle = mct_u232_unthrottle, |
| 145 | .read_int_callback = mct_u232_read_int_callback, | 146 | .read_int_callback = mct_u232_read_int_callback, |
| @@ -496,29 +497,29 @@ error: | |||
| 496 | return retval; | 497 | return retval; |
| 497 | } /* mct_u232_open */ | 498 | } /* mct_u232_open */ |
| 498 | 499 | ||
| 499 | 500 | static void mct_u232_dtr_rts(struct usb_serial_port *port, int on) | |
| 500 | static void mct_u232_close(struct tty_struct *tty, | ||
| 501 | struct usb_serial_port *port, struct file *filp) | ||
| 502 | { | 501 | { |
| 503 | unsigned int c_cflag; | ||
| 504 | unsigned int control_state; | 502 | unsigned int control_state; |
| 505 | struct mct_u232_private *priv = usb_get_serial_port_data(port); | 503 | struct mct_u232_private *priv = usb_get_serial_port_data(port); |
| 506 | dbg("%s port %d", __func__, port->number); | ||
| 507 | 504 | ||
| 508 | if (tty) { | 505 | mutex_lock(&port->serial->disc_mutex); |
| 509 | c_cflag = tty->termios->c_cflag; | 506 | if (!port->serial->disconnected) { |
| 510 | mutex_lock(&port->serial->disc_mutex); | 507 | /* drop DTR and RTS */ |
| 511 | if (c_cflag & HUPCL && !port->serial->disconnected) { | 508 | spin_lock_irq(&priv->lock); |
| 512 | /* drop DTR and RTS */ | 509 | if (on) |
| 513 | spin_lock_irq(&priv->lock); | 510 | priv->control_state |= TIOCM_DTR | TIOCM_RTS; |
| 511 | else | ||
| 514 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); | 512 | priv->control_state &= ~(TIOCM_DTR | TIOCM_RTS); |
| 515 | control_state = priv->control_state; | 513 | control_state = priv->control_state; |
| 516 | spin_unlock_irq(&priv->lock); | 514 | spin_unlock_irq(&priv->lock); |
| 517 | mct_u232_set_modem_ctrl(port->serial, control_state); | 515 | mct_u232_set_modem_ctrl(port->serial, control_state); |
| 518 | } | ||
| 519 | mutex_unlock(&port->serial->disc_mutex); | ||
| 520 | } | 516 | } |
| 517 | mutex_unlock(&port->serial->disc_mutex); | ||
| 518 | } | ||
| 521 | 519 | ||
| 520 | static void mct_u232_close(struct usb_serial_port *port) | ||
| 521 | { | ||
| 522 | dbg("%s port %d", __func__, port->number); | ||
| 522 | 523 | ||
| 523 | if (port->serial->dev) { | 524 | if (port->serial->dev) { |
| 524 | /* shutdown our urbs */ | 525 | /* shutdown our urbs */ |
diff --git a/drivers/usb/serial/mos7720.c b/drivers/usb/serial/mos7720.c index 24e3b5d4b4d4..9e1a013ee7f6 100644 --- a/drivers/usb/serial/mos7720.c +++ b/drivers/usb/serial/mos7720.c | |||
| @@ -533,8 +533,7 @@ static int mos7720_chars_in_buffer(struct tty_struct *tty) | |||
| 533 | return chars; | 533 | return chars; |
| 534 | } | 534 | } |
| 535 | 535 | ||
| 536 | static void mos7720_close(struct tty_struct *tty, | 536 | static void mos7720_close(struct usb_serial_port *port) |
| 537 | struct usb_serial_port *port, struct file *filp) | ||
| 538 | { | 537 | { |
| 539 | struct usb_serial *serial; | 538 | struct usb_serial *serial; |
| 540 | struct moschip_port *mos7720_port; | 539 | struct moschip_port *mos7720_port; |
diff --git a/drivers/usb/serial/mos7840.c b/drivers/usb/serial/mos7840.c index 84fb1dcd30dc..10b78a37214f 100644 --- a/drivers/usb/serial/mos7840.c +++ b/drivers/usb/serial/mos7840.c | |||
| @@ -1135,54 +1135,12 @@ static int mos7840_chars_in_buffer(struct tty_struct *tty) | |||
| 1135 | 1135 | ||
| 1136 | } | 1136 | } |
| 1137 | 1137 | ||
| 1138 | /************************************************************************ | ||
| 1139 | * | ||
| 1140 | * mos7840_block_until_tx_empty | ||
| 1141 | * | ||
| 1142 | * This function will block the close until one of the following: | ||
| 1143 | * 1. TX count are 0 | ||
| 1144 | * 2. The mos7840 has stopped | ||
| 1145 | * 3. A timeout of 3 seconds without activity has expired | ||
| 1146 | * | ||
| 1147 | ************************************************************************/ | ||
| 1148 | static void mos7840_block_until_tx_empty(struct tty_struct *tty, | ||
| 1149 | struct moschip_port *mos7840_port) | ||
| 1150 | { | ||
| 1151 | int timeout = HZ / 10; | ||
| 1152 | int wait = 30; | ||
| 1153 | int count; | ||
| 1154 | |||
| 1155 | while (1) { | ||
| 1156 | |||
| 1157 | count = mos7840_chars_in_buffer(tty); | ||
| 1158 | |||
| 1159 | /* Check for Buffer status */ | ||
| 1160 | if (count <= 0) | ||
| 1161 | return; | ||
| 1162 | |||
| 1163 | /* Block the thread for a while */ | ||
| 1164 | interruptible_sleep_on_timeout(&mos7840_port->wait_chase, | ||
| 1165 | timeout); | ||
| 1166 | |||
| 1167 | /* No activity.. count down section */ | ||
| 1168 | wait--; | ||
| 1169 | if (wait == 0) { | ||
| 1170 | dbg("%s - TIMEOUT", __func__); | ||
| 1171 | return; | ||
| 1172 | } else { | ||
| 1173 | /* Reset timeout value back to seconds */ | ||
| 1174 | wait = 30; | ||
| 1175 | } | ||
| 1176 | } | ||
| 1177 | } | ||
| 1178 | |||
| 1179 | /***************************************************************************** | 1138 | /***************************************************************************** |
| 1180 | * mos7840_close | 1139 | * mos7840_close |
| 1181 | * this function is called by the tty driver when a port is closed | 1140 | * this function is called by the tty driver when a port is closed |
| 1182 | *****************************************************************************/ | 1141 | *****************************************************************************/ |
| 1183 | 1142 | ||
| 1184 | static void mos7840_close(struct tty_struct *tty, | 1143 | static void mos7840_close(struct usb_serial_port *port) |
| 1185 | struct usb_serial_port *port, struct file *filp) | ||
| 1186 | { | 1144 | { |
| 1187 | struct usb_serial *serial; | 1145 | struct usb_serial *serial; |
| 1188 | struct moschip_port *mos7840_port; | 1146 | struct moschip_port *mos7840_port; |
| @@ -1223,10 +1181,6 @@ static void mos7840_close(struct tty_struct *tty, | |||
| 1223 | } | 1181 | } |
| 1224 | } | 1182 | } |
| 1225 | 1183 | ||
| 1226 | if (serial->dev) | ||
| 1227 | /* flush and block until tx is empty */ | ||
| 1228 | mos7840_block_until_tx_empty(tty, mos7840_port); | ||
| 1229 | |||
| 1230 | /* While closing port, shutdown all bulk read, write * | 1184 | /* While closing port, shutdown all bulk read, write * |
| 1231 | * and interrupt read if they exists */ | 1185 | * and interrupt read if they exists */ |
| 1232 | if (serial->dev) { | 1186 | if (serial->dev) { |
diff --git a/drivers/usb/serial/navman.c b/drivers/usb/serial/navman.c index bcdcbb822705..f5f3751a888c 100644 --- a/drivers/usb/serial/navman.c +++ b/drivers/usb/serial/navman.c | |||
| @@ -98,8 +98,7 @@ static int navman_open(struct tty_struct *tty, | |||
| 98 | return result; | 98 | return result; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | static void navman_close(struct tty_struct *tty, | 101 | static void navman_close(struct usb_serial_port *port) |
| 102 | struct usb_serial_port *port, struct file *filp) | ||
| 103 | { | 102 | { |
| 104 | dbg("%s - port %d", __func__, port->number); | 103 | dbg("%s - port %d", __func__, port->number); |
| 105 | 104 | ||
diff --git a/drivers/usb/serial/omninet.c b/drivers/usb/serial/omninet.c index df6539712726..1104617334f5 100644 --- a/drivers/usb/serial/omninet.c +++ b/drivers/usb/serial/omninet.c | |||
| @@ -66,8 +66,7 @@ static int debug; | |||
| 66 | /* function prototypes */ | 66 | /* function prototypes */ |
| 67 | static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port, | 67 | static int omninet_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 68 | struct file *filp); | 68 | struct file *filp); |
| 69 | static void omninet_close(struct tty_struct *tty, struct usb_serial_port *port, | 69 | static void omninet_close(struct usb_serial_port *port); |
| 70 | struct file *filp); | ||
| 71 | static void omninet_read_bulk_callback(struct urb *urb); | 70 | static void omninet_read_bulk_callback(struct urb *urb); |
| 72 | static void omninet_write_bulk_callback(struct urb *urb); | 71 | static void omninet_write_bulk_callback(struct urb *urb); |
| 73 | static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, | 72 | static int omninet_write(struct tty_struct *tty, struct usb_serial_port *port, |
| @@ -189,8 +188,7 @@ static int omninet_open(struct tty_struct *tty, | |||
| 189 | return result; | 188 | return result; |
| 190 | } | 189 | } |
| 191 | 190 | ||
| 192 | static void omninet_close(struct tty_struct *tty, | 191 | static void omninet_close(struct usb_serial_port *port) |
| 193 | struct usb_serial_port *port, struct file *filp) | ||
| 194 | { | 192 | { |
| 195 | dbg("%s - port %d", __func__, port->number); | 193 | dbg("%s - port %d", __func__, port->number); |
| 196 | usb_kill_urb(port->read_urb); | 194 | usb_kill_urb(port->read_urb); |
diff --git a/drivers/usb/serial/opticon.c b/drivers/usb/serial/opticon.c index b500ad10b758..c20480aa9755 100644 --- a/drivers/usb/serial/opticon.c +++ b/drivers/usb/serial/opticon.c | |||
| @@ -173,8 +173,7 @@ static int opticon_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 173 | return result; | 173 | return result; |
| 174 | } | 174 | } |
| 175 | 175 | ||
| 176 | static void opticon_close(struct tty_struct *tty, struct usb_serial_port *port, | 176 | static void opticon_close(struct usb_serial_port *port) |
| 177 | struct file *filp) | ||
| 178 | { | 177 | { |
| 179 | struct opticon_private *priv = usb_get_serial_data(port->serial); | 178 | struct opticon_private *priv = usb_get_serial_data(port->serial); |
| 180 | 179 | ||
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c index 7817b82889ca..a16d69fadba1 100644 --- a/drivers/usb/serial/option.c +++ b/drivers/usb/serial/option.c | |||
| @@ -45,8 +45,9 @@ | |||
| 45 | /* Function prototypes */ | 45 | /* Function prototypes */ |
| 46 | static int option_open(struct tty_struct *tty, struct usb_serial_port *port, | 46 | static int option_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 47 | struct file *filp); | 47 | struct file *filp); |
| 48 | static void option_close(struct tty_struct *tty, struct usb_serial_port *port, | 48 | static void option_close(struct usb_serial_port *port); |
| 49 | struct file *filp); | 49 | static void option_dtr_rts(struct usb_serial_port *port, int on); |
| 50 | |||
| 50 | static int option_startup(struct usb_serial *serial); | 51 | static int option_startup(struct usb_serial *serial); |
| 51 | static void option_shutdown(struct usb_serial *serial); | 52 | static void option_shutdown(struct usb_serial *serial); |
| 52 | static int option_write_room(struct tty_struct *tty); | 53 | static int option_write_room(struct tty_struct *tty); |
| @@ -61,7 +62,7 @@ static void option_set_termios(struct tty_struct *tty, | |||
| 61 | static int option_tiocmget(struct tty_struct *tty, struct file *file); | 62 | static int option_tiocmget(struct tty_struct *tty, struct file *file); |
| 62 | static int option_tiocmset(struct tty_struct *tty, struct file *file, | 63 | static int option_tiocmset(struct tty_struct *tty, struct file *file, |
| 63 | unsigned int set, unsigned int clear); | 64 | unsigned int set, unsigned int clear); |
| 64 | static int option_send_setup(struct tty_struct *tty, struct usb_serial_port *port); | 65 | static int option_send_setup(struct usb_serial_port *port); |
| 65 | static int option_suspend(struct usb_serial *serial, pm_message_t message); | 66 | static int option_suspend(struct usb_serial *serial, pm_message_t message); |
| 66 | static int option_resume(struct usb_serial *serial); | 67 | static int option_resume(struct usb_serial *serial); |
| 67 | 68 | ||
| @@ -551,6 +552,7 @@ static struct usb_serial_driver option_1port_device = { | |||
| 551 | .num_ports = 1, | 552 | .num_ports = 1, |
| 552 | .open = option_open, | 553 | .open = option_open, |
| 553 | .close = option_close, | 554 | .close = option_close, |
| 555 | .dtr_rts = option_dtr_rts, | ||
| 554 | .write = option_write, | 556 | .write = option_write, |
| 555 | .write_room = option_write_room, | 557 | .write_room = option_write_room, |
| 556 | .chars_in_buffer = option_chars_in_buffer, | 558 | .chars_in_buffer = option_chars_in_buffer, |
| @@ -630,7 +632,7 @@ static void option_set_termios(struct tty_struct *tty, | |||
| 630 | dbg("%s", __func__); | 632 | dbg("%s", __func__); |
| 631 | /* Doesn't support option setting */ | 633 | /* Doesn't support option setting */ |
| 632 | tty_termios_copy_hw(tty->termios, old_termios); | 634 | tty_termios_copy_hw(tty->termios, old_termios); |
| 633 | option_send_setup(tty, port); | 635 | option_send_setup(port); |
| 634 | } | 636 | } |
| 635 | 637 | ||
| 636 | static int option_tiocmget(struct tty_struct *tty, struct file *file) | 638 | static int option_tiocmget(struct tty_struct *tty, struct file *file) |
| @@ -669,7 +671,7 @@ static int option_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 669 | portdata->rts_state = 0; | 671 | portdata->rts_state = 0; |
| 670 | if (clear & TIOCM_DTR) | 672 | if (clear & TIOCM_DTR) |
| 671 | portdata->dtr_state = 0; | 673 | portdata->dtr_state = 0; |
| 672 | return option_send_setup(tty, port); | 674 | return option_send_setup(port); |
| 673 | } | 675 | } |
| 674 | 676 | ||
| 675 | /* Write */ | 677 | /* Write */ |
| @@ -897,10 +899,6 @@ static int option_open(struct tty_struct *tty, | |||
| 897 | 899 | ||
| 898 | dbg("%s", __func__); | 900 | dbg("%s", __func__); |
| 899 | 901 | ||
| 900 | /* Set some sane defaults */ | ||
| 901 | portdata->rts_state = 1; | ||
| 902 | portdata->dtr_state = 1; | ||
| 903 | |||
| 904 | /* Reset low level data toggle and start reading from endpoints */ | 902 | /* Reset low level data toggle and start reading from endpoints */ |
| 905 | for (i = 0; i < N_IN_URB; i++) { | 903 | for (i = 0; i < N_IN_URB; i++) { |
| 906 | urb = portdata->in_urbs[i]; | 904 | urb = portdata->in_urbs[i]; |
| @@ -936,37 +934,43 @@ static int option_open(struct tty_struct *tty, | |||
| 936 | usb_pipeout(urb->pipe), 0); */ | 934 | usb_pipeout(urb->pipe), 0); */ |
| 937 | } | 935 | } |
| 938 | 936 | ||
| 939 | option_send_setup(tty, port); | 937 | option_send_setup(port); |
| 940 | 938 | ||
| 941 | return 0; | 939 | return 0; |
| 942 | } | 940 | } |
| 943 | 941 | ||
| 944 | static void option_close(struct tty_struct *tty, | 942 | static void option_dtr_rts(struct usb_serial_port *port, int on) |
| 945 | struct usb_serial_port *port, struct file *filp) | ||
| 946 | { | 943 | { |
| 947 | int i; | ||
| 948 | struct usb_serial *serial = port->serial; | 944 | struct usb_serial *serial = port->serial; |
| 949 | struct option_port_private *portdata; | 945 | struct option_port_private *portdata; |
| 950 | 946 | ||
| 951 | dbg("%s", __func__); | 947 | dbg("%s", __func__); |
| 952 | portdata = usb_get_serial_port_data(port); | 948 | portdata = usb_get_serial_port_data(port); |
| 949 | mutex_lock(&serial->disc_mutex); | ||
| 950 | portdata->rts_state = on; | ||
| 951 | portdata->dtr_state = on; | ||
| 952 | if (serial->dev) | ||
| 953 | option_send_setup(port); | ||
| 954 | mutex_unlock(&serial->disc_mutex); | ||
| 955 | } | ||
| 953 | 956 | ||
| 954 | portdata->rts_state = 0; | ||
| 955 | portdata->dtr_state = 0; | ||
| 956 | 957 | ||
| 957 | if (serial->dev) { | 958 | static void option_close(struct usb_serial_port *port) |
| 958 | mutex_lock(&serial->disc_mutex); | 959 | { |
| 959 | if (!serial->disconnected) | 960 | int i; |
| 960 | option_send_setup(tty, port); | 961 | struct usb_serial *serial = port->serial; |
| 961 | mutex_unlock(&serial->disc_mutex); | 962 | struct option_port_private *portdata; |
| 963 | |||
| 964 | dbg("%s", __func__); | ||
| 965 | portdata = usb_get_serial_port_data(port); | ||
| 962 | 966 | ||
| 967 | if (serial->dev) { | ||
| 963 | /* Stop reading/writing urbs */ | 968 | /* Stop reading/writing urbs */ |
| 964 | for (i = 0; i < N_IN_URB; i++) | 969 | for (i = 0; i < N_IN_URB; i++) |
| 965 | usb_kill_urb(portdata->in_urbs[i]); | 970 | usb_kill_urb(portdata->in_urbs[i]); |
| 966 | for (i = 0; i < N_OUT_URB; i++) | 971 | for (i = 0; i < N_OUT_URB; i++) |
| 967 | usb_kill_urb(portdata->out_urbs[i]); | 972 | usb_kill_urb(portdata->out_urbs[i]); |
| 968 | } | 973 | } |
| 969 | tty_port_tty_set(&port->port, NULL); | ||
| 970 | } | 974 | } |
| 971 | 975 | ||
| 972 | /* Helper functions used by option_setup_urbs */ | 976 | /* Helper functions used by option_setup_urbs */ |
| @@ -1032,28 +1036,24 @@ static void option_setup_urbs(struct usb_serial *serial) | |||
| 1032 | * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN | 1036 | * This is exactly the same as SET_CONTROL_LINE_STATE from the PSTN |
| 1033 | * CDC. | 1037 | * CDC. |
| 1034 | */ | 1038 | */ |
| 1035 | static int option_send_setup(struct tty_struct *tty, | 1039 | static int option_send_setup(struct usb_serial_port *port) |
| 1036 | struct usb_serial_port *port) | ||
| 1037 | { | 1040 | { |
| 1038 | struct usb_serial *serial = port->serial; | 1041 | struct usb_serial *serial = port->serial; |
| 1039 | struct option_port_private *portdata; | 1042 | struct option_port_private *portdata; |
| 1040 | int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; | 1043 | int ifNum = serial->interface->cur_altsetting->desc.bInterfaceNumber; |
| 1044 | int val = 0; | ||
| 1041 | dbg("%s", __func__); | 1045 | dbg("%s", __func__); |
| 1042 | 1046 | ||
| 1043 | portdata = usb_get_serial_port_data(port); | 1047 | portdata = usb_get_serial_port_data(port); |
| 1044 | 1048 | ||
| 1045 | if (tty) { | 1049 | if (portdata->dtr_state) |
| 1046 | int val = 0; | 1050 | val |= 0x01; |
| 1047 | if (portdata->dtr_state) | 1051 | if (portdata->rts_state) |
| 1048 | val |= 0x01; | 1052 | val |= 0x02; |
| 1049 | if (portdata->rts_state) | ||
| 1050 | val |= 0x02; | ||
| 1051 | 1053 | ||
| 1052 | return usb_control_msg(serial->dev, | 1054 | return usb_control_msg(serial->dev, |
| 1053 | usb_rcvctrlpipe(serial->dev, 0), | 1055 | usb_rcvctrlpipe(serial->dev, 0), |
| 1054 | 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); | 1056 | 0x22, 0x21, val, ifNum, NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 1055 | } | ||
| 1056 | return 0; | ||
| 1057 | } | 1057 | } |
| 1058 | 1058 | ||
| 1059 | static int option_startup(struct usb_serial *serial) | 1059 | static int option_startup(struct usb_serial *serial) |
diff --git a/drivers/usb/serial/oti6858.c b/drivers/usb/serial/oti6858.c index ba551f00f16f..7de54781fe61 100644 --- a/drivers/usb/serial/oti6858.c +++ b/drivers/usb/serial/oti6858.c | |||
| @@ -143,8 +143,7 @@ struct oti6858_control_pkt { | |||
| 143 | /* function prototypes */ | 143 | /* function prototypes */ |
| 144 | static int oti6858_open(struct tty_struct *tty, | 144 | static int oti6858_open(struct tty_struct *tty, |
| 145 | struct usb_serial_port *port, struct file *filp); | 145 | struct usb_serial_port *port, struct file *filp); |
| 146 | static void oti6858_close(struct tty_struct *tty, | 146 | static void oti6858_close(struct usb_serial_port *port); |
| 147 | struct usb_serial_port *port, struct file *filp); | ||
| 148 | static void oti6858_set_termios(struct tty_struct *tty, | 147 | static void oti6858_set_termios(struct tty_struct *tty, |
| 149 | struct usb_serial_port *port, struct ktermios *old); | 148 | struct usb_serial_port *port, struct ktermios *old); |
| 150 | static int oti6858_ioctl(struct tty_struct *tty, struct file *file, | 149 | static int oti6858_ioctl(struct tty_struct *tty, struct file *file, |
| @@ -622,67 +621,30 @@ static int oti6858_open(struct tty_struct *tty, | |||
| 622 | if (result != 0) { | 621 | if (result != 0) { |
| 623 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" | 622 | dev_err(&port->dev, "%s(): usb_submit_urb() failed" |
| 624 | " with error %d\n", __func__, result); | 623 | " with error %d\n", __func__, result); |
| 625 | oti6858_close(tty, port, NULL); | 624 | oti6858_close(port); |
| 626 | return -EPROTO; | 625 | return -EPROTO; |
| 627 | } | 626 | } |
| 628 | 627 | ||
| 629 | /* setup termios */ | 628 | /* setup termios */ |
| 630 | if (tty) | 629 | if (tty) |
| 631 | oti6858_set_termios(tty, port, &tmp_termios); | 630 | oti6858_set_termios(tty, port, &tmp_termios); |
| 632 | 631 | port->port.drain_delay = 256; /* FIXME: check the FIFO length */ | |
| 633 | return 0; | 632 | return 0; |
| 634 | } | 633 | } |
| 635 | 634 | ||
| 636 | static void oti6858_close(struct tty_struct *tty, | 635 | static void oti6858_close(struct usb_serial_port *port) |
| 637 | struct usb_serial_port *port, struct file *filp) | ||
| 638 | { | 636 | { |
| 639 | struct oti6858_private *priv = usb_get_serial_port_data(port); | 637 | struct oti6858_private *priv = usb_get_serial_port_data(port); |
| 640 | unsigned long flags; | 638 | unsigned long flags; |
| 641 | long timeout; | ||
| 642 | wait_queue_t wait; | ||
| 643 | 639 | ||
| 644 | dbg("%s(port = %d)", __func__, port->number); | 640 | dbg("%s(port = %d)", __func__, port->number); |
| 645 | 641 | ||
| 646 | /* wait for data to drain from the buffer */ | ||
| 647 | spin_lock_irqsave(&priv->lock, flags); | 642 | spin_lock_irqsave(&priv->lock, flags); |
| 648 | timeout = 30 * HZ; /* PL2303_CLOSING_WAIT */ | ||
| 649 | init_waitqueue_entry(&wait, current); | ||
| 650 | add_wait_queue(&tty->write_wait, &wait); | ||
| 651 | dbg("%s(): entering wait loop", __func__); | ||
| 652 | for (;;) { | ||
| 653 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 654 | if (oti6858_buf_data_avail(priv->buf) == 0 | ||
| 655 | || timeout == 0 || signal_pending(current) | ||
| 656 | || port->serial->disconnected) | ||
| 657 | break; | ||
| 658 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 659 | timeout = schedule_timeout(timeout); | ||
| 660 | spin_lock_irqsave(&priv->lock, flags); | ||
| 661 | } | ||
| 662 | set_current_state(TASK_RUNNING); | ||
| 663 | remove_wait_queue(&tty->write_wait, &wait); | ||
| 664 | dbg("%s(): after wait loop", __func__); | ||
| 665 | |||
| 666 | /* clear out any remaining data in the buffer */ | 643 | /* clear out any remaining data in the buffer */ |
| 667 | oti6858_buf_clear(priv->buf); | 644 | oti6858_buf_clear(priv->buf); |
| 668 | spin_unlock_irqrestore(&priv->lock, flags); | 645 | spin_unlock_irqrestore(&priv->lock, flags); |
| 669 | 646 | ||
| 670 | /* wait for characters to drain from the device */ | 647 | dbg("%s(): after buf_clear()", __func__); |
| 671 | /* (this is long enough for the entire 256 byte */ | ||
| 672 | /* pl2303 hardware buffer to drain with no flow */ | ||
| 673 | /* control for data rates of 1200 bps or more, */ | ||
| 674 | /* for lower rates we should really know how much */ | ||
| 675 | /* data is in the buffer to compute a delay */ | ||
| 676 | /* that is not unnecessarily long) */ | ||
| 677 | /* FIXME | ||
| 678 | bps = tty_get_baud_rate(tty); | ||
| 679 | if (bps > 1200) | ||
| 680 | timeout = max((HZ*2560)/bps,HZ/10); | ||
| 681 | else | ||
| 682 | */ | ||
| 683 | timeout = 2*HZ; | ||
| 684 | schedule_timeout_interruptible(timeout); | ||
| 685 | dbg("%s(): after schedule_timeout_interruptible()", __func__); | ||
| 686 | 648 | ||
| 687 | /* cancel scheduled setup */ | 649 | /* cancel scheduled setup */ |
| 688 | cancel_delayed_work(&priv->delayed_setup_work); | 650 | cancel_delayed_work(&priv->delayed_setup_work); |
| @@ -694,15 +656,6 @@ static void oti6858_close(struct tty_struct *tty, | |||
| 694 | usb_kill_urb(port->write_urb); | 656 | usb_kill_urb(port->write_urb); |
| 695 | usb_kill_urb(port->read_urb); | 657 | usb_kill_urb(port->read_urb); |
| 696 | usb_kill_urb(port->interrupt_in_urb); | 658 | usb_kill_urb(port->interrupt_in_urb); |
| 697 | |||
| 698 | /* | ||
| 699 | if (tty && (tty->termios->c_cflag) & HUPCL) { | ||
| 700 | // drop DTR and RTS | ||
| 701 | spin_lock_irqsave(&priv->lock, flags); | ||
| 702 | priv->pending_setup.control &= ~CONTROL_MASK; | ||
| 703 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 704 | } | ||
| 705 | */ | ||
| 706 | } | 659 | } |
| 707 | 660 | ||
| 708 | static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, | 661 | static int oti6858_tiocmset(struct tty_struct *tty, struct file *file, |
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c index 751a533a4347..e02dc3d643c7 100644 --- a/drivers/usb/serial/pl2303.c +++ b/drivers/usb/serial/pl2303.c | |||
| @@ -652,69 +652,41 @@ static void pl2303_set_termios(struct tty_struct *tty, | |||
| 652 | kfree(buf); | 652 | kfree(buf); |
| 653 | } | 653 | } |
| 654 | 654 | ||
| 655 | static void pl2303_close(struct tty_struct *tty, | 655 | static void pl2303_dtr_rts(struct usb_serial_port *port, int on) |
| 656 | struct usb_serial_port *port, struct file *filp) | 656 | { |
| 657 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
| 658 | unsigned long flags; | ||
| 659 | u8 control; | ||
| 660 | |||
| 661 | spin_lock_irqsave(&priv->lock, flags); | ||
| 662 | /* Change DTR and RTS */ | ||
| 663 | if (on) | ||
| 664 | priv->line_control |= (CONTROL_DTR | CONTROL_RTS); | ||
| 665 | else | ||
| 666 | priv->line_control &= ~(CONTROL_DTR | CONTROL_RTS); | ||
| 667 | control = priv->line_control; | ||
| 668 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 669 | set_control_lines(port->serial->dev, control); | ||
| 670 | } | ||
| 671 | |||
| 672 | static void pl2303_close(struct usb_serial_port *port) | ||
| 657 | { | 673 | { |
| 658 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 674 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
| 659 | unsigned long flags; | 675 | unsigned long flags; |
| 660 | unsigned int c_cflag; | ||
| 661 | int bps; | ||
| 662 | long timeout; | ||
| 663 | wait_queue_t wait; | ||
| 664 | 676 | ||
| 665 | dbg("%s - port %d", __func__, port->number); | 677 | dbg("%s - port %d", __func__, port->number); |
| 666 | 678 | ||
| 667 | /* wait for data to drain from the buffer */ | ||
| 668 | spin_lock_irqsave(&priv->lock, flags); | 679 | spin_lock_irqsave(&priv->lock, flags); |
| 669 | timeout = PL2303_CLOSING_WAIT; | ||
| 670 | init_waitqueue_entry(&wait, current); | ||
| 671 | add_wait_queue(&tty->write_wait, &wait); | ||
| 672 | for (;;) { | ||
| 673 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 674 | if (pl2303_buf_data_avail(priv->buf) == 0 || | ||
| 675 | timeout == 0 || signal_pending(current) || | ||
| 676 | port->serial->disconnected) | ||
| 677 | break; | ||
| 678 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 679 | timeout = schedule_timeout(timeout); | ||
| 680 | spin_lock_irqsave(&priv->lock, flags); | ||
| 681 | } | ||
| 682 | set_current_state(TASK_RUNNING); | ||
| 683 | remove_wait_queue(&tty->write_wait, &wait); | ||
| 684 | /* clear out any remaining data in the buffer */ | 680 | /* clear out any remaining data in the buffer */ |
| 685 | pl2303_buf_clear(priv->buf); | 681 | pl2303_buf_clear(priv->buf); |
| 686 | spin_unlock_irqrestore(&priv->lock, flags); | 682 | spin_unlock_irqrestore(&priv->lock, flags); |
| 687 | 683 | ||
| 688 | /* wait for characters to drain from the device */ | ||
| 689 | /* (this is long enough for the entire 256 byte */ | ||
| 690 | /* pl2303 hardware buffer to drain with no flow */ | ||
| 691 | /* control for data rates of 1200 bps or more, */ | ||
| 692 | /* for lower rates we should really know how much */ | ||
| 693 | /* data is in the buffer to compute a delay */ | ||
| 694 | /* that is not unnecessarily long) */ | ||
| 695 | bps = tty_get_baud_rate(tty); | ||
| 696 | if (bps > 1200) | ||
| 697 | timeout = max((HZ*2560)/bps, HZ/10); | ||
| 698 | else | ||
| 699 | timeout = 2*HZ; | ||
| 700 | schedule_timeout_interruptible(timeout); | ||
| 701 | |||
| 702 | /* shutdown our urbs */ | 684 | /* shutdown our urbs */ |
| 703 | dbg("%s - shutting down urbs", __func__); | 685 | dbg("%s - shutting down urbs", __func__); |
| 704 | usb_kill_urb(port->write_urb); | 686 | usb_kill_urb(port->write_urb); |
| 705 | usb_kill_urb(port->read_urb); | 687 | usb_kill_urb(port->read_urb); |
| 706 | usb_kill_urb(port->interrupt_in_urb); | 688 | usb_kill_urb(port->interrupt_in_urb); |
| 707 | 689 | ||
| 708 | if (tty) { | ||
| 709 | c_cflag = tty->termios->c_cflag; | ||
| 710 | if (c_cflag & HUPCL) { | ||
| 711 | /* drop DTR and RTS */ | ||
| 712 | spin_lock_irqsave(&priv->lock, flags); | ||
| 713 | priv->line_control = 0; | ||
| 714 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 715 | set_control_lines(port->serial->dev, 0); | ||
| 716 | } | ||
| 717 | } | ||
| 718 | } | 690 | } |
| 719 | 691 | ||
| 720 | static int pl2303_open(struct tty_struct *tty, | 692 | static int pl2303_open(struct tty_struct *tty, |
| @@ -748,7 +720,7 @@ static int pl2303_open(struct tty_struct *tty, | |||
| 748 | if (result) { | 720 | if (result) { |
| 749 | dev_err(&port->dev, "%s - failed submitting read urb," | 721 | dev_err(&port->dev, "%s - failed submitting read urb," |
| 750 | " error %d\n", __func__, result); | 722 | " error %d\n", __func__, result); |
| 751 | pl2303_close(tty, port, NULL); | 723 | pl2303_close(port); |
| 752 | return -EPROTO; | 724 | return -EPROTO; |
| 753 | } | 725 | } |
| 754 | 726 | ||
| @@ -758,9 +730,10 @@ static int pl2303_open(struct tty_struct *tty, | |||
| 758 | if (result) { | 730 | if (result) { |
| 759 | dev_err(&port->dev, "%s - failed submitting interrupt urb," | 731 | dev_err(&port->dev, "%s - failed submitting interrupt urb," |
| 760 | " error %d\n", __func__, result); | 732 | " error %d\n", __func__, result); |
| 761 | pl2303_close(tty, port, NULL); | 733 | pl2303_close(port); |
| 762 | return -EPROTO; | 734 | return -EPROTO; |
| 763 | } | 735 | } |
| 736 | port->port.drain_delay = 256; | ||
| 764 | return 0; | 737 | return 0; |
| 765 | } | 738 | } |
| 766 | 739 | ||
| @@ -821,6 +794,14 @@ static int pl2303_tiocmget(struct tty_struct *tty, struct file *file) | |||
| 821 | return result; | 794 | return result; |
| 822 | } | 795 | } |
| 823 | 796 | ||
| 797 | static int pl2303_carrier_raised(struct usb_serial_port *port) | ||
| 798 | { | ||
| 799 | struct pl2303_private *priv = usb_get_serial_port_data(port); | ||
| 800 | if (priv->line_status & UART_DCD) | ||
| 801 | return 1; | ||
| 802 | return 0; | ||
| 803 | } | ||
| 804 | |||
| 824 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) | 805 | static int wait_modem_info(struct usb_serial_port *port, unsigned int arg) |
| 825 | { | 806 | { |
| 826 | struct pl2303_private *priv = usb_get_serial_port_data(port); | 807 | struct pl2303_private *priv = usb_get_serial_port_data(port); |
| @@ -1125,6 +1106,8 @@ static struct usb_serial_driver pl2303_device = { | |||
| 1125 | .num_ports = 1, | 1106 | .num_ports = 1, |
| 1126 | .open = pl2303_open, | 1107 | .open = pl2303_open, |
| 1127 | .close = pl2303_close, | 1108 | .close = pl2303_close, |
| 1109 | .dtr_rts = pl2303_dtr_rts, | ||
| 1110 | .carrier_raised = pl2303_carrier_raised, | ||
| 1128 | .write = pl2303_write, | 1111 | .write = pl2303_write, |
| 1129 | .ioctl = pl2303_ioctl, | 1112 | .ioctl = pl2303_ioctl, |
| 1130 | .break_ctl = pl2303_break_ctl, | 1113 | .break_ctl = pl2303_break_ctl, |
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c index 913225c61610..17ac34f4d668 100644 --- a/drivers/usb/serial/sierra.c +++ b/drivers/usb/serial/sierra.c | |||
| @@ -26,12 +26,10 @@ | |||
| 26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
| 27 | #include <linux/usb.h> | 27 | #include <linux/usb.h> |
| 28 | #include <linux/usb/serial.h> | 28 | #include <linux/usb/serial.h> |
| 29 | #include <linux/usb/ch9.h> | ||
| 30 | 29 | ||
| 31 | #define SWIMS_USB_REQUEST_SetPower 0x00 | 30 | #define SWIMS_USB_REQUEST_SetPower 0x00 |
| 32 | #define SWIMS_USB_REQUEST_SetNmea 0x07 | 31 | #define SWIMS_USB_REQUEST_SetNmea 0x07 |
| 33 | 32 | ||
| 34 | /* per port private data */ | ||
| 35 | #define N_IN_URB 4 | 33 | #define N_IN_URB 4 |
| 36 | #define N_OUT_URB 4 | 34 | #define N_OUT_URB 4 |
| 37 | #define IN_BUFLEN 4096 | 35 | #define IN_BUFLEN 4096 |
| @@ -39,6 +37,12 @@ | |||
| 39 | static int debug; | 37 | static int debug; |
| 40 | static int nmea; | 38 | static int nmea; |
| 41 | 39 | ||
| 40 | /* Used in interface blacklisting */ | ||
| 41 | struct sierra_iface_info { | ||
| 42 | const u32 infolen; /* number of interface numbers on blacklist */ | ||
| 43 | const u8 *ifaceinfo; /* pointer to the array holding the numbers */ | ||
| 44 | }; | ||
| 45 | |||
| 42 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) | 46 | static int sierra_set_power_state(struct usb_device *udev, __u16 swiState) |
| 43 | { | 47 | { |
| 44 | int result; | 48 | int result; |
| @@ -85,6 +89,23 @@ static int sierra_calc_num_ports(struct usb_serial *serial) | |||
| 85 | return result; | 89 | return result; |
| 86 | } | 90 | } |
| 87 | 91 | ||
| 92 | static int is_blacklisted(const u8 ifnum, | ||
| 93 | const struct sierra_iface_info *blacklist) | ||
| 94 | { | ||
| 95 | const u8 *info; | ||
| 96 | int i; | ||
| 97 | |||
| 98 | if (blacklist) { | ||
| 99 | info = blacklist->ifaceinfo; | ||
| 100 | |||
| 101 | for (i = 0; i < blacklist->infolen; i++) { | ||
| 102 | if (info[i] == ifnum) | ||
| 103 | return 1; | ||
| 104 | } | ||
| 105 | } | ||
| 106 | return 0; | ||
| 107 | } | ||
| 108 | |||
| 88 | static int sierra_calc_interface(struct usb_serial *serial) | 109 | static int sierra_calc_interface(struct usb_serial *serial) |
| 89 | { | 110 | { |
| 90 | int interface; | 111 | int interface; |
| @@ -153,9 +174,25 @@ static int sierra_probe(struct usb_serial *serial, | |||
| 153 | */ | 174 | */ |
| 154 | usb_set_serial_data(serial, (void *)num_ports); | 175 | usb_set_serial_data(serial, (void *)num_ports); |
| 155 | 176 | ||
| 177 | /* ifnum could have changed - by calling usb_set_interface */ | ||
| 178 | ifnum = sierra_calc_interface(serial); | ||
| 179 | |||
| 180 | if (is_blacklisted(ifnum, | ||
| 181 | (struct sierra_iface_info *)id->driver_info)) { | ||
| 182 | dev_dbg(&serial->dev->dev, | ||
| 183 | "Ignoring blacklisted interface #%d\n", ifnum); | ||
| 184 | return -ENODEV; | ||
| 185 | } | ||
| 186 | |||
| 156 | return result; | 187 | return result; |
| 157 | } | 188 | } |
| 158 | 189 | ||
| 190 | static const u8 direct_ip_non_serial_ifaces[] = { 7, 8, 9, 10, 11 }; | ||
| 191 | static const struct sierra_iface_info direct_ip_interface_blacklist = { | ||
| 192 | .infolen = ARRAY_SIZE(direct_ip_non_serial_ifaces), | ||
| 193 | .ifaceinfo = direct_ip_non_serial_ifaces, | ||
| 194 | }; | ||
| 195 | |||
| 159 | static struct usb_device_id id_table [] = { | 196 | static struct usb_device_id id_table [] = { |
| 160 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ | 197 | { USB_DEVICE(0x1199, 0x0017) }, /* Sierra Wireless EM5625 */ |
| 161 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ | 198 | { USB_DEVICE(0x1199, 0x0018) }, /* Sierra Wireless MC5720 */ |
| @@ -188,9 +225,11 @@ static struct usb_device_id id_table [] = { | |||
| 188 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ | 225 | { USB_DEVICE(0x1199, 0x6833) }, /* Sierra Wireless MC8781 */ |
| 189 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ | 226 | { USB_DEVICE(0x1199, 0x683A) }, /* Sierra Wireless MC8785 */ |
| 190 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ | 227 | { USB_DEVICE(0x1199, 0x683B) }, /* Sierra Wireless MC8785 Composite */ |
| 191 | { USB_DEVICE(0x1199, 0x683C) }, /* Sierra Wireless MC8790 */ | 228 | /* Sierra Wireless MC8790, MC8791, MC8792 Composite */ |
| 192 | { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8790 */ | 229 | { USB_DEVICE(0x1199, 0x683C) }, |
| 193 | { USB_DEVICE(0x1199, 0x683E) }, /* Sierra Wireless MC8790 */ | 230 | { USB_DEVICE(0x1199, 0x683D) }, /* Sierra Wireless MC8791 Composite */ |
| 231 | /* Sierra Wireless MC8790, MC8791, MC8792 */ | ||
| 232 | { USB_DEVICE(0x1199, 0x683E) }, | ||
| 194 | { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ | 233 | { USB_DEVICE(0x1199, 0x6850) }, /* Sierra Wireless AirCard 880 */ |
| 195 | { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ | 234 | { USB_DEVICE(0x1199, 0x6851) }, /* Sierra Wireless AirCard 881 */ |
| 196 | { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ | 235 | { USB_DEVICE(0x1199, 0x6852) }, /* Sierra Wireless AirCard 880 E */ |
| @@ -211,6 +250,10 @@ static struct usb_device_id id_table [] = { | |||
| 211 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ | 250 | { USB_DEVICE(0x1199, 0x0112) }, /* Sierra Wireless AirCard 580 */ |
| 212 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ | 251 | { USB_DEVICE(0x0F3D, 0x0112) }, /* Airprime/Sierra PC 5220 */ |
| 213 | 252 | ||
| 253 | { USB_DEVICE(0x1199, 0x68A3), /* Sierra Wireless Direct IP modems */ | ||
| 254 | .driver_info = (kernel_ulong_t)&direct_ip_interface_blacklist | ||
| 255 | }, | ||
| 256 | |||
| 214 | { } | 257 | { } |
| 215 | }; | 258 | }; |
| 216 | MODULE_DEVICE_TABLE(usb, id_table); | 259 | MODULE_DEVICE_TABLE(usb, id_table); |
| @@ -229,7 +272,6 @@ struct sierra_port_private { | |||
| 229 | 272 | ||
| 230 | /* Input endpoints and buffers for this port */ | 273 | /* Input endpoints and buffers for this port */ |
| 231 | struct urb *in_urbs[N_IN_URB]; | 274 | struct urb *in_urbs[N_IN_URB]; |
| 232 | char *in_buffer[N_IN_URB]; | ||
| 233 | 275 | ||
| 234 | /* Settings for the port */ | 276 | /* Settings for the port */ |
| 235 | int rts_state; /* Handshaking pins (outputs) */ | 277 | int rts_state; /* Handshaking pins (outputs) */ |
| @@ -240,57 +282,50 @@ struct sierra_port_private { | |||
| 240 | int ri_state; | 282 | int ri_state; |
| 241 | }; | 283 | }; |
| 242 | 284 | ||
| 243 | static int sierra_send_setup(struct tty_struct *tty, | 285 | static int sierra_send_setup(struct usb_serial_port *port) |
| 244 | struct usb_serial_port *port) | ||
| 245 | { | 286 | { |
| 246 | struct usb_serial *serial = port->serial; | 287 | struct usb_serial *serial = port->serial; |
| 247 | struct sierra_port_private *portdata; | 288 | struct sierra_port_private *portdata; |
| 248 | __u16 interface = 0; | 289 | __u16 interface = 0; |
| 290 | int val = 0; | ||
| 249 | 291 | ||
| 250 | dev_dbg(&port->dev, "%s", __func__); | 292 | dev_dbg(&port->dev, "%s", __func__); |
| 251 | 293 | ||
| 252 | portdata = usb_get_serial_port_data(port); | 294 | portdata = usb_get_serial_port_data(port); |
| 253 | 295 | ||
| 254 | if (tty) { | 296 | if (portdata->dtr_state) |
| 255 | int val = 0; | 297 | val |= 0x01; |
| 256 | if (portdata->dtr_state) | 298 | if (portdata->rts_state) |
| 257 | val |= 0x01; | 299 | val |= 0x02; |
| 258 | if (portdata->rts_state) | ||
| 259 | val |= 0x02; | ||
| 260 | |||
| 261 | /* If composite device then properly report interface */ | ||
| 262 | if (serial->num_ports == 1) { | ||
| 263 | interface = sierra_calc_interface(serial); | ||
| 264 | |||
| 265 | /* Control message is sent only to interfaces with | ||
| 266 | * interrupt_in endpoints | ||
| 267 | */ | ||
| 268 | if (port->interrupt_in_urb) { | ||
| 269 | /* send control message */ | ||
| 270 | return usb_control_msg(serial->dev, | ||
| 271 | usb_rcvctrlpipe(serial->dev, 0), | ||
| 272 | 0x22, 0x21, val, interface, | ||
| 273 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 274 | } | ||
| 275 | } | ||
| 276 | |||
| 277 | /* Otherwise the need to do non-composite mapping */ | ||
| 278 | else { | ||
| 279 | if (port->bulk_out_endpointAddress == 2) | ||
| 280 | interface = 0; | ||
| 281 | else if (port->bulk_out_endpointAddress == 4) | ||
| 282 | interface = 1; | ||
| 283 | else if (port->bulk_out_endpointAddress == 5) | ||
| 284 | interface = 2; | ||
| 285 | 300 | ||
| 301 | /* If composite device then properly report interface */ | ||
| 302 | if (serial->num_ports == 1) { | ||
| 303 | interface = sierra_calc_interface(serial); | ||
| 304 | /* Control message is sent only to interfaces with | ||
| 305 | * interrupt_in endpoints | ||
| 306 | */ | ||
| 307 | if (port->interrupt_in_urb) { | ||
| 308 | /* send control message */ | ||
| 286 | return usb_control_msg(serial->dev, | 309 | return usb_control_msg(serial->dev, |
| 287 | usb_rcvctrlpipe(serial->dev, 0), | 310 | usb_rcvctrlpipe(serial->dev, 0), |
| 288 | 0x22, 0x21, val, interface, | 311 | 0x22, 0x21, val, interface, |
| 289 | NULL, 0, USB_CTRL_SET_TIMEOUT); | 312 | NULL, 0, USB_CTRL_SET_TIMEOUT); |
| 290 | |||
| 291 | } | 313 | } |
| 292 | } | 314 | } |
| 293 | 315 | ||
| 316 | /* Otherwise the need to do non-composite mapping */ | ||
| 317 | else { | ||
| 318 | if (port->bulk_out_endpointAddress == 2) | ||
| 319 | interface = 0; | ||
| 320 | else if (port->bulk_out_endpointAddress == 4) | ||
| 321 | interface = 1; | ||
| 322 | else if (port->bulk_out_endpointAddress == 5) | ||
| 323 | interface = 2; | ||
| 324 | return usb_control_msg(serial->dev, | ||
| 325 | usb_rcvctrlpipe(serial->dev, 0), | ||
| 326 | 0x22, 0x21, val, interface, | ||
| 327 | NULL, 0, USB_CTRL_SET_TIMEOUT); | ||
| 328 | } | ||
| 294 | return 0; | 329 | return 0; |
| 295 | } | 330 | } |
| 296 | 331 | ||
| @@ -299,7 +334,7 @@ static void sierra_set_termios(struct tty_struct *tty, | |||
| 299 | { | 334 | { |
| 300 | dev_dbg(&port->dev, "%s", __func__); | 335 | dev_dbg(&port->dev, "%s", __func__); |
| 301 | tty_termios_copy_hw(tty->termios, old_termios); | 336 | tty_termios_copy_hw(tty->termios, old_termios); |
| 302 | sierra_send_setup(tty, port); | 337 | sierra_send_setup(port); |
| 303 | } | 338 | } |
| 304 | 339 | ||
| 305 | static int sierra_tiocmget(struct tty_struct *tty, struct file *file) | 340 | static int sierra_tiocmget(struct tty_struct *tty, struct file *file) |
| @@ -338,7 +373,18 @@ static int sierra_tiocmset(struct tty_struct *tty, struct file *file, | |||
| 338 | portdata->rts_state = 0; | 373 | portdata->rts_state = 0; |
| 339 | if (clear & TIOCM_DTR) | 374 | if (clear & TIOCM_DTR) |
| 340 | portdata->dtr_state = 0; | 375 | portdata->dtr_state = 0; |
| 341 | return sierra_send_setup(tty, port); | 376 | return sierra_send_setup(port); |
| 377 | } | ||
| 378 | |||
| 379 | static void sierra_release_urb(struct urb *urb) | ||
| 380 | { | ||
| 381 | struct usb_serial_port *port; | ||
| 382 | if (urb) { | ||
| 383 | port = urb->context; | ||
| 384 | dev_dbg(&port->dev, "%s: %p\n", __func__, urb); | ||
| 385 | kfree(urb->transfer_buffer); | ||
| 386 | usb_free_urb(urb); | ||
| 387 | } | ||
| 342 | } | 388 | } |
| 343 | 389 | ||
| 344 | static void sierra_outdat_callback(struct urb *urb) | 390 | static void sierra_outdat_callback(struct urb *urb) |
| @@ -465,7 +511,7 @@ static void sierra_indat_callback(struct urb *urb) | |||
| 465 | " received", __func__); | 511 | " received", __func__); |
| 466 | 512 | ||
| 467 | /* Resubmit urb so we continue receiving */ | 513 | /* Resubmit urb so we continue receiving */ |
| 468 | if (port->port.count && status != -ESHUTDOWN) { | 514 | if (port->port.count && status != -ESHUTDOWN && status != -EPERM) { |
| 469 | err = usb_submit_urb(urb, GFP_ATOMIC); | 515 | err = usb_submit_urb(urb, GFP_ATOMIC); |
| 470 | if (err) | 516 | if (err) |
| 471 | dev_err(&port->dev, "resubmit read urb failed." | 517 | dev_err(&port->dev, "resubmit read urb failed." |
| @@ -557,67 +603,99 @@ static int sierra_write_room(struct tty_struct *tty) | |||
| 557 | return 2048; | 603 | return 2048; |
| 558 | } | 604 | } |
| 559 | 605 | ||
| 560 | static int sierra_open(struct tty_struct *tty, | 606 | static void sierra_stop_rx_urbs(struct usb_serial_port *port) |
| 561 | struct usb_serial_port *port, struct file *filp) | ||
| 562 | { | 607 | { |
| 563 | struct sierra_port_private *portdata; | ||
| 564 | struct usb_serial *serial = port->serial; | ||
| 565 | int i; | 608 | int i; |
| 566 | struct urb *urb; | 609 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); |
| 567 | int result; | ||
| 568 | 610 | ||
| 569 | portdata = usb_get_serial_port_data(port); | 611 | for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) |
| 612 | usb_kill_urb(portdata->in_urbs[i]); | ||
| 570 | 613 | ||
| 571 | dev_dbg(&port->dev, "%s", __func__); | 614 | usb_kill_urb(port->interrupt_in_urb); |
| 615 | } | ||
| 572 | 616 | ||
| 573 | /* Set some sane defaults */ | 617 | static int sierra_submit_rx_urbs(struct usb_serial_port *port, gfp_t mem_flags) |
| 574 | portdata->rts_state = 1; | 618 | { |
| 575 | portdata->dtr_state = 1; | 619 | int ok_cnt; |
| 620 | int err = -EINVAL; | ||
| 621 | int i; | ||
| 622 | struct urb *urb; | ||
| 623 | struct sierra_port_private *portdata = usb_get_serial_port_data(port); | ||
| 576 | 624 | ||
| 577 | /* Reset low level data toggle and start reading from endpoints */ | 625 | ok_cnt = 0; |
| 578 | for (i = 0; i < N_IN_URB; i++) { | 626 | for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { |
| 579 | urb = portdata->in_urbs[i]; | 627 | urb = portdata->in_urbs[i]; |
| 580 | if (!urb) | 628 | if (!urb) |
| 581 | continue; | 629 | continue; |
| 582 | if (urb->dev != serial->dev) { | 630 | err = usb_submit_urb(urb, mem_flags); |
| 583 | dev_dbg(&port->dev, "%s: dev %p != %p", | 631 | if (err) { |
| 584 | __func__, urb->dev, serial->dev); | 632 | dev_err(&port->dev, "%s: submit urb failed: %d\n", |
| 585 | continue; | 633 | __func__, err); |
| 634 | } else { | ||
| 635 | ok_cnt++; | ||
| 586 | } | 636 | } |
| 637 | } | ||
| 587 | 638 | ||
| 588 | /* | 639 | if (ok_cnt && port->interrupt_in_urb) { |
| 589 | * make sure endpoint data toggle is synchronized with the | 640 | err = usb_submit_urb(port->interrupt_in_urb, mem_flags); |
| 590 | * device | 641 | if (err) { |
| 591 | */ | 642 | dev_err(&port->dev, "%s: submit intr urb failed: %d\n", |
| 592 | usb_clear_halt(urb->dev, urb->pipe); | 643 | __func__, err); |
| 593 | |||
| 594 | result = usb_submit_urb(urb, GFP_KERNEL); | ||
| 595 | if (result) { | ||
| 596 | dev_err(&port->dev, "submit urb %d failed (%d) %d\n", | ||
| 597 | i, result, urb->transfer_buffer_length); | ||
| 598 | } | 644 | } |
| 599 | } | 645 | } |
| 600 | 646 | ||
| 601 | sierra_send_setup(tty, port); | 647 | if (ok_cnt > 0) /* at least one rx urb submitted */ |
| 648 | return 0; | ||
| 649 | else | ||
| 650 | return err; | ||
| 651 | } | ||
| 652 | |||
| 653 | static struct urb *sierra_setup_urb(struct usb_serial *serial, int endpoint, | ||
| 654 | int dir, void *ctx, int len, | ||
| 655 | gfp_t mem_flags, | ||
| 656 | usb_complete_t callback) | ||
| 657 | { | ||
| 658 | struct urb *urb; | ||
| 659 | u8 *buf; | ||
| 660 | |||
| 661 | if (endpoint == -1) | ||
| 662 | return NULL; | ||
| 602 | 663 | ||
| 603 | /* start up the interrupt endpoint if we have one */ | 664 | urb = usb_alloc_urb(0, mem_flags); |
| 604 | if (port->interrupt_in_urb) { | 665 | if (urb == NULL) { |
| 605 | result = usb_submit_urb(port->interrupt_in_urb, GFP_KERNEL); | 666 | dev_dbg(&serial->dev->dev, "%s: alloc for endpoint %d failed\n", |
| 606 | if (result) | 667 | __func__, endpoint); |
| 607 | dev_err(&port->dev, "submit irq_in urb failed %d\n", | 668 | return NULL; |
| 608 | result); | ||
| 609 | } | 669 | } |
| 610 | return 0; | 670 | |
| 671 | buf = kmalloc(len, mem_flags); | ||
| 672 | if (buf) { | ||
| 673 | /* Fill URB using supplied data */ | ||
| 674 | usb_fill_bulk_urb(urb, serial->dev, | ||
| 675 | usb_sndbulkpipe(serial->dev, endpoint) | dir, | ||
| 676 | buf, len, callback, ctx); | ||
| 677 | |||
| 678 | /* debug */ | ||
| 679 | dev_dbg(&serial->dev->dev, "%s %c u : %p d:%p\n", __func__, | ||
| 680 | dir == USB_DIR_IN ? 'i' : 'o', urb, buf); | ||
| 681 | } else { | ||
| 682 | dev_dbg(&serial->dev->dev, "%s %c u:%p d:%p\n", __func__, | ||
| 683 | dir == USB_DIR_IN ? 'i' : 'o', urb, buf); | ||
| 684 | |||
| 685 | sierra_release_urb(urb); | ||
| 686 | urb = NULL; | ||
| 687 | } | ||
| 688 | |||
| 689 | return urb; | ||
| 611 | } | 690 | } |
| 612 | 691 | ||
| 613 | static void sierra_close(struct tty_struct *tty, | 692 | static void sierra_close(struct usb_serial_port *port) |
| 614 | struct usb_serial_port *port, struct file *filp) | ||
| 615 | { | 693 | { |
| 616 | int i; | 694 | int i; |
| 617 | struct usb_serial *serial = port->serial; | 695 | struct usb_serial *serial = port->serial; |
| 618 | struct sierra_port_private *portdata; | 696 | struct sierra_port_private *portdata; |
| 619 | 697 | ||
| 620 | dev_dbg(&port->dev, "%s", __func__); | 698 | dev_dbg(&port->dev, "%s\n", __func__); |
| 621 | portdata = usb_get_serial_port_data(port); | 699 | portdata = usb_get_serial_port_data(port); |
| 622 | 700 | ||
| 623 | portdata->rts_state = 0; | 701 | portdata->rts_state = 0; |
| @@ -626,25 +704,83 @@ static void sierra_close(struct tty_struct *tty, | |||
| 626 | if (serial->dev) { | 704 | if (serial->dev) { |
| 627 | mutex_lock(&serial->disc_mutex); | 705 | mutex_lock(&serial->disc_mutex); |
| 628 | if (!serial->disconnected) | 706 | if (!serial->disconnected) |
| 629 | sierra_send_setup(tty, port); | 707 | sierra_send_setup(port); |
| 630 | mutex_unlock(&serial->disc_mutex); | 708 | mutex_unlock(&serial->disc_mutex); |
| 631 | 709 | ||
| 632 | /* Stop reading/writing urbs */ | 710 | /* Stop reading urbs */ |
| 633 | for (i = 0; i < N_IN_URB; i++) | 711 | sierra_stop_rx_urbs(port); |
| 634 | usb_kill_urb(portdata->in_urbs[i]); | 712 | /* .. and release them */ |
| 713 | for (i = 0; i < N_IN_URB; i++) { | ||
| 714 | sierra_release_urb(portdata->in_urbs[i]); | ||
| 715 | portdata->in_urbs[i] = NULL; | ||
| 716 | } | ||
| 635 | } | 717 | } |
| 718 | } | ||
| 636 | 719 | ||
| 637 | usb_kill_urb(port->interrupt_in_urb); | 720 | static int sierra_open(struct tty_struct *tty, |
| 638 | tty_port_tty_set(&port->port, NULL); | 721 | struct usb_serial_port *port, struct file *filp) |
| 722 | { | ||
| 723 | struct sierra_port_private *portdata; | ||
| 724 | struct usb_serial *serial = port->serial; | ||
| 725 | int i; | ||
| 726 | int err; | ||
| 727 | int endpoint; | ||
| 728 | struct urb *urb; | ||
| 729 | |||
| 730 | portdata = usb_get_serial_port_data(port); | ||
| 731 | |||
| 732 | dev_dbg(&port->dev, "%s", __func__); | ||
| 733 | |||
| 734 | /* Set some sane defaults */ | ||
| 735 | portdata->rts_state = 1; | ||
| 736 | portdata->dtr_state = 1; | ||
| 737 | |||
| 738 | |||
| 739 | endpoint = port->bulk_in_endpointAddress; | ||
| 740 | for (i = 0; i < ARRAY_SIZE(portdata->in_urbs); i++) { | ||
| 741 | urb = sierra_setup_urb(serial, endpoint, USB_DIR_IN, port, | ||
| 742 | IN_BUFLEN, GFP_KERNEL, | ||
| 743 | sierra_indat_callback); | ||
| 744 | portdata->in_urbs[i] = urb; | ||
| 745 | } | ||
| 746 | /* clear halt condition */ | ||
| 747 | usb_clear_halt(serial->dev, | ||
| 748 | usb_sndbulkpipe(serial->dev, endpoint) | USB_DIR_IN); | ||
| 749 | |||
| 750 | err = sierra_submit_rx_urbs(port, GFP_KERNEL); | ||
| 751 | if (err) { | ||
| 752 | /* get rid of everything as in close */ | ||
| 753 | sierra_close(port); | ||
| 754 | return err; | ||
| 755 | } | ||
| 756 | sierra_send_setup(port); | ||
| 757 | |||
| 758 | return 0; | ||
| 759 | } | ||
| 760 | |||
| 761 | |||
| 762 | static void sierra_dtr_rts(struct usb_serial_port *port, int on) | ||
| 763 | { | ||
| 764 | struct usb_serial *serial = port->serial; | ||
| 765 | struct sierra_port_private *portdata; | ||
| 766 | |||
| 767 | portdata = usb_get_serial_port_data(port); | ||
| 768 | portdata->rts_state = on; | ||
| 769 | portdata->dtr_state = on; | ||
| 770 | |||
| 771 | if (serial->dev) { | ||
| 772 | mutex_lock(&serial->disc_mutex); | ||
| 773 | if (!serial->disconnected) | ||
| 774 | sierra_send_setup(port); | ||
| 775 | mutex_unlock(&serial->disc_mutex); | ||
| 776 | } | ||
| 639 | } | 777 | } |
| 640 | 778 | ||
| 641 | static int sierra_startup(struct usb_serial *serial) | 779 | static int sierra_startup(struct usb_serial *serial) |
| 642 | { | 780 | { |
| 643 | struct usb_serial_port *port; | 781 | struct usb_serial_port *port; |
| 644 | struct sierra_port_private *portdata; | 782 | struct sierra_port_private *portdata; |
| 645 | struct urb *urb; | ||
| 646 | int i; | 783 | int i; |
| 647 | int j; | ||
| 648 | 784 | ||
| 649 | dev_dbg(&serial->dev->dev, "%s", __func__); | 785 | dev_dbg(&serial->dev->dev, "%s", __func__); |
| 650 | 786 | ||
| @@ -666,34 +802,8 @@ static int sierra_startup(struct usb_serial *serial) | |||
| 666 | return -ENOMEM; | 802 | return -ENOMEM; |
| 667 | } | 803 | } |
| 668 | spin_lock_init(&portdata->lock); | 804 | spin_lock_init(&portdata->lock); |
| 669 | for (j = 0; j < N_IN_URB; j++) { | 805 | /* Set the port private data pointer */ |
| 670 | portdata->in_buffer[j] = kmalloc(IN_BUFLEN, GFP_KERNEL); | ||
| 671 | if (!portdata->in_buffer[j]) { | ||
| 672 | for (--j; j >= 0; j--) | ||
| 673 | kfree(portdata->in_buffer[j]); | ||
| 674 | kfree(portdata); | ||
| 675 | return -ENOMEM; | ||
| 676 | } | ||
| 677 | } | ||
| 678 | |||
| 679 | usb_set_serial_port_data(port, portdata); | 806 | usb_set_serial_port_data(port, portdata); |
| 680 | |||
| 681 | /* initialize the in urbs */ | ||
| 682 | for (j = 0; j < N_IN_URB; ++j) { | ||
| 683 | urb = usb_alloc_urb(0, GFP_KERNEL); | ||
| 684 | if (urb == NULL) { | ||
| 685 | dev_dbg(&port->dev, "%s: alloc for in " | ||
| 686 | "port failed.", __func__); | ||
| 687 | continue; | ||
| 688 | } | ||
| 689 | /* Fill URB using supplied data. */ | ||
| 690 | usb_fill_bulk_urb(urb, serial->dev, | ||
| 691 | usb_rcvbulkpipe(serial->dev, | ||
| 692 | port->bulk_in_endpointAddress), | ||
| 693 | portdata->in_buffer[j], IN_BUFLEN, | ||
| 694 | sierra_indat_callback, port); | ||
| 695 | portdata->in_urbs[j] = urb; | ||
| 696 | } | ||
| 697 | } | 807 | } |
| 698 | 808 | ||
| 699 | return 0; | 809 | return 0; |
| @@ -701,7 +811,7 @@ static int sierra_startup(struct usb_serial *serial) | |||
| 701 | 811 | ||
| 702 | static void sierra_shutdown(struct usb_serial *serial) | 812 | static void sierra_shutdown(struct usb_serial *serial) |
| 703 | { | 813 | { |
| 704 | int i, j; | 814 | int i; |
| 705 | struct usb_serial_port *port; | 815 | struct usb_serial_port *port; |
| 706 | struct sierra_port_private *portdata; | 816 | struct sierra_port_private *portdata; |
| 707 | 817 | ||
| @@ -714,12 +824,6 @@ static void sierra_shutdown(struct usb_serial *serial) | |||
| 714 | portdata = usb_get_serial_port_data(port); | 824 | portdata = usb_get_serial_port_data(port); |
| 715 | if (!portdata) | 825 | if (!portdata) |
| 716 | continue; | 826 | continue; |
| 717 | |||
| 718 | for (j = 0; j < N_IN_URB; j++) { | ||
| 719 | usb_kill_urb(portdata->in_urbs[j]); | ||
| 720 | usb_free_urb(portdata->in_urbs[j]); | ||
| 721 | kfree(portdata->in_buffer[j]); | ||
| 722 | } | ||
| 723 | kfree(portdata); | 827 | kfree(portdata); |
| 724 | usb_set_serial_port_data(port, NULL); | 828 | usb_set_serial_port_data(port, NULL); |
| 725 | } | 829 | } |
| @@ -737,6 +841,7 @@ static struct usb_serial_driver sierra_device = { | |||
| 737 | .probe = sierra_probe, | 841 | .probe = sierra_probe, |
| 738 | .open = sierra_open, | 842 | .open = sierra_open, |
| 739 | .close = sierra_close, | 843 | .close = sierra_close, |
| 844 | .dtr_rts = sierra_dtr_rts, | ||
| 740 | .write = sierra_write, | 845 | .write = sierra_write, |
| 741 | .write_room = sierra_write_room, | 846 | .write_room = sierra_write_room, |
| 742 | .set_termios = sierra_set_termios, | 847 | .set_termios = sierra_set_termios, |
diff --git a/drivers/usb/serial/spcp8x5.c b/drivers/usb/serial/spcp8x5.c index 5e7528cc81a8..8f7ed8f13996 100644 --- a/drivers/usb/serial/spcp8x5.c +++ b/drivers/usb/serial/spcp8x5.c | |||
| @@ -446,66 +446,47 @@ static void spcp8x5_set_workMode(struct usb_device *dev, u16 value, | |||
| 446 | "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret); | 446 | "RTSCTS usb_control_msg(enable flowctrl) = %d\n", ret); |
| 447 | } | 447 | } |
| 448 | 448 | ||
| 449 | static int spcp8x5_carrier_raised(struct usb_serial_port *port) | ||
| 450 | { | ||
| 451 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
| 452 | if (priv->line_status & MSR_STATUS_LINE_DCD) | ||
| 453 | return 1; | ||
| 454 | return 0; | ||
| 455 | } | ||
| 456 | |||
| 457 | static void spcp8x5_dtr_rts(struct usb_serial_port *port, int on) | ||
| 458 | { | ||
| 459 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | ||
| 460 | unsigned long flags; | ||
| 461 | u8 control; | ||
| 462 | |||
| 463 | spin_lock_irqsave(&priv->lock, flags); | ||
| 464 | if (on) | ||
| 465 | priv->line_control = MCR_CONTROL_LINE_DTR | ||
| 466 | | MCR_CONTROL_LINE_RTS; | ||
| 467 | else | ||
| 468 | priv->line_control &= ~ (MCR_CONTROL_LINE_DTR | ||
| 469 | | MCR_CONTROL_LINE_RTS); | ||
| 470 | control = priv->line_control; | ||
| 471 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 472 | spcp8x5_set_ctrlLine(port->serial->dev, control , priv->type); | ||
| 473 | } | ||
| 474 | |||
| 449 | /* close the serial port. We should wait for data sending to device 1st and | 475 | /* close the serial port. We should wait for data sending to device 1st and |
| 450 | * then kill all urb. */ | 476 | * then kill all urb. */ |
| 451 | static void spcp8x5_close(struct tty_struct *tty, | 477 | static void spcp8x5_close(struct usb_serial_port *port) |
| 452 | struct usb_serial_port *port, struct file *filp) | ||
| 453 | { | 478 | { |
| 454 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); | 479 | struct spcp8x5_private *priv = usb_get_serial_port_data(port); |
| 455 | unsigned long flags; | 480 | unsigned long flags; |
| 456 | unsigned int c_cflag; | ||
| 457 | int bps; | ||
| 458 | long timeout; | ||
| 459 | wait_queue_t wait; | ||
| 460 | int result; | 481 | int result; |
| 461 | 482 | ||
| 462 | dbg("%s - port %d", __func__, port->number); | 483 | dbg("%s - port %d", __func__, port->number); |
| 463 | 484 | ||
| 464 | /* wait for data to drain from the buffer */ | ||
| 465 | spin_lock_irqsave(&priv->lock, flags); | 485 | spin_lock_irqsave(&priv->lock, flags); |
| 466 | timeout = SPCP8x5_CLOSING_WAIT; | ||
| 467 | init_waitqueue_entry(&wait, current); | ||
| 468 | add_wait_queue(&tty->write_wait, &wait); | ||
| 469 | for (;;) { | ||
| 470 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 471 | if (ringbuf_avail_data(priv->buf) == 0 || | ||
| 472 | timeout == 0 || signal_pending(current)) | ||
| 473 | break; | ||
| 474 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 475 | timeout = schedule_timeout(timeout); | ||
| 476 | spin_lock_irqsave(&priv->lock, flags); | ||
| 477 | } | ||
| 478 | set_current_state(TASK_RUNNING); | ||
| 479 | remove_wait_queue(&tty->write_wait, &wait); | ||
| 480 | |||
| 481 | /* clear out any remaining data in the buffer */ | 486 | /* clear out any remaining data in the buffer */ |
| 482 | clear_ringbuf(priv->buf); | 487 | clear_ringbuf(priv->buf); |
| 483 | spin_unlock_irqrestore(&priv->lock, flags); | 488 | spin_unlock_irqrestore(&priv->lock, flags); |
| 484 | 489 | ||
| 485 | /* wait for characters to drain from the device (this is long enough | ||
| 486 | * for the entire all byte spcp8x5 hardware buffer to drain with no | ||
| 487 | * flow control for data rates of 1200 bps or more, for lower rates we | ||
| 488 | * should really know how much data is in the buffer to compute a delay | ||
| 489 | * that is not unnecessarily long) */ | ||
| 490 | bps = tty_get_baud_rate(tty); | ||
| 491 | if (bps > 1200) | ||
| 492 | timeout = max((HZ*2560) / bps, HZ/10); | ||
| 493 | else | ||
| 494 | timeout = 2*HZ; | ||
| 495 | set_current_state(TASK_INTERRUPTIBLE); | ||
| 496 | schedule_timeout(timeout); | ||
| 497 | |||
| 498 | /* clear control lines */ | ||
| 499 | if (tty) { | ||
| 500 | c_cflag = tty->termios->c_cflag; | ||
| 501 | if (c_cflag & HUPCL) { | ||
| 502 | spin_lock_irqsave(&priv->lock, flags); | ||
| 503 | priv->line_control = 0; | ||
| 504 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 505 | spcp8x5_set_ctrlLine(port->serial->dev, 0 , priv->type); | ||
| 506 | } | ||
| 507 | } | ||
| 508 | |||
| 509 | /* kill urb */ | 490 | /* kill urb */ |
| 510 | if (port->write_urb != NULL) { | 491 | if (port->write_urb != NULL) { |
| 511 | result = usb_unlink_urb(port->write_urb); | 492 | result = usb_unlink_urb(port->write_urb); |
| @@ -665,13 +646,6 @@ static int spcp8x5_open(struct tty_struct *tty, | |||
| 665 | if (ret) | 646 | if (ret) |
| 666 | return ret; | 647 | return ret; |
| 667 | 648 | ||
| 668 | spin_lock_irqsave(&priv->lock, flags); | ||
| 669 | if (tty && (tty->termios->c_cflag & CBAUD)) | ||
| 670 | priv->line_control = MCR_DTR | MCR_RTS; | ||
| 671 | else | ||
| 672 | priv->line_control = 0; | ||
| 673 | spin_unlock_irqrestore(&priv->lock, flags); | ||
| 674 | |||
| 675 | spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); | 649 | spcp8x5_set_ctrlLine(serial->dev, priv->line_control , priv->type); |
| 676 | 650 | ||
| 677 | /* Setup termios */ | 651 | /* Setup termios */ |
| @@ -691,9 +665,10 @@ static int spcp8x5_open(struct tty_struct *tty, | |||
| 691 | port->read_urb->dev = serial->dev; | 665 | port->read_urb->dev = serial->dev; |
| 692 | ret = usb_submit_urb(port->read_urb, GFP_KERNEL); | 666 | ret = usb_submit_urb(port->read_urb, GFP_KERNEL); |
| 693 | if (ret) { | 667 | if (ret) { |
| 694 | spcp8x5_close(tty, port, NULL); | 668 | spcp8x5_close(port); |
| 695 | return -EPROTO; | 669 | return -EPROTO; |
| 696 | } | 670 | } |
| 671 | port->port.drain_delay = 256; | ||
| 697 | return 0; | 672 | return 0; |
| 698 | } | 673 | } |
| 699 | 674 | ||
| @@ -1033,6 +1008,8 @@ static struct usb_serial_driver spcp8x5_device = { | |||
| 1033 | .num_ports = 1, | 1008 | .num_ports = 1, |
| 1034 | .open = spcp8x5_open, | 1009 | .open = spcp8x5_open, |
| 1035 | .close = spcp8x5_close, | 1010 | .close = spcp8x5_close, |
| 1011 | .dtr_rts = spcp8x5_dtr_rts, | ||
| 1012 | .carrier_raised = spcp8x5_carrier_raised, | ||
| 1036 | .write = spcp8x5_write, | 1013 | .write = spcp8x5_write, |
| 1037 | .set_termios = spcp8x5_set_termios, | 1014 | .set_termios = spcp8x5_set_termios, |
| 1038 | .ioctl = spcp8x5_ioctl, | 1015 | .ioctl = spcp8x5_ioctl, |
diff --git a/drivers/usb/serial/symbolserial.c b/drivers/usb/serial/symbolserial.c index 69879e437940..8b07ebc6baeb 100644 --- a/drivers/usb/serial/symbolserial.c +++ b/drivers/usb/serial/symbolserial.c | |||
| @@ -152,8 +152,7 @@ static int symbol_open(struct tty_struct *tty, struct usb_serial_port *port, | |||
| 152 | return result; | 152 | return result; |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | static void symbol_close(struct tty_struct *tty, struct usb_serial_port *port, | 155 | static void symbol_close(struct usb_serial_port *port) |
| 156 | struct file *filp) | ||
| 157 | { | 156 | { |
| 158 | struct symbol_private *priv = usb_get_serial_data(port->serial); | 157 | struct symbol_private *priv = usb_get_serial_data(port->serial); |
| 159 | 158 | ||
diff --git a/drivers/usb/serial/ti_usb_3410_5052.c b/drivers/usb/serial/ti_usb_3410_5052.c index 0a64bac306ee..42cb04c403be 100644 --- a/drivers/usb/serial/ti_usb_3410_5052.c +++ b/drivers/usb/serial/ti_usb_3410_5052.c | |||
| @@ -100,8 +100,7 @@ static int ti_startup(struct usb_serial *serial); | |||
| 100 | static void ti_shutdown(struct usb_serial *serial); | 100 | static void ti_shutdown(struct usb_serial *serial); |
| 101 | static int ti_open(struct tty_struct *tty, struct usb_serial_port *port, | 101 | static int ti_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 102 | struct file *file); | 102 | struct file *file); |
| 103 | static void ti_close(struct tty_struct *tty, struct usb_serial_port *port, | 103 | static void ti_close(struct usb_serial_port *port); |
| 104 | struct file *file); | ||
| 105 | static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, | 104 | static int ti_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 106 | const unsigned char *data, int count); | 105 | const unsigned char *data, int count); |
| 107 | static int ti_write_room(struct tty_struct *tty); | 106 | static int ti_write_room(struct tty_struct *tty); |
| @@ -647,8 +646,7 @@ release_lock: | |||
| 647 | } | 646 | } |
| 648 | 647 | ||
| 649 | 648 | ||
| 650 | static void ti_close(struct tty_struct *tty, struct usb_serial_port *port, | 649 | static void ti_close(struct usb_serial_port *port) |
| 651 | struct file *file) | ||
| 652 | { | 650 | { |
| 653 | struct ti_device *tdev; | 651 | struct ti_device *tdev; |
| 654 | struct ti_port *tport; | 652 | struct ti_port *tport; |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index 0a566eea49c0..1967a7edc10c 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -238,9 +238,11 @@ static int serial_open (struct tty_struct *tty, struct file *filp) | |||
| 238 | goto bailout_interface_put; | 238 | goto bailout_interface_put; |
| 239 | mutex_unlock(&serial->disc_mutex); | 239 | mutex_unlock(&serial->disc_mutex); |
| 240 | } | 240 | } |
| 241 | |||
| 242 | mutex_unlock(&port->mutex); | 241 | mutex_unlock(&port->mutex); |
| 243 | return 0; | 242 | /* Now do the correct tty layer semantics */ |
| 243 | retval = tty_port_block_til_ready(&port->port, tty, filp); | ||
| 244 | if (retval == 0) | ||
| 245 | return 0; | ||
| 244 | 246 | ||
| 245 | bailout_interface_put: | 247 | bailout_interface_put: |
| 246 | usb_autopm_put_interface(serial->interface); | 248 | usb_autopm_put_interface(serial->interface); |
| @@ -259,64 +261,89 @@ bailout_serial_put: | |||
| 259 | return retval; | 261 | return retval; |
| 260 | } | 262 | } |
| 261 | 263 | ||
| 262 | static void serial_close(struct tty_struct *tty, struct file *filp) | 264 | /** |
| 265 | * serial_do_down - shut down hardware | ||
| 266 | * @port: port to shut down | ||
| 267 | * | ||
| 268 | * Shut down a USB port unless it is the console. We never shut down the | ||
| 269 | * console hardware as it will always be in use. | ||
| 270 | * | ||
| 271 | * Don't free any resources at this point | ||
| 272 | */ | ||
| 273 | static void serial_do_down(struct usb_serial_port *port) | ||
| 263 | { | 274 | { |
| 264 | struct usb_serial_port *port = tty->driver_data; | 275 | struct usb_serial_driver *drv = port->serial->type; |
| 265 | struct usb_serial *serial; | 276 | struct usb_serial *serial; |
| 266 | struct module *owner; | 277 | struct module *owner; |
| 267 | int count; | ||
| 268 | 278 | ||
| 269 | if (!port) | 279 | /* The console is magical, do not hang up the console hardware |
| 280 | or there will be tears */ | ||
| 281 | if (port->console) | ||
| 270 | return; | 282 | return; |
| 271 | 283 | ||
| 272 | dbg("%s - port %d", __func__, port->number); | ||
| 273 | |||
| 274 | mutex_lock(&port->mutex); | 284 | mutex_lock(&port->mutex); |
| 275 | serial = port->serial; | 285 | serial = port->serial; |
| 276 | owner = serial->type->driver.owner; | 286 | owner = serial->type->driver.owner; |
| 277 | 287 | ||
| 278 | if (port->port.count == 0) { | 288 | if (drv->close) |
| 279 | mutex_unlock(&port->mutex); | 289 | drv->close(port); |
| 280 | return; | ||
| 281 | } | ||
| 282 | |||
| 283 | if (port->port.count == 1) | ||
| 284 | /* only call the device specific close if this | ||
| 285 | * port is being closed by the last owner. Ensure we do | ||
| 286 | * this before we drop the port count. The call is protected | ||
| 287 | * by the port mutex | ||
| 288 | */ | ||
| 289 | serial->type->close(tty, port, filp); | ||
| 290 | |||
| 291 | if (port->port.count == (port->console ? 2 : 1)) { | ||
| 292 | struct tty_struct *tty = tty_port_tty_get(&port->port); | ||
| 293 | if (tty) { | ||
| 294 | /* We must do this before we drop the port count to | ||
| 295 | zero. */ | ||
| 296 | if (tty->driver_data) | ||
| 297 | tty->driver_data = NULL; | ||
| 298 | tty_port_tty_set(&port->port, NULL); | ||
| 299 | tty_kref_put(tty); | ||
| 300 | } | ||
| 301 | } | ||
| 302 | 290 | ||
| 303 | --port->port.count; | ||
| 304 | count = port->port.count; | ||
| 305 | mutex_unlock(&port->mutex); | 291 | mutex_unlock(&port->mutex); |
| 306 | put_device(&port->dev); | 292 | } |
| 293 | |||
| 294 | /** | ||
| 295 | * serial_do_free - free resources post close/hangup | ||
| 296 | * @port: port to free up | ||
| 297 | * | ||
| 298 | * Do the resource freeing and refcount dropping for the port. We must | ||
| 299 | * be careful about ordering and we must avoid freeing up the console. | ||
| 300 | */ | ||
| 307 | 301 | ||
| 302 | static void serial_do_free(struct usb_serial_port *port) | ||
| 303 | { | ||
| 304 | struct usb_serial *serial; | ||
| 305 | struct module *owner; | ||
| 306 | |||
| 307 | /* The console is magical, do not hang up the console hardware | ||
| 308 | or there will be tears */ | ||
| 309 | if (port->console) | ||
| 310 | return; | ||
| 311 | |||
| 312 | serial = port->serial; | ||
| 313 | owner = serial->type->driver.owner; | ||
| 314 | put_device(&port->dev); | ||
| 308 | /* Mustn't dereference port any more */ | 315 | /* Mustn't dereference port any more */ |
| 309 | if (count == 0) { | 316 | mutex_lock(&serial->disc_mutex); |
| 310 | mutex_lock(&serial->disc_mutex); | 317 | if (!serial->disconnected) |
| 311 | if (!serial->disconnected) | 318 | usb_autopm_put_interface(serial->interface); |
| 312 | usb_autopm_put_interface(serial->interface); | 319 | mutex_unlock(&serial->disc_mutex); |
| 313 | mutex_unlock(&serial->disc_mutex); | ||
| 314 | } | ||
| 315 | usb_serial_put(serial); | 320 | usb_serial_put(serial); |
| 316 | |||
| 317 | /* Mustn't dereference serial any more */ | 321 | /* Mustn't dereference serial any more */ |
| 318 | if (count == 0) | 322 | module_put(owner); |
| 319 | module_put(owner); | 323 | } |
| 324 | |||
| 325 | static void serial_close(struct tty_struct *tty, struct file *filp) | ||
| 326 | { | ||
| 327 | struct usb_serial_port *port = tty->driver_data; | ||
| 328 | |||
| 329 | dbg("%s - port %d", __func__, port->number); | ||
| 330 | |||
| 331 | |||
| 332 | if (tty_port_close_start(&port->port, tty, filp) == 0) | ||
| 333 | return; | ||
| 334 | |||
| 335 | serial_do_down(port); | ||
| 336 | tty_port_close_end(&port->port, tty); | ||
| 337 | tty_port_tty_set(&port->port, NULL); | ||
| 338 | serial_do_free(port); | ||
| 339 | } | ||
| 340 | |||
| 341 | static void serial_hangup(struct tty_struct *tty) | ||
| 342 | { | ||
| 343 | struct usb_serial_port *port = tty->driver_data; | ||
| 344 | serial_do_down(port); | ||
| 345 | tty_port_hangup(&port->port); | ||
| 346 | serial_do_free(port); | ||
| 320 | } | 347 | } |
| 321 | 348 | ||
| 322 | static int serial_write(struct tty_struct *tty, const unsigned char *buf, | 349 | static int serial_write(struct tty_struct *tty, const unsigned char *buf, |
| @@ -648,6 +675,29 @@ static struct usb_serial_driver *search_serial_device( | |||
| 648 | return NULL; | 675 | return NULL; |
| 649 | } | 676 | } |
| 650 | 677 | ||
| 678 | static int serial_carrier_raised(struct tty_port *port) | ||
| 679 | { | ||
| 680 | struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); | ||
| 681 | struct usb_serial_driver *drv = p->serial->type; | ||
| 682 | if (drv->carrier_raised) | ||
| 683 | return drv->carrier_raised(p); | ||
| 684 | /* No carrier control - don't block */ | ||
| 685 | return 1; | ||
| 686 | } | ||
| 687 | |||
| 688 | static void serial_dtr_rts(struct tty_port *port, int on) | ||
| 689 | { | ||
| 690 | struct usb_serial_port *p = container_of(port, struct usb_serial_port, port); | ||
| 691 | struct usb_serial_driver *drv = p->serial->type; | ||
| 692 | if (drv->dtr_rts) | ||
| 693 | drv->dtr_rts(p, on); | ||
| 694 | } | ||
| 695 | |||
| 696 | static const struct tty_port_operations serial_port_ops = { | ||
| 697 | .carrier_raised = serial_carrier_raised, | ||
| 698 | .dtr_rts = serial_dtr_rts, | ||
| 699 | }; | ||
| 700 | |||
| 651 | int usb_serial_probe(struct usb_interface *interface, | 701 | int usb_serial_probe(struct usb_interface *interface, |
| 652 | const struct usb_device_id *id) | 702 | const struct usb_device_id *id) |
| 653 | { | 703 | { |
| @@ -841,6 +891,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 841 | if (!port) | 891 | if (!port) |
| 842 | goto probe_error; | 892 | goto probe_error; |
| 843 | tty_port_init(&port->port); | 893 | tty_port_init(&port->port); |
| 894 | port->port.ops = &serial_port_ops; | ||
| 844 | port->serial = serial; | 895 | port->serial = serial; |
| 845 | spin_lock_init(&port->lock); | 896 | spin_lock_init(&port->lock); |
| 846 | mutex_init(&port->mutex); | 897 | mutex_init(&port->mutex); |
| @@ -974,6 +1025,7 @@ int usb_serial_probe(struct usb_interface *interface, | |||
| 974 | if (retval > 0) { | 1025 | if (retval > 0) { |
| 975 | /* quietly accept this device, but don't bind to a | 1026 | /* quietly accept this device, but don't bind to a |
| 976 | serial port as it's about to disappear */ | 1027 | serial port as it's about to disappear */ |
| 1028 | serial->num_ports = 0; | ||
| 977 | goto exit; | 1029 | goto exit; |
| 978 | } | 1030 | } |
| 979 | } | 1031 | } |
| @@ -1070,6 +1122,9 @@ void usb_serial_disconnect(struct usb_interface *interface) | |||
| 1070 | if (port) { | 1122 | if (port) { |
| 1071 | struct tty_struct *tty = tty_port_tty_get(&port->port); | 1123 | struct tty_struct *tty = tty_port_tty_get(&port->port); |
| 1072 | if (tty) { | 1124 | if (tty) { |
| 1125 | /* The hangup will occur asynchronously but | ||
| 1126 | the object refcounts will sort out all the | ||
| 1127 | cleanup */ | ||
| 1073 | tty_hangup(tty); | 1128 | tty_hangup(tty); |
| 1074 | tty_kref_put(tty); | 1129 | tty_kref_put(tty); |
| 1075 | } | 1130 | } |
| @@ -1134,6 +1189,7 @@ static const struct tty_operations serial_ops = { | |||
| 1134 | .open = serial_open, | 1189 | .open = serial_open, |
| 1135 | .close = serial_close, | 1190 | .close = serial_close, |
| 1136 | .write = serial_write, | 1191 | .write = serial_write, |
| 1192 | .hangup = serial_hangup, | ||
| 1137 | .write_room = serial_write_room, | 1193 | .write_room = serial_write_room, |
| 1138 | .ioctl = serial_ioctl, | 1194 | .ioctl = serial_ioctl, |
| 1139 | .set_termios = serial_set_termios, | 1195 | .set_termios = serial_set_termios, |
| @@ -1146,6 +1202,7 @@ static const struct tty_operations serial_ops = { | |||
| 1146 | .proc_fops = &serial_proc_fops, | 1202 | .proc_fops = &serial_proc_fops, |
| 1147 | }; | 1203 | }; |
| 1148 | 1204 | ||
| 1205 | |||
| 1149 | struct tty_driver *usb_serial_tty_driver; | 1206 | struct tty_driver *usb_serial_tty_driver; |
| 1150 | 1207 | ||
| 1151 | static int __init usb_serial_init(void) | 1208 | static int __init usb_serial_init(void) |
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c index 5ac414bda718..b15f1c0e1d4a 100644 --- a/drivers/usb/serial/visor.c +++ b/drivers/usb/serial/visor.c | |||
| @@ -38,8 +38,7 @@ | |||
| 38 | /* function prototypes for a handspring visor */ | 38 | /* function prototypes for a handspring visor */ |
| 39 | static int visor_open(struct tty_struct *tty, struct usb_serial_port *port, | 39 | static int visor_open(struct tty_struct *tty, struct usb_serial_port *port, |
| 40 | struct file *filp); | 40 | struct file *filp); |
| 41 | static void visor_close(struct tty_struct *tty, struct usb_serial_port *port, | 41 | static void visor_close(struct usb_serial_port *port); |
| 42 | struct file *filp); | ||
| 43 | static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, | 42 | static int visor_write(struct tty_struct *tty, struct usb_serial_port *port, |
| 44 | const unsigned char *buf, int count); | 43 | const unsigned char *buf, int count); |
| 45 | static int visor_write_room(struct tty_struct *tty); | 44 | static int visor_write_room(struct tty_struct *tty); |
| @@ -324,8 +323,7 @@ exit: | |||
| 324 | } | 323 | } |
| 325 | 324 | ||
| 326 | 325 | ||
| 327 | static void visor_close(struct tty_struct *tty, | 326 | static void visor_close(struct usb_serial_port *port) |
| 328 | struct usb_serial_port *port, struct file *filp) | ||
| 329 | { | 327 | { |
| 330 | struct visor_private *priv = usb_get_serial_port_data(port); | 328 | struct visor_private *priv = usb_get_serial_port_data(port); |
| 331 | unsigned char *transfer_buffer; | 329 | unsigned char *transfer_buffer; |
diff --git a/drivers/usb/serial/whiteheat.c b/drivers/usb/serial/whiteheat.c index 5335d3211c07..7c7295d09f34 100644 --- a/drivers/usb/serial/whiteheat.c +++ b/drivers/usb/serial/whiteheat.c | |||
| @@ -147,8 +147,7 @@ static int whiteheat_attach(struct usb_serial *serial); | |||
| 147 | static void whiteheat_shutdown(struct usb_serial *serial); | 147 | static void whiteheat_shutdown(struct usb_serial *serial); |
| 148 | static int whiteheat_open(struct tty_struct *tty, | 148 | static int whiteheat_open(struct tty_struct *tty, |
| 149 | struct usb_serial_port *port, struct file *filp); | 149 | struct usb_serial_port *port, struct file *filp); |
| 150 | static void whiteheat_close(struct tty_struct *tty, | 150 | static void whiteheat_close(struct usb_serial_port *port); |
| 151 | struct usb_serial_port *port, struct file *filp); | ||
| 152 | static int whiteheat_write(struct tty_struct *tty, | 151 | static int whiteheat_write(struct tty_struct *tty, |
| 153 | struct usb_serial_port *port, | 152 | struct usb_serial_port *port, |
| 154 | const unsigned char *buf, int count); | 153 | const unsigned char *buf, int count); |
| @@ -712,8 +711,7 @@ exit: | |||
| 712 | } | 711 | } |
| 713 | 712 | ||
| 714 | 713 | ||
| 715 | static void whiteheat_close(struct tty_struct *tty, | 714 | static void whiteheat_close(struct usb_serial_port *port) |
| 716 | struct usb_serial_port *port, struct file *filp) | ||
| 717 | { | 715 | { |
| 718 | struct whiteheat_private *info = usb_get_serial_port_data(port); | 716 | struct whiteheat_private *info = usb_get_serial_port_data(port); |
| 719 | struct whiteheat_urb_wrap *wrap; | 717 | struct whiteheat_urb_wrap *wrap; |
| @@ -723,31 +721,7 @@ static void whiteheat_close(struct tty_struct *tty, | |||
| 723 | 721 | ||
| 724 | dbg("%s - port %d", __func__, port->number); | 722 | dbg("%s - port %d", __func__, port->number); |
| 725 | 723 | ||
| 726 | mutex_lock(&port->serial->disc_mutex); | ||
| 727 | /* filp is NULL when called from usb_serial_disconnect */ | ||
| 728 | if ((filp && (tty_hung_up_p(filp))) || port->serial->disconnected) { | ||
| 729 | mutex_unlock(&port->serial->disc_mutex); | ||
| 730 | return; | ||
| 731 | } | ||
| 732 | mutex_unlock(&port->serial->disc_mutex); | ||
| 733 | |||
| 734 | tty->closing = 1; | ||
| 735 | |||
| 736 | /* | ||
| 737 | * Not currently in use; tty_wait_until_sent() calls | ||
| 738 | * serial_chars_in_buffer() which deadlocks on the second semaphore | ||
| 739 | * acquisition. This should be fixed at some point. Greg's been | ||
| 740 | * notified. | ||
| 741 | if ((filp->f_flags & (O_NDELAY | O_NONBLOCK)) == 0) { | ||
| 742 | tty_wait_until_sent(tty, CLOSING_DELAY); | ||
| 743 | } | ||
| 744 | */ | ||
| 745 | |||
| 746 | tty_driver_flush_buffer(tty); | ||
| 747 | tty_ldisc_flush(tty); | ||
| 748 | |||
| 749 | firm_report_tx_done(port); | 724 | firm_report_tx_done(port); |
| 750 | |||
| 751 | firm_close(port); | 725 | firm_close(port); |
| 752 | 726 | ||
| 753 | /* shutdown our bulk reads and writes */ | 727 | /* shutdown our bulk reads and writes */ |
| @@ -775,10 +749,7 @@ static void whiteheat_close(struct tty_struct *tty, | |||
| 775 | } | 749 | } |
| 776 | spin_unlock_irq(&info->lock); | 750 | spin_unlock_irq(&info->lock); |
| 777 | mutex_unlock(&info->deathwarrant); | 751 | mutex_unlock(&info->deathwarrant); |
| 778 | |||
| 779 | stop_command_port(port->serial); | 752 | stop_command_port(port->serial); |
| 780 | |||
| 781 | tty->closing = 0; | ||
| 782 | } | 753 | } |
| 783 | 754 | ||
| 784 | 755 | ||
diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c index 4ca3b5860643..cfa26d56ce60 100644 --- a/drivers/usb/storage/scsiglue.c +++ b/drivers/usb/storage/scsiglue.c | |||
| @@ -132,7 +132,7 @@ static int slave_configure(struct scsi_device *sdev) | |||
| 132 | 132 | ||
| 133 | if (us->fflags & US_FL_MAX_SECTORS_MIN) | 133 | if (us->fflags & US_FL_MAX_SECTORS_MIN) |
| 134 | max_sectors = PAGE_CACHE_SIZE >> 9; | 134 | max_sectors = PAGE_CACHE_SIZE >> 9; |
| 135 | if (sdev->request_queue->max_sectors > max_sectors) | 135 | if (queue_max_sectors(sdev->request_queue) > max_sectors) |
| 136 | blk_queue_max_sectors(sdev->request_queue, | 136 | blk_queue_max_sectors(sdev->request_queue, |
| 137 | max_sectors); | 137 | max_sectors); |
| 138 | } else if (sdev->type == TYPE_TAPE) { | 138 | } else if (sdev->type == TYPE_TAPE) { |
| @@ -483,7 +483,7 @@ static ssize_t show_max_sectors(struct device *dev, struct device_attribute *att | |||
| 483 | { | 483 | { |
| 484 | struct scsi_device *sdev = to_scsi_device(dev); | 484 | struct scsi_device *sdev = to_scsi_device(dev); |
| 485 | 485 | ||
| 486 | return sprintf(buf, "%u\n", sdev->request_queue->max_sectors); | 486 | return sprintf(buf, "%u\n", queue_max_sectors(sdev->request_queue)); |
| 487 | } | 487 | } |
| 488 | 488 | ||
| 489 | /* Input routine for the sysfs max_sectors file */ | 489 | /* Input routine for the sysfs max_sectors file */ |
diff --git a/drivers/video/atmel_lcdfb.c b/drivers/video/atmel_lcdfb.c index 9a577a800db5..2fb63f6ea2f1 100644 --- a/drivers/video/atmel_lcdfb.c +++ b/drivers/video/atmel_lcdfb.c | |||
| @@ -29,14 +29,8 @@ | |||
| 29 | 29 | ||
| 30 | /* configurable parameters */ | 30 | /* configurable parameters */ |
| 31 | #define ATMEL_LCDC_CVAL_DEFAULT 0xc8 | 31 | #define ATMEL_LCDC_CVAL_DEFAULT 0xc8 |
| 32 | #define ATMEL_LCDC_DMA_BURST_LEN 8 | 32 | #define ATMEL_LCDC_DMA_BURST_LEN 8 /* words */ |
| 33 | 33 | #define ATMEL_LCDC_FIFO_SIZE 512 /* words */ | |
| 34 | #if defined(CONFIG_ARCH_AT91SAM9263) || defined(CONFIG_ARCH_AT91CAP9) || \ | ||
| 35 | defined(CONFIG_ARCH_AT91SAM9RL) | ||
| 36 | #define ATMEL_LCDC_FIFO_SIZE 2048 | ||
| 37 | #else | ||
| 38 | #define ATMEL_LCDC_FIFO_SIZE 512 | ||
| 39 | #endif | ||
| 40 | 34 | ||
| 41 | #if defined(CONFIG_ARCH_AT91) | 35 | #if defined(CONFIG_ARCH_AT91) |
| 42 | #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ | 36 | #define ATMEL_LCDFB_FBINFO_DEFAULT (FBINFO_DEFAULT \ |
diff --git a/drivers/video/console/vgacon.c b/drivers/video/console/vgacon.c index 38e86b84dce0..59d7d5ec17a4 100644 --- a/drivers/video/console/vgacon.c +++ b/drivers/video/console/vgacon.c | |||
| @@ -180,7 +180,7 @@ static inline void vga_set_mem_top(struct vc_data *c) | |||
| 180 | } | 180 | } |
| 181 | 181 | ||
| 182 | #ifdef CONFIG_VGACON_SOFT_SCROLLBACK | 182 | #ifdef CONFIG_VGACON_SOFT_SCROLLBACK |
| 183 | #include <linux/bootmem.h> | 183 | #include <linux/slab.h> |
| 184 | /* software scrollback */ | 184 | /* software scrollback */ |
| 185 | static void *vgacon_scrollback; | 185 | static void *vgacon_scrollback; |
| 186 | static int vgacon_scrollback_tail; | 186 | static int vgacon_scrollback_tail; |
| @@ -210,8 +210,7 @@ static void vgacon_scrollback_init(int pitch) | |||
| 210 | */ | 210 | */ |
| 211 | static void __init_refok vgacon_scrollback_startup(void) | 211 | static void __init_refok vgacon_scrollback_startup(void) |
| 212 | { | 212 | { |
| 213 | vgacon_scrollback = alloc_bootmem(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE | 213 | vgacon_scrollback = kcalloc(CONFIG_VGACON_SOFT_SCROLLBACK_SIZE, 1024, GFP_NOWAIT); |
| 214 | * 1024); | ||
| 215 | vgacon_scrollback_init(vga_video_num_columns * 2); | 214 | vgacon_scrollback_init(vga_video_num_columns * 2); |
| 216 | } | 215 | } |
| 217 | 216 | ||
diff --git a/drivers/video/hitfb.c b/drivers/video/hitfb.c index e6467cf9f19f..020db7fc9153 100644 --- a/drivers/video/hitfb.c +++ b/drivers/video/hitfb.c | |||
| @@ -335,9 +335,9 @@ static int __init hitfb_probe(struct platform_device *dev) | |||
| 335 | if (fb_get_options("hitfb", NULL)) | 335 | if (fb_get_options("hitfb", NULL)) |
| 336 | return -ENODEV; | 336 | return -ENODEV; |
| 337 | 337 | ||
| 338 | hitfb_fix.mmio_start = CONFIG_HD64461_IOBASE+0x1000; | 338 | hitfb_fix.mmio_start = HD64461_IO_OFFSET(0x1000); |
| 339 | hitfb_fix.mmio_len = 0x1000; | 339 | hitfb_fix.mmio_len = 0x1000; |
| 340 | hitfb_fix.smem_start = CONFIG_HD64461_IOBASE + 0x02000000; | 340 | hitfb_fix.smem_start = HD64461_IO_OFFSET(0x02000000); |
| 341 | hitfb_fix.smem_len = 512 * 1024; | 341 | hitfb_fix.smem_len = 512 * 1024; |
| 342 | 342 | ||
| 343 | lcdclor = fb_readw(HD64461_LCDCLOR); | 343 | lcdclor = fb_readw(HD64461_LCDCLOR); |
diff --git a/drivers/video/s3c-fb.c b/drivers/video/s3c-fb.c index 5e9c6302433b..d3a568e6b169 100644 --- a/drivers/video/s3c-fb.c +++ b/drivers/video/s3c-fb.c | |||
| @@ -947,7 +947,8 @@ static int __devexit s3c_fb_remove(struct platform_device *pdev) | |||
| 947 | int win; | 947 | int win; |
| 948 | 948 | ||
| 949 | for (win = 0; win <= S3C_FB_MAX_WIN; win++) | 949 | for (win = 0; win <= S3C_FB_MAX_WIN; win++) |
| 950 | s3c_fb_release_win(sfb, sfb->windows[win]); | 950 | if (sfb->windows[win]) |
| 951 | s3c_fb_release_win(sfb, sfb->windows[win]); | ||
| 951 | 952 | ||
| 952 | iounmap(sfb->regs); | 953 | iounmap(sfb->regs); |
| 953 | 954 | ||
| @@ -985,11 +986,20 @@ static int s3c_fb_suspend(struct platform_device *pdev, pm_message_t state) | |||
| 985 | static int s3c_fb_resume(struct platform_device *pdev) | 986 | static int s3c_fb_resume(struct platform_device *pdev) |
| 986 | { | 987 | { |
| 987 | struct s3c_fb *sfb = platform_get_drvdata(pdev); | 988 | struct s3c_fb *sfb = platform_get_drvdata(pdev); |
| 989 | struct s3c_fb_platdata *pd = sfb->pdata; | ||
| 988 | struct s3c_fb_win *win; | 990 | struct s3c_fb_win *win; |
| 989 | int win_no; | 991 | int win_no; |
| 990 | 992 | ||
| 991 | clk_enable(sfb->bus_clk); | 993 | clk_enable(sfb->bus_clk); |
| 992 | 994 | ||
| 995 | /* setup registers */ | ||
| 996 | writel(pd->vidcon1, sfb->regs + VIDCON1); | ||
| 997 | |||
| 998 | /* zero all windows before we do anything */ | ||
| 999 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) | ||
| 1000 | s3c_fb_clear_win(sfb, win_no); | ||
| 1001 | |||
| 1002 | /* restore framebuffers */ | ||
| 993 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { | 1003 | for (win_no = 0; win_no < S3C_FB_MAX_WIN; win_no++) { |
| 994 | win = sfb->windows[win_no]; | 1004 | win = sfb->windows[win_no]; |
| 995 | if (!win) | 1005 | if (!win) |
diff --git a/drivers/xen/Kconfig b/drivers/xen/Kconfig index 8ac9cddac575..cab100acf983 100644 --- a/drivers/xen/Kconfig +++ b/drivers/xen/Kconfig | |||
| @@ -18,6 +18,16 @@ config XEN_SCRUB_PAGES | |||
| 18 | secure, but slightly less efficient. | 18 | secure, but slightly less efficient. |
| 19 | If in doubt, say yes. | 19 | If in doubt, say yes. |
| 20 | 20 | ||
| 21 | config XEN_DEV_EVTCHN | ||
| 22 | tristate "Xen /dev/xen/evtchn device" | ||
| 23 | depends on XEN | ||
| 24 | default y | ||
| 25 | help | ||
| 26 | The evtchn driver allows a userspace process to triger event | ||
| 27 | channels and to receive notification of an event channel | ||
| 28 | firing. | ||
| 29 | If in doubt, say yes. | ||
| 30 | |||
| 21 | config XENFS | 31 | config XENFS |
| 22 | tristate "Xen filesystem" | 32 | tristate "Xen filesystem" |
| 23 | depends on XEN | 33 | depends on XEN |
| @@ -41,3 +51,13 @@ config XEN_COMPAT_XENFS | |||
| 41 | a xen platform. | 51 | a xen platform. |
| 42 | If in doubt, say yes. | 52 | If in doubt, say yes. |
| 43 | 53 | ||
| 54 | config XEN_SYS_HYPERVISOR | ||
| 55 | bool "Create xen entries under /sys/hypervisor" | ||
| 56 | depends on XEN && SYSFS | ||
| 57 | select SYS_HYPERVISOR | ||
| 58 | default y | ||
| 59 | help | ||
| 60 | Create entries under /sys/hypervisor describing the Xen | ||
| 61 | hypervisor environment. When running native or in another | ||
| 62 | virtual environment, /sys/hypervisor will still be present, | ||
| 63 | but will have no xen contents. \ No newline at end of file | ||
diff --git a/drivers/xen/Makefile b/drivers/xen/Makefile index ff8accc9e103..ec2a39b1e26f 100644 --- a/drivers/xen/Makefile +++ b/drivers/xen/Makefile | |||
| @@ -4,4 +4,6 @@ obj-y += xenbus/ | |||
| 4 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o | 4 | obj-$(CONFIG_HOTPLUG_CPU) += cpu_hotplug.o |
| 5 | obj-$(CONFIG_XEN_XENCOMM) += xencomm.o | 5 | obj-$(CONFIG_XEN_XENCOMM) += xencomm.o |
| 6 | obj-$(CONFIG_XEN_BALLOON) += balloon.o | 6 | obj-$(CONFIG_XEN_BALLOON) += balloon.o |
| 7 | obj-$(CONFIG_XENFS) += xenfs/ \ No newline at end of file | 7 | obj-$(CONFIG_XEN_DEV_EVTCHN) += evtchn.o |
| 8 | obj-$(CONFIG_XENFS) += xenfs/ | ||
| 9 | obj-$(CONFIG_XEN_SYS_HYPERVISOR) += sys-hypervisor.o \ No newline at end of file | ||
diff --git a/drivers/xen/events.c b/drivers/xen/events.c index 30963af5dba0..891d2e90753a 100644 --- a/drivers/xen/events.c +++ b/drivers/xen/events.c | |||
| @@ -151,6 +151,12 @@ static unsigned int evtchn_from_irq(unsigned irq) | |||
| 151 | return info_for_irq(irq)->evtchn; | 151 | return info_for_irq(irq)->evtchn; |
| 152 | } | 152 | } |
| 153 | 153 | ||
| 154 | unsigned irq_from_evtchn(unsigned int evtchn) | ||
| 155 | { | ||
| 156 | return evtchn_to_irq[evtchn]; | ||
| 157 | } | ||
| 158 | EXPORT_SYMBOL_GPL(irq_from_evtchn); | ||
| 159 | |||
| 154 | static enum ipi_vector ipi_from_irq(unsigned irq) | 160 | static enum ipi_vector ipi_from_irq(unsigned irq) |
| 155 | { | 161 | { |
| 156 | struct irq_info *info = info_for_irq(irq); | 162 | struct irq_info *info = info_for_irq(irq); |
| @@ -335,7 +341,7 @@ static int find_unbound_irq(void) | |||
| 335 | if (irq == nr_irqs) | 341 | if (irq == nr_irqs) |
| 336 | panic("No available IRQ to bind to: increase nr_irqs!\n"); | 342 | panic("No available IRQ to bind to: increase nr_irqs!\n"); |
| 337 | 343 | ||
| 338 | desc = irq_to_desc_alloc_cpu(irq, 0); | 344 | desc = irq_to_desc_alloc_node(irq, 0); |
| 339 | if (WARN_ON(desc == NULL)) | 345 | if (WARN_ON(desc == NULL)) |
| 340 | return -1; | 346 | return -1; |
| 341 | 347 | ||
| @@ -688,13 +694,13 @@ void rebind_evtchn_irq(int evtchn, int irq) | |||
| 688 | } | 694 | } |
| 689 | 695 | ||
| 690 | /* Rebind an evtchn so that it gets delivered to a specific cpu */ | 696 | /* Rebind an evtchn so that it gets delivered to a specific cpu */ |
| 691 | static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | 697 | static int rebind_irq_to_cpu(unsigned irq, unsigned tcpu) |
| 692 | { | 698 | { |
| 693 | struct evtchn_bind_vcpu bind_vcpu; | 699 | struct evtchn_bind_vcpu bind_vcpu; |
| 694 | int evtchn = evtchn_from_irq(irq); | 700 | int evtchn = evtchn_from_irq(irq); |
| 695 | 701 | ||
| 696 | if (!VALID_EVTCHN(evtchn)) | 702 | if (!VALID_EVTCHN(evtchn)) |
| 697 | return; | 703 | return -1; |
| 698 | 704 | ||
| 699 | /* Send future instances of this interrupt to other vcpu. */ | 705 | /* Send future instances of this interrupt to other vcpu. */ |
| 700 | bind_vcpu.port = evtchn; | 706 | bind_vcpu.port = evtchn; |
| @@ -707,13 +713,15 @@ static void rebind_irq_to_cpu(unsigned irq, unsigned tcpu) | |||
| 707 | */ | 713 | */ |
| 708 | if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0) | 714 | if (HYPERVISOR_event_channel_op(EVTCHNOP_bind_vcpu, &bind_vcpu) >= 0) |
| 709 | bind_evtchn_to_cpu(evtchn, tcpu); | 715 | bind_evtchn_to_cpu(evtchn, tcpu); |
| 710 | } | ||
| 711 | 716 | ||
| 717 | return 0; | ||
| 718 | } | ||
| 712 | 719 | ||
| 713 | static void set_affinity_irq(unsigned irq, const struct cpumask *dest) | 720 | static int set_affinity_irq(unsigned irq, const struct cpumask *dest) |
| 714 | { | 721 | { |
| 715 | unsigned tcpu = cpumask_first(dest); | 722 | unsigned tcpu = cpumask_first(dest); |
| 716 | rebind_irq_to_cpu(irq, tcpu); | 723 | |
| 724 | return rebind_irq_to_cpu(irq, tcpu); | ||
| 717 | } | 725 | } |
| 718 | 726 | ||
| 719 | int resend_irq_on_evtchn(unsigned int irq) | 727 | int resend_irq_on_evtchn(unsigned int irq) |
diff --git a/drivers/xen/evtchn.c b/drivers/xen/evtchn.c new file mode 100644 index 000000000000..af031950f9b1 --- /dev/null +++ b/drivers/xen/evtchn.c | |||
| @@ -0,0 +1,507 @@ | |||
| 1 | /****************************************************************************** | ||
| 2 | * evtchn.c | ||
| 3 | * | ||
| 4 | * Driver for receiving and demuxing event-channel signals. | ||
| 5 | * | ||
| 6 | * Copyright (c) 2004-2005, K A Fraser | ||
| 7 | * Multi-process extensions Copyright (c) 2004, Steven Smith | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License version 2 | ||
| 11 | * as published by the Free Software Foundation; or, when distributed | ||
| 12 | * separately from the Linux kernel or incorporated into other | ||
| 13 | * software packages, subject to the following license: | ||
| 14 | * | ||
| 15 | * Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 16 | * of this source file (the "Software"), to deal in the Software without | ||
| 17 | * restriction, including without limitation the rights to use, copy, modify, | ||
| 18 | * merge, publish, distribute, sublicense, and/or sell copies of the Software, | ||
| 19 | * and to permit persons to whom the Software is furnished to do so, subject to | ||
| 20 | * the following conditions: | ||
| 21 | * | ||
| 22 | * The above copyright notice and this permission notice shall be included in | ||
| 23 | * all copies or substantial portions of the Software. | ||
| 24 | * | ||
| 25 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 26 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 27 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 28 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 29 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
| 30 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS | ||
| 31 | * IN THE SOFTWARE. | ||
| 32 | */ | ||
| 33 | |||
| 34 | #include <linux/module.h> | ||
| 35 | #include <linux/kernel.h> | ||
| 36 | #include <linux/sched.h> | ||
| 37 | #include <linux/slab.h> | ||
| 38 | #include <linux/string.h> | ||
| 39 | #include <linux/errno.h> | ||
| 40 | #include <linux/fs.h> | ||
| 41 | #include <linux/errno.h> | ||
| 42 | #include <linux/miscdevice.h> | ||
| 43 | #include <linux/major.h> | ||
| 44 | #include <linux/proc_fs.h> | ||
| 45 | #include <linux/stat.h> | ||
| 46 | #include <linux/poll.h> | ||
| 47 | #include <linux/irq.h> | ||
| 48 | #include <linux/init.h> | ||
| 49 | #include <linux/gfp.h> | ||
| 50 | #include <linux/mutex.h> | ||
| 51 | #include <linux/cpu.h> | ||
| 52 | #include <xen/events.h> | ||
| 53 | #include <xen/evtchn.h> | ||
| 54 | #include <asm/xen/hypervisor.h> | ||
| 55 | |||
| 56 | struct per_user_data { | ||
| 57 | struct mutex bind_mutex; /* serialize bind/unbind operations */ | ||
| 58 | |||
| 59 | /* Notification ring, accessed via /dev/xen/evtchn. */ | ||
| 60 | #define EVTCHN_RING_SIZE (PAGE_SIZE / sizeof(evtchn_port_t)) | ||
| 61 | #define EVTCHN_RING_MASK(_i) ((_i)&(EVTCHN_RING_SIZE-1)) | ||
| 62 | evtchn_port_t *ring; | ||
| 63 | unsigned int ring_cons, ring_prod, ring_overflow; | ||
| 64 | struct mutex ring_cons_mutex; /* protect against concurrent readers */ | ||
| 65 | |||
| 66 | /* Processes wait on this queue when ring is empty. */ | ||
| 67 | wait_queue_head_t evtchn_wait; | ||
| 68 | struct fasync_struct *evtchn_async_queue; | ||
| 69 | const char *name; | ||
| 70 | }; | ||
| 71 | |||
| 72 | /* Who's bound to each port? */ | ||
| 73 | static struct per_user_data *port_user[NR_EVENT_CHANNELS]; | ||
| 74 | static DEFINE_SPINLOCK(port_user_lock); /* protects port_user[] and ring_prod */ | ||
| 75 | |||
| 76 | irqreturn_t evtchn_interrupt(int irq, void *data) | ||
| 77 | { | ||
| 78 | unsigned int port = (unsigned long)data; | ||
| 79 | struct per_user_data *u; | ||
| 80 | |||
| 81 | spin_lock(&port_user_lock); | ||
| 82 | |||
| 83 | u = port_user[port]; | ||
| 84 | |||
| 85 | disable_irq_nosync(irq); | ||
| 86 | |||
| 87 | if ((u->ring_prod - u->ring_cons) < EVTCHN_RING_SIZE) { | ||
| 88 | u->ring[EVTCHN_RING_MASK(u->ring_prod)] = port; | ||
| 89 | wmb(); /* Ensure ring contents visible */ | ||
| 90 | if (u->ring_cons == u->ring_prod++) { | ||
| 91 | wake_up_interruptible(&u->evtchn_wait); | ||
| 92 | kill_fasync(&u->evtchn_async_queue, | ||
| 93 | SIGIO, POLL_IN); | ||
| 94 | } | ||
| 95 | } else { | ||
| 96 | u->ring_overflow = 1; | ||
| 97 | } | ||
| 98 | |||
| 99 | spin_unlock(&port_user_lock); | ||
| 100 | |||
| 101 | return IRQ_HANDLED; | ||
| 102 | } | ||
| 103 | |||
| 104 | static ssize_t evtchn_read(struct file *file, char __user *buf, | ||
| 105 | size_t count, loff_t *ppos) | ||
| 106 | { | ||
| 107 | int rc; | ||
| 108 | unsigned int c, p, bytes1 = 0, bytes2 = 0; | ||
| 109 | struct per_user_data *u = file->private_data; | ||
| 110 | |||
| 111 | /* Whole number of ports. */ | ||
| 112 | count &= ~(sizeof(evtchn_port_t)-1); | ||
| 113 | |||
| 114 | if (count == 0) | ||
| 115 | return 0; | ||
| 116 | |||
| 117 | if (count > PAGE_SIZE) | ||
| 118 | count = PAGE_SIZE; | ||
| 119 | |||
| 120 | for (;;) { | ||
| 121 | mutex_lock(&u->ring_cons_mutex); | ||
| 122 | |||
| 123 | rc = -EFBIG; | ||
| 124 | if (u->ring_overflow) | ||
| 125 | goto unlock_out; | ||
| 126 | |||
| 127 | c = u->ring_cons; | ||
| 128 | p = u->ring_prod; | ||
| 129 | if (c != p) | ||
| 130 | break; | ||
| 131 | |||
| 132 | mutex_unlock(&u->ring_cons_mutex); | ||
| 133 | |||
| 134 | if (file->f_flags & O_NONBLOCK) | ||
| 135 | return -EAGAIN; | ||
| 136 | |||
| 137 | rc = wait_event_interruptible(u->evtchn_wait, | ||
| 138 | u->ring_cons != u->ring_prod); | ||
| 139 | if (rc) | ||
| 140 | return rc; | ||
| 141 | } | ||
| 142 | |||
| 143 | /* Byte lengths of two chunks. Chunk split (if any) is at ring wrap. */ | ||
| 144 | if (((c ^ p) & EVTCHN_RING_SIZE) != 0) { | ||
| 145 | bytes1 = (EVTCHN_RING_SIZE - EVTCHN_RING_MASK(c)) * | ||
| 146 | sizeof(evtchn_port_t); | ||
| 147 | bytes2 = EVTCHN_RING_MASK(p) * sizeof(evtchn_port_t); | ||
| 148 | } else { | ||
| 149 | bytes1 = (p - c) * sizeof(evtchn_port_t); | ||
| 150 | bytes2 = 0; | ||
| 151 | } | ||
| 152 | |||
| 153 | /* Truncate chunks according to caller's maximum byte count. */ | ||
| 154 | if (bytes1 > count) { | ||
| 155 | bytes1 = count; | ||
| 156 | bytes2 = 0; | ||
| 157 | } else if ((bytes1 + bytes2) > count) { | ||
| 158 | bytes2 = count - bytes1; | ||
| 159 | } | ||
| 160 | |||
| 161 | rc = -EFAULT; | ||
| 162 | rmb(); /* Ensure that we see the port before we copy it. */ | ||
| 163 | if (copy_to_user(buf, &u->ring[EVTCHN_RING_MASK(c)], bytes1) || | ||
| 164 | ((bytes2 != 0) && | ||
| 165 | copy_to_user(&buf[bytes1], &u->ring[0], bytes2))) | ||
| 166 | goto unlock_out; | ||
| 167 | |||
| 168 | u->ring_cons += (bytes1 + bytes2) / sizeof(evtchn_port_t); | ||
| 169 | rc = bytes1 + bytes2; | ||
| 170 | |||
| 171 | unlock_out: | ||
| 172 | mutex_unlock(&u->ring_cons_mutex); | ||
| 173 | return rc; | ||
| 174 | } | ||
| 175 | |||
| 176 | static ssize_t evtchn_write(struct file *file, const char __user *buf, | ||
| 177 | size_t count, loff_t *ppos) | ||
| 178 | { | ||
| 179 | int rc, i; | ||
| 180 | evtchn_port_t *kbuf = (evtchn_port_t *)__get_free_page(GFP_KERNEL); | ||
| 181 | struct per_user_data *u = file->private_data; | ||
| 182 | |||
| 183 | if (kbuf == NULL) | ||
| 184 | return -ENOMEM; | ||
| 185 | |||
| 186 | /* Whole number of ports. */ | ||
| 187 | count &= ~(sizeof(evtchn_port_t)-1); | ||
| 188 | |||
| 189 | rc = 0; | ||
| 190 | if (count == 0) | ||
| 191 | goto out; | ||
| 192 | |||
| 193 | if (count > PAGE_SIZE) | ||
| 194 | count = PAGE_SIZE; | ||
| 195 | |||
| 196 | rc = -EFAULT; | ||
| 197 | if (copy_from_user(kbuf, buf, count) != 0) | ||
| 198 | goto out; | ||
| 199 | |||
| 200 | spin_lock_irq(&port_user_lock); | ||
| 201 | for (i = 0; i < (count/sizeof(evtchn_port_t)); i++) | ||
| 202 | if ((kbuf[i] < NR_EVENT_CHANNELS) && (port_user[kbuf[i]] == u)) | ||
| 203 | enable_irq(irq_from_evtchn(kbuf[i])); | ||
| 204 | spin_unlock_irq(&port_user_lock); | ||
| 205 | |||
| 206 | rc = count; | ||
| 207 | |||
| 208 | out: | ||
| 209 | free_page((unsigned long)kbuf); | ||
| 210 | return rc; | ||
| 211 | } | ||
| 212 | |||
| 213 | static int evtchn_bind_to_user(struct per_user_data *u, int port) | ||
| 214 | { | ||
| 215 | int rc = 0; | ||
| 216 | |||
| 217 | /* | ||
| 218 | * Ports are never reused, so every caller should pass in a | ||
| 219 | * unique port. | ||
| 220 | * | ||
| 221 | * (Locking not necessary because we haven't registered the | ||
| 222 | * interrupt handler yet, and our caller has already | ||
| 223 | * serialized bind operations.) | ||
| 224 | */ | ||
| 225 | BUG_ON(port_user[port] != NULL); | ||
| 226 | port_user[port] = u; | ||
| 227 | |||
| 228 | rc = bind_evtchn_to_irqhandler(port, evtchn_interrupt, IRQF_DISABLED, | ||
| 229 | u->name, (void *)(unsigned long)port); | ||
| 230 | if (rc >= 0) | ||
| 231 | rc = 0; | ||
| 232 | |||
| 233 | return rc; | ||
| 234 | } | ||
| 235 | |||
| 236 | static void evtchn_unbind_from_user(struct per_user_data *u, int port) | ||
| 237 | { | ||
| 238 | int irq = irq_from_evtchn(port); | ||
| 239 | |||
| 240 | unbind_from_irqhandler(irq, (void *)(unsigned long)port); | ||
| 241 | |||
| 242 | /* make sure we unbind the irq handler before clearing the port */ | ||
| 243 | barrier(); | ||
| 244 | |||
| 245 | port_user[port] = NULL; | ||
| 246 | } | ||
| 247 | |||
| 248 | static long evtchn_ioctl(struct file *file, | ||
| 249 | unsigned int cmd, unsigned long arg) | ||
| 250 | { | ||
| 251 | int rc; | ||
| 252 | struct per_user_data *u = file->private_data; | ||
| 253 | void __user *uarg = (void __user *) arg; | ||
| 254 | |||
| 255 | /* Prevent bind from racing with unbind */ | ||
| 256 | mutex_lock(&u->bind_mutex); | ||
| 257 | |||
| 258 | switch (cmd) { | ||
| 259 | case IOCTL_EVTCHN_BIND_VIRQ: { | ||
| 260 | struct ioctl_evtchn_bind_virq bind; | ||
| 261 | struct evtchn_bind_virq bind_virq; | ||
| 262 | |||
| 263 | rc = -EFAULT; | ||
| 264 | if (copy_from_user(&bind, uarg, sizeof(bind))) | ||
| 265 | break; | ||
| 266 | |||
| 267 | bind_virq.virq = bind.virq; | ||
| 268 | bind_virq.vcpu = 0; | ||
| 269 | rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_virq, | ||
| 270 | &bind_virq); | ||
| 271 | if (rc != 0) | ||
| 272 | break; | ||
| 273 | |||
| 274 | rc = evtchn_bind_to_user(u, bind_virq.port); | ||
| 275 | if (rc == 0) | ||
| 276 | rc = bind_virq.port; | ||
| 277 | break; | ||
| 278 | } | ||
| 279 | |||
| 280 | case IOCTL_EVTCHN_BIND_INTERDOMAIN: { | ||
| 281 | struct ioctl_evtchn_bind_interdomain bind; | ||
| 282 | struct evtchn_bind_interdomain bind_interdomain; | ||
| 283 | |||
| 284 | rc = -EFAULT; | ||
| 285 | if (copy_from_user(&bind, uarg, sizeof(bind))) | ||
| 286 | break; | ||
| 287 | |||
| 288 | bind_interdomain.remote_dom = bind.remote_domain; | ||
| 289 | bind_interdomain.remote_port = bind.remote_port; | ||
| 290 | rc = HYPERVISOR_event_channel_op(EVTCHNOP_bind_interdomain, | ||
| 291 | &bind_interdomain); | ||
| 292 | if (rc != 0) | ||
| 293 | break; | ||
| 294 | |||
| 295 | rc = evtchn_bind_to_user(u, bind_interdomain.local_port); | ||
| 296 | if (rc == 0) | ||
| 297 | rc = bind_interdomain.local_port; | ||
| 298 | break; | ||
| 299 | } | ||
| 300 | |||
| 301 | case IOCTL_EVTCHN_BIND_UNBOUND_PORT: { | ||
| 302 | struct ioctl_evtchn_bind_unbound_port bind; | ||
| 303 | struct evtchn_alloc_unbound alloc_unbound; | ||
| 304 | |||
| 305 | rc = -EFAULT; | ||
| 306 | if (copy_from_user(&bind, uarg, sizeof(bind))) | ||
| 307 | break; | ||
| 308 | |||
| 309 | alloc_unbound.dom = DOMID_SELF; | ||
| 310 | alloc_unbound.remote_dom = bind.remote_domain; | ||
| 311 | rc = HYPERVISOR_event_channel_op(EVTCHNOP_alloc_unbound, | ||
| 312 | &alloc_unbound); | ||
| 313 | if (rc != 0) | ||
| 314 | break; | ||
| 315 | |||
| 316 | rc = evtchn_bind_to_user(u, alloc_unbound.port); | ||
| 317 | if (rc == 0) | ||
| 318 | rc = alloc_unbound.port; | ||
| 319 | break; | ||
| 320 | } | ||
| 321 | |||
| 322 | case IOCTL_EVTCHN_UNBIND: { | ||
| 323 | struct ioctl_evtchn_unbind unbind; | ||
| 324 | |||
| 325 | rc = -EFAULT; | ||
| 326 | if (copy_from_user(&unbind, uarg, sizeof(unbind))) | ||
| 327 | break; | ||
| 328 | |||
| 329 | rc = -EINVAL; | ||
| 330 | if (unbind.port >= NR_EVENT_CHANNELS) | ||
| 331 | break; | ||
| 332 | |||
| 333 | spin_lock_irq(&port_user_lock); | ||
| 334 | |||
| 335 | rc = -ENOTCONN; | ||
| 336 | if (port_user[unbind.port] != u) { | ||
| 337 | spin_unlock_irq(&port_user_lock); | ||
| 338 | break; | ||
| 339 | } | ||
| 340 | |||
| 341 | evtchn_unbind_from_user(u, unbind.port); | ||
| 342 | |||
| 343 | spin_unlock_irq(&port_user_lock); | ||
| 344 | |||
| 345 | rc = 0; | ||
| 346 | break; | ||
| 347 | } | ||
| 348 | |||
| 349 | case IOCTL_EVTCHN_NOTIFY: { | ||
| 350 | struct ioctl_evtchn_notify notify; | ||
| 351 | |||
| 352 | rc = -EFAULT; | ||
| 353 | if (copy_from_user(¬ify, uarg, sizeof(notify))) | ||
| 354 | break; | ||
| 355 | |||
| 356 | if (notify.port >= NR_EVENT_CHANNELS) { | ||
| 357 | rc = -EINVAL; | ||
| 358 | } else if (port_user[notify.port] != u) { | ||
| 359 | rc = -ENOTCONN; | ||
| 360 | } else { | ||
| 361 | notify_remote_via_evtchn(notify.port); | ||
| 362 | rc = 0; | ||
| 363 | } | ||
| 364 | break; | ||
| 365 | } | ||
| 366 | |||
| 367 | case IOCTL_EVTCHN_RESET: { | ||
| 368 | /* Initialise the ring to empty. Clear errors. */ | ||
| 369 | mutex_lock(&u->ring_cons_mutex); | ||
| 370 | spin_lock_irq(&port_user_lock); | ||
| 371 | u->ring_cons = u->ring_prod = u->ring_overflow = 0; | ||
| 372 | spin_unlock_irq(&port_user_lock); | ||
| 373 | mutex_unlock(&u->ring_cons_mutex); | ||
| 374 | rc = 0; | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | |||
| 378 | default: | ||
| 379 | rc = -ENOSYS; | ||
| 380 | break; | ||
| 381 | } | ||
| 382 | mutex_unlock(&u->bind_mutex); | ||
| 383 | |||
| 384 | return rc; | ||
| 385 | } | ||
| 386 | |||
| 387 | static unsigned int evtchn_poll(struct file *file, poll_table *wait) | ||
| 388 | { | ||
| 389 | unsigned int mask = POLLOUT | POLLWRNORM; | ||
| 390 | struct per_user_data *u = file->private_data; | ||
| 391 | |||
| 392 | poll_wait(file, &u->evtchn_wait, wait); | ||
| 393 | if (u->ring_cons != u->ring_prod) | ||
| 394 | mask |= POLLIN | POLLRDNORM; | ||
| 395 | if (u->ring_overflow) | ||
| 396 | mask = POLLERR; | ||
| 397 | return mask; | ||
| 398 | } | ||
| 399 | |||
| 400 | static int evtchn_fasync(int fd, struct file *filp, int on) | ||
| 401 | { | ||
| 402 | struct per_user_data *u = filp->private_data; | ||
| 403 | return fasync_helper(fd, filp, on, &u->evtchn_async_queue); | ||
| 404 | } | ||
| 405 | |||
| 406 | static int evtchn_open(struct inode *inode, struct file *filp) | ||
| 407 | { | ||
| 408 | struct per_user_data *u; | ||
| 409 | |||
| 410 | u = kzalloc(sizeof(*u), GFP_KERNEL); | ||
| 411 | if (u == NULL) | ||
| 412 | return -ENOMEM; | ||
| 413 | |||
| 414 | u->name = kasprintf(GFP_KERNEL, "evtchn:%s", current->comm); | ||
| 415 | if (u->name == NULL) { | ||
| 416 | kfree(u); | ||
| 417 | return -ENOMEM; | ||
| 418 | } | ||
| 419 | |||
| 420 | init_waitqueue_head(&u->evtchn_wait); | ||
| 421 | |||
| 422 | u->ring = (evtchn_port_t *)__get_free_page(GFP_KERNEL); | ||
| 423 | if (u->ring == NULL) { | ||
| 424 | kfree(u->name); | ||
| 425 | kfree(u); | ||
| 426 | return -ENOMEM; | ||
| 427 | } | ||
| 428 | |||
| 429 | mutex_init(&u->bind_mutex); | ||
| 430 | mutex_init(&u->ring_cons_mutex); | ||
| 431 | |||
| 432 | filp->private_data = u; | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | } | ||
| 436 | |||
| 437 | static int evtchn_release(struct inode *inode, struct file *filp) | ||
| 438 | { | ||
| 439 | int i; | ||
| 440 | struct per_user_data *u = filp->private_data; | ||
| 441 | |||
| 442 | spin_lock_irq(&port_user_lock); | ||
| 443 | |||
| 444 | free_page((unsigned long)u->ring); | ||
| 445 | |||
| 446 | for (i = 0; i < NR_EVENT_CHANNELS; i++) { | ||
| 447 | if (port_user[i] != u) | ||
| 448 | continue; | ||
| 449 | |||
| 450 | evtchn_unbind_from_user(port_user[i], i); | ||
| 451 | } | ||
| 452 | |||
| 453 | spin_unlock_irq(&port_user_lock); | ||
| 454 | |||
| 455 | kfree(u->name); | ||
| 456 | kfree(u); | ||
| 457 | |||
| 458 | return 0; | ||
| 459 | } | ||
| 460 | |||
| 461 | static const struct file_operations evtchn_fops = { | ||
| 462 | .owner = THIS_MODULE, | ||
| 463 | .read = evtchn_read, | ||
| 464 | .write = evtchn_write, | ||
| 465 | .unlocked_ioctl = evtchn_ioctl, | ||
| 466 | .poll = evtchn_poll, | ||
| 467 | .fasync = evtchn_fasync, | ||
| 468 | .open = evtchn_open, | ||
| 469 | .release = evtchn_release, | ||
| 470 | }; | ||
| 471 | |||
| 472 | static struct miscdevice evtchn_miscdev = { | ||
| 473 | .minor = MISC_DYNAMIC_MINOR, | ||
| 474 | .name = "evtchn", | ||
| 475 | .fops = &evtchn_fops, | ||
| 476 | }; | ||
| 477 | static int __init evtchn_init(void) | ||
| 478 | { | ||
| 479 | int err; | ||
| 480 | |||
| 481 | if (!xen_domain()) | ||
| 482 | return -ENODEV; | ||
| 483 | |||
| 484 | spin_lock_init(&port_user_lock); | ||
| 485 | memset(port_user, 0, sizeof(port_user)); | ||
| 486 | |||
| 487 | /* Create '/dev/misc/evtchn'. */ | ||
| 488 | err = misc_register(&evtchn_miscdev); | ||
| 489 | if (err != 0) { | ||
| 490 | printk(KERN_ALERT "Could not register /dev/misc/evtchn\n"); | ||
| 491 | return err; | ||
| 492 | } | ||
| 493 | |||
| 494 | printk(KERN_INFO "Event-channel device installed.\n"); | ||
| 495 | |||
| 496 | return 0; | ||
| 497 | } | ||
| 498 | |||
| 499 | static void __exit evtchn_cleanup(void) | ||
| 500 | { | ||
| 501 | misc_deregister(&evtchn_miscdev); | ||
| 502 | } | ||
| 503 | |||
| 504 | module_init(evtchn_init); | ||
| 505 | module_exit(evtchn_cleanup); | ||
| 506 | |||
| 507 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/xen/manage.c b/drivers/xen/manage.c index 4b5b84837ee1..fddc2025dece 100644 --- a/drivers/xen/manage.c +++ b/drivers/xen/manage.c | |||
| @@ -98,9 +98,8 @@ static void do_suspend(void) | |||
| 98 | goto out; | 98 | goto out; |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | printk("suspending xenbus...\n"); | 101 | printk(KERN_DEBUG "suspending xenstore...\n"); |
| 102 | /* XXX use normal device tree? */ | 102 | xs_suspend(); |
| 103 | xenbus_suspend(); | ||
| 104 | 103 | ||
| 105 | err = device_power_down(PMSG_SUSPEND); | 104 | err = device_power_down(PMSG_SUSPEND); |
| 106 | if (err) { | 105 | if (err) { |
| @@ -116,9 +115,9 @@ static void do_suspend(void) | |||
| 116 | 115 | ||
| 117 | if (!cancelled) { | 116 | if (!cancelled) { |
| 118 | xen_arch_resume(); | 117 | xen_arch_resume(); |
| 119 | xenbus_resume(); | 118 | xs_resume(); |
| 120 | } else | 119 | } else |
| 121 | xenbus_suspend_cancel(); | 120 | xs_suspend_cancel(); |
| 122 | 121 | ||
| 123 | device_power_up(PMSG_RESUME); | 122 | device_power_up(PMSG_RESUME); |
| 124 | 123 | ||
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c new file mode 100644 index 000000000000..88a60e03ccf0 --- /dev/null +++ b/drivers/xen/sys-hypervisor.c | |||
| @@ -0,0 +1,445 @@ | |||
| 1 | /* | ||
| 2 | * copyright (c) 2006 IBM Corporation | ||
| 3 | * Authored by: Mike D. Day <ncmike@us.ibm.com> | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or modify | ||
| 6 | * it under the terms of the GNU General Public License version 2 as | ||
| 7 | * published by the Free Software Foundation. | ||
| 8 | */ | ||
| 9 | |||
| 10 | #include <linux/kernel.h> | ||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/kobject.h> | ||
| 13 | |||
| 14 | #include <asm/xen/hypervisor.h> | ||
| 15 | #include <asm/xen/hypercall.h> | ||
| 16 | |||
| 17 | #include <xen/xenbus.h> | ||
| 18 | #include <xen/interface/xen.h> | ||
| 19 | #include <xen/interface/version.h> | ||
| 20 | |||
| 21 | #define HYPERVISOR_ATTR_RO(_name) \ | ||
| 22 | static struct hyp_sysfs_attr _name##_attr = __ATTR_RO(_name) | ||
| 23 | |||
| 24 | #define HYPERVISOR_ATTR_RW(_name) \ | ||
| 25 | static struct hyp_sysfs_attr _name##_attr = \ | ||
| 26 | __ATTR(_name, 0644, _name##_show, _name##_store) | ||
| 27 | |||
| 28 | struct hyp_sysfs_attr { | ||
| 29 | struct attribute attr; | ||
| 30 | ssize_t (*show)(struct hyp_sysfs_attr *, char *); | ||
| 31 | ssize_t (*store)(struct hyp_sysfs_attr *, const char *, size_t); | ||
| 32 | void *hyp_attr_data; | ||
| 33 | }; | ||
| 34 | |||
| 35 | static ssize_t type_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 36 | { | ||
| 37 | return sprintf(buffer, "xen\n"); | ||
| 38 | } | ||
| 39 | |||
| 40 | HYPERVISOR_ATTR_RO(type); | ||
| 41 | |||
| 42 | static int __init xen_sysfs_type_init(void) | ||
| 43 | { | ||
| 44 | return sysfs_create_file(hypervisor_kobj, &type_attr.attr); | ||
| 45 | } | ||
| 46 | |||
| 47 | static void xen_sysfs_type_destroy(void) | ||
| 48 | { | ||
| 49 | sysfs_remove_file(hypervisor_kobj, &type_attr.attr); | ||
| 50 | } | ||
| 51 | |||
| 52 | /* xen version attributes */ | ||
| 53 | static ssize_t major_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 54 | { | ||
| 55 | int version = HYPERVISOR_xen_version(XENVER_version, NULL); | ||
| 56 | if (version) | ||
| 57 | return sprintf(buffer, "%d\n", version >> 16); | ||
| 58 | return -ENODEV; | ||
| 59 | } | ||
| 60 | |||
| 61 | HYPERVISOR_ATTR_RO(major); | ||
| 62 | |||
| 63 | static ssize_t minor_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 64 | { | ||
| 65 | int version = HYPERVISOR_xen_version(XENVER_version, NULL); | ||
| 66 | if (version) | ||
| 67 | return sprintf(buffer, "%d\n", version & 0xff); | ||
| 68 | return -ENODEV; | ||
| 69 | } | ||
| 70 | |||
| 71 | HYPERVISOR_ATTR_RO(minor); | ||
| 72 | |||
| 73 | static ssize_t extra_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 74 | { | ||
| 75 | int ret = -ENOMEM; | ||
| 76 | char *extra; | ||
| 77 | |||
| 78 | extra = kmalloc(XEN_EXTRAVERSION_LEN, GFP_KERNEL); | ||
| 79 | if (extra) { | ||
| 80 | ret = HYPERVISOR_xen_version(XENVER_extraversion, extra); | ||
| 81 | if (!ret) | ||
| 82 | ret = sprintf(buffer, "%s\n", extra); | ||
| 83 | kfree(extra); | ||
| 84 | } | ||
| 85 | |||
| 86 | return ret; | ||
| 87 | } | ||
| 88 | |||
| 89 | HYPERVISOR_ATTR_RO(extra); | ||
| 90 | |||
| 91 | static struct attribute *version_attrs[] = { | ||
| 92 | &major_attr.attr, | ||
| 93 | &minor_attr.attr, | ||
| 94 | &extra_attr.attr, | ||
| 95 | NULL | ||
| 96 | }; | ||
| 97 | |||
| 98 | static struct attribute_group version_group = { | ||
| 99 | .name = "version", | ||
| 100 | .attrs = version_attrs, | ||
| 101 | }; | ||
| 102 | |||
| 103 | static int __init xen_sysfs_version_init(void) | ||
| 104 | { | ||
| 105 | return sysfs_create_group(hypervisor_kobj, &version_group); | ||
| 106 | } | ||
| 107 | |||
| 108 | static void xen_sysfs_version_destroy(void) | ||
| 109 | { | ||
| 110 | sysfs_remove_group(hypervisor_kobj, &version_group); | ||
| 111 | } | ||
| 112 | |||
| 113 | /* UUID */ | ||
| 114 | |||
| 115 | static ssize_t uuid_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 116 | { | ||
| 117 | char *vm, *val; | ||
| 118 | int ret; | ||
| 119 | extern int xenstored_ready; | ||
| 120 | |||
| 121 | if (!xenstored_ready) | ||
| 122 | return -EBUSY; | ||
| 123 | |||
| 124 | vm = xenbus_read(XBT_NIL, "vm", "", NULL); | ||
| 125 | if (IS_ERR(vm)) | ||
| 126 | return PTR_ERR(vm); | ||
| 127 | val = xenbus_read(XBT_NIL, vm, "uuid", NULL); | ||
| 128 | kfree(vm); | ||
| 129 | if (IS_ERR(val)) | ||
| 130 | return PTR_ERR(val); | ||
| 131 | ret = sprintf(buffer, "%s\n", val); | ||
| 132 | kfree(val); | ||
| 133 | return ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | HYPERVISOR_ATTR_RO(uuid); | ||
| 137 | |||
| 138 | static int __init xen_sysfs_uuid_init(void) | ||
| 139 | { | ||
| 140 | return sysfs_create_file(hypervisor_kobj, &uuid_attr.attr); | ||
| 141 | } | ||
| 142 | |||
| 143 | static void xen_sysfs_uuid_destroy(void) | ||
| 144 | { | ||
| 145 | sysfs_remove_file(hypervisor_kobj, &uuid_attr.attr); | ||
| 146 | } | ||
| 147 | |||
| 148 | /* xen compilation attributes */ | ||
| 149 | |||
| 150 | static ssize_t compiler_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 151 | { | ||
| 152 | int ret = -ENOMEM; | ||
| 153 | struct xen_compile_info *info; | ||
| 154 | |||
| 155 | info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); | ||
| 156 | if (info) { | ||
| 157 | ret = HYPERVISOR_xen_version(XENVER_compile_info, info); | ||
| 158 | if (!ret) | ||
| 159 | ret = sprintf(buffer, "%s\n", info->compiler); | ||
| 160 | kfree(info); | ||
| 161 | } | ||
| 162 | |||
| 163 | return ret; | ||
| 164 | } | ||
| 165 | |||
| 166 | HYPERVISOR_ATTR_RO(compiler); | ||
| 167 | |||
| 168 | static ssize_t compiled_by_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 169 | { | ||
| 170 | int ret = -ENOMEM; | ||
| 171 | struct xen_compile_info *info; | ||
| 172 | |||
| 173 | info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); | ||
| 174 | if (info) { | ||
| 175 | ret = HYPERVISOR_xen_version(XENVER_compile_info, info); | ||
| 176 | if (!ret) | ||
| 177 | ret = sprintf(buffer, "%s\n", info->compile_by); | ||
| 178 | kfree(info); | ||
| 179 | } | ||
| 180 | |||
| 181 | return ret; | ||
| 182 | } | ||
| 183 | |||
| 184 | HYPERVISOR_ATTR_RO(compiled_by); | ||
| 185 | |||
| 186 | static ssize_t compile_date_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 187 | { | ||
| 188 | int ret = -ENOMEM; | ||
| 189 | struct xen_compile_info *info; | ||
| 190 | |||
| 191 | info = kmalloc(sizeof(struct xen_compile_info), GFP_KERNEL); | ||
| 192 | if (info) { | ||
| 193 | ret = HYPERVISOR_xen_version(XENVER_compile_info, info); | ||
| 194 | if (!ret) | ||
| 195 | ret = sprintf(buffer, "%s\n", info->compile_date); | ||
| 196 | kfree(info); | ||
| 197 | } | ||
| 198 | |||
| 199 | return ret; | ||
| 200 | } | ||
| 201 | |||
| 202 | HYPERVISOR_ATTR_RO(compile_date); | ||
| 203 | |||
| 204 | static struct attribute *xen_compile_attrs[] = { | ||
| 205 | &compiler_attr.attr, | ||
| 206 | &compiled_by_attr.attr, | ||
| 207 | &compile_date_attr.attr, | ||
| 208 | NULL | ||
| 209 | }; | ||
| 210 | |||
| 211 | static struct attribute_group xen_compilation_group = { | ||
| 212 | .name = "compilation", | ||
| 213 | .attrs = xen_compile_attrs, | ||
| 214 | }; | ||
| 215 | |||
| 216 | int __init static xen_compilation_init(void) | ||
| 217 | { | ||
| 218 | return sysfs_create_group(hypervisor_kobj, &xen_compilation_group); | ||
| 219 | } | ||
| 220 | |||
| 221 | static void xen_compilation_destroy(void) | ||
| 222 | { | ||
| 223 | sysfs_remove_group(hypervisor_kobj, &xen_compilation_group); | ||
| 224 | } | ||
| 225 | |||
| 226 | /* xen properties info */ | ||
| 227 | |||
| 228 | static ssize_t capabilities_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 229 | { | ||
| 230 | int ret = -ENOMEM; | ||
| 231 | char *caps; | ||
| 232 | |||
| 233 | caps = kmalloc(XEN_CAPABILITIES_INFO_LEN, GFP_KERNEL); | ||
| 234 | if (caps) { | ||
| 235 | ret = HYPERVISOR_xen_version(XENVER_capabilities, caps); | ||
| 236 | if (!ret) | ||
| 237 | ret = sprintf(buffer, "%s\n", caps); | ||
| 238 | kfree(caps); | ||
| 239 | } | ||
| 240 | |||
| 241 | return ret; | ||
| 242 | } | ||
| 243 | |||
| 244 | HYPERVISOR_ATTR_RO(capabilities); | ||
| 245 | |||
| 246 | static ssize_t changeset_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 247 | { | ||
| 248 | int ret = -ENOMEM; | ||
| 249 | char *cset; | ||
| 250 | |||
| 251 | cset = kmalloc(XEN_CHANGESET_INFO_LEN, GFP_KERNEL); | ||
| 252 | if (cset) { | ||
| 253 | ret = HYPERVISOR_xen_version(XENVER_changeset, cset); | ||
| 254 | if (!ret) | ||
| 255 | ret = sprintf(buffer, "%s\n", cset); | ||
| 256 | kfree(cset); | ||
| 257 | } | ||
| 258 | |||
| 259 | return ret; | ||
| 260 | } | ||
| 261 | |||
| 262 | HYPERVISOR_ATTR_RO(changeset); | ||
| 263 | |||
| 264 | static ssize_t virtual_start_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 265 | { | ||
| 266 | int ret = -ENOMEM; | ||
| 267 | struct xen_platform_parameters *parms; | ||
| 268 | |||
| 269 | parms = kmalloc(sizeof(struct xen_platform_parameters), GFP_KERNEL); | ||
| 270 | if (parms) { | ||
| 271 | ret = HYPERVISOR_xen_version(XENVER_platform_parameters, | ||
| 272 | parms); | ||
| 273 | if (!ret) | ||
| 274 | ret = sprintf(buffer, "%lx\n", parms->virt_start); | ||
| 275 | kfree(parms); | ||
| 276 | } | ||
| 277 | |||
| 278 | return ret; | ||
| 279 | } | ||
| 280 | |||
| 281 | HYPERVISOR_ATTR_RO(virtual_start); | ||
| 282 | |||
| 283 | static ssize_t pagesize_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 284 | { | ||
| 285 | int ret; | ||
| 286 | |||
| 287 | ret = HYPERVISOR_xen_version(XENVER_pagesize, NULL); | ||
| 288 | if (ret > 0) | ||
| 289 | ret = sprintf(buffer, "%x\n", ret); | ||
| 290 | |||
| 291 | return ret; | ||
| 292 | } | ||
| 293 | |||
| 294 | HYPERVISOR_ATTR_RO(pagesize); | ||
| 295 | |||
| 296 | static ssize_t xen_feature_show(int index, char *buffer) | ||
| 297 | { | ||
| 298 | ssize_t ret; | ||
| 299 | struct xen_feature_info info; | ||
| 300 | |||
| 301 | info.submap_idx = index; | ||
| 302 | ret = HYPERVISOR_xen_version(XENVER_get_features, &info); | ||
| 303 | if (!ret) | ||
| 304 | ret = sprintf(buffer, "%08x", info.submap); | ||
| 305 | |||
| 306 | return ret; | ||
| 307 | } | ||
| 308 | |||
| 309 | static ssize_t features_show(struct hyp_sysfs_attr *attr, char *buffer) | ||
| 310 | { | ||
| 311 | ssize_t len; | ||
| 312 | int i; | ||
| 313 | |||
| 314 | len = 0; | ||
| 315 | for (i = XENFEAT_NR_SUBMAPS-1; i >= 0; i--) { | ||
| 316 | int ret = xen_feature_show(i, buffer + len); | ||
| 317 | if (ret < 0) { | ||
| 318 | if (len == 0) | ||
| 319 | len = ret; | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | len += ret; | ||
| 323 | } | ||
| 324 | if (len > 0) | ||
| 325 | buffer[len++] = '\n'; | ||
| 326 | |||
| 327 | return len; | ||
| 328 | } | ||
| 329 | |||
| 330 | HYPERVISOR_ATTR_RO(features); | ||
| 331 | |||
| 332 | static struct attribute *xen_properties_attrs[] = { | ||
| 333 | &capabilities_attr.attr, | ||
| 334 | &changeset_attr.attr, | ||
| 335 | &virtual_start_attr.attr, | ||
| 336 | &pagesize_attr.attr, | ||
| 337 | &features_attr.attr, | ||
| 338 | NULL | ||
| 339 | }; | ||
| 340 | |||
| 341 | static struct attribute_group xen_properties_group = { | ||
| 342 | .name = "properties", | ||
| 343 | .attrs = xen_properties_attrs, | ||
| 344 | }; | ||
| 345 | |||
| 346 | static int __init xen_properties_init(void) | ||
| 347 | { | ||
| 348 | return sysfs_create_group(hypervisor_kobj, &xen_properties_group); | ||
| 349 | } | ||
| 350 | |||
| 351 | static void xen_properties_destroy(void) | ||
| 352 | { | ||
| 353 | sysfs_remove_group(hypervisor_kobj, &xen_properties_group); | ||
| 354 | } | ||
| 355 | |||
| 356 | static int __init hyper_sysfs_init(void) | ||
| 357 | { | ||
| 358 | int ret; | ||
| 359 | |||
| 360 | if (!xen_domain()) | ||
| 361 | return -ENODEV; | ||
| 362 | |||
| 363 | ret = xen_sysfs_type_init(); | ||
| 364 | if (ret) | ||
| 365 | goto out; | ||
| 366 | ret = xen_sysfs_version_init(); | ||
| 367 | if (ret) | ||
| 368 | goto version_out; | ||
| 369 | ret = xen_compilation_init(); | ||
| 370 | if (ret) | ||
| 371 | goto comp_out; | ||
| 372 | ret = xen_sysfs_uuid_init(); | ||
| 373 | if (ret) | ||
| 374 | goto uuid_out; | ||
| 375 | ret = xen_properties_init(); | ||
| 376 | if (ret) | ||
| 377 | goto prop_out; | ||
| 378 | |||
| 379 | goto out; | ||
| 380 | |||
| 381 | prop_out: | ||
| 382 | xen_sysfs_uuid_destroy(); | ||
| 383 | uuid_out: | ||
| 384 | xen_compilation_destroy(); | ||
| 385 | comp_out: | ||
| 386 | xen_sysfs_version_destroy(); | ||
| 387 | version_out: | ||
| 388 | xen_sysfs_type_destroy(); | ||
| 389 | out: | ||
| 390 | return ret; | ||
| 391 | } | ||
| 392 | |||
| 393 | static void __exit hyper_sysfs_exit(void) | ||
| 394 | { | ||
| 395 | xen_properties_destroy(); | ||
| 396 | xen_compilation_destroy(); | ||
| 397 | xen_sysfs_uuid_destroy(); | ||
| 398 | xen_sysfs_version_destroy(); | ||
| 399 | xen_sysfs_type_destroy(); | ||
| 400 | |||
| 401 | } | ||
| 402 | module_init(hyper_sysfs_init); | ||
| 403 | module_exit(hyper_sysfs_exit); | ||
| 404 | |||
| 405 | static ssize_t hyp_sysfs_show(struct kobject *kobj, | ||
| 406 | struct attribute *attr, | ||
| 407 | char *buffer) | ||
| 408 | { | ||
| 409 | struct hyp_sysfs_attr *hyp_attr; | ||
| 410 | hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); | ||
| 411 | if (hyp_attr->show) | ||
| 412 | return hyp_attr->show(hyp_attr, buffer); | ||
| 413 | return 0; | ||
| 414 | } | ||
| 415 | |||
| 416 | static ssize_t hyp_sysfs_store(struct kobject *kobj, | ||
| 417 | struct attribute *attr, | ||
| 418 | const char *buffer, | ||
| 419 | size_t len) | ||
| 420 | { | ||
| 421 | struct hyp_sysfs_attr *hyp_attr; | ||
| 422 | hyp_attr = container_of(attr, struct hyp_sysfs_attr, attr); | ||
| 423 | if (hyp_attr->store) | ||
| 424 | return hyp_attr->store(hyp_attr, buffer, len); | ||
| 425 | return 0; | ||
| 426 | } | ||
| 427 | |||
| 428 | static struct sysfs_ops hyp_sysfs_ops = { | ||
| 429 | .show = hyp_sysfs_show, | ||
| 430 | .store = hyp_sysfs_store, | ||
| 431 | }; | ||
| 432 | |||
| 433 | static struct kobj_type hyp_sysfs_kobj_type = { | ||
| 434 | .sysfs_ops = &hyp_sysfs_ops, | ||
| 435 | }; | ||
| 436 | |||
| 437 | static int __init hypervisor_subsys_init(void) | ||
| 438 | { | ||
| 439 | if (!xen_domain()) | ||
| 440 | return -ENODEV; | ||
| 441 | |||
| 442 | hypervisor_kobj->ktype = &hyp_sysfs_kobj_type; | ||
| 443 | return 0; | ||
| 444 | } | ||
| 445 | device_initcall(hypervisor_subsys_init); | ||
diff --git a/drivers/xen/xenbus/xenbus_probe.c b/drivers/xen/xenbus/xenbus_probe.c index 773d1cf23283..d42e25d5968d 100644 --- a/drivers/xen/xenbus/xenbus_probe.c +++ b/drivers/xen/xenbus/xenbus_probe.c | |||
| @@ -71,6 +71,9 @@ static int xenbus_probe_frontend(const char *type, const char *name); | |||
| 71 | 71 | ||
| 72 | static void xenbus_dev_shutdown(struct device *_dev); | 72 | static void xenbus_dev_shutdown(struct device *_dev); |
| 73 | 73 | ||
| 74 | static int xenbus_dev_suspend(struct device *dev, pm_message_t state); | ||
| 75 | static int xenbus_dev_resume(struct device *dev); | ||
| 76 | |||
| 74 | /* If something in array of ids matches this device, return it. */ | 77 | /* If something in array of ids matches this device, return it. */ |
| 75 | static const struct xenbus_device_id * | 78 | static const struct xenbus_device_id * |
| 76 | match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) | 79 | match_device(const struct xenbus_device_id *arr, struct xenbus_device *dev) |
| @@ -188,6 +191,9 @@ static struct xen_bus_type xenbus_frontend = { | |||
| 188 | .remove = xenbus_dev_remove, | 191 | .remove = xenbus_dev_remove, |
| 189 | .shutdown = xenbus_dev_shutdown, | 192 | .shutdown = xenbus_dev_shutdown, |
| 190 | .dev_attrs = xenbus_dev_attrs, | 193 | .dev_attrs = xenbus_dev_attrs, |
| 194 | |||
| 195 | .suspend = xenbus_dev_suspend, | ||
| 196 | .resume = xenbus_dev_resume, | ||
| 191 | }, | 197 | }, |
| 192 | }; | 198 | }; |
| 193 | 199 | ||
| @@ -654,6 +660,7 @@ void xenbus_dev_changed(const char *node, struct xen_bus_type *bus) | |||
| 654 | 660 | ||
| 655 | kfree(root); | 661 | kfree(root); |
| 656 | } | 662 | } |
| 663 | EXPORT_SYMBOL_GPL(xenbus_dev_changed); | ||
| 657 | 664 | ||
| 658 | static void frontend_changed(struct xenbus_watch *watch, | 665 | static void frontend_changed(struct xenbus_watch *watch, |
| 659 | const char **vec, unsigned int len) | 666 | const char **vec, unsigned int len) |
| @@ -669,7 +676,7 @@ static struct xenbus_watch fe_watch = { | |||
| 669 | .callback = frontend_changed, | 676 | .callback = frontend_changed, |
| 670 | }; | 677 | }; |
| 671 | 678 | ||
| 672 | static int suspend_dev(struct device *dev, void *data) | 679 | static int xenbus_dev_suspend(struct device *dev, pm_message_t state) |
| 673 | { | 680 | { |
| 674 | int err = 0; | 681 | int err = 0; |
| 675 | struct xenbus_driver *drv; | 682 | struct xenbus_driver *drv; |
| @@ -682,35 +689,14 @@ static int suspend_dev(struct device *dev, void *data) | |||
| 682 | drv = to_xenbus_driver(dev->driver); | 689 | drv = to_xenbus_driver(dev->driver); |
| 683 | xdev = container_of(dev, struct xenbus_device, dev); | 690 | xdev = container_of(dev, struct xenbus_device, dev); |
| 684 | if (drv->suspend) | 691 | if (drv->suspend) |
| 685 | err = drv->suspend(xdev); | 692 | err = drv->suspend(xdev, state); |
| 686 | if (err) | 693 | if (err) |
| 687 | printk(KERN_WARNING | 694 | printk(KERN_WARNING |
| 688 | "xenbus: suspend %s failed: %i\n", dev_name(dev), err); | 695 | "xenbus: suspend %s failed: %i\n", dev_name(dev), err); |
| 689 | return 0; | 696 | return 0; |
| 690 | } | 697 | } |
| 691 | 698 | ||
| 692 | static int suspend_cancel_dev(struct device *dev, void *data) | 699 | static int xenbus_dev_resume(struct device *dev) |
| 693 | { | ||
| 694 | int err = 0; | ||
| 695 | struct xenbus_driver *drv; | ||
| 696 | struct xenbus_device *xdev; | ||
| 697 | |||
| 698 | DPRINTK(""); | ||
| 699 | |||
| 700 | if (dev->driver == NULL) | ||
| 701 | return 0; | ||
| 702 | drv = to_xenbus_driver(dev->driver); | ||
| 703 | xdev = container_of(dev, struct xenbus_device, dev); | ||
| 704 | if (drv->suspend_cancel) | ||
| 705 | err = drv->suspend_cancel(xdev); | ||
| 706 | if (err) | ||
| 707 | printk(KERN_WARNING | ||
| 708 | "xenbus: suspend_cancel %s failed: %i\n", | ||
| 709 | dev_name(dev), err); | ||
| 710 | return 0; | ||
| 711 | } | ||
| 712 | |||
| 713 | static int resume_dev(struct device *dev, void *data) | ||
| 714 | { | 700 | { |
| 715 | int err; | 701 | int err; |
| 716 | struct xenbus_driver *drv; | 702 | struct xenbus_driver *drv; |
| @@ -755,33 +741,6 @@ static int resume_dev(struct device *dev, void *data) | |||
| 755 | return 0; | 741 | return 0; |
| 756 | } | 742 | } |
| 757 | 743 | ||
| 758 | void xenbus_suspend(void) | ||
| 759 | { | ||
| 760 | DPRINTK(""); | ||
| 761 | |||
| 762 | bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_dev); | ||
| 763 | xenbus_backend_suspend(suspend_dev); | ||
| 764 | xs_suspend(); | ||
| 765 | } | ||
| 766 | EXPORT_SYMBOL_GPL(xenbus_suspend); | ||
| 767 | |||
| 768 | void xenbus_resume(void) | ||
| 769 | { | ||
| 770 | xb_init_comms(); | ||
| 771 | xs_resume(); | ||
| 772 | bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, resume_dev); | ||
| 773 | xenbus_backend_resume(resume_dev); | ||
| 774 | } | ||
| 775 | EXPORT_SYMBOL_GPL(xenbus_resume); | ||
| 776 | |||
| 777 | void xenbus_suspend_cancel(void) | ||
| 778 | { | ||
| 779 | xs_suspend_cancel(); | ||
| 780 | bus_for_each_dev(&xenbus_frontend.bus, NULL, NULL, suspend_cancel_dev); | ||
| 781 | xenbus_backend_resume(suspend_cancel_dev); | ||
| 782 | } | ||
| 783 | EXPORT_SYMBOL_GPL(xenbus_suspend_cancel); | ||
| 784 | |||
| 785 | /* A flag to determine if xenstored is 'ready' (i.e. has started) */ | 744 | /* A flag to determine if xenstored is 'ready' (i.e. has started) */ |
| 786 | int xenstored_ready = 0; | 745 | int xenstored_ready = 0; |
| 787 | 746 | ||
diff --git a/drivers/xen/xenbus/xenbus_xs.c b/drivers/xen/xenbus/xenbus_xs.c index e325eab4724d..eab33f1dbdf7 100644 --- a/drivers/xen/xenbus/xenbus_xs.c +++ b/drivers/xen/xenbus/xenbus_xs.c | |||
| @@ -673,6 +673,8 @@ void xs_resume(void) | |||
| 673 | struct xenbus_watch *watch; | 673 | struct xenbus_watch *watch; |
| 674 | char token[sizeof(watch) * 2 + 1]; | 674 | char token[sizeof(watch) * 2 + 1]; |
| 675 | 675 | ||
| 676 | xb_init_comms(); | ||
| 677 | |||
| 676 | mutex_unlock(&xs_state.response_mutex); | 678 | mutex_unlock(&xs_state.response_mutex); |
| 677 | mutex_unlock(&xs_state.request_mutex); | 679 | mutex_unlock(&xs_state.request_mutex); |
| 678 | up_write(&xs_state.transaction_mutex); | 680 | up_write(&xs_state.transaction_mutex); |
diff --git a/drivers/xen/xenfs/super.c b/drivers/xen/xenfs/super.c index 515741a8e6b8..6559e0c752ce 100644 --- a/drivers/xen/xenfs/super.c +++ b/drivers/xen/xenfs/super.c | |||
| @@ -20,10 +20,27 @@ | |||
| 20 | MODULE_DESCRIPTION("Xen filesystem"); | 20 | MODULE_DESCRIPTION("Xen filesystem"); |
| 21 | MODULE_LICENSE("GPL"); | 21 | MODULE_LICENSE("GPL"); |
| 22 | 22 | ||
| 23 | static ssize_t capabilities_read(struct file *file, char __user *buf, | ||
| 24 | size_t size, loff_t *off) | ||
| 25 | { | ||
| 26 | char *tmp = ""; | ||
| 27 | |||
| 28 | if (xen_initial_domain()) | ||
| 29 | tmp = "control_d\n"; | ||
| 30 | |||
| 31 | return simple_read_from_buffer(buf, size, off, tmp, strlen(tmp)); | ||
| 32 | } | ||
| 33 | |||
| 34 | static const struct file_operations capabilities_file_ops = { | ||
| 35 | .read = capabilities_read, | ||
| 36 | }; | ||
| 37 | |||
| 23 | static int xenfs_fill_super(struct super_block *sb, void *data, int silent) | 38 | static int xenfs_fill_super(struct super_block *sb, void *data, int silent) |
| 24 | { | 39 | { |
| 25 | static struct tree_descr xenfs_files[] = { | 40 | static struct tree_descr xenfs_files[] = { |
| 26 | [2] = {"xenbus", &xenbus_file_ops, S_IRUSR|S_IWUSR}, | 41 | [1] = {}, |
| 42 | { "xenbus", &xenbus_file_ops, S_IRUSR|S_IWUSR }, | ||
| 43 | { "capabilities", &capabilities_file_ops, S_IRUGO }, | ||
| 27 | {""}, | 44 | {""}, |
| 28 | }; | 45 | }; |
| 29 | 46 | ||
