* RE: [PATCH] aacraid changes for 2.4.24 kernel to add support of AMD64 (part 2)
@ 2004-02-13 22:37 Salyzyn, Mark
2004-02-13 23:04 ` Christoph Hellwig
0 siblings, 1 reply; 4+ messages in thread
From: Salyzyn, Mark @ 2004-02-13 22:37 UTC (permalink / raw)
To: Christoph Hellwig; +Cc: linux-scsi
Comments embedded
-----Original Message-----
From: Christoph Hellwig [mailto:hch@infradead.org]
Sent: Friday, February 13, 2004 4:59 PM
To: Salyzyn, Mark
Cc: linux-scsi
Subject: Re: [PATCH] aacraid changes for 2.4.24 kernel to add support of
AMD64 (part 2)
struct fib_ioctl
{
- char *fibctx;
- int wait;
- char *fib;
+ u32 fibctx;
+ s32 wait;
+#if (defined(__x86_64__))
+ u64 fib;
+#else
+ u32 fib;
+#endif
This is broken. If you really mean what you wrote just use
unsigned long, but if you want this API to actually work as
expected use the same value on all architectures.
[MGS] The ioctl that utilizes this structure detects if the caller is a
32 bit or a 64 bit application under the AMD64 environment, and tunes
itself to the size of the fib element as necessary. I opted to use the
redefinition of this structure as a means to simplify the split
personality code that utilizes this structure.
In a 32 bit environment, there is no need to detect if the caller is a
32 bit or a 64 bit application, so the smaller fib element is all that
is needed.
+ if (!dev || !dev->scsi_host_ptr) {
+ return;
+ }
+ for (device = dev->scsi_host_ptr->host_queue;
+ device != (Scsi_Device *)NULL;
+ device = device->next)
+ {
+ dprintk((KERN_INFO "aifd: device (%d,%d,%d,%d)?\n",
+ dev->scsi_host_ptr->host_no,
+ device->channel,
+ device->id,
+ device->lun));
+ if ((device->channel == CONTAINER_TO_CHANNEL(container))
+ && (device->id == CONTAINER_TO_ID(container))
+ && (device->lun == CONTAINER_TO_LUN(container))) {
+ busy |= device->access_count ||
dev->scsi_host_ptr->in_recovery;
+ if (busy == 0) {
+ device->removable = TRUE;
+ }
+ }
+ }
This gives you nice races again.
[MGS] Without any test of busy status at all, we run the *high* risk of
a panic resulting from a stack overflow. This code is here because of a
broken error recovery in the scsi layer resulting in infinite recursion
under some sensitive activities.
Fix the scsi layer, and this code can go away.
+ dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi));
+ for (entry = proc_scsi->subdir;
+ entry != (struct proc_dir_entry *)NULL;
+ entry = entry->next) {
+ dprintk(("\"%.*s\"[%d]=%x ", entry->namelen,
+ entry->name, entry->namelen, entry->low_ino));
+ if ((entry->low_ino != 0)
+ && (entry->namelen == 4)
+ && (memcmp ("scsi", entry->name, 4) == 0)) {
+ dprintk(("%p->write_proc=%p ", entry,
entry->write_proc));
+ if (entry->write_proc != (int (*)(struct
file *, const char *, unsigned long, void *))NULL) {
+ char buffer[80];
+ int length;
+ mm_segment_t fs;
+
+ sprintf (buffer,
+ "scsi %s-single-device %d %d
%d %d\n",
+ ((DeviceConfigNeeded ==
DELETE)
+ ? "remove"
+ : "add"),
+ dev->scsi_host_ptr->host_no,
+
CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container));
+ length = strlen (buffer);
+ dprintk((KERN_INFO
+ "echo %.*s >
/proc/scsi/scsi\n",
+ length-1,
+ buffer));
+//printk("echo %.*s > /proc/scsi/scsi\n", length-1, buffer);
+ fs = get_fs();
+ set_fs(get_ds());
+ length = entry->write_proc(
+ NULL, buffer, length, NULL);
+ set_fs(fs);
+ dprintk((KERN_INFO
+ "returns %d\n", length));
Stop it. The code is bogus that I wonder how you even dare to
post it.
[MGS] Ok, tell me how to rescan for a device? The RAID drivers cause
asynchronous device changes that need to be reported to the scsi layer.
The scan_scsis call is hidden, so we *must* use the proc write to get to
it.
The code may be bogus, but it works. If you have a means to rescan
devices in the current 2.4 scsi layer, I will take that as a valid
alternative. Otherwise Adaptec customers will need to reboot their
machine every time something significant happens with the array.
+#if (defined(__x86_64__))
+# include <asm-x86_64/ioctl32.h>
+ /* Cast the function, since sys_ioctl does not match */
+# define aac_ioctl32(x,y) register_ioctl32_conversion((x), \
+ (int(*)(unsigned int,unsigned int,unsigned long,struct file*))(y))
+# include <asm/uaccess.h>
+#endif
So why do the other drivers not need this?
[MGS] Not sure what you mean about other drivers? I have a series of
warning messages without the cast.
Or do you mean the arrangements for register_ioctl32_conversion? Because
other drivers do not have 32 bit applications calling a 64 bit ioctl for
RAID management functions. The current structure of the x86_64 port in
the 2.4 tree is to block 32 bit applications from calling the ioctl
without these arrangements.
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] aacraid changes for 2.4.24 kernel to add support of AMD64 (part 2)
2004-02-13 22:37 [PATCH] aacraid changes for 2.4.24 kernel to add support of AMD64 (part 2) Salyzyn, Mark
@ 2004-02-13 23:04 ` Christoph Hellwig
0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2004-02-13 23:04 UTC (permalink / raw)
To: Salyzyn, Mark; +Cc: linux-scsi
On Fri, Feb 13, 2004 at 05:37:44PM -0500, Salyzyn, Mark wrote:
> [MGS] The ioctl that utilizes this structure detects if the caller is a
> 32 bit or a 64 bit application under the AMD64 environment, and tunes
> itself to the size of the fib element as necessary. I opted to use the
> redefinition of this structure as a means to simplify the split
> personality code that utilizes this structure.
>
> In a 32 bit environment, there is no need to detect if the caller is a
> 32 bit or a 64 bit application, so the smaller fib element is all that
> is needed.
Well.. What about ia64 or ppc64 or mips64 or..? There's much
more than PCs out there.
> [MGS] Without any test of busy status at all, we run the *high* risk of
> a panic resulting from a stack overflow. This code is here because of a
> broken error recovery in the scsi layer resulting in infinite recursion
> under some sensitive activities.
You mean the thing rmk fixed? If that's still not in 2.4 it's
rather sad indeed.. If you mean something else please explain
it to the list, a patch would be even better.
> Fix the scsi layer, and this code can go away.
Some cooperation from vendors could also help ;-)
> [MGS] Ok, tell me how to rescan for a device? The RAID drivers cause
> asynchronous device changes that need to be reported to the scsi layer.
> The scan_scsis call is hidden, so we *must* use the proc write to get to
> it.
DO NOT DO IT. Even from userland. /proc/scsi/scsi's dubious
scan interface existing is more than bad enough and a _big_
mistake from the people writing the original linux scsi code.
But at least we canb blame it on those peopl brave enough.
But in addition top the rescan beeing bogus opening files from
kernelspace and writing to them is simply not allowed.
> Or do you mean the arrangements for register_ioctl32_conversion? Because
> other drivers do not have 32 bit applications calling a 64 bit ioctl for
> RAID management functions. The current structure of the x86_64 port in
> the 2.4 tree is to block 32 bit applications from calling the ioctl
> without these arrangements.
There's quite a lot of drivers using register_ioctl32_conversion
that don't seem to need it. But I don't have an x86-64 box so
don't ask me for details. It just looked more than strange..
^ permalink raw reply [flat|nested] 4+ messages in thread
* [PATCH] aacraid changes for 2.4.24 kernel to add support of AMD64 (part 2)
@ 2004-02-13 21:16 Salyzyn, Mark
2004-02-13 21:58 ` Christoph Hellwig
0 siblings, 1 reply; 4+ messages in thread
From: Salyzyn, Mark @ 2004-02-13 21:16 UTC (permalink / raw)
To: linux-scsi
[-- Attachment #1: Type: text/plain, Size: 554 bytes --]
This is part 2 to the following referenced patch.
Sincerely -- Mark Salyzyn
-----Original Message-----
From: Salyzyn, Mark
Sent: Friday, February 13, 2004 4:16 PM
To: 'linux-scsi'
Subject: [PATCH] aacraid changes for 2.4.24 kernel to add support of
AMD64 (part 1)
This first part of two forms a `big' patch to the aacraid driver adds
support for the AMD64 systems.
There is some side effect of this patch associated with bug fixes and
clean up that became apparent as a result of the 64 bit adjustments.
Sincerely -- Mark Salyzyn
[-- Attachment #2: aac_x86_64.patch.pt2 --]
[-- Type: application/octet-stream, Size: 48903 bytes --]
@@ -649,6 +657,7 @@
struct aac_fib_context {
s16 type; // used for verification of structure
s16 size;
+ u32 unique; // unique value representing this context
ulong jiffies; // used for cleanup - dmb changed to ulong
struct list_head next; // used to link context's into a linked list
struct semaphore wait_sem; // this is used to wait for the next fib to arrive.
@@ -664,7 +673,7 @@
u8 ro[MAXIMUM_NUM_CONTAINERS];
u8 locked[MAXIMUM_NUM_CONTAINERS];
u8 deleted[MAXIMUM_NUM_CONTAINERS];
- s32 devno[MAXIMUM_NUM_CONTAINERS];
+ char devname[MAXIMUM_NUM_CONTAINERS][8];
};
struct fib {
@@ -836,11 +845,14 @@
u32 aif_thread;
struct completion aif_completion;
struct aac_adapter_info adapter_info;
+ u32 DeviceContainerID;
+ u32 DeviceConfigWaitingOn;
+ int DeviceConfigNeeded;
/* These are in adapter info but they are in the io flow so
* lets break them out so we don't have to do an AND to check them
*/
u8 nondasd_support;
- u8 pae_support;
+ u8 dac_support;
u8 raid_scsi_mode;
};
@@ -1054,7 +1066,7 @@
{
u32 function;
u32 channel;
- u32 target;
+ u32 id;
u32 lun;
u32 timeout;
u32 flags;
@@ -1255,6 +1267,19 @@
u8 data[16];
};
+/**
+ * Convert capacity to cylinders
+ * accounting for the fact capacity could be a 64 bit value
+ *
+ */
+typedef unsigned long sector_t;
+
+static inline u32 cap_to_cyls(sector_t capacity, u32 divisor)
+{
+ capacity /= divisor;
+ return (u32)capacity;
+}
+
/*
* The following command is sent to shut down each container.
*/
@@ -1268,7 +1293,7 @@
{
s32 cnum;
s32 bus;
- s32 target;
+ s32 id;
s32 lun;
u32 valid;
u32 locked;
@@ -1285,9 +1310,13 @@
struct fib_ioctl
{
- char *fibctx;
- int wait;
- char *fib;
+ u32 fibctx;
+ s32 wait;
+#if (defined(__x86_64__))
+ u64 fib;
+#else
+ u32 fib;
+#endif
};
struct revision
@@ -1327,6 +1356,7 @@
#define FSACTL_MINIPORT_REV_CHECK CTL_CODE(2107, METHOD_BUFFERED)
#define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED)
#define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER)
+#define FSACTL_REGISTER_FIB_SEND CTL_CODE(2136, METHOD_BUFFERED)
struct aac_common
@@ -1424,8 +1454,14 @@
*/
#define AifCmdEventNotify 1 /* Notify of event */
+#define AifEnConfigChange 3 /* Adapter configuration change */
#define AifEnContainerChange 4 /* Container configuration change */
+#define AifEnDeviceFailure 5 /* SCSI device failed */
+#define AifEnAddContainer 15 /* A new array was created. */
+#define AifEnDeleteContainer 16 /* A container was deleted. */
#define AifCmdJobProgress 2 /* Progress report */
+#define AifJobCtrZero 101 /* Array Zero progress */
+#define AifJobStsSuccess 1 /* Job completes successfully */
#define AifCmdAPIReport 3 /* Report from other user of API */
#define AifCmdDriverNotify 4 /* Notify host driver of event */
#define AifDenMorphComplete 200 /* A morph operation completed */
@@ -1462,7 +1498,8 @@
void fib_init(struct fib * context);
void fib_dealloc(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
-int fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
+#define aac_fib_send fib_send
+int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
int aac_consumer_avail(struct aac_dev * dev, struct aac_queue * q);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
diff -u -P --recursive linux-2.4.24/drivers/scsi/aacraid/commctrl.c linux-2.4.24-2322/drivers/scsi/aacraid/commctrl.c
--- linux-2.4.24/drivers/scsi/aacraid/commctrl.c Mon Oct 20 10:43:26 2003
+++ linux-2.4.24-2322/drivers/scsi/aacraid/commctrl.c Fri Feb 13 11:48:51 2004
@@ -37,7 +37,7 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/completion.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
#include <asm/semaphore.h>
#include <asm/uaccess.h>
#include "scsi.h"
@@ -60,8 +60,9 @@
struct fib *fibptr;
fibptr = fib_alloc(dev);
- if(fibptr == NULL)
+ if(fibptr == NULL) {
return -ENOMEM;
+ }
kfib = fibptr->hw_fib;
/*
@@ -94,11 +95,12 @@
*/
kfib->header.XferState = 0;
} else {
- if (fib_send(kfib->header.Command, fibptr, le32_to_cpu(kfib->header.Size) , FsaNormal,
- 1, 1, NULL, NULL) != 0)
- {
+ int retval = fib_send(kfib->header.Command, fibptr,
+ le32_to_cpu(kfib->header.Size) , FsaNormal,
+ 1, 1, NULL, NULL);
+ if (retval != 0) {
fib_free(fibptr);
- return -EINVAL;
+ return retval;
}
if (fib_complete(fibptr) != 0) {
fib_free(fibptr);
@@ -132,15 +134,25 @@
{
struct aac_fib_context * fibctx;
int status;
- unsigned long flags;
fibctx = kmalloc(sizeof(struct aac_fib_context), GFP_KERNEL);
if (fibctx == NULL) {
status = -ENOMEM;
} else {
+ unsigned long flags;
+ struct list_head * entry;
+ struct aac_fib_context * context;
+
fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT;
fibctx->size = sizeof(struct aac_fib_context);
/*
+ * Yes yes, I know this could be an index, but we have a
+ * better guarantee of uniqueness for the locked loop below.
+ * Without the aid of a persistent history, this also helps
+ * reduce the chance that the opaque context would be reused.
+ */
+ fibctx->unique = (u32)((ulong)fibctx & 0xFFFFFFFF);
+ /*
* Initialize the mutex used to wait for the next AIF.
*/
init_MUTEX_LOCKED(&fibctx->wait_sem);
@@ -157,9 +169,21 @@
* AdapterFibContext list.
*/
spin_lock_irqsave(&dev->fib_lock, flags);
+ /* Ensure that we have a unique identifier */
+ entry = dev->fib_list.next;
+ while(entry != &dev->fib_list) {
+ context = list_entry(entry, struct aac_fib_context, next);
+ if (context->unique == fibctx->unique) {
+ /* Not unique (32 bits) */
+ fibctx->unique++;
+ entry = dev->fib_list.next;
+ } else {
+ entry = entry->next;
+ }
+ }
list_add_tail(&fibctx->next, &dev->fib_list);
spin_unlock_irqrestore(&dev->fib_lock, flags);
- if (copy_to_user(arg, &fibctx, sizeof(struct aac_fib_context *))) {
+ if (copy_to_user(arg, &fibctx->unique, sizeof(fibctx->unique))) {
status = -EFAULT;
} else {
status = 0;
@@ -180,19 +204,14 @@
static int next_getadapter_fib(struct aac_dev * dev, void *arg)
{
struct fib_ioctl f;
- struct aac_fib_context *fibctx, *aifcp;
+ struct aac_fib_context *fibctx;
struct fib * fib;
int status;
struct list_head * entry;
- int found;
unsigned long flags;
if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl)))
return -EFAULT;
- /*
- * Extract the AdapterFibContext from the Input parameters.
- */
- fibctx = (struct aac_fib_context *) f.fibctx;
/*
* Verify that the HANDLE passed in was a valid AdapterFibContext
@@ -200,18 +219,21 @@
* Search the list of AdapterFibContext addresses on the adapter
* to be sure this is a valid address
*/
- found = 0;
entry = dev->fib_list.next;
+ fibctx = NULL;
while(entry != &dev->fib_list) {
- aifcp = list_entry(entry, struct aac_fib_context, next);
- if(fibctx == aifcp) { /* We found a winner */
- found = 1;
+ fibctx = list_entry(entry, struct aac_fib_context, next);
+ /*
+ * Extract the AdapterFibContext from the Input parameters.
+ */
+ if(fibctx->unique == f.fibctx) { /* We found a winner */
break;
}
entry = entry->next;
+ fibctx = NULL;
}
- if (found == 0) {
+ if (!fibctx) {
dprintk ((KERN_INFO "Fib not found\n"));
return -EINVAL;
}
@@ -239,7 +261,7 @@
fib = list_entry(entry, struct fib, fiblink);
fibctx->count--;
spin_unlock_irqrestore(&dev->fib_lock, flags);
- if (copy_to_user(f.fib, fib->hw_fib, sizeof(struct hw_fib))) {
+ if (copy_to_user((char *)(unsigned long)f.fib, fib->hw_fib, sizeof(struct hw_fib))) {
kfree(fib->hw_fib);
kfree(fib);
return -EFAULT;
@@ -315,16 +337,10 @@
static int close_getadapter_fib(struct aac_dev * dev, void *arg)
{
- struct aac_fib_context *fibctx, *aifcp;
+ struct aac_fib_context *fibctx;
int status;
unsigned long flags;
struct list_head * entry;
- int found;
-
- /*
- * Extract the fibctx from the input parameters
- */
- fibctx = arg;
/*
* Verify that the HANDLE passed in was a valid AdapterFibContext
@@ -333,19 +349,22 @@
* to be sure this is a valid address
*/
- found = 0;
entry = dev->fib_list.next;
+ fibctx = NULL;
while(entry != &dev->fib_list) {
- aifcp = list_entry(entry, struct aac_fib_context, next);
- if(fibctx == aifcp) { /* We found a winner */
- found = 1;
+ fibctx = list_entry(entry, struct aac_fib_context, next);
+ /*
+ * Extract the fibctx from the input parameters
+ */
+ if(fibctx->unique == (u32)(unsigned long)arg) { /* We found a winner */
break;
}
entry = entry->next;
+ fibctx = NULL;
}
- if(found == 0)
+ if(!fibctx)
return 0; /* Already gone */
if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
@@ -363,16 +382,22 @@
* @arg: ioctl arguments
*
* This routine returns the driver version.
- * Under Linux, there have been no version incompatibilities, so this is simple!
+ * Under Linux, there have been no version incompatibilities, so
+ * this is simple!
*/
static int check_revision(struct aac_dev *dev, void *arg)
{
struct revision response;
+ extern unsigned long aac_driver_version;
response.compat = 1;
- response.version = AAC_DRIVER_VERSION;
- response.build = 9999;
+ response.version = aac_driver_version;
+# if (defined(AAC_DRIVER_BUILD))
+ response.build = AAC_DRIVER_BUILD;
+# else
+ response.build = 9999;
+# endif
if (copy_to_user(arg, &response, sizeof(response)))
return -EFAULT;
@@ -437,7 +462,7 @@
// 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->id = cpu_to_le32(srbcmd->id);
srbcmd->lun = cpu_to_le32(srbcmd->lun);
srbcmd->flags = cpu_to_le32(srbcmd->flags);
srbcmd->timeout = cpu_to_le32(srbcmd->timeout);
@@ -458,12 +483,14 @@
data_dir = SCSI_DATA_NONE;
}
- if( dev->pae_support ==1 ) {
+ if( dev->dac_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));
+ actual_fibsize = sizeof (struct aac_srb) -
+ sizeof(struct sgentry) + ((srbcmd->sg.count & 0xff) *
+ 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;
@@ -602,10 +629,10 @@
pci_info.bus = dev->pdev->bus->number;
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)))
return -EFAULT;
return 0;
- }
+}
int aac_do_ioctl(struct aac_dev * dev, int cmd, void *arg)
@@ -617,8 +644,9 @@
*/
status = aac_dev_ioctl(dev, cmd, arg);
- if(status != -ENOTTY)
+ if(status != -ENOTTY) {
return status;
+ }
switch (cmd) {
case FSACTL_MINIPORT_REV_CHECK:
diff -u -P --recursive linux-2.4.24/drivers/scsi/aacraid/commsup.c linux-2.4.24-2322/drivers/scsi/aacraid/commsup.c
--- linux-2.4.24/drivers/scsi/aacraid/commsup.c Fri Feb 13 11:31:25 2004
+++ linux-2.4.24-2322/drivers/scsi/aacraid/commsup.c Fri Feb 13 12:14:24 2004
@@ -311,10 +311,7 @@
{
struct aac_entry * entry = NULL;
int map = 0;
- struct aac_queue * q = &dev->queues->queue[qid];
-
- spin_lock_irqsave(q->lock, q->SavedIrql);
-
+
if (qid == AdapHighCmdQueue || qid == AdapNormCmdQueue)
{
/* if no entries wait for some if caller wants to */
@@ -352,42 +349,6 @@
return 0;
}
-
-/**
- * aac_insert_entry - insert a queue entry
- * @dev: Adapter
- * @index: Index of entry to insert
- * @qid: Queue number
- * @nonotify: Suppress adapter notification
- *
- * Gets the next free QE off the requested priorty adapter command
- * queue and associates the Fib with the QE. The QE represented by
- * index is ready to insert on the queue when this routine returns
- * success.
- */
-
-static int aac_insert_entry(struct aac_dev * dev, u32 index, u32 qid, unsigned long nonotify)
-{
- struct aac_queue * q = &dev->queues->queue[qid];
-
- if(q == NULL)
- BUG();
- *(q->headers.producer) = cpu_to_le32(index + 1);
- spin_unlock_irqrestore(q->lock, q->SavedIrql);
-
- if (qid == AdapHighCmdQueue ||
- qid == AdapNormCmdQueue ||
- qid == AdapHighRespQueue ||
- qid == AdapNormRespQueue)
- {
- if (!nonotify)
- aac_adapter_notify(dev, qid);
- }
- else
- printk("Suprise insert!\n");
- return 0;
-}
-
/*
* Define the highest level of host to adapter communication routines.
* These routines will support host to adapter FS commuication. These
@@ -413,7 +374,9 @@
* response FIB is received from the adapter.
*/
-int fib_send(u16 command, struct fib * fibptr, unsigned long size, int priority, int wait, int reply, fib_callback callback, void * callback_data)
+int aac_fib_send(u16 command, struct fib * fibptr, unsigned long size,
+ int priority, int wait, int reply, fib_callback callback,
+ void * callback_data)
{
u32 index;
u32 qid;
@@ -422,14 +385,15 @@
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_queue * q;
unsigned long flags = 0;
+ unsigned long qflags;
- if (!(le32_to_cpu(hw_fib->header.XferState) & HostOwned))
+ if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned)))
return -EBUSY;
/*
* There are 5 cases with the wait and reponse requested flags.
* The only invalid cases are if the caller requests to wait and
* does not request a response and if the caller does not want a
- * response and the Fibis not allocated from pool. If a response
+ * response and the Fib is not allocated from pool. If a response
* is not requesed the Fib will just be deallocaed by the DPC
* routine when the response comes back from the adapter. No
* further processing will be done besides deleting the Fib. We
@@ -486,12 +450,13 @@
if(wait)
spin_lock_irqsave(&fibptr->event_lock, flags);
- if(aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr)<0)
- return -EWOULDBLOCK;
+ spin_lock_irqsave(q->lock, qflags);
+ aac_queue_get( dev, &index, qid, hw_fib, 1, fibptr, &nointr);
+
dprintk((KERN_DEBUG "fib_send: inserting a queue entry at index %d.\n",index));
dprintk((KERN_DEBUG "Fib contents:.\n"));
- dprintk((KERN_DEBUG " Command = %d.\n", hw_fib->header.Command));
- dprintk((KERN_DEBUG " XferState = %x.\n", hw_fib->header.XferState));
+ dprintk((KERN_DEBUG " Command = %d.\n", le32_to_cpu(hw_fib->header.Command)));
+ dprintk((KERN_DEBUG " XferState = %x.\n", le32_to_cpu(hw_fib->header.XferState)));
dprintk((KERN_DEBUG " hw_fib va being sent=%p\n",fibptr->hw_fib));
dprintk((KERN_DEBUG " hw_fib pa being sent=%lx\n",(ulong)fibptr->hw_fib_pa));
dprintk((KERN_DEBUG " fib being sent=%p\n",fibptr));
@@ -510,8 +475,10 @@
fibptr->done = 0;
fibptr->flags = 0;
- if(aac_insert_entry(dev, index, qid, (nointr & aac_config.irq_mod)) < 0)
- return -EWOULDBLOCK;
+ *(q->headers.producer) = cpu_to_le32(index + 1);
+ spin_unlock_irqrestore(q->lock, qflags);
+ if (!(nointr & aac_config.irq_mod))
+ aac_adapter_notify(dev, qid);
/*
* If the caller wanted us to wait for response wait now.
*/
@@ -635,15 +602,19 @@
{
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_dev * dev = fibptr->dev;
+ struct aac_queue * q;
unsigned long nointr = 0;
- if (le32_to_cpu(hw_fib->header.XferState) == 0)
+ unsigned long qflags;
+ u32 qid;
+
+ if (hw_fib->header.XferState == 0)
return 0;
/*
* 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 )
return -EINVAL;
- }
+
/*
* This block handles the case where the adapter had sent us a
* command and we have finished processing the command. We
@@ -652,39 +623,27 @@
* send the completed cdb to the adapter.
*/
if (hw_fib->header.XferState & cpu_to_le32(SentFromAdapter)) {
+ u32 index;
hw_fib->header.XferState |= cpu_to_le32(HostProcessed);
- if (hw_fib->header.XferState & cpu_to_le32(HighPriority)) {
- u32 index;
- if (size)
- {
- size += sizeof(struct aac_fibhdr);
- if (size > le16_to_cpu(hw_fib->header.SenderSize))
- return -EMSGSIZE;
- hw_fib->header.Size = cpu_to_le16(size);
- }
- if(aac_queue_get(dev, &index, AdapHighRespQueue, hw_fib, 1, NULL, &nointr) < 0) {
- return -EWOULDBLOCK;
- }
- if (aac_insert_entry(dev, index, AdapHighRespQueue, (nointr & (int)aac_config.irq_mod)) != 0) {
- }
- }
- else if (hw_fib->header.XferState & NormalPriority)
- {
- u32 index;
-
- if (size) {
- size += sizeof(struct aac_fibhdr);
- if (size > le16_to_cpu(hw_fib->header.SenderSize))
- return -EMSGSIZE;
- hw_fib->header.Size = cpu_to_le16(size);
- }
- if (aac_queue_get(dev, &index, AdapNormRespQueue, hw_fib, 1, NULL, &nointr) < 0)
- return -EWOULDBLOCK;
- if (aac_insert_entry(dev, index, AdapNormRespQueue,
- (nointr & (int)aac_config.irq_mod)) != 0)
- {
- }
+ if (hw_fib->header.XferState & cpu_to_le32(HighPriority))
+ qid = AdapHighRespQueue;
+ else if (hw_fib->header.XferState & cpu_to_le32(NormalPriority))
+ qid = AdapNormRespQueue;
+ else
+ return 0;
+ if (size) {
+ size += sizeof(struct aac_fibhdr);
+ if (size > le16_to_cpu(hw_fib->header.SenderSize))
+ return -EMSGSIZE;
+ hw_fib->header.Size = cpu_to_le16(size);
}
+ q = &dev->queues->queue[qid];
+ spin_lock_irqsave(q->lock, qflags);
+ aac_queue_get(dev, &index, qid, 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, qid);
}
else
{
@@ -754,9 +713,10 @@
void aac_printf(struct aac_dev *dev, u32 val)
{
+ char *cp = dev->printfbuf;
+#if (defined(AAC_PRINTF_ENABLED))
int length = val & 0xffff;
int level = (val >> 16) & 0xffff;
- char *cp = dev->printfbuf;
/*
* The size of the printfbuf is set in port.c
@@ -770,6 +730,7 @@
printk(KERN_WARNING "aacraid:%s", cp);
else
printk(KERN_INFO "aacraid:%s", cp);
+#endif
memset(cp, 0, 256);
}
@@ -783,122 +744,274 @@
* dispatches it to the appropriate routine for handling.
*/
-#define CONTAINER_TO_BUS(cont) (0)
-#define CONTAINER_TO_TARGET(cont) ((cont))
-#define CONTAINER_TO_LUN(cont) (0)
-
static void aac_handle_aif(struct aac_dev * dev, struct fib * fibptr)
{
struct hw_fib * hw_fib = fibptr->hw_fib;
struct aac_aifcmd * aifcmd = (struct aac_aifcmd *)hw_fib->data;
int busy;
u32 container;
+ Scsi_Device * device;
+ enum {
+ NOTHING,
+ DELETE,
+ ADD,
+ CHANGE
+ } DeviceConfigNeeded;
+ extern struct proc_dir_entry * proc_scsi;
/* Sniff for container changes */
- dprintk ((KERN_INFO "AifCmdDriverNotify=%x\n", le32_to_cpu(*(u32 *)aifcmd->data)));
- switch (le32_to_cpu(*(u32 *)aifcmd->data)) {
- case AifDenMorphComplete:
- case AifDenVolumeExtendComplete:
- case AifEnContainerChange: /* Not really a driver notify Event */
-
- busy = 0;
- container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
- dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d) ",
- container,
- (dev && dev->scsi_host_ptr)
- ? dev->scsi_host_ptr->host_no
- : -1,
- CONTAINER_TO_BUS(container),
- CONTAINER_TO_TARGET(container),
- CONTAINER_TO_LUN(container)));
+ dprintk ((KERN_INFO "aac_handle_aif: Aif command=%x type=%x\n",
+ le32_to_cpu(aifcmd->command), le32_to_cpu(*(u32 *)aifcmd->data)));
+
+ DeviceConfigNeeded = NOTHING;
+ /*
+ * We have set this up to try and minimize the number of
+ * re-configures that take place. As a result of this when
+ * certain AIF's come in we will set a flag waiting for another
+ * type of AIF before setting the re-config flag.
+ */
+ switch (le32_to_cpu(aifcmd->command)) {
+ case AifCmdDriverNotify:
+ switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) {
/*
- * Find the Scsi_Device associated with the SCSI address,
- * and mark it as changed, invalidating the cache. This deals
- * with changes to existing device IDs.
+ * Morph or Expand complete
*/
+ case AifDenMorphComplete:
+ case AifDenVolumeExtendComplete:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= MAXIMUM_NUM_CONTAINERS)
+ break;
+ dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d)\n",
+ container,
+ (dev && dev->scsi_host_ptr)
+ ? dev->scsi_host_ptr->host_no
+ : -1,
+ CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container)));
- if ((dev != (struct aac_dev *)NULL)
- && (dev->scsi_host_ptr != (struct Scsi_Host *)NULL)) {
- Scsi_Device * device;
-
- for (device = dev->scsi_host_ptr->host_queue;
- device != (Scsi_Device *)NULL;
- device = device->next) {
- dprintk((KERN_INFO
- "aifd: device (%d,%d,%d,%d)?\n",
- dev->scsi_host_ptr->host_no,
- device->channel,
- device->id,
- device->lun));
- if ((device->channel == CONTAINER_TO_BUS(container))
- && (device->id == CONTAINER_TO_TARGET(container))
- && (device->lun == CONTAINER_TO_LUN(container))) {
- busy |= (device->access_count != 0);
- if (busy == 0) {
- device->removable = TRUE;
- }
- }
+ /*
+ * Find the Scsi_Device associated with the SCSI
+ * address. Make sure we have the right array, and if
+ * so set the flag to initiate a new re-config once we
+ * see an AifEnConfigChange AIF come through.
+ */
+
+ if ((dev != (struct aac_dev *)NULL)
+ && (dev->scsi_host_ptr != (struct Scsi_Host *)NULL)) {
+ for (device = dev->scsi_host_ptr->host_queue;
+ device != (Scsi_Device *)NULL;
+ device = device->next)
+ {
+ if ((device->channel == CONTAINER_TO_CHANNEL(container))
+ && (device->id == CONTAINER_TO_ID(container))
+ && (device->lun == CONTAINER_TO_LUN(container))) {
+ dev->DeviceContainerID = container;
+ dev->DeviceConfigNeeded = CHANGE;
+ dev->DeviceConfigWaitingOn = AifEnConfigChange;
+ break;
+ } /* if */
+ } /* for */
+ } /* if */
+ } /* switch */
+
+ /*
+ * If we are waiting on something and this happens to be
+ * that thing then set the re-configure flag.
+ */
+ if (dev->DeviceConfigWaitingOn == le32_to_cpu(*(u32 *)aifcmd->data)) {
+ DeviceConfigNeeded = dev->DeviceConfigNeeded;
+ }
+ break;
+
+ case AifCmdEventNotify:
+ switch (le32_to_cpu(((u32 *)aifcmd->data)[0])) {
+ /*
+ * Add an Array.
+ */
+ case AifEnAddContainer:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= MAXIMUM_NUM_CONTAINERS)
+ break;
+ dev->DeviceContainerID = container;
+ dev->DeviceConfigNeeded = ADD;
+ dev->DeviceConfigWaitingOn = AifEnConfigChange;
+ break;
+
+ /*
+ * Delete an Array.
+ */
+ case AifEnDeleteContainer:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= MAXIMUM_NUM_CONTAINERS)
+ break;
+ dev->DeviceContainerID = container;
+ dev->DeviceConfigNeeded = DELETE;
+ dev->DeviceConfigWaitingOn = AifEnConfigChange;
+ break;
+
+ /*
+ * Container change detected. If we currently are not
+ * waiting on something else, setup to wait on a Config Change.
+ */
+ case AifEnContainerChange:
+ container = le32_to_cpu(((u32 *)aifcmd->data)[1]);
+ if (container >= MAXIMUM_NUM_CONTAINERS)
+ break;
+ dev->DeviceContainerID = container;
+ if (dev->DeviceConfigWaitingOn) {
+ break;
}
+ dev->DeviceConfigNeeded = CHANGE;
+ dev->DeviceConfigWaitingOn = AifEnConfigChange;
+ break;
+ } /* switch */
+
+ /*
+ * If we are waiting on something and this happens to be
+ * that thing then set the re-configure flag.
+ */
+ if (dev->DeviceConfigWaitingOn == le32_to_cpu(*(u32 *)aifcmd->data)) {
+ DeviceConfigNeeded = dev->DeviceConfigNeeded;
}
- dprintk (("busy=%d\n", busy));
+ break;
+ case AifCmdJobProgress:
/*
- * if (busy == 0) {
- * scan_scsis(dev->scsi_host_ptr, 1,
- * CONTAINER_TO_BUS(container),
- * CONTAINER_TO_TARGET(container),
- * CONTAINER_TO_LUN(container));
- * }
- * is not exported as accessible, so we need to go around it
- * another way. So, we look for the "proc/scsi/scsi" entry in
- * the proc filesystem (using proc_scsi as a shortcut) and send
- * it a message. This deals with new devices that have
- * appeared. If the device has gone offline, scan_scsis will
- * also discover this, but we do not want the device to
- * go away. We need to check the access_count for the
- * device since we are not wanting the devices to go away.
+ * These are job progress AIF's. When a Clear is being
+ * done on a container it is initially created then hidden from
+ * the OS. When the clear completes we don't get a config
+ * change so we monitor the job status complete on a clear then
+ * wait for a containe change.
*/
- if ((busy == 0)
- && (proc_scsi != (struct proc_dir_entry *)NULL)) {
- struct proc_dir_entry * entry;
-
- dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi));
- for (entry = proc_scsi->subdir;
- entry != (struct proc_dir_entry *)NULL;
- entry = entry->next) {
- dprintk(("\"%.*s\"[%d]=%x ", entry->namelen,
- entry->name, entry->namelen, entry->low_ino));
- if ((entry->low_ino != 0)
- && (entry->namelen == 4)
- && (memcmp ("scsi", entry->name, 4) == 0)) {
- dprintk(("%p->write_proc=%p ", entry, entry->write_proc));
- if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) {
- char buffer[80];
- int length;
- mm_segment_t fs;
-
- sprintf (buffer,
- "scsi add-single-device %d %d %d %d\n",
- dev->scsi_host_ptr->host_no,
- CONTAINER_TO_BUS(container),
- CONTAINER_TO_TARGET(container),
- CONTAINER_TO_LUN(container));
- length = strlen (buffer);
- dprintk((KERN_INFO
- "echo %.*s > /proc/scsi/scsi\n",
- length-1,
- buffer));
- fs = get_fs();
- set_fs(get_ds());
- length = entry->write_proc(
- NULL, buffer, length, NULL);
- set_fs(fs);
- dprintk((KERN_INFO
- "returns %d\n", length));
- }
- break;
+
+ if ((((u32 *)aifcmd->data)[1] == cpu_to_le32(AifJobCtrZero))
+ && ((((u32 *)aifcmd->data)[6] == ((u32 *)aifcmd->data)[5])
+ || (((u32 *)aifcmd->data)[4] == cpu_to_le32(AifJobStsSuccess)))) {
+ dev->DeviceContainerID = -1;
+ dev->DeviceConfigWaitingOn = AifEnContainerChange;
+ dev->DeviceConfigNeeded = ADD;
+ }
+ break;
+ } /* switch */
+
+ if (DeviceConfigNeeded == NOTHING) {
+ return;
+ }
+
+ /*
+ * If we decided that a re-configuration needs to be done,
+ * schedule it here on the way out the door, please close the door
+ * behind you.
+ */
+ dev->DeviceConfigWaitingOn = 0;
+ dev->DeviceConfigNeeded = NOTHING;
+ container = dev->DeviceContainerID;
+ dev->DeviceContainerID = -1;
+
+ busy = 0;
+
+ dprintk ((KERN_INFO "container=%d(%d,%d,%d,%d)\n",
+ container,
+ (dev && dev->scsi_host_ptr)
+ ? dev->scsi_host_ptr->host_no
+ : -1,
+ CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container)));
+
+ /*
+ * Find the Scsi_Device associated with the SCSI address,
+ * and mark it as changed, invalidating the cache. This deals
+ * with changes to existing device IDs.
+ */
+
+ if (!dev || !dev->scsi_host_ptr) {
+ return;
+ }
+ for (device = dev->scsi_host_ptr->host_queue;
+ device != (Scsi_Device *)NULL;
+ device = device->next)
+ {
+ dprintk((KERN_INFO "aifd: device (%d,%d,%d,%d)?\n",
+ dev->scsi_host_ptr->host_no,
+ device->channel,
+ device->id,
+ device->lun));
+ if ((device->channel == CONTAINER_TO_CHANNEL(container))
+ && (device->id == CONTAINER_TO_ID(container))
+ && (device->lun == CONTAINER_TO_LUN(container))) {
+ busy |= device->access_count || dev->scsi_host_ptr->in_recovery;
+ if (busy == 0) {
+ device->removable = TRUE;
+ }
+ }
+ }
+ dprintk (("busy=%d\n", busy));
+
+ /*
+ * if (busy == 0) {
+ * scan_scsis(dev->scsi_host_ptr, 1,
+ * CONTAINER_TO_CHANNEL(container),
+ * CONTAINER_TO_ID(container),
+ * CONTAINER_TO_LUN(container));
+ * }
+ * is not exported as accessible, so we need to go around it
+ * another way. So, we look for the "proc/scsi/scsi" entry in
+ * the proc filesystem (using proc_scsi as a shortcut) and send
+ * it a message. This deals with new devices that have
+ * appeared. If the device has gone offline, scan_scsis will
+ * also discover this, but we do not want the device to
+ * go away. We need to check the access_count for the
+ * device since we are not wanting the devices to go away.
+ */
+ if ((busy == 0) && (DeviceConfigNeeded == CHANGE) && (dev->fsa_dev.valid[container] == 1)) {
+ dev->fsa_dev.valid[container] = 2;
+ }
+ if ((busy == 0)
+ && (proc_scsi != (struct proc_dir_entry *)NULL)) {
+ struct proc_dir_entry * entry;
+
+ dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi));
+ for (entry = proc_scsi->subdir;
+ entry != (struct proc_dir_entry *)NULL;
+ entry = entry->next) {
+ dprintk(("\"%.*s\"[%d]=%x ", entry->namelen,
+ entry->name, entry->namelen, entry->low_ino));
+ if ((entry->low_ino != 0)
+ && (entry->namelen == 4)
+ && (memcmp ("scsi", entry->name, 4) == 0)) {
+ dprintk(("%p->write_proc=%p ", entry, entry->write_proc));
+ if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) {
+ char buffer[80];
+ int length;
+ mm_segment_t fs;
+
+ sprintf (buffer,
+ "scsi %s-single-device %d %d %d %d\n",
+ ((DeviceConfigNeeded == DELETE)
+ ? "remove"
+ : "add"),
+ dev->scsi_host_ptr->host_no,
+ CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container));
+ length = strlen (buffer);
+ dprintk((KERN_INFO
+ "echo %.*s > /proc/scsi/scsi\n",
+ length-1,
+ buffer));
+//printk("echo %.*s > /proc/scsi/scsi\n", length-1, buffer);
+ fs = get_fs();
+ set_fs(get_ds());
+ length = entry->write_proc(
+ NULL, buffer, length, NULL);
+ set_fs(fs);
+ dprintk((KERN_INFO
+ "returns %d\n", length));
}
+ break;
}
}
}
@@ -918,7 +1031,7 @@
{
struct hw_fib *hw_fib, *hw_newfib;
struct fib *fib, *newfib;
- struct aac_queue_block *queues = dev->queues;
+ struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue];
struct aac_fib_context *fibctx;
unsigned long flags;
DECLARE_WAITQUEUE(wait, current);
@@ -938,22 +1051,22 @@
* Let the DPC know it has a place to send the AIF's to.
*/
dev->aif_thread = 1;
- add_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);
+ add_wait_queue(&q->cmdready, &wait);
set_current_state(TASK_INTERRUPTIBLE);
dprintk ((KERN_INFO "aac_command_thread start\n"));
while(1)
{
- spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
- while(!list_empty(&(queues->queue[HostNormCmdQueue].cmdq))) {
+ spin_lock_irqsave(q->lock, flags);
+ while(!list_empty(&(q->cmdq))) {
struct list_head *entry;
struct aac_aifcmd * aifcmd;
set_current_state(TASK_RUNNING);
- entry = queues->queue[HostNormCmdQueue].cmdq.next;
+ entry = q->cmdq.next;
list_del(entry);
- spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);
+ spin_unlock_irqrestore(q->lock, flags);
fib = list_entry(entry, struct fib, fiblink);
/*
* We will process the FIB here or pass it to a
@@ -987,8 +1101,10 @@
unsigned long flagv;
/* Sniff events */
- if (aifcmd->command == cpu_to_le32(AifCmdEventNotify))
+ if ((aifcmd->command == cpu_to_le32(AifCmdEventNotify))
+ || (aifcmd->command == cpu_to_le32(AifCmdJobProgress))) {
aac_handle_aif(dev, fib);
+ }
time_now = jiffies/HZ;
@@ -1069,20 +1185,21 @@
fib_adapter_complete(fib, sizeof(u32));
spin_unlock_irqrestore(&dev->fib_lock, flagv);
}
- spin_lock_irqsave(queues->queue[HostNormCmdQueue].lock, flags);
+ spin_lock_irqsave(q->lock, flags);
kfree(fib);
}
/*
* There are no more AIF's
*/
- spin_unlock_irqrestore(queues->queue[HostNormCmdQueue].lock, flags);
+ spin_unlock_irqrestore(q->lock, flags);
schedule();
if(signal_pending(current))
break;
set_current_state(TASK_INTERRUPTIBLE);
}
- remove_wait_queue(&queues->queue[HostNormCmdQueue].cmdready, &wait);
+ remove_wait_queue(&q->cmdready, &wait);
dev->aif_thread = 0;
complete_and_exit(&dev->aif_completion, 0);
+ return 0;
}
diff -u -P --recursive linux-2.4.24/drivers/scsi/aacraid/dpcsup.c linux-2.4.24-2322/drivers/scsi/aacraid/dpcsup.c
--- linux-2.4.24/drivers/scsi/aacraid/dpcsup.c Fri Feb 13 11:31:25 2004
+++ linux-2.4.24-2322/drivers/scsi/aacraid/dpcsup.c Tue Oct 7 12:59:37 2003
@@ -182,18 +182,24 @@
u32 index;
struct fib *fib = &fibctx;
- index = le32_to_cpu(entry->addr / sizeof(struct hw_fib));
- hw_fib = &dev->aif_base_va[index];
-
/*
- * Allocate a FIB at all costs. 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
+ * 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)
- if((fib = kmalloc(sizeof(struct fib), GFP_ATOMIC))==NULL)
+ if (dev->aif_thread) {
+ /* Limit the number we retreive from fib pool */
+ struct list_head * each;
+ int i = (dev->init->AdapterFibsSize / sizeof(struct hw_fib)) - 1;
+ list_for_each(each, &(q->cmdq))
+ if (--i <= 0)
+ break;
+ if ((i <= 0) || (!(fib = kmalloc(sizeof(struct fib),GFP_ATOMIC))))
fib = &fibctx;
-
+ }
+
+ index = le32_to_cpu(entry->addr / sizeof(struct hw_fib));
+ hw_fib = &dev->aif_base_va[index];
memset(fib, 0, sizeof(struct fib));
INIT_LIST_HEAD(&fib->fiblink);
fib->type = FSAFS_NTC_FIB_CONTEXT;
diff -u -P --recursive linux-2.4.24/drivers/scsi/aacraid/linit.c linux-2.4.24-2322/drivers/scsi/aacraid/linit.c
--- linux-2.4.24/drivers/scsi/aacraid/linit.c Fri Feb 13 11:31:25 2004
+++ linux-2.4.24-2322/drivers/scsi/aacraid/linit.c Fri Feb 13 12:13:20 2004
@@ -35,6 +35,9 @@
*
*/
+#define AAC_DRIVER_VERSION 0x01010004
+#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
+
#include <linux/module.h>
#include <linux/config.h>
#include <linux/kernel.h>
@@ -45,13 +48,22 @@
#include <linux/spinlock.h>
#include <linux/slab.h>
#include <linux/completion.h>
+#include <linux/interrupt.h>
#include <asm/semaphore.h>
-#include <linux/blk.h>
+#include <linux/blkdev.h>
#include "scsi.h"
#include "hosts.h"
+#include "sd.h"
+#include <linux/blk.h> /* for io_request_lock definition */
+#if (defined(__x86_64__))
+# include <asm-x86_64/ioctl32.h>
+ /* Cast the function, since sys_ioctl does not match */
+# define aac_ioctl32(x,y) register_ioctl32_conversion((x), \
+ (int(*)(unsigned int,unsigned int,unsigned long,struct file*))(y))
+# include <asm/uaccess.h>
+#endif
#include "aacraid.h"
-#include "sd.h"
#define AAC_DRIVER_NAME "aacraid"
@@ -63,6 +75,7 @@
static unsigned aac_count = 0;
static int aac_cfg_major = -1;
+unsigned long aac_driver_version = AAC_DRIVER_VERSION | 0x00000400;
/*
* Because of the way Linux names scsi devices, the order in this table has
@@ -138,13 +179,31 @@
static int aac_queuecommand(Scsi_Cmnd *, void (*CompletionRoutine)(Scsi_Cmnd *));
static int aac_biosparm(Scsi_Disk *, kdev_t, int *);
static int aac_procinfo(char *, char **, off_t, int, int, int);
+static void aac_queuedepth(struct Scsi_Host *, Scsi_Device *);
static int aac_ioctl(Scsi_Device *, int, void *);
static int aac_eh_abort(Scsi_Cmnd * cmd);
static int aac_eh_device_reset(Scsi_Cmnd* cmd);
static int aac_eh_bus_reset(Scsi_Cmnd* cmd);
static int aac_eh_reset(Scsi_Cmnd* cmd);
-static void aac_queuedepth(struct Scsi_Host *, Scsi_Device *);
+#if (defined(__x86_64__))
+/* Promote 32 bit apps that call get_next_adapter_fib_ioctl to 64 bit version */
+int aac_get_next_adapter_fib_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg)
+{
+ struct fib_ioctl f;
+ mm_segment_t fs;
+ int retval;
+
+ memset (&f, 0, sizeof(f));
+ if(copy_from_user((void *)&f, (void *)arg, sizeof(struct fib_ioctl) - sizeof(u32)))
+ return -EFAULT;
+ fs = get_fs();
+ set_fs(get_ds());
+ retval = sys_ioctl(fd, cmd, (unsigned long)&f);
+ set_fs(fs);
+ return retval;
+}
+#endif /* __x86_64__ */
/**
* aac_detect - Probe for aacraid cards
@@ -175,43 +234,56 @@
struct aac_dev *aac;
struct fsa_scsi_hba *fsa_dev_ptr;
char *name = NULL;
-
- printk(KERN_INFO "Red Hat/Adaptec %s driver (%d.%d-%d %s)\n",
- AAC_DRIVER_NAME,
- AAC_DRIVER_VERSION >> 24,
- (AAC_DRIVER_VERSION >> 16) & 0xFF,
- (AAC_DRIVER_VERSION >> 8) & 0xFF,
- AAC_DRIVER_BUILD_DATE);
-
+ int ret;
+
+# if (defined(AAC_DRIVER_BUILD))
+ printk(KERN_INFO "Red Hat/Adaptec %s driver (%d.%d-%d[%d])\n",
+ AAC_DRIVER_NAME,
+ AAC_DRIVER_VERSION >> 24,
+ (AAC_DRIVER_VERSION >> 16) & 0xFF,
+ AAC_DRIVER_VERSION & 0xFF,
+ AAC_DRIVER_BUILD);
+# else
+ printk(KERN_INFO "Red Hat/Adaptec %s driver (%d.%d-%d %s)\n",
+ AAC_DRIVER_NAME,
+ AAC_DRIVER_VERSION >> 24,
+ (AAC_DRIVER_VERSION >> 16) & 0xFF,
+ AAC_DRIVER_VERSION & 0xFF,
+ AAC_DRIVER_BUILD_DATE);
+# endif
+
/* setting up the proc directory structure */
-
- template->proc_name = "aacraid";
spin_unlock_irq(&io_request_lock);
- for( index = 0; index != num_aacdrivers; index++ )
+ dev = NULL;
+ while((dev = pci_find_device(PCI_ANY_ID, PCI_ANY_ID, dev)))
{
- device_id = aac_drivers[index].device;
- vendor_id = aac_drivers[index].vendor;
- name = aac_drivers[index].name;
- dprintk((KERN_DEBUG "Checking %s %x/%x/%x/%x.\n",
- name, vendor_id, device_id,
- aac_drivers[index].subsystem_vendor,
- aac_drivers[index].subsystem_device));
-
- dev = NULL;
- while((dev = pci_find_device(vendor_id, device_id, dev))) {
- if (pci_enable_device(dev))
+ if (pci_enable_device(dev))
+ continue;
+ for( index = 0; index != num_aacdrivers; index++ )
+ {
+ device_id = aac_drivers[index].device;
+ vendor_id = aac_drivers[index].vendor;
+ name = aac_drivers[index].name;
+
+ if((dev->vendor != vendor_id) ||
+ (dev->device != device_id) ||
+ ((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) &&
+ (aac_drivers[index].subsystem_vendor != (unsigned short)PCI_ANY_ID)) ||
+ ((dev->subsystem_device != aac_drivers[index].subsystem_device) &&
+ (aac_drivers[index].subsystem_device != (unsigned short)PCI_ANY_ID)))
continue;
+
pci_set_master(dev);
-
- if(aac_drivers[index].quirks & AAC_QUIRK_31BIT)
- pci_set_dma_mask(dev, 0x7FFFFFFFULL);
+
+ if (aac_drivers[index].quirks & AAC_QUIRK_31BIT)
+ ret = pci_set_dma_mask(dev, 0x7FFFFFFFULL);
else
- pci_set_dma_mask(dev, 0xFFFFFFFFULL);
+ ret = pci_set_dma_mask(dev, 0xFFFFFFFFULL);
- if((dev->subsystem_vendor != aac_drivers[index].subsystem_vendor) ||
- (dev->subsystem_device != aac_drivers[index].subsystem_device))
- continue;
+ if (ret) {
+ printk(KERN_WARNING "%s: Can't set DMA mask.\n", name);
+ }
dprintk((KERN_DEBUG "%s device detected.\n", name));
dprintk((KERN_DEBUG "%x/%x/%x/%x.\n", vendor_id, device_id,
@@ -254,9 +331,9 @@
*/
host_ptr->unique_id = aac_count - 1;
/*
- * This function is called after the device list has
- * been built to find the tagged queueing depth
- * supported for each device.
+ * This function is called after the device list
+ * has been built to find the tagged queueing
+ * depth supported for each device.
*/
host_ptr->select_queue_depths = aac_queuedepth;
aac = (struct aac_dev *)host_ptr->hostdata;
@@ -273,16 +350,16 @@
/* Initialize the ordinal number of the device to -1 */
fsa_dev_ptr = &(aac->fsa_dev);
for( container = 0; container < MAXIMUM_NUM_CONTAINERS; container++ )
- fsa_dev_ptr->devno[container] = -1;
+ fsa_dev_ptr->devname[container][0] = '\0';
dprintk((KERN_DEBUG "Initializing Hardware...\n"));
if((*aac_drivers[index].init)(aac , host_ptr->unique_id) != 0)
{
/* device initialization failed */
- printk(KERN_WARNING "aacraid: device initialization failed.\n");
+ printk(KERN_WARNING "%s: device initialization failed.\n", AAC_DRIVER_NAME);
scsi_unregister(host_ptr);
aac_count--;
- continue;
+ break;
}
dprintk((KERN_DEBUG "%s:%d device initialization successful.\n", name, host_ptr->unique_id));
aac_get_adapter_info(aac);
@@ -305,18 +382,32 @@
* dmb - we may need to move the setting of these parms somewhere else once
* we get a fib that can report the actual numbers
*/
- host_ptr->max_id = AAC_MAX_TARGET;
+ host_ptr->max_id = MAXIMUM_NUM_CONTAINERS;
host_ptr->max_lun = AAC_MAX_LUN;
+ break;
}
}
if( aac_count ){
if((aac_cfg_major = register_chrdev( 0, "aac", &aac_cfg_fops))<0)
- printk(KERN_WARNING "aacraid: unable to register \"aac\" device.\n");
+ printk(KERN_WARNING "%s: unable to register \"aac\" device.\n", AAC_DRIVER_NAME);
+# if (defined(__x86_64__))
+ aac_ioctl32(FSACTL_MINIPORT_REV_CHECK, sys_ioctl);
+ aac_ioctl32(FSACTL_SENDFIB, sys_ioctl);
+ aac_ioctl32(FSACTL_OPEN_GET_ADAPTER_FIB, sys_ioctl);
+ aac_ioctl32(FSACTL_GET_NEXT_ADAPTER_FIB,
+ aac_get_next_adapter_fib_ioctl);
+ aac_ioctl32(FSACTL_CLOSE_GET_ADAPTER_FIB, sys_ioctl);
+ aac_ioctl32(FSACTL_SEND_RAW_SRB, sys_ioctl);
+ aac_ioctl32(FSACTL_GET_PCI_INFO, sys_ioctl);
+ aac_ioctl32(FSACTL_QUERY_DISK, sys_ioctl);
+ aac_ioctl32(FSACTL_DELETE_DISK, sys_ioctl);
+ aac_ioctl32(FSACTL_FORCE_DELETE_DISK, sys_ioctl);
+ aac_ioctl32(2131, sys_ioctl);
+# endif
}
spin_lock_irq(&io_request_lock);
- template->present = aac_count; /* # of cards of this type found */
return aac_count;
}
@@ -355,6 +446,19 @@
*/
if( aac_cfg_major >= 0 )
{
+# if (defined(__x86_64__))
+ unregister_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK);
+ unregister_ioctl32_conversion(FSACTL_SENDFIB);
+ unregister_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB);
+ unregister_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB);
+ unregister_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB);
+ unregister_ioctl32_conversion(FSACTL_SEND_RAW_SRB);
+ unregister_ioctl32_conversion(FSACTL_GET_PCI_INFO);
+ unregister_ioctl32_conversion(FSACTL_QUERY_DISK);
+ unregister_ioctl32_conversion(FSACTL_DELETE_DISK);
+ unregister_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK);
+ unregister_ioctl32_conversion(2131);
+# endif
unregister_chrdev(aac_cfg_major, "aac");
aac_cfg_major = -1;
}
@@ -411,6 +515,9 @@
* aac_biosparm - return BIOS parameters for disk
* @disk: SCSI disk object to process
* @device: kdev_t of the disk in question
+ * @sdev: The scsi device corresponding to the disk
+ * @bdev: The block device corresponding to the disk
+ * @capacity: The sector capacity of the disk
* @geom: geometry block to fill in
*
* Return the Heads/Sectors/Cylinders BIOS Disk Parameters for Disk.
@@ -428,19 +535,22 @@
* be displayed.
*/
-static int aac_biosparm(Scsi_Disk *disk, kdev_t dev, int *geom)
+static int aac_biosparm(
+ Scsi_Disk *disk, kdev_t dev,
+ int *geom)
{
struct diskparm *param = (struct diskparm *)geom;
struct buffer_head * buf;
+ sector_t capacity = disk->capacity;
dprintk((KERN_DEBUG "aac_biosparm.\n"));
/*
* Assuming extended translation is enabled - #REVISIT#
*/
- if( disk->capacity >= 2 * 1024 * 1024 ) /* 1 GB in 512 byte sectors */
+ if( capacity >= 2 * 1024 * 1024 ) /* 1 GB in 512 byte sectors */
{
- if( disk->capacity >= 4 * 1024 * 1024 ) /* 2 GB in 512 byte sectors */
+ if( capacity >= 4 * 1024 * 1024 ) /* 2 GB in 512 byte sectors */
{
param->heads = 255;
param->sectors = 63;
@@ -457,7 +567,7 @@
param->sectors = 32;
}
- param->cylinders = disk->capacity/(param->heads * param->sectors);
+ param->cylinders = cap_to_cyls(capacity, param->heads * param->sectors);
/*
* Read the first 1024 bytes from the disk device
@@ -512,7 +622,7 @@
end_sec = first->end_sector & 0x3f;
}
- param->cylinders = disk->capacity / (param->heads * param->sectors);
+ param->cylinders = cap_to_cyls(capacity, param->heads * param->sectors);
if(num < 4 && end_sec == param->sectors)
{
@@ -655,6 +795,11 @@
* zero for success
*/
+/*------------------------------------------------------------------------------
+ aac_ioctl()
+
+ Handle SCSI ioctls
+ *----------------------------------------------------------------------------*/
static int aac_ioctl(Scsi_Device * scsi_dev_ptr, int cmd, void * arg)
{
struct aac_dev *dev;
@@ -677,7 +822,7 @@
static int aac_cfg_open(struct inode * inode, struct file * file )
{
- unsigned minor_number = MINOR(inode->i_rdev);
+ unsigned minor_number = iminor(inode);
if(minor_number >= aac_count)
return -ENODEV;
return 0;
@@ -713,7 +858,7 @@
static int aac_cfg_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg )
{
- struct aac_dev *dev = aac_devices[MINOR(inode->i_rdev)];
+ struct aac_dev *dev = aac_devices[iminor(inode)];
return aac_do_ioctl(dev, cmd, (void *)arg);
}
@@ -748,6 +893,7 @@
.highmem_io = 1,
#endif
+ .proc_name = AAC_DRIVER_NAME,
};
#include "scsi_module.c"
@@ -775,43 +921,59 @@
* Bugs: Only offset zero is handled
*/
-static int aac_procinfo(char *proc_buffer, char **start_ptr,off_t offset,
- int bytes_available, int host_no, int write)
+static int aac_procinfo(
+ char *proc_buffer, char **start_ptr,off_t offset,
+ int bytes_available,
+ int host_no,
+ int write)
{
- struct aac_dev * dev;
+ struct aac_dev * dev = (struct aac_dev *)NULL;
int index, ret, tmp;
if(write || offset > 0)
return 0;
*start_ptr = proc_buffer;
- ret = sprintf(proc_buffer,
- "Adaptec Raid Controller %d.%d-%d %s, scsi hba number %d\n",
+# if (defined(AAC_DRIVER_BUILD))
+ ret = sprintf(proc_buffer,
+ "Adaptec Raid Controller %d.%d-%d[%d]\n",
+ AAC_DRIVER_VERSION >> 24,
+ (AAC_DRIVER_VERSION >> 16) & 0xFF,
+ AAC_DRIVER_VERSION & 0xFF,
+ AAC_DRIVER_BUILD);
+# else
+ ret = sprintf(proc_buffer,
+ "Adaptec Raid Controller %d.%d-%d %s\n",
AAC_DRIVER_VERSION >> 24,
(AAC_DRIVER_VERSION >> 16) & 0xFF,
- (AAC_DRIVER_VERSION >> 8) & 0xFF,
- AAC_DRIVER_BUILD_DATE,
- host_no);
+ AAC_DRIVER_VERSION & 0xFF,
+ AAC_DRIVER_BUILD_DATE);
+# endif
for (index = 0; index < aac_count; ++index) {
- if (((dev = aac_devices[index]) != NULL) && dev->scsi_host_ptr->host_no == host_no)
+ if (((dev = aac_devices[index]) != (struct aac_dev *)NULL)
+ && (dev->scsi_host_ptr->host_no == host_no)
+ ) {
break;
+ }
}
- if (index >= aac_count || dev == NULL)
+ if ((index >= aac_count) || (dev == (struct aac_dev *)NULL)) {
return ret;
+ }
+ ret += sprintf(proc_buffer + ret, "Vendor: %s Model: %s\n",
+ aac_drivers[dev->cardtype].vname, aac_drivers[dev->cardtype].model);
tmp = dev->adapter_info.kernelrev;
ret += sprintf(proc_buffer + ret, "kernel: %d.%d-%d[%d]\n",
- tmp >> 24, (tmp >> 16) & 0xff, (tmp >> 8) & 0xff,
- dev->adapter_info.kernelbuild);
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ dev->adapter_info.kernelbuild);
tmp = dev->adapter_info.monitorrev;
ret += sprintf(proc_buffer + ret, "monitor: %d.%d-%d[%d]\n",
- tmp >> 24, (tmp >> 16) & 0xff, (tmp >> 8) & 0xff,
- dev->adapter_info.monitorbuild);
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ dev->adapter_info.monitorbuild);
tmp = dev->adapter_info.biosrev;
ret += sprintf(proc_buffer + ret, "bios: %d.%d-%d[%d]\n",
- tmp >> 24, (tmp >> 16) & 0xff, (tmp >> 8) & 0xff,
- dev->adapter_info.biosbuild);
- ret += sprintf(proc_buffer + ret, "serial: %x%x\n",
- dev->adapter_info.serial[0],
- dev->adapter_info.serial[1]);
+ tmp >> 24, (tmp >> 16) & 0xff, tmp & 0xff,
+ dev->adapter_info.biosbuild);
+ ret += sprintf(proc_buffer + ret, "serial: %x\n",
+ dev->adapter_info.serial[0]);
return ret;
}
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH] aacraid changes for 2.4.24 kernel to add support of AMD64 (part 2)
2004-02-13 21:16 Salyzyn, Mark
@ 2004-02-13 21:58 ` Christoph Hellwig
0 siblings, 0 replies; 4+ messages in thread
From: Christoph Hellwig @ 2004-02-13 21:58 UTC (permalink / raw)
To: Salyzyn, Mark; +Cc: linux-scsi
struct fib_ioctl
{
- char *fibctx;
- int wait;
- char *fib;
+ u32 fibctx;
+ s32 wait;
+#if (defined(__x86_64__))
+ u64 fib;
+#else
+ u32 fib;
+#endif
This is broken. If you really mean what you wrote just use
unsigned long, but if you want this API to actually work as
expected use the same value on all architectures.
+ if (!dev || !dev->scsi_host_ptr) {
+ return;
+ }
+ for (device = dev->scsi_host_ptr->host_queue;
+ device != (Scsi_Device *)NULL;
+ device = device->next)
+ {
+ dprintk((KERN_INFO "aifd: device (%d,%d,%d,%d)?\n",
+ dev->scsi_host_ptr->host_no,
+ device->channel,
+ device->id,
+ device->lun));
+ if ((device->channel == CONTAINER_TO_CHANNEL(container))
+ && (device->id == CONTAINER_TO_ID(container))
+ && (device->lun == CONTAINER_TO_LUN(container))) {
+ busy |= device->access_count || dev->scsi_host_ptr->in_recovery;
+ if (busy == 0) {
+ device->removable = TRUE;
+ }
+ }
+ }
This gives you nice races again.
+ dprintk((KERN_INFO "proc_scsi=%p ", proc_scsi));
+ for (entry = proc_scsi->subdir;
+ entry != (struct proc_dir_entry *)NULL;
+ entry = entry->next) {
+ dprintk(("\"%.*s\"[%d]=%x ", entry->namelen,
+ entry->name, entry->namelen, entry->low_ino));
+ if ((entry->low_ino != 0)
+ && (entry->namelen == 4)
+ && (memcmp ("scsi", entry->name, 4) == 0)) {
+ dprintk(("%p->write_proc=%p ", entry, entry->write_proc));
+ if (entry->write_proc != (int (*)(struct file *, const char *, unsigned long, void *))NULL) {
+ char buffer[80];
+ int length;
+ mm_segment_t fs;
+
+ sprintf (buffer,
+ "scsi %s-single-device %d %d %d %d\n",
+ ((DeviceConfigNeeded == DELETE)
+ ? "remove"
+ : "add"),
+ dev->scsi_host_ptr->host_no,
+ CONTAINER_TO_CHANNEL(container),
+ CONTAINER_TO_ID(container),
+ CONTAINER_TO_LUN(container));
+ length = strlen (buffer);
+ dprintk((KERN_INFO
+ "echo %.*s > /proc/scsi/scsi\n",
+ length-1,
+ buffer));
+//printk("echo %.*s > /proc/scsi/scsi\n", length-1, buffer);
+ fs = get_fs();
+ set_fs(get_ds());
+ length = entry->write_proc(
+ NULL, buffer, length, NULL);
+ set_fs(fs);
+ dprintk((KERN_INFO
+ "returns %d\n", length));
Stop it. The code is bogus that I wonder how you even dare to post it.
+#if (defined(__x86_64__))
+# include <asm-x86_64/ioctl32.h>
+ /* Cast the function, since sys_ioctl does not match */
+# define aac_ioctl32(x,y) register_ioctl32_conversion((x), \
+ (int(*)(unsigned int,unsigned int,unsigned long,struct file*))(y))
+# include <asm/uaccess.h>
+#endif
So why do the other drivers not need this?
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2004-02-13 23:04 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-02-13 22:37 [PATCH] aacraid changes for 2.4.24 kernel to add support of AMD64 (part 2) Salyzyn, Mark
2004-02-13 23:04 ` Christoph Hellwig
-- strict thread matches above, loose matches on Subject: below --
2004-02-13 21:16 Salyzyn, Mark
2004-02-13 21:58 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox