Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/tg3.c drivers/net/wireless/rt2x00/rt2x00dev.c net/mac80211/ieee80211_i.h
This commit is contained in:
@@ -565,7 +565,7 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
|
||||
|
||||
acpi_os_release_mutex(method_desc->method.
|
||||
mutex->mutex.os_mutex);
|
||||
method_desc->method.mutex->mutex.thread_id = 0;
|
||||
method_desc->method.mutex->mutex.thread_id = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -326,7 +326,7 @@ acpi_status acpi_ex_release_mutex_object(union acpi_operand_object *obj_desc)
|
||||
|
||||
/* Clear mutex info */
|
||||
|
||||
obj_desc->mutex.thread_id = 0;
|
||||
obj_desc->mutex.thread_id = NULL;
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
@@ -463,7 +463,7 @@ void acpi_ex_release_all_mutexes(struct acpi_thread_state *thread)
|
||||
/* Mark mutex unowned */
|
||||
|
||||
obj_desc->mutex.owner_thread = NULL;
|
||||
obj_desc->mutex.thread_id = 0;
|
||||
obj_desc->mutex.thread_id = NULL;
|
||||
|
||||
/* Update Thread sync_level (Last mutex is the important one) */
|
||||
|
||||
|
||||
+4
-4
@@ -502,10 +502,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bcd), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bce), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bcf), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bd0), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bd1), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bd2), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bd3), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bc4), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bc5), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bc6), board_ahci }, /* MCP7B */
|
||||
{ PCI_VDEVICE(NVIDIA, 0x0bc7), board_ahci }, /* MCP7B */
|
||||
|
||||
/* SiS */
|
||||
{ PCI_VDEVICE(SI, 0x1184), board_ahci }, /* SiS 966 */
|
||||
|
||||
@@ -247,10 +247,11 @@ static const struct pci_device_id piix_pci_tbl[] = {
|
||||
{ 0x8086, 0x2820, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
|
||||
/* SATA Controller 2 IDE (ICH8) */
|
||||
{ 0x8086, 0x2825, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
|
||||
/* Mobile SATA Controller IDE (ICH8M) */
|
||||
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
|
||||
/* Mobile SATA Controller IDE (ICH8M), Apple */
|
||||
{ 0x8086, 0x2828, 0x106b, 0x00a0, 0, 0, ich8m_apple_sata },
|
||||
{ 0x8086, 0x2828, 0x106b, 0x00a1, 0, 0, ich8m_apple_sata },
|
||||
/* Mobile SATA Controller IDE (ICH8M) */
|
||||
{ 0x8086, 0x2828, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
|
||||
/* SATA Controller IDE (ICH9) */
|
||||
{ 0x8086, 0x2920, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
|
||||
/* SATA Controller IDE (ICH9) */
|
||||
@@ -526,7 +527,7 @@ static struct ata_port_info piix_port_info[] = {
|
||||
|
||||
[ich8m_apple_sata] =
|
||||
{
|
||||
.flags = PIIX_SATA_FLAGS | PIIX_FLAG_SIDPR,
|
||||
.flags = PIIX_SATA_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.mwdma_mask = 0x07, /* mwdma0-2 */
|
||||
.udma_mask = ATA_UDMA6,
|
||||
|
||||
+48
-25
@@ -118,8 +118,8 @@ static void ata_acpi_associate_ide_port(struct ata_port *ap)
|
||||
ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
|
||||
}
|
||||
|
||||
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
|
||||
u32 event)
|
||||
static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device
|
||||
*dev, u32 event)
|
||||
{
|
||||
char event_string[12];
|
||||
char *envp[] = { event_string, NULL };
|
||||
@@ -127,6 +127,9 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
|
||||
struct kobject *kobj = NULL;
|
||||
int wait = 0;
|
||||
unsigned long flags;
|
||||
acpi_handle handle, tmphandle;
|
||||
unsigned long sta;
|
||||
acpi_status status;
|
||||
|
||||
if (!ap)
|
||||
ap = dev->link->ap;
|
||||
@@ -134,32 +137,57 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
|
||||
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
if (dev)
|
||||
handle = dev->acpi_handle;
|
||||
else
|
||||
handle = ap->acpi_handle;
|
||||
|
||||
status = acpi_get_handle(handle, "_EJ0", &tmphandle);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
/* This device is not ejectable */
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_STA", NULL, &sta);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
printk ("Unable to determine bay status\n");
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event) {
|
||||
case ACPI_NOTIFY_BUS_CHECK:
|
||||
case ACPI_NOTIFY_DEVICE_CHECK:
|
||||
ata_ehi_push_desc(ehi, "ACPI event");
|
||||
ata_ehi_hotplugged(ehi);
|
||||
ata_port_freeze(ap);
|
||||
break;
|
||||
if (!sta) {
|
||||
/* Device has been unplugged */
|
||||
if (dev)
|
||||
dev->flags |= ATA_DFLAG_DETACH;
|
||||
else {
|
||||
struct ata_link *tlink;
|
||||
struct ata_device *tdev;
|
||||
|
||||
case ACPI_NOTIFY_EJECT_REQUEST:
|
||||
ata_ehi_push_desc(ehi, "ACPI event");
|
||||
if (dev)
|
||||
dev->flags |= ATA_DFLAG_DETACH;
|
||||
else {
|
||||
struct ata_link *tlink;
|
||||
struct ata_device *tdev;
|
||||
|
||||
ata_port_for_each_link(tlink, ap)
|
||||
ata_link_for_each_dev(tdev, tlink)
|
||||
tdev->flags |= ATA_DFLAG_DETACH;
|
||||
ata_port_for_each_link(tlink, ap) {
|
||||
ata_link_for_each_dev(tdev, tlink) {
|
||||
tdev->flags |=
|
||||
ATA_DFLAG_DETACH;
|
||||
}
|
||||
}
|
||||
}
|
||||
ata_port_schedule_eh(ap);
|
||||
wait = 1;
|
||||
} else {
|
||||
ata_ehi_hotplugged(ehi);
|
||||
ata_port_freeze(ap);
|
||||
}
|
||||
|
||||
ata_port_schedule_eh(ap);
|
||||
wait = 1;
|
||||
break;
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
if (wait)
|
||||
ata_port_wait_eh(ap);
|
||||
|
||||
if (dev) {
|
||||
if (dev->sdev)
|
||||
kobj = &dev->sdev->sdev_gendev.kobj;
|
||||
@@ -170,11 +198,6 @@ static void ata_acpi_handle_hotplug(struct ata_port *ap, struct ata_device *dev,
|
||||
sprintf(event_string, "BAY_EVENT=%d", event);
|
||||
kobject_uevent_env(kobj, KOBJ_CHANGE, envp);
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
|
||||
if (wait)
|
||||
ata_port_wait_eh(ap);
|
||||
}
|
||||
|
||||
static void ata_acpi_dev_notify(acpi_handle handle, u32 event, void *data)
|
||||
|
||||
+23
-19
@@ -2126,6 +2126,13 @@ int ata_dev_configure(struct ata_device *dev)
|
||||
dev->horkage |= ata_dev_blacklisted(dev);
|
||||
ata_force_horkage(dev);
|
||||
|
||||
if (dev->horkage & ATA_HORKAGE_DISABLE) {
|
||||
ata_dev_printk(dev, KERN_INFO,
|
||||
"unsupported device, disabling\n");
|
||||
ata_dev_disable(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* let ACPI work its magic */
|
||||
rc = ata_acpi_on_devcfg(dev);
|
||||
if (rc)
|
||||
@@ -3490,22 +3497,11 @@ int sata_link_resume(struct ata_link *link, const unsigned long *params,
|
||||
if ((rc = sata_link_debounce(link, params, deadline)))
|
||||
return rc;
|
||||
|
||||
/* Clear SError. PMP and some host PHYs require this to
|
||||
* operate and clearing should be done before checking PHY
|
||||
* online status to avoid race condition (hotplugging between
|
||||
* link resume and status check).
|
||||
*/
|
||||
/* clear SError, some PHYs require this even for SRST to work */
|
||||
if (!(rc = sata_scr_read(link, SCR_ERROR, &serror)))
|
||||
rc = sata_scr_write(link, SCR_ERROR, serror);
|
||||
if (rc == 0 || rc == -EINVAL) {
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(link->ap->lock, flags);
|
||||
link->eh_info.serror = 0;
|
||||
spin_unlock_irqrestore(link->ap->lock, flags);
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
return rc != -EINVAL ? rc : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3653,9 +3649,13 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing,
|
||||
if (check_ready)
|
||||
rc = ata_wait_ready(link, deadline, check_ready);
|
||||
out:
|
||||
if (rc && rc != -EAGAIN)
|
||||
if (rc && rc != -EAGAIN) {
|
||||
/* online is set iff link is online && reset succeeded */
|
||||
if (online)
|
||||
*online = false;
|
||||
ata_link_printk(link, KERN_ERR,
|
||||
"COMRESET failed (errno=%d)\n", rc);
|
||||
}
|
||||
DPRINTK("EXIT, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
@@ -3700,8 +3700,14 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
|
||||
*/
|
||||
void ata_std_postreset(struct ata_link *link, unsigned int *classes)
|
||||
{
|
||||
u32 serror;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
|
||||
/* reset complete, clear SError */
|
||||
if (!sata_scr_read(link, SCR_ERROR, &serror))
|
||||
sata_scr_write(link, SCR_ERROR, serror);
|
||||
|
||||
/* print link status */
|
||||
sata_print_link_status(link);
|
||||
|
||||
@@ -3894,8 +3900,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
|
||||
{ "SAMSUNG CD-ROM SN-124", "N001", ATA_HORKAGE_NODMA },
|
||||
{ "Seagate STT20000A", NULL, ATA_HORKAGE_NODMA },
|
||||
/* Odd clown on sil3726/4726 PMPs */
|
||||
{ "Config Disk", NULL, ATA_HORKAGE_NODMA |
|
||||
ATA_HORKAGE_SKIP_PM },
|
||||
{ "Config Disk", NULL, ATA_HORKAGE_DISABLE },
|
||||
|
||||
/* Weird ATAPI devices */
|
||||
{ "TORiSAN DVD-ROM DRD-N216", NULL, ATA_HORKAGE_MAX_SEC_128 },
|
||||
@@ -5398,7 +5403,7 @@ static void ata_host_stop(struct device *gendev, void *res)
|
||||
*/
|
||||
static void ata_finalize_port_ops(struct ata_port_operations *ops)
|
||||
{
|
||||
static spinlock_t lock = SPIN_LOCK_UNLOCKED;
|
||||
static DEFINE_SPINLOCK(lock);
|
||||
const struct ata_port_operations *cur;
|
||||
void **begin = (void **)ops;
|
||||
void **end = (void **)&ops->inherits;
|
||||
@@ -5616,7 +5621,7 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
|
||||
ehi->probe_mask |= ATA_ALL_DEVICES;
|
||||
ehi->action |= ATA_EH_RESET;
|
||||
ehi->action |= ATA_EH_RESET | ATA_EH_LPM;
|
||||
ehi->flags |= ATA_EHI_NO_AUTOPSY | ATA_EHI_QUIET;
|
||||
|
||||
ap->pflags &= ~ATA_PFLAG_INITIALIZING;
|
||||
@@ -5649,7 +5654,6 @@ int ata_host_register(struct ata_host *host, struct scsi_host_template *sht)
|
||||
struct ata_port *ap = host->ports[i];
|
||||
|
||||
ata_scsi_scan_host(ap, 1);
|
||||
ata_lpm_schedule(ap, ap->pm_policy);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
+113
-94
@@ -1308,12 +1308,7 @@ static void ata_eh_analyze_serror(struct ata_link *link)
|
||||
unsigned int err_mask = 0, action = 0;
|
||||
u32 hotplug_mask;
|
||||
|
||||
if (serror & SERR_PERSISTENT) {
|
||||
err_mask |= AC_ERR_ATA_BUS;
|
||||
action |= ATA_EH_RESET;
|
||||
}
|
||||
if (serror &
|
||||
(SERR_DATA_RECOVERED | SERR_COMM_RECOVERED | SERR_DATA)) {
|
||||
if (serror & (SERR_PERSISTENT | SERR_DATA)) {
|
||||
err_mask |= AC_ERR_ATA_BUS;
|
||||
action |= ATA_EH_RESET;
|
||||
}
|
||||
@@ -2047,19 +2042,11 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset,
|
||||
unsigned int *classes, unsigned long deadline)
|
||||
{
|
||||
struct ata_device *dev;
|
||||
int rc;
|
||||
|
||||
ata_link_for_each_dev(dev, link)
|
||||
classes[dev->devno] = ATA_DEV_UNKNOWN;
|
||||
|
||||
rc = reset(link, classes, deadline);
|
||||
|
||||
/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
|
||||
ata_link_for_each_dev(dev, link)
|
||||
if (classes[dev->devno] == ATA_DEV_UNKNOWN)
|
||||
classes[dev->devno] = ATA_DEV_NONE;
|
||||
|
||||
return rc;
|
||||
return reset(link, classes, deadline);
|
||||
}
|
||||
|
||||
static int ata_eh_followup_srst_needed(struct ata_link *link,
|
||||
@@ -2096,9 +2083,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
|
||||
ata_reset_fn_t reset;
|
||||
unsigned long flags;
|
||||
u32 sstatus;
|
||||
int rc;
|
||||
int nr_known, rc;
|
||||
|
||||
/* about to reset */
|
||||
/*
|
||||
* Prepare to reset
|
||||
*/
|
||||
spin_lock_irqsave(ap->lock, flags);
|
||||
ap->pflags |= ATA_PFLAG_RESETTING;
|
||||
spin_unlock_irqrestore(ap->lock, flags);
|
||||
@@ -2124,16 +2113,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
|
||||
ap->ops->set_piomode(ap, dev);
|
||||
}
|
||||
|
||||
if (!softreset && !hardreset) {
|
||||
if (verbose)
|
||||
ata_link_printk(link, KERN_INFO, "no reset method "
|
||||
"available, skipping reset\n");
|
||||
if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
|
||||
lflags |= ATA_LFLAG_ASSUME_ATA;
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* prefer hardreset */
|
||||
reset = NULL;
|
||||
ehc->i.action &= ~ATA_EH_RESET;
|
||||
if (hardreset) {
|
||||
reset = hardreset;
|
||||
@@ -2141,11 +2122,6 @@ int ata_eh_reset(struct ata_link *link, int classify,
|
||||
} else if (softreset) {
|
||||
reset = softreset;
|
||||
ehc->i.action = ATA_EH_SOFTRESET;
|
||||
} else {
|
||||
ata_link_printk(link, KERN_ERR, "BUG: no reset method, "
|
||||
"please report to linux-ide@vger.kernel.org\n");
|
||||
dump_stack();
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (prereset) {
|
||||
@@ -2165,55 +2141,71 @@ int ata_eh_reset(struct ata_link *link, int classify,
|
||||
"prereset failed (errno=%d)\n", rc);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* prereset() might have cleared ATA_EH_RESET */
|
||||
if (!(ehc->i.action & ATA_EH_RESET)) {
|
||||
/* prereset told us not to reset, bang classes and return */
|
||||
ata_link_for_each_dev(dev, link)
|
||||
classes[dev->devno] = ATA_DEV_NONE;
|
||||
rc = 0;
|
||||
goto out;
|
||||
/* prereset() might have cleared ATA_EH_RESET. If so,
|
||||
* bang classes and return.
|
||||
*/
|
||||
if (reset && !(ehc->i.action & ATA_EH_RESET)) {
|
||||
ata_link_for_each_dev(dev, link)
|
||||
classes[dev->devno] = ATA_DEV_NONE;
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
retry:
|
||||
/*
|
||||
* Perform reset
|
||||
*/
|
||||
if (ata_is_host_link(link))
|
||||
ata_eh_freeze_port(ap);
|
||||
|
||||
deadline = jiffies + ata_eh_reset_timeouts[try++];
|
||||
|
||||
/* shut up during boot probing */
|
||||
if (verbose)
|
||||
ata_link_printk(link, KERN_INFO, "%s resetting link\n",
|
||||
reset == softreset ? "soft" : "hard");
|
||||
if (reset) {
|
||||
if (verbose)
|
||||
ata_link_printk(link, KERN_INFO, "%s resetting link\n",
|
||||
reset == softreset ? "soft" : "hard");
|
||||
|
||||
/* mark that this EH session started with reset */
|
||||
if (reset == hardreset)
|
||||
ehc->i.flags |= ATA_EHI_DID_HARDRESET;
|
||||
else
|
||||
ehc->i.flags |= ATA_EHI_DID_SOFTRESET;
|
||||
/* mark that this EH session started with reset */
|
||||
if (reset == hardreset)
|
||||
ehc->i.flags |= ATA_EHI_DID_HARDRESET;
|
||||
else
|
||||
ehc->i.flags |= ATA_EHI_DID_SOFTRESET;
|
||||
|
||||
rc = ata_do_reset(link, reset, classes, deadline);
|
||||
rc = ata_do_reset(link, reset, classes, deadline);
|
||||
|
||||
if (reset == hardreset &&
|
||||
ata_eh_followup_srst_needed(link, rc, classify, classes)) {
|
||||
/* okay, let's do follow-up softreset */
|
||||
reset = softreset;
|
||||
if (reset == hardreset &&
|
||||
ata_eh_followup_srst_needed(link, rc, classify, classes)) {
|
||||
/* okay, let's do follow-up softreset */
|
||||
reset = softreset;
|
||||
|
||||
if (!reset) {
|
||||
ata_link_printk(link, KERN_ERR,
|
||||
"follow-up softreset required "
|
||||
"but no softreset avaliable\n");
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
if (!reset) {
|
||||
ata_link_printk(link, KERN_ERR,
|
||||
"follow-up softreset required "
|
||||
"but no softreset avaliable\n");
|
||||
rc = -EINVAL;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
|
||||
rc = ata_do_reset(link, reset, classes, deadline);
|
||||
}
|
||||
|
||||
ata_eh_about_to_do(link, NULL, ATA_EH_RESET);
|
||||
rc = ata_do_reset(link, reset, classes, deadline);
|
||||
/* -EAGAIN can happen if we skipped followup SRST */
|
||||
if (rc && rc != -EAGAIN)
|
||||
goto fail;
|
||||
} else {
|
||||
if (verbose)
|
||||
ata_link_printk(link, KERN_INFO, "no reset method "
|
||||
"available, skipping reset\n");
|
||||
if (!(lflags & ATA_LFLAG_ASSUME_CLASS))
|
||||
lflags |= ATA_LFLAG_ASSUME_ATA;
|
||||
}
|
||||
|
||||
/* -EAGAIN can happen if we skipped followup SRST */
|
||||
if (rc && rc != -EAGAIN)
|
||||
goto fail;
|
||||
|
||||
done:
|
||||
/*
|
||||
* Post-reset processing
|
||||
*/
|
||||
ata_link_for_each_dev(dev, link) {
|
||||
/* After the reset, the device state is PIO 0 and the
|
||||
* controller state is undefined. Reset also wakes up
|
||||
@@ -2236,9 +2228,53 @@ int ata_eh_reset(struct ata_link *link, int classify,
|
||||
if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
|
||||
link->sata_spd = (sstatus >> 4) & 0xf;
|
||||
|
||||
/* thaw the port */
|
||||
if (ata_is_host_link(link))
|
||||
ata_eh_thaw_port(ap);
|
||||
|
||||
/* postreset() should clear hardware SError. Although SError
|
||||
* is cleared during link resume, clearing SError here is
|
||||
* necessary as some PHYs raise hotplug events after SRST.
|
||||
* This introduces race condition where hotplug occurs between
|
||||
* reset and here. This race is mediated by cross checking
|
||||
* link onlineness and classification result later.
|
||||
*/
|
||||
if (postreset)
|
||||
postreset(link, classes);
|
||||
|
||||
/* clear cached SError */
|
||||
spin_lock_irqsave(link->ap->lock, flags);
|
||||
link->eh_info.serror = 0;
|
||||
spin_unlock_irqrestore(link->ap->lock, flags);
|
||||
|
||||
/* Make sure onlineness and classification result correspond.
|
||||
* Hotplug could have happened during reset and some
|
||||
* controllers fail to wait while a drive is spinning up after
|
||||
* being hotplugged causing misdetection. By cross checking
|
||||
* link onlineness and classification result, those conditions
|
||||
* can be reliably detected and retried.
|
||||
*/
|
||||
nr_known = 0;
|
||||
ata_link_for_each_dev(dev, link) {
|
||||
/* convert all ATA_DEV_UNKNOWN to ATA_DEV_NONE */
|
||||
if (classes[dev->devno] == ATA_DEV_UNKNOWN)
|
||||
classes[dev->devno] = ATA_DEV_NONE;
|
||||
else
|
||||
nr_known++;
|
||||
}
|
||||
|
||||
if (classify && !nr_known && ata_link_online(link)) {
|
||||
if (try < max_tries) {
|
||||
ata_link_printk(link, KERN_WARNING, "link online but "
|
||||
"device misclassified, retrying\n");
|
||||
rc = -EAGAIN;
|
||||
goto fail;
|
||||
}
|
||||
ata_link_printk(link, KERN_WARNING,
|
||||
"link online but device misclassified, "
|
||||
"device detection might fail\n");
|
||||
}
|
||||
|
||||
/* reset successful, schedule revalidation */
|
||||
ata_eh_done(link, NULL, ATA_EH_RESET);
|
||||
ehc->i.action |= ATA_EH_REVALIDATE;
|
||||
@@ -2587,7 +2623,7 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
||||
struct ata_link *link;
|
||||
struct ata_device *dev;
|
||||
int nr_failed_devs, nr_disabled_devs;
|
||||
int reset, rc;
|
||||
int rc;
|
||||
unsigned long flags;
|
||||
|
||||
DPRINTK("ENTER\n");
|
||||
@@ -2630,7 +2666,6 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
||||
rc = 0;
|
||||
nr_failed_devs = 0;
|
||||
nr_disabled_devs = 0;
|
||||
reset = 0;
|
||||
|
||||
/* if UNLOADING, finish immediately */
|
||||
if (ap->pflags & ATA_PFLAG_UNLOADING)
|
||||
@@ -2644,40 +2679,24 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
|
||||
if (ata_eh_skip_recovery(link))
|
||||
ehc->i.action = 0;
|
||||
|
||||
/* do we need to reset? */
|
||||
if (ehc->i.action & ATA_EH_RESET)
|
||||
reset = 1;
|
||||
|
||||
ata_link_for_each_dev(dev, link)
|
||||
ehc->classes[dev->devno] = ATA_DEV_UNKNOWN;
|
||||
}
|
||||
|
||||
/* reset */
|
||||
if (reset) {
|
||||
/* if PMP is attached, this function only deals with
|
||||
* downstream links, port should stay thawed.
|
||||
*/
|
||||
if (!sata_pmp_attached(ap))
|
||||
ata_eh_freeze_port(ap);
|
||||
ata_port_for_each_link(link, ap) {
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
|
||||
ata_port_for_each_link(link, ap) {
|
||||
struct ata_eh_context *ehc = &link->eh_context;
|
||||
if (!(ehc->i.action & ATA_EH_RESET))
|
||||
continue;
|
||||
|
||||
if (!(ehc->i.action & ATA_EH_RESET))
|
||||
continue;
|
||||
|
||||
rc = ata_eh_reset(link, ata_link_nr_vacant(link),
|
||||
prereset, softreset, hardreset,
|
||||
postreset);
|
||||
if (rc) {
|
||||
ata_link_printk(link, KERN_ERR,
|
||||
"reset failed, giving up\n");
|
||||
goto out;
|
||||
}
|
||||
rc = ata_eh_reset(link, ata_link_nr_vacant(link),
|
||||
prereset, softreset, hardreset, postreset);
|
||||
if (rc) {
|
||||
ata_link_printk(link, KERN_ERR,
|
||||
"reset failed, giving up\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!sata_pmp_attached(ap))
|
||||
ata_eh_thaw_port(ap);
|
||||
}
|
||||
|
||||
/* the rest */
|
||||
|
||||
+27
-24
@@ -48,7 +48,7 @@ static unsigned int sata_pmp_read(struct ata_link *link, int reg, u32 *r_val)
|
||||
tf.device = link->pmp;
|
||||
|
||||
err_mask = ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0,
|
||||
SATA_PMP_SCR_TIMEOUT);
|
||||
SATA_PMP_RW_TIMEOUT);
|
||||
if (err_mask)
|
||||
return err_mask;
|
||||
|
||||
@@ -88,7 +88,7 @@ static unsigned int sata_pmp_write(struct ata_link *link, int reg, u32 val)
|
||||
tf.lbah = (val >> 24) & 0xff;
|
||||
|
||||
return ata_exec_internal(pmp_dev, &tf, NULL, DMA_NONE, NULL, 0,
|
||||
SATA_PMP_SCR_TIMEOUT);
|
||||
SATA_PMP_RW_TIMEOUT);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -257,19 +257,6 @@ static int sata_pmp_configure(struct ata_device *dev, int print_info)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* turn off notification till fan-out ports are reset and configured */
|
||||
if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) {
|
||||
gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY;
|
||||
|
||||
err_mask = sata_pmp_write(dev->link, SATA_PMP_GSCR_FEAT_EN,
|
||||
gscr[SATA_PMP_GSCR_FEAT_EN]);
|
||||
if (err_mask) {
|
||||
rc = -EIO;
|
||||
reason = "failed to write GSCR_FEAT_EN";
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
|
||||
if (print_info) {
|
||||
ata_dev_printk(dev, KERN_INFO, "Port Multiplier %s, "
|
||||
"0x%04x:0x%04x r%d, %d ports, feat 0x%x/0x%x\n",
|
||||
@@ -335,9 +322,12 @@ static void sata_pmp_quirks(struct ata_port *ap)
|
||||
if (vendor == 0x1095 && devid == 0x3726) {
|
||||
/* sil3726 quirks */
|
||||
ata_port_for_each_link(link, ap) {
|
||||
/* class code report is unreliable */
|
||||
/* Class code report is unreliable and SRST
|
||||
* times out under certain configurations.
|
||||
*/
|
||||
if (link->pmp < 5)
|
||||
link->flags |= ATA_LFLAG_ASSUME_ATA;
|
||||
link->flags |= ATA_LFLAG_NO_SRST |
|
||||
ATA_LFLAG_ASSUME_ATA;
|
||||
|
||||
/* port 5 is for SEMB device and it doesn't like SRST */
|
||||
if (link->pmp == 5)
|
||||
@@ -700,8 +690,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
|
||||
if (ehc->i.action & ATA_EH_RESET) {
|
||||
struct ata_link *tlink;
|
||||
|
||||
ata_eh_freeze_port(ap);
|
||||
|
||||
/* reset */
|
||||
rc = ata_eh_reset(link, 0, prereset, softreset, hardreset,
|
||||
postreset);
|
||||
@@ -711,8 +699,6 @@ static int sata_pmp_eh_recover_pmp(struct ata_port *ap,
|
||||
goto fail;
|
||||
}
|
||||
|
||||
ata_eh_thaw_port(ap);
|
||||
|
||||
/* PMP is reset, SErrors cannot be trusted, scan all */
|
||||
ata_port_for_each_link(tlink, ap) {
|
||||
struct ata_eh_context *ehc = &tlink->eh_context;
|
||||
@@ -864,6 +850,7 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
|
||||
struct ata_link *pmp_link = &ap->link;
|
||||
struct ata_device *pmp_dev = pmp_link->device;
|
||||
struct ata_eh_context *pmp_ehc = &pmp_link->eh_context;
|
||||
u32 *gscr = pmp_dev->gscr;
|
||||
struct ata_link *link;
|
||||
struct ata_device *dev;
|
||||
unsigned int err_mask;
|
||||
@@ -901,6 +888,22 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
|
||||
if (rc)
|
||||
goto pmp_fail;
|
||||
|
||||
/* PHY event notification can disturb reset and other recovery
|
||||
* operations. Turn it off.
|
||||
*/
|
||||
if (gscr[SATA_PMP_GSCR_FEAT_EN] & SATA_PMP_FEAT_NOTIFY) {
|
||||
gscr[SATA_PMP_GSCR_FEAT_EN] &= ~SATA_PMP_FEAT_NOTIFY;
|
||||
|
||||
err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
|
||||
gscr[SATA_PMP_GSCR_FEAT_EN]);
|
||||
if (err_mask) {
|
||||
ata_link_printk(pmp_link, KERN_WARNING,
|
||||
"failed to disable NOTIFY (err_mask=0x%x)\n",
|
||||
err_mask);
|
||||
goto pmp_fail;
|
||||
}
|
||||
}
|
||||
|
||||
/* handle disabled links */
|
||||
rc = sata_pmp_eh_handle_disabled_links(ap);
|
||||
if (rc)
|
||||
@@ -923,10 +926,10 @@ static int sata_pmp_eh_recover(struct ata_port *ap)
|
||||
|
||||
/* enable notification */
|
||||
if (pmp_dev->flags & ATA_DFLAG_AN) {
|
||||
pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;
|
||||
gscr[SATA_PMP_GSCR_FEAT_EN] |= SATA_PMP_FEAT_NOTIFY;
|
||||
|
||||
err_mask = sata_pmp_write(pmp_dev->link, SATA_PMP_GSCR_FEAT_EN,
|
||||
pmp_dev->gscr[SATA_PMP_GSCR_FEAT_EN]);
|
||||
err_mask = sata_pmp_write(pmp_link, SATA_PMP_GSCR_FEAT_EN,
|
||||
gscr[SATA_PMP_GSCR_FEAT_EN]);
|
||||
if (err_mask) {
|
||||
ata_dev_printk(pmp_dev, KERN_ERR, "failed to write "
|
||||
"PMP_FEAT_EN (Emask=0x%x)\n", err_mask);
|
||||
|
||||
@@ -1082,12 +1082,6 @@ static unsigned int ata_scsi_start_stop_xlat(struct ata_queued_cmd *qc)
|
||||
if (((cdb[4] >> 4) & 0xf) != 0)
|
||||
goto invalid_fld; /* power conditions not supported */
|
||||
|
||||
if (qc->dev->horkage & ATA_HORKAGE_SKIP_PM) {
|
||||
/* the device lacks PM support, finish without doing anything */
|
||||
scmd->result = SAM_STAT_GOOD;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (cdb[4] & 0x1) {
|
||||
tf->nsect = 1; /* 1 sector, lba=0 */
|
||||
|
||||
@@ -1643,6 +1637,7 @@ defer:
|
||||
|
||||
/**
|
||||
* ata_scsi_rbuf_get - Map response buffer.
|
||||
* @cmd: SCSI command containing buffer to be mapped.
|
||||
* @flags: unsigned long variable to store irq enable status
|
||||
* @copy_in: copy in from user buffer
|
||||
*
|
||||
@@ -1960,7 +1955,7 @@ static unsigned int ata_msense_ctl_mode(u8 *buf)
|
||||
|
||||
/**
|
||||
* ata_msense_rw_recovery - Simulate MODE SENSE r/w error recovery page
|
||||
* @bufp: output buffer
|
||||
* @buf: output buffer
|
||||
*
|
||||
* Generate a generic MODE SENSE r/w error recovery page.
|
||||
*
|
||||
|
||||
@@ -177,11 +177,11 @@ static void ali_program_modes(struct ata_port *ap, struct ata_device *adev, stru
|
||||
u8 udma;
|
||||
|
||||
if (t != NULL) {
|
||||
t->setup = FIT(t->setup, 1, 8) & 7;
|
||||
t->act8b = FIT(t->act8b, 1, 8) & 7;
|
||||
t->rec8b = FIT(t->rec8b, 1, 16) & 15;
|
||||
t->active = FIT(t->active, 1, 8) & 7;
|
||||
t->recover = FIT(t->recover, 1, 16) & 15;
|
||||
t->setup = clamp_val(t->setup, 1, 8) & 7;
|
||||
t->act8b = clamp_val(t->act8b, 1, 8) & 7;
|
||||
t->rec8b = clamp_val(t->rec8b, 1, 16) & 15;
|
||||
t->active = clamp_val(t->active, 1, 8) & 7;
|
||||
t->recover = clamp_val(t->recover, 1, 16) & 15;
|
||||
|
||||
pci_write_config_byte(pdev, cas, t->setup);
|
||||
pci_write_config_byte(pdev, cbt, (t->act8b << 4) | t->rec8b);
|
||||
|
||||
@@ -84,32 +84,32 @@ static void timing_setup(struct ata_port *ap, struct ata_device *adev, int offse
|
||||
|
||||
/* Configure the address set up timing */
|
||||
pci_read_config_byte(pdev, offset + 0x0C, &t);
|
||||
t = (t & ~(3 << ((3 - dn) << 1))) | ((FIT(at.setup, 1, 4) - 1) << ((3 - dn) << 1));
|
||||
t = (t & ~(3 << ((3 - dn) << 1))) | ((clamp_val(at.setup, 1, 4) - 1) << ((3 - dn) << 1));
|
||||
pci_write_config_byte(pdev, offset + 0x0C , t);
|
||||
|
||||
/* Configure the 8bit I/O timing */
|
||||
pci_write_config_byte(pdev, offset + 0x0E + (1 - (dn >> 1)),
|
||||
((FIT(at.act8b, 1, 16) - 1) << 4) | (FIT(at.rec8b, 1, 16) - 1));
|
||||
((clamp_val(at.act8b, 1, 16) - 1) << 4) | (clamp_val(at.rec8b, 1, 16) - 1));
|
||||
|
||||
/* Drive timing */
|
||||
pci_write_config_byte(pdev, offset + 0x08 + (3 - dn),
|
||||
((FIT(at.active, 1, 16) - 1) << 4) | (FIT(at.recover, 1, 16) - 1));
|
||||
((clamp_val(at.active, 1, 16) - 1) << 4) | (clamp_val(at.recover, 1, 16) - 1));
|
||||
|
||||
switch (clock) {
|
||||
case 1:
|
||||
t = at.udma ? (0xc0 | (FIT(at.udma, 2, 5) - 2)) : 0x03;
|
||||
t = at.udma ? (0xc0 | (clamp_val(at.udma, 2, 5) - 2)) : 0x03;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 2, 10)]) : 0x03;
|
||||
t = at.udma ? (0xc0 | amd_cyc2udma[clamp_val(at.udma, 2, 10)]) : 0x03;
|
||||
break;
|
||||
|
||||
case 3:
|
||||
t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 10)]) : 0x03;
|
||||
t = at.udma ? (0xc0 | amd_cyc2udma[clamp_val(at.udma, 1, 10)]) : 0x03;
|
||||
break;
|
||||
|
||||
case 4:
|
||||
t = at.udma ? (0xc0 | amd_cyc2udma[FIT(at.udma, 1, 15)]) : 0x03;
|
||||
t = at.udma ? (0xc0 | amd_cyc2udma[clamp_val(at.udma, 1, 15)]) : 0x03;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
@@ -291,8 +291,6 @@ static int __init pata_at32_probe(struct platform_device *pdev)
|
||||
if (!info)
|
||||
return -ENOMEM;
|
||||
|
||||
memset(info, 0, sizeof(struct at32_ide_info));
|
||||
|
||||
info->irq = irq;
|
||||
info->cs = board->cs;
|
||||
|
||||
|
||||
@@ -911,7 +911,10 @@ static void bfin_bmdma_start(struct ata_queued_cmd *qc)
|
||||
/* Reset all transfer count */
|
||||
ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | TFRCNT_RST);
|
||||
|
||||
/* Set transfer length to buffer len */
|
||||
/* Set ATAPI state machine contorl in terminate sequence */
|
||||
ATAPI_SET_CONTROL(base, ATAPI_GET_CONTROL(base) | END_ON_TERM);
|
||||
|
||||
/* Set transfer length to buffer len */
|
||||
for_each_sg(qc->sg, sg, qc->n_elem, si) {
|
||||
ATAPI_SET_XFER_LEN(base, (sg_dma_len(sg) >> 1));
|
||||
}
|
||||
|
||||
@@ -62,14 +62,14 @@ static void cy82c693_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
return;
|
||||
}
|
||||
|
||||
time_16 = FIT(t.recover, 0, 15) | (FIT(t.active, 0, 15) << 4);
|
||||
time_8 = FIT(t.act8b, 0, 15) | (FIT(t.rec8b, 0, 15) << 4);
|
||||
time_16 = clamp_val(t.recover, 0, 15) | (clamp_val(t.active, 0, 15) << 4);
|
||||
time_8 = clamp_val(t.act8b, 0, 15) | (clamp_val(t.rec8b, 0, 15) << 4);
|
||||
|
||||
if (adev->devno == 0) {
|
||||
pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr);
|
||||
|
||||
addr &= ~0x0F; /* Mask bits */
|
||||
addr |= FIT(t.setup, 0, 15);
|
||||
addr |= clamp_val(t.setup, 0, 15);
|
||||
|
||||
pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr);
|
||||
pci_write_config_byte(pdev, CY82_IDE_MASTER_IOR, time_16);
|
||||
@@ -79,7 +79,7 @@ static void cy82c693_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
pci_read_config_dword(pdev, CY82_IDE_ADDRSETUP, &addr);
|
||||
|
||||
addr &= ~0xF0; /* Mask bits */
|
||||
addr |= (FIT(t.setup, 0, 15) << 4);
|
||||
addr |= (clamp_val(t.setup, 0, 15) << 4);
|
||||
|
||||
pci_write_config_dword(pdev, CY82_IDE_ADDRSETUP, addr);
|
||||
pci_write_config_byte(pdev, CY82_IDE_SLAVE_IOR, time_16);
|
||||
|
||||
+25
-25
@@ -343,8 +343,8 @@ static void ht6560a_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
/* Get the timing data in cycles. For now play safe at 50Mhz */
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
|
||||
|
||||
active = FIT(t.active, 2, 15);
|
||||
recover = FIT(t.recover, 4, 15);
|
||||
active = clamp_val(t.active, 2, 15);
|
||||
recover = clamp_val(t.recover, 4, 15);
|
||||
|
||||
inb(0x3E6);
|
||||
inb(0x3E6);
|
||||
@@ -377,8 +377,8 @@ static void ht6560b_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
/* Get the timing data in cycles. For now play safe at 50Mhz */
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 20000, 1000);
|
||||
|
||||
active = FIT(t.active, 2, 15);
|
||||
recover = FIT(t.recover, 2, 16);
|
||||
active = clamp_val(t.active, 2, 15);
|
||||
recover = clamp_val(t.recover, 2, 16);
|
||||
recover &= 0x15;
|
||||
|
||||
inb(0x3E6);
|
||||
@@ -462,9 +462,9 @@ static void opti82c611a_set_piomode(struct ata_port *ap,
|
||||
ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
|
||||
}
|
||||
|
||||
active = FIT(t.active, 2, 17) - 2;
|
||||
recover = FIT(t.recover, 1, 16) - 1;
|
||||
setup = FIT(t.setup, 1, 4) - 1;
|
||||
active = clamp_val(t.active, 2, 17) - 2;
|
||||
recover = clamp_val(t.recover, 1, 16) - 1;
|
||||
setup = clamp_val(t.setup, 1, 4) - 1;
|
||||
|
||||
/* Select the right timing bank for write timing */
|
||||
rc = ioread8(ap->ioaddr.lbal_addr);
|
||||
@@ -541,9 +541,9 @@ static void opti82c46x_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
ata_timing_merge(&t, &tp, &t, ATA_TIMING_SETUP);
|
||||
}
|
||||
|
||||
active = FIT(t.active, 2, 17) - 2;
|
||||
recover = FIT(t.recover, 1, 16) - 1;
|
||||
setup = FIT(t.setup, 1, 4) - 1;
|
||||
active = clamp_val(t.active, 2, 17) - 2;
|
||||
recover = clamp_val(t.recover, 1, 16) - 1;
|
||||
setup = clamp_val(t.setup, 1, 4) - 1;
|
||||
|
||||
/* Select the right timing bank for write timing */
|
||||
rc = ioread8(ap->ioaddr.lbal_addr);
|
||||
@@ -624,11 +624,11 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
if (ld_qdi->fast) {
|
||||
active = 8 - FIT(t.active, 1, 8);
|
||||
recovery = 18 - FIT(t.recover, 3, 18);
|
||||
active = 8 - clamp_val(t.active, 1, 8);
|
||||
recovery = 18 - clamp_val(t.recover, 3, 18);
|
||||
} else {
|
||||
active = 9 - FIT(t.active, 2, 9);
|
||||
recovery = 15 - FIT(t.recover, 0, 15);
|
||||
active = 9 - clamp_val(t.active, 2, 9);
|
||||
recovery = 15 - clamp_val(t.recover, 0, 15);
|
||||
}
|
||||
timing = (recovery << 4) | active | 0x08;
|
||||
|
||||
@@ -658,11 +658,11 @@ static void qdi6580dp_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
if (ld_qdi->fast) {
|
||||
active = 8 - FIT(t.active, 1, 8);
|
||||
recovery = 18 - FIT(t.recover, 3, 18);
|
||||
active = 8 - clamp_val(t.active, 1, 8);
|
||||
recovery = 18 - clamp_val(t.recover, 3, 18);
|
||||
} else {
|
||||
active = 9 - FIT(t.active, 2, 9);
|
||||
recovery = 15 - FIT(t.recover, 0, 15);
|
||||
active = 9 - clamp_val(t.active, 2, 9);
|
||||
recovery = 15 - clamp_val(t.recover, 0, 15);
|
||||
}
|
||||
timing = (recovery << 4) | active | 0x08;
|
||||
|
||||
@@ -695,11 +695,11 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
if (ld_qdi->fast) {
|
||||
active = 8 - FIT(t.active, 1, 8);
|
||||
recovery = 18 - FIT(t.recover, 3, 18);
|
||||
active = 8 - clamp_val(t.active, 1, 8);
|
||||
recovery = 18 - clamp_val(t.recover, 3, 18);
|
||||
} else {
|
||||
active = 9 - FIT(t.active, 2, 9);
|
||||
recovery = 15 - FIT(t.recover, 0, 15);
|
||||
active = 9 - clamp_val(t.active, 2, 9);
|
||||
recovery = 15 - clamp_val(t.recover, 0, 15);
|
||||
}
|
||||
timing = (recovery << 4) | active | 0x08;
|
||||
ld_qdi->clock[adev->devno] = timing;
|
||||
@@ -830,8 +830,8 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
else
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
active = (FIT(t.active, 3, 17) - 1) & 0x0F;
|
||||
recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
|
||||
active = (clamp_val(t.active, 3, 17) - 1) & 0x0F;
|
||||
recovery = (clamp_val(t.recover, 1, 15) + 1) & 0x0F;
|
||||
timing = (active << 4) | recovery;
|
||||
winbond_writecfg(ld_winbond->timing, timing, reg);
|
||||
|
||||
@@ -842,7 +842,7 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
reg |= 0x08; /* FIFO off */
|
||||
if (!ata_pio_need_iordy(adev))
|
||||
reg |= 0x02; /* IORDY off */
|
||||
reg |= (FIT(t.setup, 0, 3) << 6);
|
||||
reg |= (clamp_val(t.setup, 0, 3) << 6);
|
||||
winbond_writecfg(ld_winbond->timing, timing + 1, reg);
|
||||
}
|
||||
|
||||
|
||||
@@ -91,9 +91,9 @@ static void ns87410_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
return;
|
||||
}
|
||||
|
||||
at.active = FIT(at.active, 2, 16) - 2;
|
||||
at.setup = FIT(at.setup, 1, 4) - 1;
|
||||
at.recover = FIT(at.recover, 1, 12) - 1;
|
||||
at.active = clamp_val(at.active, 2, 16) - 2;
|
||||
at.setup = clamp_val(at.setup, 1, 4) - 1;
|
||||
at.recover = clamp_val(at.recover, 1, 12) - 1;
|
||||
|
||||
idetcr = (at.setup << 6) | (recoverbits[at.recover] << 3) | activebits[at.active];
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@ static void ns87415_set_mode(struct ata_port *ap, struct ata_device *adev, u8 mo
|
||||
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, T, 0);
|
||||
|
||||
clocking = 17 - FIT(t.active, 2, 17);
|
||||
clocking |= (16 - FIT(t.recover, 1, 16)) << 4;
|
||||
clocking = 17 - clamp_val(t.active, 2, 17);
|
||||
clocking |= (16 - clamp_val(t.recover, 1, 16)) << 4;
|
||||
/* Use the same timing for read and write bytes */
|
||||
clocking |= (clocking << 8);
|
||||
pci_write_config_word(dev, timing, clocking);
|
||||
|
||||
@@ -60,11 +60,11 @@ static void qdi6500_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
if (qdi->fast) {
|
||||
active = 8 - FIT(t.active, 1, 8);
|
||||
recovery = 18 - FIT(t.recover, 3, 18);
|
||||
active = 8 - clamp_val(t.active, 1, 8);
|
||||
recovery = 18 - clamp_val(t.recover, 3, 18);
|
||||
} else {
|
||||
active = 9 - FIT(t.active, 2, 9);
|
||||
recovery = 15 - FIT(t.recover, 0, 15);
|
||||
active = 9 - clamp_val(t.active, 2, 9);
|
||||
recovery = 15 - clamp_val(t.recover, 0, 15);
|
||||
}
|
||||
timing = (recovery << 4) | active | 0x08;
|
||||
|
||||
@@ -84,11 +84,11 @@ static void qdi6580_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
if (qdi->fast) {
|
||||
active = 8 - FIT(t.active, 1, 8);
|
||||
recovery = 18 - FIT(t.recover, 3, 18);
|
||||
active = 8 - clamp_val(t.active, 1, 8);
|
||||
recovery = 18 - clamp_val(t.recover, 3, 18);
|
||||
} else {
|
||||
active = 9 - FIT(t.active, 2, 9);
|
||||
recovery = 15 - FIT(t.recover, 0, 15);
|
||||
active = 9 - clamp_val(t.active, 2, 9);
|
||||
recovery = 15 - clamp_val(t.recover, 0, 15);
|
||||
}
|
||||
timing = (recovery << 4) | active | 0x08;
|
||||
|
||||
|
||||
@@ -216,7 +216,7 @@ static int sl82c105_qc_defer(struct ata_queued_cmd *qc)
|
||||
struct ata_port *alt = host->ports[1 ^ qc->ap->port_no];
|
||||
int rc;
|
||||
|
||||
/* First apply the usual rules */
|
||||
/* First apply the usual rules */
|
||||
rc = ata_std_qc_defer(qc);
|
||||
if (rc != 0)
|
||||
return rc;
|
||||
|
||||
@@ -259,15 +259,15 @@ static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mo
|
||||
|
||||
pci_read_config_byte(pdev, 0x4C, &setup);
|
||||
setup &= ~(3 << shift);
|
||||
setup |= FIT(t.setup, 1, 4) << shift; /* 1,4 or 1,4 - 1 FIXME */
|
||||
setup |= clamp_val(t.setup, 1, 4) << shift; /* 1,4 or 1,4 - 1 FIXME */
|
||||
pci_write_config_byte(pdev, 0x4C, setup);
|
||||
}
|
||||
|
||||
/* Load the PIO mode bits */
|
||||
pci_write_config_byte(pdev, 0x4F - ap->port_no,
|
||||
((FIT(t.act8b, 1, 16) - 1) << 4) | (FIT(t.rec8b, 1, 16) - 1));
|
||||
((clamp_val(t.act8b, 1, 16) - 1) << 4) | (clamp_val(t.rec8b, 1, 16) - 1));
|
||||
pci_write_config_byte(pdev, 0x48 + offset,
|
||||
((FIT(t.active, 1, 16) - 1) << 4) | (FIT(t.recover, 1, 16) - 1));
|
||||
((clamp_val(t.active, 1, 16) - 1) << 4) | (clamp_val(t.recover, 1, 16) - 1));
|
||||
|
||||
/* Load the UDMA bits according to type */
|
||||
switch(udma_type) {
|
||||
@@ -275,16 +275,16 @@ static void via_do_set_mode(struct ata_port *ap, struct ata_device *adev, int mo
|
||||
/* BUG() ? */
|
||||
/* fall through */
|
||||
case 33:
|
||||
ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 5) - 2)) : 0x03;
|
||||
ut = t.udma ? (0xe0 | (clamp_val(t.udma, 2, 5) - 2)) : 0x03;
|
||||
break;
|
||||
case 66:
|
||||
ut = t.udma ? (0xe8 | (FIT(t.udma, 2, 9) - 2)) : 0x0f;
|
||||
ut = t.udma ? (0xe8 | (clamp_val(t.udma, 2, 9) - 2)) : 0x0f;
|
||||
break;
|
||||
case 100:
|
||||
ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07;
|
||||
ut = t.udma ? (0xe0 | (clamp_val(t.udma, 2, 9) - 2)) : 0x07;
|
||||
break;
|
||||
case 133:
|
||||
ut = t.udma ? (0xe0 | (FIT(t.udma, 2, 9) - 2)) : 0x07;
|
||||
ut = t.udma ? (0xe0 | (clamp_val(t.udma, 2, 9) - 2)) : 0x07;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -75,8 +75,8 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
else
|
||||
ata_timing_compute(adev, adev->pio_mode, &t, 30303, 1000);
|
||||
|
||||
active = (FIT(t.active, 3, 17) - 1) & 0x0F;
|
||||
recovery = (FIT(t.recover, 1, 15) + 1) & 0x0F;
|
||||
active = (clamp_val(t.active, 3, 17) - 1) & 0x0F;
|
||||
recovery = (clamp_val(t.recover, 1, 15) + 1) & 0x0F;
|
||||
timing = (active << 4) | recovery;
|
||||
winbond_writecfg(winbond->config, timing, reg);
|
||||
|
||||
@@ -87,7 +87,7 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
|
||||
reg |= 0x08; /* FIFO off */
|
||||
if (!ata_pio_need_iordy(adev))
|
||||
reg |= 0x02; /* IORDY off */
|
||||
reg |= (FIT(t.setup, 0, 3) << 6);
|
||||
reg |= (clamp_val(t.setup, 0, 3) << 6);
|
||||
winbond_writecfg(winbond->config, timing + 1, reg);
|
||||
}
|
||||
|
||||
|
||||
+160
-58
@@ -34,7 +34,7 @@ enum {
|
||||
|
||||
SATA_FSL_HOST_FLAGS = (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
|
||||
ATA_FLAG_NCQ),
|
||||
ATA_FLAG_PMP | ATA_FLAG_NCQ),
|
||||
|
||||
SATA_FSL_MAX_CMDS = SATA_FSL_QUEUE_DEPTH,
|
||||
SATA_FSL_CMD_HDR_SIZE = 16, /* 4 DWORDS */
|
||||
@@ -395,7 +395,7 @@ static void sata_fsl_qc_prep(struct ata_queued_cmd *qc)
|
||||
cd = (struct command_desc *)pp->cmdentry + tag;
|
||||
cd_paddr = pp->cmdentry_paddr + tag * SATA_FSL_CMD_DESC_SIZE;
|
||||
|
||||
ata_tf_to_fis(&qc->tf, 0, 1, (u8 *) &cd->cfis);
|
||||
ata_tf_to_fis(&qc->tf, qc->dev->link->pmp, 1, (u8 *) &cd->cfis);
|
||||
|
||||
VPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x\n",
|
||||
cd->cfis[0], cd->cfis[1], cd->cfis[2]);
|
||||
@@ -438,6 +438,8 @@ static unsigned int sata_fsl_qc_issue(struct ata_queued_cmd *qc)
|
||||
ioread32(CA + hcr_base),
|
||||
ioread32(CE + hcr_base), ioread32(CC + hcr_base));
|
||||
|
||||
iowrite32(qc->dev->link->pmp, CQPMP + hcr_base);
|
||||
|
||||
/* Simply queue command to the controller/device */
|
||||
iowrite32(1 << tag, CQ + hcr_base);
|
||||
|
||||
@@ -558,11 +560,36 @@ static void sata_fsl_thaw(struct ata_port *ap)
|
||||
ioread32(hcr_base + HCONTROL), ioread32(hcr_base + HSTATUS));
|
||||
}
|
||||
|
||||
static void sata_fsl_pmp_attach(struct ata_port *ap)
|
||||
{
|
||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||
void __iomem *hcr_base = host_priv->hcr_base;
|
||||
u32 temp;
|
||||
|
||||
temp = ioread32(hcr_base + HCONTROL);
|
||||
iowrite32((temp | HCONTROL_PMP_ATTACHED), hcr_base + HCONTROL);
|
||||
}
|
||||
|
||||
static void sata_fsl_pmp_detach(struct ata_port *ap)
|
||||
{
|
||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||
void __iomem *hcr_base = host_priv->hcr_base;
|
||||
u32 temp;
|
||||
|
||||
temp = ioread32(hcr_base + HCONTROL);
|
||||
temp &= ~HCONTROL_PMP_ATTACHED;
|
||||
iowrite32(temp, hcr_base + HCONTROL);
|
||||
|
||||
/* enable interrupts on the controller/port */
|
||||
temp = ioread32(hcr_base + HCONTROL);
|
||||
iowrite32((temp | DEFAULT_PORT_IRQ_ENABLE_MASK), hcr_base + HCONTROL);
|
||||
|
||||
}
|
||||
|
||||
static int sata_fsl_port_start(struct ata_port *ap)
|
||||
{
|
||||
struct device *dev = ap->host->dev;
|
||||
struct sata_fsl_port_priv *pp;
|
||||
int retval;
|
||||
void *mem;
|
||||
dma_addr_t mem_dma;
|
||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||
@@ -688,12 +715,13 @@ static int sata_fsl_prereset(struct ata_link *link, unsigned long deadline)
|
||||
}
|
||||
|
||||
static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||
unsigned long deadline)
|
||||
unsigned long deadline)
|
||||
{
|
||||
struct ata_port *ap = link->ap;
|
||||
struct sata_fsl_port_priv *pp = ap->private_data;
|
||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||
void __iomem *hcr_base = host_priv->hcr_base;
|
||||
int pmp = sata_srst_pmp(link);
|
||||
u32 temp;
|
||||
struct ata_taskfile tf;
|
||||
u8 *cfis;
|
||||
@@ -703,6 +731,9 @@ static int sata_fsl_softreset(struct ata_link *link, unsigned int *class,
|
||||
|
||||
DPRINTK("in xx_softreset\n");
|
||||
|
||||
if (pmp != SATA_PMP_CTRL_PORT)
|
||||
goto issue_srst;
|
||||
|
||||
try_offline_again:
|
||||
/*
|
||||
* Force host controller to go off-line, aborting current operations
|
||||
@@ -746,6 +777,7 @@ try_offline_again:
|
||||
|
||||
temp = ioread32(hcr_base + HCONTROL);
|
||||
temp |= (HCONTROL_ONLINE_PHY_RST | HCONTROL_SNOOP_ENABLE);
|
||||
temp |= HCONTROL_PMP_ATTACHED;
|
||||
iowrite32(temp, hcr_base + HCONTROL);
|
||||
|
||||
temp = ata_wait_register(hcr_base + HSTATUS, ONLINE, 0, 1, 500);
|
||||
@@ -771,7 +803,8 @@ try_offline_again:
|
||||
ata_port_printk(ap, KERN_WARNING,
|
||||
"No Device OR PHYRDY change,Hstatus = 0x%x\n",
|
||||
ioread32(hcr_base + HSTATUS));
|
||||
goto err;
|
||||
*class = ATA_DEV_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -783,7 +816,8 @@ try_offline_again:
|
||||
|
||||
if ((temp & 0xFF) != 0x18) {
|
||||
ata_port_printk(ap, KERN_WARNING, "No Signature Update\n");
|
||||
goto err;
|
||||
*class = ATA_DEV_NONE;
|
||||
goto out;
|
||||
} else {
|
||||
ata_port_printk(ap, KERN_INFO,
|
||||
"Signature Update detected @ %d msecs\n",
|
||||
@@ -798,6 +832,7 @@ try_offline_again:
|
||||
* reached here, we can send a command to the target device
|
||||
*/
|
||||
|
||||
issue_srst:
|
||||
DPRINTK("Sending SRST/device reset\n");
|
||||
|
||||
ata_tf_init(link->device, &tf);
|
||||
@@ -808,7 +843,7 @@ try_offline_again:
|
||||
SRST_CMD | CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
|
||||
|
||||
tf.ctl |= ATA_SRST; /* setup SRST bit in taskfile control reg */
|
||||
ata_tf_to_fis(&tf, 0, 0, cfis);
|
||||
ata_tf_to_fis(&tf, pmp, 0, cfis);
|
||||
|
||||
DPRINTK("Dumping cfis : 0x%x, 0x%x, 0x%x, 0x%x\n",
|
||||
cfis[0], cfis[1], cfis[2], cfis[3]);
|
||||
@@ -854,8 +889,10 @@ try_offline_again:
|
||||
sata_fsl_setup_cmd_hdr_entry(pp, 0, CMD_DESC_SNOOP_ENABLE, 0, 0, 5);
|
||||
|
||||
tf.ctl &= ~ATA_SRST; /* 2nd H2D Ctl. register FIS */
|
||||
ata_tf_to_fis(&tf, 0, 0, cfis);
|
||||
ata_tf_to_fis(&tf, pmp, 0, cfis);
|
||||
|
||||
if (pmp != SATA_PMP_CTRL_PORT)
|
||||
iowrite32(pmp, CQPMP + hcr_base);
|
||||
iowrite32(1, CQ + hcr_base);
|
||||
msleep(150); /* ?? */
|
||||
|
||||
@@ -886,12 +923,21 @@ try_offline_again:
|
||||
VPRINTK("cereg = 0x%x\n", ioread32(hcr_base + CE));
|
||||
}
|
||||
|
||||
out:
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
static void sata_fsl_error_handler(struct ata_port *ap)
|
||||
{
|
||||
|
||||
DPRINTK("in xx_error_handler\n");
|
||||
sata_pmp_error_handler(ap);
|
||||
|
||||
}
|
||||
|
||||
static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
|
||||
{
|
||||
if (qc->flags & ATA_QCFLAG_FAILED)
|
||||
@@ -905,18 +951,21 @@ static void sata_fsl_post_internal_cmd(struct ata_queued_cmd *qc)
|
||||
|
||||
static void sata_fsl_error_intr(struct ata_port *ap)
|
||||
{
|
||||
struct ata_link *link = &ap->link;
|
||||
struct ata_eh_info *ehi = &link->eh_info;
|
||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||
void __iomem *hcr_base = host_priv->hcr_base;
|
||||
u32 hstatus, dereg, cereg = 0, SError = 0;
|
||||
u32 hstatus, dereg=0, cereg = 0, SError = 0;
|
||||
unsigned int err_mask = 0, action = 0;
|
||||
struct ata_queued_cmd *qc;
|
||||
int freeze = 0;
|
||||
int freeze = 0, abort=0;
|
||||
struct ata_link *link = NULL;
|
||||
struct ata_queued_cmd *qc = NULL;
|
||||
struct ata_eh_info *ehi;
|
||||
|
||||
hstatus = ioread32(hcr_base + HSTATUS);
|
||||
cereg = ioread32(hcr_base + CE);
|
||||
|
||||
/* first, analyze and record host port events */
|
||||
link = &ap->link;
|
||||
ehi = &link->eh_info;
|
||||
ata_ehi_clear_desc(ehi);
|
||||
|
||||
/*
|
||||
@@ -926,12 +975,41 @@ static void sata_fsl_error_intr(struct ata_port *ap)
|
||||
sata_fsl_scr_read(ap, SCR_ERROR, &SError);
|
||||
if (unlikely(SError & 0xFFFF0000)) {
|
||||
sata_fsl_scr_write(ap, SCR_ERROR, SError);
|
||||
err_mask |= AC_ERR_ATA_BUS;
|
||||
}
|
||||
|
||||
DPRINTK("error_intr,hStat=0x%x,CE=0x%x,DE =0x%x,SErr=0x%x\n",
|
||||
hstatus, cereg, ioread32(hcr_base + DE), SError);
|
||||
|
||||
/* handle fatal errors */
|
||||
if (hstatus & FATAL_ERROR_DECODE) {
|
||||
ehi->err_mask |= AC_ERR_ATA_BUS;
|
||||
ehi->action |= ATA_EH_SOFTRESET;
|
||||
|
||||
/*
|
||||
* Ignore serror in case of fatal errors as we always want
|
||||
* to do a soft-reset of the FSL SATA controller. Analyzing
|
||||
* serror may cause libata to schedule a hard-reset action,
|
||||
* and hard-reset currently does not do controller
|
||||
* offline/online, causing command timeouts and leads to an
|
||||
* un-recoverable state, hence make libATA ignore
|
||||
* autopsy in case of fatal errors.
|
||||
*/
|
||||
|
||||
ehi->flags |= ATA_EHI_NO_AUTOPSY;
|
||||
|
||||
freeze = 1;
|
||||
}
|
||||
|
||||
/* Handle PHYRDY change notification */
|
||||
if (hstatus & INT_ON_PHYRDY_CHG) {
|
||||
DPRINTK("SATA FSL: PHYRDY change indication\n");
|
||||
|
||||
/* Setup a soft-reset EH action */
|
||||
ata_ehi_hotplugged(ehi);
|
||||
ata_ehi_push_desc(ehi, "%s", "PHY RDY changed");
|
||||
freeze = 1;
|
||||
}
|
||||
|
||||
/* handle single device errors */
|
||||
if (cereg) {
|
||||
/*
|
||||
@@ -943,58 +1021,68 @@ static void sata_fsl_error_intr(struct ata_port *ap)
|
||||
* clearing the device error, we can issue commands to the
|
||||
* device to interrogate it to find the source of the error.
|
||||
*/
|
||||
dereg = ioread32(hcr_base + DE);
|
||||
iowrite32(dereg, hcr_base + DE);
|
||||
iowrite32(cereg, hcr_base + CE);
|
||||
abort = 1;
|
||||
|
||||
DPRINTK("single device error, CE=0x%x, DE=0x%x\n",
|
||||
ioread32(hcr_base + CE), ioread32(hcr_base + DE));
|
||||
/*
|
||||
* We should consider this as non fatal error, and TF must
|
||||
* be updated as done below.
|
||||
*/
|
||||
|
||||
err_mask |= AC_ERR_DEV;
|
||||
}
|
||||
/* find out the offending link and qc */
|
||||
if (ap->nr_pmp_links) {
|
||||
dereg = ioread32(hcr_base + DE);
|
||||
iowrite32(dereg, hcr_base + DE);
|
||||
iowrite32(cereg, hcr_base + CE);
|
||||
|
||||
/* handle fatal errors */
|
||||
if (hstatus & FATAL_ERROR_DECODE) {
|
||||
err_mask |= AC_ERR_ATA_BUS;
|
||||
action |= ATA_EH_RESET;
|
||||
/* how will fatal error interrupts be completed ?? */
|
||||
freeze = 1;
|
||||
}
|
||||
if (dereg < ap->nr_pmp_links) {
|
||||
link = &ap->pmp_link[dereg];
|
||||
ehi = &link->eh_info;
|
||||
qc = ata_qc_from_tag(ap, link->active_tag);
|
||||
/*
|
||||
* We should consider this as non fatal error,
|
||||
* and TF must be updated as done below.
|
||||
*/
|
||||
|
||||
/* Handle PHYRDY change notification */
|
||||
if (hstatus & INT_ON_PHYRDY_CHG) {
|
||||
DPRINTK("SATA FSL: PHYRDY change indication\n");
|
||||
err_mask |= AC_ERR_DEV;
|
||||
|
||||
/* Setup a soft-reset EH action */
|
||||
ata_ehi_hotplugged(ehi);
|
||||
freeze = 1;
|
||||
} else {
|
||||
err_mask |= AC_ERR_HSM;
|
||||
action |= ATA_EH_HARDRESET;
|
||||
freeze = 1;
|
||||
}
|
||||
} else {
|
||||
dereg = ioread32(hcr_base + DE);
|
||||
iowrite32(dereg, hcr_base + DE);
|
||||
iowrite32(cereg, hcr_base + CE);
|
||||
|
||||
qc = ata_qc_from_tag(ap, link->active_tag);
|
||||
/*
|
||||
* We should consider this as non fatal error,
|
||||
* and TF must be updated as done below.
|
||||
*/
|
||||
err_mask |= AC_ERR_DEV;
|
||||
}
|
||||
}
|
||||
|
||||
/* record error info */
|
||||
qc = ata_qc_from_tag(ap, link->active_tag);
|
||||
|
||||
if (qc)
|
||||
if (qc) {
|
||||
qc->err_mask |= err_mask;
|
||||
else
|
||||
} else
|
||||
ehi->err_mask |= err_mask;
|
||||
|
||||
ehi->action |= action;
|
||||
ehi->serror |= SError;
|
||||
|
||||
/* freeze or abort */
|
||||
if (freeze)
|
||||
ata_port_freeze(ap);
|
||||
else
|
||||
ata_port_abort(ap);
|
||||
else if (abort) {
|
||||
if (qc)
|
||||
ata_link_abort(qc->dev->link);
|
||||
else
|
||||
ata_port_abort(ap);
|
||||
}
|
||||
}
|
||||
|
||||
static void sata_fsl_host_intr(struct ata_port *ap)
|
||||
{
|
||||
struct ata_link *link = &ap->link;
|
||||
struct sata_fsl_host_priv *host_priv = ap->host->private_data;
|
||||
void __iomem *hcr_base = host_priv->hcr_base;
|
||||
u32 hstatus, qc_active = 0;
|
||||
@@ -1017,10 +1105,19 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
||||
return;
|
||||
}
|
||||
|
||||
if (link->sactive) { /* only true for NCQ commands */
|
||||
/* Read command completed register */
|
||||
qc_active = ioread32(hcr_base + CC);
|
||||
|
||||
VPRINTK("Status of all queues :\n");
|
||||
VPRINTK("qc_active/CC = 0x%x, CA = 0x%x, CE=0x%x,CQ=0x%x,apqa=0x%x\n",
|
||||
qc_active,
|
||||
ioread32(hcr_base + CA),
|
||||
ioread32(hcr_base + CE),
|
||||
ioread32(hcr_base + CQ),
|
||||
ap->qc_active);
|
||||
|
||||
if (qc_active & ap->qc_active) {
|
||||
int i;
|
||||
/* Read command completed register */
|
||||
qc_active = ioread32(hcr_base + CC);
|
||||
/* clear CC bit, this will also complete the interrupt */
|
||||
iowrite32(qc_active, hcr_base + CC);
|
||||
|
||||
@@ -1032,8 +1129,9 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
||||
for (i = 0; i < SATA_FSL_QUEUE_DEPTH; i++) {
|
||||
if (qc_active & (1 << i)) {
|
||||
qc = ata_qc_from_tag(ap, i);
|
||||
if (qc)
|
||||
if (qc) {
|
||||
ata_qc_complete(qc);
|
||||
}
|
||||
DPRINTK
|
||||
("completing ncq cmd,tag=%d,CC=0x%x,CA=0x%x\n",
|
||||
i, ioread32(hcr_base + CC),
|
||||
@@ -1042,19 +1140,21 @@ static void sata_fsl_host_intr(struct ata_port *ap)
|
||||
}
|
||||
return;
|
||||
|
||||
} else if (ap->qc_active) {
|
||||
} else if ((ap->qc_active & (1 << ATA_TAG_INTERNAL))) {
|
||||
iowrite32(1, hcr_base + CC);
|
||||
qc = ata_qc_from_tag(ap, link->active_tag);
|
||||
qc = ata_qc_from_tag(ap, ATA_TAG_INTERNAL);
|
||||
|
||||
DPRINTK("completing non-ncq cmd, tag=%d,CC=0x%x\n",
|
||||
link->active_tag, ioread32(hcr_base + CC));
|
||||
DPRINTK("completing non-ncq cmd, CC=0x%x\n",
|
||||
ioread32(hcr_base + CC));
|
||||
|
||||
if (qc)
|
||||
if (qc) {
|
||||
ata_qc_complete(qc);
|
||||
}
|
||||
} else {
|
||||
/* Spurious Interrupt!! */
|
||||
DPRINTK("spurious interrupt!!, CC = 0x%x\n",
|
||||
ioread32(hcr_base + CC));
|
||||
iowrite32(qc_active, hcr_base + CC);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1130,9 +1230,6 @@ static int sata_fsl_init_controller(struct ata_host *host)
|
||||
iowrite32(0x00000FFFF, hcr_base + CE);
|
||||
iowrite32(0x00000FFFF, hcr_base + DE);
|
||||
|
||||
/* initially assuming no Port multiplier, set CQPMP to 0 */
|
||||
iowrite32(0x0, hcr_base + CQPMP);
|
||||
|
||||
/*
|
||||
* host controller will be brought on-line, during xx_port_start()
|
||||
* callback, that should also initiate the OOB, COMINIT sequence
|
||||
@@ -1154,8 +1251,8 @@ static struct scsi_host_template sata_fsl_sht = {
|
||||
.dma_boundary = ATA_DMA_BOUNDARY,
|
||||
};
|
||||
|
||||
static const struct ata_port_operations sata_fsl_ops = {
|
||||
.inherits = &sata_port_ops,
|
||||
static struct ata_port_operations sata_fsl_ops = {
|
||||
.inherits = &sata_pmp_port_ops,
|
||||
|
||||
.qc_prep = sata_fsl_qc_prep,
|
||||
.qc_issue = sata_fsl_qc_issue,
|
||||
@@ -1168,10 +1265,15 @@ static const struct ata_port_operations sata_fsl_ops = {
|
||||
.thaw = sata_fsl_thaw,
|
||||
.prereset = sata_fsl_prereset,
|
||||
.softreset = sata_fsl_softreset,
|
||||
.pmp_softreset = sata_fsl_softreset,
|
||||
.error_handler = sata_fsl_error_handler,
|
||||
.post_internal_cmd = sata_fsl_post_internal_cmd,
|
||||
|
||||
.port_start = sata_fsl_port_start,
|
||||
.port_stop = sata_fsl_port_stop,
|
||||
|
||||
.pmp_attach = sata_fsl_pmp_attach,
|
||||
.pmp_detach = sata_fsl_pmp_detach,
|
||||
};
|
||||
|
||||
static const struct ata_port_info sata_fsl_port_info[] = {
|
||||
|
||||
+127
-111
@@ -72,7 +72,7 @@
|
||||
#include <linux/libata.h>
|
||||
|
||||
#define DRV_NAME "sata_mv"
|
||||
#define DRV_VERSION "1.20"
|
||||
#define DRV_VERSION "1.24"
|
||||
|
||||
enum {
|
||||
/* BAR's are enumerated in terms of pci_resource_start() terms */
|
||||
@@ -122,14 +122,17 @@ enum {
|
||||
/* Host Flags */
|
||||
MV_FLAG_DUAL_HC = (1 << 30), /* two SATA Host Controllers */
|
||||
MV_FLAG_IRQ_COALESCE = (1 << 29), /* IRQ coalescing capability */
|
||||
/* SoC integrated controllers, no PCI interface */
|
||||
MV_FLAG_SOC = (1 << 28),
|
||||
|
||||
MV_COMMON_FLAGS = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
|
||||
ATA_FLAG_MMIO | ATA_FLAG_NO_ATAPI |
|
||||
ATA_FLAG_PIO_POLLING,
|
||||
|
||||
MV_6XXX_FLAGS = MV_FLAG_IRQ_COALESCE,
|
||||
|
||||
MV_GENIIE_FLAGS = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
|
||||
ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
|
||||
ATA_FLAG_NCQ | ATA_FLAG_AN,
|
||||
|
||||
CRQB_FLAG_READ = (1 << 0),
|
||||
CRQB_TAG_SHIFT = 1,
|
||||
CRQB_IOID_SHIFT = 6, /* CRQB Gen-II/IIE IO Id shift */
|
||||
@@ -197,13 +200,6 @@ enum {
|
||||
HC_MAIN_RSVD = (0x7f << 25), /* bits 31-25 */
|
||||
HC_MAIN_RSVD_5 = (0x1fff << 19), /* bits 31-19 */
|
||||
HC_MAIN_RSVD_SOC = (0x3fffffb << 6), /* bits 31-9, 7-6 */
|
||||
HC_MAIN_MASKED_IRQS = (TRAN_LO_DONE | TRAN_HI_DONE |
|
||||
PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
|
||||
PORTS_0_7_COAL_DONE | GPIO_INT | TWSI_INT |
|
||||
HC_MAIN_RSVD),
|
||||
HC_MAIN_MASKED_IRQS_5 = (PORTS_0_3_COAL_DONE | PORTS_4_7_COAL_DONE |
|
||||
HC_MAIN_RSVD_5),
|
||||
HC_MAIN_MASKED_IRQS_SOC = (PORTS_0_3_COAL_DONE | HC_MAIN_RSVD_SOC),
|
||||
|
||||
/* SATAHC registers */
|
||||
HC_CFG_OFS = 0,
|
||||
@@ -221,6 +217,7 @@ enum {
|
||||
SATA_STATUS_OFS = 0x300, /* ctrl, err regs follow status */
|
||||
SATA_ACTIVE_OFS = 0x350,
|
||||
SATA_FIS_IRQ_CAUSE_OFS = 0x364,
|
||||
SATA_FIS_IRQ_AN = (1 << 9), /* async notification */
|
||||
|
||||
LTMODE_OFS = 0x30c,
|
||||
LTMODE_BIT8 = (1 << 8), /* unknown, but necessary */
|
||||
@@ -357,12 +354,12 @@ enum {
|
||||
MV_HP_ERRATA_50XXB2 = (1 << 2),
|
||||
MV_HP_ERRATA_60X1B2 = (1 << 3),
|
||||
MV_HP_ERRATA_60X1C0 = (1 << 4),
|
||||
MV_HP_ERRATA_XX42A0 = (1 << 5),
|
||||
MV_HP_GEN_I = (1 << 6), /* Generation I: 50xx */
|
||||
MV_HP_GEN_II = (1 << 7), /* Generation II: 60xx */
|
||||
MV_HP_GEN_IIE = (1 << 8), /* Generation IIE: 6042/7042 */
|
||||
MV_HP_PCIE = (1 << 9), /* PCIe bus/regs: 7042 */
|
||||
MV_HP_CUT_THROUGH = (1 << 10), /* can use EDMA cut-through */
|
||||
MV_HP_FLAG_SOC = (1 << 11), /* SystemOnChip, no PCI */
|
||||
|
||||
/* Port private flags (pp_flags) */
|
||||
MV_PP_FLAG_EDMA_EN = (1 << 0), /* is EDMA engine enabled? */
|
||||
@@ -375,7 +372,7 @@ enum {
|
||||
#define IS_GEN_II(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_II)
|
||||
#define IS_GEN_IIE(hpriv) ((hpriv)->hp_flags & MV_HP_GEN_IIE)
|
||||
#define IS_PCIE(hpriv) ((hpriv)->hp_flags & MV_HP_PCIE)
|
||||
#define HAS_PCI(host) (!((host)->ports[0]->flags & MV_FLAG_SOC))
|
||||
#define IS_SOC(hpriv) ((hpriv)->hp_flags & MV_HP_FLAG_SOC)
|
||||
|
||||
#define WINDOW_CTRL(i) (0x20030 + ((i) << 4))
|
||||
#define WINDOW_BASE(i) (0x20034 + ((i) << 4))
|
||||
@@ -459,6 +456,7 @@ struct mv_port_signal {
|
||||
|
||||
struct mv_host_priv {
|
||||
u32 hp_flags;
|
||||
u32 main_irq_mask;
|
||||
struct mv_port_signal signal[8];
|
||||
const struct mv_hw_ops *ops;
|
||||
int n_ports;
|
||||
@@ -640,25 +638,19 @@ static const struct ata_port_info mv_port_info[] = {
|
||||
.port_ops = &mv6_ops,
|
||||
},
|
||||
{ /* chip_6042 */
|
||||
.flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
|
||||
ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
|
||||
ATA_FLAG_NCQ,
|
||||
.flags = MV_GENIIE_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &mv_iie_ops,
|
||||
},
|
||||
{ /* chip_7042 */
|
||||
.flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
|
||||
ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
|
||||
ATA_FLAG_NCQ,
|
||||
.flags = MV_GENIIE_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &mv_iie_ops,
|
||||
},
|
||||
{ /* chip_soc */
|
||||
.flags = MV_COMMON_FLAGS | MV_6XXX_FLAGS |
|
||||
ATA_FLAG_PMP | ATA_FLAG_ACPI_SATA |
|
||||
ATA_FLAG_NCQ | MV_FLAG_SOC,
|
||||
.flags = MV_GENIIE_FLAGS,
|
||||
.pio_mask = 0x1f, /* pio0-4 */
|
||||
.udma_mask = ATA_UDMA6,
|
||||
.port_ops = &mv_iie_ops,
|
||||
@@ -818,12 +810,7 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
|
||||
writel((pp->crqb_dma >> 16) >> 16, port_mmio + EDMA_REQ_Q_BASE_HI_OFS);
|
||||
writelfl((pp->crqb_dma & EDMA_REQ_Q_BASE_LO_MASK) | index,
|
||||
port_mmio + EDMA_REQ_Q_IN_PTR_OFS);
|
||||
|
||||
if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
|
||||
writelfl((pp->crqb_dma & 0xffffffff) | index,
|
||||
port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
|
||||
else
|
||||
writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
|
||||
writelfl(index, port_mmio + EDMA_REQ_Q_OUT_PTR_OFS);
|
||||
|
||||
/*
|
||||
* initialize response queue
|
||||
@@ -833,17 +820,38 @@ static void mv_set_edma_ptrs(void __iomem *port_mmio,
|
||||
|
||||
WARN_ON(pp->crpb_dma & 0xff);
|
||||
writel((pp->crpb_dma >> 16) >> 16, port_mmio + EDMA_RSP_Q_BASE_HI_OFS);
|
||||
|
||||
if (hpriv->hp_flags & MV_HP_ERRATA_XX42A0)
|
||||
writelfl((pp->crpb_dma & 0xffffffff) | index,
|
||||
port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
|
||||
else
|
||||
writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
|
||||
|
||||
writelfl(index, port_mmio + EDMA_RSP_Q_IN_PTR_OFS);
|
||||
writelfl((pp->crpb_dma & EDMA_RSP_Q_BASE_LO_MASK) | index,
|
||||
port_mmio + EDMA_RSP_Q_OUT_PTR_OFS);
|
||||
}
|
||||
|
||||
static void mv_set_main_irq_mask(struct ata_host *host,
|
||||
u32 disable_bits, u32 enable_bits)
|
||||
{
|
||||
struct mv_host_priv *hpriv = host->private_data;
|
||||
u32 old_mask, new_mask;
|
||||
|
||||
old_mask = hpriv->main_irq_mask;
|
||||
new_mask = (old_mask & ~disable_bits) | enable_bits;
|
||||
if (new_mask != old_mask) {
|
||||
hpriv->main_irq_mask = new_mask;
|
||||
writelfl(new_mask, hpriv->main_irq_mask_addr);
|
||||
}
|
||||
}
|
||||
|
||||
static void mv_enable_port_irqs(struct ata_port *ap,
|
||||
unsigned int port_bits)
|
||||
{
|
||||
unsigned int shift, hardport, port = ap->port_no;
|
||||
u32 disable_bits, enable_bits;
|
||||
|
||||
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
|
||||
|
||||
disable_bits = (DONE_IRQ | ERR_IRQ) << shift;
|
||||
enable_bits = port_bits << shift;
|
||||
mv_set_main_irq_mask(ap->host, disable_bits, enable_bits);
|
||||
}
|
||||
|
||||
/**
|
||||
* mv_start_dma - Enable eDMA engine
|
||||
* @base: port base address
|
||||
@@ -886,9 +894,11 @@ static void mv_start_dma(struct ata_port *ap, void __iomem *port_mmio,
|
||||
mv_edma_cfg(ap, want_ncq);
|
||||
|
||||
/* clear FIS IRQ Cause */
|
||||
writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
|
||||
if (IS_GEN_IIE(hpriv))
|
||||
writelfl(0, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
|
||||
|
||||
mv_set_edma_ptrs(port_mmio, hpriv, pp);
|
||||
mv_enable_port_irqs(ap, DONE_IRQ|ERR_IRQ);
|
||||
|
||||
writelfl(EDMA_EN, port_mmio + EDMA_CMD_OFS);
|
||||
pp->pp_flags |= MV_PP_FLAG_EDMA_EN;
|
||||
@@ -1231,7 +1241,7 @@ static void mv_edma_cfg(struct ata_port *ap, int want_ncq)
|
||||
|
||||
cfg |= (1 << 23); /* do not mask PM field in rx'd FIS */
|
||||
cfg |= (1 << 22); /* enab 4-entry host queue cache */
|
||||
if (HAS_PCI(ap->host))
|
||||
if (!IS_SOC(hpriv))
|
||||
cfg |= (1 << 18); /* enab early completion */
|
||||
if (hpriv->hp_flags & MV_HP_CUT_THROUGH)
|
||||
cfg |= (1 << 17); /* enab cut-thru (dis stor&forwrd) */
|
||||
@@ -1341,6 +1351,7 @@ out_port_free_dma_mem:
|
||||
static void mv_port_stop(struct ata_port *ap)
|
||||
{
|
||||
mv_stop_edma(ap);
|
||||
mv_enable_port_irqs(ap, 0);
|
||||
mv_port_free_dma_mem(ap);
|
||||
}
|
||||
|
||||
@@ -1582,6 +1593,7 @@ static unsigned int mv_qc_issue(struct ata_queued_cmd *qc)
|
||||
* shadow block, etc registers.
|
||||
*/
|
||||
mv_stop_edma(ap);
|
||||
mv_enable_port_irqs(ap, ERR_IRQ);
|
||||
mv_pmp_select(ap, qc->dev->link->pmp);
|
||||
return ata_sff_qc_issue(qc);
|
||||
}
|
||||
@@ -1670,6 +1682,18 @@ static void mv_pmp_eh_prep(struct ata_port *ap, unsigned int pmp_map)
|
||||
}
|
||||
}
|
||||
|
||||
static int mv_req_q_empty(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = mv_ap_base(ap);
|
||||
u32 in_ptr, out_ptr;
|
||||
|
||||
in_ptr = (readl(port_mmio + EDMA_REQ_Q_IN_PTR_OFS)
|
||||
>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
|
||||
out_ptr = (readl(port_mmio + EDMA_REQ_Q_OUT_PTR_OFS)
|
||||
>> EDMA_REQ_Q_PTR_SHIFT) & MV_MAX_Q_DEPTH_MASK;
|
||||
return (in_ptr == out_ptr); /* 1 == queue_is_empty */
|
||||
}
|
||||
|
||||
static int mv_handle_fbs_ncq_dev_err(struct ata_port *ap)
|
||||
{
|
||||
struct mv_port_priv *pp = ap->private_data;
|
||||
@@ -1703,7 +1727,7 @@ static int mv_handle_fbs_ncq_dev_err(struct ata_port *ap)
|
||||
ap->qc_active, failed_links,
|
||||
ap->nr_active_links);
|
||||
|
||||
if (ap->nr_active_links <= failed_links) {
|
||||
if (ap->nr_active_links <= failed_links && mv_req_q_empty(ap)) {
|
||||
mv_process_crpb_entries(ap, pp);
|
||||
mv_stop_edma(ap);
|
||||
mv_eh_freeze(ap);
|
||||
@@ -1812,6 +1836,7 @@ static void mv_err_intr(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *port_mmio = mv_ap_base(ap);
|
||||
u32 edma_err_cause, eh_freeze_mask, serr = 0;
|
||||
u32 fis_cause = 0;
|
||||
struct mv_port_priv *pp = ap->private_data;
|
||||
struct mv_host_priv *hpriv = ap->host->private_data;
|
||||
unsigned int action = 0, err_mask = 0;
|
||||
@@ -1821,16 +1846,19 @@ static void mv_err_intr(struct ata_port *ap)
|
||||
|
||||
/*
|
||||
* Read and clear the SError and err_cause bits.
|
||||
* For GenIIe, if EDMA_ERR_TRANS_IRQ_7 is set, we also must read/clear
|
||||
* the FIS_IRQ_CAUSE register before clearing edma_err_cause.
|
||||
*/
|
||||
sata_scr_read(&ap->link, SCR_ERROR, &serr);
|
||||
sata_scr_write_flush(&ap->link, SCR_ERROR, serr);
|
||||
|
||||
edma_err_cause = readl(port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
|
||||
if (IS_GEN_IIE(hpriv) && (edma_err_cause & EDMA_ERR_TRANS_IRQ_7)) {
|
||||
fis_cause = readl(port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
|
||||
writelfl(~fis_cause, port_mmio + SATA_FIS_IRQ_CAUSE_OFS);
|
||||
}
|
||||
writelfl(~edma_err_cause, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
|
||||
|
||||
ata_port_printk(ap, KERN_INFO, "%s: err_cause=%08x pp_flags=0x%x\n",
|
||||
__func__, edma_err_cause, pp->pp_flags);
|
||||
|
||||
if (edma_err_cause & EDMA_ERR_DEV) {
|
||||
/*
|
||||
* Device errors during FIS-based switching operation
|
||||
@@ -1844,6 +1872,18 @@ static void mv_err_intr(struct ata_port *ap)
|
||||
ata_ehi_clear_desc(ehi);
|
||||
ata_ehi_push_desc(ehi, "edma_err_cause=%08x pp_flags=%08x",
|
||||
edma_err_cause, pp->pp_flags);
|
||||
|
||||
if (IS_GEN_IIE(hpriv) && (edma_err_cause & EDMA_ERR_TRANS_IRQ_7)) {
|
||||
ata_ehi_push_desc(ehi, "fis_cause=%08x", fis_cause);
|
||||
if (fis_cause & SATA_FIS_IRQ_AN) {
|
||||
u32 ec = edma_err_cause &
|
||||
~(EDMA_ERR_TRANS_IRQ_7 | EDMA_ERR_IRQ_TRANSIENT);
|
||||
sata_async_notification(ap);
|
||||
if (!ec)
|
||||
return; /* Just an AN; no need for the nukes */
|
||||
ata_ehi_push_desc(ehi, "SDB notify");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* All generations share these EDMA error cause bits:
|
||||
*/
|
||||
@@ -2162,20 +2202,20 @@ static irqreturn_t mv_interrupt(int irq, void *dev_instance)
|
||||
struct ata_host *host = dev_instance;
|
||||
struct mv_host_priv *hpriv = host->private_data;
|
||||
unsigned int handled = 0;
|
||||
u32 main_irq_cause, main_irq_mask;
|
||||
u32 main_irq_cause, pending_irqs;
|
||||
|
||||
spin_lock(&host->lock);
|
||||
main_irq_cause = readl(hpriv->main_irq_cause_addr);
|
||||
main_irq_mask = readl(hpriv->main_irq_mask_addr);
|
||||
pending_irqs = main_irq_cause & hpriv->main_irq_mask;
|
||||
/*
|
||||
* Deal with cases where we either have nothing pending, or have read
|
||||
* a bogus register value which can indicate HW removal or PCI fault.
|
||||
*/
|
||||
if ((main_irq_cause & main_irq_mask) && (main_irq_cause != 0xffffffffU)) {
|
||||
if (unlikely((main_irq_cause & PCI_ERR) && HAS_PCI(host)))
|
||||
if (pending_irqs && main_irq_cause != 0xffffffffU) {
|
||||
if (unlikely((pending_irqs & PCI_ERR) && !IS_SOC(hpriv)))
|
||||
handled = mv_pci_error(host, hpriv->base);
|
||||
else
|
||||
handled = mv_host_intr(host, main_irq_cause);
|
||||
handled = mv_host_intr(host, pending_irqs);
|
||||
}
|
||||
spin_unlock(&host->lock);
|
||||
return IRQ_RETVAL(handled);
|
||||
@@ -2373,7 +2413,6 @@ static void mv_reset_pci_bus(struct ata_host *host, void __iomem *mmio)
|
||||
ZERO(MV_PCI_DISC_TIMER);
|
||||
ZERO(MV_PCI_MSI_TRIGGER);
|
||||
writel(0x000100ff, mmio + MV_PCI_XBAR_TMOUT_OFS);
|
||||
ZERO(PCI_HC_MAIN_IRQ_MASK_OFS);
|
||||
ZERO(MV_PCI_SERR_MASK);
|
||||
ZERO(hpriv->irq_cause_ofs);
|
||||
ZERO(hpriv->irq_mask_ofs);
|
||||
@@ -2495,7 +2534,7 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
|
||||
hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
|
||||
int fix_phy_mode4 =
|
||||
hp_flags & (MV_HP_ERRATA_60X1B2 | MV_HP_ERRATA_60X1C0);
|
||||
u32 m2, tmp;
|
||||
u32 m2, m3;
|
||||
|
||||
if (fix_phy_mode2) {
|
||||
m2 = readl(port_mmio + PHY_MODE2);
|
||||
@@ -2512,28 +2551,37 @@ static void mv6_phy_errata(struct mv_host_priv *hpriv, void __iomem *mmio,
|
||||
udelay(200);
|
||||
}
|
||||
|
||||
/* who knows what this magic does */
|
||||
tmp = readl(port_mmio + PHY_MODE3);
|
||||
tmp &= ~0x7F800000;
|
||||
tmp |= 0x2A800000;
|
||||
writel(tmp, port_mmio + PHY_MODE3);
|
||||
/*
|
||||
* Gen-II/IIe PHY_MODE3 errata RM#2:
|
||||
* Achieves better receiver noise performance than the h/w default:
|
||||
*/
|
||||
m3 = readl(port_mmio + PHY_MODE3);
|
||||
m3 = (m3 & 0x1f) | (0x5555601 << 5);
|
||||
|
||||
/* Guideline 88F5182 (GL# SATA-S11) */
|
||||
if (IS_SOC(hpriv))
|
||||
m3 &= ~0x1c;
|
||||
|
||||
if (fix_phy_mode4) {
|
||||
u32 m4;
|
||||
|
||||
m4 = readl(port_mmio + PHY_MODE4);
|
||||
|
||||
if (hp_flags & MV_HP_ERRATA_60X1B2)
|
||||
tmp = readl(port_mmio + PHY_MODE3);
|
||||
|
||||
/* workaround for errata FEr SATA#10 (part 1) */
|
||||
m4 = (m4 & ~(1 << 1)) | (1 << 0);
|
||||
|
||||
writel(m4, port_mmio + PHY_MODE4);
|
||||
/* enforce bit restrictions on GenIIe devices */
|
||||
if (IS_GEN_IIE(hpriv))
|
||||
m4 = (m4 & ~0x5DE3FFFC) | (1 << 2);
|
||||
|
||||
if (hp_flags & MV_HP_ERRATA_60X1B2)
|
||||
writel(tmp, port_mmio + PHY_MODE3);
|
||||
writel(m4, port_mmio + PHY_MODE4);
|
||||
}
|
||||
/*
|
||||
* Workaround for 60x1-B2 errata SATA#13:
|
||||
* Any write to PHY_MODE4 (above) may corrupt PHY_MODE3,
|
||||
* so we must always rewrite PHY_MODE3 after PHY_MODE4.
|
||||
*/
|
||||
writel(m3, port_mmio + PHY_MODE3);
|
||||
|
||||
/* Revert values of pre-emphasis and signal amps to the saved ones */
|
||||
m2 = readl(port_mmio + PHY_MODE2);
|
||||
@@ -2728,6 +2776,7 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
|
||||
|
||||
rc = sata_link_hardreset(link, timing, deadline + extra,
|
||||
&online, NULL);
|
||||
rc = online ? -EAGAIN : rc;
|
||||
if (rc)
|
||||
return rc;
|
||||
sata_scr_read(link, SCR_STATUS, &sstatus);
|
||||
@@ -2744,32 +2793,18 @@ static int mv_hardreset(struct ata_link *link, unsigned int *class,
|
||||
|
||||
static void mv_eh_freeze(struct ata_port *ap)
|
||||
{
|
||||
struct mv_host_priv *hpriv = ap->host->private_data;
|
||||
unsigned int shift, hardport, port = ap->port_no;
|
||||
u32 main_irq_mask;
|
||||
|
||||
/* FIXME: handle coalescing completion events properly */
|
||||
|
||||
mv_stop_edma(ap);
|
||||
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
|
||||
|
||||
/* disable assertion of portN err, done events */
|
||||
main_irq_mask = readl(hpriv->main_irq_mask_addr);
|
||||
main_irq_mask &= ~((DONE_IRQ | ERR_IRQ) << shift);
|
||||
writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
|
||||
mv_enable_port_irqs(ap, 0);
|
||||
}
|
||||
|
||||
static void mv_eh_thaw(struct ata_port *ap)
|
||||
{
|
||||
struct mv_host_priv *hpriv = ap->host->private_data;
|
||||
unsigned int shift, hardport, port = ap->port_no;
|
||||
unsigned int port = ap->port_no;
|
||||
unsigned int hardport = mv_hardport_from_port(port);
|
||||
void __iomem *hc_mmio = mv_hc_base_from_port(hpriv->base, port);
|
||||
void __iomem *port_mmio = mv_ap_base(ap);
|
||||
u32 main_irq_mask, hc_irq_cause;
|
||||
|
||||
/* FIXME: handle coalescing completion events properly */
|
||||
|
||||
MV_PORT_TO_SHIFT_AND_HARDPORT(port, shift, hardport);
|
||||
u32 hc_irq_cause;
|
||||
|
||||
/* clear EDMA errors on this port */
|
||||
writel(0, port_mmio + EDMA_ERR_IRQ_CAUSE_OFS);
|
||||
@@ -2779,10 +2814,7 @@ static void mv_eh_thaw(struct ata_port *ap)
|
||||
hc_irq_cause &= ~((DEV_IRQ | DMA_IRQ) << hardport);
|
||||
writelfl(hc_irq_cause, hc_mmio + HC_IRQ_CAUSE_OFS);
|
||||
|
||||
/* enable assertion of portN err, done events */
|
||||
main_irq_mask = readl(hpriv->main_irq_mask_addr);
|
||||
main_irq_mask |= ((DONE_IRQ | ERR_IRQ) << shift);
|
||||
writelfl(main_irq_mask, hpriv->main_irq_mask_addr);
|
||||
mv_enable_port_irqs(ap, ERR_IRQ);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2840,7 +2872,7 @@ static unsigned int mv_in_pcix_mode(struct ata_host *host)
|
||||
void __iomem *mmio = hpriv->base;
|
||||
u32 reg;
|
||||
|
||||
if (!HAS_PCI(host) || !IS_PCIE(hpriv))
|
||||
if (IS_SOC(hpriv) || !IS_PCIE(hpriv))
|
||||
return 0; /* not PCI-X capable */
|
||||
reg = readl(mmio + MV_PCI_MODE_OFS);
|
||||
if ((reg & MV_PCI_MODE_MASK) == 0)
|
||||
@@ -2967,10 +2999,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
|
||||
hp_flags |= MV_HP_CUT_THROUGH;
|
||||
|
||||
switch (pdev->revision) {
|
||||
case 0x0:
|
||||
hp_flags |= MV_HP_ERRATA_XX42A0;
|
||||
break;
|
||||
case 0x1:
|
||||
case 0x2: /* Rev.B0: the first/only public release */
|
||||
hp_flags |= MV_HP_ERRATA_60X1C0;
|
||||
break;
|
||||
default:
|
||||
@@ -2982,7 +3011,7 @@ static int mv_chip_id(struct ata_host *host, unsigned int board_idx)
|
||||
break;
|
||||
case chip_soc:
|
||||
hpriv->ops = &mv_soc_ops;
|
||||
hp_flags |= MV_HP_ERRATA_60X1C0;
|
||||
hp_flags |= MV_HP_FLAG_SOC | MV_HP_ERRATA_60X1C0;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -3026,16 +3055,16 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
|
||||
if (rc)
|
||||
goto done;
|
||||
|
||||
if (HAS_PCI(host)) {
|
||||
hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
|
||||
hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
|
||||
} else {
|
||||
if (IS_SOC(hpriv)) {
|
||||
hpriv->main_irq_cause_addr = mmio + SOC_HC_MAIN_IRQ_CAUSE_OFS;
|
||||
hpriv->main_irq_mask_addr = mmio + SOC_HC_MAIN_IRQ_MASK_OFS;
|
||||
} else {
|
||||
hpriv->main_irq_cause_addr = mmio + PCI_HC_MAIN_IRQ_CAUSE_OFS;
|
||||
hpriv->main_irq_mask_addr = mmio + PCI_HC_MAIN_IRQ_MASK_OFS;
|
||||
}
|
||||
|
||||
/* global interrupt mask: 0 == mask everything */
|
||||
writel(0, hpriv->main_irq_mask_addr);
|
||||
mv_set_main_irq_mask(host, ~0, 0);
|
||||
|
||||
n_hc = mv_get_hc_count(host->ports[0]->flags);
|
||||
|
||||
@@ -3057,7 +3086,7 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
|
||||
mv_port_init(&ap->ioaddr, port_mmio);
|
||||
|
||||
#ifdef CONFIG_PCI
|
||||
if (HAS_PCI(host)) {
|
||||
if (!IS_SOC(hpriv)) {
|
||||
unsigned int offset = port_mmio - mmio;
|
||||
ata_port_pbar_desc(ap, MV_PRIMARY_BAR, -1, "mmio");
|
||||
ata_port_pbar_desc(ap, MV_PRIMARY_BAR, offset, "port");
|
||||
@@ -3077,31 +3106,18 @@ static int mv_init_host(struct ata_host *host, unsigned int board_idx)
|
||||
writelfl(0, hc_mmio + HC_IRQ_CAUSE_OFS);
|
||||
}
|
||||
|
||||
if (HAS_PCI(host)) {
|
||||
if (!IS_SOC(hpriv)) {
|
||||
/* Clear any currently outstanding host interrupt conditions */
|
||||
writelfl(0, mmio + hpriv->irq_cause_ofs);
|
||||
|
||||
/* and unmask interrupt generation for host regs */
|
||||
writelfl(hpriv->unmask_all_irqs, mmio + hpriv->irq_mask_ofs);
|
||||
if (IS_GEN_I(hpriv))
|
||||
writelfl(~HC_MAIN_MASKED_IRQS_5,
|
||||
hpriv->main_irq_mask_addr);
|
||||
else
|
||||
writelfl(~HC_MAIN_MASKED_IRQS,
|
||||
hpriv->main_irq_mask_addr);
|
||||
|
||||
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x "
|
||||
"PCI int cause/mask=0x%08x/0x%08x\n",
|
||||
readl(hpriv->main_irq_cause_addr),
|
||||
readl(hpriv->main_irq_mask_addr),
|
||||
readl(mmio + hpriv->irq_cause_ofs),
|
||||
readl(mmio + hpriv->irq_mask_ofs));
|
||||
} else {
|
||||
writelfl(~HC_MAIN_MASKED_IRQS_SOC,
|
||||
hpriv->main_irq_mask_addr);
|
||||
VPRINTK("HC MAIN IRQ cause/mask=0x%08x/0x%08x\n",
|
||||
readl(hpriv->main_irq_cause_addr),
|
||||
readl(hpriv->main_irq_mask_addr));
|
||||
/*
|
||||
* enable only global host interrupts for now.
|
||||
* The per-port interrupts get done later as ports are set up.
|
||||
*/
|
||||
mv_set_main_irq_mask(host, 0, PCI_ERR);
|
||||
}
|
||||
done:
|
||||
return rc;
|
||||
|
||||
+72
-76
@@ -53,7 +53,15 @@ enum {
|
||||
PDC_MMIO_BAR = 3,
|
||||
PDC_MAX_PRD = LIBATA_MAX_PRD - 1, /* -1 for ASIC PRD bug workaround */
|
||||
|
||||
/* register offsets */
|
||||
/* host register offsets (from host->iomap[PDC_MMIO_BAR]) */
|
||||
PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
|
||||
PDC_FLASH_CTL = 0x44, /* Flash control register */
|
||||
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
|
||||
PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */
|
||||
PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */
|
||||
PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */
|
||||
|
||||
/* per-port ATA register offsets (from ap->ioaddr.cmd_addr) */
|
||||
PDC_FEATURE = 0x04, /* Feature/Error reg (per port) */
|
||||
PDC_SECTOR_COUNT = 0x08, /* Sector count reg (per port) */
|
||||
PDC_SECTOR_NUMBER = 0x0C, /* Sector number reg (per port) */
|
||||
@@ -63,14 +71,11 @@ enum {
|
||||
PDC_COMMAND = 0x1C, /* Command/status reg (per port) */
|
||||
PDC_ALTSTATUS = 0x38, /* Alternate-status/device-control reg (per port) */
|
||||
PDC_PKT_SUBMIT = 0x40, /* Command packet pointer addr */
|
||||
PDC_INT_SEQMASK = 0x40, /* Mask of asserted SEQ INTs */
|
||||
PDC_FLASH_CTL = 0x44, /* Flash control register */
|
||||
PDC_GLOBAL_CTL = 0x48, /* Global control/status (per port) */
|
||||
PDC_CTLSTAT = 0x60, /* IDE control and status (per port) */
|
||||
PDC_SATA_PLUG_CSR = 0x6C, /* SATA Plug control/status reg */
|
||||
PDC2_SATA_PLUG_CSR = 0x60, /* SATAII Plug control/status reg */
|
||||
PDC_TBG_MODE = 0x41C, /* TBG mode (not SATAII) */
|
||||
PDC_SLEW_CTL = 0x470, /* slew rate control reg (not SATAII) */
|
||||
|
||||
/* per-port SATA register offsets (from ap->ioaddr.scr_addr) */
|
||||
PDC_PHYMODE4 = 0x14,
|
||||
|
||||
/* PDC_GLOBAL_CTL bit definitions */
|
||||
PDC_PH_ERR = (1 << 8), /* PCI error while loading packet */
|
||||
@@ -134,7 +139,7 @@ struct pdc_port_priv {
|
||||
|
||||
static int pdc_sata_scr_read(struct ata_port *ap, unsigned int sc_reg, u32 *val);
|
||||
static int pdc_sata_scr_write(struct ata_port *ap, unsigned int sc_reg, u32 val);
|
||||
static int pdc_ata_init_one (struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
static int pdc_ata_init_one(struct pci_dev *pdev, const struct pci_device_id *ent);
|
||||
static int pdc_common_port_start(struct ata_port *ap);
|
||||
static int pdc_sata_port_start(struct ata_port *ap);
|
||||
static void pdc_qc_prep(struct ata_queued_cmd *qc);
|
||||
@@ -332,12 +337,12 @@ static int pdc_sata_port_start(struct ata_port *ap)
|
||||
|
||||
/* fix up PHYMODE4 align timing */
|
||||
if (ap->flags & PDC_FLAG_GEN_II) {
|
||||
void __iomem *mmio = ap->ioaddr.scr_addr;
|
||||
void __iomem *sata_mmio = ap->ioaddr.scr_addr;
|
||||
unsigned int tmp;
|
||||
|
||||
tmp = readl(mmio + 0x014);
|
||||
tmp = readl(sata_mmio + PDC_PHYMODE4);
|
||||
tmp = (tmp & ~3) | 1; /* set bits 1:0 = 0:1 */
|
||||
writel(tmp, mmio + 0x014);
|
||||
writel(tmp, sata_mmio + PDC_PHYMODE4);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -345,32 +350,32 @@ static int pdc_sata_port_start(struct ata_port *ap)
|
||||
|
||||
static void pdc_reset_port(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
|
||||
void __iomem *ata_ctlstat_mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT;
|
||||
unsigned int i;
|
||||
u32 tmp;
|
||||
|
||||
for (i = 11; i > 0; i--) {
|
||||
tmp = readl(mmio);
|
||||
tmp = readl(ata_ctlstat_mmio);
|
||||
if (tmp & PDC_RESET)
|
||||
break;
|
||||
|
||||
udelay(100);
|
||||
|
||||
tmp |= PDC_RESET;
|
||||
writel(tmp, mmio);
|
||||
writel(tmp, ata_ctlstat_mmio);
|
||||
}
|
||||
|
||||
tmp &= ~PDC_RESET;
|
||||
writel(tmp, mmio);
|
||||
readl(mmio); /* flush */
|
||||
writel(tmp, ata_ctlstat_mmio);
|
||||
readl(ata_ctlstat_mmio); /* flush */
|
||||
}
|
||||
|
||||
static int pdc_pata_cable_detect(struct ata_port *ap)
|
||||
{
|
||||
u8 tmp;
|
||||
void __iomem *mmio = ap->ioaddr.cmd_addr + PDC_CTLSTAT + 0x03;
|
||||
void __iomem *ata_mmio = ap->ioaddr.cmd_addr;
|
||||
|
||||
tmp = readb(mmio);
|
||||
tmp = readb(ata_mmio + PDC_CTLSTAT + 3);
|
||||
if (tmp & 0x01)
|
||||
return ATA_CBL_PATA40;
|
||||
return ATA_CBL_PATA80;
|
||||
@@ -557,31 +562,25 @@ static void pdc_qc_prep(struct ata_queued_cmd *qc)
|
||||
switch (qc->tf.protocol) {
|
||||
case ATA_PROT_DMA:
|
||||
pdc_fill_sg(qc);
|
||||
/* fall through */
|
||||
|
||||
/*FALLTHROUGH*/
|
||||
case ATA_PROT_NODATA:
|
||||
i = pdc_pkt_header(&qc->tf, qc->ap->prd_dma,
|
||||
qc->dev->devno, pp->pkt);
|
||||
|
||||
if (qc->tf.flags & ATA_TFLAG_LBA48)
|
||||
i = pdc_prep_lba48(&qc->tf, pp->pkt, i);
|
||||
else
|
||||
i = pdc_prep_lba28(&qc->tf, pp->pkt, i);
|
||||
|
||||
pdc_pkt_footer(&qc->tf, pp->pkt, i);
|
||||
break;
|
||||
|
||||
case ATAPI_PROT_PIO:
|
||||
pdc_fill_sg(qc);
|
||||
break;
|
||||
|
||||
case ATAPI_PROT_DMA:
|
||||
pdc_fill_sg(qc);
|
||||
/*FALLTHROUGH*/
|
||||
case ATAPI_PROT_NODATA:
|
||||
pdc_atapi_pkt(qc);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -611,7 +610,7 @@ static unsigned int pdc_sata_ata_port_to_ata_no(const struct ata_port *ap)
|
||||
unsigned int nr_ports = pdc_sata_nr_ports(ap);
|
||||
unsigned int i;
|
||||
|
||||
for(i = 0; i < nr_ports && host->ports[i] != ap; ++i)
|
||||
for (i = 0; i < nr_ports && host->ports[i] != ap; ++i)
|
||||
;
|
||||
BUG_ON(i >= nr_ports);
|
||||
return pdc_port_no_to_ata_no(i, pdc_is_sataii_tx4(ap->flags));
|
||||
@@ -624,14 +623,14 @@ static unsigned int pdc_sata_hotplug_offset(const struct ata_port *ap)
|
||||
|
||||
static void pdc_freeze(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = ap->ioaddr.cmd_addr;
|
||||
void __iomem *ata_mmio = ap->ioaddr.cmd_addr;
|
||||
u32 tmp;
|
||||
|
||||
tmp = readl(mmio + PDC_CTLSTAT);
|
||||
tmp = readl(ata_mmio + PDC_CTLSTAT);
|
||||
tmp |= PDC_IRQ_DISABLE;
|
||||
tmp &= ~PDC_DMA_ENABLE;
|
||||
writel(tmp, mmio + PDC_CTLSTAT);
|
||||
readl(mmio + PDC_CTLSTAT); /* flush */
|
||||
writel(tmp, ata_mmio + PDC_CTLSTAT);
|
||||
readl(ata_mmio + PDC_CTLSTAT); /* flush */
|
||||
}
|
||||
|
||||
static void pdc_sata_freeze(struct ata_port *ap)
|
||||
@@ -659,17 +658,17 @@ static void pdc_sata_freeze(struct ata_port *ap)
|
||||
|
||||
static void pdc_thaw(struct ata_port *ap)
|
||||
{
|
||||
void __iomem *mmio = ap->ioaddr.cmd_addr;
|
||||
void __iomem *ata_mmio = ap->ioaddr.cmd_addr;
|
||||
u32 tmp;
|
||||
|
||||
/* clear IRQ */
|
||||
readl(mmio + PDC_INT_SEQMASK);
|
||||
readl(ata_mmio + PDC_COMMAND);
|
||||
|
||||
/* turn IRQ back on */
|
||||
tmp = readl(mmio + PDC_CTLSTAT);
|
||||
tmp = readl(ata_mmio + PDC_CTLSTAT);
|
||||
tmp &= ~PDC_IRQ_DISABLE;
|
||||
writel(tmp, mmio + PDC_CTLSTAT);
|
||||
readl(mmio + PDC_CTLSTAT); /* flush */
|
||||
writel(tmp, ata_mmio + PDC_CTLSTAT);
|
||||
readl(ata_mmio + PDC_CTLSTAT); /* flush */
|
||||
}
|
||||
|
||||
static void pdc_sata_thaw(struct ata_port *ap)
|
||||
@@ -743,11 +742,11 @@ static void pdc_error_intr(struct ata_port *ap, struct ata_queued_cmd *qc,
|
||||
ata_port_abort(ap);
|
||||
}
|
||||
|
||||
static inline unsigned int pdc_host_intr(struct ata_port *ap,
|
||||
struct ata_queued_cmd *qc)
|
||||
static unsigned int pdc_host_intr(struct ata_port *ap,
|
||||
struct ata_queued_cmd *qc)
|
||||
{
|
||||
unsigned int handled = 0;
|
||||
void __iomem *port_mmio = ap->ioaddr.cmd_addr;
|
||||
void __iomem *ata_mmio = ap->ioaddr.cmd_addr;
|
||||
u32 port_status, err_mask;
|
||||
|
||||
err_mask = PDC_ERR_MASK;
|
||||
@@ -755,7 +754,7 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,
|
||||
err_mask &= ~PDC1_ERR_MASK;
|
||||
else
|
||||
err_mask &= ~PDC2_ERR_MASK;
|
||||
port_status = readl(port_mmio + PDC_GLOBAL_CTL);
|
||||
port_status = readl(ata_mmio + PDC_GLOBAL_CTL);
|
||||
if (unlikely(port_status & err_mask)) {
|
||||
pdc_error_intr(ap, qc, port_status, err_mask);
|
||||
return 1;
|
||||
@@ -770,7 +769,6 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,
|
||||
ata_qc_complete(qc);
|
||||
handled = 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
ap->stats.idle_irq++;
|
||||
break;
|
||||
@@ -781,10 +779,9 @@ static inline unsigned int pdc_host_intr(struct ata_port *ap,
|
||||
|
||||
static void pdc_irq_clear(struct ata_port *ap)
|
||||
{
|
||||
struct ata_host *host = ap->host;
|
||||
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
|
||||
void __iomem *ata_mmio = ap->ioaddr.cmd_addr;
|
||||
|
||||
readl(mmio + PDC_INT_SEQMASK);
|
||||
readl(ata_mmio + PDC_COMMAND);
|
||||
}
|
||||
|
||||
static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
|
||||
@@ -794,7 +791,7 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
|
||||
u32 mask = 0;
|
||||
unsigned int i, tmp;
|
||||
unsigned int handled = 0;
|
||||
void __iomem *mmio_base;
|
||||
void __iomem *host_mmio;
|
||||
unsigned int hotplug_offset, ata_no;
|
||||
u32 hotplug_status;
|
||||
int is_sataii_tx4;
|
||||
@@ -806,7 +803,7 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
mmio_base = host->iomap[PDC_MMIO_BAR];
|
||||
host_mmio = host->iomap[PDC_MMIO_BAR];
|
||||
|
||||
spin_lock(&host->lock);
|
||||
|
||||
@@ -815,26 +812,26 @@ static irqreturn_t pdc_interrupt(int irq, void *dev_instance)
|
||||
hotplug_offset = PDC2_SATA_PLUG_CSR;
|
||||
else
|
||||
hotplug_offset = PDC_SATA_PLUG_CSR;
|
||||
hotplug_status = readl(mmio_base + hotplug_offset);
|
||||
hotplug_status = readl(host_mmio + hotplug_offset);
|
||||
if (hotplug_status & 0xff)
|
||||
writel(hotplug_status | 0xff, mmio_base + hotplug_offset);
|
||||
writel(hotplug_status | 0xff, host_mmio + hotplug_offset);
|
||||
hotplug_status &= 0xff; /* clear uninteresting bits */
|
||||
|
||||
/* reading should also clear interrupts */
|
||||
mask = readl(mmio_base + PDC_INT_SEQMASK);
|
||||
mask = readl(host_mmio + PDC_INT_SEQMASK);
|
||||
|
||||
if (mask == 0xffffffff && hotplug_status == 0) {
|
||||
VPRINTK("QUICK EXIT 2\n");
|
||||
goto done_irq;
|
||||
}
|
||||
|
||||
mask &= 0xffff; /* only 16 tags possible */
|
||||
mask &= 0xffff; /* only 16 SEQIDs possible */
|
||||
if (mask == 0 && hotplug_status == 0) {
|
||||
VPRINTK("QUICK EXIT 3\n");
|
||||
goto done_irq;
|
||||
}
|
||||
|
||||
writel(mask, mmio_base + PDC_INT_SEQMASK);
|
||||
writel(mask, host_mmio + PDC_INT_SEQMASK);
|
||||
|
||||
is_sataii_tx4 = pdc_is_sataii_tx4(host->ports[0]->flags);
|
||||
|
||||
@@ -875,23 +872,24 @@ done_irq:
|
||||
return IRQ_RETVAL(handled);
|
||||
}
|
||||
|
||||
static inline void pdc_packet_start(struct ata_queued_cmd *qc)
|
||||
static void pdc_packet_start(struct ata_queued_cmd *qc)
|
||||
{
|
||||
struct ata_port *ap = qc->ap;
|
||||
struct pdc_port_priv *pp = ap->private_data;
|
||||
void __iomem *mmio = ap->host->iomap[PDC_MMIO_BAR];
|
||||
void __iomem *host_mmio = ap->host->iomap[PDC_MMIO_BAR];
|
||||
void __iomem *ata_mmio = ap->ioaddr.cmd_addr;
|
||||
unsigned int port_no = ap->port_no;
|
||||
u8 seq = (u8) (port_no + 1);
|
||||
|
||||
VPRINTK("ENTER, ap %p\n", ap);
|
||||
|
||||
writel(0x00000001, mmio + (seq * 4));
|
||||
readl(mmio + (seq * 4)); /* flush */
|
||||
writel(0x00000001, host_mmio + (seq * 4));
|
||||
readl(host_mmio + (seq * 4)); /* flush */
|
||||
|
||||
pp->pkt[2] = seq;
|
||||
wmb(); /* flush PRD, pkt writes */
|
||||
writel(pp->pkt_dma, ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT);
|
||||
readl(ap->ioaddr.cmd_addr + PDC_PKT_SUBMIT); /* flush */
|
||||
writel(pp->pkt_dma, ata_mmio + PDC_PKT_SUBMIT);
|
||||
readl(ata_mmio + PDC_PKT_SUBMIT); /* flush */
|
||||
}
|
||||
|
||||
static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc)
|
||||
@@ -909,11 +907,9 @@ static unsigned int pdc_qc_issue(struct ata_queued_cmd *qc)
|
||||
case ATA_PROT_DMA:
|
||||
pdc_packet_start(qc);
|
||||
return 0;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return ata_sff_qc_issue(qc);
|
||||
}
|
||||
|
||||
@@ -987,7 +983,7 @@ static void pdc_ata_setup_port(struct ata_port *ap,
|
||||
|
||||
static void pdc_host_init(struct ata_host *host)
|
||||
{
|
||||
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
|
||||
void __iomem *host_mmio = host->iomap[PDC_MMIO_BAR];
|
||||
int is_gen2 = host->ports[0]->flags & PDC_FLAG_GEN_II;
|
||||
int hotplug_offset;
|
||||
u32 tmp;
|
||||
@@ -1004,38 +1000,38 @@ static void pdc_host_init(struct ata_host *host)
|
||||
*/
|
||||
|
||||
/* enable BMR_BURST, maybe change FIFO_SHD to 8 dwords */
|
||||
tmp = readl(mmio + PDC_FLASH_CTL);
|
||||
tmp = readl(host_mmio + PDC_FLASH_CTL);
|
||||
tmp |= 0x02000; /* bit 13 (enable bmr burst) */
|
||||
if (!is_gen2)
|
||||
tmp |= 0x10000; /* bit 16 (fifo threshold at 8 dw) */
|
||||
writel(tmp, mmio + PDC_FLASH_CTL);
|
||||
writel(tmp, host_mmio + PDC_FLASH_CTL);
|
||||
|
||||
/* clear plug/unplug flags for all ports */
|
||||
tmp = readl(mmio + hotplug_offset);
|
||||
writel(tmp | 0xff, mmio + hotplug_offset);
|
||||
tmp = readl(host_mmio + hotplug_offset);
|
||||
writel(tmp | 0xff, host_mmio + hotplug_offset);
|
||||
|
||||
/* unmask plug/unplug ints */
|
||||
tmp = readl(mmio + hotplug_offset);
|
||||
writel(tmp & ~0xff0000, mmio + hotplug_offset);
|
||||
tmp = readl(host_mmio + hotplug_offset);
|
||||
writel(tmp & ~0xff0000, host_mmio + hotplug_offset);
|
||||
|
||||
/* don't initialise TBG or SLEW on 2nd generation chips */
|
||||
if (is_gen2)
|
||||
return;
|
||||
|
||||
/* reduce TBG clock to 133 Mhz. */
|
||||
tmp = readl(mmio + PDC_TBG_MODE);
|
||||
tmp = readl(host_mmio + PDC_TBG_MODE);
|
||||
tmp &= ~0x30000; /* clear bit 17, 16*/
|
||||
tmp |= 0x10000; /* set bit 17:16 = 0:1 */
|
||||
writel(tmp, mmio + PDC_TBG_MODE);
|
||||
writel(tmp, host_mmio + PDC_TBG_MODE);
|
||||
|
||||
readl(mmio + PDC_TBG_MODE); /* flush */
|
||||
readl(host_mmio + PDC_TBG_MODE); /* flush */
|
||||
msleep(10);
|
||||
|
||||
/* adjust slew rate control register. */
|
||||
tmp = readl(mmio + PDC_SLEW_CTL);
|
||||
tmp = readl(host_mmio + PDC_SLEW_CTL);
|
||||
tmp &= 0xFFFFF03F; /* clear bit 11 ~ 6 */
|
||||
tmp |= 0x00000900; /* set bit 11-9 = 100b , bit 8-6 = 100 */
|
||||
writel(tmp, mmio + PDC_SLEW_CTL);
|
||||
writel(tmp, host_mmio + PDC_SLEW_CTL);
|
||||
}
|
||||
|
||||
static int pdc_ata_init_one(struct pci_dev *pdev,
|
||||
@@ -1045,7 +1041,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
|
||||
const struct ata_port_info *pi = &pdc_port_info[ent->driver_data];
|
||||
const struct ata_port_info *ppi[PDC_MAX_PORTS];
|
||||
struct ata_host *host;
|
||||
void __iomem *base;
|
||||
void __iomem *host_mmio;
|
||||
int n_ports, i, rc;
|
||||
int is_sataii_tx4;
|
||||
|
||||
@@ -1062,7 +1058,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
|
||||
pcim_pin_device(pdev);
|
||||
if (rc)
|
||||
return rc;
|
||||
base = pcim_iomap_table(pdev)[PDC_MMIO_BAR];
|
||||
host_mmio = pcim_iomap_table(pdev)[PDC_MMIO_BAR];
|
||||
|
||||
/* determine port configuration and setup host */
|
||||
n_ports = 2;
|
||||
@@ -1072,7 +1068,7 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
|
||||
ppi[i] = pi;
|
||||
|
||||
if (pi->flags & PDC_FLAG_SATA_PATA) {
|
||||
u8 tmp = readb(base + PDC_FLASH_CTL+1);
|
||||
u8 tmp = readb(host_mmio + PDC_FLASH_CTL + 1);
|
||||
if (!(tmp & 0x80))
|
||||
ppi[n_ports++] = pi + 1;
|
||||
}
|
||||
@@ -1088,13 +1084,13 @@ static int pdc_ata_init_one(struct pci_dev *pdev,
|
||||
for (i = 0; i < host->n_ports; i++) {
|
||||
struct ata_port *ap = host->ports[i];
|
||||
unsigned int ata_no = pdc_port_no_to_ata_no(i, is_sataii_tx4);
|
||||
unsigned int port_offset = 0x200 + ata_no * 0x80;
|
||||
unsigned int ata_offset = 0x200 + ata_no * 0x80;
|
||||
unsigned int scr_offset = 0x400 + ata_no * 0x100;
|
||||
|
||||
pdc_ata_setup_port(ap, base + port_offset, base + scr_offset);
|
||||
pdc_ata_setup_port(ap, host_mmio + ata_offset, host_mmio + scr_offset);
|
||||
|
||||
ata_port_pbar_desc(ap, PDC_MMIO_BAR, -1, "mmio");
|
||||
ata_port_pbar_desc(ap, PDC_MMIO_BAR, port_offset, "port");
|
||||
ata_port_pbar_desc(ap, PDC_MMIO_BAR, ata_offset, "ata");
|
||||
}
|
||||
|
||||
/* initialize adapter */
|
||||
|
||||
@@ -899,14 +899,25 @@ static bool sil24_qc_fill_rtf(struct ata_queued_cmd *qc)
|
||||
|
||||
static void sil24_pmp_attach(struct ata_port *ap)
|
||||
{
|
||||
u32 *gscr = ap->link.device->gscr;
|
||||
|
||||
sil24_config_pmp(ap, 1);
|
||||
sil24_init_port(ap);
|
||||
|
||||
if (sata_pmp_gscr_vendor(gscr) == 0x11ab &&
|
||||
sata_pmp_gscr_devid(gscr) == 0x4140) {
|
||||
ata_port_printk(ap, KERN_INFO,
|
||||
"disabling NCQ support due to sil24-mv4140 quirk\n");
|
||||
ap->flags &= ~ATA_FLAG_NCQ;
|
||||
}
|
||||
}
|
||||
|
||||
static void sil24_pmp_detach(struct ata_port *ap)
|
||||
{
|
||||
sil24_init_port(ap);
|
||||
sil24_config_pmp(ap, 0);
|
||||
|
||||
ap->flags |= ATA_FLAG_NCQ;
|
||||
}
|
||||
|
||||
static int sil24_pmp_hardreset(struct ata_link *link, unsigned int *class,
|
||||
|
||||
+116
-28
@@ -759,6 +759,21 @@ static void device_remove_class_symlinks(struct device *dev)
|
||||
sysfs_remove_link(&dev->kobj, "subsystem");
|
||||
}
|
||||
|
||||
/**
|
||||
* dev_set_name - set a device name
|
||||
* @dev: device
|
||||
*/
|
||||
int dev_set_name(struct device *dev, const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
vsnprintf(dev->bus_id, sizeof(dev->bus_id), fmt, vargs);
|
||||
va_end(vargs);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dev_set_name);
|
||||
|
||||
/**
|
||||
* device_add - add device to device hierarchy.
|
||||
* @dev: device.
|
||||
@@ -1083,6 +1098,102 @@ static void device_create_release(struct device *dev)
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
/**
|
||||
* device_create_vargs - creates a device and registers it with sysfs
|
||||
* @class: pointer to the struct class that this device should be registered to
|
||||
* @parent: pointer to the parent struct device of this new device, if any
|
||||
* @devt: the dev_t for the char device to be added
|
||||
* @drvdata: the data to be added to the device for callbacks
|
||||
* @fmt: string for the device's name
|
||||
* @args: va_list for the device's name
|
||||
*
|
||||
* This function can be used by char device classes. A struct device
|
||||
* will be created in sysfs, registered to the specified class.
|
||||
*
|
||||
* A "dev" file will be created, showing the dev_t for the device, if
|
||||
* the dev_t is not 0,0.
|
||||
* If a pointer to a parent struct device is passed in, the newly created
|
||||
* struct device will be a child of that device in sysfs.
|
||||
* The pointer to the struct device will be returned from the call.
|
||||
* Any further sysfs files that might be required can be created using this
|
||||
* pointer.
|
||||
*
|
||||
* Note: the struct class passed to this function must have previously
|
||||
* been created with a call to class_create().
|
||||
*/
|
||||
struct device *device_create_vargs(struct class *class, struct device *parent,
|
||||
dev_t devt, void *drvdata, const char *fmt,
|
||||
va_list args)
|
||||
{
|
||||
struct device *dev = NULL;
|
||||
int retval = -ENODEV;
|
||||
|
||||
if (class == NULL || IS_ERR(class))
|
||||
goto error;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev->devt = devt;
|
||||
dev->class = class;
|
||||
dev->parent = parent;
|
||||
dev->release = device_create_release;
|
||||
dev_set_drvdata(dev, drvdata);
|
||||
|
||||
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
|
||||
retval = device_register(dev);
|
||||
if (retval)
|
||||
goto error;
|
||||
|
||||
return dev;
|
||||
|
||||
error:
|
||||
kfree(dev);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create_vargs);
|
||||
|
||||
/**
|
||||
* device_create_drvdata - creates a device and registers it with sysfs
|
||||
* @class: pointer to the struct class that this device should be registered to
|
||||
* @parent: pointer to the parent struct device of this new device, if any
|
||||
* @devt: the dev_t for the char device to be added
|
||||
* @drvdata: the data to be added to the device for callbacks
|
||||
* @fmt: string for the device's name
|
||||
*
|
||||
* This function can be used by char device classes. A struct device
|
||||
* will be created in sysfs, registered to the specified class.
|
||||
*
|
||||
* A "dev" file will be created, showing the dev_t for the device, if
|
||||
* the dev_t is not 0,0.
|
||||
* If a pointer to a parent struct device is passed in, the newly created
|
||||
* struct device will be a child of that device in sysfs.
|
||||
* The pointer to the struct device will be returned from the call.
|
||||
* Any further sysfs files that might be required can be created using this
|
||||
* pointer.
|
||||
*
|
||||
* Note: the struct class passed to this function must have previously
|
||||
* been created with a call to class_create().
|
||||
*/
|
||||
struct device *device_create_drvdata(struct class *class,
|
||||
struct device *parent,
|
||||
dev_t devt,
|
||||
void *drvdata,
|
||||
const char *fmt, ...)
|
||||
{
|
||||
va_list vargs;
|
||||
struct device *dev;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs);
|
||||
va_end(vargs);
|
||||
return dev;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create_drvdata);
|
||||
|
||||
/**
|
||||
* device_create - creates a device and registers it with sysfs
|
||||
* @class: pointer to the struct class that this device should be registered to
|
||||
@@ -1107,36 +1218,13 @@ static void device_create_release(struct device *dev)
|
||||
struct device *device_create(struct class *class, struct device *parent,
|
||||
dev_t devt, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
struct device *dev = NULL;
|
||||
int retval = -ENODEV;
|
||||
|
||||
if (class == NULL || IS_ERR(class))
|
||||
goto error;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev) {
|
||||
retval = -ENOMEM;
|
||||
goto error;
|
||||
}
|
||||
|
||||
dev->devt = devt;
|
||||
dev->class = class;
|
||||
dev->parent = parent;
|
||||
dev->release = device_create_release;
|
||||
|
||||
va_start(args, fmt);
|
||||
vsnprintf(dev->bus_id, BUS_ID_SIZE, fmt, args);
|
||||
va_end(args);
|
||||
retval = device_register(dev);
|
||||
if (retval)
|
||||
goto error;
|
||||
va_list vargs;
|
||||
struct device *dev;
|
||||
|
||||
va_start(vargs, fmt);
|
||||
dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs);
|
||||
va_end(vargs);
|
||||
return dev;
|
||||
|
||||
error:
|
||||
kfree(dev);
|
||||
return ERR_PTR(retval);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(device_create);
|
||||
|
||||
|
||||
@@ -418,7 +418,7 @@ void __suspend_report_result(const char *function, void *fn, int ret)
|
||||
{
|
||||
if (ret) {
|
||||
printk(KERN_ERR "%s(): ", function);
|
||||
print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn);
|
||||
print_fn_descriptor_symbol("%s returns ", fn);
|
||||
printk("%d\n", ret);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1714,10 +1714,10 @@ static int __init amiga_floppy_init(void)
|
||||
int i, ret;
|
||||
|
||||
if (!MACH_IS_AMIGA)
|
||||
return -ENXIO;
|
||||
return -ENODEV;
|
||||
|
||||
if (!AMIGAHW_PRESENT(AMI_FLOPPY))
|
||||
return -ENXIO;
|
||||
return -ENODEV;
|
||||
|
||||
if (register_blkdev(FLOPPY_MAJOR,"fd"))
|
||||
return -EBUSY;
|
||||
@@ -1755,7 +1755,7 @@ static int __init amiga_floppy_init(void)
|
||||
if (!floppy_queue)
|
||||
goto out_queue;
|
||||
|
||||
ret = -ENXIO;
|
||||
ret = -ENODEV;
|
||||
if (fd_probe_drives() < 1) /* No usable drives */
|
||||
goto out_probe;
|
||||
|
||||
|
||||
@@ -447,6 +447,7 @@ static struct brd_device *brd_alloc(int i)
|
||||
disk->fops = &brd_fops;
|
||||
disk->private_data = brd;
|
||||
disk->queue = brd->brd_queue;
|
||||
disk->flags |= GENHD_FL_SUPPRESS_PARTITION_INFO;
|
||||
sprintf(disk->disk_name, "ram%d", i);
|
||||
set_capacity(disk, rd_size * 2);
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* Authors: Dave Boutcher <boutcher@us.ibm.com>
|
||||
* Ryan Arnold <ryanarn@us.ibm.com>
|
||||
* Colin Devilbiss <devilbis@us.ibm.com>
|
||||
* Stephen Rothwell <sfr@au1.ibm.com>
|
||||
* Stephen Rothwell
|
||||
*
|
||||
* (C) Copyright 2000-2004 IBM Corporation
|
||||
*
|
||||
|
||||
@@ -260,6 +260,10 @@ static int virtblk_probe(struct virtio_device *vdev)
|
||||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_BARRIER))
|
||||
blk_queue_ordered(vblk->disk->queue, QUEUE_ORDERED_TAG, NULL);
|
||||
|
||||
/* If disk is read-only in the host, the guest should obey */
|
||||
if (virtio_has_feature(vdev, VIRTIO_BLK_F_RO))
|
||||
set_disk_ro(vblk->disk, 1);
|
||||
|
||||
/* Host must always specify the capacity. */
|
||||
vdev->config->get(vdev, offsetof(struct virtio_blk_config, capacity),
|
||||
&cap, sizeof(cap));
|
||||
@@ -311,6 +315,7 @@ static void virtblk_remove(struct virtio_device *vdev)
|
||||
/* Stop all the virtqueues. */
|
||||
vdev->config->reset(vdev);
|
||||
|
||||
del_gendisk(vblk->disk);
|
||||
blk_cleanup_queue(vblk->disk->queue);
|
||||
put_disk(vblk->disk);
|
||||
mempool_destroy(vblk->pool);
|
||||
@@ -325,7 +330,7 @@ static struct virtio_device_id id_table[] = {
|
||||
|
||||
static unsigned int features[] = {
|
||||
VIRTIO_BLK_F_BARRIER, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX,
|
||||
VIRTIO_BLK_F_GEOMETRY,
|
||||
VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_RO,
|
||||
};
|
||||
|
||||
static struct virtio_driver virtio_blk = {
|
||||
|
||||
@@ -332,7 +332,7 @@ z2_init(void)
|
||||
int ret;
|
||||
|
||||
if (!MACH_IS_AMIGA)
|
||||
return -ENXIO;
|
||||
return -ENODEV;
|
||||
|
||||
ret = -EBUSY;
|
||||
if (register_blkdev(Z2RAM_MAJOR, DEVICE_NAME))
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Authors: Dave Boutcher <boutcher@us.ibm.com>
|
||||
* Ryan Arnold <ryanarn@us.ibm.com>
|
||||
* Colin Devilbiss <devilbis@us.ibm.com>
|
||||
* Stephen Rothwell <sfr@au1.ibm.com>
|
||||
* Stephen Rothwell
|
||||
*
|
||||
* (C) Copyright 2000-2004 IBM Corporation
|
||||
*
|
||||
|
||||
@@ -471,7 +471,6 @@ struct drm_irq_busid {
|
||||
enum drm_vblank_seq_type {
|
||||
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
|
||||
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
|
||||
_DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
|
||||
_DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
|
||||
_DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
|
||||
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking */
|
||||
@@ -504,21 +503,6 @@ union drm_wait_vblank {
|
||||
struct drm_wait_vblank_reply reply;
|
||||
};
|
||||
|
||||
enum drm_modeset_ctl_cmd {
|
||||
_DRM_PRE_MODESET = 1,
|
||||
_DRM_POST_MODESET = 2,
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_MODESET_CTL ioctl argument type
|
||||
*
|
||||
* \sa drmModesetCtl().
|
||||
*/
|
||||
struct drm_modeset_ctl {
|
||||
unsigned long arg;
|
||||
enum drm_modeset_ctl_cmd cmd;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ENABLE ioctl argument type.
|
||||
*
|
||||
@@ -603,7 +587,6 @@ struct drm_set_version {
|
||||
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
|
||||
#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
|
||||
#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
|
||||
#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
|
||||
|
||||
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
|
||||
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
|
||||
|
||||
+17
-74
@@ -100,8 +100,10 @@ struct drm_device;
|
||||
#define DRIVER_HAVE_DMA 0x20
|
||||
#define DRIVER_HAVE_IRQ 0x40
|
||||
#define DRIVER_IRQ_SHARED 0x80
|
||||
#define DRIVER_IRQ_VBL 0x100
|
||||
#define DRIVER_DMA_QUEUE 0x200
|
||||
#define DRIVER_FB_DMA 0x400
|
||||
#define DRIVER_IRQ_VBL2 0x800
|
||||
|
||||
/***********************************************************************/
|
||||
/** \name Begin the DRM... */
|
||||
@@ -577,52 +579,10 @@ struct drm_driver {
|
||||
int (*context_dtor) (struct drm_device *dev, int context);
|
||||
int (*kernel_context_switch) (struct drm_device *dev, int old,
|
||||
int new);
|
||||
void (*kernel_context_switch_unlock) (struct drm_device * dev);
|
||||
/**
|
||||
* get_vblank_counter - get raw hardware vblank counter
|
||||
* @dev: DRM device
|
||||
* @crtc: counter to fetch
|
||||
*
|
||||
* Driver callback for fetching a raw hardware vblank counter
|
||||
* for @crtc. If a device doesn't have a hardware counter, the
|
||||
* driver can simply return the value of drm_vblank_count and
|
||||
* make the enable_vblank() and disable_vblank() hooks into no-ops,
|
||||
* leaving interrupts enabled at all times.
|
||||
*
|
||||
* Wraparound handling and loss of events due to modesetting is dealt
|
||||
* with in the DRM core code.
|
||||
*
|
||||
* RETURNS
|
||||
* Raw vblank counter value.
|
||||
*/
|
||||
u32 (*get_vblank_counter) (struct drm_device *dev, int crtc);
|
||||
|
||||
/**
|
||||
* enable_vblank - enable vblank interrupt events
|
||||
* @dev: DRM device
|
||||
* @crtc: which irq to enable
|
||||
*
|
||||
* Enable vblank interrupts for @crtc. If the device doesn't have
|
||||
* a hardware vblank counter, this routine should be a no-op, since
|
||||
* interrupts will have to stay on to keep the count accurate.
|
||||
*
|
||||
* RETURNS
|
||||
* Zero on success, appropriate errno if the given @crtc's vblank
|
||||
* interrupt cannot be enabled.
|
||||
*/
|
||||
int (*enable_vblank) (struct drm_device *dev, int crtc);
|
||||
|
||||
/**
|
||||
* disable_vblank - disable vblank interrupt events
|
||||
* @dev: DRM device
|
||||
* @crtc: which irq to enable
|
||||
*
|
||||
* Disable vblank interrupts for @crtc. If the device doesn't have
|
||||
* a hardware vblank counter, this routine should be a no-op, since
|
||||
* interrupts will have to stay on to keep the count accurate.
|
||||
*/
|
||||
void (*disable_vblank) (struct drm_device *dev, int crtc);
|
||||
int (*dri_library_name) (struct drm_device *dev, char * buf);
|
||||
void (*kernel_context_switch_unlock) (struct drm_device *dev);
|
||||
int (*vblank_wait) (struct drm_device *dev, unsigned int *sequence);
|
||||
int (*vblank_wait2) (struct drm_device *dev, unsigned int *sequence);
|
||||
int (*dri_library_name) (struct drm_device *dev, char *buf);
|
||||
|
||||
/**
|
||||
* Called by \c drm_device_is_agp. Typically used to determine if a
|
||||
@@ -641,7 +601,7 @@ struct drm_driver {
|
||||
|
||||
irqreturn_t(*irq_handler) (DRM_IRQ_ARGS);
|
||||
void (*irq_preinstall) (struct drm_device *dev);
|
||||
int (*irq_postinstall) (struct drm_device *dev);
|
||||
void (*irq_postinstall) (struct drm_device *dev);
|
||||
void (*irq_uninstall) (struct drm_device *dev);
|
||||
void (*reclaim_buffers) (struct drm_device *dev,
|
||||
struct drm_file * file_priv);
|
||||
@@ -770,21 +730,13 @@ struct drm_device {
|
||||
/** \name VBLANK IRQ support */
|
||||
/*@{ */
|
||||
|
||||
wait_queue_head_t *vbl_queue; /**< VBLANK wait queue */
|
||||
atomic_t *_vblank_count; /**< number of VBLANK interrupts (driver must alloc the right number of counters) */
|
||||
wait_queue_head_t vbl_queue; /**< VBLANK wait queue */
|
||||
atomic_t vbl_received;
|
||||
atomic_t vbl_received2; /**< number of secondary VBLANK interrupts */
|
||||
spinlock_t vbl_lock;
|
||||
struct list_head *vbl_sigs; /**< signal list to send on VBLANK */
|
||||
atomic_t vbl_signal_pending; /* number of signals pending on all crtcs*/
|
||||
atomic_t *vblank_refcount; /* number of users of vblank interrupts per crtc */
|
||||
u32 *last_vblank; /* protected by dev->vbl_lock, used */
|
||||
/* for wraparound handling */
|
||||
u32 *vblank_offset; /* used to track how many vblanks */
|
||||
int *vblank_enabled; /* so we don't call enable more than
|
||||
once per disable */
|
||||
u32 *vblank_premodeset; /* were lost during modeset */
|
||||
struct timer_list vblank_disable_timer;
|
||||
|
||||
unsigned long max_vblank_count; /**< size of vblank counter register */
|
||||
struct list_head vbl_sigs; /**< signal list to send on VBLANK */
|
||||
struct list_head vbl_sigs2; /**< signals to send on secondary VBLANK */
|
||||
unsigned int vbl_pending;
|
||||
spinlock_t tasklet_lock; /**< For drm_locked_tasklet */
|
||||
void (*locked_tasklet_func)(struct drm_device *dev);
|
||||
|
||||
@@ -804,7 +756,6 @@ struct drm_device {
|
||||
#ifdef __alpha__
|
||||
struct pci_controller *hose;
|
||||
#endif
|
||||
int num_crtcs; /**< Number of CRTCs on this device */
|
||||
struct drm_sg_mem *sg; /**< Scatter gather memory */
|
||||
void *dev_private; /**< device private data */
|
||||
struct drm_sigdata sigdata; /**< For block_all_signals */
|
||||
@@ -1039,19 +990,11 @@ extern void drm_driver_irq_preinstall(struct drm_device *dev);
|
||||
extern void drm_driver_irq_postinstall(struct drm_device *dev);
|
||||
extern void drm_driver_irq_uninstall(struct drm_device *dev);
|
||||
|
||||
extern int drm_vblank_init(struct drm_device *dev, int num_crtcs);
|
||||
extern int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *filp);
|
||||
extern int drm_vblank_wait(struct drm_device * dev, unsigned int *vbl_seq);
|
||||
extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
|
||||
extern u32 drm_vblank_count(struct drm_device *dev, int crtc);
|
||||
extern void drm_update_vblank_count(struct drm_device *dev, int crtc);
|
||||
extern void drm_handle_vblank(struct drm_device *dev, int crtc);
|
||||
extern int drm_vblank_get(struct drm_device *dev, int crtc);
|
||||
extern void drm_vblank_put(struct drm_device *dev, int crtc);
|
||||
|
||||
/* Modesetting support */
|
||||
extern int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
extern int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int drm_vblank_wait(struct drm_device *dev, unsigned int *vbl_seq);
|
||||
extern void drm_vbl_send_signals(struct drm_device *dev);
|
||||
extern void drm_locked_tasklet(struct drm_device *dev, void(*func)(struct drm_device*));
|
||||
|
||||
/* AGP/GART support (drm_agpsupport.h) */
|
||||
extern struct drm_agp_head *drm_agp_init(struct drm_device *dev);
|
||||
|
||||
@@ -323,7 +323,6 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
struct drm_file *file_priv = filp->private_data;
|
||||
struct drm_device *dev = file_priv->minor->dev;
|
||||
int retcode = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
lock_kernel();
|
||||
|
||||
@@ -355,11 +354,9 @@ int drm_release(struct inode *inode, struct file *filp)
|
||||
*/
|
||||
|
||||
do{
|
||||
spin_lock_irqsave(&dev->lock.spinlock,
|
||||
irqflags);
|
||||
spin_lock_bh(&dev->lock.spinlock);
|
||||
locked = dev->lock.idle_has_lock;
|
||||
spin_unlock_irqrestore(&dev->lock.spinlock,
|
||||
irqflags);
|
||||
spin_unlock_bh(&dev->lock.spinlock);
|
||||
if (locked)
|
||||
break;
|
||||
schedule();
|
||||
|
||||
+55
-324
@@ -71,117 +71,6 @@ int drm_irq_by_busid(struct drm_device *dev, void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vblank_disable_fn(unsigned long arg)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *)arg;
|
||||
unsigned long irqflags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dev->num_crtcs; i++) {
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
if (atomic_read(&dev->vblank_refcount[i]) == 0 &&
|
||||
dev->vblank_enabled[i]) {
|
||||
dev->driver->disable_vblank(dev, i);
|
||||
dev->vblank_enabled[i] = 0;
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
}
|
||||
}
|
||||
|
||||
static void drm_vblank_cleanup(struct drm_device *dev)
|
||||
{
|
||||
/* Bail if the driver didn't call drm_vblank_init() */
|
||||
if (dev->num_crtcs == 0)
|
||||
return;
|
||||
|
||||
del_timer(&dev->vblank_disable_timer);
|
||||
|
||||
vblank_disable_fn((unsigned long)dev);
|
||||
|
||||
drm_free(dev->vbl_queue, sizeof(*dev->vbl_queue) * dev->num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->vbl_sigs, sizeof(*dev->vbl_sigs) * dev->num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->_vblank_count, sizeof(*dev->_vblank_count) *
|
||||
dev->num_crtcs, DRM_MEM_DRIVER);
|
||||
drm_free(dev->vblank_refcount, sizeof(*dev->vblank_refcount) *
|
||||
dev->num_crtcs, DRM_MEM_DRIVER);
|
||||
drm_free(dev->vblank_enabled, sizeof(*dev->vblank_enabled) *
|
||||
dev->num_crtcs, DRM_MEM_DRIVER);
|
||||
drm_free(dev->last_vblank, sizeof(*dev->last_vblank) * dev->num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
drm_free(dev->vblank_premodeset, sizeof(*dev->vblank_premodeset) *
|
||||
dev->num_crtcs, DRM_MEM_DRIVER);
|
||||
drm_free(dev->vblank_offset, sizeof(*dev->vblank_offset) * dev->num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
dev->num_crtcs = 0;
|
||||
}
|
||||
|
||||
int drm_vblank_init(struct drm_device *dev, int num_crtcs)
|
||||
{
|
||||
int i, ret = -ENOMEM;
|
||||
|
||||
setup_timer(&dev->vblank_disable_timer, vblank_disable_fn,
|
||||
(unsigned long)dev);
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
atomic_set(&dev->vbl_signal_pending, 0);
|
||||
dev->num_crtcs = num_crtcs;
|
||||
|
||||
dev->vbl_queue = drm_alloc(sizeof(wait_queue_head_t) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vbl_queue)
|
||||
goto err;
|
||||
|
||||
dev->vbl_sigs = drm_alloc(sizeof(struct list_head) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vbl_sigs)
|
||||
goto err;
|
||||
|
||||
dev->_vblank_count = drm_alloc(sizeof(atomic_t) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->_vblank_count)
|
||||
goto err;
|
||||
|
||||
dev->vblank_refcount = drm_alloc(sizeof(atomic_t) * num_crtcs,
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vblank_refcount)
|
||||
goto err;
|
||||
|
||||
dev->vblank_enabled = drm_calloc(num_crtcs, sizeof(int),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vblank_enabled)
|
||||
goto err;
|
||||
|
||||
dev->last_vblank = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
|
||||
if (!dev->last_vblank)
|
||||
goto err;
|
||||
|
||||
dev->vblank_premodeset = drm_calloc(num_crtcs, sizeof(u32),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!dev->vblank_premodeset)
|
||||
goto err;
|
||||
|
||||
dev->vblank_offset = drm_calloc(num_crtcs, sizeof(u32), DRM_MEM_DRIVER);
|
||||
if (!dev->vblank_offset)
|
||||
goto err;
|
||||
|
||||
/* Zero per-crtc vblank stuff */
|
||||
for (i = 0; i < num_crtcs; i++) {
|
||||
init_waitqueue_head(&dev->vbl_queue[i]);
|
||||
INIT_LIST_HEAD(&dev->vbl_sigs[i]);
|
||||
atomic_set(&dev->_vblank_count[i], 0);
|
||||
atomic_set(&dev->vblank_refcount[i], 0);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
drm_vblank_cleanup(dev);
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_init);
|
||||
|
||||
/**
|
||||
* Install IRQ handler.
|
||||
*
|
||||
@@ -220,6 +109,17 @@ static int drm_irq_install(struct drm_device * dev)
|
||||
|
||||
DRM_DEBUG("irq=%d\n", dev->irq);
|
||||
|
||||
if (drm_core_check_feature(dev, DRIVER_IRQ_VBL)) {
|
||||
init_waitqueue_head(&dev->vbl_queue);
|
||||
|
||||
spin_lock_init(&dev->vbl_lock);
|
||||
|
||||
INIT_LIST_HEAD(&dev->vbl_sigs);
|
||||
INIT_LIST_HEAD(&dev->vbl_sigs2);
|
||||
|
||||
dev->vbl_pending = 0;
|
||||
}
|
||||
|
||||
/* Before installing handler */
|
||||
dev->driver->irq_preinstall(dev);
|
||||
|
||||
@@ -237,14 +137,9 @@ static int drm_irq_install(struct drm_device * dev)
|
||||
}
|
||||
|
||||
/* After installing handler */
|
||||
ret = dev->driver->irq_postinstall(dev);
|
||||
if (ret < 0) {
|
||||
mutex_lock(&dev->struct_mutex);
|
||||
dev->irq_enabled = 0;
|
||||
mutex_unlock(&dev->struct_mutex);
|
||||
}
|
||||
dev->driver->irq_postinstall(dev);
|
||||
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,8 +170,6 @@ int drm_irq_uninstall(struct drm_device * dev)
|
||||
|
||||
free_irq(dev->irq, dev);
|
||||
|
||||
drm_vblank_cleanup(dev);
|
||||
|
||||
dev->locked_tasklet_func = NULL;
|
||||
|
||||
return 0;
|
||||
@@ -320,148 +213,6 @@ int drm_control(struct drm_device *dev, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_vblank_count - retrieve "cooked" vblank counter value
|
||||
* @dev: DRM device
|
||||
* @crtc: which counter to retrieve
|
||||
*
|
||||
* Fetches the "cooked" vblank count value that represents the number of
|
||||
* vblank events since the system was booted, including lost events due to
|
||||
* modesetting activity.
|
||||
*/
|
||||
u32 drm_vblank_count(struct drm_device *dev, int crtc)
|
||||
{
|
||||
return atomic_read(&dev->_vblank_count[crtc]) +
|
||||
dev->vblank_offset[crtc];
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_count);
|
||||
|
||||
/**
|
||||
* drm_update_vblank_count - update the master vblank counter
|
||||
* @dev: DRM device
|
||||
* @crtc: counter to update
|
||||
*
|
||||
* Call back into the driver to update the appropriate vblank counter
|
||||
* (specified by @crtc). Deal with wraparound, if it occurred, and
|
||||
* update the last read value so we can deal with wraparound on the next
|
||||
* call if necessary.
|
||||
*/
|
||||
void drm_update_vblank_count(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
u32 cur_vblank, diff;
|
||||
|
||||
/*
|
||||
* Interrupts were disabled prior to this call, so deal with counter
|
||||
* wrap if needed.
|
||||
* NOTE! It's possible we lost a full dev->max_vblank_count events
|
||||
* here if the register is small or we had vblank interrupts off for
|
||||
* a long time.
|
||||
*/
|
||||
cur_vblank = dev->driver->get_vblank_counter(dev, crtc);
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
if (cur_vblank < dev->last_vblank[crtc]) {
|
||||
diff = dev->max_vblank_count -
|
||||
dev->last_vblank[crtc];
|
||||
diff += cur_vblank;
|
||||
} else {
|
||||
diff = cur_vblank - dev->last_vblank[crtc];
|
||||
}
|
||||
dev->last_vblank[crtc] = cur_vblank;
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
atomic_add(diff, &dev->_vblank_count[crtc]);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_update_vblank_count);
|
||||
|
||||
/**
|
||||
* drm_vblank_get - get a reference count on vblank events
|
||||
* @dev: DRM device
|
||||
* @crtc: which CRTC to own
|
||||
*
|
||||
* Acquire a reference count on vblank events to avoid having them disabled
|
||||
* while in use. Note callers will probably want to update the master counter
|
||||
* using drm_update_vblank_count() above before calling this routine so that
|
||||
* wakeups occur on the right vblank event.
|
||||
*
|
||||
* RETURNS
|
||||
* Zero on success, nonzero on failure.
|
||||
*/
|
||||
int drm_vblank_get(struct drm_device *dev, int crtc)
|
||||
{
|
||||
unsigned long irqflags;
|
||||
int ret = 0;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
/* Going from 0->1 means we have to enable interrupts again */
|
||||
if (atomic_add_return(1, &dev->vblank_refcount[crtc]) == 1 &&
|
||||
!dev->vblank_enabled[crtc]) {
|
||||
ret = dev->driver->enable_vblank(dev, crtc);
|
||||
if (ret)
|
||||
atomic_dec(&dev->vblank_refcount[crtc]);
|
||||
else
|
||||
dev->vblank_enabled[crtc] = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_get);
|
||||
|
||||
/**
|
||||
* drm_vblank_put - give up ownership of vblank events
|
||||
* @dev: DRM device
|
||||
* @crtc: which counter to give up
|
||||
*
|
||||
* Release ownership of a given vblank counter, turning off interrupts
|
||||
* if possible.
|
||||
*/
|
||||
void drm_vblank_put(struct drm_device *dev, int crtc)
|
||||
{
|
||||
/* Last user schedules interrupt disable */
|
||||
if (atomic_dec_and_test(&dev->vblank_refcount[crtc]))
|
||||
mod_timer(&dev->vblank_disable_timer, jiffies + 5*DRM_HZ);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_vblank_put);
|
||||
|
||||
/**
|
||||
* drm_modeset_ctl - handle vblank event counter changes across mode switch
|
||||
* @DRM_IOCTL_ARGS: standard ioctl arguments
|
||||
*
|
||||
* Applications should call the %_DRM_PRE_MODESET and %_DRM_POST_MODESET
|
||||
* ioctls around modesetting so that any lost vblank events are accounted for.
|
||||
*/
|
||||
int drm_modeset_ctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
struct drm_modeset_ctl *modeset = data;
|
||||
int crtc, ret = 0;
|
||||
u32 new;
|
||||
|
||||
crtc = modeset->arg;
|
||||
if (crtc >= dev->num_crtcs) {
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (modeset->cmd) {
|
||||
case _DRM_PRE_MODESET:
|
||||
dev->vblank_premodeset[crtc] =
|
||||
dev->driver->get_vblank_counter(dev, crtc);
|
||||
break;
|
||||
case _DRM_POST_MODESET:
|
||||
new = dev->driver->get_vblank_counter(dev, crtc);
|
||||
dev->vblank_offset[crtc] = dev->vblank_premodeset[crtc] - new;
|
||||
break;
|
||||
default:
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for VBLANK.
|
||||
*
|
||||
@@ -481,13 +232,12 @@ out:
|
||||
*
|
||||
* If a signal is not requested, then calls vblank_wait().
|
||||
*/
|
||||
int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
int drm_wait_vblank(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
{
|
||||
union drm_wait_vblank *vblwait = data;
|
||||
struct timeval now;
|
||||
int ret = 0;
|
||||
unsigned int flags, seq, crtc;
|
||||
unsigned int flags, seq;
|
||||
|
||||
if ((!dev->irq) || (!dev->irq_enabled))
|
||||
return -EINVAL;
|
||||
@@ -501,13 +251,13 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
|
||||
crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
|
||||
|
||||
if (crtc >= dev->num_crtcs)
|
||||
if (!drm_core_check_feature(dev, (flags & _DRM_VBLANK_SECONDARY) ?
|
||||
DRIVER_IRQ_VBL2 : DRIVER_IRQ_VBL))
|
||||
return -EINVAL;
|
||||
|
||||
drm_update_vblank_count(dev, crtc);
|
||||
seq = drm_vblank_count(dev, crtc);
|
||||
seq = atomic_read((flags & _DRM_VBLANK_SECONDARY) ? &dev->vbl_received2
|
||||
: &dev->vbl_received);
|
||||
|
||||
switch (vblwait->request.type & _DRM_VBLANK_TYPES_MASK) {
|
||||
case _DRM_VBLANK_RELATIVE:
|
||||
@@ -526,7 +276,8 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
|
||||
if (flags & _DRM_VBLANK_SIGNAL) {
|
||||
unsigned long irqflags;
|
||||
struct list_head *vbl_sigs = &dev->vbl_sigs[crtc];
|
||||
struct list_head *vbl_sigs = (flags & _DRM_VBLANK_SECONDARY)
|
||||
? &dev->vbl_sigs2 : &dev->vbl_sigs;
|
||||
struct drm_vbl_sig *vbl_sig;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, irqflags);
|
||||
@@ -547,26 +298,22 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
if (atomic_read(&dev->vbl_signal_pending) >= 100) {
|
||||
if (dev->vbl_pending >= 100) {
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
dev->vbl_pending++;
|
||||
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
|
||||
|
||||
vbl_sig = drm_calloc(1, sizeof(struct drm_vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
if (!vbl_sig)
|
||||
if (!
|
||||
(vbl_sig =
|
||||
drm_alloc(sizeof(struct drm_vbl_sig), DRM_MEM_DRIVER))) {
|
||||
return -ENOMEM;
|
||||
|
||||
ret = drm_vblank_get(dev, crtc);
|
||||
if (ret) {
|
||||
drm_free(vbl_sig, sizeof(struct drm_vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
atomic_inc(&dev->vbl_signal_pending);
|
||||
memset((void *)vbl_sig, 0, sizeof(*vbl_sig));
|
||||
|
||||
vbl_sig->sequence = vblwait->request.sequence;
|
||||
vbl_sig->info.si_signo = vblwait->request.signal;
|
||||
@@ -580,20 +327,17 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
|
||||
vblwait->reply.sequence = seq;
|
||||
} else {
|
||||
unsigned long cur_vblank;
|
||||
if (flags & _DRM_VBLANK_SECONDARY) {
|
||||
if (dev->driver->vblank_wait2)
|
||||
ret = dev->driver->vblank_wait2(dev, &vblwait->request.sequence);
|
||||
} else if (dev->driver->vblank_wait)
|
||||
ret =
|
||||
dev->driver->vblank_wait(dev,
|
||||
&vblwait->request.sequence);
|
||||
|
||||
ret = drm_vblank_get(dev, crtc);
|
||||
if (ret)
|
||||
return ret;
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue[crtc], 3 * DRM_HZ,
|
||||
(((cur_vblank = drm_vblank_count(dev, crtc))
|
||||
- vblwait->request.sequence) <= (1 << 23)));
|
||||
drm_vblank_put(dev, crtc);
|
||||
do_gettimeofday(&now);
|
||||
|
||||
vblwait->reply.tval_sec = now.tv_sec;
|
||||
vblwait->reply.tval_usec = now.tv_usec;
|
||||
vblwait->reply.sequence = cur_vblank;
|
||||
}
|
||||
|
||||
done:
|
||||
@@ -604,57 +348,44 @@ int drm_wait_vblank(struct drm_device *dev, void *data,
|
||||
* Send the VBLANK signals.
|
||||
*
|
||||
* \param dev DRM device.
|
||||
* \param crtc CRTC where the vblank event occurred
|
||||
*
|
||||
* Sends a signal for each task in drm_device::vbl_sigs and empties the list.
|
||||
*
|
||||
* If a signal is not requested, then calls vblank_wait().
|
||||
*/
|
||||
static void drm_vbl_send_signals(struct drm_device * dev, int crtc)
|
||||
void drm_vbl_send_signals(struct drm_device * dev)
|
||||
{
|
||||
struct drm_vbl_sig *vbl_sig, *tmp;
|
||||
struct list_head *vbl_sigs;
|
||||
unsigned int vbl_seq;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&dev->vbl_lock, flags);
|
||||
|
||||
vbl_sigs = &dev->vbl_sigs[crtc];
|
||||
vbl_seq = drm_vblank_count(dev, crtc);
|
||||
for (i = 0; i < 2; i++) {
|
||||
struct drm_vbl_sig *vbl_sig, *tmp;
|
||||
struct list_head *vbl_sigs = i ? &dev->vbl_sigs2 : &dev->vbl_sigs;
|
||||
unsigned int vbl_seq = atomic_read(i ? &dev->vbl_received2 :
|
||||
&dev->vbl_received);
|
||||
|
||||
list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
|
||||
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
|
||||
vbl_sig->info.si_code = vbl_seq;
|
||||
send_sig_info(vbl_sig->info.si_signo,
|
||||
&vbl_sig->info, vbl_sig->task);
|
||||
list_for_each_entry_safe(vbl_sig, tmp, vbl_sigs, head) {
|
||||
if ((vbl_seq - vbl_sig->sequence) <= (1 << 23)) {
|
||||
vbl_sig->info.si_code = vbl_seq;
|
||||
send_sig_info(vbl_sig->info.si_signo,
|
||||
&vbl_sig->info, vbl_sig->task);
|
||||
|
||||
list_del(&vbl_sig->head);
|
||||
list_del(&vbl_sig->head);
|
||||
|
||||
drm_free(vbl_sig, sizeof(*vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
atomic_dec(&dev->vbl_signal_pending);
|
||||
drm_vblank_put(dev, crtc);
|
||||
}
|
||||
drm_free(vbl_sig, sizeof(*vbl_sig),
|
||||
DRM_MEM_DRIVER);
|
||||
|
||||
dev->vbl_pending--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock_irqrestore(&dev->vbl_lock, flags);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_handle_vblank - handle a vblank event
|
||||
* @dev: DRM device
|
||||
* @crtc: where this event occurred
|
||||
*
|
||||
* Drivers should call this routine in their vblank interrupt handlers to
|
||||
* update the vblank counter and send any signals that may be pending.
|
||||
*/
|
||||
void drm_handle_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
drm_update_vblank_count(dev, crtc);
|
||||
DRM_WAKEUP(&dev->vbl_queue[crtc]);
|
||||
drm_vbl_send_signals(dev, crtc);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_handle_vblank);
|
||||
EXPORT_SYMBOL(drm_vbl_send_signals);
|
||||
|
||||
/**
|
||||
* Tasklet wrapper function.
|
||||
|
||||
+15
-20
@@ -53,7 +53,6 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
DECLARE_WAITQUEUE(entry, current);
|
||||
struct drm_lock *lock = data;
|
||||
int ret = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
++file_priv->lock_count;
|
||||
|
||||
@@ -72,9 +71,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
return -EINVAL;
|
||||
|
||||
add_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
spin_lock_irqsave(&dev->lock.spinlock, irqflags);
|
||||
spin_lock_bh(&dev->lock.spinlock);
|
||||
dev->lock.user_waiters++;
|
||||
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
|
||||
spin_unlock_bh(&dev->lock.spinlock);
|
||||
for (;;) {
|
||||
__set_current_state(TASK_INTERRUPTIBLE);
|
||||
if (!dev->lock.hw_lock) {
|
||||
@@ -96,9 +95,9 @@ int drm_lock(struct drm_device *dev, void *data, struct drm_file *file_priv)
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_lock_irqsave(&dev->lock.spinlock, irqflags);
|
||||
spin_lock_bh(&dev->lock.spinlock);
|
||||
dev->lock.user_waiters--;
|
||||
spin_unlock_irqrestore(&dev->lock.spinlock, irqflags);
|
||||
spin_unlock_bh(&dev->lock.spinlock);
|
||||
__set_current_state(TASK_RUNNING);
|
||||
remove_wait_queue(&dev->lock.lock_queue, &entry);
|
||||
|
||||
@@ -199,9 +198,8 @@ int drm_lock_take(struct drm_lock_data *lock_data,
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
spin_lock_bh(&lock_data->spinlock);
|
||||
do {
|
||||
old = *lock;
|
||||
if (old & _DRM_LOCK_HELD)
|
||||
@@ -213,7 +211,7 @@ int drm_lock_take(struct drm_lock_data *lock_data,
|
||||
}
|
||||
prev = cmpxchg(lock, old, new);
|
||||
} while (prev != old);
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
spin_unlock_bh(&lock_data->spinlock);
|
||||
|
||||
if (_DRM_LOCKING_CONTEXT(old) == context) {
|
||||
if (old & _DRM_LOCK_HELD) {
|
||||
@@ -274,16 +272,15 @@ int drm_lock_free(struct drm_lock_data *lock_data, unsigned int context)
|
||||
{
|
||||
unsigned int old, new, prev;
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
spin_lock_bh(&lock_data->spinlock);
|
||||
if (lock_data->kernel_waiters != 0) {
|
||||
drm_lock_transfer(lock_data, 0);
|
||||
lock_data->idle_has_lock = 1;
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
spin_unlock_bh(&lock_data->spinlock);
|
||||
return 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
spin_unlock_bh(&lock_data->spinlock);
|
||||
|
||||
do {
|
||||
old = *lock;
|
||||
@@ -347,20 +344,19 @@ static int drm_notifier(void *priv)
|
||||
void drm_idlelock_take(struct drm_lock_data *lock_data)
|
||||
{
|
||||
int ret = 0;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
spin_lock_bh(&lock_data->spinlock);
|
||||
lock_data->kernel_waiters++;
|
||||
if (!lock_data->idle_has_lock) {
|
||||
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
spin_unlock_bh(&lock_data->spinlock);
|
||||
ret = drm_lock_take(lock_data, DRM_KERNEL_CONTEXT);
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
spin_lock_bh(&lock_data->spinlock);
|
||||
|
||||
if (ret == 1)
|
||||
lock_data->idle_has_lock = 1;
|
||||
}
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
spin_unlock_bh(&lock_data->spinlock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_idlelock_take);
|
||||
|
||||
@@ -368,9 +364,8 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
|
||||
{
|
||||
unsigned int old, prev;
|
||||
volatile unsigned int *lock = &lock_data->hw_lock->lock;
|
||||
unsigned long irqflags;
|
||||
|
||||
spin_lock_irqsave(&lock_data->spinlock, irqflags);
|
||||
spin_lock_bh(&lock_data->spinlock);
|
||||
if (--lock_data->kernel_waiters == 0) {
|
||||
if (lock_data->idle_has_lock) {
|
||||
do {
|
||||
@@ -381,7 +376,7 @@ void drm_idlelock_release(struct drm_lock_data *lock_data)
|
||||
lock_data->idle_has_lock = 0;
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&lock_data->spinlock, irqflags);
|
||||
spin_unlock_bh(&lock_data->spinlock);
|
||||
}
|
||||
EXPORT_SYMBOL(drm_idlelock_release);
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ static int drm_sysfs_suspend(struct device *dev, pm_message_t state)
|
||||
struct drm_minor *drm_minor = to_drm_minor(dev);
|
||||
struct drm_device *drm_dev = drm_minor->dev;
|
||||
|
||||
printk(KERN_ERR "%s\n", __func__);
|
||||
|
||||
if (drm_dev->driver->suspend)
|
||||
return drm_dev->driver->suspend(drm_dev, state);
|
||||
|
||||
|
||||
+43
-121
@@ -415,13 +415,10 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
|
||||
if (++dev_priv->counter > BREADCRUMB_MASK) {
|
||||
dev_priv->counter = 1;
|
||||
DRM_DEBUG("Breadcrumb counter wrapped around\n");
|
||||
}
|
||||
dev_priv->sarea_priv->last_enqueue = ++dev_priv->counter;
|
||||
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter;
|
||||
if (dev_priv->counter > 0x7FFFFFFFUL)
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter = 1;
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
@@ -431,26 +428,6 @@ static void i915_emit_breadcrumb(struct drm_device *dev)
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
int i915_emit_mi_flush(struct drm_device *dev, uint32_t flush)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
uint32_t flush_cmd = CMD_MI_FLUSH;
|
||||
RING_LOCALS;
|
||||
|
||||
flush_cmd |= flush;
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(flush_cmd);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_dispatch_cmdbuffer(struct drm_device * dev,
|
||||
drm_i915_cmdbuffer_t * cmd)
|
||||
{
|
||||
@@ -534,74 +511,52 @@ static int i915_dispatch_batchbuffer(struct drm_device * dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void i915_do_dispatch_flip(struct drm_device * dev, int plane, int sync)
|
||||
static int i915_dispatch_flip(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
u32 num_pages, current_page, next_page, dspbase;
|
||||
int shift = 2 * plane, x, y;
|
||||
RING_LOCALS;
|
||||
|
||||
/* Calculate display base offset */
|
||||
num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
|
||||
current_page = (dev_priv->sarea_priv->pf_current_page >> shift) & 0x3;
|
||||
next_page = (current_page + 1) % num_pages;
|
||||
DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
|
||||
__FUNCTION__,
|
||||
dev_priv->current_page,
|
||||
dev_priv->sarea_priv->pf_current_page);
|
||||
|
||||
switch (next_page) {
|
||||
default:
|
||||
case 0:
|
||||
dspbase = dev_priv->sarea_priv->front_offset;
|
||||
break;
|
||||
case 1:
|
||||
dspbase = dev_priv->sarea_priv->back_offset;
|
||||
break;
|
||||
case 2:
|
||||
dspbase = dev_priv->sarea_priv->third_offset;
|
||||
break;
|
||||
}
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
if (plane == 0) {
|
||||
x = dev_priv->sarea_priv->planeA_x;
|
||||
y = dev_priv->sarea_priv->planeA_y;
|
||||
} else {
|
||||
x = dev_priv->sarea_priv->planeB_x;
|
||||
y = dev_priv->sarea_priv->planeB_y;
|
||||
}
|
||||
|
||||
dspbase += (y * dev_priv->sarea_priv->pitch + x) * dev_priv->cpp;
|
||||
|
||||
DRM_DEBUG("plane=%d current_page=%d dspbase=0x%x\n", plane, current_page,
|
||||
dspbase);
|
||||
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(sync ? 0 :
|
||||
(MI_WAIT_FOR_EVENT | (plane ? MI_WAIT_FOR_PLANE_B_FLIP :
|
||||
MI_WAIT_FOR_PLANE_A_FLIP)));
|
||||
OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | (sync ? 0 : ASYNC_FLIP) |
|
||||
(plane ? DISPLAY_PLANE_B : DISPLAY_PLANE_A));
|
||||
OUT_RING(dev_priv->sarea_priv->pitch * dev_priv->cpp);
|
||||
OUT_RING(dspbase);
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
dev_priv->sarea_priv->pf_current_page &= ~(0x3 << shift);
|
||||
dev_priv->sarea_priv->pf_current_page |= next_page << shift;
|
||||
}
|
||||
BEGIN_LP_RING(6);
|
||||
OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
|
||||
OUT_RING(0);
|
||||
if (dev_priv->current_page == 0) {
|
||||
OUT_RING(dev_priv->back_offset);
|
||||
dev_priv->current_page = 1;
|
||||
} else {
|
||||
OUT_RING(dev_priv->front_offset);
|
||||
dev_priv->current_page = 0;
|
||||
}
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
void i915_dispatch_flip(struct drm_device * dev, int planes, int sync)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int i;
|
||||
BEGIN_LP_RING(2);
|
||||
OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
DRM_DEBUG("planes=0x%x pfCurrentPage=%d\n",
|
||||
planes, dev_priv->sarea_priv->pf_current_page);
|
||||
dev_priv->sarea_priv->last_enqueue = dev_priv->counter++;
|
||||
|
||||
i915_emit_mi_flush(dev, MI_READ_FLUSH | MI_EXE_FLUSH);
|
||||
|
||||
for (i = 0; i < 2; i++)
|
||||
if (planes & (1 << i))
|
||||
i915_do_dispatch_flip(dev, i, sync);
|
||||
|
||||
i915_emit_breadcrumb(dev);
|
||||
BEGIN_LP_RING(4);
|
||||
OUT_RING(CMD_STORE_DWORD_IDX);
|
||||
OUT_RING(20);
|
||||
OUT_RING(dev_priv->counter);
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
|
||||
dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_quiescent(struct drm_device * dev)
|
||||
@@ -624,6 +579,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 *hw_status = dev_priv->hw_status_page;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
drm_i915_batchbuffer_t *batch = data;
|
||||
@@ -646,7 +602,7 @@ static int i915_batchbuffer(struct drm_device *dev, void *data,
|
||||
|
||||
ret = i915_dispatch_batchbuffer(dev, batch);
|
||||
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
sarea_priv->last_dispatch = (int)hw_status[5];
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -654,6 +610,7 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 *hw_status = dev_priv->hw_status_page;
|
||||
drm_i915_sarea_t *sarea_priv = (drm_i915_sarea_t *)
|
||||
dev_priv->sarea_priv;
|
||||
drm_i915_cmdbuffer_t *cmdbuf = data;
|
||||
@@ -678,51 +635,18 @@ static int i915_cmdbuffer(struct drm_device *dev, void *data,
|
||||
return ret;
|
||||
}
|
||||
|
||||
sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_do_cleanup_pageflip(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
int i, planes, num_pages = dev_priv->sarea_priv->third_handle ? 3 : 2;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
for (i = 0, planes = 0; i < 2; i++)
|
||||
if (dev_priv->sarea_priv->pf_current_page & (0x3 << (2 * i))) {
|
||||
dev_priv->sarea_priv->pf_current_page =
|
||||
(dev_priv->sarea_priv->pf_current_page &
|
||||
~(0x3 << (2 * i))) | ((num_pages - 1) << (2 * i));
|
||||
|
||||
planes |= 1 << i;
|
||||
}
|
||||
|
||||
if (planes)
|
||||
i915_dispatch_flip(dev, planes, 0);
|
||||
|
||||
sarea_priv->last_dispatch = (int)hw_status[5];
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i915_flip_bufs(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv)
|
||||
{
|
||||
drm_i915_flip_t *param = data;
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
DRM_DEBUG("%s\n", __FUNCTION__);
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
/* This is really planes */
|
||||
if (param->pipes & ~0x3) {
|
||||
DRM_ERROR("Invalid planes 0x%x, only <= 0x3 is valid\n",
|
||||
param->pipes);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i915_dispatch_flip(dev, param->pipes, 0);
|
||||
|
||||
return 0;
|
||||
return i915_dispatch_flip(dev);
|
||||
}
|
||||
|
||||
static int i915_getparam(struct drm_device *dev, void *data,
|
||||
@@ -883,8 +807,6 @@ void i915_driver_lastclose(struct drm_device * dev)
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
if (drm_getsarea(dev) && dev_priv->sarea_priv)
|
||||
i915_do_cleanup_pageflip(dev);
|
||||
if (dev_priv->agp_heap)
|
||||
i915_mem_takedown(&(dev_priv->agp_heap));
|
||||
|
||||
|
||||
@@ -105,29 +105,14 @@ typedef struct _drm_i915_sarea {
|
||||
unsigned int rotated_tiled;
|
||||
unsigned int rotated2_tiled;
|
||||
|
||||
int planeA_x;
|
||||
int planeA_y;
|
||||
int planeA_w;
|
||||
int planeA_h;
|
||||
int planeB_x;
|
||||
int planeB_y;
|
||||
int planeB_w;
|
||||
int planeB_h;
|
||||
|
||||
/* Triple buffering */
|
||||
drm_handle_t third_handle;
|
||||
int third_offset;
|
||||
int third_size;
|
||||
unsigned int third_tiled;
|
||||
|
||||
/* buffer object handles for the static buffers. May change
|
||||
* over the lifetime of the client, though it doesn't in our current
|
||||
* implementation.
|
||||
*/
|
||||
unsigned int front_bo_handle;
|
||||
unsigned int back_bo_handle;
|
||||
unsigned int third_bo_handle;
|
||||
unsigned int depth_bo_handle;
|
||||
int pipeA_x;
|
||||
int pipeA_y;
|
||||
int pipeA_w;
|
||||
int pipeA_h;
|
||||
int pipeB_x;
|
||||
int pipeB_y;
|
||||
int pipeB_w;
|
||||
int pipeB_h;
|
||||
} drm_i915_sarea_t;
|
||||
|
||||
/* Flags for perf_boxes
|
||||
@@ -161,7 +146,7 @@ typedef struct _drm_i915_sarea {
|
||||
|
||||
#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
|
||||
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
|
||||
#define DRM_IOCTL_I915_FLIP DRM_IOW( DRM_COMMAND_BASE + DRM_I915_FLIP, drm_i915_flip_t)
|
||||
#define DRM_IOCTL_I915_FLIP DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLIP)
|
||||
#define DRM_IOCTL_I915_BATCHBUFFER DRM_IOW( DRM_COMMAND_BASE + DRM_I915_BATCHBUFFER, drm_i915_batchbuffer_t)
|
||||
#define DRM_IOCTL_I915_IRQ_EMIT DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_IRQ_EMIT, drm_i915_irq_emit_t)
|
||||
#define DRM_IOCTL_I915_IRQ_WAIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_IRQ_WAIT, drm_i915_irq_wait_t)
|
||||
@@ -176,18 +161,6 @@ typedef struct _drm_i915_sarea {
|
||||
#define DRM_IOCTL_I915_GET_VBLANK_PIPE DRM_IOR( DRM_COMMAND_BASE + DRM_I915_GET_VBLANK_PIPE, drm_i915_vblank_pipe_t)
|
||||
#define DRM_IOCTL_I915_VBLANK_SWAP DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_VBLANK_SWAP, drm_i915_vblank_swap_t)
|
||||
|
||||
/* Asynchronous page flipping:
|
||||
*/
|
||||
typedef struct drm_i915_flip {
|
||||
/*
|
||||
* This is really talking about planes, and we could rename it
|
||||
* except for the fact that some of the duplicated i915_drm.h files
|
||||
* out there check for HAVE_I915_FLIP and so might pick up this
|
||||
* version.
|
||||
*/
|
||||
int pipes;
|
||||
} drm_i915_flip_t;
|
||||
|
||||
/* Allow drivers to submit batchbuffers directly to hardware, relying
|
||||
* on the security mechanisms provided by hardware.
|
||||
*/
|
||||
|
||||
@@ -147,7 +147,7 @@ static void i915_save_vga(struct drm_device *dev)
|
||||
i915_write_indexed(cr_index, cr_data, 0x11,
|
||||
i915_read_indexed(cr_index, cr_data, 0x11) &
|
||||
(~0x80));
|
||||
for (i = 0; i < 0x24; i++)
|
||||
for (i = 0; i <= 0x24; i++)
|
||||
dev_priv->saveCR[i] =
|
||||
i915_read_indexed(cr_index, cr_data, i);
|
||||
/* Make sure we don't turn off CR group 0 writes */
|
||||
@@ -156,7 +156,7 @@ static void i915_save_vga(struct drm_device *dev)
|
||||
/* Attribute controller registers */
|
||||
inb(st01);
|
||||
dev_priv->saveAR_INDEX = inb(VGA_AR_INDEX);
|
||||
for (i = 0; i < 20; i++)
|
||||
for (i = 0; i <= 0x14; i++)
|
||||
dev_priv->saveAR[i] = i915_read_ar(st01, i, 0);
|
||||
inb(st01);
|
||||
outb(dev_priv->saveAR_INDEX, VGA_AR_INDEX);
|
||||
@@ -206,7 +206,7 @@ static void i915_restore_vga(struct drm_device *dev)
|
||||
/* CRT controller regs */
|
||||
/* Enable CR group 0 writes */
|
||||
i915_write_indexed(cr_index, cr_data, 0x11, dev_priv->saveCR[0x11]);
|
||||
for (i = 0; i < 0x24; i++)
|
||||
for (i = 0; i <= 0x24; i++)
|
||||
i915_write_indexed(cr_index, cr_data, i, dev_priv->saveCR[i]);
|
||||
|
||||
/* Graphics controller regs */
|
||||
@@ -223,7 +223,7 @@ static void i915_restore_vga(struct drm_device *dev)
|
||||
|
||||
/* Attribute controller registers */
|
||||
inb(st01);
|
||||
for (i = 0; i < 20; i++)
|
||||
for (i = 0; i <= 0x14; i++)
|
||||
i915_write_ar(st01, i, dev_priv->saveAR[i], 0);
|
||||
inb(st01); /* switch back to index mode */
|
||||
outb(dev_priv->saveAR_INDEX | 0x20, VGA_AR_INDEX);
|
||||
@@ -256,6 +256,9 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
|
||||
pci_save_state(dev->pdev);
|
||||
pci_read_config_byte(dev->pdev, LBB, &dev_priv->saveLBB);
|
||||
|
||||
/* Display arbitration control */
|
||||
dev_priv->saveDSPARB = I915_READ(DSPARB);
|
||||
|
||||
/* Pipe & plane A info */
|
||||
dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
|
||||
dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
|
||||
@@ -349,6 +352,7 @@ static int i915_suspend(struct drm_device *dev, pm_message_t state)
|
||||
dev_priv->saveVGACNTRL = I915_READ(VGACNTRL);
|
||||
|
||||
/* Clock gating state */
|
||||
dev_priv->saveD_STATE = I915_READ(D_STATE);
|
||||
dev_priv->saveDSPCLK_GATE_D = I915_READ(DSPCLK_GATE_D);
|
||||
|
||||
/* Cache mode state */
|
||||
@@ -388,6 +392,8 @@ static int i915_resume(struct drm_device *dev)
|
||||
|
||||
pci_write_config_byte(dev->pdev, LBB, dev_priv->saveLBB);
|
||||
|
||||
I915_WRITE(DSPARB, dev_priv->saveDSPARB);
|
||||
|
||||
/* Pipe & plane A info */
|
||||
/* Prime the clock */
|
||||
if (dev_priv->saveDPLL_A & DPLL_VCO_ENABLE) {
|
||||
@@ -507,6 +513,7 @@ static int i915_resume(struct drm_device *dev)
|
||||
udelay(150);
|
||||
|
||||
/* Clock gating state */
|
||||
I915_WRITE (D_STATE, dev_priv->saveD_STATE);
|
||||
I915_WRITE (DSPCLK_GATE_D, dev_priv->saveDSPCLK_GATE_D);
|
||||
|
||||
/* Cache mode state */
|
||||
@@ -533,7 +540,8 @@ static struct drm_driver driver = {
|
||||
*/
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | /* DRIVER_USE_MTRR |*/
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL |
|
||||
DRIVER_IRQ_VBL2,
|
||||
.load = i915_driver_load,
|
||||
.unload = i915_driver_unload,
|
||||
.lastclose = i915_driver_lastclose,
|
||||
@@ -541,9 +549,8 @@ static struct drm_driver driver = {
|
||||
.suspend = i915_suspend,
|
||||
.resume = i915_resume,
|
||||
.device_is_agp = i915_driver_device_is_agp,
|
||||
.get_vblank_counter = i915_get_vblank_counter,
|
||||
.enable_vblank = i915_enable_vblank,
|
||||
.disable_vblank = i915_disable_vblank,
|
||||
.vblank_wait = i915_driver_vblank_wait,
|
||||
.vblank_wait2 = i915_driver_vblank_wait2,
|
||||
.irq_preinstall = i915_driver_irq_preinstall,
|
||||
.irq_postinstall = i915_driver_irq_postinstall,
|
||||
.irq_uninstall = i915_driver_irq_uninstall,
|
||||
|
||||
+23
-92
@@ -76,9 +76,8 @@ struct mem_block {
|
||||
typedef struct _drm_i915_vbl_swap {
|
||||
struct list_head head;
|
||||
drm_drawable_t drw_id;
|
||||
unsigned int plane;
|
||||
unsigned int pipe;
|
||||
unsigned int sequence;
|
||||
int flip;
|
||||
} drm_i915_vbl_swap_t;
|
||||
|
||||
typedef struct drm_i915_private {
|
||||
@@ -91,7 +90,7 @@ typedef struct drm_i915_private {
|
||||
drm_dma_handle_t *status_page_dmah;
|
||||
void *hw_status_page;
|
||||
dma_addr_t dma_status_page;
|
||||
uint32_t counter;
|
||||
unsigned long counter;
|
||||
unsigned int status_gfx_addr;
|
||||
drm_local_map_t hws_map;
|
||||
|
||||
@@ -104,18 +103,13 @@ typedef struct drm_i915_private {
|
||||
|
||||
wait_queue_head_t irq_queue;
|
||||
atomic_t irq_received;
|
||||
atomic_t irq_emited;
|
||||
atomic_t irq_emitted;
|
||||
|
||||
int tex_lru_log_granularity;
|
||||
int allow_batchbuffer;
|
||||
struct mem_block *agp_heap;
|
||||
unsigned int sr01, adpa, ppcr, dvob, dvoc, lvds;
|
||||
int vblank_pipe;
|
||||
spinlock_t user_irq_lock;
|
||||
int user_irq_refcount;
|
||||
int fence_irq_on;
|
||||
uint32_t irq_enable_reg;
|
||||
int irq_enabled;
|
||||
|
||||
spinlock_t swaps_lock;
|
||||
drm_i915_vbl_swap_t vbl_swaps;
|
||||
@@ -125,6 +119,7 @@ typedef struct drm_i915_private {
|
||||
u8 saveLBB;
|
||||
u32 saveDSPACNTR;
|
||||
u32 saveDSPBCNTR;
|
||||
u32 saveDSPARB;
|
||||
u32 savePIPEACONF;
|
||||
u32 savePIPEBCONF;
|
||||
u32 savePIPEASRC;
|
||||
@@ -194,6 +189,7 @@ typedef struct drm_i915_private {
|
||||
u32 saveIIR;
|
||||
u32 saveIMR;
|
||||
u32 saveCACHE_MODE_0;
|
||||
u32 saveD_STATE;
|
||||
u32 saveDSPCLK_GATE_D;
|
||||
u32 saveMI_ARB_STATE;
|
||||
u32 saveSWF0[16];
|
||||
@@ -203,10 +199,10 @@ typedef struct drm_i915_private {
|
||||
u8 saveSR[8];
|
||||
u8 saveGR[25];
|
||||
u8 saveAR_INDEX;
|
||||
u8 saveAR[20];
|
||||
u8 saveAR[21];
|
||||
u8 saveDACMASK;
|
||||
u8 saveDACDATA[256*3]; /* 256 3-byte colors */
|
||||
u8 saveCR[36];
|
||||
u8 saveCR[37];
|
||||
} drm_i915_private_t;
|
||||
|
||||
extern struct drm_ioctl_desc i915_ioctls[];
|
||||
@@ -222,7 +218,7 @@ extern void i915_driver_preclose(struct drm_device *dev,
|
||||
extern int i915_driver_device_is_agp(struct drm_device * dev);
|
||||
extern long i915_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
extern void i915_dispatch_flip(struct drm_device * dev, int pipes, int sync);
|
||||
|
||||
/* i915_irq.c */
|
||||
extern int i915_irq_emit(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
@@ -233,7 +229,7 @@ extern int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequenc
|
||||
extern int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
|
||||
extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void i915_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern int i915_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void i915_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void i915_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern int i915_vblank_pipe_set(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
@@ -241,9 +237,6 @@ extern int i915_vblank_pipe_get(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
struct drm_file *file_priv);
|
||||
extern int i915_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void i915_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
|
||||
/* i915_mem.c */
|
||||
extern int i915_mem_alloc(struct drm_device *dev, void *data,
|
||||
@@ -388,91 +381,21 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
|
||||
/* Interrupt bits:
|
||||
*/
|
||||
#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18)
|
||||
#define I915_DISPLAY_PORT_INTERRUPT (1<<17)
|
||||
#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15)
|
||||
#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14)
|
||||
#define I915_HWB_OOM_INTERRUPT (1<<13) /* binner out of memory */
|
||||
#define I915_SYNC_STATUS_INTERRUPT (1<<12)
|
||||
#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11)
|
||||
#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10)
|
||||
#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9)
|
||||
#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8)
|
||||
#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7)
|
||||
#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6)
|
||||
#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5)
|
||||
#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4)
|
||||
#define I915_DEBUG_INTERRUPT (1<<2)
|
||||
#define I915_USER_INTERRUPT (1<<1)
|
||||
|
||||
#define USER_INT_FLAG (1<<1)
|
||||
#define VSYNC_PIPEB_FLAG (1<<5)
|
||||
#define VSYNC_PIPEA_FLAG (1<<7)
|
||||
#define HWB_OOM_FLAG (1<<13) /* binner out of memory */
|
||||
|
||||
#define I915REG_HWSTAM 0x02098
|
||||
#define I915REG_INT_IDENTITY_R 0x020a4
|
||||
#define I915REG_INT_MASK_R 0x020a8
|
||||
#define I915REG_INT_ENABLE_R 0x020a0
|
||||
#define I915REG_INSTPM 0x020c0
|
||||
|
||||
#define PIPEADSL 0x70000
|
||||
#define PIPEBDSL 0x71000
|
||||
|
||||
#define I915REG_PIPEASTAT 0x70024
|
||||
#define I915REG_PIPEBSTAT 0x71024
|
||||
/*
|
||||
* The two pipe frame counter registers are not synchronized, so
|
||||
* reading a stable value is somewhat tricky. The following code
|
||||
* should work:
|
||||
*
|
||||
* do {
|
||||
* high1 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
|
||||
* PIPE_FRAME_HIGH_SHIFT;
|
||||
* low1 = ((INREG(PIPEAFRAMEPIXEL) & PIPE_FRAME_LOW_MASK) >>
|
||||
* PIPE_FRAME_LOW_SHIFT);
|
||||
* high2 = ((INREG(PIPEAFRAMEHIGH) & PIPE_FRAME_HIGH_MASK) >>
|
||||
* PIPE_FRAME_HIGH_SHIFT);
|
||||
* } while (high1 != high2);
|
||||
* frame = (high1 << 8) | low1;
|
||||
*/
|
||||
#define PIPEAFRAMEHIGH 0x70040
|
||||
#define PIPEBFRAMEHIGH 0x71040
|
||||
#define PIPE_FRAME_HIGH_MASK 0x0000ffff
|
||||
#define PIPE_FRAME_HIGH_SHIFT 0
|
||||
#define PIPEAFRAMEPIXEL 0x70044
|
||||
#define PIPEBFRAMEPIXEL 0x71044
|
||||
|
||||
#define PIPE_FRAME_LOW_MASK 0xff000000
|
||||
#define PIPE_FRAME_LOW_SHIFT 24
|
||||
/*
|
||||
* Pixel within the current frame is counted in the PIPEAFRAMEPIXEL register
|
||||
* and is 24 bits wide.
|
||||
*/
|
||||
#define PIPE_PIXEL_MASK 0x00ffffff
|
||||
#define PIPE_PIXEL_SHIFT 0
|
||||
|
||||
#define I915_FIFO_UNDERRUN_STATUS (1UL<<31)
|
||||
#define I915_CRC_ERROR_ENABLE (1UL<<29)
|
||||
#define I915_CRC_DONE_ENABLE (1UL<<28)
|
||||
#define I915_GMBUS_EVENT_ENABLE (1UL<<27)
|
||||
#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25)
|
||||
#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24)
|
||||
#define I915_DPST_EVENT_ENABLE (1UL<<23)
|
||||
#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22)
|
||||
#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21)
|
||||
#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20)
|
||||
#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */
|
||||
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
|
||||
#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16)
|
||||
#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13)
|
||||
#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12)
|
||||
#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11)
|
||||
#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9)
|
||||
#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8)
|
||||
#define I915_DPST_EVENT_STATUS (1UL<<7)
|
||||
#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6)
|
||||
#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5)
|
||||
#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4)
|
||||
#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */
|
||||
#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1)
|
||||
#define I915_OVERLAY_UPDATED_STATUS (1UL<<0)
|
||||
#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17)
|
||||
#define I915_VBLANK_CLEAR (1UL<<1)
|
||||
|
||||
#define SRX_INDEX 0x3c4
|
||||
#define SRX_DATA 0x3c5
|
||||
@@ -749,6 +672,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
/** P1 value is 2 greater than this field */
|
||||
# define VGA0_PD_P1_MASK (0x1f << 0)
|
||||
|
||||
/* PCI D state control register */
|
||||
#define D_STATE 0x6104
|
||||
#define DSPCLK_GATE_D 0x6200
|
||||
|
||||
/* I830 CRTC registers */
|
||||
@@ -1059,6 +984,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller);
|
||||
#define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21)
|
||||
#define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21)
|
||||
|
||||
#define DSPARB 0x70030
|
||||
#define DSPARB_CSTART_MASK (0x7f << 7)
|
||||
#define DSPARB_CSTART_SHIFT 7
|
||||
#define DSPARB_BSTART_MASK (0x7f)
|
||||
#define DSPARB_BSTART_SHIFT 0
|
||||
|
||||
#define PIPEBCONF 0x71008
|
||||
#define PIPEBCONF_ENABLE (1<<31)
|
||||
#define PIPEBCONF_DISABLE 0
|
||||
|
||||
+150
-443
@@ -37,109 +37,6 @@
|
||||
|
||||
#define MAX_NOPID ((u32)~0)
|
||||
|
||||
/**
|
||||
* i915_get_pipe - return the the pipe associated with a given plane
|
||||
* @dev: DRM device
|
||||
* @plane: plane to look for
|
||||
*
|
||||
* The Intel Mesa & 2D drivers call the vblank routines with a plane number
|
||||
* rather than a pipe number, since they may not always be equal. This routine
|
||||
* maps the given @plane back to a pipe number.
|
||||
*/
|
||||
static int
|
||||
i915_get_pipe(struct drm_device *dev, int plane)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 dspcntr;
|
||||
|
||||
dspcntr = plane ? I915_READ(DSPBCNTR) : I915_READ(DSPACNTR);
|
||||
|
||||
return dspcntr & DISPPLANE_SEL_PIPE_MASK ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_get_plane - return the the plane associated with a given pipe
|
||||
* @dev: DRM device
|
||||
* @pipe: pipe to look for
|
||||
*
|
||||
* The Intel Mesa & 2D drivers call the vblank routines with a plane number
|
||||
* rather than a plane number, since they may not always be equal. This routine
|
||||
* maps the given @pipe back to a plane number.
|
||||
*/
|
||||
static int
|
||||
i915_get_plane(struct drm_device *dev, int pipe)
|
||||
{
|
||||
if (i915_get_pipe(dev, 0) == pipe)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* i915_pipe_enabled - check if a pipe is enabled
|
||||
* @dev: DRM device
|
||||
* @pipe: pipe to check
|
||||
*
|
||||
* Reading certain registers when the pipe is disabled can hang the chip.
|
||||
* Use this routine to make sure the PLL is running and the pipe is active
|
||||
* before reading such registers if unsure.
|
||||
*/
|
||||
static int
|
||||
i915_pipe_enabled(struct drm_device *dev, int pipe)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long pipeconf = pipe ? PIPEBCONF : PIPEACONF;
|
||||
|
||||
if (I915_READ(pipeconf) & PIPEACONF_ENABLE)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit a synchronous flip.
|
||||
*
|
||||
* This function must be called with the drawable spinlock held.
|
||||
*/
|
||||
static void
|
||||
i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
|
||||
int plane)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
u16 x1, y1, x2, y2;
|
||||
int pf_planes = 1 << plane;
|
||||
|
||||
/* If the window is visible on the other plane, we have to flip on that
|
||||
* plane as well.
|
||||
*/
|
||||
if (plane == 1) {
|
||||
x1 = sarea_priv->planeA_x;
|
||||
y1 = sarea_priv->planeA_y;
|
||||
x2 = x1 + sarea_priv->planeA_w;
|
||||
y2 = y1 + sarea_priv->planeA_h;
|
||||
} else {
|
||||
x1 = sarea_priv->planeB_x;
|
||||
y1 = sarea_priv->planeB_y;
|
||||
x2 = x1 + sarea_priv->planeB_w;
|
||||
y2 = y1 + sarea_priv->planeB_h;
|
||||
}
|
||||
|
||||
if (x2 > 0 && y2 > 0) {
|
||||
int i, num_rects = drw->num_rects;
|
||||
struct drm_clip_rect *rect = drw->rects;
|
||||
|
||||
for (i = 0; i < num_rects; i++)
|
||||
if (!(rect[i].x1 >= x2 || rect[i].y1 >= y2 ||
|
||||
rect[i].x2 <= x1 || rect[i].y2 <= y1)) {
|
||||
pf_planes = 0x3;
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
i915_dispatch_flip(dev, pf_planes, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit blits for scheduled buffer swaps.
|
||||
*
|
||||
@@ -148,19 +45,20 @@ i915_dispatch_vsync_flip(struct drm_device *dev, struct drm_drawable_info *drw,
|
||||
static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long irqflags;
|
||||
struct list_head *list, *tmp, hits, *hit;
|
||||
int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages;
|
||||
unsigned counter[2];
|
||||
int nhits, nrects, slice[2], upper[2], lower[2], i;
|
||||
unsigned counter[2] = { atomic_read(&dev->vbl_received),
|
||||
atomic_read(&dev->vbl_received2) };
|
||||
struct drm_drawable_info *drw;
|
||||
drm_i915_sarea_t *sarea_priv = dev_priv->sarea_priv;
|
||||
u32 cpp = dev_priv->cpp, offsets[3];
|
||||
u32 cpp = dev_priv->cpp;
|
||||
u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD |
|
||||
XY_SRC_COPY_BLT_WRITE_ALPHA |
|
||||
XY_SRC_COPY_BLT_WRITE_RGB)
|
||||
: XY_SRC_COPY_BLT_CMD;
|
||||
u32 src_pitch = sarea_priv->pitch * cpp;
|
||||
u32 dst_pitch = sarea_priv->pitch * cpp;
|
||||
/* COPY rop (0xcc), map cpp to magic color depth constants */
|
||||
u32 ropcpp = (0xcc << 16) | ((cpp - 1) << 24);
|
||||
RING_LOCALS;
|
||||
|
||||
@@ -173,34 +71,24 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
src_pitch >>= 2;
|
||||
}
|
||||
|
||||
counter[0] = drm_vblank_count(dev, 0);
|
||||
counter[1] = drm_vblank_count(dev, 1);
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
INIT_LIST_HEAD(&hits);
|
||||
|
||||
nhits = nrects = 0;
|
||||
|
||||
/* No irqsave/restore necessary. This tasklet may be run in an
|
||||
* interrupt context or normal context, but we don't have to worry
|
||||
* about getting interrupted by something acquiring the lock, because
|
||||
* we are the interrupt context thing that acquires the lock.
|
||||
*/
|
||||
spin_lock(&dev_priv->swaps_lock);
|
||||
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
|
||||
|
||||
/* Find buffer swaps scheduled for this vertical blank */
|
||||
list_for_each_safe(list, tmp, &dev_priv->vbl_swaps.head) {
|
||||
drm_i915_vbl_swap_t *vbl_swap =
|
||||
list_entry(list, drm_i915_vbl_swap_t, head);
|
||||
int pipe = i915_get_pipe(dev, vbl_swap->plane);
|
||||
|
||||
if ((counter[pipe] - vbl_swap->sequence) > (1<<23))
|
||||
if ((counter[vbl_swap->pipe] - vbl_swap->sequence) > (1<<23))
|
||||
continue;
|
||||
|
||||
list_del(list);
|
||||
dev_priv->swaps_pending--;
|
||||
drm_vblank_put(dev, pipe);
|
||||
|
||||
spin_unlock(&dev_priv->swaps_lock);
|
||||
spin_lock(&dev->drw_lock);
|
||||
@@ -238,23 +126,43 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
spin_lock(&dev_priv->swaps_lock);
|
||||
}
|
||||
|
||||
spin_unlock(&dev_priv->swaps_lock);
|
||||
|
||||
if (nhits == 0)
|
||||
if (nhits == 0) {
|
||||
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
|
||||
return;
|
||||
}
|
||||
|
||||
spin_unlock(&dev_priv->swaps_lock);
|
||||
|
||||
i915_kernel_lost_context(dev);
|
||||
|
||||
upper[0] = upper[1] = 0;
|
||||
slice[0] = max(sarea_priv->planeA_h / nhits, 1);
|
||||
slice[1] = max(sarea_priv->planeB_h / nhits, 1);
|
||||
lower[0] = sarea_priv->planeA_y + slice[0];
|
||||
lower[1] = sarea_priv->planeB_y + slice[0];
|
||||
if (IS_I965G(dev)) {
|
||||
BEGIN_LP_RING(4);
|
||||
|
||||
offsets[0] = sarea_priv->front_offset;
|
||||
offsets[1] = sarea_priv->back_offset;
|
||||
offsets[2] = sarea_priv->third_offset;
|
||||
num_pages = sarea_priv->third_handle ? 3 : 2;
|
||||
OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
|
||||
OUT_RING(0);
|
||||
OUT_RING(((sarea_priv->width - 1) & 0xffff) | ((sarea_priv->height - 1) << 16));
|
||||
OUT_RING(0);
|
||||
ADVANCE_LP_RING();
|
||||
} else {
|
||||
BEGIN_LP_RING(6);
|
||||
|
||||
OUT_RING(GFX_OP_DRAWRECT_INFO);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0);
|
||||
OUT_RING(sarea_priv->width | sarea_priv->height << 16);
|
||||
OUT_RING(sarea_priv->width | sarea_priv->height << 16);
|
||||
OUT_RING(0);
|
||||
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
|
||||
|
||||
upper[0] = upper[1] = 0;
|
||||
slice[0] = max(sarea_priv->pipeA_h / nhits, 1);
|
||||
slice[1] = max(sarea_priv->pipeB_h / nhits, 1);
|
||||
lower[0] = sarea_priv->pipeA_y + slice[0];
|
||||
lower[1] = sarea_priv->pipeB_y + slice[0];
|
||||
|
||||
spin_lock(&dev->drw_lock);
|
||||
|
||||
@@ -266,8 +174,6 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
for (i = 0; i++ < nhits;
|
||||
upper[0] = lower[0], lower[0] += slice[0],
|
||||
upper[1] = lower[1], lower[1] += slice[1]) {
|
||||
int init_drawrect = 1;
|
||||
|
||||
if (i == nhits)
|
||||
lower[0] = lower[1] = sarea_priv->height;
|
||||
|
||||
@@ -275,7 +181,7 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
drm_i915_vbl_swap_t *swap_hit =
|
||||
list_entry(hit, drm_i915_vbl_swap_t, head);
|
||||
struct drm_clip_rect *rect;
|
||||
int num_rects, plane, front, back;
|
||||
int num_rects, pipe;
|
||||
unsigned short top, bottom;
|
||||
|
||||
drw = drm_get_drawable_info(dev, swap_hit->drw_id);
|
||||
@@ -283,50 +189,10 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
if (!drw)
|
||||
continue;
|
||||
|
||||
plane = swap_hit->plane;
|
||||
|
||||
if (swap_hit->flip) {
|
||||
i915_dispatch_vsync_flip(dev, drw, plane);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (init_drawrect) {
|
||||
int width = sarea_priv->width;
|
||||
int height = sarea_priv->height;
|
||||
if (IS_I965G(dev)) {
|
||||
BEGIN_LP_RING(4);
|
||||
|
||||
OUT_RING(GFX_OP_DRAWRECT_INFO_I965);
|
||||
OUT_RING(0);
|
||||
OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
|
||||
OUT_RING(0);
|
||||
|
||||
ADVANCE_LP_RING();
|
||||
} else {
|
||||
BEGIN_LP_RING(6);
|
||||
|
||||
OUT_RING(GFX_OP_DRAWRECT_INFO);
|
||||
OUT_RING(0);
|
||||
OUT_RING(0);
|
||||
OUT_RING(((width - 1) & 0xffff) | ((height - 1) << 16));
|
||||
OUT_RING(0);
|
||||
OUT_RING(0);
|
||||
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
|
||||
sarea_priv->ctxOwner = DRM_KERNEL_CONTEXT;
|
||||
|
||||
init_drawrect = 0;
|
||||
}
|
||||
|
||||
rect = drw->rects;
|
||||
top = upper[plane];
|
||||
bottom = lower[plane];
|
||||
|
||||
front = (dev_priv->sarea_priv->pf_current_page >>
|
||||
(2 * plane)) & 0x3;
|
||||
back = (front + 1) % num_pages;
|
||||
pipe = swap_hit->pipe;
|
||||
top = upper[pipe];
|
||||
bottom = lower[pipe];
|
||||
|
||||
for (num_rects = drw->num_rects; num_rects--; rect++) {
|
||||
int y1 = max(rect->y1, top);
|
||||
@@ -341,17 +207,17 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
OUT_RING(ropcpp | dst_pitch);
|
||||
OUT_RING((y1 << 16) | rect->x1);
|
||||
OUT_RING((y2 << 16) | rect->x2);
|
||||
OUT_RING(offsets[front]);
|
||||
OUT_RING(sarea_priv->front_offset);
|
||||
OUT_RING((y1 << 16) | rect->x1);
|
||||
OUT_RING(src_pitch);
|
||||
OUT_RING(offsets[back]);
|
||||
OUT_RING(sarea_priv->back_offset);
|
||||
|
||||
ADVANCE_LP_RING();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
spin_unlock(&dev->drw_lock);
|
||||
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
|
||||
|
||||
list_for_each_safe(hit, tmp, &hits) {
|
||||
drm_i915_vbl_swap_t *swap_hit =
|
||||
@@ -363,112 +229,67 @@ static void i915_vblank_tasklet(struct drm_device *dev)
|
||||
}
|
||||
}
|
||||
|
||||
u32 i915_get_vblank_counter(struct drm_device *dev, int plane)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
unsigned long high_frame;
|
||||
unsigned long low_frame;
|
||||
u32 high1, high2, low, count;
|
||||
int pipe;
|
||||
|
||||
pipe = i915_get_pipe(dev, plane);
|
||||
high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
|
||||
low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
|
||||
|
||||
if (!i915_pipe_enabled(dev, pipe)) {
|
||||
printk(KERN_ERR "trying to get vblank count for disabled "
|
||||
"pipe %d\n", pipe);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* High & low register fields aren't synchronized, so make sure
|
||||
* we get a low value that's stable across two reads of the high
|
||||
* register.
|
||||
*/
|
||||
do {
|
||||
high1 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
|
||||
PIPE_FRAME_HIGH_SHIFT);
|
||||
low = ((I915_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
|
||||
PIPE_FRAME_LOW_SHIFT);
|
||||
high2 = ((I915_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
|
||||
PIPE_FRAME_HIGH_SHIFT);
|
||||
} while (high1 != high2);
|
||||
|
||||
count = (high1 << 8) | low;
|
||||
|
||||
/* count may be reset by other driver(e.g. 2D driver),
|
||||
we have no way to know if it is wrapped or resetted
|
||||
when count is zero. do a rough guess.
|
||||
*/
|
||||
if (count == 0 && dev->last_vblank[pipe] < dev->max_vblank_count/2)
|
||||
dev->last_vblank[pipe] = 0;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 iir;
|
||||
u16 temp;
|
||||
u32 pipea_stats, pipeb_stats;
|
||||
int vblank = 0;
|
||||
|
||||
iir = I915_READ(I915REG_INT_IDENTITY_R);
|
||||
if (iir == 0) {
|
||||
DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n",
|
||||
iir,
|
||||
I915_READ(I915REG_INT_MASK_R),
|
||||
I915_READ(I915REG_INT_ENABLE_R),
|
||||
I915_READ(I915REG_PIPEASTAT),
|
||||
I915_READ(I915REG_PIPEBSTAT));
|
||||
pipea_stats = I915_READ(I915REG_PIPEASTAT);
|
||||
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
|
||||
|
||||
temp = I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
|
||||
temp &= (USER_INT_FLAG | VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG);
|
||||
|
||||
DRM_DEBUG("%s flag=%08x\n", __FUNCTION__, temp);
|
||||
|
||||
if (temp == 0)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear the PIPE(A|B)STAT regs before the IIR otherwise
|
||||
* we may get extra interrupts.
|
||||
*/
|
||||
if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) {
|
||||
pipea_stats = I915_READ(I915REG_PIPEASTAT);
|
||||
if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
|
||||
I915_VBLANK_INTERRUPT_STATUS))
|
||||
{
|
||||
vblank++;
|
||||
drm_handle_vblank(dev, i915_get_plane(dev, 0));
|
||||
}
|
||||
I915_WRITE(I915REG_PIPEASTAT, pipea_stats);
|
||||
}
|
||||
if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) {
|
||||
pipeb_stats = I915_READ(I915REG_PIPEBSTAT);
|
||||
if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS|
|
||||
I915_VBLANK_INTERRUPT_STATUS))
|
||||
{
|
||||
vblank++;
|
||||
drm_handle_vblank(dev, i915_get_plane(dev, 1));
|
||||
}
|
||||
I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats);
|
||||
}
|
||||
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
|
||||
(void) I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
DRM_READMEMORYBARRIER();
|
||||
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
|
||||
I915_WRITE(I915REG_INT_IDENTITY_R, iir);
|
||||
(void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */
|
||||
|
||||
if (iir & I915_USER_INTERRUPT) {
|
||||
if (temp & USER_INT_FLAG)
|
||||
DRM_WAKEUP(&dev_priv->irq_queue);
|
||||
}
|
||||
if (vblank) {
|
||||
|
||||
if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) {
|
||||
int vblank_pipe = dev_priv->vblank_pipe;
|
||||
|
||||
if ((vblank_pipe &
|
||||
(DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B))
|
||||
== (DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B)) {
|
||||
if (temp & VSYNC_PIPEA_FLAG)
|
||||
atomic_inc(&dev->vbl_received);
|
||||
if (temp & VSYNC_PIPEB_FLAG)
|
||||
atomic_inc(&dev->vbl_received2);
|
||||
} else if (((temp & VSYNC_PIPEA_FLAG) &&
|
||||
(vblank_pipe & DRM_I915_VBLANK_PIPE_A)) ||
|
||||
((temp & VSYNC_PIPEB_FLAG) &&
|
||||
(vblank_pipe & DRM_I915_VBLANK_PIPE_B)))
|
||||
atomic_inc(&dev->vbl_received);
|
||||
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
|
||||
if (dev_priv->swaps_pending > 0)
|
||||
drm_locked_tasklet(dev, i915_vblank_tasklet);
|
||||
I915_WRITE(I915REG_PIPEASTAT,
|
||||
pipea_stats|I915_VBLANK_INTERRUPT_ENABLE|
|
||||
I915_VBLANK_CLEAR);
|
||||
I915_WRITE(I915REG_PIPEBSTAT,
|
||||
pipeb_stats|I915_VBLANK_INTERRUPT_ENABLE|
|
||||
I915_VBLANK_CLEAR);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int i915_emit_irq(struct drm_device *dev)
|
||||
static int i915_emit_irq(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
RING_LOCALS;
|
||||
@@ -515,12 +336,42 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr)
|
||||
READ_BREADCRUMB(dev_priv), (int)dev_priv->counter);
|
||||
}
|
||||
|
||||
if (dev_priv->sarea_priv)
|
||||
dev_priv->sarea_priv->last_dispatch =
|
||||
READ_BREADCRUMB(dev_priv);
|
||||
dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int i915_driver_vblank_do_wait(struct drm_device *dev, unsigned int *sequence,
|
||||
atomic_t *counter)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(counter))
|
||||
- *sequence) <= (1<<23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int i915_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received);
|
||||
}
|
||||
|
||||
int i915_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
return i915_driver_vblank_do_wait(dev, sequence, &dev->vbl_received2);
|
||||
}
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
*/
|
||||
int i915_irq_emit(struct drm_device *dev, void *data,
|
||||
@@ -563,96 +414,18 @@ int i915_irq_wait(struct drm_device *dev, void *data,
|
||||
return i915_wait_irq(dev, irqwait->irq_seq);
|
||||
}
|
||||
|
||||
int i915_enable_vblank(struct drm_device *dev, int plane)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int pipe = i915_get_pipe(dev, plane);
|
||||
u32 pipestat_reg = 0;
|
||||
u32 pipestat;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
pipestat_reg = I915REG_PIPEASTAT;
|
||||
dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
|
||||
break;
|
||||
case 1:
|
||||
pipestat_reg = I915REG_PIPEBSTAT;
|
||||
dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to enable vblank on non-existent pipe %d\n",
|
||||
pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
if (pipestat_reg)
|
||||
{
|
||||
pipestat = I915_READ (pipestat_reg);
|
||||
/*
|
||||
* Older chips didn't have the start vblank interrupt,
|
||||
* but
|
||||
*/
|
||||
if (IS_I965G (dev))
|
||||
pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE;
|
||||
else
|
||||
pipestat |= I915_VBLANK_INTERRUPT_ENABLE;
|
||||
/*
|
||||
* Clear any pending status
|
||||
*/
|
||||
pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
|
||||
I915_VBLANK_INTERRUPT_STATUS);
|
||||
I915_WRITE(pipestat_reg, pipestat);
|
||||
}
|
||||
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_disable_vblank(struct drm_device *dev, int plane)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int pipe = i915_get_pipe(dev, plane);
|
||||
u32 pipestat_reg = 0;
|
||||
u32 pipestat;
|
||||
|
||||
switch (pipe) {
|
||||
case 0:
|
||||
pipestat_reg = I915REG_PIPEASTAT;
|
||||
dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT;
|
||||
break;
|
||||
case 1:
|
||||
pipestat_reg = I915REG_PIPEBSTAT;
|
||||
dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to disable vblank on non-existent pipe %d\n",
|
||||
pipe);
|
||||
break;
|
||||
}
|
||||
|
||||
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
|
||||
if (pipestat_reg)
|
||||
{
|
||||
pipestat = I915_READ (pipestat_reg);
|
||||
pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE |
|
||||
I915_VBLANK_INTERRUPT_ENABLE);
|
||||
/*
|
||||
* Clear any pending status
|
||||
*/
|
||||
pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS |
|
||||
I915_VBLANK_INTERRUPT_STATUS);
|
||||
I915_WRITE(pipestat_reg, pipestat);
|
||||
}
|
||||
}
|
||||
|
||||
static void i915_enable_interrupt (struct drm_device *dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u16 flag;
|
||||
|
||||
dev_priv->irq_enable_reg |= I915_USER_INTERRUPT;
|
||||
flag = 0;
|
||||
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_A)
|
||||
flag |= VSYNC_PIPEA_FLAG;
|
||||
if (dev_priv->vblank_pipe & DRM_I915_VBLANK_PIPE_B)
|
||||
flag |= VSYNC_PIPEB_FLAG;
|
||||
|
||||
I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg);
|
||||
dev_priv->irq_enabled = 1;
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, USER_INT_FLAG | flag);
|
||||
}
|
||||
|
||||
/* Set the vblank monitor pipe
|
||||
@@ -675,6 +448,8 @@ int i915_vblank_pipe_set(struct drm_device *dev, void *data,
|
||||
|
||||
dev_priv->vblank_pipe = pipe->pipe;
|
||||
|
||||
i915_enable_interrupt (dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -692,9 +467,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data,
|
||||
|
||||
flag = I915_READ(I915REG_INT_ENABLE_R);
|
||||
pipe->pipe = 0;
|
||||
if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT)
|
||||
if (flag & VSYNC_PIPEA_FLAG)
|
||||
pipe->pipe |= DRM_I915_VBLANK_PIPE_A;
|
||||
if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT)
|
||||
if (flag & VSYNC_PIPEB_FLAG)
|
||||
pipe->pipe |= DRM_I915_VBLANK_PIPE_B;
|
||||
|
||||
return 0;
|
||||
@@ -709,30 +484,27 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||
drm_i915_vblank_swap_t *swap = data;
|
||||
drm_i915_vbl_swap_t *vbl_swap;
|
||||
unsigned int pipe, seqtype, curseq, plane;
|
||||
unsigned int pipe, seqtype, curseq;
|
||||
unsigned long irqflags;
|
||||
struct list_head *list;
|
||||
int ret;
|
||||
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("%s called with no initialization\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!dev_priv->sarea_priv || dev_priv->sarea_priv->rotation) {
|
||||
if (dev_priv->sarea_priv->rotation) {
|
||||
DRM_DEBUG("Rotation not supported\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (swap->seqtype & ~(_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE |
|
||||
_DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS |
|
||||
_DRM_VBLANK_FLIP)) {
|
||||
_DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)) {
|
||||
DRM_ERROR("Invalid sequence type 0x%x\n", swap->seqtype);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
plane = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
|
||||
pipe = i915_get_pipe(dev, plane);
|
||||
pipe = (swap->seqtype & _DRM_VBLANK_SECONDARY) ? 1 : 0;
|
||||
|
||||
seqtype = swap->seqtype & (_DRM_VBLANK_RELATIVE | _DRM_VBLANK_ABSOLUTE);
|
||||
|
||||
@@ -743,11 +515,6 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
|
||||
spin_lock_irqsave(&dev->drw_lock, irqflags);
|
||||
|
||||
/* It makes no sense to schedule a swap for a drawable that doesn't have
|
||||
* valid information at this point. E.g. this could mean that the X
|
||||
* server is too old to push drawable information to the DRM, in which
|
||||
* case all such swaps would become ineffective.
|
||||
*/
|
||||
if (!drm_get_drawable_info(dev, swap->drawable)) {
|
||||
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
|
||||
DRM_DEBUG("Invalid drawable ID %d\n", swap->drawable);
|
||||
@@ -756,8 +523,7 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
|
||||
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
|
||||
|
||||
drm_update_vblank_count(dev, pipe);
|
||||
curseq = drm_vblank_count(dev, pipe);
|
||||
curseq = atomic_read(pipe ? &dev->vbl_received2 : &dev->vbl_received);
|
||||
|
||||
if (seqtype == _DRM_VBLANK_RELATIVE)
|
||||
swap->sequence += curseq;
|
||||
@@ -771,43 +537,14 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
}
|
||||
}
|
||||
|
||||
if (swap->seqtype & _DRM_VBLANK_FLIP) {
|
||||
swap->sequence--;
|
||||
|
||||
if ((curseq - swap->sequence) <= (1<<23)) {
|
||||
struct drm_drawable_info *drw;
|
||||
|
||||
LOCK_TEST_WITH_RETURN(dev, file_priv);
|
||||
|
||||
spin_lock_irqsave(&dev->drw_lock, irqflags);
|
||||
|
||||
drw = drm_get_drawable_info(dev, swap->drawable);
|
||||
|
||||
if (!drw) {
|
||||
spin_unlock_irqrestore(&dev->drw_lock,
|
||||
irqflags);
|
||||
DRM_DEBUG("Invalid drawable ID %d\n",
|
||||
swap->drawable);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
i915_dispatch_vsync_flip(dev, drw, plane);
|
||||
|
||||
spin_unlock_irqrestore(&dev->drw_lock, irqflags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
|
||||
|
||||
list_for_each(list, &dev_priv->vbl_swaps.head) {
|
||||
vbl_swap = list_entry(list, drm_i915_vbl_swap_t, head);
|
||||
|
||||
if (vbl_swap->drw_id == swap->drawable &&
|
||||
vbl_swap->plane == plane &&
|
||||
vbl_swap->pipe == pipe &&
|
||||
vbl_swap->sequence == swap->sequence) {
|
||||
vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
|
||||
spin_unlock_irqrestore(&dev_priv->swaps_lock, irqflags);
|
||||
DRM_DEBUG("Already scheduled\n");
|
||||
return 0;
|
||||
@@ -830,19 +567,9 @@ int i915_vblank_swap(struct drm_device *dev, void *data,
|
||||
|
||||
DRM_DEBUG("\n");
|
||||
|
||||
ret = drm_vblank_get(dev, pipe);
|
||||
if (ret) {
|
||||
drm_free(vbl_swap, sizeof(*vbl_swap), DRM_MEM_DRIVER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
vbl_swap->drw_id = swap->drawable;
|
||||
vbl_swap->plane = plane;
|
||||
vbl_swap->pipe = pipe;
|
||||
vbl_swap->sequence = swap->sequence;
|
||||
vbl_swap->flip = (swap->seqtype & _DRM_VBLANK_FLIP);
|
||||
|
||||
if (vbl_swap->flip)
|
||||
swap->sequence++;
|
||||
|
||||
spin_lock_irqsave(&dev_priv->swaps_lock, irqflags);
|
||||
|
||||
@@ -860,57 +587,37 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
|
||||
I915_WRITE16(I915REG_HWSTAM, 0xeffe);
|
||||
I915_WRITE16(I915REG_HWSTAM, 0xfffe);
|
||||
I915_WRITE16(I915REG_INT_MASK_R, 0x0);
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
|
||||
}
|
||||
|
||||
int i915_driver_irq_postinstall(struct drm_device * dev)
|
||||
void i915_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
int ret, num_pipes = 2;
|
||||
|
||||
spin_lock_init(&dev_priv->swaps_lock);
|
||||
INIT_LIST_HEAD(&dev_priv->vbl_swaps.head);
|
||||
dev_priv->swaps_pending = 0;
|
||||
|
||||
dev_priv->user_irq_refcount = 0;
|
||||
dev_priv->irq_enable_reg = 0;
|
||||
|
||||
ret = drm_vblank_init(dev, num_pipes);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
|
||||
|
||||
if (!dev_priv->vblank_pipe)
|
||||
dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A;
|
||||
i915_enable_interrupt(dev);
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);
|
||||
|
||||
/*
|
||||
* Initialize the hardware status page IRQ location.
|
||||
*/
|
||||
|
||||
I915_WRITE(I915REG_INSTPM, (1 << 5) | (1 << 21));
|
||||
return 0;
|
||||
}
|
||||
|
||||
void i915_driver_irq_uninstall(struct drm_device * dev)
|
||||
{
|
||||
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
|
||||
u32 temp;
|
||||
u16 temp;
|
||||
|
||||
if (!dev_priv)
|
||||
return;
|
||||
|
||||
dev_priv->irq_enabled = 0;
|
||||
I915_WRITE(I915REG_HWSTAM, 0xffffffff);
|
||||
I915_WRITE(I915REG_INT_MASK_R, 0xffffffff);
|
||||
I915_WRITE(I915REG_INT_ENABLE_R, 0x0);
|
||||
I915_WRITE16(I915REG_HWSTAM, 0xffff);
|
||||
I915_WRITE16(I915REG_INT_MASK_R, 0xffff);
|
||||
I915_WRITE16(I915REG_INT_ENABLE_R, 0x0);
|
||||
|
||||
temp = I915_READ(I915REG_PIPEASTAT);
|
||||
I915_WRITE(I915REG_PIPEASTAT, temp);
|
||||
temp = I915_READ(I915REG_PIPEBSTAT);
|
||||
I915_WRITE(I915REG_PIPEBSTAT, temp);
|
||||
temp = I915_READ(I915REG_INT_IDENTITY_R);
|
||||
I915_WRITE(I915REG_INT_IDENTITY_R, temp);
|
||||
temp = I915_READ16(I915REG_INT_IDENTITY_R);
|
||||
I915_WRITE16(I915REG_INT_IDENTITY_R, temp);
|
||||
}
|
||||
|
||||
@@ -45,16 +45,15 @@ static struct pci_device_id pciidlist[] = {
|
||||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA |
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL,
|
||||
.dev_priv_size = sizeof(drm_mga_buf_priv_t),
|
||||
.load = mga_driver_load,
|
||||
.unload = mga_driver_unload,
|
||||
.lastclose = mga_driver_lastclose,
|
||||
.dma_quiescent = mga_driver_dma_quiescent,
|
||||
.device_is_agp = mga_driver_device_is_agp,
|
||||
.get_vblank_counter = mga_get_vblank_counter,
|
||||
.enable_vblank = mga_enable_vblank,
|
||||
.disable_vblank = mga_disable_vblank,
|
||||
.vblank_wait = mga_driver_vblank_wait,
|
||||
.irq_preinstall = mga_driver_irq_preinstall,
|
||||
.irq_postinstall = mga_driver_irq_postinstall,
|
||||
.irq_uninstall = mga_driver_irq_uninstall,
|
||||
|
||||
@@ -120,7 +120,6 @@ typedef struct drm_mga_private {
|
||||
u32 clear_cmd;
|
||||
u32 maccess;
|
||||
|
||||
atomic_t vbl_received; /**< Number of vblanks received. */
|
||||
wait_queue_head_t fence_queue;
|
||||
atomic_t last_fence_retired;
|
||||
u32 next_fence_to_post;
|
||||
@@ -182,14 +181,11 @@ extern int mga_warp_install_microcode(drm_mga_private_t * dev_priv);
|
||||
extern int mga_warp_init(drm_mga_private_t * dev_priv);
|
||||
|
||||
/* mga_irq.c */
|
||||
extern int mga_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void mga_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 mga_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
extern int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
extern irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void mga_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern int mga_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void mga_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void mga_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern long mga_compat_ioctl(struct file *filp, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
|
||||
+19
-52
@@ -35,20 +35,6 @@
|
||||
#include "mga_drm.h"
|
||||
#include "mga_drv.h"
|
||||
|
||||
u32 mga_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
const drm_mga_private_t *const dev_priv =
|
||||
(drm_mga_private_t *) dev->dev_private;
|
||||
|
||||
if (crtc != 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
return atomic_read(&dev_priv->vbl_received);
|
||||
}
|
||||
|
||||
|
||||
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
@@ -61,8 +47,9 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
/* VBLANK interrupt */
|
||||
if (status & MGA_VLINEPEN) {
|
||||
MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
|
||||
atomic_inc(&dev_priv->vbl_received);
|
||||
drm_handle_vblank(dev, 0);
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
@@ -91,34 +78,22 @@ irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int mga_enable_vblank(struct drm_device *dev, int crtc)
|
||||
int mga_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
return 0;
|
||||
}
|
||||
|
||||
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void mga_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("tried to disable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
}
|
||||
|
||||
/* Do *NOT* disable the vertical refresh interrupt. MGA doesn't have
|
||||
* a nice hardware counter that tracks the number of refreshes when
|
||||
* the interrupt is disabled, and the kernel doesn't know the refresh
|
||||
* rate to calculate an estimate.
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
/* MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN); */
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int mga_driver_fence_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
@@ -150,22 +125,14 @@ void mga_driver_irq_preinstall(struct drm_device * dev)
|
||||
MGA_WRITE(MGA_ICLEAR, ~0);
|
||||
}
|
||||
|
||||
int mga_driver_irq_postinstall(struct drm_device * dev)
|
||||
void mga_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
|
||||
int ret;
|
||||
|
||||
ret = drm_vblank_init(dev, 1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);
|
||||
|
||||
/* Turn on soft trap interrupt. Vertical blank interrupts are enabled
|
||||
* in mga_enable_vblank.
|
||||
*/
|
||||
MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
|
||||
return 0;
|
||||
/* Turn on vertical blank interrupt and soft trap interrupt. */
|
||||
MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
|
||||
}
|
||||
|
||||
void mga_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
||||
@@ -43,13 +43,12 @@ static struct pci_device_id pciidlist[] = {
|
||||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED,
|
||||
DRIVER_HAVE_DMA | DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL,
|
||||
.dev_priv_size = sizeof(drm_r128_buf_priv_t),
|
||||
.preclose = r128_driver_preclose,
|
||||
.lastclose = r128_driver_lastclose,
|
||||
.get_vblank_counter = r128_get_vblank_counter,
|
||||
.enable_vblank = r128_enable_vblank,
|
||||
.disable_vblank = r128_disable_vblank,
|
||||
.vblank_wait = r128_driver_vblank_wait,
|
||||
.irq_preinstall = r128_driver_irq_preinstall,
|
||||
.irq_postinstall = r128_driver_irq_postinstall,
|
||||
.irq_uninstall = r128_driver_irq_uninstall,
|
||||
|
||||
@@ -97,8 +97,6 @@ typedef struct drm_r128_private {
|
||||
u32 crtc_offset;
|
||||
u32 crtc_offset_cntl;
|
||||
|
||||
atomic_t vbl_received;
|
||||
|
||||
u32 color_fmt;
|
||||
unsigned int front_offset;
|
||||
unsigned int front_pitch;
|
||||
@@ -151,12 +149,11 @@ extern int r128_wait_ring(drm_r128_private_t * dev_priv, int n);
|
||||
extern int r128_do_cce_idle(drm_r128_private_t * dev_priv);
|
||||
extern int r128_do_cleanup_cce(struct drm_device * dev);
|
||||
|
||||
extern int r128_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void r128_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern u32 r128_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
|
||||
extern irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void r128_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern int r128_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void r128_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void r128_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern void r128_driver_lastclose(struct drm_device * dev);
|
||||
extern void r128_driver_preclose(struct drm_device * dev,
|
||||
|
||||
+21
-36
@@ -35,16 +35,6 @@
|
||||
#include "r128_drm.h"
|
||||
#include "r128_drv.h"
|
||||
|
||||
u32 r128_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
const drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (crtc != 0)
|
||||
return 0;
|
||||
|
||||
return atomic_read(&dev_priv->vbl_received);
|
||||
}
|
||||
|
||||
irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
{
|
||||
struct drm_device *dev = (struct drm_device *) arg;
|
||||
@@ -56,38 +46,30 @@ irqreturn_t r128_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
/* VBLANK interrupt */
|
||||
if (status & R128_CRTC_VBLANK_INT) {
|
||||
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
|
||||
atomic_inc(&dev_priv->vbl_received);
|
||||
drm_handle_vblank(dev, 0);
|
||||
atomic_inc(&dev->vbl_received);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
||||
int r128_enable_vblank(struct drm_device *dev, int crtc)
|
||||
int r128_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
{
|
||||
drm_r128_private_t *dev_priv = dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void r128_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
if (crtc != 0)
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
|
||||
/*
|
||||
* FIXME: implement proper interrupt disable by using the vblank
|
||||
* counter register (if available)
|
||||
*
|
||||
* R128_WRITE(R128_GEN_INT_CNTL,
|
||||
* R128_READ(R128_GEN_INT_CNTL) & ~R128_CRTC_VBLANK_INT_EN);
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void r128_driver_irq_preinstall(struct drm_device * dev)
|
||||
@@ -100,9 +82,12 @@ void r128_driver_irq_preinstall(struct drm_device * dev)
|
||||
R128_WRITE(R128_GEN_INT_STATUS, R128_CRTC_VBLANK_INT_AK);
|
||||
}
|
||||
|
||||
int r128_driver_irq_postinstall(struct drm_device * dev)
|
||||
void r128_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
return drm_vblank_init(dev, 1);
|
||||
drm_r128_private_t *dev_priv = (drm_r128_private_t *) dev->dev_private;
|
||||
|
||||
/* Turn on VBL interrupt */
|
||||
R128_WRITE(R128_GEN_INT_CNTL, R128_CRTC_VBLANK_INT_EN);
|
||||
}
|
||||
|
||||
void r128_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
||||
@@ -59,7 +59,8 @@ static struct pci_device_id pciidlist[] = {
|
||||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_PCI_DMA | DRIVER_SG |
|
||||
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED,
|
||||
DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED |
|
||||
DRIVER_IRQ_VBL | DRIVER_IRQ_VBL2,
|
||||
.dev_priv_size = sizeof(drm_radeon_buf_priv_t),
|
||||
.load = radeon_driver_load,
|
||||
.firstopen = radeon_driver_firstopen,
|
||||
@@ -68,9 +69,8 @@ static struct drm_driver driver = {
|
||||
.postclose = radeon_driver_postclose,
|
||||
.lastclose = radeon_driver_lastclose,
|
||||
.unload = radeon_driver_unload,
|
||||
.get_vblank_counter = radeon_get_vblank_counter,
|
||||
.enable_vblank = radeon_enable_vblank,
|
||||
.disable_vblank = radeon_disable_vblank,
|
||||
.vblank_wait = radeon_driver_vblank_wait,
|
||||
.vblank_wait2 = radeon_driver_vblank_wait2,
|
||||
.dri_library_name = dri_library_name,
|
||||
.irq_preinstall = radeon_driver_irq_preinstall,
|
||||
.irq_postinstall = radeon_driver_irq_postinstall,
|
||||
|
||||
@@ -304,9 +304,6 @@ typedef struct drm_radeon_private {
|
||||
|
||||
u32 scratch_ages[5];
|
||||
|
||||
unsigned int crtc_last_cnt;
|
||||
unsigned int crtc2_last_cnt;
|
||||
|
||||
/* starting from here on, data is preserved accross an open */
|
||||
uint32_t flags; /* see radeon_chip_flags */
|
||||
unsigned long fb_aper_offset;
|
||||
@@ -377,13 +374,13 @@ extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *
|
||||
extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv);
|
||||
|
||||
extern void radeon_do_release(struct drm_device * dev);
|
||||
extern u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int radeon_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void radeon_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void radeon_do_release(struct drm_device * dev);
|
||||
extern int radeon_driver_vblank_wait(struct drm_device * dev,
|
||||
unsigned int *sequence);
|
||||
extern int radeon_driver_vblank_wait2(struct drm_device * dev,
|
||||
unsigned int *sequence);
|
||||
extern irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void radeon_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern int radeon_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void radeon_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void radeon_driver_irq_uninstall(struct drm_device * dev);
|
||||
extern int radeon_vblank_crtc_get(struct drm_device *dev);
|
||||
extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value);
|
||||
@@ -561,12 +558,6 @@ extern int r300_do_cp_cmdbuf(struct drm_device * dev,
|
||||
? DRM_READ32( dev_priv->ring_rptr, RADEON_SCRATCHOFF(x) ) \
|
||||
: RADEON_READ( RADEON_SCRATCH_REG0 + 4*(x) ) )
|
||||
|
||||
#define RADEON_CRTC_CRNT_FRAME 0x0214
|
||||
#define RADEON_CRTC2_CRNT_FRAME 0x0314
|
||||
|
||||
#define RADEON_CRTC_STATUS 0x005c
|
||||
#define RADEON_CRTC2_STATUS 0x03fc
|
||||
|
||||
#define RADEON_GEN_INT_CNTL 0x0040
|
||||
# define RADEON_CRTC_VBLANK_MASK (1 << 0)
|
||||
# define RADEON_CRTC2_VBLANK_MASK (1 << 9)
|
||||
|
||||
@@ -35,61 +35,12 @@
|
||||
#include "radeon_drm.h"
|
||||
#include "radeon_drv.h"
|
||||
|
||||
static void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state)
|
||||
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv,
|
||||
u32 mask)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
if (state)
|
||||
dev_priv->irq_enable_reg |= mask;
|
||||
else
|
||||
dev_priv->irq_enable_reg &= ~mask;
|
||||
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
|
||||
}
|
||||
|
||||
int radeon_enable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
switch (crtc) {
|
||||
case 0:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1);
|
||||
break;
|
||||
case 1:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
switch (crtc) {
|
||||
case 0:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0);
|
||||
break;
|
||||
case 1:
|
||||
radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0);
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
|
||||
crtc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv)
|
||||
{
|
||||
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) &
|
||||
(RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT |
|
||||
RADEON_CRTC2_VBLANK_STAT);
|
||||
|
||||
u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask;
|
||||
if (irqs)
|
||||
RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs);
|
||||
|
||||
return irqs;
|
||||
}
|
||||
|
||||
@@ -121,21 +72,39 @@ irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
/* Only consider the bits we're interested in - others could be used
|
||||
* outside the DRM
|
||||
*/
|
||||
stat = radeon_acknowledge_irqs(dev_priv);
|
||||
stat = radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
|
||||
RADEON_CRTC_VBLANK_STAT |
|
||||
RADEON_CRTC2_VBLANK_STAT));
|
||||
if (!stat)
|
||||
return IRQ_NONE;
|
||||
|
||||
stat &= dev_priv->irq_enable_reg;
|
||||
|
||||
/* SW interrupt */
|
||||
if (stat & RADEON_SW_INT_TEST)
|
||||
if (stat & RADEON_SW_INT_TEST) {
|
||||
DRM_WAKEUP(&dev_priv->swi_queue);
|
||||
}
|
||||
|
||||
/* VBLANK interrupt */
|
||||
if (stat & RADEON_CRTC_VBLANK_STAT)
|
||||
drm_handle_vblank(dev, 0);
|
||||
if (stat & RADEON_CRTC2_VBLANK_STAT)
|
||||
drm_handle_vblank(dev, 1);
|
||||
if (stat & (RADEON_CRTC_VBLANK_STAT|RADEON_CRTC2_VBLANK_STAT)) {
|
||||
int vblank_crtc = dev_priv->vblank_crtc;
|
||||
|
||||
if ((vblank_crtc &
|
||||
(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) ==
|
||||
(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) {
|
||||
if (stat & RADEON_CRTC_VBLANK_STAT)
|
||||
atomic_inc(&dev->vbl_received);
|
||||
if (stat & RADEON_CRTC2_VBLANK_STAT)
|
||||
atomic_inc(&dev->vbl_received2);
|
||||
} else if (((stat & RADEON_CRTC_VBLANK_STAT) &&
|
||||
(vblank_crtc & DRM_RADEON_VBLANK_CRTC1)) ||
|
||||
((stat & RADEON_CRTC2_VBLANK_STAT) &&
|
||||
(vblank_crtc & DRM_RADEON_VBLANK_CRTC2)))
|
||||
atomic_inc(&dev->vbl_received);
|
||||
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@@ -175,27 +144,54 @@ static int radeon_wait_irq(struct drm_device * dev, int swi_nr)
|
||||
return ret;
|
||||
}
|
||||
|
||||
u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
static int radeon_driver_vblank_do_wait(struct drm_device * dev,
|
||||
unsigned int *sequence, int crtc)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = dev->dev_private;
|
||||
u32 crtc_cnt_reg, crtc_status_reg;
|
||||
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
int ack = 0;
|
||||
atomic_t *counter;
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (crtc == 0) {
|
||||
crtc_cnt_reg = RADEON_CRTC_CRNT_FRAME;
|
||||
crtc_status_reg = RADEON_CRTC_STATUS;
|
||||
} else if (crtc == 1) {
|
||||
crtc_cnt_reg = RADEON_CRTC2_CRNT_FRAME;
|
||||
crtc_status_reg = RADEON_CRTC2_STATUS;
|
||||
} else {
|
||||
if (crtc == DRM_RADEON_VBLANK_CRTC1) {
|
||||
counter = &dev->vbl_received;
|
||||
ack |= RADEON_CRTC_VBLANK_STAT;
|
||||
} else if (crtc == DRM_RADEON_VBLANK_CRTC2) {
|
||||
counter = &dev->vbl_received2;
|
||||
ack |= RADEON_CRTC2_VBLANK_STAT;
|
||||
} else
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return RADEON_READ(crtc_cnt_reg) + (RADEON_READ(crtc_status_reg) & 1);
|
||||
radeon_acknowledge_irqs(dev_priv, ack);
|
||||
|
||||
dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
|
||||
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(counter))
|
||||
- *sequence) <= (1 << 23)));
|
||||
|
||||
*sequence = cur_vblank;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int radeon_driver_vblank_wait(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC1);
|
||||
}
|
||||
|
||||
int radeon_driver_vblank_wait2(struct drm_device *dev, unsigned int *sequence)
|
||||
{
|
||||
return radeon_driver_vblank_do_wait(dev, sequence, DRM_RADEON_VBLANK_CRTC2);
|
||||
}
|
||||
|
||||
/* Needs the lock as it touches the ring.
|
||||
@@ -238,6 +234,21 @@ int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_pr
|
||||
return radeon_wait_irq(dev, irqwait->irq_seq);
|
||||
}
|
||||
|
||||
static void radeon_enable_interrupt(struct drm_device *dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private;
|
||||
|
||||
dev_priv->irq_enable_reg = RADEON_SW_INT_ENABLE;
|
||||
if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC1)
|
||||
dev_priv->irq_enable_reg |= RADEON_CRTC_VBLANK_MASK;
|
||||
|
||||
if (dev_priv->vblank_crtc & DRM_RADEON_VBLANK_CRTC2)
|
||||
dev_priv->irq_enable_reg |= RADEON_CRTC2_VBLANK_MASK;
|
||||
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg);
|
||||
dev_priv->irq_enabled = 1;
|
||||
}
|
||||
|
||||
/* drm_dma.h hooks
|
||||
*/
|
||||
void radeon_driver_irq_preinstall(struct drm_device * dev)
|
||||
@@ -249,27 +260,20 @@ void radeon_driver_irq_preinstall(struct drm_device * dev)
|
||||
RADEON_WRITE(RADEON_GEN_INT_CNTL, 0);
|
||||
|
||||
/* Clear bits if they're already high */
|
||||
radeon_acknowledge_irqs(dev_priv);
|
||||
radeon_acknowledge_irqs(dev_priv, (RADEON_SW_INT_TEST_ACK |
|
||||
RADEON_CRTC_VBLANK_STAT |
|
||||
RADEON_CRTC2_VBLANK_STAT));
|
||||
}
|
||||
|
||||
int radeon_driver_irq_postinstall(struct drm_device * dev)
|
||||
void radeon_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_radeon_private_t *dev_priv =
|
||||
(drm_radeon_private_t *) dev->dev_private;
|
||||
int ret;
|
||||
|
||||
atomic_set(&dev_priv->swi_emitted, 0);
|
||||
DRM_INIT_WAITQUEUE(&dev_priv->swi_queue);
|
||||
|
||||
ret = drm_vblank_init(dev, 2);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
dev->max_vblank_count = 0x001fffff;
|
||||
|
||||
radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1);
|
||||
|
||||
return 0;
|
||||
radeon_enable_interrupt(dev);
|
||||
}
|
||||
|
||||
void radeon_driver_irq_uninstall(struct drm_device * dev)
|
||||
@@ -311,5 +315,6 @@ int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value)
|
||||
return -EINVAL;
|
||||
}
|
||||
dev_priv->vblank_crtc = (unsigned int)value;
|
||||
radeon_enable_interrupt(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,13 +40,11 @@ static struct pci_device_id pciidlist[] = {
|
||||
static struct drm_driver driver = {
|
||||
.driver_features =
|
||||
DRIVER_USE_AGP | DRIVER_USE_MTRR | DRIVER_HAVE_IRQ |
|
||||
DRIVER_IRQ_SHARED,
|
||||
DRIVER_IRQ_SHARED | DRIVER_IRQ_VBL,
|
||||
.load = via_driver_load,
|
||||
.unload = via_driver_unload,
|
||||
.context_dtor = via_final_context,
|
||||
.get_vblank_counter = via_get_vblank_counter,
|
||||
.enable_vblank = via_enable_vblank,
|
||||
.disable_vblank = via_disable_vblank,
|
||||
.vblank_wait = via_driver_vblank_wait,
|
||||
.irq_preinstall = via_driver_irq_preinstall,
|
||||
.irq_postinstall = via_driver_irq_postinstall,
|
||||
.irq_uninstall = via_driver_irq_uninstall,
|
||||
|
||||
@@ -75,7 +75,6 @@ typedef struct drm_via_private {
|
||||
struct timeval last_vblank;
|
||||
int last_vblank_valid;
|
||||
unsigned usec_per_vblank;
|
||||
atomic_t vbl_received;
|
||||
drm_via_state_t hc_state;
|
||||
char pci_buf[VIA_PCI_BUF_SIZE];
|
||||
const uint32_t *fire_offsets[VIA_FIRE_BUF_SIZE];
|
||||
@@ -131,13 +130,11 @@ extern int via_init_context(struct drm_device * dev, int context);
|
||||
extern int via_final_context(struct drm_device * dev, int context);
|
||||
|
||||
extern int via_do_cleanup_map(struct drm_device * dev);
|
||||
extern u32 via_get_vblank_counter(struct drm_device *dev, int crtc);
|
||||
extern int via_enable_vblank(struct drm_device *dev, int crtc);
|
||||
extern void via_disable_vblank(struct drm_device *dev, int crtc);
|
||||
extern int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence);
|
||||
|
||||
extern irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS);
|
||||
extern void via_driver_irq_preinstall(struct drm_device * dev);
|
||||
extern int via_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void via_driver_irq_postinstall(struct drm_device * dev);
|
||||
extern void via_driver_irq_uninstall(struct drm_device * dev);
|
||||
|
||||
extern int via_dma_cleanup(struct drm_device * dev);
|
||||
|
||||
+34
-47
@@ -92,17 +92,8 @@ static int via_irqmap_unichrome[] = {-1, -1, -1, 0, -1, 1};
|
||||
static unsigned time_diff(struct timeval *now, struct timeval *then)
|
||||
{
|
||||
return (now->tv_usec >= then->tv_usec) ?
|
||||
now->tv_usec - then->tv_usec :
|
||||
1000000 - (then->tv_usec - now->tv_usec);
|
||||
}
|
||||
|
||||
u32 via_get_vblank_counter(struct drm_device *dev, int crtc)
|
||||
{
|
||||
drm_via_private_t *dev_priv = dev->dev_private;
|
||||
if (crtc != 0)
|
||||
return 0;
|
||||
|
||||
return atomic_read(&dev_priv->vbl_received);
|
||||
now->tv_usec - then->tv_usec :
|
||||
1000000 - (then->tv_usec - now->tv_usec);
|
||||
}
|
||||
|
||||
irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
@@ -117,8 +108,8 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
if (status & VIA_IRQ_VBLANK_PENDING) {
|
||||
atomic_inc(&dev_priv->vbl_received);
|
||||
if (!(atomic_read(&dev_priv->vbl_received) & 0x0F)) {
|
||||
atomic_inc(&dev->vbl_received);
|
||||
if (!(atomic_read(&dev->vbl_received) & 0x0F)) {
|
||||
do_gettimeofday(&cur_vblank);
|
||||
if (dev_priv->last_vblank_valid) {
|
||||
dev_priv->usec_per_vblank =
|
||||
@@ -128,11 +119,12 @@ irqreturn_t via_driver_irq_handler(DRM_IRQ_ARGS)
|
||||
dev_priv->last_vblank = cur_vblank;
|
||||
dev_priv->last_vblank_valid = 1;
|
||||
}
|
||||
if (!(atomic_read(&dev_priv->vbl_received) & 0xFF)) {
|
||||
if (!(atomic_read(&dev->vbl_received) & 0xFF)) {
|
||||
DRM_DEBUG("US per vblank is: %u\n",
|
||||
dev_priv->usec_per_vblank);
|
||||
}
|
||||
drm_handle_vblank(dev, 0);
|
||||
DRM_WAKEUP(&dev->vbl_queue);
|
||||
drm_vbl_send_signals(dev);
|
||||
handled = 1;
|
||||
}
|
||||
|
||||
@@ -171,34 +163,31 @@ static __inline__ void viadrv_acknowledge_irqs(drm_via_private_t * dev_priv)
|
||||
}
|
||||
}
|
||||
|
||||
int via_enable_vblank(struct drm_device *dev, int crtc)
|
||||
int via_driver_vblank_wait(struct drm_device * dev, unsigned int *sequence)
|
||||
{
|
||||
drm_via_private_t *dev_priv = dev->dev_private;
|
||||
u32 status;
|
||||
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
|
||||
unsigned int cur_vblank;
|
||||
int ret = 0;
|
||||
|
||||
if (crtc != 0) {
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
DRM_DEBUG("\n");
|
||||
if (!dev_priv) {
|
||||
DRM_ERROR("called with no initialization\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
VIA_WRITE(VIA_REG_INTERRUPT, status & VIA_IRQ_VBLANK_ENABLE);
|
||||
viadrv_acknowledge_irqs(dev_priv);
|
||||
|
||||
VIA_WRITE8(0x83d4, 0x11);
|
||||
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
|
||||
/* Assume that the user has missed the current sequence number
|
||||
* by about a day rather than she wants to wait for years
|
||||
* using vertical blanks...
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
|
||||
(((cur_vblank = atomic_read(&dev->vbl_received)) -
|
||||
*sequence) <= (1 << 23)));
|
||||
|
||||
void via_disable_vblank(struct drm_device *dev, int crtc)
|
||||
{
|
||||
drm_via_private_t *dev_priv = dev->dev_private;
|
||||
|
||||
VIA_WRITE8(0x83d4, 0x11);
|
||||
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) & ~0x30);
|
||||
|
||||
if (crtc != 0)
|
||||
DRM_ERROR("%s: bad crtc %d\n", __FUNCTION__, crtc);
|
||||
*sequence = cur_vblank;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -303,25 +292,23 @@ void via_driver_irq_preinstall(struct drm_device * dev)
|
||||
}
|
||||
}
|
||||
|
||||
int via_driver_irq_postinstall(struct drm_device * dev)
|
||||
void via_driver_irq_postinstall(struct drm_device * dev)
|
||||
{
|
||||
drm_via_private_t *dev_priv = (drm_via_private_t *) dev->dev_private;
|
||||
u32 status;
|
||||
|
||||
DRM_DEBUG("via_driver_irq_postinstall\n");
|
||||
if (!dev_priv)
|
||||
return -EINVAL;
|
||||
DRM_DEBUG("\n");
|
||||
if (dev_priv) {
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
|
||||
| dev_priv->irq_enable_mask);
|
||||
|
||||
drm_vblank_init(dev, 1);
|
||||
status = VIA_READ(VIA_REG_INTERRUPT);
|
||||
VIA_WRITE(VIA_REG_INTERRUPT, status | VIA_IRQ_GLOBAL
|
||||
| dev_priv->irq_enable_mask);
|
||||
/* Some magic, oh for some data sheets ! */
|
||||
|
||||
/* Some magic, oh for some data sheets ! */
|
||||
VIA_WRITE8(0x83d4, 0x11);
|
||||
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
|
||||
VIA_WRITE8(0x83d4, 0x11);
|
||||
VIA_WRITE8(0x83d5, VIA_READ8(0x83d5) | 0x30);
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void via_driver_irq_uninstall(struct drm_device * dev)
|
||||
|
||||
@@ -112,3 +112,12 @@ config HW_RANDOM_PASEMI
|
||||
|
||||
If unsure, say Y.
|
||||
|
||||
config HW_RANDOM_VIRTIO
|
||||
tristate "VirtIO Random Number Generator support"
|
||||
depends on HW_RANDOM && VIRTIO
|
||||
---help---
|
||||
This driver provides kernel-side support for the virtual Random Number
|
||||
Generator hardware.
|
||||
|
||||
To compile this driver as a module, choose M here: the
|
||||
module will be called virtio-rng. If unsure, say N.
|
||||
|
||||
@@ -11,3 +11,4 @@ obj-$(CONFIG_HW_RANDOM_VIA) += via-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_IXP4XX) += ixp4xx-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_OMAP) += omap-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_PASEMI) += pasemi-rng.o
|
||||
obj-$(CONFIG_HW_RANDOM_VIRTIO) += virtio-rng.o
|
||||
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Randomness driver for virtio
|
||||
* Copyright (C) 2007, 2008 Rusty Russell IBM Corporation
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include <linux/err.h>
|
||||
#include <linux/hw_random.h>
|
||||
#include <linux/scatterlist.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/virtio.h>
|
||||
#include <linux/virtio_rng.h>
|
||||
|
||||
/* The host will fill any buffer we give it with sweet, sweet randomness. We
|
||||
* give it 64 bytes at a time, and the hwrng framework takes it 4 bytes at a
|
||||
* time. */
|
||||
#define RANDOM_DATA_SIZE 64
|
||||
|
||||
static struct virtqueue *vq;
|
||||
static u32 *random_data;
|
||||
static unsigned int data_left;
|
||||
static DECLARE_COMPLETION(have_data);
|
||||
|
||||
static void random_recv_done(struct virtqueue *vq)
|
||||
{
|
||||
int len;
|
||||
|
||||
/* We never get spurious callbacks. */
|
||||
if (!vq->vq_ops->get_buf(vq, &len))
|
||||
BUG();
|
||||
|
||||
data_left = len / sizeof(random_data[0]);
|
||||
complete(&have_data);
|
||||
}
|
||||
|
||||
static void register_buffer(void)
|
||||
{
|
||||
struct scatterlist sg;
|
||||
|
||||
sg_init_one(&sg, random_data, RANDOM_DATA_SIZE);
|
||||
/* There should always be room for one buffer. */
|
||||
if (vq->vq_ops->add_buf(vq, &sg, 0, 1, random_data) != 0)
|
||||
BUG();
|
||||
vq->vq_ops->kick(vq);
|
||||
}
|
||||
|
||||
/* At least we don't udelay() in a loop like some other drivers. */
|
||||
static int virtio_data_present(struct hwrng *rng, int wait)
|
||||
{
|
||||
if (data_left)
|
||||
return 1;
|
||||
|
||||
if (!wait)
|
||||
return 0;
|
||||
|
||||
wait_for_completion(&have_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* virtio_data_present() must have succeeded before this is called. */
|
||||
static int virtio_data_read(struct hwrng *rng, u32 *data)
|
||||
{
|
||||
BUG_ON(!data_left);
|
||||
|
||||
*data = random_data[--data_left];
|
||||
|
||||
if (!data_left) {
|
||||
init_completion(&have_data);
|
||||
register_buffer();
|
||||
}
|
||||
return sizeof(*data);
|
||||
}
|
||||
|
||||
static struct hwrng virtio_hwrng = {
|
||||
.name = "virtio",
|
||||
.data_present = virtio_data_present,
|
||||
.data_read = virtio_data_read,
|
||||
};
|
||||
|
||||
static int virtrng_probe(struct virtio_device *vdev)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* We expect a single virtqueue. */
|
||||
vq = vdev->config->find_vq(vdev, 0, random_recv_done);
|
||||
if (IS_ERR(vq))
|
||||
return PTR_ERR(vq);
|
||||
|
||||
err = hwrng_register(&virtio_hwrng);
|
||||
if (err) {
|
||||
vdev->config->del_vq(vq);
|
||||
return err;
|
||||
}
|
||||
|
||||
register_buffer();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void virtrng_remove(struct virtio_device *vdev)
|
||||
{
|
||||
vdev->config->reset(vdev);
|
||||
hwrng_unregister(&virtio_hwrng);
|
||||
vdev->config->del_vq(vq);
|
||||
}
|
||||
|
||||
static struct virtio_device_id id_table[] = {
|
||||
{ VIRTIO_ID_RNG, VIRTIO_DEV_ANY_ID },
|
||||
{ 0 },
|
||||
};
|
||||
|
||||
static struct virtio_driver virtio_rng = {
|
||||
.driver.name = KBUILD_MODNAME,
|
||||
.driver.owner = THIS_MODULE,
|
||||
.id_table = id_table,
|
||||
.probe = virtrng_probe,
|
||||
.remove = __devexit_p(virtrng_remove),
|
||||
};
|
||||
|
||||
static int __init init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
random_data = kmalloc(RANDOM_DATA_SIZE, GFP_KERNEL);
|
||||
if (!random_data)
|
||||
return -ENOMEM;
|
||||
|
||||
err = register_virtio_driver(&virtio_rng);
|
||||
if (err)
|
||||
kfree(random_data);
|
||||
return err;
|
||||
}
|
||||
|
||||
static void __exit fini(void)
|
||||
{
|
||||
kfree(random_data);
|
||||
unregister_virtio_driver(&virtio_rng);
|
||||
}
|
||||
module_init(init);
|
||||
module_exit(fini);
|
||||
|
||||
MODULE_DEVICE_TABLE(virtio, id_table);
|
||||
MODULE_DESCRIPTION("Virtio random number driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -2,7 +2,7 @@
|
||||
# Makefile for the Computone IntelliPort Plus Driver
|
||||
#
|
||||
|
||||
obj-$(CONFIG_COMPUTONE) += ip2.o ip2main.o
|
||||
obj-$(CONFIG_COMPUTONE) += ip2.o
|
||||
|
||||
ip2-objs := ip2base.o
|
||||
ip2-objs := ip2base.o ip2main.o
|
||||
|
||||
|
||||
@@ -345,27 +345,6 @@ have_requested_irq( char irq )
|
||||
return 0;
|
||||
}
|
||||
|
||||
/******************************************************************************/
|
||||
/* Function: init_module() */
|
||||
/* Parameters: None */
|
||||
/* Returns: Success (0) */
|
||||
/* */
|
||||
/* Description: */
|
||||
/* This is a required entry point for an installable module. It simply calls */
|
||||
/* the driver initialisation function and returns what it returns. */
|
||||
/******************************************************************************/
|
||||
#ifdef MODULE
|
||||
static int __init
|
||||
ip2_init_module(void)
|
||||
{
|
||||
#ifdef IP2DEBUG_INIT
|
||||
printk (KERN_DEBUG "Loading module ...\n" );
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
module_init(ip2_init_module);
|
||||
#endif /* MODULE */
|
||||
|
||||
/******************************************************************************/
|
||||
/* Function: cleanup_module() */
|
||||
/* Parameters: None */
|
||||
@@ -779,8 +758,6 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
EXPORT_SYMBOL(ip2_loadmain);
|
||||
|
||||
/******************************************************************************/
|
||||
/* Function: ip2_init_board() */
|
||||
/* Parameters: Index of board in configuration structure */
|
||||
|
||||
+10
-3
@@ -282,16 +282,20 @@ static int opost(unsigned char c, struct tty_struct *tty)
|
||||
if (O_ONLRET(tty))
|
||||
tty->column = 0;
|
||||
if (O_ONLCR(tty)) {
|
||||
if (space < 2)
|
||||
if (space < 2) {
|
||||
unlock_kernel();
|
||||
return -1;
|
||||
}
|
||||
tty_put_char(tty, '\r');
|
||||
tty->column = 0;
|
||||
}
|
||||
tty->canon_column = tty->column;
|
||||
break;
|
||||
case '\r':
|
||||
if (O_ONOCR(tty) && tty->column == 0)
|
||||
if (O_ONOCR(tty) && tty->column == 0) {
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
}
|
||||
if (O_OCRNL(tty)) {
|
||||
c = '\n';
|
||||
if (O_ONLRET(tty))
|
||||
@@ -303,10 +307,13 @@ static int opost(unsigned char c, struct tty_struct *tty)
|
||||
case '\t':
|
||||
spaces = 8 - (tty->column & 7);
|
||||
if (O_TABDLY(tty) == XTABS) {
|
||||
if (space < spaces)
|
||||
if (space < spaces) {
|
||||
unlock_kernel();
|
||||
return -1;
|
||||
}
|
||||
tty->column += spaces;
|
||||
tty->ops->write(tty, " ", spaces);
|
||||
unlock_kernel();
|
||||
return 0;
|
||||
}
|
||||
tty->column += spaces;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/byteorder/generic.h>
|
||||
#include <asm/byteorder.h>
|
||||
#include <asm/sn/sn_sal.h>
|
||||
#include <asm/unaligned.h>
|
||||
#include "snsc.h"
|
||||
|
||||
@@ -402,6 +402,7 @@ static struct sysrq_key_op *sysrq_key_table[36] = {
|
||||
&sysrq_showstate_blocked_op, /* w */
|
||||
/* x: May be registered on ppc/powerpc for xmon */
|
||||
NULL, /* x */
|
||||
/* y: May be registered on sparc64 for global register dump */
|
||||
NULL, /* y */
|
||||
NULL /* z */
|
||||
};
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
* Authors: Dave Boutcher <boutcher@us.ibm.com>
|
||||
* Ryan Arnold <ryanarn@us.ibm.com>
|
||||
* Colin Devilbiss <devilbis@us.ibm.com>
|
||||
* Stephen Rothwell <sfr@au1.ibm.com>
|
||||
* Stephen Rothwell
|
||||
*
|
||||
* (C) Copyright 2000, 2001, 2002, 2003, 2004 IBM Corporation
|
||||
*
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* Authors: Dave Boutcher <boutcher@us.ibm.com>
|
||||
* Ryan Arnold <ryanarn@us.ibm.com>
|
||||
* Colin Devilbiss <devilbis@us.ibm.com>
|
||||
* Stephen Rothwell <sfr@au1.ibm.com>
|
||||
* Stephen Rothwell
|
||||
*
|
||||
* (C) Copyright 2000-2004 IBM Corporation
|
||||
*
|
||||
|
||||
@@ -89,9 +89,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state);
|
||||
|
||||
static struct tty_driver *scc_driver;
|
||||
|
||||
struct scc_port scc_ports[2];
|
||||
|
||||
int scc_initialized = 0;
|
||||
static struct scc_port scc_ports[2];
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
* Interface from generic_serial.c back here
|
||||
|
||||
@@ -928,13 +928,13 @@ static int cpufreq_add_dev(struct sys_device *sys_dev)
|
||||
policy->user_policy.policy = policy->policy;
|
||||
policy->user_policy.governor = policy->governor;
|
||||
|
||||
unlock_policy_rwsem_write(cpu);
|
||||
|
||||
if (ret) {
|
||||
dprintk("setting policy failed\n");
|
||||
goto err_out_unregister;
|
||||
}
|
||||
|
||||
unlock_policy_rwsem_write(cpu);
|
||||
|
||||
kobject_uevent(&policy->kobj, KOBJ_ADD);
|
||||
module_put(cpufreq_driver->owner);
|
||||
dprintk("initialization complete\n");
|
||||
|
||||
@@ -2,6 +2,11 @@
|
||||
* linux/drivers/cpufreq/freq_table.c
|
||||
*
|
||||
* Copyright (C) 2002 - 2003 Dominik Brodowski
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
|
||||
@@ -821,10 +821,10 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
|
||||
|
||||
dev_dbg(device->common.dev, "%s\n", __func__);
|
||||
|
||||
src = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
|
||||
src = kmalloc(IOP_ADMA_TEST_SIZE, GFP_KERNEL);
|
||||
if (!src)
|
||||
return -ENOMEM;
|
||||
dest = kzalloc(sizeof(u8) * IOP_ADMA_TEST_SIZE, GFP_KERNEL);
|
||||
dest = kzalloc(IOP_ADMA_TEST_SIZE, GFP_KERNEL);
|
||||
if (!dest) {
|
||||
kfree(src);
|
||||
return -ENOMEM;
|
||||
@@ -834,8 +834,6 @@ static int __devinit iop_adma_memcpy_self_test(struct iop_adma_device *device)
|
||||
for (i = 0; i < IOP_ADMA_TEST_SIZE; i++)
|
||||
((u8 *) src)[i] = (u8)i;
|
||||
|
||||
memset(dest, 0, IOP_ADMA_TEST_SIZE);
|
||||
|
||||
/* Start copy, using first DMA channel */
|
||||
dma_chan = container_of(device->common.channels.next,
|
||||
struct dma_chan,
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <asm/mpc85xx.h>
|
||||
#include "edac_module.h"
|
||||
#include "edac_core.h"
|
||||
#include "mpc85xx_edac.h"
|
||||
@@ -43,8 +42,6 @@ static u32 orig_pci_err_en;
|
||||
static u32 orig_l2_err_disable;
|
||||
static u32 orig_hid1;
|
||||
|
||||
static const char *mpc85xx_ctl_name = "MPC85xx";
|
||||
|
||||
/************************ MC SYSFS parts ***********************************/
|
||||
|
||||
static ssize_t mpc85xx_mc_inject_data_hi_show(struct mem_ctl_info *mci,
|
||||
|
||||
@@ -113,6 +113,11 @@ static int fw_device_op_open(struct inode *inode, struct file *file)
|
||||
if (device == NULL)
|
||||
return -ENODEV;
|
||||
|
||||
if (fw_device_is_shutdown(device)) {
|
||||
fw_device_put(device);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
||||
if (client == NULL) {
|
||||
fw_device_put(device);
|
||||
@@ -901,6 +906,9 @@ fw_device_op_ioctl(struct file *file,
|
||||
{
|
||||
struct client *client = file->private_data;
|
||||
|
||||
if (fw_device_is_shutdown(client->device))
|
||||
return -ENODEV;
|
||||
|
||||
return dispatch_ioctl(client, cmd, (void __user *) arg);
|
||||
}
|
||||
|
||||
@@ -911,6 +919,9 @@ fw_device_op_compat_ioctl(struct file *file,
|
||||
{
|
||||
struct client *client = file->private_data;
|
||||
|
||||
if (fw_device_is_shutdown(client->device))
|
||||
return -ENODEV;
|
||||
|
||||
return dispatch_ioctl(client, cmd, compat_ptr(arg));
|
||||
}
|
||||
#endif
|
||||
@@ -922,6 +933,9 @@ static int fw_device_op_mmap(struct file *file, struct vm_area_struct *vma)
|
||||
unsigned long size;
|
||||
int page_count, retval;
|
||||
|
||||
if (fw_device_is_shutdown(client->device))
|
||||
return -ENODEV;
|
||||
|
||||
/* FIXME: We could support multiple buffers, but we don't. */
|
||||
if (client->buffer.pages != NULL)
|
||||
return -EBUSY;
|
||||
|
||||
@@ -127,7 +127,7 @@ int __init gpiochip_reserve(int start, int ngpio)
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio))
|
||||
if (!gpio_is_valid(start) || !gpio_is_valid(start + ngpio - 1))
|
||||
return -EINVAL;
|
||||
|
||||
spin_lock_irqsave(&gpio_lock, flags);
|
||||
@@ -170,7 +170,7 @@ int gpiochip_add(struct gpio_chip *chip)
|
||||
unsigned id;
|
||||
int base = chip->base;
|
||||
|
||||
if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio))
|
||||
if ((!gpio_is_valid(base) || !gpio_is_valid(base + chip->ngpio - 1))
|
||||
&& base >= 0) {
|
||||
status = -EINVAL;
|
||||
goto fail;
|
||||
@@ -207,7 +207,7 @@ fail:
|
||||
/* failures here can mean systems won't boot... */
|
||||
if (status)
|
||||
pr_err("gpiochip_add: gpios %d..%d (%s) not registered\n",
|
||||
chip->base, chip->base + chip->ngpio,
|
||||
chip->base, chip->base + chip->ngpio - 1,
|
||||
chip->label ? : "generic");
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -168,7 +168,7 @@ static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
|
||||
{
|
||||
struct mcp23s08 *mcp;
|
||||
char bank;
|
||||
unsigned t;
|
||||
int t;
|
||||
unsigned mask;
|
||||
|
||||
mcp = container_of(chip, struct mcp23s08, chip);
|
||||
|
||||
@@ -30,6 +30,7 @@ static const struct i2c_device_id pca953x_id[] = {
|
||||
{ "pca9537", 4, },
|
||||
{ "pca9538", 8, },
|
||||
{ "pca9539", 16, },
|
||||
{ "pca9554", 8, },
|
||||
{ "pca9555", 16, },
|
||||
{ "pca9557", 8, },
|
||||
/* REVISIT several pca955x parts should work here too */
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: hid-debug.h,v 1.8 2001/09/25 09:37:57 vojtech Exp $
|
||||
*
|
||||
* (c) 1999 Andreas Gal <gal@cs.uni-magdeburg.de>
|
||||
* (c) 2000-2001 Vojtech Pavlik <vojtech@ucw.cz>
|
||||
* (c) 2007 Jiri Kosina
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: hid-input.c,v 1.2 2002/04/23 00:59:25 rdamazio Exp $
|
||||
*
|
||||
* Copyright (c) 2000-2001 Vojtech Pavlik
|
||||
* Copyright (c) 2006-2007 Jiri Kosina
|
||||
*
|
||||
@@ -218,8 +216,9 @@ int hidinput_apple_event(struct hid_device *hid, struct input_dev *input,
|
||||
}
|
||||
}
|
||||
|
||||
if (test_bit(usage->code, hid->pb_pressed_numlock) ||
|
||||
test_bit(LED_NUML, input->led)) {
|
||||
if (hid->quirks & HID_QUIRK_APPLE_NUMLOCK_EMULATION && (
|
||||
test_bit(usage->code, hid->pb_pressed_numlock) ||
|
||||
test_bit(LED_NUML, input->led))) {
|
||||
trans = find_translation(powerbook_numlock_keys, usage->code);
|
||||
|
||||
if (trans) {
|
||||
|
||||
@@ -325,6 +325,10 @@
|
||||
#define USB_DEVICE_ID_MGE_UPS 0xffff
|
||||
#define USB_DEVICE_ID_MGE_UPS1 0x0001
|
||||
|
||||
#define USB_VENDOR_ID_MICROCHIP 0x04d8
|
||||
#define USB_DEVICE_ID_PICKIT1 0x0032
|
||||
#define USB_DEVICE_ID_PICKIT2 0x0033
|
||||
|
||||
#define USB_VENDOR_ID_MICROSOFT 0x045e
|
||||
#define USB_DEVICE_ID_SIDEWINDER_GV 0x003b
|
||||
#define USB_DEVICE_ID_WIRELESS_OPTICAL_DESKTOP_3_0 0x009d
|
||||
@@ -371,6 +375,9 @@
|
||||
#define USB_VENDOR_ID_SONY 0x054c
|
||||
#define USB_DEVICE_ID_SONY_PS3_CONTROLLER 0x0268
|
||||
|
||||
#define USB_VENDOR_ID_SOUNDGRAPH 0x15c2
|
||||
#define USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD 0x0038
|
||||
|
||||
#define USB_VENDOR_ID_SUN 0x0430
|
||||
#define USB_DEVICE_ID_RARITAN_KVM_DONGLE 0xcdab
|
||||
|
||||
@@ -567,6 +574,7 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_PANJIT, 0x0002, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_PANJIT, 0x0003, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_PANJIT, 0x0004, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_SOUNDGRAPH, USB_DEVICE_ID_SOUNDGRAPH_IMON_LCD, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_LABPRO, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_GOTEMP, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_VERNIER, USB_DEVICE_ID_VERNIER_SKIP, HID_QUIRK_IGNORE },
|
||||
@@ -580,6 +588,9 @@ static const struct hid_blacklist {
|
||||
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_FLAIR, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_ACECAD, USB_DEVICE_ID_ACECAD_302, HID_QUIRK_IGNORE },
|
||||
|
||||
{ USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT1, HID_QUIRK_IGNORE },
|
||||
{ USB_VENDOR_ID_MICROCHIP, USB_DEVICE_ID_PICKIT2, HID_QUIRK_IGNORE },
|
||||
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_ELITE_KBD, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_CORDLESS_DESKTOP_LX500, HID_QUIRK_LOGITECH_IGNORE_DOUBLED_WHEEL | HID_QUIRK_LOGITECH_EXPANDED_KEYMAP },
|
||||
|
||||
@@ -611,28 +622,28 @@ static const struct hid_blacklist {
|
||||
|
||||
{ USB_VENDOR_ID_WISEGROUP_LTD, USB_DEVICE_ID_SMARTJOY_DUAL_PLUS, HID_QUIRK_NOGET | HID_QUIRK_MULTI_INPUT },
|
||||
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER3_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE | HID_QUIRK_APPLE_ISO_KEYBOARD},
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ANSI, HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_JIS, HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER4_HF_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ANSI, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_ISO, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_APPLE_ISO_KEYBOARD },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_JIS, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
{ USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY, HID_QUIRK_APPLE_NUMLOCK_EMULATION | HID_QUIRK_APPLE_HAS_FN | HID_QUIRK_IGNORE_MOUSE },
|
||||
|
||||
{ USB_VENDOR_ID_DELL, USB_DEVICE_ID_DELL_W7658, HID_QUIRK_RESET_LEDS },
|
||||
{ USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_KBD, HID_QUIRK_RESET_LEDS },
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: usbkbd.c,v 1.27 2001/12/27 10:37:41 vojtech Exp $
|
||||
*
|
||||
* Copyright (c) 1999-2001 Vojtech Pavlik
|
||||
*
|
||||
* USB HIDBP Keyboard support
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: usbmouse.c,v 1.15 2001/12/27 10:37:41 vojtech Exp $
|
||||
*
|
||||
* Copyright (c) 1999-2001 Vojtech Pavlik
|
||||
*
|
||||
* USB HIDBP Mouse support
|
||||
|
||||
@@ -330,6 +330,20 @@ config SENSORS_CORETEMP
|
||||
sensor inside your CPU. Supported all are all known variants
|
||||
of Intel Core family.
|
||||
|
||||
config SENSORS_IBMAEM
|
||||
tristate "IBM Active Energy Manager temperature/power sensors and control"
|
||||
select IPMI_SI
|
||||
depends on IPMI_HANDLER
|
||||
help
|
||||
If you say yes here you get support for the temperature and
|
||||
power sensors and capping hardware in various IBM System X
|
||||
servers that support Active Energy Manager. This includes
|
||||
the x3350, x3550, x3650, x3655, x3755, x3850 M2, x3950 M2,
|
||||
and certain HS2x/LS2x/QS2x blades.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called ibmaem.
|
||||
|
||||
config SENSORS_IBMPEX
|
||||
tristate "IBM PowerExecutive temperature/power sensors"
|
||||
select IPMI_SI
|
||||
|
||||
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
|
||||
obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o
|
||||
obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o
|
||||
obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o
|
||||
obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o
|
||||
obj-$(CONFIG_SENSORS_IBMPEX) += ibmpex.o
|
||||
obj-$(CONFIG_SENSORS_IT87) += it87.o
|
||||
obj-$(CONFIG_SENSORS_K8TEMP) += k8temp.o
|
||||
|
||||
@@ -515,6 +515,7 @@ static struct dmi_system_id __initdata hdaps_whitelist[] = {
|
||||
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R50"),
|
||||
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R51"),
|
||||
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad R52"),
|
||||
HDAPS_DMI_MATCH_INVERT("LENOVO", "ThinkPad R61i"),
|
||||
HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T41p"),
|
||||
HDAPS_DMI_MATCH_NORMAL("IBM", "ThinkPad T41"),
|
||||
HDAPS_DMI_MATCH_INVERT("IBM", "ThinkPad T42p"),
|
||||
|
||||
+34
-5
@@ -111,6 +111,7 @@ struct i5k_amb_data {
|
||||
void __iomem *amb_mmio;
|
||||
struct i5k_device_attribute *attrs;
|
||||
unsigned int num_attrs;
|
||||
unsigned long chipset_id;
|
||||
};
|
||||
|
||||
static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
|
||||
@@ -382,7 +383,8 @@ err:
|
||||
return res;
|
||||
}
|
||||
|
||||
static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
|
||||
static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data,
|
||||
unsigned long devid)
|
||||
{
|
||||
struct pci_dev *pcidev;
|
||||
u32 val32;
|
||||
@@ -390,7 +392,7 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
|
||||
|
||||
/* Find AMB register memory space */
|
||||
pcidev = pci_get_device(PCI_VENDOR_ID_INTEL,
|
||||
PCI_DEVICE_ID_INTEL_5000_ERR,
|
||||
devid,
|
||||
NULL);
|
||||
if (!pcidev)
|
||||
return -ENODEV;
|
||||
@@ -409,6 +411,8 @@ static int __devinit i5k_find_amb_registers(struct i5k_amb_data *data)
|
||||
goto out;
|
||||
}
|
||||
|
||||
data->chipset_id = devid;
|
||||
|
||||
res = 0;
|
||||
out:
|
||||
pci_dev_put(pcidev);
|
||||
@@ -441,10 +445,30 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static unsigned long i5k_channel_pci_id(struct i5k_amb_data *data,
|
||||
unsigned long channel)
|
||||
{
|
||||
switch (data->chipset_id) {
|
||||
case PCI_DEVICE_ID_INTEL_5000_ERR:
|
||||
return PCI_DEVICE_ID_INTEL_5000_FBD0 + channel;
|
||||
case PCI_DEVICE_ID_INTEL_5400_ERR:
|
||||
return PCI_DEVICE_ID_INTEL_5400_FBD0 + channel;
|
||||
default:
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned long chipset_ids[] = {
|
||||
PCI_DEVICE_ID_INTEL_5000_ERR,
|
||||
PCI_DEVICE_ID_INTEL_5400_ERR,
|
||||
0
|
||||
};
|
||||
|
||||
static int __devinit i5k_amb_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct i5k_amb_data *data;
|
||||
struct resource *reso;
|
||||
int i;
|
||||
int res = -ENODEV;
|
||||
|
||||
data = kzalloc(sizeof(*data), GFP_KERNEL);
|
||||
@@ -452,19 +476,24 @@ static int __devinit i5k_amb_probe(struct platform_device *pdev)
|
||||
return -ENOMEM;
|
||||
|
||||
/* Figure out where the AMB registers live */
|
||||
res = i5k_find_amb_registers(data);
|
||||
i = 0;
|
||||
do {
|
||||
res = i5k_find_amb_registers(data, chipset_ids[i]);
|
||||
i++;
|
||||
} while (res && chipset_ids[i]);
|
||||
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
/* Copy the DIMM presence map for the first two channels */
|
||||
res = i5k_channel_probe(&data->amb_present[0],
|
||||
PCI_DEVICE_ID_INTEL_5000_FBD0);
|
||||
i5k_channel_pci_id(data, 0));
|
||||
if (res)
|
||||
goto err;
|
||||
|
||||
/* Copy the DIMM presence map for the optional second two channels */
|
||||
i5k_channel_probe(&data->amb_present[2],
|
||||
PCI_DEVICE_ID_INTEL_5000_FBD1);
|
||||
i5k_channel_pci_id(data, 1));
|
||||
|
||||
/* Set up resource regions */
|
||||
reso = request_mem_region(data->amb_base, data->amb_len, DRVNAME);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -290,7 +290,7 @@ static u32 amd756_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
|
||||
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||
}
|
||||
|
||||
static const struct i2c_algorithm smbus_algorithm = {
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/dmi.h>
|
||||
#include <asm/io.h>
|
||||
|
||||
MODULE_LICENSE("GPL");
|
||||
@@ -109,6 +110,18 @@ struct nforce2_smbus {
|
||||
/* Misc definitions */
|
||||
#define MAX_TIMEOUT 100
|
||||
|
||||
/* We disable the second SMBus channel on these boards */
|
||||
static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = {
|
||||
{
|
||||
.ident = "DFI Lanparty NF4 Expert",
|
||||
.matches = {
|
||||
DMI_MATCH(DMI_BOARD_VENDOR, "DFI Corp,LTD"),
|
||||
DMI_MATCH(DMI_BOARD_NAME, "LP UT NF4 Expert"),
|
||||
},
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct pci_driver nforce2_driver;
|
||||
|
||||
static void nforce2_abort(struct i2c_adapter *adap)
|
||||
@@ -367,10 +380,17 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
|
||||
smbuses[0].base = 0; /* to have a check value */
|
||||
}
|
||||
/* SMBus adapter 2 */
|
||||
res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1], "SMB2");
|
||||
if (res2 < 0) {
|
||||
dev_err(&dev->dev, "Error probing SMB2.\n");
|
||||
smbuses[1].base = 0; /* to have a check value */
|
||||
if (dmi_check_system(nforce2_dmi_blacklist2)) {
|
||||
dev_err(&dev->dev, "Disabling SMB2 for safety reasons.\n");
|
||||
res2 = -EPERM;
|
||||
smbuses[1].base = 0;
|
||||
} else {
|
||||
res2 = nforce2_probe_smb(dev, 5, NFORCE_PCI_SMB2, &smbuses[1],
|
||||
"SMB2");
|
||||
if (res2 < 0) {
|
||||
dev_err(&dev->dev, "Error probing SMB2.\n");
|
||||
smbuses[1].base = 0; /* to have a check value */
|
||||
}
|
||||
}
|
||||
if ((res1 < 0) && (res2 < 0)) {
|
||||
/* we did not find even one of the SMBuses, so we give up */
|
||||
|
||||
@@ -207,9 +207,6 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
|
||||
fake_client->flags = 0;
|
||||
strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
|
||||
|
||||
/* Prevent 24RF08 corruption (in case of user error) */
|
||||
i2c_smbus_write_quick(real_client, 0);
|
||||
|
||||
if ((err = i2c_attach_client(real_client)) != 0)
|
||||
goto exit_kfree2;
|
||||
|
||||
|
||||
+5
-17
@@ -74,10 +74,7 @@ static int i2c_device_match(struct device *dev, struct device_driver *drv)
|
||||
if (driver->id_table)
|
||||
return i2c_match_id(driver->id_table, client) != NULL;
|
||||
|
||||
/* new style drivers use the same kind of driver matching policy
|
||||
* as platform devices or SPI: compare device and driver IDs.
|
||||
*/
|
||||
return strcmp(client->driver_name, drv->name) == 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG
|
||||
@@ -91,14 +88,9 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
if (dev->driver)
|
||||
return 0;
|
||||
|
||||
if (client->driver_name[0]) {
|
||||
if (add_uevent_var(env, "MODALIAS=%s", client->driver_name))
|
||||
return -ENOMEM;
|
||||
} else {
|
||||
if (add_uevent_var(env, "MODALIAS=%s%s",
|
||||
I2C_MODULE_PREFIX, client->name))
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (add_uevent_var(env, "MODALIAS=%s%s",
|
||||
I2C_MODULE_PREFIX, client->name))
|
||||
return -ENOMEM;
|
||||
dev_dbg(dev, "uevent\n");
|
||||
return 0;
|
||||
}
|
||||
@@ -206,9 +198,7 @@ static ssize_t show_client_name(struct device *dev, struct device_attribute *att
|
||||
static ssize_t show_modalias(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct i2c_client *client = to_i2c_client(dev);
|
||||
return client->driver_name[0]
|
||||
? sprintf(buf, "%s\n", client->driver_name)
|
||||
: sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
|
||||
return sprintf(buf, "%s%s\n", I2C_MODULE_PREFIX, client->name);
|
||||
}
|
||||
|
||||
static struct device_attribute i2c_dev_attrs[] = {
|
||||
@@ -282,8 +272,6 @@ i2c_new_device(struct i2c_adapter *adap, struct i2c_board_info const *info)
|
||||
client->addr = info->addr;
|
||||
client->irq = info->irq;
|
||||
|
||||
strlcpy(client->driver_name, info->driver_name,
|
||||
sizeof(client->driver_name));
|
||||
strlcpy(client->name, info->type, sizeof(client->name));
|
||||
|
||||
/* a new style driver may be bound to this device when we
|
||||
|
||||
@@ -648,13 +648,12 @@ static int ide_register_port(ide_hwif_t *hwif)
|
||||
|
||||
get_device(&hwif->gendev);
|
||||
|
||||
hwif->portdev = device_create(ide_port_class, &hwif->gendev,
|
||||
MKDEV(0, 0), hwif->name);
|
||||
hwif->portdev = device_create_drvdata(ide_port_class, &hwif->gendev,
|
||||
MKDEV(0, 0), hwif, hwif->name);
|
||||
if (IS_ERR(hwif->portdev)) {
|
||||
ret = PTR_ERR(hwif->portdev);
|
||||
device_unregister(&hwif->gendev);
|
||||
}
|
||||
dev_set_drvdata(hwif->portdev, hwif);
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -95,6 +95,9 @@ static int __init macide_init(void)
|
||||
int irq;
|
||||
hw_regs_t hw;
|
||||
|
||||
if (!MACH_IS_MAC)
|
||||
return -ENODEV;
|
||||
|
||||
switch (macintosh_config->ide_type) {
|
||||
case MAC_IDE_QUADRA:
|
||||
base = IDE_BASE;
|
||||
|
||||
+8
-12
@@ -1539,15 +1539,13 @@ static void sbp2_prep_command_orb_sg(struct sbp2_command_orb *orb,
|
||||
|
||||
static void sbp2_create_command_orb(struct sbp2_lu *lu,
|
||||
struct sbp2_command_info *cmd,
|
||||
unchar *scsi_cmd,
|
||||
unsigned int scsi_use_sg,
|
||||
unsigned int scsi_request_bufflen,
|
||||
struct scatterlist *sg,
|
||||
enum dma_data_direction dma_dir)
|
||||
struct scsi_cmnd *SCpnt)
|
||||
{
|
||||
struct sbp2_fwhost_info *hi = lu->hi;
|
||||
struct sbp2_command_orb *orb = &cmd->command_orb;
|
||||
u32 orb_direction;
|
||||
unsigned int scsi_request_bufflen = scsi_bufflen(SCpnt);
|
||||
enum dma_data_direction dma_dir = SCpnt->sc_data_direction;
|
||||
|
||||
/*
|
||||
* Set-up our command ORB.
|
||||
@@ -1580,13 +1578,14 @@ static void sbp2_create_command_orb(struct sbp2_lu *lu,
|
||||
orb->data_descriptor_lo = 0x0;
|
||||
orb->misc |= ORB_SET_DIRECTION(1);
|
||||
} else
|
||||
sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_use_sg, sg,
|
||||
sbp2_prep_command_orb_sg(orb, hi, cmd, scsi_sg_count(SCpnt),
|
||||
scsi_sglist(SCpnt),
|
||||
orb_direction, dma_dir);
|
||||
|
||||
sbp2util_cpu_to_be32_buffer(orb, sizeof(*orb));
|
||||
|
||||
memset(orb->cdb, 0, 12);
|
||||
memcpy(orb->cdb, scsi_cmd, COMMAND_SIZE(*scsi_cmd));
|
||||
memset(orb->cdb, 0, sizeof(orb->cdb));
|
||||
memcpy(orb->cdb, SCpnt->cmnd, SCpnt->cmd_len);
|
||||
}
|
||||
|
||||
static void sbp2_link_orb_command(struct sbp2_lu *lu,
|
||||
@@ -1669,16 +1668,13 @@ static void sbp2_link_orb_command(struct sbp2_lu *lu,
|
||||
static int sbp2_send_command(struct sbp2_lu *lu, struct scsi_cmnd *SCpnt,
|
||||
void (*done)(struct scsi_cmnd *))
|
||||
{
|
||||
unchar *scsi_cmd = (unchar *)SCpnt->cmnd;
|
||||
struct sbp2_command_info *cmd;
|
||||
|
||||
cmd = sbp2util_allocate_command_orb(lu, SCpnt, done);
|
||||
if (!cmd)
|
||||
return -EIO;
|
||||
|
||||
sbp2_create_command_orb(lu, cmd, scsi_cmd, scsi_sg_count(SCpnt),
|
||||
scsi_bufflen(SCpnt), scsi_sglist(SCpnt),
|
||||
SCpnt->sc_data_direction);
|
||||
sbp2_create_command_orb(lu, cmd, SCpnt);
|
||||
sbp2_link_orb_command(lu, cmd);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -747,7 +747,9 @@ static int handle_outgoing_dr_smp(struct ib_mad_agent_private *mad_agent_priv,
|
||||
break;
|
||||
case IB_MAD_RESULT_SUCCESS | IB_MAD_RESULT_CONSUMED:
|
||||
kmem_cache_free(ib_mad_cache, mad_priv);
|
||||
break;
|
||||
kfree(local);
|
||||
ret = 1;
|
||||
goto out;
|
||||
case IB_MAD_RESULT_SUCCESS:
|
||||
/* Treat like an incoming receive MAD */
|
||||
port_priv = ib_get_mad_port(mad_agent_priv->agent.device,
|
||||
|
||||
@@ -1005,8 +1005,9 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
|
||||
if (cdev_add(port->cdev, base_dev + port->dev_num, 1))
|
||||
goto err_cdev;
|
||||
|
||||
port->dev = device_create(umad_class, device->dma_device,
|
||||
port->cdev->dev, "umad%d", port->dev_num);
|
||||
port->dev = device_create_drvdata(umad_class, device->dma_device,
|
||||
port->cdev->dev, port,
|
||||
"umad%d", port->dev_num);
|
||||
if (IS_ERR(port->dev))
|
||||
goto err_cdev;
|
||||
|
||||
@@ -1024,15 +1025,12 @@ static int ib_umad_init_port(struct ib_device *device, int port_num,
|
||||
if (cdev_add(port->sm_cdev, base_dev + port->dev_num + IB_UMAD_MAX_PORTS, 1))
|
||||
goto err_sm_cdev;
|
||||
|
||||
port->sm_dev = device_create(umad_class, device->dma_device,
|
||||
port->sm_cdev->dev,
|
||||
"issm%d", port->dev_num);
|
||||
port->sm_dev = device_create_drvdata(umad_class, device->dma_device,
|
||||
port->sm_cdev->dev, port,
|
||||
"issm%d", port->dev_num);
|
||||
if (IS_ERR(port->sm_dev))
|
||||
goto err_sm_cdev;
|
||||
|
||||
dev_set_drvdata(port->dev, port);
|
||||
dev_set_drvdata(port->sm_dev, port);
|
||||
|
||||
if (device_create_file(port->sm_dev, &dev_attr_ibdev))
|
||||
goto err_sm_dev;
|
||||
if (device_create_file(port->sm_dev, &dev_attr_port))
|
||||
|
||||
@@ -755,14 +755,15 @@ static void ib_uverbs_add_one(struct ib_device *device)
|
||||
if (cdev_add(uverbs_dev->cdev, IB_UVERBS_BASE_DEV + uverbs_dev->devnum, 1))
|
||||
goto err_cdev;
|
||||
|
||||
uverbs_dev->dev = device_create(uverbs_class, device->dma_device,
|
||||
uverbs_dev->cdev->dev,
|
||||
"uverbs%d", uverbs_dev->devnum);
|
||||
uverbs_dev->dev = device_create_drvdata(uverbs_class,
|
||||
device->dma_device,
|
||||
uverbs_dev->cdev->dev,
|
||||
uverbs_dev,
|
||||
"uverbs%d",
|
||||
uverbs_dev->devnum);
|
||||
if (IS_ERR(uverbs_dev->dev))
|
||||
goto err_cdev;
|
||||
|
||||
dev_set_drvdata(uverbs_dev->dev, uverbs_dev);
|
||||
|
||||
if (device_create_file(uverbs_dev->dev, &dev_attr_ibdev))
|
||||
goto err_class;
|
||||
if (device_create_file(uverbs_dev->dev, &dev_attr_abi_version))
|
||||
|
||||
@@ -229,7 +229,7 @@ int iwch_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
struct ib_send_wr **bad_wr)
|
||||
{
|
||||
int err = 0;
|
||||
u8 t3_wr_flit_cnt;
|
||||
u8 uninitialized_var(t3_wr_flit_cnt);
|
||||
enum t3_wr_opcode t3_wr_opcode = 0;
|
||||
enum t3_wr_flags t3_wr_flags;
|
||||
struct iwch_qp *qhp;
|
||||
|
||||
@@ -345,7 +345,7 @@ resched:
|
||||
* state change
|
||||
*/
|
||||
if (jiffies > dd->ipath_sdma_abort_jiffies) {
|
||||
ipath_dbg("looping with status 0x%016llx\n",
|
||||
ipath_dbg("looping with status 0x%08lx\n",
|
||||
dd->ipath_sdma_status);
|
||||
dd->ipath_sdma_abort_jiffies = jiffies + 5 * HZ;
|
||||
}
|
||||
@@ -615,7 +615,7 @@ void ipath_restart_sdma(struct ipath_devdata *dd)
|
||||
}
|
||||
spin_unlock_irqrestore(&dd->ipath_sdma_lock, flags);
|
||||
if (!needed) {
|
||||
ipath_dbg("invalid attempt to restart SDMA, status 0x%016llx\n",
|
||||
ipath_dbg("invalid attempt to restart SDMA, status 0x%08lx\n",
|
||||
dd->ipath_sdma_status);
|
||||
goto bail;
|
||||
}
|
||||
|
||||
@@ -407,12 +407,11 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
|
||||
dev->n_pkt_drops++;
|
||||
goto done;
|
||||
}
|
||||
/* XXX Need to free SGEs */
|
||||
wc.opcode = IB_WC_RECV;
|
||||
last_imm:
|
||||
ipath_copy_sge(&qp->r_sge, data, tlen);
|
||||
wc.wr_id = qp->r_wr_id;
|
||||
wc.status = IB_WC_SUCCESS;
|
||||
wc.opcode = IB_WC_RECV;
|
||||
wc.qp = &qp->ibqp;
|
||||
wc.src_qp = qp->remote_qpn;
|
||||
wc.slid = qp->remote_ah_attr.dlid;
|
||||
@@ -514,6 +513,7 @@ void ipath_uc_rcv(struct ipath_ibdev *dev, struct ipath_ib_header *hdr,
|
||||
goto done;
|
||||
}
|
||||
wc.byte_len = qp->r_len;
|
||||
wc.opcode = IB_WC_RECV_RDMA_WITH_IMM;
|
||||
goto last_imm;
|
||||
|
||||
case OP(RDMA_WRITE_LAST):
|
||||
|
||||
@@ -333,6 +333,9 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
|
||||
cap->max_inline_data + sizeof (struct mlx4_wqe_inline_seg)) +
|
||||
send_wqe_overhead(type, qp->flags);
|
||||
|
||||
if (s > dev->dev->caps.max_sq_desc_sz)
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* Hermon supports shrinking WQEs, such that a single work
|
||||
* request can include multiple units of 1 << wqe_shift. This
|
||||
@@ -372,9 +375,6 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
|
||||
qp->sq.wqe_shift = ilog2(roundup_pow_of_two(s));
|
||||
|
||||
for (;;) {
|
||||
if (1 << qp->sq.wqe_shift > dev->dev->caps.max_sq_desc_sz)
|
||||
return -EINVAL;
|
||||
|
||||
qp->sq_max_wqes_per_wr = DIV_ROUND_UP(s, 1U << qp->sq.wqe_shift);
|
||||
|
||||
/*
|
||||
@@ -395,7 +395,8 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
|
||||
++qp->sq.wqe_shift;
|
||||
}
|
||||
|
||||
qp->sq.max_gs = ((qp->sq_max_wqes_per_wr << qp->sq.wqe_shift) -
|
||||
qp->sq.max_gs = (min(dev->dev->caps.max_sq_desc_sz,
|
||||
(qp->sq_max_wqes_per_wr << qp->sq.wqe_shift)) -
|
||||
send_wqe_overhead(type, qp->flags)) /
|
||||
sizeof (struct mlx4_wqe_data_seg);
|
||||
|
||||
@@ -411,7 +412,9 @@ static int set_kernel_sq_size(struct mlx4_ib_dev *dev, struct ib_qp_cap *cap,
|
||||
|
||||
cap->max_send_wr = qp->sq.max_post =
|
||||
(qp->sq.wqe_cnt - qp->sq_spare_wqes) / qp->sq_max_wqes_per_wr;
|
||||
cap->max_send_sge = qp->sq.max_gs;
|
||||
cap->max_send_sge = min(qp->sq.max_gs,
|
||||
min(dev->dev->caps.max_sq_sg,
|
||||
dev->dev->caps.max_rq_sg));
|
||||
/* We don't support inline sends for kernel QPs (yet) */
|
||||
cap->max_inline_data = 0;
|
||||
|
||||
@@ -1457,7 +1460,7 @@ int mlx4_ib_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
|
||||
unsigned ind;
|
||||
int uninitialized_var(stamp);
|
||||
int uninitialized_var(size);
|
||||
unsigned seglen;
|
||||
unsigned uninitialized_var(seglen);
|
||||
int i;
|
||||
|
||||
spin_lock_irqsave(&qp->sq.lock, flags);
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "mthca_cmd.h"
|
||||
#include "mthca_profile.h"
|
||||
#include "mthca_memfree.h"
|
||||
#include "mthca_wqe.h"
|
||||
|
||||
MODULE_AUTHOR("Roland Dreier");
|
||||
MODULE_DESCRIPTION("Mellanox InfiniBand HCA low-level driver");
|
||||
@@ -200,7 +201,18 @@ static int mthca_dev_lim(struct mthca_dev *mdev, struct mthca_dev_lim *dev_lim)
|
||||
mdev->limits.gid_table_len = dev_lim->max_gids;
|
||||
mdev->limits.pkey_table_len = dev_lim->max_pkeys;
|
||||
mdev->limits.local_ca_ack_delay = dev_lim->local_ca_ack_delay;
|
||||
mdev->limits.max_sg = dev_lim->max_sg;
|
||||
/*
|
||||
* Need to allow for worst case send WQE overhead and check
|
||||
* whether max_desc_sz imposes a lower limit than max_sg; UD
|
||||
* send has the biggest overhead.
|
||||
*/
|
||||
mdev->limits.max_sg = min_t(int, dev_lim->max_sg,
|
||||
(dev_lim->max_desc_sz -
|
||||
sizeof (struct mthca_next_seg) -
|
||||
(mthca_is_memfree(mdev) ?
|
||||
sizeof (struct mthca_arbel_ud_seg) :
|
||||
sizeof (struct mthca_tavor_ud_seg))) /
|
||||
sizeof (struct mthca_data_seg));
|
||||
mdev->limits.max_wqes = dev_lim->max_qp_sz;
|
||||
mdev->limits.max_qp_init_rdma = dev_lim->max_requester_per_qp;
|
||||
mdev->limits.reserved_qps = dev_lim->reserved_qps;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user