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

Commit 423400e6 authored by Raghava Aditya Renukunta's avatar Raghava Aditya Renukunta Committed by Martin K. Petersen
Browse files

scsi: aacraid: Include HBA direct interface



Added support to send direct pasthru srb commands from management utilty
to the  controller.

Signed-off-by: default avatarRaghava Aditya Renukunta <RaghavaAditya.Renukunta@microsemi.com>
Signed-off-by: default avatarDave Carroll <David.Carroll@microsemi.com>
Reviewed-by: default avatarJohannes Thumshirn <jthumshirn@suse.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 6223a39f
Loading
Loading
Loading
Loading
+162 −13
Original line number Original line Diff line number Diff line
@@ -86,6 +86,7 @@ enum {
#define AAC_MAX_BUSES			5
#define AAC_MAX_BUSES			5
#define AAC_MAX_TARGETS		256
#define AAC_MAX_TARGETS		256
#define AAC_MAX_NATIVE_SIZE		2048
#define AAC_MAX_NATIVE_SIZE		2048
#define FW_ERROR_BUFFER_SIZE		512


/* Thor AIF events */
/* Thor AIF events */
#define SA_AIF_HOTPLUG			(1<<1)
#define SA_AIF_HOTPLUG			(1<<1)
@@ -95,6 +96,141 @@ enum {
#define SA_AIF_BPSTAT_CHANGE		(1<<30)
#define SA_AIF_BPSTAT_CHANGE		(1<<30)
#define SA_AIF_BPCFG_CHANGE		(1<<31)
#define SA_AIF_BPCFG_CHANGE		(1<<31)


#define HBA_MAX_SG_EMBEDDED		28
#define HBA_MAX_SG_SEPARATE		90
#define HBA_SENSE_DATA_LEN_MAX		32
#define HBA_REQUEST_TAG_ERROR_FLAG	0x00000002
#define HBA_SGL_FLAGS_EXT		0x80000000UL

struct aac_hba_sgl {
	u32		addr_lo; /* Lower 32-bits of SGL element address */
	u32		addr_hi; /* Upper 32-bits of SGL element address */
	u32		len;	/* Length of SGL element in bytes */
	u32		flags;	/* SGL element flags */
};

enum {
	HBA_IU_TYPE_SCSI_CMD_REQ		= 0x40,
	HBA_IU_TYPE_SCSI_TM_REQ			= 0x41,
	HBA_IU_TYPE_SATA_REQ			= 0x42,
	HBA_IU_TYPE_RESP			= 0x60,
	HBA_IU_TYPE_COALESCED_RESP		= 0x61,
	HBA_IU_TYPE_INT_COALESCING_CFG_REQ	= 0x70
};

enum {
	HBA_CMD_BYTE1_DATA_DIR_IN		= 0x1,
	HBA_CMD_BYTE1_DATA_DIR_OUT		= 0x2,
	HBA_CMD_BYTE1_DATA_TYPE_DDR		= 0x4,
	HBA_CMD_BYTE1_CRYPTO_ENABLE		= 0x8
};

enum {
	HBA_CMD_BYTE1_BITOFF_DATA_DIR_IN	= 0x0,
	HBA_CMD_BYTE1_BITOFF_DATA_DIR_OUT,
	HBA_CMD_BYTE1_BITOFF_DATA_TYPE_DDR,
	HBA_CMD_BYTE1_BITOFF_CRYPTO_ENABLE
};

enum {
	HBA_RESP_DATAPRES_NO_DATA		= 0x0,
	HBA_RESP_DATAPRES_RESPONSE_DATA,
	HBA_RESP_DATAPRES_SENSE_DATA
};

enum {
	HBA_RESP_SVCRES_TASK_COMPLETE		= 0x0,
	HBA_RESP_SVCRES_FAILURE,
	HBA_RESP_SVCRES_TMF_COMPLETE,
	HBA_RESP_SVCRES_TMF_SUCCEEDED,
	HBA_RESP_SVCRES_TMF_REJECTED,
	HBA_RESP_SVCRES_TMF_LUN_INVALID
};

enum {
	HBA_RESP_STAT_IO_ERROR			= 0x1,
	HBA_RESP_STAT_IO_ABORTED,
	HBA_RESP_STAT_NO_PATH_TO_DEVICE,
	HBA_RESP_STAT_INVALID_DEVICE,
	HBA_RESP_STAT_HBAMODE_DISABLED		= 0xE,
	HBA_RESP_STAT_UNDERRUN			= 0x51,
	HBA_RESP_STAT_OVERRUN			= 0x75
};

struct aac_hba_cmd_req {
	u8	iu_type;	/* HBA information unit type */
	/*
	 * byte1:
	 * [1:0] DIR - 0=No data, 0x1 = IN, 0x2 = OUT
	 * [2]   TYPE - 0=PCI, 1=DDR
	 * [3]   CRYPTO_ENABLE - 0=Crypto disabled, 1=Crypto enabled
	 */
	u8	byte1;
	u8	reply_qid;	/* Host reply queue to post response to */
	u8	reserved1;
	__le32	it_nexus;	/* Device handle for the request */
	__le32	request_id;	/* Sender context */
	/* Lower 32-bits of tweak value for crypto enabled IOs */
	__le32	tweak_value_lo;
	u8	cdb[16];	/* SCSI CDB of the command */
	u8	lun[8];		/* SCSI LUN of the command */

	/* Total data length in bytes to be read/written (if any) */
	__le32	data_length;

	/* [2:0] Task Attribute, [6:3] Command Priority */
	u8	attr_prio;

	/* Number of SGL elements embedded in the HBA req */
	u8	emb_data_desc_count;

	__le16	dek_index;	/* DEK index for crypto enabled IOs */

	/* Lower 32-bits of reserved error data target location on the host */
	__le32	error_ptr_lo;

	/* Upper 32-bits of reserved error data target location on the host */
	__le32	error_ptr_hi;

	/* Length of reserved error data area on the host in bytes */
	__le32	error_length;

	/* Upper 32-bits of tweak value for crypto enabled IOs */
	__le32	tweak_value_hi;

	struct aac_hba_sgl sge[HBA_MAX_SG_SEPARATE+2]; /* SG list space */

	/*
	 * structure must not exceed
	 * AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE
	 */
};

struct aac_hba_resp {
	u8	iu_type;		/* HBA information unit type */
	u8	reserved1[3];
	__le32	request_identifier;	/* sender context */
	__le32	reserved2;
	u8	service_response;	/* SCSI service response */
	u8	status;			/* SCSI status */
	u8	datapres;	/* [1:0] - data present, [7:2] - reserved */
	u8	sense_response_data_len;	/* Sense/response data length */
	__le32	residual_count;		/* Residual data length in bytes */
	/* Sense/response data */
	u8	sense_response_buf[HBA_SENSE_DATA_LEN_MAX];
};

struct aac_native_hba {
	union {
		struct aac_hba_cmd_req cmd;
		u8 cmd_bytes[AAC_MAX_NATIVE_SIZE-FW_ERROR_BUFFER_SIZE];
	} cmd;
	union {
		struct aac_hba_resp err;
		u8 resp_bytes[FW_ERROR_BUFFER_SIZE];
	} resp;
};

#define CISS_REPORT_PHYSICAL_LUNS	0xc3
#define CISS_REPORT_PHYSICAL_LUNS	0xc3
#define WRITE_HOST_WELLNESS		0xa5
#define WRITE_HOST_WELLNESS		0xa5
#define CISS_IDENTIFY_PHYSICAL_DEVICE	0x15
#define CISS_IDENTIFY_PHYSICAL_DEVICE	0x15
@@ -468,10 +604,10 @@ enum aac_queue_types {


/* transport FIB header (PMC) */
/* transport FIB header (PMC) */
struct aac_fib_xporthdr {
struct aac_fib_xporthdr {
	u64	HostAddress;	/* FIB host address w/o xport header */
	__le64	HostAddress;	/* FIB host address w/o xport header */
	u32	Size;		/* FIB size excluding xport header */
	__le32	Size;		/* FIB size excluding xport header */
	u32	Handle;		/* driver handle to reference the FIB */
	__le32	Handle;		/* driver handle to reference the FIB */
	u64	Reserved[2];
	__le64	Reserved[2];
};
};


#define		ALIGN32		32
#define		ALIGN32		32
@@ -978,17 +1114,20 @@ struct src_mu_registers {
	__le32	IQ_L;		/*  c0h | Inbound Queue (Low address) */
	__le32	IQ_L;		/*  c0h | Inbound Queue (Low address) */
	__le32	IQ_H;		/*  c4h | Inbound Queue (High address) */
	__le32	IQ_H;		/*  c4h | Inbound Queue (High address) */
	__le32	ODR_MSI;	/*  c8h | MSI register for sync./AIF */
	__le32	ODR_MSI;	/*  c8h | MSI register for sync./AIF */
	__le32  reserved5;	/*  cch | Reserved */
	__le32	IQN_L;		/*  d0h | Inbound (native cmd) low  */
	__le32	IQN_H;		/*  d4h | Inbound (native cmd) high */
};
};


struct src_registers {
struct src_registers {
	struct src_mu_registers MUnit;	/* 00h - cbh */
	struct src_mu_registers MUnit;	/* 00h - cbh */
	union {
	union {
		struct {
		struct {
			__le32 reserved1[130789];	/* cch - 7fc5fh */
			__le32 reserved1[130786];	/* d8h - 7fc5fh */
			struct src_inbound IndexRegs;	/* 7fc60h */
			struct src_inbound IndexRegs;	/* 7fc60h */
		} tupelo;
		} tupelo;
		struct {
		struct {
			__le32 reserved1[973];		/* cch - fffh */
			__le32 reserved1[970];		/* d8h - fffh */
			struct src_inbound IndexRegs;	/* 1000h */
			struct src_inbound IndexRegs;	/* 1000h */
		} denali;
		} denali;
	} u;
	} u;
@@ -1102,8 +1241,10 @@ struct fib {
	struct list_head	fiblink;
	struct list_head	fiblink;
	void			*data;
	void			*data;
	u32			vector_no;
	u32			vector_no;
	struct hw_fib		*hw_fib_va;		/* Actual shared object */
	struct hw_fib		*hw_fib_va;	/* also used for native */
	dma_addr_t		hw_fib_pa;	/* physical address of hw_fib*/
	dma_addr_t		hw_fib_pa;	/* physical address of hw_fib*/
	dma_addr_t		hw_sgl_pa;	/* extra sgl for native */
	dma_addr_t		hw_error_pa;	/* error buffer for native */
	u32			hbacmd_size;	/* cmd size for native */
	u32			hbacmd_size;	/* cmd size for native */
};
};


@@ -1285,6 +1426,7 @@ struct aac_bus_info_response {
#define AAC_OPT_NEW_COMM		cpu_to_le32(1<<17)
#define AAC_OPT_NEW_COMM		cpu_to_le32(1<<17)
#define AAC_OPT_NEW_COMM_64		cpu_to_le32(1<<18)
#define AAC_OPT_NEW_COMM_64		cpu_to_le32(1<<18)
#define AAC_OPT_EXTENDED		cpu_to_le32(1<<23)
#define AAC_OPT_EXTENDED		cpu_to_le32(1<<23)
#define AAC_OPT_NATIVE_HBA		cpu_to_le32(1<<25)
#define AAC_OPT_NEW_COMM_TYPE1		cpu_to_le32(1<<28)
#define AAC_OPT_NEW_COMM_TYPE1		cpu_to_le32(1<<28)
#define AAC_OPT_NEW_COMM_TYPE2		cpu_to_le32(1<<29)
#define AAC_OPT_NEW_COMM_TYPE2		cpu_to_le32(1<<29)
#define AAC_OPT_NEW_COMM_TYPE3		cpu_to_le32(1<<30)
#define AAC_OPT_NEW_COMM_TYPE3		cpu_to_le32(1<<30)
@@ -1322,8 +1464,8 @@ struct aac_dev
	/*
	/*
	 *	Map for 128 fib objects (64k)
	 *	Map for 128 fib objects (64k)
	 */
	 */
	dma_addr_t		hw_fib_pa;
	dma_addr_t		hw_fib_pa;	/* also used for native cmd */
	struct hw_fib		*hw_fib_va;
	struct hw_fib		*hw_fib_va;	/* also used for native cmd */
	struct hw_fib		*aif_base_va;
	struct hw_fib		*aif_base_va;
	/*
	/*
	 *	Fib Headers
	 *	Fib Headers
@@ -1498,6 +1640,8 @@ struct aac_dev
#define FIB_CONTEXT_FLAG			(0x00000002)
#define FIB_CONTEXT_FLAG			(0x00000002)
#define FIB_CONTEXT_FLAG_WAIT			(0x00000004)
#define FIB_CONTEXT_FLAG_WAIT			(0x00000004)
#define FIB_CONTEXT_FLAG_FASTRESP		(0x00000008)
#define FIB_CONTEXT_FLAG_FASTRESP		(0x00000008)
#define FIB_CONTEXT_FLAG_NATIVE_HBA		(0x00000010)
#define FIB_CONTEXT_FLAG_NATIVE_HBA_TMF	(0x00000020)


/*
/*
 *	Define the command values
 *	Define the command values
@@ -2157,6 +2301,8 @@ struct aac_common
#ifdef DBG
#ifdef DBG
	u32 FibsSent;
	u32 FibsSent;
	u32 FibRecved;
	u32 FibRecved;
	u32 NativeSent;
	u32 NativeRecved;
	u32 NoResponseSent;
	u32 NoResponseSent;
	u32 NoResponseRecved;
	u32 NoResponseRecved;
	u32 AsyncSent;
	u32 AsyncSent;
@@ -2168,7 +2314,6 @@ struct aac_common


extern struct aac_common aac_config;
extern struct aac_common aac_config;



/*
/*
 *	The following macro is used when sending and receiving FIBs. It is
 *	The following macro is used when sending and receiving FIBs. It is
 *	only used for debugging.
 *	only used for debugging.
@@ -2295,9 +2440,10 @@ extern struct aac_common aac_config;


/* PMC NEW COMM: Request the event data */
/* PMC NEW COMM: Request the event data */
#define		AifReqEvent		200
#define		AifReqEvent		200
#define		AifRawDeviceRemove	203	/* RAW device deleted */
#define		AifNativeDeviceAdd	204	/* native HBA device added */
#define		AifNativeDeviceRemove	205	/* native HBA device removed */


/* RAW device deleted */
#define		AifRawDeviceRemove	203


/*
/*
 *	Adapter Initiated FIB command structures. Start with the adapter
 *	Adapter Initiated FIB command structures. Start with the adapter
@@ -2342,9 +2488,12 @@ void aac_fib_free(struct fib * context);
void aac_fib_init(struct fib * context);
void aac_fib_init(struct fib * context);
void aac_printf(struct aac_dev *dev, u32 val);
void aac_printf(struct aac_dev *dev, u32 val);
int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_fib_send(u16 command, struct fib * context, unsigned long size, int priority, int wait, int reply, fib_callback callback, void *ctxt);
int aac_hba_send(u8 command, struct fib *context,
		fib_callback callback, void *ctxt);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
int aac_consumer_get(struct aac_dev * dev, struct aac_queue * q, struct aac_entry **entry);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
void aac_consumer_free(struct aac_dev * dev, struct aac_queue * q, u32 qnum);
int aac_fib_complete(struct fib * context);
int aac_fib_complete(struct fib * context);
void aac_hba_callback(void *context, struct fib *fibptr);
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data)
#define fib_data(fibctx) ((void *)(fibctx)->hw_fib_va->data)
struct aac_dev *aac_init_adapter(struct aac_dev *dev);
struct aac_dev *aac_init_adapter(struct aac_dev *dev);
void aac_src_access_devreg(struct aac_dev *dev, int mode);
void aac_src_access_devreg(struct aac_dev *dev, int mode);
+224 −70
Original line number Original line Diff line number Diff line
@@ -477,20 +477,24 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
	struct fib* srbfib;
	struct fib* srbfib;
	int status;
	int status;
	struct aac_srb *srbcmd = NULL;
	struct aac_srb *srbcmd = NULL;
	struct aac_hba_cmd_req *hbacmd = NULL;
	struct user_aac_srb *user_srbcmd = NULL;
	struct user_aac_srb *user_srbcmd = NULL;
	struct user_aac_srb __user *user_srb = arg;
	struct user_aac_srb __user *user_srb = arg;
	struct aac_srb_reply __user *user_reply;
	struct aac_srb_reply __user *user_reply;
	struct aac_srb_reply* reply;
	u32 chn;
	u32 fibsize = 0;
	u32 fibsize = 0;
	u32 flags = 0;
	u32 flags = 0;
	s32 rcode = 0;
	s32 rcode = 0;
	u32 data_dir;
	u32 data_dir;
	void __user *sg_user[32];
	void __user *sg_user[HBA_MAX_SG_EMBEDDED];
	void *sg_list[32];
	void *sg_list[HBA_MAX_SG_EMBEDDED];
	u32 sg_count[HBA_MAX_SG_EMBEDDED];
	u32 sg_indx = 0;
	u32 sg_indx = 0;
	u32 byte_count = 0;
	u32 byte_count = 0;
	u32 actual_fibsize64, actual_fibsize = 0;
	u32 actual_fibsize64, actual_fibsize = 0;
	int i;
	int i;
	int is_native_device;
	u64 address;




	if (dev->in_reset) {
	if (dev->in_reset) {
@@ -507,11 +511,6 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
	if (!(srbfib = aac_fib_alloc(dev))) {
	if (!(srbfib = aac_fib_alloc(dev))) {
		return -ENOMEM;
		return -ENOMEM;
	}
	}
	aac_fib_init(srbfib);
	/* raw_srb FIB is not FastResponseCapable */
	srbfib->hw_fib_va->header.XferState &= ~cpu_to_le32(FastResponseCapable);

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


	memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
	memset(sg_list, 0, sizeof(sg_list)); /* cleanup may take issue */
	if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
	if(copy_from_user(&fibsize, &user_srb->count,sizeof(u32))){
@@ -538,21 +537,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
		goto cleanup;
		goto cleanup;
	}
	}


	user_reply = arg+fibsize;

	flags = user_srbcmd->flags; /* from user in cpu order */
	flags = user_srbcmd->flags; /* from user in cpu order */
	// Fix up srb for endian and force some values

	srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi);	// Force this
	srbcmd->channel	 = cpu_to_le32(user_srbcmd->channel);
	srbcmd->id	 = cpu_to_le32(user_srbcmd->id);
	srbcmd->lun	 = cpu_to_le32(user_srbcmd->lun);
	srbcmd->timeout	 = cpu_to_le32(user_srbcmd->timeout);
	srbcmd->flags	 = cpu_to_le32(flags);
	srbcmd->retry_limit = 0; // Obsolete parameter
	srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
	memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));

	switch (flags & (SRB_DataIn | SRB_DataOut)) {
	switch (flags & (SRB_DataIn | SRB_DataOut)) {
	case SRB_DataOut:
	case SRB_DataOut:
		data_dir = DMA_TO_DEVICE;
		data_dir = DMA_TO_DEVICE;
@@ -568,7 +553,12 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
	}
	}
	if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) {
	if (user_srbcmd->sg.count > ARRAY_SIZE(sg_list)) {
		dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
		dprintk((KERN_DEBUG"aacraid: too many sg entries %d\n",
		  le32_to_cpu(srbcmd->sg.count)));
			user_srbcmd->sg.count));
		rcode = -EINVAL;
		goto cleanup;
	}
	if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {
		dprintk((KERN_DEBUG"aacraid:SG with no direction specified\n"));
		rcode = -EINVAL;
		rcode = -EINVAL;
		goto cleanup;
		goto cleanup;
	}
	}
