提交 11604612 编写于 作者: M Mahesh Rajashekhara 提交者: James Bottomley

[SCSI] aacraid: Added Sync.mode to support series 7/8/9 controllers

Added Sync. mode to support Series 7/8/9 controller families: This is a
compatibility mode for all these controller families. The Async. (Performance)
mode can be changed in the future.  First Async. mode version added for Series
7; Controller parameter aac_sync_mode added
Signed-off-by: NMahesh Rajashekhara <aacraid@pmc-sierra.com>
Signed-off-by: NJames Bottomley <JBottomley@Parallels.com>
上级 70fc872c
...@@ -151,7 +151,11 @@ int aac_msi; ...@@ -151,7 +151,11 @@ int aac_msi;
int aac_commit = -1; int aac_commit = -1;
int startup_timeout = 180; int startup_timeout = 180;
int aif_timeout = 120; int aif_timeout = 120;
int aac_sync_mode; /* Only Sync. transfer - disabled */
module_param(aac_sync_mode, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(aac_sync_mode, "Force sync. transfer mode"
" 0=off, 1=on");
module_param(nondasd, int, S_IRUGO|S_IWUSR); module_param(nondasd, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices." MODULE_PARM_DESC(nondasd, "Control scanning of hba for nondasd devices."
" 0=off, 1=on"); " 0=off, 1=on");
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
*----------------------------------------------------------------------------*/ *----------------------------------------------------------------------------*/
#ifndef AAC_DRIVER_BUILD #ifndef AAC_DRIVER_BUILD
# define AAC_DRIVER_BUILD 28000 # define AAC_DRIVER_BUILD 28900
# define AAC_DRIVER_BRANCH "-ms" # define AAC_DRIVER_BRANCH "-ms"
#endif #endif
#define MAXIMUM_NUM_CONTAINERS 32 #define MAXIMUM_NUM_CONTAINERS 32
...@@ -756,8 +756,16 @@ struct src_mu_registers { ...@@ -756,8 +756,16 @@ struct src_mu_registers {
struct src_registers { struct src_registers {
struct src_mu_registers MUnit; /* 00h - c7h */ struct src_mu_registers MUnit; /* 00h - c7h */
__le32 reserved1[130790]; /* c8h - 7fc5fh */ union {
struct src_inbound IndexRegs; /* 7fc60h */ struct {
__le32 reserved1[130790]; /* c8h - 7fc5fh */
struct src_inbound IndexRegs; /* 7fc60h */
} tupelo;
struct {
__le32 reserved1[974]; /* c8h - fffh */
struct src_inbound IndexRegs; /* 1000h */
} denali;
} u;
}; };
#define src_readb(AEP, CSR) readb(&((AEP)->regs.src.bar0->CSR)) #define src_readb(AEP, CSR) readb(&((AEP)->regs.src.bar0->CSR))
...@@ -999,6 +1007,10 @@ struct aac_bus_info_response { ...@@ -999,6 +1007,10 @@ struct aac_bus_info_response {
#define AAC_OPT_NEW_COMM cpu_to_le32(1<<17) #define AAC_OPT_NEW_COMM cpu_to_le32(1<<17)
#define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18) #define AAC_OPT_NEW_COMM_64 cpu_to_le32(1<<18)
#define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28) #define AAC_OPT_NEW_COMM_TYPE1 cpu_to_le32(1<<28)
#define AAC_OPT_NEW_COMM_TYPE2 cpu_to_le32(1<<29)
#define AAC_OPT_NEW_COMM_TYPE3 cpu_to_le32(1<<30)
#define AAC_OPT_NEW_COMM_TYPE4 cpu_to_le32(1<<31)
struct aac_dev struct aac_dev
{ {
...@@ -1076,6 +1088,8 @@ struct aac_dev ...@@ -1076,6 +1088,8 @@ struct aac_dev
# define AAC_MIN_FOOTPRINT_SIZE 8192 # define AAC_MIN_FOOTPRINT_SIZE 8192
# define AAC_MIN_SRC_BAR0_SIZE 0x400000 # define AAC_MIN_SRC_BAR0_SIZE 0x400000
# define AAC_MIN_SRC_BAR1_SIZE 0x800 # define AAC_MIN_SRC_BAR1_SIZE 0x800
# define AAC_MIN_SRCV_BAR0_SIZE 0x100000
# define AAC_MIN_SRCV_BAR1_SIZE 0x400
#endif #endif
union union
{ {
...@@ -1116,7 +1130,10 @@ struct aac_dev ...@@ -1116,7 +1130,10 @@ struct aac_dev
u8 msi; u8 msi;
int management_fib_count; int management_fib_count;
spinlock_t manage_lock; spinlock_t manage_lock;
spinlock_t sync_lock;
int sync_mode;
struct fib *sync_fib;
struct list_head sync_fib_list;
}; };
#define aac_adapter_interrupt(dev) \ #define aac_adapter_interrupt(dev) \
...@@ -1163,6 +1180,7 @@ struct aac_dev ...@@ -1163,6 +1180,7 @@ struct aac_dev
#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001) #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001)
#define FIB_CONTEXT_FLAG (0x00000002) #define FIB_CONTEXT_FLAG (0x00000002)
#define FIB_CONTEXT_FLAG_WAIT (0x00000004)
/* /*
* Define the command values * Define the command values
...@@ -1970,6 +1988,7 @@ int aac_rkt_init(struct aac_dev *dev); ...@@ -1970,6 +1988,7 @@ int aac_rkt_init(struct aac_dev *dev);
int aac_nark_init(struct aac_dev *dev); int aac_nark_init(struct aac_dev *dev);
int aac_sa_init(struct aac_dev *dev); int aac_sa_init(struct aac_dev *dev);
int aac_src_init(struct aac_dev *dev); int aac_src_init(struct aac_dev *dev);
int aac_srcv_init(struct aac_dev *dev);
int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify); int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
unsigned int aac_response_normal(struct aac_queue * q); unsigned int aac_response_normal(struct aac_queue * q);
unsigned int aac_command_normal(struct aac_queue * q); unsigned int aac_command_normal(struct aac_queue * q);
......
...@@ -325,12 +325,14 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) ...@@ -325,12 +325,14 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
{ {
u32 status[5]; u32 status[5];
struct Scsi_Host * host = dev->scsi_host_ptr; struct Scsi_Host * host = dev->scsi_host_ptr;
extern int aac_sync_mode;
/* /*
* Check the preferred comm settings, defaults from template. * Check the preferred comm settings, defaults from template.
*/ */
dev->management_fib_count = 0; dev->management_fib_count = 0;
spin_lock_init(&dev->manage_lock); spin_lock_init(&dev->manage_lock);
spin_lock_init(&dev->sync_lock);
dev->max_fib_size = sizeof(struct hw_fib); dev->max_fib_size = sizeof(struct hw_fib);
dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size dev->sg_tablesize = host->sg_tablesize = (dev->max_fib_size
- sizeof(struct aac_fibhdr) - sizeof(struct aac_fibhdr)
...@@ -344,13 +346,21 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) ...@@ -344,13 +346,21 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
(status[0] == 0x00000001)) { (status[0] == 0x00000001)) {
if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64)) if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
dev->raw_io_64 = 1; dev->raw_io_64 = 1;
if (dev->a_ops.adapter_comm) { dev->sync_mode = aac_sync_mode;
if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1)) { if (dev->a_ops.adapter_comm &&
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1; (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM))) {
dev->raw_io_interface = 1;
} else if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)) {
dev->comm_interface = AAC_COMM_MESSAGE; dev->comm_interface = AAC_COMM_MESSAGE;
dev->raw_io_interface = 1; dev->raw_io_interface = 1;
if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1))) {
/* driver supports TYPE1 (Tupelo) */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
} else if ((status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE4)) ||
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE3)) ||
(status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE2))) {
/* driver doesn't support TYPE2 (Series7), TYPE3 and TYPE4 */
/* switch to sync. mode */
dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
dev->sync_mode = 1;
} }
} }
if ((dev->comm_interface == AAC_COMM_MESSAGE) && if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
...@@ -455,6 +465,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) ...@@ -455,6 +465,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
} }
INIT_LIST_HEAD(&dev->fib_list); INIT_LIST_HEAD(&dev->fib_list);
INIT_LIST_HEAD(&dev->sync_fib_list);
return dev; return dev;
} }
......
...@@ -416,6 +416,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -416,6 +416,7 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
unsigned long flags = 0; unsigned long flags = 0;
unsigned long qflags; unsigned long qflags;
unsigned long mflags = 0; unsigned long mflags = 0;
unsigned long sflags = 0;
if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned))) if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned)))
...@@ -512,6 +513,31 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size, ...@@ -512,6 +513,31 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
spin_lock_irqsave(&fibptr->event_lock, flags); spin_lock_irqsave(&fibptr->event_lock, flags);
} }
if (dev->sync_mode) {
if (wait)
spin_unlock_irqrestore(&fibptr->event_lock, flags);
spin_lock_irqsave(&dev->sync_lock, sflags);
if (dev->sync_fib) {
list_add_tail(&fibptr->fiblink, &dev->sync_fib_list);
spin_unlock_irqrestore(&dev->sync_lock, sflags);
} else {
dev->sync_fib = fibptr;
spin_unlock_irqrestore(&dev->sync_lock, sflags);
aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB,
(u32)fibptr->hw_fib_pa, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL);
}
if (wait) {
fibptr->flags |= FIB_CONTEXT_FLAG_WAIT;
if (down_interruptible(&fibptr->event_wait)) {
fibptr->flags &= ~FIB_CONTEXT_FLAG_WAIT;
return -EFAULT;
}
return 0;
}
return -EINPROGRESS;
}
if (aac_adapter_deliver(fibptr) != 0) { if (aac_adapter_deliver(fibptr) != 0) {
printk(KERN_ERR "aac_fib_send: returned -EBUSY\n"); printk(KERN_ERR "aac_fib_send: returned -EBUSY\n");
if (wait) { if (wait) {
......
...@@ -56,7 +56,7 @@ ...@@ -56,7 +56,7 @@
#include "aacraid.h" #include "aacraid.h"
#define AAC_DRIVER_VERSION "1.1-7" #define AAC_DRIVER_VERSION "1.2-0"
#ifndef AAC_DRIVER_BRANCH #ifndef AAC_DRIVER_BRANCH
#define AAC_DRIVER_BRANCH "" #define AAC_DRIVER_BRANCH ""
#endif #endif
...@@ -162,7 +162,10 @@ static const struct pci_device_id aac_pci_tbl[] __devinitdata = { ...@@ -162,7 +162,10 @@ static const struct pci_device_id aac_pci_tbl[] __devinitdata = {
{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */ { 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */ { 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
{ 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */ { 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */
{ 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Catch All */ { 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Series 6 (Tupelo) */
{ 0x9005, 0x028c, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 63 }, /* Adaptec PMC Series 7 (Denali) */
{ 0x9005, 0x028d, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 64 }, /* Adaptec PMC Series 8 */
{ 0x9005, 0x028f, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 65 }, /* Adaptec PMC Series 9 */
{ 0,} { 0,}
}; };
MODULE_DEVICE_TABLE(pci, aac_pci_tbl); MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
...@@ -238,7 +241,10 @@ static struct aac_driver_ident aac_drivers[] = { ...@@ -238,7 +241,10 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */ { aac_rx_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Catch All */
{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */ { aac_rkt_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec Rocket Catch All */
{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */ { aac_nark_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec NEMER/ARK Catch All */
{ aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Catch All */ { aac_src_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 6 (Tupelo) */
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 7 (Denali) */
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 }, /* Adaptec PMC Series 8 */
{ aac_srcv_init, "aacraid", "ADAPTEC ", "RAID ", 2 } /* Adaptec PMC Series 9 */
}; };
/** /**
...@@ -1102,6 +1108,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, ...@@ -1102,6 +1108,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
int error = -ENODEV; int error = -ENODEV;
int unique_id = 0; int unique_id = 0;
u64 dmamask; u64 dmamask;
extern int aac_sync_mode;
list_for_each_entry(aac, &aac_devices, entry) { list_for_each_entry(aac, &aac_devices, entry) {
if (aac->id > unique_id) if (aac->id > unique_id)
...@@ -1162,6 +1169,21 @@ static int __devinit aac_probe_one(struct pci_dev *pdev, ...@@ -1162,6 +1169,21 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
if ((*aac_drivers[index].init)(aac)) if ((*aac_drivers[index].init)(aac))
goto out_unmap; goto out_unmap;
if (aac->sync_mode) {
if (aac_sync_mode)
printk(KERN_INFO "%s%d: Sync. mode enforced "
"by driver parameter. This will cause "
"a significant performance decrease!\n",
aac->name,
aac->id);
else
printk(KERN_INFO "%s%d: Async. mode not supported "
"by current driver, sync. mode enforced."
"\nPlease update driver to get full performance.\n",
aac->name,
aac->id);
}
/* /*
* Start any kernel threads needed * Start any kernel threads needed
*/ */
......
...@@ -643,6 +643,7 @@ int _aac_rx_init(struct aac_dev *dev) ...@@ -643,6 +643,7 @@ int _aac_rx_init(struct aac_dev *dev)
if (aac_init_adapter(dev) == NULL) if (aac_init_adapter(dev) == NULL)
goto error_iounmap; goto error_iounmap;
aac_adapter_comm(dev, dev->comm_interface); aac_adapter_comm(dev, dev->comm_interface);
dev->sync_mode = 0; /* sync. mode not supported */
dev->msi = aac_msi && !pci_enable_msi(dev->pdev); dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) { IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
......
...@@ -385,6 +385,7 @@ int aac_sa_init(struct aac_dev *dev) ...@@ -385,6 +385,7 @@ int aac_sa_init(struct aac_dev *dev)
if(aac_init_adapter(dev) == NULL) if(aac_init_adapter(dev) == NULL)
goto error_irq; goto error_irq;
dev->sync_mode = 0; /* sync. mode not supported */
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr, if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
IRQF_SHARED|IRQF_DISABLED, IRQF_SHARED|IRQF_DISABLED,
"aacraid", (void *)dev ) < 0) { "aacraid", (void *)dev ) < 0) {
......
...@@ -96,6 +96,38 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id) ...@@ -96,6 +96,38 @@ static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
our_interrupt = 1; our_interrupt = 1;
/* handle AIF */ /* handle AIF */
aac_intr_normal(dev, 0, 2, 0, NULL); aac_intr_normal(dev, 0, 2, 0, NULL);
} else if (bellbits_shifted & OUTBOUNDDOORBELL_0) {
unsigned long sflags;
struct list_head *entry;
int send_it = 0;
if (dev->sync_fib) {
our_interrupt = 1;
if (dev->sync_fib->callback)
dev->sync_fib->callback(dev->sync_fib->callback_data,
dev->sync_fib);
spin_lock_irqsave(&dev->sync_fib->event_lock, sflags);
if (dev->sync_fib->flags & FIB_CONTEXT_FLAG_WAIT) {
dev->management_fib_count--;
up(&dev->sync_fib->event_wait);
}
spin_unlock_irqrestore(&dev->sync_fib->event_lock, sflags);
spin_lock_irqsave(&dev->sync_lock, sflags);
if (!list_empty(&dev->sync_fib_list)) {
entry = dev->sync_fib_list.next;
dev->sync_fib = list_entry(entry, struct fib, fiblink);
list_del(entry);
send_it = 1;
} else {
dev->sync_fib = NULL;
}
spin_unlock_irqrestore(&dev->sync_lock, sflags);
if (send_it) {
aac_adapter_sync_cmd(dev, SEND_SYNCHRONOUS_FIB,
(u32)dev->sync_fib->hw_fib_pa, 0, 0, 0, 0, 0,
NULL, NULL, NULL, NULL, NULL);
}
}
} }
} }
...@@ -177,56 +209,63 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command, ...@@ -177,56 +209,63 @@ static int src_sync_cmd(struct aac_dev *dev, u32 command,
*/ */
src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT); src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
ok = 0; if (!dev->sync_mode || command != SEND_SYNCHRONOUS_FIB) {
start = jiffies; ok = 0;
start = jiffies;
/* /*
* Wait up to 30 seconds * Wait up to 5 minutes
*/
while (time_before(jiffies, start+30*HZ)) {
/* Delay 5 microseconds to let Mon960 get info. */
udelay(5);
/* Mon960 will set doorbell0 bit
* when it has completed the command
*/ */
if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) { while (time_before(jiffies, start+300*HZ)) {
/* Clear the doorbell */ udelay(5); /* Delay 5 microseconds to let Mon960 get info. */
src_writel(dev, /*
MUnit.ODR_C, * Mon960 will set doorbell0 bit when it has completed the command.
OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT); */
ok = 1; if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) {
break; /*
* Clear the doorbell.
*/
src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
ok = 1;
break;
}
/*
* Yield the processor in case we are slow
*/
msleep(1);
} }
if (unlikely(ok != 1)) {
/* Yield the processor in case we are slow */ /*
msleep(1); * Restore interrupt mask even though we timed out
} */
if (unlikely(ok != 1)) { aac_adapter_enable_int(dev);
/* Restore interrupt mask even though we timed out */ return -ETIMEDOUT;
aac_adapter_enable_int(dev); }
return -ETIMEDOUT; /*
* Pull the synch status from Mailbox 0.
*/
if (status)
*status = readl(&dev->IndexRegs->Mailbox[0]);
if (r1)
*r1 = readl(&dev->IndexRegs->Mailbox[1]);
if (r2)
*r2 = readl(&dev->IndexRegs->Mailbox[2]);
if (r3)
*r3 = readl(&dev->IndexRegs->Mailbox[3]);
if (r4)
*r4 = readl(&dev->IndexRegs->Mailbox[4]);
/*
* Clear the synch command doorbell.
*/
src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
} }
/* Pull the synch status from Mailbox 0 */ /*
if (status) * Restore interrupt mask
*status = readl(&dev->IndexRegs->Mailbox[0]); */
if (r1)
*r1 = readl(&dev->IndexRegs->Mailbox[1]);
if (r2)
*r2 = readl(&dev->IndexRegs->Mailbox[2]);
if (r3)
*r3 = readl(&dev->IndexRegs->Mailbox[3]);
if (r4)
*r4 = readl(&dev->IndexRegs->Mailbox[4]);
/* Clear the synch command doorbell */
src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
/* Restore interrupt mask */
aac_adapter_enable_int(dev); aac_adapter_enable_int(dev);
return 0; return 0;
} }
/** /**
...@@ -386,9 +425,7 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size) ...@@ -386,9 +425,7 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size)
{ {
if (!size) { if (!size) {
iounmap(dev->regs.src.bar0); iounmap(dev->regs.src.bar0);
dev->regs.src.bar0 = NULL; dev->base = dev->regs.src.bar0 = NULL;
iounmap(dev->base);
dev->base = NULL;
return 0; return 0;
} }
dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2), dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
...@@ -404,7 +441,27 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size) ...@@ -404,7 +441,27 @@ static int aac_src_ioremap(struct aac_dev *dev, u32 size)
return -1; return -1;
} }
dev->IndexRegs = &((struct src_registers __iomem *) dev->IndexRegs = &((struct src_registers __iomem *)
dev->base)->IndexRegs; dev->base)->u.tupelo.IndexRegs;
return 0;
}
/**
* aac_srcv_ioremap
* @size: mapping resize request
*
*/
static int aac_srcv_ioremap(struct aac_dev *dev, u32 size)
{
if (!size) {
iounmap(dev->regs.src.bar0);
dev->base = dev->regs.src.bar0 = NULL;
return 0;
}
dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base, size);
if (dev->base == NULL)
return -1;
dev->IndexRegs = &((struct src_registers __iomem *)
dev->base)->u.denali.IndexRegs;
return 0; return 0;
} }
...@@ -419,7 +476,7 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled) ...@@ -419,7 +476,7 @@ static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS, bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL); 0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
if (bled || (var != 0x00000001)) if (bled || (var != 0x00000001))
bled = -EINVAL; return -EINVAL;
if (dev->supplement_adapter_info.SupportedOptions2 & if (dev->supplement_adapter_info.SupportedOptions2 &
AAC_OPTION_DOORBELL_RESET) { AAC_OPTION_DOORBELL_RESET) {
src_writel(dev, MUnit.IDR, reset_mask); src_writel(dev, MUnit.IDR, reset_mask);
...@@ -579,15 +636,149 @@ int aac_src_init(struct aac_dev *dev) ...@@ -579,15 +636,149 @@ int aac_src_init(struct aac_dev *dev)
dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE; dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
aac_adapter_enable_int(dev); aac_adapter_enable_int(dev);
if (!dev->sync_mode) {
/*
* Tell the adapter that all is configured, and it can
* start accepting requests
*/
aac_src_start_adapter(dev);
}
return 0;
error_iounmap:
return -1;
}
/**
* aac_srcv_init - initialize an SRCv card
* @dev: device to configure
*
*/
int aac_srcv_init(struct aac_dev *dev)
{
unsigned long start;
unsigned long status;
int restart = 0;
int instance = dev->id;
const char *name = dev->name;
dev->a_ops.adapter_ioremap = aac_srcv_ioremap;
dev->a_ops.adapter_comm = aac_src_select_comm;
dev->base_size = AAC_MIN_SRCV_BAR0_SIZE;
if (aac_adapter_ioremap(dev, dev->base_size)) {
printk(KERN_WARNING "%s: unable to map adapter.\n", name);
goto error_iounmap;
}
/* Failure to reset here is an option ... */
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
if ((aac_reset_devices || reset_devices) &&
!aac_src_restart_adapter(dev, 0))
++restart;
/* /*
* Tell the adapter that all is configured, and it can * Check to see if the board panic'd while booting.
* start accepting requests
*/ */
aac_src_start_adapter(dev); status = src_readl(dev, MUnit.OMR);
if (status & KERNEL_PANIC) {
if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
goto error_iounmap;
++restart;
}
/*
* Check to see if the board failed any self tests.
*/
status = src_readl(dev, MUnit.OMR);
if (status & SELF_TEST_FAILED) {
printk(KERN_ERR "%s%d: adapter self-test failed.\n", dev->name, instance);
goto error_iounmap;
}
/*
* Check to see if the monitor panic'd while booting.
*/
if (status & MONITOR_PANIC) {
printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
goto error_iounmap;
}
start = jiffies;
/*
* Wait for the adapter to be up and running. Wait up to 3 minutes
*/
while (!((status = src_readl(dev, MUnit.OMR)) & KERNEL_UP_AND_RUNNING)) {
if ((restart &&
(status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
time_after(jiffies, start+HZ*startup_timeout)) {
printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
dev->name, instance, status);
goto error_iounmap;
}
if (!restart &&
((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
time_after(jiffies, start + HZ *
((startup_timeout > 60)
? (startup_timeout - 60)
: (startup_timeout / 2))))) {
if (likely(!aac_src_restart_adapter(dev, aac_src_check_health(dev))))
start = jiffies;
++restart;
}
msleep(1);
}
if (restart && aac_commit)
aac_commit = 1;
/*
* Fill in the common function dispatch table.
*/
dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
dev->a_ops.adapter_notify = aac_src_notify_adapter;
dev->a_ops.adapter_sync_cmd = src_sync_cmd;
dev->a_ops.adapter_check_health = aac_src_check_health;
dev->a_ops.adapter_restart = aac_src_restart_adapter;
/*
* First clear out all interrupts. Then enable the one's that we
* can handle.
*/
aac_adapter_comm(dev, AAC_COMM_MESSAGE);
aac_adapter_disable_int(dev);
src_writel(dev, MUnit.ODR_C, 0xffffffff);
aac_adapter_enable_int(dev);
if (aac_init_adapter(dev) == NULL)
goto error_iounmap;
if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
goto error_iounmap;
dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
if (dev->msi)
pci_disable_msi(dev->pdev);
printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
name, instance);
goto error_iounmap;
}
dev->dbg_base = dev->scsi_host_ptr->base;
dev->dbg_base_mapped = dev->base;
dev->dbg_size = dev->base_size;
aac_adapter_enable_int(dev);
if (!dev->sync_mode) {
/*
* Tell the adapter that all is configured, and it can
* start accepting requests
*/
aac_src_start_adapter(dev);
}
return 0; return 0;
error_iounmap: error_iounmap:
return -1; return -1;
} }
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册