[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:
committed by
James Bottomley
parent
38a9a621ab
commit
8e0c5ebde8
@@ -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
|
||||||
-------------------------
|
-------------------------
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
*/
|
*/
|
||||||
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)
|
|||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
|
|
||||||
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 {
|
|||||||
#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
|
|||||||
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 {
|
|||||||
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 {
|
|||||||
#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 {
|
|||||||
#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 {
|
|||||||
#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
|
|||||||
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
|
|||||||
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
|
|||||||
/*
|
/*
|
||||||
* 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
|
|||||||
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
|
|||||||
#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);
|
|||||||
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
|
|||||||
}
|
}
|
||||||
|
|
||||||
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)
|
|||||||
- 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)
|
|||||||
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
|
|||||||
|
|
||||||
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
|
|||||||
* 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
|
|||||||
|
|
||||||
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
|
|||||||
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);
|
||||||
|
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.
|
* 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.
|
* 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)
|
|||||||
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)
|
|||||||
* 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)
|
|||||||
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)
|
|||||||
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,
|
|||||||
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,
|
|||||||
|
|
||||||
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)
|
|||||||
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 @@
|
|||||||
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) {
|
} else {
|
||||||
rkt_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
|
unsigned long bellbits;
|
||||||
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
|
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;
|
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
|
* 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,
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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 @@
|
|||||||
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) {
|
} else {
|
||||||
rx_writel(dev, MUnit.ODR, DoorBellAdapterNormCmdReady);
|
unsigned long bellbits;
|
||||||
aac_command_normal(&dev->queues->queue[HostNormCmdQueue]);
|
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;
|
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
|
* 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,
|
|||||||
/*
|
/*
|
||||||
* 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
|||||||
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;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user