@@ -588,13 +578,136 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
		rcode = -EINVAL;
		rcode = -EINVAL;
		goto cleanup;
		goto cleanup;
	}
	}
	if ((data_dir == DMA_NONE) && user_srbcmd->sg.count) {

		dprintk((KERN_DEBUG"aacraid: SG with no direction specified in Raw SRB command\n"));
	chn = aac_logical_to_phys(user_srbcmd->channel);
	if (chn < AAC_MAX_BUSES && user_srbcmd->id < AAC_MAX_TARGETS &&
		dev->hba_map[chn][user_srbcmd->id].devtype ==
		AAC_DEVTYPE_NATIVE_RAW) {
		is_native_device = 1;
		hbacmd = (struct aac_hba_cmd_req *)srbfib->hw_fib_va;
		memset(hbacmd, 0, 96);	/* sizeof(*hbacmd) is not necessary */

		/* iu_type is a parameter of aac_hba_send */
		switch (data_dir) {
		case DMA_TO_DEVICE:
			hbacmd->byte1 = 2;
			break;
		case DMA_FROM_DEVICE:
		case DMA_BIDIRECTIONAL:
			hbacmd->byte1 = 1;
			break;
		case DMA_NONE:
		default:
			break;
		}
		hbacmd->lun[1] = cpu_to_le32(user_srbcmd->lun);
		hbacmd->it_nexus = dev->hba_map[chn][user_srbcmd->id].rmw_nexus;

		/*
		 * we fill in reply_qid later in aac_src_deliver_message
		 * we fill in iu_type, request_id later in aac_hba_send
		 * we fill in emb_data_desc_count, data_length later
		 * in sg list build
		 */

		memcpy(hbacmd->cdb, user_srbcmd->cdb, sizeof(hbacmd->cdb));

		address = (u64)srbfib->hw_error_pa;
		hbacmd->error_ptr_hi = cpu_to_le32((u32)(address >> 32));
		hbacmd->error_ptr_lo = cpu_to_le32((u32)(address & 0xffffffff));
		hbacmd->error_length = cpu_to_le32(FW_ERROR_BUFFER_SIZE);
		hbacmd->emb_data_desc_count =
					cpu_to_le32(user_srbcmd->sg.count);
		srbfib->hbacmd_size = 64 +
			user_srbcmd->sg.count * sizeof(struct aac_hba_sgl);

	} else {
		is_native_device = 0;
		aac_fib_init(srbfib);

		/* raw_srb FIB is not FastResponseCapable */
		srbfib->hw_fib_va->header.XferState &=
			~cpu_to_le32(FastResponseCapable);

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

		// Fix up srb for endian and force some values

		srbcmd->function = cpu_to_le32(SRBF_ExecuteScsi); // Force this
		srbcmd->channel	 = cpu_to_le32(user_srbcmd->channel);
		srbcmd->id	 = cpu_to_le32(user_srbcmd->id);
		srbcmd->lun	 = cpu_to_le32(user_srbcmd->lun);
		srbcmd->timeout	 = cpu_to_le32(user_srbcmd->timeout);
		srbcmd->flags	 = cpu_to_le32(flags);
		srbcmd->retry_limit = 0; // Obsolete parameter
		srbcmd->cdb_size = cpu_to_le32(user_srbcmd->cdb_size);
		memcpy(srbcmd->cdb, user_srbcmd->cdb, sizeof(srbcmd->cdb));
	}

	byte_count = 0;
	if (is_native_device) {
		struct user_sgmap *usg32 = &user_srbcmd->sg;
		struct user_sgmap64 *usg64 =
			(struct user_sgmap64 *)&user_srbcmd->sg;

		for (i = 0; i < usg32->count; i++) {
			void *p;
			u64 addr;

			sg_count[i] = (actual_fibsize64 == fibsize) ?
				usg64->sg[i].count : usg32->sg[i].count;
			if (sg_count[i] >
				(dev->scsi_host_ptr->max_sectors << 9)) {
				pr_err("aacraid: upsg->sg[%d].count=%u>%u\n",
					i, sg_count[i],
					dev->scsi_host_ptr->max_sectors << 9);
				rcode = -EINVAL;
				rcode = -EINVAL;
				goto cleanup;
				goto cleanup;
			}
			}
	byte_count = 0;

	if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
			p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
			if (!p) {
				rcode = -ENOMEM;
				goto cleanup;
			}

			if (actual_fibsize64 == fibsize) {
				addr = (u64)usg64->sg[i].addr[0];
				addr += ((u64)usg64->sg[i].addr[1]) << 32;
			} else {
				addr = (u64)usg32->sg[i].addr;
			}

			sg_user[i] = (void __user *)(uintptr_t)addr;
			sg_list[i] = p; // save so we can clean up later
			sg_indx = i;

			if (flags & SRB_DataOut) {
				if (copy_from_user(p, sg_user[i],
					sg_count[i])) {
					rcode = -EFAULT;
					goto cleanup;
				}
			}
			addr = pci_map_single(dev->pdev, p, sg_count[i],
						data_dir);
			hbacmd->sge[i].addr_hi = cpu_to_le32((u32)(addr>>32));
			hbacmd->sge[i].addr_lo = cpu_to_le32(
						(u32)(addr & 0xffffffff));
			hbacmd->sge[i].len = cpu_to_le32(sg_count[i]);
			hbacmd->sge[i].flags = 0;
			byte_count += sg_count[i];
		}

		if (usg32->count > 0)	/* embedded sglist */
			hbacmd->sge[usg32->count-1].flags =
				cpu_to_le32(0x40000000);
		hbacmd->data_length = cpu_to_le32(byte_count);

		status = aac_hba_send(HBA_IU_TYPE_SCSI_CMD_REQ, srbfib,
					NULL, NULL);

	} else if (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64) {
		struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
		struct user_sgmap64* upsg = (struct user_sgmap64*)&user_srbcmd->sg;
		struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;
		struct sgmap64* psg = (struct sgmap64*)&srbcmd->sg;


@@ -606,7 +719,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
			for (i = 0; i < upsg->count; i++) {
			for (i = 0; i < upsg->count; i++) {
				u64 addr;
				u64 addr;
				void* p;
				void* p;
				if (upsg->sg[i].count >

				sg_count[i] = upsg->sg[i].count;
				if (sg_count[i] >
				    ((dev->adapter_info.options &
				    ((dev->adapter_info.options &
				     AAC_OPT_NEW_COMM) ?
				     AAC_OPT_NEW_COMM) ?
				      (dev->scsi_host_ptr->max_sectors << 9) :
				      (dev->scsi_host_ptr->max_sectors << 9) :
@@ -615,10 +730,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
					goto cleanup;
					goto cleanup;
				}
				}
				/* Does this really need to be GFP_DMA? */
				/* Does this really need to be GFP_DMA? */
				p = kmalloc(upsg->sg[i].count,GFP_KERNEL|__GFP_DMA);
				p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
				if(!p) {
				if(!p) {
					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					  upsg->sg[i].count,i,upsg->count));
					  sg_count[i], i, upsg->count));
					rcode = -ENOMEM;
					rcode = -ENOMEM;
					goto cleanup;
					goto cleanup;
				}
				}
@@ -629,18 +744,20 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
				sg_indx = i;
				sg_indx = i;


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


				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
				byte_count += upsg->sg[i].count;
				byte_count += sg_count[i];
				psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
				psg->sg[i].count = cpu_to_le32(sg_count[i]);
			}
			}
		} else {
		} else {
			struct user_sgmap* usg;
			struct user_sgmap* usg;
@@ -657,7 +774,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
			for (i = 0; i < usg->count; i++) {
			for (i = 0; i < usg->count; i++) {
				u64 addr;
				u64 addr;
				void* p;
				void* p;
				if (usg->sg[i].count >

				sg_count[i] = usg->sg[i].count;
				if (sg_count[i] >
				    ((dev->adapter_info.options &
				    ((dev->adapter_info.options &
				     AAC_OPT_NEW_COMM) ?
				     AAC_OPT_NEW_COMM) ?
				      (dev->scsi_host_ptr->max_sectors << 9) :
				      (dev->scsi_host_ptr->max_sectors << 9) :
@@ -667,10 +786,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
					goto cleanup;
					goto cleanup;
				}
				}
				/* Does this really need to be GFP_DMA? */
				/* Does this really need to be GFP_DMA? */
				p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
				p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
				if(!p) {
				if(!p) {
					dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					dprintk((KERN_DEBUG "aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					  usg->sg[i].count,i,usg->count));
						sg_count[i], i, usg->count));
					kfree(usg);
					kfree(usg);
					rcode = -ENOMEM;
					rcode = -ENOMEM;
					goto cleanup;
					goto cleanup;
@@ -680,19 +799,21 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
				sg_indx = i;
				sg_indx = i;


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


				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
				psg->sg[i].addr[0] = cpu_to_le32(addr & 0xffffffff);
				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
				psg->sg[i].addr[1] = cpu_to_le32(addr>>32);
				byte_count += usg->sg[i].count;
				byte_count += sg_count[i];
				psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
				psg->sg[i].count = cpu_to_le32(sg_count[i]);
			}
			}
			kfree (usg);
			kfree (usg);
		}
		}
@@ -711,7 +832,9 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
			for (i = 0; i < upsg->count; i++) {
			for (i = 0; i < upsg->count; i++) {
				uintptr_t addr;
				uintptr_t addr;
				void* p;
				void* p;
				if (usg->sg[i].count >

				sg_count[i] = usg->sg[i].count;
				if (sg_count[i] >
				    ((dev->adapter_info.options &
				    ((dev->adapter_info.options &
				     AAC_OPT_NEW_COMM) ?
				     AAC_OPT_NEW_COMM) ?
				      (dev->scsi_host_ptr->max_sectors << 9) :
				      (dev->scsi_host_ptr->max_sectors << 9) :
@@ -720,10 +843,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
					goto cleanup;
					goto cleanup;
				}
				}
				/* Does this really need to be GFP_DMA? */
				/* Does this really need to be GFP_DMA? */
				p = kmalloc(usg->sg[i].count,GFP_KERNEL|__GFP_DMA);
				p = kmalloc(sg_count[i], GFP_KERNEL|__GFP_DMA);
				if (!p) {
				if (!p) {
					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					  usg->sg[i].count,i,usg->count));
						sg_count[i], i, usg->count));
					rcode = -ENOMEM;
					rcode = -ENOMEM;
					goto cleanup;
					goto cleanup;
				}
				}
@@ -734,7 +857,8 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
				sg_indx = i;
				sg_indx = i;


				if (flags & SRB_DataOut) {
				if (flags & SRB_DataOut) {
					if(copy_from_user(p,sg_user[i],usg->sg[i].count)){
					if (copy_from_user(p, sg_user[i],
						sg_count[i])){
						dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
						dprintk((KERN_DEBUG"aacraid: Could not copy sg data from user\n"));
						rcode = -EFAULT;
						rcode = -EFAULT;
						goto cleanup;
						goto cleanup;
@@ -744,13 +868,15 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)


				psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
				psg->sg[i].addr = cpu_to_le32(addr & 0xffffffff);
				byte_count += usg->sg[i].count;
				byte_count += usg->sg[i].count;
				psg->sg[i].count = cpu_to_le32(usg->sg[i].count);
				psg->sg[i].count = cpu_to_le32(sg_count[i]);
			}
			}
		} else {
		} else {
			for (i = 0; i < upsg->count; i++) {
			for (i = 0; i < upsg->count; i++) {
				dma_addr_t addr;
				dma_addr_t addr;
				void* p;
				void* p;
				if (upsg->sg[i].count >

				sg_count[i] = upsg->sg[i].count;
				if (sg_count[i] >
				    ((dev->adapter_info.options &
				    ((dev->adapter_info.options &
				     AAC_OPT_NEW_COMM) ?
				     AAC_OPT_NEW_COMM) ?
				      (dev->scsi_host_ptr->max_sectors << 9) :
				      (dev->scsi_host_ptr->max_sectors << 9) :
@@ -758,10 +884,10 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
					rcode = -EINVAL;
					rcode = -EINVAL;
					goto cleanup;
					goto cleanup;
				}
				}
				p = kmalloc(upsg->sg[i].count, GFP_KERNEL);
				p = kmalloc(sg_count[i], GFP_KERNEL);
				if (!p) {
				if (!p) {
					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					dprintk((KERN_DEBUG"aacraid: Could not allocate SG buffer - size = %d buffer number %d of %d\n",
					  upsg->sg[i].count, i, upsg->count));
					  sg_count[i], i, upsg->count));
					rcode = -ENOMEM;
					rcode = -ENOMEM;
					goto cleanup;
					goto cleanup;
				}
				}
@@ -771,18 +897,18 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)


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


				psg->sg[i].addr = cpu_to_le32(addr);
				psg->sg[i].addr = cpu_to_le32(addr);
				byte_count += upsg->sg[i].count;
				byte_count += sg_count[i];
				psg->sg[i].count = cpu_to_le32(upsg->sg[i].count);
				psg->sg[i].count = cpu_to_le32(sg_count[i]);
			}
			}
		}
		}
		srbcmd->count = cpu_to_le32(byte_count);
		srbcmd->count = cpu_to_le32(byte_count);
@@ -792,6 +918,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
			psg->count = 0;
			psg->count = 0;
		status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
		status = aac_fib_send(ScsiPortCommand, srbfib, actual_fibsize, FsaNormal, 1, 1, NULL, NULL);
	}
	}

	if (status == -ERESTARTSYS) {
	if (status == -ERESTARTSYS) {
		rcode = -ERESTARTSYS;
		rcode = -ERESTARTSYS;
		goto cleanup;
		goto cleanup;
@@ -805,11 +932,7 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)


	if (flags & SRB_DataIn) {
	if (flags & SRB_DataIn) {
		for(i = 0 ; i <= sg_indx; i++){
		for(i = 0 ; i <= sg_indx; i++){
			byte_count = le32_to_cpu(
			if (copy_to_user(sg_user[i], sg_list[i], sg_count[i])) {
			  (dev->adapter_info.options & AAC_OPT_SGMAP_HOST64)
			      ? ((struct sgmap64*)&srbcmd->sg)->sg[i].count
			      : srbcmd->sg.sg[i].count);
			if(copy_to_user(sg_user[i], sg_list[i], byte_count)){
				dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n"));
				dprintk((KERN_DEBUG"aacraid: Could not copy sg data to user\n"));
				rcode = -EFAULT;
				rcode = -EFAULT;
				goto cleanup;
				goto cleanup;
@@ -818,19 +941,50 @@ static int aac_send_raw_srb(struct aac_dev* dev, void __user * arg)
		}
		}
	}
	}


	user_reply = arg + fibsize;
	if (is_native_device) {
		struct aac_hba_resp *err =
			&((struct aac_native_hba *)srbfib->hw_fib_va)->resp.err;
		struct aac_srb_reply reply;

		reply.status = ST_OK;
		if (srbfib->flags & FIB_CONTEXT_FLAG_FASTRESP) {
			/* fast response */
			reply.srb_status = SRB_STATUS_SUCCESS;
			reply.scsi_status = 0;
			reply.data_xfer_length = byte_count;
		} else {
			reply.srb_status = err->service_response;
			reply.scsi_status = err->status;
			reply.data_xfer_length = byte_count -
				le32_to_cpu(err->residual_count);
			reply.sense_data_size = err->sense_response_data_len;
			memcpy(reply.sense_data, err->sense_response_buf,
				AAC_SENSE_BUFFERSIZE);
		}
		if (copy_to_user(user_reply, &reply,
			sizeof(struct aac_srb_reply))) {
			dprintk((KERN_DEBUG"aacraid: Copy to user failed\n"));
			rcode = -EFAULT;
			goto cleanup;
		}
	} else {
		struct aac_srb_reply *reply;

		reply = (struct aac_srb_reply *) fib_data(srbfib);
		reply = (struct aac_srb_reply *) fib_data(srbfib);
	if(copy_to_user(user_reply,reply,sizeof(struct aac_srb_reply))){
		if (copy_to_user(user_reply, reply,
		dprintk((KERN_DEBUG"aacraid: Could not copy reply to user\n"));
			sizeof(struct aac_srb_reply))) {
			dprintk((KERN_DEBUG"aacraid: Copy to user failed\n"));
			rcode = -EFAULT;
			rcode = -EFAULT;
			goto cleanup;
			goto cleanup;
		}
		}
	}


cleanup:
cleanup:
	kfree(user_srbcmd);
	kfree(user_srbcmd);
	for(i=0; i <= sg_indx; i++){
		kfree(sg_list[i]);
	}
	if (rcode != -ERESTARTSYS) {
	if (rcode != -ERESTARTSYS) {
		for (i = 0; i <= sg_indx; i++)
			kfree(sg_list[i]);
		aac_fib_complete(srbfib);
		aac_fib_complete(srbfib);
		aac_fib_free(srbfib);
		aac_fib_free(srbfib);
	}
	}
+114 −20

File changed.

Preview size limit exceeded, changes collapsed.

+90 −46

File changed.

Preview size limit exceeded, changes collapsed.

+1 −0
Original line number Original line Diff line number Diff line
@@ -1110,6 +1110,7 @@ static void __aac_shutdown(struct aac_dev * aac)
{
{
	int i;
	int i;


	aac->adapter_shutdown = 1;
	aac_send_shutdown(aac);
	aac_send_shutdown(aac);


	if (aac->aif_thread) {
	if (aac->aif_thread) {
Loading