summaryrefslogtreecommitdiff
path: root/drivers/scsi/aacraid
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/aacraid')
-rw-r--r--drivers/scsi/aacraid/aachba.c60
-rw-r--r--drivers/scsi/aacraid/aacraid.h20
-rw-r--r--drivers/scsi/aacraid/commctrl.c25
-rw-r--r--drivers/scsi/aacraid/comminit.c13
-rw-r--r--drivers/scsi/aacraid/commsup.c280
-rw-r--r--drivers/scsi/aacraid/dpcsup.c10
-rw-r--r--drivers/scsi/aacraid/linit.c35
-rw-r--r--drivers/scsi/aacraid/rkt.c446
-rw-r--r--drivers/scsi/aacraid/rx.c117
-rw-r--r--drivers/scsi/aacraid/sa.c21
10 files changed, 496 insertions, 531 deletions
diff --git a/drivers/scsi/aacraid/aachba.c b/drivers/scsi/aacraid/aachba.c
index 83b5c7d085f..ac108f9e267 100644
--- a/drivers/scsi/aacraid/aachba.c
+++ b/drivers/scsi/aacraid/aachba.c
@@ -169,13 +169,17 @@ MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control block
int acbsize = -1;
module_param(acbsize, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512, 2048, 4096 and 8192. Default is to use suggestion from Firmware.");
+
+int expose_physicals = 0;
+module_param(expose_physicals, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(expose_physicals, "Expose physical components of the arrays. 0=off, 1=on");
/**
* aac_get_config_status - check the adapter configuration
* @common: adapter to query
*
* Query config status, and commit the configuration if needed.
*/
-int aac_get_config_status(struct aac_dev *dev)
+int aac_get_config_status(struct aac_dev *dev, int commit_flag)
{
int status = 0;
struct fib * fibptr;
@@ -219,7 +223,7 @@ int aac_get_config_status(struct aac_dev *dev)
aac_fib_complete(fibptr);
/* Send a CT_COMMIT_CONFIG to enable discovery of devices */
if (status >= 0) {
- if (commit == 1) {
+ if ((commit == 1) || commit_flag) {
struct aac_commit_config * dinfo;
aac_fib_init(fibptr);
dinfo = (struct aac_commit_config *) fib_data(fibptr);
@@ -489,6 +493,8 @@ int aac_probe_container(struct aac_dev *dev, int cid)
unsigned instance;
fsa_dev_ptr = dev->fsa_dev;
+ if (!fsa_dev_ptr)
+ return -ENOMEM;
instance = dev->scsi_host_ptr->unique_id;
if (!(fibptr = aac_fib_alloc(dev)))
@@ -782,8 +788,9 @@ int aac_get_adapter_info(struct aac_dev* dev)
dev->maximum_num_channels = le32_to_cpu(bus_info->BusCount);
}
- tmp = le32_to_cpu(dev->adapter_info.kernelrev);
- printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
+ if (!dev->in_reset) {
+ tmp = le32_to_cpu(dev->adapter_info.kernelrev);
+ printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n",
dev->name,
dev->id,
tmp>>24,
@@ -792,20 +799,21 @@ int aac_get_adapter_info(struct aac_dev* dev)
le32_to_cpu(dev->adapter_info.kernelbuild),
(int)sizeof(dev->supplement_adapter_info.BuildDate),
dev->supplement_adapter_info.BuildDate);
- tmp = le32_to_cpu(dev->adapter_info.monitorrev);
- printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
+ tmp = le32_to_cpu(dev->adapter_info.monitorrev);
+ printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n",
dev->name, dev->id,
tmp>>24,(tmp>>16)&0xff,tmp&0xff,
le32_to_cpu(dev->adapter_info.monitorbuild));
- tmp = le32_to_cpu(dev->adapter_info.biosrev);
- printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n",
+ tmp = le32_to_cpu(dev->adapter_info.biosrev);
+ printk(KERN_INFO "%s%d: bios %d.%d-%d[%d]\n",
dev->name, dev->id,
tmp>>24,(tmp>>16)&0xff,tmp&0xff,
le32_to_cpu(dev->adapter_info.biosbuild));
- if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
- printk(KERN_INFO "%s%d: serial %x\n",
- dev->name, dev->id,
- le32_to_cpu(dev->adapter_info.serial[0]));
+ if (le32_to_cpu(dev->adapter_info.serial[0]) != 0xBAD0)
+ printk(KERN_INFO "%s%d: serial %x\n",
+ dev->name, dev->id,
+ le32_to_cpu(dev->adapter_info.serial[0]));
+ }
dev->nondasd_support = 0;
dev->raid_scsi_mode = 0;
@@ -1392,6 +1400,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
struct scsi_cmnd *cmd;
struct scsi_device *sdev = scsicmd->device;
int active = 0;
+ struct aac_dev *aac;
unsigned long flags;
/*
@@ -1413,11 +1422,14 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
if (active)
return SCSI_MLQUEUE_DEVICE_BUSY;
+ aac = (struct aac_dev *)scsicmd->device->host->hostdata;
+ if (aac->in_reset)
+ return SCSI_MLQUEUE_HOST_BUSY;
+
/*
* Allocate and initialize a Fib
*/
- if (!(cmd_fibcontext =
- aac_fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata)))
+ if (!(cmd_fibcontext = aac_fib_alloc(aac)))
return SCSI_MLQUEUE_HOST_BUSY;
aac_fib_init(cmd_fibcontext);
@@ -1470,6 +1482,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
struct aac_dev *dev = (struct aac_dev *)host->hostdata;
struct fsa_dev_info *fsa_dev_ptr = dev->fsa_dev;
+ if (fsa_dev_ptr == NULL)
+ return -1;
/*
* If the bus, id or lun is out of range, return fail
* Test does not apply to ID 16, the pseudo id for the controller
@@ -1499,6 +1513,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case INQUIRY:
case READ_CAPACITY:
case TEST_UNIT_READY:
+ if (dev->in_reset)
+ return -1;
spin_unlock_irq(host->host_lock);
aac_probe_container(dev, cid);
if ((fsa_dev_ptr[cid].valid & 1) == 0)
@@ -1523,7 +1539,9 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
return 0;
}
} else { /* check for physical non-dasd devices */
- if(dev->nondasd_support == 1){
+ if ((dev->nondasd_support == 1) || expose_physicals) {
+ if (dev->in_reset)
+ return -1;
return aac_send_srb_fib(scsicmd);
} else {
scsicmd->result = DID_NO_CONNECT << 16;
@@ -1579,6 +1597,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
scsicmd->scsi_done(scsicmd);
return 0;
}
+ if (dev->in_reset)
+ return -1;
setinqstr(dev, (void *) (inq_data.inqd_vid), fsa_dev_ptr[cid].type);
inq_data.inqd_pdt = INQD_PDT_DA; /* Direct/random access device */
aac_internal_transfer(scsicmd, &inq_data, 0, sizeof(inq_data));
@@ -1734,6 +1754,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case READ_10:
case READ_12:
case READ_16:
+ if (dev->in_reset)
+ return -1;
/*
* Hack to keep track of ordinal number of the device that
* corresponds to a container. Needed to convert
@@ -1752,6 +1774,8 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
case WRITE_10:
case WRITE_12:
case WRITE_16:
+ if (dev->in_reset)
+ return -1;
return aac_write(scsicmd, cid);
case SYNCHRONIZE_CACHE:
@@ -1782,6 +1806,8 @@ static int query_disk(struct aac_dev *dev, void __user *arg)
struct fsa_dev_info *fsa_dev_ptr;
fsa_dev_ptr = dev->fsa_dev;
+ if (!fsa_dev_ptr)
+ return -EBUSY;
if (copy_from_user(&qd, arg, sizeof (struct aac_query_disk)))
return -EFAULT;
if (qd.cnum == -1)
@@ -1820,6 +1846,8 @@ static int force_delete_disk(struct aac_dev *dev, void __user *arg)
struct fsa_dev_info *fsa_dev_ptr;
fsa_dev_ptr = dev->fsa_dev;
+ if (!fsa_dev_ptr)
+ return -EBUSY;
if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
return -EFAULT;
@@ -1843,6 +1871,8 @@ static int delete_disk(struct aac_dev *dev, void __user *arg)
struct fsa_dev_info *fsa_dev_ptr;
fsa_dev_ptr = dev->fsa_dev;
+ if (!fsa_dev_ptr)
+ return -EBUSY;
if (copy_from_user(&dd, arg, sizeof (struct aac_delete_disk)))
return -EFAULT;
diff --git a/drivers/scsi/aacraid/aacraid.h b/drivers/scsi/aacraid/aacraid.h
index d0eecd4bec8..eb3ed91bac7 100644
--- a/drivers/scsi/aacraid/aacraid.h
+++ b/drivers/scsi/aacraid/aacraid.h
@@ -494,6 +494,7 @@ struct adapter_ops
int (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
int (*adapter_check_health)(struct aac_dev *dev);
int (*adapter_send)(struct fib * fib);
+ int (*adapter_ioremap)(struct aac_dev * dev, u32 size);
};
/*
@@ -682,14 +683,6 @@ struct rx_inbound {
__le32 Mailbox[8];
};
-#define InboundMailbox0 IndexRegs.Mailbox[0]
-#define InboundMailbox1 IndexRegs.Mailbox[1]
-#define InboundMailbox2 IndexRegs.Mailbox[2]
-#define InboundMailbox3 IndexRegs.Mailbox[3]
-#define InboundMailbox4 IndexRegs.Mailbox[4]
-#define InboundMailbox5 IndexRegs.Mailbox[5]
-#define InboundMailbox6 IndexRegs.Mailbox[6]
-
#define INBOUNDDOORBELL_0 0x00000001
#define INBOUNDDOORBELL_1 0x00000002
#define INBOUNDDOORBELL_2 0x00000004
@@ -1010,6 +1003,8 @@ struct aac_dev
struct rx_registers __iomem *rx;
struct rkt_registers __iomem *rkt;
} regs;
+ volatile void __iomem *base;
+ volatile struct rx_inbound __iomem *IndexRegs;
u32 OIMR; /* Mask Register Cache */
/*
* AIF thread states
@@ -1029,6 +1024,7 @@ struct aac_dev
init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
u8 raw_io_64;
u8 printf_enabled;
+ u8 in_reset;
};
#define aac_adapter_interrupt(dev) \
@@ -1049,6 +1045,9 @@ struct aac_dev
#define aac_adapter_send(fib) \
((fib)->dev)->a_ops.adapter_send(fib)
+#define aac_adapter_ioremap(dev, size) \
+ (dev)->a_ops.adapter_ioremap(dev, size)
+
#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001)
/*
@@ -1524,7 +1523,6 @@ struct aac_get_name {
__le32 count; /* sizeof(((struct aac_get_name_resp *)NULL)->data) */
};
-#define CT_OK 218
struct aac_get_name_resp {
__le32 dummy0;
__le32 dummy1;
@@ -1670,6 +1668,7 @@ extern struct aac_common aac_config;
#define RCV_TEMP_READINGS 0x00000025
#define GET_COMM_PREFERRED_SETTINGS 0x00000026
#define IOP_RESET 0x00001000
+#define IOP_RESET_ALWAYS 0x00001001
#define RE_INIT_ADAPTER 0x000000ee
/*
@@ -1788,7 +1787,7 @@ void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
int aac_fib_complete(struct fib * context);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib->data)
struct aac_dev *aac_init_adapter(struct aac_dev *dev);
-int aac_get_config_status(struct aac_dev *dev);
+int aac_get_config_status(struct aac_dev *dev, int commit_flag);
int aac_get_containers(struct aac_dev *dev);
int aac_scsi_cmd(struct scsi_cmnd *cmd);
int aac_dev_ioctl(struct aac_dev *dev, int cmd, void __user *arg);
@@ -1799,6 +1798,7 @@ int aac_sa_init(struct aac_dev *dev);
unsigned int aac_response_normal(struct aac_queue * q);
unsigned int aac_command_normal(struct aac_queue * q);
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
+int aac_check_health(struct aac_dev * dev);
int aac_command_thread(void *data);
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
int aac_fib_adapter_complete(struct fib * fibptr, unsigned short size);
diff --git a/drivers/scsi/aacraid/commctrl.c b/drivers/scsi/aacraid/commctrl.c
index 255421de9d1..da1d3a9212f 100644
--- a/drivers/scsi/aacraid/commctrl.c
+++ b/drivers/scsi/aacraid/commctrl.c
@@ -38,7 +38,7 @@
#include <linux/completion.h>
#include <linux/dma-mapping.h>
#include <linux/blkdev.h>
-#include <linux/delay.h>
+#include <linux/delay.h> /* ssleep prototype */
#include <linux/kthread.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
@@ -140,7 +140,8 @@ cleanup:
fibptr->hw_fib_pa = hw_fib_pa;
fibptr->hw_fib = hw_fib;
}
- aac_fib_free(fibptr);
+ if (retval != -EINTR)
+ aac_fib_free(fibptr);
return retval;
}
@@ -297,7 +298,7 @@ return_fib:
spin_unlock_irqrestore(&dev->fib_lock, flags);
/* If someone killed the AIF aacraid thread, restart it */
status = !dev->aif_thread;
- if (status && dev->queues && dev->fsa_dev) {
+ if (status && !dev->in_reset && dev->queues && dev->fsa_dev) {
/* Be paranoid, be very paranoid! */
kthread_stop(dev->thread);
ssleep(1);
@@ -621,7 +622,13 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
actual_fibsize = sizeof (struct aac_srb) + (((user_srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
- dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
+ dprintk((KERN_DEBUG"aacraid: Bad Size specified in "
+ "Raw SRB command calculated fibsize=%d "
+ "user_srbcmd->sg.count=%d aac_srb=%d sgentry=%d "
+ "issued fibsize=%d\n",
+ actual_fibsize, user_srbcmd->sg.count,
+ sizeof(struct aac_srb), sizeof(struct sgentry),
+ fibsize));
rcode = -EINVAL;
goto cleanup;
}
@@ -663,6 +670,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
psg->count = cpu_to_le32(sg_indx+1);
status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
}
+ if (status == -EINTR) {
+ rcode = -EINTR;
+ goto cleanup;
+ }
if (status != 0){
dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));
@@ -696,8 +707,10 @@ cleanup:
for(i=0; i <= sg_indx; i++){
kfree(sg_list[i]);
}
- aac_fib_complete(srbfib);
- aac_fib_free(srbfib);
+ if (rcode != -EINTR) {
+ aac_fib_complete(srbfib);
+ aac_fib_free(srbfib);
+ }
return rcode;
}
diff --git a/drivers/scsi/aacraid/comminit.c b/drivers/scsi/aacraid/comminit.c
index 1cd3584ba7f..d5cf8b91a0e 100644
--- a/drivers/scsi/aacraid/comminit.c
+++ b/drivers/scsi/aacraid/comminit.c
@@ -180,7 +180,7 @@ int aac_send_shutdown(struct aac_dev * dev)
-2 /* Timeout silently */, 1,
NULL, NULL);
- if (status == 0)
+ if (status >= 0)
aac_fib_complete(fibctx);
aac_fib_free(fibctx);
return status;
@@ -307,17 +307,12 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
if (status[1] & AAC_OPT_NEW_COMM)
dev->new_comm_interface = dev->a_ops.adapter_send != 0;
if (dev->new_comm_interface && (status[2] > dev->base_size)) {
- iounmap(dev->regs.sa);
+ aac_adapter_ioremap(dev, 0);
dev->base_size = status[2];
- dprintk((KERN_DEBUG "ioremap(%lx,%d)\n",
- host->base, status[2]));
- dev->regs.sa = ioremap(host->base, status[2]);
- if (dev->regs.sa == NULL) {
+ if (aac_adapter_ioremap(dev, status[2])) {
/* remap failed, go back ... */
dev->new_comm_interface = 0;
- dev->regs.sa = ioremap(host->base,
- AAC_MIN_FOOTPRINT_SIZE);
- if (dev->regs.sa == NULL) {
+ if (aac_adapter_ioremap(dev, AAC_MIN_FOOTPRINT_SIZE)) {
printk(KERN_WARNING
"aacraid: unable to map adapter.\n");
return NULL;
diff --git a/drivers/scsi/aacraid/commsup.c b/drivers/scsi/aacraid/commsup.c
index 3f27419c66a..19e42ac07cb 100644
--- a/drivers/scsi/aacraid/commsup.c
+++ b/drivers/scsi/aacraid/commsup.c
@@ -40,8 +40,11 @@
#include <linux/blkdev.h>
#include <linux/delay.h>
#include <linux/kthread.h>
+#include <linux/interrupt.h>
+#include <scsi/scsi.h>
#include <scsi/scsi_host.h>
#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
#include <asm/semaphore.h>
#include "aacraid.h"
@@ -464,6 +467,8 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
+ if (!dev->queues)
+ return -EBUSY;
q = &dev->queues->queue[AdapNormCmdQueue];
if(wait)
@@ -527,8 +532,15 @@ int aac_fib_send(u16 command, struct fib *fibptr, unsigned long size,
}
udelay(5);
}
- } else
- down(&fibptr->event_wait);
+ } else if (down_interruptible(&fibptr->event_wait)) {
+ spin_lock_irqsave(&fibptr->event_lock, flags);
+ if (fibptr->done == 0) {
+ fibptr->done = 2; /* Tell interrupt we aborted */
+ spin_unlock_irqrestore(&fibptr->event_lock, flags);
+ return -EINTR;
+ }
+ spin_unlock_irqrestore(&fibptr->event_lock, flags);
+ }
BUG_ON(fibptr->done == 0);
if((fibptr->flags & FIB_CONTEXT_FLAG_TIMED_OUT)){
@@ -795,7 +807,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
/* Sniff for container changes */
- if (!dev)
+ if (!dev || !dev->fsa_dev)
return;
container = (u32)-1;
@@ -1022,13 +1034,7 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
if (device) {
switch (device_config_needed) {
case DELETE:
- scsi_remove_device(device);
- break;
case CHANGE:
- if (!dev->fsa_dev[container].valid) {
- scsi_remove_device(device);
- break;
- }
scsi_rescan_device(&device->sdev_gendev);
default:
@@ -1045,6 +1051,262 @@ static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
}
+static int _aac_reset_adapter(struct aac_dev *aac)
+{
+ int index, quirks;
+ u32 ret;
+ int retval;
+ struct Scsi_Host *host;
+ struct scsi_device *dev;
+ struct scsi_cmnd *command;
+ struct scsi_cmnd *command_list;
+
+ /*
+ * Assumptions:
+ * - host is locked.
+ * - in_reset is asserted, so no new i/o is getting to the
+ * card.
+ * - The card is dead.
+ */
+ host = aac->scsi_host_ptr;
+ scsi_block_requests(host);
+ aac_adapter_disable_int(aac);
+ spin_unlock_irq(host->host_lock);
+ kthread_stop(aac->thread);
+
+ /*
+ * If a positive health, means in a known DEAD PANIC
+ * state and the adapter could be reset to `try again'.
+ */
+ retval = aac_adapter_check_health(aac);
+ if (retval == 0)
+ retval = aac_adapter_sync_cmd(aac, IOP_RESET_ALWAYS,
+ 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
+ if (retval)
+ retval = aac_adapter_sync_cmd(aac, IOP_RESET,
+ 0, 0, 0, 0, 0, 0, &ret, NULL, NULL, NULL, NULL);
+
+ if (retval)
+ goto out;
+ if (ret != 0x00000001) {
+ retval = -ENODEV;
+ goto out;
+ }
+
+ index = aac->cardtype;
+
+ /*
+ * Re-initialize the adapter, first free resources, then carefully
+ * apply the initialization sequence to come back again. Only risk
+ * is a change in Firmware dropping cache, it is assumed the caller
+ * will ensure that i/o is queisced and the card is flushed in that
+ * case.
+ */
+ aac_fib_map_free(aac);
+ aac->hw_fib_va = NULL;
+ aac->hw_fib_pa = 0;
+ pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
+ aac->comm_addr = NULL;
+ aac->comm_phys = 0;
+ kfree(aac->queues);
+ aac->queues = NULL;
+ free_irq(aac->pdev->irq, aac);
+ kfree(aac->fsa_dev);
+ aac->fsa_dev = NULL;
+ if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT) {
+ if (((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK))) ||
+ ((retval = pci_set_consistent_dma_mask(aac->pdev, DMA_32BIT_MASK))))
+ goto out;
+ } else {
+ if (((retval = pci_set_dma_mask(aac->pdev, 0x7FFFFFFFULL))) ||
+ ((retval = pci_set_consistent_dma_mask(aac->pdev, 0x7FFFFFFFULL))))
+ goto out;
+ }
+ if ((retval = (*(aac_get_driver_ident(index)->init))(aac)))
+ goto out;
+ if (aac_get_driver_ident(index)->quirks & AAC_QUIRK_31BIT)
+ if ((retval = pci_set_dma_mask(aac->pdev, DMA_32BIT_MASK)))
+ goto out;
+ aac->thread = kthread_run(aac_command_thread, aac, aac->name);
+ if (IS_ERR(aac->thread)) {
+ retval = PTR_ERR(aac->thread);
+ goto out;
+ }
+ (void)aac_get_adapter_info(aac);
+ quirks = aac_get_driver_ident(index)->quirks;
+ if ((quirks & AAC_QUIRK_34SG) && (host->sg_tablesize > 34)) {
+ host->sg_tablesize = 34;
+ host->max_sectors = (host->sg_tablesize * 8) + 112;
+ }
+ if ((quirks & AAC_QUIRK_17SG) && (host->sg_tablesize > 17)) {
+ host->sg_tablesize = 17;
+ host->max_sectors = (host->sg_tablesize * 8) + 112;
+ }
+ aac_get_config_status(aac, 1);
+ aac_get_containers(aac);
+ /*
+ * This is where the assumption that the Adapter is quiesced
+ * is important.
+ */
+ command_list = NULL;
+ __shost_for_each_device(dev, host) {
+ unsigned long flags;
+ spin_lock_irqsave(&dev->list_lock, flags);
+ list_for_each_entry(command, &dev->cmd_list, list)
+ if (command->SCp.phase == AAC_OWNER_FIRMWARE) {
+ command->SCp.buffer = (struct scatterlist *)command_list;
+ command_list = command;
+ }
+ spin_unlock_irqrestore(&dev->list_lock, flags);
+ }
+ while ((command = command_list)) {
+ command_list = (struct scsi_cmnd *)command->SCp.buffer;
+ command->SCp.buffer = NULL;
+ command->result = DID_OK << 16
+ | COMMAND_COMPLETE << 8
+ | SAM_STAT_TASK_SET_FULL;
+ command->SCp.phase = AAC_OWNER_ERROR_HANDLER;
+ command->scsi_done(command);
+ }
+ retval = 0;
+
+out:
+ aac->in_reset = 0;
+ scsi_unblock_requests(host);
+ spin_lock_irq(host->host_lock);
+ return retval;
+}
+
+int aac_check_health(struct aac_dev * aac)
+{
+ int BlinkLED;
+ unsigned long time_now, flagv = 0;
+ struct list_head * entry;
+ struct Scsi_Host * host;
+
+ /* Extending the scope of fib_lock slightly to protect aac->in_reset */
+ if (spin_trylock_irqsave(&aac->fib_lock, flagv) == 0)
+ return 0;
+
+ if (aac->in_reset || !(BlinkLED = aac_adapter_check_health(aac))) {
+ spin_unlock_irqrestore(&aac->fib_lock, flagv);
+ return 0; /* OK */
+ }
+
+ aac->in_reset = 1;
+
+ /* Fake up an AIF:
+ * aac_aifcmd.command = AifCmdEventNotify = 1
+ * aac_aifcmd.seqnum = 0xFFFFFFFF
+ * aac_aifcmd.data[0] = AifEnExpEvent = 23
+ * aac_aifcmd.data[1] = AifExeFirmwarePanic = 3
+ * aac.aifcmd.data[2] = AifHighPriority = 3
+ * aac.aifcmd.data[3] = BlinkLED
+ */
+
+ time_now = jiffies/HZ;
+ entry = aac->fib_list.next;
+
+ /*
+ * For each Context that is on the
+ * fibctxList, make a copy of the
+ * fib, and then set the event to wake up the
+ * thread that is waiting for it.
+ */
+ while (entry != &aac->fib_list) {
+ /*
+ * Extract the fibctx
+ */
+ struct aac_fib_context *fibctx = list_entry(entry, struct aac_fib_context, next);
+ struct hw_fib * hw_fib;
+ struct fib * fib;
+ /*
+ * Check if the queue is getting
+ * backlogged
+ */
+ if (fibctx->count > 20) {
+ /*
+ * It's *not* jiffies folks,
+ * but jiffies / HZ, so do not
+ * panic ...
+ */
+ u32 time_last = fibctx->jiffies;
+ /*
+ * Has it been > 2 minutes
+ * since the last read off
+ * the queue?
+ */
+ if ((time_now - time_last) > aif_timeout) {
+ entry = entry->next;
+ aac_close_fib_context(aac, fibctx);
+ continue;
+ }
+ }
+ /*
+ * Warning: no sleep allowed while
+ * holding spinlock
+ */
+ hw_fib = kmalloc(sizeof(struct hw_fib), GFP_ATOMIC);
+ fib = kmalloc(sizeof(struct fib), GFP_ATOMIC);
+ if (fib && hw_fib) {
+ struct aac_aifcmd * aif;
+
+ memset(hw_fib, 0, sizeof(struct hw_fib));
+ memset(fib, 0, sizeof(struct fib));
+ fib->hw_fib = hw_fib;
+ fib->dev = aac;
+ aac_fib_init(fib);
+ fib->type = FSAFS_NTC_FIB_CONTEXT;
+ fib->size = sizeof (struct fib);
+ fib->data = hw_fib->data;
+ aif = (struct aac_aifcmd *)hw_fib->data;
+ aif->command = cpu_to_le32(AifCmdEventNotify);
+ aif->seqnum = cpu_to_le32(0xFFFFFFFF);
+ aif->data[0] = cpu_to_le32(AifEnExpEvent);
+ aif->data[1] = cpu_to_le32(AifExeFirmwarePanic);
+ aif->data[2] = cpu_to_le32(AifHighPriority);
+ aif->data[3] = cpu_to_le32(BlinkLED);
+
+ /*
+ * Put the FIB onto the
+ * fibctx's fibs
+ */
+ list_add_tail(&fib->fiblink, &fibctx->fib_list);
+ fibctx->count++;
+ /*
+ * Set the event to wake up the
+ * thread that will waiting.
+ */
+ up(&fibctx->wait_sem);
+ } else {
+ printk(KERN_WARNING "aifd: didn't allocate NewFib.\n");
+ kfree(fib);
+ kfree(hw_fib);
+ }
+ entry = entry->next;
+ }
+
+ spin_unlock_irqrestore(&aac->fib_lock, flagv);
+
+ if (BlinkLED < 0) {
+ printk(KERN_ERR "%s: Host adapter dead %d\n", aac->name, BlinkLED);
+ goto out;
+ }
+
+ printk(KERN_ERR "%s: Host adapter BLINK LED 0x%x\n", aac->name, BlinkLED);
+
+ host = aac->scsi_host_ptr;
+ spin_lock_irqsave(host->host_lock, flagv);
+ BlinkLED = _aac_reset_adapter(aac);
+ spin_unlock_irqrestore(host->host_lock, flagv);
+ return BlinkLED;
+
+out:
+ aac->in_reset = 0;
+ return BlinkLED;
+}
+
+
/**
* aac_command_thread - command processing thread
* @dev: Adapter to monitor
diff --git a/drivers/scsi/aacraid/dpcsup.c b/drivers/scsi/aacraid/dpcsup.c
index b2a5c7262f3..8335f07b772 100644
--- a/drivers/scsi/aacraid/dpcsup.c
+++ b/drivers/scsi/aacraid/dpcsup.c
@@ -124,10 +124,15 @@ unsigned int aac_response_normal(struct aac_queue * q)
} else {
unsigned long flagv;
spin_lock_irqsave(&fib->event_lock, flagv);
- fib->done = 1;
+ if (!fib->done)
+ fib->done = 1;
up(&fib->event_wait);
spin_unlock_irqrestore(&fib->event_lock, flagv);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
+ if (fib->done == 2) {
+ aac_fib_complete(fib);
+ aac_fib_free(fib);
+ }
}
consumed++;
spin_lock_irqsave(q->lock, flags);
@@ -316,7 +321,8 @@ unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
unsigned long flagv;
dprintk((KERN_INFO "event_wait up\n"));
spin_lock_irqsave(&fib->event_lock, flagv);
- fib->done = 1;
+ if (!fib->done)
+ fib->done = 1;
up(&fib->event_wait);
spin_unlock_irqrestore(&fib->event_lock, flagv);
FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
diff --git a/drivers/scsi/aacraid/linit.c b/drivers/scsi/aacraid/linit.c
index e42a479ce64..359e7ddfdb4 100644
--- a/drivers/scsi/aacraid/linit.c
+++ b/drivers/scsi/aacraid/linit.c
@@ -82,6 +82,8 @@ static LIST_HEAD(aac_devices);
static int aac_cfg_major = -1;
char aac_driver_version[] = AAC_DRIVER_FULL_VERSION;
+extern int expose_physicals;
+
/*
* Because of the way Linux names scsi devices, the order in this table has
* become important. Check for on-board Raid first, add-in cards second.
@@ -394,6 +396,7 @@ static int aac_slave_configure(struct scsi_device *sdev)
sdev->skip_ms_page_3f = 1;
}
if ((sdev->type == TYPE_DISK) &&
+ !expose_physicals &&
(sdev_channel(sdev) != CONTAINER_CHANNEL)) {
struct aac_dev *aac = (struct aac_dev *)sdev->host->hostdata;
if (!aac->raid_scsi_mode || (sdev_channel(sdev) != 2))
@@ -454,17 +457,17 @@ static int aac_eh_reset(struct scsi_cmnd* cmd)
printk(KERN_ERR "%s: Host adapter reset request. SCSI hang ?\n",
AAC_DRIVERNAME);
aac = (struct aac_dev *)host->hostdata;
- if (aac_adapter_check_health(aac)) {
- printk(KERN_ERR "%s: Host adapter appears dead\n",
- AAC_DRIVERNAME);
- return -ENODEV;
- }
+
+ if ((count = aac_check_health(aac)))
+ return count;
/*
* Wait for all commands to complete to this specific
* target (block maximum 60 seconds).
*/
for (count = 60; count; --count) {
- int active = 0;
+ int active = aac->in_reset;
+
+ if (active == 0)
__shost_for_each_device(dev, host) {
spin_lock_irqsave(&dev->list_lock, flags);
list_for_each_entry(command, &dev->cmd_list, list) {
@@ -864,13 +867,6 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
* Map in the registers from the adapter.
*/
aac->base_size = AAC_MIN_FOOTPRINT_SIZE;
- if ((aac->regs.sa = ioremap(
- (unsigned long)aac->scsi_host_ptr->base, AAC_MIN_FOOTPRINT_SIZE))
- == NULL) {
- printk(KERN_WARNING "%s: unable to map adapter.\n",
- AAC_DRIVERNAME);
- goto out_free_fibs;
- }
if ((*aac_drivers[index].init)(aac))
goto out_unmap;
@@ -928,12 +924,12 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
* all containers are on the virtual channel 0 (CONTAINER_CHANNEL)
* physical channels are address by their actual physical number+1
*/
- if (aac->nondasd_support == 1)
+ if ((aac->nondasd_support == 1) || expose_physicals)
shost->max_channel = aac->maximum_num_channels;
else
shost->max_channel = 0;
- aac_get_config_status(aac);
+ aac_get_config_status(aac, 0);
aac_get_containers(aac);
list_add(&aac->entry, insert);
@@ -969,8 +965,7 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
kfree(aac->queues);
- iounmap(aac->regs.sa);
- out_free_fibs:
+ aac_adapter_ioremap(aac, 0);
kfree(aac->fibs);
kfree(aac->fsa_dev);
out_free_host:
@@ -1005,7 +1000,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
kfree(aac->queues);
free_irq(pdev->irq, aac);
- iounmap(aac->regs.sa);
+ aac_adapter_ioremap(aac, 0);
kfree(aac->fibs);
kfree(aac->fsa_dev);
@@ -1013,6 +1008,10 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
list_del(&aac->entry);
scsi_host_put(shost);
pci_disable_device(pdev);
+ if (list_empty(&aac_devices)) {
+ unregister_chrdev(aac_cfg_major, "aac");
+ aac_cfg_major = -1;
+ }
}
static struct pci_driver aac_pci_driver = {
diff --git a/drivers/scsi/aacraid/rkt.c b/drivers/scsi/aacraid/rkt.c
index 458ea897fd7..643f23b5ded 100644
--- a/drivers/scsi/aacraid/rkt.c
+++ b/drivers/scsi/aacraid/rkt.c
@@ -28,370 +28,27 @@
*
*/
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/pci.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
#include <linux/blkdev.h>
-#include <linux/delay.h>
-#include <linux/completion.h>
-#include <linux/time.h>
-#include <linux/interrupt.h>
-#include <asm/semaphore.h>
#include <scsi/scsi_host.h>
#include "aacraid.h"
-static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
-{
- struct aac_dev *dev = dev_id;
-
- if (dev->new_comm_interface) {
- u32 Index = rkt_readl(dev, MUnit.OutboundQueue);
- if (Index == 0xFFFFFFFFL)
- Index = rkt_readl(dev, MUnit.OutboundQueue);
- if (Index != 0xFFFFFFFFL) {
- do {
- if (aac_intr_normal(dev, Index)) {
- rkt_writel(dev, MUnit.OutboundQueue, Index);
- rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
- }
- Index = rkt_readl(dev, MUnit.OutboundQueue);
- } while (Index != 0xFFFFFFFFL);
- return IRQ_HANDLED;
- }
- } else {
- unsigned long bellbits;
- u8 intstat;
- intstat = rkt_readb(dev, MUnit.OISR);
- /*
- * Read mask and invert because drawbridge is reversed.
- * This allows us to only service interrupts that have
- * been enabled.
- * Check to see if this is our interrupt. If it isn't just return
- */
- if (intstat & ~(dev->OIMR))
- {
- bellbits = rkt_readl(dev, OutboundDoorbellReg);
- if (bellbits & DoorBellPrintfReady) {
- aac_printf(dev, rkt_readl (dev, IndexRegs.Mailbox[5]));
- rkt_writel(dev, MUnit.ODR,DoorBellPrintfReady);
- rkt_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
- }
- else if (bellbits & DoorBellAdapterNormCmdReady) {
- rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
- aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
-// rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
- }
- else if (bellbits & DoorBellAdapterNormRespReady) {
- rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
- aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
- }
- else if (bellbits & DoorBellAdapterNormCmdNotFull) {
- rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
- }
- else if (bellbits & DoorBellAdapterNormRespNotFull) {
- rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
- rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
- }
- return IRQ_HANDLED;
- }
- }
- return IRQ_NONE;
-}
-
-/**
- * aac_rkt_disable_interrupt - Disable interrupts
- * @dev: Adapter
- */
-
-static void aac_rkt_disable_interrupt(struct aac_dev *dev)
-{
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
-}
-
/**
- * rkt_sync_cmd - send a command and wait
- * @dev: Adapter
- * @command: Command to execute
- * @p1: first parameter
- * @ret: adapter status
+ * aac_rkt_ioremap
+ * @size: mapping resize request
*
- * This routine will send a synchronous command to the adapter and wait
- * for its completion.
*/
-
-static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
- u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
- u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4)
+static int aac_rkt_ioremap(struct aac_dev * dev, u32 size)
{
- unsigned long start;
- int ok;
- /*
- * Write the command into Mailbox 0
- */
- rkt_writel(dev, InboundMailbox0, command);
- /*
- * Write the parameters into Mailboxes 1 - 6
- */
- rkt_writel(dev, InboundMailbox1, p1);
- rkt_writel(dev, InboundMailbox2, p2);
- rkt_writel(dev, InboundMailbox3, p3);
- rkt_writel(dev, InboundMailbox4, p4);
- /*
- * Clear the synch command doorbell to start on a clean slate.
- */
- rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
- /*
- * Disable doorbell interrupts
- */
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
- /*
- * Force the completion of the mask register write before issuing
- * the interrupt.
- */
- rkt_readb (dev, MUnit.OIMR);
- /*
- * Signal that there is a new synch command
- */
- rkt_writel(dev, InboundDoorbellReg, INBOUNDDOORBELL_0);
-
- ok = 0;
- start = jiffies;
-
- /*
- * Wait up to 30 seconds
- */
- while (time_before(jiffies, start+30*HZ))
- {
- udelay(5); /* Delay 5 microseconds to let Mon960 get info. */
- /*
- * Mon960 will set doorbell0 bit when it has completed the command.
- */
- if (rkt_readl(dev, OutboundDoorbellReg) & OUTBOUNDDOORBELL_0) {
- /*
- * Clear the doorbell.
- */
- rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
- ok = 1;
- break;
- }
- /*
- * Yield the processor in case we are slow
- */
- msleep(1);
+ if (!size) {
+ iounmap(dev->regs.rkt);
+ return 0;
}
- if (ok != 1) {
- /*
- * Restore interrupt mask even though we timed out
- */
- if (dev->new_comm_interface)
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
- else
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
- return -ETIMEDOUT;
- }
- /*
- * Pull the synch status from Mailbox 0.
- */
- if (status)
- *status = rkt_readl(dev, IndexRegs.Mailbox[0]);
- if (r1)
- *r1 = rkt_readl(dev, IndexRegs.Mailbox[1]);
- if (r2)
- *r2 = rkt_readl(dev, IndexRegs.Mailbox[2]);
- if (r3)
- *r3 = rkt_readl(dev, IndexRegs.Mailbox[3]);
- if (r4)
- *r4 = rkt_readl(dev, IndexRegs.Mailbox[4]);
- /*
- * Clear the synch command doorbell.
- */
- rkt_writel(dev, OutboundDoorbellReg, OUTBOUNDDOORBELL_0);
- /*
- * Restore interrupt mask
- */
- if (dev->new_comm_interface)
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
- else
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
- return 0;
-
-}
-
-/**
- * aac_rkt_interrupt_adapter - interrupt adapter
- * @dev: Adapter
- *
- * Send an interrupt to the i960 and breakpoint it.
- */
-
-static void aac_rkt_interrupt_adapter(struct aac_dev *dev)
-{
- rkt_sync_cmd(dev, BREAKPOINT_REQUEST, 0, 0, 0, 0, 0, 0,
- NULL, NULL, NULL, NULL, NULL);
-}
-
-/**
- * aac_rkt_notify_adapter - send an event to the adapter
- * @dev: Adapter
- * @event: Event to send
- *
- * Notify the i960 that something it probably cares about has
- * happened.
- */
-
-static void aac_rkt_notify_adapter(struct aac_dev *dev, u32 event)
-{
- switch (event) {
-
- case AdapNormCmdQue:
- rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_1);
- break;
- case HostNormRespNotFull:
- rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_4);
- break;
- case AdapNormRespQue:
- rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_2);
- break;
- case HostNormCmdNotFull:
- rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
- break;
- case HostShutdown:
-// rkt_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
-// NULL, NULL, NULL, NULL, NULL);
- break;
- case FastIo:
- rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
- break;
- case AdapPrintfDone:
- rkt_writel(dev, MUnit.IDR,INBOUNDDOORBELL_5);
- break;
- default:
- BUG();
- break;
- }
-}
-
-/**
- * aac_rkt_start_adapter - activate adapter
- * @dev: Adapter
- *
- * Start up processing on an i960 based AAC adapter
- */
-
-static void aac_rkt_start_adapter(struct aac_dev *dev)
-{
- struct aac_init *init;
-
- init = dev->init;
- init->HostElapsedSeconds = cpu_to_le32(get_seconds());
- // We can only use a 32 bit address here
- rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
- 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
-}
-
-/**
- * aac_rkt_check_health
- * @dev: device to check if healthy
- *
- * Will attempt to determine if the specified adapter is alive and
- * capable of handling requests, returning 0 if alive.
- */
-static int aac_rkt_check_health(struct aac_dev *dev)
-{
- u32 status = rkt_readl(dev, MUnit.OMRx[0]);
-
- /*
- * Check to see if the board failed any self tests.
- */
- if (status & SELF_TEST_FAILED)
+ dev->base = dev->regs.rkt = ioremap(dev->scsi_host_ptr->base, size);
+ if (dev->base == NULL)
return -1;
- /*
- * Check to see if the board panic'd.
- */
- if (status & KERNEL_PANIC) {
- char * buffer;
- struct POSTSTATUS {
- __le32 Post_Command;
- __le32 Post_Address;
- } * post;
- dma_addr_t paddr, baddr;
- int ret;
-
- if ((status & 0xFF000000L) == 0xBC000000L)
- return (status >> 16) & 0xFF;
- buffer = pci_alloc_consistent(dev->pdev, 512, &baddr);
- ret = -2;
- if (buffer == NULL)
- return ret;
- post = pci_alloc_consistent(dev->pdev,
- sizeof(struct POSTSTATUS), &paddr);
- if (post == NULL) {
- pci_free_consistent(dev->pdev, 512, buffer, baddr);
- return ret;
- }
- memset(buffer, 0, 512);
- post->Post_Command = cpu_to_le32(COMMAND_POST_RESULTS);
- post->Post_Address = cpu_to_le32(baddr);
- rkt_writel(dev, MUnit.IMRx[0], paddr);
- rkt_sync_cmd(dev, COMMAND_POST_RESULTS, baddr, 0, 0, 0, 0, 0,
- NULL, NULL, NULL, NULL, NULL);
- pci_free_consistent(dev->pdev, sizeof(struct POSTSTATUS),
- post, paddr);
- if ((buffer[0] == '0') && ((buffer[1] == 'x') || (buffer[1] == 'X'))) {
- ret = (buffer[2] <= '9') ? (buffer[2] - '0') : (buffer[2] - 'A' + 10);
- ret <<= 4;
- ret += (buffer[3] <= '9') ? (buffer[3] - '0') : (buffer[3] - 'A' + 10);
- }
- pci_free_consistent(dev->pdev, 512, buffer, baddr);
- return ret;
- }
- /*
- * Wait for the adapter to be up and running.
- */
- if (!(status & KERNEL_UP_AND_RUNNING))
- return -3;
- /*
- * Everything is OK
- */
- return 0;
-}
-
-/**
- * aac_rkt_send
- * @fib: fib to issue
- *
- * Will send a fib, returning 0 if successful.
- */
-static int aac_rkt_send(struct fib * fib)
-{
- u64 addr = fib->hw_fib_pa;
- struct aac_dev *dev = fib->dev;
- volatile void __iomem *device = dev->regs.rkt;
- u32 Index;
-
- dprintk((KERN_DEBUG "%p->aac_rkt_send(%p->%llx)\n", dev, fib, addr));
- Index = rkt_readl(dev, MUnit.InboundQueue);
- if (Index == 0xFFFFFFFFL)
- Index = rkt_readl(dev, MUnit.InboundQueue);
- dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
- if (Index == 0xFFFFFFFFL)
- return Index;
- device += Index;
- dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
- (u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
- writel((u32)(addr & 0xffffffff), device);
- device += sizeof(u32);
- writel((u32)(addr >> 32), device);
- device += sizeof(u32);
- writel(le16_to_cpu(fib->hw_fib->header.Size), device);
- rkt_writel(dev, MUnit.InboundQueue, Index);
- dprintk((KERN_DEBUG "aac_rkt_send - return 0\n"));
+ dev->IndexRegs = &dev->regs.rkt->IndexRegs;
return 0;
}
@@ -406,78 +63,18 @@ static int aac_rkt_send(struct fib * fib)
int aac_rkt_init(struct aac_dev *dev)
{
- unsigned long start;
- unsigned long status;
- int instance;
- const char * name;
-
- instance = dev->id;
- name = dev->name;
+ int retval;
+ extern int _aac_rx_init(struct aac_dev *dev);
+ extern void aac_rx_start_adapter(struct aac_dev *dev);
/*
- * Check to see if the board panic'd while booting.
- */
- /*
- * Check to see if the board failed any self tests.
- */
- if (rkt_readl(dev, MUnit.OMRx[0]) & 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 (rkt_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) {
- printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
- goto error_iounmap;
- }
- /*
- * Check to see if the board panic'd while booting.
- */
- if (rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) {
- printk(KERN_ERR "%s%d: adapter kernel panic'd.\n", dev->name, instance);
- goto error_iounmap;
- }
- start = jiffies;
- /*
- * Wait for the adapter to be up and running. Wait up to 3 minutes
- */
- while (!(rkt_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING))
- {
- if(time_after(jiffies, start+startup_timeout*HZ))
- {
- status = rkt_readl(dev, MUnit.OMRx[0]);
- printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
- dev->name, instance, status);
- goto error_iounmap;
- }
- msleep(1);
- }
- if (request_irq(dev->scsi_host_ptr->irq, aac_rkt_intr, IRQF_SHARED|IRQF_DISABLED, "aacraid", (void *)dev)<0)
- {
- printk(KERN_ERR "%s%d: Interrupt unavailable.\n", name, instance);
- goto error_iounmap;
- }
- /*
* Fill in the function dispatch table.
*/
- dev->a_ops.adapter_interrupt = aac_rkt_interrupt_adapter;
- dev->a_ops.adapter_disable_int = aac_rkt_disable_interrupt;
- dev->a_ops.adapter_notify = aac_rkt_notify_adapter;
- dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
- dev->a_ops.adapter_check_health = aac_rkt_check_health;
- dev->a_ops.adapter_send = aac_rkt_send;
-
- /*
- * First clear out all interrupts. Then enable the one's that we
- * can handle.
- */
- rkt_writeb(dev, MUnit.OIMR, 0xff);
- rkt_writel(dev, MUnit.ODR, 0xffffffff);
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
+ dev->a_ops.adapter_ioremap = aac_rkt_ioremap;
- if (aac_init_adapter(dev) == NULL)
- goto error_irq;
+ retval = _aac_rx_init(dev);
+ if (retval)
+ return retval;
if (dev->new_comm_interface) {
/*
* FIB Setup has already been done, but we can minimize the
@@ -494,20 +91,11 @@ int aac_rkt_init(struct aac_dev *dev)
dev->init->MaxIoCommands = cpu_to_le32(246);
dev->scsi_host_ptr->can_queue = 246 - AAC_NUM_MGT_FIB;
}
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
}
/*
* Tell the adapter that all is configured, and it can start
* accepting requests
*/
- aac_rkt_start_adapter(dev);
+ aac_rx_start_adapter(dev);
return 0;
-
-error_irq:
- rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
- free_irq(dev->scsi_host_ptr->irq, (void *)dev);
-
-error_iounmap:
-
- return -1;
}
diff --git a/drivers/scsi/aacraid/rx.c b/drivers/scsi/aacraid/rx.c
index 035018db69b..a1d214d770e 100644
--- a/drivers/scsi/aacraid/rx.c
+++ b/drivers/scsi/aacraid/rx.c
@@ -79,7 +79,7 @@ static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
{
bellbits = rx_readl(dev, OutboundDoorbellReg);
if (bellbits & DoorBellPrintfReady) {
- aac_printf(dev, rx_readl (dev, IndexRegs.Mailbox[5]));
+ aac_printf(dev, readl (&dev->IndexRegs->Mailbox[5]));
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
}
@@ -134,14 +134,14 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/*
* Write the command into Mailbox 0
*/
- rx_writel(dev, InboundMailbox0, command);
+ writel(command, &dev->IndexRegs->Mailbox[0]);
/*
* Write the parameters into Mailboxes 1 - 6
*/
- rx_writel(dev, InboundMailbox1, p1);
- rx_writel(dev, InboundMailbox2, p2);
- rx_writel(dev, InboundMailbox3, p3);
- rx_writel(dev, InboundMailbox4, p4);
+ writel(p1, &dev->IndexRegs->Mailbox[1]);
+ writel(p2, &dev->IndexRegs->Mailbox[2]);
+ writel(p3, &dev->IndexRegs->Mailbox[3]);
+ writel(p4, &dev->IndexRegs->Mailbox[4]);
/*
* Clear the synch command doorbell to start on a clean slate.
*/
@@ -199,15 +199,15 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
* Pull the synch status from Mailbox 0.
*/
if (status)
- *status = rx_readl(dev, IndexRegs.Mailbox[0]);
+ *status = readl(&dev->IndexRegs->Mailbox[0]);
if (r1)
- *r1 = rx_readl(dev, IndexRegs.Mailbox[1]);
+ *r1 = readl(&dev->IndexRegs->Mailbox[1]);
if (r2)
- *r2 = rx_readl(dev, IndexRegs.Mailbox[2]);
+ *r2 = readl(&dev->IndexRegs->Mailbox[2]);
if (r3)
- *r3 = rx_readl(dev, IndexRegs.Mailbox[3]);
+ *r3 = readl(&dev->IndexRegs->Mailbox[3]);
if (r4)
- *r4 = rx_readl(dev, IndexRegs.Mailbox[4]);
+ *r4 = readl(&dev->IndexRegs->Mailbox[4]);
/*
* Clear the synch command doorbell.
*/
@@ -261,8 +261,6 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_3);
break;
case HostShutdown:
-// rx_sync_cmd(dev, HOST_CRASHING, 0, 0, 0, 0, 0, 0,
-// NULL, NULL, NULL, NULL, NULL);
break;
case FastIo:
rx_writel(dev, MUnit.IDR,INBOUNDDOORBELL_6);
@@ -283,7 +281,7 @@ static void aac_rx_notify_adapter(struct aac_dev *dev, u32 event)
* Start up processing on an i960 based AAC adapter
*/
-static void aac_rx_start_adapter(struct aac_dev *dev)
+void aac_rx_start_adapter(struct aac_dev *dev)
{
struct aac_init *init;
@@ -381,7 +379,7 @@ static int aac_rx_send(struct fib * fib)
dprintk((KERN_DEBUG "Index = 0x%x\n", Index));
if (Index == 0xFFFFFFFFL)
return Index;
- device += Index;
+ device = dev->base + Index;
dprintk((KERN_DEBUG "entry = %x %x %u\n", (u32)(addr & 0xffffffff),
(u32)(addr >> 32), (u32)le16_to_cpu(fib->hw_fib->header.Size)));
writel((u32)(addr & 0xffffffff), device);
@@ -395,6 +393,43 @@ static int aac_rx_send(struct fib * fib)
}
/**
+ * aac_rx_ioremap
+ * @size: mapping resize request
+ *
+ */
+static int aac_rx_ioremap(struct aac_dev * dev, u32 size)
+{
+ if (!size) {
+ iounmap(dev->regs.rx);
+ return 0;
+ }
+ dev->base = dev->regs.rx = ioremap(dev->scsi_host_ptr->base, size);
+ if (dev->base == NULL)
+ return -1;
+ dev->IndexRegs = &dev->regs.rx->IndexRegs;
+ return 0;
+}
+
+static int aac_rx_restart_adapter(struct aac_dev *dev)
+{
+ u32 var;
+
+ printk(KERN_ERR "%s%d: adapter kernel panic'd.\n",
+ dev->name, dev->id);
+
+ if (aac_rx_check_health(dev) <= 0)
+ return 1;
+ if (rx_sync_cmd(dev, IOP_RESET, 0, 0, 0, 0, 0, 0,
+ &var, NULL, NULL, NULL, NULL))
+ return 1;
+ if (var != 0x00000001)
+ return 1;
+ if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC)
+ return 1;
+ return 0;
+}
+
+/**
* aac_rx_init - initialize an i960 based AAC card
* @dev: device to configure
*
@@ -403,7 +438,7 @@ static int aac_rx_send(struct fib * fib)
* to the comm region.
*/
-int aac_rx_init(struct aac_dev *dev)
+int _aac_rx_init(struct aac_dev *dev)
{
unsigned long start;
unsigned long status;
@@ -413,27 +448,30 @@ int aac_rx_init(struct aac_dev *dev)
instance = dev->id;
name = dev->name;
+ if (aac_adapter_ioremap(dev, dev->base_size)) {
+ printk(KERN_WARNING "%s: unable to map adapter.\n", name);
+ goto error_iounmap;
+ }
+
/*
* Check to see if the board panic'd while booting.
*/
+ status = rx_readl(dev, MUnit.OMRx[0]);
+ if (status & KERNEL_PANIC)
+ if (aac_rx_restart_adapter(dev))
+ goto error_iounmap;
/*
* Check to see if the board failed any self tests.
*/
- if (rx_readl(dev, MUnit.OMRx[0]) & SELF_TEST_FAILED) {
+ status = rx_readl(dev, MUnit.OMRx[0]);
+ 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 board panic'd while booting.
- */
- if (rx_readl(dev, MUnit.OMRx[0]) & KERNEL_PANIC) {
- printk(KERN_ERR "%s%d: adapter kernel panic.\n", dev->name, instance);
- goto error_iounmap;
- }
- /*
* Check to see if the monitor panic'd while booting.
*/
- if (rx_readl(dev, MUnit.OMRx[0]) & MONITOR_PANIC) {
+ if (status & MONITOR_PANIC) {
printk(KERN_ERR "%s%d: adapter monitor panic.\n", dev->name, instance);
goto error_iounmap;
}
@@ -441,12 +479,10 @@ int aac_rx_init(struct aac_dev *dev)
/*
* Wait for the adapter to be up and running. Wait up to 3 minutes
*/
- while ((!(rx_readl(dev, IndexRegs.Mailbox[7]) & KERNEL_UP_AND_RUNNING))
- || (!(rx_readl(dev, MUnit.OMRx[0]) & KERNEL_UP_AND_RUNNING)))
+ while (!((status = rx_readl(dev, MUnit.OMRx[0])) & KERNEL_UP_AND_RUNNING))
{
if(time_after(jiffies, start+startup_timeout*HZ))
{
- status = rx_readl(dev, IndexRegs.Mailbox[7]);
printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
dev->name, instance, status);
goto error_iounmap;
@@ -481,11 +517,6 @@ int aac_rx_init(struct aac_dev *dev)
if (dev->new_comm_interface)
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
- /*
- * Tell the adapter that all is configured, and it can start
- * accepting requests
- */
- aac_rx_start_adapter(dev);
return 0;
error_irq:
@@ -496,3 +527,23 @@ error_iounmap:
return -1;
}
+
+int aac_rx_init(struct aac_dev *dev)
+{
+ int retval;
+
+ /*
+ * Fill in the function dispatch table.
+ */
+ dev->a_ops.adapter_ioremap = aac_rx_ioremap;
+
+ retval = _aac_rx_init(dev);
+ if (!retval) {
+ /*
+ * Tell the adapter that all is configured, and it can
+ * start accepting requests
+ */
+ aac_rx_start_adapter(dev);
+ }
+ return retval;
+}
diff --git a/drivers/scsi/aacraid/sa.c b/drivers/scsi/aacraid/sa.c
index cd586cc8f9b..f906ead239d 100644
--- a/drivers/scsi/aacraid/sa.c
+++ b/drivers/scsi/aacraid/sa.c
@@ -281,6 +281,21 @@ static int aac_sa_check_health(struct aac_dev *dev)
}
/**
+ * aac_sa_ioremap
+ * @size: mapping resize request
+ *
+ */
+static int aac_sa_ioremap(struct aac_dev * dev, u32 size)
+{
+ if (!size) {
+ iounmap(dev->regs.sa);
+ return 0;
+ }
+ dev->base = dev->regs.sa = ioremap(dev->scsi_host_ptr->base, size);
+ return (dev->base == NULL) ? -1 : 0;
+}
+
+/**
* aac_sa_init - initialize an ARM based AAC card
* @dev: device to configure
*
@@ -299,6 +314,11 @@ int aac_sa_init(struct aac_dev *dev)
instance = dev->id;
name = dev->name;
+ if (aac_sa_ioremap(dev, dev->base_size)) {
+ printk(KERN_WARNING "%s: unable to map adapter.\n", name);
+ goto error_iounmap;
+ }
+
/*
* Check to see if the board failed any self tests.
*/
@@ -341,6 +361,7 @@ int aac_sa_init(struct aac_dev *dev)
dev->a_ops.adapter_notify = aac_sa_notify_adapter;
dev->a_ops.adapter_sync_cmd = sa_sync_cmd;
dev->a_ops.adapter_check_health = aac_sa_check_health;
+ dev->a_ops.adapter_ioremap = aac_sa_ioremap;
/*
* First clear out all interrupts. Then enable the one's that