提交 b2329239 编写于 作者: J Jeff Garzik

Merge branch 'master' into upstream-fixes

...@@ -657,7 +657,11 @@ einval: li v0, -EINVAL ...@@ -657,7 +657,11 @@ einval: li v0, -EINVAL
sys sys_getcpu 3 sys sys_getcpu 3
sys sys_epoll_pwait 6 sys sys_epoll_pwait 6
sys sys_ioprio_set 3 sys sys_ioprio_set 3
sys sys_ioprio_get 2 sys sys_ioprio_get 2 /* 4315 */
sys sys_utimensat 4
sys sys_signalfd 3
sys sys_timerfd 4
sys sys_eventfd 1
.endm .endm
/* We pre-compute the number of _instruction_ bytes needed to /* We pre-compute the number of _instruction_ bytes needed to
......
...@@ -473,4 +473,8 @@ sys_call_table: ...@@ -473,4 +473,8 @@ sys_call_table:
PTR sys_epoll_pwait PTR sys_epoll_pwait
PTR sys_ioprio_set PTR sys_ioprio_set
PTR sys_ioprio_get PTR sys_ioprio_get
PTR sys_utimensat /* 5275 */
PTR sys_signalfd
PTR sys_timerfd
PTR sys_eventfd
.size sys_call_table,.-sys_call_table .size sys_call_table,.-sys_call_table
...@@ -399,4 +399,8 @@ EXPORT(sysn32_call_table) ...@@ -399,4 +399,8 @@ EXPORT(sysn32_call_table)
PTR compat_sys_epoll_pwait PTR compat_sys_epoll_pwait
PTR sys_ioprio_set PTR sys_ioprio_set
PTR sys_ioprio_get PTR sys_ioprio_get
PTR compat_sys_utimensat
PTR compat_sys_signalfd /* 5280 */
PTR compat_sys_timerfd
PTR sys_eventfd
.size sysn32_call_table,.-sysn32_call_table .size sysn32_call_table,.-sysn32_call_table
...@@ -521,4 +521,8 @@ sys_call_table: ...@@ -521,4 +521,8 @@ sys_call_table:
PTR compat_sys_epoll_pwait PTR compat_sys_epoll_pwait
PTR sys_ioprio_set PTR sys_ioprio_set
PTR sys_ioprio_get /* 4315 */ PTR sys_ioprio_get /* 4315 */
PTR compat_sys_utimensat
PTR compat_sys_signalfd
PTR compat_sys_timerfd
PTR sys_eventfd
.size sys_call_table,.-sys_call_table .size sys_call_table,.-sys_call_table
...@@ -68,7 +68,7 @@ extern ATTRIB_NORET void cpu_idle(void); ...@@ -68,7 +68,7 @@ extern ATTRIB_NORET void cpu_idle(void);
* First C code run on the secondary CPUs after being started up by * First C code run on the secondary CPUs after being started up by
* the master. * the master.
*/ */
asmlinkage void start_secondary(void) asmlinkage __cpuinit void start_secondary(void)
{ {
unsigned int cpu; unsigned int cpu;
......
...@@ -121,10 +121,7 @@ LEAF(self_ipi) ...@@ -121,10 +121,7 @@ LEAF(self_ipi)
subu t1,sp,PT_SIZE subu t1,sp,PT_SIZE
sw ra,PT_EPC(t1) sw ra,PT_EPC(t1)
sw a0,PT_PADSLOT4(t1) sw a0,PT_PADSLOT4(t1)
LONG_L s0, TI_REGS($28)
LONG_S sp, TI_REGS($28)
la t2,ipi_decode la t2,ipi_decode
LONG_S s0, TI_REGS($28)
sw t2,PT_PADSLOT5(t1) sw t2,PT_PADSLOT5(t1)
/* Save pre-disable value of TCStatus */ /* Save pre-disable value of TCStatus */
sw t0,PT_TCSTATUS(t1) sw t0,PT_TCSTATUS(t1)
......
...@@ -611,12 +611,12 @@ void smtc_cpus_done(void) ...@@ -611,12 +611,12 @@ void smtc_cpus_done(void)
int setup_irq_smtc(unsigned int irq, struct irqaction * new, int setup_irq_smtc(unsigned int irq, struct irqaction * new,
unsigned long hwmask) unsigned long hwmask)
{ {
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
unsigned int vpe = current_cpu_data.vpe_id; unsigned int vpe = current_cpu_data.vpe_id;
irq_hwmask[irq] = hwmask;
#ifdef CONFIG_SMTC_IDLE_HOOK_DEBUG
vpemask[vpe][irq - MIPSCPU_INT_BASE] = 1; vpemask[vpe][irq - MIPSCPU_INT_BASE] = 1;
#endif #endif
irq_hwmask[irq] = hwmask;
return setup_irq(irq, new); return setup_irq(irq, new);
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* Copyright (C) 2000, 01 MIPS Technologies, Inc. * Copyright (C) 2000, 01 MIPS Technologies, Inc.
* Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki * Copyright (C) 2002, 2003, 2004, 2005 Maciej W. Rozycki
*/ */
#include <linux/bug.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/module.h> #include <linux/module.h>
...@@ -1190,8 +1191,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs) ...@@ -1190,8 +1191,8 @@ static void *set_vi_srs_handler(int n, vi_handler_t addr, int srs)
memcpy (b, &except_vec_vi, handler_len); memcpy (b, &except_vec_vi, handler_len);
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
if (n > 7) BUG_ON(n > 7); /* Vector index %d exceeds SMTC maximum. */
printk("Vector index %d exceeds SMTC maximum\n", n);
w = (u32 *)(b + mori_offset); w = (u32 *)(b + mori_offset);
*w = (*w & 0xffff0000) | (0x100 << n); *w = (*w & 0xffff0000) | (0x100 << n);
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
...@@ -1383,6 +1384,13 @@ void __init per_cpu_trap_init(void) ...@@ -1383,6 +1384,13 @@ void __init per_cpu_trap_init(void)
cpu_cache_init(); cpu_cache_init();
tlb_init(); tlb_init();
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
} else if (!secondaryTC) {
/*
* First TC in non-boot VPE must do subset of tlb_init()
* for MMU countrol registers.
*/
write_c0_pagemask(PM_DEFAULT_MASK);
write_c0_wired(0);
} }
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
} }
...@@ -1531,8 +1539,7 @@ void __init trap_init(void) ...@@ -1531,8 +1539,7 @@ void __init trap_init(void)
if (cpu_has_mipsmt) if (cpu_has_mipsmt)
set_except_vector(25, handle_mt); set_except_vector(25, handle_mt);
if (cpu_has_dsp) set_except_vector(26, handle_dsp);
set_except_vector(26, handle_dsp);
if (cpu_has_vce) if (cpu_has_vce)
/* Special exception: R4[04]00 uses also the divec space. */ /* Special exception: R4[04]00 uses also the divec space. */
......
...@@ -248,14 +248,13 @@ void __init arch_init_irq(void) ...@@ -248,14 +248,13 @@ void __init arch_init_irq(void)
case MIPS_REVISION_CORID_CORE_24K: case MIPS_REVISION_CORID_CORE_24K:
case MIPS_REVISION_CORID_CORE_EMUL_MSC: case MIPS_REVISION_CORID_CORE_EMUL_MSC:
if (cpu_has_veic) if (cpu_has_veic)
init_msc_irqs (MSC01E_INT_BASE, init_msc_irqs (MSC01E_INT_BASE, MSC01E_INT_BASE,
msc_eicirqmap, msc_nr_eicirqs); msc_eicirqmap, msc_nr_eicirqs);
else else
init_msc_irqs (MSC01C_INT_BASE, init_msc_irqs (MSC01E_INT_BASE, MSC01C_INT_BASE,
msc_irqmap, msc_nr_irqs); msc_irqmap, msc_nr_irqs);
} }
if (cpu_has_veic) { if (cpu_has_veic) {
set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch); set_vi_handler (MSC01E_INT_ATLAS, atlas_hw0_irqdispatch);
setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq); setup_irq (MSC01E_INT_BASE + MSC01E_INT_ATLAS, &atlasirq);
......
...@@ -88,8 +88,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id) ...@@ -88,8 +88,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
* the general MIPS timer_interrupt routine. * the general MIPS timer_interrupt routine.
*/ */
int vpflags;
/* /*
* We could be here due to timer interrupt, * We could be here due to timer interrupt,
* perf counter overflow, or both. * perf counter overflow, or both.
...@@ -98,15 +96,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id) ...@@ -98,15 +96,6 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
perf_irq(); perf_irq();
if (read_c0_cause() & (1 << 30)) { if (read_c0_cause() & (1 << 30)) {
/* If timer interrupt, make it de-assert */
write_c0_compare (read_c0_count() - 1);
/*
* DVPE is necessary so long as cross-VPE interrupts
* are done via read-modify-write of Cause register.
*/
vpflags = dvpe();
clear_c0_cause(CPUCTR_IMASKBIT);
evpe(vpflags);
/* /*
* There are things we only want to do once per tick * There are things we only want to do once per tick
* in an "MP" system. One TC of each VPE will take * in an "MP" system. One TC of each VPE will take
...@@ -115,14 +104,13 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id) ...@@ -115,14 +104,13 @@ irqreturn_t mips_timer_interrupt(int irq, void *dev_id)
* the tick on VPE 0 to run the full timer_interrupt(). * the tick on VPE 0 to run the full timer_interrupt().
*/ */
if (cpu_data[cpu].vpe_id == 0) { if (cpu_data[cpu].vpe_id == 0) {
timer_interrupt(irq, NULL); timer_interrupt(irq, NULL);
smtc_timer_broadcast(cpu_data[cpu].vpe_id);
} else { } else {
write_c0_compare(read_c0_count() + write_c0_compare(read_c0_count() +
(mips_hpt_frequency/HZ)); (mips_hpt_frequency/HZ));
local_timer_interrupt(irq, dev_id); local_timer_interrupt(irq, dev_id);
smtc_timer_broadcast(cpu_data[cpu].vpe_id);
} }
smtc_timer_broadcast(cpu_data[cpu].vpe_id);
} }
#else /* CONFIG_MIPS_MT_SMTC */ #else /* CONFIG_MIPS_MT_SMTC */
int r2 = cpu_has_mips_r2; int r2 = cpu_has_mips_r2;
......
...@@ -517,7 +517,7 @@ void __init paging_init(void) ...@@ -517,7 +517,7 @@ void __init paging_init(void)
pfn_t start_pfn = slot_getbasepfn(node, 0); pfn_t start_pfn = slot_getbasepfn(node, 0);
pfn_t end_pfn = node_getmaxclick(node) + 1; pfn_t end_pfn = node_getmaxclick(node) + 1;
zones_size[ZONE_DMA] = end_pfn - start_pfn; zones_size[ZONE_NORMAL] = end_pfn - start_pfn;
free_area_init_node(node, NODE_DATA(node), free_area_init_node(node, NODE_DATA(node),
zones_size, start_pfn, NULL); zones_size, start_pfn, NULL);
......
...@@ -426,6 +426,30 @@ static const struct pci_device_id ahci_pci_tbl[] = { ...@@ -426,6 +426,30 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */ { PCI_VDEVICE(NVIDIA, 0x0559), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */ { PCI_VDEVICE(NVIDIA, 0x055a), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */ { PCI_VDEVICE(NVIDIA, 0x055b), board_ahci }, /* MCP67 */
{ PCI_VDEVICE(NVIDIA, 0x07f0), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f1), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f2), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f3), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f4), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f5), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f6), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f7), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f8), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07f9), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07fa), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x07fb), board_ahci }, /* MCP73 */
{ PCI_VDEVICE(NVIDIA, 0x0ad0), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad1), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad2), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad3), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad4), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad5), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad6), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad7), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad8), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ad9), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0ada), board_ahci }, /* MCP77 */
{ PCI_VDEVICE(NVIDIA, 0x0adb), board_ahci }, /* MCP77 */
/* SiS */ /* SiS */
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */ { PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
......
...@@ -1727,7 +1727,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, ...@@ -1727,7 +1727,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
/* sanity check */ /* sanity check */
rc = -EINVAL; rc = -EINVAL;
reason = "device reports illegal type"; reason = "device reports invalid type";
if (class == ATA_DEV_ATA) { if (class == ATA_DEV_ATA) {
if (!ata_id_is_ata(id) && !ata_id_is_cfa(id)) if (!ata_id_is_ata(id) && !ata_id_is_cfa(id))
...@@ -1900,6 +1900,13 @@ int ata_dev_configure(struct ata_device *dev) ...@@ -1900,6 +1900,13 @@ int ata_dev_configure(struct ata_device *dev)
if (ata_msg_probe(ap)) if (ata_msg_probe(ap))
ata_dump_id(id); ata_dump_id(id);
/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
sizeof(fwrevbuf));
ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
sizeof(modelbuf));
/* ATA-specific feature tests */ /* ATA-specific feature tests */
if (dev->class == ATA_DEV_ATA) { if (dev->class == ATA_DEV_ATA) {
if (ata_id_is_cfa(id)) { if (ata_id_is_cfa(id)) {
...@@ -1914,13 +1921,6 @@ int ata_dev_configure(struct ata_device *dev) ...@@ -1914,13 +1921,6 @@ int ata_dev_configure(struct ata_device *dev)
dev->n_sectors = ata_id_n_sectors(id); dev->n_sectors = ata_id_n_sectors(id);
/* SCSI only uses 4-char revisions, dump full 8 chars from ATA */
ata_id_c_string(dev->id, fwrevbuf, ATA_ID_FW_REV,
sizeof(fwrevbuf));
ata_id_c_string(dev->id, modelbuf, ATA_ID_PROD,
sizeof(modelbuf));
if (dev->id[59] & 0x100) if (dev->id[59] & 0x100)
dev->multi_count = dev->id[59] & 0xff; dev->multi_count = dev->id[59] & 0xff;
...@@ -2009,7 +2009,9 @@ int ata_dev_configure(struct ata_device *dev) ...@@ -2009,7 +2009,9 @@ int ata_dev_configure(struct ata_device *dev)
/* print device info to dmesg */ /* print device info to dmesg */
if (ata_msg_drv(ap) && print_info) if (ata_msg_drv(ap) && print_info)
ata_dev_printk(dev, KERN_INFO, "ATAPI, max %s%s\n", ata_dev_printk(dev, KERN_INFO,
"ATAPI: %s, %s, max %s%s\n",
modelbuf, fwrevbuf,
ata_mode_string(xfer_mask), ata_mode_string(xfer_mask),
cdb_intr_string); cdb_intr_string);
} }
...@@ -3059,22 +3061,28 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask, ...@@ -3059,22 +3061,28 @@ static int ata_bus_post_reset(struct ata_port *ap, unsigned int devmask,
} }
} }
/* if device 1 was found in ata_devchk, wait for /* if device 1 was found in ata_devchk, wait for register
* register access, then wait for BSY to clear * access briefly, then wait for BSY to clear.
*/ */
while (dev1) { if (dev1) {
u8 nsect, lbal; int i;
ap->ops->dev_select(ap, 1); ap->ops->dev_select(ap, 1);
nsect = ioread8(ioaddr->nsect_addr);
lbal = ioread8(ioaddr->lbal_addr); /* Wait for register access. Some ATAPI devices fail
if ((nsect == 1) && (lbal == 1)) * to set nsect/lbal after reset, so don't waste too
break; * much time on it. We're gonna wait for !BSY anyway.
if (time_after(jiffies, deadline)) */
return -EBUSY; for (i = 0; i < 2; i++) {
msleep(50); /* give drive a breather */ u8 nsect, lbal;
}
if (dev1) { nsect = ioread8(ioaddr->nsect_addr);
lbal = ioread8(ioaddr->lbal_addr);
if ((nsect == 1) && (lbal == 1))
break;
msleep(50); /* give drive a breather */
}
rc = ata_wait_ready(ap, deadline); rc = ata_wait_ready(ap, deadline);
if (rc) { if (rc) {
if (rc != -ENODEV) if (rc != -ENODEV)
...@@ -3769,6 +3777,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { ...@@ -3769,6 +3777,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA }, { "_NEC DV5800A", NULL, ATA_HORKAGE_NODMA },
{ "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA }, { "SAMSUNG CD-ROM SN-124","N001", ATA_HORKAGE_NODMA },
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA }, { "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
{ "IOMEGA ZIP 250 ATAPI", NULL, ATA_HORKAGE_NODMA }, /* temporary fix */
/* Weird ATAPI devices */ /* Weird ATAPI devices */
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 | { "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 |
...@@ -3791,6 +3800,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = { ...@@ -3791,6 +3800,8 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
{ "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541060G9SA00", "MB3OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, }, { "HTS541080G9SA00", "MB4OC60D", ATA_HORKAGE_NONCQ, },
{ "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, }, { "HTS541010G9SA00", "MBZOC60D", ATA_HORKAGE_NONCQ, },
/* Drives which do spurious command completion */
{ "HTS541680J9SA00", "SB2IC7EP", ATA_HORKAGE_NONCQ, },
/* Devices with NCQ limits */ /* Devices with NCQ limits */
...@@ -6313,7 +6324,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht) ...@@ -6313,7 +6324,8 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
/* init sata_spd_limit to the current value */ /* init sata_spd_limit to the current value */
if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) { if (sata_scr_read(ap, SCR_CONTROL, &scontrol) == 0) {
int spd = (scontrol >> 4) & 0xf; int spd = (scontrol >> 4) & 0xf;
ap->hw_sata_spd_limit &= (1 << spd) - 1; if (spd)
ap->hw_sata_spd_limit &= (1 << spd) - 1;
} }
ap->sata_spd_limit = ap->hw_sata_spd_limit; ap->sata_spd_limit = ap->hw_sata_spd_limit;
...@@ -6433,6 +6445,9 @@ int ata_host_activate(struct ata_host *host, int irq, ...@@ -6433,6 +6445,9 @@ int ata_host_activate(struct ata_host *host, int irq,
if (rc) if (rc)
devm_free_irq(host->dev, irq, host); devm_free_irq(host->dev, irq, host);
/* Used to print device info at probe */
host->irq = irq;
return rc; return rc;
} }
...@@ -6818,6 +6833,7 @@ EXPORT_SYMBOL_GPL(ata_check_status); ...@@ -6818,6 +6833,7 @@ EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_altstatus); EXPORT_SYMBOL_GPL(ata_altstatus);
EXPORT_SYMBOL_GPL(ata_exec_command); EXPORT_SYMBOL_GPL(ata_exec_command);
EXPORT_SYMBOL_GPL(ata_port_start); EXPORT_SYMBOL_GPL(ata_port_start);
EXPORT_SYMBOL_GPL(ata_sff_port_start);
EXPORT_SYMBOL_GPL(ata_interrupt); EXPORT_SYMBOL_GPL(ata_interrupt);
EXPORT_SYMBOL_GPL(ata_do_set_mode); EXPORT_SYMBOL_GPL(ata_do_set_mode);
EXPORT_SYMBOL_GPL(ata_data_xfer); EXPORT_SYMBOL_GPL(ata_data_xfer);
......
...@@ -1363,12 +1363,22 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc) ...@@ -1363,12 +1363,22 @@ static void ata_scsi_qc_complete(struct ata_queued_cmd *qc)
* schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE * schedule EH_REVALIDATE operation to update the IDENTIFY DEVICE
* cache * cache
*/ */
if (ap->ops->error_handler && if (ap->ops->error_handler && !need_sense) {
!need_sense && (qc->tf.command == ATA_CMD_SET_FEATURES) && switch (qc->tf.command) {
((qc->tf.feature == SETFEATURES_WC_ON) || case ATA_CMD_SET_FEATURES:
(qc->tf.feature == SETFEATURES_WC_OFF))) { if ((qc->tf.feature == SETFEATURES_WC_ON) ||
ap->eh_info.action |= ATA_EH_REVALIDATE; (qc->tf.feature == SETFEATURES_WC_OFF)) {
ata_port_schedule_eh(ap); ap->eh_info.action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap);
}
break;
case ATA_CMD_INIT_DEV_PARAMS: /* CHS translation changed */
case ATA_CMD_SET_MULTI: /* multi_count changed */
ap->eh_info.action |= ATA_EH_REVALIDATE;
ata_port_schedule_eh(ap);
break;
}
} }
/* For ATA pass thru (SAT) commands, generate a sense block if /* For ATA pass thru (SAT) commands, generate a sense block if
...@@ -2506,22 +2516,21 @@ ata_scsi_map_proto(u8 byte1) ...@@ -2506,22 +2516,21 @@ ata_scsi_map_proto(u8 byte1)
return ATA_PROT_NODATA; return ATA_PROT_NODATA;
case 6: /* DMA */ case 6: /* DMA */
case 10: /* UDMA Data-in */
case 11: /* UDMA Data-Out */
return ATA_PROT_DMA; return ATA_PROT_DMA;
case 4: /* PIO Data-in */ case 4: /* PIO Data-in */
case 5: /* PIO Data-out */ case 5: /* PIO Data-out */
return ATA_PROT_PIO; return ATA_PROT_PIO;
case 10: /* Device Reset */
case 0: /* Hard Reset */ case 0: /* Hard Reset */
case 1: /* SRST */ case 1: /* SRST */
case 2: /* Bus Idle */ case 8: /* Device Diagnostic */
case 7: /* Packet */ case 9: /* Device Reset */
case 8: /* DMA Queued */ case 7: /* DMA Queued */
case 9: /* Device Diagnostic */ case 12: /* FPDMA */
case 11: /* UDMA Data-in */ case 15: /* Return Response Info */
case 12: /* UDMA Data-Out */
case 13: /* FPDMA */
default: /* Reserved */ default: /* Reserved */
break; break;
} }
...@@ -2552,10 +2561,6 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) ...@@ -2552,10 +2561,6 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0) if (tf->protocol == ATA_PROT_DMA && dev->dma_mode == 0)
goto invalid_fld; goto invalid_fld;
if (cdb[1] & 0xe0)
/* PIO multi not supported yet */
goto invalid_fld;
/* /*
* 12 and 16 byte CDBs use different offsets to * 12 and 16 byte CDBs use different offsets to
* provide the various register values. * provide the various register values.
...@@ -2600,12 +2605,26 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc) ...@@ -2600,12 +2605,26 @@ static unsigned int ata_scsi_pass_thru(struct ata_queued_cmd *qc)
tf->device = cdb[8]; tf->device = cdb[8];
tf->command = cdb[9]; tf->command = cdb[9];
} }
/*
* If slave is possible, enforce correct master/slave bit /* enforce correct master/slave bit */
*/ tf->device = dev->devno ?
if (qc->ap->flags & ATA_FLAG_SLAVE_POSS) tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1;
tf->device = qc->dev->devno ?
tf->device | ATA_DEV1 : tf->device & ~ATA_DEV1; /* sanity check for pio multi commands */
if ((cdb[1] & 0xe0) && !is_multi_taskfile(tf))
goto invalid_fld;
if (is_multi_taskfile(tf)) {
unsigned int multi_count = 1 << (cdb[1] >> 5);
/* compare the passed through multi_count
* with the cached multi_count of libata
*/
if (multi_count != dev->multi_count)
ata_dev_printk(dev, KERN_WARNING,
"invalid multi_count %u ignored\n",
multi_count);
}
/* READ/WRITE LONG use a non-standard sect_size */ /* READ/WRITE LONG use a non-standard sect_size */
qc->sect_size = ATA_SECT_SIZE; qc->sect_size = ATA_SECT_SIZE;
......
...@@ -80,25 +80,25 @@ u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; } ...@@ -80,25 +80,25 @@ u8 ata_dummy_irq_on (struct ata_port *ap) { return 0; }
u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq) u8 ata_irq_ack(struct ata_port *ap, unsigned int chk_drq)
{ {
unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY; unsigned int bits = chk_drq ? ATA_BUSY | ATA_DRQ : ATA_BUSY;
u8 host_stat, post_stat, status; u8 host_stat = 0, post_stat = 0, status;
status = ata_busy_wait(ap, bits, 1000); status = ata_busy_wait(ap, bits, 1000);
if (status & bits) if (status & bits)
if (ata_msg_err(ap)) if (ata_msg_err(ap))
printk(KERN_ERR "abnormal status 0x%X\n", status); printk(KERN_ERR "abnormal status 0x%X\n", status);
/* get controller status; clear intr, err bits */ if (ap->ioaddr.bmdma_addr) {
host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); /* get controller status; clear intr, err bits */
iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR, host_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
ap->ioaddr.bmdma_addr + ATA_DMA_STATUS); iowrite8(host_stat | ATA_DMA_INTR | ATA_DMA_ERR,
ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
post_stat = ioread8(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
}
if (ata_msg_intr(ap)) if (ata_msg_intr(ap))
printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n", printk(KERN_INFO "%s: irq ack: host_stat 0x%X, new host_stat 0x%X, drv_stat 0x%X\n",
__FUNCTION__, __FUNCTION__,
host_stat, post_stat, status); host_stat, post_stat, status);
return status; return status;
} }
...@@ -516,6 +516,27 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc) ...@@ -516,6 +516,27 @@ void ata_bmdma_post_internal_cmd(struct ata_queued_cmd *qc)
ata_bmdma_stop(qc); ata_bmdma_stop(qc);
} }
/**
* ata_sff_port_start - Set port up for dma.
* @ap: Port to initialize
*
* Called just after data structures for each port are
* initialized. Allocates space for PRD table if the device
* is DMA capable SFF.
*
* May be used as the port_start() entry in ata_port_operations.
*
* LOCKING:
* Inherited from caller.
*/
int ata_sff_port_start(struct ata_port *ap)
{
if (ap->ioaddr.bmdma_addr)
return ata_port_start(ap);
return 0;
}
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
static int ata_resources_present(struct pci_dev *pdev, int port) static int ata_resources_present(struct pci_dev *pdev, int port)
......
...@@ -77,7 +77,6 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev ...@@ -77,7 +77,6 @@ static int isapnp_init_one(struct pnp_dev *idev, const struct pnp_device_id *dev
struct ata_host *host; struct ata_host *host;
struct ata_port *ap; struct ata_port *ap;
void __iomem *cmd_addr, *ctl_addr; void __iomem *cmd_addr, *ctl_addr;
int rc;
if (pnp_port_valid(idev, 0) == 0) if (pnp_port_valid(idev, 0) == 0)
return -ENODEV; return -ENODEV;
......
...@@ -176,7 +176,7 @@ struct agp_bridge_data { ...@@ -176,7 +176,7 @@ struct agp_bridge_data {
#define I830_GMCH_MEM_MASK 0x1 #define I830_GMCH_MEM_MASK 0x1
#define I830_GMCH_MEM_64M 0x1 #define I830_GMCH_MEM_64M 0x1
#define I830_GMCH_MEM_128M 0 #define I830_GMCH_MEM_128M 0
#define I830_GMCH_GMS_MASK 0x70 #define I830_GMCH_GMS_MASK 0xF0
#define I830_GMCH_GMS_DISABLED 0x00 #define I830_GMCH_GMS_DISABLED 0x00
#define I830_GMCH_GMS_LOCAL 0x10 #define I830_GMCH_GMS_LOCAL 0x10
#define I830_GMCH_GMS_STOLEN_512 0x20 #define I830_GMCH_GMS_STOLEN_512 0x20
...@@ -231,6 +231,10 @@ struct agp_bridge_data { ...@@ -231,6 +231,10 @@ struct agp_bridge_data {
#define I965_PGETBL_SIZE_512KB (0 << 1) #define I965_PGETBL_SIZE_512KB (0 << 1)
#define I965_PGETBL_SIZE_256KB (1 << 1) #define I965_PGETBL_SIZE_256KB (1 << 1)
#define I965_PGETBL_SIZE_128KB (2 << 1) #define I965_PGETBL_SIZE_128KB (2 << 1)
#define G33_PGETBL_SIZE_MASK (3 << 8)
#define G33_PGETBL_SIZE_1M (1 << 8)
#define G33_PGETBL_SIZE_2M (2 << 8)
#define I810_DRAM_CTL 0x3000 #define I810_DRAM_CTL 0x3000
#define I810_DRAM_ROW_0 0x00000001 #define I810_DRAM_ROW_0 0x00000001
#define I810_DRAM_ROW_0_SDRAM 0x00000001 #define I810_DRAM_ROW_0_SDRAM 0x00000001
......
此差异已折叠。
...@@ -1037,6 +1037,17 @@ static void ide_disk_release(struct kref *kref) ...@@ -1037,6 +1037,17 @@ static void ide_disk_release(struct kref *kref)
static int ide_disk_probe(ide_drive_t *drive); static int ide_disk_probe(ide_drive_t *drive);
/*
* On HPA drives the capacity needs to be
* reinitilized on resume otherwise the disk
* can not be used and a hard reset is required
*/
static void ide_disk_resume(ide_drive_t *drive)
{
if (idedisk_supports_hpa(drive->id))
init_idedisk_capacity(drive);
}
static void ide_device_shutdown(ide_drive_t *drive) static void ide_device_shutdown(ide_drive_t *drive)
{ {
#ifdef CONFIG_ALPHA #ifdef CONFIG_ALPHA
...@@ -1071,6 +1082,7 @@ static ide_driver_t idedisk_driver = { ...@@ -1071,6 +1082,7 @@ static ide_driver_t idedisk_driver = {
}, },
.probe = ide_disk_probe, .probe = ide_disk_probe,
.remove = ide_disk_remove, .remove = ide_disk_remove,
.resume = ide_disk_resume,
.shutdown = ide_device_shutdown, .shutdown = ide_device_shutdown,
.version = IDEDISK_VERSION, .version = IDEDISK_VERSION,
.media = ide_disk, .media = ide_disk,
......
...@@ -717,7 +717,7 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave); ...@@ -717,7 +717,7 @@ EXPORT_SYMBOL_GPL(ide_undecoded_slave);
* This routine only knows how to look for drive units 0 and 1 * This routine only knows how to look for drive units 0 and 1
* on an interface, so any setting of MAX_DRIVES > 2 won't work here. * on an interface, so any setting of MAX_DRIVES > 2 won't work here.
*/ */
static void probe_hwif(ide_hwif_t *hwif) static void probe_hwif(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
{ {
unsigned int unit; unsigned int unit;
unsigned long flags; unsigned long flags;
...@@ -820,6 +820,9 @@ static void probe_hwif(ide_hwif_t *hwif) ...@@ -820,6 +820,9 @@ static void probe_hwif(ide_hwif_t *hwif)
return; return;
} }
if (fixup)
fixup(hwif);
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit]; ide_drive_t *drive = &hwif->drives[unit];
...@@ -874,10 +877,7 @@ static int hwif_init(ide_hwif_t *hwif); ...@@ -874,10 +877,7 @@ static int hwif_init(ide_hwif_t *hwif);
int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif)) int probe_hwif_init_with_fixup(ide_hwif_t *hwif, void (*fixup)(ide_hwif_t *hwif))
{ {
probe_hwif(hwif); probe_hwif(hwif, fixup);
if (fixup)
fixup(hwif);
if (!hwif_init(hwif)) { if (!hwif_init(hwif)) {
printk(KERN_INFO "%s: failed to initialize IDE interface\n", printk(KERN_INFO "%s: failed to initialize IDE interface\n",
...@@ -1404,7 +1404,7 @@ int ideprobe_init (void) ...@@ -1404,7 +1404,7 @@ int ideprobe_init (void)
for (index = 0; index < MAX_HWIFS; ++index) for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index]) if (probe[index])
probe_hwif(&ide_hwifs[index]); probe_hwif(&ide_hwifs[index], NULL);
for (index = 0; index < MAX_HWIFS; ++index) for (index = 0; index < MAX_HWIFS; ++index)
if (probe[index]) if (probe[index])
hwif_init(&ide_hwifs[index]); hwif_init(&ide_hwifs[index]);
......
...@@ -1010,9 +1010,11 @@ static int generic_ide_resume(struct device *dev) ...@@ -1010,9 +1010,11 @@ static int generic_ide_resume(struct device *dev)
{ {
ide_drive_t *drive = dev->driver_data; ide_drive_t *drive = dev->driver_data;
ide_hwif_t *hwif = HWIF(drive); ide_hwif_t *hwif = HWIF(drive);
ide_driver_t *drv = to_ide_driver(dev->driver);
struct request rq; struct request rq;
struct request_pm_state rqpm; struct request_pm_state rqpm;
ide_task_t args; ide_task_t args;
int err;
/* Call ACPI _STM only once */ /* Call ACPI _STM only once */
if (!(drive->dn % 2)) if (!(drive->dn % 2))
...@@ -1029,7 +1031,12 @@ static int generic_ide_resume(struct device *dev) ...@@ -1029,7 +1031,12 @@ static int generic_ide_resume(struct device *dev)
rqpm.pm_step = ide_pm_state_start_resume; rqpm.pm_step = ide_pm_state_start_resume;
rqpm.pm_state = PM_EVENT_ON; rqpm.pm_state = PM_EVENT_ON;
return ide_do_drive_cmd(drive, &rq, ide_head_wait); err = ide_do_drive_cmd(drive, &rq, ide_head_wait);
if (err == 0 && drv && drv->resume)
drv->resume(drive);
return err;
} }
int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev, int generic_ide_ioctl(ide_drive_t *drive, struct file *file, struct block_device *bdev,
......
/* /*
* Version 2.13 * Version 2.15
* *
* AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04 * AMD 755/756/766/8111 and nVidia nForce/2/2s/3/3s/CK804/MCP04
* IDE driver for Linux. * IDE driver for Linux.
...@@ -76,6 +76,8 @@ static struct amd_ide_chip { ...@@ -76,6 +76,8 @@ static struct amd_ide_chip {
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, AMD_UDMA_133 }, { PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, 0x50, AMD_UDMA_133 },
{ PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 }, { PCI_DEVICE_ID_AMD_CS5536_IDE, 0x40, AMD_UDMA_100 },
{ 0 } { 0 }
}; };
...@@ -494,7 +496,9 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = { ...@@ -494,7 +496,9 @@ static ide_pci_device_t amd74xx_chipsets[] __devinitdata = {
/* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"), /* 17 */ DECLARE_NV_DEV("NFORCE-MCP61"),
/* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"), /* 18 */ DECLARE_NV_DEV("NFORCE-MCP65"),
/* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"), /* 19 */ DECLARE_NV_DEV("NFORCE-MCP67"),
/* 20 */ DECLARE_AMD_DEV("AMD5536"), /* 20 */ DECLARE_NV_DEV("NFORCE-MCP73"),
/* 21 */ DECLARE_NV_DEV("NFORCE-MCP77"),
/* 22 */ DECLARE_AMD_DEV("AMD5536"),
}; };
static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit amd74xx_probe(struct pci_dev *dev, const struct pci_device_id *id)
...@@ -534,7 +538,9 @@ static struct pci_device_id amd74xx_pci_tbl[] = { ...@@ -534,7 +538,9 @@ static struct pci_device_id amd74xx_pci_tbl[] = {
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP61_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 17 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP65_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 18 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 19 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 }, { PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 20 },
{ PCI_VENDOR_ID_NVIDIA, PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 21 },
{ PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CS5536_IDE, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 22 },
{ 0, }, { 0, },
}; };
MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl); MODULE_DEVICE_TABLE(pci, amd74xx_pci_tbl);
......
...@@ -198,32 +198,41 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = { ...@@ -198,32 +198,41 @@ static ide_pci_device_t generic_chipsets[] __devinitdata = {
static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id) static int __devinit generic_init_one(struct pci_dev *dev, const struct pci_device_id *id)
{ {
ide_pci_device_t *d = &generic_chipsets[id->driver_data]; ide_pci_device_t *d = &generic_chipsets[id->driver_data];
u16 command;
int ret = -ENODEV; int ret = -ENODEV;
/* Don't use the generic entry unless instructed to do so */ /* Don't use the generic entry unless instructed to do so */
if (id->driver_data == 0 && ide_generic_all == 0) if (id->driver_data == 0 && ide_generic_all == 0)
goto out; goto out;
if (dev->vendor == PCI_VENDOR_ID_UMC && switch (dev->vendor) {
dev->device == PCI_DEVICE_ID_UMC_UM8886A && case PCI_VENDOR_ID_UMC:
(!(PCI_FUNC(dev->devfn) & 1))) if (dev->device == PCI_DEVICE_ID_UMC_UM8886A &&
goto out; /* UM8886A/BF pair */ !(PCI_FUNC(dev->devfn) & 1))
goto out; /* UM8886A/BF pair */
if (dev->vendor == PCI_VENDOR_ID_OPTI && break;
dev->device == PCI_DEVICE_ID_OPTI_82C558 && case PCI_VENDOR_ID_OPTI:
(!(PCI_FUNC(dev->devfn) & 1))) if (dev->device == PCI_DEVICE_ID_OPTI_82C558 &&
goto out; !(PCI_FUNC(dev->devfn) & 1))
goto out;
if (dev->vendor == PCI_VENDOR_ID_JMICRON) { break;
if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 && PCI_FUNC(dev->devfn) != 1) case PCI_VENDOR_ID_JMICRON:
if (dev->device != PCI_DEVICE_ID_JMICRON_JMB368 &&
PCI_FUNC(dev->devfn) != 1)
goto out;
break;
case PCI_VENDOR_ID_NS:
if (dev->device == PCI_DEVICE_ID_NS_87410 &&
(dev->class >> 8) != PCI_CLASS_STORAGE_IDE)
goto out; goto out;
break;
} }
if (dev->vendor != PCI_VENDOR_ID_JMICRON) { if (dev->vendor != PCI_VENDOR_ID_JMICRON) {
u16 command;
pci_read_config_word(dev, PCI_COMMAND, &command); pci_read_config_word(dev, PCI_COMMAND, &command);
if (!(command & PCI_COMMAND_IO)) { if (!(command & PCI_COMMAND_IO)) {
printk(KERN_INFO "Skipping disabled %s IDE controller.\n", d->name); printk(KERN_INFO "Skipping disabled %s IDE "
"controller.\n", d->name);
goto out; goto out;
} }
} }
......
/* /*
* linux/drivers/ide/pci/hpt366.c Version 1.03 May 4, 2007 * linux/drivers/ide/pci/hpt366.c Version 1.04 Jun 4, 2007
* *
* Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org> * Copyright (C) 1999-2003 Andre Hedrick <andre@linux-ide.org>
* Portions Copyright (C) 2001 Sun Microsystems, Inc. * Portions Copyright (C) 2001 Sun Microsystems, Inc.
...@@ -106,7 +106,8 @@ ...@@ -106,7 +106,8 @@
* switch to calculating PCI clock frequency based on the chip's base DPLL * switch to calculating PCI clock frequency based on the chip's base DPLL
* frequency * frequency
* - switch to using the DPLL clock and enable UltraATA/133 mode by default on * - switch to using the DPLL clock and enable UltraATA/133 mode by default on
* anything newer than HPT370/A * anything newer than HPT370/A (except HPT374 that is not capable of this
* mode according to the manual)
* - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(), * - fold PCI clock detection and DPLL setup code into init_chipset_hpt366(),
* also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips; * also fixing the interchanged 25/40 MHz PCI clock cases for HPT36x chips;
* unify HPT36x/37x timing setup code and the speedproc handlers by joining * unify HPT36x/37x timing setup code and the speedproc handlers by joining
...@@ -365,7 +366,6 @@ static u32 sixty_six_base_hpt37x[] = { ...@@ -365,7 +366,6 @@ static u32 sixty_six_base_hpt37x[] = {
}; };
#define HPT366_DEBUG_DRIVE_INFO 0 #define HPT366_DEBUG_DRIVE_INFO 0
#define HPT374_ALLOW_ATA133_6 1
#define HPT371_ALLOW_ATA133_6 1 #define HPT371_ALLOW_ATA133_6 1
#define HPT302_ALLOW_ATA133_6 1 #define HPT302_ALLOW_ATA133_6 1
#define HPT372_ALLOW_ATA133_6 1 #define HPT372_ALLOW_ATA133_6 1
...@@ -450,7 +450,7 @@ static struct hpt_info hpt370a __devinitdata = { ...@@ -450,7 +450,7 @@ static struct hpt_info hpt370a __devinitdata = {
static struct hpt_info hpt374 __devinitdata = { static struct hpt_info hpt374 __devinitdata = {
.chip_type = HPT374, .chip_type = HPT374,
.max_mode = HPT374_ALLOW_ATA133_6 ? 4 : 3, .max_mode = 3,
.dpll_clk = 48, .dpll_clk = 48,
.settings = hpt37x_settings .settings = hpt37x_settings
}; };
......
/* /*
* linux/drivers/ide/pci/it821x.c Version 0.10 Mar 10 2007 * linux/drivers/ide/pci/it821x.c Version 0.15 Jun 2 2007
* *
* Copyright (C) 2004 Red Hat <alan@redhat.com> * Copyright (C) 2004 Red Hat <alan@redhat.com>
* Copyright (C) 2007 Bartlomiej Zolnierkiewicz * Copyright (C) 2007 Bartlomiej Zolnierkiewicz
...@@ -262,7 +262,7 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio) ...@@ -262,7 +262,7 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
} }
if (itdev->smart) if (itdev->smart)
goto set_drive_speed; return 0;
/* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */ /* We prefer 66Mhz clock for PIO 0-3, don't care for PIO4 */
itdev->want[unit][1] = pio_want[set_pio]; itdev->want[unit][1] = pio_want[set_pio];
...@@ -271,7 +271,6 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio) ...@@ -271,7 +271,6 @@ static int it821x_tunepio(ide_drive_t *drive, u8 set_pio)
it821x_clock_strategy(drive); it821x_clock_strategy(drive);
it821x_program(drive, itdev->pio[unit]); it821x_program(drive, itdev->pio[unit]);
set_drive_speed:
return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio); return ide_config_drive_speed(drive, XFER_PIO_0 + set_pio);
} }
...@@ -455,12 +454,12 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed) ...@@ -455,12 +454,12 @@ static int it821x_tune_chipset (ide_drive_t *drive, byte xferspeed)
default: default:
return 1; return 1;
} }
return ide_config_drive_speed(drive, speed);
} }
/*
* In smart mode the clocking is done by the host controller /* don't touch anything in the smart mode */
* snooping the mode we picked. The rest of it is not our problem return 0;
*/
return ide_config_drive_speed(drive, speed);
} }
/** /**
...@@ -559,17 +558,10 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif) ...@@ -559,17 +558,10 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
if(idbits[129] != 1) if(idbits[129] != 1)
printk("(%dK stripe)", idbits[146]); printk("(%dK stripe)", idbits[146]);
printk(".\n"); printk(".\n");
/* Now the core code will have wrongly decided no DMA
so we need to fix this */
hwif->dma_off_quietly(drive);
#ifdef CONFIG_IDEDMA_ONLYDISK
if (drive->media == ide_disk)
#endif
ide_set_dma(drive);
} else { } else {
/* Non RAID volume. Fixups to stop the core code /* Non RAID volume. Fixups to stop the core code
doing unsupported things */ doing unsupported things */
id->field_valid &= 1; id->field_valid &= 3;
id->queue_depth = 0; id->queue_depth = 0;
id->command_set_1 = 0; id->command_set_1 = 0;
id->command_set_2 &= 0xC400; id->command_set_2 &= 0xC400;
...@@ -584,6 +576,16 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif) ...@@ -584,6 +576,16 @@ static void __devinit it821x_fixups(ide_hwif_t *hwif)
printk(KERN_INFO "%s: Performing identify fixups.\n", printk(KERN_INFO "%s: Performing identify fixups.\n",
drive->name); drive->name);
} }
/*
* Set MWDMA0 mode as enabled/support - just to tell
* IDE core that DMA is supported (it821x hardware
* takes care of DMA mode programming).
*/
if (id->capability & 1) {
id->dma_mword |= 0x0101;
drive->current_speed = XFER_MW_DMA_0;
}
} }
} }
......
/* /*
* linux/drivers/ide/pci/serverworks.c Version 0.9 Mar 4 2007 * linux/drivers/ide/pci/serverworks.c Version 0.11 Jun 2 2007
* *
* Copyright (C) 1998-2000 Michel Aubry * Copyright (C) 1998-2000 Michel Aubry
* Copyright (C) 1998-2000 Andrzej Krzysztofowicz * Copyright (C) 1998-2000 Andrzej Krzysztofowicz
...@@ -170,42 +170,55 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -170,42 +170,55 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
if (!drive->init_speed) { if (!drive->init_speed) {
u8 dma_stat = inb(hwif->dma_status); u8 dma_stat = inb(hwif->dma_status);
dma_pio:
if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) && if (((ultra_enable << (7-drive->dn) & 0x80) == 0x80) &&
((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) { ((dma_stat & (1<<(5+unit))) == (1<<(5+unit)))) {
drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)]; drive->current_speed = drive->init_speed = XFER_UDMA_0 + udma_modes[(ultra_timing >> (4*unit)) & ~(0xF0)];
return 0; return 0;
} else if ((dma_timing) && } else if ((dma_timing) &&
((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) { ((dma_stat&(1<<(5+unit)))==(1<<(5+unit)))) {
u8 dmaspeed = dma_timing; u8 dmaspeed;
dma_timing &= ~0xFFU; switch (dma_timing & 0x77) {
if ((dmaspeed & 0x20) == 0x20) case 0x20:
dmaspeed = XFER_MW_DMA_2; dmaspeed = XFER_MW_DMA_2;
else if ((dmaspeed & 0x21) == 0x21) break;
case 0x21:
dmaspeed = XFER_MW_DMA_1; dmaspeed = XFER_MW_DMA_1;
else if ((dmaspeed & 0x77) == 0x77) break;
case 0x77:
dmaspeed = XFER_MW_DMA_0; dmaspeed = XFER_MW_DMA_0;
else break;
default:
goto dma_pio; goto dma_pio;
}
drive->current_speed = drive->init_speed = dmaspeed; drive->current_speed = drive->init_speed = dmaspeed;
return 0; return 0;
} else if (pio_timing) { }
u8 piospeed = pio_timing; dma_pio:
if (pio_timing) {
u8 piospeed;
pio_timing &= ~0xFFU; switch (pio_timing & 0x7f) {
if ((piospeed & 0x20) == 0x20) case 0x20:
piospeed = XFER_PIO_4; piospeed = XFER_PIO_4;
else if ((piospeed & 0x22) == 0x22) break;
case 0x22:
piospeed = XFER_PIO_3; piospeed = XFER_PIO_3;
else if ((piospeed & 0x34) == 0x34) break;
case 0x34:
piospeed = XFER_PIO_2; piospeed = XFER_PIO_2;
else if ((piospeed & 0x47) == 0x47) break;
case 0x47:
piospeed = XFER_PIO_1; piospeed = XFER_PIO_1;
else if ((piospeed & 0x5d) == 0x5d) break;
case 0x5d:
piospeed = XFER_PIO_0; piospeed = XFER_PIO_0;
else break;
default:
goto oem_setup_failed; goto oem_setup_failed;
}
drive->current_speed = drive->init_speed = piospeed; drive->current_speed = drive->init_speed = piospeed;
return 0; return 0;
} }
...@@ -214,8 +227,8 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed) ...@@ -214,8 +227,8 @@ static int svwks_tune_chipset (ide_drive_t *drive, u8 xferspeed)
oem_setup_failed: oem_setup_failed:
pio_timing &= ~0xFFU; pio_timing = 0;
dma_timing &= ~0xFFU; dma_timing = 0;
ultra_timing &= ~(0x0F << (4*unit)); ultra_timing &= ~(0x0F << (4*unit));
ultra_enable &= ~(0x01 << drive->dn); ultra_enable &= ~(0x01 << drive->dn);
csb5_pio &= ~(0x0F << (4*drive->dn)); csb5_pio &= ~(0x0F << (4*drive->dn));
......
...@@ -2773,8 +2773,8 @@ static int cma_init(void) ...@@ -2773,8 +2773,8 @@ static int cma_init(void)
int ret; int ret;
get_random_bytes(&next_port, sizeof next_port); get_random_bytes(&next_port, sizeof next_port);
next_port = (next_port % (sysctl_local_port_range[1] - next_port = ((unsigned int) next_port %
sysctl_local_port_range[0])) + (sysctl_local_port_range[1] - sysctl_local_port_range[0])) +
sysctl_local_port_range[0]; sysctl_local_port_range[0];
cma_wq = create_singlethread_workqueue("rdma_cm"); cma_wq = create_singlethread_workqueue("rdma_cm");
if (!cma_wq) if (!cma_wq)
......
...@@ -189,18 +189,28 @@ static int send_wqe_overhead(enum ib_qp_type type) ...@@ -189,18 +189,28 @@ static int send_wqe_overhead(enum ib_qp_type type)
} }
static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap, static int set_rq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
struct mlx4_ib_qp *qp) int is_user, int has_srq, struct mlx4_ib_qp *qp)
{ {
/* Sanity check RQ size before proceeding */ /* Sanity check RQ size before proceeding */
if (cap->max_recv_wr > dev->dev->caps.max_wqes || if (cap->max_recv_wr > dev->dev->caps.max_wqes ||
cap->max_recv_sge > dev->dev->caps.max_rq_sg) cap->max_recv_sge > dev->dev->caps.max_rq_sg)
return -EINVAL; return -EINVAL;
qp->rq.max = cap->max_recv_wr ? roundup_pow_of_two(cap->max_recv_wr) : 0; if (has_srq) {
/* QPs attached to an SRQ should have no RQ */
if (cap->max_recv_wr)
return -EINVAL;
qp->rq.max = qp->rq.max_gs = 0;
} else {
/* HW requires >= 1 RQ entry with >= 1 gather entry */
if (is_user && (!cap->max_recv_wr || !cap->max_recv_sge))
return -EINVAL;
qp->rq.wqe_shift = ilog2(roundup_pow_of_two(cap->max_recv_sge * qp->rq.max = roundup_pow_of_two(max(1, cap->max_recv_wr));
sizeof (struct mlx4_wqe_data_seg))); qp->rq.max_gs = roundup_pow_of_two(max(1, cap->max_recv_sge));
qp->rq.max_gs = (1 << qp->rq.wqe_shift) / sizeof (struct mlx4_wqe_data_seg); qp->rq.wqe_shift = ilog2(qp->rq.max_gs * sizeof (struct mlx4_wqe_data_seg));
}
cap->max_recv_wr = qp->rq.max; cap->max_recv_wr = qp->rq.max;
cap->max_recv_sge = qp->rq.max_gs; cap->max_recv_sge = qp->rq.max_gs;
...@@ -285,7 +295,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd, ...@@ -285,7 +295,7 @@ static int create_qp_common(struct mlx4_ib_dev *dev, struct ib_pd *pd,
qp->sq.head = 0; qp->sq.head = 0;
qp->sq.tail = 0; qp->sq.tail = 0;
err = set_rq_size(dev, &init_attr->cap, qp); err = set_rq_size(dev, &init_attr->cap, !!pd->uobject, !!init_attr->srq, qp);
if (err) if (err)
goto err; goto err;
...@@ -762,11 +772,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -762,11 +772,6 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
optpar |= MLX4_QP_OPTPAR_PKEY_INDEX; optpar |= MLX4_QP_OPTPAR_PKEY_INDEX;
} }
if (attr_mask & IB_QP_RNR_RETRY) {
context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
}
if (attr_mask & IB_QP_AV) { if (attr_mask & IB_QP_AV) {
if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path, if (mlx4_set_path(dev, &attr->ah_attr, &context->pri_path,
attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) { attr_mask & IB_QP_PORT ? attr->port_num : qp->port)) {
...@@ -802,6 +807,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, ...@@ -802,6 +807,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp,
context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn); context->pd = cpu_to_be32(to_mpd(ibqp->pd)->pdn);
context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28); context->params1 = cpu_to_be32(MLX4_IB_ACK_REQ_FREQ << 28);
if (attr_mask & IB_QP_RNR_RETRY) {
context->params1 |= cpu_to_be32(attr->rnr_retry << 13);
optpar |= MLX4_QP_OPTPAR_RNR_RETRY;
}
if (attr_mask & IB_QP_RETRY_CNT) { if (attr_mask & IB_QP_RETRY_CNT) {
context->params1 |= cpu_to_be32(attr->retry_cnt << 16); context->params1 |= cpu_to_be32(attr->retry_cnt << 16);
optpar |= MLX4_QP_OPTPAR_RETRY_COUNT; optpar |= MLX4_QP_OPTPAR_RETRY_COUNT;
......
...@@ -772,7 +772,7 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status) ...@@ -772,7 +772,7 @@ int mthca_QUERY_FW(struct mthca_dev *dev, u8 *status)
MTHCA_GET(dev->fw_ver, outbox, QUERY_FW_VER_OFFSET); MTHCA_GET(dev->fw_ver, outbox, QUERY_FW_VER_OFFSET);
/* /*
* FW subminor version is at more signifant bits than minor * FW subminor version is at more significant bits than minor
* version, so swap here. * version, so swap here.
*/ */
dev->fw_ver = (dev->fw_ver & 0xffff00000000ull) | dev->fw_ver = (dev->fw_ver & 0xffff00000000ull) |
......
...@@ -4,5 +4,6 @@ config VIDEO_SAA7146 ...@@ -4,5 +4,6 @@ config VIDEO_SAA7146
config VIDEO_SAA7146_VV config VIDEO_SAA7146_VV
tristate tristate
depends on VIDEO_DEV
select VIDEO_BUF select VIDEO_BUF
select VIDEO_SAA7146 select VIDEO_SAA7146
b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \ b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o \ flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
flexcop-dma.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
b2c2-flexcop-objs += flexcop-dma.o
endif
b2c2-flexcop-pci-objs = flexcop-pci.o b2c2-flexcop-pci-objs = flexcop-pci.o
obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
......
...@@ -519,8 +519,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file) ...@@ -519,8 +519,7 @@ static int cinergyt2_release (struct inode *inode, struct file *file)
struct dvb_device *dvbdev = file->private_data; struct dvb_device *dvbdev = file->private_data;
struct cinergyt2 *cinergyt2 = dvbdev->priv; struct cinergyt2 *cinergyt2 = dvbdev->priv;
if (mutex_lock_interruptible(&cinergyt2->sem)) mutex_lock(&cinergyt2->sem);
return -ERESTARTSYS;
if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) { if (!cinergyt2->disconnect_pending && (file->f_flags & O_ACCMODE) != O_RDONLY) {
cancel_delayed_work(&cinergyt2->query_work); cancel_delayed_work(&cinergyt2->query_work);
......
...@@ -41,6 +41,7 @@ struct tda10086_state { ...@@ -41,6 +41,7 @@ struct tda10086_state {
/* private demod data */ /* private demod data */
u32 frequency; u32 frequency;
u32 symbol_rate; u32 symbol_rate;
bool has_lock;
}; };
static int debug = 0; static int debug = 0;
...@@ -116,7 +117,7 @@ static int tda10086_init(struct dvb_frontend* fe) ...@@ -116,7 +117,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// misc setup // misc setup
tda10086_write_byte(state, 0x01, 0x94); tda10086_write_byte(state, 0x01, 0x94);
tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP tda10086_write_byte(state, 0x02, 0x35); // NOTE: TT drivers appear to disable CSWP
tda10086_write_byte(state, 0x03, 0x64); tda10086_write_byte(state, 0x03, 0xe4);
tda10086_write_byte(state, 0x04, 0x43); tda10086_write_byte(state, 0x04, 0x43);
tda10086_write_byte(state, 0x0c, 0x0c); tda10086_write_byte(state, 0x0c, 0x0c);
tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold tda10086_write_byte(state, 0x1b, 0xb0); // noise threshold
...@@ -146,7 +147,7 @@ static int tda10086_init(struct dvb_frontend* fe) ...@@ -146,7 +147,7 @@ static int tda10086_init(struct dvb_frontend* fe)
// setup AGC // setup AGC
tda10086_write_byte(state, 0x05, 0x0B); tda10086_write_byte(state, 0x05, 0x0B);
tda10086_write_byte(state, 0x37, 0x63); tda10086_write_byte(state, 0x37, 0x63);
tda10086_write_byte(state, 0x3f, 0x03); // NOTE: flydvb uses 0x0a and varies it tda10086_write_byte(state, 0x3f, 0x0a); // NOTE: flydvb varies it
tda10086_write_byte(state, 0x40, 0x64); tda10086_write_byte(state, 0x40, 0x64);
tda10086_write_byte(state, 0x41, 0x4f); tda10086_write_byte(state, 0x41, 0x4f);
tda10086_write_byte(state, 0x42, 0x43); tda10086_write_byte(state, 0x42, 0x43);
...@@ -398,6 +399,10 @@ static int tda10086_set_frontend(struct dvb_frontend* fe, ...@@ -398,6 +399,10 @@ static int tda10086_set_frontend(struct dvb_frontend* fe,
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
// modify parameters for tuning
tda10086_write_byte(state, 0x02, 0x35);
state->has_lock = false;
// set params // set params
if (fe->ops.tuner_ops.set_params) { if (fe->ops.tuner_ops.set_params) {
fe->ops.tuner_ops.set_params(fe, fe_params); fe->ops.tuner_ops.set_params(fe, fe_params);
...@@ -542,8 +547,14 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status) ...@@ -542,8 +547,14 @@ static int tda10086_read_status(struct dvb_frontend* fe, fe_status_t *fe_status)
*fe_status |= FE_HAS_VITERBI; *fe_status |= FE_HAS_VITERBI;
if (val & 0x08) if (val & 0x08)
*fe_status |= FE_HAS_SYNC; *fe_status |= FE_HAS_SYNC;
if (val & 0x10) if (val & 0x10) {
*fe_status |= FE_HAS_LOCK; *fe_status |= FE_HAS_LOCK;
if (!state->has_lock) {
state->has_lock = true;
// modify parameters for stable reception
tda10086_write_byte(state, 0x02, 0x00);
}
}
return 0; return 0;
} }
...@@ -555,7 +566,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal) ...@@ -555,7 +566,7 @@ static int tda10086_read_signal_strength(struct dvb_frontend* fe, u16 * signal)
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
_str = tda10086_read_byte(state, 0x43); _str = 0xff - tda10086_read_byte(state, 0x43);
*signal = (_str << 8) | _str; *signal = (_str << 8) | _str;
return 0; return 0;
...@@ -568,7 +579,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr) ...@@ -568,7 +579,7 @@ static int tda10086_read_snr(struct dvb_frontend* fe, u16 * snr)
dprintk ("%s\n", __FUNCTION__); dprintk ("%s\n", __FUNCTION__);
_snr = tda10086_read_byte(state, 0x1c); _snr = 0xff - tda10086_read_byte(state, 0x1c);
*snr = (_snr << 8) | _snr; *snr = (_snr << 8) | _snr;
return 0; return 0;
......
...@@ -89,8 +89,8 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param ...@@ -89,8 +89,8 @@ static int tda826x_set_params(struct dvb_frontend *fe, struct dvb_frontend_param
buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO buf[2] = (1<<5) | 0x0b; // 1Mhz + 0.45 VCO
buf[3] = div >> 7; buf[3] = div >> 7;
buf[4] = div << 1; buf[4] = div << 1;
buf[5] = 0xff; // basedband filter to max buf[5] = 0x77; // baseband cut-off 19 MHz
buf[6] = 0xfe; // gains at max + no RF attenuation buf[6] = 0xfe; // baseband gain 9 db + no RF attenuation
buf[7] = 0x83; // charge pumps at high, tests off buf[7] = 0x83; // charge pumps at high, tests off
buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports. buf[8] = 0x80; // recommended value 4 for AMPVCO + disable ports.
buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL buf[9] = 0x1a; // normal caltime + recommended values for SELTH + SELVTL
......
...@@ -347,7 +347,7 @@ endmenu # encoder / decoder chips ...@@ -347,7 +347,7 @@ endmenu # encoder / decoder chips
config VIDEO_VIVI config VIDEO_VIVI
tristate "Virtual Video Driver" tristate "Virtual Video Driver"
depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI depends on VIDEO_V4L2 && !SPARC32 && !SPARC64 && PCI && VIDEO_DEV
select VIDEO_BUF select VIDEO_BUF
default n default n
---help--- ---help---
......
...@@ -86,7 +86,7 @@ ...@@ -86,7 +86,7 @@
V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \ V4L2_CAP_AUDIO | V4L2_CAP_READWRITE | V4L2_CAP_VBI_CAPTURE | \
V4L2_CAP_SLICED_VBI_CAPTURE) V4L2_CAP_SLICED_VBI_CAPTURE)
#define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \ #define IVTV_CAP_DECODER (V4L2_CAP_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT | \
V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY | V4L2_CAP_VIDEO_OUTPUT_POS) V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_OVERLAY)
struct ivtv_card_video_input { struct ivtv_card_video_input {
u8 video_type; /* video input type */ u8 video_type; /* video input type */
......
...@@ -652,6 +652,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv) ...@@ -652,6 +652,7 @@ static int __devinit ivtv_init_struct1(struct ivtv *itv)
itv->dma_timer.data = (unsigned long)itv; itv->dma_timer.data = (unsigned long)itv;
itv->cur_dma_stream = -1; itv->cur_dma_stream = -1;
itv->cur_pio_stream = -1;
itv->audio_stereo_mode = AUDIO_STEREO; itv->audio_stereo_mode = AUDIO_STEREO;
itv->audio_bilingual_mode = AUDIO_MONO_LEFT; itv->audio_bilingual_mode = AUDIO_MONO_LEFT;
......
...@@ -237,6 +237,7 @@ extern const u32 yuv_offset[4]; ...@@ -237,6 +237,7 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29) #define IVTV_IRQ_ENC_VBI_CAP (0x1 << 29)
#define IVTV_IRQ_ENC_VIM_RST (0x1 << 28) #define IVTV_IRQ_ENC_VIM_RST (0x1 << 28)
#define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27) #define IVTV_IRQ_ENC_DMA_COMPLETE (0x1 << 27)
#define IVTV_IRQ_ENC_PIO_COMPLETE (0x1 << 25)
#define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24) #define IVTV_IRQ_DEC_AUD_MODE_CHG (0x1 << 24)
#define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22) #define IVTV_IRQ_DEC_DATA_REQ (0x1 << 22)
#define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20) #define IVTV_IRQ_DEC_DMA_COMPLETE (0x1 << 20)
...@@ -247,7 +248,8 @@ extern const u32 yuv_offset[4]; ...@@ -247,7 +248,8 @@ extern const u32 yuv_offset[4];
#define IVTV_IRQ_DEC_VSYNC (0x1 << 10) #define IVTV_IRQ_DEC_VSYNC (0x1 << 10)
/* IRQ Masks */ /* IRQ Masks */
#define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|IVTV_IRQ_DMA_READ) #define IVTV_IRQ_MASK_INIT (IVTV_IRQ_DMA_ERR|IVTV_IRQ_ENC_DMA_COMPLETE|\
IVTV_IRQ_DMA_READ|IVTV_IRQ_ENC_PIO_COMPLETE)
#define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS) #define IVTV_IRQ_MASK_CAPTURE (IVTV_IRQ_ENC_START_CAP | IVTV_IRQ_ENC_EOS)
#define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG) #define IVTV_IRQ_MASK_DECODE (IVTV_IRQ_DEC_DATA_REQ|IVTV_IRQ_DEC_AUD_MODE_CHG)
...@@ -374,6 +376,9 @@ struct ivtv_mailbox_data { ...@@ -374,6 +376,9 @@ struct ivtv_mailbox_data {
#define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */ #define IVTV_F_S_STREAMOFF 7 /* signal end of stream EOS */
#define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */ #define IVTV_F_S_APPL_IO 8 /* this stream is used read/written by an application */
#define IVTV_F_S_PIO_PENDING 9 /* this stream has pending PIO */
#define IVTV_F_S_PIO_HAS_VBI 1 /* the current PIO request also requests VBI data */
/* per-ivtv, i_flags */ /* per-ivtv, i_flags */
#define IVTV_F_I_DMA 0 /* DMA in progress */ #define IVTV_F_I_DMA 0 /* DMA in progress */
#define IVTV_F_I_UDMA 1 /* UDMA in progress */ #define IVTV_F_I_UDMA 1 /* UDMA in progress */
...@@ -390,8 +395,11 @@ struct ivtv_mailbox_data { ...@@ -390,8 +395,11 @@ struct ivtv_mailbox_data {
#define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */ #define IVTV_F_I_DECODING_YUV 12 /* this stream is YUV frame decoding */
#define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */ #define IVTV_F_I_ENC_PAUSED 13 /* the encoder is paused */
#define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */ #define IVTV_F_I_VALID_DEC_TIMINGS 14 /* last_dec_timing is valid */
#define IVTV_F_I_WORK_HANDLER_VBI 15 /* there is work to be done for VBI */ #define IVTV_F_I_HAVE_WORK 15 /* Used in the interrupt handler: there is work to be done */
#define IVTV_F_I_WORK_HANDLER_YUV 16 /* there is work to be done for YUV */ #define IVTV_F_I_WORK_HANDLER_VBI 16 /* there is work to be done for VBI */
#define IVTV_F_I_WORK_HANDLER_YUV 17 /* there is work to be done for YUV */
#define IVTV_F_I_WORK_HANDLER_PIO 18 /* there is work to be done for PIO */
#define IVTV_F_I_PIO 19 /* PIO in progress */
/* Event notifications */ /* Event notifications */
#define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */ #define IVTV_F_I_EV_DEC_STOPPED 28 /* decoder stopped event */
...@@ -484,6 +492,7 @@ struct ivtv_stream { ...@@ -484,6 +492,7 @@ struct ivtv_stream {
/* Base Dev SG Array for cx23415/6 */ /* Base Dev SG Array for cx23415/6 */
struct ivtv_SG_element *SGarray; struct ivtv_SG_element *SGarray;
struct ivtv_SG_element *PIOarray;
dma_addr_t SG_handle; dma_addr_t SG_handle;
int SG_length; int SG_length;
...@@ -706,6 +715,7 @@ struct ivtv { ...@@ -706,6 +715,7 @@ struct ivtv {
atomic_t decoding; /* count number of active decoding streams */ atomic_t decoding; /* count number of active decoding streams */
u32 irq_rr_idx; /* Round-robin stream index */ u32 irq_rr_idx; /* Round-robin stream index */
int cur_dma_stream; /* index of stream doing DMA */ int cur_dma_stream; /* index of stream doing DMA */
int cur_pio_stream; /* index of stream doing PIO */
u32 dma_data_req_offset; u32 dma_data_req_offset;
u32 dma_data_req_size; u32 dma_data_req_size;
int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */ int output_mode; /* NONE, MPG, YUV, UDMA YUV, passthrough */
......
...@@ -32,6 +32,8 @@ ...@@ -32,6 +32,8 @@
#include "ivtv-yuv.h" #include "ivtv-yuv.h"
#include "ivtv-controls.h" #include "ivtv-controls.h"
#include "ivtv-ioctl.h" #include "ivtv-ioctl.h"
#include "ivtv-cards.h"
#include <media/saa7115.h>
/* This function tries to claim the stream for a specific file descriptor. /* This function tries to claim the stream for a specific file descriptor.
If no one else is using this stream then the stream is claimed and If no one else is using this stream then the stream is claimed and
...@@ -786,6 +788,13 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp) ...@@ -786,6 +788,13 @@ int ivtv_v4l2_close(struct inode *inode, struct file *filp)
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
/* Select correct audio input (i.e. TV tuner or Line in) */ /* Select correct audio input (i.e. TV tuner or Line in) */
ivtv_audio_set_io(itv); ivtv_audio_set_io(itv);
if (itv->hw_flags & IVTV_HW_SAA711X)
{
struct v4l2_crystal_freq crystal_freq;
crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
crystal_freq.flags = 0;
ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
}
/* Done! Unmute and continue. */ /* Done! Unmute and continue. */
ivtv_unmute(itv); ivtv_unmute(itv);
ivtv_release_stream(s); ivtv_release_stream(s);
...@@ -872,6 +881,13 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp) ...@@ -872,6 +881,13 @@ int ivtv_v4l2_open(struct inode *inode, struct file *filp)
set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags); set_bit(IVTV_F_I_RADIO_USER, &itv->i_flags);
/* Select the correct audio input (i.e. radio tuner) */ /* Select the correct audio input (i.e. radio tuner) */
ivtv_audio_set_io(itv); ivtv_audio_set_io(itv);
if (itv->hw_flags & IVTV_HW_SAA711X)
{
struct v4l2_crystal_freq crystal_freq;
crystal_freq.freq = SAA7115_FREQ_32_11_MHZ;
crystal_freq.flags = SAA7115_FREQ_FL_APLL;
ivtv_saa7115(itv, VIDIOC_INT_S_CRYSTAL_FREQ, &crystal_freq);
}
/* Done! Unmute and continue. */ /* Done! Unmute and continue. */
ivtv_unmute(itv); ivtv_unmute(itv);
} }
......
...@@ -532,11 +532,6 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype, ...@@ -532,11 +532,6 @@ static int ivtv_try_or_set_fmt(struct ivtv *itv, int streamtype,
itv->yuv_info.yuv_forced_update = 1; itv->yuv_info.yuv_forced_update = 1;
return 0; return 0;
} }
if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
r.width, r.height, r.left, r.top))
itv->main_rect = r;
else
return -EINVAL;
} }
return 0; return 0;
} }
...@@ -799,9 +794,39 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -799,9 +794,39 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
return ivtv_get_fmt(itv, id->type, fmt); return ivtv_get_fmt(itv, id->type, fmt);
} }
case VIDIOC_CROPCAP: {
struct v4l2_cropcap *cropcap = arg;
if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
cropcap->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
return -EINVAL;
cropcap->bounds.top = cropcap->bounds.left = 0;
cropcap->bounds.width = 720;
if (cropcap->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
cropcap->bounds.height = itv->is_50hz ? 576 : 480;
cropcap->pixelaspect.numerator = itv->is_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_50hz ? 54 : 11;
} else {
cropcap->bounds.height = itv->is_out_50hz ? 576 : 480;
cropcap->pixelaspect.numerator = itv->is_out_50hz ? 59 : 10;
cropcap->pixelaspect.denominator = itv->is_out_50hz ? 54 : 11;
}
cropcap->defrect = cropcap->bounds;
return 0;
}
case VIDIOC_S_CROP: { case VIDIOC_S_CROP: {
struct v4l2_crop *crop = arg; struct v4l2_crop *crop = arg;
if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
if (!ivtv_vapi(itv, CX2341X_OSD_SET_FRAMEBUFFER_WINDOW, 4,
crop->c.width, crop->c.height, crop->c.left, crop->c.top)) {
itv->main_rect = crop->c;
return 0;
}
return -EINVAL;
}
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_S_CROP, arg); return itv->video_dec_func(itv, VIDIOC_S_CROP, arg);
...@@ -810,6 +835,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -810,6 +835,11 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
case VIDIOC_G_CROP: { case VIDIOC_G_CROP: {
struct v4l2_crop *crop = arg; struct v4l2_crop *crop = arg;
if (crop->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT)) {
crop->c = itv->main_rect;
return 0;
}
if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
return -EINVAL; return -EINVAL;
return itv->video_dec_func(itv, VIDIOC_G_CROP, arg); return itv->video_dec_func(itv, VIDIOC_G_CROP, arg);
...@@ -977,7 +1007,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -977,7 +1007,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
if (itv->hw_flags & IVTV_HW_CX25840) { if (itv->hw_flags & IVTV_HW_CX25840) {
itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284; itv->vbi.sliced_decoder_line_size = itv->is_60hz ? 272 : 284;
} }
IVTV_DEBUG_INFO("Switching standard to %llx.\n", itv->std); IVTV_DEBUG_INFO("Switching standard to %llx.\n", (unsigned long long)itv->std);
/* Tuner */ /* Tuner */
ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std); ivtv_call_i2c_clients(itv, VIDIOC_S_STD, &itv->std);
...@@ -1207,7 +1237,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void ...@@ -1207,7 +1237,7 @@ int ivtv_v4l2_ioctls(struct ivtv *itv, struct file *filp, unsigned int cmd, void
(s->buffers - s->q_free.buffers) * 100 / s->buffers, (s->buffers - s->q_free.buffers) * 100 / s->buffers,
(s->buffers * s->buf_size) / 1024, s->buffers); (s->buffers * s->buf_size) / 1024, s->buffers);
} }
IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", itv->mpg_data_received, itv->vbi_data_inserted); IVTV_INFO("Read MPEG/VBI: %lld/%lld bytes\n", (long long)itv->mpg_data_received, (long long)itv->vbi_data_inserted);
IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num); IVTV_INFO("================== END STATUS CARD #%d ==================\n", itv->num);
break; break;
} }
...@@ -1455,6 +1485,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp, ...@@ -1455,6 +1485,7 @@ static int ivtv_v4l2_do_ioctl(struct inode *inode, struct file *filp,
case VIDIOC_S_FMT: case VIDIOC_S_FMT:
case VIDIOC_TRY_FMT: case VIDIOC_TRY_FMT:
case VIDIOC_ENUM_FMT: case VIDIOC_ENUM_FMT:
case VIDIOC_CROPCAP:
case VIDIOC_G_CROP: case VIDIOC_G_CROP:
case VIDIOC_S_CROP: case VIDIOC_S_CROP:
case VIDIOC_G_FREQUENCY: case VIDIOC_G_FREQUENCY:
......
...@@ -31,8 +31,6 @@ ...@@ -31,8 +31,6 @@
#define DMA_MAGIC_COOKIE 0x000001fe #define DMA_MAGIC_COOKIE 0x000001fe
#define SLICED_VBI_PIO 1
static void ivtv_dma_dec_start(struct ivtv_stream *s); static void ivtv_dma_dec_start(struct ivtv_stream *s);
static const int ivtv_stream_map[] = { static const int ivtv_stream_map[] = {
...@@ -42,12 +40,40 @@ static const int ivtv_stream_map[] = { ...@@ -42,12 +40,40 @@ static const int ivtv_stream_map[] = {
IVTV_ENC_STREAM_TYPE_VBI, IVTV_ENC_STREAM_TYPE_VBI,
}; };
static inline int ivtv_use_pio(struct ivtv_stream *s)
static void ivtv_pio_work_handler(struct ivtv *itv)
{ {
struct ivtv *itv = s->itv; struct ivtv_stream *s = &itv->streams[itv->cur_pio_stream];
struct ivtv_buffer *buf;
struct list_head *p;
int i = 0;
IVTV_DEBUG_DMA("ivtv_pio_work_handler\n");
if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS ||
s->v4l2dev == NULL || !ivtv_use_pio(s)) {
itv->cur_pio_stream = -1;
/* trigger PIO complete user interrupt */
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
return;
}
IVTV_DEBUG_DMA("Process PIO %s\n", s->name);
buf = list_entry(s->q_dma.list.next, struct ivtv_buffer, list);
list_for_each(p, &s->q_dma.list) {
struct ivtv_buffer *buf = list_entry(p, struct ivtv_buffer, list);
u32 size = s->PIOarray[i].size & 0x3ffff;
return s->dma == PCI_DMA_NONE || /* Copy the data from the card to the buffer */
(SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set); if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
memcpy_fromio(buf->buf, itv->dec_mem + s->PIOarray[i].src - IVTV_DECODER_OFFSET, size);
}
else {
memcpy_fromio(buf->buf, itv->enc_mem + s->PIOarray[i].src, size);
}
if (s->PIOarray[i].size & 0x80000000)
break;
i++;
}
write_reg(IVTV_IRQ_ENC_PIO_COMPLETE, 0x44);
} }
void ivtv_irq_work_handler(struct work_struct *work) void ivtv_irq_work_handler(struct work_struct *work)
...@@ -56,8 +82,11 @@ void ivtv_irq_work_handler(struct work_struct *work) ...@@ -56,8 +82,11 @@ void ivtv_irq_work_handler(struct work_struct *work)
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags))
ivtv_pio_work_handler(itv);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags)) if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags))
vbi_work_handler(itv); ivtv_vbi_work_handler(itv);
if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags)) if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
ivtv_yuv_work_handler(itv); ivtv_yuv_work_handler(itv);
...@@ -173,8 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA ...@@ -173,8 +202,7 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
} }
s->buffers_stolen = rc; s->buffers_stolen = rc;
/* got the buffers, now fill in SGarray (DMA) or copy the data from the card /* got the buffers, now fill in SGarray (DMA) */
to the buffers (PIO). */
buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list); buf = list_entry(s->q_predma.list.next, struct ivtv_buffer, list);
memset(buf->buf, 0, 128); memset(buf->buf, 0, 128);
list_for_each(p, &s->q_predma.list) { list_for_each(p, &s->q_predma.list) {
...@@ -182,21 +210,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA ...@@ -182,21 +210,11 @@ static int stream_enc_dma_append(struct ivtv_stream *s, u32 data[CX2341X_MBOX_MA
if (skip_bufs-- > 0) if (skip_bufs-- > 0)
continue; continue;
if (!ivtv_use_pio(s)) { s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle);
s->SGarray[idx].dst = cpu_to_le32(buf->dma_handle); s->SGarray[idx].src = cpu_to_le32(offset);
s->SGarray[idx].src = cpu_to_le32(offset); s->SGarray[idx].size = cpu_to_le32(s->buf_size);
s->SGarray[idx].size = cpu_to_le32(s->buf_size);
}
buf->bytesused = (size < s->buf_size) ? size : s->buf_size; buf->bytesused = (size < s->buf_size) ? size : s->buf_size;
/* If PIO, then copy the data from the card to the buffer */
if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
memcpy_fromio(buf->buf, itv->dec_mem + offset - IVTV_DECODER_OFFSET, buf->bytesused);
}
else if (ivtv_use_pio(s)) {
memcpy_fromio(buf->buf, itv->enc_mem + offset, buf->bytesused);
}
s->q_predma.bytesused += buf->bytesused; s->q_predma.bytesused += buf->bytesused;
size -= buf->bytesused; size -= buf->bytesused;
offset += s->buf_size; offset += s->buf_size;
...@@ -224,11 +242,6 @@ static void dma_post(struct ivtv_stream *s) ...@@ -224,11 +242,6 @@ static void dma_post(struct ivtv_stream *s)
u32 *u32buf; u32 *u32buf;
int x = 0; int x = 0;
if (ivtv_use_pio(s)) {
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
s->SG_length = 0;
}
IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA", IVTV_DEBUG_DMA("%s %s completed (%x)\n", ivtv_use_pio(s) ? "PIO" : "DMA",
s->name, s->dma_offset); s->name, s->dma_offset);
list_for_each(p, &s->q_dma.list) { list_for_each(p, &s->q_dma.list) {
...@@ -278,10 +291,14 @@ static void dma_post(struct ivtv_stream *s) ...@@ -278,10 +291,14 @@ static void dma_post(struct ivtv_stream *s)
if (buf) if (buf)
buf->bytesused += s->dma_last_offset; buf->bytesused += s->dma_last_offset;
if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) { if (buf && s->type == IVTV_DEC_STREAM_TYPE_VBI) {
/* Parse and Groom VBI Data */ list_for_each(p, &s->q_dma.list) {
s->q_dma.bytesused -= buf->bytesused; buf = list_entry(p, struct ivtv_buffer, list);
ivtv_process_vbi_data(itv, buf, 0, s->type);
s->q_dma.bytesused += buf->bytesused; /* Parse and Groom VBI Data */
s->q_dma.bytesused -= buf->bytesused;
ivtv_process_vbi_data(itv, buf, 0, s->type);
s->q_dma.bytesused += buf->bytesused;
}
if (s->id == -1) { if (s->id == -1) {
ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0); ivtv_queue_move(s, &s->q_dma, NULL, &s->q_free, 0);
return; return;
...@@ -351,10 +368,14 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) ...@@ -351,10 +368,14 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; struct ivtv_stream *s_vbi = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
int i; int i;
IVTV_DEBUG_DMA("start %s for %s\n", ivtv_use_dma(s) ? "DMA" : "PIO", s->name);
if (s->q_predma.bytesused) if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused); ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
IVTV_DEBUG_DMA("start DMA for %s\n", s->name);
s->SGarray[s->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256); if (ivtv_use_dma(s))
s->SGarray[s->SG_length - 1].size =
cpu_to_le32(le32_to_cpu(s->SGarray[s->SG_length - 1].size) + 256);
/* If this is an MPEG stream, and VBI data is also pending, then append the /* If this is an MPEG stream, and VBI data is also pending, then append the
VBI DMA to the MPEG DMA and transfer both sets of data at once. VBI DMA to the MPEG DMA and transfer both sets of data at once.
...@@ -368,7 +389,8 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) ...@@ -368,7 +389,8 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length && if (s->type == IVTV_ENC_STREAM_TYPE_MPG && s_vbi->SG_length &&
s->SG_length + s_vbi->SG_length <= s->buffers) { s->SG_length + s_vbi->SG_length <= s->buffers) {
ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused); ivtv_queue_move(s_vbi, &s_vbi->q_predma, NULL, &s_vbi->q_dma, s_vbi->q_predma.bytesused);
s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256); if (ivtv_use_dma(s_vbi))
s_vbi->SGarray[s_vbi->SG_length - 1].size = cpu_to_le32(le32_to_cpu(s_vbi->SGarray[s->SG_length - 1].size) + 256);
for (i = 0; i < s_vbi->SG_length; i++) { for (i = 0; i < s_vbi->SG_length; i++) {
s->SGarray[s->SG_length++] = s_vbi->SGarray[i]; s->SGarray[s->SG_length++] = s_vbi->SGarray[i];
} }
...@@ -381,14 +403,26 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s) ...@@ -381,14 +403,26 @@ static void ivtv_dma_enc_start(struct ivtv_stream *s)
/* Mark last buffer size for Interrupt flag */ /* Mark last buffer size for Interrupt flag */
s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000); s->SGarray[s->SG_length - 1].size |= cpu_to_le32(0x80000000);
/* Sync Hardware SG List of buffers */ if (ivtv_use_pio(s)) {
ivtv_stream_sync_for_device(s); for (i = 0; i < s->SG_length; i++) {
write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR); s->PIOarray[i].src = le32_to_cpu(s->SGarray[i].src);
write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER); s->PIOarray[i].size = le32_to_cpu(s->SGarray[i].size);
set_bit(IVTV_F_I_DMA, &itv->i_flags); }
itv->cur_dma_stream = s->type; set_bit(IVTV_F_I_WORK_HANDLER_PIO, &itv->i_flags);
itv->dma_timer.expires = jiffies + HZ / 10; set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
add_timer(&itv->dma_timer); set_bit(IVTV_F_I_PIO, &itv->i_flags);
itv->cur_pio_stream = s->type;
}
else {
/* Sync Hardware SG List of buffers */
ivtv_stream_sync_for_device(s);
write_reg(s->SG_handle, IVTV_REG_ENCDMAADDR);
write_reg_sync(read_reg(IVTV_REG_DMAXFER) | 0x02, IVTV_REG_DMAXFER);
set_bit(IVTV_F_I_DMA, &itv->i_flags);
itv->cur_dma_stream = s->type;
itv->dma_timer.expires = jiffies + HZ / 10;
add_timer(&itv->dma_timer);
}
} }
static void ivtv_dma_dec_start(struct ivtv_stream *s) static void ivtv_dma_dec_start(struct ivtv_stream *s)
...@@ -489,6 +523,40 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv) ...@@ -489,6 +523,40 @@ static void ivtv_irq_enc_dma_complete(struct ivtv *itv)
wake_up(&itv->dma_waitq); wake_up(&itv->dma_waitq);
} }
static void ivtv_irq_enc_pio_complete(struct ivtv *itv)
{
struct ivtv_stream *s;
if (itv->cur_pio_stream < 0 || itv->cur_pio_stream >= IVTV_MAX_STREAMS) {
itv->cur_pio_stream = -1;
return;
}
s = &itv->streams[itv->cur_pio_stream];
IVTV_DEBUG_IRQ("ENC PIO COMPLETE %s\n", s->name);
s->SG_length = 0;
clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
clear_bit(IVTV_F_I_PIO, &itv->i_flags);
itv->cur_pio_stream = -1;
dma_post(s);
if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 0);
else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 1);
else if (s->type == IVTV_ENC_STREAM_TYPE_PCM)
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, 2);
clear_bit(IVTV_F_I_PIO, &itv->i_flags);
if (test_and_clear_bit(IVTV_F_S_DMA_HAS_VBI, &s->s_flags)) {
u32 tmp;
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
tmp = s->dma_offset;
s->dma_offset = itv->vbi.dma_offset;
dma_post(s);
s->dma_offset = tmp;
}
wake_up(&itv->dma_waitq);
}
static void ivtv_irq_dma_err(struct ivtv *itv) static void ivtv_irq_dma_err(struct ivtv *itv)
{ {
u32 data[CX2341X_MBOX_MAX_DATA]; u32 data[CX2341X_MBOX_MAX_DATA];
...@@ -532,13 +600,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv) ...@@ -532,13 +600,7 @@ static void ivtv_irq_enc_start_cap(struct ivtv *itv)
clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); clear_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
s = &itv->streams[ivtv_stream_map[data[0]]]; s = &itv->streams[ivtv_stream_map[data[0]]];
if (!stream_enc_dma_append(s, data)) { if (!stream_enc_dma_append(s, data)) {
if (ivtv_use_pio(s)) { set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
dma_post(s);
ivtv_vapi(itv, CX2341X_ENC_SCHED_DMA_TO_HOST, 3, 0, 0, data[0]);
}
else {
set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags);
}
} }
} }
...@@ -551,15 +613,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) ...@@ -551,15 +613,6 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
IVTV_DEBUG_IRQ("ENC START VBI CAP\n"); IVTV_DEBUG_IRQ("ENC START VBI CAP\n");
s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI]; s = &itv->streams[IVTV_ENC_STREAM_TYPE_VBI];
if (ivtv_use_pio(s)) {
if (stream_enc_dma_append(s, data))
return;
if (s->q_predma.bytesused)
ivtv_queue_move(s, &s->q_predma, NULL, &s->q_dma, s->q_predma.bytesused);
s->SG_length = 0;
dma_post(s);
return;
}
/* If more than two VBI buffers are pending, then /* If more than two VBI buffers are pending, then
clear the old ones and start with this new one. clear the old ones and start with this new one.
This can happen during transition stages when MPEG capturing is This can happen during transition stages when MPEG capturing is
...@@ -582,11 +635,11 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv) ...@@ -582,11 +635,11 @@ static void ivtv_irq_enc_vbi_cap(struct ivtv *itv)
if (!stream_enc_dma_append(s, data) && if (!stream_enc_dma_append(s, data) &&
!test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) { !test_bit(IVTV_F_S_STREAMING, &s_mpg->s_flags)) {
set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags); set_bit(IVTV_F_I_ENC_VBI, &itv->i_flags);
set_bit(IVTV_F_S_DMA_PENDING, &s->s_flags); set_bit(ivtv_use_pio(s) ? IVTV_F_S_PIO_PENDING : IVTV_F_S_DMA_PENDING, &s->s_flags);
} }
} }
static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) static void ivtv_irq_dec_vbi_reinsert(struct ivtv *itv)
{ {
u32 data[CX2341X_MBOX_MAX_DATA]; u32 data[CX2341X_MBOX_MAX_DATA];
struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI]; struct ivtv_stream *s = &itv->streams[IVTV_DEC_STREAM_TYPE_VBI];
...@@ -594,7 +647,7 @@ static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv) ...@@ -594,7 +647,7 @@ static void ivtv_irq_dev_vbi_reinsert(struct ivtv *itv)
IVTV_DEBUG_IRQ("DEC VBI REINSERT\n"); IVTV_DEBUG_IRQ("DEC VBI REINSERT\n");
if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) && if (test_bit(IVTV_F_S_CLAIMED, &s->s_flags) &&
!stream_enc_dma_append(s, data)) { !stream_enc_dma_append(s, data)) {
dma_post(s); set_bit(IVTV_F_S_PIO_PENDING, &s->s_flags);
} }
} }
...@@ -657,7 +710,6 @@ static void ivtv_irq_vsync(struct ivtv *itv) ...@@ -657,7 +710,6 @@ static void ivtv_irq_vsync(struct ivtv *itv)
} }
if (frame != (itv->lastVsyncFrame & 1)) { if (frame != (itv->lastVsyncFrame & 1)) {
struct ivtv_stream *s = ivtv_get_output_stream(itv); struct ivtv_stream *s = ivtv_get_output_stream(itv);
int work = 0;
itv->lastVsyncFrame += 1; itv->lastVsyncFrame += 1;
if (frame == 0) { if (frame == 0) {
...@@ -678,7 +730,7 @@ static void ivtv_irq_vsync(struct ivtv *itv) ...@@ -678,7 +730,7 @@ static void ivtv_irq_vsync(struct ivtv *itv)
/* Send VBI to saa7127 */ /* Send VBI to saa7127 */
if (frame) { if (frame) {
set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags); set_bit(IVTV_F_I_WORK_HANDLER_VBI, &itv->i_flags);
work = 1; set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
} }
/* Check if we need to update the yuv registers */ /* Check if we need to update the yuv registers */
...@@ -691,11 +743,9 @@ static void ivtv_irq_vsync(struct ivtv *itv) ...@@ -691,11 +743,9 @@ static void ivtv_irq_vsync(struct ivtv *itv)
itv->yuv_info.new_frame_info[last_dma_frame].update = 0; itv->yuv_info.new_frame_info[last_dma_frame].update = 0;
itv->yuv_info.yuv_forced_update = 0; itv->yuv_info.yuv_forced_update = 0;
set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags); set_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags);
work = 1; set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
} }
} }
if (work)
queue_work(itv->irq_work_queues, &itv->irq_work_queue);
} }
} }
...@@ -755,6 +805,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) ...@@ -755,6 +805,10 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
ivtv_irq_enc_dma_complete(itv); ivtv_irq_enc_dma_complete(itv);
} }
if (combo & IVTV_IRQ_ENC_PIO_COMPLETE) {
ivtv_irq_enc_pio_complete(itv);
}
if (combo & IVTV_IRQ_DMA_ERR) { if (combo & IVTV_IRQ_DMA_ERR) {
ivtv_irq_dma_err(itv); ivtv_irq_dma_err(itv);
} }
...@@ -768,7 +822,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) ...@@ -768,7 +822,7 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
} }
if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) { if (combo & IVTV_IRQ_DEC_VBI_RE_INSERT) {
ivtv_irq_dev_vbi_reinsert(itv); ivtv_irq_dec_vbi_reinsert(itv);
} }
if (combo & IVTV_IRQ_ENC_EOS) { if (combo & IVTV_IRQ_ENC_EOS) {
...@@ -813,6 +867,22 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id) ...@@ -813,6 +867,22 @@ irqreturn_t ivtv_irq_handler(int irq, void *dev_id)
} }
} }
if ((combo & IVTV_IRQ_DMA) && !test_bit(IVTV_F_I_PIO, &itv->i_flags)) {
for (i = 0; i < IVTV_MAX_STREAMS; i++) {
int idx = (i + itv->irq_rr_idx++) % IVTV_MAX_STREAMS;
struct ivtv_stream *s = &itv->streams[idx];
if (!test_and_clear_bit(IVTV_F_S_PIO_PENDING, &s->s_flags))
continue;
if (s->type == IVTV_DEC_STREAM_TYPE_VBI || s->type < IVTV_DEC_STREAM_TYPE_MPG)
ivtv_dma_enc_start(s);
break;
}
}
if (test_and_clear_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags))
queue_work(itv->irq_work_queues, &itv->irq_work_queue);
spin_unlock(&itv->dma_reg_lock); spin_unlock(&itv->dma_reg_lock);
/* If we've just handled a 'forced' vsync, it's safest to say it /* If we've just handled a 'forced' vsync, it's safest to say it
......
...@@ -195,14 +195,26 @@ int ivtv_stream_alloc(struct ivtv_stream *s) ...@@ -195,14 +195,26 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
s->dma != PCI_DMA_NONE ? "DMA " : "", s->dma != PCI_DMA_NONE ? "DMA " : "",
s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024); s->name, s->buffers, s->buf_size, s->buffers * s->buf_size / 1024);
/* Allocate DMA SG Arrays */ if (ivtv_might_use_pio(s)) {
if (s->dma != PCI_DMA_NONE) { s->PIOarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL); if (s->PIOarray == NULL) {
if (s->SGarray == NULL) { IVTV_ERR("Could not allocate PIOarray for %s stream\n", s->name);
IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
return -ENOMEM; return -ENOMEM;
} }
s->SG_length = 0; }
/* Allocate DMA SG Arrays */
s->SGarray = (struct ivtv_SG_element *)kzalloc(SGsize, GFP_KERNEL);
if (s->SGarray == NULL) {
IVTV_ERR("Could not allocate SGarray for %s stream\n", s->name);
if (ivtv_might_use_pio(s)) {
kfree(s->PIOarray);
s->PIOarray = NULL;
}
return -ENOMEM;
}
s->SG_length = 0;
if (ivtv_might_use_dma(s)) {
s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma); s->SG_handle = pci_map_single(itv->dev, s->SGarray, SGsize, s->dma);
ivtv_stream_sync_for_cpu(s); ivtv_stream_sync_for_cpu(s);
} }
...@@ -219,7 +231,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s) ...@@ -219,7 +231,7 @@ int ivtv_stream_alloc(struct ivtv_stream *s)
break; break;
} }
INIT_LIST_HEAD(&buf->list); INIT_LIST_HEAD(&buf->list);
if (s->dma != PCI_DMA_NONE) { if (ivtv_might_use_dma(s)) {
buf->dma_handle = pci_map_single(s->itv->dev, buf->dma_handle = pci_map_single(s->itv->dev,
buf->buf, s->buf_size + 256, s->dma); buf->buf, s->buf_size + 256, s->dma);
ivtv_buf_sync_for_cpu(s, buf); ivtv_buf_sync_for_cpu(s, buf);
...@@ -242,7 +254,7 @@ void ivtv_stream_free(struct ivtv_stream *s) ...@@ -242,7 +254,7 @@ void ivtv_stream_free(struct ivtv_stream *s)
/* empty q_free */ /* empty q_free */
while ((buf = ivtv_dequeue(s, &s->q_free))) { while ((buf = ivtv_dequeue(s, &s->q_free))) {
if (s->dma != PCI_DMA_NONE) if (ivtv_might_use_dma(s))
pci_unmap_single(s->itv->dev, buf->dma_handle, pci_unmap_single(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma); s->buf_size + 256, s->dma);
kfree(buf->buf); kfree(buf->buf);
...@@ -256,6 +268,9 @@ void ivtv_stream_free(struct ivtv_stream *s) ...@@ -256,6 +268,9 @@ void ivtv_stream_free(struct ivtv_stream *s)
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
s->SG_handle = IVTV_DMA_UNMAPPED; s->SG_handle = IVTV_DMA_UNMAPPED;
} }
kfree(s->SGarray);
kfree(s->PIOarray);
s->PIOarray = NULL;
s->SGarray = NULL; s->SGarray = NULL;
s->SG_length = 0; s->SG_length = 0;
} }
......
...@@ -20,18 +20,43 @@ ...@@ -20,18 +20,43 @@
*/ */
#define IVTV_DMA_UNMAPPED ((u32) -1) #define IVTV_DMA_UNMAPPED ((u32) -1)
#define SLICED_VBI_PIO 1
/* ivtv_buffer utility functions */ /* ivtv_buffer utility functions */
static inline int ivtv_might_use_pio(struct ivtv_stream *s)
{
return s->dma == PCI_DMA_NONE || (SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI);
}
static inline int ivtv_use_pio(struct ivtv_stream *s)
{
struct ivtv *itv = s->itv;
return s->dma == PCI_DMA_NONE ||
(SLICED_VBI_PIO && s->type == IVTV_ENC_STREAM_TYPE_VBI && itv->vbi.sliced_in->service_set);
}
static inline int ivtv_might_use_dma(struct ivtv_stream *s)
{
return s->dma != PCI_DMA_NONE;
}
static inline int ivtv_use_dma(struct ivtv_stream *s)
{
return !ivtv_use_pio(s);
}
static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf) static inline void ivtv_buf_sync_for_cpu(struct ivtv_stream *s, struct ivtv_buffer *buf)
{ {
if (s->dma != PCI_DMA_NONE) if (ivtv_use_dma(s))
pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle, pci_dma_sync_single_for_cpu(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma); s->buf_size + 256, s->dma);
} }
static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf) static inline void ivtv_buf_sync_for_device(struct ivtv_stream *s, struct ivtv_buffer *buf)
{ {
if (s->dma != PCI_DMA_NONE) if (ivtv_use_dma(s))
pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle, pci_dma_sync_single_for_device(s->itv->dev, buf->dma_handle,
s->buf_size + 256, s->dma); s->buf_size + 256, s->dma);
} }
...@@ -53,12 +78,14 @@ void ivtv_stream_free(struct ivtv_stream *s); ...@@ -53,12 +78,14 @@ void ivtv_stream_free(struct ivtv_stream *s);
static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s) static inline void ivtv_stream_sync_for_cpu(struct ivtv_stream *s)
{ {
pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle, if (ivtv_use_dma(s))
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); pci_dma_sync_single_for_cpu(s->itv->dev, s->SG_handle,
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
} }
static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s) static inline void ivtv_stream_sync_for_device(struct ivtv_stream *s)
{ {
pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle, if (ivtv_use_dma(s))
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE); pci_dma_sync_single_for_device(s->itv->dev, s->SG_handle,
sizeof(struct ivtv_SG_element) * s->buffers, PCI_DMA_TODEVICE);
} }
...@@ -868,7 +868,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts) ...@@ -868,7 +868,7 @@ int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags)) if (!test_bit(IVTV_F_S_STREAMING, &s->s_flags))
return 0; return 0;
IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", pts, flags); IVTV_DEBUG_INFO("Stop Decode at %llu, flags: %x\n", (unsigned long long)pts, flags);
/* Stop Decoder */ /* Stop Decoder */
if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) { if (!(flags & VIDEO_CMD_STOP_IMMEDIATELY) || pts) {
......
...@@ -450,7 +450,7 @@ void ivtv_disable_vbi(struct ivtv *itv) ...@@ -450,7 +450,7 @@ void ivtv_disable_vbi(struct ivtv *itv)
} }
void vbi_work_handler(struct ivtv *itv) void ivtv_vbi_work_handler(struct ivtv *itv)
{ {
struct v4l2_sliced_vbi_data data; struct v4l2_sliced_vbi_data data;
......
...@@ -23,4 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf, ...@@ -23,4 +23,4 @@ void ivtv_process_vbi_data(struct ivtv *itv, struct ivtv_buffer *buf,
int ivtv_used_line(struct ivtv *itv, int line, int field); int ivtv_used_line(struct ivtv *itv, int line, int field);
void ivtv_disable_vbi(struct ivtv *itv); void ivtv_disable_vbi(struct ivtv *itv);
void ivtv_set_vbi(unsigned long arg); void ivtv_set_vbi(unsigned long arg);
void vbi_work_handler(struct ivtv *itv); void ivtv_vbi_work_handler(struct ivtv *itv);
...@@ -75,10 +75,6 @@ struct saa7111 { ...@@ -75,10 +75,6 @@ struct saa7111 {
int norm; int norm;
int input; int input;
int enable; int enable;
int bright;
int contrast;
int hue;
int sat;
}; };
#define I2C_SAA7111 0x48 #define I2C_SAA7111 0x48
...@@ -96,6 +92,17 @@ saa7111_write (struct i2c_client *client, ...@@ -96,6 +92,17 @@ saa7111_write (struct i2c_client *client,
return i2c_smbus_write_byte_data(client, reg, value); return i2c_smbus_write_byte_data(client, reg, value);
} }
static inline void
saa7111_write_if_changed(struct i2c_client *client, u8 reg, u8 value)
{
struct saa7111 *decoder = i2c_get_clientdata(client);
if (decoder->reg[reg] != value) {
decoder->reg[reg] = value;
i2c_smbus_write_byte_data(client, reg, value);
}
}
static int static int
saa7111_write_block (struct i2c_client *client, saa7111_write_block (struct i2c_client *client,
const u8 *data, const u8 *data,
...@@ -439,28 +446,14 @@ saa7111_command (struct i2c_client *client, ...@@ -439,28 +446,14 @@ saa7111_command (struct i2c_client *client,
{ {
struct video_picture *pic = arg; struct video_picture *pic = arg;
if (decoder->bright != pic->brightness) { /* We want 0 to 255 we get 0-65535 */
/* We want 0 to 255 we get 0-65535 */ saa7111_write_if_changed(client, 0x0a, pic->brightness >> 8);
decoder->bright = pic->brightness; /* We want 0 to 127 we get 0-65535 */
saa7111_write(client, 0x0a, decoder->bright >> 8); saa7111_write(client, 0x0b, pic->contrast >> 9);
} /* We want 0 to 127 we get 0-65535 */
if (decoder->contrast != pic->contrast) { saa7111_write(client, 0x0c, pic->colour >> 9);
/* We want 0 to 127 we get 0-65535 */ /* We want -128 to 127 we get 0-65535 */
decoder->contrast = pic->contrast; saa7111_write(client, 0x0d, (pic->hue - 32768) >> 8);
saa7111_write(client, 0x0b,
decoder->contrast >> 9);
}
if (decoder->sat != pic->colour) {
/* We want 0 to 127 we get 0-65535 */
decoder->sat = pic->colour;
saa7111_write(client, 0x0c, decoder->sat >> 9);
}
if (decoder->hue != pic->hue) {
/* We want -128 to 127 we get 0-65535 */
decoder->hue = pic->hue;
saa7111_write(client, 0x0d,
(decoder->hue - 32768) >> 8);
}
} }
break; break;
...@@ -524,10 +517,6 @@ saa7111_detect_client (struct i2c_adapter *adapter, ...@@ -524,10 +517,6 @@ saa7111_detect_client (struct i2c_adapter *adapter,
decoder->norm = VIDEO_MODE_NTSC; decoder->norm = VIDEO_MODE_NTSC;
decoder->input = 0; decoder->input = 0;
decoder->enable = 1; decoder->enable = 1;
decoder->bright = 32768;
decoder->contrast = 32768;
decoder->hue = 32768;
decoder->sat = 32768;
i2c_set_clientdata(client, decoder); i2c_set_clientdata(client, decoder);
i = i2c_attach_client(client); i = i2c_attach_client(client);
......
...@@ -1414,6 +1414,11 @@ static void usbvision_isocIrq(struct urb *urb) ...@@ -1414,6 +1414,11 @@ static void usbvision_isocIrq(struct urb *urb)
if (!USBVISION_IS_OPERATIONAL(usbvision)) if (!USBVISION_IS_OPERATIONAL(usbvision))
return; return;
/* any urb with wrong status is ignored without acknowledgement */
if (urb->status == -ENOENT) {
return;
}
f = &usbvision->curFrame; f = &usbvision->curFrame;
/* Manage streaming interruption */ /* Manage streaming interruption */
...@@ -1436,18 +1441,21 @@ static void usbvision_isocIrq(struct urb *urb) ...@@ -1436,18 +1441,21 @@ static void usbvision_isocIrq(struct urb *urb)
if (usbvision->streaming == Stream_On) { if (usbvision->streaming == Stream_On) {
/* If we collected enough data let's parse! */ /* If we collected enough data let's parse! */
if (scratch_len(usbvision) > USBVISION_HEADER_LENGTH) { /* 12 == header_length */ if ((scratch_len(usbvision) > USBVISION_HEADER_LENGTH) &&
/*If we don't have a frame we're current working on, complain */ (!list_empty(&(usbvision->inqueue))) ) {
if(!list_empty(&(usbvision->inqueue))) { if (!(*f)) {
if (!(*f)) { (*f) = list_entry(usbvision->inqueue.next,
(*f) = list_entry(usbvision->inqueue.next,struct usbvision_frame, frame); struct usbvision_frame,
} frame);
usbvision_parse_data(usbvision);
}
else {
PDEBUG(DBG_IRQ, "received data, but no one needs it");
scratch_reset(usbvision);
} }
usbvision_parse_data(usbvision);
}
else {
/*If we don't have a frame
we're current working on, complain */
PDEBUG(DBG_IRQ,
"received data, but no one needs it");
scratch_reset(usbvision);
} }
} }
else { else {
...@@ -1466,10 +1474,10 @@ static void usbvision_isocIrq(struct urb *urb) ...@@ -1466,10 +1474,10 @@ static void usbvision_isocIrq(struct urb *urb)
urb->dev = usbvision->dev; urb->dev = usbvision->dev;
errCode = usb_submit_urb (urb, GFP_ATOMIC); errCode = usb_submit_urb (urb, GFP_ATOMIC);
/* Disable this warning. By design of the driver. */ if(errCode) {
// if(errCode) { err("%s: usb_submit_urb failed: error %d",
// err("%s: usb_submit_urb failed: error %d", __FUNCTION__, errCode); __FUNCTION__, errCode);
// } }
return; return;
} }
...@@ -2394,7 +2402,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) ...@@ -2394,7 +2402,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
{ {
struct usb_device *dev = usbvision->dev; struct usb_device *dev = usbvision->dev;
int bufIdx, errCode, regValue; int bufIdx, errCode, regValue;
const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; int sb_size;
if (!USBVISION_IS_OPERATIONAL(usbvision)) if (!USBVISION_IS_OPERATIONAL(usbvision))
return -EFAULT; return -EFAULT;
...@@ -2408,11 +2416,14 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) ...@@ -2408,11 +2416,14 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
usbvision->last_error = errCode; usbvision->last_error = errCode;
return -EBUSY; return -EBUSY;
} }
sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; regValue = (16 - usbvision_read_reg(usbvision,
USBVISION_ALTER_REG)) & 0x0F;
usbvision->usb_bandwidth = regValue >> 1; usbvision->usb_bandwidth = regValue >> 1;
PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
usbvision->usb_bandwidth);
...@@ -2428,7 +2439,11 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) ...@@ -2428,7 +2439,11 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
return -ENOMEM; return -ENOMEM;
} }
usbvision->sbuf[bufIdx].urb = urb; usbvision->sbuf[bufIdx].urb = urb;
usbvision->sbuf[bufIdx].data = usb_buffer_alloc(usbvision->dev, sb_size, GFP_KERNEL,&urb->transfer_dma); usbvision->sbuf[bufIdx].data =
usb_buffer_alloc(usbvision->dev,
sb_size,
GFP_KERNEL,
&urb->transfer_dma);
urb->dev = dev; urb->dev = dev;
urb->context = usbvision; urb->context = usbvision;
urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp); urb->pipe = usb_rcvisocpipe(dev, usbvision->video_endp);
...@@ -2442,21 +2457,26 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) ...@@ -2442,21 +2457,26 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
for (j = k = 0; j < USBVISION_URB_FRAMES; j++, for (j = k = 0; j < USBVISION_URB_FRAMES; j++,
k += usbvision->isocPacketSize) { k += usbvision->isocPacketSize) {
urb->iso_frame_desc[j].offset = k; urb->iso_frame_desc[j].offset = k;
urb->iso_frame_desc[j].length = usbvision->isocPacketSize; urb->iso_frame_desc[j].length =
usbvision->isocPacketSize;
} }
} }
/* Submit all URBs */ /* Submit all URBs */
for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) { for (bufIdx = 0; bufIdx < USBVISION_NUMSBUF; bufIdx++) {
errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb, GFP_KERNEL); errCode = usb_submit_urb(usbvision->sbuf[bufIdx].urb,
GFP_KERNEL);
if (errCode) { if (errCode) {
err("%s: usb_submit_urb(%d) failed: error %d", __FUNCTION__, bufIdx, errCode); err("%s: usb_submit_urb(%d) failed: error %d",
__FUNCTION__, bufIdx, errCode);
} }
} }
usbvision->streaming = Stream_Idle; usbvision->streaming = Stream_Idle;
PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x", __FUNCTION__, usbvision->video_endp); PDEBUG(DBG_ISOC, "%s: streaming=1 usbvision->video_endp=$%02x",
__FUNCTION__,
usbvision->video_endp);
return 0; return 0;
} }
...@@ -2470,7 +2490,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision) ...@@ -2470,7 +2490,7 @@ int usbvision_init_isoc(struct usb_usbvision *usbvision)
void usbvision_stop_isoc(struct usb_usbvision *usbvision) void usbvision_stop_isoc(struct usb_usbvision *usbvision)
{ {
int bufIdx, errCode, regValue; int bufIdx, errCode, regValue;
const int sb_size = USBVISION_URB_FRAMES * USBVISION_MAX_ISOC_PACKET_SIZE; int sb_size = USBVISION_URB_FRAMES * usbvision->isocPacketSize;
if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL)) if ((usbvision->streaming == Stream_Off) || (usbvision->dev == NULL))
return; return;
...@@ -2499,15 +2519,19 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision) ...@@ -2499,15 +2519,19 @@ void usbvision_stop_isoc(struct usb_usbvision *usbvision)
errCode = usb_set_interface(usbvision->dev, usbvision->iface, errCode = usb_set_interface(usbvision->dev, usbvision->iface,
usbvision->ifaceAlt); usbvision->ifaceAlt);
if (errCode < 0) { if (errCode < 0) {
err("%s: usb_set_interface() failed: error %d", __FUNCTION__, errCode); err("%s: usb_set_interface() failed: error %d",
__FUNCTION__, errCode);
usbvision->last_error = errCode; usbvision->last_error = errCode;
} }
regValue = (16 - usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F; regValue = (16-usbvision_read_reg(usbvision, USBVISION_ALTER_REG)) & 0x0F;
usbvision->isocPacketSize = (regValue == 0) ? 0 : (regValue * 64) - 1; usbvision->isocPacketSize =
PDEBUG(DBG_ISOC, "ISO Packet Length:%d", usbvision->isocPacketSize); (regValue == 0) ? 0 : (regValue * 64) - 1;
PDEBUG(DBG_ISOC, "ISO Packet Length:%d",
usbvision->isocPacketSize);
usbvision->usb_bandwidth = regValue >> 1; usbvision->usb_bandwidth = regValue >> 1;
PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec", usbvision->usb_bandwidth); PDEBUG(DBG_ISOC, "USB Bandwidth Usage: %dMbit/Sec",
usbvision->usb_bandwidth);
} }
} }
......
...@@ -146,7 +146,6 @@ ...@@ -146,7 +146,6 @@
#define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask #define USBVISION_CLIPMASK_SIZE (MAX_FRAME_WIDTH * MAX_FRAME_HEIGHT / 8) //bytesize of clipmask
#define USBVISION_URB_FRAMES 32 #define USBVISION_URB_FRAMES 32
#define USBVISION_MAX_ISOC_PACKET_SIZE 959 // NT1003 Specs Document says 1023
#define USBVISION_NUM_HEADERMARKER 20 #define USBVISION_NUM_HEADERMARKER 20
#define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */ #define USBVISION_NUMFRAMES 3 /* Maximum number of frames an application can get */
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
#include <linux/mmc/host.h> #include <linux/mmc/host.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
#include <linux/mmc/mmc.h> #include <linux/mmc/mmc.h>
#include <linux/mmc/sd.h>
#include "core.h" #include "core.h"
#include "sysfs.h" #include "sysfs.h"
...@@ -192,6 +193,16 @@ static int mmc_read_switch(struct mmc_card *card) ...@@ -192,6 +193,16 @@ static int mmc_read_switch(struct mmc_card *card)
int err; int err;
u8 *status; u8 *status;
if (card->scr.sda_vsn < SCR_SPEC_VER_1)
return MMC_ERR_NONE;
if (!(card->csd.cmdclass & CCC_SWITCH)) {
printk(KERN_WARNING "%s: card lacks mandatory switch "
"function, performance might suffer.\n",
mmc_hostname(card->host));
return MMC_ERR_NONE;
}
err = MMC_ERR_FAILED; err = MMC_ERR_FAILED;
status = kmalloc(64, GFP_KERNEL); status = kmalloc(64, GFP_KERNEL);
...@@ -204,10 +215,9 @@ static int mmc_read_switch(struct mmc_card *card) ...@@ -204,10 +215,9 @@ static int mmc_read_switch(struct mmc_card *card)
err = mmc_sd_switch(card, 0, 0, 1, status); err = mmc_sd_switch(card, 0, 0, 1, status);
if (err != MMC_ERR_NONE) { if (err != MMC_ERR_NONE) {
/* printk(KERN_WARNING "%s: problem reading switch "
* Card not supporting high-speed will ignore the "capabilities, performance might suffer.\n",
* command. mmc_hostname(card->host));
*/
err = MMC_ERR_NONE; err = MMC_ERR_NONE;
goto out; goto out;
} }
...@@ -229,6 +239,12 @@ static int mmc_switch_hs(struct mmc_card *card) ...@@ -229,6 +239,12 @@ static int mmc_switch_hs(struct mmc_card *card)
int err; int err;
u8 *status; u8 *status;
if (card->scr.sda_vsn < SCR_SPEC_VER_1)
return MMC_ERR_NONE;
if (!(card->csd.cmdclass & CCC_SWITCH))
return MMC_ERR_NONE;
if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED))
return MMC_ERR_NONE; return MMC_ERR_NONE;
...@@ -402,7 +418,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr, ...@@ -402,7 +418,7 @@ static int mmc_sd_init_card(struct mmc_host *host, u32 ocr,
/* /*
* Switch to wider bus (if supported). * Switch to wider bus (if supported).
*/ */
if ((host->caps && MMC_CAP_4_BIT_DATA) && if ((host->caps & MMC_CAP_4_BIT_DATA) &&
(card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) { (card->scr.bus_widths & SD_SCR_BUS_WIDTH_4)) {
err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4); err = mmc_app_set_bus_width(card, MMC_BUS_WIDTH_4);
if (err != MMC_ERR_NONE) if (err != MMC_ERR_NONE)
......
...@@ -417,7 +417,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_ ...@@ -417,7 +417,7 @@ static unsigned int at91_mci_send_command(struct at91mci_host *host, struct mmc_
blocks = 0; blocks = 0;
} }
if (cmd->opcode == MMC_STOP_TRANSMISSION) if (host->flags & FL_SENT_STOP)
cmdr |= AT91_MCI_TRCMD_STOP; cmdr |= AT91_MCI_TRCMD_STOP;
if (host->bus_mode == MMC_BUSMODE_OPENDRAIN) if (host->bus_mode == MMC_BUSMODE_OPENDRAIN)
...@@ -563,8 +563,7 @@ static void at91mci_completed_command(struct at91mci_host *host) ...@@ -563,8 +563,7 @@ static void at91mci_completed_command(struct at91mci_host *host)
if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE | if (status & (AT91_MCI_RINDE | AT91_MCI_RDIRE | AT91_MCI_RCRCE |
AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE | AT91_MCI_RENDE | AT91_MCI_RTOE | AT91_MCI_DCRCE |
AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) { AT91_MCI_DTOE | AT91_MCI_OVRE | AT91_MCI_UNRE)) {
if ((status & AT91_MCI_RCRCE) && if ((status & AT91_MCI_RCRCE) && !(mmc_resp_type(cmd) & MMC_RSP_CRC)) {
((cmd->opcode == MMC_SEND_OP_COND) || (cmd->opcode == SD_APP_OP_COND))) {
cmd->error = MMC_ERR_NONE; cmd->error = MMC_ERR_NONE;
} }
else { else {
......
...@@ -76,8 +76,7 @@ const struct { ...@@ -76,8 +76,7 @@ const struct {
#endif #endif
}; };
#define AU1XMMC_CONTROLLER_COUNT \ #define AU1XMMC_CONTROLLER_COUNT (ARRAY_SIZE(au1xmmc_card_table))
(sizeof(au1xmmc_card_table) / sizeof(au1xmmc_card_table[0]))
/* This array stores pointers for the hosts (used by the IRQ handler) */ /* This array stores pointers for the hosts (used by the IRQ handler) */
struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT]; struct au1xmmc_host *au1xmmc_hosts[AU1XMMC_CONTROLLER_COUNT];
......
...@@ -61,7 +61,7 @@ struct mlx4_cq_context { ...@@ -61,7 +61,7 @@ struct mlx4_cq_context {
__be32 solicit_producer_index; __be32 solicit_producer_index;
__be32 consumer_index; __be32 consumer_index;
__be32 producer_index; __be32 producer_index;
u8 reserved6[2]; u32 reserved6[2];
__be64 db_rec_addr; __be64 db_rec_addr;
}; };
......
...@@ -490,9 +490,11 @@ static void mlx4_free_irqs(struct mlx4_dev *dev) ...@@ -490,9 +490,11 @@ static void mlx4_free_irqs(struct mlx4_dev *dev)
if (eq_table->have_irq) if (eq_table->have_irq)
free_irq(dev->pdev->irq, dev); free_irq(dev->pdev->irq, dev);
for (i = 0; i < MLX4_NUM_EQ; ++i) for (i = 0; i < MLX4_EQ_CATAS; ++i)
if (eq_table->eq[i].have_irq) if (eq_table->eq[i].have_irq)
free_irq(eq_table->eq[i].irq, eq_table->eq + i); free_irq(eq_table->eq[i].irq, eq_table->eq + i);
if (eq_table->eq[MLX4_EQ_CATAS].have_irq)
free_irq(eq_table->eq[MLX4_EQ_CATAS].irq, dev);
} }
static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev) static int __devinit mlx4_map_clr_int(struct mlx4_dev *dev)
......
...@@ -37,6 +37,10 @@ ...@@ -37,6 +37,10 @@
#include "fw.h" #include "fw.h"
#include "icm.h" #include "icm.h"
enum {
MLX4_COMMAND_INTERFACE_REV = 1
};
extern void __buggy_use_of_MLX4_GET(void); extern void __buggy_use_of_MLX4_GET(void);
extern void __buggy_use_of_MLX4_PUT(void); extern void __buggy_use_of_MLX4_PUT(void);
...@@ -452,10 +456,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) ...@@ -452,10 +456,12 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
u32 *outbox; u32 *outbox;
int err = 0; int err = 0;
u64 fw_ver; u64 fw_ver;
u16 cmd_if_rev;
u8 lg; u8 lg;
#define QUERY_FW_OUT_SIZE 0x100 #define QUERY_FW_OUT_SIZE 0x100
#define QUERY_FW_VER_OFFSET 0x00 #define QUERY_FW_VER_OFFSET 0x00
#define QUERY_FW_CMD_IF_REV_OFFSET 0x0a
#define QUERY_FW_MAX_CMD_OFFSET 0x0f #define QUERY_FW_MAX_CMD_OFFSET 0x0f
#define QUERY_FW_ERR_START_OFFSET 0x30 #define QUERY_FW_ERR_START_OFFSET 0x30
#define QUERY_FW_ERR_SIZE_OFFSET 0x38 #define QUERY_FW_ERR_SIZE_OFFSET 0x38
...@@ -477,21 +483,36 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev) ...@@ -477,21 +483,36 @@ int mlx4_QUERY_FW(struct mlx4_dev *dev)
MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET); MLX4_GET(fw_ver, outbox, QUERY_FW_VER_OFFSET);
/* /*
* FW subminor version is at more signifant bits than minor * FW subminor version is at more significant bits than minor
* version, so swap here. * version, so swap here.
*/ */
dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) | dev->caps.fw_ver = (fw_ver & 0xffff00000000ull) |
((fw_ver & 0xffff0000ull) >> 16) | ((fw_ver & 0xffff0000ull) >> 16) |
((fw_ver & 0x0000ffffull) << 16); ((fw_ver & 0x0000ffffull) << 16);
MLX4_GET(cmd_if_rev, outbox, QUERY_FW_CMD_IF_REV_OFFSET);
if (cmd_if_rev != MLX4_COMMAND_INTERFACE_REV) {
mlx4_err(dev, "Installed FW has unsupported "
"command interface revision %d.\n",
cmd_if_rev);
mlx4_err(dev, "(Installed FW version is %d.%d.%03d)\n",
(int) (dev->caps.fw_ver >> 32),
(int) (dev->caps.fw_ver >> 16) & 0xffff,
(int) dev->caps.fw_ver & 0xffff);
mlx4_err(dev, "This driver version supports only revision %d.\n",
MLX4_COMMAND_INTERFACE_REV);
err = -ENODEV;
goto out;
}
MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET); MLX4_GET(lg, outbox, QUERY_FW_MAX_CMD_OFFSET);
cmd->max_cmds = 1 << lg; cmd->max_cmds = 1 << lg;
mlx4_dbg(dev, "FW version %d.%d.%03d, max commands %d\n", mlx4_dbg(dev, "FW version %d.%d.%03d (cmd intf rev %d), max commands %d\n",
(int) (dev->caps.fw_ver >> 32), (int) (dev->caps.fw_ver >> 32),
(int) (dev->caps.fw_ver >> 16) & 0xffff, (int) (dev->caps.fw_ver >> 16) & 0xffff,
(int) dev->caps.fw_ver & 0xffff, (int) dev->caps.fw_ver & 0xffff,
cmd->max_cmds); cmd_if_rev, cmd->max_cmds);
MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET); MLX4_GET(fw->catas_offset, outbox, QUERY_FW_ERR_START_OFFSET);
MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET); MLX4_GET(fw->catas_size, outbox, QUERY_FW_ERR_SIZE_OFFSET);
......
...@@ -135,9 +135,6 @@ int mlx4_register_device(struct mlx4_dev *dev) ...@@ -135,9 +135,6 @@ int mlx4_register_device(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
struct mlx4_interface *intf; struct mlx4_interface *intf;
INIT_LIST_HEAD(&priv->ctx_list);
spin_lock_init(&priv->ctx_lock);
mutex_lock(&intf_mutex); mutex_lock(&intf_mutex);
list_add_tail(&priv->dev_list, &dev_list); list_add_tail(&priv->dev_list, &dev_list);
......
...@@ -787,6 +787,8 @@ static int __devinit mlx4_init_one(struct pci_dev *pdev, ...@@ -787,6 +787,8 @@ static int __devinit mlx4_init_one(struct pci_dev *pdev,
dev = &priv->dev; dev = &priv->dev;
dev->pdev = pdev; dev->pdev = pdev;
INIT_LIST_HEAD(&priv->ctx_list);
spin_lock_init(&priv->ctx_lock);
/* /*
* Now reset the HCA before we touch the PCI capabilities or * Now reset the HCA before we touch the PCI capabilities or
......
...@@ -324,15 +324,17 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr) ...@@ -324,15 +324,17 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
MLX4_MPT_FLAG_MIO | MLX4_MPT_FLAG_MIO |
MLX4_MPT_FLAG_REGION | MLX4_MPT_FLAG_REGION |
mr->access); mr->access);
if (mr->mtt.order < 0)
mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key)); mpt_entry->key = cpu_to_be32(key_to_hw_index(mr->key));
mpt_entry->pd = cpu_to_be32(mr->pd); mpt_entry->pd = cpu_to_be32(mr->pd);
mpt_entry->start = cpu_to_be64(mr->iova); mpt_entry->start = cpu_to_be64(mr->iova);
mpt_entry->length = cpu_to_be64(mr->size); mpt_entry->length = cpu_to_be64(mr->size);
mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift);
mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt)); if (mr->mtt.order < 0) {
mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL);
mpt_entry->mtt_seg = 0;
} else
mpt_entry->mtt_seg = cpu_to_be64(mlx4_mtt_addr(dev, &mr->mtt));
err = mlx4_SW2HW_MPT(dev, mailbox, err = mlx4_SW2HW_MPT(dev, mailbox,
key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1)); key_to_hw_index(mr->key) & (dev->caps.num_mpts - 1));
......
...@@ -7,16 +7,16 @@ ...@@ -7,16 +7,16 @@
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details. * the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/fs.h> #include <linux/fs.h>
...@@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length) ...@@ -39,7 +39,7 @@ cifs_dump_mem(char *label, void *data, int length)
char *charptr = data; char *charptr = data;
char buf[10], line[80]; char buf[10], line[80];
printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n", printk(KERN_DEBUG "%s: dump of %d bytes of data at 0x%p\n",
label, length, data); label, length, data);
for (i = 0; i < length; i += 16) { for (i = 0; i < length; i += 16) {
line[0] = 0; line[0] = 0;
...@@ -60,10 +60,10 @@ cifs_dump_mem(char *label, void *data, int length) ...@@ -60,10 +60,10 @@ cifs_dump_mem(char *label, void *data, int length)
#ifdef CONFIG_CIFS_DEBUG2 #ifdef CONFIG_CIFS_DEBUG2
void cifs_dump_detail(struct smb_hdr * smb) void cifs_dump_detail(struct smb_hdr * smb)
{ {
cERROR(1,("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d", cERROR(1, ("Cmd: %d Err: 0x%x Flags: 0x%x Flgs2: 0x%x Mid: %d Pid: %d",
smb->Command, smb->Status.CifsError, smb->Command, smb->Status.CifsError,
smb->Flags, smb->Flags2, smb->Mid, smb->Pid)); smb->Flags, smb->Flags2, smb->Mid, smb->Pid));
cERROR(1,("smb buf %p len %d", smb, smbCalcSize_LE(smb))); cERROR(1, ("smb buf %p len %d", smb, smbCalcSize_LE(smb)));
} }
...@@ -72,36 +72,35 @@ void cifs_dump_mids(struct TCP_Server_Info * server) ...@@ -72,36 +72,35 @@ void cifs_dump_mids(struct TCP_Server_Info * server)
struct list_head *tmp; struct list_head *tmp;
struct mid_q_entry * mid_entry; struct mid_q_entry * mid_entry;
if(server == NULL) if (server == NULL)
return; return;
cERROR(1,("Dump pending requests:")); cERROR(1, ("Dump pending requests:"));
spin_lock(&GlobalMid_Lock); spin_lock(&GlobalMid_Lock);
list_for_each(tmp, &server->pending_mid_q) { list_for_each(tmp, &server->pending_mid_q) {
mid_entry = list_entry(tmp, struct mid_q_entry, qhead); mid_entry = list_entry(tmp, struct mid_q_entry, qhead);
if(mid_entry) { if (mid_entry) {
cERROR(1,("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d", cERROR(1, ("State: %d Cmd: %d Pid: %d Tsk: %p Mid %d",
mid_entry->midState, mid_entry->midState,
(int)mid_entry->command, (int)mid_entry->command,
mid_entry->pid, mid_entry->pid,
mid_entry->tsk, mid_entry->tsk,
mid_entry->mid)); mid_entry->mid));
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
cERROR(1,("IsLarge: %d buf: %p time rcv: %ld now: %ld", cERROR(1, ("IsLarge: %d buf: %p time rcv: %ld now: %ld",
mid_entry->largeBuf, mid_entry->largeBuf,
mid_entry->resp_buf, mid_entry->resp_buf,
mid_entry->when_received, mid_entry->when_received,
jiffies)); jiffies));
#endif /* STATS2 */ #endif /* STATS2 */
cERROR(1,("IsMult: %d IsEnd: %d", mid_entry->multiRsp, cERROR(1, ("IsMult: %d IsEnd: %d", mid_entry->multiRsp,
mid_entry->multiEnd)); mid_entry->multiEnd));
if(mid_entry->resp_buf) { if (mid_entry->resp_buf) {
cifs_dump_detail(mid_entry->resp_buf); cifs_dump_detail(mid_entry->resp_buf);
cifs_dump_mem("existing buf: ", cifs_dump_mem("existing buf: ",
mid_entry->resp_buf, mid_entry->resp_buf,
62 /* fixme */); 62 /* fixme */);
} }
} }
} }
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
...@@ -129,9 +128,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -129,9 +128,10 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
"Display Internal CIFS Data Structures for Debugging\n" "Display Internal CIFS Data Structures for Debugging\n"
"---------------------------------------------------\n"); "---------------------------------------------------\n");
buf += length; buf += length;
length = sprintf(buf,"CIFS Version %s\n",CIFS_VERSION); length = sprintf(buf, "CIFS Version %s\n", CIFS_VERSION);
buf += length; buf += length;
length = sprintf(buf,"Active VFS Requests: %d\n", GlobalTotalActiveXid); length = sprintf(buf,
"Active VFS Requests: %d\n", GlobalTotalActiveXid);
buf += length; buf += length;
length = sprintf(buf, "Servers:"); length = sprintf(buf, "Servers:");
buf += length; buf += length;
...@@ -141,7 +141,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -141,7 +141,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
list_for_each(tmp, &GlobalSMBSessionList) { list_for_each(tmp, &GlobalSMBSessionList) {
i++; i++;
ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList); ses = list_entry(tmp, struct cifsSesInfo, cifsSessionList);
if((ses->serverDomain == NULL) || (ses->serverOS == NULL) || if ((ses->serverDomain == NULL) || (ses->serverOS == NULL) ||
(ses->serverNOS == NULL)) { (ses->serverNOS == NULL)) {
buf += sprintf(buf, "\nentry for %s not fully " buf += sprintf(buf, "\nentry for %s not fully "
"displayed\n\t", ses->serverName); "displayed\n\t", ses->serverName);
...@@ -149,15 +149,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -149,15 +149,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
} else { } else {
length = length =
sprintf(buf, sprintf(buf,
"\n%d) Name: %s Domain: %s Mounts: %d OS: %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB session status: %d\t", "\n%d) Name: %s Domain: %s Mounts: %d OS:"
" %s \n\tNOS: %s\tCapability: 0x%x\n\tSMB"
" session status: %d\t",
i, ses->serverName, ses->serverDomain, i, ses->serverName, ses->serverDomain,
atomic_read(&ses->inUse), atomic_read(&ses->inUse),
ses->serverOS, ses->serverNOS, ses->serverOS, ses->serverNOS,
ses->capabilities,ses->status); ses->capabilities, ses->status);
buf += length; buf += length;
} }
if(ses->server) { if (ses->server) {
buf += sprintf(buf, "TCP status: %d\n\tLocal Users To Server: %d SecMode: 0x%x Req On Wire: %d", buf += sprintf(buf, "TCP status: %d\n\tLocal Users To "
"Server: %d SecMode: 0x%x Req On Wire: %d",
ses->server->tcpStatus, ses->server->tcpStatus,
atomic_read(&ses->server->socketUseCount), atomic_read(&ses->server->socketUseCount),
ses->server->secMode, ses->server->secMode,
...@@ -165,7 +168,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -165,7 +168,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d", buf += sprintf(buf, " In Send: %d In MaxReq Wait: %d",
atomic_read(&ses->server->inSend), atomic_read(&ses->server->inSend),
atomic_read(&ses->server->num_waiters)); atomic_read(&ses->server->num_waiters));
#endif #endif
...@@ -177,17 +180,19 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -177,17 +180,19 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
mid_entry = list_entry(tmp1, struct mid_entry = list_entry(tmp1, struct
mid_q_entry, mid_q_entry,
qhead); qhead);
if(mid_entry) { if (mid_entry) {
length = sprintf(buf,"State: %d com: %d pid: %d tsk: %p mid %d\n", length = sprintf(buf,
mid_entry->midState, "State: %d com: %d pid:"
(int)mid_entry->command, " %d tsk: %p mid %d\n",
mid_entry->pid, mid_entry->midState,
mid_entry->tsk, (int)mid_entry->command,
mid_entry->mid); mid_entry->pid,
mid_entry->tsk,
mid_entry->mid);
buf += length; buf += length;
} }
} }
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
} }
} }
...@@ -207,7 +212,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -207,7 +212,8 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType); dev_type = le32_to_cpu(tcon->fsDevInfo.DeviceType);
length = length =
sprintf(buf, sprintf(buf,
"\n%d) %s Uses: %d Type: %s DevInfo: 0x%x Attributes: 0x%x\nPathComponentMax: %d Status: %d", "\n%d) %s Uses: %d Type: %s DevInfo: 0x%x "
"Attributes: 0x%x\nPathComponentMax: %d Status: %d",
i, tcon->treeName, i, tcon->treeName,
atomic_read(&tcon->useCount), atomic_read(&tcon->useCount),
tcon->nativeFileSystem, tcon->nativeFileSystem,
...@@ -215,7 +221,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -215,7 +221,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
le32_to_cpu(tcon->fsAttrInfo.Attributes), le32_to_cpu(tcon->fsAttrInfo.Attributes),
le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength), le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength),
tcon->tidStatus); tcon->tidStatus);
buf += length; buf += length;
if (dev_type == FILE_DEVICE_DISK) if (dev_type == FILE_DEVICE_DISK)
length = sprintf(buf, " type: DISK "); length = sprintf(buf, " type: DISK ");
else if (dev_type == FILE_DEVICE_CD_ROM) else if (dev_type == FILE_DEVICE_CD_ROM)
...@@ -224,7 +230,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -224,7 +230,7 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
length = length =
sprintf(buf, " type: %d ", dev_type); sprintf(buf, " type: %d ", dev_type);
buf += length; buf += length;
if(tcon->tidStatus == CifsNeedReconnect) { if (tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED "); buf += sprintf(buf, "\tDISCONNECTED ");
length += 14; length += 14;
} }
...@@ -238,9 +244,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -238,9 +244,9 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
/* Now calculate total size of returned data */ /* Now calculate total size of returned data */
length = buf - original_buf; length = buf - original_buf;
if(offset + count >= length) if (offset + count >= length)
*eof = 1; *eof = 1;
if(length < offset) { if (length < offset) {
*eof = 1; *eof = 1;
return 0; return 0;
} else { } else {
...@@ -256,18 +262,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset, ...@@ -256,18 +262,18 @@ cifs_debug_data_read(char *buf, char **beginBuffer, off_t offset,
static int static int
cifs_stats_write(struct file *file, const char __user *buffer, cifs_stats_write(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
char c; char c;
int rc; int rc;
struct list_head *tmp; struct list_head *tmp;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
rc = get_user(c, buffer); rc = get_user(c, buffer);
if (rc) if (rc)
return rc; return rc;
if (c == '1' || c == 'y' || c == 'Y' || c == '0') { if (c == '1' || c == 'y' || c == 'Y' || c == '0') {
read_lock(&GlobalSMBSeslock); read_lock(&GlobalSMBSeslock);
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
atomic_set(&totBufAllocCount, 0); atomic_set(&totBufAllocCount, 0);
...@@ -297,14 +303,14 @@ cifs_stats_write(struct file *file, const char __user *buffer, ...@@ -297,14 +303,14 @@ cifs_stats_write(struct file *file, const char __user *buffer,
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
} }
return count; return count;
} }
static int static int
cifs_stats_read(char *buf, char **beginBuffer, off_t offset, cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
int item_length,i,length; int item_length, i, length;
struct list_head *tmp; struct list_head *tmp;
struct cifsTconInfo *tcon; struct cifsTconInfo *tcon;
...@@ -314,44 +320,44 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, ...@@ -314,44 +320,44 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
"Resources in use\nCIFS Session: %d\n", "Resources in use\nCIFS Session: %d\n",
sesInfoAllocCount.counter); sesInfoAllocCount.counter);
buf += length; buf += length;
item_length = item_length =
sprintf(buf,"Share (unique mount targets): %d\n", sprintf(buf, "Share (unique mount targets): %d\n",
tconInfoAllocCount.counter); tconInfoAllocCount.counter);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
item_length = item_length =
sprintf(buf,"SMB Request/Response Buffer: %d Pool size: %d\n", sprintf(buf, "SMB Request/Response Buffer: %d Pool size: %d\n",
bufAllocCount.counter, bufAllocCount.counter,
cifs_min_rcv + tcpSesAllocCount.counter); cifs_min_rcv + tcpSesAllocCount.counter);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
item_length = item_length =
sprintf(buf,"SMB Small Req/Resp Buffer: %d Pool size: %d\n", sprintf(buf, "SMB Small Req/Resp Buffer: %d Pool size: %d\n",
smBufAllocCount.counter,cifs_min_small); smBufAllocCount.counter, cifs_min_small);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
#ifdef CONFIG_CIFS_STATS2 #ifdef CONFIG_CIFS_STATS2
item_length = sprintf(buf, "Total Large %d Small %d Allocations\n", item_length = sprintf(buf, "Total Large %d Small %d Allocations\n",
atomic_read(&totBufAllocCount), atomic_read(&totBufAllocCount),
atomic_read(&totSmBufAllocCount)); atomic_read(&totSmBufAllocCount));
length += item_length; length += item_length;
buf += item_length; buf += item_length;
#endif /* CONFIG_CIFS_STATS2 */ #endif /* CONFIG_CIFS_STATS2 */
item_length = item_length =
sprintf(buf,"Operations (MIDs): %d\n", sprintf(buf, "Operations (MIDs): %d\n",
midCount.counter); midCount.counter);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
item_length = sprintf(buf, item_length = sprintf(buf,
"\n%d session %d share reconnects\n", "\n%d session %d share reconnects\n",
tcpSesReconnectCount.counter,tconInfoReconnectCount.counter); tcpSesReconnectCount.counter, tconInfoReconnectCount.counter);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
item_length = sprintf(buf, item_length = sprintf(buf,
"Total vfs operations: %d maximum at one time: %d\n", "Total vfs operations: %d maximum at one time: %d\n",
GlobalCurrentXid,GlobalMaxActiveXid); GlobalCurrentXid, GlobalMaxActiveXid);
length += item_length; length += item_length;
buf += item_length; buf += item_length;
...@@ -360,10 +366,10 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, ...@@ -360,10 +366,10 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
list_for_each(tmp, &GlobalTreeConnectionList) { list_for_each(tmp, &GlobalTreeConnectionList) {
i++; i++;
tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList); tcon = list_entry(tmp, struct cifsTconInfo, cifsConnectionList);
item_length = sprintf(buf,"\n%d) %s",i, tcon->treeName); item_length = sprintf(buf, "\n%d) %s", i, tcon->treeName);
buf += item_length; buf += item_length;
length += item_length; length += item_length;
if(tcon->tidStatus == CifsNeedReconnect) { if (tcon->tidStatus == CifsNeedReconnect) {
buf += sprintf(buf, "\tDISCONNECTED "); buf += sprintf(buf, "\tDISCONNECTED ");
length += 14; length += 14;
} }
...@@ -380,15 +386,15 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, ...@@ -380,15 +386,15 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
item_length = sprintf(buf, "\nWrites: %d Bytes: %lld", item_length = sprintf(buf, "\nWrites: %d Bytes: %lld",
atomic_read(&tcon->num_writes), atomic_read(&tcon->num_writes),
(long long)(tcon->bytes_written)); (long long)(tcon->bytes_written));
buf += item_length; buf += item_length;
length += item_length; length += item_length;
item_length = sprintf(buf, item_length = sprintf(buf,
"\nLocks: %d HardLinks: %d Symlinks: %d", "\nLocks: %d HardLinks: %d Symlinks: %d",
atomic_read(&tcon->num_locks), atomic_read(&tcon->num_locks),
atomic_read(&tcon->num_hardlinks), atomic_read(&tcon->num_hardlinks),
atomic_read(&tcon->num_symlinks)); atomic_read(&tcon->num_symlinks));
buf += item_length; buf += item_length;
length += item_length; length += item_length;
item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d", item_length = sprintf(buf, "\nOpens: %d Closes: %d Deletes: %d",
atomic_read(&tcon->num_opens), atomic_read(&tcon->num_opens),
...@@ -415,12 +421,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, ...@@ -415,12 +421,12 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
} }
read_unlock(&GlobalSMBSeslock); read_unlock(&GlobalSMBSeslock);
buf += sprintf(buf,"\n"); buf += sprintf(buf, "\n");
length++; length++;
if(offset + count >= length) if (offset + count >= length)
*eof = 1; *eof = 1;
if(length < offset) { if (length < offset) {
*eof = 1; *eof = 1;
return 0; return 0;
} else { } else {
...@@ -428,7 +434,7 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset, ...@@ -428,7 +434,7 @@ cifs_stats_read(char *buf, char **beginBuffer, off_t offset,
} }
if (length > count) if (length > count)
length = count; length = count;
return length; return length;
} }
#endif #endif
...@@ -547,11 +553,11 @@ cifs_proc_clean(void) ...@@ -547,11 +553,11 @@ cifs_proc_clean(void)
remove_proc_entry("MultiuserMount", proc_fs_cifs); remove_proc_entry("MultiuserMount", proc_fs_cifs);
remove_proc_entry("OplockEnabled", proc_fs_cifs); remove_proc_entry("OplockEnabled", proc_fs_cifs);
/* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */ /* remove_proc_entry("NTLMV2Enabled",proc_fs_cifs); */
remove_proc_entry("SecurityFlags",proc_fs_cifs); remove_proc_entry("SecurityFlags", proc_fs_cifs);
/* remove_proc_entry("PacketSigningEnabled",proc_fs_cifs); */ /* remove_proc_entry("PacketSigningEnabled", proc_fs_cifs); */
remove_proc_entry("LinuxExtensionsEnabled",proc_fs_cifs); remove_proc_entry("LinuxExtensionsEnabled", proc_fs_cifs);
remove_proc_entry("Experimental",proc_fs_cifs); remove_proc_entry("Experimental", proc_fs_cifs);
remove_proc_entry("LookupCacheEnabled",proc_fs_cifs); remove_proc_entry("LookupCacheEnabled", proc_fs_cifs);
remove_proc_entry("cifs", proc_root_fs); remove_proc_entry("cifs", proc_root_fs);
} }
...@@ -590,7 +596,7 @@ cifsFYI_write(struct file *file, const char __user *buffer, ...@@ -590,7 +596,7 @@ cifsFYI_write(struct file *file, const char __user *buffer,
cifsFYI = 0; cifsFYI = 0;
else if (c == '1' || c == 'y' || c == 'Y') else if (c == '1' || c == 'y' || c == 'Y')
cifsFYI = 1; cifsFYI = 1;
else if((c > '1') && (c <= '9')) else if ((c > '1') && (c <= '9'))
cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */ cifsFYI = (int) (c - '0'); /* see cifs_debug.h for meanings */
return count; return count;
...@@ -637,28 +643,28 @@ oplockEnabled_write(struct file *file, const char __user *buffer, ...@@ -637,28 +643,28 @@ oplockEnabled_write(struct file *file, const char __user *buffer,
static int static int
experimEnabled_read(char *page, char **start, off_t off, experimEnabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
int len; int len;
len = sprintf(page, "%d\n", experimEnabled); len = sprintf(page, "%d\n", experimEnabled);
len -= off; len -= off;
*start = page + off; *start = page + off;
if (len > count) if (len > count)
len = count; len = count;
else else
*eof = 1; *eof = 1;
if (len < 0) if (len < 0)
len = 0; len = 0;
return len; return len;
} }
static int static int
experimEnabled_write(struct file *file, const char __user *buffer, experimEnabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
char c; char c;
int rc; int rc;
...@@ -678,46 +684,46 @@ experimEnabled_write(struct file *file, const char __user *buffer, ...@@ -678,46 +684,46 @@ experimEnabled_write(struct file *file, const char __user *buffer,
static int static int
linuxExtensionsEnabled_read(char *page, char **start, off_t off, linuxExtensionsEnabled_read(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
int len; int len;
len = sprintf(page, "%d\n", linuxExtEnabled); len = sprintf(page, "%d\n", linuxExtEnabled);
len -= off; len -= off;
*start = page + off; *start = page + off;
if (len > count) if (len > count)
len = count; len = count;
else else
*eof = 1; *eof = 1;
if (len < 0) if (len < 0)
len = 0; len = 0;
return len; return len;
} }
static int static int
linuxExtensionsEnabled_write(struct file *file, const char __user *buffer, linuxExtensionsEnabled_write(struct file *file, const char __user *buffer,
unsigned long count, void *data) unsigned long count, void *data)
{ {
char c; char c;
int rc; int rc;
rc = get_user(c, buffer); rc = get_user(c, buffer);
if (rc) if (rc)
return rc; return rc;
if (c == '0' || c == 'n' || c == 'N') if (c == '0' || c == 'n' || c == 'N')
linuxExtEnabled = 0; linuxExtEnabled = 0;
else if (c == '1' || c == 'y' || c == 'Y') else if (c == '1' || c == 'y' || c == 'Y')
linuxExtEnabled = 1; linuxExtEnabled = 1;
return count; return count;
} }
static int static int
lookupFlag_read(char *page, char **start, off_t off, lookupFlag_read(char *page, char **start, off_t off,
int count, int *eof, void *data) int count, int *eof, void *data)
{ {
int len; int len;
...@@ -860,15 +866,15 @@ security_flags_write(struct file *file, const char __user *buffer, ...@@ -860,15 +866,15 @@ security_flags_write(struct file *file, const char __user *buffer,
char flags_string[12]; char flags_string[12];
char c; char c;
if((count < 1) || (count > 11)) if ((count < 1) || (count > 11))
return -EINVAL; return -EINVAL;
memset(flags_string, 0, 12); memset(flags_string, 0, 12);
if(copy_from_user(flags_string, buffer, count)) if (copy_from_user(flags_string, buffer, count))
return -EFAULT; return -EFAULT;
if(count < 3) { if (count < 3) {
/* single char or single char followed by null */ /* single char or single char followed by null */
c = flags_string[0]; c = flags_string[0];
if (c == '0' || c == 'n' || c == 'N') if (c == '0' || c == 'n' || c == 'N')
...@@ -881,15 +887,15 @@ security_flags_write(struct file *file, const char __user *buffer, ...@@ -881,15 +887,15 @@ security_flags_write(struct file *file, const char __user *buffer,
flags = simple_strtoul(flags_string, NULL, 0); flags = simple_strtoul(flags_string, NULL, 0);
cFYI(1,("sec flags 0x%x", flags)); cFYI(1, ("sec flags 0x%x", flags));
if(flags <= 0) { if (flags <= 0) {
cERROR(1,("invalid security flags %s",flags_string)); cERROR(1, ("invalid security flags %s", flags_string));
return -EINVAL; return -EINVAL;
} }
if(flags & ~CIFSSEC_MASK) { if (flags & ~CIFSSEC_MASK) {
cERROR(1,("attempt to set unsupported security flags 0x%x", cERROR(1, ("attempt to set unsupported security flags 0x%x",
flags & ~CIFSSEC_MASK)); flags & ~CIFSSEC_MASK));
return -EINVAL; return -EINVAL;
} }
......
...@@ -6,16 +6,16 @@ ...@@ -6,16 +6,16 @@
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or * the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
* the GNU General Public License for more details. * the GNU General Public License for more details.
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include <linux/fs.h> #include <linux/fs.h>
...@@ -32,7 +32,7 @@ ...@@ -32,7 +32,7 @@
* *
*/ */
int int
cifs_strfromUCS_le(char *to, const __le16 * from, cifs_strfromUCS_le(char *to, const __le16 * from,
int len, const struct nls_table *codepage) int len, const struct nls_table *codepage)
{ {
int i; int i;
...@@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len, ...@@ -66,7 +66,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
{ {
int charlen; int charlen;
int i; int i;
wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */ wchar_t * wchar_to = (wchar_t *)to; /* needed to quiet sparse */
for (i = 0; len && *from; i++, from += charlen, len -= charlen) { for (i = 0; len && *from; i++, from += charlen, len -= charlen) {
...@@ -79,7 +79,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len, ...@@ -79,7 +79,7 @@ cifs_strtoUCS(__le16 * to, const char *from, int len,
/* A question mark */ /* A question mark */
to[i] = cpu_to_le16(0x003f); to[i] = cpu_to_le16(0x003f);
charlen = 1; charlen = 1;
} else } else
to[i] = cpu_to_le16(wchar_to[i]); to[i] = cpu_to_le16(wchar_to[i]);
} }
......
...@@ -825,8 +825,8 @@ cifs_init_mids(void) ...@@ -825,8 +825,8 @@ cifs_init_mids(void)
sizeof (struct oplock_q_entry), 0, sizeof (struct oplock_q_entry), 0,
SLAB_HWCACHE_ALIGN, NULL, NULL); SLAB_HWCACHE_ALIGN, NULL, NULL);
if (cifs_oplock_cachep == NULL) { if (cifs_oplock_cachep == NULL) {
kmem_cache_destroy(cifs_mid_cachep);
mempool_destroy(cifs_mid_poolp); mempool_destroy(cifs_mid_poolp);
kmem_cache_destroy(cifs_mid_cachep);
return -ENOMEM; return -ENOMEM;
} }
......
...@@ -433,8 +433,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses) ...@@ -433,8 +433,8 @@ CIFSSMBNegotiate(unsigned int xid, struct cifsSesInfo *ses)
cFYI(1,("secFlags 0x%x",secFlags)); cFYI(1,("secFlags 0x%x",secFlags));
pSMB->hdr.Mid = GetNextMid(server); pSMB->hdr.Mid = GetNextMid(server);
pSMB->hdr.Flags2 |= SMBFLG2_UNICODE; pSMB->hdr.Flags2 |= (SMBFLG2_UNICODE | SMBFLG2_ERR_STATUS);
if((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5) if ((secFlags & CIFSSEC_MUST_KRB5) == CIFSSEC_MUST_KRB5)
pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC; pSMB->hdr.Flags2 |= SMBFLG2_EXT_SEC;
count = 0; count = 0;
......
...@@ -2069,8 +2069,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2069,8 +2069,15 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
srvTcp->tcpStatus = CifsExiting; srvTcp->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock); spin_unlock(&GlobalMid_Lock);
if (srvTcp->tsk) { if (srvTcp->tsk) {
struct task_struct *tsk;
/* If we could verify that kthread_stop would
always wake up processes blocked in
tcp in recv_mesg then we could remove the
send_sig call */
send_sig(SIGKILL,srvTcp->tsk,1); send_sig(SIGKILL,srvTcp->tsk,1);
kthread_stop(srvTcp->tsk); tsk = srvTcp->tsk;
if(tsk)
kthread_stop(tsk);
} }
} }
/* If find_unc succeeded then rc == 0 so we can not end */ /* If find_unc succeeded then rc == 0 so we can not end */
...@@ -2085,8 +2092,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb, ...@@ -2085,8 +2092,11 @@ cifs_mount(struct super_block *sb, struct cifs_sb_info *cifs_sb,
/* if the socketUseCount is now zero */ /* if the socketUseCount is now zero */
if ((temp_rc == -ESHUTDOWN) && if ((temp_rc == -ESHUTDOWN) &&
(pSesInfo->server) && (pSesInfo->server->tsk)) { (pSesInfo->server) && (pSesInfo->server->tsk)) {
struct task_struct *tsk;
send_sig(SIGKILL,pSesInfo->server->tsk,1); send_sig(SIGKILL,pSesInfo->server->tsk,1);
kthread_stop(pSesInfo->server->tsk); tsk = pSesInfo->server->tsk;
if (tsk)
kthread_stop(tsk);
} }
} else } else
cFYI(1, ("No session or bad tcon")); cFYI(1, ("No session or bad tcon"));
...@@ -3334,7 +3344,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb) ...@@ -3334,7 +3344,7 @@ cifs_umount(struct super_block *sb, struct cifs_sb_info *cifs_sb)
return 0; return 0;
} else if (rc == -ESHUTDOWN) { } else if (rc == -ESHUTDOWN) {
cFYI(1,("Waking up socket by sending it signal")); cFYI(1,("Waking up socket by sending it signal"));
if(cifsd_task) { if (cifsd_task) {
send_sig(SIGKILL,cifsd_task,1); send_sig(SIGKILL,cifsd_task,1);
kthread_stop(cifsd_task); kthread_stop(cifsd_task);
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* fs/cifs/dir.c * fs/cifs/dir.c
* *
* vfs operations that deal with dentries * vfs operations that deal with dentries
* *
* Copyright (C) International Business Machines Corp., 2002,2005 * Copyright (C) International Business Machines Corp., 2002,2005
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
...@@ -34,11 +34,12 @@ ...@@ -34,11 +34,12 @@
static void static void
renew_parental_timestamps(struct dentry *direntry) renew_parental_timestamps(struct dentry *direntry)
{ {
/* BB check if there is a way to get the kernel to do this or if we really need this */ /* BB check if there is a way to get the kernel to do this or if we
really need this */
do { do {
direntry->d_time = jiffies; direntry->d_time = jiffies;
direntry = direntry->d_parent; direntry = direntry->d_parent;
} while (!IS_ROOT(direntry)); } while (!IS_ROOT(direntry));
} }
/* Note: caller must free return buffer */ /* Note: caller must free return buffer */
...@@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -51,7 +52,7 @@ build_path_from_dentry(struct dentry *direntry)
char *full_path; char *full_path;
char dirsep; char dirsep;
if(direntry == NULL) if (direntry == NULL)
return NULL; /* not much we can do if dentry is freed and return NULL; /* not much we can do if dentry is freed and
we need to reopen the file after it was closed implicitly we need to reopen the file after it was closed implicitly
when the server crashed */ when the server crashed */
...@@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -59,18 +60,18 @@ build_path_from_dentry(struct dentry *direntry)
dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb)); dirsep = CIFS_DIR_SEP(CIFS_SB(direntry->d_sb));
pplen = CIFS_SB(direntry->d_sb)->prepathlen; pplen = CIFS_SB(direntry->d_sb)->prepathlen;
cifs_bp_rename_retry: cifs_bp_rename_retry:
namelen = pplen; namelen = pplen;
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
namelen += (1 + temp->d_name.len); namelen += (1 + temp->d_name.len);
temp = temp->d_parent; temp = temp->d_parent;
if(temp == NULL) { if (temp == NULL) {
cERROR(1,("corrupt dentry")); cERROR(1, ("corrupt dentry"));
return NULL; return NULL;
} }
} }
full_path = kmalloc(namelen+1, GFP_KERNEL); full_path = kmalloc(namelen+1, GFP_KERNEL);
if(full_path == NULL) if (full_path == NULL)
return full_path; return full_path;
full_path[namelen] = 0; /* trailing null */ full_path[namelen] = 0; /* trailing null */
for (temp = direntry; !IS_ROOT(temp);) { for (temp = direntry; !IS_ROOT(temp);) {
...@@ -84,8 +85,8 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -84,8 +85,8 @@ build_path_from_dentry(struct dentry *direntry)
cFYI(0, ("name: %s", full_path + namelen)); cFYI(0, ("name: %s", full_path + namelen));
} }
temp = temp->d_parent; temp = temp->d_parent;
if(temp == NULL) { if (temp == NULL) {
cERROR(1,("corrupt dentry")); cERROR(1, ("corrupt dentry"));
kfree(full_path); kfree(full_path);
return NULL; return NULL;
} }
...@@ -94,7 +95,7 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -94,7 +95,7 @@ build_path_from_dentry(struct dentry *direntry)
cERROR(1, cERROR(1,
("did not end path lookup where expected namelen is %d", ("did not end path lookup where expected namelen is %d",
namelen)); namelen));
/* presumably this is only possible if racing with a rename /* presumably this is only possible if racing with a rename
of one of the parent directories (we can not lock the dentries of one of the parent directories (we can not lock the dentries
above us to prevent this, but retrying should be harmless) */ above us to prevent this, but retrying should be harmless) */
kfree(full_path); kfree(full_path);
...@@ -106,7 +107,7 @@ build_path_from_dentry(struct dentry *direntry) ...@@ -106,7 +107,7 @@ build_path_from_dentry(struct dentry *direntry)
since the '\' is a valid posix character so we can not switch since the '\' is a valid posix character so we can not switch
those safely to '/' if any are found in the middle of the prepath */ those safely to '/' if any are found in the middle of the prepath */
/* BB test paths to Windows with '/' in the midst of prepath */ /* BB test paths to Windows with '/' in the midst of prepath */
strncpy(full_path,CIFS_SB(direntry->d_sb)->prepath,pplen); strncpy(full_path, CIFS_SB(direntry->d_sb)->prepath, pplen);
return full_path; return full_path;
} }
...@@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -147,12 +148,12 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
if(nd && (nd->flags & LOOKUP_OPEN)) { if (nd && (nd->flags & LOOKUP_OPEN)) {
int oflags = nd->intent.open.flags; int oflags = nd->intent.open.flags;
desiredAccess = 0; desiredAccess = 0;
...@@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -164,28 +165,29 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
write_only = TRUE; write_only = TRUE;
} }
if((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) if ((oflags & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL))
disposition = FILE_CREATE; disposition = FILE_CREATE;
else if((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC)) else if ((oflags & (O_CREAT | O_TRUNC)) == (O_CREAT | O_TRUNC))
disposition = FILE_OVERWRITE_IF; disposition = FILE_OVERWRITE_IF;
else if((oflags & O_CREAT) == O_CREAT) else if ((oflags & O_CREAT) == O_CREAT)
disposition = FILE_OPEN_IF; disposition = FILE_OPEN_IF;
else { else {
cFYI(1,("Create flag not set in create function")); cFYI(1, ("Create flag not set in create function"));
} }
} }
/* BB add processing to set equivalent of mode - e.g. via CreateX with ACLs */ /* BB add processing to set equivalent of mode - e.g. via CreateX with
ACLs */
if (oplockEnabled) if (oplockEnabled)
oplock = REQ_OPLOCK; oplock = REQ_OPLOCK;
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if(buf == NULL) { if (buf == NULL) {
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
} }
if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS) if (cifs_sb->tcon->ses->capabilities & CAP_NT_SMBS)
rc = CIFSSMBOpen(xid, pTcon, full_path, disposition, rc = CIFSSMBOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR, desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls, &fileHandle, &oplock, buf, cifs_sb->local_nls,
...@@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -193,27 +195,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
else else
rc = -EIO; /* no NT SMB support fall into legacy open below */ rc = -EIO; /* no NT SMB support fall into legacy open below */
if(rc == -EIO) { if (rc == -EIO) {
/* old server, retry the open legacy style */ /* old server, retry the open legacy style */
rc = SMBLegacyOpen(xid, pTcon, full_path, disposition, rc = SMBLegacyOpen(xid, pTcon, full_path, disposition,
desiredAccess, CREATE_NOT_DIR, desiredAccess, CREATE_NOT_DIR,
&fileHandle, &oplock, buf, cifs_sb->local_nls, &fileHandle, &oplock, buf, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
} }
if (rc) { if (rc) {
cFYI(1, ("cifs_create returned 0x%x", rc)); cFYI(1, ("cifs_create returned 0x%x", rc));
} else { } else {
/* If Open reported that we actually created a file /* If Open reported that we actually created a file
then we now have to set the mode if possible */ then we now have to set the mode if possible */
if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) && if ((cifs_sb->tcon->ses->capabilities & CAP_UNIX) &&
(oplock & CIFS_CREATE_ACTION)) (oplock & CIFS_CREATE_ACTION)) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
(__u64)current->fsuid, (__u64)current->fsuid,
(__u64)current->fsgid, (__u64)current->fsgid,
0 /* dev */, 0 /* dev */,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} else { } else {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode, CIFSSMBUnixSetPerms(xid, pTcon, full_path, mode,
...@@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -221,26 +224,28 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
(__u64)-1, (__u64)-1,
0 /* dev */, 0 /* dev */,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} }
else { } else {
/* BB implement mode setting via Windows security descriptors */ /* BB implement mode setting via Windows security
/* eg CIFSSMBWinSetPerms(xid,pTcon,full_path,mode,-1,-1,local_nls);*/ descriptors e.g. */
/* could set r/o dos attribute if mode & 0222 == 0 */ /* CIFSSMBWinSetPerms(xid,pTcon,path,mode,-1,-1,nls);*/
/* Could set r/o dos attribute if mode & 0222 == 0 */
} }
/* BB server might mask mode so we have to query for Unix case*/ /* BB server might mask mode so we have to query for Unix case*/
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid); inode->i_sb, xid);
else { else {
rc = cifs_get_inode_info(&newinode, full_path, rc = cifs_get_inode_info(&newinode, full_path,
buf, inode->i_sb,xid); buf, inode->i_sb, xid);
if(newinode) { if (newinode) {
newinode->i_mode = mode; newinode->i_mode = mode;
if((oplock & CIFS_CREATE_ACTION) && if ((oplock & CIFS_CREATE_ACTION) &&
(cifs_sb->mnt_cifs_flags & (cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_SET_UID)) { CIFS_MOUNT_SET_UID)) {
newinode->i_uid = current->fsuid; newinode->i_uid = current->fsuid;
newinode->i_gid = current->fsgid; newinode->i_gid = current->fsgid;
...@@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -259,14 +264,14 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
d_instantiate(direntry, newinode); d_instantiate(direntry, newinode);
} }
if((nd->flags & LOOKUP_OPEN) == FALSE) { if ((nd->flags & LOOKUP_OPEN) == FALSE) {
/* mknod case - do not leave file open */ /* mknod case - do not leave file open */
CIFSSMBClose(xid, pTcon, fileHandle); CIFSSMBClose(xid, pTcon, fileHandle);
} else if(newinode) { } else if (newinode) {
pCifsFile = pCifsFile =
kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL); kzalloc(sizeof (struct cifsFileInfo), GFP_KERNEL);
if(pCifsFile == NULL) if (pCifsFile == NULL)
goto cifs_create_out; goto cifs_create_out;
pCifsFile->netfid = fileHandle; pCifsFile->netfid = fileHandle;
pCifsFile->pid = current->tgid; pCifsFile->pid = current->tgid;
...@@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -276,33 +281,33 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
init_MUTEX(&pCifsFile->fh_sem); init_MUTEX(&pCifsFile->fh_sem);
mutex_init(&pCifsFile->lock_mutex); mutex_init(&pCifsFile->lock_mutex);
INIT_LIST_HEAD(&pCifsFile->llist); INIT_LIST_HEAD(&pCifsFile->llist);
atomic_set(&pCifsFile->wrtPending,0); atomic_set(&pCifsFile->wrtPending, 0);
/* set the following in open now /* set the following in open now
pCifsFile->pfile = file; */ pCifsFile->pfile = file; */
write_lock(&GlobalSMBSeslock); write_lock(&GlobalSMBSeslock);
list_add(&pCifsFile->tlist,&pTcon->openFileList); list_add(&pCifsFile->tlist, &pTcon->openFileList);
pCifsInode = CIFS_I(newinode); pCifsInode = CIFS_I(newinode);
if(pCifsInode) { if (pCifsInode) {
/* if readable file instance put first in list*/ /* if readable file instance put first in list*/
if (write_only == TRUE) { if (write_only == TRUE) {
list_add_tail(&pCifsFile->flist, list_add_tail(&pCifsFile->flist,
&pCifsInode->openFileList); &pCifsInode->openFileList);
} else { } else {
list_add(&pCifsFile->flist, list_add(&pCifsFile->flist,
&pCifsInode->openFileList); &pCifsInode->openFileList);
} }
if((oplock & 0xF) == OPLOCK_EXCLUSIVE) { if ((oplock & 0xF) == OPLOCK_EXCLUSIVE) {
pCifsInode->clientCanCacheAll = TRUE; pCifsInode->clientCanCacheAll = TRUE;
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
cFYI(1,("Exclusive Oplock for inode %p", cFYI(1, ("Exclusive Oplock inode %p",
newinode)); newinode));
} else if((oplock & 0xF) == OPLOCK_READ) } else if ((oplock & 0xF) == OPLOCK_READ)
pCifsInode->clientCanCacheRead = TRUE; pCifsInode->clientCanCacheRead = TRUE;
} }
write_unlock(&GlobalSMBSeslock); write_unlock(&GlobalSMBSeslock);
} }
} }
cifs_create_out: cifs_create_out:
kfree(buf); kfree(buf);
kfree(full_path); kfree(full_path);
...@@ -310,8 +315,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode, ...@@ -310,8 +315,8 @@ cifs_create(struct inode *inode, struct dentry *direntry, int mode,
return rc; return rc;
} }
int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
dev_t device_number) dev_t device_number)
{ {
int rc = -EPERM; int rc = -EPERM;
int xid; int xid;
...@@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -329,43 +334,45 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
pTcon = cifs_sb->tcon; pTcon = cifs_sb->tcon;
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) if (full_path == NULL)
rc = -ENOMEM; rc = -ENOMEM;
else if (pTcon->ses->capabilities & CAP_UNIX) { else if (pTcon->ses->capabilities & CAP_UNIX) {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path, rc = CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode,(__u64)current->fsuid,(__u64)current->fsgid, mode, (__u64)current->fsuid,
(__u64)current->fsgid,
device_number, cifs_sb->local_nls, device_number, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} else { } else {
rc = CIFSSMBUnixSetPerms(xid, pTcon, rc = CIFSSMBUnixSetPerms(xid, pTcon,
full_path, mode, (__u64)-1, (__u64)-1, full_path, mode, (__u64)-1, (__u64)-1,
device_number, cifs_sb->local_nls, device_number, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} }
if(!rc) { if (!rc) {
rc = cifs_get_inode_info_unix(&newinode, full_path, rc = cifs_get_inode_info_unix(&newinode, full_path,
inode->i_sb,xid); inode->i_sb, xid);
if (pTcon->nocase) if (pTcon->nocase)
direntry->d_op = &cifs_ci_dentry_ops; direntry->d_op = &cifs_ci_dentry_ops;
else else
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
if(rc == 0) if (rc == 0)
d_instantiate(direntry, newinode); d_instantiate(direntry, newinode);
} }
} else { } else {
if(cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
int oplock = 0; int oplock = 0;
u16 fileHandle; u16 fileHandle;
FILE_ALL_INFO * buf; FILE_ALL_INFO * buf;
cFYI(1,("sfu compat create special file")); cFYI(1, ("sfu compat create special file"));
buf = kmalloc(sizeof(FILE_ALL_INFO),GFP_KERNEL); buf = kmalloc(sizeof(FILE_ALL_INFO), GFP_KERNEL);
if(buf == NULL) { if (buf == NULL) {
kfree(full_path); kfree(full_path);
FreeXid(xid); FreeXid(xid);
return -ENOMEM; return -ENOMEM;
...@@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -373,39 +380,38 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
rc = CIFSSMBOpen(xid, pTcon, full_path, rc = CIFSSMBOpen(xid, pTcon, full_path,
FILE_CREATE, /* fail if exists */ FILE_CREATE, /* fail if exists */
GENERIC_WRITE /* BB would GENERIC_WRITE /* BB would
WRITE_OWNER | WRITE_DAC be better? */, WRITE_OWNER | WRITE_DAC be better? */,
/* Create a file and set the /* Create a file and set the
file attribute to SYSTEM */ file attribute to SYSTEM */
CREATE_NOT_DIR | CREATE_OPTION_SPECIAL, CREATE_NOT_DIR | CREATE_OPTION_SPECIAL,
&fileHandle, &oplock, buf, &fileHandle, &oplock, buf,
cifs_sb->local_nls, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB FIXME - add handling for backlevel servers /* BB FIXME - add handling for backlevel servers
which need legacy open and check for all which need legacy open and check for all
calls to SMBOpen for fallback to calls to SMBOpen for fallback to SMBLeagcyOpen */
SMBLeagcyOpen */ if (!rc) {
if(!rc) {
/* BB Do not bother to decode buf since no /* BB Do not bother to decode buf since no
local inode yet to put timestamps in, local inode yet to put timestamps in,
but we can reuse it safely */ but we can reuse it safely */
int bytes_written; int bytes_written;
struct win_dev *pdev; struct win_dev *pdev;
pdev = (struct win_dev *)buf; pdev = (struct win_dev *)buf;
if(S_ISCHR(mode)) { if (S_ISCHR(mode)) {
memcpy(pdev->type, "IntxCHR", 8); memcpy(pdev->type, "IntxCHR", 8);
pdev->major = pdev->major =
cpu_to_le64(MAJOR(device_number)); cpu_to_le64(MAJOR(device_number));
pdev->minor = pdev->minor =
cpu_to_le64(MINOR(device_number)); cpu_to_le64(MINOR(device_number));
rc = CIFSSMBWrite(xid, pTcon, rc = CIFSSMBWrite(xid, pTcon,
fileHandle, fileHandle,
sizeof(struct win_dev), sizeof(struct win_dev),
0, &bytes_written, (char *)pdev, 0, &bytes_written, (char *)pdev,
NULL, 0); NULL, 0);
} else if(S_ISBLK(mode)) { } else if (S_ISBLK(mode)) {
memcpy(pdev->type, "IntxBLK", 8); memcpy(pdev->type, "IntxBLK", 8);
pdev->major = pdev->major =
cpu_to_le64(MAJOR(device_number)); cpu_to_le64(MAJOR(device_number));
...@@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode, ...@@ -432,7 +438,8 @@ int cifs_mknod(struct inode *inode, struct dentry *direntry, int mode,
struct dentry * struct dentry *
cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct nameidata *nd) cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry,
struct nameidata *nd)
{ {
int xid; int xid;
int rc = 0; /* to get around spurious gcc warning, set to zero here */ int rc = 0; /* to get around spurious gcc warning, set to zero here */
...@@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -447,8 +454,6 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
(" parent inode = 0x%p name is: %s and dentry = 0x%p", (" parent inode = 0x%p name is: %s and dentry = 0x%p",
parent_dir_inode, direntry->d_name.name, direntry)); parent_dir_inode, direntry->d_name.name, direntry));
/* BB Add check of incoming data - e.g. frame not longer than maximum SMB - let server check the namelen BB */
/* check whether path exists */ /* check whether path exists */
cifs_sb = CIFS_SB(parent_dir_inode->i_sb); cifs_sb = CIFS_SB(parent_dir_inode->i_sb);
...@@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -472,7 +477,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
deadlock in the cases (beginning of sys_rename itself) deadlock in the cases (beginning of sys_rename itself)
in which we already have the sb rename sem */ in which we already have the sb rename sem */
full_path = build_path_from_dentry(direntry); full_path = build_path_from_dentry(direntry);
if(full_path == NULL) { if (full_path == NULL) {
FreeXid(xid); FreeXid(xid);
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
} }
...@@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -487,10 +492,10 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
if (pTcon->ses->capabilities & CAP_UNIX) if (pTcon->ses->capabilities & CAP_UNIX)
rc = cifs_get_inode_info_unix(&newInode, full_path, rc = cifs_get_inode_info_unix(&newInode, full_path,
parent_dir_inode->i_sb,xid); parent_dir_inode->i_sb, xid);
else else
rc = cifs_get_inode_info(&newInode, full_path, NULL, rc = cifs_get_inode_info(&newInode, full_path, NULL,
parent_dir_inode->i_sb,xid); parent_dir_inode->i_sb, xid);
if ((rc == 0) && (newInode != NULL)) { if ((rc == 0) && (newInode != NULL)) {
if (pTcon->nocase) if (pTcon->nocase)
...@@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -499,7 +504,7 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
d_add(direntry, newInode); d_add(direntry, newInode);
/* since paths are not looked up by component - the parent /* since paths are not looked up by component - the parent
directories are presumed to be good here */ directories are presumed to be good here */
renew_parental_timestamps(direntry); renew_parental_timestamps(direntry);
...@@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name ...@@ -511,13 +516,13 @@ cifs_lookup(struct inode *parent_dir_inode, struct dentry *direntry, struct name
else else
direntry->d_op = &cifs_dentry_ops; direntry->d_op = &cifs_dentry_ops;
d_add(direntry, NULL); d_add(direntry, NULL);
/* if it was once a directory (but how can we tell?) we could do /* if it was once a directory (but how can we tell?) we could do
shrink_dcache_parent(direntry); */ shrink_dcache_parent(direntry); */
} else { } else {
cERROR(1,("Error 0x%x on cifs_get_inode_info in lookup of %s", cERROR(1, ("Error 0x%x on cifs_get_inode_info in lookup of %s",
rc,full_path)); rc, full_path));
/* BB special case check for Access Denied - watch security /* BB special case check for Access Denied - watch security
exposure of returning dir info implicitly via different rc exposure of returning dir info implicitly via different rc
if file exists or not but no access BB */ if file exists or not but no access BB */
} }
...@@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) ...@@ -538,11 +543,11 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
} else { } else {
cFYI(1, ("neg dentry 0x%p name = %s", cFYI(1, ("neg dentry 0x%p name = %s",
direntry, direntry->d_name.name)); direntry, direntry->d_name.name));
if(time_after(jiffies, direntry->d_time + HZ) || if (time_after(jiffies, direntry->d_time + HZ) ||
!lookupCacheEnabled) { !lookupCacheEnabled) {
d_drop(direntry); d_drop(direntry);
isValid = 0; isValid = 0;
} }
} }
return isValid; return isValid;
...@@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd) ...@@ -559,8 +564,7 @@ cifs_d_revalidate(struct dentry *direntry, struct nameidata *nd)
struct dentry_operations cifs_dentry_ops = { struct dentry_operations cifs_dentry_ops = {
.d_revalidate = cifs_d_revalidate, .d_revalidate = cifs_d_revalidate,
/* d_delete: cifs_d_delete, *//* not needed except for debugging */ /* d_delete: cifs_d_delete, */ /* not needed except for debugging */
/* no need for d_hash, d_compare, d_release, d_iput ... yet. BB confirm this BB */
}; };
static int cifs_ci_hash(struct dentry *dentry, struct qstr *q) static int cifs_ci_hash(struct dentry *dentry, struct qstr *q)
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* fs/cifs/fcntl.c * fs/cifs/fcntl.c
* *
* vfs operations that deal with the file control API * vfs operations that deal with the file control API
* *
* Copyright (C) International Business Machines Corp., 2003,2004 * Copyright (C) International Business Machines Corp., 2003,2004
* Author(s): Steve French (sfrench@us.ibm.com) * Author(s): Steve French (sfrench@us.ibm.com)
* *
...@@ -35,35 +35,34 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags) ...@@ -35,35 +35,34 @@ static __u32 convert_to_cifs_notify_flags(unsigned long fcntl_notify_flags)
/* No way on Linux VFS to ask to monitor xattr /* No way on Linux VFS to ask to monitor xattr
changes (and no stream support either */ changes (and no stream support either */
if(fcntl_notify_flags & DN_ACCESS) { if (fcntl_notify_flags & DN_ACCESS) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS; cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_ACCESS;
} }
if(fcntl_notify_flags & DN_MODIFY) { if (fcntl_notify_flags & DN_MODIFY) {
/* What does this mean on directories? */ /* What does this mean on directories? */
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_SIZE; FILE_NOTIFY_CHANGE_SIZE;
} }
if(fcntl_notify_flags & DN_CREATE) { if (fcntl_notify_flags & DN_CREATE) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_CREATION |
FILE_NOTIFY_CHANGE_LAST_WRITE; FILE_NOTIFY_CHANGE_LAST_WRITE;
} }
if(fcntl_notify_flags & DN_DELETE) { if (fcntl_notify_flags & DN_DELETE) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE; cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_LAST_WRITE;
} }
if(fcntl_notify_flags & DN_RENAME) { if (fcntl_notify_flags & DN_RENAME) {
/* BB review this - checking various server behaviors */ /* BB review this - checking various server behaviors */
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_DIR_NAME |
FILE_NOTIFY_CHANGE_FILE_NAME; FILE_NOTIFY_CHANGE_FILE_NAME;
} }
if(fcntl_notify_flags & DN_ATTRIB) { if (fcntl_notify_flags & DN_ATTRIB) {
cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY | cifs_ntfy_flags |= FILE_NOTIFY_CHANGE_SECURITY |
FILE_NOTIFY_CHANGE_ATTRIBUTES; FILE_NOTIFY_CHANGE_ATTRIBUTES;
} }
/* if(fcntl_notify_flags & DN_MULTISHOT) { /* if (fcntl_notify_flags & DN_MULTISHOT) {
cifs_ntfy_flags |= ; cifs_ntfy_flags |= ;
} */ /* BB fixme - not sure how to handle this with CIFS yet */ } */ /* BB fixme - not sure how to handle this with CIFS yet */
return cifs_ntfy_flags; return cifs_ntfy_flags;
} }
...@@ -78,8 +77,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg) ...@@ -78,8 +77,7 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
__u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES; __u32 filter = FILE_NOTIFY_CHANGE_NAME | FILE_NOTIFY_CHANGE_ATTRIBUTES;
__u16 netfid; __u16 netfid;
if (experimEnabled == 0)
if(experimEnabled == 0)
return 0; return 0;
xid = GetXid(); xid = GetXid();
...@@ -88,21 +86,21 @@ int cifs_dir_notify(struct file * file, unsigned long arg) ...@@ -88,21 +86,21 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
full_path = build_path_from_dentry(file->f_path.dentry); full_path = build_path_from_dentry(file->f_path.dentry);
if(full_path == NULL) { if (full_path == NULL) {
rc = -ENOMEM; rc = -ENOMEM;
} else { } else {
cFYI(1,("dir notify on file %s Arg 0x%lx",full_path,arg)); cFYI(1, ("dir notify on file %s Arg 0x%lx", full_path, arg));
rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN, rc = CIFSSMBOpen(xid, pTcon, full_path, FILE_OPEN,
GENERIC_READ | SYNCHRONIZE, 0 /* create options */, GENERIC_READ | SYNCHRONIZE, 0 /* create options */,
&netfid, &oplock,NULL, cifs_sb->local_nls, &netfid, &oplock, NULL, cifs_sb->local_nls,
cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR); cifs_sb->mnt_cifs_flags & CIFS_MOUNT_MAP_SPECIAL_CHR);
/* BB fixme - add this handle to a notify handle list */ /* BB fixme - add this handle to a notify handle list */
if(rc) { if (rc) {
cFYI(1,("Could not open directory for notify")); cFYI(1, ("Could not open directory for notify"));
} else { } else {
filter = convert_to_cifs_notify_flags(arg); filter = convert_to_cifs_notify_flags(arg);
if(filter != 0) { if (filter != 0) {
rc = CIFSSMBNotify(xid, pTcon, rc = CIFSSMBNotify(xid, pTcon,
0 /* no subdirs */, netfid, 0 /* no subdirs */, netfid,
filter, file, arg & DN_MULTISHOT, filter, file, arg & DN_MULTISHOT,
cifs_sb->local_nls); cifs_sb->local_nls);
...@@ -113,10 +111,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg) ...@@ -113,10 +111,10 @@ int cifs_dir_notify(struct file * file, unsigned long arg)
it would close automatically but may be a way it would close automatically but may be a way
to do it easily when inode freed or when to do it easily when inode freed or when
notify info is cleared/changed */ notify info is cleared/changed */
cFYI(1,("notify rc %d",rc)); cFYI(1, ("notify rc %d", rc));
} }
} }
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
...@@ -986,7 +986,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -986,7 +986,8 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
* failed to get it from the server or was set bogus */ * failed to get it from the server or was set bogus */
if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2)) if ((direntry->d_inode) && (direntry->d_inode->i_nlink < 2))
direntry->d_inode->i_nlink = 2; direntry->d_inode->i_nlink = 2;
if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) if (cifs_sb->tcon->ses->capabilities & CAP_UNIX) {
mode &= ~current->fs->umask;
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) { if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_SET_UID) {
CIFSSMBUnixSetPerms(xid, pTcon, full_path, CIFSSMBUnixSetPerms(xid, pTcon, full_path,
mode, mode,
...@@ -1004,7 +1005,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode) ...@@ -1004,7 +1005,7 @@ int cifs_mkdir(struct inode *inode, struct dentry *direntry, int mode)
cifs_sb->mnt_cifs_flags & cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR); CIFS_MOUNT_MAP_SPECIAL_CHR);
} }
else { } else {
/* BB to be implemented via Windows secrty descriptors /* BB to be implemented via Windows secrty descriptors
eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode, eg CIFSSMBWinSetPerms(xid, pTcon, full_path, mode,
-1, -1, local_nls); */ -1, -1, local_nls); */
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2) #define CIFS_IOC_CHECKUMOUNT _IO(0xCF, 2)
int cifs_ioctl (struct inode * inode, struct file * filep, int cifs_ioctl (struct inode * inode, struct file * filep,
unsigned int command, unsigned long arg) unsigned int command, unsigned long arg)
{ {
int rc = -ENOTTY; /* strange error - but the precedent */ int rc = -ENOTTY; /* strange error - but the precedent */
...@@ -47,13 +47,13 @@ int cifs_ioctl (struct inode * inode, struct file * filep, ...@@ -47,13 +47,13 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
xid = GetXid(); xid = GetXid();
cFYI(1,("ioctl file %p cmd %u arg %lu",filep,command,arg)); cFYI(1, ("ioctl file %p cmd %u arg %lu", filep, command, arg));
cifs_sb = CIFS_SB(inode->i_sb); cifs_sb = CIFS_SB(inode->i_sb);
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
tcon = cifs_sb->tcon; tcon = cifs_sb->tcon;
if(tcon) if (tcon)
caps = le64_to_cpu(tcon->fsUnixInfo.Capability); caps = le64_to_cpu(tcon->fsUnixInfo.Capability);
else { else {
rc = -EIO; rc = -EIO;
...@@ -62,24 +62,24 @@ int cifs_ioctl (struct inode * inode, struct file * filep, ...@@ -62,24 +62,24 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
} }
#endif /* CONFIG_CIFS_POSIX */ #endif /* CONFIG_CIFS_POSIX */
switch(command) { switch (command) {
case CIFS_IOC_CHECKUMOUNT: case CIFS_IOC_CHECKUMOUNT:
cFYI(1,("User unmount attempted")); cFYI(1, ("User unmount attempted"));
if(cifs_sb->mnt_uid == current->uid) if (cifs_sb->mnt_uid == current->uid)
rc = 0; rc = 0;
else { else {
rc = -EACCES; rc = -EACCES;
cFYI(1,("uids do not match")); cFYI(1, ("uids do not match"));
} }
break; break;
#ifdef CONFIG_CIFS_POSIX #ifdef CONFIG_CIFS_POSIX
case FS_IOC_GETFLAGS: case FS_IOC_GETFLAGS:
if(CIFS_UNIX_EXTATTR_CAP & caps) { if (CIFS_UNIX_EXTATTR_CAP & caps) {
if (pSMBFile == NULL) if (pSMBFile == NULL)
break; break;
rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid, rc = CIFSGetExtAttr(xid, tcon, pSMBFile->netfid,
&ExtAttrBits, &ExtAttrMask); &ExtAttrBits, &ExtAttrMask);
if(rc == 0) if (rc == 0)
rc = put_user(ExtAttrBits & rc = put_user(ExtAttrBits &
FS_FL_USER_VISIBLE, FS_FL_USER_VISIBLE,
(int __user *)arg); (int __user *)arg);
...@@ -87,8 +87,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep, ...@@ -87,8 +87,8 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
break; break;
case FS_IOC_SETFLAGS: case FS_IOC_SETFLAGS:
if(CIFS_UNIX_EXTATTR_CAP & caps) { if (CIFS_UNIX_EXTATTR_CAP & caps) {
if(get_user(ExtAttrBits,(int __user *)arg)) { if (get_user(ExtAttrBits, (int __user *)arg)) {
rc = -EFAULT; rc = -EFAULT;
break; break;
} }
...@@ -96,16 +96,15 @@ int cifs_ioctl (struct inode * inode, struct file * filep, ...@@ -96,16 +96,15 @@ int cifs_ioctl (struct inode * inode, struct file * filep,
break; break;
/* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid, /* rc= CIFSGetExtAttr(xid,tcon,pSMBFile->netfid,
extAttrBits, &ExtAttrMask);*/ extAttrBits, &ExtAttrMask);*/
} }
cFYI(1,("set flags not implemented yet")); cFYI(1, ("set flags not implemented yet"));
break; break;
#endif /* CONFIG_CIFS_POSIX */ #endif /* CONFIG_CIFS_POSIX */
default: default:
cFYI(1,("unsupported ioctl")); cFYI(1, ("unsupported ioctl"));
break; break;
} }
FreeXid(xid); FreeXid(xid);
return rc; return rc;
} }
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, write to the Free Software * along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
/* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */ /* NB: unlike smb/cifs packets, the RFC1002 structures are big endian */
......
...@@ -272,7 +272,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, ...@@ -272,7 +272,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
struct page *page; struct page *page;
pgoff_t index, end_index; pgoff_t index, end_index;
loff_t isize; loff_t isize;
size_t total_len;
int error, page_nr; int error, page_nr;
struct splice_pipe_desc spd = { struct splice_pipe_desc spd = {
.pages = pages, .pages = pages,
...@@ -298,7 +297,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, ...@@ -298,7 +297,6 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
* Now fill in the holes: * Now fill in the holes:
*/ */
error = 0; error = 0;
total_len = 0;
/* /*
* Lookup the (hopefully) full range of pages we need. * Lookup the (hopefully) full range of pages we need.
...@@ -415,43 +413,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos, ...@@ -415,43 +413,47 @@ __generic_file_splice_read(struct file *in, loff_t *ppos,
break; break;
} }
}
fill_it:
/*
* i_size must be checked after PageUptodate.
*/
isize = i_size_read(mapping->host);
end_index = (isize - 1) >> PAGE_CACHE_SHIFT;
if (unlikely(!isize || index > end_index))
break;
/*
* if this is the last page, see if we need to shrink
* the length and stop
*/
if (end_index == index) {
unsigned int plen;
/* /*
* i_size must be checked after ->readpage(). * max good bytes in this page
*/ */
isize = i_size_read(mapping->host); plen = ((isize - 1) & ~PAGE_CACHE_MASK) + 1;
end_index = (isize - 1) >> PAGE_CACHE_SHIFT; if (plen <= loff)
if (unlikely(!isize || index > end_index))
break; break;
/* /*
* if this is the last page, see if we need to shrink * force quit after adding this page
* the length and stop
*/ */
if (end_index == index) { this_len = min(this_len, plen - loff);
loff = PAGE_CACHE_SIZE - (isize & ~PAGE_CACHE_MASK); len = this_len;
if (total_len + loff > isize)
break;
/*
* force quit after adding this page
*/
len = this_len;
this_len = min(this_len, loff);
loff = 0;
}
} }
fill_it:
partial[page_nr].offset = loff; partial[page_nr].offset = loff;
partial[page_nr].len = this_len; partial[page_nr].len = this_len;
len -= this_len; len -= this_len;
total_len += this_len;
loff = 0; loff = 0;
spd.nr_pages++; spd.nr_pages++;
index++; index++;
} }
/* /*
* Release any pages at the end, if we quit early. 'i' is how far * Release any pages at the end, if we quit early. 'page_nr' is how far
* we got, 'nr_pages' is how many pages are in the map. * we got, 'nr_pages' is how many pages are in the map.
*/ */
while (page_nr < nr_pages) while (page_nr < nr_pages)
...@@ -478,10 +480,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos, ...@@ -478,10 +480,18 @@ ssize_t generic_file_splice_read(struct file *in, loff_t *ppos,
{ {
ssize_t spliced; ssize_t spliced;
int ret; int ret;
loff_t isize, left;
isize = i_size_read(in->f_mapping->host);
if (unlikely(*ppos >= isize))
return 0;
left = isize - *ppos;
if (unlikely(left < len))
len = left;
ret = 0; ret = 0;
spliced = 0; spliced = 0;
while (len) { while (len) {
ret = __generic_file_splice_read(in, ppos, pipe, len, flags); ret = __generic_file_splice_read(in, ppos, pipe, len, flags);
...@@ -644,7 +654,6 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf, ...@@ -644,7 +654,6 @@ static int pipe_to_file(struct pipe_inode_info *pipe, struct pipe_buffer *buf,
* accessed, we are now done! * accessed, we are now done!
*/ */
mark_page_accessed(page); mark_page_accessed(page);
balance_dirty_pages_ratelimited(mapping);
out: out:
page_cache_release(page); page_cache_release(page);
unlock_page(page); unlock_page(page);
...@@ -815,6 +824,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out, ...@@ -815,6 +824,7 @@ generic_file_splice_write_nolock(struct pipe_inode_info *pipe, struct file *out,
if (err) if (err)
ret = err; ret = err;
} }
balance_dirty_pages_ratelimited(mapping);
} }
return ret; return ret;
...@@ -868,6 +878,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out, ...@@ -868,6 +878,7 @@ generic_file_splice_write(struct pipe_inode_info *pipe, struct file *out,
if (err) if (err)
ret = err; ret = err;
} }
balance_dirty_pages_ratelimited(mapping);
} }
return ret; return ret;
...@@ -922,7 +933,6 @@ static long do_splice_to(struct file *in, loff_t *ppos, ...@@ -922,7 +933,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
struct pipe_inode_info *pipe, size_t len, struct pipe_inode_info *pipe, size_t len,
unsigned int flags) unsigned int flags)
{ {
loff_t isize, left;
int ret; int ret;
if (unlikely(!in->f_op || !in->f_op->splice_read)) if (unlikely(!in->f_op || !in->f_op->splice_read))
...@@ -935,14 +945,6 @@ static long do_splice_to(struct file *in, loff_t *ppos, ...@@ -935,14 +945,6 @@ static long do_splice_to(struct file *in, loff_t *ppos,
if (unlikely(ret < 0)) if (unlikely(ret < 0))
return ret; return ret;
isize = i_size_read(in->f_mapping->host);
if (unlikely(*ppos >= isize))
return 0;
left = isize - *ppos;
if (unlikely(left < len))
len = left;
return in->f_op->splice_read(in, ppos, pipe, len, flags); return in->f_op->splice_read(in, ppos, pipe, len, flags);
} }
...@@ -1058,8 +1060,6 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out, ...@@ -1058,8 +1060,6 @@ long do_splice_direct(struct file *in, loff_t *ppos, struct file *out,
return ret; return ret;
} }
EXPORT_SYMBOL(do_splice_direct);
/* /*
* After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same * After the inode slimming patch, i_pipe/i_bdev/i_cdev share the same
* location, so checking ->i_pipe is not enough to verify that this is a * location, so checking ->i_pipe is not enough to verify that this is a
......
...@@ -238,10 +238,11 @@ static inline int test_and_set_bit(unsigned long nr, ...@@ -238,10 +238,11 @@ static inline int test_and_set_bit(unsigned long nr,
volatile unsigned long *addr) volatile unsigned long *addr)
{ {
unsigned short bit = nr & SZLONG_MASK; unsigned short bit = nr & SZLONG_MASK;
unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) { if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp, res; unsigned long temp;
__asm__ __volatile__( __asm__ __volatile__(
" .set mips3 \n" " .set mips3 \n"
...@@ -254,11 +255,9 @@ static inline int test_and_set_bit(unsigned long nr, ...@@ -254,11 +255,9 @@ static inline int test_and_set_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res) : "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m) : "r" (1UL << bit), "m" (*m)
: "memory"); : "memory");
return res != 0;
} else if (cpu_has_llsc) { } else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp, res; unsigned long temp;
__asm__ __volatile__( __asm__ __volatile__(
" .set push \n" " .set push \n"
...@@ -277,25 +276,22 @@ static inline int test_and_set_bit(unsigned long nr, ...@@ -277,25 +276,22 @@ static inline int test_and_set_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res) : "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m) : "r" (1UL << bit), "m" (*m)
: "memory"); : "memory");
return res != 0;
} else { } else {
volatile unsigned long *a = addr; volatile unsigned long *a = addr;
unsigned long mask; unsigned long mask;
int retval;
unsigned long flags; unsigned long flags;
a += nr >> SZLONG_LOG; a += nr >> SZLONG_LOG;
mask = 1UL << bit; mask = 1UL << bit;
raw_local_irq_save(flags); raw_local_irq_save(flags);
retval = (mask & *a) != 0; res = (mask & *a);
*a |= mask; *a |= mask;
raw_local_irq_restore(flags); raw_local_irq_restore(flags);
return retval;
} }
smp_mb(); smp_mb();
return res != 0;
} }
/* /*
...@@ -310,6 +306,7 @@ static inline int test_and_clear_bit(unsigned long nr, ...@@ -310,6 +306,7 @@ static inline int test_and_clear_bit(unsigned long nr,
volatile unsigned long *addr) volatile unsigned long *addr)
{ {
unsigned short bit = nr & SZLONG_MASK; unsigned short bit = nr & SZLONG_MASK;
unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) { if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
...@@ -327,12 +324,10 @@ static inline int test_and_clear_bit(unsigned long nr, ...@@ -327,12 +324,10 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res) : "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m) : "r" (1UL << bit), "m" (*m)
: "memory"); : "memory");
return res != 0;
#ifdef CONFIG_CPU_MIPSR2 #ifdef CONFIG_CPU_MIPSR2
} else if (__builtin_constant_p(nr)) { } else if (__builtin_constant_p(nr)) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp, res; unsigned long temp;
__asm__ __volatile__( __asm__ __volatile__(
"1: " __LL "%0, %1 # test_and_clear_bit \n" "1: " __LL "%0, %1 # test_and_clear_bit \n"
...@@ -346,12 +341,10 @@ static inline int test_and_clear_bit(unsigned long nr, ...@@ -346,12 +341,10 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res) : "=&r" (temp), "=m" (*m), "=&r" (res)
: "ri" (bit), "m" (*m) : "ri" (bit), "m" (*m)
: "memory"); : "memory");
return res;
#endif #endif
} else if (cpu_has_llsc) { } else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp, res; unsigned long temp;
__asm__ __volatile__( __asm__ __volatile__(
" .set push \n" " .set push \n"
...@@ -371,25 +364,22 @@ static inline int test_and_clear_bit(unsigned long nr, ...@@ -371,25 +364,22 @@ static inline int test_and_clear_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res) : "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m) : "r" (1UL << bit), "m" (*m)
: "memory"); : "memory");
return res != 0;
} else { } else {
volatile unsigned long *a = addr; volatile unsigned long *a = addr;
unsigned long mask; unsigned long mask;
int retval;
unsigned long flags; unsigned long flags;
a += nr >> SZLONG_LOG; a += nr >> SZLONG_LOG;
mask = 1UL << bit; mask = 1UL << bit;
raw_local_irq_save(flags); raw_local_irq_save(flags);
retval = (mask & *a) != 0; res = (mask & *a);
*a &= ~mask; *a &= ~mask;
raw_local_irq_restore(flags); raw_local_irq_restore(flags);
return retval;
} }
smp_mb(); smp_mb();
return res != 0;
} }
/* /*
...@@ -404,10 +394,11 @@ static inline int test_and_change_bit(unsigned long nr, ...@@ -404,10 +394,11 @@ static inline int test_and_change_bit(unsigned long nr,
volatile unsigned long *addr) volatile unsigned long *addr)
{ {
unsigned short bit = nr & SZLONG_MASK; unsigned short bit = nr & SZLONG_MASK;
unsigned long res;
if (cpu_has_llsc && R10000_LLSC_WAR) { if (cpu_has_llsc && R10000_LLSC_WAR) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp, res; unsigned long temp;
__asm__ __volatile__( __asm__ __volatile__(
" .set mips3 \n" " .set mips3 \n"
...@@ -420,11 +411,9 @@ static inline int test_and_change_bit(unsigned long nr, ...@@ -420,11 +411,9 @@ static inline int test_and_change_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res) : "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m) : "r" (1UL << bit), "m" (*m)
: "memory"); : "memory");
return res != 0;
} else if (cpu_has_llsc) { } else if (cpu_has_llsc) {
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG); unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
unsigned long temp, res; unsigned long temp;
__asm__ __volatile__( __asm__ __volatile__(
" .set push \n" " .set push \n"
...@@ -443,24 +432,22 @@ static inline int test_and_change_bit(unsigned long nr, ...@@ -443,24 +432,22 @@ static inline int test_and_change_bit(unsigned long nr,
: "=&r" (temp), "=m" (*m), "=&r" (res) : "=&r" (temp), "=m" (*m), "=&r" (res)
: "r" (1UL << bit), "m" (*m) : "r" (1UL << bit), "m" (*m)
: "memory"); : "memory");
return res != 0;
} else { } else {
volatile unsigned long *a = addr; volatile unsigned long *a = addr;
unsigned long mask, retval; unsigned long mask;
unsigned long flags; unsigned long flags;
a += nr >> SZLONG_LOG; a += nr >> SZLONG_LOG;
mask = 1UL << bit; mask = 1UL << bit;
raw_local_irq_save(flags); raw_local_irq_save(flags);
retval = (mask & *a) != 0; res = (mask & *a);
*a ^= mask; *a ^= mask;
raw_local_irq_restore(flags); raw_local_irq_restore(flags);
return retval;
} }
smp_mb(); smp_mb();
return res != 0;
} }
#include <asm-generic/bitops/non-atomic.h> #include <asm-generic/bitops/non-atomic.h>
......
...@@ -17,6 +17,18 @@ ...@@ -17,6 +17,18 @@
#include <asm/mipsregs.h> #include <asm/mipsregs.h>
#include <asm/asm-offsets.h> #include <asm/asm-offsets.h>
/*
* For SMTC kernel, global IE should be left set, and interrupts
* controlled exclusively via IXMT.
*/
#ifdef CONFIG_MIPS_MT_SMTC
#define STATMASK 0x1e
#elif defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
#define STATMASK 0x3f
#else
#define STATMASK 0x1f
#endif
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
#include <asm/mipsmtregs.h> #include <asm/mipsmtregs.h>
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
...@@ -236,10 +248,10 @@ ...@@ -236,10 +248,10 @@
.set reorder .set reorder
.set noat .set noat
mfc0 a0, CP0_STATUS mfc0 a0, CP0_STATUS
ori a0, 0x1f
xori a0, 0x1f
mtc0 a0, CP0_STATUS
li v1, 0xff00 li v1, 0xff00
ori a0, STATMASK
xori a0, STATMASK
mtc0 a0, CP0_STATUS
and a0, v1 and a0, v1
LONG_L v0, PT_STATUS(sp) LONG_L v0, PT_STATUS(sp)
nor v1, $0, v1 nor v1, $0, v1
...@@ -249,10 +261,6 @@ ...@@ -249,10 +261,6 @@
LONG_L $31, PT_R31(sp) LONG_L $31, PT_R31(sp)
LONG_L $28, PT_R28(sp) LONG_L $28, PT_R28(sp)
LONG_L $25, PT_R25(sp) LONG_L $25, PT_R25(sp)
#ifdef CONFIG_64BIT
LONG_L $8, PT_R8(sp)
LONG_L $9, PT_R9(sp)
#endif
LONG_L $7, PT_R7(sp) LONG_L $7, PT_R7(sp)
LONG_L $6, PT_R6(sp) LONG_L $6, PT_R6(sp)
LONG_L $5, PT_R5(sp) LONG_L $5, PT_R5(sp)
...@@ -273,16 +281,6 @@ ...@@ -273,16 +281,6 @@
.endm .endm
#else #else
/*
* For SMTC kernel, global IE should be left set, and interrupts
* controlled exclusively via IXMT.
*/
#ifdef CONFIG_MIPS_MT_SMTC
#define STATMASK 0x1e
#else
#define STATMASK 0x1f
#endif
.macro RESTORE_SOME .macro RESTORE_SOME
.set push .set push
.set reorder .set reorder
...@@ -385,9 +383,9 @@ ...@@ -385,9 +383,9 @@
.macro CLI .macro CLI
#if !defined(CONFIG_MIPS_MT_SMTC) #if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1f li t1, ST0_CU0 | STATMASK
or t0, t1 or t0, t1
xori t0, 0x1f xori t0, STATMASK
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */ #else /* CONFIG_MIPS_MT_SMTC */
/* /*
...@@ -420,9 +418,9 @@ ...@@ -420,9 +418,9 @@
.macro STI .macro STI
#if !defined(CONFIG_MIPS_MT_SMTC) #if !defined(CONFIG_MIPS_MT_SMTC)
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1f li t1, ST0_CU0 | STATMASK
or t0, t1 or t0, t1
xori t0, 0x1e xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
#else /* CONFIG_MIPS_MT_SMTC */ #else /* CONFIG_MIPS_MT_SMTC */
/* /*
...@@ -451,7 +449,8 @@ ...@@ -451,7 +449,8 @@
.endm .endm
/* /*
* Just move to kernel mode and leave interrupts as they are. * Just move to kernel mode and leave interrupts as they are. Note
* for the R3000 this means copying the previous enable from IEp.
* Set cp0 enable bit as sign that we're running on the kernel stack * Set cp0 enable bit as sign that we're running on the kernel stack
*/ */
.macro KMODE .macro KMODE
...@@ -482,9 +481,14 @@ ...@@ -482,9 +481,14 @@
move ra, t0 move ra, t0
#endif /* CONFIG_MIPS_MT_SMTC */ #endif /* CONFIG_MIPS_MT_SMTC */
mfc0 t0, CP0_STATUS mfc0 t0, CP0_STATUS
li t1, ST0_CU0 | 0x1e li t1, ST0_CU0 | (STATMASK & ~1)
#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)
andi t2, t0, ST0_IEP
srl t2, 2
or t0, t2
#endif
or t0, t1 or t0, t1
xori t0, 0x1e xori t0, STATMASK & ~1
mtc0 t0, CP0_STATUS mtc0 t0, CP0_STATUS
#ifdef CONFIG_MIPS_MT_SMTC #ifdef CONFIG_MIPS_MT_SMTC
_ehb _ehb
......
...@@ -336,16 +336,20 @@ ...@@ -336,16 +336,20 @@
#define __NR_epoll_pwait (__NR_Linux + 313) #define __NR_epoll_pwait (__NR_Linux + 313)
#define __NR_ioprio_set (__NR_Linux + 314) #define __NR_ioprio_set (__NR_Linux + 314)
#define __NR_ioprio_get (__NR_Linux + 315) #define __NR_ioprio_get (__NR_Linux + 315)
#define __NR_utimensat (__NR_Linux + 316)
#define __NR_signalfd (__NR_Linux + 317)
#define __NR_timerfd (__NR_Linux + 318)
#define __NR_eventfd (__NR_Linux + 319)
/* /*
* Offset of the last Linux o32 flavoured syscall * Offset of the last Linux o32 flavoured syscall
*/ */
#define __NR_Linux_syscalls 315 #define __NR_Linux_syscalls 319
#endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */ #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
#define __NR_O32_Linux 4000 #define __NR_O32_Linux 4000
#define __NR_O32_Linux_syscalls 315 #define __NR_O32_Linux_syscalls 319
#if _MIPS_SIM == _MIPS_SIM_ABI64 #if _MIPS_SIM == _MIPS_SIM_ABI64
...@@ -628,16 +632,20 @@ ...@@ -628,16 +632,20 @@
#define __NR_epoll_pwait (__NR_Linux + 272) #define __NR_epoll_pwait (__NR_Linux + 272)
#define __NR_ioprio_set (__NR_Linux + 273) #define __NR_ioprio_set (__NR_Linux + 273)
#define __NR_ioprio_get (__NR_Linux + 274) #define __NR_ioprio_get (__NR_Linux + 274)
#define __NR_utimensat (__NR_Linux + 275)
#define __NR_signalfd (__NR_Linux + 276)
#define __NR_timerfd (__NR_Linux + 277)
#define __NR_eventfd (__NR_Linux + 278)
/* /*
* Offset of the last Linux 64-bit flavoured syscall * Offset of the last Linux 64-bit flavoured syscall
*/ */
#define __NR_Linux_syscalls 274 #define __NR_Linux_syscalls 278
#endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */ #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
#define __NR_64_Linux 5000 #define __NR_64_Linux 5000
#define __NR_64_Linux_syscalls 274 #define __NR_64_Linux_syscalls 278
#if _MIPS_SIM == _MIPS_SIM_NABI32 #if _MIPS_SIM == _MIPS_SIM_NABI32
...@@ -924,16 +932,20 @@ ...@@ -924,16 +932,20 @@
#define __NR_epoll_pwait (__NR_Linux + 276) #define __NR_epoll_pwait (__NR_Linux + 276)
#define __NR_ioprio_set (__NR_Linux + 277) #define __NR_ioprio_set (__NR_Linux + 277)
#define __NR_ioprio_get (__NR_Linux + 278) #define __NR_ioprio_get (__NR_Linux + 278)
#define __NR_utimensat (__NR_Linux + 279)
#define __NR_signalfd (__NR_Linux + 280)
#define __NR_timerfd (__NR_Linux + 281)
#define __NR_eventfd (__NR_Linux + 282)
/* /*
* Offset of the last N32 flavoured syscall * Offset of the last N32 flavoured syscall
*/ */
#define __NR_Linux_syscalls 278 #define __NR_Linux_syscalls 282
#endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */ #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
#define __NR_N32_Linux 6000 #define __NR_N32_Linux 6000
#define __NR_N32_Linux_syscalls 278 #define __NR_N32_Linux_syscalls 282
#ifdef __KERNEL__ #ifdef __KERNEL__
......
...@@ -151,6 +151,7 @@ enum { ...@@ -151,6 +151,7 @@ enum {
ATA_CMD_WRITE_MULTI_EXT = 0x39, ATA_CMD_WRITE_MULTI_EXT = 0x39,
ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE, ATA_CMD_WRITE_MULTI_FUA_EXT = 0xCE,
ATA_CMD_SET_FEATURES = 0xEF, ATA_CMD_SET_FEATURES = 0xEF,
ATA_CMD_SET_MULTI = 0xC6,
ATA_CMD_PACKET = 0xA0, ATA_CMD_PACKET = 0xA0,
ATA_CMD_VERIFY = 0x40, ATA_CMD_VERIFY = 0x40,
ATA_CMD_VERIFY_EXT = 0x42, ATA_CMD_VERIFY_EXT = 0x42,
...@@ -249,7 +250,7 @@ enum ata_tf_protocols { ...@@ -249,7 +250,7 @@ enum ata_tf_protocols {
/* ATA taskfile protocols */ /* ATA taskfile protocols */
ATA_PROT_UNKNOWN, /* unknown/invalid */ ATA_PROT_UNKNOWN, /* unknown/invalid */
ATA_PROT_NODATA, /* no data */ ATA_PROT_NODATA, /* no data */
ATA_PROT_PIO, /* PIO single sector */ ATA_PROT_PIO, /* PIO data xfer */
ATA_PROT_DMA, /* DMA */ ATA_PROT_DMA, /* DMA */
ATA_PROT_NCQ, /* NCQ */ ATA_PROT_NCQ, /* NCQ */
ATA_PROT_ATAPI, /* packet command, PIO data xfer*/ ATA_PROT_ATAPI, /* packet command, PIO data xfer*/
......
...@@ -1001,6 +1001,7 @@ struct ide_driver_s { ...@@ -1001,6 +1001,7 @@ struct ide_driver_s {
struct device_driver gen_driver; struct device_driver gen_driver;
int (*probe)(ide_drive_t *); int (*probe)(ide_drive_t *);
void (*remove)(ide_drive_t *); void (*remove)(ide_drive_t *);
void (*resume)(ide_drive_t *);
void (*shutdown)(ide_drive_t *); void (*shutdown)(ide_drive_t *);
#ifdef CONFIG_IDE_PROC_FS #ifdef CONFIG_IDE_PROC_FS
ide_proc_entry_t *proc; ide_proc_entry_t *proc;
......
...@@ -753,6 +753,7 @@ extern u8 ata_check_status(struct ata_port *ap); ...@@ -753,6 +753,7 @@ extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap); extern u8 ata_altstatus(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf); extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap); extern int ata_port_start (struct ata_port *ap);
extern int ata_sff_port_start (struct ata_port *ap);
extern irqreturn_t ata_interrupt (int irq, void *dev_instance); extern irqreturn_t ata_interrupt (int irq, void *dev_instance);
extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf, extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
unsigned int buflen, int write_data); unsigned int buflen, int write_data);
......
...@@ -1233,6 +1233,8 @@ ...@@ -1233,6 +1233,8 @@
#define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E #define PCI_DEVICE_ID_NVIDIA_NVENET_26 0x054E
#define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F #define PCI_DEVICE_ID_NVIDIA_NVENET_27 0x054F
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560 #define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP67_IDE 0x0560
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP73_IDE 0x056C
#define PCI_DEVICE_ID_NVIDIA_NFORCE_MCP77_IDE 0x0759
#define PCI_VENDOR_ID_IMS 0x10e0 #define PCI_VENDOR_ID_IMS 0x10e0
#define PCI_DEVICE_ID_IMS_TT128 0x9128 #define PCI_DEVICE_ID_IMS_TT128 0x9128
......
...@@ -16,6 +16,21 @@ struct pipe_buffer { ...@@ -16,6 +16,21 @@ struct pipe_buffer {
unsigned int flags; unsigned int flags;
}; };
struct pipe_inode_info {
wait_queue_head_t wait;
unsigned int nrbufs, curbuf;
struct page *tmp_page;
unsigned int readers;
unsigned int writers;
unsigned int waiting_writers;
unsigned int r_counter;
unsigned int w_counter;
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
struct inode *inode;
struct pipe_buffer bufs[PIPE_BUFFERS];
};
/* /*
* Note on the nesting of these functions: * Note on the nesting of these functions:
* *
...@@ -38,21 +53,6 @@ struct pipe_buf_operations { ...@@ -38,21 +53,6 @@ struct pipe_buf_operations {
void (*get)(struct pipe_inode_info *, struct pipe_buffer *); void (*get)(struct pipe_inode_info *, struct pipe_buffer *);
}; };
struct pipe_inode_info {
wait_queue_head_t wait;
unsigned int nrbufs, curbuf;
struct page *tmp_page;
unsigned int readers;
unsigned int writers;
unsigned int waiting_writers;
unsigned int r_counter;
unsigned int w_counter;
struct fasync_struct *fasync_readers;
struct fasync_struct *fasync_writers;
struct inode *inode;
struct pipe_buffer bufs[PIPE_BUFFERS];
};
/* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual /* Differs from PIPE_BUF in that PIPE_SIZE is the length of the actual
memory allocation, whereas PIPE_BUF makes atomicity guarantees. */ memory allocation, whereas PIPE_BUF makes atomicity guarantees. */
#define PIPE_SIZE PAGE_SIZE #define PIPE_SIZE PAGE_SIZE
......
...@@ -243,8 +243,7 @@ struct v4l2_capability ...@@ -243,8 +243,7 @@ struct v4l2_capability
#define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */ #define V4L2_CAP_SLICED_VBI_CAPTURE 0x00000040 /* Is a sliced VBI capture device */
#define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */ #define V4L2_CAP_SLICED_VBI_OUTPUT 0x00000080 /* Is a sliced VBI output device */
#define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */ #define V4L2_CAP_RDS_CAPTURE 0x00000100 /* RDS data capture */
#define V4L2_CAP_VIDEO_OUTPUT_POS 0x00000200 /* Video output can have x,y coords */ #define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000200 /* Can do video output overlay */
#define V4L2_CAP_VIDEO_OUTPUT_OVERLAY 0x00000400 /* Can do video output overlay */
#define V4L2_CAP_TUNER 0x00010000 /* has a tuner */ #define V4L2_CAP_TUNER 0x00010000 /* has a tuner */
#define V4L2_CAP_AUDIO 0x00020000 /* has audio support */ #define V4L2_CAP_AUDIO 0x00020000 /* has audio support */
...@@ -616,12 +615,16 @@ struct v4l2_framebuffer ...@@ -616,12 +615,16 @@ struct v4l2_framebuffer
#define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008 #define V4L2_FBUF_CAP_BITMAP_CLIPPING 0x0008
#define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010 #define V4L2_FBUF_CAP_LOCAL_ALPHA 0x0010
#define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020 #define V4L2_FBUF_CAP_GLOBAL_ALPHA 0x0020
#define V4L2_FBUF_CAP_LOCAL_INV_ALPHA 0x0040
#define V4L2_FBUF_CAP_GLOBAL_INV_ALPHA 0x0080
/* Flags for the 'flags' field. */ /* Flags for the 'flags' field. */
#define V4L2_FBUF_FLAG_PRIMARY 0x0001 #define V4L2_FBUF_FLAG_PRIMARY 0x0001
#define V4L2_FBUF_FLAG_OVERLAY 0x0002 #define V4L2_FBUF_FLAG_OVERLAY 0x0002
#define V4L2_FBUF_FLAG_CHROMAKEY 0x0004 #define V4L2_FBUF_FLAG_CHROMAKEY 0x0004
#define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008 #define V4L2_FBUF_FLAG_LOCAL_ALPHA 0x0008
#define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010 #define V4L2_FBUF_FLAG_GLOBAL_ALPHA 0x0010
#define V4L2_FBUF_FLAG_LOCAL_INV_ALPHA 0x0020
#define V4L2_FBUF_FLAG_GLOBAL_INV_ALPHA 0x0040
struct v4l2_clip struct v4l2_clip
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册