Commit 02e58fc8 authored by Linus Torvalds's avatar Linus Torvalds

Merge http://ppc.bkbits.net/for-linus-ppc64

into home.transmeta.com:/home/torvalds/v2.5/linux
parents 2e6e0d09 424706ad
...@@ -21,7 +21,7 @@ locking rules: ...@@ -21,7 +21,7 @@ locking rules:
dcache_lock may block dcache_lock may block
d_revalidate: no yes d_revalidate: no yes
d_hash no yes d_hash no yes
d_compare: yes no d_compare: no no
d_delete: yes no d_delete: yes no
d_release: no yes d_release: no yes
d_iput: no yes d_iput: no yes
......
...@@ -223,7 +223,7 @@ io7_redirect_one_lsi(struct io7 *io7, unsigned int which, unsigned int where) ...@@ -223,7 +223,7 @@ io7_redirect_one_lsi(struct io7 *io7, unsigned int which, unsigned int where)
*/ */
val = io7->csrs->PO7_LSI_CTL[which].csr; val = io7->csrs->PO7_LSI_CTL[which].csr;
val &= ~(0x1ffUL << 14); /* clear the target pid */ val &= ~(0x1ffUL << 14); /* clear the target pid */
val |= ((unsigned long)where << 14); /* set teh new target pid */ val |= ((unsigned long)where << 14); /* set the new target pid */
io7->csrs->PO7_LSI_CTL[which].csr = val; io7->csrs->PO7_LSI_CTL[which].csr = val;
mb(); mb();
...@@ -240,7 +240,7 @@ io7_redirect_one_msi(struct io7 *io7, unsigned int which, unsigned int where) ...@@ -240,7 +240,7 @@ io7_redirect_one_msi(struct io7 *io7, unsigned int which, unsigned int where)
*/ */
val = io7->csrs->PO7_MSI_CTL[which].csr; val = io7->csrs->PO7_MSI_CTL[which].csr;
val &= ~(0x1ffUL << 14); /* clear the target pid */ val &= ~(0x1ffUL << 14); /* clear the target pid */
val |= ((unsigned long)where << 14); /* set teh new target pid */ val |= ((unsigned long)where << 14); /* set the new target pid */
io7->csrs->PO7_MSI_CTL[which].csr = val; io7->csrs->PO7_MSI_CTL[which].csr = val;
mb(); mb();
......
...@@ -83,15 +83,13 @@ void __init mtrr_state_warn(void) ...@@ -83,15 +83,13 @@ void __init mtrr_state_warn(void)
if (!mask) if (!mask)
return; return;
if (mask & MTRR_CHANGE_MASK_FIXED) if (mask & MTRR_CHANGE_MASK_FIXED)
printk printk(KERN_WARNING "mtrr: your CPUs had inconsistent fixed MTRR settings\n");
("mtrr: your CPUs had inconsistent fixed MTRR settings\n");
if (mask & MTRR_CHANGE_MASK_VARIABLE) if (mask & MTRR_CHANGE_MASK_VARIABLE)
printk printk(KERN_WARNING "mtrr: your CPUs had inconsistent variable MTRR settings\n");
("mtrr: your CPUs had inconsistent variable MTRR settings\n");
if (mask & MTRR_CHANGE_MASK_DEFTYPE) if (mask & MTRR_CHANGE_MASK_DEFTYPE)
printk printk(KERN_WARNING "mtrr: your CPUs had inconsistent MTRRdefType settings\n");
("mtrr: your CPUs had inconsistent MTRRdefType settings\n"); printk(KERN_INFO "mtrr: probably your BIOS does not setup all CPUs.\n");
printk("mtrr: probably your BIOS does not setup all CPUs\n"); printk(KERN_INFO "mtrr: corrected configuration.\n");
} }
...@@ -338,23 +336,19 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i ...@@ -338,23 +336,19 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
boot_cpu_data.x86_model == 1 && boot_cpu_data.x86_model == 1 &&
boot_cpu_data.x86_mask <= 7) { boot_cpu_data.x86_mask <= 7) {
if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) { if (base & ((1 << (22 - PAGE_SHIFT)) - 1)) {
printk(KERN_WARNING printk(KERN_WARNING "mtrr: base(0x%lx000) is not 4 MiB aligned\n", base);
"mtrr: base(0x%lx000) is not 4 MiB aligned\n",
base);
return -EINVAL; return -EINVAL;
} }
if (!(base + size < 0x70000000 || base > 0x7003FFFF) && if (!(base + size < 0x70000000 || base > 0x7003FFFF) &&
(type == MTRR_TYPE_WRCOMB (type == MTRR_TYPE_WRCOMB
|| type == MTRR_TYPE_WRBACK)) { || type == MTRR_TYPE_WRBACK)) {
printk(KERN_WARNING printk(KERN_WARNING "mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
"mtrr: writable mtrr between 0x70000000 and 0x7003FFFF may hang the CPU.\n");
return -EINVAL; return -EINVAL;
} }
} }
if (base + size < 0x100) { if (base + size < 0x100) {
printk(KERN_WARNING printk(KERN_WARNING "mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
"mtrr: cannot set region below 1 MiB (0x%lx000,0x%lx000)\n",
base, size); base, size);
return -EINVAL; return -EINVAL;
} }
...@@ -364,8 +358,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i ...@@ -364,8 +358,7 @@ int generic_validate_add_page(unsigned long base, unsigned long size, unsigned i
for (lbase = base; !(lbase & 1) && (last & 1); for (lbase = base; !(lbase & 1) && (last & 1);
lbase = lbase >> 1, last = last >> 1) ; lbase = lbase >> 1, last = last >> 1) ;
if (lbase != last) { if (lbase != last) {
printk(KERN_WARNING printk(KERN_WARNING "mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n",
"mtrr: base(0x%lx000) is not aligned on a size(0x%lx000) boundary\n",
base, size); base, size);
return -EINVAL; return -EINVAL;
} }
......
...@@ -668,7 +668,9 @@ static int __init find_isa_irq_pin(int irq, int type) ...@@ -668,7 +668,9 @@ static int __init find_isa_irq_pin(int irq, int type)
if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA || if ((mp_bus_id_to_type[lbus] == MP_BUS_ISA ||
mp_bus_id_to_type[lbus] == MP_BUS_EISA || mp_bus_id_to_type[lbus] == MP_BUS_EISA ||
mp_bus_id_to_type[lbus] == MP_BUS_MCA) && mp_bus_id_to_type[lbus] == MP_BUS_MCA ||
mp_bus_id_to_type[lbus] == MP_BUS_NEC98
) &&
(mp_irqs[i].mpc_irqtype == type) && (mp_irqs[i].mpc_irqtype == type) &&
(mp_irqs[i].mpc_srcbusirq == irq)) (mp_irqs[i].mpc_srcbusirq == irq))
...@@ -762,6 +764,12 @@ static int __init EISA_ELCR(unsigned int irq) ...@@ -762,6 +764,12 @@ static int __init EISA_ELCR(unsigned int irq)
#define default_MCA_trigger(idx) (1) #define default_MCA_trigger(idx) (1)
#define default_MCA_polarity(idx) (0) #define default_MCA_polarity(idx) (0)
/* NEC98 interrupts are always polarity zero edge triggered,
* when listed as conforming in the MP table. */
#define default_NEC98_trigger(idx) (0)
#define default_NEC98_polarity(idx) (0)
static int __init MPBIOS_polarity(int idx) static int __init MPBIOS_polarity(int idx)
{ {
int bus = mp_irqs[idx].mpc_srcbus; int bus = mp_irqs[idx].mpc_srcbus;
...@@ -796,6 +804,11 @@ static int __init MPBIOS_polarity(int idx) ...@@ -796,6 +804,11 @@ static int __init MPBIOS_polarity(int idx)
polarity = default_MCA_polarity(idx); polarity = default_MCA_polarity(idx);
break; break;
} }
case MP_BUS_NEC98: /* NEC 98 pin */
{
polarity = default_NEC98_polarity(idx);
break;
}
default: default:
{ {
printk(KERN_WARNING "broken BIOS!!\n"); printk(KERN_WARNING "broken BIOS!!\n");
...@@ -865,6 +878,11 @@ static int __init MPBIOS_trigger(int idx) ...@@ -865,6 +878,11 @@ static int __init MPBIOS_trigger(int idx)
trigger = default_MCA_trigger(idx); trigger = default_MCA_trigger(idx);
break; break;
} }
case MP_BUS_NEC98: /* NEC 98 pin */
{
trigger = default_NEC98_trigger(idx);
break;
}
default: default:
{ {
printk(KERN_WARNING "broken BIOS!!\n"); printk(KERN_WARNING "broken BIOS!!\n");
...@@ -926,6 +944,7 @@ static int pin_2_irq(int idx, int apic, int pin) ...@@ -926,6 +944,7 @@ static int pin_2_irq(int idx, int apic, int pin)
case MP_BUS_ISA: /* ISA pin */ case MP_BUS_ISA: /* ISA pin */
case MP_BUS_EISA: case MP_BUS_EISA:
case MP_BUS_MCA: case MP_BUS_MCA:
case MP_BUS_NEC98:
{ {
irq = mp_irqs[idx].mpc_srcbusirq; irq = mp_irqs[idx].mpc_srcbusirq;
break; break;
...@@ -1133,8 +1152,9 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector) ...@@ -1133,8 +1152,9 @@ void __init setup_ExtINT_IRQ0_pin(unsigned int pin, int vector)
void __init UNEXPECTED_IO_APIC(void) void __init UNEXPECTED_IO_APIC(void)
{ {
printk(KERN_WARNING " WARNING: unexpected IO-APIC, please mail\n"); printk(KERN_WARNING "INFO: unexpected IO-APIC, please file a report at\n");
printk(KERN_WARNING " to linux-smp@vger.kernel.org\n"); printk(KERN_WARNING " http://bugzilla.kernel.org\n");
printk(KERN_WARNING " if your kernel is less than 3 months old.\n");
} }
void __init print_IO_APIC(void) void __init print_IO_APIC(void)
......
...@@ -169,7 +169,7 @@ void __init MP_processor_info (struct mpc_config_processor *m) ...@@ -169,7 +169,7 @@ void __init MP_processor_info (struct mpc_config_processor *m)
num_processors++; num_processors++;
if (m->mpc_apicid > MAX_APICS) { if (m->mpc_apicid > MAX_APICS) {
printk("Processor #%d INVALID. (Max ID: %d).\n", printk(KERN_WARNING "Processor #%d INVALID. (Max ID: %d).\n",
m->mpc_apicid, MAX_APICS); m->mpc_apicid, MAX_APICS);
--num_processors; --num_processors;
return; return;
...@@ -182,7 +182,7 @@ void __init MP_processor_info (struct mpc_config_processor *m) ...@@ -182,7 +182,7 @@ void __init MP_processor_info (struct mpc_config_processor *m)
* Validate version * Validate version
*/ */
if (ver == 0x0) { if (ver == 0x0) {
printk("BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid); printk(KERN_WARNING "BIOS bug, APIC version is 0 for CPU#%d! fixing up to 0x10. (tell your hw vendor)\n", m->mpc_apicid);
ver = 0x10; ver = 0x10;
} }
apic_version[m->mpc_apicid] = ver; apic_version[m->mpc_apicid] = ver;
...@@ -209,8 +209,10 @@ static void __init MP_bus_info (struct mpc_config_bus *m) ...@@ -209,8 +209,10 @@ static void __init MP_bus_info (struct mpc_config_bus *m)
mp_current_pci_id++; mp_current_pci_id++;
} else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) { } else if (strncmp(str, BUSTYPE_MCA, sizeof(BUSTYPE_MCA)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA; mp_bus_id_to_type[m->mpc_busid] = MP_BUS_MCA;
} else if (strncmp(str, BUSTYPE_NEC98, sizeof(BUSTYPE_NEC98)-1) == 0) {
mp_bus_id_to_type[m->mpc_busid] = MP_BUS_NEC98;
} else { } else {
printk("Unknown bustype %s - ignoring\n", str); printk(KERN_WARNING "Unknown bustype %s - ignoring\n", str);
} }
} }
...@@ -219,10 +221,10 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m) ...@@ -219,10 +221,10 @@ static void __init MP_ioapic_info (struct mpc_config_ioapic *m)
if (!(m->mpc_flags & MPC_APIC_USABLE)) if (!(m->mpc_flags & MPC_APIC_USABLE))
return; return;
printk("I/O APIC #%d Version %d at 0x%lX.\n", printk(KERN_INFO "I/O APIC #%d Version %d at 0x%lX.\n",
m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr); m->mpc_apicid, m->mpc_apicver, m->mpc_apicaddr);
if (nr_ioapics >= MAX_IO_APICS) { if (nr_ioapics >= MAX_IO_APICS) {
printk("Max # of I/O APICs (%d) exceeded (found %d).\n", printk(KERN_CRIT "Max # of I/O APICs (%d) exceeded (found %d).\n",
MAX_IO_APICS, nr_ioapics); MAX_IO_APICS, nr_ioapics);
panic("Recompile kernel with bigger MAX_IO_APICS!.\n"); panic("Recompile kernel with bigger MAX_IO_APICS!.\n");
} }
...@@ -272,10 +274,10 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m) ...@@ -272,10 +274,10 @@ static void __init MP_lintsrc_info (struct mpc_config_lintsrc *m)
#ifdef CONFIG_X86_NUMAQ #ifdef CONFIG_X86_NUMAQ
static void __init MP_translation_info (struct mpc_config_translation *m) static void __init MP_translation_info (struct mpc_config_translation *m)
{ {
printk("Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local); printk(KERN_INFO "Translation: record %d, type %d, quad %d, global %d, local %d\n", mpc_record, m->trans_type, m->trans_quad, m->trans_global, m->trans_local);
if (mpc_record >= MAX_MPC_ENTRY) if (mpc_record >= MAX_MPC_ENTRY)
printk("MAX_MPC_ENTRY exceeded!\n"); printk(KERN_ERR "MAX_MPC_ENTRY exceeded!\n");
else else
translation_table[mpc_record] = m; /* stash this for later */ translation_table[mpc_record] = m; /* stash this for later */
if (m->trans_quad+1 > numnodes) if (m->trans_quad+1 > numnodes)
...@@ -293,10 +295,10 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ ...@@ -293,10 +295,10 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
unsigned char *oemptr = ((unsigned char *)oemtable)+count; unsigned char *oemptr = ((unsigned char *)oemtable)+count;
mpc_record = 0; mpc_record = 0;
printk("Found an OEM MPC table at %8p - parsing it ... \n", oemtable); printk(KERN_INFO "Found an OEM MPC table at %8p - parsing it ... \n", oemtable);
if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4)) if (memcmp(oemtable->oem_signature,MPC_OEM_SIGNATURE,4))
{ {
printk("SMP mpc oemtable: bad signature [%c%c%c%c]!\n", printk(KERN_WARNING "SMP mpc oemtable: bad signature [%c%c%c%c]!\n",
oemtable->oem_signature[0], oemtable->oem_signature[0],
oemtable->oem_signature[1], oemtable->oem_signature[1],
oemtable->oem_signature[2], oemtable->oem_signature[2],
...@@ -305,7 +307,7 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ ...@@ -305,7 +307,7 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
} }
if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length)) if (mpf_checksum((unsigned char *)oemtable,oemtable->oem_length))
{ {
printk("SMP oem mptable: checksum error!\n"); printk(KERN_WARNING "SMP oem mptable: checksum error!\n");
return; return;
} }
while (count < oemtable->oem_length) { while (count < oemtable->oem_length) {
...@@ -322,7 +324,7 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \ ...@@ -322,7 +324,7 @@ static void __init smp_read_mpc_oem(struct mp_config_oemtable *oemtable, \
} }
default: default:
{ {
printk("Unrecognised OEM table entry type! - %d\n", (int) *oemptr); printk(KERN_WARNING "Unrecognised OEM table entry type! - %d\n", (int) *oemptr);
return; return;
} }
} }
...@@ -364,7 +366,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc) ...@@ -364,7 +366,7 @@ static int __init smp_read_mpc(struct mp_config_table *mpc)
} }
memcpy(oem,mpc->mpc_oem,8); memcpy(oem,mpc->mpc_oem,8);
oem[8]=0; oem[8]=0;
printk("OEM ID: %s ",oem); printk(KERN_INFO "OEM ID: %s ",oem);
memcpy(str,mpc->mpc_productid,12); memcpy(str,mpc->mpc_productid,12);
str[12]=0; str[12]=0;
...@@ -479,12 +481,12 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type) ...@@ -479,12 +481,12 @@ static void __init construct_default_ioirq_mptable(int mpc_default_type)
* If it does, we assume it's valid. * If it does, we assume it's valid.
*/ */
if (mpc_default_type == 5) { if (mpc_default_type == 5) {
printk("ISA/PCI bus type with no IRQ information... falling back to ELCR\n"); printk(KERN_INFO "ISA/PCI bus type with no IRQ information... falling back to ELCR\n");
if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13)) if (ELCR_trigger(0) || ELCR_trigger(1) || ELCR_trigger(2) || ELCR_trigger(13))
printk("ELCR contains invalid data... not using ELCR\n"); printk(KERN_WARNING "ELCR contains invalid data... not using ELCR\n");
else { else {
printk("Using ELCR to identify PCI interrupts\n"); printk(KERN_INFO "Using ELCR to identify PCI interrupts\n");
ELCR_fallback = 1; ELCR_fallback = 1;
} }
} }
...@@ -559,7 +561,8 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type) ...@@ -559,7 +561,8 @@ static inline void __init construct_default_ISA_mptable(int mpc_default_type)
bus.mpc_busid = 0; bus.mpc_busid = 0;
switch (mpc_default_type) { switch (mpc_default_type) {
default: default:
printk("???\nUnknown standard configuration %d\n", printk("???\n");
printk(KERN_ERR "Unknown standard configuration %d\n",
mpc_default_type); mpc_default_type);
/* fall through */ /* fall through */
case 1: case 1:
...@@ -628,12 +631,12 @@ void __init get_smp_config (void) ...@@ -628,12 +631,12 @@ void __init get_smp_config (void)
else if (acpi_lapic) else if (acpi_lapic)
printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n"); printk(KERN_INFO "Using ACPI for processor (LAPIC) configuration information\n");
printk("Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification); printk("KERN_INFO Intel MultiProcessor Specification v1.%d\n", mpf->mpf_specification);
if (mpf->mpf_feature2 & (1<<7)) { if (mpf->mpf_feature2 & (1<<7)) {
printk(" IMCR and PIC compatibility mode.\n"); printk(KERN_INFO " IMCR and PIC compatibility mode.\n");
pic_mode = 1; pic_mode = 1;
} else { } else {
printk(" Virtual Wire compatibility mode.\n"); printk(KERN_INFO " Virtual Wire compatibility mode.\n");
pic_mode = 0; pic_mode = 0;
} }
...@@ -642,7 +645,7 @@ void __init get_smp_config (void) ...@@ -642,7 +645,7 @@ void __init get_smp_config (void)
*/ */
if (mpf->mpf_feature1 != 0) { if (mpf->mpf_feature1 != 0) {
printk("Default MP configuration #%d\n", mpf->mpf_feature1); printk(KERN_INFO "Default MP configuration #%d\n", mpf->mpf_feature1);
construct_default_ISA_mptable(mpf->mpf_feature1); construct_default_ISA_mptable(mpf->mpf_feature1);
} else if (mpf->mpf_physptr) { } else if (mpf->mpf_physptr) {
...@@ -665,7 +668,7 @@ void __init get_smp_config (void) ...@@ -665,7 +668,7 @@ void __init get_smp_config (void)
if (!mp_irq_entries) { if (!mp_irq_entries) {
struct mpc_config_bus bus; struct mpc_config_bus bus;
printk("BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n"); printk(KERN_ERR "BIOS bug, no explicit IRQ entries, using default mptable. (tell your hw vendor)\n");
bus.mpc_type = MP_BUS; bus.mpc_type = MP_BUS;
bus.mpc_busid = 0; bus.mpc_busid = 0;
...@@ -678,7 +681,7 @@ void __init get_smp_config (void) ...@@ -678,7 +681,7 @@ void __init get_smp_config (void)
} else } else
BUG(); BUG();
printk("Processors: %d\n", num_processors); printk(KERN_INFO "Processors: %d\n", num_processors);
/* /*
* Only use the first configuration found. * Only use the first configuration found.
*/ */
...@@ -702,7 +705,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length) ...@@ -702,7 +705,7 @@ static int __init smp_scan_config (unsigned long base, unsigned long length)
|| (mpf->mpf_specification == 4)) ) { || (mpf->mpf_specification == 4)) ) {
smp_found_config = 1; smp_found_config = 1;
printk("found SMP MP-table at %08lx\n", printk(KERN_INFO "found SMP MP-table at %08lx\n",
virt_to_phys(mpf)); virt_to_phys(mpf));
reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE); reserve_bootmem(virt_to_phys(mpf), PAGE_SIZE);
if (mpf->mpf_physptr) if (mpf->mpf_physptr)
...@@ -752,8 +755,6 @@ void __init find_smp_config (void) ...@@ -752,8 +755,6 @@ void __init find_smp_config (void)
address = *(unsigned short *)phys_to_virt(0x40E); address = *(unsigned short *)phys_to_virt(0x40E);
address <<= 4; address <<= 4;
smp_scan_config(address, 0x400); smp_scan_config(address, 0x400);
if (smp_found_config)
printk(KERN_WARNING "WARNING: MP table in the EBDA can be UNSAFE, contact linux-smp@vger.kernel.org if you experience SMP problems!\n");
} }
......
...@@ -452,9 +452,11 @@ static void flush_tlb_all_ipi(void* info) ...@@ -452,9 +452,11 @@ static void flush_tlb_all_ipi(void* info)
void flush_tlb_all(void) void flush_tlb_all(void)
{ {
preempt_disable();
smp_call_function (flush_tlb_all_ipi,0,1,1); smp_call_function (flush_tlb_all_ipi,0,1,1);
do_flush_tlb_all_local(); do_flush_tlb_all_local();
preempt_enable();
} }
/* /*
......
...@@ -631,7 +631,7 @@ hub_provider_shutdown(devfs_handle_t hub) ...@@ -631,7 +631,7 @@ hub_provider_shutdown(devfs_handle_t hub)
} }
/* /*
* Check that an address is in teh real small window widget 0 space * Check that an address is in the real small window widget 0 space
* or else in the big window we're using to emulate small window 0 * or else in the big window we're using to emulate small window 0
* in the kernel. * in the kernel.
*/ */
...@@ -708,7 +708,7 @@ hub_check_pci_equiv(void *addra, void *addrb) ...@@ -708,7 +708,7 @@ hub_check_pci_equiv(void *addra, void *addrb)
/* /*
* hub_setup_prb(nasid, prbnum, credits, conveyor) * hub_setup_prb(nasid, prbnum, credits, conveyor)
* *
* Put a PRB into fire-and-forget mode if conveyor isn't set. Otehrwise, * Put a PRB into fire-and-forget mode if conveyor isn't set. Otherwise,
* put it into conveyor belt mode with the specified number of credits. * put it into conveyor belt mode with the specified number of credits.
*/ */
void void
......
...@@ -320,7 +320,8 @@ tracesys_sigexit: ...@@ -320,7 +320,8 @@ tracesys_sigexit:
#ifdef __LP64__ #ifdef __LP64__
/* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
* narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific * narrow palinux. Use ENTRY_DIFF for those where a 32-bit specific
* implementation is required on wide palinux. * implementation is required on wide palinux. Use ENTRY_COMP where
* the compatability layer has a useful 32-bit implementation.
*/ */
#define ENTRY_SAME(_name_) .dword sys_##_name_ #define ENTRY_SAME(_name_) .dword sys_##_name_
#define ENTRY_DIFF(_name_) .dword sys32_##_name_ #define ENTRY_DIFF(_name_) .dword sys32_##_name_
...@@ -597,7 +598,7 @@ sys_call_table: ...@@ -597,7 +598,7 @@ sys_call_table:
ENTRY_SAME(ni_syscall) /* tkill */ ENTRY_SAME(ni_syscall) /* tkill */
ENTRY_SAME(sendfile64) ENTRY_SAME(sendfile64)
ENTRY_SAME(futex) /* 210 */ ENTRY_COMP(futex) /* 210 */
ENTRY_SAME(sched_setaffinity) ENTRY_SAME(sched_setaffinity)
ENTRY_SAME(sched_getaffinity) ENTRY_SAME(sched_getaffinity)
ENTRY_SAME(set_thread_area) ENTRY_SAME(set_thread_area)
......
...@@ -41,9 +41,9 @@ ...@@ -41,9 +41,9 @@
#define dbsr 0x3f0 /* debug status register */ #define dbsr 0x3f0 /* debug status register */
#define dccr 0x3fa /* data cache control reg. */ #define dccr 0x3fa /* data cache control reg. */
#define dcwr 0x3ba /* data cache write-thru reg */ #define dcwr 0x3ba /* data cache write-thru reg */
#define dear 0x3d5 /* data exeption address reg */ #define dear 0x3d5 /* data exception address reg */
#define esr 0x3d4 /* execption syndrome registe */ #define esr 0x3d4 /* exception syndrome registe */
#define evpr 0x3d6 /* exeption vector prefix reg */ #define evpr 0x3d6 /* exception vector prefix reg */
#define iccr 0x3fb /* instruction cache cntrl re */ #define iccr 0x3fb /* instruction cache cntrl re */
#define icdbdr 0x3d3 /* instr cache dbug data reg */ #define icdbdr 0x3d3 /* instr cache dbug data reg */
#define lrreg 0x008 /* link register */ #define lrreg 0x008 /* link register */
......
...@@ -1337,7 +1337,7 @@ setup_604_hid0: ...@@ -1337,7 +1337,7 @@ setup_604_hid0:
blr blr
/* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some /* 7400 <= rev 2.7 and 7410 rev = 1.0 suffer from some
* erratas we work around here. * errata we work around here.
* Moto MPC710CE.pdf describes them, those are errata * Moto MPC710CE.pdf describes them, those are errata
* #3, #4 and #5 * #3, #4 and #5
* Note that we assume the firmware didn't choose to * Note that we assume the firmware didn't choose to
......
...@@ -723,7 +723,7 @@ _GLOBAL(sys_call_table32) ...@@ -723,7 +723,7 @@ _GLOBAL(sys_call_table32)
.llong .sys_removexattr .llong .sys_removexattr
.llong .sys_lremovexattr .llong .sys_lremovexattr
.llong .sys_fremovexattr /* 220 */ .llong .sys_fremovexattr /* 220 */
.llong .sys_futex .llong .compat_sys_futex
.llong .sys32_sched_setaffinity .llong .sys32_sched_setaffinity
.llong .sys32_sched_getaffinity .llong .sys32_sched_getaffinity
.llong .sys_ni_syscall .llong .sys_ni_syscall
......
...@@ -629,7 +629,7 @@ sys_call_table: ...@@ -629,7 +629,7 @@ sys_call_table:
.long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper) /* 235 */ .long SYSCALL(sys_fremovexattr,sys32_fremovexattr_wrapper) /* 235 */
.long SYSCALL(sys_gettid,sys_gettid) .long SYSCALL(sys_gettid,sys_gettid)
.long SYSCALL(sys_tkill,sys_tkill) .long SYSCALL(sys_tkill,sys_tkill)
.long SYSCALL(sys_futex,sys32_futex_wrapper) .long SYSCALL(sys_futex,compat_sys_futex_wrapper)
.long SYSCALL(sys_sched_setaffinity,sys32_sched_setaffinity_wrapper) .long SYSCALL(sys_sched_setaffinity,sys32_sched_setaffinity_wrapper)
.long SYSCALL(sys_sched_getaffinity,sys32_sched_getaffinity_wrapper) /* 240 */ .long SYSCALL(sys_sched_getaffinity,sys32_sched_getaffinity_wrapper) /* 240 */
.long SYSCALL(sys_ni_syscall,sys_ni_syscall) .long SYSCALL(sys_ni_syscall,sys_ni_syscall)
......
...@@ -4049,28 +4049,6 @@ asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len, ...@@ -4049,28 +4049,6 @@ asmlinkage int sys32_sched_getaffinity(compat_pid_t pid, unsigned int len,
return ret; return ret;
} }
asmlinkage int
sys_futex(void *uaddr, int op, int val, struct timespec *utime);
asmlinkage int
sys32_futex(void *uaddr, int op, int val,
struct compat_timespec *timeout32)
{
struct timespec tmp;
mm_segment_t old_fs;
int ret;
if (timeout32 && get_compat_timespec(&tmp, timeout32))
return -EINVAL;
old_fs = get_fs();
set_fs(KERNEL_DS);
ret = sys_futex(uaddr, op, val, timeout32 ? &tmp : NULL);
set_fs(old_fs);
return ret;
}
asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count); asmlinkage ssize_t sys_read(unsigned int fd, char * buf, size_t count);
asmlinkage compat_ssize_t sys32_read(unsigned int fd, char * buf, size_t count) asmlinkage compat_ssize_t sys32_read(unsigned int fd, char * buf, size_t count)
......
...@@ -1088,13 +1088,13 @@ sys32_fstat64_wrapper: ...@@ -1088,13 +1088,13 @@ sys32_fstat64_wrapper:
llgfr %r4,%r4 # long llgfr %r4,%r4 # long
jg sys32_fstat64 # branch to system call jg sys32_fstat64 # branch to system call
.globl sys32_futex_wrapper .globl compat_sys_futex_wrapper
sys32_futex_wrapper: compat_sys_futex_wrapper:
llgtr %r2,%r2 # void * llgtr %r2,%r2 # u32 *
lgfr %r3,%r3 # int lgfr %r3,%r3 # int
lgfr %r4,%r4 # int lgfr %r4,%r4 # int
llgtr %r5,%r5 # struct timespec * llgtr %r5,%r5 # struct compat_timespec *
jg sys32_futex # branch to system call jg compat_sys_futex # branch to system call
.globl sys32_setxattr_wrapper .globl sys32_setxattr_wrapper
sys32_setxattr_wrapper: sys32_setxattr_wrapper:
......
...@@ -440,7 +440,7 @@ ia32_sys_call_table: ...@@ -440,7 +440,7 @@ ia32_sys_call_table:
.quad sys_fremovexattr .quad sys_fremovexattr
.quad sys_tkill /* 238 */ .quad sys_tkill /* 238 */
.quad sys_sendfile64 .quad sys_sendfile64
.quad sys32_futex /* 240 */ .quad compat_sys_futex /* 240 */
.quad sys32_sched_setaffinity .quad sys32_sched_setaffinity
.quad sys32_sched_getaffinity .quad sys32_sched_getaffinity
.quad sys_set_thread_area .quad sys_set_thread_area
......
...@@ -2199,26 +2199,6 @@ long sys32_sched_getaffinity(pid_t pid, unsigned int len, ...@@ -2199,26 +2199,6 @@ long sys32_sched_getaffinity(pid_t pid, unsigned int len,
return err; return err;
} }
extern int sys_futex(unsigned long uaddr, int op, int val, struct timespec *t);
asmlinkage long
sys32_futex(unsigned long uaddr, int op, int val, struct compat_timespec *utime32)
{
struct timespec t;
mm_segment_t oldfs = get_fs();
int err;
if (utime32 && get_compat_timespec(&t, utime32))
return -EFAULT;
/* the set_fs is safe because futex doesn't use the seg limit
for valid page checking of uaddr. */
set_fs(KERNEL_DS);
err = sys_futex(uaddr, op, val, utime32 ? &t : NULL);
set_fs(oldfs);
return err;
}
extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx); extern long sys_io_setup(unsigned nr_reqs, aio_context_t *ctx);
long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p) long sys32_io_setup(unsigned nr_reqs, u32 *ctx32p)
......
This diff is collapsed.
...@@ -89,8 +89,10 @@ static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = { ...@@ -89,8 +89,10 @@ static struct cciss_scsi_hba_t ccissscsi[MAX_CTLR] = {
working even with the SCSI system. It's so working even with the SCSI system. It's so
scsi_unregister_host will differentiate the controllers. scsi_unregister_host will differentiate the controllers.
When register_scsi_module is called, each host template is When register_scsi_module is called, each host template is
customized (name change) in cciss_register_scsi() customized (name change) in cciss_register_scsi() (that's
(that's called from cciss.c:cciss_init_one()) */ called from cciss_engage_scsi, called from
cciss.c:cciss_proc_write(), on "engage scsi" being received
from user space.) */
static static
Scsi_Host_Template driver_template[MAX_CTLR] = Scsi_Host_Template driver_template[MAX_CTLR] =
...@@ -199,14 +201,12 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd) ...@@ -199,14 +201,12 @@ scsi_cmd_free(ctlr_info_t *h, CommandList_struct *cmd)
} }
static int static int
scsi_cmd_stack_setup(int ctlr) scsi_cmd_stack_setup(int ctlr, struct cciss_scsi_adapter_data_t *sa)
{ {
int i; int i;
struct cciss_scsi_adapter_data_t *sa;
struct cciss_scsi_cmd_stack_t *stk; struct cciss_scsi_cmd_stack_t *stk;
size_t size; size_t size;
sa = (struct cciss_scsi_adapter_data_t *) hba[ctlr]->scsi_ctlr;
stk = &sa->cmd_stack; stk = &sa->cmd_stack;
size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE; size = sizeof(struct cciss_scsi_cmd_stack_elem_t) * CMD_STACK_SIZE;
...@@ -535,126 +535,24 @@ lookup_scsi3addr(int ctlr, int bus, int target, int lun, char *scsi3addr) ...@@ -535,126 +535,24 @@ lookup_scsi3addr(int ctlr, int bus, int target, int lun, char *scsi3addr)
return -1; return -1;
} }
static void static void
cciss_find_non_disk_devices(int cntl_num) cciss_scsi_setup(int cntl_num)
{ {
ReportLunData_struct *ld_buff; struct cciss_scsi_adapter_data_t * shba;
InquiryData_struct *inq_buff;
int return_code;
int i;
int listlength = 0;
int num_luns;
unsigned char scsi3addr[8];
unsigned long flags;
int reportlunsize = sizeof(*ld_buff) + CISS_MAX_PHYS_LUN * 8;
hba[cntl_num]->scsi_ctlr = (void *)
kmalloc(sizeof(struct cciss_scsi_adapter_data_t),
GFP_KERNEL);
if (hba[cntl_num]->scsi_ctlr == NULL)
return;
((struct cciss_scsi_adapter_data_t *)
hba[cntl_num]->scsi_ctlr)->scsi_host = NULL;
((struct cciss_scsi_adapter_data_t *)
hba[cntl_num]->scsi_ctlr)->lock = SPIN_LOCK_UNLOCKED;
((struct cciss_scsi_adapter_data_t *)
hba[cntl_num]->scsi_ctlr)->registered = 0;
if (scsi_cmd_stack_setup(cntl_num) != 0) {
printk("Trouble, returned non-zero!\n");
return;
}
ld_buff = kmalloc(reportlunsize, GFP_KERNEL);
if (ld_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
return;
}
memset(ld_buff, 0, sizeof(ReportLunData_struct));
inq_buff = kmalloc(sizeof( InquiryData_struct), GFP_KERNEL);
if (inq_buff == NULL) {
printk(KERN_ERR "cciss: out of memory\n");
kfree(ld_buff);
return;
}
/* Get the physical luns */
return_code = sendcmd(CISS_REPORT_PHYS, cntl_num, ld_buff,
reportlunsize, 0, 0, 0, NULL );
if( return_code == IO_OK) {
unsigned char *c = &ld_buff->LUNListLength[0];
listlength = (c[0] << 24) | (c[1] << 16) | (c[2] << 8) | c[3];
}
else { /* getting report of physical luns failed */
printk(KERN_WARNING "cciss: report physical luns"
" command failed\n");
listlength = 0;
}
CPQ_TAPE_LOCK(cntl_num, flags);
ccissscsi[cntl_num].ndevices = 0; ccissscsi[cntl_num].ndevices = 0;
num_luns = listlength / 8; // 8 bytes pre entry shba = (struct cciss_scsi_adapter_data_t *)
/* printk("Found %d LUNs\n", num_luns); */ kmalloc(sizeof(*shba), GFP_KERNEL);
if (shba == NULL)
if (num_luns > CISS_MAX_PHYS_LUN) return;
{ shba->scsi_host = NULL;
printk(KERN_WARNING shba->lock = SPIN_LOCK_UNLOCKED;
"cciss: Maximum physical LUNs (%d) exceeded. " shba->registered = 0;
"%d LUNs ignored.\n", CISS_MAX_PHYS_LUN, if (scsi_cmd_stack_setup(cntl_num, shba) != 0) {
num_luns - CISS_MAX_PHYS_LUN); kfree(shba);
num_luns = CISS_MAX_PHYS_LUN; shba = NULL;
}
for(i=0; i<num_luns; i++) {
/* Execute an inquiry to figure the device type */
memset(inq_buff, 0, sizeof(InquiryData_struct));
memcpy(scsi3addr, ld_buff->LUN[i], 8); /* ugly... */
return_code = sendcmd(CISS_INQUIRY, cntl_num, inq_buff,
sizeof(InquiryData_struct), 2, 0 ,0, scsi3addr );
if (return_code == IO_OK) {
if(inq_buff->data_byte[8] == 0xFF)
{
printk(KERN_WARNING "cciss: inquiry failed\n");
} else {
int devtype;
/* printk("Inquiry...\n");
print_bytes((unsigned char *) inq_buff, 36, 1, 1); */
devtype = (inq_buff->data_byte[0] & 0x1f);
switch (devtype)
{
case 0x01: /* sequential access, (tape) */
case 0x08: /* medium changer */
/* this is the only kind of dev */
/* we want to expose here. */
if (cciss_scsi_add_entry(cntl_num, -1,
(unsigned char *) ld_buff->LUN[i],
devtype) != 0)
i=num_luns; // leave loop
break;
default:
break;
}
}
}
else printk("cciss: inquiry failed.\n");
} }
#if 0 hba[cntl_num]->scsi_ctlr = (void *) shba;
for (i=0;i<ccissscsi[cntl_num].ndevices;i++)
printk("Tape device presented at c%db%dt%dl%d\n",
cntl_num, // <-- this is wrong
ccissscsi[cntl_num].dev[i].bus,
ccissscsi[cntl_num].dev[i].target,
ccissscsi[cntl_num].dev[i].lun);
#endif
CPQ_TAPE_UNLOCK(cntl_num, flags);
kfree(ld_buff);
kfree(inq_buff);
return; return;
} }
...@@ -913,7 +811,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c, ...@@ -913,7 +811,7 @@ cciss_scsi_do_simple_cmd(ctlr_info_t *c,
memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
memcpy(cp->Request.CDB, cdb, cdblen); memcpy(cp->Request.CDB, cdb, cdblen);
cp->Request.Timeout = 1000; // guarantee completion. cp->Request.Timeout = 0;
cp->Request.CDBLen = cdblen; cp->Request.CDBLen = cdblen;
cp->Request.Type.Type = TYPE_CMD; cp->Request.Type.Type = TYPE_CMD;
cp->Request.Type.Attribute = ATTR_SIMPLE; cp->Request.Type.Attribute = ATTR_SIMPLE;
...@@ -1208,6 +1106,12 @@ cciss_update_non_disk_devices(int cntl_num, int hostno) ...@@ -1208,6 +1106,12 @@ cciss_update_non_disk_devices(int cntl_num, int hostno)
{ {
case 0x01: /* sequential access, (tape) */ case 0x01: /* sequential access, (tape) */
case 0x08: /* medium changer */ case 0x08: /* medium changer */
if (ncurrent >= CCISS_MAX_SCSI_DEVS_PER_HBA) {
printk(KERN_INFO "cciss%d: %s ignored, "
"too many devices.\n", cntl_num,
DEVICETYPE(devtype));
break;
}
memcpy(&currentsd[ncurrent].scsi3addr[0], memcpy(&currentsd[ncurrent].scsi3addr[0],
&scsi3addr[0], 8); &scsi3addr[0], 8);
currentsd[ncurrent].devtype = devtype; currentsd[ncurrent].devtype = devtype;
...@@ -1262,7 +1166,6 @@ cciss_scsi_proc_info(char *buffer, /* data buffer */ ...@@ -1262,7 +1166,6 @@ cciss_scsi_proc_info(char *buffer, /* data buffer */
int buflen, datalen; int buflen, datalen;
struct Scsi_Host *sh; struct Scsi_Host *sh;
int found;
ctlr_info_t *ci; ctlr_info_t *ci;
int cntl_num; int cntl_num;
...@@ -1379,11 +1282,11 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) ...@@ -1379,11 +1282,11 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
// Get the ptr to our adapter structure (hba[i]) out of cmd->host. // Get the ptr to our adapter structure (hba[i]) out of cmd->host.
// We violate cmd->host privacy here. (Is there another way?) // We violate cmd->host privacy here. (Is there another way?)
c = (ctlr_info_t **) &cmd->device->host->hostdata[0]; c = (ctlr_info_t **) &cmd->device->host->hostdata[0];
ctlr = (*c)->ctlr; ctlr = (*c)->ctlr;
rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id, cmd->device->lun, rc = lookup_scsi3addr(ctlr, cmd->device->channel, cmd->device->id,
scsi3addr); cmd->device->lun, scsi3addr);
if (rc != 0) { if (rc != 0) {
/* the scsi nexus does not match any that we presented... */ /* the scsi nexus does not match any that we presented... */
/* pretend to mid layer that we got selection timeout */ /* pretend to mid layer that we got selection timeout */
...@@ -1428,7 +1331,7 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) ...@@ -1428,7 +1331,7 @@ cciss_scsi_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *))
// Fill in the request block... // Fill in the request block...
cp->Request.Timeout = 1000; // guarantee completion cp->Request.Timeout = 0;
memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB)); memset(cp->Request.CDB, 0, sizeof(cp->Request.CDB));
if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG(); if (cmd->cmd_len > sizeof(cp->Request.CDB)) BUG();
cp->Request.CDBLen = cmd->cmd_len; cp->Request.CDBLen = cmd->cmd_len;
...@@ -1531,7 +1434,7 @@ cciss_unregister_scsi(int ctlr) ...@@ -1531,7 +1434,7 @@ cciss_unregister_scsi(int ctlr)
} }
static int static int
cciss_register_scsi(int ctlr, int this_is_init_time) cciss_register_scsi(int ctlr)
{ {
unsigned long flags; unsigned long flags;
...@@ -1541,15 +1444,10 @@ cciss_register_scsi(int ctlr, int this_is_init_time) ...@@ -1541,15 +1444,10 @@ cciss_register_scsi(int ctlr, int this_is_init_time)
driver_template[ctlr].module = THIS_MODULE;; driver_template[ctlr].module = THIS_MODULE;;
/* Since this is really a block driver, the SCSI core may not be /* Since this is really a block driver, the SCSI core may not be
initialized yet, in which case, calling scsi_register_host initialized at init time, in which case, calling scsi_register_host
would hang. instead, we will do it later, via /proc filesystem would hang. Instead, we do it later, via /proc filesystem
and rc scripts, when we know SCSI core is good to go. */ and rc scripts, when we know SCSI core is good to go. */
if (this_is_init_time) {
CPQ_TAPE_UNLOCK(ctlr, flags);
return 0;
}
/* Only register if SCSI devices are detected. */ /* Only register if SCSI devices are detected. */
if (ccissscsi[ctlr].ndevices != 0) { if (ccissscsi[ctlr].ndevices != 0) {
((struct cciss_scsi_adapter_data_t *) ((struct cciss_scsi_adapter_data_t *)
...@@ -1583,7 +1481,7 @@ cciss_engage_scsi(int ctlr) ...@@ -1583,7 +1481,7 @@ cciss_engage_scsi(int ctlr)
} }
spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags); spin_unlock_irqrestore(CCISS_LOCK(ctlr), flags);
cciss_update_non_disk_devices(ctlr, -1); cciss_update_non_disk_devices(ctlr, -1);
cciss_register_scsi(ctlr, 0); cciss_register_scsi(ctlr);
return 0; return 0;
} }
...@@ -1607,9 +1505,9 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len) ...@@ -1607,9 +1505,9 @@ cciss_proc_tape_report(int ctlr, unsigned char *buffer, off_t *pos, off_t *len)
/* If no tape support, then these become defined out of existence */ /* If no tape support, then these become defined out of existence */
#define cciss_find_non_disk_devices(cntl_num) #define cciss_scsi_setup(cntl_num)
#define cciss_unregister_scsi(ctlr) #define cciss_unregister_scsi(ctlr)
#define cciss_register_scsi(ctlr, this_is_init_time) #define cciss_register_scsi(ctlr)
#define cciss_proc_tape_report(ctlr, buffer, pos, len) #define cciss_proc_tape_report(ctlr, buffer, pos, len)
#endif /* CONFIG_CISS_SCSI_TAPE */ #endif /* CONFIG_CISS_SCSI_TAPE */
...@@ -98,6 +98,8 @@ struct deadline_rq { ...@@ -98,6 +98,8 @@ struct deadline_rq {
unsigned long expires; unsigned long expires;
}; };
static inline void deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq);
static kmem_cache_t *drq_pool; static kmem_cache_t *drq_pool;
#define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private) #define RQ_DATA(rq) ((struct deadline_rq *) (rq)->elevator_private)
...@@ -189,26 +191,22 @@ __deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) ...@@ -189,26 +191,22 @@ __deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
return 0; return 0;
} }
static int static void
deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq) deadline_add_drq_rb(struct deadline_data *dd, struct deadline_rq *drq)
{ {
struct deadline_rq *__alias; struct deadline_rq *__alias;
drq->rb_key = rq_rb_key(drq->request); drq->rb_key = rq_rb_key(drq->request);
retry:
__alias = __deadline_add_drq_rb(dd, drq); __alias = __deadline_add_drq_rb(dd, drq);
if (!__alias) { if (!__alias) {
rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq)); rb_insert_color(&drq->rb_node, DRQ_RB_ROOT(dd, drq));
return 0; return;
} }
/* deadline_move_to_dispatch(dd, __alias);
* this should not typically happen, but if it does simply chain goto retry;
* the two requests. then they will be moved to the dispatch list
* at the same time
*/
list_add(&drq->request->queuelist, &__alias->request->queuelist);
return 1;
} }
static inline void static inline void
...@@ -276,13 +274,12 @@ deadline_add_request(struct deadline_data *dd, struct deadline_rq *drq) ...@@ -276,13 +274,12 @@ deadline_add_request(struct deadline_data *dd, struct deadline_rq *drq)
{ {
const int data_dir = rq_data_dir(drq->request); const int data_dir = rq_data_dir(drq->request);
if (!deadline_add_drq_rb(dd, drq)) { deadline_add_drq_rb(dd, drq);
/* /*
* set expire time (only used for reads) and add to fifo list * set expire time (only used for reads) and add to fifo list
*/ */
drq->expires = jiffies + dd->fifo_expire[data_dir]; drq->expires = jiffies + dd->fifo_expire[data_dir];
list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]); list_add_tail(&drq->fifo, &dd->fifo_list[data_dir]);
}
} }
/* /*
...@@ -425,6 +422,12 @@ deadline_merged_requests(request_queue_t *q, struct request *req, ...@@ -425,6 +422,12 @@ deadline_merged_requests(request_queue_t *q, struct request *req,
static inline void static inline void
deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq) deadline_move_to_dispatch(struct deadline_data *dd, struct deadline_rq *drq)
{ {
request_queue_t *q = drq->request->q;
if (q->last_merge == &drq->request->queuelist)
q->last_merge = NULL;
deadline_del_drq_hash(drq);
deadline_del_drq_rb(dd, drq); deadline_del_drq_rb(dd, drq);
list_del_init(&drq->fifo); list_del_init(&drq->fifo);
list_add_tail(&drq->request->queuelist, dd->dispatch); list_add_tail(&drq->request->queuelist, dd->dispatch);
......
...@@ -399,7 +399,7 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq) ...@@ -399,7 +399,7 @@ struct request *elv_former_request(request_queue_t *q, struct request *rq)
elevator_t *e = &q->elevator; elevator_t *e = &q->elevator;
if (e->elevator_former_req_fn) if (e->elevator_former_req_fn)
return e->elevator_latter_req_fn(q, rq); return e->elevator_former_req_fn(q, rq);
prev = rq->queuelist.prev; prev = rq->queuelist.prev;
if (prev != &q->queue_head && prev != &rq->queuelist) if (prev != &q->queue_head && prev != &rq->queuelist)
......
...@@ -1358,11 +1358,19 @@ static struct request *get_request_wait(request_queue_t *q, int rw) ...@@ -1358,11 +1358,19 @@ static struct request *get_request_wait(request_queue_t *q, int rw)
generic_unplug_device(q); generic_unplug_device(q);
do { do {
int block = 0;
prepare_to_wait_exclusive(&rl->wait, &wait, prepare_to_wait_exclusive(&rl->wait, &wait,
TASK_UNINTERRUPTIBLE); TASK_UNINTERRUPTIBLE);
spin_lock_irq(q->queue_lock);
if (!rl->count) if (!rl->count)
block = 1;
spin_unlock_irq(q->queue_lock);
if (block)
io_schedule(); io_schedule();
finish_wait(&rl->wait, &wait); finish_wait(&rl->wait, &wait);
spin_lock_irq(q->queue_lock); spin_lock_irq(q->queue_lock);
rq = get_request(q, rw); rq = get_request(q, rw);
spin_unlock_irq(q->queue_lock); spin_unlock_irq(q->queue_lock);
...@@ -1596,13 +1604,9 @@ void blk_congestion_wait(int rw, long timeout) ...@@ -1596,13 +1604,9 @@ void blk_congestion_wait(int rw, long timeout)
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
struct congestion_state *cs = &congestion_states[rw]; struct congestion_state *cs = &congestion_states[rw];
if (!atomic_read(&cs->nr_active_queues))
return;
blk_run_queues(); blk_run_queues();
prepare_to_wait(&cs->wqh, &wait, TASK_UNINTERRUPTIBLE); prepare_to_wait(&cs->wqh, &wait, TASK_UNINTERRUPTIBLE);
if (atomic_read(&cs->nr_active_queues)) io_schedule_timeout(timeout);
io_schedule_timeout(timeout);
finish_wait(&cs->wqh, &wait); finish_wait(&cs->wqh, &wait);
} }
......
...@@ -2233,6 +2233,23 @@ static int probe_si (struct sx_board *board) ...@@ -2233,6 +2233,23 @@ static int probe_si (struct sx_board *board)
return 0; return 0;
} }
/* Now we're pretty much convinced that there is an SI board here,
but to prevent trouble, we'd better double check that we don't
have an SI1 board when we're probing for an SI2 board.... */
write_sx_byte (board, SI2_ISA_ID_BASE,0x10);
if ( IS_SI1_BOARD(board)) {
/* This should be an SI1 board, which has this
location writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) != 0x10)
return 0;
} else {
/* This should be an SI2 board, which has the bottom
3 bits non-writable... */
if (read_sx_byte (board, SI2_ISA_ID_BASE) == 0x10)
return 0;
}
printheader (); printheader ();
printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base); printk (KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
......
...@@ -18,6 +18,8 @@ obj-$(CONFIG_IEEE1394_CMP) += cmp.o ...@@ -18,6 +18,8 @@ obj-$(CONFIG_IEEE1394_CMP) += cmp.o
clean-files := oui.c clean-files := oui.c
ieee1394.o: $(ieee1394-objs)
$(LD) $(LDFLAGS) -r -o $@ $(ieee1394-objs)
ifeq ($(obj),) ifeq ($(obj),)
obj = . obj = .
......
...@@ -598,6 +598,8 @@ static struct buffer *buffer_alloc(int size) ...@@ -598,6 +598,8 @@ static struct buffer *buffer_alloc(int size)
struct buffer *b; struct buffer *b;
b = kmalloc(sizeof *b + size, SLAB_KERNEL); b = kmalloc(sizeof *b + size, SLAB_KERNEL);
if (b == NULL)
return NULL;
b->head = 0; b->head = 0;
b->tail = 0; b->tail = 0;
b->length = 0; b->length = 0;
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
#ifndef __AMDTP_H #ifndef __AMDTP_H
#define __AMDTP_H #define __AMDTP_H
#include <asm/ioctl.h>
#include <asm/types.h> #include <asm/types.h>
#include "ieee1394-ioctl.h"
/* The userspace interface for the Audio & Music Data Transmission /* The userspace interface for the Audio & Music Data Transmission
* Protocol driver is really simple. First, open /dev/amdtp, use the * Protocol driver is really simple. First, open /dev/amdtp, use the
...@@ -57,13 +57,6 @@ ...@@ -57,13 +57,6 @@
* *
*/ */
/* We use '#' for our ioctl magic number because it's cool. */
#define AMDTP_IOC_CHANNEL _IOW('#', 0, sizeof (struct amdtp_ioctl))
#define AMDTP_IOC_PLUG _IOW('#', 1, sizeof (struct amdtp_ioctl))
#define AMDTP_IOC_PING _IOW('#', 2, sizeof (struct amdtp_ioctl))
#define AMDTP_IOC_ZAP _IO('#', 3)
enum { enum {
AMDTP_FORMAT_RAW, AMDTP_FORMAT_RAW,
AMDTP_FORMAT_IEC958_PCM, AMDTP_FORMAT_IEC958_PCM,
......
...@@ -25,9 +25,8 @@ void dma_prog_region_init(struct dma_prog_region *prog) ...@@ -25,9 +25,8 @@ void dma_prog_region_init(struct dma_prog_region *prog)
int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev) int dma_prog_region_alloc(struct dma_prog_region *prog, unsigned long n_bytes, struct pci_dev *dev)
{ {
/* round up to page size */ /* round up to page size */
if(n_bytes % PAGE_SIZE) n_bytes = round_up_to_page(n_bytes);
n_bytes += PAGE_SIZE - (n_bytes & PAGE_SIZE);
prog->n_pages = n_bytes / PAGE_SIZE; prog->n_pages = n_bytes / PAGE_SIZE;
prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr); prog->kvirt = pci_alloc_consistent(dev, prog->n_pages * PAGE_SIZE, &prog->bus_addr);
...@@ -47,7 +46,7 @@ void dma_prog_region_free(struct dma_prog_region *prog) ...@@ -47,7 +46,7 @@ void dma_prog_region_free(struct dma_prog_region *prog)
if(prog->kvirt) { if(prog->kvirt) {
pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr); pci_free_consistent(prog->dev, prog->n_pages * PAGE_SIZE, prog->kvirt, prog->bus_addr);
} }
prog->kvirt = NULL; prog->kvirt = NULL;
prog->dev = NULL; prog->dev = NULL;
prog->n_pages = 0; prog->n_pages = 0;
...@@ -70,11 +69,10 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d ...@@ -70,11 +69,10 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
unsigned int i, n_pages; unsigned int i, n_pages;
/* round up to page size */ /* round up to page size */
if(n_bytes % PAGE_SIZE) n_bytes = round_up_to_page(n_bytes);
n_bytes += PAGE_SIZE - (n_bytes & PAGE_SIZE);
n_pages = n_bytes / PAGE_SIZE; n_pages = n_bytes / PAGE_SIZE;
dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE); dma->kvirt = vmalloc_32(n_pages * PAGE_SIZE);
if(!dma->kvirt) { if(!dma->kvirt) {
printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n"); printk(KERN_ERR "dma_region_alloc: vmalloc_32() failed\n");
...@@ -82,7 +80,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d ...@@ -82,7 +80,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
} }
dma->n_pages = n_pages; dma->n_pages = n_pages;
/* Clear the ram out, no junk to the user */ /* Clear the ram out, no junk to the user */
memset(dma->kvirt, 0, n_pages * PAGE_SIZE); memset(dma->kvirt, 0, n_pages * PAGE_SIZE);
...@@ -114,7 +112,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d ...@@ -114,7 +112,7 @@ int dma_region_alloc(struct dma_region *dma, unsigned long n_bytes, struct pci_d
dma->dev = dev; dma->dev = dev;
dma->direction = direction; dma->direction = direction;
return 0; return 0;
err: err:
...@@ -148,7 +146,7 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset, ...@@ -148,7 +146,7 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
{ {
int i; int i;
unsigned long off = offset; unsigned long off = offset;
for(i = 0; i < dma->n_dma_pages; i++) { for(i = 0; i < dma->n_dma_pages; i++) {
if(off < sg_dma_len(&dma->sglist[i])) { if(off < sg_dma_len(&dma->sglist[i])) {
*rem = off; *rem = off;
...@@ -157,14 +155,14 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset, ...@@ -157,14 +155,14 @@ static inline int dma_region_find(struct dma_region *dma, unsigned long offset,
off -= sg_dma_len(&dma->sglist[i]); off -= sg_dma_len(&dma->sglist[i]);
} }
panic("dma_region_find: offset %lu beyond end of DMA mapping\n", offset); panic("dma_region_find: offset %lu beyond end of DMA mapping\n", offset);
} }
dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset) dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset)
{ {
unsigned long rem; unsigned long rem;
struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)]; struct scatterlist *sg = &dma->sglist[dma_region_find(dma, offset, &rem)];
return sg_dma_address(sg) + rem; return sg_dma_address(sg) + rem;
} }
...@@ -176,10 +174,10 @@ void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long ...@@ -176,10 +174,10 @@ void dma_region_sync(struct dma_region *dma, unsigned long offset, unsigned long
if(!len) if(!len)
len = 1; len = 1;
first = dma_region_find(dma, offset, &rem); first = dma_region_find(dma, offset, &rem);
last = dma_region_find(dma, offset + len - 1, &rem); last = dma_region_find(dma, offset + len - 1, &rem);
pci_dma_sync_sg(dma->dev, &dma->sglist[first], last - first + 1, dma->direction); pci_dma_sync_sg(dma->dev, &dma->sglist[first], last - first + 1, dma->direction);
} }
...@@ -210,13 +208,13 @@ dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int wri ...@@ -210,13 +208,13 @@ dma_region_pagefault(struct vm_area_struct *area, unsigned long address, int wri
} }
static struct vm_operations_struct dma_region_vm_ops = { static struct vm_operations_struct dma_region_vm_ops = {
nopage: dma_region_pagefault, .nopage = dma_region_pagefault,
}; };
int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma) int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_struct *vma)
{ {
unsigned long size; unsigned long size;
if(!dma->kvirt) if(!dma->kvirt)
return -EINVAL; return -EINVAL;
...@@ -233,6 +231,6 @@ int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_st ...@@ -233,6 +231,6 @@ int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_st
vma->vm_private_data = dma; vma->vm_private_data = dma;
vma->vm_file = file; vma->vm_file = file;
vma->vm_flags |= VM_RESERVED; vma->vm_flags |= VM_RESERVED;
return 0; return 0;
} }
...@@ -73,4 +73,12 @@ int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_s ...@@ -73,4 +73,12 @@ int dma_region_mmap(struct dma_region *dma, struct file *file, struct vm_area_s
relative to the beginning of the dma_region */ relative to the beginning of the dma_region */
dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset); dma_addr_t dma_region_offset_to_bus(struct dma_region *dma, unsigned long offset);
/* round up a number of bytes to be a multiple of the PAGE_SIZE */
static inline unsigned long round_up_to_page(unsigned long len)
{
if(len % PAGE_SIZE)
len += PAGE_SIZE - (len % PAGE_SIZE);
return len;
}
#endif /* IEEE1394_DMA_H */ #endif /* IEEE1394_DMA_H */
...@@ -918,6 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init) ...@@ -918,6 +918,7 @@ static int do_dv1394_init(struct video_card *video, struct dv1394_init *init)
u64 chan_mask; u64 chan_mask;
int retval = -EINVAL; int retval = -EINVAL;
debug_printk( "dv1394: initialising %d\n", video->id );
if(init->api_version != DV1394_API_VERSION) if(init->api_version != DV1394_API_VERSION)
goto err; goto err;
...@@ -1186,6 +1187,7 @@ static void stop_dma(struct video_card *video) ...@@ -1186,6 +1187,7 @@ static void stop_dma(struct video_card *video)
if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) || if( (reg_read(video->ohci, video->ohci_IsoXmitContextControlClear) & (1 << 10)) ||
(reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) { (reg_read(video->ohci, video->ohci_IsoRcvContextControlClear) & (1 << 10)) ) {
/* still active */ /* still active */
debug_printk("dv1394: stop_dma: DMA not stopped yet\n" );
mb(); mb();
} else { } else {
debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10); debug_printk("dv1394: stop_dma: DMA stopped safely after %d ms\n", i/10);
...@@ -1199,7 +1201,9 @@ static void stop_dma(struct video_card *video) ...@@ -1199,7 +1201,9 @@ static void stop_dma(struct video_card *video)
printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10); printk(KERN_ERR "dv1394: stop_dma: DMA still going after %d ms!\n", i/10);
} }
} }
else
debug_printk("dv1394: stop_dma: already stopped.\n");
spin_unlock_irqrestore(&video->spinlock, flags); spin_unlock_irqrestore(&video->spinlock, flags);
} }
...@@ -1226,7 +1230,8 @@ static int do_dv1394_shutdown(struct video_card *video, int free_dv_buf) ...@@ -1226,7 +1230,8 @@ static int do_dv1394_shutdown(struct video_card *video, int free_dv_buf)
/* disable interrupts for IT context */ /* disable interrupts for IT context */
reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx)); reg_write(video->ohci, OHCI1394_IsoXmitIntMaskClear, (1 << video->ohci_it_ctx));
clear_bit(video->ohci_it_ctx, &video->ohci->it_ctx_usage); /* remove tasklet */
ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet);
debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx); debug_printk("dv1394: IT context %d released\n", video->ohci_it_ctx);
video->ohci_it_ctx = -1; video->ohci_it_ctx = -1;
} }
...@@ -1240,23 +1245,14 @@ static int do_dv1394_shutdown(struct video_card *video, int free_dv_buf) ...@@ -1240,23 +1245,14 @@ static int do_dv1394_shutdown(struct video_card *video, int free_dv_buf)
/* disable interrupts for IR context */ /* disable interrupts for IR context */
reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx)); reg_write(video->ohci, OHCI1394_IsoRecvIntMaskClear, (1 << video->ohci_ir_ctx));
clear_bit(video->ohci_ir_ctx, &video->ohci->ir_ctx_usage); /* remove tasklet */
ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet);
debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx); debug_printk("dv1394: IR context %d released\n", video->ohci_ir_ctx);
video->ohci_ir_ctx = -1; video->ohci_ir_ctx = -1;
} }
spin_unlock_irqrestore(&video->spinlock, flags); spin_unlock_irqrestore(&video->spinlock, flags);
/* remove tasklets */
if(video->ohci_it_ctx != -1) {
ohci1394_unregister_iso_tasklet(video->ohci, &video->it_tasklet);
video->ohci_it_ctx = -1;
}
if(video->ohci_ir_ctx != -1) {
ohci1394_unregister_iso_tasklet(video->ohci, &video->ir_tasklet);
video->ohci_ir_ctx = -1;
}
/* release the ISO channel */ /* release the ISO channel */
if(video->channel != -1) { if(video->channel != -1) {
u64 chan_mask; u64 chan_mask;
...@@ -1612,7 +1608,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, ...@@ -1612,7 +1608,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file,
switch(cmd) switch(cmd)
{ {
case DV1394_SUBMIT_FRAMES: { case DV1394_IOC_SUBMIT_FRAMES: {
unsigned int n_submit; unsigned int n_submit;
if( !video_card_initialized(video) ) { if( !video_card_initialized(video) ) {
...@@ -1666,7 +1662,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, ...@@ -1666,7 +1662,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file,
break; break;
} }
case DV1394_WAIT_FRAMES: { case DV1394_IOC_WAIT_FRAMES: {
unsigned int n_wait; unsigned int n_wait;
if( !video_card_initialized(video) ) { if( !video_card_initialized(video) ) {
...@@ -1715,7 +1711,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, ...@@ -1715,7 +1711,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file,
break; break;
} }
case DV1394_RECEIVE_FRAMES: { case DV1394_IOC_RECEIVE_FRAMES: {
unsigned int n_recv; unsigned int n_recv;
if( !video_card_initialized(video) ) { if( !video_card_initialized(video) ) {
...@@ -1748,7 +1744,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, ...@@ -1748,7 +1744,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file,
break; break;
} }
case DV1394_START_RECEIVE: { case DV1394_IOC_START_RECEIVE: {
if( !video_card_initialized(video) ) { if( !video_card_initialized(video) ) {
ret = do_dv1394_init_default(video); ret = do_dv1394_init_default(video);
if(ret) if(ret)
...@@ -1765,7 +1761,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, ...@@ -1765,7 +1761,7 @@ static int dv1394_ioctl(struct inode *inode, struct file *file,
break; break;
} }
case DV1394_INIT: { case DV1394_IOC_INIT: {
struct dv1394_init init; struct dv1394_init init;
if(arg == (unsigned long) NULL) { if(arg == (unsigned long) NULL) {
ret = do_dv1394_init_default(video); ret = do_dv1394_init_default(video);
...@@ -1779,12 +1775,12 @@ static int dv1394_ioctl(struct inode *inode, struct file *file, ...@@ -1779,12 +1775,12 @@ static int dv1394_ioctl(struct inode *inode, struct file *file,
break; break;
} }
case DV1394_SHUTDOWN: case DV1394_IOC_SHUTDOWN:
ret = do_dv1394_shutdown(video, 0); ret = do_dv1394_shutdown(video, 0);
break; break;
case DV1394_GET_STATUS: { case DV1394_IOC_GET_STATUS: {
struct dv1394_status status; struct dv1394_status status;
if( !video_card_initialized(video) ) { if( !video_card_initialized(video) ) {
...@@ -2346,6 +2342,7 @@ static void ir_tasklet_func(unsigned long data) ...@@ -2346,6 +2342,7 @@ static void ir_tasklet_func(unsigned long data)
dbc = (int) (p->cip_h1 >> 24); dbc = (int) (p->cip_h1 >> 24);
if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) ) if ( video->continuity_counter != -1 && dbc > ((video->continuity_counter + 1) % 256) )
{ {
printk(KERN_WARNING "dv1394: discontinuity detected, dropping all frames\n" );
video->dropped_frames += video->n_clear_frames + 1; video->dropped_frames += video->n_clear_frames + 1;
video->first_frame = 0; video->first_frame = 0;
video->n_clear_frames = 0; video->n_clear_frames = 0;
...@@ -2364,9 +2361,8 @@ static void ir_tasklet_func(unsigned long data) ...@@ -2364,9 +2361,8 @@ static void ir_tasklet_func(unsigned long data)
video->n_clear_frames++; video->n_clear_frames++;
if (video->n_clear_frames > video->n_frames) { if (video->n_clear_frames > video->n_frames) {
video->dropped_frames++; video->dropped_frames++;
video->n_clear_frames--; printk(KERN_WARNING "dv1394: dropped a frame during reception\n" );
if (video->n_clear_frames < 0) video->n_clear_frames = video->n_frames-1;
video->n_clear_frames = 0;
video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames; video->first_clear_frame = (video->first_clear_frame + 1) % video->n_frames;
} }
if (video->first_clear_frame == -1) if (video->first_clear_frame == -1)
...@@ -2375,7 +2371,6 @@ static void ir_tasklet_func(unsigned long data) ...@@ -2375,7 +2371,6 @@ static void ir_tasklet_func(unsigned long data)
/* get the next frame */ /* get the next frame */
video->active_frame = (video->active_frame + 1) % video->n_frames; video->active_frame = (video->active_frame + 1) % video->n_frames;
f = video->frames[video->active_frame]; f = video->frames[video->active_frame];
irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n", irq_printk(" frame received, active_frame = %d, n_clear_frames = %d, first_clear_frame = %d\n",
video->active_frame, video->n_clear_frames, video->first_clear_frame); video->active_frame, video->n_clear_frames, video->first_clear_frame);
} }
......
...@@ -200,48 +200,7 @@ ...@@ -200,48 +200,7 @@
/* ioctl() commands */ /* ioctl() commands */
#include "ieee1394-ioctl.h"
enum {
/* I don't like using 0 as a valid ioctl() */
DV1394_INVALID = 0,
/* get the driver ready to transmit video.
pass a struct dv1394_init* as the parameter (see below),
or NULL to get default parameters */
DV1394_INIT,
/* stop transmitting video and free the ringbuffer */
DV1394_SHUTDOWN,
/* submit N new frames to be transmitted, where
the index of the first new frame is first_clear_buffer,
and the index of the last new frame is
(first_clear_buffer + N) % n_frames */
DV1394_SUBMIT_FRAMES,
/* block until N buffers are clear (pass N as the parameter)
Because we re-transmit the last frame on underrun, there
will at most be n_frames - 1 clear frames at any time */
DV1394_WAIT_FRAMES,
/* capture new frames that have been received, where
the index of the first new frame is first_clear_buffer,
and the index of the last new frame is
(first_clear_buffer + N) % n_frames */
DV1394_RECEIVE_FRAMES,
DV1394_START_RECEIVE,
/* pass a struct dv1394_status* as the parameter (see below) */
DV1394_GET_STATUS,
};
enum pal_or_ntsc { enum pal_or_ntsc {
......
...@@ -77,7 +77,7 @@ ...@@ -77,7 +77,7 @@
printk(KERN_ERR fmt, ## args) printk(KERN_ERR fmt, ## args)
static char version[] __devinitdata = static char version[] __devinitdata =
"$Rev: 641 $ Ben Collins <bcollins@debian.org>"; "$Rev: 770 $ Ben Collins <bcollins@debian.org>";
/* Our ieee1394 highlevel driver */ /* Our ieee1394 highlevel driver */
#define ETHER1394_DRIVER_NAME "ether1394" #define ETHER1394_DRIVER_NAME "ether1394"
...@@ -368,6 +368,7 @@ static void ether1394_add_host (struct hpsb_host *host) ...@@ -368,6 +368,7 @@ static void ether1394_add_host (struct hpsb_host *host)
if (register_netdev (dev)) { if (register_netdev (dev)) {
ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n"); ETH1394_PRINT (KERN_ERR, dev->name, "Error registering network driver\n");
kfree (dev); kfree (dev);
kfree (hi);
return; return;
} }
......
...@@ -164,17 +164,19 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start) ...@@ -164,17 +164,19 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start)
return retval; return retval;
} }
void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel) unsigned int channel)
{ {
if (channel > 63) { if (channel > 63) {
HPSB_ERR("%s called with invalid channel", __FUNCTION__); HPSB_ERR("%s called with invalid channel", __FUNCTION__);
return; return -EINVAL;
} }
if (host->iso_listen_count[channel]++ == 0) { if (host->iso_listen_count[channel]++ == 0) {
host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel); return host->driver->devctl(host, ISO_LISTEN_CHANNEL, channel);
} }
return 0;
} }
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
......
...@@ -150,8 +150,8 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start); ...@@ -150,8 +150,8 @@ int hpsb_unregister_addrspace(struct hpsb_highlevel *hl, u64 start);
* Enable or disable receving a certain isochronous channel through the * Enable or disable receving a certain isochronous channel through the
* iso_receive op. * iso_receive op.
*/ */
void hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, int hpsb_listen_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel); unsigned int channel);
void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host, void hpsb_unlisten_channel(struct hpsb_highlevel *hl, struct hpsb_host *host,
unsigned int channel); unsigned int channel);
......
...@@ -38,9 +38,15 @@ static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg) ...@@ -38,9 +38,15 @@ static int dummy_devctl(struct hpsb_host *h, enum devctl_cmd c, int arg)
return -1; return -1;
} }
static int dummy_isoctl(struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg)
{
return -1;
}
static struct hpsb_host_driver dummy_driver = { static struct hpsb_host_driver dummy_driver = {
.transmit_packet = dummy_transmit_packet, .transmit_packet = dummy_transmit_packet,
.devctl = dummy_devctl .devctl = dummy_devctl,
.isoctl = dummy_isoctl
}; };
/** /**
...@@ -63,9 +69,11 @@ int hpsb_ref_host(struct hpsb_host *host) ...@@ -63,9 +69,11 @@ int hpsb_ref_host(struct hpsb_host *host)
spin_lock_irqsave(&hosts_lock, flags); spin_lock_irqsave(&hosts_lock, flags);
list_for_each(lh, &hosts) { list_for_each(lh, &hosts) {
if (host == list_entry(lh, struct hpsb_host, host_list)) { if (host == list_entry(lh, struct hpsb_host, host_list)) {
host->driver->devctl(host, MODIFY_USAGE, 1); if (host->driver->devctl(host, MODIFY_USAGE, 1)) {
host->refcount++; host->driver->devctl(host, MODIFY_USAGE, 1);
retval = 1; host->refcount++;
retval = 1;
}
break; break;
} }
} }
......
...@@ -108,19 +108,22 @@ enum devctl_cmd { ...@@ -108,19 +108,22 @@ enum devctl_cmd {
enum isoctl_cmd { enum isoctl_cmd {
/* rawiso API - see iso.h for the meanings of these commands /* rawiso API - see iso.h for the meanings of these commands
* INIT = allocate resources * INIT = allocate resources
* START = begin transmission/reception (arg: cycle to start on) * START = begin transmission/reception
* STOP = halt transmission/reception * STOP = halt transmission/reception
* QUEUE/RELEASE = produce/consume packets (arg: # of packets) * QUEUE/RELEASE = produce/consume packets
* SHUTDOWN = deallocate resources * SHUTDOWN = deallocate resources
*/ */
XMIT_INIT, XMIT_INIT,
XMIT_START, XMIT_START,
XMIT_STOP, XMIT_STOP,
XMIT_QUEUE, XMIT_QUEUE,
XMIT_SHUTDOWN, XMIT_SHUTDOWN,
RECV_INIT, RECV_INIT,
RECV_LISTEN_CHANNEL, /* multi-channel only */
RECV_UNLISTEN_CHANNEL, /* multi-channel only */
RECV_SET_CHANNEL_MASK, /* multi-channel only; arg is a *u64 */
RECV_START, RECV_START,
RECV_STOP, RECV_STOP,
RECV_RELEASE, RECV_RELEASE,
...@@ -170,11 +173,12 @@ struct hpsb_host_driver { ...@@ -170,11 +173,12 @@ struct hpsb_host_driver {
*/ */
int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg); int (*devctl) (struct hpsb_host *host, enum devctl_cmd command, int arg);
/* ISO transmission/reception functions. Return 0 on success, -1 on failure. /* ISO transmission/reception functions. Return 0 on success, -1
* If the low-level driver does not support the new ISO API, set isoctl to NULL. * (or -EXXX errno code) on failure. If the low-level driver does not
* support the new ISO API, set isoctl to NULL.
*/ */
int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, int arg); int (*isoctl) (struct hpsb_iso *iso, enum isoctl_cmd command, unsigned long arg);
/* This function is mainly to redirect local CSR reads/locks to the iso /* This function is mainly to redirect local CSR reads/locks to the iso
* management registers (bus manager id, bandwidth available, channels * management registers (bus manager id, bandwidth available, channels
* available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus * available) to the hardware registers in OHCI. reg is 0,1,2,3 for bus
......
/* Base file for all ieee1394 ioctl's. Linux-1394 has allocated base '#'
* with a range of 0x00-0x3f. */
#ifndef __IEEE1394_IOCTL_H
#define __IEEE1394_IOCTL_H
#include <asm/ioctl.h>
#include <asm/types.h>
/* AMDTP Gets 6 */
#define AMDTP_IOC_CHANNEL _IOW('#', 0x00, struct amdtp_ioctl)
#define AMDTP_IOC_PLUG _IOW('#', 0x01, struct amdtp_ioctl)
#define AMDTP_IOC_PING _IOW('#', 0x02, struct amdtp_ioctl)
#define AMDTP_IOC_ZAP _IO ('#', 0x03)
/* DV1394 Gets 10 */
/* Get the driver ready to transmit video. pass a struct dv1394_init* as
* the parameter (see below), or NULL to get default parameters */
#define DV1394_IOC_INIT _IOW('#', 0x06, struct dv1394_init)
/* Stop transmitting video and free the ringbuffer */
#define DV1394_IOC_SHUTDOWN _IO ('#', 0x07)
/* Submit N new frames to be transmitted, where the index of the first new
* frame is first_clear_buffer, and the index of the last new frame is
* (first_clear_buffer + N) % n_frames */
#define DV1394_IOC_SUBMIT_FRAMES _IO ('#', 0x08)
/* Block until N buffers are clear (pass N as the parameter) Because we
* re-transmit the last frame on underrun, there will at most be n_frames
* - 1 clear frames at any time */
#define DV1394_IOC_WAIT_FRAMES _IO ('#', 0x09)
/* Capture new frames that have been received, where the index of the
* first new frame is first_clear_buffer, and the index of the last new
* frame is (first_clear_buffer + N) % n_frames */
#define DV1394_IOC_RECEIVE_FRAMES _IO ('#', 0x0a)
/* Tell card to start receiving DMA */
#define DV1394_IOC_START_RECEIVE _IO ('#', 0x0b)
/* Pass a struct dv1394_status* as the parameter */
#define DV1394_IOC_GET_STATUS _IOR('#', 0x0c, struct dv1394_status)
/* Video1394 Gets 10 */
#define VIDEO1394_IOC_LISTEN_CHANNEL \
_IOWR('#', 0x10, struct video1394_mmap)
#define VIDEO1394_IOC_UNLISTEN_CHANNEL \
_IOW ('#', 0x11, int)
#define VIDEO1394_IOC_LISTEN_QUEUE_BUFFER \
_IOW ('#', 0x12, struct video1394_wait)
#define VIDEO1394_IOC_LISTEN_WAIT_BUFFER \
_IOWR('#', 0x13, struct video1394_wait)
#define VIDEO1394_IOC_TALK_CHANNEL \
_IOWR('#', 0x14, struct video1394_mmap)
#define VIDEO1394_IOC_UNTALK_CHANNEL \
_IOW ('#', 0x15, int)
#define VIDEO1394_IOC_TALK_QUEUE_BUFFER \
_IOW ('#', 0x16, sizeof (struct video1394_wait) + \
sizeof (struct video1394_queue_variable))
#define VIDEO1394_IOC_TALK_WAIT_BUFFER \
_IOW ('#', 0x17, struct video1394_wait)
#define VIDEO1394_IOC_LISTEN_POLL_BUFFER \
_IOWR('#', 0x18, struct video1394_wait)
/* Raw1394's ISO interface */
#define RAW1394_IOC_ISO_XMIT_INIT \
_IOW ('#', 0x1a, struct raw1394_iso_status)
#define RAW1394_IOC_ISO_RECV_INIT \
_IOWR('#', 0x1b, struct raw1394_iso_status)
#define RAW1394_IOC_ISO_RECV_START \
_IOC (_IOC_WRITE, '#', 0x1c, sizeof(int) * 3)
#define RAW1394_IOC_ISO_XMIT_START \
_IOC (_IOC_WRITE, '#', 0x1d, sizeof(int) * 2)
#define RAW1394_IOC_ISO_XMIT_RECV_STOP \
_IO ('#', 0x1e)
#define RAW1394_IOC_ISO_GET_STATUS \
_IOR ('#', 0x1f, struct raw1394_iso_status)
#define RAW1394_IOC_ISO_SHUTDOWN \
_IO ('#', 0x20)
#define RAW1394_IOC_ISO_QUEUE_ACTIVITY \
_IO ('#', 0x21)
#define RAW1394_IOC_ISO_RECV_LISTEN_CHANNEL \
_IOW ('#', 0x22, unsigned char)
#define RAW1394_IOC_ISO_RECV_UNLISTEN_CHANNEL \
_IOW ('#', 0x23, unsigned char)
#define RAW1394_IOC_ISO_RECV_SET_CHANNEL_MASK \
_IOW ('#', 0x24, u64)
#define RAW1394_IOC_ISO_RECV_PACKETS \
_IOW ('#', 0x25, struct raw1394_iso_packets)
#define RAW1394_IOC_ISO_RECV_RELEASE_PACKETS \
_IOW ('#', 0x26, unsigned int)
#define RAW1394_IOC_ISO_XMIT_PACKETS \
_IOW ('#', 0x27, struct raw1394_iso_packets)
#define RAW1394_IOC_ISO_XMIT_SYNC \
_IO ('#', 0x28)
#endif /* __IEEE1394_IOCTL_H */
...@@ -1000,7 +1000,7 @@ int ieee1394_register_chardev(int blocknum, ...@@ -1000,7 +1000,7 @@ int ieee1394_register_chardev(int blocknum,
struct file_operations *file_ops) struct file_operations *file_ops)
{ {
int retval; int retval;
if( (blocknum < 0) || (blocknum > 15) ) if( (blocknum < 0) || (blocknum > 15) )
return -EINVAL; return -EINVAL;
...@@ -1016,7 +1016,7 @@ int ieee1394_register_chardev(int blocknum, ...@@ -1016,7 +1016,7 @@ int ieee1394_register_chardev(int blocknum,
/* block already taken */ /* block already taken */
retval = -EBUSY; retval = -EBUSY;
} }
write_unlock(&ieee1394_chardevs_lock); write_unlock(&ieee1394_chardevs_lock);
return retval; return retval;
...@@ -1027,14 +1027,14 @@ void ieee1394_unregister_chardev(int blocknum) ...@@ -1027,14 +1027,14 @@ void ieee1394_unregister_chardev(int blocknum)
{ {
if( (blocknum < 0) || (blocknum > 15) ) if( (blocknum < 0) || (blocknum > 15) )
return; return;
write_lock(&ieee1394_chardevs_lock); write_lock(&ieee1394_chardevs_lock);
if(ieee1394_chardevs[blocknum].file_ops) { if(ieee1394_chardevs[blocknum].file_ops) {
ieee1394_chardevs[blocknum].file_ops = NULL; ieee1394_chardevs[blocknum].file_ops = NULL;
ieee1394_chardevs[blocknum].module = NULL; ieee1394_chardevs[blocknum].module = NULL;
} }
write_unlock(&ieee1394_chardevs_lock); write_unlock(&ieee1394_chardevs_lock);
} }
...@@ -1055,7 +1055,7 @@ static int ieee1394_get_chardev(int blocknum, ...@@ -1055,7 +1055,7 @@ static int ieee1394_get_chardev(int blocknum,
{ {
int ret = 0; int ret = 0;
if( (blocknum < 0) || (blocknum > 15) ) if ((blocknum < 0) || (blocknum > 15))
return ret; return ret;
read_lock(&ieee1394_chardevs_lock); read_lock(&ieee1394_chardevs_lock);
...@@ -1063,15 +1063,15 @@ static int ieee1394_get_chardev(int blocknum, ...@@ -1063,15 +1063,15 @@ static int ieee1394_get_chardev(int blocknum,
*module = ieee1394_chardevs[blocknum].module; *module = ieee1394_chardevs[blocknum].module;
*file_ops = ieee1394_chardevs[blocknum].file_ops; *file_ops = ieee1394_chardevs[blocknum].file_ops;
if(*file_ops == NULL) if (*file_ops == NULL)
goto out; goto out;
if(!try_module_get(*module)) if (!try_module_get(*module))
goto out; goto out;
/* success! */ /* success! */
ret = 1; ret = 1;
out: out:
read_unlock(&ieee1394_chardevs_lock); read_unlock(&ieee1394_chardevs_lock);
return ret; return ret;
...@@ -1101,11 +1101,11 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file) ...@@ -1101,11 +1101,11 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
reference count of whatever module file->f_op->owner points reference count of whatever module file->f_op->owner points
to, immediately after this function returns. to, immediately after this function returns.
*/ */
/* shift away lower four bits of the minor /* shift away lower four bits of the minor
to get the index of the ieee1394_driver to get the index of the ieee1394_driver
we want */ we want */
blocknum = (minor(inode->i_rdev) >> 4) & 0xF; blocknum = (minor(inode->i_rdev) >> 4) & 0xF;
/* look up the driver */ /* look up the driver */
...@@ -1126,14 +1126,14 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file) ...@@ -1126,14 +1126,14 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
if(retval == 0) { if(retval == 0) {
/* If the open() succeeded, then ieee1394 will be left /* If the open() succeeded, then ieee1394 will be left
with an extra module reference, so we discard it here. * with an extra module reference, so we discard it here.
*
The task-specific driver still has the extra * The task-specific driver still has the extra reference
reference given to it by ieee1394_get_chardev(). * given to it by ieee1394_get_chardev(). This extra
This extra reference prevents the module from * reference prevents the module from unloading while the
unloading while the file is open, and will be * file is open, and will be dropped by the VFS when the
dropped by the VFS when the file is released. * file is released. */
*/
module_put(THIS_MODULE); module_put(THIS_MODULE);
} else { } else {
/* point the file's f_ops back to ieee1394. The VFS will then /* point the file's f_ops back to ieee1394. The VFS will then
...@@ -1142,11 +1142,10 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file) ...@@ -1142,11 +1142,10 @@ static int ieee1394_dispatch_open(struct inode *inode, struct file *file)
file->f_op = &ieee1394_chardev_ops; file->f_op = &ieee1394_chardev_ops;
/* if the open() failed, then we need to drop the /* If the open() failed, then we need to drop the extra
extra reference we gave to the task-specific * reference we gave to the task-specific driver. */
driver */
module_put(module); module_put(module);
} }
return retval; return retval;
...@@ -1199,10 +1198,10 @@ static void __exit ieee1394_cleanup(void) ...@@ -1199,10 +1198,10 @@ static void __exit ieee1394_cleanup(void)
kmem_cache_destroy(hpsb_packet_cache); kmem_cache_destroy(hpsb_packet_cache);
unregister_chrdev(IEEE1394_MAJOR, "ieee1394"); unregister_chrdev(IEEE1394_MAJOR, "ieee1394");
/* it's ok to pass a NULL devfs_handle to devfs_unregister */ /* it's ok to pass a NULL devfs_handle to devfs_unregister */
devfs_unregister(ieee1394_devfs_handle); devfs_unregister(ieee1394_devfs_handle);
remove_proc_entry("ieee1394", proc_bus); remove_proc_entry("ieee1394", proc_bus);
} }
...@@ -1298,10 +1297,16 @@ EXPORT_SYMBOL(hpsb_iso_xmit_init); ...@@ -1298,10 +1297,16 @@ EXPORT_SYMBOL(hpsb_iso_xmit_init);
EXPORT_SYMBOL(hpsb_iso_recv_init); EXPORT_SYMBOL(hpsb_iso_recv_init);
EXPORT_SYMBOL(hpsb_iso_xmit_start); EXPORT_SYMBOL(hpsb_iso_xmit_start);
EXPORT_SYMBOL(hpsb_iso_recv_start); EXPORT_SYMBOL(hpsb_iso_recv_start);
EXPORT_SYMBOL(hpsb_iso_recv_listen_channel);
EXPORT_SYMBOL(hpsb_iso_recv_unlisten_channel);
EXPORT_SYMBOL(hpsb_iso_recv_set_channel_mask);
EXPORT_SYMBOL(hpsb_iso_stop); EXPORT_SYMBOL(hpsb_iso_stop);
EXPORT_SYMBOL(hpsb_iso_shutdown); EXPORT_SYMBOL(hpsb_iso_shutdown);
EXPORT_SYMBOL(hpsb_iso_xmit_queue_packets); EXPORT_SYMBOL(hpsb_iso_xmit_queue_packet);
EXPORT_SYMBOL(hpsb_iso_xmit_sync);
EXPORT_SYMBOL(hpsb_iso_recv_release_packets); EXPORT_SYMBOL(hpsb_iso_recv_release_packets);
EXPORT_SYMBOL(hpsb_iso_n_ready); EXPORT_SYMBOL(hpsb_iso_n_ready);
EXPORT_SYMBOL(hpsb_iso_packet_data); EXPORT_SYMBOL(hpsb_iso_packet_sent);
EXPORT_SYMBOL(hpsb_iso_packet_info); EXPORT_SYMBOL(hpsb_iso_packet_received);
EXPORT_SYMBOL(hpsb_iso_wake);
This diff is collapsed.
...@@ -17,25 +17,37 @@ ...@@ -17,25 +17,37 @@
/* high-level ISO interface */ /* high-level ISO interface */
/* per-packet data embedded in the ringbuffer */ /* This API sends and receives isochronous packets on a large,
virtually-contiguous kernel memory buffer. The buffer may be mapped
into a user-space process for zero-copy transmission and reception.
There are no explicit boundaries between packets in the buffer. A
packet may be transmitted or received at any location. However,
low-level drivers may impose certain restrictions on alignment or
size of packets. (e.g. in OHCI no packet may cross a page boundary,
and packets should be quadlet-aligned)
*/
/* Packet descriptor - the API maintains a ring buffer of these packet
descriptors in kernel memory (hpsb_iso.infos[]). */
struct hpsb_iso_packet_info { struct hpsb_iso_packet_info {
unsigned short len; /* offset of data payload relative to the first byte of the buffer */
unsigned short cycle; __u32 offset;
unsigned char channel; /* recv only */
unsigned char tag;
unsigned char sy;
};
/* /* length of the data payload, in bytes (not including the isochronous header) */
* each packet in the ringbuffer consists of three things: __u16 len;
* 1. the packet's data payload (no isochronous header)
* 2. a struct hpsb_iso_packet_info /* (recv only) the cycle number (mod 8000) on which the packet was received */
* 3. some empty space before the next packet __u16 cycle;
*
* packets are separated by hpsb_iso.buf_stride bytes /* (recv only) channel on which the packet was received */
* an even number of packets fit on one page __u8 channel;
* no packet can be larger than one page
*/ /* 2-bit 'tag' and 4-bit 'sy' fields of the isochronous header */
__u8 tag;
__u8 sy;
};
enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 }; enum hpsb_iso_type { HPSB_ISO_RECV = 0, HPSB_ISO_XMIT = 1 };
...@@ -45,48 +57,49 @@ struct hpsb_iso { ...@@ -45,48 +57,49 @@ struct hpsb_iso {
/* pointer to low-level driver and its private data */ /* pointer to low-level driver and its private data */
struct hpsb_host *host; struct hpsb_host *host;
void *hostdata; void *hostdata;
/* function to be called (from interrupt context) when the iso status changes */ /* a function to be called (from interrupt context) after
outgoing packets have been sent, or incoming packets have
arrived */
void (*callback)(struct hpsb_iso*); void (*callback)(struct hpsb_iso*);
/* wait for buffer space */
wait_queue_head_t waitq;
int speed; /* SPEED_100, 200, or 400 */ int speed; /* SPEED_100, 200, or 400 */
int channel; int channel; /* -1 if multichannel */
/* greatest # of packets between interrupts - controls /* greatest # of packets between interrupts - controls
the maximum latency of the buffer */ the maximum latency of the buffer */
int irq_interval; int irq_interval;
/* the packet ringbuffer */ /* the buffer for packet data payloads */
struct dma_region buf; struct dma_region data_buf;
/* size of data_buf, in bytes (always a multiple of PAGE_SIZE) */
unsigned int buf_size;
/* ringbuffer of packet descriptors in regular kernel memory */
struct hpsb_iso_packet_info *infos;
/* # of packets in the ringbuffer */ /* # of packets in the ringbuffer */
unsigned int buf_packets; unsigned int buf_packets;
/* offset between successive packets, in bytes - /* protects packet cursors */
you can assume that this is a power of 2, spinlock_t lock;
and less than or equal to the page size */
int buf_stride;
/* largest possible packet size, in bytes */
unsigned int max_packet_size;
/* offset relative to (buf.kvirt + N*buf_stride) at which
the data payload begins for packet N */
int packet_data_offset;
/* offset relative to (buf.kvirt + N*buf_stride) at which the
struct hpsb_iso_packet_info is stored for packet N */
int packet_info_offset;
/* the index of the next packet that will be produced /* the index of the next packet that will be produced
or consumed by the user */ or consumed by the user */
int first_packet; int first_packet;
/* number of packets owned by the low-level driver and /* the index of the next packet that will be transmitted
queued for transmission or reception. or received by the 1394 hardware */
this is related to the number of packets available int pkt_dma;
to the user process: n_ready = buf_packets - n_dma_packets */
atomic_t n_dma_packets; /* how many packets, starting at first_packet:
(transmit) are ready to be filled with data
(receive) contain received data */
int n_ready_packets;
/* how many times the buffer has overflowed or underflowed */ /* how many times the buffer has overflowed or underflowed */
atomic_t overflows; atomic_t overflows;
...@@ -99,8 +112,12 @@ struct hpsb_iso { ...@@ -99,8 +112,12 @@ struct hpsb_iso {
/* # of packets left to prebuffer (xmit only) */ /* # of packets left to prebuffer (xmit only) */
int prebuffer; int prebuffer;
/* starting cycle (xmit only) */ /* starting cycle for DMA (xmit only) */
int start_cycle; int start_cycle;
/* cycle at which next packet will be transmitted,
-1 if not known */
int xmit_cycle;
}; };
/* functions available to high-level drivers (e.g. raw1394) */ /* functions available to high-level drivers (e.g. raw1394) */
...@@ -108,30 +125,40 @@ struct hpsb_iso { ...@@ -108,30 +125,40 @@ struct hpsb_iso {
/* allocate the buffer and DMA context */ /* allocate the buffer and DMA context */
struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host, struct hpsb_iso* hpsb_iso_xmit_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets, unsigned int buf_packets,
unsigned int max_packet_size,
int channel, int channel,
int speed, int speed,
int irq_interval, int irq_interval,
void (*callback)(struct hpsb_iso*)); void (*callback)(struct hpsb_iso*));
/* note: if channel = -1, multi-channel receive is enabled */
struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host, struct hpsb_iso* hpsb_iso_recv_init(struct hpsb_host *host,
unsigned int data_buf_size,
unsigned int buf_packets, unsigned int buf_packets,
unsigned int max_packet_size,
int channel, int channel,
int irq_interval, int irq_interval,
void (*callback)(struct hpsb_iso*)); void (*callback)(struct hpsb_iso*));
/* multi-channel only */
int hpsb_iso_recv_listen_channel(struct hpsb_iso *iso, unsigned char channel);
int hpsb_iso_recv_unlisten_channel(struct hpsb_iso *iso, unsigned char channel);
int hpsb_iso_recv_set_channel_mask(struct hpsb_iso *iso, u64 mask);
/* start/stop DMA */ /* start/stop DMA */
int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer); int hpsb_iso_xmit_start(struct hpsb_iso *iso, int start_on_cycle, int prebuffer);
int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle); int hpsb_iso_recv_start(struct hpsb_iso *iso, int start_on_cycle, int tag_mask, int sync);
void hpsb_iso_stop(struct hpsb_iso *iso); void hpsb_iso_stop(struct hpsb_iso *iso);
/* deallocate buffer and DMA context */ /* deallocate buffer and DMA context */
void hpsb_iso_shutdown(struct hpsb_iso *iso); void hpsb_iso_shutdown(struct hpsb_iso *iso);
/* N packets have been written to the buffer; queue them for transmission */ /* queue a packet for transmission. 'offset' is relative to the beginning of the
int hpsb_iso_xmit_queue_packets(struct hpsb_iso *xmit, unsigned int n_packets); DMA buffer, where the packet's data payload should already have been placed */
int hpsb_iso_xmit_queue_packet(struct hpsb_iso *iso, u32 offset, u16 len, u8 tag, u8 sy);
/* wait until all queued packets have been transmitted to the bus */
int hpsb_iso_xmit_sync(struct hpsb_iso *iso);
/* N packets have been read out of the buffer, re-use the buffer space */ /* N packets have been read out of the buffer, re-use the buffer space */
int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets); int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets);
...@@ -139,10 +166,19 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets ...@@ -139,10 +166,19 @@ int hpsb_iso_recv_release_packets(struct hpsb_iso *recv, unsigned int n_packets
/* returns # of packets ready to send or receive */ /* returns # of packets ready to send or receive */
int hpsb_iso_n_ready(struct hpsb_iso *iso); int hpsb_iso_n_ready(struct hpsb_iso *iso);
/* returns a pointer to the payload of packet 'pkt' */ /* the following are callbacks available to low-level drivers */
unsigned char* hpsb_iso_packet_data(struct hpsb_iso *iso, unsigned int pkt);
/* call after a packet has been transmitted to the bus (interrupt context is OK)
'cycle' is the _exact_ cycle the packet was sent on
'error' should be non-zero if some sort of error occurred when sending the packet
*/
void hpsb_iso_packet_sent(struct hpsb_iso *iso, int cycle, int error);
/* call after a packet has been received (interrupt context OK) */
void hpsb_iso_packet_received(struct hpsb_iso *iso, u32 offset, u16 len,
u16 cycle, u8 channel, u8 tag, u8 sy);
/* returns a pointer to the info struct of packet 'pkt' */ /* call to wake waiting processes after buffer space has opened up. */
struct hpsb_iso_packet_info* hpsb_iso_packet_info(struct hpsb_iso *iso, unsigned int pkt); void hpsb_iso_wake(struct hpsb_iso *iso);
#endif /* IEEE1394_ISO_H */ #endif /* IEEE1394_ISO_H */
...@@ -1089,8 +1089,7 @@ static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned ...@@ -1089,8 +1089,7 @@ static int read_businfo_block(struct hpsb_host *host, nodeid_t nodeid, unsigned
static void nodemgr_remove_node(struct node_entry *ne) static void nodemgr_remove_node(struct node_entry *ne)
{ {
HPSB_DEBUG("%s removed: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]", HPSB_DEBUG("Device removed: Node[" NODE_BUS_FMT "] GUID[%016Lx] [%s]",
(ne->host->node_id == ne->nodeid) ? "Host" : "Device",
NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid, NODE_BUS_ARGS(ne->nodeid), (unsigned long long)ne->guid,
ne->vendor_name ?: "Unknown"); ne->vendor_name ?: "Unknown");
......
This diff is collapsed.
...@@ -109,6 +109,7 @@ struct dma_rcv_ctx { ...@@ -109,6 +109,7 @@ struct dma_rcv_ctx {
int ctrlClear; int ctrlClear;
int ctrlSet; int ctrlSet;
int cmdPtr; int cmdPtr;
int ctxtMatch;
}; };
/* DMA transmit context */ /* DMA transmit context */
...@@ -145,7 +146,8 @@ struct ohci1394_iso_tasklet { ...@@ -145,7 +146,8 @@ struct ohci1394_iso_tasklet {
struct tasklet_struct tasklet; struct tasklet_struct tasklet;
struct list_head link; struct list_head link;
int context; int context;
enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE } type; enum { OHCI_ISO_TRANSMIT, OHCI_ISO_RECEIVE,
OHCI_ISO_MULTICHANNEL_RECEIVE } type;
}; };
struct ti_ohci { struct ti_ohci {
...@@ -170,7 +172,7 @@ struct ti_ohci { ...@@ -170,7 +172,7 @@ struct ti_ohci {
/* dma buffer for self-id packets */ /* dma buffer for self-id packets */
quadlet_t *selfid_buf_cpu; quadlet_t *selfid_buf_cpu;
dma_addr_t selfid_buf_bus; dma_addr_t selfid_buf_bus;
/* buffer for csr config rom */ /* buffer for csr config rom */
quadlet_t *csr_config_rom_cpu; quadlet_t *csr_config_rom_cpu;
dma_addr_t csr_config_rom_bus; dma_addr_t csr_config_rom_bus;
...@@ -187,18 +189,28 @@ struct ti_ohci { ...@@ -187,18 +189,28 @@ struct ti_ohci {
struct dma_trm_ctx at_req_context; struct dma_trm_ctx at_req_context;
/* iso receive */ /* iso receive */
struct dma_rcv_ctx ir_context;
struct ohci1394_iso_tasklet ir_tasklet;
spinlock_t IR_channel_lock;
int nb_iso_rcv_ctx; int nb_iso_rcv_ctx;
unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */ unsigned long ir_ctx_usage; /* use test_and_set_bit() for atomicity */
unsigned long ir_multichannel_used; /* ditto */
spinlock_t IR_channel_lock;
/* iso receive (legacy API) */
u64 ir_legacy_channels; /* note: this differs from ISO_channel_usage;
it only accounts for channels listened to
by the legacy API, so that we can know when
it is safe to free the legacy API context */
struct dma_rcv_ctx ir_legacy_context;
struct ohci1394_iso_tasklet ir_legacy_tasklet;
/* iso transmit */ /* iso transmit */
struct dma_trm_ctx it_context;
struct ohci1394_iso_tasklet it_tasklet;
int nb_iso_xmit_ctx; int nb_iso_xmit_ctx;
unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */ unsigned long it_ctx_usage; /* use test_and_set_bit() for atomicity */
/* iso transmit (legacy API) */
struct dma_trm_ctx it_legacy_context;
struct ohci1394_iso_tasklet it_legacy_tasklet;
u64 ISO_channel_usage; u64 ISO_channel_usage;
/* IEEE-1394 part follows */ /* IEEE-1394 part follows */
...@@ -213,10 +225,10 @@ struct ti_ohci { ...@@ -213,10 +225,10 @@ struct ti_ohci {
/* Tasklets for iso receive and transmit, used by video1394, /* Tasklets for iso receive and transmit, used by video1394,
* amdtp and dv1394 */ * amdtp and dv1394 */
struct list_head iso_tasklet_list; struct list_head iso_tasklet_list;
spinlock_t iso_tasklet_list_lock; spinlock_t iso_tasklet_list_lock;
/* Swap the selfid buffer? */ /* Swap the selfid buffer? */
unsigned int selfid_swap:1; unsigned int selfid_swap:1;
/* Some Apple chipset seem to swap incoming headers for us */ /* Some Apple chipset seem to swap incoming headers for us */
...@@ -385,7 +397,7 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset) ...@@ -385,7 +397,7 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
/* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */ /* OHCI evt_* error types, table 3-2 of the OHCI 1.1 spec. */
#define EVT_NO_STATUS 0x0 /* No event status */ #define EVT_NO_STATUS 0x0 /* No event status */
#define EVT_RESERVED 0x1 /* Reserved, not used !!! */ #define EVT_RESERVED_A 0x1 /* Reserved, not used !!! */
#define EVT_LONG_PACKET 0x2 /* The revc data was longer than the buf */ #define EVT_LONG_PACKET 0x2 /* The revc data was longer than the buf */
#define EVT_MISSING_ACK 0x3 /* A subaction gap was detected before an ack #define EVT_MISSING_ACK 0x3 /* A subaction gap was detected before an ack
arrived, or recv'd ack had a parity error */ arrived, or recv'd ack had a parity error */
...@@ -404,6 +416,17 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset) ...@@ -404,6 +416,17 @@ static inline u32 reg_read(const struct ti_ohci *ohci, int offset)
16-bit host memory write */ 16-bit host memory write */
#define EVT_BUS_RESET 0x9 /* Identifies a PHY packet in the recv buffer as #define EVT_BUS_RESET 0x9 /* Identifies a PHY packet in the recv buffer as
being a synthesized bus reset packet */ being a synthesized bus reset packet */
#define EVT_TIMEOUT 0xa /* Indicates that the asynchronous transmit response
packet expired and was not transmitted, or that an
IT DMA context experienced a skip processing overflow */
#define EVT_TCODE_ERR 0xb /* A bad tCode is associated with this packet.
The packet was flushed */
#define EVT_RESERVED_B 0xc /* Reserved, not used !!! */
#define EVT_RESERVED_C 0xd /* Reserved, not used !!! */
#define EVT_UNKNOWN 0xe /* An error condition has occurred that cannot be
represented by any other event codes defined herein. */
#define EVT_FLUSHED 0xf /* Send by the link side of output FIFO when asynchronous
packets are being flushed due to a bus reset. */
#define OHCI1394_TCODE_PHY 0xE #define OHCI1394_TCODE_PHY 0xE
...@@ -416,8 +439,8 @@ int ohci1394_register_iso_tasklet(struct ti_ohci *ohci, ...@@ -416,8 +439,8 @@ int ohci1394_register_iso_tasklet(struct ti_ohci *ohci,
void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci, void ohci1394_unregister_iso_tasklet(struct ti_ohci *ohci,
struct ohci1394_iso_tasklet *tasklet); struct ohci1394_iso_tasklet *tasklet);
void ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg); /* returns zero if successful, one if DMA context is locked up */
int ohci1394_stop_context (struct ti_ohci *ohci, int reg, char *msg);
struct ti_ohci *ohci1394_get_struct(int card_num); struct ti_ohci *ohci1394_get_struct(int card_num);
#endif #endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -21,6 +21,8 @@ ...@@ -21,6 +21,8 @@
#ifndef _VIDEO_1394_H #ifndef _VIDEO_1394_H
#define _VIDEO_1394_H #define _VIDEO_1394_H
#include "ieee1394-ioctl.h"
#define VIDEO1394_DRIVER_NAME "video1394" #define VIDEO1394_DRIVER_NAME "video1394"
#define VIDEO1394_MAX_SIZE 0x4000000 #define VIDEO1394_MAX_SIZE 0x4000000
...@@ -31,18 +33,6 @@ enum { ...@@ -31,18 +33,6 @@ enum {
VIDEO1394_BUFFER_READY VIDEO1394_BUFFER_READY
}; };
enum {
VIDEO1394_LISTEN_CHANNEL = 0,
VIDEO1394_UNLISTEN_CHANNEL,
VIDEO1394_LISTEN_QUEUE_BUFFER,
VIDEO1394_LISTEN_WAIT_BUFFER, // wait until buffer is ready
VIDEO1394_TALK_CHANNEL,
VIDEO1394_UNTALK_CHANNEL,
VIDEO1394_TALK_QUEUE_BUFFER,
VIDEO1394_TALK_WAIT_BUFFER,
VIDEO1394_LISTEN_POLL_BUFFER // return immediately with -EINTR if not ready
};
#define VIDEO1394_SYNC_FRAMES 0x00000001 #define VIDEO1394_SYNC_FRAMES 0x00000001
#define VIDEO1394_INCLUDE_ISO_HEADERS 0x00000002 #define VIDEO1394_INCLUDE_ISO_HEADERS 0x00000002
#define VIDEO1394_VARIABLE_PACKET_SIZE 0x00000004 #define VIDEO1394_VARIABLE_PACKET_SIZE 0x00000004
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment