Commit afd7d9c5 authored by James Bottomley's avatar James Bottomley Committed by James Bottomley

Update aacraid to last drop on 2.4 from Alan Cox

parent fecb256b
# Adaptec aacraid
obj-$(CONFIG_SCSI_AACRAID) := aacraid.o EXTRA_CFLAGS += -I$(TOPDIR)/drivers/scsi
aacraid-objs := linit.o aachba.o commctrl.o comminit.o commsup.o \
O_TARGET := aacraid.o
obj-m := $(O_TARGET)
obj-y := linit.o aachba.o commctrl.o comminit.o commsup.o \
dpcsup.o rx.o sa.o dpcsup.o rx.o sa.o
EXTRA_CFLAGS := -Idrivers/scsi include $(TOPDIR)/Rules.make
...@@ -18,6 +18,12 @@ Supported Cards/Chipsets ...@@ -18,6 +18,12 @@ Supported Cards/Chipsets
ADAPTEC 2120S ADAPTEC 2120S
ADAPTEC 2200S ADAPTEC 2200S
ADAPTEC 5400S ADAPTEC 5400S
Legend S220
Legend S230
Adaptec 3230S
Adaptec 3240S
ASR-2020S PCI-X
AAR-2410SA SATA
People People
------------------------- -------------------------
...@@ -28,6 +34,9 @@ Deanna Bonds <deanna_bonds@adaptec.com> (non-DASD support, PAE fibs and 64 bit, ...@@ -28,6 +34,9 @@ Deanna Bonds <deanna_bonds@adaptec.com> (non-DASD support, PAE fibs and 64 bit,
added new ioctls, changed scsi interface to use new error handler, added new ioctls, changed scsi interface to use new error handler,
increased the number of fibs and outstanding commands to a container) increased the number of fibs and outstanding commands to a container)
(fixed 64bit and 64G memory model, changed confusing naming convention
where fibs that go to the hardware are consistently called hw_fibs and
not just fibs like the name of the driver tracking structure)
Original Driver Original Driver
------------------------- -------------------------
Adaptec Unix OEM Product Group Adaptec Unix OEM Product Group
......
This diff is collapsed.
This diff is collapsed.
...@@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void *arg) ...@@ -63,7 +63,7 @@ static int ioctl_send_fib(struct aac_dev * dev, void *arg)
if(fibptr == NULL) if(fibptr == NULL)
return -ENOMEM; return -ENOMEM;
kfib = fibptr->fib; kfib = fibptr->hw_fib;
/* /*
* First copy in the header so that we can check the size field. * First copy in the header so that we can check the size field.
*/ */
...@@ -150,7 +150,7 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -150,7 +150,7 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg)
* the list to 0. * the list to 0.
*/ */
fibctx->count = 0; fibctx->count = 0;
INIT_LIST_HEAD(&fibctx->fibs); AAC_INIT_LIST_HEAD(&fibctx->hw_fib_list);
fibctx->jiffies = jiffies/HZ; fibctx->jiffies = jiffies/HZ;
/* /*
* Now add this context onto the adapter's * Now add this context onto the adapter's
...@@ -181,7 +181,7 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -181,7 +181,7 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg)
{ {
struct fib_ioctl f; struct fib_ioctl f;
struct aac_fib_context *fibctx, *aifcp; struct aac_fib_context *fibctx, *aifcp;
struct hw_fib * fib; struct hw_fib * hw_fib;
int status; int status;
struct list_head * entry; struct list_head * entry;
int found; int found;
...@@ -224,25 +224,25 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -224,25 +224,25 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg)
* -EAGAIN * -EAGAIN
*/ */
return_fib: return_fib:
if (!list_empty(&fibctx->fibs)) { if (!aac_list_empty(&fibctx->hw_fib_list)) {
struct list_head * entry; struct aac_list_head * entry;
/* /*
* Pull the next fib from the fibs * Pull the next fib from the fibs
*/ */
entry = fibctx->fibs.next; entry = (struct aac_list_head*)(ulong)fibctx->hw_fib_list.next;
list_del(entry); aac_list_del(entry);
fib = list_entry(entry, struct hw_fib, header.FibLinks); hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks);
fibctx->count--; fibctx->count--;
spin_unlock_irqrestore(&dev->fib_lock, flags); spin_unlock_irqrestore(&dev->fib_lock, flags);
if (copy_to_user(f.fib, fib, sizeof(struct hw_fib))) { if (copy_to_user(f.fib, hw_fib, sizeof(struct hw_fib))) {
kfree(fib); kfree(hw_fib);
return -EFAULT; return -EFAULT;
} }
/* /*
* Free the space occupied by this copy of the fib. * Free the space occupied by this copy of the fib.
*/ */
kfree(fib); kfree(hw_fib);
status = 0; status = 0;
fibctx->jiffies = jiffies/HZ; fibctx->jiffies = jiffies/HZ;
} else { } else {
...@@ -264,24 +264,24 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -264,24 +264,24 @@ static int next_getadapter_fib(struct aac_dev * dev, void *arg)
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)
{ {
struct hw_fib *fib; struct hw_fib *hw_fib;
/* /*
* First free any FIBs that have not been consumed. * First free any FIBs that have not been consumed.
*/ */
while (!list_empty(&fibctx->fibs)) { while (!aac_list_empty(&fibctx->hw_fib_list)) {
struct list_head * entry; struct aac_list_head * entry;
/* /*
* Pull the next fib from the fibs * Pull the next fib from the fibs
*/ */
entry = fibctx->fibs.next; entry = (struct aac_list_head*)(ulong)(fibctx->hw_fib_list.next);
list_del(entry); aac_list_del(entry);
fib = list_entry(entry, struct hw_fib, header.FibLinks); hw_fib = aac_list_entry(entry, struct hw_fib, header.FibLinks);
fibctx->count--; fibctx->count--;
/* /*
* Free the space occupied by this copy of the fib. * Free the space occupied by this copy of the fib.
*/ */
kfree(fib); kfree(hw_fib);
} }
/* /*
* Remove the Context from the AdapterFibContext List * Remove the Context from the AdapterFibContext List
...@@ -372,6 +372,204 @@ static int check_revision(struct aac_dev *dev, void *arg) ...@@ -372,6 +372,204 @@ static int check_revision(struct aac_dev *dev, void *arg)
return 0; return 0;
} }
/**
*
* aac_send_raw_scb
*
*/
int aac_send_raw_srb(struct aac_dev* dev, void* arg)
{
struct fib* srbfib;
int status;
struct aac_srb *srbcmd;
struct aac_srb *user_srb = arg;
struct aac_srb_reply* user_reply;
struct aac_srb_reply* reply;
u32 fibsize = 0;
u32 flags = 0;
s32 rcode = 0;
u32 data_dir;
ulong sg_user[32];
ulong sg_list[32];
u32 sg_indx = 0;
u32 byte_count = 0;
u32 actual_fibsize = 0;
int i;
if (!capable(CAP_SYS_ADMIN)){
printk(KERN_DEBUG"aacraid: No permission to send raw srb\n");
return -EPERM;
}
/*
* Allocate and initialize a Fib then setup a BlockWrite command
*/
if (!(srbfib = fib_alloc(dev))) {
return -1;
}
fib_init(srbfib);
srbcmd = (struct aac_srb*) fib_data(srbfib);
if(copy_from_user((void*)&fibsize, (void*)&user_srb->count,sizeof(u32))){
printk(KERN_DEBUG"aacraid: Could not copy data size from user\n");
rcode = -EFAULT;
goto cleanup;
}
if(copy_from_user(srbcmd, user_srb,fibsize)){
printk(KERN_DEBUG"aacraid: Could not copy srb from user\n");
rcode = -EFAULT;
goto cleanup;
}
user_reply = arg+fibsize;
flags = srbcmd->flags;
// Fix up srb for endian and force some values
srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this
srbcmd->channel = cpu_to_le32(srbcmd->channel);
srbcmd->target = cpu_to_le32(srbcmd->target);
srbcmd->lun = cpu_to_le32(srbcmd->lun);
srbcmd->flags = cpu_to_le32(srbcmd->flags);
srbcmd->timeout = cpu_to_le32(srbcmd->timeout);
srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size);
switch(srbcmd->flags){
case SRB_DataOut:
data_dir = SCSI_DATA_WRITE;
break;
case (SRB_DataIn | SRB_DataOut):
data_dir = SCSI_DATA_UNKNOWN;
break;
case SRB_DataIn:
data_dir = SCSI_DATA_READ;
break;
default:
data_dir = SCSI_DATA_NONE;
}
if( dev->pae_support ==1 ) {
struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
byte_count = 0;
// This should also catch if user used the 32 bit sgmap
actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry64));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
rcode = -EINVAL;
goto cleanup;
}
for (i = 0; i < psg->count; i++) {
dma_addr_t addr;
u64 le_addr;
void* p;
p = kmalloc(psg->sg[i].count,GFP_KERNEL|__GFP_DMA);
if(p == 0) {
printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
psg->sg[i].count,i,psg->count);
rcode = -ENOMEM;
goto cleanup;
}
sg_user[i] = (ulong)psg->sg[i].addr;
sg_list[i] = (ulong)p; // save so we can clean up later
sg_indx = i;
if( flags & SRB_DataOut ){
if(copy_from_user(p,psg->sg[i].addr,psg->sg[i].count)){
printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n");
rcode = -EFAULT;
goto cleanup;
}
}
addr = pci_map_single(dev->pdev, p, psg->sg[i].count, scsi_to_pci_dma_dir(data_dir));
le_addr = cpu_to_le64(addr);
psg->sg[i].addr[1] = (u32)(le_addr>>32);
psg->sg[i].addr[0] = (u32)(le_addr & 0xffffffff);
psg->sg[i].count = cpu_to_le32(psg->sg[i].count);
byte_count += psg->sg[i].count;
}
srbcmd->count = cpu_to_le32(byte_count);
status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,0,0);
} else {
struct sgmap* psg = &srbcmd->sg;
byte_count = 0;
actual_fibsize = sizeof (struct aac_srb) + (((srbcmd->sg.count & 0xff) - 1) * sizeof (struct sgentry));
if(actual_fibsize != fibsize){ // User made a mistake - should not continue
printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
rcode = -EINVAL;
goto cleanup;
}
for (i = 0; i < psg->count; i++) {
dma_addr_t addr;
void* p;
p = kmalloc(psg->sg[i].count,GFP_KERNEL);
if(p == 0) {
printk(KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
psg->sg[i].count,i,psg->count);
rcode = -ENOMEM;
goto cleanup;
}
sg_user[i] = (ulong)(psg->sg[i].addr);
sg_list[i] = (ulong)p; // save so we can clean up later
sg_indx = i;
if( flags & SRB_DataOut ){
if(copy_from_user((void*)p,(void*)(ulong)(psg->sg[i].addr),psg->sg[i].count)){
printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n");
rcode = -EFAULT;
goto cleanup;
}
}
addr = pci_map_single(dev->pdev, p, psg->sg[i].count, scsi_to_pci_dma_dir(data_dir));
psg->sg[i].addr = cpu_to_le32(addr);
psg->sg[i].count = cpu_to_le32(psg->sg[i].count);
byte_count += psg->sg[i].count;
}
srbcmd->count = cpu_to_le32(byte_count);
status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, 0, 0);
}
if (status != 0){
printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n");
rcode = -1;
goto cleanup;
}
if( flags & SRB_DataIn ) {
for(i = 0 ; i <= sg_indx; i++){
if(copy_to_user((void*)(sg_user[i]),(void*)(sg_list[i]),le32_to_cpu(srbcmd->sg.sg[i].count))){
printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n");
rcode = -EFAULT;
goto cleanup;
}
}
}
reply = (struct aac_srb_reply *) fib_data(srbfib);
if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){
printk(KERN_DEBUG"aacraid: Could not copy reply to user\n");
rcode = -EFAULT;
goto cleanup;
}
cleanup:
for(i=0; i <= sg_indx; i++){
kfree((void*)sg_list[i]);
}
fib_complete(srbfib);
fib_free(srbfib);
return rcode;
}
struct aac_pci_info { struct aac_pci_info {
u32 bus; u32 bus;
...@@ -386,8 +584,10 @@ int aac_get_pci_info(struct aac_dev* dev, void* arg) ...@@ -386,8 +584,10 @@ int aac_get_pci_info(struct aac_dev* dev, void* arg)
pci_info.bus = dev->pdev->bus->number; pci_info.bus = dev->pdev->bus->number;
pci_info.slot = PCI_SLOT(dev->pdev->devfn); pci_info.slot = PCI_SLOT(dev->pdev->devfn);
if(copy_to_user( arg, (void*)&pci_info, sizeof(struct aac_pci_info))) if(copy_to_user( arg, (void*)&pci_info, sizeof(struct aac_pci_info))){
printk(KERN_DEBUG "aacraid: Could not copy pci info\n");
return -EFAULT; return -EFAULT;
}
return 0; return 0;
} }
...@@ -420,6 +620,9 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg) ...@@ -420,6 +620,9 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg)
case FSACTL_CLOSE_GET_ADAPTER_FIB: case FSACTL_CLOSE_GET_ADAPTER_FIB:
status = close_getadapter_fib(dev, arg); status = close_getadapter_fib(dev, arg);
break; break;
case FSACTL_SEND_RAW_SRB:
status = aac_send_raw_srb(dev,arg);
break;
case FSACTL_GET_PCI_INFO: case FSACTL_GET_PCI_INFO:
status = aac_get_pci_info(dev,arg); status = aac_get_pci_info(dev,arg);
break; break;
......
...@@ -39,6 +39,7 @@ ...@@ -39,6 +39,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/blk.h> #include <linux/blk.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/mm.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include "scsi.h" #include "scsi.h"
#include "hosts.h" #include "hosts.h"
...@@ -58,10 +59,11 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -58,10 +59,11 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
struct aac_init *init; struct aac_init *init;
dma_addr_t phys; dma_addr_t phys;
/* FIXME: Adaptec add 128 bytes to this value - WHY ?? */
size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz; size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz;
base = pci_alloc_consistent(dev->pdev, size, &phys); base = pci_alloc_consistent(dev->pdev, size, &phys);
if(base == NULL) if(base == NULL)
{ {
printk(KERN_ERR "aacraid: unable to create mapping.\n"); printk(KERN_ERR "aacraid: unable to create mapping.\n");
...@@ -74,14 +76,6 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -74,14 +76,6 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
dev->init = (struct aac_init *)(base + fibsize); dev->init = (struct aac_init *)(base + fibsize);
dev->init_pa = phys + fibsize; dev->init_pa = phys + fibsize;
/*
* Cache the upper bits of the virtual mapping for 64bit boxes
* FIXME: this crap should be rewritten
*/
#if BITS_PER_LONG >= 64
dev->fib_base_va = ((ulong)base & 0xffffffff00000000);
#endif
init = dev->init; init = dev->init;
init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION); init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION);
...@@ -92,16 +86,19 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -92,16 +86,19 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
* Adapter Fibs are the first thing allocated so that they * Adapter Fibs are the first thing allocated so that they
* start page aligned * start page aligned
*/ */
init->AdapterFibsVirtualAddress = cpu_to_le32((u32)base); dev->fib_base_va = (ulong)base;
init->AdapterFibsPhysicalAddress = cpu_to_le32(phys);
init->AdapterFibsVirtualAddress = cpu_to_le32((u32)(ulong)base);
init->AdapterFibsPhysicalAddress = cpu_to_le32((u32)phys);
init->AdapterFibsSize = cpu_to_le32(fibsize); init->AdapterFibsSize = cpu_to_le32(fibsize);
init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib)); init->AdapterFibAlign = cpu_to_le32(sizeof(struct hw_fib));
init->HostPhysMemPages = cpu_to_le32(num_physpages); // number of 4k pages of host physical memory
/* /*
* Increment the base address by the amount already used * Increment the base address by the amount already used
*/ */
base = base + fibsize + sizeof(struct aac_init); base = base + fibsize + sizeof(struct aac_init);
phys = phys + fibsize + sizeof(struct aac_init); phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init));
/* /*
* Align the beginning of Headers to commalign * Align the beginning of Headers to commalign
*/ */
...@@ -111,8 +108,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co ...@@ -111,8 +108,8 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
/* /*
* Fill in addresses of the Comm Area Headers and Queues * Fill in addresses of the Comm Area Headers and Queues
*/ */
*commaddr = (unsigned long *)base; *commaddr = base;
init->CommHeaderAddress = cpu_to_le32(phys); init->CommHeaderAddress = cpu_to_le32((u32)phys);
/* /*
* Increment the base address by the size of the CommArea * Increment the base address by the size of the CommArea
*/ */
...@@ -134,14 +131,14 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem, ...@@ -134,14 +131,14 @@ static void aac_queue_init(struct aac_dev * dev, struct aac_queue * q, u32 *mem,
q->dev = dev; q->dev = dev;
INIT_LIST_HEAD(&q->pendingq); INIT_LIST_HEAD(&q->pendingq);
init_waitqueue_head(&q->cmdready); init_waitqueue_head(&q->cmdready);
INIT_LIST_HEAD(&q->cmdq); AAC_INIT_LIST_HEAD(&q->cmdq);
init_waitqueue_head(&q->qfull); init_waitqueue_head(&q->qfull);
spin_lock_init(&q->lockdata); spin_lock_init(&q->lockdata);
q->lock = &q->lockdata; q->lock = &q->lockdata;
q->headers.producer = mem; q->headers.producer = mem;
q->headers.consumer = mem+1; q->headers.consumer = mem+1;
*q->headers.producer = cpu_to_le32(qsize); *(q->headers.producer) = cpu_to_le32(qsize);
*q->headers.consumer = cpu_to_le32(qsize); *(q->headers.consumer) = cpu_to_le32(qsize);
q->entries = qsize; q->entries = qsize;
} }
...@@ -210,7 +207,7 @@ int aac_detach(struct aac_dev *detach) ...@@ -210,7 +207,7 @@ int aac_detach(struct aac_dev *detach)
/** /**
* aac_comm_init - Initialise FSA data structures * aac_comm_init - Initialise FSA data structures
* @dev: Adapter to initialise * @dev: Adapter to intialise
* *
* Initializes the data structures that are required for the FSA commuication * Initializes the data structures that are required for the FSA commuication
* interface to operate. * interface to operate.
...@@ -227,7 +224,6 @@ int aac_comm_init(struct aac_dev * dev) ...@@ -227,7 +224,6 @@ int aac_comm_init(struct aac_dev * dev)
struct aac_entry * queues; struct aac_entry * queues;
unsigned long size; unsigned long size;
struct aac_queue_block * comm = dev->queues; struct aac_queue_block * comm = dev->queues;
/* /*
* Now allocate and initialize the zone structures used as our * Now allocate and initialize the zone structures used as our
* pool of FIB context records. The size of the zone is based * pool of FIB context records. The size of the zone is based
...@@ -246,9 +242,9 @@ int aac_comm_init(struct aac_dev * dev) ...@@ -246,9 +242,9 @@ int aac_comm_init(struct aac_dev * dev)
if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT)) if (!aac_alloc_comm(dev, (void * *)&headers, size, QUEUE_ALIGNMENT))
return -ENOMEM; return -ENOMEM;
queues = (struct aac_entry *)((unsigned char *)headers + hdrsize); queues = (struct aac_entry *)(((ulong)headers) + hdrsize);
/* Adapter to Host normal proirity Command queue */ /* Adapter to Host normal priority Command queue */
comm->queue[HostNormCmdQueue].base = queues; comm->queue[HostNormCmdQueue].base = queues;
aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES); aac_queue_init(dev, &comm->queue[HostNormCmdQueue], headers, HOST_NORM_CMD_ENTRIES);
queues += HOST_NORM_CMD_ENTRIES; queues += HOST_NORM_CMD_ENTRIES;
...@@ -278,7 +274,6 @@ int aac_comm_init(struct aac_dev * dev) ...@@ -278,7 +274,6 @@ int aac_comm_init(struct aac_dev * dev)
/* adapter to host normal priority response queue */ /* adapter to host normal priority response queue */
comm->queue[HostNormRespQueue].base = queues; comm->queue[HostNormRespQueue].base = queues;
aac_queue_init(dev, &comm->queue[HostNormRespQueue], headers, HOST_NORM_RESP_ENTRIES); aac_queue_init(dev, &comm->queue[HostNormRespQueue], headers, HOST_NORM_RESP_ENTRIES);
queues += HOST_NORM_RESP_ENTRIES; queues += HOST_NORM_RESP_ENTRIES;
headers += 2; headers += 2;
...@@ -313,6 +308,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) ...@@ -313,6 +308,7 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
/* /*
* Ok now init the communication subsystem * Ok now init the communication subsystem
*/ */
dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL); dev->queues = (struct aac_queue_block *) kmalloc(sizeof(struct aac_queue_block), GFP_KERNEL);
if (dev->queues == NULL) { if (dev->queues == NULL) {
printk(KERN_ERR "Error could not allocate comm region.\n"); printk(KERN_ERR "Error could not allocate comm region.\n");
...@@ -320,13 +316,17 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev) ...@@ -320,13 +316,17 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
} }
memset(dev->queues, 0, sizeof(struct aac_queue_block)); memset(dev->queues, 0, sizeof(struct aac_queue_block));
if (aac_comm_init(dev)<0) if (aac_comm_init(dev)<0){
kfree(dev->queues);
return NULL; return NULL;
}
/* /*
* Initialize the list of fibs * Initialize the list of fibs
*/ */
if(fib_setup(dev)<0) if(fib_setup(dev)<0){
kfree(dev->queues);
return NULL; return NULL;
}
INIT_LIST_HEAD(&dev->fib_list); INIT_LIST_HEAD(&dev->fib_list);
init_completion(&dev->aif_completion); init_completion(&dev->aif_completion);
......
This diff is collapsed.
/*
* Adaptec AAC series RAID controller driver
* (c) Copyright 2001 Red Hat Inc. <alan@redhat.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
*
*/
/*
* This file is for backwards compatibility with older kernel versions
*/
#include <linux/version.h>
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,4,11)
#include <linux/blk.h>
static inline unsigned int block_size(kdev_t dev)
{
int retval = BLOCK_SIZE;
int major = MAJOR(dev);
if (blksize_size[major]) {
int minor = MINOR(dev);
if (blksize_size[major][minor])
retval = blksize_size[major][minor];
}
return retval;
}
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,7)
#ifndef COMPLETION_INITIALIZER
#include <linux/wait.h>
struct completion {
unsigned int done;
wait_queue_head_t wait;
};
#define COMPLETION_INITIALIZER(work) \
{ 0, __WAIT_QUEUE_HEAD_INITIALIZER((work).wait) }
#define DECLARE_COMPLETION(work) \
struct completion work = COMPLETION_INITIALIZER(work)
#define INIT_COMPLETION(x) ((x).done = 0)
static inline void init_completion(struct completion *x)
{
x->done = 0;
init_waitqueue_head(&x->wait);
}
#endif
#ifndef complete_and_exit
static inline void complete_and_exit(struct completion *comp, long code)
{
/*
if (comp)
complete(comp);
do_exit(code);
*/
}
#endif
#endif
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2,4,2)
static inline void scsi_set_pci_device(struct Scsi_Host *SHpnt,
struct pci_dev *pdev)
{
// SHpnt->pci_dev = pdev;
}
static inline void wait_for_completion(struct completion *x)
{
spin_lock_irq(&x->wait.lock);
if (!x->done) {
DECLARE_WAITQUEUE(wait, current);
wait.flags |= WQ_FLAG_EXCLUSIVE;
__add_wait_queue_tail(&x->wait, &wait);
do {
__set_current_state(TASK_UNINTERRUPTIBLE);
spin_unlock_irq(&x->wait.lock);
schedule();
spin_lock_irq(&x->wait.lock);
} while (!x->done);
__remove_wait_queue(&x->wait, &wait);
}
x->done--;
spin_unlock_irq(&x->wait.lock);
}
static inline int pci_set_dma_mask(struct pci_dev *dev, dma_addr_t mask)
{
dev->dma_mask = mask;
return 0;
}
#endif
...@@ -65,7 +65,6 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -65,7 +65,6 @@ unsigned int aac_response_normal(struct aac_queue * q)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(q->lock, flags); spin_lock_irqsave(q->lock, flags);
/* /*
* Keep pulling response QEs off the response queue and waking * Keep pulling response QEs off the response queue and waking
* up the waiters until there are no more QEs. We then return * up the waiters until there are no more QEs. We then return
...@@ -74,12 +73,14 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -74,12 +73,14 @@ unsigned int aac_response_normal(struct aac_queue * q)
*/ */
while(aac_consumer_get(dev, q, &entry)) while(aac_consumer_get(dev, q, &entry))
{ {
int fast; u32 fast ;
fast = (entry->addr & cpu_to_le32(0x01));
// fib = &dev->fibs[(entry->addr >> 1)];
// hwfib = fib->hw_fib;
hwfib = bus_to_virt(le32_to_cpu(entry->addr & cpu_to_le32(~0x01)));
fib = &dev->fibs[hwfib->header.SenderData];
fast = (int) (entry->addr & 0x01);
hwfib = addr2fib(entry->addr & ~0x01);
aac_consumer_free(dev, q, HostNormRespQueue); aac_consumer_free(dev, q, HostNormRespQueue);
fib = &dev->fibs[hwfib->header.SenderData];
/* /*
* Remove this fib from the Outstanding I/O queue. * Remove this fib from the Outstanding I/O queue.
* But only if it has not already been timed out. * But only if it has not already been timed out.
...@@ -93,6 +94,7 @@ unsigned int aac_response_normal(struct aac_queue * q) ...@@ -93,6 +94,7 @@ unsigned int aac_response_normal(struct aac_queue * q)
dev->queues->queue[AdapNormCmdQueue].numpending--; dev->queues->queue[AdapNormCmdQueue].numpending--;
} else { } else {
printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags); printk(KERN_WARNING "aacraid: FIB timeout (%x).\n", fib->flags);
printk(KERN_DEBUG"aacraid: hwfib=%p fib index=%i fib=%p\n",hwfib, hwfib->header.SenderData,fib);
continue; continue;
} }
spin_unlock_irqrestore(q->lock, flags); spin_unlock_irqrestore(q->lock, flags);
...@@ -171,11 +173,11 @@ unsigned int aac_command_normal(struct aac_queue *q) ...@@ -171,11 +173,11 @@ unsigned int aac_command_normal(struct aac_queue *q)
*/ */
while(aac_consumer_get(dev, q, &entry)) while(aac_consumer_get(dev, q, &entry))
{ {
struct hw_fib * fib; struct hw_fib * hw_fib;
fib = addr2fib(entry->addr); hw_fib = bus_to_virt(le32_to_cpu(entry->addr & cpu_to_le32(~0x01)));
if (dev->aif_thread) { if (dev->aif_thread) {
list_add_tail(&fib->header.FibLinks, &q->cmdq); aac_list_add_tail(&hw_fib->header.FibLinks, &q->cmdq);
aac_consumer_free(dev, q, HostNormCmdQueue); aac_consumer_free(dev, q, HostNormCmdQueue);
wake_up_interruptible(&q->cmdready); wake_up_interruptible(&q->cmdready);
} else { } else {
...@@ -185,13 +187,13 @@ unsigned int aac_command_normal(struct aac_queue *q) ...@@ -185,13 +187,13 @@ unsigned int aac_command_normal(struct aac_queue *q)
memset(&fibctx, 0, sizeof(struct fib)); memset(&fibctx, 0, sizeof(struct fib));
fibctx.type = FSAFS_NTC_FIB_CONTEXT; fibctx.type = FSAFS_NTC_FIB_CONTEXT;
fibctx.size = sizeof(struct fib); fibctx.size = sizeof(struct fib);
fibctx.fib = fib; fibctx.hw_fib = hw_fib;
fibctx.data = fib->data; fibctx.data = hw_fib->data;
fibctx.dev = dev; fibctx.dev = dev;
/* /*
* Set the status of this FIB * Set the status of this FIB
*/ */
*(u32 *)fib->data = cpu_to_le32(ST_OK); *(u32 *)hw_fib->data = cpu_to_le32(ST_OK);
fib_adapter_complete(&fibctx, sizeof(u32)); fib_adapter_complete(&fibctx, sizeof(u32));
spin_lock_irqsave(q->lock, flags); spin_lock_irqsave(q->lock, flags);
} }
......
This diff is collapsed.
...@@ -352,7 +352,7 @@ int aac_sa_init(struct aac_dev *dev, unsigned long devnum) ...@@ -352,7 +352,7 @@ int aac_sa_init(struct aac_dev *dev, unsigned long devnum)
* Wait for the adapter to be up and running. Wait up to 3 minutes. * Wait for the adapter to be up and running. Wait up to 3 minutes.
*/ */
while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) { while (!(sa_readl(dev, Mailbox7) & KERNEL_UP_AND_RUNNING)) {
if (time_after(start+180*HZ, jiffies)) { if (time_after(jiffies, start+180*HZ)) {
status = sa_readl(dev, Mailbox7) >> 16; status = sa_readl(dev, Mailbox7) >> 16;
printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status)); printk(KERN_WARNING "%s%d: adapter kernel failed to start, init status = %d.\n", name, instance, le32_to_cpu(status));
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