diff --git a/[refs] b/[refs] index 3fe3c96141f7..b77f45af5f40 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 437105f2a7f23899fd647e7ada683ba8dacf11ba +refs/heads/master: a186b4a6b22fdc96a1ed63da483d267b5d00839e diff --git a/trunk/arch/ia64/Makefile b/trunk/arch/ia64/Makefile index b916ccfdef84..34951aa2370b 100644 --- a/trunk/arch/ia64/Makefile +++ b/trunk/arch/ia64/Makefile @@ -77,7 +77,7 @@ vmlinux.gz: vmlinux $(Q)$(MAKE) $(build)=$(boot) $@ unwcheck: vmlinux - -$(Q)READELF=$(READELF) python $(srctree)/arch/ia64/scripts/unwcheck.py $< + -$(Q)READELF=$(READELF) $(srctree)/arch/ia64/scripts/unwcheck.py $< archclean: $(Q)$(MAKE) $(clean)=$(boot) diff --git a/trunk/arch/ia64/hp/sim/boot/Makefile b/trunk/arch/ia64/hp/sim/boot/Makefile index 2e805e0cc560..df6e9968c845 100644 --- a/trunk/arch/ia64/hp/sim/boot/Makefile +++ b/trunk/arch/ia64/hp/sim/boot/Makefile @@ -33,5 +33,5 @@ $(obj)/vmlinux.bin: vmlinux FORCE LDFLAGS_bootloader = -static -T $(obj)/bootloader: $(src)/bootloader.lds $(obj)/bootloader.o $(obj)/boot_head.o $(obj)/fw-emu.o \ - lib/lib.a arch/ia64/lib/built-in.o arch/ia64/lib/lib.a FORCE + lib/lib.a arch/ia64/lib/lib.a FORCE $(call if_changed,ld) diff --git a/trunk/arch/ia64/hp/sim/boot/bootloader.lds b/trunk/arch/ia64/hp/sim/boot/bootloader.lds index 3977f25a1265..69ae58531033 100644 --- a/trunk/arch/ia64/hp/sim/boot/bootloader.lds +++ b/trunk/arch/ia64/hp/sim/boot/bootloader.lds @@ -22,11 +22,10 @@ SECTIONS .sdata : { *(.sdata) } _edata = .; - __bss_start = .; + _bss = .; .sbss : { *(.sbss) *(.scommon) } .bss : { *(.bss) *(COMMON) } . = ALIGN(64 / 8); - __bss_stop = .; _end = . ; /* Stabs debugging sections. */ diff --git a/trunk/arch/ia64/kernel/acpi.c b/trunk/arch/ia64/kernel/acpi.c index 00b5d08f6da8..897e2083a3b1 100644 --- a/trunk/arch/ia64/kernel/acpi.c +++ b/trunk/arch/ia64/kernel/acpi.c @@ -860,7 +860,7 @@ int acpi_map_lsapic(acpi_handle handle, int *pcpu) lsapic = (struct acpi_madt_local_sapic *)obj->buffer.pointer; if ((lsapic->header.type != ACPI_MADT_TYPE_LOCAL_SAPIC) || - (!(lsapic->lapic_flags & ACPI_MADT_ENABLED))) { + (!lsapic->lapic_flags & ACPI_MADT_ENABLED)) { kfree(buffer.pointer); return -EINVAL; } diff --git a/trunk/arch/ia64/kernel/efi.c b/trunk/arch/ia64/kernel/efi.c index 242d79341120..8e8f8b6193ee 100644 --- a/trunk/arch/ia64/kernel/efi.c +++ b/trunk/arch/ia64/kernel/efi.c @@ -370,7 +370,7 @@ efi_get_pal_addr (void) continue; } - if (efi_md_size(md) > IA64_GRANULE_SIZE) + if (md->num_pages << EFI_PAGE_SHIFT > IA64_GRANULE_SIZE) panic("Woah! PAL code size bigger than a granule!"); #if EFI_DEBUG @@ -378,7 +378,7 @@ efi_get_pal_addr (void) printk(KERN_INFO "CPU %d: mapping PAL code [0x%lx-0x%lx) into [0x%lx-0x%lx)\n", smp_processor_id(), md->phys_addr, - md->phys_addr + efi_md_size(md), + md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), vaddr & mask, (vaddr & mask) + IA64_GRANULE_SIZE); #endif return __va(md->phys_addr); @@ -523,7 +523,7 @@ efi_init (void) md = p; printk("mem%02u: type=%u, attr=0x%lx, range=[0x%016lx-0x%016lx) (%luMB)\n", i, md->type, md->attribute, md->phys_addr, - md->phys_addr + efi_md_size(md), + md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT), md->num_pages >> (20 - EFI_PAGE_SHIFT)); } } @@ -656,7 +656,7 @@ efi_memory_descriptor (unsigned long phys_addr) for (p = efi_map_start; p < efi_map_end; p += efi_desc_size) { md = p; - if (phys_addr - md->phys_addr < efi_md_size(md)) + if (phys_addr - md->phys_addr < (md->num_pages << EFI_PAGE_SHIFT)) return md; } return NULL; @@ -1158,7 +1158,7 @@ efi_initialize_iomem_resources(struct resource *code_resource, res->name = name; res->start = md->phys_addr; - res->end = md->phys_addr + efi_md_size(md) - 1; + res->end = md->phys_addr + (md->num_pages << EFI_PAGE_SHIFT) - 1; res->flags = flags; if (insert_resource(&iomem_resource, res) < 0) diff --git a/trunk/arch/ia64/kernel/gate.lds.S b/trunk/arch/ia64/kernel/gate.lds.S index 3cb1abc00e24..454d7a7dfa9d 100644 --- a/trunk/arch/ia64/kernel/gate.lds.S +++ b/trunk/arch/ia64/kernel/gate.lds.S @@ -30,7 +30,7 @@ SECTIONS * the dynamic symbol table et al. If this amount is insufficient, * ld -shared will barf. Just increase it here. */ - . = GATE_ADDR + 0x600; + . = GATE_ADDR + 0x500; .data.patch : { __start_gate_mckinley_e9_patchlist = .; diff --git a/trunk/arch/ia64/kernel/ia64_ksyms.c b/trunk/arch/ia64/kernel/ia64_ksyms.c index c3b4412ccc67..bd17190bebb6 100644 --- a/trunk/arch/ia64/kernel/ia64_ksyms.c +++ b/trunk/arch/ia64/kernel/ia64_ksyms.c @@ -63,9 +63,6 @@ EXPORT_SYMBOL(__udivdi3); EXPORT_SYMBOL(__moddi3); EXPORT_SYMBOL(__umoddi3); -#include -EXPORT_SYMBOL(copy_page); - #if defined(CONFIG_MD_RAID456) || defined(CONFIG_MD_RAID456_MODULE) extern void xor_ia64_2(void); extern void xor_ia64_3(void); diff --git a/trunk/arch/ia64/kernel/iosapic.c b/trunk/arch/ia64/kernel/iosapic.c index 398e2fd1cd25..274a59383043 100644 --- a/trunk/arch/ia64/kernel/iosapic.c +++ b/trunk/arch/ia64/kernel/iosapic.c @@ -199,6 +199,19 @@ static inline int __gsi_to_irq(unsigned int gsi) return -1; } +/* + * Translate GSI number to the corresponding IA-64 interrupt vector. If no + * entry exists, return -1. + */ +inline int +gsi_to_vector (unsigned int gsi) +{ + int irq = __gsi_to_irq(gsi); + if (check_irq_used(irq) < 0) + return -1; + return irq_to_vector(irq); +} + int gsi_to_irq (unsigned int gsi) { @@ -416,7 +429,7 @@ iosapic_end_level_irq (unsigned int irq) #define iosapic_disable_level_irq mask_irq #define iosapic_ack_level_irq nop -static struct irq_chip irq_type_iosapic_level = { +struct irq_chip irq_type_iosapic_level = { .name = "IO-SAPIC-level", .startup = iosapic_startup_level_irq, .shutdown = iosapic_shutdown_level_irq, @@ -465,7 +478,7 @@ iosapic_ack_edge_irq (unsigned int irq) #define iosapic_disable_edge_irq nop #define iosapic_end_edge_irq nop -static struct irq_chip irq_type_iosapic_edge = { +struct irq_chip irq_type_iosapic_edge = { .name = "IO-SAPIC-edge", .startup = iosapic_startup_edge_irq, .shutdown = iosapic_disable_edge_irq, @@ -478,7 +491,7 @@ static struct irq_chip irq_type_iosapic_edge = { .set_affinity = iosapic_set_affinity }; -static unsigned int +unsigned int iosapic_version (char __iomem *addr) { /* @@ -925,7 +938,7 @@ iosapic_register_platform_intr (u32 int_type, unsigned int gsi, case ACPI_INTERRUPT_CPEI: irq = vector = IA64_CPE_VECTOR; BUG_ON(bind_irq_vector(irq, vector, CPU_MASK_ALL)); - delivery = IOSAPIC_FIXED; + delivery = IOSAPIC_LOWEST_PRIORITY; mask = 1; break; default: diff --git a/trunk/arch/ia64/kernel/kprobes.c b/trunk/arch/ia64/kernel/kprobes.c index fc4d2676264f..5fd65d8302c8 100644 --- a/trunk/arch/ia64/kernel/kprobes.c +++ b/trunk/arch/ia64/kernel/kprobes.c @@ -182,8 +182,8 @@ static int __kprobes unsupported_inst(uint template, uint slot, qp = kprobe_inst & 0x3f; if (is_cmp_ctype_unc_inst(template, slot, major_opcode, kprobe_inst)) { if (slot == 1 && qp) { - printk(KERN_WARNING "Kprobes on cmp unc " - "instruction on slot 1 at <0x%lx> " + printk(KERN_WARNING "Kprobes on cmp unc" + "instruction on slot 1 at <0x%lx>" "is not supported\n", addr); return -EINVAL; @@ -221,8 +221,8 @@ static int __kprobes unsupported_inst(uint template, uint slot, * bit 12 to be equal to 1 */ if (slot == 1 && qp) { - printk(KERN_WARNING "Kprobes on test bit " - "instruction on slot at <0x%lx> " + printk(KERN_WARNING "Kprobes on test bit" + "instruction on slot at <0x%lx>" "is not supported\n", addr); return -EINVAL; } @@ -242,7 +242,7 @@ static int __kprobes unsupported_inst(uint template, uint slot, */ int x6=(kprobe_inst >> 27) & 0x3F; if ((x6 == 0x10) || (x6 == 0x11)) { - printk(KERN_WARNING "Kprobes on " + printk(KERN_WARNING "Kprobes on" "Indirect Predict is not supported\n"); return -EINVAL; } @@ -430,23 +430,6 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) * real return address, and all the rest will point to * kretprobe_trampoline */ - hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { - if (ri->task != current) - /* another task is sharing our hash bucket */ - continue; - - orig_ret_address = (unsigned long)ri->ret_addr; - if (orig_ret_address != trampoline_address) - /* - * This is the real return address. Any other - * instances associated with this task are for - * other calls deeper on the call stack - */ - break; - } - - regs->cr_iip = orig_ret_address; - hlist_for_each_entry_safe(ri, node, tmp, head, hlist) { if (ri->task != current) /* another task is sharing our hash bucket */ @@ -469,6 +452,8 @@ int __kprobes trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs) kretprobe_assert(ri, orig_ret_address, trampoline_address); + regs->cr_iip = orig_ret_address; + reset_current_kprobe(); spin_unlock_irqrestore(&kretprobe_lock, flags); preempt_enable_no_resched(); diff --git a/trunk/arch/ia64/kernel/setup.c b/trunk/arch/ia64/kernel/setup.c index 4ac2b1f1bd3b..2b3751eef5ce 100644 --- a/trunk/arch/ia64/kernel/setup.c +++ b/trunk/arch/ia64/kernel/setup.c @@ -95,6 +95,7 @@ static struct resource bss_resource = { .name = "Kernel bss", .flags = IORESOURCE_BUSY | IORESOURCE_MEM }; +extern char _text[], _end[], _etext[], _edata[], _bss[]; unsigned long ia64_max_cacheline_size; @@ -205,7 +206,7 @@ static int __init register_memory(void) code_resource.end = ia64_tpa(_etext) - 1; data_resource.start = ia64_tpa(_etext); data_resource.end = ia64_tpa(_edata) - 1; - bss_resource.start = ia64_tpa(__bss_start); + bss_resource.start = ia64_tpa(_bss); bss_resource.end = ia64_tpa(_end) - 1; efi_initialize_iomem_resources(&code_resource, &data_resource, &bss_resource); diff --git a/trunk/arch/ia64/kernel/signal.c b/trunk/arch/ia64/kernel/signal.c index 4c730099d58f..cdb64cc4d9c8 100644 --- a/trunk/arch/ia64/kernel/signal.c +++ b/trunk/arch/ia64/kernel/signal.c @@ -98,7 +98,7 @@ restore_sigcontext (struct sigcontext __user *sc, struct sigscratch *scr) if ((flags & IA64_SC_FLAG_FPH_VALID) != 0) { struct ia64_psr *psr = ia64_psr(&scr->pt); - err |= __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16); + __copy_from_user(current->thread.fph, &sc->sc_fr[32], 96*16); psr->mfh = 0; /* drop signal handler's fph contents... */ preempt_disable(); if (psr->dfh) @@ -244,7 +244,7 @@ static long setup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratch *scr) { unsigned long flags = 0, ifs, cfm, nat; - long err = 0; + long err; ifs = scr->pt.cr_ifs; @@ -257,12 +257,12 @@ setup_sigcontext (struct sigcontext __user *sc, sigset_t *mask, struct sigscratc ia64_flush_fph(current); if ((current->thread.flags & IA64_THREAD_FPH_VALID)) { flags |= IA64_SC_FLAG_FPH_VALID; - err = __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16); + __copy_to_user(&sc->sc_fr[32], current->thread.fph, 96*16); } nat = ia64_get_scratch_nat_bits(&scr->pt, scr->scratch_unat); - err |= __put_user(flags, &sc->sc_flags); + err = __put_user(flags, &sc->sc_flags); err |= __put_user(nat, &sc->sc_nat); err |= PUT_SIGSET(mask, &sc->sc_mask); err |= __put_user(cfm, &sc->sc_cfm); diff --git a/trunk/arch/ia64/kernel/vmlinux.lds.S b/trunk/arch/ia64/kernel/vmlinux.lds.S index 757e419ebcf8..00232b4357ba 100644 --- a/trunk/arch/ia64/kernel/vmlinux.lds.S +++ b/trunk/arch/ia64/kernel/vmlinux.lds.S @@ -240,12 +240,11 @@ SECTIONS .sdata : AT(ADDR(.sdata) - LOAD_OFFSET) { *(.sdata) *(.sdata1) *(.srdata) } _edata = .; - __bss_start = .; + _bss = .; .sbss : AT(ADDR(.sbss) - LOAD_OFFSET) { *(.sbss) *(.scommon) } .bss : AT(ADDR(.bss) - LOAD_OFFSET) { *(.bss) *(COMMON) } - __bss_stop = .; _end = .; diff --git a/trunk/arch/ia64/lib/Makefile b/trunk/arch/ia64/lib/Makefile index 98771e2a78af..46edf8444c7e 100644 --- a/trunk/arch/ia64/lib/Makefile +++ b/trunk/arch/ia64/lib/Makefile @@ -11,8 +11,8 @@ lib-y := __divsi3.o __udivsi3.o __modsi3.o __umodsi3.o \ flush.o ip_fast_csum.o do_csum.o \ memset.o strlen.o xor.o -obj-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o -obj-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o +lib-$(CONFIG_ITANIUM) += copy_page.o copy_user.o memcpy.o +lib-$(CONFIG_MCKINLEY) += copy_page_mck.o memcpy_mck.o lib-$(CONFIG_PERFMON) += carta_random.o AFLAGS___divdi3.o = diff --git a/trunk/arch/ia64/mm/tlb.c b/trunk/arch/ia64/mm/tlb.c index cef164729db7..1682fc639038 100644 --- a/trunk/arch/ia64/mm/tlb.c +++ b/trunk/arch/ia64/mm/tlb.c @@ -180,7 +180,7 @@ ia64_tlb_init (void) long status; if ((status = ia64_pal_vm_page_size(&tr_pgbits, &purge.mask)) != 0) { - printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld; " + printk(KERN_ERR "PAL_VM_PAGE_SIZE failed with status=%ld;" "defaulting to architected purge page-sizes.\n", status); purge.mask = 0x115557000UL; } diff --git a/trunk/arch/ia64/scripts/unwcheck.py b/trunk/arch/ia64/scripts/unwcheck.py old mode 100644 new mode 100755 diff --git a/trunk/arch/ia64/sn/kernel/io_common.c b/trunk/arch/ia64/sn/kernel/io_common.c index c4eb84f9e781..4594770e685a 100644 --- a/trunk/arch/ia64/sn/kernel/io_common.c +++ b/trunk/arch/ia64/sn/kernel/io_common.c @@ -347,7 +347,7 @@ sn_common_bus_fixup(struct pci_bus *bus, if (controller->node >= num_online_nodes()) { struct pcibus_bussoft *b = SN_PCIBUS_BUSSOFT(bus); - printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u " + printk(KERN_WARNING "Device ASIC=%u XID=%u PBUSNUM=%u" "L_IO=%lx L_MEM=%lx BASE=%lx\n", b->bs_asic_type, b->bs_xid, b->bs_persist_busnum, b->bs_legacy_io, b->bs_legacy_mem, b->bs_base); @@ -545,18 +545,19 @@ sn_io_late_init(void) nasid = NASID_GET(bussoft->bs_base); cnode = nasid_to_cnodeid(nasid); if ((bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCP) || - (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCE) || - (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_PIC)) { - /* PCI Bridge: find nearest node with CPUs */ + (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_TIOCE)) { + /* TIO PCI Bridge: find nearest node with CPUs */ int e = sn_hwperf_get_nearest_node(cnode, NULL, &near_cnode); if (e < 0) { near_cnode = (cnodeid_t)-1; /* use any node */ - printk(KERN_WARNING "sn_io_late_init: failed " - "to find near node with CPUs for " + printk(KERN_WARNING "pcibr_bus_fixup: failed " + "to find near node with CPUs to TIO " "node %d, err=%d\n", cnode, e); } PCI_CONTROLLER(bus)->node = near_cnode; + } else if (bussoft->bs_asic_type == PCIIO_ASIC_TYPE_PIC) { + PCI_CONTROLLER(bus)->node = cnode; } } diff --git a/trunk/drivers/firewire/fw-ohci.c b/trunk/drivers/firewire/fw-ohci.c index c9b9081831da..436a855a4c60 100644 --- a/trunk/drivers/firewire/fw-ohci.c +++ b/trunk/drivers/firewire/fw-ohci.c @@ -437,6 +437,21 @@ static void ar_context_run(struct ar_context *ctx) flush_writes(ctx->ohci); } +static struct descriptor * +find_branch_descriptor(struct descriptor *d, int z) +{ + int b, key; + + b = (le16_to_cpu(d->control) & DESCRIPTOR_BRANCH_ALWAYS) >> 2; + key = (le16_to_cpu(d->control) & DESCRIPTOR_KEY_IMMEDIATE) >> 8; + + /* figure out which descriptor the branch address goes in */ + if (z == 2 && (b == 3 || key == 2)) + return d; + else + return d + z - 1; +} + static void context_tasklet(unsigned long data) { struct context *ctx = (struct context *) data; @@ -455,7 +470,7 @@ static void context_tasklet(unsigned long data) address = le32_to_cpu(last->branch_address); z = address & 0xf; d = ctx->buffer + (address - ctx->buffer_bus) / sizeof(*d); - last = (z == 2) ? d : d + z - 1; + last = find_branch_descriptor(d, z); if (!ctx->callback(ctx, d, last)) break; @@ -566,7 +581,7 @@ static void context_append(struct context *ctx, ctx->head_descriptor = d + z + extra; ctx->prev_descriptor->branch_address = cpu_to_le32(d_bus | z); - ctx->prev_descriptor = z == 2 ? d : d + z - 1; + ctx->prev_descriptor = find_branch_descriptor(d, z); dma_sync_single_for_device(ctx->ohci->card.device, ctx->buffer_bus, ctx->buffer_size, DMA_TO_DEVICE); @@ -655,7 +670,7 @@ at_context_queue_packet(struct context *ctx, struct fw_packet *packet) driver_data = (struct driver_data *) &d[3]; driver_data->packet = packet; packet->driver_data = driver_data; - + if (packet->payload_length > 0) { payload_bus = dma_map_single(ohci->card.device, packet->payload, @@ -903,7 +918,7 @@ at_context_transmit(struct context *ctx, struct fw_packet *packet) if (retval < 0) packet->callback(packet, &ctx->ohci->card, packet->ack); - + } static void bus_reset_tasklet(unsigned long data) @@ -1431,6 +1446,57 @@ static int handle_ir_dualbuffer_packet(struct context *context, return 1; } +static int handle_ir_packet_per_buffer(struct context *context, + struct descriptor *d, + struct descriptor *last) +{ + struct iso_context *ctx = + container_of(context, struct iso_context, context); + struct descriptor *pd = d + 1; + __le32 *ir_header; + size_t header_length; + void *p, *end; + int i, z; + + if (pd->res_count == pd->req_count) + /* Descriptor(s) not done yet, stop iteration */ + return 0; + + header_length = le16_to_cpu(d->req_count); + + i = ctx->header_length; + z = le32_to_cpu(pd->branch_address) & 0xf; + p = d + z; + end = p + header_length; + + while (p < end && i + ctx->base.header_size <= PAGE_SIZE) { + /* + * The iso header is byteswapped to little endian by + * the controller, but the remaining header quadlets + * are big endian. We want to present all the headers + * as big endian, so we have to swap the first quadlet. + */ + *(u32 *) (ctx->header + i) = __swab32(*(u32 *) (p + 4)); + memcpy(ctx->header + i + 4, p + 8, ctx->base.header_size - 4); + i += ctx->base.header_size; + p += ctx->base.header_size + 4; + } + + ctx->header_length = i; + + if (le16_to_cpu(pd->control) & DESCRIPTOR_IRQ_ALWAYS) { + ir_header = (__le32 *) (d + z); + ctx->base.callback(&ctx->base, + le32_to_cpu(ir_header[0]) & 0xffff, + ctx->header_length, ctx->header, + ctx->base.callback_data); + ctx->header_length = 0; + } + + + return 1; +} + static int handle_it_packet(struct context *context, struct descriptor *d, struct descriptor *last) @@ -1466,14 +1532,12 @@ ohci_allocate_iso_context(struct fw_card *card, int type, size_t header_size) } else { mask = &ohci->ir_context_mask; list = ohci->ir_context_list; - callback = handle_ir_dualbuffer_packet; + if (ohci->version >= OHCI_VERSION_1_1) + callback = handle_ir_dualbuffer_packet; + else + callback = handle_ir_packet_per_buffer; } - /* FIXME: We need a fallback for pre 1.1 OHCI. */ - if (callback == handle_ir_dualbuffer_packet && - ohci->version < OHCI_VERSION_1_1) - return ERR_PTR(-ENOSYS); - spin_lock_irqsave(&ohci->lock, flags); index = ffs(*mask) - 1; if (index >= 0) @@ -1532,7 +1596,9 @@ static int ohci_start_iso(struct fw_iso_context *base, context_run(&ctx->context, match); } else { index = ctx - ohci->ir_context_list; - control = IR_CONTEXT_DUAL_BUFFER_MODE | IR_CONTEXT_ISOCH_HEADER; + control = IR_CONTEXT_ISOCH_HEADER; + if (ohci->version >= OHCI_VERSION_1_1) + control |= IR_CONTEXT_DUAL_BUFFER_MODE; match = (tags << 28) | (sync << 8) | ctx->base.channel; if (cycle >= 0) { match |= (cycle & 0x07fff) << 12; @@ -1738,7 +1804,6 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, offset = payload & ~PAGE_MASK; rest = p->payload_length; - /* FIXME: OHCI 1.0 doesn't support dual buffer receive */ /* FIXME: make packet-per-buffer/dual-buffer a context option */ while (rest > 0) { d = context_get_descriptors(&ctx->context, @@ -1776,6 +1841,81 @@ ohci_queue_iso_receive_dualbuffer(struct fw_iso_context *base, return 0; } +static int +ohci_queue_iso_receive_packet_per_buffer(struct fw_iso_context *base, + struct fw_iso_packet *packet, + struct fw_iso_buffer *buffer, + unsigned long payload) +{ + struct iso_context *ctx = container_of(base, struct iso_context, base); + struct descriptor *d = NULL, *pd = NULL; + struct fw_iso_packet *p; + dma_addr_t d_bus, page_bus; + u32 z, header_z, rest; + int i, page, offset, packet_count, header_size; + + if (packet->skip) { + d = context_get_descriptors(&ctx->context, 1, &d_bus); + if (d == NULL) + return -ENOMEM; + + d->control = cpu_to_le16(DESCRIPTOR_STATUS | + DESCRIPTOR_INPUT_LAST | + DESCRIPTOR_BRANCH_ALWAYS | + DESCRIPTOR_WAIT); + context_append(&ctx->context, d, 1, 0); + } + + /* one descriptor for header, one for payload */ + /* FIXME: handle cases where we need multiple desc. for payload */ + z = 2; + p = packet; + + /* + * The OHCI controller puts the status word in the + * buffer too, so we need 4 extra bytes per packet. + */ + packet_count = p->header_length / ctx->base.header_size; + header_size = packet_count * (ctx->base.header_size + 4); + + /* Get header size in number of descriptors. */ + header_z = DIV_ROUND_UP(header_size, sizeof(*d)); + page = payload >> PAGE_SHIFT; + offset = payload & ~PAGE_MASK; + rest = p->payload_length; + + for (i = 0; i < packet_count; i++) { + /* d points to the header descriptor */ + d = context_get_descriptors(&ctx->context, + z + header_z, &d_bus); + if (d == NULL) + return -ENOMEM; + + d->control = cpu_to_le16(DESCRIPTOR_INPUT_MORE); + d->req_count = cpu_to_le16(header_size); + d->res_count = d->req_count; + d->data_address = cpu_to_le32(d_bus + (z * sizeof(*d))); + + /* pd points to the payload descriptor */ + pd = d + 1; + pd->control = cpu_to_le16(DESCRIPTOR_STATUS | + DESCRIPTOR_INPUT_LAST | + DESCRIPTOR_BRANCH_ALWAYS); + if (p->interrupt) + pd->control |= cpu_to_le16(DESCRIPTOR_IRQ_ALWAYS); + + pd->req_count = cpu_to_le16(rest); + pd->res_count = pd->req_count; + + page_bus = page_private(buffer->pages[page]); + pd->data_address = cpu_to_le32(page_bus + offset); + + context_append(&ctx->context, d, z, header_z); + } + + return 0; +} + static int ohci_queue_iso(struct fw_iso_context *base, struct fw_iso_packet *packet, @@ -1790,8 +1930,9 @@ ohci_queue_iso(struct fw_iso_context *base, return ohci_queue_iso_receive_dualbuffer(base, packet, buffer, payload); else - /* FIXME: Implement fallback for OHCI 1.0 controllers. */ - return -ENOSYS; + return ohci_queue_iso_receive_packet_per_buffer(base, packet, + buffer, + payload); } static const struct fw_card_driver ohci_driver = { @@ -1911,12 +2052,6 @@ pci_probe(struct pci_dev *dev, const struct pci_device_id *ent) ohci->version = reg_read(ohci, OHCI1394_Version) & 0x00ff00ff; fw_notify("Added fw-ohci device %s, OHCI version %x.%x\n", dev->dev.bus_id, ohci->version >> 16, ohci->version & 0xff); - if (ohci->version < OHCI_VERSION_1_1) { - fw_notify(" Isochronous I/O is not yet implemented for " - "OHCI 1.0 chips.\n"); - fw_notify(" Cameras, audio devices etc. won't work on " - "this controller with this driver version.\n"); - } return 0; fail_self_id: diff --git a/trunk/include/asm-ia64/iosapic.h b/trunk/include/asm-ia64/iosapic.h index a3a4288daae8..b8f712859140 100644 --- a/trunk/include/asm-ia64/iosapic.h +++ b/trunk/include/asm-ia64/iosapic.h @@ -80,6 +80,7 @@ extern int iosapic_remove (unsigned int gsi_base); #else #define iosapic_remove(gsi_base) (-EINVAL) #endif /* CONFIG_HOTPLUG */ +extern int gsi_to_vector (unsigned int gsi); extern int gsi_to_irq (unsigned int gsi); extern int iosapic_register_intr (unsigned int gsi, unsigned long polarity, unsigned long trigger); @@ -93,6 +94,7 @@ extern int __init iosapic_register_platform_intr (u32 int_type, u16 eid, u16 id, unsigned long polarity, unsigned long trigger); +extern unsigned int iosapic_version (char __iomem *addr); #ifdef CONFIG_NUMA extern void __devinit map_iosapic_to_node (unsigned int, int);