Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

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