Commit 8e0c5ebd authored by Mark Haverkamp's avatar Mark Haverkamp Committed by James Bottomley

[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: default avatarMark Haverkamp <markh@osdl.org>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 38a9a621
...@@ -57,7 +57,7 @@ Deanna Bonds (non-DASD support, PAE fibs and 64 bit, ...@@ -57,7 +57,7 @@ Deanna Bonds (non-DASD support, PAE fibs and 64 bit,
(fixed 64bit and 64G memory model, changed confusing naming convention (fixed 64bit and 64G memory model, changed confusing naming convention
where fibs that go to the hardware are consistently called hw_fibs and where fibs that go to the hardware are consistently called hw_fibs and
not just fibs like the name of the driver tracking structure) 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 Original Driver
------------------------- -------------------------
......
o Testing o Testing
o More testing o More testing
o Drop irq_mask, basically unused
o I/O size increase o I/O size increase
...@@ -359,15 +359,6 @@ int aac_get_containers(struct aac_dev *dev) ...@@ -359,15 +359,6 @@ int aac_get_containers(struct aac_dev *dev)
return status; 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) static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
{ {
void *buf; void *buf;
...@@ -424,7 +415,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr) ...@@ -424,7 +415,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)
fib_complete(fibptr); fib_complete(fibptr);
fib_free(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) ...@@ -988,7 +979,7 @@ static void io_callback(void *context, struct fib * fibptr)
fib_complete(fibptr); fib_complete(fibptr);
fib_free(fibptr); fib_free(fibptr);
aac_io_done(scsicmd); scsicmd->scsi_done(scsicmd);
} }
static int aac_read(struct scsi_cmnd * scsicmd, int cid) static int aac_read(struct scsi_cmnd * scsicmd, int cid)
...@@ -1167,7 +1158,7 @@ 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 * For some reason, the Fib didn't queue, return QUEUE_FULL
*/ */
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_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_complete(cmd_fibcontext);
fib_free(cmd_fibcontext); fib_free(cmd_fibcontext);
return 0; return 0;
...@@ -1239,7 +1230,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) ...@@ -1239,7 +1230,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
*/ */
if (!(cmd_fibcontext = fib_alloc(dev))) { if (!(cmd_fibcontext = fib_alloc(dev))) {
scsicmd->result = DID_ERROR << 16; scsicmd->result = DID_ERROR << 16;
aac_io_done(scsicmd); scsicmd->scsi_done(scsicmd);
return 0; return 0;
} }
fib_init(cmd_fibcontext); fib_init(cmd_fibcontext);
...@@ -1336,7 +1327,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid) ...@@ -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 * For some reason, the Fib didn't queue, return QUEUE_FULL
*/ */
scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_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_complete(cmd_fibcontext);
fib_free(cmd_fibcontext); fib_free(cmd_fibcontext);
...@@ -1380,7 +1371,7 @@ static void synchronize_callback(void *context, struct fib *fibptr) ...@@ -1380,7 +1371,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)
fib_complete(fibptr); fib_complete(fibptr);
fib_free(fibptr); fib_free(fibptr);
aac_io_done(cmd); cmd->scsi_done(cmd);
} }
static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid) static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
...@@ -2097,7 +2088,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr) ...@@ -2097,7 +2088,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)
fib_complete(fibptr); fib_complete(fibptr);
fib_free(fibptr); fib_free(fibptr);
aac_io_done(scsicmd); scsicmd->scsi_done(scsicmd);
} }
/** /**
......
...@@ -481,6 +481,7 @@ enum aac_log_level { ...@@ -481,6 +481,7 @@ enum aac_log_level {
#define FSAFS_NTC_FIB_CONTEXT 0x030c #define FSAFS_NTC_FIB_CONTEXT 0x030c
struct aac_dev; struct aac_dev;
struct fib;
struct adapter_ops struct adapter_ops
{ {
...@@ -489,6 +490,7 @@ struct adapter_ops ...@@ -489,6 +490,7 @@ struct adapter_ops
void (*adapter_disable_int)(struct aac_dev *dev); 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_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_check_health)(struct aac_dev *dev);
int (*adapter_send)(struct fib * fib);
}; };
/* /*
...@@ -659,6 +661,10 @@ struct rx_mu_registers { ...@@ -659,6 +661,10 @@ struct rx_mu_registers {
Status Register */ Status Register */
__le32 OIMR; /* 1334h | 34h | Outbound Interrupt __le32 OIMR; /* 1334h | 34h | Outbound Interrupt
Mask Register */ 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 /* * Must access through ATU Inbound
Translation Window */ Translation Window */
}; };
...@@ -693,8 +699,8 @@ struct rx_inbound { ...@@ -693,8 +699,8 @@ struct rx_inbound {
#define OutboundDoorbellReg MUnit.ODR #define OutboundDoorbellReg MUnit.ODR
struct rx_registers { struct rx_registers {
struct rx_mu_registers MUnit; /* 1300h - 1334h */ struct rx_mu_registers MUnit; /* 1300h - 1344h */
__le32 reserved1[6]; /* 1338h - 134ch */ __le32 reserved1[2]; /* 1348h - 134ch */
struct rx_inbound IndexRegs; struct rx_inbound IndexRegs;
}; };
...@@ -711,8 +717,8 @@ struct rx_registers { ...@@ -711,8 +717,8 @@ struct rx_registers {
#define rkt_inbound rx_inbound #define rkt_inbound rx_inbound
struct rkt_registers { struct rkt_registers {
struct rkt_mu_registers MUnit; /* 1300h - 1334h */ struct rkt_mu_registers MUnit; /* 1300h - 1344h */
__le32 reserved1[1010]; /* 1338h - 22fch */ __le32 reserved1[1006]; /* 1348h - 22fch */
struct rkt_inbound IndexRegs; /* 2300h - */ struct rkt_inbound IndexRegs; /* 2300h - */
}; };
...@@ -721,8 +727,6 @@ struct rkt_registers { ...@@ -721,8 +727,6 @@ struct rkt_registers {
#define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR)) #define rkt_writeb(AEP, CSR, value) writeb(value, &((AEP)->regs.rkt->CSR))
#define rkt_writel(AEP, CSR, value) writel(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); typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
struct aac_fib_context { struct aac_fib_context {
...@@ -937,7 +941,6 @@ struct aac_dev ...@@ -937,7 +941,6 @@ struct aac_dev
const char *name; const char *name;
int id; int id;
u16 irq_mask;
/* /*
* negotiated FIB settings * negotiated FIB settings
*/ */
...@@ -972,6 +975,7 @@ struct aac_dev ...@@ -972,6 +975,7 @@ struct aac_dev
struct adapter_ops a_ops; struct adapter_ops a_ops;
unsigned long fsrev; /* Main driver's revision number */ 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 */ struct aac_init *init; /* Holds initialization info to communicate with adapter */
dma_addr_t init_pa; /* Holds physical address of the init struct */ dma_addr_t init_pa; /* Holds physical address of the init struct */
...@@ -992,6 +996,9 @@ struct aac_dev ...@@ -992,6 +996,9 @@ struct aac_dev
/* /*
* The following is the device specific extension. * The following is the device specific extension.
*/ */
#if (!defined(AAC_MIN_FOOTPRINT_SIZE))
# define AAC_MIN_FOOTPRINT_SIZE 8192
#endif
union union
{ {
struct sa_registers __iomem *sa; struct sa_registers __iomem *sa;
...@@ -1012,6 +1019,7 @@ struct aac_dev ...@@ -1012,6 +1019,7 @@ struct aac_dev
u8 nondasd_support; u8 nondasd_support;
u8 dac_support; u8 dac_support;
u8 raid_scsi_mode; u8 raid_scsi_mode;
u8 new_comm_interface;
/* macro side-effects BEWARE */ /* macro side-effects BEWARE */
# define raw_io_interface \ # define raw_io_interface \
init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4) init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
...@@ -1034,6 +1042,8 @@ struct aac_dev ...@@ -1034,6 +1042,8 @@ struct aac_dev
#define aac_adapter_check_health(dev) \ #define aac_adapter_check_health(dev) \
(dev)->a_ops.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) #define FIB_CONTEXT_FLAG_TIMED_OUT (0x00000001)
...@@ -1779,6 +1789,7 @@ int aac_rkt_init(struct aac_dev *dev); ...@@ -1779,6 +1789,7 @@ int aac_rkt_init(struct aac_dev *dev);
int aac_sa_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_response_normal(struct aac_queue * q);
unsigned int aac_command_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_command_thread(struct aac_dev * dev);
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx); int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
int fib_adapter_complete(struct fib * fibptr, unsigned short size); 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 ...@@ -116,6 +116,10 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
} }
init->InitFlags = 0; 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->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->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
init->MaxFibSize = cpu_to_le32(dev->max_fib_size); init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
...@@ -315,12 +319,33 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) ...@@ -315,12 +319,33 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
- sizeof(struct aac_fibhdr) - sizeof(struct aac_fibhdr)
- sizeof(struct aac_write) + sizeof(struct sgentry)) - sizeof(struct aac_write) + sizeof(struct sgentry))
/ sizeof(struct sgentry); / sizeof(struct sgentry);
dev->new_comm_interface = 0;
dev->raw_io_64 = 0; dev->raw_io_64 = 0;
if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES, if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) && 0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
(status[0] == 0x00000001)) { (status[0] == 0x00000001)) {
if (status[1] & AAC_OPT_NEW_COMM_64) if (status[1] & AAC_OPT_NEW_COMM_64)
dev->raw_io_64 = 1; 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, if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
......
...@@ -212,7 +212,7 @@ void fib_init(struct fib *fibptr) ...@@ -212,7 +212,7 @@ void fib_init(struct fib *fibptr)
hw_fib->header.StructType = FIB_MAGIC; hw_fib->header.StructType = FIB_MAGIC;
hw_fib->header.Size = cpu_to_le16(fibptr->dev->max_fib_size); 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.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.ReceiverFibAddress = cpu_to_le32(fibptr->hw_fib_pa);
hw_fib->header.SenderSize = cpu_to_le16(fibptr->dev->max_fib_size); 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 ...@@ -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) 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; struct aac_dev * dev = fibptr->dev;
unsigned long nointr = 0;
struct hw_fib * hw_fib = fibptr->hw_fib; struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_queue * q; struct aac_queue * q;
unsigned long flags = 0; unsigned long flags = 0;
...@@ -417,7 +415,7 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority ...@@ -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 * 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); hw_fib->header.SenderData = (u32)(fibptr - dev->fibs);
/* /*
* Set FIB state to indicate where it came from and if we want a * 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 ...@@ -456,10 +454,10 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
FIB_COUNTER_INCREMENT(aac_config.FibsSent); 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 "Fib contents:.\n"));
dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command)); dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command)));
dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState)); 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 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 " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr)); 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 ...@@ -469,14 +467,37 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
if(wait) if(wait)
spin_lock_irqsave(&fibptr->event_lock, flags); spin_lock_irqsave(&fibptr->event_lock, flags);
spin_lock_irqsave(q->lock, qflags); 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); list_add_tail(&fibptr->queue, &q->pendingq);
q->numpending++; q->numpending++;
*(q->headers.producer) = cpu_to_le32(index + 1); spin_unlock_irqrestore(q->lock, qflags);
spin_unlock_irqrestore(q->lock, qflags); while (aac_adapter_send(fibptr) != 0) {
if (!(nointr & aac_config.irq_mod)) if (--count == 0) {
aac_adapter_notify(dev, AdapNormCmdQueue); 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);
}
/* /*
* If the caller wanted us to wait for response wait now. * 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 ...@@ -492,7 +513,6 @@ int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority
* hardware failure has occurred. * hardware failure has occurred.
*/ */
unsigned long count = 36000000L; /* 3 minutes */ unsigned long count = 36000000L; /* 3 minutes */
unsigned long qflags;
while (down_trylock(&fibptr->event_wait)) { while (down_trylock(&fibptr->event_wait)) {
if (--count == 0) { if (--count == 0) {
spin_lock_irqsave(q->lock, qflags); spin_lock_irqsave(q->lock, qflags);
...@@ -621,12 +641,16 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) ...@@ -621,12 +641,16 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
unsigned long qflags; unsigned long qflags;
if (hw_fib->header.XferState == 0) { if (hw_fib->header.XferState == 0) {
if (dev->new_comm_interface)
kfree (hw_fib);
return 0; return 0;
} }
/* /*
* If we plan to do anything check the structure type first. * If we plan to do anything check the structure type first.
*/ */
if ( hw_fib->header.StructType != FIB_MAGIC ) { if ( hw_fib->header.StructType != FIB_MAGIC ) {
if (dev->new_comm_interface)
kfree (hw_fib);
return -EINVAL; return -EINVAL;
} }
/* /*
...@@ -637,21 +661,25 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size) ...@@ -637,21 +661,25 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size)
* send the completed cdb to the adapter. * send the completed cdb to the adapter.
*/ */
if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) { if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
u32 index; if (dev->new_comm_interface) {
hw_fib->header.XferState |= cpu_to_le32(HostProcessed); kfree (hw_fib);
if (size) { } else {
size += sizeof(struct aac_fibhdr); u32 index;
if (size > le16_to_cpu(hw_fib->header.SenderSize)) hw_fib->header.XferState |= cpu_to_le32(HostProcessed);
return -EMSGSIZE; if (size) {
hw_fib->header.Size = cpu_to_le16(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 else
{ {
......
...@@ -73,7 +73,7 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -73,7 +73,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
int fast; int fast;
u32 index = le32_to_cpu(entry->addr); u32 index = le32_to_cpu(entry->addr);
fast = index & 0x01; fast = index & 0x01;
fib = &dev->fibs[index >> 1]; fib = &dev->fibs[index >> 2];
hwfib = fib->hw_fib; hwfib = fib->hw_fib;
aac_consumer_free(dev, q, HostNormRespQueue); aac_consumer_free(dev, q, HostNormRespQueue);
...@@ -213,3 +213,116 @@ unsigned int aac_command_normal(struct aac_queue *q) ...@@ -213,3 +213,116 @@ unsigned int aac_command_normal(struct aac_queue *q)
spin_unlock_irqrestore(q->lock, flags); spin_unlock_irqrestore(q->lock, flags);
return 0; 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, ...@@ -788,8 +788,29 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
goto out_free_host; goto out_free_host;
spin_lock_init(&aac->fib_lock); 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; 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 * 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, ...@@ -866,10 +887,11 @@ static int __devinit aac_probe_one(struct pci_dev *pdev,
aac_send_shutdown(aac); aac_send_shutdown(aac);
aac_adapter_disable_int(aac); aac_adapter_disable_int(aac);
free_irq(pdev->irq, aac);
out_unmap:
fib_map_free(aac); fib_map_free(aac);
pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys); pci_free_consistent(aac->pdev, aac->comm_size, aac->comm_addr, aac->comm_phys);
kfree(aac->queues); kfree(aac->queues);
free_irq(pdev->irq, aac);
iounmap(aac->regs.sa); iounmap(aac->regs.sa);
out_free_fibs: out_free_fibs:
kfree(aac->fibs); kfree(aac->fibs);
...@@ -910,6 +932,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev) ...@@ -910,6 +932,7 @@ static void __devexit aac_remove_one(struct pci_dev *pdev)
iounmap(aac->regs.sa); iounmap(aac->regs.sa);
kfree(aac->fibs); kfree(aac->fibs);
kfree(aac->fsa_dev);
list_del(&aac->entry); list_del(&aac->entry);
scsi_host_put(shost); scsi_host_put(shost);
......
...@@ -49,40 +49,57 @@ ...@@ -49,40 +49,57 @@
static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t aac_rkt_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct aac_dev *dev = dev_id; struct aac_dev *dev = dev_id;
unsigned long bellbits;
u8 intstat, mask; if (dev->new_comm_interface) {
intstat = rkt_readb(dev, MUnit.OISR); u32 Index = rkt_readl(dev, MUnit.OutboundQueue);
/* if (Index == 0xFFFFFFFFL)
* Read mask and invert because drawbridge is reversed. Index = rkt_readl(dev, MUnit.OutboundQueue);
* This allows us to only service interrupts that have if (Index != 0xFFFFFFFFL) {
* been enabled. do {
*/ if (aac_intr_normal(dev, Index)) {
mask = ~(dev->OIMR); rkt_writel(dev, MUnit.OutboundQueue, Index);
/* Check to see if this is our interrupt. If it isn't just return */ rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
if (intstat & mask) }
{ Index = rkt_readl(dev, MUnit.OutboundQueue);
bellbits = rkt_readl(dev, OutboundDoorbellReg); } while (Index != 0xFFFFFFFFL);
if (bellbits & DoorBellPrintfReady) { return IRQ_HANDLED;
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]);
}
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) { } else {
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); unsigned long bellbits;
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); 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_HANDLED;
} }
return IRQ_NONE; return IRQ_NONE;
} }
...@@ -173,7 +190,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, ...@@ -173,7 +190,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
/* /*
* Restore interrupt mask even though we timed out * 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; return -ETIMEDOUT;
} }
/* /*
...@@ -196,7 +216,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command, ...@@ -196,7 +216,10 @@ static int rkt_sync_cmd(struct aac_dev *dev, u32 command,
/* /*
* Restore interrupt mask * 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; return 0;
} }
...@@ -268,15 +291,6 @@ static void aac_rkt_start_adapter(struct aac_dev *dev) ...@@ -268,15 +291,6 @@ static void aac_rkt_start_adapter(struct aac_dev *dev)
init = dev->init; init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 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 // We can only use a 32 bit address here
rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, rkt_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
...@@ -349,6 +363,39 @@ static int aac_rkt_check_health(struct aac_dev *dev) ...@@ -349,6 +363,39 @@ static int aac_rkt_check_health(struct aac_dev *dev)
return 0; 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 * aac_rkt_init - initialize an i960 based AAC card
* @dev: device to configure * @dev: device to configure
...@@ -369,13 +416,8 @@ int aac_rkt_init(struct aac_dev *dev) ...@@ -369,13 +416,8 @@ int aac_rkt_init(struct aac_dev *dev)
name = dev->name; 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. * Check to see if the board failed any self tests.
*/ */
...@@ -426,6 +468,7 @@ int aac_rkt_init(struct aac_dev *dev) ...@@ -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_notify = aac_rkt_notify_adapter;
dev->a_ops.adapter_sync_cmd = rkt_sync_cmd; dev->a_ops.adapter_sync_cmd = rkt_sync_cmd;
dev->a_ops.adapter_check_health = aac_rkt_check_health; 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 * First clear out all interrupts. Then enable the one's that we
...@@ -437,15 +480,24 @@ int aac_rkt_init(struct aac_dev *dev) ...@@ -437,15 +480,24 @@ int aac_rkt_init(struct aac_dev *dev)
if (aac_init_adapter(dev) == NULL) if (aac_init_adapter(dev) == NULL)
goto error_irq; goto error_irq;
/* if (dev->new_comm_interface) {
* Start any kernel threads needed /*
*/ * FIB Setup has already been done, but we can minimize the
dev->thread_pid = kernel_thread((int (*)(void *))aac_command_thread, dev, 0); * damage by at least ensuring the OS never issues more
if(dev->thread_pid < 0) * commands than we can handle. The Rocket adapters currently
{ * can only handle 246 commands and 8 AIFs at the same time,
printk(KERN_ERR "aacraid: Unable to create rkt thread.\n"); * and in fact do notify us accordingly if we negotiate the
goto error_kfree; * 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 * Tell the adapter that all is configured, and it can start
* accepting requests * accepting requests
...@@ -453,15 +505,11 @@ int aac_rkt_init(struct aac_dev *dev) ...@@ -453,15 +505,11 @@ int aac_rkt_init(struct aac_dev *dev)
aac_rkt_start_adapter(dev); aac_rkt_start_adapter(dev);
return 0; return 0;
error_kfree:
kfree(dev->queues);
error_irq: error_irq:
rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); rkt_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev); free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap: error_iounmap:
iounmap(dev->regs.rkt);
return -1; return -1;
} }
...@@ -49,40 +49,57 @@ ...@@ -49,40 +49,57 @@
static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs) static irqreturn_t aac_rx_intr(int irq, void *dev_id, struct pt_regs *regs)
{ {
struct aac_dev *dev = dev_id; struct aac_dev *dev = dev_id;
unsigned long bellbits;
u8 intstat, mask; dprintk((KERN_DEBUG "aac_rx_intr(%d,%p,%p)\n", irq, dev_id, regs));
intstat = rx_readb(dev, MUnit.OISR); if (dev->new_comm_interface) {
/* u32 Index = rx_readl(dev, MUnit.OutboundQueue);
* Read mask and invert because drawbridge is reversed. if (Index == 0xFFFFFFFFL)
* This allows us to only service interrupts that have Index = rx_readl(dev, MUnit.OutboundQueue);
* been enabled. if (Index != 0xFFFFFFFFL) {
*/ do {
mask = ~(dev->OIMR); if (aac_intr_normal(dev, Index)) {
/* Check to see if this is our interrupt. If it isn't just return */ rx_writel(dev, MUnit.OutboundQueue, Index);
if (intstat & mask) rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
{ }
bellbits = rx_readl(dev, OutboundDoorbellReg); Index = rx_readl(dev, MUnit.OutboundQueue);
if (bellbits & DoorBellPrintfReady) { } while (Index != 0xFFFFFFFFL);
aac_printf(dev, rx_readl(dev, IndexRegs.Mailbox[5])); return IRQ_HANDLED;
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) {
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) { } else {
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdNotFull); unsigned long bellbits;
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespNotFull); 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;
} }
return IRQ_HANDLED;
} }
return IRQ_NONE; return IRQ_NONE;
} }
...@@ -173,7 +190,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, ...@@ -173,7 +190,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/* /*
* Restore interrupt mask even though we timed out * 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; return -ETIMEDOUT;
} }
/* /*
...@@ -196,7 +216,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command, ...@@ -196,7 +216,10 @@ static int rx_sync_cmd(struct aac_dev *dev, u32 command,
/* /*
* Restore interrupt mask * 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; return 0;
} }
...@@ -267,15 +290,6 @@ static void aac_rx_start_adapter(struct aac_dev *dev) ...@@ -267,15 +290,6 @@ static void aac_rx_start_adapter(struct aac_dev *dev)
init = dev->init; init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 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 // We can only use a 32 bit address here
rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa, rx_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL); 0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
...@@ -348,6 +362,39 @@ static int aac_rx_check_health(struct aac_dev *dev) ...@@ -348,6 +362,39 @@ static int aac_rx_check_health(struct aac_dev *dev)
return 0; 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 * aac_rx_init - initialize an i960 based AAC card
* @dev: device to configure * @dev: device to configure
...@@ -368,13 +415,8 @@ int aac_rx_init(struct aac_dev *dev) ...@@ -368,13 +415,8 @@ int aac_rx_init(struct aac_dev *dev)
name = dev->name; 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. * Check to see if the board failed any self tests.
*/ */
...@@ -426,6 +468,7 @@ int aac_rx_init(struct aac_dev *dev) ...@@ -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_notify = aac_rx_notify_adapter;
dev->a_ops.adapter_sync_cmd = rx_sync_cmd; dev->a_ops.adapter_sync_cmd = rx_sync_cmd;
dev->a_ops.adapter_check_health = aac_rx_check_health; 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 * First clear out all interrupts. Then enable the one's that we
...@@ -437,15 +480,9 @@ int aac_rx_init(struct aac_dev *dev) ...@@ -437,15 +480,9 @@ int aac_rx_init(struct aac_dev *dev)
if (aac_init_adapter(dev) == NULL) if (aac_init_adapter(dev) == NULL)
goto error_irq; goto error_irq;
/* if (dev->new_comm_interface)
* Start any kernel threads needed rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xf7);
*/
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;
}
/* /*
* Tell the adapter that all is configured, and it can start * Tell the adapter that all is configured, and it can start
* accepting requests * accepting requests
...@@ -453,15 +490,11 @@ int aac_rx_init(struct aac_dev *dev) ...@@ -453,15 +490,11 @@ int aac_rx_init(struct aac_dev *dev)
aac_rx_start_adapter(dev); aac_rx_start_adapter(dev);
return 0; return 0;
error_kfree:
kfree(dev->queues);
error_irq: error_irq:
rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff); rx_writeb(dev, MUnit.OIMR, dev->OIMR = 0xff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev); free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap: error_iounmap:
iounmap(dev->regs.rx);
return -1; return -1;
} }
...@@ -237,29 +237,16 @@ static void aac_sa_interrupt_adapter (struct aac_dev *dev) ...@@ -237,29 +237,16 @@ static void aac_sa_interrupt_adapter (struct aac_dev *dev)
static void aac_sa_start_adapter(struct aac_dev *dev) static void aac_sa_start_adapter(struct aac_dev *dev)
{ {
u32 ret;
struct aac_init *init; struct aac_init *init;
/* /*
* Fill in the remaining pieces of the init. * Fill in the remaining pieces of the init.
*/ */
init = dev->init; init = dev->init;
init->HostElapsedSeconds = cpu_to_le32(get_seconds()); 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 */ /* We can only use a 32 bit address here */
sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, sa_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS,
(u32)(ulong)dev->init_pa, 0, 0, 0, 0, 0, (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) ...@@ -313,15 +300,6 @@ int aac_sa_init(struct aac_dev *dev)
instance = dev->id; instance = dev->id;
name = dev->name; 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. * Check to see if the board failed any self tests.
*/ */
...@@ -377,15 +355,6 @@ int aac_sa_init(struct aac_dev *dev) ...@@ -377,15 +355,6 @@ 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;
/*
* 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 * Tell the adapter that all is configure, and it can start
* accepting requests * accepting requests
...@@ -393,16 +362,11 @@ int aac_sa_init(struct aac_dev *dev) ...@@ -393,16 +362,11 @@ int aac_sa_init(struct aac_dev *dev)
aac_sa_start_adapter(dev); aac_sa_start_adapter(dev);
return 0; return 0;
error_kfree:
kfree(dev->queues);
error_irq: error_irq:
sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff); sa_writew(dev, SaDbCSR.PRISETIRQMASK, 0xffff);
free_irq(dev->scsi_host_ptr->irq, (void *)dev); free_irq(dev->scsi_host_ptr->irq, (void *)dev);
error_iounmap: error_iounmap:
iounmap(dev->regs.sa);
return -1; return -1;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment