Commit 0202b160 authored by Jeff Garzik's avatar Jeff Garzik

Merge pobox.com:/garz/repo/netdev-2.6/r8169

into pobox.com:/garz/repo/net-drivers-2.6
parents 3cbae07b f5f23ec8
...@@ -107,8 +107,11 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address) ...@@ -107,8 +107,11 @@ pte_t *pte_alloc_one_kernel(struct mm_struct *mm, unsigned long address)
ptepage->mapping = (void *) mm; ptepage->mapping = (void *) mm;
ptepage->index = address & PMD_MASK; ptepage->index = address & PMD_MASK;
} }
} else } else {
pte = (pte_t *)early_get_page(); pte = (pte_t *)early_get_page();
if (pte)
clear_page(pte);
}
return pte; return pte;
} }
......
...@@ -62,7 +62,7 @@ void flush_hash_one_pte(pte_t *ptep) ...@@ -62,7 +62,7 @@ void flush_hash_one_pte(pte_t *ptep)
ptepage = virt_to_page(ptep); ptepage = virt_to_page(ptep);
mm = (struct mm_struct *) ptepage->mapping; mm = (struct mm_struct *) ptepage->mapping;
ptephys = __pa(ptep) & PAGE_MASK; ptephys = __pa(ptep) & PAGE_MASK;
addr = ptepage->index + (((unsigned long)ptep & ~PAGE_MASK) << 9); addr = ptepage->index + (((unsigned long)ptep & ~PAGE_MASK) << 10);
flush_hash_pages(mm->context, addr, ptephys, 1); flush_hash_pages(mm->context, addr, ptephys, 1);
} }
......
...@@ -628,11 +628,13 @@ int xmon_fault_handler(struct pt_regs *regs) ...@@ -628,11 +628,13 @@ int xmon_fault_handler(struct pt_regs *regs)
(data address breakpoint register) directly. */ (data address breakpoint register) directly. */
static void set_controlled_dabr(unsigned long val) static void set_controlled_dabr(unsigned long val)
{ {
#ifdef CONFIG_PPC_PSERIES
if (systemcfg->platform == PLATFORM_PSERIES_LPAR) { if (systemcfg->platform == PLATFORM_PSERIES_LPAR) {
int rc = plpar_hcall_norets(H_SET_DABR, val); int rc = plpar_hcall_norets(H_SET_DABR, val);
if (rc != H_Success) if (rc != H_Success)
xmon_printf("Warning: setting DABR failed (%d)\n", rc); xmon_printf("Warning: setting DABR failed (%d)\n", rc);
} else } else
#endif
set_dabr(val); set_dabr(val);
} }
......
...@@ -34,7 +34,7 @@ struct alps_model_info { ...@@ -34,7 +34,7 @@ struct alps_model_info {
unsigned char signature[3]; unsigned char signature[3];
unsigned char model; unsigned char model;
} alps_model_data[] = { } alps_model_data[] = {
{ { 0x33, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, /* { { 0x33, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, */
{ { 0x53, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, { { 0x53, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
{ { 0x53, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT }, { { 0x53, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
{ { 0x63, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, { { 0x63, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
...@@ -42,8 +42,8 @@ struct alps_model_info { ...@@ -42,8 +42,8 @@ struct alps_model_info {
{ { 0x73, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT }, { { 0x73, 0x02, 0x0a }, ALPS_MODEL_GLIDEPOINT },
{ { 0x73, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT }, { { 0x73, 0x02, 0x14 }, ALPS_MODEL_GLIDEPOINT },
{ { 0x63, 0x02, 0x28 }, ALPS_MODEL_GLIDEPOINT }, { { 0x63, 0x02, 0x28 }, ALPS_MODEL_GLIDEPOINT },
{ { 0x63, 0x02, 0x3c }, ALPS_MODEL_GLIDEPOINT }, /* { { 0x63, 0x02, 0x3c }, ALPS_MODEL_GLIDEPOINT }, */
{ { 0x63, 0x02, 0x50 }, ALPS_MODEL_GLIDEPOINT }, /* { { 0x63, 0x02, 0x50 }, ALPS_MODEL_GLIDEPOINT }, */
{ { 0x63, 0x02, 0x64 }, ALPS_MODEL_GLIDEPOINT }, { { 0x63, 0x02, 0x64 }, ALPS_MODEL_GLIDEPOINT },
{ { 0x20, 0x02, 0x0e }, ALPS_MODEL_DUALPOINT }, { { 0x20, 0x02, 0x0e }, ALPS_MODEL_DUALPOINT },
{ { 0x22, 0x02, 0x0a }, ALPS_MODEL_DUALPOINT }, { { 0x22, 0x02, 0x0a }, ALPS_MODEL_DUALPOINT },
......
...@@ -253,9 +253,9 @@ static struct region *__rh_alloc(struct region_hash *rh, region_t region) ...@@ -253,9 +253,9 @@ static struct region *__rh_alloc(struct region_hash *rh, region_t region)
else { else {
__rh_insert(rh, nreg); __rh_insert(rh, nreg);
if (nreg->state == RH_CLEAN) { if (nreg->state == RH_CLEAN) {
spin_lock_irq(&rh->region_lock); spin_lock(&rh->region_lock);
list_add(&nreg->list, &rh->clean_regions); list_add(&nreg->list, &rh->clean_regions);
spin_unlock_irq(&rh->region_lock); spin_unlock(&rh->region_lock);
} }
reg = nreg; reg = nreg;
} }
......
...@@ -457,6 +457,14 @@ config SCSI_SATA_PROMISE ...@@ -457,6 +457,14 @@ config SCSI_SATA_PROMISE
If unsure, say N. If unsure, say N.
config SCSI_SATA_QSTOR
tristate "Pacific Digital SATA QStor support"
depends on SCSI_SATA && PCI
help
This option enables support for Pacific Digital Serial ATA QStor.
If unsure, say N.
config SCSI_SATA_SX4 config SCSI_SATA_SX4
tristate "Promise SATA SX4 support" tristate "Promise SATA SX4 support"
depends on SCSI_SATA && PCI && EXPERIMENTAL depends on SCSI_SATA && PCI && EXPERIMENTAL
......
...@@ -125,6 +125,7 @@ obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o ...@@ -125,6 +125,7 @@ obj-$(CONFIG_SCSI_SATA_AHCI) += libata.o ahci.o
obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o obj-$(CONFIG_SCSI_SATA_SVW) += libata.o sata_svw.o
obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o obj-$(CONFIG_SCSI_ATA_PIIX) += libata.o ata_piix.o
obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o obj-$(CONFIG_SCSI_SATA_PROMISE) += libata.o sata_promise.o
obj-$(CONFIG_SCSI_SATA_QSTOR) += libata.o sata_qstor.o
obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o obj-$(CONFIG_SCSI_SATA_SIL) += libata.o sata_sil.o
obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o obj-$(CONFIG_SCSI_SATA_VIA) += libata.o sata_via.o
obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o obj-$(CONFIG_SCSI_SATA_VITESSE) += libata.o sata_vsc.o
......
...@@ -179,6 +179,7 @@ static void ahci_port_stop(struct ata_port *ap); ...@@ -179,6 +179,7 @@ static void ahci_port_stop(struct ata_port *ap);
static void ahci_host_stop(struct ata_host_set *host_set); static void ahci_host_stop(struct ata_host_set *host_set);
static void ahci_qc_prep(struct ata_queued_cmd *qc); static void ahci_qc_prep(struct ata_queued_cmd *qc);
static u8 ahci_check_status(struct ata_port *ap); static u8 ahci_check_status(struct ata_port *ap);
static u8 ahci_check_err(struct ata_port *ap);
static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc); static inline int ahci_host_intr(struct ata_port *ap, struct ata_queued_cmd *qc);
static Scsi_Host_Template ahci_sht = { static Scsi_Host_Template ahci_sht = {
...@@ -204,6 +205,8 @@ static struct ata_port_operations ahci_ops = { ...@@ -204,6 +205,8 @@ static struct ata_port_operations ahci_ops = {
.port_disable = ata_port_disable, .port_disable = ata_port_disable,
.check_status = ahci_check_status, .check_status = ahci_check_status,
.check_altstatus = ahci_check_status,
.check_err = ahci_check_err,
.dev_select = ata_noop_dev_select, .dev_select = ata_noop_dev_select,
.phy_reset = ahci_phy_reset, .phy_reset = ahci_phy_reset,
...@@ -452,6 +455,13 @@ static u8 ahci_check_status(struct ata_port *ap) ...@@ -452,6 +455,13 @@ static u8 ahci_check_status(struct ata_port *ap)
return readl(mmio + PORT_TFDATA) & 0xFF; return readl(mmio + PORT_TFDATA) & 0xFF;
} }
static u8 ahci_check_err(struct ata_port *ap)
{
void *mmio = (void *) ap->ioaddr.cmd_addr;
return (readl(mmio + PORT_TFDATA) >> 8) & 0xFF;
}
static void ahci_fill_sg(struct ata_queued_cmd *qc) static void ahci_fill_sg(struct ata_queued_cmd *qc)
{ {
struct ahci_port_priv *pp = qc->ap->private_data; struct ahci_port_priv *pp = qc->ap->private_data;
...@@ -940,6 +950,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -940,6 +950,7 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
unsigned long base; unsigned long base;
void *mmio_base; void *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
int rc; int rc;
VPRINTK("ENTER\n"); VPRINTK("ENTER\n");
...@@ -952,8 +963,10 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -952,8 +963,10 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
pci_enable_intx(pdev); pci_enable_intx(pdev);
...@@ -1015,7 +1028,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -1015,7 +1028,8 @@ static int ahci_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -138,6 +138,8 @@ static struct ata_port_operations piix_pata_ops = { ...@@ -138,6 +138,8 @@ static struct ata_port_operations piix_pata_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
...@@ -163,6 +165,8 @@ static struct ata_port_operations piix_sata_ops = { ...@@ -163,6 +165,8 @@ static struct ata_port_operations piix_sata_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
......
...@@ -377,7 +377,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf) ...@@ -377,7 +377,7 @@ void ata_tf_read(struct ata_port *ap, struct ata_taskfile *tf)
} }
/** /**
* ata_check_status - Read device status reg & clear interrupt * ata_check_status_pio - Read device status reg & clear interrupt
* @ap: port where the device is * @ap: port where the device is
* *
* Reads ATA taskfile status register for currently-selected device * Reads ATA taskfile status register for currently-selected device
...@@ -415,6 +415,27 @@ u8 ata_check_status(struct ata_port *ap) ...@@ -415,6 +415,27 @@ u8 ata_check_status(struct ata_port *ap)
return ata_check_status_pio(ap); return ata_check_status_pio(ap);
} }
u8 ata_altstatus(struct ata_port *ap)
{
if (ap->ops->check_altstatus)
return ap->ops->check_altstatus(ap);
if (ap->flags & ATA_FLAG_MMIO)
return readb((void __iomem *)ap->ioaddr.altstatus_addr);
return inb(ap->ioaddr.altstatus_addr);
}
u8 ata_chk_err(struct ata_port *ap)
{
if (ap->ops->check_err)
return ap->ops->check_err(ap);
if (ap->flags & ATA_FLAG_MMIO) {
return readb((void __iomem *) ap->ioaddr.error_addr);
}
return inb(ap->ioaddr.error_addr);
}
/** /**
* ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure * ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
* @tf: Taskfile to convert * @tf: Taskfile to convert
...@@ -1161,7 +1182,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device) ...@@ -1161,7 +1182,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n", printk(KERN_WARNING "ata%u: dev %u not supported, ignoring\n",
ap->id, device); ap->id, device);
err_out: err_out:
ata_irq_on(ap); /* re-enable interrupts */
dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */ dev->class++; /* converts ATA_DEV_xxx into ATA_DEV_xxx_UNSUP */
DPRINTK("EXIT, err\n"); DPRINTK("EXIT, err\n");
} }
...@@ -1669,7 +1689,8 @@ void ata_bus_reset(struct ata_port *ap) ...@@ -1669,7 +1689,8 @@ void ata_bus_reset(struct ata_port *ap)
ata_dev_try_classify(ap, 1); ata_dev_try_classify(ap, 1);
/* re-enable interrupts */ /* re-enable interrupts */
ata_irq_on(ap); if (ap->ioaddr.ctl_addr) /* FIXME: hack. create a hook instead */
ata_irq_on(ap);
/* is double-select really necessary? */ /* is double-select really necessary? */
if (ap->device[1].class != ATA_DEV_NONE) if (ap->device[1].class != ATA_DEV_NONE)
...@@ -2601,10 +2622,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ...@@ -2601,10 +2622,10 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
case ATA_PROT_DMA: case ATA_PROT_DMA:
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
host_stat = ata_bmdma_status(ap); host_stat = ap->ops->bmdma_status(ap);
/* before we do anything else, clear DMA-Start bit */ /* before we do anything else, clear DMA-Start bit */
ata_bmdma_stop(ap); ap->ops->bmdma_stop(ap);
/* fall through */ /* fall through */
...@@ -2613,7 +2634,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc) ...@@ -2613,7 +2634,7 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
drv_stat = ata_chk_status(ap); drv_stat = ata_chk_status(ap);
/* ack bmdma irq events */ /* ack bmdma irq events */
ata_bmdma_ack_irq(ap); ap->ops->irq_clear(ap);
printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n", printk(KERN_ERR "ata%u: command 0x%x timeout, stat 0x%x host_stat 0x%x\n",
ap->id, qc->tf.command, drv_stat, host_stat); ap->id, qc->tf.command, drv_stat, host_stat);
...@@ -2751,6 +2772,24 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc) ...@@ -2751,6 +2772,24 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
clear_bit(tag, &ap->qactive); clear_bit(tag, &ap->qactive);
} }
/**
* ata_qc_free - free unused ata_queued_cmd
* @qc: Command to complete
*
* Designed to free unused ata_queued_cmd object
* in case something prevents using it.
*
* LOCKING:
*
*/
void ata_qc_free(struct ata_queued_cmd *qc)
{
assert(qc != NULL); /* ata_qc_from_tag _might_ return NULL */
assert(qc->waiting == NULL); /* nothing should be waiting */
__ata_qc_complete(qc);
}
/** /**
* ata_qc_complete - Complete an active ATA command * ata_qc_complete - Complete an active ATA command
* @qc: Command to complete * @qc: Command to complete
...@@ -3042,7 +3081,43 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc) ...@@ -3042,7 +3081,43 @@ void ata_bmdma_setup(struct ata_queued_cmd *qc)
void ata_bmdma_irq_clear(struct ata_port *ap) void ata_bmdma_irq_clear(struct ata_port *ap)
{ {
ata_bmdma_ack_irq(ap); if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
writeb(readb(mmio), mmio);
} else {
unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
outb(inb(addr), addr);
}
}
u8 ata_bmdma_status(struct ata_port *ap)
{
u8 host_stat;
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
return host_stat;
}
void ata_bmdma_stop(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
/* clear start/stop bit */
writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
mmio + ATA_DMA_CMD);
} else {
/* clear start/stop bit */
outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_altstatus(ap); /* dummy read */
} }
/** /**
...@@ -3072,7 +3147,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -3072,7 +3147,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
case ATA_PROT_ATAPI_DMA: case ATA_PROT_ATAPI_DMA:
case ATA_PROT_ATAPI: case ATA_PROT_ATAPI:
/* check status of DMA engine */ /* check status of DMA engine */
host_stat = ata_bmdma_status(ap); host_stat = ap->ops->bmdma_status(ap);
VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat); VPRINTK("ata%u: host_stat 0x%X\n", ap->id, host_stat);
/* if it's not our irq... */ /* if it's not our irq... */
...@@ -3080,7 +3155,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -3080,7 +3155,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
goto idle_irq; goto idle_irq;
/* before we do anything else, clear DMA-Start bit */ /* before we do anything else, clear DMA-Start bit */
ata_bmdma_stop(ap); ap->ops->bmdma_stop(ap);
/* fall through */ /* fall through */
...@@ -3099,7 +3174,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap, ...@@ -3099,7 +3174,7 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
ap->id, qc->tf.protocol, status); ap->id, qc->tf.protocol, status);
/* ack bmdma irq events */ /* ack bmdma irq events */
ata_bmdma_ack_irq(ap); ap->ops->irq_clear(ap);
/* complete taskfile transaction */ /* complete taskfile transaction */
ata_qc_complete(qc, status); ata_qc_complete(qc, status);
...@@ -3656,6 +3731,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, ...@@ -3656,6 +3731,7 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
struct ata_port_info *port[2]; struct ata_port_info *port[2];
u8 tmp8, mask; u8 tmp8, mask;
unsigned int legacy_mode = 0; unsigned int legacy_mode = 0;
int disable_dev_on_err = 1;
int rc; int rc;
DPRINTK("ENTER\n"); DPRINTK("ENTER\n");
...@@ -3686,8 +3762,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, ...@@ -3686,8 +3762,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
disable_dev_on_err = 0;
goto err_out; goto err_out;
}
if (legacy_mode) { if (legacy_mode) {
if (!request_region(0x1f0, 8, "libata")) { if (!request_region(0x1f0, 8, "libata")) {
...@@ -3697,8 +3775,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, ...@@ -3697,8 +3775,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
conflict = ____request_resource(&ioport_resource, &res); conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata")) if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 0); legacy_mode |= (1 << 0);
else else {
disable_dev_on_err = 0;
printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n"); printk(KERN_WARNING "ata: 0x1f0 IDE port busy\n");
}
} else } else
legacy_mode |= (1 << 0); legacy_mode |= (1 << 0);
...@@ -3709,8 +3789,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, ...@@ -3709,8 +3789,10 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
conflict = ____request_resource(&ioport_resource, &res); conflict = ____request_resource(&ioport_resource, &res);
if (!strcmp(conflict->name, "libata")) if (!strcmp(conflict->name, "libata"))
legacy_mode |= (1 << 1); legacy_mode |= (1 << 1);
else else {
disable_dev_on_err = 0;
printk(KERN_WARNING "ata: 0x170 IDE port busy\n"); printk(KERN_WARNING "ata: 0x170 IDE port busy\n");
}
} else } else
legacy_mode |= (1 << 1); legacy_mode |= (1 << 1);
} }
...@@ -3760,7 +3842,8 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info, ...@@ -3760,7 +3842,8 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
release_region(0x170, 8); release_region(0x170, 8);
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (disable_dev_on_err)
pci_disable_device(pdev);
return rc; return rc;
} }
...@@ -3910,6 +3993,8 @@ EXPORT_SYMBOL_GPL(ata_std_dev_select); ...@@ -3910,6 +3993,8 @@ EXPORT_SYMBOL_GPL(ata_std_dev_select);
EXPORT_SYMBOL_GPL(ata_tf_to_fis); EXPORT_SYMBOL_GPL(ata_tf_to_fis);
EXPORT_SYMBOL_GPL(ata_tf_from_fis); EXPORT_SYMBOL_GPL(ata_tf_from_fis);
EXPORT_SYMBOL_GPL(ata_check_status); EXPORT_SYMBOL_GPL(ata_check_status);
EXPORT_SYMBOL_GPL(ata_altstatus);
EXPORT_SYMBOL_GPL(ata_chk_err);
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_port_stop); EXPORT_SYMBOL_GPL(ata_port_stop);
...@@ -3918,6 +4003,8 @@ EXPORT_SYMBOL_GPL(ata_qc_prep); ...@@ -3918,6 +4003,8 @@ EXPORT_SYMBOL_GPL(ata_qc_prep);
EXPORT_SYMBOL_GPL(ata_bmdma_setup); EXPORT_SYMBOL_GPL(ata_bmdma_setup);
EXPORT_SYMBOL_GPL(ata_bmdma_start); EXPORT_SYMBOL_GPL(ata_bmdma_start);
EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear); EXPORT_SYMBOL_GPL(ata_bmdma_irq_clear);
EXPORT_SYMBOL_GPL(ata_bmdma_status);
EXPORT_SYMBOL_GPL(ata_bmdma_stop);
EXPORT_SYMBOL_GPL(ata_port_probe); EXPORT_SYMBOL_GPL(ata_port_probe);
EXPORT_SYMBOL_GPL(sata_phy_reset); EXPORT_SYMBOL_GPL(sata_phy_reset);
EXPORT_SYMBOL_GPL(__sata_phy_reset); EXPORT_SYMBOL_GPL(__sata_phy_reset);
......
...@@ -701,6 +701,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev, ...@@ -701,6 +701,7 @@ static void ata_scsi_translate(struct ata_port *ap, struct ata_device *dev,
return; return;
err_out: err_out:
ata_qc_free(qc);
ata_bad_cdb(cmd, done); ata_bad_cdb(cmd, done);
DPRINTK("EXIT - badcmd\n"); DPRINTK("EXIT - badcmd\n");
} }
......
...@@ -37,6 +37,7 @@ struct ata_scsi_args { ...@@ -37,6 +37,7 @@ struct ata_scsi_args {
/* libata-core.c */ /* libata-core.c */
extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap, extern struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
struct ata_device *dev); struct ata_device *dev);
extern void ata_qc_free(struct ata_queued_cmd *qc);
extern int ata_qc_issue(struct ata_queued_cmd *qc); extern int ata_qc_issue(struct ata_queued_cmd *qc);
extern int ata_check_atapi_dma(struct ata_queued_cmd *qc); extern int ata_check_atapi_dma(struct ata_queued_cmd *qc);
extern void ata_dev_select(struct ata_port *ap, unsigned int device, extern void ata_dev_select(struct ata_port *ap, unsigned int device,
......
...@@ -217,6 +217,8 @@ static struct ata_port_operations nv_ops = { ...@@ -217,6 +217,8 @@ static struct ata_port_operations nv_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
...@@ -332,6 +334,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -332,6 +334,7 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct nv_host *host; struct nv_host *host;
struct ata_port_info *ppi; struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent; struct ata_probe_ent *probe_ent;
int pci_dev_busy = 0;
int rc; int rc;
u32 bar; u32 bar;
...@@ -350,8 +353,10 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -350,8 +353,10 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out; goto err_out;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out_disable; goto err_out_disable;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)
...@@ -427,7 +432,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -427,7 +432,8 @@ static int nv_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out_disable: err_out_disable:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
err_out: err_out:
return rc; return rc;
} }
......
...@@ -556,6 +556,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -556,6 +556,7 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
unsigned long base; unsigned long base;
void *mmio_base; void *mmio_base;
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
int rc; int rc;
if (!printed_version++) if (!printed_version++)
...@@ -570,8 +571,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -570,8 +571,10 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)
...@@ -650,7 +653,8 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -650,7 +653,8 @@ static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
This diff is collapsed.
...@@ -139,6 +139,8 @@ static struct ata_port_operations sil_ops = { ...@@ -139,6 +139,8 @@ static struct ata_port_operations sil_ops = {
.post_set_mode = sil_post_set_mode, .post_set_mode = sil_post_set_mode,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
...@@ -336,6 +338,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -336,6 +338,7 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
void *mmio_base; void *mmio_base;
int rc; int rc;
unsigned int i; unsigned int i;
int pci_dev_busy = 0;
u32 tmp, irq_mask; u32 tmp, irq_mask;
if (!printed_version++) if (!printed_version++)
...@@ -350,8 +353,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -350,8 +353,10 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)
...@@ -438,7 +443,8 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -438,7 +443,8 @@ static int sil_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -102,6 +102,8 @@ static struct ata_port_operations sis_ops = { ...@@ -102,6 +102,8 @@ static struct ata_port_operations sis_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
...@@ -200,14 +202,17 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -200,14 +202,17 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
int rc; int rc;
u32 genctl; u32 genctl;
struct ata_port_info *ppi; struct ata_port_info *ppi;
int pci_dev_busy = 0;
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) if (rc)
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)
...@@ -259,7 +264,8 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -259,7 +264,8 @@ static int sis_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -301,6 +301,8 @@ static struct ata_port_operations k2_sata_ops = { ...@@ -301,6 +301,8 @@ static struct ata_port_operations k2_sata_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = k2_bmdma_setup_mmio, .bmdma_setup = k2_bmdma_setup_mmio,
.bmdma_start = k2_bmdma_start_mmio, .bmdma_start = k2_bmdma_start_mmio,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
...@@ -338,6 +340,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -338,6 +340,7 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
struct ata_probe_ent *probe_ent = NULL; struct ata_probe_ent *probe_ent = NULL;
unsigned long base; unsigned long base;
void *mmio_base; void *mmio_base;
int pci_dev_busy = 0;
int rc; int rc;
if (!printed_version++) if (!printed_version++)
...@@ -359,8 +362,10 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -359,8 +362,10 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
/* Request PCI regions */ /* Request PCI regions */
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)
...@@ -433,7 +438,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e ...@@ -433,7 +438,8 @@ static int k2_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *e
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -1366,6 +1366,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1366,6 +1366,7 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
void *mmio_base, *dimm_mmio = NULL; void *mmio_base, *dimm_mmio = NULL;
struct pdc_host_priv *hpriv = NULL; struct pdc_host_priv *hpriv = NULL;
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
int rc; int rc;
if (!printed_version++) if (!printed_version++)
...@@ -1380,8 +1381,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1380,8 +1381,10 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)
...@@ -1471,7 +1474,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id * ...@@ -1471,7 +1474,8 @@ static int pdc_sata_init_one (struct pci_dev *pdev, const struct pci_device_id *
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -97,6 +97,8 @@ static struct ata_port_operations uli_ops = { ...@@ -97,6 +97,8 @@ static struct ata_port_operations uli_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
...@@ -185,14 +187,17 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -185,14 +187,17 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
struct ata_port_info *ppi; struct ata_port_info *ppi;
int rc; int rc;
unsigned int board_idx = (unsigned int) ent->driver_data; unsigned int board_idx = (unsigned int) ent->driver_data;
int pci_dev_busy = 0;
rc = pci_enable_device(pdev); rc = pci_enable_device(pdev);
if (rc) if (rc)
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
rc = pci_set_dma_mask(pdev, ATA_DMA_MASK); rc = pci_set_dma_mask(pdev, ATA_DMA_MASK);
if (rc) if (rc)
...@@ -260,7 +265,8 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -260,7 +265,8 @@ static int uli_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -24,6 +24,11 @@ ...@@ -24,6 +24,11 @@
If you do not delete the provisions above, a recipient may use your If you do not delete the provisions above, a recipient may use your
version of this file under either the OSL or the GPL. version of this file under either the OSL or the GPL.
----------------------------------------------------------------------
To-do list:
* VT6421 PATA support
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -38,11 +43,14 @@ ...@@ -38,11 +43,14 @@
#include <asm/io.h> #include <asm/io.h>
#define DRV_NAME "sata_via" #define DRV_NAME "sata_via"
#define DRV_VERSION "1.0" #define DRV_VERSION "1.1"
enum { enum board_ids_enum {
via_sata = 0, vt6420,
vt6421,
};
enum {
SATA_CHAN_ENAB = 0x40, /* SATA channel enable */ SATA_CHAN_ENAB = 0x40, /* SATA channel enable */
SATA_INT_GATE = 0x41, /* SATA interrupt gating */ SATA_INT_GATE = 0x41, /* SATA interrupt gating */
SATA_NATIVE_MODE = 0x42, /* Native mode enable */ SATA_NATIVE_MODE = 0x42, /* Native mode enable */
...@@ -50,10 +58,8 @@ enum { ...@@ -50,10 +58,8 @@ enum {
PORT0 = (1 << 1), PORT0 = (1 << 1),
PORT1 = (1 << 0), PORT1 = (1 << 0),
ALL_PORTS = PORT0 | PORT1,
ENAB_ALL = PORT0 | PORT1, N_PORTS = 2,
INT_GATE_ALL = PORT0 | PORT1,
NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4), NATIVE_MODE_ALL = (1 << 7) | (1 << 6) | (1 << 5) | (1 << 4),
...@@ -66,7 +72,8 @@ static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg); ...@@ -66,7 +72,8 @@ static u32 svia_scr_read (struct ata_port *ap, unsigned int sc_reg);
static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val); static void svia_scr_write (struct ata_port *ap, unsigned int sc_reg, u32 val);
static struct pci_device_id svia_pci_tbl[] = { static struct pci_device_id svia_pci_tbl[] = {
{ 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, via_sata }, { 0x1106, 0x3149, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6420 },
{ 0x1106, 0x3249, PCI_ANY_ID, PCI_ANY_ID, 0, 0, vt6421 },
{ } /* terminate list */ { } /* terminate list */
}; };
...@@ -110,6 +117,9 @@ static struct ata_port_operations svia_sata_ops = { ...@@ -110,6 +117,9 @@ static struct ata_port_operations svia_sata_ops = {
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
...@@ -158,18 +168,132 @@ static const unsigned int svia_bar_sizes[] = { ...@@ -158,18 +168,132 @@ static const unsigned int svia_bar_sizes[] = {
8, 4, 8, 4, 16, 256 8, 4, 8, 4, 16, 256
}; };
static const unsigned int vt6421_bar_sizes[] = {
16, 16, 16, 16, 32, 128
};
static unsigned long svia_scr_addr(unsigned long addr, unsigned int port) static unsigned long svia_scr_addr(unsigned long addr, unsigned int port)
{ {
return addr + (port * 128); return addr + (port * 128);
} }
static unsigned long vt6421_scr_addr(unsigned long addr, unsigned int port)
{
return addr + (port * 64);
}
static void vt6421_init_addrs(struct ata_probe_ent *probe_ent,
struct pci_dev *pdev,
unsigned int port)
{
unsigned long reg_addr = pci_resource_start(pdev, port);
unsigned long bmdma_addr = pci_resource_start(pdev, 4) + (port * 8);
unsigned long scr_addr;
probe_ent->port[port].cmd_addr = reg_addr;
probe_ent->port[port].altstatus_addr =
probe_ent->port[port].ctl_addr = (reg_addr + 8) | ATA_PCI_CTL_OFS;
probe_ent->port[port].bmdma_addr = bmdma_addr;
scr_addr = vt6421_scr_addr(pci_resource_start(pdev, 5), port);
probe_ent->port[port].scr_addr = scr_addr;
ata_std_ports(&probe_ent->port[port]);
}
static struct ata_probe_ent *vt6420_init_probe_ent(struct pci_dev *pdev)
{
struct ata_probe_ent *probe_ent;
struct ata_port_info *ppi = &svia_port_info;
probe_ent = ata_pci_init_native_mode(pdev, &ppi);
if (!probe_ent)
return NULL;
probe_ent->port[0].scr_addr =
svia_scr_addr(pci_resource_start(pdev, 5), 0);
probe_ent->port[1].scr_addr =
svia_scr_addr(pci_resource_start(pdev, 5), 1);
return probe_ent;
}
static struct ata_probe_ent *vt6421_init_probe_ent(struct pci_dev *pdev)
{
struct ata_probe_ent *probe_ent;
unsigned int i;
probe_ent = kmalloc(sizeof(*probe_ent), GFP_KERNEL);
if (!probe_ent)
return NULL;
memset(probe_ent, 0, sizeof(*probe_ent));
probe_ent->dev = pci_dev_to_dev(pdev);
INIT_LIST_HEAD(&probe_ent->node);
probe_ent->sht = &svia_sht;
probe_ent->host_flags = ATA_FLAG_SATA | ATA_FLAG_SATA_RESET |
ATA_FLAG_NO_LEGACY;
probe_ent->port_ops = &svia_sata_ops;
probe_ent->n_ports = N_PORTS;
probe_ent->irq = pdev->irq;
probe_ent->irq_flags = SA_SHIRQ;
probe_ent->pio_mask = 0x1f;
probe_ent->mwdma_mask = 0x07;
probe_ent->udma_mask = 0x7f;
for (i = 0; i < N_PORTS; i++)
vt6421_init_addrs(probe_ent, pdev, i);
return probe_ent;
}
static void svia_configure(struct pci_dev *pdev)
{
u8 tmp8;
pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
pci_name(pdev),
(int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
/* make sure SATA channels are enabled */
pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
pci_name(pdev), (int) tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
}
/* make sure interrupts for each channel sent to us */
pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
if ((tmp8 & ALL_PORTS) != ALL_PORTS) {
printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
pci_name(pdev), (int) tmp8);
tmp8 |= ALL_PORTS;
pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
}
/* make sure native mode is enabled */
pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
pci_name(pdev), (int) tmp8);
tmp8 |= NATIVE_MODE_ALL;
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
}
static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
{ {
static int printed_version; static int printed_version;
unsigned int i; unsigned int i;
int rc; int rc;
struct ata_port_info *ppi;
struct ata_probe_ent *probe_ent; struct ata_probe_ent *probe_ent;
int board_id = (int) ent->driver_data;
const int *bar_sizes;
int pci_dev_busy = 0;
u8 tmp8; u8 tmp8;
if (!printed_version++) if (!printed_version++)
...@@ -180,20 +304,28 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -180,20 +304,28 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
return rc; return rc;
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8); if (board_id == vt6420) {
if (tmp8 & SATA_2DEV) { pci_read_config_byte(pdev, SATA_PATA_SHARING, &tmp8);
printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n", if (tmp8 & SATA_2DEV) {
pci_name(pdev), (int) tmp8); printk(KERN_ERR DRV_NAME "(%s): SATA master/slave not supported (0x%x)\n",
rc = -EIO; pci_name(pdev), (int) tmp8);
goto err_out_regions; rc = -EIO;
goto err_out_regions;
}
bar_sizes = &svia_bar_sizes[0];
} else {
bar_sizes = &vt6421_bar_sizes[0];
} }
for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++) for (i = 0; i < ARRAY_SIZE(svia_bar_sizes); i++)
if ((pci_resource_start(pdev, i) == 0) || if ((pci_resource_start(pdev, i) == 0) ||
(pci_resource_len(pdev, i) < svia_bar_sizes[i])) { (pci_resource_len(pdev, i) < bar_sizes[i])) {
printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n", printk(KERN_ERR DRV_NAME "(%s): invalid PCI BAR %u (sz 0x%lx, val 0x%lx)\n",
pci_name(pdev), i, pci_name(pdev), i,
pci_resource_start(pdev, i), pci_resource_start(pdev, i),
...@@ -209,8 +341,11 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -209,8 +341,11 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
if (rc) if (rc)
goto err_out_regions; goto err_out_regions;
ppi = &svia_port_info; if (board_id == vt6420)
probe_ent = ata_pci_init_native_mode(pdev, &ppi); probe_ent = vt6420_init_probe_ent(pdev);
else
probe_ent = vt6421_init_probe_ent(pdev);
if (!probe_ent) { if (!probe_ent) {
printk(KERN_ERR DRV_NAME "(%s): out of memory\n", printk(KERN_ERR DRV_NAME "(%s): out of memory\n",
pci_name(pdev)); pci_name(pdev));
...@@ -218,42 +353,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -218,42 +353,7 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
goto err_out_regions; goto err_out_regions;
} }
probe_ent->port[0].scr_addr = svia_configure(pdev);
svia_scr_addr(pci_resource_start(pdev, 5), 0);
probe_ent->port[1].scr_addr =
svia_scr_addr(pci_resource_start(pdev, 5), 1);
pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &tmp8);
printk(KERN_INFO DRV_NAME "(%s): routed to hard irq line %d\n",
pci_name(pdev),
(int) (tmp8 & 0xf0) == 0xf0 ? 0 : tmp8 & 0x0f);
/* make sure SATA channels are enabled */
pci_read_config_byte(pdev, SATA_CHAN_ENAB, &tmp8);
if ((tmp8 & ENAB_ALL) != ENAB_ALL) {
printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channels (0x%x)\n",
pci_name(pdev), (int) tmp8);
tmp8 |= ENAB_ALL;
pci_write_config_byte(pdev, SATA_CHAN_ENAB, tmp8);
}
/* make sure interrupts for each channel sent to us */
pci_read_config_byte(pdev, SATA_INT_GATE, &tmp8);
if ((tmp8 & INT_GATE_ALL) != INT_GATE_ALL) {
printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel interrupts (0x%x)\n",
pci_name(pdev), (int) tmp8);
tmp8 |= INT_GATE_ALL;
pci_write_config_byte(pdev, SATA_INT_GATE, tmp8);
}
/* make sure native mode is enabled */
pci_read_config_byte(pdev, SATA_NATIVE_MODE, &tmp8);
if ((tmp8 & NATIVE_MODE_ALL) != NATIVE_MODE_ALL) {
printk(KERN_DEBUG DRV_NAME "(%s): enabling SATA channel native mode (0x%x)\n",
pci_name(pdev), (int) tmp8);
tmp8 |= NATIVE_MODE_ALL;
pci_write_config_byte(pdev, SATA_NATIVE_MODE, tmp8);
}
pci_set_master(pdev); pci_set_master(pdev);
...@@ -266,7 +366,8 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -266,7 +366,8 @@ static int svia_init_one (struct pci_dev *pdev, const struct pci_device_id *ent)
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -217,6 +217,8 @@ static struct ata_port_operations vsc_sata_ops = { ...@@ -217,6 +217,8 @@ static struct ata_port_operations vsc_sata_ops = {
.phy_reset = sata_phy_reset, .phy_reset = sata_phy_reset,
.bmdma_setup = ata_bmdma_setup, .bmdma_setup = ata_bmdma_setup,
.bmdma_start = ata_bmdma_start, .bmdma_start = ata_bmdma_start,
.bmdma_stop = ata_bmdma_stop,
.bmdma_status = ata_bmdma_status,
.qc_prep = ata_qc_prep, .qc_prep = ata_qc_prep,
.qc_issue = ata_qc_issue_prot, .qc_issue = ata_qc_issue_prot,
.eng_timeout = ata_eng_timeout, .eng_timeout = ata_eng_timeout,
...@@ -255,6 +257,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d ...@@ -255,6 +257,7 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
static int printed_version; static int printed_version;
struct ata_probe_ent *probe_ent = NULL; struct ata_probe_ent *probe_ent = NULL;
unsigned long base; unsigned long base;
int pci_dev_busy = 0;
void *mmio_base; void *mmio_base;
int rc; int rc;
...@@ -274,8 +277,10 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d ...@@ -274,8 +277,10 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
} }
rc = pci_request_regions(pdev, DRV_NAME); rc = pci_request_regions(pdev, DRV_NAME);
if (rc) if (rc) {
pci_dev_busy = 1;
goto err_out; goto err_out;
}
/* /*
* Use 32 bit DMA mask, because 64 bit address support is poor. * Use 32 bit DMA mask, because 64 bit address support is poor.
...@@ -352,7 +357,8 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d ...@@ -352,7 +357,8 @@ static int __devinit vsc_sata_init_one (struct pci_dev *pdev, const struct pci_d
err_out_regions: err_out_regions:
pci_release_regions(pdev); pci_release_regions(pdev);
err_out: err_out:
pci_disable_device(pdev); if (!pci_dev_busy)
pci_disable_device(pdev);
return rc; return rc;
} }
......
...@@ -303,10 +303,10 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl) ...@@ -303,10 +303,10 @@ static int do_getlk(struct file *filp, int cmd, struct file_lock *fl)
status = NFS_PROTO(inode)->lock(filp, cmd, fl); status = NFS_PROTO(inode)->lock(filp, cmd, fl);
else { else {
struct file_lock *cfl = posix_test_lock(filp, fl); struct file_lock *cfl = posix_test_lock(filp, fl);
if (cfl != NULL) {
fl->fl_type = F_UNLCK;
if (cfl != NULL)
memcpy(fl, cfl, sizeof(*fl)); memcpy(fl, cfl, sizeof(*fl));
fl->fl_type = F_UNLCK;
}
} }
unlock_kernel(); unlock_kernel();
return status; return status;
......
...@@ -54,7 +54,7 @@ struct agp_kern_info { ...@@ -54,7 +54,7 @@ struct agp_kern_info {
struct pci_dev *device; struct pci_dev *device;
enum chipset_type chipset; enum chipset_type chipset;
unsigned long mode; unsigned long mode;
off_t aper_base; unsigned long aper_base;
size_t aper_size; size_t aper_size;
int max_memory; /* In pages */ int max_memory; /* In pages */
int current_memory; int current_memory;
......
...@@ -64,7 +64,7 @@ typedef struct _agp_info { ...@@ -64,7 +64,7 @@ typedef struct _agp_info {
struct agp_version version; /* version of the driver */ struct agp_version version; /* version of the driver */
__u32 bridge_id; /* bridge vendor/device */ __u32 bridge_id; /* bridge vendor/device */
__u32 agp_mode; /* mode info of bridge */ __u32 agp_mode; /* mode info of bridge */
off_t aper_base; /* base of aperture */ unsigned long aper_base;/* base of aperture */
size_t aper_size; /* size of aperture */ size_t aper_size; /* size of aperture */
size_t pg_total; /* max pages (swap + system) */ size_t pg_total; /* max pages (swap + system) */
size_t pg_system; /* max pages (system) */ size_t pg_system; /* max pages (system) */
...@@ -118,7 +118,7 @@ struct agp_info { ...@@ -118,7 +118,7 @@ struct agp_info {
struct agp_version version; /* version of the driver */ struct agp_version version; /* version of the driver */
u32 bridge_id; /* bridge vendor/device */ u32 bridge_id; /* bridge vendor/device */
u32 agp_mode; /* mode info of bridge */ u32 agp_mode; /* mode info of bridge */
off_t aper_base; /* base of aperture */ unsigned long aper_base;/* base of aperture */
size_t aper_size; /* size of aperture */ size_t aper_size; /* size of aperture */
size_t pg_total; /* max pages (swap + system) */ size_t pg_total; /* max pages (swap + system) */
size_t pg_system; /* max pages (system) */ size_t pg_system; /* max pages (system) */
......
...@@ -334,6 +334,8 @@ struct ata_port_operations { ...@@ -334,6 +334,8 @@ struct ata_port_operations {
void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf); void (*exec_command)(struct ata_port *ap, struct ata_taskfile *tf);
u8 (*check_status)(struct ata_port *ap); u8 (*check_status)(struct ata_port *ap);
u8 (*check_altstatus)(struct ata_port *ap);
u8 (*check_err)(struct ata_port *ap);
void (*dev_select)(struct ata_port *ap, unsigned int device); void (*dev_select)(struct ata_port *ap, unsigned int device);
void (*phy_reset) (struct ata_port *ap); void (*phy_reset) (struct ata_port *ap);
...@@ -360,6 +362,9 @@ struct ata_port_operations { ...@@ -360,6 +362,9 @@ struct ata_port_operations {
void (*port_stop) (struct ata_port *ap); void (*port_stop) (struct ata_port *ap);
void (*host_stop) (struct ata_host_set *host_set); void (*host_stop) (struct ata_host_set *host_set);
void (*bmdma_stop) (struct ata_port *ap);
u8 (*bmdma_status) (struct ata_port *ap);
}; };
struct ata_port_info { struct ata_port_info {
...@@ -400,6 +405,8 @@ extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf); ...@@ -400,6 +405,8 @@ extern void ata_tf_from_fis(u8 *fis, struct ata_taskfile *tf);
extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device); extern void ata_noop_dev_select (struct ata_port *ap, unsigned int device);
extern void ata_std_dev_select (struct ata_port *ap, unsigned int device); extern void ata_std_dev_select (struct ata_port *ap, unsigned int device);
extern u8 ata_check_status(struct ata_port *ap); extern u8 ata_check_status(struct ata_port *ap);
extern u8 ata_altstatus(struct ata_port *ap);
extern u8 ata_chk_err(struct ata_port *ap);
extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf); extern void ata_exec_command(struct ata_port *ap, struct ata_taskfile *tf);
extern int ata_port_start (struct ata_port *ap); extern int ata_port_start (struct ata_port *ap);
extern void ata_port_stop (struct ata_port *ap); extern void ata_port_stop (struct ata_port *ap);
...@@ -415,6 +422,8 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s, ...@@ -415,6 +422,8 @@ extern void ata_dev_id_string(u16 *id, unsigned char *s,
unsigned int ofs, unsigned int len); unsigned int ofs, unsigned int len);
extern void ata_bmdma_setup (struct ata_queued_cmd *qc); extern void ata_bmdma_setup (struct ata_queued_cmd *qc);
extern void ata_bmdma_start (struct ata_queued_cmd *qc); extern void ata_bmdma_start (struct ata_queued_cmd *qc);
extern void ata_bmdma_stop(struct ata_port *ap);
extern u8 ata_bmdma_status(struct ata_port *ap);
extern void ata_bmdma_irq_clear(struct ata_port *ap); extern void ata_bmdma_irq_clear(struct ata_port *ap);
extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat); extern void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat);
extern void ata_eng_timeout(struct ata_port *ap); extern void ata_eng_timeout(struct ata_port *ap);
...@@ -452,26 +461,11 @@ static inline unsigned int ata_dev_present(struct ata_device *dev) ...@@ -452,26 +461,11 @@ static inline unsigned int ata_dev_present(struct ata_device *dev)
(dev->class == ATA_DEV_ATAPI)); (dev->class == ATA_DEV_ATAPI));
} }
static inline u8 ata_chk_err(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
return readb((void __iomem *) ap->ioaddr.error_addr);
}
return inb(ap->ioaddr.error_addr);
}
static inline u8 ata_chk_status(struct ata_port *ap) static inline u8 ata_chk_status(struct ata_port *ap)
{ {
return ap->ops->check_status(ap); return ap->ops->check_status(ap);
} }
static inline u8 ata_altstatus(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO)
return readb((void __iomem *)ap->ioaddr.altstatus_addr);
return inb(ap->ioaddr.altstatus_addr);
}
static inline void ata_pause(struct ata_port *ap) static inline void ata_pause(struct ata_port *ap)
{ {
ata_altstatus(ap); ata_altstatus(ap);
...@@ -595,46 +589,6 @@ static inline unsigned int sata_dev_present(struct ata_port *ap) ...@@ -595,46 +589,6 @@ static inline unsigned int sata_dev_present(struct ata_port *ap)
return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0; return ((scr_read(ap, SCR_STATUS) & 0xf) == 0x3) ? 1 : 0;
} }
static inline void ata_bmdma_stop(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
/* clear start/stop bit */
writeb(readb(mmio + ATA_DMA_CMD) & ~ATA_DMA_START,
mmio + ATA_DMA_CMD);
} else {
/* clear start/stop bit */
outb(inb(ap->ioaddr.bmdma_addr + ATA_DMA_CMD) & ~ATA_DMA_START,
ap->ioaddr.bmdma_addr + ATA_DMA_CMD);
}
/* one-PIO-cycle guaranteed wait, per spec, for HDMA1:0 transition */
ata_altstatus(ap); /* dummy read */
}
static inline void ata_bmdma_ack_irq(struct ata_port *ap)
{
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = ((void __iomem *) ap->ioaddr.bmdma_addr) + ATA_DMA_STATUS;
writeb(readb(mmio), mmio);
} else {
unsigned long addr = ap->ioaddr.bmdma_addr + ATA_DMA_STATUS;
outb(inb(addr), addr);
}
}
static inline u8 ata_bmdma_status(struct ata_port *ap)
{
u8 host_stat;
if (ap->flags & ATA_FLAG_MMIO) {
void __iomem *mmio = (void __iomem *) ap->ioaddr.bmdma_addr;
host_stat = readb(mmio + ATA_DMA_STATUS);
} else
host_stat = inb(ap->ioaddr.bmdma_addr + ATA_DMA_STATUS);
return host_stat;
}
static inline int ata_try_flush_cache(struct ata_device *dev) static inline int ata_try_flush_cache(struct ata_device *dev)
{ {
return ata_id_wcache_enabled(dev->id) || return ata_id_wcache_enabled(dev->id) ||
......
...@@ -258,6 +258,18 @@ static void drop_key_refs(union futex_key *key) ...@@ -258,6 +258,18 @@ static void drop_key_refs(union futex_key *key)
} }
} }
static inline int get_futex_value_locked(int *dest, int __user *from)
{
int ret;
inc_preempt_count();
ret = __copy_from_user_inatomic(dest, from, sizeof(int));
dec_preempt_count();
preempt_check_resched();
return ret ? -EFAULT : 0;
}
/* /*
* The hash bucket lock must be held when this is called. * The hash bucket lock must be held when this is called.
* Afterwards, the futex_q must not be accessed. * Afterwards, the futex_q must not be accessed.
...@@ -329,6 +341,7 @@ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2, ...@@ -329,6 +341,7 @@ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
int ret, drop_count = 0; int ret, drop_count = 0;
unsigned int nqueued; unsigned int nqueued;
retry:
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
ret = get_futex_key(uaddr1, &key1); ret = get_futex_key(uaddr1, &key1);
...@@ -355,9 +368,20 @@ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2, ...@@ -355,9 +368,20 @@ static int futex_requeue(unsigned long uaddr1, unsigned long uaddr2,
before *uaddr1. */ before *uaddr1. */
smp_mb(); smp_mb();
if (get_user(curval, (int __user *)uaddr1) != 0) { ret = get_futex_value_locked(&curval, (int __user *)uaddr1);
ret = -EFAULT;
goto out; if (unlikely(ret)) {
/* If we would have faulted, release mmap_sem, fault
* it in and start all over again.
*/
up_read(&current->mm->mmap_sem);
ret = get_user(curval, (int __user *)uaddr1);
if (!ret)
goto retry;
return ret;
} }
if (curval != *valp) { if (curval != *valp) {
ret = -EAGAIN; ret = -EAGAIN;
...@@ -480,6 +504,7 @@ static int futex_wait(unsigned long uaddr, int val, unsigned long time) ...@@ -480,6 +504,7 @@ static int futex_wait(unsigned long uaddr, int val, unsigned long time)
int ret, curval; int ret, curval;
struct futex_q q; struct futex_q q;
retry:
down_read(&current->mm->mmap_sem); down_read(&current->mm->mmap_sem);
ret = get_futex_key(uaddr, &q.key); ret = get_futex_key(uaddr, &q.key);
...@@ -508,9 +533,23 @@ static int futex_wait(unsigned long uaddr, int val, unsigned long time) ...@@ -508,9 +533,23 @@ static int futex_wait(unsigned long uaddr, int val, unsigned long time)
* We hold the mmap semaphore, so the mapping cannot have changed * We hold the mmap semaphore, so the mapping cannot have changed
* since we looked it up in get_futex_key. * since we looked it up in get_futex_key.
*/ */
if (get_user(curval, (int __user *)uaddr) != 0) {
ret = -EFAULT; ret = get_futex_value_locked(&curval, (int __user *)uaddr);
goto out_unqueue;
if (unlikely(ret)) {
/* If we would have faulted, release mmap_sem, fault it in and
* start all over again.
*/
up_read(&current->mm->mmap_sem);
if (!unqueue_me(&q)) /* There's a chance we got woken already */
return 0;
ret = get_user(curval, (int __user *)uaddr);
if (!ret)
goto retry;
return ret;
} }
if (curval != val) { if (curval != val) {
ret = -EWOULDBLOCK; ret = -EWOULDBLOCK;
......
...@@ -524,9 +524,13 @@ asmlinkage long sys_get_mempolicy(int __user *policy, ...@@ -524,9 +524,13 @@ asmlinkage long sys_get_mempolicy(int __user *policy,
} else } else
pval = pol->policy; pval = pol->policy;
err = -EFAULT; if (vma) {
up_read(&current->mm->mmap_sem);
vma = NULL;
}
if (policy && put_user(pval, policy)) if (policy && put_user(pval, policy))
goto out; return -EFAULT;
err = 0; err = 0;
if (nmask) { if (nmask) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment