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

Commit 8e0c5ebd authored by Mark Haverkamp's avatar Mark Haverkamp Committed by James Bottomley
Browse files

[SCSI] aacraid: Newer adapter communication iterface support



Received from Mark Salyzyn.

This patch adds the 'new comm' interface, which modern AAC based
adapters that are less than a year old support in the name of much
improved performance. These modern adapters support both the legacy and
the 'new comm' interfaces.

Signed-off-by: default avatarMark Haverkamp <markh@osdl.org>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 38a9a621
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -57,7 +57,7 @@ Deanna Bonds (non-DASD support, PAE fibs and 64 bit,
					(fixed 64bit and 64G memory model, changed confusing naming convention
					 where fibs that go to the hardware are consistently called hw_fibs and
					 not just fibs like the name of the driver tracking structure)
Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas.
Mark Salyzyn <Mark_Salyzyn@adaptec.com> Fixed panic issues and added some new product ids for upcoming hbas. Performance tuning, card failover and bug mitigations.

Original Driver
-------------------------
+0 −1
Original line number Diff line number Diff line
o	Testing
o	More testing
o	Drop irq_mask, basically unused
o	I/O size increase
+7 −16
Original line number Diff line number Diff line
@@ -359,15 +359,6 @@ int aac_get_containers(struct aac_dev *dev)
	return status;
}

static void aac_io_done(struct scsi_cmnd * scsicmd)
{
	unsigned long cpu_flags;
	struct Scsi_Host *host = scsicmd->device->host;
	spin_lock_irqsave(host->host_lock, cpu_flags);
	scsicmd->scsi_done(scsicmd);
	spin_unlock_irqrestore(host->host_lock, cpu_flags);
}

static void aac_internal_transfer(struct scsi_cmnd *scsicmd, void *data, unsigned int offset, unsigned int len)
{
	void *buf;
@@ -424,7 +415,7 @@ static void get_container_name_callback(void *context, struct fib * fibptr)

	fib_complete(fibptr);
	fib_free(fibptr);
	aac_io_done(scsicmd);
	scsicmd->scsi_done(scsicmd);
}

/**
@@ -988,7 +979,7 @@ static void io_callback(void *context, struct fib * fibptr)
	fib_complete(fibptr);
	fib_free(fibptr);

	aac_io_done(scsicmd);
	scsicmd->scsi_done(scsicmd);
}

static int aac_read(struct scsi_cmnd * scsicmd, int cid)
@@ -1167,7 +1158,7 @@ static int aac_read(struct scsi_cmnd * scsicmd, int cid)
	 *	For some reason, the Fib didn't queue, return QUEUE_FULL
	 */
	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
	aac_io_done(scsicmd);
	scsicmd->scsi_done(scsicmd);
	fib_complete(cmd_fibcontext);
	fib_free(cmd_fibcontext);
	return 0;
@@ -1239,7 +1230,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
	 */
	if (!(cmd_fibcontext = fib_alloc(dev))) {
		scsicmd->result = DID_ERROR << 16;
		aac_io_done(scsicmd);
		scsicmd->scsi_done(scsicmd);
		return 0;
	}
	fib_init(cmd_fibcontext);
@@ -1336,7 +1327,7 @@ static int aac_write(struct scsi_cmnd * scsicmd, int cid)
	 *	For some reason, the Fib didn't queue, return QUEUE_FULL
	 */
	scsicmd->result = DID_OK << 16 | COMMAND_COMPLETE << 8 | SAM_STAT_TASK_SET_FULL;
	aac_io_done(scsicmd);
	scsicmd->scsi_done(scsicmd);

	fib_complete(cmd_fibcontext);
	fib_free(cmd_fibcontext);
@@ -1380,7 +1371,7 @@ static void synchronize_callback(void *context, struct fib *fibptr)

	fib_complete(fibptr);
	fib_free(fibptr);
	aac_io_done(cmd);
	cmd->scsi_done(cmd);
}

static int aac_synchronize(struct scsi_cmnd *scsicmd, int cid)
@@ -2097,7 +2088,7 @@ static void aac_srb_callback(void *context, struct fib * fibptr)

	fib_complete(fibptr);
	fib_free(fibptr);
	aac_io_done(scsicmd);
	scsicmd->scsi_done(scsicmd);
}

/**
+18 −7
Original line number Diff line number Diff line
@@ -481,6 +481,7 @@ enum aac_log_level {
#define FSAFS_NTC_FIB_CONTEXT			0x030c

struct aac_dev;
struct fib;

struct adapter_ops
{
@@ -489,6 +490,7 @@ struct adapter_ops
	void (*adapter_disable_int)(struct aac_dev *dev);
	int  (*adapter_sync_cmd)(struct aac_dev *dev, u32 command, u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6, u32 *status, u32 *r1, u32 *r2, u32 *r3, u32 *r4);
	int  (*adapter_check_health)(struct aac_dev *dev);
	int  (*adapter_send)(struct fib * fib);
};

/*
@@ -659,6 +661,10 @@ struct rx_mu_registers {
						Status Register */
	__le32	OIMR;	    /*	1334h  | 34h | Outbound Interrupt 
						Mask Register */
	__le32	reserved2;  /*	1338h  | 38h | Reserved */
	__le32	reserved3;  /*	133Ch  | 3Ch | Reserved */
	__le32	InboundQueue;/*	1340h  | 40h | Inbound Queue Port relative to firmware */
	__le32	OutboundQueue;/*1344h  | 44h | Outbound Queue Port relative to firmware */
			    /* * Must access through ATU Inbound 
			     	 Translation Window */
};
@@ -693,8 +699,8 @@ struct rx_inbound {
#define OutboundDoorbellReg	MUnit.ODR

struct rx_registers {
	struct rx_mu_registers		MUnit;		/* 1300h - 1334h */
	__le32				reserved1[6];	/* 1338h - 134ch */
	struct rx_mu_registers		MUnit;		/* 1300h - 1344h */
	__le32				reserved1[2];	/* 1348h - 134ch */
	struct rx_inbound		IndexRegs;
};

@@ -711,8 +717,8 @@ struct rx_registers {
#define rkt_inbound rx_inbound

struct rkt_registers {
	struct rkt_mu_registers		MUnit;		 /* 1300h - 1334h */
	__le32				reserved1[1010]; /* 1338h - 22fch */
	struct rkt_mu_registers		MUnit;		 /* 1300h - 1344h */
	__le32				reserved1[1006]; /* 1348h - 22fch */
	struct rkt_inbound		IndexRegs;	 /* 2300h - */
};

@@ -721,8 +727,6 @@ struct rkt_registers {
#define rkt_writeb(AEP, CSR, value)	writeb(value, &((AEP)->regs.rkt->CSR))
#define rkt_writel(AEP, CSR, value)	writel(value, &((AEP)->regs.rkt->CSR))

struct fib;

typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);

struct aac_fib_context {
@@ -937,7 +941,6 @@ struct aac_dev
	const char		*name;
	int			id;

	u16			irq_mask;
	/*
	 *	negotiated FIB settings
	 */
@@ -972,6 +975,7 @@ struct aac_dev
	struct adapter_ops	a_ops;
	unsigned long		fsrev;		/* Main driver's revision number */
	
	unsigned		base_size;	/* Size of mapped in region */
	struct aac_init		*init;		/* Holds initialization info to communicate with adapter */
	dma_addr_t		init_pa; 	/* Holds physical address of the init struct */
	
@@ -992,6 +996,9 @@ struct aac_dev
	/*
	 *	The following is the device specific extension.
	 */
#if (!defined(AAC_MIN_FOOTPRINT_SIZE))
#	define AAC_MIN_FOOTPRINT_SIZE 8192
#endif
	union
	{
		struct sa_registers __iomem *sa;
@@ -1012,6 +1019,7 @@ struct aac_dev
	u8			nondasd_support; 
	u8			dac_support;
	u8			raid_scsi_mode;
	u8			new_comm_interface;
	/* macro side-effects BEWARE */
#	define			raw_io_interface \
	  init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
@@ -1034,6 +1042,8 @@ struct aac_dev
#define aac_adapter_check_health(dev) \
	(dev)->a_ops.adapter_check_health(dev)

#define aac_adapter_send(fib) \
	((fib)->dev)->a_ops.adapter_send(fib)

#define FIB_CONTEXT_FLAG_TIMED_OUT		(0x00000001)

@@ -1779,6 +1789,7 @@ int aac_rkt_init(struct aac_dev *dev);
int aac_sa_init(struct aac_dev *dev);
unsigned int aac_response_normal(struct aac_queue * q);
unsigned int aac_command_normal(struct aac_queue * q);
unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
int aac_command_thread(struct aac_dev * dev);
int aac_close_fib_context(struct aac_dev * dev, struct aac_fib_context *fibctx);
int fib_adapter_complete(struct fib * fibptr, unsigned short size);
+25 −0
Original line number Diff line number Diff line
@@ -116,6 +116,10 @@ static int aac_alloc_comm(struct aac_dev *dev, void **commaddr, unsigned long co
	}

	init->InitFlags = 0;
	if (dev->new_comm_interface) {
		init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
		dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
	}
	init->MaxIoCommands = cpu_to_le32(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB);
	init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
	init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
@@ -315,12 +319,33 @@ struct aac_dev *aac_init_adapter(struct aac_dev *dev)
		- sizeof(struct aac_fibhdr)
		- sizeof(struct aac_write) + sizeof(struct sgentry))
			/ sizeof(struct sgentry);
	dev->new_comm_interface = 0;
	dev->raw_io_64 = 0;
	if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
		0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
	 		(status[0] == 0x00000001)) {
		if (status[1] & AAC_OPT_NEW_COMM_64)
			dev->raw_io_64 = 1;
		if (status[1] & AAC_OPT_NEW_COMM)
			dev->new_comm_interface = dev->a_ops.adapter_send != 0;
		if (dev->new_comm_interface && (status[2] > dev->base_size)) {
			iounmap(dev->regs.sa);
			dev->base_size = status[2];
			dprintk((KERN_DEBUG "ioremap(%lx,%d)\n",
			  host->base, status[2]));
			dev->regs.sa = ioremap(host->base, status[2]);
			if (dev->regs.sa == NULL) {
				/* remap failed, go back ... */
				dev->new_comm_interface = 0;
				dev->regs.sa = ioremap(host->base, 
						AAC_MIN_FOOTPRINT_SIZE);
				if (dev->regs.sa == NULL) {	
					printk(KERN_WARNING
					  "aacraid: unable to map adapter.\n");
					return NULL;
				}
			}
		}
	}
	if ((!aac_adapter_sync_cmd(dev, GET_COMM_PREFERRED_SETTINGS,
	  0, 0, 0, 0, 0, 0,
Loading