mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 19:26:25 +00:00
[SCSI] aacraid: Newer adapter communication iterface support
Received from Mark Salyzyn. This patch adds the 'new comm' interface, which modern AAC based adapters that are less than a year old support in the name of much improved performance. These modern adapters support both the legacy and the 'new comm' interfaces. Signed-off-by: Mark Haverkamp <markh@osdl.org> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
parent
38a9a621ab
commit
8e0c5ebde8
11 changed files with 453 additions and 218 deletions
|
@ -57,7 +57,7 @@ Deanna Bonds (non-DASD support, PAE fibs and 64 bit,
|
|||
(fixed 64bit and 64G memory model, changed confusing naming convention
|
||||
where fibs that go to the hardware are consistently called hw_fibs and
|
||||
not just fibs like the name of the driver tracking structure)
|
||||
Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas.
|
||||
Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.
|
||||
|
||||
Original Driver
|
||||
-------------------------
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
o Testing
|
||||
o More testing
|
||||
o Drop irq_mask, basically unused
|
||||
o I/O size increase
|
||||
|
|
|
@ -359,15 +359,6 @@ int aac_get_containers(struct aac_dev *dev)
|
|||
return status;
|
||||
}
|
||||
|
||||
static void aac_io_done(struct scsi_cmnd * scsicmd)
|
||||
{
|
||||
unsigned long cpu_flags;
|
||||
struct Scsi_Host *host = scsicmd->device->host;
|
||||
spin_lock_irqsave(host->host_lock, cpu_flags);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
spin_unlock_irqrestore(host->host_lock, cpu_flags);
|
||||
}
|
||||
|
||||
static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
|
||||
{
|
||||
void *buf;
|
||||
|
@ -424,7 +415,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
|
|||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_io_done(scsicmd);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -988,7 +979,7 @@ static void io_callback(void *context, struct fib * fibptr)
|
|||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
|
||||
aac_io_done(scsicmd);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
}
|
||||
|
||||
static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
||||
|
@ -1167,7 +1158,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
|
|||
* For some reason, the Fib didn't queue, return QUEUE_FULL
|
||||
*/
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
|
||||
aac_io_done(scsicmd);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
fib_complete(cmd_fibcontext);
|
||||
fib_free(cmd_fibcontext);
|
||||
return 0;
|
||||
|
@ -1239,7 +1230,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
|||
*/
|
||||
if (!(cmd_fibcontext = fib_alloc(dev))) {
|
||||
scsicmd->result = DID_ERROR << 16;
|
||||
aac_io_done(scsicmd);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
return 0;
|
||||
}
|
||||
fib_init(cmd_fibcontext);
|
||||
|
@ -1336,7 +1327,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
|
|||
* For some reason, the Fib didn't queue, return QUEUE_FULL
|
||||
*/
|
||||
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
|
||||
aac_io_done(scsicmd);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
|
||||
fib_complete(cmd_fibcontext);
|
||||
fib_free(cmd_fibcontext);
|
||||
|
@ -1380,7 +1371,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
|
|||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_io_done(cmd);
|
||||
cmd->scsi_done(cmd);
|
||||
}
|
||||
|
||||
static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
|
||||
|
@ -2097,7 +2088,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
|
|||
|
||||
fib_complete(fibptr);
|
||||
fib_free(fibptr);
|
||||
aac_io_done(scsicmd);
|
||||
scsicmd->scsi_done(scsicmd);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -481,6 +481,7 @@ enum aac_log_level {
|
|||
#define FSAFS_NTC_FIB_CONTEXT 0x030c
|
||||
|
||||
struct aac_dev;
|
||||
struct fib;
|
||||
|
||||
struct adapter_ops
|
||||
{
|
||||
|
@ -489,6 +490,7 @@ struct adapter_ops
|
|||
void (*adapter_disable_int)(struct aac_dev *dev);
|
||||
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);
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -659,6 +661,10 @@ struct rx_mu_registers {
|
|||
Status Register */
|
||||
__le32 OIMR; /* 1334h | 34h | Outbound Interrupt
|
||||
Mask Register */
|
||||
__le32 reserved2; /* 1338h | 38h | Reserved */
|
||||
__le32 reserved3; /* 133Ch | 3Ch | Reserved */
|
||||
__le32 InboundQueue;/* 1340h | 40h | Inbound Queue Port relative to firmware */
|
||||
__le32 OutboundQueue;/*1344h | 44h | Outbound Queue Port relative to firmware */
|
||||
/* * Must access through ATU Inbound
|
||||
Translation Window */
|
||||
};
|
||||
|
@ -693,8 +699,8 @@ struct rx_inbound {
|
|||
#define OutboundDoorbellReg MUnit.ODR
|
||||
|
||||
struct rx_registers {
|
||||
struct rx_mu_registers MUnit; /* 1300h - 1334h */
|
||||
__le32 reserved1[6]; /* 1338h - 134ch */
|
||||
struct rx_mu_registers MUnit; /* 1300h - 1344h */
|
||||
__le32 reserved1[2]; /* 1348h - 134ch */
|
||||
struct rx_inbound IndexRegs;
|
||||
};
|
||||
|
||||
|
@ -711,8 +717,8 @@ struct rx_registers {
|
|||
#define rkt_inbound rx_inbound
|
||||
|
||||
struct rkt_registers {
|
||||
struct rkt_mu_registers MUnit; /* 1300h - 1334h */
|
||||
__le32 reserved1[1010]; /* 1338h - 22fch */
|
||||
struct rkt_mu_registers MUnit; /* 1300h - 1344h */
|
||||
__le32 reserved1[1006]; /* 1348h - 22fch */
|
||||
struct rkt_inbound IndexRegs; /* 2300h - */
|
||||
};
|
||||
|
||||
|
@ -721,8 +727,6 @@ struct rkt_registers {
|
|||
#define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR))
|
||||
#define rkt_writel(AEP, CSR, value) writel(value, &((AEP)->regs.rkt->CSR))
|
||||
|
||||
struct fib;
|
||||
|
||||
typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
|
||||
|
||||
struct aac_fib_context {
|
||||
|
@ -937,7 +941,6 @@ struct aac_dev
|
|||
const char *name;
|
||||
int id;
|
||||
|
||||
u16 irq_mask;
|
||||
/*
|
||||
* negotiated FIB settings
|
||||
*/
|
||||
|
@ -972,6 +975,7 @@ struct aac_dev
|
|||
struct adapter_ops a_ops;
|
||||
unsigned long fsrev; /* Main driver's revision number */
|
||||
|
||||
unsigned base_size; /* Size of mapped in region */
|
||||
struct aac_init *init; /* Holds initialization info to communicate with adapter */
|
||||
dma_addr_t init_pa; /* Holds physical address of the init struct */
|
||||
|
||||
|
@ -992,6 +996,9 @@ struct aac_dev
|
|||
/*
|
||||
* The following is the device specific extension.
|
||||
*/
|
||||
#if (!defined(AAC_MIN_FOOTPRINT_SIZE))
|
||||
# define AAC_MIN_FOOTPRINT_SIZE 8192
|
||||
#endif
|
||||
union
|
||||
{
|
||||
struct sa_registers __iomem *sa;
|
||||
|
@ -1012,6 +1019,7 @@ struct aac_dev
|
|||
u8 nondasd_support;
|
||||
u8 dac_support;
|
||||
u8 raid_scsi_mode;
|
||||
u8 new_comm_interface;
|
||||
/* macro side-effects BEWARE */
|
||||
# define raw_io_interface \
|
||||
init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
|
||||
|
@ -1034,6 +1042,8 @@ struct aac_dev
|
|||
#define aac_adapter_check_health(dev) \
|
||||
(dev)->a_ops.adapter_check_health(dev)
|
||||
|
||||
#define aac_adapter_send(fib) \
|
||||
((fib)->dev)->a_ops.adapter_send(fib)
|
||||
|
||||
#define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001)
|
||||
|
||||
|
@ -1779,6 +1789,7 @@ int aac_rkt_init(struct aac_dev *dev);
|
|||
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_command_thread(struct aac_dev * dev);
|
||||
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
|
||||
int fib_adapter_complete(struct fib * fibptr, unsigned short size);
|
||||
|
|
|
@ -116,6 +116,10 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
|
|||
}
|
||||
|
||||
init->InitFlags = 0;
|
||||
if (dev->new_comm_interface) {
|
||||
init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
|
||||
dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
|
||||
}
|
||||
init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
|
||||
init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
|
||||
init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
|
||||
|
@ -315,12 +319,33 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
|
|||
- sizeof(struct aac_fibhdr)
|
||||
- sizeof(struct aac_write) + sizeof(struct sgentry))
|
||||
/ sizeof(struct sgentry);
|
||||
dev->new_comm_interface = 0;
|
||||
dev->raw_io_64 = 0;
|
||||
if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
|
||||
0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
|
||||
(status[0] == 0x00000001)) {
|
||||
if (status[1] & AAC_OPT_NEW_COMM_64)
|
||||
dev->raw_io_64 = 1;
|
||||
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);
|
||||
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) {
|
||||
/* remap failed, go back ... */
|
||||
dev->new_comm_interface = 0;
|
||||
dev->regs.sa = ioremap(host->base,
|
||||
AAC_MIN_FOOTPRINT_SIZE);
|
||||
if (dev->regs.sa == NULL) {
|
||||
printk(KERN_WARNING
|
||||
"aacraid: unable to map adapter.\n");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
|
||||
0, 0, 0, 0, 0, 0,
|
||||
|
|
|
@ -212,7 +212,7 @@ void fib_init(struct fib *fibptr)
|
|||
hw_fib->header.StructType = FIB_MAGIC;
|
||||
hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size);
|
||||
hw_fib->header.XferState = cpu_to_le32(HostOwned | FibInitialized | FibEmpty | FastResponseCapable);
|
||||
hw_fib->header.SenderFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
|
||||
hw_fib->header.SenderFibAddress = 0; /* Filled in later if needed */
|
||||
hw_fib->header.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
|
||||
hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size);
|
||||
}
|
||||
|
@ -380,9 +380,7 @@ static int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_f
|
|||
|
||||
int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data)
|
||||
{
|
||||
u32 index;
|
||||
struct aac_dev * dev = fibptr->dev;
|
||||
unsigned long nointr = 0;
|
||||
struct hw_fib * hw_fib = fibptr->hw_fib;
|
||||
struct aac_queue * q;
|
||||
unsigned long flags = 0;
|
||||
|
@ -417,7 +415,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
|
|||
* Map the fib into 32bits by using the fib number
|
||||
*/
|
||||
|
||||
hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr-dev->fibs)) << 1);
|
||||
hw_fib->header.SenderFibAddress = cpu_to_le32(((u32)(fibptr - dev->fibs)) << 2);
|
||||
hw_fib->header.SenderData = (u32)(fibptr - dev->fibs);
|
||||
/*
|
||||
* Set FIB state to indicate where it came from and if we want a
|
||||
|
@ -456,10 +454,10 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
|
|||
|
||||
FIB_COUNTER_INCREMENT(aac_config.FibsSent);
|
||||
|
||||
dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
|
||||
dprintk((KERN_DEBUG "Fib contents:.\n"));
|
||||
dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command));
|
||||
dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState));
|
||||
dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command)));
|
||||
dprintk((KERN_DEBUG " SubCommand = %d.\n", le32_to_cpu(((struct aac_query_mount *)fib_data(fibptr))->command)));
|
||||
dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState)));
|
||||
dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib));
|
||||
dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
|
||||
dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
|
||||
|
@ -469,14 +467,37 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
|
|||
if(wait)
|
||||
spin_lock_irqsave(&fibptr->event_lock, flags);
|
||||
spin_lock_irqsave(q->lock, qflags);
|
||||
aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
|
||||
if (dev->new_comm_interface) {
|
||||
unsigned long count = 10000000L; /* 50 seconds */
|
||||
list_add_tail(&fibptr->queue, &q->pendingq);
|
||||
q->numpending++;
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
while (aac_adapter_send(fibptr) != 0) {
|
||||
if (--count == 0) {
|
||||
if (wait)
|
||||
spin_unlock_irqrestore(&fibptr->event_lock, flags);
|
||||
spin_lock_irqsave(q->lock, qflags);
|
||||
q->numpending--;
|
||||
list_del(&fibptr->queue);
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
udelay(5);
|
||||
}
|
||||
} else {
|
||||
u32 index;
|
||||
unsigned long nointr = 0;
|
||||
aac_queue_get( dev, &index, AdapNormCmdQueue, hw_fib, 1, fibptr, &nointr);
|
||||
|
||||
list_add_tail(&fibptr->queue, &q->pendingq);
|
||||
q->numpending++;
|
||||
*(q->headers.producer) = cpu_to_le32(index + 1);
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
|
||||
if (!(nointr & aac_config.irq_mod))
|
||||
aac_adapter_notify(dev, AdapNormCmdQueue);
|
||||
}
|
||||
|
||||
list_add_tail(&fibptr->queue, &q->pendingq);
|
||||
q->numpending++;
|
||||
*(q->headers.producer) = cpu_to_le32(index + 1);
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
if (!(nointr & aac_config.irq_mod))
|
||||
aac_adapter_notify(dev, AdapNormCmdQueue);
|
||||
/*
|
||||
* If the caller wanted us to wait for response wait now.
|
||||
*/
|
||||
|
@ -492,7 +513,6 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
|
|||
* hardware failure has occurred.
|
||||
*/
|
||||
unsigned long count = 36000000L; /* 3 minutes */
|
||||
unsigned long qflags;
|
||||
while (down_trylock(&fibptr->event_wait)) {
|
||||
if (--count == 0) {
|
||||
spin_lock_irqsave(q->lock, qflags);
|
||||
|
@ -621,12 +641,16 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
|
|||
unsigned long qflags;
|
||||
|
||||
if (hw_fib->header.XferState == 0) {
|
||||
if (dev->new_comm_interface)
|
||||
kfree (hw_fib);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* If we plan to do anything check the structure type first.
|
||||
*/
|
||||
if ( hw_fib->header.StructType != FIB_MAGIC ) {
|
||||
if (dev->new_comm_interface)
|
||||
kfree (hw_fib);
|
||||
return -EINVAL;
|
||||
}
|
||||
/*
|
||||
|
@ -637,21 +661,25 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
|
|||
* send the completed cdb to the adapter.
|
||||
*/
|
||||
if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
|
||||
u32 index;
|
||||
hw_fib->header.XferState |= cpu_to_le32(HostProcessed);
|
||||
if (size) {
|
||||
size += sizeof(struct aac_fibhdr);
|
||||
if (size > le16_to_cpu(hw_fib->header.SenderSize))
|
||||
return -EMSGSIZE;
|
||||
hw_fib->header.Size = cpu_to_le16(size);
|
||||
if (dev->new_comm_interface) {
|
||||
kfree (hw_fib);
|
||||
} else {
|
||||
u32 index;
|
||||
hw_fib->header.XferState |= cpu_to_le32(HostProcessed);
|
||||
if (size) {
|
||||
size += sizeof(struct aac_fibhdr);
|
||||
if (size > le16_to_cpu(hw_fib->header.SenderSize))
|
||||
return -EMSGSIZE;
|
||||
hw_fib->header.Size = cpu_to_le16(size);
|
||||
}
|
||||
q = &dev->queues->queue[AdapNormRespQueue];
|
||||
spin_lock_irqsave(q->lock, qflags);
|
||||
aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr);
|
||||
*(q->headers.producer) = cpu_to_le32(index + 1);
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
if (!(nointr & (int)aac_config.irq_mod))
|
||||
aac_adapter_notify(dev, AdapNormRespQueue);
|
||||
}
|
||||
q = &dev->queues->queue[AdapNormRespQueue];
|
||||
spin_lock_irqsave(q->lock, qflags);
|
||||
aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr);
|
||||
*(q->headers.producer) = cpu_to_le32(index + 1);
|
||||
spin_unlock_irqrestore(q->lock, qflags);
|
||||
if (!(nointr & (int)aac_config.irq_mod))
|
||||
aac_adapter_notify(dev, AdapNormRespQueue);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -73,7 +73,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
|
|||
int fast;
|
||||
u32 index = le32_to_cpu(entry->addr);
|
||||
fast = index & 0x01;
|
||||
fib = &dev->fibs[index >> 1];
|
||||
fib = &dev->fibs[index >> 2];
|
||||
hwfib = fib->hw_fib;
|
||||
|
||||
aac_consumer_free(dev, q, HostNormRespQueue);
|
||||
|
@ -213,3 +213,116 @@ unsigned int aac_command_normal(struct aac_queue *q)
|
|||
spin_unlock_irqrestore(q->lock, flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* aac_intr_normal - Handle command replies
|
||||
* @dev: Device
|
||||
* @index: completion reference
|
||||
*
|
||||
* This DPC routine will be run when the adapter interrupts us to let us
|
||||
* know there is a response on our normal priority queue. We will pull off
|
||||
* all QE there are and wake up all the waiters before exiting.
|
||||
*/
|
||||
|
||||
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index)
|
||||
{
|
||||
u32 index = le32_to_cpu(Index);
|
||||
|
||||
dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, Index));
|
||||
if ((index & 0x00000002L)) {
|
||||
struct hw_fib * hw_fib;
|
||||
struct fib * fib;
|
||||
struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue];
|
||||
unsigned long flags;
|
||||
|
||||
if (index == 0xFFFFFFFEL) /* Special Case */
|
||||
return 0; /* Do nothing */
|
||||
/*
|
||||
* Allocate a FIB. For non queued stuff we can just use
|
||||
* the stack so we are happy. We need a fib object in order to
|
||||
* manage the linked lists.
|
||||
*/
|
||||
if ((!dev->aif_thread)
|
||||
|| (!(fib = kmalloc(sizeof(struct fib),GFP_ATOMIC))))
|
||||
return 1;
|
||||
if (!(hw_fib = kmalloc(sizeof(struct hw_fib),GFP_ATOMIC))) {
|
||||
kfree (fib);
|
||||
return 1;
|
||||
}
|
||||
memset(hw_fib, 0, sizeof(struct hw_fib));
|
||||
memcpy(hw_fib, (struct hw_fib *)(((unsigned long)(dev->regs.sa)) + (index & ~0x00000002L)), sizeof(struct hw_fib));
|
||||
memset(fib, 0, sizeof(struct fib));
|
||||
INIT_LIST_HEAD(&fib->fiblink);
|
||||
fib->type = FSAFS_NTC_FIB_CONTEXT;
|
||||
fib->size = sizeof(struct fib);
|
||||
fib->hw_fib = hw_fib;
|
||||
fib->data = hw_fib->data;
|
||||
fib->dev = dev;
|
||||
|
||||
spin_lock_irqsave(q->lock, flags);
|
||||
list_add_tail(&fib->fiblink, &q->cmdq);
|
||||
wake_up_interruptible(&q->cmdready);
|
||||
spin_unlock_irqrestore(q->lock, flags);
|
||||
return 1;
|
||||
} else {
|
||||
int fast = index & 0x01;
|
||||
struct fib * fib = &dev->fibs[index >> 2];
|
||||
struct hw_fib * hwfib = fib->hw_fib;
|
||||
|
||||
/*
|
||||
* Remove this fib from the Outstanding I/O queue.
|
||||
* But only if it has not already been timed out.
|
||||
*
|
||||
* If the fib has been timed out already, then just
|
||||
* continue. The caller has already been notified that
|
||||
* the fib timed out.
|
||||
*/
|
||||
if ((fib->flags & FIB_CONTEXT_FLAG_TIMED_OUT)) {
|
||||
printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
|
||||
printk(KERN_DEBUG"aacraid: hwfib=%p index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
|
||||
return 0;
|
||||
}
|
||||
|
||||
list_del(&fib->queue);
|
||||
dev->queues->queue[AdapNormCmdQueue].numpending--;
|
||||
|
||||
if (fast) {
|
||||
/*
|
||||
* Doctor the fib
|
||||
*/
|
||||
*(__le32 *)hwfib->data = cpu_to_le32(ST_OK);
|
||||
hwfib->header.XferState |= cpu_to_le32(AdapterProcessed);
|
||||
}
|
||||
|
||||
FIB_COUNTER_INCREMENT(aac_config.FibRecved);
|
||||
|
||||
if (hwfib->header.Command == cpu_to_le16(NuFileSystem))
|
||||
{
|
||||
u32 *pstatus = (u32 *)hwfib->data;
|
||||
if (*pstatus & cpu_to_le32(0xffff0000))
|
||||
*pstatus = cpu_to_le32(ST_OK);
|
||||
}
|
||||
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected | Async))
|
||||
{
|
||||
if (hwfib->header.XferState & cpu_to_le32(NoResponseExpected))
|
||||
FIB_COUNTER_INCREMENT(aac_config.NoResponseRecved);
|
||||
else
|
||||
FIB_COUNTER_INCREMENT(aac_config.AsyncRecved);
|
||||
/*
|
||||
* NOTE: we cannot touch the fib after this
|
||||
* call, because it may have been deallocated.
|
||||
*/
|
||||
fib->callback(fib->callback_data, fib);
|
||||
} else {
|
||||
unsigned long flagv;
|
||||
dprintk((KERN_INFO "event_wait up\n"));
|
||||
spin_lock_irqsave(&fib->event_lock, flagv);
|
||||
fib->done = 1;
|
||||
up(&fib->event_wait);
|
||||
spin_unlock_irqrestore(&fib->event_lock, flagv);
|
||||
FIB_COUNTER_INCREMENT(aac_config.NormalRecved);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -788,8 +788,29 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
|
|||
goto out_free_host;
|
||||
spin_lock_init(&aac->fib_lock);
|
||||
|
||||
if ((*aac_drivers[index].init)(aac))
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/*
|
||||
* Start any kernel threads needed
|
||||
*/
|
||||
aac->thread_pid = kernel_thread((int (*)(void *))aac_command_thread,
|
||||
aac, 0);
|
||||
if (aac->thread_pid < 0) {
|
||||
printk(KERN_ERR "aacraid: Unable to create command thread.\n");
|
||||
goto out_deinit;
|
||||
}
|
||||
|
||||
/*
|
||||
* If we had set a smaller DMA mask earlier, set it to 4gig
|
||||
|
@ -866,10 +887,11 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
|
|||
|
||||
aac_send_shutdown(aac);
|
||||
aac_adapter_disable_int(aac);
|
||||
free_irq(pdev->irq, aac);
|
||||
out_unmap:
|
||||
fib_map_free(aac);
|
||||
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
|
||||
kfree(aac->queues);
|
||||
free_irq(pdev->irq, aac);
|
||||
iounmap(aac->regs.sa);
|
||||
out_free_fibs:
|
||||
kfree(aac->fibs);
|
||||
|
@ -910,6 +932,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
|
|||
iounmap(aac->regs.sa);
|
||||
|
||||
kfree(aac->fibs);
|
||||
kfree(aac->fsa_dev);
|
||||
|
||||
list_del(&aac->entry);
|
||||
scsi_host_put(shost);
|
||||
|
|
|
@ -49,40 +49,57 @@
|
|||
static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct aac_dev *dev = dev_id;
|
||||
unsigned long bellbits;
|
||||
u8 intstat, mask;
|
||||
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.
|
||||
*/
|
||||
mask = ~(dev->OIMR);
|
||||
/* Check to see if this is our interrupt. If it isn't just return */
|
||||
if (intstat & mask)
|
||||
{
|
||||
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);
|
||||
|
||||
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 if (bellbits & DoorBellAdapterNormCmdReady) {
|
||||
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
|
||||
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
|
||||
} 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;
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormRespReady) {
|
||||
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
|
||||
rkt_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
@ -173,7 +190,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
|
|||
/*
|
||||
* Restore interrupt mask even though we timed out
|
||||
*/
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
if (dev->new_comm_interface)
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
|
||||
else
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
/*
|
||||
|
@ -196,7 +216,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
|
|||
/*
|
||||
* Restore interrupt mask
|
||||
*/
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
if (dev->new_comm_interface)
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
|
||||
else
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -268,15 +291,6 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
|
|||
|
||||
init = dev->init;
|
||||
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
|
||||
/*
|
||||
* 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, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
|
||||
// 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);
|
||||
|
@ -349,6 +363,39 @@ static int aac_rkt_check_health(struct aac_dev *dev)
|
|||
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"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_rkt_init - initialize an i960 based AAC card
|
||||
* @dev: device to configure
|
||||
|
@ -369,13 +416,8 @@ int aac_rkt_init(struct aac_dev *dev)
|
|||
name = dev->name;
|
||||
|
||||
/*
|
||||
* Map in the registers from the adapter.
|
||||
* Check to see if the board panic'd while booting.
|
||||
*/
|
||||
if((dev->regs.rkt = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
|
||||
{
|
||||
printk(KERN_WARNING "aacraid: unable to map i960.\n" );
|
||||
goto error_iounmap;
|
||||
}
|
||||
/*
|
||||
* Check to see if the board failed any self tests.
|
||||
*/
|
||||
|
@ -426,6 +468,7 @@ int aac_rkt_init(struct aac_dev *dev)
|
|||
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
|
||||
|
@ -437,15 +480,24 @@ int aac_rkt_init(struct aac_dev *dev)
|
|||
|
||||
if (aac_init_adapter(dev) == NULL)
|
||||
goto error_irq;
|
||||
/*
|
||||
* Start any kernel threads needed
|
||||
*/
|
||||
dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
|
||||
if(dev->thread_pid < 0)
|
||||
{
|
||||
printk(KERN_ERR "aacraid: Unable to create rkt thread.\n");
|
||||
goto error_kfree;
|
||||
}
|
||||
if (dev->new_comm_interface) {
|
||||
/*
|
||||
* FIB Setup has already been done, but we can minimize the
|
||||
* damage by at least ensuring the OS never issues more
|
||||
* commands than we can handle. The Rocket adapters currently
|
||||
* can only handle 246 commands and 8 AIFs at the same time,
|
||||
* and in fact do notify us accordingly if we negotiate the
|
||||
* FIB size. The problem that causes us to add this check is
|
||||
* to ensure that we do not overdo it with the adapter when a
|
||||
* hard coded FIB override is being utilized. This special
|
||||
* case warrants this half baked, but convenient, check here.
|
||||
*/
|
||||
if (dev->scsi_host_ptr->can_queue > (246 - AAC_NUM_MGT_FIB)) {
|
||||
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
|
||||
|
@ -453,15 +505,11 @@ int aac_rkt_init(struct aac_dev *dev)
|
|||
aac_rkt_start_adapter(dev);
|
||||
return 0;
|
||||
|
||||
error_kfree:
|
||||
kfree(dev->queues);
|
||||
|
||||
error_irq:
|
||||
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
|
||||
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
|
||||
|
||||
error_iounmap:
|
||||
iounmap(dev->regs.rkt);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -49,40 +49,57 @@
|
|||
static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
|
||||
{
|
||||
struct aac_dev *dev = dev_id;
|
||||
unsigned long bellbits;
|
||||
u8 intstat, mask;
|
||||
intstat = rx_readb(dev, MUnit.OISR);
|
||||
/*
|
||||
* Read mask and invert because drawbridge is reversed.
|
||||
* This allows us to only service interrupts that have
|
||||
* been enabled.
|
||||
*/
|
||||
mask = ~(dev->OIMR);
|
||||
/* Check to see if this is our interrupt. If it isn't just return */
|
||||
if (intstat & mask)
|
||||
{
|
||||
bellbits = rx_readl(dev, OutboundDoorbellReg);
|
||||
if (bellbits & DoorBellPrintfReady) {
|
||||
aac_printf(dev, rx_readl(dev, IndexRegs.Mailbox[5]));
|
||||
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
|
||||
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
|
||||
|
||||
dprintk((KERN_DEBUG "aac_rx_intr(%d,%p,%p)\n", irq, dev_id, regs));
|
||||
if (dev->new_comm_interface) {
|
||||
u32 Index = rx_readl(dev, MUnit.OutboundQueue);
|
||||
if (Index == 0xFFFFFFFFL)
|
||||
Index = rx_readl(dev, MUnit.OutboundQueue);
|
||||
if (Index != 0xFFFFFFFFL) {
|
||||
do {
|
||||
if (aac_intr_normal(dev, Index)) {
|
||||
rx_writel(dev, MUnit.OutboundQueue, Index);
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
|
||||
}
|
||||
Index = rx_readl(dev, MUnit.OutboundQueue);
|
||||
} while (Index != 0xFFFFFFFFL);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormCmdReady) {
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
|
||||
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
|
||||
} else {
|
||||
unsigned long bellbits;
|
||||
u8 intstat;
|
||||
intstat = rx_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 = rx_readl(dev, OutboundDoorbellReg);
|
||||
if (bellbits & DoorBellPrintfReady) {
|
||||
aac_printf(dev, rx_readl (dev, IndexRegs.Mailbox[5]));
|
||||
rx_writel(dev, MUnit.ODR,DoorBellPrintfReady);
|
||||
rx_writel(dev, InboundDoorbellReg,DoorBellPrintfDone);
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormCmdReady) {
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
|
||||
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormRespReady) {
|
||||
rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
|
||||
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormCmdNotFull) {
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormRespNotFull) {
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormRespReady) {
|
||||
aac_response_normal(&dev->queues->queue[HostNormRespQueue]);
|
||||
rx_writel(dev, MUnit.ODR,DoorBellAdapterNormRespReady);
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormCmdNotFull) {
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
|
||||
}
|
||||
else if (bellbits & DoorBellAdapterNormRespNotFull) {
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull);
|
||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull);
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
return IRQ_NONE;
|
||||
}
|
||||
|
@ -173,7 +190,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
|
|||
/*
|
||||
* Restore interrupt mask even though we timed out
|
||||
*/
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
|
||||
if (dev->new_comm_interface)
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
|
||||
else
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
/*
|
||||
|
@ -196,7 +216,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
|
|||
/*
|
||||
* Restore interrupt mask
|
||||
*/
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR &= 0xfb);
|
||||
if (dev->new_comm_interface)
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
|
||||
else
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -267,15 +290,6 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
|
|||
|
||||
init = dev->init;
|
||||
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that we
|
||||
* can handle.
|
||||
*/
|
||||
rx_writeb(dev, MUnit.OIMR, 0xff);
|
||||
rx_writel(dev, MUnit.ODR, 0xffffffff);
|
||||
// rx_writeb(dev, MUnit.OIMR, ~(u8)OUTBOUND_DOORBELL_INTERRUPT_MASK);
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xfb);
|
||||
|
||||
// We can only use a 32 bit address here
|
||||
rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
|
||||
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
|
||||
|
@ -348,6 +362,39 @@ static int aac_rx_check_health(struct aac_dev *dev)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_rx_send
|
||||
* @fib: fib to issue
|
||||
*
|
||||
* Will send a fib, returning 0 if successful.
|
||||
*/
|
||||
static int aac_rx_send(struct fib * fib)
|
||||
{
|
||||
u64 addr = fib->hw_fib_pa;
|
||||
struct aac_dev *dev = fib->dev;
|
||||
volatile void __iomem *device = dev->regs.rx;
|
||||
u32 Index;
|
||||
|
||||
dprintk((KERN_DEBUG "%p->aac_rx_send(%p->%llx)\n", dev, fib, addr));
|
||||
Index = rx_readl(dev, MUnit.InboundQueue);
|
||||
if (Index == 0xFFFFFFFFL)
|
||||
Index = rx_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);
|
||||
rx_writel(dev, MUnit.InboundQueue, Index);
|
||||
dprintk((KERN_DEBUG "aac_rx_send - return 0\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* aac_rx_init - initialize an i960 based AAC card
|
||||
* @dev: device to configure
|
||||
|
@ -368,13 +415,8 @@ int aac_rx_init(struct aac_dev *dev)
|
|||
name = dev->name;
|
||||
|
||||
/*
|
||||
* Map in the registers from the adapter.
|
||||
* Check to see if the board panic'd while booting.
|
||||
*/
|
||||
if((dev->regs.rx = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
|
||||
{
|
||||
printk(KERN_WARNING "aacraid: unable to map i960.\n" );
|
||||
return -1;
|
||||
}
|
||||
/*
|
||||
* Check to see if the board failed any self tests.
|
||||
*/
|
||||
|
@ -426,6 +468,7 @@ int aac_rx_init(struct aac_dev *dev)
|
|||
dev->a_ops.adapter_notify = aac_rx_notify_adapter;
|
||||
dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
|
||||
dev->a_ops.adapter_check_health = aac_rx_check_health;
|
||||
dev->a_ops.adapter_send = aac_rx_send;
|
||||
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that we
|
||||
|
@ -437,15 +480,9 @@ int aac_rx_init(struct aac_dev *dev)
|
|||
|
||||
if (aac_init_adapter(dev) == NULL)
|
||||
goto error_irq;
|
||||
/*
|
||||
* Start any kernel threads needed
|
||||
*/
|
||||
dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
|
||||
if(dev->thread_pid < 0)
|
||||
{
|
||||
printk(KERN_ERR "aacraid: Unable to create rx thread.\n");
|
||||
goto error_kfree;
|
||||
}
|
||||
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
|
||||
|
@ -453,15 +490,11 @@ int aac_rx_init(struct aac_dev *dev)
|
|||
aac_rx_start_adapter(dev);
|
||||
return 0;
|
||||
|
||||
error_kfree:
|
||||
kfree(dev->queues);
|
||||
|
||||
error_irq:
|
||||
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
|
||||
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
|
||||
|
||||
error_iounmap:
|
||||
iounmap(dev->regs.rx);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -237,29 +237,16 @@ static void aac_sa_interrupt_adapter (struct aac_dev *dev)
|
|||
|
||||
static void aac_sa_start_adapter(struct aac_dev *dev)
|
||||
{
|
||||
u32 ret;
|
||||
struct aac_init *init;
|
||||
/*
|
||||
* Fill in the remaining pieces of the init.
|
||||
*/
|
||||
init = dev->init;
|
||||
init->HostElapsedSeconds = cpu_to_le32(get_seconds());
|
||||
|
||||
/*
|
||||
* Tell the adapter we are back and up and running so it will scan its command
|
||||
* queues and enable our interrupts
|
||||
*/
|
||||
dev->irq_mask = (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4);
|
||||
/*
|
||||
* First clear out all interrupts. Then enable the one's that
|
||||
* we can handle.
|
||||
*/
|
||||
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
|
||||
sa_writew(dev, SaDbCSR.PRICLEARIRQMASK, (PrintfReady | DOORBELL_1 | DOORBELL_2 | DOORBELL_3 | DOORBELL_4));
|
||||
/* We can only use a 32 bit address here */
|
||||
sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
|
||||
(u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0,
|
||||
&ret, NULL, NULL, NULL, NULL);
|
||||
NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -313,15 +300,6 @@ int aac_sa_init(struct aac_dev *dev)
|
|||
instance = dev->id;
|
||||
name = dev->name;
|
||||
|
||||
/*
|
||||
* Map in the registers from the adapter.
|
||||
*/
|
||||
|
||||
if((dev->regs.sa = ioremap((unsigned long)dev->scsi_host_ptr->base, 8192))==NULL)
|
||||
{
|
||||
printk(KERN_WARNING "aacraid: unable to map ARM.\n" );
|
||||
goto error_iounmap;
|
||||
}
|
||||
/*
|
||||
* Check to see if the board failed any self tests.
|
||||
*/
|
||||
|
@ -377,15 +355,6 @@ int aac_sa_init(struct aac_dev *dev)
|
|||
if(aac_init_adapter(dev) == NULL)
|
||||
goto error_irq;
|
||||
|
||||
/*
|
||||
* Start any kernel threads needed
|
||||
*/
|
||||
dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0);
|
||||
if (dev->thread_pid < 0) {
|
||||
printk(KERN_ERR "aacraid: Unable to create command thread.\n");
|
||||
goto error_kfree;
|
||||
}
|
||||
|
||||
/*
|
||||
* Tell the adapter that all is configure, and it can start
|
||||
* accepting requests
|
||||
|
@ -393,16 +362,11 @@ int aac_sa_init(struct aac_dev *dev)
|
|||
aac_sa_start_adapter(dev);
|
||||
return 0;
|
||||
|
||||
|
||||
error_kfree:
|
||||
kfree(dev->queues);
|
||||
|
||||
error_irq:
|
||||
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
|
||||
free_irq(dev->scsi_host_ptr->irq, (void *)dev);
|
||||
|
||||
error_iounmap:
|
||||
iounmap(dev->regs.sa);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue