brintos

brintos / linux-shallow public Read only

0
0
Text · 28.8 KiB · 68240d6 Raw
1122 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 *	Adaptec AAC series RAID controller driver4 *	(c) Copyright 2001 Red Hat Inc.5 *6 * based on the old aacraid driver that is..7 * Adaptec aacraid device driver for Linux.8 *9 * Copyright (c) 2000-2010 Adaptec, Inc.10 *               2010-2015 PMC-Sierra, Inc. (aacraid@pmc-sierra.com)11 *		 2016-2017 Microsemi Corp. (aacraid@microsemi.com)12 *13 * Module Name:14 *  commctrl.c15 *16 * Abstract: Contains all routines for control of the AFA comm layer17 */18 19#include <linux/kernel.h>20#include <linux/init.h>21#include <linux/types.h>22#include <linux/pci.h>23#include <linux/spinlock.h>24#include <linux/slab.h>25#include <linux/completion.h>26#include <linux/dma-mapping.h>27#include <linux/blkdev.h>28#include <linux/compat.h>29#include <linux/delay.h> /* ssleep prototype */30#include <linux/kthread.h>31#include <linux/uaccess.h>32#include <scsi/scsi_host.h>33 34#include "aacraid.h"35 36# define AAC_DEBUG_PREAMBLE	KERN_INFO37# define AAC_DEBUG_POSTAMBLE38/**39 *	ioctl_send_fib	-	send a FIB from userspace40 *	@dev:	adapter is being processed41 *	@arg:	arguments to the ioctl call42 *43 *	This routine sends a fib to the adapter on behalf of a user level44 *	program.45 */46static int ioctl_send_fib(struct aac_dev * dev, void __user *arg)47{48	struct hw_fib * kfib;49	struct fib *fibptr;50	struct hw_fib * hw_fib = (struct hw_fib *)0;51	dma_addr_t hw_fib_pa = (dma_addr_t)0LL;52	unsigned int size, osize;53	int retval;54 55	if (dev->in_reset) {56		return -EBUSY;57	}58	fibptr = aac_fib_alloc(dev);59	if(fibptr == NULL) {60		return -ENOMEM;61	}62 63	kfib = fibptr->hw_fib_va;64	/*65	 *	First copy in the header so that we can check the size field.66	 */67	if (copy_from_user((void *)kfib, arg, sizeof(struct aac_fibhdr))) {68		aac_fib_free(fibptr);69		return -EFAULT;70	}71	/*72	 *	Since we copy based on the fib header size, make sure that we73	 *	will not overrun the buffer when we copy the memory. Return74	 *	an error if we would.75	 */76	osize = size = le16_to_cpu(kfib->header.Size) +77		sizeof(struct aac_fibhdr);78	if (size < le16_to_cpu(kfib->header.SenderSize))79		size = le16_to_cpu(kfib->header.SenderSize);80	if (size > dev->max_fib_size) {81		dma_addr_t daddr;82 83		if (size > 2048) {84			retval = -EINVAL;85			goto cleanup;86		}87 88		kfib = dma_alloc_coherent(&dev->pdev->dev, size, &daddr,89					  GFP_KERNEL);90		if (!kfib) {91			retval = -ENOMEM;92			goto cleanup;93		}94 95		/* Highjack the hw_fib */96		hw_fib = fibptr->hw_fib_va;97		hw_fib_pa = fibptr->hw_fib_pa;98		fibptr->hw_fib_va = kfib;99		fibptr->hw_fib_pa = daddr;100		memset(((char *)kfib) + dev->max_fib_size, 0, size - dev->max_fib_size);101		memcpy(kfib, hw_fib, dev->max_fib_size);102	}103 104	if (copy_from_user(kfib, arg, size)) {105		retval = -EFAULT;106		goto cleanup;107	}108 109	/* Sanity check the second copy */110	if ((osize != le16_to_cpu(kfib->header.Size) +111		sizeof(struct aac_fibhdr))112		|| (size < le16_to_cpu(kfib->header.SenderSize))) {113		retval = -EINVAL;114		goto cleanup;115	}116 117	if (kfib->header.Command == cpu_to_le16(TakeABreakPt)) {118		aac_adapter_interrupt(dev);119		/*120		 * Since we didn't really send a fib, zero out the state to allow121		 * cleanup code not to assert.122		 */123		kfib->header.XferState = 0;124	} else {125		retval = aac_fib_send(le16_to_cpu(kfib->header.Command), fibptr,126				le16_to_cpu(kfib->header.Size) , FsaNormal,127				1, 1, NULL, NULL);128		if (retval) {129			goto cleanup;130		}131		if (aac_fib_complete(fibptr) != 0) {132			retval = -EINVAL;133			goto cleanup;134		}135	}136	/*137	 *	Make sure that the size returned by the adapter (which includes138	 *	the header) is less than or equal to the size of a fib, so we139	 *	don't corrupt application data. Then copy that size to the user140	 *	buffer. (Don't try to add the header information again, since it141	 *	was already included by the adapter.)142	 */143 144	retval = 0;145	if (copy_to_user(arg, (void *)kfib, size))146		retval = -EFAULT;147cleanup:148	if (hw_fib) {149		dma_free_coherent(&dev->pdev->dev, size, kfib,150				  fibptr->hw_fib_pa);151		fibptr->hw_fib_pa = hw_fib_pa;152		fibptr->hw_fib_va = hw_fib;153	}154	if (retval != -ERESTARTSYS)155		aac_fib_free(fibptr);156	return retval;157}158 159/**160 *	open_getadapter_fib	-	Get the next fib161 *	@dev:	adapter is being processed162 *	@arg:	arguments to the open call163 *164 *	This routine will get the next Fib, if available, from the AdapterFibContext165 *	passed in from the user.166 */167static int open_getadapter_fib(struct aac_dev * dev, void __user *arg)168{169	struct aac_fib_context * fibctx;170	int status;171 172	fibctx = kmalloc(sizeof(struct aac_fib_context), GFP_KERNEL);173	if (fibctx == NULL) {174		status = -ENOMEM;175	} else {176		unsigned long flags;177		struct list_head * entry;178		struct aac_fib_context * context;179 180		fibctx->type = FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT;181		fibctx->size = sizeof(struct aac_fib_context);182		/*183		 *	Yes yes, I know this could be an index, but we have a184		 * better guarantee of uniqueness for the locked loop below.185		 * Without the aid of a persistent history, this also helps186		 * reduce the chance that the opaque context would be reused.187		 */188		fibctx->unique = (u32)((ulong)fibctx & 0xFFFFFFFF);189		/*190		 *	Initialize the mutex used to wait for the next AIF.191		 */192		init_completion(&fibctx->completion);193		fibctx->wait = 0;194		/*195		 *	Initialize the fibs and set the count of fibs on196		 *	the list to 0.197		 */198		fibctx->count = 0;199		INIT_LIST_HEAD(&fibctx->fib_list);200		fibctx->jiffies = jiffies/HZ;201		/*202		 *	Now add this context onto the adapter's203		 *	AdapterFibContext list.204		 */205		spin_lock_irqsave(&dev->fib_lock, flags);206		/* Ensure that we have a unique identifier */207		entry = dev->fib_list.next;208		while (entry != &dev->fib_list) {209			context = list_entry(entry, struct aac_fib_context, next);210			if (context->unique == fibctx->unique) {211				/* Not unique (32 bits) */212				fibctx->unique++;213				entry = dev->fib_list.next;214			} else {215				entry = entry->next;216			}217		}218		list_add_tail(&fibctx->next, &dev->fib_list);219		spin_unlock_irqrestore(&dev->fib_lock, flags);220		if (copy_to_user(arg, &fibctx->unique,221						sizeof(fibctx->unique))) {222			status = -EFAULT;223		} else {224			status = 0;225		}226	}227	return status;228}229 230struct compat_fib_ioctl {231	u32	fibctx;232	s32	wait;233	compat_uptr_t fib;234};235 236/**237 *	next_getadapter_fib	-	get the next fib238 *	@dev: adapter to use239 *	@arg: ioctl argument240 *241 *	This routine will get the next Fib, if available, from the AdapterFibContext242 *	passed in from the user.243 */244static int next_getadapter_fib(struct aac_dev * dev, void __user *arg)245{246	struct fib_ioctl f;247	struct fib *fib;248	struct aac_fib_context *fibctx;249	int status;250	struct list_head * entry;251	unsigned long flags;252 253	if (in_compat_syscall()) {254		struct compat_fib_ioctl cf;255 256		if (copy_from_user(&cf, arg, sizeof(struct compat_fib_ioctl)))257			return -EFAULT;258 259		f.fibctx = cf.fibctx;260		f.wait = cf.wait;261		f.fib = compat_ptr(cf.fib);262	} else {263		if (copy_from_user(&f, arg, sizeof(struct fib_ioctl)))264			return -EFAULT;265	}266	/*267	 *	Verify that the HANDLE passed in was a valid AdapterFibContext268	 *269	 *	Search the list of AdapterFibContext addresses on the adapter270	 *	to be sure this is a valid address271	 */272	spin_lock_irqsave(&dev->fib_lock, flags);273	entry = dev->fib_list.next;274	fibctx = NULL;275 276	while (entry != &dev->fib_list) {277		fibctx = list_entry(entry, struct aac_fib_context, next);278		/*279		 *	Extract the AdapterFibContext from the Input parameters.280		 */281		if (fibctx->unique == f.fibctx) { /* We found a winner */282			break;283		}284		entry = entry->next;285		fibctx = NULL;286	}287	if (!fibctx) {288		spin_unlock_irqrestore(&dev->fib_lock, flags);289		dprintk ((KERN_INFO "Fib Context not found\n"));290		return -EINVAL;291	}292 293	if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||294		 (fibctx->size != sizeof(struct aac_fib_context))) {295		spin_unlock_irqrestore(&dev->fib_lock, flags);296		dprintk ((KERN_INFO "Fib Context corrupt?\n"));297		return -EINVAL;298	}299	status = 0;300	/*301	 *	If there are no fibs to send back, then either wait or return302	 *	-EAGAIN303	 */304return_fib:305	if (!list_empty(&fibctx->fib_list)) {306		/*307		 *	Pull the next fib from the fibs308		 */309		entry = fibctx->fib_list.next;310		list_del(entry);311 312		fib = list_entry(entry, struct fib, fiblink);313		fibctx->count--;314		spin_unlock_irqrestore(&dev->fib_lock, flags);315		if (copy_to_user(f.fib, fib->hw_fib_va, sizeof(struct hw_fib))) {316			kfree(fib->hw_fib_va);317			kfree(fib);318			return -EFAULT;319		}320		/*321		 *	Free the space occupied by this copy of the fib.322		 */323		kfree(fib->hw_fib_va);324		kfree(fib);325		status = 0;326	} else {327		spin_unlock_irqrestore(&dev->fib_lock, flags);328		/* If someone killed the AIF aacraid thread, restart it */329		status = !dev->aif_thread;330		if (status && !dev->in_reset && dev->queues && dev->fsa_dev) {331			/* Be paranoid, be very paranoid! */332			kthread_stop(dev->thread);333			ssleep(1);334			dev->aif_thread = 0;335			dev->thread = kthread_run(aac_command_thread, dev,336						  "%s", dev->name);337			ssleep(1);338		}339		if (f.wait) {340			if (wait_for_completion_interruptible(&fibctx->completion) < 0) {341				status = -ERESTARTSYS;342			} else {343				/* Lock again and retry */344				spin_lock_irqsave(&dev->fib_lock, flags);345				goto return_fib;346			}347		} else {348			status = -EAGAIN;349		}350	}351	fibctx->jiffies = jiffies/HZ;352	return status;353}354 355int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context * fibctx)356{357	struct fib *fib;358 359	/*360	 *	First free any FIBs that have not been consumed.361	 */362	while (!list_empty(&fibctx->fib_list)) {363		struct list_head * entry;364		/*365		 *	Pull the next fib from the fibs366		 */367		entry = fibctx->fib_list.next;368		list_del(entry);369		fib = list_entry(entry, struct fib, fiblink);370		fibctx->count--;371		/*372		 *	Free the space occupied by this copy of the fib.373		 */374		kfree(fib->hw_fib_va);375		kfree(fib);376	}377	/*378	 *	Remove the Context from the AdapterFibContext List379	 */380	list_del(&fibctx->next);381	/*382	 *	Invalidate context383	 */384	fibctx->type = 0;385	/*386	 *	Free the space occupied by the Context387	 */388	kfree(fibctx);389	return 0;390}391 392/**393 *	close_getadapter_fib	-	close down user fib context394 *	@dev: adapter395 *	@arg: ioctl arguments396 *397 *	This routine will close down the fibctx passed in from the user.398 */399 400static int close_getadapter_fib(struct aac_dev * dev, void __user *arg)401{402	struct aac_fib_context *fibctx;403	int status;404	unsigned long flags;405	struct list_head * entry;406 407	/*408	 *	Verify that the HANDLE passed in was a valid AdapterFibContext409	 *410	 *	Search the list of AdapterFibContext addresses on the adapter411	 *	to be sure this is a valid address412	 */413 414	entry = dev->fib_list.next;415	fibctx = NULL;416 417	while(entry != &dev->fib_list) {418		fibctx = list_entry(entry, struct aac_fib_context, next);419		/*420		 *	Extract the fibctx from the input parameters421		 */422		if (fibctx->unique == (u32)(uintptr_t)arg) /* We found a winner */423			break;424		entry = entry->next;425		fibctx = NULL;426	}427 428	if (!fibctx)429		return 0; /* Already gone */430 431	if((fibctx->type != FSAFS_NTC_GET_ADAPTER_FIB_CONTEXT) ||432		 (fibctx->size != sizeof(struct aac_fib_context)))433		return -EINVAL;434	spin_lock_irqsave(&dev->fib_lock, flags);435	status = aac_close_fib_context(dev, fibctx);436	spin_unlock_irqrestore(&dev->fib_lock, flags);437	return status;438}439 440/**441 *	check_revision	-	close down user fib context442 *	@dev: adapter443 *	@arg: ioctl arguments444 *445 *	This routine returns the driver version.446 *	Under Linux, there have been no version incompatibilities, so this is447 *	simple!448 */449 450static int check_revision(struct aac_dev *dev, void __user *arg)451{452	struct revision response;453	char *driver_version = aac_driver_version;454	u32 version;455 456	response.compat = 1;457	version = (simple_strtol(driver_version,458				&driver_version, 10) << 24) | 0x00000400;459	version += simple_strtol(driver_version + 1, &driver_version, 10) << 16;460	version += simple_strtol(driver_version + 1, NULL, 10);461	response.version = cpu_to_le32(version);462#	ifdef AAC_DRIVER_BUILD463		response.build = cpu_to_le32(AAC_DRIVER_BUILD);464#	else465		response.build = cpu_to_le32(9999);466#	endif467 468	if (copy_to_user(arg, &response, sizeof(response)))469		return -EFAULT;470	return 0;471}472 473 474/**475 * aac_send_raw_srb()476 *	@dev:	adapter is being processed477 *	@arg:	arguments to the send call478 */479static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)480{481	struct fib* srbfib;482	int status;483	struct aac_srb *srbcmd = NULL;484	struct aac_hba_cmd_req *hbacmd = NULL;485	struct user_aac_srb *user_srbcmd = NULL;486	struct user_aac_srb __user *user_srb = arg;487	struct aac_srb_reply __user *user_reply;488	u32 chn;489	u32 fibsize = 0;490	u32 flags = 0;491	s32 rcode = 0;492	u32 data_dir;493	void __user *sg_user[HBA_MAX_SG_EMBEDDED];494	void *sg_list[HBA_MAX_SG_EMBEDDED];495	u32 sg_count[HBA_MAX_SG_EMBEDDED];496	u32 sg_indx = 0;497	u32 byte_count = 0;498	u32 actual_fibsize64, actual_fibsize = 0;499	int i;500	int is_native_device;501	u64 address;502 503 504	if (dev->in_reset) {505		dprintk((KERN_DEBUG"aacraid: send raw srb -EBUSY\n"));506		return -EBUSY;507	}508	if (!capable(CAP_SYS_ADMIN)){509		dprintk((KERN_DEBUG"aacraid: No permission to send raw srb\n"));510		return -EPERM;511	}512	/*513	 *	Allocate and initialize a Fib then setup a SRB command514	 */515	if (!(srbfib = aac_fib_alloc(dev))) {516		return -ENOMEM;517	}518 519	memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */520	if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){521		dprintk((KERN_DEBUG"aacraid: Could not copy data size from user\n"));522		rcode = -EFAULT;523		goto cleanup;524	}525 526	if ((fibsize < sizeof(struct user_aac_srb)) ||527	    (fibsize > (dev->max_fib_size - sizeof(struct aac_fibhdr)))) {528		rcode = -EINVAL;529		goto cleanup;530	}531 532	user_srbcmd = memdup_user(user_srb, fibsize);533	if (IS_ERR(user_srbcmd)) {534		rcode = PTR_ERR(user_srbcmd);535		user_srbcmd = NULL;536		goto cleanup;537	}538 539	flags = user_srbcmd->flags; /* from user in cpu order */540	switch (flags & (SRB_DataIn | SRB_DataOut)) {541	case SRB_DataOut:542		data_dir = DMA_TO_DEVICE;543		break;544	case (SRB_DataIn | SRB_DataOut):545		data_dir = DMA_BIDIRECTIONAL;546		break;547	case SRB_DataIn:548		data_dir = DMA_FROM_DEVICE;549		break;550	default:551		data_dir = DMA_NONE;552	}553	if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) {554		dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",555			user_srbcmd->sg.count));556		rcode = -EINVAL;557		goto cleanup;558	}559	if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {560		dprintk((KERN_DEBUG"aacraid:SG with no direction specified\n"));561		rcode = -EINVAL;562		goto cleanup;563	}564	actual_fibsize = sizeof(struct aac_srb) +565		((user_srbcmd->sg.count & 0xff) * sizeof(struct sgentry));566	actual_fibsize64 = actual_fibsize + (user_srbcmd->sg.count & 0xff) *567	  (sizeof(struct sgentry64) - sizeof(struct sgentry));568	/* User made a mistake - should not continue */569	if ((actual_fibsize != fibsize) && (actual_fibsize64 != fibsize)) {570		dprintk((KERN_DEBUG"aacraid: Bad Size specified in "571		  "Raw SRB command calculated fibsize=%lu;%lu "572		  "user_srbcmd->sg.count=%d aac_srb=%lu sgentry=%lu;%lu "573		  "issued fibsize=%d\n",574		  actual_fibsize, actual_fibsize64, user_srbcmd->sg.count,575		  sizeof(struct aac_srb), sizeof(struct sgentry),576		  sizeof(struct sgentry64), fibsize));577		rcode = -EINVAL;578		goto cleanup;579	}580 581	chn = user_srbcmd->channel;582	if (chn < AAC_MAX_BUSES && user_srbcmd->id < AAC_MAX_TARGETS &&583		dev->hba_map[chn][user_srbcmd->id].devtype ==584		AAC_DEVTYPE_NATIVE_RAW) {585		is_native_device = 1;586		hbacmd = (struct aac_hba_cmd_req *)srbfib->hw_fib_va;587		memset(hbacmd, 0, 96);	/* sizeof(*hbacmd) is not necessary */588 589		/* iu_type is a parameter of aac_hba_send */590		switch (data_dir) {591		case DMA_TO_DEVICE:592			hbacmd->byte1 = 2;593			break;594		case DMA_FROM_DEVICE:595		case DMA_BIDIRECTIONAL:596			hbacmd->byte1 = 1;597			break;598		case DMA_NONE:599		default:600			break;601		}602		hbacmd->lun[1] = cpu_to_le32(user_srbcmd->lun);603		hbacmd->it_nexus = dev->hba_map[chn][user_srbcmd->id].rmw_nexus;604 605		/*606		 * we fill in reply_qid later in aac_src_deliver_message607		 * we fill in iu_type, request_id later in aac_hba_send608		 * we fill in emb_data_desc_count, data_length later609		 * in sg list build610		 */611 612		memcpy(hbacmd->cdb, user_srbcmd->cdb, sizeof(hbacmd->cdb));613 614		address = (u64)srbfib->hw_error_pa;615		hbacmd->error_ptr_hi = cpu_to_le32((u32)(address >> 32));616		hbacmd->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff));617		hbacmd->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);618		hbacmd->emb_data_desc_count =619					cpu_to_le32(user_srbcmd->sg.count);620		srbfib->hbacmd_size = 64 +621			user_srbcmd->sg.count * sizeof(struct aac_hba_sgl);622 623	} else {624		is_native_device = 0;625		aac_fib_init(srbfib);626 627		/* raw_srb FIB is not FastResponseCapable */628		srbfib->hw_fib_va->header.XferState &=629			~cpu_to_le32(FastResponseCapable);630 631		srbcmd = (struct aac_srb *) fib_data(srbfib);632 633		// Fix up srb for endian and force some values634 635		srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this636		srbcmd->channel	 = cpu_to_le32(user_srbcmd->channel);637		srbcmd->id	 = cpu_to_le32(user_srbcmd->id);638		srbcmd->lun	 = cpu_to_le32(user_srbcmd->lun);639		srbcmd->timeout	 = cpu_to_le32(user_srbcmd->timeout);640		srbcmd->flags	 = cpu_to_le32(flags);641		srbcmd->retry_limit = 0; // Obsolete parameter642		srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);643		memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));644	}645 646	byte_count = 0;647	if (is_native_device) {648		struct user_sgmap *usg32 = &user_srbcmd->sg;649		struct user_sgmap64 *usg64 =650			(struct user_sgmap64 *)&user_srbcmd->sg;651 652		for (i = 0; i < usg32->count; i++) {653			void *p;654			u64 addr;655 656			sg_count[i] = (actual_fibsize64 == fibsize) ?657				usg64->sg[i].count : usg32->sg[i].count;658			if (sg_count[i] >659				(dev->scsi_host_ptr->max_sectors << 9)) {660				pr_err("aacraid: upsg->sg[%d].count=%u>%u\n",661					i, sg_count[i],662					dev->scsi_host_ptr->max_sectors << 9);663				rcode = -EINVAL;664				goto cleanup;665			}666 667			p = kmalloc(sg_count[i], GFP_KERNEL);668			if (!p) {669				rcode = -ENOMEM;670				goto cleanup;671			}672 673			if (actual_fibsize64 == fibsize) {674				addr = (u64)usg64->sg[i].addr[0];675				addr += ((u64)usg64->sg[i].addr[1]) << 32;676			} else {677				addr = (u64)usg32->sg[i].addr;678			}679 680			sg_user[i] = (void __user *)(uintptr_t)addr;681			sg_list[i] = p; // save so we can clean up later682			sg_indx = i;683 684			if (flags & SRB_DataOut) {685				if (copy_from_user(p, sg_user[i],686					sg_count[i])) {687					rcode = -EFAULT;688					goto cleanup;689				}690			}691			addr = dma_map_single(&dev->pdev->dev, p, sg_count[i],692					      data_dir);693			hbacmd->sge[i].addr_hi = cpu_to_le32((u32)(addr>>32));694			hbacmd->sge[i].addr_lo = cpu_to_le32(695						(u32)(addr & 0xffffffff));696			hbacmd->sge[i].len = cpu_to_le32(sg_count[i]);697			hbacmd->sge[i].flags = 0;698			byte_count += sg_count[i];699		}700 701		if (usg32->count > 0)	/* embedded sglist */702			hbacmd->sge[usg32->count-1].flags =703				cpu_to_le32(0x40000000);704		hbacmd->data_length = cpu_to_le32(byte_count);705 706		status = aac_hba_send(HBA_IU_TYPE_SCSI_CMD_REQ, srbfib,707					NULL, NULL);708 709	} else if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {710		struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;711		struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;712 713		/*714		 * This should also catch if user used the 32 bit sgmap715		 */716		if (actual_fibsize64 == fibsize) {717			actual_fibsize = actual_fibsize64;718			for (i = 0; i < upsg->count; i++) {719				u64 addr;720				void* p;721 722				sg_count[i] = upsg->sg[i].count;723				if (sg_count[i] >724				    ((dev->adapter_info.options &725				     AAC_OPT_NEW_COMM) ?726				      (dev->scsi_host_ptr->max_sectors << 9) :727				      65536)) {728					rcode = -EINVAL;729					goto cleanup;730				}731 732				p = kmalloc(sg_count[i], GFP_KERNEL);733				if(!p) {734					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",735					  sg_count[i], i, upsg->count));736					rcode = -ENOMEM;737					goto cleanup;738				}739				addr = (u64)upsg->sg[i].addr[0];740				addr += ((u64)upsg->sg[i].addr[1]) << 32;741				sg_user[i] = (void __user *)(uintptr_t)addr;742				sg_list[i] = p; // save so we can clean up later743				sg_indx = i;744 745				if (flags & SRB_DataOut) {746					if (copy_from_user(p, sg_user[i],747						sg_count[i])){748						dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));749						rcode = -EFAULT;750						goto cleanup;751					}752				}753				addr = dma_map_single(&dev->pdev->dev, p,754						      sg_count[i], data_dir);755 756				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);757				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);758				byte_count += sg_count[i];759				psg->sg[i].count = cpu_to_le32(sg_count[i]);760			}761		} else {762			struct user_sgmap* usg;763			usg = kmemdup(upsg,764				      actual_fibsize - sizeof(struct aac_srb)765				      + sizeof(struct sgmap), GFP_KERNEL);766			if (!usg) {767				dprintk((KERN_DEBUG"aacraid: Allocation error in Raw SRB command\n"));768				rcode = -ENOMEM;769				goto cleanup;770			}771			actual_fibsize = actual_fibsize64;772 773			for (i = 0; i < usg->count; i++) {774				u64 addr;775				void* p;776 777				sg_count[i] = usg->sg[i].count;778				if (sg_count[i] >779				    ((dev->adapter_info.options &780				     AAC_OPT_NEW_COMM) ?781				      (dev->scsi_host_ptr->max_sectors << 9) :782				      65536)) {783					kfree(usg);784					rcode = -EINVAL;785					goto cleanup;786				}787 788				p = kmalloc(sg_count[i], GFP_KERNEL);789				if(!p) {790					dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",791						sg_count[i], i, usg->count));792					kfree(usg);793					rcode = -ENOMEM;794					goto cleanup;795				}796				sg_user[i] = (void __user *)(uintptr_t)usg->sg[i].addr;797				sg_list[i] = p; // save so we can clean up later798				sg_indx = i;799 800				if (flags & SRB_DataOut) {801					if (copy_from_user(p, sg_user[i],802						sg_count[i])) {803						kfree (usg);804						dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));805						rcode = -EFAULT;806						goto cleanup;807					}808				}809				addr = dma_map_single(&dev->pdev->dev, p,810						      sg_count[i], data_dir);811 812				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);813				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);814				byte_count += sg_count[i];815				psg->sg[i].count = cpu_to_le32(sg_count[i]);816			}817			kfree (usg);818		}819		srbcmd->count = cpu_to_le32(byte_count);820		if (user_srbcmd->sg.count)821			psg->count = cpu_to_le32(sg_indx+1);822		else823			psg->count = 0;824		status = aac_fib_send(ScsiPortCommand64, srbfib, actual_fibsize, FsaNormal, 1, 1,NULL,NULL);825	} else {826		struct user_sgmap* upsg = &user_srbcmd->sg;827		struct sgmap* psg = &srbcmd->sg;828 829		if (actual_fibsize64 == fibsize) {830			struct user_sgmap64* usg = (struct user_sgmap64 *)upsg;831			for (i = 0; i < upsg->count; i++) {832				uintptr_t addr;833				void* p;834 835				sg_count[i] = usg->sg[i].count;836				if (sg_count[i] >837				    ((dev->adapter_info.options &838				     AAC_OPT_NEW_COMM) ?839				      (dev->scsi_host_ptr->max_sectors << 9) :840				      65536)) {841					rcode = -EINVAL;842					goto cleanup;843				}844				p = kmalloc(sg_count[i], GFP_KERNEL);845				if (!p) {846					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",847						sg_count[i], i, usg->count));848					rcode = -ENOMEM;849					goto cleanup;850				}851				addr = (u64)usg->sg[i].addr[0];852				addr += ((u64)usg->sg[i].addr[1]) << 32;853				sg_user[i] = (void __user *)addr;854				sg_list[i] = p; // save so we can clean up later855				sg_indx = i;856 857				if (flags & SRB_DataOut) {858					if (copy_from_user(p, sg_user[i],859						sg_count[i])){860						dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));861						rcode = -EFAULT;862						goto cleanup;863					}864				}865				addr = dma_map_single(&dev->pdev->dev, p,866						      usg->sg[i].count,867						      data_dir);868 869				psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);870				byte_count += usg->sg[i].count;871				psg->sg[i].count = cpu_to_le32(sg_count[i]);872			}873		} else {874			for (i = 0; i < upsg->count; i++) {875				dma_addr_t addr;876				void* p;877 878				sg_count[i] = upsg->sg[i].count;879				if (sg_count[i] >880				    ((dev->adapter_info.options &881				     AAC_OPT_NEW_COMM) ?882				      (dev->scsi_host_ptr->max_sectors << 9) :883				      65536)) {884					rcode = -EINVAL;885					goto cleanup;886				}887				p = kmalloc(sg_count[i], GFP_KERNEL);888				if (!p) {889					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",890					  sg_count[i], i, upsg->count));891					rcode = -ENOMEM;892					goto cleanup;893				}894				sg_user[i] = (void __user *)(uintptr_t)upsg->sg[i].addr;895				sg_list[i] = p; // save so we can clean up later896				sg_indx = i;897 898				if (flags & SRB_DataOut) {899					if (copy_from_user(p, sg_user[i],900						sg_count[i])) {901						dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));902						rcode = -EFAULT;903						goto cleanup;904					}905				}906				addr = dma_map_single(&dev->pdev->dev, p,907						      sg_count[i], data_dir);908 909				psg->sg[i].addr = cpu_to_le32(addr);910				byte_count += sg_count[i];911				psg->sg[i].count = cpu_to_le32(sg_count[i]);912			}913		}914		srbcmd->count = cpu_to_le32(byte_count);915		if (user_srbcmd->sg.count)916			psg->count = cpu_to_le32(sg_indx+1);917		else918			psg->count = 0;919		status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);920	}921 922	if (status == -ERESTARTSYS) {923		rcode = -ERESTARTSYS;924		goto cleanup;925	}926 927	if (status != 0) {928		dprintk((KERN_DEBUG"aacraid: Could not send raw srb fib to hba\n"));929		rcode = -ENXIO;930		goto cleanup;931	}932 933	if (flags & SRB_DataIn) {934		for(i = 0 ; i <= sg_indx; i++){935			if (copy_to_user(sg_user[i], sg_list[i], sg_count[i])) {936				dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n"));937				rcode = -EFAULT;938				goto cleanup;939 940			}941		}942	}943 944	user_reply = arg + fibsize;945	if (is_native_device) {946		struct aac_hba_resp *err =947			&((struct aac_native_hba *)srbfib->hw_fib_va)->resp.err;948		struct aac_srb_reply reply;949 950		memset(&reply, 0, sizeof(reply));951		reply.status = ST_OK;952		if (srbfib->flags & FIB_CONTEXT_FLAG_FASTRESP) {953			/* fast response */954			reply.srb_status = SRB_STATUS_SUCCESS;955			reply.scsi_status = 0;956			reply.data_xfer_length = byte_count;957			reply.sense_data_size = 0;958			memset(reply.sense_data, 0, AAC_SENSE_BUFFERSIZE);959		} else {960			reply.srb_status = err->service_response;961			reply.scsi_status = err->status;962			reply.data_xfer_length = byte_count -963				le32_to_cpu(err->residual_count);964			reply.sense_data_size = err->sense_response_data_len;965			memcpy(reply.sense_data, err->sense_response_buf,966				AAC_SENSE_BUFFERSIZE);967		}968		if (copy_to_user(user_reply, &reply,969			sizeof(struct aac_srb_reply))) {970			dprintk((KERN_DEBUG"aacraid: Copy to user failed\n"));971			rcode = -EFAULT;972			goto cleanup;973		}974	} else {975		struct aac_srb_reply *reply;976 977		reply = (struct aac_srb_reply *) fib_data(srbfib);978		if (copy_to_user(user_reply, reply,979			sizeof(struct aac_srb_reply))) {980			dprintk((KERN_DEBUG"aacraid: Copy to user failed\n"));981			rcode = -EFAULT;982			goto cleanup;983		}984	}985 986cleanup:987	kfree(user_srbcmd);988	if (rcode != -ERESTARTSYS) {989		for (i = 0; i <= sg_indx; i++)990			kfree(sg_list[i]);991		aac_fib_complete(srbfib);992		aac_fib_free(srbfib);993	}994 995	return rcode;996}997 998struct aac_pci_info {999	u32 bus;1000	u32 slot;1001};1002 1003 1004static int aac_get_pci_info(struct aac_dev* dev, void __user *arg)1005{1006	struct aac_pci_info pci_info;1007 1008	pci_info.bus = dev->pdev->bus->number;1009	pci_info.slot = PCI_SLOT(dev->pdev->devfn);1010 1011	if (copy_to_user(arg, &pci_info, sizeof(struct aac_pci_info))) {1012		dprintk((KERN_DEBUG "aacraid: Could not copy pci info\n"));1013		return -EFAULT;1014	}1015	return 0;1016}1017 1018static int aac_get_hba_info(struct aac_dev *dev, void __user *arg)1019{1020	struct aac_hba_info hbainfo;1021 1022	memset(&hbainfo, 0, sizeof(hbainfo));1023	hbainfo.adapter_number		= (u8) dev->id;1024	hbainfo.system_io_bus_number	= dev->pdev->bus->number;1025	hbainfo.device_number		= (dev->pdev->devfn >> 3);1026	hbainfo.function_number		= (dev->pdev->devfn & 0x0007);1027 1028	hbainfo.vendor_id		= dev->pdev->vendor;1029	hbainfo.device_id		= dev->pdev->device;1030	hbainfo.sub_vendor_id		= dev->pdev->subsystem_vendor;1031	hbainfo.sub_system_id		= dev->pdev->subsystem_device;1032 1033	if (copy_to_user(arg, &hbainfo, sizeof(struct aac_hba_info))) {1034		dprintk((KERN_DEBUG "aacraid: Could not copy hba info\n"));1035		return -EFAULT;1036	}1037 1038	return 0;1039}1040 1041struct aac_reset_iop {1042	u8	reset_type;1043};1044 1045static int aac_send_reset_adapter(struct aac_dev *dev, void __user *arg)1046{1047	struct aac_reset_iop reset;1048	int retval;1049 1050	if (copy_from_user((void *)&reset, arg, sizeof(struct aac_reset_iop)))1051		return -EFAULT;1052 1053	dev->adapter_shutdown = 1;1054 1055	mutex_unlock(&dev->ioctl_mutex);1056	retval = aac_reset_adapter(dev, 0, reset.reset_type);1057	mutex_lock(&dev->ioctl_mutex);1058 1059	return retval;1060}1061 1062int aac_do_ioctl(struct aac_dev *dev, unsigned int cmd, void __user *arg)1063{1064	int status;1065 1066	mutex_lock(&dev->ioctl_mutex);1067 1068	if (dev->adapter_shutdown) {1069		status = -EACCES;1070		goto cleanup;1071	}1072 1073	/*1074	 *	HBA gets first crack1075	 */1076 1077	status = aac_dev_ioctl(dev, cmd, arg);1078	if (status != -ENOTTY)1079		goto cleanup;1080 1081	switch (cmd) {1082	case FSACTL_MINIPORT_REV_CHECK:1083		status = check_revision(dev, arg);1084		break;1085	case FSACTL_SEND_LARGE_FIB:1086	case FSACTL_SENDFIB:1087		status = ioctl_send_fib(dev, arg);1088		break;1089	case FSACTL_OPEN_GET_ADAPTER_FIB:1090		status = open_getadapter_fib(dev, arg);1091		break;1092	case FSACTL_GET_NEXT_ADAPTER_FIB:1093		status = next_getadapter_fib(dev, arg);1094		break;1095	case FSACTL_CLOSE_GET_ADAPTER_FIB:1096		status = close_getadapter_fib(dev, arg);1097		break;1098	case FSACTL_SEND_RAW_SRB:1099		status = aac_send_raw_srb(dev,arg);1100		break;1101	case FSACTL_GET_PCI_INFO:1102		status = aac_get_pci_info(dev,arg);1103		break;1104	case FSACTL_GET_HBA_INFO:1105		status = aac_get_hba_info(dev, arg);1106		break;1107	case FSACTL_RESET_IOP:1108		status = aac_send_reset_adapter(dev, arg);1109		break;1110 1111	default:1112		status = -ENOTTY;1113		break;1114	}1115 1116cleanup:1117	mutex_unlock(&dev->ioctl_mutex);1118 1119	return status;1120}1121 1122