Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7c00ffa3 authored by Mark Haverkamp 's avatar Mark Haverkamp Committed by James Bottomley
Browse files

[SCSI] 2.6 aacraid: Variable FIB size (updated patch)



New code from the Adaptec driver.  Performance enhancement for newer
adapters.  I hope that this isn't too big for a single patch.  I believe
that other than the few small cleanups mentioned, that the changes are
all related.

- Added Variable FIB size negotiation for new adapters.
- Added support to maximize scatter gather tables and thus permit
  requests larger than 64KB/each.
- Limit Scatter Gather to 34 elements for ROMB platforms.
- aac_printf is only enabled with AAC_QUIRK_34SG
- Large FIB ioctl support
- some minor cleanup

Passes sparse check.
I have tested it on x86 and ppc64 machines.

Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 672b2d38
Loading
Loading
Loading
Loading
+95 −37
Original line number Diff line number Diff line
@@ -53,10 +53,6 @@
#define	INQD_PDT_DMASK	0x1F	/* Peripheral Device Type Mask */
#define	INQD_PDT_QMASK	0xE0	/* Peripheral Device Qualifer Mask */

#define MAX_FIB_DATA (sizeof(struct hw_fib) - sizeof(FIB_HEADER))

#define MAX_DRIVER_SG_SEGMENT_COUNT 17

/*
 *	Sense codes
 */
