Commit 2562d40e authored by Mark Haverkamp's avatar Mark Haverkamp Committed by James Bottomley

[PATCH] aacraid 32bit app ioctl compat patch (Updated)

Allows 32 bit apps to use ioctls in a 64 bit kernel.

Signed-off-by Mark Haverkamp <markh@osdl.org>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 7ce0f3b7
...@@ -1176,7 +1176,7 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg) ...@@ -1176,7 +1176,7 @@ int aac_dev_ioctl(struct aac_dev *dev, int cmd, void *arg)
return delete_disk(dev, arg); return delete_disk(dev, arg);
case FSACTL_FORCE_DELETE_DISK: case FSACTL_FORCE_DELETE_DISK:
return force_delete_disk(dev, arg); return force_delete_disk(dev, arg);
case 2131: case FSACTL_GET_CONTAINERS:
return aac_get_containers(dev); return aac_get_containers(dev);
default: default:
return -ENOTTY; return -ENOTTY;
......
...@@ -656,6 +656,7 @@ typedef void (*fib_callback)(void *ctxt, struct fib *fibctx); ...@@ -656,6 +656,7 @@ typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
struct aac_fib_context { struct aac_fib_context {
s16 type; // used for verification of structure s16 type; // used for verification of structure
s16 size; s16 size;
u32 unique; // unique value representing this context
ulong jiffies; // used for cleanup - dmb changed to ulong ulong jiffies; // used for cleanup - dmb changed to ulong
struct list_head next; // used to link context's into a linked list 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. struct semaphore wait_sem; // this is used to wait for the next fib to arrive.
...@@ -1231,11 +1232,11 @@ struct aac_delete_disk { ...@@ -1231,11 +1232,11 @@ struct aac_delete_disk {
u32 disknum; u32 disknum;
u32 cnum; u32 cnum;
}; };
struct fib_ioctl struct fib_ioctl
{ {
char *fibctx; u32 fibctx;
int wait; s32 wait;
char *fib; char *fib;
}; };
...@@ -1276,6 +1277,7 @@ struct revision ...@@ -1276,6 +1277,7 @@ struct revision
#define FSACTL_MINIPORT_REV_CHECK CTL_CODE(2107, METHOD_BUFFERED) #define FSACTL_MINIPORT_REV_CHECK CTL_CODE(2107, METHOD_BUFFERED)
#define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED) #define FSACTL_GET_PCI_INFO CTL_CODE(2119, METHOD_BUFFERED)
#define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER) #define FSACTL_FORCE_DELETE_DISK CTL_CODE(2120, METHOD_NEITHER)
#define FSACTL_GET_CONTAINERS 2131
struct aac_common struct aac_common
......
...@@ -92,11 +92,12 @@ static int ioctl_send_fib(struct aac_dev * dev, void *arg) ...@@ -92,11 +92,12 @@ static int ioctl_send_fib(struct aac_dev * dev, void *arg)
*/ */
kfib->header.XferState = 0; kfib->header.XferState = 0;
} else { } else {
if (fib_send(kfib->header.Command, fibptr, le32_to_cpu(kfib->header.Size) , FsaNormal, int retval = fib_send(kfib->header.Command, fibptr,
1, 1, NULL, NULL) != 0) le32_to_cpu(kfib->header.Size) , FsaNormal,
{ 1, 1, NULL, NULL);
if (retval) {
fib_free(fibptr); fib_free(fibptr);
return -EINVAL; return retval;
} }
if (fib_complete(fibptr) != 0) { if (fib_complete(fibptr) != 0) {
fib_free(fibptr); fib_free(fibptr);
...@@ -130,14 +131,24 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -130,14 +131,24 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg)
{ {
struct aac_fib_context * fibctx; struct aac_fib_context * fibctx;
int status; int status;
unsigned long flags;
fibctx = kmalloc(sizeof(struct aac_fib_context), GFP_KERNEL); fibctx = kmalloc(sizeof(struct aac_fib_context), GFP_KERNEL);
if (fibctx == NULL) { if (fibctx == NULL) {
status = -ENOMEM; status = -ENOMEM;
} else { } else {
unsigned long flags;
struct list_head * entry;
struct aac_fib_context * context;
fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT; fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT;
fibctx->size = sizeof(struct aac_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. * Initialize the mutex used to wait for the next AIF.
*/ */
...@@ -155,9 +166,22 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -155,9 +166,22 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg)
* AdapterFibContext list. * AdapterFibContext list.
*/ */
spin_lock_irqsave(&dev->fib_lock, flags); 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); list_add_tail(&fibctx->next, &dev->fib_list);
spin_unlock_irqrestore(&dev->fib_lock, flags); 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; status = -EFAULT;
} else { } else {
status = 0; status = 0;
...@@ -178,43 +202,44 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -178,43 +202,44 @@ static int open_getadapter_fib(struct aac_dev * dev, void *arg)
static int next_getadapter_fib(struct aac_dev * dev, void *arg) 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 fib *fib; struct fib *fib;
struct aac_fib_context *fibctx;
int status; int status;
struct list_head * entry; struct list_head * entry;
int found;
unsigned long flags; unsigned long flags;
if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl))) if(copy_from_user((void *)&f, arg, sizeof(struct fib_ioctl)))
return -EFAULT; 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 * Verify that the HANDLE passed in was a valid AdapterFibContext
* *
* Search the list of AdapterFibContext addresses on the adapter * Search the list of AdapterFibContext addresses on the adapter
* to be sure this is a valid address * to be sure this is a valid address
*/ */
found = 0;
entry = dev->fib_list.next; entry = dev->fib_list.next;
fibctx = NULL;
while(entry != &dev->fib_list) { while (entry != &dev->fib_list) {
aifcp = list_entry(entry, struct aac_fib_context, next); fibctx = list_entry(entry, struct aac_fib_context, next);
if(fibctx == aifcp) { /* We found a winner */ /*
found = 1; * Extract the AdapterFibContext from the Input parameters.
*/
if (fibctx->unique == f.fibctx) { /* We found a winner */
break; break;
} }
entry = entry->next; entry = entry->next;
fibctx = NULL;
} }
if (found == 0) if (!fibctx) {
dprintk ((KERN_INFO "Fib Context not found\n"));
return -EINVAL; return -EINVAL;
}
if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) || if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
(fibctx->size != sizeof(struct aac_fib_context))) (fibctx->size != sizeof(struct aac_fib_context))) {
dprintk ((KERN_INFO "Fib Context corrupt?\n"));
return -EINVAL; return -EINVAL;
}
status = 0; status = 0;
spin_lock_irqsave(&dev->fib_lock, flags); spin_lock_irqsave(&dev->fib_lock, flags);
/* /*
...@@ -309,16 +334,10 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx) ...@@ -309,16 +334,10 @@ int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)
static int close_getadapter_fib(struct aac_dev * dev, void *arg) static int close_getadapter_fib(struct aac_dev * dev, void *arg)
{ {
struct aac_fib_context *fibctx, *aifcp; struct aac_fib_context *fibctx;
int status; int status;
unsigned long flags; unsigned long flags;
struct list_head * entry; 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 * Verify that the HANDLE passed in was a valid AdapterFibContext
...@@ -327,19 +346,23 @@ static int close_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -327,19 +346,23 @@ static int close_getadapter_fib(struct aac_dev * dev, void *arg)
* to be sure this is a valid address * to be sure this is a valid address
*/ */
found = 0;
entry = dev->fib_list.next; entry = dev->fib_list.next;
fibctx = NULL;
while(entry != &dev->fib_list) { while(entry != &dev->fib_list) {
aifcp = list_entry(entry, struct aac_fib_context, next); fibctx = list_entry(entry, struct aac_fib_context, next);
if(fibctx == aifcp) { /* We found a winner */ /*
found = 1; * Extract the fibctx from the input parameters
*/
if (fibctx->unique == (u32)(unsigned long)arg) {
/* We found a winner */
break; break;
} }
entry = entry->next; entry = entry->next;
fibctx = NULL;
} }
if(found == 0) if (!fibctx)
return 0; /* Already gone */ return 0; /* Already gone */
if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) || if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||
...@@ -356,8 +379,9 @@ static int close_getadapter_fib(struct aac_dev * dev, void *arg) ...@@ -356,8 +379,9 @@ static int close_getadapter_fib(struct aac_dev * dev, void *arg)
* @dev: adapter * @dev: adapter
* @arg: ioctl arguments * @arg: ioctl arguments
* *
* This routine returns the firmware version. * 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) static int check_revision(struct aac_dev *dev, void *arg)
...@@ -419,6 +443,11 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg) ...@@ -419,6 +443,11 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg)
goto cleanup; goto cleanup;
} }
if (fibsize > FIB_DATA_SIZE_IN_BYTES) {
rcode = -EINVAL;
goto cleanup;
}
if(copy_from_user(srbcmd, user_srb,fibsize)){ if(copy_from_user(srbcmd, user_srb,fibsize)){
printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); printk(KERN_DEBUG"aacraid: Could not copy srb from user\n");
rcode = -EFAULT; rcode = -EFAULT;
...@@ -438,7 +467,7 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg) ...@@ -438,7 +467,7 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg)
srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size); srbcmd->cdb_size = cpu_to_le32(srbcmd->cdb_size);
switch(srbcmd->flags){ switch (srbcmd->flags & (SRB_DataIn | SRB_DataOut)) {
case SRB_DataOut: case SRB_DataOut:
data_dir = DMA_TO_DEVICE; data_dir = DMA_TO_DEVICE;
break; break;
...@@ -451,17 +480,26 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg) ...@@ -451,17 +480,26 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg)
default: default:
data_dir = DMA_NONE; data_dir = DMA_NONE;
} }
if( dev->pae_support ==1 ) { if (dev->pae_support == 1) {
struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg; struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
byte_count = 0; 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)); * This should also catch if user used the 32 bit sgmap
*/
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 if(actual_fibsize != fibsize){ // User made a mistake - should not continue
printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"); printk(KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n");
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
if ((data_dir == DMA_NONE) && psg->count) {
printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
rcode = -EINVAL;
goto cleanup;
}
for (i = 0; i < psg->count; i++) { for (i = 0; i < psg->count; i++) {
dma_addr_t addr; dma_addr_t addr;
...@@ -506,6 +544,11 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg) ...@@ -506,6 +544,11 @@ int aac_send_raw_srb(struct aac_dev* dev, void* arg)
rcode = -EINVAL; rcode = -EINVAL;
goto cleanup; goto cleanup;
} }
if ((data_dir == DMA_NONE) && psg->count) {
printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
rcode = -EINVAL;
goto cleanup;
}
for (i = 0; i < psg->count; i++) { for (i = 0; i < psg->count; i++) {
dma_addr_t addr; dma_addr_t addr;
void* p; void* p;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#define AAC_DRIVER_BUILD_DATE __DATE__ #define AAC_DRIVER_BUILD_DATE __DATE__
#define AAC_DRIVERNAME "aacraid" #define AAC_DRIVERNAME "aacraid"
#include <linux/compat.h>
#include <linux/blkdev.h> #include <linux/blkdev.h>
#include <linux/completion.h> #include <linux/completion.h>
#include <linux/init.h> #include <linux/init.h>
...@@ -41,6 +42,8 @@ ...@@ -41,6 +42,8 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/syscalls.h>
#include <linux/ioctl32.h>
#include <asm/semaphore.h> #include <asm/semaphore.h>
#include <scsi/scsi.h> #include <scsi/scsi.h>
...@@ -168,6 +171,29 @@ static struct aac_driver_ident aac_drivers[] = { ...@@ -168,6 +171,29 @@ static struct aac_driver_ident aac_drivers[] = {
{ aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA (ZCR DIMM SATA) */ { aac_rx_init, "aacraid", "ADAPTEC ", "ASR-2025SA ", 1 }, /* ASR-2025SA (ZCR DIMM SATA) */
}; };
#ifdef CONFIG_COMPAT
/*
* Promote 32 bit apps that call get_next_adapter_fib_ioctl to 64 bit version
*/
static int aac_get_next_adapter_fib_ioctl(unsigned int fd, unsigned int cmd,
unsigned long arg, struct file *file)
{
struct fib_ioctl *f;
f = compat_alloc_user_space(sizeof(*f));
if (!access_ok(VERIFY_WRITE, f, sizeof(*f)))
return -EFAULT;
clear_user(f, sizeof(*f));
if (copy_from_user((void *)f, (void *)arg,
sizeof(struct fib_ioctl) - sizeof(u32)))
return -EFAULT;
return sys_ioctl(fd, cmd, (unsigned long)f);
}
#endif
/** /**
* aac_queuecommand - queue a SCSI command * aac_queuecommand - queue a SCSI command
* @cmd: SCSI command to queue * @cmd: SCSI command to queue
...@@ -647,12 +673,39 @@ static int __init aac_init(void) ...@@ -647,12 +673,39 @@ static int __init aac_init(void)
printk(KERN_WARNING printk(KERN_WARNING
"aacraid: unable to register \"aac\" device.\n"); "aacraid: unable to register \"aac\" device.\n");
} }
#ifdef CONFIG_COMPAT
register_ioctl32_conversion(FSACTL_MINIPORT_REV_CHECK, NULL);
register_ioctl32_conversion(FSACTL_SENDFIB, NULL);
register_ioctl32_conversion(FSACTL_OPEN_GET_ADAPTER_FIB, NULL);
register_ioctl32_conversion(FSACTL_GET_NEXT_ADAPTER_FIB,
aac_get_next_adapter_fib_ioctl);
register_ioctl32_conversion(FSACTL_CLOSE_GET_ADAPTER_FIB, NULL);
register_ioctl32_conversion(FSACTL_SEND_RAW_SRB, NULL);
register_ioctl32_conversion(FSACTL_GET_PCI_INFO, NULL);
register_ioctl32_conversion(FSACTL_QUERY_DISK, NULL);
register_ioctl32_conversion(FSACTL_DELETE_DISK, NULL);
register_ioctl32_conversion(FSACTL_FORCE_DELETE_DISK, NULL);
register_ioctl32_conversion(FSACTL_GET_CONTAINERS, NULL);
#endif
return 0; return 0;
} }
static void __exit aac_exit(void) static void __exit aac_exit(void)
{ {
#ifdef CONFIG_COMPAT
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(FSACTL_GET_CONTAINERS);
#endif
unregister_chrdev(aac_cfg_major, "aac"); unregister_chrdev(aac_cfg_major, "aac");
pci_unregister_driver(&aac_pci_driver); pci_unregister_driver(&aac_pci_driver);
} }
......
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