@@ -158,6 +154,13 @@ MODULE_PARM_DESC(dacmode, "Control whether dma addressing is using 64 bit DAC. 0
module_param(commit, int, 0);
MODULE_PARM_DESC(commit, "Control whether a COMMIT_CONFIG is issued to the adapter for foreign arrays.\nThis is typically needed in systems that do not have a BIOS. 0=off, 1=on");

int numacb = -1;
module_param(numacb, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(numacb, "Request a limit to the number of adapter control blocks (FIB) allocated. Valid\nvalues are 512 and down. Default is to use suggestion from Firmware.");

int acbsize = -1;
module_param(acbsize, int, S_IRUGO|S_IWUSR);
MODULE_PARM_DESC(acbsize, "Request a specific adapter control block (FIB) size. Valid values are 512,\n2048, 4096 and 8192. Default is to use suggestion from Firmware.");
/**
 *	aac_get_config_status	-	check the adapter configuration
 *	@common: adapter to query
@@ -462,7 +465,7 @@ static int probe_container(struct aac_dev *dev, int cid)
			    1, 1,
			    NULL, NULL);
	if (status < 0) {
		printk(KERN_WARNING "aacraid: probe_containers query failed.\n");
		printk(KERN_WARNING "aacraid: probe_container query failed.\n");
		goto error;
	}

@@ -605,35 +608,63 @@ static void set_sense(u8 *sense_buf, u8 sense_key, u8 sense_code,
int aac_get_adapter_info(struct aac_dev* dev)
{
	struct fib* fibptr;
	struct aac_adapter_info* info;
	int rcode;
	u32 tmp;
	struct aac_adapter_info * info;

	if (!(fibptr = fib_alloc(dev)))
		return -ENOMEM;

	fib_init(fibptr);
	info = (struct aac_adapter_info *) fib_data(fibptr);

	memset(info,0,sizeof(struct aac_adapter_info));
	memset(info,0,sizeof(*info));

	rcode = fib_send(RequestAdapterInfo,
			 fibptr, 
			sizeof(struct aac_adapter_info),
			 sizeof(*info),
			 FsaNormal, 
			 1, 1, 
			 NULL, 
			 NULL);

	memcpy(&dev->adapter_info, info, sizeof(struct aac_adapter_info));
	if (rcode < 0) {
		fib_complete(fibptr);
		fib_free(fibptr);
		return rcode;
	}
	memcpy(&dev->adapter_info, info, sizeof(*info));

	if (dev->adapter_info.options & AAC_OPT_SUPPLEMENT_ADAPTER_INFO) {
		struct aac_supplement_adapter_info * info;

		fib_init(fibptr);

		info = (struct aac_supplement_adapter_info *) fib_data(fibptr);

		memset(info,0,sizeof(*info));

		rcode = fib_send(RequestSupplementAdapterInfo,
				 fibptr,
				 sizeof(*info),
				 FsaNormal,
				 1, 1,
				 NULL,
				 NULL);

		if (rcode >= 0)
			memcpy(&dev->supplement_adapter_info, info, sizeof(*info));
	}

	tmp = le32_to_cpu(dev->adapter_info.kernelrev);
	printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d]\n", 
	printk(KERN_INFO "%s%d: kernel %d.%d-%d[%d] %.*s\n", 
			dev->name, 
			dev->id,
			tmp>>24,
			(tmp>>16)&0xff,
			tmp&0xff,
			le32_to_cpu(dev->adapter_info.kernelbuild));
			le32_to_cpu(dev->adapter_info.kernelbuild),
			(int)sizeof(dev->supplement_adapter_info.BuildDate),
			dev->supplement_adapter_info.BuildDate);
	tmp = le32_to_cpu(dev->adapter_info.monitorrev);
	printk(KERN_INFO "%s%d: monitor %d.%d-%d[%d]\n", 
			dev->name, dev->id,
@@ -707,6 +738,38 @@ int aac_get_adapter_info(struct aac_dev* dev)
			rcode = -ENOMEM;
		}
	}
	/* 
	 * 57 scatter gather elements 
	 */
	dev->scsi_host_ptr->sg_tablesize = (dev->max_fib_size -
		sizeof(struct aac_fibhdr) -
		sizeof(struct aac_write) + sizeof(struct sgmap)) /
			sizeof(struct sgmap);
	if (dev->dac_support) {
		/* 
		 * 38 scatter gather elements 
		 */
		dev->scsi_host_ptr->sg_tablesize =
			(dev->max_fib_size -
			sizeof(struct aac_fibhdr) -
			sizeof(struct aac_write64) +
			sizeof(struct sgmap64)) /
				sizeof(struct sgmap64);
	}
	dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
	if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
		/*
		 * Worst case size that could cause sg overflow when
		 * we break up SG elements that are larger than 64KB.
		 * Would be nice if we could tell the SCSI layer what
		 * the maximum SG element size can be. Worst case is
		 * (sg_tablesize-1) 4KB elements with one 64KB
		 * element.
		 *	32bit -> 468 or 238KB	64bit -> 424 or 212KB
		 */
		dev->scsi_host_ptr->max_sectors =
		  (dev->scsi_host_ptr->sg_tablesize * 8) + 112;
	}

	fib_complete(fibptr);
	fib_free(fibptr);
@@ -747,8 +810,10 @@ static void read_callback(void *context, struct fib * fibptr)
	if (le32_to_cpu(readreply->status) == ST_OK)
		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_GOOD;
	else {
		printk(KERN_WARNING "read_callback: read failed, status = %d\n",
#ifdef AAC_DETAILED_STATUS_INFO
		printk(KERN_WARNING "read_callback: io failed, status = %d\n",
		  le32_to_cpu(readreply->status));
#endif
		scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
		set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
				    HARDWARE_ERROR,
@@ -842,7 +907,8 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
		lba = (scsicmd->cmnd[2] << 24) | (scsicmd->cmnd[3] << 16) | (scsicmd->cmnd[4] << 8) | scsicmd->cmnd[5];
		count = (scsicmd->cmnd[7] << 8) | scsicmd->cmnd[8];
	}
	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n", smp_processor_id(), lba, jiffies));
	dprintk((KERN_DEBUG "aac_read[cpu %d]: lba = %u, t = %ld.\n",
	  smp_processor_id(), (unsigned long long)lba, jiffies));
	/*
	 *	Alocate and initialize a Fib
	 */
@@ -886,14 +952,11 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
		readcmd->block = cpu_to_le32(lba);
		readcmd->count = cpu_to_le32(count * 512);

		if (count * 512 > (64 * 1024))
			BUG();

		aac_build_sg(scsicmd, &readcmd->sg);
		fibsize = sizeof(struct aac_read) + 
			((le32_to_cpu(readcmd->sg.count) - 1) * 
			 sizeof (struct sgentry));
		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
		BUG_ON (fibsize > (dev->max_fib_size -
					sizeof(struct aac_fibhdr)));
		/*
		 *	Now send the Fib to the adapter
@@ -976,7 +1039,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
		fibsize = sizeof(struct aac_write64) + 
			((le32_to_cpu(writecmd->sg.count) - 1) * 
			 sizeof (struct sgentry64));
		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
		BUG_ON (fibsize > (dev->max_fib_size -
					sizeof(struct aac_fibhdr)));
		/*
		 *	Now send the Fib to the adapter
@@ -998,15 +1061,11 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
		writecmd->sg.count = cpu_to_le32(1);
		/* ->stable is not used - it did mean which type of write */

		if (count * 512 > (64 * 1024)) {
			BUG();
		}

		aac_build_sg(scsicmd, &writecmd->sg);
		fibsize = sizeof(struct aac_write) + 
			((le32_to_cpu(writecmd->sg.count) - 1) * 
			 sizeof (struct sgentry));
		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
		BUG_ON (fibsize > (dev->max_fib_size -
					sizeof(struct aac_fibhdr)));
		/*
		 *	Now send the Fib to the adapter
@@ -1025,7 +1084,6 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
	 */
	if (status == -EINPROGRESS)
	{
		dprintk("write queued.\n");
		return 0;
	}

@@ -1111,7 +1169,7 @@ static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
		return SCSI_MLQUEUE_DEVICE_BUSY;

	/*
	 *	Alocate and initialize a Fib
	 *	Allocate and initialize a Fib
	 */
	if (!(cmd_fibcontext = 
	    fib_alloc((struct aac_dev *)scsicmd->device->host->hostdata))) 
@@ -1403,7 +1461,7 @@ int aac_scsi_cmd(struct scsi_cmnd * scsicmd)
			/*
			 *	Unhandled commands
			 */
			printk(KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]);
			dprintk((KERN_WARNING "Unhandled SCSI Command: 0x%x.\n", scsicmd->cmnd[0]));
			scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_CHECK_CONDITION;
			set_sense((u8 *) &dev->fsa_dev[cid].sense_data,
				ILLEGAL_REQUEST, SENCODE_INVALID_COMMAND,
@@ -1818,7 +1876,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
		fibsize = sizeof (struct aac_srb) - sizeof (struct sgentry) +
			((le32_to_cpu(srbcmd->sg.count) & 0xff) * 
			 sizeof (struct sgentry64));
		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
		BUG_ON (fibsize > (dev->max_fib_size -
					sizeof(struct aac_fibhdr)));

		/*
@@ -1840,7 +1898,7 @@ static int aac_send_srb_fib(struct scsi_cmnd* scsicmd)
		fibsize = sizeof (struct aac_srb) + 
			(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 
			 sizeof (struct sgentry));
		BUG_ON (fibsize > (sizeof(struct hw_fib) - 
		BUG_ON (fibsize > (dev->max_fib_size -
					sizeof(struct aac_fibhdr)));

		/*
+58 −12
Original line number Diff line number Diff line
@@ -8,12 +8,18 @@

#define MAXIMUM_NUM_CONTAINERS	32

#define AAC_NUM_FIB		(256 + 64)
#define AAC_NUM_IO_FIB		100
#define AAC_NUM_MGT_FIB         8
#define AAC_NUM_IO_FIB		(512 - AAC_NUM_MGT_FIB)
#define AAC_NUM_FIB		(AAC_NUM_IO_FIB + AAC_NUM_MGT_FIB)

#define AAC_MAX_LUN		(8)

#define AAC_MAX_HOSTPHYSMEMPAGES (0xfffff)
/*
 *  max_sectors is an unsigned short, otherwise limit is 0x100000000 / 512
 * Linux has starvation problems if we permit larger than 4MB I/O ...
 */
#define AAC_MAX_32BIT_SGBCOUNT	((unsigned short)8192)

/*
 * These macros convert from physical channels to virtual channels
@@ -303,12 +309,9 @@ struct aac_fibhdr {
	} _u;
};

#define FIB_DATA_SIZE_IN_BYTES (512 - sizeof(struct aac_fibhdr))


struct hw_fib {
	struct aac_fibhdr header;
	u8 data[FIB_DATA_SIZE_IN_BYTES];		// Command specific data
	u8 data[512-sizeof(struct aac_fibhdr)];	// Command specific data
};

/*
@@ -370,11 +373,12 @@ struct hw_fib {
#define		RequestAdapterInfo		703
#define		IsAdapterPaused			704
#define		SendHostTime			705
#define		LastMiscCommand			706
#define		RequestSupplementAdapterInfo	706
#define		LastMiscCommand			707

//
// Commands that will target the failover level on the FSA adapter
//
/*
 * Commands that will target the failover level on the FSA adapter
 */

enum fib_xfer_state {
	HostOwned 			= (1<<0),
@@ -407,6 +411,7 @@ enum fib_xfer_state {
 */

#define ADAPTER_INIT_STRUCT_REVISION		3
#define ADAPTER_INIT_STRUCT_REVISION_4		4 // rocket science

struct aac_init
{
@@ -424,6 +429,14 @@ struct aac_init
	__le32	HostPhysMemPages;   /* number of 4k pages of host 
				       physical memory */
	__le32	HostElapsedSeconds; /* number of seconds since 1970. */
	/*
	 * ADAPTER_INIT_STRUCT_REVISION_4 begins here
	 */
	__le32	InitFlags;	/* flags for supported features */
#define INITFLAGS_NEW_COMM_SUPPORTED	0x00000001
	__le32	MaxIoCommands;	/* max outstanding commands */
	__le32	MaxIoSize;	/* largest I/O command */
	__le32	MaxFibSize;	/* largest FIB to adapter */
};

enum aac_log_level {
@@ -447,7 +460,7 @@ struct adapter_ops
{
	void (*adapter_interrupt)(struct aac_dev *dev);
	void (*adapter_notify)(struct aac_dev *dev, u32 event);
	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 *status);
	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
	int  (*adapter_check_health)(struct aac_dev *dev);
};

@@ -567,6 +580,7 @@ struct sa_drawbridge_CSR {
#define Mailbox3	SaDbCSR.MAILBOX3
#define Mailbox4	SaDbCSR.MAILBOX4
#define Mailbox5	SaDbCSR.MAILBOX5
#define Mailbox6	SaDbCSR.MAILBOX6
#define Mailbox7	SaDbCSR.MAILBOX7
	
#define DoorbellReg_p SaDbCSR.PRISETIRQ
@@ -812,6 +826,25 @@ struct aac_adapter_info
	__le32	OEM;
};

struct aac_supplement_adapter_info
{
	u8	AdapterTypeText[17+1];
	u8	Pad[2];
	__le32	FlashMemoryByteSize;
	__le32	FlashImageId;
	__le32	MaxNumberPorts;
	__le32	Version;
	__le32	FeatureBits;
	u8	SlotNumber;
	u8	ReservedPad0[0];
	u8	BuildDate[12];
	__le32	CurrentNumberPorts;
	__le32	ReservedGrowth[24];
};
#define AAC_FEATURE_FALCON	0x00000010
#define AAC_SIS_VERSION_V3	3
#define AAC_SIS_SLOT_UNKNOWN	0xFF

/*
 * Battery platforms
 */
@@ -856,6 +889,12 @@ struct aac_dev
	int			id;

	u16			irq_mask;
	/*
	 *	negotiated FIB settings
	 */
	unsigned		max_fib_size;
	unsigned		sg_tablesize;

	/*
	 *	Map for 128 fib objects (64k)
	 */	
@@ -915,12 +954,14 @@ struct aac_dev
	u32			aif_thread;
	struct completion	aif_completion;
	struct aac_adapter_info adapter_info;
	struct aac_supplement_adapter_info supplement_adapter_info;
	/* 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			dac_support;
	u8			raid_scsi_mode;
	u8			printf_enabled;
};

#define aac_adapter_interrupt(dev) \
@@ -929,6 +970,8 @@ struct aac_dev
#define aac_adapter_notify(dev, event) \
	(dev)->a_ops.adapter_notify(dev, event)

#define aac_adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4) \
	(dev)->a_ops.adapter_sync_cmd(dev, command, p1, p2, p3, p4, p5, p6, status, r1, r2, r3, r4)

#define aac_adapter_check_health(dev) \
	(dev)->a_ops.adapter_check_health(dev)
@@ -1327,7 +1370,7 @@ struct aac_commit_config {
};

/*
 *	Query for Container Configuration Count
 *	Query for Container Configuration Status
 */

#define CT_GET_CONTAINER_COUNT 4
@@ -1481,6 +1524,7 @@ struct revision
#define FSACTL_GET_PCI_INFO               	CTL_CODE(2119, METHOD_BUFFERED)
#define FSACTL_FORCE_DELETE_DISK		CTL_CODE(2120, METHOD_NEITHER)
#define FSACTL_GET_CONTAINERS			2131
#define FSACTL_SEND_LARGE_FIB			CTL_CODE(2138, METHOD_BUFFERED)


struct aac_common
@@ -1667,3 +1711,5 @@ int fib_adapter_complete(struct fib * fibptr, unsigned short size);
struct aac_driver_ident* aac_get_driver_ident(int devtype);
int aac_get_adapter_info(struct aac_dev* dev);
int aac_send_shutdown(struct aac_dev *dev);
extern int numacb;
extern int acbsize;
+115 −65
Original line number Diff line number Diff line
@@ -51,15 +51,22 @@
 *	This routine sends a fib to the adapter on behalf of a user level
 *	program.
 */
# define AAC_DEBUG_PREAMBLE	KERN_INFO
# define AAC_DEBUG_POSTAMBLE
 
static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
{
	struct hw_fib * kfib;
	struct fib *fibptr;
	struct hw_fib * hw_fib = (struct hw_fib *)0;
	dma_addr_t hw_fib_pa = (dma_addr_t)0LL;
	unsigned size;
	int retval;

	fibptr = fib_alloc(dev);
	if(fibptr == NULL)
	if(fibptr == NULL) {
		return -ENOMEM;
	}
		
	kfib = fibptr->hw_fib;
	/*
@@ -74,16 +81,21 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
	 *	will not overrun the buffer when we copy the memory. Return
	 *	an error if we would.
	 */
	if (le16_to_cpu(kfib->header.Size) > 
			sizeof(struct hw_fib) - sizeof(struct aac_fibhdr)) {
		fib_free(fibptr);
		return -EINVAL;
	}

	if (copy_from_user(kfib, arg, le16_to_cpu(kfib->header.Size) +
				sizeof(struct aac_fibhdr))) {
		fib_free(fibptr);
		return -EFAULT;
	size = le16_to_cpu(kfib->header.Size) + sizeof(struct aac_fibhdr);
	if (size < le16_to_cpu(kfib->header.SenderSize))
		size = le16_to_cpu(kfib->header.SenderSize);
	if (size > dev->max_fib_size) {
		/* Highjack the hw_fib */
		hw_fib = fibptr->hw_fib;
		hw_fib_pa = fibptr->hw_fib_pa;
		fibptr->hw_fib = kfib = pci_alloc_consistent(dev->pdev, size, &fibptr->hw_fib_pa);
		memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);
		memcpy(kfib, hw_fib, dev->max_fib_size);
	}

	if (copy_from_user(kfib, arg, size)) {
		retval = -EFAULT;
		goto cleanup;
	}

	if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {
@@ -94,16 +106,15 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
		 */
		kfib->header.XferState = 0;
	} else {
		int retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
		retval = fib_send(le16_to_cpu(kfib->header.Command), fibptr,
				le16_to_cpu(kfib->header.Size) , FsaNormal,
				1, 1, NULL, NULL);
		if (retval) {
			fib_free(fibptr);
			return retval;
			goto cleanup;
		}
		if (fib_complete(fibptr) != 0) {
			fib_free(fibptr);
			return -EINVAL;
			retval = -EINVAL;
			goto cleanup;
		}
	}
	/*
@@ -114,12 +125,17 @@ static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)
	 *	was already included by the adapter.)
	 */

	if (copy_to_user(arg, (void *)kfib, le16_to_cpu(kfib->header.Size))) {
		fib_free(fibptr);
		return -EFAULT;
	retval = 0;
	if (copy_to_user(arg, (void *)kfib, size))
		retval = -EFAULT;
cleanup:
	if (hw_fib) {
		pci_free_consistent(dev->pdev, size, kfib, fibptr->hw_fib_pa);
		fibptr->hw_fib_pa = hw_fib_pa;
		fibptr->hw_fib = hw_fib;
	}
	fib_free(fibptr);
	return 0;
	return retval;
}

/**
@@ -399,6 +415,7 @@ static int check_revision(struct aac_dev *dev, void __user *arg)
	return 0;
}


/**
 *
 * aac_send_raw_scb
@@ -427,7 +444,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)


	if (!capable(CAP_SYS_ADMIN)){
		printk(KERN_DEBUG"aacraid: No permission to send raw srb\n"); 
		dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n")); 
		return -EPERM;
	}
	/*
@@ -440,20 +457,26 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)

	srbcmd = (struct aac_srb*) fib_data(srbfib);

	memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
	if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
		printk(KERN_DEBUG"aacraid: Could not copy data size from user\n"); 
		dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n")); 
		rcode = -EFAULT;
		goto cleanup;
	}

	if (fibsize > FIB_DATA_SIZE_IN_BYTES) {
	if (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr))) {
		rcode = -EINVAL;
		goto cleanup;
	}

	user_srbcmd = kmalloc(GFP_KERNEL, fibsize);
	if (!user_srbcmd) {
		dprintk((KERN_DEBUG"aacraid: Could not make a copy of the srb\n"));
		rcode = -ENOMEM;
		goto cleanup;
	}
	if(copy_from_user(user_srbcmd, user_srb,fibsize)){
		printk(KERN_DEBUG"aacraid: Could not copy srb from user\n"); 
		dprintk((KERN_DEBUG"aacraid: Could not copy srb from user\n")); 
		rcode = -EFAULT;
		goto cleanup;
	}
@@ -467,9 +490,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
	srbcmd->channel  = cpu_to_le32(user_srbcmd->channel);
	srbcmd->id	 = cpu_to_le32(user_srbcmd->id);
	srbcmd->lun      = cpu_to_le32(user_srbcmd->lun);
	srbcmd->flags = cpu_to_le32(user_srbcmd->flags);
	srbcmd->flags    = cpu_to_le32(flags);
	srbcmd->timeout  = cpu_to_le32(user_srbcmd->timeout);
	srbcmd->retry_limit = 0; 
	srbcmd->retry_limit =cpu_to_le32(0); // Obsolete parameter
	srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
	
	switch (flags & (SRB_DataIn | SRB_DataOut)) {
@@ -485,9 +508,16 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
	default:
		data_dir = DMA_NONE;
	}
	if (le32_to_cpu(srbcmd->sg.count) > (sizeof(sg_list)/sizeof(sg_list[0]))) {
		dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
		  le32_to_cpu(srbcmd->sg.count)));
		rcode = -EINVAL;
		goto cleanup;
	}
	if (dev->dac_support == 1) {
		struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
		struct sgmap64* psg = (struct sgmap64*)&user_srbcmd->sg;
		struct user_sgmap* usg;
		byte_count = 0;

		/*
@@ -495,65 +525,81 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
		 */
		actual_fibsize = sizeof(struct aac_srb) - 
			sizeof(struct sgentry) +
			((user_srbcmd->sg.count & 0xff) * 
		 	sizeof(struct sgentry64));
			((upsg->count & 0xff) * 
		 	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");
			dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
			rcode = -EINVAL;
			goto cleanup;
		}
		usg = kmalloc(actual_fibsize - sizeof(struct aac_srb)
		  + sizeof(struct sgmap), GFP_KERNEL);
		if (!usg) {
			dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));
			rcode = -ENOMEM;
			goto cleanup;
		}
		memcpy (usg, upsg, actual_fibsize - sizeof(struct aac_srb)
		  + sizeof(struct sgmap));
		actual_fibsize = sizeof(struct aac_srb) - 
			sizeof(struct sgentry) + ((usg->count & 0xff) * 
			 	sizeof(struct sgentry64));
		if ((data_dir == DMA_NONE) && upsg->count) {
			printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
			kfree (usg);
			dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
			rcode = -EINVAL;
			goto cleanup;
		}

		for (i = 0; i < upsg->count; i++) {
		for (i = 0; i < usg->count; i++) {
			u64 addr;
			void* p;
			p = kmalloc(upsg->sg[i].count, GFP_KERNEL|__GFP_DMA);
			/* Does this really need to be GFP_DMA? */
			p = kmalloc(usg->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",
				upsg->sg[i].count,i,upsg->count);
				kfree (usg);
				dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
				  usg->sg[i].count,i,usg->count));
				rcode = -ENOMEM;
				goto cleanup;
			}
			sg_user[i] = (void __user *)upsg->sg[i].addr;
			sg_user[i] = (void __user *)usg->sg[i].addr;
			sg_list[i] = p; // save so we can clean up later
			sg_indx = i;

			if( flags & SRB_DataOut ){
				if(copy_from_user(p,sg_user[i],upsg->sg[i].count)){
					printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); 
					kfree (usg);
					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
					rcode = -EFAULT;
					goto cleanup;
				}
			}
			addr = pci_map_single(dev->pdev, p, upsg->sg[i].count, data_dir);
			addr = pci_map_single(dev->pdev, p, usg->sg[i].count, data_dir);

			psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
			psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
			psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);  
			byte_count += upsg->sg[i].count;
			psg->sg[i].count = cpu_to_le32(usg->sg[i].count);  
			byte_count += usg->sg[i].count;
		}
		kfree (usg);

		srbcmd->count = cpu_to_le32(byte_count);
		psg->count = cpu_to_le32(sg_indx+1);
		status = fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);
	} else {
		struct user_sgmap* upsg = &user_srbcmd->sg;
		struct sgmap* psg = &srbcmd->sg;
		byte_count = 0;

		actual_fibsize = sizeof (struct aac_srb) + 
			(((le32_to_cpu(srbcmd->sg.count) & 0xff) - 1) * 
			 sizeof (struct sgentry));
		actual_fibsize = sizeof (struct aac_srb) + (((le32_to_cpu(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");
			dprintk((KERN_DEBUG"aacraid: Bad Size specified in Raw SRB command\n"));
			rcode = -EINVAL;
			goto cleanup;
		}
		if ((data_dir == DMA_NONE) && upsg->count) {
			printk(KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n");
			dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
			rcode = -EINVAL;
			goto cleanup;
		}
@@ -562,8 +608,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
			void* p;
			p = kmalloc(upsg->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",
				upsg->sg[i].count, i, upsg->count);
				dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
				  upsg->sg[i].count, i, upsg->count));
				rcode = -ENOMEM;
				goto cleanup;
			}
@@ -574,7 +620,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
			if( flags & SRB_DataOut ){
				if(copy_from_user(p, sg_user[i],
						upsg->sg[i].count)) {
					printk(KERN_DEBUG"aacraid: Could not copy sg data from user\n"); 
					dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n")); 
					rcode = -EFAULT;
					goto cleanup;
				}
@@ -587,19 +633,23 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
			byte_count += upsg->sg[i].count;
		}
		srbcmd->count = cpu_to_le32(byte_count);
		psg->count = cpu_to_le32(sg_indx+1);
		status = fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
	}

	if (status != 0){
		printk(KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"); 
		dprintk((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(sg_user[i],sg_list[i],le32_to_cpu(srbcmd->sg.sg[i].count))){
				printk(KERN_DEBUG"aacraid: Could not copy sg data to user\n"); 
			byte_count = le32_to_cpu((dev->dac_support == 1)
			      ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
			      : srbcmd->sg.sg[i].count);
			if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
				dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n")); 
				rcode = -EFAULT;
				goto cleanup;

@@ -609,7 +659,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)

	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"); 
		dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n")); 
		rcode = -EFAULT;
		goto cleanup;
	}
@@ -625,7 +675,6 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
	return rcode;
}


struct aac_pci_info {
        u32 bus;
        u32 slot;
@@ -640,7 +689,7 @@ static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)
	pci_info.slot = PCI_SLOT(dev->pdev->devfn);

       if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {
		printk(KERN_DEBUG "aacraid: Could not copy pci info\n");
               dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));
               return -EFAULT;
	}
        return 0;
@@ -663,6 +712,7 @@ int aac_do_ioctl(struct aac_dev * dev, int cmd, void __user *arg)
	case FSACTL_MINIPORT_REV_CHECK:
		status = check_revision(dev, arg);
		break;
	case FSACTL_SEND_LARGE_FIB:
	case FSACTL_SENDFIB:
		status = ioctl_send_fib(dev, arg);
		break;
+84 −2

File changed.

Preview size limit exceeded, changes collapsed.

+50 −35

File changed.

Preview size limit exceeded, changes collapsed.

Loading